https://git.reactos.org/?p=reactos.git;a=commitdiff;h=5e3341f4bb252ed7127a7…
commit 5e3341f4bb252ed7127a7439bf6a90e73f0f6295
Author: Amine Khaldi <amine.khaldi(a)reactos.org>
AuthorDate: Sun May 27 03:56:13 2018 +0100
Commit: Amine Khaldi <amine.khaldi(a)reactos.org>
CommitDate: Sun May 27 03:56:13 2018 +0100
[DEVENUM] Sync with Wine Staging 3.9. CORE-14656
---
dll/directx/wine/devenum/CMakeLists.txt | 4 +-
dll/directx/wine/devenum/createdevenum.c | 1169 ++++++++++++++-------------
dll/directx/wine/devenum/devenum.rc | 12 -
dll/directx/wine/devenum/devenum_private.h | 40 +-
dll/directx/wine/devenum/fil_data.idl | 47 ++
dll/directx/wine/devenum/mediacatenum.c | 214 +++--
dll/directx/wine/devenum/parsedisplayname.c | 93 +--
media/doc/README.WINE | 2 +-
8 files changed, 859 insertions(+), 722 deletions(-)
diff --git a/dll/directx/wine/devenum/CMakeLists.txt
b/dll/directx/wine/devenum/CMakeLists.txt
index d8af794b86..1f5e7eb321 100644
--- a/dll/directx/wine/devenum/CMakeLists.txt
+++ b/dll/directx/wine/devenum/CMakeLists.txt
@@ -4,6 +4,7 @@ add_definitions(-D_WIN32_WINNT=0x600 -DWINVER=0x600)
add_definitions(-D__WINESRC__)
include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/wine)
+add_idl_headers(devenum_fil_data_header fil_data.idl)
spec2def(devenum.dll devenum.spec)
list(APPEND SOURCE
@@ -23,6 +24,7 @@ set_source_files_properties(devenum.rc PROPERTIES OBJECT_DEPENDS
${CMAKE_CURRENT
set_module_type(devenum win32dll UNICODE)
target_link_libraries(devenum strmiids uuid wine)
add_delay_importlibs(devenum msvfw32)
-add_importlibs(devenum advapi32 advapi32_vista ole32 oleaut32 winmm user32 avicap32
msacm32 msvcrt kernel32 ntdll)
+add_importlibs(devenum advapi32 advapi32_vista ole32 oleaut32 winmm user32 avicap32
msacm32 dsound msvcrt kernel32 ntdll)
+add_dependencies(devenum devenum_fil_data_header)
add_pch(devenum precomp.h SOURCE)
add_cd_file(TARGET devenum DESTINATION reactos/system32 FOR all)
diff --git a/dll/directx/wine/devenum/createdevenum.c
b/dll/directx/wine/devenum/createdevenum.c
index 002ffbc876..fbde0cb61d 100644
--- a/dll/directx/wine/devenum/createdevenum.c
+++ b/dll/directx/wine/devenum/createdevenum.c
@@ -29,22 +29,20 @@
#include "devenum_private.h"
#include "vfw.h"
#include "aviriff.h"
+#include "dsound.h"
#include "wine/debug.h"
#include "wine/unicode.h"
+#include "wine/heap.h"
#include "mmddk.h"
+#include "initguid.h"
+#include "fil_data.h"
+
WINE_DEFAULT_DEBUG_CHANNEL(devenum);
extern HINSTANCE DEVENUM_hInstance;
-const WCHAR wszInstanceKeyName[]
={'\\','I','n','s','t','a','n','c','e',0};
-
-static const WCHAR wszRegSeparator[] = {'\\', 0 };
-static const WCHAR wszActiveMovieKey[] =
{'S','o','f','t','w','a','r','e','\\',
-
'M','i','c','r','o','s','o','f','t','\\',
-
'A','c','t','i','v','e','M','o','v','i','e','\\',
-
'd','e','v','e','n','u','m','\\',0};
static const WCHAR wszFilterKeyName[] =
{'F','i','l','t','e','r',0};
static const WCHAR wszMeritName[] =
{'M','e','r','i','t',0};
static const WCHAR wszPins[] = {'P','i','n','s',0};
@@ -54,11 +52,11 @@ static const WCHAR wszDirection[] =
{'D','i','r','e','c','t','i','o','n',0};
static const WCHAR wszIsRendered[] =
{'I','s','R','e','n','d','e','r','e','d',0};
static const WCHAR wszTypes[] =
{'T','y','p','e','s',0};
static const WCHAR wszFriendlyName[] =
{'F','r','i','e','n','d','l','y','N','a','m','e',0};
-static const WCHAR wszWaveInID[] =
{'W','a','v','e','I','n','I','D',0};
-static const WCHAR wszWaveOutID[] =
{'W','a','v','e','O','u','t','I','D',0};
+static const WCHAR wszFilterData[] =
{'F','i','l','t','e','r','D','a','t','a',0};
static ULONG WINAPI DEVENUM_ICreateDevEnum_AddRef(ICreateDevEnum * iface);
-static HRESULT DEVENUM_CreateSpecialCategories(void);
+static HRESULT register_codecs(void);
+static HRESULT DEVENUM_CreateAMCategoryKey(const CLSID * clsidCategory);
/**********************************************************************
* DEVENUM_ICreateDevEnum_QueryInterface (also IUnknown)
@@ -108,87 +106,37 @@ static ULONG WINAPI DEVENUM_ICreateDevEnum_Release(ICreateDevEnum *
iface)
return 1; /* non-heap based object */
}
-static BOOL IsSpecialCategory(const CLSID *clsid)
+static HRESULT register_codec(const CLSID *class, const WCHAR *name, IMoniker **ret)
{
- return IsEqualGUID(clsid, &CLSID_AudioRendererCategory) ||
- IsEqualGUID(clsid, &CLSID_AudioInputDeviceCategory) ||
- IsEqualGUID(clsid, &CLSID_VideoInputDeviceCategory) ||
- IsEqualGUID(clsid, &CLSID_VideoCompressorCategory) ||
- IsEqualGUID(clsid, &CLSID_AudioCompressorCategory) ||
- IsEqualGUID(clsid, &CLSID_MidiRendererCategory);
-}
+ static const WCHAR deviceW[] =
{'@','d','e','v','i','c','e',':','c','m',':',0};
+ IParseDisplayName *parser;
+ WCHAR *buffer;
+ ULONG eaten;
+ HRESULT hr;
-HRESULT DEVENUM_GetCategoryKey(REFCLSID clsidDeviceClass, HKEY *pBaseKey, WCHAR
*wszRegKeyName, UINT maxLen)
-{
- if (IsSpecialCategory(clsidDeviceClass))
- {
- *pBaseKey = HKEY_CURRENT_USER;
- strcpyW(wszRegKeyName, wszActiveMovieKey);
+ hr = CoCreateInstance(&CLSID_CDeviceMoniker, NULL, CLSCTX_INPROC,
&IID_IParseDisplayName, (void **)&parser);
+ if (FAILED(hr))
+ return hr;
- if (!StringFromGUID2(clsidDeviceClass, wszRegKeyName + strlenW(wszRegKeyName),
maxLen - strlenW(wszRegKeyName)))
- return E_OUTOFMEMORY;
- }
- else
+ buffer = heap_alloc((strlenW(deviceW) + CHARS_IN_GUID + strlenW(name) + 1) *
sizeof(WCHAR));
+ if (!buffer)
{
- *pBaseKey = HKEY_CLASSES_ROOT;
- strcpyW(wszRegKeyName, clsid_keyname);
- strcatW(wszRegKeyName, wszRegSeparator);
-
- if (!StringFromGUID2(clsidDeviceClass, wszRegKeyName + CLSID_STR_LEN, maxLen -
CLSID_STR_LEN))
- return E_OUTOFMEMORY;
-
- strcatW(wszRegKeyName, wszInstanceKeyName);
- }
-
- return S_OK;
-}
-
-static HKEY open_category_key(const CLSID *clsid)
-{
- WCHAR key_name[sizeof(wszInstanceKeyName)/sizeof(WCHAR) + CHARS_IN_GUID-1 + 6 /*
strlen("CLSID\") */], *ptr;
- HKEY ret;
-
- strcpyW(key_name, clsid_keyname);
- ptr = key_name + strlenW(key_name);
- *ptr++ = '\\';
-
- if (!StringFromGUID2(clsid, ptr, CHARS_IN_GUID))
- return NULL;
-
- ptr += strlenW(ptr);
- strcpyW(ptr, wszInstanceKeyName);
-
- if (RegOpenKeyExW(HKEY_CLASSES_ROOT, key_name, 0, KEY_READ, &ret) !=
ERROR_SUCCESS) {
- WARN("Could not open %s\n", debugstr_w(key_name));
- return NULL;
+ IParseDisplayName_Release(parser);
+ return E_OUTOFMEMORY;
}
- return ret;
-}
-
-static HKEY open_special_category_key(const CLSID *clsid, BOOL create)
-{
- WCHAR key_name[sizeof(wszActiveMovieKey)/sizeof(WCHAR) + CHARS_IN_GUID-1];
- HKEY ret;
- LONG res;
-
- strcpyW(key_name, wszActiveMovieKey);
- if (!StringFromGUID2(clsid, key_name + sizeof(wszActiveMovieKey)/sizeof(WCHAR)-1,
CHARS_IN_GUID))
- return NULL;
+ strcpyW(buffer, deviceW);
+ StringFromGUID2(class, buffer + strlenW(buffer), CHARS_IN_GUID);
+ strcatW(buffer, backslashW);
+ strcatW(buffer, name);
- if(create)
- res = RegCreateKeyW(HKEY_CURRENT_USER, key_name, &ret);
- else
- res = RegOpenKeyExW(HKEY_CURRENT_USER, key_name, 0, KEY_READ, &ret);
- if (res != ERROR_SUCCESS) {
- WARN("Could not open %s\n", debugstr_w(key_name));
- return NULL;
- }
-
- return ret;
+ hr = IParseDisplayName_ParseDisplayName(parser, NULL, buffer, &eaten, ret);
+ IParseDisplayName_Release(parser);
+ heap_free(buffer);
+ return hr;
}
-static void DEVENUM_ReadPinTypes(HKEY hkeyPinKey, REGFILTERPINS *rgPin)
+static void DEVENUM_ReadPinTypes(HKEY hkeyPinKey, REGFILTERPINS2 *rgPin)
{
HKEY hkeyTypes = NULL;
DWORD dwMajorTypes, i;
@@ -285,7 +233,11 @@ static void DEVENUM_ReadPins(HKEY hkeyFilterClass, REGFILTER2 *rgf2)
{
HKEY hkeyPins = NULL;
DWORD dwPinsSubkeys, i;
- REGFILTERPINS *rgPins = NULL;
+ REGFILTERPINS2 *rgPins = NULL;
+
+ rgf2->dwVersion = 2;
+ rgf2->u.s2.cPins2 = 0;
+ rgf2->u.s2.rgPins2 = NULL;
if (RegOpenKeyExW(hkeyFilterClass, wszPins, 0, KEY_READ, &hkeyPins) !=
ERROR_SUCCESS)
return ;
@@ -299,7 +251,7 @@ static void DEVENUM_ReadPins(HKEY hkeyFilterClass, REGFILTER2 *rgf2)
if (dwPinsSubkeys)
{
- rgPins = CoTaskMemAlloc(sizeof(REGFILTERPINS) * dwPinsSubkeys);
+ rgPins = CoTaskMemAlloc(sizeof(REGFILTERPINS2) * dwPinsSubkeys);
if (!rgPins)
{
RegCloseKey(hkeyPins);
@@ -312,82 +264,137 @@ static void DEVENUM_ReadPins(HKEY hkeyFilterClass, REGFILTER2
*rgf2)
HKEY hkeyPinKey = NULL;
WCHAR wszPinName[MAX_PATH];
DWORD cName = sizeof(wszPinName) / sizeof(WCHAR);
- DWORD Type, cbData;
- REGFILTERPINS *rgPin = &rgPins[rgf2->u.s1.cPins];
+ REGFILTERPINS2 *rgPin = &rgPins[rgf2->u.s2.cPins2];
+ DWORD value, size, Type;
LONG lRet;
- rgPin->strName = NULL;
- rgPin->clsConnectsToFilter = &GUID_NULL;
- rgPin->strConnectsToPin = NULL;
- rgPin->nMediaTypes = 0;
- rgPin->lpMediaType = NULL;
+ memset(rgPin, 0, sizeof(*rgPin));
if (RegEnumKeyExW(hkeyPins, i, wszPinName, &cName, NULL, NULL, NULL, NULL) !=
ERROR_SUCCESS) continue;
if (RegOpenKeyExW(hkeyPins, wszPinName, 0, KEY_READ, &hkeyPinKey) !=
ERROR_SUCCESS) continue;
- rgPin->strName = CoTaskMemAlloc((strlenW(wszPinName) + 1) * sizeof(WCHAR));
- if (!rgPin->strName) goto error_cleanup;
-
- strcpyW(rgPin->strName, wszPinName);
-
- cbData = sizeof(rgPin->bMany);
- lRet = RegQueryValueExW(hkeyPinKey, wszAllowedMany, NULL, &Type,
(LPBYTE)&rgPin->bMany, &cbData);
+ size = sizeof(DWORD);
+ lRet = RegQueryValueExW(hkeyPinKey, wszAllowedMany, NULL, &Type, (BYTE
*)&value, &size);
if (lRet != ERROR_SUCCESS || Type != REG_DWORD)
goto error_cleanup;
+ if (value)
+ rgPin->dwFlags |= REG_PINFLAG_B_MANY;
- cbData = sizeof(rgPin->bZero);
- lRet = RegQueryValueExW(hkeyPinKey, wszAllowedZero, NULL, &Type,
(LPBYTE)&rgPin->bZero, &cbData);
+ size = sizeof(DWORD);
+ lRet = RegQueryValueExW(hkeyPinKey, wszAllowedZero, NULL, &Type, (BYTE
*)&value, &size);
if (lRet != ERROR_SUCCESS || Type != REG_DWORD)
goto error_cleanup;
+ if (value)
+ rgPin->dwFlags |= REG_PINFLAG_B_ZERO;
- cbData = sizeof(rgPin->bOutput);
- lRet = RegQueryValueExW(hkeyPinKey, wszDirection, NULL, &Type,
(LPBYTE)&rgPin->bOutput, &cbData);
+ size = sizeof(DWORD);
+ lRet = RegQueryValueExW(hkeyPinKey, wszDirection, NULL, &Type, (BYTE
*)&value, &size);
if (lRet != ERROR_SUCCESS || Type != REG_DWORD)
goto error_cleanup;
+ if (value)
+ rgPin->dwFlags |= REG_PINFLAG_B_OUTPUT;
+
- cbData = sizeof(rgPin->bRendered);
- lRet = RegQueryValueExW(hkeyPinKey, wszIsRendered, NULL, &Type,
(LPBYTE)&rgPin->bRendered, &cbData);
+ size = sizeof(DWORD);
+ lRet = RegQueryValueExW(hkeyPinKey, wszIsRendered, NULL, &Type, (BYTE
*)&value, &size);
if (lRet != ERROR_SUCCESS || Type != REG_DWORD)
goto error_cleanup;
+ if (value)
+ rgPin->dwFlags |= REG_PINFLAG_B_RENDERER;
DEVENUM_ReadPinTypes(hkeyPinKey, rgPin);
- ++rgf2->u.s1.cPins;
+ ++rgf2->u.s2.cPins2;
continue;
error_cleanup:
RegCloseKey(hkeyPinKey);
- CoTaskMemFree(rgPin->strName);
}
RegCloseKey(hkeyPins);
- if (rgPins && !rgf2->u.s1.cPins)
+ if (rgPins && !rgf2->u.s2.cPins2)
{
CoTaskMemFree(rgPins);
rgPins = NULL;
}
- rgf2->u.s1.rgPins = rgPins;
+ rgf2->u.s2.rgPins2 = rgPins;
+}
+
+static void free_regfilter2(REGFILTER2 *rgf)
+{
+ if (rgf->u.s2.rgPins2)
+ {
+ UINT iPin;
+
+ for (iPin = 0; iPin < rgf->u.s2.cPins2; iPin++)
+ {
+ if (rgf->u.s2.rgPins2[iPin].lpMediaType)
+ {
+ UINT iType;
+
+ for (iType = 0; iType < rgf->u.s2.rgPins2[iPin].nMediaTypes;
iType++)
+ {
+ CoTaskMemFree((void
*)rgf->u.s2.rgPins2[iPin].lpMediaType[iType].clsMajorType);
+ CoTaskMemFree((void
*)rgf->u.s2.rgPins2[iPin].lpMediaType[iType].clsMinorType);
+ }
+
+ CoTaskMemFree((void *)rgf->u.s2.rgPins2[iPin].lpMediaType);
+ }
+ }
+
+ CoTaskMemFree((void *)rgf->u.s2.rgPins2);
+ }
+}
+
+static void write_filter_data(IPropertyBag *prop_bag, REGFILTER2 *rgf)
+{
+ IAMFilterData *fildata;
+ SAFEARRAYBOUND sabound;
+ BYTE *data, *array;
+ VARIANT var;
+ ULONG size;
+ HRESULT hr;
+
+ hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC,
&IID_IAMFilterData, (void **)&fildata);
+ if (FAILED(hr)) goto cleanup;
+
+ hr = IAMFilterData_CreateFilterData(fildata, rgf, &data, &size);
+ if (FAILED(hr)) goto cleanup;
+
+ V_VT(&var) = VT_ARRAY | VT_UI1;
+ sabound.lLbound = 0;
+ sabound.cElements = size;
+ if (!(V_ARRAY(&var) = SafeArrayCreate(VT_UI1, 1, &sabound)))
+ goto cleanup;
+ hr = SafeArrayAccessData(V_ARRAY(&var), (void *)&array);
+ if (FAILED(hr)) goto cleanup;
+
+ memcpy(array, data, size);
+ hr = SafeArrayUnaccessData(V_ARRAY(&var));
+ if (FAILED(hr)) goto cleanup;
+
+ hr = IPropertyBag_Write(prop_bag, wszFilterData, &var);
+ if (FAILED(hr)) goto cleanup;
+
+cleanup:
+ VariantClear(&var);
+ CoTaskMemFree(data);
+ IAMFilterData_Release(fildata);
}
-static HRESULT DEVENUM_RegisterLegacyAmFilters(void)
+static void register_legacy_filters(void)
{
HKEY hkeyFilter = NULL;
DWORD dwFilterSubkeys, i;
LONG lRet;
- IFilterMapper2 *pMapper = NULL;
HRESULT hr;
- hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC,
- &IID_IFilterMapper2, (void **) &pMapper);
- if (SUCCEEDED(hr))
- {
- lRet = RegOpenKeyExW(HKEY_CLASSES_ROOT, wszFilterKeyName, 0, KEY_READ,
&hkeyFilter);
- hr = HRESULT_FROM_WIN32(lRet);
- }
+ lRet = RegOpenKeyExW(HKEY_CLASSES_ROOT, wszFilterKeyName, 0, KEY_READ,
&hkeyFilter);
+ hr = HRESULT_FROM_WIN32(lRet);
if (SUCCEEDED(hr))
{
@@ -395,113 +402,487 @@ static HRESULT DEVENUM_RegisterLegacyAmFilters(void)
hr = HRESULT_FROM_WIN32(lRet);
}
+ if (SUCCEEDED(hr))
+ hr = DEVENUM_CreateAMCategoryKey(&CLSID_LegacyAmFilterCategory);
+
if (SUCCEEDED(hr))
{
for (i = 0; i < dwFilterSubkeys; i++)
{
WCHAR wszFilterSubkeyName[64];
DWORD cName = sizeof(wszFilterSubkeyName) / sizeof(WCHAR);
- HKEY hkeyCategoryBaseKey;
+ IPropertyBag *prop_bag = NULL;
WCHAR wszRegKey[MAX_PATH];
- HKEY hkeyInstance = NULL;
+ HKEY classkey = NULL;
+ IMoniker *mon = NULL;
+ VARIANT var;
+ REGFILTER2 rgf2;
+ DWORD Type, len;
if (RegEnumKeyExW(hkeyFilter, i, wszFilterSubkeyName, &cName, NULL, NULL,
NULL, NULL) != ERROR_SUCCESS) continue;
- hr = DEVENUM_GetCategoryKey(&CLSID_LegacyAmFilterCategory,
&hkeyCategoryBaseKey, wszRegKey, MAX_PATH);
- if (FAILED(hr)) continue;
+ TRACE("Registering %s\n", debugstr_w(wszFilterSubkeyName));
- strcatW(wszRegKey, wszRegSeparator);
+ strcpyW(wszRegKey, clsidW);
strcatW(wszRegKey, wszFilterSubkeyName);
- if (RegOpenKeyExW(HKEY_CLASSES_ROOT, wszRegKey, 0, KEY_READ,
&hkeyInstance) == ERROR_SUCCESS)
+ if (RegOpenKeyExW(HKEY_CLASSES_ROOT, wszRegKey, 0, KEY_READ, &classkey)
!= ERROR_SUCCESS)
+ continue;
+
+ hr = register_codec(&CLSID_LegacyAmFilterCategory, wszFilterSubkeyName,
&mon);
+ if (FAILED(hr)) goto cleanup;
+
+ hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void
**)&prop_bag);
+ if (FAILED(hr)) goto cleanup;
+
+ /* write friendly name */
+ len = 0;
+ V_VT(&var) = VT_BSTR;
+ if (!RegQueryValueExW(classkey, NULL, NULL, &Type, NULL, &len))
{
- RegCloseKey(hkeyInstance);
+ WCHAR *friendlyname = heap_alloc(len);
+ if (!friendlyname)
+ goto cleanup;
+ RegQueryValueExW(classkey, NULL, NULL, &Type, (BYTE *)friendlyname,
&len);
+ V_BSTR(&var) = SysAllocStringLen(friendlyname, len/sizeof(WCHAR));
+ heap_free(friendlyname);
}
else
- {
- /* Filter is registered the IFilterMapper(1)-way in HKCR\Filter. Needs to
be added to
- * legacy am filter category. */
- HKEY hkeyFilterClass = NULL;
- REGFILTER2 rgf2;
- CLSID clsidFilter;
- WCHAR wszFilterName[MAX_PATH];
- DWORD Type;
- DWORD cbData;
- HRESULT res;
- IMoniker *pMoniker = NULL;
-
- TRACE("Registering %s\n", debugstr_w(wszFilterSubkeyName));
-
- strcpyW(wszRegKey, clsid_keyname);
- strcatW(wszRegKey, wszRegSeparator);
- strcatW(wszRegKey, wszFilterSubkeyName);
-
- if (RegOpenKeyExW(HKEY_CLASSES_ROOT, wszRegKey, 0, KEY_READ,
&hkeyFilterClass) != ERROR_SUCCESS)
- continue;
-
- rgf2.dwVersion = 1;
- rgf2.dwMerit = 0;
- rgf2.u.s1.cPins = 0;
- rgf2.u.s1.rgPins = NULL;
-
- cbData = sizeof(wszFilterName);
- if (RegQueryValueExW(hkeyFilterClass, NULL, NULL, &Type,
(LPBYTE)wszFilterName, &cbData) != ERROR_SUCCESS ||
- Type != REG_SZ)
- goto cleanup;
+ V_BSTR(&var) = SysAllocString(wszFilterSubkeyName);
+
+ if (!V_BSTR(&var))
+ goto cleanup;
+ hr = IPropertyBag_Write(prop_bag, wszFriendlyName, &var);
+ if (FAILED(hr)) goto cleanup;
+ VariantClear(&var);
+
+ /* write clsid */
+ V_VT(&var) = VT_BSTR;
+ if (!(V_BSTR(&var) = SysAllocString(wszFilterSubkeyName)))
+ goto cleanup;
+ hr = IPropertyBag_Write(prop_bag, clsid_keyname, &var);
+ if (FAILED(hr)) goto cleanup;
+ VariantClear(&var);
+
+ /* write filter data */
+ rgf2.dwMerit = MERIT_NORMAL;
+
+ len = sizeof(rgf2.dwMerit);
+ RegQueryValueExW(classkey, wszMeritName, NULL, &Type, (BYTE
*)&rgf2.dwMerit, &len);
+
+ DEVENUM_ReadPins(classkey, &rgf2);
+
+ write_filter_data(prop_bag, &rgf2);
+
+cleanup:
+ if (prop_bag) IPropertyBag_Release(prop_bag);
+ if (mon) IMoniker_Release(mon);
+ RegCloseKey(classkey);
+ VariantClear(&var);
+ free_regfilter2(&rgf2);
+ }
+ }
- cbData = sizeof(rgf2.dwMerit);
- if (RegQueryValueExW(hkeyFilterClass, wszMeritName, NULL, &Type,
(LPBYTE)&rgf2.dwMerit, &cbData) != ERROR_SUCCESS ||
- Type != REG_DWORD)
- goto cleanup;
+ if (hkeyFilter) RegCloseKey(hkeyFilter);
+}
- DEVENUM_ReadPins(hkeyFilterClass, &rgf2);
+static BOOL CALLBACK register_dsound_devices(GUID *guid, const WCHAR *desc, const WCHAR
*module, void *context)
+{
+ static const WCHAR defaultW[] =
{'D','e','f','a','u','l','t','
','D','i','r','e','c','t','S','o','u','n','d','
','D','e','v','i','c','e',0};
+ static const WCHAR directsoundW[] =
{'D','i','r','e','c','t','S','o','u','n','d',':','
',0};
+ static const WCHAR dsguidW[] =
{'D','S','G','u','i','d',0};
+ IPropertyBag *prop_bag = NULL;
+ REGFILTERPINS2 rgpins = {0};
+ REGPINTYPES rgtypes = {0};
+ REGFILTER2 rgf = {0};
+ WCHAR clsid[CHARS_IN_GUID];
+ IMoniker *mon = NULL;
+ VARIANT var;
+ HRESULT hr;
- res = CLSIDFromString(wszFilterSubkeyName, &clsidFilter);
- if (FAILED(res)) goto cleanup;
+ hr = DEVENUM_CreateAMCategoryKey(&CLSID_AudioRendererCategory);
+ if (FAILED(hr)) goto cleanup;
- IFilterMapper2_RegisterFilter(pMapper, &clsidFilter, wszFilterName,
&pMoniker, NULL, NULL, &rgf2);
+ V_VT(&var) = VT_BSTR;
+ if (guid)
+ {
+ WCHAR *name = heap_alloc(sizeof(defaultW) + strlenW(desc) * sizeof(WCHAR));
+ if (!name)
+ goto cleanup;
+ strcpyW(name, directsoundW);
+ strcatW(name, desc);
+
+ V_BSTR(&var) = SysAllocString(name);
+ heap_free(name);
+ }
+ else
+ V_BSTR(&var) = SysAllocString(defaultW);
+
+ if (!V_BSTR(&var))
+ goto cleanup;
+
+ hr = register_codec(&CLSID_AudioRendererCategory, V_BSTR(&var), &mon);
+ if (FAILED(hr)) goto cleanup;
+
+ hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void
**)&prop_bag);
+ if (FAILED(hr)) goto cleanup;
+
+ /* write friendly name */
+ hr = IPropertyBag_Write(prop_bag, wszFriendlyName, &var);
+ if (FAILED(hr)) goto cleanup;
+ VariantClear(&var);
+
+ /* write clsid */
+ V_VT(&var) = VT_BSTR;
+ StringFromGUID2(&CLSID_DSoundRender, clsid, CHARS_IN_GUID);
+ if (!(V_BSTR(&var) = SysAllocString(clsid)))
+ goto cleanup;
+ hr = IPropertyBag_Write(prop_bag, clsid_keyname, &var);
+ if (FAILED(hr)) goto cleanup;
+ VariantClear(&var);
+
+ /* write filter data */
+ rgf.dwVersion = 2;
+ rgf.dwMerit = guid ? MERIT_DO_NOT_USE : MERIT_PREFERRED;
+ rgf.u.s2.cPins2 = 1;
+ rgf.u.s2.rgPins2 = &rgpins;
+ rgpins.dwFlags = REG_PINFLAG_B_RENDERER;
+ /* FIXME: native registers many more formats */
+ rgpins.nMediaTypes = 1;
+ rgpins.lpMediaType = &rgtypes;
+ rgtypes.clsMajorType = &MEDIATYPE_Audio;
+ rgtypes.clsMinorType = &MEDIASUBTYPE_PCM;
+
+ write_filter_data(prop_bag, &rgf);
+
+ /* write DSound guid */
+ V_VT(&var) = VT_BSTR;
+ StringFromGUID2(guid ? guid : &GUID_NULL, clsid, CHARS_IN_GUID);
+ if (!(V_BSTR(&var) = SysAllocString(clsid)))
+ goto cleanup;
+ hr = IPropertyBag_Write(prop_bag, dsguidW, &var);
+ if (FAILED(hr)) goto cleanup;
+
+cleanup:
+ VariantClear(&var);
+ if (prop_bag) IPropertyBag_Release(prop_bag);
+ if (mon) IMoniker_Release(mon);
- if (pMoniker)
- IMoniker_Release(pMoniker);
+ return TRUE;
+}
- cleanup:
+static void register_waveout_devices(void)
+{
+ static const WCHAR defaultW[] =
{'D','e','f','a','u','l','t','
','W','a','v','e','O','u','t','
','D','e','v','i','c','e',0};
+ static const WCHAR waveoutidW[] =
{'W','a','v','e','O','u','t','I','d',0};
+ IPropertyBag *prop_bag = NULL;
+ REGFILTERPINS2 rgpins = {0};
+ REGPINTYPES rgtypes = {0};
+ REGFILTER2 rgf = {0};
+ WCHAR clsid[CHARS_IN_GUID];
+ IMoniker *mon = NULL;
+ WAVEOUTCAPSW caps;
+ int i, count;
+ VARIANT var;
+ HRESULT hr;
- if (hkeyFilterClass) RegCloseKey(hkeyFilterClass);
+ hr = DEVENUM_CreateAMCategoryKey(&CLSID_AudioRendererCategory);
+ if (FAILED(hr)) return;
- if (rgf2.u.s1.rgPins)
- {
- UINT iPin;
+ count = waveOutGetNumDevs();
- for (iPin = 0; iPin < rgf2.u.s1.cPins; iPin++)
- {
- CoTaskMemFree(rgf2.u.s1.rgPins[iPin].strName);
+ for (i = -1; i < count; i++)
+ {
+ waveOutGetDevCapsW(i, &caps, sizeof(caps));
+
+ V_VT(&var) = VT_BSTR;
+
+ if (i == -1) /* WAVE_MAPPER */
+ V_BSTR(&var) = SysAllocString(defaultW);
+ else
+ V_BSTR(&var) = SysAllocString(caps.szPname);
+ if (!(V_BSTR(&var)))
+ goto cleanup;
+
+ hr = register_codec(&CLSID_AudioRendererCategory, V_BSTR(&var),
&mon);
+ if (FAILED(hr)) goto cleanup;
+
+ hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void
**)&prop_bag);
+ if (FAILED(hr)) goto cleanup;
+
+ /* write friendly name */
+ hr = IPropertyBag_Write(prop_bag, wszFriendlyName, &var);
+ if (FAILED(hr)) goto cleanup;
+ VariantClear(&var);
+
+ /* write clsid */
+ V_VT(&var) = VT_BSTR;
+ StringFromGUID2(&CLSID_AudioRender, clsid, CHARS_IN_GUID);
+ if (!(V_BSTR(&var) = SysAllocString(clsid)))
+ goto cleanup;
+ hr = IPropertyBag_Write(prop_bag, clsid_keyname, &var);
+ if (FAILED(hr)) goto cleanup;
+ VariantClear(&var);
+
+ /* write filter data */
+ rgf.dwVersion = 2;
+ rgf.dwMerit = MERIT_DO_NOT_USE;
+ rgf.u.s2.cPins2 = 1;
+ rgf.u.s2.rgPins2 = &rgpins;
+ rgpins.dwFlags = REG_PINFLAG_B_RENDERER;
+ rgpins.nMediaTypes = 1;
+ rgpins.lpMediaType = &rgtypes;
+ rgtypes.clsMajorType = &MEDIATYPE_Audio;
+ rgtypes.clsMinorType = &MEDIASUBTYPE_NULL;
+
+ write_filter_data(prop_bag, &rgf);
+
+ /* write WaveOutId */
+ V_VT(&var) = VT_I4;
+ V_I4(&var) = i;
+ hr = IPropertyBag_Write(prop_bag, waveoutidW, &var);
+ if (FAILED(hr)) goto cleanup;
+
+cleanup:
+ VariantClear(&var);
+ if (prop_bag) IPropertyBag_Release(prop_bag);
+ if (mon) IMoniker_Release(mon);
+ }
+}
- if (rgf2.u.s1.rgPins[iPin].lpMediaType)
- {
- UINT iType;
+static void register_wavein_devices(void)
+{
+ static const WCHAR waveinidW[] =
{'W','a','v','e','I','n','I','d',0};
+ IPropertyBag *prop_bag = NULL;
+ REGFILTER2 rgf = {0};
+ WCHAR clsid[CHARS_IN_GUID];
+ IMoniker *mon = NULL;
+ WAVEINCAPSW caps;
+ int i, count;
+ VARIANT var;
+ HRESULT hr;
- for (iType = 0; iType <
rgf2.u.s1.rgPins[iPin].nMediaTypes; iType++)
- {
-
CoTaskMemFree((void*)rgf2.u.s1.rgPins[iPin].lpMediaType[iType].clsMajorType);
-
CoTaskMemFree((void*)rgf2.u.s1.rgPins[iPin].lpMediaType[iType].clsMinorType);
- }
+ hr = DEVENUM_CreateAMCategoryKey(&CLSID_AudioRendererCategory);
+ if (FAILED(hr)) return;
- CoTaskMemFree((void*)rgf2.u.s1.rgPins[iPin].lpMediaType);
- }
- }
+ count = waveInGetNumDevs();
- CoTaskMemFree((void*)rgf2.u.s1.rgPins);
- }
- }
- }
+ for (i = 0; i < count; i++)
+ {
+ waveInGetDevCapsW(i, &caps, sizeof(caps));
+
+ V_VT(&var) = VT_BSTR;
+
+ V_BSTR(&var) = SysAllocString(caps.szPname);
+ if (!(V_BSTR(&var)))
+ goto cleanup;
+
+ hr = register_codec(&CLSID_AudioInputDeviceCategory, V_BSTR(&var),
&mon);
+ if (FAILED(hr)) goto cleanup;
+
+ hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void
**)&prop_bag);
+ if (FAILED(hr)) goto cleanup;
+
+ /* write friendly name */
+ hr = IPropertyBag_Write(prop_bag, wszFriendlyName, &var);
+ if (FAILED(hr)) goto cleanup;
+ VariantClear(&var);
+
+ /* write clsid */
+ V_VT(&var) = VT_BSTR;
+ StringFromGUID2(&CLSID_AudioRecord, clsid, CHARS_IN_GUID);
+ if (!(V_BSTR(&var) = SysAllocString(clsid)))
+ goto cleanup;
+ hr = IPropertyBag_Write(prop_bag, clsid_keyname, &var);
+ if (FAILED(hr)) goto cleanup;
+ VariantClear(&var);
+
+ /* write filter data */
+ rgf.dwVersion = 2;
+ rgf.dwMerit = MERIT_DO_NOT_USE;
+
+ write_filter_data(prop_bag, &rgf);
+
+ /* write WaveInId */
+ V_VT(&var) = VT_I4;
+ V_I4(&var) = i;
+ hr = IPropertyBag_Write(prop_bag, waveinidW, &var);
+ if (FAILED(hr)) goto cleanup;
+
+cleanup:
+ VariantClear(&var);
+ if (prop_bag) IPropertyBag_Release(prop_bag);
+ if (mon) IMoniker_Release(mon);
}
+}
- if (hkeyFilter) RegCloseKey(hkeyFilter);
+static void register_midiout_devices(void)
+{
+ static const WCHAR defaultW[] =
{'D','e','f','a','u','l','t','
','M','i','d','i','O','u','t','
','D','e','v','i','c','e',0};
+ static const WCHAR midioutidW[] =
{'M','i','d','i','O','u','t','I','d',0};
+ IPropertyBag *prop_bag = NULL;
+ REGFILTERPINS2 rgpins = {0};
+ REGPINTYPES rgtypes = {0};
+ REGFILTER2 rgf = {0};
+ WCHAR clsid[CHARS_IN_GUID];
+ IMoniker *mon = NULL;
+ MIDIOUTCAPSW caps;
+ int i, count;
+ VARIANT var;
+ HRESULT hr;
- if (pMapper)
- IFilterMapper2_Release(pMapper);
+ hr = DEVENUM_CreateAMCategoryKey(&CLSID_AudioRendererCategory);
+ if (FAILED(hr)) return;
+
+ count = midiOutGetNumDevs();
- return S_OK;
+ for (i = -1; i < count; i++)
+ {
+ midiOutGetDevCapsW(i, &caps, sizeof(caps));
+
+ V_VT(&var) = VT_BSTR;
+
+ if (i == -1) /* MIDI_MAPPER */
+ V_BSTR(&var) = SysAllocString(defaultW);
+ else
+ V_BSTR(&var) = SysAllocString(caps.szPname);
+ if (!(V_BSTR(&var)))
+ goto cleanup;
+
+ hr = register_codec(&CLSID_MidiRendererCategory, V_BSTR(&var),
&mon);
+ if (FAILED(hr)) goto cleanup;
+
+ hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void
**)&prop_bag);
+ if (FAILED(hr)) goto cleanup;
+
+ /* write friendly name */
+ hr = IPropertyBag_Write(prop_bag, wszFriendlyName, &var);
+ if (FAILED(hr)) goto cleanup;
+ VariantClear(&var);
+
+ /* write clsid */
+ V_VT(&var) = VT_BSTR;
+ StringFromGUID2(&CLSID_AVIMIDIRender, clsid, CHARS_IN_GUID);
+ if (!(V_BSTR(&var) = SysAllocString(clsid)))
+ goto cleanup;
+ hr = IPropertyBag_Write(prop_bag, clsid_keyname, &var);
+ if (FAILED(hr)) goto cleanup;
+ VariantClear(&var);
+
+ /* write filter data */
+ rgf.dwVersion = 2;
+ rgf.dwMerit = (i == -1) ? MERIT_PREFERRED : MERIT_DO_NOT_USE;
+ rgf.u.s2.cPins2 = 1;
+ rgf.u.s2.rgPins2 = &rgpins;
+ rgpins.dwFlags = REG_PINFLAG_B_RENDERER;
+ rgpins.nMediaTypes = 1;
+ rgpins.lpMediaType = &rgtypes;
+ rgtypes.clsMajorType = &MEDIATYPE_Midi;
+ rgtypes.clsMinorType = &MEDIASUBTYPE_NULL;
+
+ write_filter_data(prop_bag, &rgf);
+
+ /* write MidiOutId */
+ V_VT(&var) = VT_I4;
+ V_I4(&var) = i;
+ hr = IPropertyBag_Write(prop_bag, midioutidW, &var);
+ if (FAILED(hr)) goto cleanup;
+
+cleanup:
+ VariantClear(&var);
+ if (prop_bag) IPropertyBag_Release(prop_bag);
+ if (mon) IMoniker_Release(mon);
+ }
+}
+
+static void register_vfw_codecs(void)
+{
+ static const WCHAR fcchandlerW[] =
{'F','c','c','H','a','n','d','l','e','r',0};
+ REGFILTERPINS2 rgpins[2];
+ IPropertyBag *prop_bag = NULL;
+ REGPINTYPES rgtypes[2];
+ REGFILTER2 rgf;
+ WCHAR clsid[CHARS_IN_GUID];
+ IMoniker *mon = NULL;
+ GUID typeguid;
+ ICINFO info;
+ VARIANT var;
+ HRESULT hr;
+ int i = 0;
+ HIC hic;
+
+ hr = DEVENUM_CreateAMCategoryKey(&CLSID_AudioRendererCategory);
+ if (FAILED(hr)) return;
+
+ while (ICInfo(ICTYPE_VIDEO, i++, &info))
+ {
+ WCHAR name[5] = {LOBYTE(LOWORD(info.fccHandler)),
HIBYTE(LOWORD(info.fccHandler)),
+ LOBYTE(HIWORD(info.fccHandler)),
HIBYTE(HIWORD(info.fccHandler))};
+
+ hic = ICOpen(ICTYPE_VIDEO, info.fccHandler, ICMODE_QUERY);
+ ICGetInfo(hic, &info, sizeof(info));
+ ICClose(hic);
+
+ V_VT(&var) = VT_BSTR;
+
+ V_BSTR(&var) = SysAllocString(name);
+ if (!(V_BSTR(&var)))
+ goto cleanup;
+
+ hr = register_codec(&CLSID_VideoCompressorCategory, V_BSTR(&var),
&mon);
+ if (FAILED(hr)) goto cleanup;
+
+ hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void
**)&prop_bag);
+ if (FAILED(hr)) goto cleanup;
+
+ /* write WaveInId */
+ hr = IPropertyBag_Write(prop_bag, fcchandlerW, &var);
+ if (FAILED(hr)) goto cleanup;
+ VariantClear(&var);
+
+ /* write friendly name */
+ V_VT(&var) = VT_BSTR;
+ if (!(V_BSTR(&var) = SysAllocString(info.szDescription)))
+ goto cleanup;
+
+ hr = IPropertyBag_Write(prop_bag, wszFriendlyName, &var);
+ if (FAILED(hr)) goto cleanup;
+ VariantClear(&var);
+
+ /* write clsid */
+ V_VT(&var) = VT_BSTR;
+ StringFromGUID2(&CLSID_AVICo, clsid, CHARS_IN_GUID);
+ if (!(V_BSTR(&var) = SysAllocString(clsid)))
+ goto cleanup;
+ hr = IPropertyBag_Write(prop_bag, clsid_keyname, &var);
+ if (FAILED(hr)) goto cleanup;
+ VariantClear(&var);
+
+ /* write filter data */
+ rgf.dwVersion = 2;
+ rgf.dwMerit = MERIT_DO_NOT_USE;
+ rgf.u.s2.cPins2 = 2;
+ rgf.u.s2.rgPins2 = rgpins;
+ rgpins[0].dwFlags = 0;
+ rgpins[0].nMediaTypes = 1;
+ rgpins[0].lpMediaType = &rgtypes[0];
+ rgtypes[0].clsMajorType = &MEDIATYPE_Video;
+ typeguid = MEDIASUBTYPE_PCM;
+ typeguid.Data1 = info.fccHandler;
+ rgtypes[0].clsMinorType = &typeguid;
+ rgpins[1].dwFlags = REG_PINFLAG_B_OUTPUT;
+ rgpins[1].nMediaTypes = 1;
+ rgpins[1].lpMediaType = &rgtypes[1];
+ rgtypes[1].clsMajorType = &MEDIATYPE_Video;
+ rgtypes[1].clsMinorType = &GUID_NULL;
+
+ write_filter_data(prop_bag, &rgf);
+
+cleanup:
+ VariantClear(&var);
+ if (prop_bag) IPropertyBag_Release(prop_bag);
+ if (mon) IMoniker_Release(mon);
+ }
}
/**********************************************************************
@@ -513,7 +894,6 @@ static HRESULT WINAPI DEVENUM_ICreateDevEnum_CreateClassEnumerator(
IEnumMoniker **ppEnumMoniker,
DWORD dwFlags)
{
- HKEY hkey, special_hkey = NULL;
HRESULT hr;
TRACE("(%p)->(%s, %p, %x)\n", iface, debugstr_guid(clsidDeviceClass),
ppEnumMoniker, dwFlags);
@@ -523,34 +903,16 @@ static HRESULT WINAPI DEVENUM_ICreateDevEnum_CreateClassEnumerator(
*ppEnumMoniker = NULL;
- if (IsEqualGUID(clsidDeviceClass, &CLSID_LegacyAmFilterCategory))
- {
- DEVENUM_RegisterLegacyAmFilters();
- }
-
- if (IsSpecialCategory(clsidDeviceClass))
- {
- hr = DEVENUM_CreateSpecialCategories();
- if (FAILED(hr))
- return hr;
-
- special_hkey = open_special_category_key(clsidDeviceClass, FALSE);
- if (!special_hkey)
- {
- ERR("Couldn't open registry key for special device: %s\n",
- debugstr_guid(clsidDeviceClass));
- return S_FALSE;
- }
- }
-
- hkey = open_category_key(clsidDeviceClass);
- if (!hkey && !special_hkey)
- {
- FIXME("Category %s not found\n", debugstr_guid(clsidDeviceClass));
- return S_FALSE;
- }
+ register_codecs();
+ register_legacy_filters();
+ hr = DirectSoundEnumerateW(®ister_dsound_devices, NULL);
+ if (FAILED(hr)) return hr;
+ register_waveout_devices();
+ register_wavein_devices();
+ register_midiout_devices();
+ register_vfw_codecs();
- return DEVENUM_IEnumMoniker_Construct(hkey, special_hkey, ppEnumMoniker);
+ return create_EnumMoniker(clsidDeviceClass, ppEnumMoniker);
}
/**********************************************************************
@@ -601,164 +963,33 @@ static HRESULT DEVENUM_CreateAMCategoryKey(const CLSID *
clsidCategory)
return res;
}
-static void register_vfw_codecs(void)
-{
- WCHAR avico_clsid_str[CHARS_IN_GUID];
- HKEY basekey, key;
- ICINFO icinfo;
- DWORD i, res;
-
- static const WCHAR CLSIDW[] =
{'C','L','S','I','D',0};
- static const WCHAR FccHandlerW[] =
{'F','c','c','H','a','n','d','l','e','r',0};
- static const WCHAR FriendlyNameW[] =
{'F','r','i','e','n','d','l','y','N','a','m','e',0};
-
- StringFromGUID2(&CLSID_AVICo, avico_clsid_str,
sizeof(avico_clsid_str)/sizeof(WCHAR));
-
- basekey = open_special_category_key(&CLSID_VideoCompressorCategory, TRUE);
- if(!basekey) {
- ERR("Could not create key\n");
- return;
- }
-
- for(i=0; ICInfo(FCC('v','i','d','c'), i,
&icinfo); i++) {
- WCHAR fcc_str[5] = {LOBYTE(LOWORD(icinfo.fccHandler)),
HIBYTE(LOWORD(icinfo.fccHandler)),
- LOBYTE(HIWORD(icinfo.fccHandler)),
HIBYTE(HIWORD(icinfo.fccHandler))};
-
- res = RegCreateKeyW(basekey, fcc_str, &key);
- if(res != ERROR_SUCCESS)
- continue;
-
- RegSetValueExW(key, CLSIDW, 0, REG_SZ, (const BYTE*)avico_clsid_str,
sizeof(avico_clsid_str));
- RegSetValueExW(key, FccHandlerW, 0, REG_SZ, (const BYTE*)fcc_str,
sizeof(fcc_str));
- RegSetValueExW(key, FriendlyNameW, 0, REG_SZ, (const BYTE*)icinfo.szName,
(strlenW(icinfo.szName)+1)*sizeof(WCHAR));
- /* FIXME: Set ClassManagerFlags and FilterData values */
-
- RegCloseKey(key);
- }
-
- RegCloseKey(basekey);
-}
-
-static BOOL WINAPI acm_driver_callback(HACMDRIVERID hadid, DWORD_PTR user, DWORD
support)
-{
- static const WCHAR CLSIDW[] =
{'C','L','S','I','D',0};
- static const WCHAR AcmIdW[] =
{'A','c','m','I','d',0};
- static const WCHAR FriendlyNameW[] =
{'F','r','i','e','n','d','l','y','N','a','m','e',0};
- static const WCHAR fmtW[] = {'%','u','%','s',0};
-
- WCHAR acmwrapper_clsid_str[CHARS_IN_GUID], buffer[MAX_PATH];
- HKEY key, basekey = (HKEY) user;
- ACMFORMATTAGDETAILSW format;
- ACMDRIVERDETAILSW driver;
- HACMDRIVER had;
- DWORD i, res;
-
- StringFromGUID2(&CLSID_ACMWrapper, acmwrapper_clsid_str,
sizeof(acmwrapper_clsid_str)/sizeof(WCHAR));
-
- driver.cbStruct = sizeof(driver);
- if (acmDriverDetailsW(hadid, &driver, 0) != MMSYSERR_NOERROR)
- return TRUE;
-
- if (acmDriverOpen(&had, hadid, 0) != MMSYSERR_NOERROR)
- return TRUE;
-
- for (i = 0; i < driver.cFormatTags; i++)
- {
- memset(&format, 0, sizeof(format));
- format.cbStruct = sizeof(format);
- format.dwFormatTagIndex = i;
-
- if (acmFormatTagDetailsW(had, &format, ACM_FORMATTAGDETAILSF_INDEX) !=
MMSYSERR_NOERROR)
- continue;
-
- snprintfW(buffer, sizeof(buffer)/sizeof(WCHAR), fmtW, format.dwFormatTag,
format.szFormatTag);
-
- res = RegCreateKeyW(basekey, buffer, &key);
- if (res != ERROR_SUCCESS) continue;
-
- RegSetValueExW(key, CLSIDW, 0, REG_SZ, (BYTE*)acmwrapper_clsid_str,
sizeof(acmwrapper_clsid_str));
- RegSetValueExW(key, AcmIdW, 0, REG_DWORD, (BYTE*)&format.dwFormatTag,
sizeof(DWORD));
- RegSetValueExW(key, FriendlyNameW, 0, REG_SZ, (BYTE*)format.szFormatTag,
(strlenW(format.szFormatTag)+1)*sizeof(WCHAR));
- /* FIXME: Set FilterData values */
-
- RegCloseKey(key);
- }
-
- acmDriverClose(had, 0);
-
- return TRUE;
-}
-
-static void register_acm_codecs(void)
-{
- HKEY basekey;
-
- basekey = open_special_category_key(&CLSID_AudioCompressorCategory, TRUE);
- if (!basekey)
- {
- ERR("Could not create key\n");
- return;
- }
-
- acmDriverEnum(acm_driver_callback, (DWORD_PTR)basekey, 0);
-
- RegCloseKey(basekey);
-}
-
-static HANDLE DEVENUM_populate_handle;
-static const WCHAR DEVENUM_populate_handle_nameW[] =
-
{'_','_','W','I','N','E','_',
-
'D','e','v','e','n','u','m','_',
-
'P','o','p','u','l','a','t','e',0};
-
-/**********************************************************************
- * DEVENUM_CreateSpecialCategories (INTERNAL)
- *
- * Creates the keys in the registry for the dynamic categories
- */
-static HRESULT DEVENUM_CreateSpecialCategories(void)
+static HRESULT register_codecs(void)
{
HRESULT res;
- WCHAR szDSoundNameFormat[MAX_PATH + 1];
- WCHAR szDSoundName[MAX_PATH + 1];
+ WCHAR class[CHARS_IN_GUID];
DWORD iDefaultDevice = -1;
- UINT numDevs;
IFilterMapper2 * pMapper = NULL;
REGFILTER2 rf2;
REGFILTERPINS2 rfp2;
- WCHAR path[MAX_PATH];
HKEY basekey;
- if (DEVENUM_populate_handle)
- return S_OK;
- DEVENUM_populate_handle = CreateEventW(NULL, TRUE, FALSE,
DEVENUM_populate_handle_nameW);
- if (GetLastError() == ERROR_ALREADY_EXISTS)
- {
- /* Webcams can take some time to scan if the driver is badly written and it
enables them,
- * so have a 10 s timeout here
- */
- if (WaitForSingleObject(DEVENUM_populate_handle, 10000) == WAIT_TIMEOUT)
- WARN("Waiting for object timed out\n");
- TRACE("No need to rescan\n");
- return S_OK;
- }
- TRACE("Scanning for devices\n");
-
/* Since devices can change between session, for example because you just plugged in
a webcam
* or switched from pulseaudio to alsa, delete all old devices first
*/
- if (SUCCEEDED(DEVENUM_GetCategoryKey(&CLSID_AudioRendererCategory, &basekey,
path, MAX_PATH)))
- RegDeleteTreeW(basekey, path);
- if (SUCCEEDED(DEVENUM_GetCategoryKey(&CLSID_AudioInputDeviceCategory,
&basekey, path, MAX_PATH)))
- RegDeleteTreeW(basekey, path);
- if (SUCCEEDED(DEVENUM_GetCategoryKey(&CLSID_VideoInputDeviceCategory,
&basekey, path, MAX_PATH)))
- RegDeleteTreeW(basekey, path);
- if (SUCCEEDED(DEVENUM_GetCategoryKey(&CLSID_MidiRendererCategory, &basekey,
path, MAX_PATH)))
- RegDeleteTreeW(basekey, path);
- if (SUCCEEDED(DEVENUM_GetCategoryKey(&CLSID_VideoCompressorCategory,
&basekey, path, MAX_PATH)))
- RegDeleteTreeW(basekey, path);
- if (SUCCEEDED(DEVENUM_GetCategoryKey(&CLSID_AudioCompressorCategory,
&basekey, path, MAX_PATH)))
- RegDeleteTreeW(basekey, path);
+ RegOpenKeyW(HKEY_CURRENT_USER, wszActiveMovieKey, &basekey);
+ StringFromGUID2(&CLSID_LegacyAmFilterCategory, class, CHARS_IN_GUID);
+ RegDeleteTreeW(basekey, class);
+ StringFromGUID2(&CLSID_AudioRendererCategory, class, CHARS_IN_GUID);
+ RegDeleteTreeW(basekey, class);
+ StringFromGUID2(&CLSID_AudioInputDeviceCategory, class, CHARS_IN_GUID);
+ RegDeleteTreeW(basekey, class);
+ StringFromGUID2(&CLSID_VideoInputDeviceCategory, class, CHARS_IN_GUID);
+ RegDeleteTreeW(basekey, class);
+ StringFromGUID2(&CLSID_MidiRendererCategory, class, CHARS_IN_GUID);
+ RegDeleteTreeW(basekey, class);
+ StringFromGUID2(&CLSID_VideoCompressorCategory, class, CHARS_IN_GUID);
+ RegDeleteTreeW(basekey, class);
+ RegCloseKey(basekey);
rf2.dwVersion = 2;
rf2.dwMerit = MERIT_PREFERRED;
@@ -769,12 +1000,6 @@ static HRESULT DEVENUM_CreateSpecialCategories(void)
rfp2.lpMedium = NULL;
rfp2.clsPinCategory = &IID_NULL;
- if (!LoadStringW(DEVENUM_hInstance, IDS_DEVENUM_DS, szDSoundNameFormat,
sizeof(szDSoundNameFormat)/sizeof(szDSoundNameFormat[0])-1))
- {
- ERR("Couldn't get string resource (GetLastError() is %d)\n",
GetLastError());
- return HRESULT_FROM_WIN32(GetLastError());
- }
-
res = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC,
&IID_IFilterMapper2, (void **) &pMapper);
/*
@@ -783,205 +1008,9 @@ static HRESULT DEVENUM_CreateSpecialCategories(void)
if (SUCCEEDED(res))
{
UINT i;
- WAVEOUTCAPSW wocaps;
- WAVEINCAPSW wicaps;
- MIDIOUTCAPSW mocaps;
REGPINTYPES * pTypes;
IPropertyBag * pPropBag = NULL;
- numDevs = waveOutGetNumDevs();
-
- res = DEVENUM_CreateAMCategoryKey(&CLSID_AudioRendererCategory);
- if (FAILED(res)) /* can't register any devices in this category */
- numDevs = 0;
-
- rfp2.dwFlags = REG_PINFLAG_B_RENDERER;
- for (i = 0; i < numDevs; i++)
- {
- if (waveOutGetDevCapsW(i, &wocaps, sizeof(WAVEOUTCAPSW))
- == MMSYSERR_NOERROR)
- {
- IMoniker * pMoniker = NULL;
-
- rfp2.nMediaTypes = 1;
- pTypes = CoTaskMemAlloc(rfp2.nMediaTypes * sizeof(REGPINTYPES));
- if (!pTypes)
- {
- IFilterMapper2_Release(pMapper);
- return E_OUTOFMEMORY;
- }
- /* FIXME: Native devenum seems to register a lot more types for
- * DSound than we do. Not sure what purpose they serve */
- pTypes[0].clsMajorType = &MEDIATYPE_Audio;
- pTypes[0].clsMinorType = &MEDIASUBTYPE_PCM;
-
- rfp2.lpMediaType = pTypes;
-
- res = IFilterMapper2_RegisterFilter(pMapper,
- &CLSID_AudioRender,
- wocaps.szPname,
- &pMoniker,
- &CLSID_AudioRendererCategory,
- wocaps.szPname,
- &rf2);
-
- if (pMoniker)
- {
- VARIANT var;
-
- V_VT(&var) = VT_I4;
- V_I4(&var) = i;
- res = IMoniker_BindToStorage(pMoniker, NULL, NULL,
&IID_IPropertyBag, (LPVOID)&pPropBag);
- if (SUCCEEDED(res))
- res = IPropertyBag_Write(pPropBag, wszWaveOutID, &var);
- else
- pPropBag = NULL;
-
- V_VT(&var) = VT_LPWSTR;
- V_BSTR(&var) = wocaps.szPname;
- if (SUCCEEDED(res))
- res = IPropertyBag_Write(pPropBag, wszFriendlyName, &var);
- if (pPropBag)
- IPropertyBag_Release(pPropBag);
- IMoniker_Release(pMoniker);
- pMoniker = NULL;
- }
-
- wsprintfW(szDSoundName, szDSoundNameFormat, wocaps.szPname);
- res = IFilterMapper2_RegisterFilter(pMapper,
- &CLSID_DSoundRender,
- szDSoundName,
- &pMoniker,
- &CLSID_AudioRendererCategory,
- szDSoundName,
- &rf2);
-
- /* FIXME: do additional stuff with IMoniker here, depending on what
RegisterFilter does */
-
- if (pMoniker)
- IMoniker_Release(pMoniker);
-
- if (i == iDefaultDevice)
- {
- FIXME("Default device\n");
- }
-
- CoTaskMemFree(pTypes);
- }
- }
-
- numDevs = waveInGetNumDevs();
-
- res = DEVENUM_CreateAMCategoryKey(&CLSID_AudioInputDeviceCategory);
- if (FAILED(res)) /* can't register any devices in this category */
- numDevs = 0;
-
- rfp2.dwFlags = REG_PINFLAG_B_OUTPUT;
- for (i = 0; i < numDevs; i++)
- {
- if (waveInGetDevCapsW(i, &wicaps, sizeof(WAVEINCAPSW))
- == MMSYSERR_NOERROR)
- {
- IMoniker * pMoniker = NULL;
-
- rfp2.nMediaTypes = 1;
- pTypes = CoTaskMemAlloc(rfp2.nMediaTypes * sizeof(REGPINTYPES));
- if (!pTypes)
- {
- IFilterMapper2_Release(pMapper);
- return E_OUTOFMEMORY;
- }
-
- /* FIXME: Not sure if these are correct */
- pTypes[0].clsMajorType = &MEDIATYPE_Audio;
- pTypes[0].clsMinorType = &MEDIASUBTYPE_PCM;
-
- rfp2.lpMediaType = pTypes;
-
- res = IFilterMapper2_RegisterFilter(pMapper,
- &CLSID_AudioRecord,
- wicaps.szPname,
- &pMoniker,
- &CLSID_AudioInputDeviceCategory,
- wicaps.szPname,
- &rf2);
-
-
- if (pMoniker) {
- VARIANT var;
-
- V_VT(&var) = VT_I4;
- V_I4(&var) = i;
- res = IMoniker_BindToStorage(pMoniker, NULL, NULL,
&IID_IPropertyBag, (LPVOID)&pPropBag);
- if (SUCCEEDED(res))
- res = IPropertyBag_Write(pPropBag, wszWaveInID, &var);
- else
- pPropBag = NULL;
-
- V_VT(&var) = VT_LPWSTR;
- V_BSTR(&var) = wicaps.szPname;
- if (SUCCEEDED(res))
- res = IPropertyBag_Write(pPropBag, wszFriendlyName, &var);
-
- if (pPropBag)
- IPropertyBag_Release(pPropBag);
- IMoniker_Release(pMoniker);
- }
-
- CoTaskMemFree(pTypes);
- }
- }
-
- numDevs = midiOutGetNumDevs();
-
- res = DEVENUM_CreateAMCategoryKey(&CLSID_MidiRendererCategory);
- if (FAILED(res)) /* can't register any devices in this category */
- numDevs = 0;
-
- rfp2.dwFlags = REG_PINFLAG_B_RENDERER;
- for (i = 0; i < numDevs; i++)
- {
- if (midiOutGetDevCapsW(i, &mocaps, sizeof(MIDIOUTCAPSW))
- == MMSYSERR_NOERROR)
- {
- IMoniker * pMoniker = NULL;
-
- rfp2.nMediaTypes = 1;
- pTypes = CoTaskMemAlloc(rfp2.nMediaTypes * sizeof(REGPINTYPES));
- if (!pTypes)
- {
- IFilterMapper2_Release(pMapper);
- return E_OUTOFMEMORY;
- }
-
- /* FIXME: Not sure if these are correct */
- pTypes[0].clsMajorType = &MEDIATYPE_Midi;
- pTypes[0].clsMinorType = &MEDIASUBTYPE_None;
-
- rfp2.lpMediaType = pTypes;
-
- res = IFilterMapper2_RegisterFilter(pMapper,
- &CLSID_AVIMIDIRender,
- mocaps.szPname,
- &pMoniker,
- &CLSID_MidiRendererCategory,
- mocaps.szPname,
- &rf2);
-
- /* FIXME: do additional stuff with IMoniker here, depending on what
RegisterFilter does */
- /* Native version sets MidiOutId */
-
- if (pMoniker)
- IMoniker_Release(pMoniker);
-
- if (i == iDefaultDevice)
- {
- FIXME("Default device\n");
- }
-
- CoTaskMemFree(pTypes);
- }
- }
res = DEVENUM_CreateAMCategoryKey(&CLSID_VideoInputDeviceCategory);
if (SUCCEEDED(res))
for (i = 0; i < 10; i++)
@@ -1039,9 +1068,5 @@ static HRESULT DEVENUM_CreateSpecialCategories(void)
if (pMapper)
IFilterMapper2_Release(pMapper);
- register_vfw_codecs();
- register_acm_codecs();
-
- SetEvent(DEVENUM_populate_handle);
return res;
}
diff --git a/dll/directx/wine/devenum/devenum.rc b/dll/directx/wine/devenum/devenum.rc
index 294d41ff23..1cc74a4394 100644
--- a/dll/directx/wine/devenum/devenum.rc
+++ b/dll/directx/wine/devenum/devenum.rc
@@ -23,18 +23,6 @@
#include "winnls.h"
#include "devenum_private.h"
-#pragma makedep po
-
-LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT
-
-STRINGTABLE
-{
- IDS_DEVENUM_DSDEFAULT "Default DirectSound"
- IDS_DEVENUM_DS "DirectSound: %s"
- IDS_DEVENUM_WODEFAULT "Default WaveOut Device"
- IDS_DEVENUM_MIDEFAULT "Default MidiOut Device"
-}
-
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
#define WINE_FILEDESCRIPTION_STR "Wine Device Enumerator Library"
diff --git a/dll/directx/wine/devenum/devenum_private.h
b/dll/directx/wine/devenum/devenum_private.h
index 72c285d422..005f0b56e6 100644
--- a/dll/directx/wine/devenum/devenum_private.h
+++ b/dll/directx/wine/devenum/devenum_private.h
@@ -62,38 +62,40 @@ typedef struct
IClassFactory IClassFactory_iface;
} ClassFactoryImpl;
+enum device_type
+{
+ DEVICE_FILTER,
+ DEVICE_CODEC,
+};
+
typedef struct
{
IMoniker IMoniker_iface;
LONG ref;
- HKEY hkey;
+ CLSID class;
+ BOOL has_class;
+ enum device_type type;
+ WCHAR *name;
} MediaCatMoniker;
MediaCatMoniker * DEVENUM_IMediaCatMoniker_Construct(void) DECLSPEC_HIDDEN;
-HRESULT DEVENUM_IEnumMoniker_Construct(HKEY hkey, HKEY special_hkey, IEnumMoniker **
ppEnumMoniker) DECLSPEC_HIDDEN;
+HRESULT create_EnumMoniker(REFCLSID class, IEnumMoniker **enum_mon) DECLSPEC_HIDDEN;
extern ClassFactoryImpl DEVENUM_ClassFactory DECLSPEC_HIDDEN;
extern ICreateDevEnum DEVENUM_CreateDevEnum DECLSPEC_HIDDEN;
extern IParseDisplayName DEVENUM_ParseDisplayName DECLSPEC_HIDDEN;
-/**********************************************************************
- * Private helper function to get AM filter category key location
- */
-HRESULT DEVENUM_GetCategoryKey(REFCLSID clsidDeviceClass, HKEY *pBaseKey, WCHAR
*wszRegKeyName, UINT maxLen) DECLSPEC_HIDDEN;
-
/**********************************************************************
* Global string constant declarations
*/
-extern const WCHAR clsid_keyname[6] DECLSPEC_HIDDEN;
-extern const WCHAR wszInstanceKeyName[] DECLSPEC_HIDDEN;
-#define CLSID_STR_LEN (sizeof(clsid_keyname) / sizeof(WCHAR))
-/**********************************************************************
- * Resource IDs
- */
-#define IDS_DEVENUM_DSDEFAULT 7
-#define IDS_DEVENUM_DS 8
-#define IDS_DEVENUM_WODEFAULT 9
-#define IDS_DEVENUM_MIDEFAULT 10
-#define IDS_DEVENUM_KSDEFAULT 11
-#define IDS_DEVENUM_KS 12
+static const WCHAR backslashW[] = {'\\',0};
+static const WCHAR clsidW[] =
{'C','L','S','I','D','\\',0};
+static const WCHAR instanceW[] =
{'\\','I','n','s','t','a','n','c','e',0};
+static const WCHAR wszActiveMovieKey[] =
{'S','o','f','t','w','a','r','e','\\',
+
'M','i','c','r','o','s','o','f','t','\\',
+
'A','c','t','i','v','e','M','o','v','i','e','\\',
+
'd','e','v','e','n','u','m','\\',0};
+static const WCHAR deviceW[] =
{'@','d','e','v','i','c','e',':',0};
+
+extern const WCHAR clsid_keyname[6] DECLSPEC_HIDDEN;
diff --git a/dll/directx/wine/devenum/fil_data.idl
b/dll/directx/wine/devenum/fil_data.idl
new file mode 100644
index 0000000000..7e37a755d9
--- /dev/null
+++ b/dll/directx/wine/devenum/fil_data.idl
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2009 Vitaliy Margolen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#pragma makedep header
+
+import "objidl.idl";
+import "strmif.idl";
+import "unknwn.idl";
+
+
+/*****************************************************************************
+ * IAMFilterData interface
+ */
+[
+ object,
+ uuid(97f7c4d4-547b-4a5f-8332-536430ad2e4d),
+ pointer_default(unique)
+]
+interface IAMFilterData : IUnknown
+{
+ typedef [unique] IAMFilterData *LPIAMFILTERDATA;
+
+ HRESULT ParseFilterData(
+ [in] BYTE * rgbFilterData,
+ [in] ULONG cb,
+ [out] BYTE ** prgbRegFilter2);
+
+ HRESULT CreateFilterData(
+ [in] REGFILTER2 * prf2,
+ [out] BYTE ** prgbFilterData,
+ [out] ULONG * pcb);
+}
diff --git a/dll/directx/wine/devenum/mediacatenum.c
b/dll/directx/wine/devenum/mediacatenum.c
index 4edc4e9622..a76c7bebfb 100644
--- a/dll/directx/wine/devenum/mediacatenum.c
+++ b/dll/directx/wine/devenum/mediacatenum.c
@@ -33,18 +33,20 @@ WINE_DEFAULT_DEBUG_CHANNEL(devenum);
typedef struct
{
IEnumMoniker IEnumMoniker_iface;
+ CLSID class;
LONG ref;
- DWORD index;
- DWORD subkey_cnt;
- HKEY hkey;
- HKEY special_hkey;
+ HKEY sw_key;
+ DWORD sw_index;
+ HKEY cm_key;
+ DWORD cm_index;
} EnumMonikerImpl;
typedef struct
{
IPropertyBag IPropertyBag_iface;
LONG ref;
- HKEY hkey;
+ enum device_type type;
+ WCHAR path[MAX_PATH];
} RegPropBagImpl;
@@ -100,7 +102,6 @@ static ULONG WINAPI DEVENUM_IPropertyBag_Release(LPPROPERTYBAG iface)
ref = InterlockedDecrement(&This->ref);
if (ref == 0) {
- RegCloseKey(This->hkey);
CoTaskMemFree(This);
DEVENUM_UnlockModule();
}
@@ -118,22 +119,32 @@ static HRESULT WINAPI DEVENUM_IPropertyBag_Read(
DWORD type = 0;
RegPropBagImpl *This = impl_from_IPropertyBag(iface);
HRESULT res = S_OK;
- LONG reswin32;
+ LONG reswin32 = ERROR_SUCCESS;
+ HKEY hkey;
TRACE("(%p)->(%s, %p, %p)\n", This, debugstr_w(pszPropName), pVar,
pErrorLog);
if (!pszPropName || !pVar)
return E_POINTER;
- reswin32 = RegQueryValueExW(This->hkey, pszPropName, NULL, NULL, NULL,
&received);
+ if (This->type == DEVICE_FILTER)
+ reswin32 = RegOpenKeyW(HKEY_CLASSES_ROOT, This->path, &hkey);
+ else if (This->type == DEVICE_CODEC)
+ reswin32 = RegOpenKeyW(HKEY_CURRENT_USER, This->path, &hkey);
res = HRESULT_FROM_WIN32(reswin32);
+ if (SUCCEEDED(res))
+ {
+ reswin32 = RegQueryValueExW(hkey, pszPropName, NULL, NULL, NULL, &received);
+ res = HRESULT_FROM_WIN32(reswin32);
+ }
+
if (SUCCEEDED(res))
{
pData = HeapAlloc(GetProcessHeap(), 0, received);
/* work around a GCC bug that occurs here unless we use the reswin32 variable as
well */
- reswin32 = RegQueryValueExW(This->hkey, pszPropName, NULL, &type, pData,
&received);
+ reswin32 = RegQueryValueExW(hkey, pszPropName, NULL, &type, pData,
&received);
res = HRESULT_FROM_WIN32(reswin32);
}
@@ -214,6 +225,8 @@ static HRESULT WINAPI DEVENUM_IPropertyBag_Read(
HeapFree(GetProcessHeap(), 0, pData);
+ RegCloseKey(hkey);
+
TRACE("<- %x\n", res);
return res;
}
@@ -228,6 +241,8 @@ static HRESULT WINAPI DEVENUM_IPropertyBag_Write(
DWORD cbData = 0;
DWORD dwType = 0;
HRESULT res = S_OK;
+ LONG lres = ERROR_SUCCESS;
+ HKEY hkey;
TRACE("(%p)->(%s, %p)\n", This, debugstr_w(pszPropName), pVar);
@@ -264,10 +279,18 @@ static HRESULT WINAPI DEVENUM_IPropertyBag_Write(
return E_FAIL;
}
- if (RegSetValueExW(This->hkey,
- pszPropName, 0,
- dwType, lpData, cbData) != ERROR_SUCCESS)
- res = E_FAIL;
+ if (This->type == DEVICE_FILTER)
+ lres = RegCreateKeyW(HKEY_CLASSES_ROOT, This->path, &hkey);
+ else if (This->type == DEVICE_CODEC)
+ lres = RegCreateKeyW(HKEY_CURRENT_USER, This->path, &hkey);
+ res = HRESULT_FROM_WIN32(lres);
+
+ if (SUCCEEDED(res))
+ {
+ lres = RegSetValueExW(hkey, pszPropName, 0, dwType, lpData, cbData);
+ res = HRESULT_FROM_WIN32(lres);
+ RegCloseKey(hkey);
+ }
if (V_VT(pVar) & VT_ARRAY)
res = SafeArrayUnaccessData(V_ARRAY(pVar));
@@ -284,14 +307,28 @@ static const IPropertyBagVtbl IPropertyBag_Vtbl =
DEVENUM_IPropertyBag_Write
};
-static HRESULT DEVENUM_IPropertyBag_Construct(HANDLE hkey, IPropertyBag **ppBag)
+static HRESULT create_PropertyBag(MediaCatMoniker *mon, IPropertyBag **ppBag)
{
RegPropBagImpl * rpb = CoTaskMemAlloc(sizeof(RegPropBagImpl));
if (!rpb)
return E_OUTOFMEMORY;
rpb->IPropertyBag_iface.lpVtbl = &IPropertyBag_Vtbl;
rpb->ref = 1;
- rpb->hkey = hkey;
+ rpb->type = mon->type;
+
+ if (rpb->type == DEVICE_FILTER)
+ strcpyW(rpb->path, clsidW);
+ else if (rpb->type == DEVICE_CODEC)
+ strcpyW(rpb->path, wszActiveMovieKey);
+ if (mon->has_class)
+ {
+ StringFromGUID2(&mon->class, rpb->path + strlenW(rpb->path),
CHARS_IN_GUID);
+ if (rpb->type == DEVICE_FILTER)
+ strcatW(rpb->path, instanceW);
+ strcatW(rpb->path, backslashW);
+ }
+ strcatW(rpb->path, mon->name);
+
*ppBag = &rpb->IPropertyBag_iface;
DEVENUM_LockModule();
return S_OK;
@@ -344,7 +381,7 @@ static ULONG WINAPI DEVENUM_IMediaCatMoniker_Release(IMoniker *iface)
TRACE("(%p) ref=%d\n", This, ref);
if (ref == 0) {
- RegCloseKey(This->hkey);
+ CoTaskMemFree(This->name);
CoTaskMemFree(This);
DEVENUM_UnlockModule();
}
@@ -407,6 +444,9 @@ static HRESULT WINAPI DEVENUM_IMediaCatMoniker_BindToObject(IMoniker
*iface, IBi
TRACE("(%p)->(%p, %p, %s, %p)\n", This, pbc, pmkToLeft,
debugstr_guid(riidResult), ppvResult);
+ if (!ppvResult)
+ return E_POINTER;
+
VariantInit(&var);
*ppvResult = NULL;
@@ -485,9 +525,7 @@ static HRESULT WINAPI DEVENUM_IMediaCatMoniker_BindToStorage(IMoniker
*iface, IB
if (IsEqualGUID(riid, &IID_IPropertyBag))
{
- HANDLE hkey;
- DuplicateHandle(GetCurrentProcess(), This->hkey, GetCurrentProcess(),
&hkey, 0, 0, DUPLICATE_SAME_ACCESS);
- return DEVENUM_IPropertyBag_Construct(hkey, (IPropertyBag**)ppvObj);
+ return create_PropertyBag(This, (IPropertyBag**)ppvObj);
}
return MK_E_NOSTORAGE;
@@ -620,24 +658,35 @@ static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_RelativePathTo(IMoniker *iface, I
static HRESULT WINAPI DEVENUM_IMediaCatMoniker_GetDisplayName(IMoniker *iface, IBindCtx
*pbc,
IMoniker *pmkToLeft, LPOLESTR *ppszDisplayName)
{
+ static const WCHAR swW[] = {'s','w',':',0};
+ static const WCHAR cmW[] = {'c','m',':',0};
MediaCatMoniker *This = impl_from_IMoniker(iface);
- WCHAR wszBuffer[MAX_PATH];
- static const WCHAR wszFriendlyName[] =
{'F','r','i','e','n','d','l','y','N','a','m','e',0};
- DWORD received = sizeof(wszBuffer);
+ WCHAR *buffer;
TRACE("(%p)->(%p, %p, %p)\n", iface, pbc, pmkToLeft, ppszDisplayName);
*ppszDisplayName = NULL;
- /* FIXME: should this be the weird stuff we have to parse in IParseDisplayName? */
- if (RegQueryValueExW(This->hkey, wszFriendlyName, NULL, NULL, (LPBYTE)wszBuffer,
&received) == ERROR_SUCCESS)
+ buffer = CoTaskMemAlloc((strlenW(deviceW) + 4 + (This->has_class ? CHARS_IN_GUID :
0)
+ + strlenW(This->name) + 1) * sizeof(WCHAR));
+ if (!buffer)
+ return E_OUTOFMEMORY;
+
+ strcpyW(buffer, deviceW);
+ if (This->type == DEVICE_FILTER)
+ strcatW(buffer, swW);
+ else if (This->type == DEVICE_CODEC)
+ strcatW(buffer, cmW);
+
+ if (This->has_class)
{
- *ppszDisplayName = CoTaskMemAlloc(received);
- strcpyW(*ppszDisplayName, wszBuffer);
- return S_OK;
+ StringFromGUID2(&This->class, buffer + strlenW(buffer), CHARS_IN_GUID);
+ strcatW(buffer, backslashW);
}
+ strcatW(buffer, This->name);
- return E_FAIL;
+ *ppszDisplayName = buffer;
+ return S_OK;
}
static HRESULT WINAPI DEVENUM_IMediaCatMoniker_ParseDisplayName(IMoniker *iface, IBindCtx
*pbc,
@@ -694,7 +743,8 @@ MediaCatMoniker * DEVENUM_IMediaCatMoniker_Construct(void)
pMoniker->IMoniker_iface.lpVtbl = &IMoniker_Vtbl;
pMoniker->ref = 0;
- pMoniker->hkey = NULL;
+ pMoniker->has_class = FALSE;
+ pMoniker->name = NULL;
DEVENUM_IMediaCatMoniker_AddRef(&pMoniker->IMoniker_iface);
@@ -748,9 +798,8 @@ static ULONG WINAPI DEVENUM_IEnumMoniker_Release(IEnumMoniker *iface)
if (!ref)
{
- if(This->special_hkey)
- RegCloseKey(This->special_hkey);
- RegCloseKey(This->hkey);
+ RegCloseKey(This->sw_key);
+ RegCloseKey(This->cm_key);
CoTaskMemFree(This);
DEVENUM_UnlockModule();
return 0;
@@ -766,37 +815,55 @@ static HRESULT WINAPI DEVENUM_IEnumMoniker_Next(IEnumMoniker *iface,
ULONG celt,
LONG res;
ULONG fetched = 0;
MediaCatMoniker * pMoniker;
+ HKEY hkey;
TRACE("(%p)->(%d, %p, %p)\n", iface, celt, rgelt, pceltFetched);
while (fetched < celt)
{
- if(This->index+fetched < This->subkey_cnt)
- res = RegEnumKeyW(This->hkey, This->index+fetched, buffer,
sizeof(buffer) / sizeof(WCHAR));
- else if(This->special_hkey)
- res = RegEnumKeyW(This->special_hkey,
This->index+fetched-This->subkey_cnt, buffer, sizeof(buffer) / sizeof(WCHAR));
- else
- break;
- if (res != ERROR_SUCCESS)
+ /* FIXME: try PNP devices and DMOs first */
+
+ /* try DirectShow filters */
+ if (!(res = RegEnumKeyW(This->sw_key, This->sw_index, buffer,
sizeof(buffer)/sizeof(WCHAR))))
{
- break;
+ This->sw_index++;
+ if ((res = RegOpenKeyExW(This->sw_key, buffer, 0, KEY_QUERY_VALUE,
&hkey)))
+ break;
+
+ if (!(pMoniker = DEVENUM_IMediaCatMoniker_Construct()))
+ return E_OUTOFMEMORY;
+
+ pMoniker->type = DEVICE_FILTER;
}
- pMoniker = DEVENUM_IMediaCatMoniker_Construct();
- if (!pMoniker)
- return E_OUTOFMEMORY;
+ /* then try codecs */
+ else if (!(res = RegEnumKeyW(This->cm_key, This->cm_index, buffer,
sizeof(buffer)/sizeof(WCHAR))))
+ {
+ This->cm_index++;
+
+ if ((res = RegOpenKeyExW(This->cm_key, buffer, 0, KEY_QUERY_VALUE,
&hkey)))
+ break;
- if (RegOpenKeyW(This->index+fetched < This->subkey_cnt ? This->hkey :
This->special_hkey,
- buffer, &pMoniker->hkey) != ERROR_SUCCESS)
+ if (!(pMoniker = DEVENUM_IMediaCatMoniker_Construct()))
+ return E_OUTOFMEMORY;
+
+ pMoniker->type = DEVICE_CODEC;
+ }
+ else
+ break;
+
+ if (!(pMoniker->name = CoTaskMemAlloc((strlenW(buffer) + 1) *
sizeof(WCHAR))))
{
IMoniker_Release(&pMoniker->IMoniker_iface);
- break;
+ return E_OUTOFMEMORY;
}
+ strcpyW(pMoniker->name, buffer);
+ pMoniker->has_class = TRUE;
+ pMoniker->class = This->class;
+
rgelt[fetched] = &pMoniker->IMoniker_iface;
fetched++;
}
- This->index += fetched;
-
TRACE("-- fetched %d\n", fetched);
if (pceltFetched)
@@ -811,21 +878,26 @@ static HRESULT WINAPI DEVENUM_IEnumMoniker_Next(IEnumMoniker *iface,
ULONG celt,
static HRESULT WINAPI DEVENUM_IEnumMoniker_Skip(IEnumMoniker *iface, ULONG celt)
{
EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
- DWORD special_subkeys = 0;
TRACE("(%p)->(%d)\n", iface, celt);
- /* Before incrementing, check if there are any more values to run through.
- Some programs use the Skip() function to get the number of devices */
- if(This->special_hkey)
- RegQueryInfoKeyW(This->special_hkey, NULL, NULL, NULL, &special_subkeys,
NULL, NULL, NULL, NULL, NULL, NULL, NULL);
-
- if((This->index + celt) >= This->subkey_cnt + special_subkeys)
+ while (celt--)
{
- return S_FALSE;
- }
+ /* FIXME: try PNP devices and DMOs first */
- This->index += celt;
+ /* try DirectShow filters */
+ if (RegEnumKeyW(This->sw_key, This->sw_index, NULL, 0) !=
ERROR_NO_MORE_ITEMS)
+ {
+ This->sw_index++;
+ }
+ /* then try codecs */
+ else if (RegEnumKeyW(This->cm_key, This->cm_index, NULL, 0) !=
ERROR_NO_MORE_ITEMS)
+ {
+ This->cm_index++;
+ }
+ else
+ return S_FALSE;
+ }
return S_OK;
}
@@ -836,7 +908,8 @@ static HRESULT WINAPI DEVENUM_IEnumMoniker_Reset(IEnumMoniker *iface)
TRACE("(%p)->()\n", iface);
- This->index = 0;
+ This->sw_index = 0;
+ This->cm_index = 0;
return S_OK;
}
@@ -862,23 +935,32 @@ static const IEnumMonikerVtbl IEnumMoniker_Vtbl =
DEVENUM_IEnumMoniker_Clone
};
-HRESULT DEVENUM_IEnumMoniker_Construct(HKEY hkey, HKEY special_hkey, IEnumMoniker **
ppEnumMoniker)
+HRESULT create_EnumMoniker(REFCLSID class, IEnumMoniker **ppEnumMoniker)
{
EnumMonikerImpl * pEnumMoniker = CoTaskMemAlloc(sizeof(EnumMonikerImpl));
+ WCHAR buffer[78];
+
if (!pEnumMoniker)
return E_OUTOFMEMORY;
pEnumMoniker->IEnumMoniker_iface.lpVtbl = &IEnumMoniker_Vtbl;
pEnumMoniker->ref = 1;
- pEnumMoniker->index = 0;
- pEnumMoniker->hkey = hkey;
- pEnumMoniker->special_hkey = special_hkey;
+ pEnumMoniker->sw_index = 0;
+ pEnumMoniker->cm_index = 0;
+ pEnumMoniker->class = *class;
- *ppEnumMoniker = &pEnumMoniker->IEnumMoniker_iface;
+ strcpyW(buffer, clsidW);
+ StringFromGUID2(class, buffer + strlenW(buffer), CHARS_IN_GUID);
+ strcatW(buffer, instanceW);
+ if (RegOpenKeyExW(HKEY_CLASSES_ROOT, buffer, 0, KEY_ENUMERATE_SUB_KEYS,
&pEnumMoniker->sw_key))
+ pEnumMoniker->sw_key = NULL;
- if(RegQueryInfoKeyW(pEnumMoniker->hkey, NULL, NULL, NULL,
&pEnumMoniker->subkey_cnt, NULL, NULL, NULL, NULL, NULL, NULL, NULL) !=
ERROR_SUCCESS)
- pEnumMoniker->subkey_cnt = 0;
+ strcpyW(buffer, wszActiveMovieKey);
+ StringFromGUID2(class, buffer + strlenW(buffer), CHARS_IN_GUID);
+ if (RegOpenKeyExW(HKEY_CURRENT_USER, buffer, 0, KEY_ENUMERATE_SUB_KEYS,
&pEnumMoniker->cm_key))
+ pEnumMoniker->cm_key = NULL;
+ *ppEnumMoniker = &pEnumMoniker->IEnumMoniker_iface;
DEVENUM_LockModule();
diff --git a/dll/directx/wine/devenum/parsedisplayname.c
b/dll/directx/wine/devenum/parsedisplayname.c
index 77ea1ecdcb..0f3ef3be5a 100644
--- a/dll/directx/wine/devenum/parsedisplayname.c
+++ b/dll/directx/wine/devenum/parsedisplayname.c
@@ -76,69 +76,60 @@ static ULONG WINAPI
DEVENUM_IParseDisplayName_Release(IParseDisplayName *iface)
* not in "@device:sw:{CLSID1}\<filter name or CLSID>" format
*/
static HRESULT WINAPI DEVENUM_IParseDisplayName_ParseDisplayName(IParseDisplayName
*iface,
- IBindCtx *pbc, LPOLESTR pszDisplayName, ULONG *pchEaten, IMoniker **ppmkOut)
+ IBindCtx *pbc, LPOLESTR name, ULONG *eaten, IMoniker **ret)
{
- LPOLESTR pszBetween = NULL;
- LPOLESTR pszClass = NULL;
- MediaCatMoniker * pMoniker = NULL;
- CLSID clsidDevice;
- HRESULT res = S_OK;
- WCHAR wszRegKeyName[MAX_PATH];
- HKEY hbasekey;
- int classlen;
- static const WCHAR wszRegSeparator[] = {'\\', 0 };
-
- TRACE("(%p, %s, %p, %p)\n", pbc, debugstr_w(pszDisplayName), pchEaten,
ppmkOut);
-
- *ppmkOut = NULL;
- if (pchEaten)
- *pchEaten = strlenW(pszDisplayName);
-
- pszDisplayName = strchrW(pszDisplayName, '{');
- pszBetween = strchrW(pszDisplayName, '}') + 2;
-
- /* size = pszBetween - pszDisplayName - 1 (for '\\' after CLSID)
- * + 1 (for NULL character)
- */
- classlen = (int)(pszBetween - pszDisplayName - 1);
- pszClass = CoTaskMemAlloc((classlen + 1) * sizeof(WCHAR));
- if (!pszClass)
- return E_OUTOFMEMORY;
+ WCHAR buffer[MAX_PATH];
+ enum device_type type;
+ MediaCatMoniker *mon;
+ CLSID class;
+
+ TRACE("(%p, %s, %p, %p)\n", pbc, debugstr_w(name), eaten, ret);
+
+ *ret = NULL;
+ if (eaten)
+ *eaten = strlenW(name);
- memcpy(pszClass, pszDisplayName, classlen * sizeof(WCHAR));
- pszClass[classlen] = 0;
+ name = strchrW(name, ':') + 1;
- TRACE("Device CLSID: %s\n", debugstr_w(pszClass));
+ if (name[0] == 's' && name[1] == 'w' && name[2] ==
':')
+ {
+ type = DEVICE_FILTER;
+ name += 3;
+ }
+ else if (name[0] == 'c' && name[1] == 'm' && name[2]
== ':')
+ {
+ type = DEVICE_CODEC;
+ name += 3;
+ }
+ else
+ {
+ FIXME("unhandled device type %s\n", debugstr_w(name));
+ return MK_E_SYNTAX;
+ }
- res = CLSIDFromString(pszClass, &clsidDevice);
+ if (!(mon = DEVENUM_IMediaCatMoniker_Construct()))
+ return E_OUTOFMEMORY;
- if (SUCCEEDED(res))
+ lstrcpynW(buffer, name, CHARS_IN_GUID);
+ if (CLSIDFromString(buffer, &class) == S_OK)
{
- res = DEVENUM_GetCategoryKey(&clsidDevice, &hbasekey, wszRegKeyName,
MAX_PATH);
+ mon->has_class = TRUE;
+ mon->class = class;
+ name += CHARS_IN_GUID;
}
- if (SUCCEEDED(res))
+ mon->type = type;
+
+ if (!(mon->name = CoTaskMemAlloc((strlenW(name) + 1) * sizeof(WCHAR))))
{
- pMoniker = DEVENUM_IMediaCatMoniker_Construct();
- if (pMoniker)
- {
- strcatW(wszRegKeyName, wszRegSeparator);
- strcatW(wszRegKeyName, pszBetween);
-
- if (RegCreateKeyW(hbasekey, wszRegKeyName, &pMoniker->hkey) ==
ERROR_SUCCESS)
- *ppmkOut = &pMoniker->IMoniker_iface;
- else
- {
- IMoniker_Release(&pMoniker->IMoniker_iface);
- res = MK_E_NOOBJECT;
- }
- }
+ IMoniker_Release(&mon->IMoniker_iface);
+ return E_OUTOFMEMORY;
}
+ strcpyW(mon->name, name);
- CoTaskMemFree(pszClass);
+ *ret = &mon->IMoniker_iface;
- TRACE("-- returning: %x\n", res);
- return res;
+ return S_OK;
}
/**********************************************************************
diff --git a/media/doc/README.WINE b/media/doc/README.WINE
index 477bb4d3e3..a5b6b1865a 100644
--- a/media/doc/README.WINE
+++ b/media/doc/README.WINE
@@ -29,7 +29,7 @@ reactos/dll/directx/wine/d3drm # Synced to WineStaging-3.9
reactos/dll/directx/wine/d3dx9_24 => 43 # Synced to WineStaging-3.9
reactos/dll/directx/wine/d3dxof # Synced to WineStaging-3.3
reactos/dll/directx/wine/ddraw # Synced to WineStaging-3.9
-reactos/dll/directx/wine/devenum # Synced to WineStaging-3.3
+reactos/dll/directx/wine/devenum # Synced to WineStaging-3.9
reactos/dll/directx/wine/dinput # Synced to WineStaging-3.3
reactos/dll/directx/wine/dinput8 # Synced to WineStaging-3.3
reactos/dll/directx/wine/dmusic # Synced to WineStaging-3.3