[PATCH 2/2] devenum: Register DirectSound devices as codec devices.

Zebediah Figura z.figura12 at gmail.com
Sat Mar 10 22:11:52 CST 2018


Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
 dlls/devenum/Makefile.in       |   2 +-
 dlls/devenum/createdevenum.c   | 129 ++++++++++++++++++++++++++++-------------
 dlls/devenum/devenum.rc        |   2 -
 dlls/devenum/devenum_private.h |   2 -
 dlls/devenum/tests/Makefile.in |   2 +-
 dlls/devenum/tests/devenum.c   |  94 ++++++++++++++++++++++++++++++
 6 files changed, 186 insertions(+), 45 deletions(-)

diff --git a/dlls/devenum/Makefile.in b/dlls/devenum/Makefile.in
index 0a7e903..8f81f93 100644
--- a/dlls/devenum/Makefile.in
+++ b/dlls/devenum/Makefile.in
@@ -1,5 +1,5 @@
 MODULE    = devenum.dll
-IMPORTS   = strmiids uuid ole32 oleaut32 avicap32 winmm user32 advapi32
+IMPORTS   = strmiids uuid ole32 oleaut32 avicap32 winmm user32 advapi32 dsound
 DELAYIMPORTS = msvfw32
 
 C_SRCS = \
diff --git a/dlls/devenum/createdevenum.c b/dlls/devenum/createdevenum.c
index a6f6626..5fc4725 100644
--- a/dlls/devenum/createdevenum.c
+++ b/dlls/devenum/createdevenum.c
@@ -29,6 +29,7 @@
 #include "devenum_private.h"
 #include "vfw.h"
 #include "aviriff.h"
+#include "dsound.h"
 
 #include "wine/debug.h"
 #include "wine/unicode.h"
@@ -510,6 +511,91 @@ cleanup:
     if (hkeyFilter) RegCloseKey(hkeyFilter);
 }
 
+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;
+
+    hr = DEVENUM_CreateAMCategoryKey(&CLSID_AudioRendererCategory);
+    if (FAILED(hr)) goto cleanup;
+
+    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);
+
+    return TRUE;
+}
+
 /**********************************************************************
  * DEVENUM_ICreateDevEnum_CreateClassEnumerator
  */
@@ -519,6 +605,8 @@ static HRESULT WINAPI DEVENUM_ICreateDevEnum_CreateClassEnumerator(
     IEnumMoniker **ppEnumMoniker,
     DWORD dwFlags)
 {
+    HRESULT hr;
+
     TRACE("(%p)->(%s, %p, %x)\n", iface, debugstr_guid(clsidDeviceClass), ppEnumMoniker, dwFlags);
 
     if (!ppEnumMoniker)
@@ -528,6 +616,8 @@ static HRESULT WINAPI DEVENUM_ICreateDevEnum_CreateClassEnumerator(
 
     register_codecs();
     register_legacy_filters();
+    hr = DirectSoundEnumerateW(&register_dsound_devices, NULL);
+    if (FAILED(hr)) return hr;
 
     return create_EnumMoniker(clsidDeviceClass, ppEnumMoniker);
 }
@@ -621,8 +711,6 @@ static void register_vfw_codecs(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;
@@ -658,12 +746,6 @@ static HRESULT register_codecs(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);
     /*
@@ -714,37 +796,6 @@ static HRESULT register_codecs(void)
 					      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)
diff --git a/dlls/devenum/devenum.rc b/dlls/devenum/devenum.rc
index d43c159..d9262e1 100644
--- a/dlls/devenum/devenum.rc
+++ b/dlls/devenum/devenum.rc
@@ -29,8 +29,6 @@ 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"
 }
diff --git a/dlls/devenum/devenum_private.h b/dlls/devenum/devenum_private.h
index a483062..93147ad 100644
--- a/dlls/devenum/devenum_private.h
+++ b/dlls/devenum/devenum_private.h
@@ -101,8 +101,6 @@ extern const WCHAR clsid_keyname[6] DECLSPEC_HIDDEN;
 /**********************************************************************
  * 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
diff --git a/dlls/devenum/tests/Makefile.in b/dlls/devenum/tests/Makefile.in
index f6ef993..028ba27 100644
--- a/dlls/devenum/tests/Makefile.in
+++ b/dlls/devenum/tests/Makefile.in
@@ -1,5 +1,5 @@
 TESTDLL   = devenum.dll
-IMPORTS   = oleaut32 ole32 advapi32
+IMPORTS   = advapi32 dsound oleaut32 ole32
 
 C_SRCS = \
 	devenum.c
diff --git a/dlls/devenum/tests/devenum.c b/dlls/devenum/tests/devenum.c
index 43d6eeb..c4bf8af 100644
--- a/dlls/devenum/tests/devenum.c
+++ b/dlls/devenum/tests/devenum.c
@@ -28,6 +28,10 @@
 #include "strmif.h"
 #include "uuids.h"
 #include "vfwmsgs.h"
+#include "mmsystem.h"
+#include "dsound.h"
+
+DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
 
 static const WCHAR friendly_name[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0};
 static const WCHAR fcc_handlerW[] = {'F','c','c','H','a','n','d','l','e','r',0};
@@ -526,6 +530,94 @@ end:
     IParseDisplayName_Release(parser);
 }
 
+static BOOL CALLBACK test_dsound(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};
+    IParseDisplayName *parser;
+    IPropertyBag *prop_bag;
+    IMoniker *mon;
+    WCHAR buffer[200];
+    WCHAR name[200];
+    VARIANT var;
+    HRESULT hr;
+
+    if (guid)
+    {
+        lstrcpyW(name, directsoundW);
+        lstrcatW(name, desc);
+    }
+    else
+    {
+        lstrcpyW(name, defaultW);
+        guid = (GUID *)&GUID_NULL;
+    }
+
+    hr = CoCreateInstance(&CLSID_CDeviceMoniker, NULL, CLSCTX_INPROC, &IID_IParseDisplayName, (void **)&parser);
+    ok(hr == S_OK, "Failed to create ParseDisplayName: %#x\n", hr);
+
+    lstrcpyW(buffer, deviceW);
+    lstrcatW(buffer, cmW);
+    StringFromGUID2(&CLSID_AudioRendererCategory, buffer + lstrlenW(buffer), CHARS_IN_GUID);
+    lstrcatW(buffer, backslashW);
+    lstrcatW(buffer, name);
+
+    mon = check_display_name(parser, buffer);
+
+    hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag);
+    ok(hr == S_OK, "BindToStorage failed: %#x\n", hr);
+
+    VariantInit(&var);
+    hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL);
+    if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
+    {
+        /* Win8+ uses the GUID instead of the device name */
+        IPropertyBag_Release(prop_bag);
+        IMoniker_Release(mon);
+
+        lstrcpyW(buffer, deviceW);
+        lstrcatW(buffer, cmW);
+        StringFromGUID2(&CLSID_AudioRendererCategory, buffer + lstrlenW(buffer), CHARS_IN_GUID);
+        lstrcatW(buffer, backslashW);
+        lstrcatW(buffer, directsoundW);
+        StringFromGUID2(guid, buffer + lstrlenW(buffer) - 1, CHARS_IN_GUID);
+
+        mon = check_display_name(parser, buffer);
+
+        hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag);
+        ok(hr == S_OK, "BindToStorage failed: %#x\n", hr);
+
+        VariantInit(&var);
+        hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL);
+    }
+    ok(hr == S_OK, "Read failed: %#x\n", hr);
+
+    ok(!lstrcmpW(name, V_BSTR(&var)), "expected %s, got %s\n",
+        wine_dbgstr_w(name), wine_dbgstr_w(V_BSTR(&var)));
+
+    VariantClear(&var);
+    hr = IPropertyBag_Read(prop_bag, clsidW, &var, NULL);
+    ok(hr == S_OK, "Read failed: %#x\n", hr);
+
+    StringFromGUID2(&CLSID_DSoundRender, buffer, CHARS_IN_GUID);
+    ok(!lstrcmpW(buffer, V_BSTR(&var)), "expected %s, got %s\n",
+        wine_dbgstr_w(buffer), wine_dbgstr_w(V_BSTR(&var)));
+
+    VariantClear(&var);
+    hr = IPropertyBag_Read(prop_bag, dsguidW, &var, NULL);
+    ok(hr == S_OK, "Read failed: %#x\n", hr);
+
+    StringFromGUID2(guid, buffer, CHARS_IN_GUID);
+    ok(!lstrcmpW(buffer, V_BSTR(&var)), "expected %s, got %s\n",
+        wine_dbgstr_w(buffer), wine_dbgstr_w(V_BSTR(&var)));
+
+    IPropertyBag_Release(prop_bag);
+    IMoniker_Release(mon);
+    IParseDisplayName_Release(parser);
+    return TRUE;
+}
+
 START_TEST(devenum)
 {
     IBindCtx *bind_ctx = NULL;
@@ -549,6 +641,8 @@ START_TEST(devenum)
     test_codec();
 
     test_legacy_filter();
+    hr = DirectSoundEnumerateW(test_dsound, NULL);
+    ok(hr == S_OK, "got %#x\n", hr);
 
     CoUninitialize();
 }
-- 
2.7.4




More information about the wine-devel mailing list