/*
* 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 */
/*
* 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__ */
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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);
/*
* 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>
#include <stdio.h>
#include "mkhive.h"
-#include "registry.h"
-#include "reginf.h"
-#include "binhive.h"
#ifdef _MSC_VER
#include <stdlib.h>
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;
}
/*
* 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))
#ifdef WIN32
#define strncasecmp strnicmp
-#define strcasecmp stricmp
+#define strcasecmp _stricmp
#endif//WIN32
#ifdef _MSC_VER
-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
/*
* 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
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);
if (Buffer == NULL)
return;
- Error = RegQueryValue (KeyHandle,
+ Error = RegQueryValueExA (KeyHandle,
ValueName,
NULL,
- (PCHAR)Buffer,
+ NULL,
+ (PUCHAR)Buffer,
&Size);
if (Error != ERROR_SUCCESS)
goto done;
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:
{
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);
}
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))
DPRINT("setting dword %s to %lx\n", ValueName, dw);
- RegSetValue (KeyHandle,
+ RegSetValueExA (KeyHandle,
ValueName,
+ 0,
Type,
- (PVOID)&dw,
+ (const PUCHAR)&dw,
sizeof(ULONG));
}
else
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);
InfHostGetBinaryField (Context, 5, Data, Size, NULL);
}
- RegSetValue (KeyHandle,
+ RegSetValueExA (KeyHandle,
ValueName,
+ 0,
Type,
(PVOID)Data,
- Size);
+ (ULONG)Size);
free (Data);
}
CHAR Buffer[MAX_INF_STRING_LENGTH];
PCHAR ValuePtr;
ULONG Flags;
- ULONG Length;
+ size_t Length;
PINFCONTEXT Context = NULL;
HKEY KeyHandle;
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 */
}
else
{
- if (RegCreateKey (NULL, Buffer, &KeyHandle) != ERROR_SUCCESS)
+ if (RegCreateKeyA (NULL, Buffer, &KeyHandle) != ERROR_SUCCESS)
{
DPRINT("RegCreateKey(%s) failed\n", Buffer);
continue;
BOOL
-ImportRegistryFile(PCHAR FileName,
- PCHAR Section,
- BOOL Delete)
+ImportRegistryFile(PCHAR FileName)
{
HINF hInf;
ULONG ErrorLine;
/*
* 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__ */
/*
* 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);
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 */
-/*
- * 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
{
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
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 (
(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
#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);
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__ */
--- /dev/null
+/* 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);
+}
+