Implemented value enumeration in RtlQueryRegistryValues().

svn path=/trunk/; revision=2603
This commit is contained in:
Eric Kohl 2002-02-05 15:42:41 +00:00
parent 5d67a14618
commit 916157c159
2 changed files with 779 additions and 569 deletions

File diff suppressed because it is too large Load diff

View file

@ -133,151 +133,258 @@ RtlQueryRegistryValues(IN ULONG RelativeTo,
IN PVOID Context, IN PVOID Context,
IN PVOID Environment) IN PVOID Environment)
{ {
NTSTATUS Status; NTSTATUS Status;
HANDLE BaseKeyHandle; HANDLE BaseKeyHandle;
HANDLE CurrentKeyHandle; HANDLE CurrentKeyHandle;
PRTL_QUERY_REGISTRY_TABLE QueryEntry; PRTL_QUERY_REGISTRY_TABLE QueryEntry;
OBJECT_ATTRIBUTES ObjectAttributes; OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING KeyName; UNICODE_STRING KeyName;
PKEY_VALUE_PARTIAL_INFORMATION ValueInfo; PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
ULONG BufferSize; PKEY_VALUE_FULL_INFORMATION FullValueInfo;
ULONG ResultSize; ULONG BufferSize;
ULONG ResultSize;
DPRINT("RtlQueryRegistryValues() called\n"); ULONG Index;
Status = RtlpGetRegistryHandle(RelativeTo, DPRINT("RtlQueryRegistryValues() called\n");
Path,
FALSE, Status = RtlpGetRegistryHandle(RelativeTo,
&BaseKeyHandle); Path,
if (!NT_SUCCESS(Status)) FALSE,
&BaseKeyHandle);
if (!NT_SUCCESS(Status))
{ {
DPRINT("RtlpGetRegistryHandle() failed with status %x\n", Status); DPRINT("RtlpGetRegistryHandle() failed with status %x\n", Status);
return Status; return(Status);
} }
CurrentKeyHandle = BaseKeyHandle; CurrentKeyHandle = BaseKeyHandle;
QueryEntry = QueryTable; QueryEntry = QueryTable;
while ((QueryEntry->QueryRoutine != NULL) || while ((QueryEntry->QueryRoutine != NULL) ||
(QueryEntry->Name != NULL)) (QueryEntry->Name != NULL))
{ {
//CSH: Was: //CSH: Was:
//if ((QueryEntry->QueryRoutine == NULL) && //if ((QueryEntry->QueryRoutine == NULL) &&
// ((QueryEntry->Flags & (RTL_QUERY_REGISTRY_SUBKEY | RTL_QUERY_REGISTRY_DIRECT)) != 0)) // ((QueryEntry->Flags & (RTL_QUERY_REGISTRY_SUBKEY | RTL_QUERY_REGISTRY_DIRECT)) != 0))
// Which is more correct? // Which is more correct?
if ((QueryEntry->QueryRoutine == NULL) && if ((QueryEntry->QueryRoutine == NULL) &&
((QueryEntry->Flags & RTL_QUERY_REGISTRY_SUBKEY) != 0)) ((QueryEntry->Flags & RTL_QUERY_REGISTRY_SUBKEY) != 0))
{ {
DPRINT("Bad parameters\n"); DPRINT("Bad parameters\n");
Status = STATUS_INVALID_PARAMETER; Status = STATUS_INVALID_PARAMETER;
break; break;
} }
DPRINT("Name: %S\n", QueryEntry->Name); DPRINT("Name: %S\n", QueryEntry->Name);
if (((QueryEntry->Flags & (RTL_QUERY_REGISTRY_SUBKEY | RTL_QUERY_REGISTRY_TOPKEY)) != 0) && if (((QueryEntry->Flags & (RTL_QUERY_REGISTRY_SUBKEY | RTL_QUERY_REGISTRY_TOPKEY)) != 0) &&
(BaseKeyHandle != CurrentKeyHandle)) (BaseKeyHandle != CurrentKeyHandle))
{ {
NtClose(CurrentKeyHandle); NtClose(CurrentKeyHandle);
CurrentKeyHandle = BaseKeyHandle; CurrentKeyHandle = BaseKeyHandle;
} }
if (QueryEntry->Flags & RTL_QUERY_REGISTRY_SUBKEY) if (QueryEntry->Flags & RTL_QUERY_REGISTRY_SUBKEY)
{ {
DPRINT("Open new subkey: %S\n", QueryEntry->Name); DPRINT("Open new subkey: %S\n", QueryEntry->Name);
RtlInitUnicodeString(&KeyName, RtlInitUnicodeString(&KeyName,
QueryEntry->Name); QueryEntry->Name);
InitializeObjectAttributes(&ObjectAttributes, InitializeObjectAttributes(&ObjectAttributes,
&KeyName, &KeyName,
OBJ_CASE_INSENSITIVE, OBJ_CASE_INSENSITIVE,
BaseKeyHandle, BaseKeyHandle,
NULL); NULL);
Status = NtOpenKey(&CurrentKeyHandle, Status = NtOpenKey(&CurrentKeyHandle,
KEY_ALL_ACCESS, KEY_ALL_ACCESS,
&ObjectAttributes); &ObjectAttributes);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
break; break;
} }
else if (QueryEntry->Flags & RTL_QUERY_REGISTRY_DIRECT) else if (QueryEntry->Flags & RTL_QUERY_REGISTRY_DIRECT)
{ {
DPRINT("Query value directly: %S\n", QueryEntry->Name); DPRINT("Query value directly: %S\n", QueryEntry->Name);
RtlInitUnicodeString(&KeyName, RtlInitUnicodeString(&KeyName,
QueryEntry->Name); QueryEntry->Name);
BufferSize = sizeof (KEY_VALUE_PARTIAL_INFORMATION) + 4096; BufferSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 4096;
ValueInfo = ExAllocatePool(PagedPool, BufferSize); ValueInfo = ExAllocatePool(PagedPool, BufferSize);
if (ValueInfo == NULL) if (ValueInfo == NULL)
{ {
Status = STATUS_NO_MEMORY;
break;
}
Status = ZwQueryValueKey(CurrentKeyHandle,
&KeyName,
KeyValuePartialInformation,
ValueInfo,
BufferSize,
&ResultSize);
if (!NT_SUCCESS(Status))
{
DPRINT("ZwQueryValueKey() failed with status %x\n", Status);
ExFreePool(ValueInfo);
break;
}
else
{
if (ValueInfo->Type == REG_SZ)
{
PUNICODE_STRING ValueString;
ValueString = (PUNICODE_STRING)QueryEntry->EntryContext;
if (ValueString->Buffer == 0)
{
RtlInitUnicodeString(ValueString,
NULL);
ValueString->MaximumLength = 256 * sizeof(WCHAR);
ValueString->Buffer = ExAllocatePool(PagedPool,
ValueString->MaximumLength);
if (!ValueString->Buffer)
break;
ValueString->Buffer[0] = 0;
}
ValueString->Length = RtlMin(ValueInfo->DataLength,
ValueString->MaximumLength - sizeof(WCHAR));
memcpy(ValueString->Buffer,
ValueInfo->Data,
ValueInfo->DataLength);
((PWSTR)ValueString->Buffer)[ValueString->Length / sizeof(WCHAR)] = 0;
}
else
{
memcpy(QueryEntry->EntryContext,
ValueInfo->Data,
ValueInfo->DataLength);
}
}
ExFreePool(ValueInfo);
}
else
{
DPRINT("Query value via query routine: %S\n", QueryEntry->Name);
if (QueryEntry->Name != NULL)
{
RtlInitUnicodeString(&KeyName,
QueryEntry->Name);
BufferSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 4096;
ValueInfo = ExAllocatePool(PagedPool,
BufferSize);
if (ValueInfo == NULL)
{
Status = STATUS_NO_MEMORY; Status = STATUS_NO_MEMORY;
break; break;
} }
Status = ZwQueryValueKey(CurrentKeyHandle, Status = NtQueryValueKey(CurrentKeyHandle,
&KeyName, &KeyName,
KeyValuePartialInformation, KeyValuePartialInformation,
ValueInfo, ValueInfo,
BufferSize, BufferSize,
&ResultSize); &ResultSize);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT("ZwQueryValueKey() failed with status %x\n", Status); Status = QueryEntry->QueryRoutine(QueryEntry->Name,
ExFreePool(ValueInfo); QueryEntry->DefaultType,
QueryEntry->DefaultData,
QueryEntry->DefaultLength,
Context,
QueryEntry->EntryContext);
}
else
{
Status = QueryEntry->QueryRoutine(QueryEntry->Name,
ValueInfo->Type,
ValueInfo->Data,
ValueInfo->DataLength,
Context,
QueryEntry->EntryContext);
}
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 (ValueInfo == NULL)
{
Status = STATUS_NO_MEMORY;
break; break;
} }
else
{ Index = 0;
if (ValueInfo->Type == REG_SZ) while (TRUE)
{
Status = NtEnumerateValueKey(CurrentKeyHandle,
Index,
KeyValueFullInformation,
FullValueInfo,
BufferSize,
&ResultSize);
if (!NT_SUCCESS(Status))
{ {
PUNICODE_STRING ValueString; if (Status == STATUS_NO_MORE_ENTRIES)
ValueString = (PUNICODE_STRING)QueryEntry->EntryContext; Status = STATUS_SUCCESS;
if (ValueString->Buffer == 0) break;
{
RtlInitUnicodeString(ValueString, NULL);
ValueString->MaximumLength = 256 * sizeof(WCHAR);
ValueString->Buffer = ExAllocatePool(PagedPool, ValueString->MaximumLength);
if (!ValueString->Buffer)
break;
ValueString->Buffer[0] = 0;
}
ValueString->Length = RtlMin(ValueInfo->DataLength,
ValueString->MaximumLength - sizeof(WCHAR));
memcpy(ValueString->Buffer,
ValueInfo->Data,
ValueInfo->DataLength);
((PWSTR)ValueString->Buffer)[ValueString->Length / sizeof(WCHAR)] = 0;
} }
else
{
memcpy(QueryEntry->EntryContext,
ValueInfo->Data,
ValueInfo->DataLength);
}
}
ExFreePool (ValueInfo); Status = QueryEntry->QueryRoutine(FullValueInfo->Name,
} FullValueInfo->Type,
else (PVOID)FullValueInfo + FullValueInfo->DataOffset,
{ FullValueInfo->DataLength,
DPRINT("Query value via query routine: %S\n", QueryEntry->Name); Context,
QueryEntry->EntryContext);
} if (!NT_SUCCESS(Status))
break;
if (QueryEntry->Flags & RTL_QUERY_REGISTRY_DELETE) Index++;
{ }
DPRINT("Delete value: %S\n", QueryEntry->Name);
}
QueryEntry++; ExFreePool(ValueInfo);
}
if (CurrentKeyHandle != BaseKeyHandle) if (!NT_SUCCESS(Status))
NtClose(CurrentKeyHandle); break;
}
}
NtClose(BaseKeyHandle); if (QueryEntry->Flags & RTL_QUERY_REGISTRY_DELETE)
{
DPRINT1("FIXME: Delete value: %S\n", QueryEntry->Name);
return Status; }
QueryEntry++;
}
if (CurrentKeyHandle != BaseKeyHandle)
NtClose(CurrentKeyHandle);
NtClose(BaseKeyHandle);
return(Status);
} }
@ -289,40 +396,41 @@ RtlWriteRegistryValue(IN ULONG RelativeTo,
IN PVOID ValueData, IN PVOID ValueData,
IN ULONG ValueLength) IN ULONG ValueLength)
{ {
HANDLE KeyHandle; HANDLE KeyHandle;
NTSTATUS Status; NTSTATUS Status;
UNICODE_STRING Name; UNICODE_STRING Name;
Status = RtlpGetRegistryHandle(RelativeTo, Status = RtlpGetRegistryHandle(RelativeTo,
Path, Path,
TRUE, TRUE,
&KeyHandle); &KeyHandle);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
return Status; return(Status);
RtlInitUnicodeString(&Name, RtlInitUnicodeString(&Name,
ValueName); ValueName);
NtSetValueKey(KeyHandle, NtSetValueKey(KeyHandle,
&Name, &Name,
0, 0,
ValueType, ValueType,
ValueData, ValueData,
ValueLength); ValueLength);
NtClose(KeyHandle); NtClose(KeyHandle);
return STATUS_SUCCESS; return(STATUS_SUCCESS);
} }
NTSTATUS STDCALL NTSTATUS STDCALL
RtlFormatCurrentUserKeyPath(IN OUT PUNICODE_STRING KeyPath) RtlFormatCurrentUserKeyPath(IN OUT PUNICODE_STRING KeyPath)
{ {
/* FIXME: !!! */ /* FIXME: !!! */
RtlCreateUnicodeString(KeyPath, RtlCreateUnicodeString(KeyPath,
L"\\Registry\\User\\.Default"); L"\\Registry\\User\\.Default");
return STATUS_SUCCESS; return(STATUS_SUCCESS);
} }
/* ------------------------------------------ Private Implementation */ /* ------------------------------------------ Private Implementation */