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