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
);
31 DPRINT("HvpWriteLog called\n");
33 if (RegistryHive
->BaseBlock
->Sequence1
!=
34 RegistryHive
->BaseBlock
->Sequence2
)
39 BitmapSize
= RegistryHive
->DirtyVector
.SizeOfBitMap
;
40 BufferSize
= HV_LOG_HEADER_SIZE
+ sizeof(ULONG
) + BitmapSize
;
41 BufferSize
= ROUND_UP(BufferSize
, HV_BLOCK_SIZE
);
43 DPRINT("Bitmap size %lu buffer size: %lu\n", BitmapSize
, BufferSize
);
45 Buffer
= RegistryHive
->Allocate(BufferSize
, TRUE
, TAG_CM
);
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
);
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);
62 RtlCopyMemory(Ptr
, RegistryHive
->DirtyVector
.Buffer
, BitmapSize
);
64 /* Write hive block and block bitmap */
66 Success
= RegistryHive
->FileWrite(RegistryHive
, HFILE_TYPE_LOG
,
67 &FileOffset
, Buffer
, BufferSize
);
68 RegistryHive
->Free(Buffer
, 0);
75 /* Write dirty blocks */
76 FileOffset
= BufferSize
;
78 while (BlockIndex
< RegistryHive
->Storage
[Stable
].Length
)
80 LastIndex
= BlockIndex
;
81 BlockIndex
= RtlFindSetBits(&RegistryHive
->DirtyVector
, 1, BlockIndex
);
82 if (BlockIndex
== ~0U || BlockIndex
< LastIndex
)
87 BlockPtr
= (PVOID
)RegistryHive
->Storage
[Stable
].BlockList
[BlockIndex
].BlockAddress
;
89 /* Write hive block */
90 Success
= RegistryHive
->FileWrite(RegistryHive
, HFILE_TYPE_LOG
,
91 &FileOffset
, BlockPtr
,
99 FileOffset
+= HV_BLOCK_SIZE
;
102 Success
= RegistryHive
->FileSetSize(RegistryHive
, HFILE_TYPE_LOG
, FileOffset
, FileOffset
);
105 DPRINT("FileSetSize failed\n");
109 /* Flush the log file */
110 Success
= RegistryHive
->FileFlush(RegistryHive
, HFILE_TYPE_LOG
, NULL
, 0);
113 DPRINT("FileFlush failed\n");
116 /* Update first and second update counter and CheckSum. */
117 RegistryHive
->BaseBlock
->Sequence2
++;
118 RegistryHive
->BaseBlock
->CheckSum
=
119 HvpHiveHeaderChecksum(RegistryHive
->BaseBlock
);
121 /* Write hive header again with updated sequence counter. */
123 Success
= RegistryHive
->FileWrite(RegistryHive
, HFILE_TYPE_LOG
,
124 &FileOffset
, RegistryHive
->BaseBlock
,
131 /* Flush the log file */
132 Success
= RegistryHive
->FileFlush(RegistryHive
, HFILE_TYPE_LOG
, NULL
, 0);
135 DPRINT("FileFlush failed\n");
152 ASSERT(RegistryHive
->ReadOnly
== FALSE
);
154 DPRINT("HvpWriteHive called\n");
156 if (RegistryHive
->BaseBlock
->Sequence1
!=
157 RegistryHive
->BaseBlock
->Sequence2
)
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
);
168 /* Write hive block */
170 Success
= RegistryHive
->FileWrite(RegistryHive
, HFILE_TYPE_PRIMARY
,
171 &FileOffset
, RegistryHive
->BaseBlock
,
172 sizeof(HBASE_BLOCK
));
179 while (BlockIndex
< RegistryHive
->Storage
[Stable
].Length
)
183 LastIndex
= BlockIndex
;
184 BlockIndex
= RtlFindSetBits(&RegistryHive
->DirtyVector
, 1, BlockIndex
);
185 if (BlockIndex
== ~0U || BlockIndex
< LastIndex
)
191 BlockPtr
= (PVOID
)RegistryHive
->Storage
[Stable
].BlockList
[BlockIndex
].BlockAddress
;
192 FileOffset
= (BlockIndex
+ 1) * HV_BLOCK_SIZE
;
194 /* Write hive block */
195 Success
= RegistryHive
->FileWrite(RegistryHive
, HFILE_TYPE_PRIMARY
,
196 &FileOffset
, BlockPtr
,
206 Success
= RegistryHive
->FileFlush(RegistryHive
, HFILE_TYPE_PRIMARY
, NULL
, 0);
209 DPRINT("FileFlush failed\n");
212 /* Update second update counter and CheckSum */
213 RegistryHive
->BaseBlock
->Sequence2
++;
214 RegistryHive
->BaseBlock
->CheckSum
=
215 HvpHiveHeaderChecksum(RegistryHive
->BaseBlock
);
217 /* Write hive block */
219 Success
= RegistryHive
->FileWrite(RegistryHive
, HFILE_TYPE_PRIMARY
,
220 &FileOffset
, RegistryHive
->BaseBlock
,
221 sizeof(HBASE_BLOCK
));
227 Success
= RegistryHive
->FileFlush(RegistryHive
, HFILE_TYPE_PRIMARY
, NULL
, 0);
230 DPRINT("FileFlush failed\n");
240 ASSERT(RegistryHive
->ReadOnly
== FALSE
);
242 if (RtlFindSetBits(&RegistryHive
->DirtyVector
, 1, 0) == ~0U)
247 /* Update hive header modification time */
248 KeQuerySystemTime(&RegistryHive
->BaseBlock
->TimeStamp
);
250 /* Update log file */
251 if (!HvpWriteLog(RegistryHive
))
256 /* Update hive file */
257 if (!HvpWriteHive(RegistryHive
, TRUE
))
262 /* Clear dirty bitmap. */
263 RtlClearAllBits(&RegistryHive
->DirtyVector
);
272 ASSERT(RegistryHive
->ReadOnly
== FALSE
);
274 /* Update hive header modification time */
275 KeQuerySystemTime(&RegistryHive
->BaseBlock
->TimeStamp
);
277 /* Update hive file */
278 if (!HvpWriteHive(RegistryHive
, FALSE
))