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 } 2564