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