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