winspool: Remove unused code.
[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 WCHAR const mimetypes_valuename[] = {'M','i','m','e','T','y','p','e','s',0};
40 static WCHAR const pixelformats_keyname[] = {'P','i','x','e','l','F','o','r','m','a','t','s',0};
41
42 static HRESULT ComponentInfo_GetStringValue(HKEY classkey, LPCWSTR value,
43     UINT buffer_size, WCHAR *buffer, UINT *actual_size)
44 {
45     LONG ret;
46     DWORD cbdata=buffer_size * sizeof(WCHAR);
47
48     if (!actual_size)
49         return E_INVALIDARG;
50
51     ret = RegGetValueW(classkey, NULL, value, RRF_RT_REG_SZ|RRF_NOEXPAND, NULL,
52         buffer, &cbdata);
53
54     if (ret == 0 || ret == ERROR_MORE_DATA)
55         *actual_size = cbdata/sizeof(WCHAR);
56
57     if (!buffer && buffer_size != 0)
58         /* Yes, native returns the correct size in this case. */
59         return E_INVALIDARG;
60
61     if (ret == ERROR_MORE_DATA)
62         return WINCODEC_ERR_INSUFFICIENTBUFFER;
63
64     return HRESULT_FROM_WIN32(ret);
65 }
66
67 typedef struct {
68     const IWICBitmapDecoderInfoVtbl *lpIWICBitmapDecoderInfoVtbl;
69     LONG ref;
70     HKEY classkey;
71     CLSID clsid;
72 } BitmapDecoderInfo;
73
74 static HRESULT WINAPI BitmapDecoderInfo_QueryInterface(IWICBitmapDecoderInfo *iface, REFIID iid,
75     void **ppv)
76 {
77     BitmapDecoderInfo *This = (BitmapDecoderInfo*)iface;
78     TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
79
80     if (!ppv) return E_INVALIDARG;
81
82     if (IsEqualIID(&IID_IUnknown, iid) ||
83         IsEqualIID(&IID_IWICComponentInfo, iid) ||
84         IsEqualIID(&IID_IWICBitmapCodecInfo, iid) ||
85         IsEqualIID(&IID_IWICBitmapDecoderInfo ,iid))
86     {
87         *ppv = This;
88     }
89     else
90     {
91         *ppv = NULL;
92         return E_NOINTERFACE;
93     }
94
95     IUnknown_AddRef((IUnknown*)*ppv);
96     return S_OK;
97 }
98
99 static ULONG WINAPI BitmapDecoderInfo_AddRef(IWICBitmapDecoderInfo *iface)
100 {
101     BitmapDecoderInfo *This = (BitmapDecoderInfo*)iface;
102     ULONG ref = InterlockedIncrement(&This->ref);
103
104     TRACE("(%p) refcount=%u\n", iface, ref);
105
106     return ref;
107 }
108
109 static ULONG WINAPI BitmapDecoderInfo_Release(IWICBitmapDecoderInfo *iface)
110 {
111     BitmapDecoderInfo *This = (BitmapDecoderInfo*)iface;
112     ULONG ref = InterlockedDecrement(&This->ref);
113
114     TRACE("(%p) refcount=%u\n", iface, ref);
115
116     if (ref == 0)
117     {
118         RegCloseKey(This->classkey);
119         HeapFree(GetProcessHeap(), 0, This);
120     }
121
122     return ref;
123 }
124
125 static HRESULT WINAPI BitmapDecoderInfo_GetComponentType(IWICBitmapDecoderInfo *iface,
126     WICComponentType *pType)
127 {
128     TRACE("(%p,%p)\n", iface, pType);
129     *pType = WICDecoder;
130     return S_OK;
131 }
132
133 static HRESULT WINAPI BitmapDecoderInfo_GetCLSID(IWICBitmapDecoderInfo *iface, CLSID *pclsid)
134 {
135     BitmapDecoderInfo *This = (BitmapDecoderInfo*)iface;
136     TRACE("(%p,%p)\n", iface, pclsid);
137
138     if (!pclsid)
139         return E_INVALIDARG;
140
141     memcpy(pclsid, &This->clsid, sizeof(CLSID));
142
143     return S_OK;
144 }
145
146 static HRESULT WINAPI BitmapDecoderInfo_GetSigningStatus(IWICBitmapDecoderInfo *iface, DWORD *pStatus)
147 {
148     FIXME("(%p,%p): stub\n", iface, pStatus);
149     return E_NOTIMPL;
150 }
151
152 static HRESULT WINAPI BitmapDecoderInfo_GetAuthor(IWICBitmapDecoderInfo *iface, UINT cchAuthor,
153     WCHAR *wzAuthor, UINT *pcchActual)
154 {
155     FIXME("(%p,%u,%p,%p): stub\n", iface, cchAuthor, wzAuthor, pcchActual);
156     return E_NOTIMPL;
157 }
158
159 static HRESULT WINAPI BitmapDecoderInfo_GetVendorGUID(IWICBitmapDecoderInfo *iface, GUID *pguidVendor)
160 {
161     FIXME("(%p,%p): stub\n", iface, pguidVendor);
162     return E_NOTIMPL;
163 }
164
165 static HRESULT WINAPI BitmapDecoderInfo_GetVersion(IWICBitmapDecoderInfo *iface, UINT cchVersion,
166     WCHAR *wzVersion, UINT *pcchActual)
167 {
168     FIXME("(%p,%u,%p,%p): stub\n", iface, cchVersion, wzVersion, pcchActual);
169     return E_NOTIMPL;
170 }
171
172 static HRESULT WINAPI BitmapDecoderInfo_GetSpecVersion(IWICBitmapDecoderInfo *iface, UINT cchSpecVersion,
173     WCHAR *wzSpecVersion, UINT *pcchActual)
174 {
175     FIXME("(%p,%u,%p,%p): stub\n", iface, cchSpecVersion, wzSpecVersion, pcchActual);
176     return E_NOTIMPL;
177 }
178
179 static HRESULT WINAPI BitmapDecoderInfo_GetFriendlyName(IWICBitmapDecoderInfo *iface, UINT cchFriendlyName,
180     WCHAR *wzFriendlyName, UINT *pcchActual)
181 {
182     FIXME("(%p,%u,%p,%p): stub\n", iface, cchFriendlyName, wzFriendlyName, pcchActual);
183     return E_NOTIMPL;
184 }
185
186 static HRESULT WINAPI BitmapDecoderInfo_GetContainerFormat(IWICBitmapDecoderInfo *iface,
187     GUID *pguidContainerFormat)
188 {
189     FIXME("(%p,%p): stub\n", iface, pguidContainerFormat);
190     return E_NOTIMPL;
191 }
192
193 static HRESULT WINAPI BitmapDecoderInfo_GetPixelFormats(IWICBitmapDecoderInfo *iface,
194     UINT cFormats, GUID *pguidPixelFormats, UINT *pcActual)
195 {
196     FIXME("(%p,%u,%p,%p): stub\n", iface, cFormats, pguidPixelFormats, pcActual);
197     return E_NOTIMPL;
198 }
199
200 static HRESULT WINAPI BitmapDecoderInfo_GetColorManagementVersion(IWICBitmapDecoderInfo *iface,
201     UINT cchColorManagementVersion, WCHAR *wzColorManagementVersion, UINT *pcchActual)
202 {
203     FIXME("(%p,%u,%p,%p): stub\n", iface, cchColorManagementVersion, wzColorManagementVersion, pcchActual);
204     return E_NOTIMPL;
205 }
206
207 static HRESULT WINAPI BitmapDecoderInfo_GetDeviceManufacturer(IWICBitmapDecoderInfo *iface,
208     UINT cchDeviceManufacturer, WCHAR *wzDeviceManufacturer, UINT *pcchActual)
209 {
210     FIXME("(%p,%u,%p,%p): stub\n", iface, cchDeviceManufacturer, wzDeviceManufacturer, pcchActual);
211     return E_NOTIMPL;
212 }
213
214 static HRESULT WINAPI BitmapDecoderInfo_GetDeviceModels(IWICBitmapDecoderInfo *iface,
215     UINT cchDeviceModels, WCHAR *wzDeviceModels, UINT *pcchActual)
216 {
217     FIXME("(%p,%u,%p,%p): stub\n", iface, cchDeviceModels, wzDeviceModels, pcchActual);
218     return E_NOTIMPL;
219 }
220
221 static HRESULT WINAPI BitmapDecoderInfo_GetMimeTypes(IWICBitmapDecoderInfo *iface,
222     UINT cchMimeTypes, WCHAR *wzMimeTypes, UINT *pcchActual)
223 {
224     BitmapDecoderInfo *This = (BitmapDecoderInfo*)iface;
225
226     TRACE("(%p,%u,%p,%p)\n", iface, cchMimeTypes, wzMimeTypes, pcchActual);
227
228     return ComponentInfo_GetStringValue(This->classkey, mimetypes_valuename,
229         cchMimeTypes, wzMimeTypes, pcchActual);
230 }
231
232 static HRESULT WINAPI BitmapDecoderInfo_GetFileExtensions(IWICBitmapDecoderInfo *iface,
233     UINT cchFileExtensions, WCHAR *wzFileExtensions, UINT *pcchActual)
234 {
235     FIXME("(%p,%u,%p,%p): stub\n", iface, cchFileExtensions, wzFileExtensions, pcchActual);
236     return E_NOTIMPL;
237 }
238
239 static HRESULT WINAPI BitmapDecoderInfo_DoesSupportAnimation(IWICBitmapDecoderInfo *iface,
240     BOOL *pfSupportAnimation)
241 {
242     FIXME("(%p,%p): stub\n", iface, pfSupportAnimation);
243     return E_NOTIMPL;
244 }
245
246 static HRESULT WINAPI BitmapDecoderInfo_DoesSupportChromaKey(IWICBitmapDecoderInfo *iface,
247     BOOL *pfSupportChromaKey)
248 {
249     FIXME("(%p,%p): stub\n", iface, pfSupportChromaKey);
250     return E_NOTIMPL;
251 }
252
253 static HRESULT WINAPI BitmapDecoderInfo_DoesSupportLossless(IWICBitmapDecoderInfo *iface,
254     BOOL *pfSupportLossless)
255 {
256     FIXME("(%p,%p): stub\n", iface, pfSupportLossless);
257     return E_NOTIMPL;
258 }
259
260 static HRESULT WINAPI BitmapDecoderInfo_DoesSupportMultiframe(IWICBitmapDecoderInfo *iface,
261     BOOL *pfSupportMultiframe)
262 {
263     FIXME("(%p,%p): stub\n", iface, pfSupportMultiframe);
264     return E_NOTIMPL;
265 }
266
267 static HRESULT WINAPI BitmapDecoderInfo_MatchesMimeType(IWICBitmapDecoderInfo *iface,
268     LPCWSTR wzMimeType, BOOL *pfMatches)
269 {
270     FIXME("(%p,%s,%p): stub\n", iface, debugstr_w(wzMimeType), pfMatches);
271     return E_NOTIMPL;
272 }
273
274 static HRESULT WINAPI BitmapDecoderInfo_GetPatterns(IWICBitmapDecoderInfo *iface,
275     UINT cbSizePatterns, WICBitmapPattern *pPatterns, UINT *pcPatterns, UINT *pcbPatternsActual)
276 {
277     BitmapDecoderInfo *This = (BitmapDecoderInfo*)iface;
278     UINT pattern_count=0, patterns_size=0;
279     WCHAR subkeyname[11];
280     LONG res;
281     HKEY patternskey, patternkey;
282     static const WCHAR uintformatW[] = {'%','u',0};
283     static const WCHAR patternsW[] = {'P','a','t','t','e','r','n','s',0};
284     static const WCHAR positionW[] = {'P','o','s','i','t','i','o','n',0};
285     static const WCHAR lengthW[] = {'L','e','n','g','t','h',0};
286     static const WCHAR patternW[] = {'P','a','t','t','e','r','n',0};
287     static const WCHAR maskW[] = {'M','a','s','k',0};
288     static const WCHAR endofstreamW[] = {'E','n','d','O','f','S','t','r','e','a','m',0};
289     HRESULT hr=S_OK;
290     UINT i;
291     BYTE *bPatterns=(BYTE*)pPatterns;
292     DWORD length, valuesize;
293
294     TRACE("(%p,%i,%p,%p,%p)\n", iface, cbSizePatterns, pPatterns, pcPatterns, pcbPatternsActual);
295
296     res = RegOpenKeyExW(This->classkey, patternsW, 0, KEY_READ, &patternskey);
297     if (res != ERROR_SUCCESS) return HRESULT_FROM_WIN32(res);
298
299     res = RegQueryInfoKeyW(patternskey, NULL, NULL, NULL, &pattern_count, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
300     if (res == ERROR_SUCCESS)
301     {
302         patterns_size = pattern_count * sizeof(WICBitmapPattern);
303
304         for (i=0; i<pattern_count; i++)
305         {
306             snprintfW(subkeyname, 11, uintformatW, i);
307             res = RegOpenKeyExW(patternskey, subkeyname, 0, KEY_READ, &patternkey);
308             if (res == ERROR_SUCCESS)
309             {
310                 valuesize = sizeof(ULONG);
311                 res = RegGetValueW(patternkey, NULL, lengthW, RRF_RT_DWORD, NULL,
312                     &length, &valuesize);
313                 patterns_size += length*2;
314
315                 if ((cbSizePatterns >= patterns_size) && (res == ERROR_SUCCESS))
316                 {
317                     pPatterns[i].Length = length;
318
319                     pPatterns[i].EndOfStream = 0;
320                     valuesize = sizeof(BOOL);
321                     RegGetValueW(patternkey, NULL, endofstreamW, RRF_RT_DWORD, NULL,
322                         &pPatterns[i].EndOfStream, &valuesize);
323
324                     pPatterns[i].Position.QuadPart = 0;
325                     valuesize = sizeof(ULARGE_INTEGER);
326                     res = RegGetValueW(patternkey, NULL, positionW, RRF_RT_DWORD|RRF_RT_QWORD, NULL,
327                         &pPatterns[i].Position, &valuesize);
328
329                     if (res == ERROR_SUCCESS)
330                     {
331                         pPatterns[i].Pattern = bPatterns+patterns_size-length*2;
332                         valuesize = length;
333                         res = RegGetValueW(patternkey, NULL, patternW, RRF_RT_REG_BINARY, NULL,
334                             pPatterns[i].Pattern, &valuesize);
335                     }
336
337                     if (res == ERROR_SUCCESS)
338                     {
339                         pPatterns[i].Mask = bPatterns+patterns_size-length;
340                         valuesize = length;
341                         res = RegGetValueW(patternkey, NULL, maskW, RRF_RT_REG_BINARY, NULL,
342                             pPatterns[i].Mask, &valuesize);
343                     }
344                 }
345
346                 RegCloseKey(patternkey);
347             }
348             if (res != ERROR_SUCCESS)
349             {
350                 hr = HRESULT_FROM_WIN32(res);
351                 break;
352             }
353         }
354     }
355     else hr = HRESULT_FROM_WIN32(res);
356
357     RegCloseKey(patternskey);
358
359     if (hr == S_OK)
360     {
361         *pcPatterns = pattern_count;
362         *pcbPatternsActual = patterns_size;
363         if (pPatterns && cbSizePatterns < patterns_size)
364             hr = WINCODEC_ERR_INSUFFICIENTBUFFER;
365     }
366
367     return hr;
368 }
369
370 static HRESULT WINAPI BitmapDecoderInfo_MatchesPattern(IWICBitmapDecoderInfo *iface,
371     IStream *pIStream, BOOL *pfMatches)
372 {
373     WICBitmapPattern *patterns;
374     UINT pattern_count=0, patterns_size=0;
375     HRESULT hr;
376     int i, pos;
377     BYTE *data=NULL;
378     ULONG datasize=0;
379     ULONG bytesread;
380     LARGE_INTEGER seekpos;
381
382     TRACE("(%p,%p,%p)\n", iface, pIStream, pfMatches);
383
384     hr = BitmapDecoderInfo_GetPatterns(iface, 0, NULL, &pattern_count, &patterns_size);
385     if (FAILED(hr)) return hr;
386
387     patterns = HeapAlloc(GetProcessHeap(), 0, patterns_size);
388     if (!patterns) return E_OUTOFMEMORY;
389
390     hr = BitmapDecoderInfo_GetPatterns(iface, patterns_size, patterns, &pattern_count, &patterns_size);
391     if (FAILED(hr)) goto end;
392
393     for (i=0; i<pattern_count; i++)
394     {
395         if (datasize < patterns[i].Length)
396         {
397             HeapFree(GetProcessHeap(), 0, data);
398             datasize = patterns[i].Length;
399             data = HeapAlloc(GetProcessHeap(), 0, patterns[i].Length);
400             if (!data)
401             {
402                 hr = E_OUTOFMEMORY;
403                 break;
404             }
405         }
406
407         if (patterns[i].EndOfStream)
408             seekpos.QuadPart = -patterns[i].Position.QuadPart;
409         else
410             seekpos.QuadPart = patterns[i].Position.QuadPart;
411         hr = IStream_Seek(pIStream, seekpos, patterns[i].EndOfStream ? STREAM_SEEK_END : STREAM_SEEK_SET, NULL);
412         if (hr == STG_E_INVALIDFUNCTION) continue; /* before start of stream */
413         if (FAILED(hr)) break;
414
415         hr = IStream_Read(pIStream, data, patterns[i].Length, &bytesread);
416         if (hr == S_FALSE || (hr == S_OK && bytesread != patterns[i].Length)) /* past end of stream */
417             continue;
418         if (FAILED(hr)) break;
419
420         for (pos=0; pos<patterns[i].Length; pos++)
421         {
422             if ((data[pos] & patterns[i].Mask[pos]) != patterns[i].Pattern[pos])
423                 break;
424         }
425         if (pos == patterns[i].Length) /* matches pattern */
426         {
427             hr = S_OK;
428             *pfMatches = TRUE;
429             break;
430         }
431     }
432
433     if (i == pattern_count) /* does not match any pattern */
434     {
435         hr = S_OK;
436         *pfMatches = FALSE;
437     }
438
439 end:
440     HeapFree(GetProcessHeap(), 0, patterns);
441     HeapFree(GetProcessHeap(), 0, data);
442
443     return hr;
444 }
445
446 static HRESULT WINAPI BitmapDecoderInfo_CreateInstance(IWICBitmapDecoderInfo *iface,
447     IWICBitmapDecoder **ppIBitmapDecoder)
448 {
449     BitmapDecoderInfo *This = (BitmapDecoderInfo*)iface;
450
451     TRACE("(%p,%p)\n", iface, ppIBitmapDecoder);
452
453     return CoCreateInstance(&This->clsid, NULL, CLSCTX_INPROC_SERVER,
454         &IID_IWICBitmapDecoder, (void**)ppIBitmapDecoder);
455 }
456
457 static const IWICBitmapDecoderInfoVtbl BitmapDecoderInfo_Vtbl = {
458     BitmapDecoderInfo_QueryInterface,
459     BitmapDecoderInfo_AddRef,
460     BitmapDecoderInfo_Release,
461     BitmapDecoderInfo_GetComponentType,
462     BitmapDecoderInfo_GetCLSID,
463     BitmapDecoderInfo_GetSigningStatus,
464     BitmapDecoderInfo_GetAuthor,
465     BitmapDecoderInfo_GetVendorGUID,
466     BitmapDecoderInfo_GetVersion,
467     BitmapDecoderInfo_GetSpecVersion,
468     BitmapDecoderInfo_GetFriendlyName,
469     BitmapDecoderInfo_GetContainerFormat,
470     BitmapDecoderInfo_GetPixelFormats,
471     BitmapDecoderInfo_GetColorManagementVersion,
472     BitmapDecoderInfo_GetDeviceManufacturer,
473     BitmapDecoderInfo_GetDeviceModels,
474     BitmapDecoderInfo_GetMimeTypes,
475     BitmapDecoderInfo_GetFileExtensions,
476     BitmapDecoderInfo_DoesSupportAnimation,
477     BitmapDecoderInfo_DoesSupportChromaKey,
478     BitmapDecoderInfo_DoesSupportLossless,
479     BitmapDecoderInfo_DoesSupportMultiframe,
480     BitmapDecoderInfo_MatchesMimeType,
481     BitmapDecoderInfo_GetPatterns,
482     BitmapDecoderInfo_MatchesPattern,
483     BitmapDecoderInfo_CreateInstance
484 };
485
486 static HRESULT BitmapDecoderInfo_Constructor(HKEY classkey, REFCLSID clsid, IWICComponentInfo **ppIInfo)
487 {
488     BitmapDecoderInfo *This;
489
490     This = HeapAlloc(GetProcessHeap(), 0, sizeof(BitmapDecoderInfo));
491     if (!This)
492     {
493         RegCloseKey(classkey);
494         return E_OUTOFMEMORY;
495     }
496
497     This->lpIWICBitmapDecoderInfoVtbl = &BitmapDecoderInfo_Vtbl;
498     This->ref = 1;
499     This->classkey = classkey;
500     memcpy(&This->clsid, clsid, sizeof(CLSID));
501
502     *ppIInfo = (IWICComponentInfo*)This;
503     return S_OK;
504 }
505
506 typedef struct {
507     const IWICBitmapEncoderInfoVtbl *lpIWICBitmapEncoderInfoVtbl;
508     LONG ref;
509     HKEY classkey;
510     CLSID clsid;
511 } BitmapEncoderInfo;
512
513 static HRESULT WINAPI BitmapEncoderInfo_QueryInterface(IWICBitmapEncoderInfo *iface, REFIID iid,
514     void **ppv)
515 {
516     BitmapEncoderInfo *This = (BitmapEncoderInfo*)iface;
517     TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
518
519     if (!ppv) return E_INVALIDARG;
520
521     if (IsEqualIID(&IID_IUnknown, iid) ||
522         IsEqualIID(&IID_IWICComponentInfo, iid) ||
523         IsEqualIID(&IID_IWICBitmapCodecInfo, iid) ||
524         IsEqualIID(&IID_IWICBitmapEncoderInfo ,iid))
525     {
526         *ppv = This;
527     }
528     else
529     {
530         *ppv = NULL;
531         return E_NOINTERFACE;
532     }
533
534     IUnknown_AddRef((IUnknown*)*ppv);
535     return S_OK;
536 }
537
538 static ULONG WINAPI BitmapEncoderInfo_AddRef(IWICBitmapEncoderInfo *iface)
539 {
540     BitmapEncoderInfo *This = (BitmapEncoderInfo*)iface;
541     ULONG ref = InterlockedIncrement(&This->ref);
542
543     TRACE("(%p) refcount=%u\n", iface, ref);
544
545     return ref;
546 }
547
548 static ULONG WINAPI BitmapEncoderInfo_Release(IWICBitmapEncoderInfo *iface)
549 {
550     BitmapEncoderInfo *This = (BitmapEncoderInfo*)iface;
551     ULONG ref = InterlockedDecrement(&This->ref);
552
553     TRACE("(%p) refcount=%u\n", iface, ref);
554
555     if (ref == 0)
556     {
557         RegCloseKey(This->classkey);
558         HeapFree(GetProcessHeap(), 0, This);
559     }
560
561     return ref;
562 }
563
564 static HRESULT WINAPI BitmapEncoderInfo_GetComponentType(IWICBitmapEncoderInfo *iface,
565     WICComponentType *pType)
566 {
567     TRACE("(%p,%p)\n", iface, pType);
568     *pType = WICEncoder;
569     return S_OK;
570 }
571
572 static HRESULT WINAPI BitmapEncoderInfo_GetCLSID(IWICBitmapEncoderInfo *iface, CLSID *pclsid)
573 {
574     BitmapEncoderInfo *This = (BitmapEncoderInfo*)iface;
575     TRACE("(%p,%p)\n", iface, pclsid);
576
577     if (!pclsid)
578         return E_INVALIDARG;
579
580     memcpy(pclsid, &This->clsid, sizeof(CLSID));
581
582     return S_OK;
583 }
584
585 static HRESULT WINAPI BitmapEncoderInfo_GetSigningStatus(IWICBitmapEncoderInfo *iface, DWORD *pStatus)
586 {
587     FIXME("(%p,%p): stub\n", iface, pStatus);
588     return E_NOTIMPL;
589 }
590
591 static HRESULT WINAPI BitmapEncoderInfo_GetAuthor(IWICBitmapEncoderInfo *iface, UINT cchAuthor,
592     WCHAR *wzAuthor, UINT *pcchActual)
593 {
594     FIXME("(%p,%u,%p,%p): stub\n", iface, cchAuthor, wzAuthor, pcchActual);
595     return E_NOTIMPL;
596 }
597
598 static HRESULT WINAPI BitmapEncoderInfo_GetVendorGUID(IWICBitmapEncoderInfo *iface, GUID *pguidVendor)
599 {
600     FIXME("(%p,%p): stub\n", iface, pguidVendor);
601     return E_NOTIMPL;
602 }
603
604 static HRESULT WINAPI BitmapEncoderInfo_GetVersion(IWICBitmapEncoderInfo *iface, UINT cchVersion,
605     WCHAR *wzVersion, UINT *pcchActual)
606 {
607     FIXME("(%p,%u,%p,%p): stub\n", iface, cchVersion, wzVersion, pcchActual);
608     return E_NOTIMPL;
609 }
610
611 static HRESULT WINAPI BitmapEncoderInfo_GetSpecVersion(IWICBitmapEncoderInfo *iface, UINT cchSpecVersion,
612     WCHAR *wzSpecVersion, UINT *pcchActual)
613 {
614     FIXME("(%p,%u,%p,%p): stub\n", iface, cchSpecVersion, wzSpecVersion, pcchActual);
615     return E_NOTIMPL;
616 }
617
618 static HRESULT WINAPI BitmapEncoderInfo_GetFriendlyName(IWICBitmapEncoderInfo *iface, UINT cchFriendlyName,
619     WCHAR *wzFriendlyName, UINT *pcchActual)
620 {
621     FIXME("(%p,%u,%p,%p): stub\n", iface, cchFriendlyName, wzFriendlyName, pcchActual);
622     return E_NOTIMPL;
623 }
624
625 static HRESULT WINAPI BitmapEncoderInfo_GetContainerFormat(IWICBitmapEncoderInfo *iface,
626     GUID *pguidContainerFormat)
627 {
628     FIXME("(%p,%p): stub\n", iface, pguidContainerFormat);
629     return E_NOTIMPL;
630 }
631
632 static HRESULT WINAPI BitmapEncoderInfo_GetPixelFormats(IWICBitmapEncoderInfo *iface,
633     UINT cFormats, GUID *pguidPixelFormats, UINT *pcActual)
634 {
635     FIXME("(%p,%u,%p,%p): stub\n", iface, cFormats, pguidPixelFormats, pcActual);
636     return E_NOTIMPL;
637 }
638
639 static HRESULT WINAPI BitmapEncoderInfo_GetColorManagementVersion(IWICBitmapEncoderInfo *iface,
640     UINT cchColorManagementVersion, WCHAR *wzColorManagementVersion, UINT *pcchActual)
641 {
642     FIXME("(%p,%u,%p,%p): stub\n", iface, cchColorManagementVersion, wzColorManagementVersion, pcchActual);
643     return E_NOTIMPL;
644 }
645
646 static HRESULT WINAPI BitmapEncoderInfo_GetDeviceManufacturer(IWICBitmapEncoderInfo *iface,
647     UINT cchDeviceManufacturer, WCHAR *wzDeviceManufacturer, UINT *pcchActual)
648 {
649     FIXME("(%p,%u,%p,%p): stub\n", iface, cchDeviceManufacturer, wzDeviceManufacturer, pcchActual);
650     return E_NOTIMPL;
651 }
652
653 static HRESULT WINAPI BitmapEncoderInfo_GetDeviceModels(IWICBitmapEncoderInfo *iface,
654     UINT cchDeviceModels, WCHAR *wzDeviceModels, UINT *pcchActual)
655 {
656     FIXME("(%p,%u,%p,%p): stub\n", iface, cchDeviceModels, wzDeviceModels, pcchActual);
657     return E_NOTIMPL;
658 }
659
660 static HRESULT WINAPI BitmapEncoderInfo_GetMimeTypes(IWICBitmapEncoderInfo *iface,
661     UINT cchMimeTypes, WCHAR *wzMimeTypes, UINT *pcchActual)
662 {
663     BitmapEncoderInfo *This = (BitmapEncoderInfo*)iface;
664
665     TRACE("(%p,%u,%p,%p)\n", iface, cchMimeTypes, wzMimeTypes, pcchActual);
666
667     return ComponentInfo_GetStringValue(This->classkey, mimetypes_valuename,
668         cchMimeTypes, wzMimeTypes, pcchActual);
669 }
670
671 static HRESULT WINAPI BitmapEncoderInfo_GetFileExtensions(IWICBitmapEncoderInfo *iface,
672     UINT cchFileExtensions, WCHAR *wzFileExtensions, UINT *pcchActual)
673 {
674     FIXME("(%p,%u,%p,%p): stub\n", iface, cchFileExtensions, wzFileExtensions, pcchActual);
675     return E_NOTIMPL;
676 }
677
678 static HRESULT WINAPI BitmapEncoderInfo_DoesSupportAnimation(IWICBitmapEncoderInfo *iface,
679     BOOL *pfSupportAnimation)
680 {
681     FIXME("(%p,%p): stub\n", iface, pfSupportAnimation);
682     return E_NOTIMPL;
683 }
684
685 static HRESULT WINAPI BitmapEncoderInfo_DoesSupportChromaKey(IWICBitmapEncoderInfo *iface,
686     BOOL *pfSupportChromaKey)
687 {
688     FIXME("(%p,%p): stub\n", iface, pfSupportChromaKey);
689     return E_NOTIMPL;
690 }
691
692 static HRESULT WINAPI BitmapEncoderInfo_DoesSupportLossless(IWICBitmapEncoderInfo *iface,
693     BOOL *pfSupportLossless)
694 {
695     FIXME("(%p,%p): stub\n", iface, pfSupportLossless);
696     return E_NOTIMPL;
697 }
698
699 static HRESULT WINAPI BitmapEncoderInfo_DoesSupportMultiframe(IWICBitmapEncoderInfo *iface,
700     BOOL *pfSupportMultiframe)
701 {
702     FIXME("(%p,%p): stub\n", iface, pfSupportMultiframe);
703     return E_NOTIMPL;
704 }
705
706 static HRESULT WINAPI BitmapEncoderInfo_MatchesMimeType(IWICBitmapEncoderInfo *iface,
707     LPCWSTR wzMimeType, BOOL *pfMatches)
708 {
709     FIXME("(%p,%s,%p): stub\n", iface, debugstr_w(wzMimeType), pfMatches);
710     return E_NOTIMPL;
711 }
712
713 static HRESULT WINAPI BitmapEncoderInfo_CreateInstance(IWICBitmapEncoderInfo *iface,
714     IWICBitmapEncoder **ppIBitmapEncoder)
715 {
716     BitmapEncoderInfo *This = (BitmapEncoderInfo*)iface;
717
718     TRACE("(%p,%p)\n", iface, ppIBitmapEncoder);
719
720     return CoCreateInstance(&This->clsid, NULL, CLSCTX_INPROC_SERVER,
721         &IID_IWICBitmapEncoder, (void**)ppIBitmapEncoder);
722 }
723
724 static const IWICBitmapEncoderInfoVtbl BitmapEncoderInfo_Vtbl = {
725     BitmapEncoderInfo_QueryInterface,
726     BitmapEncoderInfo_AddRef,
727     BitmapEncoderInfo_Release,
728     BitmapEncoderInfo_GetComponentType,
729     BitmapEncoderInfo_GetCLSID,
730     BitmapEncoderInfo_GetSigningStatus,
731     BitmapEncoderInfo_GetAuthor,
732     BitmapEncoderInfo_GetVendorGUID,
733     BitmapEncoderInfo_GetVersion,
734     BitmapEncoderInfo_GetSpecVersion,
735     BitmapEncoderInfo_GetFriendlyName,
736     BitmapEncoderInfo_GetContainerFormat,
737     BitmapEncoderInfo_GetPixelFormats,
738     BitmapEncoderInfo_GetColorManagementVersion,
739     BitmapEncoderInfo_GetDeviceManufacturer,
740     BitmapEncoderInfo_GetDeviceModels,
741     BitmapEncoderInfo_GetMimeTypes,
742     BitmapEncoderInfo_GetFileExtensions,
743     BitmapEncoderInfo_DoesSupportAnimation,
744     BitmapEncoderInfo_DoesSupportChromaKey,
745     BitmapEncoderInfo_DoesSupportLossless,
746     BitmapEncoderInfo_DoesSupportMultiframe,
747     BitmapEncoderInfo_MatchesMimeType,
748     BitmapEncoderInfo_CreateInstance
749 };
750
751 static HRESULT BitmapEncoderInfo_Constructor(HKEY classkey, REFCLSID clsid, IWICComponentInfo **ppIInfo)
752 {
753     BitmapEncoderInfo *This;
754
755     This = HeapAlloc(GetProcessHeap(), 0, sizeof(BitmapEncoderInfo));
756     if (!This)
757     {
758         RegCloseKey(classkey);
759         return E_OUTOFMEMORY;
760     }
761
762     This->lpIWICBitmapEncoderInfoVtbl = &BitmapEncoderInfo_Vtbl;
763     This->ref = 1;
764     This->classkey = classkey;
765     memcpy(&This->clsid, clsid, sizeof(CLSID));
766
767     *ppIInfo = (IWICComponentInfo*)This;
768     return S_OK;
769 }
770
771 typedef struct {
772     const IWICFormatConverterInfoVtbl *lpIWICFormatConverterInfoVtbl;
773     LONG ref;
774     HKEY classkey;
775     CLSID clsid;
776 } FormatConverterInfo;
777
778 static HRESULT WINAPI FormatConverterInfo_QueryInterface(IWICFormatConverterInfo *iface, REFIID iid,
779     void **ppv)
780 {
781     FormatConverterInfo *This = (FormatConverterInfo*)iface;
782     TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
783
784     if (!ppv) return E_INVALIDARG;
785
786     if (IsEqualIID(&IID_IUnknown, iid) ||
787         IsEqualIID(&IID_IWICComponentInfo, iid) ||
788         IsEqualIID(&IID_IWICFormatConverterInfo ,iid))
789     {
790         *ppv = This;
791     }
792     else
793     {
794         *ppv = NULL;
795         return E_NOINTERFACE;
796     }
797
798     IUnknown_AddRef((IUnknown*)*ppv);
799     return S_OK;
800 }
801
802 static ULONG WINAPI FormatConverterInfo_AddRef(IWICFormatConverterInfo *iface)
803 {
804     FormatConverterInfo *This = (FormatConverterInfo*)iface;
805     ULONG ref = InterlockedIncrement(&This->ref);
806
807     TRACE("(%p) refcount=%u\n", iface, ref);
808
809     return ref;
810 }
811
812 static ULONG WINAPI FormatConverterInfo_Release(IWICFormatConverterInfo *iface)
813 {
814     FormatConverterInfo *This = (FormatConverterInfo*)iface;
815     ULONG ref = InterlockedDecrement(&This->ref);
816
817     TRACE("(%p) refcount=%u\n", iface, ref);
818
819     if (ref == 0)
820     {
821         RegCloseKey(This->classkey);
822         HeapFree(GetProcessHeap(), 0, This);
823     }
824
825     return ref;
826 }
827
828 static HRESULT WINAPI FormatConverterInfo_GetComponentType(IWICFormatConverterInfo *iface,
829     WICComponentType *pType)
830 {
831     TRACE("(%p,%p)\n", iface, pType);
832     *pType = WICPixelFormatConverter;
833     return S_OK;
834 }
835
836 static HRESULT WINAPI FormatConverterInfo_GetCLSID(IWICFormatConverterInfo *iface, CLSID *pclsid)
837 {
838     FormatConverterInfo *This = (FormatConverterInfo*)iface;
839     TRACE("(%p,%p)\n", iface, pclsid);
840
841     if (!pclsid)
842         return E_INVALIDARG;
843
844     memcpy(pclsid, &This->clsid, sizeof(CLSID));
845
846     return S_OK;
847 }
848
849 static HRESULT WINAPI FormatConverterInfo_GetSigningStatus(IWICFormatConverterInfo *iface, DWORD *pStatus)
850 {
851     FIXME("(%p,%p): stub\n", iface, pStatus);
852     return E_NOTIMPL;
853 }
854
855 static HRESULT WINAPI FormatConverterInfo_GetAuthor(IWICFormatConverterInfo *iface, UINT cchAuthor,
856     WCHAR *wzAuthor, UINT *pcchActual)
857 {
858     FIXME("(%p,%u,%p,%p): stub\n", iface, cchAuthor, wzAuthor, pcchActual);
859     return E_NOTIMPL;
860 }
861
862 static HRESULT WINAPI FormatConverterInfo_GetVendorGUID(IWICFormatConverterInfo *iface, GUID *pguidVendor)
863 {
864     FIXME("(%p,%p): stub\n", iface, pguidVendor);
865     return E_NOTIMPL;
866 }
867
868 static HRESULT WINAPI FormatConverterInfo_GetVersion(IWICFormatConverterInfo *iface, UINT cchVersion,
869     WCHAR *wzVersion, UINT *pcchActual)
870 {
871     FIXME("(%p,%u,%p,%p): stub\n", iface, cchVersion, wzVersion, pcchActual);
872     return E_NOTIMPL;
873 }
874
875 static HRESULT WINAPI FormatConverterInfo_GetSpecVersion(IWICFormatConverterInfo *iface, UINT cchSpecVersion,
876     WCHAR *wzSpecVersion, UINT *pcchActual)
877 {
878     FIXME("(%p,%u,%p,%p): stub\n", iface, cchSpecVersion, wzSpecVersion, pcchActual);
879     return E_NOTIMPL;
880 }
881
882 static HRESULT WINAPI FormatConverterInfo_GetFriendlyName(IWICFormatConverterInfo *iface, UINT cchFriendlyName,
883     WCHAR *wzFriendlyName, UINT *pcchActual)
884 {
885     FIXME("(%p,%u,%p,%p): stub\n", iface, cchFriendlyName, wzFriendlyName, pcchActual);
886     return E_NOTIMPL;
887 }
888
889 static HRESULT WINAPI FormatConverterInfo_GetPixelFormats(IWICFormatConverterInfo *iface,
890     UINT cFormats, GUID *pguidPixelFormats, UINT *pcActual)
891 {
892     FIXME("(%p,%u,%p,%p): stub\n", iface, cFormats, pguidPixelFormats, pcActual);
893     return E_NOTIMPL;
894 }
895
896 static HRESULT WINAPI FormatConverterInfo_CreateInstance(IWICFormatConverterInfo *iface,
897     IWICFormatConverter **ppIFormatConverter)
898 {
899     FormatConverterInfo *This = (FormatConverterInfo*)iface;
900
901     TRACE("(%p,%p)\n", iface, ppIFormatConverter);
902
903     return CoCreateInstance(&This->clsid, NULL, CLSCTX_INPROC_SERVER,
904         &IID_IWICFormatConverter, (void**)ppIFormatConverter);
905 }
906
907 static BOOL ConverterSupportsFormat(IWICFormatConverterInfo *iface, const WCHAR *formatguid)
908 {
909     LONG res;
910     FormatConverterInfo *This = (FormatConverterInfo*)iface;
911     HKEY formats_key, guid_key;
912
913     /* Avoid testing using IWICFormatConverter_GetPixelFormats because that
914         would be O(n). A registry test should do better. */
915
916     res = RegOpenKeyExW(This->classkey, pixelformats_keyname, 0, KEY_READ, &formats_key);
917     if (res != ERROR_SUCCESS) return FALSE;
918
919     res = RegOpenKeyExW(formats_key, formatguid, 0, KEY_READ, &guid_key);
920     if (res == ERROR_SUCCESS) RegCloseKey(guid_key);
921
922     RegCloseKey(formats_key);
923
924     return (res == ERROR_SUCCESS);
925 }
926
927 static const IWICFormatConverterInfoVtbl FormatConverterInfo_Vtbl = {
928     FormatConverterInfo_QueryInterface,
929     FormatConverterInfo_AddRef,
930     FormatConverterInfo_Release,
931     FormatConverterInfo_GetComponentType,
932     FormatConverterInfo_GetCLSID,
933     FormatConverterInfo_GetSigningStatus,
934     FormatConverterInfo_GetAuthor,
935     FormatConverterInfo_GetVendorGUID,
936     FormatConverterInfo_GetVersion,
937     FormatConverterInfo_GetSpecVersion,
938     FormatConverterInfo_GetFriendlyName,
939     FormatConverterInfo_GetPixelFormats,
940     FormatConverterInfo_CreateInstance
941 };
942
943 static HRESULT FormatConverterInfo_Constructor(HKEY classkey, REFCLSID clsid, IWICComponentInfo **ppIInfo)
944 {
945     FormatConverterInfo *This;
946
947     This = HeapAlloc(GetProcessHeap(), 0, sizeof(FormatConverterInfo));
948     if (!This)
949     {
950         RegCloseKey(classkey);
951         return E_OUTOFMEMORY;
952     }
953
954     This->lpIWICFormatConverterInfoVtbl = &FormatConverterInfo_Vtbl;
955     This->ref = 1;
956     This->classkey = classkey;
957     memcpy(&This->clsid, clsid, sizeof(CLSID));
958
959     *ppIInfo = (IWICComponentInfo*)This;
960     return S_OK;
961 }
962
963 static WCHAR const clsid_keyname[] = {'C','L','S','I','D',0};
964 static WCHAR const instance_keyname[] = {'I','n','s','t','a','n','c','e',0};
965
966 struct category {
967     WICComponentType type;
968     const GUID *catid;
969     HRESULT (*constructor)(HKEY,REFCLSID,IWICComponentInfo**);
970 };
971
972 static const struct category categories[] = {
973     {WICDecoder, &CATID_WICBitmapDecoders, BitmapDecoderInfo_Constructor},
974     {WICEncoder, &CATID_WICBitmapEncoders, BitmapEncoderInfo_Constructor},
975     {WICPixelFormatConverter, &CATID_WICFormatConverters, FormatConverterInfo_Constructor},
976     {0}
977 };
978
979 HRESULT CreateComponentInfo(REFCLSID clsid, IWICComponentInfo **ppIInfo)
980 {
981     HKEY clsidkey;
982     HKEY classkey;
983     HKEY catidkey;
984     HKEY instancekey;
985     WCHAR guidstring[39];
986     LONG res;
987     const struct category *category;
988     int found=0;
989     HRESULT hr;
990
991     res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, KEY_READ, &clsidkey);
992     if (res != ERROR_SUCCESS)
993         return HRESULT_FROM_WIN32(res);
994
995     for (category=categories; category->type; category++)
996     {
997         StringFromGUID2(category->catid, guidstring, 39);
998         res = RegOpenKeyExW(clsidkey, guidstring, 0, KEY_READ, &catidkey);
999         if (res == ERROR_SUCCESS)
1000         {
1001             res = RegOpenKeyExW(catidkey, instance_keyname, 0, KEY_READ, &instancekey);
1002             if (res == ERROR_SUCCESS)
1003             {
1004                 StringFromGUID2(clsid, guidstring, 39);
1005                 res = RegOpenKeyExW(instancekey, guidstring, 0, KEY_READ, &classkey);
1006                 if (res == ERROR_SUCCESS)
1007                 {
1008                     RegCloseKey(classkey);
1009                     found = 1;
1010                 }
1011                 RegCloseKey(instancekey);
1012             }
1013             RegCloseKey(catidkey);
1014         }
1015         if (found) break;
1016     }
1017
1018     if (found)
1019     {
1020         res = RegOpenKeyExW(clsidkey, guidstring, 0, KEY_READ, &classkey);
1021         if (res == ERROR_SUCCESS)
1022             hr = category->constructor(classkey, clsid, ppIInfo);
1023         else
1024             hr = HRESULT_FROM_WIN32(res);
1025     }
1026     else
1027         hr = E_FAIL;
1028
1029     RegCloseKey(clsidkey);
1030
1031     return hr;
1032 }
1033
1034 typedef struct {
1035     const IEnumUnknownVtbl *IEnumUnknown_Vtbl;
1036     LONG ref;
1037     struct list objects;
1038     struct list *cursor;
1039     CRITICAL_SECTION lock; /* Must be held when reading or writing cursor */
1040 } ComponentEnum;
1041
1042 typedef struct {
1043     struct list entry;
1044     IUnknown *unk;
1045 } ComponentEnumItem;
1046
1047 static const IEnumUnknownVtbl ComponentEnumVtbl;
1048
1049 static HRESULT WINAPI ComponentEnum_QueryInterface(IEnumUnknown *iface, REFIID iid,
1050     void **ppv)
1051 {
1052     ComponentEnum *This = (ComponentEnum*)iface;
1053     TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
1054
1055     if (!ppv) return E_INVALIDARG;
1056
1057     if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IEnumUnknown, iid))
1058     {
1059         *ppv = This;
1060     }
1061     else
1062     {
1063         *ppv = NULL;
1064         return E_NOINTERFACE;
1065     }
1066
1067     IUnknown_AddRef((IUnknown*)*ppv);
1068     return S_OK;
1069 }
1070
1071 static ULONG WINAPI ComponentEnum_AddRef(IEnumUnknown *iface)
1072 {
1073     ComponentEnum *This = (ComponentEnum*)iface;
1074     ULONG ref = InterlockedIncrement(&This->ref);
1075
1076     TRACE("(%p) refcount=%u\n", iface, ref);
1077
1078     return ref;
1079 }
1080
1081 static ULONG WINAPI ComponentEnum_Release(IEnumUnknown *iface)
1082 {
1083     ComponentEnum *This = (ComponentEnum*)iface;
1084     ULONG ref = InterlockedDecrement(&This->ref);
1085     ComponentEnumItem *cursor, *cursor2;
1086
1087     TRACE("(%p) refcount=%u\n", iface, ref);
1088
1089     if (ref == 0)
1090     {
1091         LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, &This->objects, ComponentEnumItem, entry)
1092         {
1093             IUnknown_Release(cursor->unk);
1094             list_remove(&cursor->entry);
1095             HeapFree(GetProcessHeap(), 0, cursor);
1096         }
1097         This->lock.DebugInfo->Spare[0] = 0;
1098         DeleteCriticalSection(&This->lock);
1099         HeapFree(GetProcessHeap(), 0, This);
1100     }
1101
1102     return ref;
1103 }
1104
1105 static HRESULT WINAPI ComponentEnum_Next(IEnumUnknown *iface, ULONG celt,
1106     IUnknown **rgelt, ULONG *pceltFetched)
1107 {
1108     ComponentEnum *This = (ComponentEnum*)iface;
1109     int num_fetched=0;
1110     ComponentEnumItem *item;
1111     HRESULT hr=S_OK;
1112
1113     TRACE("(%p,%u,%p,%p)\n", iface, celt, rgelt, pceltFetched);
1114
1115     EnterCriticalSection(&This->lock);
1116     while (num_fetched<celt)
1117     {
1118         if (!This->cursor)
1119         {
1120             hr = S_FALSE;
1121             break;
1122         }
1123         item = LIST_ENTRY(This->cursor, ComponentEnumItem, entry);
1124         IUnknown_AddRef(item->unk);
1125         rgelt[num_fetched] = item->unk;
1126         num_fetched++;
1127         This->cursor = list_next(&This->objects, This->cursor);
1128     }
1129     LeaveCriticalSection(&This->lock);
1130     if (pceltFetched)
1131         *pceltFetched = num_fetched;
1132     return hr;
1133 }
1134
1135 static HRESULT WINAPI ComponentEnum_Skip(IEnumUnknown *iface, ULONG celt)
1136 {
1137     ComponentEnum *This = (ComponentEnum*)iface;
1138     int i;
1139     HRESULT hr=S_OK;
1140
1141     TRACE("(%p,%u)\n", iface, celt);
1142
1143     EnterCriticalSection(&This->lock);
1144     for (i=0; i<celt; i++)
1145     {
1146         if (!This->cursor)
1147         {
1148             hr = S_FALSE;
1149             break;
1150         }
1151         This->cursor = list_next(&This->objects, This->cursor);
1152     }
1153     LeaveCriticalSection(&This->lock);
1154     return hr;
1155 }
1156
1157 static HRESULT WINAPI ComponentEnum_Reset(IEnumUnknown *iface)
1158 {
1159     ComponentEnum *This = (ComponentEnum*)iface;
1160
1161     TRACE("(%p)\n", iface);
1162
1163     EnterCriticalSection(&This->lock);
1164     This->cursor = list_head(&This->objects);
1165     LeaveCriticalSection(&This->lock);
1166     return S_OK;
1167 }
1168
1169 static HRESULT WINAPI ComponentEnum_Clone(IEnumUnknown *iface, IEnumUnknown **ppenum)
1170 {
1171     ComponentEnum *This = (ComponentEnum*)iface;
1172     ComponentEnum *new_enum;
1173     ComponentEnumItem *old_item, *new_item;
1174     HRESULT ret=S_OK;
1175     struct list *old_cursor;
1176
1177     new_enum = HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentEnum));
1178     if (!new_enum)
1179     {
1180         *ppenum = NULL;
1181         return E_OUTOFMEMORY;
1182     }
1183
1184     new_enum->IEnumUnknown_Vtbl = &ComponentEnumVtbl;
1185     new_enum->ref = 1;
1186     new_enum->cursor = NULL;
1187     list_init(&new_enum->objects);
1188     InitializeCriticalSection(&new_enum->lock);
1189     new_enum->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": ComponentEnum.lock");
1190
1191     EnterCriticalSection(&This->lock);
1192     old_cursor = This->cursor;
1193     LeaveCriticalSection(&This->lock);
1194
1195     LIST_FOR_EACH_ENTRY(old_item, &This->objects, ComponentEnumItem, entry)
1196     {
1197         new_item = HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentEnumItem));
1198         if (!new_item)
1199         {
1200             ret = E_OUTOFMEMORY;
1201             break;
1202         }
1203         new_item->unk = old_item->unk;
1204         list_add_tail(&new_enum->objects, &new_item->entry);
1205         IUnknown_AddRef(new_item->unk);
1206         if (&old_item->entry == old_cursor) new_enum->cursor = &new_item->entry;
1207     }
1208
1209     if (FAILED(ret))
1210     {
1211         IUnknown_Release((IUnknown*)new_enum);
1212         *ppenum = NULL;
1213     }
1214     else
1215         *ppenum = (IEnumUnknown*)new_enum;
1216
1217     return ret;
1218 }
1219
1220 static const IEnumUnknownVtbl ComponentEnumVtbl = {
1221     ComponentEnum_QueryInterface,
1222     ComponentEnum_AddRef,
1223     ComponentEnum_Release,
1224     ComponentEnum_Next,
1225     ComponentEnum_Skip,
1226     ComponentEnum_Reset,
1227     ComponentEnum_Clone
1228 };
1229
1230 HRESULT CreateComponentEnumerator(DWORD componentTypes, DWORD options, IEnumUnknown **ppIEnumUnknown)
1231 {
1232     ComponentEnum *This;
1233     ComponentEnumItem *item;
1234     const struct category *category;
1235     HKEY clsidkey, catidkey, instancekey;
1236     WCHAR guidstring[39];
1237     LONG res;
1238     int i;
1239     HRESULT hr=S_OK;
1240     CLSID clsid;
1241
1242     if (options) FIXME("ignoring flags %x\n", options);
1243
1244     res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, KEY_READ, &clsidkey);
1245     if (res != ERROR_SUCCESS)
1246         return HRESULT_FROM_WIN32(res);
1247
1248     This = HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentEnum));
1249     if (!This)
1250     {
1251         RegCloseKey(clsidkey);
1252         return E_OUTOFMEMORY;
1253     }
1254
1255     This->IEnumUnknown_Vtbl = &ComponentEnumVtbl;
1256     This->ref = 1;
1257     list_init(&This->objects);
1258     InitializeCriticalSection(&This->lock);
1259     This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": ComponentEnum.lock");
1260
1261     for (category=categories; category->type && hr == S_OK; category++)
1262     {
1263         if ((category->type & componentTypes) == 0) continue;
1264         StringFromGUID2(category->catid, guidstring, 39);
1265         res = RegOpenKeyExW(clsidkey, guidstring, 0, KEY_READ, &catidkey);
1266         if (res == ERROR_SUCCESS)
1267         {
1268             res = RegOpenKeyExW(catidkey, instance_keyname, 0, KEY_READ, &instancekey);
1269             if (res == ERROR_SUCCESS)
1270             {
1271                 i=0;
1272                 for (;;i++)
1273                 {
1274                     DWORD guidstring_size = 39;
1275                     res = RegEnumKeyExW(instancekey, i, guidstring, &guidstring_size, NULL, NULL, NULL, NULL);
1276                     if (res != ERROR_SUCCESS) break;
1277
1278                     item = HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentEnumItem));
1279                     if (!item) { hr = E_OUTOFMEMORY; break; }
1280
1281                     hr = CLSIDFromString(guidstring, &clsid);
1282                     if (SUCCEEDED(hr))
1283                     {
1284                         hr = CreateComponentInfo(&clsid, (IWICComponentInfo**)&item->unk);
1285                         if (SUCCEEDED(hr))
1286                             list_add_tail(&This->objects, &item->entry);
1287                     }
1288
1289                     if (FAILED(hr))
1290                     {
1291                         HeapFree(GetProcessHeap(), 0, item);
1292                         hr = S_OK;
1293                     }
1294                 }
1295                 RegCloseKey(instancekey);
1296             }
1297             RegCloseKey(catidkey);
1298         }
1299         if (res != ERROR_SUCCESS && res != ERROR_NO_MORE_ITEMS)
1300             hr = HRESULT_FROM_WIN32(res);
1301     }
1302     RegCloseKey(clsidkey);
1303
1304     if (SUCCEEDED(hr))
1305     {
1306         IEnumUnknown_Reset((IEnumUnknown*)This);
1307         *ppIEnumUnknown = (IEnumUnknown*)This;
1308     }
1309     else
1310     {
1311         *ppIEnumUnknown = NULL;
1312         IUnknown_Release((IUnknown*)This);
1313     }
1314
1315     return hr;
1316 }
1317
1318 HRESULT WINAPI WICConvertBitmapSource(REFWICPixelFormatGUID dstFormat, IWICBitmapSource *pISrc, IWICBitmapSource **ppIDst)
1319 {
1320     HRESULT res;
1321     IEnumUnknown *enumconverters;
1322     IUnknown *unkconverterinfo;
1323     IWICFormatConverterInfo *converterinfo=NULL;
1324     IWICFormatConverter *converter=NULL;
1325     GUID srcFormat;
1326     WCHAR srcformatstr[39], dstformatstr[39];
1327     BOOL canconvert;
1328     ULONG num_fetched;
1329
1330     res = IWICBitmapSource_GetPixelFormat(pISrc, &srcFormat);
1331     if (FAILED(res)) return res;
1332
1333     if (IsEqualGUID(&srcFormat, dstFormat))
1334     {
1335         IWICBitmapSource_AddRef(pISrc);
1336         *ppIDst = pISrc;
1337         return S_OK;
1338     }
1339
1340     StringFromGUID2(&srcFormat, srcformatstr, 39);
1341     StringFromGUID2(dstFormat, dstformatstr, 39);
1342
1343     res = CreateComponentEnumerator(WICPixelFormatConverter, 0, &enumconverters);
1344     if (FAILED(res)) return res;
1345
1346     while (!converter)
1347     {
1348         res = IEnumUnknown_Next(enumconverters, 1, &unkconverterinfo, &num_fetched);
1349
1350         if (res == S_OK)
1351         {
1352             res = IUnknown_QueryInterface(unkconverterinfo, &IID_IWICFormatConverterInfo, (void**)&converterinfo);
1353
1354             if (SUCCEEDED(res))
1355             {
1356                 canconvert = ConverterSupportsFormat(converterinfo, srcformatstr);
1357
1358                 if (canconvert)
1359                     canconvert = ConverterSupportsFormat(converterinfo, dstformatstr);
1360
1361                 if (canconvert)
1362                 {
1363                     res = IWICFormatConverterInfo_CreateInstance(converterinfo, &converter);
1364
1365                     if (SUCCEEDED(res))
1366                         res = IWICFormatConverter_CanConvert(converter, &srcFormat, dstFormat, &canconvert);
1367
1368                     if (SUCCEEDED(res) && canconvert)
1369                         res = IWICFormatConverter_Initialize(converter, pISrc, dstFormat, WICBitmapDitherTypeNone,
1370                             NULL, 0.0, WICBitmapPaletteTypeCustom);
1371
1372                     if (FAILED(res) || !canconvert)
1373                     {
1374                         if (converter)
1375                         {
1376                             IWICFormatConverter_Release(converter);
1377                             converter = NULL;
1378                         }
1379                         res = S_OK;
1380                     }
1381                 }
1382
1383                 IWICFormatConverterInfo_Release(converterinfo);
1384             }
1385
1386             IUnknown_Release(unkconverterinfo);
1387         }
1388         else
1389             break;
1390     }
1391
1392     IEnumUnknown_Release(enumconverters);
1393
1394     if (converter)
1395     {
1396         *ppIDst = (IWICBitmapSource*)converter;
1397         return S_OK;
1398     }
1399     else
1400     {
1401         FIXME("cannot convert %s to %s\n", debugstr_guid(&srcFormat), debugstr_guid(dstFormat));
1402         *ppIDst = NULL;
1403         return WINCODEC_ERR_COMPONENTNOTFOUND;
1404     }
1405 }