From: Hermès Bélusca-Maïto Date: Tue, 3 Dec 2019 01:08:34 +0000 (+0100) Subject: [VIDEOPRT] Protect access to HwResetAdaptersList with spinlock. X-Git-Tag: 0.4.14-RC~1012 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=44314189991059109e60f4b101171aaf1c735f8a [VIDEOPRT] Protect access to HwResetAdaptersList with spinlock. --- 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