xref: /reactos/sdk/lib/cmlib/hivebin.c (revision 682f85ad)
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