mirror of
https://github.com/reactos/reactos.git
synced 2025-07-25 19:23:56 +00:00
- Get rid of CmiCopyKey since it was dead code. Make CmiScanKeyForValue and CmiScanForSubKey simple wrappers around the newer CmpFindSubKeyByName and CmpFindValueByName routines.
- Allow cmlib to support HINIT_FILE flag for HvInitializeHive. This means the kernel doesn't need to create a section for the hive, then call HvInitializeHive with HINIT_MEMORY anymore, and can simply send the file handle. I wrote a sneaky little hack in cmlib which actually ends up doing the same idea, albeit not by using a section, making it portable. - Fix a serious bug in CmpFindSubKeyInLeaf affected by our lack of alphabetically-sorted cells; the linear search I hacked was slightly broken. - Remove the need to hold a LogFileName in the hive structure, since we generate it dynamically now. svn path=/trunk/; revision=26712
This commit is contained in:
parent
6ef9f575cb
commit
ef1f549526
5 changed files with 205 additions and 435 deletions
|
@ -271,6 +271,130 @@ HvpInitializeMemoryInplaceHive(
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef enum _RESULT
|
||||||
|
{
|
||||||
|
NotHive,
|
||||||
|
Fail,
|
||||||
|
NoMemory,
|
||||||
|
HiveSuccess,
|
||||||
|
RecoverHeader,
|
||||||
|
RecoverData,
|
||||||
|
SelfHeal
|
||||||
|
} RESULT;
|
||||||
|
|
||||||
|
RESULT CMAPI
|
||||||
|
HvpGetHiveHeader(IN PHHIVE Hive,
|
||||||
|
IN PHBASE_BLOCK *BaseBlock,
|
||||||
|
IN PLARGE_INTEGER TimeStamp)
|
||||||
|
{
|
||||||
|
PHBASE_BLOCK HiveHeader;
|
||||||
|
ULONG Alignment;
|
||||||
|
ULONG Result;
|
||||||
|
ULONGLONG Offset = 0;
|
||||||
|
ASSERT(sizeof(HBASE_BLOCK) >= (HV_BLOCK_SIZE * Hive->Cluster));
|
||||||
|
|
||||||
|
/* Assume failure and allocate the buffer */
|
||||||
|
*BaseBlock = 0;
|
||||||
|
HiveHeader = Hive->Allocate(sizeof(HBASE_BLOCK), TRUE);
|
||||||
|
if (!HiveHeader) return NoMemory;
|
||||||
|
|
||||||
|
/* Check for, and enforce, alignment */
|
||||||
|
Alignment = Hive->Cluster * HV_BLOCK_SIZE -1;
|
||||||
|
if ((ULONG_PTR)HiveHeader & Alignment)
|
||||||
|
{
|
||||||
|
/* Free the old header */
|
||||||
|
Hive->Free(HiveHeader);
|
||||||
|
HiveHeader = Hive->Allocate(PAGE_SIZE, TRUE);
|
||||||
|
if (!HiveHeader) return NoMemory;
|
||||||
|
|
||||||
|
//HiveHeader->Length = PAGE_SIZE; ??
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear it */
|
||||||
|
RtlZeroMemory(HiveHeader, sizeof(HBASE_BLOCK));
|
||||||
|
|
||||||
|
/* Now read it from disk */
|
||||||
|
Result = Hive->FileRead(Hive,
|
||||||
|
HV_TYPE_PRIMARY,
|
||||||
|
Offset,
|
||||||
|
HiveHeader,
|
||||||
|
Hive->Cluster * HV_BLOCK_SIZE);
|
||||||
|
|
||||||
|
/* Couldn't read: assume it's not a hive */
|
||||||
|
if (!Result) return NotHive;
|
||||||
|
|
||||||
|
/* Do validation */
|
||||||
|
if (!HvpVerifyHiveHeader(HiveHeader)) return NotHive;
|
||||||
|
|
||||||
|
/* Return information */
|
||||||
|
*BaseBlock = HiveHeader;
|
||||||
|
*TimeStamp = HiveHeader->TimeStamp;
|
||||||
|
return HiveSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS CMAPI
|
||||||
|
HvLoadHive(IN PHHIVE Hive,
|
||||||
|
IN ULONG FileSize)
|
||||||
|
{
|
||||||
|
PHBASE_BLOCK BaseBlock = NULL;
|
||||||
|
ULONG Result;
|
||||||
|
LARGE_INTEGER TimeStamp;
|
||||||
|
ULONGLONG Offset = 0;
|
||||||
|
PVOID HiveData;
|
||||||
|
|
||||||
|
/* Get the hive header */
|
||||||
|
Result = HvpGetHiveHeader(Hive, &BaseBlock, &TimeStamp);
|
||||||
|
switch (Result)
|
||||||
|
{
|
||||||
|
/* Out of memory */
|
||||||
|
case NoMemory:
|
||||||
|
|
||||||
|
/* Fail */
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
|
||||||
|
/* Not a hive */
|
||||||
|
case NotHive:
|
||||||
|
|
||||||
|
/* Fail */
|
||||||
|
return STATUS_NOT_REGISTRY_FILE;
|
||||||
|
|
||||||
|
/* Has recovery data */
|
||||||
|
case RecoverData:
|
||||||
|
case RecoverHeader:
|
||||||
|
|
||||||
|
/* Fail */
|
||||||
|
return STATUS_REGISTRY_CORRUPT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set default boot type */
|
||||||
|
BaseBlock->BootType = 0;
|
||||||
|
|
||||||
|
/* Setup hive data */
|
||||||
|
Hive->HiveHeader = BaseBlock;
|
||||||
|
Hive->Version = Hive->HiveHeader->Minor;
|
||||||
|
|
||||||
|
/* Allocate a buffer large enough to hold the hive */
|
||||||
|
HiveData = Hive->Allocate(FileSize, TRUE);
|
||||||
|
if (!HiveData) return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
|
||||||
|
/* Now read the whole hive */
|
||||||
|
Result = Hive->FileRead(Hive,
|
||||||
|
HV_TYPE_PRIMARY,
|
||||||
|
Offset,
|
||||||
|
HiveData,
|
||||||
|
FileSize);
|
||||||
|
if (!Result) return STATUS_NOT_REGISTRY_FILE;
|
||||||
|
|
||||||
|
/* Apply "US National Debt" hack */
|
||||||
|
((PHBASE_BLOCK)HiveData)->Length = FileSize;
|
||||||
|
|
||||||
|
/* Free our base block... it's usless in this implementation */
|
||||||
|
Hive->Free(BaseBlock);
|
||||||
|
|
||||||
|
/* Initialize the hive directly from memory */
|
||||||
|
return HvpInitializeMemoryHive(Hive, (ULONG_PTR)HiveData);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name HvInitialize
|
* @name HvInitialize
|
||||||
*
|
*
|
||||||
|
@ -334,6 +458,7 @@ HvInitialize(
|
||||||
Hive->FileSetSize = FileSetSize;
|
Hive->FileSetSize = FileSetSize;
|
||||||
Hive->FileFlush = FileFlush;
|
Hive->FileFlush = FileFlush;
|
||||||
Hive->StorageTypeCount = 2;
|
Hive->StorageTypeCount = 2;
|
||||||
|
Hive->Cluster = 1;
|
||||||
|
|
||||||
switch (Operation)
|
switch (Operation)
|
||||||
{
|
{
|
||||||
|
@ -349,6 +474,21 @@ HvInitialize(
|
||||||
Status = HvpInitializeMemoryInplaceHive(Hive, HiveData);
|
Status = HvpInitializeMemoryInplaceHive(Hive, HiveData);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
|
||||||
|
/* Hack of doom: Cluster is actually the file size. */
|
||||||
|
Status = HvLoadHive(Hive, Cluster);
|
||||||
|
if ((Status != STATUS_SUCCESS) &&
|
||||||
|
(Status != STATUS_REGISTRY_RECOVERED))
|
||||||
|
{
|
||||||
|
/* Unrecoverable failure */
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for previous damage */
|
||||||
|
if (Status == STATUS_REGISTRY_RECOVERED) ASSERT(FALSE);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* FIXME: A better return status value is needed */
|
/* FIXME: A better return status value is needed */
|
||||||
Status = STATUS_NOT_IMPLEMENTED;
|
Status = STATUS_NOT_IMPLEMENTED;
|
||||||
|
|
|
@ -332,6 +332,22 @@ CmiComparePackedNames(IN PUNICODE_STRING Name,
|
||||||
IN USHORT NameBufferSize,
|
IN USHORT NameBufferSize,
|
||||||
IN BOOLEAN NamePacked);
|
IN BOOLEAN NamePacked);
|
||||||
|
|
||||||
|
HCELL_INDEX
|
||||||
|
NTAPI
|
||||||
|
CmpFindValueByName(
|
||||||
|
IN PHHIVE Hive,
|
||||||
|
IN PCM_KEY_NODE KeyNode,
|
||||||
|
IN PUNICODE_STRING Name
|
||||||
|
);
|
||||||
|
|
||||||
|
HCELL_INDEX
|
||||||
|
NTAPI
|
||||||
|
CmpFindSubKeyByName(
|
||||||
|
IN PHHIVE Hive,
|
||||||
|
IN PCM_KEY_NODE Parent,
|
||||||
|
IN PUNICODE_STRING SearchName
|
||||||
|
);
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
CmiCopyPackedName(PWCHAR NameBuffer,
|
CmiCopyPackedName(PWCHAR NameBuffer,
|
||||||
PUCHAR PackedNameBuffer,
|
PUCHAR PackedNameBuffer,
|
||||||
|
@ -361,12 +377,6 @@ CmiSyncHives(VOID);
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
CmiCreateTempHive(PEREGISTRY_HIVE *RegistryHive);
|
CmiCreateTempHive(PEREGISTRY_HIVE *RegistryHive);
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
CmiCopyKey (PEREGISTRY_HIVE DstHive,
|
|
||||||
PCM_KEY_NODE DstKeyCell,
|
|
||||||
PEREGISTRY_HIVE SrcHive,
|
|
||||||
PCM_KEY_NODE SrcKeyCell);
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
CmiSaveTempHive (PEREGISTRY_HIVE Hive,
|
CmiSaveTempHive (PEREGISTRY_HIVE Hive,
|
||||||
HANDLE FileHandle);
|
HANDLE FileHandle);
|
||||||
|
|
|
@ -64,10 +64,8 @@ CmiInitNonVolatileRegistryHive (PEREGISTRY_HIVE RegistryHive,
|
||||||
ULONG CreateDisposition;
|
ULONG CreateDisposition;
|
||||||
IO_STATUS_BLOCK IoSB;
|
IO_STATUS_BLOCK IoSB;
|
||||||
HANDLE FileHandle;
|
HANDLE FileHandle;
|
||||||
PVOID SectionObject;
|
|
||||||
PUCHAR ViewBase;
|
|
||||||
ULONG ViewSize;
|
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
FILE_STANDARD_INFORMATION FileInformation;
|
||||||
|
|
||||||
DPRINT("CmiInitNonVolatileRegistryHive(%p, %S) called\n",
|
DPRINT("CmiInitNonVolatileRegistryHive(%p, %S) called\n",
|
||||||
RegistryHive, Filename);
|
RegistryHive, Filename);
|
||||||
|
@ -81,23 +79,6 @@ CmiInitNonVolatileRegistryHive (PEREGISTRY_HIVE RegistryHive,
|
||||||
return(Status);
|
return(Status);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create log file name */
|
|
||||||
RegistryHive->LogFileName.Length = (wcslen(Filename) + 4) * sizeof(WCHAR);
|
|
||||||
RegistryHive->LogFileName.MaximumLength = RegistryHive->LogFileName.Length + sizeof(WCHAR);
|
|
||||||
RegistryHive->LogFileName.Buffer = ExAllocatePoolWithTag(PagedPool,
|
|
||||||
RegistryHive->LogFileName.MaximumLength,
|
|
||||||
TAG('U', 'S', 'T', 'R'));
|
|
||||||
if (RegistryHive->LogFileName.Buffer == NULL)
|
|
||||||
{
|
|
||||||
RtlFreeUnicodeString(&RegistryHive->HiveFileName);
|
|
||||||
DPRINT("ExAllocatePool() failed\n");
|
|
||||||
return(STATUS_INSUFFICIENT_RESOURCES);
|
|
||||||
}
|
|
||||||
wcscpy(RegistryHive->LogFileName.Buffer,
|
|
||||||
Filename);
|
|
||||||
wcscat(RegistryHive->LogFileName.Buffer,
|
|
||||||
L".log");
|
|
||||||
|
|
||||||
InitializeObjectAttributes(&ObjectAttributes,
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
&RegistryHive->HiveFileName,
|
&RegistryHive->HiveFileName,
|
||||||
OBJ_CASE_INSENSITIVE,
|
OBJ_CASE_INSENSITIVE,
|
||||||
|
@ -119,7 +100,6 @@ CmiInitNonVolatileRegistryHive (PEREGISTRY_HIVE RegistryHive,
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
RtlFreeUnicodeString(&RegistryHive->HiveFileName);
|
RtlFreeUnicodeString(&RegistryHive->HiveFileName);
|
||||||
RtlFreeUnicodeString(&RegistryHive->LogFileName);
|
|
||||||
DPRINT("ZwCreateFile() failed (Status %lx)\n", Status);
|
DPRINT("ZwCreateFile() failed (Status %lx)\n", Status);
|
||||||
return(Status);
|
return(Status);
|
||||||
}
|
}
|
||||||
|
@ -132,77 +112,33 @@ CmiInitNonVolatileRegistryHive (PEREGISTRY_HIVE RegistryHive,
|
||||||
DPRINT("CmiCreateNewRegFile() failed (Status %lx)\n", Status);
|
DPRINT("CmiCreateNewRegFile() failed (Status %lx)\n", Status);
|
||||||
ZwClose(FileHandle);
|
ZwClose(FileHandle);
|
||||||
RtlFreeUnicodeString(&RegistryHive->HiveFileName);
|
RtlFreeUnicodeString(&RegistryHive->HiveFileName);
|
||||||
RtlFreeUnicodeString(&RegistryHive->LogFileName);
|
|
||||||
return(Status);
|
return(Status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create the hive section */
|
RegistryHive->HiveHandle = FileHandle;
|
||||||
Status = MmCreateSection(&SectionObject,
|
|
||||||
SECTION_ALL_ACCESS,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
PAGE_READWRITE,
|
|
||||||
SEC_COMMIT,
|
|
||||||
FileHandle,
|
|
||||||
NULL);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT1("MmCreateSection() failed (Status %lx)\n", Status);
|
|
||||||
RtlFreeUnicodeString(&RegistryHive->HiveFileName);
|
|
||||||
RtlFreeUnicodeString(&RegistryHive->LogFileName);
|
|
||||||
return(Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Map the hive file */
|
/* Check how large the file is */
|
||||||
ViewBase = NULL;
|
ZwQueryInformationFile(FileHandle,
|
||||||
ViewSize = 0;
|
&IoSB,
|
||||||
Status = MmMapViewOfSection(SectionObject,
|
&FileInformation,
|
||||||
PsGetCurrentProcess(),
|
sizeof(FileInformation),
|
||||||
(PVOID*)&ViewBase,
|
FileStandardInformation);
|
||||||
0,
|
Status = HvInitialize(&RegistryHive->Hive, HINIT_FILE, 0, 0,
|
||||||
ViewSize,
|
0, FileInformation.EndOfFile.LowPart,
|
||||||
NULL,
|
|
||||||
&ViewSize,
|
|
||||||
0,
|
|
||||||
MEM_COMMIT,
|
|
||||||
PAGE_READWRITE);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT1("MmMapViewOfSection() failed (Status %lx)\n", Status);
|
|
||||||
ObDereferenceObject(SectionObject);
|
|
||||||
RtlFreeUnicodeString(&RegistryHive->HiveFileName);
|
|
||||||
RtlFreeUnicodeString(&RegistryHive->LogFileName);
|
|
||||||
ZwClose(FileHandle);
|
|
||||||
return(Status);
|
|
||||||
}
|
|
||||||
DPRINT("ViewBase %p ViewSize %lx\n", ViewBase, ViewSize);
|
|
||||||
|
|
||||||
((PHBASE_BLOCK)ViewBase)->Length = ViewSize;
|
|
||||||
Status = HvInitialize(&RegistryHive->Hive, HV_OPERATION_MEMORY, 0, 0,
|
|
||||||
(ULONG_PTR)ViewBase, 0,
|
|
||||||
CmpAllocate, CmpFree,
|
CmpAllocate, CmpFree,
|
||||||
CmpFileRead, CmpFileWrite, CmpFileSetSize,
|
CmpFileRead, CmpFileWrite, CmpFileSetSize,
|
||||||
CmpFileFlush, NULL);
|
CmpFileFlush, NULL);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT1("Failed to open hive\n");
|
DPRINT1("Failed to open hive\n");
|
||||||
MmUnmapViewOfSection(PsGetCurrentProcess(),
|
|
||||||
ViewBase);
|
|
||||||
ObDereferenceObject(SectionObject);
|
|
||||||
RtlFreeUnicodeString(&RegistryHive->HiveFileName);
|
RtlFreeUnicodeString(&RegistryHive->HiveFileName);
|
||||||
RtlFreeUnicodeString(&RegistryHive->LogFileName);
|
|
||||||
ZwClose(FileHandle);
|
ZwClose(FileHandle);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
CmPrepareHive(&RegistryHive->Hive);
|
CmPrepareHive(&RegistryHive->Hive);
|
||||||
|
|
||||||
/* Unmap and dereference the hive section */
|
|
||||||
MmUnmapViewOfSection(PsGetCurrentProcess(),
|
|
||||||
ViewBase);
|
|
||||||
ObDereferenceObject(SectionObject);
|
|
||||||
|
|
||||||
/* Close the hive file */
|
/* Close the hive file */
|
||||||
ZwClose(FileHandle);
|
ZwClose(FileHandle);
|
||||||
|
|
||||||
|
@ -275,7 +211,6 @@ CmiRemoveRegistryHive(PEREGISTRY_HIVE RegistryHive)
|
||||||
|
|
||||||
/* Release file names */
|
/* Release file names */
|
||||||
RtlFreeUnicodeString (&RegistryHive->HiveFileName);
|
RtlFreeUnicodeString (&RegistryHive->HiveFileName);
|
||||||
RtlFreeUnicodeString (&RegistryHive->LogFileName);
|
|
||||||
|
|
||||||
/* Release hive */
|
/* Release hive */
|
||||||
HvFree (&RegistryHive->Hive);
|
HvFree (&RegistryHive->Hive);
|
||||||
|
@ -511,82 +446,53 @@ CmiGetMaxValueDataLength(PEREGISTRY_HIVE RegistryHive,
|
||||||
return MaxValueData;
|
return MaxValueData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
CmiScanKeyForValue(IN PEREGISTRY_HIVE RegistryHive,
|
||||||
|
IN PCM_KEY_NODE KeyCell,
|
||||||
|
IN PUNICODE_STRING ValueName,
|
||||||
|
OUT PCM_KEY_VALUE *ValueCell,
|
||||||
|
OUT HCELL_INDEX *ValueCellOffset)
|
||||||
|
{
|
||||||
|
HCELL_INDEX CellIndex;
|
||||||
|
|
||||||
|
/* Assume failure */
|
||||||
|
*ValueCell = NULL;
|
||||||
|
if (ValueCellOffset) *ValueCellOffset = HCELL_NIL;
|
||||||
|
|
||||||
|
/* Call newer Cm API */
|
||||||
|
CellIndex = CmpFindValueByName(&RegistryHive->Hive, KeyCell, ValueName);
|
||||||
|
if (CellIndex == HCELL_NIL) return STATUS_OBJECT_NAME_NOT_FOUND;
|
||||||
|
|
||||||
|
/* Otherwise, get the cell data back too */
|
||||||
|
if (ValueCellOffset) *ValueCellOffset = CellIndex;
|
||||||
|
*ValueCell = HvGetCell(&RegistryHive->Hive, CellIndex);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
CmiScanForSubKey(IN PEREGISTRY_HIVE RegistryHive,
|
CmiScanForSubKey(IN PEREGISTRY_HIVE RegistryHive,
|
||||||
IN PCM_KEY_NODE KeyCell,
|
IN PCM_KEY_NODE KeyCell,
|
||||||
OUT PCM_KEY_NODE *SubKeyCell,
|
OUT PCM_KEY_NODE *SubKeyCell,
|
||||||
OUT HCELL_INDEX *BlockOffset,
|
OUT HCELL_INDEX *BlockOffset,
|
||||||
IN PUNICODE_STRING KeyName,
|
IN PUNICODE_STRING KeyName,
|
||||||
IN ACCESS_MASK DesiredAccess,
|
IN ACCESS_MASK DesiredAccess,
|
||||||
IN ULONG Attributes)
|
IN ULONG Attributes)
|
||||||
{
|
{
|
||||||
PHASH_TABLE_CELL HashBlock;
|
HCELL_INDEX CellIndex;
|
||||||
PCM_KEY_NODE CurSubKeyCell;
|
|
||||||
ULONG Storage;
|
|
||||||
ULONG i;
|
|
||||||
|
|
||||||
VERIFY_KEY_CELL(KeyCell);
|
/* Assume failure */
|
||||||
|
*SubKeyCell = NULL;
|
||||||
|
|
||||||
DPRINT("Scanning for sub key %wZ\n", KeyName);
|
/* Call newer Cm API */
|
||||||
|
CellIndex = CmpFindSubKeyByName(&RegistryHive->Hive, KeyCell, KeyName);
|
||||||
|
if (CellIndex == HCELL_NIL) return STATUS_OBJECT_NAME_NOT_FOUND;
|
||||||
|
|
||||||
ASSERT(RegistryHive);
|
/* Otherwise, get the cell data back too */
|
||||||
|
*BlockOffset = CellIndex;
|
||||||
*SubKeyCell = NULL;
|
*SubKeyCell = HvGetCell(&RegistryHive->Hive, CellIndex);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
for (Storage = HvStable; Storage < HvMaxStorageType; Storage++)
|
|
||||||
{
|
|
||||||
/* The key does not have any subkeys */
|
|
||||||
if (KeyCell->SubKeyLists[Storage] == HCELL_NULL)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get hash table */
|
|
||||||
HashBlock = HvGetCell (&RegistryHive->Hive, KeyCell->SubKeyLists[Storage]);
|
|
||||||
ASSERT(HashBlock->Id == REG_HASH_TABLE_CELL_ID);
|
|
||||||
|
|
||||||
for (i = 0; i < KeyCell->SubKeyCounts[Storage]; i++)
|
|
||||||
{
|
|
||||||
if (Attributes & OBJ_CASE_INSENSITIVE)
|
|
||||||
{
|
|
||||||
if ((HashBlock->Table[i].HashValue == 0 ||
|
|
||||||
CmiCompareHashI(KeyName, (PCHAR)&HashBlock->Table[i].HashValue)))
|
|
||||||
{
|
|
||||||
CurSubKeyCell = HvGetCell (&RegistryHive->Hive,
|
|
||||||
HashBlock->Table[i].KeyOffset);
|
|
||||||
|
|
||||||
if (CmiCompareKeyNamesI(KeyName, CurSubKeyCell))
|
|
||||||
{
|
|
||||||
*SubKeyCell = CurSubKeyCell;
|
|
||||||
*BlockOffset = HashBlock->Table[i].KeyOffset;
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ((HashBlock->Table[i].HashValue == 0 ||
|
|
||||||
CmiCompareHash(KeyName, (PCHAR)&HashBlock->Table[i].HashValue)))
|
|
||||||
{
|
|
||||||
CurSubKeyCell = HvGetCell (&RegistryHive->Hive,
|
|
||||||
HashBlock->Table[i].KeyOffset);
|
|
||||||
|
|
||||||
if (CmiCompareKeyNames(KeyName, CurSubKeyCell))
|
|
||||||
{
|
|
||||||
*SubKeyCell = CurSubKeyCell;
|
|
||||||
*BlockOffset = HashBlock->Table[i].KeyOffset;
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return STATUS_OBJECT_NAME_NOT_FOUND;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
CmiAddSubKey(PEREGISTRY_HIVE RegistryHive,
|
CmiAddSubKey(PEREGISTRY_HIVE RegistryHive,
|
||||||
PKEY_OBJECT ParentKey,
|
PKEY_OBJECT ParentKey,
|
||||||
|
@ -884,54 +790,6 @@ CmiRemoveSubKey(PEREGISTRY_HIVE RegistryHive,
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
CmiScanKeyForValue(IN PEREGISTRY_HIVE RegistryHive,
|
|
||||||
IN PCM_KEY_NODE KeyCell,
|
|
||||||
IN PUNICODE_STRING ValueName,
|
|
||||||
OUT PCM_KEY_VALUE *ValueCell,
|
|
||||||
OUT HCELL_INDEX *ValueCellOffset)
|
|
||||||
{
|
|
||||||
PVALUE_LIST_CELL ValueListCell;
|
|
||||||
PCM_KEY_VALUE CurValueCell;
|
|
||||||
ULONG i;
|
|
||||||
|
|
||||||
*ValueCell = NULL;
|
|
||||||
if (ValueCellOffset != NULL)
|
|
||||||
*ValueCellOffset = (HCELL_INDEX)-1;
|
|
||||||
|
|
||||||
/* The key does not have any values */
|
|
||||||
if (KeyCell->ValueList.List == (HCELL_INDEX)-1)
|
|
||||||
{
|
|
||||||
return STATUS_OBJECT_NAME_NOT_FOUND;
|
|
||||||
}
|
|
||||||
|
|
||||||
ValueListCell = HvGetCell (&RegistryHive->Hive, KeyCell->ValueList.List);
|
|
||||||
|
|
||||||
VERIFY_VALUE_LIST_CELL(ValueListCell);
|
|
||||||
|
|
||||||
for (i = 0; i < KeyCell->ValueList.Count; i++)
|
|
||||||
{
|
|
||||||
CurValueCell = HvGetCell (&RegistryHive->Hive,
|
|
||||||
ValueListCell->ValueOffset[i]);
|
|
||||||
|
|
||||||
if (CmiComparePackedNames(ValueName,
|
|
||||||
CurValueCell->Name,
|
|
||||||
CurValueCell->NameSize,
|
|
||||||
(BOOLEAN)((CurValueCell->Flags & REG_VALUE_NAME_PACKED) ? TRUE : FALSE)))
|
|
||||||
{
|
|
||||||
*ValueCell = CurValueCell;
|
|
||||||
if (ValueCellOffset != NULL)
|
|
||||||
*ValueCellOffset = ValueListCell->ValueOffset[i];
|
|
||||||
//DPRINT("Found value %s\n", ValueName);
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return STATUS_OBJECT_NAME_NOT_FOUND;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
CmiGetValueFromKeyByIndex(IN PEREGISTRY_HIVE RegistryHive,
|
CmiGetValueFromKeyByIndex(IN PEREGISTRY_HIVE RegistryHive,
|
||||||
IN PCM_KEY_NODE KeyCell,
|
IN PCM_KEY_NODE KeyCell,
|
||||||
|
@ -1480,241 +1338,6 @@ CmiCompareKeyNamesI(PUNICODE_STRING KeyName,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
CmiCopyKey (PEREGISTRY_HIVE DstHive,
|
|
||||||
PCM_KEY_NODE DstKeyCell,
|
|
||||||
PEREGISTRY_HIVE SrcHive,
|
|
||||||
PCM_KEY_NODE SrcKeyCell)
|
|
||||||
{
|
|
||||||
PCM_KEY_NODE NewKeyCell;
|
|
||||||
ULONG NewKeyCellSize;
|
|
||||||
HCELL_INDEX NewKeyCellOffset;
|
|
||||||
PHASH_TABLE_CELL NewHashTableCell;
|
|
||||||
ULONG NewHashTableSize;
|
|
||||||
HCELL_INDEX NewHashTableOffset;
|
|
||||||
ULONG i;
|
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
|
||||||
|
|
||||||
DPRINT ("CmiCopyKey() called\n");
|
|
||||||
|
|
||||||
if (DstKeyCell == NULL)
|
|
||||||
{
|
|
||||||
/* Allocate and copy key cell */
|
|
||||||
NewKeyCellSize = sizeof(CM_KEY_NODE) + SrcKeyCell->NameSize;
|
|
||||||
NewKeyCellOffset = HvAllocateCell (&DstHive->Hive, NewKeyCellSize, HvStable);
|
|
||||||
if (NewKeyCellOffset == HCELL_NULL)
|
|
||||||
{
|
|
||||||
DPRINT1 ("Failed to allocate a key cell\n");
|
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
}
|
|
||||||
|
|
||||||
NewKeyCell = HvGetCell (&DstHive->Hive, NewKeyCellOffset);
|
|
||||||
RtlCopyMemory (NewKeyCell,
|
|
||||||
SrcKeyCell,
|
|
||||||
NewKeyCellSize);
|
|
||||||
|
|
||||||
DstHive->Hive.HiveHeader->RootCell = NewKeyCellOffset;
|
|
||||||
|
|
||||||
/* Copy class name */
|
|
||||||
if (SrcKeyCell->ClassNameOffset != (HCELL_INDEX) -1)
|
|
||||||
{
|
|
||||||
PVOID SrcClassNameCell;
|
|
||||||
PVOID NewClassNameCell;
|
|
||||||
HCELL_INDEX NewClassNameOffset;
|
|
||||||
|
|
||||||
SrcClassNameCell = HvGetCell (&SrcHive->Hive, SrcKeyCell->ClassNameOffset);
|
|
||||||
|
|
||||||
NewKeyCell->ClassSize = SrcKeyCell->ClassSize;
|
|
||||||
NewClassNameOffset = HvAllocateCell (&DstHive->Hive, NewKeyCell->ClassSize, HvStable);
|
|
||||||
if (NewClassNameOffset == HCELL_NULL)
|
|
||||||
{
|
|
||||||
DPRINT1 ("CmiAllocateBlock() failed\n");
|
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
}
|
|
||||||
|
|
||||||
NewClassNameCell = HvGetCell (&DstHive->Hive, NewClassNameOffset);
|
|
||||||
RtlCopyMemory (NewClassNameCell,
|
|
||||||
SrcClassNameCell,
|
|
||||||
NewKeyCell->ClassSize);
|
|
||||||
NewKeyCell->ClassNameOffset = NewClassNameOffset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
NewKeyCell = DstKeyCell;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Allocate hash table */
|
|
||||||
if (SrcKeyCell->SubKeyCounts[HvStable] > 0)
|
|
||||||
{
|
|
||||||
NewHashTableSize = ROUND_UP(SrcKeyCell->SubKeyCounts[HvStable] + 1, 4) - 1;
|
|
||||||
Status = CmiAllocateHashTableCell (DstHive,
|
|
||||||
&NewHashTableCell,
|
|
||||||
&NewHashTableOffset,
|
|
||||||
NewHashTableSize,
|
|
||||||
HvStable);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT1 ("CmiAllocateHashTableBlock() failed (Status %lx)\n", Status);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
NewKeyCell->SubKeyLists[HvStable] = NewHashTableOffset;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
NewHashTableCell = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Allocate and copy value list and values */
|
|
||||||
if (SrcKeyCell->ValueList.Count != 0)
|
|
||||||
{
|
|
||||||
PVALUE_LIST_CELL NewValueListCell;
|
|
||||||
PVALUE_LIST_CELL SrcValueListCell;
|
|
||||||
PCM_KEY_VALUE NewValueCell;
|
|
||||||
PCM_KEY_VALUE SrcValueCell;
|
|
||||||
PVOID SrcValueDataCell;
|
|
||||||
PVOID NewValueDataCell;
|
|
||||||
HCELL_INDEX ValueCellOffset;
|
|
||||||
HCELL_INDEX ValueDataCellOffset;
|
|
||||||
ULONG NewValueListCellSize;
|
|
||||||
ULONG NewValueCellSize;
|
|
||||||
|
|
||||||
|
|
||||||
NewValueListCellSize =
|
|
||||||
ROUND_UP(SrcKeyCell->ValueList.Count, 4) * sizeof(HCELL_INDEX);
|
|
||||||
NewKeyCell->ValueList.List = HvAllocateCell (&DstHive->Hive,
|
|
||||||
NewValueListCellSize,
|
|
||||||
HvStable);
|
|
||||||
if (NewKeyCell->ValueList.List == HCELL_NULL)
|
|
||||||
{
|
|
||||||
DPRINT1 ("HvAllocateCell() failed\n");
|
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
}
|
|
||||||
DPRINT1("KeyCell->ValueList.List: %x\n", NewKeyCell->ValueList.List);
|
|
||||||
|
|
||||||
NewValueListCell = HvGetCell (&DstHive->Hive, NewKeyCell->ValueList.List);
|
|
||||||
RtlZeroMemory (NewValueListCell,
|
|
||||||
NewValueListCellSize);
|
|
||||||
|
|
||||||
/* Copy values */
|
|
||||||
SrcValueListCell = HvGetCell (&SrcHive->Hive, SrcKeyCell->ValueList.List);
|
|
||||||
for (i = 0; i < SrcKeyCell->ValueList.Count; i++)
|
|
||||||
{
|
|
||||||
/* Copy value cell */
|
|
||||||
SrcValueCell = HvGetCell (&SrcHive->Hive, SrcValueListCell->ValueOffset[i]);
|
|
||||||
|
|
||||||
NewValueCellSize = sizeof(CM_KEY_VALUE) + SrcValueCell->NameSize;
|
|
||||||
ValueCellOffset = HvAllocateCell (&DstHive->Hive, NewValueCellSize, HvStable);
|
|
||||||
if (ValueCellOffset == HCELL_NULL)
|
|
||||||
{
|
|
||||||
DPRINT1 ("HvAllocateCell() failed (Status %lx)\n", Status);
|
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
}
|
|
||||||
|
|
||||||
NewValueCell = HvGetCell (&DstHive->Hive, ValueCellOffset);
|
|
||||||
NewValueListCell->ValueOffset[i] = ValueCellOffset;
|
|
||||||
RtlCopyMemory (NewValueCell,
|
|
||||||
SrcValueCell,
|
|
||||||
NewValueCellSize);
|
|
||||||
|
|
||||||
/* Copy value data cell */
|
|
||||||
if (SrcValueCell->DataSize > (LONG) sizeof(PVOID))
|
|
||||||
{
|
|
||||||
SrcValueDataCell = HvGetCell (&SrcHive->Hive, SrcValueCell->DataOffset);
|
|
||||||
|
|
||||||
ValueDataCellOffset = HvAllocateCell (&DstHive->Hive, SrcValueCell->DataSize, HvStable);
|
|
||||||
if (ValueDataCellOffset == HCELL_NULL)
|
|
||||||
{
|
|
||||||
DPRINT1 ("HvAllocateCell() failed\n");
|
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
}
|
|
||||||
NewValueDataCell = HvGetCell (&DstHive->Hive, ValueDataCellOffset);
|
|
||||||
RtlCopyMemory (NewValueDataCell,
|
|
||||||
SrcValueDataCell,
|
|
||||||
SrcValueCell->DataSize);
|
|
||||||
NewValueCell->DataOffset = ValueDataCellOffset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Copy subkeys */
|
|
||||||
if (SrcKeyCell->SubKeyCounts[HvStable] > 0)
|
|
||||||
{
|
|
||||||
PHASH_TABLE_CELL SrcHashTableCell;
|
|
||||||
PCM_KEY_NODE SrcSubKeyCell;
|
|
||||||
PCM_KEY_NODE NewSubKeyCell;
|
|
||||||
ULONG NewSubKeyCellSize;
|
|
||||||
HCELL_INDEX NewSubKeyCellOffset;
|
|
||||||
PHASH_RECORD SrcHashRecord;
|
|
||||||
|
|
||||||
SrcHashTableCell = HvGetCell (&SrcHive->Hive, SrcKeyCell->SubKeyLists[HvStable]);
|
|
||||||
|
|
||||||
for (i = 0; i < SrcKeyCell->SubKeyCounts[HvStable]; i++)
|
|
||||||
{
|
|
||||||
SrcHashRecord = &SrcHashTableCell->Table[i];
|
|
||||||
SrcSubKeyCell = HvGetCell (&SrcHive->Hive, SrcHashRecord->KeyOffset);
|
|
||||||
|
|
||||||
/* Allocate and copy key cell */
|
|
||||||
NewSubKeyCellSize = sizeof(CM_KEY_NODE) + SrcSubKeyCell->NameSize;
|
|
||||||
NewSubKeyCellOffset = HvAllocateCell (&DstHive->Hive, NewSubKeyCellSize, HvStable);
|
|
||||||
if (NewSubKeyCellOffset == HCELL_NULL)
|
|
||||||
{
|
|
||||||
DPRINT1 ("Failed to allocate a sub key cell\n");
|
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
}
|
|
||||||
|
|
||||||
NewSubKeyCell = HvGetCell (&DstHive->Hive, NewSubKeyCellOffset);
|
|
||||||
NewHashTableCell->Table[i].KeyOffset = NewSubKeyCellOffset;
|
|
||||||
NewHashTableCell->Table[i].HashValue = SrcHashRecord->HashValue;
|
|
||||||
|
|
||||||
RtlCopyMemory (NewSubKeyCell,
|
|
||||||
SrcSubKeyCell,
|
|
||||||
NewSubKeyCellSize);
|
|
||||||
|
|
||||||
/* Copy class name */
|
|
||||||
if (SrcSubKeyCell->ClassNameOffset != (HCELL_INDEX) -1)
|
|
||||||
{
|
|
||||||
PVOID SrcClassNameCell;
|
|
||||||
PVOID NewClassNameCell;
|
|
||||||
HCELL_INDEX NewClassNameOffset;
|
|
||||||
|
|
||||||
SrcClassNameCell = HvGetCell (&SrcHive->Hive,
|
|
||||||
SrcSubKeyCell->ClassNameOffset);
|
|
||||||
|
|
||||||
NewSubKeyCell->ClassSize = SrcSubKeyCell->ClassSize;
|
|
||||||
NewClassNameOffset = HvAllocateCell (&DstHive->Hive,
|
|
||||||
NewSubKeyCell->ClassSize,
|
|
||||||
HvStable);
|
|
||||||
if (NewClassNameOffset == HCELL_NULL)
|
|
||||||
{
|
|
||||||
DPRINT1 ("HvAllocateCell() failed (Status %lx)\n", Status);
|
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
}
|
|
||||||
|
|
||||||
NewClassNameCell = HvGetCell (&DstHive->Hive, NewClassNameOffset);
|
|
||||||
NewSubKeyCell->ClassNameOffset = NewClassNameOffset;
|
|
||||||
RtlCopyMemory (NewClassNameCell,
|
|
||||||
SrcClassNameCell,
|
|
||||||
NewSubKeyCell->ClassSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Copy subkey data and subkeys */
|
|
||||||
Status = CmiCopyKey (DstHive,
|
|
||||||
NewSubKeyCell,
|
|
||||||
SrcHive,
|
|
||||||
SrcSubKeyCell);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT1 ("CmiAllocateBlock() failed (Status %lx)\n", Status);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
CmiSaveTempHive (PEREGISTRY_HIVE Hive,
|
CmiSaveTempHive (PEREGISTRY_HIVE Hive,
|
||||||
HANDLE FileHandle)
|
HANDLE FileHandle)
|
||||||
|
|
|
@ -391,6 +391,7 @@ CmpFindSubKeyInLeaf(IN PHHIVE Hive,
|
||||||
/* Check if we got lucky and found it */
|
/* Check if we got lucky and found it */
|
||||||
if (!Result) return i;
|
if (!Result) return i;
|
||||||
|
|
||||||
|
#ifdef SOMEONE_WAS_NICE_ENOUGH_TO_MAKE_OUR_CELLS_LEXICALLY_SORTED
|
||||||
/* Check if the result is below us */
|
/* Check if the result is below us */
|
||||||
if (Result < 0)
|
if (Result < 0)
|
||||||
{
|
{
|
||||||
|
@ -405,7 +406,6 @@ CmpFindSubKeyInLeaf(IN PHHIVE Hive,
|
||||||
Low = i;
|
Low = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SOMEONE_WAS_NICE_ENOUGH_TO_MAKE_OUR_CELLS_LEXICALLY_SORTED
|
|
||||||
/* Check if this is the last entry, if so, break out and handle it */
|
/* Check if this is the last entry, if so, break out and handle it */
|
||||||
if ((High - Low) <= 1) break;
|
if ((High - Low) <= 1) break;
|
||||||
|
|
||||||
|
|
|
@ -364,9 +364,6 @@ CmpInitializeSystemHive(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
/* Set the hive filename */
|
/* Set the hive filename */
|
||||||
RtlCreateUnicodeString(&SystemHive->HiveFileName, SYSTEM_REG_FILE);
|
RtlCreateUnicodeString(&SystemHive->HiveFileName, SYSTEM_REG_FILE);
|
||||||
|
|
||||||
/* Set the log filename */
|
|
||||||
RtlCreateUnicodeString(&SystemHive->LogFileName, SYSTEM_LOG_FILE);
|
|
||||||
|
|
||||||
/* We imported, no need to create a new hive */
|
/* We imported, no need to create a new hive */
|
||||||
Allocate = FALSE;
|
Allocate = FALSE;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue