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