/* * PROJECT: Registry manipulation library * LICENSE: GPL - See COPYING in the top level directory * COPYRIGHT: Copyright 2005 Filip Navara * Copyright 2001 - 2005 Eric Kohl */ #include "cmlib.h" #define NDEBUG #include static BOOLEAN CMAPI HvpWriteLog( PHHIVE RegistryHive) { #if 0 // UNIMPLEMENTED ULONG FileOffset; UINT32 BufferSize; UINT32 BitmapSize; PUCHAR Buffer; PUCHAR Ptr; ULONG BlockIndex; ULONG LastIndex; PVOID BlockPtr; BOOLEAN Success; ASSERT(RegistryHive->ReadOnly == FALSE); ASSERT(RegistryHive->BaseBlock->Length == RegistryHive->Storage[Stable].Length * HBLOCK_SIZE); DPRINT("HvpWriteLog called\n"); if (RegistryHive->BaseBlock->Sequence1 != RegistryHive->BaseBlock->Sequence2) { return FALSE; } BitmapSize = RegistryHive->DirtyVector.SizeOfBitMap; BufferSize = HV_LOG_HEADER_SIZE + sizeof(ULONG) + BitmapSize; BufferSize = ROUND_UP(BufferSize, HBLOCK_SIZE); DPRINT("Bitmap size %u buffer size: %u\n", BitmapSize, BufferSize); Buffer = RegistryHive->Allocate(BufferSize, TRUE, TAG_CM); if (Buffer == NULL) { return FALSE; } /* Update first update counter and CheckSum */ RegistryHive->BaseBlock->Type = HFILE_TYPE_LOG; RegistryHive->BaseBlock->Sequence1++; RegistryHive->BaseBlock->CheckSum = HvpHiveHeaderChecksum(RegistryHive->BaseBlock); /* Copy hive header */ RtlCopyMemory(Buffer, RegistryHive->BaseBlock, 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 */ FileOffset = 0; Success = RegistryHive->FileWrite(RegistryHive, HFILE_TYPE_LOG, &FileOffset, Buffer, BufferSize); RegistryHive->Free(Buffer, 0); if (!Success) { return FALSE; } /* Write dirty blocks */ FileOffset = BufferSize; BlockIndex = 0; while (BlockIndex < RegistryHive->Storage[Stable].Length) { LastIndex = BlockIndex; BlockIndex = RtlFindSetBits(&RegistryHive->DirtyVector, 1, BlockIndex); if (BlockIndex == ~0U || BlockIndex < LastIndex) { break; } BlockPtr = (PVOID)RegistryHive->Storage[Stable].BlockList[BlockIndex].BlockAddress; /* Write hive block */ Success = RegistryHive->FileWrite(RegistryHive, HFILE_TYPE_LOG, &FileOffset, BlockPtr, HBLOCK_SIZE); if (!Success) { return FALSE; } BlockIndex++; FileOffset += HBLOCK_SIZE; } Success = RegistryHive->FileSetSize(RegistryHive, HFILE_TYPE_LOG, FileOffset, FileOffset); if (!Success) { DPRINT("FileSetSize failed\n"); return FALSE; } /* Flush the log file */ Success = RegistryHive->FileFlush(RegistryHive, HFILE_TYPE_LOG, NULL, 0); if (!Success) { DPRINT("FileFlush failed\n"); } /* Update second update counter and CheckSum */ RegistryHive->BaseBlock->Sequence2++; RegistryHive->BaseBlock->CheckSum = HvpHiveHeaderChecksum(RegistryHive->BaseBlock); /* Write hive header again with updated sequence counter. */ FileOffset = 0; Success = RegistryHive->FileWrite(RegistryHive, HFILE_TYPE_LOG, &FileOffset, RegistryHive->BaseBlock, HV_LOG_HEADER_SIZE); if (!Success) { return FALSE; } /* Flush the log file */ Success = RegistryHive->FileFlush(RegistryHive, HFILE_TYPE_LOG, NULL, 0); if (!Success) { DPRINT("FileFlush failed\n"); } #endif // UNIMPLEMENTED return TRUE; } static BOOLEAN CMAPI HvpWriteHive( PHHIVE RegistryHive, BOOLEAN OnlyDirty) { ULONG FileOffset; ULONG BlockIndex; ULONG LastIndex; PVOID BlockPtr; BOOLEAN Success; ASSERT(RegistryHive->ReadOnly == FALSE); ASSERT(RegistryHive->BaseBlock->Length == RegistryHive->Storage[Stable].Length * HBLOCK_SIZE); DPRINT("HvpWriteHive called\n"); if (RegistryHive->BaseBlock->Sequence1 != RegistryHive->BaseBlock->Sequence2) { return FALSE; } /* Update first update counter and CheckSum */ RegistryHive->BaseBlock->Type = HFILE_TYPE_PRIMARY; RegistryHive->BaseBlock->Sequence1++; RegistryHive->BaseBlock->CheckSum = HvpHiveHeaderChecksum(RegistryHive->BaseBlock); /* Write hive block */ FileOffset = 0; Success = RegistryHive->FileWrite(RegistryHive, HFILE_TYPE_PRIMARY, &FileOffset, RegistryHive->BaseBlock, sizeof(HBASE_BLOCK)); if (!Success) { return FALSE; } BlockIndex = 0; while (BlockIndex < RegistryHive->Storage[Stable].Length) { if (OnlyDirty) { LastIndex = BlockIndex; BlockIndex = RtlFindSetBits(&RegistryHive->DirtyVector, 1, BlockIndex); if (BlockIndex == ~0U || BlockIndex < LastIndex) { break; } } BlockPtr = (PVOID)RegistryHive->Storage[Stable].BlockList[BlockIndex].BlockAddress; FileOffset = (BlockIndex + 1) * HBLOCK_SIZE; /* Write hive block */ Success = RegistryHive->FileWrite(RegistryHive, HFILE_TYPE_PRIMARY, &FileOffset, BlockPtr, HBLOCK_SIZE); if (!Success) { return FALSE; } BlockIndex++; } Success = RegistryHive->FileFlush(RegistryHive, HFILE_TYPE_PRIMARY, NULL, 0); if (!Success) { DPRINT("FileFlush failed\n"); } /* Update second update counter and CheckSum */ RegistryHive->BaseBlock->Sequence2++; RegistryHive->BaseBlock->CheckSum = HvpHiveHeaderChecksum(RegistryHive->BaseBlock); /* Write hive block */ FileOffset = 0; Success = RegistryHive->FileWrite(RegistryHive, HFILE_TYPE_PRIMARY, &FileOffset, RegistryHive->BaseBlock, sizeof(HBASE_BLOCK)); if (!Success) { return FALSE; } Success = RegistryHive->FileFlush(RegistryHive, HFILE_TYPE_PRIMARY, NULL, 0); if (!Success) { DPRINT("FileFlush failed\n"); } return TRUE; } BOOLEAN CMAPI HvSyncHive( PHHIVE RegistryHive) { ASSERT(RegistryHive->ReadOnly == FALSE); if (RtlFindSetBits(&RegistryHive->DirtyVector, 1, 0) == ~0U) { return TRUE; } /* Update hive header modification time */ KeQuerySystemTime(&RegistryHive->BaseBlock->TimeStamp); /* Update log file */ if (!HvpWriteLog(RegistryHive)) { return FALSE; } /* Update hive file */ if (!HvpWriteHive(RegistryHive, TRUE)) { return FALSE; } /* Clear dirty bitmap. */ RtlClearAllBits(&RegistryHive->DirtyVector); RegistryHive->DirtyCount = 0; return TRUE; } BOOLEAN CMAPI HvHiveWillShrink(IN PHHIVE RegistryHive) { /* No shrinking yet */ return FALSE; } BOOLEAN CMAPI HvWriteHive( PHHIVE RegistryHive) { ASSERT(RegistryHive->ReadOnly == FALSE); /* Update hive header modification time */ KeQuerySystemTime(&RegistryHive->BaseBlock->TimeStamp); /* Update hive file */ if (!HvpWriteHive(RegistryHive, FALSE)) { return FALSE; } return TRUE; }