[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.
This commit is contained in:
Hervé Poussineau 2022-10-22 14:37:50 +02:00
parent 0ecd997bdf
commit ea30b96334

View file

@ -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;
}