/*
* ReactOS kernel
- * Copyright (C) 2003 ReactOS Team
+ * Copyright (C) 2003, 2004 ReactOS Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/* $Id: binhive.c,v 1.6 2003/10/10 21:53:47 ekohl Exp $
+/* $Id$
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS hive maker
* FILE: tools/mkhive/binhive.c
//#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
+#include <string.h>
#include "mkhive.h"
#include "binhive.h"
#define REG_EXTEND_HASH_TABLE_SIZE 4
#define REG_VALUE_LIST_CELL_MULTIPLE 4
-#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
-#define ROUND_DOWN(N, S) ((N) - ((N) % (S)))
+#define ROUND_UP_POW2(N,S) (((N) + (S) - 1) & ~((S) - 1))
+#define ROUND_DOWN_POW2(N,S) ((N) & ~((S) - 1))
#define ABS_VALUE(V) (((V) < 0) ? -(V) : (V))
// BLOCK_OFFSET = offset in file after header block
typedef ULONG BLOCK_OFFSET, *PBLOCK_OFFSET;
+#ifdef _MSC_VER
+typedef unsigned __int64 FILETIME;
+#else
typedef unsigned long long FILETIME;
+#endif
+
+#ifdef _MSC_VER
+#pragma pack ( push, hive_header, 1 )
+#endif//_MSC_VER
/* header for registry hive file : */
typedef struct _HIVE_HEADER
/* When this hive file was last modified */
FILETIME DateModified;
- /* Registry format version ? (1?) */
- ULONG Unused3;
+ /* Registry format major version (1) */
+ ULONG MajorVersion;
- /* Registry format version ? (3?) */
- ULONG Unused4;
+ /* Registry format minor version (3)
+ Version 3 added fast indexes, version 5 has large value optimizations */
+ ULONG MinorVersion;
- /* Registry format version ? (0?) */
- ULONG Unused5;
+ /* Registry file type (0 - Primary, 1 - Log) */
+ ULONG Type;
- /* Registry format version ? (1?) */
- ULONG Unused6;
+ /* Registry format (1 is the only defined value so far) */
+ ULONG Format;
/* Offset into file from the byte after the end of the base block.
If the hive is volatile, this is the actual pointer to the KEY_CELL */
ULONG Unused7;
/* Name of hive file */
- WCHAR FileName[64];
+ WCHAR FileName[48];
- /* ? */
- ULONG Unused8[83];
+ ULONG Reserved[99];
/* Checksum of first 0x200 bytes */
ULONG Checksum;
-} __attribute__((packed)) HIVE_HEADER, *PHIVE_HEADER;
+} GCC_PACKED HIVE_HEADER, *PHIVE_HEADER;
typedef struct _HBIN
{
/* Bin identifier "hbin" (0x6E696268) */
- ULONG BlockId;
+ ULONG HeaderId;
/* Block offset of this bin */
- BLOCK_OFFSET BlockOffset;
+ BLOCK_OFFSET BinOffset;
/* Size in bytes, multiple of the block size (4KB) */
- ULONG BlockSize;
+ ULONG BinSize;
- /* ? */
- ULONG Unused1;
+ ULONG Reserved[2];
/* When this bin was last modified */
FILETIME DateModified;
- /* ? */
- ULONG Unused2;
-} __attribute__((packed)) HBIN, *PHBIN;
+ /* ? (In-memory only) */
+ ULONG MemAlloc;
+} GCC_PACKED HBIN, *PHBIN;
typedef struct _CELL_HEADER
{
/* <0 if used, >0 if free */
LONG CellSize;
-} __attribute__((packed)) CELL_HEADER, *PCELL_HEADER;
+} GCC_PACKED CELL_HEADER, *PCELL_HEADER;
typedef struct _KEY_CELL
{
USHORT ClassSize;
/* Name of key (not zero terminated) */
- UCHAR Name[0];
-} __attribute__((packed)) KEY_CELL, *PKEY_CELL;
+ CHAR Name[0];
+} GCC_PACKED KEY_CELL, *PKEY_CELL;
/* KEY_CELL.Type constants */
#define REG_LINK_KEY_CELL_TYPE 0x10
{
BLOCK_OFFSET KeyOffset;
ULONG HashValue;
-} __attribute__((packed)) HASH_RECORD, *PHASH_RECORD;
+} GCC_PACKED HASH_RECORD, *PHASH_RECORD;
typedef struct _HASH_TABLE_CELL
{
USHORT Id;
USHORT HashTableSize;
HASH_RECORD Table[0];
-} __attribute__((packed)) HASH_TABLE_CELL, *PHASH_TABLE_CELL;
+} GCC_PACKED HASH_TABLE_CELL, *PHASH_TABLE_CELL;
typedef struct _VALUE_LIST_CELL
{
LONG CellSize;
BLOCK_OFFSET ValueOffset[0];
-} __attribute__((packed)) VALUE_LIST_CELL, *PVALUE_LIST_CELL;
+} GCC_PACKED VALUE_LIST_CELL, *PVALUE_LIST_CELL;
typedef struct _VALUE_CELL
{
ULONG DataType;
USHORT Flags;
USHORT Unused1;
- UCHAR Name[0]; /* warning : not zero terminated */
-} __attribute__((packed)) VALUE_CELL, *PVALUE_CELL;
+ CHAR Name[0]; /* warning : not zero terminated */
+} GCC_PACKED VALUE_CELL, *PVALUE_CELL;
/* VALUE_CELL.Flags constants */
#define REG_VALUE_NAME_PACKED 0x0001
typedef struct _DATA_CELL
{
LONG CellSize;
- UCHAR Data[0];
-} __attribute__((packed)) DATA_CELL, *PDATA_CELL;
+ CHAR Data[0];
+} GCC_PACKED DATA_CELL, *PDATA_CELL;
+
+#ifdef _MSC_VER
+#pragma pack ( pop, hive_header )
+#endif//_MSC_VER
typedef struct _REGISTRY_HIVE
{
/* FUNCTIONS ****************************************************************/
static VOID
-CmiCreateDefaultHiveHeader(PHIVE_HEADER Header)
+memexpand (PWCHAR Dst,
+ PCHAR Src,
+ ULONG Length)
{
- assert(Header);
+ 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 = 0ULL;
- Header->Unused3 = 1;
- Header->Unused4 = 3;
- Header->Unused5 = 0;
- Header->Unused6 = 1;
+ Header->DateModified = 0;
+ Header->MajorVersion = 1;
+ Header->MinorVersion = 3;
+ Header->Type = 0;
+ Header->Format = 1;
Header->Unused7 = 1;
Header->RootKeyOffset = -1;
Header->BlockSize = REG_BLOCK_SIZE;
- Header->Unused6 = 1;
Header->Checksum = 0;
}
static VOID
CmiCreateDefaultBinCell(PHBIN BinCell)
{
- assert(BinCell);
+ assert (BinCell);
memset (BinCell, 0, REG_BLOCK_SIZE);
- BinCell->BlockId = REG_BIN_ID;
- BinCell->DateModified = 0ULL;
- BinCell->BlockSize = REG_BLOCK_SIZE;
+ BinCell->HeaderId = REG_BIN_ID;
+ BinCell->DateModified = 0;
+ BinCell->BinSize = REG_BLOCK_SIZE;
}
static VOID
-CmiCreateDefaultRootKeyCell(PKEY_CELL RootKeyCell)
+CmiCreateDefaultRootKeyCell(PKEY_CELL RootKeyCell, PCHAR KeyName)
{
- assert(RootKeyCell);
- memset (RootKeyCell, 0, sizeof(KEY_CELL));
- RootKeyCell->CellSize = -sizeof(KEY_CELL);
+ PCHAR BaseKeyName;
+ USHORT NameSize;
+ ULONG CellSize;
+
+ assert (RootKeyCell);
+
+ BaseKeyName = strrchr(KeyName, '\\') + 1;
+ NameSize = strlen(BaseKeyName);
+ CellSize = ROUND_UP_POW2(sizeof(KEY_CELL) + NameSize - 1, 16);
+
+ memset (RootKeyCell, 0, CellSize);
+ RootKeyCell->CellSize = (ULONG)-(LONG)CellSize;
RootKeyCell->Id = REG_KEY_CELL_ID;
RootKeyCell->Type = REG_ROOT_KEY_CELL_TYPE;
- RootKeyCell->LastWriteTime = 0ULL;
+ RootKeyCell->LastWriteTime = 0;
RootKeyCell->ParentKeyOffset = 0;
RootKeyCell->NumberOfSubKeys = 0;
RootKeyCell->HashTableOffset = -1;
RootKeyCell->ValueListOffset = -1;
RootKeyCell->SecurityKeyOffset = 0;
RootKeyCell->ClassNameOffset = -1;
- RootKeyCell->NameSize = 0;
+ RootKeyCell->NameSize = NameSize;
RootKeyCell->ClassSize = 0;
+ memcpy (RootKeyCell->Name,
+ BaseKeyName,
+ NameSize);
}
static PREGISTRY_HIVE
-CmiCreateRegistryHive (VOID)
+CmiCreateRegistryHive (PCHAR KeyName)
{
PREGISTRY_HIVE Hive;
PCELL_HEADER FreeCell;
}
memset (Hive, 0, sizeof(REGISTRY_HIVE));
- DPRINT("Hive %x\n", Hive);
+ DPRINT("Hive %p\n", Hive);
/* Create hive beader (aka 'base block') */
Hive->HiveHeader = (PHIVE_HEADER) malloc (REG_BLOCK_SIZE);
free (Hive);
return NULL;
}
- CmiCreateDefaultHiveHeader(Hive->HiveHeader);
+ CmiCreateDefaultHiveHeader (Hive->HiveHeader);
Hive->FileSize = REG_BLOCK_SIZE;
/* Allocate block list */
/* Init first bin */
BinCell = (PHBIN)Hive->BlockList[0];
- CmiCreateDefaultBinCell(BinCell);
- BinCell->BlockOffset = 0;
+ CmiCreateDefaultBinCell (BinCell);
+ BinCell->BinOffset = 0;
/* Init root key cell */
RootKeyCell = (PKEY_CELL)((ULONG_PTR)BinCell + REG_HBIN_DATA_OFFSET);
- CmiCreateDefaultRootKeyCell(RootKeyCell);
+ CmiCreateDefaultRootKeyCell (RootKeyCell, KeyName);
Hive->HiveHeader->RootKeyOffset = REG_HBIN_DATA_OFFSET;
/* Init free cell */
- FreeCell = (PCELL_HEADER)((ULONG_PTR)RootKeyCell + sizeof(KEY_CELL));
- FreeCell->CellSize = REG_BLOCK_SIZE - (REG_HBIN_DATA_OFFSET + sizeof(KEY_CELL));
+ FreeCell = (PCELL_HEADER)((ULONG_PTR)RootKeyCell - RootKeyCell->CellSize);
+ FreeCell->CellSize = REG_BLOCK_SIZE - (REG_HBIN_DATA_OFFSET - RootKeyCell->CellSize);
Hive->FreeList[0] = FreeCell;
- Hive->FreeListOffset[0] = REG_HBIN_DATA_OFFSET + sizeof(KEY_CELL);
+ Hive->FreeListOffset[0] = REG_HBIN_DATA_OFFSET - RootKeyCell->CellSize;
Hive->FreeListSize++;
return Hive;
Bin = Hive->BlockList[i];
DPRINT ("Bin[%lu]: Offset 0x%lx Size 0x%lx\n",
- i, Bin->BlockOffset, Bin->BlockSize);
+ i, Bin->BinOffset, Bin->BinSize);
free (Bin);
}
if (ppBin)
*ppBin = pBin;
- return (PVOID)((ULONG_PTR)pBin + (BlockOffset - pBin->BlockOffset));
+ return (PVOID)((ULONG_PTR)pBin + (BlockOffset - pBin->BinOffset));
}
PHBIN Bin;
ULONG i;
- DPRINT("CmiMergeFree(Block %lx Offset %lx Size %lx) called\n",
+ DPRINT("CmiMergeFree(Block %p Offset %lx Size %lx) called\n",
FreeBlock, FreeOffset, FreeBlock->CellSize);
CmiGetCell (RegistryHive,
if (Bin == NULL)
return FALSE;
- BinOffset = Bin->BlockOffset;
- BinSize = Bin->BlockSize;
+ BinOffset = Bin->BinOffset;
+ BinSize = Bin->BinSize;
DPRINT("Bin %p Offset %lx Size %lx\n", Bin, BinOffset, BinSize);
for (i = 0; i < RegistryHive->FreeListSize; i++)
assert(RegistryHive);
assert(FreeBlock);
- DPRINT("FreeBlock %.08lx FreeOffset %.08lx\n",
+ DPRINT("FreeBlock %p FreeOffset %.08lx\n",
FreeBlock, FreeOffset);
/* Merge free blocks */
static BOOL
CmiAddBin(PREGISTRY_HIVE RegistryHive,
+ ULONG BlockCount,
PVOID *NewBlock,
PBLOCK_OFFSET NewBlockOffset)
{
PCELL_HEADER tmpBlock;
PHBIN * tmpBlockList;
PHBIN tmpBin;
+ ULONG BinSize;
+ ULONG i;
- tmpBin = malloc (REG_BLOCK_SIZE);
+ BinSize = BlockCount *REG_BLOCK_SIZE;
+ tmpBin = malloc (BinSize);
if (tmpBin == NULL)
{
return FALSE;
}
- memset (tmpBin, 0, REG_BLOCK_SIZE);
+ memset (tmpBin, 0, BinSize);
- tmpBin->BlockId = REG_BIN_ID;
- tmpBin->BlockOffset = RegistryHive->FileSize - REG_BLOCK_SIZE;
- RegistryHive->FileSize += REG_BLOCK_SIZE;
- tmpBin->BlockSize = REG_BLOCK_SIZE;
- tmpBin->Unused1 = 0;
- tmpBin->DateModified = 0ULL;
- tmpBin->Unused2 = 0;
+ tmpBin->HeaderId = REG_BIN_ID;
+ tmpBin->BinOffset = RegistryHive->FileSize - REG_BLOCK_SIZE;
+ RegistryHive->FileSize += BinSize;
+ tmpBin->BinSize = BinSize;
+ tmpBin->DateModified = 0;
+ tmpBin->MemAlloc = 0;
/* Increase size of list of blocks */
- tmpBlockList = malloc (sizeof(PHBIN) * (RegistryHive->BlockListSize + 1));
+ tmpBlockList = malloc (sizeof(PHBIN) * (RegistryHive->BlockListSize + BlockCount));
if (tmpBlockList == NULL)
{
free (tmpBin);
}
RegistryHive->BlockList = tmpBlockList;
- RegistryHive->BlockList[RegistryHive->BlockListSize++] = tmpBin;
+ for (i = 0; i < BlockCount; i++)
+ RegistryHive->BlockList[RegistryHive->BlockListSize + i] = tmpBin;
+ RegistryHive->BlockListSize += BlockCount;
/* Initialize a free block in this heap : */
tmpBlock = (PCELL_HEADER)((ULONG_PTR) tmpBin + REG_HBIN_DATA_OFFSET);
*NewBlock = (PVOID) tmpBlock;
if (NewBlockOffset)
- *NewBlockOffset = tmpBin->BlockOffset + REG_HBIN_DATA_OFFSET;
+ *NewBlockOffset = tmpBin->BinOffset + REG_HBIN_DATA_OFFSET;
return TRUE;
}
static BOOL
CmiAllocateCell (PREGISTRY_HIVE RegistryHive,
+ LONG CellSize,
PVOID *Block,
- LONG BlockSize,
PBLOCK_OFFSET pBlockOffset)
{
PCELL_HEADER NewBlock;
- PHBIN pBin;
ULONG i;
*Block = NULL;
/* Round to 16 bytes multiple */
- BlockSize = (BlockSize + sizeof(ULONG) + 15) & 0xfffffff0;
+ CellSize = ROUND_UP_POW2(CellSize, 16);
/* first search in free blocks */
NewBlock = NULL;
for (i = 0; i < RegistryHive->FreeListSize; i++)
{
- if (RegistryHive->FreeList[i]->CellSize >= BlockSize)
+ if (RegistryHive->FreeList[i]->CellSize >= CellSize)
{
NewBlock = RegistryHive->FreeList[i];
if (pBlockOffset)
if (NewBlock == NULL)
{
/* Add a new block */
- if (!CmiAddBin(RegistryHive, (PVOID *)&NewBlock , pBlockOffset))
+ if (!CmiAddBin(RegistryHive,
+ ((sizeof(HBIN) + CellSize - 1) / REG_BLOCK_SIZE) + 1,
+ (PVOID *)&NewBlock,
+ pBlockOffset))
return FALSE;
}
*Block = NewBlock;
/* Split the block in two parts */
- if (NewBlock->CellSize > BlockSize)
+ if (NewBlock->CellSize > CellSize)
{
- NewBlock = (PCELL_HEADER) ((ULONG_PTR) NewBlock+BlockSize);
- NewBlock->CellSize = ((PCELL_HEADER) (*Block))->CellSize - BlockSize;
+ NewBlock = (PCELL_HEADER) ((ULONG_PTR) NewBlock + CellSize);
+ NewBlock->CellSize = ((PCELL_HEADER) (*Block))->CellSize - CellSize;
+ ((PCELL_HEADER) (*Block))->CellSize = CellSize;
CmiAddFree (RegistryHive,
NewBlock,
- *pBlockOffset + BlockSize,
+ *pBlockOffset + CellSize,
TRUE);
}
- else if (NewBlock->CellSize < BlockSize)
+ else if (NewBlock->CellSize < CellSize)
{
return FALSE;
}
- memset(*Block, 0, BlockSize);
- ((PCELL_HEADER)(*Block))->CellSize = -BlockSize;
+ memset(*Block, 0, CellSize);
+ ((PCELL_HEADER)(*Block))->CellSize *= -1;
return TRUE;
}
static BOOL
CmiAllocateHashTableCell (PREGISTRY_HIVE Hive,
PBLOCK_OFFSET HBOffset,
- ULONG SubKeyCount)
+ USHORT SubKeyCount)
{
PHASH_TABLE_CELL HashCell;
ULONG NewHashSize;
BOOL Status;
- NewHashSize = ROUND_UP(sizeof(HASH_TABLE_CELL) +
- (SubKeyCount - 1) * sizeof(HASH_RECORD),
- 0x10);
+ NewHashSize = sizeof(HASH_TABLE_CELL) +
+ (SubKeyCount * sizeof(HASH_RECORD));
Status = CmiAllocateCell (Hive,
- (PVOID*) &HashCell,
NewHashSize,
+ (PVOID*) &HashCell,
HBOffset);
if ((HashCell == NULL) || (Status == FALSE))
{
ULONG ValueListSize;
BOOL Status;
- ValueListSize = ROUND_UP (ValueCount * sizeof(BLOCK_OFFSET),
- 0x10);
+ ValueListSize = sizeof(VALUE_LIST_CELL) +
+ (ValueCount * sizeof(BLOCK_OFFSET));
Status = CmiAllocateCell (Hive,
- (PVOID)&ValueListCell,
ValueListSize,
+ (PVOID)&ValueListCell,
ValueListOffset);
if ((ValueListCell == NULL) || (Status == FALSE))
{
PCHAR ValueName)
{
PVALUE_CELL NewValueCell;
- ULONG NameSize;
+ USHORT NameSize;
BOOL Status;
NameSize = (ValueName == NULL) ? 0 : strlen (ValueName);
Status = CmiAllocateCell (Hive,
- (PVOID*)&NewValueCell,
sizeof(VALUE_CELL) + NameSize,
+ (PVOID*)&NewValueCell,
ValueCellOffset);
if ((NewValueCell == NULL) || (Status == FALSE))
{
}
-static VOID
-memexpand (PWCHAR Dst,
- PCHAR Src,
- ULONG Length)
-{
- ULONG i;
-
- for (i = 0; i < Length; i++)
- Dst[i] = (WCHAR)Src[i];
-}
-
-
static BOOL
CmiExportValue (PREGISTRY_HIVE Hive,
BLOCK_OFFSET KeyCellOffset,
ULONG SrcDataSize;
ULONG DstDataSize;
ULONG DataType;
- PUCHAR Data;
+ PCHAR Data;
BOOL Expand = FALSE;
DPRINT ("CmiExportValue('%s') called\n", (Value == NULL) ? "<default>" : (PCHAR)Value->Name);
}
else
{
+ /* Allocate data cell */
if (!CmiAllocateCell (Hive,
+ sizeof(CELL_HEADER) + DstDataSize,
(PVOID *)&DataCell,
- DstDataSize,
&DataCellOffset))
{
return FALSE;
BLOCK_OFFSET NKBOffset;
PKEY_CELL NewKeyCell;
ULONG KeyCellSize;
- ULONG SubKeyCount;
+ USHORT SubKeyCount;
ULONG ValueCount;
PLIST_ENTRY Entry;
HKEY SubKey;
/* Allocate key cell */
KeyCellSize = sizeof(KEY_CELL) + Key->NameSize - 1;
- if (!CmiAllocateCell (Hive, (PVOID)&NewKeyCell, KeyCellSize, &NKBOffset))
+ 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 = 0ULL;
+ NewKeyCell->LastWriteTime = 0;
NewKeyCell->ParentKeyOffset = ParentKeyOffset;
NewKeyCell->NumberOfSubKeys = 0;
NewKeyCell->HashTableOffset = -1;
{
PKEY_CELL KeyCell;
HKEY Key;
- ULONG i;
- ULONG SubKeyCount;
+ USHORT SubKeyCount;
ULONG ValueCount;
PLIST_ENTRY Entry;
HKEY SubKey;
NULL);
if (KeyCell == NULL)
{
- DPRINT1 ("CmiGetBlock() failed\n");
+ DPRINT1 ("CmiGetCell() failed\n");
return FALSE;
}
File = fopen (FileName, "w+b");
if (File == NULL)
{
+ printf(" Error creating/opening file\n");
return FALSE;
}
Bin = Hive->BlockList[i];
DPRINT ("Bin[%lu]: Offset 0x%lx Size 0x%lx\n",
- i, Bin->BlockOffset, Bin->BlockSize);
+ i, Bin->BinOffset, Bin->BinSize);
- fwrite (Bin, Bin->BlockSize, 1, File);
+ fwrite (Bin, Bin->BinSize, 1, File);
}
}
printf (" Creating binary hive: %s\n", FileName);
- Hive = CmiCreateRegistryHive ();
+ Hive = CmiCreateRegistryHive (KeyName);
if (Hive == NULL)
return FALSE;