Andrew Eikum : winmm: Support DRV_QUERYDEVICEINTERFACE in waveXxxMessage.
Alexandre Julliard
julliard at winehq.org
Fri Apr 6 14:43:23 CDT 2012
Module: wine
Branch: master
Commit: d022cc1ddfecd7c8a942ea29d18e0cdb0fe5a5de
URL: http://source.winehq.org/git/wine.git/?a=commit;h=d022cc1ddfecd7c8a942ea29d18e0cdb0fe5a5de
Author: Andrew Eikum <aeikum at codeweavers.com>
Date: Thu Apr 5 14:16:44 2012 -0500
winmm: Support DRV_QUERYDEVICEINTERFACE in waveXxxMessage.
---
dlls/winmm/tests/wave.c | 4 +-
dlls/winmm/waveform.c | 129 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 131 insertions(+), 2 deletions(-)
diff --git a/dlls/winmm/tests/wave.c b/dlls/winmm/tests/wave.c
index 8a070b3..111dd1c 100644
--- a/dlls/winmm/tests/wave.c
+++ b/dlls/winmm/tests/wave.c
@@ -919,8 +919,8 @@ static void wave_out_test_device(UINT_PTR device)
nameA=NULL;
rc=waveOutMessage((HWAVEOUT)device, DRV_QUERYDEVICEINTERFACESIZE,
(DWORD_PTR)&size, 0);
- ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_INVALPARAM ||
- rc==MMSYSERR_NOTSUPPORTED,
+ ok(rc==MMSYSERR_NOERROR || broken(rc==MMSYSERR_INVALPARAM ||
+ rc==MMSYSERR_NOTSUPPORTED),
"waveOutMessage(%s): failed to get interface size, rc=%s\n",
dev_name(device),wave_out_error(rc));
if (rc==MMSYSERR_NOERROR) {
diff --git a/dlls/winmm/waveform.c b/dlls/winmm/waveform.c
index c7d3118..d4dc9aa 100644
--- a/dlls/winmm/waveform.c
+++ b/dlls/winmm/waveform.c
@@ -169,6 +169,13 @@ typedef struct _WINMM_ControlDetails {
DWORD flags;
} WINMM_ControlDetails;
+typedef struct _WINMM_QueryInterfaceInfo {
+ BOOL is_out;
+ UINT index;
+ WCHAR *str;
+ UINT *len_bytes;
+} WINMM_QueryInterfaceInfo;
+
static LRESULT WOD_Open(WINMM_OpenInfo *info);
static LRESULT WOD_Close(HWAVEOUT hwave);
static LRESULT WID_Open(WINMM_OpenInfo *info);
@@ -2014,6 +2021,92 @@ static LRESULT MXD_SetControlDetails(WINMM_ControlDetails *details)
return MMSYSERR_NOERROR;
}
+static LRESULT DRV_QueryDeviceInterface(WINMM_QueryInterfaceInfo *info)
+{
+ WINMM_MMDevice *mmdevice;
+ IMMDevice *device;
+ IPropertyStore *ps;
+ PROPVARIANT pv;
+ DWORD len_bytes;
+ HRESULT hr;
+
+ static const PROPERTYKEY deviceinterface_key = {
+ {0x233164c8, 0x1b2c, 0x4c7d, {0xbc, 0x68, 0xb6, 0x71, 0x68, 0x7a, 0x25, 0x67}}, 1
+ };
+
+ if(WINMM_IsMapper(info->index)){
+ if(info->str){
+ if(*info->len_bytes < sizeof(WCHAR))
+ return MMSYSERR_INVALPARAM;
+ *info->str = 0;
+ }else
+ *info->len_bytes = sizeof(WCHAR);
+ return MMSYSERR_NOERROR;
+ }
+
+ if(info->is_out){
+ if(info->index >= g_outmmdevices_count)
+ return MMSYSERR_INVALHANDLE;
+
+ mmdevice = &g_out_mmdevices[info->index];
+ }else{
+ if(info->index >= g_inmmdevices_count)
+ return MMSYSERR_INVALHANDLE;
+
+ mmdevice = &g_in_mmdevices[info->index];
+ }
+
+ hr = IMMDeviceEnumerator_GetDevice(g_devenum, mmdevice->dev_id,
+ &device);
+ if(FAILED(hr)){
+ WARN("Device %s unavailable: %08x\n", wine_dbgstr_w(mmdevice->dev_id), hr);
+ return MMSYSERR_ERROR;
+ }
+
+ hr = IMMDevice_OpenPropertyStore(device, STGM_READ, &ps);
+ if(FAILED(hr)){
+ WARN("OpenPropertyStore failed: %08x\n", hr);
+ IMMDevice_Release(device);
+ return MMSYSERR_ERROR;
+ }
+
+ PropVariantInit(&pv);
+ hr = IPropertyStore_GetValue(ps, &deviceinterface_key, &pv);
+ if(FAILED(hr)){
+ WARN("GetValue failed: %08x\n", hr);
+ IPropertyStore_Release(ps);
+ IMMDevice_Release(device);
+ return MMSYSERR_ERROR;
+ }
+ if(pv.vt != VT_LPWSTR){
+ WARN("Got unexpected property type: %u\n", pv.vt);
+ PropVariantClear(&pv);
+ IPropertyStore_Release(ps);
+ IMMDevice_Release(device);
+ return MMSYSERR_ERROR;
+ }
+
+ len_bytes = (lstrlenW(pv.u.pwszVal) + 1) * sizeof(WCHAR);
+
+ if(info->str){
+ if(len_bytes > *info->len_bytes){
+ PropVariantClear(&pv);
+ IPropertyStore_Release(ps);
+ IMMDevice_Release(device);
+ return MMSYSERR_INVALPARAM;
+ }
+
+ memcpy(info->str, pv.u.pwszVal, len_bytes);
+ }else
+ *info->len_bytes = len_bytes;
+
+ PropVariantClear(&pv);
+ IPropertyStore_Release(ps);
+ IMMDevice_Release(device);
+
+ return MMSYSERR_NOERROR;
+}
+
static LRESULT CALLBACK WINMM_DevicesMsgProc(HWND hwnd, UINT msg, WPARAM wparam,
LPARAM lparam)
{
@@ -2030,6 +2123,9 @@ static LRESULT CALLBACK WINMM_DevicesMsgProc(HWND hwnd, UINT msg, WPARAM wparam,
return MXD_GetControlDetails((WINMM_ControlDetails*)wparam);
case MXDM_SETCONTROLDETAILS:
return MXD_SetControlDetails((WINMM_ControlDetails*)wparam);
+ case DRV_QUERYDEVICEINTERFACESIZE:
+ case DRV_QUERYDEVICEINTERFACE:
+ return DRV_QueryDeviceInterface((WINMM_QueryInterfaceInfo*)wparam);
}
return DefWindowProcW(hwnd, msg, wparam, lparam);
}
@@ -2781,6 +2877,21 @@ static UINT WINMM_QueryInstanceID(UINT device, WCHAR *str, DWORD_PTR len,
return MMSYSERR_NOERROR;
}
+static UINT get_device_interface(UINT msg, BOOL is_out, UINT index, WCHAR *out, ULONG *out_len)
+{
+ WINMM_QueryInterfaceInfo info;
+
+ if(!WINMM_StartDevicesThread())
+ return MMSYSERR_ERROR;
+
+ info.is_out = is_out;
+ info.index = index;
+ info.str = out;
+ info.len_bytes = out_len;
+
+ return SendMessageW(g_devices_hwnd, msg, (DWORD_PTR)&info, 0);
+}
+
/**************************************************************************
* waveOutMessage [WINMM.@]
*/
@@ -2795,6 +2906,15 @@ UINT WINAPI waveOutMessage(HWAVEOUT hWaveOut, UINT uMessage,
(DWORD_PTR*)dwParam1, TRUE);
case DRV_QUERYFUNCTIONINSTANCEID:
return WINMM_QueryInstanceID(HandleToULong(hWaveOut), (WCHAR*)dwParam1, dwParam2, TRUE);
+ case DRV_QUERYDEVICEINTERFACESIZE:
+ return get_device_interface(DRV_QUERYDEVICEINTERFACESIZE, TRUE, HandleToULong(hWaveOut),
+ NULL, (ULONG*)dwParam1);
+ case DRV_QUERYDEVICEINTERFACE:
+ {
+ ULONG size = dwParam2;
+ return get_device_interface(DRV_QUERYDEVICEINTERFACE, TRUE, HandleToULong(hWaveOut),
+ (WCHAR*)dwParam1, &size);
+ }
case DRV_QUERYMAPPABLE:
return MMSYSERR_NOERROR;
case DRVM_MAPPER_PREFERRED_GET:
@@ -3185,6 +3305,15 @@ UINT WINAPI waveInMessage(HWAVEIN hWaveIn, UINT uMessage,
(DWORD_PTR*)dwParam1, FALSE);
case DRV_QUERYFUNCTIONINSTANCEID:
return WINMM_QueryInstanceID(HandleToULong(hWaveIn), (WCHAR*)dwParam1, dwParam2, FALSE);
+ case DRV_QUERYDEVICEINTERFACESIZE:
+ return get_device_interface(DRV_QUERYDEVICEINTERFACESIZE, FALSE, HandleToULong(hWaveIn),
+ NULL, (ULONG*)dwParam1);
+ case DRV_QUERYDEVICEINTERFACE:
+ {
+ ULONG size = dwParam2;
+ return get_device_interface(DRV_QUERYDEVICEINTERFACE, FALSE, HandleToULong(hWaveIn),
+ (WCHAR*)dwParam1, &size);
+ }
case DRV_QUERYMAPPABLE:
return MMSYSERR_NOERROR;
case DRVM_MAPPER_PREFERRED_GET:
More information about the wine-cvs
mailing list