*/
#include <ddk/ntddk.h>
-#include <ddk/ntifs.h>
#include <roscfg.h>
#include <internal/ob.h>
#include <limits.h>
#include <string.h>
-#include <internal/pool.h>
#include <internal/registry.h>
+#include <ntos/minmax.h>
#include <reactos/bugcodes.h>
#define NDEBUG
Header->BlockId = REG_HIVE_ID;
Header->UpdateCounter1 = 0;
Header->UpdateCounter2 = 0;
- Header->DateModified.dwLowDateTime = 0;
- Header->DateModified.dwHighDateTime = 0;
+ Header->DateModified.u.LowPart = 0;
+ Header->DateModified.u.HighPart = 0;
Header->Unused3 = 1;
Header->Unused4 = 3;
Header->Unused5 = 0;
assert(BinCell);
RtlZeroMemory(BinCell, sizeof(HBIN));
BinCell->BlockId = REG_BIN_ID;
- BinCell->DateModified.dwLowDateTime = 0;
- BinCell->DateModified.dwHighDateTime = 0;
+ BinCell->DateModified.u.LowPart = 0;
+ BinCell->DateModified.u.HighPart = 0;
BinCell->BlockSize = REG_BLOCK_SIZE;
}
RtlZeroMemory(RootKeyCell, sizeof(KEY_CELL));
RootKeyCell->CellSize = -sizeof(KEY_CELL);
RootKeyCell->Id = REG_KEY_CELL_ID;
- RootKeyCell->Type = REG_ROOT_KEY_CELL_TYPE;
- NtQuerySystemTime((PTIME) &RootKeyCell->LastWriteTime);
+ RootKeyCell->Flags = REG_KEY_ROOT_CELL | REG_KEY_NAME_PACKED;
+ NtQuerySystemTime(&RootKeyCell->LastWriteTime);
RootKeyCell->ParentKeyOffset = 0;
RootKeyCell->NumberOfSubKeys = 0;
RootKeyCell->HashTableOffset = -1;
assert(KeyCell->Id == REG_KEY_CELL_ID);
}
- if ((KeyCell->Type != REG_KEY_CELL_TYPE)
- && (KeyCell->Type != REG_ROOT_KEY_CELL_TYPE))
- {
- DbgPrint("Type is %.08x (should be %.08x or %.08x)\n",
- KeyCell->Type, REG_KEY_CELL_TYPE, REG_ROOT_KEY_CELL_TYPE);
- assert(FALSE);
- }
+ //KeyCell->Flags;
//KeyCell->LastWriteTime;
CmiVerifyKeyCell(RootKeyCell);
- if (RootKeyCell->Type != REG_ROOT_KEY_CELL_TYPE)
+ if (!(RootKeyCell->Flags & REG_KEY_ROOT_CELL))
{
- DbgPrint("Type is %.08x (should be %.08x)\n",
- RootKeyCell->Type, REG_ROOT_KEY_CELL_TYPE);
- assert(RootKeyCell->Type == REG_ROOT_KEY_CELL_TYPE);
+ DbgPrint("Flags is %.08x (should be %.08x)\n",
+ RootKeyCell->Flags, REG_KEY_ROOT_CELL | REG_KEY_NAME_PACKED);
+ assert(!(RootKeyCell->Flags & (REG_KEY_ROOT_CELL | REG_KEY_NAME_PACKED)));
}
}
}
-#if 0
-static NTSTATUS
-CmiPopulateHive(HANDLE FileHandle)
-{
- IO_STATUS_BLOCK IoStatusBlock;
- LARGE_INTEGER FileOffset;
- PCELL_HEADER FreeCell;
- NTSTATUS Status;
- PHBIN BinCell;
- PCHAR tBuf;
- ULONG i;
-
- tBuf = (PCHAR) ExAllocatePool(NonPagedPool, REG_BLOCK_SIZE);
- if (tBuf == NULL)
- return STATUS_INSUFFICIENT_RESOURCES;
-
- BinCell = (PHBIN) tBuf;
- FreeCell = (PCELL_HEADER) (tBuf + REG_HBIN_DATA_OFFSET);
-
- CmiCreateDefaultBinCell(BinCell);
-
- // The whole block is free
- FreeCell->CellSize = REG_BLOCK_SIZE - REG_HBIN_DATA_OFFSET;
-
- // Add free blocks so we don't need to expand
- // the file for a while
- for (i = 1; i < 50; i++)
- {
- // Block offset of this bin
- BinCell->BlockOffset = i * REG_BLOCK_SIZE;
-
- FileOffset.u.HighPart = 0;
- FileOffset.u.LowPart = (i + 1) * REG_BLOCK_SIZE;
-
- Status = NtWriteFile(FileHandle,
- NULL,
- NULL,
- NULL,
- &IoStatusBlock,
- tBuf,
- REG_BLOCK_SIZE,
- &FileOffset,
- NULL);
- assertmsg(NT_SUCCESS(Status), ("Status: 0x%X\n", Status));
- if (!NT_SUCCESS(Status))
- {
- ExFreePool(tBuf);
- return Status;
- }
- }
-
- ExFreePool(tBuf);
-
- return Status;
-}
-#endif
-
-
static NTSTATUS
CmiCreateNewRegFile(HANDLE FileHandle)
{
return(Status);
}
-#if 0
- if (NT_SUCCESS(Status))
- {
- CmiPopulateHive(FileHandle);
- }
-#endif
-
Status = NtFlushBuffersFile(FileHandle,
&IoStatusBlock);
{
/* There is no way to fix the hive without log file - BSOD! */
DPRINT("Hive header inconsistent and no log file available!\n");
- KeBugCheck(CONFIG_LIST_FAILED);
+ KEBUGCHECK(CONFIG_LIST_FAILED);
}
Status = STATUS_SUCCESS;
HiveHeader->UpdateCounter1 != HiveHeader->UpdateCounter2)
{
DPRINT("Hive file and log file are inconsistent!\n");
- KeBugCheck(CONFIG_LIST_FAILED);
+ KEBUGCHECK(CONFIG_LIST_FAILED);
}
/* Log file damaged but hive is okay */
#endif
+NTSTATUS
+CmiImportHiveBins(PREGISTRY_HIVE Hive,
+ PUCHAR ChunkPtr)
+{
+ BLOCK_OFFSET BlockOffset;
+ ULONG BlockIndex;
+ PHBIN Bin;
+ ULONG j;
+
+ BlockIndex = 0;
+ BlockOffset = 0;
+ while (BlockIndex < Hive->BlockListSize)
+ {
+ Bin = (PHBIN)((ULONG_PTR)ChunkPtr + BlockOffset);
+
+ if (Bin->BlockId != REG_BIN_ID)
+ {
+ DPRINT1 ("Bad BlockId %x, offset %x\n", Bin->BlockId, BlockOffset);
+ return STATUS_REGISTRY_CORRUPT;
+ }
+
+ assertmsg((Bin->BlockSize % 4096) == 0,
+ ("BlockSize (0x%.08x) must be multiple of 4K\n",
+ Bin->BlockSize));
+
+ /* Allocate the hive block */
+ Hive->BlockList[BlockIndex] = ExAllocatePool (PagedPool,
+ Bin->BlockSize);
+ if (Hive->BlockList[BlockIndex] == NULL)
+ {
+ DPRINT1 ("ExAllocatePool() failed\n");
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* Import the Bin */
+ RtlCopyMemory (Hive->BlockList[BlockIndex],
+ Bin,
+ Bin->BlockSize);
+
+ if (Bin->BlockSize > 4096)
+ {
+ for (j = 1; j < Bin->BlockSize / 4096; j++)
+ {
+ Hive->BlockList[BlockIndex + j] = Hive->BlockList[BlockIndex];
+ }
+ }
+
+ BlockIndex += Bin->BlockSize / 4096;
+ BlockOffset += Bin->BlockSize;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+
+VOID
+CmiFreeHiveBins (PREGISTRY_HIVE Hive)
+{
+ ULONG i;
+ PHBIN Bin;
+
+ Bin = NULL;
+ for (i = 0; i < Hive->BlockListSize; i++)
+ {
+ if (Hive->BlockList[i] == NULL)
+ continue;
+
+ if (Hive->BlockList[i] != Bin)
+ {
+ Bin = Hive->BlockList[i];
+ ExFreePool (Hive->BlockList[i]);
+ }
+ Hive->BlockList[i] = NULL;
+ }
+}
+
+
+NTSTATUS
+CmiCreateHiveFreeCellList(PREGISTRY_HIVE Hive)
+{
+ BLOCK_OFFSET BlockOffset;
+ PCELL_HEADER FreeBlock;
+ ULONG BlockIndex;
+ ULONG FreeOffset;
+ PHBIN Bin;
+ NTSTATUS Status;
+
+ /* Initialize the free cell list */
+ Hive->FreeListSize = 0;
+ Hive->FreeListMax = 0;
+ Hive->FreeList = NULL;
+ Hive->FreeListOffset = NULL;
+
+ BlockOffset = 0;
+ BlockIndex = 0;
+ while (BlockIndex < Hive->BlockListSize)
+ {
+ Bin = Hive->BlockList[BlockIndex];
+
+ /* Search free blocks and add to list */
+ FreeOffset = REG_HBIN_DATA_OFFSET;
+ while (FreeOffset < Bin->BlockSize)
+ {
+ FreeBlock = (PCELL_HEADER) ((ULONG_PTR) Bin + FreeOffset);
+ if (FreeBlock->CellSize > 0)
+ {
+ Status = CmiAddFree(Hive,
+ FreeBlock,
+ Bin->BlockOffset + FreeOffset,
+ FALSE);
+
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ FreeOffset += FreeBlock->CellSize;
+ }
+ else
+ {
+ FreeOffset -= FreeBlock->CellSize;
+ }
+ }
+
+ BlockIndex += Bin->BlockSize / 4096;
+ BlockOffset += Bin->BlockSize;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+
+VOID
+CmiFreeHiveFreeCellList(PREGISTRY_HIVE Hive)
+{
+ ExFreePool (Hive->FreeList);
+ ExFreePool (Hive->FreeListOffset);
+
+ Hive->FreeListSize = 0;
+ Hive->FreeListMax = 0;
+ Hive->FreeList = NULL;
+ Hive->FreeListOffset = NULL;
+}
+
+
+NTSTATUS
+CmiCreateHiveBitmap(PREGISTRY_HIVE Hive)
+{
+ ULONG BitmapSize;
+
+ /* 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)
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ RtlInitializeBitMap(&Hive->DirtyBitMap,
+ Hive->BitmapBuffer,
+ BitmapSize * 8);
+
+ /* Initialize bitmap */
+ RtlClearAllBits(&Hive->DirtyBitMap);
+ Hive->HiveDirty = FALSE;
+
+ return STATUS_SUCCESS;
+}
+
+
static NTSTATUS
-CmiInitNonVolatileRegistryHive(PREGISTRY_HIVE RegistryHive,
- PWSTR Filename,
- BOOLEAN CreateNew)
+CmiInitNonVolatileRegistryHive (PREGISTRY_HIVE RegistryHive,
+ PWSTR Filename)
{
OBJECT_ATTRIBUTES ObjectAttributes;
- FILE_STANDARD_INFORMATION fsi;
- PCELL_HEADER FreeBlock;
- LARGE_INTEGER FileOffset;
- BLOCK_OFFSET BlockOffset;
ULONG CreateDisposition;
IO_STATUS_BLOCK IoSB;
HANDLE FileHandle;
- ULONG FreeOffset;
+ HANDLE SectionHandle;
+ PUCHAR ViewBase;
+ ULONG ViewSize;
NTSTATUS Status;
- PHBIN tmpBin;
- ULONG i, j;
- ULONG BitmapSize;
- DPRINT("CmiInitNonVolatileRegistryHive(%p, %S, %d) called\n",
- RegistryHive, Filename, CreateNew);
+ DPRINT("CmiInitNonVolatileRegistryHive(%p, %S) called\n",
+ RegistryHive, Filename);
/* Duplicate Filename */
Status = RtlCreateUnicodeString(&RegistryHive->HiveFileName,
NULL,
NULL);
- /*
- * Note:
- * This is a workaround to prevent a BSOD because of missing registry hives.
- * The workaround is only useful for developers. An implementation for the
- * ordinary user must bail out on missing registry hives because they are
- * essential to booting and configuring the OS.
- */
-#if 0
- if (CreateNew == TRUE)
- CreateDisposition = FILE_OPEN_IF;
- else
- CreateDisposition = FILE_OPEN;
-#endif
CreateDisposition = FILE_OPEN_IF;
-
Status = NtCreateFile(&FileHandle,
FILE_ALL_ACCESS,
&ObjectAttributes,
return(Status);
}
- /* Note: Another workaround! See the note above! */
-#if 0
- if ((CreateNew) && (IoSB.Information == FILE_CREATED))
-#endif
if (IoSB.Information != FILE_OPENED)
{
Status = CmiCreateNewRegFile(FileHandle);
}
}
- /* Read hive header */
- FileOffset.u.HighPart = 0;
- FileOffset.u.LowPart = 0;
- DPRINT(" Attempting to ZwReadFile(%d) for %d bytes into %p\n", FileHandle, sizeof(HIVE_HEADER), RegistryHive->HiveHeader);
- Status = NtReadFile(FileHandle,
- 0,
- 0,
- 0,
- &IoSB,
- RegistryHive->HiveHeader,
- sizeof(HIVE_HEADER),
- &FileOffset,
- 0);
- assertmsg(NT_SUCCESS(Status), ("Status: 0x%X\n", Status));
+ /* Create the hive section */
+ Status = NtCreateSection(&SectionHandle,
+ SECTION_ALL_ACCESS,
+ NULL,
+ NULL,
+ PAGE_READWRITE,
+ SEC_COMMIT,
+ FileHandle);
+ NtClose(FileHandle);
if (!NT_SUCCESS(Status))
{
- DPRINT("NtReadFile() failed (Status %lx)\n", Status);
- NtClose(FileHandle);
+ DPRINT1("NtCreateSection() failed (Status %lx)\n", Status);
RtlFreeUnicodeString(&RegistryHive->HiveFileName);
RtlFreeUnicodeString(&RegistryHive->LogFileName);
- return Status;
+ return(Status);
}
- /* Read update counter */
- RegistryHive->UpdateCounter = RegistryHive->HiveHeader->UpdateCounter1;
-
- Status = NtQueryInformationFile(FileHandle,
- &IoSB,
- &fsi,
- sizeof(fsi),
- FileStandardInformation);
- assertmsg(NT_SUCCESS(Status), ("Status: 0x%X\n", Status));
- if (!NT_SUCCESS(Status) || fsi.EndOfFile.u.LowPart == 0)
+ /* Map the hive file */
+ ViewBase = NULL;
+ ViewSize = 0;
+ Status = NtMapViewOfSection(SectionHandle,
+ NtCurrentProcess(),
+ (PVOID*)&ViewBase,
+ 0,
+ ViewSize,
+ NULL,
+ &ViewSize,
+ 0,
+ MEM_COMMIT,
+ PAGE_READWRITE);
+ if (!NT_SUCCESS(Status))
{
- DPRINT("NtQueryInformationFile() failed (Status %lx)\n", Status);
- NtClose(FileHandle);
+ DPRINT1("MmMapViewInSystemSpace() failed (Status %lx)\n", Status);
+ NtClose(SectionHandle);
RtlFreeUnicodeString(&RegistryHive->HiveFileName);
RtlFreeUnicodeString(&RegistryHive->LogFileName);
- return Status;
+ return(Status);
}
+ DPRINT("ViewBase %p ViewSize %lx\n", ViewBase, ViewSize);
- RegistryHive->FileSize = fsi.EndOfFile.u.LowPart;
+ /* Copy hive header and initalize hive */
+ RtlCopyMemory (RegistryHive->HiveHeader,
+ ViewBase,
+ sizeof(HIVE_HEADER));
+ RegistryHive->FileSize = ViewSize;
RegistryHive->BlockListSize = (RegistryHive->FileSize / 4096) - 1;
+ RegistryHive->UpdateCounter = RegistryHive->HiveHeader->UpdateCounter1;
- DPRINT("Space needed for block list describing hive: 0x%x\n",
- sizeof(PHBIN *) * RegistryHive->BlockListSize);
-
+ /* Allocate hive block list */
RegistryHive->BlockList = ExAllocatePool(NonPagedPool,
sizeof(PHBIN *) * RegistryHive->BlockListSize);
-
if (RegistryHive->BlockList == NULL)
{
- ExFreePool(RegistryHive->BlockList);
- NtClose(FileHandle);
+ DPRINT1("Failed to allocate the hive block list\n");
+ NtUnmapViewOfSection(NtCurrentProcess(),
+ ViewBase);
+ NtClose(SectionHandle);
RtlFreeUnicodeString(&RegistryHive->HiveFileName);
RtlFreeUnicodeString(&RegistryHive->LogFileName);
- DPRINT("CmiInitNonVolatileRegistryHive() - Failed 6.\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
- RegistryHive->BlockList[0] = ExAllocatePool(PagedPool,
- RegistryHive->FileSize - 4096);
- if (RegistryHive->BlockList[0] == NULL)
+ /* Import the hive bins */
+ Status = CmiImportHiveBins (RegistryHive,
+ ViewBase + 4096);
+ if (!NT_SUCCESS(Status))
{
ExFreePool(RegistryHive->BlockList);
- NtClose(FileHandle);
+ NtUnmapViewOfSection(NtCurrentProcess(),
+ ViewBase);
+ NtClose(SectionHandle);
RtlFreeUnicodeString(&RegistryHive->HiveFileName);
RtlFreeUnicodeString(&RegistryHive->LogFileName);
- DPRINT("CmiInitNonVolatileRegistryHive() - Failed 8.\n");
- return STATUS_INSUFFICIENT_RESOURCES;
+ return Status;
}
- FileOffset.u.HighPart = 0;
- FileOffset.u.LowPart = 4096;
-
- DPRINT(" Attempting to NtReadFile(%d) for %d bytes into %p\n",
- FileHandle, RegistryHive->FileSize - 4096, (PVOID)RegistryHive->BlockList[0]);
- Status = NtReadFile(FileHandle,
- 0,
- 0,
- 0,
- &IoSB,
- (PVOID) RegistryHive->BlockList[0],
- RegistryHive->FileSize - 4096,
- &FileOffset,
- 0);
-
- assertmsg(NT_SUCCESS(Status), ("Status: 0x%X\n", Status));
-
- NtClose(FileHandle);
+ /* Unmap and dereference the hive section */
+ NtUnmapViewOfSection(NtCurrentProcess(),
+ ViewBase);
+ NtClose(SectionHandle);
- RegistryHive->FreeListSize = 0;
- RegistryHive->FreeListMax = 0;
- RegistryHive->FreeList = NULL;
+ /* Initialize the free cell list */
+ Status = CmiCreateHiveFreeCellList (RegistryHive);
+ if (!NT_SUCCESS(Status))
+ {
+ CmiFreeHiveBins(RegistryHive);
+ ExFreePool(RegistryHive->BlockList);
+ RtlFreeUnicodeString(&RegistryHive->HiveFileName);
+ RtlFreeUnicodeString(&RegistryHive->LogFileName);
+ return Status;
+ }
- BlockOffset = 0;
- for (i = 0; i < RegistryHive->BlockListSize; i++)
+ /* Create the block bitmap */
+ Status = CmiCreateHiveBitmap (RegistryHive);
+ if (!NT_SUCCESS(Status))
{
- RegistryHive->BlockList[i] = (PHBIN) (((ULONG_PTR) RegistryHive->BlockList[0]) + BlockOffset);
- tmpBin = (PHBIN) (((ULONG_PTR) RegistryHive->BlockList[i]));
- if (tmpBin->BlockId != REG_BIN_ID)
- {
- DPRINT("Bad BlockId %x, offset %x\n", tmpBin->BlockId, BlockOffset);
- //KeBugCheck(0);
- return STATUS_INSUFFICIENT_RESOURCES;
- }
+ CmiFreeHiveFreeCellList(RegistryHive);
+ CmiFreeHiveBins(RegistryHive);
+ ExFreePool(RegistryHive->BlockList);
+ RtlFreeUnicodeString(&RegistryHive->HiveFileName);
+ RtlFreeUnicodeString(&RegistryHive->LogFileName);
+ return Status;
+ }
- assertmsg((tmpBin->BlockSize % 4096) == 0, ("BlockSize (0x%.08x) must be multiplum of 4K\n", tmpBin->BlockSize));
+ DPRINT("CmiInitNonVolatileRegistryHive(%p, %S) - Finished.\n",
+ RegistryHive, Filename);
- if (tmpBin->BlockSize > 4096)
- {
- for (j = 1; j < tmpBin->BlockSize / 4096; j++)
- {
- RegistryHive->BlockList[i + j] = RegistryHive->BlockList[i];
- }
- i = i + j - 1;
- }
+ return(STATUS_SUCCESS);
+}
- /* Search free blocks and add to list */
- FreeOffset = REG_HBIN_DATA_OFFSET;
- while (FreeOffset < tmpBin->BlockSize)
- {
- FreeBlock = (PCELL_HEADER) ((ULONG_PTR) RegistryHive->BlockList[i] + FreeOffset);
- if (FreeBlock->CellSize > 0)
- {
- Status = CmiAddFree(RegistryHive,
- FreeBlock,
- RegistryHive->BlockList[i]->BlockOffset + FreeOffset,
- FALSE);
- if (!NT_SUCCESS(Status))
- {
- /* FIXME: */
- assert(FALSE);
- }
+NTSTATUS
+CmiCreateVolatileHive(PREGISTRY_HIVE *RegistryHive)
+{
+ PKEY_CELL RootKeyCell;
+ PREGISTRY_HIVE Hive;
- FreeOffset += FreeBlock->CellSize;
- }
- else
- {
- FreeOffset -= FreeBlock->CellSize;
- }
- }
- BlockOffset += tmpBin->BlockSize;
- }
+ *RegistryHive = NULL;
- /*
- * Create block bitmap and clear all bits
- */
- /* Calculate bitmap size in bytes (always a multiple of 32 bits) */
- BitmapSize = ROUND_UP(RegistryHive->BlockListSize, sizeof(ULONG) * 8) / 8;
- DPRINT("RegistryHive->BlockListSize: %lu\n", RegistryHive->BlockListSize);
- DPRINT("BitmapSize: %lu Bytes %lu Bits\n", BitmapSize, BitmapSize * 8);
+ Hive = ExAllocatePool (NonPagedPool,
+ sizeof(REGISTRY_HIVE));
+ if (Hive == NULL)
+ return STATUS_INSUFFICIENT_RESOURCES;
- /* Allocate bitmap */
- RegistryHive->BitmapBuffer = (PULONG)ExAllocatePool(PagedPool,
- BitmapSize);
- RtlInitializeBitMap(&RegistryHive->DirtyBitMap,
- RegistryHive->BitmapBuffer,
- BitmapSize * 8);
+ RtlZeroMemory (Hive,
+ sizeof(REGISTRY_HIVE));
- /* Initialize bitmap */
- RtlClearAllBits(&RegistryHive->DirtyBitMap);
- RegistryHive->HiveDirty = FALSE;
+ DPRINT("Hive %x\n", Hive);
- DPRINT("CmiInitNonVolatileRegistryHive(%p, %S, %d) - Finished.\n",
- RegistryHive, Filename, CreateNew);
+ Hive->HiveHeader = (PHIVE_HEADER)ExAllocatePool (NonPagedPool,
+ sizeof(HIVE_HEADER));
+ if (Hive->HiveHeader == NULL)
+ {
+ ExFreePool (Hive);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
- return(STATUS_SUCCESS);
-}
+ Hive->Flags = (HIVE_NO_FILE | HIVE_POINTER);
+ CmiCreateDefaultHiveHeader (Hive->HiveHeader);
-static NTSTATUS
-CmiInitVolatileRegistryHive(PREGISTRY_HIVE RegistryHive)
-{
- PKEY_CELL RootKeyCell;
+ RootKeyCell = (PKEY_CELL)ExAllocatePool (NonPagedPool,
+ sizeof(KEY_CELL));
+ if (RootKeyCell == NULL)
+ {
+ ExFreePool(Hive->HiveHeader);
+ ExFreePool(Hive);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
- RegistryHive->Flags |= (HIVE_VOLATILE | HIVE_POINTER);
+ CmiCreateDefaultRootKeyCell (RootKeyCell);
+ Hive->HiveHeader->RootKeyCell = (BLOCK_OFFSET)RootKeyCell;
- CmiCreateDefaultHiveHeader(RegistryHive->HiveHeader);
+ ExInitializeResourceLite (&Hive->HiveResource);
- RootKeyCell = (PKEY_CELL) ExAllocatePool(NonPagedPool, sizeof(KEY_CELL));
+ /* Acquire hive list lock exclusively */
+ ExAcquireResourceExclusiveLite (&CmiHiveListLock,
+ TRUE);
- if (RootKeyCell == NULL)
- return STATUS_INSUFFICIENT_RESOURCES;
+ /* Add the new hive to the hive list */
+ InsertTailList (&CmiHiveListHead,
+ &Hive->HiveList);
- CmiCreateDefaultRootKeyCell(RootKeyCell);
+ /* Release hive list lock */
+ ExReleaseResourceLite (&CmiHiveListLock);
- RegistryHive->HiveHeader->RootKeyCell = (BLOCK_OFFSET) RootKeyCell;
+ VERIFY_REGISTRY_HIVE (Hive);
+
+ *RegistryHive = Hive;
return STATUS_SUCCESS;
}
NTSTATUS
-CmiCreateRegistryHive(PWSTR Filename,
- PREGISTRY_HIVE *RegistryHive,
- BOOLEAN CreateNew)
+CmiCreateTempHive(PREGISTRY_HIVE *RegistryHive)
{
+ PHBIN BinCell;
+ PCELL_HEADER FreeCell;
PREGISTRY_HIVE Hive;
NTSTATUS Status;
- DPRINT("CmiCreateRegistryHive(Filename %S)\n", Filename);
+ DPRINT ("CmiCreateTempHive() called\n");
*RegistryHive = NULL;
- Hive = ExAllocatePool(NonPagedPool, sizeof(REGISTRY_HIVE));
+ Hive = ExAllocatePool (NonPagedPool,
+ sizeof(REGISTRY_HIVE));
if (Hive == NULL)
- return(STATUS_INSUFFICIENT_RESOURCES);
-
- DPRINT("Hive %x\n", Hive);
-
- RtlZeroMemory(Hive, sizeof(REGISTRY_HIVE));
+ {
+ DPRINT1 ("Failed to allocate registry hive block\n");
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ RtlZeroMemory (Hive,
+ sizeof(REGISTRY_HIVE));
- Hive->HiveHeader = (PHIVE_HEADER)
- ExAllocatePool(NonPagedPool, sizeof(HIVE_HEADER));
+ DPRINT ("Hive %x\n", Hive);
+ Hive->HiveHeader = (PHIVE_HEADER)ExAllocatePool (NonPagedPool,
+ REG_BLOCK_SIZE);
if (Hive->HiveHeader == NULL)
{
- ExFreePool(Hive);
- return(STATUS_INSUFFICIENT_RESOURCES);
+ DPRINT1 ("Failed to allocate hive header block\n");
+ ExFreePool (Hive);
+ return STATUS_INSUFFICIENT_RESOURCES;
}
+ RtlZeroMemory (Hive->HiveHeader,
+ REG_BLOCK_SIZE);
+
+ DPRINT ("HiveHeader %x\n", Hive->HiveHeader);
+
+ Hive->Flags = HIVE_NO_FILE;
- if (Filename != NULL)
+ RtlInitUnicodeString (&Hive->HiveFileName,
+ NULL);
+ RtlInitUnicodeString (&Hive->LogFileName,
+ NULL);
+
+ CmiCreateDefaultHiveHeader (Hive->HiveHeader);
+
+ /* Allocate hive block list */
+ Hive->BlockList = ExAllocatePool (NonPagedPool,
+ sizeof(PHBIN *));
+ if (Hive->BlockList == NULL)
{
- Status = CmiInitNonVolatileRegistryHive(Hive, Filename, CreateNew);
+ DPRINT1 ("Failed to allocate hive block list\n");
+ ExFreePool(Hive->HiveHeader);
+ ExFreePool(Hive);
+ return STATUS_INSUFFICIENT_RESOURCES;
}
- else
+
+ /* Allocate first Bin */
+ Hive->BlockList[0] = ExAllocatePool (NonPagedPool,
+ REG_BLOCK_SIZE);
+ if (Hive->BlockList[0] == NULL)
{
- Status = CmiInitVolatileRegistryHive(Hive);
+ DPRINT1 ("Failed to allocate first bin\n");
+ ExFreePool(Hive->BlockList);
+ ExFreePool(Hive->HiveHeader);
+ ExFreePool(Hive);
+ return STATUS_INSUFFICIENT_RESOURCES;
}
- if (!NT_SUCCESS(Status))
+ Hive->FileSize = 2* REG_BLOCK_SIZE;
+ Hive->BlockListSize = 1;
+ Hive->UpdateCounter = Hive->HiveHeader->UpdateCounter1;
+
+
+ BinCell = (PHBIN)Hive->BlockList[0];
+ FreeCell = (PCELL_HEADER)((ULONG_PTR)BinCell + REG_HBIN_DATA_OFFSET);
+
+ CmiCreateDefaultBinCell (BinCell);
+
+ /* First block */
+ BinCell->BlockOffset = 0;
+
+ /* Offset to root key block */
+ Hive->HiveHeader->RootKeyCell = -1;
+
+ /* The rest of the block is free */
+ FreeCell->CellSize = REG_BLOCK_SIZE - REG_HBIN_DATA_OFFSET;
+
+ /* Create the free cell list */
+ Status = CmiCreateHiveFreeCellList (Hive);
+ if (Hive->BlockList[0] == NULL)
{
+ DPRINT1 ("CmiCreateHiveFreeCellList() failed (Status %lx)\n", Status);
+ ExFreePool(Hive->BlockList[0]);
+ ExFreePool(Hive->BlockList);
ExFreePool(Hive->HiveHeader);
ExFreePool(Hive);
- return(Status);
+ return Status;
}
- ExInitializeResourceLite(&Hive->HiveResource);
+
+ ExInitializeResourceLite (&Hive->HiveResource);
/* Acquire hive list lock exclusively */
- ExAcquireResourceExclusiveLite(&CmiHiveListLock, TRUE);
+ ExAcquireResourceExclusiveLite (&CmiHiveListLock,
+ TRUE);
/* Add the new hive to the hive list */
- InsertTailList(&CmiHiveListHead, &Hive->HiveList);
+ InsertTailList (&CmiHiveListHead,
+ &Hive->HiveList);
/* Release hive list lock */
- ExReleaseResourceLite(&CmiHiveListLock);
+ ExReleaseResourceLite (&CmiHiveListLock);
- VERIFY_REGISTRY_HIVE(Hive);
+ VERIFY_REGISTRY_HIVE (Hive);
*RegistryHive = Hive;
- DPRINT("CmiCreateRegistryHive(Filename %S) - Finished.\n", Filename);
+ return STATUS_SUCCESS;
+}
- return(STATUS_SUCCESS);
+
+NTSTATUS
+CmiLoadHive(IN POBJECT_ATTRIBUTES KeyObjectAttributes,
+ IN PUNICODE_STRING FileName,
+ IN ULONG Flags)
+{
+ PREGISTRY_HIVE Hive;
+ NTSTATUS Status;
+
+ DPRINT ("CmiLoadHive(Filename %wZ)\n", FileName);
+
+ if (Flags & ~REG_NO_LAZY_FLUSH)
+ return STATUS_INVALID_PARAMETER;
+
+ Hive = ExAllocatePool (NonPagedPool,
+ sizeof(REGISTRY_HIVE));
+ if (Hive == NULL)
+ {
+ DPRINT1 ("Failed to allocate hive header.\n");
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ RtlZeroMemory (Hive,
+ sizeof(REGISTRY_HIVE));
+
+ DPRINT ("Hive %x\n", Hive);
+ Hive->Flags = (Flags & REG_NO_LAZY_FLUSH) ? HIVE_NO_SYNCH : 0;
+
+ Hive->HiveHeader = (PHIVE_HEADER)ExAllocatePool(NonPagedPool,
+ sizeof(HIVE_HEADER));
+ if (Hive->HiveHeader == NULL)
+ {
+ DPRINT1 ("Failed to allocate hive header.\n");
+ ExFreePool (Hive);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ Status = CmiInitNonVolatileRegistryHive (Hive,
+ FileName->Buffer);
+ if (!NT_SUCCESS (Status))
+ {
+ DPRINT1 ("CmiInitNonVolatileRegistryHive() failed (Status %lx)\n", Status);
+ ExFreePool (Hive->HiveHeader);
+ ExFreePool (Hive);
+ return Status;
+ }
+
+ ExInitializeResourceLite (&Hive->HiveResource);
+
+ /* Add the new hive to the hive list */
+ ExAcquireResourceExclusiveLite (&CmiHiveListLock,
+ TRUE);
+ InsertTailList (&CmiHiveListHead,
+ &Hive->HiveList);
+ ExReleaseResourceLite (&CmiHiveListLock);
+
+
+ VERIFY_REGISTRY_HIVE(Hive);
+
+
+ Status = CmiConnectHive (KeyObjectAttributes,
+ Hive);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1 ("CmiConnectHive() failed (Status %lx)\n", Status);
+// CmiRemoveRegistryHive (Hive);
+ }
+
+ DPRINT ("CmiLoadHive() done\n");
+
+ return Status;
}
NTSTATUS
CmiRemoveRegistryHive(PREGISTRY_HIVE RegistryHive)
{
+ if (RegistryHive->Flags & HIVE_POINTER)
+ return STATUS_UNSUCCESSFUL;
+
/* Acquire hive list lock exclusively */
- ExAcquireResourceExclusiveLite(&CmiHiveListLock, TRUE);
+ ExAcquireResourceExclusiveLite (&CmiHiveListLock,
+ TRUE);
/* Remove hive from hive list */
- RemoveEntryList(&RegistryHive->HiveList);
+ RemoveEntryList (&RegistryHive->HiveList);
/* Release hive list lock */
- ExReleaseResourceLite(&CmiHiveListLock);
+ ExReleaseResourceLite (&CmiHiveListLock);
+
+ /* Release file names */
+ RtlFreeUnicodeString (&RegistryHive->HiveFileName);
+ RtlFreeUnicodeString (&RegistryHive->LogFileName);
+ /* Release hive bitmap */
+ ExFreePool (RegistryHive->BitmapBuffer);
- /* FIXME: Remove attached keys and values */
+ /* Release free cell list */
+ ExFreePool (RegistryHive->FreeList);
+ ExFreePool (RegistryHive->FreeListOffset);
+ /* Release hive resource */
+ ExDeleteResource (&RegistryHive->HiveResource);
+
+ /* Release bins and bin list */
+ CmiFreeHiveBins (RegistryHive);
+ ExFreePool (RegistryHive->BlockList);
/* Release hive header */
- ExFreePool(RegistryHive->HiveHeader);
+ ExFreePool (RegistryHive->HiveHeader);
/* Release hive */
- ExFreePool(RegistryHive);
+ ExFreePool (RegistryHive);
- return(STATUS_SUCCESS);
+ return STATUS_SUCCESS;
}
&RegistryHive->LogFileName);
/* Update hive header modification time */
- NtQuerySystemTime((PTIME)&RegistryHive->HiveHeader->DateModified);
+ NtQuerySystemTime(&RegistryHive->HiveHeader->DateModified);
/* Start log update */
Status = CmiStartLogUpdate(RegistryHive);
ULONG
-CmiGetMaxNameLength(PREGISTRY_HIVE RegistryHive,
- PKEY_CELL KeyCell)
+CmiGetMaxNameLength(PKEY_OBJECT KeyObject)
{
PHASH_TABLE_CELL HashBlock;
+ PKEY_OBJECT CurKey;
PKEY_CELL CurSubKeyCell;
+ PKEY_CELL KeyCell;
ULONG MaxName;
+ ULONG NameSize;
ULONG i;
+ VERIFY_KEY_OBJECT(KeyObject);
+
+ KeyCell = KeyObject->KeyCell;
VERIFY_KEY_CELL(KeyCell);
MaxName = 0;
- HashBlock = CmiGetBlock(RegistryHive, KeyCell->HashTableOffset, NULL);
+ HashBlock = CmiGetBlock(KeyObject->RegistryHive,
+ KeyCell->HashTableOffset,
+ NULL);
if (HashBlock == NULL)
{
DPRINT("CmiGetBlock() failed\n");
- return 0;
- }
-
- for (i = 0; i < HashBlock->HashTableSize; i++)
+ }
+ else
{
- if (HashBlock->Table[i].KeyOffset != 0)
- {
- CurSubKeyCell = CmiGetBlock(RegistryHive,
- HashBlock->Table[i].KeyOffset,
- NULL);
- if (CurSubKeyCell == NULL)
+ for (i = 0; i < HashBlock->HashTableSize; i++)
+ {
+ if (HashBlock->Table[i].KeyOffset != 0)
{
- DPRINT("CmiGetBlock() failed\n");
- return 0;
+ CurSubKeyCell = CmiGetBlock(KeyObject->RegistryHive,
+ HashBlock->Table[i].KeyOffset,
+ NULL);
+ if (CurSubKeyCell == NULL)
+ {
+ DPRINT("CmiGetBlock() failed\n");
+ continue;
+ }
+ NameSize = CurSubKeyCell->NameSize;
+ if (CurSubKeyCell->Flags & REG_KEY_NAME_PACKED)
+ {
+ NameSize *= sizeof(WCHAR);
+ }
+ if (MaxName < NameSize)
+ {
+ MaxName = NameSize;
+ }
}
-
- if (MaxName < CurSubKeyCell->NameSize)
+ }
+ }
+ if (KeyObject->RegistryHive != CmiVolatileHive)
+ {
+ DPRINT("KeyObject->NumberOfSubKeys %d\n", KeyObject->NumberOfSubKeys);
+ for (i = 0; i < KeyObject->NumberOfSubKeys; i++)
+ {
+ CurKey = KeyObject->SubKeys[i];
+ if (CurKey->RegistryHive == CmiVolatileHive)
{
- MaxName = CurSubKeyCell->NameSize;
+ CurSubKeyCell = CurKey->KeyCell;
+ if (CurSubKeyCell == NULL)
+ {
+ DPRINT("CmiGetBlock() failed\n");
+ continue;
+ }
+ NameSize = CurSubKeyCell->NameSize;
+ if (CurSubKeyCell->Flags & REG_KEY_NAME_PACKED)
+ {
+ NameSize *= sizeof(WCHAR);
+ }
+ if (MaxName < NameSize)
+ {
+ MaxName = NameSize;
+ }
}
}
}
ULONG
-CmiGetMaxClassLength(PREGISTRY_HIVE RegistryHive,
- PKEY_CELL KeyCell)
+CmiGetMaxClassLength(PKEY_OBJECT KeyObject)
{
PHASH_TABLE_CELL HashBlock;
+ PKEY_OBJECT CurKey;
PKEY_CELL CurSubKeyCell;
+ PKEY_CELL KeyCell;
ULONG MaxClass;
ULONG i;
+ VERIFY_KEY_OBJECT(KeyObject);
+
+ KeyCell = KeyObject->KeyCell;
VERIFY_KEY_CELL(KeyCell);
MaxClass = 0;
- HashBlock = CmiGetBlock(RegistryHive, KeyCell->HashTableOffset, NULL);
+ HashBlock = CmiGetBlock(KeyObject->RegistryHive,
+ KeyCell->HashTableOffset,
+ NULL);
if (HashBlock == NULL)
{
DPRINT("CmiGetBlock() failed\n");
- return 0;
}
-
- for (i = 0; i < HashBlock->HashTableSize; i++)
+ else
{
- if (HashBlock->Table[i].KeyOffset != 0)
- {
- CurSubKeyCell = CmiGetBlock(RegistryHive,
- HashBlock->Table[i].KeyOffset,
- NULL);
- if (CurSubKeyCell == NULL)
+ for (i = 0; i < HashBlock->HashTableSize; i++)
+ {
+ if (HashBlock->Table[i].KeyOffset != 0)
{
- DPRINT("CmiGetBlock() failed\n");
- return 0;
+ CurSubKeyCell = CmiGetBlock(KeyObject->RegistryHive,
+ HashBlock->Table[i].KeyOffset,
+ NULL);
+ if (CurSubKeyCell == NULL)
+ {
+ DPRINT("CmiGetBlock() failed\n");
+ continue;
+ }
+
+ if (MaxClass < CurSubKeyCell->ClassSize)
+ {
+ MaxClass = CurSubKeyCell->ClassSize;
+ }
}
-
- if (MaxClass < CurSubKeyCell->ClassSize)
+ }
+ }
+ if (KeyObject->RegistryHive != CmiVolatileHive)
+ {
+ DPRINT("KeyObject->NumberOfSubKeys %d\n", KeyObject->NumberOfSubKeys);
+ for (i = 0; i < KeyObject->NumberOfSubKeys; i++)
+ {
+ CurKey = KeyObject->SubKeys[i];
+ if (CurKey->RegistryHive == CmiVolatileHive)
{
- MaxClass = CurSubKeyCell->ClassSize;
+ CurSubKeyCell = CurKey->KeyCell;
+ if (CurSubKeyCell == NULL)
+ {
+ DPRINT("CmiGetBlock() failed\n");
+ continue;
+ }
+ if (MaxClass < CurSubKeyCell->ClassSize)
+ {
+ MaxClass = CurSubKeyCell->ClassSize;
+ }
}
}
}
PVALUE_LIST_CELL ValueListCell;
PVALUE_CELL CurValueCell;
ULONG MaxValueName;
+ ULONG Size;
ULONG i;
VERIFY_KEY_CELL(KeyCell);
DPRINT("CmiGetBlock() failed\n");
}
- if (CurValueCell != NULL &&
- MaxValueName < CurValueCell->NameSize)
+ if (CurValueCell != NULL)
{
- MaxValueName = CurValueCell->NameSize;
+ Size = CurValueCell->NameSize;
+ if (CurValueCell->Flags & REG_VALUE_NAME_PACKED)
+ {
+ Size *= sizeof(WCHAR);
+ }
+ if (MaxValueName < Size)
+ {
+ MaxValueName = Size;
+ }
}
}
IN PKEY_CELL KeyCell,
OUT PKEY_CELL *SubKeyCell,
OUT BLOCK_OFFSET *BlockOffset,
- IN PCHAR KeyName,
+ IN PUNICODE_STRING KeyName,
IN ACCESS_MASK DesiredAccess,
IN ULONG Attributes)
{
PHASH_TABLE_CELL HashBlock;
PKEY_CELL CurSubKeyCell;
- USHORT KeyLength;
ULONG i;
VERIFY_KEY_CELL(KeyCell);
- //DPRINT("Scanning for sub key %s\n", KeyName);
+ DPRINT("Scanning for sub key %wZ\n", KeyName);
assert(RegistryHive);
return STATUS_UNSUCCESSFUL;
}
- KeyLength = strlen(KeyName);
for (i = 0; (i < KeyCell->NumberOfSubKeys) && (i < HashBlock->HashTableSize); i++)
{
if (Attributes & OBJ_CASE_INSENSITIVE)
{
- if ((HashBlock->Table[i].KeyOffset != 0) &&
- (HashBlock->Table[i].KeyOffset != (ULONG_PTR)-1) &&
- (_strnicmp(KeyName, (PCHAR) &HashBlock->Table[i].HashValue, 4) == 0))
+ if (HashBlock->Table[i].KeyOffset != 0 &&
+ HashBlock->Table[i].KeyOffset != (ULONG_PTR)-1 &&
+ (HashBlock->Table[i].HashValue == 0 ||
+ CmiCompareHashI(KeyName, (PCHAR)&HashBlock->Table[i].HashValue)))
{
CurSubKeyCell = CmiGetBlock(RegistryHive,
HashBlock->Table[i].KeyOffset,
return STATUS_UNSUCCESSFUL;
}
- if ((CurSubKeyCell->NameSize == KeyLength)
- && (_strnicmp(KeyName, CurSubKeyCell->Name, KeyLength) == 0))
- {
- *SubKeyCell = CurSubKeyCell;
- *BlockOffset = HashBlock->Table[i].KeyOffset;
- break;
- }
- }
+ if (CmiCompareKeyNamesI(KeyName, CurSubKeyCell))
+ {
+ *SubKeyCell = CurSubKeyCell;
+ *BlockOffset = HashBlock->Table[i].KeyOffset;
+ break;
+ }
+ }
}
else
{
if (HashBlock->Table[i].KeyOffset != 0 &&
HashBlock->Table[i].KeyOffset != (ULONG_PTR) -1 &&
- !strncmp(KeyName, (PCHAR) &HashBlock->Table[i].HashValue, 4))
+ (HashBlock->Table[i].HashValue == 0 ||
+ CmiCompareHash(KeyName, (PCHAR)&HashBlock->Table[i].HashValue)))
{
CurSubKeyCell = CmiGetBlock(RegistryHive,
HashBlock->Table[i].KeyOffset,
return STATUS_UNSUCCESSFUL;
}
- if (CurSubKeyCell->NameSize == KeyLength
- && !_strnicmp(KeyName, CurSubKeyCell->Name, KeyLength))
- {
- *SubKeyCell = CurSubKeyCell;
- *BlockOffset = HashBlock->Table[i].KeyOffset;
- break;
- }
- }
+ if (CmiCompareKeyNames(KeyName, CurSubKeyCell))
+ {
+ *SubKeyCell = CurSubKeyCell;
+ *BlockOffset = HashBlock->Table[i].KeyOffset;
+ break;
+ }
+ }
}
}
CmiAddSubKey(PREGISTRY_HIVE RegistryHive,
PKEY_OBJECT Parent,
PKEY_OBJECT SubKey,
- PWSTR NewSubKeyName,
- USHORT NewSubKeyNameSize,
+ PUNICODE_STRING SubKeyName,
ULONG TitleIndex,
PUNICODE_STRING Class,
ULONG CreateOptions)
PHASH_TABLE_CELL NewHashBlock;
PHASH_TABLE_CELL HashBlock;
BLOCK_OFFSET NKBOffset;
- PKEY_CELL NewKeyCell;
+ PKEY_CELL NewKeyCell;
ULONG NewBlockSize;
PKEY_CELL KeyCell;
NTSTATUS Status;
USHORT NameSize;
+ PWSTR NamePtr;
+ BOOLEAN Packable;
+ ULONG i;
KeyCell = Parent->KeyCell;
VERIFY_KEY_CELL(KeyCell);
- if (NewSubKeyName[0] == L'\\')
+ /* Skip leading backslash */
+ if (SubKeyName->Buffer[0] == L'\\')
{
- NewSubKeyName++;
- NameSize = NewSubKeyNameSize / 2 - 1;
+ NamePtr = &SubKeyName->Buffer[1];
+ NameSize = SubKeyName->Length - sizeof(WCHAR);
}
else
{
- NameSize = NewSubKeyNameSize / 2;
+ NamePtr = SubKeyName->Buffer;
+ NameSize = SubKeyName->Length;
+ }
+
+ /* Check whether key name can be packed */
+ Packable = TRUE;
+ for (i = 0; i < NameSize / sizeof(WCHAR); i++)
+ {
+ if (NamePtr[i] & 0xFF00)
+ {
+ Packable = FALSE;
+ break;
+ }
+ }
+
+ /* Adjust name size */
+ if (Packable)
+ {
+ NameSize = NameSize / sizeof(WCHAR);
}
+
+ DPRINT("Key %S Length %lu %s\n", NamePtr, NameSize, (Packable)?"True":"False");
+
Status = STATUS_SUCCESS;
NewBlockSize = sizeof(KEY_CELL) + NameSize;
else
{
NewKeyCell->Id = REG_KEY_CELL_ID;
- NewKeyCell->Type = REG_KEY_CELL_TYPE;
- ZwQuerySystemTime((PTIME) &NewKeyCell->LastWriteTime);
+ NewKeyCell->Flags = 0;
+ NtQuerySystemTime(&NewKeyCell->LastWriteTime);
NewKeyCell->ParentKeyOffset = -1;
NewKeyCell->NumberOfSubKeys = 0;
NewKeyCell->HashTableOffset = -1;
NewKeyCell->NumberOfValues = 0;
NewKeyCell->ValuesOffset = -1;
NewKeyCell->SecurityKeyOffset = -1;
- NewKeyCell->NameSize = NameSize;
- wcstombs(NewKeyCell->Name, NewSubKeyName, NameSize);
NewKeyCell->ClassNameOffset = -1;
+ /* Pack the key name */
+ NewKeyCell->NameSize = NameSize;
+ if (Packable)
+ {
+ NewKeyCell->Flags |= REG_KEY_NAME_PACKED;
+ for (i = 0; i < NameSize; i++)
+ {
+ NewKeyCell->Name[i] = (CHAR)(NamePtr[i] & 0x00FF);
+ }
+ }
+ else
+ {
+ RtlCopyMemory(NewKeyCell->Name,
+ NamePtr,
+ NameSize);
+ }
+
VERIFY_KEY_CELL(NewKeyCell);
if (Class)
NewKeyCell->ClassSize = Class->Length + sizeof(WCHAR);
Status = CmiAllocateBlock(RegistryHive,
- (PVOID) &pClass,
+ (PVOID)&pClass,
NewKeyCell->ClassSize,
&NewKeyCell->ClassNameOffset);
- wcsncpy((PWSTR) pClass->Data, Class->Buffer, Class->Length);
+ wcsncpy((PWSTR)pClass->Data,
+ Class->Buffer,
+ Class->Length);
((PWSTR) (pClass->Data))[Class->Length] = 0;
}
}
}
else
{
- HashBlock = CmiGetBlock(RegistryHive, KeyCell->HashTableOffset, NULL);
+ HashBlock = CmiGetBlock(RegistryHive,
+ KeyCell->HashTableOffset,
+ NULL);
if (HashBlock == NULL)
{
DPRINT("CmiGetBlock() failed\n");
if (ParentKey->KeyCell->HashTableOffset != (BLOCK_OFFSET) -1)
{
DPRINT("ParentKey HashTableOffset %lx\n", ParentKey->KeyCell->HashTableOffset)
- HashBlock = CmiGetBlock(RegistryHive,
+ HashBlock = CmiGetBlock(ParentKey->RegistryHive,
ParentKey->KeyCell->HashTableOffset,
NULL);
if (HashBlock == NULL)
DPRINT("ParentKey HashBlock %p\n", HashBlock)
if (HashBlock != NULL)
{
- CmiRemoveKeyFromHashTable(RegistryHive,
+ CmiRemoveKeyFromHashTable(ParentKey->RegistryHive,
HashBlock,
SubKey->BlockOffset);
- CmiMarkBlockDirty(RegistryHive,
+ CmiMarkBlockDirty(ParentKey->RegistryHive,
ParentKey->KeyCell->HashTableOffset);
}
}
if (ParentKey->KeyCell->NumberOfSubKeys == 0)
{
DPRINT("ParentKey HashTableOffset %lx\n", ParentKey->KeyCell->HashTableOffset)
- HashBlock = CmiGetBlock(RegistryHive,
+ HashBlock = CmiGetBlock(ParentKey->RegistryHive,
ParentKey->KeyCell->HashTableOffset,
NULL);
if (HashBlock == NULL)
DPRINT("ParentKey HashBlock %p\n", HashBlock)
if (HashBlock != NULL)
{
- CmiDestroyBlock(RegistryHive,
+ CmiDestroyBlock(ParentKey->RegistryHive,
HashBlock,
ParentKey->KeyCell->HashTableOffset);
ParentKey->KeyCell->HashTableOffset = -1;
}
}
- NtQuerySystemTime((PTIME)&ParentKey->KeyCell->LastWriteTime);
- CmiMarkBlockDirty(RegistryHive,
+ NtQuerySystemTime(&ParentKey->KeyCell->LastWriteTime);
+ CmiMarkBlockDirty(ParentKey->RegistryHive,
ParentKey->BlockOffset);
}
if (HashBlock->Table[i].KeyOffset == 0)
{
HashBlock->Table[i].KeyOffset = NKBOffset;
- RtlCopyMemory(&HashBlock->Table[i].HashValue, NewKeyCell->Name, 4);
+ HashBlock->Table[i].HashValue = 0;
+ if (NewKeyCell->Flags & REG_KEY_NAME_PACKED)
+ {
+ RtlCopyMemory(&HashBlock->Table[i].HashValue,
+ NewKeyCell->Name,
+ min(NewKeyCell->NameSize, 4));
+ }
return STATUS_SUCCESS;
}
}
if (HashBlock->Table[i].KeyOffset == NKBOffset)
{
HashBlock->Table[i].KeyOffset = 0;
- RtlZeroMemory(&HashBlock->Table[i].HashValue, 4);
+ HashBlock->Table[i].HashValue = 0;
return STATUS_SUCCESS;
}
}
}
/* Update time of heap */
- if (!IsVolatileHive(RegistryHive))
- NtQuerySystemTime((PTIME) &pBin->DateModified);
+ if (!IsNoFileHive(RegistryHive))
+ NtQuerySystemTime(&pBin->DateModified);
}
/* Destroy the value cell */
Status = CmiDestroyBlock(RegistryHive, ValueCell, VBOffset);
/* Update time of heap */
- if (!IsVolatileHive(RegistryHive) && CmiGetBlock(RegistryHive, VBOffset, &pBin))
+ if (!IsNoFileHive(RegistryHive) && CmiGetBlock(RegistryHive, VBOffset, &pBin))
{
- NtQuerySystemTime((PTIME) &pBin->DateModified);
+ NtQuerySystemTime(&pBin->DateModified);
}
return Status;
RegistryHive->FileSize += REG_BLOCK_SIZE;
tmpBin->BlockSize = REG_BLOCK_SIZE;
tmpBin->Unused1 = 0;
- ZwQuerySystemTime((PTIME) &tmpBin->DateModified);
+ ZwQuerySystemTime(&tmpBin->DateModified);
tmpBin->Unused2 = 0;
/* Increase size of list of blocks */
tmpBlock->CellSize = (REG_BLOCK_SIZE - REG_HBIN_DATA_OFFSET);
/* Grow bitmap if necessary */
- if (IsVolatileHive(RegistryHive) &&
+ if (IsNoFileHive(RegistryHive) &&
(RegistryHive->BlockListSize % (sizeof(ULONG) * 8) == 0))
{
PULONG BitmapBuffer;
if (Temp)
{
- NtQuerySystemTime((PTIME) &pBin->DateModified);
+ NtQuerySystemTime(&pBin->DateModified);
CmiMarkBlockDirty(RegistryHive, RegistryHive->FreeListOffset[i]);
}
CmiAddFree(RegistryHive, Block, Offset, TRUE);
/* Update time of heap */
- if (!IsVolatileHive(RegistryHive) && CmiGetBlock(RegistryHive, Offset,&pBin))
- NtQuerySystemTime((PTIME) &pBin->DateModified);
+ if (!IsNoFileHive(RegistryHive) && CmiGetBlock(RegistryHive, Offset,&pBin))
+ NtQuerySystemTime(&pBin->DateModified);
CmiMarkBlockDirty(RegistryHive, Offset);
}
ULONG BlockNumber;
ULONG BlockCount;
- if (IsVolatileHive(RegistryHive))
+ if (IsNoFileHive(RegistryHive))
return;
DPRINT("CmiMarkBlockDirty(Offset 0x%lx)\n", (ULONG)BlockOffset);
ULONG BlockCount;
PHBIN Bin;
- if (IsVolatileHive(RegistryHive))
+ if (IsNoFileHive(RegistryHive))
return;
DPRINT("CmiMarkBinDirty(Offset 0x%lx)\n", (ULONG)BinOffset);
if (Packable != NULL)
*Packable = TRUE;
- for (i = 0; i < Name->Length; i++)
+ for (i = 0; i < Name->Length / sizeof(WCHAR); i++)
{
- if (Name->Buffer[i] > 0xFF)
+ if (Name->Buffer[i] & 0xFF00)
{
if (Packable != NULL)
*Packable = FALSE;
- return(Name->Length);
+ return Name->Length;
}
}
- return(Name->Length / sizeof(WCHAR));
+ return (Name->Length / sizeof(WCHAR));
}
NameBuffer[i] = (WCHAR)PackedNameBuffer[i];
}
+
+BOOLEAN
+CmiCompareHash(PUNICODE_STRING KeyName,
+ PCHAR HashString)
+{
+ CHAR Buffer[4];
+
+ Buffer[0] = (KeyName->Length >= 2) ? (CHAR)KeyName->Buffer[0] : 0;
+ Buffer[1] = (KeyName->Length >= 4) ? (CHAR)KeyName->Buffer[1] : 0;
+ Buffer[2] = (KeyName->Length >= 6) ? (CHAR)KeyName->Buffer[2] : 0;
+ Buffer[3] = (KeyName->Length >= 8) ? (CHAR)KeyName->Buffer[3] : 0;
+
+ return (strncmp(Buffer, HashString, 4) == 0);
+}
+
+
+BOOLEAN
+CmiCompareHashI(PUNICODE_STRING KeyName,
+ PCHAR HashString)
+{
+ CHAR Buffer[4];
+
+ Buffer[0] = (KeyName->Length >= 2) ? (CHAR)KeyName->Buffer[0] : 0;
+ Buffer[1] = (KeyName->Length >= 4) ? (CHAR)KeyName->Buffer[1] : 0;
+ Buffer[2] = (KeyName->Length >= 6) ? (CHAR)KeyName->Buffer[2] : 0;
+ Buffer[3] = (KeyName->Length >= 8) ? (CHAR)KeyName->Buffer[3] : 0;
+
+ return (_strnicmp(Buffer, HashString, 4) == 0);
+}
+
+
+BOOLEAN
+CmiCompareKeyNames(PUNICODE_STRING KeyName,
+ PKEY_CELL KeyCell)
+{
+ PWCHAR UnicodeName;
+ USHORT i;
+
+ DPRINT("Flags: %hx\n", KeyCell->Flags);
+
+ if (KeyCell->Flags & REG_KEY_NAME_PACKED)
+ {
+ if (KeyName->Length != KeyCell->NameSize * sizeof(WCHAR))
+ return FALSE;
+
+ for (i = 0; i < KeyCell->NameSize; i++)
+ {
+ if (KeyName->Buffer[i] != (WCHAR)KeyCell->Name[i])
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (KeyName->Length != KeyCell->NameSize)
+ return FALSE;
+
+ UnicodeName = (PWCHAR)KeyCell->Name;
+ for (i = 0; i < KeyCell->NameSize / sizeof(WCHAR); i++)
+ {
+ if (KeyName->Buffer[i] != UnicodeName[i])
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+
+BOOLEAN
+CmiCompareKeyNamesI(PUNICODE_STRING KeyName,
+ PKEY_CELL KeyCell)
+{
+ PWCHAR UnicodeName;
+ USHORT i;
+
+ DPRINT("Flags: %hx\n", KeyCell->Flags);
+
+ if (KeyCell->Flags & REG_KEY_NAME_PACKED)
+ {
+ if (KeyName->Length != KeyCell->NameSize * sizeof(WCHAR))
+ return FALSE;
+
+ for (i = 0; i < KeyCell->NameSize; i++)
+ {
+ if (RtlUpcaseUnicodeChar(KeyName->Buffer[i]) !=
+ RtlUpcaseUnicodeChar((WCHAR)KeyCell->Name[i]))
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (KeyName->Length != KeyCell->NameSize)
+ return FALSE;
+
+ UnicodeName = (PWCHAR)KeyCell->Name;
+ for (i = 0; i < KeyCell->NameSize / sizeof(WCHAR); i++)
+ {
+ if (RtlUpcaseUnicodeChar(KeyName->Buffer[i]) !=
+ RtlUpcaseUnicodeChar(UnicodeName[i]))
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+
+NTSTATUS
+CmiCopyKey (PREGISTRY_HIVE DstHive,
+ PKEY_CELL DstKeyCell,
+ PREGISTRY_HIVE SrcHive,
+ PKEY_CELL SrcKeyCell)
+{
+ PKEY_CELL NewKeyCell;
+ ULONG NewKeyCellSize;
+ BLOCK_OFFSET NewKeyCellOffset;
+ PHASH_TABLE_CELL NewHashTableCell;
+ ULONG NewHashTableSize;
+ BLOCK_OFFSET NewHashTableOffset;
+ ULONG i;
+ NTSTATUS Status;
+
+ DPRINT ("CmiCopyKey() called\n");
+
+ if (DstKeyCell == NULL)
+ {
+ /* Allocate and copy key cell */
+ NewKeyCellSize = sizeof(KEY_CELL) + SrcKeyCell->NameSize;
+ Status = CmiAllocateBlock (DstHive,
+ (PVOID) &NewKeyCell,
+ NewKeyCellSize,
+ &NewKeyCellOffset);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1 ("CmiAllocateBlock() failed (Status %lx)\n", Status);
+ return Status;
+ }
+ if (NewKeyCell == NULL)
+ {
+ DPRINT1 ("Failed to allocate a key cell\n");
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ RtlCopyMemory (NewKeyCell,
+ SrcKeyCell,
+ NewKeyCellSize);
+
+ DstHive->HiveHeader->RootKeyCell = NewKeyCellOffset;
+
+ /* Copy class name */
+ if (SrcKeyCell->ClassNameOffset != (BLOCK_OFFSET) -1)
+ {
+ PDATA_CELL SrcClassNameCell;
+ PDATA_CELL NewClassNameCell;
+ BLOCK_OFFSET NewClassNameOffset;
+
+ SrcClassNameCell = CmiGetBlock (SrcHive, SrcKeyCell->ClassNameOffset, NULL),
+
+ NewKeyCell->ClassSize = SrcKeyCell->ClassSize;
+ Status = CmiAllocateBlock (DstHive,
+ (PVOID)&NewClassNameCell,
+ NewKeyCell->ClassSize,
+ &NewClassNameOffset);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1 ("CmiAllocateBlock() failed (Status %lx)\n", Status);
+ return Status;
+ }
+
+ RtlCopyMemory (NewClassNameCell,
+ SrcClassNameCell,
+ NewKeyCell->ClassSize);
+ NewKeyCell->ClassNameOffset = NewClassNameOffset;
+ }
+ }
+ else
+ {
+ NewKeyCell = DstKeyCell;
+ }
+
+ /* Allocate hash table */
+ if (SrcKeyCell->NumberOfSubKeys > 0)
+ {
+ NewHashTableSize = ROUND_UP(SrcKeyCell->NumberOfSubKeys + 1, 4) - 1;
+ Status = CmiAllocateHashTableBlock (DstHive,
+ &NewHashTableCell,
+ &NewHashTableOffset,
+ NewHashTableSize);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1 ("CmiAllocateHashTableBlock() failed (Status %lx)\n", Status);
+ return Status;
+ }
+ NewKeyCell->HashTableOffset = NewHashTableOffset;
+ }
+
+ /* Allocate and copy value list and values */
+ if (SrcKeyCell->NumberOfValues != 0)
+ {
+ PVALUE_LIST_CELL NewValueListCell;
+ PVALUE_LIST_CELL SrcValueListCell;
+ PVALUE_CELL NewValueCell;
+ PVALUE_CELL SrcValueCell;
+ PDATA_CELL SrcValueDataCell;
+ PDATA_CELL NewValueDataCell;
+ BLOCK_OFFSET ValueCellOffset;
+ BLOCK_OFFSET ValueDataCellOffset;
+ ULONG NewValueListCellSize;
+ ULONG NewValueCellSize;
+
+
+ NewValueListCellSize =
+ ROUND_UP(SrcKeyCell->NumberOfValues, 4) * sizeof(BLOCK_OFFSET);
+ Status = CmiAllocateBlock (DstHive,
+ (PVOID)&NewValueListCell,
+ NewValueListCellSize,
+ &NewKeyCell->ValuesOffset);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1 ("CmiAllocateBlock() failed (Status %lx)\n", Status);
+ return Status;
+ }
+
+ RtlZeroMemory (NewValueListCell,
+ NewValueListCellSize);
+
+ /* Copy values */
+ SrcValueListCell = CmiGetBlock (SrcHive, SrcKeyCell->ValuesOffset, NULL);
+ for (i = 0; i < SrcKeyCell->NumberOfValues; i++)
+ {
+ /* Copy value cell */
+ SrcValueCell = CmiGetBlock (SrcHive, SrcValueListCell->Values[i], NULL);
+
+ NewValueCellSize = sizeof(VALUE_CELL) + SrcValueCell->NameSize;
+ Status = CmiAllocateBlock (DstHive,
+ (PVOID*) &NewValueCell,
+ NewValueCellSize,
+ &ValueCellOffset);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1 ("CmiAllocateBlock() failed (Status %lx)\n", Status);
+ return Status;
+ }
+
+ NewValueListCell->Values[i] = ValueCellOffset;
+ RtlCopyMemory (NewValueCell,
+ SrcValueCell,
+ NewValueCellSize);
+
+ /* Copy value data cell */
+ if (SrcValueCell->DataSize > (LONG) sizeof(PVOID))
+ {
+ SrcValueDataCell = CmiGetBlock (SrcHive, SrcValueCell->DataOffset, NULL);
+
+ Status = CmiAllocateBlock (DstHive,
+ (PVOID*) &NewValueDataCell,
+ SrcValueCell->DataSize,
+ &ValueDataCellOffset);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1 ("CmiAllocateBlock() failed (Status %lx)\n", Status);
+ return Status;
+ }
+ RtlCopyMemory (NewValueDataCell,
+ SrcValueDataCell,
+ SrcValueCell->DataSize);
+ NewValueCell->DataOffset = ValueDataCellOffset;
+ }
+ }
+ }
+
+ /* Copy subkeys */
+ if (SrcKeyCell->NumberOfSubKeys > 0)
+ {
+ PHASH_TABLE_CELL SrcHashTableCell;
+ PKEY_CELL SrcSubKeyCell;
+ PKEY_CELL NewSubKeyCell;
+ ULONG NewSubKeyCellSize;
+ BLOCK_OFFSET NewSubKeyCellOffset;
+ PHASH_RECORD SrcHashRecord;
+
+ SrcHashTableCell = CmiGetBlock (SrcHive,
+ SrcKeyCell->HashTableOffset,
+ NULL);
+
+ for (i = 0; i < SrcKeyCell->NumberOfSubKeys; i++)
+ {
+ SrcHashRecord = &SrcHashTableCell->Table[i];
+ SrcSubKeyCell = CmiGetBlock (SrcHive, SrcHashRecord->KeyOffset, NULL);
+
+ /* Allocate and copy key cell */
+ NewSubKeyCellSize = sizeof(KEY_CELL) + SrcSubKeyCell->NameSize;
+ Status = CmiAllocateBlock (DstHive,
+ (PVOID)&NewSubKeyCell,
+ NewSubKeyCellSize,
+ &NewSubKeyCellOffset);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1 ("CmiAllocateBlock() failed (Status %lx)\n", Status);
+ return Status;
+ }
+ if (NewKeyCell == NULL)
+ {
+ DPRINT1 ("Failed to allocate a sub key cell\n");
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ NewHashTableCell->Table[i].KeyOffset = NewSubKeyCellOffset;
+ NewHashTableCell->Table[i].HashValue = SrcHashRecord->HashValue;
+
+ RtlCopyMemory (NewSubKeyCell,
+ SrcSubKeyCell,
+ NewSubKeyCellSize);
+
+ /* Copy class name */
+ if (SrcSubKeyCell->ClassNameOffset != (BLOCK_OFFSET) -1)
+ {
+ PDATA_CELL SrcClassNameCell;
+ PDATA_CELL NewClassNameCell;
+ BLOCK_OFFSET NewClassNameOffset;
+
+ SrcClassNameCell = CmiGetBlock (SrcHive,
+ SrcSubKeyCell->ClassNameOffset,
+ NULL),
+
+ NewSubKeyCell->ClassSize = SrcSubKeyCell->ClassSize;
+ Status = CmiAllocateBlock (DstHive,
+ (PVOID)&NewClassNameCell,
+ NewSubKeyCell->ClassSize,
+ &NewClassNameOffset);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1 ("CmiAllocateBlock() failed (Status %lx)\n", Status);
+ return Status;
+ }
+
+ 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
+CmiSaveTempHive (PREGISTRY_HIVE Hive,
+ HANDLE FileHandle)
+{
+ IO_STATUS_BLOCK IoStatusBlock;
+ LARGE_INTEGER FileOffset;
+ ULONG BlockIndex;
+ PVOID BlockPtr;
+ NTSTATUS Status;
+
+ DPRINT ("CmiSaveTempHive() called\n");
+
+ Hive->HiveHeader->Checksum = CmiCalcChecksum ((PULONG)Hive->HiveHeader);
+
+ /* Write hive block */
+ FileOffset.QuadPart = 0ULL;
+ Status = NtWriteFile (FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ Hive->HiveHeader,
+ sizeof(HIVE_HEADER),
+ &FileOffset,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1 ("NtWriteFile() failed (Status %lx)\n", Status);
+ return Status;
+ }
+
+ DPRINT ("Saving %lu blocks\n", Hive->BlockListSize);
+ for (BlockIndex = 0; BlockIndex < Hive->BlockListSize; BlockIndex++)
+ {
+ BlockPtr = Hive->BlockList[BlockIndex];
+ DPRINT ("BlockPtr %p\n", BlockPtr);
+
+ FileOffset.QuadPart = (ULONGLONG)(BlockIndex + 1) * 4096ULL;
+ DPRINT ("File offset %I64x\n", FileOffset.QuadPart);
+
+ /* Write hive block */
+ Status = NtWriteFile (FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ BlockPtr,
+ REG_BLOCK_SIZE,
+ &FileOffset,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1 ("NtWriteFile() failed (Status %lx)\n", Status);
+ return Status;
+ }
+ }
+
+ Status = NtFlushBuffersFile (FileHandle,
+ &IoStatusBlock);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1 ("NtFlushBuffersFile() failed (Status %lx)\n", Status);
+ }
+
+ DPRINT ("CmiSaveTempHive() done\n");
+
+ return Status;
+}
+
/* EOF */