| /* |
| * Copyright 2009 Vincent Povirk for CodeWeavers |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2.1 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA |
| */ |
| |
| #include "config.h" |
| |
| #include <stdarg.h> |
| |
| #define COBJMACROS |
| |
| #include "windef.h" |
| #include "winbase.h" |
| #include "winreg.h" |
| #include "objbase.h" |
| #include "ocidl.h" |
| #include "initguid.h" |
| |
| #include "wincodecs_private.h" |
| |
| #include "wine/debug.h" |
| |
| WINE_DEFAULT_DEBUG_CHANNEL(wincodecs); |
| |
| extern HRESULT WINAPI WIC_DllGetClassObject(REFCLSID, REFIID, LPVOID *) DECLSPEC_HIDDEN; |
| |
| typedef struct { |
| REFCLSID classid; |
| class_constructor constructor; |
| } classinfo; |
| |
| static const classinfo wic_classes[] = { |
| {&CLSID_WICImagingFactory, ComponentFactory_CreateInstance}, |
| {&CLSID_WICBmpDecoder, BmpDecoder_CreateInstance}, |
| {&CLSID_WICPngDecoder, PngDecoder_CreateInstance}, |
| {&CLSID_WICPngEncoder, PngEncoder_CreateInstance}, |
| {&CLSID_WICBmpEncoder, BmpEncoder_CreateInstance}, |
| {&CLSID_WICGifDecoder, GifDecoder_CreateInstance}, |
| {&CLSID_WICIcoDecoder, IcoDecoder_CreateInstance}, |
| {&CLSID_WICJpegDecoder, JpegDecoder_CreateInstance}, |
| {&CLSID_WICJpegEncoder, JpegEncoder_CreateInstance}, |
| {&CLSID_WICTiffDecoder, TiffDecoder_CreateInstance}, |
| {&CLSID_WICTiffEncoder, TiffEncoder_CreateInstance}, |
| {&CLSID_WICIcnsEncoder, IcnsEncoder_CreateInstance}, |
| {&CLSID_WICDefaultFormatConverter, FormatConverter_CreateInstance}, |
| {&CLSID_WineTgaDecoder, TgaDecoder_CreateInstance}, |
| {&CLSID_WICUnknownMetadataReader, UnknownMetadataReader_CreateInstance}, |
| {&CLSID_WICIfdMetadataReader, IfdMetadataReader_CreateInstance}, |
| {&CLSID_WICPngGamaMetadataReader, PngGamaReader_CreateInstance}, |
| {&CLSID_WICPngTextMetadataReader, PngTextReader_CreateInstance}, |
| {&CLSID_WICLSDMetadataReader, LSDReader_CreateInstance}, |
| {&CLSID_WICIMDMetadataReader, IMDReader_CreateInstance}, |
| {&CLSID_WICGCEMetadataReader, GCEReader_CreateInstance}, |
| {&CLSID_WICAPEMetadataReader, APEReader_CreateInstance}, |
| {&CLSID_WICGifCommentMetadataReader, GifCommentReader_CreateInstance}, |
| {0}}; |
| |
| typedef struct { |
| IClassFactory IClassFactory_iface; |
| LONG ref; |
| const classinfo *info; |
| } ClassFactoryImpl; |
| |
| static inline ClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface) |
| { |
| return CONTAINING_RECORD(iface, ClassFactoryImpl, IClassFactory_iface); |
| } |
| |
| static HRESULT WINAPI ClassFactoryImpl_QueryInterface(IClassFactory *iface, |
| REFIID iid, void **ppv) |
| { |
| ClassFactoryImpl *This = impl_from_IClassFactory(iface); |
| TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv); |
| |
| if (!ppv) return E_INVALIDARG; |
| |
| if (IsEqualIID(&IID_IUnknown, iid) || |
| IsEqualIID(&IID_IClassFactory, iid)) |
| { |
| *ppv = &This->IClassFactory_iface; |
| } |
| else |
| { |
| *ppv = NULL; |
| return E_NOINTERFACE; |
| } |
| |
| IUnknown_AddRef((IUnknown*)*ppv); |
| return S_OK; |
| } |
| |
| static ULONG WINAPI ClassFactoryImpl_AddRef(IClassFactory *iface) |
| { |
| ClassFactoryImpl *This = impl_from_IClassFactory(iface); |
| ULONG ref = InterlockedIncrement(&This->ref); |
| |
| TRACE("(%p) refcount=%u\n", iface, ref); |
| |
| return ref; |
| } |
| |
| static ULONG WINAPI ClassFactoryImpl_Release(IClassFactory *iface) |
| { |
| ClassFactoryImpl *This = impl_from_IClassFactory(iface); |
| ULONG ref = InterlockedDecrement(&This->ref); |
| |
| TRACE("(%p) refcount=%u\n", iface, ref); |
| |
| if (ref == 0) |
| HeapFree(GetProcessHeap(), 0, This); |
| |
| return ref; |
| } |
| |
| static HRESULT WINAPI ClassFactoryImpl_CreateInstance(IClassFactory *iface, |
| IUnknown *pUnkOuter, REFIID riid, void **ppv) |
| { |
| ClassFactoryImpl *This = impl_from_IClassFactory(iface); |
| |
| *ppv = NULL; |
| |
| if (pUnkOuter) return CLASS_E_NOAGGREGATION; |
| |
| return This->info->constructor(riid, ppv); |
| } |
| |
| static HRESULT WINAPI ClassFactoryImpl_LockServer(IClassFactory *iface, BOOL lock) |
| { |
| TRACE("(%p, %i): stub\n", iface, lock); |
| return E_NOTIMPL; |
| } |
| |
| static const IClassFactoryVtbl ClassFactoryImpl_Vtbl = { |
| ClassFactoryImpl_QueryInterface, |
| ClassFactoryImpl_AddRef, |
| ClassFactoryImpl_Release, |
| ClassFactoryImpl_CreateInstance, |
| ClassFactoryImpl_LockServer |
| }; |
| |
| static HRESULT ClassFactoryImpl_Constructor(const classinfo *info, REFIID riid, LPVOID *ppv) |
| { |
| ClassFactoryImpl *This; |
| HRESULT ret; |
| |
| *ppv = NULL; |
| |
| This = HeapAlloc(GetProcessHeap(), 0, sizeof(ClassFactoryImpl)); |
| if (!This) return E_OUTOFMEMORY; |
| |
| This->IClassFactory_iface.lpVtbl = &ClassFactoryImpl_Vtbl; |
| This->ref = 1; |
| This->info = info; |
| |
| ret = IClassFactory_QueryInterface(&This->IClassFactory_iface, riid, ppv); |
| IClassFactory_Release(&This->IClassFactory_iface); |
| |
| return ret; |
| } |
| |
| HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv) |
| { |
| HRESULT ret; |
| const classinfo *info=NULL; |
| int i; |
| |
| TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(iid), ppv); |
| |
| if (!rclsid || !iid || !ppv) |
| return E_INVALIDARG; |
| |
| *ppv = NULL; |
| |
| for (i=0; wic_classes[i].classid; i++) |
| { |
| if (IsEqualCLSID(wic_classes[i].classid, rclsid)) |
| { |
| info = &wic_classes[i]; |
| break; |
| } |
| } |
| |
| if (info) |
| ret = ClassFactoryImpl_Constructor(info, iid, ppv); |
| else |
| ret = WIC_DllGetClassObject(rclsid, iid, ppv); |
| |
| TRACE("<-- %08X\n", ret); |
| return ret; |
| } |
| |
| HRESULT create_instance(CLSID *clsid, const IID *iid, void **ppv) |
| { |
| int i; |
| |
| for (i=0; wic_classes[i].classid; i++) |
| if (IsEqualCLSID(wic_classes[i].classid, clsid)) |
| return wic_classes[i].constructor(iid, ppv); |
| |
| return CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, iid, ppv); |
| } |