[PATCH 5/6] user32: Use a DISPLAY_DEVICEW array as display device cache.

Rémi Bernon rbernon at codeweavers.com
Mon Oct 18 06:31:51 CDT 2021


Signed-off-by: Rémi Bernon <rbernon at 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;
-- 
2.33.0




More information about the wine-devel mailing list