mirror of
https://github.com/reactos/reactos.git
synced 2024-09-06 10:52:52 +00:00
![Hermès Bélusca-Maïto](/assets/img/avatar_default.png)
This is done by creating the volatile key \Registry\Machine\System\CurrentControlSet\Control\GraphicsDrivers\BaseVideo . Also cache during first initialization of VIDEOPRT the state of the boot options BASEVIDEO and NOVESA, so that they can be readily retrieved later (for example, in VideoPortIsNoVesa()).
640 lines
23 KiB
C
640 lines
23 KiB
C
/*
|
|
* VideoPort driver
|
|
*
|
|
* Copyright (C) 2002-2004, 2007 ReactOS Team
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*
|
|
*/
|
|
|
|
#include "videoprt.h"
|
|
#include <ndk/obfuncs.h>
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
IntCopyRegistryKey(
|
|
_In_ HANDLE SourceKeyHandle,
|
|
_In_ HANDLE DestKeyHandle)
|
|
{
|
|
PVOID InfoBuffer;
|
|
PKEY_BASIC_INFORMATION KeyInformation;
|
|
PKEY_VALUE_FULL_INFORMATION KeyValueInformation;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
ULONG Index, InformationLength, RequiredLength;
|
|
UNICODE_STRING NameString;
|
|
NTSTATUS Status;
|
|
HANDLE SourceSubKeyHandle, DestSubKeyHandle;
|
|
|
|
/* Start with no buffer, set initial size */
|
|
InfoBuffer = NULL;
|
|
InformationLength = 256;
|
|
|
|
/* Start looping with key index 0 */
|
|
Index = 0;
|
|
while (TRUE)
|
|
{
|
|
/* Check if we have no buffer */
|
|
if (InfoBuffer == NULL)
|
|
{
|
|
/* Allocate a new buffer */
|
|
InfoBuffer = ExAllocatePoolWithTag(PagedPool,
|
|
InformationLength,
|
|
TAG_VIDEO_PORT_BUFFER);
|
|
if (InfoBuffer == NULL)
|
|
{
|
|
ERR_(VIDEOPRT, "Could not allocate buffer for key info\n");
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
}
|
|
|
|
/* Enumerate the next sub-key */
|
|
KeyInformation = InfoBuffer;
|
|
Status = ZwEnumerateKey(SourceKeyHandle,
|
|
Index,
|
|
KeyBasicInformation,
|
|
KeyInformation,
|
|
InformationLength,
|
|
&RequiredLength);
|
|
if ((Status == STATUS_BUFFER_OVERFLOW) ||
|
|
(Status == STATUS_BUFFER_TOO_SMALL))
|
|
{
|
|
/* Free the buffer and remember the required size */
|
|
ExFreePoolWithTag(InfoBuffer, TAG_VIDEO_PORT_BUFFER);
|
|
InfoBuffer = NULL;
|
|
InformationLength = RequiredLength;
|
|
|
|
/* Try again */
|
|
continue;
|
|
}
|
|
else if (Status == STATUS_NO_MORE_ENTRIES)
|
|
{
|
|
/* We are done with the sub-keys */
|
|
break;
|
|
}
|
|
else if (!NT_SUCCESS(Status))
|
|
{
|
|
ERR_(VIDEOPRT, "ZwEnumerateKey failed, status 0x%lx\n", Status);
|
|
goto Cleanup;
|
|
}
|
|
|
|
/* Initialize a unicode string from the key name */
|
|
NameString.Buffer = KeyInformation->Name;
|
|
NameString.Length = (USHORT)KeyInformation->NameLength;
|
|
NameString.MaximumLength = NameString.Length;
|
|
|
|
/* Initialize object attributes and open the source sub-key */
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&NameString,
|
|
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
|
|
SourceKeyHandle,
|
|
NULL);
|
|
Status = ZwOpenKey(&SourceSubKeyHandle, KEY_READ, &ObjectAttributes);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
ERR_(VIDEOPRT, "failed to open the source key.\n");
|
|
goto Cleanup;
|
|
}
|
|
|
|
/* Initialize object attributes and create the dest sub-key */
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&NameString,
|
|
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
|
|
DestKeyHandle,
|
|
NULL);
|
|
Status = ZwCreateKey(&DestSubKeyHandle,
|
|
KEY_WRITE,
|
|
&ObjectAttributes,
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
ERR_(VIDEOPRT, "failed to create the destination key.\n");
|
|
ObCloseHandle(SourceSubKeyHandle, KernelMode);
|
|
goto Cleanup;
|
|
}
|
|
|
|
/* Recursively copy the sub-key */
|
|
Status = IntCopyRegistryKey(SourceSubKeyHandle, DestSubKeyHandle);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
/* Just warn, but continue with the remaining sub-keys */
|
|
WARN_(VIDEOPRT, "failed to copy subkey '%wZ'.\n", &NameString);
|
|
}
|
|
|
|
/* Close the sub-key handles */
|
|
ObCloseHandle(SourceSubKeyHandle, KernelMode);
|
|
ObCloseHandle(DestSubKeyHandle, KernelMode);
|
|
|
|
/* Next sub-key */
|
|
Index++;
|
|
}
|
|
|
|
/* Start looping with value index 0 */
|
|
Index = 0;
|
|
while (TRUE)
|
|
{
|
|
/* Check if we have no buffer */
|
|
if (InfoBuffer == NULL)
|
|
{
|
|
/* Allocate a new buffer */
|
|
InfoBuffer = ExAllocatePoolWithTag(PagedPool,
|
|
InformationLength,
|
|
TAG_VIDEO_PORT_BUFFER);
|
|
if (InfoBuffer == NULL)
|
|
{
|
|
ERR_(VIDEOPRT, "Could not allocate buffer for key values\n");
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
/* Enumerate the next value */
|
|
KeyValueInformation = InfoBuffer;
|
|
Status = ZwEnumerateValueKey(SourceKeyHandle,
|
|
Index,
|
|
KeyValueFullInformation,
|
|
KeyValueInformation,
|
|
InformationLength,
|
|
&RequiredLength);
|
|
if ((Status == STATUS_BUFFER_OVERFLOW) ||
|
|
(Status == STATUS_BUFFER_TOO_SMALL))
|
|
{
|
|
/* Free the buffer and remember the required size */
|
|
ExFreePoolWithTag(InfoBuffer, TAG_VIDEO_PORT_BUFFER);
|
|
InfoBuffer = NULL;
|
|
InformationLength = RequiredLength;
|
|
|
|
/* Try again */
|
|
continue;
|
|
}
|
|
else if (Status == STATUS_NO_MORE_ENTRIES)
|
|
{
|
|
/* We are done with the values */
|
|
Status = STATUS_SUCCESS;
|
|
break;
|
|
}
|
|
else if (!NT_SUCCESS(Status))
|
|
{
|
|
ERR_(VIDEOPRT, "ZwEnumerateValueKey failed, status 0x%lx\n", Status);
|
|
goto Cleanup;
|
|
}
|
|
|
|
/* Initialize a unicode string from the value name */
|
|
NameString.Buffer = KeyValueInformation->Name;
|
|
NameString.Length = (USHORT)KeyValueInformation->NameLength;
|
|
NameString.MaximumLength = NameString.Length;
|
|
|
|
/* Create the key value in the destination key */
|
|
Status = ZwSetValueKey(DestKeyHandle,
|
|
&NameString,
|
|
KeyValueInformation->TitleIndex,
|
|
KeyValueInformation->Type,
|
|
(PUCHAR)KeyValueInformation + KeyValueInformation->DataOffset,
|
|
KeyValueInformation->DataLength);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
/* Just warn, but continue with the remaining sub-keys */
|
|
WARN_(VIDEOPRT, "failed to set value '%wZ'.\n", &NameString);
|
|
}
|
|
|
|
/* Next subkey */
|
|
Index++;
|
|
}
|
|
|
|
Cleanup:
|
|
/* Free the buffer and return the failure code */
|
|
if (InfoBuffer != NULL)
|
|
ExFreePoolWithTag(InfoBuffer, TAG_VIDEO_PORT_BUFFER);
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
IntCopyRegistryValue(
|
|
HANDLE SourceKeyHandle,
|
|
HANDLE DestKeyHandle,
|
|
PWSTR ValueName)
|
|
{
|
|
PKEY_VALUE_PARTIAL_INFORMATION ValueInformation;
|
|
UNICODE_STRING ValueNameString;
|
|
ULONG Length;
|
|
NTSTATUS Status;
|
|
|
|
RtlInitUnicodeString(&ValueNameString, ValueName);
|
|
|
|
/* Query the value length */
|
|
Status = ZwQueryValueKey(SourceKeyHandle,
|
|
&ValueNameString,
|
|
KeyValuePartialInformation,
|
|
NULL,
|
|
0,
|
|
&Length);
|
|
if ((Status != STATUS_BUFFER_OVERFLOW) &&
|
|
(Status != STATUS_BUFFER_TOO_SMALL))
|
|
{
|
|
/* The key seems not present */
|
|
NT_ASSERT(!NT_SUCCESS(Status));
|
|
return Status;
|
|
}
|
|
|
|
/* Allocate a buffer */
|
|
ValueInformation = ExAllocatePoolWithTag(PagedPool, Length, TAG_VIDEO_PORT_BUFFER);
|
|
if (ValueInformation == NULL)
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
/* Query the value */
|
|
Status = ZwQueryValueKey(SourceKeyHandle,
|
|
&ValueNameString,
|
|
KeyValuePartialInformation,
|
|
ValueInformation,
|
|
Length,
|
|
&Length);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
ExFreePoolWithTag(ValueInformation, TAG_VIDEO_PORT_BUFFER);
|
|
return Status;
|
|
}
|
|
|
|
/* Write the registry value */
|
|
Status = ZwSetValueKey(DestKeyHandle,
|
|
&ValueNameString,
|
|
ValueInformation->TitleIndex,
|
|
ValueInformation->Type,
|
|
ValueInformation->Data,
|
|
ValueInformation->DataLength);
|
|
|
|
ExFreePoolWithTag(ValueInformation, TAG_VIDEO_PORT_BUFFER);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
ERR_(VIDEOPRT, "ZwSetValueKey failed: status 0x%lx\n", Status);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
IntSetupDeviceSettingsKey(
|
|
PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension)
|
|
{
|
|
static UNICODE_STRING SettingsKeyName = RTL_CONSTANT_STRING(L"Settings");
|
|
HANDLE DevInstRegKey, SourceKeyHandle, DestKeyHandle;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
NTSTATUS Status;
|
|
|
|
/* Open the software key: HKLM\System\CurrentControlSet\Control\Class\<ClassGUID>\<n> */
|
|
Status = IoOpenDeviceRegistryKey(DeviceExtension->PhysicalDeviceObject,
|
|
PLUGPLAY_REGKEY_DRIVER,
|
|
KEY_ALL_ACCESS,
|
|
&DevInstRegKey);
|
|
if (Status != STATUS_SUCCESS)
|
|
{
|
|
ERR_(VIDEOPRT, "Failed to open device software key. Status 0x%lx\n", Status);
|
|
return Status;
|
|
}
|
|
|
|
/* Open the 'Settings' sub-key */
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&SettingsKeyName,
|
|
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
|
|
DevInstRegKey,
|
|
NULL);
|
|
Status = ZwOpenKey(&DestKeyHandle, KEY_WRITE, &ObjectAttributes);
|
|
|
|
/* Close the device software key */
|
|
ObCloseHandle(DevInstRegKey, KernelMode);
|
|
|
|
if (Status != STATUS_SUCCESS)
|
|
{
|
|
ERR_(VIDEOPRT, "Failed to open settings key. Status 0x%lx\n", Status);
|
|
return Status;
|
|
}
|
|
|
|
/* Open the device profile key */
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&DeviceExtension->RegistryPath,
|
|
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL);
|
|
Status = ZwOpenKey(&SourceKeyHandle, KEY_WRITE, &ObjectAttributes);
|
|
if (Status != STATUS_SUCCESS)
|
|
{
|
|
ERR_(VIDEOPRT, "ZwOpenKey failed for settings key: status 0x%lx\n", Status);
|
|
ObCloseHandle(DestKeyHandle, KernelMode);
|
|
return Status;
|
|
}
|
|
|
|
IntCopyRegistryValue(SourceKeyHandle, DestKeyHandle, L"InstalledDisplayDrivers");
|
|
IntCopyRegistryValue(SourceKeyHandle, DestKeyHandle, L"Attach.ToDesktop");
|
|
|
|
ObCloseHandle(SourceKeyHandle, KernelMode);
|
|
ObCloseHandle(DestKeyHandle, KernelMode);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
IntCreateNewRegistryPath(
|
|
PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension)
|
|
{
|
|
static UNICODE_STRING VideoIdValueName = RTL_CONSTANT_STRING(L"VideoId");
|
|
static UNICODE_STRING ControlVideoPathName =
|
|
RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Video\\");
|
|
HANDLE DevInstRegKey, SettingsKey, NewKey;
|
|
UCHAR VideoIdBuffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + GUID_STRING_LENGTH];
|
|
UNICODE_STRING VideoIdString;
|
|
UUID VideoId;
|
|
PKEY_VALUE_PARTIAL_INFORMATION ValueInformation ;
|
|
NTSTATUS Status;
|
|
ULONG ResultLength;
|
|
USHORT KeyMaxLength;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
|
|
/* Open the hardware key: HKLM\System\CurrentControlSet\Enum\... */
|
|
Status = IoOpenDeviceRegistryKey(DeviceExtension->PhysicalDeviceObject,
|
|
PLUGPLAY_REGKEY_DEVICE,
|
|
KEY_ALL_ACCESS,
|
|
&DevInstRegKey);
|
|
if (Status != STATUS_SUCCESS)
|
|
{
|
|
ERR_(VIDEOPRT, "IoOpenDeviceRegistryKey failed: status 0x%lx\n", Status);
|
|
return Status;
|
|
}
|
|
|
|
/* Query the VideoId value */
|
|
ValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION)VideoIdBuffer;
|
|
Status = ZwQueryValueKey(DevInstRegKey,
|
|
&VideoIdValueName,
|
|
KeyValuePartialInformation,
|
|
ValueInformation,
|
|
sizeof(VideoIdBuffer),
|
|
&ResultLength);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
/* Create a new video Id */
|
|
Status = ExUuidCreate(&VideoId);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
ERR_(VIDEOPRT, "ExUuidCreate failed: status 0x%lx\n", Status);
|
|
ObCloseHandle(DevInstRegKey, KernelMode);
|
|
return Status;
|
|
}
|
|
|
|
/* Convert the GUID into a string */
|
|
Status = RtlStringFromGUID(&VideoId, &VideoIdString);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
ERR_(VIDEOPRT, "RtlStringFromGUID failed: status 0x%lx\n", Status);
|
|
ObCloseHandle(DevInstRegKey, KernelMode);
|
|
return Status;
|
|
}
|
|
|
|
/* Copy the GUID String to our buffer */
|
|
ValueInformation->DataLength = min(VideoIdString.Length, GUID_STRING_LENGTH);
|
|
RtlCopyMemory(ValueInformation->Data,
|
|
VideoIdString.Buffer,
|
|
ValueInformation->DataLength);
|
|
|
|
/* Free the GUID string */
|
|
RtlFreeUnicodeString(&VideoIdString);
|
|
|
|
/* Write the VideoId registry value */
|
|
Status = ZwSetValueKey(DevInstRegKey,
|
|
&VideoIdValueName,
|
|
0,
|
|
REG_SZ,
|
|
ValueInformation->Data,
|
|
ValueInformation->DataLength);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
ERR_(VIDEOPRT, "ZwSetValueKey failed: status 0x%lx\n", Status);
|
|
ObCloseHandle(DevInstRegKey, KernelMode);
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
/* Initialize the VideoId string from the registry data */
|
|
VideoIdString.Buffer = (PWCHAR)ValueInformation->Data;
|
|
VideoIdString.Length = (USHORT)ValueInformation->DataLength;
|
|
VideoIdString.MaximumLength = VideoIdString.Length;
|
|
|
|
/* Close the hardware key */
|
|
ObCloseHandle(DevInstRegKey, KernelMode);
|
|
|
|
/* Calculate the size needed for the new registry path name */
|
|
KeyMaxLength = ControlVideoPathName.Length +
|
|
VideoIdString.Length +
|
|
sizeof(L"\\0000");
|
|
|
|
/* Allocate the path name buffer */
|
|
DeviceExtension->NewRegistryPath.Length = 0;
|
|
DeviceExtension->NewRegistryPath.MaximumLength = KeyMaxLength;
|
|
DeviceExtension->NewRegistryPath.Buffer = ExAllocatePoolWithTag(PagedPool,
|
|
KeyMaxLength,
|
|
TAG_VIDEO_PORT);
|
|
if (DeviceExtension->NewRegistryPath.Buffer == NULL)
|
|
{
|
|
ERR_(VIDEOPRT, "Failed to allocate key name buffer.\n");
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
/* Copy the root key name and append the VideoId string */
|
|
RtlCopyUnicodeString(&DeviceExtension->NewRegistryPath,
|
|
&ControlVideoPathName);
|
|
RtlAppendUnicodeStringToString(&DeviceExtension->NewRegistryPath,
|
|
&VideoIdString);
|
|
|
|
/* Check if we have the key already */
|
|
Status = RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE,
|
|
DeviceExtension->NewRegistryPath.Buffer);
|
|
if (Status != STATUS_SUCCESS)
|
|
{
|
|
/* Try to create the new key */
|
|
Status = RtlCreateRegistryKey(RTL_REGISTRY_ABSOLUTE,
|
|
DeviceExtension->NewRegistryPath.Buffer);
|
|
}
|
|
|
|
/* Append a the instance path */ /// \todo HACK
|
|
RtlAppendUnicodeToString(&DeviceExtension->NewRegistryPath, L"\\");
|
|
RtlAppendUnicodeToString(&DeviceExtension->NewRegistryPath, L"0000");
|
|
|
|
/* Check this key again */
|
|
Status = RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE,
|
|
DeviceExtension->NewRegistryPath.Buffer);
|
|
if (Status != STATUS_SUCCESS)
|
|
{
|
|
/* Try to create the new key */
|
|
Status = RtlCreateRegistryKey(RTL_REGISTRY_ABSOLUTE,
|
|
DeviceExtension->NewRegistryPath.Buffer);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
ERR_(VIDEOPRT, "Failed create key '%wZ'\n", &DeviceExtension->NewRegistryPath);
|
|
return Status;
|
|
}
|
|
|
|
/* Open the new key */
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&DeviceExtension->NewRegistryPath,
|
|
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL);
|
|
Status = ZwOpenKey(&NewKey, KEY_READ, &ObjectAttributes);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
ERR_(VIDEOPRT, "Failed to open settings key. Status 0x%lx\n", Status);
|
|
return Status;
|
|
}
|
|
|
|
/* Open the device profile key */
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&DeviceExtension->RegistryPath,
|
|
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL);
|
|
Status = ZwOpenKey(&SettingsKey, KEY_READ, &ObjectAttributes);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
ERR_(VIDEOPRT, "Failed to open settings key. Status 0x%lx\n", Status);
|
|
ObCloseHandle(NewKey, KernelMode);
|
|
return Status;
|
|
}
|
|
|
|
/* Copy the registry data from the legacy key */
|
|
Status = IntCopyRegistryKey(SettingsKey, NewKey);
|
|
}
|
|
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
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";
|
|
BOOLEAN Valid;
|
|
UNICODE_STRING AfterControlSet;
|
|
|
|
AfterControlSet = *DriverRegistryPath;
|
|
|
|
/* Check if path begins with \\REGISTRY\\MACHINE\\SYSTEM\\ */
|
|
Valid = (DriverRegistryPath->Length > sizeof(RegistryMachineSystem) &&
|
|
0 == _wcsnicmp(DriverRegistryPath->Buffer, RegistryMachineSystem,
|
|
wcslen(RegistryMachineSystem)));
|
|
if (Valid)
|
|
{
|
|
AfterControlSet.Buffer += wcslen(RegistryMachineSystem);
|
|
AfterControlSet.Length -= sizeof(RegistryMachineSystem) - sizeof(UNICODE_NULL);
|
|
|
|
/* Check if path contains CURRENTCONTROLSET */
|
|
if (AfterControlSet.Length > sizeof(CurrentControlSet) &&
|
|
0 == _wcsnicmp(AfterControlSet.Buffer, CurrentControlSet, wcslen(CurrentControlSet)))
|
|
{
|
|
AfterControlSet.Buffer += wcslen(CurrentControlSet);
|
|
AfterControlSet.Length -= sizeof(CurrentControlSet) - sizeof(UNICODE_NULL);
|
|
}
|
|
/* Check if path contains CONTROLSETnum */
|
|
else if (AfterControlSet.Length > sizeof(ControlSet) &&
|
|
0 == _wcsnicmp(AfterControlSet.Buffer, ControlSet, wcslen(ControlSet)))
|
|
{
|
|
AfterControlSet.Buffer += wcslen(ControlSet);
|
|
AfterControlSet.Length -= sizeof(ControlSet) - sizeof(UNICODE_NULL);
|
|
while (AfterControlSet.Length > 0 &&
|
|
*AfterControlSet.Buffer >= L'0' &&
|
|
*AfterControlSet.Buffer <= L'9')
|
|
{
|
|
AfterControlSet.Buffer++;
|
|
AfterControlSet.Length -= sizeof(WCHAR);
|
|
}
|
|
|
|
Valid = (AfterControlSet.Length > 0 && L'\\' == *AfterControlSet.Buffer);
|
|
AfterControlSet.Buffer++;
|
|
AfterControlSet.Length -= sizeof(WCHAR);
|
|
AfterControlSet.MaximumLength = AfterControlSet.Length;
|
|
}
|
|
else
|
|
{
|
|
Valid = FALSE;
|
|
}
|
|
}
|
|
|
|
if (Valid)
|
|
{
|
|
DeviceRegistryPath->MaximumLength = DriverRegistryPath->Length + sizeof(Insert1) + sizeof(Insert2);
|
|
DeviceRegistryPath->Buffer = ExAllocatePoolWithTag(PagedPool,
|
|
DeviceRegistryPath->MaximumLength,
|
|
TAG_VIDEO_PORT);
|
|
if (DeviceRegistryPath->Buffer != NULL)
|
|
{
|
|
/* Build device path */
|
|
wcsncpy(DeviceRegistryPath->Buffer,
|
|
DriverRegistryPath->Buffer,
|
|
AfterControlSet.Buffer - DriverRegistryPath->Buffer);
|
|
DeviceRegistryPath->Length = (AfterControlSet.Buffer - DriverRegistryPath->Buffer) * sizeof(WCHAR);
|
|
RtlAppendUnicodeToString(DeviceRegistryPath, Insert1);
|
|
RtlAppendUnicodeStringToString(DeviceRegistryPath, &AfterControlSet);
|
|
RtlAppendUnicodeToString(DeviceRegistryPath, Insert2);
|
|
|
|
/* Check if registry key exists */
|
|
Valid = NT_SUCCESS(RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE, DeviceRegistryPath->Buffer));
|
|
|
|
if (!Valid)
|
|
ExFreePoolWithTag(DeviceRegistryPath->Buffer, TAG_VIDEO_PORT);
|
|
}
|
|
else
|
|
{
|
|
Valid = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WARN_(VIDEOPRT, "Unparsable registry path %wZ\n", DriverRegistryPath);
|
|
}
|
|
|
|
/* If path doesn't point to *ControlSet*, use DriverRegistryPath directly */
|
|
if (!Valid)
|
|
{
|
|
DeviceRegistryPath->MaximumLength = DriverRegistryPath->Length + sizeof(Insert2);
|
|
DeviceRegistryPath->Buffer = ExAllocatePoolWithTag(NonPagedPool,
|
|
DeviceRegistryPath->MaximumLength,
|
|
TAG_VIDEO_PORT);
|
|
|
|
if (!DeviceRegistryPath->Buffer)
|
|
return STATUS_NO_MEMORY;
|
|
|
|
RtlCopyUnicodeString(DeviceRegistryPath, DriverRegistryPath);
|
|
RtlAppendUnicodeToString(DeviceRegistryPath, Insert2);
|
|
}
|
|
|
|
DPRINT("Formatted registry key '%wZ' -> '%wZ'\n",
|
|
DriverRegistryPath, DeviceRegistryPath);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|