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
29 ASSERT(RegistryHive
->ReadOnly
== FALSE
);
30 ASSERT(RegistryHive
->BaseBlock
->Length
==
31 RegistryHive
->Storage
[Stable
].Length
* HV_BLOCK_SIZE
);
33 DPRINT("HvpWriteLog called\n");
35 if (RegistryHive
->BaseBlock
->Sequence1
!=
36 RegistryHive
->BaseBlock
->Sequence2
)
41 BitmapSize
= RegistryHive
->DirtyVector
.SizeOfBitMap
;
42 BufferSize
= HV_LOG_HEADER_SIZE
+ sizeof(ULONG
) + BitmapSize
;
43 BufferSize
= ROUND_UP(BufferSize
, HV_BLOCK_SIZE
);
45 DPRINT("Bitmap size %lu buffer size: %lu\n", BitmapSize
, BufferSize
);
47 Buffer
= RegistryHive
->Allocate(BufferSize
, TRUE
, TAG_CM
);
53 /* Update first update counter and CheckSum */
54 RegistryHive
->BaseBlock
->Type
= HFILE_TYPE_LOG
;
55 RegistryHive
->BaseBlock
->Sequence1
++;
56 RegistryHive
->BaseBlock
->CheckSum
=
57 HvpHiveHeaderChecksum(RegistryHive
->BaseBlock
);
59 /* Copy hive header */
60 RtlCopyMemory(Buffer
, RegistryHive
->BaseBlock
, HV_LOG_HEADER_SIZE
);
61 Ptr
= Buffer
+ HV_LOG_HEADER_SIZE
;
62 RtlCopyMemory(Ptr
, "DIRT", 4);
64 RtlCopyMemory(Ptr
, RegistryHive
->DirtyVector
.Buffer
, BitmapSize
);
66 /* Write hive block and block bitmap */
68 Success
= RegistryHive
->FileWrite(RegistryHive
, HFILE_TYPE_LOG
,
69 &FileOffset
, Buffer
, BufferSize
);
70 RegistryHive
->Free(Buffer
, 0);
77 /* Write dirty blocks */
78 FileOffset
= BufferSize
;
80 while (BlockIndex
< RegistryHive
->Storage
[Stable
].Length
)
82 LastIndex
= BlockIndex
;
83 BlockIndex
= RtlFindSetBits(&RegistryHive
->DirtyVector
, 1, BlockIndex
);
84 if (BlockIndex
== ~0U || BlockIndex
< LastIndex
)
89 BlockPtr
= (PVOID
)RegistryHive
->Storage
[Stable
].BlockList
[BlockIndex
].BlockAddress
;
91 /* Write hive block */
92 Success
= RegistryHive
->FileWrite(RegistryHive
, HFILE_TYPE_LOG
,
93 &FileOffset
, BlockPtr
,
101 FileOffset
+= HV_BLOCK_SIZE
;
104 Success
= RegistryHive
->FileSetSize(RegistryHive
, HFILE_TYPE_LOG
, FileOffset
, FileOffset
);
107 DPRINT("FileSetSize failed\n");
111 /* Flush the log file */
112 Success
= RegistryHive
->FileFlush(RegistryHive
, HFILE_TYPE_LOG
, NULL
, 0);
115 DPRINT("FileFlush failed\n");
118 /* Update first and second update counter and CheckSum. */
119 RegistryHive
->BaseBlock
->Sequence2
++;
120 RegistryHive
->BaseBlock
->CheckSum
=
121 HvpHiveHeaderChecksum(RegistryHive
->BaseBlock
);
123 /* Write hive header again with updated sequence counter. */
125 Success
= RegistryHive
->FileWrite(RegistryHive
, HFILE_TYPE_LOG
,
126 &FileOffset
, RegistryHive
->BaseBlock
,
133 /* Flush the log file */
134 Success
= RegistryHive
->FileFlush(RegistryHive
, HFILE_TYPE_LOG
, NULL
, 0);
137 DPRINT("FileFlush failed\n");
154 ASSERT(RegistryHive
->ReadOnly
== FALSE
);
155 ASSERT(RegistryHive
->BaseBlock
->Length
==
156 RegistryHive
->Storage
[Stable
].Length
* HV_BLOCK_SIZE
);
158 DPRINT("HvpWriteHive called\n");
160 if (RegistryHive
->BaseBlock
->Sequence1
!=
161 RegistryHive
->BaseBlock
->Sequence2
)
166 /* Update first update counter and CheckSum */
167 RegistryHive
->BaseBlock
->Type
= HFILE_TYPE_PRIMARY
;
168 RegistryHive
->BaseBlock
->Sequence1
++;
169 RegistryHive
->BaseBlock
->CheckSum
=
170 HvpHiveHeaderChecksum(RegistryHive
->BaseBlock
);
172 /* Write hive block */
174 Success
= RegistryHive
->FileWrite(RegistryHive
, HFILE_TYPE_PRIMARY
,
175 &FileOffset
, RegistryHive
->BaseBlock
,
176 sizeof(HBASE_BLOCK
));
183 while (BlockIndex
< RegistryHive
->Storage
[Stable
].Length
)
187 LastIndex
= BlockIndex
;
188 BlockIndex
= RtlFindSetBits(&RegistryHive
->DirtyVector
, 1, BlockIndex
);
189 if (BlockIndex
== ~0U || BlockIndex
< LastIndex
)
195 BlockPtr
= (PVOID
)RegistryHive
->Storage
[Stable
].BlockList
[BlockIndex
].BlockAddress
;
196 FileOffset
= (BlockIndex
+ 1) * HV_BLOCK_SIZE
;
198 /* Write hive block */
199 Success
= RegistryHive
->FileWrite(RegistryHive
, HFILE_TYPE_PRIMARY
,
200 &FileOffset
, BlockPtr
,
210 Success
= RegistryHive
->FileFlush(RegistryHive
, HFILE_TYPE_PRIMARY
, NULL
, 0);
213 DPRINT("FileFlush failed\n");
216 /* Update second update counter and CheckSum */
217 RegistryHive
->BaseBlock
->Sequence2
++;
218 RegistryHive
->BaseBlock
->CheckSum
=
219 HvpHiveHeaderChecksum(RegistryHive
->BaseBlock
);
221 /* Write hive block */
223 Success
= RegistryHive
->FileWrite(RegistryHive
, HFILE_TYPE_PRIMARY
,
224 &FileOffset
, RegistryHive
->BaseBlock
,
225 sizeof(HBASE_BLOCK
));
231 Success
= RegistryHive
->FileFlush(RegistryHive
, HFILE_TYPE_PRIMARY
, NULL
, 0);
234 DPRINT("FileFlush failed\n");
244 ASSERT(RegistryHive
->ReadOnly
== FALSE
);
246 if (RtlFindSetBits(&RegistryHive
->DirtyVector
, 1, 0) == ~0U)
251 /* Update hive header modification time */
252 KeQuerySystemTime(&RegistryHive
->BaseBlock
->TimeStamp
);
254 /* Update log file */
255 if (!HvpWriteLog(RegistryHive
))
260 /* Update hive file */
261 if (!HvpWriteHive(RegistryHive
, TRUE
))
266 /* Clear dirty bitmap. */
267 RtlClearAllBits(&RegistryHive
->DirtyVector
);
268 RegistryHive
->DirtyCount
= 0;
275 HvHiveWillShrink(IN PHHIVE RegistryHive
)
277 /* No shrinking yet */
285 ASSERT(RegistryHive
->ReadOnly
== FALSE
);
287 /* Update hive header modification time */
288 KeQuerySystemTime(&RegistryHive
->BaseBlock
->TimeStamp
);
290 /* Update hive file */
291 if (!HvpWriteHive(RegistryHive
, FALSE
))