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