makefiles: Output rules for building generated .rc files.
[wine.git] / dlls / windowscodecs / info.c
blobe131107e995bca48e26e32356d1afb409384b6f3
1 /*
2 * Copyright 2009 Vincent Povirk for CodeWeavers
3 * Copyright 2012 Dmitry Timoshkov
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include "config.h"
22 #include <stdarg.h>
24 #define COBJMACROS
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winreg.h"
29 #include "objbase.h"
31 #include "wincodecs_private.h"
33 #include "wine/debug.h"
34 #include "wine/unicode.h"
35 #include "wine/list.h"
36 #include "wine/rbtree.h"
37 #include "wine/heap.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
41 static const WCHAR mimetypes_valuename[] = {'M','i','m','e','T','y','p','e','s',0};
42 static const WCHAR author_valuename[] = {'A','u','t','h','o','r',0};
43 static const WCHAR friendlyname_valuename[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0};
44 static const WCHAR pixelformats_keyname[] = {'P','i','x','e','l','F','o','r','m','a','t','s',0};
45 static const WCHAR formats_keyname[] = {'F','o','r','m','a','t','s',0};
46 static const WCHAR containerformat_valuename[] = {'C','o','n','t','a','i','n','e','r','F','o','r','m','a','t',0};
47 static const WCHAR metadataformat_valuename[] = {'M','e','t','a','d','a','t','a','F','o','r','m','a','t',0};
48 static const WCHAR vendor_valuename[] = {'V','e','n','d','o','r',0};
49 static const WCHAR version_valuename[] = {'V','e','r','s','i','o','n',0};
50 static const WCHAR specversion_valuename[] = {'S','p','e','c','V','e','r','s','i','o','n',0};
51 static const WCHAR bitsperpixel_valuename[] = {'B','i','t','L','e','n','g','t','h',0};
52 static const WCHAR channelcount_valuename[] = {'C','h','a','n','n','e','l','C','o','u','n','t',0};
53 static const WCHAR channelmasks_keyname[] = {'C','h','a','n','n','e','l','M','a','s','k','s',0};
54 static const WCHAR numericrepresentation_valuename[] = {'N','u','m','e','r','i','c','R','e','p','r','e','s','e','n','t','a','t','i','o','n',0};
55 static const WCHAR supportstransparency_valuename[] = {'S','u','p','p','o','r','t','s','T','r','a','n','s','p','a','r','e','n','c','y',0};
56 static const WCHAR requiresfullstream_valuename[] = {'R','e','q','u','i','r','e','s','F','u','l','l','S','t','r','e','a','m',0};
57 static const WCHAR supportspadding_valuename[] = {'S','u','p','p','o','r','t','s','P','a','d','d','i','n','g',0};
58 static const WCHAR fileextensions_valuename[] = {'F','i','l','e','E','x','t','e','n','s','i','o','n','s',0};
59 static const WCHAR containers_keyname[] = {'C','o','n','t','a','i','n','e','r','s',0};
61 typedef struct {
62 IWICComponentInfo IWICComponentInfo_iface;
63 LONG ref;
64 CLSID clsid;
65 struct wine_rb_entry entry;
66 } ComponentInfo;
68 static HRESULT ComponentInfo_GetStringValue(HKEY classkey, LPCWSTR value,
69 UINT buffer_size, WCHAR *buffer, UINT *actual_size)
71 LONG ret;
72 DWORD cbdata=buffer_size * sizeof(WCHAR);
74 if (!actual_size)
75 return E_INVALIDARG;
77 ret = RegGetValueW(classkey, NULL, value, RRF_RT_REG_SZ|RRF_NOEXPAND, NULL,
78 buffer, &cbdata);
80 if (ret == ERROR_FILE_NOT_FOUND)
82 *actual_size = 0;
83 return S_OK;
86 if (ret == 0 || ret == ERROR_MORE_DATA)
87 *actual_size = cbdata/sizeof(WCHAR);
89 if (!buffer && buffer_size != 0)
90 /* Yes, native returns the correct size in this case. */
91 return E_INVALIDARG;
93 if (ret == ERROR_MORE_DATA)
94 return WINCODEC_ERR_INSUFFICIENTBUFFER;
96 return HRESULT_FROM_WIN32(ret);
99 static HRESULT ComponentInfo_GetGUIDValue(HKEY classkey, LPCWSTR value,
100 GUID *result)
102 LONG ret;
103 WCHAR guid_string[39];
104 DWORD cbdata = sizeof(guid_string);
105 HRESULT hr;
107 if (!result)
108 return E_INVALIDARG;
110 ret = RegGetValueW(classkey, NULL, value, RRF_RT_REG_SZ|RRF_NOEXPAND, NULL,
111 guid_string, &cbdata);
113 if (ret != ERROR_SUCCESS)
114 return HRESULT_FROM_WIN32(ret);
116 if (cbdata < sizeof(guid_string))
118 ERR("incomplete GUID value\n");
119 return E_FAIL;
122 hr = CLSIDFromString(guid_string, result);
124 return hr;
127 static HRESULT ComponentInfo_GetDWORDValue(HKEY classkey, LPCWSTR value,
128 DWORD *result)
130 LONG ret;
131 DWORD cbdata = sizeof(DWORD);
133 if (!result)
134 return E_INVALIDARG;
136 ret = RegGetValueW(classkey, NULL, value, RRF_RT_DWORD, NULL,
137 result, &cbdata);
139 if (ret == ERROR_FILE_NOT_FOUND)
141 *result = 0;
142 return S_OK;
145 return HRESULT_FROM_WIN32(ret);
148 static HRESULT ComponentInfo_GetGuidList(HKEY classkey, LPCWSTR subkeyname,
149 UINT buffersize, GUID *buffer, UINT *actual_size)
151 LONG ret;
152 HKEY subkey;
153 UINT items_returned;
154 WCHAR guid_string[39];
155 DWORD guid_string_size;
156 HRESULT hr=S_OK;
158 if (!actual_size)
159 return E_INVALIDARG;
161 ret = RegOpenKeyExW(classkey, subkeyname, 0, KEY_READ, &subkey);
162 if (ret == ERROR_FILE_NOT_FOUND)
164 *actual_size = 0;
165 return S_OK;
167 else if (ret != ERROR_SUCCESS) return HRESULT_FROM_WIN32(ret);
169 if (buffer)
171 items_returned = 0;
172 guid_string_size = 39;
173 while (items_returned < buffersize)
175 ret = RegEnumKeyExW(subkey, items_returned, guid_string,
176 &guid_string_size, NULL, NULL, NULL, NULL);
178 if (ret != ERROR_SUCCESS)
180 hr = HRESULT_FROM_WIN32(ret);
181 break;
184 if (guid_string_size != 38)
186 hr = E_FAIL;
187 break;
190 hr = CLSIDFromString(guid_string, &buffer[items_returned]);
191 if (FAILED(hr))
192 break;
194 items_returned++;
195 guid_string_size = 39;
198 if (ret == ERROR_NO_MORE_ITEMS)
199 hr = S_OK;
201 *actual_size = items_returned;
203 else
205 ret = RegQueryInfoKeyW(subkey, NULL, NULL, NULL, actual_size, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
206 if (ret != ERROR_SUCCESS)
207 hr = HRESULT_FROM_WIN32(ret);
210 RegCloseKey(subkey);
212 return hr;
215 typedef struct {
216 ComponentInfo base;
217 HKEY classkey;
218 WICBitmapPattern *patterns;
219 UINT pattern_count;
220 UINT patterns_size;
221 } BitmapDecoderInfo;
223 static inline BitmapDecoderInfo *impl_from_IWICBitmapDecoderInfo(IWICBitmapDecoderInfo *iface)
225 return CONTAINING_RECORD(iface, BitmapDecoderInfo, base.IWICComponentInfo_iface);
228 static HRESULT WINAPI BitmapDecoderInfo_QueryInterface(IWICBitmapDecoderInfo *iface, REFIID iid,
229 void **ppv)
231 BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
232 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
234 if (!ppv) return E_INVALIDARG;
236 if (IsEqualIID(&IID_IUnknown, iid) ||
237 IsEqualIID(&IID_IWICComponentInfo, iid) ||
238 IsEqualIID(&IID_IWICBitmapCodecInfo, iid) ||
239 IsEqualIID(&IID_IWICBitmapDecoderInfo ,iid))
241 *ppv = &This->base.IWICComponentInfo_iface;
243 else
245 *ppv = NULL;
246 return E_NOINTERFACE;
249 IUnknown_AddRef((IUnknown*)*ppv);
250 return S_OK;
253 static ULONG WINAPI BitmapDecoderInfo_AddRef(IWICBitmapDecoderInfo *iface)
255 BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
256 ULONG ref = InterlockedIncrement(&This->base.ref);
258 TRACE("(%p) refcount=%u\n", iface, ref);
260 return ref;
263 static ULONG WINAPI BitmapDecoderInfo_Release(IWICBitmapDecoderInfo *iface)
265 BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
266 ULONG ref = InterlockedDecrement(&This->base.ref);
268 TRACE("(%p) refcount=%u\n", iface, ref);
270 if (ref == 0)
272 RegCloseKey(This->classkey);
273 heap_free(This->patterns);
274 HeapFree(GetProcessHeap(), 0, This);
277 return ref;
280 static HRESULT WINAPI BitmapDecoderInfo_GetComponentType(IWICBitmapDecoderInfo *iface,
281 WICComponentType *pType)
283 TRACE("(%p,%p)\n", iface, pType);
284 if (!pType) return E_INVALIDARG;
285 *pType = WICDecoder;
286 return S_OK;
289 static HRESULT WINAPI BitmapDecoderInfo_GetCLSID(IWICBitmapDecoderInfo *iface, CLSID *pclsid)
291 BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
292 TRACE("(%p,%p)\n", iface, pclsid);
294 if (!pclsid)
295 return E_INVALIDARG;
297 *pclsid = This->base.clsid;
298 return S_OK;
301 static HRESULT WINAPI BitmapDecoderInfo_GetSigningStatus(IWICBitmapDecoderInfo *iface, DWORD *pStatus)
303 FIXME("(%p,%p): stub\n", iface, pStatus);
304 return E_NOTIMPL;
307 static HRESULT WINAPI BitmapDecoderInfo_GetAuthor(IWICBitmapDecoderInfo *iface, UINT cchAuthor,
308 WCHAR *wzAuthor, UINT *pcchActual)
310 BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
312 TRACE("(%p,%u,%p,%p)\n", iface, cchAuthor, wzAuthor, pcchActual);
314 return ComponentInfo_GetStringValue(This->classkey, author_valuename,
315 cchAuthor, wzAuthor, pcchActual);
318 static HRESULT WINAPI BitmapDecoderInfo_GetVendorGUID(IWICBitmapDecoderInfo *iface, GUID *pguidVendor)
320 BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
322 TRACE("(%p,%p)\n", iface, pguidVendor);
324 return ComponentInfo_GetGUIDValue(This->classkey, vendor_valuename, pguidVendor);
327 static HRESULT WINAPI BitmapDecoderInfo_GetVersion(IWICBitmapDecoderInfo *iface, UINT cchVersion,
328 WCHAR *wzVersion, UINT *pcchActual)
330 BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
332 TRACE("(%p,%u,%p,%p)\n", iface, cchVersion, wzVersion, pcchActual);
334 return ComponentInfo_GetStringValue(This->classkey, version_valuename,
335 cchVersion, wzVersion, pcchActual);
338 static HRESULT WINAPI BitmapDecoderInfo_GetSpecVersion(IWICBitmapDecoderInfo *iface, UINT cchSpecVersion,
339 WCHAR *wzSpecVersion, UINT *pcchActual)
341 BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
343 TRACE("(%p,%u,%p,%p)\n", iface, cchSpecVersion, wzSpecVersion, pcchActual);
345 return ComponentInfo_GetStringValue(This->classkey, specversion_valuename,
346 cchSpecVersion, wzSpecVersion, pcchActual);
349 static HRESULT WINAPI BitmapDecoderInfo_GetFriendlyName(IWICBitmapDecoderInfo *iface, UINT cchFriendlyName,
350 WCHAR *wzFriendlyName, UINT *pcchActual)
352 BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
354 TRACE("(%p,%u,%p,%p)\n", iface, cchFriendlyName, wzFriendlyName, pcchActual);
356 return ComponentInfo_GetStringValue(This->classkey, friendlyname_valuename,
357 cchFriendlyName, wzFriendlyName, pcchActual);
360 static HRESULT WINAPI BitmapDecoderInfo_GetContainerFormat(IWICBitmapDecoderInfo *iface,
361 GUID *pguidContainerFormat)
363 BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
364 TRACE("(%p,%p)\n", iface, pguidContainerFormat);
365 return ComponentInfo_GetGUIDValue(This->classkey, containerformat_valuename, pguidContainerFormat);
368 static HRESULT WINAPI BitmapDecoderInfo_GetPixelFormats(IWICBitmapDecoderInfo *iface,
369 UINT cFormats, GUID *pguidPixelFormats, UINT *pcActual)
371 BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
372 TRACE("(%p,%u,%p,%p)\n", iface, cFormats, pguidPixelFormats, pcActual);
373 return ComponentInfo_GetGuidList(This->classkey, formats_keyname, cFormats, pguidPixelFormats, pcActual);
376 static HRESULT WINAPI BitmapDecoderInfo_GetColorManagementVersion(IWICBitmapDecoderInfo *iface,
377 UINT cchColorManagementVersion, WCHAR *wzColorManagementVersion, UINT *pcchActual)
379 FIXME("(%p,%u,%p,%p): stub\n", iface, cchColorManagementVersion, wzColorManagementVersion, pcchActual);
380 return E_NOTIMPL;
383 static HRESULT WINAPI BitmapDecoderInfo_GetDeviceManufacturer(IWICBitmapDecoderInfo *iface,
384 UINT cchDeviceManufacturer, WCHAR *wzDeviceManufacturer, UINT *pcchActual)
386 FIXME("(%p,%u,%p,%p): stub\n", iface, cchDeviceManufacturer, wzDeviceManufacturer, pcchActual);
387 return E_NOTIMPL;
390 static HRESULT WINAPI BitmapDecoderInfo_GetDeviceModels(IWICBitmapDecoderInfo *iface,
391 UINT cchDeviceModels, WCHAR *wzDeviceModels, UINT *pcchActual)
393 FIXME("(%p,%u,%p,%p): stub\n", iface, cchDeviceModels, wzDeviceModels, pcchActual);
394 return E_NOTIMPL;
397 static HRESULT WINAPI BitmapDecoderInfo_GetMimeTypes(IWICBitmapDecoderInfo *iface,
398 UINT cchMimeTypes, WCHAR *wzMimeTypes, UINT *pcchActual)
400 BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
402 TRACE("(%p,%u,%p,%p)\n", iface, cchMimeTypes, wzMimeTypes, pcchActual);
404 return ComponentInfo_GetStringValue(This->classkey, mimetypes_valuename,
405 cchMimeTypes, wzMimeTypes, pcchActual);
408 static HRESULT WINAPI BitmapDecoderInfo_GetFileExtensions(IWICBitmapDecoderInfo *iface,
409 UINT cchFileExtensions, WCHAR *wzFileExtensions, UINT *pcchActual)
411 BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
413 TRACE("(%p,%u,%p,%p)\n", iface, cchFileExtensions, wzFileExtensions, pcchActual);
415 return ComponentInfo_GetStringValue(This->classkey, fileextensions_valuename,
416 cchFileExtensions, wzFileExtensions, pcchActual);
419 static HRESULT WINAPI BitmapDecoderInfo_DoesSupportAnimation(IWICBitmapDecoderInfo *iface,
420 BOOL *pfSupportAnimation)
422 FIXME("(%p,%p): stub\n", iface, pfSupportAnimation);
423 return E_NOTIMPL;
426 static HRESULT WINAPI BitmapDecoderInfo_DoesSupportChromaKey(IWICBitmapDecoderInfo *iface,
427 BOOL *pfSupportChromaKey)
429 FIXME("(%p,%p): stub\n", iface, pfSupportChromaKey);
430 return E_NOTIMPL;
433 static HRESULT WINAPI BitmapDecoderInfo_DoesSupportLossless(IWICBitmapDecoderInfo *iface,
434 BOOL *pfSupportLossless)
436 FIXME("(%p,%p): stub\n", iface, pfSupportLossless);
437 return E_NOTIMPL;
440 static HRESULT WINAPI BitmapDecoderInfo_DoesSupportMultiframe(IWICBitmapDecoderInfo *iface,
441 BOOL *pfSupportMultiframe)
443 FIXME("(%p,%p): stub\n", iface, pfSupportMultiframe);
444 return E_NOTIMPL;
447 static HRESULT WINAPI BitmapDecoderInfo_MatchesMimeType(IWICBitmapDecoderInfo *iface,
448 LPCWSTR wzMimeType, BOOL *pfMatches)
450 FIXME("(%p,%s,%p): stub\n", iface, debugstr_w(wzMimeType), pfMatches);
451 return E_NOTIMPL;
454 static HRESULT WINAPI BitmapDecoderInfo_GetPatterns(IWICBitmapDecoderInfo *iface,
455 UINT cbSizePatterns, WICBitmapPattern *pPatterns, UINT *pcPatterns, UINT *pcbPatternsActual)
457 BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
459 TRACE("(%p,%i,%p,%p,%p)\n", iface, cbSizePatterns, pPatterns, pcPatterns, pcbPatternsActual);
461 if (!pcPatterns || !pcbPatternsActual) return E_INVALIDARG;
463 *pcPatterns = This->pattern_count;
464 *pcbPatternsActual = This->patterns_size;
465 if (pPatterns)
467 if (This->patterns_size && cbSizePatterns < This->patterns_size)
468 return WINCODEC_ERR_INSUFFICIENTBUFFER;
469 memcpy(pPatterns, This->patterns, This->patterns_size);
471 return S_OK;
474 static HRESULT WINAPI BitmapDecoderInfo_MatchesPattern(IWICBitmapDecoderInfo *iface,
475 IStream *pIStream, BOOL *pfMatches)
477 BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
478 HRESULT hr;
479 UINT i;
480 ULONG pos;
481 BYTE *data=NULL;
482 ULONG datasize=0;
483 ULONG bytesread;
484 LARGE_INTEGER seekpos;
486 TRACE("(%p,%p,%p)\n", iface, pIStream, pfMatches);
488 for (i=0; i < This->pattern_count; i++)
490 if (datasize < This->patterns[i].Length)
492 HeapFree(GetProcessHeap(), 0, data);
493 datasize = This->patterns[i].Length;
494 data = HeapAlloc(GetProcessHeap(), 0, This->patterns[i].Length);
495 if (!data)
497 hr = E_OUTOFMEMORY;
498 break;
502 if (This->patterns[i].EndOfStream)
503 seekpos.QuadPart = -This->patterns[i].Position.QuadPart;
504 else
505 seekpos.QuadPart = This->patterns[i].Position.QuadPart;
506 hr = IStream_Seek(pIStream, seekpos, This->patterns[i].EndOfStream ? STREAM_SEEK_END : STREAM_SEEK_SET, NULL);
507 if (hr == STG_E_INVALIDFUNCTION) continue; /* before start of stream */
508 if (FAILED(hr)) break;
510 hr = IStream_Read(pIStream, data, This->patterns[i].Length, &bytesread);
511 if (hr == S_FALSE || (hr == S_OK && bytesread != This->patterns[i].Length)) /* past end of stream */
512 continue;
513 if (FAILED(hr)) break;
515 for (pos=0; pos < This->patterns[i].Length; pos++)
517 if ((data[pos] & This->patterns[i].Mask[pos]) != This->patterns[i].Pattern[pos])
518 break;
520 if (pos == This->patterns[i].Length) /* matches pattern */
522 hr = S_OK;
523 *pfMatches = TRUE;
524 break;
528 if (i == This->pattern_count) /* does not match any pattern */
530 hr = S_OK;
531 *pfMatches = FALSE;
534 HeapFree(GetProcessHeap(), 0, data);
535 return hr;
538 static HRESULT WINAPI BitmapDecoderInfo_CreateInstance(IWICBitmapDecoderInfo *iface,
539 IWICBitmapDecoder **ppIBitmapDecoder)
541 BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
543 TRACE("(%p,%p)\n", iface, ppIBitmapDecoder);
545 return create_instance(&This->base.clsid, &IID_IWICBitmapDecoder, (void**)ppIBitmapDecoder);
548 static const IWICBitmapDecoderInfoVtbl BitmapDecoderInfo_Vtbl = {
549 BitmapDecoderInfo_QueryInterface,
550 BitmapDecoderInfo_AddRef,
551 BitmapDecoderInfo_Release,
552 BitmapDecoderInfo_GetComponentType,
553 BitmapDecoderInfo_GetCLSID,
554 BitmapDecoderInfo_GetSigningStatus,
555 BitmapDecoderInfo_GetAuthor,
556 BitmapDecoderInfo_GetVendorGUID,
557 BitmapDecoderInfo_GetVersion,
558 BitmapDecoderInfo_GetSpecVersion,
559 BitmapDecoderInfo_GetFriendlyName,
560 BitmapDecoderInfo_GetContainerFormat,
561 BitmapDecoderInfo_GetPixelFormats,
562 BitmapDecoderInfo_GetColorManagementVersion,
563 BitmapDecoderInfo_GetDeviceManufacturer,
564 BitmapDecoderInfo_GetDeviceModels,
565 BitmapDecoderInfo_GetMimeTypes,
566 BitmapDecoderInfo_GetFileExtensions,
567 BitmapDecoderInfo_DoesSupportAnimation,
568 BitmapDecoderInfo_DoesSupportChromaKey,
569 BitmapDecoderInfo_DoesSupportLossless,
570 BitmapDecoderInfo_DoesSupportMultiframe,
571 BitmapDecoderInfo_MatchesMimeType,
572 BitmapDecoderInfo_GetPatterns,
573 BitmapDecoderInfo_MatchesPattern,
574 BitmapDecoderInfo_CreateInstance
577 static void read_bitmap_patterns(BitmapDecoderInfo *info)
579 UINT pattern_count=0, patterns_size=0;
580 WCHAR subkeyname[11];
581 LONG res;
582 HKEY patternskey, patternkey;
583 static const WCHAR uintformatW[] = {'%','u',0};
584 static const WCHAR patternsW[] = {'P','a','t','t','e','r','n','s',0};
585 static const WCHAR positionW[] = {'P','o','s','i','t','i','o','n',0};
586 static const WCHAR lengthW[] = {'L','e','n','g','t','h',0};
587 static const WCHAR patternW[] = {'P','a','t','t','e','r','n',0};
588 static const WCHAR maskW[] = {'M','a','s','k',0};
589 static const WCHAR endofstreamW[] = {'E','n','d','O','f','S','t','r','e','a','m',0};
590 UINT i;
591 WICBitmapPattern *patterns;
592 BYTE *patterns_ptr;
593 DWORD length, valuesize;
595 res = RegOpenKeyExW(info->classkey, patternsW, 0, KEY_READ, &patternskey);
596 if (res != ERROR_SUCCESS) return;
598 res = RegQueryInfoKeyW(patternskey, NULL, NULL, NULL, &pattern_count, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
599 if (res != ERROR_SUCCESS)
601 RegCloseKey(patternskey);
602 return;
605 patterns_size = pattern_count * sizeof(WICBitmapPattern);
606 patterns = heap_alloc(patterns_size);
607 if (!patterns)
609 RegCloseKey(patternskey);
610 return;
613 for (i=0; res == ERROR_SUCCESS && i < pattern_count; i++)
615 snprintfW(subkeyname, 11, uintformatW, i);
616 res = RegOpenKeyExW(patternskey, subkeyname, 0, KEY_READ, &patternkey);
617 if (res != ERROR_SUCCESS) break;
619 valuesize = sizeof(ULONG);
620 res = RegGetValueW(patternkey, NULL, lengthW, RRF_RT_DWORD, NULL, &length, &valuesize);
621 if (res == ERROR_SUCCESS)
623 patterns_size += length*2;
624 patterns[i].Length = length;
626 valuesize = sizeof(BOOL);
627 res = RegGetValueW(patternkey, NULL, endofstreamW, RRF_RT_DWORD, NULL,
628 &patterns[i].EndOfStream, &valuesize);
629 if (res) patterns[i].EndOfStream = 0;
631 patterns[i].Position.QuadPart = 0;
632 valuesize = sizeof(ULARGE_INTEGER);
633 res = RegGetValueW(patternkey, NULL, positionW, RRF_RT_DWORD|RRF_RT_QWORD, NULL,
634 &patterns[i].Position, &valuesize);
637 RegCloseKey(patternkey);
640 if (res != ERROR_SUCCESS || !(patterns_ptr = heap_realloc(patterns, patterns_size)))
642 heap_free(patterns);
643 RegCloseKey(patternskey);
644 return;
646 patterns = (WICBitmapPattern*)patterns_ptr;
647 patterns_ptr += pattern_count * sizeof(*patterns);
649 for (i=0; res == ERROR_SUCCESS && i < pattern_count; i++)
651 snprintfW(subkeyname, 11, uintformatW, i);
652 res = RegOpenKeyExW(patternskey, subkeyname, 0, KEY_READ, &patternkey);
653 if (res != ERROR_SUCCESS) break;
655 length = patterns[i].Length;
656 patterns[i].Pattern = patterns_ptr;
657 valuesize = length;
658 res = RegGetValueW(patternkey, NULL, patternW, RRF_RT_REG_BINARY, NULL,
659 patterns[i].Pattern, &valuesize);
660 patterns_ptr += length;
662 if (res == ERROR_SUCCESS)
664 patterns[i].Mask = patterns_ptr;
665 valuesize = length;
666 res = RegGetValueW(patternkey, NULL, maskW, RRF_RT_REG_BINARY, NULL,
667 patterns[i].Mask, &valuesize);
668 patterns_ptr += length;
671 RegCloseKey(patternkey);
674 RegCloseKey(patternskey);
676 if (res != ERROR_SUCCESS)
678 heap_free(patterns);
679 return;
682 info->pattern_count = pattern_count;
683 info->patterns_size = patterns_size;
684 info->patterns = patterns;
687 static HRESULT BitmapDecoderInfo_Constructor(HKEY classkey, REFCLSID clsid, ComponentInfo **ret)
689 BitmapDecoderInfo *This;
691 This = heap_alloc_zero(sizeof(BitmapDecoderInfo));
692 if (!This)
694 RegCloseKey(classkey);
695 return E_OUTOFMEMORY;
698 This->base.IWICComponentInfo_iface.lpVtbl = (const IWICComponentInfoVtbl*)&BitmapDecoderInfo_Vtbl;
699 This->base.ref = 1;
700 This->classkey = classkey;
701 This->base.clsid = *clsid;
703 read_bitmap_patterns(This);
705 *ret = &This->base;
706 return S_OK;
709 typedef struct {
710 ComponentInfo base;
711 HKEY classkey;
712 } BitmapEncoderInfo;
714 static inline BitmapEncoderInfo *impl_from_IWICBitmapEncoderInfo(IWICBitmapEncoderInfo *iface)
716 return CONTAINING_RECORD(iface, BitmapEncoderInfo, base.IWICComponentInfo_iface);
719 static HRESULT WINAPI BitmapEncoderInfo_QueryInterface(IWICBitmapEncoderInfo *iface, REFIID iid,
720 void **ppv)
722 BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
723 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
725 if (!ppv) return E_INVALIDARG;
727 if (IsEqualIID(&IID_IUnknown, iid) ||
728 IsEqualIID(&IID_IWICComponentInfo, iid) ||
729 IsEqualIID(&IID_IWICBitmapCodecInfo, iid) ||
730 IsEqualIID(&IID_IWICBitmapEncoderInfo ,iid))
732 *ppv = &This->base.IWICComponentInfo_iface;
734 else
736 *ppv = NULL;
737 return E_NOINTERFACE;
740 IUnknown_AddRef((IUnknown*)*ppv);
741 return S_OK;
744 static ULONG WINAPI BitmapEncoderInfo_AddRef(IWICBitmapEncoderInfo *iface)
746 BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
747 ULONG ref = InterlockedIncrement(&This->base.ref);
749 TRACE("(%p) refcount=%u\n", iface, ref);
751 return ref;
754 static ULONG WINAPI BitmapEncoderInfo_Release(IWICBitmapEncoderInfo *iface)
756 BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
757 ULONG ref = InterlockedDecrement(&This->base.ref);
759 TRACE("(%p) refcount=%u\n", iface, ref);
761 if (ref == 0)
763 RegCloseKey(This->classkey);
764 HeapFree(GetProcessHeap(), 0, This);
767 return ref;
770 static HRESULT WINAPI BitmapEncoderInfo_GetComponentType(IWICBitmapEncoderInfo *iface,
771 WICComponentType *pType)
773 TRACE("(%p,%p)\n", iface, pType);
774 if (!pType) return E_INVALIDARG;
775 *pType = WICEncoder;
776 return S_OK;
779 static HRESULT WINAPI BitmapEncoderInfo_GetCLSID(IWICBitmapEncoderInfo *iface, CLSID *pclsid)
781 BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
782 TRACE("(%p,%p)\n", iface, pclsid);
784 if (!pclsid)
785 return E_INVALIDARG;
787 *pclsid = This->base.clsid;
788 return S_OK;
791 static HRESULT WINAPI BitmapEncoderInfo_GetSigningStatus(IWICBitmapEncoderInfo *iface, DWORD *pStatus)
793 FIXME("(%p,%p): stub\n", iface, pStatus);
794 return E_NOTIMPL;
797 static HRESULT WINAPI BitmapEncoderInfo_GetAuthor(IWICBitmapEncoderInfo *iface, UINT cchAuthor,
798 WCHAR *wzAuthor, UINT *pcchActual)
800 BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
802 TRACE("(%p,%u,%p,%p)\n", iface, cchAuthor, wzAuthor, pcchActual);
804 return ComponentInfo_GetStringValue(This->classkey, author_valuename,
805 cchAuthor, wzAuthor, pcchActual);
808 static HRESULT WINAPI BitmapEncoderInfo_GetVendorGUID(IWICBitmapEncoderInfo *iface, GUID *pguidVendor)
810 BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
812 TRACE("(%p,%p)\n", iface, pguidVendor);
814 return ComponentInfo_GetGUIDValue(This->classkey, vendor_valuename, pguidVendor);
817 static HRESULT WINAPI BitmapEncoderInfo_GetVersion(IWICBitmapEncoderInfo *iface, UINT cchVersion,
818 WCHAR *wzVersion, UINT *pcchActual)
820 BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
822 TRACE("(%p,%u,%p,%p)\n", iface, cchVersion, wzVersion, pcchActual);
824 return ComponentInfo_GetStringValue(This->classkey, version_valuename,
825 cchVersion, wzVersion, pcchActual);
828 static HRESULT WINAPI BitmapEncoderInfo_GetSpecVersion(IWICBitmapEncoderInfo *iface, UINT cchSpecVersion,
829 WCHAR *wzSpecVersion, UINT *pcchActual)
831 BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
833 TRACE("(%p,%u,%p,%p)\n", iface, cchSpecVersion, wzSpecVersion, pcchActual);
835 return ComponentInfo_GetStringValue(This->classkey, specversion_valuename,
836 cchSpecVersion, wzSpecVersion, pcchActual);
839 static HRESULT WINAPI BitmapEncoderInfo_GetFriendlyName(IWICBitmapEncoderInfo *iface, UINT cchFriendlyName,
840 WCHAR *wzFriendlyName, UINT *pcchActual)
842 BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
844 TRACE("(%p,%u,%p,%p)\n", iface, cchFriendlyName, wzFriendlyName, pcchActual);
846 return ComponentInfo_GetStringValue(This->classkey, friendlyname_valuename,
847 cchFriendlyName, wzFriendlyName, pcchActual);
850 static HRESULT WINAPI BitmapEncoderInfo_GetContainerFormat(IWICBitmapEncoderInfo *iface,
851 GUID *pguidContainerFormat)
853 BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
854 TRACE("(%p,%p)\n", iface, pguidContainerFormat);
855 return ComponentInfo_GetGUIDValue(This->classkey, containerformat_valuename, pguidContainerFormat);
858 static HRESULT WINAPI BitmapEncoderInfo_GetPixelFormats(IWICBitmapEncoderInfo *iface,
859 UINT cFormats, GUID *pguidPixelFormats, UINT *pcActual)
861 BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
862 TRACE("(%p,%u,%p,%p)\n", iface, cFormats, pguidPixelFormats, pcActual);
863 return ComponentInfo_GetGuidList(This->classkey, formats_keyname, cFormats, pguidPixelFormats, pcActual);
866 static HRESULT WINAPI BitmapEncoderInfo_GetColorManagementVersion(IWICBitmapEncoderInfo *iface,
867 UINT cchColorManagementVersion, WCHAR *wzColorManagementVersion, UINT *pcchActual)
869 FIXME("(%p,%u,%p,%p): stub\n", iface, cchColorManagementVersion, wzColorManagementVersion, pcchActual);
870 return E_NOTIMPL;
873 static HRESULT WINAPI BitmapEncoderInfo_GetDeviceManufacturer(IWICBitmapEncoderInfo *iface,
874 UINT cchDeviceManufacturer, WCHAR *wzDeviceManufacturer, UINT *pcchActual)
876 FIXME("(%p,%u,%p,%p): stub\n", iface, cchDeviceManufacturer, wzDeviceManufacturer, pcchActual);
877 return E_NOTIMPL;
880 static HRESULT WINAPI BitmapEncoderInfo_GetDeviceModels(IWICBitmapEncoderInfo *iface,
881 UINT cchDeviceModels, WCHAR *wzDeviceModels, UINT *pcchActual)
883 FIXME("(%p,%u,%p,%p): stub\n", iface, cchDeviceModels, wzDeviceModels, pcchActual);
884 return E_NOTIMPL;
887 static HRESULT WINAPI BitmapEncoderInfo_GetMimeTypes(IWICBitmapEncoderInfo *iface,
888 UINT cchMimeTypes, WCHAR *wzMimeTypes, UINT *pcchActual)
890 BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
892 TRACE("(%p,%u,%p,%p)\n", iface, cchMimeTypes, wzMimeTypes, pcchActual);
894 return ComponentInfo_GetStringValue(This->classkey, mimetypes_valuename,
895 cchMimeTypes, wzMimeTypes, pcchActual);
898 static HRESULT WINAPI BitmapEncoderInfo_GetFileExtensions(IWICBitmapEncoderInfo *iface,
899 UINT cchFileExtensions, WCHAR *wzFileExtensions, UINT *pcchActual)
901 FIXME("(%p,%u,%p,%p): stub\n", iface, cchFileExtensions, wzFileExtensions, pcchActual);
902 return E_NOTIMPL;
905 static HRESULT WINAPI BitmapEncoderInfo_DoesSupportAnimation(IWICBitmapEncoderInfo *iface,
906 BOOL *pfSupportAnimation)
908 FIXME("(%p,%p): stub\n", iface, pfSupportAnimation);
909 return E_NOTIMPL;
912 static HRESULT WINAPI BitmapEncoderInfo_DoesSupportChromaKey(IWICBitmapEncoderInfo *iface,
913 BOOL *pfSupportChromaKey)
915 FIXME("(%p,%p): stub\n", iface, pfSupportChromaKey);
916 return E_NOTIMPL;
919 static HRESULT WINAPI BitmapEncoderInfo_DoesSupportLossless(IWICBitmapEncoderInfo *iface,
920 BOOL *pfSupportLossless)
922 FIXME("(%p,%p): stub\n", iface, pfSupportLossless);
923 return E_NOTIMPL;
926 static HRESULT WINAPI BitmapEncoderInfo_DoesSupportMultiframe(IWICBitmapEncoderInfo *iface,
927 BOOL *pfSupportMultiframe)
929 FIXME("(%p,%p): stub\n", iface, pfSupportMultiframe);
930 return E_NOTIMPL;
933 static HRESULT WINAPI BitmapEncoderInfo_MatchesMimeType(IWICBitmapEncoderInfo *iface,
934 LPCWSTR wzMimeType, BOOL *pfMatches)
936 FIXME("(%p,%s,%p): stub\n", iface, debugstr_w(wzMimeType), pfMatches);
937 return E_NOTIMPL;
940 static HRESULT WINAPI BitmapEncoderInfo_CreateInstance(IWICBitmapEncoderInfo *iface,
941 IWICBitmapEncoder **ppIBitmapEncoder)
943 BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
945 TRACE("(%p,%p)\n", iface, ppIBitmapEncoder);
947 return create_instance(&This->base.clsid, &IID_IWICBitmapEncoder, (void**)ppIBitmapEncoder);
950 static const IWICBitmapEncoderInfoVtbl BitmapEncoderInfo_Vtbl = {
951 BitmapEncoderInfo_QueryInterface,
952 BitmapEncoderInfo_AddRef,
953 BitmapEncoderInfo_Release,
954 BitmapEncoderInfo_GetComponentType,
955 BitmapEncoderInfo_GetCLSID,
956 BitmapEncoderInfo_GetSigningStatus,
957 BitmapEncoderInfo_GetAuthor,
958 BitmapEncoderInfo_GetVendorGUID,
959 BitmapEncoderInfo_GetVersion,
960 BitmapEncoderInfo_GetSpecVersion,
961 BitmapEncoderInfo_GetFriendlyName,
962 BitmapEncoderInfo_GetContainerFormat,
963 BitmapEncoderInfo_GetPixelFormats,
964 BitmapEncoderInfo_GetColorManagementVersion,
965 BitmapEncoderInfo_GetDeviceManufacturer,
966 BitmapEncoderInfo_GetDeviceModels,
967 BitmapEncoderInfo_GetMimeTypes,
968 BitmapEncoderInfo_GetFileExtensions,
969 BitmapEncoderInfo_DoesSupportAnimation,
970 BitmapEncoderInfo_DoesSupportChromaKey,
971 BitmapEncoderInfo_DoesSupportLossless,
972 BitmapEncoderInfo_DoesSupportMultiframe,
973 BitmapEncoderInfo_MatchesMimeType,
974 BitmapEncoderInfo_CreateInstance
977 static HRESULT BitmapEncoderInfo_Constructor(HKEY classkey, REFCLSID clsid, ComponentInfo **ret)
979 BitmapEncoderInfo *This;
981 This = HeapAlloc(GetProcessHeap(), 0, sizeof(BitmapEncoderInfo));
982 if (!This)
984 RegCloseKey(classkey);
985 return E_OUTOFMEMORY;
988 This->base.IWICComponentInfo_iface.lpVtbl = (const IWICComponentInfoVtbl*)&BitmapEncoderInfo_Vtbl;
989 This->base.ref = 1;
990 This->classkey = classkey;
991 This->base.clsid = *clsid;
993 *ret = &This->base;
994 return S_OK;
997 typedef struct {
998 ComponentInfo base;
999 HKEY classkey;
1000 } FormatConverterInfo;
1002 static inline FormatConverterInfo *impl_from_IWICFormatConverterInfo(IWICFormatConverterInfo *iface)
1004 return CONTAINING_RECORD(iface, FormatConverterInfo, base.IWICComponentInfo_iface);
1007 static HRESULT WINAPI FormatConverterInfo_QueryInterface(IWICFormatConverterInfo *iface, REFIID iid,
1008 void **ppv)
1010 FormatConverterInfo *This = impl_from_IWICFormatConverterInfo(iface);
1011 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
1013 if (!ppv) return E_INVALIDARG;
1015 if (IsEqualIID(&IID_IUnknown, iid) ||
1016 IsEqualIID(&IID_IWICComponentInfo, iid) ||
1017 IsEqualIID(&IID_IWICFormatConverterInfo ,iid))
1019 *ppv = &This->base.IWICComponentInfo_iface;
1021 else
1023 *ppv = NULL;
1024 return E_NOINTERFACE;
1027 IUnknown_AddRef((IUnknown*)*ppv);
1028 return S_OK;
1031 static ULONG WINAPI FormatConverterInfo_AddRef(IWICFormatConverterInfo *iface)
1033 FormatConverterInfo *This = impl_from_IWICFormatConverterInfo(iface);
1034 ULONG ref = InterlockedIncrement(&This->base.ref);
1036 TRACE("(%p) refcount=%u\n", iface, ref);
1038 return ref;
1041 static ULONG WINAPI FormatConverterInfo_Release(IWICFormatConverterInfo *iface)
1043 FormatConverterInfo *This = impl_from_IWICFormatConverterInfo(iface);
1044 ULONG ref = InterlockedDecrement(&This->base.ref);
1046 TRACE("(%p) refcount=%u\n", iface, ref);
1048 if (ref == 0)
1050 RegCloseKey(This->classkey);
1051 HeapFree(GetProcessHeap(), 0, This);
1054 return ref;
1057 static HRESULT WINAPI FormatConverterInfo_GetComponentType(IWICFormatConverterInfo *iface,
1058 WICComponentType *pType)
1060 TRACE("(%p,%p)\n", iface, pType);
1061 if (!pType) return E_INVALIDARG;
1062 *pType = WICPixelFormatConverter;
1063 return S_OK;
1066 static HRESULT WINAPI FormatConverterInfo_GetCLSID(IWICFormatConverterInfo *iface, CLSID *pclsid)
1068 FormatConverterInfo *This = impl_from_IWICFormatConverterInfo(iface);
1069 TRACE("(%p,%p)\n", iface, pclsid);
1071 if (!pclsid)
1072 return E_INVALIDARG;
1074 *pclsid = This->base.clsid;
1075 return S_OK;
1078 static HRESULT WINAPI FormatConverterInfo_GetSigningStatus(IWICFormatConverterInfo *iface, DWORD *pStatus)
1080 FIXME("(%p,%p): stub\n", iface, pStatus);
1081 return E_NOTIMPL;
1084 static HRESULT WINAPI FormatConverterInfo_GetAuthor(IWICFormatConverterInfo *iface, UINT cchAuthor,
1085 WCHAR *wzAuthor, UINT *pcchActual)
1087 FormatConverterInfo *This = impl_from_IWICFormatConverterInfo(iface);
1089 TRACE("(%p,%u,%p,%p)\n", iface, cchAuthor, wzAuthor, pcchActual);
1091 return ComponentInfo_GetStringValue(This->classkey, author_valuename,
1092 cchAuthor, wzAuthor, pcchActual);
1095 static HRESULT WINAPI FormatConverterInfo_GetVendorGUID(IWICFormatConverterInfo *iface, GUID *pguidVendor)
1097 FormatConverterInfo *This = impl_from_IWICFormatConverterInfo(iface);
1099 TRACE("(%p,%p)\n", iface, pguidVendor);
1101 return ComponentInfo_GetGUIDValue(This->classkey, vendor_valuename, pguidVendor);
1104 static HRESULT WINAPI FormatConverterInfo_GetVersion(IWICFormatConverterInfo *iface, UINT cchVersion,
1105 WCHAR *wzVersion, UINT *pcchActual)
1107 FormatConverterInfo *This = impl_from_IWICFormatConverterInfo(iface);
1109 TRACE("(%p,%u,%p,%p)\n", iface, cchVersion, wzVersion, pcchActual);
1111 return ComponentInfo_GetStringValue(This->classkey, version_valuename,
1112 cchVersion, wzVersion, pcchActual);
1115 static HRESULT WINAPI FormatConverterInfo_GetSpecVersion(IWICFormatConverterInfo *iface, UINT cchSpecVersion,
1116 WCHAR *wzSpecVersion, UINT *pcchActual)
1118 FormatConverterInfo *This = impl_from_IWICFormatConverterInfo(iface);
1120 TRACE("(%p,%u,%p,%p)\n", iface, cchSpecVersion, wzSpecVersion, pcchActual);
1122 return ComponentInfo_GetStringValue(This->classkey, specversion_valuename,
1123 cchSpecVersion, wzSpecVersion, pcchActual);
1126 static HRESULT WINAPI FormatConverterInfo_GetFriendlyName(IWICFormatConverterInfo *iface, UINT cchFriendlyName,
1127 WCHAR *wzFriendlyName, UINT *pcchActual)
1129 FormatConverterInfo *This = impl_from_IWICFormatConverterInfo(iface);
1131 TRACE("(%p,%u,%p,%p)\n", iface, cchFriendlyName, wzFriendlyName, pcchActual);
1133 return ComponentInfo_GetStringValue(This->classkey, friendlyname_valuename,
1134 cchFriendlyName, wzFriendlyName, pcchActual);
1137 static HRESULT WINAPI FormatConverterInfo_GetPixelFormats(IWICFormatConverterInfo *iface,
1138 UINT cFormats, GUID *pguidPixelFormats, UINT *pcActual)
1140 FIXME("(%p,%u,%p,%p): stub\n", iface, cFormats, pguidPixelFormats, pcActual);
1141 return E_NOTIMPL;
1144 static HRESULT WINAPI FormatConverterInfo_CreateInstance(IWICFormatConverterInfo *iface,
1145 IWICFormatConverter **ppIFormatConverter)
1147 FormatConverterInfo *This = impl_from_IWICFormatConverterInfo(iface);
1149 TRACE("(%p,%p)\n", iface, ppIFormatConverter);
1151 return create_instance(&This->base.clsid, &IID_IWICFormatConverter,
1152 (void**)ppIFormatConverter);
1155 static BOOL ConverterSupportsFormat(IWICFormatConverterInfo *iface, const WCHAR *formatguid)
1157 LONG res;
1158 FormatConverterInfo *This = impl_from_IWICFormatConverterInfo(iface);
1159 HKEY formats_key, guid_key;
1161 /* Avoid testing using IWICFormatConverter_GetPixelFormats because that
1162 would be O(n). A registry test should do better. */
1164 res = RegOpenKeyExW(This->classkey, pixelformats_keyname, 0, KEY_READ, &formats_key);
1165 if (res != ERROR_SUCCESS) return FALSE;
1167 res = RegOpenKeyExW(formats_key, formatguid, 0, KEY_READ, &guid_key);
1168 if (res == ERROR_SUCCESS) RegCloseKey(guid_key);
1170 RegCloseKey(formats_key);
1172 return (res == ERROR_SUCCESS);
1175 static const IWICFormatConverterInfoVtbl FormatConverterInfo_Vtbl = {
1176 FormatConverterInfo_QueryInterface,
1177 FormatConverterInfo_AddRef,
1178 FormatConverterInfo_Release,
1179 FormatConverterInfo_GetComponentType,
1180 FormatConverterInfo_GetCLSID,
1181 FormatConverterInfo_GetSigningStatus,
1182 FormatConverterInfo_GetAuthor,
1183 FormatConverterInfo_GetVendorGUID,
1184 FormatConverterInfo_GetVersion,
1185 FormatConverterInfo_GetSpecVersion,
1186 FormatConverterInfo_GetFriendlyName,
1187 FormatConverterInfo_GetPixelFormats,
1188 FormatConverterInfo_CreateInstance
1191 static HRESULT FormatConverterInfo_Constructor(HKEY classkey, REFCLSID clsid, ComponentInfo **ret)
1193 FormatConverterInfo *This;
1195 This = HeapAlloc(GetProcessHeap(), 0, sizeof(FormatConverterInfo));
1196 if (!This)
1198 RegCloseKey(classkey);
1199 return E_OUTOFMEMORY;
1202 This->base.IWICComponentInfo_iface.lpVtbl = (const IWICComponentInfoVtbl*)&FormatConverterInfo_Vtbl;
1203 This->base.ref = 1;
1204 This->classkey = classkey;
1205 This->base.clsid = *clsid;
1207 *ret = &This->base;
1208 return S_OK;
1211 typedef struct {
1212 ComponentInfo base;
1213 HKEY classkey;
1214 } PixelFormatInfo;
1216 static inline PixelFormatInfo *impl_from_IWICPixelFormatInfo2(IWICPixelFormatInfo2 *iface)
1218 return CONTAINING_RECORD(iface, PixelFormatInfo, base.IWICComponentInfo_iface);
1221 static HRESULT WINAPI PixelFormatInfo_QueryInterface(IWICPixelFormatInfo2 *iface, REFIID iid,
1222 void **ppv)
1224 PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1225 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
1227 if (!ppv) return E_INVALIDARG;
1229 if (IsEqualIID(&IID_IUnknown, iid) ||
1230 IsEqualIID(&IID_IWICComponentInfo, iid) ||
1231 IsEqualIID(&IID_IWICPixelFormatInfo, iid) ||
1232 IsEqualIID(&IID_IWICPixelFormatInfo2 ,iid))
1234 *ppv = &This->base.IWICComponentInfo_iface;
1236 else
1238 *ppv = NULL;
1239 return E_NOINTERFACE;
1242 IUnknown_AddRef((IUnknown*)*ppv);
1243 return S_OK;
1246 static ULONG WINAPI PixelFormatInfo_AddRef(IWICPixelFormatInfo2 *iface)
1248 PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1249 ULONG ref = InterlockedIncrement(&This->base.ref);
1251 TRACE("(%p) refcount=%u\n", iface, ref);
1253 return ref;
1256 static ULONG WINAPI PixelFormatInfo_Release(IWICPixelFormatInfo2 *iface)
1258 PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1259 ULONG ref = InterlockedDecrement(&This->base.ref);
1261 TRACE("(%p) refcount=%u\n", iface, ref);
1263 if (ref == 0)
1265 RegCloseKey(This->classkey);
1266 HeapFree(GetProcessHeap(), 0, This);
1269 return ref;
1272 static HRESULT WINAPI PixelFormatInfo_GetComponentType(IWICPixelFormatInfo2 *iface,
1273 WICComponentType *pType)
1275 TRACE("(%p,%p)\n", iface, pType);
1276 if (!pType) return E_INVALIDARG;
1277 *pType = WICPixelFormat;
1278 return S_OK;
1281 static HRESULT WINAPI PixelFormatInfo_GetCLSID(IWICPixelFormatInfo2 *iface, CLSID *pclsid)
1283 PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1284 TRACE("(%p,%p)\n", iface, pclsid);
1286 if (!pclsid)
1287 return E_INVALIDARG;
1289 *pclsid = This->base.clsid;
1290 return S_OK;
1293 static HRESULT WINAPI PixelFormatInfo_GetSigningStatus(IWICPixelFormatInfo2 *iface, DWORD *pStatus)
1295 TRACE("(%p,%p)\n", iface, pStatus);
1297 if (!pStatus)
1298 return E_INVALIDARG;
1300 /* Pixel formats don't require code, so they are considered signed. */
1301 *pStatus = WICComponentSigned;
1303 return S_OK;
1306 static HRESULT WINAPI PixelFormatInfo_GetAuthor(IWICPixelFormatInfo2 *iface, UINT cchAuthor,
1307 WCHAR *wzAuthor, UINT *pcchActual)
1309 PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1311 TRACE("(%p,%u,%p,%p)\n", iface, cchAuthor, wzAuthor, pcchActual);
1313 return ComponentInfo_GetStringValue(This->classkey, author_valuename,
1314 cchAuthor, wzAuthor, pcchActual);
1317 static HRESULT WINAPI PixelFormatInfo_GetVendorGUID(IWICPixelFormatInfo2 *iface, GUID *pguidVendor)
1319 PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1321 TRACE("(%p,%p)\n", iface, pguidVendor);
1323 return ComponentInfo_GetGUIDValue(This->classkey, vendor_valuename, pguidVendor);
1326 static HRESULT WINAPI PixelFormatInfo_GetVersion(IWICPixelFormatInfo2 *iface, UINT cchVersion,
1327 WCHAR *wzVersion, UINT *pcchActual)
1329 PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1331 TRACE("(%p,%u,%p,%p)\n", iface, cchVersion, wzVersion, pcchActual);
1333 return ComponentInfo_GetStringValue(This->classkey, version_valuename,
1334 cchVersion, wzVersion, pcchActual);
1337 static HRESULT WINAPI PixelFormatInfo_GetSpecVersion(IWICPixelFormatInfo2 *iface, UINT cchSpecVersion,
1338 WCHAR *wzSpecVersion, UINT *pcchActual)
1340 PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1342 TRACE("(%p,%u,%p,%p)\n", iface, cchSpecVersion, wzSpecVersion, pcchActual);
1344 return ComponentInfo_GetStringValue(This->classkey, specversion_valuename,
1345 cchSpecVersion, wzSpecVersion, pcchActual);
1348 static HRESULT WINAPI PixelFormatInfo_GetFriendlyName(IWICPixelFormatInfo2 *iface, UINT cchFriendlyName,
1349 WCHAR *wzFriendlyName, UINT *pcchActual)
1351 PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1353 TRACE("(%p,%u,%p,%p)\n", iface, cchFriendlyName, wzFriendlyName, pcchActual);
1355 return ComponentInfo_GetStringValue(This->classkey, friendlyname_valuename,
1356 cchFriendlyName, wzFriendlyName, pcchActual);
1359 static HRESULT WINAPI PixelFormatInfo_GetFormatGUID(IWICPixelFormatInfo2 *iface,
1360 GUID *pFormat)
1362 PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1363 TRACE("(%p,%p)\n", iface, pFormat);
1365 if (!pFormat)
1366 return E_INVALIDARG;
1368 *pFormat = This->base.clsid;
1369 return S_OK;
1372 static HRESULT WINAPI PixelFormatInfo_GetColorContext(IWICPixelFormatInfo2 *iface,
1373 IWICColorContext **ppIColorContext)
1375 FIXME("(%p,%p): stub\n", iface, ppIColorContext);
1376 return E_NOTIMPL;
1379 static HRESULT WINAPI PixelFormatInfo_GetBitsPerPixel(IWICPixelFormatInfo2 *iface,
1380 UINT *puiBitsPerPixel)
1382 PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1384 TRACE("(%p,%p)\n", iface, puiBitsPerPixel);
1386 return ComponentInfo_GetDWORDValue(This->classkey, bitsperpixel_valuename, puiBitsPerPixel);
1389 static HRESULT WINAPI PixelFormatInfo_GetChannelCount(IWICPixelFormatInfo2 *iface,
1390 UINT *puiChannelCount)
1392 PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1394 TRACE("(%p,%p)\n", iface, puiChannelCount);
1396 return ComponentInfo_GetDWORDValue(This->classkey, channelcount_valuename, puiChannelCount);
1399 static HRESULT WINAPI PixelFormatInfo_GetChannelMask(IWICPixelFormatInfo2 *iface,
1400 UINT uiChannelIndex, UINT cbMaskBuffer, BYTE *pbMaskBuffer, UINT *pcbActual)
1402 static const WCHAR uintformatW[] = {'%','u',0};
1403 PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1404 UINT channel_count;
1405 HRESULT hr;
1406 LONG ret;
1407 WCHAR valuename[11];
1408 DWORD cbData;
1410 TRACE("(%p,%u,%u,%p,%p)\n", iface, uiChannelIndex, cbMaskBuffer, pbMaskBuffer, pcbActual);
1412 if (!pcbActual)
1413 return E_INVALIDARG;
1415 hr = PixelFormatInfo_GetChannelCount(iface, &channel_count);
1417 if (SUCCEEDED(hr) && uiChannelIndex >= channel_count)
1418 hr = E_INVALIDARG;
1420 if (SUCCEEDED(hr))
1422 snprintfW(valuename, 11, uintformatW, uiChannelIndex);
1424 cbData = cbMaskBuffer;
1426 ret = RegGetValueW(This->classkey, channelmasks_keyname, valuename, RRF_RT_REG_BINARY, NULL, pbMaskBuffer, &cbData);
1428 if (ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA)
1429 *pcbActual = cbData;
1431 if (ret == ERROR_MORE_DATA)
1432 hr = E_INVALIDARG;
1433 else
1434 hr = HRESULT_FROM_WIN32(ret);
1437 return hr;
1440 static HRESULT WINAPI PixelFormatInfo_SupportsTransparency(IWICPixelFormatInfo2 *iface,
1441 BOOL *pfSupportsTransparency)
1443 PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1445 TRACE("(%p,%p)\n", iface, pfSupportsTransparency);
1447 return ComponentInfo_GetDWORDValue(This->classkey, supportstransparency_valuename, (DWORD*)pfSupportsTransparency);
1450 static HRESULT WINAPI PixelFormatInfo_GetNumericRepresentation(IWICPixelFormatInfo2 *iface,
1451 WICPixelFormatNumericRepresentation *pNumericRepresentation)
1453 PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1455 TRACE("(%p,%p)\n", iface, pNumericRepresentation);
1457 return ComponentInfo_GetDWORDValue(This->classkey, numericrepresentation_valuename, pNumericRepresentation);
1460 static const IWICPixelFormatInfo2Vtbl PixelFormatInfo_Vtbl = {
1461 PixelFormatInfo_QueryInterface,
1462 PixelFormatInfo_AddRef,
1463 PixelFormatInfo_Release,
1464 PixelFormatInfo_GetComponentType,
1465 PixelFormatInfo_GetCLSID,
1466 PixelFormatInfo_GetSigningStatus,
1467 PixelFormatInfo_GetAuthor,
1468 PixelFormatInfo_GetVendorGUID,
1469 PixelFormatInfo_GetVersion,
1470 PixelFormatInfo_GetSpecVersion,
1471 PixelFormatInfo_GetFriendlyName,
1472 PixelFormatInfo_GetFormatGUID,
1473 PixelFormatInfo_GetColorContext,
1474 PixelFormatInfo_GetBitsPerPixel,
1475 PixelFormatInfo_GetChannelCount,
1476 PixelFormatInfo_GetChannelMask,
1477 PixelFormatInfo_SupportsTransparency,
1478 PixelFormatInfo_GetNumericRepresentation
1481 static HRESULT PixelFormatInfo_Constructor(HKEY classkey, REFCLSID clsid, ComponentInfo **ret)
1483 PixelFormatInfo *This;
1485 This = HeapAlloc(GetProcessHeap(), 0, sizeof(PixelFormatInfo));
1486 if (!This)
1488 RegCloseKey(classkey);
1489 return E_OUTOFMEMORY;
1492 This->base.IWICComponentInfo_iface.lpVtbl = (const IWICComponentInfoVtbl*)&PixelFormatInfo_Vtbl;
1493 This->base.ref = 1;
1494 This->classkey = classkey;
1495 This->base.clsid = *clsid;
1497 *ret = &This->base;
1498 return S_OK;
1501 struct metadata_container
1503 WICMetadataPattern *patterns;
1504 UINT pattern_count;
1505 UINT patterns_size;
1508 typedef struct
1510 ComponentInfo base;
1511 HKEY classkey;
1512 GUID *container_formats;
1513 struct metadata_container *containers;
1514 UINT container_count;
1515 } MetadataReaderInfo;
1517 static struct metadata_container *get_metadata_container(MetadataReaderInfo *info, const GUID *guid)
1519 unsigned i;
1521 for (i = 0; i < info->container_count; i++)
1522 if (IsEqualGUID(info->container_formats + i, guid))
1523 return info->containers + i;
1525 return NULL;
1528 static inline MetadataReaderInfo *impl_from_IWICMetadataReaderInfo(IWICMetadataReaderInfo *iface)
1530 return CONTAINING_RECORD(iface, MetadataReaderInfo, base.IWICComponentInfo_iface);
1533 static HRESULT WINAPI MetadataReaderInfo_QueryInterface(IWICMetadataReaderInfo *iface,
1534 REFIID riid, void **ppv)
1536 MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1538 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(riid), ppv);
1540 if (!ppv) return E_INVALIDARG;
1542 if (IsEqualIID(&IID_IUnknown, riid) ||
1543 IsEqualIID(&IID_IWICComponentInfo, riid) ||
1544 IsEqualIID(&IID_IWICMetadataHandlerInfo, riid) ||
1545 IsEqualIID(&IID_IWICMetadataReaderInfo, riid))
1547 *ppv = &This->base.IWICComponentInfo_iface;
1549 else
1551 *ppv = NULL;
1552 return E_NOINTERFACE;
1555 IUnknown_AddRef((IUnknown *)*ppv);
1556 return S_OK;
1559 static ULONG WINAPI MetadataReaderInfo_AddRef(IWICMetadataReaderInfo *iface)
1561 MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1562 ULONG ref = InterlockedIncrement(&This->base.ref);
1564 TRACE("(%p) refcount=%u\n", iface, ref);
1565 return ref;
1568 static ULONG WINAPI MetadataReaderInfo_Release(IWICMetadataReaderInfo *iface)
1570 MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1571 ULONG ref = InterlockedDecrement(&This->base.ref);
1573 TRACE("(%p) refcount=%u\n", iface, ref);
1575 if (!ref)
1577 unsigned i;
1578 RegCloseKey(This->classkey);
1579 for (i = 0; i < This->container_count; i++)
1580 heap_free(This->containers[i].patterns);
1581 heap_free(This->containers);
1582 heap_free(This->container_formats);
1583 HeapFree(GetProcessHeap(), 0, This);
1585 return ref;
1588 static HRESULT WINAPI MetadataReaderInfo_GetComponentType(IWICMetadataReaderInfo *iface,
1589 WICComponentType *type)
1591 TRACE("(%p,%p)\n", iface, type);
1593 if (!type) return E_INVALIDARG;
1594 *type = WICMetadataReader;
1595 return S_OK;
1598 static HRESULT WINAPI MetadataReaderInfo_GetCLSID(IWICMetadataReaderInfo *iface,
1599 CLSID *clsid)
1601 MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1603 TRACE("(%p,%p)\n", iface, clsid);
1605 if (!clsid) return E_INVALIDARG;
1606 *clsid = This->base.clsid;
1607 return S_OK;
1610 static HRESULT WINAPI MetadataReaderInfo_GetSigningStatus(IWICMetadataReaderInfo *iface,
1611 DWORD *status)
1613 FIXME("(%p,%p): stub\n", iface, status);
1614 return E_NOTIMPL;
1617 static HRESULT WINAPI MetadataReaderInfo_GetAuthor(IWICMetadataReaderInfo *iface,
1618 UINT length, WCHAR *author, UINT *actual_length)
1620 MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1622 TRACE("(%p,%u,%p,%p)\n", iface, length, author, actual_length);
1624 return ComponentInfo_GetStringValue(This->classkey, author_valuename,
1625 length, author, actual_length);
1628 static HRESULT WINAPI MetadataReaderInfo_GetVendorGUID(IWICMetadataReaderInfo *iface,
1629 GUID *vendor)
1631 MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1633 TRACE("(%p,%p)\n", iface, vendor);
1635 return ComponentInfo_GetGUIDValue(This->classkey, vendor_valuename, vendor);
1638 static HRESULT WINAPI MetadataReaderInfo_GetVersion(IWICMetadataReaderInfo *iface,
1639 UINT length, WCHAR *version, UINT *actual_length)
1641 MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1643 TRACE("(%p,%u,%p,%p)\n", iface, length, version, actual_length);
1645 return ComponentInfo_GetStringValue(This->classkey, version_valuename,
1646 length, version, actual_length);
1649 static HRESULT WINAPI MetadataReaderInfo_GetSpecVersion(IWICMetadataReaderInfo *iface,
1650 UINT length, WCHAR *version, UINT *actual_length)
1652 MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1654 TRACE("(%p,%u,%p,%p)\n", iface, length, version, actual_length);
1656 return ComponentInfo_GetStringValue(This->classkey, specversion_valuename,
1657 length, version, actual_length);
1660 static HRESULT WINAPI MetadataReaderInfo_GetFriendlyName(IWICMetadataReaderInfo *iface,
1661 UINT length, WCHAR *name, UINT *actual_length)
1663 MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1665 TRACE("(%p,%u,%p,%p)\n", iface, length, name, actual_length);
1667 return ComponentInfo_GetStringValue(This->classkey, friendlyname_valuename,
1668 length, name, actual_length);
1671 static HRESULT WINAPI MetadataReaderInfo_GetMetadataFormat(IWICMetadataReaderInfo *iface,
1672 GUID *format)
1674 MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1675 TRACE("(%p,%p)\n", iface, format);
1676 return ComponentInfo_GetGUIDValue(This->classkey, metadataformat_valuename, format);
1679 static HRESULT WINAPI MetadataReaderInfo_GetContainerFormats(IWICMetadataReaderInfo *iface,
1680 UINT length, GUID *formats, UINT *actual_length)
1682 MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1684 TRACE("(%p,%u,%p,%p)\n", iface, length, formats, actual_length);
1686 if (!actual_length)
1687 return E_INVALIDARG;
1689 *actual_length = This->container_count;
1690 if (formats)
1692 if (This->container_count && length < This->container_count)
1693 return WINCODEC_ERR_INSUFFICIENTBUFFER;
1694 memcpy(formats, This->container_formats, This->container_count);
1696 return S_OK;
1699 static HRESULT WINAPI MetadataReaderInfo_GetDeviceManufacturer(IWICMetadataReaderInfo *iface,
1700 UINT length, WCHAR *manufacturer, UINT *actual_length)
1702 FIXME("(%p,%u,%p,%p): stub\n", iface, length, manufacturer, actual_length);
1703 return E_NOTIMPL;
1706 static HRESULT WINAPI MetadataReaderInfo_GetDeviceModels(IWICMetadataReaderInfo *iface,
1707 UINT length, WCHAR *models, UINT *actual_length)
1709 FIXME("(%p,%u,%p,%p): stub\n", iface, length, models, actual_length);
1710 return E_NOTIMPL;
1713 static HRESULT WINAPI MetadataReaderInfo_DoesRequireFullStream(IWICMetadataReaderInfo *iface,
1714 BOOL *param)
1716 MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1717 TRACE("(%p,%p)\n", iface, param);
1718 return ComponentInfo_GetDWORDValue(This->classkey, requiresfullstream_valuename, (DWORD *)param);
1721 static HRESULT WINAPI MetadataReaderInfo_DoesSupportPadding(IWICMetadataReaderInfo *iface,
1722 BOOL *param)
1724 MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1725 TRACE("(%p,%p)\n", iface, param);
1726 return ComponentInfo_GetDWORDValue(This->classkey, supportspadding_valuename, (DWORD *)param);
1729 static HRESULT WINAPI MetadataReaderInfo_DoesRequireFixedSize(IWICMetadataReaderInfo *iface,
1730 BOOL *param)
1732 FIXME("(%p,%p): stub\n", iface, param);
1733 return E_NOTIMPL;
1736 static HRESULT WINAPI MetadataReaderInfo_GetPatterns(IWICMetadataReaderInfo *iface,
1737 REFGUID container_guid, UINT length, WICMetadataPattern *patterns, UINT *count, UINT *actual_length)
1739 MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1740 struct metadata_container *container;
1742 TRACE("(%p,%s,%u,%p,%p,%p)\n", iface, debugstr_guid(container_guid), length, patterns, count, actual_length);
1744 if (!actual_length || !container_guid) return E_INVALIDARG;
1746 if (!(container = get_metadata_container(This, container_guid)))
1747 return WINCODEC_ERR_COMPONENTNOTFOUND;
1749 *count = container->pattern_count;
1750 *actual_length = container->patterns_size;
1751 if (patterns)
1753 if (container->patterns_size && length < container->patterns_size)
1754 return WINCODEC_ERR_INSUFFICIENTBUFFER;
1755 memcpy(patterns, container->patterns, container->patterns_size);
1757 return S_OK;
1760 static HRESULT WINAPI MetadataReaderInfo_MatchesPattern(IWICMetadataReaderInfo *iface,
1761 REFGUID container_guid, IStream *stream, BOOL *matches)
1763 MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1764 struct metadata_container *container;
1765 HRESULT hr;
1766 ULONG datasize=0;
1767 BYTE *data=NULL;
1768 ULONG bytesread;
1769 UINT i;
1770 LARGE_INTEGER seekpos;
1771 ULONG pos;
1773 TRACE("(%p,%s,%p,%p)\n", iface, debugstr_guid(container_guid), stream, matches);
1775 if (!(container = get_metadata_container(This, container_guid)))
1776 return WINCODEC_ERR_COMPONENTNOTFOUND;
1778 for (i=0; i < container->pattern_count; i++)
1780 if (datasize < container->patterns[i].Length)
1782 HeapFree(GetProcessHeap(), 0, data);
1783 datasize = container->patterns[i].Length;
1784 data = HeapAlloc(GetProcessHeap(), 0, container->patterns[i].Length);
1785 if (!data)
1787 hr = E_OUTOFMEMORY;
1788 break;
1792 seekpos.QuadPart = container->patterns[i].Position.QuadPart;
1793 hr = IStream_Seek(stream, seekpos, STREAM_SEEK_SET, NULL);
1794 if (FAILED(hr)) break;
1796 hr = IStream_Read(stream, data, container->patterns[i].Length, &bytesread);
1797 if (hr == S_FALSE || (hr == S_OK && bytesread != container->patterns[i].Length)) /* past end of stream */
1798 continue;
1799 if (FAILED(hr)) break;
1801 for (pos=0; pos < container->patterns[i].Length; pos++)
1803 if ((data[pos] & container->patterns[i].Mask[pos]) != container->patterns[i].Pattern[pos])
1804 break;
1806 if (pos == container->patterns[i].Length) /* matches pattern */
1808 hr = S_OK;
1809 *matches = TRUE;
1810 break;
1814 if (i == container->pattern_count) /* does not match any pattern */
1816 hr = S_OK;
1817 *matches = FALSE;
1820 HeapFree(GetProcessHeap(), 0, data);
1822 return hr;
1825 static HRESULT WINAPI MetadataReaderInfo_CreateInstance(IWICMetadataReaderInfo *iface,
1826 IWICMetadataReader **reader)
1828 MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1830 TRACE("(%p,%p)\n", iface, reader);
1832 return create_instance(&This->base.clsid, &IID_IWICMetadataReader, (void **)reader);
1835 static const IWICMetadataReaderInfoVtbl MetadataReaderInfo_Vtbl = {
1836 MetadataReaderInfo_QueryInterface,
1837 MetadataReaderInfo_AddRef,
1838 MetadataReaderInfo_Release,
1839 MetadataReaderInfo_GetComponentType,
1840 MetadataReaderInfo_GetCLSID,
1841 MetadataReaderInfo_GetSigningStatus,
1842 MetadataReaderInfo_GetAuthor,
1843 MetadataReaderInfo_GetVendorGUID,
1844 MetadataReaderInfo_GetVersion,
1845 MetadataReaderInfo_GetSpecVersion,
1846 MetadataReaderInfo_GetFriendlyName,
1847 MetadataReaderInfo_GetMetadataFormat,
1848 MetadataReaderInfo_GetContainerFormats,
1849 MetadataReaderInfo_GetDeviceManufacturer,
1850 MetadataReaderInfo_GetDeviceModels,
1851 MetadataReaderInfo_DoesRequireFullStream,
1852 MetadataReaderInfo_DoesSupportPadding,
1853 MetadataReaderInfo_DoesRequireFixedSize,
1854 MetadataReaderInfo_GetPatterns,
1855 MetadataReaderInfo_MatchesPattern,
1856 MetadataReaderInfo_CreateInstance
1859 static void read_metadata_patterns(MetadataReaderInfo *info, GUID *container_guid,
1860 struct metadata_container *container)
1862 UINT pattern_count=0, patterns_size=0;
1863 WCHAR subkeyname[11], guidkeyname[39];
1864 LONG res;
1865 HKEY containers_key, guid_key, patternkey;
1866 static const WCHAR uintformatW[] = {'%','u',0};
1867 static const WCHAR patternW[] = {'P','a','t','t','e','r','n',0};
1868 static const WCHAR positionW[] = {'P','o','s','i','t','i','o','n',0};
1869 static const WCHAR maskW[] = {'M','a','s','k',0};
1870 static const WCHAR dataoffsetW[] = {'D','a','t','a','O','f','f','s','e','t',0};
1871 UINT i;
1872 WICMetadataPattern *patterns;
1873 BYTE *patterns_ptr;
1874 DWORD length, valuesize;
1876 res = RegOpenKeyExW(info->classkey, containers_keyname, 0, KEY_READ, &containers_key);
1877 if (res != ERROR_SUCCESS) return;
1879 StringFromGUID2(container_guid, guidkeyname, 39);
1880 res = RegOpenKeyExW(containers_key, guidkeyname, 0, KEY_READ, &guid_key);
1881 RegCloseKey(containers_key);
1882 if (res != ERROR_SUCCESS) return;
1884 res = RegQueryInfoKeyW(guid_key, NULL, NULL, NULL, &pattern_count,
1885 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1886 if (res != ERROR_SUCCESS)
1888 RegCloseKey(guid_key);
1889 return;
1892 patterns_size = pattern_count * sizeof(WICMetadataPattern);
1893 patterns = heap_alloc(patterns_size);
1894 if (!patterns)
1896 RegCloseKey(guid_key);
1897 return;
1900 for (i=0; res == ERROR_SUCCESS && i < pattern_count; i++)
1902 snprintfW(subkeyname, 11, uintformatW, i);
1903 res = RegOpenKeyExW(guid_key, subkeyname, 0, KEY_READ, &patternkey);
1904 if (res != ERROR_SUCCESS) break;
1906 res = RegGetValueW(patternkey, NULL, patternW, RRF_RT_REG_BINARY, NULL, NULL, &length);
1907 if (res == ERROR_SUCCESS)
1909 patterns_size += length*2;
1910 patterns[i].Length = length;
1912 valuesize = sizeof(DWORD64);
1913 res = RegGetValueW(patternkey, NULL, dataoffsetW, RRF_RT_DWORD|RRF_RT_QWORD, NULL,
1914 &patterns[i].DataOffset, &valuesize);
1915 if (res) patterns[i].DataOffset.QuadPart = 0;
1917 patterns[i].Position.QuadPart = 0;
1918 valuesize = sizeof(DWORD64);
1919 res = RegGetValueW(patternkey, NULL, positionW, RRF_RT_DWORD|RRF_RT_QWORD, NULL,
1920 &patterns[i].Position, &valuesize);
1923 RegCloseKey(patternkey);
1926 if (res != ERROR_SUCCESS || !(patterns_ptr = heap_realloc(patterns, patterns_size)))
1928 heap_free(patterns);
1929 RegCloseKey(guid_key);
1930 return;
1932 patterns = (WICMetadataPattern*)patterns_ptr;
1933 patterns_ptr += pattern_count * sizeof(*patterns);
1935 for (i=0; res == ERROR_SUCCESS && i < pattern_count; i++)
1937 snprintfW(subkeyname, 11, uintformatW, i);
1938 res = RegOpenKeyExW(guid_key, subkeyname, 0, KEY_READ, &patternkey);
1939 if (res != ERROR_SUCCESS) break;
1941 length = patterns[i].Length;
1942 patterns[i].Pattern = patterns_ptr;
1943 valuesize = length;
1944 res = RegGetValueW(patternkey, NULL, patternW, RRF_RT_REG_BINARY, NULL,
1945 patterns[i].Pattern, &valuesize);
1946 patterns_ptr += length;
1948 if (res == ERROR_SUCCESS)
1950 patterns[i].Mask = patterns_ptr;
1951 valuesize = length;
1952 res = RegGetValueW(patternkey, NULL, maskW, RRF_RT_REG_BINARY, NULL,
1953 patterns[i].Mask, &valuesize);
1954 patterns_ptr += length;
1957 RegCloseKey(patternkey);
1960 RegCloseKey(guid_key);
1962 if (res != ERROR_SUCCESS)
1964 heap_free(patterns);
1965 return;
1968 container->pattern_count = pattern_count;
1969 container->patterns_size = patterns_size;
1970 container->patterns = patterns;
1973 static BOOL read_metadata_info(MetadataReaderInfo *info)
1975 UINT format_count;
1976 GUID *formats;
1977 HRESULT hr;
1979 hr = ComponentInfo_GetGuidList(info->classkey, containers_keyname, 0, NULL, &format_count);
1980 if (FAILED(hr)) return TRUE;
1982 formats = heap_calloc(format_count, sizeof(*formats));
1983 if (!formats) return FALSE;
1985 hr = ComponentInfo_GetGuidList(info->classkey, containers_keyname, format_count, formats,
1986 &format_count);
1987 if (FAILED(hr))
1989 heap_free(formats);
1990 return FALSE;
1993 info->container_formats = formats;
1994 info->container_count = format_count;
1996 if (format_count)
1998 unsigned i;
2000 info->containers = heap_calloc(format_count, sizeof(*info->containers));
2001 if (!info->containers) return FALSE;
2003 for (i = 0; i < format_count; i++)
2004 read_metadata_patterns(info, info->container_formats + i, info->containers + i);
2007 return TRUE;
2010 static HRESULT MetadataReaderInfo_Constructor(HKEY classkey, REFCLSID clsid, ComponentInfo **info)
2012 MetadataReaderInfo *This;
2014 This = heap_alloc_zero(sizeof(*This));
2015 if (!This)
2017 RegCloseKey(classkey);
2018 return E_OUTOFMEMORY;
2021 This->base.IWICComponentInfo_iface.lpVtbl = (const IWICComponentInfoVtbl*)&MetadataReaderInfo_Vtbl;
2022 This->base.ref = 1;
2023 This->classkey = classkey;
2024 This->base.clsid = *clsid;
2026 if (!read_metadata_info(This))
2028 IWICComponentInfo_Release(&This->base.IWICComponentInfo_iface);
2029 return WINCODEC_ERR_COMPONENTNOTFOUND;
2032 *info = &This->base;
2033 return S_OK;
2036 static const WCHAR clsid_keyname[] = {'C','L','S','I','D',0};
2037 static const WCHAR instance_keyname[] = {'I','n','s','t','a','n','c','e',0};
2039 struct category {
2040 WICComponentType type;
2041 const GUID *catid;
2042 HRESULT (*constructor)(HKEY,REFCLSID,ComponentInfo**);
2045 static const struct category categories[] = {
2046 {WICDecoder, &CATID_WICBitmapDecoders, BitmapDecoderInfo_Constructor},
2047 {WICEncoder, &CATID_WICBitmapEncoders, BitmapEncoderInfo_Constructor},
2048 {WICPixelFormatConverter, &CATID_WICFormatConverters, FormatConverterInfo_Constructor},
2049 {WICPixelFormat, &CATID_WICPixelFormats, PixelFormatInfo_Constructor},
2050 {WICMetadataReader, &CATID_WICMetadataReader, MetadataReaderInfo_Constructor},
2054 static int ComponentInfo_Compare(const void *key, const struct wine_rb_entry *entry)
2056 ComponentInfo *info = WINE_RB_ENTRY_VALUE(entry, ComponentInfo, entry);
2057 return memcmp(key, &info->clsid, sizeof(info->clsid));
2060 static struct wine_rb_tree component_info_cache = { ComponentInfo_Compare };
2062 static CRITICAL_SECTION component_info_cache_cs;
2063 static CRITICAL_SECTION_DEBUG component_info_cache_cs_dbg =
2065 0, 0, &component_info_cache_cs,
2066 { &component_info_cache_cs_dbg.ProcessLocksList, &component_info_cache_cs_dbg.ProcessLocksList },
2067 0, 0, { (DWORD_PTR)(__FILE__ ": component_info_cache") }
2069 static CRITICAL_SECTION component_info_cache_cs = { &component_info_cache_cs_dbg, -1, 0, 0, 0, 0 };
2071 HRESULT CreateComponentInfo(REFCLSID clsid, IWICComponentInfo **ppIInfo)
2073 struct wine_rb_entry *cache_entry;
2074 ComponentInfo *info;
2075 HKEY clsidkey;
2076 HKEY classkey;
2077 HKEY catidkey;
2078 HKEY instancekey;
2079 WCHAR guidstring[39];
2080 LONG res;
2081 const struct category *category;
2082 BOOL found = FALSE;
2083 HRESULT hr;
2085 EnterCriticalSection(&component_info_cache_cs);
2087 cache_entry = wine_rb_get(&component_info_cache, clsid);
2088 if(cache_entry)
2090 info = WINE_RB_ENTRY_VALUE(cache_entry, ComponentInfo, entry);
2091 IWICComponentInfo_AddRef(*ppIInfo = &info->IWICComponentInfo_iface);
2092 LeaveCriticalSection(&component_info_cache_cs);
2093 return S_OK;
2096 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, KEY_READ, &clsidkey);
2097 if (res != ERROR_SUCCESS)
2099 LeaveCriticalSection(&component_info_cache_cs);
2100 return HRESULT_FROM_WIN32(res);
2103 for (category=categories; category->type; category++)
2105 StringFromGUID2(category->catid, guidstring, 39);
2106 res = RegOpenKeyExW(clsidkey, guidstring, 0, KEY_READ, &catidkey);
2107 if (res == ERROR_SUCCESS)
2109 res = RegOpenKeyExW(catidkey, instance_keyname, 0, KEY_READ, &instancekey);
2110 if (res == ERROR_SUCCESS)
2112 StringFromGUID2(clsid, guidstring, 39);
2113 res = RegOpenKeyExW(instancekey, guidstring, 0, KEY_READ, &classkey);
2114 if (res == ERROR_SUCCESS)
2116 RegCloseKey(classkey);
2117 found = TRUE;
2119 RegCloseKey(instancekey);
2121 RegCloseKey(catidkey);
2123 if (found) break;
2126 if (found)
2128 res = RegOpenKeyExW(clsidkey, guidstring, 0, KEY_READ, &classkey);
2129 if (res == ERROR_SUCCESS)
2130 hr = category->constructor(classkey, clsid, &info);
2131 else
2132 hr = HRESULT_FROM_WIN32(res);
2134 else
2136 FIXME("%s is not supported\n", wine_dbgstr_guid(clsid));
2137 hr = E_FAIL;
2140 RegCloseKey(clsidkey);
2142 if (SUCCEEDED(hr))
2144 wine_rb_put(&component_info_cache, clsid, &info->entry);
2145 IWICComponentInfo_AddRef(*ppIInfo = &info->IWICComponentInfo_iface);
2147 LeaveCriticalSection(&component_info_cache_cs);
2148 return hr;
2151 void ReleaseComponentInfos(void)
2153 ComponentInfo *info, *next_info;
2154 WINE_RB_FOR_EACH_ENTRY_DESTRUCTOR(info, next_info, &component_info_cache, ComponentInfo, entry)
2155 IWICComponentInfo_Release(&info->IWICComponentInfo_iface);
2158 HRESULT get_decoder_info(REFCLSID clsid, IWICBitmapDecoderInfo **info)
2160 IWICComponentInfo *compinfo;
2161 HRESULT hr;
2163 hr = CreateComponentInfo(clsid, &compinfo);
2164 if (FAILED(hr)) return hr;
2166 hr = IWICComponentInfo_QueryInterface(compinfo, &IID_IWICBitmapDecoderInfo,
2167 (void **)info);
2169 IWICComponentInfo_Release(compinfo);
2171 return hr;
2174 typedef struct {
2175 IEnumUnknown IEnumUnknown_iface;
2176 LONG ref;
2177 struct list objects;
2178 struct list *cursor;
2179 CRITICAL_SECTION lock; /* Must be held when reading or writing cursor */
2180 } ComponentEnum;
2182 static inline ComponentEnum *impl_from_IEnumUnknown(IEnumUnknown *iface)
2184 return CONTAINING_RECORD(iface, ComponentEnum, IEnumUnknown_iface);
2187 typedef struct {
2188 struct list entry;
2189 IUnknown *unk;
2190 } ComponentEnumItem;
2192 static const IEnumUnknownVtbl ComponentEnumVtbl;
2194 static HRESULT WINAPI ComponentEnum_QueryInterface(IEnumUnknown *iface, REFIID iid,
2195 void **ppv)
2197 ComponentEnum *This = impl_from_IEnumUnknown(iface);
2198 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
2200 if (!ppv) return E_INVALIDARG;
2202 if (IsEqualIID(&IID_IUnknown, iid) ||
2203 IsEqualIID(&IID_IEnumUnknown, iid))
2205 *ppv = &This->IEnumUnknown_iface;
2207 else
2209 *ppv = NULL;
2210 return E_NOINTERFACE;
2213 IUnknown_AddRef((IUnknown*)*ppv);
2214 return S_OK;
2217 static ULONG WINAPI ComponentEnum_AddRef(IEnumUnknown *iface)
2219 ComponentEnum *This = impl_from_IEnumUnknown(iface);
2220 ULONG ref = InterlockedIncrement(&This->ref);
2222 TRACE("(%p) refcount=%u\n", iface, ref);
2224 return ref;
2227 static ULONG WINAPI ComponentEnum_Release(IEnumUnknown *iface)
2229 ComponentEnum *This = impl_from_IEnumUnknown(iface);
2230 ULONG ref = InterlockedDecrement(&This->ref);
2231 ComponentEnumItem *cursor, *cursor2;
2233 TRACE("(%p) refcount=%u\n", iface, ref);
2235 if (ref == 0)
2237 LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, &This->objects, ComponentEnumItem, entry)
2239 IUnknown_Release(cursor->unk);
2240 list_remove(&cursor->entry);
2241 HeapFree(GetProcessHeap(), 0, cursor);
2243 This->lock.DebugInfo->Spare[0] = 0;
2244 DeleteCriticalSection(&This->lock);
2245 HeapFree(GetProcessHeap(), 0, This);
2248 return ref;
2251 static HRESULT WINAPI ComponentEnum_Next(IEnumUnknown *iface, ULONG celt,
2252 IUnknown **rgelt, ULONG *pceltFetched)
2254 ComponentEnum *This = impl_from_IEnumUnknown(iface);
2255 ULONG num_fetched=0;
2256 ComponentEnumItem *item;
2257 HRESULT hr=S_OK;
2259 TRACE("(%p,%u,%p,%p)\n", iface, celt, rgelt, pceltFetched);
2261 EnterCriticalSection(&This->lock);
2262 while (num_fetched<celt)
2264 if (!This->cursor)
2266 hr = S_FALSE;
2267 break;
2269 item = LIST_ENTRY(This->cursor, ComponentEnumItem, entry);
2270 IUnknown_AddRef(item->unk);
2271 rgelt[num_fetched] = item->unk;
2272 num_fetched++;
2273 This->cursor = list_next(&This->objects, This->cursor);
2275 LeaveCriticalSection(&This->lock);
2276 if (pceltFetched)
2277 *pceltFetched = num_fetched;
2278 return hr;
2281 static HRESULT WINAPI ComponentEnum_Skip(IEnumUnknown *iface, ULONG celt)
2283 ComponentEnum *This = impl_from_IEnumUnknown(iface);
2284 ULONG i;
2285 HRESULT hr=S_OK;
2287 TRACE("(%p,%u)\n", iface, celt);
2289 EnterCriticalSection(&This->lock);
2290 for (i=0; i<celt; i++)
2292 if (!This->cursor)
2294 hr = S_FALSE;
2295 break;
2297 This->cursor = list_next(&This->objects, This->cursor);
2299 LeaveCriticalSection(&This->lock);
2300 return hr;
2303 static HRESULT WINAPI ComponentEnum_Reset(IEnumUnknown *iface)
2305 ComponentEnum *This = impl_from_IEnumUnknown(iface);
2307 TRACE("(%p)\n", iface);
2309 EnterCriticalSection(&This->lock);
2310 This->cursor = list_head(&This->objects);
2311 LeaveCriticalSection(&This->lock);
2312 return S_OK;
2315 static HRESULT WINAPI ComponentEnum_Clone(IEnumUnknown *iface, IEnumUnknown **ppenum)
2317 ComponentEnum *This = impl_from_IEnumUnknown(iface);
2318 ComponentEnum *new_enum;
2319 ComponentEnumItem *old_item, *new_item;
2320 HRESULT ret=S_OK;
2321 struct list *old_cursor;
2323 new_enum = HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentEnum));
2324 if (!new_enum)
2326 *ppenum = NULL;
2327 return E_OUTOFMEMORY;
2330 new_enum->IEnumUnknown_iface.lpVtbl = &ComponentEnumVtbl;
2331 new_enum->ref = 1;
2332 new_enum->cursor = NULL;
2333 list_init(&new_enum->objects);
2334 InitializeCriticalSection(&new_enum->lock);
2335 new_enum->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": ComponentEnum.lock");
2337 EnterCriticalSection(&This->lock);
2338 old_cursor = This->cursor;
2339 LeaveCriticalSection(&This->lock);
2341 LIST_FOR_EACH_ENTRY(old_item, &This->objects, ComponentEnumItem, entry)
2343 new_item = HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentEnumItem));
2344 if (!new_item)
2346 ret = E_OUTOFMEMORY;
2347 break;
2349 new_item->unk = old_item->unk;
2350 list_add_tail(&new_enum->objects, &new_item->entry);
2351 IUnknown_AddRef(new_item->unk);
2352 if (&old_item->entry == old_cursor) new_enum->cursor = &new_item->entry;
2355 if (FAILED(ret))
2357 IEnumUnknown_Release(&new_enum->IEnumUnknown_iface);
2358 *ppenum = NULL;
2360 else
2361 *ppenum = &new_enum->IEnumUnknown_iface;
2363 return ret;
2366 static const IEnumUnknownVtbl ComponentEnumVtbl = {
2367 ComponentEnum_QueryInterface,
2368 ComponentEnum_AddRef,
2369 ComponentEnum_Release,
2370 ComponentEnum_Next,
2371 ComponentEnum_Skip,
2372 ComponentEnum_Reset,
2373 ComponentEnum_Clone
2376 HRESULT CreateComponentEnumerator(DWORD componentTypes, DWORD options, IEnumUnknown **ppIEnumUnknown)
2378 ComponentEnum *This;
2379 ComponentEnumItem *item;
2380 const struct category *category;
2381 HKEY clsidkey, catidkey, instancekey;
2382 WCHAR guidstring[39];
2383 LONG res;
2384 int i;
2385 HRESULT hr=S_OK;
2386 CLSID clsid;
2388 if (options) FIXME("ignoring flags %x\n", options);
2390 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, KEY_READ, &clsidkey);
2391 if (res != ERROR_SUCCESS)
2392 return HRESULT_FROM_WIN32(res);
2394 This = HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentEnum));
2395 if (!This)
2397 RegCloseKey(clsidkey);
2398 return E_OUTOFMEMORY;
2401 This->IEnumUnknown_iface.lpVtbl = &ComponentEnumVtbl;
2402 This->ref = 1;
2403 list_init(&This->objects);
2404 InitializeCriticalSection(&This->lock);
2405 This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": ComponentEnum.lock");
2407 for (category=categories; category->type && hr == S_OK; category++)
2409 if ((category->type & componentTypes) == 0) continue;
2410 StringFromGUID2(category->catid, guidstring, 39);
2411 res = RegOpenKeyExW(clsidkey, guidstring, 0, KEY_READ, &catidkey);
2412 if (res == ERROR_SUCCESS)
2414 res = RegOpenKeyExW(catidkey, instance_keyname, 0, KEY_READ, &instancekey);
2415 if (res == ERROR_SUCCESS)
2417 i=0;
2418 for (;;i++)
2420 DWORD guidstring_size = 39;
2421 res = RegEnumKeyExW(instancekey, i, guidstring, &guidstring_size, NULL, NULL, NULL, NULL);
2422 if (res != ERROR_SUCCESS) break;
2424 item = HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentEnumItem));
2425 if (!item) { hr = E_OUTOFMEMORY; break; }
2427 hr = CLSIDFromString(guidstring, &clsid);
2428 if (SUCCEEDED(hr))
2430 hr = CreateComponentInfo(&clsid, (IWICComponentInfo**)&item->unk);
2431 if (SUCCEEDED(hr))
2432 list_add_tail(&This->objects, &item->entry);
2435 if (FAILED(hr))
2437 HeapFree(GetProcessHeap(), 0, item);
2438 hr = S_OK;
2441 RegCloseKey(instancekey);
2443 RegCloseKey(catidkey);
2445 if (res != ERROR_SUCCESS && res != ERROR_NO_MORE_ITEMS)
2446 hr = HRESULT_FROM_WIN32(res);
2448 RegCloseKey(clsidkey);
2450 if (SUCCEEDED(hr))
2452 IEnumUnknown_Reset(&This->IEnumUnknown_iface);
2453 *ppIEnumUnknown = &This->IEnumUnknown_iface;
2455 else
2457 *ppIEnumUnknown = NULL;
2458 IEnumUnknown_Release(&This->IEnumUnknown_iface);
2461 return hr;
2464 HRESULT WINAPI WICConvertBitmapSource(REFWICPixelFormatGUID dstFormat, IWICBitmapSource *pISrc, IWICBitmapSource **ppIDst)
2466 HRESULT res;
2467 IEnumUnknown *enumconverters;
2468 IUnknown *unkconverterinfo;
2469 IWICFormatConverterInfo *converterinfo=NULL;
2470 IWICFormatConverter *converter=NULL;
2471 GUID srcFormat;
2472 WCHAR srcformatstr[39], dstformatstr[39];
2473 BOOL canconvert;
2474 ULONG num_fetched;
2476 res = IWICBitmapSource_GetPixelFormat(pISrc, &srcFormat);
2477 if (FAILED(res)) return res;
2479 if (IsEqualGUID(&srcFormat, dstFormat))
2481 IWICBitmapSource_AddRef(pISrc);
2482 *ppIDst = pISrc;
2483 return S_OK;
2486 StringFromGUID2(&srcFormat, srcformatstr, 39);
2487 StringFromGUID2(dstFormat, dstformatstr, 39);
2489 res = CreateComponentEnumerator(WICPixelFormatConverter, 0, &enumconverters);
2490 if (FAILED(res)) return res;
2492 while (!converter)
2494 res = IEnumUnknown_Next(enumconverters, 1, &unkconverterinfo, &num_fetched);
2496 if (res == S_OK)
2498 res = IUnknown_QueryInterface(unkconverterinfo, &IID_IWICFormatConverterInfo, (void**)&converterinfo);
2500 if (SUCCEEDED(res))
2502 canconvert = ConverterSupportsFormat(converterinfo, srcformatstr);
2504 if (canconvert)
2505 canconvert = ConverterSupportsFormat(converterinfo, dstformatstr);
2507 if (canconvert)
2509 res = IWICFormatConverterInfo_CreateInstance(converterinfo, &converter);
2511 if (SUCCEEDED(res))
2512 res = IWICFormatConverter_CanConvert(converter, &srcFormat, dstFormat, &canconvert);
2514 if (SUCCEEDED(res) && canconvert)
2515 res = IWICFormatConverter_Initialize(converter, pISrc, dstFormat, WICBitmapDitherTypeNone,
2516 NULL, 0.0, WICBitmapPaletteTypeCustom);
2518 if (FAILED(res) || !canconvert)
2520 if (converter)
2522 IWICFormatConverter_Release(converter);
2523 converter = NULL;
2528 IWICFormatConverterInfo_Release(converterinfo);
2531 IUnknown_Release(unkconverterinfo);
2533 else
2534 break;
2537 IEnumUnknown_Release(enumconverters);
2539 if (converter)
2541 res = IWICFormatConverter_QueryInterface(converter, &IID_IWICBitmapSource, (void **)ppIDst);
2542 IWICFormatConverter_Release(converter);
2543 return res;
2545 else
2547 FIXME("cannot convert %s to %s\n", debugstr_guid(&srcFormat), debugstr_guid(dstFormat));
2548 *ppIDst = NULL;
2549 return WINCODEC_ERR_COMPONENTNOTFOUND;