Fix splitting of cells (noticed by Hartmut).
[reactos.git] / reactos / ntoskrnl / cm / regfile.c
index f4c7331..85b3409 100644 (file)
@@ -1,20 +1,14 @@
-/*
- * 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>
 
@@ -26,9 +20,6 @@
 
 /* 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;
@@ -41,51 +32,50 @@ CmiCalcChecksum(PULONG Buffer);
 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.u.LowPart = 0;
   Header->DateModified.u.HighPart = 0;
-  Header->Unused3 = 1;
-  Header->Unused4 = 3;
-  Header->Unused5 = 0;
-  Header->Unused6 = 1;
+  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.u.LowPart = 0;
-  BinCell->DateModified.u.HighPart = 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(&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;
@@ -94,30 +84,30 @@ CmiCreateDefaultRootKeyCell(PKEY_CELL RootKeyCell)
 
 
 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
+
+  //BinHeader->DateModified.dwHighDateTime
 
-  //BinCell->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);
     }
 
     }
@@ -130,20 +120,20 @@ CmiVerifyKeyCell(PKEY_CELL KeyCell)
   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;
@@ -154,14 +144,14 @@ CmiVerifyKeyCell(PKEY_CELL KeyCell)
     {
       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;
@@ -170,7 +160,7 @@ CmiVerifyKeyCell(PKEY_CELL KeyCell)
     {
       DbgPrint("NumberOfValues is %d (must not be < 0)\n",
         KeyCell->NumberOfValues);
-      assert(KeyCell->NumberOfValues >= 0);
+      ASSERT(KeyCell->NumberOfValues >= 0);
     }
 
   //KeyCell->ValuesOffset = -1;
@@ -179,7 +169,7 @@ CmiVerifyKeyCell(PKEY_CELL KeyCell)
     {
       DbgPrint("SecurityKeyOffset is %d (must not be < 0)\n",
         KeyCell->SecurityKeyOffset);
-      assert(KeyCell->SecurityKeyOffset >= 0);
+      ASSERT(KeyCell->SecurityKeyOffset >= 0);
     }
 
   //KeyCell->ClassNameOffset = -1;
@@ -204,7 +194,7 @@ CmiVerifyRootKeyCell(PKEY_CELL RootKeyCell)
     {
       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)));
     }
 
     }
@@ -217,20 +207,20 @@ CmiVerifyValueCell(PVALUE_CELL ValueCell)
   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;
@@ -254,7 +244,7 @@ CmiVerifyValueListCell(PVALUE_LIST_CELL ValueListCell)
     {
       DbgPrint("CellSize is %d (must not be 0)\n",
         ValueListCell->CellSize);
-      assert(ValueListCell->CellSize != 0);
+      ASSERT(ValueListCell->CellSize != 0);
     }
 
     }
@@ -271,21 +261,21 @@ CmiVerifyKeyObject(PKEY_OBJECT KeyObject)
     {
       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);
     }
 
     }
@@ -303,42 +293,42 @@ CmiVerifyHiveHeader(PHIVE_HEADER Header)
       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);
     }
 
     }
@@ -365,32 +355,35 @@ CmiCreateNewRegFile(HANDLE FileHandle)
   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,
@@ -402,14 +395,12 @@ CmiCreateNewRegFile(HANDLE FileHandle)
 
   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);
@@ -439,11 +430,11 @@ CmiCheckAndFixHive(PREGISTRY_HIVE RegistryHive)
   /* 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,
@@ -460,18 +451,18 @@ CmiCheckAndFixHive(PREGISTRY_HIVE RegistryHive)
     }
   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,
@@ -488,8 +479,8 @@ CmiCheckAndFixHive(PREGISTRY_HIVE RegistryHive)
     }
   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);
     }
 
@@ -505,7 +496,7 @@ CmiCheckAndFixHive(PREGISTRY_HIVE RegistryHive)
 
   /* Read hive base block */
   FileOffset.QuadPart = 0ULL;
-  Status = NtReadFile(HiveHandle,
+  Status = ZwReadFile(HiveHandle,
                      0,
                      0,
                      0,
@@ -516,7 +507,7 @@ CmiCheckAndFixHive(PREGISTRY_HIVE RegistryHive)
                      0);
   if (!NT_SUCCESS(Status))
     {
-      DPRINT("NtReadFile() failed (Status %lx)\n", Status);
+      DPRINT("ZwReadFile() failed (Status %lx)\n", Status);
       goto ByeBye;
     }
 
@@ -547,7 +538,7 @@ CmiCheckAndFixHive(PREGISTRY_HIVE RegistryHive)
 
       /* Read log file header */
       FileOffset.QuadPart = 0ULL;
-      Status = NtReadFile(LogHandle,
+      Status = ZwReadFile(LogHandle,
                          0,
                          0,
                          0,
@@ -558,7 +549,7 @@ CmiCheckAndFixHive(PREGISTRY_HIVE RegistryHive)
                          0);
       if (!NT_SUCCESS(Status))
        {
-         DPRINT("NtReadFile() failed (Status %lx)\n", Status);
+         DPRINT("ZwReadFile() failed (Status %lx)\n", Status);
          goto ByeBye;
        }
 
@@ -591,24 +582,24 @@ CmiCheckAndFixHive(PREGISTRY_HIVE RegistryHive)
        */
 
       /* 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);
@@ -623,7 +614,7 @@ CmiCheckAndFixHive(PREGISTRY_HIVE RegistryHive)
 
       /* Read log file header */
       FileOffset.QuadPart = 0ULL;
-      Status = NtReadFile(LogHandle,
+      Status = ZwReadFile(LogHandle,
                          0,
                          0,
                          0,
@@ -634,13 +625,13 @@ CmiCheckAndFixHive(PREGISTRY_HIVE RegistryHive)
                          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 */
@@ -662,9 +653,9 @@ ByeBye:
     ExFreePool(LogHeader);
 
   if (LogHandle != INVALID_HANDLE_VALUE)
-    NtClose(LogHandle);
+    ZwClose(LogHandle);
 
-  NtClose(HiveHandle);
+  ZwClose(HiveHandle);
 
   return(Status);
 }
@@ -686,40 +677,42 @@ CmiImportHiveBins(PREGISTRY_HIVE Hive,
     {
       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;
@@ -735,15 +728,16 @@ CmiFreeHiveBins (PREGISTRY_HIVE Hive)
   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;
     }
 }
 
@@ -768,18 +762,18 @@ CmiCreateHiveFreeCellList(PREGISTRY_HIVE Hive)
   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))
@@ -795,8 +789,8 @@ CmiCreateHiveFreeCellList(PREGISTRY_HIVE Hive)
            }
        }
 
-      BlockIndex += Bin->BlockSize / 4096;
-      BlockOffset += Bin->BlockSize;
+      BlockIndex += Bin->BinSize / REG_BLOCK_SIZE;
+      BlockOffset += Bin->BinSize;
     }
 
   return STATUS_SUCCESS;
@@ -854,7 +848,7 @@ CmiInitNonVolatileRegistryHive (PREGISTRY_HIVE RegistryHive,
   ULONG CreateDisposition;
   IO_STATUS_BLOCK IoSB;
   HANDLE FileHandle;
-  HANDLE SectionHandle;
+  PSECTION_OBJECT SectionObject;
   PUCHAR ViewBase;
   ULONG ViewSize;
   NTSTATUS Status;
@@ -864,7 +858,7 @@ CmiInitNonVolatileRegistryHive (PREGISTRY_HIVE RegistryHive,
 
   /* Duplicate Filename */
   Status = RtlCreateUnicodeString(&RegistryHive->HiveFileName,
-                                 Filename);
+                                  Filename);
   if (!NT_SUCCESS(Status))
     {
       DPRINT("RtlCreateUnicodeString() failed (Status %lx)\n", Status);
@@ -874,8 +868,9 @@ CmiInitNonVolatileRegistryHive (PREGISTRY_HIVE RegistryHive,
   /* 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);
@@ -901,12 +896,12 @@ CmiInitNonVolatileRegistryHive (PREGISTRY_HIVE RegistryHive,
 
   InitializeObjectAttributes(&ObjectAttributes,
                             &RegistryHive->HiveFileName,
-                            0,
+                            OBJ_CASE_INSENSITIVE,
                             NULL,
                             NULL);
 
   CreateDisposition = FILE_OPEN_IF;
-  Status = NtCreateFile(&FileHandle,
+  Status = ZwCreateFile(&FileHandle,
                        FILE_ALL_ACCESS,
                        &ObjectAttributes,
                        &IoSB,
@@ -921,7 +916,7 @@ CmiInitNonVolatileRegistryHive (PREGISTRY_HIVE RegistryHive,
     {
       RtlFreeUnicodeString(&RegistryHive->HiveFileName);
       RtlFreeUnicodeString(&RegistryHive->LogFileName);
-      DPRINT("NtCreateFile() failed (Status %lx)\n", Status);
+      DPRINT("ZwCreateFile() failed (Status %lx)\n", Status);
       return(Status);
     }
 
@@ -931,7 +926,7 @@ CmiInitNonVolatileRegistryHive (PREGISTRY_HIVE RegistryHive,
       if (!NT_SUCCESS(Status))
        {
          DPRINT("CmiCreateNewRegFile() failed (Status %lx)\n", Status);
-         NtClose(FileHandle);
+         ZwClose(FileHandle);
          RtlFreeUnicodeString(&RegistryHive->HiveFileName);
          RtlFreeUnicodeString(&RegistryHive->LogFileName);
          return(Status);
@@ -939,17 +934,17 @@ CmiInitNonVolatileRegistryHive (PREGISTRY_HIVE RegistryHive,
     }
 
   /* 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);
@@ -958,8 +953,8 @@ CmiInitNonVolatileRegistryHive (PREGISTRY_HIVE RegistryHive,
   /* Map the hive file */
   ViewBase = NULL;
   ViewSize = 0;
-  Status = NtMapViewOfSection(SectionHandle,
-                             NtCurrentProcess(),
+  Status = MmMapViewOfSection(SectionObject,
+                             PsGetCurrentProcess(),
                              (PVOID*)&ViewBase,
                              0,
                              ViewSize,
@@ -970,10 +965,11 @@ CmiInitNonVolatileRegistryHive (PREGISTRY_HIVE RegistryHive,
                              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);
@@ -983,41 +979,48 @@ CmiInitNonVolatileRegistryHive (PREGISTRY_HIVE RegistryHive,
                 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);
@@ -1045,7 +1048,7 @@ CmiInitNonVolatileRegistryHive (PREGISTRY_HIVE RegistryHive,
   DPRINT("CmiInitNonVolatileRegistryHive(%p, %S) - Finished.\n",
         RegistryHive, Filename);
 
-  return(STATUS_SUCCESS);
+  return STATUS_SUCCESS;
 }
 
 
@@ -1065,7 +1068,7 @@ CmiCreateVolatileHive(PREGISTRY_HIVE *RegistryHive)
   RtlZeroMemory (Hive,
                 sizeof(REGISTRY_HIVE));
 
-  DPRINT("Hive %x\n", Hive);
+  DPRINT("Hive 0x%p\n", Hive);
 
   Hive->HiveHeader = (PHIVE_HEADER)ExAllocatePool (NonPagedPool,
                                                   sizeof(HIVE_HEADER));
@@ -1074,6 +1077,8 @@ CmiCreateVolatileHive(PREGISTRY_HIVE *RegistryHive)
       ExFreePool (Hive);
       return STATUS_INSUFFICIENT_RESOURCES;
     }
+  RtlZeroMemory (Hive->HiveHeader,
+                sizeof(HIVE_HEADER));
 
   Hive->Flags = (HIVE_NO_FILE | HIVE_POINTER);
 
@@ -1089,20 +1094,19 @@ CmiCreateVolatileHive(PREGISTRY_HIVE *RegistryHive)
     }
 
   CmiCreateDefaultRootKeyCell (RootKeyCell);
-  Hive->HiveHeader->RootKeyCell = (BLOCK_OFFSET)RootKeyCell;
-
-  ExInitializeResourceLite (&Hive->HiveResource);
+  Hive->HiveHeader->RootKeyOffset = (BLOCK_OFFSET)RootKeyCell;
 
   /* Acquire hive list lock exclusively */
-  ExAcquireResourceExclusiveLite (&CmiHiveListLock,
-                                 TRUE);
+  KeEnterCriticalRegion();
+  ExAcquireResourceExclusiveLite (&CmiRegistryLock, TRUE);
 
   /* Add the new hive to the hive list */
   InsertTailList (&CmiHiveListHead,
                  &Hive->HiveList);
 
   /* Release hive list lock */
-  ExReleaseResourceLite (&CmiHiveListLock);
+  ExReleaseResourceLite (&CmiRegistryLock);
+  KeLeaveCriticalRegion();
 
   VERIFY_REGISTRY_HIVE (Hive);
 
@@ -1115,7 +1119,7 @@ CmiCreateVolatileHive(PREGISTRY_HIVE *RegistryHive)
 NTSTATUS
 CmiCreateTempHive(PREGISTRY_HIVE *RegistryHive)
 {
-  PHBIN BinCell;
+  PHBIN BinHeader;
   PCELL_HEADER FreeCell;
   PREGISTRY_HIVE Hive;
   NTSTATUS Status;
@@ -1134,7 +1138,7 @@ CmiCreateTempHive(PREGISTRY_HIVE *RegistryHive)
   RtlZeroMemory (Hive,
                 sizeof(REGISTRY_HIVE));
 
-  DPRINT ("Hive %x\n", Hive);
+  DPRINT ("Hive 0x%p\n", Hive);
 
   Hive->HiveHeader = (PHIVE_HEADER)ExAllocatePool (NonPagedPool,
                                                   REG_BLOCK_SIZE);
@@ -1147,7 +1151,7 @@ CmiCreateTempHive(PREGISTRY_HIVE *RegistryHive)
   RtlZeroMemory (Hive->HiveHeader,
                 REG_BLOCK_SIZE);
 
-  DPRINT ("HiveHeader %x\n", Hive->HiveHeader);
+  DPRINT ("HiveHeader 0x%p\n", Hive->HiveHeader);
 
   Hive->Flags = HIVE_NO_FILE;
 
@@ -1160,7 +1164,7 @@ CmiCreateTempHive(PREGISTRY_HIVE *RegistryHive)
 
   /* Allocate hive block list */
   Hive->BlockList = ExAllocatePool (NonPagedPool,
-                                   sizeof(PHBIN *));
+                                   sizeof(PBLOCK_LIST_ENTRY));
   if (Hive->BlockList == NULL)
     {
       DPRINT1 ("Failed to allocate hive block list\n");
@@ -1170,9 +1174,9 @@ CmiCreateTempHive(PREGISTRY_HIVE *RegistryHive)
     }
 
   /* Allocate first Bin */
-  Hive->BlockList[0] = ExAllocatePool (NonPagedPool,
-                                      REG_BLOCK_SIZE);
-  if (Hive->BlockList[0] == NULL)
+  Hive->BlockList[0].Bin = ExAllocatePool (NonPagedPool,
+                                          REG_BLOCK_SIZE);
+  if (Hive->BlockList[0].Bin == NULL)
     {
       DPRINT1 ("Failed to allocate first bin\n");
       ExFreePool(Hive->BlockList);
@@ -1180,51 +1184,50 @@ CmiCreateTempHive(PREGISTRY_HIVE *RegistryHive)
       ExFreePool(Hive);
       return STATUS_INSUFFICIENT_RESOURCES;
     }
+  Hive->BlockList[0].Block = (PVOID)Hive->BlockList[0].Bin;
 
   Hive->FileSize = 2* REG_BLOCK_SIZE;
   Hive->BlockListSize = 1;
   Hive->UpdateCounter = Hive->HiveHeader->UpdateCounter1;
 
 
-  BinCell = (PHBIN)Hive->BlockList[0];
-  FreeCell = (PCELL_HEADER)((ULONG_PTR)BinCell + REG_HBIN_DATA_OFFSET);
+  BinHeader = Hive->BlockList[0].Bin;
+  FreeCell = (PCELL_HEADER)((ULONG_PTR)BinHeader + REG_HBIN_DATA_OFFSET);
 
-  CmiCreateDefaultBinCell (BinCell);
+  CmiCreateDefaultBinHeader (BinHeader);
 
   /* First block */
-  BinCell->BlockOffset = 0;
+  BinHeader->BinOffset = 0;
 
   /* Offset to root key block */
-  Hive->HiveHeader->RootKeyCell = -1;
+  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] == NULL)
+  if (Hive->BlockList[0].Bin == NULL)
     {
       DPRINT1 ("CmiCreateHiveFreeCellList() failed (Status %lx)\n", Status);
-      ExFreePool(Hive->BlockList[0]);
+      ExFreePool(Hive->BlockList[0].Bin);
       ExFreePool(Hive->BlockList);
       ExFreePool(Hive->HiveHeader);
       ExFreePool(Hive);
       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);
 
   /* Release hive list lock */
-  ExReleaseResourceLite (&CmiHiveListLock);
+  ExReleaseResourceLite(&CmiRegistryLock);
+  KeLeaveCriticalRegion();
 
   VERIFY_REGISTRY_HIVE (Hive);
 
@@ -1257,7 +1260,7 @@ CmiLoadHive(IN POBJECT_ATTRIBUTES KeyObjectAttributes,
   RtlZeroMemory (Hive,
                 sizeof(REGISTRY_HIVE));
 
-  DPRINT ("Hive %x\n", Hive);
+  DPRINT ("Hive 0x%p\n", Hive);
   Hive->Flags = (Flags & REG_NO_LAZY_FLUSH) ? HIVE_NO_SYNCH : 0;
 
   Hive->HiveHeader = (PHIVE_HEADER)ExAllocatePool(NonPagedPool,
@@ -1269,6 +1272,9 @@ CmiLoadHive(IN POBJECT_ATTRIBUTES KeyObjectAttributes,
       return STATUS_INSUFFICIENT_RESOURCES;
     }
 
+  RtlZeroMemory (Hive->HiveHeader,
+                sizeof(HIVE_HEADER));
+
   Status = CmiInitNonVolatileRegistryHive (Hive,
                                           FileName->Buffer);
   if (!NT_SUCCESS (Status))
@@ -1279,19 +1285,12 @@ CmiLoadHive(IN POBJECT_ATTRIBUTES KeyObjectAttributes,
       return Status;
     }
 
-  ExInitializeResourceLite (&Hive->HiveResource);
-
   /* Add the new hive to the hive list */
-  ExAcquireResourceExclusiveLite (&CmiHiveListLock,
-                                 TRUE);
   InsertTailList (&CmiHiveListHead,
                  &Hive->HiveList);
-  ExReleaseResourceLite (&CmiHiveListLock);
-
 
   VERIFY_REGISTRY_HIVE(Hive);
 
-
   Status = CmiConnectHive (KeyObjectAttributes,
                           Hive);
   if (!NT_SUCCESS(Status))
@@ -1312,16 +1311,9 @@ CmiRemoveRegistryHive(PREGISTRY_HIVE RegistryHive)
   if (RegistryHive->Flags & HIVE_POINTER)
     return STATUS_UNSUCCESSFUL;
 
-  /* Acquire hive list lock exclusively */
-  ExAcquireResourceExclusiveLite (&CmiHiveListLock,
-                                 TRUE);
-
   /* Remove hive from hive list */
   RemoveEntryList (&RegistryHive->HiveList);
 
-  /* Release hive list lock */
-  ExReleaseResourceLite (&CmiHiveListLock);
-
   /* Release file names */
   RtlFreeUnicodeString (&RegistryHive->HiveFileName);
   RtlFreeUnicodeString (&RegistryHive->LogFileName);
@@ -1333,9 +1325,6 @@ CmiRemoveRegistryHive(PREGISTRY_HIVE RegistryHive)
   ExFreePool (RegistryHive->FreeList);
   ExFreePool (RegistryHive->FreeListOffset);
 
-  /* Release hive resource */
-  ExDeleteResource (&RegistryHive->HiveResource);
-
   /* Release bins and bin list */
   CmiFreeHiveBins (RegistryHive);
   ExFreePool (RegistryHive->BlockList);
@@ -1377,6 +1366,7 @@ CmiStartLogUpdate(PREGISTRY_HIVE RegistryHive)
   PUCHAR Buffer;
   PUCHAR Ptr;
   ULONG BlockIndex;
+  ULONG LastIndex;
   PVOID BlockPtr;
   NTSTATUS Status;
 
@@ -1386,25 +1376,28 @@ CmiStartLogUpdate(PREGISTRY_HIVE RegistryHive)
   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,
@@ -1417,7 +1410,7 @@ CmiStartLogUpdate(PREGISTRY_HIVE RegistryHive)
                        0);
   if (!NT_SUCCESS(Status))
     {
-      DPRINT("NtCreateFile() failed (Status %lx)\n", Status);
+      DPRINT("ZwCreateFile() failed (Status %lx)\n", Status);
       ExFreePool(Buffer);
       return(Status);
     }
@@ -1441,8 +1434,8 @@ CmiStartLogUpdate(PREGISTRY_HIVE RegistryHive)
                BitmapSize);
 
   /* Write hive block and block bitmap */
-  FileOffset.QuadPart = 0ULL;
-  Status = NtWriteFile(FileHandle,
+  FileOffset.QuadPart = (ULONGLONG)0;
+  Status = ZwWriteFile(FileHandle,
                       NULL,
                       NULL,
                       NULL,
@@ -1453,8 +1446,8 @@ CmiStartLogUpdate(PREGISTRY_HIVE RegistryHive)
                       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);
     }
@@ -1463,13 +1456,13 @@ CmiStartLogUpdate(PREGISTRY_HIVE RegistryHive)
   /* 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;
@@ -1478,12 +1471,12 @@ CmiStartLogUpdate(PREGISTRY_HIVE RegistryHive)
 
       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,
@@ -1494,51 +1487,51 @@ CmiStartLogUpdate(PREGISTRY_HIVE RegistryHive)
                           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);
 }
@@ -1563,7 +1556,7 @@ CmiFinishLogUpdate(PREGISTRY_HIVE RegistryHive)
   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);
 
@@ -1577,11 +1570,11 @@ CmiFinishLogUpdate(PREGISTRY_HIVE RegistryHive)
   /* 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,
@@ -1594,7 +1587,7 @@ CmiFinishLogUpdate(PREGISTRY_HIVE RegistryHive)
                        0);
   if (!NT_SUCCESS(Status))
     {
-      DPRINT("NtCreateFile() failed (Status %lx)\n", Status);
+      DPRINT("ZwCreateFile() failed (Status %lx)\n", Status);
       ExFreePool(Buffer);
       return(Status);
     }
@@ -1619,8 +1612,8 @@ CmiFinishLogUpdate(PREGISTRY_HIVE RegistryHive)
                BitmapSize);
 
   /* Write hive block and block bitmap */
-  FileOffset.QuadPart = 0ULL;
-  Status = NtWriteFile(FileHandle,
+  FileOffset.QuadPart = (ULONGLONG)0;
+  Status = ZwWriteFile(FileHandle,
                       NULL,
                       NULL,
                       NULL,
@@ -1631,8 +1624,8 @@ CmiFinishLogUpdate(PREGISTRY_HIVE RegistryHive)
                       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);
     }
@@ -1640,14 +1633,14 @@ CmiFinishLogUpdate(PREGISTRY_HIVE RegistryHive)
   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);
 }
@@ -1671,18 +1664,18 @@ CmiCleanupLogUpdate(PREGISTRY_HIVE RegistryHive)
   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,
@@ -1695,26 +1688,26 @@ CmiCleanupLogUpdate(PREGISTRY_HIVE RegistryHive)
                        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),
@@ -1722,19 +1715,19 @@ CmiCleanupLogUpdate(PREGISTRY_HIVE RegistryHive)
   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);
 }
@@ -1748,6 +1741,7 @@ CmiStartHiveUpdate(PREGISTRY_HIVE RegistryHive)
   HANDLE FileHandle;
   LARGE_INTEGER FileOffset;
   ULONG BlockIndex;
+  ULONG LastIndex;
   PVOID BlockPtr;
   NTSTATUS Status;
 
@@ -1756,11 +1750,11 @@ CmiStartHiveUpdate(PREGISTRY_HIVE RegistryHive)
   /* 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,
@@ -1773,7 +1767,7 @@ CmiStartHiveUpdate(PREGISTRY_HIVE RegistryHive)
                        0);
   if (!NT_SUCCESS(Status))
     {
-      DPRINT("NtCreateFile() failed (Status %lx)\n", Status);
+      DPRINT("ZwCreateFile() failed (Status %lx)\n", Status);
       return(Status);
     }
 
@@ -1782,8 +1776,8 @@ CmiStartHiveUpdate(PREGISTRY_HIVE RegistryHive)
   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,
@@ -1794,19 +1788,19 @@ CmiStartHiveUpdate(PREGISTRY_HIVE RegistryHive)
                       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;
@@ -1815,14 +1809,14 @@ CmiStartHiveUpdate(PREGISTRY_HIVE RegistryHive)
 
       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,
@@ -1833,22 +1827,22 @@ CmiStartHiveUpdate(PREGISTRY_HIVE RegistryHive)
                           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);
 }
@@ -1867,11 +1861,11 @@ CmiFinishHiveUpdate(PREGISTRY_HIVE RegistryHive)
 
   InitializeObjectAttributes(&ObjectAttributes,
                             &RegistryHive->HiveFileName,
-                            0,
+                            OBJ_CASE_INSENSITIVE,
                             NULL,
                             NULL);
 
-  Status = NtCreateFile(&FileHandle,
+  Status = ZwCreateFile(&FileHandle,
                        FILE_ALL_ACCESS,
                        &ObjectAttributes,
                        &IoStatusBlock,
@@ -1884,7 +1878,7 @@ CmiFinishHiveUpdate(PREGISTRY_HIVE RegistryHive)
                        0);
   if (!NT_SUCCESS(Status))
     {
-      DPRINT("NtCreateFile() failed (Status %lx)\n", Status);
+      DPRINT("ZwCreateFile() failed (Status %lx)\n", Status);
       return(Status);
     }
 
@@ -1894,8 +1888,8 @@ CmiFinishHiveUpdate(PREGISTRY_HIVE RegistryHive)
   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,
@@ -1906,19 +1900,19 @@ CmiFinishHiveUpdate(PREGISTRY_HIVE RegistryHive)
                       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);
 }
@@ -1942,7 +1936,7 @@ CmiFlushRegistryHive(PREGISTRY_HIVE RegistryHive)
         &RegistryHive->LogFileName);
 
   /* Update hive header modification time */
-  NtQuerySystemTime(&RegistryHive->HiveHeader->DateModified);
+  KeQuerySystemTime(&RegistryHive->HiveHeader->DateModified);
 
   /* Start log update */
   Status = CmiStartLogUpdate(RegistryHive);
@@ -1998,78 +1992,189 @@ CmiFlushRegistryHive(PREGISTRY_HIVE 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 (MaxName < CurSubKeyCell->NameSize)
+         if ((CurSubKeyCell->Flags & REG_KEY_ROOT_CELL) == REG_KEY_ROOT_CELL)
            {
-             MaxName = CurSubKeyCell->NameSize;
+             /* 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 (NameSize > MaxName)
+           {
+             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)
@@ -2090,13 +2195,14 @@ CmiGetMaxValueNameLength(PREGISTRY_HIVE RegistryHive,
   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)
     {
@@ -2106,18 +2212,25 @@ CmiGetMaxValueNameLength(PREGISTRY_HIVE RegistryHive,
 
   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;
+           }
         }
     }
 
@@ -2137,7 +2250,7 @@ CmiGetMaxValueDataLength(PREGISTRY_HIVE RegistryHive,
   VERIFY_KEY_CELL(KeyCell);
 
   MaxValueData = 0;
-  ValueListCell = CmiGetBlock(RegistryHive, KeyCell->ValuesOffset, NULL);
+  ValueListCell = CmiGetCell (RegistryHive, KeyCell->ValueListOffset, NULL);
   if (ValueListCell == NULL)
     {
       return 0;
@@ -2145,12 +2258,12 @@ CmiGetMaxValueDataLength(PREGISTRY_HIVE RegistryHive,
 
   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;
         }
     }
 
@@ -2175,7 +2288,7 @@ CmiScanForSubKey(IN PREGISTRY_HIVE RegistryHive,
 
   DPRINT("Scanning for sub key %wZ\n", KeyName);
 
-  assert(RegistryHive);
+  ASSERT(RegistryHive);
 
   *SubKeyCell = NULL;
 
@@ -2186,7 +2299,7 @@ CmiScanForSubKey(IN PREGISTRY_HIVE RegistryHive,
     }
 
   /* Get hash table */
-  HashBlock = CmiGetBlock(RegistryHive, KeyCell->HashTableOffset, NULL);
+  HashBlock = CmiGetCell (RegistryHive, KeyCell->HashTableOffset, NULL);
   if (HashBlock == NULL)
     {
       DPRINT("CmiGetBlock() failed\n");
@@ -2202,7 +2315,7 @@ CmiScanForSubKey(IN PREGISTRY_HIVE RegistryHive,
              (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)
@@ -2226,7 +2339,7 @@ CmiScanForSubKey(IN PREGISTRY_HIVE RegistryHive,
              (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)
@@ -2251,28 +2364,28 @@ CmiScanForSubKey(IN PREGISTRY_HIVE RegistryHive,
 
 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'\\')
@@ -2308,9 +2421,9 @@ CmiAddSubKey(PREGISTRY_HIVE RegistryHive,
   Status = STATUS_SUCCESS;
 
   NewBlockSize = sizeof(KEY_CELL) + NameSize;
-  Status = CmiAllocateBlock(RegistryHive,
-                           (PVOID) &NewKeyCell,
+  Status = CmiAllocateCell (RegistryHive,
                            NewBlockSize,
+                           (PVOID) &NewKeyCell,
                            &NKBOffset);
   if (NewKeyCell == NULL)
     {
@@ -2320,12 +2433,12 @@ CmiAddSubKey(PREGISTRY_HIVE RegistryHive,
     {
       NewKeyCell->Id = REG_KEY_CELL_ID;
       NewKeyCell->Flags = 0;
-      NtQuerySystemTime(&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;
 
@@ -2348,19 +2461,16 @@ CmiAddSubKey(PREGISTRY_HIVE RegistryHive,
 
       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);
        }
     }
 
@@ -2370,19 +2480,19 @@ CmiAddSubKey(PREGISTRY_HIVE RegistryHive,
     }
 
   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))
        {
@@ -2391,21 +2501,22 @@ CmiAddSubKey(PREGISTRY_HIVE RegistryHive,
     }
   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 +
@@ -2420,23 +2531,27 @@ CmiAddSubKey(PREGISTRY_HIVE RegistryHive,
          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);
 }
 
@@ -2458,82 +2573,86 @@ CmiRemoveSubKey(PREGISTRY_HIVE RegistryHive,
   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)
            {
-             /* Get pointer to value cell */
-             ValueCell = CmiGetBlock(RegistryHive,
-                                     ValueList->Values[i],
-                                     NULL);
-             if (ValueCell != NULL)
+             DPRINT("CmiGetCell() failed\n");
+             return STATUS_UNSUCCESSFUL;
+           }
+
+         if (!(ValueCell->DataSize & REG_DATA_IN_OFFSET)
+              && ValueCell->DataSize > sizeof(BLOCK_OFFSET))
+           {
+             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);
        }
     }
@@ -2541,19 +2660,19 @@ CmiRemoveSubKey(PREGISTRY_HIVE RegistryHive,
   /* 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;
@@ -2563,44 +2682,46 @@ CmiRemoveSubKey(PREGISTRY_HIVE RegistryHive,
   /* 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(&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;
 }
 
 
@@ -2609,21 +2730,23 @@ CmiScanKeyForValue(IN PREGISTRY_HIVE RegistryHive,
                   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");
@@ -2634,8 +2757,8 @@ CmiScanKeyForValue(IN PREGISTRY_HIVE RegistryHive,
 
   for (i = 0; i < KeyCell->NumberOfValues; i++)
     {
-      CurValueCell = CmiGetBlock(RegistryHive,
-                                ValueListCell->Values[i],
+      CurValueCell = CmiGetCell (RegistryHive,
+                                ValueListCell->ValueOffset[i],
                                 NULL);
       if (CurValueCell == NULL)
        {
@@ -2647,17 +2770,17 @@ CmiScanKeyForValue(IN PREGISTRY_HIVE RegistryHive,
          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;
 }
 
 
@@ -2672,7 +2795,7 @@ CmiGetValueFromKeyByIndex(IN PREGISTRY_HIVE RegistryHive,
 
   *ValueCell = NULL;
 
-  if (KeyCell->ValuesOffset == (BLOCK_OFFSET)-1)
+  if (KeyCell->ValueListOffset == (BLOCK_OFFSET)-1)
     {
       return STATUS_NO_MORE_ENTRIES;
     }
@@ -2683,7 +2806,7 @@ CmiGetValueFromKeyByIndex(IN PREGISTRY_HIVE RegistryHive,
     }
 
 
-  ValueListCell = CmiGetBlock(RegistryHive, KeyCell->ValuesOffset, NULL);
+  ValueListCell = CmiGetCell (RegistryHive, KeyCell->ValueListOffset, NULL);
   if (ValueListCell == NULL)
     {
       DPRINT("CmiGetBlock() failed\n");
@@ -2693,8 +2816,8 @@ CmiGetValueFromKeyByIndex(IN PREGISTRY_HIVE RegistryHive,
   VERIFY_VALUE_LIST_CELL(ValueListCell);
 
 
-  CurValueCell = CmiGetBlock(RegistryHive,
-                            ValueListCell->Values[Index],
+  CurValueCell = CmiGetCell (RegistryHive,
+                            ValueListCell->ValueOffset[Index],
                             NULL);
   if (CurValueCell == NULL)
     {
@@ -2711,77 +2834,93 @@ CmiGetValueFromKeyByIndex(IN PREGISTRY_HIVE RegistryHive,
 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;
 }
@@ -2795,13 +2934,13 @@ CmiDeleteValueFromKey(IN PREGISTRY_HIVE RegistryHive,
 {
   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;
     }
 
@@ -2809,61 +2948,69 @@ CmiDeleteValueFromKey(IN PREGISTRY_HIVE RegistryHive,
 
   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;
@@ -2871,11 +3018,11 @@ CmiAllocateHashTableBlock(IN PREGISTRY_HIVE RegistryHive,
 
   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)))
@@ -2884,8 +3031,9 @@ CmiAllocateHashTableBlock(IN PREGISTRY_HIVE RegistryHive,
     }
   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;
     }
 
@@ -2911,7 +3059,7 @@ CmiGetKeyFromHashByIndex(PREGISTRY_HIVE RegistryHive,
   else
     {
       KeyOffset =  HashBlock->Table[Index].KeyOffset;
-      KeyCell = CmiGetBlock(RegistryHive, KeyOffset, NULL);
+      KeyCell = CmiGetCell (RegistryHive, KeyOffset, NULL);
     }
 
   return KeyCell;
@@ -2920,24 +3068,26 @@ CmiGetKeyFromHashByIndex(PREGISTRY_HIVE RegistryHive,
 
 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;
        }
     }
@@ -2986,9 +3136,9 @@ CmiAllocateValueCell(PREGISTRY_HIVE RegistryHive,
 
   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)))
     {
@@ -2996,8 +3146,9 @@ CmiAllocateValueCell(PREGISTRY_HIVE RegistryHive,
     }
   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 */
@@ -3015,7 +3166,7 @@ CmiAllocateValueCell(PREGISTRY_HIVE RegistryHive,
        }
       NewValueCell->DataType = 0;
       NewValueCell->DataSize = 0;
-      NewValueCell->DataOffset = 0xffffffff;
+      NewValueCell->DataOffset = (BLOCK_OFFSET)-1;
       *ValueCell = NewValueCell;
     }
 
@@ -3026,44 +3177,46 @@ CmiAllocateValueCell(PREGISTRY_HIVE RegistryHive,
 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 (!IsNoFileHive(RegistryHive))
-       NtQuerySystemTime(&pBin->DateModified);
+       KeQuerySystemTime(&Bin->DateModified);
     }
 
   /* Destroy the value cell */
-  Status = CmiDestroyBlock(RegistryHive, ValueCell, VBOffset);
+  Status = CmiDestroyCell (RegistryHive, ValueCell, ValueCellOffset);
 
   /* Update time of heap */
-  if (!IsNoFileHive(RegistryHive) && CmiGetBlock(RegistryHive, VBOffset, &pBin))
+  if (!IsNoFileHive(RegistryHive) && CmiGetCell (RegistryHive, ValueCellOffset, &Bin))
     {
-      NtQuerySystemTime(&pBin->DateModified);
+      KeQuerySystemTime(&Bin->DateModified);
     }
 
   return Status;
@@ -3072,31 +3225,41 @@ CmiDestroyValueCell(PREGISTRY_HIVE RegistryHive,
 
 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(&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;
@@ -3104,31 +3267,36 @@ CmiAddBin(PREGISTRY_HIVE RegistryHive,
 
   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 (IsNoFileHive(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,
@@ -3136,7 +3304,7 @@ CmiAddBin(PREGISTRY_HIVE RegistryHive,
       RtlZeroMemory(BitmapBuffer, BitmapSize);
       RtlCopyMemory(BitmapBuffer,
                    RegistryHive->DirtyBitMap.Buffer,
-                   RegistryHive->DirtyBitMap.SizeOfBitMap);
+                   RegistryHive->DirtyBitMap.SizeOfBitMap / 8);
       ExFreePool(RegistryHive->BitmapBuffer);
       RegistryHive->BitmapBuffer = BitmapBuffer;
       RtlInitializeBitMap(&RegistryHive->DirtyBitMap,
@@ -3147,76 +3315,72 @@ CmiAddBin(PREGISTRY_HIVE RegistryHive,
   *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(&pBin->DateModified);
-                 CmiMarkBlockDirty(RegistryHive, RegistryHive->FreeListOffset[i]);
-               }
+             KeQuerySystemTime(&Bin->DateModified);
+             CmiMarkBlockDirty(RegistryHive, RegistryHive->FreeListOffset[i]);
 
              if ((i + 1) < RegistryHive->FreeListSize)
                {
@@ -3235,46 +3399,50 @@ CmiAllocateBlock(PREGISTRY_HIVE RegistryHive,
        }
 
       /* 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;
+         ((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 *= -1;
     }
 
-  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;
@@ -3283,33 +3451,77 @@ CmiDestroyBlock(PREGISTRY_HIVE RegistryHive,
 
   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 (!IsNoFileHive(RegistryHive) && CmiGetBlock(RegistryHive, Offset,&pBin))
-       NtQuerySystemTime(&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,
@@ -3325,15 +3537,15 @@ CmiMergeFree(PREGISTRY_HIVE RegistryHive,
   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++)
@@ -3419,8 +3631,8 @@ CmiAddFree(PREGISTRY_HIVE RegistryHive,
   LONG maxInd;
   LONG medInd;
 
-  assert(RegistryHive);
-  assert(FreeBlock);
+  ASSERT(RegistryHive);
+  ASSERT(FreeBlock);
 
   DPRINT("FreeBlock %.08lx  FreeOffset %.08lx\n",
         FreeBlock, FreeOffset);
@@ -3515,41 +3727,6 @@ CmiAddFree(PREGISTRY_HIVE RegistryHive,
 }
 
 
-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)
@@ -3564,9 +3741,9 @@ CmiMarkBlockDirty(PREGISTRY_HIVE RegistryHive,
 
   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);
 
@@ -3574,7 +3751,8 @@ CmiMarkBlockDirty(PREGISTRY_HIVE RegistryHive,
   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,
@@ -3602,15 +3780,15 @@ CmiMarkBinDirty(PREGISTRY_HIVE RegistryHive,
 
   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;
@@ -3645,7 +3823,7 @@ CmiGetPackedNameLength(IN PUNICODE_STRING Name,
 
 BOOLEAN
 CmiComparePackedNames(IN PUNICODE_STRING Name,
-                     IN PCHAR NameBuffer,
+                     IN PUCHAR NameBuffer,
                      IN USHORT NameBufferSize,
                      IN BOOLEAN NamePacked)
 {
@@ -3683,7 +3861,7 @@ CmiComparePackedNames(IN PUNICODE_STRING Name,
 
 VOID
 CmiCopyPackedName(PWCHAR NameBuffer,
-                 PCHAR PackedNameBuffer,
+                 PUCHAR PackedNameBuffer,
                  ULONG PackedNameSize)
 {
   ULONG i;
@@ -3820,10 +3998,10 @@ CmiCopyKey (PREGISTRY_HIVE DstHive,
     {
       /* Allocate and copy key cell */
       NewKeyCellSize = sizeof(KEY_CELL) + SrcKeyCell->NameSize;
-      Status = CmiAllocateBlock (DstHive,
-                                (PVOID) &NewKeyCell,
-                                NewKeyCellSize,
-                                &NewKeyCellOffset);
+      Status = CmiAllocateCell (DstHive,
+                               NewKeyCellSize,
+                               (PVOID) &NewKeyCell,
+                               &NewKeyCellOffset);
       if (!NT_SUCCESS(Status))
        {
          DPRINT1 ("CmiAllocateBlock() failed (Status %lx)\n", Status);
@@ -3839,7 +4017,7 @@ CmiCopyKey (PREGISTRY_HIVE DstHive,
                     SrcKeyCell,
                     NewKeyCellSize);
 
-      DstHive->HiveHeader->RootKeyCell = NewKeyCellOffset;
+      DstHive->HiveHeader->RootKeyOffset = NewKeyCellOffset;
 
       /* Copy class name */
       if (SrcKeyCell->ClassNameOffset != (BLOCK_OFFSET) -1)
@@ -3848,13 +4026,13 @@ CmiCopyKey (PREGISTRY_HIVE DstHive,
          PDATA_CELL NewClassNameCell;
          BLOCK_OFFSET NewClassNameOffset;
 
-         SrcClassNameCell = CmiGetBlock (SrcHive, SrcKeyCell->ClassNameOffset, NULL),
+         SrcClassNameCell = CmiGetCell (SrcHive, SrcKeyCell->ClassNameOffset, NULL),
 
          NewKeyCell->ClassSize = SrcKeyCell->ClassSize;
-         Status = CmiAllocateBlock (DstHive,
-                                    (PVOID)&NewClassNameCell,
-                                    NewKeyCell->ClassSize,
-                                    &NewClassNameOffset);
+         Status = CmiAllocateCell (DstHive,
+                                   sizeof(CELL_HEADER) + NewKeyCell->ClassSize,
+                                   (PVOID)&NewClassNameCell,
+                                   &NewClassNameOffset);
          if (!NT_SUCCESS(Status))
            {
              DPRINT1 ("CmiAllocateBlock() failed (Status %lx)\n", Status);
@@ -3876,10 +4054,10 @@ CmiCopyKey (PREGISTRY_HIVE DstHive,
   if (SrcKeyCell->NumberOfSubKeys > 0)
     {
       NewHashTableSize = ROUND_UP(SrcKeyCell->NumberOfSubKeys + 1, 4) - 1;
-      Status = CmiAllocateHashTableBlock (DstHive,
-                                         &NewHashTableCell,
-                                         &NewHashTableOffset,
-                                         NewHashTableSize);
+      Status = CmiAllocateHashTableCell (DstHive,
+                                        &NewHashTableCell,
+                                        &NewHashTableOffset,
+                                        NewHashTableSize);
       if (!NT_SUCCESS(Status))
        {
          DPRINT1 ("CmiAllocateHashTableBlock() failed (Status %lx)\n", Status);
@@ -3887,6 +4065,10 @@ CmiCopyKey (PREGISTRY_HIVE DstHive,
        }
       NewKeyCell->HashTableOffset = NewHashTableOffset;
     }
+  else
+    {
+      NewHashTableCell = NULL;
+    }
 
   /* Allocate and copy value list and values */
   if (SrcKeyCell->NumberOfValues != 0)
@@ -3905,10 +4087,10 @@ CmiCopyKey (PREGISTRY_HIVE DstHive,
 
       NewValueListCellSize =
        ROUND_UP(SrcKeyCell->NumberOfValues, 4) * sizeof(BLOCK_OFFSET);
-      Status = CmiAllocateBlock (DstHive,
-                                (PVOID)&NewValueListCell,
-                                NewValueListCellSize,
-                                &NewKeyCell->ValuesOffset);
+      Status = CmiAllocateCell (DstHive,
+                               NewValueListCellSize,
+                               (PVOID)&NewValueListCell,
+                               &NewKeyCell->ValueListOffset);
       if (!NT_SUCCESS(Status))
        {
          DPRINT1 ("CmiAllocateBlock() failed (Status %lx)\n", Status);
@@ -3919,24 +4101,24 @@ CmiCopyKey (PREGISTRY_HIVE DstHive,
                     NewValueListCellSize);
 
       /* Copy values */
-      SrcValueListCell = CmiGetBlock (SrcHive, SrcKeyCell->ValuesOffset, NULL);
+      SrcValueListCell = CmiGetCell (SrcHive, SrcKeyCell->ValueListOffset, NULL);
       for (i = 0; i < SrcKeyCell->NumberOfValues; i++)
        {
          /* Copy value cell */
-         SrcValueCell = CmiGetBlock (SrcHive, SrcValueListCell->Values[i], NULL);
+         SrcValueCell = CmiGetCell (SrcHive, SrcValueListCell->ValueOffset[i], NULL);
 
          NewValueCellSize = sizeof(VALUE_CELL) + SrcValueCell->NameSize;
-         Status = CmiAllocateBlock (DstHive,
-                                    (PVOID*) &NewValueCell,
-                                    NewValueCellSize,
-                                    &ValueCellOffset);
+         Status = CmiAllocateCell (DstHive,
+                                   NewValueCellSize,
+                                   (PVOID*) &NewValueCell,
+                                   &ValueCellOffset);
          if (!NT_SUCCESS(Status))
            {
              DPRINT1 ("CmiAllocateBlock() failed (Status %lx)\n", Status);
              return Status;
            }
 
-         NewValueListCell->Values[i] = ValueCellOffset;
+         NewValueListCell->ValueOffset[i] = ValueCellOffset;
          RtlCopyMemory (NewValueCell,
                         SrcValueCell,
                         NewValueCellSize);
@@ -3944,12 +4126,12 @@ CmiCopyKey (PREGISTRY_HIVE DstHive,
          /* Copy value data cell */
          if (SrcValueCell->DataSize > (LONG) sizeof(PVOID))
            {
-             SrcValueDataCell = CmiGetBlock (SrcHive, SrcValueCell->DataOffset, NULL);
+             SrcValueDataCell = CmiGetCell (SrcHive, SrcValueCell->DataOffset, NULL);
 
-             Status = CmiAllocateBlock (DstHive,
-                                        (PVOID*) &NewValueDataCell,
-                                        SrcValueCell->DataSize,
-                                        &ValueDataCellOffset);
+             Status = CmiAllocateCell (DstHive,
+                                       sizeof(CELL_HEADER) + SrcValueCell->DataSize,
+                                       (PVOID*) &NewValueDataCell,
+                                       &ValueDataCellOffset);
              if (!NT_SUCCESS(Status))
                {
                  DPRINT1 ("CmiAllocateBlock() failed (Status %lx)\n", Status);
@@ -3973,21 +4155,21 @@ CmiCopyKey (PREGISTRY_HIVE DstHive,
       BLOCK_OFFSET NewSubKeyCellOffset;
       PHASH_RECORD SrcHashRecord;
 
-      SrcHashTableCell = CmiGetBlock (SrcHive,
-                                     SrcKeyCell->HashTableOffset,
-                                     NULL);
+      SrcHashTableCell = CmiGetCell (SrcHive,
+                                    SrcKeyCell->HashTableOffset,
+                                    NULL);
 
       for (i = 0; i < SrcKeyCell->NumberOfSubKeys; i++)
        {
          SrcHashRecord = &SrcHashTableCell->Table[i];
-         SrcSubKeyCell = CmiGetBlock (SrcHive, SrcHashRecord->KeyOffset, NULL);
+         SrcSubKeyCell = CmiGetCell (SrcHive, SrcHashRecord->KeyOffset, NULL);
 
          /* Allocate and copy key cell */
          NewSubKeyCellSize = sizeof(KEY_CELL) + SrcSubKeyCell->NameSize;
-         Status = CmiAllocateBlock (DstHive,
-                                    (PVOID)&NewSubKeyCell,
-                                    NewSubKeyCellSize,
-                                    &NewSubKeyCellOffset);
+         Status = CmiAllocateCell (DstHive,
+                                   NewSubKeyCellSize,
+                                   (PVOID)&NewSubKeyCell,
+                                   &NewSubKeyCellOffset);
          if (!NT_SUCCESS(Status))
            {
              DPRINT1 ("CmiAllocateBlock() failed (Status %lx)\n", Status);
@@ -4013,15 +4195,15 @@ CmiCopyKey (PREGISTRY_HIVE DstHive,
              PDATA_CELL NewClassNameCell;
              BLOCK_OFFSET NewClassNameOffset;
 
-             SrcClassNameCell = CmiGetBlock (SrcHive,
-                                             SrcSubKeyCell->ClassNameOffset,
-                                             NULL),
+             SrcClassNameCell = CmiGetCell (SrcHive,
+                                            SrcSubKeyCell->ClassNameOffset,
+                                            NULL),
 
              NewSubKeyCell->ClassSize = SrcSubKeyCell->ClassSize;
-             Status = CmiAllocateBlock (DstHive,
-                                        (PVOID)&NewClassNameCell,
-                                        NewSubKeyCell->ClassSize,
-                                        &NewClassNameOffset);
+             Status = CmiAllocateCell (DstHive,
+                                       sizeof(CELL_HEADER) + NewSubKeyCell->ClassSize,
+                                       (PVOID)&NewClassNameCell,
+                                       &NewClassNameOffset);
              if (!NT_SUCCESS(Status))
                {
                  DPRINT1 ("CmiAllocateBlock() failed (Status %lx)\n", Status);
@@ -4066,8 +4248,8 @@ CmiSaveTempHive (PREGISTRY_HIVE Hive,
   Hive->HiveHeader->Checksum = CmiCalcChecksum ((PULONG)Hive->HiveHeader);
 
   /* Write hive block */
-  FileOffset.QuadPart = 0ULL;
-  Status = NtWriteFile (FileHandle,
+  FileOffset.QuadPart = (ULONGLONG)0;
+  Status = ZwWriteFile (FileHandle,
                        NULL,
                        NULL,
                        NULL,
@@ -4078,21 +4260,21 @@ CmiSaveTempHive (PREGISTRY_HIVE Hive,
                        NULL);
   if (!NT_SUCCESS(Status))
     {
-      DPRINT1 ("NtWriteFile() failed (Status %lx)\n", 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];
+      BlockPtr = Hive->BlockList[BlockIndex].Block;
       DPRINT ("BlockPtr %p\n", BlockPtr);
 
-      FileOffset.QuadPart = (ULONGLONG)(BlockIndex + 1) * 4096ULL;
+      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,
@@ -4103,16 +4285,16 @@ CmiSaveTempHive (PREGISTRY_HIVE Hive,
                            NULL);
       if (!NT_SUCCESS(Status))
        {
-         DPRINT1 ("NtWriteFile() failed (Status %lx)\n", Status);
+         DPRINT1 ("ZwWriteFile() failed (Status %lx)\n", Status);
          return Status;
        }
     }
 
-  Status = NtFlushBuffersFile (FileHandle,
+  Status = ZwFlushBuffersFile (FileHandle,
                               &IoStatusBlock);
   if (!NT_SUCCESS(Status))
     {
-      DPRINT1 ("NtFlushBuffersFile() failed (Status %lx)\n", Status);
+      DPRINT1 ("ZwFlushBuffersFile() failed (Status %lx)\n", Status);
     }
 
   DPRINT ("CmiSaveTempHive() done\n");