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