mirror of
https://github.com/reactos/reactos.git
synced 2025-05-28 13:38:19 +00:00
Share duplicated Rtl code. I've taken care to use the most recent code, so now ntoskrnl can also do environment string expansion.
svn path=/trunk/; revision=13113
This commit is contained in:
parent
c435570afa
commit
e4d14eb7ad
5 changed files with 25 additions and 820 deletions
|
@ -77,7 +77,6 @@ RTL_OBJECTS = \
|
|||
rtl/process.o \
|
||||
rtl/propvar.o \
|
||||
rtl/rangelist.o \
|
||||
rtl/registry.o \
|
||||
rtl/resource.o \
|
||||
rtl/teb.o \
|
||||
rtl/thread.o \
|
||||
|
|
|
@ -32,6 +32,7 @@ TARGET_OBJECTS = \
|
|||
network.o \
|
||||
nls.o \
|
||||
random.o \
|
||||
registry.o \
|
||||
sd.o \
|
||||
security.o \
|
||||
sid.o \
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
/* $Id$
|
||||
/* $Id: registry.c 12852 2005-01-06 13:58:04Z mf $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* PURPOSE: Rtl registry functions
|
||||
* FILE: lib/ntdll/rtl/registry.c
|
||||
* FILE: lib/rtl/registry.c
|
||||
* PROGRAMER: Eric Kohl
|
||||
* REVISION HISTORY:
|
||||
* 2000/08/11: Created
|
||||
|
@ -17,6 +17,7 @@
|
|||
|
||||
/* INCLUDES ****************************************************************/
|
||||
|
||||
#define __NTDRIVER__
|
||||
#include <ddk/ntddk.h>
|
||||
#include <ntdll/rtl.h>
|
||||
#include <ntos/minmax.h>
|
||||
|
@ -290,9 +291,8 @@ RtlFormatCurrentUserKeyPath (OUT PUNICODE_STRING KeyPath)
|
|||
|
||||
KeyPath->Length = 0;
|
||||
KeyPath->MaximumLength = Length;
|
||||
KeyPath->Buffer = RtlAllocateHeap (RtlGetProcessHeap (),
|
||||
0,
|
||||
KeyPath->MaximumLength);
|
||||
KeyPath->Buffer = ExAllocatePool (NonPagedPool,
|
||||
KeyPath->MaximumLength);
|
||||
if (KeyPath->Buffer == NULL)
|
||||
{
|
||||
DPRINT1 ("RtlAllocateHeap() failed\n");
|
||||
|
@ -432,9 +432,7 @@ RtlQueryRegistryValues(IN ULONG RelativeTo,
|
|||
QueryEntry->Name);
|
||||
|
||||
BufferSize = sizeof (KEY_VALUE_PARTIAL_INFORMATION) + 4096;
|
||||
ValueInfo = RtlAllocateHeap(RtlGetProcessHeap(),
|
||||
0,
|
||||
BufferSize);
|
||||
ValueInfo = ExAllocatePool(PagedPool, BufferSize);
|
||||
if (ValueInfo == NULL)
|
||||
{
|
||||
Status = STATUS_NO_MEMORY;
|
||||
|
@ -451,7 +449,7 @@ RtlQueryRegistryValues(IN ULONG RelativeTo,
|
|||
{
|
||||
if (QueryEntry->Flags & RTL_QUERY_REGISTRY_REQUIRED)
|
||||
{
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, ValueInfo);
|
||||
ExFreePool(ValueInfo);
|
||||
Status = STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
break;
|
||||
}
|
||||
|
@ -467,9 +465,7 @@ RtlQueryRegistryValues(IN ULONG RelativeTo,
|
|||
{
|
||||
ValueString->Length = SourceString->Length;
|
||||
ValueString->MaximumLength = SourceString->MaximumLength;
|
||||
ValueString->Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
|
||||
0,
|
||||
ValueString->MaximumLength);
|
||||
ValueString->Buffer = ExAllocatePool(PagedPool, BufferSize);
|
||||
if (!ValueString->Buffer)
|
||||
break;
|
||||
ValueString->Buffer[0] = 0;
|
||||
|
@ -507,9 +503,7 @@ RtlQueryRegistryValues(IN ULONG RelativeTo,
|
|||
if (ValueString->Buffer == NULL)
|
||||
{
|
||||
ValueString->MaximumLength = ValueInfo->DataLength;
|
||||
ValueString->Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
|
||||
0,
|
||||
ValueString->MaximumLength);
|
||||
ValueString->Buffer = ExAllocatePool(PagedPool, ValueString->MaximumLength);
|
||||
if (ValueString->Buffer == NULL)
|
||||
{
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
@ -532,9 +526,7 @@ RtlQueryRegistryValues(IN ULONG RelativeTo,
|
|||
|
||||
ValueString = (PUNICODE_STRING)QueryEntry->EntryContext;
|
||||
|
||||
ExpandBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
|
||||
0,
|
||||
ValueInfo->DataLength * 2);
|
||||
ExpandBuffer = ExAllocatePool(PagedPool, ValueInfo->DataLength * 2);
|
||||
if (ExpandBuffer == NULL)
|
||||
{
|
||||
Status = STATUS_NO_MEMORY;
|
||||
|
@ -557,9 +549,7 @@ RtlQueryRegistryValues(IN ULONG RelativeTo,
|
|||
{
|
||||
ValueString->MaximumLength = EnvExpandedValue.Length + sizeof(WCHAR);
|
||||
ValueString->Length = EnvExpandedValue.Length;
|
||||
ValueString->Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
|
||||
0,
|
||||
ValueString->MaximumLength);
|
||||
ValueString->Buffer = ExAllocatePool(PagedPool, ValueString->MaximumLength);
|
||||
if (ValueString->Buffer == NULL)
|
||||
{
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
@ -577,9 +567,7 @@ RtlQueryRegistryValues(IN ULONG RelativeTo,
|
|||
ValueString->Length);
|
||||
((PWSTR)ValueString->Buffer)[ValueString->Length / sizeof(WCHAR)] = 0;
|
||||
|
||||
RtlFreeHeap(RtlGetProcessHeap(),
|
||||
0,
|
||||
ExpandBuffer);
|
||||
ExFreePool(ExpandBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -595,9 +583,7 @@ RtlQueryRegistryValues(IN ULONG RelativeTo,
|
|||
|
||||
}
|
||||
|
||||
RtlFreeHeap(RtlGetProcessHeap(),
|
||||
0,
|
||||
ValueInfo);
|
||||
ExFreePool(ValueInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -608,9 +594,7 @@ RtlQueryRegistryValues(IN ULONG RelativeTo,
|
|||
QueryEntry->Name);
|
||||
|
||||
BufferSize = sizeof (KEY_VALUE_PARTIAL_INFORMATION) + 4096;
|
||||
ValueInfo = RtlAllocateHeap(RtlGetProcessHeap(),
|
||||
0,
|
||||
BufferSize);
|
||||
ValueInfo = ExAllocatePool(PagedPool, BufferSize);
|
||||
if (ValueInfo == NULL)
|
||||
{
|
||||
Status = STATUS_NO_MEMORY;
|
||||
|
@ -659,9 +643,7 @@ RtlQueryRegistryValues(IN ULONG RelativeTo,
|
|||
{
|
||||
DPRINT("Expand REG_EXPAND_SZ type\n");
|
||||
|
||||
ExpandBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
|
||||
0,
|
||||
ValueInfo->DataLength * 2);
|
||||
ExpandBuffer = ExAllocatePool(PagedPool, ValueInfo->DataLength * 2);
|
||||
if (ExpandBuffer == NULL)
|
||||
{
|
||||
Status = STATUS_NO_MEMORY;
|
||||
|
@ -688,9 +670,7 @@ RtlQueryRegistryValues(IN ULONG RelativeTo,
|
|||
Context,
|
||||
QueryEntry->EntryContext);
|
||||
|
||||
RtlFreeHeap(RtlGetProcessHeap(),
|
||||
0,
|
||||
ExpandBuffer);
|
||||
ExFreePool(ExpandBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -708,9 +688,7 @@ RtlQueryRegistryValues(IN ULONG RelativeTo,
|
|||
|
||||
}
|
||||
|
||||
RtlFreeHeap(RtlGetProcessHeap(),
|
||||
0,
|
||||
ValueInfo);
|
||||
ExFreePool(ValueInfo);
|
||||
if (!NT_SUCCESS(Status))
|
||||
break;
|
||||
}
|
||||
|
@ -731,18 +709,14 @@ RtlQueryRegistryValues(IN ULONG RelativeTo,
|
|||
DPRINT("Enumerate values\n");
|
||||
|
||||
BufferSize = sizeof(KEY_VALUE_FULL_INFORMATION) + 4096;
|
||||
FullValueInfo = RtlAllocateHeap(RtlGetProcessHeap(),
|
||||
0,
|
||||
BufferSize);
|
||||
FullValueInfo = ExAllocatePool(PagedPool, BufferSize);
|
||||
if (FullValueInfo == NULL)
|
||||
{
|
||||
Status = STATUS_NO_MEMORY;
|
||||
break;
|
||||
}
|
||||
ValueNameSize = 256 * sizeof(WCHAR);
|
||||
ValueName = RtlAllocateHeap(RtlGetProcessHeap(),
|
||||
0,
|
||||
ValueNameSize);
|
||||
ValueName = ExAllocatePool(PagedPool, ValueNameSize);
|
||||
if (ValueName == NULL)
|
||||
{
|
||||
Status = STATUS_NO_MEMORY;
|
||||
|
@ -775,9 +749,7 @@ RtlQueryRegistryValues(IN ULONG RelativeTo,
|
|||
if (FullValueInfo->NameLength > ValueNameSize - sizeof(WCHAR))
|
||||
{
|
||||
/* Should not happen, because the name length is limited to 255 characters */
|
||||
RtlFreeHeap(RtlGetProcessHeap(),
|
||||
0,
|
||||
ValueName);
|
||||
ExFreePool(ValueName);
|
||||
ValueNameSize = FullValueInfo->NameLength + sizeof(WCHAR);
|
||||
ValueName = RtlAllocateHeap(RtlGetProcessHeap(),
|
||||
0,
|
||||
|
@ -820,9 +792,7 @@ RtlQueryRegistryValues(IN ULONG RelativeTo,
|
|||
DPRINT("Expand REG_EXPAND_SZ type\n");
|
||||
|
||||
StringPtr = (PWSTR)((PVOID)FullValueInfo + FullValueInfo->DataOffset);
|
||||
ExpandBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
|
||||
0,
|
||||
FullValueInfo->DataLength * 2);
|
||||
ExpandBuffer = ExAllocatePool(PagedPool, FullValueInfo->DataLength * 2);
|
||||
if (ExpandBuffer == NULL)
|
||||
{
|
||||
Status = STATUS_NO_MEMORY;
|
||||
|
@ -849,9 +819,7 @@ RtlQueryRegistryValues(IN ULONG RelativeTo,
|
|||
Context,
|
||||
QueryEntry->EntryContext);
|
||||
|
||||
RtlFreeHeap(RtlGetProcessHeap(),
|
||||
0,
|
||||
ExpandBuffer);
|
||||
ExFreePool(ExpandBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -871,12 +839,8 @@ RtlQueryRegistryValues(IN ULONG RelativeTo,
|
|||
Index++;
|
||||
}
|
||||
|
||||
RtlFreeHeap(RtlGetProcessHeap(),
|
||||
0,
|
||||
FullValueInfo);
|
||||
RtlFreeHeap(RtlGetProcessHeap(),
|
||||
0,
|
||||
ValueName);
|
||||
ExFreePool(FullValueInfo);
|
||||
ExFreePool(ValueName);
|
||||
if (!NT_SUCCESS(Status))
|
||||
break;
|
||||
}
|
|
@ -307,7 +307,6 @@ OBJECTS_CM = \
|
|||
cm/regfile.o \
|
||||
cm/registry.o \
|
||||
cm/regobj.o \
|
||||
cm/rtlfunc.o
|
||||
|
||||
# Debugger Support (Dbg)
|
||||
OBJECTS_DBG = \
|
||||
|
|
|
@ -1,758 +0,0 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: ntoskrnl/cm/rtlfunc.c
|
||||
* PURPOSE: Rtlxxx function for registry access
|
||||
* UPDATE HISTORY:
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include <ntoskrnl.h>
|
||||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
#include "cm.h"
|
||||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
|
||||
static NTSTATUS
|
||||
RtlpGetRegistryHandle(ULONG RelativeTo,
|
||||
PWSTR Path,
|
||||
BOOLEAN Create,
|
||||
PHANDLE KeyHandle)
|
||||
{
|
||||
UNICODE_STRING KeyPath;
|
||||
UNICODE_STRING KeyName;
|
||||
WCHAR KeyBuffer[MAX_PATH];
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
NTSTATUS Status;
|
||||
|
||||
if (RelativeTo & RTL_REGISTRY_HANDLE)
|
||||
{
|
||||
Status = NtDuplicateObject(NtCurrentProcess(),
|
||||
(HANDLE)Path,
|
||||
NtCurrentProcess(),
|
||||
KeyHandle,
|
||||
0,
|
||||
FALSE,
|
||||
DUPLICATE_SAME_ACCESS);
|
||||
return(Status);
|
||||
}
|
||||
|
||||
if (RelativeTo & RTL_REGISTRY_OPTIONAL)
|
||||
RelativeTo &= ~RTL_REGISTRY_OPTIONAL;
|
||||
|
||||
if (RelativeTo >= RTL_REGISTRY_MAXIMUM)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
KeyName.Length = 0;
|
||||
KeyName.MaximumLength = MAX_PATH;
|
||||
KeyName.Buffer = KeyBuffer;
|
||||
KeyBuffer[0] = 0;
|
||||
|
||||
switch (RelativeTo)
|
||||
{
|
||||
case RTL_REGISTRY_SERVICES:
|
||||
RtlAppendUnicodeToString(&KeyName,
|
||||
L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
|
||||
break;
|
||||
|
||||
case RTL_REGISTRY_CONTROL:
|
||||
RtlAppendUnicodeToString(&KeyName,
|
||||
L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\");
|
||||
break;
|
||||
|
||||
case RTL_REGISTRY_WINDOWS_NT:
|
||||
RtlAppendUnicodeToString(&KeyName,
|
||||
L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\");
|
||||
break;
|
||||
|
||||
case RTL_REGISTRY_DEVICEMAP:
|
||||
RtlAppendUnicodeToString(&KeyName,
|
||||
L"\\Registry\\Machine\\Hardware\\DeviceMap\\");
|
||||
break;
|
||||
|
||||
case RTL_REGISTRY_USER:
|
||||
Status = RtlFormatCurrentUserKeyPath (&KeyPath);
|
||||
if (!NT_SUCCESS(Status))
|
||||
return(Status);
|
||||
RtlAppendUnicodeStringToString (&KeyName,
|
||||
&KeyPath);
|
||||
RtlFreeUnicodeString (&KeyPath);
|
||||
RtlAppendUnicodeToString (&KeyName,
|
||||
L"\\");
|
||||
break;
|
||||
|
||||
/* ReactOS specific */
|
||||
case RTL_REGISTRY_ENUM:
|
||||
RtlAppendUnicodeToString(&KeyName,
|
||||
L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
|
||||
break;
|
||||
}
|
||||
|
||||
if (Path[0] == L'\\' && RelativeTo != RTL_REGISTRY_ABSOLUTE)
|
||||
{
|
||||
Path++;
|
||||
}
|
||||
RtlAppendUnicodeToString(&KeyName,
|
||||
Path);
|
||||
|
||||
DPRINT("KeyName '%wZ'\n", &KeyName);
|
||||
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&KeyName,
|
||||
OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
if (Create == TRUE)
|
||||
{
|
||||
Status = NtCreateKey(KeyHandle,
|
||||
KEY_ALL_ACCESS,
|
||||
&ObjectAttributes,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = NtOpenKey(KeyHandle,
|
||||
KEY_ALL_ACCESS,
|
||||
&ObjectAttributes);
|
||||
}
|
||||
|
||||
return(Status);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
NTSTATUS STDCALL
|
||||
RtlCheckRegistryKey(IN ULONG RelativeTo,
|
||||
IN PWSTR Path)
|
||||
{
|
||||
HANDLE KeyHandle;
|
||||
NTSTATUS Status;
|
||||
|
||||
Status = RtlpGetRegistryHandle(RelativeTo,
|
||||
Path,
|
||||
FALSE,
|
||||
&KeyHandle);
|
||||
if (!NT_SUCCESS(Status))
|
||||
return(Status);
|
||||
|
||||
NtClose(KeyHandle);
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
NTSTATUS STDCALL
|
||||
RtlCreateRegistryKey(IN ULONG RelativeTo,
|
||||
IN PWSTR Path)
|
||||
{
|
||||
HANDLE KeyHandle;
|
||||
NTSTATUS Status;
|
||||
|
||||
Status = RtlpGetRegistryHandle(RelativeTo,
|
||||
Path,
|
||||
TRUE,
|
||||
&KeyHandle);
|
||||
if (!NT_SUCCESS(Status))
|
||||
return(Status);
|
||||
|
||||
NtClose(KeyHandle);
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
NTSTATUS STDCALL
|
||||
RtlDeleteRegistryValue(IN ULONG RelativeTo,
|
||||
IN PCWSTR Path,
|
||||
IN PCWSTR ValueName)
|
||||
{
|
||||
HANDLE KeyHandle;
|
||||
NTSTATUS Status;
|
||||
UNICODE_STRING Name;
|
||||
|
||||
Status = RtlpGetRegistryHandle(RelativeTo,
|
||||
(PWSTR) Path,
|
||||
TRUE,
|
||||
&KeyHandle);
|
||||
if (!NT_SUCCESS(Status))
|
||||
return(Status);
|
||||
|
||||
RtlInitUnicodeString(&Name,
|
||||
ValueName);
|
||||
|
||||
NtDeleteValueKey(KeyHandle,
|
||||
&Name);
|
||||
|
||||
NtClose(KeyHandle);
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
NTSTATUS STDCALL
|
||||
RtlFormatCurrentUserKeyPath (OUT PUNICODE_STRING KeyPath)
|
||||
{
|
||||
HANDLE TokenHandle;
|
||||
UCHAR Buffer[256];
|
||||
PSID_AND_ATTRIBUTES SidBuffer;
|
||||
ULONG Length;
|
||||
UNICODE_STRING SidString;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT ("RtlFormatCurrentUserKeyPath() called\n");
|
||||
|
||||
Status = ZwOpenThreadToken (NtCurrentThread (),
|
||||
TOKEN_READ,
|
||||
TRUE,
|
||||
&TokenHandle);
|
||||
if (!NT_SUCCESS (Status))
|
||||
{
|
||||
if (Status != STATUS_NO_TOKEN)
|
||||
{
|
||||
DPRINT1 ("ZwOpenThreadToken() failed (Status %lx)\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = ZwOpenProcessToken (NtCurrentProcess (),
|
||||
TOKEN_READ,
|
||||
&TokenHandle);
|
||||
if (!NT_SUCCESS (Status))
|
||||
{
|
||||
DPRINT1 ("ZwOpenProcessToken() failed (Status %lx)\n", Status);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
SidBuffer = (PSID_AND_ATTRIBUTES)Buffer;
|
||||
Status = ZwQueryInformationToken (TokenHandle,
|
||||
TokenUser,
|
||||
(PVOID)SidBuffer,
|
||||
256,
|
||||
&Length);
|
||||
NtClose (TokenHandle);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT ("ZwQueryInformationToken() failed (Status %lx)\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = RtlConvertSidToUnicodeString (&SidString,
|
||||
SidBuffer[0].Sid,
|
||||
TRUE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1 ("RtlConvertSidToUnicodeString() failed (Status %lx)\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
DPRINT ("SidString: '%wZ'\n", &SidString);
|
||||
|
||||
Length = SidString.Length + sizeof(L"\\Registry\\User\\");
|
||||
DPRINT ("Length: %lu\n", Length);
|
||||
|
||||
KeyPath->Length = 0;
|
||||
KeyPath->MaximumLength = Length;
|
||||
KeyPath->Buffer = ExAllocatePool (NonPagedPool,
|
||||
KeyPath->MaximumLength);
|
||||
if (KeyPath->Buffer == NULL)
|
||||
{
|
||||
DPRINT1 ("RtlAllocateHeap() failed\n");
|
||||
RtlFreeUnicodeString (&SidString);
|
||||
return STATUS_NO_TOKEN;
|
||||
}
|
||||
|
||||
RtlAppendUnicodeToString (KeyPath,
|
||||
L"\\Registry\\User\\");
|
||||
RtlAppendUnicodeStringToString (KeyPath,
|
||||
&SidString);
|
||||
RtlFreeUnicodeString (&SidString);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS STDCALL
|
||||
RtlOpenCurrentUser(IN ACCESS_MASK DesiredAccess,
|
||||
OUT PHANDLE KeyHandle)
|
||||
{
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
UNICODE_STRING KeyPath;
|
||||
NTSTATUS Status;
|
||||
|
||||
Status = RtlFormatCurrentUserKeyPath(&KeyPath);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&KeyPath,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
NULL,
|
||||
NULL);
|
||||
Status = NtOpenKey(KeyHandle,
|
||||
DesiredAccess,
|
||||
&ObjectAttributes);
|
||||
RtlFreeUnicodeString(&KeyPath);
|
||||
if (NT_SUCCESS(Status))
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
RtlInitUnicodeString (&KeyPath,
|
||||
L"\\Registry\\User\\.Default");
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&KeyPath,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
NULL,
|
||||
NULL);
|
||||
Status = NtOpenKey(KeyHandle,
|
||||
DesiredAccess,
|
||||
&ObjectAttributes);
|
||||
return(Status);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
NTSTATUS STDCALL
|
||||
RtlQueryRegistryValues(IN ULONG RelativeTo,
|
||||
IN PCWSTR Path,
|
||||
IN PRTL_QUERY_REGISTRY_TABLE QueryTable,
|
||||
IN PVOID Context,
|
||||
IN PVOID Environment)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
HANDLE BaseKeyHandle;
|
||||
HANDLE CurrentKeyHandle;
|
||||
PRTL_QUERY_REGISTRY_TABLE QueryEntry;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
UNICODE_STRING KeyName;
|
||||
PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
|
||||
PKEY_VALUE_FULL_INFORMATION FullValueInfo;
|
||||
ULONG BufferSize;
|
||||
ULONG ResultSize;
|
||||
ULONG ValueNameSize;
|
||||
ULONG Index;
|
||||
ULONG StringLen;
|
||||
PWSTR StringPtr;
|
||||
PWSTR ValueName;
|
||||
|
||||
DPRINT("RtlQueryRegistryValues() called\n");
|
||||
|
||||
Status = RtlpGetRegistryHandle(RelativeTo,
|
||||
(PWSTR) Path,
|
||||
FALSE,
|
||||
&BaseKeyHandle);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("RtlpGetRegistryHandle() failed with status %x\n", Status);
|
||||
return(Status);
|
||||
}
|
||||
|
||||
CurrentKeyHandle = BaseKeyHandle;
|
||||
QueryEntry = QueryTable;
|
||||
while ((QueryEntry->QueryRoutine != NULL) ||
|
||||
(QueryEntry->Name != NULL))
|
||||
{
|
||||
if (((QueryEntry->Flags & (RTL_QUERY_REGISTRY_SUBKEY | RTL_QUERY_REGISTRY_TOPKEY)) != 0) &&
|
||||
(BaseKeyHandle != CurrentKeyHandle))
|
||||
{
|
||||
NtClose(CurrentKeyHandle);
|
||||
CurrentKeyHandle = BaseKeyHandle;
|
||||
}
|
||||
|
||||
if (QueryEntry->Flags & RTL_QUERY_REGISTRY_SUBKEY)
|
||||
{
|
||||
DPRINT("Open new subkey: %S\n", QueryEntry->Name);
|
||||
|
||||
RtlInitUnicodeString(&KeyName,
|
||||
QueryEntry->Name);
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&KeyName,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
BaseKeyHandle,
|
||||
NULL);
|
||||
Status = NtOpenKey(&CurrentKeyHandle,
|
||||
KEY_ALL_ACCESS,
|
||||
&ObjectAttributes);
|
||||
if (!NT_SUCCESS(Status))
|
||||
break;
|
||||
}
|
||||
else if (QueryEntry->Flags & RTL_QUERY_REGISTRY_DIRECT)
|
||||
{
|
||||
DPRINT("Query value directly: %S\n", QueryEntry->Name);
|
||||
|
||||
RtlInitUnicodeString(&KeyName,
|
||||
QueryEntry->Name);
|
||||
|
||||
BufferSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 4096;
|
||||
ValueInfo = ExAllocatePool(PagedPool, BufferSize);
|
||||
if (ValueInfo == NULL)
|
||||
{
|
||||
Status = STATUS_NO_MEMORY;
|
||||
break;
|
||||
}
|
||||
|
||||
Status = ZwQueryValueKey(CurrentKeyHandle,
|
||||
&KeyName,
|
||||
KeyValuePartialInformation,
|
||||
ValueInfo,
|
||||
BufferSize,
|
||||
&ResultSize);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
if (QueryEntry->Flags & RTL_QUERY_REGISTRY_REQUIRED)
|
||||
{
|
||||
ExFreePool(ValueInfo);
|
||||
Status = STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
goto ByeBye;
|
||||
}
|
||||
|
||||
if (QueryEntry->DefaultType == REG_SZ)
|
||||
{
|
||||
PUNICODE_STRING ValueString;
|
||||
PUNICODE_STRING SourceString;
|
||||
|
||||
SourceString = (PUNICODE_STRING)QueryEntry->DefaultData;
|
||||
ValueString = (PUNICODE_STRING)QueryEntry->EntryContext;
|
||||
if (ValueString->Buffer == 0)
|
||||
{
|
||||
ValueString->Length = SourceString->Length;
|
||||
ValueString->MaximumLength = SourceString->MaximumLength;
|
||||
ValueString->Buffer = ExAllocatePool(PagedPool,
|
||||
ValueString->MaximumLength);
|
||||
if (!ValueString->Buffer)
|
||||
break;
|
||||
ValueString->Buffer[0] = 0;
|
||||
memcpy(ValueString->Buffer,
|
||||
SourceString->Buffer,
|
||||
SourceString->MaximumLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
ValueString->Length = RtlRosMin(SourceString->Length,
|
||||
ValueString->MaximumLength - sizeof(WCHAR));
|
||||
memcpy(ValueString->Buffer,
|
||||
SourceString->Buffer,
|
||||
ValueString->Length);
|
||||
((PWSTR)ValueString->Buffer)[ValueString->Length / sizeof(WCHAR)] = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(QueryEntry->EntryContext,
|
||||
QueryEntry->DefaultData,
|
||||
QueryEntry->DefaultLength);
|
||||
}
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ValueInfo->Type == REG_SZ ||
|
||||
ValueInfo->Type == REG_MULTI_SZ ||
|
||||
ValueInfo->Type == REG_EXPAND_SZ)
|
||||
{
|
||||
PUNICODE_STRING ValueString;
|
||||
|
||||
ValueString = (PUNICODE_STRING)QueryEntry->EntryContext;
|
||||
if (ValueString->Buffer == 0)
|
||||
{
|
||||
RtlInitUnicodeString(ValueString,
|
||||
NULL);
|
||||
ValueString->MaximumLength = ValueInfo->DataLength;
|
||||
ValueString->Buffer = ExAllocatePool(PagedPool,
|
||||
ValueString->MaximumLength);
|
||||
if (!ValueString->Buffer)
|
||||
break;
|
||||
ValueString->Buffer[0] = 0;
|
||||
}
|
||||
ValueString->Length = RtlRosMin(ValueInfo->DataLength,
|
||||
ValueString->MaximumLength) - sizeof(WCHAR);
|
||||
memcpy(ValueString->Buffer,
|
||||
ValueInfo->Data,
|
||||
ValueString->Length);
|
||||
((PWSTR)ValueString->Buffer)[ValueString->Length / sizeof(WCHAR)] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(QueryEntry->EntryContext,
|
||||
ValueInfo->Data,
|
||||
ValueInfo->DataLength);
|
||||
}
|
||||
}
|
||||
|
||||
if (QueryEntry->Flags & RTL_QUERY_REGISTRY_DELETE)
|
||||
{
|
||||
DPRINT("FIXME: Delete value: %S\n", QueryEntry->Name);
|
||||
|
||||
}
|
||||
|
||||
ExFreePool(ValueInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT("Query value via query routine: %S\n", QueryEntry->Name);
|
||||
|
||||
if (QueryEntry->Name != NULL)
|
||||
{
|
||||
DPRINT("Callback\n");
|
||||
|
||||
RtlInitUnicodeString(&KeyName,
|
||||
QueryEntry->Name);
|
||||
|
||||
BufferSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 4096;
|
||||
ValueInfo = ExAllocatePool(PagedPool,
|
||||
BufferSize);
|
||||
if (ValueInfo == NULL)
|
||||
{
|
||||
Status = STATUS_NO_MEMORY;
|
||||
break;
|
||||
}
|
||||
|
||||
Status = NtQueryValueKey(CurrentKeyHandle,
|
||||
&KeyName,
|
||||
KeyValuePartialInformation,
|
||||
ValueInfo,
|
||||
BufferSize,
|
||||
&ResultSize);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
if (! (QueryEntry->Flags & RTL_QUERY_REGISTRY_REQUIRED))
|
||||
{
|
||||
Status = QueryEntry->QueryRoutine(QueryEntry->Name,
|
||||
QueryEntry->DefaultType,
|
||||
QueryEntry->DefaultData,
|
||||
QueryEntry->DefaultLength,
|
||||
Context,
|
||||
QueryEntry->EntryContext);
|
||||
}
|
||||
}
|
||||
else if ((ValueInfo->Type == REG_MULTI_SZ) &&
|
||||
!(QueryEntry->Flags & RTL_QUERY_REGISTRY_NOEXPAND))
|
||||
{
|
||||
DPRINT("Expand REG_MULTI_SZ type\n");
|
||||
StringPtr = (PWSTR)ValueInfo->Data;
|
||||
while (*StringPtr != 0)
|
||||
{
|
||||
StringLen = (wcslen(StringPtr) + 1) * sizeof(WCHAR);
|
||||
Status = QueryEntry->QueryRoutine(QueryEntry->Name,
|
||||
REG_SZ,
|
||||
(PVOID)StringPtr,
|
||||
StringLen,
|
||||
Context,
|
||||
QueryEntry->EntryContext);
|
||||
if(!NT_SUCCESS(Status))
|
||||
break;
|
||||
StringPtr = (PWSTR)((PUCHAR)StringPtr + StringLen);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = QueryEntry->QueryRoutine(QueryEntry->Name,
|
||||
ValueInfo->Type,
|
||||
ValueInfo->Data,
|
||||
ValueInfo->DataLength,
|
||||
Context,
|
||||
QueryEntry->EntryContext);
|
||||
}
|
||||
|
||||
if (QueryEntry->Flags & RTL_QUERY_REGISTRY_DELETE)
|
||||
{
|
||||
DPRINT("FIXME: Delete value: %S\n", QueryEntry->Name);
|
||||
|
||||
}
|
||||
|
||||
ExFreePool(ValueInfo);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
break;
|
||||
}
|
||||
else if (QueryEntry->Flags & RTL_QUERY_REGISTRY_NOVALUE)
|
||||
{
|
||||
DPRINT("Simple callback\n");
|
||||
Status = QueryEntry->QueryRoutine(NULL,
|
||||
REG_NONE,
|
||||
NULL,
|
||||
0,
|
||||
Context,
|
||||
QueryEntry->EntryContext);
|
||||
if (!NT_SUCCESS(Status))
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT("Enumerate values\n");
|
||||
|
||||
BufferSize = sizeof(KEY_VALUE_FULL_INFORMATION) + 4096;
|
||||
FullValueInfo = ExAllocatePool(PagedPool,
|
||||
BufferSize);
|
||||
if (FullValueInfo == NULL)
|
||||
{
|
||||
Status = STATUS_NO_MEMORY;
|
||||
break;
|
||||
}
|
||||
ValueNameSize = 256 * sizeof(WCHAR);
|
||||
ValueName = ExAllocatePool(PagedPool,
|
||||
ValueNameSize);
|
||||
if (ValueName == NULL)
|
||||
{
|
||||
Status = STATUS_NO_MEMORY;
|
||||
break;
|
||||
}
|
||||
Index = 0;
|
||||
while (TRUE)
|
||||
{
|
||||
Status = NtEnumerateValueKey(CurrentKeyHandle,
|
||||
Index,
|
||||
KeyValueFullInformation,
|
||||
FullValueInfo,
|
||||
BufferSize,
|
||||
&ResultSize);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
if ((Status == STATUS_NO_MORE_ENTRIES) &&
|
||||
(Index == 0) &&
|
||||
(QueryEntry->Flags & RTL_QUERY_REGISTRY_REQUIRED))
|
||||
{
|
||||
Status = STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
}
|
||||
else if (Status == STATUS_NO_MORE_ENTRIES)
|
||||
{
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (FullValueInfo->NameLength > ValueNameSize - sizeof(WCHAR))
|
||||
{
|
||||
/* Should not happen, because the name length is limited to 255 characters */
|
||||
ExFreePool(ValueName);
|
||||
ValueNameSize = FullValueInfo->NameLength + sizeof(WCHAR);
|
||||
ValueName = ExAllocatePool(PagedPool, ValueNameSize);
|
||||
if (ValueName == NULL)
|
||||
{
|
||||
Status = STATUS_NO_MEMORY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
RtlCopyMemory(ValueName,
|
||||
FullValueInfo->Name,
|
||||
FullValueInfo->NameLength);
|
||||
ValueName[FullValueInfo->NameLength / sizeof(WCHAR)] = 0;
|
||||
|
||||
if ((FullValueInfo->Type == REG_MULTI_SZ) &&
|
||||
!(QueryEntry->Flags & RTL_QUERY_REGISTRY_NOEXPAND))
|
||||
{
|
||||
DPRINT("Expand REG_MULTI_SZ type\n");
|
||||
|
||||
StringPtr = (PWSTR)((char*)FullValueInfo + FullValueInfo->DataOffset);
|
||||
while (*StringPtr != 0)
|
||||
{
|
||||
StringLen = (wcslen(StringPtr) + 1) * sizeof(WCHAR);
|
||||
Status = QueryEntry->QueryRoutine(ValueName,
|
||||
REG_SZ,
|
||||
(PVOID)StringPtr,
|
||||
StringLen,
|
||||
Context,
|
||||
QueryEntry->EntryContext);
|
||||
if(!NT_SUCCESS(Status))
|
||||
break;
|
||||
StringPtr = (PWSTR)((PUCHAR)StringPtr + StringLen);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = QueryEntry->QueryRoutine(ValueName,
|
||||
FullValueInfo->Type,
|
||||
(char*)FullValueInfo + FullValueInfo->DataOffset,
|
||||
FullValueInfo->DataLength,
|
||||
Context,
|
||||
QueryEntry->EntryContext);
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
break;
|
||||
|
||||
/* FIXME: How will these be deleted? */
|
||||
|
||||
Index++;
|
||||
}
|
||||
|
||||
ExFreePool(FullValueInfo);
|
||||
ExFreePool(ValueName);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QueryEntry++;
|
||||
}
|
||||
|
||||
ByeBye:
|
||||
|
||||
if (CurrentKeyHandle != BaseKeyHandle)
|
||||
NtClose(CurrentKeyHandle);
|
||||
|
||||
NtClose(BaseKeyHandle);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
NTSTATUS STDCALL
|
||||
RtlWriteRegistryValue(IN ULONG RelativeTo,
|
||||
IN PCWSTR Path,
|
||||
IN PCWSTR ValueName,
|
||||
IN ULONG ValueType,
|
||||
IN PVOID ValueData,
|
||||
IN ULONG ValueLength)
|
||||
{
|
||||
HANDLE KeyHandle;
|
||||
NTSTATUS Status;
|
||||
UNICODE_STRING Name;
|
||||
|
||||
Status = RtlpGetRegistryHandle(RelativeTo,
|
||||
(PWSTR) Path,
|
||||
TRUE,
|
||||
&KeyHandle);
|
||||
if (!NT_SUCCESS(Status))
|
||||
return(Status);
|
||||
|
||||
RtlInitUnicodeString(&Name,
|
||||
ValueName);
|
||||
|
||||
NtSetValueKey(KeyHandle,
|
||||
&Name,
|
||||
0,
|
||||
ValueType,
|
||||
ValueData,
|
||||
ValueLength);
|
||||
|
||||
NtClose(KeyHandle);
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
/* EOF */
|
Loading…
Reference in a new issue