[WINDOWSCODECS] Sync with Wine Staging 4.0. CORE-15682
[reactos.git] / dll / win32 / windowscodecs / clsfactory.c
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, ImagingFactory_CreateInstance},
47 {&CLSID_WICImagingFactory2, ImagingFactory_CreateInstance},
48 {&CLSID_WICBmpDecoder, BmpDecoder_CreateInstance},
49 {&CLSID_WICPngDecoder, PngDecoder_CreateInstance},
50 {&CLSID_WICPngEncoder, PngEncoder_CreateInstance},
51 {&CLSID_WICBmpEncoder, BmpEncoder_CreateInstance},
52 {&CLSID_WICGifDecoder, GifDecoder_CreateInstance},
53 {&CLSID_WICGifEncoder, GifEncoder_CreateInstance},
54 {&CLSID_WICIcoDecoder, IcoDecoder_CreateInstance},
55 {&CLSID_WICJpegDecoder, JpegDecoder_CreateInstance},
56 {&CLSID_WICJpegEncoder, JpegEncoder_CreateInstance},
57 {&CLSID_WICTiffDecoder, TiffDecoder_CreateInstance},
58 {&CLSID_WICTiffEncoder, TiffEncoder_CreateInstance},
59 {&CLSID_WICIcnsEncoder, IcnsEncoder_CreateInstance},
60 {&CLSID_WICDefaultFormatConverter, FormatConverter_CreateInstance},
61 {&CLSID_WineTgaDecoder, TgaDecoder_CreateInstance},
62 {&CLSID_WICUnknownMetadataReader, UnknownMetadataReader_CreateInstance},
63 {&CLSID_WICIfdMetadataReader, IfdMetadataReader_CreateInstance},
64 {&CLSID_WICPngChrmMetadataReader, PngChrmReader_CreateInstance},
65 {&CLSID_WICPngGamaMetadataReader, PngGamaReader_CreateInstance},
66 {&CLSID_WICPngTextMetadataReader, PngTextReader_CreateInstance},
67 {&CLSID_WICLSDMetadataReader, LSDReader_CreateInstance},
68 {&CLSID_WICIMDMetadataReader, IMDReader_CreateInstance},
69 {&CLSID_WICGCEMetadataReader, GCEReader_CreateInstance},
70 {&CLSID_WICAPEMetadataReader, APEReader_CreateInstance},
71 {&CLSID_WICGifCommentMetadataReader, GifCommentReader_CreateInstance},
72 {0}};
73
74 typedef struct {
75 IClassFactory IClassFactory_iface;
76 LONG ref;
77 const classinfo *info;
78 } ClassFactoryImpl;
79
80 static inline ClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface)
81 {
82 return CONTAINING_RECORD(iface, ClassFactoryImpl, IClassFactory_iface);
83 }
84
85 static HRESULT WINAPI ClassFactoryImpl_QueryInterface(IClassFactory *iface,
86 REFIID iid, void **ppv)
87 {
88 ClassFactoryImpl *This = impl_from_IClassFactory(iface);
89 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
90
91 if (!ppv) return E_INVALIDARG;
92
93 if (IsEqualIID(&IID_IUnknown, iid) ||
94 IsEqualIID(&IID_IClassFactory, iid))
95 {
96 *ppv = &This->IClassFactory_iface;
97 }
98 else
99 {
100 *ppv = NULL;
101 return E_NOINTERFACE;
102 }
103
104 IUnknown_AddRef((IUnknown*)*ppv);
105 return S_OK;
106 }
107
108 static ULONG WINAPI ClassFactoryImpl_AddRef(IClassFactory *iface)
109 {
110 ClassFactoryImpl *This = impl_from_IClassFactory(iface);
111 ULONG ref = InterlockedIncrement(&This->ref);
112
113 TRACE("(%p) refcount=%u\n", iface, ref);
114
115 return ref;
116 }
117
118 static ULONG WINAPI ClassFactoryImpl_Release(IClassFactory *iface)
119 {
120 ClassFactoryImpl *This = impl_from_IClassFactory(iface);
121 ULONG ref = InterlockedDecrement(&This->ref);
122
123 TRACE("(%p) refcount=%u\n", iface, ref);
124
125 if (ref == 0)
126 HeapFree(GetProcessHeap(), 0, This);
127
128 return ref;
129 }
130
131 static HRESULT WINAPI ClassFactoryImpl_CreateInstance(IClassFactory *iface,
132 IUnknown *pUnkOuter, REFIID riid, void **ppv)
133 {
134 ClassFactoryImpl *This = impl_from_IClassFactory(iface);
135
136 *ppv = NULL;
137
138 if (pUnkOuter) return CLASS_E_NOAGGREGATION;
139
140 return This->info->constructor(riid, ppv);
141 }
142
143 static HRESULT WINAPI ClassFactoryImpl_LockServer(IClassFactory *iface, BOOL lock)
144 {
145 TRACE("(%p, %i): stub\n", iface, lock);
146 return E_NOTIMPL;
147 }
148
149 static const IClassFactoryVtbl ClassFactoryImpl_Vtbl = {
150 ClassFactoryImpl_QueryInterface,
151 ClassFactoryImpl_AddRef,
152 ClassFactoryImpl_Release,
153 ClassFactoryImpl_CreateInstance,
154 ClassFactoryImpl_LockServer
155 };
156
157 static HRESULT ClassFactoryImpl_Constructor(const classinfo *info, REFIID riid, LPVOID *ppv)
158 {
159 ClassFactoryImpl *This;
160 HRESULT ret;
161
162 *ppv = NULL;
163
164 This = HeapAlloc(GetProcessHeap(), 0, sizeof(ClassFactoryImpl));
165 if (!This) return E_OUTOFMEMORY;
166
167 This->IClassFactory_iface.lpVtbl = &ClassFactoryImpl_Vtbl;
168 This->ref = 1;
169 This->info = info;
170
171 ret = IClassFactory_QueryInterface(&This->IClassFactory_iface, riid, ppv);
172 IClassFactory_Release(&This->IClassFactory_iface);
173
174 return ret;
175 }
176
177 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv)
178 {
179 HRESULT ret;
180 const classinfo *info=NULL;
181 int i;
182
183 TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(iid), ppv);
184
185 if (!rclsid || !iid || !ppv)
186 return E_INVALIDARG;
187
188 *ppv = NULL;
189
190 for (i=0; wic_classes[i].classid; i++)
191 {
192 if (IsEqualCLSID(wic_classes[i].classid, rclsid))
193 {
194 info = &wic_classes[i];
195 break;
196 }
197 }
198
199 if (info)
200 ret = ClassFactoryImpl_Constructor(info, iid, ppv);
201 else
202 ret = WIC_DllGetClassObject(rclsid, iid, ppv);
203
204 TRACE("<-- %08X\n", ret);
205 return ret;
206 }
207
208 HRESULT create_instance(CLSID *clsid, const IID *iid, void **ppv)
209 {
210 int i;
211
212 for (i=0; wic_classes[i].classid; i++)
213 if (IsEqualCLSID(wic_classes[i].classid, clsid))
214 return wic_classes[i].constructor(iid, ppv);
215
216 return CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, iid, ppv);
217 }