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