Andrew Eikum : winmm: Determine the driver from MMDevAPI.

Alexandre Julliard julliard at winehq.org
Thu Sep 1 11:55:58 CDT 2011


Module: wine
Branch: master
Commit: f6890ef0e227afd12ce2325497d0cae478602c7d
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=f6890ef0e227afd12ce2325497d0cae478602c7d

Author: Andrew Eikum <aeikum at codeweavers.com>
Date:   Wed Aug 31 15:04:23 2011 -0500

winmm: Determine the driver from MMDevAPI.

This uses a half-implemented, Wine-specific IMMDevice object to extract
the driver name.

---

 dlls/mmdevapi/devenum.c  |   95 +++++++++++++++++++++++++++++++++++++++++++++-
 dlls/mmdevapi/main.c     |    1 +
 dlls/mmdevapi/mmdevapi.h |    1 +
 dlls/winmm/lolvldrv.c    |   80 +++++++++++++++++++++++++++++---------
 4 files changed, 157 insertions(+), 20 deletions(-)

diff --git a/dlls/mmdevapi/devenum.c b/dlls/mmdevapi/devenum.c
index 8a71262..0cb471b 100644
--- a/dlls/mmdevapi/devenum.c
+++ b/dlls/mmdevapi/devenum.c
@@ -85,6 +85,8 @@ static const IMMDeviceVtbl MMDeviceVtbl;
 static const IPropertyStoreVtbl MMDevPropVtbl;
 static const IMMEndpointVtbl MMEndpointVtbl;
 
+static IMMDevice info_device;
+
 typedef struct MMDevColImpl
 {
     IMMDeviceCollection IMMDeviceCollection_iface;
@@ -935,10 +937,19 @@ static HRESULT WINAPI MMDevEnum_GetDevice(IMMDeviceEnumerator *iface, const WCHA
     DWORD i=0;
     IMMDevice *dev = NULL;
 
+    static const WCHAR wine_info_deviceW[] = {'W','i','n','e',' ',
+        'i','n','f','o',' ','d','e','v','i','c','e',0};
+
+    TRACE("(%p)->(%s,%p)\n", This, debugstr_w(name), device);
+
     if(!name || !device)
         return E_POINTER;
 
-    TRACE("(%p)->(%s,%p)\n", This, debugstr_w(name), device);
+    if(!lstrcmpW(name, wine_info_deviceW)){
+        *device = &info_device;
+        return S_OK;
+    }
+
     for (i = 0; i < MMDevice_count; ++i)
     {
         WCHAR *str;
@@ -1211,3 +1222,85 @@ static const IPropertyBagVtbl PB_Vtbl =
     PB_Read,
     PB_Write
 };
+
+static ULONG WINAPI info_device_ps_AddRef(IPropertyStore *iface)
+{
+    return 2;
+}
+
+static ULONG WINAPI info_device_ps_Release(IPropertyStore *iface)
+{
+    return 1;
+}
+
+static HRESULT WINAPI info_device_ps_GetValue(IPropertyStore *iface,
+        REFPROPERTYKEY key, PROPVARIANT *pv)
+{
+    MMDevPropStore *This = impl_from_IPropertyStore(iface);
+
+    if (!key || !pv)
+        return E_POINTER;
+    if (This->access != STGM_READ
+        && This->access != STGM_READWRITE)
+        return STG_E_ACCESSDENIED;
+
+    if (IsEqualPropertyKey(*key, DEVPKEY_Device_Driver))
+    {
+        pv->vt = VT_LPWSTR;
+        pv->u.pwszVal = CoTaskMemAlloc(lstrlenW(drvs.module_name) * sizeof(WCHAR));
+        if (!pv->u.pwszVal)
+            return E_OUTOFMEMORY;
+        lstrcpyW(pv->u.pwszVal, drvs.module_name);
+        return S_OK;
+    }
+
+    return E_INVALIDARG;
+}
+
+static const IPropertyStoreVtbl info_device_ps_Vtbl =
+{
+    NULL,
+    info_device_ps_AddRef,
+    info_device_ps_Release,
+    NULL,
+    NULL,
+    info_device_ps_GetValue,
+    NULL,
+    NULL
+};
+
+static IPropertyStore info_device_ps = {
+    &info_device_ps_Vtbl
+};
+
+static ULONG WINAPI info_device_AddRef(IMMDevice *iface)
+{
+    return 2;
+}
+
+static ULONG WINAPI info_device_Release(IMMDevice *iface)
+{
+    return 1;
+}
+
+static HRESULT WINAPI info_device_OpenPropertyStore(IMMDevice *iface,
+        DWORD access, IPropertyStore **ppv)
+{
+    *ppv = &info_device_ps;
+    return S_OK;
+}
+
+static const IMMDeviceVtbl info_device_Vtbl =
+{
+    NULL,
+    info_device_AddRef,
+    info_device_Release,
+    NULL,
+    info_device_OpenPropertyStore,
+    NULL,
+    NULL
+};
+
+static IMMDevice info_device = {
+    &info_device_Vtbl
+};
diff --git a/dlls/mmdevapi/main.c b/dlls/mmdevapi/main.c
index c694c6e..57541ab 100644
--- a/dlls/mmdevapi/main.c
+++ b/dlls/mmdevapi/main.c
@@ -79,6 +79,7 @@ static BOOL load_driver(const WCHAR *name)
     LDFC(GetAudioSessionManager);
 #undef LDFC
 
+    lstrcpyW(drvs.module_name, driver_module);
     TRACE("Successfully loaded %s\n", wine_dbgstr_w(driver_module));
 
     return TRUE;
diff --git a/dlls/mmdevapi/mmdevapi.h b/dlls/mmdevapi/mmdevapi.h
index 2c3cd2d..e61c539 100644
--- a/dlls/mmdevapi/mmdevapi.h
+++ b/dlls/mmdevapi/mmdevapi.h
@@ -27,6 +27,7 @@ extern HRESULT MMDevice_GetPropValue(const GUID *devguid, DWORD flow, REFPROPERT
 
 typedef struct _DriverFuncs {
     HMODULE module;
+    WCHAR module_name[64];
 
     /* ids gets an array of human-friendly endpoint names
      * keys gets an array of driver-specific stuff that is used
diff --git a/dlls/winmm/lolvldrv.c b/dlls/winmm/lolvldrv.c
index 907d356..b8f1b54 100644
--- a/dlls/winmm/lolvldrv.c
+++ b/dlls/winmm/lolvldrv.c
@@ -23,6 +23,9 @@
 #include "config.h"
 #include "wine/port.h"
 
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
+#define COBJMACROS
 #include <string.h>
 #include <stdarg.h>
 #include <stdio.h>
@@ -30,10 +33,16 @@
 #include "windef.h"
 #include "winbase.h"
 #include "winreg.h"
+#include "winnls.h"
 #include "winemm.h"
 #include "wine/debug.h"
 #include "wine/exception.h"
 
+#include "wingdi.h"
+#include "ole2.h"
+#include "devpkey.h"
+#include "mmdeviceapi.h"
+
 WINE_DEFAULT_DEBUG_CHANNEL(winmm);
 
 /* Default set of drivers to be loaded */
@@ -509,34 +518,67 @@ static	BOOL	MMDRV_Install(LPCSTR drvRegName, LPCSTR drvFileName, BOOL bIsMapper)
  */
 static void MMDRV_Init(void)
 {
-    HKEY	hKey;
-    char	driver_buffer[256];
-    char *p, *next;
+    IMMDeviceEnumerator *devenum;
+    IMMDevice *device;
+    IPropertyStore *ps;
+    PROPVARIANT pv;
+    DWORD size;
+    char *drvA;
+    HRESULT init_hr, hr;
+
+    static const WCHAR wine_info_deviceW[] = {'W','i','n','e',' ',
+        'i','n','f','o',' ','d','e','v','i','c','e',0};
+
     TRACE("()\n");
 
-    strcpy(driver_buffer, WINE_DEFAULT_WINMM_DRIVER);
+    init_hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
 
-    /* @@ Wine registry key: HKCU\Software\Wine\Drivers */
-    if (!RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Drivers", &hKey))
-    {
-        DWORD size = sizeof(driver_buffer);
-        if (RegQueryValueExA(hKey, "Audio", 0, NULL, (BYTE*)driver_buffer, &size))
-            strcpy(driver_buffer, WINE_DEFAULT_WINMM_DRIVER);
+    hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL,
+            CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, (void**)&devenum);
+    if(FAILED(hr)){
+        ERR("CoCreateInstance failed: %08x\n", hr);
+        goto exit;
     }
 
-    for (p = driver_buffer; p; p = next)
-    {
-        char filename[sizeof(driver_buffer)+10];
-        next = strchr(p, ',');
-        if (next) *next++ = 0;
-        sprintf( filename, "wine%s.drv", p );
-        if (MMDRV_Install(filename, filename, FALSE))
-            break;
-        p = next;
+    hr = IMMDeviceEnumerator_GetDevice(devenum, wine_info_deviceW, &device);
+    IMMDeviceEnumerator_Release(devenum);
+    if(FAILED(hr)){
+        ERR("GetDevice failed: %08x\n", hr);
+        goto exit;
+    }
+
+    hr = IMMDevice_OpenPropertyStore(device, STGM_READ, &ps);
+    if(FAILED(hr)){
+        ERR("OpenPropertyStore failed: %08x\n", hr);
+        IMMDevice_Release(device);
+        goto exit;
     }
 
+    hr = IPropertyStore_GetValue(ps,
+            (const PROPERTYKEY *)&DEVPKEY_Device_Driver, &pv);
+    IPropertyStore_Release(ps);
+    IMMDevice_Release(device);
+    if(FAILED(hr)){
+        ERR("GetValue failed: %08x\n", hr);
+        goto exit;
+    }
+
+    size = WideCharToMultiByte(CP_ACP, 0, pv.u.pwszVal, -1,
+            NULL, 0, NULL, NULL);
+    drvA = HeapAlloc(GetProcessHeap(), 0, size);
+    WideCharToMultiByte(CP_ACP, 0, pv.u.pwszVal, -1, drvA, size, NULL, NULL);
+
+    MMDRV_Install(drvA, drvA, FALSE);
+
+    HeapFree(GetProcessHeap(), 0, drvA);
+    PropVariantClear(&pv);
+
     MMDRV_Install("wavemapper", "msacm32.drv", TRUE);
     MMDRV_Install("midimapper", "midimap.dll", TRUE);
+
+exit:
+    if(SUCCEEDED(init_hr))
+        CoUninitialize();
 }
 
 /******************************************************************




More information about the wine-cvs mailing list