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