[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.

CORE-7728, CORE-19224
This commit is contained in:
Hervé Poussineau 2024-02-07 20:20:22 +01:00
parent 2ad5e1cd69
commit 8b7770aa2c
5 changed files with 91 additions and 58 deletions

View file

@ -7,6 +7,3 @@ Signature = "$Windows NT$"
; ;
; Display driver section ; Display driver section
; ;
; VGA miniport driver
HKLM,"SYSTEM\CurrentControlSet\Services\VgaSave","Start",0x00010001,0x00000001

View file

@ -3,7 +3,7 @@
HKLM,"SYSTEM\CurrentControlSet\Services\VgaSave","ErrorControl",0x00010001,0x00000000 HKLM,"SYSTEM\CurrentControlSet\Services\VgaSave","ErrorControl",0x00010001,0x00000000
HKLM,"SYSTEM\CurrentControlSet\Services\VgaSave","Group",0x00000000,"Video Save" 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","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","Type",0x00010001,0x00000001
HKLM,"SYSTEM\CurrentControlSet\Services\VgaSave","Tag",0x00010001,0x00000002 HKLM,"SYSTEM\CurrentControlSet\Services\VgaSave","Tag",0x00010001,0x00000002
HKLM,"SYSTEM\CurrentControlSet\Services\VgaSave\Video","Service",0x00000000,"VgaSave" HKLM,"SYSTEM\CurrentControlSet\Services\VgaSave\Video","Service",0x00000000,"VgaSave"

View file

@ -98,6 +98,30 @@ EngpHasVgaDriver(
return (_wcsnicmp(awcServiceName, L"VGA", 3) == 0); return (_wcsnicmp(awcServiceName, L"VGA", 3) == 0);
} }
static
BOOLEAN
EngpIsVgaDevice(
_In_ PGRAPHICS_DEVICE pGraphicsDevice)
{
BOOLEAN IsVgaDevice;
ULONG ulReturn;
NTSTATUS Status;
Status = (NTSTATUS)EngDeviceIoControl((HANDLE)pGraphicsDevice->DeviceObject,
IOCTL_VIDEO_IS_VGA_DEVICE,
NULL, 0,
&IsVgaDevice, sizeof(IsVgaDevice),
&ulReturn);
if (Status != ERROR_SUCCESS)
{
ERR("EngDeviceIoControl(0x%p, IOCTL_VIDEO_IS_VGA_DEVICE) failed, Status 0x%lx\n",
pGraphicsDevice->DeviceObject, Status);
return FALSE;
}
TRACE("'%S' is%s VGA device\n", pGraphicsDevice->szNtDeviceName, IsVgaDevice ? "" : " NOT");
return IsVgaDevice;
}
/* /*
* Add a device to gpGraphicsDeviceFirst/gpGraphicsDeviceLast list (if not already present). * Add a device to gpGraphicsDeviceFirst/gpGraphicsDeviceLast list (if not already present).
*/ */
@ -170,16 +194,24 @@ EngpUnlinkGraphicsDevice(
} }
} }
/* Goal of this function is to:
* - detect new graphic devices (from registry) and initialize them
* - set DISPLAY_DEVICE_VGA_COMPATIBLE flag on compatible devices
* - set gpVgaGraphicsDevice
* - handle gbBaseVideo global flag
* - set DISPLAY_DEVICE_PRIMARY_DEVICE on at least one device
* - set gpPrimaryGraphicsDevice
* - link primary device and VGA device (if available) using pVgaDevice field
*/
NTSTATUS NTSTATUS
EngpUpdateGraphicsDeviceList(VOID) EngpUpdateGraphicsDeviceList(VOID)
{ {
ULONG iDevNum, iVGACompatible = -1, ulMaxObjectNumber = 0; ULONG iDevNum, ulMaxObjectNumber = 0;
WCHAR awcDeviceName[20], awcWinDeviceName[20]; WCHAR awcDeviceName[20], awcWinDeviceName[20];
UNICODE_STRING ustrDeviceName; UNICODE_STRING ustrDeviceName;
WCHAR awcBuffer[256]; WCHAR awcBuffer[256];
NTSTATUS Status; NTSTATUS Status;
PGRAPHICS_DEVICE pGraphicsDevice; PGRAPHICS_DEVICE pGraphicsDevice, pNewPrimaryGraphicsDevice = NULL;
BOOLEAN bFoundNewDevice = FALSE;
ULONG cbValue; ULONG cbValue;
HKEY hkey; HKEY hkey;
@ -191,15 +223,6 @@ EngpUpdateGraphicsDeviceList(VOID)
return Status; 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 */ /* Get the maximum number of adapters */
if (!RegReadDWORD(hkey, L"MaxObjectNumber", &ulMaxObjectNumber)) if (!RegReadDWORD(hkey, L"MaxObjectNumber", &ulMaxObjectNumber))
{ {
@ -208,7 +231,7 @@ EngpUpdateGraphicsDeviceList(VOID)
TRACE("Found %lu devices\n", ulMaxObjectNumber + 1); 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++) for (iDevNum = 0; iDevNum <= ulMaxObjectNumber; iDevNum++)
{ {
/* Create the adapter's key name */ /* Create the adapter's key name */
@ -237,43 +260,29 @@ EngpUpdateGraphicsDeviceList(VOID)
/* Initialize the driver for this device */ /* Initialize the driver for this device */
pGraphicsDevice = InitDisplayDriver(awcDeviceName, awcBuffer); pGraphicsDevice = InitDisplayDriver(awcDeviceName, awcBuffer);
if (!pGraphicsDevice) continue; 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)
{
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 */ /* Close the device map registry key */
ZwClose(hkey); ZwClose(hkey);
/* Can we link VGA device to primary device? */ /* Choose a VGA device */
if (gpPrimaryGraphicsDevice && /* Try a device with DISPLAY_DEVICE_VGA_COMPATIBLE flag. If not found,
gpVgaGraphicsDevice && * fall back to current VGA device */
gpPrimaryGraphicsDevice != gpVgaGraphicsDevice && for (pGraphicsDevice = gpGraphicsDeviceFirst;
!gpPrimaryGraphicsDevice->pVgaDevice) pGraphicsDevice;
pGraphicsDevice = pGraphicsDevice->pNextGraphicsDevice)
{ {
/* Yes. Remove VGA device from global list, and attach it to primary device */ if (pGraphicsDevice == gpVgaGraphicsDevice)
TRACE("Linking VGA device %S to primary device %S\n", gpVgaGraphicsDevice->szNtDeviceName, gpPrimaryGraphicsDevice->szNtDeviceName); continue;
EngpUnlinkGraphicsDevice(gpVgaGraphicsDevice); if (pGraphicsDevice->StateFlags & DISPLAY_DEVICE_VGA_COMPATIBLE && EngpIsVgaDevice(pGraphicsDevice))
gpPrimaryGraphicsDevice->pVgaDevice = gpVgaGraphicsDevice; {
gpVgaGraphicsDevice = pGraphicsDevice;
break;
}
} }
if (bFoundNewDevice && gbBaseVideo) /* Handle gbBaseVideo */
if (gbBaseVideo)
{ {
PGRAPHICS_DEVICE pToDelete; PGRAPHICS_DEVICE pToDelete;
@ -307,6 +316,42 @@ EngpUpdateGraphicsDeviceList(VOID)
EngReleaseSemaphore(ghsemGraphicsDeviceList); 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; return STATUS_SUCCESS;
} }

View file

@ -543,7 +543,7 @@ PDEVOBJ_Create(
{ {
RtlCopyMemory(ppdev->pdmwDev, pdm, pdm->dmSize + pdm->dmDriverExtra); RtlCopyMemory(ppdev->pdmwDev, pdm, pdm->dmSize + pdm->dmDriverExtra);
/* FIXME: this must be done in a better way */ /* 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;
} }
} }

View file

@ -171,17 +171,8 @@ InitVideo(VOID)
/* Check if we had any success */ /* Check if we had any success */
if (!gpPrimaryGraphicsDevice) if (!gpPrimaryGraphicsDevice)
{ {
/* Check if there is a VGA device we skipped */ ERR("No usable display driver was found.\n");
if (gpVgaGraphicsDevice) return STATUS_UNSUCCESSFUL;
{
/* There is, use the VGA device */
gpPrimaryGraphicsDevice = gpVgaGraphicsDevice;
}
else
{
ERR("No usable display driver was found.\n");
return STATUS_UNSUCCESSFUL;
}
} }
InitSysParams(); InitSysParams();