https://git.reactos.org/?p=reactos.git;a=commitdiff;h=44314189991059109e60f4b101171aaf1c735f8a

commit 44314189991059109e60f4b101171aaf1c735f8a
Author:     Hermès Bélusca-Maïto <[email protected]>
AuthorDate: Tue Dec 3 02:08:34 2019 +0100
Commit:     Hermès Bélusca-Maïto <[email protected]>
CommitDate: Tue Dec 3 02:46:38 2019 +0100

    [VIDEOPRT] Protect access to HwResetAdaptersList with spinlock.
---
 win32ss/drivers/videoprt/dispatch.c | 45 ++++++++++++++++++++++++++++---------
 win32ss/drivers/videoprt/videoprt.c | 13 ++++++-----
 win32ss/drivers/videoprt/videoprt.h |  1 +
 3 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/win32ss/drivers/videoprt/dispatch.c 
b/win32ss/drivers/videoprt/dispatch.c
index 42f7023b0b1..b116cf1100b 100644
--- a/win32ss/drivers/videoprt/dispatch.c
+++ b/win32ss/drivers/videoprt/dispatch.c
@@ -74,22 +74,35 @@ IntVideoPortResetDisplayParametersEx(
     _In_ ULONG Rows,
     _In_ BOOLEAN CalledByInbv)
 {
-    BOOLEAN Success = TRUE;
+    BOOLEAN Success = TRUE; // Suppose we don't need to perform a full reset.
+    KIRQL OldIrql;
     PLIST_ENTRY PrevEntry, Entry;
     PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
     PVIDEO_PORT_DRIVER_EXTENSION DriverExtension;
 
+    /* Check if we are at dispatch level or lower, and acquire the lock */
+    OldIrql = KeGetCurrentIrql();
+    if (OldIrql <= DISPATCH_LEVEL)
+    {
+        /* Loop until the lock is free, then raise IRQL to dispatch level */
+        while (!KeTestSpinLock(&HwResetAdaptersLock));
+        KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
+    }
+    KeAcquireSpinLockAtDpcLevel(&HwResetAdaptersLock);
+
+    /* Bail out early if we don't have any resettable adapter */
     if (IsListEmpty(&HwResetAdaptersList))
-        return FALSE;
+    {
+        Success = FALSE; // No adapter found: request HAL to perform a full 
reset.
+        goto Quit;
+    }
 
+    /*
+     * If we have been unexpectedly called via a callback from
+     * InbvAcquireDisplayOwnership(), start monitoring INBV.
+     */
     if (CalledByInbv)
-    {
-        /*
-         * We have been unexpectedly called via a callback from
-         * InbvAcquireDisplayOwnership(): start monitoring INBV.
-         */
         InbvMonitoring = TRUE;
-    }
 
     for (PrevEntry = &HwResetAdaptersList, Entry = PrevEntry->Flink;
          Entry != &HwResetAdaptersList;
@@ -102,7 +115,10 @@ IntVideoPortResetDisplayParametersEx(
          */
 // #define IS_ALIGNED(addr, align) (((ULONG64)(addr) & (align - 1)) == 0)
         if (((ULONG_PTR)Entry & (sizeof(ULONG_PTR) - 1)) != 0)
-            return FALSE;
+        {
+            Success = FALSE; // We failed: request HAL to perform a full reset.
+            goto Quit;
+        }
 
         DeviceExtension = CONTAINING_RECORD(Entry,
                                             VIDEO_PORT_DEVICE_EXTENSION,
@@ -118,7 +134,10 @@ IntVideoPortResetDisplayParametersEx(
             ASSERT(DriverExtension);
 
             if (DeviceExtension->HwResetListEntry.Blink != PrevEntry)
-                _SEH2_YIELD(return FALSE);
+            {
+                Success = FALSE; // We failed: request HAL to perform a full 
reset.
+                _SEH2_YIELD(goto Quit);
+            }
 
             if ((DeviceExtension->DeviceOpened >= 1) &&
                 (DriverExtension->InitializationData.HwResetHw != NULL))
@@ -134,6 +153,12 @@ IntVideoPortResetDisplayParametersEx(
         _SEH2_END;
     }
 
+Quit:
+    /* Release the lock and restore the old IRQL if we were at dispatch level 
or lower */
+    KeReleaseSpinLockFromDpcLevel(&HwResetAdaptersLock);
+    if (OldIrql <= DISPATCH_LEVEL)
+        KeLowerIrql(OldIrql);
+
     return Success;
 }
 
diff --git a/win32ss/drivers/videoprt/videoprt.c 
b/win32ss/drivers/videoprt/videoprt.c
index 6e75d563ea9..b4207309e93 100644
--- a/win32ss/drivers/videoprt/videoprt.c
+++ b/win32ss/drivers/videoprt/videoprt.c
@@ -33,6 +33,7 @@
 PKPROCESS CsrProcess = NULL;
 ULONG VideoPortDeviceNumber = 0;
 KMUTEX VideoPortInt10Mutex;
+KSPIN_LOCK HwResetAdaptersLock;
 RTL_STATIC_LIST_HEAD(HwResetAdaptersList);
 
 /* PRIVATE FUNCTIONS 
**********************************************************/
@@ -410,8 +411,9 @@ IntVideoPortFindAdapter(
     InitializeListHead(&DeviceExtension->HwResetListEntry);
     if (DriverExtension->InitializationData.HwResetHw != NULL)
     {
-        InsertTailList(&HwResetAdaptersList,
-                       &DeviceExtension->HwResetListEntry);
+        ExInterlockedInsertTailList(&HwResetAdaptersList,
+                                    &DeviceExtension->HwResetListEntry,
+                                    &HwResetAdaptersLock);
     }
 
     /* Query children of the device. */
@@ -471,14 +473,15 @@ VideoPortInitialize(
     NTSTATUS Status;
     PVIDEO_PORT_DRIVER_EXTENSION DriverExtension;
     BOOLEAN PnpDriver = FALSE, LegacyDetection = FALSE;
-    static BOOLEAN Int10MutexInitialized;
+    static BOOLEAN FirstInitialization;
 
     TRACE_(VIDEOPRT, "VideoPortInitialize\n");
 
-    if (!Int10MutexInitialized)
+    if (!FirstInitialization)
     {
         KeInitializeMutex(&VideoPortInt10Mutex, 0);
-        Int10MutexInitialized = TRUE;
+        KeInitializeSpinLock(&HwResetAdaptersLock);
+        FirstInitialization = TRUE;
     }
 
     /* As a first thing do parameter checks. */
diff --git a/win32ss/drivers/videoprt/videoprt.h 
b/win32ss/drivers/videoprt/videoprt.h
index 94289dc031a..8035278e349 100644
--- a/win32ss/drivers/videoprt/videoprt.h
+++ b/win32ss/drivers/videoprt/videoprt.h
@@ -246,6 +246,7 @@ IntVideoPortMapPhysicalMemory(
 extern PKPROCESS CsrProcess;
 extern ULONG VideoPortDeviceNumber;
 extern KMUTEX VideoPortInt10Mutex;
+extern KSPIN_LOCK HwResetAdaptersLock;
 extern LIST_ENTRY HwResetAdaptersList;
 
 VOID FASTCALL

Reply via email to