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