https://git.reactos.org/?p=reactos.git;a=commitdiff;h=ea30b96334d91ec2229dc…
commit ea30b96334d91ec2229dc68c6323d2cb9a307abc
Author: Hervé Poussineau <hpoussin(a)reactos.org>
AuthorDate: Sat Oct 22 14:37:50 2022 +0200
Commit: Hervé Poussineau <hpoussin(a)reactos.org>
CommitDate: Tue Nov 15 23:15:26 2022 +0100
[WIN32SS:ENG] When VGA mode is requested, drop all graphic devices except VGA one
We don't need driver cooperation anymore to handle VGA mode request.
---
win32ss/gdi/eng/device.c | 140 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 140 insertions(+)
diff --git a/win32ss/gdi/eng/device.c b/win32ss/gdi/eng/device.c
index 7940a059752..a4bbb2c7254 100644
--- a/win32ss/gdi/eng/device.c
+++ b/win32ss/gdi/eng/device.c
@@ -32,6 +32,110 @@ InitDeviceImpl(VOID)
return STATUS_SUCCESS;
}
+static
+BOOLEAN
+EngpHasVgaDriver(
+ _In_ PGRAPHICS_DEVICE pGraphicsDevice)
+{
+ WCHAR awcDeviceKey[256], awcServiceName[100];
+ PWSTR lastBkSlash;
+ NTSTATUS Status;
+ ULONG cbValue;
+ HKEY hkey;
+
+ /* Open the key for the adapters */
+ Status = RegOpenKey(L"\\Registry\\Machine\\HARDWARE\\DEVICEMAP\\VIDEO",
&hkey);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("Could not open HARDWARE\\DEVICEMAP\\VIDEO registry key:
0x%08lx\n", Status);
+ return FALSE;
+ }
+
+ /* Read the name of the device key */
+ cbValue = sizeof(awcDeviceKey);
+ Status = RegQueryValue(hkey, pGraphicsDevice->szNtDeviceName, REG_SZ,
awcDeviceKey, &cbValue);
+ ZwClose(hkey);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("Could not read '%S' registry value: 0x%08lx\n", Status);
+ return FALSE;
+ }
+
+ /* Replace 'DeviceN' by 'Video' */
+ lastBkSlash = wcsrchr(awcDeviceKey, L'\\');
+ if (!lastBkSlash)
+ {
+ ERR("Invalid registry key '%S'\n", lastBkSlash);
+ return FALSE;
+ }
+ if (!NT_SUCCESS(RtlStringCchCopyW(lastBkSlash + 1,
+ ARRAYSIZE(awcDeviceKey) - (lastBkSlash + 1 -
awcDeviceKey),
+ L"Video")))
+ {
+ ERR("Failed to add 'Video' to registry key '%S'\n",
awcDeviceKey);
+ return FALSE;
+ }
+
+ /* Open device key */
+ Status = RegOpenKey(awcDeviceKey, &hkey);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("Could not open %S registry key: 0x%08lx\n", awcDeviceKey,
Status);
+ return FALSE;
+ }
+
+ /* Read service name */
+ cbValue = sizeof(awcServiceName);
+ Status = RegQueryValue(hkey, L"Service", REG_SZ, awcServiceName,
&cbValue);
+ ZwClose(hkey);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("Could not read Service registry value in %S: 0x%08lx\n",
awcDeviceKey, Status);
+ return FALSE;
+ }
+
+ /* Device is using VGA driver if service name starts with 'VGA' (case
insensitive) */
+ return (_wcsnicmp(awcServiceName, L"VGA", 3) == 0);
+}
+
+/*
+ * Remove a device from gpGraphicsDeviceFirst/gpGraphicsDeviceLast list.
+ */
+_Requires_lock_held_(ghsemGraphicsDeviceList)
+static
+VOID
+EngpUnlinkGraphicsDevice(
+ _In_ PGRAPHICS_DEVICE pToDelete)
+{
+ PGRAPHICS_DEVICE pPrevGraphicsDevice = NULL;
+ PGRAPHICS_DEVICE pGraphicsDevice = gpGraphicsDeviceFirst;
+
+ TRACE("EngpUnlinkGraphicsDevice('%S')\n",
pToDelete->szNtDeviceName);
+
+ while (pGraphicsDevice)
+ {
+ if (pGraphicsDevice != pToDelete)
+ {
+ /* Keep current device */
+ pPrevGraphicsDevice = pGraphicsDevice;
+ pGraphicsDevice = pGraphicsDevice->pNextGraphicsDevice;
+ }
+ else
+ {
+ /* We need to remove current device */
+ pGraphicsDevice = pGraphicsDevice->pNextGraphicsDevice;
+
+ /* Unlink chain */
+ if (!pPrevGraphicsDevice)
+ gpGraphicsDeviceFirst = pToDelete->pNextGraphicsDevice;
+ else
+ pPrevGraphicsDevice->pNextGraphicsDevice =
pToDelete->pNextGraphicsDevice;
+ if (gpGraphicsDeviceLast == pToDelete)
+ gpGraphicsDeviceLast = pPrevGraphicsDevice;
+ }
+ }
+}
+
NTSTATUS
EngpUpdateGraphicsDeviceList(VOID)
{
@@ -41,6 +145,7 @@ EngpUpdateGraphicsDeviceList(VOID)
WCHAR awcBuffer[256];
NTSTATUS Status;
PGRAPHICS_DEVICE pGraphicsDevice;
+ BOOLEAN bFoundNewDevice = FALSE;
ULONG cbValue;
HKEY hkey;
@@ -109,6 +214,7 @@ EngpUpdateGraphicsDeviceList(VOID)
TRACE("gpVgaGraphicsDevice = %p\n", gpVgaGraphicsDevice);
}
}
+ bFoundNewDevice = TRUE;
/* Set the first one as primary device */
if (!gpPrimaryGraphicsDevice)
@@ -121,6 +227,40 @@ EngpUpdateGraphicsDeviceList(VOID)
/* Close the device map registry key */
ZwClose(hkey);
+ if (bFoundNewDevice && gbBaseVideo)
+ {
+ PGRAPHICS_DEVICE pToDelete;
+
+ /* Lock list */
+ EngAcquireSemaphore(ghsemGraphicsDeviceList);
+
+ /* Remove every device from linked list, except base-video one */
+ pGraphicsDevice = gpGraphicsDeviceFirst;
+ while (pGraphicsDevice)
+ {
+ if (!EngpHasVgaDriver(pGraphicsDevice))
+ {
+ /* Not base-video device. Remove it */
+ pToDelete = pGraphicsDevice;
+ TRACE("Removing non-base-video device %S (%S)\n",
pToDelete->szWinDeviceName, pToDelete->szNtDeviceName);
+
+ EngpUnlinkGraphicsDevice(pGraphicsDevice);
+ pGraphicsDevice = pGraphicsDevice->pNextGraphicsDevice;
+
+ /* Free memory */
+ ExFreePoolWithTag(pToDelete->pDiplayDrivers, GDITAG_DRVSUP);
+ ExFreePoolWithTag(pToDelete, GDITAG_GDEVICE);
+ }
+ else
+ {
+ pGraphicsDevice = pGraphicsDevice->pNextGraphicsDevice;
+ }
+ }
+
+ /* Unlock list */
+ EngReleaseSemaphore(ghsemGraphicsDeviceList);
+ }
+
return STATUS_SUCCESS;
}