mirror of
https://github.com/reactos/reactos.git
synced 2024-10-15 13:45:58 +00:00
Actually add cmlib itself
svn path=/trunk/; revision=23336
This commit is contained in:
parent
d01cb10386
commit
793b990edb
134
reactos/lib/cmlib/cmdata.h
Normal file
134
reactos/lib/cmlib/cmdata.h
Normal file
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* PROJECT: registry manipulation library
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* COPYRIGHT: Copyright 2005 Filip Navara <navaraf@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 */
|
82
reactos/lib/cmlib/cminit.c
Normal file
82
reactos/lib/cmlib/cminit.c
Normal file
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* PROJECT: registry manipulation library
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* COPYRIGHT: Copyright 2005 Filip Navara <navaraf@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);
|
||||
}
|
175
reactos/lib/cmlib/cmlib.h
Normal file
175
reactos/lib/cmlib/cmlib.h
Normal file
|
@ -0,0 +1,175 @@
|
|||
/*
|
||||
* PROJECT: registry manipulation library
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* COPYRIGHT: Copyright 2005 Filip Navara <navaraf@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 */
|
55
reactos/lib/cmlib/cmlib.mak
Normal file
55
reactos/lib/cmlib/cmlib.mak
Normal file
|
@ -0,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
|
14
reactos/lib/cmlib/cmlib.rbuild
Normal file
14
reactos/lib/cmlib/cmlib.rbuild
Normal file
|
@ -0,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>
|
98
reactos/lib/cmlib/hivebin.c
Normal file
98
reactos/lib/cmlib/hivebin.c
Normal file
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* PROJECT: registry manipulation library
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* COPYRIGHT: Copyright 2005 Filip Navara <navaraf@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;
|
||||
}
|
429
reactos/lib/cmlib/hivecell.c
Normal file
429
reactos/lib/cmlib/hivecell.c
Normal file
|
@ -0,0 +1,429 @@
|
|||
/*
|
||||
* PROJECT: registry manipulation library
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* COPYRIGHT: Copyright 2005 Filip Navara <navaraf@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);
|
||||
}
|
138
reactos/lib/cmlib/hivedata.h
Normal file
138
reactos/lib/cmlib/hivedata.h
Normal file
|
@ -0,0 +1,138 @@
|
|||
/*
|
||||
* PROJECT: registry manipulation library
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* COPYRIGHT: Copyright 2005 Filip Navara <navaraf@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 */
|
377
reactos/lib/cmlib/hiveinit.c
Normal file
377
reactos/lib/cmlib/hiveinit.c
Normal file
|
@ -0,0 +1,377 @@
|
|||
/*
|
||||
* PROJECT: registry manipulation library
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* COPYRIGHT: Copyright 2005 Filip Navara <navaraf@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 */
|
32
reactos/lib/cmlib/hivesum.c
Normal file
32
reactos/lib/cmlib/hivesum.c
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* PROJECT: registry manipulation library
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* COPYRIGHT: Copyright 2005 Filip Navara <navaraf@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;
|
||||
}
|
277
reactos/lib/cmlib/hivewrt.c
Normal file
277
reactos/lib/cmlib/hivewrt.c
Normal file
|
@ -0,0 +1,277 @@
|
|||
/*
|
||||
* PROJECT: registry manipulation library
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* COPYRIGHT: Copyright 2005 Filip Navara <navaraf@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;
|
||||
}
|
Loading…
Reference in a new issue