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