mirror of
https://github.com/reactos/reactos.git
synced 2025-08-07 07:03:06 +00:00
Create a branch for cmake bringup.
svn path=/branches/cmake-bringup/; revision=48236
This commit is contained in:
parent
a28e798006
commit
c424146e2c
20602 changed files with 0 additions and 1140137 deletions
210
lib/cmlib/cmdata.h
Normal file
210
lib/cmlib/cmdata.h
Normal file
|
@ -0,0 +1,210 @@
|
|||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#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
|
||||
|
||||
//
|
||||
// Key Types
|
||||
//
|
||||
#define CM_KEY_INDEX_ROOT 0x6972
|
||||
#define CM_KEY_INDEX_LEAF 0x696c
|
||||
#define CM_KEY_FAST_LEAF 0x666c
|
||||
#define CM_KEY_HASH_LEAF 0x686c
|
||||
|
||||
//
|
||||
// Key Signatures
|
||||
//
|
||||
#define CM_KEY_NODE_SIGNATURE 0x6B6E
|
||||
#define CM_LINK_NODE_SIGNATURE 0x6B6C
|
||||
#define CM_KEY_VALUE_SIGNATURE 0x6B76
|
||||
|
||||
//
|
||||
// CM_KEY_NODE Flags
|
||||
//
|
||||
#define KEY_IS_VOLATILE 0x01
|
||||
#define KEY_HIVE_EXIT 0x02
|
||||
#define KEY_HIVE_ENTRY 0x04
|
||||
#define KEY_NO_DELETE 0x08
|
||||
#define KEY_SYM_LINK 0x10
|
||||
#define KEY_COMP_NAME 0x20
|
||||
#define KEY_PREFEF_HANDLE 0x40
|
||||
#define KEY_VIRT_MIRRORED 0x80
|
||||
#define KEY_VIRT_TARGET 0x100
|
||||
#define KEY_VIRTUAL_STORE 0x200
|
||||
|
||||
//
|
||||
// CM_KEY_VALUE Flags
|
||||
//
|
||||
#define VALUE_COMP_NAME 0x0001
|
||||
|
||||
#ifdef CMLIB_HOST
|
||||
#include <host/pshpack1.h>
|
||||
#else
|
||||
#include <pshpack1.h>
|
||||
#endif
|
||||
|
||||
//
|
||||
// For memory-mapped Hives
|
||||
//
|
||||
typedef struct _CM_VIEW_OF_FILE
|
||||
{
|
||||
LIST_ENTRY LRUViewList;
|
||||
LIST_ENTRY PinViewList;
|
||||
ULONG FileOffset;
|
||||
ULONG Size;
|
||||
PULONG ViewAddress;
|
||||
PVOID Bcb;
|
||||
ULONG UseCount;
|
||||
} CM_VIEW_OF_FILE, *PCM_VIEW_OF_FILE;
|
||||
|
||||
//
|
||||
// Children of Key Notes
|
||||
//
|
||||
typedef struct _CHILD_LIST
|
||||
{
|
||||
ULONG Count;
|
||||
HCELL_INDEX List;
|
||||
} CHILD_LIST, *PCHILD_LIST;
|
||||
|
||||
//
|
||||
// Node Key Reference to Parents
|
||||
//
|
||||
typedef struct _CM_KEY_REFERENCE
|
||||
{
|
||||
HCELL_INDEX KeyCell;
|
||||
PHHIVE KeyHive;
|
||||
} CM_KEY_REFERENCE, *PCM_KEY_REFERENCE;
|
||||
|
||||
//
|
||||
// Node Key
|
||||
//
|
||||
typedef struct _CM_KEY_NODE
|
||||
{
|
||||
USHORT Signature;
|
||||
USHORT Flags;
|
||||
LARGE_INTEGER LastWriteTime;
|
||||
ULONG Spare;
|
||||
HCELL_INDEX Parent;
|
||||
ULONG SubKeyCounts[HTYPE_COUNT];
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
HCELL_INDEX SubKeyLists[HTYPE_COUNT];
|
||||
CHILD_LIST ValueList;
|
||||
};
|
||||
CM_KEY_REFERENCE ChildHiveReference;
|
||||
};
|
||||
HCELL_INDEX Security;
|
||||
HCELL_INDEX Class;
|
||||
ULONG MaxNameLen;
|
||||
ULONG MaxClassLen;
|
||||
ULONG MaxValueNameLen;
|
||||
ULONG MaxValueDataLen;
|
||||
ULONG WorkVar;
|
||||
USHORT NameLength;
|
||||
USHORT ClassLength;
|
||||
WCHAR Name[ANYSIZE_ARRAY];
|
||||
} CM_KEY_NODE, *PCM_KEY_NODE;
|
||||
|
||||
//
|
||||
// Value List
|
||||
//
|
||||
typedef struct _VALUE_LIST_CELL
|
||||
{
|
||||
HCELL_INDEX ValueOffset[ANYSIZE_ARRAY];
|
||||
} VALUE_LIST_CELL, *PVALUE_LIST_CELL;
|
||||
|
||||
//
|
||||
// Value Key
|
||||
//
|
||||
typedef struct _CM_KEY_VALUE
|
||||
{
|
||||
USHORT Signature;
|
||||
USHORT NameLength;
|
||||
ULONG DataLength;
|
||||
HCELL_INDEX Data;
|
||||
ULONG Type;
|
||||
USHORT Flags;
|
||||
USHORT Unused1;
|
||||
WCHAR Name[ANYSIZE_ARRAY];
|
||||
} CM_KEY_VALUE, *PCM_KEY_VALUE;
|
||||
|
||||
//
|
||||
// Security Key
|
||||
//
|
||||
typedef struct _CM_KEY_SECURITY
|
||||
{
|
||||
USHORT Signature;
|
||||
USHORT Reserved;
|
||||
HCELL_INDEX Flink;
|
||||
HCELL_INDEX Blink;
|
||||
ULONG ReferenceCount;
|
||||
ULONG DescriptorLength;
|
||||
//SECURITY_DESCRIPTOR_RELATIVE Descriptor;
|
||||
UCHAR Data[ANYSIZE_ARRAY];
|
||||
} CM_KEY_SECURITY, *PCM_KEY_SECURITY;
|
||||
|
||||
#ifdef CMLIB_HOST
|
||||
#include <host/poppack.h>
|
||||
#else
|
||||
#include <poppack.h>
|
||||
#endif
|
||||
|
||||
//
|
||||
// Generic Index Entry
|
||||
//
|
||||
typedef struct _CM_INDEX
|
||||
{
|
||||
HCELL_INDEX Cell;
|
||||
union
|
||||
{
|
||||
UCHAR NameHint[4];
|
||||
ULONG HashKey;
|
||||
};
|
||||
} CM_INDEX, *PCM_INDEX;
|
||||
|
||||
//
|
||||
// Key Index
|
||||
//
|
||||
typedef struct _CM_KEY_INDEX
|
||||
{
|
||||
USHORT Signature;
|
||||
USHORT Count;
|
||||
HCELL_INDEX List[ANYSIZE_ARRAY];
|
||||
} CM_KEY_INDEX, *PCM_KEY_INDEX;
|
||||
|
||||
//
|
||||
// Fast/Hash Key Index
|
||||
//
|
||||
typedef struct _CM_KEY_FAST_INDEX
|
||||
{
|
||||
USHORT Signature;
|
||||
USHORT Count;
|
||||
CM_INDEX List[ANYSIZE_ARRAY];
|
||||
} CM_KEY_FAST_INDEX, *PCM_KEY_FAST_INDEX;
|
||||
|
||||
//
|
||||
// Cell Data
|
||||
//
|
||||
typedef struct _CELL_DATA
|
||||
{
|
||||
union
|
||||
{
|
||||
CM_KEY_NODE KeyNode;
|
||||
CM_KEY_VALUE KeyValue;
|
||||
CM_KEY_SECURITY KeySecurity;
|
||||
CM_KEY_INDEX KeyIndex;
|
||||
HCELL_INDEX KeyList[ANYSIZE_ARRAY];
|
||||
WCHAR KeyString[ANYSIZE_ARRAY];
|
||||
} u;
|
||||
} CELL_DATA, *PCELL_DATA;
|
136
lib/cmlib/cminit.c
Normal file
136
lib/cmlib/cminit.c
Normal file
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* 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>
|
||||
|
||||
ULONG CmlibTraceLevel = 0;
|
||||
|
||||
BOOLEAN CMAPI
|
||||
CmCreateRootNode(
|
||||
PHHIVE Hive,
|
||||
PCWSTR Name)
|
||||
{
|
||||
PCM_KEY_NODE KeyCell;
|
||||
HCELL_INDEX RootCellIndex;
|
||||
SIZE_T NameSize;
|
||||
|
||||
/* Allocate the cell */
|
||||
NameSize = strlenW(Name) * sizeof(WCHAR);
|
||||
RootCellIndex = HvAllocateCell(Hive,
|
||||
FIELD_OFFSET(CM_KEY_NODE, Name) + NameSize,
|
||||
Stable,
|
||||
HCELL_NIL);
|
||||
if (RootCellIndex == HCELL_NIL) return FALSE;
|
||||
|
||||
/* Seutp the base block */
|
||||
Hive->BaseBlock->RootCell = RootCellIndex;
|
||||
Hive->BaseBlock->CheckSum = HvpHiveHeaderChecksum(Hive->BaseBlock);
|
||||
|
||||
/* Get the key cell */
|
||||
KeyCell = (PCM_KEY_NODE)HvGetCell(Hive, RootCellIndex);
|
||||
if (!KeyCell) return FALSE;
|
||||
|
||||
/* Setup the cell */
|
||||
KeyCell->Signature = (USHORT)CM_KEY_NODE_SIGNATURE;
|
||||
KeyCell->Flags = KEY_HIVE_ENTRY | KEY_NO_DELETE;
|
||||
KeyCell->LastWriteTime.QuadPart = 0;
|
||||
KeyCell->Parent = HCELL_NIL;
|
||||
KeyCell->SubKeyCounts[Stable] = 0;
|
||||
KeyCell->SubKeyCounts[Volatile] = 0;
|
||||
KeyCell->SubKeyLists[Stable] = HCELL_NIL;
|
||||
KeyCell->SubKeyLists[Volatile] = HCELL_NIL;
|
||||
KeyCell->ValueList.Count = 0;
|
||||
KeyCell->ValueList.List = HCELL_NIL;
|
||||
KeyCell->Security = HCELL_NIL;
|
||||
KeyCell->Class = HCELL_NIL;
|
||||
KeyCell->ClassLength = 0;
|
||||
KeyCell->MaxNameLen = 0;
|
||||
KeyCell->MaxClassLen = 0;
|
||||
KeyCell->MaxValueNameLen = 0;
|
||||
KeyCell->MaxValueDataLen = 0;
|
||||
|
||||
/* Write the name */
|
||||
KeyCell->NameLength = (USHORT)NameSize;
|
||||
memcpy(KeyCell->Name, Name, NameSize);
|
||||
|
||||
/* Return success */
|
||||
HvReleaseCell(Hive, RootCellIndex);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static VOID CMAPI
|
||||
CmpPrepareKey(
|
||||
PHHIVE RegistryHive,
|
||||
PCM_KEY_NODE KeyCell);
|
||||
|
||||
static VOID CMAPI
|
||||
CmpPrepareIndexOfKeys(
|
||||
PHHIVE RegistryHive,
|
||||
PCM_KEY_INDEX IndexCell)
|
||||
{
|
||||
ULONG i;
|
||||
|
||||
if (IndexCell->Signature == CM_KEY_INDEX_ROOT ||
|
||||
IndexCell->Signature == CM_KEY_INDEX_LEAF)
|
||||
{
|
||||
for (i = 0; i < IndexCell->Count; i++)
|
||||
{
|
||||
PCM_KEY_INDEX SubIndexCell = HvGetCell(RegistryHive, IndexCell->List[i]);
|
||||
if (SubIndexCell->Signature == CM_KEY_NODE_SIGNATURE)
|
||||
CmpPrepareKey(RegistryHive, (PCM_KEY_NODE)SubIndexCell);
|
||||
else
|
||||
CmpPrepareIndexOfKeys(RegistryHive, SubIndexCell);
|
||||
}
|
||||
}
|
||||
else if (IndexCell->Signature == CM_KEY_FAST_LEAF ||
|
||||
IndexCell->Signature == CM_KEY_HASH_LEAF)
|
||||
{
|
||||
PCM_KEY_FAST_INDEX HashCell = (PCM_KEY_FAST_INDEX)IndexCell;
|
||||
for (i = 0; i < HashCell->Count; i++)
|
||||
{
|
||||
PCM_KEY_NODE SubKeyCell = HvGetCell(RegistryHive, HashCell->List[i].Cell);
|
||||
CmpPrepareKey(RegistryHive, SubKeyCell);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT1("IndexCell->Signature %x\n", IndexCell->Signature);
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
static VOID CMAPI
|
||||
CmpPrepareKey(
|
||||
PHHIVE RegistryHive,
|
||||
PCM_KEY_NODE KeyCell)
|
||||
{
|
||||
PCM_KEY_INDEX IndexCell;
|
||||
|
||||
ASSERT(KeyCell->Signature == CM_KEY_NODE_SIGNATURE);
|
||||
|
||||
KeyCell->SubKeyLists[Volatile] = HCELL_NIL;
|
||||
KeyCell->SubKeyCounts[Volatile] = 0;
|
||||
|
||||
/* Enumerate and add subkeys */
|
||||
if (KeyCell->SubKeyCounts[Stable] > 0)
|
||||
{
|
||||
IndexCell = HvGetCell(RegistryHive, KeyCell->SubKeyLists[Stable]);
|
||||
CmpPrepareIndexOfKeys(RegistryHive, IndexCell);
|
||||
}
|
||||
}
|
||||
|
||||
VOID CMAPI
|
||||
CmPrepareHive(
|
||||
PHHIVE RegistryHive)
|
||||
{
|
||||
PCM_KEY_NODE RootCell;
|
||||
|
||||
RootCell = HvGetCell(RegistryHive, RegistryHive->BaseBlock->RootCell);
|
||||
CmpPrepareKey(RegistryHive, RootCell);
|
||||
}
|
346
lib/cmlib/cmlib.h
Normal file
346
lib/cmlib/cmlib.h
Normal file
|
@ -0,0 +1,346 @@
|
|||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
//
|
||||
// Debug support switch
|
||||
//
|
||||
#define _CMLIB_DEBUG_ 1
|
||||
|
||||
#ifdef CMLIB_HOST
|
||||
#include <wine/unicode.h>
|
||||
#include <host/typedefs.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
// Definitions copied from <ntstatus.h>
|
||||
// We only want to include host headers, so we define them manually
|
||||
#define STATUS_SUCCESS ((NTSTATUS)0x00000000)
|
||||
#define STATUS_NOT_IMPLEMENTED ((NTSTATUS)0xC0000002)
|
||||
#define STATUS_NO_MEMORY ((NTSTATUS)0xC0000017)
|
||||
#define STATUS_INSUFFICIENT_RESOURCES ((NTSTATUS)0xC000009A)
|
||||
#define STATUS_REGISTRY_CORRUPT ((NTSTATUS)0xC000014C)
|
||||
#define STATUS_NOT_REGISTRY_FILE ((NTSTATUS)0xC000015C)
|
||||
#define STATUS_REGISTRY_RECOVERED ((NTSTATUS)0x40000009)
|
||||
|
||||
#define REG_OPTION_VOLATILE 1
|
||||
#define OBJ_CASE_INSENSITIVE 0x00000040L
|
||||
#define USHORT_MAX USHRT_MAX
|
||||
|
||||
VOID NTAPI
|
||||
KeQuerySystemTime(
|
||||
OUT PLARGE_INTEGER CurrentTime);
|
||||
|
||||
VOID NTAPI
|
||||
RtlInitializeBitMap(
|
||||
IN PRTL_BITMAP BitMapHeader,
|
||||
IN PULONG BitMapBuffer,
|
||||
IN ULONG SizeOfBitMap);
|
||||
|
||||
ULONG NTAPI
|
||||
RtlFindSetBits(
|
||||
IN PRTL_BITMAP BitMapHeader,
|
||||
IN ULONG NumberToFind,
|
||||
IN ULONG HintIndex);
|
||||
|
||||
VOID NTAPI
|
||||
RtlSetBits(
|
||||
IN PRTL_BITMAP BitMapHeader,
|
||||
IN ULONG StartingIndex,
|
||||
IN ULONG NumberToSet);
|
||||
|
||||
VOID NTAPI
|
||||
RtlClearAllBits(
|
||||
IN PRTL_BITMAP BitMapHeader);
|
||||
|
||||
#define RtlCheckBit(BMH,BP) (((((PLONG)(BMH)->Buffer)[(BP) / 32]) >> ((BP) % 32)) & 0x1)
|
||||
#define UNREFERENCED_PARAMETER(P) {(P)=(P);}
|
||||
|
||||
#define PKTHREAD PVOID
|
||||
#define PKGUARDED_MUTEX PVOID
|
||||
#define PERESOURCE PVOID
|
||||
#define PFILE_OBJECT PVOID
|
||||
#define PKEVENT PVOID
|
||||
#define PWORK_QUEUE_ITEM PVOID
|
||||
#define EX_PUSH_LOCK PULONG_PTR
|
||||
|
||||
/* For <host/wcsfuncs.h> */
|
||||
#define USE_HOST_WCSFUNCS
|
||||
|
||||
#define CMLTRACE(x, ...)
|
||||
#else
|
||||
//
|
||||
// Debug/Tracing support
|
||||
//
|
||||
#if _CMLIB_DEBUG_
|
||||
#ifdef NEW_DEBUG_SYSTEM_IMPLEMENTED // enable when Debug Filters are implemented
|
||||
#define CMLTRACE DbgPrintEx
|
||||
#else
|
||||
#define CMLTRACE(x, ...) \
|
||||
if (x & CmlibTraceLevel) DbgPrint(__VA_ARGS__)
|
||||
#endif
|
||||
#else
|
||||
#define CMLTRACE(x, ...) DPRINT(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#include <ntdef.h>
|
||||
#undef DECLSPEC_IMPORT
|
||||
#define DECLSPEC_IMPORT
|
||||
#include <ntddk.h>
|
||||
#endif
|
||||
|
||||
#include <host/wcsfuncs.h>
|
||||
|
||||
//
|
||||
// These define the Debug Masks Supported
|
||||
//
|
||||
#define CMLIB_HCELL_DEBUG 0x01
|
||||
|
||||
#ifndef ROUND_UP
|
||||
#define ROUND_UP(a,b) ((((a)+(b)-1)/(b))*(b))
|
||||
#define ROUND_DOWN(a,b) (((a)/(b))*(b))
|
||||
#endif
|
||||
|
||||
//
|
||||
// PAGE_SIZE definition
|
||||
//
|
||||
#ifndef PAGE_SIZE
|
||||
#if defined(TARGET_i386) || defined(TARGET_amd64) || defined(TARGET_arm)
|
||||
#define PAGE_SIZE 0x1000
|
||||
#else
|
||||
#error Local PAGE_SIZE definition required when built as host
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define TAG_CM 0x68742020
|
||||
|
||||
#define CMAPI NTAPI
|
||||
|
||||
#include <wchar.h>
|
||||
#include "hivedata.h"
|
||||
#include "cmdata.h"
|
||||
|
||||
#if defined(_TYPEDEFS_HOST_H) || defined(__FREELDR_H)
|
||||
|
||||
#define PCM_KEY_SECURITY_CACHE_ENTRY PVOID
|
||||
#define PCM_KEY_CONTROL_BLOCK PVOID
|
||||
#define CMP_SECURITY_HASH_LISTS 64
|
||||
#define PCM_CELL_REMAP_BLOCK PVOID
|
||||
|
||||
//
|
||||
// Use Count Log and Entry
|
||||
//
|
||||
typedef struct _CM_USE_COUNT_LOG_ENTRY
|
||||
{
|
||||
HCELL_INDEX Cell;
|
||||
PVOID Stack[7];
|
||||
} CM_USE_COUNT_LOG_ENTRY, *PCM_USE_COUNT_LOG_ENTRY;
|
||||
|
||||
typedef struct _CM_USE_COUNT_LOG
|
||||
{
|
||||
USHORT Next;
|
||||
USHORT Size;
|
||||
CM_USE_COUNT_LOG_ENTRY Log[32];
|
||||
} CM_USE_COUNT_LOG, *PCM_USE_COUNT_LOG;
|
||||
|
||||
//
|
||||
// Configuration Manager Hive Structure
|
||||
//
|
||||
typedef struct _CMHIVE
|
||||
{
|
||||
HHIVE Hive;
|
||||
HANDLE FileHandles[3];
|
||||
LIST_ENTRY NotifyList;
|
||||
LIST_ENTRY HiveList;
|
||||
EX_PUSH_LOCK HiveLock;
|
||||
PKTHREAD HiveLockOwner;
|
||||
PKGUARDED_MUTEX ViewLock;
|
||||
PKTHREAD ViewLockOwner;
|
||||
EX_PUSH_LOCK WriterLock;
|
||||
PKTHREAD WriterLockOwner;
|
||||
PERESOURCE FlusherLock;
|
||||
EX_PUSH_LOCK SecurityLock;
|
||||
PKTHREAD HiveSecurityLockOwner;
|
||||
LIST_ENTRY LRUViewListHead;
|
||||
LIST_ENTRY PinViewListHead;
|
||||
PFILE_OBJECT FileObject;
|
||||
UNICODE_STRING FileFullPath;
|
||||
UNICODE_STRING FileUserName;
|
||||
USHORT MappedViews;
|
||||
USHORT PinnedViews;
|
||||
ULONG UseCount;
|
||||
ULONG SecurityCount;
|
||||
ULONG SecurityCacheSize;
|
||||
LONG SecurityHitHint;
|
||||
PCM_KEY_SECURITY_CACHE_ENTRY SecurityCache;
|
||||
LIST_ENTRY SecurityHash[CMP_SECURITY_HASH_LISTS];
|
||||
PKEVENT UnloadEvent;
|
||||
PCM_KEY_CONTROL_BLOCK RootKcb;
|
||||
BOOLEAN Frozen;
|
||||
PWORK_QUEUE_ITEM UnloadWorkItem;
|
||||
BOOLEAN GrowOnlyMode;
|
||||
ULONG GrowOffset;
|
||||
LIST_ENTRY KcbConvertListHead;
|
||||
LIST_ENTRY KnodeConvertListHead;
|
||||
PCM_CELL_REMAP_BLOCK CellRemapArray;
|
||||
CM_USE_COUNT_LOG UseCountLog;
|
||||
CM_USE_COUNT_LOG LockHiveLog;
|
||||
ULONG Flags;
|
||||
LIST_ENTRY TrustClassEntry;
|
||||
ULONG FlushCount;
|
||||
BOOLEAN HiveIsLoading;
|
||||
PKTHREAD CreatorOwner;
|
||||
} CMHIVE, *PCMHIVE;
|
||||
|
||||
#endif
|
||||
|
||||
typedef struct _HV_HIVE_CELL_PAIR
|
||||
{
|
||||
PHHIVE Hive;
|
||||
HCELL_INDEX Cell;
|
||||
} HV_HIVE_CELL_PAIR, *PHV_HIVE_CELL_PAIR;
|
||||
|
||||
#define STATIC_CELL_PAIR_COUNT 4
|
||||
typedef struct _HV_TRACK_CELL_REF
|
||||
{
|
||||
USHORT Count;
|
||||
USHORT Max;
|
||||
PHV_HIVE_CELL_PAIR CellArray;
|
||||
HV_HIVE_CELL_PAIR StaticArray[STATIC_CELL_PAIR_COUNT];
|
||||
USHORT StaticCount;
|
||||
} HV_TRACK_CELL_REF, *PHV_TRACK_CELL_REF;
|
||||
|
||||
extern ULONG CmlibTraceLevel;
|
||||
|
||||
/*
|
||||
* Public functions.
|
||||
*/
|
||||
NTSTATUS CMAPI
|
||||
HvInitialize(
|
||||
PHHIVE RegistryHive,
|
||||
ULONG Operation,
|
||||
ULONG HiveType,
|
||||
ULONG HiveFlags,
|
||||
PVOID HiveData OPTIONAL,
|
||||
PALLOCATE_ROUTINE Allocate,
|
||||
PFREE_ROUTINE Free,
|
||||
PFILE_SET_SIZE_ROUTINE FileSetSize,
|
||||
PFILE_WRITE_ROUTINE FileWrite,
|
||||
PFILE_READ_ROUTINE FileRead,
|
||||
PFILE_FLUSH_ROUTINE FileFlush,
|
||||
ULONG Cluster OPTIONAL,
|
||||
PUNICODE_STRING FileName);
|
||||
|
||||
VOID CMAPI
|
||||
HvFree(
|
||||
PHHIVE RegistryHive);
|
||||
|
||||
PVOID CMAPI
|
||||
HvGetCell(
|
||||
PHHIVE RegistryHive,
|
||||
HCELL_INDEX CellOffset);
|
||||
|
||||
#define HvReleaseCell(h, c) \
|
||||
if (h->ReleaseCellRoutine) h->ReleaseCellRoutine(h, c)
|
||||
|
||||
LONG CMAPI
|
||||
HvGetCellSize(
|
||||
PHHIVE RegistryHive,
|
||||
PVOID Cell);
|
||||
|
||||
HCELL_INDEX CMAPI
|
||||
HvAllocateCell(
|
||||
PHHIVE RegistryHive,
|
||||
SIZE_T Size,
|
||||
HSTORAGE_TYPE Storage,
|
||||
IN HCELL_INDEX Vicinity);
|
||||
|
||||
BOOLEAN CMAPI
|
||||
HvIsCellAllocated(
|
||||
IN PHHIVE RegistryHive,
|
||||
IN HCELL_INDEX CellIndex
|
||||
);
|
||||
|
||||
HCELL_INDEX CMAPI
|
||||
HvReallocateCell(
|
||||
PHHIVE RegistryHive,
|
||||
HCELL_INDEX CellOffset,
|
||||
ULONG Size);
|
||||
|
||||
VOID CMAPI
|
||||
HvFreeCell(
|
||||
PHHIVE RegistryHive,
|
||||
HCELL_INDEX CellOffset);
|
||||
|
||||
BOOLEAN CMAPI
|
||||
HvMarkCellDirty(
|
||||
PHHIVE RegistryHive,
|
||||
HCELL_INDEX CellOffset,
|
||||
BOOLEAN HoldingLock);
|
||||
|
||||
BOOLEAN CMAPI
|
||||
HvIsCellDirty(
|
||||
IN PHHIVE Hive,
|
||||
IN HCELL_INDEX Cell
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
CMAPI
|
||||
HvHiveWillShrink(
|
||||
IN PHHIVE RegistryHive
|
||||
);
|
||||
|
||||
BOOLEAN CMAPI
|
||||
HvSyncHive(
|
||||
PHHIVE RegistryHive);
|
||||
|
||||
BOOLEAN CMAPI
|
||||
HvWriteHive(
|
||||
PHHIVE RegistryHive);
|
||||
|
||||
BOOLEAN CMAPI
|
||||
CmCreateRootNode(
|
||||
PHHIVE Hive,
|
||||
PCWSTR Name);
|
||||
|
||||
VOID CMAPI
|
||||
CmPrepareHive(
|
||||
PHHIVE RegistryHive);
|
||||
|
||||
|
||||
BOOLEAN
|
||||
CMAPI
|
||||
HvTrackCellRef(
|
||||
PHV_TRACK_CELL_REF CellRef,
|
||||
PHHIVE Hive,
|
||||
HCELL_INDEX Cell
|
||||
);
|
||||
|
||||
VOID
|
||||
CMAPI
|
||||
HvReleaseFreeCellRefArray(
|
||||
PHV_TRACK_CELL_REF CellRef
|
||||
);
|
||||
|
||||
/*
|
||||
* Private functions.
|
||||
*/
|
||||
|
||||
PHBIN CMAPI
|
||||
HvpAddBin(
|
||||
PHHIVE RegistryHive,
|
||||
ULONG Size,
|
||||
HSTORAGE_TYPE Storage);
|
||||
|
||||
NTSTATUS CMAPI
|
||||
HvpCreateHiveFreeCellList(
|
||||
PHHIVE Hive);
|
||||
|
||||
ULONG CMAPI
|
||||
HvpHiveHeaderChecksum(
|
||||
PHBASE_BLOCK HiveHeader);
|
36
lib/cmlib/cmlib.rbuild
Normal file
36
lib/cmlib/cmlib.rbuild
Normal file
|
@ -0,0 +1,36 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE module SYSTEM "../../tools/rbuild/project.dtd">
|
||||
<group>
|
||||
<module name="cmlib" type="staticlibrary">
|
||||
<include base="cmlib">.</include>
|
||||
<define name="_NTOSKRNL_" />
|
||||
<define name="_NTSYSTEM_" />
|
||||
<define name="NASSERT" />
|
||||
<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>
|
||||
<module name="cmlibhost" type="hoststaticlibrary">
|
||||
<define name="WINE_UNICODE_API">" "</define>
|
||||
<include base="unicode" />
|
||||
<include base="cmlibhost">.</include>
|
||||
<define name="__NO_CTYPE_INLINES" />
|
||||
<define name="_NTOSKRNL_" />
|
||||
<define name="_NTSYSTEM_" />
|
||||
<define name="NASSERT" />
|
||||
<group compilerset="gcc">
|
||||
<compilerflag>-Wwrite-strings</compilerflag>
|
||||
<compilerflag>-Wpointer-arith</compilerflag>
|
||||
</group>
|
||||
<define name="CMLIB_HOST" />
|
||||
<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>
|
||||
</group>
|
104
lib/cmlib/hivebin.c
Normal file
104
lib/cmlib/hivebin.c
Normal file
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* 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(
|
||||
PHHIVE RegistryHive,
|
||||
ULONG Size,
|
||||
HSTORAGE_TYPE Storage)
|
||||
{
|
||||
PHMAP_ENTRY BlockList;
|
||||
PHBIN Bin;
|
||||
SIZE_T BinSize;
|
||||
ULONG i;
|
||||
ULONG BitmapSize;
|
||||
ULONG BlockCount;
|
||||
ULONG OldBlockListSize;
|
||||
PHCELL Block;
|
||||
|
||||
BinSize = ROUND_UP(Size + sizeof(HBIN), HV_BLOCK_SIZE);
|
||||
BlockCount = (ULONG)(BinSize / HV_BLOCK_SIZE);
|
||||
|
||||
Bin = RegistryHive->Allocate(BinSize, TRUE, TAG_CM);
|
||||
if (Bin == NULL)
|
||||
return NULL;
|
||||
RtlZeroMemory(Bin, BinSize);
|
||||
|
||||
Bin->Signature = HV_BIN_SIGNATURE;
|
||||
Bin->FileOffset = RegistryHive->Storage[Storage].Length *
|
||||
HV_BLOCK_SIZE;
|
||||
Bin->Size = (ULONG)BinSize;
|
||||
|
||||
/* Allocate new block list */
|
||||
OldBlockListSize = RegistryHive->Storage[Storage].Length;
|
||||
BlockList = RegistryHive->Allocate(sizeof(HMAP_ENTRY) *
|
||||
(OldBlockListSize + BlockCount),
|
||||
TRUE,
|
||||
TAG_CM);
|
||||
if (BlockList == NULL)
|
||||
{
|
||||
RegistryHive->Free(Bin, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (OldBlockListSize > 0)
|
||||
{
|
||||
RtlCopyMemory(BlockList, RegistryHive->Storage[Storage].BlockList,
|
||||
OldBlockListSize * sizeof(HMAP_ENTRY));
|
||||
RegistryHive->Free(RegistryHive->Storage[Storage].BlockList, 0);
|
||||
}
|
||||
|
||||
RegistryHive->Storage[Storage].BlockList = BlockList;
|
||||
RegistryHive->Storage[Storage].Length += BlockCount;
|
||||
|
||||
for (i = 0; i < BlockCount; i++)
|
||||
{
|
||||
RegistryHive->Storage[Storage].BlockList[OldBlockListSize + i].BlockAddress =
|
||||
((ULONG_PTR)Bin + (i * HV_BLOCK_SIZE));
|
||||
RegistryHive->Storage[Storage].BlockList[OldBlockListSize + i].BinAddress = (ULONG_PTR)Bin;
|
||||
}
|
||||
|
||||
/* Initialize a free block in this heap. */
|
||||
Block = (PHCELL)(Bin + 1);
|
||||
Block->Size = (LONG)(BinSize - sizeof(HBIN));
|
||||
|
||||
if (Storage == Stable)
|
||||
{
|
||||
/* Calculate bitmap size in bytes (always a multiple of 32 bits). */
|
||||
BitmapSize = ROUND_UP(RegistryHive->Storage[Stable].Length,
|
||||
sizeof(ULONG) * 8) / 8;
|
||||
|
||||
/* Grow bitmap if necessary. */
|
||||
if (BitmapSize > RegistryHive->DirtyVector.SizeOfBitMap / 8)
|
||||
{
|
||||
PULONG BitmapBuffer;
|
||||
|
||||
BitmapBuffer = RegistryHive->Allocate(BitmapSize, TRUE, TAG_CM);
|
||||
RtlZeroMemory(BitmapBuffer, BitmapSize);
|
||||
if (RegistryHive->DirtyVector.SizeOfBitMap > 0)
|
||||
{
|
||||
ASSERT(RegistryHive->DirtyVector.Buffer);
|
||||
RtlCopyMemory(BitmapBuffer,
|
||||
RegistryHive->DirtyVector.Buffer,
|
||||
RegistryHive->DirtyVector.SizeOfBitMap / 8);
|
||||
RegistryHive->Free(RegistryHive->DirtyVector.Buffer, 0);
|
||||
}
|
||||
RtlInitializeBitMap(&RegistryHive->DirtyVector, BitmapBuffer,
|
||||
BitmapSize * 8);
|
||||
}
|
||||
|
||||
/* Mark new bin dirty. */
|
||||
RtlSetBits(&RegistryHive->DirtyVector,
|
||||
Bin->FileOffset / HV_BLOCK_SIZE,
|
||||
BlockCount);
|
||||
}
|
||||
|
||||
return Bin;
|
||||
}
|
580
lib/cmlib/hivecell.c
Normal file
580
lib/cmlib/hivecell.c
Normal file
|
@ -0,0 +1,580 @@
|
|||
/*
|
||||
* 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 __inline PHCELL CMAPI
|
||||
HvpGetCellHeader(
|
||||
PHHIVE RegistryHive,
|
||||
HCELL_INDEX CellIndex)
|
||||
{
|
||||
PVOID Block;
|
||||
|
||||
CMLTRACE(CMLIB_HCELL_DEBUG, "%s - Hive %p, CellIndex %08lx\n",
|
||||
__FUNCTION__, RegistryHive, CellIndex);
|
||||
|
||||
ASSERT(CellIndex != HCELL_NIL);
|
||||
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].Length);
|
||||
Block = (PVOID)RegistryHive->Storage[CellType].BlockList[CellBlock].BlockAddress;
|
||||
ASSERT(Block != NULL);
|
||||
return (PVOID)((ULONG_PTR)Block + CellOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT((CellIndex & HCELL_TYPE_MASK) == Stable);
|
||||
return (PVOID)((ULONG_PTR)RegistryHive->BaseBlock + HV_BLOCK_SIZE +
|
||||
CellIndex);
|
||||
}
|
||||
}
|
||||
|
||||
BOOLEAN CMAPI
|
||||
HvIsCellAllocated(IN PHHIVE RegistryHive,
|
||||
IN HCELL_INDEX CellIndex)
|
||||
{
|
||||
ULONG Type, Block;
|
||||
|
||||
/* If it's a flat hive, the cell is always allocated */
|
||||
if (RegistryHive->Flat)
|
||||
return TRUE;
|
||||
|
||||
/* Otherwise, get the type and make sure it's valid */
|
||||
Type = HvGetCellType(CellIndex);
|
||||
Block = HvGetCellBlock(CellIndex);
|
||||
if (Block >= RegistryHive->Storage[Type].Length)
|
||||
return FALSE;
|
||||
|
||||
/* Try to get the cell block */
|
||||
if (RegistryHive->Storage[Type].BlockList[Block].BlockAddress)
|
||||
return TRUE;
|
||||
|
||||
/* No valid block, fail */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
PVOID CMAPI
|
||||
HvGetCell(
|
||||
PHHIVE RegistryHive,
|
||||
HCELL_INDEX CellIndex)
|
||||
{
|
||||
return (PVOID)(HvpGetCellHeader(RegistryHive, CellIndex) + 1);
|
||||
}
|
||||
|
||||
static __inline LONG CMAPI
|
||||
HvpGetCellFullSize(
|
||||
PHHIVE RegistryHive,
|
||||
PVOID Cell)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(RegistryHive);
|
||||
return ((PHCELL)Cell - 1)->Size;
|
||||
}
|
||||
|
||||
LONG CMAPI
|
||||
HvGetCellSize(IN PHHIVE Hive,
|
||||
IN PVOID Address)
|
||||
{
|
||||
PHCELL CellHeader;
|
||||
LONG Size;
|
||||
|
||||
UNREFERENCED_PARAMETER(Hive);
|
||||
|
||||
CellHeader = (PHCELL)Address - 1;
|
||||
Size = CellHeader->Size * -1;
|
||||
Size -= sizeof(HCELL);
|
||||
return Size;
|
||||
}
|
||||
|
||||
BOOLEAN CMAPI
|
||||
HvMarkCellDirty(
|
||||
PHHIVE RegistryHive,
|
||||
HCELL_INDEX CellIndex,
|
||||
BOOLEAN HoldingLock)
|
||||
{
|
||||
ULONG CellBlock;
|
||||
ULONG CellLastBlock;
|
||||
|
||||
ASSERT(RegistryHive->ReadOnly == FALSE);
|
||||
|
||||
CMLTRACE(CMLIB_HCELL_DEBUG, "%s - Hive %p, CellIndex %08lx, HoldingLock %b\n",
|
||||
__FUNCTION__, RegistryHive, CellIndex, HoldingLock);
|
||||
|
||||
if ((CellIndex & HCELL_TYPE_MASK) >> HCELL_TYPE_SHIFT != Stable)
|
||||
return TRUE;
|
||||
|
||||
CellBlock = (CellIndex & HCELL_BLOCK_MASK) >> HCELL_BLOCK_SHIFT;
|
||||
CellLastBlock = ((CellIndex + HV_BLOCK_SIZE - 1) & HCELL_BLOCK_MASK) >> HCELL_BLOCK_SHIFT;
|
||||
|
||||
RtlSetBits(&RegistryHive->DirtyVector,
|
||||
CellBlock, CellLastBlock - CellBlock);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOLEAN CMAPI
|
||||
HvIsCellDirty(IN PHHIVE Hive,
|
||||
IN HCELL_INDEX Cell)
|
||||
{
|
||||
BOOLEAN IsDirty = FALSE;
|
||||
|
||||
/* Sanity checks */
|
||||
ASSERT(Hive->ReadOnly == FALSE);
|
||||
|
||||
/* Volatile cells are always "dirty" */
|
||||
if (HvGetCellType(Cell) == Volatile)
|
||||
return TRUE;
|
||||
|
||||
/* Check if the dirty bit is set */
|
||||
if (RtlCheckBit(&Hive->DirtyVector, Cell / HV_BLOCK_SIZE))
|
||||
IsDirty = TRUE;
|
||||
|
||||
/* Return result as boolean*/
|
||||
return IsDirty;
|
||||
}
|
||||
|
||||
static __inline ULONG 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(
|
||||
PHHIVE RegistryHive,
|
||||
PHCELL FreeBlock,
|
||||
HCELL_INDEX FreeIndex)
|
||||
{
|
||||
PHCELL_INDEX FreeBlockData;
|
||||
HSTORAGE_TYPE Storage;
|
||||
ULONG Index;
|
||||
|
||||
ASSERT(RegistryHive != NULL);
|
||||
ASSERT(FreeBlock != NULL);
|
||||
|
||||
Storage = (FreeIndex & HCELL_TYPE_MASK) >> HCELL_TYPE_SHIFT;
|
||||
Index = HvpComputeFreeListIndex((ULONG)FreeBlock->Size);
|
||||
|
||||
FreeBlockData = (PHCELL_INDEX)(FreeBlock + 1);
|
||||
*FreeBlockData = RegistryHive->Storage[Storage].FreeDisplay[Index];
|
||||
RegistryHive->Storage[Storage].FreeDisplay[Index] = FreeIndex;
|
||||
|
||||
/* FIXME: Eventually get rid of free bins. */
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static VOID CMAPI
|
||||
HvpRemoveFree(
|
||||
PHHIVE RegistryHive,
|
||||
PHCELL CellBlock,
|
||||
HCELL_INDEX CellIndex)
|
||||
{
|
||||
PHCELL_INDEX FreeCellData;
|
||||
PHCELL_INDEX pFreeCellOffset;
|
||||
HSTORAGE_TYPE Storage;
|
||||
ULONG Index, FreeListIndex;
|
||||
|
||||
ASSERT(RegistryHive->ReadOnly == FALSE);
|
||||
|
||||
Storage = (CellIndex & HCELL_TYPE_MASK) >> HCELL_TYPE_SHIFT;
|
||||
Index = HvpComputeFreeListIndex((ULONG)CellBlock->Size);
|
||||
|
||||
pFreeCellOffset = &RegistryHive->Storage[Storage].FreeDisplay[Index];
|
||||
while (*pFreeCellOffset != HCELL_NIL)
|
||||
{
|
||||
FreeCellData = (PHCELL_INDEX)HvGetCell(RegistryHive, *pFreeCellOffset);
|
||||
if (*pFreeCellOffset == CellIndex)
|
||||
{
|
||||
*pFreeCellOffset = *FreeCellData;
|
||||
return;
|
||||
}
|
||||
pFreeCellOffset = FreeCellData;
|
||||
}
|
||||
|
||||
/* Something bad happened, print a useful trace info and bugcheck */
|
||||
CMLTRACE(CMLIB_HCELL_DEBUG, "-- beginning of HvpRemoveFree trace --\n");
|
||||
CMLTRACE(CMLIB_HCELL_DEBUG, "block we are about to free: %08x\n", CellIndex);
|
||||
CMLTRACE(CMLIB_HCELL_DEBUG, "chosen free list index: %d\n", Index);
|
||||
for (FreeListIndex = 0; FreeListIndex < 24; FreeListIndex++)
|
||||
{
|
||||
CMLTRACE(CMLIB_HCELL_DEBUG, "free list [%d]: ", FreeListIndex);
|
||||
pFreeCellOffset = &RegistryHive->Storage[Storage].FreeDisplay[FreeListIndex];
|
||||
while (*pFreeCellOffset != HCELL_NIL)
|
||||
{
|
||||
CMLTRACE(CMLIB_HCELL_DEBUG, "%08x ", *pFreeCellOffset);
|
||||
FreeCellData = (PHCELL_INDEX)HvGetCell(RegistryHive, *pFreeCellOffset);
|
||||
pFreeCellOffset = FreeCellData;
|
||||
}
|
||||
CMLTRACE(CMLIB_HCELL_DEBUG, "\n");
|
||||
}
|
||||
CMLTRACE(CMLIB_HCELL_DEBUG, "-- end of HvpRemoveFree trace --\n");
|
||||
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
|
||||
static HCELL_INDEX CMAPI
|
||||
HvpFindFree(
|
||||
PHHIVE RegistryHive,
|
||||
ULONG Size,
|
||||
HSTORAGE_TYPE Storage)
|
||||
{
|
||||
PHCELL_INDEX FreeCellData;
|
||||
HCELL_INDEX FreeCellOffset;
|
||||
PHCELL_INDEX pFreeCellOffset;
|
||||
ULONG Index;
|
||||
|
||||
for (Index = HvpComputeFreeListIndex(Size); Index < 24; Index++)
|
||||
{
|
||||
pFreeCellOffset = &RegistryHive->Storage[Storage].FreeDisplay[Index];
|
||||
while (*pFreeCellOffset != HCELL_NIL)
|
||||
{
|
||||
FreeCellData = (PHCELL_INDEX)HvGetCell(RegistryHive, *pFreeCellOffset);
|
||||
if ((ULONG)HvpGetCellFullSize(RegistryHive, FreeCellData) >= Size)
|
||||
{
|
||||
FreeCellOffset = *pFreeCellOffset;
|
||||
*pFreeCellOffset = *FreeCellData;
|
||||
return FreeCellOffset;
|
||||
}
|
||||
pFreeCellOffset = FreeCellData;
|
||||
}
|
||||
}
|
||||
|
||||
return HCELL_NIL;
|
||||
}
|
||||
|
||||
NTSTATUS CMAPI
|
||||
HvpCreateHiveFreeCellList(
|
||||
PHHIVE Hive)
|
||||
{
|
||||
HCELL_INDEX BlockOffset;
|
||||
PHCELL FreeBlock;
|
||||
ULONG BlockIndex;
|
||||
ULONG FreeOffset;
|
||||
PHBIN Bin;
|
||||
NTSTATUS Status;
|
||||
ULONG Index;
|
||||
|
||||
/* Initialize the free cell list */
|
||||
for (Index = 0; Index < 24; Index++)
|
||||
{
|
||||
Hive->Storage[Stable].FreeDisplay[Index] = HCELL_NIL;
|
||||
Hive->Storage[Volatile].FreeDisplay[Index] = HCELL_NIL;
|
||||
}
|
||||
|
||||
BlockOffset = 0;
|
||||
BlockIndex = 0;
|
||||
while (BlockIndex < Hive->Storage[Stable].Length)
|
||||
{
|
||||
Bin = (PHBIN)Hive->Storage[Stable].BlockList[BlockIndex].BinAddress;
|
||||
|
||||
/* Search free blocks and add to list */
|
||||
FreeOffset = sizeof(HBIN);
|
||||
while (FreeOffset < Bin->Size)
|
||||
{
|
||||
FreeBlock = (PHCELL)((ULONG_PTR)Bin + FreeOffset);
|
||||
if (FreeBlock->Size > 0)
|
||||
{
|
||||
Status = HvpAddFree(Hive, FreeBlock, Bin->FileOffset + FreeOffset);
|
||||
if (!NT_SUCCESS(Status))
|
||||
return Status;
|
||||
|
||||
FreeOffset += FreeBlock->Size;
|
||||
}
|
||||
else
|
||||
{
|
||||
FreeOffset -= FreeBlock->Size;
|
||||
}
|
||||
}
|
||||
|
||||
BlockIndex += Bin->Size / HV_BLOCK_SIZE;
|
||||
BlockOffset += Bin->Size;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
HCELL_INDEX CMAPI
|
||||
HvAllocateCell(
|
||||
PHHIVE RegistryHive,
|
||||
SIZE_T Size,
|
||||
HSTORAGE_TYPE Storage,
|
||||
HCELL_INDEX Vicinity)
|
||||
{
|
||||
PHCELL FreeCell;
|
||||
HCELL_INDEX FreeCellOffset;
|
||||
PHCELL NewCell;
|
||||
PHBIN Bin;
|
||||
|
||||
ASSERT(RegistryHive->ReadOnly == FALSE);
|
||||
|
||||
CMLTRACE(CMLIB_HCELL_DEBUG, "%s - Hive %p, Size %x, %s, Vicinity %08lx\n",
|
||||
__FUNCTION__, RegistryHive, Size, (Storage == 0) ? "Stable" : "Volatile", Vicinity);
|
||||
|
||||
/* Round to 16 bytes multiple. */
|
||||
Size = ROUND_UP(Size + sizeof(HCELL), 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_NIL)
|
||||
{
|
||||
Bin = HvpAddBin(RegistryHive, Size, Storage);
|
||||
if (Bin == NULL)
|
||||
return HCELL_NIL;
|
||||
FreeCellOffset = Bin->FileOffset + sizeof(HBIN);
|
||||
FreeCellOffset |= Storage << HCELL_TYPE_SHIFT;
|
||||
}
|
||||
|
||||
FreeCell = HvpGetCellHeader(RegistryHive, FreeCellOffset);
|
||||
|
||||
/* Split the block in two parts */
|
||||
|
||||
/* The free block that is created has to be at least
|
||||
sizeof(HCELL) + sizeof(HCELL_INDEX) big, so that free
|
||||
cell list code can work. Moreover we round cell sizes
|
||||
to 16 bytes, so creating a smaller block would result in
|
||||
a cell that would never be allocated. */
|
||||
if ((ULONG)FreeCell->Size > Size + 16)
|
||||
{
|
||||
NewCell = (PHCELL)((ULONG_PTR)FreeCell + Size);
|
||||
NewCell->Size = FreeCell->Size - Size;
|
||||
FreeCell->Size = Size;
|
||||
HvpAddFree(RegistryHive, NewCell, FreeCellOffset + Size);
|
||||
if (Storage == Stable)
|
||||
HvMarkCellDirty(RegistryHive, FreeCellOffset + Size, FALSE);
|
||||
}
|
||||
|
||||
if (Storage == Stable)
|
||||
HvMarkCellDirty(RegistryHive, FreeCellOffset, FALSE);
|
||||
FreeCell->Size = -FreeCell->Size;
|
||||
RtlZeroMemory(FreeCell + 1, Size - sizeof(HCELL));
|
||||
|
||||
CMLTRACE(CMLIB_HCELL_DEBUG, "%s - CellIndex %08lx\n",
|
||||
__FUNCTION__, FreeCellOffset);
|
||||
|
||||
return FreeCellOffset;
|
||||
}
|
||||
|
||||
HCELL_INDEX CMAPI
|
||||
HvReallocateCell(
|
||||
PHHIVE RegistryHive,
|
||||
HCELL_INDEX CellIndex,
|
||||
ULONG Size)
|
||||
{
|
||||
PVOID OldCell;
|
||||
PVOID NewCell;
|
||||
LONG OldCellSize;
|
||||
HCELL_INDEX NewCellIndex;
|
||||
HSTORAGE_TYPE Storage;
|
||||
|
||||
ASSERT(CellIndex != HCELL_NIL);
|
||||
|
||||
CMLTRACE(CMLIB_HCELL_DEBUG, "%s - Hive %p, CellIndex %08lx, Size %x\n",
|
||||
__FUNCTION__, RegistryHive, CellIndex, Size);
|
||||
|
||||
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 > (ULONG)OldCellSize)
|
||||
{
|
||||
NewCellIndex = HvAllocateCell(RegistryHive, Size, Storage, HCELL_NIL);
|
||||
if (NewCellIndex == HCELL_NIL)
|
||||
return HCELL_NIL;
|
||||
|
||||
NewCell = HvGetCell(RegistryHive, NewCellIndex);
|
||||
RtlCopyMemory(NewCell, OldCell, (SIZE_T)OldCellSize);
|
||||
|
||||
HvFreeCell(RegistryHive, CellIndex);
|
||||
|
||||
return NewCellIndex;
|
||||
}
|
||||
|
||||
return CellIndex;
|
||||
}
|
||||
|
||||
VOID CMAPI
|
||||
HvFreeCell(
|
||||
PHHIVE RegistryHive,
|
||||
HCELL_INDEX CellIndex)
|
||||
{
|
||||
PHCELL Free;
|
||||
PHCELL Neighbor;
|
||||
PHBIN Bin;
|
||||
ULONG CellType;
|
||||
ULONG CellBlock;
|
||||
|
||||
ASSERT(RegistryHive->ReadOnly == FALSE);
|
||||
|
||||
CMLTRACE(CMLIB_HCELL_DEBUG, "%s - Hive %p, CellIndex %08lx\n",
|
||||
__FUNCTION__, RegistryHive, CellIndex);
|
||||
|
||||
Free = HvpGetCellHeader(RegistryHive, CellIndex);
|
||||
|
||||
ASSERT(Free->Size < 0);
|
||||
|
||||
Free->Size = -Free->Size;
|
||||
|
||||
CellType = (CellIndex & HCELL_TYPE_MASK) >> HCELL_TYPE_SHIFT;
|
||||
CellBlock = (CellIndex & HCELL_BLOCK_MASK) >> HCELL_BLOCK_SHIFT;
|
||||
|
||||
/* FIXME: Merge free blocks */
|
||||
Bin = (PHBIN)RegistryHive->Storage[CellType].BlockList[CellBlock].BinAddress;
|
||||
|
||||
if ((CellIndex & ~HCELL_TYPE_MASK) + Free->Size <
|
||||
Bin->FileOffset + Bin->Size)
|
||||
{
|
||||
Neighbor = (PHCELL)((ULONG_PTR)Free + Free->Size);
|
||||
if (Neighbor->Size > 0)
|
||||
{
|
||||
HvpRemoveFree(RegistryHive, Neighbor,
|
||||
((HCELL_INDEX)((ULONG_PTR)Neighbor - (ULONG_PTR)Bin +
|
||||
Bin->FileOffset)) | (CellIndex & HCELL_TYPE_MASK));
|
||||
Free->Size += Neighbor->Size;
|
||||
}
|
||||
}
|
||||
|
||||
Neighbor = (PHCELL)(Bin + 1);
|
||||
while (Neighbor < Free)
|
||||
{
|
||||
if (Neighbor->Size > 0)
|
||||
{
|
||||
if ((ULONG_PTR)Neighbor + Neighbor->Size == (ULONG_PTR)Free)
|
||||
{
|
||||
HCELL_INDEX NeighborCellIndex =
|
||||
(HCELL_INDEX)((ULONG_PTR)Neighbor - (ULONG_PTR)Bin +
|
||||
Bin->FileOffset) | (CellIndex & HCELL_TYPE_MASK);
|
||||
|
||||
if (HvpComputeFreeListIndex(Neighbor->Size) !=
|
||||
HvpComputeFreeListIndex(Neighbor->Size + Free->Size))
|
||||
{
|
||||
HvpRemoveFree(RegistryHive, Neighbor, NeighborCellIndex);
|
||||
Neighbor->Size += Free->Size;
|
||||
HvpAddFree(RegistryHive, Neighbor, NeighborCellIndex);
|
||||
}
|
||||
else
|
||||
Neighbor->Size += Free->Size;
|
||||
|
||||
if (CellType == Stable)
|
||||
HvMarkCellDirty(RegistryHive, NeighborCellIndex, FALSE);
|
||||
|
||||
return;
|
||||
}
|
||||
Neighbor = (PHCELL)((ULONG_PTR)Neighbor + Neighbor->Size);
|
||||
}
|
||||
else
|
||||
{
|
||||
Neighbor = (PHCELL)((ULONG_PTR)Neighbor - Neighbor->Size);
|
||||
}
|
||||
}
|
||||
|
||||
/* Add block to the list of free blocks */
|
||||
HvpAddFree(RegistryHive, Free, CellIndex);
|
||||
|
||||
if (CellType == Stable)
|
||||
HvMarkCellDirty(RegistryHive, CellIndex, FALSE);
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
CMAPI
|
||||
HvTrackCellRef(PHV_TRACK_CELL_REF CellRef,
|
||||
PHHIVE Hive,
|
||||
HCELL_INDEX Cell)
|
||||
{
|
||||
/* Sanity checks */
|
||||
ASSERT(CellRef);
|
||||
ASSERT(Hive );
|
||||
ASSERT(Cell != HCELL_NIL);
|
||||
|
||||
/* Less than 4? */
|
||||
if (CellRef->StaticCount < STATIC_CELL_PAIR_COUNT)
|
||||
{
|
||||
/* Add reference */
|
||||
CellRef->StaticArray[CellRef->StaticCount].Hive = Hive;
|
||||
CellRef->StaticArray[CellRef->StaticCount].Cell = Cell;
|
||||
CellRef->StaticCount++;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* FIXME: TODO */
|
||||
DPRINT1("ERROR: Too many references\n");
|
||||
while (TRUE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
VOID
|
||||
CMAPI
|
||||
HvReleaseFreeCellRefArray(PHV_TRACK_CELL_REF CellRef)
|
||||
{
|
||||
ULONG i;
|
||||
ASSERT(CellRef);
|
||||
|
||||
/* Any references? */
|
||||
if (CellRef->StaticCount > 0)
|
||||
{
|
||||
/* Sanity check */
|
||||
ASSERT(CellRef->StaticCount <= STATIC_CELL_PAIR_COUNT);
|
||||
|
||||
/* Loop them */
|
||||
for (i = 0; i < CellRef->StaticCount;i++)
|
||||
{
|
||||
/* Release them */
|
||||
HvReleaseCell(CellRef->StaticArray[i].Hive,
|
||||
CellRef->StaticArray[i].Cell);
|
||||
}
|
||||
|
||||
/* Free again */
|
||||
CellRef->StaticCount = 0;
|
||||
}
|
||||
}
|
306
lib/cmlib/hivedata.h
Normal file
306
lib/cmlib/hivedata.h
Normal file
|
@ -0,0 +1,306 @@
|
|||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
//
|
||||
// Hive operations
|
||||
//
|
||||
#define HINIT_CREATE 0
|
||||
#define HINIT_MEMORY 1
|
||||
#define HINIT_FILE 2
|
||||
#define HINIT_MEMORY_INPLACE 3
|
||||
#define HINIT_FLAT 4
|
||||
#define HINIT_MAPFILE 5
|
||||
|
||||
//
|
||||
// Hive flags
|
||||
//
|
||||
#define HIVE_VOLATILE 1
|
||||
#define HIVE_NOLAZYFLUSH 2
|
||||
#define HIVE_HAS_BEEN_REPLACED 4
|
||||
#define HIVE_HAS_BEEN_FREED 8
|
||||
#define HIVE_UNKNOWN 0x10
|
||||
#define HIVE_IS_UNLOADING 0x20
|
||||
|
||||
//
|
||||
// Hive types
|
||||
//
|
||||
#define HFILE_TYPE_PRIMARY 0
|
||||
#define HFILE_TYPE_ALTERNATE 1
|
||||
#define HFILE_TYPE_LOG 2
|
||||
#define HFILE_TYPE_EXTERNAL 3
|
||||
#define HFILE_TYPE_MAX 4
|
||||
|
||||
//
|
||||
// Hive sizes
|
||||
//
|
||||
#define HBLOCK_SIZE 0x1000
|
||||
#define HSECTOR_SIZE 0x200
|
||||
#define HSECTOR_COUNT 8
|
||||
|
||||
#define HV_BLOCK_SIZE 4096
|
||||
#define HV_LOG_HEADER_SIZE FIELD_OFFSET(HBASE_BLOCK, Reserved2)
|
||||
#define HV_SIGNATURE 0x66676572
|
||||
#define HV_BIN_SIGNATURE 0x6e696268
|
||||
|
||||
//
|
||||
// Hive versions
|
||||
//
|
||||
#define HSYS_MAJOR 1
|
||||
#define HSYS_MINOR 3
|
||||
#define HSYS_WHISTLER_BETA1 4
|
||||
#define HSYS_WHISTLER 5
|
||||
#define HSYS_MINOR_SUPPORTED HSYS_WHISTLER
|
||||
|
||||
//
|
||||
// Hive formats
|
||||
//
|
||||
#define HBASE_FORMAT_MEMORY 1
|
||||
|
||||
//
|
||||
// Hive storage
|
||||
//
|
||||
#define HTYPE_COUNT 2
|
||||
|
||||
/**
|
||||
* @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;
|
||||
|
||||
//
|
||||
// Cell Magic Values
|
||||
//
|
||||
#define HCELL_NIL MAXULONG
|
||||
#define HCELL_CACHED 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
|
||||
|
||||
#define HvGetCellType(Cell) \
|
||||
((ULONG)((Cell & HCELL_TYPE_MASK) >> HCELL_TYPE_SHIFT))
|
||||
#define HvGetCellBlock(Cell) \
|
||||
((ULONG)((Cell & HCELL_BLOCK_MASK) >> HCELL_BLOCK_SHIFT))
|
||||
|
||||
typedef enum
|
||||
{
|
||||
Stable = 0,
|
||||
Volatile = 1
|
||||
} HSTORAGE_TYPE;
|
||||
|
||||
#ifdef CMLIB_HOST
|
||||
#include <host/pshpack1.h>
|
||||
#else
|
||||
#include <pshpack1.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @name HBASE_BLOCK
|
||||
*
|
||||
* On-disk header for registry hive file.
|
||||
*/
|
||||
|
||||
typedef struct _HBASE_BLOCK
|
||||
{
|
||||
/* 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 CM_KEY_NODE */
|
||||
HCELL_INDEX RootCell;
|
||||
|
||||
/* Size of each hive block ? */
|
||||
ULONG Length;
|
||||
|
||||
/* (1?) */
|
||||
ULONG Cluster;
|
||||
|
||||
/* Name of hive file */
|
||||
CHAR FileName[64];
|
||||
|
||||
ULONG Reserved1[99];
|
||||
|
||||
/* Checksum of first 0x200 bytes */
|
||||
ULONG CheckSum;
|
||||
|
||||
ULONG Reserved2[0x37E];
|
||||
ULONG BootType;
|
||||
ULONG BootRecover;
|
||||
} HBASE_BLOCK, *PHBASE_BLOCK;
|
||||
|
||||
typedef struct _HBIN
|
||||
{
|
||||
/* Bin identifier "hbin" (0x6E696268) */
|
||||
ULONG Signature;
|
||||
|
||||
/* Block offset of this bin */
|
||||
HCELL_INDEX FileOffset;
|
||||
|
||||
/* Size in bytes, multiple of the block size (4KB) */
|
||||
ULONG Size;
|
||||
|
||||
ULONG Reserved1[2];
|
||||
|
||||
/* When this bin was last modified */
|
||||
LARGE_INTEGER TimeStamp;
|
||||
|
||||
/* ? (In-memory only) */
|
||||
ULONG Spare;
|
||||
} HBIN, *PHBIN;
|
||||
|
||||
typedef struct _HCELL
|
||||
{
|
||||
/* <0 if used, >0 if free */
|
||||
LONG Size;
|
||||
} HCELL, *PHCELL;
|
||||
|
||||
#ifdef CMLIB_HOST
|
||||
#include <host/poppack.h>
|
||||
#else
|
||||
#include <poppack.h>
|
||||
#endif
|
||||
|
||||
struct _HHIVE;
|
||||
|
||||
typedef struct _CELL_DATA* (CMAPI *PGET_CELL_ROUTINE)(
|
||||
struct _HHIVE *Hive,
|
||||
HCELL_INDEX Cell);
|
||||
|
||||
typedef VOID (CMAPI *PRELEASE_CELL_ROUTINE)(
|
||||
struct _HHIVE *Hive,
|
||||
HCELL_INDEX Cell);
|
||||
|
||||
typedef PVOID (CMAPI *PALLOCATE_ROUTINE)(
|
||||
SIZE_T Size,
|
||||
BOOLEAN Paged,
|
||||
ULONG Tag);
|
||||
|
||||
typedef VOID (CMAPI *PFREE_ROUTINE)(
|
||||
PVOID Ptr,
|
||||
ULONG Quota);
|
||||
|
||||
typedef BOOLEAN (CMAPI *PFILE_READ_ROUTINE)(
|
||||
struct _HHIVE *RegistryHive,
|
||||
ULONG FileType,
|
||||
PULONG FileOffset,
|
||||
PVOID Buffer,
|
||||
SIZE_T BufferLength);
|
||||
|
||||
typedef BOOLEAN (CMAPI *PFILE_WRITE_ROUTINE)(
|
||||
struct _HHIVE *RegistryHive,
|
||||
ULONG FileType,
|
||||
PULONG FileOffset,
|
||||
PVOID Buffer,
|
||||
SIZE_T BufferLength);
|
||||
|
||||
typedef BOOLEAN (CMAPI *PFILE_SET_SIZE_ROUTINE)(
|
||||
struct _HHIVE *RegistryHive,
|
||||
ULONG FileType,
|
||||
ULONG FileSize,
|
||||
ULONG OldfileSize);
|
||||
|
||||
typedef BOOLEAN (CMAPI *PFILE_FLUSH_ROUTINE)(
|
||||
struct _HHIVE *RegistryHive,
|
||||
ULONG FileType,
|
||||
PLARGE_INTEGER FileOffset,
|
||||
ULONG Length
|
||||
);
|
||||
|
||||
typedef struct _HMAP_ENTRY
|
||||
{
|
||||
ULONG_PTR BlockAddress;
|
||||
ULONG_PTR BinAddress;
|
||||
struct _CM_VIEW_OF_FILE *CmView;
|
||||
ULONG MemAlloc;
|
||||
} HMAP_ENTRY, *PHMAP_ENTRY;
|
||||
|
||||
typedef struct _HMAP_TABLE
|
||||
{
|
||||
HMAP_ENTRY Table[512];
|
||||
} HMAP_TABLE, *PHMAP_TABLE;
|
||||
|
||||
typedef struct _HMAP_DIRECTORY
|
||||
{
|
||||
PHMAP_TABLE Directory[2048];
|
||||
} HMAP_DIRECTORY, *PHMAP_DIRECTORY;
|
||||
|
||||
typedef struct _DUAL
|
||||
{
|
||||
ULONG Length;
|
||||
PHMAP_DIRECTORY Map;
|
||||
PHMAP_ENTRY BlockList; // PHMAP_TABLE SmallDir;
|
||||
ULONG Guard;
|
||||
HCELL_INDEX FreeDisplay[24]; //FREE_DISPLAY FreeDisplay[24];
|
||||
ULONG FreeSummary;
|
||||
LIST_ENTRY FreeBins;
|
||||
} DUAL, *PDUAL;
|
||||
|
||||
typedef struct _HHIVE
|
||||
{
|
||||
ULONG Signature;
|
||||
PGET_CELL_ROUTINE GetCellRoutine;
|
||||
PRELEASE_CELL_ROUTINE ReleaseCellRoutine;
|
||||
PALLOCATE_ROUTINE Allocate;
|
||||
PFREE_ROUTINE Free;
|
||||
PFILE_READ_ROUTINE FileRead;
|
||||
PFILE_WRITE_ROUTINE FileWrite;
|
||||
PFILE_SET_SIZE_ROUTINE FileSetSize;
|
||||
PFILE_FLUSH_ROUTINE FileFlush;
|
||||
PHBASE_BLOCK BaseBlock;
|
||||
RTL_BITMAP DirtyVector;
|
||||
ULONG DirtyCount;
|
||||
ULONG DirtyAlloc;
|
||||
ULONG BaseBlockAlloc;
|
||||
ULONG Cluster;
|
||||
BOOLEAN Flat;
|
||||
BOOLEAN ReadOnly;
|
||||
BOOLEAN Log;
|
||||
BOOLEAN DirtyFlag;
|
||||
ULONG HvBinHeadersUse;
|
||||
ULONG HvFreeCellsUse;
|
||||
ULONG HvUsedcellsUse;
|
||||
ULONG CmUsedCellsUse;
|
||||
ULONG HiveFlags;
|
||||
ULONG LogSize;
|
||||
ULONG RefreshCount;
|
||||
ULONG StorageTypeCount;
|
||||
ULONG Version;
|
||||
DUAL Storage[HTYPE_COUNT];
|
||||
} HHIVE, *PHHIVE;
|
||||
|
||||
#define IsFreeCell(Cell)(Cell->Size >= 0)
|
||||
#define IsUsedCell(Cell)(Cell->Size < 0)
|
535
lib/cmlib/hiveinit.c
Normal file
535
lib/cmlib/hiveinit.c
Normal file
|
@ -0,0 +1,535 @@
|
|||
/*
|
||||
* 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(
|
||||
PHBASE_BLOCK BaseBlock)
|
||||
{
|
||||
if (BaseBlock->Signature != HV_SIGNATURE ||
|
||||
BaseBlock->Major != HSYS_MAJOR ||
|
||||
BaseBlock->Minor < HSYS_MINOR ||
|
||||
BaseBlock->Type != HFILE_TYPE_PRIMARY ||
|
||||
BaseBlock->Format != HBASE_FORMAT_MEMORY ||
|
||||
BaseBlock->Cluster != 1 ||
|
||||
BaseBlock->Sequence1 != BaseBlock->Sequence2 ||
|
||||
HvpHiveHeaderChecksum(BaseBlock) != BaseBlock->CheckSum)
|
||||
{
|
||||
DPRINT1("Verify Hive Header failed: \n");
|
||||
DPRINT1(" Signature: 0x%x and not 0x%x, Major: 0x%x and not 0x%x\n",
|
||||
BaseBlock->Signature, HV_SIGNATURE, BaseBlock->Major, HSYS_MAJOR);
|
||||
DPRINT1(" Minor: 0x%x is not >= 0x%x, Type: 0x%x and not 0x%x\n",
|
||||
BaseBlock->Minor, HSYS_MINOR, BaseBlock->Type, HFILE_TYPE_PRIMARY);
|
||||
DPRINT1(" Format: 0x%x and not 0x%x, Cluster: 0x%x and not 1\n",
|
||||
BaseBlock->Format, HBASE_FORMAT_MEMORY, BaseBlock->Cluster);
|
||||
DPRINT1(" Sequence: 0x%x and not 0x%x, Checksum: 0x%x and not 0x%x\n",
|
||||
BaseBlock->Sequence1, BaseBlock->Sequence2,
|
||||
HvpHiveHeaderChecksum(BaseBlock), BaseBlock->CheckSum);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @name HvpFreeHiveBins
|
||||
*
|
||||
* Internal function to free all bin storage associated with hive
|
||||
* descriptor.
|
||||
*/
|
||||
|
||||
VOID CMAPI
|
||||
HvpFreeHiveBins(
|
||||
PHHIVE Hive)
|
||||
{
|
||||
ULONG i;
|
||||
PHBIN Bin;
|
||||
ULONG Storage;
|
||||
|
||||
for (Storage = Stable; Storage < HTYPE_COUNT; Storage++)
|
||||
{
|
||||
Bin = NULL;
|
||||
for (i = 0; i < Hive->Storage[Storage].Length; i++)
|
||||
{
|
||||
if (Hive->Storage[Storage].BlockList[i].BinAddress == (ULONG_PTR)NULL)
|
||||
continue;
|
||||
if (Hive->Storage[Storage].BlockList[i].BinAddress != (ULONG_PTR)Bin)
|
||||
{
|
||||
Bin = (PHBIN)Hive->Storage[Storage].BlockList[i].BinAddress;
|
||||
Hive->Free((PHBIN)Hive->Storage[Storage].BlockList[i].BinAddress, 0);
|
||||
}
|
||||
Hive->Storage[Storage].BlockList[i].BinAddress = (ULONG_PTR)NULL;
|
||||
Hive->Storage[Storage].BlockList[i].BlockAddress = (ULONG_PTR)NULL;
|
||||
}
|
||||
|
||||
if (Hive->Storage[Storage].Length)
|
||||
Hive->Free(Hive->Storage[Storage].BlockList, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @name HvpCreateHive
|
||||
*
|
||||
* Internal helper function to initalize hive descriptor structure for
|
||||
* newly created hive.
|
||||
*
|
||||
* @see HvInitialize
|
||||
*/
|
||||
|
||||
NTSTATUS CMAPI
|
||||
HvpCreateHive(
|
||||
PHHIVE RegistryHive)
|
||||
{
|
||||
PHBASE_BLOCK BaseBlock;
|
||||
ULONG Index;
|
||||
|
||||
BaseBlock = RegistryHive->Allocate(sizeof(HBASE_BLOCK), FALSE, TAG_CM);
|
||||
if (BaseBlock == NULL)
|
||||
return STATUS_NO_MEMORY;
|
||||
RtlZeroMemory(BaseBlock, sizeof(HBASE_BLOCK));
|
||||
BaseBlock->Signature = HV_SIGNATURE;
|
||||
BaseBlock->Major = HSYS_MAJOR;
|
||||
BaseBlock->Minor = HSYS_MINOR;
|
||||
BaseBlock->Type = HFILE_TYPE_PRIMARY;
|
||||
BaseBlock->Format = HBASE_FORMAT_MEMORY;
|
||||
BaseBlock->Cluster = 1;
|
||||
BaseBlock->RootCell = HCELL_NIL;
|
||||
BaseBlock->Length = HV_BLOCK_SIZE;
|
||||
BaseBlock->Sequence1 = 1;
|
||||
BaseBlock->Sequence2 = 1;
|
||||
/* FIXME: Fill in the file name */
|
||||
BaseBlock->CheckSum = HvpHiveHeaderChecksum(BaseBlock);
|
||||
|
||||
RegistryHive->BaseBlock = BaseBlock;
|
||||
for (Index = 0; Index < 24; Index++)
|
||||
{
|
||||
RegistryHive->Storage[Stable].FreeDisplay[Index] = HCELL_NIL;
|
||||
RegistryHive->Storage[Volatile].FreeDisplay[Index] = HCELL_NIL;
|
||||
}
|
||||
RtlInitializeBitMap(&RegistryHive->DirtyVector, 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(
|
||||
PHHIVE Hive,
|
||||
PVOID ChunkBase)
|
||||
{
|
||||
SIZE_T BlockIndex;
|
||||
PHBIN Bin, NewBin;
|
||||
ULONG i;
|
||||
ULONG BitmapSize;
|
||||
PULONG BitmapBuffer;
|
||||
SIZE_T ChunkSize;
|
||||
|
||||
//
|
||||
// This hack is similar in magnitude to the US's National Debt
|
||||
//
|
||||
ChunkSize = ((PHBASE_BLOCK)ChunkBase)->Length;
|
||||
((PHBASE_BLOCK)ChunkBase)->Length = HV_BLOCK_SIZE;
|
||||
DPRINT("ChunkSize: %lx\n", ChunkSize);
|
||||
|
||||
if (ChunkSize < sizeof(HBASE_BLOCK) ||
|
||||
!HvpVerifyHiveHeader((PHBASE_BLOCK)ChunkBase))
|
||||
{
|
||||
DPRINT1("Registry is corrupt: ChunkSize %lu < sizeof(HBASE_BLOCK) %lu, "
|
||||
"or HvpVerifyHiveHeader() failed\n", ChunkSize, (SIZE_T)sizeof(HBASE_BLOCK));
|
||||
return STATUS_REGISTRY_CORRUPT;
|
||||
}
|
||||
|
||||
Hive->BaseBlock = Hive->Allocate(sizeof(HBASE_BLOCK), FALSE, TAG_CM);
|
||||
if (Hive->BaseBlock == NULL)
|
||||
{
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
RtlCopyMemory(Hive->BaseBlock, ChunkBase, sizeof(HBASE_BLOCK));
|
||||
|
||||
/*
|
||||
* Build a block list from the in-memory chunk and copy the data as
|
||||
* we go.
|
||||
*/
|
||||
|
||||
Hive->Storage[Stable].Length = (ULONG)(ChunkSize / HV_BLOCK_SIZE) - 1;
|
||||
Hive->Storage[Stable].BlockList =
|
||||
Hive->Allocate(Hive->Storage[Stable].Length *
|
||||
sizeof(HMAP_ENTRY), FALSE, TAG_CM);
|
||||
if (Hive->Storage[Stable].BlockList == NULL)
|
||||
{
|
||||
DPRINT1("Allocating block list failed\n");
|
||||
Hive->Free(Hive->BaseBlock, 0);
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
for (BlockIndex = 0; BlockIndex < Hive->Storage[Stable].Length; )
|
||||
{
|
||||
Bin = (PHBIN)((ULONG_PTR)ChunkBase + (BlockIndex + 1) * HV_BLOCK_SIZE);
|
||||
if (Bin->Signature != HV_BIN_SIGNATURE ||
|
||||
(Bin->Size % HV_BLOCK_SIZE) != 0)
|
||||
{
|
||||
Hive->Free(Hive->BaseBlock, 0);
|
||||
Hive->Free(Hive->Storage[Stable].BlockList, 0);
|
||||
return STATUS_REGISTRY_CORRUPT;
|
||||
}
|
||||
|
||||
NewBin = Hive->Allocate(Bin->Size, TRUE, TAG_CM);
|
||||
if (NewBin == NULL)
|
||||
{
|
||||
Hive->Free(Hive->BaseBlock, 0);
|
||||
Hive->Free(Hive->Storage[Stable].BlockList, 0);
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
Hive->Storage[Stable].BlockList[BlockIndex].BinAddress = (ULONG_PTR)NewBin;
|
||||
Hive->Storage[Stable].BlockList[BlockIndex].BlockAddress = (ULONG_PTR)NewBin;
|
||||
|
||||
RtlCopyMemory(NewBin, Bin, Bin->Size);
|
||||
|
||||
if (Bin->Size > HV_BLOCK_SIZE)
|
||||
{
|
||||
for (i = 1; i < Bin->Size / HV_BLOCK_SIZE; i++)
|
||||
{
|
||||
Hive->Storage[Stable].BlockList[BlockIndex + i].BinAddress = (ULONG_PTR)NewBin;
|
||||
Hive->Storage[Stable].BlockList[BlockIndex + i].BlockAddress =
|
||||
((ULONG_PTR)NewBin + (i * HV_BLOCK_SIZE));
|
||||
}
|
||||
}
|
||||
|
||||
BlockIndex += Bin->Size / HV_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
if (HvpCreateHiveFreeCellList(Hive))
|
||||
{
|
||||
HvpFreeHiveBins(Hive);
|
||||
Hive->Free(Hive->BaseBlock, 0);
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
BitmapSize = ROUND_UP(Hive->Storage[Stable].Length,
|
||||
sizeof(ULONG) * 8) / 8;
|
||||
BitmapBuffer = (PULONG)Hive->Allocate(BitmapSize, TRUE, TAG_CM);
|
||||
if (BitmapBuffer == NULL)
|
||||
{
|
||||
HvpFreeHiveBins(Hive);
|
||||
Hive->Free(Hive->BaseBlock, 0);
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
RtlInitializeBitMap(&Hive->DirtyVector, BitmapBuffer, BitmapSize * 8);
|
||||
RtlClearAllBits(&Hive->DirtyVector);
|
||||
|
||||
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(
|
||||
PHHIVE Hive,
|
||||
PVOID ChunkBase)
|
||||
{
|
||||
if (!HvpVerifyHiveHeader((PHBASE_BLOCK)ChunkBase))
|
||||
{
|
||||
return STATUS_REGISTRY_CORRUPT;
|
||||
}
|
||||
|
||||
Hive->BaseBlock = (PHBASE_BLOCK)ChunkBase;
|
||||
Hive->ReadOnly = TRUE;
|
||||
Hive->Flat = TRUE;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
typedef enum _RESULT
|
||||
{
|
||||
NotHive,
|
||||
Fail,
|
||||
NoMemory,
|
||||
HiveSuccess,
|
||||
RecoverHeader,
|
||||
RecoverData,
|
||||
SelfHeal
|
||||
} RESULT;
|
||||
|
||||
RESULT CMAPI
|
||||
HvpGetHiveHeader(IN PHHIVE Hive,
|
||||
IN PHBASE_BLOCK *HiveBaseBlock,
|
||||
IN PLARGE_INTEGER TimeStamp)
|
||||
{
|
||||
PHBASE_BLOCK BaseBlock;
|
||||
ULONG Alignment;
|
||||
ULONG Result;
|
||||
ULONG Offset = 0;
|
||||
ASSERT(sizeof(HBASE_BLOCK) >= (HV_BLOCK_SIZE * Hive->Cluster));
|
||||
|
||||
/* Assume failure and allocate the buffer */
|
||||
*HiveBaseBlock = 0;
|
||||
BaseBlock = Hive->Allocate(sizeof(HBASE_BLOCK), TRUE, TAG_CM);
|
||||
if (!BaseBlock) return NoMemory;
|
||||
|
||||
/* Check for, and enforce, alignment */
|
||||
Alignment = Hive->Cluster * HV_BLOCK_SIZE -1;
|
||||
if ((ULONG_PTR)BaseBlock & Alignment)
|
||||
{
|
||||
/* Free the old header */
|
||||
Hive->Free(BaseBlock, 0);
|
||||
BaseBlock = Hive->Allocate(PAGE_SIZE, TRUE, TAG_CM);
|
||||
if (!BaseBlock) return NoMemory;
|
||||
|
||||
//BaseBlock->Length = PAGE_SIZE; ??
|
||||
}
|
||||
|
||||
/* Clear it */
|
||||
RtlZeroMemory(BaseBlock, sizeof(HBASE_BLOCK));
|
||||
|
||||
/* Now read it from disk */
|
||||
Result = Hive->FileRead(Hive,
|
||||
HFILE_TYPE_PRIMARY,
|
||||
&Offset,
|
||||
BaseBlock,
|
||||
Hive->Cluster * HV_BLOCK_SIZE);
|
||||
|
||||
/* Couldn't read: assume it's not a hive */
|
||||
if (!Result) return NotHive;
|
||||
|
||||
/* Do validation */
|
||||
if (!HvpVerifyHiveHeader(BaseBlock)) return NotHive;
|
||||
|
||||
/* Return information */
|
||||
*HiveBaseBlock = BaseBlock;
|
||||
*TimeStamp = BaseBlock->TimeStamp;
|
||||
return HiveSuccess;
|
||||
}
|
||||
|
||||
NTSTATUS CMAPI
|
||||
HvLoadHive(IN PHHIVE Hive,
|
||||
IN ULONG FileSize)
|
||||
{
|
||||
PHBASE_BLOCK BaseBlock = NULL;
|
||||
ULONG Result;
|
||||
LARGE_INTEGER TimeStamp;
|
||||
ULONG Offset = 0;
|
||||
PVOID HiveData;
|
||||
|
||||
/* Get the hive header */
|
||||
Result = HvpGetHiveHeader(Hive, &BaseBlock, &TimeStamp);
|
||||
switch (Result)
|
||||
{
|
||||
/* Out of memory */
|
||||
case NoMemory:
|
||||
|
||||
/* Fail */
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
/* Not a hive */
|
||||
case NotHive:
|
||||
|
||||
/* Fail */
|
||||
return STATUS_NOT_REGISTRY_FILE;
|
||||
|
||||
/* Has recovery data */
|
||||
case RecoverData:
|
||||
case RecoverHeader:
|
||||
|
||||
/* Fail */
|
||||
return STATUS_REGISTRY_CORRUPT;
|
||||
}
|
||||
|
||||
/* Set default boot type */
|
||||
BaseBlock->BootType = 0;
|
||||
|
||||
/* Setup hive data */
|
||||
Hive->BaseBlock = BaseBlock;
|
||||
Hive->Version = Hive->BaseBlock->Minor;
|
||||
|
||||
/* Allocate a buffer large enough to hold the hive */
|
||||
HiveData = Hive->Allocate(FileSize, TRUE, TAG_CM);
|
||||
if (!HiveData) return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
/* Now read the whole hive */
|
||||
Result = Hive->FileRead(Hive,
|
||||
HFILE_TYPE_PRIMARY,
|
||||
&Offset,
|
||||
HiveData,
|
||||
FileSize);
|
||||
if (!Result) return STATUS_NOT_REGISTRY_FILE;
|
||||
|
||||
/* Apply "US National Debt" hack */
|
||||
((PHBASE_BLOCK)HiveData)->Length = FileSize;
|
||||
|
||||
/* Free our base block... it's usless in this implementation */
|
||||
Hive->Free(BaseBlock, 0);
|
||||
|
||||
/* Initialize the hive directly from memory */
|
||||
return HvpInitializeMemoryHive(Hive, HiveData);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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(
|
||||
PHHIVE RegistryHive,
|
||||
ULONG Operation,
|
||||
ULONG HiveType,
|
||||
ULONG HiveFlags,
|
||||
PVOID HiveData OPTIONAL,
|
||||
PALLOCATE_ROUTINE Allocate,
|
||||
PFREE_ROUTINE Free,
|
||||
PFILE_SET_SIZE_ROUTINE FileSetSize,
|
||||
PFILE_WRITE_ROUTINE FileWrite,
|
||||
PFILE_READ_ROUTINE FileRead,
|
||||
PFILE_FLUSH_ROUTINE FileFlush,
|
||||
ULONG Cluster OPTIONAL,
|
||||
PUNICODE_STRING FileName)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PHHIVE Hive = RegistryHive;
|
||||
|
||||
UNREFERENCED_PARAMETER(HiveType);
|
||||
UNREFERENCED_PARAMETER(FileName);
|
||||
|
||||
/*
|
||||
* Create a new hive structure that will hold all the maintenance data.
|
||||
*/
|
||||
|
||||
RtlZeroMemory(Hive, sizeof(HHIVE));
|
||||
|
||||
Hive->Allocate = Allocate;
|
||||
Hive->Free = Free;
|
||||
Hive->FileRead = FileRead;
|
||||
Hive->FileWrite = FileWrite;
|
||||
Hive->FileSetSize = FileSetSize;
|
||||
Hive->FileFlush = FileFlush;
|
||||
Hive->StorageTypeCount = HTYPE_COUNT;
|
||||
Hive->Cluster = 1;
|
||||
Hive->Version = HSYS_MINOR;
|
||||
Hive->HiveFlags = HiveFlags &~ HIVE_NOLAZYFLUSH;
|
||||
|
||||
switch (Operation)
|
||||
{
|
||||
case HINIT_CREATE:
|
||||
Status = HvpCreateHive(Hive);
|
||||
break;
|
||||
|
||||
case HINIT_MEMORY:
|
||||
Status = HvpInitializeMemoryHive(Hive, HiveData);
|
||||
break;
|
||||
|
||||
case HINIT_FLAT:
|
||||
Status = HvpInitializeMemoryInplaceHive(Hive, HiveData);
|
||||
break;
|
||||
|
||||
case HINIT_FILE:
|
||||
|
||||
/* Hack of doom: Cluster is actually the file size. */
|
||||
Status = HvLoadHive(Hive, Cluster);
|
||||
if ((Status != STATUS_SUCCESS) &&
|
||||
(Status != STATUS_REGISTRY_RECOVERED))
|
||||
{
|
||||
/* Unrecoverable failure */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Check for previous damage */
|
||||
if (Status == STATUS_REGISTRY_RECOVERED) ASSERT(FALSE);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* FIXME: A better return status value is needed */
|
||||
Status = STATUS_NOT_IMPLEMENTED;
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
return Status;
|
||||
|
||||
if (Operation != HINIT_CREATE) CmPrepareHive(Hive);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @name HvFree
|
||||
*
|
||||
* Free all stroage and handles associated with hive descriptor.
|
||||
*/
|
||||
|
||||
VOID CMAPI
|
||||
HvFree(
|
||||
PHHIVE RegistryHive)
|
||||
{
|
||||
if (!RegistryHive->ReadOnly)
|
||||
{
|
||||
/* Release hive bitmap */
|
||||
if (RegistryHive->DirtyVector.Buffer)
|
||||
{
|
||||
RegistryHive->Free(RegistryHive->DirtyVector.Buffer, 0);
|
||||
}
|
||||
|
||||
HvpFreeHiveBins(RegistryHive);
|
||||
}
|
||||
|
||||
RegistryHive->Free(RegistryHive, 0);
|
||||
}
|
||||
|
||||
/* EOF */
|
32
lib/cmlib/hivesum.c
Normal file
32
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(
|
||||
PHBASE_BLOCK 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;
|
||||
}
|
292
lib/cmlib/hivewrt.c
Normal file
292
lib/cmlib/hivewrt.c
Normal file
|
@ -0,0 +1,292 @@
|
|||
/*
|
||||
* 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(
|
||||
PHHIVE RegistryHive)
|
||||
{
|
||||
ULONG FileOffset;
|
||||
SIZE_T BufferSize;
|
||||
SIZE_T BitmapSize;
|
||||
PUCHAR Buffer;
|
||||
PUCHAR Ptr;
|
||||
ULONG BlockIndex;
|
||||
ULONG LastIndex;
|
||||
PVOID BlockPtr;
|
||||
BOOLEAN Success;
|
||||
|
||||
UNIMPLEMENTED;
|
||||
return TRUE;
|
||||
|
||||
ASSERT(RegistryHive->ReadOnly == FALSE);
|
||||
|
||||
DPRINT("HvpWriteLog called\n");
|
||||
|
||||
if (RegistryHive->BaseBlock->Sequence1 !=
|
||||
RegistryHive->BaseBlock->Sequence2)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BitmapSize = RegistryHive->DirtyVector.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, TAG_CM);
|
||||
if (Buffer == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Update first update counter and CheckSum */
|
||||
RegistryHive->BaseBlock->Type = HFILE_TYPE_LOG;
|
||||
RegistryHive->BaseBlock->Sequence1++;
|
||||
RegistryHive->BaseBlock->CheckSum =
|
||||
HvpHiveHeaderChecksum(RegistryHive->BaseBlock);
|
||||
|
||||
/* Copy hive header */
|
||||
RtlCopyMemory(Buffer, RegistryHive->BaseBlock, HV_LOG_HEADER_SIZE);
|
||||
Ptr = Buffer + HV_LOG_HEADER_SIZE;
|
||||
RtlCopyMemory(Ptr, "DIRT", 4);
|
||||
Ptr += 4;
|
||||
RtlCopyMemory(Ptr, RegistryHive->DirtyVector.Buffer, BitmapSize);
|
||||
|
||||
/* Write hive block and block bitmap */
|
||||
FileOffset = 0;
|
||||
Success = RegistryHive->FileWrite(RegistryHive, HFILE_TYPE_LOG,
|
||||
&FileOffset, Buffer, BufferSize);
|
||||
RegistryHive->Free(Buffer, 0);
|
||||
|
||||
if (!Success)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Write dirty blocks */
|
||||
FileOffset = BufferSize;
|
||||
BlockIndex = 0;
|
||||
while (BlockIndex < RegistryHive->Storage[Stable].Length)
|
||||
{
|
||||
LastIndex = BlockIndex;
|
||||
BlockIndex = RtlFindSetBits(&RegistryHive->DirtyVector, 1, BlockIndex);
|
||||
if (BlockIndex == ~0U || BlockIndex < LastIndex)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
BlockPtr = (PVOID)RegistryHive->Storage[Stable].BlockList[BlockIndex].BlockAddress;
|
||||
|
||||
/* Write hive block */
|
||||
Success = RegistryHive->FileWrite(RegistryHive, HFILE_TYPE_LOG,
|
||||
&FileOffset, BlockPtr,
|
||||
HV_BLOCK_SIZE);
|
||||
if (!Success)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BlockIndex++;
|
||||
FileOffset += HV_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
Success = RegistryHive->FileSetSize(RegistryHive, HFILE_TYPE_LOG, FileOffset, FileOffset);
|
||||
if (!Success)
|
||||
{
|
||||
DPRINT("FileSetSize failed\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Flush the log file */
|
||||
Success = RegistryHive->FileFlush(RegistryHive, HFILE_TYPE_LOG, NULL, 0);
|
||||
if (!Success)
|
||||
{
|
||||
DPRINT("FileFlush failed\n");
|
||||
}
|
||||
|
||||
/* Update first and second update counter and CheckSum. */
|
||||
RegistryHive->BaseBlock->Sequence2++;
|
||||
RegistryHive->BaseBlock->CheckSum =
|
||||
HvpHiveHeaderChecksum(RegistryHive->BaseBlock);
|
||||
|
||||
/* Write hive header again with updated sequence counter. */
|
||||
FileOffset = 0;
|
||||
Success = RegistryHive->FileWrite(RegistryHive, HFILE_TYPE_LOG,
|
||||
&FileOffset, RegistryHive->BaseBlock,
|
||||
HV_LOG_HEADER_SIZE);
|
||||
if (!Success)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Flush the log file */
|
||||
Success = RegistryHive->FileFlush(RegistryHive, HFILE_TYPE_LOG, NULL, 0);
|
||||
if (!Success)
|
||||
{
|
||||
DPRINT("FileFlush failed\n");
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOLEAN CMAPI
|
||||
HvpWriteHive(
|
||||
PHHIVE RegistryHive,
|
||||
BOOLEAN OnlyDirty)
|
||||
{
|
||||
ULONG FileOffset;
|
||||
ULONG BlockIndex;
|
||||
ULONG LastIndex;
|
||||
PVOID BlockPtr;
|
||||
BOOLEAN Success;
|
||||
|
||||
ASSERT(RegistryHive->ReadOnly == FALSE);
|
||||
|
||||
DPRINT("HvpWriteHive called\n");
|
||||
|
||||
if (RegistryHive->BaseBlock->Sequence1 !=
|
||||
RegistryHive->BaseBlock->Sequence2)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Update first update counter and CheckSum */
|
||||
RegistryHive->BaseBlock->Type = HFILE_TYPE_PRIMARY;
|
||||
RegistryHive->BaseBlock->Sequence1++;
|
||||
RegistryHive->BaseBlock->CheckSum =
|
||||
HvpHiveHeaderChecksum(RegistryHive->BaseBlock);
|
||||
|
||||
/* Write hive block */
|
||||
FileOffset = 0;
|
||||
Success = RegistryHive->FileWrite(RegistryHive, HFILE_TYPE_PRIMARY,
|
||||
&FileOffset, RegistryHive->BaseBlock,
|
||||
sizeof(HBASE_BLOCK));
|
||||
if (!Success)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BlockIndex = 0;
|
||||
while (BlockIndex < RegistryHive->Storage[Stable].Length)
|
||||
{
|
||||
if (OnlyDirty)
|
||||
{
|
||||
LastIndex = BlockIndex;
|
||||
BlockIndex = RtlFindSetBits(&RegistryHive->DirtyVector, 1, BlockIndex);
|
||||
if (BlockIndex == ~0U || BlockIndex < LastIndex)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
BlockPtr = (PVOID)RegistryHive->Storage[Stable].BlockList[BlockIndex].BlockAddress;
|
||||
FileOffset = (BlockIndex + 1) * HV_BLOCK_SIZE;
|
||||
|
||||
/* Write hive block */
|
||||
Success = RegistryHive->FileWrite(RegistryHive, HFILE_TYPE_PRIMARY,
|
||||
&FileOffset, BlockPtr,
|
||||
HV_BLOCK_SIZE);
|
||||
if (!Success)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BlockIndex++;
|
||||
}
|
||||
|
||||
Success = RegistryHive->FileFlush(RegistryHive, HFILE_TYPE_PRIMARY, NULL, 0);
|
||||
if (!Success)
|
||||
{
|
||||
DPRINT("FileFlush failed\n");
|
||||
}
|
||||
|
||||
/* Update second update counter and CheckSum */
|
||||
RegistryHive->BaseBlock->Sequence2++;
|
||||
RegistryHive->BaseBlock->CheckSum =
|
||||
HvpHiveHeaderChecksum(RegistryHive->BaseBlock);
|
||||
|
||||
/* Write hive block */
|
||||
FileOffset = 0;
|
||||
Success = RegistryHive->FileWrite(RegistryHive, HFILE_TYPE_PRIMARY,
|
||||
&FileOffset, RegistryHive->BaseBlock,
|
||||
sizeof(HBASE_BLOCK));
|
||||
if (!Success)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Success = RegistryHive->FileFlush(RegistryHive, HFILE_TYPE_PRIMARY, NULL, 0);
|
||||
if (!Success)
|
||||
{
|
||||
DPRINT("FileFlush failed\n");
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOLEAN CMAPI
|
||||
HvSyncHive(
|
||||
PHHIVE RegistryHive)
|
||||
{
|
||||
ASSERT(RegistryHive->ReadOnly == FALSE);
|
||||
|
||||
if (RtlFindSetBits(&RegistryHive->DirtyVector, 1, 0) == ~0U)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Update hive header modification time */
|
||||
KeQuerySystemTime(&RegistryHive->BaseBlock->TimeStamp);
|
||||
|
||||
/* Update log file */
|
||||
if (!HvpWriteLog(RegistryHive))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Update hive file */
|
||||
if (!HvpWriteHive(RegistryHive, TRUE))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Clear dirty bitmap. */
|
||||
RtlClearAllBits(&RegistryHive->DirtyVector);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
CMAPI
|
||||
HvHiveWillShrink(IN PHHIVE RegistryHive)
|
||||
{
|
||||
/* No shrinking yet */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOLEAN CMAPI
|
||||
HvWriteHive(
|
||||
PHHIVE RegistryHive)
|
||||
{
|
||||
ASSERT(RegistryHive->ReadOnly == FALSE);
|
||||
|
||||
/* Update hive header modification time */
|
||||
KeQuerySystemTime(&RegistryHive->BaseBlock->TimeStamp);
|
||||
|
||||
/* Update hive file */
|
||||
if (!HvpWriteHive(RegistryHive, FALSE))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue