1 /* 2 * PROJECT: Registry manipulation library 3 * LICENSE: GPL - See COPYING in the top level directory 4 * COPYRIGHT: Copyright 2005 Filip Navara <navaraf@reactos.org> 5 * Copyright 2005 Hartmut Birr 6 * Copyright 2001 - 2005 Eric Kohl 7 */ 8 9 #include "cmlib.h" 10 11 PHBIN CMAPI 12 HvpAddBin( 13 PHHIVE RegistryHive, 14 ULONG Size, 15 HSTORAGE_TYPE Storage) 16 { 17 PHMAP_ENTRY BlockList; 18 PHBIN Bin; 19 ULONG BinSize; 20 ULONG i; 21 ULONG BitmapSize; 22 ULONG BlockCount; 23 ULONG OldBlockListSize; 24 PHCELL Block; 25 26 BinSize = ROUND_UP(Size + sizeof(HBIN), HBLOCK_SIZE); 27 BlockCount = BinSize / HBLOCK_SIZE; 28 29 Bin = RegistryHive->Allocate(BinSize, TRUE, TAG_CM); 30 if (Bin == NULL) 31 return NULL; 32 RtlZeroMemory(Bin, BinSize); 33 34 Bin->Signature = HV_HBIN_SIGNATURE; 35 Bin->FileOffset = RegistryHive->Storage[Storage].Length * 36 HBLOCK_SIZE; 37 Bin->Size = BinSize; 38 39 /* Allocate new block list */ 40 OldBlockListSize = RegistryHive->Storage[Storage].Length; 41 BlockList = RegistryHive->Allocate(sizeof(HMAP_ENTRY) * 42 (OldBlockListSize + BlockCount), 43 TRUE, 44 TAG_CM); 45 if (BlockList == NULL) 46 { 47 RegistryHive->Free(Bin, 0); 48 return NULL; 49 } 50 51 if (OldBlockListSize > 0) 52 { 53 RtlCopyMemory(BlockList, RegistryHive->Storage[Storage].BlockList, 54 OldBlockListSize * sizeof(HMAP_ENTRY)); 55 RegistryHive->Free(RegistryHive->Storage[Storage].BlockList, 0); 56 } 57 58 RegistryHive->Storage[Storage].BlockList = BlockList; 59 RegistryHive->Storage[Storage].Length += BlockCount; 60 61 for (i = 0; i < BlockCount; i++) 62 { 63 RegistryHive->Storage[Storage].BlockList[OldBlockListSize + i].BlockAddress = 64 ((ULONG_PTR)Bin + (i * HBLOCK_SIZE)); 65 RegistryHive->Storage[Storage].BlockList[OldBlockListSize + i].BinAddress = (ULONG_PTR)Bin; 66 } 67 68 /* Initialize a free block in this heap. */ 69 Block = (PHCELL)(Bin + 1); 70 Block->Size = (LONG)(BinSize - sizeof(HBIN)); 71 72 if (Storage == Stable) 73 { 74 /* Calculate bitmap size in bytes (always a multiple of 32 bits). */ 75 BitmapSize = ROUND_UP(RegistryHive->Storage[Stable].Length, 76 sizeof(ULONG) * 8) / 8; 77 78 /* Grow bitmap if necessary. */ 79 if (BitmapSize > RegistryHive->DirtyVector.SizeOfBitMap / 8) 80 { 81 PULONG BitmapBuffer; 82 83 BitmapBuffer = RegistryHive->Allocate(BitmapSize, TRUE, TAG_CM); 84 RtlZeroMemory(BitmapBuffer, BitmapSize); 85 if (RegistryHive->DirtyVector.SizeOfBitMap > 0) 86 { 87 ASSERT(RegistryHive->DirtyVector.Buffer); 88 RtlCopyMemory(BitmapBuffer, 89 RegistryHive->DirtyVector.Buffer, 90 RegistryHive->DirtyVector.SizeOfBitMap / 8); 91 RegistryHive->Free(RegistryHive->DirtyVector.Buffer, 0); 92 } 93 RtlInitializeBitMap(&RegistryHive->DirtyVector, BitmapBuffer, 94 BitmapSize * 8); 95 } 96 97 /* Mark new bin dirty. */ 98 RtlSetBits(&RegistryHive->DirtyVector, 99 Bin->FileOffset / HBLOCK_SIZE, 100 BlockCount); 101 102 /* Update size in the base block */ 103 RegistryHive->BaseBlock->Length += BinSize; 104 } 105 106 return Bin; 107 } 108