Implemented import of binary system hive. (UNTESTED)

Improved handling of a hive's dirty block bitmap.

svn path=/trunk/; revision=4423
This commit is contained in:
Eric Kohl 2003-03-24 19:10:00 +00:00
parent 6b349cca78
commit 192fe9f464
4 changed files with 237 additions and 82 deletions

View file

@ -256,6 +256,7 @@ typedef struct _REGISTRY_HIVE
BLOCK_OFFSET *FreeListOffset;
ERESOURCE HiveResource;
PULONG BitmapBuffer;
RTL_BITMAP DirtyBitMap;
BOOLEAN HiveDirty;
} REGISTRY_HIVE, *PREGISTRY_HIVE;

View file

@ -1,4 +1,4 @@
/* $Id: import.c,v 1.11 2003/03/22 18:26:53 ekohl Exp $
/* $Id: import.c,v 1.12 2003/03/24 19:09:04 ekohl Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -613,29 +613,202 @@ CmImportTextHive(PCHAR ChunkBase,
}
VOID
BOOLEAN
CmImportSystemHive(PCHAR ChunkBase,
ULONG ChunkSize)
{
PREGISTRY_HIVE Hive;
PCELL_HEADER FreeBlock;
BLOCK_OFFSET BlockOffset;
PHBIN Bin;
ULONG i, j;
ULONG FreeOffset;
NTSTATUS Status;
ULONG BitmapSize;
// CmImportTextHive (ChunkBase, ChunkSize);
if (strncmp (ChunkBase, "REGEDIT4", 8) == 0)
{
DPRINT("Found 'REGEDIT4' magic\n");
DPRINT1("Found 'REGEDIT4' magic\n");
CmImportTextHive (ChunkBase, ChunkSize);
return TRUE;
}
else
else if (strncpy (ChunkBase, "regf", 4) != 0)
{
DPRINT1("Found '%*s' magic\n", 4, ChunkBase);
KeBugCheck(0);
DPRINT1("Found invalid '%*s' magic\n", 4, ChunkBase);
return FALSE;
}
/* Create a new hive */
Hive = ExAllocatePool (NonPagedPool,
sizeof(REGISTRY_HIVE));
if (Hive == NULL)
{
return FALSE;
}
RtlZeroMemory (Hive,
sizeof(REGISTRY_HIVE));
Hive->HiveHeader = (PHIVE_HEADER)ExAllocatePool (NonPagedPool,
sizeof(HIVE_HEADER));
if (Hive->HiveHeader == NULL)
{
DPRINT1 ("Allocating hive header failed\n");
ExFreePool (Hive);
return FALSE;
}
/* Import the hive header */
RtlCopyMemory (Hive->HiveHeader,
ChunkBase,
sizeof(HIVE_HEADER));
/* Read update counter */
Hive->UpdateCounter = Hive->HiveHeader->UpdateCounter1;
/* Set the hive's size */
Hive->FileSize = ChunkSize;
/* Set the size of the block list */
Hive->BlockListSize = (Hive->FileSize / 4096) - 1;
/* Allocate block list */
DPRINT1("Space needed for block list describing hive: 0x%x\n",
sizeof(PHBIN *) * Hive->BlockListSize);
Hive->BlockList = ExAllocatePool(NonPagedPool,
sizeof(PHBIN *) * Hive->BlockListSize);
if (Hive->BlockList == NULL)
{
DPRINT1 ("Allocating block list failed\n");
ExFreePool (Hive->HiveHeader);
ExFreePool (Hive);
return FALSE;
}
/* Allocate the first hive block */
Hive->BlockList[0] = ExAllocatePool(PagedPool,
Hive->FileSize - 4096);
if (Hive->BlockList[0] == NULL)
{
DPRINT1 ("Allocating the first hive block failed\n");
ExFreePool (Hive->BlockList);
ExFreePool (Hive->HiveHeader);
ExFreePool (Hive);
return FALSE;
}
/* Import the hive block */
RtlCopyMemory (Hive->BlockList[0],
ChunkBase + 4096,
Hive->FileSize - 4096);
/* Initialize the free block list */
Hive->FreeListSize = 0;
Hive->FreeListMax = 0;
Hive->FreeList = NULL;
BlockOffset = 0;
for (i = 0; i < Hive->BlockListSize; i++)
{
Hive->BlockList[i] = (PHBIN) (((ULONG_PTR)Hive->BlockList[0]) + BlockOffset);
Bin = (PHBIN) (((ULONG_PTR)Hive->BlockList[i]));
if (Bin->BlockId != REG_BIN_ID)
{
DPRINT1("Bad BlockId %x, offset %x\n", Bin->BlockId, BlockOffset);
/* FIXME: */
assert(FALSE);
// return STATUS_INSUFFICIENT_RESOURCES;
}
assertmsg((Bin->BlockSize % 4096) == 0, ("BlockSize (0x%.08x) must be multiplum of 4K\n", Bin->BlockSize));
if (Bin->BlockSize > 4096)
{
for (j = 1; j < Bin->BlockSize / 4096; j++)
{
Hive->BlockList[i + j] = Hive->BlockList[i];
}
i = i + j - 1;
}
/* Search free blocks and add to list */
FreeOffset = REG_HBIN_DATA_OFFSET;
while (FreeOffset < Bin->BlockSize)
{
FreeBlock = (PCELL_HEADER) ((ULONG_PTR)Hive->BlockList[i] + FreeOffset);
if (FreeBlock->CellSize > 0)
{
Status = CmiAddFree(Hive,
FreeBlock,
Hive->BlockList[i]->BlockOffset + FreeOffset,
FALSE);
if (!NT_SUCCESS(Status))
{
/* FIXME: */
assert(FALSE);
}
FreeOffset += FreeBlock->CellSize;
}
else
{
FreeOffset -= FreeBlock->CellSize;
}
}
BlockOffset += Bin->BlockSize;
}
/* Calculate bitmap size in bytes (always a multiple of 32 bits) */
BitmapSize = ROUND_UP(Hive->BlockListSize, sizeof(ULONG) * 8) / 8;
DPRINT("Hive->BlockListSize: %lu\n", Hive->BlockListSize);
DPRINT("BitmapSize: %lu Bytes %lu Bits\n", BitmapSize, BitmapSize * 8);
/* Allocate bitmap */
Hive->BitmapBuffer = (PULONG)ExAllocatePool(PagedPool,
BitmapSize);
if (Hive->BitmapBuffer == NULL)
{
DPRINT1 ("Allocating the hive bitmap failed\n");
ExFreePool (Hive->BlockList[0]);
ExFreePool (Hive->BlockList);
ExFreePool (Hive->HiveHeader);
ExFreePool (Hive);
return FALSE;
}
/* Initialize bitmap */
RtlInitializeBitMap(&Hive->DirtyBitMap,
Hive->BitmapBuffer,
BitmapSize * 8);
RtlClearAllBits(&Hive->DirtyBitMap);
Hive->HiveDirty = FALSE;
/* Initialize the hive's executive resource */
ExInitializeResourceLite(&Hive->HiveResource);
/* Acquire hive list lock exclusively */
ExAcquireResourceExclusiveLite(&CmiHiveListLock, TRUE);
/* Add the new hive to the hive list */
InsertTailList(&CmiHiveListHead, &Hive->HiveList);
/* Release hive list lock */
ExReleaseResourceLite(&CmiHiveListLock);
return TRUE;
}
VOID
BOOLEAN
CmImportHardwareHive(PCHAR ChunkBase,
ULONG ChunkSize)
{
DPRINT1("CmImportHardwareHive() called\n");
return TRUE;
}
/* EOF */

View file

@ -6,9 +6,6 @@
* UPDATE HISTORY:
*/
#ifdef WIN32_REGDBG
#include "cm_win32.h"
#else
#include <ddk/ntddk.h>
#include <ddk/ntifs.h>
#include <roscfg.h>
@ -23,7 +20,7 @@
#include <internal/debug.h>
#include "cm.h"
#endif
/* uncomment to enable hive checks (incomplete and probably buggy) */
// #define HIVE_CHECK
@ -81,11 +78,7 @@ CmiCreateDefaultRootKeyCell(PKEY_CELL RootKeyCell)
{
assert(RootKeyCell);
RtlZeroMemory(RootKeyCell, sizeof(KEY_CELL));
#ifdef WIN32_REGDBG
RootKeyCell->CellSize = -(LONG)sizeof(KEY_CELL);
#else
RootKeyCell->CellSize = -sizeof(KEY_CELL);
#endif
RootKeyCell->Id = REG_KEY_CELL_ID;
RootKeyCell->Type = REG_ROOT_KEY_CELL_TYPE;
NtQuerySystemTime((PTIME) &RootKeyCell->LastWriteTime);
@ -766,9 +759,9 @@ CmiInitNonVolatileRegistryHive(PREGISTRY_HIVE RegistryHive,
PHBIN tmpBin;
ULONG i, j;
ULONG BitmapSize;
PULONG BitmapBuffer;
DPRINT1("CmiInitNonVolatileRegistryHive(%p, %S, %d) - Entered.\n", RegistryHive, Filename, CreateNew);
DPRINT("CmiInitNonVolatileRegistryHive(%p, %S, %d) called\n",
RegistryHive, Filename, CreateNew);
/* Duplicate Filename */
Status = RtlCreateUnicodeString(&RegistryHive->HiveFileName,
@ -896,7 +889,7 @@ CmiInitNonVolatileRegistryHive(PREGISTRY_HIVE RegistryHive,
sizeof(fsi),
FileStandardInformation);
assertmsg(NT_SUCCESS(Status), ("Status: 0x%X\n", Status));
if (!NT_SUCCESS(Status))
if (!NT_SUCCESS(Status) || fsi.EndOfFile.u.LowPart == 0)
{
DPRINT("NtQueryInformationFile() failed (Status %lx)\n", Status);
NtClose(FileHandle);
@ -906,17 +899,6 @@ CmiInitNonVolatileRegistryHive(PREGISTRY_HIVE RegistryHive,
}
RegistryHive->FileSize = fsi.EndOfFile.u.LowPart;
#ifdef WIN32_REGDBG
// assert(RegistryHive->FileSize);
if (RegistryHive->FileSize == 0)
{
DPRINT("CmiInitPermanentRegistryHive() - Failed, zero length hive file.\n");
NtClose(FileHandle);
RtlFreeUnicodeString(&RegistryHive->HiveFileName);
RtlFreeUnicodeString(&RegistryHive->LogFileName);
return STATUS_INSUFFICIENT_RESOURCES;
}
#endif
RegistryHive->BlockListSize = (RegistryHive->FileSize / 4096) - 1;
DPRINT("Space needed for block list describing hive: 0x%x\n",
@ -937,10 +919,6 @@ CmiInitNonVolatileRegistryHive(PREGISTRY_HIVE RegistryHive,
RegistryHive->BlockList[0] = ExAllocatePool(PagedPool,
RegistryHive->FileSize - 4096);
#ifdef WIN32_REGDBG
RtlZeroMemory(RegistryHive->BlockList[0], RegistryHive->FileSize - 4096);
#endif
if (RegistryHive->BlockList[0] == NULL)
{
ExFreePool(RegistryHive->BlockList);
@ -1034,10 +1012,10 @@ CmiInitNonVolatileRegistryHive(PREGISTRY_HIVE RegistryHive,
DPRINT("BitmapSize: %lu Bytes %lu Bits\n", BitmapSize, BitmapSize * 8);
/* Allocate bitmap */
BitmapBuffer = (PULONG)ExAllocatePool(PagedPool,
BitmapSize);
RegistryHive->BitmapBuffer = (PULONG)ExAllocatePool(PagedPool,
BitmapSize);
RtlInitializeBitMap(&RegistryHive->DirtyBitMap,
BitmapBuffer,
RegistryHive->BitmapBuffer,
BitmapSize * 8);
/* Initialize bitmap */
@ -1822,7 +1800,7 @@ CmiFlushRegistryHive(PREGISTRY_HIVE RegistryHive)
ULONG
CmiGetMaxNameLength(PREGISTRY_HIVE RegistryHive,
PKEY_CELL KeyCell)
PKEY_CELL KeyCell)
{
PHASH_TABLE_CELL HashBlock;
PKEY_CELL CurSubKeyCell;
@ -1841,27 +1819,27 @@ CmiGetMaxNameLength(PREGISTRY_HIVE RegistryHive,
for (i = 0; i < HashBlock->HashTableSize; i++)
{
if (HashBlock->Table[i].KeyOffset != 0)
{
CurSubKeyCell = CmiGetBlock(RegistryHive,
HashBlock->Table[i].KeyOffset,
NULL);
if (MaxName < CurSubKeyCell->NameSize)
{
MaxName = CurSubKeyCell->NameSize;
}
CmiReleaseBlock(RegistryHive, CurSubKeyCell);
}
{
CurSubKeyCell = CmiGetBlock(RegistryHive,
HashBlock->Table[i].KeyOffset,
NULL);
if (MaxName < CurSubKeyCell->NameSize)
{
MaxName = CurSubKeyCell->NameSize;
}
CmiReleaseBlock(RegistryHive, CurSubKeyCell);
}
}
CmiReleaseBlock(RegistryHive, HashBlock);
return MaxName;
}
ULONG
CmiGetMaxClassLength(PREGISTRY_HIVE RegistryHive,
PKEY_CELL KeyCell)
PKEY_CELL KeyCell)
{
PHASH_TABLE_CELL HashBlock;
PKEY_CELL CurSubKeyCell;
@ -1880,16 +1858,16 @@ CmiGetMaxClassLength(PREGISTRY_HIVE RegistryHive,
for (i = 0; i < HashBlock->HashTableSize; i++)
{
if (HashBlock->Table[i].KeyOffset != 0)
{
CurSubKeyCell = CmiGetBlock(RegistryHive,
HashBlock->Table[i].KeyOffset,
NULL);
if (MaxClass < CurSubKeyCell->ClassSize)
{
MaxClass = CurSubKeyCell->ClassSize;
}
CmiReleaseBlock(RegistryHive, CurSubKeyCell);
}
{
CurSubKeyCell = CmiGetBlock(RegistryHive,
HashBlock->Table[i].KeyOffset,
NULL);
if (MaxClass < CurSubKeyCell->ClassSize)
{
MaxClass = CurSubKeyCell->ClassSize;
}
CmiReleaseBlock(RegistryHive, CurSubKeyCell);
}
}
CmiReleaseBlock(RegistryHive, HashBlock);
@ -1898,9 +1876,9 @@ CmiGetMaxClassLength(PREGISTRY_HIVE RegistryHive,
}
ULONG
ULONG
CmiGetMaxValueNameLength(PREGISTRY_HIVE RegistryHive,
PKEY_CELL KeyCell)
PKEY_CELL KeyCell)
{
PVALUE_LIST_CELL ValueListCell;
PVALUE_CELL CurValueCell;
@ -1909,7 +1887,9 @@ CmiGetMaxValueNameLength(PREGISTRY_HIVE RegistryHive,
VERIFY_KEY_CELL(KeyCell);
ValueListCell = CmiGetBlock(RegistryHive, KeyCell->ValuesOffset, NULL);
ValueListCell = CmiGetBlock(RegistryHive,
KeyCell->ValuesOffset,
NULL);
MaxValueName = 0;
if (ValueListCell == NULL)
{
@ -1930,7 +1910,7 @@ CmiGetMaxValueNameLength(PREGISTRY_HIVE RegistryHive,
}
CmiReleaseBlock(RegistryHive, ValueListCell);
return MaxValueName;
}
@ -1973,12 +1953,12 @@ CmiGetMaxValueDataLength(PREGISTRY_HIVE RegistryHive,
NTSTATUS
CmiScanForSubKey(IN PREGISTRY_HIVE RegistryHive,
IN PKEY_CELL KeyCell,
OUT PKEY_CELL *SubKeyCell,
OUT BLOCK_OFFSET *BlockOffset,
IN PCHAR KeyName,
IN ACCESS_MASK DesiredAccess,
IN ULONG Attributes)
IN PKEY_CELL KeyCell,
OUT PKEY_CELL *SubKeyCell,
OUT BLOCK_OFFSET *BlockOffset,
IN PCHAR KeyName,
IN ACCESS_MASK DesiredAccess,
IN ULONG Attributes)
{
PHASH_TABLE_CELL HashBlock;
PKEY_CELL CurSubKeyCell;
@ -2336,10 +2316,10 @@ CmiRemoveSubKey(PREGISTRY_HIVE RegistryHive,
NTSTATUS
CmiScanKeyForValue(IN PREGISTRY_HIVE RegistryHive,
IN PKEY_CELL KeyCell,
IN PUNICODE_STRING ValueName,
OUT PVALUE_CELL *ValueCell,
OUT BLOCK_OFFSET *VBOffset)
IN PKEY_CELL KeyCell,
IN PUNICODE_STRING ValueName,
OUT PVALUE_CELL *ValueCell,
OUT BLOCK_OFFSET *VBOffset)
{
PVALUE_LIST_CELL ValueListCell;
PVALUE_CELL CurValueCell;
@ -2386,9 +2366,9 @@ CmiScanKeyForValue(IN PREGISTRY_HIVE RegistryHive,
NTSTATUS
CmiGetValueFromKeyByIndex(IN PREGISTRY_HIVE RegistryHive,
IN PKEY_CELL KeyCell,
IN ULONG Index,
OUT PVALUE_CELL *ValueCell)
IN PKEY_CELL KeyCell,
IN ULONG Index,
OUT PVALUE_CELL *ValueCell)
{
PVALUE_LIST_CELL ValueListCell;
PVALUE_CELL CurValueCell;
@ -2775,8 +2755,8 @@ CmiDestroyValueCell(PREGISTRY_HIVE RegistryHive,
NTSTATUS
CmiAddBin(PREGISTRY_HIVE RegistryHive,
PVOID *NewBlock,
BLOCK_OFFSET *NewBlockOffset)
PVOID *NewBlock,
BLOCK_OFFSET *NewBlockOffset)
{
PCELL_HEADER tmpBlock;
PHBIN * tmpBlockList;
@ -2839,9 +2819,10 @@ CmiAddBin(PREGISTRY_HIVE RegistryHive,
RtlCopyMemory(BitmapBuffer,
RegistryHive->DirtyBitMap.Buffer,
RegistryHive->DirtyBitMap.SizeOfBitMap);
ExFreePool(RegistryHive->DirtyBitMap.Buffer);
ExFreePool(RegistryHive->BitmapBuffer);
RegistryHive->BitmapBuffer = BitmapBuffer;
RtlInitializeBitMap(&RegistryHive->DirtyBitMap,
BitmapBuffer,
RegistryHive->BitmapBuffer,
BitmapSize * 8);
}

View file

@ -45,8 +45,8 @@ VOID PsInit(VOID);
VOID CmInitializeRegistry(VOID);
VOID CmInit2(PCHAR CommandLine);
VOID CmShutdownRegistry(VOID);
VOID CmImportSystemHive(PCHAR ChunkBase, ULONG ChunkSize);
VOID CmImportHardwareHive(PCHAR ChunkBase, ULONG ChunkSize);
BOOLEAN CmImportSystemHive(PCHAR ChunkBase, ULONG ChunkSize);
BOOLEAN CmImportHardwareHive(PCHAR ChunkBase, ULONG ChunkSize);
VOID KdInitSystem(ULONG Reserved, PLOADER_PARAMETER_BLOCK LoaderBlock);
VOID RtlpInitNlsTables(VOID);