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