From f6890ef0e227afd12ce2325497d0cae478602c7d Mon Sep 17 00:00:00 2001 From: Andrew Eikum Date: Wed, 31 Aug 2011 15:04:23 -0500 Subject: [PATCH] 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 8a712628046..0cb471b4d52 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 c694c6e1d9b..57541aba10c 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 2c3cd2d1444..e61c539d4a2 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 907d3561b95..b8f1b5496e6 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 #include #include @@ -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(); } /****************************************************************** -- 2.11.4.GIT