Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

785 lines
24 KiB

  1. // Copyright (c) 1999 Microsoft Corporation. All Rights Reserved.
  2. //
  3. // regenum.cpp - registration/enumeration part of DMO runtime
  4. //
  5. #include <windows.h>
  6. #include <tchar.h>
  7. #include "dmoreg.h"
  8. #include "guidenum.h"
  9. #include "shlwapi.h"
  10. #include "dmoutils.h"
  11. #define DMO_REGISTRY_HIVE HKEY_CLASSES_ROOT
  12. #define DMO_REGISTRY_PATH TEXT("DirectShow\\MediaObjects")
  13. #define INPUT_TYPES_STR "InputTypes"
  14. #define OUTPUT_TYPES_STR "OutputTypes"
  15. #define SUBTYPES_STR "Subtypes"
  16. #define KEYED_STR "Keyed"
  17. #define CATEGORIES_STR "Categories"
  18. #ifndef CHARS_IN_GUID
  19. #define CHARS_IN_GUID 39
  20. #endif
  21. // Helper copied from shwapi
  22. /*----------------------------------------------------------
  23. Purpose: Recursively delete the key, including all child values
  24. and keys. Mimics what RegDeleteKey does in Win95.
  25. Returns:
  26. Cond: --
  27. */
  28. DWORD
  29. DeleteKeyRecursively(
  30. IN HKEY hkey,
  31. IN LPCTSTR pszSubKey)
  32. {
  33. DWORD dwRet;
  34. HKEY hkSubKey;
  35. // Open the subkey so we can enumerate any children
  36. dwRet = RegOpenKey(hkey, pszSubKey, &hkSubKey);
  37. if (ERROR_SUCCESS == dwRet)
  38. {
  39. DWORD dwIndex;
  40. TCHAR szSubKeyName[MAX_PATH + 1];
  41. DWORD cchSubKeyName = sizeof(szSubKeyName) / sizeof(szSubKeyName[0]);
  42. TCHAR szClass[MAX_PATH];
  43. DWORD cbClass = sizeof(szClass) / sizeof(szClass[0]);
  44. // I can't just call RegEnumKey with an ever-increasing index, because
  45. // I'm deleting the subkeys as I go, which alters the indices of the
  46. // remaining subkeys in an implementation-dependent way. In order to
  47. // be safe, I have to count backwards while deleting the subkeys.
  48. // Find out how many subkeys there are
  49. dwRet = RegQueryInfoKey(hkSubKey,
  50. szClass,
  51. &cbClass,
  52. NULL,
  53. &dwIndex, // The # of subkeys -- all we need
  54. NULL,
  55. NULL,
  56. NULL,
  57. NULL,
  58. NULL,
  59. NULL,
  60. NULL);
  61. if (NO_ERROR == dwRet && dwIndex > 0)
  62. {
  63. // dwIndex is now the count of subkeys, but it needs to be
  64. // zero-based for RegEnumKey, so I'll pre-decrement, rather
  65. // than post-decrement.
  66. while (ERROR_SUCCESS == RegEnumKey(hkSubKey, --dwIndex, szSubKeyName, cchSubKeyName))
  67. {
  68. DeleteKeyRecursively(hkSubKey, szSubKeyName);
  69. }
  70. }
  71. RegCloseKey(hkSubKey);
  72. dwRet = RegDeleteKey(hkey, pszSubKey);
  73. }
  74. return dwRet;
  75. }
  76. // Automatically calls RegCloseKey when leaving scope
  77. class CAutoHKey {
  78. public:
  79. CAutoHKey() : m_hKey(NULL) {}
  80. ~CAutoHKey() {
  81. if (m_hKey)
  82. RegCloseKey(m_hKey);
  83. }
  84. LRESULT Create(HKEY hKey, LPCTSTR szSubKey)
  85. {
  86. return RegCreateKey(hKey, szSubKey, &m_hKey);
  87. }
  88. LRESULT Open(HKEY hKey, LPCTSTR szSubKey)
  89. {
  90. return RegOpenKey(hKey, szSubKey, &m_hKey);
  91. }
  92. void Close()
  93. {
  94. if (m_hKey) {
  95. RegCloseKey(m_hKey);
  96. }
  97. m_hKey = NULL;
  98. }
  99. HKEY m_hKey;
  100. HKEY Key() const { return m_hKey; }
  101. };
  102. // Automatically calls RegCloseKey when leaving scope
  103. class CAutoCreateHKey {
  104. public:
  105. CAutoCreateHKey(HKEY hKey, TCHAR* szSubKey, HKEY *phKey) {
  106. if (RegCreateKeyEx(hKey,
  107. szSubKey,
  108. 0,
  109. TEXT(""),
  110. REG_OPTION_NON_VOLATILE,
  111. MAXIMUM_ALLOWED,
  112. NULL,
  113. phKey,
  114. NULL) != ERROR_SUCCESS)
  115. m_hKey = *phKey = NULL;
  116. else
  117. m_hKey = *phKey;
  118. }
  119. ~CAutoCreateHKey() {
  120. if (m_hKey)
  121. RegCloseKey(m_hKey);
  122. }
  123. HKEY m_hKey;
  124. };
  125. class CAutoOpenHKey {
  126. public:
  127. CAutoOpenHKey(HKEY hKey, TCHAR* szSubKey, HKEY *phKey, REGSAM samDesired = KEY_READ) {
  128. if (RegOpenKeyEx(hKey,
  129. szSubKey,
  130. 0,
  131. samDesired,
  132. phKey) != ERROR_SUCCESS)
  133. m_hKey = *phKey = NULL;
  134. else
  135. m_hKey = *phKey;
  136. }
  137. ~CAutoOpenHKey() {
  138. if (m_hKey)
  139. RegCloseKey(m_hKey);
  140. }
  141. HKEY m_hKey;
  142. };
  143. HRESULT ReadTypesFromKeys(HKEY hkDMO, LPCTSTR pszTypes, DWORD *pcbData, PVOID *ppvData)
  144. {
  145. // Collect all the types into 1 value - need to enumerate
  146. // keys and subkeys
  147. LPVOID pMem = CoTaskMemAlloc(0);
  148. unsigned int nEntries = 0;
  149. DWORD dwTypeIndex;
  150. BOOL bSuccess = TRUE;
  151. DMO_PARTIAL_MEDIATYPE Type;
  152. CAutoHKey hkSrc;
  153. if (NOERROR != hkSrc.Open(hkDMO, pszTypes)) {
  154. bSuccess = FALSE;
  155. }
  156. for (dwTypeIndex = 0; bSuccess; dwTypeIndex++) {
  157. TCHAR szType[MAX_PATH];
  158. LONG lResult = RegEnumKey(hkSrc.Key(), dwTypeIndex, szType, MAX_PATH);
  159. if (NOERROR != lResult) {
  160. if (ERROR_NO_MORE_ITEMS != lResult) {
  161. bSuccess = FALSE;
  162. }
  163. break;
  164. }
  165. if (DMOStrToGuid(szType, &Type.type)) {
  166. CAutoHKey kType;
  167. kType.Open(hkSrc.Key(), szType);
  168. if (NULL == kType.Key()) {
  169. bSuccess = FALSE;
  170. } else {
  171. DWORD dwSubtypeIndex;
  172. for (dwSubtypeIndex = 0; bSuccess; dwSubtypeIndex++) {
  173. TCHAR szSubtype[MAX_PATH];
  174. lResult = RegEnumKey(kType.Key(), dwSubtypeIndex, szSubtype, MAX_PATH);
  175. if (NOERROR != lResult) {
  176. if (ERROR_NO_MORE_ITEMS != lResult) {
  177. bSuccess = FALSE;
  178. }
  179. break;
  180. }
  181. if (DMOStrToGuid(szSubtype, &Type.subtype)) {
  182. // Add to our list
  183. LPVOID pMemNew = CoTaskMemRealloc(pMem,
  184. (nEntries + 1) * sizeof(DMO_PARTIAL_MEDIATYPE));
  185. if (NULL == pMemNew) {
  186. bSuccess = FALSE;
  187. } else {
  188. pMem = pMemNew;
  189. CopyMemory((LPBYTE)pMem +
  190. nEntries * sizeof(DMO_PARTIAL_MEDIATYPE),
  191. &Type,
  192. sizeof(DMO_PARTIAL_MEDIATYPE));
  193. nEntries++;
  194. }
  195. }
  196. }
  197. }
  198. }
  199. }
  200. if (bSuccess && nEntries != 0) {
  201. *ppvData = pMem;
  202. *pcbData = nEntries * sizeof(DMO_PARTIAL_MEDIATYPE);
  203. return S_OK;
  204. } else {
  205. CoTaskMemFree(pMem);
  206. return S_FALSE;
  207. }
  208. }
  209. HRESULT ReadTypes(HKEY hkDMO, LPCTSTR pszTypes, DWORD *pcbData, PVOID *ppvData)
  210. {
  211. *pcbData = 0;
  212. // Try reading the value first
  213. DWORD cbData;
  214. if (NOERROR != RegQueryValueEx(hkDMO, pszTypes, NULL, NULL, NULL, &cbData)) {
  215. return ReadTypesFromKeys(hkDMO, pszTypes, pcbData, ppvData);
  216. }
  217. if (cbData == 0) {
  218. return S_OK;
  219. }
  220. PVOID pvData = (PBYTE)CoTaskMemAlloc(cbData);
  221. if (NULL == pvData) {
  222. return E_OUTOFMEMORY;
  223. }
  224. if (NOERROR == RegQueryValueEx(hkDMO, pszTypes, NULL, NULL, (PBYTE)pvData, &cbData)) {
  225. *ppvData = pvData;
  226. *pcbData = cbData;
  227. return S_OK;
  228. } else {
  229. CoTaskMemFree(pvData);
  230. return E_OUTOFMEMORY;
  231. }
  232. }
  233. /////////////////////////////////////////////////////////////////////////////
  234. //
  235. // DMO Registration code
  236. //
  237. // Registration helper
  238. void CreateObjectGuidKey(HKEY hKey, REFCLSID clsidDMO) {
  239. TCHAR szSubkeyName[80];
  240. HKEY hObjectGuidKey;
  241. DMOGuidToStr(szSubkeyName, clsidDMO);
  242. CAutoCreateHKey kGuid(hKey, szSubkeyName, &hObjectGuidKey);
  243. }
  244. // Registration helper
  245. // Registers types\subtypes underneath the object's key
  246. void RegisterTypes(HKEY hObjectKey,
  247. TCHAR* szInputOrOutput,
  248. ULONG ulTypes,
  249. const DMO_PARTIAL_MEDIATYPE* pTypes) {
  250. RegSetValueEx(hObjectKey, szInputOrOutput, 0, REG_BINARY,
  251. (const BYTE *)pTypes,
  252. ulTypes * sizeof(DMO_PARTIAL_MEDIATYPE));
  253. }
  254. //
  255. // Public entry point
  256. //
  257. STDAPI DMORegister(
  258. LPCWSTR szName,
  259. REFCLSID clsidDMO,
  260. REFGUID guidCategory,
  261. DWORD dwFlags, // DMO_REGISTERF_XXX
  262. unsigned long ulInTypes,
  263. const DMO_PARTIAL_MEDIATYPE *pInTypes,
  264. unsigned long ulOutTypes,
  265. const DMO_PARTIAL_MEDIATYPE *pOutTypes
  266. ) {
  267. TCHAR szSubkeyName[80];
  268. if ((clsidDMO == GUID_NULL) || (guidCategory == GUID_NULL))
  269. return E_INVALIDARG;
  270. // Create/open the main DMO key
  271. HKEY hMainKey;
  272. CAutoCreateHKey kMain(DMO_REGISTRY_HIVE, DMO_REGISTRY_PATH, &hMainKey);
  273. if (hMainKey == NULL)
  274. return E_FAIL;
  275. HKEY hCategoriesKey;
  276. CAutoCreateHKey kCats(hMainKey, TEXT(CATEGORIES_STR), &hCategoriesKey);
  277. if (hCategoriesKey == NULL)
  278. return E_FAIL;
  279. // Create/open the category specific subkey underneath the main key
  280. DMOGuidToStr(szSubkeyName, guidCategory);
  281. HKEY hCategoryKey;
  282. CAutoCreateHKey kCat(hCategoriesKey, szSubkeyName, &hCategoryKey);
  283. if (hCategoryKey == NULL)
  284. return E_FAIL;
  285. // Deletet the redundant old types keys
  286. DeleteKeyRecursively(hCategoryKey, TEXT(INPUT_TYPES_STR));
  287. DeleteKeyRecursively(hCategoryKey, TEXT(OUTPUT_TYPES_STR));
  288. // If the category key does not have a name yet, add one
  289. DWORD cbName;
  290. DWORD dwType;
  291. if ((RegQueryValueEx(hCategoryKey, NULL, NULL, &dwType, NULL, &cbName) != ERROR_SUCCESS) ||
  292. (cbName <= sizeof(TCHAR)) || (REG_SZ != dwType)) {
  293. TCHAR* szName;
  294. if (guidCategory == DMOCATEGORY_AUDIO_DECODER)
  295. szName = TEXT("Audio decoders");
  296. else if (guidCategory == DMOCATEGORY_AUDIO_ENCODER)
  297. szName = TEXT("Audio encoders");
  298. else if (guidCategory == DMOCATEGORY_VIDEO_DECODER)
  299. szName = TEXT("Video decoders");
  300. else if (guidCategory == DMOCATEGORY_VIDEO_ENCODER)
  301. szName = TEXT("Video encoders");
  302. else if (guidCategory == DMOCATEGORY_AUDIO_EFFECT)
  303. szName = TEXT("Audio effects");
  304. else if (guidCategory == DMOCATEGORY_VIDEO_EFFECT)
  305. szName = TEXT("Video effects");
  306. else if (guidCategory == DMOCATEGORY_AUDIO_CAPTURE_EFFECT)
  307. szName = TEXT("Audio capture effects");
  308. else if (guidCategory == DMOCATEGORY_ACOUSTIC_ECHO_CANCEL)
  309. szName = TEXT("Acoustic Echo Canceller");
  310. else if (guidCategory == DMOCATEGORY_AUDIO_NOISE_SUPPRESS)
  311. szName = TEXT("Audio Noise Suppressor");
  312. else if (guidCategory == DMOCATEGORY_AGC)
  313. szName = TEXT("Automatic Gain Control");
  314. else
  315. szName = TEXT("Unknown DMO category");
  316. RegSetValue(hCategoryKey, NULL, REG_SZ, szName, lstrlen(szName) * sizeof(TCHAR));
  317. }
  318. // Create/open the object specific key underneath the category key
  319. DMOGuidToStr(szSubkeyName, clsidDMO);
  320. // Remove the old one
  321. DeleteKeyRecursively(hMainKey, szSubkeyName);
  322. HKEY hObjKey;
  323. CAutoCreateHKey kObj(hCategoryKey, szSubkeyName, &hObjKey);
  324. if (hObjKey == NULL)
  325. return E_FAIL;
  326. // Create/open the object specific key underneath the main key
  327. DMOGuidToStr(szSubkeyName, clsidDMO); // BUGBUG: redundant
  328. HKEY hObjectKey;
  329. CAutoCreateHKey kObject(hMainKey, szSubkeyName, &hObjectKey);
  330. if (hObjectKey == NULL)
  331. return E_FAIL;
  332. // set the default value of the object key to the name of the DMO
  333. #ifdef UNICODE
  334. LPCWSTR sz = szName;
  335. #else
  336. char sz[80];
  337. WideCharToMultiByte(0,0,szName,-1,sz,80,NULL,NULL);
  338. #endif
  339. if (RegSetValue(hObjectKey, NULL, REG_SZ, sz, lstrlen(sz) * sizeof(TCHAR))
  340. != ERROR_SUCCESS)
  341. return E_FAIL;
  342. // If the object is keyed, add a registry value indicating so
  343. if (dwFlags & DMO_REGISTERF_IS_KEYED) {
  344. if (RegSetValue(hObjectKey, TEXT(KEYED_STR), REG_SZ, TEXT(""), 0)
  345. != ERROR_SUCCESS)
  346. return E_FAIL;
  347. }
  348. // Register types
  349. if (ulInTypes) {
  350. RegisterTypes(hObjectKey, TEXT(INPUT_TYPES_STR), ulInTypes, pInTypes);
  351. }
  352. if (ulOutTypes) {
  353. RegisterTypes(hObjectKey, TEXT(OUTPUT_TYPES_STR),ulOutTypes,pOutTypes);
  354. }
  355. // Nuke the DShow filter cache
  356. DeleteKeyRecursively(HKEY_CURRENT_USER, TEXT("Software\\Microsoft\\Multimedia\\ActiveMovie\\Filter Cache"));
  357. return NOERROR;
  358. }
  359. // helper
  360. void MakeSubkeyName (TCHAR* szSubkeyName,
  361. REFGUID guidCategory,
  362. REFCLSID clsidDMO) {
  363. DMOGuidToStr(szSubkeyName, guidCategory);
  364. _tcscat(szSubkeyName, TEXT("\\"));
  365. DMOGuidToStr(szSubkeyName + lstrlen(szSubkeyName), clsidDMO);
  366. }
  367. //
  368. // Public entry point
  369. //
  370. STDAPI DMOUnregister(
  371. REFCLSID clsidDMO,
  372. REFGUID guidCategory
  373. ) {
  374. HRESULT hr;
  375. // open the root DMO key
  376. HKEY hMainKey;
  377. CAutoOpenHKey kMain(DMO_REGISTRY_HIVE, DMO_REGISTRY_PATH, &hMainKey, MAXIMUM_ALLOWED);
  378. if (hMainKey == NULL)
  379. return E_FAIL;
  380. // open the "Categories" key underneath the root key
  381. HKEY hCategoriesKey;
  382. CAutoOpenHKey kCats(hMainKey, TEXT(CATEGORIES_STR), &hCategoriesKey, MAXIMUM_ALLOWED);
  383. if (hCategoriesKey == NULL)
  384. return E_FAIL;
  385. // Iterate through all categories attempting to delete from each one
  386. TCHAR szCategory[80];
  387. DWORD dwIndex = 0;
  388. BOOL bDeletedAnything = FALSE;
  389. BOOL bDeletedAll = TRUE;
  390. DMOGuidToStr(szCategory, guidCategory);
  391. while (RegEnumKey(hCategoriesKey, dwIndex, szCategory, 80) == ERROR_SUCCESS) {
  392. // process the subkey only if it resembles a category GUID
  393. GUID guid;
  394. if (DMOStrToGuid(szCategory, &guid)) {
  395. // Try to delete from this category
  396. TCHAR szSubkeyName[256];
  397. MakeSubkeyName(szSubkeyName, guid, clsidDMO);
  398. if (guidCategory == GUID_NULL || guid == guidCategory) {
  399. if (DeleteKeyRecursively(hCategoriesKey, szSubkeyName) == ERROR_SUCCESS)
  400. bDeletedAnything = TRUE;
  401. } else {
  402. CAutoHKey hk;
  403. if (ERROR_FILE_NOT_FOUND != hk.Open(hCategoriesKey, szSubkeyName)) {
  404. bDeletedAll = FALSE;
  405. }
  406. }
  407. }
  408. dwIndex++;
  409. }
  410. if (bDeletedAnything) {
  411. hr = S_OK;
  412. if (bDeletedAll) {
  413. // Now delete this object's key from underneath the root DMO key
  414. TCHAR szGuid[CHARS_IN_GUID];
  415. DMOGuidToStr(szGuid, clsidDMO);
  416. if (DeleteKeyRecursively(hMainKey, szGuid) != ERROR_SUCCESS) {
  417. hr = S_FALSE;
  418. }
  419. }
  420. }
  421. else
  422. hr = S_FALSE;
  423. return hr;
  424. }
  425. //
  426. // End DMO Registration code
  427. //
  428. /////////////////////////////////////////////////////////////////////////////
  429. /////////////////////////////////////////////////////////////////////////////
  430. //
  431. // DMO Enumeration code
  432. // Some of it leaves room for future improvements in terms of speed
  433. //
  434. // helper
  435. HRESULT ReadName(HKEY hDMOKey, WCHAR szName[80]) {
  436. LONG cbSize = 80;
  437. #ifdef UNICODE
  438. if (RegQueryValue(hDMOKey, NULL, szName, &cbSize) == ERROR_SUCCESS)
  439. return S_OK;
  440. #else
  441. char szTmp[80];
  442. if (RegQueryValue(hDMOKey, NULL, szTmp, &cbSize) == ERROR_SUCCESS) {
  443. MultiByteToWideChar(0,0,szTmp,-1,szName,80);
  444. return S_OK;
  445. }
  446. #endif
  447. else {
  448. szName[0] = L'\0'; // no name - corrupt registry ?
  449. return S_FALSE;
  450. }
  451. }
  452. // Enumeration helper, does what the name says
  453. void LookupNameAndAddToEnum(HKEY hObjectKey,
  454. TCHAR* szGuid,
  455. DWORD dwFlags,
  456. REFCLSID clsidDMO,
  457. CEnumDMOCLSID* pEnum) {
  458. // Skip keyed DMOs unless explicitly asked to include them
  459. if (!(dwFlags & DMO_ENUMF_INCLUDE_KEYED)) {
  460. // open the DMO's registry key
  461. LONG cbValue;
  462. if (RegQueryValue(hObjectKey, TEXT(KEYED_STR), NULL, &cbValue)
  463. == ERROR_SUCCESS)
  464. return; // DMO is keyed - skip
  465. }
  466. WCHAR szName[80];
  467. if (FAILED(ReadName(hObjectKey, szName)))
  468. szName[0] = L'\0';
  469. pEnum->Add(clsidDMO, szName);
  470. }
  471. // Check if any of the requested types match
  472. // If no requested types are specified then this is treated
  473. // as a match
  474. BOOL CompareTypes(HKEY hkDMO,
  475. unsigned long ulTypes,
  476. const DMO_PARTIAL_MEDIATYPE *pTypes,
  477. LPCTSTR pszTypesValue)
  478. {
  479. if (ulTypes == 0) {
  480. return TRUE;
  481. }
  482. DWORD cbData;
  483. PVOID pvDMOTypes = NULL;
  484. if (S_OK == ReadTypes(hkDMO, pszTypesValue, &cbData, &pvDMOTypes)) {
  485. for (unsigned long ulType = 0; ulType < ulTypes; ulType++) {
  486. DMO_PARTIAL_MEDIATYPE *pDMOTypes = (DMO_PARTIAL_MEDIATYPE *)pvDMOTypes;
  487. while ((PBYTE)(pDMOTypes + 1) <= (PBYTE)pvDMOTypes + cbData) {
  488. if (pDMOTypes->type == pTypes[ulType].type ||
  489. pDMOTypes->type == GUID_NULL ||
  490. pTypes[ulType].type == GUID_NULL) {
  491. if (pTypes[ulType].subtype == GUID_NULL ||
  492. pDMOTypes->subtype == GUID_NULL ||
  493. pTypes[ulType].subtype == pDMOTypes->subtype) {
  494. CoTaskMemFree(pvDMOTypes);
  495. return TRUE;
  496. }
  497. }
  498. pDMOTypes++;
  499. }
  500. }
  501. }
  502. CoTaskMemFree(pvDMOTypes);
  503. return FALSE;
  504. }
  505. // Enumeration helper
  506. HRESULT EnumerateDMOs(HKEY hMainKey,
  507. HKEY hCatKey,
  508. DWORD dwFlags,
  509. unsigned long ulInputTypes,
  510. const DMO_PARTIAL_MEDIATYPE *pInputTypes,
  511. unsigned long ulOutputTypes,
  512. const DMO_PARTIAL_MEDIATYPE *pOutputTypes,
  513. CEnumDMOCLSID *pEnum) {
  514. DWORD dwIndex = 0;
  515. TCHAR szSubkey[80];
  516. while (RegEnumKey(hCatKey, dwIndex, szSubkey, 80) == ERROR_SUCCESS) {
  517. // Does this look like an object CLSID ?
  518. CLSID clsidDMO;
  519. if (DMOStrToGuid(szSubkey, &clsidDMO)) {
  520. // Do the type match?
  521. CAutoHKey hkDMO;
  522. if (NOERROR == hkDMO.Open(hMainKey, szSubkey)) {
  523. if (CompareTypes(hkDMO.Key(), ulInputTypes, pInputTypes, TEXT(INPUT_TYPES_STR)) &&
  524. CompareTypes(hkDMO.Key(), ulOutputTypes, pOutputTypes, TEXT(OUTPUT_TYPES_STR))) {
  525. LookupNameAndAddToEnum(hkDMO.Key(), szSubkey, dwFlags, clsidDMO, pEnum);
  526. }
  527. }
  528. }
  529. dwIndex++;
  530. }
  531. return S_OK;
  532. }
  533. //
  534. // Public entry point
  535. //
  536. STDAPI DMOEnum(
  537. REFGUID guidCategory, // GUID_NULL for "all"
  538. DWORD dwFlags, // DMO_ENUMF_XXX
  539. unsigned long ulInTypes,
  540. const DMO_PARTIAL_MEDIATYPE *pInTypes, // can be NULL only of ulInTypes = 0
  541. unsigned long ulOutTypes,
  542. const DMO_PARTIAL_MEDIATYPE *pOutTypes,// can be NULL only of ulOutTypes = 0
  543. IEnumDMO **ppEnum
  544. ) {
  545. if (ppEnum == NULL) {
  546. return E_POINTER;
  547. }
  548. if (ulInTypes > 0 && pInTypes == NULL ||
  549. ulOutTypes > 0 && pOutTypes == NULL) {
  550. return E_INVALIDARG;
  551. }
  552. *ppEnum = NULL;
  553. // open the root key
  554. CAutoHKey kMain;
  555. kMain.Open(DMO_REGISTRY_HIVE, DMO_REGISTRY_PATH);
  556. if (kMain.Key() == NULL)
  557. return E_FAIL;
  558. CEnumDMOCLSID *pEnum = new CEnumDMOCLSID();
  559. if (!pEnum)
  560. return E_OUTOFMEMORY;
  561. HRESULT hr = S_OK;
  562. if (guidCategory == GUID_NULL) {
  563. hr = EnumerateDMOs(kMain.Key(),
  564. kMain.Key(),
  565. dwFlags,
  566. ulInTypes,
  567. pInTypes,
  568. ulOutTypes,
  569. pOutTypes,
  570. pEnum);
  571. } else {
  572. // open the subkey for the specified category and enumerate its subkeys
  573. TCHAR szCategory[CHARS_IN_GUID];
  574. TCHAR szCategoryPath[MAX_PATH];
  575. DMOGuidToStr(szCategory, guidCategory);
  576. wsprintf(szCategoryPath, TEXT(CATEGORIES_STR) TEXT("\\%s"), szCategory);
  577. CAutoHKey key2;
  578. key2.Open(kMain.Key(), szCategoryPath);
  579. if (key2.Key()) {
  580. hr = EnumerateDMOs(kMain.Key(),
  581. key2.Key(),
  582. dwFlags,
  583. ulInTypes,
  584. pInTypes,
  585. ulOutTypes,
  586. pOutTypes,
  587. pEnum);
  588. }
  589. }
  590. if (SUCCEEDED(hr)) {
  591. *ppEnum = (IEnumDMO*) pEnum;
  592. hr = S_OK;
  593. } else {
  594. delete pEnum;
  595. }
  596. return hr;
  597. }
  598. // Copy the type information
  599. HRESULT FetchTypeInfo(HKEY hObjKey, LPCTSTR pszTypesValue,
  600. unsigned long ulTypesRequested,
  601. unsigned long *pulTypesSupplied,
  602. DMO_PARTIAL_MEDIATYPE *pTypes)
  603. {
  604. DWORD cbData;
  605. unsigned long ulTypesCopied = 0;
  606. PVOID pvData;
  607. if (S_OK == ReadTypes(hObjKey, pszTypesValue, &cbData, &pvData)) {
  608. ulTypesCopied =
  609. min(ulTypesRequested, cbData / sizeof(DMO_PARTIAL_MEDIATYPE));
  610. CopyMemory(pTypes, pvData,
  611. ulTypesCopied * sizeof(DMO_PARTIAL_MEDIATYPE));
  612. CoTaskMemFree(pvData);
  613. }
  614. *pulTypesSupplied = ulTypesCopied;
  615. return ulTypesCopied != 0 ? S_OK : S_FALSE;
  616. }
  617. // Mediatype helper
  618. HRESULT FetchMediatypeInfo(HKEY hObjKey,
  619. unsigned long ulInputTypesRequested,
  620. unsigned long *pulInputTypesSupplied,
  621. DMO_PARTIAL_MEDIATYPE *pInputTypes,
  622. unsigned long ulOutputTypesRequested,
  623. unsigned long *pulOutputTypesSupplied,
  624. DMO_PARTIAL_MEDIATYPE *pOutputTypes) {
  625. HRESULT hr1 = S_OK;
  626. if (ulInputTypesRequested) {
  627. hr1 = FetchTypeInfo(hObjKey,
  628. TEXT(INPUT_TYPES_STR),
  629. ulInputTypesRequested,
  630. pulInputTypesSupplied,
  631. pInputTypes);
  632. } else {
  633. *pulInputTypesSupplied = 0;
  634. }
  635. HRESULT hr2 = S_OK;
  636. if (ulOutputTypesRequested) {
  637. hr2 = FetchTypeInfo(hObjKey,
  638. TEXT(OUTPUT_TYPES_STR),
  639. ulOutputTypesRequested,
  640. pulOutputTypesSupplied,
  641. pOutputTypes);
  642. } else {
  643. *pulOutputTypesSupplied = 0;
  644. }
  645. if ((hr1 == S_OK) && (hr2 == S_OK))
  646. return S_OK;
  647. else
  648. return S_FALSE;
  649. }
  650. //
  651. // Public entry point
  652. //
  653. STDAPI DMOGetTypes(
  654. REFCLSID clsidDMO,
  655. unsigned long ulInputTypesRequested,
  656. unsigned long *pulInputTypesSupplied,
  657. DMO_PARTIAL_MEDIATYPE *pInputTypes,
  658. unsigned long ulOutputTypesRequested,
  659. unsigned long *pulOutputTypesSupplied,
  660. DMO_PARTIAL_MEDIATYPE *pOutputTypes
  661. ) {
  662. // open the DMO root registry key
  663. HKEY hMainKey;
  664. CAutoOpenHKey kMain(DMO_REGISTRY_HIVE, DMO_REGISTRY_PATH, &hMainKey);
  665. if (hMainKey == NULL)
  666. return E_FAIL;
  667. // open the object specific guid key
  668. TCHAR szGuid[80];
  669. DMOGuidToStr(szGuid, clsidDMO);
  670. HKEY hObjKey;
  671. CAutoOpenHKey kObj(hMainKey, szGuid, &hObjKey);
  672. if (!hObjKey)
  673. return E_FAIL;
  674. return FetchMediatypeInfo(hObjKey,
  675. ulInputTypesRequested,
  676. pulInputTypesSupplied,
  677. pInputTypes,
  678. ulOutputTypesRequested,
  679. pulOutputTypesSupplied,
  680. pOutputTypes);
  681. }
  682. STDAPI DMOGetName(REFCLSID clsidDMO, WCHAR szName[80]) {
  683. // open the DMO root registry key
  684. HKEY hMainKey;
  685. CAutoOpenHKey kMain(DMO_REGISTRY_HIVE, DMO_REGISTRY_PATH, &hMainKey);
  686. if (hMainKey == NULL)
  687. return E_FAIL;
  688. // open the object specific guid key
  689. TCHAR szGuid[80];
  690. DMOGuidToStr(szGuid, clsidDMO);
  691. HKEY hObjKey;
  692. CAutoOpenHKey kObj(hMainKey, szGuid, &hObjKey);
  693. if (!hObjKey)
  694. return E_FAIL;
  695. return ReadName(hObjKey, szName);
  696. }
  697. //
  698. // End DMO Enumeration code
  699. //
  700. /////////////////////////////////////////////////////////////////////////////