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
);
821 *pceltFetched
= num_fetched
;
825 static HRESULT WINAPI
ComponentEnum_Skip(IEnumUnknown
*iface
, ULONG celt
)
827 ComponentEnum
*This
= (ComponentEnum
*)iface
;
831 TRACE("(%p,%u)\n", iface
, celt
);
833 EnterCriticalSection(&This
->lock
);
834 for (i
=0; i
<celt
; i
++)
841 This
->cursor
= list_next(&This
->objects
, This
->cursor
);
843 LeaveCriticalSection(&This
->lock
);
847 static HRESULT WINAPI
ComponentEnum_Reset(IEnumUnknown
*iface
)
849 ComponentEnum
*This
= (ComponentEnum
*)iface
;
851 TRACE("(%p)\n", iface
);
853 EnterCriticalSection(&This
->lock
);
854 This
->cursor
= list_head(&This
->objects
);
855 LeaveCriticalSection(&This
->lock
);
859 static HRESULT WINAPI
ComponentEnum_Clone(IEnumUnknown
*iface
, IEnumUnknown
**ppenum
)
861 ComponentEnum
*This
= (ComponentEnum
*)iface
;
862 ComponentEnum
*new_enum
;
863 ComponentEnumItem
*old_item
, *new_item
;
865 struct list
*old_cursor
;
867 new_enum
= HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentEnum
));
871 return E_OUTOFMEMORY
;
874 new_enum
->IEnumUnknown_Vtbl
= &ComponentEnumVtbl
;
876 new_enum
->cursor
= NULL
;
877 list_init(&new_enum
->objects
);
878 InitializeCriticalSection(&new_enum
->lock
);
879 new_enum
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": ComponentEnum.lock");
881 EnterCriticalSection(&This
->lock
);
882 old_cursor
= This
->cursor
;
883 LeaveCriticalSection(&This
->lock
);
885 LIST_FOR_EACH_ENTRY(old_item
, &This
->objects
, ComponentEnumItem
, entry
)
887 new_item
= HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentEnumItem
));
893 new_item
->unk
= old_item
->unk
;
894 list_add_tail(&new_enum
->objects
, &new_item
->entry
);
895 IUnknown_AddRef(new_item
->unk
);
896 if (&old_item
->entry
== old_cursor
) new_enum
->cursor
= &new_item
->entry
;
901 IUnknown_Release((IUnknown
*)new_enum
);
905 *ppenum
= (IEnumUnknown
*)new_enum
;
910 static const IEnumUnknownVtbl ComponentEnumVtbl
= {
911 ComponentEnum_QueryInterface
,
912 ComponentEnum_AddRef
,
913 ComponentEnum_Release
,
920 HRESULT
CreateComponentEnumerator(DWORD componentTypes
, DWORD options
, IEnumUnknown
**ppIEnumUnknown
)
923 ComponentEnumItem
*item
;
924 const struct category
*category
;
925 HKEY clsidkey
, catidkey
, instancekey
;
926 WCHAR guidstring
[39];
932 if (options
) FIXME("ignoring flags %x\n", options
);
934 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0, KEY_READ
, &clsidkey
);
935 if (res
!= ERROR_SUCCESS
)
936 return HRESULT_FROM_WIN32(res
);
938 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentEnum
));
941 RegCloseKey(clsidkey
);
942 return E_OUTOFMEMORY
;
945 This
->IEnumUnknown_Vtbl
= &ComponentEnumVtbl
;
947 list_init(&This
->objects
);
948 InitializeCriticalSection(&This
->lock
);
949 This
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": ComponentEnum.lock");
951 for (category
=categories
; category
->type
&& hr
== S_OK
; category
++)
953 if ((category
->type
& componentTypes
) == 0) continue;
954 StringFromGUID2(category
->catid
, guidstring
, 39);
955 res
= RegOpenKeyExW(clsidkey
, guidstring
, 0, KEY_READ
, &catidkey
);
956 if (res
== ERROR_SUCCESS
)
958 res
= RegOpenKeyExW(catidkey
, instance_keyname
, 0, KEY_READ
, &instancekey
);
959 if (res
== ERROR_SUCCESS
)
964 DWORD guidstring_size
= 39;
965 res
= RegEnumKeyExW(instancekey
, i
, guidstring
, &guidstring_size
, NULL
, NULL
, NULL
, NULL
);
966 if (res
!= ERROR_SUCCESS
) break;
968 item
= HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentEnumItem
));
969 if (!item
) { hr
= E_OUTOFMEMORY
; break; }
971 hr
= CLSIDFromString(guidstring
, &clsid
);
974 hr
= CreateComponentInfo(&clsid
, (IWICComponentInfo
**)&item
->unk
);
976 list_add_tail(&This
->objects
, &item
->entry
);
981 HeapFree(GetProcessHeap(), 0, item
);
985 RegCloseKey(instancekey
);
987 RegCloseKey(catidkey
);
989 if (res
!= ERROR_SUCCESS
&& res
!= ERROR_NO_MORE_ITEMS
)
990 hr
= HRESULT_FROM_WIN32(res
);
992 RegCloseKey(clsidkey
);
996 IEnumUnknown_Reset((IEnumUnknown
*)This
);
997 *ppIEnumUnknown
= (IEnumUnknown
*)This
;
1001 *ppIEnumUnknown
= NULL
;
1002 IUnknown_Release((IUnknown
*)This
);
1008 HRESULT WINAPI
WICConvertBitmapSource(REFWICPixelFormatGUID dstFormat
, IWICBitmapSource
*pISrc
, IWICBitmapSource
**ppIDst
)
1011 IEnumUnknown
*enumconverters
;
1012 IUnknown
*unkconverterinfo
;
1013 IWICFormatConverterInfo
*converterinfo
=NULL
;
1014 IWICFormatConverter
*converter
=NULL
;
1016 WCHAR srcformatstr
[39], dstformatstr
[39];
1020 res
= IWICBitmapSource_GetPixelFormat(pISrc
, &srcFormat
);
1021 if (FAILED(res
)) return res
;
1023 if (IsEqualGUID(&srcFormat
, dstFormat
))
1025 IWICBitmapSource_AddRef(pISrc
);
1030 StringFromGUID2(&srcFormat
, srcformatstr
, 39);
1031 StringFromGUID2(dstFormat
, dstformatstr
, 39);
1033 res
= CreateComponentEnumerator(WICPixelFormatConverter
, 0, &enumconverters
);
1034 if (FAILED(res
)) return res
;
1038 res
= IEnumUnknown_Next(enumconverters
, 1, &unkconverterinfo
, &num_fetched
);
1042 res
= IUnknown_QueryInterface(unkconverterinfo
, &IID_IWICFormatConverterInfo
, (void**)&converterinfo
);
1046 canconvert
= ConverterSupportsFormat(converterinfo
, srcformatstr
);
1049 canconvert
= ConverterSupportsFormat(converterinfo
, dstformatstr
);
1053 res
= IWICFormatConverterInfo_CreateInstance(converterinfo
, &converter
);
1056 res
= IWICFormatConverter_CanConvert(converter
, &srcFormat
, dstFormat
, &canconvert
);
1058 if (SUCCEEDED(res
) && canconvert
)
1059 res
= IWICFormatConverter_Initialize(converter
, pISrc
, dstFormat
, WICBitmapDitherTypeNone
,
1060 NULL
, 0.0, WICBitmapPaletteTypeCustom
);
1062 if (FAILED(res
) || !canconvert
)
1066 IWICFormatConverter_Release(converter
);
1073 IWICFormatConverterInfo_Release(converterinfo
);
1076 IUnknown_Release(unkconverterinfo
);
1082 IEnumUnknown_Release(enumconverters
);
1086 *ppIDst
= (IWICBitmapSource
*)converter
;
1091 FIXME("cannot convert %s to %s\n", debugstr_guid(&srcFormat
), debugstr_guid(dstFormat
));
1093 return WINCODEC_ERR_COMPONENTNOTFOUND
;