58 BaseBlock->Cluster != 1 ||
59 BaseBlock->Sequence1 != BaseBlock->Sequence2 ||
62 DPRINT1(
"Verify Hive Header failed:\n");
63 DPRINT1(
" Signature: 0x%x, expected 0x%x; Major: 0x%x, expected 0x%x\n",
65 DPRINT1(
" Minor: 0x%x expected to be >= 0x%x; Type: 0x%x, expected 0x%x\n",
67 DPRINT1(
" Format: 0x%x, expected 0x%x; Cluster: 0x%x, expected 1\n",
69 DPRINT1(
" Sequence: 0x%x, expected 0x%x; Checksum: 0x%x, expected 0x%x\n",
70 BaseBlock->Sequence1, BaseBlock->Sequence2,
100 for (
i = 0;
i < Hive->Storage[
Storage].Length;
i++)
107 Hive->Free((
PHBIN)Hive->Storage[
Storage].BlockList[
i].BinAddress, 0);
113 if (Hive->Storage[
Storage].Length)
114 Hive->Free(Hive->Storage[
Storage].BlockList, 0);
154 BaseBlock = Hive->Allocate(Hive->BaseBlockAlloc, Paged,
Tag);
155 if (!BaseBlock)
return NULL;
162 Hive->Free(BaseBlock, Hive->BaseBlockAlloc);
164 if (!BaseBlock)
return NULL;
247 if (BaseBlock ==
NULL)
275 RegistryHive->BaseBlock = BaseBlock;
276 RegistryHive->Version = BaseBlock->
Minor;
336 DPRINT1(
"Registry is corrupt: ChunkSize 0x%zx < sizeof(HBASE_BLOCK) 0x%zx, "
343 if (Hive->BaseBlock ==
NULL)
349 Hive->Version = ChunkBase->Minor;
357 Hive->Storage[
Stable].BlockList =
358 Hive->Allocate(Hive->Storage[
Stable].Length *
362 DPRINT1(
"Allocating block list failed\n");
363 Hive->Free(Hive->BaseBlock, Hive->BaseBlockAlloc);
367 for (BlockIndex = 0; BlockIndex < Hive->Storage[
Stable].Length; )
383 DPRINT1(
"Invalid bin at BlockIndex %lu, Signature 0x%x, Size 0x%x. Self-heal not possible!\n",
384 (
unsigned long)BlockIndex, (
unsigned)
Bin->Signature, (
unsigned)
Bin->Size);
385 Hive->Free(Hive->Storage[
Stable].BlockList, 0);
386 Hive->Free(Hive->BaseBlock, Hive->BaseBlockAlloc);
395 DPRINT1(
"Bin at index %lu is corrupt and it has been repaired!\n", (
unsigned long)BlockIndex);
401 Hive->Free(Hive->Storage[
Stable].BlockList, 0);
402 Hive->Free(Hive->BaseBlock, Hive->BaseBlockAlloc);
406 Hive->Storage[
Stable].BlockList[BlockIndex].BinAddress = (
ULONG_PTR)NewBin;
407 Hive->Storage[
Stable].BlockList[BlockIndex].BlockAddress = (
ULONG_PTR)NewBin;
415 Hive->Storage[
Stable].BlockList[BlockIndex +
i].BinAddress = (
ULONG_PTR)NewBin;
416 Hive->Storage[
Stable].BlockList[BlockIndex +
i].BlockAddress =
427 Hive->Free(Hive->BaseBlock, Hive->BaseBlockAlloc);
432 sizeof(
ULONG) * 8) / 8;
437 Hive->Free(Hive->BaseBlock, Hive->BaseBlockAlloc);
453 Hive->DirtyCount = Hive->DirtyVector.SizeOfBitMap;
493 Hive->BaseBlock = ChunkBase;
494 Hive->Version = ChunkBase->Minor;
496 Hive->ReadOnly =
TRUE;
498 Hive->StorageTypeCount = 1;
565 *HiveBaseBlock =
NULL;
569 DPRINT1(
"Failed to allocate an aligned base block buffer\n");
578 Result = Hive->FileRead(Hive,
592 Result = Hive->FileRead(Hive,
599 DPRINT1(
"Failed to read the first block of the first bin hive (hive too corrupt)\n");
600 Hive->Free(BaseBlock, Hive->BaseBlockAlloc);
611 FirstBin = (
PHBIN)BaseBlock;
615 DPRINT1(
"Failed to read the first block of the first bin hive (hive too corrupt)\n");
616 Hive->Free(BaseBlock, Hive->BaseBlockAlloc);
625 DPRINT1(
"The hive is not fully corrupt, the base block needs to be RECOVERED\n");
640 DPRINT1(
"The hive base header block needs to be RECOVERED\n");
642 Hive->Free(BaseBlock, Hive->BaseBlockAlloc);
647 *HiveBaseBlock = BaseBlock;
656#if !defined(_M_AMD64)
674#if !defined(CMLIB_HOST) && !defined(_BLDR_)
686#if !defined(CMLIB_HOST) && !defined(_BLDR_)
761 HeaderResuscitated =
FALSE;
767 DPRINT1(
"Failed to allocate memory for the log header\n");
793 DPRINT1(
"The log couldn't be read and self-healing mode is disabled\n");
794 Hive->Free(LogHeader, Hive->BaseBlockAlloc);
806 DPRINT1(
"Failed to query the hive size\n");
807 Hive->Free(LogHeader, Hive->BaseBlockAlloc);
827 LogHeader->
Length = HiveSize;
834 HeaderResuscitated =
TRUE;
835 DPRINT1(
"Header has been resuscitated, triggering self-heal mode\n");
851 if (!HeaderResuscitated)
857 Success = Hive->FileWrite(Hive,
864 DPRINT1(
"Couldn't write the base header to primary hive\n");
865 Hive->Free(LogHeader, Hive->BaseBlockAlloc);
869 *BaseBlock = LogHeader;
922 DPRINT1(
"The log couldn't be read and self-healing mode is disabled\n");
934 DPRINT1(
"Triggering self-heal mode, DATA LOSS IS IMMINENT\n");
943 DPRINT1(
"The log's dirty vector signature is not valid\n");
953 DPRINT1(
"Triggering self-heal mode, DATA LOSS IS IMMINENT\n");
960 for (BlockIndex = 0; BlockIndex < StorageLength; BlockIndex++)
976 DPRINT1(
"Failed to read the dirty block (index %u)\n", BlockIndex);
981 Success = Hive->FileWrite(Hive,
988 DPRINT1(
"Failed to write dirty block to hive (index %u)\n", BlockIndex);
1038#if defined(_M_AMD64)
1057 DPRINT1(
"There's no enough memory to get the header\n");
1065 DPRINT1(
"The hive is not an actual registry hive file\n");
1089#if defined(_M_AMD64)
1096 #if (NTDDI_VERSION < NTDDI_VISTA)
1099 DPRINT1(
"The hive has no log for header recovery\n");
1105 DPRINT1(
"Attempting to heal the header...\n");
1109 DPRINT1(
"There's no enough memory to recover header from log\n");
1114 if (Result2 ==
Fail)
1116 DPRINT1(
"Failed to recover the hive header\n");
1123 HiveSelfHeal =
TRUE;
1128 if (Result2 ==
Fail)
1130 DPRINT1(
"Failed to recover the hive data\n");
1135 if ((Result2 ==
SelfHeal) && (!HiveSelfHeal))
1137 HiveSelfHeal =
TRUE;
1149 Hive->BaseBlock = BaseBlock;
1150 Hive->Version = BaseBlock->
Minor;
1157 Hive->Free(BaseBlock, Hive->BaseBlockAlloc);
1158 DPRINT1(
"There's no enough memory to allocate hive data\n");
1163 Success = Hive->FileRead(Hive,
1170 DPRINT1(
"Failed to read the whole hive\n");
1172 Hive->Free(BaseBlock, Hive->BaseBlockAlloc);
1192 Hive->Free(BaseBlock, Hive->BaseBlockAlloc);
1196 DPRINT1(
"Failed to initialize hive from memory\n");
1368 PHHIVE Hive = RegistryHive;
1390#if (NTDDI_VERSION < NTDDI_VISTA)
1394 Hive->
HiveFlags = HiveFlags & ~HIVE_NOLAZYFLUSH;
1401 switch (OperationType)
1432 DPRINT1(
"Registry hive couldn't be initialized, it's corrupt (hive 0x%p)\n", Hive);
1437#if !defined(_M_AMD64)
1446 DPRINT1(
"Fail to write healthy data back to hive\n");
1480 DPRINT1(
"HINIT_MEMORY_INPLACE is UNIMPLEMENTED\n");
1486 DPRINT1(
"HINIT_MAPFILE is UNIMPLEMENTED\n");
1492 DPRINT1(
"Invalid operation type (OperationType = %u)\n", OperationType);
1515 if (!RegistryHive->ReadOnly)
1518 if (RegistryHive->DirtyVector.Buffer)
1520 RegistryHive->Free(RegistryHive->DirtyVector.Buffer, 0);
1526 if (RegistryHive->BaseBlock)
1528 RegistryHive->Free(RegistryHive->BaseBlock, RegistryHive->BaseBlockAlloc);
1529 RegistryHive->BaseBlock =
NULL;
_In_ PFCB _In_ LONGLONG FileOffset
BOOLEAN CMAPI CmIsSelfHealEnabled(_In_ BOOLEAN FixHive)
Checks if self healing is permitted by the kernel and/or bootloader. Self healing is also triggered i...
BOOLEAN CMAPI HvSyncHiveFromRecover(_In_ PHHIVE RegistryHive)
Synchronizes a hive with recovered data during a healing/resuscitation operation of the registry.
ULONG CMAPI HvpHiveHeaderChecksum(PHBASE_BLOCK HiveHeader)
PCELL_DATA CMAPI HvpGetCellData(_In_ PHHIVE Hive, _In_ HCELL_INDEX CellIndex)
NTSTATUS CMAPI HvpCreateHiveFreeCellList(PHHIVE Hive)
#define STATUS_NOT_IMPLEMENTED
#define RtlInitializeBitMap
#define NT_SUCCESS(StatCode)
#define ROUND_UP(n, align)
_Must_inspect_result_ _Out_ PLARGE_INTEGER FileSize
union Alignment_ Alignment
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
static ULONG BitmapBuffer[(XMS_BLOCKS+31)/32]
BOOLEAN(CMAPI * PFILE_READ_ROUTINE)(struct _HHIVE *RegistryHive, ULONG FileType, PULONG FileOffset, PVOID Buffer, SIZE_T BufferLength)
#define HV_HBIN_SIGNATURE
#define HBOOT_BOOT_RECOVERED_BY_ALTERNATE_HIVE
#define HBOOT_TYPE_REGULAR
#define HV_HHIVE_SIGNATURE
#define HV_LOG_HEADER_SIZE
#define HFILE_TYPE_ALTERNATE
#define HV_HBLOCK_SIGNATURE
BOOLEAN(CMAPI * PFILE_WRITE_ROUTINE)(struct _HHIVE *RegistryHive, ULONG FileType, PULONG FileOffset, PVOID Buffer, SIZE_T BufferLength)
VOID(CMAPI * PFREE_ROUTINE)(PVOID Ptr, ULONG Quota)
#define HFILE_TYPE_PRIMARY
struct _HBASE_BLOCK HBASE_BLOCK
#define HIVE_FILENAME_MAXLEN
BOOLEAN(CMAPI * PFILE_FLUSH_ROUTINE)(struct _HHIVE *RegistryHive, ULONG FileType, PLARGE_INTEGER FileOffset, ULONG Length)
#define HV_LOG_DIRTY_BLOCK
PVOID(CMAPI * PALLOCATE_ROUTINE)(SIZE_T Size, BOOLEAN Paged, ULONG Tag)
#define HINIT_MEMORY_INPLACE
#define HBOOT_TYPE_SELF_HEAL
#define HBASE_FORMAT_MEMORY
BOOLEAN(CMAPI * PFILE_SET_SIZE_ROUTINE)(struct _HHIVE *RegistryHive, ULONG FileType, ULONG FileSize, ULONG OldfileSize)
#define HV_LOG_DIRTY_SIGNATURE
BOOLEAN CMAPI HvpVerifyHiveHeader(_In_ PHBASE_BLOCK BaseBlock, _In_ ULONG FileType)
Validates the base block header of a registry file (hive or log).
static __inline PHBASE_BLOCK HvpAllocBaseBlockAligned(_In_ PHHIVE Hive, _In_ BOOLEAN Paged, _In_ ULONG Tag)
Allocates a cluster-aligned hive base header block.
NTSTATUS CMAPI HvInitialize(_Inout_ PHHIVE RegistryHive, _In_ ULONG OperationType, _In_ ULONG HiveFlags, _In_ ULONG FileType, _In_opt_ PVOID HiveData, _In_opt_ PALLOCATE_ROUTINE Allocate, _In_opt_ PFREE_ROUTINE Free, _In_opt_ PFILE_SET_SIZE_ROUTINE FileSetSize, _In_opt_ PFILE_WRITE_ROUTINE FileWrite, _In_opt_ PFILE_READ_ROUTINE FileRead, _In_opt_ PFILE_FLUSH_ROUTINE FileFlush, _In_ ULONG Cluster, _In_opt_ PCUNICODE_STRING FileName)
Initializes a registry hive. It allocates a hive descriptor and sets up the hive type depending on th...
VOID CMAPI HvFree(_In_ PHHIVE RegistryHive)
Frees all the bins within the storage, the dirty vector and the base block associated with the given ...
ULONG CMAPI HvpQueryHiveSize(_In_ PHHIVE Hive)
Computes the hive space size by querying the file size of the associated hive file.
NTSTATUS CMAPI HvpInitializeMemoryHive(_In_ PHHIVE Hive, _In_ PHBASE_BLOCK ChunkBase, _In_opt_ PCUNICODE_STRING FileName)
Initializes a hive descriptor from an already loaded registry hive stored in memory....
NTSTATUS CMAPI HvLoadHive(_In_ PHHIVE Hive, _In_opt_ PCUNICODE_STRING FileName)
Loads a registry hive from a physical hive file within the physical backing storage....
static VOID HvpInitFileName(_Inout_ PHBASE_BLOCK BaseBlock, _In_opt_ PCUNICODE_STRING FileName)
Initializes a NULL-terminated Unicode hive file name of a hive header by copying the last 31 characte...
NTSTATUS CMAPI HvpCreateHive(_Inout_ PHHIVE RegistryHive, _In_opt_ PCUNICODE_STRING FileName)
Initializes a hive descriptor structure for a newly created hive in memory.
NTSTATUS CMAPI HvpInitializeFlatHive(_In_ PHHIVE Hive, _In_ PHBASE_BLOCK ChunkBase)
Initializes a hive descriptor for an already loaded hive that is stored in memory....
RESULT CMAPI HvpGetHiveHeader(_In_ PHHIVE Hive, _Inout_ PHBASE_BLOCK *HiveBaseBlock, _Inout_ PLARGE_INTEGER TimeStamp)
Retrieves the base block hive header from the primary hive file stored in physical backing storage....
RESULT CMAPI HvpRecoverHeaderFromLog(_In_ PHHIVE Hive, _In_ PLARGE_INTEGER TimeStamp, _Inout_ PHBASE_BLOCK *BaseBlock)
Recovers the base block header by obtaining it from a log file associated with the hive.
RESULT CMAPI HvpRecoverDataFromLog(_In_ PHHIVE Hive, _In_ PHBASE_BLOCK BaseBlock)
Recovers the registry data by obtaining it from a log that is associated with the hive.
VOID CMAPI HvpFreeHiveBins(_In_ PHHIVE Hive)
Frees all the bins within storage space associated with a hive descriptor.
static OUT PIO_STATUS_BLOCK IoStatusBlock
_In_ ULONG _In_ ULONG Offset
_In_ ULONG _In_ ULONG _In_ ULONG Length
#define STATUS_REGISTRY_RECOVERED
#define STATUS_NOT_REGISTRY_FILE
#define STATUS_REGISTRY_CORRUPT
#define STATUS_REGISTRY_IO_FAILED
SECURITY_INTEGER TimeStamp
#define FileStandardInformation
PFILE_FLUSH_ROUTINE FileFlush
PFILE_SET_SIZE_ROUTINE FileSetSize
PFILE_WRITE_ROUTINE FileWrite
PALLOCATE_ROUTINE Allocate
PFILE_READ_ROUTINE FileRead
PGET_CELL_ROUTINE GetCellRoutine
PRELEASE_CELL_ROUTINE ReleaseCellRoutine
#define RtlCopyMemory(Destination, Source, Length)
#define RtlZeroMemory(Destination, Length)
#define STATUS_INVALID_PARAMETER
#define STATUS_INSUFFICIENT_RESOURCES
struct _LARGE_INTEGER::@2303 u
_In_ WDFCOLLECTION _In_ ULONG Index
_Must_inspect_result_ _In_ WDFDEVICE _In_ BOOLEAN _In_opt_ PVOID Tag
_In_ WDFDEVICE _In_ WDF_SPECIAL_FILE_TYPE FileType
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
_In_opt_ PALLOCATE_FUNCTION Allocate
_In_opt_ PALLOCATE_FUNCTION _In_opt_ PFREE_FUNCTION Free
_Inout_ PUCHAR _In_ PUCHAR _Out_ PUCHAR _Out_ PULONG ChunkSize