2006-11-08 11:47:44 +00:00
|
|
|
/*
|
|
|
|
* 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)
|
|
|
|
{
|
2007-10-25 15:53:51 +00:00
|
|
|
ULONG FileOffset;
|
2006-11-08 11:47:44 +00:00
|
|
|
SIZE_T BufferSize;
|
|
|
|
SIZE_T BitmapSize;
|
|
|
|
PUCHAR Buffer;
|
|
|
|
PUCHAR Ptr;
|
|
|
|
ULONG BlockIndex;
|
|
|
|
ULONG LastIndex;
|
|
|
|
PVOID BlockPtr;
|
|
|
|
BOOLEAN Success;
|
2007-09-28 04:56:40 +00:00
|
|
|
|
|
|
|
DPRINT1("FIXME: HvpWriteLog doesn't do anything atm\n");
|
|
|
|
return TRUE;
|
|
|
|
|
2006-11-08 11:47:44 +00:00
|
|
|
ASSERT(RegistryHive->ReadOnly == FALSE);
|
2007-09-28 04:56:40 +00:00
|
|
|
|
2006-11-08 11:47:44 +00:00
|
|
|
DPRINT("HvpWriteLog called\n");
|
|
|
|
|
2007-10-25 15:53:51 +00:00
|
|
|
if (RegistryHive->BaseBlock->Sequence1 !=
|
|
|
|
RegistryHive->BaseBlock->Sequence2)
|
2006-11-08 11:47:44 +00:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
|
2007-10-25 15:53:51 +00:00
|
|
|
Buffer = RegistryHive->Allocate(BufferSize, TRUE, TAG_CM);
|
2006-11-08 11:47:44 +00:00
|
|
|
if (Buffer == NULL)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2007-10-25 15:53:51 +00:00
|
|
|
/* Update first update counter and CheckSum */
|
|
|
|
RegistryHive->BaseBlock->Type = HFILE_TYPE_LOG;
|
|
|
|
RegistryHive->BaseBlock->Sequence1++;
|
|
|
|
RegistryHive->BaseBlock->CheckSum =
|
|
|
|
HvpHiveHeaderChecksum(RegistryHive->BaseBlock);
|
2006-11-08 11:47:44 +00:00
|
|
|
|
|
|
|
/* Copy hive header */
|
2007-10-25 15:53:51 +00:00
|
|
|
RtlCopyMemory(Buffer, RegistryHive->BaseBlock, HV_LOG_HEADER_SIZE);
|
2006-11-08 11:47:44 +00:00
|
|
|
Ptr = Buffer + HV_LOG_HEADER_SIZE;
|
|
|
|
RtlCopyMemory(Ptr, "DIRT", 4);
|
|
|
|
Ptr += 4;
|
|
|
|
RtlCopyMemory(Ptr, RegistryHive->DirtyVector.Buffer, BitmapSize);
|
|
|
|
|
|
|
|
/* Write hive block and block bitmap */
|
2007-10-25 15:53:51 +00:00
|
|
|
FileOffset = 0;
|
|
|
|
Success = RegistryHive->FileWrite(RegistryHive, HFILE_TYPE_LOG,
|
|
|
|
&FileOffset, Buffer, BufferSize);
|
|
|
|
RegistryHive->Free(Buffer, 0);
|
2007-09-28 04:17:13 +00:00
|
|
|
|
2006-11-08 11:47:44 +00:00
|
|
|
if (!Success)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Write dirty blocks */
|
|
|
|
FileOffset = BufferSize;
|
|
|
|
BlockIndex = 0;
|
2007-10-25 15:53:51 +00:00
|
|
|
while (BlockIndex < RegistryHive->Storage[Stable].Length)
|
2006-11-08 11:47:44 +00:00
|
|
|
{
|
|
|
|
LastIndex = BlockIndex;
|
|
|
|
BlockIndex = RtlFindSetBits(&RegistryHive->DirtyVector, 1, BlockIndex);
|
2008-12-03 17:32:36 +00:00
|
|
|
if (BlockIndex == ~0U || BlockIndex < LastIndex)
|
2006-11-08 11:47:44 +00:00
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2007-10-25 15:53:51 +00:00
|
|
|
BlockPtr = (PVOID)RegistryHive->Storage[Stable].BlockList[BlockIndex].BlockAddress;
|
2006-11-08 11:47:44 +00:00
|
|
|
|
|
|
|
/* Write hive block */
|
2007-10-25 15:53:51 +00:00
|
|
|
Success = RegistryHive->FileWrite(RegistryHive, HFILE_TYPE_LOG,
|
|
|
|
&FileOffset, BlockPtr,
|
2006-11-08 11:47:44 +00:00
|
|
|
HV_BLOCK_SIZE);
|
|
|
|
if (!Success)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
BlockIndex++;
|
|
|
|
FileOffset += HV_BLOCK_SIZE;
|
|
|
|
}
|
|
|
|
|
2007-10-25 15:53:51 +00:00
|
|
|
Success = RegistryHive->FileSetSize(RegistryHive, HFILE_TYPE_LOG, FileOffset, FileOffset);
|
2006-11-08 11:47:44 +00:00
|
|
|
if (!Success)
|
|
|
|
{
|
|
|
|
DPRINT("FileSetSize failed\n");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Flush the log file */
|
2007-10-25 15:53:51 +00:00
|
|
|
Success = RegistryHive->FileFlush(RegistryHive, HFILE_TYPE_LOG, NULL, 0);
|
2006-11-08 11:47:44 +00:00
|
|
|
if (!Success)
|
|
|
|
{
|
|
|
|
DPRINT("FileFlush failed\n");
|
|
|
|
}
|
|
|
|
|
2007-10-25 15:53:51 +00:00
|
|
|
/* Update first and second update counter and CheckSum. */
|
|
|
|
RegistryHive->BaseBlock->Sequence2++;
|
|
|
|
RegistryHive->BaseBlock->CheckSum =
|
|
|
|
HvpHiveHeaderChecksum(RegistryHive->BaseBlock);
|
2006-11-08 11:47:44 +00:00
|
|
|
|
|
|
|
/* Write hive header again with updated sequence counter. */
|
2007-10-25 15:53:51 +00:00
|
|
|
FileOffset = 0;
|
|
|
|
Success = RegistryHive->FileWrite(RegistryHive, HFILE_TYPE_LOG,
|
|
|
|
&FileOffset, RegistryHive->BaseBlock,
|
2006-11-08 11:47:44 +00:00
|
|
|
HV_LOG_HEADER_SIZE);
|
|
|
|
if (!Success)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Flush the log file */
|
2007-10-25 15:53:51 +00:00
|
|
|
Success = RegistryHive->FileFlush(RegistryHive, HFILE_TYPE_LOG, NULL, 0);
|
2006-11-08 11:47:44 +00:00
|
|
|
if (!Success)
|
|
|
|
{
|
|
|
|
DPRINT("FileFlush failed\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static BOOLEAN CMAPI
|
|
|
|
HvpWriteHive(
|
|
|
|
PHHIVE RegistryHive,
|
|
|
|
BOOLEAN OnlyDirty)
|
|
|
|
{
|
2007-10-25 15:53:51 +00:00
|
|
|
ULONG FileOffset;
|
2006-11-08 11:47:44 +00:00
|
|
|
ULONG BlockIndex;
|
|
|
|
ULONG LastIndex;
|
|
|
|
PVOID BlockPtr;
|
|
|
|
BOOLEAN Success;
|
|
|
|
|
|
|
|
ASSERT(RegistryHive->ReadOnly == FALSE);
|
2007-10-19 23:21:45 +00:00
|
|
|
|
2006-11-08 11:47:44 +00:00
|
|
|
DPRINT("HvpWriteHive called\n");
|
|
|
|
|
2007-10-25 15:53:51 +00:00
|
|
|
if (RegistryHive->BaseBlock->Sequence1 !=
|
|
|
|
RegistryHive->BaseBlock->Sequence2)
|
2006-11-08 11:47:44 +00:00
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2007-10-25 15:53:51 +00:00
|
|
|
/* Update first update counter and CheckSum */
|
|
|
|
RegistryHive->BaseBlock->Type = HFILE_TYPE_PRIMARY;
|
|
|
|
RegistryHive->BaseBlock->Sequence1++;
|
|
|
|
RegistryHive->BaseBlock->CheckSum =
|
2007-12-14 13:02:39 +00:00
|
|
|
HvpHiveHeaderChecksum(RegistryHive->BaseBlock);
|
2006-11-08 11:47:44 +00:00
|
|
|
|
|
|
|
/* Write hive block */
|
2007-10-25 15:53:51 +00:00
|
|
|
FileOffset = 0;
|
|
|
|
Success = RegistryHive->FileWrite(RegistryHive, HFILE_TYPE_PRIMARY,
|
|
|
|
&FileOffset, RegistryHive->BaseBlock,
|
2006-11-08 11:47:44 +00:00
|
|
|
sizeof(HBASE_BLOCK));
|
|
|
|
if (!Success)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
BlockIndex = 0;
|
2007-10-25 15:53:51 +00:00
|
|
|
while (BlockIndex < RegistryHive->Storage[Stable].Length)
|
2006-11-08 11:47:44 +00:00
|
|
|
{
|
|
|
|
if (OnlyDirty)
|
|
|
|
{
|
|
|
|
LastIndex = BlockIndex;
|
|
|
|
BlockIndex = RtlFindSetBits(&RegistryHive->DirtyVector, 1, BlockIndex);
|
2008-12-03 17:32:36 +00:00
|
|
|
if (BlockIndex == ~0U || BlockIndex < LastIndex)
|
2006-11-08 11:47:44 +00:00
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-10-25 15:53:51 +00:00
|
|
|
BlockPtr = (PVOID)RegistryHive->Storage[Stable].BlockList[BlockIndex].BlockAddress;
|
2008-09-21 11:34:04 +00:00
|
|
|
FileOffset = (BlockIndex + 1) * HV_BLOCK_SIZE;
|
2006-11-08 11:47:44 +00:00
|
|
|
|
|
|
|
/* Write hive block */
|
2007-10-25 15:53:51 +00:00
|
|
|
Success = RegistryHive->FileWrite(RegistryHive, HFILE_TYPE_PRIMARY,
|
|
|
|
&FileOffset, BlockPtr,
|
2006-11-08 11:47:44 +00:00
|
|
|
HV_BLOCK_SIZE);
|
|
|
|
if (!Success)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
BlockIndex++;
|
|
|
|
}
|
|
|
|
|
2007-10-25 15:53:51 +00:00
|
|
|
Success = RegistryHive->FileFlush(RegistryHive, HFILE_TYPE_PRIMARY, NULL, 0);
|
2006-11-08 11:47:44 +00:00
|
|
|
if (!Success)
|
|
|
|
{
|
|
|
|
DPRINT("FileFlush failed\n");
|
|
|
|
}
|
|
|
|
|
2007-10-25 15:53:51 +00:00
|
|
|
/* Update second update counter and CheckSum */
|
|
|
|
RegistryHive->BaseBlock->Sequence2++;
|
|
|
|
RegistryHive->BaseBlock->CheckSum =
|
|
|
|
HvpHiveHeaderChecksum(RegistryHive->BaseBlock);
|
2006-11-08 11:47:44 +00:00
|
|
|
|
|
|
|
/* Write hive block */
|
2007-10-25 15:53:51 +00:00
|
|
|
FileOffset = 0;
|
|
|
|
Success = RegistryHive->FileWrite(RegistryHive, HFILE_TYPE_PRIMARY,
|
|
|
|
&FileOffset, RegistryHive->BaseBlock,
|
2006-11-08 11:47:44 +00:00
|
|
|
sizeof(HBASE_BLOCK));
|
|
|
|
if (!Success)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2007-10-25 15:53:51 +00:00
|
|
|
Success = RegistryHive->FileFlush(RegistryHive, HFILE_TYPE_PRIMARY, NULL, 0);
|
2006-11-08 11:47:44 +00:00
|
|
|
if (!Success)
|
|
|
|
{
|
|
|
|
DPRINT("FileFlush failed\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN CMAPI
|
|
|
|
HvSyncHive(
|
|
|
|
PHHIVE RegistryHive)
|
|
|
|
{
|
|
|
|
ASSERT(RegistryHive->ReadOnly == FALSE);
|
|
|
|
|
2008-12-03 17:32:36 +00:00
|
|
|
if (RtlFindSetBits(&RegistryHive->DirtyVector, 1, 0) == ~0U)
|
2006-11-08 11:47:44 +00:00
|
|
|
{
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Update hive header modification time */
|
2007-10-25 15:53:51 +00:00
|
|
|
KeQuerySystemTime(&RegistryHive->BaseBlock->TimeStamp);
|
2006-11-08 11:47:44 +00:00
|
|
|
|
|
|
|
/* 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 */
|
2007-10-25 15:53:51 +00:00
|
|
|
KeQuerySystemTime(&RegistryHive->BaseBlock->TimeStamp);
|
2006-11-08 11:47:44 +00:00
|
|
|
|
|
|
|
/* Update hive file */
|
|
|
|
if (!HvpWriteHive(RegistryHive, FALSE))
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|