Revert 45697:
[reactos.git] / lib / cmlib / hivewrt.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 2001 - 2005 Eric Kohl
6 */
7
8 #include "cmlib.h"
9 #define NDEBUG
10 #include <debug.h>
11
12 static BOOLEAN CMAPI
13 HvpWriteLog(
14 PHHIVE RegistryHive)
15 {
16 ULONG FileOffset;
17 SIZE_T BufferSize;
18 SIZE_T BitmapSize;
19 PUCHAR Buffer;
20 PUCHAR Ptr;
21 ULONG BlockIndex;
22 ULONG LastIndex;
23 PVOID BlockPtr;
24 BOOLEAN Success;
25
26 UNIMPLEMENTED;
27 return TRUE;
28
29 ASSERT(RegistryHive->ReadOnly == FALSE);
30
31 DPRINT("HvpWriteLog called\n");
32
33 if (RegistryHive->BaseBlock->Sequence1 !=
34 RegistryHive->BaseBlock->Sequence2)
35 {
36 return FALSE;
37 }
38
39 BitmapSize = RegistryHive->DirtyVector.SizeOfBitMap;
40 BufferSize = HV_LOG_HEADER_SIZE + sizeof(ULONG) + BitmapSize;
41 BufferSize = ROUND_UP(BufferSize, HV_BLOCK_SIZE);
42
43 DPRINT("Bitmap size %lu buffer size: %lu\n", BitmapSize, BufferSize);
44
45 Buffer = RegistryHive->Allocate(BufferSize, TRUE, TAG_CM);
46 if (Buffer == NULL)
47 {
48 return FALSE;
49 }
50
51 /* Update first update counter and CheckSum */
52 RegistryHive->BaseBlock->Type = HFILE_TYPE_LOG;
53 RegistryHive->BaseBlock->Sequence1++;
54 RegistryHive->BaseBlock->CheckSum =
55 HvpHiveHeaderChecksum(RegistryHive->BaseBlock);
56
57 /* Copy hive header */
58 RtlCopyMemory(Buffer, RegistryHive->BaseBlock, HV_LOG_HEADER_SIZE);
59 Ptr = Buffer + HV_LOG_HEADER_SIZE;
60 RtlCopyMemory(Ptr, "DIRT", 4);
61 Ptr += 4;
62 RtlCopyMemory(Ptr, RegistryHive->DirtyVector.Buffer, BitmapSize);
63
64 /* Write hive block and block bitmap */
65 FileOffset = 0;
66 Success = RegistryHive->FileWrite(RegistryHive, HFILE_TYPE_LOG,
67 &FileOffset, Buffer, BufferSize);
68 RegistryHive->Free(Buffer, 0);
69
70 if (!Success)
71 {
72 return FALSE;
73 }
74
75 /* Write dirty blocks */
76 FileOffset = BufferSize;
77 BlockIndex = 0;
78 while (BlockIndex < RegistryHive->Storage[Stable].Length)
79 {
80 LastIndex = BlockIndex;
81 BlockIndex = RtlFindSetBits(&RegistryHive->DirtyVector, 1, BlockIndex);
82 if (BlockIndex == ~0U || BlockIndex < LastIndex)
83 {
84 break;
85 }
86
87 BlockPtr = (PVOID)RegistryHive->Storage[Stable].BlockList[BlockIndex].BlockAddress;
88
89 /* Write hive block */
90 Success = RegistryHive->FileWrite(RegistryHive, HFILE_TYPE_LOG,
91 &FileOffset, BlockPtr,
92 HV_BLOCK_SIZE);
93 if (!Success)
94 {
95 return FALSE;
96 }
97
98 BlockIndex++;
99 FileOffset += HV_BLOCK_SIZE;
100 }
101
102 Success = RegistryHive->FileSetSize(RegistryHive, HFILE_TYPE_LOG, FileOffset, FileOffset);
103 if (!Success)
104 {
105 DPRINT("FileSetSize failed\n");
106 return FALSE;
107 }
108
109 /* Flush the log file */
110 Success = RegistryHive->FileFlush(RegistryHive, HFILE_TYPE_LOG, NULL, 0);
111 if (!Success)
112 {
113 DPRINT("FileFlush failed\n");
114 }
115
116 /* Update first and second update counter and CheckSum. */
117 RegistryHive->BaseBlock->Sequence2++;
118 RegistryHive->BaseBlock->CheckSum =
119 HvpHiveHeaderChecksum(RegistryHive->BaseBlock);
120
121 /* Write hive header again with updated sequence counter. */
122 FileOffset = 0;
123 Success = RegistryHive->FileWrite(RegistryHive, HFILE_TYPE_LOG,
124 &FileOffset, RegistryHive->BaseBlock,
125 HV_LOG_HEADER_SIZE);
126 if (!Success)
127 {
128 return FALSE;
129 }
130
131 /* Flush the log file */
132 Success = RegistryHive->FileFlush(RegistryHive, HFILE_TYPE_LOG, NULL, 0);
133 if (!Success)
134 {
135 DPRINT("FileFlush failed\n");
136 }
137
138 return TRUE;
139 }
140
141 static BOOLEAN CMAPI
142 HvpWriteHive(
143 PHHIVE RegistryHive,
144 BOOLEAN OnlyDirty)
145 {
146 ULONG FileOffset;
147 ULONG BlockIndex;
148 ULONG LastIndex;
149 PVOID BlockPtr;
150 BOOLEAN Success;
151
152 ASSERT(RegistryHive->ReadOnly == FALSE);
153
154 DPRINT("HvpWriteHive called\n");
155
156 if (RegistryHive->BaseBlock->Sequence1 !=
157 RegistryHive->BaseBlock->Sequence2)
158 {
159 return FALSE;
160 }
161
162 /* Update first update counter and CheckSum */
163 RegistryHive->BaseBlock->Type = HFILE_TYPE_PRIMARY;
164 RegistryHive->BaseBlock->Sequence1++;
165 RegistryHive->BaseBlock->CheckSum =
166 HvpHiveHeaderChecksum(RegistryHive->BaseBlock);
167
168 /* Write hive block */
169 FileOffset = 0;
170 Success = RegistryHive->FileWrite(RegistryHive, HFILE_TYPE_PRIMARY,
171 &FileOffset, RegistryHive->BaseBlock,
172 sizeof(HBASE_BLOCK));
173 if (!Success)
174 {
175 return FALSE;
176 }
177
178 BlockIndex = 0;
179 while (BlockIndex < RegistryHive->Storage[Stable].Length)
180 {
181 if (OnlyDirty)
182 {
183 LastIndex = BlockIndex;
184 BlockIndex = RtlFindSetBits(&RegistryHive->DirtyVector, 1, BlockIndex);
185 if (BlockIndex == ~0U || BlockIndex < LastIndex)
186 {
187 break;
188 }
189 }
190
191 BlockPtr = (PVOID)RegistryHive->Storage[Stable].BlockList[BlockIndex].BlockAddress;
192 FileOffset = (BlockIndex + 1) * HV_BLOCK_SIZE;
193
194 /* Write hive block */
195 Success = RegistryHive->FileWrite(RegistryHive, HFILE_TYPE_PRIMARY,
196 &FileOffset, BlockPtr,
197 HV_BLOCK_SIZE);
198 if (!Success)
199 {
200 return FALSE;
201 }
202
203 BlockIndex++;
204 }
205
206 Success = RegistryHive->FileFlush(RegistryHive, HFILE_TYPE_PRIMARY, NULL, 0);
207 if (!Success)
208 {
209 DPRINT("FileFlush failed\n");
210 }
211
212 /* Update second update counter and CheckSum */
213 RegistryHive->BaseBlock->Sequence2++;
214 RegistryHive->BaseBlock->CheckSum =
215 HvpHiveHeaderChecksum(RegistryHive->BaseBlock);
216
217 /* Write hive block */
218 FileOffset = 0;
219 Success = RegistryHive->FileWrite(RegistryHive, HFILE_TYPE_PRIMARY,
220 &FileOffset, RegistryHive->BaseBlock,
221 sizeof(HBASE_BLOCK));
222 if (!Success)
223 {
224 return FALSE;
225 }
226
227 Success = RegistryHive->FileFlush(RegistryHive, HFILE_TYPE_PRIMARY, NULL, 0);
228 if (!Success)
229 {
230 DPRINT("FileFlush failed\n");
231 }
232
233 return TRUE;
234 }
235
236 BOOLEAN CMAPI
237 HvSyncHive(
238 PHHIVE RegistryHive)
239 {
240 ASSERT(RegistryHive->ReadOnly == FALSE);
241
242 if (RtlFindSetBits(&RegistryHive->DirtyVector, 1, 0) == ~0U)
243 {
244 return TRUE;
245 }
246
247 /* Update hive header modification time */
248 KeQuerySystemTime(&RegistryHive->BaseBlock->TimeStamp);
249
250 /* Update log file */
251 if (!HvpWriteLog(RegistryHive))
252 {
253 return FALSE;
254 }
255
256 /* Update hive file */
257 if (!HvpWriteHive(RegistryHive, TRUE))
258 {
259 return FALSE;
260 }
261
262 /* Clear dirty bitmap. */
263 RtlClearAllBits(&RegistryHive->DirtyVector);
264
265 return TRUE;
266 }
267
268 BOOLEAN CMAPI
269 HvWriteHive(
270 PHHIVE RegistryHive)
271 {
272 ASSERT(RegistryHive->ReadOnly == FALSE);
273
274 /* Update hive header modification time */
275 KeQuerySystemTime(&RegistryHive->BaseBlock->TimeStamp);
276
277 /* Update hive file */
278 if (!HvpWriteHive(RegistryHive, FALSE))
279 {
280 return FALSE;
281 }
282
283 return TRUE;
284 }