From dca369cf41cd3c2be7ce5956d77d536dada4ea1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= Date: Wed, 7 Feb 2024 20:20:22 +0100 Subject: [PATCH] [WIN32SS:ENG] Rework EngpUpdateGraphicsDeviceList - choose VGA adapter outside of driver initialization loop - choose primary adapter outside of driver initialization loop - link VGA adapter to primary adapter at the end - only set DISPLAY_DEVICE_PRIMARY_DEVICE in this function Also mark VgaSave driver as SystemStart instead of Disabled, so it is available if main display driver doesn't work. --- boot/bootdata/hiveinst.inf | 3 - win32ss/drivers/miniport/vga/vga_reg.inf | 2 +- win32ss/gdi/eng/device.c | 104 ++++++++++++++--------- win32ss/gdi/eng/pdevobj.c | 2 +- 4 files changed, 64 insertions(+), 47 deletions(-) diff --git a/boot/bootdata/hiveinst.inf b/boot/bootdata/hiveinst.inf index bdd4d49c6f0..228b68931d9 100644 --- a/boot/bootdata/hiveinst.inf +++ b/boot/bootdata/hiveinst.inf @@ -7,6 +7,3 @@ Signature = "$Windows NT$" ; ; Display driver section ; - -; VGA miniport driver -HKLM,"SYSTEM\CurrentControlSet\Services\VgaSave","Start",0x00010001,0x00000001 diff --git a/win32ss/drivers/miniport/vga/vga_reg.inf b/win32ss/drivers/miniport/vga/vga_reg.inf index 617afe6e038..528a5916b7f 100644 --- a/win32ss/drivers/miniport/vga/vga_reg.inf +++ b/win32ss/drivers/miniport/vga/vga_reg.inf @@ -3,7 +3,7 @@ HKLM,"SYSTEM\CurrentControlSet\Services\VgaSave","ErrorControl",0x00010001,0x00000000 HKLM,"SYSTEM\CurrentControlSet\Services\VgaSave","Group",0x00000000,"Video Save" HKLM,"SYSTEM\CurrentControlSet\Services\VgaSave","ImagePath",0x00020000,"system32\drivers\vga.sys" -HKLM,"SYSTEM\CurrentControlSet\Services\VgaSave","Start",0x00010001,0x00000004 +HKLM,"SYSTEM\CurrentControlSet\Services\VgaSave","Start",0x00010001,0x00000001 HKLM,"SYSTEM\CurrentControlSet\Services\VgaSave","Type",0x00010001,0x00000001 HKLM,"SYSTEM\CurrentControlSet\Services\VgaSave","Tag",0x00010001,0x00000002 HKLM,"SYSTEM\CurrentControlSet\Services\VgaSave\Video","Service",0x00000000,"VgaSave" diff --git a/win32ss/gdi/eng/device.c b/win32ss/gdi/eng/device.c index 6072fccf571..ba49bd4dd7e 100644 --- a/win32ss/gdi/eng/device.c +++ b/win32ss/gdi/eng/device.c @@ -170,16 +170,23 @@ EngpUnlinkGraphicsDevice( } } +/* Goal of this function is to: + * - detect new graphic devices (from registry) and initialize them + * - link primary device and VGA device (if available) using pVgaDevice field + * - handle gbBaseVideo global flag + * - set DISPLAY_DEVICE_PRIMARY_DEVICE on at least one device + * - set gpPrimaryGraphicsDevice + * - set gpVgaGraphicsDevice + */ NTSTATUS EngpUpdateGraphicsDeviceList(VOID) { - ULONG iDevNum, iVGACompatible = -1, ulMaxObjectNumber = 0; + ULONG iDevNum, ulMaxObjectNumber = 0; WCHAR awcDeviceName[20], awcWinDeviceName[20]; UNICODE_STRING ustrDeviceName; WCHAR awcBuffer[256]; NTSTATUS Status; - PGRAPHICS_DEVICE pGraphicsDevice; - BOOLEAN bFoundNewDevice = FALSE; + PGRAPHICS_DEVICE pGraphicsDevice, pNewPrimaryGraphicsDevice = NULL; ULONG cbValue; HKEY hkey; @@ -191,15 +198,6 @@ EngpUpdateGraphicsDeviceList(VOID) return Status; } - /* Read the name of the VGA adapter */ - cbValue = sizeof(awcDeviceName); - Status = RegQueryValue(hkey, L"VgaCompatible", REG_SZ, awcDeviceName, &cbValue); - if (NT_SUCCESS(Status)) - { - iVGACompatible = _wtoi(&awcDeviceName[sizeof("\\Device\\Video")-1]); - ERR("VGA adapter = %lu\n", iVGACompatible); - } - /* Get the maximum number of adapters */ if (!RegReadDWORD(hkey, L"MaxObjectNumber", &ulMaxObjectNumber)) { @@ -208,7 +206,7 @@ EngpUpdateGraphicsDeviceList(VOID) TRACE("Found %lu devices\n", ulMaxObjectNumber + 1); - /* Loop through all adapters */ + /* Loop through all adapters, to detect new ones */ for (iDevNum = 0; iDevNum <= ulMaxObjectNumber; iDevNum++) { /* Create the adapter's key name */ @@ -237,43 +235,29 @@ EngpUpdateGraphicsDeviceList(VOID) /* Initialize the driver for this device */ pGraphicsDevice = InitDisplayDriver(awcDeviceName, awcBuffer); if (!pGraphicsDevice) continue; - - /* Check if this is a VGA compatible adapter */ - if (pGraphicsDevice->StateFlags & DISPLAY_DEVICE_VGA_COMPATIBLE) - { - /* Save this as the VGA adapter */ - if (!gpVgaGraphicsDevice || !EngpHasVgaDriver(gpVgaGraphicsDevice)) - { - gpVgaGraphicsDevice = pGraphicsDevice; - TRACE("gpVgaGraphicsDevice = %p\n", gpVgaGraphicsDevice); - } - } - bFoundNewDevice = TRUE; - - /* Set the first one as primary device */ - if (!gpPrimaryGraphicsDevice || EngpHasVgaDriver(gpPrimaryGraphicsDevice)) - { - gpPrimaryGraphicsDevice = pGraphicsDevice; - TRACE("gpPrimaryGraphicsDevice = %p\n", gpPrimaryGraphicsDevice); - } } /* Close the device map registry key */ ZwClose(hkey); - /* Can we link VGA device to primary device? */ - if (gpPrimaryGraphicsDevice && - gpVgaGraphicsDevice && - gpPrimaryGraphicsDevice != gpVgaGraphicsDevice && - !gpPrimaryGraphicsDevice->pVgaDevice) + /* Choose a VGA device */ + /* Try a device with DISPLAY_DEVICE_VGA_COMPATIBLE flag. If not found, + * fall back to current VGA device */ + for (pGraphicsDevice = gpGraphicsDeviceFirst; + pGraphicsDevice; + pGraphicsDevice = pGraphicsDevice->pNextGraphicsDevice) { - /* Yes. Remove VGA device from global list, and attach it to primary device */ - TRACE("Linking VGA device %S to primary device %S\n", gpVgaGraphicsDevice->szNtDeviceName, gpPrimaryGraphicsDevice->szNtDeviceName); - EngpUnlinkGraphicsDevice(gpVgaGraphicsDevice); - gpPrimaryGraphicsDevice->pVgaDevice = gpVgaGraphicsDevice; + if (pGraphicsDevice == gpVgaGraphicsDevice) + continue; + if (pGraphicsDevice->StateFlags & DISPLAY_DEVICE_VGA_COMPATIBLE && EngpHasVgaDriver(pGraphicsDevice)) + { + gpVgaGraphicsDevice = pGraphicsDevice; + break; + } } - if (bFoundNewDevice && gbBaseVideo) + /* Handle gbBaseVideo */ + if (gbBaseVideo) { PGRAPHICS_DEVICE pToDelete; @@ -307,6 +291,42 @@ EngpUpdateGraphicsDeviceList(VOID) EngReleaseSemaphore(ghsemGraphicsDeviceList); } + /* Choose a primary device (if none already exists) */ + if (!gpPrimaryGraphicsDevice) + { + for (pGraphicsDevice = gpGraphicsDeviceFirst; + pGraphicsDevice; + pGraphicsDevice = pGraphicsDevice->pNextGraphicsDevice) + { + if (!EngpHasVgaDriver(pGraphicsDevice)) + { + pNewPrimaryGraphicsDevice = pGraphicsDevice; + break; + } + } + if (!pNewPrimaryGraphicsDevice) + pNewPrimaryGraphicsDevice = gpGraphicsDeviceFirst; + if (pNewPrimaryGraphicsDevice) + { + pNewPrimaryGraphicsDevice->StateFlags |= DISPLAY_DEVICE_PRIMARY_DEVICE; + gpPrimaryGraphicsDevice = pNewPrimaryGraphicsDevice; + } + } + + /* Can we link VGA device to primary device? */ + if (gpPrimaryGraphicsDevice && + gpVgaGraphicsDevice && + gpPrimaryGraphicsDevice != gpVgaGraphicsDevice && + !gpPrimaryGraphicsDevice->pVgaDevice) + { + /* Yes. Remove VGA device from global list, and attach it to primary device */ + TRACE("Linking VGA device %S to primary device %S\n", gpVgaGraphicsDevice->szNtDeviceName, gpPrimaryGraphicsDevice->szNtDeviceName); + EngAcquireSemaphore(ghsemGraphicsDeviceList); + EngpUnlinkGraphicsDevice(gpVgaGraphicsDevice); + gpPrimaryGraphicsDevice->pVgaDevice = gpVgaGraphicsDevice; + EngReleaseSemaphore(ghsemGraphicsDeviceList); + } + return STATUS_SUCCESS; } diff --git a/win32ss/gdi/eng/pdevobj.c b/win32ss/gdi/eng/pdevobj.c index 54d69cf7dc7..396c450009b 100644 --- a/win32ss/gdi/eng/pdevobj.c +++ b/win32ss/gdi/eng/pdevobj.c @@ -547,7 +547,7 @@ PDEVOBJ_Create( { RtlCopyMemory(ppdev->pdmwDev, pdm, pdm->dmSize + pdm->dmDriverExtra); /* FIXME: this must be done in a better way */ - pGraphicsDevice->StateFlags |= DISPLAY_DEVICE_PRIMARY_DEVICE | DISPLAY_DEVICE_ATTACHED_TO_DESKTOP; + pGraphicsDevice->StateFlags |= DISPLAY_DEVICE_ATTACHED_TO_DESKTOP; } }