2 * Copyright 2009 Vincent Povirk for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
31 #include "wincodecs_private.h"
33 #include "wine/debug.h"
34 #include "wine/unicode.h"
35 #include "wine/list.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
39 static WCHAR const pixelformats_keyname[] = {'P','i','x','e','l','F','o','r','m','a','t','s',0};
42 const IWICBitmapDecoderInfoVtbl *lpIWICBitmapDecoderInfoVtbl;
48 static HRESULT WINAPI BitmapDecoderInfo_QueryInterface(IWICBitmapDecoderInfo *iface, REFIID iid,
51 BitmapDecoderInfo *This = (BitmapDecoderInfo*)iface;
52 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
54 if (!ppv) return E_INVALIDARG;
56 if (IsEqualIID(&IID_IUnknown, iid) ||
57 IsEqualIID(&IID_IWICComponentInfo, iid) ||
58 IsEqualIID(&IID_IWICBitmapCodecInfo, iid) ||
59 IsEqualIID(&IID_IWICBitmapDecoderInfo ,iid))
69 IUnknown_AddRef((IUnknown*)*ppv);
73 static ULONG WINAPI BitmapDecoderInfo_AddRef(IWICBitmapDecoderInfo *iface)
75 BitmapDecoderInfo *This = (BitmapDecoderInfo*)iface;
76 ULONG ref = InterlockedIncrement(&This->ref);
78 TRACE("(%p) refcount=%u\n", iface, ref);
83 static ULONG WINAPI BitmapDecoderInfo_Release(IWICBitmapDecoderInfo *iface)
85 BitmapDecoderInfo *This = (BitmapDecoderInfo*)iface;
86 ULONG ref = InterlockedDecrement(&This->ref);
88 TRACE("(%p) refcount=%u\n", iface, ref);
92 RegCloseKey(This->classkey);
93 HeapFree(GetProcessHeap(), 0, This);
99 static HRESULT WINAPI BitmapDecoderInfo_GetComponentType(IWICBitmapDecoderInfo *iface,
100 WICComponentType *pType)
102 TRACE("(%p,%p)\n", iface, pType);
107 static HRESULT WINAPI BitmapDecoderInfo_GetCLSID(IWICBitmapDecoderInfo *iface, CLSID *pclsid)
109 FIXME("(%p,%p): stub\n", iface, pclsid);
113 static HRESULT WINAPI BitmapDecoderInfo_GetSigningStatus(IWICBitmapDecoderInfo *iface, DWORD *pStatus)
115 FIXME("(%p,%p): stub\n", iface, pStatus);
119 static HRESULT WINAPI BitmapDecoderInfo_GetAuthor(IWICBitmapDecoderInfo *iface, UINT cchAuthor,
120 WCHAR *wzAuthor, UINT *pcchActual)
122 FIXME("(%p,%u,%p,%p): stub\n", iface, cchAuthor, wzAuthor, pcchActual);
126 static HRESULT WINAPI BitmapDecoderInfo_GetVendorGUID(IWICBitmapDecoderInfo *iface, GUID *pguidVendor)
128 FIXME("(%p,%p): stub\n", iface, pguidVendor);
132 static HRESULT WINAPI BitmapDecoderInfo_GetVersion(IWICBitmapDecoderInfo *iface, UINT cchVersion,
133 WCHAR *wzVersion, UINT *pcchActual)
135 FIXME("(%p,%u,%p,%p): stub\n", iface, cchVersion, wzVersion, pcchActual);
139 static HRESULT WINAPI BitmapDecoderInfo_GetSpecVersion(IWICBitmapDecoderInfo *iface, UINT cchSpecVersion,
140 WCHAR *wzSpecVersion, UINT *pcchActual)
142 FIXME("(%p,%u,%p,%p): stub\n", iface, cchSpecVersion, wzSpecVersion, pcchActual);
146 static HRESULT WINAPI BitmapDecoderInfo_GetFriendlyName(IWICBitmapDecoderInfo *iface, UINT cchFriendlyName,
147 WCHAR *wzFriendlyName, UINT *pcchActual)
149 FIXME("(%p,%u,%p,%p): stub\n", iface, cchFriendlyName, wzFriendlyName, pcchActual);
153 static HRESULT WINAPI BitmapDecoderInfo_GetContainerFormat(IWICBitmapDecoderInfo *iface,
154 GUID *pguidContainerFormat)
156 FIXME("(%p,%p): stub\n", iface, pguidContainerFormat);
160 static HRESULT WINAPI BitmapDecoderInfo_GetPixelFormats(IWICBitmapDecoderInfo *iface,
161 UINT cFormats, GUID *pguidPixelFormats, UINT *pcActual)
163 FIXME("(%p,%u,%p,%p): stub\n", iface, cFormats, pguidPixelFormats, pcActual);
167 static HRESULT WINAPI BitmapDecoderInfo_GetColorManagementVersion(IWICBitmapDecoderInfo *iface,
168 UINT cchColorManagementVersion, WCHAR *wzColorManagementVersion, UINT *pcchActual)
170 FIXME("(%p,%u,%p,%p): stub\n", iface, cchColorManagementVersion, wzColorManagementVersion, pcchActual);
174 static HRESULT WINAPI BitmapDecoderInfo_GetDeviceManufacturer(IWICBitmapDecoderInfo *iface,
175 UINT cchDeviceManufacturer, WCHAR *wzDeviceManufacturer, UINT *pcchActual)
177 FIXME("(%p,%u,%p,%p): stub\n", iface, cchDeviceManufacturer, wzDeviceManufacturer, pcchActual);
181 static HRESULT WINAPI BitmapDecoderInfo_GetDeviceModels(IWICBitmapDecoderInfo *iface,
182 UINT cchDeviceModels, WCHAR *wzDeviceModels, UINT *pcchActual)
184 FIXME("(%p,%u,%p,%p): stub\n", iface, cchDeviceModels, wzDeviceModels, pcchActual);
188 static HRESULT WINAPI BitmapDecoderInfo_GetMimeTypes(IWICBitmapDecoderInfo *iface,
189 UINT cchMimeTypes, WCHAR *wzMimeTypes, UINT *pcchActual)
191 FIXME("(%p,%u,%p,%p): stub\n", iface, cchMimeTypes, wzMimeTypes, pcchActual);
195 static HRESULT WINAPI BitmapDecoderInfo_GetFileExtensions(IWICBitmapDecoderInfo *iface,
196 UINT cchFileExtensions, WCHAR *wzFileExtensions, UINT *pcchActual)
198 FIXME("(%p,%u,%p,%p): stub\n", iface, cchFileExtensions, wzFileExtensions, pcchActual);
202 static HRESULT WINAPI BitmapDecoderInfo_DoesSupportAnimation(IWICBitmapDecoderInfo *iface,
203 BOOL *pfSupportAnimation)
205 FIXME("(%p,%p): stub\n", iface, pfSupportAnimation);
209 static HRESULT WINAPI BitmapDecoderInfo_DoesSupportChromaKey(IWICBitmapDecoderInfo *iface,
210 BOOL *pfSupportChromaKey)
212 FIXME("(%p,%p): stub\n", iface, pfSupportChromaKey);
216 static HRESULT WINAPI BitmapDecoderInfo_DoesSupportLossless(IWICBitmapDecoderInfo *iface,
217 BOOL *pfSupportLossless)
219 FIXME("(%p,%p): stub\n", iface, pfSupportLossless);
223 static HRESULT WINAPI BitmapDecoderInfo_DoesSupportMultiframe(IWICBitmapDecoderInfo *iface,
224 BOOL *pfSupportMultiframe)
226 FIXME("(%p,%p): stub\n", iface, pfSupportMultiframe);
230 static HRESULT WINAPI BitmapDecoderInfo_MatchesMimeType(IWICBitmapDecoderInfo *iface,
231 LPCWSTR wzMimeType, BOOL *pfMatches)
233 FIXME("(%p,%s,%p): stub\n", iface, debugstr_w(wzMimeType), pfMatches);
237 static HRESULT WINAPI BitmapDecoderInfo_GetPatterns(IWICBitmapDecoderInfo *iface,
238 UINT cbSizePatterns, WICBitmapPattern *pPatterns, UINT *pcPatterns, UINT *pcbPatternsActual)
240 BitmapDecoderInfo *This = (BitmapDecoderInfo*)iface;
241 UINT pattern_count=0, patterns_size=0;
242 WCHAR subkeyname[11];
244 HKEY patternskey, patternkey;
245 static const WCHAR uintformatW[] = {'%','u',0};
246 static const WCHAR patternsW[] = {'P','a','t','t','e','r','n','s',0};
247 static const WCHAR positionW[] = {'P','o','s','i','t','i','o','n',0};
248 static const WCHAR lengthW[] = {'L','e','n','g','t','h',0};
249 static const WCHAR patternW[] = {'P','a','t','t','e','r','n',0};
250 static const WCHAR maskW[] = {'M','a','s','k',0};
251 static const WCHAR endofstreamW[] = {'E','n','d','O','f','S','t','r','e','a','m',0};
254 BYTE *bPatterns=(BYTE*)pPatterns;
255 DWORD length, valuesize;
257 TRACE("(%p,%i,%p,%p,%p)\n", iface, cbSizePatterns, pPatterns, pcPatterns, pcbPatternsActual);
259 res = RegOpenKeyExW(This->classkey, patternsW, 0, KEY_READ, &patternskey);
260 if (res != ERROR_SUCCESS) return HRESULT_FROM_WIN32(res);
262 res = RegQueryInfoKeyW(patternskey, NULL, NULL, NULL, &pattern_count, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
263 if (res == ERROR_SUCCESS)
265 patterns_size = pattern_count * sizeof(WICBitmapPattern);
267 for (i=0; i<pattern_count; i++)
269 snprintfW(subkeyname, 11, uintformatW, i);
270 res = RegOpenKeyExW(patternskey, subkeyname, 0, KEY_READ, &patternkey);
271 if (res == ERROR_SUCCESS)
273 valuesize = sizeof(ULONG);
274 res = RegGetValueW(patternkey, NULL, lengthW, RRF_RT_DWORD, NULL,
275 &length, &valuesize);
276 patterns_size += length*2;
278 if ((cbSizePatterns >= patterns_size) && (res == ERROR_SUCCESS))
280 pPatterns[i].Length = length;
282 pPatterns[i].EndOfStream = 0;
283 valuesize = sizeof(BOOL);
284 RegGetValueW(patternkey, NULL, endofstreamW, RRF_RT_DWORD, NULL,
285 &pPatterns[i].EndOfStream, &valuesize);
287 pPatterns[i].Position.QuadPart = 0;
288 valuesize = sizeof(ULARGE_INTEGER);
289 res = RegGetValueW(patternkey, NULL, positionW, RRF_RT_DWORD|RRF_RT_QWORD, NULL,
290 &pPatterns[i].Position, &valuesize);
292 if (res == ERROR_SUCCESS)
294 pPatterns[i].Pattern = bPatterns+patterns_size-length*2;
296 res = RegGetValueW(patternkey, NULL, patternW, RRF_RT_REG_BINARY, NULL,
297 pPatterns[i].Pattern, &valuesize);
300 if (res == ERROR_SUCCESS)
302 pPatterns[i].Mask = bPatterns+patterns_size-length;
304 res = RegGetValueW(patternkey, NULL, maskW, RRF_RT_REG_BINARY, NULL,
305 pPatterns[i].Mask, &valuesize);
309 RegCloseKey(patternkey);
311 if (res != ERROR_SUCCESS)
313 hr = HRESULT_FROM_WIN32(res);
318 else hr = HRESULT_FROM_WIN32(res);
320 RegCloseKey(patternskey);
324 *pcPatterns = pattern_count;
325 *pcbPatternsActual = patterns_size;
326 if (pPatterns && cbSizePatterns < patterns_size)
327 hr = WINCODEC_ERR_INSUFFICIENTBUFFER;
333 static HRESULT WINAPI BitmapDecoderInfo_MatchesPattern(IWICBitmapDecoderInfo *iface,
334 IStream *pIStream, BOOL *pfMatches)
336 WICBitmapPattern *patterns;
337 UINT pattern_count=0, patterns_size=0;
343 LARGE_INTEGER seekpos;
345 TRACE("(%p,%p,%p)\n", iface, pIStream, pfMatches);
347 hr = BitmapDecoderInfo_GetPatterns(iface, 0, NULL, &pattern_count, &patterns_size);
348 if (FAILED(hr)) return hr;
350 patterns = HeapAlloc(GetProcessHeap(), 0, patterns_size);
351 if (!patterns) return E_OUTOFMEMORY;
353 hr = BitmapDecoderInfo_GetPatterns(iface, patterns_size, patterns, &pattern_count, &patterns_size);
354 if (FAILED(hr)) goto end;
356 for (i=0; i<pattern_count; i++)
358 if (datasize < patterns[i].Length)
360 HeapFree(GetProcessHeap(), 0, data);
361 datasize = patterns[i].Length;
362 data = HeapAlloc(GetProcessHeap(), 0, patterns[i].Length);
370 if (patterns[i].EndOfStream)
371 seekpos.QuadPart = -patterns[i].Position.QuadPart;
373 seekpos.QuadPart = patterns[i].Position.QuadPart;
374 hr = IStream_Seek(pIStream, seekpos, patterns[i].EndOfStream ? STREAM_SEEK_END : STREAM_SEEK_SET, NULL);
375 if (hr == STG_E_INVALIDFUNCTION) continue; /* before start of stream */
376 if (FAILED(hr)) break;
378 hr = IStream_Read(pIStream, data, patterns[i].Length, &bytesread);
379 if (hr == S_FALSE || (hr == S_OK && bytesread != patterns[i].Length)) /* past end of stream */
381 if (FAILED(hr)) break;
383 for (pos=0; pos<patterns[i].Length; pos++)
385 if ((data[pos] & patterns[i].Mask[pos]) != patterns[i].Pattern[pos])
388 if (pos == patterns[i].Length) /* matches pattern */
396 if (i == pattern_count) /* does not match any pattern */
403 HeapFree(GetProcessHeap(), 0, patterns);
404 HeapFree(GetProcessHeap(), 0, data);
409 static HRESULT WINAPI BitmapDecoderInfo_CreateInstance(IWICBitmapDecoderInfo *iface,
410 IWICBitmapDecoder **ppIBitmapDecoder)
412 BitmapDecoderInfo *This = (BitmapDecoderInfo*)iface;
414 TRACE("(%p,%p)\n", iface, ppIBitmapDecoder);
416 return CoCreateInstance(&This->clsid, NULL, CLSCTX_INPROC_SERVER,
417 &IID_IWICBitmapDecoder, (void**)ppIBitmapDecoder);
420 static const IWICBitmapDecoderInfoVtbl BitmapDecoderInfo_Vtbl = {
421 BitmapDecoderInfo_QueryInterface,
422 BitmapDecoderInfo_AddRef,
423 BitmapDecoderInfo_Release,
424 BitmapDecoderInfo_GetComponentType,
425 BitmapDecoderInfo_GetCLSID,
426 BitmapDecoderInfo_GetSigningStatus,
427 BitmapDecoderInfo_GetAuthor,
428 BitmapDecoderInfo_GetVendorGUID,
429 BitmapDecoderInfo_GetVersion,
430 BitmapDecoderInfo_GetSpecVersion,
431 BitmapDecoderInfo_GetFriendlyName,
432 BitmapDecoderInfo_GetContainerFormat,
433 BitmapDecoderInfo_GetPixelFormats,
434 BitmapDecoderInfo_GetColorManagementVersion,
435 BitmapDecoderInfo_GetDeviceManufacturer,
436 BitmapDecoderInfo_GetDeviceModels,
437 BitmapDecoderInfo_GetMimeTypes,
438 BitmapDecoderInfo_GetFileExtensions,
439 BitmapDecoderInfo_DoesSupportAnimation,
440 BitmapDecoderInfo_DoesSupportChromaKey,
441 BitmapDecoderInfo_DoesSupportLossless,
442 BitmapDecoderInfo_DoesSupportMultiframe,
443 BitmapDecoderInfo_MatchesMimeType,
444 BitmapDecoderInfo_GetPatterns,
445 BitmapDecoderInfo_MatchesPattern,
446 BitmapDecoderInfo_CreateInstance
449 static HRESULT BitmapDecoderInfo_Constructor(HKEY classkey, REFCLSID clsid, IWICComponentInfo **ppIInfo)
451 BitmapDecoderInfo *This;
453 This = HeapAlloc(GetProcessHeap(), 0, sizeof(BitmapDecoderInfo));
456 RegCloseKey(classkey);
457 return E_OUTOFMEMORY;
460 This->lpIWICBitmapDecoderInfoVtbl = &BitmapDecoderInfo_Vtbl;
462 This->classkey = classkey;
463 memcpy(&This->clsid, clsid, sizeof(CLSID));
465 *ppIInfo = (IWICComponentInfo*)This;
470 const IWICFormatConverterInfoVtbl *lpIWICFormatConverterInfoVtbl;
474 } FormatConverterInfo;
476 static HRESULT WINAPI FormatConverterInfo_QueryInterface(IWICFormatConverterInfo *iface, REFIID iid,
479 FormatConverterInfo *This = (FormatConverterInfo*)iface;
480 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
482 if (!ppv) return E_INVALIDARG;
484 if (IsEqualIID(&IID_IUnknown, iid) ||
485 IsEqualIID(&IID_IWICComponentInfo, iid) ||
486 IsEqualIID(&IID_IWICFormatConverterInfo ,iid))
493 return E_NOINTERFACE;
496 IUnknown_AddRef((IUnknown*)*ppv);
500 static ULONG WINAPI FormatConverterInfo_AddRef(IWICFormatConverterInfo *iface)
502 FormatConverterInfo *This = (FormatConverterInfo*)iface;
503 ULONG ref = InterlockedIncrement(&This->ref);
505 TRACE("(%p) refcount=%u\n", iface, ref);
510 static ULONG WINAPI FormatConverterInfo_Release(IWICFormatConverterInfo *iface)
512 FormatConverterInfo *This = (FormatConverterInfo*)iface;
513 ULONG ref = InterlockedDecrement(&This->ref);
515 TRACE("(%p) refcount=%u\n", iface, ref);
519 RegCloseKey(This->classkey);
520 HeapFree(GetProcessHeap(), 0, This);
526 static HRESULT WINAPI FormatConverterInfo_GetComponentType(IWICFormatConverterInfo *iface,
527 WICComponentType *pType)
529 TRACE("(%p,%p)\n", iface, pType);
530 *pType = WICPixelFormatConverter;
534 static HRESULT WINAPI FormatConverterInfo_GetCLSID(IWICFormatConverterInfo *iface, CLSID *pclsid)
536 FIXME("(%p,%p): stub\n", iface, pclsid);
540 static HRESULT WINAPI FormatConverterInfo_GetSigningStatus(IWICFormatConverterInfo *iface, DWORD *pStatus)
542 FIXME("(%p,%p): stub\n", iface, pStatus);
546 static HRESULT WINAPI FormatConverterInfo_GetAuthor(IWICFormatConverterInfo *iface, UINT cchAuthor,
547 WCHAR *wzAuthor, UINT *pcchActual)
549 FIXME("(%p,%u,%p,%p): stub\n", iface, cchAuthor, wzAuthor, pcchActual);
553 static HRESULT WINAPI FormatConverterInfo_GetVendorGUID(IWICFormatConverterInfo *iface, GUID *pguidVendor)
555 FIXME("(%p,%p): stub\n", iface, pguidVendor);
559 static HRESULT WINAPI FormatConverterInfo_GetVersion(IWICFormatConverterInfo *iface, UINT cchVersion,
560 WCHAR *wzVersion, UINT *pcchActual)
562 FIXME("(%p,%u,%p,%p): stub\n", iface, cchVersion, wzVersion, pcchActual);
566 static HRESULT WINAPI FormatConverterInfo_GetSpecVersion(IWICFormatConverterInfo *iface, UINT cchSpecVersion,
567 WCHAR *wzSpecVersion, UINT *pcchActual)
569 FIXME("(%p,%u,%p,%p): stub\n", iface, cchSpecVersion, wzSpecVersion, pcchActual);
573 static HRESULT WINAPI FormatConverterInfo_GetFriendlyName(IWICFormatConverterInfo *iface, UINT cchFriendlyName,
574 WCHAR *wzFriendlyName, UINT *pcchActual)
576 FIXME("(%p,%u,%p,%p): stub\n", iface, cchFriendlyName, wzFriendlyName, pcchActual);
580 static HRESULT WINAPI FormatConverterInfo_GetPixelFormats(IWICFormatConverterInfo *iface,
581 UINT cFormats, GUID *pguidPixelFormats, UINT *pcActual)
583 FIXME("(%p,%u,%p,%p): stub\n", iface, cFormats, pguidPixelFormats, pcActual);
587 static HRESULT WINAPI FormatConverterInfo_CreateInstance(IWICFormatConverterInfo *iface,
588 IWICFormatConverter **ppIFormatConverter)
590 FormatConverterInfo *This = (FormatConverterInfo*)iface;
592 TRACE("(%p,%p)\n", iface, ppIFormatConverter);
594 return CoCreateInstance(&This->clsid, NULL, CLSCTX_INPROC_SERVER,
595 &IID_IWICFormatConverter, (void**)ppIFormatConverter);
598 static BOOL ConverterSupportsFormat(IWICFormatConverterInfo *iface, const WCHAR *formatguid)
601 FormatConverterInfo *This = (FormatConverterInfo*)iface;
602 HKEY formats_key, guid_key;
604 /* Avoid testing using IWICFormatConverter_GetPixelFormats because that
605 would be O(n). A registry test should do better. */
607 res = RegOpenKeyExW(This->classkey, pixelformats_keyname, 0, KEY_READ, &formats_key);
608 if (res != ERROR_SUCCESS) return FALSE;
610 res = RegOpenKeyExW(formats_key, formatguid, 0, KEY_READ, &guid_key);
611 if (res == ERROR_SUCCESS) RegCloseKey(guid_key);
613 RegCloseKey(formats_key);
615 return (res == ERROR_SUCCESS);
618 static const IWICFormatConverterInfoVtbl FormatConverterInfo_Vtbl = {
619 FormatConverterInfo_QueryInterface,
620 FormatConverterInfo_AddRef,
621 FormatConverterInfo_Release,
622 FormatConverterInfo_GetComponentType,
623 FormatConverterInfo_GetCLSID,
624 FormatConverterInfo_GetSigningStatus,
625 FormatConverterInfo_GetAuthor,
626 FormatConverterInfo_GetVendorGUID,
627 FormatConverterInfo_GetVersion,
628 FormatConverterInfo_GetSpecVersion,
629 FormatConverterInfo_GetFriendlyName,
630 FormatConverterInfo_GetPixelFormats,
631 FormatConverterInfo_CreateInstance
634 static HRESULT FormatConverterInfo_Constructor(HKEY classkey, REFCLSID clsid, IWICComponentInfo **ppIInfo)
636 FormatConverterInfo *This;
638 This = HeapAlloc(GetProcessHeap(), 0, sizeof(FormatConverterInfo));
641 RegCloseKey(classkey);
642 return E_OUTOFMEMORY;
645 This->lpIWICFormatConverterInfoVtbl = &FormatConverterInfo_Vtbl;
647 This->classkey = classkey;
648 memcpy(&This->clsid, clsid, sizeof(CLSID));
650 *ppIInfo = (IWICComponentInfo*)This;
654 static WCHAR const clsid_keyname[] = {'C','L','S','I','D',0};
655 static WCHAR const instance_keyname[] = {'I','n','s','t','a','n','c','e',0};
658 WICComponentType type;
660 HRESULT (*constructor)(HKEY,REFCLSID,IWICComponentInfo**);
663 static const struct category categories[] = {
664 {WICDecoder, &CATID_WICBitmapDecoders, BitmapDecoderInfo_Constructor},
665 {WICPixelFormatConverter, &CATID_WICFormatConverters, FormatConverterInfo_Constructor},
669 HRESULT CreateComponentInfo(REFCLSID clsid, IWICComponentInfo **ppIInfo)
675 WCHAR guidstring[39];
677 const struct category *category;
681 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, KEY_READ, &clsidkey);
682 if (res != ERROR_SUCCESS)
683 return HRESULT_FROM_WIN32(res);
685 for (category=categories; category->type; category++)
687 StringFromGUID2(category->catid, guidstring, 39);
688 res = RegOpenKeyExW(clsidkey, guidstring, 0, KEY_READ, &catidkey);
689 if (res == ERROR_SUCCESS)
691 res = RegOpenKeyExW(catidkey, instance_keyname, 0, KEY_READ, &instancekey);
692 if (res == ERROR_SUCCESS)
694 StringFromGUID2(clsid, guidstring, 39);
695 res = RegOpenKeyExW(instancekey, guidstring, 0, KEY_READ, &classkey);
696 if (res == ERROR_SUCCESS)
698 RegCloseKey(classkey);
701 RegCloseKey(instancekey);
703 RegCloseKey(catidkey);
710 res = RegOpenKeyExW(clsidkey, guidstring, 0, KEY_READ, &classkey);
711 if (res == ERROR_SUCCESS)
712 hr = category->constructor(classkey, clsid, ppIInfo);
714 hr = HRESULT_FROM_WIN32(res);
719 RegCloseKey(clsidkey);
725 const IEnumUnknownVtbl *IEnumUnknown_Vtbl;
729 CRITICAL_SECTION lock; /* Must be held when reading or writing cursor */
737 static const IEnumUnknownVtbl ComponentEnumVtbl;
739 static HRESULT WINAPI ComponentEnum_QueryInterface(IEnumUnknown *iface, REFIID iid,
742 ComponentEnum *This = (ComponentEnum*)iface;
743 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
745 if (!ppv) return E_INVALIDARG;
747 if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IEnumUnknown, iid))
754 return E_NOINTERFACE;
757 IUnknown_AddRef((IUnknown*)*ppv);
761 static ULONG WINAPI ComponentEnum_AddRef(IEnumUnknown *iface)
763 ComponentEnum *This = (ComponentEnum*)iface;
764 ULONG ref = InterlockedIncrement(&This->ref);
766 TRACE("(%p) refcount=%u\n", iface, ref);
771 static ULONG WINAPI ComponentEnum_Release(IEnumUnknown *iface)
773 ComponentEnum *This = (ComponentEnum*)iface;
774 ULONG ref = InterlockedDecrement(&This->ref);
775 ComponentEnumItem *cursor, *cursor2;
777 TRACE("(%p) refcount=%u\n", iface, ref);
781 LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, &This->objects, ComponentEnumItem, entry)
783 IUnknown_Release(cursor->unk);
784 list_remove(&cursor->entry);
785 HeapFree(GetProcessHeap(), 0, cursor);
787 This->lock.DebugInfo->Spare[0] = 0;
788 DeleteCriticalSection(&This->lock);
789 HeapFree(GetProcessHeap(), 0, This);
795 static HRESULT WINAPI ComponentEnum_Next(IEnumUnknown *iface, ULONG celt,
796 IUnknown **rgelt, ULONG *pceltFetched)
798 ComponentEnum *This = (ComponentEnum*)iface;
800 ComponentEnumItem *item;
803 TRACE("(%p,%u,%p,%p)\n", iface, celt, rgelt, pceltFetched);
805 EnterCriticalSection(&This->lock);
806 while (num_fetched<celt)
813 item = LIST_ENTRY(This->cursor, ComponentEnumItem, entry);
814 IUnknown_AddRef(item->unk);
815 rgelt[num_fetched] = item->unk;
817 This->cursor = list_next(&This->objects, This->cursor);
819 LeaveCriticalSection(&This->lock);
820 *pceltFetched = num_fetched;
824 static HRESULT WINAPI ComponentEnum_Skip(IEnumUnknown *iface, ULONG celt)
826 ComponentEnum *This = (ComponentEnum*)iface;
830 TRACE("(%p,%u)\n", iface, celt);
832 EnterCriticalSection(&This->lock);
833 for (i=0; i<celt; i++)
840 This->cursor = list_next(&This->objects, This->cursor);
842 LeaveCriticalSection(&This->lock);
846 static HRESULT WINAPI ComponentEnum_Reset(IEnumUnknown *iface)
848 ComponentEnum *This = (ComponentEnum*)iface;
850 TRACE("(%p)\n", iface);
852 EnterCriticalSection(&This->lock);
853 This->cursor = list_head(&This->objects);
854 LeaveCriticalSection(&This->lock);
858 static HRESULT WINAPI ComponentEnum_Clone(IEnumUnknown *iface, IEnumUnknown **ppenum)
860 ComponentEnum *This = (ComponentEnum*)iface;
861 ComponentEnum *new_enum;
862 ComponentEnumItem *old_item, *new_item;
864 struct list *old_cursor;
866 new_enum = HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentEnum));
870 return E_OUTOFMEMORY;
873 new_enum->IEnumUnknown_Vtbl = &ComponentEnumVtbl;
875 new_enum->cursor = NULL;
876 list_init(&new_enum->objects);
877 InitializeCriticalSection(&new_enum->lock);
878 new_enum->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": ComponentEnum.lock");
880 EnterCriticalSection(&This->lock);
881 old_cursor = This->cursor;
882 LeaveCriticalSection(&This->lock);
884 LIST_FOR_EACH_ENTRY(old_item, &This->objects, ComponentEnumItem, entry)
886 new_item = HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentEnumItem));
892 new_item->unk = old_item->unk;
893 list_add_tail(&new_enum->objects, &new_item->entry);
894 IUnknown_AddRef(new_item->unk);
895 if (&old_item->entry == old_cursor) new_enum->cursor = &new_item->entry;
900 IUnknown_Release((IUnknown*)new_enum);
904 *ppenum = (IEnumUnknown*)new_enum;
909 static const IEnumUnknownVtbl ComponentEnumVtbl = {
910 ComponentEnum_QueryInterface,
911 ComponentEnum_AddRef,
912 ComponentEnum_Release,
919 HRESULT CreateComponentEnumerator(DWORD componentTypes, DWORD options, IEnumUnknown **ppIEnumUnknown)
922 ComponentEnumItem *item;
923 const struct category *category;
924 HKEY clsidkey, catidkey, instancekey;
925 WCHAR guidstring[39];
931 if (options) FIXME("ignoring flags %x\n", options);
933 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, KEY_READ, &clsidkey);
934 if (res != ERROR_SUCCESS)
935 return HRESULT_FROM_WIN32(res);
937 This = HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentEnum));
940 RegCloseKey(clsidkey);
941 return E_OUTOFMEMORY;
944 This->IEnumUnknown_Vtbl = &ComponentEnumVtbl;
946 list_init(&This->objects);
947 InitializeCriticalSection(&This->lock);
948 This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": ComponentEnum.lock");
950 for (category=categories; category->type && hr == S_OK; category++)
952 if ((category->type & componentTypes) == 0) continue;
953 StringFromGUID2(category->catid, guidstring, 39);
954 res = RegOpenKeyExW(clsidkey, guidstring, 0, KEY_READ, &catidkey);
955 if (res == ERROR_SUCCESS)
957 res = RegOpenKeyExW(catidkey, instance_keyname, 0, KEY_READ, &instancekey);
958 if (res == ERROR_SUCCESS)
963 DWORD guidstring_size = 39;
964 res = RegEnumKeyExW(instancekey, i, guidstring, &guidstring_size, NULL, NULL, NULL, NULL);
965 if (res != ERROR_SUCCESS) break;
967 item = HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentEnumItem));
968 if (!item) { hr = E_OUTOFMEMORY; break; }
970 hr = CLSIDFromString(guidstring, &clsid);
973 hr = CreateComponentInfo(&clsid, (IWICComponentInfo**)&item->unk);
975 list_add_tail(&This->objects, &item->entry);
980 HeapFree(GetProcessHeap(), 0, item);
984 RegCloseKey(instancekey);
986 RegCloseKey(catidkey);
988 if (res != ERROR_SUCCESS && res != ERROR_NO_MORE_ITEMS)
989 hr = HRESULT_FROM_WIN32(res);
991 RegCloseKey(clsidkey);
995 IEnumUnknown_Reset((IEnumUnknown*)This);
996 *ppIEnumUnknown = (IEnumUnknown*)This;
1000 *ppIEnumUnknown = NULL;
1001 IUnknown_Release((IUnknown*)This);
1007 HRESULT WINAPI WICConvertBitmapSource(REFWICPixelFormatGUID dstFormat, IWICBitmapSource *pISrc, IWICBitmapSource **ppIDst)
1010 IEnumUnknown *enumconverters;
1011 IUnknown *unkconverterinfo;
1012 IWICFormatConverterInfo *converterinfo=NULL;
1013 IWICFormatConverter *converter=NULL;
1015 WCHAR srcformatstr[39], dstformatstr[39];
1019 res = IWICBitmapSource_GetPixelFormat(pISrc, &srcFormat);
1020 if (FAILED(res)) return res;
1022 if (IsEqualGUID(&srcFormat, dstFormat))
1024 IWICBitmapSource_AddRef(pISrc);
1029 StringFromGUID2(&srcFormat, srcformatstr, 39);
1030 StringFromGUID2(dstFormat, dstformatstr, 39);
1032 res = CreateComponentEnumerator(WICPixelFormatConverter, 0, &enumconverters);
1033 if (FAILED(res)) return res;
1037 res = IEnumUnknown_Next(enumconverters, 1, &unkconverterinfo, &num_fetched);
1041 res = IUnknown_QueryInterface(unkconverterinfo, &IID_IWICFormatConverterInfo, (void**)&converterinfo);
1045 canconvert = ConverterSupportsFormat(converterinfo, srcformatstr);
1048 canconvert = ConverterSupportsFormat(converterinfo, dstformatstr);
1052 res = IWICFormatConverterInfo_CreateInstance(converterinfo, &converter);
1055 res = IWICFormatConverter_CanConvert(converter, &srcFormat, dstFormat, &canconvert);
1057 if (SUCCEEDED(res) && canconvert)
1058 res = IWICFormatConverter_Initialize(converter, pISrc, dstFormat, WICBitmapDitherTypeNone,
1059 NULL, 0.0, WICBitmapPaletteTypeCustom);
1061 if (FAILED(res) || !canconvert)
1065 IWICFormatConverter_Release(converter);
1072 IWICFormatConverterInfo_Release(converterinfo);
1075 IUnknown_Release(unkconverterinfo);
1081 IEnumUnknown_Release(enumconverters);
1085 *ppIDst = (IWICBitmapSource*)converter;
1090 FIXME("cannot convert %s to %s\n", debugstr_guid(&srcFormat), debugstr_guid(dstFormat));
1092 return WINCODEC_ERR_COMPONENTNOTFOUND;