Somehow the field is not present for sound capture devices, at least on my Win11.
Fixes Tom Clancy's Splinter Cell: Conviction not finding any sound devices and refusing to start.
From: Paul Gofman pgofman@codeweavers.com
--- dlls/dxdiagn/Makefile.in | 2 +- dlls/dxdiagn/dxdiag_main.c | 2 +- dlls/dxdiagn/dxdiag_private.h | 4 -- dlls/dxdiagn/provider.c | 73 ++++++++++++++++++++++++++++++++++ dlls/dxdiagn/tests/container.c | 1 + 5 files changed, 76 insertions(+), 6 deletions(-)
diff --git a/dlls/dxdiagn/Makefile.in b/dlls/dxdiagn/Makefile.in index da0b48b9894..e556a93f8e8 100644 --- a/dlls/dxdiagn/Makefile.in +++ b/dlls/dxdiagn/Makefile.in @@ -1,5 +1,5 @@ MODULE = dxdiagn.dll -IMPORTS = strmiids dxguid uuid d3d9 ddraw dsound version ole32 oleaut32 user32 advapi32 +IMPORTS = strmiids dxguid d3d9 ddraw dsound version ole32 oleaut32 user32 advapi32
SOURCES = \ container.c \ diff --git a/dlls/dxdiagn/dxdiag_main.c b/dlls/dxdiagn/dxdiag_main.c index 90e769cd81f..0198508fd48 100644 --- a/dlls/dxdiagn/dxdiag_main.c +++ b/dlls/dxdiagn/dxdiag_main.c @@ -23,13 +23,13 @@
#include <stdarg.h>
+#include "initguid.h" #include "windef.h" #include "winbase.h" #include "objbase.h" #include "oleauto.h" #include "oleidl.h" #include "rpcproxy.h" -#include "initguid.h" #include "dxdiag_private.h" #include "wine/debug.h"
diff --git a/dlls/dxdiagn/dxdiag_private.h b/dlls/dxdiagn/dxdiag_private.h index 5f4b7c28fd0..5c5f51e7bb5 100644 --- a/dlls/dxdiagn/dxdiag_private.h +++ b/dlls/dxdiagn/dxdiag_private.h @@ -23,10 +23,6 @@
#include <stdarg.h>
-#include "windef.h" -#include "winbase.h" -#include "wingdi.h" - #include "wine/list.h" #include "dxdiag.h" #include "resource.h" diff --git a/dlls/dxdiagn/provider.c b/dlls/dxdiagn/provider.c index 05fe76849a2..7c8dfaf5c98 100644 --- a/dlls/dxdiagn/provider.c +++ b/dlls/dxdiagn/provider.c @@ -31,6 +31,7 @@ #include "d3d9.h" #include "strmif.h" #include "initguid.h" +#include "mmdeviceapi.h" #include "wine/fil_data.h" #include "psapi.h" #include "wbemcli.h" @@ -1242,6 +1243,7 @@ static HRESULT build_displaydevices_tree(IDxDiagContainerImpl_Container *node) struct enum_context { IDxDiagContainerImpl_Container *cont; + IMMDeviceCollection *devices; HRESULT hr; int index; }; @@ -1261,6 +1263,7 @@ BOOL CALLBACK dsound_enum(LPGUID guid, LPCWSTR desc, LPCWSTR module, LPVOID cont IDxDiagContainerImpl_Container *device; WCHAR buffer[256]; const WCHAR *p, *name; + UINT32 i, count;
/* the default device is enumerated twice, one time without GUID */ if (!guid) return TRUE; @@ -1296,6 +1299,62 @@ BOOL CALLBACK dsound_enum(LPGUID guid, LPCWSTR desc, LPCWSTR module, LPVOID cont if (FAILED(enum_ctx->hr)) return FALSE;
+ if (enum_ctx->devices && SUCCEEDED(IMMDeviceCollection_GetCount(enum_ctx->devices, &count))) + { + static const PROPERTYKEY devicepath_key = + { + {0xb3f8fa53, 0x0004, 0x438e, {0x90, 0x03, 0x51, 0xa4, 0x6e, 0x13, 0x9b, 0xfc}}, 2 + }; + IPropertyStore *ps; + WCHAR *start, *end; + IMMDevice *mmdev; + PROPVARIANT pv; + HRESULT hr; + + for (i = 0; i < count; ++i) + { + mmdev = NULL; + ps = NULL; + hr = IMMDeviceCollection_Item(enum_ctx->devices, i, &mmdev);; + if (SUCCEEDED(hr)) + hr = IMMDevice_OpenPropertyStore(mmdev, STGM_READ, &ps); + PropVariantInit(&pv); + if (SUCCEEDED(hr)) + hr = IPropertyStore_GetValue(ps, (const PROPERTYKEY*)&PKEY_AudioEndpoint_GUID, &pv); + if (SUCCEEDED(hr)) + { + StringFromGUID2(guid, buffer, ARRAY_SIZE(buffer)); + hr = pv.vt == VT_LPWSTR && !wcsicmp(buffer, pv.pwszVal) ? S_OK : E_FAIL; + PropVariantClear(&pv); + } + PropVariantInit(&pv); + if (SUCCEEDED(hr)) + hr = IPropertyStore_GetValue(ps, &devicepath_key, &pv); + if (SUCCEEDED(hr) && pv.vt == VT_LPWSTR) + { + if ((start = wcsstr(pv.pwszVal, L"}."))) + start += 2; + else + start = pv.pwszVal; + if (wcsnicmp(start, L"ROOT", 4) && (end = wcschr(start, '\')) && (end = wcschr(end + 1, '\')) + && end - start < ARRAY_SIZE(buffer)) + { + memcpy(buffer, start, (end - start) * sizeof(WCHAR)); + buffer[end - start] = 0; + start = buffer; + } + add_bstr_property(device, L"szHardwareID", start); + PropVariantClear(&pv); + } + if (ps) + IPropertyStore_Release(ps); + if (mmdev) + IMMDevice_Release(mmdev); + if (SUCCEEDED(hr)) + break; + } + } + enum_ctx->index++; return TRUE; } @@ -1304,6 +1363,7 @@ static HRESULT build_directsound_tree(IDxDiagContainerImpl_Container *node) { struct enum_context enum_ctx; IDxDiagContainerImpl_Container *cont; + IMMDeviceEnumerator *mmdevenum;
cont = allocate_information_node(L"DxDiag_SoundDevices"); if (!cont) @@ -1315,7 +1375,20 @@ static HRESULT build_directsound_tree(IDxDiagContainerImpl_Container *node) enum_ctx.hr = S_OK; enum_ctx.index = 0;
+ enum_ctx.devices = NULL; + if (SUCCEEDED(CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, + (void **)&mmdevenum))) + { + IMMDeviceEnumerator_EnumAudioEndpoints(mmdevenum, eAll, DEVICE_STATE_ACTIVE, &enum_ctx.devices); + IMMDeviceEnumerator_Release(mmdevenum); + } + DirectSoundEnumerateW(dsound_enum, &enum_ctx); + if (enum_ctx.devices) + { + IMMDeviceCollection_Release(enum_ctx.devices); + enum_ctx.devices = NULL; + } if (FAILED(enum_ctx.hr)) return enum_ctx.hr;
diff --git a/dlls/dxdiagn/tests/container.c b/dlls/dxdiagn/tests/container.c index 146c83070d8..c511b9da672 100644 --- a/dlls/dxdiagn/tests/container.c +++ b/dlls/dxdiagn/tests/container.c @@ -945,6 +945,7 @@ static void test_DxDiag_SoundDevices(void) {L"szGuidDeviceID", VT_BSTR}, {L"szDriverName", VT_BSTR}, {L"szDriverPath", VT_BSTR}, + {L"szHardwareID", VT_BSTR}, };
IDxDiagContainer *sound_cont = NULL;
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=147155
Your paranoid android.
=== debian11b (64 bit WoW report) ===
user32: input.c:4305: Test succeeded inside todo block: button_down_hwnd_todo 1: got MSG_TEST_WIN hwnd 0000000000CD00D6, msg WM_LBUTTONDOWN, wparam 0x1, lparam 0x320032