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

commit ea30b96334d91ec2229dc68c6323d2cb9a307abc
Author:     Hervé Poussineau <[email protected]>
AuthorDate: Sat Oct 22 14:37:50 2022 +0200
Commit:     Hervé Poussineau <[email protected]>
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;
 }
 

Reply via email to