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.
278 lines
7.2 KiB
278 lines
7.2 KiB
/*++
|
|
|
|
Copyright (c) 1989-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
registry.c
|
|
|
|
Abstract:
|
|
|
|
Implement registry functions
|
|
|
|
Author:
|
|
|
|
Jiandong Ruan
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#include "registry.tmh"
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(PAGE, SmbQueryValueKey)
|
|
#pragma alloc_text(PAGE, SmbReadULong)
|
|
#endif
|
|
|
|
PKEY_VALUE_FULL_INFORMATION
|
|
SmbQueryValueKey(
|
|
HANDLE hKey,
|
|
LPWSTR ValueStringName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function retrieves the full information for the specified key.
|
|
It allocates local memory for the returned information.
|
|
|
|
Arguments:
|
|
|
|
Key : registry handle to the key where the value is.
|
|
|
|
ValueStringName : name of the value string.
|
|
|
|
Return Value:
|
|
|
|
NULL if out of resource or error. Otherwise, the pointer to the full information
|
|
|
|
--*/
|
|
{
|
|
DWORD BytesNeeded, BytesAllocated;
|
|
NTSTATUS status;
|
|
UNICODE_STRING KeyName;
|
|
PKEY_VALUE_FULL_INFORMATION Buffer;
|
|
|
|
PAGED_CODE();
|
|
|
|
RtlInitUnicodeString(&KeyName, ValueStringName);
|
|
|
|
Buffer = NULL;
|
|
BytesAllocated = 0;
|
|
BytesNeeded = 240;
|
|
while(1) {
|
|
ASSERT(Buffer == NULL);
|
|
|
|
Buffer = (PKEY_VALUE_FULL_INFORMATION)ExAllocatePoolWithTag(PagedPool, BytesNeeded, SMB_POOL_REGISTRY);
|
|
if (Buffer == NULL) {
|
|
SmbTrace(SMB_TRACE_REGISTRY, ("(Out of memory)"));
|
|
return NULL;
|
|
}
|
|
BytesAllocated = BytesNeeded;
|
|
|
|
status = ZwQueryValueKey(
|
|
hKey,
|
|
&KeyName,
|
|
KeyValueFullInformation,
|
|
Buffer,
|
|
BytesAllocated,
|
|
&BytesNeeded
|
|
);
|
|
if (status == STATUS_SUCCESS) {
|
|
break;
|
|
}
|
|
|
|
ASSERT(Buffer);
|
|
ExFreePool(Buffer);
|
|
Buffer = NULL;
|
|
if (BytesNeeded == 0 || (status != STATUS_BUFFER_TOO_SMALL && status != STATUS_BUFFER_OVERFLOW)) {
|
|
SmbTrace(SMB_TRACE_REGISTRY, ("return %!status! BytesAllocated=%d BytsNeeded=%d %ws",
|
|
status, BytesAllocated, BytesNeeded, ValueStringName));
|
|
SmbPrint(SMB_TRACE_REGISTRY, ("SmbQueryValueKey return 0x%08lx BytesAllocated=%d BytsNeeded=%d %ws\n",
|
|
status, BytesAllocated, BytesNeeded, ValueStringName));
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
ASSERT (status == STATUS_SUCCESS);
|
|
ASSERT (Buffer);
|
|
return Buffer;
|
|
}
|
|
|
|
LONG
|
|
SmbReadLong(
|
|
IN HANDLE hKey,
|
|
IN WCHAR *KeyName,
|
|
IN LONG DefaultValue,
|
|
IN LONG MinimumValue
|
|
)
|
|
{
|
|
PKEY_VALUE_FULL_INFORMATION KeyInfo;
|
|
LONG Value;
|
|
|
|
PAGED_CODE();
|
|
|
|
ASSERT (DefaultValue >= MinimumValue);
|
|
|
|
Value = DefaultValue;
|
|
if (Value < MinimumValue) {
|
|
Value = MinimumValue;
|
|
}
|
|
|
|
KeyInfo = SmbQueryValueKey(hKey, KeyName);
|
|
if (KeyInfo == NULL) {
|
|
return Value;
|
|
}
|
|
|
|
if (KeyInfo->Type == REG_DWORD && KeyInfo->DataLength == sizeof(ULONG)) {
|
|
RtlCopyMemory(&Value, (PCHAR)KeyInfo + KeyInfo->DataOffset, sizeof(ULONG));
|
|
if (Value < MinimumValue) {
|
|
Value = MinimumValue;
|
|
}
|
|
}
|
|
ExFreePool(KeyInfo);
|
|
return Value;
|
|
}
|
|
|
|
ULONG
|
|
SmbReadULong(
|
|
IN HANDLE hKey,
|
|
IN WCHAR *KeyName,
|
|
IN ULONG DefaultValue,
|
|
IN ULONG MinimumValue
|
|
)
|
|
{
|
|
PKEY_VALUE_FULL_INFORMATION KeyInfo;
|
|
ULONG Value;
|
|
|
|
PAGED_CODE();
|
|
|
|
ASSERT (DefaultValue >= MinimumValue);
|
|
|
|
Value = DefaultValue;
|
|
if (Value < MinimumValue) {
|
|
Value = MinimumValue;
|
|
}
|
|
|
|
KeyInfo = SmbQueryValueKey(hKey, KeyName);
|
|
if (KeyInfo == NULL) {
|
|
return Value;
|
|
}
|
|
|
|
if (KeyInfo->Type == REG_DWORD && KeyInfo->DataLength == sizeof(ULONG)) {
|
|
RtlCopyMemory(&Value, (PCHAR)KeyInfo + KeyInfo->DataOffset, sizeof(ULONG));
|
|
if (Value < MinimumValue) {
|
|
Value = MinimumValue;
|
|
}
|
|
}
|
|
ExFreePool(KeyInfo);
|
|
return Value;
|
|
}
|
|
|
|
NTSTATUS
|
|
SmbReadRegistry(
|
|
IN HANDLE Key,
|
|
IN LPWSTR ValueStringName,
|
|
IN OUT DWORD *Type,
|
|
IN OUT DWORD *Size,
|
|
IN OUT PVOID *Buffer
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read a regisry value
|
|
|
|
Arguments:
|
|
|
|
Key The registry handle under which the registry key resides.
|
|
ValueStringName The name of registry key
|
|
Type The data type of the registry key
|
|
Type == NULL The caller is not interested in the data type
|
|
Type != NULL The caller want to receive the data type
|
|
*Type != REG_NONE The caller can receive the value as any data type.
|
|
|
|
Size The size (# of bytes) of the registry value.
|
|
Size == NULL The caller is not interested in the data size
|
|
Size != NULL The caller want to know the data size.
|
|
Size != NULL && *Buffer != NULL
|
|
The caller has provided a buffer. *Size is the size of
|
|
caller-supplied buffer.
|
|
Buffer The output buffer
|
|
*Buffer == NULL The caller doesn't provide any buffer. This function
|
|
should allocate a buffer. The caller is responsible to
|
|
free the buffer.
|
|
*Buffer != NULL The caller provides a buffer. The size of buffer is specified
|
|
in *Size;
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS success
|
|
other failure
|
|
|
|
--*/
|
|
{
|
|
PKEY_VALUE_FULL_INFORMATION KeyInfo;
|
|
|
|
ASSERT (Buffer);
|
|
if (Buffer == NULL) {
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
// ASSERT (*Buffer ==> Size && *Size);
|
|
ASSERT (!(*Buffer) || (Size && *Size));
|
|
if ((*Buffer) && !(Size && *Size)) {
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
if ((NULL == *Buffer) && Size && *Size) {
|
|
ASSERT(0);
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
KeyInfo = SmbQueryValueKey(
|
|
Key,
|
|
ValueStringName
|
|
);
|
|
if (NULL == KeyInfo) {
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
if (Type && *Type != REG_NONE) {
|
|
if (KeyInfo->Type != *Type) {
|
|
ExFreePool(KeyInfo);
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
}
|
|
|
|
if (NULL == *Buffer) {
|
|
*Buffer = ExAllocatePoolWithTag(PagedPool, KeyInfo->DataLength, SMB_POOL_REGISTRY);
|
|
if (NULL == *Buffer) {
|
|
ExFreePool(KeyInfo);
|
|
return STATUS_NO_MEMORY;
|
|
}
|
|
} else {
|
|
if (*Size < KeyInfo->DataLength) {
|
|
ExFreePool(KeyInfo);
|
|
|
|
*Size = KeyInfo->DataLength;
|
|
return STATUS_BUFFER_TOO_SMALL;
|
|
}
|
|
}
|
|
|
|
//
|
|
// From now on, we cannot fail
|
|
//
|
|
if (Size) {
|
|
*Size = KeyInfo->DataLength;
|
|
}
|
|
|
|
if (Type) {
|
|
*Type = KeyInfo->Type;
|
|
}
|
|
RtlCopyMemory(*Buffer, ((PUCHAR)KeyInfo) + KeyInfo->DataOffset, KeyInfo->DataLength);
|
|
|
|
ExFreePool(KeyInfo);
|
|
return STATUS_SUCCESS;
|
|
}
|