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