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