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:
parent
9d9baef789
commit
f6890ef0e2
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
|
|
Loading…
Reference in New Issue