-/*\r
- * PROJECT: registry manipulation library\r
- * LICENSE: GPL - See COPYING in the top level directory\r
- * COPYRIGHT: Copyright 2005 Filip Navara <navaraf@reactos.org>\r
- * Copyright 2001 - 2005 Eric Kohl\r
- */\r
-\r
-#include "cmlib.h"\r
-#define NDEBUG\r
-#include <debug.h>\r
-\r
-static BOOLEAN CMAPI\r
-HvpWriteLog(\r
- PHHIVE RegistryHive)\r
-{\r
- ULONGLONG FileOffset;\r
- SIZE_T BufferSize;\r
- SIZE_T BitmapSize;\r
- PUCHAR Buffer;\r
- PUCHAR Ptr;\r
- ULONG BlockIndex;\r
- ULONG LastIndex;\r
- PVOID BlockPtr;\r
- BOOLEAN Success;\r
- \r
- ASSERT(RegistryHive->ReadOnly == FALSE);\r
- \r
- DPRINT("HvpWriteLog called\n");\r
-\r
- if (RegistryHive->HiveHeader->Sequence1 !=\r
- RegistryHive->HiveHeader->Sequence2)\r
- {\r
- return FALSE;\r
- }\r
-\r
- BitmapSize = RegistryHive->DirtyVector.SizeOfBitMap;\r
- BufferSize = HV_LOG_HEADER_SIZE + sizeof(ULONG) + BitmapSize;\r
- BufferSize = ROUND_UP(BufferSize, HV_BLOCK_SIZE);\r
-\r
- DPRINT("Bitmap size %lu buffer size: %lu\n", BitmapSize, BufferSize);\r
-\r
- Buffer = RegistryHive->Allocate(BufferSize, TRUE);\r
- if (Buffer == NULL)\r
- {\r
- return FALSE;\r
- }\r
-\r
- /* Update first update counter and checksum */\r
- RegistryHive->HiveHeader->Type = HV_TYPE_LOG;\r
- RegistryHive->HiveHeader->Sequence1++;\r
- RegistryHive->HiveHeader->Checksum =\r
- HvpHiveHeaderChecksum(RegistryHive->HiveHeader);\r
-\r
- /* Copy hive header */\r
- RtlCopyMemory(Buffer, RegistryHive->HiveHeader, HV_LOG_HEADER_SIZE);\r
- Ptr = Buffer + HV_LOG_HEADER_SIZE;\r
- RtlCopyMemory(Ptr, "DIRT", 4);\r
- Ptr += 4;\r
- RtlCopyMemory(Ptr, RegistryHive->DirtyVector.Buffer, BitmapSize);\r
-\r
- /* Write hive block and block bitmap */\r
- Success = RegistryHive->FileWrite(RegistryHive, HV_TYPE_LOG,\r
- 0, Buffer, BufferSize);\r
- if (!Success)\r
- {\r
- return FALSE;\r
- }\r
-\r
- RegistryHive->Free(Buffer);\r
-\r
- /* Write dirty blocks */\r
- FileOffset = BufferSize;\r
- BlockIndex = 0;\r
- while (BlockIndex < RegistryHive->Storage[HvStable].Length)\r
- {\r
- LastIndex = BlockIndex;\r
- BlockIndex = RtlFindSetBits(&RegistryHive->DirtyVector, 1, BlockIndex);\r
- if (BlockIndex == ~0 || BlockIndex < LastIndex)\r
- {\r
- break;\r
- }\r
-\r
- BlockPtr = (PVOID)RegistryHive->Storage[HvStable].BlockList[BlockIndex].Block;\r
-\r
- /* Write hive block */\r
- Success = RegistryHive->FileWrite(RegistryHive, HV_TYPE_LOG,\r
- FileOffset, BlockPtr,\r
- HV_BLOCK_SIZE);\r
- if (!Success)\r
- {\r
- return FALSE;\r
- }\r
-\r
- BlockIndex++;\r
- FileOffset += HV_BLOCK_SIZE;\r
- }\r
-\r
- Success = RegistryHive->FileSetSize(RegistryHive, HV_TYPE_LOG, FileOffset);\r
- if (!Success)\r
- {\r
- DPRINT("FileSetSize failed\n");\r
- return FALSE;\r
- }\r
-\r
- /* Flush the log file */\r
- Success = RegistryHive->FileFlush(RegistryHive, HV_TYPE_LOG);\r
- if (!Success)\r
- {\r
- DPRINT("FileFlush failed\n");\r
- }\r
-\r
- /* Update first and second update counter and checksum. */\r
- RegistryHive->HiveHeader->Sequence2++;\r
- RegistryHive->HiveHeader->Checksum =\r
- HvpHiveHeaderChecksum(RegistryHive->HiveHeader);\r
-\r
- /* Write hive header again with updated sequence counter. */\r
- Success = RegistryHive->FileWrite(RegistryHive, HV_TYPE_LOG,\r
- 0, RegistryHive->HiveHeader,\r
- HV_LOG_HEADER_SIZE);\r
- if (!Success)\r
- {\r
- return FALSE;\r
- }\r
-\r
- /* Flush the log file */\r
- Success = RegistryHive->FileFlush(RegistryHive, HV_TYPE_LOG);\r
- if (!Success)\r
- {\r
- DPRINT("FileFlush failed\n");\r
- }\r
-\r
- return TRUE;\r
-}\r
-\r
-static BOOLEAN CMAPI\r
-HvpWriteHive(\r
- PHHIVE RegistryHive,\r
- BOOLEAN OnlyDirty)\r
-{\r
- ULONGLONG FileOffset;\r
- ULONG BlockIndex;\r
- ULONG LastIndex;\r
- PVOID BlockPtr;\r
- BOOLEAN Success;\r
-\r
- ASSERT(RegistryHive->ReadOnly == FALSE);\r
- \r
- DPRINT("HvpWriteHive called\n");\r
-\r
- if (RegistryHive->HiveHeader->Sequence1 !=\r
- RegistryHive->HiveHeader->Sequence2)\r
- {\r
- return FALSE;\r
- }\r
-\r
- /* Update first update counter and checksum */\r
- RegistryHive->HiveHeader->Type = HV_TYPE_PRIMARY;\r
- RegistryHive->HiveHeader->Sequence1++;\r
- RegistryHive->HiveHeader->Checksum =\r
- HvpHiveHeaderChecksum(RegistryHive->HiveHeader);\r
-\r
- /* Write hive block */\r
- Success = RegistryHive->FileWrite(RegistryHive, HV_TYPE_PRIMARY,\r
- 0, RegistryHive->HiveHeader,\r
- sizeof(HBASE_BLOCK));\r
- if (!Success)\r
- {\r
- return FALSE;\r
- }\r
-\r
- BlockIndex = 0;\r
- while (BlockIndex < RegistryHive->Storage[HvStable].Length)\r
- {\r
- if (OnlyDirty)\r
- {\r
- LastIndex = BlockIndex;\r
- BlockIndex = RtlFindSetBits(&RegistryHive->DirtyVector, 1, BlockIndex);\r
- if (BlockIndex == ~0 || BlockIndex < LastIndex)\r
- {\r
- break;\r
- }\r
- }\r
-\r
- BlockPtr = (PVOID)RegistryHive->Storage[HvStable].BlockList[BlockIndex].Block;\r
- FileOffset = (ULONGLONG)(BlockIndex + 1) * (ULONGLONG)HV_BLOCK_SIZE;\r
-\r
- /* Write hive block */\r
- Success = RegistryHive->FileWrite(RegistryHive, HV_TYPE_PRIMARY,\r
- FileOffset, BlockPtr,\r
- HV_BLOCK_SIZE);\r
- if (!Success)\r
- {\r
- return FALSE;\r
- }\r
-\r
- BlockIndex++;\r
- }\r
-\r
- Success = RegistryHive->FileFlush(RegistryHive, HV_TYPE_PRIMARY);\r
- if (!Success)\r
- {\r
- DPRINT("FileFlush failed\n");\r
- }\r
-\r
- /* Update second update counter and checksum */\r
- RegistryHive->HiveHeader->Sequence2++;\r
- RegistryHive->HiveHeader->Checksum =\r
- HvpHiveHeaderChecksum(RegistryHive->HiveHeader);\r
-\r
- /* Write hive block */\r
- Success = RegistryHive->FileWrite(RegistryHive, HV_TYPE_PRIMARY,\r
- 0, RegistryHive->HiveHeader,\r
- sizeof(HBASE_BLOCK));\r
- if (!Success)\r
- {\r
- return FALSE;\r
- }\r
-\r
- Success = RegistryHive->FileFlush(RegistryHive, HV_TYPE_PRIMARY);\r
- if (!Success)\r
- {\r
- DPRINT("FileFlush failed\n");\r
- }\r
-\r
- return TRUE;\r
-}\r
-\r
-BOOLEAN CMAPI\r
-HvSyncHive(\r
- PHHIVE RegistryHive)\r
-{\r
- ASSERT(RegistryHive->ReadOnly == FALSE);\r
-\r
- if (RtlFindSetBits(&RegistryHive->DirtyVector, 1, 0) == ~0)\r
- {\r
- return TRUE;\r
- }\r
-\r
- /* Update hive header modification time */\r
- KeQuerySystemTime(&RegistryHive->HiveHeader->TimeStamp);\r
-\r
- /* Update log file */\r
- if (!HvpWriteLog(RegistryHive))\r
- {\r
- return FALSE;\r
- }\r
-\r
- /* Update hive file */\r
- if (!HvpWriteHive(RegistryHive, TRUE))\r
- {\r
- return FALSE;\r
- }\r
-\r
- /* Clear dirty bitmap. */\r
- RtlClearAllBits(&RegistryHive->DirtyVector);\r
-\r
- return TRUE;\r
-}\r
-\r
-BOOLEAN CMAPI\r
-HvWriteHive(\r
- PHHIVE RegistryHive)\r
-{\r
- ASSERT(RegistryHive->ReadOnly == FALSE);\r
-\r
- /* Update hive header modification time */\r
- KeQuerySystemTime(&RegistryHive->HiveHeader->TimeStamp);\r
-\r
- /* Update hive file */\r
- if (!HvpWriteHive(RegistryHive, FALSE))\r
- {\r
- return FALSE;\r
- }\r
-\r
- return TRUE;\r
-}\r
+/*
+ * PROJECT: registry manipulation library
+ * LICENSE: GPL - See COPYING in the top level directory
+ * COPYRIGHT: Copyright 2005 Filip Navara <navaraf@reactos.org>
+ * Copyright 2001 - 2005 Eric Kohl
+ */
+
+#include "cmlib.h"
+#define NDEBUG
+#include <debug.h>
+
+static BOOLEAN CMAPI
+HvpWriteLog(
+ PHHIVE RegistryHive)
+{
+ ULONGLONG FileOffset;
+ SIZE_T BufferSize;
+ SIZE_T BitmapSize;
+ PUCHAR Buffer;
+ PUCHAR Ptr;
+ ULONG BlockIndex;
+ ULONG LastIndex;
+ PVOID BlockPtr;
+ BOOLEAN Success;
+
+ ASSERT(RegistryHive->ReadOnly == FALSE);
+
+ DPRINT("HvpWriteLog called\n");
+
+ if (RegistryHive->HiveHeader->Sequence1 !=
+ RegistryHive->HiveHeader->Sequence2)
+ {
+ return FALSE;
+ }
+
+ BitmapSize = RegistryHive->DirtyVector.SizeOfBitMap;
+ BufferSize = HV_LOG_HEADER_SIZE + sizeof(ULONG) + BitmapSize;
+ BufferSize = ROUND_UP(BufferSize, HV_BLOCK_SIZE);
+
+ DPRINT("Bitmap size %lu buffer size: %lu\n", BitmapSize, BufferSize);
+
+ Buffer = RegistryHive->Allocate(BufferSize, TRUE);
+ if (Buffer == NULL)
+ {
+ return FALSE;
+ }
+
+ /* Update first update counter and checksum */
+ RegistryHive->HiveHeader->Type = HV_TYPE_LOG;
+ RegistryHive->HiveHeader->Sequence1++;
+ RegistryHive->HiveHeader->Checksum =
+ HvpHiveHeaderChecksum(RegistryHive->HiveHeader);
+
+ /* Copy hive header */
+ RtlCopyMemory(Buffer, RegistryHive->HiveHeader, HV_LOG_HEADER_SIZE);
+ Ptr = Buffer + HV_LOG_HEADER_SIZE;
+ RtlCopyMemory(Ptr, "DIRT", 4);
+ Ptr += 4;
+ RtlCopyMemory(Ptr, RegistryHive->DirtyVector.Buffer, BitmapSize);
+
+ /* Write hive block and block bitmap */
+ Success = RegistryHive->FileWrite(RegistryHive, HV_TYPE_LOG,
+ 0, Buffer, BufferSize);
+ if (!Success)
+ {
+ return FALSE;
+ }
+
+ RegistryHive->Free(Buffer);
+
+ /* Write dirty blocks */
+ FileOffset = BufferSize;
+ BlockIndex = 0;
+ while (BlockIndex < RegistryHive->Storage[HvStable].Length)
+ {
+ LastIndex = BlockIndex;
+ BlockIndex = RtlFindSetBits(&RegistryHive->DirtyVector, 1, BlockIndex);
+ if (BlockIndex == ~0 || BlockIndex < LastIndex)
+ {
+ break;
+ }
+
+ BlockPtr = (PVOID)RegistryHive->Storage[HvStable].BlockList[BlockIndex].Block;
+
+ /* Write hive block */
+ Success = RegistryHive->FileWrite(RegistryHive, HV_TYPE_LOG,
+ FileOffset, BlockPtr,
+ HV_BLOCK_SIZE);
+ if (!Success)
+ {
+ return FALSE;
+ }
+
+ BlockIndex++;
+ FileOffset += HV_BLOCK_SIZE;
+ }
+
+ Success = RegistryHive->FileSetSize(RegistryHive, HV_TYPE_LOG, FileOffset);
+ if (!Success)
+ {
+ DPRINT("FileSetSize failed\n");
+ return FALSE;
+ }
+
+ /* Flush the log file */
+ Success = RegistryHive->FileFlush(RegistryHive, HV_TYPE_LOG);
+ if (!Success)
+ {
+ DPRINT("FileFlush failed\n");
+ }
+
+ /* Update first and second update counter and checksum. */
+ RegistryHive->HiveHeader->Sequence2++;
+ RegistryHive->HiveHeader->Checksum =
+ HvpHiveHeaderChecksum(RegistryHive->HiveHeader);
+
+ /* Write hive header again with updated sequence counter. */
+ Success = RegistryHive->FileWrite(RegistryHive, HV_TYPE_LOG,
+ 0, RegistryHive->HiveHeader,
+ HV_LOG_HEADER_SIZE);
+ if (!Success)
+ {
+ return FALSE;
+ }
+
+ /* Flush the log file */
+ Success = RegistryHive->FileFlush(RegistryHive, HV_TYPE_LOG);
+ if (!Success)
+ {
+ DPRINT("FileFlush failed\n");
+ }
+
+ return TRUE;
+}
+
+static BOOLEAN CMAPI
+HvpWriteHive(
+ PHHIVE RegistryHive,
+ BOOLEAN OnlyDirty)
+{
+ ULONGLONG FileOffset;
+ ULONG BlockIndex;
+ ULONG LastIndex;
+ PVOID BlockPtr;
+ BOOLEAN Success;
+
+ ASSERT(RegistryHive->ReadOnly == FALSE);
+
+ DPRINT("HvpWriteHive called\n");
+
+ if (RegistryHive->HiveHeader->Sequence1 !=
+ RegistryHive->HiveHeader->Sequence2)
+ {
+ return FALSE;
+ }
+
+ /* Update first update counter and checksum */
+ RegistryHive->HiveHeader->Type = HV_TYPE_PRIMARY;
+ RegistryHive->HiveHeader->Sequence1++;
+ RegistryHive->HiveHeader->Checksum =
+ HvpHiveHeaderChecksum(RegistryHive->HiveHeader);
+
+ /* Write hive block */
+ Success = RegistryHive->FileWrite(RegistryHive, HV_TYPE_PRIMARY,
+ 0, RegistryHive->HiveHeader,
+ sizeof(HBASE_BLOCK));
+ if (!Success)
+ {
+ return FALSE;
+ }
+
+ BlockIndex = 0;
+ while (BlockIndex < RegistryHive->Storage[HvStable].Length)
+ {
+ if (OnlyDirty)
+ {
+ LastIndex = BlockIndex;
+ BlockIndex = RtlFindSetBits(&RegistryHive->DirtyVector, 1, BlockIndex);
+ if (BlockIndex == ~0 || BlockIndex < LastIndex)
+ {
+ break;
+ }
+ }
+
+ BlockPtr = (PVOID)RegistryHive->Storage[HvStable].BlockList[BlockIndex].Block;
+ FileOffset = (ULONGLONG)(BlockIndex + 1) * (ULONGLONG)HV_BLOCK_SIZE;
+
+ /* Write hive block */
+ Success = RegistryHive->FileWrite(RegistryHive, HV_TYPE_PRIMARY,
+ FileOffset, BlockPtr,
+ HV_BLOCK_SIZE);
+ if (!Success)
+ {
+ return FALSE;
+ }
+
+ BlockIndex++;
+ }
+
+ Success = RegistryHive->FileFlush(RegistryHive, HV_TYPE_PRIMARY);
+ if (!Success)
+ {
+ DPRINT("FileFlush failed\n");
+ }
+
+ /* Update second update counter and checksum */
+ RegistryHive->HiveHeader->Sequence2++;
+ RegistryHive->HiveHeader->Checksum =
+ HvpHiveHeaderChecksum(RegistryHive->HiveHeader);
+
+ /* Write hive block */
+ Success = RegistryHive->FileWrite(RegistryHive, HV_TYPE_PRIMARY,
+ 0, RegistryHive->HiveHeader,
+ sizeof(HBASE_BLOCK));
+ if (!Success)
+ {
+ return FALSE;
+ }
+
+ Success = RegistryHive->FileFlush(RegistryHive, HV_TYPE_PRIMARY);
+ if (!Success)
+ {
+ DPRINT("FileFlush failed\n");
+ }
+
+ return TRUE;
+}
+
+BOOLEAN CMAPI
+HvSyncHive(
+ PHHIVE RegistryHive)
+{
+ ASSERT(RegistryHive->ReadOnly == FALSE);
+
+ if (RtlFindSetBits(&RegistryHive->DirtyVector, 1, 0) == ~0)
+ {
+ return TRUE;
+ }
+
+ /* Update hive header modification time */
+ KeQuerySystemTime(&RegistryHive->HiveHeader->TimeStamp);
+
+ /* Update log file */
+ if (!HvpWriteLog(RegistryHive))
+ {
+ return FALSE;
+ }
+
+ /* Update hive file */
+ if (!HvpWriteHive(RegistryHive, TRUE))
+ {
+ return FALSE;
+ }
+
+ /* Clear dirty bitmap. */
+ RtlClearAllBits(&RegistryHive->DirtyVector);
+
+ return TRUE;
+}
+
+BOOLEAN CMAPI
+HvWriteHive(
+ PHHIVE RegistryHive)
+{
+ ASSERT(RegistryHive->ReadOnly == FALSE);
+
+ /* Update hive header modification time */
+ KeQuerySystemTime(&RegistryHive->HiveHeader->TimeStamp);
+
+ /* Update hive file */
+ if (!HvpWriteHive(RegistryHive, FALSE))
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}