-/*
- * COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS kernel
- * FILE: ntoskrnl/cm/regfile.c
- * PURPOSE: Registry file manipulation routines
- * UPDATE HISTORY:
-*/
-
-#include <ddk/ntddk.h>
-#include <roscfg.h>
-#include <internal/ob.h>
-#include <limits.h>
-#include <string.h>
-#include <internal/registry.h>
-#include <ntos/minmax.h>
-#include <reactos/bugcodes.h>
-
+/* $Id$
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: ntoskrnl/cm/regfile.c
+ * PURPOSE: Registry file manipulation routines
+ *
+ * PROGRAMMERS: No programmer listed.
+ */
+
+#include <ntoskrnl.h>
#define NDEBUG
#include <internal/debug.h>
/* LOCAL MACROS *************************************************************/
-#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
-#define ROUND_DOWN(N, S) ((N) - ((N) % (S)))
-
#define ABS_VALUE(V) (((V) < 0) ? -(V) : (V))
BOOLEAN CmiDoVerify = FALSE;
VOID
CmiCreateDefaultHiveHeader(PHIVE_HEADER Header)
{
- assert(Header);
+ ASSERT(Header);
RtlZeroMemory(Header, sizeof(HIVE_HEADER));
Header->BlockId = REG_HIVE_ID;
Header->UpdateCounter1 = 0;
Header->UpdateCounter2 = 0;
- Header->DateModified.dwLowDateTime = 0;
- Header->DateModified.dwHighDateTime = 0;
- Header->Unused3 = 1;
- Header->Unused4 = 3;
- Header->Unused5 = 0;
- Header->Unused6 = 1;
+ Header->DateModified.u.LowPart = 0;
+ Header->DateModified.u.HighPart = 0;
+ Header->MajorVersion = 1;
+ Header->MinorVersion = 3;
+ Header->Type = 0;
+ Header->Format = 1;
Header->Unused7 = 1;
- Header->RootKeyCell = 0;
+ Header->RootKeyOffset = (BLOCK_OFFSET)-1;
Header->BlockSize = REG_BLOCK_SIZE;
- Header->Unused6 = 1;
Header->Checksum = 0;
}
VOID
-CmiCreateDefaultBinCell(PHBIN BinCell)
+CmiCreateDefaultBinHeader(PHBIN BinHeader)
{
- assert(BinCell);
- RtlZeroMemory(BinCell, sizeof(HBIN));
- BinCell->BlockId = REG_BIN_ID;
- BinCell->DateModified.dwLowDateTime = 0;
- BinCell->DateModified.dwHighDateTime = 0;
- BinCell->BlockSize = REG_BLOCK_SIZE;
+ ASSERT(BinHeader);
+ RtlZeroMemory(BinHeader, sizeof(HBIN));
+ BinHeader->HeaderId = REG_BIN_ID;
+ BinHeader->DateModified.u.LowPart = 0;
+ BinHeader->DateModified.u.HighPart = 0;
+ BinHeader->BinSize = REG_BLOCK_SIZE;
}
VOID
CmiCreateDefaultRootKeyCell(PKEY_CELL RootKeyCell)
{
- assert(RootKeyCell);
+ ASSERT(RootKeyCell);
RtlZeroMemory(RootKeyCell, sizeof(KEY_CELL));
RootKeyCell->CellSize = -sizeof(KEY_CELL);
RootKeyCell->Id = REG_KEY_CELL_ID;
RootKeyCell->Flags = REG_KEY_ROOT_CELL | REG_KEY_NAME_PACKED;
- NtQuerySystemTime((PTIME) &RootKeyCell->LastWriteTime);
+ KeQuerySystemTime(&RootKeyCell->LastWriteTime);
RootKeyCell->ParentKeyOffset = 0;
RootKeyCell->NumberOfSubKeys = 0;
RootKeyCell->HashTableOffset = -1;
RootKeyCell->NumberOfValues = 0;
- RootKeyCell->ValuesOffset = -1;
+ RootKeyCell->ValueListOffset = -1;
RootKeyCell->SecurityKeyOffset = 0;
RootKeyCell->ClassNameOffset = -1;
RootKeyCell->NameSize = 0;
VOID
-CmiVerifyBinCell(PHBIN BinCell)
+CmiVerifyBinHeader(PHBIN BinHeader)
{
if (CmiDoVerify)
{
- assert(BinCell);
+ ASSERT(BinHeader);
- if (BinCell->BlockId != REG_BIN_ID)
+ if (BinHeader->HeaderId != REG_BIN_ID)
{
- DbgPrint("BlockId is %.08x (should be %.08x)\n",
- BinCell->BlockId, REG_BIN_ID);
- assert(BinCell->BlockId == REG_BIN_ID);
+ DbgPrint("Bin header ID is %.08x (should be %.08x)\n",
+ BinHeader->HeaderId, REG_BIN_ID);
+ ASSERT(BinHeader->HeaderId == REG_BIN_ID);
}
- //BinCell->DateModified.dwLowDateTime
+ //BinHeader->DateModified.dwLowDateTime
- //BinCell->DateModified.dwHighDateTime
+ //BinHeader->DateModified.dwHighDateTime
-
- if (BinCell->BlockSize != REG_BLOCK_SIZE)
+
+ if (BinHeader->BinSize != REG_BLOCK_SIZE)
{
- DbgPrint("BlockSize is %.08x (should be %.08x)\n",
- BinCell->BlockSize, REG_BLOCK_SIZE);
- assert(BinCell->BlockSize == REG_BLOCK_SIZE);
+ DbgPrint("BinSize is %.08x (should be a multiple of %.08x)\n",
+ BinHeader->BinSize, REG_BLOCK_SIZE);
+ ASSERT(BinHeader->BinSize % REG_BLOCK_SIZE == 0);
}
}
if (CmiDoVerify)
{
- assert(KeyCell);
+ ASSERT(KeyCell);
if (KeyCell->CellSize == 0)
{
DbgPrint("CellSize is %d (must not be 0)\n",
KeyCell->CellSize);
- assert(KeyCell->CellSize != 0);
+ ASSERT(KeyCell->CellSize != 0);
}
if (KeyCell->Id != REG_KEY_CELL_ID)
{
DbgPrint("Id is %.08x (should be %.08x)\n",
KeyCell->Id, REG_KEY_CELL_ID);
- assert(KeyCell->Id == REG_KEY_CELL_ID);
+ ASSERT(KeyCell->Id == REG_KEY_CELL_ID);
}
//KeyCell->Flags;
{
DbgPrint("ParentKeyOffset is %d (must not be < 0)\n",
KeyCell->ParentKeyOffset);
- assert(KeyCell->ParentKeyOffset >= 0);
+ ASSERT(KeyCell->ParentKeyOffset >= 0);
}
if (KeyCell->NumberOfSubKeys < 0)
{
DbgPrint("NumberOfSubKeys is %d (must not be < 0)\n",
KeyCell->NumberOfSubKeys);
- assert(KeyCell->NumberOfSubKeys >= 0);
+ ASSERT(KeyCell->NumberOfSubKeys >= 0);
}
//KeyCell->HashTableOffset;
{
DbgPrint("NumberOfValues is %d (must not be < 0)\n",
KeyCell->NumberOfValues);
- assert(KeyCell->NumberOfValues >= 0);
+ ASSERT(KeyCell->NumberOfValues >= 0);
}
//KeyCell->ValuesOffset = -1;
{
DbgPrint("SecurityKeyOffset is %d (must not be < 0)\n",
KeyCell->SecurityKeyOffset);
- assert(KeyCell->SecurityKeyOffset >= 0);
+ ASSERT(KeyCell->SecurityKeyOffset >= 0);
}
//KeyCell->ClassNameOffset = -1;
{
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)));
+ ASSERT(!(RootKeyCell->Flags & (REG_KEY_ROOT_CELL | REG_KEY_NAME_PACKED)));
}
}
if (CmiDoVerify)
{
- assert(ValueCell);
+ ASSERT(ValueCell);
if (ValueCell->CellSize == 0)
{
DbgPrint("CellSize is %d (must not be 0)\n",
ValueCell->CellSize);
- assert(ValueCell->CellSize != 0);
+ ASSERT(ValueCell->CellSize != 0);
}
if (ValueCell->Id != REG_VALUE_CELL_ID)
{
DbgPrint("Id is %.08x (should be %.08x)\n",
ValueCell->Id, REG_VALUE_CELL_ID);
- assert(ValueCell->Id == REG_VALUE_CELL_ID);
+ ASSERT(ValueCell->Id == REG_VALUE_CELL_ID);
}
//ValueCell->NameSize;
{
DbgPrint("CellSize is %d (must not be 0)\n",
ValueListCell->CellSize);
- assert(ValueListCell->CellSize != 0);
+ ASSERT(ValueListCell->CellSize != 0);
}
}
{
DbgPrint("RegistryHive is NULL (must not be NULL)\n",
KeyObject->RegistryHive);
- assert(KeyObject->RegistryHive != NULL);
+ ASSERT(KeyObject->RegistryHive != NULL);
}
if (KeyObject->KeyCell == NULL)
{
DbgPrint("KeyCell is NULL (must not be NULL)\n",
KeyObject->KeyCell);
- assert(KeyObject->KeyCell != NULL);
+ ASSERT(KeyObject->KeyCell != NULL);
}
if (KeyObject->ParentKey == NULL)
{
DbgPrint("ParentKey is NULL (must not be NULL)\n",
KeyObject->ParentKey);
- assert(KeyObject->ParentKey != NULL);
+ ASSERT(KeyObject->ParentKey != NULL);
}
}
DbgPrint("BlockId is %.08x (must be %.08x)\n",
Header->BlockId,
REG_HIVE_ID);
- assert(Header->BlockId == REG_HIVE_ID);
+ ASSERT(Header->BlockId == REG_HIVE_ID);
}
- if (Header->Unused3 != 1)
+ if (Header->MajorVersion != 1)
{
- DbgPrint("Unused3 is %.08x (must be 1)\n",
- Header->Unused3);
- assert(Header->Unused3 == 1);
+ DbgPrint("MajorVersion is %.08x (must be 1)\n",
+ Header->MajorVersion);
+ ASSERT(Header->MajorVersion == 1);
}
- if (Header->Unused4 != 3)
+ if (Header->MinorVersion != 3)
{
- DbgPrint("Unused4 is %.08x (must be 3)\n",
- Header->Unused4);
- assert(Header->Unused4 == 3);
+ DbgPrint("MinorVersion is %.08x (must be 3)\n",
+ Header->MajorVersion);
+ ASSERT(Header->MajorVersion == 3);
}
- if (Header->Unused5 != 0)
+ if (Header->Type != 0)
{
- DbgPrint("Unused5 is %.08x (must be 0)\n",
- Header->Unused5);
- assert(Header->Unused5 == 0);
+ DbgPrint("Type is %.08x (must be 0)\n",
+ Header->Type);
+ ASSERT(Header->Type == 0);
}
- if (Header->Unused6 != 1)
+ if (Header->Format != 1)
{
- DbgPrint("Unused6 is %.08x (must be 1)\n",
- Header->Unused6);
- assert(Header->Unused6 == 1);
+ DbgPrint("Format is %.08x (must be 1)\n",
+ Header->Format);
+ ASSERT(Header->Format == 1);
}
if (Header->Unused7 != 1)
{
DbgPrint("Unused7 is %.08x (must be 1)\n",
Header->Unused7);
- assert(Header->Unused7 == 1);
+ ASSERT(Header->Unused7 == 1);
}
}
PHIVE_HEADER HiveHeader;
PKEY_CELL RootKeyCell;
NTSTATUS Status;
- PHBIN BinCell;
+ PHBIN BinHeader;
PCHAR Buffer;
Buffer = (PCHAR) ExAllocatePool(NonPagedPool, 2 * REG_BLOCK_SIZE);
if (Buffer == NULL)
return STATUS_INSUFFICIENT_RESOURCES;
+ RtlZeroMemory (Buffer,
+ 2 * REG_BLOCK_SIZE);
+
HiveHeader = (PHIVE_HEADER)Buffer;
- BinCell = (PHBIN)((ULONG_PTR)Buffer + REG_BLOCK_SIZE);
+ BinHeader = (PHBIN)((ULONG_PTR)Buffer + REG_BLOCK_SIZE);
RootKeyCell = (PKEY_CELL)((ULONG_PTR)Buffer + REG_BLOCK_SIZE + REG_HBIN_DATA_OFFSET);
FreeCell = (PCELL_HEADER)((ULONG_PTR)Buffer + REG_BLOCK_SIZE + REG_HBIN_DATA_OFFSET + sizeof(KEY_CELL));
CmiCreateDefaultHiveHeader(HiveHeader);
- CmiCreateDefaultBinCell(BinCell);
+ CmiCreateDefaultBinHeader(BinHeader);
CmiCreateDefaultRootKeyCell(RootKeyCell);
/* First block */
- BinCell->BlockOffset = 0;
+ BinHeader->BinOffset = 0;
/* Offset to root key block */
- HiveHeader->RootKeyCell = REG_HBIN_DATA_OFFSET;
+ HiveHeader->RootKeyOffset = REG_HBIN_DATA_OFFSET;
/* The rest of the block is free */
FreeCell->CellSize = REG_BLOCK_SIZE - (REG_HBIN_DATA_OFFSET + sizeof(KEY_CELL));
- Status = NtWriteFile(FileHandle,
+ Status = ZwWriteFile(FileHandle,
NULL,
NULL,
NULL,
ExFreePool(Buffer);
- assertmsg(NT_SUCCESS(Status), ("Status: 0x%X\n", Status));
-
if (!NT_SUCCESS(Status))
{
return(Status);
}
- Status = NtFlushBuffersFile(FileHandle,
+ Status = ZwFlushBuffersFile(FileHandle,
&IoStatusBlock);
return(Status);
/* Try to open the hive file */
InitializeObjectAttributes(&ObjectAttributes,
&RegistryHive->HiveFileName,
- 0,
+ OBJ_CASE_INSENSITIVE,
NULL,
NULL);
- Status = NtCreateFile(&HiveHandle,
+ Status = ZwCreateFile(&HiveHandle,
FILE_READ_DATA | FILE_READ_ATTRIBUTES,
&ObjectAttributes,
&IoStatusBlock,
}
if (!NT_SUCCESS(Status))
{
- DPRINT("NtCreateFile() failed (Status %lx)\n", Status);
+ DPRINT("ZwCreateFile() failed (Status %lx)\n", Status);
return(Status);
}
/* Try to open the log file */
InitializeObjectAttributes(&ObjectAttributes,
&RegistryHive->LogFileName,
- 0,
+ OBJ_CASE_INSENSITIVE,
NULL,
NULL);
- Status = NtCreateFile(&LogHandle,
+ Status = ZwCreateFile(&LogHandle,
FILE_READ_DATA | FILE_READ_ATTRIBUTES,
&ObjectAttributes,
&IoStatusBlock,
}
else if (!NT_SUCCESS(Status))
{
- DPRINT("NtCreateFile() failed (Status %lx)\n", Status);
- NtClose(HiveHandle);
+ DPRINT("ZwCreateFile() failed (Status %lx)\n", Status);
+ ZwClose(HiveHandle);
return(Status);
}
/* Read hive base block */
FileOffset.QuadPart = 0ULL;
- Status = NtReadFile(HiveHandle,
+ Status = ZwReadFile(HiveHandle,
0,
0,
0,
0);
if (!NT_SUCCESS(Status))
{
- DPRINT("NtReadFile() failed (Status %lx)\n", Status);
+ DPRINT("ZwReadFile() failed (Status %lx)\n", Status);
goto ByeBye;
}
{
/* 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;
/* Read log file header */
FileOffset.QuadPart = 0ULL;
- Status = NtReadFile(LogHandle,
+ Status = ZwReadFile(LogHandle,
0,
0,
0,
0);
if (!NT_SUCCESS(Status))
{
- DPRINT("NtReadFile() failed (Status %lx)\n", Status);
+ DPRINT("ZwReadFile() failed (Status %lx)\n", Status);
goto ByeBye;
}
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 */
*/
/* Get file size */
- Status = NtQueryInformationFile(LogHandle,
+ Status = ZwQueryInformationFile(LogHandle,
&IoStatusBlock,
&fsi,
sizeof(fsi),
FileStandardInformation);
if (!NT_SUCCESS(Status))
{
- DPRINT("NtQueryInformationFile() failed (Status %lx)\n", Status);
+ DPRINT("ZwQueryInformationFile() failed (Status %lx)\n", Status);
goto ByeBye;
}
FileSize = fsi.EndOfFile.u.LowPart;
/* Calculate bitmap and block size */
- BitmapSize = ROUND_UP((FileSize / 4096) - 1, sizeof(ULONG) * 8) / 8;
+ BitmapSize = ROUND_UP((FileSize / REG_BLOCK_SIZE) - 1, sizeof(ULONG) * 8) / 8;
BufferSize = sizeof(HIVE_HEADER) +
sizeof(ULONG) +
BitmapSize;
- BufferSize = ROUND_UP(BufferSize, 4096);
+ BufferSize = ROUND_UP(BufferSize, REG_BLOCK_SIZE);
/* Reallocate log header block */
ExFreePool(LogHeader);
/* Read log file header */
FileOffset.QuadPart = 0ULL;
- Status = NtReadFile(LogHandle,
+ Status = ZwReadFile(LogHandle,
0,
0,
0,
0);
if (!NT_SUCCESS(Status))
{
- DPRINT("NtReadFile() failed (Status %lx)\n", Status);
+ DPRINT("ZwReadFile() failed (Status %lx)\n", Status);
goto ByeBye;
}
/* Initialize bitmap */
RtlInitializeBitMap(&BlockBitMap,
- (PVOID)((ULONG)LogHeader + 4096 + sizeof(ULONG)),
+ (PVOID)((ULONG_PTR)LogHeader + REG_BLOCK_SIZE + sizeof(ULONG)),
BitmapSize * 8);
/* FIXME: Update dirty blocks */
ExFreePool(LogHeader);
if (LogHandle != INVALID_HANDLE_VALUE)
- NtClose(LogHandle);
+ ZwClose(LogHandle);
- NtClose(HiveHandle);
+ ZwClose(HiveHandle);
return(Status);
}
{
Bin = (PHBIN)((ULONG_PTR)ChunkPtr + BlockOffset);
- if (Bin->BlockId != REG_BIN_ID)
+ if (Bin->HeaderId != REG_BIN_ID)
{
- DPRINT1 ("Bad BlockId %x, offset %x\n", Bin->BlockId, BlockOffset);
+ DPRINT1 ("Bad bin header id %x, offset %x\n", Bin->HeaderId, BlockOffset);
return STATUS_REGISTRY_CORRUPT;
}
- assertmsg((Bin->BlockSize % 4096) == 0,
- ("BlockSize (0x%.08x) must be multiple of 4K\n",
- Bin->BlockSize));
+ ASSERTMSG("Bin size must be multiple of 4K\n",
+ (Bin->BinSize % REG_BLOCK_SIZE) == 0);
/* Allocate the hive block */
- Hive->BlockList[BlockIndex] = ExAllocatePool (PagedPool,
- Bin->BlockSize);
- if (Hive->BlockList[BlockIndex] == NULL)
+ Hive->BlockList[BlockIndex].Bin = ExAllocatePool (PagedPool,
+ Bin->BinSize);
+ if (Hive->BlockList[BlockIndex].Bin == NULL)
{
DPRINT1 ("ExAllocatePool() failed\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
+ Hive->BlockList[BlockIndex].Block = (PVOID)Hive->BlockList[BlockIndex].Bin;
/* Import the Bin */
- RtlCopyMemory (Hive->BlockList[BlockIndex],
+ RtlCopyMemory (Hive->BlockList[BlockIndex].Bin,
Bin,
- Bin->BlockSize);
+ Bin->BinSize);
- if (Bin->BlockSize > 4096)
+ if (Bin->BinSize > REG_BLOCK_SIZE)
{
- for (j = 1; j < Bin->BlockSize / 4096; j++)
+ for (j = 1; j < Bin->BinSize / REG_BLOCK_SIZE; j++)
{
- Hive->BlockList[BlockIndex + j] = Hive->BlockList[BlockIndex];
+ Hive->BlockList[BlockIndex + j].Bin = Hive->BlockList[BlockIndex].Bin;
+ Hive->BlockList[BlockIndex + j].Block =
+ (PVOID)((ULONG_PTR)Hive->BlockList[BlockIndex].Bin + (j * REG_BLOCK_SIZE));
}
}
- BlockIndex += Bin->BlockSize / 4096;
- BlockOffset += Bin->BlockSize;
+ BlockIndex += Bin->BinSize / REG_BLOCK_SIZE;
+ BlockOffset += Bin->BinSize;
}
return STATUS_SUCCESS;
Bin = NULL;
for (i = 0; i < Hive->BlockListSize; i++)
{
- if (Hive->BlockList[i] == NULL)
+ if (Hive->BlockList[i].Bin == NULL)
continue;
- if (Hive->BlockList[i] != Bin)
+ if (Hive->BlockList[i].Bin != Bin)
{
- Bin = Hive->BlockList[i];
- ExFreePool (Hive->BlockList[i]);
+ Bin = Hive->BlockList[i].Bin;
+ ExFreePool (Hive->BlockList[i].Bin);
}
- Hive->BlockList[i] = NULL;
+ Hive->BlockList[i].Bin = NULL;
+ Hive->BlockList[i].Block = NULL;
}
}
BlockIndex = 0;
while (BlockIndex < Hive->BlockListSize)
{
- Bin = Hive->BlockList[BlockIndex];
+ Bin = Hive->BlockList[BlockIndex].Bin;
/* Search free blocks and add to list */
FreeOffset = REG_HBIN_DATA_OFFSET;
- while (FreeOffset < Bin->BlockSize)
+ while (FreeOffset < Bin->BinSize)
{
FreeBlock = (PCELL_HEADER) ((ULONG_PTR) Bin + FreeOffset);
if (FreeBlock->CellSize > 0)
{
Status = CmiAddFree(Hive,
FreeBlock,
- Bin->BlockOffset + FreeOffset,
+ Bin->BinOffset + FreeOffset,
FALSE);
if (!NT_SUCCESS(Status))
}
}
- BlockIndex += Bin->BlockSize / 4096;
- BlockOffset += Bin->BlockSize;
+ BlockIndex += Bin->BinSize / REG_BLOCK_SIZE;
+ BlockOffset += Bin->BinSize;
}
return STATUS_SUCCESS;
static NTSTATUS
-CmiInitNonVolatileRegistryHive(PREGISTRY_HIVE RegistryHive,
- PWSTR Filename,
- BOOLEAN CreateNew)
+CmiInitNonVolatileRegistryHive (PREGISTRY_HIVE RegistryHive,
+ PWSTR Filename)
{
OBJECT_ATTRIBUTES ObjectAttributes;
ULONG CreateDisposition;
IO_STATUS_BLOCK IoSB;
HANDLE FileHandle;
- HANDLE SectionHandle;
+ PSECTION_OBJECT SectionObject;
PUCHAR ViewBase;
ULONG ViewSize;
NTSTATUS Status;
- DPRINT("CmiInitNonVolatileRegistryHive(%p, %S, %d) called\n",
- RegistryHive, Filename, CreateNew);
+ DPRINT("CmiInitNonVolatileRegistryHive(%p, %S) called\n",
+ RegistryHive, Filename);
/* Duplicate Filename */
Status = RtlCreateUnicodeString(&RegistryHive->HiveFileName,
- Filename);
+ Filename);
if (!NT_SUCCESS(Status))
{
DPRINT("RtlCreateUnicodeString() failed (Status %lx)\n", Status);
/* Create log file name */
RegistryHive->LogFileName.Length = (wcslen(Filename) + 4) * sizeof(WCHAR);
RegistryHive->LogFileName.MaximumLength = RegistryHive->LogFileName.Length + sizeof(WCHAR);
- RegistryHive->LogFileName.Buffer = ExAllocatePool(NonPagedPool,
- RegistryHive->LogFileName.MaximumLength);
+ RegistryHive->LogFileName.Buffer = ExAllocatePoolWithTag(PagedPool,
+ RegistryHive->LogFileName.MaximumLength,
+ TAG('U', 'S', 'T', 'R'));
if (RegistryHive->LogFileName.Buffer == NULL)
{
RtlFreeUnicodeString(&RegistryHive->HiveFileName);
InitializeObjectAttributes(&ObjectAttributes,
&RegistryHive->HiveFileName,
- 0,
+ OBJ_CASE_INSENSITIVE,
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,
+ Status = ZwCreateFile(&FileHandle,
FILE_ALL_ACCESS,
&ObjectAttributes,
&IoSB,
{
RtlFreeUnicodeString(&RegistryHive->HiveFileName);
RtlFreeUnicodeString(&RegistryHive->LogFileName);
- DPRINT("NtCreateFile() failed (Status %lx)\n", Status);
+ DPRINT("ZwCreateFile() failed (Status %lx)\n", Status);
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);
if (!NT_SUCCESS(Status))
{
DPRINT("CmiCreateNewRegFile() failed (Status %lx)\n", Status);
- NtClose(FileHandle);
+ ZwClose(FileHandle);
RtlFreeUnicodeString(&RegistryHive->HiveFileName);
RtlFreeUnicodeString(&RegistryHive->LogFileName);
return(Status);
}
/* Create the hive section */
- Status = NtCreateSection(&SectionHandle,
+ Status = MmCreateSection(&SectionObject,
SECTION_ALL_ACCESS,
NULL,
NULL,
PAGE_READWRITE,
SEC_COMMIT,
- FileHandle);
- NtClose(FileHandle);
+ FileHandle,
+ NULL);
if (!NT_SUCCESS(Status))
{
- DPRINT1("NtCreateSection() failed (Status %lx)\n", Status);
+ DPRINT1("MmCreateSection() failed (Status %lx)\n", Status);
RtlFreeUnicodeString(&RegistryHive->HiveFileName);
RtlFreeUnicodeString(&RegistryHive->LogFileName);
return(Status);
/* Map the hive file */
ViewBase = NULL;
ViewSize = 0;
- Status = NtMapViewOfSection(SectionHandle,
- NtCurrentProcess(),
+ Status = MmMapViewOfSection(SectionObject,
+ PsGetCurrentProcess(),
(PVOID*)&ViewBase,
0,
ViewSize,
PAGE_READWRITE);
if (!NT_SUCCESS(Status))
{
- DPRINT1("MmMapViewInSystemSpace() failed (Status %lx)\n", Status);
- NtClose(SectionHandle);
+ 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);
ViewBase,
sizeof(HIVE_HEADER));
RegistryHive->FileSize = ViewSize;
- RegistryHive->BlockListSize = (RegistryHive->FileSize / 4096) - 1;
+ RegistryHive->BlockListSize = (RegistryHive->FileSize / REG_BLOCK_SIZE) - 1;
RegistryHive->UpdateCounter = RegistryHive->HiveHeader->UpdateCounter1;
/* Allocate hive block list */
RegistryHive->BlockList = ExAllocatePool(NonPagedPool,
- sizeof(PHBIN *) * RegistryHive->BlockListSize);
+ RegistryHive->BlockListSize * sizeof(BLOCK_LIST_ENTRY));
if (RegistryHive->BlockList == NULL)
{
DPRINT1("Failed to allocate the hive block list\n");
- NtUnmapViewOfSection(NtCurrentProcess(),
+ MmUnmapViewOfSection(PsGetCurrentProcess(),
ViewBase);
- NtClose(SectionHandle);
+ ObDereferenceObject(SectionObject);
RtlFreeUnicodeString(&RegistryHive->HiveFileName);
RtlFreeUnicodeString(&RegistryHive->LogFileName);
+ ZwClose(FileHandle);
return STATUS_INSUFFICIENT_RESOURCES;
}
+ RtlZeroMemory (RegistryHive->BlockList,
+ RegistryHive->BlockListSize * sizeof(BLOCK_LIST_ENTRY));
/* Import the hive bins */
Status = CmiImportHiveBins (RegistryHive,
- ViewBase + 4096);
+ ViewBase + REG_BLOCK_SIZE);
if (!NT_SUCCESS(Status))
{
ExFreePool(RegistryHive->BlockList);
- NtUnmapViewOfSection(NtCurrentProcess(),
+ MmUnmapViewOfSection(PsGetCurrentProcess(),
ViewBase);
- NtClose(SectionHandle);
+ ObDereferenceObject(SectionObject);
RtlFreeUnicodeString(&RegistryHive->HiveFileName);
RtlFreeUnicodeString(&RegistryHive->LogFileName);
+ ZwClose(FileHandle);
return Status;
}
/* Unmap and dereference the hive section */
- NtUnmapViewOfSection(NtCurrentProcess(),
- ViewBase);
- NtClose(SectionHandle);
+ MmUnmapViewOfSection(PsGetCurrentProcess(),
+ ViewBase);
+ ObDereferenceObject(SectionObject);
+
+ /* Close the hive file */
+ ZwClose(FileHandle);
/* Initialize the free cell list */
Status = CmiCreateHiveFreeCellList (RegistryHive);
return Status;
}
- DPRINT("CmiInitNonVolatileRegistryHive(%p, %S, %d) - Finished.\n",
- RegistryHive, Filename, CreateNew);
+ DPRINT("CmiInitNonVolatileRegistryHive(%p, %S) - Finished.\n",
+ RegistryHive, Filename);
- return(STATUS_SUCCESS);
+ return STATUS_SUCCESS;
}
-static NTSTATUS
-CmiInitVolatileRegistryHive(PREGISTRY_HIVE RegistryHive)
+NTSTATUS
+CmiCreateVolatileHive(PREGISTRY_HIVE *RegistryHive)
{
PKEY_CELL RootKeyCell;
+ PREGISTRY_HIVE Hive;
+
+ *RegistryHive = NULL;
+
+ Hive = ExAllocatePool (NonPagedPool,
+ sizeof(REGISTRY_HIVE));
+ if (Hive == NULL)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ RtlZeroMemory (Hive,
+ sizeof(REGISTRY_HIVE));
- RegistryHive->Flags |= (HIVE_VOLATILE | HIVE_POINTER);
+ DPRINT("Hive 0x%p\n", Hive);
- CmiCreateDefaultHiveHeader(RegistryHive->HiveHeader);
+ Hive->HiveHeader = (PHIVE_HEADER)ExAllocatePool (NonPagedPool,
+ sizeof(HIVE_HEADER));
+ if (Hive->HiveHeader == NULL)
+ {
+ ExFreePool (Hive);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ RtlZeroMemory (Hive->HiveHeader,
+ sizeof(HIVE_HEADER));
+
+ Hive->Flags = (HIVE_NO_FILE | HIVE_POINTER);
- RootKeyCell = (PKEY_CELL) ExAllocatePool(NonPagedPool, sizeof(KEY_CELL));
+ CmiCreateDefaultHiveHeader (Hive->HiveHeader);
+ RootKeyCell = (PKEY_CELL)ExAllocatePool (NonPagedPool,
+ sizeof(KEY_CELL));
if (RootKeyCell == NULL)
- return STATUS_INSUFFICIENT_RESOURCES;
+ {
+ ExFreePool(Hive->HiveHeader);
+ ExFreePool(Hive);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
- CmiCreateDefaultRootKeyCell(RootKeyCell);
+ CmiCreateDefaultRootKeyCell (RootKeyCell);
+ Hive->HiveHeader->RootKeyOffset = (BLOCK_OFFSET)RootKeyCell;
+
+ /* Acquire hive list lock exclusively */
+ KeEnterCriticalRegion();
+ ExAcquireResourceExclusiveLite (&CmiRegistryLock, TRUE);
+
+ /* Add the new hive to the hive list */
+ InsertTailList (&CmiHiveListHead,
+ &Hive->HiveList);
+
+ /* Release hive list lock */
+ ExReleaseResourceLite (&CmiRegistryLock);
+ KeLeaveCriticalRegion();
+
+ VERIFY_REGISTRY_HIVE (Hive);
- RegistryHive->HiveHeader->RootKeyCell = (BLOCK_OFFSET) RootKeyCell;
+ *RegistryHive = Hive;
return STATUS_SUCCESS;
}
NTSTATUS
-CmiCreateRegistryHive(PWSTR Filename,
- PREGISTRY_HIVE *RegistryHive,
- BOOLEAN CreateNew)
+CmiCreateTempHive(PREGISTRY_HIVE *RegistryHive)
{
+ PHBIN BinHeader;
+ 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 0x%p\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 0x%p\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(PBLOCK_LIST_ENTRY));
+ 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].Bin = ExAllocatePool (NonPagedPool,
+ REG_BLOCK_SIZE);
+ if (Hive->BlockList[0].Bin == NULL)
{
- Status = CmiInitVolatileRegistryHive(Hive);
+ DPRINT1 ("Failed to allocate first bin\n");
+ ExFreePool(Hive->BlockList);
+ ExFreePool(Hive->HiveHeader);
+ ExFreePool(Hive);
+ return STATUS_INSUFFICIENT_RESOURCES;
}
+ Hive->BlockList[0].Block = (PVOID)Hive->BlockList[0].Bin;
- if (!NT_SUCCESS(Status))
+ Hive->FileSize = 2* REG_BLOCK_SIZE;
+ Hive->BlockListSize = 1;
+ Hive->UpdateCounter = Hive->HiveHeader->UpdateCounter1;
+
+
+ BinHeader = Hive->BlockList[0].Bin;
+ FreeCell = (PCELL_HEADER)((ULONG_PTR)BinHeader + REG_HBIN_DATA_OFFSET);
+
+ CmiCreateDefaultBinHeader (BinHeader);
+
+ /* First block */
+ BinHeader->BinOffset = 0;
+
+ /* Offset to root key block */
+ Hive->HiveHeader->RootKeyOffset = (BLOCK_OFFSET)-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].Bin == NULL)
{
+ DPRINT1 ("CmiCreateHiveFreeCellList() failed (Status %lx)\n", Status);
+ ExFreePool(Hive->BlockList[0].Bin);
+ ExFreePool(Hive->BlockList);
ExFreePool(Hive->HiveHeader);
ExFreePool(Hive);
- return(Status);
+ return Status;
}
- ExInitializeResourceLite(&Hive->HiveResource);
-
/* Acquire hive list lock exclusively */
- ExAcquireResourceExclusiveLite(&CmiHiveListLock, TRUE);
+ KeEnterCriticalRegion();
+ ExAcquireResourceExclusiveLite(&CmiRegistryLock, TRUE);
/* Add the new hive to the hive list */
- InsertTailList(&CmiHiveListHead, &Hive->HiveList);
+ InsertTailList (&CmiHiveListHead,
+ &Hive->HiveList);
/* Release hive list lock */
- ExReleaseResourceLite(&CmiHiveListLock);
+ ExReleaseResourceLite(&CmiRegistryLock);
+ KeLeaveCriticalRegion();
- 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 0x%p\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;
+ }
+
+ RtlZeroMemory (Hive->HiveHeader,
+ sizeof(HIVE_HEADER));
+
+ Status = CmiInitNonVolatileRegistryHive (Hive,
+ FileName->Buffer);
+ if (!NT_SUCCESS (Status))
+ {
+ DPRINT1 ("CmiInitNonVolatileRegistryHive() failed (Status %lx)\n", Status);
+ ExFreePool (Hive->HiveHeader);
+ ExFreePool (Hive);
+ return Status;
+ }
+
+ /* Add the new hive to the hive list */
+ InsertTailList (&CmiHiveListHead,
+ &Hive->HiveList);
+
+ 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)
{
- /* Acquire hive list lock exclusively */
- ExAcquireResourceExclusiveLite(&CmiHiveListLock, TRUE);
+ if (RegistryHive->Flags & HIVE_POINTER)
+ return STATUS_UNSUCCESSFUL;
/* Remove hive from hive list */
- RemoveEntryList(&RegistryHive->HiveList);
+ RemoveEntryList (&RegistryHive->HiveList);
- /* Release hive list lock */
- 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 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;
}
PUCHAR Buffer;
PUCHAR Ptr;
ULONG BlockIndex;
+ ULONG LastIndex;
PVOID BlockPtr;
NTSTATUS Status;
BufferSize = sizeof(HIVE_HEADER) +
sizeof(ULONG) +
BitmapSize;
- BufferSize = ROUND_UP(BufferSize, 4096);
+ BufferSize = ROUND_UP(BufferSize, REG_BLOCK_SIZE);
DPRINT("Bitmap size %lu buffer size: %lu\n", BitmapSize, BufferSize);
- Buffer = (PUCHAR)ExAllocatePool(NonPagedPool, BufferSize);
+ Buffer = (PUCHAR)ExAllocatePool(NonPagedPool,
+ BufferSize);
if (Buffer == NULL)
{
DPRINT("ExAllocatePool() failed\n");
return(STATUS_INSUFFICIENT_RESOURCES);
}
+ RtlZeroMemory (Buffer,
+ BufferSize);
/* Open log file for writing */
InitializeObjectAttributes(&ObjectAttributes,
&RegistryHive->LogFileName,
- 0,
+ OBJ_CASE_INSENSITIVE,
NULL,
NULL);
- Status = NtCreateFile(&FileHandle,
+ Status = ZwCreateFile(&FileHandle,
FILE_ALL_ACCESS,
&ObjectAttributes,
&IoStatusBlock,
0);
if (!NT_SUCCESS(Status))
{
- DPRINT("NtCreateFile() failed (Status %lx)\n", Status);
+ DPRINT("ZwCreateFile() failed (Status %lx)\n", Status);
ExFreePool(Buffer);
return(Status);
}
BitmapSize);
/* Write hive block and block bitmap */
- FileOffset.QuadPart = 0ULL;
- Status = NtWriteFile(FileHandle,
+ FileOffset.QuadPart = (ULONGLONG)0;
+ Status = ZwWriteFile(FileHandle,
NULL,
NULL,
NULL,
NULL);
if (!NT_SUCCESS(Status))
{
- DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
- NtClose(FileHandle);
+ DPRINT("ZwWriteFile() failed (Status %lx)\n", Status);
+ ZwClose(FileHandle);
ExFreePool(Buffer);
return(Status);
}
/* Write dirty blocks */
FileOffset.QuadPart = (ULONGLONG)BufferSize;
BlockIndex = 0;
- while (TRUE)
+ while (BlockIndex < RegistryHive->BlockListSize)
{
+ LastIndex = BlockIndex;
BlockIndex = RtlFindSetBits(&RegistryHive->DirtyBitMap,
1,
BlockIndex);
- if ((BlockIndex == (ULONG)-1) ||
- (BlockIndex >= RegistryHive->BlockListSize))
+ if (BlockIndex == (ULONG)-1 || BlockIndex < LastIndex)
{
DPRINT("No more set bits\n");
Status = STATUS_SUCCESS;
DPRINT("Block %lu is dirty\n", BlockIndex);
- BlockPtr = RegistryHive->BlockList[BlockIndex];
+ BlockPtr = RegistryHive->BlockList[BlockIndex].Block;
DPRINT("BlockPtr %p\n", BlockPtr);
DPRINT("File offset %I64x\n", FileOffset.QuadPart);
/* Write hive block */
- Status = NtWriteFile(FileHandle,
+ Status = ZwWriteFile(FileHandle,
NULL,
NULL,
NULL,
NULL);
if (!NT_SUCCESS(Status))
{
- DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
- NtClose(FileHandle);
+ DPRINT1("ZwWriteFile() failed (Status %lx)\n", Status);
+ ZwClose(FileHandle);
return(Status);
}
BlockIndex++;
- FileOffset.QuadPart += 4096ULL;
+ FileOffset.QuadPart += (ULONGLONG)REG_BLOCK_SIZE;
}
/* Truncate log file */
EndOfFileInfo.EndOfFile.QuadPart = FileOffset.QuadPart;
- Status = NtSetInformationFile(FileHandle,
+ Status = ZwSetInformationFile(FileHandle,
&IoStatusBlock,
&EndOfFileInfo,
sizeof(FILE_END_OF_FILE_INFORMATION),
FileEndOfFileInformation);
if (!NT_SUCCESS(Status))
{
- DPRINT("NtSetInformationFile() failed (Status %lx)\n", Status);
- NtClose(FileHandle);
+ DPRINT("ZwSetInformationFile() failed (Status %lx)\n", Status);
+ ZwClose(FileHandle);
return(Status);
}
FileAllocationInfo.AllocationSize.QuadPart = FileOffset.QuadPart;
- Status = NtSetInformationFile(FileHandle,
+ Status = ZwSetInformationFile(FileHandle,
&IoStatusBlock,
&FileAllocationInfo,
sizeof(FILE_ALLOCATION_INFORMATION),
FileAllocationInformation);
if (!NT_SUCCESS(Status))
{
- DPRINT("NtSetInformationFile() failed (Status %lx)\n", Status);
- NtClose(FileHandle);
+ DPRINT("ZwSetInformationFile() failed (Status %lx)\n", Status);
+ ZwClose(FileHandle);
return(Status);
}
/* Flush the log file */
- Status = NtFlushBuffersFile(FileHandle,
+ Status = ZwFlushBuffersFile(FileHandle,
&IoStatusBlock);
if (!NT_SUCCESS(Status))
{
- DPRINT("NtFlushBuffersFile() failed (Status %lx)\n", Status);
+ DPRINT("ZwFlushBuffersFile() failed (Status %lx)\n", Status);
}
- NtClose(FileHandle);
+ ZwClose(FileHandle);
return(Status);
}
BufferSize = sizeof(HIVE_HEADER) +
sizeof(ULONG) +
BitmapSize;
- BufferSize = ROUND_UP(BufferSize, 4096);
+ BufferSize = ROUND_UP(BufferSize, REG_BLOCK_SIZE);
DPRINT("Bitmap size %lu buffer size: %lu\n", BitmapSize, BufferSize);
/* Open log file for writing */
InitializeObjectAttributes(&ObjectAttributes,
&RegistryHive->LogFileName,
- 0,
+ OBJ_CASE_INSENSITIVE,
NULL,
NULL);
- Status = NtCreateFile(&FileHandle,
+ Status = ZwCreateFile(&FileHandle,
FILE_ALL_ACCESS,
&ObjectAttributes,
&IoStatusBlock,
0);
if (!NT_SUCCESS(Status))
{
- DPRINT("NtCreateFile() failed (Status %lx)\n", Status);
+ DPRINT("ZwCreateFile() failed (Status %lx)\n", Status);
ExFreePool(Buffer);
return(Status);
}
BitmapSize);
/* Write hive block and block bitmap */
- FileOffset.QuadPart = 0ULL;
- Status = NtWriteFile(FileHandle,
+ FileOffset.QuadPart = (ULONGLONG)0;
+ Status = ZwWriteFile(FileHandle,
NULL,
NULL,
NULL,
NULL);
if (!NT_SUCCESS(Status))
{
- DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
- NtClose(FileHandle);
+ DPRINT("ZwWriteFile() failed (Status %lx)\n", Status);
+ ZwClose(FileHandle);
ExFreePool(Buffer);
return(Status);
}
ExFreePool(Buffer);
/* Flush the log file */
- Status = NtFlushBuffersFile(FileHandle,
+ Status = ZwFlushBuffersFile(FileHandle,
&IoStatusBlock);
if (!NT_SUCCESS(Status))
{
- DPRINT("NtFlushBuffersFile() failed (Status %lx)\n", Status);
+ DPRINT("ZwFlushBuffersFile() failed (Status %lx)\n", Status);
}
- NtClose(FileHandle);
+ ZwClose(FileHandle);
return(Status);
}
BufferSize = sizeof(HIVE_HEADER) +
sizeof(ULONG) +
BitmapSize;
- BufferSize = ROUND_UP(BufferSize, 4096);
+ BufferSize = ROUND_UP(BufferSize, REG_BLOCK_SIZE);
DPRINT("Bitmap size %lu buffer size: %lu\n", BitmapSize, BufferSize);
/* Open log file for writing */
InitializeObjectAttributes(&ObjectAttributes,
&RegistryHive->LogFileName,
- 0,
+ OBJ_CASE_INSENSITIVE,
NULL,
NULL);
- Status = NtCreateFile(&FileHandle,
+ Status = ZwCreateFile(&FileHandle,
FILE_ALL_ACCESS,
&ObjectAttributes,
&IoStatusBlock,
0);
if (!NT_SUCCESS(Status))
{
- DPRINT("NtCreateFile() failed (Status %lx)\n", Status);
+ DPRINT("ZwCreateFile() failed (Status %lx)\n", Status);
return(Status);
}
/* Truncate log file */
EndOfFileInfo.EndOfFile.QuadPart = (ULONGLONG)BufferSize;
- Status = NtSetInformationFile(FileHandle,
+ Status = ZwSetInformationFile(FileHandle,
&IoStatusBlock,
&EndOfFileInfo,
sizeof(FILE_END_OF_FILE_INFORMATION),
FileEndOfFileInformation);
if (!NT_SUCCESS(Status))
{
- DPRINT("NtSetInformationFile() failed (Status %lx)\n", Status);
- NtClose(FileHandle);
+ DPRINT("ZwSetInformationFile() failed (Status %lx)\n", Status);
+ ZwClose(FileHandle);
return(Status);
}
FileAllocationInfo.AllocationSize.QuadPart = (ULONGLONG)BufferSize;
- Status = NtSetInformationFile(FileHandle,
+ Status = ZwSetInformationFile(FileHandle,
&IoStatusBlock,
&FileAllocationInfo,
sizeof(FILE_ALLOCATION_INFORMATION),
if (!NT_SUCCESS(Status))
{
DPRINT("NtSetInformationFile() failed (Status %lx)\n", Status);
- NtClose(FileHandle);
+ ZwClose(FileHandle);
return(Status);
}
/* Flush the log file */
- Status = NtFlushBuffersFile(FileHandle,
+ Status = ZwFlushBuffersFile(FileHandle,
&IoStatusBlock);
if (!NT_SUCCESS(Status))
{
- DPRINT("NtFlushBuffersFile() failed (Status %lx)\n", Status);
+ DPRINT("ZwFlushBuffersFile() failed (Status %lx)\n", Status);
}
- NtClose(FileHandle);
+ ZwClose(FileHandle);
return(Status);
}
HANDLE FileHandle;
LARGE_INTEGER FileOffset;
ULONG BlockIndex;
+ ULONG LastIndex;
PVOID BlockPtr;
NTSTATUS Status;
/* Open hive for writing */
InitializeObjectAttributes(&ObjectAttributes,
&RegistryHive->HiveFileName,
- 0,
+ OBJ_CASE_INSENSITIVE,
NULL,
NULL);
- Status = NtCreateFile(&FileHandle,
+ Status = ZwCreateFile(&FileHandle,
FILE_ALL_ACCESS,
&ObjectAttributes,
&IoStatusBlock,
0);
if (!NT_SUCCESS(Status))
{
- DPRINT("NtCreateFile() failed (Status %lx)\n", Status);
+ DPRINT("ZwCreateFile() failed (Status %lx)\n", Status);
return(Status);
}
RegistryHive->HiveHeader->Checksum = CmiCalcChecksum((PULONG)RegistryHive->HiveHeader);
/* Write hive block */
- FileOffset.QuadPart = 0ULL;
- Status = NtWriteFile(FileHandle,
+ FileOffset.QuadPart = (ULONGLONG)0;
+ Status = ZwWriteFile(FileHandle,
NULL,
NULL,
NULL,
NULL);
if (!NT_SUCCESS(Status))
{
- DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
- NtClose(FileHandle);
+ DPRINT("ZwWriteFile() failed (Status %lx)\n", Status);
+ ZwClose(FileHandle);
return(Status);
}
BlockIndex = 0;
- while (TRUE)
+ while (BlockIndex < RegistryHive->BlockListSize)
{
+ LastIndex = BlockIndex;
BlockIndex = RtlFindSetBits(&RegistryHive->DirtyBitMap,
1,
BlockIndex);
- if ((BlockIndex == (ULONG)-1) ||
- (BlockIndex >= RegistryHive->BlockListSize))
+ if (BlockIndex == (ULONG)-1 || BlockIndex < LastIndex)
{
DPRINT("No more set bits\n");
Status = STATUS_SUCCESS;
DPRINT("Block %lu is dirty\n", BlockIndex);
- BlockPtr = RegistryHive->BlockList[BlockIndex];
- DPRINT("BlockPtr %p\n", BlockPtr);
+ BlockPtr = RegistryHive->BlockList[BlockIndex].Block;
+ DPRINT(" BlockPtr %p\n", BlockPtr);
- FileOffset.QuadPart = (ULONGLONG)(BlockIndex + 1) * 4096ULL;
- DPRINT("File offset %I64x\n", FileOffset.QuadPart);
+ FileOffset.QuadPart = (ULONGLONG)(BlockIndex + 1) * (ULONGLONG)REG_BLOCK_SIZE;
+ DPRINT(" File offset %I64x\n", FileOffset.QuadPart);
/* Write hive block */
- Status = NtWriteFile(FileHandle,
+ Status = ZwWriteFile(FileHandle,
NULL,
NULL,
NULL,
NULL);
if (!NT_SUCCESS(Status))
{
- DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
- NtClose(FileHandle);
+ DPRINT("ZwWriteFile() failed (Status %lx)\n", Status);
+ ZwClose(FileHandle);
return(Status);
}
BlockIndex++;
}
- Status = NtFlushBuffersFile(FileHandle,
+ Status = ZwFlushBuffersFile(FileHandle,
&IoStatusBlock);
if (!NT_SUCCESS(Status))
{
- DPRINT("NtFlushBuffersFile() failed (Status %lx)\n", Status);
+ DPRINT("ZwFlushBuffersFile() failed (Status %lx)\n", Status);
}
- NtClose(FileHandle);
+ ZwClose(FileHandle);
return(Status);
}
InitializeObjectAttributes(&ObjectAttributes,
&RegistryHive->HiveFileName,
- 0,
+ OBJ_CASE_INSENSITIVE,
NULL,
NULL);
- Status = NtCreateFile(&FileHandle,
+ Status = ZwCreateFile(&FileHandle,
FILE_ALL_ACCESS,
&ObjectAttributes,
&IoStatusBlock,
0);
if (!NT_SUCCESS(Status))
{
- DPRINT("NtCreateFile() failed (Status %lx)\n", Status);
+ DPRINT("ZwCreateFile() failed (Status %lx)\n", Status);
return(Status);
}
RegistryHive->HiveHeader->Checksum = CmiCalcChecksum((PULONG)RegistryHive->HiveHeader);
/* Write hive block */
- FileOffset.QuadPart = 0ULL;
- Status = NtWriteFile(FileHandle,
+ FileOffset.QuadPart = (ULONGLONG)0;
+ Status = ZwWriteFile(FileHandle,
NULL,
NULL,
NULL,
NULL);
if (!NT_SUCCESS(Status))
{
- DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
- NtClose(FileHandle);
+ DPRINT("ZwWriteFile() failed (Status %lx)\n", Status);
+ ZwClose(FileHandle);
return(Status);
}
- Status = NtFlushBuffersFile(FileHandle,
+ Status = ZwFlushBuffersFile(FileHandle,
&IoStatusBlock);
if (!NT_SUCCESS(Status))
{
- DPRINT("NtFlushBuffersFile() failed (Status %lx)\n", Status);
+ DPRINT("ZwFlushBuffersFile() failed (Status %lx)\n", Status);
}
- NtClose(FileHandle);
+ ZwClose(FileHandle);
return(Status);
}
&RegistryHive->LogFileName);
/* Update hive header modification time */
- NtQuerySystemTime((PTIME)&RegistryHive->HiveHeader->DateModified);
+ KeQuerySystemTime(&RegistryHive->HiveHeader->DateModified);
/* Start log update */
Status = CmiStartLogUpdate(RegistryHive);
ULONG
-CmiGetMaxNameLength(PREGISTRY_HIVE RegistryHive,
- PKEY_CELL KeyCell)
+CmiGetNumberOfSubKeys(PKEY_OBJECT KeyObject)
+{
+ PKEY_OBJECT CurKey;
+ PKEY_CELL KeyCell;
+ ULONG SubKeyCount;
+ ULONG i;
+
+ VERIFY_KEY_OBJECT(KeyObject);
+
+ KeyCell = KeyObject->KeyCell;
+ VERIFY_KEY_CELL(KeyCell);
+
+ SubKeyCount = (KeyCell == NULL) ? 0 : KeyCell->NumberOfSubKeys;
+
+ /* Search for volatile or 'foreign' keys */
+ for (i = 0; i < KeyObject->NumberOfSubKeys; i++)
+ {
+ CurKey = KeyObject->SubKeys[i];
+ if (CurKey->RegistryHive == CmiVolatileHive ||
+ CurKey->RegistryHive != KeyObject->RegistryHive)
+ {
+ SubKeyCount++;
+ }
+ }
+
+ return SubKeyCount;
+}
+
+
+ULONG
+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 = CmiGetCell (KeyObject->RegistryHive,
+ KeyCell->HashTableOffset,
+ NULL);
if (HashBlock == NULL)
{
DPRINT("CmiGetBlock() failed\n");
- return 0;
+ }
+ else
+ {
+ for (i = 0; i < HashBlock->HashTableSize; i++)
+ {
+ if (HashBlock->Table[i].KeyOffset != 0)
+ {
+ CurSubKeyCell = CmiGetCell (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 (NameSize > MaxName)
+ {
+ MaxName = NameSize;
+ }
+ }
+ }
}
- for (i = 0; i < HashBlock->HashTableSize; i++)
+ DPRINT ("KeyObject->NumberOfSubKeys %d\n", KeyObject->NumberOfSubKeys);
+ for (i = 0; i < KeyObject->NumberOfSubKeys; i++)
{
- if (HashBlock->Table[i].KeyOffset != 0)
+ CurKey = KeyObject->SubKeys[i];
+ if (CurKey->RegistryHive == CmiVolatileHive ||
+ CurKey->RegistryHive != KeyObject->RegistryHive)
{
- CurSubKeyCell = CmiGetBlock(RegistryHive,
- HashBlock->Table[i].KeyOffset,
- NULL);
+ CurSubKeyCell = CurKey->KeyCell;
if (CurSubKeyCell == NULL)
{
DPRINT("CmiGetBlock() failed\n");
- return 0;
+ continue;
+ }
+
+ if ((CurSubKeyCell->Flags & REG_KEY_ROOT_CELL) == REG_KEY_ROOT_CELL)
+ {
+ /* Use name of the key object */
+ NameSize = CurKey->Name.Length;
}
+ else
+ {
+ /* Use name of the key cell */
+ NameSize = CurSubKeyCell->NameSize;
+ if (CurSubKeyCell->Flags & REG_KEY_NAME_PACKED)
+ {
+ NameSize *= sizeof(WCHAR);
+ }
+ }
+ DPRINT ("NameSize %lu\n", NameSize);
- if (MaxName < CurSubKeyCell->NameSize)
+ if (NameSize > MaxName)
{
- MaxName = CurSubKeyCell->NameSize;
+ MaxName = NameSize;
}
}
}
+ DPRINT ("MaxName %lu\n", MaxName);
+
return MaxName;
}
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 = CmiGetCell (KeyObject->RegistryHive,
+ KeyCell->HashTableOffset,
+ NULL);
if (HashBlock == NULL)
{
DPRINT("CmiGetBlock() failed\n");
- return 0;
+ }
+ else
+ {
+ for (i = 0; i < HashBlock->HashTableSize; i++)
+ {
+ if (HashBlock->Table[i].KeyOffset != 0)
+ {
+ CurSubKeyCell = CmiGetCell (KeyObject->RegistryHive,
+ HashBlock->Table[i].KeyOffset,
+ NULL);
+ if (CurSubKeyCell == NULL)
+ {
+ DPRINT("CmiGetBlock() failed\n");
+ continue;
+ }
+
+ if (MaxClass < CurSubKeyCell->ClassSize)
+ {
+ MaxClass = CurSubKeyCell->ClassSize;
+ }
+ }
+ }
}
- for (i = 0; i < HashBlock->HashTableSize; i++)
+ DPRINT("KeyObject->NumberOfSubKeys %d\n", KeyObject->NumberOfSubKeys);
+ for (i = 0; i < KeyObject->NumberOfSubKeys; i++)
{
- if (HashBlock->Table[i].KeyOffset != 0)
+ CurKey = KeyObject->SubKeys[i];
+ if (CurKey->RegistryHive == CmiVolatileHive ||
+ CurKey->RegistryHive != KeyObject->RegistryHive)
{
- CurSubKeyCell = CmiGetBlock(RegistryHive,
- HashBlock->Table[i].KeyOffset,
- NULL);
+ CurSubKeyCell = CurKey->KeyCell;
if (CurSubKeyCell == NULL)
{
DPRINT("CmiGetBlock() failed\n");
- return 0;
+ continue;
}
if (MaxClass < CurSubKeyCell->ClassSize)
PVALUE_LIST_CELL ValueListCell;
PVALUE_CELL CurValueCell;
ULONG MaxValueName;
+ ULONG Size;
ULONG i;
VERIFY_KEY_CELL(KeyCell);
MaxValueName = 0;
- ValueListCell = CmiGetBlock(RegistryHive,
- KeyCell->ValuesOffset,
+ ValueListCell = CmiGetCell (RegistryHive,
+ KeyCell->ValueListOffset,
NULL);
if (ValueListCell == NULL)
{
for (i = 0; i < KeyCell->NumberOfValues; i++)
{
- CurValueCell = CmiGetBlock (RegistryHive,
- ValueListCell->Values[i],
- NULL);
+ CurValueCell = CmiGetCell (RegistryHive,
+ ValueListCell->ValueOffset[i],
+ NULL);
if (CurValueCell == NULL)
{
DPRINT("CmiGetBlock() failed\n");
}
- if (CurValueCell != NULL &&
- MaxValueName < CurValueCell->NameSize)
- {
- MaxValueName = CurValueCell->NameSize;
+ if (CurValueCell != NULL)
+ {
+ Size = CurValueCell->NameSize;
+ if (CurValueCell->Flags & REG_VALUE_NAME_PACKED)
+ {
+ Size *= sizeof(WCHAR);
+ }
+ if (MaxValueName < Size)
+ {
+ MaxValueName = Size;
+ }
}
}
VERIFY_KEY_CELL(KeyCell);
MaxValueData = 0;
- ValueListCell = CmiGetBlock(RegistryHive, KeyCell->ValuesOffset, NULL);
+ ValueListCell = CmiGetCell (RegistryHive, KeyCell->ValueListOffset, NULL);
if (ValueListCell == NULL)
{
return 0;
for (i = 0; i < KeyCell->NumberOfValues; i++)
{
- CurValueCell = CmiGetBlock(RegistryHive,
- ValueListCell->Values[i],NULL);
+ CurValueCell = CmiGetCell (RegistryHive,
+ ValueListCell->ValueOffset[i],NULL);
if ((CurValueCell != NULL) &&
- (MaxValueData < (CurValueCell->DataSize & LONG_MAX)))
+ (MaxValueData < (LONG)(CurValueCell->DataSize & REG_DATA_SIZE_MASK)))
{
- MaxValueData = CurValueCell->DataSize & LONG_MAX;
+ MaxValueData = CurValueCell->DataSize & REG_DATA_SIZE_MASK;
}
}
DPRINT("Scanning for sub key %wZ\n", KeyName);
- assert(RegistryHive);
+ ASSERT(RegistryHive);
*SubKeyCell = NULL;
}
/* Get hash table */
- HashBlock = CmiGetBlock(RegistryHive, KeyCell->HashTableOffset, NULL);
+ HashBlock = CmiGetCell (RegistryHive, KeyCell->HashTableOffset, NULL);
if (HashBlock == NULL)
{
DPRINT("CmiGetBlock() failed\n");
(HashBlock->Table[i].HashValue == 0 ||
CmiCompareHashI(KeyName, (PCHAR)&HashBlock->Table[i].HashValue)))
{
- CurSubKeyCell = CmiGetBlock(RegistryHive,
+ CurSubKeyCell = CmiGetCell (RegistryHive,
HashBlock->Table[i].KeyOffset,
NULL);
if (CurSubKeyCell == NULL)
(HashBlock->Table[i].HashValue == 0 ||
CmiCompareHash(KeyName, (PCHAR)&HashBlock->Table[i].HashValue)))
{
- CurSubKeyCell = CmiGetBlock(RegistryHive,
+ CurSubKeyCell = CmiGetCell (RegistryHive,
HashBlock->Table[i].KeyOffset,
NULL);
if (CurSubKeyCell == NULL)
NTSTATUS
CmiAddSubKey(PREGISTRY_HIVE RegistryHive,
- PKEY_OBJECT Parent,
+ PKEY_OBJECT ParentKey,
PKEY_OBJECT SubKey,
PUNICODE_STRING SubKeyName,
ULONG TitleIndex,
PUNICODE_STRING Class,
ULONG CreateOptions)
{
- PHASH_TABLE_CELL NewHashBlock;
PHASH_TABLE_CELL HashBlock;
BLOCK_OFFSET NKBOffset;
PKEY_CELL NewKeyCell;
ULONG NewBlockSize;
- PKEY_CELL KeyCell;
+ PKEY_CELL ParentKeyCell;
+ PDATA_CELL ClassCell;
NTSTATUS Status;
USHORT NameSize;
PWSTR NamePtr;
+ BOOLEAN Packable;
+ ULONG i;
- KeyCell = Parent->KeyCell;
+ ParentKeyCell = ParentKey->KeyCell;
- VERIFY_KEY_CELL(KeyCell);
+ VERIFY_KEY_CELL(ParentKeyCell);
+ /* Skip leading backslash */
if (SubKeyName->Buffer[0] == L'\\')
{
NamePtr = &SubKeyName->Buffer[1];
- NameSize = SubKeyName->Length / 2 - 1;
+ NameSize = SubKeyName->Length - sizeof(WCHAR);
}
else
{
NamePtr = SubKeyName->Buffer;
- NameSize = SubKeyName->Length / 2;
+ 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;
- Status = CmiAllocateBlock(RegistryHive,
- (PVOID) &NewKeyCell,
+ Status = CmiAllocateCell (RegistryHive,
NewBlockSize,
+ (PVOID) &NewKeyCell,
&NKBOffset);
if (NewKeyCell == NULL)
{
{
NewKeyCell->Id = REG_KEY_CELL_ID;
NewKeyCell->Flags = 0;
- ZwQuerySystemTime((PTIME) &NewKeyCell->LastWriteTime);
+ KeQuerySystemTime(&NewKeyCell->LastWriteTime);
NewKeyCell->ParentKeyOffset = -1;
NewKeyCell->NumberOfSubKeys = 0;
NewKeyCell->HashTableOffset = -1;
NewKeyCell->NumberOfValues = 0;
- NewKeyCell->ValuesOffset = -1;
+ NewKeyCell->ValueListOffset = -1;
NewKeyCell->SecurityKeyOffset = -1;
NewKeyCell->ClassNameOffset = -1;
- NewKeyCell->Flags |= REG_KEY_NAME_PACKED;
+ /* Pack the key name */
NewKeyCell->NameSize = NameSize;
- wcstombs(NewKeyCell->Name, NamePtr, 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)
+ if (Class != NULL)
{
- PDATA_CELL pClass;
-
- NewKeyCell->ClassSize = Class->Length + sizeof(WCHAR);
- Status = CmiAllocateBlock(RegistryHive,
- (PVOID) &pClass,
- NewKeyCell->ClassSize,
+ NewKeyCell->ClassSize = Class->Length;
+ Status = CmiAllocateCell (RegistryHive,
+ sizeof(CELL_HEADER) + NewKeyCell->ClassSize,
+ (PVOID)&ClassCell,
&NewKeyCell->ClassNameOffset);
- wcsncpy((PWSTR) pClass->Data, Class->Buffer, Class->Length);
- ((PWSTR) (pClass->Data))[Class->Length] = 0;
+ RtlCopyMemory (ClassCell->Data,
+ Class->Buffer,
+ Class->Length);
}
}
}
SubKey->KeyCell = NewKeyCell;
- SubKey->BlockOffset = NKBOffset;
+ SubKey->KeyCellOffset = NKBOffset;
/* Don't modify hash table if key is located in a pointer-based hive and parent key is not */
- if (IsPointerHive(RegistryHive) && (!IsPointerHive(Parent->RegistryHive)))
+ if (IsPointerHive(RegistryHive) && (!IsPointerHive(ParentKey->RegistryHive)))
{
return(Status);
}
- if (KeyCell->HashTableOffset == (ULONG_PTR) -1)
+ if (ParentKeyCell->HashTableOffset == (ULONG_PTR) -1)
{
- Status = CmiAllocateHashTableBlock(RegistryHive,
+ Status = CmiAllocateHashTableCell (RegistryHive,
&HashBlock,
- &KeyCell->HashTableOffset,
+ &ParentKeyCell->HashTableOffset,
REG_INIT_HASH_TABLE_SIZE);
if (!NT_SUCCESS(Status))
{
}
else
{
- HashBlock = CmiGetBlock(RegistryHive,
- KeyCell->HashTableOffset,
+ HashBlock = CmiGetCell (RegistryHive,
+ ParentKeyCell->HashTableOffset,
NULL);
if (HashBlock == NULL)
{
- DPRINT("CmiGetBlock() failed\n");
+ DPRINT("CmiGetCell() failed\n");
return STATUS_UNSUCCESSFUL;
}
- if (((KeyCell->NumberOfSubKeys + 1) >= HashBlock->HashTableSize))
+ if (((ParentKeyCell->NumberOfSubKeys + 1) >= HashBlock->HashTableSize))
{
+ PHASH_TABLE_CELL NewHashBlock;
BLOCK_OFFSET HTOffset;
- /* Reallocate the hash table block */
- Status = CmiAllocateHashTableBlock(RegistryHive,
+ /* Reallocate the hash table cell */
+ Status = CmiAllocateHashTableCell (RegistryHive,
&NewHashBlock,
&HTOffset,
HashBlock->HashTableSize +
RtlCopyMemory(&NewHashBlock->Table[0],
&HashBlock->Table[0],
sizeof(NewHashBlock->Table[0]) * HashBlock->HashTableSize);
- CmiDestroyBlock(RegistryHive,
+ CmiDestroyCell (RegistryHive,
HashBlock,
- KeyCell->HashTableOffset);
- KeyCell->HashTableOffset = HTOffset;
+ ParentKeyCell->HashTableOffset);
+ ParentKeyCell->HashTableOffset = HTOffset;
HashBlock = NewHashBlock;
}
}
Status = CmiAddKeyToHashTable(RegistryHive,
HashBlock,
+ ParentKeyCell->HashTableOffset,
NewKeyCell,
NKBOffset);
if (NT_SUCCESS(Status))
{
- KeyCell->NumberOfSubKeys++;
+ ParentKeyCell->NumberOfSubKeys++;
}
+ KeQuerySystemTime (&ParentKeyCell->LastWriteTime);
+ CmiMarkBlockDirty (RegistryHive, ParentKey->KeyCellOffset);
+
return(Status);
}
if (SubKey->KeyCell->NumberOfValues != 0)
{
/* Get pointer to the value list cell */
- ValueList = CmiGetBlock(RegistryHive,
- SubKey->KeyCell->ValuesOffset,
+ ValueList = CmiGetCell (RegistryHive,
+ SubKey->KeyCell->ValueListOffset,
NULL);
if (ValueList == NULL)
{
- DPRINT("CmiGetBlock() failed\n");
+ DPRINT("CmiGetCell() failed\n");
return STATUS_UNSUCCESSFUL;
}
- if (ValueList != NULL)
+ /* Enumerate all values */
+ for (i = 0; i < SubKey->KeyCell->NumberOfValues; i++)
{
- /* Enumerate all values */
- for (i = 0; i < SubKey->KeyCell->NumberOfValues; i++)
+ /* Get pointer to value cell */
+ ValueCell = CmiGetCell(RegistryHive,
+ ValueList->ValueOffset[i],
+ NULL);
+ if (ValueCell == NULL)
+ {
+ DPRINT("CmiGetCell() failed\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ if (!(ValueCell->DataSize & REG_DATA_IN_OFFSET)
+ && ValueCell->DataSize > sizeof(BLOCK_OFFSET))
{
- /* Get pointer to value cell */
- ValueCell = CmiGetBlock(RegistryHive,
- ValueList->Values[i],
- NULL);
- if (ValueCell != NULL)
+ DataCell = CmiGetCell (RegistryHive,
+ ValueCell->DataOffset,
+ NULL);
+ if (DataCell == NULL)
{
- if (ValueCell->DataSize > 4)
- {
- DataCell = CmiGetBlock(RegistryHive,
- ValueCell->DataOffset,
- NULL);
- if (DataCell == NULL)
- {
- DPRINT("CmiGetBlock() failed\n");
- return STATUS_UNSUCCESSFUL;
- }
-
- if (DataCell != NULL)
- {
- /* Destroy data cell */
- CmiDestroyBlock(RegistryHive,
- DataCell,
- ValueCell->DataOffset);
- }
- }
-
- /* Destroy value cell */
- CmiDestroyBlock(RegistryHive,
- ValueCell,
- ValueList->Values[i]);
+ DPRINT("CmiGetCell() failed\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ if (DataCell != NULL)
+ {
+ /* Destroy data cell */
+ CmiDestroyCell (RegistryHive,
+ DataCell,
+ ValueCell->DataOffset);
}
}
+
+ /* Destroy value cell */
+ CmiDestroyCell (RegistryHive,
+ ValueCell,
+ ValueList->ValueOffset[i]);
}
/* Destroy value list cell */
- CmiDestroyBlock(RegistryHive,
+ CmiDestroyCell (RegistryHive,
ValueList,
- SubKey->KeyCell->ValuesOffset);
+ SubKey->KeyCell->ValueListOffset);
SubKey->KeyCell->NumberOfValues = 0;
- SubKey->KeyCell->ValuesOffset = -1;
+ SubKey->KeyCell->ValueListOffset = (BLOCK_OFFSET)-1;
+
+ CmiMarkBlockDirty(RegistryHive,
+ SubKey->KeyCellOffset);
}
/* Remove the key from the parent key's hash block */
if (ParentKey->KeyCell->HashTableOffset != (BLOCK_OFFSET) -1)
{
- DPRINT("ParentKey HashTableOffset %lx\n", ParentKey->KeyCell->HashTableOffset)
- HashBlock = CmiGetBlock(RegistryHive,
+ DPRINT("ParentKey HashTableOffset %lx\n", ParentKey->KeyCell->HashTableOffset);
+ HashBlock = CmiGetCell (ParentKey->RegistryHive,
ParentKey->KeyCell->HashTableOffset,
NULL);
if (HashBlock == NULL)
{
- DPRINT("CmiGetBlock() failed\n");
+ DPRINT("CmiGetCell() failed\n");
return STATUS_UNSUCCESSFUL;
}
- DPRINT("ParentKey HashBlock %p\n", HashBlock)
+ DPRINT("ParentKey HashBlock %p\n", HashBlock);
if (HashBlock != NULL)
{
- CmiRemoveKeyFromHashTable(RegistryHive,
+ CmiRemoveKeyFromHashTable(ParentKey->RegistryHive,
HashBlock,
- SubKey->BlockOffset);
- CmiMarkBlockDirty(RegistryHive,
+ SubKey->KeyCellOffset);
+ CmiMarkBlockDirty(ParentKey->RegistryHive,
ParentKey->KeyCell->HashTableOffset);
}
}
/* Remove the key's hash block */
if (SubKey->KeyCell->HashTableOffset != (BLOCK_OFFSET) -1)
{
- DPRINT("SubKey HashTableOffset %lx\n", SubKey->KeyCell->HashTableOffset)
- HashBlock = CmiGetBlock(RegistryHive,
+ DPRINT("SubKey HashTableOffset %lx\n", SubKey->KeyCell->HashTableOffset);
+ HashBlock = CmiGetCell (RegistryHive,
SubKey->KeyCell->HashTableOffset,
NULL);
if (HashBlock == NULL)
{
- DPRINT("CmiGetBlock() failed\n");
+ DPRINT("CmiGetCell() failed\n");
return STATUS_UNSUCCESSFUL;
}
- DPRINT("SubKey HashBlock %p\n", HashBlock)
+ DPRINT("SubKey HashBlock %p\n", HashBlock);
if (HashBlock != NULL)
{
- CmiDestroyBlock(RegistryHive,
+ CmiDestroyCell (RegistryHive,
HashBlock,
SubKey->KeyCell->HashTableOffset);
SubKey->KeyCell->HashTableOffset = -1;
/* Decrement the number of the parent key's sub keys */
if (ParentKey != NULL)
{
- DPRINT("ParentKey %p\n", ParentKey)
+ DPRINT("ParentKey %p\n", ParentKey);
ParentKey->KeyCell->NumberOfSubKeys--;
/* Remove the parent key's hash table */
if (ParentKey->KeyCell->NumberOfSubKeys == 0)
{
- DPRINT("ParentKey HashTableOffset %lx\n", ParentKey->KeyCell->HashTableOffset)
- HashBlock = CmiGetBlock(RegistryHive,
+ DPRINT("ParentKey HashTableOffset %lx\n", ParentKey->KeyCell->HashTableOffset);
+ HashBlock = CmiGetCell (ParentKey->RegistryHive,
ParentKey->KeyCell->HashTableOffset,
NULL);
if (HashBlock == NULL)
{
- DPRINT("CmiGetBlock() failed\n");
+ DPRINT("CmiGetCell() failed\n");
return STATUS_UNSUCCESSFUL;
}
- DPRINT("ParentKey HashBlock %p\n", HashBlock)
+ DPRINT("ParentKey HashBlock %p\n", HashBlock);
if (HashBlock != NULL)
{
- CmiDestroyBlock(RegistryHive,
+ CmiDestroyCell (ParentKey->RegistryHive,
HashBlock,
ParentKey->KeyCell->HashTableOffset);
- ParentKey->KeyCell->HashTableOffset = -1;
+ ParentKey->KeyCell->HashTableOffset = (BLOCK_OFFSET)-1;
}
}
- NtQuerySystemTime((PTIME)&ParentKey->KeyCell->LastWriteTime);
- CmiMarkBlockDirty(RegistryHive,
- ParentKey->BlockOffset);
+ KeQuerySystemTime(&ParentKey->KeyCell->LastWriteTime);
+ CmiMarkBlockDirty(ParentKey->RegistryHive,
+ ParentKey->KeyCellOffset);
}
/* Destroy key cell */
- CmiDestroyBlock(RegistryHive,
+ CmiDestroyCell (RegistryHive,
SubKey->KeyCell,
- SubKey->BlockOffset);
- SubKey->BlockOffset = -1;
+ SubKey->KeyCellOffset);
SubKey->KeyCell = NULL;
+ SubKey->KeyCellOffset = (BLOCK_OFFSET)-1;
- return(STATUS_SUCCESS);
+ DPRINT("CmiRemoveSubKey() done\n");
+
+ return STATUS_SUCCESS;
}
IN PKEY_CELL KeyCell,
IN PUNICODE_STRING ValueName,
OUT PVALUE_CELL *ValueCell,
- OUT BLOCK_OFFSET *VBOffset)
+ OUT BLOCK_OFFSET *ValueCellOffset)
{
PVALUE_LIST_CELL ValueListCell;
PVALUE_CELL CurValueCell;
ULONG i;
*ValueCell = NULL;
+ if (ValueCellOffset != NULL)
+ *ValueCellOffset = (BLOCK_OFFSET)-1;
/* The key does not have any values */
- if (KeyCell->ValuesOffset == (BLOCK_OFFSET)-1)
+ if (KeyCell->ValueListOffset == (BLOCK_OFFSET)-1)
{
- return STATUS_SUCCESS;
+ return STATUS_OBJECT_NAME_NOT_FOUND;
}
- ValueListCell = CmiGetBlock(RegistryHive, KeyCell->ValuesOffset, NULL);
+ ValueListCell = CmiGetCell (RegistryHive, KeyCell->ValueListOffset, NULL);
if (ValueListCell == NULL)
{
DPRINT("ValueListCell is NULL\n");
for (i = 0; i < KeyCell->NumberOfValues; i++)
{
- CurValueCell = CmiGetBlock(RegistryHive,
- ValueListCell->Values[i],
+ CurValueCell = CmiGetCell (RegistryHive,
+ ValueListCell->ValueOffset[i],
NULL);
if (CurValueCell == NULL)
{
CmiComparePackedNames(ValueName,
CurValueCell->Name,
CurValueCell->NameSize,
- CurValueCell->Flags & REG_VALUE_NAME_PACKED))
+ (BOOLEAN)((CurValueCell->Flags & REG_VALUE_NAME_PACKED) ? TRUE : FALSE)))
{
*ValueCell = CurValueCell;
- if (VBOffset)
- *VBOffset = ValueListCell->Values[i];
+ if (ValueCellOffset != NULL)
+ *ValueCellOffset = ValueListCell->ValueOffset[i];
//DPRINT("Found value %s\n", ValueName);
- break;
+ return STATUS_SUCCESS;
}
}
- return STATUS_SUCCESS;
+ return STATUS_OBJECT_NAME_NOT_FOUND;
}
*ValueCell = NULL;
- if (KeyCell->ValuesOffset == (BLOCK_OFFSET)-1)
+ if (KeyCell->ValueListOffset == (BLOCK_OFFSET)-1)
{
return STATUS_NO_MORE_ENTRIES;
}
}
- ValueListCell = CmiGetBlock(RegistryHive, KeyCell->ValuesOffset, NULL);
+ ValueListCell = CmiGetCell (RegistryHive, KeyCell->ValueListOffset, NULL);
if (ValueListCell == NULL)
{
DPRINT("CmiGetBlock() failed\n");
VERIFY_VALUE_LIST_CELL(ValueListCell);
- CurValueCell = CmiGetBlock(RegistryHive,
- ValueListCell->Values[Index],
+ CurValueCell = CmiGetCell (RegistryHive,
+ ValueListCell->ValueOffset[Index],
NULL);
if (CurValueCell == NULL)
{
NTSTATUS
CmiAddValueToKey(IN PREGISTRY_HIVE RegistryHive,
IN PKEY_CELL KeyCell,
+ IN BLOCK_OFFSET KeyCellOffset,
IN PUNICODE_STRING ValueName,
OUT PVALUE_CELL *pValueCell,
- OUT BLOCK_OFFSET *pVBOffset)
+ OUT BLOCK_OFFSET *pValueCellOffset)
{
PVALUE_LIST_CELL NewValueListCell;
PVALUE_LIST_CELL ValueListCell;
PVALUE_CELL NewValueCell;
- BLOCK_OFFSET VLBOffset;
- BLOCK_OFFSET VBOffset;
+ BLOCK_OFFSET NewValueListCellOffset;
+ BLOCK_OFFSET ValueListCellOffset;
+ BLOCK_OFFSET NewValueCellOffset;
+ ULONG CellSize;
NTSTATUS Status;
- Status = CmiAllocateValueCell(RegistryHive,
- &NewValueCell,
- &VBOffset,
- ValueName);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
-
- DPRINT("KeyCell->ValuesOffset %lu\n", (ULONG)KeyCell->ValuesOffset);
-
- ValueListCell = CmiGetBlock(RegistryHive, KeyCell->ValuesOffset, NULL);
+ DPRINT("KeyCell->ValuesOffset %lu\n", (ULONG)KeyCell->ValueListOffset);
+ ValueListCell = CmiGetCell (RegistryHive, KeyCell->ValueListOffset, NULL);
if (ValueListCell == NULL)
{
- Status = CmiAllocateBlock(RegistryHive,
- (PVOID) &ValueListCell,
- sizeof(BLOCK_OFFSET) * 3,
- &VLBOffset);
-
+ CellSize = sizeof(VALUE_LIST_CELL) +
+ (3 * sizeof(BLOCK_OFFSET));
+ Status = CmiAllocateCell (RegistryHive,
+ CellSize,
+ (PVOID) &ValueListCell,
+ &ValueListCellOffset);
if (!NT_SUCCESS(Status))
{
- CmiDestroyValueCell(RegistryHive, NewValueCell, VBOffset);
return Status;
}
- KeyCell->ValuesOffset = VLBOffset;
+
+ KeyCell->ValueListOffset = ValueListCellOffset;
+ CmiMarkBlockDirty(RegistryHive, KeyCellOffset);
+ CmiMarkBlockDirty(RegistryHive, ValueListCellOffset);
}
- else if (KeyCell->NumberOfValues >=
- (((ULONG)ABS_VALUE(ValueListCell->CellSize) - 4) / sizeof(BLOCK_OFFSET)))
+ else if (KeyCell->NumberOfValues >=
+ (((ULONG)ABS_VALUE(ValueListCell->CellSize) - sizeof(VALUE_LIST_CELL)) / sizeof(BLOCK_OFFSET)))
{
- Status = CmiAllocateBlock(RegistryHive,
+#if 0
+ CellSize = sizeof(VALUE_LIST_CELL) +
+ ((KeyCell->NumberOfValues + REG_VALUE_LIST_CELL_MULTIPLE) * sizeof(BLOCK_OFFSET));
+#endif
+ CellSize = 2 * (ULONG)ABS_VALUE(ValueListCell->CellSize);
+ Status = CmiAllocateCell (RegistryHive,
+ CellSize,
(PVOID) &NewValueListCell,
- (KeyCell->NumberOfValues + REG_VALUE_LIST_CELL_MULTIPLE) *
- sizeof(BLOCK_OFFSET),
- &VLBOffset);
+ &NewValueListCellOffset);
if (!NT_SUCCESS(Status))
{
- CmiDestroyValueCell(RegistryHive, NewValueCell, VBOffset);
return Status;
}
- RtlCopyMemory(&NewValueListCell->Values[0],
- &ValueListCell->Values[0],
+ RtlCopyMemory(&NewValueListCell->ValueOffset[0],
+ &ValueListCell->ValueOffset[0],
sizeof(BLOCK_OFFSET) * KeyCell->NumberOfValues);
- CmiDestroyBlock(RegistryHive, ValueListCell, KeyCell->ValuesOffset);
- KeyCell->ValuesOffset = VLBOffset;
+ CmiDestroyCell (RegistryHive, ValueListCell, KeyCell->ValueListOffset);
+ CmiMarkBlockDirty (RegistryHive, KeyCell->ValueListOffset);
+
+ KeyCell->ValueListOffset = NewValueListCellOffset;
ValueListCell = NewValueListCell;
+ CmiMarkBlockDirty (RegistryHive, KeyCellOffset);
+ CmiMarkBlockDirty (RegistryHive, NewValueListCellOffset);
}
DPRINT("KeyCell->NumberOfValues %lu, ValueListCell->CellSize %lu (%lu %lx)\n",
KeyCell->NumberOfValues,
(ULONG)ABS_VALUE(ValueListCell->CellSize),
- ((ULONG)ABS_VALUE(ValueListCell->CellSize) - 4) / sizeof(BLOCK_OFFSET),
- ((ULONG)ABS_VALUE(ValueListCell->CellSize) - 4) / sizeof(BLOCK_OFFSET));
+ ((ULONG)ABS_VALUE(ValueListCell->CellSize) - sizeof(VALUE_LIST_CELL)) / sizeof(BLOCK_OFFSET),
+ ((ULONG)ABS_VALUE(ValueListCell->CellSize) - sizeof(VALUE_LIST_CELL)) / sizeof(BLOCK_OFFSET));
- ValueListCell->Values[KeyCell->NumberOfValues] = VBOffset;
+ Status = CmiAllocateValueCell(RegistryHive,
+ &NewValueCell,
+ &NewValueCellOffset,
+ ValueName);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ ValueListCell->ValueOffset[KeyCell->NumberOfValues] = NewValueCellOffset;
KeyCell->NumberOfValues++;
+ CmiMarkBlockDirty(RegistryHive, KeyCellOffset);
+ CmiMarkBlockDirty(RegistryHive, KeyCell->ValueListOffset);
+ CmiMarkBlockDirty(RegistryHive, NewValueCellOffset);
+
*pValueCell = NewValueCell;
- *pVBOffset = VBOffset;
+ *pValueCellOffset = NewValueCellOffset;
return STATUS_SUCCESS;
}
{
PVALUE_LIST_CELL ValueListCell;
PVALUE_CELL CurValueCell;
- ULONG i;
-
- ValueListCell = CmiGetBlock(RegistryHive, KeyCell->ValuesOffset, NULL);
+ ULONG i;
+ NTSTATUS Status;
+ ValueListCell = CmiGetCell (RegistryHive, KeyCell->ValueListOffset, NULL);
if (ValueListCell == NULL)
{
- DPRINT("CmiGetBlock() failed\n");
+ DPRINT1("CmiGetBlock() failed\n");
return STATUS_SUCCESS;
}
for (i = 0; i < KeyCell->NumberOfValues; i++)
{
- CurValueCell = CmiGetBlock(RegistryHive, ValueListCell->Values[i], NULL);
+ CurValueCell = CmiGetCell (RegistryHive, ValueListCell->ValueOffset[i], NULL);
if (CurValueCell == NULL)
{
- DPRINT("CmiGetBlock() failed\n");
+ DPRINT1("CmiGetBlock() failed\n");
return STATUS_UNSUCCESSFUL;
}
- if ((CurValueCell != NULL) &&
- CmiComparePackedNames(ValueName,
+ if (CmiComparePackedNames(ValueName,
CurValueCell->Name,
CurValueCell->NameSize,
- CurValueCell->Flags & REG_VALUE_NAME_PACKED))
+ (BOOLEAN)((CurValueCell->Flags & REG_VALUE_NAME_PACKED) ? TRUE : FALSE)))
{
- CmiDestroyValueCell(RegistryHive, CurValueCell, ValueListCell->Values[i]);
+ Status = CmiDestroyValueCell(RegistryHive,
+ CurValueCell,
+ ValueListCell->ValueOffset[i]);
+ if (CurValueCell == NULL)
+ {
+ DPRINT1("CmiDestroyValueCell() failed\n");
+ return Status;
+ }
- if ((KeyCell->NumberOfValues - 1) < i)
+ if (i < (KeyCell->NumberOfValues - 1))
{
- RtlCopyMemory(&ValueListCell->Values[i],
- &ValueListCell->Values[i + 1],
+ RtlMoveMemory(&ValueListCell->ValueOffset[i],
+ &ValueListCell->ValueOffset[i + 1],
sizeof(BLOCK_OFFSET) * (KeyCell->NumberOfValues - 1 - i));
}
+ ValueListCell->ValueOffset[KeyCell->NumberOfValues - 1] = 0;
+
+
+ KeyCell->NumberOfValues--;
+
+ if (KeyCell->NumberOfValues == 0)
+ {
+ CmiDestroyCell(RegistryHive,
+ ValueListCell,
+ KeyCell->ValueListOffset);
+ KeyCell->ValueListOffset = -1;
+ }
else
{
- RtlZeroMemory(&ValueListCell->Values[i], sizeof(BLOCK_OFFSET));
+ CmiMarkBlockDirty(RegistryHive,
+ KeyCell->ValueListOffset);
}
- KeyCell->NumberOfValues -= 1;
- break;
- }
- }
+ CmiMarkBlockDirty(RegistryHive,
+ KeyCellOffset);
- if (KeyCell->NumberOfValues == 0)
- {
- CmiDestroyBlock(RegistryHive,
- ValueListCell,
- KeyCell->ValuesOffset);
- }
- else
- {
- CmiMarkBlockDirty(RegistryHive,
- KeyCell->ValuesOffset);
+ return STATUS_SUCCESS;
+ }
}
- CmiMarkBlockDirty(RegistryHive,
- KeyCellOffset);
+ DPRINT("Couldn't find the desired value\n");
- return STATUS_SUCCESS;
+ return STATUS_OBJECT_NAME_NOT_FOUND;
}
NTSTATUS
-CmiAllocateHashTableBlock(IN PREGISTRY_HIVE RegistryHive,
+CmiAllocateHashTableCell (IN PREGISTRY_HIVE RegistryHive,
OUT PHASH_TABLE_CELL *HashBlock,
OUT BLOCK_OFFSET *HBOffset,
- IN ULONG HashTableSize)
+ IN ULONG SubKeyCount)
{
PHASH_TABLE_CELL NewHashBlock;
ULONG NewHashSize;
Status = STATUS_SUCCESS;
*HashBlock = NULL;
- NewHashSize = sizeof(HASH_TABLE_CELL) +
- (HashTableSize - 1) * sizeof(HASH_RECORD);
- Status = CmiAllocateBlock(RegistryHive,
- (PVOID*) &NewHashBlock,
+ NewHashSize = sizeof(HASH_TABLE_CELL) +
+ (SubKeyCount * sizeof(HASH_RECORD));
+ Status = CmiAllocateCell (RegistryHive,
NewHashSize,
+ (PVOID*) &NewHashBlock,
HBOffset);
if ((NewHashBlock == NULL) || (!NT_SUCCESS(Status)))
}
else
{
- NewHashBlock->Id = REG_HASH_TABLE_BLOCK_ID;
- NewHashBlock->HashTableSize = HashTableSize;
+ ASSERT(SubKeyCount <= 0xffff); /* should really be USHORT_MAX or similar */
+ NewHashBlock->Id = REG_HASH_TABLE_CELL_ID;
+ NewHashBlock->HashTableSize = (USHORT)SubKeyCount;
*HashBlock = NewHashBlock;
}
else
{
KeyOffset = HashBlock->Table[Index].KeyOffset;
- KeyCell = CmiGetBlock(RegistryHive, KeyOffset, NULL);
+ KeyCell = CmiGetCell (RegistryHive, KeyOffset, NULL);
}
return KeyCell;
NTSTATUS
CmiAddKeyToHashTable(PREGISTRY_HIVE RegistryHive,
- PHASH_TABLE_CELL HashBlock,
+ PHASH_TABLE_CELL HashCell,
+ BLOCK_OFFSET HashCellOffset,
PKEY_CELL NewKeyCell,
BLOCK_OFFSET NKBOffset)
{
ULONG i;
- for (i = 0; i < HashBlock->HashTableSize; i++)
+ for (i = 0; i < HashCell->HashTableSize; i++)
{
- if (HashBlock->Table[i].KeyOffset == 0)
+ if (HashCell->Table[i].KeyOffset == 0)
{
- HashBlock->Table[i].KeyOffset = NKBOffset;
- HashBlock->Table[i].HashValue = 0;
+ HashCell->Table[i].KeyOffset = NKBOffset;
+ HashCell->Table[i].HashValue = 0;
if (NewKeyCell->Flags & REG_KEY_NAME_PACKED)
{
- RtlCopyMemory(&HashBlock->Table[i].HashValue,
+ RtlCopyMemory(&HashCell->Table[i].HashValue,
NewKeyCell->Name,
- min(NewKeyCell->NameSize, 4));
+ min(NewKeyCell->NameSize, sizeof(ULONG)));
}
+ CmiMarkBlockDirty(RegistryHive, HashCellOffset);
return STATUS_SUCCESS;
}
}
DPRINT("ValueName->Length %lu NameSize %lu\n", ValueName->Length, NameSize);
- Status = CmiAllocateBlock(RegistryHive,
- (PVOID*) &NewValueCell,
+ Status = CmiAllocateCell (RegistryHive,
sizeof(VALUE_CELL) + NameSize,
+ (PVOID*) &NewValueCell,
VBOffset);
if ((NewValueCell == NULL) || (!NT_SUCCESS(Status)))
{
}
else
{
+ ASSERT(NameSize <= 0xffff); /* should really be USHORT_MAX or similar */
NewValueCell->Id = REG_VALUE_CELL_ID;
- NewValueCell->NameSize = NameSize;
+ NewValueCell->NameSize = (USHORT)NameSize;
if (Packable)
{
/* Pack the value name */
}
NewValueCell->DataType = 0;
NewValueCell->DataSize = 0;
- NewValueCell->DataOffset = 0xffffffff;
+ NewValueCell->DataOffset = (BLOCK_OFFSET)-1;
*ValueCell = NewValueCell;
}
NTSTATUS
CmiDestroyValueCell(PREGISTRY_HIVE RegistryHive,
PVALUE_CELL ValueCell,
- BLOCK_OFFSET VBOffset)
+ BLOCK_OFFSET ValueCellOffset)
{
NTSTATUS Status;
- PVOID pBlock;
- PHBIN pBin;
+ PVOID DataCell;
+ PHBIN Bin;
- DPRINT("CmiDestroyValueCell(Cell %p Offset %lx)\n", ValueCell, VBOffset);
+ DPRINT("CmiDestroyValueCell(Cell %p Offset %lx)\n",
+ ValueCell, ValueCellOffset);
VERIFY_VALUE_CELL(ValueCell);
/* Destroy the data cell */
- if (ValueCell->DataSize > 4)
+ if (!(ValueCell->DataSize & REG_DATA_IN_OFFSET)
+ && ValueCell->DataSize > sizeof(BLOCK_OFFSET))
{
- pBlock = CmiGetBlock(RegistryHive, ValueCell->DataOffset, &pBin);
- if (pBlock == NULL)
+ DataCell = CmiGetCell (RegistryHive, ValueCell->DataOffset, &Bin);
+ if (DataCell == NULL)
{
- DPRINT("CmiGetBlock() failed\n");
+ DPRINT("CmiGetCell() failed\n");
return STATUS_UNSUCCESSFUL;
}
- Status = CmiDestroyBlock(RegistryHive, pBlock, ValueCell->DataOffset);
+ Status = CmiDestroyCell (RegistryHive, DataCell, ValueCell->DataOffset);
if (!NT_SUCCESS(Status))
{
- return Status;
+ return Status;
}
/* Update time of heap */
- if (!IsVolatileHive(RegistryHive))
- NtQuerySystemTime((PTIME) &pBin->DateModified);
+ if (!IsNoFileHive(RegistryHive))
+ KeQuerySystemTime(&Bin->DateModified);
}
/* Destroy the value cell */
- Status = CmiDestroyBlock(RegistryHive, ValueCell, VBOffset);
+ Status = CmiDestroyCell (RegistryHive, ValueCell, ValueCellOffset);
/* Update time of heap */
- if (!IsVolatileHive(RegistryHive) && CmiGetBlock(RegistryHive, VBOffset, &pBin))
+ if (!IsNoFileHive(RegistryHive) && CmiGetCell (RegistryHive, ValueCellOffset, &Bin))
{
- NtQuerySystemTime((PTIME) &pBin->DateModified);
+ KeQuerySystemTime(&Bin->DateModified);
}
return Status;
NTSTATUS
CmiAddBin(PREGISTRY_HIVE RegistryHive,
+ ULONG BlockCount,
PVOID *NewBlock,
BLOCK_OFFSET *NewBlockOffset)
{
+ PBLOCK_LIST_ENTRY BlockList;
PCELL_HEADER tmpBlock;
- PHBIN * tmpBlockList;
PHBIN tmpBin;
+ ULONG BinSize;
+ ULONG i;
+ ULONG BitmapSize;
- tmpBin = ExAllocatePool(PagedPool, REG_BLOCK_SIZE);
+ DPRINT ("CmiAddBin (BlockCount %lu)\n", BlockCount);
+
+ BinSize = BlockCount * REG_BLOCK_SIZE;
+ tmpBin = ExAllocatePool(PagedPool, BinSize);
if (tmpBin == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
+ RtlZeroMemory (tmpBin,
+ BinSize);
+
+ tmpBin->HeaderId = REG_BIN_ID;
+ tmpBin->BinOffset = RegistryHive->FileSize - REG_BLOCK_SIZE;
+ RegistryHive->FileSize += BinSize;
+ tmpBin->BinSize = BinSize;
+ KeQuerySystemTime(&tmpBin->DateModified);
+ tmpBin->MemAlloc = 0;
- tmpBin->BlockId = REG_BIN_ID;
- tmpBin->BlockOffset = RegistryHive->FileSize - REG_BLOCK_SIZE;
- RegistryHive->FileSize += REG_BLOCK_SIZE;
- tmpBin->BlockSize = REG_BLOCK_SIZE;
- tmpBin->Unused1 = 0;
- ZwQuerySystemTime((PTIME) &tmpBin->DateModified);
- tmpBin->Unused2 = 0;
+ DPRINT (" BinOffset %lx BinSize %lx\n", tmpBin->BinOffset,tmpBin->BinSize);
- /* Increase size of list of blocks */
- tmpBlockList = ExAllocatePool(NonPagedPool,
- sizeof(PHBIN *) * (RegistryHive->BlockListSize + 1));
- if (tmpBlockList == NULL)
+ /* Allocate new block list */
+ BlockList = ExAllocatePool(NonPagedPool,
+ sizeof(BLOCK_LIST_ENTRY) * (RegistryHive->BlockListSize + BlockCount));
+ if (BlockList == NULL)
{
ExFreePool(tmpBin);
return STATUS_INSUFFICIENT_RESOURCES;
if (RegistryHive->BlockListSize > 0)
{
- RtlCopyMemory (tmpBlockList,
+ RtlCopyMemory (BlockList,
RegistryHive->BlockList,
- sizeof(PHBIN *)*(RegistryHive->BlockListSize));
+ sizeof(BLOCK_LIST_ENTRY) * RegistryHive->BlockListSize);
ExFreePool(RegistryHive->BlockList);
}
- RegistryHive->BlockList = tmpBlockList;
- RegistryHive->BlockList[RegistryHive->BlockListSize] = tmpBin;
- RegistryHive->BlockListSize++;
+ RegistryHive->BlockList = BlockList;
+ for (i = 0; i < BlockCount; i++)
+ {
+ RegistryHive->BlockList[RegistryHive->BlockListSize + i].Block =
+ (PVOID)((ULONG_PTR)tmpBin + (i * REG_BLOCK_SIZE));
+ RegistryHive->BlockList[RegistryHive->BlockListSize + i].Bin = tmpBin;
+ }
+ RegistryHive->BlockListSize += BlockCount;
/* Initialize a free block in this heap : */
tmpBlock = (PCELL_HEADER)((ULONG_PTR) tmpBin + REG_HBIN_DATA_OFFSET);
- tmpBlock->CellSize = (REG_BLOCK_SIZE - REG_HBIN_DATA_OFFSET);
+ tmpBlock->CellSize = (BinSize - REG_HBIN_DATA_OFFSET);
+
+ /* Calculate bitmap size in bytes (always a multiple of 32 bits) */
+ BitmapSize = ROUND_UP(RegistryHive->BlockListSize, sizeof(ULONG) * 8) / 8;
/* Grow bitmap if necessary */
- if (IsVolatileHive(RegistryHive) &&
- (RegistryHive->BlockListSize % (sizeof(ULONG) * 8) == 0))
+ if (!IsNoFileHive(RegistryHive) &&
+ BitmapSize > RegistryHive->DirtyBitMap.SizeOfBitMap / 8)
{
PULONG BitmapBuffer;
- ULONG BitmapSize;
DPRINT("Grow hive bitmap\n");
- /* 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);
BitmapBuffer = (PULONG)ExAllocatePool(PagedPool,
RtlZeroMemory(BitmapBuffer, BitmapSize);
RtlCopyMemory(BitmapBuffer,
RegistryHive->DirtyBitMap.Buffer,
- RegistryHive->DirtyBitMap.SizeOfBitMap);
+ RegistryHive->DirtyBitMap.SizeOfBitMap / 8);
ExFreePool(RegistryHive->BitmapBuffer);
RegistryHive->BitmapBuffer = BitmapBuffer;
RtlInitializeBitMap(&RegistryHive->DirtyBitMap,
*NewBlock = (PVOID) tmpBlock;
if (NewBlockOffset)
- *NewBlockOffset = tmpBin->BlockOffset + REG_HBIN_DATA_OFFSET;
+ *NewBlockOffset = tmpBin->BinOffset + REG_HBIN_DATA_OFFSET;
/* Mark new bin dirty */
CmiMarkBinDirty(RegistryHive,
- tmpBin->BlockOffset);
+ tmpBin->BinOffset);
return STATUS_SUCCESS;
}
NTSTATUS
-CmiAllocateBlock(PREGISTRY_HIVE RegistryHive,
- PVOID *Block,
- LONG BlockSize,
- BLOCK_OFFSET * pBlockOffset)
+CmiAllocateCell (PREGISTRY_HIVE RegistryHive,
+ LONG CellSize,
+ PVOID *Cell,
+ BLOCK_OFFSET *CellOffset)
{
- PCELL_HEADER NewBlock;
- NTSTATUS Status;
- PHBIN pBin;
+ PCELL_HEADER NewCell;
+ PHBIN Bin;
ULONG i;
PVOID Temp;
-
- Status = STATUS_SUCCESS;
+ NTSTATUS Status;
/* Round to 16 bytes multiple */
- BlockSize = (BlockSize + sizeof(DWORD) + 15) & 0xfffffff0;
+ CellSize = ROUND_UP(CellSize, 16);
/* Handle volatile hives first */
if (IsPointerHive(RegistryHive))
{
- NewBlock = ExAllocatePool(NonPagedPool, BlockSize);
-
- if (NewBlock == NULL)
- {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- }
- else
+ NewCell = ExAllocatePool(NonPagedPool, CellSize);
+ if (NewCell == NULL)
{
- RtlZeroMemory(NewBlock, BlockSize);
- NewBlock->CellSize = BlockSize;
- *Block = NewBlock;
- if (pBlockOffset)
- *pBlockOffset = (BLOCK_OFFSET) NewBlock;
+ return STATUS_INSUFFICIENT_RESOURCES;
}
+
+ RtlZeroMemory (NewCell,
+ CellSize);
+ NewCell->CellSize = -CellSize;
+
+ *Cell = NewCell;
+ if (CellOffset != NULL)
+ *CellOffset = (BLOCK_OFFSET) NewCell;
}
else
{
/* first search in free blocks */
- NewBlock = NULL;
+ NewCell = NULL;
for (i = 0; i < RegistryHive->FreeListSize; i++)
{
- if (RegistryHive->FreeList[i]->CellSize >= BlockSize)
+ if (RegistryHive->FreeList[i]->CellSize >= CellSize)
{
- NewBlock = RegistryHive->FreeList[i];
- if (pBlockOffset)
- *pBlockOffset = RegistryHive->FreeListOffset[i];
+ NewCell = RegistryHive->FreeList[i];
+ if (CellOffset != NULL)
+ *CellOffset = RegistryHive->FreeListOffset[i];
/* Update time of heap */
- Temp = CmiGetBlock(RegistryHive, RegistryHive->FreeListOffset[i], &pBin);
+ Temp = CmiGetCell (RegistryHive,
+ RegistryHive->FreeListOffset[i],
+ &Bin);
if (Temp == NULL)
{
DPRINT("CmiGetBlock() failed\n");
return STATUS_UNSUCCESSFUL;
}
- if (Temp)
- {
- NtQuerySystemTime((PTIME) &pBin->DateModified);
- CmiMarkBlockDirty(RegistryHive, RegistryHive->FreeListOffset[i]);
- }
+ KeQuerySystemTime(&Bin->DateModified);
+ CmiMarkBlockDirty(RegistryHive, RegistryHive->FreeListOffset[i]);
if ((i + 1) < RegistryHive->FreeListSize)
{
}
/* Need to extend hive file : */
- if (NewBlock == NULL)
+ if (NewCell == NULL)
{
- /* Add a new block */
- Status = CmiAddBin(RegistryHive, (PVOID *) &NewBlock , pBlockOffset);
+ /* Add a new bin */
+ Status = CmiAddBin(RegistryHive,
+ ((CellSize + sizeof(HBIN) - 1) / REG_BLOCK_SIZE) + 1,
+ (PVOID *)&NewCell,
+ CellOffset);
+ if (!NT_SUCCESS(Status))
+ return Status;
}
- if (NT_SUCCESS(Status))
- {
- *Block = NewBlock;
-
- /* Split the block in two parts */
- if (NewBlock->CellSize > BlockSize)
- {
- NewBlock = (PCELL_HEADER) ((ULONG_PTR) NewBlock+BlockSize);
- NewBlock->CellSize = ((PCELL_HEADER) (*Block))->CellSize - BlockSize;
- CmiAddFree(RegistryHive,
- NewBlock,
- *pBlockOffset + BlockSize,
- TRUE);
- CmiMarkBlockDirty(RegistryHive,
- *pBlockOffset + BlockSize);
- }
- else if (NewBlock->CellSize < BlockSize)
- {
- return(STATUS_UNSUCCESSFUL);
- }
+ *Cell = NewCell;
- RtlZeroMemory(*Block, BlockSize);
- ((PCELL_HEADER) (*Block))->CellSize = -BlockSize;
+ /* Split the block in two parts */
+ if (NewCell->CellSize > CellSize)
+ {
+ NewCell = (PCELL_HEADER) ((ULONG_PTR) NewCell + CellSize);
+ NewCell->CellSize = ((PCELL_HEADER) (*Cell))->CellSize - CellSize;
+ CmiAddFree(RegistryHive,
+ NewCell,
+ *CellOffset + CellSize,
+ TRUE);
+ CmiMarkBlockDirty(RegistryHive,
+ *CellOffset + CellSize);
+ }
+ else if (NewCell->CellSize < CellSize)
+ {
+ return STATUS_UNSUCCESSFUL;
}
+
+ RtlZeroMemory(*Cell,
+ CellSize);
+ ((PCELL_HEADER) (*Cell))->CellSize = -CellSize;
}
- return(Status);
+ return STATUS_SUCCESS;
}
NTSTATUS
-CmiDestroyBlock(PREGISTRY_HIVE RegistryHive,
- PVOID Block,
- BLOCK_OFFSET Offset)
+CmiDestroyCell (PREGISTRY_HIVE RegistryHive,
+ PVOID Cell,
+ BLOCK_OFFSET CellOffset)
{
NTSTATUS Status;
PHBIN pBin;
if (IsPointerHive(RegistryHive))
{
- ExFreePool(Block);
+ ExFreePool(Cell);
}
else
{
- PCELL_HEADER pFree = Block;
+ PCELL_HEADER pFree = Cell;
if (pFree->CellSize < 0)
pFree->CellSize = -pFree->CellSize;
/* Clear block (except the block size) */
- RtlZeroMemory(((PVOID)pFree) + sizeof(ULONG),
+ RtlZeroMemory(((char*)pFree) + sizeof(ULONG),
pFree->CellSize - sizeof(ULONG));
/* Add block to the list of free blocks */
- CmiAddFree(RegistryHive, Block, Offset, TRUE);
+ CmiAddFree(RegistryHive, Cell, CellOffset, TRUE);
/* Update time of heap */
- if (!IsVolatileHive(RegistryHive) && CmiGetBlock(RegistryHive, Offset,&pBin))
- NtQuerySystemTime((PTIME) &pBin->DateModified);
+ if (!IsNoFileHive(RegistryHive) && CmiGetCell (RegistryHive, CellOffset,&pBin))
+ KeQuerySystemTime(&pBin->DateModified);
- CmiMarkBlockDirty(RegistryHive, Offset);
+ CmiMarkBlockDirty(RegistryHive, CellOffset);
}
return Status;
}
+PVOID
+CmiGetCell (PREGISTRY_HIVE RegistryHive,
+ BLOCK_OFFSET CellOffset,
+ PHBIN *Bin)
+{
+ PHBIN pBin;
+
+ if (Bin != NULL)
+ {
+ *Bin = NULL;
+ }
+
+ if (CellOffset == (BLOCK_OFFSET)-1)
+ {
+ return NULL;
+ }
+
+ if (IsPointerHive (RegistryHive))
+ {
+ return (PVOID)CellOffset;
+ }
+
+ if (CellOffset > RegistryHive->BlockListSize * REG_BLOCK_SIZE)
+ {
+ DPRINT1("CellOffset exceeds valid range (%lu > %lu)\n",
+ CellOffset, RegistryHive->BlockListSize * REG_BLOCK_SIZE);
+ return NULL;
+ }
+
+ pBin = RegistryHive->BlockList[CellOffset / REG_BLOCK_SIZE].Bin;
+ if (pBin == NULL)
+ {
+ return NULL;
+ }
+
+ if (Bin != NULL)
+ {
+ *Bin = pBin;
+ }
+
+ return((PVOID)((ULONG_PTR)pBin + (CellOffset - pBin->BinOffset)));
+}
+
+
static BOOLEAN
CmiMergeFree(PREGISTRY_HIVE RegistryHive,
PCELL_HEADER FreeBlock,
DPRINT("CmiMergeFree(Block %lx Offset %lx Size %lx) called\n",
FreeBlock, FreeOffset, FreeBlock->CellSize);
- CmiGetBlock(RegistryHive,
+ CmiGetCell (RegistryHive,
FreeOffset,
&Bin);
DPRINT("Bin %p\n", Bin);
if (Bin == NULL)
return(FALSE);
- BinOffset = Bin->BlockOffset;
- BinSize = Bin->BlockSize;
+ BinOffset = Bin->BinOffset;
+ BinSize = Bin->BinSize;
DPRINT("Bin %p Offset %lx Size %lx\n", Bin, BinOffset, BinSize);
for (i = 0; i < RegistryHive->FreeListSize; i++)
LONG maxInd;
LONG medInd;
- assert(RegistryHive);
- assert(FreeBlock);
+ ASSERT(RegistryHive);
+ ASSERT(FreeBlock);
DPRINT("FreeBlock %.08lx FreeOffset %.08lx\n",
FreeBlock, FreeOffset);
}
-PVOID
-CmiGetBlock(PREGISTRY_HIVE RegistryHive,
- BLOCK_OFFSET BlockOffset,
- PHBIN * ppBin)
-{
- PHBIN pBin;
-
- if (ppBin)
- *ppBin = NULL;
-
- if (BlockOffset == (BLOCK_OFFSET)-1)
- {
- return NULL;
- }
-
- if (IsPointerHive (RegistryHive))
- {
- return (PVOID)BlockOffset;
- }
- else
- {
- if (BlockOffset > RegistryHive->BlockListSize * 4096)
- {
- DPRINT1("BlockOffset exceeds valid range (%lu > %lu)\n",
- BlockOffset, RegistryHive->BlockListSize * 4096);
- return NULL;
- }
- pBin = RegistryHive->BlockList[BlockOffset / 4096];
- if (ppBin)
- *ppBin = pBin;
- return((PVOID)((ULONG_PTR)pBin + (BlockOffset - pBin->BlockOffset)));
- }
-}
-
-
VOID
CmiMarkBlockDirty(PREGISTRY_HIVE RegistryHive,
BLOCK_OFFSET BlockOffset)
ULONG BlockNumber;
ULONG BlockCount;
- if (IsVolatileHive(RegistryHive))
+ if (IsNoFileHive(RegistryHive))
return;
DPRINT("CmiMarkBlockDirty(Offset 0x%lx)\n", (ULONG)BlockOffset);
- BlockNumber = (ULONG)BlockOffset / 4096;
+ BlockNumber = (ULONG)BlockOffset / REG_BLOCK_SIZE;
- Cell = CmiGetBlock(RegistryHive,
+ Cell = CmiGetCell (RegistryHive,
BlockOffset,
NULL);
if (CellSize < 0)
CellSize = -CellSize;
- BlockCount = (ROUND_UP(BlockOffset + CellSize, 4096) - ROUND_DOWN(BlockOffset, 4096)) / 4096;
+ BlockCount = (ROUND_UP(BlockOffset + CellSize, REG_BLOCK_SIZE) -
+ ROUND_DOWN(BlockOffset, REG_BLOCK_SIZE)) / REG_BLOCK_SIZE;
DPRINT(" BlockNumber %lu Size %lu (%s) BlockCount %lu\n",
BlockNumber,
ULONG BlockCount;
PHBIN Bin;
- if (IsVolatileHive(RegistryHive))
+ if (IsNoFileHive(RegistryHive))
return;
DPRINT("CmiMarkBinDirty(Offset 0x%lx)\n", (ULONG)BinOffset);
- BlockNumber = (ULONG)BinOffset / 4096;
+ BlockNumber = (ULONG)BinOffset / REG_BLOCK_SIZE;
- Bin = RegistryHive->BlockList[BlockNumber];
+ Bin = RegistryHive->BlockList[BlockNumber].Bin;
- BlockCount = Bin->BlockSize / 4096;
+ BlockCount = Bin->BinSize / REG_BLOCK_SIZE;
- DPRINT(" BlockNumber %lu Size %lu BlockCount %lu\n",
+ DPRINT(" BlockNumber %lu BinSize %lu BlockCount %lu\n",
BlockNumber,
- Bin->BlockSize,
+ Bin->BinSize,
BlockCount);
RegistryHive->HiveDirty = TRUE;
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));
}
BOOLEAN
CmiComparePackedNames(IN PUNICODE_STRING Name,
- IN PCHAR NameBuffer,
+ IN PUCHAR NameBuffer,
IN USHORT NameBufferSize,
IN BOOLEAN NamePacked)
{
VOID
CmiCopyPackedName(PWCHAR NameBuffer,
- PCHAR PackedNameBuffer,
+ PUCHAR PackedNameBuffer,
ULONG PackedNameSize)
{
ULONG i;
PWCHAR UnicodeName;
USHORT i;
- DPRINT1("Flags: %hx\n", KeyCell->Flags);
+ DPRINT("Flags: %hx\n", KeyCell->Flags);
if (KeyCell->Flags & REG_KEY_NAME_PACKED)
{
PWCHAR UnicodeName;
USHORT i;
- DPRINT1("Flags: %hx\n", KeyCell->Flags);
+ DPRINT("Flags: %hx\n", KeyCell->Flags);
if (KeyCell->Flags & REG_KEY_NAME_PACKED)
{
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 = CmiAllocateCell (DstHive,
+ NewKeyCellSize,
+ (PVOID) &NewKeyCell,
+ &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->RootKeyOffset = NewKeyCellOffset;
+
+ /* Copy class name */
+ if (SrcKeyCell->ClassNameOffset != (BLOCK_OFFSET) -1)
+ {
+ PDATA_CELL SrcClassNameCell;
+ PDATA_CELL NewClassNameCell;
+ BLOCK_OFFSET NewClassNameOffset;
+
+ SrcClassNameCell = CmiGetCell (SrcHive, SrcKeyCell->ClassNameOffset, NULL),
+
+ NewKeyCell->ClassSize = SrcKeyCell->ClassSize;
+ Status = CmiAllocateCell (DstHive,
+ sizeof(CELL_HEADER) + NewKeyCell->ClassSize,
+ (PVOID)&NewClassNameCell,
+ &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 = CmiAllocateHashTableCell (DstHive,
+ &NewHashTableCell,
+ &NewHashTableOffset,
+ NewHashTableSize);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1 ("CmiAllocateHashTableBlock() failed (Status %lx)\n", Status);
+ return Status;
+ }
+ NewKeyCell->HashTableOffset = NewHashTableOffset;
+ }
+ else
+ {
+ NewHashTableCell = NULL;
+ }
+
+ /* 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 = CmiAllocateCell (DstHive,
+ NewValueListCellSize,
+ (PVOID)&NewValueListCell,
+ &NewKeyCell->ValueListOffset);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1 ("CmiAllocateBlock() failed (Status %lx)\n", Status);
+ return Status;
+ }
+
+ RtlZeroMemory (NewValueListCell,
+ NewValueListCellSize);
+
+ /* Copy values */
+ SrcValueListCell = CmiGetCell (SrcHive, SrcKeyCell->ValueListOffset, NULL);
+ for (i = 0; i < SrcKeyCell->NumberOfValues; i++)
+ {
+ /* Copy value cell */
+ SrcValueCell = CmiGetCell (SrcHive, SrcValueListCell->ValueOffset[i], NULL);
+
+ NewValueCellSize = sizeof(VALUE_CELL) + SrcValueCell->NameSize;
+ Status = CmiAllocateCell (DstHive,
+ NewValueCellSize,
+ (PVOID*) &NewValueCell,
+ &ValueCellOffset);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1 ("CmiAllocateBlock() failed (Status %lx)\n", Status);
+ return Status;
+ }
+
+ NewValueListCell->ValueOffset[i] = ValueCellOffset;
+ RtlCopyMemory (NewValueCell,
+ SrcValueCell,
+ NewValueCellSize);
+
+ /* Copy value data cell */
+ if (SrcValueCell->DataSize > (LONG) sizeof(PVOID))
+ {
+ SrcValueDataCell = CmiGetCell (SrcHive, SrcValueCell->DataOffset, NULL);
+
+ Status = CmiAllocateCell (DstHive,
+ sizeof(CELL_HEADER) + SrcValueCell->DataSize,
+ (PVOID*) &NewValueDataCell,
+ &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 = CmiGetCell (SrcHive,
+ SrcKeyCell->HashTableOffset,
+ NULL);
+
+ for (i = 0; i < SrcKeyCell->NumberOfSubKeys; i++)
+ {
+ SrcHashRecord = &SrcHashTableCell->Table[i];
+ SrcSubKeyCell = CmiGetCell (SrcHive, SrcHashRecord->KeyOffset, NULL);
+
+ /* Allocate and copy key cell */
+ NewSubKeyCellSize = sizeof(KEY_CELL) + SrcSubKeyCell->NameSize;
+ Status = CmiAllocateCell (DstHive,
+ NewSubKeyCellSize,
+ (PVOID)&NewSubKeyCell,
+ &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 = CmiGetCell (SrcHive,
+ SrcSubKeyCell->ClassNameOffset,
+ NULL),
+
+ NewSubKeyCell->ClassSize = SrcSubKeyCell->ClassSize;
+ Status = CmiAllocateCell (DstHive,
+ sizeof(CELL_HEADER) + NewSubKeyCell->ClassSize,
+ (PVOID)&NewClassNameCell,
+ &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 = (ULONGLONG)0;
+ Status = ZwWriteFile (FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ Hive->HiveHeader,
+ sizeof(HIVE_HEADER),
+ &FileOffset,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1 ("ZwWriteFile() 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].Block;
+ DPRINT ("BlockPtr %p\n", BlockPtr);
+
+ FileOffset.QuadPart = (ULONGLONG)(BlockIndex + 1) * (ULONGLONG)REG_BLOCK_SIZE;
+ DPRINT ("File offset %I64x\n", FileOffset.QuadPart);
+
+ /* Write hive block */
+ Status = ZwWriteFile (FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ BlockPtr,
+ REG_BLOCK_SIZE,
+ &FileOffset,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1 ("ZwWriteFile() failed (Status %lx)\n", Status);
+ return Status;
+ }
+ }
+
+ Status = ZwFlushBuffersFile (FileHandle,
+ &IoStatusBlock);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1 ("ZwFlushBuffersFile() failed (Status %lx)\n", Status);
+ }
+
+ DPRINT ("CmiSaveTempHive() done\n");
+
+ return Status;
+}
+
/* EOF */