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