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 %u, list count %u)\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 %u, list count %u)\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 %u, value count %u)\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 %u, cell size %u, at index %u)\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 %u, cell size %u)\n",
555 TotalValueLength, ValueSize);
572 DPRINT1(
"One of the values is corrupt and couldn't be repaired\n");
577 if (ValuesRemoved > 0)
579 DPRINT1(
"%u values removed in the list\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 %u, root key index count %u)\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 %u\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 %u, total leaf count %u)\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 %u)\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 %u, cell size %u)\n",
1004 TotalKeyNameLength, CellSize);
1018 DPRINT1(
"The parent key node doesn't point to the actual parent\n");
1031 DPRINT1(
"The parent key node signature is not valid\n");
1051 DPRINT1(
"Failed to repair the hive, the cell class is not valid\n");
1052 return CmStatusCode;
1069 DPRINT1(
"Failed to repair the hive, the value list is corrupt\n");
1070 return CmStatusCode;
1082 if (!DoSubkeysRepair)
1084 DPRINT1(
"The subkeys list is totally corrupt, can't repair\n");
1085 return CmStatusCode;
1097 DPRINT1(
"Failed to repair the hive, the subkeys list is corrupt!\n");
1098 return CmStatusCode;
1159 ULONG WorkStateLength;
1181 DPRINT1(
"Couldn't allocate memory for registry stack work state\n");
1189 DPRINT1(
"Couldn't get the root cell of the hive\n");
1190 CmpFree(WorkState, WorkStateLength);
1202 WorkState[StackDepth].
Current = RootCell;
1212 AllChildrenChecked =
FALSE;
1214 while (StackDepth >= 0)
1217 CurrentCell = WorkState[StackDepth].
Current;
1218 ParentCell = WorkState[StackDepth].
Parent;
1221 if (!AllChildrenChecked)
1238 if (CurrentCell == RootCell)
1240 DPRINT1(
"THE ROOT CELL IS BROKEN\n");
1241 CmpFree(WorkState, WorkStateLength);
1242 return CmStatusCode;
1252 DPRINT1(
"The key is corrupt (current cell 0x%x, parent cell 0x%x)\n",
1253 CurrentCell, ParentCell);
1254 CmpFree(WorkState, WorkStateLength);
1255 return CmStatusCode;
1259 DPRINT1(
"Hive repaired, restarting the validation loop...\n");
1260 goto RestartValidation;
1268 if (StackDepth > 0 &&
1283 DPRINT1(
"The lexicographical order is invalid (sibling 0x%x, current cell 0x%x)\n",
1285 CmpFree(WorkState, WorkStateLength);
1290 DPRINT1(
"Hive repaired, restarting the validation loop...\n");
1291 goto RestartValidation;
1304 DPRINT1(
"Couldn't get the node of key (current cell 0x%x)\n", CurrentCell);
1305 CmpFree(WorkState, WorkStateLength);
1317 if (WorkState[StackDepth].ChildCellIndex < KeyNode->SubKeyCounts[
Stable])
1327 DPRINT1(
"Couldn't get the child subkey cell (at stack index %d)\n", StackDepth);
1328 CmpFree(WorkState, WorkStateLength);
1351 DPRINT1(
"The registry tree has so many levels!\n");
1352 CmpFree(WorkState, WorkStateLength);
1358 WorkState[StackDepth].
Current = ChildSubKeyCell;
1367 AllChildrenChecked =
FALSE;
1379 AllChildrenChecked =
TRUE;
1384 CmpFree(WorkState, WorkStateLength);
1428 DPRINT1(
"The bin's signature header is corrupt\n");
1459 DPRINT1(
"The free cell exceeds the bin size or cell size equal to 0 (cell 0x%p, cell size %d, bin size %u)\n",
1477 DPRINT1(
"The allocated cell exceeds the bin size (cell 0x%p, cell size %d, bin size %u)\n",
1512 ULONG StorageLength;
1522 DPRINT1(
"Hive's signature corrupted (signature %u)\n", Hive->Signature);
1530 for (StorageIndex = 0; StorageIndex < Hive->StorageTypeCount; StorageIndex++)
1533 StorageLength = Hive->Storage[StorageIndex].Length;
1535 for (BlockIndex = 0; BlockIndex < StorageLength;)
1538 if (Hive->Storage[StorageIndex].BlockList[BlockIndex].BinAddress == (
ULONG_PTR)
NULL)
1552 DPRINT1(
"Bin size or offset is corrupt (bin size %u, file offset %u, storage length %u)\n",
1553 Bin->Size,
Bin->FileOffset, StorageLength);
1561 DPRINT1(
"This bin is not valid (bin 0x%p)\n",
Bin);
1562 return CmStatusCode;
1647 DPRINT1(
"No registry hive given for check\n");
1651#if !defined(CMLIB_HOST) && !defined(_BLDR_)
1659 DPRINT(
"This is master registry hive, don't do anything\n");
1671 DPRINT1(
"Invalid flag for registry check given (flag %u)\n",
Flags);
1685 DPRINT1(
"The hive is not valid (hive 0x%p, check status code %u)\n",
1686 Hive, CmStatusCode);
1687 return CmStatusCode;
1698 ShouldFixHive =
TRUE;
1713 DPRINT1(
"The hive is not valid (hive 0x%p, check status code %u)\n",
1714 Hive, CmStatusCode);
1715 return CmStatusCode;
1718 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::@4305 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