wbemprox: Implement IEnumWbemClassObject::Clone.
[wine] / dlls / windowscodecs / info.c
1 /*
2  * Copyright 2009 Vincent Povirk for CodeWeavers
3  * Copyright 2012 Dmitry Timoshkov
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18  */
19
20 #include "config.h"
21
22 #include <stdarg.h>
23
24 #define COBJMACROS
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winreg.h"
29 #include "objbase.h"
30 #include "wincodec.h"
31 #include "wincodecsdk.h"
32
33 #include "wincodecs_private.h"
34
35 #include "wine/debug.h"
36 #include "wine/unicode.h"
37 #include "wine/list.h"
38
39 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
40
41 static const WCHAR mimetypes_valuename[] = {'M','i','m','e','T','y','p','e','s',0};
42 static const WCHAR author_valuename[] = {'A','u','t','h','o','r',0};
43 static const WCHAR friendlyname_valuename[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0};
44 static const WCHAR pixelformats_keyname[] = {'P','i','x','e','l','F','o','r','m','a','t','s',0};
45 static const WCHAR containerformat_valuename[] = {'C','o','n','t','a','i','n','e','r','F','o','r','m','a','t',0};
46 static const WCHAR metadataformat_valuename[] = {'M','e','t','a','d','a','t','a','F','o','r','m','a','t',0};
47 static const WCHAR vendor_valuename[] = {'V','e','n','d','o','r',0};
48 static const WCHAR version_valuename[] = {'V','e','r','s','i','o','n',0};
49 static const WCHAR bitsperpixel_valuename[] = {'B','i','t','L','e','n','g','t','h',0};
50 static const WCHAR channelcount_valuename[] = {'C','h','a','n','n','e','l','C','o','u','n','t',0};
51 static const WCHAR channelmasks_keyname[] = {'C','h','a','n','n','e','l','M','a','s','k','s',0};
52 static const WCHAR numericrepresentation_valuename[] = {'N','u','m','e','r','i','c','R','e','p','r','e','s','e','n','t','a','t','i','o','n',0};
53 static const WCHAR supportstransparency_valuename[] = {'S','u','p','p','o','r','t','s','T','r','a','n','s','p','a','r','e','n','c','y',0};
54
55 static HRESULT ComponentInfo_GetStringValue(HKEY classkey, LPCWSTR value,
56     UINT buffer_size, WCHAR *buffer, UINT *actual_size)
57 {
58     LONG ret;
59     DWORD cbdata=buffer_size * sizeof(WCHAR);
60
61     if (!actual_size)
62         return E_INVALIDARG;
63
64     ret = RegGetValueW(classkey, NULL, value, RRF_RT_REG_SZ|RRF_NOEXPAND, NULL,
65         buffer, &cbdata);
66
67     if (ret == ERROR_FILE_NOT_FOUND)
68     {
69         *actual_size = 0;
70         return S_OK;
71     }
72
73     if (ret == 0 || ret == ERROR_MORE_DATA)
74         *actual_size = cbdata/sizeof(WCHAR);
75
76     if (!buffer && buffer_size != 0)
77         /* Yes, native returns the correct size in this case. */
78         return E_INVALIDARG;
79
80     if (ret == ERROR_MORE_DATA)
81         return WINCODEC_ERR_INSUFFICIENTBUFFER;
82
83     return HRESULT_FROM_WIN32(ret);
84 }
85
86 static HRESULT ComponentInfo_GetGUIDValue(HKEY classkey, LPCWSTR value,
87     GUID *result)
88 {
89     LONG ret;
90     WCHAR guid_string[39];
91     DWORD cbdata = sizeof(guid_string);
92     HRESULT hr;
93
94     if (!result)
95         return E_INVALIDARG;
96
97     ret = RegGetValueW(classkey, NULL, value, RRF_RT_REG_SZ|RRF_NOEXPAND, NULL,
98         guid_string, &cbdata);
99
100     if (ret != ERROR_SUCCESS)
101         return HRESULT_FROM_WIN32(ret);
102
103     if (cbdata < sizeof(guid_string))
104     {
105         ERR("incomplete GUID value\n");
106         return E_FAIL;
107     }
108
109     hr = CLSIDFromString(guid_string, result);
110
111     return hr;
112 }
113
114 static HRESULT ComponentInfo_GetDWORDValue(HKEY classkey, LPCWSTR value,
115     DWORD *result)
116 {
117     LONG ret;
118     DWORD cbdata = sizeof(DWORD);
119
120     if (!result)
121         return E_INVALIDARG;
122
123     ret = RegGetValueW(classkey, NULL, value, RRF_RT_DWORD, NULL,
124         result, &cbdata);
125
126     if (ret == ERROR_FILE_NOT_FOUND)
127     {
128         *result = 0;
129         return S_OK;
130     }
131
132     return HRESULT_FROM_WIN32(ret);
133 }
134
135 typedef struct {
136     IWICBitmapDecoderInfo IWICBitmapDecoderInfo_iface;
137     LONG ref;
138     HKEY classkey;
139     CLSID clsid;
140 } BitmapDecoderInfo;
141
142 static inline BitmapDecoderInfo *impl_from_IWICBitmapDecoderInfo(IWICBitmapDecoderInfo *iface)
143 {
144     return CONTAINING_RECORD(iface, BitmapDecoderInfo, IWICBitmapDecoderInfo_iface);
145 }
146
147 static HRESULT WINAPI BitmapDecoderInfo_QueryInterface(IWICBitmapDecoderInfo *iface, REFIID iid,
148     void **ppv)
149 {
150     BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
151     TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
152
153     if (!ppv) return E_INVALIDARG;
154
155     if (IsEqualIID(&IID_IUnknown, iid) ||
156         IsEqualIID(&IID_IWICComponentInfo, iid) ||
157         IsEqualIID(&IID_IWICBitmapCodecInfo, iid) ||
158         IsEqualIID(&IID_IWICBitmapDecoderInfo ,iid))
159     {
160         *ppv = This;
161     }
162     else
163     {
164         *ppv = NULL;
165         return E_NOINTERFACE;
166     }
167
168     IUnknown_AddRef((IUnknown*)*ppv);
169     return S_OK;
170 }
171
172 static ULONG WINAPI BitmapDecoderInfo_AddRef(IWICBitmapDecoderInfo *iface)
173 {
174     BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
175     ULONG ref = InterlockedIncrement(&This->ref);
176
177     TRACE("(%p) refcount=%u\n", iface, ref);
178
179     return ref;
180 }
181
182 static ULONG WINAPI BitmapDecoderInfo_Release(IWICBitmapDecoderInfo *iface)
183 {
184     BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
185     ULONG ref = InterlockedDecrement(&This->ref);
186
187     TRACE("(%p) refcount=%u\n", iface, ref);
188
189     if (ref == 0)
190     {
191         RegCloseKey(This->classkey);
192         HeapFree(GetProcessHeap(), 0, This);
193     }
194
195     return ref;
196 }
197
198 static HRESULT WINAPI BitmapDecoderInfo_GetComponentType(IWICBitmapDecoderInfo *iface,
199     WICComponentType *pType)
200 {
201     TRACE("(%p,%p)\n", iface, pType);
202     if (!pType) return E_INVALIDARG;
203     *pType = WICDecoder;
204     return S_OK;
205 }
206
207 static HRESULT WINAPI BitmapDecoderInfo_GetCLSID(IWICBitmapDecoderInfo *iface, CLSID *pclsid)
208 {
209     BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
210     TRACE("(%p,%p)\n", iface, pclsid);
211
212     if (!pclsid)
213         return E_INVALIDARG;
214
215     memcpy(pclsid, &This->clsid, sizeof(CLSID));
216
217     return S_OK;
218 }
219
220 static HRESULT WINAPI BitmapDecoderInfo_GetSigningStatus(IWICBitmapDecoderInfo *iface, DWORD *pStatus)
221 {
222     FIXME("(%p,%p): stub\n", iface, pStatus);
223     return E_NOTIMPL;
224 }
225
226 static HRESULT WINAPI BitmapDecoderInfo_GetAuthor(IWICBitmapDecoderInfo *iface, UINT cchAuthor,
227     WCHAR *wzAuthor, UINT *pcchActual)
228 {
229     BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
230
231     TRACE("(%p,%u,%p,%p)\n", iface, cchAuthor, wzAuthor, pcchActual);
232
233     return ComponentInfo_GetStringValue(This->classkey, author_valuename,
234         cchAuthor, wzAuthor, pcchActual);
235 }
236
237 static HRESULT WINAPI BitmapDecoderInfo_GetVendorGUID(IWICBitmapDecoderInfo *iface, GUID *pguidVendor)
238 {
239     BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
240
241     TRACE("(%p,%p)\n", iface, pguidVendor);
242
243     return ComponentInfo_GetGUIDValue(This->classkey, vendor_valuename, pguidVendor);
244 }
245
246 static HRESULT WINAPI BitmapDecoderInfo_GetVersion(IWICBitmapDecoderInfo *iface, UINT cchVersion,
247     WCHAR *wzVersion, UINT *pcchActual)
248 {
249     BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
250
251     TRACE("(%p,%u,%p,%p)\n", iface, cchVersion, wzVersion, pcchActual);
252
253     return ComponentInfo_GetStringValue(This->classkey, version_valuename,
254         cchVersion, wzVersion, pcchActual);
255 }
256
257 static HRESULT WINAPI BitmapDecoderInfo_GetSpecVersion(IWICBitmapDecoderInfo *iface, UINT cchSpecVersion,
258     WCHAR *wzSpecVersion, UINT *pcchActual)
259 {
260     FIXME("(%p,%u,%p,%p): stub\n", iface, cchSpecVersion, wzSpecVersion, pcchActual);
261     return E_NOTIMPL;
262 }
263
264 static HRESULT WINAPI BitmapDecoderInfo_GetFriendlyName(IWICBitmapDecoderInfo *iface, UINT cchFriendlyName,
265     WCHAR *wzFriendlyName, UINT *pcchActual)
266 {
267     BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
268
269     TRACE("(%p,%u,%p,%p)\n", iface, cchFriendlyName, wzFriendlyName, pcchActual);
270
271     return ComponentInfo_GetStringValue(This->classkey, friendlyname_valuename,
272         cchFriendlyName, wzFriendlyName, pcchActual);
273 }
274
275 static HRESULT WINAPI BitmapDecoderInfo_GetContainerFormat(IWICBitmapDecoderInfo *iface,
276     GUID *pguidContainerFormat)
277 {
278     BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
279     TRACE("(%p,%p)\n", iface, pguidContainerFormat);
280     return ComponentInfo_GetGUIDValue(This->classkey, containerformat_valuename, pguidContainerFormat);
281 }
282
283 static HRESULT WINAPI BitmapDecoderInfo_GetPixelFormats(IWICBitmapDecoderInfo *iface,
284     UINT cFormats, GUID *pguidPixelFormats, UINT *pcActual)
285 {
286     FIXME("(%p,%u,%p,%p): stub\n", iface, cFormats, pguidPixelFormats, pcActual);
287     return E_NOTIMPL;
288 }
289
290 static HRESULT WINAPI BitmapDecoderInfo_GetColorManagementVersion(IWICBitmapDecoderInfo *iface,
291     UINT cchColorManagementVersion, WCHAR *wzColorManagementVersion, UINT *pcchActual)
292 {
293     FIXME("(%p,%u,%p,%p): stub\n", iface, cchColorManagementVersion, wzColorManagementVersion, pcchActual);
294     return E_NOTIMPL;
295 }
296
297 static HRESULT WINAPI BitmapDecoderInfo_GetDeviceManufacturer(IWICBitmapDecoderInfo *iface,
298     UINT cchDeviceManufacturer, WCHAR *wzDeviceManufacturer, UINT *pcchActual)
299 {
300     FIXME("(%p,%u,%p,%p): stub\n", iface, cchDeviceManufacturer, wzDeviceManufacturer, pcchActual);
301     return E_NOTIMPL;
302 }
303
304 static HRESULT WINAPI BitmapDecoderInfo_GetDeviceModels(IWICBitmapDecoderInfo *iface,
305     UINT cchDeviceModels, WCHAR *wzDeviceModels, UINT *pcchActual)
306 {
307     FIXME("(%p,%u,%p,%p): stub\n", iface, cchDeviceModels, wzDeviceModels, pcchActual);
308     return E_NOTIMPL;
309 }
310
311 static HRESULT WINAPI BitmapDecoderInfo_GetMimeTypes(IWICBitmapDecoderInfo *iface,
312     UINT cchMimeTypes, WCHAR *wzMimeTypes, UINT *pcchActual)
313 {
314     BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
315
316     TRACE("(%p,%u,%p,%p)\n", iface, cchMimeTypes, wzMimeTypes, pcchActual);
317
318     return ComponentInfo_GetStringValue(This->classkey, mimetypes_valuename,
319         cchMimeTypes, wzMimeTypes, pcchActual);
320 }
321
322 static HRESULT WINAPI BitmapDecoderInfo_GetFileExtensions(IWICBitmapDecoderInfo *iface,
323     UINT cchFileExtensions, WCHAR *wzFileExtensions, UINT *pcchActual)
324 {
325     FIXME("(%p,%u,%p,%p): stub\n", iface, cchFileExtensions, wzFileExtensions, pcchActual);
326     return E_NOTIMPL;
327 }
328
329 static HRESULT WINAPI BitmapDecoderInfo_DoesSupportAnimation(IWICBitmapDecoderInfo *iface,
330     BOOL *pfSupportAnimation)
331 {
332     FIXME("(%p,%p): stub\n", iface, pfSupportAnimation);
333     return E_NOTIMPL;
334 }
335
336 static HRESULT WINAPI BitmapDecoderInfo_DoesSupportChromaKey(IWICBitmapDecoderInfo *iface,
337     BOOL *pfSupportChromaKey)
338 {
339     FIXME("(%p,%p): stub\n", iface, pfSupportChromaKey);
340     return E_NOTIMPL;
341 }
342
343 static HRESULT WINAPI BitmapDecoderInfo_DoesSupportLossless(IWICBitmapDecoderInfo *iface,
344     BOOL *pfSupportLossless)
345 {
346     FIXME("(%p,%p): stub\n", iface, pfSupportLossless);
347     return E_NOTIMPL;
348 }
349
350 static HRESULT WINAPI BitmapDecoderInfo_DoesSupportMultiframe(IWICBitmapDecoderInfo *iface,
351     BOOL *pfSupportMultiframe)
352 {
353     FIXME("(%p,%p): stub\n", iface, pfSupportMultiframe);
354     return E_NOTIMPL;
355 }
356
357 static HRESULT WINAPI BitmapDecoderInfo_MatchesMimeType(IWICBitmapDecoderInfo *iface,
358     LPCWSTR wzMimeType, BOOL *pfMatches)
359 {
360     FIXME("(%p,%s,%p): stub\n", iface, debugstr_w(wzMimeType), pfMatches);
361     return E_NOTIMPL;
362 }
363
364 static HRESULT WINAPI BitmapDecoderInfo_GetPatterns(IWICBitmapDecoderInfo *iface,
365     UINT cbSizePatterns, WICBitmapPattern *pPatterns, UINT *pcPatterns, UINT *pcbPatternsActual)
366 {
367     BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
368     UINT pattern_count=0, patterns_size=0;
369     WCHAR subkeyname[11];
370     LONG res;
371     HKEY patternskey, patternkey;
372     static const WCHAR uintformatW[] = {'%','u',0};
373     static const WCHAR patternsW[] = {'P','a','t','t','e','r','n','s',0};
374     static const WCHAR positionW[] = {'P','o','s','i','t','i','o','n',0};
375     static const WCHAR lengthW[] = {'L','e','n','g','t','h',0};
376     static const WCHAR patternW[] = {'P','a','t','t','e','r','n',0};
377     static const WCHAR maskW[] = {'M','a','s','k',0};
378     static const WCHAR endofstreamW[] = {'E','n','d','O','f','S','t','r','e','a','m',0};
379     HRESULT hr=S_OK;
380     UINT i;
381     BYTE *bPatterns=(BYTE*)pPatterns;
382     DWORD length, valuesize;
383
384     TRACE("(%p,%i,%p,%p,%p)\n", iface, cbSizePatterns, pPatterns, pcPatterns, pcbPatternsActual);
385
386     res = RegOpenKeyExW(This->classkey, patternsW, 0, KEY_READ, &patternskey);
387     if (res != ERROR_SUCCESS) return HRESULT_FROM_WIN32(res);
388
389     res = RegQueryInfoKeyW(patternskey, NULL, NULL, NULL, &pattern_count, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
390     if (res == ERROR_SUCCESS)
391     {
392         patterns_size = pattern_count * sizeof(WICBitmapPattern);
393
394         for (i=0; i<pattern_count; i++)
395         {
396             snprintfW(subkeyname, 11, uintformatW, i);
397             res = RegOpenKeyExW(patternskey, subkeyname, 0, KEY_READ, &patternkey);
398             if (res == ERROR_SUCCESS)
399             {
400                 valuesize = sizeof(ULONG);
401                 res = RegGetValueW(patternkey, NULL, lengthW, RRF_RT_DWORD, NULL,
402                     &length, &valuesize);
403                 patterns_size += length*2;
404
405                 if ((cbSizePatterns >= patterns_size) && (res == ERROR_SUCCESS))
406                 {
407                     pPatterns[i].Length = length;
408
409                     pPatterns[i].EndOfStream = 0;
410                     valuesize = sizeof(BOOL);
411                     RegGetValueW(patternkey, NULL, endofstreamW, RRF_RT_DWORD, NULL,
412                         &pPatterns[i].EndOfStream, &valuesize);
413
414                     pPatterns[i].Position.QuadPart = 0;
415                     valuesize = sizeof(ULARGE_INTEGER);
416                     res = RegGetValueW(patternkey, NULL, positionW, RRF_RT_DWORD|RRF_RT_QWORD, NULL,
417                         &pPatterns[i].Position, &valuesize);
418
419                     if (res == ERROR_SUCCESS)
420                     {
421                         pPatterns[i].Pattern = bPatterns+patterns_size-length*2;
422                         valuesize = length;
423                         res = RegGetValueW(patternkey, NULL, patternW, RRF_RT_REG_BINARY, NULL,
424                             pPatterns[i].Pattern, &valuesize);
425                     }
426
427                     if (res == ERROR_SUCCESS)
428                     {
429                         pPatterns[i].Mask = bPatterns+patterns_size-length;
430                         valuesize = length;
431                         res = RegGetValueW(patternkey, NULL, maskW, RRF_RT_REG_BINARY, NULL,
432                             pPatterns[i].Mask, &valuesize);
433                     }
434                 }
435
436                 RegCloseKey(patternkey);
437             }
438             if (res != ERROR_SUCCESS)
439             {
440                 hr = HRESULT_FROM_WIN32(res);
441                 break;
442             }
443         }
444     }
445     else hr = HRESULT_FROM_WIN32(res);
446
447     RegCloseKey(patternskey);
448
449     if (hr == S_OK)
450     {
451         *pcPatterns = pattern_count;
452         *pcbPatternsActual = patterns_size;
453         if (pPatterns && cbSizePatterns < patterns_size)
454             hr = WINCODEC_ERR_INSUFFICIENTBUFFER;
455     }
456
457     return hr;
458 }
459
460 static HRESULT WINAPI BitmapDecoderInfo_MatchesPattern(IWICBitmapDecoderInfo *iface,
461     IStream *pIStream, BOOL *pfMatches)
462 {
463     WICBitmapPattern *patterns;
464     UINT pattern_count=0, patterns_size=0;
465     HRESULT hr;
466     int i, pos;
467     BYTE *data=NULL;
468     ULONG datasize=0;
469     ULONG bytesread;
470     LARGE_INTEGER seekpos;
471
472     TRACE("(%p,%p,%p)\n", iface, pIStream, pfMatches);
473
474     hr = BitmapDecoderInfo_GetPatterns(iface, 0, NULL, &pattern_count, &patterns_size);
475     if (FAILED(hr)) return hr;
476
477     patterns = HeapAlloc(GetProcessHeap(), 0, patterns_size);
478     if (!patterns) return E_OUTOFMEMORY;
479
480     hr = BitmapDecoderInfo_GetPatterns(iface, patterns_size, patterns, &pattern_count, &patterns_size);
481     if (FAILED(hr)) goto end;
482
483     for (i=0; i<pattern_count; i++)
484     {
485         if (datasize < patterns[i].Length)
486         {
487             HeapFree(GetProcessHeap(), 0, data);
488             datasize = patterns[i].Length;
489             data = HeapAlloc(GetProcessHeap(), 0, patterns[i].Length);
490             if (!data)
491             {
492                 hr = E_OUTOFMEMORY;
493                 break;
494             }
495         }
496
497         if (patterns[i].EndOfStream)
498             seekpos.QuadPart = -patterns[i].Position.QuadPart;
499         else
500             seekpos.QuadPart = patterns[i].Position.QuadPart;
501         hr = IStream_Seek(pIStream, seekpos, patterns[i].EndOfStream ? STREAM_SEEK_END : STREAM_SEEK_SET, NULL);
502         if (hr == STG_E_INVALIDFUNCTION) continue; /* before start of stream */
503         if (FAILED(hr)) break;
504
505         hr = IStream_Read(pIStream, data, patterns[i].Length, &bytesread);
506         if (hr == S_FALSE || (hr == S_OK && bytesread != patterns[i].Length)) /* past end of stream */
507             continue;
508         if (FAILED(hr)) break;
509
510         for (pos=0; pos<patterns[i].Length; pos++)
511         {
512             if ((data[pos] & patterns[i].Mask[pos]) != patterns[i].Pattern[pos])
513                 break;
514         }
515         if (pos == patterns[i].Length) /* matches pattern */
516         {
517             hr = S_OK;
518             *pfMatches = TRUE;
519             break;
520         }
521     }
522
523     if (i == pattern_count) /* does not match any pattern */
524     {
525         hr = S_OK;
526         *pfMatches = FALSE;
527     }
528
529 end:
530     HeapFree(GetProcessHeap(), 0, patterns);
531     HeapFree(GetProcessHeap(), 0, data);
532
533     return hr;
534 }
535
536 static HRESULT WINAPI BitmapDecoderInfo_CreateInstance(IWICBitmapDecoderInfo *iface,
537     IWICBitmapDecoder **ppIBitmapDecoder)
538 {
539     BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
540
541     TRACE("(%p,%p)\n", iface, ppIBitmapDecoder);
542
543     return CoCreateInstance(&This->clsid, NULL, CLSCTX_INPROC_SERVER,
544         &IID_IWICBitmapDecoder, (void**)ppIBitmapDecoder);
545 }
546
547 static const IWICBitmapDecoderInfoVtbl BitmapDecoderInfo_Vtbl = {
548     BitmapDecoderInfo_QueryInterface,
549     BitmapDecoderInfo_AddRef,
550     BitmapDecoderInfo_Release,
551     BitmapDecoderInfo_GetComponentType,
552     BitmapDecoderInfo_GetCLSID,
553     BitmapDecoderInfo_GetSigningStatus,
554     BitmapDecoderInfo_GetAuthor,
555     BitmapDecoderInfo_GetVendorGUID,
556     BitmapDecoderInfo_GetVersion,
557     BitmapDecoderInfo_GetSpecVersion,
558     BitmapDecoderInfo_GetFriendlyName,
559     BitmapDecoderInfo_GetContainerFormat,
560     BitmapDecoderInfo_GetPixelFormats,
561     BitmapDecoderInfo_GetColorManagementVersion,
562     BitmapDecoderInfo_GetDeviceManufacturer,
563     BitmapDecoderInfo_GetDeviceModels,
564     BitmapDecoderInfo_GetMimeTypes,
565     BitmapDecoderInfo_GetFileExtensions,
566     BitmapDecoderInfo_DoesSupportAnimation,
567     BitmapDecoderInfo_DoesSupportChromaKey,
568     BitmapDecoderInfo_DoesSupportLossless,
569     BitmapDecoderInfo_DoesSupportMultiframe,
570     BitmapDecoderInfo_MatchesMimeType,
571     BitmapDecoderInfo_GetPatterns,
572     BitmapDecoderInfo_MatchesPattern,
573     BitmapDecoderInfo_CreateInstance
574 };
575
576 static HRESULT BitmapDecoderInfo_Constructor(HKEY classkey, REFCLSID clsid, IWICComponentInfo **ppIInfo)
577 {
578     BitmapDecoderInfo *This;
579
580     This = HeapAlloc(GetProcessHeap(), 0, sizeof(BitmapDecoderInfo));
581     if (!This)
582     {
583         RegCloseKey(classkey);
584         return E_OUTOFMEMORY;
585     }
586
587     This->IWICBitmapDecoderInfo_iface.lpVtbl = &BitmapDecoderInfo_Vtbl;
588     This->ref = 1;
589     This->classkey = classkey;
590     memcpy(&This->clsid, clsid, sizeof(CLSID));
591
592     *ppIInfo = (IWICComponentInfo*)This;
593     return S_OK;
594 }
595
596 typedef struct {
597     IWICBitmapEncoderInfo IWICBitmapEncoderInfo_iface;
598     LONG ref;
599     HKEY classkey;
600     CLSID clsid;
601 } BitmapEncoderInfo;
602
603 static inline BitmapEncoderInfo *impl_from_IWICBitmapEncoderInfo(IWICBitmapEncoderInfo *iface)
604 {
605     return CONTAINING_RECORD(iface, BitmapEncoderInfo, IWICBitmapEncoderInfo_iface);
606 }
607
608 static HRESULT WINAPI BitmapEncoderInfo_QueryInterface(IWICBitmapEncoderInfo *iface, REFIID iid,
609     void **ppv)
610 {
611     BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
612     TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
613
614     if (!ppv) return E_INVALIDARG;
615
616     if (IsEqualIID(&IID_IUnknown, iid) ||
617         IsEqualIID(&IID_IWICComponentInfo, iid) ||
618         IsEqualIID(&IID_IWICBitmapCodecInfo, iid) ||
619         IsEqualIID(&IID_IWICBitmapEncoderInfo ,iid))
620     {
621         *ppv = This;
622     }
623     else
624     {
625         *ppv = NULL;
626         return E_NOINTERFACE;
627     }
628
629     IUnknown_AddRef((IUnknown*)*ppv);
630     return S_OK;
631 }
632
633 static ULONG WINAPI BitmapEncoderInfo_AddRef(IWICBitmapEncoderInfo *iface)
634 {
635     BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
636     ULONG ref = InterlockedIncrement(&This->ref);
637
638     TRACE("(%p) refcount=%u\n", iface, ref);
639
640     return ref;
641 }
642
643 static ULONG WINAPI BitmapEncoderInfo_Release(IWICBitmapEncoderInfo *iface)
644 {
645     BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
646     ULONG ref = InterlockedDecrement(&This->ref);
647
648     TRACE("(%p) refcount=%u\n", iface, ref);
649
650     if (ref == 0)
651     {
652         RegCloseKey(This->classkey);
653         HeapFree(GetProcessHeap(), 0, This);
654     }
655
656     return ref;
657 }
658
659 static HRESULT WINAPI BitmapEncoderInfo_GetComponentType(IWICBitmapEncoderInfo *iface,
660     WICComponentType *pType)
661 {
662     TRACE("(%p,%p)\n", iface, pType);
663     if (!pType) return E_INVALIDARG;
664     *pType = WICEncoder;
665     return S_OK;
666 }
667
668 static HRESULT WINAPI BitmapEncoderInfo_GetCLSID(IWICBitmapEncoderInfo *iface, CLSID *pclsid)
669 {
670     BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
671     TRACE("(%p,%p)\n", iface, pclsid);
672
673     if (!pclsid)
674         return E_INVALIDARG;
675
676     memcpy(pclsid, &This->clsid, sizeof(CLSID));
677
678     return S_OK;
679 }
680
681 static HRESULT WINAPI BitmapEncoderInfo_GetSigningStatus(IWICBitmapEncoderInfo *iface, DWORD *pStatus)
682 {
683     FIXME("(%p,%p): stub\n", iface, pStatus);
684     return E_NOTIMPL;
685 }
686
687 static HRESULT WINAPI BitmapEncoderInfo_GetAuthor(IWICBitmapEncoderInfo *iface, UINT cchAuthor,
688     WCHAR *wzAuthor, UINT *pcchActual)
689 {
690     BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
691
692     TRACE("(%p,%u,%p,%p)\n", iface, cchAuthor, wzAuthor, pcchActual);
693
694     return ComponentInfo_GetStringValue(This->classkey, author_valuename,
695         cchAuthor, wzAuthor, pcchActual);
696 }
697
698 static HRESULT WINAPI BitmapEncoderInfo_GetVendorGUID(IWICBitmapEncoderInfo *iface, GUID *pguidVendor)
699 {
700     BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
701
702     TRACE("(%p,%p)\n", iface, pguidVendor);
703
704     return ComponentInfo_GetGUIDValue(This->classkey, vendor_valuename, pguidVendor);
705 }
706
707 static HRESULT WINAPI BitmapEncoderInfo_GetVersion(IWICBitmapEncoderInfo *iface, UINT cchVersion,
708     WCHAR *wzVersion, UINT *pcchActual)
709 {
710     BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
711
712     TRACE("(%p,%u,%p,%p)\n", iface, cchVersion, wzVersion, pcchActual);
713
714     return ComponentInfo_GetStringValue(This->classkey, version_valuename,
715         cchVersion, wzVersion, pcchActual);
716 }
717
718 static HRESULT WINAPI BitmapEncoderInfo_GetSpecVersion(IWICBitmapEncoderInfo *iface, UINT cchSpecVersion,
719     WCHAR *wzSpecVersion, UINT *pcchActual)
720 {
721     FIXME("(%p,%u,%p,%p): stub\n", iface, cchSpecVersion, wzSpecVersion, pcchActual);
722     return E_NOTIMPL;
723 }
724
725 static HRESULT WINAPI BitmapEncoderInfo_GetFriendlyName(IWICBitmapEncoderInfo *iface, UINT cchFriendlyName,
726     WCHAR *wzFriendlyName, UINT *pcchActual)
727 {
728     BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
729
730     TRACE("(%p,%u,%p,%p)\n", iface, cchFriendlyName, wzFriendlyName, pcchActual);
731
732     return ComponentInfo_GetStringValue(This->classkey, friendlyname_valuename,
733         cchFriendlyName, wzFriendlyName, pcchActual);
734 }
735
736 static HRESULT WINAPI BitmapEncoderInfo_GetContainerFormat(IWICBitmapEncoderInfo *iface,
737     GUID *pguidContainerFormat)
738 {
739     BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
740     TRACE("(%p,%p)\n", iface, pguidContainerFormat);
741     return ComponentInfo_GetGUIDValue(This->classkey, containerformat_valuename, pguidContainerFormat);
742 }
743
744 static HRESULT WINAPI BitmapEncoderInfo_GetPixelFormats(IWICBitmapEncoderInfo *iface,
745     UINT cFormats, GUID *pguidPixelFormats, UINT *pcActual)
746 {
747     FIXME("(%p,%u,%p,%p): stub\n", iface, cFormats, pguidPixelFormats, pcActual);
748     return E_NOTIMPL;
749 }
750
751 static HRESULT WINAPI BitmapEncoderInfo_GetColorManagementVersion(IWICBitmapEncoderInfo *iface,
752     UINT cchColorManagementVersion, WCHAR *wzColorManagementVersion, UINT *pcchActual)
753 {
754     FIXME("(%p,%u,%p,%p): stub\n", iface, cchColorManagementVersion, wzColorManagementVersion, pcchActual);
755     return E_NOTIMPL;
756 }
757
758 static HRESULT WINAPI BitmapEncoderInfo_GetDeviceManufacturer(IWICBitmapEncoderInfo *iface,
759     UINT cchDeviceManufacturer, WCHAR *wzDeviceManufacturer, UINT *pcchActual)
760 {
761     FIXME("(%p,%u,%p,%p): stub\n", iface, cchDeviceManufacturer, wzDeviceManufacturer, pcchActual);
762     return E_NOTIMPL;
763 }
764
765 static HRESULT WINAPI BitmapEncoderInfo_GetDeviceModels(IWICBitmapEncoderInfo *iface,
766     UINT cchDeviceModels, WCHAR *wzDeviceModels, UINT *pcchActual)
767 {
768     FIXME("(%p,%u,%p,%p): stub\n", iface, cchDeviceModels, wzDeviceModels, pcchActual);
769     return E_NOTIMPL;
770 }
771
772 static HRESULT WINAPI BitmapEncoderInfo_GetMimeTypes(IWICBitmapEncoderInfo *iface,
773     UINT cchMimeTypes, WCHAR *wzMimeTypes, UINT *pcchActual)
774 {
775     BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
776
777     TRACE("(%p,%u,%p,%p)\n", iface, cchMimeTypes, wzMimeTypes, pcchActual);
778
779     return ComponentInfo_GetStringValue(This->classkey, mimetypes_valuename,
780         cchMimeTypes, wzMimeTypes, pcchActual);
781 }
782
783 static HRESULT WINAPI BitmapEncoderInfo_GetFileExtensions(IWICBitmapEncoderInfo *iface,
784     UINT cchFileExtensions, WCHAR *wzFileExtensions, UINT *pcchActual)
785 {
786     FIXME("(%p,%u,%p,%p): stub\n", iface, cchFileExtensions, wzFileExtensions, pcchActual);
787     return E_NOTIMPL;
788 }
789
790 static HRESULT WINAPI BitmapEncoderInfo_DoesSupportAnimation(IWICBitmapEncoderInfo *iface,
791     BOOL *pfSupportAnimation)
792 {
793     FIXME("(%p,%p): stub\n", iface, pfSupportAnimation);
794     return E_NOTIMPL;
795 }
796
797 static HRESULT WINAPI BitmapEncoderInfo_DoesSupportChromaKey(IWICBitmapEncoderInfo *iface,
798     BOOL *pfSupportChromaKey)
799 {
800     FIXME("(%p,%p): stub\n", iface, pfSupportChromaKey);
801     return E_NOTIMPL;
802 }
803
804 static HRESULT WINAPI BitmapEncoderInfo_DoesSupportLossless(IWICBitmapEncoderInfo *iface,
805     BOOL *pfSupportLossless)
806 {
807     FIXME("(%p,%p): stub\n", iface, pfSupportLossless);
808     return E_NOTIMPL;
809 }
810
811 static HRESULT WINAPI BitmapEncoderInfo_DoesSupportMultiframe(IWICBitmapEncoderInfo *iface,
812     BOOL *pfSupportMultiframe)
813 {
814     FIXME("(%p,%p): stub\n", iface, pfSupportMultiframe);
815     return E_NOTIMPL;
816 }
817
818 static HRESULT WINAPI BitmapEncoderInfo_MatchesMimeType(IWICBitmapEncoderInfo *iface,
819     LPCWSTR wzMimeType, BOOL *pfMatches)
820 {
821     FIXME("(%p,%s,%p): stub\n", iface, debugstr_w(wzMimeType), pfMatches);
822     return E_NOTIMPL;
823 }
824
825 static HRESULT WINAPI BitmapEncoderInfo_CreateInstance(IWICBitmapEncoderInfo *iface,
826     IWICBitmapEncoder **ppIBitmapEncoder)
827 {
828     BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
829
830     TRACE("(%p,%p)\n", iface, ppIBitmapEncoder);
831
832     return CoCreateInstance(&This->clsid, NULL, CLSCTX_INPROC_SERVER,
833         &IID_IWICBitmapEncoder, (void**)ppIBitmapEncoder);
834 }
835
836 static const IWICBitmapEncoderInfoVtbl BitmapEncoderInfo_Vtbl = {
837     BitmapEncoderInfo_QueryInterface,
838     BitmapEncoderInfo_AddRef,
839     BitmapEncoderInfo_Release,
840     BitmapEncoderInfo_GetComponentType,
841     BitmapEncoderInfo_GetCLSID,
842     BitmapEncoderInfo_GetSigningStatus,
843     BitmapEncoderInfo_GetAuthor,
844     BitmapEncoderInfo_GetVendorGUID,
845     BitmapEncoderInfo_GetVersion,
846     BitmapEncoderInfo_GetSpecVersion,
847     BitmapEncoderInfo_GetFriendlyName,
848     BitmapEncoderInfo_GetContainerFormat,
849     BitmapEncoderInfo_GetPixelFormats,
850     BitmapEncoderInfo_GetColorManagementVersion,
851     BitmapEncoderInfo_GetDeviceManufacturer,
852     BitmapEncoderInfo_GetDeviceModels,
853     BitmapEncoderInfo_GetMimeTypes,
854     BitmapEncoderInfo_GetFileExtensions,
855     BitmapEncoderInfo_DoesSupportAnimation,
856     BitmapEncoderInfo_DoesSupportChromaKey,
857     BitmapEncoderInfo_DoesSupportLossless,
858     BitmapEncoderInfo_DoesSupportMultiframe,
859     BitmapEncoderInfo_MatchesMimeType,
860     BitmapEncoderInfo_CreateInstance
861 };
862
863 static HRESULT BitmapEncoderInfo_Constructor(HKEY classkey, REFCLSID clsid, IWICComponentInfo **ppIInfo)
864 {
865     BitmapEncoderInfo *This;
866
867     This = HeapAlloc(GetProcessHeap(), 0, sizeof(BitmapEncoderInfo));
868     if (!This)
869     {
870         RegCloseKey(classkey);
871         return E_OUTOFMEMORY;
872     }
873
874     This->IWICBitmapEncoderInfo_iface.lpVtbl = &BitmapEncoderInfo_Vtbl;
875     This->ref = 1;
876     This->classkey = classkey;
877     memcpy(&This->clsid, clsid, sizeof(CLSID));
878
879     *ppIInfo = (IWICComponentInfo*)This;
880     return S_OK;
881 }
882
883 typedef struct {
884     IWICFormatConverterInfo IWICFormatConverterInfo_iface;
885     LONG ref;
886     HKEY classkey;
887     CLSID clsid;
888 } FormatConverterInfo;
889
890 static inline FormatConverterInfo *impl_from_IWICFormatConverterInfo(IWICFormatConverterInfo *iface)
891 {
892     return CONTAINING_RECORD(iface, FormatConverterInfo, IWICFormatConverterInfo_iface);
893 }
894
895 static HRESULT WINAPI FormatConverterInfo_QueryInterface(IWICFormatConverterInfo *iface, REFIID iid,
896     void **ppv)
897 {
898     FormatConverterInfo *This = impl_from_IWICFormatConverterInfo(iface);
899     TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
900
901     if (!ppv) return E_INVALIDARG;
902
903     if (IsEqualIID(&IID_IUnknown, iid) ||
904         IsEqualIID(&IID_IWICComponentInfo, iid) ||
905         IsEqualIID(&IID_IWICFormatConverterInfo ,iid))
906     {
907         *ppv = This;
908     }
909     else
910     {
911         *ppv = NULL;
912         return E_NOINTERFACE;
913     }
914
915     IUnknown_AddRef((IUnknown*)*ppv);
916     return S_OK;
917 }
918
919 static ULONG WINAPI FormatConverterInfo_AddRef(IWICFormatConverterInfo *iface)
920 {
921     FormatConverterInfo *This = impl_from_IWICFormatConverterInfo(iface);
922     ULONG ref = InterlockedIncrement(&This->ref);
923
924     TRACE("(%p) refcount=%u\n", iface, ref);
925
926     return ref;
927 }
928
929 static ULONG WINAPI FormatConverterInfo_Release(IWICFormatConverterInfo *iface)
930 {
931     FormatConverterInfo *This = impl_from_IWICFormatConverterInfo(iface);
932     ULONG ref = InterlockedDecrement(&This->ref);
933
934     TRACE("(%p) refcount=%u\n", iface, ref);
935
936     if (ref == 0)
937     {
938         RegCloseKey(This->classkey);
939         HeapFree(GetProcessHeap(), 0, This);
940     }
941
942     return ref;
943 }
944
945 static HRESULT WINAPI FormatConverterInfo_GetComponentType(IWICFormatConverterInfo *iface,
946     WICComponentType *pType)
947 {
948     TRACE("(%p,%p)\n", iface, pType);
949     if (!pType) return E_INVALIDARG;
950     *pType = WICPixelFormatConverter;
951     return S_OK;
952 }
953
954 static HRESULT WINAPI FormatConverterInfo_GetCLSID(IWICFormatConverterInfo *iface, CLSID *pclsid)
955 {
956     FormatConverterInfo *This = impl_from_IWICFormatConverterInfo(iface);
957     TRACE("(%p,%p)\n", iface, pclsid);
958
959     if (!pclsid)
960         return E_INVALIDARG;
961
962     memcpy(pclsid, &This->clsid, sizeof(CLSID));
963
964     return S_OK;
965 }
966
967 static HRESULT WINAPI FormatConverterInfo_GetSigningStatus(IWICFormatConverterInfo *iface, DWORD *pStatus)
968 {
969     FIXME("(%p,%p): stub\n", iface, pStatus);
970     return E_NOTIMPL;
971 }
972
973 static HRESULT WINAPI FormatConverterInfo_GetAuthor(IWICFormatConverterInfo *iface, UINT cchAuthor,
974     WCHAR *wzAuthor, UINT *pcchActual)
975 {
976     FormatConverterInfo *This = impl_from_IWICFormatConverterInfo(iface);
977
978     TRACE("(%p,%u,%p,%p)\n", iface, cchAuthor, wzAuthor, pcchActual);
979
980     return ComponentInfo_GetStringValue(This->classkey, author_valuename,
981         cchAuthor, wzAuthor, pcchActual);
982 }
983
984 static HRESULT WINAPI FormatConverterInfo_GetVendorGUID(IWICFormatConverterInfo *iface, GUID *pguidVendor)
985 {
986     FormatConverterInfo *This = impl_from_IWICFormatConverterInfo(iface);
987
988     TRACE("(%p,%p)\n", iface, pguidVendor);
989
990     return ComponentInfo_GetGUIDValue(This->classkey, vendor_valuename, pguidVendor);
991 }
992
993 static HRESULT WINAPI FormatConverterInfo_GetVersion(IWICFormatConverterInfo *iface, UINT cchVersion,
994     WCHAR *wzVersion, UINT *pcchActual)
995 {
996     FormatConverterInfo *This = impl_from_IWICFormatConverterInfo(iface);
997
998     TRACE("(%p,%u,%p,%p)\n", iface, cchVersion, wzVersion, pcchActual);
999
1000     return ComponentInfo_GetStringValue(This->classkey, version_valuename,
1001         cchVersion, wzVersion, pcchActual);
1002 }
1003
1004 static HRESULT WINAPI FormatConverterInfo_GetSpecVersion(IWICFormatConverterInfo *iface, UINT cchSpecVersion,
1005     WCHAR *wzSpecVersion, UINT *pcchActual)
1006 {
1007     FIXME("(%p,%u,%p,%p): stub\n", iface, cchSpecVersion, wzSpecVersion, pcchActual);
1008     return E_NOTIMPL;
1009 }
1010
1011 static HRESULT WINAPI FormatConverterInfo_GetFriendlyName(IWICFormatConverterInfo *iface, UINT cchFriendlyName,
1012     WCHAR *wzFriendlyName, UINT *pcchActual)
1013 {
1014     FormatConverterInfo *This = impl_from_IWICFormatConverterInfo(iface);
1015
1016     TRACE("(%p,%u,%p,%p)\n", iface, cchFriendlyName, wzFriendlyName, pcchActual);
1017
1018     return ComponentInfo_GetStringValue(This->classkey, friendlyname_valuename,
1019         cchFriendlyName, wzFriendlyName, pcchActual);
1020 }
1021
1022 static HRESULT WINAPI FormatConverterInfo_GetPixelFormats(IWICFormatConverterInfo *iface,
1023     UINT cFormats, GUID *pguidPixelFormats, UINT *pcActual)
1024 {
1025     FIXME("(%p,%u,%p,%p): stub\n", iface, cFormats, pguidPixelFormats, pcActual);
1026     return E_NOTIMPL;
1027 }
1028
1029 static HRESULT WINAPI FormatConverterInfo_CreateInstance(IWICFormatConverterInfo *iface,
1030     IWICFormatConverter **ppIFormatConverter)
1031 {
1032     FormatConverterInfo *This = impl_from_IWICFormatConverterInfo(iface);
1033
1034     TRACE("(%p,%p)\n", iface, ppIFormatConverter);
1035
1036     return CoCreateInstance(&This->clsid, NULL, CLSCTX_INPROC_SERVER,
1037         &IID_IWICFormatConverter, (void**)ppIFormatConverter);
1038 }
1039
1040 static BOOL ConverterSupportsFormat(IWICFormatConverterInfo *iface, const WCHAR *formatguid)
1041 {
1042     LONG res;
1043     FormatConverterInfo *This = impl_from_IWICFormatConverterInfo(iface);
1044     HKEY formats_key, guid_key;
1045
1046     /* Avoid testing using IWICFormatConverter_GetPixelFormats because that
1047         would be O(n). A registry test should do better. */
1048
1049     res = RegOpenKeyExW(This->classkey, pixelformats_keyname, 0, KEY_READ, &formats_key);
1050     if (res != ERROR_SUCCESS) return FALSE;
1051
1052     res = RegOpenKeyExW(formats_key, formatguid, 0, KEY_READ, &guid_key);
1053     if (res == ERROR_SUCCESS) RegCloseKey(guid_key);
1054
1055     RegCloseKey(formats_key);
1056
1057     return (res == ERROR_SUCCESS);
1058 }
1059
1060 static const IWICFormatConverterInfoVtbl FormatConverterInfo_Vtbl = {
1061     FormatConverterInfo_QueryInterface,
1062     FormatConverterInfo_AddRef,
1063     FormatConverterInfo_Release,
1064     FormatConverterInfo_GetComponentType,
1065     FormatConverterInfo_GetCLSID,
1066     FormatConverterInfo_GetSigningStatus,
1067     FormatConverterInfo_GetAuthor,
1068     FormatConverterInfo_GetVendorGUID,
1069     FormatConverterInfo_GetVersion,
1070     FormatConverterInfo_GetSpecVersion,
1071     FormatConverterInfo_GetFriendlyName,
1072     FormatConverterInfo_GetPixelFormats,
1073     FormatConverterInfo_CreateInstance
1074 };
1075
1076 static HRESULT FormatConverterInfo_Constructor(HKEY classkey, REFCLSID clsid, IWICComponentInfo **ppIInfo)
1077 {
1078     FormatConverterInfo *This;
1079
1080     This = HeapAlloc(GetProcessHeap(), 0, sizeof(FormatConverterInfo));
1081     if (!This)
1082     {
1083         RegCloseKey(classkey);
1084         return E_OUTOFMEMORY;
1085     }
1086
1087     This->IWICFormatConverterInfo_iface.lpVtbl = &FormatConverterInfo_Vtbl;
1088     This->ref = 1;
1089     This->classkey = classkey;
1090     memcpy(&This->clsid, clsid, sizeof(CLSID));
1091
1092     *ppIInfo = (IWICComponentInfo*)This;
1093     return S_OK;
1094 }
1095
1096 typedef struct {
1097     IWICPixelFormatInfo2 IWICPixelFormatInfo2_iface;
1098     LONG ref;
1099     HKEY classkey;
1100     CLSID clsid;
1101 } PixelFormatInfo;
1102
1103 static inline PixelFormatInfo *impl_from_IWICPixelFormatInfo2(IWICPixelFormatInfo2 *iface)
1104 {
1105     return CONTAINING_RECORD(iface, PixelFormatInfo, IWICPixelFormatInfo2_iface);
1106 }
1107
1108 static HRESULT WINAPI PixelFormatInfo_QueryInterface(IWICPixelFormatInfo2 *iface, REFIID iid,
1109     void **ppv)
1110 {
1111     PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1112     TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
1113
1114     if (!ppv) return E_INVALIDARG;
1115
1116     if (IsEqualIID(&IID_IUnknown, iid) ||
1117         IsEqualIID(&IID_IWICComponentInfo, iid) ||
1118         IsEqualIID(&IID_IWICPixelFormatInfo, iid) ||
1119         IsEqualIID(&IID_IWICPixelFormatInfo2 ,iid))
1120     {
1121         *ppv = This;
1122     }
1123     else
1124     {
1125         *ppv = NULL;
1126         return E_NOINTERFACE;
1127     }
1128
1129     IUnknown_AddRef((IUnknown*)*ppv);
1130     return S_OK;
1131 }
1132
1133 static ULONG WINAPI PixelFormatInfo_AddRef(IWICPixelFormatInfo2 *iface)
1134 {
1135     PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1136     ULONG ref = InterlockedIncrement(&This->ref);
1137
1138     TRACE("(%p) refcount=%u\n", iface, ref);
1139
1140     return ref;
1141 }
1142
1143 static ULONG WINAPI PixelFormatInfo_Release(IWICPixelFormatInfo2 *iface)
1144 {
1145     PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1146     ULONG ref = InterlockedDecrement(&This->ref);
1147
1148     TRACE("(%p) refcount=%u\n", iface, ref);
1149
1150     if (ref == 0)
1151     {
1152         RegCloseKey(This->classkey);
1153         HeapFree(GetProcessHeap(), 0, This);
1154     }
1155
1156     return ref;
1157 }
1158
1159 static HRESULT WINAPI PixelFormatInfo_GetComponentType(IWICPixelFormatInfo2 *iface,
1160     WICComponentType *pType)
1161 {
1162     TRACE("(%p,%p)\n", iface, pType);
1163     if (!pType) return E_INVALIDARG;
1164     *pType = WICPixelFormat;
1165     return S_OK;
1166 }
1167
1168 static HRESULT WINAPI PixelFormatInfo_GetCLSID(IWICPixelFormatInfo2 *iface, CLSID *pclsid)
1169 {
1170     PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1171     TRACE("(%p,%p)\n", iface, pclsid);
1172
1173     if (!pclsid)
1174         return E_INVALIDARG;
1175
1176     memcpy(pclsid, &This->clsid, sizeof(CLSID));
1177
1178     return S_OK;
1179 }
1180
1181 static HRESULT WINAPI PixelFormatInfo_GetSigningStatus(IWICPixelFormatInfo2 *iface, DWORD *pStatus)
1182 {
1183     TRACE("(%p,%p)\n", iface, pStatus);
1184
1185     if (!pStatus)
1186         return E_INVALIDARG;
1187
1188     /* Pixel formats don't require code, so they are considered signed. */
1189     *pStatus = WICComponentSigned;
1190
1191     return S_OK;
1192 }
1193
1194 static HRESULT WINAPI PixelFormatInfo_GetAuthor(IWICPixelFormatInfo2 *iface, UINT cchAuthor,
1195     WCHAR *wzAuthor, UINT *pcchActual)
1196 {
1197     PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1198
1199     TRACE("(%p,%u,%p,%p)\n", iface, cchAuthor, wzAuthor, pcchActual);
1200
1201     return ComponentInfo_GetStringValue(This->classkey, author_valuename,
1202         cchAuthor, wzAuthor, pcchActual);
1203 }
1204
1205 static HRESULT WINAPI PixelFormatInfo_GetVendorGUID(IWICPixelFormatInfo2 *iface, GUID *pguidVendor)
1206 {
1207     PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1208
1209     TRACE("(%p,%p)\n", iface, pguidVendor);
1210
1211     return ComponentInfo_GetGUIDValue(This->classkey, vendor_valuename, pguidVendor);
1212 }
1213
1214 static HRESULT WINAPI PixelFormatInfo_GetVersion(IWICPixelFormatInfo2 *iface, UINT cchVersion,
1215     WCHAR *wzVersion, UINT *pcchActual)
1216 {
1217     PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1218
1219     TRACE("(%p,%u,%p,%p)\n", iface, cchVersion, wzVersion, pcchActual);
1220
1221     return ComponentInfo_GetStringValue(This->classkey, version_valuename,
1222         cchVersion, wzVersion, pcchActual);
1223 }
1224
1225 static HRESULT WINAPI PixelFormatInfo_GetSpecVersion(IWICPixelFormatInfo2 *iface, UINT cchSpecVersion,
1226     WCHAR *wzSpecVersion, UINT *pcchActual)
1227 {
1228     FIXME("(%p,%u,%p,%p): stub\n", iface, cchSpecVersion, wzSpecVersion, pcchActual);
1229     return E_NOTIMPL;
1230 }
1231
1232 static HRESULT WINAPI PixelFormatInfo_GetFriendlyName(IWICPixelFormatInfo2 *iface, UINT cchFriendlyName,
1233     WCHAR *wzFriendlyName, UINT *pcchActual)
1234 {
1235     PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1236
1237     TRACE("(%p,%u,%p,%p)\n", iface, cchFriendlyName, wzFriendlyName, pcchActual);
1238
1239     return ComponentInfo_GetStringValue(This->classkey, friendlyname_valuename,
1240         cchFriendlyName, wzFriendlyName, pcchActual);
1241 }
1242
1243 static HRESULT WINAPI PixelFormatInfo_GetFormatGUID(IWICPixelFormatInfo2 *iface,
1244     GUID *pFormat)
1245 {
1246     PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1247     TRACE("(%p,%p)\n", iface, pFormat);
1248
1249     if (!pFormat)
1250         return E_INVALIDARG;
1251
1252     *pFormat = This->clsid;
1253
1254     return S_OK;
1255 }
1256
1257 static HRESULT WINAPI PixelFormatInfo_GetColorContext(IWICPixelFormatInfo2 *iface,
1258     IWICColorContext **ppIColorContext)
1259 {
1260     FIXME("(%p,%p): stub\n", iface, ppIColorContext);
1261     return E_NOTIMPL;
1262 }
1263
1264 static HRESULT WINAPI PixelFormatInfo_GetBitsPerPixel(IWICPixelFormatInfo2 *iface,
1265     UINT *puiBitsPerPixel)
1266 {
1267     PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1268
1269     TRACE("(%p,%p)\n", iface, puiBitsPerPixel);
1270
1271     return ComponentInfo_GetDWORDValue(This->classkey, bitsperpixel_valuename, puiBitsPerPixel);
1272 }
1273
1274 static HRESULT WINAPI PixelFormatInfo_GetChannelCount(IWICPixelFormatInfo2 *iface,
1275     UINT *puiChannelCount)
1276 {
1277     PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1278
1279     TRACE("(%p,%p)\n", iface, puiChannelCount);
1280
1281     return ComponentInfo_GetDWORDValue(This->classkey, channelcount_valuename, puiChannelCount);
1282 }
1283
1284 static HRESULT WINAPI PixelFormatInfo_GetChannelMask(IWICPixelFormatInfo2 *iface,
1285     UINT uiChannelIndex, UINT cbMaskBuffer, BYTE *pbMaskBuffer, UINT *pcbActual)
1286 {
1287     static const WCHAR uintformatW[] = {'%','u',0};
1288     PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1289     UINT channel_count;
1290     HRESULT hr;
1291     LONG ret;
1292     WCHAR valuename[11];
1293     DWORD cbData;
1294
1295     TRACE("(%p,%u,%u,%p,%p)\n", iface, uiChannelIndex, cbMaskBuffer, pbMaskBuffer, pcbActual);
1296
1297     if (!pcbActual)
1298         return E_INVALIDARG;
1299
1300     hr = PixelFormatInfo_GetChannelCount(iface, &channel_count);
1301
1302     if (SUCCEEDED(hr) && uiChannelIndex >= channel_count)
1303         hr = E_INVALIDARG;
1304
1305     if (SUCCEEDED(hr))
1306     {
1307         snprintfW(valuename, 11, uintformatW, uiChannelIndex);
1308
1309         cbData = cbMaskBuffer;
1310
1311         ret = RegGetValueW(This->classkey, channelmasks_keyname, valuename, RRF_RT_REG_BINARY, NULL, pbMaskBuffer, &cbData);
1312
1313         if (ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA)
1314             *pcbActual = cbData;
1315
1316         if (ret == ERROR_MORE_DATA)
1317             hr = E_INVALIDARG;
1318         else
1319             hr = HRESULT_FROM_WIN32(ret);
1320     }
1321
1322     return hr;
1323 }
1324
1325 static HRESULT WINAPI PixelFormatInfo_SupportsTransparency(IWICPixelFormatInfo2 *iface,
1326     BOOL *pfSupportsTransparency)
1327 {
1328     PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1329
1330     TRACE("(%p,%p)\n", iface, pfSupportsTransparency);
1331
1332     return ComponentInfo_GetDWORDValue(This->classkey, supportstransparency_valuename, (DWORD*)pfSupportsTransparency);
1333 }
1334
1335 static HRESULT WINAPI PixelFormatInfo_GetNumericRepresentation(IWICPixelFormatInfo2 *iface,
1336     WICPixelFormatNumericRepresentation *pNumericRepresentation)
1337 {
1338     PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1339
1340     TRACE("(%p,%p)\n", iface, pNumericRepresentation);
1341
1342     return ComponentInfo_GetDWORDValue(This->classkey, numericrepresentation_valuename, pNumericRepresentation);
1343 }
1344
1345 static const IWICPixelFormatInfo2Vtbl PixelFormatInfo_Vtbl = {
1346     PixelFormatInfo_QueryInterface,
1347     PixelFormatInfo_AddRef,
1348     PixelFormatInfo_Release,
1349     PixelFormatInfo_GetComponentType,
1350     PixelFormatInfo_GetCLSID,
1351     PixelFormatInfo_GetSigningStatus,
1352     PixelFormatInfo_GetAuthor,
1353     PixelFormatInfo_GetVendorGUID,
1354     PixelFormatInfo_GetVersion,
1355     PixelFormatInfo_GetSpecVersion,
1356     PixelFormatInfo_GetFriendlyName,
1357     PixelFormatInfo_GetFormatGUID,
1358     PixelFormatInfo_GetColorContext,
1359     PixelFormatInfo_GetBitsPerPixel,
1360     PixelFormatInfo_GetChannelCount,
1361     PixelFormatInfo_GetChannelMask,
1362     PixelFormatInfo_SupportsTransparency,
1363     PixelFormatInfo_GetNumericRepresentation
1364 };
1365
1366 static HRESULT PixelFormatInfo_Constructor(HKEY classkey, REFCLSID clsid, IWICComponentInfo **ppIInfo)
1367 {
1368     PixelFormatInfo *This;
1369
1370     This = HeapAlloc(GetProcessHeap(), 0, sizeof(PixelFormatInfo));
1371     if (!This)
1372     {
1373         RegCloseKey(classkey);
1374         return E_OUTOFMEMORY;
1375     }
1376
1377     This->IWICPixelFormatInfo2_iface.lpVtbl = &PixelFormatInfo_Vtbl;
1378     This->ref = 1;
1379     This->classkey = classkey;
1380     memcpy(&This->clsid, clsid, sizeof(CLSID));
1381
1382     *ppIInfo = (IWICComponentInfo*)This;
1383     return S_OK;
1384 }
1385
1386 typedef struct
1387 {
1388     IWICMetadataReaderInfo IWICMetadataReaderInfo_iface;
1389     LONG ref;
1390     HKEY classkey;
1391     CLSID clsid;
1392 } MetadataReaderInfo;
1393
1394 static inline MetadataReaderInfo *impl_from_IWICMetadataReaderInfo(IWICMetadataReaderInfo *iface)
1395 {
1396     return CONTAINING_RECORD(iface, MetadataReaderInfo, IWICMetadataReaderInfo_iface);
1397 }
1398
1399 static HRESULT WINAPI MetadataReaderInfo_QueryInterface(IWICMetadataReaderInfo *iface,
1400     REFIID riid, void **ppv)
1401 {
1402     MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1403
1404     TRACE("(%p,%s,%p)\n", iface, debugstr_guid(riid), ppv);
1405
1406     if (!ppv) return E_INVALIDARG;
1407
1408     if (IsEqualIID(&IID_IUnknown, riid) ||
1409         IsEqualIID(&IID_IWICComponentInfo, riid) ||
1410         IsEqualIID(&IID_IWICMetadataHandlerInfo, riid) ||
1411         IsEqualIID(&IID_IWICMetadataReaderInfo, riid))
1412     {
1413         *ppv = This;
1414     }
1415     else
1416     {
1417         *ppv = NULL;
1418         return E_NOINTERFACE;
1419     }
1420
1421     IUnknown_AddRef((IUnknown *)*ppv);
1422     return S_OK;
1423 }
1424
1425 static ULONG WINAPI MetadataReaderInfo_AddRef(IWICMetadataReaderInfo *iface)
1426 {
1427     MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1428     ULONG ref = InterlockedIncrement(&This->ref);
1429
1430     TRACE("(%p) refcount=%u\n", iface, ref);
1431     return ref;
1432 }
1433
1434 static ULONG WINAPI MetadataReaderInfo_Release(IWICMetadataReaderInfo *iface)
1435 {
1436     MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1437     ULONG ref = InterlockedDecrement(&This->ref);
1438
1439     TRACE("(%p) refcount=%u\n", iface, ref);
1440
1441     if (!ref)
1442     {
1443         RegCloseKey(This->classkey);
1444         HeapFree(GetProcessHeap(), 0, This);
1445     }
1446     return ref;
1447 }
1448
1449 static HRESULT WINAPI MetadataReaderInfo_GetComponentType(IWICMetadataReaderInfo *iface,
1450     WICComponentType *type)
1451 {
1452     TRACE("(%p,%p)\n", iface, type);
1453
1454     if (!type) return E_INVALIDARG;
1455     *type = WICMetadataReader;
1456     return S_OK;
1457 }
1458
1459 static HRESULT WINAPI MetadataReaderInfo_GetCLSID(IWICMetadataReaderInfo *iface,
1460     CLSID *clsid)
1461 {
1462     MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1463
1464     TRACE("(%p,%p)\n", iface, clsid);
1465
1466     if (!clsid) return E_INVALIDARG;
1467     *clsid = This->clsid;
1468     return S_OK;
1469 }
1470
1471 static HRESULT WINAPI MetadataReaderInfo_GetSigningStatus(IWICMetadataReaderInfo *iface,
1472     DWORD *status)
1473 {
1474     FIXME("(%p,%p): stub\n", iface, status);
1475     return E_NOTIMPL;
1476 }
1477
1478 static HRESULT WINAPI MetadataReaderInfo_GetAuthor(IWICMetadataReaderInfo *iface,
1479     UINT length, WCHAR *author, UINT *actual_length)
1480 {
1481     MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1482
1483     TRACE("(%p,%u,%p,%p)\n", iface, length, author, actual_length);
1484
1485     return ComponentInfo_GetStringValue(This->classkey, author_valuename,
1486                                         length, author, actual_length);
1487 }
1488
1489 static HRESULT WINAPI MetadataReaderInfo_GetVendorGUID(IWICMetadataReaderInfo *iface,
1490     GUID *vendor)
1491 {
1492     MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1493
1494     TRACE("(%p,%p)\n", iface, vendor);
1495
1496     return ComponentInfo_GetGUIDValue(This->classkey, vendor_valuename, vendor);
1497 }
1498
1499 static HRESULT WINAPI MetadataReaderInfo_GetVersion(IWICMetadataReaderInfo *iface,
1500     UINT length, WCHAR *version, UINT *actual_length)
1501 {
1502     MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1503
1504     TRACE("(%p,%u,%p,%p)\n", iface, length, version, actual_length);
1505
1506     return ComponentInfo_GetStringValue(This->classkey, version_valuename,
1507                                         length, version, actual_length);
1508 }
1509
1510 static HRESULT WINAPI MetadataReaderInfo_GetSpecVersion(IWICMetadataReaderInfo *iface,
1511     UINT length, WCHAR *version, UINT *actual_length)
1512 {
1513     FIXME("(%p,%u,%p,%p): stub\n", iface, length, version, actual_length);
1514     return E_NOTIMPL;
1515 }
1516
1517 static HRESULT WINAPI MetadataReaderInfo_GetFriendlyName(IWICMetadataReaderInfo *iface,
1518     UINT length, WCHAR *name, UINT *actual_length)
1519 {
1520     MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1521
1522     TRACE("(%p,%u,%p,%p)\n", iface, length, name, actual_length);
1523
1524     return ComponentInfo_GetStringValue(This->classkey, friendlyname_valuename,
1525                                         length, name, actual_length);
1526 }
1527
1528 static HRESULT WINAPI MetadataReaderInfo_GetMetadataFormat(IWICMetadataReaderInfo *iface,
1529     GUID *format)
1530 {
1531     MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1532     TRACE("(%p,%p)\n", iface, format);
1533     return ComponentInfo_GetGUIDValue(This->classkey, metadataformat_valuename, format);
1534 }
1535
1536 static HRESULT WINAPI MetadataReaderInfo_GetContainerFormats(IWICMetadataReaderInfo *iface,
1537     UINT length, GUID *formats, UINT *actual_length)
1538 {
1539     if (!actual_length) return E_INVALIDARG;
1540
1541     FIXME("(%p,%u,%p,%p): stub\n", iface, length, formats, actual_length);
1542     return E_NOTIMPL;
1543 }
1544
1545 static HRESULT WINAPI MetadataReaderInfo_GetDeviceManufacturer(IWICMetadataReaderInfo *iface,
1546     UINT length, WCHAR *manufacturer, UINT *actual_length)
1547 {
1548     FIXME("(%p,%u,%p,%p): stub\n", iface, length, manufacturer, actual_length);
1549     return E_NOTIMPL;
1550 }
1551
1552 static HRESULT WINAPI MetadataReaderInfo_GetDeviceModels(IWICMetadataReaderInfo *iface,
1553     UINT length, WCHAR *models, UINT *actual_length)
1554 {
1555     FIXME("(%p,%u,%p,%p): stub\n", iface, length, models, actual_length);
1556     return E_NOTIMPL;
1557 }
1558
1559 static HRESULT WINAPI MetadataReaderInfo_DoesRequireFullStream(IWICMetadataReaderInfo *iface,
1560     BOOL *param)
1561 {
1562     FIXME("(%p,%p): stub\n", iface, param);
1563     return E_NOTIMPL;
1564 }
1565
1566 static HRESULT WINAPI MetadataReaderInfo_DoesSupportPadding(IWICMetadataReaderInfo *iface,
1567     BOOL *param)
1568 {
1569     FIXME("(%p,%p): stub\n", iface, param);
1570     return E_NOTIMPL;
1571 }
1572
1573 static HRESULT WINAPI MetadataReaderInfo_DoesRequireFixedSize(IWICMetadataReaderInfo *iface,
1574     BOOL *param)
1575 {
1576     FIXME("(%p,%p): stub\n", iface, param);
1577     return E_NOTIMPL;
1578 }
1579
1580 static HRESULT WINAPI MetadataReaderInfo_GetPatterns(IWICMetadataReaderInfo *iface,
1581     REFGUID container, UINT length, WICMetadataPattern *pattern, UINT *count, UINT *actual_length)
1582 {
1583     if (!actual_length) return E_INVALIDARG;
1584
1585     FIXME("(%p,%s,%u,%p,%p,%p): stub\n", iface, debugstr_guid(container), length, pattern, count, actual_length);
1586     return E_NOTIMPL;
1587 }
1588
1589 static HRESULT WINAPI MetadataReaderInfo_MatchesPattern(IWICMetadataReaderInfo *iface,
1590     REFGUID container, IStream *stream, BOOL *matches)
1591 {
1592     FIXME("(%p,%s,%p,%p): stub\n", iface, debugstr_guid(container), stream, matches);
1593     return E_NOTIMPL;
1594 }
1595
1596 static HRESULT WINAPI MetadataReaderInfo_CreateInstance(IWICMetadataReaderInfo *iface,
1597     IWICMetadataReader **reader)
1598 {
1599     MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1600
1601     TRACE("(%p,%p)\n", iface, reader);
1602
1603     return CoCreateInstance(&This->clsid, NULL, CLSCTX_INPROC_SERVER,
1604                             &IID_IWICMetadataReader, (void **)reader);
1605 }
1606
1607 static const IWICMetadataReaderInfoVtbl MetadataReaderInfo_Vtbl = {
1608     MetadataReaderInfo_QueryInterface,
1609     MetadataReaderInfo_AddRef,
1610     MetadataReaderInfo_Release,
1611     MetadataReaderInfo_GetComponentType,
1612     MetadataReaderInfo_GetCLSID,
1613     MetadataReaderInfo_GetSigningStatus,
1614     MetadataReaderInfo_GetAuthor,
1615     MetadataReaderInfo_GetVendorGUID,
1616     MetadataReaderInfo_GetVersion,
1617     MetadataReaderInfo_GetSpecVersion,
1618     MetadataReaderInfo_GetFriendlyName,
1619     MetadataReaderInfo_GetMetadataFormat,
1620     MetadataReaderInfo_GetContainerFormats,
1621     MetadataReaderInfo_GetDeviceManufacturer,
1622     MetadataReaderInfo_GetDeviceModels,
1623     MetadataReaderInfo_DoesRequireFullStream,
1624     MetadataReaderInfo_DoesSupportPadding,
1625     MetadataReaderInfo_DoesRequireFixedSize,
1626     MetadataReaderInfo_GetPatterns,
1627     MetadataReaderInfo_MatchesPattern,
1628     MetadataReaderInfo_CreateInstance
1629 };
1630
1631 static HRESULT MetadataReaderInfo_Constructor(HKEY classkey, REFCLSID clsid, IWICComponentInfo **info)
1632 {
1633     MetadataReaderInfo *This;
1634
1635     This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1636     if (!This)
1637     {
1638         RegCloseKey(classkey);
1639         return E_OUTOFMEMORY;
1640     }
1641
1642     This->IWICMetadataReaderInfo_iface.lpVtbl = &MetadataReaderInfo_Vtbl;
1643     This->ref = 1;
1644     This->classkey = classkey;
1645     This->clsid = *clsid;
1646
1647     *info = (IWICComponentInfo *)This;
1648     return S_OK;
1649 }
1650
1651 static const WCHAR clsid_keyname[] = {'C','L','S','I','D',0};
1652 static const WCHAR instance_keyname[] = {'I','n','s','t','a','n','c','e',0};
1653
1654 struct category {
1655     WICComponentType type;
1656     const GUID *catid;
1657     HRESULT (*constructor)(HKEY,REFCLSID,IWICComponentInfo**);
1658 };
1659
1660 static const struct category categories[] = {
1661     {WICDecoder, &CATID_WICBitmapDecoders, BitmapDecoderInfo_Constructor},
1662     {WICEncoder, &CATID_WICBitmapEncoders, BitmapEncoderInfo_Constructor},
1663     {WICPixelFormatConverter, &CATID_WICFormatConverters, FormatConverterInfo_Constructor},
1664     {WICPixelFormat, &CATID_WICPixelFormats, PixelFormatInfo_Constructor},
1665     {WICMetadataReader, &CATID_WICMetadataReader, MetadataReaderInfo_Constructor},
1666     {0}
1667 };
1668
1669 HRESULT CreateComponentInfo(REFCLSID clsid, IWICComponentInfo **ppIInfo)
1670 {
1671     HKEY clsidkey;
1672     HKEY classkey;
1673     HKEY catidkey;
1674     HKEY instancekey;
1675     WCHAR guidstring[39];
1676     LONG res;
1677     const struct category *category;
1678     int found=0;
1679     HRESULT hr;
1680
1681     res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, KEY_READ, &clsidkey);
1682     if (res != ERROR_SUCCESS)
1683         return HRESULT_FROM_WIN32(res);
1684
1685     for (category=categories; category->type; category++)
1686     {
1687         StringFromGUID2(category->catid, guidstring, 39);
1688         res = RegOpenKeyExW(clsidkey, guidstring, 0, KEY_READ, &catidkey);
1689         if (res == ERROR_SUCCESS)
1690         {
1691             res = RegOpenKeyExW(catidkey, instance_keyname, 0, KEY_READ, &instancekey);
1692             if (res == ERROR_SUCCESS)
1693             {
1694                 StringFromGUID2(clsid, guidstring, 39);
1695                 res = RegOpenKeyExW(instancekey, guidstring, 0, KEY_READ, &classkey);
1696                 if (res == ERROR_SUCCESS)
1697                 {
1698                     RegCloseKey(classkey);
1699                     found = 1;
1700                 }
1701                 RegCloseKey(instancekey);
1702             }
1703             RegCloseKey(catidkey);
1704         }
1705         if (found) break;
1706     }
1707
1708     if (found)
1709     {
1710         res = RegOpenKeyExW(clsidkey, guidstring, 0, KEY_READ, &classkey);
1711         if (res == ERROR_SUCCESS)
1712             hr = category->constructor(classkey, clsid, ppIInfo);
1713         else
1714             hr = HRESULT_FROM_WIN32(res);
1715     }
1716     else
1717     {
1718         FIXME("%s is not supported\n", wine_dbgstr_guid(clsid));
1719         hr = E_FAIL;
1720     }
1721
1722     RegCloseKey(clsidkey);
1723
1724     return hr;
1725 }
1726
1727 typedef struct {
1728     IEnumUnknown IEnumUnknown_iface;
1729     LONG ref;
1730     struct list objects;
1731     struct list *cursor;
1732     CRITICAL_SECTION lock; /* Must be held when reading or writing cursor */
1733 } ComponentEnum;
1734
1735 static inline ComponentEnum *impl_from_IEnumUnknown(IEnumUnknown *iface)
1736 {
1737     return CONTAINING_RECORD(iface, ComponentEnum, IEnumUnknown_iface);
1738 }
1739
1740 typedef struct {
1741     struct list entry;
1742     IUnknown *unk;
1743 } ComponentEnumItem;
1744
1745 static const IEnumUnknownVtbl ComponentEnumVtbl;
1746
1747 static HRESULT WINAPI ComponentEnum_QueryInterface(IEnumUnknown *iface, REFIID iid,
1748     void **ppv)
1749 {
1750     ComponentEnum *This = impl_from_IEnumUnknown(iface);
1751     TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
1752
1753     if (!ppv) return E_INVALIDARG;
1754
1755     if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IEnumUnknown, iid))
1756     {
1757         *ppv = This;
1758     }
1759     else
1760     {
1761         *ppv = NULL;
1762         return E_NOINTERFACE;
1763     }
1764
1765     IUnknown_AddRef((IUnknown*)*ppv);
1766     return S_OK;
1767 }
1768
1769 static ULONG WINAPI ComponentEnum_AddRef(IEnumUnknown *iface)
1770 {
1771     ComponentEnum *This = impl_from_IEnumUnknown(iface);
1772     ULONG ref = InterlockedIncrement(&This->ref);
1773
1774     TRACE("(%p) refcount=%u\n", iface, ref);
1775
1776     return ref;
1777 }
1778
1779 static ULONG WINAPI ComponentEnum_Release(IEnumUnknown *iface)
1780 {
1781     ComponentEnum *This = impl_from_IEnumUnknown(iface);
1782     ULONG ref = InterlockedDecrement(&This->ref);
1783     ComponentEnumItem *cursor, *cursor2;
1784
1785     TRACE("(%p) refcount=%u\n", iface, ref);
1786
1787     if (ref == 0)
1788     {
1789         LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, &This->objects, ComponentEnumItem, entry)
1790         {
1791             IUnknown_Release(cursor->unk);
1792             list_remove(&cursor->entry);
1793             HeapFree(GetProcessHeap(), 0, cursor);
1794         }
1795         This->lock.DebugInfo->Spare[0] = 0;
1796         DeleteCriticalSection(&This->lock);
1797         HeapFree(GetProcessHeap(), 0, This);
1798     }
1799
1800     return ref;
1801 }
1802
1803 static HRESULT WINAPI ComponentEnum_Next(IEnumUnknown *iface, ULONG celt,
1804     IUnknown **rgelt, ULONG *pceltFetched)
1805 {
1806     ComponentEnum *This = impl_from_IEnumUnknown(iface);
1807     int num_fetched=0;
1808     ComponentEnumItem *item;
1809     HRESULT hr=S_OK;
1810
1811     TRACE("(%p,%u,%p,%p)\n", iface, celt, rgelt, pceltFetched);
1812
1813     EnterCriticalSection(&This->lock);
1814     while (num_fetched<celt)
1815     {
1816         if (!This->cursor)
1817         {
1818             hr = S_FALSE;
1819             break;
1820         }
1821         item = LIST_ENTRY(This->cursor, ComponentEnumItem, entry);
1822         IUnknown_AddRef(item->unk);
1823         rgelt[num_fetched] = item->unk;
1824         num_fetched++;
1825         This->cursor = list_next(&This->objects, This->cursor);
1826     }
1827     LeaveCriticalSection(&This->lock);
1828     if (pceltFetched)
1829         *pceltFetched = num_fetched;
1830     return hr;
1831 }
1832
1833 static HRESULT WINAPI ComponentEnum_Skip(IEnumUnknown *iface, ULONG celt)
1834 {
1835     ComponentEnum *This = impl_from_IEnumUnknown(iface);
1836     int i;
1837     HRESULT hr=S_OK;
1838
1839     TRACE("(%p,%u)\n", iface, celt);
1840
1841     EnterCriticalSection(&This->lock);
1842     for (i=0; i<celt; i++)
1843     {
1844         if (!This->cursor)
1845         {
1846             hr = S_FALSE;
1847             break;
1848         }
1849         This->cursor = list_next(&This->objects, This->cursor);
1850     }
1851     LeaveCriticalSection(&This->lock);
1852     return hr;
1853 }
1854
1855 static HRESULT WINAPI ComponentEnum_Reset(IEnumUnknown *iface)
1856 {
1857     ComponentEnum *This = impl_from_IEnumUnknown(iface);
1858
1859     TRACE("(%p)\n", iface);
1860
1861     EnterCriticalSection(&This->lock);
1862     This->cursor = list_head(&This->objects);
1863     LeaveCriticalSection(&This->lock);
1864     return S_OK;
1865 }
1866
1867 static HRESULT WINAPI ComponentEnum_Clone(IEnumUnknown *iface, IEnumUnknown **ppenum)
1868 {
1869     ComponentEnum *This = impl_from_IEnumUnknown(iface);
1870     ComponentEnum *new_enum;
1871     ComponentEnumItem *old_item, *new_item;
1872     HRESULT ret=S_OK;
1873     struct list *old_cursor;
1874
1875     new_enum = HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentEnum));
1876     if (!new_enum)
1877     {
1878         *ppenum = NULL;
1879         return E_OUTOFMEMORY;
1880     }
1881
1882     new_enum->IEnumUnknown_iface.lpVtbl = &ComponentEnumVtbl;
1883     new_enum->ref = 1;
1884     new_enum->cursor = NULL;
1885     list_init(&new_enum->objects);
1886     InitializeCriticalSection(&new_enum->lock);
1887     new_enum->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": ComponentEnum.lock");
1888
1889     EnterCriticalSection(&This->lock);
1890     old_cursor = This->cursor;
1891     LeaveCriticalSection(&This->lock);
1892
1893     LIST_FOR_EACH_ENTRY(old_item, &This->objects, ComponentEnumItem, entry)
1894     {
1895         new_item = HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentEnumItem));
1896         if (!new_item)
1897         {
1898             ret = E_OUTOFMEMORY;
1899             break;
1900         }
1901         new_item->unk = old_item->unk;
1902         list_add_tail(&new_enum->objects, &new_item->entry);
1903         IUnknown_AddRef(new_item->unk);
1904         if (&old_item->entry == old_cursor) new_enum->cursor = &new_item->entry;
1905     }
1906
1907     if (FAILED(ret))
1908     {
1909         IUnknown_Release((IUnknown*)new_enum);
1910         *ppenum = NULL;
1911     }
1912     else
1913         *ppenum = (IEnumUnknown*)new_enum;
1914
1915     return ret;
1916 }
1917
1918 static const IEnumUnknownVtbl ComponentEnumVtbl = {
1919     ComponentEnum_QueryInterface,
1920     ComponentEnum_AddRef,
1921     ComponentEnum_Release,
1922     ComponentEnum_Next,
1923     ComponentEnum_Skip,
1924     ComponentEnum_Reset,
1925     ComponentEnum_Clone
1926 };
1927
1928 HRESULT CreateComponentEnumerator(DWORD componentTypes, DWORD options, IEnumUnknown **ppIEnumUnknown)
1929 {
1930     ComponentEnum *This;
1931     ComponentEnumItem *item;
1932     const struct category *category;
1933     HKEY clsidkey, catidkey, instancekey;
1934     WCHAR guidstring[39];
1935     LONG res;
1936     int i;
1937     HRESULT hr=S_OK;
1938     CLSID clsid;
1939
1940     if (options) FIXME("ignoring flags %x\n", options);
1941
1942     res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, KEY_READ, &clsidkey);
1943     if (res != ERROR_SUCCESS)
1944         return HRESULT_FROM_WIN32(res);
1945
1946     This = HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentEnum));
1947     if (!This)
1948     {
1949         RegCloseKey(clsidkey);
1950         return E_OUTOFMEMORY;
1951     }
1952
1953     This->IEnumUnknown_iface.lpVtbl = &ComponentEnumVtbl;
1954     This->ref = 1;
1955     list_init(&This->objects);
1956     InitializeCriticalSection(&This->lock);
1957     This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": ComponentEnum.lock");
1958
1959     for (category=categories; category->type && hr == S_OK; category++)
1960     {
1961         if ((category->type & componentTypes) == 0) continue;
1962         StringFromGUID2(category->catid, guidstring, 39);
1963         res = RegOpenKeyExW(clsidkey, guidstring, 0, KEY_READ, &catidkey);
1964         if (res == ERROR_SUCCESS)
1965         {
1966             res = RegOpenKeyExW(catidkey, instance_keyname, 0, KEY_READ, &instancekey);
1967             if (res == ERROR_SUCCESS)
1968             {
1969                 i=0;
1970                 for (;;i++)
1971                 {
1972                     DWORD guidstring_size = 39;
1973                     res = RegEnumKeyExW(instancekey, i, guidstring, &guidstring_size, NULL, NULL, NULL, NULL);
1974                     if (res != ERROR_SUCCESS) break;
1975
1976                     item = HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentEnumItem));
1977                     if (!item) { hr = E_OUTOFMEMORY; break; }
1978
1979                     hr = CLSIDFromString(guidstring, &clsid);
1980                     if (SUCCEEDED(hr))
1981                     {
1982                         hr = CreateComponentInfo(&clsid, (IWICComponentInfo**)&item->unk);
1983                         if (SUCCEEDED(hr))
1984                             list_add_tail(&This->objects, &item->entry);
1985                     }
1986
1987                     if (FAILED(hr))
1988                     {
1989                         HeapFree(GetProcessHeap(), 0, item);
1990                         hr = S_OK;
1991                     }
1992                 }
1993                 RegCloseKey(instancekey);
1994             }
1995             RegCloseKey(catidkey);
1996         }
1997         if (res != ERROR_SUCCESS && res != ERROR_NO_MORE_ITEMS)
1998             hr = HRESULT_FROM_WIN32(res);
1999     }
2000     RegCloseKey(clsidkey);
2001
2002     if (SUCCEEDED(hr))
2003     {
2004         IEnumUnknown_Reset((IEnumUnknown*)This);
2005         *ppIEnumUnknown = (IEnumUnknown*)This;
2006     }
2007     else
2008     {
2009         *ppIEnumUnknown = NULL;
2010         IUnknown_Release((IUnknown*)This);
2011     }
2012
2013     return hr;
2014 }
2015
2016 HRESULT WINAPI WICConvertBitmapSource(REFWICPixelFormatGUID dstFormat, IWICBitmapSource *pISrc, IWICBitmapSource **ppIDst)
2017 {
2018     HRESULT res;
2019     IEnumUnknown *enumconverters;
2020     IUnknown *unkconverterinfo;
2021     IWICFormatConverterInfo *converterinfo=NULL;
2022     IWICFormatConverter *converter=NULL;
2023     GUID srcFormat;
2024     WCHAR srcformatstr[39], dstformatstr[39];
2025     BOOL canconvert;
2026     ULONG num_fetched;
2027
2028     res = IWICBitmapSource_GetPixelFormat(pISrc, &srcFormat);
2029     if (FAILED(res)) return res;
2030
2031     if (IsEqualGUID(&srcFormat, dstFormat))
2032     {
2033         IWICBitmapSource_AddRef(pISrc);
2034         *ppIDst = pISrc;
2035         return S_OK;
2036     }
2037
2038     StringFromGUID2(&srcFormat, srcformatstr, 39);
2039     StringFromGUID2(dstFormat, dstformatstr, 39);
2040
2041     res = CreateComponentEnumerator(WICPixelFormatConverter, 0, &enumconverters);
2042     if (FAILED(res)) return res;
2043
2044     while (!converter)
2045     {
2046         res = IEnumUnknown_Next(enumconverters, 1, &unkconverterinfo, &num_fetched);
2047
2048         if (res == S_OK)
2049         {
2050             res = IUnknown_QueryInterface(unkconverterinfo, &IID_IWICFormatConverterInfo, (void**)&converterinfo);
2051
2052             if (SUCCEEDED(res))
2053             {
2054                 canconvert = ConverterSupportsFormat(converterinfo, srcformatstr);
2055
2056                 if (canconvert)
2057                     canconvert = ConverterSupportsFormat(converterinfo, dstformatstr);
2058
2059                 if (canconvert)
2060                 {
2061                     res = IWICFormatConverterInfo_CreateInstance(converterinfo, &converter);
2062
2063                     if (SUCCEEDED(res))
2064                         res = IWICFormatConverter_CanConvert(converter, &srcFormat, dstFormat, &canconvert);
2065
2066                     if (SUCCEEDED(res) && canconvert)
2067                         res = IWICFormatConverter_Initialize(converter, pISrc, dstFormat, WICBitmapDitherTypeNone,
2068                             NULL, 0.0, WICBitmapPaletteTypeCustom);
2069
2070                     if (FAILED(res) || !canconvert)
2071                     {
2072                         if (converter)
2073                         {
2074                             IWICFormatConverter_Release(converter);
2075                             converter = NULL;
2076                         }
2077                         res = S_OK;
2078                     }
2079                 }
2080
2081                 IWICFormatConverterInfo_Release(converterinfo);
2082             }
2083
2084             IUnknown_Release(unkconverterinfo);
2085         }
2086         else
2087             break;
2088     }
2089
2090     IEnumUnknown_Release(enumconverters);
2091
2092     if (converter)
2093     {
2094         *ppIDst = (IWICBitmapSource*)converter;
2095         return S_OK;
2096     }
2097     else
2098     {
2099         FIXME("cannot convert %s to %s\n", debugstr_guid(&srcFormat), debugstr_guid(dstFormat));
2100         *ppIDst = NULL;
2101         return WINCODEC_ERR_COMPONENTNOTFOUND;
2102     }
2103 }