* UPDATE HISTORY:
*/
-#ifdef WIN32_REGDBG
-#include "cm_win32.h"
-#else
#include <ddk/ntddk.h>
#include <ddk/ntifs.h>
#include <roscfg.h>
#include <string.h>
#include <internal/pool.h>
#include <internal/registry.h>
+#include <reactos/bugcodes.h>
#define NDEBUG
#include <internal/debug.h>
#include "cm.h"
-#endif
+
+
+/* uncomment to enable hive checks (incomplete and probably buggy) */
+// #define HIVE_CHECK
+
+/* 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;
+static ULONG
+CmiCalcChecksum(PULONG Buffer);
+
/* FUNCTIONS ****************************************************************/
VOID
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->Version = 1;
Header->Unused3 = 1;
Header->Unused4 = 3;
Header->Unused5 = 0;
{
assert(RootKeyCell);
RtlZeroMemory(RootKeyCell, sizeof(KEY_CELL));
-#ifdef WIN32_REGDBG
- RootKeyCell->CellSize = -(LONG)sizeof(KEY_CELL);
-#else
RootKeyCell->CellSize = -sizeof(KEY_CELL);
-#endif
RootKeyCell->Id = REG_KEY_CELL_ID;
RootKeyCell->Type = REG_ROOT_KEY_CELL_TYPE;
- ZwQuerySystemTime((PTIME) &RootKeyCell->LastWriteTime);
+ NtQuerySystemTime((PTIME) &RootKeyCell->LastWriteTime);
RootKeyCell->ParentKeyOffset = 0;
RootKeyCell->NumberOfSubKeys = 0;
RootKeyCell->HashTableOffset = -1;
assert(Header->Unused7 == 1);
}
- }
+ }
}
}
-NTSTATUS
+#if 0
+static NTSTATUS
CmiPopulateHive(HANDLE FileHandle)
{
IO_STATUS_BLOCK IoStatusBlock;
// Add free blocks so we don't need to expand
// the file for a while
- for (i = 0; i < 50; i++)
+ for (i = 1; i < 50; i++)
{
// Block offset of this bin
- BinCell->BlockOffset = (2 + i) * REG_BLOCK_SIZE;
+ BinCell->BlockOffset = i * REG_BLOCK_SIZE;
FileOffset.u.HighPart = 0;
- FileOffset.u.LowPart = (2 + i) * REG_BLOCK_SIZE;
+ FileOffset.u.LowPart = (i + 1) * REG_BLOCK_SIZE;
- Status = ZwWriteFile(FileHandle,
+ Status = NtWriteFile(FileHandle,
NULL,
NULL,
NULL,
return Status;
}
+#endif
-NTSTATUS
+static NTSTATUS
CmiCreateNewRegFile(HANDLE FileHandle)
{
IO_STATUS_BLOCK IoStatusBlock;
/* The rest of the block is free */
FreeCell->CellSize = REG_BLOCK_SIZE - (REG_HBIN_DATA_OFFSET + sizeof(KEY_CELL));
- Status = ZwWriteFile(FileHandle,
+ Status = NtWriteFile(FileHandle,
NULL,
NULL,
NULL,
assertmsg(NT_SUCCESS(Status), ("Status: 0x%X\n", Status));
-#if 1
+ if (!NT_SUCCESS(Status))
+ {
+ return(Status);
+ }
+
+#if 0
if (NT_SUCCESS(Status))
{
CmiPopulateHive(FileHandle);
}
#endif
- return Status;
+ Status = NtFlushBuffersFile(FileHandle,
+ &IoStatusBlock);
+
+ return(Status);
}
-NTSTATUS
-CmiInitPermanentRegistryHive(PREGISTRY_HIVE RegistryHive,
- PWSTR Filename,
- BOOLEAN CreateNew)
+#ifdef HIVE_CHECK
+static NTSTATUS
+CmiCheckAndFixHive(PREGISTRY_HIVE RegistryHive)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ FILE_STANDARD_INFORMATION fsi;
+ IO_STATUS_BLOCK IoStatusBlock;
+ HANDLE HiveHandle = INVALID_HANDLE_VALUE;
+ HANDLE LogHandle = INVALID_HANDLE_VALUE;
+ PHIVE_HEADER HiveHeader = NULL;
+ PHIVE_HEADER LogHeader = NULL;
+ LARGE_INTEGER FileOffset;
+ ULONG FileSize;
+ ULONG BufferSize;
+ ULONG BitmapSize;
+ RTL_BITMAP BlockBitMap;
+ NTSTATUS Status;
+
+ DPRINT("CmiCheckAndFixHive() called\n");
+
+ /* Try to open the hive file */
+ InitializeObjectAttributes(&ObjectAttributes,
+ &RegistryHive->HiveFileName,
+ 0,
+ NULL,
+ NULL);
+
+ Status = NtCreateFile(&HiveHandle,
+ FILE_READ_DATA | FILE_READ_ATTRIBUTES,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ NULL,
+ FILE_ATTRIBUTE_NORMAL,
+ 0,
+ FILE_OPEN,
+ FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
+ NULL,
+ 0);
+ if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
+ {
+ return(STATUS_SUCCESS);
+ }
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("NtCreateFile() failed (Status %lx)\n", Status);
+ return(Status);
+ }
+
+ /* Try to open the log file */
+ InitializeObjectAttributes(&ObjectAttributes,
+ &RegistryHive->LogFileName,
+ 0,
+ NULL,
+ NULL);
+
+ Status = NtCreateFile(&LogHandle,
+ FILE_READ_DATA | FILE_READ_ATTRIBUTES,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ NULL,
+ FILE_ATTRIBUTE_NORMAL,
+ 0,
+ FILE_OPEN,
+ FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
+ NULL,
+ 0);
+ if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
+ {
+ LogHandle = INVALID_HANDLE_VALUE;
+ }
+ else if (!NT_SUCCESS(Status))
+ {
+ DPRINT("NtCreateFile() failed (Status %lx)\n", Status);
+ NtClose(HiveHandle);
+ return(Status);
+ }
+
+ /* Allocate hive header */
+ HiveHeader = ExAllocatePool(PagedPool,
+ sizeof(HIVE_HEADER));
+ if (HiveHeader == NULL)
+ {
+ DPRINT("ExAllocatePool() failed\n");
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto ByeBye;
+ }
+
+ /* Read hive base block */
+ FileOffset.QuadPart = 0ULL;
+ Status = NtReadFile(HiveHandle,
+ 0,
+ 0,
+ 0,
+ &IoStatusBlock,
+ HiveHeader,
+ sizeof(HIVE_HEADER),
+ &FileOffset,
+ 0);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("NtReadFile() failed (Status %lx)\n", Status);
+ goto ByeBye;
+ }
+
+ if (LogHandle == INVALID_HANDLE_VALUE)
+ {
+ if (HiveHeader->Checksum != CmiCalcChecksum((PULONG)HiveHeader) ||
+ HiveHeader->UpdateCounter1 != HiveHeader->UpdateCounter2)
+ {
+ /* 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);
+ }
+
+ Status = STATUS_SUCCESS;
+ goto ByeBye;
+ }
+ else
+ {
+ /* Allocate hive header */
+ LogHeader = ExAllocatePool(PagedPool,
+ sizeof(HIVE_HEADER));
+ if (LogHeader == NULL)
+ {
+ DPRINT("ExAllocatePool() failed\n");
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto ByeBye;
+ }
+
+ /* Read log file header */
+ FileOffset.QuadPart = 0ULL;
+ Status = NtReadFile(LogHandle,
+ 0,
+ 0,
+ 0,
+ &IoStatusBlock,
+ LogHeader,
+ sizeof(HIVE_HEADER),
+ &FileOffset,
+ 0);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("NtReadFile() failed (Status %lx)\n", Status);
+ goto ByeBye;
+ }
+
+ /* Check log file header integrity */
+ if (LogHeader->Checksum != CmiCalcChecksum((PULONG)LogHeader) ||
+ LogHeader->UpdateCounter1 != LogHeader->UpdateCounter2)
+ {
+ if (HiveHeader->Checksum != CmiCalcChecksum((PULONG)HiveHeader) ||
+ HiveHeader->UpdateCounter1 != HiveHeader->UpdateCounter2)
+ {
+ DPRINT("Hive file and log file are inconsistent!\n");
+ KeBugCheck(CONFIG_LIST_FAILED);
+ }
+
+ /* Log file damaged but hive is okay */
+ Status = STATUS_SUCCESS;
+ goto ByeBye;
+ }
+
+ if (HiveHeader->UpdateCounter1 == HiveHeader->UpdateCounter2 &&
+ HiveHeader->UpdateCounter1 == LogHeader->UpdateCounter1)
+ {
+ /* Hive and log file are up-to-date */
+ Status = STATUS_SUCCESS;
+ goto ByeBye;
+ }
+
+ /*
+ * Hive needs an update!
+ */
+
+ /* Get file size */
+ Status = NtQueryInformationFile(LogHandle,
+ &IoStatusBlock,
+ &fsi,
+ sizeof(fsi),
+ FileStandardInformation);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("NtQueryInformationFile() 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;
+ BufferSize = sizeof(HIVE_HEADER) +
+ sizeof(ULONG) +
+ BitmapSize;
+ BufferSize = ROUND_UP(BufferSize, 4096);
+
+ /* Reallocate log header block */
+ ExFreePool(LogHeader);
+ LogHeader = ExAllocatePool(PagedPool,
+ BufferSize);
+ if (LogHeader == NULL)
+ {
+ DPRINT("ExAllocatePool() failed\n");
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto ByeBye;
+ }
+
+ /* Read log file header */
+ FileOffset.QuadPart = 0ULL;
+ Status = NtReadFile(LogHandle,
+ 0,
+ 0,
+ 0,
+ &IoStatusBlock,
+ LogHeader,
+ BufferSize,
+ &FileOffset,
+ 0);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("NtReadFile() failed (Status %lx)\n", Status);
+ goto ByeBye;
+ }
+
+ /* Initialize bitmap */
+ RtlInitializeBitMap(&BlockBitMap,
+ (PVOID)((ULONG)LogHeader + 4096 + sizeof(ULONG)),
+ BitmapSize * 8);
+
+ /* FIXME: Update dirty blocks */
+
+
+ /* FIXME: Update hive header */
+
+
+ Status = STATUS_SUCCESS;
+ }
+
+
+ /* Clean up the mess */
+ByeBye:
+ if (HiveHeader != NULL)
+ ExFreePool(HiveHeader);
+
+ if (LogHeader != NULL)
+ ExFreePool(LogHeader);
+
+ if (LogHandle != INVALID_HANDLE_VALUE)
+ NtClose(LogHandle);
+
+ NtClose(HiveHandle);
+
+ return(Status);
+}
+#endif
+
+
+static NTSTATUS
+CmiInitNonVolatileRegistryHive(PREGISTRY_HIVE RegistryHive,
+ PWSTR Filename,
+ BOOLEAN CreateNew)
{
OBJECT_ATTRIBUTES ObjectAttributes;
FILE_STANDARD_INFORMATION fsi;
PHBIN tmpBin;
ULONG i, j;
ULONG BitmapSize;
- PULONG BitmapBuffer;
- DPRINT1("CmiInitPermanentRegistryHive(%p, %S, %d) - Entered.\n", RegistryHive, Filename, CreateNew);
+ DPRINT("CmiInitNonVolatileRegistryHive(%p, %S, %d) called\n",
+ RegistryHive, Filename, CreateNew);
/* Duplicate Filename */
- Status = RtlCreateUnicodeString(&RegistryHive->Filename, Filename);
+ Status = RtlCreateUnicodeString(&RegistryHive->HiveFileName,
+ Filename);
if (!NT_SUCCESS(Status))
{
- DPRINT1("CmiInitPermanentRegistryHive() - Failed 1.\n");
- return Status;
+ DPRINT("RtlCreateUnicodeString() failed (Status %lx)\n", Status);
+ return(Status);
+ }
+
+ /* Create log file name */
+ RegistryHive->LogFileName.Length = (wcslen(Filename) + 4) * sizeof(WCHAR);
+ RegistryHive->LogFileName.MaximumLength = RegistryHive->LogFileName.Length + sizeof(WCHAR);
+ RegistryHive->LogFileName.Buffer = ExAllocatePool(NonPagedPool,
+ RegistryHive->LogFileName.MaximumLength);
+ if (RegistryHive->LogFileName.Buffer == NULL)
+ {
+ RtlFreeUnicodeString(&RegistryHive->HiveFileName);
+ DPRINT("ExAllocatePool() failed\n");
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+ wcscpy(RegistryHive->LogFileName.Buffer,
+ Filename);
+ wcscat(RegistryHive->LogFileName.Buffer,
+ L".log");
+
+#ifdef HIVE_CHECK
+ /* Check and eventually fix a hive */
+ Status = CmiCheckAndFixHive(RegistryHive);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeUnicodeString(&RegistryHive->HiveFileName);
+ RtlFreeUnicodeString(&RegistryHive->LogFileName);
+ DPRINT1("CmiCheckAndFixHive() failed (Status %lx)\n", Status);
+ return(Status);
}
+#endif
InitializeObjectAttributes(&ObjectAttributes,
- &RegistryHive->Filename,
+ &RegistryHive->HiveFileName,
0,
NULL,
NULL);
0);
if (!NT_SUCCESS(Status))
{
- RtlFreeUnicodeString(&RegistryHive->Filename);
- DPRINT1("NtCreateFile() failed (Status %lx)\n", Status);
+ RtlFreeUnicodeString(&RegistryHive->HiveFileName);
+ RtlFreeUnicodeString(&RegistryHive->LogFileName);
+ DPRINT("NtCreateFile() failed (Status %lx)\n", Status);
return(Status);
}
Status = CmiCreateNewRegFile(FileHandle);
if (!NT_SUCCESS(Status))
{
- DPRINT1("CmiCreateNewRegFile() failed (Status %lx)\n", Status);
- RtlFreeUnicodeString(&RegistryHive->Filename);
+ DPRINT("CmiCreateNewRegFile() failed (Status %lx)\n", Status);
+ NtClose(FileHandle);
+ RtlFreeUnicodeString(&RegistryHive->HiveFileName);
+ RtlFreeUnicodeString(&RegistryHive->LogFileName);
return(Status);
}
}
- Status = ObReferenceObjectByHandle(FileHandle,
- FILE_ALL_ACCESS,
- IoFileObjectType,
- UserMode,
- (PVOID*)&RegistryHive->FileObject,
- NULL);
-
- assertmsg(NT_SUCCESS(Status), ("Status: 0x%X\n", Status));
-
- if (!NT_SUCCESS(Status))
- {
- NtClose(FileHandle);
- RtlFreeUnicodeString(&RegistryHive->Filename);
- DPRINT1("CmiInitPermanentRegistryHive() - ObReferenceObjectByHandle Failed with status %x.\n", Status);
- return Status;
- }
-
/* Read hive header */
FileOffset.u.HighPart = 0;
FileOffset.u.LowPart = 0;
assertmsg(NT_SUCCESS(Status), ("Status: 0x%X\n", Status));
if (!NT_SUCCESS(Status))
{
- ObDereferenceObject(RegistryHive->FileObject);
- RtlFreeUnicodeString(&RegistryHive->Filename);
- DPRINT("CmiInitPermanentRegistryHive() - Failed 4.\n");
+ DPRINT("NtReadFile() failed (Status %lx)\n", Status);
+ NtClose(FileHandle);
+ RtlFreeUnicodeString(&RegistryHive->HiveFileName);
+ RtlFreeUnicodeString(&RegistryHive->LogFileName);
return Status;
}
+ /* Read update counter */
+ RegistryHive->UpdateCounter = RegistryHive->HiveHeader->UpdateCounter1;
+
Status = NtQueryInformationFile(FileHandle,
&IoSB,
&fsi,
sizeof(fsi),
FileStandardInformation);
-
assertmsg(NT_SUCCESS(Status), ("Status: 0x%X\n", Status));
-
- if (!NT_SUCCESS(Status))
+ if (!NT_SUCCESS(Status) || fsi.EndOfFile.u.LowPart == 0)
{
- ObDereferenceObject(RegistryHive->FileObject);
- RtlFreeUnicodeString(&RegistryHive->Filename);
- DPRINT("CmiInitPermanentRegistryHive() - Failed 5.\n");
+ DPRINT("NtQueryInformationFile() failed (Status %lx)\n", Status);
+ NtClose(FileHandle);
+ RtlFreeUnicodeString(&RegistryHive->HiveFileName);
+ RtlFreeUnicodeString(&RegistryHive->LogFileName);
return Status;
}
-#if 0
- /* We have a reference to the file object so we don't need the handle anymore */
- ZwClose(FileHandle);
-#endif
-
RegistryHive->FileSize = fsi.EndOfFile.u.LowPart;
-#ifdef WIN32_REGDBG
-// assert(RegistryHive->FileSize);
- if (RegistryHive->FileSize)
- {
- RegistryHive->BlockListSize = (RegistryHive->FileSize / 4096) - 1;
- }
- else
- {
- ObDereferenceObject(RegistryHive->FileObject);
- RtlFreeUnicodeString(&RegistryHive->Filename);
- DPRINT("CmiInitPermanentRegistryHive() - Failed, zero length hive file.\n");
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-#else
RegistryHive->BlockListSize = (RegistryHive->FileSize / 4096) - 1;
-#endif
DPRINT("Space needed for block list describing hive: 0x%x\n",
sizeof(PHBIN *) * RegistryHive->BlockListSize);
if (RegistryHive->BlockList == NULL)
{
ExFreePool(RegistryHive->BlockList);
- ObDereferenceObject(RegistryHive->FileObject);
- RtlFreeUnicodeString(&RegistryHive->Filename);
- DPRINT("CmiInitPermanentRegistryHive() - Failed 6.\n");
+ NtClose(FileHandle);
+ RtlFreeUnicodeString(&RegistryHive->HiveFileName);
+ RtlFreeUnicodeString(&RegistryHive->LogFileName);
+ DPRINT("CmiInitNonVolatileRegistryHive() - Failed 6.\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
-#if 0
- /* Map hive into cache memory (readonly) (skip the base block) */
- FileOffset.u.HighPart = 0;
- FileOffset.u.LowPart = 4096;
- Success = CcMapData(RegistryHive->FileObject, /* File object */
- &FileOffset, /* File offset */
- RegistryHive->FileSize - 4096, /* Region length */
- TRUE, /* Wait if needed */
- &RegistryHive->Bcb, /* OUT: Buffer Control Block */
- (PVOID*) &RegistryHive->BlockList[0]); /* OUT: Mapped data pointer */
-
- assertmsg(Success, ("Success: %d\n", Success));
-
- if (!Success)
- {
- ExFreePool(RegistryHive->BlockList);
- ObDereferenceObject(RegistryHive->FileObject);
- RtlFreeUnicodeString(&RegistryHive->Filename);
- DPRINT("CmiInitPermanentRegistryHive() - Failed 7.\n");
- return Status;
- }
-
-#else
-
RegistryHive->BlockList[0] = ExAllocatePool(PagedPool,
RegistryHive->FileSize - 4096);
-#ifdef WIN32_REGDBG
- RtlZeroMemory(RegistryHive->BlockList[0], RegistryHive->FileSize - 4096);
-#endif
-
if (RegistryHive->BlockList[0] == NULL)
{
ExFreePool(RegistryHive->BlockList);
- ObDereferenceObject(RegistryHive->FileObject);
- RtlFreeUnicodeString(&RegistryHive->Filename);
- DPRINT("CmiInitPermanentRegistryHive() - Failed 8.\n");
+ NtClose(FileHandle);
+ RtlFreeUnicodeString(&RegistryHive->HiveFileName);
+ RtlFreeUnicodeString(&RegistryHive->LogFileName);
+ DPRINT("CmiInitNonVolatileRegistryHive() - Failed 8.\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
FileOffset.u.HighPart = 0;
FileOffset.u.LowPart = 4096;
- DPRINT(" Attempting to ZwReadFile(%d) for %d bytes into %p\n", FileHandle, RegistryHive->FileSize - 4096, (PVOID)RegistryHive->BlockList[0]);
+ DPRINT(" Attempting to NtReadFile(%d) for %d bytes into %p\n",
+ FileHandle, RegistryHive->FileSize - 4096, (PVOID)RegistryHive->BlockList[0]);
Status = NtReadFile(FileHandle,
0,
0,
assertmsg(NT_SUCCESS(Status), ("Status: 0x%X\n", Status));
NtClose(FileHandle);
-#endif
RegistryHive->FreeListSize = 0;
RegistryHive->FreeListMax = 0;
{
Status = CmiAddFree(RegistryHive,
FreeBlock,
- RegistryHive->BlockList[i]->BlockOffset + FreeOffset);
+ RegistryHive->BlockList[i]->BlockOffset + FreeOffset,
+ FALSE);
if (!NT_SUCCESS(Status))
{
BlockOffset += tmpBin->BlockSize;
}
- /* Create block bitmap and clear all bits */
-
+ /*
+ * Create block bitmap and clear all bits
+ */
/* Calculate bitmap size in bytes (always a multiple of 32 bits) */
BitmapSize = ROUND_UP(RegistryHive->BlockListSize, sizeof(ULONG) * 8) / 8;
- DPRINT1("RegistryHive->BlockListSize: %lu\n", RegistryHive->BlockListSize);
- DPRINT1("BitmapSize: %lu Bytes %lu Bits\n", BitmapSize, BitmapSize * 8);
- BitmapBuffer = (PULONG)ExAllocatePool(PagedPool,
- BitmapSize);
+ DPRINT("RegistryHive->BlockListSize: %lu\n", RegistryHive->BlockListSize);
+ DPRINT("BitmapSize: %lu Bytes %lu Bits\n", BitmapSize, BitmapSize * 8);
+
+ /* Allocate bitmap */
+ RegistryHive->BitmapBuffer = (PULONG)ExAllocatePool(PagedPool,
+ BitmapSize);
RtlInitializeBitMap(&RegistryHive->DirtyBitMap,
- BitmapBuffer,
+ RegistryHive->BitmapBuffer,
BitmapSize * 8);
+
+ /* Initialize bitmap */
RtlClearAllBits(&RegistryHive->DirtyBitMap);
RegistryHive->HiveDirty = FALSE;
- DPRINT1("CmiInitPermanentRegistryHive(%p, %S, %d) - Finished.\n", RegistryHive, Filename, CreateNew);
+ DPRINT("CmiInitNonVolatileRegistryHive(%p, %S, %d) - Finished.\n",
+ RegistryHive, Filename, CreateNew);
return(STATUS_SUCCESS);
}
-NTSTATUS
+static NTSTATUS
CmiInitVolatileRegistryHive(PREGISTRY_HIVE RegistryHive)
{
PKEY_CELL RootKeyCell;
- RegistryHive->Flags |= HIVE_VOLATILE;
+ RegistryHive->Flags |= (HIVE_VOLATILE | HIVE_POINTER);
CmiCreateDefaultHiveHeader(RegistryHive->HiveHeader);
-
+
RootKeyCell = (PKEY_CELL) ExAllocatePool(NonPagedPool, sizeof(KEY_CELL));
if (RootKeyCell == NULL)
NTSTATUS
CmiCreateRegistryHive(PWSTR Filename,
- PREGISTRY_HIVE *RegistryHive,
- BOOLEAN CreateNew)
+ PREGISTRY_HIVE *RegistryHive,
+ BOOLEAN CreateNew)
{
PREGISTRY_HIVE Hive;
NTSTATUS Status;
if (Filename != NULL)
{
- Status = CmiInitPermanentRegistryHive(Hive, Filename, CreateNew);
+ Status = CmiInitNonVolatileRegistryHive(Hive, Filename, CreateNew);
}
else
{
ExAcquireResourceExclusiveLite(&CmiHiveListLock, TRUE);
/* Add the new hive to the hive list */
- InsertHeadList(&CmiHiveListHead, &Hive->HiveList);
+ InsertTailList(&CmiHiveListHead, &Hive->HiveList);
/* Release hive list lock */
ExReleaseResourceLite(&CmiHiveListLock);
}
-NTSTATUS
-CmiFlushRegistryHive(PREGISTRY_HIVE RegistryHive)
+static ULONG
+CmiCalcChecksum(PULONG Buffer)
{
- ULONG BlockIndex;
- ULONG BlockOffset;
- PVOID BlockPtr;
- LARGE_INTEGER FileOffset;
+ ULONG Sum = 0;
+ ULONG i;
+
+ for (i = 0; i < 127; i++)
+ Sum += Buffer[i];
+
+ return(Sum);
+}
+
+
+static NTSTATUS
+CmiStartLogUpdate(PREGISTRY_HIVE RegistryHive)
+{
+ FILE_END_OF_FILE_INFORMATION EndOfFileInfo;
+ FILE_ALLOCATION_INFORMATION FileAllocationInfo;
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
HANDLE FileHandle;
+ LARGE_INTEGER FileOffset;
+ ULONG BufferSize;
+ ULONG BitmapSize;
+ PUCHAR Buffer;
+ PUCHAR Ptr;
+ ULONG BlockIndex;
+ PVOID BlockPtr;
NTSTATUS Status;
+ DPRINT("CmiStartLogUpdate() called\n");
+ BitmapSize = ROUND_UP(RegistryHive->BlockListSize, sizeof(ULONG) * 8) / 8;
+ BufferSize = sizeof(HIVE_HEADER) +
+ sizeof(ULONG) +
+ BitmapSize;
+ BufferSize = ROUND_UP(BufferSize, 4096);
+ DPRINT("Bitmap size %lu buffer size: %lu\n", BitmapSize, BufferSize);
- DPRINT("CmiFlushRegistryHive() called\n");
-
- if (RegistryHive->HiveDirty == FALSE)
+ Buffer = (PUCHAR)ExAllocatePool(NonPagedPool, BufferSize);
+ if (Buffer == NULL)
{
- return(STATUS_SUCCESS);
+ DPRINT("ExAllocatePool() failed\n");
+ return(STATUS_INSUFFICIENT_RESOURCES);
}
- DPRINT1("Hive '%wZ' is dirty\n", &RegistryHive->Filename);
-
-
- /* Open hive for writing */
+ /* Open log file for writing */
InitializeObjectAttributes(&ObjectAttributes,
- &RegistryHive->Filename,
+ &RegistryHive->LogFileName,
0,
NULL,
NULL);
NULL,
FILE_ATTRIBUTE_NORMAL,
0,
- FILE_OPEN,
+ FILE_SUPERSEDE,
FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0);
if (!NT_SUCCESS(Status))
{
- DPRINT1("NtCreateFile() failed (Status %lx)\n", Status);
+ DPRINT("NtCreateFile() failed (Status %lx)\n", Status);
+ ExFreePool(Buffer);
return(Status);
}
+ /* Update firt update counter and checksum */
+ RegistryHive->HiveHeader->UpdateCounter1 = RegistryHive->UpdateCounter + 1;
+ RegistryHive->HiveHeader->Checksum = CmiCalcChecksum((PULONG)RegistryHive->HiveHeader);
+ /* Copy hive header */
+ RtlCopyMemory(Buffer,
+ RegistryHive->HiveHeader,
+ sizeof(HIVE_HEADER));
+ Ptr = Buffer + sizeof(HIVE_HEADER);
+ RtlCopyMemory(Ptr,
+ "DIRT",
+ 4);
+ Ptr += 4;
+ RtlCopyMemory(Ptr,
+ RegistryHive->DirtyBitMap.Buffer,
+ BitmapSize);
+
+ /* Write hive block and block bitmap */
+ FileOffset.QuadPart = 0ULL;
+ Status = NtWriteFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ Buffer,
+ BufferSize,
+ &FileOffset,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
+ NtClose(FileHandle);
+ ExFreePool(Buffer);
+ return(Status);
+ }
+ ExFreePool(Buffer);
+
+ /* Write dirty blocks */
+ FileOffset.QuadPart = (ULONGLONG)BufferSize;
BlockIndex = 0;
while (TRUE)
{
- BlockIndex = RtlFindSetBitsAndClear(&RegistryHive->DirtyBitMap,
- 1,
- BlockIndex);
- if (BlockIndex == (ULONG)-1)
+ BlockIndex = RtlFindSetBits(&RegistryHive->DirtyBitMap,
+ 1,
+ BlockIndex);
+ if ((BlockIndex == (ULONG)-1) ||
+ (BlockIndex >= RegistryHive->BlockListSize))
{
DPRINT("No more set bits\n");
+ Status = STATUS_SUCCESS;
break;
}
- DPRINT1("Block %lu is dirty\n", BlockIndex);
-
- BlockOffset = RegistryHive->BlockList[BlockIndex]->BlockOffset;
- DPRINT1("Block offset %lx\n", BlockOffset);
-
- BlockPtr = RegistryHive->BlockList[BlockIndex] + ((BlockIndex * 4096) - BlockOffset);
- DPRINT1("BlockPtr %p\n", BlockPtr);
-
- FileOffset.QuadPart = (ULONGLONG)(BlockIndex + 1) * 4096ULL;
- DPRINT1("File offset %I64x\n", FileOffset.QuadPart);
+ DPRINT("Block %lu is dirty\n", BlockIndex);
+ BlockPtr = RegistryHive->BlockList[BlockIndex];
+ DPRINT("BlockPtr %p\n", BlockPtr);
+ DPRINT("File offset %I64x\n", FileOffset.QuadPart);
/* Write hive block */
Status = NtWriteFile(FileHandle,
return(Status);
}
+ BlockIndex++;
+ FileOffset.QuadPart += 4096ULL;
+ }
+ /* Truncate log file */
+ EndOfFileInfo.EndOfFile.QuadPart = FileOffset.QuadPart;
+ Status = NtSetInformationFile(FileHandle,
+ &IoStatusBlock,
+ &EndOfFileInfo,
+ sizeof(FILE_END_OF_FILE_INFORMATION),
+ FileEndOfFileInformation);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("NtSetInformationFile() failed (Status %lx)\n", Status);
+ NtClose(FileHandle);
+ return(Status);
}
- NtClose(FileHandle);
+ FileAllocationInfo.AllocationSize.QuadPart = FileOffset.QuadPart;
+ Status = NtSetInformationFile(FileHandle,
+ &IoStatusBlock,
+ &FileAllocationInfo,
+ sizeof(FILE_ALLOCATION_INFORMATION),
+ FileAllocationInformation);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("NtSetInformationFile() failed (Status %lx)\n", Status);
+ NtClose(FileHandle);
+ return(Status);
+ }
+ /* Flush the log file */
+ Status = NtFlushBuffersFile(FileHandle,
+ &IoStatusBlock);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("NtFlushBuffersFile() failed (Status %lx)\n", Status);
+ }
- /* Clear dirty flag */
+ NtClose(FileHandle);
+
+ return(Status);
+}
+
+
+static NTSTATUS
+CmiFinishLogUpdate(PREGISTRY_HIVE RegistryHive)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatusBlock;
+ HANDLE FileHandle;
+ LARGE_INTEGER FileOffset;
+ ULONG BufferSize;
+ ULONG BitmapSize;
+ PUCHAR Buffer;
+ PUCHAR Ptr;
+ NTSTATUS Status;
+
+ DPRINT("CmiFinishLogUpdate() called\n");
+
+ BitmapSize = ROUND_UP(RegistryHive->BlockListSize, sizeof(ULONG) * 8) / 8;
+ BufferSize = sizeof(HIVE_HEADER) +
+ sizeof(ULONG) +
+ BitmapSize;
+ BufferSize = ROUND_UP(BufferSize, 4096);
+
+ DPRINT("Bitmap size %lu buffer size: %lu\n", BitmapSize, BufferSize);
+
+ Buffer = (PUCHAR)ExAllocatePool(NonPagedPool, BufferSize);
+ if (Buffer == NULL)
+ {
+ DPRINT("ExAllocatePool() failed\n");
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ /* Open log file for writing */
+ InitializeObjectAttributes(&ObjectAttributes,
+ &RegistryHive->LogFileName,
+ 0,
+ NULL,
+ NULL);
+
+ Status = NtCreateFile(&FileHandle,
+ FILE_ALL_ACCESS,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ NULL,
+ FILE_ATTRIBUTE_NORMAL,
+ 0,
+ FILE_OPEN,
+ FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
+ NULL,
+ 0);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("NtCreateFile() failed (Status %lx)\n", Status);
+ ExFreePool(Buffer);
+ return(Status);
+ }
+
+ /* Update first and second update counter and checksum */
+ RegistryHive->HiveHeader->UpdateCounter1 = RegistryHive->UpdateCounter + 1;
+ RegistryHive->HiveHeader->UpdateCounter2 = RegistryHive->UpdateCounter + 1;
+ RegistryHive->HiveHeader->Checksum = CmiCalcChecksum((PULONG)RegistryHive->HiveHeader);
+
+ /* Copy hive header */
+ RtlCopyMemory(Buffer,
+ RegistryHive->HiveHeader,
+ sizeof(HIVE_HEADER));
+ Ptr = Buffer + sizeof(HIVE_HEADER);
+
+ /* Write empty block bitmap */
+ RtlCopyMemory(Ptr,
+ "DIRT",
+ 4);
+ Ptr += 4;
+ RtlZeroMemory(Ptr,
+ BitmapSize);
+
+ /* Write hive block and block bitmap */
+ FileOffset.QuadPart = 0ULL;
+ Status = NtWriteFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ Buffer,
+ BufferSize,
+ &FileOffset,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
+ NtClose(FileHandle);
+ ExFreePool(Buffer);
+ return(Status);
+ }
+
+ ExFreePool(Buffer);
+
+ /* Flush the log file */
+ Status = NtFlushBuffersFile(FileHandle,
+ &IoStatusBlock);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("NtFlushBuffersFile() failed (Status %lx)\n", Status);
+ }
+
+ NtClose(FileHandle);
+
+ return(Status);
+}
+
+
+static NTSTATUS
+CmiCleanupLogUpdate(PREGISTRY_HIVE RegistryHive)
+{
+ FILE_END_OF_FILE_INFORMATION EndOfFileInfo;
+ FILE_ALLOCATION_INFORMATION FileAllocationInfo;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatusBlock;
+ HANDLE FileHandle;
+ ULONG BufferSize;
+ ULONG BitmapSize;
+ NTSTATUS Status;
+
+ DPRINT("CmiCleanupLogUpdate() called\n");
+
+ BitmapSize = ROUND_UP(RegistryHive->BlockListSize, sizeof(ULONG) * 8) / 8;
+ BufferSize = sizeof(HIVE_HEADER) +
+ sizeof(ULONG) +
+ BitmapSize;
+ BufferSize = ROUND_UP(BufferSize, 4096);
+
+ DPRINT("Bitmap size %lu buffer size: %lu\n", BitmapSize, BufferSize);
+
+ /* Open log file for writing */
+ InitializeObjectAttributes(&ObjectAttributes,
+ &RegistryHive->LogFileName,
+ 0,
+ NULL,
+ NULL);
+
+ Status = NtCreateFile(&FileHandle,
+ FILE_ALL_ACCESS,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ NULL,
+ FILE_ATTRIBUTE_NORMAL,
+ 0,
+ FILE_OPEN,
+ FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
+ NULL,
+ 0);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("NtCreateFile() failed (Status %lx)\n", Status);
+ return(Status);
+ }
+
+ /* Truncate log file */
+ EndOfFileInfo.EndOfFile.QuadPart = (ULONGLONG)BufferSize;
+ Status = NtSetInformationFile(FileHandle,
+ &IoStatusBlock,
+ &EndOfFileInfo,
+ sizeof(FILE_END_OF_FILE_INFORMATION),
+ FileEndOfFileInformation);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("NtSetInformationFile() failed (Status %lx)\n", Status);
+ NtClose(FileHandle);
+ return(Status);
+ }
+
+ FileAllocationInfo.AllocationSize.QuadPart = (ULONGLONG)BufferSize;
+ Status = NtSetInformationFile(FileHandle,
+ &IoStatusBlock,
+ &FileAllocationInfo,
+ sizeof(FILE_ALLOCATION_INFORMATION),
+ FileAllocationInformation);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("NtSetInformationFile() failed (Status %lx)\n", Status);
+ NtClose(FileHandle);
+ return(Status);
+ }
+
+ /* Flush the log file */
+ Status = NtFlushBuffersFile(FileHandle,
+ &IoStatusBlock);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("NtFlushBuffersFile() failed (Status %lx)\n", Status);
+ }
+
+ NtClose(FileHandle);
+
+ return(Status);
+}
+
+
+static NTSTATUS
+CmiStartHiveUpdate(PREGISTRY_HIVE RegistryHive)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatusBlock;
+ HANDLE FileHandle;
+ LARGE_INTEGER FileOffset;
+ ULONG BlockIndex;
+ PVOID BlockPtr;
+ NTSTATUS Status;
+
+ DPRINT("CmiStartHiveUpdate() called\n");
+
+ /* Open hive for writing */
+ InitializeObjectAttributes(&ObjectAttributes,
+ &RegistryHive->HiveFileName,
+ 0,
+ NULL,
+ NULL);
+
+ Status = NtCreateFile(&FileHandle,
+ FILE_ALL_ACCESS,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ NULL,
+ FILE_ATTRIBUTE_NORMAL,
+ 0,
+ FILE_OPEN,
+ FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
+ NULL,
+ 0);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("NtCreateFile() failed (Status %lx)\n", Status);
+ return(Status);
+ }
+
+ /* Update firt update counter and checksum */
+ RegistryHive->HiveHeader->UpdateCounter1 = RegistryHive->UpdateCounter + 1;
+ RegistryHive->HiveHeader->Checksum = CmiCalcChecksum((PULONG)RegistryHive->HiveHeader);
+
+ /* Write hive block */
+ FileOffset.QuadPart = 0ULL;
+ Status = NtWriteFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ RegistryHive->HiveHeader,
+ sizeof(HIVE_HEADER),
+ &FileOffset,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
+ NtClose(FileHandle);
+ return(Status);
+ }
+
+ BlockIndex = 0;
+ while (TRUE)
+ {
+ BlockIndex = RtlFindSetBits(&RegistryHive->DirtyBitMap,
+ 1,
+ BlockIndex);
+ if ((BlockIndex == (ULONG)-1) ||
+ (BlockIndex >= RegistryHive->BlockListSize))
+ {
+ DPRINT("No more set bits\n");
+ Status = STATUS_SUCCESS;
+ break;
+ }
+
+ DPRINT("Block %lu is dirty\n", BlockIndex);
+
+ BlockPtr = RegistryHive->BlockList[BlockIndex];
+ DPRINT("BlockPtr %p\n", BlockPtr);
+
+ FileOffset.QuadPart = (ULONGLONG)(BlockIndex + 1) * 4096ULL;
+ DPRINT("File offset %I64x\n", FileOffset.QuadPart);
+
+ /* Write hive block */
+ Status = NtWriteFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ BlockPtr,
+ REG_BLOCK_SIZE,
+ &FileOffset,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
+ NtClose(FileHandle);
+ return(Status);
+ }
+
+ BlockIndex++;
+ }
+
+ Status = NtFlushBuffersFile(FileHandle,
+ &IoStatusBlock);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("NtFlushBuffersFile() failed (Status %lx)\n", Status);
+ }
+
+ NtClose(FileHandle);
+
+ return(Status);
+}
+
+
+static NTSTATUS
+CmiFinishHiveUpdate(PREGISTRY_HIVE RegistryHive)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatusBlock;
+ LARGE_INTEGER FileOffset;
+ HANDLE FileHandle;
+ NTSTATUS Status;
+
+ DPRINT("CmiFinishHiveUpdate() called\n");
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &RegistryHive->HiveFileName,
+ 0,
+ NULL,
+ NULL);
+
+ Status = NtCreateFile(&FileHandle,
+ FILE_ALL_ACCESS,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ NULL,
+ FILE_ATTRIBUTE_NORMAL,
+ 0,
+ FILE_OPEN,
+ FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
+ NULL,
+ 0);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("NtCreateFile() failed (Status %lx)\n", Status);
+ return(Status);
+ }
+
+ /* Update second update counter and checksum */
+ RegistryHive->HiveHeader->UpdateCounter1 = RegistryHive->UpdateCounter + 1;
+ RegistryHive->HiveHeader->UpdateCounter2 = RegistryHive->UpdateCounter + 1;
+ RegistryHive->HiveHeader->Checksum = CmiCalcChecksum((PULONG)RegistryHive->HiveHeader);
+
+ /* Write hive block */
+ FileOffset.QuadPart = 0ULL;
+ Status = NtWriteFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ RegistryHive->HiveHeader,
+ sizeof(HIVE_HEADER),
+ &FileOffset,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
+ NtClose(FileHandle);
+ return(Status);
+ }
+
+ Status = NtFlushBuffersFile(FileHandle,
+ &IoStatusBlock);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("NtFlushBuffersFile() failed (Status %lx)\n", Status);
+ }
+
+ NtClose(FileHandle);
+
+ return(Status);
+}
+
+
+NTSTATUS
+CmiFlushRegistryHive(PREGISTRY_HIVE RegistryHive)
+{
+ NTSTATUS Status;
+
+ DPRINT("CmiFlushRegistryHive() called\n");
+
+ if (RegistryHive->HiveDirty == FALSE)
+ {
+ return(STATUS_SUCCESS);
+ }
+
+ DPRINT("Hive '%wZ' is dirty\n",
+ &RegistryHive->HiveFileName);
+ DPRINT("Log file: '%wZ'\n",
+ &RegistryHive->LogFileName);
+
+ /* Update hive header modification time */
+ NtQuerySystemTime((PTIME)&RegistryHive->HiveHeader->DateModified);
+
+ /* Start log update */
+ Status = CmiStartLogUpdate(RegistryHive);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("CmiStartLogUpdate() failed (Status %lx)\n", Status);
+ return(Status);
+ }
+
+ /* Finish log update */
+ Status = CmiFinishLogUpdate(RegistryHive);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("CmiFinishLogUpdate() failed (Status %lx)\n", Status);
+ return(Status);
+ }
+
+ /* Start hive update */
+ Status = CmiStartHiveUpdate(RegistryHive);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("CmiStartHiveUpdate() failed (Status %lx)\n", Status);
+ return(Status);
+ }
+
+ /* Finish the hive update */
+ Status = CmiFinishHiveUpdate(RegistryHive);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("CmiFinishHiveUpdate() failed (Status %lx)\n", Status);
+ return(Status);
+ }
+
+ /* Cleanup log update */
+ Status = CmiCleanupLogUpdate(RegistryHive);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("CmiFinishLogUpdate() failed (Status %lx)\n", Status);
+ return(Status);
+ }
+
+ /* Increment hive update counter */
+ RegistryHive->UpdateCounter++;
+
+ /* Clear dirty bitmap and dirty flag */
+ RtlClearAllBits(&RegistryHive->DirtyBitMap);
RegistryHive->HiveDirty = FALSE;
DPRINT("CmiFlushRegistryHive() done\n");
ULONG
CmiGetMaxNameLength(PREGISTRY_HIVE RegistryHive,
- PKEY_CELL KeyCell)
+ PKEY_CELL KeyCell)
{
PHASH_TABLE_CELL HashBlock;
PKEY_CELL CurSubKeyCell;
HashBlock = CmiGetBlock(RegistryHive, KeyCell->HashTableOffset, NULL);
if (HashBlock == NULL)
{
+ DPRINT("CmiGetBlock() failed\n");
return 0;
}
for (i = 0; i < HashBlock->HashTableSize; i++)
{
- if (HashBlock->Table[i].KeyOffset != 0)
- {
- CurSubKeyCell = CmiGetBlock(RegistryHive,
- HashBlock->Table[i].KeyOffset,
- NULL);
- if (MaxName < CurSubKeyCell->NameSize)
- {
- MaxName = CurSubKeyCell->NameSize;
- }
- CmiReleaseBlock(RegistryHive, CurSubKeyCell);
- }
+ if (HashBlock->Table[i].KeyOffset != 0)
+ {
+ CurSubKeyCell = CmiGetBlock(RegistryHive,
+ HashBlock->Table[i].KeyOffset,
+ NULL);
+ if (CurSubKeyCell == NULL)
+ {
+ DPRINT("CmiGetBlock() failed\n");
+ return 0;
+ }
+
+ if (MaxName < CurSubKeyCell->NameSize)
+ {
+ MaxName = CurSubKeyCell->NameSize;
+ }
+ }
}
- CmiReleaseBlock(RegistryHive, HashBlock);
-
return MaxName;
}
ULONG
CmiGetMaxClassLength(PREGISTRY_HIVE RegistryHive,
- PKEY_CELL KeyCell)
+ PKEY_CELL KeyCell)
{
PHASH_TABLE_CELL HashBlock;
PKEY_CELL CurSubKeyCell;
HashBlock = CmiGetBlock(RegistryHive, KeyCell->HashTableOffset, NULL);
if (HashBlock == NULL)
{
+ DPRINT("CmiGetBlock() failed\n");
return 0;
}
for (i = 0; i < HashBlock->HashTableSize; i++)
{
if (HashBlock->Table[i].KeyOffset != 0)
- {
- CurSubKeyCell = CmiGetBlock(RegistryHive,
- HashBlock->Table[i].KeyOffset,
- NULL);
- if (MaxClass < CurSubKeyCell->ClassSize)
- {
- MaxClass = CurSubKeyCell->ClassSize;
- }
- CmiReleaseBlock(RegistryHive, CurSubKeyCell);
- }
- }
+ {
+ CurSubKeyCell = CmiGetBlock(RegistryHive,
+ HashBlock->Table[i].KeyOffset,
+ NULL);
+ if (CurSubKeyCell == NULL)
+ {
+ DPRINT("CmiGetBlock() failed\n");
+ return 0;
+ }
- CmiReleaseBlock(RegistryHive, HashBlock);
+ if (MaxClass < CurSubKeyCell->ClassSize)
+ {
+ MaxClass = CurSubKeyCell->ClassSize;
+ }
+ }
+ }
return MaxClass;
}
-ULONG
+ULONG
CmiGetMaxValueNameLength(PREGISTRY_HIVE RegistryHive,
- PKEY_CELL KeyCell)
+ PKEY_CELL KeyCell)
{
PVALUE_LIST_CELL ValueListCell;
PVALUE_CELL CurValueCell;
VERIFY_KEY_CELL(KeyCell);
- ValueListCell = CmiGetBlock(RegistryHive, KeyCell->ValuesOffset, NULL);
MaxValueName = 0;
+ ValueListCell = CmiGetBlock(RegistryHive,
+ KeyCell->ValuesOffset,
+ NULL);
if (ValueListCell == NULL)
{
+ DPRINT("CmiGetBlock() failed\n");
return 0;
}
for (i = 0; i < KeyCell->NumberOfValues; i++)
{
- CurValueCell = CmiGetBlock(RegistryHive,
- ValueListCell->Values[i],
- NULL);
+ CurValueCell = CmiGetBlock (RegistryHive,
+ ValueListCell->Values[i],
+ NULL);
+ if (CurValueCell == NULL)
+ {
+ DPRINT("CmiGetBlock() failed\n");
+ }
+
if (CurValueCell != NULL &&
MaxValueName < CurValueCell->NameSize)
{
MaxValueName = CurValueCell->NameSize;
}
- CmiReleaseBlock(RegistryHive, CurValueCell);
}
- CmiReleaseBlock(RegistryHive, ValueListCell);
-
return MaxValueName;
}
-ULONG
+ULONG
CmiGetMaxValueDataLength(PREGISTRY_HIVE RegistryHive,
- PKEY_CELL KeyCell)
+ PKEY_CELL KeyCell)
{
PVALUE_LIST_CELL ValueListCell;
PVALUE_CELL CurValueCell;
VERIFY_KEY_CELL(KeyCell);
- ValueListCell = CmiGetBlock(RegistryHive, KeyCell->ValuesOffset, NULL);
MaxValueData = 0;
+ ValueListCell = CmiGetBlock(RegistryHive, KeyCell->ValuesOffset, NULL);
if (ValueListCell == NULL)
{
return 0;
{
MaxValueData = CurValueCell->DataSize & LONG_MAX;
}
- CmiReleaseBlock(RegistryHive, CurValueCell);
}
- CmiReleaseBlock(RegistryHive, ValueListCell);
-
return MaxValueData;
}
NTSTATUS
CmiScanForSubKey(IN PREGISTRY_HIVE RegistryHive,
- IN PKEY_CELL KeyCell,
- OUT PKEY_CELL *SubKeyCell,
- OUT BLOCK_OFFSET *BlockOffset,
- IN PCHAR KeyName,
- IN ACCESS_MASK DesiredAccess,
- IN ULONG Attributes)
+ IN PKEY_CELL KeyCell,
+ OUT PKEY_CELL *SubKeyCell,
+ OUT BLOCK_OFFSET *BlockOffset,
+ IN PCHAR KeyName,
+ IN ACCESS_MASK DesiredAccess,
+ IN ULONG Attributes)
{
PHASH_TABLE_CELL HashBlock;
PKEY_CELL CurSubKeyCell;
- WORD KeyLength;
+ USHORT KeyLength;
ULONG i;
VERIFY_KEY_CELL(KeyCell);
assert(RegistryHive);
- KeyLength = strlen(KeyName);
+ *SubKeyCell = NULL;
+
+ /* The key does not have any subkeys */
+ if (KeyCell->HashTableOffset == (BLOCK_OFFSET)-1)
+ {
+ return STATUS_SUCCESS;
+ }
+ /* Get hash table */
HashBlock = CmiGetBlock(RegistryHive, KeyCell->HashTableOffset, NULL);
- *SubKeyCell = NULL;
if (HashBlock == NULL)
{
- return STATUS_SUCCESS;
+ DPRINT("CmiGetBlock() failed\n");
+ return STATUS_UNSUCCESSFUL;
}
- for (i = 0; (i < KeyCell->NumberOfSubKeys)
- && (i < HashBlock->HashTableSize); i++)
+ KeyLength = strlen(KeyName);
+ for (i = 0; (i < KeyCell->NumberOfSubKeys) && (i < HashBlock->HashTableSize); i++)
{
if (Attributes & OBJ_CASE_INSENSITIVE)
- {
- if ((HashBlock->Table[i].KeyOffset != 0) &&
- (HashBlock->Table[i].KeyOffset != (ULONG_PTR)-1) &&
- (_strnicmp(KeyName, (PCHAR) &HashBlock->Table[i].HashValue, 4) == 0))
- {
- CurSubKeyCell = CmiGetBlock(RegistryHive,
- HashBlock->Table[i].KeyOffset,
- NULL);
+ {
+ if ((HashBlock->Table[i].KeyOffset != 0) &&
+ (HashBlock->Table[i].KeyOffset != (ULONG_PTR)-1) &&
+ (_strnicmp(KeyName, (PCHAR) &HashBlock->Table[i].HashValue, 4) == 0))
+ {
+ CurSubKeyCell = CmiGetBlock(RegistryHive,
+ HashBlock->Table[i].KeyOffset,
+ NULL);
+ if (CurSubKeyCell == NULL)
+ {
+ DPRINT("CmiGetBlock() failed\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+
if ((CurSubKeyCell->NameSize == KeyLength)
&& (_strnicmp(KeyName, CurSubKeyCell->Name, KeyLength) == 0))
{
*BlockOffset = HashBlock->Table[i].KeyOffset;
break;
}
- else
- {
- CmiReleaseBlock(RegistryHive, CurSubKeyCell);
- }
}
- }
+ }
else
- {
- if (HashBlock->Table[i].KeyOffset != 0 &&
- HashBlock->Table[i].KeyOffset != (ULONG_PTR) -1 &&
- !strncmp(KeyName, (PCHAR) &HashBlock->Table[i].HashValue, 4))
- {
- CurSubKeyCell = CmiGetBlock(RegistryHive,
- HashBlock->Table[i].KeyOffset,NULL);
+ {
+ if (HashBlock->Table[i].KeyOffset != 0 &&
+ HashBlock->Table[i].KeyOffset != (ULONG_PTR) -1 &&
+ !strncmp(KeyName, (PCHAR) &HashBlock->Table[i].HashValue, 4))
+ {
+ CurSubKeyCell = CmiGetBlock(RegistryHive,
+ HashBlock->Table[i].KeyOffset,
+ NULL);
+ if (CurSubKeyCell == NULL)
+ {
+ DPRINT("CmiGetBlock() failed\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+
if (CurSubKeyCell->NameSize == KeyLength
&& !_strnicmp(KeyName, CurSubKeyCell->Name, KeyLength))
{
*BlockOffset = HashBlock->Table[i].KeyOffset;
break;
}
- else
- {
- CmiReleaseBlock(RegistryHive, CurSubKeyCell);
- }
}
- }
+ }
}
-
- CmiReleaseBlock(RegistryHive, HashBlock);
-
+
return STATUS_SUCCESS;
}
NewBlockSize = sizeof(KEY_CELL) + NameSize;
Status = CmiAllocateBlock(RegistryHive,
- (PVOID) &NewKeyCell,
- NewBlockSize,
- &NKBOffset);
-
+ (PVOID) &NewKeyCell,
+ NewBlockSize,
+ &NKBOffset);
if (NewKeyCell == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
SubKey->KeyCell = NewKeyCell;
SubKey->BlockOffset = NKBOffset;
- /* Don't modify hash table if key is volatile and parent is not */
- if (IsVolatileHive(RegistryHive) && (!IsVolatileHive(Parent->RegistryHive)))
+ /* 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)))
{
return(Status);
}
else
{
HashBlock = CmiGetBlock(RegistryHive, KeyCell->HashTableOffset, NULL);
+ if (HashBlock == NULL)
+ {
+ DPRINT("CmiGetBlock() failed\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+
if (((KeyCell->NumberOfSubKeys + 1) >= HashBlock->HashTableSize))
{
BLOCK_OFFSET HTOffset;
PKEY_OBJECT SubKey)
{
PHASH_TABLE_CELL HashBlock;
+ PVALUE_LIST_CELL ValueList;
+ PVALUE_CELL ValueCell;
+ PDATA_CELL DataCell;
+ ULONG i;
+
+ DPRINT("CmiRemoveSubKey() called\n");
+
+ /* Remove all values */
+ if (SubKey->KeyCell->NumberOfValues != 0)
+ {
+ /* Get pointer to the value list cell */
+ ValueList = CmiGetBlock(RegistryHive,
+ SubKey->KeyCell->ValuesOffset,
+ NULL);
+ if (ValueList == NULL)
+ {
+ DPRINT("CmiGetBlock() failed\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ if (ValueList != NULL)
+ {
+ /* Enumerate all values */
+ for (i = 0; i < SubKey->KeyCell->NumberOfValues; i++)
+ {
+ /* Get pointer to value cell */
+ ValueCell = CmiGetBlock(RegistryHive,
+ ValueList->Values[i],
+ NULL);
+ if (ValueCell != 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]);
+ }
+ }
+ }
+
+ /* Destroy value list cell */
+ CmiDestroyBlock(RegistryHive,
+ ValueList,
+ SubKey->KeyCell->ValuesOffset);
- DPRINT1("CmiRemoveSubKey() called\n");
+ SubKey->KeyCell->NumberOfValues = 0;
+ SubKey->KeyCell->ValuesOffset = -1;
+ }
/* Remove the key from the parent key's hash block */
- if (ParentKey->KeyCell->HashTableOffset != -1)
+ if (ParentKey->KeyCell->HashTableOffset != (BLOCK_OFFSET) -1)
{
- DPRINT1("ParentKey HashTableOffset %lx\n", ParentKey->KeyCell->HashTableOffset)
+ DPRINT("ParentKey HashTableOffset %lx\n", ParentKey->KeyCell->HashTableOffset)
HashBlock = CmiGetBlock(RegistryHive,
ParentKey->KeyCell->HashTableOffset,
NULL);
- DPRINT1("ParentKey HashBlock %p\n", HashBlock)
+ if (HashBlock == NULL)
+ {
+ DPRINT("CmiGetBlock() failed\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+ DPRINT("ParentKey HashBlock %p\n", HashBlock)
if (HashBlock != NULL)
{
CmiRemoveKeyFromHashTable(RegistryHive,
}
/* Remove the key's hash block */
- if (SubKey->KeyCell->HashTableOffset != -1)
+ if (SubKey->KeyCell->HashTableOffset != (BLOCK_OFFSET) -1)
{
- DPRINT1("SubKey HashTableOffset %lx\n", SubKey->KeyCell->HashTableOffset)
+ DPRINT("SubKey HashTableOffset %lx\n", SubKey->KeyCell->HashTableOffset)
HashBlock = CmiGetBlock(RegistryHive,
SubKey->KeyCell->HashTableOffset,
NULL);
- DPRINT1("SubKey HashBlock %p\n", HashBlock)
+ if (HashBlock == NULL)
+ {
+ DPRINT("CmiGetBlock() failed\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+ DPRINT("SubKey HashBlock %p\n", HashBlock)
if (HashBlock != NULL)
{
CmiDestroyBlock(RegistryHive,
/* Decrement the number of the parent key's sub keys */
if (ParentKey != NULL)
{
- DPRINT1("ParentKey %p\n", ParentKey)
+ DPRINT("ParentKey %p\n", ParentKey)
ParentKey->KeyCell->NumberOfSubKeys--;
- NtQuerySystemTime((PTIME)&ParentKey->KeyCell->LastWriteTime);
- CmiMarkBlockDirty(RegistryHive,
- ParentKey->BlockOffset);
/* Remove the parent key's hash table */
if (ParentKey->KeyCell->NumberOfSubKeys == 0)
{
- DPRINT1("FIXME: Remove parent key hash table\n")
-
+ DPRINT("ParentKey HashTableOffset %lx\n", ParentKey->KeyCell->HashTableOffset)
+ HashBlock = CmiGetBlock(RegistryHive,
+ ParentKey->KeyCell->HashTableOffset,
+ NULL);
+ if (HashBlock == NULL)
+ {
+ DPRINT("CmiGetBlock() failed\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+ DPRINT("ParentKey HashBlock %p\n", HashBlock)
+ if (HashBlock != NULL)
+ {
+ CmiDestroyBlock(RegistryHive,
+ HashBlock,
+ ParentKey->KeyCell->HashTableOffset);
+ ParentKey->KeyCell->HashTableOffset = -1;
+ }
}
+
+ NtQuerySystemTime((PTIME)&ParentKey->KeyCell->LastWriteTime);
+ CmiMarkBlockDirty(RegistryHive,
+ ParentKey->BlockOffset);
}
/* Destroy key cell */
SubKey->BlockOffset = -1;
SubKey->KeyCell = NULL;
- /* FIXME: Merge free blocks within the Bin */
-
return(STATUS_SUCCESS);
}
NTSTATUS
CmiScanKeyForValue(IN PREGISTRY_HIVE RegistryHive,
- IN PKEY_CELL KeyCell,
- IN PUNICODE_STRING ValueName,
- OUT PVALUE_CELL *ValueCell,
- OUT BLOCK_OFFSET *VBOffset)
+ IN PKEY_CELL KeyCell,
+ IN PUNICODE_STRING ValueName,
+ OUT PVALUE_CELL *ValueCell,
+ OUT BLOCK_OFFSET *VBOffset)
{
PVALUE_LIST_CELL ValueListCell;
PVALUE_CELL CurValueCell;
ULONG i;
- ValueListCell = CmiGetBlock(RegistryHive, KeyCell->ValuesOffset, NULL);
-
*ValueCell = NULL;
+ /* The key does not have any values */
+ if (KeyCell->ValuesOffset == (BLOCK_OFFSET)-1)
+ {
+ return STATUS_SUCCESS;
+ }
+
+ ValueListCell = CmiGetBlock(RegistryHive, KeyCell->ValuesOffset, NULL);
if (ValueListCell == NULL)
{
DPRINT("ValueListCell is NULL\n");
- return STATUS_SUCCESS;
+ return STATUS_UNSUCCESSFUL;
}
VERIFY_VALUE_LIST_CELL(ValueListCell);
CurValueCell = CmiGetBlock(RegistryHive,
ValueListCell->Values[i],
NULL);
+ if (CurValueCell == NULL)
+ {
+ DPRINT("CmiGetBlock() failed\n");
+ return STATUS_UNSUCCESSFUL;
+ }
if ((CurValueCell != NULL) &&
CmiComparePackedNames(ValueName,
CurValueCell->Name,
CurValueCell->NameSize,
CurValueCell->Flags & REG_VALUE_NAME_PACKED))
- {
- *ValueCell = CurValueCell;
- if (VBOffset)
- *VBOffset = ValueListCell->Values[i];
- //DPRINT("Found value %s\n", ValueName);
- break;
- }
- CmiReleaseBlock(RegistryHive, CurValueCell);
+ {
+ *ValueCell = CurValueCell;
+ if (VBOffset)
+ *VBOffset = ValueListCell->Values[i];
+ //DPRINT("Found value %s\n", ValueName);
+ break;
+ }
}
- CmiReleaseBlock(RegistryHive, ValueListCell);
-
return STATUS_SUCCESS;
}
NTSTATUS
CmiGetValueFromKeyByIndex(IN PREGISTRY_HIVE RegistryHive,
- IN PKEY_CELL KeyCell,
- IN ULONG Index,
- OUT PVALUE_CELL *ValueCell)
+ IN PKEY_CELL KeyCell,
+ IN ULONG Index,
+ OUT PVALUE_CELL *ValueCell)
{
PVALUE_LIST_CELL ValueListCell;
PVALUE_CELL CurValueCell;
- ValueListCell = CmiGetBlock(RegistryHive, KeyCell->ValuesOffset, NULL);
-
*ValueCell = NULL;
- if (ValueListCell == NULL)
+ if (KeyCell->ValuesOffset == (BLOCK_OFFSET)-1)
{
return STATUS_NO_MORE_ENTRIES;
}
- VERIFY_VALUE_LIST_CELL(ValueListCell);
-
if (Index >= KeyCell->NumberOfValues)
{
return STATUS_NO_MORE_ENTRIES;
}
- CurValueCell = CmiGetBlock(RegistryHive,
- ValueListCell->Values[Index],
- NULL);
- if (CurValueCell != NULL)
+ ValueListCell = CmiGetBlock(RegistryHive, KeyCell->ValuesOffset, NULL);
+ if (ValueListCell == NULL)
+ {
+ DPRINT("CmiGetBlock() failed\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ VERIFY_VALUE_LIST_CELL(ValueListCell);
+
+
+ CurValueCell = CmiGetBlock(RegistryHive,
+ ValueListCell->Values[Index],
+ NULL);
+ if (CurValueCell == NULL)
{
- *ValueCell = CurValueCell;
+ DPRINT("CmiGetBlock() failed\n");
+ return STATUS_UNSUCCESSFUL;
}
- CmiReleaseBlock(RegistryHive, CurValueCell);
- CmiReleaseBlock(RegistryHive, ValueListCell);
+ *ValueCell = CurValueCell;
return STATUS_SUCCESS;
}
NTSTATUS
CmiAddValueToKey(IN PREGISTRY_HIVE RegistryHive,
- IN PKEY_CELL KeyCell,
- IN PUNICODE_STRING ValueName,
- OUT PVALUE_CELL *pValueCell,
- OUT BLOCK_OFFSET *pVBOffset)
+ IN PKEY_CELL KeyCell,
+ IN PUNICODE_STRING ValueName,
+ OUT PVALUE_CELL *pValueCell,
+ OUT BLOCK_OFFSET *pVBOffset)
{
PVALUE_LIST_CELL NewValueListCell;
PVALUE_LIST_CELL ValueListCell;
NTSTATUS Status;
Status = CmiAllocateValueCell(RegistryHive,
- &NewValueCell,
- &VBOffset,
- ValueName);
- *pVBOffset = VBOffset;
-
+ &NewValueCell,
+ &VBOffset,
+ ValueName);
if (!NT_SUCCESS(Status))
{
return Status;
}
+ DPRINT("KeyCell->ValuesOffset %lu\n", (ULONG)KeyCell->ValuesOffset);
+
ValueListCell = CmiGetBlock(RegistryHive, KeyCell->ValuesOffset, NULL);
if (ValueListCell == NULL)
&VLBOffset);
if (!NT_SUCCESS(Status))
- {
- CmiDestroyValueCell(RegistryHive, NewValueCell, VBOffset);
- return Status;
- }
+ {
+ CmiDestroyValueCell(RegistryHive, NewValueCell, VBOffset);
+ return Status;
+ }
KeyCell->ValuesOffset = VLBOffset;
}
- else if ((KeyCell->NumberOfValues
- >= (ULONG) ((LONG) (ValueListCell->CellSize - 4)) / (LONG) sizeof(BLOCK_OFFSET)))
+ else if (KeyCell->NumberOfValues >=
+ (((ULONG)ABS_VALUE(ValueListCell->CellSize) - 4) / sizeof(BLOCK_OFFSET)))
{
Status = CmiAllocateBlock(RegistryHive,
- (PVOID) &NewValueListCell,
- sizeof(BLOCK_OFFSET) * (KeyCell->NumberOfValues + REG_VALUE_LIST_CELL_MULTIPLE),
- &VLBOffset);
-
+ (PVOID) &NewValueListCell,
+ (KeyCell->NumberOfValues + REG_VALUE_LIST_CELL_MULTIPLE) *
+ sizeof(BLOCK_OFFSET),
+ &VLBOffset);
if (!NT_SUCCESS(Status))
- {
- CmiDestroyValueCell(RegistryHive, NewValueCell, VBOffset);
- return Status;
- }
+ {
+ CmiDestroyValueCell(RegistryHive, NewValueCell, VBOffset);
+ return Status;
+ }
RtlCopyMemory(&NewValueListCell->Values[0],
- &ValueListCell->Values[0],
- sizeof(BLOCK_OFFSET) * KeyCell->NumberOfValues);
+ &ValueListCell->Values[0],
+ sizeof(BLOCK_OFFSET) * KeyCell->NumberOfValues);
CmiDestroyBlock(RegistryHive, ValueListCell, KeyCell->ValuesOffset);
KeyCell->ValuesOffset = VLBOffset;
ValueListCell = NewValueListCell;
}
- DPRINT("KeyCell->NumberOfValues %d, ValueListCell->CellSize %d (%d %x)\n",
- KeyCell->NumberOfValues, ValueListCell->CellSize,
- -(ValueListCell->CellSize - 4) / sizeof(BLOCK_OFFSET),
- -(ValueListCell->CellSize - 4) / sizeof(BLOCK_OFFSET));
+ 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));
ValueListCell->Values[KeyCell->NumberOfValues] = VBOffset;
KeyCell->NumberOfValues++;
- CmiReleaseBlock(RegistryHive, ValueListCell);
- CmiReleaseBlock(RegistryHive, NewValueCell);
+
*pValueCell = NewValueCell;
+ *pVBOffset = VBOffset;
return STATUS_SUCCESS;
}
if (ValueListCell == NULL)
{
+ DPRINT("CmiGetBlock() failed\n");
return STATUS_SUCCESS;
}
for (i = 0; i < KeyCell->NumberOfValues; i++)
{
CurValueCell = CmiGetBlock(RegistryHive, ValueListCell->Values[i], NULL);
+ if (CurValueCell == NULL)
+ {
+ DPRINT("CmiGetBlock() failed\n");
+ return STATUS_UNSUCCESSFUL;
+ }
if ((CurValueCell != NULL) &&
CmiComparePackedNames(ValueName,
CurValueCell->Name,
CurValueCell->NameSize,
CurValueCell->Flags & REG_VALUE_NAME_PACKED))
- {
- if ((KeyCell->NumberOfValues - 1) < i)
- {
- RtlCopyMemory(&ValueListCell->Values[i],
- &ValueListCell->Values[i + 1],
- sizeof(BLOCK_OFFSET) * (KeyCell->NumberOfValues - 1 - i));
- }
- else
- {
- RtlZeroMemory(&ValueListCell->Values[i], sizeof(BLOCK_OFFSET));
- }
+ {
+ CmiDestroyValueCell(RegistryHive, CurValueCell, ValueListCell->Values[i]);
- KeyCell->NumberOfValues -= 1;
- CmiDestroyValueCell(RegistryHive, CurValueCell, ValueListCell->Values[i]);
- break;
- }
- CmiReleaseBlock(RegistryHive, CurValueCell);
- }
+ if ((KeyCell->NumberOfValues - 1) < i)
+ {
+ RtlCopyMemory(&ValueListCell->Values[i],
+ &ValueListCell->Values[i + 1],
+ sizeof(BLOCK_OFFSET) * (KeyCell->NumberOfValues - 1 - i));
+ }
+ else
+ {
+ RtlZeroMemory(&ValueListCell->Values[i], sizeof(BLOCK_OFFSET));
+ }
- CmiReleaseBlock(RegistryHive, ValueListCell);
+ KeyCell->NumberOfValues -= 1;
+ break;
+ }
+ }
if (KeyCell->NumberOfValues == 0)
{
PKEY_CELL
CmiGetKeyFromHashByIndex(PREGISTRY_HIVE RegistryHive,
- PHASH_TABLE_CELL HashBlock,
- ULONG Index)
+ PHASH_TABLE_CELL HashBlock,
+ ULONG Index)
{
BLOCK_OFFSET KeyOffset;
PKEY_CELL KeyCell;
if (HashBlock == NULL)
return NULL;
- if (IsVolatileHive(RegistryHive))
+ if (IsPointerHive(RegistryHive))
{
KeyCell = (PKEY_CELL) HashBlock->Table[Index].KeyOffset;
}
KeyOffset = HashBlock->Table[Index].KeyOffset;
KeyCell = CmiGetBlock(RegistryHive, KeyOffset, NULL);
}
- CmiLockBlock(RegistryHive, KeyCell);
return KeyCell;
}
NTSTATUS
CmiAddKeyToHashTable(PREGISTRY_HIVE RegistryHive,
- PHASH_TABLE_CELL HashBlock,
- PKEY_CELL NewKeyCell,
- BLOCK_OFFSET NKBOffset)
+ PHASH_TABLE_CELL HashBlock,
+ PKEY_CELL NewKeyCell,
+ BLOCK_OFFSET NKBOffset)
{
ULONG i;
NTSTATUS
CmiAllocateValueCell(PREGISTRY_HIVE RegistryHive,
- PVALUE_CELL *ValueCell,
- BLOCK_OFFSET *VBOffset,
- IN PUNICODE_STRING ValueName)
+ PVALUE_CELL *ValueCell,
+ BLOCK_OFFSET *VBOffset,
+ IN PUNICODE_STRING ValueName)
{
PVALUE_CELL NewValueCell;
NTSTATUS Status;
NTSTATUS
CmiDestroyValueCell(PREGISTRY_HIVE RegistryHive,
- PVALUE_CELL ValueCell,
- BLOCK_OFFSET VBOffset)
+ PVALUE_CELL ValueCell,
+ BLOCK_OFFSET VBOffset)
{
NTSTATUS Status;
PVOID pBlock;
PHBIN pBin;
+ DPRINT("CmiDestroyValueCell(Cell %p Offset %lx)\n", ValueCell, VBOffset);
+
VERIFY_VALUE_CELL(ValueCell);
- /* First, release data: */
+ /* Destroy the data cell */
if (ValueCell->DataSize > 4)
{
pBlock = CmiGetBlock(RegistryHive, ValueCell->DataOffset, &pBin);
+ if (pBlock == NULL)
+ {
+ DPRINT("CmiGetBlock() failed\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+
Status = CmiDestroyBlock(RegistryHive, pBlock, ValueCell->DataOffset);
if (!NT_SUCCESS(Status))
{
}
/* Update time of heap */
- if (IsPermanentHive(RegistryHive))
- ZwQuerySystemTime((PTIME) &pBin->DateModified);
+ if (!IsVolatileHive(RegistryHive))
+ NtQuerySystemTime((PTIME) &pBin->DateModified);
}
+ /* Destroy the value cell */
Status = CmiDestroyBlock(RegistryHive, ValueCell, VBOffset);
/* Update time of heap */
- if (IsPermanentHive(RegistryHive) && CmiGetBlock(RegistryHive, VBOffset, &pBin))
+ if (!IsVolatileHive(RegistryHive) && CmiGetBlock(RegistryHive, VBOffset, &pBin))
{
- ZwQuerySystemTime((PTIME) &pBin->DateModified);
+ NtQuerySystemTime((PTIME) &pBin->DateModified);
}
return Status;
NTSTATUS
CmiAddBin(PREGISTRY_HIVE RegistryHive,
- PVOID *NewBlock,
- BLOCK_OFFSET *NewBlockOffset)
+ PVOID *NewBlock,
+ BLOCK_OFFSET *NewBlockOffset)
{
PCELL_HEADER tmpBlock;
PHBIN * tmpBlockList;
if (RegistryHive->BlockListSize > 0)
{
- memcpy(tmpBlockList,
- RegistryHive->BlockList,
- sizeof(PHBIN *)*(RegistryHive->BlockListSize));
+ RtlCopyMemory (tmpBlockList,
+ RegistryHive->BlockList,
+ sizeof(PHBIN *)*(RegistryHive->BlockListSize));
ExFreePool(RegistryHive->BlockList);
}
RegistryHive->BlockList = tmpBlockList;
- RegistryHive->BlockList[RegistryHive->BlockListSize++] = tmpBin;
+ RegistryHive->BlockList[RegistryHive->BlockListSize] = tmpBin;
+ RegistryHive->BlockListSize++;
/* Initialize a free block in this heap : */
tmpBlock = (PCELL_HEADER)((ULONG_PTR) tmpBin + REG_HBIN_DATA_OFFSET);
if (IsVolatileHive(RegistryHive) &&
(RegistryHive->BlockListSize % (sizeof(ULONG) * 8) == 0))
{
- DPRINT1("Grow hive bitmap - BlockListSize %lu\n", RegistryHive->BlockListSize);
+ PULONG BitmapBuffer;
+ ULONG BitmapSize;
- /* FIXME */
+ 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,
+ BitmapSize);
+ RtlZeroMemory(BitmapBuffer, BitmapSize);
+ RtlCopyMemory(BitmapBuffer,
+ RegistryHive->DirtyBitMap.Buffer,
+ RegistryHive->DirtyBitMap.SizeOfBitMap);
+ ExFreePool(RegistryHive->BitmapBuffer);
+ RegistryHive->BitmapBuffer = BitmapBuffer;
+ RtlInitializeBitMap(&RegistryHive->DirtyBitMap,
+ RegistryHive->BitmapBuffer,
+ BitmapSize * 8);
}
*NewBlock = (PVOID) tmpBlock;
if (NewBlockOffset)
*NewBlockOffset = tmpBin->BlockOffset + REG_HBIN_DATA_OFFSET;
- /* FIXME: set first dword to block_offset of another free bloc */
+ /* Mark new bin dirty */
+ CmiMarkBinDirty(RegistryHive,
+ tmpBin->BlockOffset);
return STATUS_SUCCESS;
}
PCELL_HEADER NewBlock;
NTSTATUS Status;
PHBIN pBin;
+ ULONG i;
+ PVOID Temp;
Status = STATUS_SUCCESS;
BlockSize = (BlockSize + sizeof(DWORD) + 15) & 0xfffffff0;
/* Handle volatile hives first */
- if (IsVolatileHive(RegistryHive))
+ if (IsPointerHive(RegistryHive))
{
NewBlock = ExAllocatePool(NonPagedPool, BlockSize);
{
RtlZeroMemory(NewBlock, BlockSize);
NewBlock->CellSize = BlockSize;
- CmiLockBlock(RegistryHive, NewBlock);
*Block = NewBlock;
if (pBlockOffset)
*pBlockOffset = (BLOCK_OFFSET) NewBlock;
}
else
{
- ULONG i;
-
/* first search in free blocks */
NewBlock = NULL;
for (i = 0; i < RegistryHive->FreeListSize; i++)
{
if (RegistryHive->FreeList[i]->CellSize >= BlockSize)
{
- PVOID Temp;
-
NewBlock = RegistryHive->FreeList[i];
if (pBlockOffset)
*pBlockOffset = RegistryHive->FreeListOffset[i];
/* Update time of heap */
Temp = CmiGetBlock(RegistryHive, RegistryHive->FreeListOffset[i], &pBin);
+ if (Temp == NULL)
+ {
+ DPRINT("CmiGetBlock() failed\n");
+ return STATUS_UNSUCCESSFUL;
+ }
if (Temp)
{
- ZwQuerySystemTime((PTIME) &pBin->DateModified);
+ NtQuerySystemTime((PTIME) &pBin->DateModified);
CmiMarkBlockDirty(RegistryHive, RegistryHive->FreeListOffset[i]);
}
{
NewBlock = (PCELL_HEADER) ((ULONG_PTR) NewBlock+BlockSize);
NewBlock->CellSize = ((PCELL_HEADER) (*Block))->CellSize - BlockSize;
- CmiAddFree(RegistryHive, NewBlock, *pBlockOffset + BlockSize);
- CmiMarkBlockDirty(RegistryHive, *pBlockOffset + BlockSize);
+ CmiAddFree(RegistryHive,
+ NewBlock,
+ *pBlockOffset + BlockSize,
+ TRUE);
+ CmiMarkBlockDirty(RegistryHive,
+ *pBlockOffset + BlockSize);
}
else if (NewBlock->CellSize < BlockSize)
{
RtlZeroMemory(*Block, BlockSize);
((PCELL_HEADER) (*Block))->CellSize = -BlockSize;
- CmiLockBlock(RegistryHive, *Block);
}
}
NTSTATUS
CmiDestroyBlock(PREGISTRY_HIVE RegistryHive,
- PVOID Block,
- BLOCK_OFFSET Offset)
+ PVOID Block,
+ BLOCK_OFFSET Offset)
{
NTSTATUS Status;
PHBIN pBin;
Status = STATUS_SUCCESS;
- if (IsVolatileHive(RegistryHive))
+ if (IsPointerHive(RegistryHive))
{
- CmiReleaseBlock(RegistryHive, Block);
ExFreePool(Block);
}
else
RtlZeroMemory(((PVOID)pFree) + sizeof(ULONG),
pFree->CellSize - sizeof(ULONG));
- CmiAddFree(RegistryHive, Block, Offset);
- CmiReleaseBlock(RegistryHive, Block);
+ /* Add block to the list of free blocks */
+ CmiAddFree(RegistryHive, Block, Offset, TRUE);
/* Update time of heap */
- if (IsPermanentHive(RegistryHive) && CmiGetBlock(RegistryHive, Offset,&pBin))
- ZwQuerySystemTime((PTIME) &pBin->DateModified);
+ if (!IsVolatileHive(RegistryHive) && CmiGetBlock(RegistryHive, Offset,&pBin))
+ NtQuerySystemTime((PTIME) &pBin->DateModified);
CmiMarkBlockDirty(RegistryHive, Offset);
-
- /* FIXME: Set first dword to block_offset of another free block ? */
- /* FIXME: Concatenate with previous and next block if free */
}
return Status;
}
+static BOOLEAN
+CmiMergeFree(PREGISTRY_HIVE RegistryHive,
+ PCELL_HEADER FreeBlock,
+ BLOCK_OFFSET FreeOffset)
+{
+ BLOCK_OFFSET BlockOffset;
+ BLOCK_OFFSET BinOffset;
+ ULONG BlockSize;
+ ULONG BinSize;
+ PHBIN Bin;
+ ULONG i;
+
+ DPRINT("CmiMergeFree(Block %lx Offset %lx Size %lx) called\n",
+ FreeBlock, FreeOffset, FreeBlock->CellSize);
+
+ CmiGetBlock(RegistryHive,
+ FreeOffset,
+ &Bin);
+ DPRINT("Bin %p\n", Bin);
+ if (Bin == NULL)
+ return(FALSE);
+
+ BinOffset = Bin->BlockOffset;
+ BinSize = Bin->BlockSize;
+ DPRINT("Bin %p Offset %lx Size %lx\n", Bin, BinOffset, BinSize);
+
+ for (i = 0; i < RegistryHive->FreeListSize; i++)
+ {
+ BlockOffset = RegistryHive->FreeListOffset[i];
+ BlockSize = RegistryHive->FreeList[i]->CellSize;
+ if (BlockOffset > BinOffset &&
+ BlockOffset < BinOffset + BinSize)
+ {
+ DPRINT("Free block: Offset %lx Size %lx\n",
+ BlockOffset, BlockSize);
+
+ if ((i < (RegistryHive->FreeListSize - 1)) &&
+ (BlockOffset + BlockSize == FreeOffset) &&
+ (FreeOffset + FreeBlock->CellSize == RegistryHive->FreeListOffset[i + 1]))
+ {
+ DPRINT("Merge current block with previous and next block\n");
+
+ RegistryHive->FreeList[i]->CellSize +=
+ (FreeBlock->CellSize + RegistryHive->FreeList[i + 1]->CellSize);
+
+ FreeBlock->CellSize = 0;
+ RegistryHive->FreeList[i + 1]->CellSize = 0;
+
+
+ if ((i + 2) < RegistryHive->FreeListSize)
+ {
+ RtlMoveMemory(&RegistryHive->FreeList[i + 1],
+ &RegistryHive->FreeList[i + 2],
+ sizeof(RegistryHive->FreeList[0])
+ * (RegistryHive->FreeListSize - i - 2));
+ RtlMoveMemory(&RegistryHive->FreeListOffset[i + 1],
+ &RegistryHive->FreeListOffset[i + 2],
+ sizeof(RegistryHive->FreeListOffset[0])
+ * (RegistryHive->FreeListSize - i - 2));
+ }
+ RegistryHive->FreeListSize--;
+
+ CmiMarkBlockDirty(RegistryHive, BlockOffset);
+
+ return(TRUE);
+ }
+ else if (BlockOffset + BlockSize == FreeOffset)
+ {
+ DPRINT("Merge current block with previous block\n");
+
+ RegistryHive->FreeList[i]->CellSize += FreeBlock->CellSize;
+ FreeBlock->CellSize = 0;
+
+ CmiMarkBlockDirty(RegistryHive, BlockOffset);
+
+ return(TRUE);
+ }
+ else if (FreeOffset + FreeBlock->CellSize == BlockOffset)
+ {
+ DPRINT("Merge current block with next block\n");
+
+ FreeBlock->CellSize += RegistryHive->FreeList[i]->CellSize;
+ RegistryHive->FreeList[i]->CellSize = 0;
+ RegistryHive->FreeList[i] = FreeBlock;
+ RegistryHive->FreeListOffset[i] = FreeOffset;
+
+ CmiMarkBlockDirty(RegistryHive, FreeOffset);
+
+ return(TRUE);
+ }
+ }
+ }
+
+ return(FALSE);
+}
+
+
NTSTATUS
CmiAddFree(PREGISTRY_HIVE RegistryHive,
- PCELL_HEADER FreeBlock,
- BLOCK_OFFSET FreeOffset)
+ PCELL_HEADER FreeBlock,
+ BLOCK_OFFSET FreeOffset,
+ BOOLEAN MergeFreeBlocks)
{
- PCELL_HEADER *tmpList;
- BLOCK_OFFSET *tmpListOffset;
- LONG minInd;
+ PCELL_HEADER *tmpList;
+ BLOCK_OFFSET *tmpListOffset;
+ LONG minInd;
LONG maxInd;
LONG medInd;
assert(RegistryHive);
assert(FreeBlock);
- DPRINT("FreeBlock %.08x FreeOffset %.08x\n",
- FreeBlock, FreeOffset);
-DPRINT("\n");
+ DPRINT("FreeBlock %.08lx FreeOffset %.08lx\n",
+ FreeBlock, FreeOffset);
+
+ /* Merge free blocks */
+ if (MergeFreeBlocks == TRUE)
+ {
+ if (CmiMergeFree(RegistryHive, FreeBlock, FreeOffset))
+ return(STATUS_SUCCESS);
+ }
+
if ((RegistryHive->FreeListSize + 1) > RegistryHive->FreeListMax)
{
-DPRINT("\n");
tmpList = ExAllocatePool(PagedPool,
sizeof(PCELL_HEADER) * (RegistryHive->FreeListMax + 32));
-DPRINT("\n");
-
if (tmpList == NULL)
return STATUS_INSUFFICIENT_RESOURCES;
-DPRINT("\n");
tmpListOffset = ExAllocatePool(PagedPool,
- sizeof(BLOCK_OFFSET *) * (RegistryHive->FreeListMax + 32));
-DPRINT("\n");
+ sizeof(BLOCK_OFFSET) * (RegistryHive->FreeListMax + 32));
if (tmpListOffset == NULL)
{
ExFreePool(tmpList);
return STATUS_INSUFFICIENT_RESOURCES;
}
-DPRINT("\n");
if (RegistryHive->FreeListMax)
{
-DPRINT("\n");
RtlMoveMemory(tmpList,
RegistryHive->FreeList,
sizeof(PCELL_HEADER) * (RegistryHive->FreeListMax));
-DPRINT("\n");
RtlMoveMemory(tmpListOffset,
RegistryHive->FreeListOffset,
- sizeof(BLOCK_OFFSET *) * (RegistryHive->FreeListMax));
-DPRINT("\n");
+ sizeof(BLOCK_OFFSET) * (RegistryHive->FreeListMax));
ExFreePool(RegistryHive->FreeList);
-DPRINT("\n");
ExFreePool(RegistryHive->FreeListOffset);
-DPRINT("\n");
}
-DPRINT("\n");
RegistryHive->FreeList = tmpList;
RegistryHive->FreeListOffset = tmpListOffset;
RegistryHive->FreeListMax += 32;
-DPRINT("\n");
}
-DPRINT("\n");
/* Add new offset to free list, maintaining list in ascending order */
if ((RegistryHive->FreeListSize == 0)
|| (RegistryHive->FreeListOffset[RegistryHive->FreeListSize-1] < FreeOffset))
{
-DPRINT("\n");
/* Add to end of list */
RegistryHive->FreeList[RegistryHive->FreeListSize] = FreeBlock;
RegistryHive->FreeListOffset[RegistryHive->FreeListSize++] = FreeOffset;
}
else if (RegistryHive->FreeListOffset[0] > FreeOffset)
{
-DPRINT("\n");
/* Add to begin of list */
RtlMoveMemory(&RegistryHive->FreeList[1],
&RegistryHive->FreeList[0],
}
else
{
-DPRINT("\n");
/* Search where to insert */
minInd = 0;
maxInd = RegistryHive->FreeListSize - 1;
RegistryHive->FreeListOffset[maxInd] = FreeOffset;
RegistryHive->FreeListSize++;
}
-DPRINT("\n");
return STATUS_SUCCESS;
}
BLOCK_OFFSET BlockOffset,
PHBIN * ppBin)
{
+ PHBIN pBin;
+
if (ppBin)
*ppBin = NULL;
- if ((BlockOffset == 0) || (BlockOffset == (ULONG_PTR) -1))
- return NULL;
+ if (BlockOffset == (BLOCK_OFFSET)-1)
+ {
+ return NULL;
+ }
- if (IsVolatileHive(RegistryHive))
+ if (IsPointerHive (RegistryHive))
{
- return (PVOID) BlockOffset;
+ return (PVOID)BlockOffset;
}
else
{
- PHBIN pBin;
-
+ 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)));
+ return((PVOID)((ULONG_PTR)pBin + (BlockOffset - pBin->BlockOffset)));
}
}
VOID
-CmiLockBlock(PREGISTRY_HIVE RegistryHive,
- PVOID Block)
+CmiMarkBlockDirty(PREGISTRY_HIVE RegistryHive,
+ BLOCK_OFFSET BlockOffset)
{
- if (IsPermanentHive(RegistryHive))
- {
- /* FIXME: Implement */
- }
-}
+ PDATA_CELL Cell;
+ LONG CellSize;
+ ULONG BlockNumber;
+ ULONG BlockCount;
+ if (IsVolatileHive(RegistryHive))
+ return;
-VOID
-CmiReleaseBlock(PREGISTRY_HIVE RegistryHive,
- PVOID Block)
-{
- if (IsPermanentHive(RegistryHive))
- {
- /* FIXME: Implement */
- }
+ DPRINT("CmiMarkBlockDirty(Offset 0x%lx)\n", (ULONG)BlockOffset);
+
+ BlockNumber = (ULONG)BlockOffset / 4096;
+
+ Cell = CmiGetBlock(RegistryHive,
+ BlockOffset,
+ NULL);
+
+ CellSize = Cell->CellSize;
+ if (CellSize < 0)
+ CellSize = -CellSize;
+
+ BlockCount = (ROUND_UP(BlockOffset + CellSize, 4096) - ROUND_DOWN(BlockOffset, 4096)) / 4096;
+
+ DPRINT(" BlockNumber %lu Size %lu (%s) BlockCount %lu\n",
+ BlockNumber,
+ CellSize,
+ (Cell->CellSize < 0) ? "used" : "free",
+ BlockCount);
+
+ RegistryHive->HiveDirty = TRUE;
+ RtlSetBits(&RegistryHive->DirtyBitMap,
+ BlockNumber,
+ BlockCount);
}
VOID
-CmiMarkBlockDirty(PREGISTRY_HIVE RegistryHive,
- BLOCK_OFFSET BlockOffset)
+CmiMarkBinDirty(PREGISTRY_HIVE RegistryHive,
+ BLOCK_OFFSET BinOffset)
{
- ULONG Index;
+ ULONG BlockNumber;
+ ULONG BlockCount;
+ PHBIN Bin;
if (IsVolatileHive(RegistryHive))
- return;
+ return;
+
+ DPRINT("CmiMarkBinDirty(Offset 0x%lx)\n", (ULONG)BinOffset);
+
+ BlockNumber = (ULONG)BinOffset / 4096;
+
+ Bin = RegistryHive->BlockList[BlockNumber];
- Index = (ULONG)BlockOffset / 4096;
+ BlockCount = Bin->BlockSize / 4096;
- DPRINT1("CmiMarkBlockDirty(Offset 0x%lx) Index %lu\n",
- (ULONG)BlockOffset, Index);
+ DPRINT(" BlockNumber %lu Size %lu BlockCount %lu\n",
+ BlockNumber,
+ Bin->BlockSize,
+ BlockCount);
RegistryHive->HiveDirty = TRUE;
RtlSetBits(&RegistryHive->DirtyBitMap,
- Index,
- 1);
+ BlockNumber,
+ BlockCount);
}