You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1039 lines
24 KiB
1039 lines
24 KiB
/*++
|
|
|
|
Copyright (c) 1996 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
regcd.c
|
|
|
|
Abstract:
|
|
|
|
This contains all of the registry munging code of the NT-specific
|
|
side of the ACPI driver
|
|
|
|
Author:
|
|
|
|
Stephane Plante (splante)
|
|
|
|
Environment:
|
|
|
|
Kernel mode only.
|
|
|
|
Revision History:
|
|
|
|
31-Mar-96 Initial Revision
|
|
|
|
--*/
|
|
|
|
#include "pch.h"
|
|
|
|
NTSTATUS
|
|
OSOpenUnicodeHandle(
|
|
PUNICODE_STRING UnicodeKey,
|
|
HANDLE ParentHandle,
|
|
PHANDLE ChildHandle
|
|
);
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(PAGE,OSCloseHandle)
|
|
#pragma alloc_text(PAGE,OSCreateHandle)
|
|
#pragma alloc_text(PAGE,OSGetRegistryValue)
|
|
#pragma alloc_text(PAGE,OSOpenHandle)
|
|
#pragma alloc_text(PAGE,OSOpenUnicodeHandle)
|
|
#pragma alloc_text(PAGE,OSOpenLargestSubkey)
|
|
#pragma alloc_text(PAGE,OSReadAcpiConfigurationData)
|
|
#pragma alloc_text(PAGE,OSReadRegValue)
|
|
#pragma alloc_text(PAGE,OSWriteRegValue)
|
|
#endif
|
|
|
|
WCHAR rgzAcpiBiosIdentifier[] = L"ACPI BIOS";
|
|
WCHAR rgzAcpiConfigurationDataIdentifier[] = L"Configuration Data";
|
|
WCHAR rgzAcpiMultiFunctionAdapterIdentifier[] = L"\\Registry\\Machine\\Hardware\\Description\\System\\MultiFunctionAdapter";
|
|
WCHAR rgzAcpiRegistryIdentifier[] = L"Identifier";
|
|
|
|
|
|
NTSTATUS
|
|
OSCloseHandle(
|
|
HANDLE Key
|
|
)
|
|
{
|
|
|
|
//
|
|
// Call the function that will close the handle now...
|
|
//
|
|
PAGED_CODE();
|
|
return ZwClose( Key );
|
|
|
|
}
|
|
|
|
NTSTATUS
|
|
OSCreateHandle(
|
|
PSZ KeyName,
|
|
HANDLE ParentHandle,
|
|
PHANDLE ChildHandle
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Creates a registry key for writting
|
|
|
|
Arguments:
|
|
|
|
KeyName - Name of the key to create
|
|
ParentHandle - Handle of parent key
|
|
ChildHandle - Pointer to where the handle is returned
|
|
|
|
Return Value:
|
|
|
|
Status of create/open
|
|
|
|
--*/
|
|
{
|
|
ANSI_STRING ansiKey;
|
|
NTSTATUS status;
|
|
OBJECT_ATTRIBUTES objectAttributes;
|
|
UNICODE_STRING unicodeKey;
|
|
|
|
PAGED_CODE();
|
|
ACPIDebugEnter("OSCreateHandle");
|
|
|
|
//
|
|
// We need to convert the given narrow character string into unicode
|
|
//
|
|
RtlInitAnsiString( &ansiKey, KeyName );
|
|
status = RtlAnsiStringToUnicodeString( &unicodeKey, &ansiKey, TRUE );
|
|
if (!NT_SUCCESS(status)) {
|
|
|
|
ACPIPrint( (
|
|
ACPI_PRINT_CRITICAL,
|
|
"OSCreateHandle: RtlAnsiStringToUnicodeString = %#08lx\n",
|
|
status
|
|
) );
|
|
return status;
|
|
}
|
|
|
|
//
|
|
// Initialize the OBJECT Attributes to a known value
|
|
//
|
|
RtlZeroMemory( &objectAttributes, sizeof(OBJECT_ATTRIBUTES) );
|
|
InitializeObjectAttributes(
|
|
&objectAttributes,
|
|
&unicodeKey,
|
|
OBJ_CASE_INSENSITIVE,
|
|
ParentHandle,
|
|
NULL
|
|
);
|
|
|
|
//
|
|
// Create the key here
|
|
//
|
|
*ChildHandle = 0;
|
|
status = ZwCreateKey(
|
|
ChildHandle,
|
|
KEY_WRITE,
|
|
&objectAttributes,
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
NULL
|
|
);
|
|
|
|
//
|
|
// We no longer care about the Key after this point...
|
|
//
|
|
RtlFreeUnicodeString( &unicodeKey );
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
|
|
ACPIPrint( (
|
|
ACPI_PRINT_REGISTRY,
|
|
"OSCreateHandle: ZwCreateKey = %#08lx\n",
|
|
status
|
|
) );
|
|
}
|
|
|
|
return status;
|
|
|
|
ACPIDebugExit("OSCreateHandle");
|
|
}
|
|
|
|
NTSTATUS
|
|
OSGetRegistryValue(
|
|
IN HANDLE ParentHandle,
|
|
IN PWSTR ValueName,
|
|
OUT PKEY_VALUE_PARTIAL_INFORMATION_ALIGN64 *Information
|
|
)
|
|
{
|
|
NTSTATUS status;
|
|
PKEY_VALUE_PARTIAL_INFORMATION_ALIGN64 infoBuffer;
|
|
ULONG keyValueLength;
|
|
UNICODE_STRING unicodeString;
|
|
|
|
PAGED_CODE();
|
|
ACPIDebugEnter("OSGetRegistryValue");
|
|
|
|
RtlInitUnicodeString( &unicodeString, ValueName );
|
|
|
|
//
|
|
// Figure out how big the data value is so that we can allocate the
|
|
// proper sized buffer
|
|
//
|
|
status = ZwQueryValueKey(
|
|
ParentHandle,
|
|
&unicodeString,
|
|
KeyValuePartialInformationAlign64,
|
|
(PVOID) NULL,
|
|
0,
|
|
&keyValueLength
|
|
);
|
|
if (status != STATUS_BUFFER_OVERFLOW && status != STATUS_BUFFER_TOO_SMALL) {
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
//
|
|
// Allocate a buffer large enough to contain the entire key data value
|
|
//
|
|
infoBuffer = ExAllocatePoolWithTag(
|
|
NonPagedPool,
|
|
keyValueLength,
|
|
ACPI_STRING_POOLTAG
|
|
);
|
|
if (infoBuffer == NULL) {
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
}
|
|
|
|
//
|
|
// Now query the data again and this time it will work
|
|
//
|
|
status = ZwQueryValueKey(
|
|
ParentHandle,
|
|
&unicodeString,
|
|
KeyValuePartialInformationAlign64,
|
|
(PVOID) infoBuffer,
|
|
keyValueLength,
|
|
&keyValueLength
|
|
);
|
|
if (!NT_SUCCESS(status)) {
|
|
|
|
ExFreePool( infoBuffer );
|
|
return status;
|
|
|
|
}
|
|
|
|
//
|
|
// Everything worked - so simply return the address of the allocated
|
|
// structure buffer to the caller, who is now responsible for freeing it
|
|
//
|
|
*Information = infoBuffer;
|
|
return STATUS_SUCCESS;
|
|
|
|
ACPIDebugExit("OSGetRegistryValue");
|
|
}
|
|
|
|
NTSTATUS
|
|
OSOpenHandle(
|
|
PSZ KeyName,
|
|
HANDLE ParentHandle,
|
|
PHANDLE ChildHandle
|
|
)
|
|
{
|
|
ANSI_STRING ansiKey;
|
|
NTSTATUS status;
|
|
UNICODE_STRING unicodeKey;
|
|
|
|
PAGED_CODE();
|
|
ACPIDebugEnter("OSOpenHandle");
|
|
|
|
//
|
|
// We need to convert the given narrow character string into unicode
|
|
//
|
|
RtlInitAnsiString( &ansiKey, KeyName );
|
|
status = RtlAnsiStringToUnicodeString( &unicodeKey, &ansiKey, TRUE );
|
|
if (!NT_SUCCESS(status)) {
|
|
|
|
ACPIPrint( (
|
|
ACPI_PRINT_CRITICAL,
|
|
"OSOpenHandle: RtlAnsiStringToUnicodeString = %#08lx\n",
|
|
status
|
|
) );
|
|
return status;
|
|
|
|
}
|
|
|
|
status = OSOpenUnicodeHandle( &unicodeKey, ParentHandle, ChildHandle );
|
|
|
|
//
|
|
// We no longer care about the Key after this point...
|
|
//
|
|
RtlFreeUnicodeString( &unicodeKey );
|
|
|
|
return status;
|
|
|
|
ACPIDebugExit("OSOpenHandle");
|
|
}
|
|
|
|
NTSTATUS
|
|
OSOpenUnicodeHandle(
|
|
PUNICODE_STRING UnicodeKey,
|
|
HANDLE ParentHandle,
|
|
PHANDLE ChildHandle
|
|
)
|
|
{
|
|
NTSTATUS status;
|
|
OBJECT_ATTRIBUTES objectAttributes;
|
|
|
|
PAGED_CODE();
|
|
|
|
//
|
|
// Initialize the OBJECT Attributes to a known value
|
|
//
|
|
RtlZeroMemory( &objectAttributes, sizeof(OBJECT_ATTRIBUTES) );
|
|
InitializeObjectAttributes(
|
|
&objectAttributes,
|
|
UnicodeKey,
|
|
OBJ_CASE_INSENSITIVE,
|
|
ParentHandle,
|
|
NULL
|
|
);
|
|
|
|
//
|
|
// Open the key here
|
|
//
|
|
status = ZwOpenKey(
|
|
ChildHandle,
|
|
KEY_READ,
|
|
&objectAttributes
|
|
);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
ACPIPrint( (
|
|
ACPI_PRINT_REGISTRY,
|
|
"OSOpenUnicodeHandle: ZwOpenKey = %#08lx\n",
|
|
status
|
|
) );
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
NTSTATUS
|
|
OSOpenLargestSubkey(
|
|
HANDLE ParentHandle,
|
|
PHANDLE ChildHandle,
|
|
ULONG RomVersion
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Open the largest (numerically) subkey under the given parent key.
|
|
|
|
Arguments:
|
|
|
|
ParentHandle - Handle to the parent key
|
|
ChildHandle - Pointer to where the handle is returned
|
|
RomVersion - Minimum version number that is acceptable
|
|
|
|
Return Value:
|
|
|
|
Status of open
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS status;
|
|
UNICODE_STRING unicodeName;
|
|
PKEY_BASIC_INFORMATION keyInformation;
|
|
ULONG resultLength;
|
|
ULONG i;
|
|
HANDLE workingDir = NULL;
|
|
HANDLE largestDir = NULL;
|
|
ULONG largestRev = 0;
|
|
ULONG thisRev = 0;
|
|
|
|
|
|
PAGED_CODE();
|
|
ACPIDebugEnter( "OSOpenLargestSubkey" );
|
|
|
|
keyInformation = ExAllocatePoolWithTag(
|
|
PagedPool,
|
|
512,
|
|
ACPI_MISC_POOLTAG
|
|
);
|
|
if (keyInformation == NULL) {
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
}
|
|
|
|
//
|
|
// Traverse all subkeys
|
|
//
|
|
for (i = 0; ; i++) {
|
|
|
|
//
|
|
// Get a subkey
|
|
//
|
|
status = ZwEnumerateKey(
|
|
ParentHandle,
|
|
i,
|
|
KeyBasicInformation,
|
|
keyInformation,
|
|
512,
|
|
&resultLength
|
|
);
|
|
if (!NT_SUCCESS(status)) { // Fail when no more subkeys
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Create a UNICODE_STRING using the counted string passed back to
|
|
// us in the information structure, and convert to an integer.
|
|
//
|
|
unicodeName.Length = (USHORT) keyInformation->NameLength;
|
|
unicodeName.MaximumLength = (USHORT) keyInformation->NameLength;
|
|
unicodeName.Buffer = keyInformation->Name;
|
|
RtlUnicodeStringToInteger(&unicodeName, 16, &thisRev);
|
|
|
|
//
|
|
// Save this one if it is the largest
|
|
//
|
|
if ( (workingDir == NULL) || thisRev > largestRev) {
|
|
|
|
//
|
|
// We'll just open the target rather than save
|
|
// away the name to open later
|
|
//
|
|
status = OSOpenUnicodeHandle(
|
|
&unicodeName,
|
|
ParentHandle,
|
|
&workingDir
|
|
);
|
|
if ( NT_SUCCESS(status) ) {
|
|
|
|
if (largestDir) {
|
|
|
|
OSCloseHandle (largestDir); // Close previous
|
|
|
|
}
|
|
largestDir = workingDir; // Save handle
|
|
largestRev = thisRev; // Save version number
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Done with KeyInformation
|
|
//
|
|
ExFreePool( keyInformation );
|
|
|
|
//
|
|
// No subkey found/opened, this is a problem
|
|
//
|
|
if (largestDir == NULL) {
|
|
|
|
return ( NT_SUCCESS(status) ? STATUS_UNSUCCESSFUL : status );
|
|
|
|
}
|
|
|
|
//
|
|
// Use the subkey only if it the revision is equal or greater than the
|
|
// ROM version
|
|
//
|
|
if (largestRev < RomVersion) {
|
|
|
|
OSCloseHandle (largestDir);
|
|
return STATUS_REVISION_MISMATCH;
|
|
|
|
}
|
|
|
|
*ChildHandle = largestDir; // Return handle to subkey
|
|
return STATUS_SUCCESS;
|
|
|
|
ACPIDebugExit( "OSOpenLargestSubkey" );
|
|
}
|
|
|
|
NTSTATUS
|
|
OSReadAcpiConfigurationData(
|
|
PKEY_VALUE_PARTIAL_INFORMATION_ALIGN64 *KeyInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This very specialized routine looks in the Registry and tries to find
|
|
the information that was written there by ntdetect. It returns a pointer
|
|
to the keyvalue that will then be processed by the caller to find the
|
|
pointer to the RSDT and the E820 memory table
|
|
|
|
Arguments:
|
|
|
|
KeyInfo - Where to store the pointer to the information from the registry
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
|
|
--*/
|
|
{
|
|
BOOLEAN sameId;
|
|
HANDLE functionHandle;
|
|
HANDLE multiHandle;
|
|
NTSTATUS status;
|
|
ULONG i;
|
|
ULONG length;
|
|
UNICODE_STRING biosId;
|
|
UNICODE_STRING functionId;
|
|
UNICODE_STRING registryId;
|
|
WCHAR wbuffer[4];
|
|
|
|
ASSERT( KeyInfo != NULL );
|
|
if (KeyInfo == NULL) {
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
|
*KeyInfo = NULL;
|
|
|
|
//
|
|
// Open the handle for the MultiFunctionAdapter
|
|
//
|
|
RtlInitUnicodeString( &functionId, rgzAcpiMultiFunctionAdapterIdentifier );
|
|
status = OSOpenUnicodeHandle(
|
|
&functionId,
|
|
NULL,
|
|
&multiHandle
|
|
);
|
|
if (!NT_SUCCESS(status)) {
|
|
|
|
ACPIPrint( (
|
|
ACPI_PRINT_CRITICAL,
|
|
"OSReadAcpiConfigurationData: Cannot open MFA Handle = %08lx\n",
|
|
status
|
|
) );
|
|
ACPIBreakPoint();
|
|
return status;
|
|
|
|
}
|
|
|
|
//
|
|
// Initialize the unicode strings we will need shortly
|
|
//
|
|
RtlInitUnicodeString( &biosId, rgzAcpiBiosIdentifier );
|
|
functionId.Buffer = wbuffer;
|
|
functionId.MaximumLength = sizeof(wbuffer);
|
|
|
|
//
|
|
// Loop until we run out of children in the MFA node
|
|
//
|
|
for (i = 0; i < 999; i++) {
|
|
|
|
//
|
|
// Open the subkey
|
|
//
|
|
RtlIntegerToUnicodeString(i, 10, &functionId );
|
|
status = OSOpenUnicodeHandle(
|
|
&functionId,
|
|
multiHandle,
|
|
&functionHandle
|
|
);
|
|
if (!NT_SUCCESS(status)) {
|
|
|
|
ACPIPrint( (
|
|
ACPI_PRINT_CRITICAL,
|
|
"OSReadAcpiConfigurationData: Cannot open MFA %ws = %08lx\n",
|
|
functionId.Buffer,
|
|
status
|
|
) );
|
|
ACPIBreakPoint();
|
|
OSCloseHandle( multiHandle );
|
|
return status;
|
|
|
|
}
|
|
|
|
//
|
|
// Check the identifier to see if this is an ACPI BIOS entry
|
|
//
|
|
status = OSGetRegistryValue(
|
|
functionHandle,
|
|
rgzAcpiRegistryIdentifier,
|
|
KeyInfo
|
|
);
|
|
if (!NT_SUCCESS(status)) {
|
|
|
|
OSCloseHandle( functionHandle );
|
|
continue;
|
|
|
|
}
|
|
|
|
//
|
|
// Convert the key information into a unicode string
|
|
//
|
|
registryId.Buffer = (PWSTR) ( (PUCHAR) (*KeyInfo)->Data);
|
|
registryId.MaximumLength = (USHORT) ( (*KeyInfo)->DataLength );
|
|
length = ( (*KeyInfo)->DataLength ) / sizeof(WCHAR);
|
|
|
|
//
|
|
// Determine the real length of the ID string
|
|
//
|
|
while (length) {
|
|
|
|
if (registryId.Buffer[length-1] == UNICODE_NULL) {
|
|
|
|
length--;
|
|
continue;
|
|
|
|
}
|
|
break;
|
|
|
|
}
|
|
registryId.Length = (USHORT) ( length * sizeof(WCHAR) );
|
|
|
|
//
|
|
// Compare the bios string and the registry string
|
|
//
|
|
sameId = RtlEqualUnicodeString( &biosId, ®istryId, TRUE );
|
|
|
|
//
|
|
// We are done with this information at this point
|
|
//
|
|
ExFreePool( *KeyInfo );
|
|
|
|
//
|
|
// Did the two strings match
|
|
//
|
|
if (sameId == FALSE) {
|
|
|
|
OSCloseHandle( functionHandle );
|
|
continue;
|
|
|
|
}
|
|
|
|
//
|
|
// Read the configuration data from the entry
|
|
//
|
|
status = OSGetRegistryValue(
|
|
functionHandle,
|
|
rgzAcpiConfigurationDataIdentifier,
|
|
KeyInfo
|
|
);
|
|
|
|
//
|
|
// We are done with the function handle, no matter what
|
|
//
|
|
OSCloseHandle( functionHandle );
|
|
|
|
//
|
|
// Did we read what we wanted to?
|
|
//
|
|
if (!NT_SUCCESS(status)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
//
|
|
// At this point, we don't need the bus handle
|
|
//
|
|
OSCloseHandle( multiHandle );
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
//
|
|
// If we got here, then there is nothing to return
|
|
//
|
|
ACPIPrint( (
|
|
ACPI_PRINT_CRITICAL,
|
|
"OSReadAcpiConfigurationData - Could not find entry\n"
|
|
) );
|
|
ACPIBreakPoint();
|
|
return STATUS_OBJECT_NAME_NOT_FOUND;
|
|
}
|
|
|
|
NTSTATUS
|
|
OSReadRegValue(
|
|
PSZ ValueName,
|
|
HANDLE ParentHandle,
|
|
PUCHAR Buffer,
|
|
PULONG BufferSize
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is responsible for returning the data in the specified value
|
|
over to the calling function.
|
|
|
|
Arguments:
|
|
|
|
ValueName - What we are looking for
|
|
ParentHandle - Our Parent Handle
|
|
Buffer - Where to store the data
|
|
BufferSize - Length of the buffer and where to store the # read
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
|
|
--*/
|
|
{
|
|
ANSI_STRING ansiValue;
|
|
HANDLE localHandle = NULL;
|
|
NTSTATUS status;
|
|
PKEY_VALUE_PARTIAL_INFORMATION_ALIGN64 data = NULL;
|
|
ULONG currentLength = 0;
|
|
ULONG desiredLength = 0;
|
|
UNICODE_STRING unicodeValue;
|
|
|
|
PAGED_CODE();
|
|
ACPIDebugEnter( "OSReadRegValue" );
|
|
|
|
//
|
|
// First, try to open a handle to the key
|
|
//
|
|
if (ParentHandle == NULL) {
|
|
|
|
status= OSOpenHandle(
|
|
ACPI_PARAMETERS_REGISTRY_KEY,
|
|
0,
|
|
&localHandle
|
|
);
|
|
if (!NT_SUCCESS(status) || localHandle == NULL) {
|
|
|
|
ACPIPrint( (
|
|
ACPI_PRINT_WARNING,
|
|
"OSReadRegValue: OSOpenHandle = %#08lx\n",
|
|
status
|
|
) );
|
|
return (ULONG) status;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
localHandle = ParentHandle;
|
|
|
|
}
|
|
|
|
//
|
|
// Now that we have an open handle, we can convert the value to a
|
|
// unicode string and query it
|
|
//
|
|
RtlInitAnsiString( &ansiValue, ValueName );
|
|
status = RtlAnsiStringToUnicodeString( &unicodeValue, &ansiValue, TRUE );
|
|
if (!NT_SUCCESS(status)) {
|
|
|
|
ACPIPrint( (
|
|
ACPI_PRINT_CRITICAL,
|
|
"OSReadRegValue: RtlAnsiStringToUnicodeString = %#08lx\n",
|
|
status
|
|
) );
|
|
if (ParentHandle == NULL) {
|
|
|
|
OSCloseHandle( localHandle );
|
|
|
|
}
|
|
return status;
|
|
|
|
}
|
|
|
|
//
|
|
// Next, we need to figure out how much memore we need to hold the
|
|
// entire key
|
|
//
|
|
status = ZwQueryValueKey(
|
|
localHandle,
|
|
&unicodeValue,
|
|
KeyValuePartialInformationAlign64,
|
|
data,
|
|
currentLength,
|
|
&desiredLength
|
|
);
|
|
|
|
//
|
|
// We expect this to fail with STATUS_BUFFER_OVERFLOW, so lets make
|
|
// sure that this is what happened
|
|
//
|
|
if (status != STATUS_BUFFER_OVERFLOW && status != STATUS_BUFFER_TOO_SMALL) {
|
|
|
|
ACPIPrint( (
|
|
ACPI_PRINT_WARNING,
|
|
"OSReadRegValue: ZwQueryValueKey = %#08lx\n",
|
|
status
|
|
) );
|
|
|
|
//
|
|
// Free resources
|
|
//
|
|
RtlFreeUnicodeString( &unicodeValue );
|
|
if (ParentHandle == NULL) {
|
|
|
|
OSCloseHandle( localHandle );
|
|
|
|
}
|
|
return (NT_SUCCESS(status) ? STATUS_UNSUCCESSFUL : status);
|
|
|
|
}
|
|
|
|
while (status == STATUS_BUFFER_OVERFLOW ||
|
|
status == STATUS_BUFFER_TOO_SMALL) {
|
|
|
|
//
|
|
// Set the new currentLength
|
|
//
|
|
currentLength = desiredLength;
|
|
|
|
//
|
|
// Allocate a correctly sized buffer
|
|
//
|
|
data = ExAllocatePoolWithTag(
|
|
PagedPool,
|
|
currentLength,
|
|
ACPI_MISC_POOLTAG
|
|
);
|
|
if (data == NULL) {
|
|
|
|
ACPIPrint( (
|
|
ACPI_PRINT_CRITICAL,
|
|
"OSReadRegValue: ExAllocatePool(NonPagedPool,%#08lx) failed\n",
|
|
desiredLength
|
|
) );
|
|
|
|
RtlFreeUnicodeString( &unicodeValue );
|
|
if (ParentHandle == NULL) {
|
|
|
|
OSCloseHandle( localHandle );
|
|
|
|
}
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
}
|
|
|
|
//
|
|
// Actually try to read the entire key now
|
|
//
|
|
status = ZwQueryValueKey(
|
|
localHandle,
|
|
&unicodeValue,
|
|
KeyValuePartialInformationAlign64,
|
|
data,
|
|
currentLength,
|
|
&desiredLength
|
|
);
|
|
|
|
//
|
|
// If we don't have enough resources, lets just loop again
|
|
//
|
|
if (status == STATUS_BUFFER_OVERFLOW ||
|
|
status == STATUS_BUFFER_TOO_SMALL) {
|
|
|
|
//
|
|
// Make sure to free the old buffer -- otherwise, we could
|
|
// have a major memory leak
|
|
//
|
|
ExFreePool( data );
|
|
continue;
|
|
|
|
}
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
|
|
ACPIPrint( (
|
|
ACPI_PRINT_FAILURE,
|
|
"OSReadRegValue: ZwQueryValueKey = %#08lx\n",
|
|
status
|
|
) );
|
|
RtlFreeUnicodeString( &unicodeValue );
|
|
if (ParentHandle == NULL) {
|
|
|
|
OSCloseHandle( localHandle );
|
|
|
|
}
|
|
ExFreePool( data );
|
|
return status;
|
|
|
|
}
|
|
|
|
//
|
|
// Done
|
|
//
|
|
break;
|
|
|
|
} // while (status == ...
|
|
|
|
//
|
|
// Free Resources
|
|
//
|
|
RtlFreeUnicodeString( &unicodeValue );
|
|
if (ParentHandle == NULL) {
|
|
|
|
OSCloseHandle( localHandle );
|
|
|
|
}
|
|
|
|
//
|
|
// The value read from the registry is a UNICODE Value, however
|
|
// we are asked for an ANSI string. So we just work the conversion
|
|
// backwards
|
|
//
|
|
if ( data->Type == REG_SZ ||
|
|
data->Type == REG_MULTI_SZ) {
|
|
|
|
RtlInitUnicodeString( &unicodeValue, (PWSTR) data->Data );
|
|
status = RtlUnicodeStringToAnsiString( &ansiValue, &unicodeValue, TRUE);
|
|
ExFreePool( data );
|
|
if (!NT_SUCCESS(status)) {
|
|
|
|
ACPIPrint( (
|
|
ACPI_PRINT_CRITICAL,
|
|
"OSReadRegValue: RtlAnsiStringToUnicodeString = %#08lx\n",
|
|
status
|
|
) );
|
|
return (ULONG) status;
|
|
|
|
}
|
|
|
|
//
|
|
// Is our buffer big enough?
|
|
//
|
|
if ( *BufferSize < ansiValue.MaximumLength) {
|
|
|
|
ACPIPrint( (
|
|
ACPI_PRINT_WARNING,
|
|
"OSReadRegValue: %#08lx < %#08lx\n",
|
|
*BufferSize,
|
|
ansiValue.MaximumLength
|
|
) );
|
|
|
|
RtlFreeAnsiString( &ansiValue );
|
|
return (ULONG) STATUS_BUFFER_OVERFLOW;
|
|
|
|
} else {
|
|
|
|
//
|
|
// Set the returned size
|
|
//
|
|
*BufferSize = ansiValue.MaximumLength;
|
|
|
|
}
|
|
|
|
//
|
|
// Copy the required information
|
|
//
|
|
RtlCopyMemory( Buffer, ansiValue.Buffer, *BufferSize);
|
|
RtlFreeAnsiString( &ansiValue );
|
|
|
|
} else if ( *BufferSize >= data->DataLength) {
|
|
|
|
//
|
|
// Copy the memory
|
|
//
|
|
RtlCopyMemory( Buffer, data->Data, data->DataLength );
|
|
*BufferSize = data->DataLength;
|
|
ExFreePool( data );
|
|
|
|
} else {
|
|
|
|
ExFreePool( data );
|
|
return STATUS_BUFFER_OVERFLOW;
|
|
|
|
}
|
|
|
|
//
|
|
// Done
|
|
//
|
|
return STATUS_SUCCESS;
|
|
|
|
ACPIDebugExit( "OSReadRegValue" );
|
|
|
|
}
|
|
|
|
NTSTATUS
|
|
OSWriteRegValue(
|
|
PSZ ValueName,
|
|
HANDLE Handle,
|
|
PVOID Data,
|
|
ULONG DataSize
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Creates a value item in a registry key, and writes data to it
|
|
|
|
Arguments:
|
|
|
|
ValueName - Name of the value item to create
|
|
Handle - Handle of the parent key
|
|
Data - Raw data to be written to the value
|
|
DataSize - Size of the data to write
|
|
|
|
Return Value:
|
|
|
|
Status of create/write
|
|
|
|
--*/
|
|
{
|
|
ANSI_STRING ansiKey;
|
|
NTSTATUS status;
|
|
OBJECT_ATTRIBUTES objectAttributes;
|
|
UNICODE_STRING unicodeKey;
|
|
|
|
PAGED_CODE();
|
|
ACPIDebugEnter("OSWriteRegValue");
|
|
|
|
//
|
|
// We need to convert the given narrow character string into unicode
|
|
//
|
|
RtlInitAnsiString( &ansiKey, ValueName );
|
|
status = RtlAnsiStringToUnicodeString( &unicodeKey, &ansiKey, TRUE );
|
|
if (!NT_SUCCESS(status)) {
|
|
|
|
ACPIPrint( (
|
|
ACPI_PRINT_CRITICAL,
|
|
"OSWriteRegValue: RtlAnsiStringToUnicodeString = %#08lx\n",
|
|
status
|
|
) );
|
|
return status;
|
|
|
|
}
|
|
|
|
//
|
|
// Create the value
|
|
//
|
|
status = ZwSetValueKey(
|
|
Handle,
|
|
&unicodeKey,
|
|
0,
|
|
REG_BINARY,
|
|
Data,
|
|
DataSize
|
|
);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
|
|
ACPIPrint( (
|
|
ACPI_PRINT_REGISTRY,
|
|
"OSRegWriteValue: ZwSetValueKey = %#08lx\n",
|
|
status
|
|
) );
|
|
|
|
}
|
|
|
|
//
|
|
// We no longer care about the Key after this point...
|
|
//
|
|
RtlFreeUnicodeString( &unicodeKey );
|
|
return status;
|
|
|
|
ACPIDebugExit("OSRegWriteValue");
|
|
}
|