Some games with support for the haptic feedback and speaker features of the Sony DualSense controller select the controller's audio output by filtering on the ContainerId IMMDevice property to find one that matches the controller's HID's. This MR allows this information to be accessible from the IMMDevice's property store when the audio driver provides it (none for now, but I intend to add that feature to `winepulse.drv` and maybe `winealsa.drv`)
Windows also stores the property in that registry key, but serializes it as binary instead of storing the string representation. I did not find documentation on that serialization, and while it seems mostly straightforward, there are two bytes I could not understand the meaning of: `{4a412178-e895-11ec-a989-00dbdfb57d1c}` is stored as `48 00 2b b7 01 00 00 00 78 21 41 4a 95 e8 ec 11 a9 89 00 db df b5 7d 1c`. The `01 00 00 00` DWORD seems to always have that same value, and the `2b b7` parts are safe to ignore when reading, but I do not know what meaning they have.
If there are already parts of Wine dealing with such a serialization, I could not find them, but I would gladly use them. Using the proper encoding would also conflict with `VT_BLOB` handling, but I suspect Windows also encodes `VT_BLOB` properties in a similar way than it does for `VT_CLSID`.
From: Claire Girka claire@sitedethib.com
Note that while Windows also stores the property in that registry key, it serializes it as binary instead of storing the string representation. --- dlls/mmdevapi/devenum.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/dlls/mmdevapi/devenum.c b/dlls/mmdevapi/devenum.c index bfeb3f3ecd8..19caf36e8d3 100644 --- a/dlls/mmdevapi/devenum.c +++ b/dlls/mmdevapi/devenum.c @@ -225,6 +225,17 @@ static HRESULT MMDevice_SetPropValue(const GUID *devguid, DWORD flow, REFPROPERT ret = RegSetValueExW(regkey, buffer, 0, REG_SZ, (const BYTE*)pv->pwszVal, sizeof(WCHAR)*(1+lstrlenW(pv->pwszVal))); break; } + case VT_CLSID: + { + WCHAR guidstr[39 /* MAX_GUID_STRING_LEN */]; + /* While this shouldn't be an issue in practice, that serialization is not how Windows do it. + Instead, Windows outputs VT_CLSID followed by 2 unknown bytes, a DWORD with value 1, then + the binary representation of the ID */ + FIXME("Type VT_CLSID should be serialized as binary rather than as a string\n"); + StringFromGUID2(pv->puuid, guidstr, ARRAY_SIZE(guidstr)); + ret = RegSetValueExW(regkey, buffer, 0, REG_SZ, (const BYTE*)guidstr, sizeof(WCHAR) * 39); + break; + } default: ret = 0; FIXME("Unhandled type %u\n", pv->vt);
From: Claire Girka claire@sitedethib.com
--- dlls/mmdevapi/devenum.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
diff --git a/dlls/mmdevapi/devenum.c b/dlls/mmdevapi/devenum.c index 19caf36e8d3..0ffd4fd1ad7 100644 --- a/dlls/mmdevapi/devenum.c +++ b/dlls/mmdevapi/devenum.c @@ -1450,6 +1450,24 @@ static HRESULT WINAPI MMDevPropStore_GetValue(IPropertyStore *iface, REFPROPERTY if (FAILED(hres)) return hres;
+ /* Clients apps expect a CLSID */ + if(IsEqualPropertyKey(*key,DEVPKEY_Device_ContainerId) && pv->vt == VT_LPWSTR && pv->pwszVal) { + LPWSTR guidstr = pv->pwszVal; + + pv->puuid = CoTaskMemAlloc(sizeof(*pv->puuid)); + if (!pv->puuid) + return E_OUTOFMEMORY; + + hres = CLSIDFromString(guidstr, pv->puuid); + if (FAILED(hres)) + return hres; + + pv->vt = VT_CLSID; + CoTaskMemFree(guidstr); + + return hres; + } + if (WARN_ON(mmdevapi)) { if ((IsEqualPropertyKey(*key, DEVPKEY_Device_FriendlyName) ||
From: Claire Girka claire@sitedethib.com
Some games with support for the haptic feedback and speaker features of the Sony DualSense controller select the controller's audio output by filtering on the ContainerId IMMDevice property to find one that matches the controller's HID's. --- dlls/mmdevapi/devenum.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/dlls/mmdevapi/devenum.c b/dlls/mmdevapi/devenum.c index 0ffd4fd1ad7..9f95930c308 100644 --- a/dlls/mmdevapi/devenum.c +++ b/dlls/mmdevapi/devenum.c @@ -375,6 +375,8 @@ static MMDevice *MMDevice_Create(WCHAR *name, GUID *id, EDataFlow flow, DWORD st MMDevice_SetPropValue(id, flow, (const PROPERTYKEY*)&DEVPKEY_DeviceInterface_FriendlyName, &pv); MMDevice_SetPropValue(id, flow, (const PROPERTYKEY*)&DEVPKEY_Device_DeviceDesc, &pv);
+ set_driver_prop_value(id, flow, (const PROPERTYKEY*)&DEVPKEY_Device_ContainerId); + pv.pwszVal = guidstr; MMDevice_SetPropValue(id, flow, &deviceinterface_key, &pv);