{
Status = CmiAddFree(RegistryHive,
FreeBlock,
- RegistryHive->BlockList[i]->BlockOffset + FreeOffset);
+ RegistryHive->BlockList[i]->BlockOffset + FreeOffset,
+ FALSE);
if (!NT_SUCCESS(Status))
{
{
DPRINT1("ParentKey %p\n", ParentKey)
ParentKey->KeyCell->NumberOfSubKeys--;
- NtQuerySystemTime((PTIME)&ParentKey->KeyCell->LastWriteTime);
- CmiMarkBlockDirty(RegistryHive,
- ParentKey->BlockOffset);
/* Remove the parent key's hash table */
if (ParentKey->KeyCell->NumberOfSubKeys == 0)
{
- DPRINT1("FIXME: Remove parent key hash table\n")
-
+ DPRINT1("ParentKey HashTableOffset %lx\n", ParentKey->KeyCell->HashTableOffset)
+ HashBlock = CmiGetBlock(RegistryHive,
+ ParentKey->KeyCell->HashTableOffset,
+ NULL);
+ DPRINT1("ParentKey HashBlock %p\n", HashBlock)
+ if (HashBlock != NULL)
+ {
+ CmiDestroyBlock(RegistryHive,
+ HashBlock,
+ ParentKey->KeyCell->HashTableOffset);
+ ParentKey->KeyCell->HashTableOffset = -1;
+ }
}
+
+ NtQuerySystemTime((PTIME)&ParentKey->KeyCell->LastWriteTime);
+ CmiMarkBlockDirty(RegistryHive,
+ ParentKey->BlockOffset);
}
/* Destroy key cell */
SubKey->BlockOffset = -1;
SubKey->KeyCell = NULL;
- /* FIXME: Merge free blocks within the Bin */
-
return(STATUS_SUCCESS);
}
CurValueCell->Name,
CurValueCell->NameSize,
CurValueCell->Flags & REG_VALUE_NAME_PACKED))
- {
- *ValueCell = CurValueCell;
- if (VBOffset)
- *VBOffset = ValueListCell->Values[i];
- //DPRINT("Found value %s\n", ValueName);
- break;
- }
+ {
+ *ValueCell = CurValueCell;
+ if (VBOffset)
+ *VBOffset = ValueListCell->Values[i];
+ //DPRINT("Found value %s\n", ValueName);
+ break;
+ }
CmiReleaseBlock(RegistryHive, CurValueCell);
}
CurValueCell->Name,
CurValueCell->NameSize,
CurValueCell->Flags & REG_VALUE_NAME_PACKED))
- {
+ {
+ CmiDestroyValueCell(RegistryHive, CurValueCell, ValueListCell->Values[i]);
+
if ((KeyCell->NumberOfValues - 1) < i)
{
RtlCopyMemory(&ValueListCell->Values[i],
}
KeyCell->NumberOfValues -= 1;
- CmiDestroyValueCell(RegistryHive, CurValueCell, ValueListCell->Values[i]);
break;
- }
+ }
CmiReleaseBlock(RegistryHive, CurValueCell);
}
NTSTATUS
CmiDestroyValueCell(PREGISTRY_HIVE RegistryHive,
- PVALUE_CELL ValueCell,
- BLOCK_OFFSET VBOffset)
+ PVALUE_CELL ValueCell,
+ BLOCK_OFFSET VBOffset)
{
NTSTATUS Status;
PVOID pBlock;
PHBIN pBin;
+ DPRINT("CmiDestroyValueCell(Cell %p Offset %lx)\n", ValueCell, VBOffset);
+
VERIFY_VALUE_CELL(ValueCell);
- /* First, release data: */
+ /* Destroy the data cell */
if (ValueCell->DataSize > 4)
{
pBlock = CmiGetBlock(RegistryHive, ValueCell->DataOffset, &pBin);
ZwQuerySystemTime((PTIME) &pBin->DateModified);
}
+ /* Destroy the value cell */
Status = CmiDestroyBlock(RegistryHive, ValueCell, VBOffset);
/* Update time of heap */
{
NewBlock = (PCELL_HEADER) ((ULONG_PTR) NewBlock+BlockSize);
NewBlock->CellSize = ((PCELL_HEADER) (*Block))->CellSize - BlockSize;
- CmiAddFree(RegistryHive, NewBlock, *pBlockOffset + BlockSize);
- CmiMarkBlockDirty(RegistryHive, *pBlockOffset + BlockSize);
+ CmiAddFree(RegistryHive,
+ NewBlock,
+ *pBlockOffset + BlockSize,
+ TRUE);
+ CmiMarkBlockDirty(RegistryHive,
+ *pBlockOffset + BlockSize);
}
else if (NewBlock->CellSize < BlockSize)
{
RtlZeroMemory(((PVOID)pFree) + sizeof(ULONG),
pFree->CellSize - sizeof(ULONG));
- CmiAddFree(RegistryHive, Block, Offset);
+ /* add block to the list of free blocks */
+ CmiAddFree(RegistryHive, Block, Offset, TRUE);
CmiReleaseBlock(RegistryHive, Block);
/* Update time of heap */
}
+static BOOLEAN
+CmiMergeFree(PREGISTRY_HIVE RegistryHive,
+ PCELL_HEADER FreeBlock,
+ BLOCK_OFFSET FreeOffset)
+{
+ BLOCK_OFFSET BlockOffset;
+ BLOCK_OFFSET BinOffset;
+ ULONG BlockSize;
+ ULONG BinSize;
+ PHBIN Bin;
+ LONG i;
+
+ DPRINT("CmiMergeFree(Block %lx Offset %lx Size %lx) called\n",
+ FreeBlock, FreeOffset, FreeBlock->CellSize);
+
+ CmiGetBlock(RegistryHive,
+ FreeOffset,
+ &Bin);
+ DPRINT("Bin %p\n", Bin);
+ if (Bin == NULL)
+ return(FALSE);
+
+ BinOffset = Bin->BlockOffset;
+ BinSize = Bin->BlockSize;
+ DPRINT("Bin %p Offset %lx Size %lx\n", Bin, BinOffset, BinSize);
+
+ for (i = 0; i < RegistryHive->FreeListSize; i++)
+ {
+ BlockOffset = RegistryHive->FreeListOffset[i];
+ BlockSize = RegistryHive->FreeList[i]->CellSize;
+ if (BlockOffset > BinOffset &&
+ BlockOffset < BinOffset + BinSize)
+ {
+ DPRINT("Free block: Offset %lx Size %lx\n",
+ BlockOffset, BlockSize);
+
+ if ((i < (RegistryHive->FreeListSize - 1)) &&
+ (BlockOffset + BlockSize == FreeOffset) &&
+ (FreeOffset + FreeBlock->CellSize == RegistryHive->FreeListOffset[i + 1]))
+ {
+ DPRINT("Merge current block with previous and next block\n");
+
+ RegistryHive->FreeList[i]->CellSize +=
+ (FreeBlock->CellSize + RegistryHive->FreeList[i + 1]->CellSize);
+
+ FreeBlock->CellSize = 0;
+ RegistryHive->FreeList[i + 1]->CellSize = 0;
+
+
+ if ((i + 2) < RegistryHive->FreeListSize)
+ {
+ RtlMoveMemory(&RegistryHive->FreeListOffset[i + 1],
+ &RegistryHive->FreeListOffset[i + 2],
+ sizeof(RegistryHive->FreeListOffset[0])
+ * (RegistryHive->FreeListSize - i - 2));
+ }
+ RegistryHive->FreeListSize--;
+
+ CmiMarkBlockDirty(RegistryHive, BlockOffset);
+
+ return(TRUE);
+ }
+ else if (BlockOffset + BlockSize == FreeOffset)
+ {
+ DPRINT("Merge current block with previous block\n");
+
+ RegistryHive->FreeList[i]->CellSize += FreeBlock->CellSize;
+ FreeBlock->CellSize = 0;
+
+ CmiMarkBlockDirty(RegistryHive, BlockOffset);
+
+ return(TRUE);
+ }
+ else if (FreeOffset + FreeBlock->CellSize == BlockOffset)
+ {
+ DPRINT("Merge current block with next block\n");
+
+ FreeBlock->CellSize += RegistryHive->FreeList[i]->CellSize;
+ RegistryHive->FreeList[i]->CellSize = 0;
+ RegistryHive->FreeList[i] = FreeBlock;
+ RegistryHive->FreeListOffset[i] = FreeOffset;
+
+ CmiMarkBlockDirty(RegistryHive, FreeOffset);
+
+ return(TRUE);
+ }
+ }
+ }
+
+ return(FALSE);
+}
+
+
NTSTATUS
CmiAddFree(PREGISTRY_HIVE RegistryHive,
- PCELL_HEADER FreeBlock,
- BLOCK_OFFSET FreeOffset)
+ PCELL_HEADER FreeBlock,
+ BLOCK_OFFSET FreeOffset,
+ BOOLEAN MergeFreeBlocks)
{
- PCELL_HEADER *tmpList;
- BLOCK_OFFSET *tmpListOffset;
- LONG minInd;
+ PCELL_HEADER *tmpList;
+ BLOCK_OFFSET *tmpListOffset;
+ LONG minInd;
LONG maxInd;
LONG medInd;
assert(RegistryHive);
assert(FreeBlock);
- DPRINT("FreeBlock %.08x FreeOffset %.08x\n",
- FreeBlock, FreeOffset);
-DPRINT("\n");
+ DPRINT("FreeBlock %.08lx FreeOffset %.08lx\n",
+ FreeBlock, FreeOffset);
+
+ /* Merge free blocks */
+ if (MergeFreeBlocks == TRUE)
+ {
+ if (CmiMergeFree(RegistryHive, FreeBlock, FreeOffset))
+ return(STATUS_SUCCESS);
+ }
+
if ((RegistryHive->FreeListSize + 1) > RegistryHive->FreeListMax)
{
-DPRINT("\n");
tmpList = ExAllocatePool(PagedPool,
sizeof(PCELL_HEADER) * (RegistryHive->FreeListMax + 32));
-DPRINT("\n");
-
if (tmpList == NULL)
return STATUS_INSUFFICIENT_RESOURCES;
-DPRINT("\n");
tmpListOffset = ExAllocatePool(PagedPool,
sizeof(BLOCK_OFFSET *) * (RegistryHive->FreeListMax + 32));
-DPRINT("\n");
if (tmpListOffset == NULL)
{
ExFreePool(tmpList);
return STATUS_INSUFFICIENT_RESOURCES;
}
-DPRINT("\n");
if (RegistryHive->FreeListMax)
{
-DPRINT("\n");
RtlMoveMemory(tmpList,
RegistryHive->FreeList,
sizeof(PCELL_HEADER) * (RegistryHive->FreeListMax));
-DPRINT("\n");
RtlMoveMemory(tmpListOffset,
RegistryHive->FreeListOffset,
sizeof(BLOCK_OFFSET *) * (RegistryHive->FreeListMax));
-DPRINT("\n");
ExFreePool(RegistryHive->FreeList);
-DPRINT("\n");
ExFreePool(RegistryHive->FreeListOffset);
-DPRINT("\n");
}
-DPRINT("\n");
RegistryHive->FreeList = tmpList;
RegistryHive->FreeListOffset = tmpListOffset;
RegistryHive->FreeListMax += 32;
-DPRINT("\n");
}
-DPRINT("\n");
/* Add new offset to free list, maintaining list in ascending order */
if ((RegistryHive->FreeListSize == 0)
|| (RegistryHive->FreeListOffset[RegistryHive->FreeListSize-1] < FreeOffset))
{
-DPRINT("\n");
/* Add to end of list */
RegistryHive->FreeList[RegistryHive->FreeListSize] = FreeBlock;
RegistryHive->FreeListOffset[RegistryHive->FreeListSize++] = FreeOffset;
}
else if (RegistryHive->FreeListOffset[0] > FreeOffset)
{
-DPRINT("\n");
/* Add to begin of list */
RtlMoveMemory(&RegistryHive->FreeList[1],
&RegistryHive->FreeList[0],
}
else
{
-DPRINT("\n");
/* Search where to insert */
minInd = 0;
maxInd = RegistryHive->FreeListSize - 1;
RegistryHive->FreeListOffset[maxInd] = FreeOffset;
RegistryHive->FreeListSize++;
}
-DPRINT("\n");
return STATUS_SUCCESS;
}
pBin = RegistryHive->BlockList[BlockOffset / 4096];
if (ppBin)
*ppBin = pBin;
- return ((PVOID) ((ULONG_PTR) pBin + (BlockOffset - pBin->BlockOffset)));
+ return((PVOID)((ULONG_PTR)pBin + (BlockOffset - pBin->BlockOffset)));
}
}