windowscodecs: Implement IWICComponentInfo::GetAuthor.
[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     *pType = WICPixelFormat;
1090     return S_OK;
1091 }
1092
1093 static HRESULT WINAPI PixelFormatInfo_GetCLSID(IWICPixelFormatInfo2 *iface, CLSID *pclsid)
1094 {
1095     PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1096     TRACE("(%p,%p)\n", iface, pclsid);
1097
1098     if (!pclsid)
1099         return E_INVALIDARG;
1100
1101     memcpy(pclsid, &This->clsid, sizeof(CLSID));
1102
1103     return S_OK;
1104 }
1105
1106 static HRESULT WINAPI PixelFormatInfo_GetSigningStatus(IWICPixelFormatInfo2 *iface, DWORD *pStatus)
1107 {
1108     FIXME("(%p,%p): stub\n", iface, pStatus);
1109     return E_NOTIMPL;
1110 }
1111
1112 static HRESULT WINAPI PixelFormatInfo_GetAuthor(IWICPixelFormatInfo2 *iface, UINT cchAuthor,
1113     WCHAR *wzAuthor, UINT *pcchActual)
1114 {
1115     PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1116
1117     TRACE("(%p,%u,%p,%p)\n", iface, cchAuthor, wzAuthor, pcchActual);
1118
1119     return ComponentInfo_GetStringValue(This->classkey, author_valuename,
1120         cchAuthor, wzAuthor, pcchActual);
1121 }
1122
1123 static HRESULT WINAPI PixelFormatInfo_GetVendorGUID(IWICPixelFormatInfo2 *iface, GUID *pguidVendor)
1124 {
1125     FIXME("(%p,%p): stub\n", iface, pguidVendor);
1126     return E_NOTIMPL;
1127 }
1128
1129 static HRESULT WINAPI PixelFormatInfo_GetVersion(IWICPixelFormatInfo2 *iface, UINT cchVersion,
1130     WCHAR *wzVersion, UINT *pcchActual)
1131 {
1132     FIXME("(%p,%u,%p,%p): stub\n", iface, cchVersion, wzVersion, pcchActual);
1133     return E_NOTIMPL;
1134 }
1135
1136 static HRESULT WINAPI PixelFormatInfo_GetSpecVersion(IWICPixelFormatInfo2 *iface, UINT cchSpecVersion,
1137     WCHAR *wzSpecVersion, UINT *pcchActual)
1138 {
1139     FIXME("(%p,%u,%p,%p): stub\n", iface, cchSpecVersion, wzSpecVersion, pcchActual);
1140     return E_NOTIMPL;
1141 }
1142
1143 static HRESULT WINAPI PixelFormatInfo_GetFriendlyName(IWICPixelFormatInfo2 *iface, UINT cchFriendlyName,
1144     WCHAR *wzFriendlyName, UINT *pcchActual)
1145 {
1146     FIXME("(%p,%u,%p,%p): stub\n", iface, cchFriendlyName, wzFriendlyName, pcchActual);
1147     return E_NOTIMPL;
1148 }
1149
1150 static HRESULT WINAPI PixelFormatInfo_GetFormatGUID(IWICPixelFormatInfo2 *iface,
1151     GUID *pFormat)
1152 {
1153     FIXME("(%p,%p): stub\n", iface, pFormat);
1154     return E_NOTIMPL;
1155 }
1156
1157 static HRESULT WINAPI PixelFormatInfo_GetColorContext(IWICPixelFormatInfo2 *iface,
1158     IWICColorContext **ppIColorContext)
1159 {
1160     FIXME("(%p,%p): stub\n", iface, ppIColorContext);
1161     return E_NOTIMPL;
1162 }
1163
1164 static HRESULT WINAPI PixelFormatInfo_GetBitsPerPixel(IWICPixelFormatInfo2 *iface,
1165     UINT *puiBitsPerPixel)
1166 {
1167     FIXME("(%p,%p): stub\n", iface, puiBitsPerPixel);
1168     return E_NOTIMPL;
1169 }
1170
1171 static HRESULT WINAPI PixelFormatInfo_GetChannelCount(IWICPixelFormatInfo2 *iface,
1172     UINT *puiChannelCount)
1173 {
1174     FIXME("(%p,%p): stub\n", iface, puiChannelCount);
1175     return E_NOTIMPL;
1176 }
1177
1178 static HRESULT WINAPI PixelFormatInfo_GetChannelMask(IWICPixelFormatInfo2 *iface,
1179     UINT uiChannelIndex, UINT cbMaskBuffer, BYTE *pbMaskBuffer, UINT *pcbActual)
1180 {
1181     FIXME("(%p,%u,%u,%p,%p): stub\n", iface, uiChannelIndex, cbMaskBuffer, pbMaskBuffer, pcbActual);
1182     return E_NOTIMPL;
1183 }
1184
1185 static HRESULT WINAPI PixelFormatInfo_SupportsTransparency(IWICPixelFormatInfo2 *iface,
1186     BOOL *pfSupportsTransparency)
1187 {
1188     FIXME("(%p,%p): stub\n", iface, pfSupportsTransparency);
1189     return E_NOTIMPL;
1190 }
1191
1192 static HRESULT WINAPI PixelFormatInfo_GetNumericRepresentation(IWICPixelFormatInfo2 *iface,
1193     WICPixelFormatNumericRepresentation *pNumericRepresentation)
1194 {
1195     FIXME("(%p,%p): stub\n", iface, pNumericRepresentation);
1196     return E_NOTIMPL;
1197 }
1198
1199 static const IWICPixelFormatInfo2Vtbl PixelFormatInfo_Vtbl = {
1200     PixelFormatInfo_QueryInterface,
1201     PixelFormatInfo_AddRef,
1202     PixelFormatInfo_Release,
1203     PixelFormatInfo_GetComponentType,
1204     PixelFormatInfo_GetCLSID,
1205     PixelFormatInfo_GetSigningStatus,
1206     PixelFormatInfo_GetAuthor,
1207     PixelFormatInfo_GetVendorGUID,
1208     PixelFormatInfo_GetVersion,
1209     PixelFormatInfo_GetSpecVersion,
1210     PixelFormatInfo_GetFriendlyName,
1211     PixelFormatInfo_GetFormatGUID,
1212     PixelFormatInfo_GetColorContext,
1213     PixelFormatInfo_GetBitsPerPixel,
1214     PixelFormatInfo_GetChannelCount,
1215     PixelFormatInfo_GetChannelMask,
1216     PixelFormatInfo_SupportsTransparency,
1217     PixelFormatInfo_GetNumericRepresentation
1218 };
1219
1220 static HRESULT PixelFormatInfo_Constructor(HKEY classkey, REFCLSID clsid, IWICComponentInfo **ppIInfo)
1221 {
1222     PixelFormatInfo *This;
1223
1224     This = HeapAlloc(GetProcessHeap(), 0, sizeof(PixelFormatInfo));
1225     if (!This)
1226     {
1227         RegCloseKey(classkey);
1228         return E_OUTOFMEMORY;
1229     }
1230
1231     This->IWICPixelFormatInfo2_iface.lpVtbl = &PixelFormatInfo_Vtbl;
1232     This->ref = 1;
1233     This->classkey = classkey;
1234     memcpy(&This->clsid, clsid, sizeof(CLSID));
1235
1236     *ppIInfo = (IWICComponentInfo*)This;
1237     return S_OK;
1238 }
1239
1240 static const WCHAR clsid_keyname[] = {'C','L','S','I','D',0};
1241 static const WCHAR instance_keyname[] = {'I','n','s','t','a','n','c','e',0};
1242
1243 struct category {
1244     WICComponentType type;
1245     const GUID *catid;
1246     HRESULT (*constructor)(HKEY,REFCLSID,IWICComponentInfo**);
1247 };
1248
1249 static const struct category categories[] = {
1250     {WICDecoder, &CATID_WICBitmapDecoders, BitmapDecoderInfo_Constructor},
1251     {WICEncoder, &CATID_WICBitmapEncoders, BitmapEncoderInfo_Constructor},
1252     {WICPixelFormatConverter, &CATID_WICFormatConverters, FormatConverterInfo_Constructor},
1253     {WICPixelFormat, &CATID_WICPixelFormats, PixelFormatInfo_Constructor},
1254     {0}
1255 };
1256
1257 HRESULT CreateComponentInfo(REFCLSID clsid, IWICComponentInfo **ppIInfo)
1258 {
1259     HKEY clsidkey;
1260     HKEY classkey;
1261     HKEY catidkey;
1262     HKEY instancekey;
1263     WCHAR guidstring[39];
1264     LONG res;
1265     const struct category *category;
1266     int found=0;
1267     HRESULT hr;
1268
1269     res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, KEY_READ, &clsidkey);
1270     if (res != ERROR_SUCCESS)
1271         return HRESULT_FROM_WIN32(res);
1272
1273     for (category=categories; category->type; category++)
1274     {
1275         StringFromGUID2(category->catid, guidstring, 39);
1276         res = RegOpenKeyExW(clsidkey, guidstring, 0, KEY_READ, &catidkey);
1277         if (res == ERROR_SUCCESS)
1278         {
1279             res = RegOpenKeyExW(catidkey, instance_keyname, 0, KEY_READ, &instancekey);
1280             if (res == ERROR_SUCCESS)
1281             {
1282                 StringFromGUID2(clsid, guidstring, 39);
1283                 res = RegOpenKeyExW(instancekey, guidstring, 0, KEY_READ, &classkey);
1284                 if (res == ERROR_SUCCESS)
1285                 {
1286                     RegCloseKey(classkey);
1287                     found = 1;
1288                 }
1289                 RegCloseKey(instancekey);
1290             }
1291             RegCloseKey(catidkey);
1292         }
1293         if (found) break;
1294     }
1295
1296     if (found)
1297     {
1298         res = RegOpenKeyExW(clsidkey, guidstring, 0, KEY_READ, &classkey);
1299         if (res == ERROR_SUCCESS)
1300             hr = category->constructor(classkey, clsid, ppIInfo);
1301         else
1302             hr = HRESULT_FROM_WIN32(res);
1303     }
1304     else
1305         hr = E_FAIL;
1306
1307     RegCloseKey(clsidkey);
1308
1309     return hr;
1310 }
1311
1312 typedef struct {
1313     IEnumUnknown IEnumUnknown_iface;
1314     LONG ref;
1315     struct list objects;
1316     struct list *cursor;
1317     CRITICAL_SECTION lock; /* Must be held when reading or writing cursor */
1318 } ComponentEnum;
1319
1320 static inline ComponentEnum *impl_from_IEnumUnknown(IEnumUnknown *iface)
1321 {
1322     return CONTAINING_RECORD(iface, ComponentEnum, IEnumUnknown_iface);
1323 }
1324
1325 typedef struct {
1326     struct list entry;
1327     IUnknown *unk;
1328 } ComponentEnumItem;
1329
1330 static const IEnumUnknownVtbl ComponentEnumVtbl;
1331
1332 static HRESULT WINAPI ComponentEnum_QueryInterface(IEnumUnknown *iface, REFIID iid,
1333     void **ppv)
1334 {
1335     ComponentEnum *This = impl_from_IEnumUnknown(iface);
1336     TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
1337
1338     if (!ppv) return E_INVALIDARG;
1339
1340     if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IEnumUnknown, iid))
1341     {
1342         *ppv = This;
1343     }
1344     else
1345     {
1346         *ppv = NULL;
1347         return E_NOINTERFACE;
1348     }
1349
1350     IUnknown_AddRef((IUnknown*)*ppv);
1351     return S_OK;
1352 }
1353
1354 static ULONG WINAPI ComponentEnum_AddRef(IEnumUnknown *iface)
1355 {
1356     ComponentEnum *This = impl_from_IEnumUnknown(iface);
1357     ULONG ref = InterlockedIncrement(&This->ref);
1358
1359     TRACE("(%p) refcount=%u\n", iface, ref);
1360
1361     return ref;
1362 }
1363
1364 static ULONG WINAPI ComponentEnum_Release(IEnumUnknown *iface)
1365 {
1366     ComponentEnum *This = impl_from_IEnumUnknown(iface);
1367     ULONG ref = InterlockedDecrement(&This->ref);
1368     ComponentEnumItem *cursor, *cursor2;
1369
1370     TRACE("(%p) refcount=%u\n", iface, ref);
1371
1372     if (ref == 0)
1373     {
1374         LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, &This->objects, ComponentEnumItem, entry)
1375         {
1376             IUnknown_Release(cursor->unk);
1377             list_remove(&cursor->entry);
1378             HeapFree(GetProcessHeap(), 0, cursor);
1379         }
1380         This->lock.DebugInfo->Spare[0] = 0;
1381         DeleteCriticalSection(&This->lock);
1382         HeapFree(GetProcessHeap(), 0, This);
1383     }
1384
1385     return ref;
1386 }
1387
1388 static HRESULT WINAPI ComponentEnum_Next(IEnumUnknown *iface, ULONG celt,
1389     IUnknown **rgelt, ULONG *pceltFetched)
1390 {
1391     ComponentEnum *This = impl_from_IEnumUnknown(iface);
1392     int num_fetched=0;
1393     ComponentEnumItem *item;
1394     HRESULT hr=S_OK;
1395
1396     TRACE("(%p,%u,%p,%p)\n", iface, celt, rgelt, pceltFetched);
1397
1398     EnterCriticalSection(&This->lock);
1399     while (num_fetched<celt)
1400     {
1401         if (!This->cursor)
1402         {
1403             hr = S_FALSE;
1404             break;
1405         }
1406         item = LIST_ENTRY(This->cursor, ComponentEnumItem, entry);
1407         IUnknown_AddRef(item->unk);
1408         rgelt[num_fetched] = item->unk;
1409         num_fetched++;
1410         This->cursor = list_next(&This->objects, This->cursor);
1411     }
1412     LeaveCriticalSection(&This->lock);
1413     if (pceltFetched)
1414         *pceltFetched = num_fetched;
1415     return hr;
1416 }
1417
1418 static HRESULT WINAPI ComponentEnum_Skip(IEnumUnknown *iface, ULONG celt)
1419 {
1420     ComponentEnum *This = impl_from_IEnumUnknown(iface);
1421     int i;
1422     HRESULT hr=S_OK;
1423
1424     TRACE("(%p,%u)\n", iface, celt);
1425
1426     EnterCriticalSection(&This->lock);
1427     for (i=0; i<celt; i++)
1428     {
1429         if (!This->cursor)
1430         {
1431             hr = S_FALSE;
1432             break;
1433         }
1434         This->cursor = list_next(&This->objects, This->cursor);
1435     }
1436     LeaveCriticalSection(&This->lock);
1437     return hr;
1438 }
1439
1440 static HRESULT WINAPI ComponentEnum_Reset(IEnumUnknown *iface)
1441 {
1442     ComponentEnum *This = impl_from_IEnumUnknown(iface);
1443
1444     TRACE("(%p)\n", iface);
1445
1446     EnterCriticalSection(&This->lock);
1447     This->cursor = list_head(&This->objects);
1448     LeaveCriticalSection(&This->lock);
1449     return S_OK;
1450 }
1451
1452 static HRESULT WINAPI ComponentEnum_Clone(IEnumUnknown *iface, IEnumUnknown **ppenum)
1453 {
1454     ComponentEnum *This = impl_from_IEnumUnknown(iface);
1455     ComponentEnum *new_enum;
1456     ComponentEnumItem *old_item, *new_item;
1457     HRESULT ret=S_OK;
1458     struct list *old_cursor;
1459
1460     new_enum = HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentEnum));
1461     if (!new_enum)
1462     {
1463         *ppenum = NULL;
1464         return E_OUTOFMEMORY;
1465     }
1466
1467     new_enum->IEnumUnknown_iface.lpVtbl = &ComponentEnumVtbl;
1468     new_enum->ref = 1;
1469     new_enum->cursor = NULL;
1470     list_init(&new_enum->objects);
1471     InitializeCriticalSection(&new_enum->lock);
1472     new_enum->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": ComponentEnum.lock");
1473
1474     EnterCriticalSection(&This->lock);
1475     old_cursor = This->cursor;
1476     LeaveCriticalSection(&This->lock);
1477
1478     LIST_FOR_EACH_ENTRY(old_item, &This->objects, ComponentEnumItem, entry)
1479     {
1480         new_item = HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentEnumItem));
1481         if (!new_item)
1482         {
1483             ret = E_OUTOFMEMORY;
1484             break;
1485         }
1486         new_item->unk = old_item->unk;
1487         list_add_tail(&new_enum->objects, &new_item->entry);
1488         IUnknown_AddRef(new_item->unk);
1489         if (&old_item->entry == old_cursor) new_enum->cursor = &new_item->entry;
1490     }
1491
1492     if (FAILED(ret))
1493     {
1494         IUnknown_Release((IUnknown*)new_enum);
1495         *ppenum = NULL;
1496     }
1497     else
1498         *ppenum = (IEnumUnknown*)new_enum;
1499
1500     return ret;
1501 }
1502
1503 static const IEnumUnknownVtbl ComponentEnumVtbl = {
1504     ComponentEnum_QueryInterface,
1505     ComponentEnum_AddRef,
1506     ComponentEnum_Release,
1507     ComponentEnum_Next,
1508     ComponentEnum_Skip,
1509     ComponentEnum_Reset,
1510     ComponentEnum_Clone
1511 };
1512
1513 HRESULT CreateComponentEnumerator(DWORD componentTypes, DWORD options, IEnumUnknown **ppIEnumUnknown)
1514 {
1515     ComponentEnum *This;
1516     ComponentEnumItem *item;
1517     const struct category *category;
1518     HKEY clsidkey, catidkey, instancekey;
1519     WCHAR guidstring[39];
1520     LONG res;
1521     int i;
1522     HRESULT hr=S_OK;
1523     CLSID clsid;
1524
1525     if (options) FIXME("ignoring flags %x\n", options);
1526
1527     res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, KEY_READ, &clsidkey);
1528     if (res != ERROR_SUCCESS)
1529         return HRESULT_FROM_WIN32(res);
1530
1531     This = HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentEnum));
1532     if (!This)
1533     {
1534         RegCloseKey(clsidkey);
1535         return E_OUTOFMEMORY;
1536     }
1537
1538     This->IEnumUnknown_iface.lpVtbl = &ComponentEnumVtbl;
1539     This->ref = 1;
1540     list_init(&This->objects);
1541     InitializeCriticalSection(&This->lock);
1542     This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": ComponentEnum.lock");
1543
1544     for (category=categories; category->type && hr == S_OK; category++)
1545     {
1546         if ((category->type & componentTypes) == 0) continue;
1547         StringFromGUID2(category->catid, guidstring, 39);
1548         res = RegOpenKeyExW(clsidkey, guidstring, 0, KEY_READ, &catidkey);
1549         if (res == ERROR_SUCCESS)
1550         {
1551             res = RegOpenKeyExW(catidkey, instance_keyname, 0, KEY_READ, &instancekey);
1552             if (res == ERROR_SUCCESS)
1553             {
1554                 i=0;
1555                 for (;;i++)
1556                 {
1557                     DWORD guidstring_size = 39;
1558                     res = RegEnumKeyExW(instancekey, i, guidstring, &guidstring_size, NULL, NULL, NULL, NULL);
1559                     if (res != ERROR_SUCCESS) break;
1560
1561                     item = HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentEnumItem));
1562                     if (!item) { hr = E_OUTOFMEMORY; break; }
1563
1564                     hr = CLSIDFromString(guidstring, &clsid);
1565                     if (SUCCEEDED(hr))
1566                     {
1567                         hr = CreateComponentInfo(&clsid, (IWICComponentInfo**)&item->unk);
1568                         if (SUCCEEDED(hr))
1569                             list_add_tail(&This->objects, &item->entry);
1570                     }
1571
1572                     if (FAILED(hr))
1573                     {
1574                         HeapFree(GetProcessHeap(), 0, item);
1575                         hr = S_OK;
1576                     }
1577                 }
1578                 RegCloseKey(instancekey);
1579             }
1580             RegCloseKey(catidkey);
1581         }
1582         if (res != ERROR_SUCCESS && res != ERROR_NO_MORE_ITEMS)
1583             hr = HRESULT_FROM_WIN32(res);
1584     }
1585     RegCloseKey(clsidkey);
1586
1587     if (SUCCEEDED(hr))
1588     {
1589         IEnumUnknown_Reset((IEnumUnknown*)This);
1590         *ppIEnumUnknown = (IEnumUnknown*)This;
1591     }
1592     else
1593     {
1594         *ppIEnumUnknown = NULL;
1595         IUnknown_Release((IUnknown*)This);
1596     }
1597
1598     return hr;
1599 }
1600
1601 HRESULT WINAPI WICConvertBitmapSource(REFWICPixelFormatGUID dstFormat, IWICBitmapSource *pISrc, IWICBitmapSource **ppIDst)
1602 {
1603     HRESULT res;
1604     IEnumUnknown *enumconverters;
1605     IUnknown *unkconverterinfo;
1606     IWICFormatConverterInfo *converterinfo=NULL;
1607     IWICFormatConverter *converter=NULL;
1608     GUID srcFormat;
1609     WCHAR srcformatstr[39], dstformatstr[39];
1610     BOOL canconvert;
1611     ULONG num_fetched;
1612
1613     res = IWICBitmapSource_GetPixelFormat(pISrc, &srcFormat);
1614     if (FAILED(res)) return res;
1615
1616     if (IsEqualGUID(&srcFormat, dstFormat))
1617     {
1618         IWICBitmapSource_AddRef(pISrc);
1619         *ppIDst = pISrc;
1620         return S_OK;
1621     }
1622
1623     StringFromGUID2(&srcFormat, srcformatstr, 39);
1624     StringFromGUID2(dstFormat, dstformatstr, 39);
1625
1626     res = CreateComponentEnumerator(WICPixelFormatConverter, 0, &enumconverters);
1627     if (FAILED(res)) return res;
1628
1629     while (!converter)
1630     {
1631         res = IEnumUnknown_Next(enumconverters, 1, &unkconverterinfo, &num_fetched);
1632
1633         if (res == S_OK)
1634         {
1635             res = IUnknown_QueryInterface(unkconverterinfo, &IID_IWICFormatConverterInfo, (void**)&converterinfo);
1636
1637             if (SUCCEEDED(res))
1638             {
1639                 canconvert = ConverterSupportsFormat(converterinfo, srcformatstr);
1640
1641                 if (canconvert)
1642                     canconvert = ConverterSupportsFormat(converterinfo, dstformatstr);
1643
1644                 if (canconvert)
1645                 {
1646                     res = IWICFormatConverterInfo_CreateInstance(converterinfo, &converter);
1647
1648                     if (SUCCEEDED(res))
1649                         res = IWICFormatConverter_CanConvert(converter, &srcFormat, dstFormat, &canconvert);
1650
1651                     if (SUCCEEDED(res) && canconvert)
1652                         res = IWICFormatConverter_Initialize(converter, pISrc, dstFormat, WICBitmapDitherTypeNone,
1653                             NULL, 0.0, WICBitmapPaletteTypeCustom);
1654
1655                     if (FAILED(res) || !canconvert)
1656                     {
1657                         if (converter)
1658                         {
1659                             IWICFormatConverter_Release(converter);
1660                             converter = NULL;
1661                         }
1662                         res = S_OK;
1663                     }
1664                 }
1665
1666                 IWICFormatConverterInfo_Release(converterinfo);
1667             }
1668
1669             IUnknown_Release(unkconverterinfo);
1670         }
1671         else
1672             break;
1673     }
1674
1675     IEnumUnknown_Release(enumconverters);
1676
1677     if (converter)
1678     {
1679         *ppIDst = (IWICBitmapSource*)converter;
1680         return S_OK;
1681     }
1682     else
1683     {
1684         FIXME("cannot convert %s to %s\n", debugstr_guid(&srcFormat), debugstr_guid(dstFormat));
1685         *ppIDst = NULL;
1686         return WINCODEC_ERR_COMPONENTNOTFOUND;
1687     }
1688 }