From d022cc1ddfecd7c8a942ea29d18e0cdb0fe5a5de Mon Sep 17 00:00:00 2001 From: Andrew Eikum Date: Thu, 5 Apr 2012 14:16:44 -0500 Subject: [PATCH] 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 8a070b33202..111dd1c2ed9 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 c7d3118090e..d4dc9aadf4f 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: