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 IPropertyStoreVtbl MMDevPropVtbl;
|
||||||
static const IMMEndpointVtbl MMEndpointVtbl;
|
static const IMMEndpointVtbl MMEndpointVtbl;
|
||||||
|
|
||||||
|
static IMMDevice info_device;
|
||||||
|
|
||||||
typedef struct MMDevColImpl
|
typedef struct MMDevColImpl
|
||||||
{
|
{
|
||||||
IMMDeviceCollection IMMDeviceCollection_iface;
|
IMMDeviceCollection IMMDeviceCollection_iface;
|
||||||
|
@ -935,10 +937,19 @@ static HRESULT WINAPI MMDevEnum_GetDevice(IMMDeviceEnumerator *iface, const WCHA
|
||||||
DWORD i=0;
|
DWORD i=0;
|
||||||
IMMDevice *dev = NULL;
|
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)
|
if(!name || !device)
|
||||||
return E_POINTER;
|
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)
|
for (i = 0; i < MMDevice_count; ++i)
|
||||||
{
|
{
|
||||||
WCHAR *str;
|
WCHAR *str;
|
||||||
|
@ -1211,3 +1222,85 @@ static const IPropertyBagVtbl PB_Vtbl =
|
||||||
PB_Read,
|
PB_Read,
|
||||||
PB_Write
|
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);
|
LDFC(GetAudioSessionManager);
|
||||||
#undef LDFC
|
#undef LDFC
|
||||||
|
|
||||||
|
lstrcpyW(drvs.module_name, driver_module);
|
||||||
TRACE("Successfully loaded %s\n", wine_dbgstr_w(driver_module));
|
TRACE("Successfully loaded %s\n", wine_dbgstr_w(driver_module));
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
|
@ -27,6 +27,7 @@ extern HRESULT MMDevice_GetPropValue(const GUID *devguid, DWORD flow, REFPROPERT
|
||||||
|
|
||||||
typedef struct _DriverFuncs {
|
typedef struct _DriverFuncs {
|
||||||
HMODULE module;
|
HMODULE module;
|
||||||
|
WCHAR module_name[64];
|
||||||
|
|
||||||
/* ids gets an array of human-friendly endpoint names
|
/* ids gets an array of human-friendly endpoint names
|
||||||
* keys gets an array of driver-specific stuff that is used
|
* keys gets an array of driver-specific stuff that is used
|
||||||
|
|
|
@ -23,6 +23,9 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "wine/port.h"
|
#include "wine/port.h"
|
||||||
|
|
||||||
|
#define NONAMELESSUNION
|
||||||
|
#define NONAMELESSSTRUCT
|
||||||
|
#define COBJMACROS
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -30,10 +33,16 @@
|
||||||
#include "windef.h"
|
#include "windef.h"
|
||||||
#include "winbase.h"
|
#include "winbase.h"
|
||||||
#include "winreg.h"
|
#include "winreg.h"
|
||||||
|
#include "winnls.h"
|
||||||
#include "winemm.h"
|
#include "winemm.h"
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
#include "wine/exception.h"
|
#include "wine/exception.h"
|
||||||
|
|
||||||
|
#include "wingdi.h"
|
||||||
|
#include "ole2.h"
|
||||||
|
#include "devpkey.h"
|
||||||
|
#include "mmdeviceapi.h"
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(winmm);
|
WINE_DEFAULT_DEBUG_CHANNEL(winmm);
|
||||||
|
|
||||||
/* Default set of drivers to be loaded */
|
/* 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)
|
static void MMDRV_Init(void)
|
||||||
{
|
{
|
||||||
HKEY hKey;
|
IMMDeviceEnumerator *devenum;
|
||||||
char driver_buffer[256];
|
IMMDevice *device;
|
||||||
char *p, *next;
|
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");
|
TRACE("()\n");
|
||||||
|
|
||||||
strcpy(driver_buffer, WINE_DEFAULT_WINMM_DRIVER);
|
init_hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
|
||||||
|
|
||||||
/* @@ Wine registry key: HKCU\Software\Wine\Drivers */
|
hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL,
|
||||||
if (!RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Drivers", &hKey))
|
CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, (void**)&devenum);
|
||||||
{
|
if(FAILED(hr)){
|
||||||
DWORD size = sizeof(driver_buffer);
|
ERR("CoCreateInstance failed: %08x\n", hr);
|
||||||
if (RegQueryValueExA(hKey, "Audio", 0, NULL, (BYTE*)driver_buffer, &size))
|
goto exit;
|
||||||
strcpy(driver_buffer, WINE_DEFAULT_WINMM_DRIVER);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (p = driver_buffer; p; p = next)
|
hr = IMMDeviceEnumerator_GetDevice(devenum, wine_info_deviceW, &device);
|
||||||
{
|
IMMDeviceEnumerator_Release(devenum);
|
||||||
char filename[sizeof(driver_buffer)+10];
|
if(FAILED(hr)){
|
||||||
next = strchr(p, ',');
|
ERR("GetDevice failed: %08x\n", hr);
|
||||||
if (next) *next++ = 0;
|
goto exit;
|
||||||
sprintf( filename, "wine%s.drv", p );
|
|
||||||
if (MMDRV_Install(filename, filename, FALSE))
|
|
||||||
break;
|
|
||||||
p = next;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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("wavemapper", "msacm32.drv", TRUE);
|
||||||
MMDRV_Install("midimapper", "midimap.dll", TRUE);
|
MMDRV_Install("midimapper", "midimap.dll", TRUE);
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if(SUCCEEDED(init_hr))
|
||||||
|
CoUninitialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************
|
/******************************************************************
|
||||||
|
|
Loading…
Reference in New Issue