Partially fixed up tree after merge from HEAD. More to do.
[reactos.git] / reactos / lib / cmlib / hivewrt.c
index e1d1c11..62fcfe7 100644 (file)
-/*\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;
+}