Author: fireball
Date: Sat Jul 29 00:50:05 2006
New Revision: 23336
URL:
http://svn.reactos.org/svn/reactos?rev=23336&view=rev
Log:
Actually add cmlib itself
Added:
trunk/reactos/lib/cmlib/
trunk/reactos/lib/cmlib/cmdata.h
trunk/reactos/lib/cmlib/cminit.c
trunk/reactos/lib/cmlib/cmlib.h
trunk/reactos/lib/cmlib/cmlib.mak
trunk/reactos/lib/cmlib/cmlib.rbuild
trunk/reactos/lib/cmlib/hivebin.c
trunk/reactos/lib/cmlib/hivecell.c
trunk/reactos/lib/cmlib/hivedata.h
trunk/reactos/lib/cmlib/hiveinit.c
trunk/reactos/lib/cmlib/hivesum.c
trunk/reactos/lib/cmlib/hivewrt.c
Added: trunk/reactos/lib/cmlib/cmdata.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/cmlib/cmdata.h?rev=233…
==============================================================================
--- trunk/reactos/lib/cmlib/cmdata.h (added)
+++ trunk/reactos/lib/cmlib/cmdata.h Sat Jul 29 00:50:05 2006
@@ -1,0 +1,134 @@
+/*
+ * PROJECT: registry manipulation library
+ * LICENSE: GPL - See COPYING in the top level directory
+ * COPYRIGHT: Copyright 2005 Filip Navara <navaraf(a)reactos.org>
+ * Copyright 2001 - 2005 Eric Kohl
+ */
+
+#ifndef CMLIB_CMDATA_H
+#define CMLIB_CMDATA_H
+
+#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 REG_KEY_CELL_ID 0x6b6e
+#define REG_HASH_TABLE_CELL_ID 0x666c
+#define REG_VALUE_CELL_ID 0x6b76
+#define REG_SECURITY_CELL_ID 0x6b73
+
+#include <pshpack1.h>
+
+typedef struct _KEY_CELL
+{
+ /* Key cell identifier "kn" (0x6b6e) */
+ USHORT Id;
+
+ /* Flags */
+ USHORT Flags;
+
+ /* Time of last flush */
+ LARGE_INTEGER LastWriteTime;
+
+ /* ? */
+ ULONG UnUsed1;
+
+ /* Block offset of parent key cell */
+ HCELL_INDEX ParentKeyOffset;
+
+ /* Count of sub keys for the key in this key cell (stable & volatile) */
+ ULONG NumberOfSubKeys[HvMaxStorageType];
+
+ /* Block offset of has table for FIXME: subkeys/values? (stable & volatile) */
+ HCELL_INDEX HashTableOffset[HvMaxStorageType];
+
+ /* Count of values contained in this key cell */
+ ULONG NumberOfValues;
+
+ /* Block offset of VALUE_LIST_CELL */
+ HCELL_INDEX ValueListOffset;
+
+ /* Block offset of security cell */
+ HCELL_INDEX SecurityKeyOffset;
+
+ /* Block offset of registry key class */
+ HCELL_INDEX 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) */
+ UCHAR Name[0];
+} KEY_CELL, *PKEY_CELL;
+
+/* KEY_CELL.Flags constants */
+#define REG_KEY_VOLATILE_CELL 0x01
+#define REG_KEY_ROOT_CELL 0x0C
+#define REG_KEY_LINK_CELL 0x10
+#define REG_KEY_NAME_PACKED 0x20
+
+/*
+ * Hash record
+ *
+ * HashValue:
+ * packed name: four letters of value's name
+ * otherwise: Zero!
+ */
+typedef struct _HASH_RECORD
+{
+ HCELL_INDEX KeyOffset;
+ ULONG HashValue;
+} HASH_RECORD, *PHASH_RECORD;
+
+typedef struct _HASH_TABLE_CELL
+{
+ USHORT Id;
+ USHORT HashTableSize;
+ HASH_RECORD Table[0];
+} HASH_TABLE_CELL, *PHASH_TABLE_CELL;
+
+typedef struct _VALUE_LIST_CELL
+{
+ HCELL_INDEX ValueOffset[0];
+} VALUE_LIST_CELL, *PVALUE_LIST_CELL;
+
+typedef struct _VALUE_CELL
+{
+ USHORT Id; // "kv"
+ USHORT NameSize; // length of Name
+ ULONG DataSize; // length of datas in the cell pointed by DataOffset
+ HCELL_INDEX DataOffset;// datas are here if high bit of DataSize is set
+ ULONG DataType;
+ USHORT Flags;
+ USHORT Unused1;
+ UCHAR Name[0]; /* warning : not zero terminated */
+} 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 _SECURITY_CELL
+{
+ USHORT Id; // "sk"
+ USHORT Reserved;
+ HCELL_INDEX PrevSecurityCell;
+ HCELL_INDEX NextSecurityCell;
+ ULONG RefCount;
+ ULONG SdSize;
+ UCHAR Data[0];
+} SECURITY_CELL, *PSECURITY_CELL;
+
+#include <poppack.h>
+
+#endif /* CMLIB_CMDATA_H */
Added: trunk/reactos/lib/cmlib/cminit.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/cmlib/cminit.c?rev=233…
==============================================================================
--- trunk/reactos/lib/cmlib/cminit.c (added)
+++ trunk/reactos/lib/cmlib/cminit.c Sat Jul 29 00:50:05 2006
@@ -1,0 +1,82 @@
+/*
+ * PROJECT: registry manipulation library
+ * LICENSE: GPL - See COPYING in the top level directory
+ * COPYRIGHT: Copyright 2005 Filip Navara <navaraf(a)reactos.org>
+ * Copyright 2001 - 2005 Eric Kohl
+ */
+
+#include "cmlib.h"
+
+BOOLEAN CMAPI
+CmCreateRootNode(
+ PREGISTRY_HIVE Hive,
+ PCWSTR Name)
+{
+ PKEY_CELL KeyCell;
+ HCELL_INDEX RootCellIndex;
+ ULONG NameSize;
+
+ NameSize = wcslen(Name) * sizeof(WCHAR);
+ RootCellIndex = HvAllocateCell(Hive, sizeof(KEY_CELL) + NameSize, HvStable);
+ if (RootCellIndex == HCELL_NULL)
+ return FALSE;
+
+ Hive->HiveHeader->RootCell = RootCellIndex;
+ Hive->HiveHeader->Checksum = HvpHiveHeaderChecksum(Hive->HiveHeader);
+
+ KeyCell = (PKEY_CELL)HvGetCell(Hive, RootCellIndex);
+ KeyCell->Id = REG_KEY_CELL_ID;
+ KeyCell->Flags = REG_KEY_ROOT_CELL;
+ KeyCell->LastWriteTime.QuadPart = 0;
+ KeyCell->ParentKeyOffset = HCELL_NULL;
+ KeyCell->NumberOfSubKeys[0] = 0;
+ KeyCell->NumberOfSubKeys[1] = 0;
+ KeyCell->HashTableOffset[0] = HCELL_NULL;
+ KeyCell->HashTableOffset[1] = HCELL_NULL;
+ KeyCell->NumberOfValues = 0;
+ KeyCell->ValueListOffset = HCELL_NULL;
+ KeyCell->SecurityKeyOffset = HCELL_NULL;
+ KeyCell->ClassNameOffset = HCELL_NULL;
+ KeyCell->NameSize = NameSize;
+ KeyCell->ClassSize = 0;
+ memcpy(KeyCell->Name, Name, NameSize);
+
+ return TRUE;
+}
+
+static VOID CMAPI
+CmpPrepareKey(
+ PREGISTRY_HIVE RegistryHive,
+ PKEY_CELL KeyCell)
+{
+ PKEY_CELL SubKeyCell;
+ PHASH_TABLE_CELL HashCell;
+ ULONG i;
+
+ ASSERT(KeyCell->Id == REG_KEY_CELL_ID);
+
+ KeyCell->HashTableOffset[HvVolatile] = HCELL_NULL;
+ KeyCell->NumberOfSubKeys[HvVolatile] = 0;
+
+ /* Enumerate and add subkeys */
+ if (KeyCell->NumberOfSubKeys[HvStable] > 0)
+ {
+ HashCell = HvGetCell(RegistryHive, KeyCell->HashTableOffset[HvStable]);
+
+ for (i = 0; i < KeyCell->NumberOfSubKeys[HvStable]; i++)
+ {
+ SubKeyCell = HvGetCell(RegistryHive, HashCell->Table[i].KeyOffset);
+ CmpPrepareKey(RegistryHive, SubKeyCell);
+ }
+ }
+}
+
+VOID CMAPI
+CmPrepareHive(
+ PREGISTRY_HIVE RegistryHive)
+{
+ PKEY_CELL RootCell;
+
+ RootCell = HvGetCell(RegistryHive, RegistryHive->HiveHeader->RootCell);
+ CmpPrepareKey(RegistryHive, RootCell);
+}
Added: trunk/reactos/lib/cmlib/cmlib.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/cmlib/cmlib.h?rev=2333…
==============================================================================
--- trunk/reactos/lib/cmlib/cmlib.h (added)
+++ trunk/reactos/lib/cmlib/cmlib.h Sat Jul 29 00:50:05 2006
@@ -1,0 +1,175 @@
+/*
+ * PROJECT: registry manipulation library
+ * LICENSE: GPL - See COPYING in the top level directory
+ * COPYRIGHT: Copyright 2005 Filip Navara <navaraf(a)reactos.org>
+ * Copyright 2001 - 2005 Eric Kohl
+ */
+
+#ifndef CMLIB_H
+#define CMLIB_H
+
+#include <ddk/ntddk.h>
+#include "hivedata.h"
+#include "cmdata.h"
+
+#ifndef ROUND_UP
+#define ROUND_UP(a,b) ((((a)+(b)-1)/(b))*(b))
+#define ROUND_DOWN(a,b) (((a)/(b))*(b))
+#endif
+
+#define CMAPI
+
+typedef struct _BLOCK_LIST_ENTRY
+{
+ PHBIN Bin;
+ PVOID Block;
+} BLOCK_LIST_ENTRY, *PBLOCK_LIST_ENTRY;
+
+struct _REGISTRY_HIVE;
+
+typedef PVOID (CMAPI *PHV_ALLOCATE)(
+ ULONG Size,
+ BOOLEAN Paged);
+
+typedef VOID (CMAPI *PHV_FREE)(
+ PVOID Ptr);
+
+typedef BOOLEAN (CMAPI *PHV_FILE_READ)(
+ struct _REGISTRY_HIVE *RegistryHive,
+ ULONG FileType,
+ ULONG FileOffset,
+ PVOID Buffer,
+ ULONG BufferLength);
+
+typedef BOOLEAN (CMAPI *PHV_FILE_WRITE)(
+ struct _REGISTRY_HIVE *RegistryHive,
+ ULONG FileType,
+ ULONG FileOffset,
+ PVOID Buffer,
+ ULONG BufferLength);
+
+typedef BOOLEAN (CMAPI *PHV_FILE_SET_SIZE)(
+ struct _REGISTRY_HIVE *RegistryHive,
+ ULONG FileType,
+ ULONG FileSize);
+
+typedef BOOLEAN (CMAPI *PHV_FILE_FLUSH)(
+ struct _REGISTRY_HIVE *RegistryHive,
+ ULONG FileType);
+
+typedef struct _REGISTRY_HIVE
+{
+ PHIVE_HEADER HiveHeader;
+ BOOLEAN ReadOnly;
+ BOOLEAN Flat;
+ RTL_BITMAP DirtyBitmap;
+ struct
+ {
+ ULONG BlockListSize;
+ PBLOCK_LIST_ENTRY BlockList;
+ HCELL_INDEX FreeListOffset[24];
+ } Storage[HvMaxStorageType];
+
+ PHV_ALLOCATE Allocate;
+ PHV_FREE Free;
+ PHV_FILE_READ FileRead;
+ PHV_FILE_WRITE FileWrite;
+ PHV_FILE_SET_SIZE FileSetSize;
+ PHV_FILE_FLUSH FileFlush;
+ PVOID Opaque;
+} REGISTRY_HIVE, *PREGISTRY_HIVE;
+
+/*
+ * Public functions.
+ */
+
+#define HV_OPERATION_CREATE_HIVE 1
+#define HV_OPERATION_MEMORY 2
+#define HV_OPERATION_MEMORY_INPLACE 3
+
+NTSTATUS CMAPI
+HvInitialize(
+ PREGISTRY_HIVE *RegistryHive,
+ ULONG Operation,
+ ULONG_PTR ChunkBase,
+ SIZE_T ChunkSize,
+ PHV_ALLOCATE Allocate,
+ PHV_FREE Free,
+ PHV_FILE_READ FileRead,
+ PHV_FILE_WRITE FileWrite,
+ PHV_FILE_SET_SIZE FileSetSize,
+ PHV_FILE_FLUSH FileFlush,
+ PVOID Opaque);
+
+VOID CMAPI
+HvFree(
+ PREGISTRY_HIVE RegistryHive);
+
+PVOID CMAPI
+HvGetCell(
+ PREGISTRY_HIVE RegistryHive,
+ HCELL_INDEX CellOffset);
+
+LONG CMAPI
+HvGetCellSize(
+ PREGISTRY_HIVE RegistryHive,
+ PVOID Cell);
+
+HCELL_INDEX CMAPI
+HvAllocateCell(
+ PREGISTRY_HIVE RegistryHive,
+ ULONG Size,
+ HV_STORAGE_TYPE Storage);
+
+HCELL_INDEX CMAPI
+HvReallocateCell(
+ PREGISTRY_HIVE RegistryHive,
+ HCELL_INDEX CellOffset,
+ ULONG Size);
+
+VOID CMAPI
+HvFreeCell(
+ PREGISTRY_HIVE RegistryHive,
+ HCELL_INDEX CellOffset);
+
+VOID CMAPI
+HvMarkCellDirty(
+ PREGISTRY_HIVE RegistryHive,
+ HCELL_INDEX CellOffset);
+
+BOOLEAN CMAPI
+HvSyncHive(
+ PREGISTRY_HIVE RegistryHive);
+
+BOOLEAN CMAPI
+HvWriteHive(
+ PREGISTRY_HIVE RegistryHive);
+
+BOOLEAN CMAPI
+CmCreateRootNode(
+ PREGISTRY_HIVE Hive,
+ PCWSTR Name);
+
+VOID CMAPI
+CmPrepareHive(
+ PREGISTRY_HIVE RegistryHive);
+
+/*
+ * Private functions.
+ */
+
+PHBIN CMAPI
+HvpAddBin(
+ PREGISTRY_HIVE RegistryHive,
+ ULONG Size,
+ HV_STORAGE_TYPE Storage);
+
+NTSTATUS CMAPI
+HvpCreateHiveFreeCellList(
+ PREGISTRY_HIVE Hive);
+
+ULONG CMAPI
+HvpHiveHeaderChecksum(
+ PHIVE_HEADER HiveHeader);
+
+#endif /* CMLIB_H */
Added: trunk/reactos/lib/cmlib/cmlib.mak
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/cmlib/cmlib.mak?rev=23…
==============================================================================
--- trunk/reactos/lib/cmlib/cmlib.mak (added)
+++ trunk/reactos/lib/cmlib/cmlib.mak Sat Jul 29 00:50:05 2006
@@ -1,0 +1,55 @@
+CMLIB_BASE = $(LIB_BASE_)cmlib
+CMLIB_BASE_ = $(CMLIB_BASE)$(SEP)
+CMLIB_INT = $(INTERMEDIATE_)$(CMLIB_BASE)_host
+CMLIB_INT_ = $(INTERMEDIATE_)$(CMLIB_BASE)_host$(SEP)
+CMLIB_OUT = $(OUTPUT_)$(CMLIB_BASE)_host
+CMLIB_OUT_ = $(OUTPUT_)$(CMLIB_BASE)_host$(SEP)
+
+$(CMLIB_INT): | $(LIB_INT)
+ $(ECHO_MKDIR)
+ ${mkdir} $@
+
+ifneq ($(INTERMEDIATE),$(OUTPUT))
+$(CMLIB_OUT): | $(OUTPUT_)$(LIB_BASE)
+ $(ECHO_MKDIR)
+ ${mkdir} $@
+endif
+
+CMLIB_HOST_TARGET = \
+ $(CMLIB_OUT)$(SEP)cmlib.a
+
+CMLIB_HOST_SOURCES = $(addprefix $(CMLIB_BASE_), \
+ hivebin.c \
+ hivecell.c \
+ hiveinit.c \
+ )
+
+CMLIB_HOST_OBJECTS = \
+ $(subst $(CMLIB_BASE), $(CMLIB_INT), $(CMLIB_HOST_SOURCES:.c=.o))
+
+CMLIB_HOST_CFLAGS = -O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \
+ -DCMLIB_HOST -D_M_IX86 -I$(CMLIB_BASE) -Iinclude/reactos -DDBG
+
+$(CMLIB_HOST_TARGET): $(CMLIB_HOST_OBJECTS) | $(CMLIB_OUT)
+ $(ECHO_AR)
+ $(host_ar) -r $@ $(CMLIB_HOST_OBJECTS)
+
+$(CMLIB_INT_)hivebin.o: $(CMLIB_BASE_)hivebin.c | $(CMLIB_INT)
+ $(ECHO_CC)
+ ${host_gcc} $(CMLIB_HOST_CFLAGS) -c $< -o $@
+
+$(CMLIB_INT_)hivecell.o: $(CMLIB_BASE_)hivecell.c | $(CMLIB_INT)
+ $(ECHO_CC)
+ ${host_gcc} $(CMLIB_HOST_CFLAGS) -c $< -o $@
+
+$(CMLIB_INT_)hiveinit.o: $(CMLIB_BASE_)hiveinit.c | $(CMLIB_INT)
+ $(ECHO_CC)
+ ${host_gcc} $(CMLIB_HOST_CFLAGS) -c $< -o $@
+
+.PHONY: cmlib_host
+cmlib_host: $(CMLIB_HOST_TARGET)
+
+.PHONY: cmlib_host_clean
+cmlib_host_clean:
+ -@$(rm) $(CMLIB_HOST_TARGET) $(CMLIB_HOST_OBJECTS) 2>$(NUL)
+clean: cmlib_host_clean
Added: trunk/reactos/lib/cmlib/cmlib.rbuild
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/cmlib/cmlib.rbuild?rev…
==============================================================================
--- trunk/reactos/lib/cmlib/cmlib.rbuild (added)
+++ trunk/reactos/lib/cmlib/cmlib.rbuild Sat Jul 29 00:50:05 2006
@@ -1,0 +1,14 @@
+<module name="cmlib" type="staticlibrary">
+ <include base="cmlib">.</include>
+ <define name="__NO_CTYPE_INLINES" />
+ <define name="_NTOSKRNL_" />
+ <define name="_NTSYSTEM_" />
+ <define name="NASSERT" />
+ <pch>cmlib.h</pch>
+ <file>cminit.c</file>
+ <file>hivebin.c</file>
+ <file>hivecell.c</file>
+ <file>hiveinit.c</file>
+ <file>hivesum.c</file>
+ <file>hivewrt.c</file>
+</module>
Added: trunk/reactos/lib/cmlib/hivebin.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/cmlib/hivebin.c?rev=23…
==============================================================================
--- trunk/reactos/lib/cmlib/hivebin.c (added)
+++ trunk/reactos/lib/cmlib/hivebin.c Sat Jul 29 00:50:05 2006
@@ -1,0 +1,98 @@
+/*
+ * PROJECT: registry manipulation library
+ * LICENSE: GPL - See COPYING in the top level directory
+ * COPYRIGHT: Copyright 2005 Filip Navara <navaraf(a)reactos.org>
+ * Copyright 2005 Hartmut Birr
+ * Copyright 2001 - 2005 Eric Kohl
+ */
+
+#include "cmlib.h"
+
+PHBIN CMAPI
+HvpAddBin(
+ PREGISTRY_HIVE RegistryHive,
+ ULONG Size,
+ HV_STORAGE_TYPE Storage)
+{
+ PBLOCK_LIST_ENTRY BlockList;
+ PHBIN Bin;
+ ULONG BinSize;
+ ULONG i;
+ ULONG BitmapSize;
+ ULONG BlockCount;
+ ULONG OldBlockListSize;
+ PCELL_HEADER Block;
+
+ BinSize = ROUND_UP(Size + sizeof(HBIN), HV_BLOCK_SIZE);
+ BlockCount = BinSize / HV_BLOCK_SIZE;
+
+ Bin = RegistryHive->Allocate(BinSize, TRUE);
+ if (Bin == NULL)
+ return NULL;
+ RtlZeroMemory(Bin, sizeof(HBIN));
+
+ Bin->Signature = HV_BIN_SIGNATURE;
+ Bin->BinOffset = RegistryHive->Storage[Storage].BlockListSize *
+ HV_BLOCK_SIZE;
+ Bin->BinSize = BinSize;
+
+ /* Allocate new block list */
+ OldBlockListSize = RegistryHive->Storage[Storage].BlockListSize;
+ BlockList = RegistryHive->Allocate(sizeof(BLOCK_LIST_ENTRY) *
+ (OldBlockListSize + BlockCount), TRUE);
+ if (BlockList == NULL)
+ {
+ RegistryHive->Free(Bin);
+ return NULL;
+ }
+
+ if (OldBlockListSize > 0)
+ {
+ RtlCopyMemory(BlockList, RegistryHive->Storage[Storage].BlockList,
+ OldBlockListSize * sizeof(BLOCK_LIST_ENTRY));
+ RegistryHive->Free(RegistryHive->Storage[Storage].BlockList);
+ }
+
+ RegistryHive->Storage[Storage].BlockList = BlockList;
+ RegistryHive->Storage[Storage].BlockListSize += BlockCount;
+
+ for (i = 0; i < BlockCount; i++)
+ {
+ RegistryHive->Storage[Storage].BlockList[OldBlockListSize + i].Block =
+ (PVOID)((ULONG_PTR)Bin + (i * HV_BLOCK_SIZE));
+ RegistryHive->Storage[Storage].BlockList[OldBlockListSize + i].Bin = Bin;
+ }
+
+ /* Initialize a free block in this heap. */
+ Block = (PCELL_HEADER)(Bin + 1);
+ Block->CellSize = BinSize - sizeof(HBIN);
+
+ if (Storage == HvStable)
+ {
+ /* Calculate bitmap size in bytes (always a multiple of 32 bits). */
+ BitmapSize = ROUND_UP(RegistryHive->Storage[HvStable].BlockListSize,
+ sizeof(ULONG) * 8) / 8;
+
+ /* Grow bitmap if necessary. */
+ if (BitmapSize > RegistryHive->DirtyBitmap.SizeOfBitMap / 8)
+ {
+ PULONG BitmapBuffer;
+
+ BitmapBuffer = RegistryHive->Allocate(BitmapSize, TRUE);
+ RtlZeroMemory(BitmapBuffer, BitmapSize);
+ RtlCopyMemory(BitmapBuffer,
+ RegistryHive->DirtyBitmap.Buffer,
+ RegistryHive->DirtyBitmap.SizeOfBitMap / 8);
+ RegistryHive->Free(RegistryHive->DirtyBitmap.Buffer);
+ RtlInitializeBitMap(&RegistryHive->DirtyBitmap, BitmapBuffer,
+ BitmapSize * 8);
+ }
+
+ /* Mark new bin dirty. */
+ RtlSetBits(&RegistryHive->DirtyBitmap,
+ Bin->BinOffset / HV_BLOCK_SIZE,
+ BlockCount);
+ }
+
+ return Bin;
+}
Added: trunk/reactos/lib/cmlib/hivecell.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/cmlib/hivecell.c?rev=2…
==============================================================================
--- trunk/reactos/lib/cmlib/hivecell.c (added)
+++ trunk/reactos/lib/cmlib/hivecell.c Sat Jul 29 00:50:05 2006
@@ -1,0 +1,429 @@
+/*
+ * PROJECT: registry manipulation library
+ * LICENSE: GPL - See COPYING in the top level directory
+ * COPYRIGHT: Copyright 2005 Filip Navara <navaraf(a)reactos.org>
+ * Copyright 2001 - 2005 Eric Kohl
+ */
+
+#include "cmlib.h"
+#define NDEBUG
+#include <debug.h>
+
+static PCELL_HEADER __inline CMAPI
+HvpGetCellHeader(
+ PREGISTRY_HIVE RegistryHive,
+ HCELL_INDEX CellIndex)
+{
+ PVOID Block;
+
+ ASSERT(CellIndex != HCELL_NULL);
+ if (!RegistryHive->Flat)
+ {
+ ULONG CellType;
+ ULONG CellBlock;
+ ULONG CellOffset;
+
+ CellType = (CellIndex & HCELL_TYPE_MASK) >> HCELL_TYPE_SHIFT;
+ CellBlock = (CellIndex & HCELL_BLOCK_MASK) >> HCELL_BLOCK_SHIFT;
+ CellOffset = (CellIndex & HCELL_OFFSET_MASK) >> HCELL_OFFSET_SHIFT;
+ ASSERT(CellBlock < RegistryHive->Storage[CellType].BlockListSize);
+ Block = RegistryHive->Storage[CellType].BlockList[CellBlock].Block;
+ ASSERT(Block != NULL);
+ return (PVOID)((ULONG_PTR)Block + CellOffset);
+ }
+ else
+ {
+ ASSERT((CellIndex & HCELL_TYPE_MASK) == HvStable);
+ return (PVOID)((ULONG_PTR)RegistryHive->HiveHeader + HV_BLOCK_SIZE +
+ CellIndex);
+ }
+}
+
+PVOID CMAPI
+HvGetCell(
+ PREGISTRY_HIVE RegistryHive,
+ HCELL_INDEX CellIndex)
+{
+ return (PVOID)(HvpGetCellHeader(RegistryHive, CellIndex) + 1);
+}
+
+static LONG __inline CMAPI
+HvpGetCellFullSize(
+ PREGISTRY_HIVE RegistryHive,
+ PVOID Cell)
+{
+ return ((PCELL_HEADER)Cell - 1)->CellSize;
+}
+
+LONG CMAPI
+HvGetCellSize(
+ PREGISTRY_HIVE RegistryHive,
+ PVOID Cell)
+{
+ PCELL_HEADER CellHeader;
+
+ CellHeader = (PCELL_HEADER)Cell - 1;
+ if (CellHeader->CellSize < 0)
+ return CellHeader->CellSize + sizeof(CELL_HEADER);
+ else
+ return CellHeader->CellSize - sizeof(CELL_HEADER);
+}
+
+VOID CMAPI
+HvMarkCellDirty(
+ PREGISTRY_HIVE RegistryHive,
+ HCELL_INDEX CellIndex)
+{
+ LONG CellSize;
+ ULONG CellBlock;
+ ULONG CellLastBlock;
+
+ ASSERT(RegistryHive->ReadOnly == FALSE);
+
+ if ((CellIndex & HCELL_TYPE_MASK) >> HCELL_TYPE_SHIFT != HvStable)
+ return;
+
+ CellBlock = (CellIndex & HCELL_BLOCK_MASK) >> HCELL_BLOCK_SHIFT;
+ CellLastBlock = ((CellIndex + HV_BLOCK_SIZE - 1) & HCELL_BLOCK_MASK) >>
HCELL_BLOCK_SHIFT;
+
+ CellSize = HvpGetCellFullSize(RegistryHive, HvGetCell(RegistryHive, CellIndex));
+ if (CellSize < 0)
+ CellSize = -CellSize;
+
+ RtlSetBits(&RegistryHive->DirtyBitmap,
+ CellBlock, CellLastBlock - CellBlock);
+}
+
+static ULONG __inline CMAPI
+HvpComputeFreeListIndex(
+ ULONG Size)
+{
+ ULONG Index;
+ static CCHAR FindFirstSet[256] = {
+ 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7};
+
+ Index = (Size >> 3) - 1;
+ if (Index >= 16)
+ {
+ if (Index > 255)
+ Index = 23;
+ else
+ Index = FindFirstSet[Index] + 7;
+ }
+
+ return Index;
+}
+
+static NTSTATUS CMAPI
+HvpAddFree(
+ PREGISTRY_HIVE RegistryHive,
+ PCELL_HEADER FreeBlock,
+ HCELL_INDEX FreeIndex)
+{
+ PHCELL_INDEX FreeBlockData;
+ HV_STORAGE_TYPE Storage;
+ ULONG Index;
+
+ ASSERT(RegistryHive != NULL);
+ ASSERT(FreeBlock != NULL);
+
+ Storage = (FreeIndex & HCELL_TYPE_MASK) >> HCELL_TYPE_SHIFT;
+ Index = HvpComputeFreeListIndex(FreeBlock->CellSize);
+
+ FreeBlockData = (PHCELL_INDEX)(FreeBlock + 1);
+ *FreeBlockData = RegistryHive->Storage[Storage].FreeListOffset[Index];
+ RegistryHive->Storage[Storage].FreeListOffset[Index] = FreeIndex;
+
+ /* FIXME: Eventually get rid of free bins. */
+
+ return STATUS_SUCCESS;
+}
+
+static VOID CMAPI
+HvpRemoveFree(
+ PREGISTRY_HIVE RegistryHive,
+ PCELL_HEADER CellBlock,
+ HCELL_INDEX CellIndex)
+{
+ PHCELL_INDEX FreeCellData;
+ PHCELL_INDEX pFreeCellOffset;
+ HV_STORAGE_TYPE Storage;
+ ULONG Index;
+
+ ASSERT(RegistryHive->ReadOnly == FALSE);
+
+ Storage = (CellIndex & HCELL_TYPE_MASK) >> HCELL_TYPE_SHIFT;
+ Index = HvpComputeFreeListIndex(CellBlock->CellSize);
+
+ pFreeCellOffset = &RegistryHive->Storage[Storage].FreeListOffset[Index];
+ while (*pFreeCellOffset != HCELL_NULL)
+ {
+ FreeCellData = (PHCELL_INDEX)HvGetCell(RegistryHive, *pFreeCellOffset);
+ if (*pFreeCellOffset == CellIndex)
+ {
+ *pFreeCellOffset = *FreeCellData;
+ return;
+ }
+ pFreeCellOffset = FreeCellData;
+ }
+
+ ASSERT(FALSE);
+}
+
+static HCELL_INDEX CMAPI
+HvpFindFree(
+ PREGISTRY_HIVE RegistryHive,
+ ULONG Size,
+ HV_STORAGE_TYPE Storage)
+{
+ PHCELL_INDEX FreeCellData;
+ HCELL_INDEX FreeCellOffset;
+ PHCELL_INDEX pFreeCellOffset;
+ ULONG Index;
+
+ for (Index = HvpComputeFreeListIndex(Size); Index < 24; Index++)
+ {
+ pFreeCellOffset = &RegistryHive->Storage[Storage].FreeListOffset[Index];
+ while (*pFreeCellOffset != HCELL_NULL)
+ {
+ FreeCellData = (PHCELL_INDEX)HvGetCell(RegistryHive, *pFreeCellOffset);
+ if (HvpGetCellFullSize(RegistryHive, FreeCellData) >= Size)
+ {
+ FreeCellOffset = *pFreeCellOffset;
+ *pFreeCellOffset = *FreeCellData;
+ return FreeCellOffset;
+ }
+ pFreeCellOffset = FreeCellData;
+ }
+ }
+
+ return HCELL_NULL;
+}
+
+NTSTATUS CMAPI
+HvpCreateHiveFreeCellList(
+ PREGISTRY_HIVE Hive)
+{
+ HCELL_INDEX BlockOffset;
+ PCELL_HEADER FreeBlock;
+ ULONG BlockIndex;
+ ULONG FreeOffset;
+ PHBIN Bin;
+ NTSTATUS Status;
+ ULONG Index;
+
+ /* Initialize the free cell list */
+ for (Index = 0; Index < 24; Index++)
+ {
+ Hive->Storage[HvStable].FreeListOffset[Index] = HCELL_NULL;
+ Hive->Storage[HvVolatile].FreeListOffset[Index] = HCELL_NULL;
+ }
+
+ BlockOffset = 0;
+ BlockIndex = 0;
+ while (BlockIndex < Hive->Storage[HvStable].BlockListSize)
+ {
+ Bin = Hive->Storage[HvStable].BlockList[BlockIndex].Bin;
+
+ /* Search free blocks and add to list */
+ FreeOffset = sizeof(HBIN);
+ while (FreeOffset < Bin->BinSize)
+ {
+ FreeBlock = (PCELL_HEADER)((ULONG_PTR)Bin + FreeOffset);
+ if (FreeBlock->CellSize > 0)
+ {
+ Status = HvpAddFree(Hive, FreeBlock, Bin->BinOffset + FreeOffset);
+ if (!NT_SUCCESS(Status))
+ return Status;
+
+ FreeOffset += FreeBlock->CellSize;
+ }
+ else
+ {
+ FreeOffset -= FreeBlock->CellSize;
+ }
+ }
+
+ BlockIndex += Bin->BinSize / HV_BLOCK_SIZE;
+ BlockOffset += Bin->BinSize;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+HCELL_INDEX CMAPI
+HvAllocateCell(
+ PREGISTRY_HIVE RegistryHive,
+ ULONG Size,
+ HV_STORAGE_TYPE Storage)
+{
+ PCELL_HEADER FreeCell;
+ HCELL_INDEX FreeCellOffset;
+ PCELL_HEADER NewCell;
+ PHBIN Bin;
+
+ ASSERT(RegistryHive->ReadOnly == FALSE);
+
+ /* Round to 16 bytes multiple. */
+ Size = ROUND_UP(Size + sizeof(CELL_HEADER), 16);
+
+ /* First search in free blocks. */
+ FreeCellOffset = HvpFindFree(RegistryHive, Size, Storage);
+
+ /* If no free cell was found we need to extend the hive file. */
+ if (FreeCellOffset == HCELL_NULL)
+ {
+ Bin = HvpAddBin(RegistryHive, Size, Storage);
+ if (Bin == NULL)
+ return HCELL_NULL;
+ FreeCellOffset = Bin->BinOffset + sizeof(HBIN);
+ FreeCellOffset |= Storage << HCELL_TYPE_SHIFT;
+ }
+
+ FreeCell = HvpGetCellHeader(RegistryHive, FreeCellOffset);
+
+ /* Split the block in two parts */
+ /* FIXME: There is some minimal cell size that we must respect. */
+ if (FreeCell->CellSize > Size + sizeof(HCELL_INDEX))
+ {
+ NewCell = (PCELL_HEADER)((ULONG_PTR)FreeCell + Size);
+ NewCell->CellSize = FreeCell->CellSize - Size;
+ FreeCell->CellSize = Size;
+ HvpAddFree(RegistryHive, NewCell, FreeCellOffset + Size);
+ if (Storage == HvStable)
+ HvMarkCellDirty(RegistryHive, FreeCellOffset + Size);
+ }
+
+ if (Storage == HvStable)
+ HvMarkCellDirty(RegistryHive, FreeCellOffset);
+ FreeCell->CellSize = -FreeCell->CellSize;
+ RtlZeroMemory(FreeCell + 1, Size - sizeof(CELL_HEADER));
+
+ return FreeCellOffset;
+}
+
+HCELL_INDEX CMAPI
+HvReallocateCell(
+ PREGISTRY_HIVE RegistryHive,
+ HCELL_INDEX CellIndex,
+ ULONG Size)
+{
+ PVOID OldCell;
+ PVOID NewCell;
+ LONG OldCellSize;
+ HCELL_INDEX NewCellIndex;
+ HV_STORAGE_TYPE Storage;
+
+ ASSERT(CellIndex != HCELL_NULL);
+
+ Storage = (CellIndex & HCELL_TYPE_MASK) >> HCELL_TYPE_SHIFT;
+
+ OldCell = HvGetCell(RegistryHive, CellIndex);
+ OldCellSize = HvGetCellSize(RegistryHive, OldCell);
+ ASSERT(OldCellSize < 0);
+
+ /*
+ * If new data size is larger than the current, destroy current
+ * data block and allocate a new one.
+ *
+ * FIXME: Merge with adjacent free cell if possible.
+ * FIXME: Implement shrinking.
+ */
+ if (Size > -OldCellSize)
+ {
+ NewCellIndex = HvAllocateCell(RegistryHive, Size, Storage);
+ if (NewCellIndex == HCELL_NULL)
+ return HCELL_NULL;
+
+ NewCell = HvGetCell(RegistryHive, NewCellIndex);
+ RtlCopyMemory(NewCell, OldCell, -OldCellSize);
+
+ HvFreeCell(RegistryHive, CellIndex);
+
+ return NewCellIndex;
+ }
+
+ return CellIndex;
+}
+
+VOID CMAPI
+HvFreeCell(
+ PREGISTRY_HIVE RegistryHive,
+ HCELL_INDEX CellIndex)
+{
+ PCELL_HEADER Free;
+ PCELL_HEADER Neighbor;
+ PHBIN Bin;
+ ULONG CellType;
+ ULONG CellBlock;
+
+ ASSERT(RegistryHive->ReadOnly == FALSE);
+
+ Free = HvpGetCellHeader(RegistryHive, CellIndex);
+
+ ASSERT(Free->CellSize < 0);
+
+ Free->CellSize = -Free->CellSize;
+
+ CellType = (CellIndex & HCELL_TYPE_MASK) >> HCELL_TYPE_SHIFT;
+ CellBlock = (CellIndex & HCELL_BLOCK_MASK) >> HCELL_BLOCK_SHIFT;
+
+ /* FIXME: Merge free blocks */
+ Bin = RegistryHive->Storage[CellType].BlockList[CellBlock].Bin;
+
+ if ((CellIndex & ~HCELL_TYPE_MASK) + Free->CellSize <
+ Bin->BinOffset + Bin->BinSize)
+ {
+ Neighbor = (PCELL_HEADER)((ULONG_PTR)Free + Free->CellSize);
+ if (Neighbor->CellSize > 0)
+ {
+ HvpRemoveFree(RegistryHive, Neighbor,
+ ((HCELL_INDEX)Neighbor - (HCELL_INDEX)Bin +
+ Bin->BinOffset) | (CellIndex & HCELL_TYPE_MASK));
+ Free->CellSize += Neighbor->CellSize;
+ }
+ }
+
+ Neighbor = (PCELL_HEADER)(Bin + 1);
+ while (Neighbor < Free)
+ {
+ if (Neighbor->CellSize > 0)
+ {
+ if ((ULONG_PTR)Neighbor + Neighbor->CellSize == (ULONG_PTR)Free)
+ {
+ Neighbor->CellSize += Free->CellSize;
+ if (CellType == HvStable)
+ HvMarkCellDirty(RegistryHive,
+ (HCELL_INDEX)Neighbor - (HCELL_INDEX)Bin +
+ Bin->BinOffset);
+ return;
+ }
+ Neighbor = (PCELL_HEADER)((ULONG_PTR)Neighbor + Neighbor->CellSize);
+ }
+ else
+ {
+ Neighbor = (PCELL_HEADER)((ULONG_PTR)Neighbor - Neighbor->CellSize);
+ }
+ }
+
+ /* Add block to the list of free blocks */
+ HvpAddFree(RegistryHive, Free, CellIndex);
+
+ if (CellType == HvStable)
+ HvMarkCellDirty(RegistryHive, CellIndex);
+}
Added: trunk/reactos/lib/cmlib/hivedata.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/cmlib/hivedata.h?rev=2…
==============================================================================
--- trunk/reactos/lib/cmlib/hivedata.h (added)
+++ trunk/reactos/lib/cmlib/hivedata.h Sat Jul 29 00:50:05 2006
@@ -1,0 +1,138 @@
+/*
+ * PROJECT: registry manipulation library
+ * LICENSE: GPL - See COPYING in the top level directory
+ * COPYRIGHT: Copyright 2005 Filip Navara <navaraf(a)reactos.org>
+ * Copyright 2001 - 2005 Eric Kohl
+ */
+
+#ifndef CMLIB_HIVEDATA_H
+#define CMLIB_HIVEDATA_H
+
+#define HV_BLOCK_SIZE 4096
+#define HV_LOG_HEADER_SIZE FIELD_OFFSET(HIVE_HEADER, Reserved2)
+#define HV_SIGNATURE 0x66676572
+#define HV_BIN_SIGNATURE 0x6e696268
+
+#define HV_MAJOR_VER 1
+#define HV_MINOR_VER 3
+#define HV_FORMAT_MEMORY 1
+
+#define HV_TYPE_PRIMARY 0
+#define HV_TYPE_ALTERNATE 1
+#define HV_TYPE_LOG 2
+#define HV_TYPE_EXTERNAL 3
+#define HV_TYPE_MAX 4
+
+/**
+ * @name HCELL_INDEX
+ *
+ * A handle to cell index. The highest bit specifies the cell storage and
+ * the other bits specify index into the hive file. The value HCELL_NULL
+ * (-1) is reserved for marking invalid cells.
+ */
+
+typedef ULONG HCELL_INDEX, *PHCELL_INDEX;
+
+#define HCELL_NULL ((HCELL_INDEX)-1)
+#define HCELL_TYPE_MASK 0x80000000
+#define HCELL_BLOCK_MASK 0x7ffff000
+#define HCELL_OFFSET_MASK 0x00000fff
+#define HCELL_TYPE_SHIFT 31
+#define HCELL_BLOCK_SHIFT 12
+#define HCELL_OFFSET_SHIFT 0
+
+#include <pshpack1.h>
+
+/**
+ * @name HIVE_HEADER
+ *
+ * On-disk header for registry hive file.
+ */
+
+typedef struct _HIVE_HEADER
+{
+ /* Hive identifier "regf" (0x66676572) */
+ ULONG Signature;
+
+ /* Update counter */
+ ULONG Sequence1;
+
+ /* Update counter */
+ ULONG Sequence2;
+
+ /* When this hive file was last modified */
+ LARGE_INTEGER TimeStamp;
+
+ /* Registry format major version (1) */
+ ULONG Major;
+
+ /* Registry format minor version (3)
+ Version 3 added fast indexes, version 5 has large value optimizations */
+ ULONG Minor;
+
+ /* 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 */
+ HCELL_INDEX RootCell;
+
+ /* Size of each hive block ? */
+ ULONG Length;
+
+ /* (1?) */
+ ULONG Cluster;
+
+ /* Name of hive file */
+ WCHAR FileName[32];
+
+ ULONG Reserved1[99];
+
+ /* Checksum of first 0x200 bytes */
+ ULONG Checksum;
+
+ ULONG Reserved2[0x380];
+} HIVE_HEADER, *PHIVE_HEADER;
+
+typedef struct _BIN_HEADER
+{
+ /* Bin identifier "hbin" (0x6E696268) */
+ ULONG Signature;
+
+ /* Block offset of this bin */
+ HCELL_INDEX BinOffset;
+
+ /* Size in bytes, multiple of the block size (4KB) */
+ ULONG BinSize;
+
+ ULONG Reserved[2];
+
+ /* When this bin was last modified */
+ LARGE_INTEGER DateModified;
+
+ /* ? (In-memory only) */
+ ULONG MemAlloc;
+} HBIN, *PHBIN;
+
+typedef struct _CELL_HEADER
+{
+ /* <0 if used, >0 if free */
+ LONG CellSize;
+} CELL_HEADER, *PCELL_HEADER;
+
+#include <poppack.h>
+
+#define IsFreeCell(Cell)(Cell->CellSize >= 0)
+#define IsUsedCell(Cell)(Cell->CellSize < 0)
+
+typedef enum _HV_STORAGE_TYPE
+{
+ HvStable = 0,
+ HvVolatile,
+ HvMaxStorageType
+} HV_STORAGE_TYPE;
+
+#endif /* CMLIB_HIVEDATA_H */
Added: trunk/reactos/lib/cmlib/hiveinit.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/cmlib/hiveinit.c?rev=2…
==============================================================================
--- trunk/reactos/lib/cmlib/hiveinit.c (added)
+++ trunk/reactos/lib/cmlib/hiveinit.c Sat Jul 29 00:50:05 2006
@@ -1,0 +1,377 @@
+/*
+ * PROJECT: registry manipulation library
+ * LICENSE: GPL - See COPYING in the top level directory
+ * COPYRIGHT: Copyright 2005 Filip Navara <navaraf(a)reactos.org>
+ * Copyright 2001 - 2005 Eric Kohl
+ */
+
+#include "cmlib.h"
+#define NDEBUG
+#include <debug.h>
+
+/**
+ * @name HvpVerifyHiveHeader
+ *
+ * Internal function to verify that a hive header has valid format.
+ */
+
+BOOLEAN CMAPI
+HvpVerifyHiveHeader(
+ PHIVE_HEADER HiveHeader)
+{
+ if (HiveHeader->Signature != HV_SIGNATURE ||
+ HiveHeader->Major != HV_MAJOR_VER ||
+ HiveHeader->Minor > HV_MINOR_VER ||
+ HiveHeader->Type != HV_TYPE_PRIMARY ||
+ HiveHeader->Format != HV_FORMAT_MEMORY ||
+ HiveHeader->Cluster != 1 ||
+ HiveHeader->Sequence1 != HiveHeader->Sequence2 ||
+ HvpHiveHeaderChecksum(HiveHeader) != HiveHeader->Checksum)
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ * @name HvpFreeHiveBins
+ *
+ * Internal function to free all bin storage associated with hive
+ * descriptor.
+ */
+
+VOID CMAPI
+HvpFreeHiveBins(
+ PREGISTRY_HIVE Hive)
+{
+ ULONG i;
+ PHBIN Bin;
+ ULONG Storage;
+
+ for (Storage = HvStable; Storage < HvMaxStorageType; Storage++)
+ {
+ Bin = NULL;
+ for (i = 0; i < Hive->Storage[Storage].BlockListSize; i++)
+ {
+ if (Hive->Storage[Storage].BlockList[i].Bin == NULL)
+ continue;
+ if (Hive->Storage[Storage].BlockList[i].Bin != Bin)
+ {
+ Bin = Hive->Storage[Storage].BlockList[i].Bin;
+ Hive->Free(Hive->Storage[Storage].BlockList[i].Bin);
+ }
+ Hive->Storage[Storage].BlockList[i].Bin = NULL;
+ Hive->Storage[Storage].BlockList[i].Block = NULL;
+ }
+
+ if (Hive->Storage[Storage].BlockListSize)
+ Hive->Free(Hive->Storage[Storage].BlockList);
+ }
+}
+
+/**
+ * @name HvpCreateHive
+ *
+ * Internal helper function to initalize hive descriptor structure for
+ * newly created hive.
+ *
+ * @see HvInitialize
+ */
+
+NTSTATUS CMAPI
+HvpCreateHive(
+ PREGISTRY_HIVE RegistryHive)
+{
+ PHIVE_HEADER HiveHeader;
+ ULONG Index;
+
+ HiveHeader = RegistryHive->Allocate(sizeof(HIVE_HEADER), FALSE);
+ if (HiveHeader == NULL)
+ return STATUS_NO_MEMORY;
+ RtlZeroMemory(HiveHeader, sizeof(HIVE_HEADER));
+ HiveHeader->Signature = HV_SIGNATURE;
+ HiveHeader->Major = HV_MAJOR_VER;
+ HiveHeader->Minor = HV_MINOR_VER;
+ HiveHeader->Type = HV_TYPE_PRIMARY;
+ HiveHeader->Format = HV_FORMAT_MEMORY;
+ HiveHeader->Cluster = 1;
+ HiveHeader->RootCell = HCELL_NULL;
+ HiveHeader->Length = HV_BLOCK_SIZE;
+ HiveHeader->Sequence1 = 1;
+ HiveHeader->Sequence2 = 1;
+ /* FIXME: Fill in the file name */
+ HiveHeader->Checksum = HvpHiveHeaderChecksum(HiveHeader);
+
+ RegistryHive->HiveHeader = HiveHeader;
+ for (Index = 0; Index < 24; Index++)
+ {
+ RegistryHive->Storage[HvStable].FreeListOffset[Index] = HCELL_NULL;
+ RegistryHive->Storage[HvVolatile].FreeListOffset[Index] = HCELL_NULL;
+ }
+ RtlInitializeBitMap(&RegistryHive->DirtyBitmap, NULL, 0);
+
+ return STATUS_SUCCESS;
+}
+
+/**
+ * @name HvpInitializeMemoryHive
+ *
+ * Internal helper function to initalize hive descriptor structure for
+ * a hive stored in memory. The data of the hive are copied and it is
+ * prepared for read/write access.
+ *
+ * @see HvInitialize
+ */
+
+NTSTATUS CMAPI
+HvpInitializeMemoryHive(
+ PREGISTRY_HIVE Hive,
+ ULONG_PTR ChunkBase,
+ SIZE_T ChunkSize)
+{
+ SIZE_T BlockIndex;
+ PHBIN Bin, NewBin;
+ ULONG i;
+ ULONG BitmapSize;
+ PULONG BitmapBuffer;
+
+ if (ChunkSize < sizeof(HIVE_HEADER) ||
+ !HvpVerifyHiveHeader((PHIVE_HEADER)ChunkBase))
+ {
+ return STATUS_REGISTRY_CORRUPT;
+ }
+
+ Hive->HiveHeader = Hive->Allocate(sizeof(HIVE_HEADER), FALSE);
+ if (Hive->HiveHeader == NULL)
+ {
+ return STATUS_NO_MEMORY;
+ }
+ RtlCopyMemory(Hive->HiveHeader, (PVOID)ChunkBase, sizeof(HIVE_HEADER));
+
+ /*
+ * Build a block list from the in-memory chunk and copy the data as
+ * we go.
+ */
+
+ Hive->Storage[HvStable].BlockListSize = (ChunkSize / HV_BLOCK_SIZE) - 1;
+ Hive->Storage[HvStable].BlockList =
+ Hive->Allocate(Hive->Storage[HvStable].BlockListSize *
+ sizeof(BLOCK_LIST_ENTRY), FALSE);
+ if (Hive->Storage[HvStable].BlockList == NULL)
+ {
+ DPRINT1("Allocating block list failed\n");
+ Hive->Free(Hive->HiveHeader);
+ return STATUS_NO_MEMORY;
+ }
+
+ for (BlockIndex = 0; BlockIndex < Hive->Storage[HvStable].BlockListSize; )
+ {
+ Bin = (PHBIN)((ULONG_PTR)ChunkBase + (BlockIndex + 1) * HV_BLOCK_SIZE);
+ if (Bin->Signature != HV_BIN_SIGNATURE ||
+ (Bin->BinSize % HV_BLOCK_SIZE) != 0)
+ {
+ Hive->Free(Hive->HiveHeader);
+ Hive->Free(Hive->Storage[HvStable].BlockList);
+ return STATUS_REGISTRY_CORRUPT;
+ }
+
+ NewBin = Hive->Allocate(Bin->BinSize, TRUE);
+ if (NewBin == NULL)
+ {
+ Hive->Free(Hive->HiveHeader);
+ Hive->Free(Hive->Storage[HvStable].BlockList);
+ return STATUS_NO_MEMORY;
+ }
+
+ Hive->Storage[HvStable].BlockList[BlockIndex].Bin = NewBin;
+ Hive->Storage[HvStable].BlockList[BlockIndex].Block = NewBin;
+
+ RtlCopyMemory(NewBin, Bin, Bin->BinSize);
+
+ if (Bin->BinSize > HV_BLOCK_SIZE)
+ {
+ for (i = 1; i < Bin->BinSize / HV_BLOCK_SIZE; i++)
+ {
+ Hive->Storage[HvStable].BlockList[BlockIndex + i].Bin = NewBin;
+ Hive->Storage[HvStable].BlockList[BlockIndex + i].Block =
+ (PVOID)((ULONG_PTR)NewBin + (i * HV_BLOCK_SIZE));
+ }
+ }
+
+ BlockIndex += Bin->BinSize / HV_BLOCK_SIZE;
+ }
+
+ if (HvpCreateHiveFreeCellList(Hive))
+ {
+ HvpFreeHiveBins(Hive);
+ Hive->Free(Hive->HiveHeader);
+ return STATUS_NO_MEMORY;
+ }
+
+ BitmapSize = ROUND_UP(Hive->Storage[HvStable].BlockListSize,
+ sizeof(ULONG) * 8) / 8;
+ BitmapBuffer = (PULONG)Hive->Allocate(BitmapSize, TRUE);
+ if (BitmapBuffer == NULL)
+ {
+ HvpFreeHiveBins(Hive);
+ Hive->Free(Hive->HiveHeader);
+ return STATUS_NO_MEMORY;
+ }
+
+ RtlInitializeBitMap(&Hive->DirtyBitmap, BitmapBuffer, BitmapSize * 8);
+ RtlClearAllBits(&Hive->DirtyBitmap);
+
+ return STATUS_SUCCESS;
+}
+
+/**
+ * @name HvpInitializeMemoryInplaceHive
+ *
+ * Internal helper function to initalize hive descriptor structure for
+ * a hive stored in memory. The in-memory data of the hive are directly
+ * used and it is read-only accessible.
+ *
+ * @see HvInitialize
+ */
+
+NTSTATUS CMAPI
+HvpInitializeMemoryInplaceHive(
+ PREGISTRY_HIVE Hive,
+ ULONG_PTR ChunkBase,
+ SIZE_T ChunkSize)
+{
+ if (ChunkSize < sizeof(HIVE_HEADER) ||
+ !HvpVerifyHiveHeader((PHIVE_HEADER)ChunkBase))
+ {
+ return STATUS_REGISTRY_CORRUPT;
+ }
+
+ Hive->HiveHeader = (PHIVE_HEADER)ChunkBase;
+ Hive->ReadOnly = TRUE;
+ Hive->Flat = TRUE;
+
+ return STATUS_SUCCESS;
+}
+
+/**
+ * @name HvInitialize
+ *
+ * Allocate a new hive descriptor structure and intialize it.
+ *
+ * @param RegistryHive
+ * Output variable to store pointer to the hive descriptor.
+ * @param Operation
+ * - HV_OPERATION_CREATE_HIVE
+ * Create a new hive for read/write access.
+ * - HV_OPERATION_MEMORY
+ * Load and copy in-memory hive for read/write access. The
+ * pointer to data passed to this routine can be freed after
+ * the function is executed.
+ * - HV_OPERATION_MEMORY_INPLACE
+ * Load an in-memory hive for read-only access. The pointer
+ * to data passed to this routine MUSTN'T be freed until
+ * HvFree is called.
+ * @param ChunkBase
+ * Pointer to hive data.
+ * @param ChunkSize
+ * Size of passed hive data.
+ *
+ * @return
+ * STATUS_NO_MEMORY - A memory allocation failed.
+ * STATUS_REGISTRY_CORRUPT - Registry corruption was detected.
+ * STATUS_SUCCESS
+ *
+ * @see HvFree
+ */
+
+NTSTATUS CMAPI
+HvInitialize(
+ PREGISTRY_HIVE *RegistryHive,
+ ULONG Operation,
+ ULONG_PTR ChunkBase,
+ SIZE_T ChunkSize,
+ PHV_ALLOCATE Allocate,
+ PHV_FREE Free,
+ PHV_FILE_READ FileRead,
+ PHV_FILE_WRITE FileWrite,
+ PHV_FILE_SET_SIZE FileSetSize,
+ PHV_FILE_FLUSH FileFlush,
+ PVOID Opaque)
+{
+ NTSTATUS Status;
+ PREGISTRY_HIVE Hive;
+
+ /*
+ * Create a new hive structure that will hold all the maintenance data.
+ */
+
+ Hive = Allocate(sizeof(REGISTRY_HIVE), TRUE);
+ if (Hive == NULL)
+ return STATUS_NO_MEMORY;
+ RtlZeroMemory(Hive, sizeof(REGISTRY_HIVE));
+
+ Hive->Allocate = Allocate;
+ Hive->Free = Free;
+ Hive->FileRead = FileRead;
+ Hive->FileWrite = FileWrite;
+ Hive->FileSetSize = FileSetSize;
+ Hive->FileFlush = FileFlush;
+ Hive->Opaque = Opaque;
+
+ switch (Operation)
+ {
+ case HV_OPERATION_CREATE_HIVE:
+ Status = HvpCreateHive(Hive);
+ break;
+
+ case HV_OPERATION_MEMORY:
+ Status = HvpInitializeMemoryHive(Hive, ChunkBase, ChunkSize);
+ break;
+
+ case HV_OPERATION_MEMORY_INPLACE:
+ Status = HvpInitializeMemoryInplaceHive(Hive, ChunkBase, ChunkSize);
+ break;
+
+ default:
+ /* FIXME: A better return status value is needed */
+ Status = STATUS_NOT_IMPLEMENTED;
+ ASSERT(FALSE);
+ }
+
+ if (!NT_SUCCESS(Status))
+ {
+ Hive->Free(Hive);
+ return Status;
+ }
+
+ *RegistryHive = Hive;
+
+ return Status;
+}
+
+/**
+ * @name HvFree
+ *
+ * Free all stroage and handles associated with hive descriptor.
+ */
+
+VOID CMAPI
+HvFree(
+ PREGISTRY_HIVE RegistryHive)
+{
+ if (!RegistryHive->ReadOnly)
+ {
+ /* Release hive bitmap */
+ if (RegistryHive->DirtyBitmap.Buffer)
+ {
+ RegistryHive->Free(RegistryHive->DirtyBitmap.Buffer);
+ }
+
+ HvpFreeHiveBins(RegistryHive);
+ }
+
+ RegistryHive->Free(RegistryHive);
+}
+
+/* EOF */
Added: trunk/reactos/lib/cmlib/hivesum.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/cmlib/hivesum.c?rev=23…
==============================================================================
--- trunk/reactos/lib/cmlib/hivesum.c (added)
+++ trunk/reactos/lib/cmlib/hivesum.c Sat Jul 29 00:50:05 2006
@@ -1,0 +1,32 @@
+/*
+ * PROJECT: registry manipulation library
+ * LICENSE: GPL - See COPYING in the top level directory
+ * COPYRIGHT: Copyright 2005 Filip Navara <navaraf(a)reactos.org>
+ * Copyright 2001 - 2005 Eric Kohl
+ */
+
+#include "cmlib.h"
+
+/**
+ * @name HvpHiveHeaderChecksum
+ *
+ * Compute checksum of hive header and return it.
+ */
+
+ULONG CMAPI
+HvpHiveHeaderChecksum(
+ PHIVE_HEADER HiveHeader)
+{
+ PULONG Buffer = (PULONG)HiveHeader;
+ ULONG Sum = 0;
+ ULONG i;
+
+ for (i = 0; i < 127; i++)
+ Sum ^= Buffer[i];
+ if (Sum == (ULONG)-1)
+ Sum = (ULONG)-2;
+ if (Sum == 0)
+ Sum = 1;
+
+ return Sum;
+}
Added: trunk/reactos/lib/cmlib/hivewrt.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/cmlib/hivewrt.c?rev=23…
==============================================================================
--- trunk/reactos/lib/cmlib/hivewrt.c (added)
+++ trunk/reactos/lib/cmlib/hivewrt.c Sat Jul 29 00:50:05 2006
@@ -1,0 +1,277 @@
+/*
+ * PROJECT: registry manipulation library
+ * LICENSE: GPL - See COPYING in the top level directory
+ * COPYRIGHT: Copyright 2005 Filip Navara <navaraf(a)reactos.org>
+ * Copyright 2001 - 2005 Eric Kohl
+ */
+
+#include "cmlib.h"
+#define NDEBUG
+#include <debug.h>
+
+static BOOLEAN CMAPI
+HvpWriteLog(
+ PREGISTRY_HIVE RegistryHive)
+{
+ ULONG FileOffset;
+ ULONG BufferSize;
+ ULONG BitmapSize;
+ PUCHAR Buffer;
+ PUCHAR Ptr;
+ ULONG BlockIndex;
+ ULONG LastIndex;
+ PVOID BlockPtr;
+ BOOLEAN Success;
+
+ ASSERT(RegistryHive->ReadOnly == FALSE);
+
+ DPRINT("HvpWriteLog called\n");
+
+ if (RegistryHive->HiveHeader->Sequence1 !=
+ RegistryHive->HiveHeader->Sequence2)
+ {
+ return FALSE;
+ }
+
+ BitmapSize = RegistryHive->DirtyBitmap.SizeOfBitMap;
+ BufferSize = HV_LOG_HEADER_SIZE + sizeof(ULONG) + BitmapSize;
+ BufferSize = ROUND_UP(BufferSize, HV_BLOCK_SIZE);
+
+ DPRINT("Bitmap size %lu buffer size: %lu\n", BitmapSize, BufferSize);
+
+ Buffer = RegistryHive->Allocate(BufferSize, TRUE);
+ if (Buffer == NULL)
+ {
+ return FALSE;
+ }
+
+ /* Update first update counter and checksum */
+ RegistryHive->HiveHeader->Type = HV_TYPE_LOG;
+ RegistryHive->HiveHeader->Sequence1++;
+ RegistryHive->HiveHeader->Checksum =
+ HvpHiveHeaderChecksum(RegistryHive->HiveHeader);
+
+ /* Copy hive header */
+ RtlCopyMemory(Buffer, RegistryHive->HiveHeader, HV_LOG_HEADER_SIZE);
+ Ptr = Buffer + HV_LOG_HEADER_SIZE;
+ RtlCopyMemory(Ptr, "DIRT", 4);
+ Ptr += 4;
+ RtlCopyMemory(Ptr, RegistryHive->DirtyBitmap.Buffer, BitmapSize);
+
+ /* Write hive block and block bitmap */
+ Success = RegistryHive->FileWrite(RegistryHive, HV_TYPE_LOG,
+ 0, Buffer, BufferSize);
+ if (!Success)
+ {
+ return FALSE;
+ }
+
+ RegistryHive->Free(Buffer);
+
+ /* Write dirty blocks */
+ FileOffset = BufferSize;
+ BlockIndex = 0;
+ while (BlockIndex < RegistryHive->Storage[HvStable].BlockListSize)
+ {
+ LastIndex = BlockIndex;
+ BlockIndex = RtlFindSetBits(&RegistryHive->DirtyBitmap, 1, BlockIndex);
+ if (BlockIndex == ~0 || BlockIndex < LastIndex)
+ {
+ break;
+ }
+
+ BlockPtr = RegistryHive->Storage[HvStable].BlockList[BlockIndex].Block;
+
+ /* Write hive block */
+ Success = RegistryHive->FileWrite(RegistryHive, HV_TYPE_LOG,
+ FileOffset, BlockPtr,
+ HV_BLOCK_SIZE);
+ if (!Success)
+ {
+ return FALSE;
+ }
+
+ BlockIndex++;
+ FileOffset += HV_BLOCK_SIZE;
+ }
+
+ Success = RegistryHive->FileSetSize(RegistryHive, HV_TYPE_LOG, FileOffset);
+ if (!Success)
+ {
+ DPRINT("FileSetSize failed\n");
+ return FALSE;
+ }
+
+ /* Flush the log file */
+ Success = RegistryHive->FileFlush(RegistryHive, HV_TYPE_LOG);
+ if (!Success)
+ {
+ DPRINT("FileFlush failed\n");
+ }
+
+ /* Update first and second update counter and checksum. */
+ RegistryHive->HiveHeader->Sequence2++;
+ RegistryHive->HiveHeader->Checksum =
+ HvpHiveHeaderChecksum(RegistryHive->HiveHeader);
+
+ /* Write hive header again with updated sequence counter. */
+ Success = RegistryHive->FileWrite(RegistryHive, HV_TYPE_LOG,
+ 0, RegistryHive->HiveHeader,
+ HV_LOG_HEADER_SIZE);
+ if (!Success)
+ {
+ return FALSE;
+ }
+
+ /* Flush the log file */
+ Success = RegistryHive->FileFlush(RegistryHive, HV_TYPE_LOG);
+ if (!Success)
+ {
+ DPRINT("FileFlush failed\n");
+ }
+
+ return TRUE;
+}
+
+static BOOLEAN CMAPI
+HvpWriteHive(
+ PREGISTRY_HIVE RegistryHive,
+ BOOLEAN OnlyDirty)
+{
+ ULONG FileOffset;
+ ULONG BlockIndex;
+ ULONG LastIndex;
+ PVOID BlockPtr;
+ BOOLEAN Success;
+
+ ASSERT(RegistryHive->ReadOnly == FALSE);
+
+ DPRINT("HvpWriteHive called\n");
+
+ if (RegistryHive->HiveHeader->Sequence1 !=
+ RegistryHive->HiveHeader->Sequence2)
+ {
+ return FALSE;
+ }
+
+ /* Update first update counter and checksum */
+ RegistryHive->HiveHeader->Type = HV_TYPE_PRIMARY;
+ RegistryHive->HiveHeader->Sequence1++;
+ RegistryHive->HiveHeader->Checksum =
+ HvpHiveHeaderChecksum(RegistryHive->HiveHeader);
+
+ /* Write hive block */
+ Success = RegistryHive->FileWrite(RegistryHive, HV_TYPE_PRIMARY,
+ 0, RegistryHive->HiveHeader,
+ sizeof(HIVE_HEADER));
+ if (!Success)
+ {
+ return FALSE;
+ }
+
+ BlockIndex = 0;
+ while (BlockIndex < RegistryHive->Storage[HvStable].BlockListSize)
+ {
+ if (OnlyDirty)
+ {
+ LastIndex = BlockIndex;
+ BlockIndex = RtlFindSetBits(&RegistryHive->DirtyBitmap, 1, BlockIndex);
+ if (BlockIndex == ~0 || BlockIndex < LastIndex)
+ {
+ break;
+ }
+ }
+
+ BlockPtr = RegistryHive->Storage[HvStable].BlockList[BlockIndex].Block;
+ FileOffset = (ULONGLONG)(BlockIndex + 1) * (ULONGLONG)HV_BLOCK_SIZE;
+
+ /* Write hive block */
+ Success = RegistryHive->FileWrite(RegistryHive, HV_TYPE_PRIMARY,
+ FileOffset, BlockPtr,
+ HV_BLOCK_SIZE);
+ if (!Success)
+ {
+ return FALSE;
+ }
+
+ BlockIndex++;
+ }
+
+ Success = RegistryHive->FileFlush(RegistryHive, HV_TYPE_PRIMARY);
+ if (!Success)
+ {
+ DPRINT("FileFlush failed\n");
+ }
+
+ /* Update second update counter and checksum */
+ RegistryHive->HiveHeader->Sequence2++;
+ RegistryHive->HiveHeader->Checksum =
+ HvpHiveHeaderChecksum(RegistryHive->HiveHeader);
+
+ /* Write hive block */
+ Success = RegistryHive->FileWrite(RegistryHive, HV_TYPE_PRIMARY,
+ 0, RegistryHive->HiveHeader,
+ sizeof(HIVE_HEADER));
+ if (!Success)
+ {
+ return FALSE;
+ }
+
+ Success = RegistryHive->FileFlush(RegistryHive, HV_TYPE_PRIMARY);
+ if (!Success)
+ {
+ DPRINT("FileFlush failed\n");
+ }
+
+ return TRUE;
+}
+
+BOOLEAN CMAPI
+HvSyncHive(
+ PREGISTRY_HIVE RegistryHive)
+{
+ ASSERT(RegistryHive->ReadOnly == FALSE);
+
+ if (RtlFindSetBits(&RegistryHive->DirtyBitmap, 1, 0) == ~0)
+ {
+ return TRUE;
+ }
+
+ /* Update hive header modification time */
+ KeQuerySystemTime(&RegistryHive->HiveHeader->TimeStamp);
+
+ /* Update log file */
+ if (!HvpWriteLog(RegistryHive))
+ {
+ return FALSE;
+ }
+
+ /* Update hive file */
+ if (!HvpWriteHive(RegistryHive, TRUE))
+ {
+ return FALSE;
+ }
+
+ /* Clear dirty bitmap. */
+ RtlClearAllBits(&RegistryHive->DirtyBitmap);
+
+ return TRUE;
+}
+
+BOOLEAN CMAPI
+HvWriteHive(
+ PREGISTRY_HIVE RegistryHive)
+{
+ ASSERT(RegistryHive->ReadOnly == FALSE);
+
+ /* Update hive header modification time */
+ KeQuerySystemTime(&RegistryHive->HiveHeader->TimeStamp);
+
+ /* Update hive file */
+ if (!HvpWriteHive(RegistryHive, FALSE))
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}