reactos/sdk/lib/cmlib/hivebin.c

108 lines
3.4 KiB
C

/*
* 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;
ULONG BinSize;
ULONG i;
ULONG BitmapSize;
ULONG BlockCount;
ULONG OldBlockListSize;
PHCELL Block;
BinSize = ROUND_UP(Size + sizeof(HBIN), HBLOCK_SIZE);
BlockCount = BinSize / HBLOCK_SIZE;
Bin = RegistryHive->Allocate(BinSize, TRUE, TAG_CM);
if (Bin == NULL)
return NULL;
RtlZeroMemory(Bin, BinSize);
Bin->Signature = HV_HBIN_SIGNATURE;
Bin->FileOffset = RegistryHive->Storage[Storage].Length *
HBLOCK_SIZE;
Bin->Size = 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 * 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));
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 / HBLOCK_SIZE,
BlockCount);
/* Update size in the base block */
RegistryHive->BaseBlock->Length += BinSize;
}
return Bin;
}