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
25 static ULONG PrintCount
= 0;
27 if (PrintCount
++ == 0)
33 ASSERT(RegistryHive
->ReadOnly
== FALSE
);
34 ASSERT(RegistryHive
->BaseBlock
->Length
==
35 RegistryHive
->Storage
[Stable
].Length
* HV_BLOCK_SIZE
);
37 DPRINT("HvpWriteLog called\n");
39 if (RegistryHive
->BaseBlock
->Sequence1
!=
40 RegistryHive
->BaseBlock
->Sequence2
)
45 BitmapSize
= RegistryHive
->DirtyVector
.SizeOfBitMap
;
46 BufferSize
= HV_LOG_HEADER_SIZE
+ sizeof(ULONG
) + BitmapSize
;
47 BufferSize
= ROUND_UP(BufferSize
, HV_BLOCK_SIZE
);
49 DPRINT("Bitmap size %u buffer size: %u\n", BitmapSize
, BufferSize
);
51 Buffer
= RegistryHive
->Allocate(BufferSize
, TRUE
, TAG_CM
);
57 /* Update first update counter and CheckSum */
58 RegistryHive
->BaseBlock
->Type
= HFILE_TYPE_LOG
;
59 RegistryHive
->BaseBlock
->Sequence1
++;
60 RegistryHive
->BaseBlock
->CheckSum
=
61 HvpHiveHeaderChecksum(RegistryHive
->BaseBlock
);
63 /* Copy hive header */
64 RtlCopyMemory(Buffer
, RegistryHive
->BaseBlock
, HV_LOG_HEADER_SIZE
);
65 Ptr
= Buffer
+ HV_LOG_HEADER_SIZE
;
66 RtlCopyMemory(Ptr
, "DIRT", 4);
68 RtlCopyMemory(Ptr
, RegistryHive
->DirtyVector
.Buffer
, BitmapSize
);
70 /* Write hive block and block bitmap */
72 Success
= RegistryHive
->FileWrite(RegistryHive
, HFILE_TYPE_LOG
,
73 &FileOffset
, Buffer
, BufferSize
);
74 RegistryHive
->Free(Buffer
, 0);
81 /* Write dirty blocks */
82 FileOffset
= BufferSize
;
84 while (BlockIndex
< RegistryHive
->Storage
[Stable
].Length
)
86 LastIndex
= BlockIndex
;
87 BlockIndex
= RtlFindSetBits(&RegistryHive
->DirtyVector
, 1, BlockIndex
);
88 if (BlockIndex
== ~0U || BlockIndex
< LastIndex
)
93 BlockPtr
= (PVOID
)RegistryHive
->Storage
[Stable
].BlockList
[BlockIndex
].BlockAddress
;
95 /* Write hive block */
96 Success
= RegistryHive
->FileWrite(RegistryHive
, HFILE_TYPE_LOG
,
97 &FileOffset
, BlockPtr
,
105 FileOffset
+= HV_BLOCK_SIZE
;
108 Success
= RegistryHive
->FileSetSize(RegistryHive
, HFILE_TYPE_LOG
, FileOffset
, FileOffset
);
111 DPRINT("FileSetSize failed\n");
115 /* Flush the log file */
116 Success
= RegistryHive
->FileFlush(RegistryHive
, HFILE_TYPE_LOG
, NULL
, 0);
119 DPRINT("FileFlush failed\n");
122 /* Update second update counter and CheckSum. */
123 RegistryHive
->BaseBlock
->Sequence2
++;
124 RegistryHive
->BaseBlock
->CheckSum
=
125 HvpHiveHeaderChecksum(RegistryHive
->BaseBlock
);
127 /* Write hive header again with updated sequence counter. */
129 Success
= RegistryHive
->FileWrite(RegistryHive
, HFILE_TYPE_LOG
,
130 &FileOffset
, RegistryHive
->BaseBlock
,
137 /* Flush the log file */
138 Success
= RegistryHive
->FileFlush(RegistryHive
, HFILE_TYPE_LOG
, NULL
, 0);
141 DPRINT("FileFlush failed\n");
158 ASSERT(RegistryHive
->ReadOnly
== FALSE
);
159 ASSERT(RegistryHive
->BaseBlock
->Length
==
160 RegistryHive
->Storage
[Stable
].Length
* HV_BLOCK_SIZE
);
162 DPRINT("HvpWriteHive called\n");
164 if (RegistryHive
->BaseBlock
->Sequence1
!=
165 RegistryHive
->BaseBlock
->Sequence2
)
170 /* Update first update counter and CheckSum */
171 RegistryHive
->BaseBlock
->Type
= HFILE_TYPE_PRIMARY
;
172 RegistryHive
->BaseBlock
->Sequence1
++;
173 RegistryHive
->BaseBlock
->CheckSum
=
174 HvpHiveHeaderChecksum(RegistryHive
->BaseBlock
);
176 /* Write hive block */
178 Success
= RegistryHive
->FileWrite(RegistryHive
, HFILE_TYPE_PRIMARY
,
179 &FileOffset
, RegistryHive
->BaseBlock
,
180 sizeof(HBASE_BLOCK
));
187 while (BlockIndex
< RegistryHive
->Storage
[Stable
].Length
)
191 LastIndex
= BlockIndex
;
192 BlockIndex
= RtlFindSetBits(&RegistryHive
->DirtyVector
, 1, BlockIndex
);
193 if (BlockIndex
== ~0U || BlockIndex
< LastIndex
)
199 BlockPtr
= (PVOID
)RegistryHive
->Storage
[Stable
].BlockList
[BlockIndex
].BlockAddress
;
200 FileOffset
= (BlockIndex
+ 1) * HV_BLOCK_SIZE
;
202 /* Write hive block */
203 Success
= RegistryHive
->FileWrite(RegistryHive
, HFILE_TYPE_PRIMARY
,
204 &FileOffset
, BlockPtr
,
214 Success
= RegistryHive
->FileFlush(RegistryHive
, HFILE_TYPE_PRIMARY
, NULL
, 0);
217 DPRINT("FileFlush failed\n");
220 /* Update second update counter and CheckSum */
221 RegistryHive
->BaseBlock
->Sequence2
++;
222 RegistryHive
->BaseBlock
->CheckSum
=
223 HvpHiveHeaderChecksum(RegistryHive
->BaseBlock
);
225 /* Write hive block */
227 Success
= RegistryHive
->FileWrite(RegistryHive
, HFILE_TYPE_PRIMARY
,
228 &FileOffset
, RegistryHive
->BaseBlock
,
229 sizeof(HBASE_BLOCK
));
235 Success
= RegistryHive
->FileFlush(RegistryHive
, HFILE_TYPE_PRIMARY
, NULL
, 0);
238 DPRINT("FileFlush failed\n");
248 ASSERT(RegistryHive
->ReadOnly
== FALSE
);
250 if (RtlFindSetBits(&RegistryHive
->DirtyVector
, 1, 0) == ~0U)
255 /* Update hive header modification time */
256 KeQuerySystemTime(&RegistryHive
->BaseBlock
->TimeStamp
);
258 /* Update log file */
259 if (!HvpWriteLog(RegistryHive
))
264 /* Update hive file */
265 if (!HvpWriteHive(RegistryHive
, TRUE
))
270 /* Clear dirty bitmap. */
271 RtlClearAllBits(&RegistryHive
->DirtyVector
);
272 RegistryHive
->DirtyCount
= 0;
279 HvHiveWillShrink(IN PHHIVE RegistryHive
)
281 /* No shrinking yet */
289 ASSERT(RegistryHive
->ReadOnly
== FALSE
);
291 /* Update hive header modification time */
292 KeQuerySystemTime(&RegistryHive
->BaseBlock
->TimeStamp
);
294 /* Update hive file */
295 if (!HvpWriteHive(RegistryHive
, FALSE
))