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 * HV_BLOCK_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) * HV_BLOCK_SIZE; /* Write hive block */ Success = RegistryHive->FileWrite(RegistryHive, HFILE_TYPE_PRIMARY, &FileOffset, BlockPtr, HV_BLOCK_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; }
static BOOLEAN CMAPI HvpWriteLog( PHHIVE RegistryHive) { ULONG FileOffset; ULONG BufferSize; ULONG BitmapSize; PUCHAR Buffer; PUCHAR Ptr; ULONG BlockIndex; ULONG LastIndex; PVOID BlockPtr; BOOLEAN Success; UNIMPLEMENTED; return TRUE; ASSERT(RegistryHive->ReadOnly == FALSE); ASSERT(RegistryHive->BaseBlock->Length == RegistryHive->Storage[Stable].Length * HV_BLOCK_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, HV_BLOCK_SIZE); DPRINT("Bitmap size %lu buffer size: %lu\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, HV_BLOCK_SIZE); if (!Success) { return FALSE; } BlockIndex++; FileOffset += HV_BLOCK_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"); } return TRUE; }