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