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