22a7b83e2c224a4e84e240661631efbd026cfb8f
[reactos.git] / dll / win32 / windowscodecs / info.c
1 /*
2 * Copyright 2009 Vincent Povirk for CodeWeavers
3 * Copyright 2012 Dmitry Timoshkov
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 */
19
20 #include "config.h"
21
22 #include <stdarg.h>
23
24 #define COBJMACROS
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winreg.h"
29 #include "objbase.h"
30
31 #include "wincodecs_private.h"
32
33 #include "wine/debug.h"
34 #include "wine/unicode.h"
35 #include "wine/list.h"
36
37 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
38
39 static const WCHAR mimetypes_valuename[] = {'M','i','m','e','T','y','p','e','s',0};
40 static const WCHAR author_valuename[] = {'A','u','t','h','o','r',0};
41 static const WCHAR friendlyname_valuename[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0};
42 static const WCHAR pixelformats_keyname[] = {'P','i','x','e','l','F','o','r','m','a','t','s',0};
43 static const WCHAR formats_keyname[] = {'F','o','r','m','a','t','s',0};
44 static const WCHAR containerformat_valuename[] = {'C','o','n','t','a','i','n','e','r','F','o','r','m','a','t',0};
45 static const WCHAR metadataformat_valuename[] = {'M','e','t','a','d','a','t','a','F','o','r','m','a','t',0};
46 static const WCHAR vendor_valuename[] = {'V','e','n','d','o','r',0};
47 static const WCHAR version_valuename[] = {'V','e','r','s','i','o','n',0};
48 static const WCHAR specversion_valuename[] = {'S','p','e','c','V','e','r','s','i','o','n',0};
49 static const WCHAR bitsperpixel_valuename[] = {'B','i','t','L','e','n','g','t','h',0};
50 static const WCHAR channelcount_valuename[] = {'C','h','a','n','n','e','l','C','o','u','n','t',0};
51 static const WCHAR channelmasks_keyname[] = {'C','h','a','n','n','e','l','M','a','s','k','s',0};
52 static const WCHAR numericrepresentation_valuename[] = {'N','u','m','e','r','i','c','R','e','p','r','e','s','e','n','t','a','t','i','o','n',0};
53 static const WCHAR supportstransparency_valuename[] = {'S','u','p','p','o','r','t','s','T','r','a','n','s','p','a','r','e','n','c','y',0};
54 static const WCHAR requiresfullstream_valuename[] = {'R','e','q','u','i','r','e','s','F','u','l','l','S','t','r','e','a','m',0};
55 static const WCHAR supportspadding_valuename[] = {'S','u','p','p','o','r','t','s','P','a','d','d','i','n','g',0};
56 static const WCHAR fileextensions_valuename[] = {'F','i','l','e','E','x','t','e','n','s','i','o','n','s',0};
57 static const WCHAR containers_keyname[] = {'C','o','n','t','a','i','n','e','r','s',0};
58
59 static HRESULT ComponentInfo_GetStringValue(HKEY classkey, LPCWSTR value,
60 UINT buffer_size, WCHAR *buffer, UINT *actual_size)
61 {
62 LONG ret;
63 DWORD cbdata=buffer_size * sizeof(WCHAR);
64
65 if (!actual_size)
66 return E_INVALIDARG;
67
68 ret = RegGetValueW(classkey, NULL, value, RRF_RT_REG_SZ|RRF_NOEXPAND, NULL,
69 buffer, &cbdata);
70
71 if (ret == ERROR_FILE_NOT_FOUND)
72 {
73 *actual_size = 0;
74 return S_OK;
75 }
76
77 if (ret == 0 || ret == ERROR_MORE_DATA)
78 *actual_size = cbdata/sizeof(WCHAR);
79
80 if (!buffer && buffer_size != 0)
81 /* Yes, native returns the correct size in this case. */
82 return E_INVALIDARG;
83
84 if (ret == ERROR_MORE_DATA)
85 return WINCODEC_ERR_INSUFFICIENTBUFFER;
86
87 return HRESULT_FROM_WIN32(ret);
88 }
89
90 static HRESULT ComponentInfo_GetGUIDValue(HKEY classkey, LPCWSTR value,
91 GUID *result)
92 {
93 LONG ret;
94 WCHAR guid_string[39];
95 DWORD cbdata = sizeof(guid_string);
96 HRESULT hr;
97
98 if (!result)
99 return E_INVALIDARG;
100
101 ret = RegGetValueW(classkey, NULL, value, RRF_RT_REG_SZ|RRF_NOEXPAND, NULL,
102 guid_string, &cbdata);
103
104 if (ret != ERROR_SUCCESS)
105 return HRESULT_FROM_WIN32(ret);
106
107 if (cbdata < sizeof(guid_string))
108 {
109 ERR("incomplete GUID value\n");
110 return E_FAIL;
111 }
112
113 hr = CLSIDFromString(guid_string, result);
114
115 return hr;
116 }
117
118 static HRESULT ComponentInfo_GetDWORDValue(HKEY classkey, LPCWSTR value,
119 DWORD *result)
120 {
121 LONG ret;
122 DWORD cbdata = sizeof(DWORD);
123
124 if (!result)
125 return E_INVALIDARG;
126
127 ret = RegGetValueW(classkey, NULL, value, RRF_RT_DWORD, NULL,
128 result, &cbdata);
129
130 if (ret == ERROR_FILE_NOT_FOUND)
131 {
132 *result = 0;
133 return S_OK;
134 }
135
136 return HRESULT_FROM_WIN32(ret);
137 }
138
139 static HRESULT ComponentInfo_GetGuidList(HKEY classkey, LPCWSTR subkeyname,
140 UINT buffersize, GUID *buffer, UINT *actual_size)
141 {
142 LONG ret;
143 HKEY subkey;
144 UINT items_returned;
145 WCHAR guid_string[39];
146 DWORD guid_string_size;
147 HRESULT hr=S_OK;
148
149 if (!actual_size)
150 return E_INVALIDARG;
151
152 ret = RegOpenKeyExW(classkey, subkeyname, 0, KEY_READ, &subkey);
153 if (ret == ERROR_FILE_NOT_FOUND)
154 {
155 *actual_size = 0;
156 return S_OK;
157 }
158 else if (ret != ERROR_SUCCESS) return HRESULT_FROM_WIN32(ret);
159
160 if (buffer)
161 {
162 items_returned = 0;
163 guid_string_size = 39;
164 while (items_returned < buffersize)
165 {
166 ret = RegEnumKeyExW(subkey, items_returned, guid_string,
167 &guid_string_size, NULL, NULL, NULL, NULL);
168
169 if (ret != ERROR_SUCCESS)
170 {
171 hr = HRESULT_FROM_WIN32(ret);
172 break;
173 }
174
175 if (guid_string_size != 38)
176 {
177 hr = E_FAIL;
178 break;
179 }
180
181 hr = CLSIDFromString(guid_string, &buffer[items_returned]);
182 if (FAILED(hr))
183 break;
184
185 items_returned++;
186 guid_string_size = 39;
187 }
188
189 if (ret == ERROR_NO_MORE_ITEMS)
190 hr = S_OK;
191
192 *actual_size = items_returned;
193 }
194 else
195 {
196 ret = RegQueryInfoKeyW(subkey, NULL, NULL, NULL, actual_size, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
197 if (ret != ERROR_SUCCESS)
198 hr = HRESULT_FROM_WIN32(ret);
199 }
200
201 RegCloseKey(subkey);
202
203 return hr;
204 }
205
206 typedef struct {
207 IWICBitmapDecoderInfo IWICBitmapDecoderInfo_iface;
208 LONG ref;
209 HKEY classkey;
210 CLSID clsid;
211 } BitmapDecoderInfo;
212
213 static inline BitmapDecoderInfo *impl_from_IWICBitmapDecoderInfo(IWICBitmapDecoderInfo *iface)
214 {
215 return CONTAINING_RECORD(iface, BitmapDecoderInfo, IWICBitmapDecoderInfo_iface);
216 }
217
218 static HRESULT WINAPI BitmapDecoderInfo_QueryInterface(IWICBitmapDecoderInfo *iface, REFIID iid,
219 void **ppv)
220 {
221 BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
222 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
223
224 if (!ppv) return E_INVALIDARG;
225
226 if (IsEqualIID(&IID_IUnknown, iid) ||
227 IsEqualIID(&IID_IWICComponentInfo, iid) ||
228 IsEqualIID(&IID_IWICBitmapCodecInfo, iid) ||
229 IsEqualIID(&IID_IWICBitmapDecoderInfo ,iid))
230 {
231 *ppv = &This->IWICBitmapDecoderInfo_iface;
232 }
233 else
234 {
235 *ppv = NULL;
236 return E_NOINTERFACE;
237 }
238
239 IUnknown_AddRef((IUnknown*)*ppv);
240 return S_OK;
241 }
242
243 static ULONG WINAPI BitmapDecoderInfo_AddRef(IWICBitmapDecoderInfo *iface)
244 {
245 BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
246 ULONG ref = InterlockedIncrement(&This->ref);
247
248 TRACE("(%p) refcount=%u\n", iface, ref);
249
250 return ref;
251 }
252
253 static ULONG WINAPI BitmapDecoderInfo_Release(IWICBitmapDecoderInfo *iface)
254 {
255 BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
256 ULONG ref = InterlockedDecrement(&This->ref);
257
258 TRACE("(%p) refcount=%u\n", iface, ref);
259
260 if (ref == 0)
261 {
262 RegCloseKey(This->classkey);
263 HeapFree(GetProcessHeap(), 0, This);
264 }
265
266 return ref;
267 }
268
269 static HRESULT WINAPI BitmapDecoderInfo_GetComponentType(IWICBitmapDecoderInfo *iface,
270 WICComponentType *pType)
271 {
272 TRACE("(%p,%p)\n", iface, pType);
273 if (!pType) return E_INVALIDARG;
274 *pType = WICDecoder;
275 return S_OK;
276 }
277
278 static HRESULT WINAPI BitmapDecoderInfo_GetCLSID(IWICBitmapDecoderInfo *iface, CLSID *pclsid)
279 {
280 BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
281 TRACE("(%p,%p)\n", iface, pclsid);
282
283 if (!pclsid)
284 return E_INVALIDARG;
285
286 memcpy(pclsid, &This->clsid, sizeof(CLSID));
287
288 return S_OK;
289 }
290
291 static HRESULT WINAPI BitmapDecoderInfo_GetSigningStatus(IWICBitmapDecoderInfo *iface, DWORD *pStatus)
292 {
293 FIXME("(%p,%p): stub\n", iface, pStatus);
294 return E_NOTIMPL;
295 }
296
297 static HRESULT WINAPI BitmapDecoderInfo_GetAuthor(IWICBitmapDecoderInfo *iface, UINT cchAuthor,
298 WCHAR *wzAuthor, UINT *pcchActual)
299 {
300 BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
301
302 TRACE("(%p,%u,%p,%p)\n", iface, cchAuthor, wzAuthor, pcchActual);
303
304 return ComponentInfo_GetStringValue(This->classkey, author_valuename,
305 cchAuthor, wzAuthor, pcchActual);
306 }
307
308 static HRESULT WINAPI BitmapDecoderInfo_GetVendorGUID(IWICBitmapDecoderInfo *iface, GUID *pguidVendor)
309 {
310 BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
311
312 TRACE("(%p,%p)\n", iface, pguidVendor);
313
314 return ComponentInfo_GetGUIDValue(This->classkey, vendor_valuename, pguidVendor);
315 }
316
317 static HRESULT WINAPI BitmapDecoderInfo_GetVersion(IWICBitmapDecoderInfo *iface, UINT cchVersion,
318 WCHAR *wzVersion, UINT *pcchActual)
319 {
320 BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
321
322 TRACE("(%p,%u,%p,%p)\n", iface, cchVersion, wzVersion, pcchActual);
323
324 return ComponentInfo_GetStringValue(This->classkey, version_valuename,
325 cchVersion, wzVersion, pcchActual);
326 }
327
328 static HRESULT WINAPI BitmapDecoderInfo_GetSpecVersion(IWICBitmapDecoderInfo *iface, UINT cchSpecVersion,
329 WCHAR *wzSpecVersion, UINT *pcchActual)
330 {
331 BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
332
333 TRACE("(%p,%u,%p,%p)\n", iface, cchSpecVersion, wzSpecVersion, pcchActual);
334
335 return ComponentInfo_GetStringValue(This->classkey, specversion_valuename,
336 cchSpecVersion, wzSpecVersion, pcchActual);
337 }
338
339 static HRESULT WINAPI BitmapDecoderInfo_GetFriendlyName(IWICBitmapDecoderInfo *iface, UINT cchFriendlyName,
340 WCHAR *wzFriendlyName, UINT *pcchActual)
341 {
342 BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
343
344 TRACE("(%p,%u,%p,%p)\n", iface, cchFriendlyName, wzFriendlyName, pcchActual);
345
346 return ComponentInfo_GetStringValue(This->classkey, friendlyname_valuename,
347 cchFriendlyName, wzFriendlyName, pcchActual);
348 }
349
350 static HRESULT WINAPI BitmapDecoderInfo_GetContainerFormat(IWICBitmapDecoderInfo *iface,
351 GUID *pguidContainerFormat)
352 {
353 BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
354 TRACE("(%p,%p)\n", iface, pguidContainerFormat);
355 return ComponentInfo_GetGUIDValue(This->classkey, containerformat_valuename, pguidContainerFormat);
356 }
357
358 static HRESULT WINAPI BitmapDecoderInfo_GetPixelFormats(IWICBitmapDecoderInfo *iface,
359 UINT cFormats, GUID *pguidPixelFormats, UINT *pcActual)
360 {
361 BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
362 TRACE("(%p,%u,%p,%p)\n", iface, cFormats, pguidPixelFormats, pcActual);
363 return ComponentInfo_GetGuidList(This->classkey, formats_keyname, cFormats, pguidPixelFormats, pcActual);
364 }
365
366 static HRESULT WINAPI BitmapDecoderInfo_GetColorManagementVersion(IWICBitmapDecoderInfo *iface,
367 UINT cchColorManagementVersion, WCHAR *wzColorManagementVersion, UINT *pcchActual)
368 {
369 FIXME("(%p,%u,%p,%p): stub\n", iface, cchColorManagementVersion, wzColorManagementVersion, pcchActual);
370 return E_NOTIMPL;
371 }
372
373 static HRESULT WINAPI BitmapDecoderInfo_GetDeviceManufacturer(IWICBitmapDecoderInfo *iface,
374 UINT cchDeviceManufacturer, WCHAR *wzDeviceManufacturer, UINT *pcchActual)
375 {
376 FIXME("(%p,%u,%p,%p): stub\n", iface, cchDeviceManufacturer, wzDeviceManufacturer, pcchActual);
377 return E_NOTIMPL;
378 }
379
380 static HRESULT WINAPI BitmapDecoderInfo_GetDeviceModels(IWICBitmapDecoderInfo *iface,
381 UINT cchDeviceModels, WCHAR *wzDeviceModels, UINT *pcchActual)
382 {
383 FIXME("(%p,%u,%p,%p): stub\n", iface, cchDeviceModels, wzDeviceModels, pcchActual);
384 return E_NOTIMPL;
385 }
386
387 static HRESULT WINAPI BitmapDecoderInfo_GetMimeTypes(IWICBitmapDecoderInfo *iface,
388 UINT cchMimeTypes, WCHAR *wzMimeTypes, UINT *pcchActual)
389 {
390 BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
391
392 TRACE("(%p,%u,%p,%p)\n", iface, cchMimeTypes, wzMimeTypes, pcchActual);
393
394 return ComponentInfo_GetStringValue(This->classkey, mimetypes_valuename,
395 cchMimeTypes, wzMimeTypes, pcchActual);
396 }
397
398 static HRESULT WINAPI BitmapDecoderInfo_GetFileExtensions(IWICBitmapDecoderInfo *iface,
399 UINT cchFileExtensions, WCHAR *wzFileExtensions, UINT *pcchActual)
400 {
401 BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
402
403 TRACE("(%p,%u,%p,%p)\n", iface, cchFileExtensions, wzFileExtensions, pcchActual);
404
405 return ComponentInfo_GetStringValue(This->classkey, fileextensions_valuename,
406 cchFileExtensions, wzFileExtensions, pcchActual);
407 }
408
409 static HRESULT WINAPI BitmapDecoderInfo_DoesSupportAnimation(IWICBitmapDecoderInfo *iface,
410 BOOL *pfSupportAnimation)
411 {
412 FIXME("(%p,%p): stub\n", iface, pfSupportAnimation);
413 return E_NOTIMPL;
414 }
415
416 static HRESULT WINAPI BitmapDecoderInfo_DoesSupportChromaKey(IWICBitmapDecoderInfo *iface,
417 BOOL *pfSupportChromaKey)
418 {
419 FIXME("(%p,%p): stub\n", iface, pfSupportChromaKey);
420 return E_NOTIMPL;
421 }
422
423 static HRESULT WINAPI BitmapDecoderInfo_DoesSupportLossless(IWICBitmapDecoderInfo *iface,
424 BOOL *pfSupportLossless)
425 {
426 FIXME("(%p,%p): stub\n", iface, pfSupportLossless);
427 return E_NOTIMPL;
428 }
429
430 static HRESULT WINAPI BitmapDecoderInfo_DoesSupportMultiframe(IWICBitmapDecoderInfo *iface,
431 BOOL *pfSupportMultiframe)
432 {
433 FIXME("(%p,%p): stub\n", iface, pfSupportMultiframe);
434 return E_NOTIMPL;
435 }
436
437 static HRESULT WINAPI BitmapDecoderInfo_MatchesMimeType(IWICBitmapDecoderInfo *iface,
438 LPCWSTR wzMimeType, BOOL *pfMatches)
439 {
440 FIXME("(%p,%s,%p): stub\n", iface, debugstr_w(wzMimeType), pfMatches);
441 return E_NOTIMPL;
442 }
443
444 static HRESULT WINAPI BitmapDecoderInfo_GetPatterns(IWICBitmapDecoderInfo *iface,
445 UINT cbSizePatterns, WICBitmapPattern *pPatterns, UINT *pcPatterns, UINT *pcbPatternsActual)
446 {
447 BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
448 UINT pattern_count=0, patterns_size=0;
449 WCHAR subkeyname[11];
450 LONG res;
451 HKEY patternskey, patternkey;
452 static const WCHAR uintformatW[] = {'%','u',0};
453 static const WCHAR patternsW[] = {'P','a','t','t','e','r','n','s',0};
454 static const WCHAR positionW[] = {'P','o','s','i','t','i','o','n',0};
455 static const WCHAR lengthW[] = {'L','e','n','g','t','h',0};
456 static const WCHAR patternW[] = {'P','a','t','t','e','r','n',0};
457 static const WCHAR maskW[] = {'M','a','s','k',0};
458 static const WCHAR endofstreamW[] = {'E','n','d','O','f','S','t','r','e','a','m',0};
459 HRESULT hr=S_OK;
460 UINT i;
461 BYTE *bPatterns=(BYTE*)pPatterns;
462 DWORD length, valuesize;
463
464 TRACE("(%p,%i,%p,%p,%p)\n", iface, cbSizePatterns, pPatterns, pcPatterns, pcbPatternsActual);
465
466 res = RegOpenKeyExW(This->classkey, patternsW, 0, KEY_READ, &patternskey);
467 if (res != ERROR_SUCCESS) return HRESULT_FROM_WIN32(res);
468
469 res = RegQueryInfoKeyW(patternskey, NULL, NULL, NULL, &pattern_count, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
470 if (res == ERROR_SUCCESS)
471 {
472 patterns_size = pattern_count * sizeof(WICBitmapPattern);
473
474 for (i=0; i<pattern_count; i++)
475 {
476 snprintfW(subkeyname, 11, uintformatW, i);
477 res = RegOpenKeyExW(patternskey, subkeyname, 0, KEY_READ, &patternkey);
478 if (res == ERROR_SUCCESS)
479 {
480 valuesize = sizeof(ULONG);
481 res = RegGetValueW(patternkey, NULL, lengthW, RRF_RT_DWORD, NULL,
482 &length, &valuesize);
483 patterns_size += length*2;
484
485 if ((cbSizePatterns >= patterns_size) && (res == ERROR_SUCCESS))
486 {
487 pPatterns[i].Length = length;
488
489 pPatterns[i].EndOfStream = 0;
490 valuesize = sizeof(BOOL);
491 RegGetValueW(patternkey, NULL, endofstreamW, RRF_RT_DWORD, NULL,
492 &pPatterns[i].EndOfStream, &valuesize);
493
494 pPatterns[i].Position.QuadPart = 0;
495 valuesize = sizeof(ULARGE_INTEGER);
496 res = RegGetValueW(patternkey, NULL, positionW, RRF_RT_DWORD|RRF_RT_QWORD, NULL,
497 &pPatterns[i].Position, &valuesize);
498
499 if (res == ERROR_SUCCESS)
500 {
501 pPatterns[i].Pattern = bPatterns+patterns_size-length*2;
502 valuesize = length;
503 res = RegGetValueW(patternkey, NULL, patternW, RRF_RT_REG_BINARY, NULL,
504 pPatterns[i].Pattern, &valuesize);
505 }
506
507 if (res == ERROR_SUCCESS)
508 {
509 pPatterns[i].Mask = bPatterns+patterns_size-length;
510 valuesize = length;
511 res = RegGetValueW(patternkey, NULL, maskW, RRF_RT_REG_BINARY, NULL,
512 pPatterns[i].Mask, &valuesize);
513 }
514 }
515
516 RegCloseKey(patternkey);
517 }
518 if (res != ERROR_SUCCESS)
519 {
520 hr = HRESULT_FROM_WIN32(res);
521 break;
522 }
523 }
524 }
525 else hr = HRESULT_FROM_WIN32(res);
526
527 RegCloseKey(patternskey);
528
529 if (hr == S_OK)
530 {
531 *pcPatterns = pattern_count;
532 *pcbPatternsActual = patterns_size;
533 if (pPatterns && cbSizePatterns < patterns_size)
534 hr = WINCODEC_ERR_INSUFFICIENTBUFFER;
535 }
536
537 return hr;
538 }
539
540 static HRESULT WINAPI BitmapDecoderInfo_MatchesPattern(IWICBitmapDecoderInfo *iface,
541 IStream *pIStream, BOOL *pfMatches)
542 {
543 WICBitmapPattern *patterns;
544 UINT pattern_count=0, patterns_size=0;
545 HRESULT hr;
546 UINT i;
547 ULONG pos;
548 BYTE *data=NULL;
549 ULONG datasize=0;
550 ULONG bytesread;
551 LARGE_INTEGER seekpos;
552
553 TRACE("(%p,%p,%p)\n", iface, pIStream, pfMatches);
554
555 hr = BitmapDecoderInfo_GetPatterns(iface, 0, NULL, &pattern_count, &patterns_size);
556 if (FAILED(hr)) return hr;
557
558 patterns = HeapAlloc(GetProcessHeap(), 0, patterns_size);
559 if (!patterns) return E_OUTOFMEMORY;
560
561 hr = BitmapDecoderInfo_GetPatterns(iface, patterns_size, patterns, &pattern_count, &patterns_size);
562 if (FAILED(hr)) goto end;
563
564 for (i=0; i<pattern_count; i++)
565 {
566 if (datasize < patterns[i].Length)
567 {
568 HeapFree(GetProcessHeap(), 0, data);
569 datasize = patterns[i].Length;
570 data = HeapAlloc(GetProcessHeap(), 0, patterns[i].Length);
571 if (!data)
572 {
573 hr = E_OUTOFMEMORY;
574 break;
575 }
576 }
577
578 if (patterns[i].EndOfStream)
579 seekpos.QuadPart = -patterns[i].Position.QuadPart;
580 else
581 seekpos.QuadPart = patterns[i].Position.QuadPart;
582 hr = IStream_Seek(pIStream, seekpos, patterns[i].EndOfStream ? STREAM_SEEK_END : STREAM_SEEK_SET, NULL);
583 if (hr == STG_E_INVALIDFUNCTION) continue; /* before start of stream */
584 if (FAILED(hr)) break;
585
586 hr = IStream_Read(pIStream, data, patterns[i].Length, &bytesread);
587 if (hr == S_FALSE || (hr == S_OK && bytesread != patterns[i].Length)) /* past end of stream */
588 continue;
589 if (FAILED(hr)) break;
590
591 for (pos=0; pos<patterns[i].Length; pos++)
592 {
593 if ((data[pos] & patterns[i].Mask[pos]) != patterns[i].Pattern[pos])
594 break;
595 }
596 if (pos == patterns[i].Length) /* matches pattern */
597 {
598 hr = S_OK;
599 *pfMatches = TRUE;
600 break;
601 }
602 }
603
604 if (i == pattern_count) /* does not match any pattern */
605 {
606 hr = S_OK;
607 *pfMatches = FALSE;
608 }
609
610 end:
611 HeapFree(GetProcessHeap(), 0, patterns);
612 HeapFree(GetProcessHeap(), 0, data);
613
614 return hr;
615 }
616
617 static HRESULT WINAPI BitmapDecoderInfo_CreateInstance(IWICBitmapDecoderInfo *iface,
618 IWICBitmapDecoder **ppIBitmapDecoder)
619 {
620 BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface);
621
622 TRACE("(%p,%p)\n", iface, ppIBitmapDecoder);
623
624 return create_instance(&This->clsid, &IID_IWICBitmapDecoder, (void**)ppIBitmapDecoder);
625 }
626
627 static const IWICBitmapDecoderInfoVtbl BitmapDecoderInfo_Vtbl = {
628 BitmapDecoderInfo_QueryInterface,
629 BitmapDecoderInfo_AddRef,
630 BitmapDecoderInfo_Release,
631 BitmapDecoderInfo_GetComponentType,
632 BitmapDecoderInfo_GetCLSID,
633 BitmapDecoderInfo_GetSigningStatus,
634 BitmapDecoderInfo_GetAuthor,
635 BitmapDecoderInfo_GetVendorGUID,
636 BitmapDecoderInfo_GetVersion,
637 BitmapDecoderInfo_GetSpecVersion,
638 BitmapDecoderInfo_GetFriendlyName,
639 BitmapDecoderInfo_GetContainerFormat,
640 BitmapDecoderInfo_GetPixelFormats,
641 BitmapDecoderInfo_GetColorManagementVersion,
642 BitmapDecoderInfo_GetDeviceManufacturer,
643 BitmapDecoderInfo_GetDeviceModels,
644 BitmapDecoderInfo_GetMimeTypes,
645 BitmapDecoderInfo_GetFileExtensions,
646 BitmapDecoderInfo_DoesSupportAnimation,
647 BitmapDecoderInfo_DoesSupportChromaKey,
648 BitmapDecoderInfo_DoesSupportLossless,
649 BitmapDecoderInfo_DoesSupportMultiframe,
650 BitmapDecoderInfo_MatchesMimeType,
651 BitmapDecoderInfo_GetPatterns,
652 BitmapDecoderInfo_MatchesPattern,
653 BitmapDecoderInfo_CreateInstance
654 };
655
656 static HRESULT BitmapDecoderInfo_Constructor(HKEY classkey, REFCLSID clsid, IWICComponentInfo **ppIInfo)
657 {
658 BitmapDecoderInfo *This;
659
660 This = HeapAlloc(GetProcessHeap(), 0, sizeof(BitmapDecoderInfo));
661 if (!This)
662 {
663 RegCloseKey(classkey);
664 return E_OUTOFMEMORY;
665 }
666
667 This->IWICBitmapDecoderInfo_iface.lpVtbl = &BitmapDecoderInfo_Vtbl;
668 This->ref = 1;
669 This->classkey = classkey;
670 memcpy(&This->clsid, clsid, sizeof(CLSID));
671
672 *ppIInfo = (IWICComponentInfo *)&This->IWICBitmapDecoderInfo_iface;
673 return S_OK;
674 }
675
676 typedef struct {
677 IWICBitmapEncoderInfo IWICBitmapEncoderInfo_iface;
678 LONG ref;
679 HKEY classkey;
680 CLSID clsid;
681 } BitmapEncoderInfo;
682
683 static inline BitmapEncoderInfo *impl_from_IWICBitmapEncoderInfo(IWICBitmapEncoderInfo *iface)
684 {
685 return CONTAINING_RECORD(iface, BitmapEncoderInfo, IWICBitmapEncoderInfo_iface);
686 }
687
688 static HRESULT WINAPI BitmapEncoderInfo_QueryInterface(IWICBitmapEncoderInfo *iface, REFIID iid,
689 void **ppv)
690 {
691 BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
692 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
693
694 if (!ppv) return E_INVALIDARG;
695
696 if (IsEqualIID(&IID_IUnknown, iid) ||
697 IsEqualIID(&IID_IWICComponentInfo, iid) ||
698 IsEqualIID(&IID_IWICBitmapCodecInfo, iid) ||
699 IsEqualIID(&IID_IWICBitmapEncoderInfo ,iid))
700 {
701 *ppv = &This->IWICBitmapEncoderInfo_iface;
702 }
703 else
704 {
705 *ppv = NULL;
706 return E_NOINTERFACE;
707 }
708
709 IUnknown_AddRef((IUnknown*)*ppv);
710 return S_OK;
711 }
712
713 static ULONG WINAPI BitmapEncoderInfo_AddRef(IWICBitmapEncoderInfo *iface)
714 {
715 BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
716 ULONG ref = InterlockedIncrement(&This->ref);
717
718 TRACE("(%p) refcount=%u\n", iface, ref);
719
720 return ref;
721 }
722
723 static ULONG WINAPI BitmapEncoderInfo_Release(IWICBitmapEncoderInfo *iface)
724 {
725 BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
726 ULONG ref = InterlockedDecrement(&This->ref);
727
728 TRACE("(%p) refcount=%u\n", iface, ref);
729
730 if (ref == 0)
731 {
732 RegCloseKey(This->classkey);
733 HeapFree(GetProcessHeap(), 0, This);
734 }
735
736 return ref;
737 }
738
739 static HRESULT WINAPI BitmapEncoderInfo_GetComponentType(IWICBitmapEncoderInfo *iface,
740 WICComponentType *pType)
741 {
742 TRACE("(%p,%p)\n", iface, pType);
743 if (!pType) return E_INVALIDARG;
744 *pType = WICEncoder;
745 return S_OK;
746 }
747
748 static HRESULT WINAPI BitmapEncoderInfo_GetCLSID(IWICBitmapEncoderInfo *iface, CLSID *pclsid)
749 {
750 BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
751 TRACE("(%p,%p)\n", iface, pclsid);
752
753 if (!pclsid)
754 return E_INVALIDARG;
755
756 memcpy(pclsid, &This->clsid, sizeof(CLSID));
757
758 return S_OK;
759 }
760
761 static HRESULT WINAPI BitmapEncoderInfo_GetSigningStatus(IWICBitmapEncoderInfo *iface, DWORD *pStatus)
762 {
763 FIXME("(%p,%p): stub\n", iface, pStatus);
764 return E_NOTIMPL;
765 }
766
767 static HRESULT WINAPI BitmapEncoderInfo_GetAuthor(IWICBitmapEncoderInfo *iface, UINT cchAuthor,
768 WCHAR *wzAuthor, UINT *pcchActual)
769 {
770 BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
771
772 TRACE("(%p,%u,%p,%p)\n", iface, cchAuthor, wzAuthor, pcchActual);
773
774 return ComponentInfo_GetStringValue(This->classkey, author_valuename,
775 cchAuthor, wzAuthor, pcchActual);
776 }
777
778 static HRESULT WINAPI BitmapEncoderInfo_GetVendorGUID(IWICBitmapEncoderInfo *iface, GUID *pguidVendor)
779 {
780 BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
781
782 TRACE("(%p,%p)\n", iface, pguidVendor);
783
784 return ComponentInfo_GetGUIDValue(This->classkey, vendor_valuename, pguidVendor);
785 }
786
787 static HRESULT WINAPI BitmapEncoderInfo_GetVersion(IWICBitmapEncoderInfo *iface, UINT cchVersion,
788 WCHAR *wzVersion, UINT *pcchActual)
789 {
790 BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
791
792 TRACE("(%p,%u,%p,%p)\n", iface, cchVersion, wzVersion, pcchActual);
793
794 return ComponentInfo_GetStringValue(This->classkey, version_valuename,
795 cchVersion, wzVersion, pcchActual);
796 }
797
798 static HRESULT WINAPI BitmapEncoderInfo_GetSpecVersion(IWICBitmapEncoderInfo *iface, UINT cchSpecVersion,
799 WCHAR *wzSpecVersion, UINT *pcchActual)
800 {
801 BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
802
803 TRACE("(%p,%u,%p,%p)\n", iface, cchSpecVersion, wzSpecVersion, pcchActual);
804
805 return ComponentInfo_GetStringValue(This->classkey, specversion_valuename,
806 cchSpecVersion, wzSpecVersion, pcchActual);
807 }
808
809 static HRESULT WINAPI BitmapEncoderInfo_GetFriendlyName(IWICBitmapEncoderInfo *iface, UINT cchFriendlyName,
810 WCHAR *wzFriendlyName, UINT *pcchActual)
811 {
812 BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
813
814 TRACE("(%p,%u,%p,%p)\n", iface, cchFriendlyName, wzFriendlyName, pcchActual);
815
816 return ComponentInfo_GetStringValue(This->classkey, friendlyname_valuename,
817 cchFriendlyName, wzFriendlyName, pcchActual);
818 }
819
820 static HRESULT WINAPI BitmapEncoderInfo_GetContainerFormat(IWICBitmapEncoderInfo *iface,
821 GUID *pguidContainerFormat)
822 {
823 BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
824 TRACE("(%p,%p)\n", iface, pguidContainerFormat);
825 return ComponentInfo_GetGUIDValue(This->classkey, containerformat_valuename, pguidContainerFormat);
826 }
827
828 static HRESULT WINAPI BitmapEncoderInfo_GetPixelFormats(IWICBitmapEncoderInfo *iface,
829 UINT cFormats, GUID *pguidPixelFormats, UINT *pcActual)
830 {
831 BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
832 TRACE("(%p,%u,%p,%p)\n", iface, cFormats, pguidPixelFormats, pcActual);
833 return ComponentInfo_GetGuidList(This->classkey, formats_keyname, cFormats, pguidPixelFormats, pcActual);
834 }
835
836 static HRESULT WINAPI BitmapEncoderInfo_GetColorManagementVersion(IWICBitmapEncoderInfo *iface,
837 UINT cchColorManagementVersion, WCHAR *wzColorManagementVersion, UINT *pcchActual)
838 {
839 FIXME("(%p,%u,%p,%p): stub\n", iface, cchColorManagementVersion, wzColorManagementVersion, pcchActual);
840 return E_NOTIMPL;
841 }
842
843 static HRESULT WINAPI BitmapEncoderInfo_GetDeviceManufacturer(IWICBitmapEncoderInfo *iface,
844 UINT cchDeviceManufacturer, WCHAR *wzDeviceManufacturer, UINT *pcchActual)
845 {
846 FIXME("(%p,%u,%p,%p): stub\n", iface, cchDeviceManufacturer, wzDeviceManufacturer, pcchActual);
847 return E_NOTIMPL;
848 }
849
850 static HRESULT WINAPI BitmapEncoderInfo_GetDeviceModels(IWICBitmapEncoderInfo *iface,
851 UINT cchDeviceModels, WCHAR *wzDeviceModels, UINT *pcchActual)
852 {
853 FIXME("(%p,%u,%p,%p): stub\n", iface, cchDeviceModels, wzDeviceModels, pcchActual);
854 return E_NOTIMPL;
855 }
856
857 static HRESULT WINAPI BitmapEncoderInfo_GetMimeTypes(IWICBitmapEncoderInfo *iface,
858 UINT cchMimeTypes, WCHAR *wzMimeTypes, UINT *pcchActual)
859 {
860 BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
861
862 TRACE("(%p,%u,%p,%p)\n", iface, cchMimeTypes, wzMimeTypes, pcchActual);
863
864 return ComponentInfo_GetStringValue(This->classkey, mimetypes_valuename,
865 cchMimeTypes, wzMimeTypes, pcchActual);
866 }
867
868 static HRESULT WINAPI BitmapEncoderInfo_GetFileExtensions(IWICBitmapEncoderInfo *iface,
869 UINT cchFileExtensions, WCHAR *wzFileExtensions, UINT *pcchActual)
870 {
871 BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
872
873 TRACE("(%p,%u,%p,%p)\n", iface, cchFileExtensions, wzFileExtensions, pcchActual);
874
875 return ComponentInfo_GetStringValue(This->classkey, fileextensions_valuename,
876 cchFileExtensions, wzFileExtensions, pcchActual);
877 }
878
879 static HRESULT WINAPI BitmapEncoderInfo_DoesSupportAnimation(IWICBitmapEncoderInfo *iface,
880 BOOL *pfSupportAnimation)
881 {
882 FIXME("(%p,%p): stub\n", iface, pfSupportAnimation);
883 return E_NOTIMPL;
884 }
885
886 static HRESULT WINAPI BitmapEncoderInfo_DoesSupportChromaKey(IWICBitmapEncoderInfo *iface,
887 BOOL *pfSupportChromaKey)
888 {
889 FIXME("(%p,%p): stub\n", iface, pfSupportChromaKey);
890 return E_NOTIMPL;
891 }
892
893 static HRESULT WINAPI BitmapEncoderInfo_DoesSupportLossless(IWICBitmapEncoderInfo *iface,
894 BOOL *pfSupportLossless)
895 {
896 FIXME("(%p,%p): stub\n", iface, pfSupportLossless);
897 return E_NOTIMPL;
898 }
899
900 static HRESULT WINAPI BitmapEncoderInfo_DoesSupportMultiframe(IWICBitmapEncoderInfo *iface,
901 BOOL *pfSupportMultiframe)
902 {
903 FIXME("(%p,%p): stub\n", iface, pfSupportMultiframe);
904 return E_NOTIMPL;
905 }
906
907 static HRESULT WINAPI BitmapEncoderInfo_MatchesMimeType(IWICBitmapEncoderInfo *iface,
908 LPCWSTR wzMimeType, BOOL *pfMatches)
909 {
910 FIXME("(%p,%s,%p): stub\n", iface, debugstr_w(wzMimeType), pfMatches);
911 return E_NOTIMPL;
912 }
913
914 static HRESULT WINAPI BitmapEncoderInfo_CreateInstance(IWICBitmapEncoderInfo *iface,
915 IWICBitmapEncoder **ppIBitmapEncoder)
916 {
917 BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface);
918
919 TRACE("(%p,%p)\n", iface, ppIBitmapEncoder);
920
921 return create_instance(&This->clsid, &IID_IWICBitmapEncoder, (void**)ppIBitmapEncoder);
922 }
923
924 static const IWICBitmapEncoderInfoVtbl BitmapEncoderInfo_Vtbl = {
925 BitmapEncoderInfo_QueryInterface,
926 BitmapEncoderInfo_AddRef,
927 BitmapEncoderInfo_Release,
928 BitmapEncoderInfo_GetComponentType,
929 BitmapEncoderInfo_GetCLSID,
930 BitmapEncoderInfo_GetSigningStatus,
931 BitmapEncoderInfo_GetAuthor,
932 BitmapEncoderInfo_GetVendorGUID,
933 BitmapEncoderInfo_GetVersion,
934 BitmapEncoderInfo_GetSpecVersion,
935 BitmapEncoderInfo_GetFriendlyName,
936 BitmapEncoderInfo_GetContainerFormat,
937 BitmapEncoderInfo_GetPixelFormats,
938 BitmapEncoderInfo_GetColorManagementVersion,
939 BitmapEncoderInfo_GetDeviceManufacturer,
940 BitmapEncoderInfo_GetDeviceModels,
941 BitmapEncoderInfo_GetMimeTypes,
942 BitmapEncoderInfo_GetFileExtensions,
943 BitmapEncoderInfo_DoesSupportAnimation,
944 BitmapEncoderInfo_DoesSupportChromaKey,
945 BitmapEncoderInfo_DoesSupportLossless,
946 BitmapEncoderInfo_DoesSupportMultiframe,
947 BitmapEncoderInfo_MatchesMimeType,
948 BitmapEncoderInfo_CreateInstance
949 };
950
951 static HRESULT BitmapEncoderInfo_Constructor(HKEY classkey, REFCLSID clsid, IWICComponentInfo **ppIInfo)
952 {
953 BitmapEncoderInfo *This;
954
955 This = HeapAlloc(GetProcessHeap(), 0, sizeof(BitmapEncoderInfo));
956 if (!This)
957 {
958 RegCloseKey(classkey);
959 return E_OUTOFMEMORY;
960 }
961
962 This->IWICBitmapEncoderInfo_iface.lpVtbl = &BitmapEncoderInfo_Vtbl;
963 This->ref = 1;
964 This->classkey = classkey;
965 memcpy(&This->clsid, clsid, sizeof(CLSID));
966
967 *ppIInfo = (IWICComponentInfo *)&This->IWICBitmapEncoderInfo_iface;
968 return S_OK;
969 }
970
971 typedef struct {
972 IWICFormatConverterInfo IWICFormatConverterInfo_iface;
973 LONG ref;
974 HKEY classkey;
975 CLSID clsid;
976 } FormatConverterInfo;
977
978 static inline FormatConverterInfo *impl_from_IWICFormatConverterInfo(IWICFormatConverterInfo *iface)
979 {
980 return CONTAINING_RECORD(iface, FormatConverterInfo, IWICFormatConverterInfo_iface);
981 }
982
983 static HRESULT WINAPI FormatConverterInfo_QueryInterface(IWICFormatConverterInfo *iface, REFIID iid,
984 void **ppv)
985 {
986 FormatConverterInfo *This = impl_from_IWICFormatConverterInfo(iface);
987 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
988
989 if (!ppv) return E_INVALIDARG;
990
991 if (IsEqualIID(&IID_IUnknown, iid) ||
992 IsEqualIID(&IID_IWICComponentInfo, iid) ||
993 IsEqualIID(&IID_IWICFormatConverterInfo ,iid))
994 {
995 *ppv = &This->IWICFormatConverterInfo_iface;
996 }
997 else
998 {
999 *ppv = NULL;
1000 return E_NOINTERFACE;
1001 }
1002
1003 IUnknown_AddRef((IUnknown*)*ppv);
1004 return S_OK;
1005 }
1006
1007 static ULONG WINAPI FormatConverterInfo_AddRef(IWICFormatConverterInfo *iface)
1008 {
1009 FormatConverterInfo *This = impl_from_IWICFormatConverterInfo(iface);
1010 ULONG ref = InterlockedIncrement(&This->ref);
1011
1012 TRACE("(%p) refcount=%u\n", iface, ref);
1013
1014 return ref;
1015 }
1016
1017 static ULONG WINAPI FormatConverterInfo_Release(IWICFormatConverterInfo *iface)
1018 {
1019 FormatConverterInfo *This = impl_from_IWICFormatConverterInfo(iface);
1020 ULONG ref = InterlockedDecrement(&This->ref);
1021
1022 TRACE("(%p) refcount=%u\n", iface, ref);
1023
1024 if (ref == 0)
1025 {
1026 RegCloseKey(This->classkey);
1027 HeapFree(GetProcessHeap(), 0, This);
1028 }
1029
1030 return ref;
1031 }
1032
1033 static HRESULT WINAPI FormatConverterInfo_GetComponentType(IWICFormatConverterInfo *iface,
1034 WICComponentType *pType)
1035 {
1036 TRACE("(%p,%p)\n", iface, pType);
1037 if (!pType) return E_INVALIDARG;
1038 *pType = WICPixelFormatConverter;
1039 return S_OK;
1040 }
1041
1042 static HRESULT WINAPI FormatConverterInfo_GetCLSID(IWICFormatConverterInfo *iface, CLSID *pclsid)
1043 {
1044 FormatConverterInfo *This = impl_from_IWICFormatConverterInfo(iface);
1045 TRACE("(%p,%p)\n", iface, pclsid);
1046
1047 if (!pclsid)
1048 return E_INVALIDARG;
1049
1050 memcpy(pclsid, &This->clsid, sizeof(CLSID));
1051
1052 return S_OK;
1053 }
1054
1055 static HRESULT WINAPI FormatConverterInfo_GetSigningStatus(IWICFormatConverterInfo *iface, DWORD *pStatus)
1056 {
1057 FIXME("(%p,%p): stub\n", iface, pStatus);
1058 return E_NOTIMPL;
1059 }
1060
1061 static HRESULT WINAPI FormatConverterInfo_GetAuthor(IWICFormatConverterInfo *iface, UINT cchAuthor,
1062 WCHAR *wzAuthor, UINT *pcchActual)
1063 {
1064 FormatConverterInfo *This = impl_from_IWICFormatConverterInfo(iface);
1065
1066 TRACE("(%p,%u,%p,%p)\n", iface, cchAuthor, wzAuthor, pcchActual);
1067
1068 return ComponentInfo_GetStringValue(This->classkey, author_valuename,
1069 cchAuthor, wzAuthor, pcchActual);
1070 }
1071
1072 static HRESULT WINAPI FormatConverterInfo_GetVendorGUID(IWICFormatConverterInfo *iface, GUID *pguidVendor)
1073 {
1074 FormatConverterInfo *This = impl_from_IWICFormatConverterInfo(iface);
1075
1076 TRACE("(%p,%p)\n", iface, pguidVendor);
1077
1078 return ComponentInfo_GetGUIDValue(This->classkey, vendor_valuename, pguidVendor);
1079 }
1080
1081 static HRESULT WINAPI FormatConverterInfo_GetVersion(IWICFormatConverterInfo *iface, UINT cchVersion,
1082 WCHAR *wzVersion, UINT *pcchActual)
1083 {
1084 FormatConverterInfo *This = impl_from_IWICFormatConverterInfo(iface);
1085
1086 TRACE("(%p,%u,%p,%p)\n", iface, cchVersion, wzVersion, pcchActual);
1087
1088 return ComponentInfo_GetStringValue(This->classkey, version_valuename,
1089 cchVersion, wzVersion, pcchActual);
1090 }
1091
1092 static HRESULT WINAPI FormatConverterInfo_GetSpecVersion(IWICFormatConverterInfo *iface, UINT cchSpecVersion,
1093 WCHAR *wzSpecVersion, UINT *pcchActual)
1094 {
1095 FormatConverterInfo *This = impl_from_IWICFormatConverterInfo(iface);
1096
1097 TRACE("(%p,%u,%p,%p)\n", iface, cchSpecVersion, wzSpecVersion, pcchActual);
1098
1099 return ComponentInfo_GetStringValue(This->classkey, specversion_valuename,
1100 cchSpecVersion, wzSpecVersion, pcchActual);
1101 }
1102
1103 static HRESULT WINAPI FormatConverterInfo_GetFriendlyName(IWICFormatConverterInfo *iface, UINT cchFriendlyName,
1104 WCHAR *wzFriendlyName, UINT *pcchActual)
1105 {
1106 FormatConverterInfo *This = impl_from_IWICFormatConverterInfo(iface);
1107
1108 TRACE("(%p,%u,%p,%p)\n", iface, cchFriendlyName, wzFriendlyName, pcchActual);
1109
1110 return ComponentInfo_GetStringValue(This->classkey, friendlyname_valuename,
1111 cchFriendlyName, wzFriendlyName, pcchActual);
1112 }
1113
1114 static HRESULT WINAPI FormatConverterInfo_GetPixelFormats(IWICFormatConverterInfo *iface,
1115 UINT cFormats, GUID *pguidPixelFormats, UINT *pcActual)
1116 {
1117 FIXME("(%p,%u,%p,%p): stub\n", iface, cFormats, pguidPixelFormats, pcActual);
1118 return E_NOTIMPL;
1119 }
1120
1121 static HRESULT WINAPI FormatConverterInfo_CreateInstance(IWICFormatConverterInfo *iface,
1122 IWICFormatConverter **ppIFormatConverter)
1123 {
1124 FormatConverterInfo *This = impl_from_IWICFormatConverterInfo(iface);
1125
1126 TRACE("(%p,%p)\n", iface, ppIFormatConverter);
1127
1128 return create_instance(&This->clsid, &IID_IWICFormatConverter,
1129 (void**)ppIFormatConverter);
1130 }
1131
1132 static BOOL ConverterSupportsFormat(IWICFormatConverterInfo *iface, const WCHAR *formatguid)
1133 {
1134 LONG res;
1135 FormatConverterInfo *This = impl_from_IWICFormatConverterInfo(iface);
1136 HKEY formats_key, guid_key;
1137
1138 /* Avoid testing using IWICFormatConverter_GetPixelFormats because that
1139 would be O(n). A registry test should do better. */
1140
1141 res = RegOpenKeyExW(This->classkey, pixelformats_keyname, 0, KEY_READ, &formats_key);
1142 if (res != ERROR_SUCCESS) return FALSE;
1143
1144 res = RegOpenKeyExW(formats_key, formatguid, 0, KEY_READ, &guid_key);
1145 if (res == ERROR_SUCCESS) RegCloseKey(guid_key);
1146
1147 RegCloseKey(formats_key);
1148
1149 return (res == ERROR_SUCCESS);
1150 }
1151
1152 static const IWICFormatConverterInfoVtbl FormatConverterInfo_Vtbl = {
1153 FormatConverterInfo_QueryInterface,
1154 FormatConverterInfo_AddRef,
1155 FormatConverterInfo_Release,
1156 FormatConverterInfo_GetComponentType,
1157 FormatConverterInfo_GetCLSID,
1158 FormatConverterInfo_GetSigningStatus,
1159 FormatConverterInfo_GetAuthor,
1160 FormatConverterInfo_GetVendorGUID,
1161 FormatConverterInfo_GetVersion,
1162 FormatConverterInfo_GetSpecVersion,
1163 FormatConverterInfo_GetFriendlyName,
1164 FormatConverterInfo_GetPixelFormats,
1165 FormatConverterInfo_CreateInstance
1166 };
1167
1168 static HRESULT FormatConverterInfo_Constructor(HKEY classkey, REFCLSID clsid, IWICComponentInfo **ppIInfo)
1169 {
1170 FormatConverterInfo *This;
1171
1172 This = HeapAlloc(GetProcessHeap(), 0, sizeof(FormatConverterInfo));
1173 if (!This)
1174 {
1175 RegCloseKey(classkey);
1176 return E_OUTOFMEMORY;
1177 }
1178
1179 This->IWICFormatConverterInfo_iface.lpVtbl = &FormatConverterInfo_Vtbl;
1180 This->ref = 1;
1181 This->classkey = classkey;
1182 memcpy(&This->clsid, clsid, sizeof(CLSID));
1183
1184 *ppIInfo = (IWICComponentInfo *)&This->IWICFormatConverterInfo_iface;
1185 return S_OK;
1186 }
1187
1188 typedef struct {
1189 IWICPixelFormatInfo2 IWICPixelFormatInfo2_iface;
1190 LONG ref;
1191 HKEY classkey;
1192 CLSID clsid;
1193 } PixelFormatInfo;
1194
1195 static inline PixelFormatInfo *impl_from_IWICPixelFormatInfo2(IWICPixelFormatInfo2 *iface)
1196 {
1197 return CONTAINING_RECORD(iface, PixelFormatInfo, IWICPixelFormatInfo2_iface);
1198 }
1199
1200 static HRESULT WINAPI PixelFormatInfo_QueryInterface(IWICPixelFormatInfo2 *iface, REFIID iid,
1201 void **ppv)
1202 {
1203 PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1204 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
1205
1206 if (!ppv) return E_INVALIDARG;
1207
1208 if (IsEqualIID(&IID_IUnknown, iid) ||
1209 IsEqualIID(&IID_IWICComponentInfo, iid) ||
1210 IsEqualIID(&IID_IWICPixelFormatInfo, iid) ||
1211 IsEqualIID(&IID_IWICPixelFormatInfo2 ,iid))
1212 {
1213 *ppv = &This->IWICPixelFormatInfo2_iface;
1214 }
1215 else
1216 {
1217 *ppv = NULL;
1218 return E_NOINTERFACE;
1219 }
1220
1221 IUnknown_AddRef((IUnknown*)*ppv);
1222 return S_OK;
1223 }
1224
1225 static ULONG WINAPI PixelFormatInfo_AddRef(IWICPixelFormatInfo2 *iface)
1226 {
1227 PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1228 ULONG ref = InterlockedIncrement(&This->ref);
1229
1230 TRACE("(%p) refcount=%u\n", iface, ref);
1231
1232 return ref;
1233 }
1234
1235 static ULONG WINAPI PixelFormatInfo_Release(IWICPixelFormatInfo2 *iface)
1236 {
1237 PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1238 ULONG ref = InterlockedDecrement(&This->ref);
1239
1240 TRACE("(%p) refcount=%u\n", iface, ref);
1241
1242 if (ref == 0)
1243 {
1244 RegCloseKey(This->classkey);
1245 HeapFree(GetProcessHeap(), 0, This);
1246 }
1247
1248 return ref;
1249 }
1250
1251 static HRESULT WINAPI PixelFormatInfo_GetComponentType(IWICPixelFormatInfo2 *iface,
1252 WICComponentType *pType)
1253 {
1254 TRACE("(%p,%p)\n", iface, pType);
1255 if (!pType) return E_INVALIDARG;
1256 *pType = WICPixelFormat;
1257 return S_OK;
1258 }
1259
1260 static HRESULT WINAPI PixelFormatInfo_GetCLSID(IWICPixelFormatInfo2 *iface, CLSID *pclsid)
1261 {
1262 PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1263 TRACE("(%p,%p)\n", iface, pclsid);
1264
1265 if (!pclsid)
1266 return E_INVALIDARG;
1267
1268 memcpy(pclsid, &This->clsid, sizeof(CLSID));
1269
1270 return S_OK;
1271 }
1272
1273 static HRESULT WINAPI PixelFormatInfo_GetSigningStatus(IWICPixelFormatInfo2 *iface, DWORD *pStatus)
1274 {
1275 TRACE("(%p,%p)\n", iface, pStatus);
1276
1277 if (!pStatus)
1278 return E_INVALIDARG;
1279
1280 /* Pixel formats don't require code, so they are considered signed. */
1281 *pStatus = WICComponentSigned;
1282
1283 return S_OK;
1284 }
1285
1286 static HRESULT WINAPI PixelFormatInfo_GetAuthor(IWICPixelFormatInfo2 *iface, UINT cchAuthor,
1287 WCHAR *wzAuthor, UINT *pcchActual)
1288 {
1289 PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1290
1291 TRACE("(%p,%u,%p,%p)\n", iface, cchAuthor, wzAuthor, pcchActual);
1292
1293 return ComponentInfo_GetStringValue(This->classkey, author_valuename,
1294 cchAuthor, wzAuthor, pcchActual);
1295 }
1296
1297 static HRESULT WINAPI PixelFormatInfo_GetVendorGUID(IWICPixelFormatInfo2 *iface, GUID *pguidVendor)
1298 {
1299 PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1300
1301 TRACE("(%p,%p)\n", iface, pguidVendor);
1302
1303 return ComponentInfo_GetGUIDValue(This->classkey, vendor_valuename, pguidVendor);
1304 }
1305
1306 static HRESULT WINAPI PixelFormatInfo_GetVersion(IWICPixelFormatInfo2 *iface, UINT cchVersion,
1307 WCHAR *wzVersion, UINT *pcchActual)
1308 {
1309 PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1310
1311 TRACE("(%p,%u,%p,%p)\n", iface, cchVersion, wzVersion, pcchActual);
1312
1313 return ComponentInfo_GetStringValue(This->classkey, version_valuename,
1314 cchVersion, wzVersion, pcchActual);
1315 }
1316
1317 static HRESULT WINAPI PixelFormatInfo_GetSpecVersion(IWICPixelFormatInfo2 *iface, UINT cchSpecVersion,
1318 WCHAR *wzSpecVersion, UINT *pcchActual)
1319 {
1320 PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1321
1322 TRACE("(%p,%u,%p,%p)\n", iface, cchSpecVersion, wzSpecVersion, pcchActual);
1323
1324 return ComponentInfo_GetStringValue(This->classkey, specversion_valuename,
1325 cchSpecVersion, wzSpecVersion, pcchActual);
1326 }
1327
1328 static HRESULT WINAPI PixelFormatInfo_GetFriendlyName(IWICPixelFormatInfo2 *iface, UINT cchFriendlyName,
1329 WCHAR *wzFriendlyName, UINT *pcchActual)
1330 {
1331 PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1332
1333 TRACE("(%p,%u,%p,%p)\n", iface, cchFriendlyName, wzFriendlyName, pcchActual);
1334
1335 return ComponentInfo_GetStringValue(This->classkey, friendlyname_valuename,
1336 cchFriendlyName, wzFriendlyName, pcchActual);
1337 }
1338
1339 static HRESULT WINAPI PixelFormatInfo_GetFormatGUID(IWICPixelFormatInfo2 *iface,
1340 GUID *pFormat)
1341 {
1342 PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1343 TRACE("(%p,%p)\n", iface, pFormat);
1344
1345 if (!pFormat)
1346 return E_INVALIDARG;
1347
1348 *pFormat = This->clsid;
1349
1350 return S_OK;
1351 }
1352
1353 static HRESULT WINAPI PixelFormatInfo_GetColorContext(IWICPixelFormatInfo2 *iface,
1354 IWICColorContext **ppIColorContext)
1355 {
1356 FIXME("(%p,%p): stub\n", iface, ppIColorContext);
1357 return E_NOTIMPL;
1358 }
1359
1360 static HRESULT WINAPI PixelFormatInfo_GetBitsPerPixel(IWICPixelFormatInfo2 *iface,
1361 UINT *puiBitsPerPixel)
1362 {
1363 PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1364
1365 TRACE("(%p,%p)\n", iface, puiBitsPerPixel);
1366
1367 return ComponentInfo_GetDWORDValue(This->classkey, bitsperpixel_valuename, puiBitsPerPixel);
1368 }
1369
1370 static HRESULT WINAPI PixelFormatInfo_GetChannelCount(IWICPixelFormatInfo2 *iface,
1371 UINT *puiChannelCount)
1372 {
1373 PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1374
1375 TRACE("(%p,%p)\n", iface, puiChannelCount);
1376
1377 return ComponentInfo_GetDWORDValue(This->classkey, channelcount_valuename, puiChannelCount);
1378 }
1379
1380 static HRESULT WINAPI PixelFormatInfo_GetChannelMask(IWICPixelFormatInfo2 *iface,
1381 UINT uiChannelIndex, UINT cbMaskBuffer, BYTE *pbMaskBuffer, UINT *pcbActual)
1382 {
1383 static const WCHAR uintformatW[] = {'%','u',0};
1384 PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1385 UINT channel_count;
1386 HRESULT hr;
1387 LONG ret;
1388 WCHAR valuename[11];
1389 DWORD cbData;
1390
1391 TRACE("(%p,%u,%u,%p,%p)\n", iface, uiChannelIndex, cbMaskBuffer, pbMaskBuffer, pcbActual);
1392
1393 if (!pcbActual)
1394 return E_INVALIDARG;
1395
1396 hr = PixelFormatInfo_GetChannelCount(iface, &channel_count);
1397
1398 if (SUCCEEDED(hr) && uiChannelIndex >= channel_count)
1399 hr = E_INVALIDARG;
1400
1401 if (SUCCEEDED(hr))
1402 {
1403 snprintfW(valuename, 11, uintformatW, uiChannelIndex);
1404
1405 cbData = cbMaskBuffer;
1406
1407 ret = RegGetValueW(This->classkey, channelmasks_keyname, valuename, RRF_RT_REG_BINARY, NULL, pbMaskBuffer, &cbData);
1408
1409 if (ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA)
1410 *pcbActual = cbData;
1411
1412 if (ret == ERROR_MORE_DATA)
1413 hr = E_INVALIDARG;
1414 else
1415 hr = HRESULT_FROM_WIN32(ret);
1416 }
1417
1418 return hr;
1419 }
1420
1421 static HRESULT WINAPI PixelFormatInfo_SupportsTransparency(IWICPixelFormatInfo2 *iface,
1422 BOOL *pfSupportsTransparency)
1423 {
1424 PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1425
1426 TRACE("(%p,%p)\n", iface, pfSupportsTransparency);
1427
1428 return ComponentInfo_GetDWORDValue(This->classkey, supportstransparency_valuename, (DWORD*)pfSupportsTransparency);
1429 }
1430
1431 static HRESULT WINAPI PixelFormatInfo_GetNumericRepresentation(IWICPixelFormatInfo2 *iface,
1432 WICPixelFormatNumericRepresentation *pNumericRepresentation)
1433 {
1434 PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface);
1435
1436 TRACE("(%p,%p)\n", iface, pNumericRepresentation);
1437
1438 return ComponentInfo_GetDWORDValue(This->classkey, numericrepresentation_valuename, pNumericRepresentation);
1439 }
1440
1441 static const IWICPixelFormatInfo2Vtbl PixelFormatInfo_Vtbl = {
1442 PixelFormatInfo_QueryInterface,
1443 PixelFormatInfo_AddRef,
1444 PixelFormatInfo_Release,
1445 PixelFormatInfo_GetComponentType,
1446 PixelFormatInfo_GetCLSID,
1447 PixelFormatInfo_GetSigningStatus,
1448 PixelFormatInfo_GetAuthor,
1449 PixelFormatInfo_GetVendorGUID,
1450 PixelFormatInfo_GetVersion,
1451 PixelFormatInfo_GetSpecVersion,
1452 PixelFormatInfo_GetFriendlyName,
1453 PixelFormatInfo_GetFormatGUID,
1454 PixelFormatInfo_GetColorContext,
1455 PixelFormatInfo_GetBitsPerPixel,
1456 PixelFormatInfo_GetChannelCount,
1457 PixelFormatInfo_GetChannelMask,
1458 PixelFormatInfo_SupportsTransparency,
1459 PixelFormatInfo_GetNumericRepresentation
1460 };
1461
1462 static HRESULT PixelFormatInfo_Constructor(HKEY classkey, REFCLSID clsid, IWICComponentInfo **ppIInfo)
1463 {
1464 PixelFormatInfo *This;
1465
1466 This = HeapAlloc(GetProcessHeap(), 0, sizeof(PixelFormatInfo));
1467 if (!This)
1468 {
1469 RegCloseKey(classkey);
1470 return E_OUTOFMEMORY;
1471 }
1472
1473 This->IWICPixelFormatInfo2_iface.lpVtbl = &PixelFormatInfo_Vtbl;
1474 This->ref = 1;
1475 This->classkey = classkey;
1476 memcpy(&This->clsid, clsid, sizeof(CLSID));
1477
1478 *ppIInfo = (IWICComponentInfo *)&This->IWICPixelFormatInfo2_iface;
1479 return S_OK;
1480 }
1481
1482 typedef struct
1483 {
1484 IWICMetadataReaderInfo IWICMetadataReaderInfo_iface;
1485 LONG ref;
1486 HKEY classkey;
1487 CLSID clsid;
1488 } MetadataReaderInfo;
1489
1490 static inline MetadataReaderInfo *impl_from_IWICMetadataReaderInfo(IWICMetadataReaderInfo *iface)
1491 {
1492 return CONTAINING_RECORD(iface, MetadataReaderInfo, IWICMetadataReaderInfo_iface);
1493 }
1494
1495 static HRESULT WINAPI MetadataReaderInfo_QueryInterface(IWICMetadataReaderInfo *iface,
1496 REFIID riid, void **ppv)
1497 {
1498 MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1499
1500 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(riid), ppv);
1501
1502 if (!ppv) return E_INVALIDARG;
1503
1504 if (IsEqualIID(&IID_IUnknown, riid) ||
1505 IsEqualIID(&IID_IWICComponentInfo, riid) ||
1506 IsEqualIID(&IID_IWICMetadataHandlerInfo, riid) ||
1507 IsEqualIID(&IID_IWICMetadataReaderInfo, riid))
1508 {
1509 *ppv = &This->IWICMetadataReaderInfo_iface;
1510 }
1511 else
1512 {
1513 *ppv = NULL;
1514 return E_NOINTERFACE;
1515 }
1516
1517 IUnknown_AddRef((IUnknown *)*ppv);
1518 return S_OK;
1519 }
1520
1521 static ULONG WINAPI MetadataReaderInfo_AddRef(IWICMetadataReaderInfo *iface)
1522 {
1523 MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1524 ULONG ref = InterlockedIncrement(&This->ref);
1525
1526 TRACE("(%p) refcount=%u\n", iface, ref);
1527 return ref;
1528 }
1529
1530 static ULONG WINAPI MetadataReaderInfo_Release(IWICMetadataReaderInfo *iface)
1531 {
1532 MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1533 ULONG ref = InterlockedDecrement(&This->ref);
1534
1535 TRACE("(%p) refcount=%u\n", iface, ref);
1536
1537 if (!ref)
1538 {
1539 RegCloseKey(This->classkey);
1540 HeapFree(GetProcessHeap(), 0, This);
1541 }
1542 return ref;
1543 }
1544
1545 static HRESULT WINAPI MetadataReaderInfo_GetComponentType(IWICMetadataReaderInfo *iface,
1546 WICComponentType *type)
1547 {
1548 TRACE("(%p,%p)\n", iface, type);
1549
1550 if (!type) return E_INVALIDARG;
1551 *type = WICMetadataReader;
1552 return S_OK;
1553 }
1554
1555 static HRESULT WINAPI MetadataReaderInfo_GetCLSID(IWICMetadataReaderInfo *iface,
1556 CLSID *clsid)
1557 {
1558 MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1559
1560 TRACE("(%p,%p)\n", iface, clsid);
1561
1562 if (!clsid) return E_INVALIDARG;
1563 *clsid = This->clsid;
1564 return S_OK;
1565 }
1566
1567 static HRESULT WINAPI MetadataReaderInfo_GetSigningStatus(IWICMetadataReaderInfo *iface,
1568 DWORD *status)
1569 {
1570 FIXME("(%p,%p): stub\n", iface, status);
1571 return E_NOTIMPL;
1572 }
1573
1574 static HRESULT WINAPI MetadataReaderInfo_GetAuthor(IWICMetadataReaderInfo *iface,
1575 UINT length, WCHAR *author, UINT *actual_length)
1576 {
1577 MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1578
1579 TRACE("(%p,%u,%p,%p)\n", iface, length, author, actual_length);
1580
1581 return ComponentInfo_GetStringValue(This->classkey, author_valuename,
1582 length, author, actual_length);
1583 }
1584
1585 static HRESULT WINAPI MetadataReaderInfo_GetVendorGUID(IWICMetadataReaderInfo *iface,
1586 GUID *vendor)
1587 {
1588 MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1589
1590 TRACE("(%p,%p)\n", iface, vendor);
1591
1592 return ComponentInfo_GetGUIDValue(This->classkey, vendor_valuename, vendor);
1593 }
1594
1595 static HRESULT WINAPI MetadataReaderInfo_GetVersion(IWICMetadataReaderInfo *iface,
1596 UINT length, WCHAR *version, UINT *actual_length)
1597 {
1598 MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1599
1600 TRACE("(%p,%u,%p,%p)\n", iface, length, version, actual_length);
1601
1602 return ComponentInfo_GetStringValue(This->classkey, version_valuename,
1603 length, version, actual_length);
1604 }
1605
1606 static HRESULT WINAPI MetadataReaderInfo_GetSpecVersion(IWICMetadataReaderInfo *iface,
1607 UINT length, WCHAR *version, UINT *actual_length)
1608 {
1609 MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1610
1611 TRACE("(%p,%u,%p,%p)\n", iface, length, version, actual_length);
1612
1613 return ComponentInfo_GetStringValue(This->classkey, specversion_valuename,
1614 length, version, actual_length);
1615 }
1616
1617 static HRESULT WINAPI MetadataReaderInfo_GetFriendlyName(IWICMetadataReaderInfo *iface,
1618 UINT length, WCHAR *name, UINT *actual_length)
1619 {
1620 MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1621
1622 TRACE("(%p,%u,%p,%p)\n", iface, length, name, actual_length);
1623
1624 return ComponentInfo_GetStringValue(This->classkey, friendlyname_valuename,
1625 length, name, actual_length);
1626 }
1627
1628 static HRESULT WINAPI MetadataReaderInfo_GetMetadataFormat(IWICMetadataReaderInfo *iface,
1629 GUID *format)
1630 {
1631 MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1632 TRACE("(%p,%p)\n", iface, format);
1633 return ComponentInfo_GetGUIDValue(This->classkey, metadataformat_valuename, format);
1634 }
1635
1636 static HRESULT WINAPI MetadataReaderInfo_GetContainerFormats(IWICMetadataReaderInfo *iface,
1637 UINT length, GUID *formats, UINT *actual_length)
1638 {
1639 MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1640 TRACE("(%p,%u,%p,%p)\n", iface, length, formats, actual_length);
1641
1642 return ComponentInfo_GetGuidList(This->classkey, containers_keyname, length,
1643 formats, actual_length);
1644 }
1645
1646 static HRESULT WINAPI MetadataReaderInfo_GetDeviceManufacturer(IWICMetadataReaderInfo *iface,
1647 UINT length, WCHAR *manufacturer, UINT *actual_length)
1648 {
1649 FIXME("(%p,%u,%p,%p): stub\n", iface, length, manufacturer, actual_length);
1650 return E_NOTIMPL;
1651 }
1652
1653 static HRESULT WINAPI MetadataReaderInfo_GetDeviceModels(IWICMetadataReaderInfo *iface,
1654 UINT length, WCHAR *models, UINT *actual_length)
1655 {
1656 FIXME("(%p,%u,%p,%p): stub\n", iface, length, models, actual_length);
1657 return E_NOTIMPL;
1658 }
1659
1660 static HRESULT WINAPI MetadataReaderInfo_DoesRequireFullStream(IWICMetadataReaderInfo *iface,
1661 BOOL *param)
1662 {
1663 MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1664 TRACE("(%p,%p)\n", iface, param);
1665 return ComponentInfo_GetDWORDValue(This->classkey, requiresfullstream_valuename, (DWORD *)param);
1666 }
1667
1668 static HRESULT WINAPI MetadataReaderInfo_DoesSupportPadding(IWICMetadataReaderInfo *iface,
1669 BOOL *param)
1670 {
1671 MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1672 TRACE("(%p,%p)\n", iface, param);
1673 return ComponentInfo_GetDWORDValue(This->classkey, supportspadding_valuename, (DWORD *)param);
1674 }
1675
1676 static HRESULT WINAPI MetadataReaderInfo_DoesRequireFixedSize(IWICMetadataReaderInfo *iface,
1677 BOOL *param)
1678 {
1679 FIXME("(%p,%p): stub\n", iface, param);
1680 return E_NOTIMPL;
1681 }
1682
1683 static HRESULT WINAPI MetadataReaderInfo_GetPatterns(IWICMetadataReaderInfo *iface,
1684 REFGUID container, UINT length, WICMetadataPattern *patterns, UINT *count, UINT *actual_length)
1685 {
1686 MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1687 HRESULT hr=S_OK;
1688 LONG res;
1689 UINT pattern_count=0, patterns_size=0;
1690 DWORD valuesize, patternsize;
1691 BYTE *bPatterns=(BYTE*)patterns;
1692 HKEY containers_key, guid_key, pattern_key;
1693 WCHAR subkeyname[11];
1694 WCHAR guidkeyname[39];
1695 int i;
1696 static const WCHAR uintformatW[] = {'%','u',0};
1697 static const WCHAR patternW[] = {'P','a','t','t','e','r','n',0};
1698 static const WCHAR positionW[] = {'P','o','s','i','t','i','o','n',0};
1699 static const WCHAR maskW[] = {'M','a','s','k',0};
1700 static const WCHAR dataoffsetW[] = {'D','a','t','a','O','f','f','s','e','t',0};
1701
1702 TRACE("(%p,%s,%u,%p,%p,%p)\n", iface, debugstr_guid(container), length, patterns, count, actual_length);
1703
1704 if (!actual_length || !container) return E_INVALIDARG;
1705
1706 res = RegOpenKeyExW(This->classkey, containers_keyname, 0, KEY_READ, &containers_key);
1707 if (res == ERROR_SUCCESS)
1708 {
1709 StringFromGUID2(container, guidkeyname, 39);
1710
1711 res = RegOpenKeyExW(containers_key, guidkeyname, 0, KEY_READ, &guid_key);
1712 if (res == ERROR_FILE_NOT_FOUND) hr = WINCODEC_ERR_COMPONENTNOTFOUND;
1713 else if (res != ERROR_SUCCESS) hr = HRESULT_FROM_WIN32(res);
1714
1715 RegCloseKey(containers_key);
1716 }
1717 else if (res == ERROR_FILE_NOT_FOUND) hr = WINCODEC_ERR_COMPONENTNOTFOUND;
1718 else hr = HRESULT_FROM_WIN32(res);
1719
1720 if (SUCCEEDED(hr))
1721 {
1722 res = RegQueryInfoKeyW(guid_key, NULL, NULL, NULL, &pattern_count, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1723 if (res != ERROR_SUCCESS) hr = HRESULT_FROM_WIN32(res);
1724
1725 if (SUCCEEDED(hr))
1726 {
1727 patterns_size = pattern_count * sizeof(WICMetadataPattern);
1728
1729 for (i=0; i<pattern_count; i++)
1730 {
1731 snprintfW(subkeyname, 11, uintformatW, i);
1732 res = RegOpenKeyExW(guid_key, subkeyname, 0, KEY_READ, &pattern_key);
1733 if (res == ERROR_SUCCESS)
1734 {
1735 res = RegGetValueW(pattern_key, NULL, patternW, RRF_RT_REG_BINARY, NULL,
1736 NULL, &patternsize);
1737 patterns_size += patternsize*2;
1738
1739 if ((length >= patterns_size) && (res == ERROR_SUCCESS))
1740 {
1741 patterns[i].Length = patternsize;
1742
1743 patterns[i].DataOffset.QuadPart = 0;
1744 valuesize = sizeof(ULARGE_INTEGER);
1745 RegGetValueW(pattern_key, NULL, dataoffsetW, RRF_RT_DWORD|RRF_RT_QWORD, NULL,
1746 &patterns[i].DataOffset, &valuesize);
1747
1748 patterns[i].Position.QuadPart = 0;
1749 valuesize = sizeof(ULARGE_INTEGER);
1750 res = RegGetValueW(pattern_key, NULL, positionW, RRF_RT_DWORD|RRF_RT_QWORD, NULL,
1751 &patterns[i].Position, &valuesize);
1752
1753 if (res == ERROR_SUCCESS)
1754 {
1755 patterns[i].Pattern = bPatterns+patterns_size-patternsize*2;
1756 valuesize = patternsize;
1757 res = RegGetValueW(pattern_key, NULL, patternW, RRF_RT_REG_BINARY, NULL,
1758 patterns[i].Pattern, &valuesize);
1759 }
1760
1761 if (res == ERROR_SUCCESS)
1762 {
1763 patterns[i].Mask = bPatterns+patterns_size-patternsize;
1764 valuesize = patternsize;
1765 res = RegGetValueW(pattern_key, NULL, maskW, RRF_RT_REG_BINARY, NULL,
1766 patterns[i].Mask, &valuesize);
1767 }
1768 }
1769
1770 RegCloseKey(pattern_key);
1771 }
1772 if (res != ERROR_SUCCESS)
1773 {
1774 hr = HRESULT_FROM_WIN32(res);
1775 break;
1776 }
1777 }
1778 }
1779
1780 RegCloseKey(guid_key);
1781 }
1782
1783 if (hr == S_OK)
1784 {
1785 *count = pattern_count;
1786 *actual_length = patterns_size;
1787 if (patterns && length < patterns_size)
1788 hr = WINCODEC_ERR_INSUFFICIENTBUFFER;
1789 }
1790
1791 return hr;
1792 }
1793
1794 static HRESULT WINAPI MetadataReaderInfo_MatchesPattern(IWICMetadataReaderInfo *iface,
1795 REFGUID container, IStream *stream, BOOL *matches)
1796 {
1797 HRESULT hr;
1798 WICMetadataPattern *patterns;
1799 UINT pattern_count=0, patterns_size=0;
1800 ULONG datasize=0;
1801 BYTE *data=NULL;
1802 ULONG bytesread;
1803 UINT i;
1804 LARGE_INTEGER seekpos;
1805 ULONG pos;
1806
1807 TRACE("(%p,%s,%p,%p)\n", iface, debugstr_guid(container), stream, matches);
1808
1809 hr = MetadataReaderInfo_GetPatterns(iface, container, 0, NULL, &pattern_count, &patterns_size);
1810 if (FAILED(hr)) return hr;
1811
1812 patterns = HeapAlloc(GetProcessHeap(), 0, patterns_size);
1813 if (!patterns) return E_OUTOFMEMORY;
1814
1815 hr = MetadataReaderInfo_GetPatterns(iface, container, patterns_size, patterns, &pattern_count, &patterns_size);
1816 if (FAILED(hr)) goto end;
1817
1818 for (i=0; i<pattern_count; i++)
1819 {
1820 if (datasize < patterns[i].Length)
1821 {
1822 HeapFree(GetProcessHeap(), 0, data);
1823 datasize = patterns[i].Length;
1824 data = HeapAlloc(GetProcessHeap(), 0, patterns[i].Length);
1825 if (!data)
1826 {
1827 hr = E_OUTOFMEMORY;
1828 break;
1829 }
1830 }
1831
1832 seekpos.QuadPart = patterns[i].Position.QuadPart;
1833 hr = IStream_Seek(stream, seekpos, STREAM_SEEK_SET, NULL);
1834 if (FAILED(hr)) break;
1835
1836 hr = IStream_Read(stream, data, patterns[i].Length, &bytesread);
1837 if (hr == S_FALSE || (hr == S_OK && bytesread != patterns[i].Length)) /* past end of stream */
1838 continue;
1839 if (FAILED(hr)) break;
1840
1841 for (pos=0; pos<patterns[i].Length; pos++)
1842 {
1843 if ((data[pos] & patterns[i].Mask[pos]) != patterns[i].Pattern[pos])
1844 break;
1845 }
1846 if (pos == patterns[i].Length) /* matches pattern */
1847 {
1848 hr = S_OK;
1849 *matches = TRUE;
1850 break;
1851 }
1852 }
1853
1854 if (i == pattern_count) /* does not match any pattern */
1855 {
1856 hr = S_OK;
1857 *matches = FALSE;
1858 }
1859
1860 end:
1861 HeapFree(GetProcessHeap(), 0, patterns);
1862 HeapFree(GetProcessHeap(), 0, data);
1863
1864 return hr;
1865 }
1866
1867 static HRESULT WINAPI MetadataReaderInfo_CreateInstance(IWICMetadataReaderInfo *iface,
1868 IWICMetadataReader **reader)
1869 {
1870 MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface);
1871
1872 TRACE("(%p,%p)\n", iface, reader);
1873
1874 return create_instance(&This->clsid, &IID_IWICMetadataReader, (void **)reader);
1875 }
1876
1877 static const IWICMetadataReaderInfoVtbl MetadataReaderInfo_Vtbl = {
1878 MetadataReaderInfo_QueryInterface,
1879 MetadataReaderInfo_AddRef,
1880 MetadataReaderInfo_Release,
1881 MetadataReaderInfo_GetComponentType,
1882 MetadataReaderInfo_GetCLSID,
1883 MetadataReaderInfo_GetSigningStatus,
1884 MetadataReaderInfo_GetAuthor,
1885 MetadataReaderInfo_GetVendorGUID,
1886 MetadataReaderInfo_GetVersion,
1887 MetadataReaderInfo_GetSpecVersion,
1888 MetadataReaderInfo_GetFriendlyName,
1889 MetadataReaderInfo_GetMetadataFormat,
1890 MetadataReaderInfo_GetContainerFormats,
1891 MetadataReaderInfo_GetDeviceManufacturer,
1892 MetadataReaderInfo_GetDeviceModels,
1893 MetadataReaderInfo_DoesRequireFullStream,
1894 MetadataReaderInfo_DoesSupportPadding,
1895 MetadataReaderInfo_DoesRequireFixedSize,
1896 MetadataReaderInfo_GetPatterns,
1897 MetadataReaderInfo_MatchesPattern,
1898 MetadataReaderInfo_CreateInstance
1899 };
1900
1901 static HRESULT MetadataReaderInfo_Constructor(HKEY classkey, REFCLSID clsid, IWICComponentInfo **info)
1902 {
1903 MetadataReaderInfo *This;
1904
1905 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1906 if (!This)
1907 {
1908 RegCloseKey(classkey);
1909 return E_OUTOFMEMORY;
1910 }
1911
1912 This->IWICMetadataReaderInfo_iface.lpVtbl = &MetadataReaderInfo_Vtbl;
1913 This->ref = 1;
1914 This->classkey = classkey;
1915 This->clsid = *clsid;
1916
1917 *info = (IWICComponentInfo *)&This->IWICMetadataReaderInfo_iface;
1918 return S_OK;
1919 }
1920
1921 static const WCHAR clsid_keyname[] = {'C','L','S','I','D',0};
1922 static const WCHAR instance_keyname[] = {'I','n','s','t','a','n','c','e',0};
1923
1924 struct category {
1925 WICComponentType type;
1926 const GUID *catid;
1927 HRESULT (*constructor)(HKEY,REFCLSID,IWICComponentInfo**);
1928 };
1929
1930 static const struct category categories[] = {
1931 {WICDecoder, &CATID_WICBitmapDecoders, BitmapDecoderInfo_Constructor},
1932 {WICEncoder, &CATID_WICBitmapEncoders, BitmapEncoderInfo_Constructor},
1933 {WICPixelFormatConverter, &CATID_WICFormatConverters, FormatConverterInfo_Constructor},
1934 {WICPixelFormat, &CATID_WICPixelFormats, PixelFormatInfo_Constructor},
1935 {WICMetadataReader, &CATID_WICMetadataReader, MetadataReaderInfo_Constructor},
1936 {0}
1937 };
1938
1939 HRESULT CreateComponentInfo(REFCLSID clsid, IWICComponentInfo **ppIInfo)
1940 {
1941 HKEY clsidkey;
1942 HKEY classkey;
1943 HKEY catidkey;
1944 HKEY instancekey;
1945 WCHAR guidstring[39];
1946 LONG res;
1947 const struct category *category;
1948 BOOL found = FALSE;
1949 HRESULT hr;
1950
1951 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, KEY_READ, &clsidkey);
1952 if (res != ERROR_SUCCESS)
1953 return HRESULT_FROM_WIN32(res);
1954
1955 for (category=categories; category->type; category++)
1956 {
1957 StringFromGUID2(category->catid, guidstring, 39);
1958 res = RegOpenKeyExW(clsidkey, guidstring, 0, KEY_READ, &catidkey);
1959 if (res == ERROR_SUCCESS)
1960 {
1961 res = RegOpenKeyExW(catidkey, instance_keyname, 0, KEY_READ, &instancekey);
1962 if (res == ERROR_SUCCESS)
1963 {
1964 StringFromGUID2(clsid, guidstring, 39);
1965 res = RegOpenKeyExW(instancekey, guidstring, 0, KEY_READ, &classkey);
1966 if (res == ERROR_SUCCESS)
1967 {
1968 RegCloseKey(classkey);
1969 found = TRUE;
1970 }
1971 RegCloseKey(instancekey);
1972 }
1973 RegCloseKey(catidkey);
1974 }
1975 if (found) break;
1976 }
1977
1978 if (found)
1979 {
1980 res = RegOpenKeyExW(clsidkey, guidstring, 0, KEY_READ, &classkey);
1981 if (res == ERROR_SUCCESS)
1982 hr = category->constructor(classkey, clsid, ppIInfo);
1983 else
1984 hr = HRESULT_FROM_WIN32(res);
1985 }
1986 else
1987 {
1988 FIXME("%s is not supported\n", wine_dbgstr_guid(clsid));
1989 hr = E_FAIL;
1990 }
1991
1992 RegCloseKey(clsidkey);
1993
1994 return hr;
1995 }
1996
1997 typedef struct {
1998 IEnumUnknown IEnumUnknown_iface;
1999 LONG ref;
2000 struct list objects;
2001 struct list *cursor;
2002 CRITICAL_SECTION lock; /* Must be held when reading or writing cursor */
2003 } ComponentEnum;
2004
2005 static inline ComponentEnum *impl_from_IEnumUnknown(IEnumUnknown *iface)
2006 {
2007 return CONTAINING_RECORD(iface, ComponentEnum, IEnumUnknown_iface);
2008 }
2009
2010 typedef struct {
2011 struct list entry;
2012 IUnknown *unk;
2013 } ComponentEnumItem;
2014
2015 static const IEnumUnknownVtbl ComponentEnumVtbl;
2016
2017 static HRESULT WINAPI ComponentEnum_QueryInterface(IEnumUnknown *iface, REFIID iid,
2018 void **ppv)
2019 {
2020 ComponentEnum *This = impl_from_IEnumUnknown(iface);
2021 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
2022
2023 if (!ppv) return E_INVALIDARG;
2024
2025 if (IsEqualIID(&IID_IUnknown, iid) ||
2026 IsEqualIID(&IID_IEnumUnknown, iid))
2027 {
2028 *ppv = &This->IEnumUnknown_iface;
2029 }
2030 else
2031 {
2032 *ppv = NULL;
2033 return E_NOINTERFACE;
2034 }
2035
2036 IUnknown_AddRef((IUnknown*)*ppv);
2037 return S_OK;
2038 }
2039
2040 static ULONG WINAPI ComponentEnum_AddRef(IEnumUnknown *iface)
2041 {
2042 ComponentEnum *This = impl_from_IEnumUnknown(iface);
2043 ULONG ref = InterlockedIncrement(&This->ref);
2044
2045 TRACE("(%p) refcount=%u\n", iface, ref);
2046
2047 return ref;
2048 }
2049
2050 static ULONG WINAPI ComponentEnum_Release(IEnumUnknown *iface)
2051 {
2052 ComponentEnum *This = impl_from_IEnumUnknown(iface);
2053 ULONG ref = InterlockedDecrement(&This->ref);
2054 ComponentEnumItem *cursor, *cursor2;
2055
2056 TRACE("(%p) refcount=%u\n", iface, ref);
2057
2058 if (ref == 0)
2059 {
2060 LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, &This->objects, ComponentEnumItem, entry)
2061 {
2062 IUnknown_Release(cursor->unk);
2063 list_remove(&cursor->entry);
2064 HeapFree(GetProcessHeap(), 0, cursor);
2065 }
2066 This->lock.DebugInfo->Spare[0] = 0;
2067 DeleteCriticalSection(&This->lock);
2068 HeapFree(GetProcessHeap(), 0, This);
2069 }
2070
2071 return ref;
2072 }
2073
2074 static HRESULT WINAPI ComponentEnum_Next(IEnumUnknown *iface, ULONG celt,
2075 IUnknown **rgelt, ULONG *pceltFetched)
2076 {
2077 ComponentEnum *This = impl_from_IEnumUnknown(iface);
2078 ULONG num_fetched=0;
2079 ComponentEnumItem *item;
2080 HRESULT hr=S_OK;
2081
2082 TRACE("(%p,%u,%p,%p)\n", iface, celt, rgelt, pceltFetched);
2083
2084 EnterCriticalSection(&This->lock);
2085 while (num_fetched<celt)
2086 {
2087 if (!This->cursor)
2088 {
2089 hr = S_FALSE;
2090 break;
2091 }
2092 item = LIST_ENTRY(This->cursor, ComponentEnumItem, entry);
2093 IUnknown_AddRef(item->unk);
2094 rgelt[num_fetched] = item->unk;
2095 num_fetched++;
2096 This->cursor = list_next(&This->objects, This->cursor);
2097 }
2098 LeaveCriticalSection(&This->lock);
2099 if (pceltFetched)
2100 *pceltFetched = num_fetched;
2101 return hr;
2102 }
2103
2104 static HRESULT WINAPI ComponentEnum_Skip(IEnumUnknown *iface, ULONG celt)
2105 {
2106 ComponentEnum *This = impl_from_IEnumUnknown(iface);
2107 ULONG i;
2108 HRESULT hr=S_OK;
2109
2110 TRACE("(%p,%u)\n", iface, celt);
2111
2112 EnterCriticalSection(&This->lock);
2113 for (i=0; i<celt; i++)
2114 {
2115 if (!This->cursor)
2116 {
2117 hr = S_FALSE;
2118 break;
2119 }
2120 This->cursor = list_next(&This->objects, This->cursor);
2121 }
2122 LeaveCriticalSection(&This->lock);
2123 return hr;
2124 }
2125
2126 static HRESULT WINAPI ComponentEnum_Reset(IEnumUnknown *iface)
2127 {
2128 ComponentEnum *This = impl_from_IEnumUnknown(iface);
2129
2130 TRACE("(%p)\n", iface);
2131
2132 EnterCriticalSection(&This->lock);
2133 This->cursor = list_head(&This->objects);
2134 LeaveCriticalSection(&This->lock);
2135 return S_OK;
2136 }
2137
2138 static HRESULT WINAPI ComponentEnum_Clone(IEnumUnknown *iface, IEnumUnknown **ppenum)
2139 {
2140 ComponentEnum *This = impl_from_IEnumUnknown(iface);
2141 ComponentEnum *new_enum;
2142 ComponentEnumItem *old_item, *new_item;
2143 HRESULT ret=S_OK;
2144 struct list *old_cursor;
2145
2146 new_enum = HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentEnum));
2147 if (!new_enum)
2148 {
2149 *ppenum = NULL;
2150 return E_OUTOFMEMORY;
2151 }
2152
2153 new_enum->IEnumUnknown_iface.lpVtbl = &ComponentEnumVtbl;
2154 new_enum->ref = 1;
2155 new_enum->cursor = NULL;
2156 list_init(&new_enum->objects);
2157 InitializeCriticalSection(&new_enum->lock);
2158 new_enum->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": ComponentEnum.lock");
2159
2160 EnterCriticalSection(&This->lock);
2161 old_cursor = This->cursor;
2162 LeaveCriticalSection(&This->lock);
2163
2164 LIST_FOR_EACH_ENTRY(old_item, &This->objects, ComponentEnumItem, entry)
2165 {
2166 new_item = HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentEnumItem));
2167 if (!new_item)
2168 {
2169 ret = E_OUTOFMEMORY;
2170 break;
2171 }
2172 new_item->unk = old_item->unk;
2173 list_add_tail(&new_enum->objects, &new_item->entry);
2174 IUnknown_AddRef(new_item->unk);
2175 if (&old_item->entry == old_cursor) new_enum->cursor = &new_item->entry;
2176 }
2177
2178 if (FAILED(ret))
2179 {
2180 IEnumUnknown_Release(&new_enum->IEnumUnknown_iface);
2181 *ppenum = NULL;
2182 }
2183 else
2184 *ppenum = &new_enum->IEnumUnknown_iface;
2185
2186 return ret;
2187 }
2188
2189 static const IEnumUnknownVtbl ComponentEnumVtbl = {
2190 ComponentEnum_QueryInterface,
2191 ComponentEnum_AddRef,
2192 ComponentEnum_Release,
2193 ComponentEnum_Next,
2194 ComponentEnum_Skip,
2195 ComponentEnum_Reset,
2196 ComponentEnum_Clone
2197 };
2198
2199 HRESULT CreateComponentEnumerator(DWORD componentTypes, DWORD options, IEnumUnknown **ppIEnumUnknown)
2200 {
2201 ComponentEnum *This;
2202 ComponentEnumItem *item;
2203 const struct category *category;
2204 HKEY clsidkey, catidkey, instancekey;
2205 WCHAR guidstring[39];
2206 LONG res;
2207 int i;
2208 HRESULT hr=S_OK;
2209 CLSID clsid;
2210
2211 if (options) FIXME("ignoring flags %x\n", options);
2212
2213 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, KEY_READ, &clsidkey);
2214 if (res != ERROR_SUCCESS)
2215 return HRESULT_FROM_WIN32(res);
2216
2217 This = HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentEnum));
2218 if (!This)
2219 {
2220 RegCloseKey(clsidkey);
2221 return E_OUTOFMEMORY;
2222 }
2223
2224 This->IEnumUnknown_iface.lpVtbl = &ComponentEnumVtbl;
2225 This->ref = 1;
2226 list_init(&This->objects);
2227 InitializeCriticalSection(&This->lock);
2228 This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": ComponentEnum.lock");
2229
2230 for (category=categories; category->type && hr == S_OK; category++)
2231 {
2232 if ((category->type & componentTypes) == 0) continue;
2233 StringFromGUID2(category->catid, guidstring, 39);
2234 res = RegOpenKeyExW(clsidkey, guidstring, 0, KEY_READ, &catidkey);
2235 if (res == ERROR_SUCCESS)
2236 {
2237 res = RegOpenKeyExW(catidkey, instance_keyname, 0, KEY_READ, &instancekey);
2238 if (res == ERROR_SUCCESS)
2239 {
2240 i=0;
2241 for (;;i++)
2242 {
2243 DWORD guidstring_size = 39;
2244 res = RegEnumKeyExW(instancekey, i, guidstring, &guidstring_size, NULL, NULL, NULL, NULL);
2245 if (res != ERROR_SUCCESS) break;
2246
2247 item = HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentEnumItem));
2248 if (!item) { hr = E_OUTOFMEMORY; break; }
2249
2250 hr = CLSIDFromString(guidstring, &clsid);
2251 if (SUCCEEDED(hr))
2252 {
2253 hr = CreateComponentInfo(&clsid, (IWICComponentInfo**)&item->unk);
2254 if (SUCCEEDED(hr))
2255 list_add_tail(&This->objects, &item->entry);
2256 }
2257
2258 if (FAILED(hr))
2259 {
2260 HeapFree(GetProcessHeap(), 0, item);
2261 hr = S_OK;
2262 }
2263 }
2264 RegCloseKey(instancekey);
2265 }
2266 RegCloseKey(catidkey);
2267 }
2268 if (res != ERROR_SUCCESS && res != ERROR_NO_MORE_ITEMS)
2269 hr = HRESULT_FROM_WIN32(res);
2270 }
2271 RegCloseKey(clsidkey);
2272
2273 if (SUCCEEDED(hr))
2274 {
2275 IEnumUnknown_Reset(&This->IEnumUnknown_iface);
2276 *ppIEnumUnknown = &This->IEnumUnknown_iface;
2277 }
2278 else
2279 {
2280 *ppIEnumUnknown = NULL;
2281 IEnumUnknown_Release(&This->IEnumUnknown_iface);
2282 }
2283
2284 return hr;
2285 }
2286
2287 static BOOL is_1bpp_format(const WICPixelFormatGUID *format)
2288 {
2289 return IsEqualGUID(format, &GUID_WICPixelFormatBlackWhite) ||
2290 IsEqualGUID(format, &GUID_WICPixelFormat1bppIndexed);
2291 }
2292
2293 HRESULT WINAPI WICConvertBitmapSource(REFWICPixelFormatGUID dstFormat, IWICBitmapSource *pISrc, IWICBitmapSource **ppIDst)
2294 {
2295 HRESULT res;
2296 IEnumUnknown *enumconverters;
2297 IUnknown *unkconverterinfo;
2298 IWICFormatConverterInfo *converterinfo=NULL;
2299 IWICFormatConverter *converter=NULL;
2300 GUID srcFormat;
2301 WCHAR srcformatstr[39], dstformatstr[39];
2302 BOOL canconvert;
2303 ULONG num_fetched;
2304
2305 TRACE("%s,%p,%p\n", debugstr_guid(dstFormat), pISrc, ppIDst);
2306
2307 res = IWICBitmapSource_GetPixelFormat(pISrc, &srcFormat);
2308 if (FAILED(res)) return res;
2309
2310 if (IsEqualGUID(&srcFormat, dstFormat) || (is_1bpp_format(&srcFormat) && is_1bpp_format(dstFormat)))
2311 {
2312 IWICBitmapSource_AddRef(pISrc);
2313 *ppIDst = pISrc;
2314 return S_OK;
2315 }
2316
2317 StringFromGUID2(&srcFormat, srcformatstr, 39);
2318 StringFromGUID2(dstFormat, dstformatstr, 39);
2319
2320 res = CreateComponentEnumerator(WICPixelFormatConverter, 0, &enumconverters);
2321 if (FAILED(res)) return res;
2322
2323 while (!converter)
2324 {
2325 res = IEnumUnknown_Next(enumconverters, 1, &unkconverterinfo, &num_fetched);
2326
2327 if (res == S_OK)
2328 {
2329 res = IUnknown_QueryInterface(unkconverterinfo, &IID_IWICFormatConverterInfo, (void**)&converterinfo);
2330
2331 if (SUCCEEDED(res))
2332 {
2333 canconvert = ConverterSupportsFormat(converterinfo, srcformatstr);
2334
2335 if (canconvert)
2336 canconvert = ConverterSupportsFormat(converterinfo, dstformatstr);
2337
2338 if (canconvert)
2339 {
2340 res = IWICFormatConverterInfo_CreateInstance(converterinfo, &converter);
2341
2342 if (SUCCEEDED(res))
2343 res = IWICFormatConverter_CanConvert(converter, &srcFormat, dstFormat, &canconvert);
2344
2345 if (SUCCEEDED(res) && canconvert)
2346 res = IWICFormatConverter_Initialize(converter, pISrc, dstFormat, WICBitmapDitherTypeNone,
2347 NULL, 0.0, WICBitmapPaletteTypeMedianCut);
2348
2349 if (FAILED(res) || !canconvert)
2350 {
2351 if (converter)
2352 {
2353 IWICFormatConverter_Release(converter);
2354 converter = NULL;
2355 }
2356 }
2357 }
2358
2359 IWICFormatConverterInfo_Release(converterinfo);
2360 }
2361
2362 IUnknown_Release(unkconverterinfo);
2363 }
2364 else
2365 break;
2366 }
2367
2368 IEnumUnknown_Release(enumconverters);
2369
2370 if (converter)
2371 {
2372 res = IWICFormatConverter_QueryInterface(converter, &IID_IWICBitmapSource, (void **)ppIDst);
2373 IWICFormatConverter_Release(converter);
2374 return res;
2375 }
2376 else
2377 {
2378 FIXME("cannot convert %s to %s\n", debugstr_guid(&srcFormat), debugstr_guid(dstFormat));
2379 *ppIDst = NULL;
2380 return WINCODEC_ERR_COMPONENTNOTFOUND;
2381 }
2382 }