winebuild: Signal an error when a thiscall function doesn't take a pointer as first...
[wine/hramrach.git] / dlls / windowscodecs / info.c
blobf790dbc0eec47ce2cbbceb8008db4aabdcd9ccca
1 /*
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
19 #include "config.h"
21 #include <stdarg.h>
23 #define COBJMACROS
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winreg.h"
28 #include "objbase.h"
29 #include "wincodec.h"
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};
41 typedef struct {
42 const IWICBitmapDecoderInfoVtbl *lpIWICBitmapDecoderInfoVtbl;
43 LONG ref;
44 HKEY classkey;
45 CLSID clsid;
46 } BitmapDecoderInfo;
48 static HRESULT WINAPI BitmapDecoderInfo_QueryInterface(IWICBitmapDecoderInfo *iface, REFIID iid,
49 void **ppv)
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))
61 *ppv = This;
63 else
65 *ppv = NULL;
66 return E_NOINTERFACE;
69 IUnknown_AddRef((IUnknown*)*ppv);
70 return S_OK;
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);
80 return 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);
90 if (ref == 0)
92 RegCloseKey(This->classkey);
93 HeapFree(GetProcessHeap(), 0, This);
96 return ref;
99 static HRESULT WINAPI BitmapDecoderInfo_GetComponentType(IWICBitmapDecoderInfo *iface,
100 WICComponentType *pType)
102 TRACE("(%p,%p)\n", iface, pType);
103 *pType = WICDecoder;
104 return S_OK;
107 static HRESULT WINAPI BitmapDecoderInfo_GetCLSID(IWICBitmapDecoderInfo *iface, CLSID *pclsid)
109 FIXME("(%p,%p): stub\n", iface, pclsid);
110 return E_NOTIMPL;
113 static HRESULT WINAPI BitmapDecoderInfo_GetSigningStatus(IWICBitmapDecoderInfo *iface, DWORD *pStatus)
115 FIXME("(%p,%p): stub\n", iface, pStatus);
116 return E_NOTIMPL;
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);
123 return E_NOTIMPL;
126 static HRESULT WINAPI BitmapDecoderInfo_GetVendorGUID(IWICBitmapDecoderInfo *iface, GUID *pguidVendor)
128 FIXME("(%p,%p): stub\n", iface, pguidVendor);
129 return E_NOTIMPL;
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);
136 return E_NOTIMPL;
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);
143 return E_NOTIMPL;
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);
150 return E_NOTIMPL;
153 static HRESULT WINAPI BitmapDecoderInfo_GetContainerFormat(IWICBitmapDecoderInfo *iface,
154 GUID *pguidContainerFormat)
156 FIXME("(%p,%p): stub\n", iface, pguidContainerFormat);
157 return E_NOTIMPL;
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);
164 return E_NOTIMPL;
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);
171 return E_NOTIMPL;
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);
178 return E_NOTIMPL;
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);
185 return E_NOTIMPL;
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);
192 return E_NOTIMPL;
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);
199 return E_NOTIMPL;
202 static HRESULT WINAPI BitmapDecoderInfo_DoesSupportAnimation(IWICBitmapDecoderInfo *iface,
203 BOOL *pfSupportAnimation)
205 FIXME("(%p,%p): stub\n", iface, pfSupportAnimation);
206 return E_NOTIMPL;
209 static HRESULT WINAPI BitmapDecoderInfo_DoesSupportChromaKey(IWICBitmapDecoderInfo *iface,
210 BOOL *pfSupportChromaKey)
212 FIXME("(%p,%p): stub\n", iface, pfSupportChromaKey);
213 return E_NOTIMPL;
216 static HRESULT WINAPI BitmapDecoderInfo_DoesSupportLossless(IWICBitmapDecoderInfo *iface,
217 BOOL *pfSupportLossless)
219 FIXME("(%p,%p): stub\n", iface, pfSupportLossless);
220 return E_NOTIMPL;
223 static HRESULT WINAPI BitmapDecoderInfo_DoesSupportMultiframe(IWICBitmapDecoderInfo *iface,
224 BOOL *pfSupportMultiframe)
226 FIXME("(%p,%p): stub\n", iface, pfSupportMultiframe);
227 return E_NOTIMPL;
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);
234 return E_NOTIMPL;
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];
243 LONG res;
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};
252 HRESULT hr=S_OK;
253 UINT i;
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;
295 valuesize = length;
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;
303 valuesize = 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);
314 break;
318 else hr = HRESULT_FROM_WIN32(res);
320 RegCloseKey(patternskey);
322 if (hr == S_OK)
324 *pcPatterns = pattern_count;
325 *pcbPatternsActual = patterns_size;
326 if (pPatterns && cbSizePatterns < patterns_size)
327 hr = WINCODEC_ERR_INSUFFICIENTBUFFER;
330 return hr;
333 static HRESULT WINAPI BitmapDecoderInfo_MatchesPattern(IWICBitmapDecoderInfo *iface,
334 IStream *pIStream, BOOL *pfMatches)
336 WICBitmapPattern *patterns;
337 UINT pattern_count=0, patterns_size=0;
338 HRESULT hr;
339 int i, pos;
340 BYTE *data=NULL;
341 ULONG datasize=0;
342 ULONG bytesread;
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);
363 if (!data)
365 hr = E_OUTOFMEMORY;
366 break;
370 if (patterns[i].EndOfStream)
371 seekpos.QuadPart = -patterns[i].Position.QuadPart;
372 else
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 */
380 continue;
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])
386 break;
388 if (pos == patterns[i].Length) /* matches pattern */
390 hr = S_OK;
391 *pfMatches = TRUE;
392 break;
396 if (i == pattern_count) /* does not match any pattern */
398 hr = S_OK;
399 *pfMatches = FALSE;
402 end:
403 HeapFree(GetProcessHeap(), 0, patterns);
404 HeapFree(GetProcessHeap(), 0, data);
406 return hr;
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));
454 if (!This)
456 RegCloseKey(classkey);
457 return E_OUTOFMEMORY;
460 This->lpIWICBitmapDecoderInfoVtbl = &BitmapDecoderInfo_Vtbl;
461 This->ref = 1;
462 This->classkey = classkey;
463 memcpy(&This->clsid, clsid, sizeof(CLSID));
465 *ppIInfo = (IWICComponentInfo*)This;
466 return S_OK;
469 typedef struct {
470 const IWICFormatConverterInfoVtbl *lpIWICFormatConverterInfoVtbl;
471 LONG ref;
472 HKEY classkey;
473 CLSID clsid;
474 } FormatConverterInfo;
476 static HRESULT WINAPI FormatConverterInfo_QueryInterface(IWICFormatConverterInfo *iface, REFIID iid,
477 void **ppv)
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))
488 *ppv = This;
490 else
492 *ppv = NULL;
493 return E_NOINTERFACE;
496 IUnknown_AddRef((IUnknown*)*ppv);
497 return S_OK;
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);
507 return 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);
517 if (ref == 0)
519 RegCloseKey(This->classkey);
520 HeapFree(GetProcessHeap(), 0, This);
523 return ref;
526 static HRESULT WINAPI FormatConverterInfo_GetComponentType(IWICFormatConverterInfo *iface,
527 WICComponentType *pType)
529 TRACE("(%p,%p)\n", iface, pType);
530 *pType = WICPixelFormatConverter;
531 return S_OK;
534 static HRESULT WINAPI FormatConverterInfo_GetCLSID(IWICFormatConverterInfo *iface, CLSID *pclsid)
536 FIXME("(%p,%p): stub\n", iface, pclsid);
537 return E_NOTIMPL;
540 static HRESULT WINAPI FormatConverterInfo_GetSigningStatus(IWICFormatConverterInfo *iface, DWORD *pStatus)
542 FIXME("(%p,%p): stub\n", iface, pStatus);
543 return E_NOTIMPL;
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);
550 return E_NOTIMPL;
553 static HRESULT WINAPI FormatConverterInfo_GetVendorGUID(IWICFormatConverterInfo *iface, GUID *pguidVendor)
555 FIXME("(%p,%p): stub\n", iface, pguidVendor);
556 return E_NOTIMPL;
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);
563 return E_NOTIMPL;
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);
570 return E_NOTIMPL;
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);
577 return E_NOTIMPL;
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);
584 return E_NOTIMPL;
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)
600 LONG res;
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));
639 if (!This)
641 RegCloseKey(classkey);
642 return E_OUTOFMEMORY;
645 This->lpIWICFormatConverterInfoVtbl = &FormatConverterInfo_Vtbl;
646 This->ref = 1;
647 This->classkey = classkey;
648 memcpy(&This->clsid, clsid, sizeof(CLSID));
650 *ppIInfo = (IWICComponentInfo*)This;
651 return S_OK;
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};
657 struct category {
658 WICComponentType type;
659 const GUID *catid;
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)
671 HKEY clsidkey;
672 HKEY classkey;
673 HKEY catidkey;
674 HKEY instancekey;
675 WCHAR guidstring[39];
676 LONG res;
677 const struct category *category;
678 int found=0;
679 HRESULT hr;
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);
699 found = 1;
701 RegCloseKey(instancekey);
703 RegCloseKey(catidkey);
705 if (found) break;
708 if (found)
710 res = RegOpenKeyExW(clsidkey, guidstring, 0, KEY_READ, &classkey);
711 if (res == ERROR_SUCCESS)
712 hr = category->constructor(classkey, clsid, ppIInfo);
713 else
714 hr = HRESULT_FROM_WIN32(res);
716 else
717 hr = E_FAIL;
719 RegCloseKey(clsidkey);
721 return hr;
724 typedef struct {
725 const IEnumUnknownVtbl *IEnumUnknown_Vtbl;
726 LONG ref;
727 struct list objects;
728 struct list *cursor;
729 CRITICAL_SECTION lock; /* Must be held when reading or writing cursor */
730 } ComponentEnum;
732 typedef struct {
733 struct list entry;
734 IUnknown *unk;
735 } ComponentEnumItem;
737 static const IEnumUnknownVtbl ComponentEnumVtbl;
739 static HRESULT WINAPI ComponentEnum_QueryInterface(IEnumUnknown *iface, REFIID iid,
740 void **ppv)
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))
749 *ppv = This;
751 else
753 *ppv = NULL;
754 return E_NOINTERFACE;
757 IUnknown_AddRef((IUnknown*)*ppv);
758 return S_OK;
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);
768 return 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);
779 if (ref == 0)
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);
792 return ref;
795 static HRESULT WINAPI ComponentEnum_Next(IEnumUnknown *iface, ULONG celt,
796 IUnknown **rgelt, ULONG *pceltFetched)
798 ComponentEnum *This = (ComponentEnum*)iface;
799 int num_fetched=0;
800 ComponentEnumItem *item;
801 HRESULT hr=S_OK;
803 TRACE("(%p,%u,%p,%p)\n", iface, celt, rgelt, pceltFetched);
805 EnterCriticalSection(&This->lock);
806 while (num_fetched<celt)
808 if (!This->cursor)
810 hr = S_FALSE;
811 break;
813 item = LIST_ENTRY(This->cursor, ComponentEnumItem, entry);
814 IUnknown_AddRef(item->unk);
815 rgelt[num_fetched] = item->unk;
816 num_fetched++;
817 This->cursor = list_next(&This->objects, This->cursor);
819 LeaveCriticalSection(&This->lock);
820 if (pceltFetched)
821 *pceltFetched = num_fetched;
822 return hr;
825 static HRESULT WINAPI ComponentEnum_Skip(IEnumUnknown *iface, ULONG celt)
827 ComponentEnum *This = (ComponentEnum*)iface;
828 int i;
829 HRESULT hr=S_OK;
831 TRACE("(%p,%u)\n", iface, celt);
833 EnterCriticalSection(&This->lock);
834 for (i=0; i<celt; i++)
836 if (!This->cursor)
838 hr = S_FALSE;
839 break;
841 This->cursor = list_next(&This->objects, This->cursor);
843 LeaveCriticalSection(&This->lock);
844 return hr;
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);
856 return S_OK;
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;
864 HRESULT ret=S_OK;
865 struct list *old_cursor;
867 new_enum = HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentEnum));
868 if (!new_enum)
870 *ppenum = NULL;
871 return E_OUTOFMEMORY;
874 new_enum->IEnumUnknown_Vtbl = &ComponentEnumVtbl;
875 new_enum->ref = 1;
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));
888 if (!new_item)
890 ret = E_OUTOFMEMORY;
891 break;
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;
899 if (FAILED(ret))
901 IUnknown_Release((IUnknown*)new_enum);
902 *ppenum = NULL;
904 else
905 *ppenum = (IEnumUnknown*)new_enum;
907 return ret;
910 static const IEnumUnknownVtbl ComponentEnumVtbl = {
911 ComponentEnum_QueryInterface,
912 ComponentEnum_AddRef,
913 ComponentEnum_Release,
914 ComponentEnum_Next,
915 ComponentEnum_Skip,
916 ComponentEnum_Reset,
917 ComponentEnum_Clone
920 HRESULT CreateComponentEnumerator(DWORD componentTypes, DWORD options, IEnumUnknown **ppIEnumUnknown)
922 ComponentEnum *This;
923 ComponentEnumItem *item;
924 const struct category *category;
925 HKEY clsidkey, catidkey, instancekey;
926 WCHAR guidstring[39];
927 LONG res;
928 int i;
929 HRESULT hr=S_OK;
930 CLSID clsid;
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));
939 if (!This)
941 RegCloseKey(clsidkey);
942 return E_OUTOFMEMORY;
945 This->IEnumUnknown_Vtbl = &ComponentEnumVtbl;
946 This->ref = 1;
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)
961 i=0;
962 for (;;i++)
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);
972 if (SUCCEEDED(hr))
974 hr = CreateComponentInfo(&clsid, (IWICComponentInfo**)&item->unk);
975 if (SUCCEEDED(hr))
976 list_add_tail(&This->objects, &item->entry);
979 if (FAILED(hr))
981 HeapFree(GetProcessHeap(), 0, item);
982 hr = S_OK;
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);
994 if (SUCCEEDED(hr))
996 IEnumUnknown_Reset((IEnumUnknown*)This);
997 *ppIEnumUnknown = (IEnumUnknown*)This;
999 else
1001 *ppIEnumUnknown = NULL;
1002 IUnknown_Release((IUnknown*)This);
1005 return hr;
1008 HRESULT WINAPI WICConvertBitmapSource(REFWICPixelFormatGUID dstFormat, IWICBitmapSource *pISrc, IWICBitmapSource **ppIDst)
1010 HRESULT res;
1011 IEnumUnknown *enumconverters;
1012 IUnknown *unkconverterinfo;
1013 IWICFormatConverterInfo *converterinfo=NULL;
1014 IWICFormatConverter *converter=NULL;
1015 GUID srcFormat;
1016 WCHAR srcformatstr[39], dstformatstr[39];
1017 BOOL canconvert;
1018 ULONG num_fetched;
1020 res = IWICBitmapSource_GetPixelFormat(pISrc, &srcFormat);
1021 if (FAILED(res)) return res;
1023 if (IsEqualGUID(&srcFormat, dstFormat))
1025 IWICBitmapSource_AddRef(pISrc);
1026 *ppIDst = pISrc;
1027 return S_OK;
1030 StringFromGUID2(&srcFormat, srcformatstr, 39);
1031 StringFromGUID2(dstFormat, dstformatstr, 39);
1033 res = CreateComponentEnumerator(WICPixelFormatConverter, 0, &enumconverters);
1034 if (FAILED(res)) return res;
1036 while (!converter)
1038 res = IEnumUnknown_Next(enumconverters, 1, &unkconverterinfo, &num_fetched);
1040 if (res == S_OK)
1042 res = IUnknown_QueryInterface(unkconverterinfo, &IID_IWICFormatConverterInfo, (void**)&converterinfo);
1044 if (SUCCEEDED(res))
1046 canconvert = ConverterSupportsFormat(converterinfo, srcformatstr);
1048 if (canconvert)
1049 canconvert = ConverterSupportsFormat(converterinfo, dstformatstr);
1051 if (canconvert)
1053 res = IWICFormatConverterInfo_CreateInstance(converterinfo, &converter);
1055 if (SUCCEEDED(res))
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)
1064 if (converter)
1066 IWICFormatConverter_Release(converter);
1067 converter = NULL;
1069 res = S_OK;
1073 IWICFormatConverterInfo_Release(converterinfo);
1076 IUnknown_Release(unkconverterinfo);
1078 else
1079 break;
1082 IEnumUnknown_Release(enumconverters);
1084 if (converter)
1086 *ppIDst = (IWICBitmapSource*)converter;
1087 return S_OK;
1089 else
1091 FIXME("cannot convert %s to %s\n", debugstr_guid(&srcFormat), debugstr_guid(dstFormat));
1092 *ppIDst = NULL;
1093 return WINCODEC_ERR_COMPONENTNOTFOUND;