[CMLIB]: Go from 3-space indentation to 4-space.

svn path=/trunk/; revision=70562
This commit is contained in:
Hermès Bélusca-Maïto 2016-01-09 23:42:45 +00:00
parent c55976dada
commit c8688507db
10 changed files with 1047 additions and 1047 deletions

View file

@ -1,5 +1,5 @@
/*
* PROJECT: registry manipulation library
* 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

View file

@ -1,5 +1,5 @@
/*
* PROJECT: registry manipulation library
* 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
@ -13,124 +13,124 @@ ULONG CmlibTraceLevel = 0;
BOOLEAN CMAPI
CmCreateRootNode(
PHHIVE Hive,
PCWSTR Name)
PHHIVE Hive,
PCWSTR Name)
{
PCM_KEY_NODE KeyCell;
HCELL_INDEX RootCellIndex;
ULONG NameSize;
PCM_KEY_NODE KeyCell;
HCELL_INDEX RootCellIndex;
ULONG NameSize;
/* Allocate the cell */
NameSize = (ULONG)strlenW(Name) * sizeof(WCHAR);
RootCellIndex = HvAllocateCell(Hive,
FIELD_OFFSET(CM_KEY_NODE, Name) + NameSize,
Stable,
HCELL_NIL);
if (RootCellIndex == HCELL_NIL) return FALSE;
/* Allocate the cell */
NameSize = (ULONG)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);
/* 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;
/* 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;
/* 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;
RtlCopyMemory(KeyCell->Name, Name, NameSize);
/* Write the name */
KeyCell->NameLength = (USHORT)NameSize;
RtlCopyMemory(KeyCell->Name, Name, NameSize);
/* Return success */
HvReleaseCell(Hive, RootCellIndex);
return TRUE;
/* Return success */
HvReleaseCell(Hive, RootCellIndex);
return TRUE;
}
static VOID CMAPI
CmpPrepareKey(
PHHIVE RegistryHive,
PCM_KEY_NODE KeyCell);
PHHIVE RegistryHive,
PCM_KEY_NODE KeyCell);
static VOID CMAPI
CmpPrepareIndexOfKeys(
PHHIVE RegistryHive,
PCM_KEY_INDEX IndexCell)
PHHIVE RegistryHive,
PCM_KEY_INDEX IndexCell)
{
ULONG i;
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);
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)
PHHIVE RegistryHive,
PCM_KEY_NODE KeyCell)
{
PCM_KEY_INDEX IndexCell;
PCM_KEY_INDEX IndexCell;
ASSERT(KeyCell->Signature == CM_KEY_NODE_SIGNATURE);
ASSERT(KeyCell->Signature == CM_KEY_NODE_SIGNATURE);
KeyCell->SubKeyLists[Volatile] = HCELL_NIL;
KeyCell->SubKeyCounts[Volatile] = 0;
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);
}
/* Enumerate and add subkeys */
if (KeyCell->SubKeyCounts[Stable] > 0)
{
IndexCell = HvGetCell(RegistryHive, KeyCell->SubKeyLists[Stable]);
CmpPrepareIndexOfKeys(RegistryHive, IndexCell);
}
}
VOID CMAPI
CmPrepareHive(
PHHIVE RegistryHive)
PHHIVE RegistryHive)
{
PCM_KEY_NODE RootCell;
PCM_KEY_NODE RootCell;
RootCell = HvGetCell(RegistryHive, RegistryHive->BaseBlock->RootCell);
CmpPrepareKey(RegistryHive, RootCell);
RootCell = HvGetCell(RegistryHive, RegistryHive->BaseBlock->RootCell);
CmpPrepareKey(RegistryHive, RootCell);
}

View file

@ -1,5 +1,5 @@
/*
* PROJECT: registry manipulation library
* 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

View file

@ -1,5 +1,5 @@
/*
* PROJECT: registry manipulation library
* 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

View file

@ -1,5 +1,5 @@
/*
* PROJECT: registry manipulation library
* 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
@ -10,98 +10,98 @@
PHBIN CMAPI
HvpAddBin(
PHHIVE RegistryHive,
ULONG Size,
HSTORAGE_TYPE Storage)
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;
PHMAP_ENTRY BlockList;
PHBIN Bin;
SIZE_T BinSize;
ULONG i;
ULONG BitmapSize;
ULONG BlockCount;
ULONG OldBlockListSize;
PHCELL Block;
BinSize = ROUND_UP(Size + sizeof(HBIN), HBLOCK_SIZE);
BlockCount = (ULONG)(BinSize / HBLOCK_SIZE);
BinSize = ROUND_UP(Size + sizeof(HBIN), HBLOCK_SIZE);
BlockCount = (ULONG)(BinSize / HBLOCK_SIZE);
Bin = RegistryHive->Allocate(BinSize, TRUE, TAG_CM);
if (Bin == NULL)
return NULL;
RtlZeroMemory(Bin, BinSize);
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 *
HBLOCK_SIZE;
Bin->Size = (ULONG)BinSize;
Bin->Signature = HV_BIN_SIGNATURE;
Bin->FileOffset = RegistryHive->Storage[Storage].Length *
HBLOCK_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;
}
/* 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);
}
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;
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 * HBLOCK_SIZE));
RegistryHive->Storage[Storage].BlockList[OldBlockListSize + i].BinAddress = (ULONG_PTR)Bin;
}
for (i = 0; i < BlockCount; i++)
{
RegistryHive->Storage[Storage].BlockList[OldBlockListSize + i].BlockAddress =
((ULONG_PTR)Bin + (i * HBLOCK_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));
/* 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;
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;
/* 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);
}
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 / HBLOCK_SIZE,
BlockCount);
/* Mark new bin dirty. */
RtlSetBits(&RegistryHive->DirtyVector,
Bin->FileOffset / HBLOCK_SIZE,
BlockCount);
/* Update size in the base block */
RegistryHive->BaseBlock->Length += BinSize;
}
/* Update size in the base block */
RegistryHive->BaseBlock->Length += BinSize;
}
return Bin;
return Bin;
}

View file

@ -1,5 +1,5 @@
/*
* PROJECT: registry manipulation library
* 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
@ -11,514 +11,515 @@
static __inline PHCELL CMAPI
HvpGetCellHeader(
PHHIVE RegistryHive,
HCELL_INDEX CellIndex)
PHHIVE RegistryHive,
HCELL_INDEX CellIndex)
{
PVOID Block;
PVOID Block;
CMLTRACE(CMLIB_HCELL_DEBUG, "%s - Hive %p, CellIndex %08lx\n",
__FUNCTION__, RegistryHive, CellIndex);
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;
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 + HBLOCK_SIZE +
CellIndex);
}
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 + HBLOCK_SIZE +
CellIndex);
}
}
BOOLEAN CMAPI
HvIsCellAllocated(IN PHHIVE RegistryHive,
IN HCELL_INDEX CellIndex)
{
ULONG Type, Block;
ULONG Type, Block;
/* If it's a flat hive, the cell is always allocated */
if (RegistryHive->Flat)
return TRUE;
/* 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;
/* 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;
/* Try to get the cell block */
if (RegistryHive->Storage[Type].BlockList[Block].BlockAddress)
return TRUE;
/* No valid block, fail */
return FALSE;
/* No valid block, fail */
return FALSE;
}
PVOID CMAPI
HvGetCell(
PHHIVE RegistryHive,
HCELL_INDEX CellIndex)
PHHIVE RegistryHive,
HCELL_INDEX CellIndex)
{
ASSERT(CellIndex != HCELL_NIL);
return (PVOID)(HvpGetCellHeader(RegistryHive, CellIndex) + 1);
ASSERT(CellIndex != HCELL_NIL);
return (PVOID)(HvpGetCellHeader(RegistryHive, CellIndex) + 1);
}
static __inline LONG CMAPI
HvpGetCellFullSize(
PHHIVE RegistryHive,
PVOID Cell)
PHHIVE RegistryHive,
PVOID Cell)
{
UNREFERENCED_PARAMETER(RegistryHive);
return ((PHCELL)Cell - 1)->Size;
UNREFERENCED_PARAMETER(RegistryHive);
return ((PHCELL)Cell - 1)->Size;
}
LONG CMAPI
HvGetCellSize(IN PHHIVE Hive,
IN PVOID Address)
{
PHCELL CellHeader;
LONG Size;
PHCELL CellHeader;
LONG Size;
UNREFERENCED_PARAMETER(Hive);
UNREFERENCED_PARAMETER(Hive);
CellHeader = (PHCELL)Address - 1;
Size = CellHeader->Size * -1;
Size -= sizeof(HCELL);
return Size;
CellHeader = (PHCELL)Address - 1;
Size = CellHeader->Size * -1;
Size -= sizeof(HCELL);
return Size;
}
BOOLEAN CMAPI
HvMarkCellDirty(
PHHIVE RegistryHive,
HCELL_INDEX CellIndex,
BOOLEAN HoldingLock)
PHHIVE RegistryHive,
HCELL_INDEX CellIndex,
BOOLEAN HoldingLock)
{
ULONG CellBlock;
ULONG CellLastBlock;
ULONG CellBlock;
ULONG CellLastBlock;
ASSERT(RegistryHive->ReadOnly == FALSE);
ASSERT(RegistryHive->ReadOnly == FALSE);
CMLTRACE(CMLIB_HCELL_DEBUG, "%s - Hive %p, CellIndex %08lx, HoldingLock %u\n",
__FUNCTION__, RegistryHive, CellIndex, HoldingLock);
CMLTRACE(CMLIB_HCELL_DEBUG, "%s - Hive %p, CellIndex %08lx, HoldingLock %u\n",
__FUNCTION__, RegistryHive, CellIndex, HoldingLock);
if ((CellIndex & HCELL_TYPE_MASK) >> HCELL_TYPE_SHIFT != Stable)
return TRUE;
if ((CellIndex & HCELL_TYPE_MASK) >> HCELL_TYPE_SHIFT != Stable)
return TRUE;
CellBlock = (CellIndex & HCELL_BLOCK_MASK) >> HCELL_BLOCK_SHIFT;
CellLastBlock = ((CellIndex + HBLOCK_SIZE - 1) & HCELL_BLOCK_MASK) >> HCELL_BLOCK_SHIFT;
CellBlock = (CellIndex & HCELL_BLOCK_MASK) >> HCELL_BLOCK_SHIFT;
CellLastBlock = ((CellIndex + HBLOCK_SIZE - 1) & HCELL_BLOCK_MASK) >> HCELL_BLOCK_SHIFT;
RtlSetBits(&RegistryHive->DirtyVector,
CellBlock, CellLastBlock - CellBlock);
RegistryHive->DirtyCount++;
return TRUE;
RtlSetBits(&RegistryHive->DirtyVector,
CellBlock, CellLastBlock - CellBlock);
RegistryHive->DirtyCount++;
return TRUE;
}
BOOLEAN CMAPI
HvIsCellDirty(IN PHHIVE Hive,
IN HCELL_INDEX Cell)
{
BOOLEAN IsDirty = FALSE;
BOOLEAN IsDirty = FALSE;
/* Sanity checks */
ASSERT(Hive->ReadOnly == FALSE);
/* Sanity checks */
ASSERT(Hive->ReadOnly == FALSE);
/* Volatile cells are always "dirty" */
if (HvGetCellType(Cell) == Volatile)
return TRUE;
/* Volatile cells are always "dirty" */
if (HvGetCellType(Cell) == Volatile)
return TRUE;
/* Check if the dirty bit is set */
if (RtlCheckBit(&Hive->DirtyVector, Cell / HBLOCK_SIZE))
IsDirty = TRUE;
/* Check if the dirty bit is set */
if (RtlCheckBit(&Hive->DirtyVector, Cell / HBLOCK_SIZE))
IsDirty = TRUE;
/* Return result as boolean*/
return IsDirty;
/* Return result as boolean*/
return IsDirty;
}
static __inline ULONG CMAPI
HvpComputeFreeListIndex(
ULONG Size)
ULONG Size)
{
ULONG Index;
static CCHAR FindFirstSet[128] = {
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};
ULONG Index;
static CCHAR FindFirstSet[128] = {
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};
ASSERT(Size >= (1 << 3));
Index = (Size >> 3) - 1;
if (Index >= 16)
{
if (Index > 127)
Index = 23;
else
Index = FindFirstSet[Index] + 16;
}
ASSERT(Size >= (1 << 3));
Index = (Size >> 3) - 1;
if (Index >= 16)
{
if (Index > 127)
Index = 23;
else
Index = FindFirstSet[Index] + 16;
}
return Index;
return Index;
}
static NTSTATUS CMAPI
HvpAddFree(
PHHIVE RegistryHive,
PHCELL FreeBlock,
HCELL_INDEX FreeIndex)
PHHIVE RegistryHive,
PHCELL FreeBlock,
HCELL_INDEX FreeIndex)
{
PHCELL_INDEX FreeBlockData;
HSTORAGE_TYPE Storage;
ULONG Index;
PHCELL_INDEX FreeBlockData;
HSTORAGE_TYPE Storage;
ULONG Index;
ASSERT(RegistryHive != NULL);
ASSERT(FreeBlock != NULL);
ASSERT(RegistryHive != NULL);
ASSERT(FreeBlock != NULL);
Storage = (FreeIndex & HCELL_TYPE_MASK) >> HCELL_TYPE_SHIFT;
Index = HvpComputeFreeListIndex((ULONG)FreeBlock->Size);
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;
FreeBlockData = (PHCELL_INDEX)(FreeBlock + 1);
*FreeBlockData = RegistryHive->Storage[Storage].FreeDisplay[Index];
RegistryHive->Storage[Storage].FreeDisplay[Index] = FreeIndex;
/* FIXME: Eventually get rid of free bins. */
/* FIXME: Eventually get rid of free bins. */
return STATUS_SUCCESS;
return STATUS_SUCCESS;
}
static VOID CMAPI
HvpRemoveFree(
PHHIVE RegistryHive,
PHCELL CellBlock,
HCELL_INDEX CellIndex)
PHHIVE RegistryHive,
PHCELL CellBlock,
HCELL_INDEX CellIndex)
{
PHCELL_INDEX FreeCellData;
PHCELL_INDEX pFreeCellOffset;
HSTORAGE_TYPE Storage;
ULONG Index, FreeListIndex;
PHCELL_INDEX FreeCellData;
PHCELL_INDEX pFreeCellOffset;
HSTORAGE_TYPE Storage;
ULONG Index, FreeListIndex;
ASSERT(RegistryHive->ReadOnly == FALSE);
ASSERT(RegistryHive->ReadOnly == FALSE);
Storage = (CellIndex & HCELL_TYPE_MASK) >> HCELL_TYPE_SHIFT;
Index = HvpComputeFreeListIndex((ULONG)CellBlock->Size);
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;
}
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: %u\n", Index);
for (FreeListIndex = 0; FreeListIndex < 24; FreeListIndex++)
{
CMLTRACE(CMLIB_HCELL_DEBUG, "free list [%u]: ", 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");
/* 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: %u\n", Index);
for (FreeListIndex = 0; FreeListIndex < 24; FreeListIndex++)
{
CMLTRACE(CMLIB_HCELL_DEBUG, "free list [%u]: ", 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);
ASSERT(FALSE);
}
static HCELL_INDEX CMAPI
HvpFindFree(
PHHIVE RegistryHive,
ULONG Size,
HSTORAGE_TYPE Storage)
PHHIVE RegistryHive,
ULONG Size,
HSTORAGE_TYPE Storage)
{
PHCELL_INDEX FreeCellData;
HCELL_INDEX FreeCellOffset;
PHCELL_INDEX pFreeCellOffset;
ULONG Index;
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;
}
}
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;
return HCELL_NIL;
}
NTSTATUS CMAPI
HvpCreateHiveFreeCellList(
PHHIVE Hive)
PHHIVE Hive)
{
HCELL_INDEX BlockOffset;
PHCELL FreeBlock;
ULONG BlockIndex;
ULONG FreeOffset;
PHBIN Bin;
NTSTATUS Status;
ULONG Index;
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;
}
/* 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;
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;
/* 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;
}
}
FreeOffset += FreeBlock->Size;
}
else
{
FreeOffset -= FreeBlock->Size;
}
}
BlockIndex += Bin->Size / HBLOCK_SIZE;
BlockOffset += Bin->Size;
}
BlockIndex += Bin->Size / HBLOCK_SIZE;
BlockOffset += Bin->Size;
}
return STATUS_SUCCESS;
return STATUS_SUCCESS;
}
HCELL_INDEX CMAPI
HvAllocateCell(
PHHIVE RegistryHive,
ULONG Size,
HSTORAGE_TYPE Storage,
HCELL_INDEX Vicinity)
PHHIVE RegistryHive,
ULONG Size,
HSTORAGE_TYPE Storage,
HCELL_INDEX Vicinity)
{
PHCELL FreeCell;
HCELL_INDEX FreeCellOffset;
PHCELL NewCell;
PHBIN Bin;
PHCELL FreeCell;
HCELL_INDEX FreeCellOffset;
PHCELL NewCell;
PHBIN Bin;
ASSERT(RegistryHive->ReadOnly == FALSE);
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);
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);
/* Round to 16 bytes multiple. */
Size = ROUND_UP(Size + sizeof(HCELL), 16);
/* First search in free blocks. */
FreeCellOffset = HvpFindFree(RegistryHive, Size, Storage);
/* 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;
}
/* 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);
FreeCell = HvpGetCellHeader(RegistryHive, FreeCellOffset);
/* Split the block in two parts */
/* 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);
}
/* 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));
if (Storage == Stable)
HvMarkCellDirty(RegistryHive, FreeCellOffset, FALSE);
CMLTRACE(CMLIB_HCELL_DEBUG, "%s - CellIndex %08lx\n",
__FUNCTION__, FreeCellOffset);
FreeCell->Size = -FreeCell->Size;
RtlZeroMemory(FreeCell + 1, Size - sizeof(HCELL));
return FreeCellOffset;
CMLTRACE(CMLIB_HCELL_DEBUG, "%s - CellIndex %08lx\n",
__FUNCTION__, FreeCellOffset);
return FreeCellOffset;
}
HCELL_INDEX CMAPI
HvReallocateCell(
PHHIVE RegistryHive,
HCELL_INDEX CellIndex,
ULONG Size)
PHHIVE RegistryHive,
HCELL_INDEX CellIndex,
ULONG Size)
{
PVOID OldCell;
PVOID NewCell;
LONG OldCellSize;
HCELL_INDEX NewCellIndex;
HSTORAGE_TYPE Storage;
PVOID OldCell;
PVOID NewCell;
LONG OldCellSize;
HCELL_INDEX NewCellIndex;
HSTORAGE_TYPE Storage;
ASSERT(CellIndex != HCELL_NIL);
ASSERT(CellIndex != HCELL_NIL);
CMLTRACE(CMLIB_HCELL_DEBUG, "%s - Hive %p, CellIndex %08lx, Size %x\n",
__FUNCTION__, RegistryHive, CellIndex, Size);
CMLTRACE(CMLIB_HCELL_DEBUG, "%s - Hive %p, CellIndex %08lx, Size %x\n",
__FUNCTION__, RegistryHive, CellIndex, Size);
Storage = (CellIndex & HCELL_TYPE_MASK) >> HCELL_TYPE_SHIFT;
Storage = (CellIndex & HCELL_TYPE_MASK) >> HCELL_TYPE_SHIFT;
OldCell = HvGetCell(RegistryHive, CellIndex);
OldCellSize = HvGetCellSize(RegistryHive, OldCell);
ASSERT(OldCellSize > 0);
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;
/*
* 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);
NewCell = HvGetCell(RegistryHive, NewCellIndex);
RtlCopyMemory(NewCell, OldCell, (SIZE_T)OldCellSize);
HvFreeCell(RegistryHive, CellIndex);
HvFreeCell(RegistryHive, CellIndex);
return NewCellIndex;
}
return NewCellIndex;
}
return CellIndex;
return CellIndex;
}
VOID CMAPI
HvFreeCell(
PHHIVE RegistryHive,
HCELL_INDEX CellIndex)
PHHIVE RegistryHive,
HCELL_INDEX CellIndex)
{
PHCELL Free;
PHCELL Neighbor;
PHBIN Bin;
ULONG CellType;
ULONG CellBlock;
PHCELL Free;
PHCELL Neighbor;
PHBIN Bin;
ULONG CellType;
ULONG CellBlock;
ASSERT(RegistryHive->ReadOnly == FALSE);
ASSERT(RegistryHive->ReadOnly == FALSE);
CMLTRACE(CMLIB_HCELL_DEBUG, "%s - Hive %p, CellIndex %08lx\n",
__FUNCTION__, RegistryHive, CellIndex);
CMLTRACE(CMLIB_HCELL_DEBUG, "%s - Hive %p, CellIndex %08lx\n",
__FUNCTION__, RegistryHive, CellIndex);
Free = HvpGetCellHeader(RegistryHive, CellIndex);
Free = HvpGetCellHeader(RegistryHive, CellIndex);
ASSERT(Free->Size < 0);
ASSERT(Free->Size < 0);
Free->Size = -Free->Size;
Free->Size = -Free->Size;
CellType = (CellIndex & HCELL_TYPE_MASK) >> HCELL_TYPE_SHIFT;
CellBlock = (CellIndex & HCELL_BLOCK_MASK) >> HCELL_BLOCK_SHIFT;
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;
/* 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;
}
}
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))
Neighbor = (PHCELL)(Bin + 1);
while (Neighbor < Free)
{
if (Neighbor->Size > 0)
{
if ((ULONG_PTR)Neighbor + Neighbor->Size == (ULONG_PTR)Free)
{
HvpRemoveFree(RegistryHive, Neighbor, NeighborCellIndex);
Neighbor->Size += Free->Size;
HvpAddFree(RegistryHive, Neighbor, NeighborCellIndex);
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;
}
else
Neighbor->Size += Free->Size;
Neighbor = (PHCELL)((ULONG_PTR)Neighbor + Neighbor->Size);
}
else
{
Neighbor = (PHCELL)((ULONG_PTR)Neighbor - Neighbor->Size);
}
}
if (CellType == Stable)
HvMarkCellDirty(RegistryHive, NeighborCellIndex, FALSE);
/* Add block to the list of free blocks */
HvpAddFree(RegistryHive, Free, CellIndex);
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);
if (CellType == Stable)
HvMarkCellDirty(RegistryHive, CellIndex, FALSE);
}
BOOLEAN

View file

@ -1,5 +1,5 @@
/*
* PROJECT: registry manipulation library
* 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

View file

@ -1,5 +1,5 @@
/*
* PROJECT: registry manipulation library
* 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
@ -17,32 +17,32 @@
BOOLEAN CMAPI
HvpVerifyHiveHeader(
PHBASE_BLOCK BaseBlock)
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, expected 0x%x; Major: 0x%x, expected 0x%x\n",
BaseBlock->Signature, HV_SIGNATURE, BaseBlock->Major, HSYS_MAJOR);
DPRINT1(" Minor: 0x%x is not >= 0x%x; Type: 0x%x, expected 0x%x\n",
BaseBlock->Minor, HSYS_MINOR, BaseBlock->Type, HFILE_TYPE_PRIMARY);
DPRINT1(" Format: 0x%x, expected 0x%x; Cluster: 0x%x, expected 1\n",
BaseBlock->Format, HBASE_FORMAT_MEMORY, BaseBlock->Cluster);
DPRINT1(" Sequence: 0x%x, expected 0x%x; Checksum: 0x%x, expected 0x%x\n",
BaseBlock->Sequence1, BaseBlock->Sequence2,
HvpHiveHeaderChecksum(BaseBlock), BaseBlock->CheckSum);
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, expected 0x%x; Major: 0x%x, expected 0x%x\n",
BaseBlock->Signature, HV_SIGNATURE, BaseBlock->Major, HSYS_MAJOR);
DPRINT1(" Minor: 0x%x is not >= 0x%x; Type: 0x%x, expected 0x%x\n",
BaseBlock->Minor, HSYS_MINOR, BaseBlock->Type, HFILE_TYPE_PRIMARY);
DPRINT1(" Format: 0x%x, expected 0x%x; Cluster: 0x%x, expected 1\n",
BaseBlock->Format, HBASE_FORMAT_MEMORY, BaseBlock->Cluster);
DPRINT1(" Sequence: 0x%x, expected 0x%x; Checksum: 0x%x, expected 0x%x\n",
BaseBlock->Sequence1, BaseBlock->Sequence2,
HvpHiveHeaderChecksum(BaseBlock), BaseBlock->CheckSum);
return FALSE;
}
return FALSE;
}
return TRUE;
return TRUE;
}
/**
@ -54,31 +54,31 @@ HvpVerifyHiveHeader(
VOID CMAPI
HvpFreeHiveBins(
PHHIVE Hive)
PHHIVE Hive)
{
ULONG i;
PHBIN Bin;
ULONG Storage;
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;
}
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);
}
if (Hive->Storage[Storage].Length)
Hive->Free(Hive->Storage[Storage].BlockList, 0);
}
}
/**
@ -92,60 +92,60 @@ HvpFreeHiveBins(
NTSTATUS CMAPI
HvpCreateHive(
PHHIVE RegistryHive,
PCUNICODE_STRING FileName OPTIONAL)
PHHIVE RegistryHive,
PCUNICODE_STRING FileName OPTIONAL)
{
PHBASE_BLOCK BaseBlock;
ULONG Index;
PHBASE_BLOCK BaseBlock;
ULONG Index;
BaseBlock = RegistryHive->Allocate(sizeof(HBASE_BLOCK), FALSE, TAG_CM);
if (BaseBlock == NULL)
return STATUS_NO_MEMORY;
BaseBlock = RegistryHive->Allocate(sizeof(HBASE_BLOCK), FALSE, TAG_CM);
if (BaseBlock == NULL)
return STATUS_NO_MEMORY;
RtlZeroMemory(BaseBlock, sizeof(HBASE_BLOCK));
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 = 0;
BaseBlock->Sequence1 = 1;
BaseBlock->Sequence2 = 1;
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 = 0;
BaseBlock->Sequence1 = 1;
BaseBlock->Sequence2 = 1;
/* Copy the 31 last characters of the hive file name if any */
if (FileName)
{
if (FileName->Length / sizeof(WCHAR) <= HIVE_FILENAME_MAXLEN)
{
RtlCopyMemory(BaseBlock->FileName,
FileName->Buffer,
FileName->Length);
}
else
{
RtlCopyMemory(BaseBlock->FileName,
FileName->Buffer +
FileName->Length / sizeof(WCHAR) - HIVE_FILENAME_MAXLEN,
HIVE_FILENAME_MAXLEN * sizeof(WCHAR));
}
/* Copy the 31 last characters of the hive file name if any */
if (FileName)
{
if (FileName->Length / sizeof(WCHAR) <= HIVE_FILENAME_MAXLEN)
{
RtlCopyMemory(BaseBlock->FileName,
FileName->Buffer,
FileName->Length);
}
else
{
RtlCopyMemory(BaseBlock->FileName,
FileName->Buffer +
FileName->Length / sizeof(WCHAR) - HIVE_FILENAME_MAXLEN,
HIVE_FILENAME_MAXLEN * sizeof(WCHAR));
}
/* NULL-terminate */
BaseBlock->FileName[HIVE_FILENAME_MAXLEN] = L'\0';
}
/* NULL-terminate */
BaseBlock->FileName[HIVE_FILENAME_MAXLEN] = L'\0';
}
BaseBlock->CheckSum = HvpHiveHeaderChecksum(BaseBlock);
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;
}
RegistryHive->BaseBlock = BaseBlock;
for (Index = 0; Index < 24; Index++)
{
RegistryHive->Storage[Stable].FreeDisplay[Index] = HCELL_NIL;
RegistryHive->Storage[Volatile].FreeDisplay[Index] = HCELL_NIL;
}
return STATUS_SUCCESS;
return STATUS_SUCCESS;
}
/**
@ -160,110 +160,110 @@ HvpCreateHive(
NTSTATUS CMAPI
HvpInitializeMemoryHive(
PHHIVE Hive,
PVOID ChunkBase)
PHHIVE Hive,
PVOID ChunkBase)
{
SIZE_T BlockIndex;
PHBIN Bin, NewBin;
ULONG i;
ULONG BitmapSize;
PULONG BitmapBuffer;
SIZE_T ChunkSize;
SIZE_T BlockIndex;
PHBIN Bin, NewBin;
ULONG i;
ULONG BitmapSize;
PULONG BitmapBuffer;
SIZE_T ChunkSize;
ChunkSize = ((PHBASE_BLOCK)ChunkBase)->Length;
DPRINT("ChunkSize: %lx\n", ChunkSize);
ChunkSize = ((PHBASE_BLOCK)ChunkBase)->Length;
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;
}
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));
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.
*/
/*
* Build a block list from the in-memory chunk and copy the data as
* we go.
*/
Hive->Storage[Stable].Length = (ULONG)(ChunkSize / HBLOCK_SIZE);
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;
}
Hive->Storage[Stable].Length = (ULONG)(ChunkSize / HBLOCK_SIZE);
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) * HBLOCK_SIZE);
if (Bin->Signature != HV_BIN_SIGNATURE ||
(Bin->Size % HBLOCK_SIZE) != 0)
{
DPRINT1("Invalid bin at BlockIndex %lu, Signature 0x%x, Size 0x%x\n",
(unsigned long)BlockIndex, (unsigned)Bin->Signature, (unsigned)Bin->Size);
Hive->Free(Hive->BaseBlock, 0);
Hive->Free(Hive->Storage[Stable].BlockList, 0);
return STATUS_REGISTRY_CORRUPT;
}
for (BlockIndex = 0; BlockIndex < Hive->Storage[Stable].Length; )
{
Bin = (PHBIN)((ULONG_PTR)ChunkBase + (BlockIndex + 1) * HBLOCK_SIZE);
if (Bin->Signature != HV_BIN_SIGNATURE ||
(Bin->Size % HBLOCK_SIZE) != 0)
{
DPRINT1("Invalid bin at BlockIndex %lu, Signature 0x%x, Size 0x%x\n",
(unsigned long)BlockIndex, (unsigned)Bin->Signature, (unsigned)Bin->Size);
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;
}
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;
Hive->Storage[Stable].BlockList[BlockIndex].BinAddress = (ULONG_PTR)NewBin;
Hive->Storage[Stable].BlockList[BlockIndex].BlockAddress = (ULONG_PTR)NewBin;
RtlCopyMemory(NewBin, Bin, Bin->Size);
RtlCopyMemory(NewBin, Bin, Bin->Size);
if (Bin->Size > HBLOCK_SIZE)
{
for (i = 1; i < Bin->Size / HBLOCK_SIZE; i++)
{
Hive->Storage[Stable].BlockList[BlockIndex + i].BinAddress = (ULONG_PTR)NewBin;
Hive->Storage[Stable].BlockList[BlockIndex + i].BlockAddress =
((ULONG_PTR)NewBin + (i * HBLOCK_SIZE));
}
}
if (Bin->Size > HBLOCK_SIZE)
{
for (i = 1; i < Bin->Size / HBLOCK_SIZE; i++)
{
Hive->Storage[Stable].BlockList[BlockIndex + i].BinAddress = (ULONG_PTR)NewBin;
Hive->Storage[Stable].BlockList[BlockIndex + i].BlockAddress =
((ULONG_PTR)NewBin + (i * HBLOCK_SIZE));
}
}
BlockIndex += Bin->Size / HBLOCK_SIZE;
}
BlockIndex += Bin->Size / HBLOCK_SIZE;
}
if (HvpCreateHiveFreeCellList(Hive))
{
HvpFreeHiveBins(Hive);
Hive->Free(Hive->BaseBlock, 0);
return STATUS_NO_MEMORY;
}
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;
}
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);
RtlInitializeBitMap(&Hive->DirtyVector, BitmapBuffer, BitmapSize * 8);
RtlClearAllBits(&Hive->DirtyVector);
return STATUS_SUCCESS;
return STATUS_SUCCESS;
}
/**
@ -278,19 +278,19 @@ HvpInitializeMemoryHive(
NTSTATUS CMAPI
HvpInitializeMemoryInplaceHive(
PHHIVE Hive,
PVOID ChunkBase)
PHHIVE Hive,
PVOID ChunkBase)
{
if (!HvpVerifyHiveHeader((PHBASE_BLOCK)ChunkBase))
{
return STATUS_REGISTRY_CORRUPT;
}
if (!HvpVerifyHiveHeader((PHBASE_BLOCK)ChunkBase))
{
return STATUS_REGISTRY_CORRUPT;
}
Hive->BaseBlock = (PHBASE_BLOCK)ChunkBase;
Hive->ReadOnly = TRUE;
Hive->Flat = TRUE;
Hive->BaseBlock = (PHBASE_BLOCK)ChunkBase;
Hive->ReadOnly = TRUE;
Hive->Flat = TRUE;
return STATUS_SUCCESS;
return STATUS_SUCCESS;
}
typedef enum _RESULT
@ -446,83 +446,83 @@ HvLoadHive(IN PHHIVE Hive,
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,
PCUNICODE_STRING FileName OPTIONAL)
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,
PCUNICODE_STRING FileName OPTIONAL)
{
NTSTATUS Status;
PHHIVE Hive = RegistryHive;
NTSTATUS Status;
PHHIVE Hive = RegistryHive;
UNREFERENCED_PARAMETER(HiveType);
UNREFERENCED_PARAMETER(HiveType);
/*
* Create a new hive structure that will hold all the maintenance data.
*/
/*
* Create a new hive structure that will hold all the maintenance data.
*/
RtlZeroMemory(Hive, sizeof(HHIVE));
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;
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, FileName);
break;
switch (Operation)
{
case HINIT_CREATE:
Status = HvpCreateHive(Hive, FileName);
break;
case HINIT_MEMORY:
Status = HvpInitializeMemoryHive(Hive, HiveData);
break;
case HINIT_MEMORY:
Status = HvpInitializeMemoryHive(Hive, HiveData);
break;
case HINIT_FLAT:
Status = HvpInitializeMemoryInplaceHive(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;
}
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 */
ASSERT(Status != STATUS_REGISTRY_RECOVERED);
break;
}
/* Check for previous damage */
ASSERT(Status != STATUS_REGISTRY_RECOVERED);
break;
}
default:
/* FIXME: A better return status value is needed */
Status = STATUS_NOT_IMPLEMENTED;
ASSERT(FALSE);
}
default:
/* FIXME: A better return status value is needed */
Status = STATUS_NOT_IMPLEMENTED;
ASSERT(FALSE);
}
if (!NT_SUCCESS(Status)) return Status;
if (!NT_SUCCESS(Status)) return Status;
if (Operation != HINIT_CREATE) CmPrepareHive(Hive);
if (Operation != HINIT_CREATE) CmPrepareHive(Hive);
return Status;
return Status;
}
/**
@ -534,25 +534,25 @@ HvInitialize(
VOID CMAPI
HvFree(
PHHIVE RegistryHive)
PHHIVE RegistryHive)
{
if (!RegistryHive->ReadOnly)
{
/* Release hive bitmap */
if (RegistryHive->DirtyVector.Buffer)
{
RegistryHive->Free(RegistryHive->DirtyVector.Buffer, 0);
}
if (!RegistryHive->ReadOnly)
{
/* Release hive bitmap */
if (RegistryHive->DirtyVector.Buffer)
{
RegistryHive->Free(RegistryHive->DirtyVector.Buffer, 0);
}
HvpFreeHiveBins(RegistryHive);
HvpFreeHiveBins(RegistryHive);
/* Free the BaseBlock */
if (RegistryHive->BaseBlock)
{
RegistryHive->Free(RegistryHive->BaseBlock, 0);
RegistryHive->BaseBlock = NULL;
}
}
/* Free the BaseBlock */
if (RegistryHive->BaseBlock)
{
RegistryHive->Free(RegistryHive->BaseBlock, 0);
RegistryHive->BaseBlock = NULL;
}
}
}
/* EOF */

View file

@ -1,5 +1,5 @@
/*
* PROJECT: registry manipulation library
* 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
@ -15,18 +15,18 @@
ULONG CMAPI
HvpHiveHeaderChecksum(
PHBASE_BLOCK HiveHeader)
PHBASE_BLOCK HiveHeader)
{
PULONG Buffer = (PULONG)HiveHeader;
ULONG Sum = 0;
ULONG i;
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;
for (i = 0; i < 127; i++)
Sum ^= Buffer[i];
if (Sum == (ULONG)-1)
Sum = (ULONG)-2;
if (Sum == 0)
Sum = 1;
return Sum;
return Sum;
}

View file

@ -1,5 +1,5 @@
/*
* PROJECT: registry manipulation library
* 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
@ -11,267 +11,265 @@
static BOOLEAN CMAPI
HvpWriteLog(
PHHIVE RegistryHive)
PHHIVE RegistryHive)
{
ULONG FileOffset;
UINT32 BufferSize;
UINT32 BitmapSize;
PUCHAR Buffer;
PUCHAR Ptr;
ULONG BlockIndex;
ULONG LastIndex;
PVOID BlockPtr;
BOOLEAN Success;
static ULONG PrintCount = 0;
ULONG FileOffset;
UINT32 BufferSize;
UINT32 BitmapSize;
PUCHAR Buffer;
PUCHAR Ptr;
ULONG BlockIndex;
ULONG LastIndex;
PVOID BlockPtr;
BOOLEAN Success;
static ULONG PrintCount = 0;
if (PrintCount++ == 0)
{
UNIMPLEMENTED;
}
return TRUE;
if (PrintCount++ == 0)
{
UNIMPLEMENTED;
}
return TRUE;
ASSERT(RegistryHive->ReadOnly == FALSE);
ASSERT(RegistryHive->BaseBlock->Length ==
RegistryHive->Storage[Stable].Length * HBLOCK_SIZE);
ASSERT(RegistryHive->ReadOnly == FALSE);
ASSERT(RegistryHive->BaseBlock->Length ==
RegistryHive->Storage[Stable].Length * HBLOCK_SIZE);
DPRINT("HvpWriteLog called\n");
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, HBLOCK_SIZE);
DPRINT("Bitmap size %u buffer size: %u\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,
HBLOCK_SIZE);
if (!Success)
{
return FALSE;
}
BlockIndex++;
FileOffset += HBLOCK_SIZE;
if (RegistryHive->BaseBlock->Sequence1 !=
RegistryHive->BaseBlock->Sequence2)
{
return FALSE;
}
Success = RegistryHive->FileSetSize(RegistryHive, HFILE_TYPE_LOG, FileOffset, FileOffset);
if (!Success)
{
DPRINT("FileSetSize failed\n");
return FALSE;
BitmapSize = RegistryHive->DirtyVector.SizeOfBitMap;
BufferSize = HV_LOG_HEADER_SIZE + sizeof(ULONG) + BitmapSize;
BufferSize = ROUND_UP(BufferSize, HBLOCK_SIZE);
DPRINT("Bitmap size %u buffer size: %u\n", BitmapSize, BufferSize);
Buffer = RegistryHive->Allocate(BufferSize, TRUE, TAG_CM);
if (Buffer == NULL)
{
return FALSE;
}
/* Flush the log file */
Success = RegistryHive->FileFlush(RegistryHive, HFILE_TYPE_LOG, NULL, 0);
if (!Success)
{
DPRINT("FileFlush failed\n");
}
/* Update first update counter and CheckSum */
RegistryHive->BaseBlock->Type = HFILE_TYPE_LOG;
RegistryHive->BaseBlock->Sequence1++;
RegistryHive->BaseBlock->CheckSum =
HvpHiveHeaderChecksum(RegistryHive->BaseBlock);
/* Update second update counter and CheckSum. */
RegistryHive->BaseBlock->Sequence2++;
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 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;
}
/* Write hive block and block bitmap */
FileOffset = 0;
Success = RegistryHive->FileWrite(RegistryHive, HFILE_TYPE_LOG,
&FileOffset, Buffer, BufferSize);
RegistryHive->Free(Buffer, 0);
/* Flush the log file */
Success = RegistryHive->FileFlush(RegistryHive, HFILE_TYPE_LOG, NULL, 0);
if (!Success)
{
DPRINT("FileFlush failed\n");
}
if (!Success)
{
return FALSE;
}
return TRUE;
/* 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, HBLOCK_SIZE);
if (!Success)
{
return FALSE;
}
BlockIndex++;
FileOffset += HBLOCK_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 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)
PHHIVE RegistryHive,
BOOLEAN OnlyDirty)
{
ULONG FileOffset;
ULONG BlockIndex;
ULONG LastIndex;
PVOID BlockPtr;
BOOLEAN Success;
ULONG FileOffset;
ULONG BlockIndex;
ULONG LastIndex;
PVOID BlockPtr;
BOOLEAN Success;
ASSERT(RegistryHive->ReadOnly == FALSE);
ASSERT(RegistryHive->BaseBlock->Length ==
RegistryHive->Storage[Stable].Length * HBLOCK_SIZE);
ASSERT(RegistryHive->ReadOnly == FALSE);
ASSERT(RegistryHive->BaseBlock->Length ==
RegistryHive->Storage[Stable].Length * HBLOCK_SIZE);
DPRINT("HvpWriteHive called\n");
DPRINT("HvpWriteHive called\n");
if (RegistryHive->BaseBlock->Sequence1 !=
RegistryHive->BaseBlock->Sequence2)
{
return FALSE;
}
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);
/* 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;
}
/* 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;
}
}
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) * HBLOCK_SIZE;
BlockPtr = (PVOID)RegistryHive->Storage[Stable].BlockList[BlockIndex].BlockAddress;
FileOffset = (BlockIndex + 1) * HBLOCK_SIZE;
/* Write hive block */
Success = RegistryHive->FileWrite(RegistryHive, HFILE_TYPE_PRIMARY,
&FileOffset, BlockPtr,
HBLOCK_SIZE);
if (!Success)
{
return FALSE;
}
/* Write hive block */
Success = RegistryHive->FileWrite(RegistryHive, HFILE_TYPE_PRIMARY,
&FileOffset, BlockPtr, HBLOCK_SIZE);
if (!Success)
{
return FALSE;
}
BlockIndex++;
}
BlockIndex++;
}
Success = RegistryHive->FileFlush(RegistryHive, HFILE_TYPE_PRIMARY, NULL, 0);
if (!Success)
{
DPRINT("FileFlush failed\n");
}
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);
/* 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;
}
/* 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");
}
Success = RegistryHive->FileFlush(RegistryHive, HFILE_TYPE_PRIMARY, NULL, 0);
if (!Success)
{
DPRINT("FileFlush failed\n");
}
return TRUE;
return TRUE;
}
BOOLEAN CMAPI
HvSyncHive(
PHHIVE RegistryHive)
PHHIVE RegistryHive)
{
ASSERT(RegistryHive->ReadOnly == FALSE);
ASSERT(RegistryHive->ReadOnly == FALSE);
if (RtlFindSetBits(&RegistryHive->DirtyVector, 1, 0) == ~0U)
{
return TRUE;
}
if (RtlFindSetBits(&RegistryHive->DirtyVector, 1, 0) == ~0U)
{
return TRUE;
}
/* Update hive header modification time */
KeQuerySystemTime(&RegistryHive->BaseBlock->TimeStamp);
/* Update hive header modification time */
KeQuerySystemTime(&RegistryHive->BaseBlock->TimeStamp);
/* Update log file */
if (!HvpWriteLog(RegistryHive))
{
return FALSE;
}
/* Update log file */
if (!HvpWriteLog(RegistryHive))
{
return FALSE;
}
/* Update hive file */
if (!HvpWriteHive(RegistryHive, TRUE))
{
return FALSE;
}
/* Update hive file */
if (!HvpWriteHive(RegistryHive, TRUE))
{
return FALSE;
}
/* Clear dirty bitmap. */
RtlClearAllBits(&RegistryHive->DirtyVector);
RegistryHive->DirtyCount = 0;
/* Clear dirty bitmap. */
RtlClearAllBits(&RegistryHive->DirtyVector);
RegistryHive->DirtyCount = 0;
return TRUE;
return TRUE;
}
BOOLEAN
@ -279,23 +277,24 @@ CMAPI
HvHiveWillShrink(IN PHHIVE RegistryHive)
{
/* No shrinking yet */
UNIMPLEMENTED;
return FALSE;
}
BOOLEAN CMAPI
HvWriteHive(
PHHIVE RegistryHive)
PHHIVE RegistryHive)
{
ASSERT(RegistryHive->ReadOnly == FALSE);
ASSERT(RegistryHive->ReadOnly == FALSE);
/* Update hive header modification time */
KeQuerySystemTime(&RegistryHive->BaseBlock->TimeStamp);
/* Update hive header modification time */
KeQuerySystemTime(&RegistryHive->BaseBlock->TimeStamp);
/* Update hive file */
if (!HvpWriteHive(RegistryHive, FALSE))
{
return FALSE;
}
/* Update hive file */
if (!HvpWriteHive(RegistryHive, FALSE))
{
return FALSE;
}
return TRUE;
return TRUE;
}