Let mkhive use cmlib. "make install" now works and this let the livecd go further...
authorHervé Poussineau <hpoussin@reactos.org>
Sun, 10 Sep 2006 15:39:11 +0000 (15:39 +0000)
committerHervé Poussineau <hpoussin@reactos.org>
Sun, 10 Sep 2006 15:39:11 +0000 (15:39 +0000)
svn path=/trunk/; revision=24026

12 files changed:
reactos/tools/mkhive/binhive.c
reactos/tools/mkhive/binhive.h
reactos/tools/mkhive/cmi.c [new file with mode: 0644]
reactos/tools/mkhive/cmi.h [new file with mode: 0644]
reactos/tools/mkhive/mkhive.c
reactos/tools/mkhive/mkhive.h
reactos/tools/mkhive/mkhive.mak
reactos/tools/mkhive/reginf.c
reactos/tools/mkhive/reginf.h
reactos/tools/mkhive/registry.c
reactos/tools/mkhive/registry.h
reactos/tools/mkhive/rtl.c [new file with mode: 0644]

index cc50be3..cf17a8b 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ReactOS kernel
- *  Copyright (C) 2003, 2004 ReactOS Team
+ *  Copyright (C) 2006 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
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id$
- * COPYRIGHT:       See COPYING in the top level directory
+/* COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS hive maker
  * FILE:            tools/mkhive/binhive.c
  * PURPOSE:         Binary hive export code
- * PROGRAMMER:      Eric Kohl
+ * PROGRAMMER:      Hervé Poussineau
  */
 
 /* INCLUDES *****************************************************************/
 
-//#include <assert.h>
-#include <stdlib.h>
 #include <stdio.h>
-#include <string.h>
 
 #include "mkhive.h"
-#include "binhive.h"
-#include "registry.h"
-
-
-#define  REG_HIVE_ID                   0x66676572
-#define  REG_BIN_ID                    0x6e696268
-#define  REG_KEY_CELL_ID               0x6b6e
-#define  REG_HASH_TABLE_CELL_ID        0x666c
-#define  REG_VALUE_CELL_ID             0x6b76
-
-#define  REG_BLOCK_SIZE                4096
-#define  REG_HBIN_DATA_OFFSET          32
-#define  REG_INIT_BLOCK_LIST_SIZE      32
-#define  REG_INIT_HASH_TABLE_SIZE      3
-#define  REG_EXTEND_HASH_TABLE_SIZE    4
-#define  REG_VALUE_LIST_CELL_MULTIPLE  4
-
-#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
-{
-  /* Hive identifier "regf" (0x66676572) */
-  ULONG  BlockId;
-
-  /* Update counter */
-  ULONG  UpdateCounter1;
-
-  /* Update counter */
-  ULONG  UpdateCounter2;
-
-  /* When this hive file was last modified */
-  FILETIME  DateModified;
-
-  /* Registry format major version (1) */
-  ULONG  MajorVersion;
-
-  /* Registry format minor version (3)
-     Version 3 added fast indexes, version 5 has large value optimizations */
-  ULONG  MinorVersion;
-
-  /* Registry file type (0 - Primary, 1 - Log) */
-  ULONG  Type;
-
-  /* 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  RootKeyOffset;
-
-  /* Size of each hive block ? */
-  ULONG  BlockSize;
-
-  /* (1?) */
-  ULONG  Unused7;
-
-  /* Name of hive file */
-  WCHAR  FileName[32];
-
-  ULONG  Reserved[99];
-
-  /* Checksum of first 0x200 bytes */
-  ULONG  Checksum;
-} GCC_PACKED HIVE_HEADER, *PHIVE_HEADER;
-
-typedef struct _HBIN
-{
-  /* Bin identifier "hbin" (0x6E696268) */
-  ULONG  HeaderId;
-
-  /* Block offset of this bin */
-  BLOCK_OFFSET  BinOffset;
-
-  /* Size in bytes, multiple of the block size (4KB) */
-  ULONG  BinSize;
-
-  ULONG  Reserved[2];
-
-  /* When this bin was last modified */
-  FILETIME  DateModified;
-
-  /* ? (In-memory only) */
-  ULONG  MemAlloc;
-} GCC_PACKED HBIN, *PHBIN;
-
-typedef struct _CELL_HEADER
-{
-  /* <0 if used, >0 if free */
-  LONG  CellSize;
-} GCC_PACKED CELL_HEADER, *PCELL_HEADER;
-
-typedef struct _KEY_CELL
-{
-  /* Size of this cell */
-  LONG  CellSize;
-
-  /* Key cell identifier "kn" (0x6b6e) */
-  USHORT  Id;
-
-  /* ? */
-  USHORT  Type;
-
-  /* Time of last flush */
-  FILETIME  LastWriteTime;
-
-  /* ? */
-  ULONG  UnUsed1;
-
-  /* Block offset of parent key cell */
-  BLOCK_OFFSET  ParentKeyOffset;
-
-  /* Count of sub keys for the key in this key cell */
-  ULONG  NumberOfSubKeys;
-
-  /* ? */
-  ULONG  UnUsed2;
-
-  /* Block offset of has table for FIXME: subkeys/values? */
-  BLOCK_OFFSET  HashTableOffset;
-
-  /* ? */
-  ULONG  UnUsed3;
-
-  /* Count of values contained in this key cell */
-  ULONG  NumberOfValues;
-
-  /* Block offset of VALUE_LIST_CELL */
-  BLOCK_OFFSET  ValueListOffset;
-
-  /* Block offset of security cell */
-  BLOCK_OFFSET  SecurityKeyOffset;
-
-  /* Block offset of registry key class */
-  BLOCK_OFFSET  ClassNameOffset;
-
-  /* ? */
-  ULONG  Unused4[5];
-
-  /* Size in bytes of key name */
-  USHORT  NameSize;
-
-  /* Size of class name in bytes */
-  USHORT  ClassSize;
-
-  /* Name of key (not zero terminated) */
-  CHAR  Name[0];
-} GCC_PACKED KEY_CELL, *PKEY_CELL;
-
-/* KEY_CELL.Type constants */
-#define  REG_LINK_KEY_CELL_TYPE        0x10
-#define  REG_KEY_CELL_TYPE             0x20
-#define  REG_ROOT_KEY_CELL_TYPE        0x2c
-
-
-// hash record :
-// HashValue=four letters of value's name
-typedef struct _HASH_RECORD
-{
-  BLOCK_OFFSET  KeyOffset;
-  ULONG  HashValue;
-} GCC_PACKED HASH_RECORD, *PHASH_RECORD;
-
-typedef struct _HASH_TABLE_CELL
-{
-  LONG  CellSize;
-  USHORT  Id;
-  USHORT  HashTableSize;
-  HASH_RECORD  Table[0];
-} GCC_PACKED HASH_TABLE_CELL, *PHASH_TABLE_CELL;
-
-typedef struct _VALUE_LIST_CELL
-{
-  LONG  CellSize;
-  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
-  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;
-  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;
-  CHAR  Data[0];
-} GCC_PACKED DATA_CELL, *PDATA_CELL;
-
-#ifdef _MSC_VER
-#pragma pack ( pop, hive_header )
-#endif//_MSC_VER
-
-typedef struct _REGISTRY_HIVE
-{
-  ULONG  FileSize;
-  PHIVE_HEADER  HiveHeader;
-  ULONG  BlockListSize;
-  PHBIN  *BlockList;
-  ULONG  FreeListSize;
-  ULONG  FreeListMax;
-  PCELL_HEADER *FreeList;
-  BLOCK_OFFSET *FreeListOffset;
-} REGISTRY_HIVE, *PREGISTRY_HIVE;
-
-/* FUNCTIONS ****************************************************************/
-
-static VOID
-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);
-  memset (Header, 0, REG_BLOCK_SIZE);
-  Header->BlockId = REG_HIVE_ID;
-  Header->UpdateCounter1 = 0;
-  Header->UpdateCounter2 = 0;
-  Header->DateModified = 0;
-  Header->MajorVersion = 1;
-  Header->MinorVersion = 3;
-  Header->Type = 0;
-  Header->Format = 1;
-  Header->Unused7 = 1;
-  Header->RootKeyOffset = -1;
-  Header->BlockSize = REG_BLOCK_SIZE;
-  Header->Checksum = 0;
-}
-
-
-static VOID
-CmiCreateDefaultBinCell(PHBIN BinCell)
-{
-  assert (BinCell);
-  memset (BinCell, 0, REG_BLOCK_SIZE);
-  BinCell->HeaderId = REG_BIN_ID;
-  BinCell->DateModified = 0;
-  BinCell->BinSize = REG_BLOCK_SIZE;
-}
-
-
-static VOID
-CmiCreateDefaultRootKeyCell(PKEY_CELL RootKeyCell, PCHAR KeyName)
-{
-  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 = 0;
-  RootKeyCell->ParentKeyOffset = 0;
-  RootKeyCell->NumberOfSubKeys = 0;
-  RootKeyCell->HashTableOffset = -1;
-  RootKeyCell->NumberOfValues = 0;
-  RootKeyCell->ValueListOffset = -1;
-  RootKeyCell->SecurityKeyOffset = 0;
-  RootKeyCell->ClassNameOffset = -1;
-  RootKeyCell->NameSize = NameSize;
-  RootKeyCell->ClassSize = 0;
-  memcpy (RootKeyCell->Name,
-         BaseKeyName,
-         NameSize);
-}
-
-
-static PREGISTRY_HIVE
-CmiCreateRegistryHive (PCHAR KeyName)
-{
-  PREGISTRY_HIVE Hive;
-  PCELL_HEADER FreeCell;
-  PKEY_CELL RootKeyCell;
-  PHBIN BinCell;
-
-  Hive = (PREGISTRY_HIVE) malloc (sizeof(REGISTRY_HIVE));
-  if (Hive == NULL)
-    {
-      return NULL;
-    }
-  memset (Hive, 0, sizeof(REGISTRY_HIVE));
-
-  DPRINT("Hive %p\n", Hive);
-
-  /* Create hive beader (aka 'base block') */
-  Hive->HiveHeader = (PHIVE_HEADER) malloc (REG_BLOCK_SIZE);
-  if (Hive->HiveHeader == NULL)
-    {
-      free (Hive);
-      return NULL;
-    }
-  CmiCreateDefaultHiveHeader (Hive->HiveHeader);
-  Hive->FileSize = REG_BLOCK_SIZE;
-
-  /* Allocate block list */
-  Hive->BlockListSize = 1;
-  Hive->BlockList = malloc (sizeof(PHBIN) * Hive->BlockListSize);
-  if (Hive->BlockList == NULL)
-    {
-      free (Hive->HiveHeader);
-      free (Hive);
-      return NULL;
-    }
-
-  /* Allocate free cell list */
-  Hive->FreeListMax = 32;
-  Hive->FreeList = malloc(sizeof(PCELL_HEADER) * Hive->FreeListMax);
-  if (Hive->FreeList == NULL)
-    {
-      free (Hive->BlockList);
-      free (Hive->HiveHeader);
-      free (Hive);
-      return NULL;
-    }
-  Hive->FreeListOffset = malloc(sizeof(BLOCK_OFFSET) * Hive->FreeListMax);
-  if (Hive->FreeListOffset == NULL)
-    {
-      free (Hive->FreeList);
-      free (Hive->BlockList);
-      free (Hive->HiveHeader);
-      free (Hive);
-      return NULL;
-    }
-
-  /* Allocate first bin */
-  Hive->BlockList[0] = (PHBIN) malloc (REG_BLOCK_SIZE);
-  if (Hive->BlockList[0] == NULL)
-    {
-      free (Hive->FreeListOffset);
-      free (Hive->FreeList);
-      free (Hive->BlockList);
-      free (Hive->HiveHeader);
-      free (Hive);
-      return NULL;
-    }
-  Hive->FileSize += REG_BLOCK_SIZE;
-
-  /* Init first bin */
-  BinCell = (PHBIN)Hive->BlockList[0];
-  CmiCreateDefaultBinCell (BinCell);
-  BinCell->BinOffset = 0;
-
-  /* Init root key cell */
-  RootKeyCell = (PKEY_CELL)((ULONG_PTR)BinCell + REG_HBIN_DATA_OFFSET);
-  CmiCreateDefaultRootKeyCell (RootKeyCell, KeyName);
-  Hive->HiveHeader->RootKeyOffset = REG_HBIN_DATA_OFFSET;
-
-  /* Init free 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 - RootKeyCell->CellSize;
-  Hive->FreeListSize++;
-
-  return Hive;
-}
-
-
-static VOID
-CmiDestroyRegistryHive (PREGISTRY_HIVE Hive)
-{
-  PHBIN Bin;
-  ULONG i;
-
-  if (Hive == NULL)
-    return;
-
-  /* Release free offset list */
-  if (Hive->FreeListOffset != NULL)
-    free (Hive->FreeListOffset);
-
-  /* Release free list */
-  if (Hive->FreeList != NULL)
-    free (Hive->FreeList);
-
-  if (Hive->BlockList != NULL)
-    {
-      /* Release bins */
-      Bin = NULL;
-      for (i = 0; i < Hive->BlockListSize; i++)
-       {
-         if ((Hive->BlockList[i] != NULL) &&
-             (Hive->BlockList[i] != Bin))
-           {
-             Bin = Hive->BlockList[i];
-
-             DPRINT ("Bin[%lu]: Offset 0x%lx  Size 0x%lx\n",
-                     i, Bin->BinOffset, Bin->BinSize);
-
-             free (Bin);
-           }
-       }
-
-      /* Release block list */
-      free (Hive->BlockList);
-    }
-
-  /* Release hive header */
-  if (Hive->HiveHeader != NULL)
-    free (Hive->HiveHeader);
-
-  /* Release hive */
-  free (Hive);
-}
-
-
-static PVOID
-CmiGetCell (PREGISTRY_HIVE Hive,
-           BLOCK_OFFSET BlockOffset,
-           PHBIN * ppBin)
-{
-  PHBIN pBin;
-  ULONG BlockIndex;
-
-  if (ppBin)
-    *ppBin = NULL;
-
-  if (BlockOffset == (ULONG_PTR) -1)
-    return NULL;
-
-  BlockIndex = BlockOffset / 4096;
-  if (BlockIndex >= Hive->BlockListSize)
-    return NULL;
-
-  pBin = Hive->BlockList[BlockIndex];
-  if (ppBin)
-    *ppBin = pBin;
-
-  return (PVOID)((ULONG_PTR)pBin + (BlockOffset - pBin->BinOffset));
-}
-
-
-static BOOL
-CmiMergeFree(PREGISTRY_HIVE RegistryHive,
-            PCELL_HEADER FreeBlock,
-            BLOCK_OFFSET FreeOffset)
-{
-  BLOCK_OFFSET BlockOffset;
-  BLOCK_OFFSET BinOffset;
-  ULONG BlockSize;
-  ULONG BinSize;
-  PHBIN Bin;
-  ULONG i;
-
-  DPRINT("CmiMergeFree(Block %p  Offset %lx  Size %lx) called\n",
-        FreeBlock, FreeOffset, FreeBlock->CellSize);
-
-  CmiGetCell (RegistryHive,
-             FreeOffset,
-             &Bin);
-  DPRINT("Bin %p\n", Bin);
-  if (Bin == NULL)
-    return FALSE;
-
-  BinOffset = Bin->BinOffset;
-  BinSize = Bin->BinSize;
-  DPRINT("Bin %p  Offset %lx  Size %lx\n", Bin, BinOffset, BinSize);
-
-  for (i = 0; i < RegistryHive->FreeListSize; i++)
-    {
-      BlockOffset = RegistryHive->FreeListOffset[i];
-      BlockSize = RegistryHive->FreeList[i]->CellSize;
-      if (BlockOffset > BinOffset &&
-         BlockOffset < BinOffset + BinSize)
-       {
-         DPRINT("Free block: Offset %lx  Size %lx\n",
-                 BlockOffset, BlockSize);
-
-         if ((i < (RegistryHive->FreeListSize - 1)) &&
-             (BlockOffset + BlockSize == FreeOffset) &&
-             (FreeOffset + FreeBlock->CellSize == RegistryHive->FreeListOffset[i + 1]))
-           {
-             DPRINT("Merge current block with previous and next block\n");
-
-             RegistryHive->FreeList[i]->CellSize +=
-               (FreeBlock->CellSize + RegistryHive->FreeList[i + 1]->CellSize);
-
-             FreeBlock->CellSize = 0;
-             RegistryHive->FreeList[i + 1]->CellSize = 0;
-
-
-             if ((i + 2) < RegistryHive->FreeListSize)
-               {
-                 memmove (&RegistryHive->FreeList[i + 1],
-                          &RegistryHive->FreeList[i + 2],
-                          sizeof(RegistryHive->FreeList[0])
-                            * (RegistryHive->FreeListSize - i - 2));
-                 memmove (&RegistryHive->FreeListOffset[i + 1],
-                          &RegistryHive->FreeListOffset[i + 2],
-                          sizeof(RegistryHive->FreeListOffset[0])
-                            * (RegistryHive->FreeListSize - i - 2));
-               }
-             RegistryHive->FreeListSize--;
-
-             return TRUE;
-           }
-         else if (BlockOffset + BlockSize == FreeOffset)
-           {
-             DPRINT("Merge current block with previous block\n");
-
-             RegistryHive->FreeList[i]->CellSize += FreeBlock->CellSize;
-             FreeBlock->CellSize = 0;
-
-             return TRUE;
-           }
-         else if (FreeOffset + FreeBlock->CellSize == BlockOffset)
-           {
-             DPRINT("Merge current block with next block\n");
-
-             FreeBlock->CellSize += RegistryHive->FreeList[i]->CellSize;
-             RegistryHive->FreeList[i]->CellSize = 0;
-             RegistryHive->FreeList[i] = FreeBlock;
-             RegistryHive->FreeListOffset[i] = FreeOffset;
-
-             return TRUE;
-           }
-       }
-    }
-
-  return FALSE;
-}
-
-
-static BOOL
-CmiAddFree(PREGISTRY_HIVE RegistryHive,
-          PCELL_HEADER FreeBlock,
-          BLOCK_OFFSET FreeOffset,
-          BOOL MergeFreeBlocks)
-{
-  PCELL_HEADER *tmpList;
-  BLOCK_OFFSET *tmpListOffset;
-  LONG minInd;
-  LONG maxInd;
-  LONG medInd;
-
-  assert(RegistryHive);
-  assert(FreeBlock);
-
-  DPRINT("FreeBlock %p  FreeOffset %.08lx\n",
-        FreeBlock, FreeOffset);
-
-  /* Merge free blocks */
-  if (MergeFreeBlocks == TRUE)
-    {
-      if (CmiMergeFree(RegistryHive, FreeBlock, FreeOffset))
-       return TRUE;
-    }
-
-  if ((RegistryHive->FreeListSize + 1) > RegistryHive->FreeListMax)
-    {
-      tmpList = malloc (sizeof(PCELL_HEADER) * (RegistryHive->FreeListMax + 32));
-      if (tmpList == NULL)
-       {
-         return FALSE;
-       }
-
-      tmpListOffset = malloc (sizeof(BLOCK_OFFSET) * (RegistryHive->FreeListMax + 32));
-      if (tmpListOffset == NULL)
-       {
-         free (tmpList);
-         return FALSE;
-       }
-
-      if (RegistryHive->FreeListMax)
-       {
-         memmove (tmpList,
-                  RegistryHive->FreeList,
-                  sizeof(PCELL_HEADER) * (RegistryHive->FreeListMax));
-         memmove (tmpListOffset,
-                  RegistryHive->FreeListOffset,
-                  sizeof(BLOCK_OFFSET) * (RegistryHive->FreeListMax));
-         free (RegistryHive->FreeList);
-         free (RegistryHive->FreeListOffset);
-       }
-      RegistryHive->FreeList = tmpList;
-      RegistryHive->FreeListOffset = tmpListOffset;
-      RegistryHive->FreeListMax += 32;
-    }
-
-  /* Add new offset to free list, maintaining list in ascending order */
-  if ((RegistryHive->FreeListSize == 0)
-     || (RegistryHive->FreeListOffset[RegistryHive->FreeListSize-1] < FreeOffset))
-    {
-      /* Add to end of list */
-      RegistryHive->FreeList[RegistryHive->FreeListSize] = FreeBlock;
-      RegistryHive->FreeListOffset[RegistryHive->FreeListSize++] = FreeOffset;
-    }
-  else if (RegistryHive->FreeListOffset[0] > FreeOffset)
-    {
-      /* Add to begin of list */
-      memmove (&RegistryHive->FreeList[1],
-              &RegistryHive->FreeList[0],
-              sizeof(RegistryHive->FreeList[0]) * RegistryHive->FreeListSize);
-      memmove (&RegistryHive->FreeListOffset[1],
-              &RegistryHive->FreeListOffset[0],
-              sizeof(RegistryHive->FreeListOffset[0]) * RegistryHive->FreeListSize);
-      RegistryHive->FreeList[0] = FreeBlock;
-      RegistryHive->FreeListOffset[0] = FreeOffset;
-      RegistryHive->FreeListSize++;
-    }
-  else
-    {
-      /* Search where to insert */
-      minInd = 0;
-      maxInd = RegistryHive->FreeListSize - 1;
-      while ((maxInd - minInd) > 1)
-       {
-         medInd = (minInd + maxInd) / 2;
-         if (RegistryHive->FreeListOffset[medInd] > FreeOffset)
-           maxInd = medInd;
-         else
-           minInd = medInd;
-       }
-
-      /* Insert before maxInd */
-      memmove (&RegistryHive->FreeList[maxInd+1],
-              &RegistryHive->FreeList[maxInd],
-              sizeof(RegistryHive->FreeList[0]) * (RegistryHive->FreeListSize - minInd));
-      memmove (&RegistryHive->FreeListOffset[maxInd + 1],
-              &RegistryHive->FreeListOffset[maxInd],
-              sizeof(RegistryHive->FreeListOffset[0]) * (RegistryHive->FreeListSize-minInd));
-      RegistryHive->FreeList[maxInd] = FreeBlock;
-      RegistryHive->FreeListOffset[maxInd] = FreeOffset;
-      RegistryHive->FreeListSize++;
-    }
-
-  return TRUE;
-}
-
-
-static BOOL
-CmiAddBin(PREGISTRY_HIVE RegistryHive,
-         ULONG BlockCount,
-         PVOID *NewBlock,
-         PBLOCK_OFFSET NewBlockOffset)
-{
-  PCELL_HEADER tmpBlock;
-  PHBIN * tmpBlockList;
-  PHBIN tmpBin;
-  ULONG BinSize;
-  ULONG i;
-
-  BinSize = BlockCount *REG_BLOCK_SIZE;
-  tmpBin = malloc (BinSize);
-  if (tmpBin == NULL)
-    {
-      return FALSE;
-    }
-  memset (tmpBin, 0, BinSize);
-
-  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 + BlockCount));
-  if (tmpBlockList == NULL)
-    {
-      free (tmpBin);
-      return FALSE;
-    }
-
-  if (RegistryHive->BlockListSize > 0)
-    {
-      memcpy (tmpBlockList,
-             RegistryHive->BlockList,
-             sizeof(PHBIN) * RegistryHive->BlockListSize);
-      free (RegistryHive->BlockList);
-    }
-
-  RegistryHive->BlockList = tmpBlockList;
-  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);
-  tmpBlock->CellSize = (REG_BLOCK_SIZE - REG_HBIN_DATA_OFFSET);
-
-  *NewBlock = (PVOID) tmpBlock;
-
-  if (NewBlockOffset)
-    *NewBlockOffset = tmpBin->BinOffset + REG_HBIN_DATA_OFFSET;
-
-  return TRUE;
-}
-
-
-static BOOL
-CmiAllocateCell (PREGISTRY_HIVE RegistryHive,
-                LONG CellSize,
-                PVOID *Block,
-                PBLOCK_OFFSET pBlockOffset)
-{
-  PCELL_HEADER NewBlock;
-  ULONG i;
-
-  *Block = NULL;
-
-  /* Round to 16 bytes multiple */
-  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 >= CellSize)
-       {
-         NewBlock = RegistryHive->FreeList[i];
-         if (pBlockOffset)
-           *pBlockOffset = RegistryHive->FreeListOffset[i];
-
-         if ((i + 1) < RegistryHive->FreeListSize)
-           {
-             memmove (&RegistryHive->FreeList[i],
-                      &RegistryHive->FreeList[i + 1],
-                      sizeof(RegistryHive->FreeList[0])
-                        * (RegistryHive->FreeListSize - i - 1));
-             memmove (&RegistryHive->FreeListOffset[i],
-                      &RegistryHive->FreeListOffset[i + 1],
-                      sizeof(RegistryHive->FreeListOffset[0])
-                        * (RegistryHive->FreeListSize - i - 1));
-           }
-         RegistryHive->FreeListSize--;
-         break;
-       }
-    }
-
-  /* Need to extend hive file : */
-  if (NewBlock == NULL)
-    {
-      /* Add a new block */
-      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 > CellSize)
-    {
-      NewBlock = (PCELL_HEADER) ((ULONG_PTR) NewBlock + CellSize);
-      NewBlock->CellSize = ((PCELL_HEADER) (*Block))->CellSize - CellSize;
-      ((PCELL_HEADER) (*Block))->CellSize = CellSize;
-      CmiAddFree (RegistryHive,
-                 NewBlock,
-                 *pBlockOffset + CellSize,
-                 TRUE);
-    }
-  else if (NewBlock->CellSize < CellSize)
-    {
-      return FALSE;
-    }
-
-  memset((PVOID)((ULONG_PTR)*Block + sizeof(CELL_HEADER)), 0,
-         CellSize - sizeof(CELL_HEADER));
-  ((PCELL_HEADER)(*Block))->CellSize *= -1;
-
-  return TRUE;
-}
-
-
-static BOOL
-CmiAllocateHashTableCell (PREGISTRY_HIVE Hive,
-                         PBLOCK_OFFSET HBOffset,
-                         USHORT SubKeyCount)
-{
-  PHASH_TABLE_CELL HashCell;
-  ULONG NewHashSize;
-  BOOL Status;
-
-  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_CELL_ID;
-  HashCell->HashTableSize = SubKeyCount;
-
-  return TRUE;
-}
-
-
-static BOOL
-CmiAddKeyToParentHashTable (PREGISTRY_HIVE Hive,
-                           BLOCK_OFFSET ParentKeyOffset,
-                           PKEY_CELL NewKeyCell,
-                           BLOCK_OFFSET NKBOffset)
-{
-  PHASH_TABLE_CELL HashBlock;
-  PKEY_CELL ParentKeyCell;
-  ULONG i;
-
-  ParentKeyCell = CmiGetCell (Hive,
-                             ParentKeyOffset,
-                             NULL);
-  if (ParentKeyCell == NULL)
-    {
-      DPRINT1 ("CmiGetBlock() failed\n");
-      return FALSE;
-    }
-
-  HashBlock =CmiGetCell (Hive,
-                        ParentKeyCell->HashTableOffset,
-                        NULL);
-  if (HashBlock == NULL)
-    {
-      DPRINT1 ("CmiGetBlock() failed\n");
-      return FALSE;
-    }
-
-  for (i = 0; i < HashBlock->HashTableSize; i++)
-    {
-      if (HashBlock->Table[i].KeyOffset == 0)
-       {
-         HashBlock->Table[i].KeyOffset = NKBOffset;
-         memcpy (&HashBlock->Table[i].HashValue,
-                 NewKeyCell->Name,
-                 4);
-         ParentKeyCell->NumberOfSubKeys++;
-         return TRUE;
-       }
-    }
-
-  return FALSE;
-}
-
-
-static BOOL
-CmiAllocateValueListCell (PREGISTRY_HIVE Hive,
-                         PBLOCK_OFFSET ValueListOffset,
-                         ULONG ValueCount)
-{
-  PVALUE_LIST_CELL ValueListCell;
-  ULONG ValueListSize;
-  BOOL Status;
-
-  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");
-      return FALSE;
-    }
-
-  return TRUE;
-}
-
-
-static BOOL
-CmiAllocateValueCell(PREGISTRY_HIVE Hive,
-                    PVALUE_CELL *ValueCell,
-                    BLOCK_OFFSET *ValueCellOffset,
-                    PCHAR ValueName)
-{
-  PVALUE_CELL NewValueCell;
-  USHORT NameSize;
-  BOOL Status;
-
-  NameSize = (ValueName == NULL) ? 0 : strlen (ValueName);
-  Status = CmiAllocateCell (Hive,
-                           sizeof(VALUE_CELL) + NameSize,
-                           (PVOID*)&NewValueCell,
-                           ValueCellOffset);
-  if ((NewValueCell == NULL) || (Status == FALSE))
-    {
-      DPRINT1 ("CmiAllocateBlock() failed\n");
-      return FALSE;
-    }
-
-  NewValueCell->Id = REG_VALUE_CELL_ID;
-  NewValueCell->NameSize = NameSize;
-  if (NameSize > 0)
-    {
-      memcpy (NewValueCell->Name,
-             ValueName,
-             NameSize);
-      NewValueCell->Flags = REG_VALUE_NAME_PACKED;
-    }
-  NewValueCell->DataType = 0;
-  NewValueCell->DataSize = 0;
-  NewValueCell->DataOffset = -1;
-
-  *ValueCell = NewValueCell;
-
-  return TRUE;
-}
-
-
-static BOOL
-CmiAddValueToKeyValueList(PREGISTRY_HIVE Hive,
-                         BLOCK_OFFSET KeyCellOffset,
-                         BLOCK_OFFSET ValueCellOffset)
-{
-  PVALUE_LIST_CELL ValueListCell;
-  PKEY_CELL KeyCell;
-
-  KeyCell = CmiGetCell (Hive, KeyCellOffset, NULL);
-  if (KeyCell == NULL)
-    {
-      DPRINT1 ("CmiGetBlock() failed\n");
-      return FALSE;
-    }
-
-  ValueListCell = CmiGetCell (Hive, KeyCell->ValueListOffset, NULL);
-  if (ValueListCell == NULL)
-    {
-      DPRINT1 ("CmiGetBlock() failed\n");
-      return FALSE;
-    }
-
-  ValueListCell->ValueOffset[KeyCell->NumberOfValues] = ValueCellOffset;
-  KeyCell->NumberOfValues++;
-
-  return TRUE;
-}
-
-
-static BOOL
-CmiExportValue (PREGISTRY_HIVE Hive,
-               BLOCK_OFFSET KeyCellOffset,
-               HKEY Key,
-               PVALUE Value)
-{
-  BLOCK_OFFSET ValueCellOffset;
-  BLOCK_OFFSET DataCellOffset;
-  PVALUE_CELL ValueCell;
-  PDATA_CELL DataCell;
-  ULONG SrcDataSize;
-  ULONG DstDataSize;
-  ULONG DataType;
-  PCHAR Data;
-  BOOL Expand = FALSE;
-
-  DPRINT ("CmiExportValue('%s') called\n", (Value == NULL) ? "<default>" : (PCHAR)Value->Name);
-  DPRINT ("DataSize %lu\n", (Value == NULL) ? Key->DataSize : Value->DataSize);
-
-  /* Allocate value cell */
-  if (!CmiAllocateValueCell(Hive, &ValueCell, &ValueCellOffset, (Value == NULL) ? NULL : Value->Name))
-    {
-      return FALSE;
-    }
-
-  if (!CmiAddValueToKeyValueList(Hive, KeyCellOffset, ValueCellOffset))
-    {
-      return FALSE;
-    }
-
-  if (Value == NULL)
-    {
-      DataType = Key->DataType;
-      SrcDataSize = Key->DataSize;
-      Data = Key->Data;
-    }
-  else
-    {
-      DataType = Value->DataType;
-      SrcDataSize = Value->DataSize;
-      Data = Value->Data;
-    }
-
-  DstDataSize = SrcDataSize;
-  if (DataType == REG_SZ ||
-      DataType == REG_EXPAND_SZ ||
-      DataType == REG_MULTI_SZ)
-    {
-      DstDataSize *= sizeof(WCHAR);
-      Expand = TRUE;
-    }
-
-  if ((DstDataSize & REG_DATA_SIZE_MASK) <= sizeof(BLOCK_OFFSET))
-    {
-      ValueCell->DataSize = DstDataSize | REG_DATA_IN_OFFSET;
-      ValueCell->DataType = DataType;
-      if (Expand)
-       {
-         memexpand ((PWCHAR)&ValueCell->DataOffset,
-                    (PCHAR)&Data,
-                    SrcDataSize);
-       }
-      else
-       {
-         memcpy (&ValueCell->DataOffset,
-                 &Data,
-                 SrcDataSize);
-       }
-    }
-  else
-    {
-      /* Allocate data cell */
-      if (!CmiAllocateCell (Hive,
-                           sizeof(CELL_HEADER) + DstDataSize,
-                           (PVOID *)&DataCell,
-                           &DataCellOffset))
-       {
-         return FALSE;
-       }
-
-      ValueCell->DataOffset = DataCellOffset;
-      ValueCell->DataSize = DstDataSize & REG_DATA_SIZE_MASK;
-      ValueCell->DataType = DataType;
-
-      if (Expand)
-       {
-         if (SrcDataSize <= sizeof(BLOCK_OFFSET))
-           {
-             memexpand ((PWCHAR)DataCell->Data,
-                        (PCHAR)&Data,
-                        SrcDataSize);
-           }
-         else
-           {
-             memexpand ((PWCHAR)DataCell->Data,
-                        Data,
-                        SrcDataSize);
-           }
-       }
-      else
-       {
-         memcpy (DataCell->Data,
-                 Data,
-                 SrcDataSize);
-       }
-    }
-
-  return TRUE;
-}
-
-
-static BOOL
-CmiExportSubKey (PREGISTRY_HIVE Hive,
-                BLOCK_OFFSET ParentKeyOffset,
-                HKEY ParentKey,
-                HKEY Key)
-{
-  BLOCK_OFFSET NKBOffset;
-  PKEY_CELL NewKeyCell;
-  ULONG KeyCellSize;
-  USHORT SubKeyCount;
-  ULONG ValueCount;
-  PLIST_ENTRY Entry;
-  HKEY SubKey;
-  PVALUE Value;
-
-  DPRINT ("CmiExportSubKey('%s') called\n", Key->Name);
-
-  /* Don't export links */
-  if (Key->DataType == REG_LINK)
-    return TRUE;
-
-  /* Allocate key cell */
-  KeyCellSize = sizeof(KEY_CELL) + Key->NameSize - 1;
-  if (!CmiAllocateCell (Hive, KeyCellSize, (PVOID)&NewKeyCell, &NKBOffset))
-    {
-      DPRINT1 ("CmiAllocateBlock() failed\n");
-      return FALSE;
-    }
-
-  /* Initialize key cell */
-  NewKeyCell->Id = REG_KEY_CELL_ID;
-  NewKeyCell->Type = REG_KEY_CELL_TYPE;
-  NewKeyCell->LastWriteTime = 0;
-  NewKeyCell->ParentKeyOffset = ParentKeyOffset;
-  NewKeyCell->NumberOfSubKeys = 0;
-  NewKeyCell->HashTableOffset = -1;
-  NewKeyCell->NumberOfValues = 0;
-  NewKeyCell->ValueListOffset = -1;
-  NewKeyCell->SecurityKeyOffset = -1;
-  NewKeyCell->NameSize = Key->NameSize - 1;
-  NewKeyCell->ClassNameOffset = -1;
-  memcpy (NewKeyCell->Name,
-         Key->Name,
-         Key->NameSize - 1);
-
-  /* Add key cell to the parent key's hash table */
-  if (!CmiAddKeyToParentHashTable (Hive,
-                                  ParentKeyOffset,
-                                  NewKeyCell,
-                                  NKBOffset))
-    {
-      DPRINT1 ("CmiAddKeyToParentHashTable() failed\n");
-      return FALSE;
-    }
-
-  ValueCount = RegGetValueCount (Key);
-  DPRINT ("ValueCount: %lu\n", ValueCount);
-  if (ValueCount > 0)
-    {
-      /* Allocate value list cell */
-      CmiAllocateValueListCell (Hive,
-                               &NewKeyCell->ValueListOffset,
-                               ValueCount);
-
-      if (Key->DataSize != 0)
-       {
-         if (!CmiExportValue (Hive, NKBOffset, Key, NULL))
-           return FALSE;
-       }
-
-      /* Enumerate values */
-      Entry = Key->ValueList.Flink;
-      while (Entry != &Key->ValueList)
-       {
-         Value = CONTAINING_RECORD(Entry,
-                                   VALUE,
-                                   ValueList);
-
-         if (!CmiExportValue (Hive, NKBOffset, Key, Value))
-           return FALSE;
-
-         Entry = Entry->Flink;
-       }
-    }
-
-  SubKeyCount = RegGetSubKeyCount (Key);
-  DPRINT ("SubKeyCount: %lu\n", SubKeyCount);
-  if (SubKeyCount > 0)
-    {
-      /* Allocate hash table cell */
-      CmiAllocateHashTableCell (Hive,
-                               &NewKeyCell->HashTableOffset,
-                               SubKeyCount);
-
-      /* Enumerate subkeys */
-      Entry = Key->SubKeyList.Flink;
-      while (Entry != &Key->SubKeyList)
-       {
-         SubKey = CONTAINING_RECORD(Entry,
-                                    KEY,
-                                    KeyList);
-
-         if (!CmiExportSubKey (Hive, NKBOffset, Key, SubKey))
-           return FALSE;
-
-         Entry = Entry->Flink;
-       }
-    }
-
-  return TRUE;
-}
-
-
-static VOID
-CmiCalcHiveChecksum (PREGISTRY_HIVE Hive)
-{
-  PULONG Buffer;
-  ULONG Sum;
-  ULONG i;
-
-  Buffer = (PULONG)Hive->HiveHeader;
-  Sum = 0;
-  for (i = 0; i < 127; i++)
-    Sum ^= Buffer[i];
-  if (Sum == (ULONG)-1)
-    Sum = (ULONG)-2;
-  if (Sum == 0)
-    Sum = 1;
-
-  Hive->HiveHeader->Checksum = Sum;
-}
-
 
 BOOL
-CmiExportHive (PREGISTRY_HIVE Hive,
-              PCHAR KeyName)
+ExportBinaryHive(
+       IN PCSTR FileName,
+       IN PEREGISTRY_HIVE Hive)
 {
-  PKEY_CELL KeyCell;
-  HKEY Key;
-  USHORT SubKeyCount;
-  ULONG ValueCount;
-  PLIST_ENTRY Entry;
-  HKEY SubKey;
-  PVALUE Value;
-
-  DPRINT ("CmiExportHive(%p, '%s') called\n", Hive, KeyName);
+       FILE *File;
+       BOOL ret;
 
-  if (RegOpenKey (NULL, KeyName, &Key) != ERROR_SUCCESS)
-    {
-      DPRINT1 ("RegOpenKey() failed\n");
-      return FALSE;
-    }
+       printf ("  Creating binary hive: %s\n", FileName);
 
-  DPRINT ("Name: %s\n", KeyName);
-
-  KeyCell = CmiGetCell (Hive,
-                       Hive->HiveHeader->RootKeyOffset,
-                       NULL);
-  if (KeyCell == NULL)
-    {
-      DPRINT1 ("CmiGetCell() failed\n");
-      return FALSE;
-    }
-
-  ValueCount = RegGetValueCount (Key);
-  DPRINT ("ValueCount: %lu\n", ValueCount);
-  if (ValueCount > 0)
-    {
-      /* Allocate value list cell */
-      CmiAllocateValueListCell (Hive,
-                               &KeyCell->ValueListOffset,
-                               ValueCount);
-
-      if (Key->DataSize != 0)
+       /* Create new hive file */
+       File = fopen (FileName, "w+b");
+       if (File == NULL)
        {
-         if (!CmiExportValue (Hive, Hive->HiveHeader->RootKeyOffset, Key, NULL))
-           return FALSE;
+               printf("    Error creating/opening file\n");
+               return FALSE;
        }
 
-      /* Enumerate values */
-      Entry = Key->ValueList.Flink;
-      while (Entry != &Key->ValueList)
-       {
-         Value = CONTAINING_RECORD(Entry,
-                                   VALUE,
-                                   ValueList);
-
-         if (!CmiExportValue (Hive, Hive->HiveHeader->RootKeyOffset, Key, Value))
-           return FALSE;
-
-         Entry = Entry->Flink;
-       }
-    }
-
-  SubKeyCount = RegGetSubKeyCount (Key);
-  DPRINT ("SubKeyCount: %lu\n", SubKeyCount);
-  if (SubKeyCount > 0)
-    {
-      /* Allocate hash table cell */
-      CmiAllocateHashTableCell (Hive,
-                               &KeyCell->HashTableOffset,
-                               SubKeyCount);
-
-      /* Enumerate subkeys */
-      Entry = Key->SubKeyList.Flink;
-      while (Entry != &Key->SubKeyList)
-       {
-         SubKey = CONTAINING_RECORD(Entry,
-                                    KEY,
-                                    KeyList);
-
-         if (!CmiExportSubKey (Hive, Hive->HiveHeader->RootKeyOffset, Key, SubKey))
-           return FALSE;
-
-         Entry = Entry->Flink;
-       }
-    }
-
-  CmiCalcHiveChecksum (Hive);
-
-  return TRUE;
-}
-
-
-static BOOL
-CmiWriteHive(PREGISTRY_HIVE Hive,
-            PCHAR FileName)
-{
-  PHBIN Bin;
-  FILE *File;
-  ULONG i;
-
-#if 0
-  /* Check for existing hive file */
-  File = fopen (FileName, "rb");
-  if (File != NULL)
-    {
-      printf ("    File already exists\n");
-      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;
-    }
-
-  fseek (File, 0, SEEK_SET);
-
-  /* Calculate header checksum */
-  CmiCalcHiveChecksum (Hive);
-
-  /* Write hive header */
-  fwrite (Hive->HiveHeader, REG_BLOCK_SIZE, 1, File);
-
-  Bin = NULL;
-  for (i = 0; i < Hive->BlockListSize; i++)
-    {
-      if (Hive->BlockList[i] != Bin)
-       {
-         Bin = Hive->BlockList[i];
-
-         DPRINT ("Bin[%lu]: Offset 0x%lx  Size 0x%lx\n",
-                 i, Bin->BinOffset, Bin->BinSize);
-
-         fwrite (Bin, Bin->BinSize, 1, File);
-       }
-    }
-
-  fclose (File);
-
-  return TRUE;
-}
-
-
-BOOL
-ExportBinaryHive (PCHAR FileName,
-                 PCHAR KeyName)
-{
-  PREGISTRY_HIVE Hive;
-
-  printf ("  Creating binary hive: %s\n", FileName);
-
-  Hive = CmiCreateRegistryHive (KeyName);
-  if (Hive == NULL)
-    return FALSE;
-
-  if (!CmiExportHive (Hive, KeyName))
-    {
-      CmiDestroyRegistryHive (Hive);
-      return FALSE;
-    }
-
-  if (!CmiWriteHive (Hive, FileName))
-    {
-      CmiDestroyRegistryHive (Hive);
-      return FALSE;
-    }
-
-  CmiDestroyRegistryHive (Hive);
+       fseek (File, 0, SEEK_SET);
 
-  return TRUE;
+       Hive->HiveHandle = (HANDLE)File;
+       ret = HvWriteHive(&Hive->Hive);
+       fclose (File);
+       return ret;
 }
 
 /* EOF */
index 1ab398b..b252b94 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ReactOS kernel
- *  Copyright (C) 2003 ReactOS Team
+ *  Copyright (C) 2006 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
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id$
- * COPYRIGHT:       See COPYING in the top level directory
+/* COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS hive maker
  * FILE:            tools/mkhive/binhive.h
  * PURPOSE:         Binary hive export code
- * PROGRAMMER:      Eric Kohl
+ * PROGRAMMER:      Hervé Poussineau
  */
 
 #ifndef __BINHIVE_H__
 #define __BINHIVE_H__
 
 BOOL
-ExportBinaryHive (PCHAR FileName,
-                 PCHAR KeyName);
+ExportBinaryHive(
+       IN PCSTR FileName,
+       IN PEREGISTRY_HIVE Hive);
 
 #endif /* __BINHIVE_H__ */
 
diff --git a/reactos/tools/mkhive/cmi.c b/reactos/tools/mkhive/cmi.c
new file mode 100644 (file)
index 0000000..e8cd3e5
--- /dev/null
@@ -0,0 +1,791 @@
+/*
+ *  ReactOS kernel
+ *  Copyright (C) 2006 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
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS hive maker
+ * FILE:            tools/mkhive/cmi.c
+ * PURPOSE:         Registry file manipulation routines
+ * PROGRAMMER:      Hervé Poussineau
+ */
+
+#define NDEBUG
+#include "mkhive.h"
+
+static PVOID
+CmpAllocate(
+       IN SIZE_T Size,
+       IN BOOLEAN Paged)
+{
+       return malloc(Size);
+}
+
+static VOID
+CmpFree(
+       IN PVOID Ptr)
+{
+       free(Ptr);
+}
+
+static BOOLEAN
+CmpFileRead(
+       IN PHHIVE RegistryHive,
+       IN ULONG FileType,
+       IN ULONGLONG FileOffset,
+       OUT PVOID Buffer,
+       IN SIZE_T BufferLength)
+{
+       DPRINT1("CmpFileRead() unimplemented\n");
+       return FALSE;
+}
+
+static BOOLEAN
+CmpFileWrite(
+       IN PHHIVE RegistryHive,
+       IN ULONG FileType,
+       IN ULONGLONG FileOffset,
+       IN PVOID Buffer,
+       IN SIZE_T BufferLength)
+{
+       PEREGISTRY_HIVE CmHive = (PEREGISTRY_HIVE)RegistryHive;
+       FILE *File = CmHive->HiveHandle;
+       if (0 != fseek (File, (long)FileOffset, SEEK_SET))
+               return FALSE;
+       return BufferLength == fwrite (Buffer, 1, BufferLength, File);
+}
+
+static BOOLEAN
+CmpFileSetSize(
+       IN PHHIVE RegistryHive,
+       IN ULONG FileType,
+       IN ULONGLONG FileSize)
+{
+       DPRINT1("CmpFileSetSize() unimplemented\n");
+       return FALSE;
+}
+
+static BOOLEAN
+CmpFileFlush(
+       IN PHHIVE RegistryHive,
+       IN ULONG FileType)
+{
+       PEREGISTRY_HIVE CmHive = (PEREGISTRY_HIVE)RegistryHive;
+       FILE *File = CmHive->HiveHandle;
+       return 0 == fflush (File);
+}
+
+NTSTATUS
+CmiInitializeTempHive(
+       IN OUT PEREGISTRY_HIVE Hive)
+{
+       NTSTATUS Status;
+
+       RtlZeroMemory (
+               Hive,
+               sizeof(EREGISTRY_HIVE));
+
+       DPRINT("Hive 0x%p\n", Hive);
+
+       Status = HvInitialize(
+               &Hive->Hive,
+               HV_OPERATION_CREATE_HIVE, 0, 0,
+               CmpAllocate, CmpFree,
+               CmpFileRead, CmpFileWrite, CmpFileSetSize,
+               CmpFileFlush, NULL);
+       if (!NT_SUCCESS(Status))
+       {
+               return Status;
+       }
+
+       if (!CmCreateRootNode (&Hive->Hive, L""))
+       {
+               HvFree (&Hive->Hive);
+               return STATUS_INSUFFICIENT_RESOURCES;
+       }
+
+       Hive->Flags = HIVE_NO_FILE;
+
+       /* Add the new hive to the hive list */
+       InsertTailList (
+               &CmiHiveListHead,
+               &Hive->HiveList);
+
+       VERIFY_REGISTRY_HIVE (Hive);
+
+       return STATUS_SUCCESS;
+}
+
+static NTSTATUS
+CmiAddKeyToHashTable(
+       IN PEREGISTRY_HIVE RegistryHive,
+       IN OUT PHASH_TABLE_CELL HashCell,
+       IN PCM_KEY_NODE KeyCell,
+       IN HV_STORAGE_TYPE StorageType,
+       IN PCM_KEY_NODE NewKeyCell,
+       IN HCELL_INDEX NKBOffset)
+{
+       ULONG i = KeyCell->SubKeyCounts[StorageType];
+
+       HashCell->Table[i].KeyOffset = NKBOffset;
+       HashCell->Table[i].HashValue = 0;
+       if (NewKeyCell->Flags & REG_KEY_NAME_PACKED)
+       {
+               RtlCopyMemory(
+                       &HashCell->Table[i].HashValue,
+                       NewKeyCell->Name,
+                       min(NewKeyCell->NameSize, sizeof(ULONG)));
+       }
+       HvMarkCellDirty(&RegistryHive->Hive, KeyCell->SubKeyLists[StorageType]);
+       return STATUS_SUCCESS;
+}
+
+static NTSTATUS
+CmiAllocateHashTableCell (
+       IN PEREGISTRY_HIVE RegistryHive,
+       OUT PHASH_TABLE_CELL *HashBlock,
+       OUT HCELL_INDEX *HBOffset,
+       IN USHORT SubKeyCount,
+       IN HV_STORAGE_TYPE Storage)
+{
+       PHASH_TABLE_CELL NewHashBlock;
+       ULONG NewHashSize;
+       NTSTATUS Status;
+
+       Status = STATUS_SUCCESS;
+       *HashBlock = NULL;
+       NewHashSize = sizeof(HASH_TABLE_CELL) +
+               (SubKeyCount * sizeof(HASH_RECORD));
+       *HBOffset = HvAllocateCell(&RegistryHive->Hive, NewHashSize, Storage);
+
+       if (*HBOffset == HCELL_NULL)
+       {
+               Status = STATUS_INSUFFICIENT_RESOURCES;
+       }
+       else
+       {
+               ASSERT(SubKeyCount <= USHORT_MAX);
+               NewHashBlock = HvGetCell (&RegistryHive->Hive, *HBOffset);
+               NewHashBlock->Id = REG_HASH_TABLE_CELL_ID;
+               NewHashBlock->HashTableSize = SubKeyCount;
+               *HashBlock = NewHashBlock;
+       }
+
+       return Status;
+}
+
+NTSTATUS
+CmiAddSubKey(
+       IN PEREGISTRY_HIVE RegistryHive,
+       IN PCM_KEY_NODE ParentKeyCell,
+       IN HCELL_INDEX ParentKeyCellOffset,
+       IN PCUNICODE_STRING SubKeyName,
+       IN ULONG CreateOptions,
+       OUT PCM_KEY_NODE *pSubKeyCell,
+       OUT HCELL_INDEX *pBlockOffset)
+{
+       PHASH_TABLE_CELL HashBlock;
+       HCELL_INDEX NKBOffset;
+       PCM_KEY_NODE NewKeyCell;
+       ULONG NewBlockSize;
+       NTSTATUS Status;
+       USHORT NameSize;
+       PWSTR NamePtr;
+       BOOLEAN Packable;
+       HV_STORAGE_TYPE Storage;
+       ULONG i;
+
+       DPRINT("CmiAddSubKey(%p '%wZ')\n", RegistryHive, SubKeyName);
+
+       VERIFY_KEY_CELL(ParentKeyCell);
+
+       /* Skip leading backslash */
+       if (SubKeyName->Buffer[0] == L'\\')
+       {
+               NamePtr = &SubKeyName->Buffer[1];
+               NameSize = SubKeyName->Length - sizeof(WCHAR);
+       }
+       else
+       {
+               NamePtr = SubKeyName->Buffer;
+               NameSize = SubKeyName->Length;
+       }
+
+       /* Check whether key name can be packed */
+       Packable = TRUE;
+       for (i = 0; i < NameSize / sizeof(WCHAR); i++)
+       {
+               if (NamePtr[i] & 0xFF00)
+               {
+                       Packable = FALSE;
+                       break;
+               }
+       }
+
+       /* Adjust name size */
+       if (Packable)
+       {
+               NameSize = NameSize / sizeof(WCHAR);
+       }
+
+       Status = STATUS_SUCCESS;
+
+       Storage = (CreateOptions & REG_OPTION_VOLATILE) ? HvVolatile : HvStable;
+       NewBlockSize = sizeof(CM_KEY_NODE) + NameSize;
+       NKBOffset = HvAllocateCell(&RegistryHive->Hive, NewBlockSize, Storage);
+       if (NKBOffset == HCELL_NULL)
+       {
+               Status = STATUS_INSUFFICIENT_RESOURCES;
+       }
+       else
+       {
+               NewKeyCell = HvGetCell (&RegistryHive->Hive, NKBOffset);
+               NewKeyCell->Id = REG_KEY_CELL_ID;
+               if (CreateOptions & REG_OPTION_VOLATILE)
+               {
+                       NewKeyCell->Flags = REG_KEY_VOLATILE_CELL;
+               }
+               else
+               {
+                       NewKeyCell->Flags = 0;
+               }
+               KeQuerySystemTime(&NewKeyCell->LastWriteTime);
+               NewKeyCell->Parent = HCELL_NULL;
+               NewKeyCell->SubKeyCounts[HvStable] = 0;
+               NewKeyCell->SubKeyCounts[HvVolatile] = 0;
+               NewKeyCell->SubKeyLists[HvStable] = HCELL_NULL;
+               NewKeyCell->SubKeyLists[HvVolatile] = HCELL_NULL;
+               NewKeyCell->ValueList.Count = 0;
+               NewKeyCell->ValueList.List = HCELL_NULL;
+               NewKeyCell->SecurityKeyOffset = HCELL_NULL;
+               NewKeyCell->ClassNameOffset = HCELL_NULL;
+
+               /* Pack the key name */
+               NewKeyCell->NameSize = NameSize;
+               if (Packable)
+               {
+                       NewKeyCell->Flags |= REG_KEY_NAME_PACKED;
+                       for (i = 0; i < NameSize; i++)
+                       {
+                               NewKeyCell->Name[i] = (CHAR)(NamePtr[i] & 0x00FF);
+                       }
+               }
+               else
+               {
+                       RtlCopyMemory(
+                               NewKeyCell->Name,
+                               NamePtr,
+                               NameSize);
+               }
+
+               VERIFY_KEY_CELL(NewKeyCell);
+       }
+
+       if (!NT_SUCCESS(Status))
+       {
+               return Status;
+       }
+
+       if (ParentKeyCell->SubKeyLists[Storage] == HCELL_NULL)
+       {
+               Status = CmiAllocateHashTableCell (
+                       RegistryHive,
+                       &HashBlock,
+                       &ParentKeyCell->SubKeyLists[Storage],
+                       REG_INIT_HASH_TABLE_SIZE,
+                       Storage);
+               if (!NT_SUCCESS(Status))
+               {
+                       return(Status);
+               }
+       }
+       else
+       {
+               HashBlock = HvGetCell (
+                       &RegistryHive->Hive,
+                       ParentKeyCell->SubKeyLists[Storage]);
+               ASSERT(HashBlock->Id == REG_HASH_TABLE_CELL_ID);
+
+               if (((ParentKeyCell->SubKeyCounts[Storage] + 1) >= HashBlock->HashTableSize))
+               {
+                       PHASH_TABLE_CELL NewHashBlock;
+                       HCELL_INDEX HTOffset;
+
+                       /* Reallocate the hash table cell */
+                       Status = CmiAllocateHashTableCell (
+                               RegistryHive,
+                               &NewHashBlock,
+                               &HTOffset,
+                               HashBlock->HashTableSize +
+                               REG_EXTEND_HASH_TABLE_SIZE,
+                               Storage);
+                       if (!NT_SUCCESS(Status))
+                       {
+                               return Status;
+                       }
+
+                       RtlZeroMemory(
+                               &NewHashBlock->Table[0],
+                               sizeof(NewHashBlock->Table[0]) * NewHashBlock->HashTableSize);
+                       RtlCopyMemory(
+                               &NewHashBlock->Table[0],
+                               &HashBlock->Table[0],
+                               sizeof(NewHashBlock->Table[0]) * HashBlock->HashTableSize);
+                       HvFreeCell (&RegistryHive->Hive, ParentKeyCell->SubKeyLists[Storage]);
+                       ParentKeyCell->SubKeyLists[Storage] = HTOffset;
+                       HashBlock = NewHashBlock;
+               }
+       }
+
+       Status = CmiAddKeyToHashTable(
+               RegistryHive,
+               HashBlock,
+               ParentKeyCell,
+               Storage,
+               NewKeyCell,
+               NKBOffset);
+       if (NT_SUCCESS(Status))
+       {
+               ParentKeyCell->SubKeyCounts[Storage]++;
+               *pSubKeyCell = NewKeyCell;
+               *pBlockOffset = NKBOffset;
+       }
+
+       KeQuerySystemTime(&ParentKeyCell->LastWriteTime);
+       HvMarkCellDirty(&RegistryHive->Hive, ParentKeyCellOffset);
+
+       return Status;
+}
+
+static BOOLEAN
+CmiCompareHash(
+       IN PCUNICODE_STRING KeyName,
+       IN PCHAR HashString)
+{
+       CHAR Buffer[4];
+
+       Buffer[0] = (KeyName->Length >= 2) ? (CHAR)KeyName->Buffer[0] : 0;
+       Buffer[1] = (KeyName->Length >= 4) ? (CHAR)KeyName->Buffer[1] : 0;
+       Buffer[2] = (KeyName->Length >= 6) ? (CHAR)KeyName->Buffer[2] : 0;
+       Buffer[3] = (KeyName->Length >= 8) ? (CHAR)KeyName->Buffer[3] : 0;
+
+       return (strncmp(Buffer, HashString, 4) == 0);
+}
+
+
+BOOLEAN
+CmiCompareHashI(
+       IN PCUNICODE_STRING KeyName,
+       IN PCHAR HashString)
+{
+       CHAR Buffer[4];
+
+       Buffer[0] = (KeyName->Length >= 2) ? (CHAR)KeyName->Buffer[0] : 0;
+       Buffer[1] = (KeyName->Length >= 4) ? (CHAR)KeyName->Buffer[1] : 0;
+       Buffer[2] = (KeyName->Length >= 6) ? (CHAR)KeyName->Buffer[2] : 0;
+       Buffer[3] = (KeyName->Length >= 8) ? (CHAR)KeyName->Buffer[3] : 0;
+
+       return (_strnicmp(Buffer, HashString, 4) == 0);
+}
+
+static BOOLEAN
+CmiCompareKeyNames(
+       IN PCUNICODE_STRING KeyName,
+       IN PCM_KEY_NODE KeyCell)
+{
+       PWCHAR UnicodeName;
+       USHORT i;
+
+       if (KeyCell->Flags & REG_KEY_NAME_PACKED)
+       {
+               if (KeyName->Length != KeyCell->NameSize * sizeof(WCHAR))
+                       return FALSE;
+
+               for (i = 0; i < KeyCell->NameSize; i++)
+               {
+                       if (KeyName->Buffer[i] != (WCHAR)KeyCell->Name[i])
+                               return FALSE;
+               }
+       }
+       else
+       {
+               if (KeyName->Length != KeyCell->NameSize)
+                       return FALSE;
+
+               UnicodeName = (PWCHAR)KeyCell->Name;
+               for (i = 0; i < KeyCell->NameSize / sizeof(WCHAR); i++)
+               {
+                       if (KeyName->Buffer[i] != UnicodeName[i])
+                               return FALSE;
+               }
+       }
+
+       return TRUE;
+}
+
+static BOOLEAN
+CmiCompareKeyNamesI(
+       IN PCUNICODE_STRING KeyName,
+       IN PCM_KEY_NODE KeyCell)
+{
+       PWCHAR UnicodeName;
+       USHORT i;
+
+       DPRINT("Flags: %hx\n", KeyCell->Flags);
+
+       if (KeyCell->Flags & REG_KEY_NAME_PACKED)
+       {
+               if (KeyName->Length != KeyCell->NameSize * sizeof(WCHAR))
+                       return FALSE;
+
+               /* FIXME: use _strnicmp */
+               for (i = 0; i < KeyCell->NameSize; i++)
+               {
+                       if (RtlUpcaseUnicodeChar(KeyName->Buffer[i]) !=
+                               RtlUpcaseUnicodeChar((WCHAR)KeyCell->Name[i]))
+                       return FALSE;
+               }
+       }
+       else
+       {
+               if (KeyName->Length != KeyCell->NameSize)
+                       return FALSE;
+
+               UnicodeName = (PWCHAR)KeyCell->Name;
+               /* FIXME: use _strnicmp */
+               for (i = 0; i < KeyCell->NameSize / sizeof(WCHAR); i++)
+               {
+                       if (RtlUpcaseUnicodeChar(KeyName->Buffer[i]) !=
+                               RtlUpcaseUnicodeChar(UnicodeName[i]))
+                               return FALSE;
+               }
+       }
+
+       return TRUE;
+}
+
+NTSTATUS
+CmiScanForSubKey(
+       IN PEREGISTRY_HIVE RegistryHive,
+       IN PCM_KEY_NODE KeyCell,
+       IN PCUNICODE_STRING SubKeyName,
+       IN ULONG Attributes,
+       OUT PCM_KEY_NODE *pSubKeyCell,
+       OUT HCELL_INDEX *pBlockOffset)
+{
+       PHASH_TABLE_CELL HashBlock;
+       PCM_KEY_NODE CurSubKeyCell;
+       ULONG Storage;
+       ULONG i;
+
+       VERIFY_KEY_CELL(KeyCell);
+
+       DPRINT("CmiScanForSubKey('%wZ')\n", SubKeyName);
+
+       ASSERT(RegistryHive);
+
+       *pSubKeyCell = NULL;
+
+       for (Storage = HvStable; Storage < HvMaxStorageType; Storage++)
+       {
+               if (KeyCell->SubKeyLists[Storage] == HCELL_NULL)
+               {
+                       /* The key does not have any subkeys */
+                       continue;
+               }
+
+               /* Get hash table */
+               HashBlock = HvGetCell (&RegistryHive->Hive, KeyCell->SubKeyLists[Storage]);
+               if (!HashBlock || HashBlock->Id != REG_HASH_TABLE_CELL_ID)
+                       return STATUS_UNSUCCESSFUL;
+
+               for (i = 0; i < KeyCell->SubKeyCounts[Storage]; i++)
+               {
+                       if (Attributes & OBJ_CASE_INSENSITIVE)
+                       {
+                               if ((HashBlock->Table[i].HashValue == 0
+                                || CmiCompareHashI(SubKeyName, (PCHAR)&HashBlock->Table[i].HashValue)))
+                               {
+                                       CurSubKeyCell = HvGetCell (
+                                               &RegistryHive->Hive,
+                                               HashBlock->Table[i].KeyOffset);
+
+                                       if (CmiCompareKeyNamesI(SubKeyName, CurSubKeyCell))
+                                       {
+                                               *pSubKeyCell = CurSubKeyCell;
+                                               *pBlockOffset = HashBlock->Table[i].KeyOffset;
+                                               return STATUS_SUCCESS;
+                                       }
+                               }
+                       }
+                       else
+                       {
+                               if ((HashBlock->Table[i].HashValue == 0
+                                || CmiCompareHash(SubKeyName, (PCHAR)&HashBlock->Table[i].HashValue)))
+                               {
+                                       CurSubKeyCell = HvGetCell (
+                                               &RegistryHive->Hive,
+                                               HashBlock->Table[i].KeyOffset);
+
+                                       if (CmiCompareKeyNames(SubKeyName, CurSubKeyCell))
+                                       {
+                                               *pSubKeyCell = CurSubKeyCell;
+                                               *pBlockOffset = HashBlock->Table[i].KeyOffset;
+                                               return STATUS_SUCCESS;
+                                       }
+                               }
+                       }
+               }
+       }
+
+       return STATUS_OBJECT_NAME_NOT_FOUND;
+}
+
+static USHORT
+CmiGetPackedNameLength(
+       IN PCUNICODE_STRING Name,
+       OUT PBOOLEAN pPackable)
+{
+       USHORT i;
+
+       *pPackable = TRUE;
+
+       for (i = 0; i < Name->Length / sizeof(WCHAR); i++)
+       {
+               if (Name->Buffer[i] & 0xFF00)
+               {
+                       *pPackable = FALSE;
+                       return Name->Length;
+               }
+       }
+
+       return (Name->Length / sizeof(WCHAR));
+}
+
+static NTSTATUS
+CmiAllocateValueCell(
+       IN PEREGISTRY_HIVE RegistryHive,
+       OUT PCM_KEY_VALUE *ValueCell,
+       OUT HCELL_INDEX *VBOffset,
+       IN PCUNICODE_STRING ValueName,
+       IN HV_STORAGE_TYPE Storage)
+{
+       PCM_KEY_VALUE NewValueCell;
+       BOOLEAN Packable;
+       USHORT NameSize, i;
+       NTSTATUS Status;
+
+       Status = STATUS_SUCCESS;
+
+       NameSize = CmiGetPackedNameLength(ValueName, &Packable);
+
+       DPRINT("ValueName->Length %lu  NameSize %lu\n", ValueName->Length, NameSize);
+
+       *VBOffset = HvAllocateCell(&RegistryHive->Hive, sizeof(CM_KEY_VALUE) + NameSize, Storage);
+       if (*VBOffset == HCELL_NULL)
+       {
+               Status = STATUS_INSUFFICIENT_RESOURCES;
+    }
+       else
+       {
+               ASSERT(NameSize <= USHORT_MAX);
+               NewValueCell = HvGetCell (&RegistryHive->Hive, *VBOffset);
+               NewValueCell->Id = REG_VALUE_CELL_ID;
+               NewValueCell->NameSize = (USHORT)NameSize;
+               if (Packable)
+               {
+                       /* Pack the value name */
+                       for (i = 0; i < NameSize; i++)
+                               NewValueCell->Name[i] = (CHAR)ValueName->Buffer[i];
+                       NewValueCell->Flags |= REG_VALUE_NAME_PACKED;
+               }
+               else
+               {
+                       /* Copy the value name */
+                       RtlCopyMemory(
+                               NewValueCell->Name,
+                               ValueName->Buffer,
+                               NameSize);
+                       NewValueCell->Flags = 0;
+               }
+               NewValueCell->DataType = 0;
+               NewValueCell->DataSize = 0;
+               NewValueCell->DataOffset = HCELL_NULL;
+               *ValueCell = NewValueCell;
+       }
+
+       return Status;
+}
+
+NTSTATUS
+CmiAddValueKey(
+       IN PEREGISTRY_HIVE RegistryHive,
+       IN PCM_KEY_NODE KeyCell,
+       IN HCELL_INDEX KeyCellOffset,
+       IN PCUNICODE_STRING ValueName,
+       OUT PCM_KEY_VALUE *pValueCell,
+       OUT HCELL_INDEX *pValueCellOffset)
+{
+         PVALUE_LIST_CELL ValueListCell;
+       PCM_KEY_VALUE NewValueCell;
+       HCELL_INDEX ValueListCellOffset;
+       HCELL_INDEX NewValueCellOffset;
+       ULONG CellSize;
+       HV_STORAGE_TYPE Storage;
+       NTSTATUS Status;
+
+       Storage = (KeyCell->Flags & REG_KEY_VOLATILE_CELL) ? HvVolatile : HvStable;
+       if (KeyCell->ValueList.List == HCELL_NULL)
+       {
+               /* Allocate some room for the value list */
+               CellSize = sizeof(VALUE_LIST_CELL) + (3 * sizeof(HCELL_INDEX));
+               ValueListCellOffset = HvAllocateCell(&RegistryHive->Hive, CellSize, Storage);
+               if (ValueListCellOffset == HCELL_NULL)
+                       return STATUS_INSUFFICIENT_RESOURCES;
+
+               ValueListCell = HvGetCell(&RegistryHive->Hive, ValueListCellOffset);
+               if (!ValueListCell)
+                       return STATUS_UNSUCCESSFUL;
+               KeyCell->ValueList.List = ValueListCellOffset;
+               HvMarkCellDirty(&RegistryHive->Hive, KeyCellOffset);
+       }
+       else
+       {
+               ValueListCell = (PVALUE_LIST_CELL)HvGetCell(&RegistryHive->Hive, KeyCell->ValueList.List);
+               if (!ValueListCell)
+                       return STATUS_UNSUCCESSFUL;
+               CellSize = ABS_VALUE(HvGetCellSize(&RegistryHive->Hive, ValueListCell));
+
+               if (KeyCell->ValueList.Count >= CellSize / sizeof(HCELL_INDEX))
+               {
+                       CellSize *= 2;
+                       ValueListCellOffset = HvReallocateCell(&RegistryHive->Hive, KeyCell->ValueList.List, CellSize);
+                       if (ValueListCellOffset == HCELL_NULL)
+                               return STATUS_INSUFFICIENT_RESOURCES;
+
+                       ValueListCell = HvGetCell(&RegistryHive->Hive, ValueListCellOffset);
+                       if (!ValueListCell)
+                               return STATUS_UNSUCCESSFUL;
+                       KeyCell->ValueList.List = ValueListCellOffset;
+                       HvMarkCellDirty(&RegistryHive->Hive, KeyCellOffset);
+        }
+       }
+
+       Status = CmiAllocateValueCell(
+               RegistryHive,
+               &NewValueCell,
+               &NewValueCellOffset,
+               ValueName,
+               Storage);
+       if (!NT_SUCCESS(Status))
+               return Status;
+
+       ValueListCell->ValueOffset[KeyCell->ValueList.Count] = NewValueCellOffset;
+       KeyCell->ValueList.Count++;
+
+       HvMarkCellDirty(&RegistryHive->Hive, KeyCellOffset);
+       HvMarkCellDirty(&RegistryHive->Hive, KeyCell->ValueList.List);
+       HvMarkCellDirty(&RegistryHive->Hive, NewValueCellOffset);
+
+       *pValueCell = NewValueCell;
+       *pValueCellOffset = NewValueCellOffset;
+
+       return STATUS_SUCCESS;
+}
+
+static BOOLEAN
+CmiComparePackedNames(
+       IN PCUNICODE_STRING Name,
+       IN PUCHAR NameBuffer,
+       IN USHORT NameBufferSize,
+       IN BOOLEAN NamePacked)
+{
+       PWCHAR UNameBuffer;
+       ULONG i;
+
+       if (NamePacked == TRUE)
+       {
+               if (Name->Length != NameBufferSize * sizeof(WCHAR))
+                       return FALSE;
+
+               for (i = 0; i < Name->Length / sizeof(WCHAR); i++)
+               {
+                       if (RtlUpcaseUnicodeChar(Name->Buffer[i]) != RtlUpcaseUnicodeChar((WCHAR)NameBuffer[i]))
+                               return FALSE;
+               }
+       }
+       else
+       {
+               if (Name->Length != NameBufferSize)
+                       return FALSE;
+
+               UNameBuffer = (PWCHAR)NameBuffer;
+
+               for (i = 0; i < Name->Length / sizeof(WCHAR); i++)
+               {
+                       if (RtlUpcaseUnicodeChar(Name->Buffer[i]) != RtlUpcaseUnicodeChar(UNameBuffer[i]))
+                               return FALSE;
+               }
+       }
+
+       return TRUE;
+}
+
+NTSTATUS
+CmiScanForValueKey(
+       IN PEREGISTRY_HIVE RegistryHive,
+       IN PCM_KEY_NODE KeyCell,
+       IN PCUNICODE_STRING ValueName,
+       OUT PCM_KEY_VALUE *pValueCell,
+       OUT HCELL_INDEX *pValueCellOffset)
+{
+       PVALUE_LIST_CELL ValueListCell;
+       PCM_KEY_VALUE CurValueCell;
+       ULONG i;
+
+       *pValueCell = NULL;
+       *pValueCellOffset = HCELL_NULL;
+
+       /* The key does not have any values */
+       if (KeyCell->ValueList.List == HCELL_NULL)
+    {
+               return STATUS_OBJECT_NAME_NOT_FOUND;
+    }
+
+       ValueListCell = HvGetCell(&RegistryHive->Hive, KeyCell->ValueList.List);
+
+       VERIFY_VALUE_LIST_CELL(ValueListCell);
+
+       for (i = 0; i < KeyCell->ValueList.Count; i++)
+       {
+               CurValueCell = HvGetCell(
+                       &RegistryHive->Hive,
+                       ValueListCell->ValueOffset[i]);
+
+               if (CmiComparePackedNames(
+                       ValueName,
+                       CurValueCell->Name,
+                       CurValueCell->NameSize,
+                       (BOOLEAN)((CurValueCell->Flags & REG_VALUE_NAME_PACKED) ? TRUE : FALSE)))
+               {
+                       *pValueCell = CurValueCell;
+                       *pValueCellOffset = ValueListCell->ValueOffset[i];
+                       return STATUS_SUCCESS;
+               }
+       }
+
+       return STATUS_OBJECT_NAME_NOT_FOUND;
+}
diff --git a/reactos/tools/mkhive/cmi.h b/reactos/tools/mkhive/cmi.h
new file mode 100644 (file)
index 0000000..b66d39c
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ *  ReactOS kernel
+ *  Copyright (C) 2006 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
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS hive maker
+ * FILE:            tools/mkhive/cmi.h
+ * PURPOSE:         Registry file manipulation routines
+ * PROGRAMMER:      Hervé Poussineau
+ */
+
+#define VERIFY_KEY_CELL(key)
+#define VERIFY_VALUE_LIST_CELL(cell)
+
+NTSTATUS
+CmiInitializeTempHive(
+       IN OUT PEREGISTRY_HIVE Hive);
+
+NTSTATUS
+CmiAddSubKey(
+       IN PEREGISTRY_HIVE RegistryHive,
+       IN PCM_KEY_NODE ParentKeyCell,
+       IN HCELL_INDEX ParentKeyCellOffset,
+       IN PCUNICODE_STRING SubKeyName,
+       IN ULONG CreateOptions,
+       OUT PCM_KEY_NODE *pSubKeyCell,
+       OUT HCELL_INDEX *pBlockOffset);
+
+NTSTATUS
+CmiScanForSubKey(
+       IN PEREGISTRY_HIVE RegistryHive,
+       IN PCM_KEY_NODE KeyCell,
+       IN PCUNICODE_STRING SubKeyName,
+       IN ULONG Attributes,
+       OUT PCM_KEY_NODE *pSubKeyCell,
+       OUT HCELL_INDEX *pBlockOffset);
+
+NTSTATUS
+CmiAddValueKey(
+       IN PEREGISTRY_HIVE RegistryHive,
+       IN PCM_KEY_NODE KeyCell,
+       IN HCELL_INDEX KeyCellOffset,
+       IN PCUNICODE_STRING ValueName,
+       OUT PCM_KEY_VALUE *pValueCell,
+       OUT HCELL_INDEX *pValueCellOffset);
+
+NTSTATUS
+CmiScanForValueKey(
+       IN PEREGISTRY_HIVE RegistryHive,
+       IN PCM_KEY_NODE KeyCell,
+       IN PCUNICODE_STRING ValueName,
+       OUT PCM_KEY_VALUE *pValueCell,
+       OUT HCELL_INDEX *pValueCellOffset);
index 1bfa3c5..360021e 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ReactOS kernel
- *  Copyright (C) 2003 ReactOS Team
+ *  Copyright (C) 2003, 2006 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
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id$
- * COPYRIGHT:       See COPYING in the top level directory
+/* COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS hive maker
  * FILE:            tools/mkhive/mkhive.c
  * PURPOSE:         Hive maker
  * PROGRAMMER:      Eric Kohl
+ *                  Hervé Poussineau
  */
 
 #include <limits.h>
@@ -29,9 +29,6 @@
 #include <stdio.h>
 
 #include "mkhive.h"
-#include "registry.h"
-#include "reginf.h"
-#include "binhive.h"
 
 #ifdef _MSC_VER
 #include <stdlib.h>
@@ -105,65 +102,65 @@ int main (int argc, char *argv[])
   convert_path (FileName, argv[1]);
   strcat (FileName, DIR_SEPARATOR_STRING);
   strcat (FileName, "hivesys.inf");
-  ImportRegistryFile (FileName, "AddReg", FALSE);
+  ImportRegistryFile (FileName);
 
   convert_path (FileName, argv[1]);
   strcat (FileName, DIR_SEPARATOR_STRING);
   strcat (FileName, "hivecls.inf");
-  ImportRegistryFile (FileName, "AddReg", FALSE);
+  ImportRegistryFile (FileName);
 
   convert_path (FileName, argv[1]);
   strcat (FileName, DIR_SEPARATOR_STRING);
   strcat (FileName, "hivesft.inf");
-  ImportRegistryFile (FileName, "AddReg", FALSE);
+  ImportRegistryFile (FileName);
 
   convert_path (FileName, argv[1]);
   strcat (FileName, DIR_SEPARATOR_STRING);
   strcat (FileName, "hivedef.inf");
-  ImportRegistryFile (FileName, "AddReg", FALSE);
+  ImportRegistryFile (FileName);
 
   for (Param = 3; Param < argc; Param++)
   {
     convert_path (FileName, argv[Param]);
-    ImportRegistryFile (FileName, "AddReg", FALSE);
+    ImportRegistryFile (FileName);
   }
 
   convert_path (FileName, argv[2]);
   strcat (FileName, DIR_SEPARATOR_STRING);
-  strcat (FileName, "system");
-  if (!ExportBinaryHive (FileName, "\\Registry\\Machine\\SYSTEM"))
+  strcat (FileName, "default");
+  if (!ExportBinaryHive (FileName, &DefaultHive))
   {
      return 1;
   }
 
   convert_path (FileName, argv[2]);
   strcat (FileName, DIR_SEPARATOR_STRING);
-  strcat (FileName, "software");
-  if (!ExportBinaryHive (FileName, "\\Registry\\Machine\\SOFTWARE"))
+  strcat (FileName, "sam");
+  if (!ExportBinaryHive (FileName, &SamHive))
   {
      return 1;
   }
 
   convert_path (FileName, argv[2]);
   strcat (FileName, DIR_SEPARATOR_STRING);
-  strcat (FileName, "sam");
-  if (!ExportBinaryHive (FileName, "\\Registry\\Machine\\SAM"))
+  strcat (FileName, "security");
+  if (!ExportBinaryHive (FileName, &SecurityHive))
   {
      return 1;
   }
 
   convert_path (FileName, argv[2]);
   strcat (FileName, DIR_SEPARATOR_STRING);
-  strcat (FileName, "security");
-  if (!ExportBinaryHive (FileName, "\\Registry\\Machine\\SECURITY"))
+  strcat (FileName, "software");
+  if (!ExportBinaryHive (FileName, &SoftwareHive))
   {
      return 1;
   }
 
   convert_path (FileName, argv[2]);
   strcat (FileName, DIR_SEPARATOR_STRING);
-  strcat (FileName, "default");
-  if (!ExportBinaryHive (FileName, "\\Registry\\User\\.DEFAULT"))
+  strcat (FileName, "system");
+  if (!ExportBinaryHive (FileName, &SystemHive))
   {
      return 1;
   }
index c4f8386..a81322c 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ReactOS kernel
- *  Copyright (C) 2003 ReactOS Team
+ *  Copyright (C) 2003, 2006 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
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id$
- * COPYRIGHT:       See COPYING in the top level directory
+/* COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS hive maker
  * FILE:            tools/mkhive/mkhive.h
  * PURPOSE:         Hive maker
  * PROGRAMMER:      Eric Kohl
+ *                  Hervé Poussineau
  */
 
 #ifndef __MKHIVE_H__
 #define __MKHIVE_H__
 
+#include <stdio.h>
 
-#define VOID void
-typedef void *PVOID;
-typedef char CHAR, *PCHAR;
-typedef short WCHAR, *PWCHAR;
-typedef unsigned char UCHAR, *PUCHAR;
-typedef short SHORT, *PSHORT;
-typedef unsigned short USHORT, *PUSHORT;
-typedef long LONG, *PLONG;
-typedef unsigned long ULONG, *PULONG;
-
-typedef unsigned long ULONG_PTR;
-
-typedef int BOOL, *PBOOL;
-
-#ifndef FALSE
-#define FALSE 0
-#endif
-#ifndef TRUE
-#define TRUE 1
-#endif
-
-#ifndef NULL
-#define NULL ((void*)0)
-#endif
-
+#define NTOS_MODE_USER
+#define WIN32_NO_STATUS
+#include <ntddk.h>
+#include <cmlib.h>
+#include <infhost.h>
+#include "reginf.h"
+#include "cmi.h"
+#include "registry.h"
+#include "binhive.h"
+
+#define HIVE_NO_FILE 2
+#define VERIFY_REGISTRY_HIVE(hive)
+extern LIST_ENTRY CmiHiveListHead;
+#define ABS_VALUE(V) (((V) < 0) ? -(V) : (V))
 
 #ifndef max
 #define max(a, b)  (((a) > (b)) ? (a) : (b))
@@ -88,7 +78,7 @@ static void DPRINT ( const char* fmt, ... )
 
 #ifdef WIN32
 #define strncasecmp strnicmp
-#define strcasecmp stricmp
+#define strcasecmp _stricmp
 #endif//WIN32
 
 #ifdef _MSC_VER
index 0feaeae..1f84707 100644 (file)
@@ -1,61 +1,73 @@
-MKHIVE_BASE = $(TOOLS_BASE_)mkhive\r
-MKHIVE_BASE_ = $(MKHIVE_BASE)$(SEP)\r
-MKHIVE_INT = $(INTERMEDIATE_)$(MKHIVE_BASE)\r
-MKHIVE_INT_ = $(MKHIVE_INT)$(SEP)\r
-MKHIVE_OUT = $(OUTPUT_)$(MKHIVE_BASE)\r
-MKHIVE_OUT_ = $(MKHIVE_OUT)$(SEP)\r
-\r
-$(MKHIVE_INT): | $(TOOLS_INT)\r
-       $(ECHO_MKDIR)\r
-       ${mkdir} $@\r
-\r
-ifneq ($(INTERMEDIATE),$(OUTPUT))\r
-$(MKHIVE_OUT): | $(TOOLS_OUT)\r
-       $(ECHO_MKDIR)\r
-       ${mkdir} $@\r
-endif\r
-\r
-MKHIVE_TARGET = \\r
-       $(EXEPREFIX)$(MKHIVE_OUT_)mkhive$(EXEPOSTFIX)\r
-\r
-MKHIVE_SOURCES = $(addprefix $(MKHIVE_BASE_), \\r
-       binhive.c \\r
-       mkhive.c \\r
-       reginf.c \\r
-       registry.c \\r
-       )\r
-\r
-MKHIVE_OBJECTS = \\r
-       $(addprefix $(INTERMEDIATE_), $(MKHIVE_SOURCES:.c=.o))\r
-\r
-MKHIVE_HOST_CFLAGS = $(xTOOLS_CFLAGS) -I$(INFLIB_BASE) -g3\r
-\r
-MKHIVE_HOST_LFLAGS = $(xTOOLS_LFLAGS) -g3\r
-\r
-.PHONY: mkhive\r
-mkhive: $(MKHIVE_TARGET)\r
-\r
-$(MKHIVE_TARGET): $(MKHIVE_OBJECTS) $(INFLIB_HOST_OBJECTS) | $(MKHIVE_OUT)\r
-       $(ECHO_LD)\r
-       ${host_gcc} $(MKHIVE_OBJECTS) $(INFLIB_HOST_OBJECTS) $(MKHIVE_HOST_LFLAGS) -o $@\r
-\r
-$(MKHIVE_INT_)binhive.o: $(MKHIVE_BASE_)binhive.c | $(MKHIVE_INT)\r
-       $(ECHO_CC)\r
-       ${host_gcc} $(MKHIVE_HOST_CFLAGS) -c $< -o $@\r
-\r
-$(MKHIVE_INT_)mkhive.o: $(MKHIVE_BASE_)mkhive.c | $(MKHIVE_INT)\r
-       $(ECHO_CC)\r
-       ${host_gcc} $(MKHIVE_HOST_CFLAGS) -c $< -o $@\r
-\r
-$(MKHIVE_INT_)reginf.o: $(MKHIVE_BASE_)reginf.c | $(MKHIVE_INT)\r
-       $(ECHO_CC)\r
-       ${host_gcc} $(MKHIVE_HOST_CFLAGS) -c $< -o $@\r
-\r
-$(MKHIVE_INT_)registry.o: $(MKHIVE_BASE_)registry.c | $(MKHIVE_INT)\r
-       $(ECHO_CC)\r
-       ${host_gcc} $(MKHIVE_HOST_CFLAGS) -c $< -o $@\r
-\r
-.PHONY: mkhive_clean\r
-mkhive_clean:\r
-       -@$(rm) $(MKHIVE_TARGET) $(MKHIVE_OBJECTS) 2>$(NUL)\r
-clean: mkhive_clean\r
+MKHIVE_BASE = $(TOOLS_BASE_)mkhive
+MKHIVE_BASE_ = $(MKHIVE_BASE)$(SEP)
+MKHIVE_INT = $(INTERMEDIATE_)$(MKHIVE_BASE)
+MKHIVE_INT_ = $(MKHIVE_INT)$(SEP)
+MKHIVE_OUT = $(OUTPUT_)$(MKHIVE_BASE)
+MKHIVE_OUT_ = $(MKHIVE_OUT)$(SEP)
+
+$(MKHIVE_INT): | $(TOOLS_INT)
+       $(ECHO_MKDIR)
+       ${mkdir} $@
+
+ifneq ($(INTERMEDIATE),$(OUTPUT))
+$(MKHIVE_OUT): | $(TOOLS_OUT)
+       $(ECHO_MKDIR)
+       ${mkdir} $@
+endif
+
+MKHIVE_TARGET = \
+       $(EXEPREFIX)$(MKHIVE_OUT_)mkhive$(EXEPOSTFIX)
+
+MKHIVE_SOURCES = $(addprefix $(MKHIVE_BASE_), \
+       binhive.c \
+       cmi.c \
+       mkhive.c \
+       reginf.c \
+       registry.c \
+       rtl.c \
+       )
+
+MKHIVE_OBJECTS = \
+       $(addprefix $(INTERMEDIATE_), $(MKHIVE_SOURCES:.c=.o))
+
+MKHIVE_HOST_CFLAGS = $(xTOOLS_CFLAGS) -I$(INFLIB_BASE) -I$(CMLIB_BASE) \
+  -D_NTOSKRNL_ \
+  -Iinclude/reactos -Iinclude/ddk -Iinclude/ndk -Iinclude/psdk -Iinclude -g3
+
+MKHIVE_HOST_LFLAGS = $(xTOOLS_LFLAGS) -g3
+
+.PHONY: mkhive
+mkhive: $(MKHIVE_TARGET)
+
+$(MKHIVE_TARGET): $(MKHIVE_OBJECTS) $(INFLIB_HOST_OBJECTS) $(CMLIB_HOST_OBJECTS) | $(MKHIVE_OUT)
+       $(ECHO_LD)
+       ${host_gcc} $(MKHIVE_OBJECTS) $(INFLIB_HOST_OBJECTS) $(CMLIB_HOST_OBJECTS) $(MKHIVE_HOST_LFLAGS) -o $@
+
+$(MKHIVE_INT_)binhive.o: $(MKHIVE_BASE_)binhive.c | $(MKHIVE_INT)
+       $(ECHO_CC)
+       ${host_gcc} $(MKHIVE_HOST_CFLAGS) -c $< -o $@
+
+$(MKHIVE_INT_)cmi.o: $(MKHIVE_BASE_)cmi.c | $(MKHIVE_INT)
+       $(ECHO_CC)
+       ${host_gcc} $(MKHIVE_HOST_CFLAGS) -c $< -o $@
+
+$(MKHIVE_INT_)mkhive.o: $(MKHIVE_BASE_)mkhive.c | $(MKHIVE_INT)
+       $(ECHO_CC)
+       ${host_gcc} $(MKHIVE_HOST_CFLAGS) -c $< -o $@
+
+$(MKHIVE_INT_)reginf.o: $(MKHIVE_BASE_)reginf.c | $(MKHIVE_INT)
+       $(ECHO_CC)
+       ${host_gcc} $(MKHIVE_HOST_CFLAGS) -c $< -o $@
+
+$(MKHIVE_INT_)registry.o: $(MKHIVE_BASE_)registry.c | $(MKHIVE_INT)
+       $(ECHO_CC)
+       ${host_gcc} $(MKHIVE_HOST_CFLAGS) -c $< -o $@
+
+$(MKHIVE_INT_)rtl.o: $(MKHIVE_BASE_)rtl.c | $(MKHIVE_INT)
+       $(ECHO_CC)
+       ${host_gcc} $(MKHIVE_HOST_CFLAGS) -Ilib/rtl -c $< -o $@
+
+.PHONY: mkhive_clean
+mkhive_clean:
+       -@$(rm) $(MKHIVE_TARGET) $(MKHIVE_OBJECTS) 2>$(NUL)
+clean: mkhive_clean
index 5cbd899..da801ae 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ReactOS kernel
- *  Copyright (C) 2003 ReactOS Team
+ *  Copyright (C) 2003, 2006 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
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id$
- * COPYRIGHT:       See COPYING in the top level directory
+/* COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS hive maker
  * FILE:            tools/mkhive/reginf.h
  * PURPOSE:         Inf file import code
  * PROGRAMMER:      Eric Kohl
+ *                  Hervé Poussineau
  */
 
 /* INCLUDES *****************************************************************/
 #include <stdlib.h>
 #include <stdio.h>
 
+#define NDEBUG
 #include "mkhive.h"
-#include "registry.h"
-#include <infhost.h>
-
-
 
 #define FLG_ADDREG_BINVALUETYPE           0x00000001
 #define FLG_ADDREG_NOCLOBBER              0x00000002
@@ -98,18 +95,19 @@ static VOID
 AppendMultiSzValue (HKEY KeyHandle,
                    PCHAR ValueName,
                    PCHAR Strings,
-                   ULONG StringSize)
+                   SIZE_T StringSize)
 {
-  ULONG Size;
+  SIZE_T Size;
   ULONG Type;
-  ULONG Total;
+  size_t Total;
   PCHAR Buffer;
   PCHAR p;
-  int len;
+  size_t len;
   LONG Error;
 
-  Error = RegQueryValue (KeyHandle,
+  Error = RegQueryValueExA (KeyHandle,
                         ValueName,
+                        NULL,
                         &Type,
                         NULL,
                         &Size);
@@ -121,10 +119,11 @@ AppendMultiSzValue (HKEY KeyHandle,
   if (Buffer == NULL)
      return;
 
-  Error = RegQueryValue (KeyHandle,
+  Error = RegQueryValueExA (KeyHandle,
                         ValueName,
                         NULL,
-                        (PCHAR)Buffer,
+                        NULL,
+                        (PUCHAR)Buffer,
                         &Size);
   if (Error != ERROR_SUCCESS)
      goto done;
@@ -151,11 +150,12 @@ AppendMultiSzValue (HKEY KeyHandle,
   if (Total != Size)
     {
       DPRINT ("setting value %s to %s\n", ValueName, Buffer);
-      RegSetValue (KeyHandle,
+      RegSetValueExA (KeyHandle,
                   ValueName,
+                  0,
                   REG_MULTI_SZ,
                   (PCHAR)Buffer,
-                  Total);
+                  (ULONG)Total);
     }
 
 done:
@@ -176,19 +176,19 @@ do_reg_operation(HKEY KeyHandle,
 {
   CHAR EmptyStr = (CHAR)0;
   ULONG Type;
-  ULONG Size;
+  SIZE_T Size;
   LONG Error;
 
   if (Flags & FLG_ADDREG_DELVAL)  /* deletion */
     {
       if (ValueName)
        {
-         RegDeleteValue (KeyHandle,
+         RegDeleteValueA (KeyHandle,
                          ValueName);
        }
       else
        {
-         RegDeleteKey (KeyHandle,
+         RegDeleteKeyA (KeyHandle,
                        NULL);
        }
 
@@ -200,10 +200,11 @@ do_reg_operation(HKEY KeyHandle,
 
   if (Flags & (FLG_ADDREG_NOCLOBBER | FLG_ADDREG_OVERWRITEONLY))
     {
-      Error = RegQueryValue (KeyHandle,
+      Error = RegQueryValueExA (KeyHandle,
                             ValueName,
                             NULL,
                             NULL,
+                            NULL,
                             NULL);
       if ((Error == ERROR_SUCCESS) &&
          (Flags & FLG_ADDREG_NOCLOBBER))
@@ -300,10 +301,11 @@ do_reg_operation(HKEY KeyHandle,
 
          DPRINT("setting dword %s to %lx\n", ValueName, dw);
 
-         RegSetValue (KeyHandle,
+         RegSetValueExA (KeyHandle,
                       ValueName,
+                          0,
                       Type,
-                      (PVOID)&dw,
+                      (const PUCHAR)&dw,
                       sizeof(ULONG));
        }
       else
@@ -312,19 +314,21 @@ do_reg_operation(HKEY KeyHandle,
 
          if (Str)
            {
-             RegSetValue (KeyHandle,
+             RegSetValueExA (KeyHandle,
                           ValueName,
+                          0,
                           Type,
                           (PVOID)Str,
-                          Size);
+                          (ULONG)Size);
            }
          else
            {
-             RegSetValue (KeyHandle,
+             RegSetValueExA (KeyHandle,
                           ValueName,
+                          0,
                           Type,
                           (PVOID)&EmptyStr,
-                          sizeof(CHAR));
+                          (ULONG)sizeof(CHAR));
            }
        }
       free (Str);
@@ -346,11 +350,12 @@ do_reg_operation(HKEY KeyHandle,
          InfHostGetBinaryField (Context, 5, Data, Size, NULL);
        }
 
-      RegSetValue (KeyHandle,
+      RegSetValueExA (KeyHandle,
                   ValueName,
+                  0,
                   Type,
                   (PVOID)Data,
-                  Size);
+                  (ULONG)Size);
 
       free (Data);
     }
@@ -370,7 +375,7 @@ registry_callback (HINF hInf, PCHAR Section, BOOL Delete)
   CHAR Buffer[MAX_INF_STRING_LENGTH];
   PCHAR ValuePtr;
   ULONG Flags;
-  ULONG Length;
+  size_t Length;
 
   PINFCONTEXT Context = NULL;
   HKEY KeyHandle;
@@ -411,7 +416,7 @@ registry_callback (HINF hInf, PCHAR Section, BOOL Delete)
 
       if (Delete || (Flags & FLG_ADDREG_OVERWRITEONLY))
        {
-         if (RegOpenKey (NULL, Buffer, &KeyHandle) != ERROR_SUCCESS)
+         if (RegOpenKeyA (NULL, Buffer, &KeyHandle) != ERROR_SUCCESS)
            {
              DPRINT("RegOpenKey(%s) failed\n", Buffer);
              continue;  /* ignore if it doesn't exist */
@@ -419,7 +424,7 @@ registry_callback (HINF hInf, PCHAR Section, BOOL Delete)
        }
       else
        {
-         if (RegCreateKey (NULL, Buffer, &KeyHandle) != ERROR_SUCCESS)
+         if (RegCreateKeyA (NULL, Buffer, &KeyHandle) != ERROR_SUCCESS)
            {
              DPRINT("RegCreateKey(%s) failed\n", Buffer);
              continue;
@@ -450,9 +455,7 @@ registry_callback (HINF hInf, PCHAR Section, BOOL Delete)
 
 
 BOOL
-ImportRegistryFile(PCHAR FileName,
-                  PCHAR Section,
-                  BOOL Delete)
+ImportRegistryFile(PCHAR FileName)
 {
   HINF hInf;
   ULONG ErrorLine;
index 65cfd92..04e8b0b 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ReactOS kernel
- *  Copyright (C) 2003 ReactOS Team
+ *  Copyright (C) 2006 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
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id$
- * COPYRIGHT:       See COPYING in the top level directory
+/* COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS hive maker
  * FILE:            tools/mkhive/reginf.h
  * PURPOSE:         Inf file import code
- * PROGRAMMER:      Eric Kohl
+ * PROGRAMMER:      Hervé Poussineau
  */
 
 #ifndef __REGINF_H__
 #define __REGINF_H__
 
 BOOL
-ImportRegistryFile(PCHAR Filename,
-                  PCHAR Section,
-                  BOOL Delete);
+ImportRegistryFile(PCHAR Filename);
 
 #endif /* __REGINF_H__ */
 
index 105f897..f4863d3 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ReactOS kernel
- *  Copyright (C) 2003 ReactOS Team
+ *  Copyright (C) 2006 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
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id$
- * COPYRIGHT:       See COPYING in the top level directory
+/* COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS hive maker
  * FILE:            tools/mkhive/registry.c
  * PURPOSE:         Registry code
- * PROGRAMMER:      Eric Kohl
+ * PROGRAMMER:      Hervé Poussineau
  */
 
 /*
  * TODO:
- *     - Implement RegDeleteKey().
- *     - Fix RegEnumValue().
+ *     - Implement RegDeleteKey()
+ *     - Implement RegEnumValue()
+ *     - Implement RegQueryValueExA()
  */
 
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
 
+#define NDEBUG
 #include "mkhive.h"
-#include "registry.h"
 
+static EREGISTRY_HIVE RootHive;
+static MEMKEY RootKey;
+EREGISTRY_HIVE DefaultHive;  /* \Registry\User\.DEFAULT */
+EREGISTRY_HIVE SamHive;      /* \Registry\Machine\SAM */
+EREGISTRY_HIVE SecurityHive; /* \Registry\Machine\SECURITY */
+EREGISTRY_HIVE SoftwareHive; /* \Registry\Machine\SOFTWARE */
+EREGISTRY_HIVE SystemHive;   /* \Registry\Machine\SYSTEM */
+
+static MEMKEY
+CreateInMemoryStructure(
+       IN PEREGISTRY_HIVE RegistryHive,
+       IN HCELL_INDEX KeyCellOffset,
+       IN PCUNICODE_STRING KeyName)
+{
+       MEMKEY Key;
 
-static HKEY RootKey;
+       Key = (MEMKEY) malloc (sizeof(KEY));
+       if (!Key)
+               return NULL;
 
+       InitializeListHead (&Key->SubKeyList);
+       InitializeListHead (&Key->ValueList);
+       InitializeListHead (&Key->KeyList);
 
-VOID
-RegInitializeRegistry(VOID)
-{
-  HKEY ControlSetKey;
-  HKEY LinkKey;
-
-  /* Create root key */
-  RootKey = (HKEY)malloc(sizeof(KEY));
-
-  InitializeListHead(&RootKey->SubKeyList);
-  InitializeListHead(&RootKey->ValueList);
-  InitializeListHead(&RootKey->KeyList);
-
-  RootKey->SubKeyCount = 0;
-  RootKey->ValueCount = 0;
-
-  RootKey->NameSize = 2;
-  RootKey->Name = (PCHAR)malloc(2);
-  strcpy(RootKey->Name, "\\");
-
-  RootKey->DataType = 0;
-  RootKey->DataSize = 0;
-  RootKey->Data = NULL;
-
-  /* Create SYSTEM key */
-  RegCreateKey(RootKey,
-              "Registry\\Machine\\SYSTEM",
-              NULL);
-
-  /* Create link 'CurrentControlSet' --> 'ControlSet001' */
-  RegCreateKey(RootKey,
-              "Registry\\Machine\\SYSTEM\\ControlSet001",
-              &ControlSetKey);
-
-  RegCreateKey(RootKey,
-              "Registry\\Machine\\SYSTEM\\CurrentControlSet",
-              &LinkKey);
-
-  RegSetValue(LinkKey,
-             NULL,
-             REG_LINK,
-             (PCHAR)&ControlSetKey,
-             sizeof(PVOID));
-
-  /* Create HARDWARE key */
-  RegCreateKey(RootKey,
-              "Registry\\Machine\\HARDWARE",
-              NULL);
-
-  /* Create SAM key */
-  RegCreateKey(RootKey,
-              "Registry\\Machine\\SAM",
-              NULL);
-
-  /* Create SECURITY key */
-  RegCreateKey(RootKey,
-              "Registry\\Machine\\SECURITY",
-              NULL);
-
-  /* Create SOFTWARE key */
-  RegCreateKey(RootKey,
-              "Registry\\Machine\\SOFTWARE",
-              NULL);
-
-  /* Create DEFAULT key */
-  RegCreateKey(RootKey,
-              "Registry\\User\\.DEFAULT",
-              NULL);
-}
+       Key->SubKeyCount = 0;
+       Key->ValueCount = 0;
+
+       Key->NameSize = KeyName->Length;
+       Key->Name = malloc (Key->NameSize);
+       if (!Key->Name)
+               return NULL;
+       memcpy(Key->Name, KeyName->Buffer, KeyName->Length);
 
+       Key->DataType = 0;
+       Key->DataSize = 0;
+       Key->Data = NULL;
 
-LONG
-RegCreateKey(HKEY ParentKey,
-            PCHAR KeyName,
-            PHKEY Key)
+       Key->RegistryHive = RegistryHive;
+       Key->KeyCellOffset = KeyCellOffset;
+       Key->KeyCell = HvGetCell (&RegistryHive->Hive, Key->KeyCellOffset);
+       if (!Key->KeyCell)
+       {
+               free(Key);
+               return NULL;
+       }
+       Key->LinkedKey = NULL;
+       return Key;
+}
+
+static LONG
+RegpOpenOrCreateKey(
+       IN HKEY hParentKey,
+       IN PCWSTR KeyName,
+       IN BOOL AllowCreation,
+       OUT PHKEY Key)
 {
-  PLIST_ENTRY Ptr;
-  HKEY SearchKey = INVALID_HANDLE_VALUE;
-  HKEY CurrentKey;
-  HKEY NewKey;
-  PCHAR p;
-  PCHAR name;
-  int subkeyLength;
-  int stringLength;
-
-  DPRINT ("RegCreateKey('%s')\n", KeyName);
-
-  if (*KeyName == '\\')
-    {
-      KeyName++;
-      CurrentKey = RootKey;
-    }
-  else if (ParentKey == NULL)
-    {
-      CurrentKey = RootKey;
-    }
-  else
-    {
-      CurrentKey = ParentKey;
-    }
-
-  /* Check whether current key is a link */
-  if (CurrentKey->DataType == REG_LINK)
-    {
-      CurrentKey = (HKEY)CurrentKey->Data;
-    }
-
-  while (*KeyName != 0)
-    {
-      DPRINT ("KeyName '%s'\n", KeyName);
-
-      if (*KeyName == '\\')
-       KeyName++;
-      p = strchr (KeyName, '\\');
-      if ((p != NULL) && (p != KeyName))
+       PWSTR LocalKeyName;
+       PWSTR End;
+       UNICODE_STRING KeyString;
+       NTSTATUS Status;
+       MEMKEY ParentKey;
+       MEMKEY CurrentKey;
+       PLIST_ENTRY Ptr;
+       PCM_KEY_NODE SubKeyCell;
+       HCELL_INDEX BlockOffset;
+
+       DPRINT("RegpCreateOpenKey('%S')\n", KeyName);
+
+       if (*KeyName == L'\\')
        {
-         subkeyLength = p - KeyName;
-         stringLength = subkeyLength + 1;
-         name = KeyName;
+               KeyName++;
+               ParentKey = RootKey;
        }
-      else
+       else if (hParentKey == NULL)
        {
-         subkeyLength = strlen (KeyName);
-         stringLength = subkeyLength;
-         name = KeyName;
+               ParentKey = RootKey;
        }
-
-      Ptr = CurrentKey->SubKeyList.Flink;
-      while (Ptr != &CurrentKey->SubKeyList)
+       else
        {
-         DPRINT ("Ptr 0x%p\n", Ptr);
-
-         SearchKey = CONTAINING_RECORD(Ptr,
-                                       KEY,
-                                       KeyList);
-         DPRINT ("SearchKey 0x%p\n", SearchKey);
-         DPRINT ("Searching '%s'\n", SearchKey->Name);
-         if (strncasecmp (SearchKey->Name, name, subkeyLength) == 0)
-           break;
-
-         Ptr = Ptr->Flink;
+               ParentKey = HKEY_TO_MEMKEY(RootKey);
        }
 
-      if (Ptr == &CurrentKey->SubKeyList)
+       LocalKeyName = (PWSTR)KeyName;
+       for (;;)
        {
-         /* no key found -> create new subkey */
-         NewKey = (HKEY)malloc (sizeof(KEY));
-         if (NewKey == NULL)
-          return ERROR_OUTOFMEMORY;
-
-         InitializeListHead (&NewKey->SubKeyList);
-         InitializeListHead (&NewKey->ValueList);
-
-         NewKey->SubKeyCount = 0;
-         NewKey->ValueCount = 0;
-
-         NewKey->DataType = 0;
-         NewKey->DataSize = 0;
-         NewKey->Data = NULL;
-
-         InsertTailList (&CurrentKey->SubKeyList, &NewKey->KeyList);
-         CurrentKey->SubKeyCount++;
+               End = wcschr(LocalKeyName, '\\');
+               if (End)
+               {
+                       KeyString.Buffer = LocalKeyName;
+                       KeyString.Length = KeyString.MaximumLength =
+                               (USHORT)((ULONG_PTR)End - (ULONG_PTR)LocalKeyName);
+               }
+               else
+                       RtlInitUnicodeString(&KeyString, LocalKeyName);
+
+               /* Check subkey in memory structure */
+               Ptr = ParentKey->SubKeyList.Flink;
+               while (Ptr != &ParentKey->SubKeyList)
+               {
+                       CurrentKey = CONTAINING_RECORD(Ptr, KEY, KeyList);
+                       if (CurrentKey->NameSize == KeyString.Length
+                        && memcmp(CurrentKey->Name, KeyString.Buffer, KeyString.Length) == 0)
+                       {
+                               goto nextsubkey;
+                       }
+
+                       Ptr = Ptr->Flink;
+               }
+
+               Status = CmiScanForSubKey(
+                       ParentKey->RegistryHive,
+                       ParentKey->KeyCell,
+                       &KeyString,
+                       0,
+                       &SubKeyCell,
+                       &BlockOffset);
+               if (AllowCreation && Status == STATUS_OBJECT_NAME_NOT_FOUND)
+               {
+                       Status = CmiAddSubKey(
+                               ParentKey->RegistryHive,
+                               ParentKey->KeyCell,
+                               ParentKey->KeyCellOffset,
+                               &KeyString,
+                               0,
+                               &SubKeyCell,
+                               &BlockOffset);
+               }
+               if (!NT_SUCCESS(Status))
+                       return ERROR_UNSUCCESSFUL;
+
+               /* Now, SubKeyCell/BlockOffset are valid */
+               CurrentKey = CreateInMemoryStructure(
+                       ParentKey->RegistryHive,
+                       BlockOffset,
+                       &KeyString);
+               if (!CurrentKey)
+                       return ERROR_OUTOFMEMORY;
+
+               /* Add CurrentKey in ParentKey */
+               InsertTailList(&ParentKey->SubKeyList, &CurrentKey->KeyList);
+               ParentKey->SubKeyCount++;
+
+nextsubkey:
+               /* Follow registry links */
+               while (CurrentKey->LinkedKey)
+                       CurrentKey = CurrentKey->LinkedKey;
+               ParentKey = CurrentKey;
+               if (End)
+                       LocalKeyName = End + 1;
+               else
+                       break;
+       }
 
-         NewKey->NameSize = subkeyLength + 1;
-         NewKey->Name = (PCHAR)malloc (NewKey->NameSize);
-         if (NewKey->Name == NULL)
-          return(ERROR_OUTOFMEMORY);
-         memcpy(NewKey->Name, name, subkeyLength);
-         NewKey->Name[subkeyLength] = 0;
+       *Key = MEMKEY_TO_HKEY(ParentKey);
 
-         DPRINT ("NewKey 0x%p\n", NewKey);
-         DPRINT ("NewKey '%s'  Length %ld\n", NewKey->Name, NewKey->NameSize);
+       return ERROR_SUCCESS;
+}
 
-         CurrentKey = NewKey;
-       }
-      else
-       {
-         CurrentKey = SearchKey;
+LONG WINAPI
+RegCreateKeyW(
+       IN HKEY hKey,
+       IN LPCWSTR lpSubKey,
+       OUT PHKEY phkResult)
+{
+       return RegpOpenOrCreateKey(hKey, lpSubKey, TRUE, phkResult);
+}
 
-         /* Check whether current key is a link */
-         if (CurrentKey->DataType == REG_LINK)
-           {
-             CurrentKey = (HKEY)CurrentKey->Data;
-           }
-       }
+static PWSTR
+MultiByteToWideChar(
+       IN PCSTR MultiByteString)
+{
+       ANSI_STRING Source;
+       UNICODE_STRING Destination;
+       NTSTATUS Status;
+
+       RtlInitAnsiString(&Source, MultiByteString);
+       Status = RtlAnsiStringToUnicodeString(&Destination, &Source, TRUE);
+       if (!NT_SUCCESS(Status))
+               return NULL;
+       return Destination.Buffer;
+}
 
-      KeyName = KeyName + stringLength;
-    }
+LONG WINAPI
+RegCreateKeyA(
+       IN HKEY hKey,
+       IN LPCSTR lpSubKey,
+       OUT PHKEY phkResult)
+{
+       PWSTR lpSubKeyW;
+       LONG rc;
 
-  if (Key != NULL)
-    *Key = CurrentKey;
+       lpSubKeyW = MultiByteToWideChar(lpSubKey);
+       if (!lpSubKeyW)
+               return ERROR_OUTOFMEMORY;
 
-  return ERROR_SUCCESS;
+       rc = RegCreateKeyW(hKey, lpSubKeyW, phkResult);
+       free(lpSubKeyW);
+       return rc;
 }
 
-
-LONG
-RegDeleteKey(HKEY Key,
-            PCHAR Name)
+LONG WINAPI
+RegDeleteKeyA(HKEY Key,
+            LPCSTR Name)
 {
   if (Name != NULL && strchr(Name, '\\') != NULL)
     return(ERROR_INVALID_PARAMETER);
@@ -249,458 +249,432 @@ RegDeleteKey(HKEY Key,
   return(ERROR_SUCCESS);
 }
 
-
-LONG
-RegEnumKey(HKEY Key,
-          ULONG Index,
-          PCHAR Name,
-          PULONG NameSize)
+LONG WINAPI
+RegOpenKeyW(
+       IN HKEY hKey,
+       IN LPCWSTR lpSubKey,
+       OUT PHKEY phkResult)
 {
-  PLIST_ENTRY Ptr;
-  HKEY SearchKey;
-  ULONG Count = 0;
-  ULONG Size;
-
-  Ptr = Key->SubKeyList.Flink;
-  while (Ptr != &Key->SubKeyList)
-    {
-      if (Index == Count)
-       break;
-
-      Count++;
-      Ptr = Ptr->Flink;
-    }
-
-  if (Ptr == &Key->SubKeyList)
-    return(ERROR_NO_MORE_ITEMS);
-
-  SearchKey = CONTAINING_RECORD(Ptr,
-                               KEY,
-                               KeyList);
+       return RegpOpenOrCreateKey(hKey, lpSubKey, FALSE, phkResult);
+}
 
-  DPRINT ("Name '%s'  Length %ld\n", SearchKey->Name, SearchKey->NameSize);
+LONG WINAPI
+RegOpenKeyA(
+       IN HKEY hKey,
+       IN LPCSTR lpSubKey,
+       OUT PHKEY phkResult)
+{
+       PWSTR lpSubKeyW;
+       LONG rc;
 
-  Size = min(SearchKey->NameSize, *NameSize);
-  *NameSize = Size;
-  memcpy(Name, SearchKey->Name, Size);
+       lpSubKeyW = MultiByteToWideChar(lpSubKey);
+       if (!lpSubKeyW)
+               return ERROR_OUTOFMEMORY;
 
-  return(ERROR_SUCCESS);
+       rc = RegOpenKeyW(hKey, lpSubKeyW, phkResult);
+       free(lpSubKeyW);
+       return rc;
 }
 
-
-LONG
-RegOpenKey(HKEY ParentKey,
-          PCHAR KeyName,
-          PHKEY Key)
+static NTSTATUS
+RegpOpenOrCreateValue(
+       IN HKEY hKey,
+       IN LPCWSTR ValueName,
+       IN BOOL AllowCreation,
+       OUT PCM_KEY_VALUE *ValueCell,
+       OUT PHCELL_INDEX ValueCellOffset)
 {
-  PLIST_ENTRY Ptr;
-  HKEY SearchKey = INVALID_HANDLE_VALUE;
-  HKEY CurrentKey;
-  PCHAR p;
-  PCHAR name;
-  int subkeyLength;
-  int stringLength;
-
-  DPRINT("KeyName '%s'\n", KeyName);
-
-  *Key = NULL;
-
-  if (*KeyName == '\\')
-    {
-      KeyName++;
-      CurrentKey = RootKey;
-    }
-  else if (ParentKey == NULL)
-    {
-      CurrentKey = RootKey;
-    }
-  else
-    {
-      CurrentKey = ParentKey;
-    }
-
-  /* Check whether current key is a link */
-  if (CurrentKey->DataType == REG_LINK)
-    {
-      CurrentKey = (HKEY)CurrentKey->Data;
-    }
-
-  while (*KeyName != 0)
-    {
-      DPRINT ("KeyName '%s'\n", KeyName);
-
-      if (*KeyName == '\\')
-       KeyName++;
-      p = strchr(KeyName, '\\');
-      if ((p != NULL) && (p != KeyName))
-       {
-         subkeyLength = p - KeyName;
-         stringLength = subkeyLength + 1;
-         name = KeyName;
-       }
-      else
+       MEMKEY ParentKey;
+       UNICODE_STRING ValueString;
+       NTSTATUS Status;
+
+       ParentKey = HKEY_TO_MEMKEY(hKey);
+       RtlInitUnicodeString(&ValueString, ValueName);
+
+       Status = CmiScanForValueKey(
+               ParentKey->RegistryHive,
+               ParentKey->KeyCell,
+               &ValueString,
+               ValueCell,
+               ValueCellOffset);
+       if (AllowCreation && Status == STATUS_OBJECT_NAME_NOT_FOUND)
        {
-         subkeyLength = strlen(KeyName);
-         stringLength = subkeyLength;
-         name = KeyName;
+               Status = CmiAddValueKey(
+                       ParentKey->RegistryHive,
+                       ParentKey->KeyCell,
+                       ParentKey->KeyCellOffset,
+                       &ValueString,
+                       ValueCell,
+                       ValueCellOffset);
        }
+       if (!NT_SUCCESS(Status))
+               return Status;
+       return STATUS_SUCCESS;
+}
 
-      Ptr = CurrentKey->SubKeyList.Flink;
-      while (Ptr != &CurrentKey->SubKeyList)
+LONG WINAPI
+RegSetValueExW(
+       IN HKEY hKey,
+       IN LPCWSTR lpValueName OPTIONAL,
+       IN ULONG Reserved,
+       IN ULONG dwType,
+       IN const PUCHAR lpData,
+       IN USHORT cbData)
+{
+       MEMKEY Key, DestKey;
+       PHKEY phKey;
+       PCM_KEY_VALUE ValueCell;
+       HCELL_INDEX ValueCellOffset;
+       PVOID DataCell;
+       LONG DataCellSize;
+       NTSTATUS Status;
+
+       if (dwType == REG_LINK)
        {
-         DPRINT ("Ptr 0x%p\n", Ptr);
+               /* Special handling of registry links */
+               if (cbData != sizeof(PVOID))
+                       return STATUS_INVALID_PARAMETER;
+               phKey = (PHKEY)lpData;
+               Key = HKEY_TO_MEMKEY(hKey);
+               DestKey = HKEY_TO_MEMKEY(*phKey);
+
+               /* Create the link in memory */
+               Key->LinkedKey = DestKey;
+
+               /* Create the link in registry hive (if applicable) */
+               if (Key->RegistryHive != DestKey->RegistryHive)
+                       return STATUS_SUCCESS;
+               DPRINT1("Save link to registry\n");
+               return STATUS_NOT_IMPLEMENTED;
+       }
 
-         SearchKey = CONTAINING_RECORD(Ptr,
-                                       KEY,
-                                       KeyList);
+       if ((cbData & REG_DATA_SIZE_MASK) != cbData)
+               return STATUS_UNSUCCESSFUL;
 
-         DPRINT ("SearchKey 0x%p\n", SearchKey);
-         DPRINT ("Searching '%s'\n", SearchKey->Name);
+       Key = HKEY_TO_MEMKEY(hKey);
 
-         if (strncasecmp(SearchKey->Name, name, subkeyLength) == 0)
-           break;
+       Status = RegpOpenOrCreateValue(hKey, lpValueName, TRUE, &ValueCell, &ValueCellOffset);
+       if (!NT_SUCCESS(Status))
+               return ERROR_UNSUCCESSFUL;
 
-         Ptr = Ptr->Flink;
+       /* Get size of the allocated cellule (if any) */
+       if (!(ValueCell->DataSize & REG_DATA_IN_OFFSET) &&
+               (ValueCell->DataSize & REG_DATA_SIZE_MASK) != 0)
+       {
+               DataCell = HvGetCell(&Key->RegistryHive->Hive, ValueCell->DataOffset);
+               if (!DataCell)
+                       return ERROR_UNSUCCESSFUL;
+               DataCellSize = -HvGetCellSize(&Key->RegistryHive->Hive, DataCell);
+       }
+       else
+       {
+               DataCell = NULL;
+               DataCellSize = 0;
        }
 
-      if (Ptr == &CurrentKey->SubKeyList)
+       if (cbData <= sizeof(HCELL_INDEX))
        {
-         return(ERROR_PATH_NOT_FOUND);
+               /* If data size <= sizeof(HCELL_INDEX) then store data in the data offset */
+               DPRINT("ValueCell->DataSize %lu\n", ValueCell->DataSize);
+               if (DataCell)
+                       HvFreeCell(&Key->RegistryHive->Hive, ValueCell->DataOffset);
+
+               RtlCopyMemory(&ValueCell->DataOffset, lpData, cbData);
+               ValueCell->DataSize = (ULONG)(cbData | REG_DATA_IN_OFFSET);
+               ValueCell->DataType = dwType;
+               HvMarkCellDirty(&Key->RegistryHive->Hive, ValueCellOffset);
        }
-      else
+       else
        {
-         CurrentKey = SearchKey;
-
-         /* Check whether current key is a link */
-         if (CurrentKey->DataType == REG_LINK)
-           {
-             CurrentKey = (HKEY)CurrentKey->Data;
-           }
+               if (cbData > (SIZE_T)DataCellSize)
+               {
+                       /* New data size is larger than the current, destroy current
+                        * data block and allocate a new one. */
+                       HCELL_INDEX NewOffset;
+
+                       DPRINT("ValueCell->DataSize %lu\n", ValueCell->DataSize);
+
+                       NewOffset = HvAllocateCell(&Key->RegistryHive->Hive, cbData, HvStable);
+                       if (NewOffset == HCELL_NULL)
+                       {
+                               DPRINT("HvAllocateCell() failed with status 0x%08lx\n", Status);
+                               return ERROR_UNSUCCESSFUL;
+                       }
+
+                       if (DataCell)
+                               HvFreeCell(&Key->RegistryHive->Hive, ValueCell->DataOffset);
+
+                       ValueCell->DataOffset = NewOffset;
+                       DataCell = HvGetCell(&Key->RegistryHive->Hive, NewOffset);
+               }
+
+               /* Copy new contents to cellule */
+               RtlCopyMemory(DataCell, lpData, cbData);
+               ValueCell->DataSize = (ULONG)(cbData & REG_DATA_SIZE_MASK);
+               ValueCell->DataType = dwType;
+               HvMarkCellDirty(&Key->RegistryHive->Hive, ValueCell->DataOffset);
+               HvMarkCellDirty(&Key->RegistryHive->Hive, ValueCellOffset);
        }
 
-      KeyName = KeyName + stringLength;
-    }
-
-  if (Key != NULL)
-    *Key = CurrentKey;
+       HvMarkCellDirty(&Key->RegistryHive->Hive, Key->KeyCellOffset);
 
-  return(ERROR_SUCCESS);
+       DPRINT("Return status 0x%08lx\n", Status);
+       return Status;
 }
 
-
-LONG
-RegSetValue(HKEY Key,
-           PCHAR ValueName,
-           ULONG Type,
-           PCHAR Data,
-           ULONG DataSize)
+LONG WINAPI
+RegSetValueExA(
+       IN HKEY hKey,
+       IN LPCSTR lpValueName OPTIONAL,
+       IN ULONG Reserved,
+       IN ULONG dwType,
+       IN const PUCHAR lpData,
+       IN ULONG cbData)
 {
-  PLIST_ENTRY Ptr;
-  PVALUE Value = NULL;
-
-  DPRINT ("Key 0x%x, ValueName '%s', Type %d, Data 0x%x, DataSize %d\n",
-         (int)Key, ValueName, (int)Type, (int)Data, (int)DataSize);
+       LPWSTR lpValueNameW = NULL;
+       PUCHAR lpDataW;
+       USHORT cbDataW;
+       LONG rc = ERROR_SUCCESS;
 
-  if ((ValueName == NULL) || (*ValueName == 0))
-    {
-      /* set default value */
-      if ((Key->Data != NULL) && (Key->DataSize > sizeof(PCHAR)))
+       DPRINT("RegSetValueA(%s)\n", lpValueName);
+       if (lpValueName)
        {
-         free(Key->Data);
+               lpValueNameW = MultiByteToWideChar(lpValueName);
+               if (!lpValueNameW)
+                       return ERROR_OUTOFMEMORY;
        }
 
-      if (DataSize <= sizeof(PCHAR))
+       if ((dwType == REG_SZ || dwType == REG_EXPAND_SZ || dwType == REG_MULTI_SZ)
+        && cbData != 0)
        {
-         Key->DataSize = DataSize;
-         Key->DataType = Type;
-         memcpy(&Key->Data, Data, DataSize);
+               ANSI_STRING AnsiString;
+               UNICODE_STRING Data;
+
+               if (lpData[cbData - 1] != '\0')
+                       cbData++;
+               RtlInitAnsiString(&AnsiString, NULL);
+               AnsiString.Buffer = (PSTR)lpData;
+               AnsiString.Length = (USHORT)cbData - 1;
+               AnsiString.MaximumLength = (USHORT)cbData;
+               RtlAnsiStringToUnicodeString (&Data, &AnsiString, TRUE);
+               lpDataW = (const PUCHAR)Data.Buffer;
+               cbDataW = Data.MaximumLength;
        }
-      else
+       else
        {
-         Key->Data = (PCHAR)malloc(DataSize);
-         Key->DataSize = DataSize;
-         Key->DataType = Type;
-         memcpy(Key->Data, Data, DataSize);
+               lpDataW = lpData;
+               cbDataW = (USHORT)cbData;
        }
-    }
-  else
-    {
-      /* set non-default value */
-      Ptr = Key->ValueList.Flink;
-      while (Ptr != &Key->ValueList)
-       {
-         Value = CONTAINING_RECORD(Ptr,
-                                   VALUE,
-                                   ValueList);
 
-         DPRINT ("Value->Name '%s'\n", Value->Name);
-
-         if (strcasecmp(Value->Name, ValueName) == 0)
-           break;
+       if (rc == ERROR_SUCCESS)
+               rc = RegSetValueExW(hKey, lpValueNameW, 0, dwType, lpDataW, cbDataW);
+       if (lpValueNameW)
+               free(lpValueNameW);
+       if (lpData != lpDataW)
+               free(lpDataW);
+       return rc;
+}
 
-         Ptr = Ptr->Flink;
-       }
+LONG WINAPI
+RegQueryValueExW(
+       IN HKEY hKey,
+       IN LPCWSTR lpValueName,
+       IN PULONG lpReserved,
+       OUT PULONG lpType,
+       OUT PUCHAR lpData,
+       OUT PSIZE_T lpcbData)
+{
+       //ParentKey = HKEY_TO_MEMKEY(RootKey);
+       PCM_KEY_VALUE ValueCell;
+       HCELL_INDEX ValueCellOffset;
+       NTSTATUS Status;
+
+       Status = RegpOpenOrCreateValue(
+                       hKey,
+                       lpValueName,
+                       FALSE,
+                       &ValueCell,
+                       &ValueCellOffset);
+
+       //Status = CmiScanForValueKey(
+       //      x
+       return ERROR_UNSUCCESSFUL;
+}
 
-      if (Ptr == &Key->ValueList)
-       {
-         /* add new value */
-         DPRINT("No value found - adding new value\n");
-
-         Value = (PVALUE)malloc(sizeof(VALUE));
-         if (Value == NULL)
-           return(ERROR_OUTOFMEMORY);
-         InsertTailList(&Key->ValueList, &Value->ValueList);
-         Key->ValueCount++;
-         Value->NameSize = strlen(ValueName)+1;
-         Value->Name = (PCHAR)malloc(Value->NameSize);
-         if (Value->Name == NULL)
-           return(ERROR_OUTOFMEMORY);
-         strcpy(Value->Name, ValueName);
-         Value->DataType = REG_NONE;
-         Value->DataSize = 0;
-         Value->Data = NULL;
-       }
+LONG WINAPI
+RegQueryValueExA(
+       IN HKEY hKey,
+       IN LPCSTR lpValueName,
+       IN PULONG lpReserved,
+       OUT PULONG lpType,
+       OUT PUCHAR lpData,
+       OUT PSIZE_T lpcbData)
+{
+       LPWSTR lpValueNameW = NULL;
+       LONG rc;
 
-      /* set new value */
-      if ((Value->Data != NULL) && (Value->DataSize > sizeof(PCHAR)))
+       DPRINT1("RegQueryValueExA(%s) not implemented\n", lpValueName);
+       if (lpValueName)
        {
-         free(Value->Data);
+               lpValueNameW = MultiByteToWideChar(lpValueName);
+               if (!lpValueNameW)
+                       return ERROR_OUTOFMEMORY;
        }
 
-      if (DataSize <= sizeof(PCHAR))
-       {
-         Value->DataSize = DataSize;
-         Value->DataType = Type;
-         memcpy(&Value->Data, Data, DataSize);
-       }
-      else
-       {
-         Value->Data = (PCHAR)malloc(DataSize);
-         if (Value->Data == NULL)
-           return(ERROR_OUTOFMEMORY);
-         Value->DataType = Type;
-         Value->DataSize = DataSize;
-         memcpy(Value->Data, Data, DataSize);
-       }
-    }
-  return(ERROR_SUCCESS);
+       rc = RegQueryValueExW(hKey, lpValueNameW, lpReserved, lpType, lpData, lpcbData);
+       if (lpValueNameW)
+               free(lpValueNameW);
+       return ERROR_UNSUCCESSFUL;
 }
 
-
-LONG
-RegQueryValue(HKEY Key,
-             PCHAR ValueName,
-             PULONG Type,
-             PCHAR Data,
-             PULONG DataSize)
+LONG WINAPI
+RegDeleteValueW(
+       IN HKEY hKey,
+       IN LPCWSTR lpValueName OPTIONAL)
 {
-  ULONG Size;
-  PLIST_ENTRY Ptr;
-  PVALUE Value = NULL;
-
-  if ((ValueName == NULL) || (*ValueName == 0))
-    {
-      /* query default value */
-      if (Key->Data == NULL)
-       return(ERROR_INVALID_PARAMETER);
-
-      if (Type != NULL)
-       *Type = Key->DataType;
-      if ((Data != NULL) && (DataSize != NULL))
-       {
-         if (Key->DataSize <= sizeof(PCHAR))
-           {
-             Size = min(Key->DataSize, *DataSize);
-             memcpy(Data, &Key->Data, Size);
-             *DataSize = Size;
-           }
-         else
-           {
-             Size = min(Key->DataSize, *DataSize);
-             memcpy(Data, Key->Data, Size);
-             *DataSize = Size;
-           }
-       }
-      else if ((Data == NULL) && (DataSize != NULL))
-       {
-         *DataSize = Key->DataSize;
-       }
-    }
-  else
-    {
-      /* query non-default value */
-      Ptr = Key->ValueList.Flink;
-      while (Ptr != &Key->ValueList)
-       {
-         Value = CONTAINING_RECORD(Ptr,
-                                   VALUE,
-                                   ValueList);
-
-         DPRINT("Searching for '%s'. Value name '%s'\n", ValueName, Value->Name);
-
-         if (strcasecmp(Value->Name, ValueName) == 0)
-           break;
-
-         Ptr = Ptr->Flink;
-       }
+       DPRINT1("RegDeleteValueW() unimplemented\n");
+       return ERROR_UNSUCCESSFUL;
+}
 
-      if (Ptr == &Key->ValueList)
-       return(ERROR_INVALID_PARAMETER);
+LONG WINAPI
+RegDeleteValueA(
+       IN HKEY hKey,
+       IN LPCSTR lpValueName OPTIONAL)
+{
+       LPWSTR lpValueNameW;
+       LONG rc;
 
-      if (Type != NULL)
-       *Type = Value->DataType;
-      if ((Data != NULL) && (DataSize != NULL))
+       if (lpValueName)
        {
-         if (Value->DataSize <= sizeof(PCHAR))
-           {
-             Size = min(Value->DataSize, *DataSize);
-             memcpy(Data, &Value->Data, Size);
-             *DataSize = Size;
-           }
-         else
-           {
-             Size = min(Value->DataSize, *DataSize);
-             memcpy(Data, Value->Data, Size);
-             *DataSize = Size;
-           }
+               lpValueNameW = MultiByteToWideChar(lpValueName);
+               if (!lpValueNameW)
+                       return ERROR_OUTOFMEMORY;
+               rc = RegDeleteValueW(hKey, lpValueNameW);
+               free(lpValueNameW);
        }
-      else if ((Data == NULL) && (DataSize != NULL))
-       {
-         *DataSize = Value->DataSize;
-       }
-    }
-
-  return(ERROR_SUCCESS);
+       else
+               rc = RegDeleteValueW(hKey, NULL);
+       return rc;
 }
 
-
-LONG
-RegDeleteValue(HKEY Key,
-              PCHAR ValueName)
+static BOOL
+ConnectRegistry(
+       IN HKEY RootKey,
+       IN PEREGISTRY_HIVE HiveToConnect,
+       IN LPCWSTR Path)
 {
-  PLIST_ENTRY Ptr;
-  PVALUE Value = NULL;
-
-  if ((ValueName == NULL) || (*ValueName == 0))
-    {
-      /* delete default value */
-      if (Key->Data != NULL)
-       free(Key->Data);
-      Key->Data = NULL;
-      Key->DataSize = 0;
-      Key->DataType = 0;
-    }
-  else
-    {
-      /* delete non-default value */
-      Ptr = Key->ValueList.Flink;
-      while (Ptr != &Key->ValueList)
-       {
-         Value = CONTAINING_RECORD(Ptr,
-                                   VALUE,
-                                   ValueList);
-         if (strcasecmp(Value->Name, ValueName) == 0)
-           break;
+       NTSTATUS Status;
+       MEMKEY NewKey;
+       LONG rc;
 
-         Ptr = Ptr->Flink;
-       }
-
-      if (Ptr == &Key->ValueList)
-       return(ERROR_INVALID_PARAMETER);
-
-      /* delete value */
-      Key->ValueCount--;
-      if (Value->Name != NULL)
-       free(Value->Name);
-      Value->Name = NULL;
-      Value->NameSize = 0;
-
-      if (Value->DataSize > sizeof(PCHAR))
+       Status = CmiInitializeTempHive(HiveToConnect);
+       if (!NT_SUCCESS(Status))
        {
-         if (Value->Data != NULL)
-           free(Value->Data);
+               DPRINT1("CmiInitializeTempHive() failed with status 0x%08lx\n", Status);
+               return FALSE;
        }
-      Value->Data = NULL;
-      Value->DataSize = 0;
-      Value->DataType = 0;
 
-      RemoveEntryList(&Value->ValueList);
-      free(Value);
-    }
-  return(ERROR_SUCCESS);
+       /* Create key */
+       rc = RegCreateKeyW(
+               RootKey,
+               Path,
+               (PHKEY)&NewKey);
+       if (rc != ERROR_SUCCESS)
+               return FALSE;
+
+       NewKey->RegistryHive = HiveToConnect;
+       NewKey->KeyCellOffset = HiveToConnect->Hive.HiveHeader->RootCell;
+       NewKey->KeyCell = HvGetCell (&HiveToConnect->Hive, NewKey->KeyCellOffset);
+       return TRUE;
 }
 
-
-LONG
-RegEnumValue(HKEY Key,
-            ULONG Index,
-            PCHAR ValueName,
-            PULONG NameSize,
-            PULONG Type,
-            PCHAR Data,
-            PULONG DataSize)
+static BOOL
+MyExportBinaryHive (PCHAR FileName,
+                 PEREGISTRY_HIVE RootHive)
 {
-  PLIST_ENTRY Ptr;
-  PVALUE Value;
-  ULONG Count = 0;
+       FILE *File;
+       BOOL ret;
 
-  if (Key->Data != NULL)
-    {
-      if (Index > 0)
+       /* Create new hive file */
+       File = fopen (FileName, "w+b");
+       if (File == NULL)
        {
-         Index--;
+               printf("    Error creating/opening file\n");
+               return FALSE;
        }
-      else
-       {
-         /* enumerate default value */
-         if (ValueName != NULL)
-           *ValueName = 0;
-         if (Type != NULL)
-           *Type = Key->DataType;
-         if (DataSize != NULL)
-           *DataSize = Key->DataSize;
-
-         /* FIXME: return more values */
-       }
-    }
-
-  Ptr = Key->ValueList.Flink;
-  while (Ptr != &Key->ValueList)
-    {
-      if (Index == Count)
-       break;
-
-      Count++;
-      Ptr = Ptr->Flink;
-    }
 
-  if (Ptr == &Key->ValueList)
-    return(ERROR_NO_MORE_ITEMS);
+       fseek (File, 0, SEEK_SET);
 
-  Value = CONTAINING_RECORD(Ptr,
-                           VALUE,
-                           ValueList);
-
-  /* FIXME: return values */
-
-  return(ERROR_SUCCESS);
+       RootHive->HiveHandle = (HANDLE)File;
+       ret = HvWriteHive(&RootHive->Hive);
+       fclose (File);
+       return ret;
 }
 
+LIST_ENTRY CmiHiveListHead;
 
-USHORT
-RegGetSubKeyCount (HKEY Key)
+VOID
+RegInitializeRegistry(VOID)
 {
-  return Key->SubKeyCount;
-}
+       UNICODE_STRING RootKeyName = RTL_CONSTANT_STRING(L"\\");
+       NTSTATUS Status;
+       HKEY ControlSetKey, LinkKey;
 
+       InitializeListHead(&CmiHiveListHead);
 
-ULONG
-RegGetValueCount (HKEY Key)
-{
-  if (Key->DataSize != 0)
-    return Key->ValueCount + 1;
+       Status = CmiInitializeTempHive(&RootHive);
+       if (!NT_SUCCESS(Status))
+       {
+               DPRINT1("CmiInitializeTempHive() failed with status 0x%08lx\n", Status);
+               return;
+       }
 
-  return Key->ValueCount;
+       RootKey = CreateInMemoryStructure(
+               &RootHive,
+               RootHive.Hive.HiveHeader->RootCell,
+               &RootKeyName);
+
+       /* Create DEFAULT key */
+       ConnectRegistry(
+               NULL,
+               &DefaultHive,
+               L"Registry\\User\\.DEFAULT");
+
+       /* Create SAM key */
+       ConnectRegistry(
+               NULL,
+               &SamHive,
+               L"Registry\\Machine\\SAM");
+
+       /* Create SECURITY key */
+       ConnectRegistry(
+               NULL,
+               &SecurityHive,
+               L"Registry\\Machine\\SECURITY");
+
+       /* Create SOFTWARE key */
+       ConnectRegistry(
+               NULL,
+               &SoftwareHive,
+               L"Registry\\Machine\\SOFTWARE");
+
+       /* Create SYSTEM key */
+       ConnectRegistry(
+               NULL,
+               &SystemHive,
+               L"Registry\\Machine\\SYSTEM");
+
+       /* Create link 'CurrentControlSet' --> 'ControlSet001' */
+       RegCreateKeyW(
+               NULL,
+               L"Registry\\Machine\\SYSTEM\\ControlSet001",
+               &ControlSetKey);
+       RegCreateKeyW(
+               NULL,
+               L"Registry\\Machine\\SYSTEM\\CurrentControlSet",
+               &LinkKey);
+       printf("ControlSetKey %p\n", ControlSetKey);
+       RegSetValueExW(LinkKey, NULL, 0, REG_LINK, (PCHAR)&ControlSetKey, sizeof(PVOID));
 }
 
 /* EOF */
index 4aed672..a957ccc 100644 (file)
@@ -1,41 +1,25 @@
-/*
- *  ReactOS kernel
- *  Copyright (C) 2003 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
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-/* $Id$
- * COPYRIGHT:       See COPYING in the top level directory
+/* COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS hive maker
  * FILE:            tools/mkhive/registry.h
  * PURPOSE:         Registry code
- * PROGRAMMER:      Eric Kohl
  */
 
 #ifndef __REGISTRY_H__
 #define __REGISTRY_H__
 
-
-#define INVALID_HANDLE_VALUE  NULL
-
-typedef struct _LIST_ENTRY
+typedef struct _REG_VALUE
 {
-  struct _LIST_ENTRY *Flink;
-  struct _LIST_ENTRY *Blink;
-} LIST_ENTRY, *PLIST_ENTRY;
+  LIST_ENTRY ValueList;
 
+  /* value name */
+  ULONG NameSize;
+  PCHAR Name;
+
+  /* value data */
+  ULONG DataType;
+  ULONG DataSize;
+  PCHAR Data;
+} VALUE, *PVALUE;
 
 typedef struct _REG_KEY
 {
@@ -43,36 +27,37 @@ typedef struct _REG_KEY
   LIST_ENTRY SubKeyList;
   LIST_ENTRY ValueList;
 
-  USHORT SubKeyCount;
+  ULONG SubKeyCount;
   ULONG ValueCount;
 
-  USHORT NameSize;
-  PCHAR Name;
+  ULONG NameSize;
+  PWCHAR Name;
 
   /* default data */
   ULONG DataType;
   ULONG DataSize;
   PCHAR Data;
-} KEY, *HKEY, **PHKEY;
 
+  /* Information on hard disk structure */
+  HCELL_INDEX KeyCellOffset;
+  PCM_KEY_NODE KeyCell;
+  PEREGISTRY_HIVE RegistryHive;
 
-typedef struct _REG_VALUE
-{
-  LIST_ENTRY ValueList;
+  /* Used when linking to another key */
+  struct _REG_KEY* LinkedKey;
+} KEY, *FRLDRHKEY, **PFRLDRHKEY, *MEMKEY, **PMEMKEY;
 
-  /* value name */
-  ULONG NameSize;
-  PCHAR Name;
-
-  /* value data */
-  ULONG DataType;
-  ULONG DataSize;
-  PCHAR Data;
-} VALUE, *PVALUE;
+#define HKEY_TO_MEMKEY(hKey) ((MEMKEY)(hKey))
+#define MEMKEY_TO_HKEY(memKey) ((HKEY)(memKey))
 
+extern EREGISTRY_HIVE DefaultHive;  /* \Registry\User\.DEFAULT */
+extern EREGISTRY_HIVE SamHive;      /* \Registry\Machine\SAM */
+extern EREGISTRY_HIVE SecurityHive; /* \Registry\Machine\SECURITY */
+extern EREGISTRY_HIVE SoftwareHive; /* \Registry\Machine\SOFTWARE */
+extern EREGISTRY_HIVE SystemHive;   /* \Registry\Machine\SYSTEM */
 
 #define ERROR_SUCCESS                    0L
-#define ERROR_PATH_NOT_FOUND             2L
+#define ERROR_UNSUCCESSFUL               1L
 #define ERROR_OUTOFMEMORY                14L
 #define ERROR_INVALID_PARAMETER          87L
 #define ERROR_MORE_DATA                  234L
@@ -155,22 +140,6 @@ typedef struct _REG_VALUE
        assert((ListEntry)->Flink->Blink == (ListEntry)); \
 }
 
-/*
- * BOOLEAN
- * IsListEmpty (
- *     PLIST_ENTRY     ListHead
- *     );
- *
- * FUNCTION:
- *     Checks if a double linked list is empty
- *
- * ARGUMENTS:
- *     ListHead = Head of the list
-*/
-#define IsListEmpty(ListHead) \
-       ((ListHead)->Flink == (ListHead))
-
-
 /*
  *VOID
  *RemoveEntryList (
@@ -200,11 +169,6 @@ typedef struct _REG_VALUE
        (ListEntry)->Blink = NULL; \
 }
 
-/*
- * PURPOSE: Returns the byte offset of a field within a structure
- */
-#define FIELD_OFFSET(Type,Field) (LONG)(&(((Type *)(0))->Field))
-
 /*
  * PURPOSE: Returns the base address structure if the caller knows the 
  * address of a field within the structure
@@ -230,58 +194,42 @@ typedef struct _REG_VALUE
 #define REG_FULL_RESOURCE_DESCRIPTOR 9
 #define REG_RESOURCE_REQUIREMENTS_LIST 10
 
-
-
-VOID
-RegInitializeRegistry(VOID);
-
-LONG
-RegCreateKey(HKEY ParentKey,
-            PCHAR KeyName,
-            PHKEY Key);
-
-LONG
-RegDeleteKey(HKEY Key,
-            PCHAR Name);
-
-LONG
-RegEnumKey(HKEY Key,
-          ULONG Index,
-          PCHAR Name,
-          PULONG NameSize);
-
-LONG
-RegOpenKey(HKEY ParentKey,
-          PCHAR KeyName,
-          PHKEY Key);
-
-
-LONG
-RegSetValue(HKEY Key,
-           PCHAR ValueName,
-           ULONG Type,
-           PCHAR Data,
-           ULONG DataSize);
-
-LONG
-RegQueryValue(HKEY Key,
-             PCHAR ValueName,
+LONG WINAPI
+RegCreateKeyA(
+       IN HKEY hKey,
+       IN LPCSTR lpSubKey,
+       OUT PHKEY phkResult);
+
+LONG WINAPI
+RegOpenKeyA(
+       IN HKEY hKey,
+       IN LPCSTR lpSubKey,
+       OUT PHKEY phkResult);
+
+LONG WINAPI
+RegQueryValueExA(HKEY Key,
+             LPCSTR ValueName,
+             PULONG Reserved,
              PULONG Type,
-             PCHAR Data,
-             PULONG DataSize);
-
-LONG
-RegDeleteValue(HKEY Key,
-              PCHAR ValueName);
-
-LONG
-RegEnumValue(HKEY Key,
-            ULONG Index,
-            PCHAR ValueName,
-            PULONG NameSize,
-            PULONG Type,
-            PCHAR Data,
-            PULONG DataSize);
+             PUCHAR Data,
+             PSIZE_T DataSize);
+
+LONG WINAPI
+RegSetValueExA(
+       IN HKEY hKey,
+       IN LPCSTR lpValueName OPTIONAL,
+       ULONG Reserved,
+       IN ULONG dwType,
+       IN const PUCHAR lpData,
+       IN ULONG cbData);
+
+LONG WINAPI
+RegDeleteValueA(HKEY Key,
+              LPCSTR ValueName);
+
+LONG WINAPI
+RegDeleteKeyA(HKEY Key,
+            LPCSTR Name);
 
 USHORT
 RegGetSubKeyCount (HKEY Key);
@@ -289,16 +237,8 @@ RegGetSubKeyCount (HKEY Key);
 ULONG
 RegGetValueCount (HKEY Key);
 
-
-#if 0
-BOOL
-RegImportTextHive(PCHAR ChunkBase,
-                 U32 ChunkSize);
-
-BOOL
-RegImportBinaryHive(PCHAR ChunkBase,
-                   U32 ChunkSize);
-#endif
+VOID
+RegInitializeRegistry(VOID);
 
 #endif /* __REGISTRY_H__ */
 
diff --git a/reactos/tools/mkhive/rtl.c b/reactos/tools/mkhive/rtl.c
new file mode 100644 (file)
index 0000000..4ff2be3
--- /dev/null
@@ -0,0 +1,143 @@
+/* COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS hive maker
+ * FILE:            tools/mkhive/rtl.c
+ * PURPOSE:         Runtime Library
+ */
+
+#define RTL_H
+
+#define NTOS_MODE_USER
+#define WIN32_NO_STATUS
+#include <ntddk.h>
+#include <bitmap.c>
+
+/*
+ * @implemented
+ *
+ * NOTES
+ *  If source is NULL the length of source is assumed to be 0.
+ */
+VOID NTAPI
+RtlInitAnsiString(
+       IN OUT PANSI_STRING DestinationString,
+       IN PCSTR SourceString)
+{
+       SIZE_T DestSize;
+
+       if(SourceString)
+       {
+               DestSize = strlen(SourceString);
+               DestinationString->Length = (USHORT)DestSize;
+               DestinationString->MaximumLength = (USHORT)DestSize + sizeof(CHAR);
+       }
+       else
+       {
+               DestinationString->Length = 0;
+               DestinationString->MaximumLength = 0;
+       }
+
+       DestinationString->Buffer = (PCHAR)SourceString;
+}
+
+/*
+ * @implemented
+ *
+ * NOTES
+ *  If source is NULL the length of source is assumed to be 0.
+ */
+VOID NTAPI
+RtlInitUnicodeString(
+       IN OUT PUNICODE_STRING DestinationString,
+       IN PCWSTR SourceString)
+{
+       SIZE_T DestSize;
+
+       if(SourceString)
+       {
+               DestSize = wcslen(SourceString) * sizeof(WCHAR);
+               DestinationString->Length = (USHORT)DestSize;
+               DestinationString->MaximumLength = (USHORT)DestSize + sizeof(WCHAR);
+       }
+       else
+       {
+               DestinationString->Length = 0;
+               DestinationString->MaximumLength = 0;
+       }
+
+       DestinationString->Buffer = (PWCHAR)SourceString;
+}
+
+NTSTATUS NTAPI
+RtlAnsiStringToUnicodeString(
+       IN OUT PUNICODE_STRING UniDest,
+       IN PANSI_STRING AnsiSource,
+       IN BOOLEAN AllocateDestinationString)
+{
+       ULONG Length;
+       PUCHAR WideString;
+       USHORT i;
+
+       Length = AnsiSource->Length * sizeof(WCHAR);
+       if (Length > MAXUSHORT) return STATUS_INVALID_PARAMETER_2;
+       UniDest->Length = (USHORT)Length;
+
+       if (AllocateDestinationString)
+       {
+               UniDest->MaximumLength = (USHORT)Length + sizeof(WCHAR);
+               UniDest->Buffer = malloc(UniDest->MaximumLength);
+               if (!UniDest->Buffer)
+                       return STATUS_NO_MEMORY;
+       }
+       else if (UniDest->Length >= UniDest->MaximumLength)
+       {
+               return STATUS_BUFFER_OVERFLOW;
+       }
+
+       WideString = (PUCHAR)UniDest->Buffer;
+       for (i = 0; i <= AnsiSource->Length; i++)
+       {
+               WideString[2 * i + 0] = AnsiSource->Buffer[i];
+               WideString[2 * i + 1] = 0;
+       }
+       return STATUS_SUCCESS;
+}
+
+WCHAR NTAPI
+RtlUpcaseUnicodeChar(
+       IN WCHAR Source)
+{
+       USHORT Offset;
+
+       if (Source < 'a')
+               return Source;
+
+       if (Source <= 'z')
+               return (Source - ('a' - 'A'));
+
+       Offset = 0;
+
+       return Source + (SHORT)Offset;
+}
+
+VOID NTAPI
+KeQuerySystemTime(
+       OUT PLARGE_INTEGER CurrentTime)
+{
+       DPRINT1("KeQuerySystemTime() unimplemented\n");
+}
+
+PVOID NTAPI
+ExAllocatePool(
+       IN POOL_TYPE PoolType,
+       IN SIZE_T NumberOfBytes)
+{
+       return malloc(NumberOfBytes);
+}
+
+VOID NTAPI
+ExFreePool(
+       IN PVOID p)
+{
+       free(p);
+}
+