/* * PROJECT: Registry manipulation library * LICENSE: GPL - See COPYING in the top level directory * COPYRIGHT: Copyright 2005 Filip Navara * 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; }