24#define GET_HHIVE(CmHive) (&((CmHive)->Hive))
25#define GET_HHIVE_ROOT_CELL(Hive) ((Hive)->BaseBlock->RootCell)
26#define GET_HHIVE_BIN(Hive, StorageIndex, BlockIndex) ((PHBIN)Hive->Storage[StorageIndex].BlockList[BlockIndex].BinAddress)
27#define GET_CELL_BIN(Bin) ((PHCELL)((PUCHAR)Bin + sizeof(HBIN)))
29#define IS_CELL_VOLATILE(Cell) (HvGetCellType(Cell) == Volatile)
31#if !defined(CMLIB_HOST) && !defined(_BLDR_)
35#define CMP_PRIOR_STACK 1
36#define CMP_REGISTRY_MAX_LEVELS_TREE_DEPTH 512
38#define CMP_KEY_SIZE_THRESHOLD 0x45C
39#define CMP_VOLATILE_LIST_UNINTIALIZED 0xBAADF00D
82 DPRINT1(
"Failed to get the child node\n");
91 DPRINT1(
"Failed to get the sibling node\n");
100 SiblingString.
Buffer = &(SiblingNode->
Name[0]);
112 DPRINT1(
"The sibling node name is greater or equal to that of the child\n");
122 DPRINT(
"Lexicographical order checks for two compressed names is UNIMPLEMENTED, assume the key is healthy...\n");
130 SiblingString.
Buffer = &(SiblingNode->
Name[0]);
138 DPRINT1(
"The sibling node name is greater or equal to that of the compressed child\n");
155 DPRINT1(
"The compressed sibling node name is lesser or equal to that of the child\n");
204 ClassCell = CellData->u.KeyNode.Class;
205 ClassLength = CellData->u.KeyNode.ClassLength;
214 DPRINT1(
"The key node class is NIL but the class length is not 0, resetting it\n");
216 CellData->u.KeyNode.ClassLength = 0;
222 DPRINT1(
"The key class is not allocated\n");
290 ULONG ListCountIndex;
295 ULONG ValueNameLength, TotalValueNameLength;
310 while (ListCountIndex < ListCount)
312 ValueCell = ValueListData->u.KeyList[ListCountIndex];
321 DPRINT1(
"The value cell is NIL (at index %lu, list count %lu)\n",
322 ListCountIndex, ListCount);
329 DPRINT1(
"Damaged value removed, continuing with the next value...\n");
341 DPRINT1(
"The value cell is not allocated (at index %lu, list count %lu)\n",
342 ListCountIndex, ListCount);
349 DPRINT1(
"Damaged value removed, continuing with the next value...\n");
357 DPRINT1(
"Cell data of the value cell not found (at index %lu, value count %lu)\n",
358 ListCountIndex, ListCount);
364 ValueNameLength =
ValueData->u.KeyValue.NameLength;
366 if (TotalValueNameLength > ValueDataSize)
374 DPRINT1(
"The total size is bigger than the actual cell size (total size %lu, cell size %lu, at index %lu)\n",
375 TotalValueNameLength, ValueDataSize, ListCountIndex);
382 DPRINT1(
"Damaged value removed, continuing with the next value...\n");
412 DPRINT1(
"The data is not NIL on a 0 length, data is corrupt\n");
419 DPRINT1(
"Damaged value removed, continuing with the next value...\n");
433 DPRINT1(
"The data is not NIL on a 0 length, data is corrupt\n");
440 DPRINT1(
"Damaged value removed, continuing with the next value...\n");
458 DPRINT1(
"The key value signature is invalid\n");
465 DPRINT1(
"Damaged value removed, continuing with the next value...\n");
515 ULONG TotalValueLength, ValueSize;
516 ULONG ValueListCount;
527 ValueListCell = CellData->u.KeyNode.ValueList.List;
528 ValueListCount = CellData->u.KeyNode.ValueList.Count;
529 if (ValueListCount > 0)
533 DPRINT1(
"The value list is not allocated\n");
541 DPRINT1(
"Could not get cell data from the value list\n");
551 TotalValueLength = ValueListCount *
sizeof(
HCELL_INDEX);
552 if (TotalValueLength > ValueSize)
554 DPRINT1(
"The value list is bigger than the cell (value list size %lu, cell size %lu)\n",
555 TotalValueLength, ValueSize);
572 DPRINT1(
"One of the values is corrupt and couldn't be repaired\n");
577 if (ValuesRemoved > 0)
579 DPRINT1(
"Values removed in the list -- %lu\n", ValuesRemoved);
655 ULONG TotalLeafCount;
683 if (CellData->u.KeyNode.SubKeyCounts[
Stable] != 0)
685 DPRINT1(
"The volatile key has stable subkeys\n");
696 SubKeysListCell = CellData->u.KeyNode.SubKeyLists[
Stable];
697 SubKeyCounts = CellData->u.KeyNode.SubKeyCounts[
Stable];
698 if (SubKeyCounts > 0)
702 DPRINT1(
"The subkeys list cell is not allocated\n");
711 DPRINT1(
"Could not get the root key index of the subkeys list cell\n");
725 if (SubKeyCounts != RootKeyIndex->
Count)
733 DPRINT1(
"The subkeys list has invalid count (subkeys count %lu, root key index count %lu)\n",
734 SubKeyCounts, RootKeyIndex->
Count);
755 for (RootIndex = 0; RootIndex < RootKeyIndex->
Count; RootIndex++)
757 KeyIndexCell = RootKeyIndex->
List[RootIndex];
760 DPRINT1(
"The key index cell is not allocated at index %lu\n", RootIndex);
769 DPRINT1(
"The root key index's signature is invalid!\n");
778 DPRINT1(
"The leaf's signature is invalid!\n");
784 TotalLeafCount += LeafKeyIndex->
Count;
793 if (SubKeyCounts != TotalLeafCount)
801 DPRINT1(
"The subkeys list has invalid count (subkeys count %lu, total leaf count %lu)\n",
802 SubKeyCounts, TotalLeafCount);
815 DPRINT1(
"The root key index's signature is invalid\n");
862 (CellData->u.KeyNode.SubKeyCounts[
Volatile] != 0))
884 CellData->u.KeyNode.SubKeyCounts[
Volatile] = 0;
951 ULONG TotalKeyNameLength, NameLength;
968 DPRINT1(
"The key cell is not allocated\n");
976 DPRINT1(
"Could not get cell data from the cell\n");
984 DPRINT1(
"The cell size is above the threshold size (size %lu)\n", CellSize);
996 DPRINT1(
"The key node name length is 0!\n");
1001 if (TotalKeyNameLength > CellSize)
1003 DPRINT1(
"The key is too big than the cell (key size %lu, cell size %lu)\n", TotalKeyNameLength, CellSize);
1017 DPRINT1(
"The parent key node doesn't point to the actual parent\n");
1030 DPRINT1(
"The parent key node signature is not valid\n");
1050 DPRINT1(
"Failed to repair the hive, the cell class is not valid\n");
1051 return CmStatusCode;
1068 DPRINT1(
"Failed to repair the hive, the value list is corrupt\n");
1069 return CmStatusCode;
1081 if (!DoSubkeysRepair)
1083 DPRINT1(
"The subkeys list is totally corrupt, can't repair\n");
1084 return CmStatusCode;
1096 DPRINT1(
"Failed to repair the hive, the subkeys list is corrupt!\n");
1097 return CmStatusCode;
1158 ULONG WorkStateLength;
1180 DPRINT1(
"Couldn't allocate memory for registry stack work state\n");
1188 DPRINT1(
"Couldn't get the root cell of the hive\n");
1189 CmpFree(WorkState, WorkStateLength);
1201 WorkState[StackDepth].
Current = RootCell;
1211 AllChildrenChecked =
FALSE;
1213 while (StackDepth >= 0)
1216 CurrentCell = WorkState[StackDepth].
Current;
1217 ParentCell = WorkState[StackDepth].
Parent;
1220 if (!AllChildrenChecked)
1237 if (CurrentCell == RootCell)
1239 DPRINT1(
"THE ROOT CELL IS BROKEN\n");
1240 CmpFree(WorkState, WorkStateLength);
1241 return CmStatusCode;
1251 DPRINT1(
"The key is corrupt (current cell %lu, parent cell %lu)\n",
1252 CurrentCell, ParentCell);
1253 CmpFree(WorkState, WorkStateLength);
1254 return CmStatusCode;
1258 DPRINT1(
"Hive repaired, restarting the validation loop...\n");
1259 goto RestartValidation;
1267 if (StackDepth > 0 &&
1282 DPRINT1(
"The lexicographical order is invalid (sibling %lu, current cell %lu)\n",
1284 CmpFree(WorkState, WorkStateLength);
1289 DPRINT1(
"Hive repaired, restarting the validation loop...\n");
1290 goto RestartValidation;
1303 DPRINT1(
"Couldn't get the node of key (current cell %lu)\n", CurrentCell);
1304 CmpFree(WorkState, WorkStateLength);
1316 if (WorkState[StackDepth].ChildCellIndex < KeyNode->SubKeyCounts[
Stable])
1326 DPRINT1(
"Couldn't get the child subkey cell (at stack index %lu)\n", StackDepth);
1327 CmpFree(WorkState, WorkStateLength);
1350 DPRINT1(
"The registry tree has so many levels!\n");
1351 CmpFree(WorkState, WorkStateLength);
1357 WorkState[StackDepth].
Current = ChildSubKeyCell;
1366 AllChildrenChecked =
FALSE;
1378 AllChildrenChecked =
TRUE;
1383 CmpFree(WorkState, WorkStateLength);
1427 DPRINT1(
"The bin's signature header is corrupt\n");
1458 DPRINT1(
"The free cell exceeds the bin size or cell size equal to 0 (cell 0x%p, cell size %d, bin size %lu)\n",
1476 DPRINT1(
"The allocated cell exceeds the bin size (cell 0x%p, cell size %d, bin size %lu)\n",
1511 ULONG StorageLength;
1521 DPRINT1(
"Hive's signature corrupted (signature %lu)\n", Hive->Signature);
1529 for (StorageIndex = 0; StorageIndex < Hive->StorageTypeCount; StorageIndex++)
1532 StorageLength = Hive->Storage[StorageIndex].Length;
1534 for (BlockIndex = 0; BlockIndex < StorageLength;)
1537 if (Hive->Storage[StorageIndex].BlockList[BlockIndex].BinAddress == (
ULONG_PTR)
NULL)
1551 DPRINT1(
"Bin size or offset is corrupt (bin size %lu, file offset %lu, storage length %lu)\n",
1552 Bin->Size,
Bin->FileOffset, StorageLength);
1560 DPRINT1(
"This bin is not valid (bin 0x%p)\n",
Bin);
1561 return CmStatusCode;
1646 DPRINT1(
"No registry hive given for check\n");
1650#if !defined(CMLIB_HOST) && !defined(_BLDR_)
1658 DPRINT(
"This is master registry hive, don't do anything\n");
1670 DPRINT1(
"Invalid flag for registry check given (flag %lu)\n",
Flags);
1684 DPRINT1(
"The hive is not valid (hive 0x%p, check status code %lu)\n", Hive, CmStatusCode);
1685 return CmStatusCode;
1696 ShouldFixHive =
TRUE;
1711 DPRINT1(
"The hive is not valid (hive 0x%p, check status code %lu)\n", Hive, CmStatusCode);
1712 return CmStatusCode;
1715 return CmStatusCode;
PVOID NTAPI CmpAllocate(_In_ SIZE_T Size, _In_ BOOLEAN Paged, _In_ ULONG Tag)
VOID NTAPI CmpFree(_In_ PVOID Ptr, _In_ ULONG Quota)
#define CMP_VOLATILE_LIST_UNINTIALIZED
CM_CHECK_REGISTRY_STATUS NTAPI HvValidateBin(_In_ PHHIVE Hive, _In_ PHBIN Bin)
Validates a bin from a hive. It performs checks against the cells from this bin, ensuring the bin is ...
CM_CHECK_REGISTRY_STATUS NTAPI HvValidateHive(_In_ PHHIVE Hive)
Validates a registry hive. This function ensures that the storage of this hive has valid bins.
static BOOLEAN CmpValidateLexicalOrder(_In_ PHHIVE Hive, _In_ HCELL_INDEX Child, _In_ HCELL_INDEX Sibling)
Validates the lexicographical order between a child and prior sibling of the said child.
static CM_CHECK_REGISTRY_STATUS CmpValidateValueListByCount(_In_ PHHIVE Hive, _In_ HCELL_INDEX CurrentCell, _In_ ULONG ListCount, _In_ PCELL_DATA ValueListData, _Out_ PULONG ValuesRemoved, _In_ BOOLEAN FixHive)
Validates each value in the list by count. A value that is damaged gets removed from the list....
static CM_CHECK_REGISTRY_STATUS CmpValidateKey(_In_ PHHIVE Hive, _In_ BOOLEAN SecurityDefaulted, _In_ HCELL_INDEX ParentCell, _In_ HCELL_INDEX CurrentCell, _In_ ULONG Flags, _In_ BOOLEAN FixHive)
Validates the key cell, ensuring that the key in the registry is valid and not corrupted.
CM_CHECK_REGISTRY_STATUS NTAPI CmCheckRegistry(_In_ PCMHIVE RegistryHive, _In_ ULONG Flags)
Checks the registry that is consistent and its contents valid and not corrupted. More specifically th...
#define CMP_REGISTRY_MAX_LEVELS_TREE_DEPTH
#define GET_HHIVE(CmHive)
#define CMP_KEY_SIZE_THRESHOLD
static VOID CmpPurgeVolatiles(_In_ PHHIVE Hive, _In_ HCELL_INDEX CurrentCell, _Inout_ PCELL_DATA CellData, _In_ ULONG Flags)
Purges the volatile storage of a registry hive. This operation is done mainly during the bootup of th...
struct _CMP_REGISTRY_STACK_WORK_STATE CMP_REGISTRY_STACK_WORK_STATE
#define GET_HHIVE_BIN(Hive, StorageIndex, BlockIndex)
static CM_CHECK_REGISTRY_STATUS CmpValidateRegistryInternal(_In_ PHHIVE Hive, _In_ ULONG Flags, _In_ BOOLEAN SecurityDefaulted, _In_ BOOLEAN FixHive)
Performs deep checking of the registry by walking down the registry tree using a stack based pool....
#define GET_CELL_BIN(Bin)
#define GET_HHIVE_ROOT_CELL(Hive)
static CM_CHECK_REGISTRY_STATUS CmpValidateSubKeyList(_In_ PHHIVE Hive, _In_ HCELL_INDEX CurrentCell, _Inout_ PCELL_DATA CellData, _In_ BOOLEAN FixHive, _Out_ PBOOLEAN DoRepair)
Validates the subkeys list of a key. If the list is damaged from corruption, the function can either ...
static CM_CHECK_REGISTRY_STATUS CmpValidateClass(_In_ PHHIVE Hive, _In_ HCELL_INDEX CurrentCell, _Inout_ PCELL_DATA CellData)
Validates the class of a given key cell.
static CM_CHECK_REGISTRY_STATUS CmpValidateValueList(_In_ PHHIVE Hive, _In_ HCELL_INDEX CurrentCell, _Inout_ PCELL_DATA CellData, _In_ BOOLEAN FixHive)
Validates the value list of a key. If the list is damaged due to corruption, the whole list is expung...
struct _CMP_REGISTRY_STACK_WORK_STATE * PCMP_REGISTRY_STACK_WORK_STATE
#define IS_CELL_VOLATILE(Cell)
struct _CELL_DATA * PCELL_DATA
struct _CM_KEY_NODE * PCM_KEY_NODE
#define CM_KEY_VALUE_SIGNATURE
#define CM_KEY_INDEX_LEAF
#define CM_KEY_NODE_SIGNATURE
#define CM_KEY_INDEX_ROOT
struct _CM_KEY_INDEX * PCM_KEY_INDEX
BOOLEAN CMAPI CmpRepairValueList(_Inout_ PHHIVE Hive, _In_ HCELL_INDEX CurrentCell, _In_ BOOLEAN FixHive)
Repairs the value list due to corruption. The process involes by purging the whole damaged list.
BOOLEAN CMAPI CmpRepairClassOfNodeKey(_Inout_ PHHIVE Hive, _In_ HCELL_INDEX CurrentCell, _Inout_ PCELL_DATA CellData, _In_ BOOLEAN FixHive)
Repairs the class from damage due to class corruption within the node key.
BOOLEAN CMAPI CmpRepairParentNode(_Inout_ PHHIVE Hive, _In_ HCELL_INDEX CurrentCell, _In_ HCELL_INDEX ParentCell, _Inout_ PCELL_DATA CellData, _In_ BOOLEAN FixHive)
Repairs the parent of the node from damage due to parent cell and parent node incosistency.
BOOLEAN CMAPI CmpRepairValueListCount(_Inout_ PHHIVE Hive, _In_ HCELL_INDEX CurrentCell, _In_ ULONG ListCountIndex, _Inout_ PCELL_DATA ValueListData, _In_ BOOLEAN FixHive)
Repairs the value list count of key due to corruption. The process involves by removing one damaged v...
BOOLEAN CMAPI CmpRepairKeyNodeSignature(_Inout_ PHHIVE Hive, _In_ HCELL_INDEX CurrentCell, _Inout_ PCELL_DATA CellData, _In_ BOOLEAN FixHive)
Repairs the key node signature from damage due to signature corruption.
BOOLEAN CMAPI CmpRepairSubKeyCounts(_Inout_ PHHIVE Hive, _In_ HCELL_INDEX CurrentCell, _In_ ULONG Count, _Inout_ PCELL_DATA CellData, _In_ BOOLEAN FixHive)
Repairs the subkey list count due to corruption. The process involves by fixing the count itself with...
BOOLEAN CMAPI CmpRepairSubKeyList(_Inout_ PHHIVE Hive, _In_ HCELL_INDEX CurrentCell, _Inout_ PCELL_DATA CellData, _In_ BOOLEAN FixHive)
Repairs the subkey list due to corruption. The process involves by purging the whole damaged subkeys ...
BOOLEAN CMAPI CmpRepairParentKey(_Inout_ PHHIVE Hive, _In_ HCELL_INDEX TargetKey, _In_ HCELL_INDEX ParentKey, _In_ BOOLEAN FixHive)
Repairs the parent key from damage by removing the offending subkey cell.
HCELL_INDEX NTAPI CmpFindSubKeyByNumber(IN PHHIVE Hive, IN PCM_KEY_NODE Node, IN ULONG Number)
#define CM_CHECK_REGISTRY_CELL_SIZE_NOT_SANE
#define CM_CHECK_REGISTRY_INVALID_PARAMETER
#define CM_CHECK_REGISTRY_BAD_SUBKEY_COUNT
#define CM_CHECK_REGISTRY_ROOT_CELL_NOT_FOUND
#define CM_CHECK_REGISTRY_BAD_FREE_CELL
#define CM_CHECK_REGISTRY_KEY_TOO_BIG_THAN_CELL
#define CM_CHECK_REGISTRY_VALUE_CELL_DATA_NOT_FOUND
#define CM_CHECK_REGISTRY_VALUE_CELL_UNALLOCATED
#define CM_CHECK_REGISTRY_KEY_NAME_LENGTH_ZERO
#define CM_CHECK_REGISTRY_DONT_PURGE_VOLATILES
#define CM_CHECK_REGISTRY_BAD_LEXICOGRAPHICAL_ORDER
#define CM_CHECK_REGISTRY_STABLE_KEYS_ON_VOLATILE
#define CM_CHECK_REGISTRY_NODE_NOT_FOUND
#define CM_CHECK_REGISTRY_VALUE_CELL_SIZE_NOT_SANE
#define CM_CHECK_REGISTRY_GOOD
#define CM_CHECK_REGISTRY_HIVE_CORRUPT_SIGNATURE
#define CM_CHECK_REGISTRY_KEY_INDEX_CELL_UNALLOCATED
#define CM_CHECK_REGISTRY_PURGE_VOLATILES
#define CM_CHECK_REGISTRY_BAD_KEY_NODE_PARENT
#define CM_CHECK_REGISTRY_BIN_SIZE_OR_OFFSET_CORRUPT
#define CM_CHECK_REGISTRY_CORRUPT_LEAF_ON_ROOT
#define CM_CHECK_REGISTRY_ALLOCATE_MEM_STACK_FAIL
#define TAG_REGISTRY_STACK
#define CM_CHECK_REGISTRY_BAD_ALLOC_CELL
#define CM_CHECK_REGISTRY_CORRUPT_LEAF_SIGNATURE
#define ASSERT_VALUE_BIG(h, s)
#define CM_CHECK_REGISTRY_VALIDATE_HIVE
#define CM_CHECK_REGISTRY_KEY_CELL_NOT_ALLOCATED
static BOOLEAN CmpIsKeyValueSmall(OUT PULONG RealLength, IN ULONG Length)
BOOLEAN CMAPI HvIsCellAllocated(IN PHHIVE RegistryHive, IN HCELL_INDEX CellIndex)
LONG CMAPI HvGetCellSize(PHHIVE RegistryHive, PVOID Cell)
#define CM_CHECK_REGISTRY_FIX_HIVE
LONG NTAPI CmpCompareCompressedName(IN PCUNICODE_STRING SearchName, IN PWCHAR CompressedName, IN ULONG NameLength)
#define CM_CHECK_REGISTRY_DATA_CELL_NOT_ALLOCATED
#define CM_CHECK_REGISTRY_SUCCESS(StatusCode)
ULONG CM_CHECK_REGISTRY_STATUS
#define CM_CHECK_REGISTRY_VALUE_LIST_UNALLOCATED
BOOLEAN CMAPI HvMarkCellDirty(PHHIVE RegistryHive, HCELL_INDEX CellOffset, BOOLEAN HoldingLock)
#define CM_CHECK_REGISTRY_BAD_KEY_NODE_SIGNATURE
#define CM_CHECK_REGISTRY_BOOTLOADER_PURGE_VOLATILES
#define CM_CHECK_REGISTRY_BIN_SIGNATURE_HEADER_CORRUPT
#define CM_CHECK_REGISTRY_SUBKEY_NOT_FOUND
#define CM_CHECK_REGISTRY_VALUE_CELL_NIL
#define CM_CHECK_REGISTRY_CORRUPT_VALUE_DATA
#define CM_CHECK_REGISTRY_BAD_KEY_VALUE_SIGNATURE
#define HvGetCell(Hive, Cell)
#define CM_CHECK_REGISTRY_TREE_TOO_MANY_LEVELS
#define CM_CHECK_REGISTRY_CORRUPT_SUBKEYS_INDEX
#define CM_CHECK_REGISTRY_CELL_DATA_NOT_FOUND
#define CM_CHECK_REGISTRY_SUBKEYS_LIST_UNALLOCATED
#define CM_CHECK_REGISTRY_VALUE_LIST_DATA_NOT_FOUND
#define CM_CHECK_REGISTRY_KEY_CLASS_UNALLOCATED
#define CM_CHECK_REGISTRY_CORRUPT_KEY_INDEX_SIGNATURE
#define CM_CHECK_REGISTRY_VALUE_LIST_SIZE_NOT_SANE
ULONG RtlCompareUnicodeString(PUNICODE_STRING s1, PUNICODE_STRING s2, BOOLEAN UpCase)
#define HV_HBIN_SIGNATURE
#define HV_HHIVE_SIGNATURE
#define HSYS_WHISTLER_BETA1
_In_ GUID _In_ PVOID ValueData
_In_ NDIS_STATUS _In_ ULONG _In_ USHORT _In_opt_ PVOID _In_ ULONG DataSize
#define UNREFERENCED_PARAMETER(P)
union _CELL_DATA::@4273 u
HCELL_INDEX List[ANYSIZE_ARRAY]
WCHAR Name[ANYSIZE_ARRAY]
#define FIELD_OFFSET(t, f)
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFDEVICE Child
_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
_Must_inspect_result_ _In_ ULONG Flags