From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/sysparams.c | 87 +++++++++++++++++++++++++++++------------ 1 file changed, 61 insertions(+), 26 deletions(-)
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 00a9d30691b..03a0796cc19 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -74,6 +74,9 @@ static const WCHAR guid_devclass_displayW[] = {'{','4','D','3','6','E','9','6','8','-','E','3','2','5','-','1','1','C','E','-', 'B','F','C','1','-','0','8','0','0','2','B','E','1','0','3','1','8','}',0}; static const char guid_devclass_monitorA[] = "{4D36E96E-E325-11CE-BFC1-08002BE10318}"; +static const WCHAR guid_devclass_monitorW[] = + {'{','4','D','3','6','E','9','6','E','-','E','3','2','5','-','1','1','C','E','-', + 'B','F','C','1','-','0','8','0','0','2','B','E','1','0','3','1','8','}',0};
static const char guid_devinterface_display_adapterA[] = "{5B45201D-F2F2-4F3B-85BB-30FF1F953599}"; static const char guid_display_device_arrivalA[] = "{1CA05180-A699-450A-9A0C-DE4FBE3DDD89}"; @@ -658,28 +661,14 @@ static BOOL read_display_adapter_settings( unsigned int index, struct adapter *i return TRUE; }
-static BOOL read_monitor_settings( struct adapter *adapter, UINT index, struct monitor *monitor ) +static BOOL read_monitor_from_registry( struct monitor *monitor ) { char buffer[4096]; KEY_VALUE_PARTIAL_INFORMATION *value = (void *)buffer; - WCHAR *value_str = (WCHAR *)value->Data; HKEY hkey, subkey; DWORD size; - UINT i; - - if (!(hkey = reg_open_key( config_key, adapter->config_key, - lstrlenW( adapter->config_key ) * sizeof(WCHAR) ))) - return FALSE; - - /* Interface name */ - sprintf( buffer, "MonitorID%u", index ); - size = query_reg_ascii_value( hkey, buffer, value, sizeof(buffer) ); - NtClose( hkey ); - if (!size || value->Type != REG_SZ) return FALSE;
- for (i = 0; i < value->DataLength / sizeof(WCHAR); i++) monitor->path[i] = value_str[i]; - if (!(hkey = reg_open_key( enum_key, value_str, value->DataLength - sizeof(WCHAR) ))) - return FALSE; + if (!(hkey = reg_open_ascii_key( enum_key, monitor->path ))) return FALSE;
/* Output ID */ size = query_reg_subkey_value( hkey, devpropkey_monitor_output_idA, @@ -723,6 +712,22 @@ static BOOL read_monitor_settings( struct adapter *adapter, UINT index, struct m return TRUE; }
+static BOOL read_adapter_monitor_path( HKEY hkey, UINT index, char *path ) +{ + char buffer[4096]; + KEY_VALUE_PARTIAL_INFORMATION *value = (void *)buffer; + WCHAR *value_str = (WCHAR *)value->Data; + DWORD size; + UINT i; + + sprintf( buffer, "MonitorID%u", index ); + size = query_reg_ascii_value( hkey, buffer, value, sizeof(buffer) ); + if (!size || value->Type != REG_SZ) return FALSE; + + for (i = 0; i < value->DataLength / sizeof(WCHAR); i++) path[i] = value_str[i]; + return TRUE; +} + static void reg_empty_key( HKEY root, const char *key_name ) { char buffer[4096]; @@ -1596,6 +1601,25 @@ static struct gpu *find_gpu_from_path( const char *path ) return NULL; }
+static void enum_monitors( const char *path ) +{ + struct monitor *monitor; + if (!(monitor = calloc( 1, sizeof(*monitor) ))) return; + strcpy( monitor->path, path ); + list_add_tail( &monitors, &monitor->entry ); +} + +static struct monitor *find_monitor_from_path( const char *path ) +{ + struct monitor *monitor; + + LIST_FOR_EACH_ENTRY( monitor, &monitors, struct monitor, entry ) + if (!strcmp( monitor->path, path )) return monitor; + + ERR( "Failed to find monitor with path %s\n", debugstr_a(path) ); + return NULL; +} + static BOOL update_display_cache_from_registry(void) { char path[MAX_PATH]; @@ -1606,6 +1630,7 @@ static BOOL update_display_cache_from_registry(void) HANDLE mutex = NULL; NTSTATUS status; struct gpu *gpu; + HKEY hkey; BOOL ret;
/* If user driver did initialize the registry, then exit */ @@ -1627,6 +1652,7 @@ static BOOL update_display_cache_from_registry(void) clear_display_devices();
enum_device_keys( "PCI", guid_devclass_displayW, sizeof(guid_devclass_displayW), enum_gpus ); + enum_device_keys( "DISPLAY", guid_devclass_monitorW, sizeof(guid_devclass_monitorW), enum_monitors );
LIST_FOR_EACH_ENTRY( gpu, &gpus, struct gpu, entry ) { @@ -1634,6 +1660,12 @@ static BOOL update_display_cache_from_registry(void) WARN( "Failed to read gpu from registry\n" ); }
+ LIST_FOR_EACH_ENTRY( monitor, &monitors, struct monitor, entry ) + { + if (!read_monitor_from_registry( monitor )) + WARN( "Failed to read monitor from registry\n" ); + } + for (adapter_id = 0;; adapter_id++) { if (!(adapter = calloc( 1, sizeof(*adapter) ))) break; @@ -1649,23 +1681,27 @@ static BOOL update_display_cache_from_registry(void) }
list_add_tail( &adapters, &adapter->entry ); + + size = lstrlenW( adapter->config_key ) * sizeof(WCHAR); + if (!(hkey = reg_open_key( config_key, adapter->config_key, size ))) continue; + for (monitor_id = 0;; monitor_id++) { - if (!(monitor = calloc( 1, sizeof(*monitor) ))) break; - if (!read_monitor_settings( adapter, monitor_id, monitor )) - { - free( monitor ); - break; - } + struct monitor *monitor; + + if (!read_adapter_monitor_path( hkey, monitor_id, path )) break; + if (!(monitor = find_monitor_from_path( path ))) continue;
monitor->id = monitor_id; monitor->adapter = adapter_acquire( adapter ); + monitor->handle = UlongToHandle( ++monitor_count ); + adapter->monitor_count++;
if (adapter->state_flags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) { LIST_FOR_EACH_ENTRY( monitor2, &monitors, struct monitor, entry ) { - if (!is_monitor_active( monitor2 )) continue; + if (monitor == monitor2 || !is_monitor_active( monitor2 )) continue; if (EqualRect( &monitor2->rc_monitor, &monitor->rc_monitor )) { monitor->is_clone = TRUE; @@ -1673,10 +1709,9 @@ static BOOL update_display_cache_from_registry(void) } } } - - monitor->handle = UlongToHandle( ++monitor_count ); - list_add_tail( &monitors, &monitor->entry ); } + + NtClose( hkey ); }
if ((ret = !list_empty( &adapters ) && !list_empty( &monitors )))