Revert 45697:
[reactos.git] / lib / cmlib / hivebin.c
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 SIZE_T BinSize;
20 ULONG i;
21 ULONG BitmapSize;
22 ULONG BlockCount;
23 ULONG OldBlockListSize;
24 PHCELL Block;
25
26 BinSize = ROUND_UP(Size + sizeof(HBIN), HV_BLOCK_SIZE);
27 BlockCount = (ULONG)(BinSize / HV_BLOCK_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_BIN_SIGNATURE;
35 Bin->FileOffset = RegistryHive->Storage[Storage].Length *
36 HV_BLOCK_SIZE;
37 Bin->Size = (ULONG)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 * HV_BLOCK_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 / HV_BLOCK_SIZE,
100 BlockCount);
101 }
102
103 return Bin;
104 }