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