Leaked source code of windows server 2003
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

/*++
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;
}