mirror of
https://github.com/reactos/reactos.git
synced 2024-10-14 21:25:14 +00:00
- Implement CmpFindSubKeyByNumber and CmpDoFindSubKeyByNumber.
- Make NtEnumerateKey a simpler wrapper around CmEnumerateKey. - Implement CmEnumerateKey by using the same API as previously, CmpQueryKeyData instead of duplicating code like the previous version did. Use CmpFindSubKeyByNumber to convert from index to key node. - Remove CmiGetValueFromKeyByIndex, CmiGetKeyFromHashByIndex, CmiCopyPackedName: deprecated. svn path=/trunk/; revision=26781
This commit is contained in:
parent
64f4f03b95
commit
475bf24b50
|
@ -163,39 +163,6 @@ CmRegisterCallback(IN PEX_CALLBACK_FUNCTION Function,
|
||||||
NTSTATUS STDCALL
|
NTSTATUS STDCALL
|
||||||
CmUnRegisterCallback(IN LARGE_INTEGER Cookie);
|
CmUnRegisterCallback(IN LARGE_INTEGER Cookie);
|
||||||
|
|
||||||
NTSTATUS STDCALL
|
|
||||||
CmpParseKey(IN PVOID ParsedObject,
|
|
||||||
IN PVOID ObjectType,
|
|
||||||
IN OUT PACCESS_STATE AccessState,
|
|
||||||
IN KPROCESSOR_MODE AccessMode,
|
|
||||||
IN ULONG Attributes,
|
|
||||||
IN OUT PUNICODE_STRING FullPath,
|
|
||||||
IN OUT PUNICODE_STRING RemainingName,
|
|
||||||
IN OUT PVOID Context OPTIONAL,
|
|
||||||
IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,
|
|
||||||
OUT PVOID *NextObject);
|
|
||||||
|
|
||||||
VOID STDCALL
|
|
||||||
CmpDeleteKeyObject(PVOID DeletedObject);
|
|
||||||
|
|
||||||
NTSTATUS STDCALL
|
|
||||||
CmpSecurityMethod(PVOID ObjectBody,
|
|
||||||
SECURITY_OPERATION_CODE OperationCode,
|
|
||||||
PSECURITY_INFORMATION SecurityInformation,
|
|
||||||
PSECURITY_DESCRIPTOR SecurityDescriptor,
|
|
||||||
PULONG BufferLength,
|
|
||||||
PSECURITY_DESCRIPTOR *OldSecurityDescriptor,
|
|
||||||
POOL_TYPE PoolType,
|
|
||||||
PGENERIC_MAPPING GenericMapping);
|
|
||||||
|
|
||||||
NTSTATUS STDCALL
|
|
||||||
CmpQueryKeyName (PVOID ObjectBody,
|
|
||||||
IN BOOLEAN HasObjectName,
|
|
||||||
POBJECT_NAME_INFORMATION ObjectNameInfo,
|
|
||||||
ULONG Length,
|
|
||||||
PULONG ReturnLength,
|
|
||||||
IN KPROCESSOR_MODE PreviousMode);
|
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
CmiAddKeyToList(IN PKEY_OBJECT ParentKey,
|
CmiAddKeyToList(IN PKEY_OBJECT ParentKey,
|
||||||
IN PKEY_OBJECT NewKey);
|
IN PKEY_OBJECT NewKey);
|
||||||
|
@ -264,12 +231,6 @@ CmiScanKeyForValue(IN PEREGISTRY_HIVE RegistryHive,
|
||||||
OUT PCM_KEY_VALUE *ValueCell,
|
OUT PCM_KEY_VALUE *ValueCell,
|
||||||
OUT HCELL_INDEX *VBOffset);
|
OUT HCELL_INDEX *VBOffset);
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
CmiGetValueFromKeyByIndex(IN PEREGISTRY_HIVE RegistryHive,
|
|
||||||
IN PCM_KEY_NODE KeyCell,
|
|
||||||
IN ULONG Index,
|
|
||||||
OUT PCM_KEY_VALUE *ValueCell);
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
CmDeleteValueKey(IN PKEY_OBJECT KeyControlBlock,
|
CmDeleteValueKey(IN PKEY_OBJECT KeyControlBlock,
|
||||||
|
@ -309,6 +270,15 @@ CmQueryKey(IN PKEY_OBJECT KeyObject,
|
||||||
IN ULONG Length,
|
IN ULONG Length,
|
||||||
IN PULONG ResultLength);
|
IN PULONG ResultLength);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
CmEnumerateKey(IN PKEY_OBJECT KeyObject,
|
||||||
|
IN ULONG Index,
|
||||||
|
IN KEY_INFORMATION_CLASS KeyInformationClass,
|
||||||
|
IN PVOID KeyInformation,
|
||||||
|
IN ULONG Length,
|
||||||
|
IN PULONG ResultLength);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
CmiAllocateHashTableCell(IN PEREGISTRY_HIVE RegistryHive,
|
CmiAllocateHashTableCell(IN PEREGISTRY_HIVE RegistryHive,
|
||||||
OUT PHASH_TABLE_CELL *HashBlock,
|
OUT PHASH_TABLE_CELL *HashBlock,
|
||||||
|
@ -316,11 +286,6 @@ CmiAllocateHashTableCell(IN PEREGISTRY_HIVE RegistryHive,
|
||||||
IN ULONG HashTableSize,
|
IN ULONG HashTableSize,
|
||||||
IN HV_STORAGE_TYPE Storage);
|
IN HV_STORAGE_TYPE Storage);
|
||||||
|
|
||||||
PCM_KEY_NODE
|
|
||||||
CmiGetKeyFromHashByIndex(PEREGISTRY_HIVE RegistryHive,
|
|
||||||
PHASH_TABLE_CELL HashBlock,
|
|
||||||
ULONG Index);
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
CmiAddKeyToHashTable(PEREGISTRY_HIVE RegistryHive,
|
CmiAddKeyToHashTable(PEREGISTRY_HIVE RegistryHive,
|
||||||
PHASH_TABLE_CELL HashCell,
|
PHASH_TABLE_CELL HashCell,
|
||||||
|
@ -362,18 +327,9 @@ CmpFindSubKeyByName(
|
||||||
IN PUNICODE_STRING SearchName
|
IN PUNICODE_STRING SearchName
|
||||||
);
|
);
|
||||||
|
|
||||||
VOID
|
|
||||||
CmiCopyPackedName(PWCHAR NameBuffer,
|
|
||||||
PUCHAR PackedNameBuffer,
|
|
||||||
ULONG PackedNameSize);
|
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
CmiSyncHives(VOID);
|
CmiSyncHives(VOID);
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
CmiCreateTempHive(PEREGISTRY_HIVE *RegistryHive);
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
CmiSaveTempHive (PEREGISTRY_HIVE Hive,
|
CmiSaveTempHive (PEREGISTRY_HIVE Hive,
|
||||||
HANDLE FileHandle);
|
HANDLE FileHandle);
|
||||||
|
@ -389,45 +345,6 @@ CmFindObject(
|
||||||
IN PACCESS_STATE AccessState,
|
IN PACCESS_STATE AccessState,
|
||||||
IN PVOID ParseContext
|
IN PVOID ParseContext
|
||||||
);
|
);
|
||||||
PVOID CMAPI
|
|
||||||
CmpAllocate(
|
|
||||||
ULONG Size,
|
|
||||||
BOOLEAN Paged);
|
|
||||||
|
|
||||||
VOID CMAPI
|
|
||||||
CmpFree(
|
|
||||||
PVOID Ptr);
|
|
||||||
|
|
||||||
BOOLEAN CMAPI
|
|
||||||
CmpFileRead(
|
|
||||||
PHHIVE RegistryHive,
|
|
||||||
ULONG FileType,
|
|
||||||
ULONGLONG FileOffset,
|
|
||||||
PVOID Buffer,
|
|
||||||
SIZE_T BufferLength);
|
|
||||||
|
|
||||||
BOOLEAN CMAPI
|
|
||||||
CmpFileWrite(
|
|
||||||
PHHIVE RegistryHive,
|
|
||||||
ULONG FileType,
|
|
||||||
ULONGLONG FileOffset,
|
|
||||||
PVOID Buffer,
|
|
||||||
SIZE_T BufferLength);
|
|
||||||
|
|
||||||
BOOLEAN CMAPI
|
|
||||||
CmpFileSetSize(
|
|
||||||
PHHIVE RegistryHive,
|
|
||||||
ULONG FileType,
|
|
||||||
ULONGLONG FileSize);
|
|
||||||
|
|
||||||
BOOLEAN CMAPI
|
|
||||||
CmpFileFlush(
|
|
||||||
PHHIVE RegistryHive,
|
|
||||||
ULONG FileType);
|
|
||||||
|
|
||||||
VOID
|
|
||||||
CmiCheckKey(BOOLEAN Verbose,
|
|
||||||
HANDLE Key);
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
|
@ -450,31 +367,6 @@ CmpInitHiveFromFile(IN PUNICODE_STRING HiveName,
|
||||||
IN OUT PBOOLEAN New,
|
IN OUT PBOOLEAN New,
|
||||||
IN ULONG CheckFlags);
|
IN ULONG CheckFlags);
|
||||||
|
|
||||||
#if 0
|
|
||||||
static __inline PVOID xHvGetCell(char *file, int line, PHHIVE Hive, HCELL_INDEX Cell)
|
|
||||||
{
|
|
||||||
DPRINT1("xHvGetCell @ %s:%d %x @ %x\n", file, line, Cell, Hive);
|
|
||||||
return HvGetCell(Hive, Cell);
|
|
||||||
}
|
|
||||||
|
|
||||||
static __inline VOID xHvFreeCell(char *file, int line, PHHIVE Hive, HCELL_INDEX Cell)
|
|
||||||
{
|
|
||||||
DPRINT1("xHvFreeCell @ %s:%d %x @ %x\n", file, line, Cell, Hive);
|
|
||||||
HvFreeCell(Hive, Cell);
|
|
||||||
}
|
|
||||||
|
|
||||||
static __inline HCELL_INDEX xHvAllocateCell(char *file, int line, PHHIVE Hive, SIZE_T Size)
|
|
||||||
{
|
|
||||||
HCELL_INDEX Offset = HvAllocateCell(Hive, Size);
|
|
||||||
DPRINT1("xHvAllocateCell @ %s:%d (%x) %x @ %x\n", file, line, Size, Offset, Hive);
|
|
||||||
return Offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define HvGetCell(hive, cell) xHvGetCell(__FILE__, __LINE__, hive, cell)
|
|
||||||
#define HvFreeCell(hive, cell) xHvFreeCell(__FILE__, __LINE__, hive, cell)
|
|
||||||
#define HvAllocateCell(hive, size) xHvAllocateCell(__FILE__, __LINE__, hive, size)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Some Ob definitions for debug messages in Cm
|
// Some Ob definitions for debug messages in Cm
|
||||||
#define ObGetObjectPointerCount(x) OBJECT_TO_OBJECT_HEADER(x)->PointerCount
|
#define ObGetObjectPointerCount(x) OBJECT_TO_OBJECT_HEADER(x)->PointerCount
|
||||||
#define ObGetObjectHandleCount(x) OBJECT_TO_OBJECT_HEADER(x)->HandleCount
|
#define ObGetObjectHandleCount(x) OBJECT_TO_OBJECT_HEADER(x)->HandleCount
|
||||||
|
|
|
@ -525,309 +525,60 @@ NtDeleteKey(IN HANDLE KeyHandle)
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
NTSTATUS STDCALL
|
NTAPI
|
||||||
NtEnumerateKey(IN HANDLE KeyHandle,
|
NtEnumerateKey(IN HANDLE KeyHandle,
|
||||||
IN ULONG Index,
|
IN ULONG Index,
|
||||||
IN KEY_INFORMATION_CLASS KeyInformationClass,
|
IN KEY_INFORMATION_CLASS KeyInformationClass,
|
||||||
OUT PVOID KeyInformation,
|
OUT PVOID KeyInformation,
|
||||||
IN ULONG Length,
|
IN ULONG Length,
|
||||||
OUT PULONG ResultLength)
|
OUT PULONG ResultLength)
|
||||||
{
|
{
|
||||||
PKEY_OBJECT KeyObject;
|
NTSTATUS Status;
|
||||||
PEREGISTRY_HIVE RegistryHive;
|
PKEY_OBJECT KeyObject;
|
||||||
PCM_KEY_NODE KeyCell, SubKeyCell;
|
REG_ENUMERATE_KEY_INFORMATION EnumerateKeyInfo;
|
||||||
PHASH_TABLE_CELL HashTableBlock;
|
REG_POST_OPERATION_INFORMATION PostOperationInfo;
|
||||||
PKEY_BASIC_INFORMATION BasicInformation;
|
PAGED_CODE();
|
||||||
PKEY_NODE_INFORMATION NodeInformation;
|
|
||||||
PKEY_FULL_INFORMATION FullInformation;
|
|
||||||
PVOID ClassCell;
|
|
||||||
ULONG NameSize, ClassSize;
|
|
||||||
KPROCESSOR_MODE PreviousMode;
|
|
||||||
NTSTATUS Status;
|
|
||||||
REG_ENUMERATE_KEY_INFORMATION EnumerateKeyInfo;
|
|
||||||
REG_POST_OPERATION_INFORMATION PostOperationInfo;
|
|
||||||
HV_STORAGE_TYPE Storage;
|
|
||||||
ULONG BaseIndex;
|
|
||||||
|
|
||||||
PAGED_CODE();
|
/* Verify that the handle is valid and is a registry key */
|
||||||
|
Status = ObReferenceObjectByHandle(KeyHandle,
|
||||||
|
(KeyInformationClass !=
|
||||||
|
KeyNameInformation) ?
|
||||||
|
KEY_QUERY_VALUE : 0,
|
||||||
|
CmpKeyObjectType,
|
||||||
|
ExGetPreviousMode(),
|
||||||
|
(PVOID *)&KeyObject,
|
||||||
|
NULL);
|
||||||
|
if (!NT_SUCCESS(Status)) return Status;
|
||||||
|
|
||||||
PreviousMode = ExGetPreviousMode();
|
/* Setup the callback */
|
||||||
|
PostOperationInfo.Object = (PVOID)KeyObject;
|
||||||
|
EnumerateKeyInfo.Object = (PVOID)KeyObject;
|
||||||
|
EnumerateKeyInfo.Index = Index;
|
||||||
|
EnumerateKeyInfo.KeyInformationClass = KeyInformationClass;
|
||||||
|
EnumerateKeyInfo.Length = Length;
|
||||||
|
EnumerateKeyInfo.ResultLength = ResultLength;
|
||||||
|
|
||||||
DPRINT("KH 0x%p I %d KIC %x KI 0x%p L %d RL 0x%p\n",
|
/* Do the callback */
|
||||||
KeyHandle,
|
Status = CmiCallRegisteredCallbacks(RegNtPreEnumerateKey, &EnumerateKeyInfo);
|
||||||
Index,
|
if (NT_SUCCESS(Status))
|
||||||
KeyInformationClass,
|
|
||||||
KeyInformation,
|
|
||||||
Length,
|
|
||||||
ResultLength);
|
|
||||||
|
|
||||||
/* Verify that the handle is valid and is a registry key */
|
|
||||||
Status = ObReferenceObjectByHandle(KeyHandle,
|
|
||||||
KEY_ENUMERATE_SUB_KEYS,
|
|
||||||
CmpKeyObjectType,
|
|
||||||
PreviousMode,
|
|
||||||
(PVOID *) &KeyObject,
|
|
||||||
NULL);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
{
|
||||||
DPRINT("ObReferenceObjectByHandle() failed with status %x\n", Status);
|
/* Call the internal API */
|
||||||
return(Status);
|
Status = CmEnumerateKey(KeyObject,
|
||||||
|
Index,
|
||||||
|
KeyInformationClass,
|
||||||
|
KeyInformation,
|
||||||
|
Length,
|
||||||
|
ResultLength);
|
||||||
|
|
||||||
|
/* Do the post callback */
|
||||||
|
PostOperationInfo.Status = Status;
|
||||||
|
CmiCallRegisteredCallbacks(RegNtPostEnumerateKey, &PostOperationInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
PostOperationInfo.Object = (PVOID)KeyObject;
|
/* Dereference and return status */
|
||||||
EnumerateKeyInfo.Object = (PVOID)KeyObject;
|
ObDereferenceObject(KeyObject);
|
||||||
EnumerateKeyInfo.Index = Index;
|
return Status;
|
||||||
EnumerateKeyInfo.KeyInformationClass = KeyInformationClass;
|
|
||||||
EnumerateKeyInfo.Length = Length;
|
|
||||||
EnumerateKeyInfo.ResultLength = ResultLength;
|
|
||||||
|
|
||||||
Status = CmiCallRegisteredCallbacks(RegNtPreEnumerateKey, &EnumerateKeyInfo);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
PostOperationInfo.Status = Status;
|
|
||||||
CmiCallRegisteredCallbacks(RegNtPostEnumerateKey, &PostOperationInfo);
|
|
||||||
ObDereferenceObject(KeyObject);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Acquire hive lock */
|
|
||||||
KeEnterCriticalRegion();
|
|
||||||
ExAcquireResourceSharedLite(&CmpRegistryLock, TRUE);
|
|
||||||
|
|
||||||
VERIFY_KEY_OBJECT(KeyObject);
|
|
||||||
|
|
||||||
/* Get pointer to KeyCell */
|
|
||||||
KeyCell = KeyObject->KeyCell;
|
|
||||||
RegistryHive = KeyObject->RegistryHive;
|
|
||||||
|
|
||||||
/* Check for hightest possible sub key index */
|
|
||||||
if (Index >= KeyCell->SubKeyCounts[HvStable] +
|
|
||||||
KeyCell->SubKeyCounts[HvVolatile])
|
|
||||||
{
|
|
||||||
ExReleaseResourceLite(&CmpRegistryLock);
|
|
||||||
KeLeaveCriticalRegion();
|
|
||||||
PostOperationInfo.Status = STATUS_NO_MORE_ENTRIES;
|
|
||||||
CmiCallRegisteredCallbacks(RegNtPostEnumerateKey, &PostOperationInfo);
|
|
||||||
ObDereferenceObject(KeyObject);
|
|
||||||
DPRINT("No more volatile entries\n");
|
|
||||||
return STATUS_NO_MORE_ENTRIES;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get pointer to SubKey */
|
|
||||||
if (Index >= KeyCell->SubKeyCounts[HvStable])
|
|
||||||
{
|
|
||||||
Storage = HvVolatile;
|
|
||||||
BaseIndex = Index - KeyCell->SubKeyCounts[HvStable];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Storage = HvStable;
|
|
||||||
BaseIndex = Index;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (KeyCell->SubKeyLists[Storage] == HCELL_NULL)
|
|
||||||
{
|
|
||||||
ExReleaseResourceLite(&CmpRegistryLock);
|
|
||||||
KeLeaveCriticalRegion();
|
|
||||||
PostOperationInfo.Status = STATUS_NO_MORE_ENTRIES;
|
|
||||||
CmiCallRegisteredCallbacks(RegNtPostEnumerateKey, &PostOperationInfo);
|
|
||||||
ObDereferenceObject(KeyObject);
|
|
||||||
return STATUS_NO_MORE_ENTRIES;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT(KeyCell->SubKeyLists[Storage] != HCELL_NULL);
|
|
||||||
HashTableBlock = HvGetCell (&RegistryHive->Hive, KeyCell->SubKeyLists[Storage]);
|
|
||||||
|
|
||||||
SubKeyCell = CmiGetKeyFromHashByIndex(RegistryHive,
|
|
||||||
HashTableBlock,
|
|
||||||
BaseIndex);
|
|
||||||
|
|
||||||
Status = STATUS_SUCCESS;
|
|
||||||
switch (KeyInformationClass)
|
|
||||||
{
|
|
||||||
case KeyBasicInformation:
|
|
||||||
/* Check size of buffer */
|
|
||||||
NameSize = SubKeyCell->NameSize;
|
|
||||||
if (SubKeyCell->Flags & REG_KEY_NAME_PACKED)
|
|
||||||
{
|
|
||||||
NameSize *= sizeof(WCHAR);
|
|
||||||
}
|
|
||||||
|
|
||||||
*ResultLength = FIELD_OFFSET(KEY_BASIC_INFORMATION, Name[0]) + NameSize;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* NOTE: It's perfetly valid to call NtEnumerateKey to get
|
|
||||||
* all the information but name. Actually the NT4 sound
|
|
||||||
* framework does that while querying parameters from registry.
|
|
||||||
* -- Filip Navara, 19/07/2004
|
|
||||||
*/
|
|
||||||
if (Length < FIELD_OFFSET(KEY_BASIC_INFORMATION, Name[0]))
|
|
||||||
{
|
|
||||||
Status = STATUS_BUFFER_TOO_SMALL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Fill buffer with requested info */
|
|
||||||
BasicInformation = (PKEY_BASIC_INFORMATION) KeyInformation;
|
|
||||||
BasicInformation->LastWriteTime.u.LowPart = SubKeyCell->LastWriteTime.u.LowPart;
|
|
||||||
BasicInformation->LastWriteTime.u.HighPart = SubKeyCell->LastWriteTime.u.HighPart;
|
|
||||||
BasicInformation->TitleIndex = Index;
|
|
||||||
BasicInformation->NameLength = NameSize;
|
|
||||||
|
|
||||||
if (Length - FIELD_OFFSET(KEY_BASIC_INFORMATION, Name[0]) < NameSize)
|
|
||||||
{
|
|
||||||
NameSize = Length - FIELD_OFFSET(KEY_BASIC_INFORMATION, Name[0]);
|
|
||||||
Status = STATUS_BUFFER_OVERFLOW;
|
|
||||||
CHECKPOINT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SubKeyCell->Flags & REG_KEY_NAME_PACKED)
|
|
||||||
{
|
|
||||||
CmiCopyPackedName(BasicInformation->Name,
|
|
||||||
SubKeyCell->Name,
|
|
||||||
NameSize / sizeof(WCHAR));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
RtlCopyMemory(BasicInformation->Name,
|
|
||||||
SubKeyCell->Name,
|
|
||||||
NameSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case KeyNodeInformation:
|
|
||||||
/* Check size of buffer */
|
|
||||||
NameSize = SubKeyCell->NameSize;
|
|
||||||
if (SubKeyCell->Flags & REG_KEY_NAME_PACKED)
|
|
||||||
{
|
|
||||||
NameSize *= sizeof(WCHAR);
|
|
||||||
}
|
|
||||||
ClassSize = SubKeyCell->ClassSize;
|
|
||||||
|
|
||||||
*ResultLength = FIELD_OFFSET(KEY_NODE_INFORMATION, Name[0]) +
|
|
||||||
NameSize + ClassSize;
|
|
||||||
|
|
||||||
if (Length < FIELD_OFFSET(KEY_NODE_INFORMATION, Name[0]))
|
|
||||||
{
|
|
||||||
Status = STATUS_BUFFER_TOO_SMALL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Fill buffer with requested info */
|
|
||||||
NodeInformation = (PKEY_NODE_INFORMATION) KeyInformation;
|
|
||||||
NodeInformation->LastWriteTime.u.LowPart = SubKeyCell->LastWriteTime.u.LowPart;
|
|
||||||
NodeInformation->LastWriteTime.u.HighPart = SubKeyCell->LastWriteTime.u.HighPart;
|
|
||||||
NodeInformation->TitleIndex = Index;
|
|
||||||
NodeInformation->ClassOffset = sizeof(KEY_NODE_INFORMATION) + NameSize;
|
|
||||||
NodeInformation->ClassLength = SubKeyCell->ClassSize;
|
|
||||||
NodeInformation->NameLength = NameSize;
|
|
||||||
|
|
||||||
if (Length - FIELD_OFFSET(KEY_NODE_INFORMATION, Name[0]) < NameSize)
|
|
||||||
{
|
|
||||||
NameSize = Length - FIELD_OFFSET(KEY_NODE_INFORMATION, Name[0]);
|
|
||||||
ClassSize = 0;
|
|
||||||
Status = STATUS_BUFFER_OVERFLOW;
|
|
||||||
CHECKPOINT;
|
|
||||||
}
|
|
||||||
else if (Length - FIELD_OFFSET(KEY_NODE_INFORMATION, Name[0]) -
|
|
||||||
NameSize < ClassSize)
|
|
||||||
{
|
|
||||||
ClassSize = Length - FIELD_OFFSET(KEY_NODE_INFORMATION, Name[0]) -
|
|
||||||
NameSize;
|
|
||||||
Status = STATUS_BUFFER_OVERFLOW;
|
|
||||||
CHECKPOINT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SubKeyCell->Flags & REG_KEY_NAME_PACKED)
|
|
||||||
{
|
|
||||||
CmiCopyPackedName(NodeInformation->Name,
|
|
||||||
SubKeyCell->Name,
|
|
||||||
NameSize / sizeof(WCHAR));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
RtlCopyMemory(NodeInformation->Name,
|
|
||||||
SubKeyCell->Name,
|
|
||||||
NameSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ClassSize != 0)
|
|
||||||
{
|
|
||||||
ClassCell = HvGetCell (&KeyObject->RegistryHive->Hive,
|
|
||||||
SubKeyCell->ClassNameOffset);
|
|
||||||
RtlCopyMemory (NodeInformation->Name + SubKeyCell->NameSize,
|
|
||||||
ClassCell,
|
|
||||||
ClassSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case KeyFullInformation:
|
|
||||||
ClassSize = SubKeyCell->ClassSize;
|
|
||||||
|
|
||||||
*ResultLength = FIELD_OFFSET(KEY_FULL_INFORMATION, Class[0]) +
|
|
||||||
ClassSize;
|
|
||||||
|
|
||||||
/* Check size of buffer */
|
|
||||||
if (Length < FIELD_OFFSET(KEY_FULL_INFORMATION, Class[0]))
|
|
||||||
{
|
|
||||||
Status = STATUS_BUFFER_TOO_SMALL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Fill buffer with requested info */
|
|
||||||
FullInformation = (PKEY_FULL_INFORMATION) KeyInformation;
|
|
||||||
FullInformation->LastWriteTime.u.LowPart = SubKeyCell->LastWriteTime.u.LowPart;
|
|
||||||
FullInformation->LastWriteTime.u.HighPart = SubKeyCell->LastWriteTime.u.HighPart;
|
|
||||||
FullInformation->TitleIndex = Index;
|
|
||||||
FullInformation->ClassOffset = sizeof(KEY_FULL_INFORMATION) -
|
|
||||||
sizeof(WCHAR);
|
|
||||||
FullInformation->ClassLength = SubKeyCell->ClassSize;
|
|
||||||
FullInformation->SubKeys = CmiGetNumberOfSubKeys(KeyObject); //SubKeyCell->SubKeyCounts;
|
|
||||||
FullInformation->MaxNameLen = CmiGetMaxNameLength(&RegistryHive->Hive, SubKeyCell);
|
|
||||||
FullInformation->MaxClassLen = CmiGetMaxClassLength(&RegistryHive->Hive, SubKeyCell);
|
|
||||||
FullInformation->Values = SubKeyCell->ValueList.Count;
|
|
||||||
FullInformation->MaxValueNameLen =
|
|
||||||
CmiGetMaxValueNameLength(&RegistryHive->Hive, SubKeyCell);
|
|
||||||
FullInformation->MaxValueDataLen =
|
|
||||||
CmiGetMaxValueDataLength(&RegistryHive->Hive, SubKeyCell);
|
|
||||||
|
|
||||||
if (Length - FIELD_OFFSET(KEY_FULL_INFORMATION, Class[0]) < ClassSize)
|
|
||||||
{
|
|
||||||
ClassSize = Length - FIELD_OFFSET(KEY_FULL_INFORMATION, Class[0]);
|
|
||||||
Status = STATUS_BUFFER_OVERFLOW;
|
|
||||||
CHECKPOINT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ClassSize != 0)
|
|
||||||
{
|
|
||||||
ClassCell = HvGetCell (&KeyObject->RegistryHive->Hive,
|
|
||||||
SubKeyCell->ClassNameOffset);
|
|
||||||
RtlCopyMemory (FullInformation->Class,
|
|
||||||
ClassCell,
|
|
||||||
ClassSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
DPRINT1("Not handling 0x%x\n", KeyInformationClass);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
ExReleaseResourceLite(&CmpRegistryLock);
|
|
||||||
KeLeaveCriticalRegion();
|
|
||||||
|
|
||||||
PostOperationInfo.Status = Status;
|
|
||||||
CmiCallRegisteredCallbacks(RegNtPostEnumerateKey, &PostOperationInfo);
|
|
||||||
|
|
||||||
ObDereferenceObject(KeyObject);
|
|
||||||
|
|
||||||
DPRINT("Returning status %x\n", Status);
|
|
||||||
|
|
||||||
return(Status);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
|
|
@ -620,39 +620,6 @@ CmiRemoveSubKey(PEREGISTRY_HIVE RegistryHive,
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
CmiGetValueFromKeyByIndex(IN PEREGISTRY_HIVE RegistryHive,
|
|
||||||
IN PCM_KEY_NODE KeyCell,
|
|
||||||
IN ULONG Index,
|
|
||||||
OUT PCM_KEY_VALUE *ValueCell)
|
|
||||||
{
|
|
||||||
PVALUE_LIST_CELL ValueListCell;
|
|
||||||
PCM_KEY_VALUE CurValueCell;
|
|
||||||
|
|
||||||
*ValueCell = NULL;
|
|
||||||
|
|
||||||
if (KeyCell->ValueList.List == (HCELL_INDEX)-1)
|
|
||||||
{
|
|
||||||
return STATUS_NO_MORE_ENTRIES;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Index >= KeyCell->ValueList.Count)
|
|
||||||
{
|
|
||||||
return STATUS_NO_MORE_ENTRIES;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ValueListCell = HvGetCell (&RegistryHive->Hive, KeyCell->ValueList.List);
|
|
||||||
|
|
||||||
VERIFY_VALUE_LIST_CELL(ValueListCell);
|
|
||||||
|
|
||||||
CurValueCell = HvGetCell (&RegistryHive->Hive, ValueListCell->ValueOffset[Index]);
|
|
||||||
|
|
||||||
*ValueCell = CurValueCell;
|
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
CmiAllocateHashTableCell (IN PEREGISTRY_HIVE RegistryHive,
|
CmiAllocateHashTableCell (IN PEREGISTRY_HIVE RegistryHive,
|
||||||
OUT PHASH_TABLE_CELL *HashBlock,
|
OUT PHASH_TABLE_CELL *HashBlock,
|
||||||
|
@ -686,20 +653,6 @@ CmiAllocateHashTableCell (IN PEREGISTRY_HIVE RegistryHive,
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
PCM_KEY_NODE
|
|
||||||
CmiGetKeyFromHashByIndex(PEREGISTRY_HIVE RegistryHive,
|
|
||||||
PHASH_TABLE_CELL HashBlock,
|
|
||||||
ULONG Index)
|
|
||||||
{
|
|
||||||
HCELL_INDEX KeyOffset;
|
|
||||||
PCM_KEY_NODE KeyCell;
|
|
||||||
|
|
||||||
KeyOffset = HashBlock->Table[Index].KeyOffset;
|
|
||||||
KeyCell = HvGetCell (&RegistryHive->Hive, KeyOffset);
|
|
||||||
|
|
||||||
return KeyCell;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
CmiAddKeyToHashTable(PEREGISTRY_HIVE RegistryHive,
|
CmiAddKeyToHashTable(PEREGISTRY_HIVE RegistryHive,
|
||||||
PHASH_TABLE_CELL HashCell,
|
PHASH_TABLE_CELL HashCell,
|
||||||
|
@ -744,17 +697,6 @@ CmiRemoveKeyFromHashTable(PEREGISTRY_HIVE RegistryHive,
|
||||||
return STATUS_UNSUCCESSFUL;
|
return STATUS_UNSUCCESSFUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
|
||||||
CmiCopyPackedName(PWCHAR NameBuffer,
|
|
||||||
PUCHAR PackedNameBuffer,
|
|
||||||
ULONG PackedNameSize)
|
|
||||||
{
|
|
||||||
ULONG i;
|
|
||||||
|
|
||||||
for (i = 0; i < PackedNameSize; i++)
|
|
||||||
NameBuffer[i] = (WCHAR)PackedNameBuffer[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
CmiSaveTempHive (PEREGISTRY_HIVE Hive,
|
CmiSaveTempHive (PEREGISTRY_HIVE Hive,
|
||||||
HANDLE FileHandle)
|
HANDLE FileHandle)
|
||||||
|
|
|
@ -1115,6 +1115,14 @@ CmpFindSubKeyByName(
|
||||||
IN PUNICODE_STRING SearchName
|
IN PUNICODE_STRING SearchName
|
||||||
);
|
);
|
||||||
|
|
||||||
|
HCELL_INDEX
|
||||||
|
NTAPI
|
||||||
|
CmpFindSubKeyByNumber(
|
||||||
|
IN PHHIVE Hive,
|
||||||
|
IN PCM_KEY_NODE Node,
|
||||||
|
IN ULONG Number
|
||||||
|
);
|
||||||
|
|
||||||
ULONG
|
ULONG
|
||||||
NTAPI
|
NTAPI
|
||||||
CmpComputeHashKey(
|
CmpComputeHashKey(
|
||||||
|
|
|
@ -640,7 +640,7 @@ CmpQueryKeyData(IN PHHIVE Hive,
|
||||||
USHORT NameLength;
|
USHORT NameLength;
|
||||||
|
|
||||||
/* Check if the value is compressed */
|
/* Check if the value is compressed */
|
||||||
if (Node->Flags & VALUE_COMP_NAME)
|
if (Node->Flags & KEY_COMP_NAME)
|
||||||
{
|
{
|
||||||
/* Get the compressed name size */
|
/* Get the compressed name size */
|
||||||
NameLength = CmpCompressedNameSize(Node->Name, Node->NameLength);
|
NameLength = CmpCompressedNameSize(Node->Name, Node->NameLength);
|
||||||
|
@ -917,3 +917,69 @@ Quickie:
|
||||||
KeLeaveCriticalRegion();
|
KeLeaveCriticalRegion();
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
CmEnumerateKey(IN PKEY_OBJECT KeyObject,
|
||||||
|
IN ULONG Index,
|
||||||
|
IN KEY_INFORMATION_CLASS KeyInformationClass,
|
||||||
|
IN PVOID KeyInformation,
|
||||||
|
IN ULONG Length,
|
||||||
|
IN PULONG ResultLength)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
PHHIVE Hive;
|
||||||
|
PCM_KEY_NODE Parent, Child;
|
||||||
|
HCELL_INDEX ChildCell;
|
||||||
|
|
||||||
|
/* Acquire hive lock */
|
||||||
|
KeEnterCriticalRegion();
|
||||||
|
ExAcquireResourceExclusiveLite(&CmpRegistryLock, TRUE);
|
||||||
|
|
||||||
|
/* Get the hive and parent */
|
||||||
|
Hive = &KeyObject->RegistryHive->Hive;
|
||||||
|
Parent = (PCM_KEY_NODE)HvGetCell(Hive, KeyObject->KeyCellOffset);
|
||||||
|
if (!Parent)
|
||||||
|
{
|
||||||
|
/* Fail */
|
||||||
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the child cell */
|
||||||
|
ChildCell = CmpFindSubKeyByNumber(Hive, Parent, Index);
|
||||||
|
|
||||||
|
/* Release the parent cell */
|
||||||
|
HvReleaseCell(Hive, KeyObject->KeyCellOffset);
|
||||||
|
|
||||||
|
/* Check if we found the child */
|
||||||
|
if (ChildCell == HCELL_NIL)
|
||||||
|
{
|
||||||
|
/* We didn't, fail */
|
||||||
|
Status = STATUS_NO_MORE_ENTRIES;
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now get the actual child node */
|
||||||
|
Child = (PCM_KEY_NODE)HvGetCell(Hive, ChildCell);
|
||||||
|
if (!Child)
|
||||||
|
{
|
||||||
|
/* Fail */
|
||||||
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Query the data requested */
|
||||||
|
Status = CmpQueryKeyData(Hive,
|
||||||
|
Child,
|
||||||
|
KeyInformationClass,
|
||||||
|
KeyInformation,
|
||||||
|
Length,
|
||||||
|
ResultLength);
|
||||||
|
|
||||||
|
Quickie:
|
||||||
|
/* Release hive lock */
|
||||||
|
ExReleaseResourceLite(&CmpRegistryLock);
|
||||||
|
KeLeaveCriticalRegion();
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
|
@ -514,6 +514,139 @@ CmpComputeHashKey(IN ULONG Hash,
|
||||||
return Hash;
|
return Hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HCELL_INDEX
|
||||||
|
NTAPI
|
||||||
|
CmpDoFindSubKeyByNumber(IN PHHIVE Hive,
|
||||||
|
IN PCM_KEY_INDEX Index,
|
||||||
|
IN ULONG Number)
|
||||||
|
{
|
||||||
|
ULONG i;
|
||||||
|
HCELL_INDEX LeafCell = 0;
|
||||||
|
PCM_KEY_INDEX Leaf = NULL;
|
||||||
|
PCM_KEY_FAST_INDEX FastIndex;
|
||||||
|
HCELL_INDEX Result;
|
||||||
|
|
||||||
|
/* Check if this is a root */
|
||||||
|
if (Index->Signature == CM_KEY_INDEX_ROOT)
|
||||||
|
{
|
||||||
|
/* Loop the index */
|
||||||
|
for (i = 0; i < Index->Count; i++)
|
||||||
|
{
|
||||||
|
/* Check if this isn't the first iteration */
|
||||||
|
if (i)
|
||||||
|
{
|
||||||
|
/* Make sure we had something valid, and release it */
|
||||||
|
ASSERT(Leaf != NULL );
|
||||||
|
ASSERT(LeafCell == Index->List[i - 1]);
|
||||||
|
HvReleaseCell(Hive, LeafCell);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the leaf cell and the leaf for this index */
|
||||||
|
LeafCell = Index->List[i];
|
||||||
|
Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, LeafCell);
|
||||||
|
if (!Leaf) return HCELL_NIL;
|
||||||
|
|
||||||
|
/* Check if the index may be inside it */
|
||||||
|
if (Number < Leaf->Count)
|
||||||
|
{
|
||||||
|
/* Check if this is a fast or hash leaf */
|
||||||
|
if ((Leaf->Signature == CM_KEY_FAST_LEAF) ||
|
||||||
|
(Leaf->Signature == CM_KEY_HASH_LEAF))
|
||||||
|
{
|
||||||
|
/* Get the fast index */
|
||||||
|
FastIndex = (PCM_KEY_FAST_INDEX)Leaf;
|
||||||
|
|
||||||
|
/* Look inside the list to get our actual cell */
|
||||||
|
Result = FastIndex->List[Number].Cell;
|
||||||
|
HvReleaseCell(Hive, LeafCell);
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Regular leaf, so just use the index directly */
|
||||||
|
Result = Leaf->List[Number];
|
||||||
|
|
||||||
|
/* Release and return it */
|
||||||
|
HvReleaseCell(Hive,LeafCell);
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Otherwise, skip this leaf */
|
||||||
|
Number = Number - Leaf->Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Should never get here */
|
||||||
|
ASSERT(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we got here, then the cell is in this index */
|
||||||
|
ASSERT(Number < Index->Count);
|
||||||
|
|
||||||
|
/* Check if we're a fast or hash leaf */
|
||||||
|
if ((Index->Signature == CM_KEY_FAST_LEAF) ||
|
||||||
|
(Index->Signature == CM_KEY_HASH_LEAF))
|
||||||
|
{
|
||||||
|
/* We are, get the fast index and get the cell from the list */
|
||||||
|
FastIndex = (PCM_KEY_FAST_INDEX)Index;
|
||||||
|
return FastIndex->List[Number].Cell;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* We aren't, so use the index directly to grab the cell */
|
||||||
|
return Index->List[Number];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HCELL_INDEX
|
||||||
|
NTAPI
|
||||||
|
CmpFindSubKeyByNumber(IN PHHIVE Hive,
|
||||||
|
IN PCM_KEY_NODE Node,
|
||||||
|
IN ULONG Number)
|
||||||
|
{
|
||||||
|
PCM_KEY_INDEX Index;
|
||||||
|
HCELL_INDEX Result = HCELL_NIL;
|
||||||
|
|
||||||
|
/* Check if it's in the stable list */
|
||||||
|
if (Number < Node->SubKeyCounts[HvStable])
|
||||||
|
{
|
||||||
|
/* Get the actual key index */
|
||||||
|
Index = (PCM_KEY_INDEX)HvGetCell(Hive, Node->SubKeyLists[HvStable]);
|
||||||
|
if (!Index) return HCELL_NIL;
|
||||||
|
|
||||||
|
/* Do a search inside it */
|
||||||
|
Result = CmpDoFindSubKeyByNumber(Hive, Index, Number);
|
||||||
|
|
||||||
|
/* Release the cell and return the result */
|
||||||
|
HvReleaseCell(Hive, Node->SubKeyLists[HvStable]);
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
else if (Hive->StorageTypeCount > HvVolatile)
|
||||||
|
{
|
||||||
|
/* It's in the volatile list */
|
||||||
|
Number = Number - Node->SubKeyCounts[HvStable];
|
||||||
|
if (Number < Node->SubKeyCounts[HvVolatile])
|
||||||
|
{
|
||||||
|
/* Get the actual key index */
|
||||||
|
Index = (PCM_KEY_INDEX)HvGetCell(Hive,
|
||||||
|
Node->SubKeyLists[HvVolatile]);
|
||||||
|
if (!Index) return HCELL_NIL;
|
||||||
|
|
||||||
|
/* Do a search inside it */
|
||||||
|
Result = CmpDoFindSubKeyByNumber(Hive, Index, Number);
|
||||||
|
|
||||||
|
/* Release the cell and return the result */
|
||||||
|
HvReleaseCell(Hive, Node->SubKeyLists[HvVolatile]);
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Nothing was found */
|
||||||
|
return HCELL_NIL;
|
||||||
|
}
|
||||||
|
|
||||||
HCELL_INDEX
|
HCELL_INDEX
|
||||||
NTAPI
|
NTAPI
|
||||||
CmpFindSubKeyByHash(IN PHHIVE Hive,
|
CmpFindSubKeyByHash(IN PHHIVE Hive,
|
||||||
|
|
Loading…
Reference in a new issue