winmm: Determine the driver from MMDevAPI.

This uses a half-implemented, Wine-specific IMMDevice object to extract
the driver name.
This commit is contained in:
Andrew Eikum 2011-08-31 15:04:23 -05:00 committed by Alexandre Julliard
parent 9d9baef789
commit f6890ef0e2
4 changed files with 157 additions and 20 deletions

View File

@ -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
};

View File

@ -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;

View File

@ -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

View File

@ -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();
}
/******************************************************************