[PATCH] dsound: Use mmdevice apis for enumeration

Maarten Lankhorst m.b.lankhorst at gmail.com
Wed Aug 24 06:43:16 CDT 2011


Will probably conflict with puk's com cleanup

QUERYDSOUNDDESC is no longer used after this, and a followup patch will remove
it from winmm

---
 dlls/dsound/Makefile.in          |    2 +-
 dlls/dsound/capture.c            |   61 ++++---
 dlls/dsound/dsound.c             |   49 +++---
 dlls/dsound/dsound_main.c        |  359 ++++++++++++++++++++++++++------------
 dlls/dsound/dsound_private.h     |   13 +-
 dlls/dsound/propset.c            |  274 ++++++++++++++++-------------
 dlls/mmdevapi/tests/dependency.c |    2 +-
 7 files changed, 471 insertions(+), 289 deletions(-)

diff --git a/dlls/dsound/Makefile.in b/dlls/dsound/Makefile.in
index 58b1998..8258637 100644
--- a/dlls/dsound/Makefile.in
+++ b/dlls/dsound/Makefile.in
@@ -1,6 +1,6 @@
 MODULE    = dsound.dll
 IMPORTLIB = dsound
-IMPORTS   = dxguid uuid winmm ole32 advapi32
+IMPORTS   = dxguid uuid winmm ole32 advapi32 user32
 
 C_SRCS = \
 	buffer.c \
diff --git a/dlls/dsound/capture.c b/dlls/dsound/capture.c
index 174355a..287cbcb 100644
--- a/dlls/dsound/capture.c
+++ b/dlls/dsound/capture.c
@@ -27,6 +27,7 @@
 
 #include <stdarg.h>
 
+#define COBJMACROS
 #define NONAMELESSSTRUCT
 #define NONAMELESSUNION
 #include "windef.h"
@@ -1038,40 +1039,52 @@ static HRESULT DirectSoundCaptureDevice_Initialize(
     LPCGUID lpcGUID)
 {
     HRESULT err = DSERR_INVALIDPARAM;
-    unsigned wid, widn;
-    BOOLEAN found = FALSE;
-    GUID devGUID;
+    unsigned wid = 0, widn;
+    DWORD_PTR devid_size, devid2_size;
+    IMMDevice *dev;
+    WCHAR *devid, *devid2;
     DirectSoundCaptureDevice *device = *ppDevice;
+    GUID devGUID;
     TRACE("(%p, %s)\n", ppDevice, debugstr_guid(lpcGUID));
 
     /* Default device? */
     if ( !lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL) )
 	lpcGUID = &DSDEVID_DefaultCapture;
 
-    if (GetDeviceID(lpcGUID, &devGUID) != DS_OK) {
-        WARN("invalid parameter: lpcGUID\n");
-        return DSERR_INVALIDPARAM;
+    if (DSOUND_obtain_immdevice(eCapture, lpcGUID, eCommunications, &dev) != DS_OK) {
+        WARN("invalid parameter: lpcGUID %s\n", debugstr_guid(lpcGUID));
+        return DSERR_NODRIVER;
     }
-
-    widn = waveInGetNumDevs();
-    if (!widn) {
-	WARN("no audio devices found\n");
-	return DSERR_NODRIVER;
+    DSOUND_immdevice_getguid(dev, &devGUID);
+    if (IMMDevice_GetId(dev, &devid) != DS_OK) {
+       WARN("No device id\n");
+       return DSERR_NODRIVER;
     }
-
-    /* enumerate WINMM audio devices and find the one we want */
-    for (wid=0; wid<widn; wid++) {
-	if (IsEqualGUID( &devGUID, &DSOUND_capture_guids[wid]) ) {
-	    found = TRUE;
-	    break;
-	}
+    IMMDevice_Release(dev);
+    devid_size = (lstrlenW(devid)+1)*sizeof(WCHAR);
+    devid2 = CoTaskMemAlloc(devid_size);
+    if (!devid2) {
+        CoTaskMemFree(devid);
+        return E_OUTOFMEMORY;
     }
 
-    if (found == FALSE) {
-	WARN("No device found matching given ID!\n");
-	return DSERR_NODRIVER;
+    widn = waveInGetNumDevs();
+    for (wid = 0; wid < widn; ++wid) {
+        int res;
+        res = waveInMessage(UlongToHandle(wid), DRV_QUERYFUNCTIONINSTANCEIDSIZE, (DWORD_PTR)&devid2_size, 0);
+        if (res != MMSYSERR_NOERROR || devid2_size != devid_size) continue;
+        waveInMessage(UlongToHandle(wid), DRV_QUERYFUNCTIONINSTANCEID, (DWORD_PTR)devid2, devid2_size);
+        if (!memcmp(devid2, devid, devid_size))
+            break;
+    }
+    CoTaskMemFree(devid2);
+    CoTaskMemFree(devid);
+    if (wid == widn) {
+        WARN("no audio devices found\n");
+        return DSERR_NODRIVER;
     }
 
+    /* enumerate WINMM audio devices and find the one we want */
     if (DSOUND_capture[wid]) {
         WARN("already in use\n");
         return DSERR_ALLOCATED;
@@ -1358,9 +1371,6 @@ HRESULT DSOUND_CaptureCreate(
         return E_NOINTERFACE;
     }
 
-    /* Get dsound configuration */
-    setup_dsound_options();
-
     hr = IDirectSoundCaptureImpl_Create(&pDSC);
     if (hr == DS_OK) {
         IDirectSoundCapture_AddRef(pDSC);
@@ -1387,9 +1397,6 @@ HRESULT DSOUND_CaptureCreate8(
         return E_NOINTERFACE;
     }
 
-    /* Get dsound configuration */
-    setup_dsound_options();
-
     hr = IDirectSoundCaptureImpl_Create(&pDSC8);
     if (hr == DS_OK) {
         IDirectSoundCapture_AddRef(pDSC8);
diff --git a/dlls/dsound/dsound.c b/dlls/dsound/dsound.c
index 8c1b812..7aac7dc 100644
--- a/dlls/dsound/dsound.c
+++ b/dlls/dsound/dsound.c
@@ -25,6 +25,7 @@
 
 #define NONAMELESSSTRUCT
 #define NONAMELESSUNION
+#define COBJMACROS
 #include "windef.h"
 #include "winbase.h"
 #include "winuser.h"
@@ -1347,9 +1348,11 @@ HRESULT DirectSoundDevice_Initialize(DirectSoundDevice ** ppDevice, LPCGUID lpcG
 {
     HRESULT hr = DS_OK;
     unsigned wod, wodn;
-    BOOLEAN found = FALSE;
     GUID devGUID;
     DirectSoundDevice * device = *ppDevice;
+    DWORD_PTR devid_size, devid2_size;
+    IMMDevice *dev;
+    WCHAR *devid, *devid2;
     TRACE("(%p,%s)\n",ppDevice,debugstr_guid(lpcGUID));
 
     if (*ppDevice != NULL) {
@@ -1357,33 +1360,37 @@ HRESULT DirectSoundDevice_Initialize(DirectSoundDevice ** ppDevice, LPCGUID lpcG
         return DSERR_ALREADYINITIALIZED;
     }
 
-    /* Default device? */
-    if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL))
+    if ( !lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL) )
         lpcGUID = &DSDEVID_DefaultPlayback;
 
-    if (GetDeviceID(lpcGUID, &devGUID) != DS_OK) {
-        WARN("invalid parameter: lpcGUID\n");
-        return DSERR_INVALIDPARAM;
-    }
-
-    /* Enumerate WINMM audio devices and find the one we want */
-    wodn = waveOutGetNumDevs();
-    if (!wodn) {
-        WARN("no driver\n");
+    if (DSOUND_obtain_immdevice(eRender, lpcGUID, eMultimedia, &dev) != DS_OK) {
+        WARN("invalid parameter: lpcGUID %s\n", debugstr_guid(lpcGUID));
         return DSERR_NODRIVER;
     }
-
-    for (wod=0; wod<wodn; wod++) {
-        if (IsEqualGUID( &devGUID, &DSOUND_renderer_guids[wod])) {
-            found = TRUE;
-            break;
-        }
+    DSOUND_immdevice_getguid(dev, &devGUID);
+    if (IMMDevice_GetId(dev, &devid) != DS_OK) {
+       WARN("No device id\n");
+       return DSERR_NODRIVER;
+    }
+    IMMDevice_Release(dev);
+    devid_size = (lstrlenW(devid)+1)*sizeof(WCHAR);
+    devid2 = CoTaskMemAlloc(devid_size);
+    if (!devid2) {
+        CoTaskMemFree(devid);
+        return E_OUTOFMEMORY;
     }
 
-    if (found == FALSE) {
-        WARN("No device found matching given ID!\n");
-        return DSERR_NODRIVER;
+    wodn = waveOutGetNumDevs();
+    for (wod = 0; wod < wodn; ++wod) {
+        int res;
+        res = waveOutMessage(UlongToHandle(wod), DRV_QUERYFUNCTIONINSTANCEIDSIZE, (DWORD_PTR)&devid2_size, 0);
+        if (res != MMSYSERR_NOERROR || devid2_size != devid_size) continue;
+        waveOutMessage(UlongToHandle(wod), DRV_QUERYFUNCTIONINSTANCEID, (DWORD_PTR)devid2, devid2_size);
+        if (!memcmp(devid2, devid, devid_size))
+            break;
     }
+    CoTaskMemFree(devid2);
+    CoTaskMemFree(devid);
 
     if (DSOUND_renderer[wod]) {
         if (IsEqualGUID(&devGUID, &DSOUND_renderer[wod]->guid)) {
diff --git a/dlls/dsound/dsound_main.c b/dlls/dsound/dsound_main.c
index 81dd7dd..52619ca 100644
--- a/dlls/dsound/dsound_main.c
+++ b/dlls/dsound/dsound_main.c
@@ -50,17 +50,147 @@
 #include "dsconf.h"
 #include "ks.h"
 #include "rpcproxy.h"
+#include "rpc.h"
+#include "rpcndr.h"
+#include "unknwn.h"
+#include "oleidl.h"
+#include "shobjidl.h"
+
 #include "initguid.h"
 #include "ksmedia.h"
 #include "dsdriver.h"
+#include "propkey.h"
+#include "devpkey.h"
 
 #include "dsound_private.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
 
+static IMMDeviceEnumerator *mme = NULL;
+
+static CALLBACK DWORD DSOUND_mmdevapi_thread(void *data)
+{
+    MSG msg;
+    HRESULT hr;
+    IMMDeviceEnumerator *mymme = NULL;
+    CoInitializeEx(NULL, COINIT_MULTITHREADED);
+    PeekMessageW(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
+    hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, (void**)&mymme);
+    if (SUCCEEDED(hr))
+        mme = mymme;
+    SetEvent((HANDLE)data);
+    if (FAILED(hr))
+    {
+        ERR("Cannot use mmdevapi: %08x\n", hr);
+        goto out;
+    }
+    while (GetMessageW(&msg, NULL, 0, 0))
+    {
+        if (msg.hwnd)
+        {
+            DispatchMessageW(&msg);
+            continue;
+        }
+        ERR("Unknown message: %04x\n", msg.message);
+    }
+out:
+    if (mme)
+        IMMDeviceEnumerator_Release(mme);
+    mme = NULL;
+    CoUninitialize();
+    return 0;
+}
+
+static HANDLE DSOUND_mmdevapi_thread_handle;
+static DWORD DSOUND_mmdevapi_id;
+
+CRITICAL_SECTION mme_crst;
+static CRITICAL_SECTION_DEBUG mme_crst_debug =
+{
+    0, 0, &mme_crst,
+    { &mme_crst_debug.ProcessLocksList,
+      &mme_crst_debug.ProcessLocksList },
+      0, 0, { (DWORD_PTR)(__FILE__ ": mme_crst_debug") }
+};
+CRITICAL_SECTION mme_crst = { &mme_crst_debug, -1, 0, 0, 0, 0 };
+
+IMMDeviceEnumerator *DSOUND_obtain_mme(void)
+{
+    EnterCriticalSection(&mme_crst);
+    if (!DSOUND_mmdevapi_id)
+    {
+        HANDLE ev = CreateEventW(0, 0, 0, 0);
+        DSOUND_mmdevapi_thread_handle = CreateThread(0, 0, DSOUND_mmdevapi_thread, ev, 0, &DSOUND_mmdevapi_id);
+        WaitForSingleObject(ev, INFINITE);
+        CloseHandle(ev);
+    }
+    LeaveCriticalSection(&mme_crst);
+    return mme;
+}
+
+HRESULT DSOUND_obtain_immdevice(EDataFlow flow, const GUID *guid, ERole role, IMMDevice **dev)
+{
+    IMMDeviceCollection *col;
+    HRESULT hr;
+    GUID curguid;
+    int i = 0;
+    if (!DSOUND_obtain_mme())
+        return DSERR_NODRIVER;
+    if (flow == eCapture && (IsEqualGUID(guid, &DSDEVID_DefaultVoiceCapture) ||
+                             IsEqualGUID(guid, &DSDEVID_DefaultCapture)))
+        return IMMDeviceEnumerator_GetDefaultAudioEndpoint(mme, flow, role, dev);
+    if (flow == eRender && (IsEqualGUID(guid, &DSDEVID_DefaultVoicePlayback) ||
+                             IsEqualGUID(guid, &DSDEVID_DefaultPlayback)))
+        return IMMDeviceEnumerator_GetDefaultAudioEndpoint(mme, flow, role, dev);
+    hr = IMMDeviceEnumerator_EnumAudioEndpoints(mme, flow, DEVICE_STATE_ACTIVE, &col);
+    if (FAILED(hr))
+        return E_NOTFOUND;
+    while (SUCCEEDED(IMMDeviceCollection_Item(col, i++, dev)))
+    {
+        hr = DSOUND_immdevice_getguid(*dev, &curguid);
+        if (SUCCEEDED(hr) && IsEqualGUID(&curguid, guid))
+        {
+            IMMDeviceCollection_Release(col);
+            return S_OK;
+        }
+        IMMDevice_Release(*dev);
+    }
+    IMMDeviceCollection_Release(col);
+    *dev = NULL;
+    return E_NOTFOUND;
+}
+
+HRESULT DSOUND_enumerate_immdevice(EDataFlow flow, IMMDeviceCollection **collection)
+{
+    if (!DSOUND_obtain_mme())
+        return DSERR_NODRIVER;
+    return IMMDeviceEnumerator_EnumAudioEndpoints(mme, flow, DEVICE_STATE_ACTIVE, collection);
+}
+
+HRESULT DSOUND_immdevice_getguid(IMMDevice *dev, GUID *guid)
+{
+    IPropertyStore *store;
+    PROPVARIANT pv = { VT_EMPTY };
+    HRESULT hr;
+    hr = IMMDevice_OpenPropertyStore(dev, STGM_READ, &store);
+    if (FAILED(hr))
+        return hr;
+    hr = IPropertyStore_GetValue(store, &PKEY_AudioEndpoint_GUID, &pv);
+    if (FAILED(hr))
+    {
+        IPropertyStore_Release(store);
+        return hr;
+    }
+    CLSIDFromString(pv.u.pwszVal, guid);
+    PropVariantClear(&pv);
+    IPropertyStore_Release(store);
+    return S_OK;
+}
+
 DirectSoundDevice*	DSOUND_renderer[MAXWAVEDRIVERS];
-GUID                    DSOUND_renderer_guids[MAXWAVEDRIVERS];
-GUID                    DSOUND_capture_guids[MAXWAVEDRIVERS];
+/* Some games keep a pointer to the guid instead of copying the guid itself, so keep a copy here */
+static GUID DSOUND_renderer_guids[MAXWAVEDRIVERS];
+static GUID DSOUND_capture_guids[MAXWAVEDRIVERS];
 
 HRESULT mmErr(UINT err)
 {
@@ -98,8 +228,6 @@ int ds_snd_shadow_maxsize = 2;
 int ds_hw_accel = DS_HW_ACCEL_FULL;
 int ds_default_sample_rate = 44100;
 int ds_default_bits_per_sample = 16;
-static int ds_default_playback;
-static int ds_default_capture;
 static HINSTANCE instance;
 
 /*
@@ -172,15 +300,9 @@ void setup_dsound_options(void)
 	    ds_hw_accel = DS_HW_ACCEL_EMULATION;
     }
 
-    if (!get_config_key( hkey, appkey, "DefaultPlayback", buffer, MAX_PATH ))
-        ds_default_playback = atoi(buffer);
-
     if (!get_config_key( hkey, appkey, "MaxShadowSize", buffer, MAX_PATH ))
         ds_snd_shadow_maxsize = atoi(buffer);
 
-    if (!get_config_key( hkey, appkey, "DefaultCapture", buffer, MAX_PATH ))
-        ds_default_capture = atoi(buffer);
-
     if (!get_config_key( hkey, appkey, "DefaultSampleRate", buffer, MAX_PATH ))
         ds_default_sample_rate = atoi(buffer);
 
@@ -200,8 +322,6 @@ void setup_dsound_options(void)
         ds_hw_accel==DS_HW_ACCEL_BASIC ? "Basic" :
         ds_hw_accel==DS_HW_ACCEL_EMULATION ? "Emulation" :
         "Unknown");
-    TRACE("ds_default_playback = %d\n", ds_default_playback);
-    TRACE("ds_default_capture = %d\n", ds_default_playback);
     TRACE("ds_default_sample_rate = %d\n", ds_default_sample_rate);
     TRACE("ds_default_bits_per_sample = %d\n", ds_default_bits_per_sample);
     TRACE("ds_snd_shadow_maxsize = %d\n", ds_snd_shadow_maxsize);
@@ -242,6 +362,7 @@ static const char * get_device_id(LPCGUID pGuid)
  */
 HRESULT WINAPI GetDeviceID(LPCGUID pGuidSrc, LPGUID pGuidDest)
 {
+    HRESULT hr;
     TRACE("(%s,%p)\n", get_device_id(pGuidSrc),pGuidDest);
 
     if ( pGuidSrc == NULL) {
@@ -255,17 +376,35 @@ HRESULT WINAPI GetDeviceID(LPCGUID pGuidSrc, LPGUID pGuidDest)
     }
 
     if ( IsEqualGUID( &DSDEVID_DefaultPlayback, pGuidSrc ) ||
-	 IsEqualGUID( &DSDEVID_DefaultVoicePlayback, pGuidSrc ) ) {
-	*pGuidDest = DSOUND_renderer_guids[ds_default_playback];
-        TRACE("returns %s\n", get_device_id(pGuidDest));
-	return DS_OK;
+         IsEqualGUID( &DSDEVID_DefaultVoicePlayback, pGuidSrc ) ) {
+        ERole role = IsEqualGUID( &DSDEVID_DefaultVoicePlayback, pGuidSrc ) ? eCommunications : eMultimedia;
+        IMMDevice *dev = NULL;
+
+        hr = DSOUND_obtain_immdevice(eRender, pGuidSrc, role, &dev);
+        if (SUCCEEDED(hr))
+            hr = DSOUND_immdevice_getguid(dev, pGuidDest);
+        if (dev)
+            IMMDevice_Release(dev);
+        if (FAILED(hr))
+            return DSERR_NODRIVER;
+        TRACE("returns %s\n", debugstr_guid(pGuidDest));
+        return DS_OK;
     }
 
     if ( IsEqualGUID( &DSDEVID_DefaultCapture, pGuidSrc ) ||
-	 IsEqualGUID( &DSDEVID_DefaultVoiceCapture, pGuidSrc ) ) {
-	*pGuidDest = DSOUND_capture_guids[ds_default_capture];
-        TRACE("returns %s\n", get_device_id(pGuidDest));
-	return DS_OK;
+         IsEqualGUID( &DSDEVID_DefaultVoiceCapture, pGuidSrc ) ) {
+        ERole role = IsEqualGUID( &DSDEVID_DefaultVoiceCapture, pGuidSrc ) ? eCommunications : eMultimedia;
+        IMMDevice *dev = NULL;
+
+        hr = DSOUND_obtain_immdevice(eCapture, pGuidSrc, role, &dev);
+        if (SUCCEEDED(hr))
+            hr = DSOUND_immdevice_getguid(dev, pGuidDest);
+        if (dev)
+            IMMDevice_Release(dev);
+        if (FAILED(hr))
+            return DSERR_NODRIVER;
+        TRACE("returns %s\n", debugstr_guid(pGuidDest));
+        return DS_OK;
     }
 
     *pGuidDest = *pGuidSrc;
@@ -338,60 +477,54 @@ HRESULT WINAPI DirectSoundEnumerateW(
 	LPDSENUMCALLBACKW lpDSEnumCallback,
 	LPVOID lpContext )
 {
-    unsigned devs, wod;
-    DSDRIVERDESC desc;
-    GUID guid;
-    int err;
-    WCHAR wDesc[MAXPNAMELEN];
-    WCHAR wName[MAXPNAMELEN];
+    HRESULT hr;
+    UINT devices = 0, i = 0;
+
+    WCHAR wDesc[MAXPNAMELEN] = { 'P','r','i','m','a','r','y',' ',
+        'S','o','u','n','d',' ','D','r','i','v','e','r',0 };
+    static const WCHAR wCapDrvName[] = { 'w','i','n','e','m','m','.','v','x','d', 0 };
+    static const WCHAR wEmptyDrv[] = { 0 };
+    IMMDevice *dev;
+    IPropertyStore *store;
+    IMMDeviceCollection *col;
+    PROPVARIANT pv = { VT_EMPTY };
 
-    TRACE("lpDSEnumCallback = %p, lpContext = %p\n",
-	lpDSEnumCallback, lpContext);
+    TRACE("(%p,%p)\n", lpDSEnumCallback, lpContext );
 
     if (lpDSEnumCallback == NULL) {
-	WARN("invalid parameter: lpDSEnumCallback == NULL\n");
-	return DSERR_INVALIDPARAM;
+        WARN("invalid parameter: lpDSEnumCallback == NULL\n");
+        return DSERR_INVALIDPARAM;
     }
 
-    setup_dsound_options();
-
-    devs = waveOutGetNumDevs();
-    if (devs > 0) {
-	if (GetDeviceID(&DSDEVID_DefaultPlayback, &guid) == DS_OK) {
-            static const WCHAR empty[] = { 0 };
-	    for (wod = 0; wod < devs; ++wod) {
-                if (IsEqualGUID( &guid, &DSOUND_renderer_guids[wod] ) ) {
-                    err = mmErr(waveOutMessage(UlongToHandle(wod),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,ds_hw_accel));
-                    if (err == DS_OK) {
-                        TRACE("calling lpDSEnumCallback(NULL,\"%s\",\"%s\",%p)\n",
-                              "Primary Sound Driver",desc.szDrvname,lpContext);
-                        MultiByteToWideChar( CP_ACP, 0, "Primary Sound Driver", -1,
-                                             wDesc, sizeof(wDesc)/sizeof(WCHAR) );
-                        if (lpDSEnumCallback(NULL, wDesc, empty, lpContext) == FALSE)
-                            return DS_OK;
-		    }
-		}
-	    }
-	}
-    }
+    hr = DSOUND_enumerate_immdevice(eRender, &col);
+    if (FAILED(hr))
+        return hr == DSERR_NODRIVER ? S_OK : hr;
 
-    for (wod = 0; wod < devs; ++wod) {
-        err = mmErr(waveOutMessage(UlongToHandle(wod),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,ds_hw_accel));
-	if (err == DS_OK) {
-            TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
-                  debugstr_guid(&DSOUND_renderer_guids[wod]),desc.szDesc,desc.szDrvname,lpContext);
-            MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1,
-                                 wDesc, sizeof(wDesc)/sizeof(WCHAR) );
-            wDesc[(sizeof(wDesc)/sizeof(WCHAR)) - 1] = '\0';
-
-            MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1,
-                                 wName, sizeof(wName)/sizeof(WCHAR) );
-            wName[(sizeof(wName)/sizeof(WCHAR)) - 1] = '\0';
-
-            if (lpDSEnumCallback(&DSOUND_renderer_guids[wod], wDesc, wName, lpContext) == FALSE)
-                return DS_OK;
-	}
+    if (FAILED(IMMDeviceCollection_GetCount(col, &devices)) || !devices)
+        goto done;
+
+    if (lpDSEnumCallback(NULL, wDesc, wEmptyDrv, lpContext) == FALSE)
+        goto done;
+
+    for (i = 0; i < devices; ++i)
+    {
+        IMMDeviceCollection_Item(col, i, &dev);
+        IMMDevice_OpenPropertyStore(dev, STGM_READ, &store);
+        IPropertyStore_GetValue(store, &PKEY_AudioEndpoint_GUID, &pv);
+        CLSIDFromString(pv.u.pwszVal, &DSOUND_renderer_guids[i]);
+        PropVariantClear(&pv);
+        IPropertyStore_GetValue(store, (const PROPERTYKEY*) &DEVPKEY_Device_FriendlyName, &pv);
+        lstrcpynW(wDesc, pv.u.pwszVal, sizeof(wDesc)/sizeof(*wDesc));
+        PropVariantClear(&pv);
+        IPropertyStore_Release(store);
+        IMMDevice_Release(dev);
+
+        if (lpDSEnumCallback(&DSOUND_renderer_guids[i], wDesc, wCapDrvName, lpContext) == FALSE)
+            break;
     }
+
+done:
+    IMMDeviceCollection_Release(col);
     return DS_OK;
 }
 
@@ -443,63 +576,54 @@ DirectSoundCaptureEnumerateW(
     LPDSENUMCALLBACKW lpDSEnumCallback,
     LPVOID lpContext)
 {
-    unsigned devs, wid;
-    DSDRIVERDESC desc;
-    GUID guid;
-    int err;
-    WCHAR wDesc[MAXPNAMELEN];
-    WCHAR wName[MAXPNAMELEN];
+    HRESULT hr;
+    UINT devices = 0, i = 0;
+
+    WCHAR wDesc[MAXPNAMELEN] = { 'P','r','i','m','a','r','y',' ',
+        'S','o','u','n','d',' ','C','a','p','t','u','r','e',' ','D','r','i','v','e','r',0 };
+    static const WCHAR wCapDrvName[] = { 'w','i','n','e','m','m','.','v','x','d', 0 };
+    static const WCHAR wEmptyDrv[] = { 0 };
+    IMMDevice *dev;
+    IPropertyStore *store;
+    IMMDeviceCollection *col;
+    PROPVARIANT pv = { VT_EMPTY };
 
     TRACE("(%p,%p)\n", lpDSEnumCallback, lpContext );
 
     if (lpDSEnumCallback == NULL) {
-	WARN("invalid parameter: lpDSEnumCallback == NULL\n");
+        WARN("invalid parameter: lpDSEnumCallback == NULL\n");
         return DSERR_INVALIDPARAM;
     }
 
-    setup_dsound_options();
-
-    devs = waveInGetNumDevs();
-    if (devs > 0) {
-	if (GetDeviceID(&DSDEVID_DefaultCapture, &guid) == DS_OK) {
-	    for (wid = 0; wid < devs; ++wid) {
-                if (IsEqualGUID( &guid, &DSOUND_capture_guids[wid] ) ) {
-                    err = mmErr(waveInMessage(UlongToHandle(wid),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,ds_hw_accel));
-                    if (err == DS_OK) {
-                        TRACE("calling lpDSEnumCallback(NULL,\"%s\",\"%s\",%p)\n",
-                              "Primary Sound Capture Driver",desc.szDrvname,lpContext);
-                        MultiByteToWideChar( CP_ACP, 0, "Primary Sound Capture Driver", -1,
-                                             wDesc, sizeof(wDesc)/sizeof(WCHAR) );
-                        MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1,
-                                             wName, sizeof(wName)/sizeof(WCHAR) );
-                        wName[(sizeof(wName)/sizeof(WCHAR)) - 1] = '\0';
-
-                        if (lpDSEnumCallback(NULL, wDesc, wName, lpContext) == FALSE)
-                            return DS_OK;
-                    }
-                }
-	    }
-	}
-    }
+    hr = DSOUND_enumerate_immdevice(eCapture, &col);
+    if (FAILED(hr))
+        return hr == DSERR_NODRIVER ? S_OK : hr;
 
-    for (wid = 0; wid < devs; ++wid) {
-        err = mmErr(waveInMessage(UlongToHandle(wid),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,ds_hw_accel));
-	if (err == DS_OK) {
-            TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
-                  debugstr_guid(&DSOUND_capture_guids[wid]),desc.szDesc,desc.szDrvname,lpContext);
-            MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1,
-                                 wDesc, sizeof(wDesc)/sizeof(WCHAR) );
-            wDesc[(sizeof(wDesc)/sizeof(WCHAR)) - 1] = '\0';
-
-            MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1,
-                                 wName, sizeof(wName)/sizeof(WCHAR) );
-            wName[(sizeof(wName)/sizeof(WCHAR)) - 1] = '\0';
-
-            if (lpDSEnumCallback(&DSOUND_capture_guids[wid], wDesc, wName, lpContext) == FALSE)
-                return DS_OK;
-	}
+    if (FAILED(IMMDeviceCollection_GetCount(col, &devices)) || !devices)
+        goto done;
+
+    if (lpDSEnumCallback(NULL, wDesc, wEmptyDrv, lpContext) == FALSE)
+        goto done;
+
+    for (i = 0; i < devices; ++i)
+    {
+        IMMDeviceCollection_Item(col, i, &dev);
+        IMMDevice_OpenPropertyStore(dev, STGM_READ, &store);
+        IPropertyStore_GetValue(store, &PKEY_AudioEndpoint_GUID, &pv);
+        CLSIDFromString(pv.u.pwszVal, &DSOUND_capture_guids[i]);
+        PropVariantClear(&pv);
+        IPropertyStore_GetValue(store, (const PROPERTYKEY*) &DEVPKEY_Device_FriendlyName, &pv);
+        lstrcpynW(wDesc, pv.u.pwszVal, sizeof(wDesc)/sizeof(*wDesc));
+        PropVariantClear(&pv);
+        IPropertyStore_Release(store);
+        IMMDevice_Release(dev);
+
+        if (lpDSEnumCallback(&DSOUND_capture_guids[i], wDesc, wCapDrvName, lpContext) == FALSE)
+            break;
     }
 
+done:
+    IMMDeviceCollection_Release(col);
     return DS_OK;
 }
 
@@ -676,9 +800,7 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpvReserved)
         TRACE("DLL_PROCESS_ATTACH\n");
         for (i = 0; i < MAXWAVEDRIVERS; i++) {
             DSOUND_renderer[i] = NULL;
-            DSOUND_capture[i] = NULL;
             INIT_GUID(DSOUND_renderer_guids[i], 0xbd6dd71a, 0x3deb, 0x11d1, 0xb1, 0x71, 0x00, 0xc0, 0x4f, 0xc2, 0x00, 0x00 + i);
-            INIT_GUID(DSOUND_capture_guids[i],  0xbd6dd71b, 0x3deb, 0x11d1, 0xb1, 0x71, 0x00, 0xc0, 0x4f, 0xc2, 0x00, 0x00 + i);
         }
         instance = hInstDLL;
         DisableThreadLibraryCalls(hInstDLL);
@@ -687,6 +809,11 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpvReserved)
         break;
     case DLL_PROCESS_DETACH:
         TRACE("DLL_PROCESS_DETACH\n");
+        if (mme)
+        {
+            IMMDeviceEnumerator_Release(mme);
+            CloseHandle(DSOUND_mmdevapi_thread_handle);
+        }
         break;
     default:
         TRACE("UNKNOWN REASON\n");
diff --git a/dlls/dsound/dsound_private.h b/dlls/dsound/dsound_private.h
index 3e17301..9ebc172 100644
--- a/dlls/dsound/dsound_private.h
+++ b/dlls/dsound/dsound_private.h
@@ -23,6 +23,10 @@
 #define DS_TIME_RES 2  /* Resolution of multimedia timer */
 #define DS_TIME_DEL 10  /* Delay of multimedia timer callback, and duration of HEL fragment */
 
+#include "wingdi.h"
+#include "mmdeviceapi.h"
+#include "audioclient.h"
+
 #include "wine/list.h"
 
 /* direct sound hardware acceleration levels */
@@ -401,11 +405,12 @@ HRESULT DSOUND_CaptureCreate8(REFIID riid, LPDIRECTSOUNDCAPTURE8 *ppDSC8) DECLSP
 #define DSOUND_FREQSHIFT (20)
 
 extern DirectSoundDevice* DSOUND_renderer[MAXWAVEDRIVERS] DECLSPEC_HIDDEN;
-extern GUID DSOUND_renderer_guids[MAXWAVEDRIVERS] DECLSPEC_HIDDEN;
-
-extern DirectSoundCaptureDevice * DSOUND_capture[MAXWAVEDRIVERS] DECLSPEC_HIDDEN;
-extern GUID DSOUND_capture_guids[MAXWAVEDRIVERS] DECLSPEC_HIDDEN;
 
 HRESULT mmErr(UINT err) DECLSPEC_HIDDEN;
 void setup_dsound_options(void) DECLSPEC_HIDDEN;
 const char * dumpCooperativeLevel(DWORD level) DECLSPEC_HIDDEN;
+
+HRESULT DSOUND_obtain_immdevice(EDataFlow flow, const GUID *guid, ERole role, IMMDevice **dev) DECLSPEC_HIDDEN;
+HRESULT DSOUND_enumerate_immdevice(EDataFlow flow, IMMDeviceCollection **collection) DECLSPEC_HIDDEN;
+HRESULT DSOUND_immdevice_getguid(IMMDevice *dev, GUID *guid) DECLSPEC_HIDDEN;
+IMMDeviceEnumerator *DSOUND_obtain_mme(void) DECLSPEC_HIDDEN;
diff --git a/dlls/dsound/propset.c b/dlls/dsound/propset.c
index e2d0e20..0f675539 100644
--- a/dlls/dsound/propset.c
+++ b/dlls/dsound/propset.c
@@ -117,17 +117,19 @@ static HRESULT DSPROPERTY_WaveDeviceMappingW(
     }
 
     if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER) {
-        ULONG wod;
-        unsigned int wodn;
-        TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
+        DWORD_PTR len;
+        WCHAR *data;
+        MMRESULT res;
+        ULONG wod, wodn;
+        IMMDevice *dev = NULL;
+        TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
+
         wodn = waveOutGetNumDevs();
         for (wod = 0; wod < wodn; wod++) {
             WAVEOUTCAPSW capsW;
-            MMRESULT res;
             res = waveOutGetDevCapsW(wod, &capsW, sizeof(capsW));
             if (res == MMSYSERR_NOERROR) {
                 if (lstrcmpW(capsW.szPname, ppd->DeviceName) == 0) {
-                    ppd->DeviceId = DSOUND_renderer_guids[wod];
                     hr = DS_OK;
                     TRACE("found %s for %s\n", debugstr_guid(&ppd->DeviceId),
                           debugstr_w(ppd->DeviceName));
@@ -135,18 +137,37 @@ static HRESULT DSPROPERTY_WaveDeviceMappingW(
                 }
             }
         }
+        res = waveOutMessage(UlongToHandle(wod),DRV_QUERYFUNCTIONINSTANCEIDSIZE,(DWORD_PTR)&len,0);
+        if (res == MMSYSERR_NOTSUPPORTED)
+        {
+            FIXME("No matching winmm device found, assuming winmm doesn't support mmdevapi and falling back to first device\n");
+            ppd->DeviceId = DSDEVID_DefaultPlayback;
+            goto out;
+        }
+        data = HeapAlloc(GetProcessHeap(), 0, len);
+        if (!data)
+            hr = E_OUTOFMEMORY;
+        else
+            waveOutMessage(UlongToHandle(wod),DRV_QUERYFUNCTIONINSTANCEID,(DWORD_PTR)data, len);
+        if (SUCCEEDED(hr))
+            hr = IMMDeviceEnumerator_GetDevice(DSOUND_obtain_mme(), data, &dev);
+        if (SUCCEEDED(hr))
+            hr = DSOUND_immdevice_getguid(dev, &ppd->DeviceId);
+        HeapFree(GetProcessHeap(), 0, data);
     } else if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE) {
-        ULONG wid;
-        unsigned int widn;
+        DWORD_PTR len;
+        WCHAR *data;
+        MMRESULT res;
+        ULONG wid, widn;
+        IMMDevice *dev = NULL;
         TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
+
         widn = waveInGetNumDevs();
         for (wid = 0; wid < widn; wid++) {
             WAVEINCAPSW capsW;
-            MMRESULT res;
             res = waveInGetDevCapsW(wid, &capsW, sizeof(capsW));
             if (res == MMSYSERR_NOERROR) {
                 if (lstrcmpW(capsW.szPname, ppd->DeviceName) == 0) {
-                    ppd->DeviceId = DSOUND_capture_guids[wid];
                     hr = DS_OK;
                     TRACE("found %s for %s\n", debugstr_guid(&ppd->DeviceId),
                           debugstr_w(ppd->DeviceName));
@@ -154,8 +175,26 @@ static HRESULT DSPROPERTY_WaveDeviceMappingW(
                 }
             }
         }
+        res = waveInMessage(UlongToHandle(wid),DRV_QUERYFUNCTIONINSTANCEIDSIZE,(DWORD_PTR)&len,0);
+        if (res == MMSYSERR_NOTSUPPORTED)
+        {
+            FIXME("No matching winmm device found, assuming winmm doesn't support mmdevapi and falling back to first device\n");
+            ppd->DeviceId = DSDEVID_DefaultCapture;
+            goto out;
+        }
+        data = HeapAlloc(GetProcessHeap(), 0, len);
+        if (!data)
+            hr = E_OUTOFMEMORY;
+        else
+            waveInMessage(UlongToHandle(wid),DRV_QUERYFUNCTIONINSTANCEID,(DWORD_PTR)data, len);
+        if (SUCCEEDED(hr))
+            hr = IMMDeviceEnumerator_GetDevice(DSOUND_obtain_mme(), data, &dev);
+        if (SUCCEEDED(hr))
+            hr = DSOUND_immdevice_getguid(dev, &ppd->DeviceId);
+        HeapFree(GetProcessHeap(), 0, data);
     }
 
+out:
     if (pcbReturned)
         *pcbReturned = cbPropData;
 
@@ -203,10 +242,22 @@ static HRESULT DSPROPERTY_DescriptionW(
     PULONG pcbReturned )
 {
     PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA ppd = pPropData;
-    HRESULT err;
     GUID dev_guid;
-    ULONG wod, wid, wodn, widn;
-    DSDRIVERDESC desc;
+    ULONG wodn, widn;
+    HRESULT hr;
+    WAVEINCAPSW caps_in;
+    WAVEOUTCAPSW caps_out;
+    IMMDeviceCollection *col = NULL;
+    IMMDevice *dev;
+    IMMEndpoint *endpoint = 0;
+    MMRESULT res;
+    EDataFlow flow;
+    WCHAR *str, *str2;
+    DWORD len = 0, len2;
+    GUID guid;
+    int i = 0;
+    static WCHAR wInterface[] = { 'I','n','t','e','r','f','a','c','e',0 };
+    static WCHAR wModule[] = { 'w','i','n','e','m','m','.','v','x','d',0 };
 
     TRACE("pPropData=%p,cbPropData=%d,pcbReturned=%p)\n",
           pPropData,cbPropData,pcbReturned);
@@ -226,65 +277,72 @@ static HRESULT DSPROPERTY_DescriptionW(
         }
     }
 
-    setup_dsound_options();
-
     GetDeviceID(&ppd->DeviceId, &dev_guid);
 
-    wodn = waveOutGetNumDevs();
-    widn = waveInGetNumDevs();
-    wid = wod = dev_guid.Data4[7];
-    if (!memcmp(&dev_guid, &DSOUND_renderer_guids[0], sizeof(GUID)-1)
-        && wod < wodn)
-    {
-        ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
-        ppd->WaveDeviceId = wod;
-    }
-    else if (!memcmp(&dev_guid, &DSOUND_capture_guids[0], sizeof(GUID)-1)
-             && wid < widn)
-    {
-        ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE;
-        ppd->WaveDeviceId = wid;
-    }
-    else
+    hr = DSOUND_enumerate_immdevice(eAll, &col);
+    if (FAILED(hr))
+        return hr;
+    while (IMMDeviceCollection_Item(col, i++, &dev) == S_OK)
     {
-        WARN("Device not found\n");
-        return E_PROP_ID_UNSUPPORTED;
+        DSOUND_immdevice_getguid(dev, &guid);
+        if (IsEqualGUID(&guid, &dev_guid))
+            break;
+        IMMDevice_Release(dev);
+        dev = NULL;
     }
-
-    if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER)
-        err = waveOutMessage(UlongToHandle(wod),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,ds_hw_accel);
-    else
-        err = waveInMessage(UlongToHandle(wod),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,ds_hw_accel);
-
-    if (err != MMSYSERR_NOERROR)
-    {
-        WARN("waveMessage(DRV_QUERYDSOUNDDESC) failed!\n");
+    IMMDeviceCollection_Release(col);
+    if (!dev)
         return E_PROP_ID_UNSUPPORTED;
-    }
-    else
+    IUnknown_QueryInterface(dev, &IID_IMMEndpoint, (void**)&endpoint);
+    IMMEndpoint_GetDataFlow(endpoint, &flow);
+    IUnknown_Release(endpoint);
+    ppd->DataFlow = flow == eCapture ? DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE : DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
+    IMMDevice_GetId(dev, &str);
+    IMMDevice_Release(dev);
+    len = (lstrlenW(str) + 1)*sizeof(WCHAR);
+    str2 = HeapAlloc(GetProcessHeap(), 0, len);
+
+    if (flow == eCapture)
     {
-        /* FIXME: Still a memory leak.. */
-        int desclen, modlen;
-        static WCHAR wInterface[] = { 'I','n','t','e','r','f','a','c','e',0 };
-
-        modlen = MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, NULL, 0 );
-        desclen = MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, NULL, 0 );
-        ppd->Module = HeapAlloc(GetProcessHeap(),0,modlen*sizeof(WCHAR));
-        ppd->Description = HeapAlloc(GetProcessHeap(),0,desclen*sizeof(WCHAR));
-        ppd->Interface = wInterface;
-        if (!ppd->Description || !ppd->Module)
+        widn = waveInGetNumDevs();
+        for (i = 0; i < widn; ++i)
         {
-            WARN("Out of memory\n");
-            HeapFree(GetProcessHeap(), 0, ppd->Description);
-            HeapFree(GetProcessHeap(), 0, ppd->Module);
-            ppd->Description = ppd->Module = NULL;
-            return E_OUTOFMEMORY;
+            res = waveInMessage(UlongToHandle(i),DRV_QUERYFUNCTIONINSTANCEIDSIZE,(DWORD_PTR)&len2,0);
+            if (res != MMSYSERR_NOERROR || len2 != len)
+                continue;
+            waveInMessage(UlongToHandle(i),DRV_QUERYFUNCTIONINSTANCEID,(DWORD_PTR)str2, len2);
+            if (!lstrcmpW(str2, str))
+                break;
         }
-
-        MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, ppd->Module, modlen );
-        MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, ppd->Description, desclen );
+        CoTaskMemFree(str);
+        HeapFree(GetProcessHeap(), 0, str2);
+        if (i == widn)
+            goto not_found;
+        waveInGetDevCapsW(i, &caps_in, sizeof(caps_in));
+        ppd->Description = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(caps_in.szPname)+1)*sizeof(WCHAR));
+        memcpy(ppd->Description, caps_in.szPname, (lstrlenW(caps_in.szPname)+1)*sizeof(WCHAR));
+    } else {
+        wodn = waveOutGetNumDevs();
+        for (i = 0; i < wodn; ++i)
+        {
+            res = waveOutMessage(UlongToHandle(i),DRV_QUERYFUNCTIONINSTANCEIDSIZE,(DWORD_PTR)&len2,0);
+            if (res != MMSYSERR_NOERROR || len2 != len)
+                continue;
+            waveOutMessage(UlongToHandle(i),DRV_QUERYFUNCTIONINSTANCEID,(DWORD_PTR)str2, len2);
+            if (!lstrcmpW(str2, str))
+                break;
+        }
+        CoTaskMemFree(str);
+        HeapFree(GetProcessHeap(), 0, str2);
+        if (i == wodn)
+            goto not_found;
+        waveOutGetDevCapsW(i, &caps_out, sizeof(caps_out));
+        ppd->Description = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(caps_out.szPname)+1)*sizeof(WCHAR));
+        memcpy(ppd->Description, caps_out.szPname, (lstrlenW(caps_out.szPname)+1)*sizeof(WCHAR));
     }
-
+    ppd->WaveDeviceId = i;
+    ppd->Module = wModule;
+    ppd->Interface = wInterface;
     ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
 
     if (pcbReturned) {
@@ -293,6 +351,30 @@ static HRESULT DSPROPERTY_DescriptionW(
     }
 
     return S_OK;
+
+not_found:
+    FIXME("No matching winmm device found\n");
+    return E_PROP_ID_UNSUPPORTED;
+}
+
+struct extended_enumerate_data {
+    DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W_DATA *ppd;
+    BOOL cont;
+};
+
+static BOOL CALLBACK enumerate_callback(GUID *guid, const WCHAR *desc, const WCHAR *module, void *ctx)
+{
+    struct extended_enumerate_data *enumdata = ctx;
+    DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA data;
+
+    if (!guid)
+        return 1;
+
+    data.DeviceId = *guid;
+    DSPROPERTY_DescriptionW(&data, sizeof(data), NULL);
+    enumdata->cont = enumdata->ppd->Callback(&data, enumdata->ppd->Context);
+    HeapFree(GetProcessHeap(), 0, data.Description);
+    return enumdata->cont;
 }
 
 static HRESULT DSPROPERTY_EnumerateW(
@@ -300,10 +382,8 @@ static HRESULT DSPROPERTY_EnumerateW(
     ULONG cbPropData,
     PULONG pcbReturned )
 {
+    struct extended_enumerate_data data;
     PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W_DATA ppd = pPropData;
-    DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA data;
-    BOOL ret;
-    int widn, wodn, i;
     TRACE("(pPropData=%p,cbPropData=%d,pcbReturned=%p)\n",
           pPropData,cbPropData,pcbReturned);
 
@@ -316,71 +396,31 @@ static HRESULT DSPROPERTY_EnumerateW(
         return E_PROP_ID_UNSUPPORTED;
     }
 
-    wodn = waveOutGetNumDevs();
-    widn = waveInGetNumDevs();
-
-    data.DeviceId = DSOUND_renderer_guids[0];
-    for (i = 0; i < wodn; ++i)
-    {
-        HRESULT hr;
-        data.DeviceId.Data4[7] = i;
-        hr = DSPROPERTY_DescriptionW(&data, sizeof(data), NULL);
-        if (FAILED(hr))
-        {
-            ERR("DescriptionW failed!\n");
-            return S_OK;
-        }
-        ret = ppd->Callback(&data, ppd->Context);
-        HeapFree(GetProcessHeap(), 0, data.Module);
-        HeapFree(GetProcessHeap(), 0, data.Description);
-        if (!ret)
-            return S_OK;
-    }
-
-    data.DeviceId = DSOUND_capture_guids[0];
-    for (i = 0; i < widn; ++i)
-    {
-        HRESULT hr;
-        data.DeviceId.Data4[7] = i;
-        hr = DSPROPERTY_DescriptionW(&data, sizeof(data), NULL);
-        if (FAILED(hr))
-        {
-            ERR("DescriptionW failed!\n");
-            return S_OK;
-        }
-        ret = ppd->Callback(&data, ppd->Context);
-        HeapFree(GetProcessHeap(), 0, data.Module);
-        HeapFree(GetProcessHeap(), 0, data.Description);
-        if (!ret)
-            return S_OK;
-    }
+    data.ppd = ppd;
+    data.cont = TRUE;
+    DirectSoundEnumerateW(enumerate_callback, &data);
+    if (data.cont)
+        DirectSoundCaptureEnumerateW(enumerate_callback, &data);
     return S_OK;
 }
 
 static BOOL DSPROPERTY_descWtoA(const DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA *dataW,
                                 DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A_DATA *dataA)
 {
-    DWORD modlen, desclen;
+    DWORD desclen;
     static char Interface[] = "Interface";
+    static char Module[] = "winemm.vxd";
 
-    modlen = WideCharToMultiByte(CP_ACP, 0, dataW->Module, -1, NULL, 0, NULL, NULL);
     desclen = WideCharToMultiByte(CP_ACP, 0, dataW->Description, -1, NULL, 0, NULL, NULL);
     dataA->Type = dataW->Type;
     dataA->DataFlow = dataW->DataFlow;
     dataA->DeviceId = dataW->DeviceId;
     dataA->WaveDeviceId = dataW->WaveDeviceId;
     dataA->Interface = Interface;
-    dataA->Module = HeapAlloc(GetProcessHeap(), 0, modlen);
+    dataA->Module = Module;
     dataA->Description = HeapAlloc(GetProcessHeap(), 0, desclen);
-    if (!dataA->Module || !dataA->Description)
-    {
-        HeapFree(GetProcessHeap(), 0, dataA->Module);
-        HeapFree(GetProcessHeap(), 0, dataA->Description);
-        dataA->Module = dataA->Description = NULL;
+    if (!dataA->Description)
         return FALSE;
-    }
-
-    WideCharToMultiByte(CP_ACP, 0, dataW->Module, -1, dataA->Module, modlen, NULL, NULL);
     WideCharToMultiByte(CP_ACP, 0, dataW->Description, -1, dataA->Description, desclen, NULL, NULL);
     return TRUE;
 }
@@ -410,7 +450,6 @@ static BOOL CALLBACK DSPROPERTY_enumWtoA(DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTIO
     if (!ret)
         return FALSE;
     ret = ppd->Callback(&descA, ppd->Context);
-    HeapFree(GetProcessHeap(), 0, descA.Module);
     HeapFree(GetProcessHeap(), 0, descA.Description);
     return ret;
 }
@@ -487,8 +526,6 @@ static HRESULT DSPROPERTY_DescriptionA(
         return hr;
     if (!DSPROPERTY_descWtoA(&data, ppd))
         hr = E_OUTOFMEMORY;
-    HeapFree(GetProcessHeap(), 0, data.Module);
-    HeapFree(GetProcessHeap(), 0, data.Interface);
     return hr;
 }
 
@@ -512,8 +549,7 @@ static HRESULT DSPROPERTY_Description1(
     if (FAILED(hr))
         return hr;
     DSPROPERTY_descWto1(&data, ppd);
-    HeapFree(GetProcessHeap(), 0, data.Module);
-    HeapFree(GetProcessHeap(), 0, data.Interface);
+    HeapFree(GetProcessHeap(), 0, data.Description);
     return hr;
 }
 
diff --git a/dlls/mmdevapi/tests/dependency.c b/dlls/mmdevapi/tests/dependency.c
index c14208e..59c48f8 100644
--- a/dlls/mmdevapi/tests/dependency.c
+++ b/dlls/mmdevapi/tests/dependency.c
@@ -71,7 +71,7 @@ START_TEST(dependency)
     ok(!GetModuleHandle("dsound.dll"), "dsound.dll was already loaded!\n");
 
     hr = IMMDevice_Activate(dev, &IID_IDirectSound8, CLSCTX_INPROC_SERVER, NULL, (void**)&ds8);
-    todo_wine ok(hr == S_OK, "Activating ds8 interface failed: 0x%08x\n", hr);
+    ok(hr == S_OK, "Activating ds8 interface failed: 0x%08x\n", hr);
     if (hr == S_OK)
     {
         ok(GetModuleHandle("dsound.dll") != NULL, "dsound.dll not loaded!\n");
-- 
1.7.6





More information about the wine-patches mailing list