1 /* 2 * Copyright 2009 Vincent Povirk for CodeWeavers 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 17 */ 18 19 #include "config.h" 20 21 #include <stdarg.h> 22 23 #define COBJMACROS 24 25 #include "windef.h" 26 #include "winbase.h" 27 #include "winreg.h" 28 #include "objbase.h" 29 #include "ocidl.h" 30 #include "initguid.h" 31 32 #include "wincodecs_private.h" 33 34 #include "wine/debug.h" 35 36 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs); 37 38 extern HRESULT WINAPI WIC_DllGetClassObject(REFCLSID, REFIID, LPVOID *) DECLSPEC_HIDDEN; 39 40 typedef struct { 41 REFCLSID classid; 42 class_constructor constructor; 43 } classinfo; 44 45 static const classinfo wic_classes[] = { 46 {&CLSID_WICImagingFactory, ComponentFactory_CreateInstance}, 47 {&CLSID_WICBmpDecoder, BmpDecoder_CreateInstance}, 48 {&CLSID_WICPngDecoder, PngDecoder_CreateInstance}, 49 {&CLSID_WICPngEncoder, PngEncoder_CreateInstance}, 50 {&CLSID_WICBmpEncoder, BmpEncoder_CreateInstance}, 51 {&CLSID_WICGifDecoder, GifDecoder_CreateInstance}, 52 {&CLSID_WICGifEncoder, GifEncoder_CreateInstance}, 53 {&CLSID_WICIcoDecoder, IcoDecoder_CreateInstance}, 54 {&CLSID_WICJpegDecoder, JpegDecoder_CreateInstance}, 55 {&CLSID_WICJpegEncoder, JpegEncoder_CreateInstance}, 56 {&CLSID_WICTiffDecoder, TiffDecoder_CreateInstance}, 57 {&CLSID_WICTiffEncoder, TiffEncoder_CreateInstance}, 58 {&CLSID_WICIcnsEncoder, IcnsEncoder_CreateInstance}, 59 {&CLSID_WICDefaultFormatConverter, FormatConverter_CreateInstance}, 60 {&CLSID_WineTgaDecoder, TgaDecoder_CreateInstance}, 61 {&CLSID_WICUnknownMetadataReader, UnknownMetadataReader_CreateInstance}, 62 {&CLSID_WICIfdMetadataReader, IfdMetadataReader_CreateInstance}, 63 {&CLSID_WICPngChrmMetadataReader, PngChrmReader_CreateInstance}, 64 {&CLSID_WICPngGamaMetadataReader, PngGamaReader_CreateInstance}, 65 {&CLSID_WICPngTextMetadataReader, PngTextReader_CreateInstance}, 66 {&CLSID_WICLSDMetadataReader, LSDReader_CreateInstance}, 67 {&CLSID_WICIMDMetadataReader, IMDReader_CreateInstance}, 68 {&CLSID_WICGCEMetadataReader, GCEReader_CreateInstance}, 69 {&CLSID_WICAPEMetadataReader, APEReader_CreateInstance}, 70 {&CLSID_WICGifCommentMetadataReader, GifCommentReader_CreateInstance}, 71 {0}}; 72 73 typedef struct { 74 IClassFactory IClassFactory_iface; 75 LONG ref; 76 const classinfo *info; 77 } ClassFactoryImpl; 78 79 static inline ClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface) 80 { 81 return CONTAINING_RECORD(iface, ClassFactoryImpl, IClassFactory_iface); 82 } 83 84 static HRESULT WINAPI ClassFactoryImpl_QueryInterface(IClassFactory *iface, 85 REFIID iid, void **ppv) 86 { 87 ClassFactoryImpl *This = impl_from_IClassFactory(iface); 88 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv); 89 90 if (!ppv) return E_INVALIDARG; 91 92 if (IsEqualIID(&IID_IUnknown, iid) || 93 IsEqualIID(&IID_IClassFactory, iid)) 94 { 95 *ppv = &This->IClassFactory_iface; 96 } 97 else 98 { 99 *ppv = NULL; 100 return E_NOINTERFACE; 101 } 102 103 IUnknown_AddRef((IUnknown*)*ppv); 104 return S_OK; 105 } 106 107 static ULONG WINAPI ClassFactoryImpl_AddRef(IClassFactory *iface) 108 { 109 ClassFactoryImpl *This = impl_from_IClassFactory(iface); 110 ULONG ref = InterlockedIncrement(&This->ref); 111 112 TRACE("(%p) refcount=%u\n", iface, ref); 113 114 return ref; 115 } 116 117 static ULONG WINAPI ClassFactoryImpl_Release(IClassFactory *iface) 118 { 119 ClassFactoryImpl *This = impl_from_IClassFactory(iface); 120 ULONG ref = InterlockedDecrement(&This->ref); 121 122 TRACE("(%p) refcount=%u\n", iface, ref); 123 124 if (ref == 0) 125 HeapFree(GetProcessHeap(), 0, This); 126 127 return ref; 128 } 129 130 static HRESULT WINAPI ClassFactoryImpl_CreateInstance(IClassFactory *iface, 131 IUnknown *pUnkOuter, REFIID riid, void **ppv) 132 { 133 ClassFactoryImpl *This = impl_from_IClassFactory(iface); 134 135 *ppv = NULL; 136 137 if (pUnkOuter) return CLASS_E_NOAGGREGATION; 138 139 return This->info->constructor(riid, ppv); 140 } 141 142 static HRESULT WINAPI ClassFactoryImpl_LockServer(IClassFactory *iface, BOOL lock) 143 { 144 TRACE("(%p, %i): stub\n", iface, lock); 145 return E_NOTIMPL; 146 } 147 148 static const IClassFactoryVtbl ClassFactoryImpl_Vtbl = { 149 ClassFactoryImpl_QueryInterface, 150 ClassFactoryImpl_AddRef, 151 ClassFactoryImpl_Release, 152 ClassFactoryImpl_CreateInstance, 153 ClassFactoryImpl_LockServer 154 }; 155 156 static HRESULT ClassFactoryImpl_Constructor(const classinfo *info, REFIID riid, LPVOID *ppv) 157 { 158 ClassFactoryImpl *This; 159 HRESULT ret; 160 161 *ppv = NULL; 162 163 This = HeapAlloc(GetProcessHeap(), 0, sizeof(ClassFactoryImpl)); 164 if (!This) return E_OUTOFMEMORY; 165 166 This->IClassFactory_iface.lpVtbl = &ClassFactoryImpl_Vtbl; 167 This->ref = 1; 168 This->info = info; 169 170 ret = IClassFactory_QueryInterface(&This->IClassFactory_iface, riid, ppv); 171 IClassFactory_Release(&This->IClassFactory_iface); 172 173 return ret; 174 } 175 176 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv) 177 { 178 HRESULT ret; 179 const classinfo *info=NULL; 180 int i; 181 182 TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(iid), ppv); 183 184 if (!rclsid || !iid || !ppv) 185 return E_INVALIDARG; 186 187 *ppv = NULL; 188 189 for (i=0; wic_classes[i].classid; i++) 190 { 191 if (IsEqualCLSID(wic_classes[i].classid, rclsid)) 192 { 193 info = &wic_classes[i]; 194 break; 195 } 196 } 197 198 if (info) 199 ret = ClassFactoryImpl_Constructor(info, iid, ppv); 200 else 201 ret = WIC_DllGetClassObject(rclsid, iid, ppv); 202 203 TRACE("<-- %08X\n", ret); 204 return ret; 205 } 206 207 HRESULT create_instance(CLSID *clsid, const IID *iid, void **ppv) 208 { 209 int i; 210 211 for (i=0; wic_classes[i].classid; i++) 212 if (IsEqualCLSID(wic_classes[i].classid, clsid)) 213 return wic_classes[i].constructor(iid, ppv); 214 215 return CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, iid, ppv); 216 } 217