windows-nt/Source/XPSP1/NT/multimedia/dshow/dmo/msdmo/regenum.cpp

786 lines
24 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
// Copyright (c) 1999 Microsoft Corporation. All Rights Reserved.
//
// regenum.cpp - registration/enumeration part of DMO runtime
//
#include <windows.h>
#include <tchar.h>
#include "dmoreg.h"
#include "guidenum.h"
#include "shlwapi.h"
#include "dmoutils.h"
#define DMO_REGISTRY_HIVE HKEY_CLASSES_ROOT
#define DMO_REGISTRY_PATH TEXT("DirectShow\\MediaObjects")
#define INPUT_TYPES_STR "InputTypes"
#define OUTPUT_TYPES_STR "OutputTypes"
#define SUBTYPES_STR "Subtypes"
#define KEYED_STR "Keyed"
#define CATEGORIES_STR "Categories"
#ifndef CHARS_IN_GUID
#define CHARS_IN_GUID 39
#endif
// Helper copied from shwapi
/*----------------------------------------------------------
Purpose: Recursively delete the key, including all child values
and keys. Mimics what RegDeleteKey does in Win95.
Returns:
Cond: --
*/
DWORD
DeleteKeyRecursively(
IN HKEY hkey,
IN LPCTSTR pszSubKey)
{
DWORD dwRet;
HKEY hkSubKey;
// Open the subkey so we can enumerate any children
dwRet = RegOpenKey(hkey, pszSubKey, &hkSubKey);
if (ERROR_SUCCESS == dwRet)
{
DWORD dwIndex;
TCHAR szSubKeyName[MAX_PATH + 1];
DWORD cchSubKeyName = sizeof(szSubKeyName) / sizeof(szSubKeyName[0]);
TCHAR szClass[MAX_PATH];
DWORD cbClass = sizeof(szClass) / sizeof(szClass[0]);
// I can't just call RegEnumKey with an ever-increasing index, because
// I'm deleting the subkeys as I go, which alters the indices of the
// remaining subkeys in an implementation-dependent way. In order to
// be safe, I have to count backwards while deleting the subkeys.
// Find out how many subkeys there are
dwRet = RegQueryInfoKey(hkSubKey,
szClass,
&cbClass,
NULL,
&dwIndex, // The # of subkeys -- all we need
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL);
if (NO_ERROR == dwRet && dwIndex > 0)
{
// dwIndex is now the count of subkeys, but it needs to be
// zero-based for RegEnumKey, so I'll pre-decrement, rather
// than post-decrement.
while (ERROR_SUCCESS == RegEnumKey(hkSubKey, --dwIndex, szSubKeyName, cchSubKeyName))
{
DeleteKeyRecursively(hkSubKey, szSubKeyName);
}
}
RegCloseKey(hkSubKey);
dwRet = RegDeleteKey(hkey, pszSubKey);
}
return dwRet;
}
// Automatically calls RegCloseKey when leaving scope
class CAutoHKey {
public:
CAutoHKey() : m_hKey(NULL) {}
~CAutoHKey() {
if (m_hKey)
RegCloseKey(m_hKey);
}
LRESULT Create(HKEY hKey, LPCTSTR szSubKey)
{
return RegCreateKey(hKey, szSubKey, &m_hKey);
}
LRESULT Open(HKEY hKey, LPCTSTR szSubKey)
{
return RegOpenKey(hKey, szSubKey, &m_hKey);
}
void Close()
{
if (m_hKey) {
RegCloseKey(m_hKey);
}
m_hKey = NULL;
}
HKEY m_hKey;
HKEY Key() const { return m_hKey; }
};
// Automatically calls RegCloseKey when leaving scope
class CAutoCreateHKey {
public:
CAutoCreateHKey(HKEY hKey, TCHAR* szSubKey, HKEY *phKey) {
if (RegCreateKeyEx(hKey,
szSubKey,
0,
TEXT(""),
REG_OPTION_NON_VOLATILE,
MAXIMUM_ALLOWED,
NULL,
phKey,
NULL) != ERROR_SUCCESS)
m_hKey = *phKey = NULL;
else
m_hKey = *phKey;
}
~CAutoCreateHKey() {
if (m_hKey)
RegCloseKey(m_hKey);
}
HKEY m_hKey;
};
class CAutoOpenHKey {
public:
CAutoOpenHKey(HKEY hKey, TCHAR* szSubKey, HKEY *phKey, REGSAM samDesired = KEY_READ) {
if (RegOpenKeyEx(hKey,
szSubKey,
0,
samDesired,
phKey) != ERROR_SUCCESS)
m_hKey = *phKey = NULL;
else
m_hKey = *phKey;
}
~CAutoOpenHKey() {
if (m_hKey)
RegCloseKey(m_hKey);
}
HKEY m_hKey;
};
HRESULT ReadTypesFromKeys(HKEY hkDMO, LPCTSTR pszTypes, DWORD *pcbData, PVOID *ppvData)
{
// Collect all the types into 1 value - need to enumerate
// keys and subkeys
LPVOID pMem = CoTaskMemAlloc(0);
unsigned int nEntries = 0;
DWORD dwTypeIndex;
BOOL bSuccess = TRUE;
DMO_PARTIAL_MEDIATYPE Type;
CAutoHKey hkSrc;
if (NOERROR != hkSrc.Open(hkDMO, pszTypes)) {
bSuccess = FALSE;
}
for (dwTypeIndex = 0; bSuccess; dwTypeIndex++) {
TCHAR szType[MAX_PATH];
LONG lResult = RegEnumKey(hkSrc.Key(), dwTypeIndex, szType, MAX_PATH);
if (NOERROR != lResult) {
if (ERROR_NO_MORE_ITEMS != lResult) {
bSuccess = FALSE;
}
break;
}
if (DMOStrToGuid(szType, &Type.type)) {
CAutoHKey kType;
kType.Open(hkSrc.Key(), szType);
if (NULL == kType.Key()) {
bSuccess = FALSE;
} else {
DWORD dwSubtypeIndex;
for (dwSubtypeIndex = 0; bSuccess; dwSubtypeIndex++) {
TCHAR szSubtype[MAX_PATH];
lResult = RegEnumKey(kType.Key(), dwSubtypeIndex, szSubtype, MAX_PATH);
if (NOERROR != lResult) {
if (ERROR_NO_MORE_ITEMS != lResult) {
bSuccess = FALSE;
}
break;
}
if (DMOStrToGuid(szSubtype, &Type.subtype)) {
// Add to our list
LPVOID pMemNew = CoTaskMemRealloc(pMem,
(nEntries + 1) * sizeof(DMO_PARTIAL_MEDIATYPE));
if (NULL == pMemNew) {
bSuccess = FALSE;
} else {
pMem = pMemNew;
CopyMemory((LPBYTE)pMem +
nEntries * sizeof(DMO_PARTIAL_MEDIATYPE),
&Type,
sizeof(DMO_PARTIAL_MEDIATYPE));
nEntries++;
}
}
}
}
}
}
if (bSuccess && nEntries != 0) {
*ppvData = pMem;
*pcbData = nEntries * sizeof(DMO_PARTIAL_MEDIATYPE);
return S_OK;
} else {
CoTaskMemFree(pMem);
return S_FALSE;
}
}
HRESULT ReadTypes(HKEY hkDMO, LPCTSTR pszTypes, DWORD *pcbData, PVOID *ppvData)
{
*pcbData = 0;
// Try reading the value first
DWORD cbData;
if (NOERROR != RegQueryValueEx(hkDMO, pszTypes, NULL, NULL, NULL, &cbData)) {
return ReadTypesFromKeys(hkDMO, pszTypes, pcbData, ppvData);
}
if (cbData == 0) {
return S_OK;
}
PVOID pvData = (PBYTE)CoTaskMemAlloc(cbData);
if (NULL == pvData) {
return E_OUTOFMEMORY;
}
if (NOERROR == RegQueryValueEx(hkDMO, pszTypes, NULL, NULL, (PBYTE)pvData, &cbData)) {
*ppvData = pvData;
*pcbData = cbData;
return S_OK;
} else {
CoTaskMemFree(pvData);
return E_OUTOFMEMORY;
}
}
/////////////////////////////////////////////////////////////////////////////
//
// DMO Registration code
//
// Registration helper
void CreateObjectGuidKey(HKEY hKey, REFCLSID clsidDMO) {
TCHAR szSubkeyName[80];
HKEY hObjectGuidKey;
DMOGuidToStr(szSubkeyName, clsidDMO);
CAutoCreateHKey kGuid(hKey, szSubkeyName, &hObjectGuidKey);
}
// Registration helper
// Registers types\subtypes underneath the object's key
void RegisterTypes(HKEY hObjectKey,
TCHAR* szInputOrOutput,
ULONG ulTypes,
const DMO_PARTIAL_MEDIATYPE* pTypes) {
RegSetValueEx(hObjectKey, szInputOrOutput, 0, REG_BINARY,
(const BYTE *)pTypes,
ulTypes * sizeof(DMO_PARTIAL_MEDIATYPE));
}
//
// Public entry point
//
STDAPI DMORegister(
LPCWSTR szName,
REFCLSID clsidDMO,
REFGUID guidCategory,
DWORD dwFlags, // DMO_REGISTERF_XXX
unsigned long ulInTypes,
const DMO_PARTIAL_MEDIATYPE *pInTypes,
unsigned long ulOutTypes,
const DMO_PARTIAL_MEDIATYPE *pOutTypes
) {
TCHAR szSubkeyName[80];
if ((clsidDMO == GUID_NULL) || (guidCategory == GUID_NULL))
return E_INVALIDARG;
// Create/open the main DMO key
HKEY hMainKey;
CAutoCreateHKey kMain(DMO_REGISTRY_HIVE, DMO_REGISTRY_PATH, &hMainKey);
if (hMainKey == NULL)
return E_FAIL;
HKEY hCategoriesKey;
CAutoCreateHKey kCats(hMainKey, TEXT(CATEGORIES_STR), &hCategoriesKey);
if (hCategoriesKey == NULL)
return E_FAIL;
// Create/open the category specific subkey underneath the main key
DMOGuidToStr(szSubkeyName, guidCategory);
HKEY hCategoryKey;
CAutoCreateHKey kCat(hCategoriesKey, szSubkeyName, &hCategoryKey);
if (hCategoryKey == NULL)
return E_FAIL;
// Deletet the redundant old types keys
DeleteKeyRecursively(hCategoryKey, TEXT(INPUT_TYPES_STR));
DeleteKeyRecursively(hCategoryKey, TEXT(OUTPUT_TYPES_STR));
// If the category key does not have a name yet, add one
DWORD cbName;
DWORD dwType;
if ((RegQueryValueEx(hCategoryKey, NULL, NULL, &dwType, NULL, &cbName) != ERROR_SUCCESS) ||
(cbName <= sizeof(TCHAR)) || (REG_SZ != dwType)) {
TCHAR* szName;
if (guidCategory == DMOCATEGORY_AUDIO_DECODER)
szName = TEXT("Audio decoders");
else if (guidCategory == DMOCATEGORY_AUDIO_ENCODER)
szName = TEXT("Audio encoders");
else if (guidCategory == DMOCATEGORY_VIDEO_DECODER)
szName = TEXT("Video decoders");
else if (guidCategory == DMOCATEGORY_VIDEO_ENCODER)
szName = TEXT("Video encoders");
else if (guidCategory == DMOCATEGORY_AUDIO_EFFECT)
szName = TEXT("Audio effects");
else if (guidCategory == DMOCATEGORY_VIDEO_EFFECT)
szName = TEXT("Video effects");
else if (guidCategory == DMOCATEGORY_AUDIO_CAPTURE_EFFECT)
szName = TEXT("Audio capture effects");
else if (guidCategory == DMOCATEGORY_ACOUSTIC_ECHO_CANCEL)
szName = TEXT("Acoustic Echo Canceller");
else if (guidCategory == DMOCATEGORY_AUDIO_NOISE_SUPPRESS)
szName = TEXT("Audio Noise Suppressor");
else if (guidCategory == DMOCATEGORY_AGC)
szName = TEXT("Automatic Gain Control");
else
szName = TEXT("Unknown DMO category");
RegSetValue(hCategoryKey, NULL, REG_SZ, szName, lstrlen(szName) * sizeof(TCHAR));
}
// Create/open the object specific key underneath the category key
DMOGuidToStr(szSubkeyName, clsidDMO);
// Remove the old one
DeleteKeyRecursively(hMainKey, szSubkeyName);
HKEY hObjKey;
CAutoCreateHKey kObj(hCategoryKey, szSubkeyName, &hObjKey);
if (hObjKey == NULL)
return E_FAIL;
// Create/open the object specific key underneath the main key
DMOGuidToStr(szSubkeyName, clsidDMO); // BUGBUG: redundant
HKEY hObjectKey;
CAutoCreateHKey kObject(hMainKey, szSubkeyName, &hObjectKey);
if (hObjectKey == NULL)
return E_FAIL;
// set the default value of the object key to the name of the DMO
#ifdef UNICODE
LPCWSTR sz = szName;
#else
char sz[80];
WideCharToMultiByte(0,0,szName,-1,sz,80,NULL,NULL);
#endif
if (RegSetValue(hObjectKey, NULL, REG_SZ, sz, lstrlen(sz) * sizeof(TCHAR))
!= ERROR_SUCCESS)
return E_FAIL;
// If the object is keyed, add a registry value indicating so
if (dwFlags & DMO_REGISTERF_IS_KEYED) {
if (RegSetValue(hObjectKey, TEXT(KEYED_STR), REG_SZ, TEXT(""), 0)
!= ERROR_SUCCESS)
return E_FAIL;
}
// Register types
if (ulInTypes) {
RegisterTypes(hObjectKey, TEXT(INPUT_TYPES_STR), ulInTypes, pInTypes);
}
if (ulOutTypes) {
RegisterTypes(hObjectKey, TEXT(OUTPUT_TYPES_STR),ulOutTypes,pOutTypes);
}
// Nuke the DShow filter cache
DeleteKeyRecursively(HKEY_CURRENT_USER, TEXT("Software\\Microsoft\\Multimedia\\ActiveMovie\\Filter Cache"));
return NOERROR;
}
// helper
void MakeSubkeyName (TCHAR* szSubkeyName,
REFGUID guidCategory,
REFCLSID clsidDMO) {
DMOGuidToStr(szSubkeyName, guidCategory);
_tcscat(szSubkeyName, TEXT("\\"));
DMOGuidToStr(szSubkeyName + lstrlen(szSubkeyName), clsidDMO);
}
//
// Public entry point
//
STDAPI DMOUnregister(
REFCLSID clsidDMO,
REFGUID guidCategory
) {
HRESULT hr;
// open the root DMO key
HKEY hMainKey;
CAutoOpenHKey kMain(DMO_REGISTRY_HIVE, DMO_REGISTRY_PATH, &hMainKey, MAXIMUM_ALLOWED);
if (hMainKey == NULL)
return E_FAIL;
// open the "Categories" key underneath the root key
HKEY hCategoriesKey;
CAutoOpenHKey kCats(hMainKey, TEXT(CATEGORIES_STR), &hCategoriesKey, MAXIMUM_ALLOWED);
if (hCategoriesKey == NULL)
return E_FAIL;
// Iterate through all categories attempting to delete from each one
TCHAR szCategory[80];
DWORD dwIndex = 0;
BOOL bDeletedAnything = FALSE;
BOOL bDeletedAll = TRUE;
DMOGuidToStr(szCategory, guidCategory);
while (RegEnumKey(hCategoriesKey, dwIndex, szCategory, 80) == ERROR_SUCCESS) {
// process the subkey only if it resembles a category GUID
GUID guid;
if (DMOStrToGuid(szCategory, &guid)) {
// Try to delete from this category
TCHAR szSubkeyName[256];
MakeSubkeyName(szSubkeyName, guid, clsidDMO);
if (guidCategory == GUID_NULL || guid == guidCategory) {
if (DeleteKeyRecursively(hCategoriesKey, szSubkeyName) == ERROR_SUCCESS)
bDeletedAnything = TRUE;
} else {
CAutoHKey hk;
if (ERROR_FILE_NOT_FOUND != hk.Open(hCategoriesKey, szSubkeyName)) {
bDeletedAll = FALSE;
}
}
}
dwIndex++;
}
if (bDeletedAnything) {
hr = S_OK;
if (bDeletedAll) {
// Now delete this object's key from underneath the root DMO key
TCHAR szGuid[CHARS_IN_GUID];
DMOGuidToStr(szGuid, clsidDMO);
if (DeleteKeyRecursively(hMainKey, szGuid) != ERROR_SUCCESS) {
hr = S_FALSE;
}
}
}
else
hr = S_FALSE;
return hr;
}
//
// End DMO Registration code
//
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//
// DMO Enumeration code
// Some of it leaves room for future improvements in terms of speed
//
// helper
HRESULT ReadName(HKEY hDMOKey, WCHAR szName[80]) {
LONG cbSize = 80;
#ifdef UNICODE
if (RegQueryValue(hDMOKey, NULL, szName, &cbSize) == ERROR_SUCCESS)
return S_OK;
#else
char szTmp[80];
if (RegQueryValue(hDMOKey, NULL, szTmp, &cbSize) == ERROR_SUCCESS) {
MultiByteToWideChar(0,0,szTmp,-1,szName,80);
return S_OK;
}
#endif
else {
szName[0] = L'\0'; // no name - corrupt registry ?
return S_FALSE;
}
}
// Enumeration helper, does what the name says
void LookupNameAndAddToEnum(HKEY hObjectKey,
TCHAR* szGuid,
DWORD dwFlags,
REFCLSID clsidDMO,
CEnumDMOCLSID* pEnum) {
// Skip keyed DMOs unless explicitly asked to include them
if (!(dwFlags & DMO_ENUMF_INCLUDE_KEYED)) {
// open the DMO's registry key
LONG cbValue;
if (RegQueryValue(hObjectKey, TEXT(KEYED_STR), NULL, &cbValue)
== ERROR_SUCCESS)
return; // DMO is keyed - skip
}
WCHAR szName[80];
if (FAILED(ReadName(hObjectKey, szName)))
szName[0] = L'\0';
pEnum->Add(clsidDMO, szName);
}
// Check if any of the requested types match
// If no requested types are specified then this is treated
// as a match
BOOL CompareTypes(HKEY hkDMO,
unsigned long ulTypes,
const DMO_PARTIAL_MEDIATYPE *pTypes,
LPCTSTR pszTypesValue)
{
if (ulTypes == 0) {
return TRUE;
}
DWORD cbData;
PVOID pvDMOTypes = NULL;
if (S_OK == ReadTypes(hkDMO, pszTypesValue, &cbData, &pvDMOTypes)) {
for (unsigned long ulType = 0; ulType < ulTypes; ulType++) {
DMO_PARTIAL_MEDIATYPE *pDMOTypes = (DMO_PARTIAL_MEDIATYPE *)pvDMOTypes;
while ((PBYTE)(pDMOTypes + 1) <= (PBYTE)pvDMOTypes + cbData) {
if (pDMOTypes->type == pTypes[ulType].type ||
pDMOTypes->type == GUID_NULL ||
pTypes[ulType].type == GUID_NULL) {
if (pTypes[ulType].subtype == GUID_NULL ||
pDMOTypes->subtype == GUID_NULL ||
pTypes[ulType].subtype == pDMOTypes->subtype) {
CoTaskMemFree(pvDMOTypes);
return TRUE;
}
}
pDMOTypes++;
}
}
}
CoTaskMemFree(pvDMOTypes);
return FALSE;
}
// Enumeration helper
HRESULT EnumerateDMOs(HKEY hMainKey,
HKEY hCatKey,
DWORD dwFlags,
unsigned long ulInputTypes,
const DMO_PARTIAL_MEDIATYPE *pInputTypes,
unsigned long ulOutputTypes,
const DMO_PARTIAL_MEDIATYPE *pOutputTypes,
CEnumDMOCLSID *pEnum) {
DWORD dwIndex = 0;
TCHAR szSubkey[80];
while (RegEnumKey(hCatKey, dwIndex, szSubkey, 80) == ERROR_SUCCESS) {
// Does this look like an object CLSID ?
CLSID clsidDMO;
if (DMOStrToGuid(szSubkey, &clsidDMO)) {
// Do the type match?
CAutoHKey hkDMO;
if (NOERROR == hkDMO.Open(hMainKey, szSubkey)) {
if (CompareTypes(hkDMO.Key(), ulInputTypes, pInputTypes, TEXT(INPUT_TYPES_STR)) &&
CompareTypes(hkDMO.Key(), ulOutputTypes, pOutputTypes, TEXT(OUTPUT_TYPES_STR))) {
LookupNameAndAddToEnum(hkDMO.Key(), szSubkey, dwFlags, clsidDMO, pEnum);
}
}
}
dwIndex++;
}
return S_OK;
}
//
// Public entry point
//
STDAPI DMOEnum(
REFGUID guidCategory, // GUID_NULL for "all"
DWORD dwFlags, // DMO_ENUMF_XXX
unsigned long ulInTypes,
const DMO_PARTIAL_MEDIATYPE *pInTypes, // can be NULL only of ulInTypes = 0
unsigned long ulOutTypes,
const DMO_PARTIAL_MEDIATYPE *pOutTypes,// can be NULL only of ulOutTypes = 0
IEnumDMO **ppEnum
) {
if (ppEnum == NULL) {
return E_POINTER;
}
if (ulInTypes > 0 && pInTypes == NULL ||
ulOutTypes > 0 && pOutTypes == NULL) {
return E_INVALIDARG;
}
*ppEnum = NULL;
// open the root key
CAutoHKey kMain;
kMain.Open(DMO_REGISTRY_HIVE, DMO_REGISTRY_PATH);
if (kMain.Key() == NULL)
return E_FAIL;
CEnumDMOCLSID *pEnum = new CEnumDMOCLSID();
if (!pEnum)
return E_OUTOFMEMORY;
HRESULT hr = S_OK;
if (guidCategory == GUID_NULL) {
hr = EnumerateDMOs(kMain.Key(),
kMain.Key(),
dwFlags,
ulInTypes,
pInTypes,
ulOutTypes,
pOutTypes,
pEnum);
} else {
// open the subkey for the specified category and enumerate its subkeys
TCHAR szCategory[CHARS_IN_GUID];
TCHAR szCategoryPath[MAX_PATH];
DMOGuidToStr(szCategory, guidCategory);
wsprintf(szCategoryPath, TEXT(CATEGORIES_STR) TEXT("\\%s"), szCategory);
CAutoHKey key2;
key2.Open(kMain.Key(), szCategoryPath);
if (key2.Key()) {
hr = EnumerateDMOs(kMain.Key(),
key2.Key(),
dwFlags,
ulInTypes,
pInTypes,
ulOutTypes,
pOutTypes,
pEnum);
}
}
if (SUCCEEDED(hr)) {
*ppEnum = (IEnumDMO*) pEnum;
hr = S_OK;
} else {
delete pEnum;
}
return hr;
}
// Copy the type information
HRESULT FetchTypeInfo(HKEY hObjKey, LPCTSTR pszTypesValue,
unsigned long ulTypesRequested,
unsigned long *pulTypesSupplied,
DMO_PARTIAL_MEDIATYPE *pTypes)
{
DWORD cbData;
unsigned long ulTypesCopied = 0;
PVOID pvData;
if (S_OK == ReadTypes(hObjKey, pszTypesValue, &cbData, &pvData)) {
ulTypesCopied =
min(ulTypesRequested, cbData / sizeof(DMO_PARTIAL_MEDIATYPE));
CopyMemory(pTypes, pvData,
ulTypesCopied * sizeof(DMO_PARTIAL_MEDIATYPE));
CoTaskMemFree(pvData);
}
*pulTypesSupplied = ulTypesCopied;
return ulTypesCopied != 0 ? S_OK : S_FALSE;
}
// Mediatype helper
HRESULT FetchMediatypeInfo(HKEY hObjKey,
unsigned long ulInputTypesRequested,
unsigned long *pulInputTypesSupplied,
DMO_PARTIAL_MEDIATYPE *pInputTypes,
unsigned long ulOutputTypesRequested,
unsigned long *pulOutputTypesSupplied,
DMO_PARTIAL_MEDIATYPE *pOutputTypes) {
HRESULT hr1 = S_OK;
if (ulInputTypesRequested) {
hr1 = FetchTypeInfo(hObjKey,
TEXT(INPUT_TYPES_STR),
ulInputTypesRequested,
pulInputTypesSupplied,
pInputTypes);
} else {
*pulInputTypesSupplied = 0;
}
HRESULT hr2 = S_OK;
if (ulOutputTypesRequested) {
hr2 = FetchTypeInfo(hObjKey,
TEXT(OUTPUT_TYPES_STR),
ulOutputTypesRequested,
pulOutputTypesSupplied,
pOutputTypes);
} else {
*pulOutputTypesSupplied = 0;
}
if ((hr1 == S_OK) && (hr2 == S_OK))
return S_OK;
else
return S_FALSE;
}
//
// Public entry point
//
STDAPI DMOGetTypes(
REFCLSID clsidDMO,
unsigned long ulInputTypesRequested,
unsigned long *pulInputTypesSupplied,
DMO_PARTIAL_MEDIATYPE *pInputTypes,
unsigned long ulOutputTypesRequested,
unsigned long *pulOutputTypesSupplied,
DMO_PARTIAL_MEDIATYPE *pOutputTypes
) {
// open the DMO root registry key
HKEY hMainKey;
CAutoOpenHKey kMain(DMO_REGISTRY_HIVE, DMO_REGISTRY_PATH, &hMainKey);
if (hMainKey == NULL)
return E_FAIL;
// open the object specific guid key
TCHAR szGuid[80];
DMOGuidToStr(szGuid, clsidDMO);
HKEY hObjKey;
CAutoOpenHKey kObj(hMainKey, szGuid, &hObjKey);
if (!hObjKey)
return E_FAIL;
return FetchMediatypeInfo(hObjKey,
ulInputTypesRequested,
pulInputTypesSupplied,
pInputTypes,
ulOutputTypesRequested,
pulOutputTypesSupplied,
pOutputTypes);
}
STDAPI DMOGetName(REFCLSID clsidDMO, WCHAR szName[80]) {
// open the DMO root registry key
HKEY hMainKey;
CAutoOpenHKey kMain(DMO_REGISTRY_HIVE, DMO_REGISTRY_PATH, &hMainKey);
if (hMainKey == NULL)
return E_FAIL;
// open the object specific guid key
TCHAR szGuid[80];
DMOGuidToStr(szGuid, clsidDMO);
HKEY hObjKey;
CAutoOpenHKey kObj(hMainKey, szGuid, &hObjKey);
if (!hObjKey)
return E_FAIL;
return ReadName(hObjKey, szName);
}
//
// End DMO Enumeration code
//
/////////////////////////////////////////////////////////////////////////////