[PATCH 2/3] user32: Fix a race condition in update_monitor_cache().

Zhiyi Zhang zzhang at codeweavers.com
Tue Oct 22 03:45:40 CDT 2019


Access to video_key and last_query_monitors_time should have been
protected by monitors_section.

Signed-off-by: Zhiyi Zhang <zzhang at codeweavers.com>
---
 dlls/user32/sysparams.c | 30 +++++++++++++++++-------------
 1 file changed, 17 insertions(+), 13 deletions(-)

diff --git a/dlls/user32/sysparams.c b/dlls/user32/sysparams.c
index d9c7779edb..8568a5a73a 100644
--- a/dlls/user32/sysparams.c
+++ b/dlls/user32/sysparams.c
@@ -732,6 +732,7 @@ static HANDLE get_display_device_init_mutex( void )
 
 static void release_display_device_init_mutex( HANDLE mutex )
 {
+    if (!mutex) return;
     ReleaseMutex( mutex );
     CloseHandle( mutex );
 }
@@ -3755,15 +3756,18 @@ static BOOL update_monitor_cache(void)
     DWORD type;
 
     /* Update monitor cache from SetupAPI if it's outdated */
+    EnterCriticalSection( &monitors_section );
     if (!video_key && RegOpenKeyW( HKEY_LOCAL_MACHINE, VIDEO_KEY, &video_key ))
-        return FALSE;
+        goto done;
     if (RegQueryInfoKeyW( video_key, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, &filetime ))
-        return FALSE;
+        goto done;
     if (CompareFileTime( &filetime, &last_query_monitors_time ) < 1)
-        return TRUE;
+    {
+        ret = TRUE;
+        goto done;
+    }
 
     mutex = get_display_device_init_mutex();
-    EnterCriticalSection( &monitors_section );
     devinfo = SetupDiGetClassDevsW( &GUID_DEVCLASS_MONITOR, DISPLAY, NULL, DIGCF_PRESENT );
 
     while (SetupDiEnumDeviceInfo( devinfo, i++, &device_data ))
@@ -3771,7 +3775,7 @@ static BOOL update_monitor_cache(void)
         /* Inactive monitors don't get enumerated */
         if (!SetupDiGetDevicePropertyW( devinfo, &device_data, &WINE_DEVPROPKEY_MONITOR_STATEFLAGS, &type,
                                         (BYTE *)&state_flags, sizeof(DWORD), NULL, 0 ))
-            goto fail;
+            goto done;
         if (state_flags & DISPLAY_DEVICE_ACTIVE)
             device_count++;
     }
@@ -3780,7 +3784,7 @@ static BOOL update_monitor_cache(void)
     {
         monitor_array = heap_realloc( monitors, device_count * sizeof(*monitor_array) );
         if (!monitor_array)
-            goto fail;
+            goto done;
         monitors = monitor_array;
     }
 
@@ -3788,18 +3792,18 @@ static BOOL update_monitor_cache(void)
     {
         if (!SetupDiGetDevicePropertyW( devinfo, &device_data, &WINE_DEVPROPKEY_MONITOR_STATEFLAGS, &type,
                                         (BYTE *)&state_flags, sizeof(DWORD), NULL, 0 ))
-            goto fail;
+            goto done;
         if (!(state_flags & DISPLAY_DEVICE_ACTIVE))
             continue;
         if (!SetupDiGetDevicePropertyW( devinfo, &device_data, &WINE_DEVPROPKEY_MONITOR_RCMONITOR, &type,
                                         (BYTE *)&monitors[monitor_count].rcMonitor, sizeof(RECT), NULL, 0 ))
-            goto fail;
+            goto done;
 
         /* Mirrored slave monitors also don't get enumerated */
         mirrored_slave = FALSE;
         for (j = 0; j < monitor_count; j++)
         {
-            if (EqualRect(&monitors[j].rcMonitor, &monitors[monitor_count].rcMonitor))
+            if (EqualRect( &monitors[j].rcMonitor, &monitors[monitor_count].rcMonitor ))
             {
                 mirrored_slave = TRUE;
                 break;
@@ -3810,10 +3814,10 @@ static BOOL update_monitor_cache(void)
 
         if (!SetupDiGetDevicePropertyW( devinfo, &device_data, &WINE_DEVPROPKEY_MONITOR_RCWORK, &type,
                                         (BYTE *)&monitors[monitor_count].rcWork, sizeof(RECT), NULL, 0 ))
-            goto fail;
+            goto done;
         if (!SetupDiGetDevicePropertyW( devinfo, &device_data, &WINE_DEVPROPKEY_MONITOR_ADAPTERNAME, &type,
                                         (BYTE *)monitors[monitor_count].szDevice, CCHDEVICENAME * sizeof(WCHAR), NULL, 0))
-            goto fail;
+            goto done;
         monitors[monitor_count].dwFlags =
             !lstrcmpW( DEFAULT_ADAPTER_NAME, monitors[monitor_count].szDevice ) ? MONITORINFOF_PRIMARY : 0;
 
@@ -3822,10 +3826,10 @@ static BOOL update_monitor_cache(void)
 
     last_query_monitors_time = filetime;
     ret = TRUE;
-fail:
+done:
     SetupDiDestroyDeviceInfoList( devinfo );
-    LeaveCriticalSection( &monitors_section );
     release_display_device_init_mutex( mutex );
+    LeaveCriticalSection( &monitors_section );
     if (!ret)
         ERR("Failed to update monitor cache.\n");
     return ret;
-- 
2.23.0




More information about the wine-devel mailing list