From: Paul Gofman pgofman@codeweavers.com
--- dlls/user32/tests/Makefile.in | 2 +- dlls/user32/tests/monitor.c | 63 +++++++++++++++++++++++++++++++++-- dlls/win32u/sysparams.c | 27 +++++++++++++-- 3 files changed, 86 insertions(+), 6 deletions(-)
diff --git a/dlls/user32/tests/Makefile.in b/dlls/user32/tests/Makefile.in index 344a3b66d2b..33c7f13f12d 100644 --- a/dlls/user32/tests/Makefile.in +++ b/dlls/user32/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = user32.dll -IMPORTS = user32 gdi32 advapi32 hid imm32 +IMPORTS = user32 gdi32 advapi32 hid imm32 setupapi
C_SRCS = \ broadcast.c \ diff --git a/dlls/user32/tests/monitor.c b/dlls/user32/tests/monitor.c index 4b774037508..1dff85b9621 100644 --- a/dlls/user32/tests/monitor.c +++ b/dlls/user32/tests/monitor.c @@ -23,6 +23,8 @@ #include "ntstatus.h" #define WIN32_NO_STATUS
+#include "initguid.h" + #include "wine/test.h" #include "winbase.h" #include "wingdi.h" @@ -30,9 +32,14 @@ #include "winreg.h" #include "winternl.h" #include "ddk/d3dkmthk.h" +#include "setupapi.h" +#include "ntddvdeo.h" #include "wine/heap.h" #include <stdio.h>
+DEFINE_DEVPROPKEY(DEVPROPKEY_MONITOR_GPU_LUID, 0xca085853, 0x16ce, 0x48aa, 0xb1, 0x14, 0xde, 0x9c, 0x72, 0x33, 0x42, 0x23, 1); +DEFINE_DEVPROPKEY(DEVPROPKEY_MONITOR_OUTPUT_ID, 0xca085853, 0x16ce, 0x48aa, 0xb1, 0x14, 0xde, 0x9c, 0x72, 0x33, 0x42, 0x23, 2); + static LONG (WINAPI *pGetDisplayConfigBufferSizes)(UINT32,UINT32*,UINT32*); static BOOL (WINAPI *pGetDpiForMonitorInternal)(HMONITOR,UINT,UINT*,UINT*); static LONG (WINAPI *pQueryDisplayConfig)(UINT32,UINT32*,DISPLAYCONFIG_PATH_INFO*,UINT32*, @@ -1624,6 +1631,58 @@ static void test_EnumDisplayMonitors(void) ok(ret, "CloseWindowStation failed, error %#lx.\n", GetLastError()); }
+static void check_device_path(const WCHAR *device_path, const LUID *adapter_id, DWORD id) +{ + BYTE iface_detail_buffer[sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) + 256 * sizeof(WCHAR)]; + SP_DEVINFO_DATA device_data = {sizeof(device_data)}; + SP_DEVICE_INTERFACE_DATA iface = {sizeof(iface)}; + SP_DEVICE_INTERFACE_DETAIL_DATA_W *iface_data; + BOOL ret, found = FALSE; + DEVPROPTYPE type; + DWORD output_id; + unsigned int i; + HDEVINFO set; + LUID luid; + + iface_data = (SP_DEVICE_INTERFACE_DETAIL_DATA_W *)iface_detail_buffer; + iface_data->cbSize = sizeof(*iface_data); + + set = SetupDiGetClassDevsW(&GUID_DEVINTERFACE_MONITOR, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); + ok(set != INVALID_HANDLE_VALUE, "Got error %lu.\n", GetLastError()); + + i = 0; + while (SetupDiEnumDeviceInterfaces(set, NULL, &GUID_DEVINTERFACE_MONITOR, i, &iface)) + { + ret = SetupDiGetDeviceInterfaceDetailW(set, &iface, iface_data, + sizeof(iface_detail_buffer), NULL, &device_data); + ok(ret, "Got unexpected ret %d, GetLastError() %lu.\n", ret, GetLastError()); + + ret = SetupDiGetDevicePropertyW(set, &device_data, &DEVPROPKEY_MONITOR_GPU_LUID, &type, + (BYTE *)&luid, sizeof(luid), NULL, 0); + ok(ret || broken(GetLastError() == ERROR_NOT_FOUND) /* before Win10 1809 */, + "Got error %lu.\n", GetLastError()); + if (!ret) + { + win_skip("DEVPROPKEY_MONITOR_GPU_LUID is not found, skipping device path check.\n"); + SetupDiDestroyDeviceInfoList(set); + return; + } + ret = SetupDiGetDevicePropertyW(set, &device_data, &DEVPROPKEY_MONITOR_OUTPUT_ID, + &type, (BYTE *)&output_id, sizeof(output_id), NULL, 0); + ok(ret, "Got error %lu.\n", GetLastError()); + + if (output_id == id && RtlEqualLuid(&luid, adapter_id) && !wcsicmp(device_path, iface_data->DevicePath)) + { + found = TRUE; + break; + } + ++i; + } + ok(found, "device_path %s not found, luid %04lx:%04lx.\n", debugstr_w(device_path), adapter_id->HighPart, + adapter_id->LowPart); + SetupDiDestroyDeviceInfoList(set); +} + static void test_QueryDisplayConfig_result(UINT32 flags, UINT32 paths, const DISPLAYCONFIG_PATH_INFO *pi, UINT32 modes, const DISPLAYCONFIG_MODE_INFO *mi) { @@ -1654,7 +1713,6 @@ static void test_QueryDisplayConfig_result(UINT32 flags, ret = pDisplayConfigGetDeviceInfo(&source_name.header); ok(ret == ERROR_GEN_FAILURE, "Expected GEN_FAILURE, got %ld\n", ret);
- todo_wine { target_name.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME; target_name.header.size = sizeof(target_name); target_name.header.adapterId = pi[i].targetInfo.adapterId; @@ -1662,8 +1720,7 @@ static void test_QueryDisplayConfig_result(UINT32 flags, target_name.monitorDevicePath[0] = '\0'; ret = pDisplayConfigGetDeviceInfo(&target_name.header); ok(!ret, "Expected 0, got %ld\n", ret); - ok(target_name.monitorDevicePath[0] != '\0', "Expected monitor device path, got empty string\n"); - } + check_device_path(target_name.monitorDevicePath, &target_name.header.adapterId, target_name.header.id);
todo_wine { preferred_mode.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_PREFERRED_MODE; diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index d490b54a3f4..da1b3bbcd2e 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -5546,13 +5546,36 @@ NTSTATUS WINAPI NtUserDisplayConfigGetDeviceInfo( DISPLAYCONFIG_DEVICE_INFO_HEAD case DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME: { DISPLAYCONFIG_TARGET_DEVICE_NAME *target_name = (DISPLAYCONFIG_TARGET_DEVICE_NAME *)packet; + char buffer[ARRAY_SIZE(target_name->monitorFriendlyDeviceName)]; + struct monitor *monitor;
- FIXME( "DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME stub.\n" ); + TRACE( "DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME.\n" );
if (packet->size < sizeof(*target_name)) return STATUS_INVALID_PARAMETER;
- return STATUS_NOT_SUPPORTED; + if (!lock_display_devices()) return STATUS_UNSUCCESSFUL; + + memset( &target_name->flags, 0, sizeof(*target_name) - offsetof(DISPLAYCONFIG_TARGET_DEVICE_NAME, flags) ); + + LIST_FOR_EACH_ENTRY(monitor, &monitors, struct monitor, entry) + { + if (target_name->header.id != monitor->output_id) continue; + if (memcmp( &target_name->header.adapterId, &monitor->adapter->gpu_luid, + sizeof(monitor->adapter->gpu_luid) )) + continue; + + target_name->outputTechnology = DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INTERNAL; + /* FIXME: get real monitor name. */ + snprintf( buffer, ARRAY_SIZE(buffer), "Display%u", monitor->output_id + 1 ); + asciiz_to_unicode( target_name->monitorFriendlyDeviceName, buffer ); + lstrcpyW( target_name->monitorDevicePath, monitor->dev.interface_name ); + ret = STATUS_SUCCESS; + break; + } + + unlock_display_devices(); + return ret; } case DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_PREFERRED_MODE: {