https://git.reactos.org/?p=reactos.git;a=commitdiff;h=44314189991059109e60f…
commit 44314189991059109e60f4b101171aaf1c735f8a
Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
AuthorDate: Tue Dec 3 02:08:34 2019 +0100
Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
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