ntdll: Validate blocks in the heap pending free request list.
[wine.git] / dlls / windowscodecs / info.c
blob3b674a3e2f1f31a9419a550c20a212ba720ed982
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 <stdarg.h>
22 #define COBJMACROS
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winreg.h"
27 #include "objbase.h"
29 #include "wincodecs_private.h"
31 #include "wine/debug.h"
32 #include "wine/list.h"
33 #include "wine/rbtree.h"
34 #include "wine/heap.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
38 typedef struct {
39 IWICComponentInfo IWICComponentInfo_iface;
40 LONG ref;
41 CLSID clsid;
42 struct wine_rb_entry entry;
43 } ComponentInfo;
45 static HRESULT ComponentInfo_GetStringValue(HKEY classkey, LPCWSTR value,
46 UINT buffer_size, WCHAR *buffer, UINT *actual_size)
48 LONG ret;
49 DWORD cbdata=buffer_size * sizeof(WCHAR);
51 if (!actual_size)
52 return E_INVALIDARG;
54 ret = RegGetValueW(classkey, NULL, value, RRF_RT_REG_SZ|RRF_NOEXPAND, NULL,
55 buffer, &cbdata);
57 if (ret == ERROR_FILE_NOT_FOUND)
59 *actual_size = 0;
60 return S_OK;
63 if (ret == 0 || ret == ERROR_MORE_DATA)
64 *actual_size = cbdata/sizeof(WCHAR);
66 if (!buffer && buffer_size != 0)
67 /* Yes, native returns the correct size in this case. */
68 return E_INVALIDARG;
70 if (ret == ERROR_MORE_DATA)
71 return WINCODEC_ERR_INSUFFICIENTBUFFER;
73 return HRESULT_FROM_WIN32(ret);
76 static HRESULT ComponentInfo_GetGUIDValue(HKEY classkey, LPCWSTR value,
77 GUID *result)
79 LONG ret;
80 WCHAR guid_string[39];
81 DWORD cbdata = sizeof(guid_string);
82 HRESULT hr;
84 if (!result)
85 return E_INVALIDARG;
87 ret = RegGetValueW(classkey, NULL, value, RRF_RT_REG_SZ|RRF_NOEXPAND, NULL,
88 guid_string, &cbdata);
90 if (ret != ERROR_SUCCESS)
91 return HRESULT_FROM_WIN32(ret);
93 if (cbdata < sizeof(guid_string))
95 ERR("incomplete GUID value\n");
96 return E_FAIL;
99 hr = CLSIDFromString(guid_string, result);
101 return hr;
104 static HRESULT ComponentInfo_GetUINTValue(HKEY classkey, LPCWSTR value,
105 UINT *result)
107 LONG ret;
108 DWORD cbdata = sizeof(DWORD);
110 if (!result)
111 return E_INVALIDARG;
113 ret = RegGetValueW(classkey, NULL, value, RRF_RT_DWORD, NULL,
114 (DWORD *)result, &cbdata);
116 if (ret == ERROR_FILE_NOT_FOUND)
118 *result = 0;
119 return S_OK;
122 return HRESULT_FROM_WIN32(ret);
125 static HRESULT ComponentInfo_GetGuidList(HKEY classkey, LPCWSTR subkeyname,
126 UINT buffersize, GUID *buffer, UINT *actual_size)
128 LONG ret;
129 HKEY subkey;
130 UINT items_returned;
131 WCHAR guid_string[39];
132 DWORD guid_string_size;
133 HRESULT hr=S_OK;
135 if (!actual_size)
136 return E_INVALIDARG;
138 ret = RegOpenKeyExW(classkey, subkeyname, 0, KEY_READ, &subkey);
139 if (ret == ERROR_FILE_NOT_FOUND)
141 *actual_size = 0;
142 return S_OK;
144 else if (ret != ERROR_SUCCESS) return HRESULT_FROM_WIN32(ret);
146 if (buffer)
148 items_returned = 0;
149 guid_string_size = 39;
150 while (items_returned < buffersize)
152 ret = RegEnumKeyExW(subkey, items_returned, guid_string,
153 &guid_string_size, NULL, NULL, NULL, NULL);
155 if (ret != ERROR_SUCCESS)
157 hr = HRESULT_FROM_WIN32(ret);
158 break;
161 if (guid_string_size != 38)
163 hr = E_FAIL;
164 break;
167 hr = CLSIDFromString(guid_string, &buffer[items_returned]);
168 if (FAILED(hr))
169 break;
171 items_returned++;
172 guid_string_size = 39;
175 if (ret == ERROR_NO_MORE_ITEMS)
176 hr = S_OK;
178 *actual_size = items_returned;
180 else
182 ret = RegQueryInfoKeyW(subkey, NULL, NULL, NULL, (DWORD *)actual_size, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
183 if (ret != ERROR_SUCCESS)
184 hr = HRESULT_FROM_WIN32(ret);
187 RegCloseKey(subkey);
189 return hr;
192 typedef struct {
193 ComponentInfo base;
194 HKEY classkey;
195 WICBitmapPattern *patterns;
196 UINT pattern_count;
197 UINT patterns_size;
198 } BitmapDecoderInfo;
200 static inline BitmapDecoderInfo *impl_from_IWICBitmapDecoderInfo(IWICBitmapDecoderInfo *iface)
202 return CONTAINING_RECORD(iface, BitmapDecoderInfo, base.IWICComponentInfo_iface);
205 static HRESULT WINAPI BitmapDecoderInfo_QueryInterface(IWICBitmapDecoderInfo *iface, REFIID iid,
206 void **ppv)
208 BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
209 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
211 if (!ppv) return E_INVALIDARG;
213 if (IsEqualIID(&IID_IUnknown, iid) ||
214 IsEqualIID(&IID_IWICComponentInfo, iid) ||
215 IsEqualIID(&IID_IWICBitmapCodecInfo, iid) ||
216 IsEqualIID(&IID_IWICBitmapDecoderInfo ,iid))
218 *ppv = &This->base.IWICComponentInfo_iface;
220 else
222 *ppv = NULL;
223 return E_NOINTERFACE;
226 IUnknown_AddRef((IUnknown*)*ppv);
227 return S_OK;
230 static ULONG WINAPI BitmapDecoderInfo_AddRef(IWICBitmapDecoderInfo *iface)
232 BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
233 ULONG ref = InterlockedIncrement(&This->base.ref);
235 TRACE("(%p) refcount=%lu\n", iface, ref);
237 return ref;
240 static ULONG WINAPI BitmapDecoderInfo_Release(IWICBitmapDecoderInfo *iface)
242 BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
243 ULONG ref = InterlockedDecrement(&This->base.ref);
245 TRACE("(%p) refcount=%lu\n", iface, ref);
247 if (ref == 0)
249 RegCloseKey(This->classkey);
250 heap_free(This->patterns);
251 HeapFree(GetProcessHeap(), 0, This);
254 return ref;
257 static HRESULT WINAPI BitmapDecoderInfo_GetComponentType(IWICBitmapDecoderInfo *iface,
258 WICComponentType *pType)
260 TRACE("(%p,%p)\n", iface, pType);
261 if (!pType) return E_INVALIDARG;
262 *pType = WICDecoder;
263 return S_OK;
266 static HRESULT WINAPI BitmapDecoderInfo_GetCLSID(IWICBitmapDecoderInfo *iface, CLSID *pclsid)
268 BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
269 TRACE("(%p,%p)\n", iface, pclsid);
271 if (!pclsid)
272 return E_INVALIDARG;
274 *pclsid = This->base.clsid;
275 return S_OK;
278 static HRESULT WINAPI BitmapDecoderInfo_GetSigningStatus(IWICBitmapDecoderInfo *iface, DWORD *pStatus)
280 FIXME("(%p,%p): stub\n", iface, pStatus);
281 return E_NOTIMPL;
284 static HRESULT WINAPI BitmapDecoderInfo_GetAuthor(IWICBitmapDecoderInfo *iface, UINT cchAuthor,
285 WCHAR *wzAuthor, UINT *pcchActual)
287 BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
289 TRACE("(%p,%u,%p,%p)\n", iface, cchAuthor, wzAuthor, pcchActual);
291 return ComponentInfo_GetStringValue(This->classkey, L"Author", cchAuthor, wzAuthor, pcchActual);
294 static HRESULT WINAPI BitmapDecoderInfo_GetVendorGUID(IWICBitmapDecoderInfo *iface, GUID *pguidVendor)
296 BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
298 TRACE("(%p,%p)\n", iface, pguidVendor);
300 return ComponentInfo_GetGUIDValue(This->classkey, L"Vendor", pguidVendor);
303 static HRESULT WINAPI BitmapDecoderInfo_GetVersion(IWICBitmapDecoderInfo *iface, UINT cchVersion,
304 WCHAR *wzVersion, UINT *pcchActual)
306 BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
308 TRACE("(%p,%u,%p,%p)\n", iface, cchVersion, wzVersion, pcchActual);
310 return ComponentInfo_GetStringValue(This->classkey, L"Version",
311 cchVersion, wzVersion, pcchActual);
314 static HRESULT WINAPI BitmapDecoderInfo_GetSpecVersion(IWICBitmapDecoderInfo *iface, UINT cchSpecVersion,
315 WCHAR *wzSpecVersion, UINT *pcchActual)
317 BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
319 TRACE("(%p,%u,%p,%p)\n", iface, cchSpecVersion, wzSpecVersion, pcchActual);
321 return ComponentInfo_GetStringValue(This->classkey, L"SpecVersion",
322 cchSpecVersion, wzSpecVersion, pcchActual);
325 static HRESULT WINAPI BitmapDecoderInfo_GetFriendlyName(IWICBitmapDecoderInfo *iface, UINT cchFriendlyName,
326 WCHAR *wzFriendlyName, UINT *pcchActual)
328 BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
330 TRACE("(%p,%u,%p,%p)\n", iface, cchFriendlyName, wzFriendlyName, pcchActual);
332 return ComponentInfo_GetStringValue(This->classkey, L"FriendlyName",
333 cchFriendlyName, wzFriendlyName, pcchActual);
336 static HRESULT WINAPI BitmapDecoderInfo_GetContainerFormat(IWICBitmapDecoderInfo *iface,
337 GUID *pguidContainerFormat)
339 BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
340 TRACE("(%p,%p)\n", iface, pguidContainerFormat);
341 return ComponentInfo_GetGUIDValue(This->classkey, L"ContainerFormat", pguidContainerFormat);
344 static HRESULT WINAPI BitmapDecoderInfo_GetPixelFormats(IWICBitmapDecoderInfo *iface,
345 UINT cFormats, GUID *pguidPixelFormats, UINT *pcActual)
347 BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
348 TRACE("(%p,%u,%p,%p)\n", iface, cFormats, pguidPixelFormats, pcActual);
349 return ComponentInfo_GetGuidList(This->classkey, L"Formats", cFormats, pguidPixelFormats, pcActual);
352 static HRESULT WINAPI BitmapDecoderInfo_GetColorManagementVersion(IWICBitmapDecoderInfo *iface,
353 UINT cchColorManagementVersion, WCHAR *wzColorManagementVersion, UINT *pcchActual)
355 FIXME("(%p,%u,%p,%p): stub\n", iface, cchColorManagementVersion, wzColorManagementVersion, pcchActual);
356 return E_NOTIMPL;
359 static HRESULT WINAPI BitmapDecoderInfo_GetDeviceManufacturer(IWICBitmapDecoderInfo *iface,
360 UINT cchDeviceManufacturer, WCHAR *wzDeviceManufacturer, UINT *pcchActual)
362 FIXME("(%p,%u,%p,%p): stub\n", iface, cchDeviceManufacturer, wzDeviceManufacturer, pcchActual);
363 return E_NOTIMPL;
366 static HRESULT WINAPI BitmapDecoderInfo_GetDeviceModels(IWICBitmapDecoderInfo *iface,
367 UINT cchDeviceModels, WCHAR *wzDeviceModels, UINT *pcchActual)
369 FIXME("(%p,%u,%p,%p): stub\n", iface, cchDeviceModels, wzDeviceModels, pcchActual);
370 return E_NOTIMPL;
373 static HRESULT WINAPI BitmapDecoderInfo_GetMimeTypes(IWICBitmapDecoderInfo *iface,
374 UINT cchMimeTypes, WCHAR *wzMimeTypes, UINT *pcchActual)
376 BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
378 TRACE("(%p,%u,%p,%p)\n", iface, cchMimeTypes, wzMimeTypes, pcchActual);
380 return ComponentInfo_GetStringValue(This->classkey, L"MimeTypes",
381 cchMimeTypes, wzMimeTypes, pcchActual);
384 static HRESULT WINAPI BitmapDecoderInfo_GetFileExtensions(IWICBitmapDecoderInfo *iface,
385 UINT cchFileExtensions, WCHAR *wzFileExtensions, UINT *pcchActual)
387 BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
389 TRACE("(%p,%u,%p,%p)\n", iface, cchFileExtensions, wzFileExtensions, pcchActual);
391 return ComponentInfo_GetStringValue(This->classkey, L"FileExtensions",
392 cchFileExtensions, wzFileExtensions, pcchActual);
395 static HRESULT WINAPI BitmapDecoderInfo_DoesSupportAnimation(IWICBitmapDecoderInfo *iface,
396 BOOL *pfSupportAnimation)
398 FIXME("(%p,%p): stub\n", iface, pfSupportAnimation);
399 return E_NOTIMPL;
402 static HRESULT WINAPI BitmapDecoderInfo_DoesSupportChromaKey(IWICBitmapDecoderInfo *iface,
403 BOOL *pfSupportChromaKey)
405 FIXME("(%p,%p): stub\n", iface, pfSupportChromaKey);
406 return E_NOTIMPL;
409 static HRESULT WINAPI BitmapDecoderInfo_DoesSupportLossless(IWICBitmapDecoderInfo *iface,
410 BOOL *pfSupportLossless)
412 FIXME("(%p,%p): stub\n", iface, pfSupportLossless);
413 return E_NOTIMPL;
416 static HRESULT WINAPI BitmapDecoderInfo_DoesSupportMultiframe(IWICBitmapDecoderInfo *iface,
417 BOOL *pfSupportMultiframe)
419 FIXME("(%p,%p): stub\n", iface, pfSupportMultiframe);
420 return E_NOTIMPL;
423 static HRESULT WINAPI BitmapDecoderInfo_MatchesMimeType(IWICBitmapDecoderInfo *iface,
424 LPCWSTR wzMimeType, BOOL *pfMatches)
426 FIXME("(%p,%s,%p): stub\n", iface, debugstr_w(wzMimeType), pfMatches);
427 return E_NOTIMPL;
430 static HRESULT WINAPI BitmapDecoderInfo_GetPatterns(IWICBitmapDecoderInfo *iface,
431 UINT cbSizePatterns, WICBitmapPattern *pPatterns, UINT *pcPatterns, UINT *pcbPatternsActual)
433 BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
435 TRACE("(%p,%i,%p,%p,%p)\n", iface, cbSizePatterns, pPatterns, pcPatterns, pcbPatternsActual);
437 if (!pcPatterns || !pcbPatternsActual) return E_INVALIDARG;
439 *pcPatterns = This->pattern_count;
440 *pcbPatternsActual = This->patterns_size;
441 if (pPatterns)
443 if (This->patterns_size && cbSizePatterns < This->patterns_size)
444 return WINCODEC_ERR_INSUFFICIENTBUFFER;
445 memcpy(pPatterns, This->patterns, This->patterns_size);
447 return S_OK;
450 static HRESULT WINAPI BitmapDecoderInfo_MatchesPattern(IWICBitmapDecoderInfo *iface,
451 IStream *pIStream, BOOL *pfMatches)
453 BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
454 HRESULT hr;
455 UINT i;
456 ULONG pos;
457 BYTE *data=NULL;
458 ULONG datasize=0;
459 ULONG bytesread;
460 LARGE_INTEGER seekpos;
462 TRACE("(%p,%p,%p)\n", iface, pIStream, pfMatches);
464 for (i=0; i < This->pattern_count; i++)
466 if (datasize < This->patterns[i].Length)
468 HeapFree(GetProcessHeap(), 0, data);
469 datasize = This->patterns[i].Length;
470 data = HeapAlloc(GetProcessHeap(), 0, This->patterns[i].Length);
471 if (!data)
473 hr = E_OUTOFMEMORY;
474 break;
478 if (This->patterns[i].EndOfStream)
479 seekpos.QuadPart = -This->patterns[i].Position.QuadPart;
480 else
481 seekpos.QuadPart = This->patterns[i].Position.QuadPart;
482 hr = IStream_Seek(pIStream, seekpos, This->patterns[i].EndOfStream ? STREAM_SEEK_END : STREAM_SEEK_SET, NULL);
483 if (hr == STG_E_INVALIDFUNCTION) continue; /* before start of stream */
484 if (FAILED(hr)) break;
486 hr = IStream_Read(pIStream, data, This->patterns[i].Length, &bytesread);
487 if (hr == S_FALSE || (hr == S_OK && bytesread != This->patterns[i].Length)) /* past end of stream */
488 continue;
489 if (FAILED(hr)) break;
491 for (pos=0; pos < This->patterns[i].Length; pos++)
493 if ((data[pos] & This->patterns[i].Mask[pos]) != This->patterns[i].Pattern[pos])
494 break;
496 if (pos == This->patterns[i].Length) /* matches pattern */
498 hr = S_OK;
499 *pfMatches = TRUE;
500 break;
504 if (i == This->pattern_count) /* does not match any pattern */
506 hr = S_OK;
507 *pfMatches = FALSE;
510 HeapFree(GetProcessHeap(), 0, data);
511 return hr;
514 static HRESULT WINAPI BitmapDecoderInfo_CreateInstance(IWICBitmapDecoderInfo *iface,
515 IWICBitmapDecoder **ppIBitmapDecoder)
517 BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
519 TRACE("(%p,%p)\n", iface, ppIBitmapDecoder);
521 return create_instance(&This->base.clsid, &IID_IWICBitmapDecoder, (void**)ppIBitmapDecoder);
524 static const IWICBitmapDecoderInfoVtbl BitmapDecoderInfo_Vtbl = {
525 BitmapDecoderInfo_QueryInterface,
526 BitmapDecoderInfo_AddRef,
527 BitmapDecoderInfo_Release,
528 BitmapDecoderInfo_GetComponentType,
529 BitmapDecoderInfo_GetCLSID,
530 BitmapDecoderInfo_GetSigningStatus,
531 BitmapDecoderInfo_GetAuthor,
532 BitmapDecoderInfo_GetVendorGUID,
533 BitmapDecoderInfo_GetVersion,
534 BitmapDecoderInfo_GetSpecVersion,
535 BitmapDecoderInfo_GetFriendlyName,
536 BitmapDecoderInfo_GetContainerFormat,
537 BitmapDecoderInfo_GetPixelFormats,
538 BitmapDecoderInfo_GetColorManagementVersion,
539 BitmapDecoderInfo_GetDeviceManufacturer,
540 BitmapDecoderInfo_GetDeviceModels,
541 BitmapDecoderInfo_GetMimeTypes,
542 BitmapDecoderInfo_GetFileExtensions,
543 BitmapDecoderInfo_DoesSupportAnimation,
544 BitmapDecoderInfo_DoesSupportChromaKey,
545 BitmapDecoderInfo_DoesSupportLossless,
546 BitmapDecoderInfo_DoesSupportMultiframe,
547 BitmapDecoderInfo_MatchesMimeType,
548 BitmapDecoderInfo_GetPatterns,
549 BitmapDecoderInfo_MatchesPattern,
550 BitmapDecoderInfo_CreateInstance
553 static void read_bitmap_patterns(BitmapDecoderInfo *info)
555 DWORD pattern_count=0;
556 UINT patterns_size=0;
557 WCHAR subkeyname[11];
558 LONG res;
559 HKEY patternskey, patternkey;
560 UINT i;
561 WICBitmapPattern *patterns;
562 BYTE *patterns_ptr;
563 DWORD length, valuesize;
565 res = RegOpenKeyExW(info->classkey, L"Patterns", 0, KEY_READ, &patternskey);
566 if (res != ERROR_SUCCESS) return;
568 res = RegQueryInfoKeyW(patternskey, NULL, NULL, NULL, &pattern_count, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
569 if (res != ERROR_SUCCESS)
571 RegCloseKey(patternskey);
572 return;
575 patterns_size = pattern_count * sizeof(WICBitmapPattern);
576 patterns = heap_alloc(patterns_size);
577 if (!patterns)
579 RegCloseKey(patternskey);
580 return;
583 for (i=0; res == ERROR_SUCCESS && i < pattern_count; i++)
585 swprintf(subkeyname, 11, L"%u", i);
586 res = RegOpenKeyExW(patternskey, subkeyname, 0, KEY_READ, &patternkey);
587 if (res != ERROR_SUCCESS) break;
589 valuesize = sizeof(ULONG);
590 res = RegGetValueW(patternkey, NULL, L"Length", RRF_RT_DWORD, NULL, &length, &valuesize);
591 if (res == ERROR_SUCCESS)
593 patterns_size += length*2;
594 patterns[i].Length = length;
596 valuesize = sizeof(BOOL);
597 res = RegGetValueW(patternkey, NULL, L"EndOfStream", RRF_RT_DWORD, NULL,
598 &patterns[i].EndOfStream, &valuesize);
599 if (res) patterns[i].EndOfStream = 0;
601 patterns[i].Position.QuadPart = 0;
602 valuesize = sizeof(ULARGE_INTEGER);
603 res = RegGetValueW(patternkey, NULL, L"Position", RRF_RT_DWORD|RRF_RT_QWORD, NULL,
604 &patterns[i].Position, &valuesize);
607 RegCloseKey(patternkey);
610 if (res != ERROR_SUCCESS || !(patterns_ptr = heap_realloc(patterns, patterns_size)))
612 heap_free(patterns);
613 RegCloseKey(patternskey);
614 return;
616 patterns = (WICBitmapPattern*)patterns_ptr;
617 patterns_ptr += pattern_count * sizeof(*patterns);
619 for (i=0; res == ERROR_SUCCESS && i < pattern_count; i++)
621 swprintf(subkeyname, 11, L"%u", i);
622 res = RegOpenKeyExW(patternskey, subkeyname, 0, KEY_READ, &patternkey);
623 if (res != ERROR_SUCCESS) break;
625 length = patterns[i].Length;
626 patterns[i].Pattern = patterns_ptr;
627 valuesize = length;
628 res = RegGetValueW(patternkey, NULL, L"Pattern", RRF_RT_REG_BINARY, NULL,
629 patterns[i].Pattern, &valuesize);
630 patterns_ptr += length;
632 if (res == ERROR_SUCCESS)
634 patterns[i].Mask = patterns_ptr;
635 valuesize = length;
636 res = RegGetValueW(patternkey, NULL, L"Mask", RRF_RT_REG_BINARY, NULL,
637 patterns[i].Mask, &valuesize);
638 patterns_ptr += length;
641 RegCloseKey(patternkey);
644 RegCloseKey(patternskey);
646 if (res != ERROR_SUCCESS)
648 heap_free(patterns);
649 return;
652 info->pattern_count = pattern_count;
653 info->patterns_size = patterns_size;
654 info->patterns = patterns;
657 static HRESULT BitmapDecoderInfo_Constructor(HKEY classkey, REFCLSID clsid, ComponentInfo **ret)
659 BitmapDecoderInfo *This;
661 This = heap_alloc_zero(sizeof(BitmapDecoderInfo));
662 if (!This)
664 RegCloseKey(classkey);
665 return E_OUTOFMEMORY;
668 This->base.IWICComponentInfo_iface.lpVtbl = (const IWICComponentInfoVtbl*)&BitmapDecoderInfo_Vtbl;
669 This->base.ref = 1;
670 This->classkey = classkey;
671 This->base.clsid = *clsid;
673 read_bitmap_patterns(This);
675 *ret = &This->base;
676 return S_OK;
679 typedef struct {
680 ComponentInfo base;
681 HKEY classkey;
682 } BitmapEncoderInfo;
684 static inline BitmapEncoderInfo *impl_from_IWICBitmapEncoderInfo(IWICBitmapEncoderInfo *iface)
686 return CONTAINING_RECORD(iface, BitmapEncoderInfo, base.IWICComponentInfo_iface);
689 static HRESULT WINAPI BitmapEncoderInfo_QueryInterface(IWICBitmapEncoderInfo *iface, REFIID iid,
690 void **ppv)
692 BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
693 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
695 if (!ppv) return E_INVALIDARG;
697 if (IsEqualIID(&IID_IUnknown, iid) ||
698 IsEqualIID(&IID_IWICComponentInfo, iid) ||
699 IsEqualIID(&IID_IWICBitmapCodecInfo, iid) ||
700 IsEqualIID(&IID_IWICBitmapEncoderInfo ,iid))
702 *ppv = &This->base.IWICComponentInfo_iface;
704 else
706 *ppv = NULL;
707 return E_NOINTERFACE;
710 IUnknown_AddRef((IUnknown*)*ppv);
711 return S_OK;
714 static ULONG WINAPI BitmapEncoderInfo_AddRef(IWICBitmapEncoderInfo *iface)
716 BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
717 ULONG ref = InterlockedIncrement(&This->base.ref);
719 TRACE("(%p) refcount=%lu\n", iface, ref);
721 return ref;
724 static ULONG WINAPI BitmapEncoderInfo_Release(IWICBitmapEncoderInfo *iface)
726 BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
727 ULONG ref = InterlockedDecrement(&This->base.ref);
729 TRACE("(%p) refcount=%lu\n", iface, ref);
731 if (ref == 0)
733 RegCloseKey(This->classkey);
734 HeapFree(GetProcessHeap(), 0, This);
737 return ref;
740 static HRESULT WINAPI BitmapEncoderInfo_GetComponentType(IWICBitmapEncoderInfo *iface,
741 WICComponentType *pType)
743 TRACE("(%p,%p)\n", iface, pType);
744 if (!pType) return E_INVALIDARG;
745 *pType = WICEncoder;
746 return S_OK;
749 static HRESULT WINAPI BitmapEncoderInfo_GetCLSID(IWICBitmapEncoderInfo *iface, CLSID *pclsid)
751 BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
752 TRACE("(%p,%p)\n", iface, pclsid);
754 if (!pclsid)
755 return E_INVALIDARG;
757 *pclsid = This->base.clsid;
758 return S_OK;
761 static HRESULT WINAPI BitmapEncoderInfo_GetSigningStatus(IWICBitmapEncoderInfo *iface, DWORD *pStatus)
763 FIXME("(%p,%p): stub\n", iface, pStatus);
764 return E_NOTIMPL;
767 static HRESULT WINAPI BitmapEncoderInfo_GetAuthor(IWICBitmapEncoderInfo *iface, UINT cchAuthor,
768 WCHAR *wzAuthor, UINT *pcchActual)
770 BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
772 TRACE("(%p,%u,%p,%p)\n", iface, cchAuthor, wzAuthor, pcchActual);
774 return ComponentInfo_GetStringValue(This->classkey, L"Author", cchAuthor, wzAuthor, pcchActual);
777 static HRESULT WINAPI BitmapEncoderInfo_GetVendorGUID(IWICBitmapEncoderInfo *iface, GUID *pguidVendor)
779 BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
781 TRACE("(%p,%p)\n", iface, pguidVendor);
783 return ComponentInfo_GetGUIDValue(This->classkey, L"Vendor", pguidVendor);
786 static HRESULT WINAPI BitmapEncoderInfo_GetVersion(IWICBitmapEncoderInfo *iface, UINT cchVersion,
787 WCHAR *wzVersion, UINT *pcchActual)
789 BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
791 TRACE("(%p,%u,%p,%p)\n", iface, cchVersion, wzVersion, pcchActual);
793 return ComponentInfo_GetStringValue(This->classkey, L"Version",
794 cchVersion, wzVersion, pcchActual);
797 static HRESULT WINAPI BitmapEncoderInfo_GetSpecVersion(IWICBitmapEncoderInfo *iface, UINT cchSpecVersion,
798 WCHAR *wzSpecVersion, UINT *pcchActual)
800 BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
802 TRACE("(%p,%u,%p,%p)\n", iface, cchSpecVersion, wzSpecVersion, pcchActual);
804 return ComponentInfo_GetStringValue(This->classkey, L"SpecVersion",
805 cchSpecVersion, wzSpecVersion, pcchActual);
808 static HRESULT WINAPI BitmapEncoderInfo_GetFriendlyName(IWICBitmapEncoderInfo *iface, UINT cchFriendlyName,
809 WCHAR *wzFriendlyName, UINT *pcchActual)
811 BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
813 TRACE("(%p,%u,%p,%p)\n", iface, cchFriendlyName, wzFriendlyName, pcchActual);
815 return ComponentInfo_GetStringValue(This->classkey, L"FriendlyName",
816 cchFriendlyName, wzFriendlyName, pcchActual);
819 static HRESULT WINAPI BitmapEncoderInfo_GetContainerFormat(IWICBitmapEncoderInfo *iface,
820 GUID *pguidContainerFormat)
822 BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
823 TRACE("(%p,%p)\n", iface, pguidContainerFormat);
824 return ComponentInfo_GetGUIDValue(This->classkey, L"ContainerFormat", pguidContainerFormat);
827 static HRESULT WINAPI BitmapEncoderInfo_GetPixelFormats(IWICBitmapEncoderInfo *iface,
828 UINT cFormats, GUID *pguidPixelFormats, UINT *pcActual)
830 BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
831 TRACE("(%p,%u,%p,%p)\n", iface, cFormats, pguidPixelFormats, pcActual);
832 return ComponentInfo_GetGuidList(This->classkey, L"Formats", cFormats, pguidPixelFormats, pcActual);
835 static HRESULT WINAPI BitmapEncoderInfo_GetColorManagementVersion(IWICBitmapEncoderInfo *iface,
836 UINT cchColorManagementVersion, WCHAR *wzColorManagementVersion, UINT *pcchActual)
838 FIXME("(%p,%u,%p,%p): stub\n", iface, cchColorManagementVersion, wzColorManagementVersion, pcchActual);
839 return E_NOTIMPL;
842 static HRESULT WINAPI BitmapEncoderInfo_GetDeviceManufacturer(IWICBitmapEncoderInfo *iface,
843 UINT cchDeviceManufacturer, WCHAR *wzDeviceManufacturer, UINT *pcchActual)
845 FIXME("(%p,%u,%p,%p): stub\n", iface, cchDeviceManufacturer, wzDeviceManufacturer, pcchActual);
846 return E_NOTIMPL;
849 static HRESULT WINAPI BitmapEncoderInfo_GetDeviceModels(IWICBitmapEncoderInfo *iface,
850 UINT cchDeviceModels, WCHAR *wzDeviceModels, UINT *pcchActual)
852 FIXME("(%p,%u,%p,%p): stub\n", iface, cchDeviceModels, wzDeviceModels, pcchActual);
853 return E_NOTIMPL;
856 static HRESULT WINAPI BitmapEncoderInfo_GetMimeTypes(IWICBitmapEncoderInfo *iface,
857 UINT cchMimeTypes, WCHAR *wzMimeTypes, UINT *pcchActual)
859 BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
861 TRACE("(%p,%u,%p,%p)\n", iface, cchMimeTypes, wzMimeTypes, pcchActual);
863 return ComponentInfo_GetStringValue(This->classkey, L"MimeTypes",
864 cchMimeTypes, wzMimeTypes, pcchActual);
867 static HRESULT WINAPI BitmapEncoderInfo_GetFileExtensions(IWICBitmapEncoderInfo *iface,
868 UINT cchFileExtensions, WCHAR *wzFileExtensions, UINT *pcchActual)
870 BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
872 TRACE("(%p,%u,%p,%p)\n", iface, cchFileExtensions, wzFileExtensions, pcchActual);
874 return ComponentInfo_GetStringValue(This->classkey, L"FileExtensions",
875 cchFileExtensions, wzFileExtensions, pcchActual);
878 static HRESULT WINAPI BitmapEncoderInfo_DoesSupportAnimation(IWICBitmapEncoderInfo *iface,
879 BOOL *pfSupportAnimation)
881 FIXME("(%p,%p): stub\n", iface, pfSupportAnimation);
882 return E_NOTIMPL;
885 static HRESULT WINAPI BitmapEncoderInfo_DoesSupportChromaKey(IWICBitmapEncoderInfo *iface,
886 BOOL *pfSupportChromaKey)
888 FIXME("(%p,%p): stub\n", iface, pfSupportChromaKey);
889 return E_NOTIMPL;
892 static HRESULT WINAPI BitmapEncoderInfo_DoesSupportLossless(IWICBitmapEncoderInfo *iface,
893 BOOL *pfSupportLossless)
895 FIXME("(%p,%p): stub\n", iface, pfSupportLossless);
896 return E_NOTIMPL;
899 static HRESULT WINAPI BitmapEncoderInfo_DoesSupportMultiframe(IWICBitmapEncoderInfo *iface,
900 BOOL *pfSupportMultiframe)
902 FIXME("(%p,%p): stub\n", iface, pfSupportMultiframe);
903 return E_NOTIMPL;
906 static HRESULT WINAPI BitmapEncoderInfo_MatchesMimeType(IWICBitmapEncoderInfo *iface,
907 LPCWSTR wzMimeType, BOOL *pfMatches)
909 FIXME("(%p,%s,%p): stub\n", iface, debugstr_w(wzMimeType), pfMatches);
910 return E_NOTIMPL;
913 static HRESULT WINAPI BitmapEncoderInfo_CreateInstance(IWICBitmapEncoderInfo *iface,
914 IWICBitmapEncoder **ppIBitmapEncoder)
916 BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
918 TRACE("(%p,%p)\n", iface, ppIBitmapEncoder);
920 return create_instance(&This->base.clsid, &IID_IWICBitmapEncoder, (void**)ppIBitmapEncoder);
923 static const IWICBitmapEncoderInfoVtbl BitmapEncoderInfo_Vtbl = {
924 BitmapEncoderInfo_QueryInterface,
925 BitmapEncoderInfo_AddRef,
926 BitmapEncoderInfo_Release,
927 BitmapEncoderInfo_GetComponentType,
928 BitmapEncoderInfo_GetCLSID,
929 BitmapEncoderInfo_GetSigningStatus,
930 BitmapEncoderInfo_GetAuthor,
931 BitmapEncoderInfo_GetVendorGUID,
932 BitmapEncoderInfo_GetVersion,
933 BitmapEncoderInfo_GetSpecVersion,
934 BitmapEncoderInfo_GetFriendlyName,
935 BitmapEncoderInfo_GetContainerFormat,
936 BitmapEncoderInfo_GetPixelFormats,
937 BitmapEncoderInfo_GetColorManagementVersion,
938 BitmapEncoderInfo_GetDeviceManufacturer,
939 BitmapEncoderInfo_GetDeviceModels,
940 BitmapEncoderInfo_GetMimeTypes,
941 BitmapEncoderInfo_GetFileExtensions,
942 BitmapEncoderInfo_DoesSupportAnimation,
943 BitmapEncoderInfo_DoesSupportChromaKey,
944 BitmapEncoderInfo_DoesSupportLossless,
945 BitmapEncoderInfo_DoesSupportMultiframe,
946 BitmapEncoderInfo_MatchesMimeType,
947 BitmapEncoderInfo_CreateInstance
950 static HRESULT BitmapEncoderInfo_Constructor(HKEY classkey, REFCLSID clsid, ComponentInfo **ret)
952 BitmapEncoderInfo *This;
954 This = HeapAlloc(GetProcessHeap(), 0, sizeof(BitmapEncoderInfo));
955 if (!This)
957 RegCloseKey(classkey);
958 return E_OUTOFMEMORY;
961 This->base.IWICComponentInfo_iface.lpVtbl = (const IWICComponentInfoVtbl*)&BitmapEncoderInfo_Vtbl;
962 This->base.ref = 1;
963 This->classkey = classkey;
964 This->base.clsid = *clsid;
966 *ret = &This->base;
967 return S_OK;
970 typedef struct {
971 ComponentInfo base;
972 HKEY classkey;
973 } FormatConverterInfo;
975 static inline FormatConverterInfo *impl_from_IWICFormatConverterInfo(IWICFormatConverterInfo *iface)
977 return CONTAINING_RECORD(iface, FormatConverterInfo, base.IWICComponentInfo_iface);
980 static HRESULT WINAPI FormatConverterInfo_QueryInterface(IWICFormatConverterInfo *iface, REFIID iid,
981 void **ppv)
983 FormatConverterInfo *This = impl_from_IWICFormatConverterInfo(iface);
984 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
986 if (!ppv) return E_INVALIDARG;
988 if (IsEqualIID(&IID_IUnknown, iid) ||
989 IsEqualIID(&IID_IWICComponentInfo, iid) ||
990 IsEqualIID(&IID_IWICFormatConverterInfo ,iid))
992 *ppv = &This->base.IWICComponentInfo_iface;
994 else
996 *ppv = NULL;
997 return E_NOINTERFACE;
1000 IUnknown_AddRef((IUnknown*)*ppv);
1001 return S_OK;
1004 static ULONG WINAPI FormatConverterInfo_AddRef(IWICFormatConverterInfo *iface)
1006 FormatConverterInfo *This = impl_from_IWICFormatConverterInfo(iface);
1007 ULONG ref = InterlockedIncrement(&This->base.ref);
1009 TRACE("(%p) refcount=%lu\n", iface, ref);
1011 return ref;
1014 static ULONG WINAPI FormatConverterInfo_Release(IWICFormatConverterInfo *iface)
1016 FormatConverterInfo *This = impl_from_IWICFormatConverterInfo(iface);
1017 ULONG ref = InterlockedDecrement(&This->base.ref);
1019 TRACE("(%p) refcount=%lu\n", iface, ref);
1021 if (ref == 0)
1023 RegCloseKey(This->classkey);
1024 HeapFree(GetProcessHeap(), 0, This);
1027 return ref;
1030 static HRESULT WINAPI FormatConverterInfo_GetComponentType(IWICFormatConverterInfo *iface,
1031 WICComponentType *pType)
1033 TRACE("(%p,%p)\n", iface, pType);
1034 if (!pType) return E_INVALIDARG;
1035 *pType = WICPixelFormatConverter;
1036 return S_OK;
1039 static HRESULT WINAPI FormatConverterInfo_GetCLSID(IWICFormatConverterInfo *iface, CLSID *pclsid)
1041 FormatConverterInfo *This = impl_from_IWICFormatConverterInfo(iface);
1042 TRACE("(%p,%p)\n", iface, pclsid);
1044 if (!pclsid)
1045 return E_INVALIDARG;
1047 *pclsid = This->base.clsid;
1048 return S_OK;
1051 static HRESULT WINAPI FormatConverterInfo_GetSigningStatus(IWICFormatConverterInfo *iface, DWORD *pStatus)
1053 FIXME("(%p,%p): stub\n", iface, pStatus);
1054 return E_NOTIMPL;
1057 static HRESULT WINAPI FormatConverterInfo_GetAuthor(IWICFormatConverterInfo *iface, UINT cchAuthor,
1058 WCHAR *wzAuthor, UINT *pcchActual)
1060 FormatConverterInfo *This = impl_from_IWICFormatConverterInfo(iface);
1062 TRACE("(%p,%u,%p,%p)\n", iface, cchAuthor, wzAuthor, pcchActual);
1064 return ComponentInfo_GetStringValue(This->classkey, L"Author", cchAuthor, wzAuthor, pcchActual);
1067 static HRESULT WINAPI FormatConverterInfo_GetVendorGUID(IWICFormatConverterInfo *iface, GUID *pguidVendor)
1069 FormatConverterInfo *This = impl_from_IWICFormatConverterInfo(iface);
1071 TRACE("(%p,%p)\n", iface, pguidVendor);
1073 return ComponentInfo_GetGUIDValue(This->classkey, L"Vendor", pguidVendor);
1076 static HRESULT WINAPI FormatConverterInfo_GetVersion(IWICFormatConverterInfo *iface, UINT cchVersion,
1077 WCHAR *wzVersion, UINT *pcchActual)
1079 FormatConverterInfo *This = impl_from_IWICFormatConverterInfo(iface);
1081 TRACE("(%p,%u,%p,%p)\n", iface, cchVersion, wzVersion, pcchActual);
1083 return ComponentInfo_GetStringValue(This->classkey, L"Version",
1084 cchVersion, wzVersion, pcchActual);
1087 static HRESULT WINAPI FormatConverterInfo_GetSpecVersion(IWICFormatConverterInfo *iface, UINT cchSpecVersion,
1088 WCHAR *wzSpecVersion, UINT *pcchActual)
1090 FormatConverterInfo *This = impl_from_IWICFormatConverterInfo(iface);
1092 TRACE("(%p,%u,%p,%p)\n", iface, cchSpecVersion, wzSpecVersion, pcchActual);
1094 return ComponentInfo_GetStringValue(This->classkey, L"SpecVersion",
1095 cchSpecVersion, wzSpecVersion, pcchActual);
1098 static HRESULT WINAPI FormatConverterInfo_GetFriendlyName(IWICFormatConverterInfo *iface, UINT cchFriendlyName,
1099 WCHAR *wzFriendlyName, UINT *pcchActual)
1101 FormatConverterInfo *This = impl_from_IWICFormatConverterInfo(iface);
1103 TRACE("(%p,%u,%p,%p)\n", iface, cchFriendlyName, wzFriendlyName, pcchActual);
1105 return ComponentInfo_GetStringValue(This->classkey, L"FriendlyName",
1106 cchFriendlyName, wzFriendlyName, pcchActual);
1109 static HRESULT WINAPI FormatConverterInfo_GetPixelFormats(IWICFormatConverterInfo *iface,
1110 UINT cFormats, GUID *pguidPixelFormats, UINT *pcActual)
1112 FIXME("(%p,%u,%p,%p): stub\n", iface, cFormats, pguidPixelFormats, pcActual);
1113 return E_NOTIMPL;
1116 static HRESULT WINAPI FormatConverterInfo_CreateInstance(IWICFormatConverterInfo *iface,
1117 IWICFormatConverter **ppIFormatConverter)
1119 FormatConverterInfo *This = impl_from_IWICFormatConverterInfo(iface);
1121 TRACE("(%p,%p)\n", iface, ppIFormatConverter);
1123 return create_instance(&This->base.clsid, &IID_IWICFormatConverter,
1124 (void**)ppIFormatConverter);
1127 static BOOL ConverterSupportsFormat(IWICFormatConverterInfo *iface, const WCHAR *formatguid)
1129 LONG res;
1130 FormatConverterInfo *This = impl_from_IWICFormatConverterInfo(iface);
1131 HKEY formats_key, guid_key;
1133 /* Avoid testing using IWICFormatConverter_GetPixelFormats because that
1134 would be O(n). A registry test should do better. */
1136 res = RegOpenKeyExW(This->classkey, L"PixelFormats", 0, KEY_READ, &formats_key);
1137 if (res != ERROR_SUCCESS) return FALSE;
1139 res = RegOpenKeyExW(formats_key, formatguid, 0, KEY_READ, &guid_key);
1140 if (res == ERROR_SUCCESS) RegCloseKey(guid_key);
1142 RegCloseKey(formats_key);
1144 return (res == ERROR_SUCCESS);
1147 static const IWICFormatConverterInfoVtbl FormatConverterInfo_Vtbl = {
1148 FormatConverterInfo_QueryInterface,
1149 FormatConverterInfo_AddRef,
1150 FormatConverterInfo_Release,
1151 FormatConverterInfo_GetComponentType,
1152 FormatConverterInfo_GetCLSID,
1153 FormatConverterInfo_GetSigningStatus,
1154 FormatConverterInfo_GetAuthor,
1155 FormatConverterInfo_GetVendorGUID,
1156 FormatConverterInfo_GetVersion,
1157 FormatConverterInfo_GetSpecVersion,
1158 FormatConverterInfo_GetFriendlyName,
1159 FormatConverterInfo_GetPixelFormats,
1160 FormatConverterInfo_CreateInstance
1163 static HRESULT FormatConverterInfo_Constructor(HKEY classkey, REFCLSID clsid, ComponentInfo **ret)
1165 FormatConverterInfo *This;
1167 This = HeapAlloc(GetProcessHeap(), 0, sizeof(FormatConverterInfo));
1168 if (!This)
1170 RegCloseKey(classkey);
1171 return E_OUTOFMEMORY;
1174 This->base.IWICComponentInfo_iface.lpVtbl = (const IWICComponentInfoVtbl*)&FormatConverterInfo_Vtbl;
1175 This->base.ref = 1;
1176 This->classkey = classkey;
1177 This->base.clsid = *clsid;
1179 *ret = &This->base;
1180 return S_OK;
1183 typedef struct {
1184 ComponentInfo base;
1185 HKEY classkey;
1186 } PixelFormatInfo;
1188 static inline PixelFormatInfo *impl_from_IWICPixelFormatInfo2(IWICPixelFormatInfo2 *iface)
1190 return CONTAINING_RECORD(iface, PixelFormatInfo, base.IWICComponentInfo_iface);
1193 static HRESULT WINAPI PixelFormatInfo_QueryInterface(IWICPixelFormatInfo2 *iface, REFIID iid,
1194 void **ppv)
1196 PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1197 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
1199 if (!ppv) return E_INVALIDARG;
1201 if (IsEqualIID(&IID_IUnknown, iid) ||
1202 IsEqualIID(&IID_IWICComponentInfo, iid) ||
1203 IsEqualIID(&IID_IWICPixelFormatInfo, iid) ||
1204 IsEqualIID(&IID_IWICPixelFormatInfo2 ,iid))
1206 *ppv = &This->base.IWICComponentInfo_iface;
1208 else
1210 *ppv = NULL;
1211 return E_NOINTERFACE;
1214 IUnknown_AddRef((IUnknown*)*ppv);
1215 return S_OK;
1218 static ULONG WINAPI PixelFormatInfo_AddRef(IWICPixelFormatInfo2 *iface)
1220 PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1221 ULONG ref = InterlockedIncrement(&This->base.ref);
1223 TRACE("(%p) refcount=%lu\n", iface, ref);
1225 return ref;
1228 static ULONG WINAPI PixelFormatInfo_Release(IWICPixelFormatInfo2 *iface)
1230 PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1231 ULONG ref = InterlockedDecrement(&This->base.ref);
1233 TRACE("(%p) refcount=%lu\n", iface, ref);
1235 if (ref == 0)
1237 RegCloseKey(This->classkey);
1238 HeapFree(GetProcessHeap(), 0, This);
1241 return ref;
1244 static HRESULT WINAPI PixelFormatInfo_GetComponentType(IWICPixelFormatInfo2 *iface,
1245 WICComponentType *pType)
1247 TRACE("(%p,%p)\n", iface, pType);
1248 if (!pType) return E_INVALIDARG;
1249 *pType = WICPixelFormat;
1250 return S_OK;
1253 static HRESULT WINAPI PixelFormatInfo_GetCLSID(IWICPixelFormatInfo2 *iface, CLSID *pclsid)
1255 PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1256 TRACE("(%p,%p)\n", iface, pclsid);
1258 if (!pclsid)
1259 return E_INVALIDARG;
1261 *pclsid = This->base.clsid;
1262 return S_OK;
1265 static HRESULT WINAPI PixelFormatInfo_GetSigningStatus(IWICPixelFormatInfo2 *iface, DWORD *pStatus)
1267 TRACE("(%p,%p)\n", iface, pStatus);
1269 if (!pStatus)
1270 return E_INVALIDARG;
1272 /* Pixel formats don't require code, so they are considered signed. */
1273 *pStatus = WICComponentSigned;
1275 return S_OK;
1278 static HRESULT WINAPI PixelFormatInfo_GetAuthor(IWICPixelFormatInfo2 *iface, UINT cchAuthor,
1279 WCHAR *wzAuthor, UINT *pcchActual)
1281 PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1283 TRACE("(%p,%u,%p,%p)\n", iface, cchAuthor, wzAuthor, pcchActual);
1285 return ComponentInfo_GetStringValue(This->classkey, L"Author", cchAuthor, wzAuthor, pcchActual);
1288 static HRESULT WINAPI PixelFormatInfo_GetVendorGUID(IWICPixelFormatInfo2 *iface, GUID *pguidVendor)
1290 PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1292 TRACE("(%p,%p)\n", iface, pguidVendor);
1294 return ComponentInfo_GetGUIDValue(This->classkey, L"Vendor", pguidVendor);
1297 static HRESULT WINAPI PixelFormatInfo_GetVersion(IWICPixelFormatInfo2 *iface, UINT cchVersion,
1298 WCHAR *wzVersion, UINT *pcchActual)
1300 PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1302 TRACE("(%p,%u,%p,%p)\n", iface, cchVersion, wzVersion, pcchActual);
1304 return ComponentInfo_GetStringValue(This->classkey, L"Version",
1305 cchVersion, wzVersion, pcchActual);
1308 static HRESULT WINAPI PixelFormatInfo_GetSpecVersion(IWICPixelFormatInfo2 *iface, UINT cchSpecVersion,
1309 WCHAR *wzSpecVersion, UINT *pcchActual)
1311 PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1313 TRACE("(%p,%u,%p,%p)\n", iface, cchSpecVersion, wzSpecVersion, pcchActual);
1315 return ComponentInfo_GetStringValue(This->classkey, L"SpecVersion",
1316 cchSpecVersion, wzSpecVersion, pcchActual);
1319 static HRESULT WINAPI PixelFormatInfo_GetFriendlyName(IWICPixelFormatInfo2 *iface, UINT cchFriendlyName,
1320 WCHAR *wzFriendlyName, UINT *pcchActual)
1322 PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1324 TRACE("(%p,%u,%p,%p)\n", iface, cchFriendlyName, wzFriendlyName, pcchActual);
1326 return ComponentInfo_GetStringValue(This->classkey, L"FriendlyName",
1327 cchFriendlyName, wzFriendlyName, pcchActual);
1330 static HRESULT WINAPI PixelFormatInfo_GetFormatGUID(IWICPixelFormatInfo2 *iface,
1331 GUID *pFormat)
1333 PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1334 TRACE("(%p,%p)\n", iface, pFormat);
1336 if (!pFormat)
1337 return E_INVALIDARG;
1339 *pFormat = This->base.clsid;
1340 return S_OK;
1343 static HRESULT WINAPI PixelFormatInfo_GetColorContext(IWICPixelFormatInfo2 *iface,
1344 IWICColorContext **ppIColorContext)
1346 FIXME("(%p,%p): stub\n", iface, ppIColorContext);
1347 return E_NOTIMPL;
1350 static HRESULT WINAPI PixelFormatInfo_GetBitsPerPixel(IWICPixelFormatInfo2 *iface,
1351 UINT *puiBitsPerPixel)
1353 PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1355 TRACE("(%p,%p)\n", iface, puiBitsPerPixel);
1357 return ComponentInfo_GetUINTValue(This->classkey, L"BitLength", puiBitsPerPixel);
1360 static HRESULT WINAPI PixelFormatInfo_GetChannelCount(IWICPixelFormatInfo2 *iface,
1361 UINT *puiChannelCount)
1363 PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1365 TRACE("(%p,%p)\n", iface, puiChannelCount);
1367 return ComponentInfo_GetUINTValue(This->classkey, L"ChannelCount", puiChannelCount);
1370 static HRESULT WINAPI PixelFormatInfo_GetChannelMask(IWICPixelFormatInfo2 *iface,
1371 UINT uiChannelIndex, UINT cbMaskBuffer, BYTE *pbMaskBuffer, UINT *pcbActual)
1373 PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1374 UINT channel_count;
1375 HRESULT hr;
1376 LONG ret;
1377 WCHAR valuename[11];
1378 DWORD cbData;
1380 TRACE("(%p,%u,%u,%p,%p)\n", iface, uiChannelIndex, cbMaskBuffer, pbMaskBuffer, pcbActual);
1382 if (!pcbActual)
1383 return E_INVALIDARG;
1385 hr = PixelFormatInfo_GetChannelCount(iface, &channel_count);
1387 if (SUCCEEDED(hr) && uiChannelIndex >= channel_count)
1388 hr = E_INVALIDARG;
1390 if (SUCCEEDED(hr))
1392 swprintf(valuename, 11, L"%u", uiChannelIndex);
1394 cbData = cbMaskBuffer;
1396 ret = RegGetValueW(This->classkey, L"ChannelMasks", valuename, RRF_RT_REG_BINARY, NULL, pbMaskBuffer, &cbData);
1398 if (ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA)
1399 *pcbActual = cbData;
1401 if (ret == ERROR_MORE_DATA)
1402 hr = E_INVALIDARG;
1403 else
1404 hr = HRESULT_FROM_WIN32(ret);
1407 return hr;
1410 static HRESULT WINAPI PixelFormatInfo_SupportsTransparency(IWICPixelFormatInfo2 *iface,
1411 BOOL *pfSupportsTransparency)
1413 PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1415 TRACE("(%p,%p)\n", iface, pfSupportsTransparency);
1417 return ComponentInfo_GetUINTValue(This->classkey, L"SupportsTransparency", (UINT *)pfSupportsTransparency);
1420 static HRESULT WINAPI PixelFormatInfo_GetNumericRepresentation(IWICPixelFormatInfo2 *iface,
1421 WICPixelFormatNumericRepresentation *pNumericRepresentation)
1423 PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1425 TRACE("(%p,%p)\n", iface, pNumericRepresentation);
1427 return ComponentInfo_GetUINTValue(This->classkey, L"NumericRepresentation", pNumericRepresentation);
1430 static const IWICPixelFormatInfo2Vtbl PixelFormatInfo_Vtbl = {
1431 PixelFormatInfo_QueryInterface,
1432 PixelFormatInfo_AddRef,
1433 PixelFormatInfo_Release,
1434 PixelFormatInfo_GetComponentType,
1435 PixelFormatInfo_GetCLSID,
1436 PixelFormatInfo_GetSigningStatus,
1437 PixelFormatInfo_GetAuthor,
1438 PixelFormatInfo_GetVendorGUID,
1439 PixelFormatInfo_GetVersion,
1440 PixelFormatInfo_GetSpecVersion,
1441 PixelFormatInfo_GetFriendlyName,
1442 PixelFormatInfo_GetFormatGUID,
1443 PixelFormatInfo_GetColorContext,
1444 PixelFormatInfo_GetBitsPerPixel,
1445 PixelFormatInfo_GetChannelCount,
1446 PixelFormatInfo_GetChannelMask,
1447 PixelFormatInfo_SupportsTransparency,
1448 PixelFormatInfo_GetNumericRepresentation
1451 static HRESULT PixelFormatInfo_Constructor(HKEY classkey, REFCLSID clsid, ComponentInfo **ret)
1453 PixelFormatInfo *This;
1455 This = HeapAlloc(GetProcessHeap(), 0, sizeof(PixelFormatInfo));
1456 if (!This)
1458 RegCloseKey(classkey);
1459 return E_OUTOFMEMORY;
1462 This->base.IWICComponentInfo_iface.lpVtbl = (const IWICComponentInfoVtbl*)&PixelFormatInfo_Vtbl;
1463 This->base.ref = 1;
1464 This->classkey = classkey;
1465 This->base.clsid = *clsid;
1467 *ret = &This->base;
1468 return S_OK;
1471 struct metadata_container
1473 WICMetadataPattern *patterns;
1474 UINT pattern_count;
1475 UINT patterns_size;
1478 typedef struct
1480 ComponentInfo base;
1481 HKEY classkey;
1482 GUID *container_formats;
1483 struct metadata_container *containers;
1484 UINT container_count;
1485 } MetadataReaderInfo;
1487 static struct metadata_container *get_metadata_container(MetadataReaderInfo *info, const GUID *guid)
1489 unsigned i;
1491 for (i = 0; i < info->container_count; i++)
1492 if (IsEqualGUID(info->container_formats + i, guid))
1493 return info->containers + i;
1495 return NULL;
1498 static inline MetadataReaderInfo *impl_from_IWICMetadataReaderInfo(IWICMetadataReaderInfo *iface)
1500 return CONTAINING_RECORD(iface, MetadataReaderInfo, base.IWICComponentInfo_iface);
1503 static HRESULT WINAPI MetadataReaderInfo_QueryInterface(IWICMetadataReaderInfo *iface,
1504 REFIID riid, void **ppv)
1506 MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1508 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(riid), ppv);
1510 if (!ppv) return E_INVALIDARG;
1512 if (IsEqualIID(&IID_IUnknown, riid) ||
1513 IsEqualIID(&IID_IWICComponentInfo, riid) ||
1514 IsEqualIID(&IID_IWICMetadataHandlerInfo, riid) ||
1515 IsEqualIID(&IID_IWICMetadataReaderInfo, riid))
1517 *ppv = &This->base.IWICComponentInfo_iface;
1519 else
1521 *ppv = NULL;
1522 return E_NOINTERFACE;
1525 IUnknown_AddRef((IUnknown *)*ppv);
1526 return S_OK;
1529 static ULONG WINAPI MetadataReaderInfo_AddRef(IWICMetadataReaderInfo *iface)
1531 MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1532 ULONG ref = InterlockedIncrement(&This->base.ref);
1534 TRACE("(%p) refcount=%lu\n", iface, ref);
1535 return ref;
1538 static ULONG WINAPI MetadataReaderInfo_Release(IWICMetadataReaderInfo *iface)
1540 MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1541 ULONG ref = InterlockedDecrement(&This->base.ref);
1543 TRACE("(%p) refcount=%lu\n", iface, ref);
1545 if (!ref)
1547 unsigned i;
1548 RegCloseKey(This->classkey);
1549 for (i = 0; i < This->container_count; i++)
1550 heap_free(This->containers[i].patterns);
1551 heap_free(This->containers);
1552 heap_free(This->container_formats);
1553 HeapFree(GetProcessHeap(), 0, This);
1555 return ref;
1558 static HRESULT WINAPI MetadataReaderInfo_GetComponentType(IWICMetadataReaderInfo *iface,
1559 WICComponentType *type)
1561 TRACE("(%p,%p)\n", iface, type);
1563 if (!type) return E_INVALIDARG;
1564 *type = WICMetadataReader;
1565 return S_OK;
1568 static HRESULT WINAPI MetadataReaderInfo_GetCLSID(IWICMetadataReaderInfo *iface,
1569 CLSID *clsid)
1571 MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1573 TRACE("(%p,%p)\n", iface, clsid);
1575 if (!clsid) return E_INVALIDARG;
1576 *clsid = This->base.clsid;
1577 return S_OK;
1580 static HRESULT WINAPI MetadataReaderInfo_GetSigningStatus(IWICMetadataReaderInfo *iface,
1581 DWORD *status)
1583 FIXME("(%p,%p): stub\n", iface, status);
1584 return E_NOTIMPL;
1587 static HRESULT WINAPI MetadataReaderInfo_GetAuthor(IWICMetadataReaderInfo *iface,
1588 UINT length, WCHAR *author, UINT *actual_length)
1590 MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1592 TRACE("(%p,%u,%p,%p)\n", iface, length, author, actual_length);
1594 return ComponentInfo_GetStringValue(This->classkey, L"Author", length, author, actual_length);
1597 static HRESULT WINAPI MetadataReaderInfo_GetVendorGUID(IWICMetadataReaderInfo *iface,
1598 GUID *vendor)
1600 MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1602 TRACE("(%p,%p)\n", iface, vendor);
1604 return ComponentInfo_GetGUIDValue(This->classkey, L"Vendor", vendor);
1607 static HRESULT WINAPI MetadataReaderInfo_GetVersion(IWICMetadataReaderInfo *iface,
1608 UINT length, WCHAR *version, UINT *actual_length)
1610 MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1612 TRACE("(%p,%u,%p,%p)\n", iface, length, version, actual_length);
1614 return ComponentInfo_GetStringValue(This->classkey, L"Version", length, version, actual_length);
1617 static HRESULT WINAPI MetadataReaderInfo_GetSpecVersion(IWICMetadataReaderInfo *iface,
1618 UINT length, WCHAR *version, UINT *actual_length)
1620 MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1622 TRACE("(%p,%u,%p,%p)\n", iface, length, version, actual_length);
1624 return ComponentInfo_GetStringValue(This->classkey, L"SpecVersion",
1625 length, version, actual_length);
1628 static HRESULT WINAPI MetadataReaderInfo_GetFriendlyName(IWICMetadataReaderInfo *iface,
1629 UINT length, WCHAR *name, UINT *actual_length)
1631 MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1633 TRACE("(%p,%u,%p,%p)\n", iface, length, name, actual_length);
1635 return ComponentInfo_GetStringValue(This->classkey, L"FriendlyName",
1636 length, name, actual_length);
1639 static HRESULT WINAPI MetadataReaderInfo_GetMetadataFormat(IWICMetadataReaderInfo *iface,
1640 GUID *format)
1642 MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1643 TRACE("(%p,%p)\n", iface, format);
1644 return ComponentInfo_GetGUIDValue(This->classkey, L"MetadataFormat", format);
1647 static HRESULT WINAPI MetadataReaderInfo_GetContainerFormats(IWICMetadataReaderInfo *iface,
1648 UINT length, GUID *formats, UINT *actual_length)
1650 MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1652 TRACE("(%p,%u,%p,%p)\n", iface, length, formats, actual_length);
1654 if (!actual_length)
1655 return E_INVALIDARG;
1657 *actual_length = This->container_count;
1658 if (formats)
1660 if (This->container_count && length < This->container_count)
1661 return WINCODEC_ERR_INSUFFICIENTBUFFER;
1662 memcpy(formats, This->container_formats, This->container_count * sizeof(*formats));
1664 return S_OK;
1667 static HRESULT WINAPI MetadataReaderInfo_GetDeviceManufacturer(IWICMetadataReaderInfo *iface,
1668 UINT length, WCHAR *manufacturer, UINT *actual_length)
1670 FIXME("(%p,%u,%p,%p): stub\n", iface, length, manufacturer, actual_length);
1671 return E_NOTIMPL;
1674 static HRESULT WINAPI MetadataReaderInfo_GetDeviceModels(IWICMetadataReaderInfo *iface,
1675 UINT length, WCHAR *models, UINT *actual_length)
1677 FIXME("(%p,%u,%p,%p): stub\n", iface, length, models, actual_length);
1678 return E_NOTIMPL;
1681 static HRESULT WINAPI MetadataReaderInfo_DoesRequireFullStream(IWICMetadataReaderInfo *iface,
1682 BOOL *param)
1684 MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1685 TRACE("(%p,%p)\n", iface, param);
1686 return ComponentInfo_GetUINTValue(This->classkey, L"RequiresFullStream", (UINT *)param);
1689 static HRESULT WINAPI MetadataReaderInfo_DoesSupportPadding(IWICMetadataReaderInfo *iface,
1690 BOOL *param)
1692 MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1693 TRACE("(%p,%p)\n", iface, param);
1694 return ComponentInfo_GetUINTValue(This->classkey, L"SupportsPadding", (UINT *)param);
1697 static HRESULT WINAPI MetadataReaderInfo_DoesRequireFixedSize(IWICMetadataReaderInfo *iface,
1698 BOOL *param)
1700 FIXME("(%p,%p): stub\n", iface, param);
1701 return E_NOTIMPL;
1704 static HRESULT WINAPI MetadataReaderInfo_GetPatterns(IWICMetadataReaderInfo *iface,
1705 REFGUID container_guid, UINT length, WICMetadataPattern *patterns, UINT *count, UINT *actual_length)
1707 MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1708 struct metadata_container *container;
1710 TRACE("(%p,%s,%u,%p,%p,%p)\n", iface, debugstr_guid(container_guid), length, patterns, count, actual_length);
1712 if (!actual_length || !container_guid) return E_INVALIDARG;
1714 if (!(container = get_metadata_container(This, container_guid)))
1715 return WINCODEC_ERR_COMPONENTNOTFOUND;
1717 *count = container->pattern_count;
1718 *actual_length = container->patterns_size;
1719 if (patterns)
1721 if (container->patterns_size && length < container->patterns_size)
1722 return WINCODEC_ERR_INSUFFICIENTBUFFER;
1723 memcpy(patterns, container->patterns, container->patterns_size);
1725 return S_OK;
1728 static HRESULT WINAPI MetadataReaderInfo_MatchesPattern(IWICMetadataReaderInfo *iface,
1729 REFGUID container_guid, IStream *stream, BOOL *matches)
1731 MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1732 struct metadata_container *container;
1733 HRESULT hr;
1734 ULONG datasize=0;
1735 BYTE *data=NULL;
1736 ULONG bytesread;
1737 UINT i;
1738 LARGE_INTEGER seekpos;
1739 ULONG pos;
1741 TRACE("(%p,%s,%p,%p)\n", iface, debugstr_guid(container_guid), stream, matches);
1743 if (!(container = get_metadata_container(This, container_guid)))
1744 return WINCODEC_ERR_COMPONENTNOTFOUND;
1746 for (i=0; i < container->pattern_count; i++)
1748 if (datasize < container->patterns[i].Length)
1750 HeapFree(GetProcessHeap(), 0, data);
1751 datasize = container->patterns[i].Length;
1752 data = HeapAlloc(GetProcessHeap(), 0, container->patterns[i].Length);
1753 if (!data)
1755 hr = E_OUTOFMEMORY;
1756 break;
1760 seekpos.QuadPart = container->patterns[i].Position.QuadPart;
1761 hr = IStream_Seek(stream, seekpos, STREAM_SEEK_SET, NULL);
1762 if (FAILED(hr)) break;
1764 hr = IStream_Read(stream, data, container->patterns[i].Length, &bytesread);
1765 if (hr == S_FALSE || (hr == S_OK && bytesread != container->patterns[i].Length)) /* past end of stream */
1766 continue;
1767 if (FAILED(hr)) break;
1769 for (pos=0; pos < container->patterns[i].Length; pos++)
1771 if ((data[pos] & container->patterns[i].Mask[pos]) != container->patterns[i].Pattern[pos])
1772 break;
1774 if (pos == container->patterns[i].Length) /* matches pattern */
1776 hr = S_OK;
1777 *matches = TRUE;
1778 break;
1782 if (i == container->pattern_count) /* does not match any pattern */
1784 hr = S_OK;
1785 *matches = FALSE;
1788 HeapFree(GetProcessHeap(), 0, data);
1790 return hr;
1793 static HRESULT WINAPI MetadataReaderInfo_CreateInstance(IWICMetadataReaderInfo *iface,
1794 IWICMetadataReader **reader)
1796 MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1798 TRACE("(%p,%p)\n", iface, reader);
1800 return create_instance(&This->base.clsid, &IID_IWICMetadataReader, (void **)reader);
1803 static const IWICMetadataReaderInfoVtbl MetadataReaderInfo_Vtbl = {
1804 MetadataReaderInfo_QueryInterface,
1805 MetadataReaderInfo_AddRef,
1806 MetadataReaderInfo_Release,
1807 MetadataReaderInfo_GetComponentType,
1808 MetadataReaderInfo_GetCLSID,
1809 MetadataReaderInfo_GetSigningStatus,
1810 MetadataReaderInfo_GetAuthor,
1811 MetadataReaderInfo_GetVendorGUID,
1812 MetadataReaderInfo_GetVersion,
1813 MetadataReaderInfo_GetSpecVersion,
1814 MetadataReaderInfo_GetFriendlyName,
1815 MetadataReaderInfo_GetMetadataFormat,
1816 MetadataReaderInfo_GetContainerFormats,
1817 MetadataReaderInfo_GetDeviceManufacturer,
1818 MetadataReaderInfo_GetDeviceModels,
1819 MetadataReaderInfo_DoesRequireFullStream,
1820 MetadataReaderInfo_DoesSupportPadding,
1821 MetadataReaderInfo_DoesRequireFixedSize,
1822 MetadataReaderInfo_GetPatterns,
1823 MetadataReaderInfo_MatchesPattern,
1824 MetadataReaderInfo_CreateInstance
1827 static void read_metadata_patterns(MetadataReaderInfo *info, GUID *container_guid,
1828 struct metadata_container *container)
1830 DWORD pattern_count=0;
1831 UINT patterns_size=0;
1832 WCHAR subkeyname[11], guidkeyname[39];
1833 LONG res;
1834 HKEY containers_key, guid_key, patternkey;
1835 UINT i;
1836 WICMetadataPattern *patterns;
1837 BYTE *patterns_ptr;
1838 DWORD length, valuesize;
1840 res = RegOpenKeyExW(info->classkey, L"Containers", 0, KEY_READ, &containers_key);
1841 if (res != ERROR_SUCCESS) return;
1843 StringFromGUID2(container_guid, guidkeyname, 39);
1844 res = RegOpenKeyExW(containers_key, guidkeyname, 0, KEY_READ, &guid_key);
1845 RegCloseKey(containers_key);
1846 if (res != ERROR_SUCCESS) return;
1848 res = RegQueryInfoKeyW(guid_key, NULL, NULL, NULL, &pattern_count,
1849 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1850 if (res != ERROR_SUCCESS)
1852 RegCloseKey(guid_key);
1853 return;
1856 patterns_size = pattern_count * sizeof(WICMetadataPattern);
1857 patterns = heap_alloc(patterns_size);
1858 if (!patterns)
1860 RegCloseKey(guid_key);
1861 return;
1864 for (i=0; res == ERROR_SUCCESS && i < pattern_count; i++)
1866 swprintf(subkeyname, 11, L"%u", i);
1867 res = RegOpenKeyExW(guid_key, subkeyname, 0, KEY_READ, &patternkey);
1868 if (res != ERROR_SUCCESS) break;
1870 res = RegGetValueW(patternkey, NULL, L"Pattern", RRF_RT_REG_BINARY, NULL, NULL, &length);
1871 if (res == ERROR_SUCCESS)
1873 patterns_size += length*2;
1874 patterns[i].Length = length;
1876 valuesize = sizeof(DWORD64);
1877 res = RegGetValueW(patternkey, NULL, L"DataOffset", RRF_RT_DWORD|RRF_RT_QWORD, NULL,
1878 &patterns[i].DataOffset, &valuesize);
1879 if (res) patterns[i].DataOffset.QuadPart = 0;
1881 patterns[i].Position.QuadPart = 0;
1882 valuesize = sizeof(DWORD64);
1883 res = RegGetValueW(patternkey, NULL, L"Position", RRF_RT_DWORD|RRF_RT_QWORD, NULL,
1884 &patterns[i].Position, &valuesize);
1887 RegCloseKey(patternkey);
1890 if (res != ERROR_SUCCESS || !(patterns_ptr = heap_realloc(patterns, patterns_size)))
1892 heap_free(patterns);
1893 RegCloseKey(guid_key);
1894 return;
1896 patterns = (WICMetadataPattern*)patterns_ptr;
1897 patterns_ptr += pattern_count * sizeof(*patterns);
1899 for (i=0; res == ERROR_SUCCESS && i < pattern_count; i++)
1901 swprintf(subkeyname, 11, L"%u", i);
1902 res = RegOpenKeyExW(guid_key, subkeyname, 0, KEY_READ, &patternkey);
1903 if (res != ERROR_SUCCESS) break;
1905 length = patterns[i].Length;
1906 patterns[i].Pattern = patterns_ptr;
1907 valuesize = length;
1908 res = RegGetValueW(patternkey, NULL, L"Pattern", RRF_RT_REG_BINARY, NULL,
1909 patterns[i].Pattern, &valuesize);
1910 patterns_ptr += length;
1912 if (res == ERROR_SUCCESS)
1914 patterns[i].Mask = patterns_ptr;
1915 valuesize = length;
1916 res = RegGetValueW(patternkey, NULL, L"Mask", RRF_RT_REG_BINARY, NULL,
1917 patterns[i].Mask, &valuesize);
1918 patterns_ptr += length;
1921 RegCloseKey(patternkey);
1924 RegCloseKey(guid_key);
1926 if (res != ERROR_SUCCESS)
1928 heap_free(patterns);
1929 return;
1932 container->pattern_count = pattern_count;
1933 container->patterns_size = patterns_size;
1934 container->patterns = patterns;
1937 static BOOL read_metadata_info(MetadataReaderInfo *info)
1939 UINT format_count;
1940 GUID *formats;
1941 HRESULT hr;
1943 hr = ComponentInfo_GetGuidList(info->classkey, L"Containers", 0, NULL, &format_count);
1944 if (FAILED(hr)) return TRUE;
1946 formats = heap_calloc(format_count, sizeof(*formats));
1947 if (!formats) return FALSE;
1949 hr = ComponentInfo_GetGuidList(info->classkey, L"Containers", format_count, formats,
1950 &format_count);
1951 if (FAILED(hr))
1953 heap_free(formats);
1954 return FALSE;
1957 info->container_formats = formats;
1958 info->container_count = format_count;
1960 if (format_count)
1962 unsigned i;
1964 info->containers = heap_calloc(format_count, sizeof(*info->containers));
1965 if (!info->containers) return FALSE;
1967 for (i = 0; i < format_count; i++)
1968 read_metadata_patterns(info, info->container_formats + i, info->containers + i);
1971 return TRUE;
1974 static HRESULT MetadataReaderInfo_Constructor(HKEY classkey, REFCLSID clsid, ComponentInfo **info)
1976 MetadataReaderInfo *This;
1978 This = heap_alloc_zero(sizeof(*This));
1979 if (!This)
1981 RegCloseKey(classkey);
1982 return E_OUTOFMEMORY;
1985 This->base.IWICComponentInfo_iface.lpVtbl = (const IWICComponentInfoVtbl*)&MetadataReaderInfo_Vtbl;
1986 This->base.ref = 1;
1987 This->classkey = classkey;
1988 This->base.clsid = *clsid;
1990 if (!read_metadata_info(This))
1992 IWICComponentInfo_Release(&This->base.IWICComponentInfo_iface);
1993 return WINCODEC_ERR_COMPONENTNOTFOUND;
1996 *info = &This->base;
1997 return S_OK;
2000 struct category {
2001 WICComponentType type;
2002 const GUID *catid;
2003 HRESULT (*constructor)(HKEY,REFCLSID,ComponentInfo**);
2006 static const struct category categories[] = {
2007 {WICDecoder, &CATID_WICBitmapDecoders, BitmapDecoderInfo_Constructor},
2008 {WICEncoder, &CATID_WICBitmapEncoders, BitmapEncoderInfo_Constructor},
2009 {WICPixelFormatConverter, &CATID_WICFormatConverters, FormatConverterInfo_Constructor},
2010 {WICPixelFormat, &CATID_WICPixelFormats, PixelFormatInfo_Constructor},
2011 {WICMetadataReader, &CATID_WICMetadataReader, MetadataReaderInfo_Constructor},
2015 static int ComponentInfo_Compare(const void *key, const struct wine_rb_entry *entry)
2017 ComponentInfo *info = WINE_RB_ENTRY_VALUE(entry, ComponentInfo, entry);
2018 return memcmp(key, &info->clsid, sizeof(info->clsid));
2021 static struct wine_rb_tree component_info_cache = { ComponentInfo_Compare };
2023 static CRITICAL_SECTION component_info_cache_cs;
2024 static CRITICAL_SECTION_DEBUG component_info_cache_cs_dbg =
2026 0, 0, &component_info_cache_cs,
2027 { &component_info_cache_cs_dbg.ProcessLocksList, &component_info_cache_cs_dbg.ProcessLocksList },
2028 0, 0, { (DWORD_PTR)(__FILE__ ": component_info_cache") }
2030 static CRITICAL_SECTION component_info_cache_cs = { &component_info_cache_cs_dbg, -1, 0, 0, 0, 0 };
2032 HRESULT CreateComponentInfo(REFCLSID clsid, IWICComponentInfo **ppIInfo)
2034 struct wine_rb_entry *cache_entry;
2035 ComponentInfo *info;
2036 HKEY clsidkey;
2037 HKEY classkey;
2038 HKEY catidkey;
2039 HKEY instancekey;
2040 WCHAR guidstring[39];
2041 LONG res;
2042 const struct category *category;
2043 BOOL found = FALSE;
2044 HRESULT hr;
2046 EnterCriticalSection(&component_info_cache_cs);
2048 cache_entry = wine_rb_get(&component_info_cache, clsid);
2049 if(cache_entry)
2051 info = WINE_RB_ENTRY_VALUE(cache_entry, ComponentInfo, entry);
2052 IWICComponentInfo_AddRef(*ppIInfo = &info->IWICComponentInfo_iface);
2053 LeaveCriticalSection(&component_info_cache_cs);
2054 return S_OK;
2057 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, L"CLSID", 0, KEY_READ, &clsidkey);
2058 if (res != ERROR_SUCCESS)
2060 LeaveCriticalSection(&component_info_cache_cs);
2061 return HRESULT_FROM_WIN32(res);
2064 for (category=categories; category->type; category++)
2066 StringFromGUID2(category->catid, guidstring, 39);
2067 res = RegOpenKeyExW(clsidkey, guidstring, 0, KEY_READ, &catidkey);
2068 if (res == ERROR_SUCCESS)
2070 res = RegOpenKeyExW(catidkey, L"Instance", 0, KEY_READ, &instancekey);
2071 if (res == ERROR_SUCCESS)
2073 StringFromGUID2(clsid, guidstring, 39);
2074 res = RegOpenKeyExW(instancekey, guidstring, 0, KEY_READ, &classkey);
2075 if (res == ERROR_SUCCESS)
2077 RegCloseKey(classkey);
2078 found = TRUE;
2080 RegCloseKey(instancekey);
2082 RegCloseKey(catidkey);
2084 if (found) break;
2087 if (found)
2089 res = RegOpenKeyExW(clsidkey, guidstring, 0, KEY_READ, &classkey);
2090 if (res == ERROR_SUCCESS)
2091 hr = category->constructor(classkey, clsid, &info);
2092 else
2093 hr = HRESULT_FROM_WIN32(res);
2095 else
2097 FIXME("%s is not supported\n", wine_dbgstr_guid(clsid));
2098 hr = E_FAIL;
2101 RegCloseKey(clsidkey);
2103 if (SUCCEEDED(hr))
2105 wine_rb_put(&component_info_cache, clsid, &info->entry);
2106 IWICComponentInfo_AddRef(*ppIInfo = &info->IWICComponentInfo_iface);
2108 LeaveCriticalSection(&component_info_cache_cs);
2109 return hr;
2112 void ReleaseComponentInfos(void)
2114 ComponentInfo *info, *next_info;
2115 WINE_RB_FOR_EACH_ENTRY_DESTRUCTOR(info, next_info, &component_info_cache, ComponentInfo, entry)
2116 IWICComponentInfo_Release(&info->IWICComponentInfo_iface);
2119 HRESULT get_decoder_info(REFCLSID clsid, IWICBitmapDecoderInfo **info)
2121 IWICComponentInfo *compinfo;
2122 HRESULT hr;
2124 hr = CreateComponentInfo(clsid, &compinfo);
2125 if (FAILED(hr)) return hr;
2127 hr = IWICComponentInfo_QueryInterface(compinfo, &IID_IWICBitmapDecoderInfo,
2128 (void **)info);
2130 IWICComponentInfo_Release(compinfo);
2132 return hr;
2135 typedef struct {
2136 IEnumUnknown IEnumUnknown_iface;
2137 LONG ref;
2138 struct list objects;
2139 struct list *cursor;
2140 CRITICAL_SECTION lock; /* Must be held when reading or writing cursor */
2141 } ComponentEnum;
2143 static inline ComponentEnum *impl_from_IEnumUnknown(IEnumUnknown *iface)
2145 return CONTAINING_RECORD(iface, ComponentEnum, IEnumUnknown_iface);
2148 typedef struct {
2149 struct list entry;
2150 IUnknown *unk;
2151 } ComponentEnumItem;
2153 static const IEnumUnknownVtbl ComponentEnumVtbl;
2155 static HRESULT WINAPI ComponentEnum_QueryInterface(IEnumUnknown *iface, REFIID iid,
2156 void **ppv)
2158 ComponentEnum *This = impl_from_IEnumUnknown(iface);
2159 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
2161 if (!ppv) return E_INVALIDARG;
2163 if (IsEqualIID(&IID_IUnknown, iid) ||
2164 IsEqualIID(&IID_IEnumUnknown, iid))
2166 *ppv = &This->IEnumUnknown_iface;
2168 else
2170 *ppv = NULL;
2171 return E_NOINTERFACE;
2174 IUnknown_AddRef((IUnknown*)*ppv);
2175 return S_OK;
2178 static ULONG WINAPI ComponentEnum_AddRef(IEnumUnknown *iface)
2180 ComponentEnum *This = impl_from_IEnumUnknown(iface);
2181 ULONG ref = InterlockedIncrement(&This->ref);
2183 TRACE("(%p) refcount=%lu\n", iface, ref);
2185 return ref;
2188 static ULONG WINAPI ComponentEnum_Release(IEnumUnknown *iface)
2190 ComponentEnum *This = impl_from_IEnumUnknown(iface);
2191 ULONG ref = InterlockedDecrement(&This->ref);
2192 ComponentEnumItem *cursor, *cursor2;
2194 TRACE("(%p) refcount=%lu\n", iface, ref);
2196 if (ref == 0)
2198 LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, &This->objects, ComponentEnumItem, entry)
2200 IUnknown_Release(cursor->unk);
2201 list_remove(&cursor->entry);
2202 HeapFree(GetProcessHeap(), 0, cursor);
2204 This->lock.DebugInfo->Spare[0] = 0;
2205 DeleteCriticalSection(&This->lock);
2206 HeapFree(GetProcessHeap(), 0, This);
2209 return ref;
2212 static HRESULT WINAPI ComponentEnum_Next(IEnumUnknown *iface, ULONG celt,
2213 IUnknown **rgelt, ULONG *pceltFetched)
2215 ComponentEnum *This = impl_from_IEnumUnknown(iface);
2216 ULONG num_fetched=0;
2217 ComponentEnumItem *item;
2218 HRESULT hr=S_OK;
2220 TRACE("(%p,%lu,%p,%p)\n", iface, celt, rgelt, pceltFetched);
2222 EnterCriticalSection(&This->lock);
2223 while (num_fetched<celt)
2225 if (!This->cursor)
2227 hr = S_FALSE;
2228 break;
2230 item = LIST_ENTRY(This->cursor, ComponentEnumItem, entry);
2231 IUnknown_AddRef(item->unk);
2232 rgelt[num_fetched] = item->unk;
2233 num_fetched++;
2234 This->cursor = list_next(&This->objects, This->cursor);
2236 LeaveCriticalSection(&This->lock);
2237 if (pceltFetched)
2238 *pceltFetched = num_fetched;
2239 return hr;
2242 static HRESULT WINAPI ComponentEnum_Skip(IEnumUnknown *iface, ULONG celt)
2244 ComponentEnum *This = impl_from_IEnumUnknown(iface);
2245 ULONG i;
2246 HRESULT hr=S_OK;
2248 TRACE("(%p,%lu)\n", iface, celt);
2250 EnterCriticalSection(&This->lock);
2251 for (i=0; i<celt; i++)
2253 if (!This->cursor)
2255 hr = S_FALSE;
2256 break;
2258 This->cursor = list_next(&This->objects, This->cursor);
2260 LeaveCriticalSection(&This->lock);
2261 return hr;
2264 static HRESULT WINAPI ComponentEnum_Reset(IEnumUnknown *iface)
2266 ComponentEnum *This = impl_from_IEnumUnknown(iface);
2268 TRACE("(%p)\n", iface);
2270 EnterCriticalSection(&This->lock);
2271 This->cursor = list_head(&This->objects);
2272 LeaveCriticalSection(&This->lock);
2273 return S_OK;
2276 static HRESULT WINAPI ComponentEnum_Clone(IEnumUnknown *iface, IEnumUnknown **ppenum)
2278 ComponentEnum *This = impl_from_IEnumUnknown(iface);
2279 ComponentEnum *new_enum;
2280 ComponentEnumItem *old_item, *new_item;
2281 HRESULT ret=S_OK;
2282 struct list *old_cursor;
2284 new_enum = HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentEnum));
2285 if (!new_enum)
2287 *ppenum = NULL;
2288 return E_OUTOFMEMORY;
2291 new_enum->IEnumUnknown_iface.lpVtbl = &ComponentEnumVtbl;
2292 new_enum->ref = 1;
2293 new_enum->cursor = NULL;
2294 list_init(&new_enum->objects);
2295 InitializeCriticalSection(&new_enum->lock);
2296 new_enum->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": ComponentEnum.lock");
2298 EnterCriticalSection(&This->lock);
2299 old_cursor = This->cursor;
2300 LeaveCriticalSection(&This->lock);
2302 LIST_FOR_EACH_ENTRY(old_item, &This->objects, ComponentEnumItem, entry)
2304 new_item = HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentEnumItem));
2305 if (!new_item)
2307 ret = E_OUTOFMEMORY;
2308 break;
2310 new_item->unk = old_item->unk;
2311 list_add_tail(&new_enum->objects, &new_item->entry);
2312 IUnknown_AddRef(new_item->unk);
2313 if (&old_item->entry == old_cursor) new_enum->cursor = &new_item->entry;
2316 if (FAILED(ret))
2318 IEnumUnknown_Release(&new_enum->IEnumUnknown_iface);
2319 *ppenum = NULL;
2321 else
2322 *ppenum = &new_enum->IEnumUnknown_iface;
2324 return ret;
2327 static const IEnumUnknownVtbl ComponentEnumVtbl = {
2328 ComponentEnum_QueryInterface,
2329 ComponentEnum_AddRef,
2330 ComponentEnum_Release,
2331 ComponentEnum_Next,
2332 ComponentEnum_Skip,
2333 ComponentEnum_Reset,
2334 ComponentEnum_Clone
2337 HRESULT CreateComponentEnumerator(DWORD componentTypes, DWORD options, IEnumUnknown **ppIEnumUnknown)
2339 ComponentEnum *This;
2340 ComponentEnumItem *item;
2341 const struct category *category;
2342 HKEY clsidkey, catidkey, instancekey;
2343 WCHAR guidstring[39];
2344 LONG res;
2345 int i;
2346 HRESULT hr=S_OK;
2347 CLSID clsid;
2349 if (options) FIXME("ignoring flags %lx\n", options);
2351 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, L"CLSID", 0, KEY_READ, &clsidkey);
2352 if (res != ERROR_SUCCESS)
2353 return HRESULT_FROM_WIN32(res);
2355 This = HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentEnum));
2356 if (!This)
2358 RegCloseKey(clsidkey);
2359 return E_OUTOFMEMORY;
2362 This->IEnumUnknown_iface.lpVtbl = &ComponentEnumVtbl;
2363 This->ref = 1;
2364 list_init(&This->objects);
2365 InitializeCriticalSection(&This->lock);
2366 This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": ComponentEnum.lock");
2368 for (category=categories; category->type && hr == S_OK; category++)
2370 if ((category->type & componentTypes) == 0) continue;
2371 StringFromGUID2(category->catid, guidstring, 39);
2372 res = RegOpenKeyExW(clsidkey, guidstring, 0, KEY_READ, &catidkey);
2373 if (res == ERROR_SUCCESS)
2375 res = RegOpenKeyExW(catidkey, L"Instance", 0, KEY_READ, &instancekey);
2376 if (res == ERROR_SUCCESS)
2378 i=0;
2379 for (;;i++)
2381 DWORD guidstring_size = 39;
2382 res = RegEnumKeyExW(instancekey, i, guidstring, &guidstring_size, NULL, NULL, NULL, NULL);
2383 if (res != ERROR_SUCCESS) break;
2385 item = HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentEnumItem));
2386 if (!item) { hr = E_OUTOFMEMORY; break; }
2388 hr = CLSIDFromString(guidstring, &clsid);
2389 if (SUCCEEDED(hr))
2391 hr = CreateComponentInfo(&clsid, (IWICComponentInfo**)&item->unk);
2392 if (SUCCEEDED(hr))
2393 list_add_tail(&This->objects, &item->entry);
2396 if (FAILED(hr))
2398 HeapFree(GetProcessHeap(), 0, item);
2399 hr = S_OK;
2402 RegCloseKey(instancekey);
2404 RegCloseKey(catidkey);
2406 if (res != ERROR_SUCCESS && res != ERROR_NO_MORE_ITEMS)
2407 hr = HRESULT_FROM_WIN32(res);
2409 RegCloseKey(clsidkey);
2411 if (SUCCEEDED(hr))
2413 IEnumUnknown_Reset(&This->IEnumUnknown_iface);
2414 *ppIEnumUnknown = &This->IEnumUnknown_iface;
2416 else
2418 *ppIEnumUnknown = NULL;
2419 IEnumUnknown_Release(&This->IEnumUnknown_iface);
2422 return hr;
2425 static BOOL is_1bpp_format(const WICPixelFormatGUID *format)
2427 return IsEqualGUID(format, &GUID_WICPixelFormatBlackWhite) ||
2428 IsEqualGUID(format, &GUID_WICPixelFormat1bppIndexed);
2431 HRESULT WINAPI WICConvertBitmapSource(REFWICPixelFormatGUID dstFormat, IWICBitmapSource *pISrc, IWICBitmapSource **ppIDst)
2433 HRESULT res;
2434 IEnumUnknown *enumconverters;
2435 IUnknown *unkconverterinfo;
2436 IWICFormatConverterInfo *converterinfo=NULL;
2437 IWICFormatConverter *converter=NULL;
2438 GUID srcFormat;
2439 WCHAR srcformatstr[39], dstformatstr[39];
2440 BOOL canconvert;
2441 ULONG num_fetched;
2443 TRACE("%s,%p,%p\n", debugstr_guid(dstFormat), pISrc, ppIDst);
2445 res = IWICBitmapSource_GetPixelFormat(pISrc, &srcFormat);
2446 if (FAILED(res)) return res;
2448 if (IsEqualGUID(&srcFormat, dstFormat) || (is_1bpp_format(&srcFormat) && is_1bpp_format(dstFormat)))
2450 IWICBitmapSource_AddRef(pISrc);
2451 *ppIDst = pISrc;
2452 return S_OK;
2455 StringFromGUID2(&srcFormat, srcformatstr, 39);
2456 StringFromGUID2(dstFormat, dstformatstr, 39);
2458 res = CreateComponentEnumerator(WICPixelFormatConverter, 0, &enumconverters);
2459 if (FAILED(res)) return res;
2461 while (!converter)
2463 res = IEnumUnknown_Next(enumconverters, 1, &unkconverterinfo, &num_fetched);
2465 if (res == S_OK)
2467 res = IUnknown_QueryInterface(unkconverterinfo, &IID_IWICFormatConverterInfo, (void**)&converterinfo);
2469 if (SUCCEEDED(res))
2471 canconvert = ConverterSupportsFormat(converterinfo, srcformatstr);
2473 if (canconvert)
2474 canconvert = ConverterSupportsFormat(converterinfo, dstformatstr);
2476 if (canconvert)
2478 res = IWICFormatConverterInfo_CreateInstance(converterinfo, &converter);
2480 if (SUCCEEDED(res))
2481 res = IWICFormatConverter_CanConvert(converter, &srcFormat, dstFormat, &canconvert);
2483 if (SUCCEEDED(res) && canconvert)
2484 res = IWICFormatConverter_Initialize(converter, pISrc, dstFormat, WICBitmapDitherTypeNone,
2485 NULL, 0.0, WICBitmapPaletteTypeMedianCut);
2487 if (FAILED(res) || !canconvert)
2489 if (converter)
2491 IWICFormatConverter_Release(converter);
2492 converter = NULL;
2497 IWICFormatConverterInfo_Release(converterinfo);
2500 IUnknown_Release(unkconverterinfo);
2502 else
2503 break;
2506 IEnumUnknown_Release(enumconverters);
2508 if (converter)
2510 res = IWICFormatConverter_QueryInterface(converter, &IID_IWICBitmapSource, (void **)ppIDst);
2511 IWICFormatConverter_Release(converter);
2512 return res;
2514 else
2516 FIXME("cannot convert %s to %s\n", debugstr_guid(&srcFormat), debugstr_guid(dstFormat));
2517 *ppIDst = NULL;
2518 return WINCODEC_ERR_COMPONENTNOTFOUND;