Fix splitting of cells (noticed by Hartmut).
[reactos.git] / reactos / tools / mkhive / binhive.c
index 764b8df..6b3dfb8 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ReactOS kernel
- *  Copyright (C) 2003 ReactOS Team
+ *  Copyright (C) 2003, 2004 ReactOS Team
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -16,7 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: binhive.c,v 1.4 2003/05/18 13:50:58 ekohl Exp $
+/* $Id$
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS hive maker
  * FILE:            tools/mkhive/binhive.c
@@ -29,6 +29,7 @@
 //#include <assert.h>
 #include <stdlib.h>
 #include <stdio.h>
+#include <string.h>
 
 #include "mkhive.h"
 #include "binhive.h"
@@ -38,7 +39,7 @@
 #define  REG_HIVE_ID                   0x66676572
 #define  REG_BIN_ID                    0x6e696268
 #define  REG_KEY_CELL_ID               0x6b6e
-#define  REG_HASH_TABLE_BLOCK_ID       0x666c
+#define  REG_HASH_TABLE_CELL_ID        0x666c
 #define  REG_VALUE_CELL_ID             0x6b76
 
 #define  REG_BLOCK_SIZE                4096
@@ -48,8 +49,8 @@
 #define  REG_EXTEND_HASH_TABLE_SIZE    4
 #define  REG_VALUE_LIST_CELL_MULTIPLE  4
 
-#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
-#define ROUND_DOWN(N, S) ((N) - ((N) % (S)))
+#define ROUND_UP_POW2(N,S)   (((N) + (S) - 1) & ~((S) - 1))
+#define ROUND_DOWN_POW2(N,S) ((N) & ~((S) - 1))
 
 #define ABS_VALUE(V) (((V) < 0) ? -(V) : (V))
 
 // BLOCK_OFFSET = offset in file after header block
 typedef ULONG BLOCK_OFFSET, *PBLOCK_OFFSET;
 
+#ifdef _MSC_VER
+typedef unsigned __int64 FILETIME;
+#else
 typedef unsigned long long FILETIME;
+#endif
+
+#ifdef _MSC_VER
+#pragma pack ( push, hive_header, 1 )
+#endif//_MSC_VER
 
 /* header for registry hive file : */
 typedef struct _HIVE_HEADER
@@ -74,21 +83,22 @@ typedef struct _HIVE_HEADER
   /* When this hive file was last modified */
   FILETIME  DateModified;
 
-  /* Registry format version ? (1?) */
-  ULONG  Unused3;
+  /* Registry format major version (1) */
+  ULONG  MajorVersion;
 
-  /* Registry format version ? (3?) */
-  ULONG  Unused4;
+  /* Registry format minor version (3)
+     Version 3 added fast indexes, version 5 has large value optimizations */
+  ULONG  MinorVersion;
 
-  /* Registry format version ? (0?) */
-  ULONG  Unused5;
+  /* Registry file type (0 - Primary, 1 - Log) */
+  ULONG  Type;
 
-  /* Registry format version ? (1?) */
-  ULONG  Unused6;
+  /* Registry format (1 is the only defined value so far) */
+  ULONG  Format;
 
   /* Offset into file from the byte after the end of the base block.
      If the hive is volatile, this is the actual pointer to the KEY_CELL */
-  BLOCK_OFFSET  RootKeyCell;
+  BLOCK_OFFSET  RootKeyOffset;
 
   /* Size of each hive block ? */
   ULONG  BlockSize;
@@ -97,41 +107,39 @@ typedef struct _HIVE_HEADER
   ULONG  Unused7;
 
   /* Name of hive file */
-  WCHAR  FileName[64];
+  WCHAR  FileName[48];
 
-  /* ? */
-  ULONG  Unused8[83];
+  ULONG  Reserved[99];
 
   /* Checksum of first 0x200 bytes */
   ULONG  Checksum;
-} __attribute__((packed)) HIVE_HEADER, *PHIVE_HEADER;
+} GCC_PACKED HIVE_HEADER, *PHIVE_HEADER;
 
 typedef struct _HBIN
 {
   /* Bin identifier "hbin" (0x6E696268) */
-  ULONG  BlockId;
+  ULONG  HeaderId;
 
   /* Block offset of this bin */
-  BLOCK_OFFSET  BlockOffset;
+  BLOCK_OFFSET  BinOffset;
 
   /* Size in bytes, multiple of the block size (4KB) */
-  ULONG  BlockSize;
+  ULONG  BinSize;
 
-  /* ? */
-  ULONG  Unused1;
+  ULONG  Reserved[2];
 
   /* When this bin was last modified */
   FILETIME  DateModified;
 
-  /* ? */
-  ULONG  Unused2;
-} __attribute__((packed)) HBIN, *PHBIN;
+  /* ? (In-memory only) */
+  ULONG  MemAlloc;
+} GCC_PACKED HBIN, *PHBIN;
 
 typedef struct _CELL_HEADER
 {
   /* <0 if used, >0 if free */
   LONG  CellSize;
-} __attribute__((packed)) CELL_HEADER, *PCELL_HEADER;
+} GCC_PACKED CELL_HEADER, *PCELL_HEADER;
 
 typedef struct _KEY_CELL
 {
@@ -169,7 +177,7 @@ typedef struct _KEY_CELL
   ULONG  NumberOfValues;
 
   /* Block offset of VALUE_LIST_CELL */
-  BLOCK_OFFSET  ValuesOffset;
+  BLOCK_OFFSET  ValueListOffset;
 
   /* Block offset of security cell */
   BLOCK_OFFSET  SecurityKeyOffset;
@@ -187,8 +195,8 @@ typedef struct _KEY_CELL
   USHORT  ClassSize;
 
   /* Name of key (not zero terminated) */
-  UCHAR  Name[0];
-} __attribute__((packed)) KEY_CELL, *PKEY_CELL;
+  CHAR  Name[0];
+} GCC_PACKED KEY_CELL, *PKEY_CELL;
 
 /* KEY_CELL.Type constants */
 #define  REG_LINK_KEY_CELL_TYPE        0x10
@@ -202,7 +210,7 @@ typedef struct _HASH_RECORD
 {
   BLOCK_OFFSET  KeyOffset;
   ULONG  HashValue;
-} __attribute__((packed)) HASH_RECORD, *PHASH_RECORD;
+} GCC_PACKED HASH_RECORD, *PHASH_RECORD;
 
 typedef struct _HASH_TABLE_CELL
 {
@@ -210,36 +218,43 @@ typedef struct _HASH_TABLE_CELL
   USHORT  Id;
   USHORT  HashTableSize;
   HASH_RECORD  Table[0];
-} __attribute__((packed)) HASH_TABLE_CELL, *PHASH_TABLE_CELL;
+} GCC_PACKED HASH_TABLE_CELL, *PHASH_TABLE_CELL;
 
 typedef struct _VALUE_LIST_CELL
 {
   LONG  CellSize;
-  BLOCK_OFFSET  Values[0];
-} __attribute__((packed)) VALUE_LIST_CELL, *PVALUE_LIST_CELL;
+  BLOCK_OFFSET  ValueOffset[0];
+} GCC_PACKED VALUE_LIST_CELL, *PVALUE_LIST_CELL;
 
 typedef struct _VALUE_CELL
 {
   LONG  CellSize;
   USHORT  Id;  // "kv"
   USHORT  NameSize;    // length of Name
-  LONG  DataSize;      // length of datas in the cell pointed by DataOffset
+  ULONG  DataSize;     // length of datas in the cell pointed by DataOffset
   BLOCK_OFFSET  DataOffset;// datas are here if high bit of DataSize is set
   ULONG  DataType;
   USHORT  Flags;
   USHORT  Unused1;
-  UCHAR  Name[0]; /* warning : not zero terminated */
-} __attribute__((packed)) VALUE_CELL, *PVALUE_CELL;
+  CHAR  Name[0]; /* warning : not zero terminated */
+} GCC_PACKED VALUE_CELL, *PVALUE_CELL;
 
 /* VALUE_CELL.Flags constants */
 #define REG_VALUE_NAME_PACKED             0x0001
 
+/* VALUE_CELL.DataSize mask constants */
+#define REG_DATA_SIZE_MASK 0x7FFFFFFF
+#define REG_DATA_IN_OFFSET 0x80000000
 
 typedef struct _DATA_CELL
 {
   LONG  CellSize;
-  UCHAR  Data[0];
-} __attribute__((packed)) DATA_CELL, *PDATA_CELL;
+  CHAR  Data[0];
+} GCC_PACKED DATA_CELL, *PDATA_CELL;
+
+#ifdef _MSC_VER
+#pragma pack ( pop, hive_header )
+#endif//_MSC_VER
 
 typedef struct _REGISTRY_HIVE
 {
@@ -256,22 +271,33 @@ typedef struct _REGISTRY_HIVE
 /* FUNCTIONS ****************************************************************/
 
 static VOID
-CmiCreateDefaultHiveHeader(PHIVE_HEADER Header)
+memexpand (PWCHAR Dst,
+          PCHAR Src,
+          ULONG Length)
+{
+  ULONG i;
+
+  for (i = 0; i < Length; i++)
+    Dst[i] = (WCHAR)Src[i];
+}
+
+
+static VOID
+CmiCreateDefaultHiveHeader (PHIVE_HEADER Header)
 {
-  assert(Header);
+  assert (Header);
   memset (Header, 0, REG_BLOCK_SIZE);
   Header->BlockId = REG_HIVE_ID;
   Header->UpdateCounter1 = 0;
   Header->UpdateCounter2 = 0;
-  Header->DateModified = 0ULL;
-  Header->Unused3 = 1;
-  Header->Unused4 = 3;
-  Header->Unused5 = 0;
-  Header->Unused6 = 1;
+  Header->DateModified = 0;
+  Header->MajorVersion = 1;
+  Header->MinorVersion = 3;
+  Header->Type = 0;
+  Header->Format = 1;
   Header->Unused7 = 1;
-  Header->RootKeyCell = 0;
+  Header->RootKeyOffset = -1;
   Header->BlockSize = REG_BLOCK_SIZE;
-  Header->Unused6 = 1;
   Header->Checksum = 0;
 }
 
@@ -279,37 +305,49 @@ CmiCreateDefaultHiveHeader(PHIVE_HEADER Header)
 static VOID
 CmiCreateDefaultBinCell(PHBIN BinCell)
 {
-  assert(BinCell);
+  assert (BinCell);
   memset (BinCell, 0, REG_BLOCK_SIZE);
-  BinCell->BlockId = REG_BIN_ID;
-  BinCell->DateModified = 0ULL;
-  BinCell->BlockSize = REG_BLOCK_SIZE;
+  BinCell->HeaderId = REG_BIN_ID;
+  BinCell->DateModified = 0;
+  BinCell->BinSize = REG_BLOCK_SIZE;
 }
 
 
 static VOID
-CmiCreateDefaultRootKeyCell(PKEY_CELL RootKeyCell)
+CmiCreateDefaultRootKeyCell(PKEY_CELL RootKeyCell, PCHAR KeyName)
 {
-  assert(RootKeyCell);
-  memset (RootKeyCell, 0, sizeof(KEY_CELL));
-  RootKeyCell->CellSize = -sizeof(KEY_CELL);
+  PCHAR BaseKeyName;
+  USHORT NameSize;
+  ULONG CellSize;
+
+  assert (RootKeyCell);
+
+  BaseKeyName = strrchr(KeyName, '\\') + 1;
+  NameSize = strlen(BaseKeyName);
+  CellSize = ROUND_UP_POW2(sizeof(KEY_CELL) + NameSize - 1, 16);
+
+  memset (RootKeyCell, 0, CellSize);
+  RootKeyCell->CellSize = (ULONG)-(LONG)CellSize;
   RootKeyCell->Id = REG_KEY_CELL_ID;
   RootKeyCell->Type = REG_ROOT_KEY_CELL_TYPE;
-  RootKeyCell->LastWriteTime = 0ULL;
+  RootKeyCell->LastWriteTime = 0;
   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;
+  RootKeyCell->NameSize = NameSize;
   RootKeyCell->ClassSize = 0;
+  memcpy (RootKeyCell->Name,
+         BaseKeyName,
+         NameSize);
 }
 
 
 static PREGISTRY_HIVE
-CmiCreateRegistryHive (VOID)
+CmiCreateRegistryHive (PCHAR KeyName)
 {
   PREGISTRY_HIVE Hive;
   PCELL_HEADER FreeCell;
@@ -323,7 +361,7 @@ CmiCreateRegistryHive (VOID)
     }
   memset (Hive, 0, sizeof(REGISTRY_HIVE));
 
-  DPRINT("Hive %x\n", Hive);
+  DPRINT("Hive %p\n", Hive);
 
   /* Create hive beader (aka 'base block') */
   Hive->HiveHeader = (PHIVE_HEADER) malloc (REG_BLOCK_SIZE);
@@ -332,7 +370,7 @@ CmiCreateRegistryHive (VOID)
       free (Hive);
       return NULL;
     }
-  CmiCreateDefaultHiveHeader(Hive->HiveHeader);
+  CmiCreateDefaultHiveHeader (Hive->HiveHeader);
   Hive->FileSize = REG_BLOCK_SIZE;
 
   /* Allocate block list */
@@ -380,20 +418,20 @@ CmiCreateRegistryHive (VOID)
 
   /* Init first bin */
   BinCell = (PHBIN)Hive->BlockList[0];
-  CmiCreateDefaultBinCell(BinCell);
-  BinCell->BlockOffset = 0;
+  CmiCreateDefaultBinCell (BinCell);
+  BinCell->BinOffset = 0;
 
   /* Init root key cell */
   RootKeyCell = (PKEY_CELL)((ULONG_PTR)BinCell + REG_HBIN_DATA_OFFSET);
-  CmiCreateDefaultRootKeyCell(RootKeyCell);
-  Hive->HiveHeader->RootKeyCell = REG_HBIN_DATA_OFFSET;
+  CmiCreateDefaultRootKeyCell (RootKeyCell, KeyName);
+  Hive->HiveHeader->RootKeyOffset = REG_HBIN_DATA_OFFSET;
 
   /* Init free cell */
-  FreeCell = (PCELL_HEADER)((ULONG_PTR)RootKeyCell + sizeof(KEY_CELL));
-  FreeCell->CellSize = REG_BLOCK_SIZE - (REG_HBIN_DATA_OFFSET + sizeof(KEY_CELL));
+  FreeCell = (PCELL_HEADER)((ULONG_PTR)RootKeyCell - RootKeyCell->CellSize);
+  FreeCell->CellSize = REG_BLOCK_SIZE - (REG_HBIN_DATA_OFFSET - RootKeyCell->CellSize);
 
   Hive->FreeList[0] = FreeCell;
-  Hive->FreeListOffset[0] = REG_HBIN_DATA_OFFSET + sizeof(KEY_CELL);
+  Hive->FreeListOffset[0] = REG_HBIN_DATA_OFFSET - RootKeyCell->CellSize;
   Hive->FreeListSize++;
 
   return Hive;
@@ -429,7 +467,7 @@ CmiDestroyRegistryHive (PREGISTRY_HIVE Hive)
              Bin = Hive->BlockList[i];
 
              DPRINT ("Bin[%lu]: Offset 0x%lx  Size 0x%lx\n",
-                     i, Bin->BlockOffset, Bin->BlockSize);
+                     i, Bin->BinOffset, Bin->BinSize);
 
              free (Bin);
            }
@@ -449,7 +487,7 @@ CmiDestroyRegistryHive (PREGISTRY_HIVE Hive)
 
 
 static PVOID
-CmiGetBlock(PREGISTRY_HIVE Hive,
+CmiGetCell (PREGISTRY_HIVE Hive,
            BLOCK_OFFSET BlockOffset,
            PHBIN * ppBin)
 {
@@ -470,7 +508,7 @@ CmiGetBlock(PREGISTRY_HIVE Hive,
   if (ppBin)
     *ppBin = pBin;
 
-  return (PVOID)((ULONG_PTR)pBin + (BlockOffset - pBin->BlockOffset));
+  return (PVOID)((ULONG_PTR)pBin + (BlockOffset - pBin->BinOffset));
 }
 
 
@@ -486,18 +524,18 @@ CmiMergeFree(PREGISTRY_HIVE RegistryHive,
   PHBIN Bin;
   ULONG i;
 
-  DPRINT("CmiMergeFree(Block %lx  Offset %lx  Size %lx) called\n",
+  DPRINT("CmiMergeFree(Block %p  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++)
@@ -580,7 +618,7 @@ CmiAddFree(PREGISTRY_HIVE RegistryHive,
   assert(RegistryHive);
   assert(FreeBlock);
 
-  DPRINT("FreeBlock %.08lx  FreeOffset %.08lx\n",
+  DPRINT("FreeBlock %p  FreeOffset %.08lx\n",
         FreeBlock, FreeOffset);
 
   /* Merge free blocks */
@@ -674,30 +712,33 @@ CmiAddFree(PREGISTRY_HIVE RegistryHive,
 
 static BOOL
 CmiAddBin(PREGISTRY_HIVE RegistryHive,
+         ULONG BlockCount,
          PVOID *NewBlock,
          PBLOCK_OFFSET NewBlockOffset)
 {
   PCELL_HEADER tmpBlock;
   PHBIN * tmpBlockList;
   PHBIN tmpBin;
+  ULONG BinSize;
+  ULONG i;
 
-  tmpBin = malloc (REG_BLOCK_SIZE);
+  BinSize = BlockCount *REG_BLOCK_SIZE;
+  tmpBin = malloc (BinSize);
   if (tmpBin == NULL)
     {
       return FALSE;
     }
-  memset (tmpBin, 0, REG_BLOCK_SIZE);
+  memset (tmpBin, 0, BinSize);
 
-  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;
-  tmpBin->DateModified = 0ULL;
-  tmpBin->Unused2 = 0;
+  tmpBin->HeaderId = REG_BIN_ID;
+  tmpBin->BinOffset = RegistryHive->FileSize - REG_BLOCK_SIZE;
+  RegistryHive->FileSize += BinSize;
+  tmpBin->BinSize = BinSize;
+  tmpBin->DateModified = 0;
+  tmpBin->MemAlloc = 0;
 
   /* Increase size of list of blocks */
-  tmpBlockList = malloc (sizeof(PHBIN) * (RegistryHive->BlockListSize + 1));
+  tmpBlockList = malloc (sizeof(PHBIN) * (RegistryHive->BlockListSize + BlockCount));
   if (tmpBlockList == NULL)
     {
       free (tmpBin);
@@ -713,7 +754,9 @@ CmiAddBin(PREGISTRY_HIVE RegistryHive,
     }
 
   RegistryHive->BlockList = tmpBlockList;
-  RegistryHive->BlockList[RegistryHive->BlockListSize++] = tmpBin;
+  for (i = 0; i < BlockCount; i++)
+    RegistryHive->BlockList[RegistryHive->BlockListSize + i] = tmpBin;
+  RegistryHive->BlockListSize += BlockCount;
 
   /* Initialize a free block in this heap : */
   tmpBlock = (PCELL_HEADER)((ULONG_PTR) tmpBin + REG_HBIN_DATA_OFFSET);
@@ -722,32 +765,31 @@ CmiAddBin(PREGISTRY_HIVE RegistryHive,
   *NewBlock = (PVOID) tmpBlock;
 
   if (NewBlockOffset)
-    *NewBlockOffset = tmpBin->BlockOffset + REG_HBIN_DATA_OFFSET;
+    *NewBlockOffset = tmpBin->BinOffset + REG_HBIN_DATA_OFFSET;
 
   return TRUE;
 }
 
 
 static BOOL
-CmiAllocateBlock(PREGISTRY_HIVE RegistryHive,
+CmiAllocateCell (PREGISTRY_HIVE RegistryHive,
+                LONG CellSize,
                 PVOID *Block,
-                LONG BlockSize,
                 PBLOCK_OFFSET pBlockOffset)
 {
   PCELL_HEADER NewBlock;
-  PHBIN pBin;
   ULONG i;
 
   *Block = NULL;
 
   /* Round to 16 bytes multiple */
-  BlockSize = (BlockSize + sizeof(ULONG) + 15) & 0xfffffff0;
+  CellSize = ROUND_UP_POW2(CellSize, 16);
 
   /* first search in free blocks */
   NewBlock = 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)
@@ -773,29 +815,33 @@ CmiAllocateBlock(PREGISTRY_HIVE RegistryHive,
   if (NewBlock == NULL)
     {
       /* Add a new block */
-      if (!CmiAddBin(RegistryHive, (PVOID *)&NewBlock , pBlockOffset))
+      if (!CmiAddBin(RegistryHive,
+                    ((sizeof(HBIN) + CellSize - 1) / REG_BLOCK_SIZE) + 1,
+                    (PVOID *)&NewBlock,
+                    pBlockOffset))
        return FALSE;
     }
 
   *Block = NewBlock;
 
   /* Split the block in two parts */
-  if (NewBlock->CellSize > BlockSize)
+  if (NewBlock->CellSize > CellSize)
     {
-      NewBlock = (PCELL_HEADER) ((ULONG_PTR) NewBlock+BlockSize);
-      NewBlock->CellSize = ((PCELL_HEADER) (*Block))->CellSize - BlockSize;
+      NewBlock = (PCELL_HEADER) ((ULONG_PTR) NewBlock + CellSize);
+      NewBlock->CellSize = ((PCELL_HEADER) (*Block))->CellSize - CellSize;
+      ((PCELL_HEADER) (*Block))->CellSize = CellSize;
       CmiAddFree (RegistryHive,
                  NewBlock,
-                 *pBlockOffset + BlockSize,
+                 *pBlockOffset + CellSize,
                  TRUE);
     }
-  else if (NewBlock->CellSize < BlockSize)
+  else if (NewBlock->CellSize < CellSize)
     {
       return FALSE;
     }
 
-  memset(*Block, 0, BlockSize);
-  ((PCELL_HEADER)(*Block))->CellSize = -BlockSize;
+  memset(*Block, 0, CellSize);
+  ((PCELL_HEADER)(*Block))->CellSize *= -1;
 
   return TRUE;
 }
@@ -804,25 +850,24 @@ CmiAllocateBlock(PREGISTRY_HIVE RegistryHive,
 static BOOL
 CmiAllocateHashTableCell (PREGISTRY_HIVE Hive,
                          PBLOCK_OFFSET HBOffset,
-                         ULONG SubKeyCount)
+                         USHORT SubKeyCount)
 {
   PHASH_TABLE_CELL HashCell;
   ULONG NewHashSize;
   BOOL Status;
 
-  NewHashSize = ROUND_UP(sizeof(HASH_TABLE_CELL) + 
-                        (SubKeyCount - 1) * sizeof(HASH_RECORD),
-                        0x10);
-  Status = CmiAllocateBlock (Hive,
-                            (PVOID*) &HashCell,
-                            NewHashSize,
-                            HBOffset);
+  NewHashSize = sizeof(HASH_TABLE_CELL) + 
+               (SubKeyCount * sizeof(HASH_RECORD));
+  Status = CmiAllocateCell (Hive,
+                           NewHashSize,
+                           (PVOID*) &HashCell,
+                           HBOffset);
   if ((HashCell == NULL) || (Status == FALSE))
     {
       return FALSE;
     }
 
-  HashCell->Id = REG_HASH_TABLE_BLOCK_ID;
+  HashCell->Id = REG_HASH_TABLE_CELL_ID;
   HashCell->HashTableSize = SubKeyCount;
 
   return TRUE;
@@ -839,18 +884,18 @@ CmiAddKeyToParentHashTable (PREGISTRY_HIVE Hive,
   PKEY_CELL ParentKeyCell;
   ULONG i;
 
-  ParentKeyCell = CmiGetBlock (Hive,
-                              ParentKeyOffset,
-                              NULL);
+  ParentKeyCell = CmiGetCell (Hive,
+                             ParentKeyOffset,
+                             NULL);
   if (ParentKeyCell == NULL)
     {
       DPRINT1 ("CmiGetBlock() failed\n");
       return FALSE;
     }
 
-  HashBlock =CmiGetBlock (Hive,
-                         ParentKeyCell->HashTableOffset,
-                         NULL);
+  HashBlock =CmiGetCell (Hive,
+                        ParentKeyCell->HashTableOffset,
+                        NULL);
   if (HashBlock == NULL)
     {
       DPRINT1 ("CmiGetBlock() failed\n");
@@ -883,12 +928,12 @@ CmiAllocateValueListCell (PREGISTRY_HIVE Hive,
   ULONG ValueListSize;
   BOOL Status;
 
-  ValueListSize = ROUND_UP (ValueCount * sizeof(BLOCK_OFFSET),
-                           0x10);
-  Status = CmiAllocateBlock (Hive,
-                            (PVOID)&ValueListCell,
-                            ValueListSize,
-                            ValueListOffset);
+  ValueListSize = sizeof(VALUE_LIST_CELL) +
+                 (ValueCount * sizeof(BLOCK_OFFSET));
+  Status = CmiAllocateCell (Hive,
+                           ValueListSize,
+                           (PVOID)&ValueListCell,
+                           ValueListOffset);
   if ((ValueListCell == NULL) || (Status == FALSE))
     {
       DPRINT1 ("CmiAllocateBlock() failed\n");
@@ -906,13 +951,13 @@ CmiAllocateValueCell(PREGISTRY_HIVE Hive,
                     PCHAR ValueName)
 {
   PVALUE_CELL NewValueCell;
-  ULONG NameSize;
+  USHORT NameSize;
   BOOL Status;
 
   NameSize = (ValueName == NULL) ? 0 : strlen (ValueName);
-  Status = CmiAllocateBlock(Hive,
-                           (PVOID*)&NewValueCell,
+  Status = CmiAllocateCell (Hive,
                            sizeof(VALUE_CELL) + NameSize,
+                           (PVOID*)&NewValueCell,
                            ValueCellOffset);
   if ((NewValueCell == NULL) || (Status == FALSE))
     {
@@ -947,39 +992,27 @@ CmiAddValueToKeyValueList(PREGISTRY_HIVE Hive,
   PVALUE_LIST_CELL ValueListCell;
   PKEY_CELL KeyCell;
 
-  KeyCell = CmiGetBlock (Hive, KeyCellOffset, NULL);
+  KeyCell = CmiGetCell (Hive, KeyCellOffset, NULL);
   if (KeyCell == NULL)
     {
       DPRINT1 ("CmiGetBlock() failed\n");
       return FALSE;
     }
 
-  ValueListCell = CmiGetBlock (Hive, KeyCell->ValuesOffset, NULL);
+  ValueListCell = CmiGetCell (Hive, KeyCell->ValueListOffset, NULL);
   if (ValueListCell == NULL)
     {
       DPRINT1 ("CmiGetBlock() failed\n");
       return FALSE;
     }
 
-  ValueListCell->Values[KeyCell->NumberOfValues] = ValueCellOffset;
+  ValueListCell->ValueOffset[KeyCell->NumberOfValues] = ValueCellOffset;
   KeyCell->NumberOfValues++;
 
   return TRUE;
 }
 
 
-static VOID
-memexpand (PWCHAR Dst,
-          PCHAR Src,
-          ULONG Length)
-{
-  ULONG i;
-
-  for (i = 0; i < Length; i++)
-    Dst[i] = (WCHAR)Src[i];
-}
-
-
 static BOOL
 CmiExportValue (PREGISTRY_HIVE Hive,
                BLOCK_OFFSET KeyCellOffset,
@@ -993,7 +1026,7 @@ CmiExportValue (PREGISTRY_HIVE Hive,
   ULONG SrcDataSize;
   ULONG DstDataSize;
   ULONG DataType;
-  PUCHAR Data;
+  PCHAR Data;
   BOOL Expand = FALSE;
 
   DPRINT ("CmiExportValue('%s') called\n", (Value == NULL) ? "<default>" : (PCHAR)Value->Name);
@@ -1032,9 +1065,9 @@ CmiExportValue (PREGISTRY_HIVE Hive,
       Expand = TRUE;
     }
 
-  if (DstDataSize <= sizeof(BLOCK_OFFSET))
+  if ((DstDataSize & REG_DATA_SIZE_MASK) <= sizeof(BLOCK_OFFSET))
     {
-      ValueCell->DataSize = DstDataSize | 0x80000000;
+      ValueCell->DataSize = DstDataSize | REG_DATA_IN_OFFSET;
       ValueCell->DataType = DataType;
       if (Expand)
        {
@@ -1051,16 +1084,17 @@ CmiExportValue (PREGISTRY_HIVE Hive,
     }
   else
     {
-      if (!CmiAllocateBlock (Hive,
-                            (PVOID *)&DataCell,
-                            DstDataSize,
-                            &DataCellOffset))
+      /* Allocate data cell */
+      if (!CmiAllocateCell (Hive,
+                           sizeof(CELL_HEADER) + DstDataSize,
+                           (PVOID *)&DataCell,
+                           &DataCellOffset))
        {
          return FALSE;
        }
 
       ValueCell->DataOffset = DataCellOffset;
-      ValueCell->DataSize = DstDataSize;
+      ValueCell->DataSize = DstDataSize & REG_DATA_SIZE_MASK;
       ValueCell->DataType = DataType;
 
       if (Expand)
@@ -1099,7 +1133,7 @@ CmiExportSubKey (PREGISTRY_HIVE Hive,
   BLOCK_OFFSET NKBOffset;
   PKEY_CELL NewKeyCell;
   ULONG KeyCellSize;
-  ULONG SubKeyCount;
+  USHORT SubKeyCount;
   ULONG ValueCount;
   PLIST_ENTRY Entry;
   HKEY SubKey;
@@ -1113,7 +1147,7 @@ CmiExportSubKey (PREGISTRY_HIVE Hive,
 
   /* Allocate key cell */
   KeyCellSize = sizeof(KEY_CELL) + Key->NameSize - 1;
-  if (!CmiAllocateBlock (Hive, (PVOID)&NewKeyCell, KeyCellSize, &NKBOffset))
+  if (!CmiAllocateCell (Hive, KeyCellSize, (PVOID)&NewKeyCell, &NKBOffset))
     {
       DPRINT1 ("CmiAllocateBlock() failed\n");
       return FALSE;
@@ -1122,12 +1156,12 @@ CmiExportSubKey (PREGISTRY_HIVE Hive,
   /* Initialize key cell */
   NewKeyCell->Id = REG_KEY_CELL_ID;
   NewKeyCell->Type = REG_KEY_CELL_TYPE;
-  NewKeyCell->LastWriteTime = 0ULL;
+  NewKeyCell->LastWriteTime = 0;
   NewKeyCell->ParentKeyOffset = ParentKeyOffset;
   NewKeyCell->NumberOfSubKeys = 0;
   NewKeyCell->HashTableOffset = -1;
   NewKeyCell->NumberOfValues = 0;
-  NewKeyCell->ValuesOffset = -1;
+  NewKeyCell->ValueListOffset = -1;
   NewKeyCell->SecurityKeyOffset = -1;
   NewKeyCell->NameSize = Key->NameSize - 1;
   NewKeyCell->ClassNameOffset = -1;
@@ -1151,7 +1185,7 @@ CmiExportSubKey (PREGISTRY_HIVE Hive,
     {
       /* Allocate value list cell */
       CmiAllocateValueListCell (Hive,
-                               &NewKeyCell->ValuesOffset,
+                               &NewKeyCell->ValueListOffset,
                                ValueCount);
 
       if (Key->DataSize != 0)
@@ -1225,8 +1259,7 @@ CmiExportHive (PREGISTRY_HIVE Hive,
 {
   PKEY_CELL KeyCell;
   HKEY Key;
-  ULONG i;
-  ULONG SubKeyCount;
+  USHORT SubKeyCount;
   ULONG ValueCount;
   PLIST_ENTRY Entry;
   HKEY SubKey;
@@ -1242,12 +1275,12 @@ CmiExportHive (PREGISTRY_HIVE Hive,
 
   DPRINT ("Name: %s\n", KeyName);
 
-  KeyCell = CmiGetBlock (Hive,
-                        Hive->HiveHeader->RootKeyCell,
-                        NULL);
+  KeyCell = CmiGetCell (Hive,
+                       Hive->HiveHeader->RootKeyOffset,
+                       NULL);
   if (KeyCell == NULL)
     {
-      DPRINT1 ("CmiGetBlock() failed\n");
+      DPRINT1 ("CmiGetCell() failed\n");
       return FALSE;
     }
 
@@ -1257,12 +1290,12 @@ CmiExportHive (PREGISTRY_HIVE Hive,
     {
       /* Allocate value list cell */
       CmiAllocateValueListCell (Hive,
-                               &KeyCell->ValuesOffset,
+                               &KeyCell->ValueListOffset,
                                ValueCount);
 
       if (Key->DataSize != 0)
        {
-         if (!CmiExportValue (Hive, Hive->HiveHeader->RootKeyCell, Key, NULL))
+         if (!CmiExportValue (Hive, Hive->HiveHeader->RootKeyOffset, Key, NULL))
            return FALSE;
        }
 
@@ -1274,7 +1307,7 @@ CmiExportHive (PREGISTRY_HIVE Hive,
                                    VALUE,
                                    ValueList);
 
-         if (!CmiExportValue (Hive, Hive->HiveHeader->RootKeyCell, Key, Value))
+         if (!CmiExportValue (Hive, Hive->HiveHeader->RootKeyOffset, Key, Value))
            return FALSE;
 
          Entry = Entry->Flink;
@@ -1298,7 +1331,7 @@ CmiExportHive (PREGISTRY_HIVE Hive,
                                     KEY,
                                     KeyList);
 
-         if (!CmiExportSubKey (Hive, Hive->HiveHeader->RootKeyCell, Key, SubKey))
+         if (!CmiExportSubKey (Hive, Hive->HiveHeader->RootKeyOffset, Key, SubKey))
            return FALSE;
 
          Entry = Entry->Flink;
@@ -1319,6 +1352,7 @@ CmiWriteHive(PREGISTRY_HIVE Hive,
   FILE *File;
   ULONG i;
 
+#if 0
   /* Check for existing hive file */
   File = fopen (FileName, "rb");
   if (File != NULL)
@@ -1327,11 +1361,13 @@ CmiWriteHive(PREGISTRY_HIVE Hive,
       fclose (File);
       return TRUE;
     }
+#endif
 
   /* Create new hive file */
   File = fopen (FileName, "w+b");
   if (File == NULL)
     {
+      printf("    Error creating/opening file\n");
       return FALSE;
     }
 
@@ -1351,9 +1387,9 @@ CmiWriteHive(PREGISTRY_HIVE Hive,
          Bin = Hive->BlockList[i];
 
          DPRINT ("Bin[%lu]: Offset 0x%lx  Size 0x%lx\n",
-                 i, Bin->BlockOffset, Bin->BlockSize);
+                 i, Bin->BinOffset, Bin->BinSize);
 
-         fwrite (Bin, Bin->BlockSize, 1, File);
+         fwrite (Bin, Bin->BinSize, 1, File);
        }
     }
 
@@ -1371,7 +1407,7 @@ ExportBinaryHive (PCHAR FileName,
 
   printf ("  Creating binary hive: %s\n", FileName);
 
-  Hive = CmiCreateRegistryHive ();
+  Hive = CmiCreateRegistryHive (KeyName);
   if (Hive == NULL)
     return FALSE;