1 /* 2 * Copyright (C) 2003 Michael Günnewig 3 * Copyright (C) 2003 CodeWeavers Inc. (Ulrich Czekalla) 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 "winuser.h" 27 #include "winerror.h" 28 #include "winreg.h" 29 #include "objbase.h" 30 #include "wine/unicode.h" 31 #include "wine/debug.h" 32 #include "dmo.h" 33 34 WINE_DEFAULT_DEBUG_CHANNEL(msdmo); 35 36 #define MSDMO_MAJOR_VERSION 6 37 38 static const WCHAR szDMORootKey[] = 39 { 40 'D','i','r','e','c','t','S','h','o','w','\\', 41 'M','e','d','i','a','O','b','j','e','c','t','s',0 42 }; 43 44 static const WCHAR szDMOInputType[] = 45 { 46 'I','n','p','u','t','T','y','p','e','s',0 47 }; 48 49 static const WCHAR szDMOOutputType[] = 50 { 51 'O','u','t','p','u','t','T','y','p','e','s',0 52 }; 53 54 static const WCHAR szDMOKeyed[] = 55 { 56 'K','e','y','e','d',0 57 }; 58 59 static const WCHAR szDMOCategories[] = 60 { 61 'C','a','t','e','g','o','r','i','e','s',0 62 }; 63 64 static const WCHAR szGUIDFmt[] = 65 { 66 '%','0','8','X','-','%','0','4','X','-','%','0','4','X','-','%','0', 67 '2','X','%','0','2','X','-','%','0','2','X','%','0','2','X','%','0','2', 68 'X','%','0','2','X','%','0','2','X','%','0','2','X',0 69 }; 70 71 static const WCHAR szCat3Fmt[] = 72 { 73 '%','s','\\','%','s','\\','%','s',0 74 }; 75 76 static const WCHAR szCat2Fmt[] = 77 { 78 '%','s','\\','%','s',0 79 }; 80 81 static const WCHAR szToGuidFmt[] = 82 { 83 '{','%','s','}',0 84 }; 85 86 87 typedef struct 88 { 89 IEnumDMO IEnumDMO_iface; 90 LONG ref; 91 DWORD index; 92 GUID category; 93 DWORD dwFlags; 94 DWORD cInTypes; 95 DMO_PARTIAL_MEDIATYPE *pInTypes; 96 DWORD cOutTypes; 97 DMO_PARTIAL_MEDIATYPE *pOutTypes; 98 HKEY hkey; 99 } IEnumDMOImpl; 100 101 static inline IEnumDMOImpl *impl_from_IEnumDMO(IEnumDMO *iface) 102 { 103 return CONTAINING_RECORD(iface, IEnumDMOImpl, IEnumDMO_iface); 104 } 105 106 static HRESULT read_types(HKEY root, LPCWSTR key, ULONG *supplied, ULONG requested, DMO_PARTIAL_MEDIATYPE* types); 107 108 static const IEnumDMOVtbl edmovt; 109 110 static LPWSTR GUIDToString(LPWSTR lpwstr, REFGUID lpcguid) 111 { 112 wsprintfW(lpwstr, szGUIDFmt, lpcguid->Data1, lpcguid->Data2, 113 lpcguid->Data3, lpcguid->Data4[0], lpcguid->Data4[1], 114 lpcguid->Data4[2], lpcguid->Data4[3], lpcguid->Data4[4], 115 lpcguid->Data4[5], lpcguid->Data4[6], lpcguid->Data4[7]); 116 117 return lpwstr; 118 } 119 120 static HRESULT string_to_guid(const WCHAR *string, GUID *guid) 121 { 122 WCHAR buffer[39]; 123 buffer[0] = '{'; 124 strcpyW(buffer + 1, string); 125 buffer[37] = '}'; 126 buffer[38] = 0; 127 return CLSIDFromString(buffer, guid); 128 } 129 130 static BOOL IsMediaTypeEqual(const DMO_PARTIAL_MEDIATYPE* mt1, const DMO_PARTIAL_MEDIATYPE* mt2) 131 { 132 133 return (IsEqualCLSID(&mt1->type, &mt2->type) || 134 IsEqualCLSID(&mt2->type, &GUID_NULL) || 135 IsEqualCLSID(&mt1->type, &GUID_NULL)) && 136 (IsEqualCLSID(&mt1->subtype, &mt2->subtype) || 137 IsEqualCLSID(&mt2->subtype, &GUID_NULL) || 138 IsEqualCLSID(&mt1->subtype, &GUID_NULL)); 139 } 140 141 static HRESULT write_types(HKEY hkey, LPCWSTR name, const DMO_PARTIAL_MEDIATYPE* types, DWORD count) 142 { 143 LONG ret; 144 145 if (MSDMO_MAJOR_VERSION > 5) 146 { 147 ret = RegSetValueExW(hkey, name, 0, REG_BINARY, (const BYTE*) types, 148 count* sizeof(DMO_PARTIAL_MEDIATYPE)); 149 } 150 else 151 { 152 HKEY skey1,skey2,skey3; 153 DWORD index = 0; 154 WCHAR szGuidKey[64]; 155 156 ret = RegCreateKeyExW(hkey, name, 0, NULL, REG_OPTION_NON_VOLATILE, 157 KEY_WRITE, NULL, &skey1, NULL); 158 if (ret) 159 return HRESULT_FROM_WIN32(ret); 160 161 while (index < count) 162 { 163 GUIDToString(szGuidKey,&types[index].type); 164 ret = RegCreateKeyExW(skey1, szGuidKey, 0, NULL, 165 REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &skey2, NULL); 166 GUIDToString(szGuidKey,&types[index].subtype); 167 ret = RegCreateKeyExW(skey2, szGuidKey, 0, NULL, 168 REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &skey3, NULL); 169 RegCloseKey(skey3); 170 RegCloseKey(skey2); 171 index ++; 172 } 173 RegCloseKey(skey1); 174 } 175 176 return HRESULT_FROM_WIN32(ret); 177 } 178 179 /*************************************************************** 180 * DMORegister (MSDMO.@) 181 * 182 * Register a DirectX Media Object. 183 */ 184 HRESULT WINAPI DMORegister( 185 LPCWSTR szName, 186 REFCLSID clsidDMO, 187 REFGUID guidCategory, 188 DWORD dwFlags, 189 DWORD cInTypes, 190 const DMO_PARTIAL_MEDIATYPE *pInTypes, 191 DWORD cOutTypes, 192 const DMO_PARTIAL_MEDIATYPE *pOutTypes 193 ) 194 { 195 WCHAR szguid[64]; 196 HRESULT hres; 197 HKEY hrkey = 0; 198 HKEY hkey = 0; 199 HKEY hckey = 0; 200 HKEY hclskey = 0; 201 LONG ret; 202 203 TRACE("%s %s %s\n", debugstr_w(szName), debugstr_guid(clsidDMO), debugstr_guid(guidCategory)); 204 205 if (IsEqualGUID(guidCategory, &GUID_NULL)) 206 return E_INVALIDARG; 207 208 ret = RegCreateKeyExW(HKEY_CLASSES_ROOT, szDMORootKey, 0, NULL, 209 REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hrkey, NULL); 210 if (ret) 211 return E_FAIL; 212 213 /* Create clsidDMO key under MediaObjects */ 214 ret = RegCreateKeyExW(hrkey, GUIDToString(szguid, clsidDMO), 0, NULL, 215 REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, NULL); 216 if (ret) 217 goto lend; 218 219 /* Set default Name value */ 220 ret = RegSetValueExW(hkey, NULL, 0, REG_SZ, (const BYTE*) szName, 221 (strlenW(szName) + 1) * sizeof(WCHAR)); 222 223 /* Set InputTypes */ 224 hres = write_types(hkey, szDMOInputType, pInTypes, cInTypes); 225 226 /* Set OutputTypes */ 227 hres = write_types(hkey, szDMOOutputType, pOutTypes, cOutTypes); 228 229 if (dwFlags & DMO_REGISTERF_IS_KEYED) 230 { 231 /* Create Keyed key */ 232 ret = RegCreateKeyExW(hkey, szDMOKeyed, 0, NULL, 233 REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hckey, NULL); 234 if (ret) 235 goto lend; 236 RegCloseKey(hckey); 237 } 238 239 /* Register the category */ 240 ret = RegCreateKeyExW(hrkey, szDMOCategories, 0, NULL, 241 REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hckey, NULL); 242 if (ret) 243 goto lend; 244 245 RegCloseKey(hkey); 246 247 ret = RegCreateKeyExW(hckey, GUIDToString(szguid, guidCategory), 0, NULL, 248 REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, NULL); 249 if (ret) 250 goto lend; 251 ret = RegCreateKeyExW(hkey, GUIDToString(szguid, clsidDMO), 0, NULL, 252 REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hclskey, NULL); 253 if (ret) 254 goto lend; 255 256 lend: 257 if (hkey) 258 RegCloseKey(hkey); 259 if (hckey) 260 RegCloseKey(hckey); 261 if (hclskey) 262 RegCloseKey(hclskey); 263 if (hrkey) 264 RegCloseKey(hrkey); 265 266 hres = HRESULT_FROM_WIN32(ret); 267 TRACE(" hresult=0x%08x\n", hres); 268 return hres; 269 } 270 271 static HRESULT unregister_dmo_from_category(const WCHAR *dmoW, const WCHAR *catW, HKEY categories) 272 { 273 HKEY catkey; 274 LONG ret; 275 276 ret = RegOpenKeyExW(categories, catW, 0, KEY_WRITE, &catkey); 277 if (!ret) 278 { 279 ret = RegDeleteKeyW(catkey, dmoW); 280 RegCloseKey(catkey); 281 } 282 283 return !ret ? S_OK : S_FALSE; 284 } 285 286 /*************************************************************** 287 * DMOUnregister (MSDMO.@) 288 * 289 * Unregister a DirectX Media Object. 290 */ 291 HRESULT WINAPI DMOUnregister(REFCLSID dmo, REFGUID category) 292 { 293 HKEY rootkey = 0, categorieskey = 0; 294 WCHAR dmoW[64], catW[64]; 295 HRESULT hr = S_FALSE; 296 LONG ret; 297 298 TRACE("%s %s\n", debugstr_guid(dmo), debugstr_guid(category)); 299 300 ret = RegOpenKeyExW(HKEY_CLASSES_ROOT, szDMORootKey, 0, KEY_WRITE, &rootkey); 301 if (ret) 302 return S_FALSE; 303 304 GUIDToString(dmoW, dmo); 305 RegDeleteKeyW(rootkey, dmoW); 306 307 /* open 'Categories' */ 308 ret = RegOpenKeyExW(rootkey, szDMOCategories, 0, KEY_WRITE|KEY_ENUMERATE_SUB_KEYS, &categorieskey); 309 RegCloseKey(rootkey); 310 if (ret) 311 { 312 hr = HRESULT_FROM_WIN32(ret); 313 goto lend; 314 } 315 316 /* remove from all categories */ 317 if (IsEqualGUID(category, &GUID_NULL)) 318 { 319 DWORD index = 0, len = ARRAY_SIZE(catW); 320 321 while (!RegEnumKeyExW(categorieskey, index++, catW, &len, NULL, NULL, NULL, NULL)) 322 hr = unregister_dmo_from_category(dmoW, catW, categorieskey); 323 } 324 else 325 { 326 GUIDToString(catW, category); 327 hr = unregister_dmo_from_category(dmoW, catW, categorieskey); 328 } 329 330 lend: 331 if (categorieskey) 332 RegCloseKey(categorieskey); 333 334 return hr; 335 } 336 337 338 /*************************************************************** 339 * DMOGetName (MSDMO.@) 340 * 341 * Get DMO Name from the registry 342 */ 343 HRESULT WINAPI DMOGetName(REFCLSID clsidDMO, WCHAR name[]) 344 { 345 static const INT max_name_len = 80*sizeof(WCHAR); 346 DWORD count = max_name_len; 347 WCHAR szguid[64]; 348 HKEY hrkey, hkey; 349 LONG ret; 350 351 TRACE("%s %p\n", debugstr_guid(clsidDMO), name); 352 353 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, szDMORootKey, 0, KEY_READ, &hrkey)) 354 return E_FAIL; 355 356 ret = RegOpenKeyExW(hrkey, GUIDToString(szguid, clsidDMO), 0, KEY_READ, &hkey); 357 RegCloseKey(hrkey); 358 if (ret) 359 return E_FAIL; 360 361 ret = RegQueryValueExW(hkey, NULL, NULL, NULL, (LPBYTE)name, &count); 362 RegCloseKey(hkey); 363 364 if (!ret && count > 1) 365 { 366 TRACE("name=%s\n", debugstr_w(name)); 367 return S_OK; 368 } 369 370 name[0] = 0; 371 return S_FALSE; 372 } 373 374 static HRESULT dup_partial_mediatype(const DMO_PARTIAL_MEDIATYPE *types, DWORD count, DMO_PARTIAL_MEDIATYPE **ret) 375 { 376 *ret = NULL; 377 378 if (count == 0) 379 return S_OK; 380 381 *ret = HeapAlloc(GetProcessHeap(), 0, count*sizeof(*types)); 382 if (!*ret) 383 return E_OUTOFMEMORY; 384 385 memcpy(*ret, types, count*sizeof(*types)); 386 return S_OK; 387 } 388 389 /************************************************************************** 390 * IEnumDMO_Constructor 391 */ 392 static HRESULT IEnumDMO_Constructor( 393 REFGUID guidCategory, 394 DWORD dwFlags, 395 DWORD cInTypes, 396 const DMO_PARTIAL_MEDIATYPE *pInTypes, 397 DWORD cOutTypes, 398 const DMO_PARTIAL_MEDIATYPE *pOutTypes, 399 IEnumDMO **obj) 400 { 401 IEnumDMOImpl* lpedmo; 402 HRESULT hr; 403 404 *obj = NULL; 405 406 lpedmo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IEnumDMOImpl)); 407 if (!lpedmo) 408 return E_OUTOFMEMORY; 409 410 lpedmo->IEnumDMO_iface.lpVtbl = &edmovt; 411 lpedmo->ref = 1; 412 lpedmo->index = -1; 413 lpedmo->category = *guidCategory; 414 lpedmo->dwFlags = dwFlags; 415 lpedmo->cInTypes = cInTypes; 416 lpedmo->cOutTypes = cOutTypes; 417 lpedmo->hkey = NULL; 418 419 hr = dup_partial_mediatype(pInTypes, cInTypes, &lpedmo->pInTypes); 420 if (FAILED(hr)) 421 goto lerr; 422 423 hr = dup_partial_mediatype(pOutTypes, cOutTypes, &lpedmo->pOutTypes); 424 if (FAILED(hr)) 425 goto lerr; 426 427 /* If not filtering by category enum from media objects root */ 428 if (IsEqualGUID(guidCategory, &GUID_NULL)) 429 { 430 RegOpenKeyExW(HKEY_CLASSES_ROOT, szDMORootKey, 0, KEY_READ, &lpedmo->hkey); 431 } 432 else 433 { 434 WCHAR szguid[64]; 435 WCHAR szKey[MAX_PATH]; 436 437 wsprintfW(szKey, szCat3Fmt, szDMORootKey, szDMOCategories, GUIDToString(szguid, guidCategory)); 438 RegOpenKeyExW(HKEY_CLASSES_ROOT, szKey, 0, KEY_READ, &lpedmo->hkey); 439 } 440 441 lerr: 442 443 if (FAILED(hr)) 444 IEnumDMO_Release(&lpedmo->IEnumDMO_iface); 445 else 446 { 447 TRACE("returning %p\n", lpedmo); 448 *obj = &lpedmo->IEnumDMO_iface; 449 } 450 451 return hr; 452 } 453 454 /****************************************************************************** 455 * IEnumDMO_fnAddRef 456 */ 457 static ULONG WINAPI IEnumDMO_fnAddRef(IEnumDMO * iface) 458 { 459 IEnumDMOImpl *This = impl_from_IEnumDMO(iface); 460 ULONG refCount = InterlockedIncrement(&This->ref); 461 TRACE("(%p)->(%d)\n", This, refCount); 462 return refCount; 463 } 464 465 /************************************************************************** 466 * EnumDMO_QueryInterface 467 */ 468 static HRESULT WINAPI IEnumDMO_fnQueryInterface(IEnumDMO* iface, REFIID riid, void **ppvObj) 469 { 470 IEnumDMOImpl *This = impl_from_IEnumDMO(iface); 471 472 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObj); 473 474 *ppvObj = NULL; 475 476 if (IsEqualIID(riid, &IID_IEnumDMO) || 477 IsEqualIID(riid, &IID_IUnknown)) 478 { 479 *ppvObj = iface; 480 IEnumDMO_AddRef(iface); 481 } 482 483 return *ppvObj ? S_OK : E_NOINTERFACE; 484 } 485 486 /****************************************************************************** 487 * IEnumDMO_fnRelease 488 */ 489 static ULONG WINAPI IEnumDMO_fnRelease(IEnumDMO * iface) 490 { 491 IEnumDMOImpl *This = impl_from_IEnumDMO(iface); 492 ULONG refCount = InterlockedDecrement(&This->ref); 493 494 TRACE("(%p)->(%d)\n", This, refCount); 495 496 if (!refCount) 497 { 498 if (This->hkey) 499 RegCloseKey(This->hkey); 500 HeapFree(GetProcessHeap(), 0, This->pInTypes); 501 HeapFree(GetProcessHeap(), 0, This->pOutTypes); 502 HeapFree(GetProcessHeap(), 0, This); 503 } 504 return refCount; 505 } 506 507 508 /****************************************************************************** 509 * IEnumDMO_fnNext 510 */ 511 static HRESULT WINAPI IEnumDMO_fnNext( 512 IEnumDMO * iface, 513 DWORD cItemsToFetch, 514 CLSID * pCLSID, 515 WCHAR ** Names, 516 DWORD * pcItemsFetched) 517 { 518 HKEY hkey; 519 WCHAR szNextKey[MAX_PATH]; 520 WCHAR szGuidKey[64]; 521 WCHAR szKey[MAX_PATH]; 522 WCHAR szValue[MAX_PATH]; 523 DWORD len; 524 UINT count = 0; 525 HRESULT hres = S_OK; 526 LONG ret; 527 GUID guid; 528 529 IEnumDMOImpl *This = impl_from_IEnumDMO(iface); 530 531 TRACE("(%p)->(%d %p %p %p)\n", This, cItemsToFetch, pCLSID, Names, pcItemsFetched); 532 533 if (!pCLSID || !Names) 534 return E_POINTER; 535 536 if (!pcItemsFetched && cItemsToFetch > 1) 537 return E_INVALIDARG; 538 539 while (count < cItemsToFetch) 540 { 541 This->index++; 542 543 len = MAX_PATH; 544 ret = RegEnumKeyExW(This->hkey, This->index, szNextKey, &len, NULL, NULL, NULL, NULL); 545 if (ret != ERROR_SUCCESS) 546 { 547 hres = HRESULT_FROM_WIN32(ret); 548 break; 549 } 550 551 if (string_to_guid(szNextKey, &guid) != S_OK) 552 continue; 553 554 TRACE("found %s\n", debugstr_w(szNextKey)); 555 556 if (!(This->dwFlags & DMO_ENUMF_INCLUDE_KEYED)) 557 { 558 wsprintfW(szKey, szCat3Fmt, szDMORootKey, szNextKey, szDMOKeyed); 559 ret = RegOpenKeyExW(HKEY_CLASSES_ROOT, szKey, 0, KEY_READ, &hkey); 560 if (ERROR_SUCCESS == ret) 561 { 562 RegCloseKey(hkey); 563 /* Skip Keyed entries */ 564 continue; 565 } 566 } 567 568 wsprintfW(szKey, szCat2Fmt, szDMORootKey, szNextKey); 569 ret = RegOpenKeyExW(HKEY_CLASSES_ROOT, szKey, 0, KEY_READ, &hkey); 570 TRACE("testing %s\n", debugstr_w(szKey)); 571 572 if (This->pInTypes) 573 { 574 UINT i, j; 575 DWORD cInTypes; 576 DMO_PARTIAL_MEDIATYPE* pInTypes; 577 578 hres = read_types(hkey, szDMOInputType, &cInTypes, 579 sizeof(szValue)/sizeof(DMO_PARTIAL_MEDIATYPE), 580 (DMO_PARTIAL_MEDIATYPE*)szValue); 581 582 if (FAILED(hres)) 583 { 584 RegCloseKey(hkey); 585 continue; 586 } 587 588 pInTypes = (DMO_PARTIAL_MEDIATYPE *)szValue; 589 590 TRACE("read %d intypes for %s:\n", cInTypes, debugstr_w(szKey)); 591 for (i = 0; i < cInTypes; i++) { 592 TRACE("intype %d: type %s, subtype %s\n", i, debugstr_guid(&pInTypes[i].type), 593 debugstr_guid(&pInTypes[i].subtype)); 594 } 595 596 for (i = 0; i < This->cInTypes; i++) 597 { 598 for (j = 0; j < cInTypes; j++) 599 { 600 if (IsMediaTypeEqual(&pInTypes[j], &This->pInTypes[i])) 601 break; 602 } 603 604 if (j >= cInTypes) 605 break; 606 } 607 608 if (i < This->cInTypes) 609 { 610 RegCloseKey(hkey); 611 continue; 612 } 613 } 614 615 if (This->pOutTypes) 616 { 617 UINT i, j; 618 DWORD cOutTypes; 619 DMO_PARTIAL_MEDIATYPE* pOutTypes; 620 621 hres = read_types(hkey, szDMOOutputType, &cOutTypes, 622 sizeof(szValue)/sizeof(DMO_PARTIAL_MEDIATYPE), 623 (DMO_PARTIAL_MEDIATYPE*)szValue); 624 625 if (FAILED(hres)) 626 { 627 RegCloseKey(hkey); 628 continue; 629 } 630 631 pOutTypes = (DMO_PARTIAL_MEDIATYPE *)szValue; 632 633 TRACE("read %d outtypes for %s:\n", cOutTypes, debugstr_w(szKey)); 634 for (i = 0; i < cOutTypes; i++) { 635 TRACE("outtype %d: type %s, subtype %s\n", i, debugstr_guid(&pOutTypes[i].type), 636 debugstr_guid(&pOutTypes[i].subtype)); 637 } 638 639 for (i = 0; i < This->cOutTypes; i++) 640 { 641 for (j = 0; j < cOutTypes; j++) 642 { 643 if (IsMediaTypeEqual(&pOutTypes[j], &This->pOutTypes[i])) 644 break; 645 } 646 647 if (j >= cOutTypes) 648 break; 649 } 650 651 if (i < This->cOutTypes) 652 { 653 RegCloseKey(hkey); 654 continue; 655 } 656 } 657 658 /* Media object wasn't filtered so add it to return list */ 659 Names[count] = NULL; 660 len = MAX_PATH * sizeof(WCHAR); 661 ret = RegQueryValueExW(hkey, NULL, NULL, NULL, (LPBYTE)szValue, &len); 662 if (ERROR_SUCCESS == ret) 663 { 664 Names[count] = CoTaskMemAlloc((strlenW(szValue) + 1) * sizeof(WCHAR)); 665 if (Names[count]) 666 strcpyW(Names[count], szValue); 667 } 668 wsprintfW(szGuidKey,szToGuidFmt,szNextKey); 669 CLSIDFromString(szGuidKey, &pCLSID[count]); 670 671 TRACE("found match %s %s\n", debugstr_w(szValue), debugstr_w(szNextKey)); 672 RegCloseKey(hkey); 673 count++; 674 } 675 676 if (pcItemsFetched) *pcItemsFetched = count; 677 if (count < cItemsToFetch) 678 hres = S_FALSE; 679 680 TRACE("<-- %i found\n",count); 681 return hres; 682 } 683 684 685 /****************************************************************************** 686 * IEnumDMO_fnSkip 687 */ 688 static HRESULT WINAPI IEnumDMO_fnSkip(IEnumDMO * iface, DWORD cItemsToSkip) 689 { 690 IEnumDMOImpl *This = impl_from_IEnumDMO(iface); 691 692 TRACE("(%p)->(%d)\n", This, cItemsToSkip); 693 This->index += cItemsToSkip; 694 695 return S_OK; 696 } 697 698 699 /****************************************************************************** 700 * IEnumDMO_fnReset 701 */ 702 static HRESULT WINAPI IEnumDMO_fnReset(IEnumDMO * iface) 703 { 704 IEnumDMOImpl *This = impl_from_IEnumDMO(iface); 705 706 TRACE("(%p)\n", This); 707 This->index = -1; 708 709 return S_OK; 710 } 711 712 713 /****************************************************************************** 714 * IEnumDMO_fnClone 715 */ 716 static HRESULT WINAPI IEnumDMO_fnClone(IEnumDMO *iface, IEnumDMO **ppEnum) 717 { 718 IEnumDMOImpl *This = impl_from_IEnumDMO(iface); 719 TRACE("(%p)->(%p)\n", This, ppEnum); 720 return IEnumDMO_Constructor(&This->category, This->dwFlags, This->cInTypes, This->pInTypes, 721 This->cOutTypes, This->pOutTypes, ppEnum); 722 } 723 724 725 /*************************************************************** 726 * DMOEnum (MSDMO.@) 727 * 728 * Enumerate DirectX Media Objects in the registry. 729 */ 730 HRESULT WINAPI DMOEnum( 731 REFGUID category, 732 DWORD flags, 733 DWORD cInTypes, 734 const DMO_PARTIAL_MEDIATYPE *pInTypes, 735 DWORD cOutTypes, 736 const DMO_PARTIAL_MEDIATYPE *pOutTypes, 737 IEnumDMO **ppEnum) 738 { 739 TRACE("%s 0x%08x %d %p %d %p %p\n", debugstr_guid(category), flags, cInTypes, pInTypes, 740 cOutTypes, pOutTypes, ppEnum); 741 742 if (TRACE_ON(msdmo)) 743 { 744 DWORD i; 745 if (cInTypes) 746 { 747 for (i = 0; i < cInTypes; i++) 748 TRACE("intype %d - type %s, subtype %s\n", i, debugstr_guid(&pInTypes[i].type), 749 debugstr_guid(&pInTypes[i].subtype)); 750 } 751 752 if (cOutTypes) { 753 for (i = 0; i < cOutTypes; i++) 754 TRACE("outtype %d - type %s, subtype %s\n", i, debugstr_guid(&pOutTypes[i].type), 755 debugstr_guid(&pOutTypes[i].subtype)); 756 } 757 } 758 759 return IEnumDMO_Constructor(category, flags, cInTypes, 760 pInTypes, cOutTypes, pOutTypes, ppEnum); 761 } 762 763 764 static const IEnumDMOVtbl edmovt = 765 { 766 IEnumDMO_fnQueryInterface, 767 IEnumDMO_fnAddRef, 768 IEnumDMO_fnRelease, 769 IEnumDMO_fnNext, 770 IEnumDMO_fnSkip, 771 IEnumDMO_fnReset, 772 IEnumDMO_fnClone, 773 }; 774 775 776 HRESULT read_types(HKEY root, LPCWSTR key, ULONG *supplied, ULONG requested, DMO_PARTIAL_MEDIATYPE* types ) 777 { 778 HRESULT ret = S_OK; 779 780 if (MSDMO_MAJOR_VERSION > 5) 781 { 782 DWORD len; 783 LONG rc; 784 785 len = requested * sizeof(DMO_PARTIAL_MEDIATYPE); 786 rc = RegQueryValueExW(root, key, NULL, NULL, (LPBYTE) types, &len); 787 ret = HRESULT_FROM_WIN32(rc); 788 789 *supplied = len / sizeof(DMO_PARTIAL_MEDIATYPE); 790 } 791 else 792 { 793 HKEY hkey; 794 WCHAR szGuidKey[64]; 795 796 *supplied = 0; 797 if (ERROR_SUCCESS == RegOpenKeyExW(root, key, 0, KEY_READ, &hkey)) 798 { 799 int index = 0; 800 WCHAR szNextKey[MAX_PATH]; 801 DWORD len; 802 LONG rc = ERROR_SUCCESS; 803 804 while (rc == ERROR_SUCCESS) 805 { 806 len = MAX_PATH; 807 rc = RegEnumKeyExW(hkey, index, szNextKey, &len, NULL, NULL, NULL, NULL); 808 if (rc == ERROR_SUCCESS) 809 { 810 HKEY subk; 811 int sub_index = 0; 812 LONG rcs = ERROR_SUCCESS; 813 WCHAR szSubKey[MAX_PATH]; 814 815 RegOpenKeyExW(hkey, szNextKey, 0, KEY_READ, &subk); 816 while (rcs == ERROR_SUCCESS) 817 { 818 len = MAX_PATH; 819 rcs = RegEnumKeyExW(subk, sub_index, szSubKey, &len, NULL, NULL, NULL, NULL); 820 if (rcs == ERROR_SUCCESS) 821 { 822 if (*supplied >= requested) 823 { 824 /* Bailing */ 825 ret = S_FALSE; 826 rc = ERROR_MORE_DATA; 827 rcs = ERROR_MORE_DATA; 828 break; 829 } 830 831 wsprintfW(szGuidKey,szToGuidFmt,szNextKey); 832 CLSIDFromString(szGuidKey, &types[*supplied].type); 833 wsprintfW(szGuidKey,szToGuidFmt,szSubKey); 834 CLSIDFromString(szGuidKey, &types[*supplied].subtype); 835 TRACE("Adding type %s subtype %s at index %i\n", 836 debugstr_guid(&types[*supplied].type), 837 debugstr_guid(&types[*supplied].subtype), 838 *supplied); 839 (*supplied)++; 840 } 841 sub_index++; 842 } 843 index++; 844 } 845 } 846 RegCloseKey(hkey); 847 } 848 } 849 return ret; 850 } 851 852 /*************************************************************** 853 * DMOGetTypes (MSDMO.@) 854 */ 855 HRESULT WINAPI DMOGetTypes(REFCLSID clsidDMO, 856 ULONG ulInputTypesRequested, 857 ULONG* pulInputTypesSupplied, 858 DMO_PARTIAL_MEDIATYPE* pInputTypes, 859 ULONG ulOutputTypesRequested, 860 ULONG* pulOutputTypesSupplied, 861 DMO_PARTIAL_MEDIATYPE* pOutputTypes) 862 { 863 HKEY root,hkey; 864 HRESULT ret = S_OK; 865 WCHAR szguid[64]; 866 867 TRACE ("(%s,%u,%p,%p,%u,%p,%p)\n", debugstr_guid(clsidDMO), ulInputTypesRequested, 868 pulInputTypesSupplied, pInputTypes, ulOutputTypesRequested, pulOutputTypesSupplied, 869 pOutputTypes); 870 871 if (ERROR_SUCCESS != RegOpenKeyExW(HKEY_CLASSES_ROOT, szDMORootKey, 0, 872 KEY_READ, &root)) 873 return E_FAIL; 874 875 if (ERROR_SUCCESS != RegOpenKeyExW(root,GUIDToString(szguid,clsidDMO) , 0, 876 KEY_READ, &hkey)) 877 { 878 RegCloseKey(root); 879 return E_FAIL; 880 } 881 882 if (ulInputTypesRequested > 0) 883 { 884 ret = read_types(hkey, szDMOInputType, pulInputTypesSupplied, ulInputTypesRequested, pInputTypes ); 885 } 886 else 887 *pulInputTypesSupplied = 0; 888 889 if (ulOutputTypesRequested > 0) 890 { 891 HRESULT ret2; 892 ret2 = read_types(hkey, szDMOOutputType, pulOutputTypesSupplied, ulOutputTypesRequested, pOutputTypes ); 893 894 if (ret == S_OK) 895 ret = ret2; 896 } 897 else 898 *pulOutputTypesSupplied = 0; 899 900 return ret; 901 } 902