From: Mark Harmstone Subject: [PATCH 4/5] mmdevapi: add property for device path Message-Id: <545CDE0E.4000709@burntcomma.com> Date: Fri, 07 Nov 2014 14:58:22 +0000 --- dlls/mmdevapi/devenum.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/dlls/mmdevapi/devenum.c b/dlls/mmdevapi/devenum.c index 4d77ec9..2a64edf 100644 --- a/dlls/mmdevapi/devenum.c +++ b/dlls/mmdevapi/devenum.c @@ -264,6 +264,42 @@ static HRESULT MMDevice_SetPropValue(const GUID *devguid, DWORD flow, REFPROPERT return hr; } +static WCHAR* format_device_path(DeviceProps *props, GUID *id) +{ + WCHAR* s; + + if (props->connection_type == AudioDeviceConnectionType_USB || props->connection_type == AudioDeviceConnectionType_PCI) { + static const WCHAR usbformatW[] = { '{','1','}','.','U','S','B','\\','V','I','D','_', + '%','0','4','X','&','P','I','D','_','%','0','4','X','\\', + '1','&','%','0','8','X',0 }; // "{1}.USB\VID_%04X&PID_%04X\1&%08X" + static const WCHAR pciformatW[] = { '{','1','}','.','H','D','A','U','D','I','O','\\','F','U','N','C','_','0','1','&', + 'V','E','N','_','%','0','4','X','&','D','E','V','_', + '%','0','4','X','\\','1','&','%','0','8','X',0 }; // "{1}.HDAUDIO\FUNC_01&VEN_%04X&DEV_%04X\1&%08X" + UINT serial_number; + + /* As hardly any audio devices have serial numbers, Windows instead + appears to use a persistent random number. We emulate this here + by instead using the last 8 hex digits of the GUID. */ + serial_number = (id->Data4[4] << 24) | (id->Data4[5] << 16) | (id->Data4[6] << 8) | id->Data4[7]; + + if (props->connection_type == AudioDeviceConnectionType_USB) { + s = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * 37); + + wsprintfW( s, usbformatW, props->vendor_id, props->product_id, serial_number); + } else if (props->connection_type == AudioDeviceConnectionType_PCI) { + s = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * 49); + + wsprintfW( s, pciformatW, props->vendor_id, props->product_id, serial_number); + } else { + return NULL; + } + + return s; + } else { + return NULL; + } +} + /* Creates or updates the state of a device * If GUID is null, a random guid will be assigned * and the device will be created @@ -279,6 +315,10 @@ static MMDevice *MMDevice_Create(DeviceProps *props, GUID *id, EDataFlow flow, D {0x233164c8, 0x1b2c, 0x4c7d, {0xbc, 0x68, 0xb6, 0x71, 0x68, 0x7a, 0x25, 0x67}}, 1 }; + static const PROPERTYKEY devicepath_key = { // undocumented? - {b3f8fa53-0004-438e-9003-51a46e139bfc},2 + {0xb3f8fa53, 0x0004, 0x438e, {0x90, 0x03, 0x51, 0xa4, 0x6e, 0x13, 0x9b, 0xfc}}, 2 + }; + for (i = 0; i < MMDevice_count; ++i) { MMDevice *device = MMDevice_head[i]; @@ -329,6 +369,7 @@ static MMDevice *MMDevice_Create(DeviceProps *props, GUID *id, EDataFlow flow, D if (!RegCreateKeyExW(key, reg_properties, 0, NULL, 0, KEY_WRITE|KEY_READ, NULL, &keyprop, NULL)) { PROPVARIANT pv; + WCHAR* devpath; pv.vt = VT_LPWSTR; pv.u.pwszVal = props->id; @@ -342,6 +383,19 @@ static MMDevice *MMDevice_Create(DeviceProps *props, GUID *id, EDataFlow flow, D pv.u.ulVal = props->form_factor; MMDevice_SetPropValue(id, flow, &PKEY_AudioEndpoint_FormFactor, &pv); + // only create registry entry if none exists already, to allow manual override + if (FAILED(MMDevice_GetPropValue(id, flow, &devicepath_key, &pv)) || pv.vt != VT_LPWSTR) + { + devpath = format_device_path(props, id); + if (devpath) { + pv.vt = VT_LPWSTR; + pv.u.pwszVal = devpath; + MMDevice_SetPropValue(id, flow, &devicepath_key, &pv); + + HeapFree(GetProcessHeap(), 0, devpath); + } + } + RegCloseKey(keyprop); } RegCloseKey(key);