wordpad: Add Ukrainian translations.
[wine/hacks.git] / dlls / windowscodecs / info.c
blobf909d3a6b6e7cdc99c75f50ce023598b15b24169
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 } ComponentEnum;
731 typedef struct {
732 struct list entry;
733 IUnknown *unk;
734 } ComponentEnumItem;
736 static const IEnumUnknownVtbl ComponentEnumVtbl;
738 static HRESULT WINAPI ComponentEnum_QueryInterface(IEnumUnknown *iface, REFIID iid,
739 void **ppv)
741 ComponentEnum *This = (ComponentEnum*)iface;
742 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
744 if (!ppv) return E_INVALIDARG;
746 if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IEnumUnknown, iid))
748 *ppv = This;
750 else
752 *ppv = NULL;
753 return E_NOINTERFACE;
756 IUnknown_AddRef((IUnknown*)*ppv);
757 return S_OK;
760 static ULONG WINAPI ComponentEnum_AddRef(IEnumUnknown *iface)
762 ComponentEnum *This = (ComponentEnum*)iface;
763 ULONG ref = InterlockedIncrement(&This->ref);
765 TRACE("(%p) refcount=%u\n", iface, ref);
767 return ref;
770 static ULONG WINAPI ComponentEnum_Release(IEnumUnknown *iface)
772 ComponentEnum *This = (ComponentEnum*)iface;
773 ULONG ref = InterlockedDecrement(&This->ref);
774 ComponentEnumItem *cursor, *cursor2;
776 TRACE("(%p) refcount=%u\n", iface, ref);
778 if (ref == 0)
780 LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, &This->objects, ComponentEnumItem, entry)
782 IUnknown_Release(cursor->unk);
783 list_remove(&cursor->entry);
784 HeapFree(GetProcessHeap(), 0, cursor);
786 HeapFree(GetProcessHeap(), 0, This);
789 return ref;
792 static HRESULT WINAPI ComponentEnum_Next(IEnumUnknown *iface, ULONG celt,
793 IUnknown **rgelt, ULONG *pceltFetched)
795 ComponentEnum *This = (ComponentEnum*)iface;
796 int num_fetched=0;
797 ComponentEnumItem *item;
799 TRACE("(%p,%u,%p,%p)\n", iface, celt, rgelt, pceltFetched);
801 while (num_fetched<celt)
803 if (!This->cursor)
805 *pceltFetched = num_fetched;
806 return S_FALSE;
808 item = LIST_ENTRY(This->cursor, ComponentEnumItem, entry);
809 IUnknown_AddRef(item->unk);
810 rgelt[num_fetched] = item->unk;
811 num_fetched++;
812 This->cursor = list_next(&This->objects, This->cursor);
814 *pceltFetched = num_fetched;
815 return S_OK;
818 static HRESULT WINAPI ComponentEnum_Skip(IEnumUnknown *iface, ULONG celt)
820 ComponentEnum *This = (ComponentEnum*)iface;
821 int i;
823 TRACE("(%p,%u)\n", iface, celt);
825 for (i=0; i<celt; i++)
827 if (!This->cursor)
828 return S_FALSE;
829 This->cursor = list_next(&This->objects, This->cursor);
831 return S_OK;
834 static HRESULT WINAPI ComponentEnum_Reset(IEnumUnknown *iface)
836 ComponentEnum *This = (ComponentEnum*)iface;
838 TRACE("(%p)\n", iface);
840 This->cursor = list_head(&This->objects);
841 return S_OK;
844 static HRESULT WINAPI ComponentEnum_Clone(IEnumUnknown *iface, IEnumUnknown **ppenum)
846 ComponentEnum *This = (ComponentEnum*)iface;
847 ComponentEnum *new_enum;
848 ComponentEnumItem *old_item, *new_item;
849 HRESULT ret=S_OK;
851 new_enum = HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentEnum));
852 if (!new_enum)
854 *ppenum = NULL;
855 return E_OUTOFMEMORY;
858 new_enum->IEnumUnknown_Vtbl = &ComponentEnumVtbl;
859 new_enum->ref = 1;
860 new_enum->cursor = NULL;
862 list_init(&new_enum->objects);
863 LIST_FOR_EACH_ENTRY(old_item, &This->objects, ComponentEnumItem, entry)
865 new_item = HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentEnumItem));
866 if (!new_item)
868 ret = E_OUTOFMEMORY;
869 break;
871 new_item->unk = old_item->unk;
872 list_add_tail(&new_enum->objects, &new_item->entry);
873 IUnknown_AddRef(new_item->unk);
874 if (&old_item->entry == This->cursor) new_enum->cursor = &new_item->entry;
877 if (FAILED(ret))
879 IUnknown_Release((IUnknown*)new_enum);
880 *ppenum = NULL;
882 else
883 *ppenum = (IEnumUnknown*)new_enum;
885 return ret;
888 static const IEnumUnknownVtbl ComponentEnumVtbl = {
889 ComponentEnum_QueryInterface,
890 ComponentEnum_AddRef,
891 ComponentEnum_Release,
892 ComponentEnum_Next,
893 ComponentEnum_Skip,
894 ComponentEnum_Reset,
895 ComponentEnum_Clone
898 HRESULT CreateComponentEnumerator(DWORD componentTypes, DWORD options, IEnumUnknown **ppIEnumUnknown)
900 ComponentEnum *This;
901 ComponentEnumItem *item;
902 const struct category *category;
903 HKEY clsidkey, catidkey, instancekey;
904 WCHAR guidstring[39];
905 LONG res;
906 int i;
907 HRESULT hr=S_OK;
908 CLSID clsid;
910 if (options) FIXME("ignoring flags %x\n", options);
912 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, KEY_READ, &clsidkey);
913 if (res != ERROR_SUCCESS)
914 return HRESULT_FROM_WIN32(res);
916 This = HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentEnum));
917 if (!This)
919 RegCloseKey(clsidkey);
920 return E_OUTOFMEMORY;
923 This->IEnumUnknown_Vtbl = &ComponentEnumVtbl;
924 This->ref = 1;
925 list_init(&This->objects);
927 for (category=categories; category->type && hr == S_OK; category++)
929 if ((category->type & componentTypes) == 0) continue;
930 StringFromGUID2(category->catid, guidstring, 39);
931 res = RegOpenKeyExW(clsidkey, guidstring, 0, KEY_READ, &catidkey);
932 if (res == ERROR_SUCCESS)
934 res = RegOpenKeyExW(catidkey, instance_keyname, 0, KEY_READ, &instancekey);
935 if (res == ERROR_SUCCESS)
937 i=0;
938 for (;;i++)
940 DWORD guidstring_size = 39;
941 res = RegEnumKeyExW(instancekey, i, guidstring, &guidstring_size, NULL, NULL, NULL, NULL);
942 if (res != ERROR_SUCCESS) break;
944 item = HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentEnumItem));
945 if (!item) { hr = E_OUTOFMEMORY; break; }
947 hr = CLSIDFromString(guidstring, &clsid);
948 if (SUCCEEDED(hr))
950 hr = CreateComponentInfo(&clsid, (IWICComponentInfo**)&item->unk);
951 if (SUCCEEDED(hr))
952 list_add_tail(&This->objects, &item->entry);
955 if (FAILED(hr))
957 HeapFree(GetProcessHeap(), 0, item);
958 hr = S_OK;
961 RegCloseKey(instancekey);
963 RegCloseKey(catidkey);
965 if (res != ERROR_SUCCESS && res != ERROR_NO_MORE_ITEMS)
966 hr = HRESULT_FROM_WIN32(res);
968 RegCloseKey(clsidkey);
970 if (SUCCEEDED(hr))
972 IEnumUnknown_Reset((IEnumUnknown*)This);
973 *ppIEnumUnknown = (IEnumUnknown*)This;
975 else
977 *ppIEnumUnknown = NULL;
978 IUnknown_Release((IUnknown*)This);
981 return hr;
984 HRESULT WINAPI WICConvertBitmapSource(REFWICPixelFormatGUID dstFormat, IWICBitmapSource *pISrc, IWICBitmapSource **ppIDst)
986 HRESULT res;
987 IEnumUnknown *enumconverters;
988 IUnknown *unkconverterinfo;
989 IWICFormatConverterInfo *converterinfo=NULL;
990 IWICFormatConverter *converter=NULL;
991 GUID srcFormat;
992 WCHAR srcformatstr[39], dstformatstr[39];
993 BOOL canconvert;
994 ULONG num_fetched;
996 res = IWICBitmapSource_GetPixelFormat(pISrc, &srcFormat);
997 if (FAILED(res)) return res;
999 if (IsEqualGUID(&srcFormat, dstFormat))
1001 IWICBitmapSource_AddRef(pISrc);
1002 *ppIDst = pISrc;
1003 return S_OK;
1006 StringFromGUID2(&srcFormat, srcformatstr, 39);
1007 StringFromGUID2(dstFormat, dstformatstr, 39);
1009 res = CreateComponentEnumerator(WICPixelFormatConverter, 0, &enumconverters);
1010 if (FAILED(res)) return res;
1012 while (!converter)
1014 res = IEnumUnknown_Next(enumconverters, 1, &unkconverterinfo, &num_fetched);
1016 if (res == S_OK)
1018 res = IUnknown_QueryInterface(unkconverterinfo, &IID_IWICFormatConverterInfo, (void**)&converterinfo);
1020 if (SUCCEEDED(res))
1022 canconvert = ConverterSupportsFormat(converterinfo, srcformatstr);
1024 if (canconvert)
1025 canconvert = ConverterSupportsFormat(converterinfo, dstformatstr);
1027 if (canconvert)
1029 res = IWICFormatConverterInfo_CreateInstance(converterinfo, &converter);
1031 if (SUCCEEDED(res))
1032 res = IWICFormatConverter_CanConvert(converter, &srcFormat, dstFormat, &canconvert);
1034 if (SUCCEEDED(res) && canconvert)
1035 res = IWICFormatConverter_Initialize(converter, pISrc, dstFormat, WICBitmapDitherTypeNone,
1036 NULL, 0.0, WICBitmapPaletteTypeCustom);
1038 if (FAILED(res) || !canconvert)
1040 if (converter)
1042 IWICFormatConverter_Release(converter);
1043 converter = NULL;
1045 res = S_OK;
1049 IWICFormatConverterInfo_Release(converterinfo);
1052 IUnknown_Release(unkconverterinfo);
1054 else
1055 break;
1058 IEnumUnknown_Release(enumconverters);
1060 if (converter)
1062 *ppIDst = (IWICBitmapSource*)converter;
1063 return S_OK;
1065 else
1067 FIXME("cannot convert %s to %s\n", debugstr_guid(&srcFormat), debugstr_guid(dstFormat));
1068 *ppIDst = NULL;
1069 return WINCODEC_ERR_COMPONENTNOTFOUND;