Signed-off-by: Rémi Bernon rbernon@codeweavers.com ---
A refresh and continuation of the null graphics driver improvements, as I've finally been able to make all monitor tests (and thus all user32 tests) to pass with it too, without duplicating the driver adapter and monitor initialization code and initializing the device cache with some defaults instead.
dlls/user32/tests/monitor.c | 230 ++++++++++++++++-------------------- 1 file changed, 103 insertions(+), 127 deletions(-)
diff --git a/dlls/user32/tests/monitor.c b/dlls/user32/tests/monitor.c index bd348576726..131721d7ec1 100644 --- a/dlls/user32/tests/monitor.c +++ b/dlls/user32/tests/monitor.c @@ -105,148 +105,124 @@ static int get_bitmap_stride(int width, int bpp) return ((width * bpp + 15) >> 3) & ~1; }
-static int adapter_count = 0; -static int monitor_count = 0; - -static void test_enumdisplaydevices_adapter(int index, const DISPLAY_DEVICEA *device, DWORD flags) +static void test_EnumDisplayDevices(void) { - char buffer[128]; - int number; - int vendor_id; - int device_id; - int subsys_id; - int revision_id; + DISPLAY_DEVICEW dd = {.cb = sizeof(DISPLAY_DEVICEW)}, adapter = dd, adapter_iface = dd, monitor = dd, monitor_iface = dd; + DWORD number, monitor_num, adapter_index, monitor_index, adapter_count = 0, monitor_count = 0; + WCHAR buffer[MAX_PATH], monitor_id[MAX_PATH]; + BOOL ret; HDC hdc;
- adapter_count++; - - /* DeviceName */ - ok(sscanf(device->DeviceName, "\\.\DISPLAY%d", &number) == 1, "#%d: wrong DeviceName %s\n", index, - device->DeviceName); - - /* DeviceKey */ - /* \Device\Video? value in HLKM\HARDWARE\DEVICEMAP\VIDEO are not necessarily in order with adapter index. - * Check format only */ - ok(sscanf(device->DeviceKey, "\Registry\Machine\System\CurrentControlSet\Control\Video\%[^\]\%04d", buffer, &number) == 2, - "#%d: wrong DeviceKey %s\n", index, device->DeviceKey); - - /* DeviceString */ - ok(broken(!*device->DeviceString) || /* XP on Testbot will return an empty string, whereas XP on real machine doesn't. Probably a bug in virtual adapter driver */ - *device->DeviceString, "#%d: expect DeviceString not empty\n", index); + /* Doesn't accept \.\DISPLAY */ + dd.cb = sizeof(dd); + ret = EnumDisplayDevicesW( L"\\.\DISPLAY", 0, &dd, 0 ); + ok( !ret, "EnumDisplayDevicesW succeeded\n" );
- /* StateFlags */ - if (device->StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) + adapter_index = -1; + while (EnumDisplayDevicesW( NULL, ++adapter_index, &adapter, 0 )) { - /* Test creating DC */ - hdc = CreateDCA(device->DeviceName, NULL, NULL, NULL); - ok(hdc != NULL, "#%d: failed to CreateDC("%s") err=%d\n", index, device->DeviceName, GetLastError()); - DeleteDC(hdc); - } + winetest_push_context( "adapter %u", adapter_index );
- /* DeviceID */ - /* DeviceID should equal to the first string of HardwareID value data in PCI GPU instance. You can verify this - * by changing the data and rerun EnumDisplayDevices. But it's difficult to find corresponding PCI device on - * userland. So here we check the expected format instead. */ - if (flags & EDD_GET_DEVICE_INTERFACE_NAME) - ok(strlen(device->DeviceID) == 0 || /* vista+ */ - sscanf(device->DeviceID, "PCI\VEN_%04X&DEV_%04X&SUBSYS_%08X&REV_%02X", - &vendor_id, &device_id, &subsys_id, &revision_id) == 4, /* XP/2003 ignores EDD_GET_DEVICE_INTERFACE_NAME */ - "#%d: got %s\n", index, device->DeviceID); - else - { - ok(broken(strlen(device->DeviceID) == 0) || /* XP on Testbot returns an empty string, whereas real machine doesn't */ - sscanf(device->DeviceID, "PCI\VEN_%04X&DEV_%04X&SUBSYS_%08X&REV_%02X", &vendor_id, &device_id, &subsys_id, - &revision_id) == 4, "#%d: wrong DeviceID %s\n", index, device->DeviceID); - } -} + ret = EnumDisplayDevicesW( NULL, adapter_index, &adapter_iface, EDD_GET_DEVICE_INTERFACE_NAME ); + ok( ret, "EnumDisplayDevicesW failed, error %u\n", GetLastError() );
-static void test_enumdisplaydevices_monitor(int monitor_index, const char *adapter_name, - DISPLAY_DEVICEA *device, DWORD flags) -{ - static const char device_key_prefix[] = "\Registry\Machine\System\CurrentControlSet\Control\Class" - "\{4d36e96e-e325-11ce-bfc1-08002be10318}\"; - char monitor_name[32]; - char buffer[128]; - int number; - - monitor_count++; - - /* DeviceName */ - lstrcpyA(monitor_name, adapter_name); - sprintf(monitor_name + strlen(monitor_name), "\Monitor%d", monitor_index); - ok(!strcmp(monitor_name, device->DeviceName), "#%d: expect %s, got %s\n", monitor_index, monitor_name, device->DeviceName); - - /* DeviceString */ - ok(*device->DeviceString, "#%d: expect DeviceString not empty\n", monitor_index); - - /* StateFlags */ - ok(device->StateFlags <= (DISPLAY_DEVICE_ATTACHED | DISPLAY_DEVICE_ACTIVE), - "#%d wrong state %#x\n", monitor_index, device->StateFlags); - - /* DeviceID */ - CharLowerA(device->DeviceID); - if (flags & EDD_GET_DEVICE_INTERFACE_NAME) - { /* HKLM\SYSTEM\CurrentControlSet\Enum\DISPLAY[monitor name][instance id] GUID_DEVINTERFACE_MONITOR - * ^ ^ ^ - * Expect format \?\DISPLAY#[monitor name]#[instance id]#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7} */ - ok(strlen(device->DeviceID) == 0 || /* vista ~ win7 */ - sscanf(device->DeviceID, "\\?\display#%[^#]#%[^#]#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}", buffer, buffer) == 2 || /* win8+ */ - sscanf(device->DeviceID, "monitor\%[^\]\{4d36e96e-e325-11ce-bfc1-08002be10318}\%04d", buffer, &number) == 2, /* XP/2003 ignores EDD_GET_DEVICE_INTERFACE_NAME */ - "#%d: wrong DeviceID : %s\n", monitor_index, device->DeviceID); - } - else - { - /* Expect HarewareID value data + Driver value data in HKLM\SYSTEM\CurrentControlSet\Enum\DISPLAY[monitor name]{instance} */ - /* But we don't know which monitor instance this belongs to, so check format instead */ - ok(sscanf(device->DeviceID, "monitor\%[^\]\{4d36e96e-e325-11ce-bfc1-08002be10318}\%04d", buffer, &number) == 2, - "#%d: wrong DeviceID : %s\n", monitor_index, device->DeviceID); - } + ok( !wcscmp( adapter.DeviceName, adapter_iface.DeviceName ), "got DeviceName %s expected %s\n", + debugstr_w(adapter.DeviceName), debugstr_w(adapter_iface.DeviceName) ); + ok( !wcscmp( adapter.DeviceString, adapter_iface.DeviceString ), "got DeviceString %s expected %s\n", + debugstr_w(adapter.DeviceString), debugstr_w(adapter_iface.DeviceString) ); + ok( adapter.StateFlags == adapter_iface.StateFlags, "got StateFlags %#x expected %#x\n", + adapter.StateFlags, adapter_iface.StateFlags ); + ok( !wcscmp( adapter.DeviceKey, adapter_iface.DeviceKey ), "got DeviceKey %s expected %s\n", + debugstr_w(adapter.DeviceKey), debugstr_w(adapter_iface.DeviceKey) );
- /* DeviceKey */ - lstrcpynA(buffer, device->DeviceKey, sizeof(device_key_prefix)); - ok(!lstrcmpiA(buffer, device_key_prefix), "#%d: wrong DeviceKey : %s\n", monitor_index, device->DeviceKey); - ok(sscanf(device->DeviceKey + sizeof(device_key_prefix) - 1, "%04d", &number) == 1, - "#%d wrong DeviceKey : %s\n", monitor_index, device->DeviceKey); -} - -static void test_enumdisplaydevices(void) -{ - static const DWORD flags[] = {0, EDD_GET_DEVICE_INTERFACE_NAME}; - DISPLAY_DEVICEA dd; - char adapter_name[32]; - int number; - int flag_index; - int adapter_index; - int monitor_index; - BOOL ret; + if (swscanf( adapter.DeviceName, L"\\.\DISPLAYV%u", &number ) == 1) + { + skip( "Skipping software devices %s %s\n", debugstr_w(adapter.DeviceName), debugstr_w(adapter.DeviceString) ); + winetest_pop_context(); + continue; + }
- /* Doesn't accept \.\DISPLAY */ - dd.cb = sizeof(dd); - ret = EnumDisplayDevicesA("\\.\DISPLAY", 0, &dd, 0); - ok(!ret, "Expect failure\n"); + swprintf( buffer, MAX_PATH, L"\\.\DISPLAY%u", adapter_count + 1 ); + ok( !wcscmp( adapter.DeviceName, buffer ), "got DeviceName %s expected %s\n", + debugstr_w(adapter.DeviceName), debugstr_w(buffer) );
- /* Enumeration */ - for (flag_index = 0; flag_index < ARRAY_SIZE(flags); flag_index++) - for (adapter_index = 0; EnumDisplayDevicesA(NULL, adapter_index, &dd, flags[flag_index]); adapter_index++) + ok( *adapter.DeviceString, "got empty DeviceString\n" ); + if (adapter.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) { - lstrcpyA(adapter_name, dd.DeviceName); - - if (sscanf(adapter_name, "\\.\DISPLAYV%d", &number) == 1) - { - skip("Skipping software devices %s:%s\n", adapter_name, dd.DeviceString); - continue; - } + /* Test creating DC */ + hdc = CreateDCW( adapter.DeviceName, NULL, NULL, NULL ); + ok( hdc != 0, "CreateDCW failed error %u\n", GetLastError() ); + DeleteDC( hdc ); + }
- test_enumdisplaydevices_adapter(adapter_index, &dd, flags[flag_index]); + ok( swscanf( adapter.DeviceKey, L"\Registry\Machine\System\CurrentControlSet\Control\" + "Video\%[^\]\%04u", buffer, &number ) == 2, + "got DeviceKey %s\n", debugstr_w(adapter.DeviceKey) );
- for (monitor_index = 0; EnumDisplayDevicesA(adapter_name, monitor_index, &dd, flags[flag_index]); - monitor_index++) - test_enumdisplaydevices_monitor(monitor_index, adapter_name, &dd, flags[flag_index]); + /* DeviceID should equal to the first string of HardwareID value data in PCI GPU instance. You can verify this + * by changing the data and rerun EnumDisplayDevices. But it's difficult to find corresponding PCI device on + * userland. So here we check the expected format instead. */ + todo_wine + ok( broken( !*adapter_iface.DeviceID ) || + swscanf( adapter_iface.DeviceID, L"PCI\VEN_%04X&DEV_%04X&SUBSYS_%08X&REV_%02X", + &number, &number, &number, &number ) == 4, + "got interface DeviceID %s\n", debugstr_w(adapter_iface.DeviceID) ); + ok( swscanf( adapter.DeviceID, L"PCI\VEN_%04X&DEV_%04X&SUBSYS_%08X&REV_%02X", &number, + &number, &number, &number ) == 4, + "got interface DeviceID %s\n", debugstr_w(adapter.DeviceID) ); + + monitor_index = -1; + while (EnumDisplayDevicesW( adapter.DeviceName, ++monitor_index, &monitor, 0 )) + { + winetest_push_context( "monitor %u", monitor_index ); + + ret = EnumDisplayDevicesW( adapter.DeviceName, monitor_index, &monitor_iface, EDD_GET_DEVICE_INTERFACE_NAME ); + ok( ret, "EnumDisplayDevicesW failed, error %u\n", GetLastError() ); + + ok( !wcscmp( monitor.DeviceName, monitor_iface.DeviceName ), "got DeviceName %s expected %s\n", + debugstr_w(monitor.DeviceName), debugstr_w(monitor_iface.DeviceName) ); + ok( !wcscmp( monitor.DeviceString, monitor_iface.DeviceString ), "got DeviceString %s expected %s\n", + debugstr_w(monitor.DeviceString), debugstr_w(monitor_iface.DeviceString) ); + ok( monitor.StateFlags == monitor_iface.StateFlags, "got StateFlags %#x expected %#x\n", + monitor.StateFlags, monitor_iface.StateFlags ); + ok( !wcscmp( monitor.DeviceKey, monitor_iface.DeviceKey ), "got DeviceKey %s expected %s\n", + debugstr_w(monitor.DeviceKey), debugstr_w(monitor_iface.DeviceKey) ); + + swprintf( buffer, MAX_PATH, L"%s\Monitor%u", adapter.DeviceName, monitor_index ); + ok( !wcscmp( monitor.DeviceName, buffer ), "got DeviceName %s expected %s\n", + debugstr_w(monitor.DeviceName), debugstr_w(buffer) ); + + ok( *monitor.DeviceString, "got empty DeviceString\n" ); + ok( !(monitor.StateFlags & ~(DISPLAY_DEVICE_ATTACHED | DISPLAY_DEVICE_ACTIVE)), + "got unexpected StateFlags %#x\n", monitor.StateFlags ); + + CharLowerW( monitor.DeviceKey ); + ok( swscanf( monitor.DeviceKey, L"\registry\machine\system\currentcontrolset\control\" + "class\{4d36e96e-e325-11ce-bfc1-08002be10318}\%04u", &monitor_num ) == 1, + "got DeviceKey %s\n", debugstr_w(monitor.DeviceKey) ); + + ok( broken( !*monitor_iface.DeviceID ) || + swscanf( monitor_iface.DeviceID, L"\\?\DISPLAY#%[^#]#%[^#]#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}", + monitor_id, buffer ) == 2, + "got interface DeviceID %s\n", debugstr_w(monitor_iface.DeviceID) ); + if (!*monitor_iface.DeviceID) wcscpy( monitor_id, L"default_monitor" ); + + swprintf( buffer, MAX_PATH, L"monitor\%s\{4d36e96e-e325-11ce-bfc1-08002be10318}\%04u", + monitor_id, monitor_num ); + ok( !wcsicmp( monitor.DeviceID, buffer ), "got DeviceID %s expected %s\n", + debugstr_w(monitor.DeviceID), debugstr_w(buffer) ); + + winetest_pop_context(); }
- ok(adapter_count > 0, "Expect at least one adapter found\n"); + adapter_count += 1; + monitor_count += monitor_index; + winetest_pop_context(); + } + + ok( adapter_index > 0, "Expect at least one adapter found\n" ); /* XP on Testbot doesn't report a monitor, whereas XP on real machine does */ - ok(broken(monitor_count == 0) || monitor_count > 0, "Expect at least one monitor found\n"); + ok( broken( monitor_count == 0 ) || monitor_count > 0, "Expect at least one monitor found\n" ); }
struct vid_mode @@ -2356,7 +2332,7 @@ static void test_display_dc(void) START_TEST(monitor) { init_function_pointers(); - test_enumdisplaydevices(); + test_EnumDisplayDevices(); test_ChangeDisplaySettingsEx(); test_DisplayConfigSetDeviceInfo(); test_EnumDisplayMonitors();
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/user32/tests/monitor.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+)
diff --git a/dlls/user32/tests/monitor.c b/dlls/user32/tests/monitor.c index 131721d7ec1..bd89a8d9a40 100644 --- a/dlls/user32/tests/monitor.c +++ b/dlls/user32/tests/monitor.c @@ -225,6 +225,27 @@ static void test_EnumDisplayDevices(void) ok( broken( monitor_count == 0 ) || monitor_count > 0, "Expect at least one monitor found\n" ); }
+static void test_EnumDisplaySettings(void) +{ + DISPLAY_DEVICEW adapter = {.cb = sizeof(DISPLAY_DEVICEW)}; + DEVMODEW devmode = {.dmSize = sizeof(DEVMODEW)}; + BOOL ret; + + ret = EnumDisplayDevicesW( NULL, 0, &adapter, 0 ); + ok( ret, "EnumDisplayDevicesW failed, error %u\n", GetLastError() ); + + SetLastError( 0xdeadbeef ); + ret = EnumDisplaySettingsExW( adapter.DeviceName, ENUM_REGISTRY_SETTINGS, &devmode, 0 ); + ok( ret, "EnumDisplaySettingsExW failed, error %u\n", GetLastError() ); + todo_wine + ok( GetLastError() == 0xdeadbeef, "EnumDisplaySettingsExW set last error %u\n", GetLastError() ); + + SetLastError( 0xdeadbeef ); + ret = EnumDisplaySettingsExW( adapter.DeviceName, ENUM_CURRENT_SETTINGS, &devmode, 0 ); + ok( ret, "EnumDisplaySettingsExW failed, error %u\n", GetLastError() ); + ok( GetLastError() == 0xdeadbeef, "EnumDisplaySettingsExW set last error %u\n", GetLastError() ); +} + struct vid_mode { DWORD w, h, bpp, freq, fields; @@ -521,8 +542,11 @@ static void test_ChangeDisplaySettingsEx(void) dm.dmSize = sizeof(dm); dm.dmFields = DM_POSITION | DM_PELSWIDTH | DM_PELSHEIGHT; dm.dmPosition = devices[0].original_mode.dmPosition; + SetLastError(0xdeadbeef); res = ChangeDisplaySettingsExA(devices[0].name, &dm, NULL, CDS_UPDATEREGISTRY | CDS_NORESET, NULL); ok(res == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExA %s returned unexpected %d\n", devices[0].name, res); + todo_wine + ok(GetLastError() == 0xdeadbeef, "ChangeDisplaySettingsExA set last error %u\n", GetLastError()); res = ChangeDisplaySettingsExA(NULL, NULL, NULL, 0, NULL); ok(res == DISP_CHANGE_SUCCESSFUL || broken(res == DISP_CHANGE_FAILED), /* win8 TestBot */ @@ -538,8 +562,11 @@ static void test_ChangeDisplaySettingsEx(void) ok(count == old_count, "Expect monitor count %d, got %d\n", old_count, count);
/* Restore registry settings */ + SetLastError(0xdeadbeef); res = ChangeDisplaySettingsExA(devices[0].name, &devices[0].original_mode, NULL, CDS_UPDATEREGISTRY | CDS_NORESET, NULL); + todo_wine + ok(GetLastError() == 0xdeadbeef, "ChangeDisplaySettingsExA set last error %u\n", GetLastError()); ok(res == DISP_CHANGE_SUCCESSFUL || broken(res == DISP_CHANGE_BADPARAM) || /* win10 */ broken(res == DISP_CHANGE_FAILED), /* win8 TestBot */ @@ -563,8 +590,11 @@ static void test_ChangeDisplaySettingsEx(void) dm.dmSize = sizeof(dm); dm.dmFields = DM_POSITION; dm.dmPosition = devices[1].original_mode.dmPosition; + SetLastError(0xdeadbeef); res = ChangeDisplaySettingsExA(devices[1].name, &dm, NULL, CDS_UPDATEREGISTRY | CDS_NORESET, NULL); ok(res == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExA %s returned unexpected %d\n", devices[1].name, res); + todo_wine + ok(GetLastError() == 0xdeadbeef, "ChangeDisplaySettingsExA set last error %u\n", GetLastError()); res = ChangeDisplaySettingsExA(devices[1].name, NULL, NULL, 0, NULL); ok(res == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExA %s returned unexpected %d\n", devices[1].name, res);
@@ -2333,6 +2363,7 @@ START_TEST(monitor) { init_function_pointers(); test_EnumDisplayDevices(); + test_EnumDisplaySettings(); test_ChangeDisplaySettingsEx(); test_DisplayConfigSetDeviceInfo(); test_EnumDisplayMonitors();
Preventing undesired last error modification. This doesn't change the behavior with default drivers, but it will with the null driver.
This otherwise will cause spurious failures in cursoricon tests when the null driver is used.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/user32/sysparams.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/dlls/user32/sysparams.c b/dlls/user32/sysparams.c index 733acd3d3c6..6327e05517f 100644 --- a/dlls/user32/sysparams.c +++ b/dlls/user32/sysparams.c @@ -615,16 +615,23 @@ void release_display_dc( HDC hdc )
static HANDLE get_display_device_init_mutex( void ) { - HANDLE mutex = CreateMutexW( NULL, FALSE, L"display_device_init" ); + OBJECT_ATTRIBUTES attrs; + UNICODE_STRING name_str; + NTSTATUS status; + HANDLE mutex; + + RtlInitUnicodeString( &name_str, L"display_device_init" ); + InitializeObjectAttributes( &attrs, &name_str, OBJ_CASE_INSENSITIVE, 0, NULL ); + if ((status = NtCreateMutant( &mutex, MUTEX_ALL_ACCESS, &attrs, FALSE ))) return NULL;
- WaitForSingleObject( mutex, INFINITE ); + NtWaitForMultipleObjects( 1, &mutex, TRUE, TRUE, NULL ); return mutex; }
static void release_display_device_init_mutex( HANDLE mutex ) { - ReleaseMutex( mutex ); - CloseHandle( mutex ); + NtReleaseMutant( mutex, NULL ); + NtClose( mutex ); }
/* Wait until graphics driver is loaded by explorer */
And only keep the interface name internally.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/user32/sysparams.c | 48 +++++++++++++++---------------------- dlls/user32/tests/monitor.c | 1 - 2 files changed, 19 insertions(+), 30 deletions(-)
diff --git a/dlls/user32/sysparams.c b/dlls/user32/sysparams.c index 6327e05517f..5842c0ae0c0 100644 --- a/dlls/user32/sysparams.c +++ b/dlls/user32/sysparams.c @@ -115,8 +115,7 @@ struct display_device WCHAR device_name[32]; /* as DeviceName in DISPLAY_DEVICEW */ WCHAR device_string[128]; /* as DeviceString in DISPLAY_DEVICEW */ DWORD state_flags; /* as StateFlags in DISPLAY_DEVICEW */ - WCHAR device_id[128]; /* as DeviceID in DISPLAY_DEVICEW when EDD_GET_DEVICE_INTERFACE_NAME is not set */ - WCHAR interface_name[128]; /* as DeviceID in DISPLAY_DEVICEW when EDD_GET_DEVICE_INTERFACE_NAME is set */ + WCHAR device_id[128]; /* as DeviceID in DISPLAY_DEVICEW */ WCHAR device_key[128]; /* as DeviceKey in DISPLAY_DEVICEW */ };
@@ -4223,6 +4222,7 @@ BOOL WINAPI EnumDisplayDevicesA( LPCSTR device, DWORD index, DISPLAY_DEVICEA *in BOOL WINAPI EnumDisplayDevicesW( LPCWSTR device, DWORD index, DISPLAY_DEVICEW *info, DWORD flags ) { struct display_device *adapter, *monitor, *found = NULL; + WCHAR buffer[MAX_PATH]; DWORD device_idx = 0;
TRACE("%s %u %p %#x\n", debugstr_w( device ), index, info, flags); @@ -4282,7 +4282,16 @@ BOOL WINAPI EnumDisplayDevicesW( LPCWSTR device, DWORD index, DISPLAY_DEVICEW *i if (info->cb >= offsetof(DISPLAY_DEVICEW, StateFlags) + sizeof(info->StateFlags)) info->StateFlags = found->state_flags; if (info->cb >= offsetof(DISPLAY_DEVICEW, DeviceID) + sizeof(info->DeviceID)) - lstrcpyW( info->DeviceID, (flags & EDD_GET_DEVICE_INTERFACE_NAME) ? found->interface_name : found->device_id ); + { + if (!device || (flags & EDD_GET_DEVICE_INTERFACE_NAME)) + lstrcpyW( info->DeviceID, found->device_id ); + else + { + swscanf( found->device_id, L"\\?\DISPLAY#%[^#]#%*[^#]#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}", buffer ); + swprintf( info->DeviceID, ARRAY_SIZE(info->DeviceID), L"MONITOR\%s\{4d36e96e-e325-11ce-bfc1-08002be10318}\%s", + buffer, wcsrchr( found->device_key, '\' ) + 1 ); + } + } if (info->cb >= offsetof(DISPLAY_DEVICEW, DeviceKey) + sizeof(info->DeviceKey)) lstrcpyW( info->DeviceKey, found->device_key ); LeaveCriticalSection( &display_section ); @@ -4333,9 +4342,6 @@ static BOOL enum_display_device( WCHAR *device, DWORD index, struct display_devi &info->state_flags, &size )) goto done;
- /* Interface name */ - info->interface_name[0] = 0; - /* DeviceID */ size = sizeof(bufferW); if (RegGetValueW( HKEY_CURRENT_CONFIG, key_nameW, L"GPUID", RRF_RT_REG_SZ | RRF_ZEROONFAILURE, NULL, @@ -4398,29 +4404,15 @@ static BOOL enum_display_device( WCHAR *device, DWORD index, struct display_devi lstrcatW( info->device_key, bufferW );
/* Interface name */ - lstrcpyW( info->interface_name, L"\\?\" ); - lstrcatW( info->interface_name, instanceW ); - lstrcatW( info->interface_name, L"#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}" ); + lstrcpyW( info->device_id, L"\\?\" ); + lstrcatW( info->device_id, instanceW ); + lstrcatW( info->device_id, L"#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}" ); /* Replace '\' with '#' after prefix */ - for (next_charW = info->interface_name + lstrlenW( L"\\?\" ); *next_charW; next_charW++) + for (next_charW = info->device_id + lstrlenW( L"\\?\" ); *next_charW; next_charW++) { if (*next_charW == '\') *next_charW = '#'; } - - /* DeviceID */ - if (!SetupDiGetDeviceRegistryPropertyW( set, &device_data, SPDRP_HARDWAREID, NULL, (BYTE *)bufferW, - sizeof(bufferW), NULL )) - goto done; - - lstrcpyW( info->device_id, bufferW ); - lstrcatW( info->device_id, L"\" ); - - if (!SetupDiGetDeviceRegistryPropertyW( set, &device_data, SPDRP_DRIVER, NULL, (BYTE *)bufferW, - sizeof(bufferW), NULL )) - goto done; - - lstrcatW( info->device_id, bufferW ); }
ret = TRUE; @@ -4447,9 +4439,8 @@ done: lstrcpyW( info->device_name, L"\\.\DISPLAY1" ); lstrcpyW( info->device_string, L"Wine Adapter" ); info->state_flags = DISPLAY_DEVICE_ATTACHED_TO_DESKTOP | DISPLAY_DEVICE_PRIMARY_DEVICE | DISPLAY_DEVICE_VGA_COMPATIBLE; - info->interface_name[0] = 0; lstrcpyW( info->device_id, L"PCI\VEN_0000&DEV_0000&SUBSYS_00000000&REV_00" ); - info->device_key[0] = 0; + lstrcpyW( info->device_key, L"\Registry\Machine\System\CurrentControlSet\Control\Video\{71c91c84-1064-400f-a994-95e3ff2716d6}\0000" ); } /* Monitor */ else @@ -4460,9 +4451,8 @@ done: lstrcpyW( info->device_name, L"\\.\DISPLAY1\Monitor0" ); lstrcpyW( info->device_string, L"Generic Non-PnP Monitor" ); info->state_flags = DISPLAY_DEVICE_ACTIVE | DISPLAY_DEVICE_ATTACHED; - lstrcpyW( info->interface_name, L"\\?\DISPLAY#Default_Monitor#4&17f0ff54&0&UID0#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}" ); - lstrcpyW( info->device_id, L"MONITOR\Default_Monitor\{4d36e96e-e325-11ce-bfc1-08002be10318}\0000" ); - info->device_key[0] = 0; + lstrcpyW( info->device_id, L"\\?\DISPLAY#Default_Monitor#4&17f0ff54&0&UID0#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}" ); + lstrcpyW( info->device_key, L"\Registry\Machine\System\CurrentControlSet\Control\Class\{4d36e96e-e325-11ce-bfc1-08002be10318}\0000" ); }
return TRUE; diff --git a/dlls/user32/tests/monitor.c b/dlls/user32/tests/monitor.c index bd89a8d9a40..7490ed2923f 100644 --- a/dlls/user32/tests/monitor.c +++ b/dlls/user32/tests/monitor.c @@ -162,7 +162,6 @@ static void test_EnumDisplayDevices(void) /* DeviceID should equal to the first string of HardwareID value data in PCI GPU instance. You can verify this * by changing the data and rerun EnumDisplayDevices. But it's difficult to find corresponding PCI device on * userland. So here we check the expected format instead. */ - todo_wine ok( broken( !*adapter_iface.DeviceID ) || swscanf( adapter_iface.DeviceID, L"PCI\VEN_%04X&DEV_%04X&SUBSYS_%08X&REV_%02X", &number, &number, &number, &number ) == 4,
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/user32/sysparams.c | 181 +++++++++++++++------------------------- 1 file changed, 67 insertions(+), 114 deletions(-)
diff --git a/dlls/user32/sysparams.c b/dlls/user32/sysparams.c index 5842c0ae0c0..2266e88b710 100644 --- a/dlls/user32/sysparams.c +++ b/dlls/user32/sysparams.c @@ -108,18 +108,9 @@ DEFINE_DEVPROPKEY(WINE_DEVPROPKEY_MONITOR_ADAPTERNAME, 0x233a9ef3, 0xafc4, 0x4ab #define NULLDRV_DEFAULT_HMONITOR ((HMONITOR)(UINT_PTR)(0x10000 + 1))
/* Cached display device information */ -struct display_device -{ - struct list entry; /* Device list entry */ - struct list children; /* Child device list entry. For adapters, this is monitor list. For monitors, this is unused. */ - WCHAR device_name[32]; /* as DeviceName in DISPLAY_DEVICEW */ - WCHAR device_string[128]; /* as DeviceString in DISPLAY_DEVICEW */ - DWORD state_flags; /* as StateFlags in DISPLAY_DEVICEW */ - WCHAR device_id[128]; /* as DeviceID in DISPLAY_DEVICEW */ - WCHAR device_key[128]; /* as DeviceKey in DISPLAY_DEVICEW */ -}; +static DISPLAY_DEVICEW display_devices[512]; +static DISPLAY_DEVICEW *display_devices_end = display_devices;
-static struct list adapters = LIST_INIT(adapters); static FILETIME last_query_display_time; static CRITICAL_SECTION display_section; static CRITICAL_SECTION_DEBUG display_critsect_debug = @@ -130,7 +121,7 @@ static CRITICAL_SECTION_DEBUG display_critsect_debug = }; static CRITICAL_SECTION display_section = { &display_critsect_debug, -1, 0, 0, 0, 0 };
-static BOOL enum_display_device( WCHAR *device, DWORD index, struct display_device *info ); +static BOOL enum_display_device( WCHAR *device, DWORD index, DISPLAY_DEVICEW *info );
/* Cached monitor information */ static MONITORINFOEXW *monitors; @@ -3826,9 +3817,8 @@ HMONITOR WINAPI MonitorFromWindow(HWND hWnd, DWORD dwFlags) /* Return FALSE on failure and TRUE on success */ static BOOL update_display_cache(void) { - struct display_device device, *adapter, *adapter2, *monitor, *monitor2; + DISPLAY_DEVICEW *adapter, *device; DWORD adapter_idx, monitor_idx; - struct list *monitor_list; FILETIME filetime = {0}; HANDLE mutex = NULL; BOOL ret = FALSE; @@ -3846,41 +3836,23 @@ static BOOL update_display_cache(void) mutex = get_display_device_init_mutex(); EnterCriticalSection( &display_section );
- LIST_FOR_EACH_ENTRY_SAFE(adapter, adapter2, &adapters, struct display_device, entry) + adapter_idx = 0; + device = display_devices; + while (device < display_devices + ARRAY_SIZE(display_devices) && + enum_display_device( NULL, adapter_idx++, device )) { - LIST_FOR_EACH_ENTRY_SAFE(monitor, monitor2, &adapter->children, struct display_device, entry) - { - list_remove( &monitor->entry ); - heap_free( monitor ); - } - list_remove( &adapter->entry ); - heap_free( adapter ); - } - - for (adapter_idx = 0; enum_display_device( NULL, adapter_idx, &device ); ++adapter_idx) - { - adapter = heap_alloc( sizeof(*adapter) ); - if (!adapter) - goto fail; - - memcpy( adapter, &device, sizeof(device) ); - monitor_list = &adapter->children; - list_init( monitor_list ); - list_add_tail( &adapters, &adapter->entry ); - for (monitor_idx = 0; enum_display_device( adapter->device_name, monitor_idx, &device ); ++monitor_idx) - { - monitor = heap_alloc( sizeof(*monitor) ); - if (!monitor) - goto fail; - - memcpy( monitor, &device, sizeof(device) ); - list_add_tail( monitor_list, &monitor->entry ); - } + monitor_idx = 0; + adapter = device++; + while (device < display_devices + ARRAY_SIZE(display_devices) && + enum_display_device( adapter->DeviceName, monitor_idx++, device )) + device++; } + if (device == display_devices + ARRAY_SIZE(display_devices)) + FIXME( "More than %u display devices detected, ignoring.\n", ARRAY_SIZE(display_devices) ); + display_devices_end = device;
last_query_display_time = filetime; ret = TRUE; -fail: LeaveCriticalSection( &display_section ); release_display_device_init_mutex( mutex ); return ret; @@ -4219,87 +4191,68 @@ BOOL WINAPI EnumDisplayDevicesA( LPCSTR device, DWORD index, DISPLAY_DEVICEA *in /*********************************************************************** * EnumDisplayDevicesW (USER32.@) */ -BOOL WINAPI EnumDisplayDevicesW( LPCWSTR device, DWORD index, DISPLAY_DEVICEW *info, DWORD flags ) +BOOL WINAPI EnumDisplayDevicesW( const WCHAR *devname, DWORD index, DISPLAY_DEVICEW *info, DWORD flags ) { - struct display_device *adapter, *monitor, *found = NULL; + DISPLAY_DEVICEW *device; WCHAR buffer[MAX_PATH]; - DWORD device_idx = 0; + DWORD size;
- TRACE("%s %u %p %#x\n", debugstr_w( device ), index, info, flags); + TRACE( "devname %s, index %u, info %p, flags %#x\n", debugstr_w(devname), index, info, flags );
if (!update_display_cache()) return FALSE;
EnterCriticalSection( &display_section ); /* Enumerate adapters */ - if (!device) + if (!devname) { - LIST_FOR_EACH_ENTRY(adapter, &adapters, struct display_device, entry) + for (device = display_devices; device < display_devices_end; device++) { - if (index == device_idx++) - { - found = adapter; - break; - } + if (wcsstr( device->DeviceName, L"\Monitor" )) continue; + if (!index--) break; } } /* Enumerate monitors */ else { - LIST_FOR_EACH_ENTRY(adapter, &adapters, struct display_device, entry) - { - if (!lstrcmpiW( device, adapter->device_name )) - { - found = adapter; - break; - } - } + for (device = display_devices; device < display_devices_end; device++) + if (!wcscmp( device->DeviceName, devname )) break;
- if (found) + for (device = device + 1; device < display_devices_end; device++) { - found = NULL; - LIST_FOR_EACH_ENTRY(monitor, &adapter->children, struct display_device, entry) - { - if (index == device_idx++) - { - found = monitor; - break; - } - } + if (!wcsstr( device->DeviceName, L"\Monitor" )) device = display_devices_end; + else if (!index--) break; } }
- if (!found) + if (device >= display_devices_end) { LeaveCriticalSection( &display_section ); return FALSE; }
- if (info->cb >= offsetof(DISPLAY_DEVICEW, DeviceName) + sizeof(info->DeviceName)) - lstrcpyW( info->DeviceName, found->device_name ); - if (info->cb >= offsetof(DISPLAY_DEVICEW, DeviceString) + sizeof(info->DeviceString)) - lstrcpyW( info->DeviceString, found->device_string ); - if (info->cb >= offsetof(DISPLAY_DEVICEW, StateFlags) + sizeof(info->StateFlags)) - info->StateFlags = found->state_flags; + size = info->cb; + memcpy( info, device, info->cb ); + info->cb = size; + if (info->cb >= offsetof(DISPLAY_DEVICEW, DeviceID) + sizeof(info->DeviceID)) { - if (!device || (flags & EDD_GET_DEVICE_INTERFACE_NAME)) - lstrcpyW( info->DeviceID, found->device_id ); + if (!devname || (flags & EDD_GET_DEVICE_INTERFACE_NAME)) + lstrcpyW( info->DeviceID, device->DeviceID ); else { - swscanf( found->device_id, L"\\?\DISPLAY#%[^#]#%*[^#]#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}", buffer ); + swscanf( device->DeviceID, L"\\?\DISPLAY#%[^#]#%*[^#]#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}", buffer ); swprintf( info->DeviceID, ARRAY_SIZE(info->DeviceID), L"MONITOR\%s\{4d36e96e-e325-11ce-bfc1-08002be10318}\%s", - buffer, wcsrchr( found->device_key, '\' ) + 1 ); + buffer, wcsrchr( device->DeviceKey, '\' ) + 1 ); } } - if (info->cb >= offsetof(DISPLAY_DEVICEW, DeviceKey) + sizeof(info->DeviceKey)) - lstrcpyW( info->DeviceKey, found->device_key ); + LeaveCriticalSection( &display_section ); return TRUE; }
/* Call this function with the display_device_init mutex held */ -static BOOL enum_display_device( WCHAR *device, DWORD index, struct display_device *info ) +static BOOL enum_display_device( WCHAR *device, DWORD index, DISPLAY_DEVICEW *info ) { SP_DEVINFO_DATA device_data = {sizeof(device_data)}; HDEVINFO set = INVALID_HANDLE_VALUE; @@ -4322,24 +4275,24 @@ static BOOL enum_display_device( WCHAR *device, DWORD index, struct display_devi goto done;
/* DeviceKey */ - lstrcpyW( info->device_key, bufferW ); + lstrcpyW( info->DeviceKey, bufferW );
/* DeviceName */ - swprintf( info->device_name, ARRAY_SIZE(info->device_name), L"\\.\DISPLAY%d", index + 1 ); + swprintf( info->DeviceName, ARRAY_SIZE(info->DeviceName), L"\\.\DISPLAY%d", index + 1 );
/* Strip \Registry\Machine\ */ lstrcpyW( key_nameW, bufferW + 18 );
/* DeviceString */ - size = sizeof(info->device_string); + size = sizeof(info->DeviceString); if (RegGetValueW( HKEY_LOCAL_MACHINE, key_nameW, L"DriverDesc", RRF_RT_REG_SZ, NULL, - info->device_string, &size )) + info->DeviceString, &size )) goto done;
/* StateFlags */ - size = sizeof(info->state_flags); + size = sizeof(info->StateFlags); if (RegGetValueW( HKEY_CURRENT_CONFIG, key_nameW, L"StateFlags", RRF_RT_REG_DWORD, NULL, - &info->state_flags, &size )) + &info->StateFlags, &size )) goto done;
/* DeviceID */ @@ -4352,7 +4305,7 @@ static BOOL enum_display_device( WCHAR *device, DWORD index, struct display_devi || !SetupDiGetDeviceRegistryPropertyW( set, &device_data, SPDRP_HARDWAREID, NULL, (BYTE *)bufferW, sizeof(bufferW), NULL )) goto done; - lstrcpyW( info->device_id, bufferW ); + lstrcpyW( info->DeviceID, bufferW ); } /* Find monitor */ else @@ -4369,7 +4322,7 @@ static BOOL enum_display_device( WCHAR *device, DWORD index, struct display_devi goto done;
/* DeviceName */ - swprintf( info->device_name, ARRAY_SIZE(info->device_name), L"\\.\DISPLAY%d\Monitor%d", adapter_index, index ); + swprintf( info->DeviceName, ARRAY_SIZE(info->DeviceName), L"\\.\DISPLAY%d\Monitor%d", adapter_index, index );
/* Get monitor instance */ /* Strip \Registry\Machine\ first */ @@ -4386,13 +4339,13 @@ static BOOL enum_display_device( WCHAR *device, DWORD index, struct display_devi
/* StateFlags */ if (!SetupDiGetDevicePropertyW( set, &device_data, &WINE_DEVPROPKEY_MONITOR_STATEFLAGS, &type, - (BYTE *)&info->state_flags, sizeof(info->state_flags), NULL, 0 )) + (BYTE *)&info->StateFlags, sizeof(info->StateFlags), NULL, 0 )) goto done;
/* DeviceString */ if (!SetupDiGetDeviceRegistryPropertyW( set, &device_data, SPDRP_DEVICEDESC, NULL, - (BYTE *)info->device_string, - sizeof(info->device_string), NULL )) + (BYTE *)info->DeviceString, + sizeof(info->DeviceString), NULL )) goto done;
/* DeviceKey */ @@ -4400,15 +4353,15 @@ static BOOL enum_display_device( WCHAR *device, DWORD index, struct display_devi sizeof(bufferW), NULL )) goto done;
- lstrcpyW( info->device_key, L"\Registry\Machine\System\CurrentControlSet\Control\Class\" ); - lstrcatW( info->device_key, bufferW ); + lstrcpyW( info->DeviceKey, L"\Registry\Machine\System\CurrentControlSet\Control\Class\" ); + lstrcatW( info->DeviceKey, bufferW );
/* Interface name */ - lstrcpyW( info->device_id, L"\\?\" ); - lstrcatW( info->device_id, instanceW ); - lstrcatW( info->device_id, L"#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}" ); + lstrcpyW( info->DeviceID, L"\\?\" ); + lstrcatW( info->DeviceID, instanceW ); + lstrcatW( info->DeviceID, L"#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}" ); /* Replace '\' with '#' after prefix */ - for (next_charW = info->device_id + lstrlenW( L"\\?\" ); *next_charW; next_charW++) + for (next_charW = info->DeviceID + lstrlenW( L"\\?\" ); *next_charW; next_charW++) { if (*next_charW == '\') *next_charW = '#'; @@ -4436,11 +4389,11 @@ done: /* Adapter */ if (!device) { - lstrcpyW( info->device_name, L"\\.\DISPLAY1" ); - lstrcpyW( info->device_string, L"Wine Adapter" ); - info->state_flags = DISPLAY_DEVICE_ATTACHED_TO_DESKTOP | DISPLAY_DEVICE_PRIMARY_DEVICE | DISPLAY_DEVICE_VGA_COMPATIBLE; - lstrcpyW( info->device_id, L"PCI\VEN_0000&DEV_0000&SUBSYS_00000000&REV_00" ); - lstrcpyW( info->device_key, L"\Registry\Machine\System\CurrentControlSet\Control\Video\{71c91c84-1064-400f-a994-95e3ff2716d6}\0000" ); + lstrcpyW( info->DeviceName, L"\\.\DISPLAY1" ); + lstrcpyW( info->DeviceString, L"Wine Adapter" ); + info->StateFlags = DISPLAY_DEVICE_ATTACHED_TO_DESKTOP | DISPLAY_DEVICE_PRIMARY_DEVICE | DISPLAY_DEVICE_VGA_COMPATIBLE; + lstrcpyW( info->DeviceID, L"PCI\VEN_0000&DEV_0000&SUBSYS_00000000&REV_00" ); + lstrcpyW( info->DeviceKey, L"\Registry\Machine\System\CurrentControlSet\Control\Video\{71c91c84-1064-400f-a994-95e3ff2716d6}\0000" ); } /* Monitor */ else @@ -4448,11 +4401,11 @@ done: if (lstrcmpiW( L"\\.\DISPLAY1", device )) return FALSE;
- lstrcpyW( info->device_name, L"\\.\DISPLAY1\Monitor0" ); - lstrcpyW( info->device_string, L"Generic Non-PnP Monitor" ); - info->state_flags = DISPLAY_DEVICE_ACTIVE | DISPLAY_DEVICE_ATTACHED; - lstrcpyW( info->device_id, L"\\?\DISPLAY#Default_Monitor#4&17f0ff54&0&UID0#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}" ); - lstrcpyW( info->device_key, L"\Registry\Machine\System\CurrentControlSet\Control\Class\{4d36e96e-e325-11ce-bfc1-08002be10318}\0000" ); + lstrcpyW( info->DeviceName, L"\\.\DISPLAY1\Monitor0" ); + lstrcpyW( info->DeviceString, L"Generic Non-PnP Monitor" ); + info->StateFlags = DISPLAY_DEVICE_ACTIVE | DISPLAY_DEVICE_ATTACHED; + lstrcpyW( info->DeviceID, L"\\?\DISPLAY#Default_Monitor#4&17f0ff54&0&UID0#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}" ); + lstrcpyW( info->DeviceKey, L"\Registry\Machine\System\CurrentControlSet\Control\Class\{4d36e96e-e325-11ce-bfc1-08002be10318}\0000" ); }
return TRUE;
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=100336
Your paranoid android.
=== debiant2 (32 bit report) ===
user32: win.c:10420: Test failed: Expected foreground window 00120126, got 00AD00EA
=== debiant2 (64 bit WoW report) ===
user32: menu.c:2337: Test failed: test 25
On 10/18/21 3:20 PM, Marvin wrote:
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=100336
Your paranoid android.
=== debiant2 (32 bit report) ===
user32: win.c:10420: Test failed: Expected foreground window 00120126, got 00AD00EA
=== debiant2 (64 bit WoW report) ===
user32: menu.c:2337: Test failed: test 25
I don't think these are new failures introduced by the changes.
Then should I do something differently? I agree that using the cache for some initial data is not exactly the best way to do it but adding the code to initialize a list of devices in setupapi will either:
* duplicate code that's already duplicated in winex11.drv and winemac.drv,
* or we'll have to deduplicate these two first and as far as I could try it's really not going to be easy.
On Thu, 28 Oct 2021, Rémi Bernon wrote: [...]
=== debiant2 (32 bit report) ===
user32: win.c:10420: Test failed: Expected foreground window 00120126, got 00AD00EA
This one is probably not detected as a preexisting failure because the window handle is different with every run (see e.g. the win32 Sep 9 and 15 failures).
https://test.winehq.org/data/patterns.html#user32:win
=== debiant2 (64 bit WoW report) ===
user32: menu.c:2337: Test failed: test 25
And this one is because this test rarely fails and the last time it happened it was for entry 27 and not 25 (see the wow64 result of Sep 8). It's likely that both failures are timing issues.
https://test.winehq.org/data/patterns.html#user32:menu
So only two things can stop such false positives : * Fixing the test somehow. I cannot really help with that. * Or implementing a fix for the "always new" issue (bug 48209). I'm hoping to work on it once I'm done with what's currently on my plate.
So that we have a list of default devices even without the L"HARDWARE\DEVICEMAP\VIDEO" registry key, which the null driver doesn't create.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/user32/sysparams.c | 76 +++++++++++++---------------------------- 1 file changed, 24 insertions(+), 52 deletions(-)
diff --git a/dlls/user32/sysparams.c b/dlls/user32/sysparams.c index 2266e88b710..0ef38ba02c5 100644 --- a/dlls/user32/sysparams.c +++ b/dlls/user32/sysparams.c @@ -107,9 +107,21 @@ DEFINE_DEVPROPKEY(WINE_DEVPROPKEY_MONITOR_ADAPTERNAME, 0x233a9ef3, 0xafc4, 0x4ab
#define NULLDRV_DEFAULT_HMONITOR ((HMONITOR)(UINT_PTR)(0x10000 + 1))
-/* Cached display device information */ -static DISPLAY_DEVICEW display_devices[512]; -static DISPLAY_DEVICEW *display_devices_end = display_devices; +/* Cached display device information, initialized with the default adapter and monitor */ +static DISPLAY_DEVICEW display_devices[512] = +{ + {.cb = sizeof(DISPLAY_DEVICEW), .DeviceName = L"\\.\DISPLAY1", .DeviceString = L"Wine Default Adapter", + .StateFlags = DISPLAY_DEVICE_ATTACHED_TO_DESKTOP|DISPLAY_DEVICE_PRIMARY_DEVICE|DISPLAY_DEVICE_VGA_COMPATIBLE, + .DeviceID = L"PCI\VEN_0000&DEV_0000&SUBSYS_00000000&REV_00", + .DeviceKey = L"\Registry\Machine\System\CurrentControlSet\Control\Video\{8ef18ecd-e56e-419f-8d7d-9991dd40b7f7}\0000", + }, + {.cb = sizeof(DISPLAY_DEVICEW), .DeviceName = L"\\.\DISPLAY1\Monitor0", .DeviceString = L"Generic Non-PnP Monitor", + .StateFlags = DISPLAY_DEVICE_ATTACHED|DISPLAY_DEVICE_ACTIVE, + .DeviceID = L"\\?\DISPLAY#Default_Monitor#0000&0000#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}", + .DeviceKey = L"\Registry\Machine\System\CurrentControlSet\Control\Class\{4d36e96e-e325-11ce-bfc1-08002be10318}\0000", + }, +}; +static DISPLAY_DEVICEW *display_devices_end = display_devices + 2;
static FILETIME last_query_display_time; static CRITICAL_SECTION display_section; @@ -3815,23 +3827,22 @@ HMONITOR WINAPI MonitorFromWindow(HWND hWnd, DWORD dwFlags) }
/* Return FALSE on failure and TRUE on success */ -static BOOL update_display_cache(void) +static void update_display_cache(void) { DISPLAY_DEVICEW *adapter, *device; DWORD adapter_idx, monitor_idx; FILETIME filetime = {0}; HANDLE mutex = NULL; - BOOL ret = FALSE;
/* Update display cache from SetupAPI if it's outdated */ wait_graphics_driver_ready();
if (!video_key && RegOpenKeyW( HKEY_LOCAL_MACHINE, L"HARDWARE\DEVICEMAP\VIDEO", &video_key )) - return FALSE; + return; if (RegQueryInfoKeyW( video_key, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, &filetime )) - return FALSE; + return; if (CompareFileTime( &filetime, &last_query_display_time ) < 1) - return TRUE; + return;
mutex = get_display_device_init_mutex(); EnterCriticalSection( &display_section ); @@ -3849,13 +3860,13 @@ static BOOL update_display_cache(void) } if (device == display_devices + ARRAY_SIZE(display_devices)) FIXME( "More than %u display devices detected, ignoring.\n", ARRAY_SIZE(display_devices) ); - display_devices_end = device; + + if (device != display_devices) display_devices_end = device; + else WARN( "No display devices detected, keeping default devices.\n" );
last_query_display_time = filetime; - ret = TRUE; LeaveCriticalSection( &display_section ); release_display_device_init_mutex( mutex ); - return ret; }
/* Return FALSE on failure and TRUE on success */ @@ -4199,8 +4210,7 @@ BOOL WINAPI EnumDisplayDevicesW( const WCHAR *devname, DWORD index, DISPLAY_DEVI
TRACE( "devname %s, index %u, info %p, flags %#x\n", debugstr_w(devname), index, info, flags );
- if (!update_display_cache()) - return FALSE; + update_display_cache();
EnterCriticalSection( &display_section ); /* Enumerate adapters */ @@ -4263,7 +4273,6 @@ static BOOL enum_display_device( WCHAR *device, DWORD index, DISPLAY_DEVICEW *in WCHAR *next_charW; DWORD size; DWORD type; - HKEY hkey; BOOL ret = FALSE;
/* Find adapter */ @@ -4371,44 +4380,7 @@ static BOOL enum_display_device( WCHAR *device, DWORD index, DISPLAY_DEVICEW *in ret = TRUE; done: SetupDiDestroyDeviceInfoList( set ); - if (ret) - return ret; - - /* Fallback to report at least one adapter and monitor, if user driver didn't initialize display device registry */ - if (index) - return FALSE; - - /* If user driver did initialize the registry, then exit */ - if (!RegOpenKeyW( HKEY_LOCAL_MACHINE, L"HARDWARE\DEVICEMAP\VIDEO", &hkey )) - { - RegCloseKey( hkey ); - return FALSE; - } - WARN("Reporting fallback display devices\n"); - - /* Adapter */ - if (!device) - { - lstrcpyW( info->DeviceName, L"\\.\DISPLAY1" ); - lstrcpyW( info->DeviceString, L"Wine Adapter" ); - info->StateFlags = DISPLAY_DEVICE_ATTACHED_TO_DESKTOP | DISPLAY_DEVICE_PRIMARY_DEVICE | DISPLAY_DEVICE_VGA_COMPATIBLE; - lstrcpyW( info->DeviceID, L"PCI\VEN_0000&DEV_0000&SUBSYS_00000000&REV_00" ); - lstrcpyW( info->DeviceKey, L"\Registry\Machine\System\CurrentControlSet\Control\Video\{71c91c84-1064-400f-a994-95e3ff2716d6}\0000" ); - } - /* Monitor */ - else - { - if (lstrcmpiW( L"\\.\DISPLAY1", device )) - return FALSE; - - lstrcpyW( info->DeviceName, L"\\.\DISPLAY1\Monitor0" ); - lstrcpyW( info->DeviceString, L"Generic Non-PnP Monitor" ); - info->StateFlags = DISPLAY_DEVICE_ACTIVE | DISPLAY_DEVICE_ATTACHED; - lstrcpyW( info->DeviceID, L"\\?\DISPLAY#Default_Monitor#4&17f0ff54&0&UID0#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}" ); - lstrcpyW( info->DeviceKey, L"\Registry\Machine\System\CurrentControlSet\Control\Class\{4d36e96e-e325-11ce-bfc1-08002be10318}\0000" ); - } - - return TRUE; + return ret; }
/**********************************************************************
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=100337
Your paranoid android.
=== debiant2 (32 bit Chinese:China report) ===
user32: menu.c:2337: Test failed: test 25