Store real parameters registry key in DEVICEMAP\VIDEO

Use it in win32k when loading and storing settings (SetupDevMode and IntChangeDisplaySettings)

svn path=/trunk/; revision=22169
This commit is contained in:
Hervé Poussineau
2006-06-01 21:45:50 +00:00
parent e4c46fec65
commit 9e908fc097
2 changed files with 284 additions and 166 deletions
+102 -10
View File
@@ -130,6 +130,94 @@ IntVideoPortDeferredRoutine(
((PMINIPORT_DPC_ROUTINE)SystemArgument1)(HwDeviceExtension, SystemArgument2);
}
NTSTATUS
IntCreateRegistryPath(
IN PCUNICODE_STRING DriverRegistryPath,
OUT PUNICODE_STRING DeviceRegistryPath)
{
static WCHAR RegistryMachineSystem[] = L"\\REGISTRY\\MACHINE\\SYSTEM\\";
static WCHAR CurrentControlSet[] = L"CURRENTCONTROLSET\\";
static WCHAR ControlSet[] = L"CONTROLSET";
static WCHAR Insert1[] = L"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
static WCHAR Insert2[] = L"\\Device0";
LPWSTR ProfilePath = NULL;
BOOLEAN Valid;
PWCHAR AfterControlSet;
Valid = (0 == _wcsnicmp(DriverRegistryPath->Buffer, RegistryMachineSystem,
wcslen(RegistryMachineSystem)));
{
AfterControlSet = DriverRegistryPath->Buffer + wcslen(RegistryMachineSystem);
if (0 == _wcsnicmp(AfterControlSet, CurrentControlSet, wcslen(CurrentControlSet)))
{
AfterControlSet += wcslen(CurrentControlSet);
}
else if (0 == _wcsnicmp(AfterControlSet, ControlSet, wcslen(ControlSet)))
{
AfterControlSet += wcslen(ControlSet);
while (L'0' <= *AfterControlSet && L'9' <= *AfterControlSet)
{
AfterControlSet++;
}
Valid = (L'\\' == *AfterControlSet);
AfterControlSet++;
}
else
{
Valid = FALSE;
}
}
if (Valid)
{
ProfilePath = ExAllocatePoolWithTag(PagedPool,
(wcslen(DriverRegistryPath->Buffer) +
wcslen(Insert1) + wcslen(Insert2) + 1) * sizeof(WCHAR),
TAG_VIDEO_PORT);
if (NULL != ProfilePath)
{
wcsncpy(ProfilePath, DriverRegistryPath->Buffer, AfterControlSet - DriverRegistryPath->Buffer);
wcscpy(ProfilePath + (AfterControlSet - DriverRegistryPath->Buffer), Insert1);
wcscat(ProfilePath, AfterControlSet);
wcscat(ProfilePath, Insert2);
Valid = NT_SUCCESS(RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE, ProfilePath));
}
else
{
Valid = FALSE;
}
}
else
{
DPRINT1("Unparsable registry path %wZ", DriverRegistryPath);
}
if (Valid)
{
RtlInitUnicodeString(DeviceRegistryPath, ProfilePath);
}
else
{
if (ProfilePath)
ExFreePoolWithTag(ProfilePath, TAG_VIDEO_PORT);
DeviceRegistryPath->Length =
DeviceRegistryPath->MaximumLength =
DriverRegistryPath->Length + (9 * sizeof(WCHAR));
DeviceRegistryPath->Length -= sizeof(WCHAR);
DeviceRegistryPath->Buffer = ExAllocatePoolWithTag(
NonPagedPool,
DeviceRegistryPath->MaximumLength,
TAG_VIDEO_PORT);
if (!DeviceRegistryPath->Buffer)
return STATUS_NO_MEMORY;
swprintf(DeviceRegistryPath->Buffer, L"%s\\Device0",
DriverRegistryPath->Buffer);
}
return STATUS_SUCCESS;
}
NTSTATUS NTAPI
IntVideoPortCreateAdapterDeviceObject(
IN PDRIVER_OBJECT DriverObject,
@@ -203,16 +291,20 @@ IntVideoPortCreateAdapterDeviceObject(
DeviceExtension->FunctionalDeviceObject = *DeviceObject;
DeviceExtension->DriverExtension = DriverExtension;
DeviceExtension->RegistryPath.Length =
DeviceExtension->RegistryPath.MaximumLength =
DriverExtension->RegistryPath.Length + (9 * sizeof(WCHAR));
DeviceExtension->RegistryPath.Length -= sizeof(WCHAR);
DeviceExtension->RegistryPath.Buffer = ExAllocatePoolWithTag(
NonPagedPool,
DeviceExtension->RegistryPath.MaximumLength,
TAG_VIDEO_PORT);
swprintf(DeviceExtension->RegistryPath.Buffer, L"%s\\Device0",
DriverExtension->RegistryPath.Buffer);
/*
* Get the registry path associated with this driver.
*/
Status = IntCreateRegistryPath(
&DriverExtension->RegistryPath,
&DeviceExtension->RegistryPath);
if (!NT_SUCCESS(Status))
{
DPRINT("IntCreateRegistryPath() call failed with status 0x%08x\n", Status);
IoDeleteDevice(*DeviceObject);
*DeviceObject = NULL;
return Status;
}
if (PhysicalDeviceObject != NULL)
{
+182 -156
View File
@@ -265,14 +265,14 @@ NtGdiCreateCompatibleDC(HDC hDC)
return hNewDC;
}
static BOOL FASTCALL
static BOOLEAN FASTCALL
GetRegistryPath(PUNICODE_STRING RegistryPath, ULONG DisplayNumber)
{
RTL_QUERY_REGISTRY_TABLE QueryTable[2];
WCHAR DeviceNameBuffer[20];
NTSTATUS Status;
swprintf(DeviceNameBuffer, L"\\Device\\Video%d", DisplayNumber);
swprintf(DeviceNameBuffer, L"\\Device\\Video%lu", DisplayNumber);
RtlInitUnicodeString(RegistryPath, NULL);
RtlZeroMemory(QueryTable, sizeof(QueryTable));
QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_DIRECT;
@@ -286,11 +286,11 @@ GetRegistryPath(PUNICODE_STRING RegistryPath, ULONG DisplayNumber)
NULL);
if (! NT_SUCCESS(Status))
{
DPRINT1("No \\Device\\Video%d value in DEVICEMAP\\VIDEO found\n", DisplayNumber);
DPRINT1("No \\Device\\Video%lu value in DEVICEMAP\\VIDEO found\n", DisplayNumber);
return FALSE;
}
DPRINT("RegistryPath %S\n", RegistryPath->Buffer);
DPRINT("RegistryPath %wZ\n", RegistryPath);
return TRUE;
}
@@ -381,103 +381,48 @@ DevModeCallback(IN PWSTR ValueName,
static BOOL FASTCALL
SetupDevMode(PDEVMODEW DevMode, ULONG DisplayNumber)
{
static WCHAR RegistryMachineSystem[] = L"\\REGISTRY\\MACHINE\\SYSTEM\\";
static WCHAR CurrentControlSet[] = L"CURRENTCONTROLSET\\";
static WCHAR ControlSet[] = L"CONTROLSET";
static WCHAR Insert[] = L"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
UNICODE_STRING RegistryPath;
BOOL Valid;
PWCHAR AfterControlSet;
PWCHAR ProfilePath;
RTL_QUERY_REGISTRY_TABLE QueryTable[2];
NTSTATUS Status;
BOOLEAN Valid = TRUE;
if (! GetRegistryPath(&RegistryPath, DisplayNumber))
if (!GetRegistryPath(&RegistryPath, DisplayNumber))
{
DPRINT("GetRegistryPath failed\n");
return FALSE;
}
Valid = (0 == _wcsnicmp(RegistryPath.Buffer, RegistryMachineSystem,
wcslen(RegistryMachineSystem)));
if (Valid)
RtlZeroMemory(QueryTable, sizeof(QueryTable));
QueryTable[0].QueryRoutine = DevModeCallback;
QueryTable[0].Flags = 0;
QueryTable[0].Name = NULL;
QueryTable[0].EntryContext = NULL;
QueryTable[0].DefaultType = REG_NONE;
QueryTable[0].DefaultData = NULL;
QueryTable[0].DefaultLength = 0;
Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
RegistryPath.Buffer,
QueryTable,
DevMode,
NULL);
if (! NT_SUCCESS(Status))
{
AfterControlSet = RegistryPath.Buffer + wcslen(RegistryMachineSystem);
if (0 == _wcsnicmp(AfterControlSet, CurrentControlSet, wcslen(CurrentControlSet)))
{
AfterControlSet += wcslen(CurrentControlSet);
}
else if (0 == _wcsnicmp(AfterControlSet, ControlSet, wcslen(ControlSet)))
{
AfterControlSet += wcslen(ControlSet);
while (L'0' <= *AfterControlSet && L'9' <= *AfterControlSet)
{
AfterControlSet++;
}
Valid = (L'\\' == *AfterControlSet);
AfterControlSet++;
}
else
{
Valid = FALSE;
}
}
if (Valid)
{
ProfilePath = ExAllocatePoolWithTag(PagedPool,
(wcslen(RegistryPath.Buffer) +
wcslen(Insert) + 1) * sizeof(WCHAR),
TAG_DC);
if (NULL != ProfilePath)
{
wcsncpy(ProfilePath, RegistryPath.Buffer, AfterControlSet - RegistryPath.Buffer);
wcscpy(ProfilePath + (AfterControlSet - RegistryPath.Buffer), Insert);
wcscat(ProfilePath, AfterControlSet);
RtlZeroMemory(QueryTable, sizeof(QueryTable));
QueryTable[0].QueryRoutine = DevModeCallback;
QueryTable[0].Flags = 0;
QueryTable[0].Name = NULL;
QueryTable[0].EntryContext = NULL;
QueryTable[0].DefaultType = REG_NONE;
QueryTable[0].DefaultData = NULL;
QueryTable[0].DefaultLength = 0;
Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
ProfilePath,
QueryTable,
DevMode,
NULL);
if (! NT_SUCCESS(Status))
{
DPRINT("RtlQueryRegistryValues for %S failed with status 0x%08x\n",
ProfilePath, Status);
Valid = FALSE;
}
else
{
DPRINT("dmBitsPerPel %d dmDisplayFrequency %d dmPelsWidth %d dmPelsHeight %d\n",
DevMode->dmBitsPerPel, DevMode->dmDisplayFrequency,
DevMode->dmPelsWidth, DevMode->dmPelsHeight);
if (0 == DevMode->dmBitsPerPel || 0 == DevMode->dmDisplayFrequency
|| 0 == DevMode->dmPelsWidth || 0 == DevMode->dmPelsHeight)
{
DPRINT("Not all required devmode members are set\n");
Valid = FALSE;
}
}
ExFreePool(ProfilePath);
}
else
{
Valid = FALSE;
}
DPRINT("RtlQueryRegistryValues for %wZ failed with status 0x%08x\n",
&RegistryPath, Status);
Valid = FALSE;
}
else
{
DPRINT1("Unparsable registry path %S in DEVICEMAP\\VIDEO0", RegistryPath.Buffer);
DPRINT("dmBitsPerPel %d dmDisplayFrequency %d dmPelsWidth %d dmPelsHeight %d\n",
DevMode->dmBitsPerPel, DevMode->dmDisplayFrequency,
DevMode->dmPelsWidth, DevMode->dmPelsHeight);
if (0 == DevMode->dmBitsPerPel || 0 == DevMode->dmDisplayFrequency
|| 0 == DevMode->dmPelsWidth || 0 == DevMode->dmPelsHeight)
{
DPRINT("Not all required devmode members are set\n");
Valid = FALSE;
}
}
RtlFreeUnicodeString(&RegistryPath);
@@ -2734,6 +2679,137 @@ IntEnumDisplaySettings(
return TRUE;
}
static NTSTATUS FASTCALL
GetVideoDeviceName(
OUT PUNICODE_STRING VideoDeviceName,
IN PCUNICODE_STRING DisplayDevice) /* ex: "\.\DISPLAY1" or "\??\DISPLAY1" */
{
UNICODE_STRING Prefix = RTL_CONSTANT_STRING(L"\\??\\");
UNICODE_STRING ObjectName;
UNICODE_STRING KernelModeName = { 0, };
OBJECT_ATTRIBUTES ObjectAttributes;
USHORT LastSlash;
ULONG Length;
HANDLE LinkHandle = NULL;
NTSTATUS Status;
RtlInitUnicodeString(VideoDeviceName, NULL);
/* Get device name (DisplayDevice is "\.\xxx") */
for (LastSlash = DisplayDevice->Length / sizeof(WCHAR); LastSlash > 0; LastSlash--)
{
if (DisplayDevice->Buffer[LastSlash - 1] == L'\\')
break;
}
if (LastSlash == 0)
{
DPRINT1("Invalid device name '%wZ'\n", DisplayDevice);
Status = STATUS_OBJECT_NAME_INVALID;
goto cleanup;
}
ObjectName = *DisplayDevice;
ObjectName.Length -= LastSlash * sizeof(WCHAR);
ObjectName.MaximumLength -= LastSlash * sizeof(WCHAR);
ObjectName.Buffer += LastSlash;
/* Create "\??\xxx" (ex: "\??\DISPLAY1") */
KernelModeName.MaximumLength = Prefix.Length + ObjectName.Length + sizeof(UNICODE_NULL);
KernelModeName.Buffer = ExAllocatePoolWithTag(PagedPool,
KernelModeName.MaximumLength,
TAG_DC);
if (!KernelModeName.Buffer)
{
Status = STATUS_NO_MEMORY;
goto cleanup;
}
RtlCopyUnicodeString(&KernelModeName, &Prefix);
Status = RtlAppendUnicodeStringToString(&KernelModeName, &ObjectName);
if (!NT_SUCCESS(Status))
goto cleanup;
/* Open \??\xxx (ex: "\??\DISPLAY1") */
InitializeObjectAttributes(&ObjectAttributes,
&KernelModeName,
OBJ_KERNEL_HANDLE,
NULL,
NULL);
Status = ZwOpenSymbolicLinkObject(&LinkHandle,
GENERIC_READ,
&ObjectAttributes);
if (!NT_SUCCESS(Status))
{
DPRINT1("Unable to open symbolic link %wZ (Status 0x%08lx)\n", &KernelModeName, Status);
Status = STATUS_NO_SUCH_DEVICE;
goto cleanup;
}
Status = ZwQuerySymbolicLinkObject(LinkHandle, VideoDeviceName, &Length);
if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL)
{
DPRINT1("Unable to query symbolic link %wZ (Status 0x%08lx)\n", &KernelModeName, Status);
Status = STATUS_NO_SUCH_DEVICE;
goto cleanup;
}
VideoDeviceName->MaximumLength = Length;
VideoDeviceName->Buffer = ExAllocatePoolWithTag(PagedPool,
VideoDeviceName->MaximumLength + sizeof(UNICODE_NULL),
TAG_DC);
if (!VideoDeviceName->Buffer)
{
Status = STATUS_NO_MEMORY;
goto cleanup;
}
Status = ZwQuerySymbolicLinkObject(LinkHandle, VideoDeviceName, NULL);
VideoDeviceName->Buffer[VideoDeviceName->MaximumLength / sizeof(WCHAR) - 1] = UNICODE_NULL;
if (!NT_SUCCESS(Status))
{
DPRINT1("Unable to query symbolic link %wZ (Status 0x%08lx)\n", &KernelModeName, Status);
Status = STATUS_NO_SUCH_DEVICE;
goto cleanup;
}
Status = STATUS_SUCCESS;
cleanup:
if (!NT_SUCCESS(Status) && VideoDeviceName->Buffer)
ExFreePoolWithTag(VideoDeviceName->Buffer, TAG_DC);
if (KernelModeName.Buffer)
ExFreePoolWithTag(KernelModeName.Buffer, TAG_DC);
if (LinkHandle)
ZwClose(LinkHandle);
return Status;
}
static NTSTATUS FASTCALL
GetVideoRegistryKey(
OUT PUNICODE_STRING RegistryPath,
IN PCUNICODE_STRING DeviceName) /* ex: "\Device\Video0" */
{
RTL_QUERY_REGISTRY_TABLE QueryTable[2];
NTSTATUS Status;
RtlInitUnicodeString(RegistryPath, NULL);
RtlZeroMemory(QueryTable, sizeof(QueryTable));
QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_DIRECT;
QueryTable[0].Name = DeviceName->Buffer;
QueryTable[0].EntryContext = RegistryPath;
Status = RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP,
L"VIDEO",
QueryTable,
NULL,
NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("No %wZ value in DEVICEMAP\\VIDEO found (Status 0x%08lx)\n", DeviceName, Status);
return STATUS_NO_SUCH_DEVICE;
}
DPRINT("RegistryPath %wZ\n", RegistryPath);
return STATUS_SUCCESS;
}
LONG
FASTCALL
IntChangeDisplaySettings(
@@ -2827,13 +2903,8 @@ IntChangeDisplaySettings(
if ((dwflags & CDS_UPDATEREGISTRY) == CDS_UPDATEREGISTRY)
{
UNICODE_STRING ObjectName;
UNICODE_STRING KernelModeName;
WCHAR KernelModeNameBuffer[256];
UNICODE_STRING DeviceName;
UNICODE_STRING RegistryKey;
WCHAR RegistryKeyBuffer[512];
PDEVICE_OBJECT DeviceObject;
ULONG LastSlash;
OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE DevInstRegKey;
ULONG NewValue;
@@ -2842,76 +2913,31 @@ IntChangeDisplaySettings(
dwflags &= ~CDS_UPDATEREGISTRY;
/* Get device name (pDeviceName is "\.\xxx") */
for (LastSlash = pDeviceName->Length / sizeof(WCHAR); LastSlash > 0; LastSlash--)
Status = GetVideoDeviceName(&DeviceName, pDeviceName);
if (!NT_SUCCESS(Status))
{
if (pDeviceName->Buffer[LastSlash - 1] == L'\\')
break;
DPRINT1("Unable to get destination of '%wZ' (Status 0x%08lx)\n", pDeviceName, Status);
return DISP_CHANGE_FAILED;
}
if (LastSlash == 0) return DISP_CHANGE_RESTART;
ObjectName = *pDeviceName;
ObjectName.Length -= LastSlash * sizeof(WCHAR);
ObjectName.MaximumLength -= LastSlash * sizeof(WCHAR);
ObjectName.Buffer += LastSlash;
KernelModeName.Length = 0;
KernelModeName.MaximumLength = sizeof(KernelModeNameBuffer);
KernelModeName.Buffer = KernelModeNameBuffer;
/* Open \??\xxx (ex: "\??\DISPLAY1") */
Status = RtlAppendUnicodeToString(&KernelModeName, L"\\??\\");
if (!NT_SUCCESS(Status)) return DISP_CHANGE_FAILED;
Status = RtlAppendUnicodeStringToString(&KernelModeName, &ObjectName);
if (!NT_SUCCESS(Status)) return DISP_CHANGE_FAILED;
Status = ObReferenceObjectByName(
&KernelModeName,
OBJ_CASE_INSENSITIVE,
NULL,
0,
IoDeviceObjectType,
KernelMode,
NULL,
(PVOID*)&DeviceObject);
if (!NT_SUCCESS(Status)) return DISP_CHANGE_FAILED;
/* Get associated driver name (ex: "VBE") */
for (LastSlash = DeviceObject->DriverObject->DriverName.Length / sizeof(WCHAR); LastSlash > 0; LastSlash--)
Status = GetVideoRegistryKey(&RegistryKey, &DeviceName);
if (!NT_SUCCESS(Status))
{
if (DeviceObject->DriverObject->DriverName.Buffer[LastSlash - 1] == L'\\')
break;
DPRINT1("Unable to get registry key for '%wZ' (Status 0x%08lx)\n", &DeviceName, Status);
ExFreePoolWithTag(DeviceName.Buffer, TAG_DC);
return DISP_CHANGE_FAILED;
}
if (LastSlash == 0) { ObDereferenceObject(DeviceObject); return DISP_CHANGE_FAILED; }
ObjectName = DeviceObject->DriverObject->DriverName;
ObjectName.Length -= LastSlash * sizeof(WCHAR);
ObjectName.MaximumLength -= LastSlash * sizeof(WCHAR);
ObjectName.Buffer += LastSlash;
RegistryKey.Length = 0;
RegistryKey.MaximumLength = sizeof(RegistryKeyBuffer);
RegistryKey.Buffer = RegistryKeyBuffer;
/* Open registry key */
Status = RtlAppendUnicodeToString(&RegistryKey,
L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Hardware Profiles\\Current\\System\\CurrentControlSet\\Services\\");
if (!NT_SUCCESS(Status)) { ObDereferenceObject(DeviceObject); return DISP_CHANGE_FAILED; }
Status = RtlAppendUnicodeStringToString(&RegistryKey, &ObjectName);
if (!NT_SUCCESS(Status)) { ObDereferenceObject(DeviceObject); return DISP_CHANGE_FAILED; }
Status = RtlAppendUnicodeToString(&RegistryKey,
L"\\Device0");
if (!NT_SUCCESS(Status)) { ObDereferenceObject(DeviceObject); return DISP_CHANGE_FAILED; }
ExFreePoolWithTag(DeviceName.Buffer, TAG_DC);
InitializeObjectAttributes(&ObjectAttributes, &RegistryKey,
OBJ_CASE_INSENSITIVE, NULL, NULL);
Status = ZwOpenKey(&DevInstRegKey, GENERIC_READ | GENERIC_WRITE, &ObjectAttributes);
ObDereferenceObject(DeviceObject);
if (!NT_SUCCESS(Status)) return DISP_CHANGE_FAILED;
if (!NT_SUCCESS(Status))
{
DPRINT1("Unable to open registry key %wZ (Status 0x%08lx)\n", &RegistryKey, Status);
ExFreePoolWithTag(RegistryKey.Buffer, TAG_DC);
return DISP_CHANGE_FAILED;
}
ExFreePoolWithTag(RegistryKey.Buffer, TAG_DC);
/* Update needed fields */
if (NT_SUCCESS(Status) && DevMode->dmFields & DM_BITSPERPEL)