ReactOS 0.4.15-dev-7958-gcd0bb1a
cmlib.h File Reference
#include <ntdef.h>
#include <ntifs.h>
#include <bugcodes.h>
#include <wine/unicode.h>
#include <wchar.h>
#include "hivedata.h"
#include "cmdata.h"
Include dependency graph for cmlib.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  _CM_USE_COUNT_LOG_ENTRY
 
struct  _CM_USE_COUNT_LOG
 
struct  _CMHIVE
 
struct  _HV_HIVE_CELL_PAIR
 
struct  _HV_TRACK_CELL_REF
 

Macros

#define _CMLIB_DEBUG_   1
 
#define CMLTRACE(x, ...)    if (x & CmlibTraceLevel) DbgPrint(__VA_ARGS__)
 
#define _WINDEF_
 
#define _WINBASE_
 
#define _WINNLS_
 
#define CMLIB_HCELL_DEBUG   0x01
 
#define ROUND_UP(a, b)   ((((a)+(b)-1)/(b))*(b))
 
#define ROUND_DOWN(a, b)   (((a)/(b))*(b))
 
#define TAG_CM   ' MC'
 
#define TAG_KCB   'bkMC'
 
#define TAG_CMHIVE   'vHMC'
 
#define TAG_CMSD   'DSMC'
 
#define TAG_REGISTRY_STACK   'sRMC'
 
#define CMAPI   NTAPI
 
#define CM_CHECK_REGISTRY_DONT_PURGE_VOLATILES   0x0
 
#define CM_CHECK_REGISTRY_PURGE_VOLATILES   0x2
 
#define CM_CHECK_REGISTRY_BOOTLOADER_PURGE_VOLATILES   0x4
 
#define CM_CHECK_REGISTRY_VALIDATE_HIVE   0x8
 
#define CM_CHECK_REGISTRY_FIX_HIVE   0x10
 
#define CM_CHECK_REGISTRY_GOOD   0
 
#define CM_CHECK_REGISTRY_INVALID_PARAMETER   1
 
#define CM_CHECK_REGISTRY_SD_INVALID   2
 
#define CM_CHECK_REGISTRY_HIVE_CORRUPT_SIGNATURE   3
 
#define CM_CHECK_REGISTRY_BIN_SIZE_OR_OFFSET_CORRUPT   4
 
#define CM_CHECK_REGISTRY_BIN_SIGNATURE_HEADER_CORRUPT   5
 
#define CM_CHECK_REGISTRY_BAD_FREE_CELL   6
 
#define CM_CHECK_REGISTRY_BAD_ALLOC_CELL   7
 
#define CM_CHECK_REGISTRY_ALLOCATE_MEM_STACK_FAIL   8
 
#define CM_CHECK_REGISTRY_ROOT_CELL_NOT_FOUND   9
 
#define CM_CHECK_REGISTRY_BAD_LEXICOGRAPHICAL_ORDER   10
 
#define CM_CHECK_REGISTRY_NODE_NOT_FOUND   11
 
#define CM_CHECK_REGISTRY_SUBKEY_NOT_FOUND   12
 
#define CM_CHECK_REGISTRY_TREE_TOO_MANY_LEVELS   13
 
#define CM_CHECK_REGISTRY_KEY_CELL_NOT_ALLOCATED   14
 
#define CM_CHECK_REGISTRY_CELL_DATA_NOT_FOUND   15
 
#define CM_CHECK_REGISTRY_CELL_SIZE_NOT_SANE   16
 
#define CM_CHECK_REGISTRY_KEY_NAME_LENGTH_ZERO   17
 
#define CM_CHECK_REGISTRY_KEY_TOO_BIG_THAN_CELL   18
 
#define CM_CHECK_REGISTRY_BAD_KEY_NODE_PARENT   19
 
#define CM_CHECK_REGISTRY_BAD_KEY_NODE_SIGNATURE   20
 
#define CM_CHECK_REGISTRY_KEY_CLASS_UNALLOCATED   21
 
#define CM_CHECK_REGISTRY_VALUE_LIST_UNALLOCATED   22
 
#define CM_CHECK_REGISTRY_VALUE_LIST_DATA_NOT_FOUND   23
 
#define CM_CHECK_REGISTRY_VALUE_LIST_SIZE_NOT_SANE   24
 
#define CM_CHECK_REGISTRY_VALUE_CELL_NIL   25
 
#define CM_CHECK_REGISTRY_VALUE_CELL_UNALLOCATED   26
 
#define CM_CHECK_REGISTRY_VALUE_CELL_DATA_NOT_FOUND   27
 
#define CM_CHECK_REGISTRY_VALUE_CELL_SIZE_NOT_SANE   28
 
#define CM_CHECK_REGISTRY_CORRUPT_VALUE_DATA   29
 
#define CM_CHECK_REGISTRY_DATA_CELL_NOT_ALLOCATED   30
 
#define CM_CHECK_REGISTRY_BAD_KEY_VALUE_SIGNATURE   31
 
#define CM_CHECK_REGISTRY_STABLE_KEYS_ON_VOLATILE   32
 
#define CM_CHECK_REGISTRY_SUBKEYS_LIST_UNALLOCATED   33
 
#define CM_CHECK_REGISTRY_CORRUPT_SUBKEYS_INDEX   34
 
#define CM_CHECK_REGISTRY_BAD_SUBKEY_COUNT   35
 
#define CM_CHECK_REGISTRY_KEY_INDEX_CELL_UNALLOCATED   36
 
#define CM_CHECK_REGISTRY_CORRUPT_LEAF_ON_ROOT   37
 
#define CM_CHECK_REGISTRY_CORRUPT_LEAF_SIGNATURE   38
 
#define CM_CHECK_REGISTRY_CORRUPT_KEY_INDEX_SIGNATURE   39
 
#define CM_CHECK_REGISTRY_SUCCESS(StatusCode)   ((ULONG)(StatusCode) == CM_CHECK_REGISTRY_GOOD)
 
#define CMP_SECURITY_HASH_LISTS   64
 
#define STATIC_CELL_PAIR_COUNT   4
 
#define ASSERT_VALUE_BIG(h, s)    ASSERTMSG("Big keys not supported!\n", !CmpIsKeyValueBig(h, s));
 
#define HvGetCell(Hive, Cell)    (Hive)->GetCellRoutine(Hive, Cell)
 
#define HvReleaseCell(Hive, Cell)
 

Typedefs

typedef ULONG CM_CHECK_REGISTRY_STATUS
 
typedef struct _CM_KEY_SECURITY_CACHE_ENTRYPCM_KEY_SECURITY_CACHE_ENTRY
 
typedef struct _CM_KEY_CONTROL_BLOCKPCM_KEY_CONTROL_BLOCK
 
typedef struct _CM_CELL_REMAP_BLOCKPCM_CELL_REMAP_BLOCK
 
typedef struct _CM_USE_COUNT_LOG_ENTRY CM_USE_COUNT_LOG_ENTRY
 
typedef struct _CM_USE_COUNT_LOG_ENTRYPCM_USE_COUNT_LOG_ENTRY
 
typedef struct _CM_USE_COUNT_LOG CM_USE_COUNT_LOG
 
typedef struct _CM_USE_COUNT_LOGPCM_USE_COUNT_LOG
 
typedef struct _CMHIVE CMHIVE
 
typedef struct _CMHIVEPCMHIVE
 
typedef struct _HV_HIVE_CELL_PAIR HV_HIVE_CELL_PAIR
 
typedef struct _HV_HIVE_CELL_PAIRPHV_HIVE_CELL_PAIR
 
typedef struct _HV_TRACK_CELL_REF HV_TRACK_CELL_REF
 
typedef struct _HV_TRACK_CELL_REFPHV_TRACK_CELL_REF
 

Functions

static BOOLEAN CmpIsKeyValueSmall (OUT PULONG RealLength, IN ULONG Length)
 
static BOOLEAN CmpIsKeyValueBig (IN PHHIVE Hive, IN ULONG Length)
 
NTSTATUS CMAPI HvInitialize (PHHIVE RegistryHive, ULONG OperationType, ULONG HiveFlags, ULONG FileType, PVOID HiveData OPTIONAL, PALLOCATE_ROUTINE Allocate, PFREE_ROUTINE Free, PFILE_SET_SIZE_ROUTINE FileSetSize, PFILE_WRITE_ROUTINE FileWrite, PFILE_READ_ROUTINE FileRead, PFILE_FLUSH_ROUTINE FileFlush, ULONG Cluster OPTIONAL, PCUNICODE_STRING FileName OPTIONAL)
 
VOID CMAPI HvFree (PHHIVE RegistryHive)
 
LONG CMAPI HvGetCellSize (PHHIVE RegistryHive, PVOID Cell)
 
HCELL_INDEX CMAPI HvAllocateCell (PHHIVE RegistryHive, ULONG Size, HSTORAGE_TYPE Storage, IN HCELL_INDEX Vicinity)
 
BOOLEAN CMAPI HvIsCellAllocated (IN PHHIVE RegistryHive, IN HCELL_INDEX CellIndex)
 
HCELL_INDEX CMAPI HvReallocateCell (PHHIVE RegistryHive, HCELL_INDEX CellOffset, ULONG Size)
 
VOID CMAPI HvFreeCell (PHHIVE RegistryHive, HCELL_INDEX CellOffset)
 
BOOLEAN CMAPI HvMarkCellDirty (PHHIVE RegistryHive, HCELL_INDEX CellOffset, BOOLEAN HoldingLock)
 
BOOLEAN CMAPI HvIsCellDirty (IN PHHIVE Hive, IN HCELL_INDEX Cell)
 
BOOLEAN CMAPI HvHiveWillShrink (IN PHHIVE RegistryHive)
 
BOOLEAN CMAPI HvSyncHive (PHHIVE RegistryHive)
 
BOOLEAN CMAPI HvWriteHive (PHHIVE RegistryHive)
 
BOOLEAN CMAPI HvWriteAlternateHive (_In_ PHHIVE RegistryHive)
 Writes data to an alternate registry hive. An alternate hive is usually backed up by a primary hive. This function is tipically used to force write data into the alternate hive if both hives no longer match.
 
BOOLEAN CMAPI HvSyncHiveFromRecover (_In_ PHHIVE RegistryHive)
 Synchronizes a hive with recovered data during a healing/resuscitation operation of the registry.
 
BOOLEAN CMAPI HvTrackCellRef (IN OUT PHV_TRACK_CELL_REF CellRef, IN PHHIVE Hive, IN HCELL_INDEX Cell)
 
VOID CMAPI HvReleaseFreeCellRefArray (IN OUT PHV_TRACK_CELL_REF CellRef)
 
PCELL_DATA CMAPI HvpGetCellData (_In_ PHHIVE Hive, _In_ HCELL_INDEX CellIndex)
 
PHBIN CMAPI HvpAddBin (PHHIVE RegistryHive, ULONG Size, HSTORAGE_TYPE Storage)
 
NTSTATUS CMAPI HvpCreateHiveFreeCellList (PHHIVE Hive)
 
ULONG CMAPI HvpHiveHeaderChecksum (PHBASE_BLOCK HiveHeader)
 
BOOLEAN CMAPI HvpVerifyHiveHeader (_In_ PHBASE_BLOCK BaseBlock, _In_ ULONG FileType)
 Validates the base block header of a registry file (hive or log).
 
BOOLEAN CMAPI CmIsSelfHealEnabled (_In_ BOOLEAN FixHive)
 Checks if self healing is permitted by the kernel and/or bootloader. Self healing is also triggered if such a request was prompted by the user to fix a broken hive. Such a request tipically comes from a registry repair tool such as the ReactOS Check Registry Utility.
 
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.
 
BOOLEAN CMAPI CmpRepairParentNode (_Inout_ PHHIVE Hive, _In_ HCELL_INDEX DirtyCell, _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 CmpRepairKeyNodeSignature (_Inout_ PHHIVE Hive, _In_ HCELL_INDEX DirtyCell, _Inout_ PCELL_DATA CellData, _In_ BOOLEAN FixHive)
 Repairs the key node signature from damage due to signature corruption.
 
BOOLEAN CMAPI CmpRepairClassOfNodeKey (_Inout_ PHHIVE Hive, _In_ HCELL_INDEX DirtyCell, _Inout_ PCELL_DATA CellData, _In_ BOOLEAN FixHive)
 Repairs the class from damage due to class corruption within the node key.
 
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 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 value less from the list.
 
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 a sane count.
 
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 list.
 
BOOLEAN CMAPI CmCreateRootNode (PHHIVE Hive, PCWSTR Name)
 
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 not corrupt and that the cells are consistent with each other.
 
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.
 
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 this function performs a deep check of the registry for the following properties:
 
HCELL_INDEX NTAPI CmpFindSubKeyByName (IN PHHIVE Hive, IN PCM_KEY_NODE Parent, IN PCUNICODE_STRING SearchName)
 
HCELL_INDEX NTAPI CmpFindSubKeyByNumber (IN PHHIVE Hive, IN PCM_KEY_NODE Node, IN ULONG Number)
 
ULONG NTAPI CmpComputeHashKey (IN ULONG Hash, IN PCUNICODE_STRING Name, IN BOOLEAN AllowSeparators)
 
BOOLEAN NTAPI CmpAddSubKey (IN PHHIVE Hive, IN HCELL_INDEX Parent, IN HCELL_INDEX Child)
 
BOOLEAN NTAPI CmpRemoveSubKey (IN PHHIVE Hive, IN HCELL_INDEX ParentKey, IN HCELL_INDEX TargetKey)
 
BOOLEAN NTAPI CmpMarkIndexDirty (IN PHHIVE Hive, HCELL_INDEX ParentKey, HCELL_INDEX TargetKey)
 
LONG NTAPI CmpCompareCompressedName (IN PCUNICODE_STRING SearchName, IN PWCHAR CompressedName, IN ULONG NameLength)
 
USHORT NTAPI CmpNameSize (IN PHHIVE Hive, IN PCUNICODE_STRING Name)
 
USHORT NTAPI CmpCompressedNameSize (IN PWCHAR Name, IN ULONG Length)
 
USHORT NTAPI CmpCopyName (IN PHHIVE Hive, OUT PWCHAR Destination, IN PCUNICODE_STRING Source)
 
VOID NTAPI CmpCopyCompressedName (OUT PWCHAR Destination, IN ULONG DestinationLength, IN PWCHAR Source, IN ULONG SourceLength)
 
BOOLEAN NTAPI CmpFindNameInList (IN PHHIVE Hive, IN PCHILD_LIST ChildList, IN PCUNICODE_STRING Name, OUT PULONG ChildIndex OPTIONAL, OUT PHCELL_INDEX CellIndex)
 
HCELL_INDEX NTAPI CmpFindValueByName (IN PHHIVE Hive, IN PCM_KEY_NODE KeyNode, IN PCUNICODE_STRING Name)
 
PCELL_DATA NTAPI CmpValueToData (IN PHHIVE Hive, IN PCM_KEY_VALUE Value, OUT PULONG Length)
 
NTSTATUS NTAPI CmpSetValueDataNew (IN PHHIVE Hive, IN PVOID Data, IN ULONG DataSize, IN HSTORAGE_TYPE StorageType, IN HCELL_INDEX ValueCell, OUT PHCELL_INDEX DataCell)
 
NTSTATUS NTAPI CmpAddValueToList (IN PHHIVE Hive, IN HCELL_INDEX ValueCell, IN ULONG Index, IN HSTORAGE_TYPE StorageType, IN OUT PCHILD_LIST ChildList)
 
BOOLEAN NTAPI CmpFreeValue (IN PHHIVE Hive, IN HCELL_INDEX Cell)
 
BOOLEAN NTAPI CmpMarkValueDataDirty (IN PHHIVE Hive, IN PCM_KEY_VALUE Value)
 
BOOLEAN NTAPI CmpFreeValueData (IN PHHIVE Hive, IN HCELL_INDEX DataCell, IN ULONG DataLength)
 
NTSTATUS NTAPI CmpRemoveValueFromList (IN PHHIVE Hive, IN ULONG Index, IN OUT PCHILD_LIST ChildList)
 
BOOLEAN NTAPI CmpGetValueData (IN PHHIVE Hive, IN PCM_KEY_VALUE Value, OUT PULONG Length, OUT PVOID *Buffer, OUT PBOOLEAN BufferAllocated, OUT PHCELL_INDEX CellToRelease)
 
NTSTATUS NTAPI CmpCopyKeyValueList (IN PHHIVE SourceHive, IN PCHILD_LIST SrcValueList, IN PHHIVE DestinationHive, IN OUT PCHILD_LIST DestValueList, IN HSTORAGE_TYPE StorageType)
 
NTSTATUS NTAPI CmpFreeKeyByCell (IN PHHIVE Hive, IN HCELL_INDEX Cell, IN BOOLEAN Unlink)
 
VOID NTAPI CmpRemoveSecurityCellList (IN PHHIVE Hive, IN HCELL_INDEX SecurityCell)
 
VOID NTAPI CmpFreeSecurityDescriptor (IN PHHIVE Hive, IN HCELL_INDEX Cell)
 
PVOID NTAPI CmpAllocate (IN SIZE_T Size, IN BOOLEAN Paged, IN ULONG Tag)
 
VOID NTAPI CmpFree (IN PVOID Ptr, IN ULONG Quota)
 

Variables

ULONG CmlibTraceLevel
 

Macro Definition Documentation

◆ _CMLIB_DEBUG_

#define _CMLIB_DEBUG_   1

Definition at line 15 of file cmlib.h.

◆ _WINBASE_

#define _WINBASE_

Definition at line 185 of file cmlib.h.

◆ _WINDEF_

#define _WINDEF_

Definition at line 184 of file cmlib.h.

◆ _WINNLS_

#define _WINNLS_

Definition at line 186 of file cmlib.h.

◆ ASSERT_VALUE_BIG

#define ASSERT_VALUE_BIG (   h,
  s 
)     ASSERTMSG("Big keys not supported!\n", !CmpIsKeyValueBig(h, s));

Definition at line 386 of file cmlib.h.

◆ CM_CHECK_REGISTRY_ALLOCATE_MEM_STACK_FAIL

#define CM_CHECK_REGISTRY_ALLOCATE_MEM_STACK_FAIL   8

Definition at line 245 of file cmlib.h.

◆ CM_CHECK_REGISTRY_BAD_ALLOC_CELL

#define CM_CHECK_REGISTRY_BAD_ALLOC_CELL   7

Definition at line 244 of file cmlib.h.

◆ CM_CHECK_REGISTRY_BAD_FREE_CELL

#define CM_CHECK_REGISTRY_BAD_FREE_CELL   6

Definition at line 243 of file cmlib.h.

◆ CM_CHECK_REGISTRY_BAD_KEY_NODE_PARENT

#define CM_CHECK_REGISTRY_BAD_KEY_NODE_PARENT   19

Definition at line 256 of file cmlib.h.

◆ CM_CHECK_REGISTRY_BAD_KEY_NODE_SIGNATURE

#define CM_CHECK_REGISTRY_BAD_KEY_NODE_SIGNATURE   20

Definition at line 257 of file cmlib.h.

◆ CM_CHECK_REGISTRY_BAD_KEY_VALUE_SIGNATURE

#define CM_CHECK_REGISTRY_BAD_KEY_VALUE_SIGNATURE   31

Definition at line 268 of file cmlib.h.

◆ CM_CHECK_REGISTRY_BAD_LEXICOGRAPHICAL_ORDER

#define CM_CHECK_REGISTRY_BAD_LEXICOGRAPHICAL_ORDER   10

Definition at line 247 of file cmlib.h.

◆ CM_CHECK_REGISTRY_BAD_SUBKEY_COUNT

#define CM_CHECK_REGISTRY_BAD_SUBKEY_COUNT   35

Definition at line 272 of file cmlib.h.

◆ CM_CHECK_REGISTRY_BIN_SIGNATURE_HEADER_CORRUPT

#define CM_CHECK_REGISTRY_BIN_SIGNATURE_HEADER_CORRUPT   5

Definition at line 242 of file cmlib.h.

◆ CM_CHECK_REGISTRY_BIN_SIZE_OR_OFFSET_CORRUPT

#define CM_CHECK_REGISTRY_BIN_SIZE_OR_OFFSET_CORRUPT   4

Definition at line 241 of file cmlib.h.

◆ CM_CHECK_REGISTRY_BOOTLOADER_PURGE_VOLATILES

#define CM_CHECK_REGISTRY_BOOTLOADER_PURGE_VOLATILES   0x4

Definition at line 230 of file cmlib.h.

◆ CM_CHECK_REGISTRY_CELL_DATA_NOT_FOUND

#define CM_CHECK_REGISTRY_CELL_DATA_NOT_FOUND   15

Definition at line 252 of file cmlib.h.

◆ CM_CHECK_REGISTRY_CELL_SIZE_NOT_SANE

#define CM_CHECK_REGISTRY_CELL_SIZE_NOT_SANE   16

Definition at line 253 of file cmlib.h.

◆ CM_CHECK_REGISTRY_CORRUPT_KEY_INDEX_SIGNATURE

#define CM_CHECK_REGISTRY_CORRUPT_KEY_INDEX_SIGNATURE   39

Definition at line 276 of file cmlib.h.

◆ CM_CHECK_REGISTRY_CORRUPT_LEAF_ON_ROOT

#define CM_CHECK_REGISTRY_CORRUPT_LEAF_ON_ROOT   37

Definition at line 274 of file cmlib.h.

◆ CM_CHECK_REGISTRY_CORRUPT_LEAF_SIGNATURE

#define CM_CHECK_REGISTRY_CORRUPT_LEAF_SIGNATURE   38

Definition at line 275 of file cmlib.h.

◆ CM_CHECK_REGISTRY_CORRUPT_SUBKEYS_INDEX

#define CM_CHECK_REGISTRY_CORRUPT_SUBKEYS_INDEX   34

Definition at line 271 of file cmlib.h.

◆ CM_CHECK_REGISTRY_CORRUPT_VALUE_DATA

#define CM_CHECK_REGISTRY_CORRUPT_VALUE_DATA   29

Definition at line 266 of file cmlib.h.

◆ CM_CHECK_REGISTRY_DATA_CELL_NOT_ALLOCATED

#define CM_CHECK_REGISTRY_DATA_CELL_NOT_ALLOCATED   30

Definition at line 267 of file cmlib.h.

◆ CM_CHECK_REGISTRY_DONT_PURGE_VOLATILES

#define CM_CHECK_REGISTRY_DONT_PURGE_VOLATILES   0x0

Definition at line 228 of file cmlib.h.

◆ CM_CHECK_REGISTRY_FIX_HIVE

#define CM_CHECK_REGISTRY_FIX_HIVE   0x10

Definition at line 232 of file cmlib.h.

◆ CM_CHECK_REGISTRY_GOOD

#define CM_CHECK_REGISTRY_GOOD   0

Definition at line 237 of file cmlib.h.

◆ CM_CHECK_REGISTRY_HIVE_CORRUPT_SIGNATURE

#define CM_CHECK_REGISTRY_HIVE_CORRUPT_SIGNATURE   3

Definition at line 240 of file cmlib.h.

◆ CM_CHECK_REGISTRY_INVALID_PARAMETER

#define CM_CHECK_REGISTRY_INVALID_PARAMETER   1

Definition at line 238 of file cmlib.h.

◆ CM_CHECK_REGISTRY_KEY_CELL_NOT_ALLOCATED

#define CM_CHECK_REGISTRY_KEY_CELL_NOT_ALLOCATED   14

Definition at line 251 of file cmlib.h.

◆ CM_CHECK_REGISTRY_KEY_CLASS_UNALLOCATED

#define CM_CHECK_REGISTRY_KEY_CLASS_UNALLOCATED   21

Definition at line 258 of file cmlib.h.

◆ CM_CHECK_REGISTRY_KEY_INDEX_CELL_UNALLOCATED

#define CM_CHECK_REGISTRY_KEY_INDEX_CELL_UNALLOCATED   36

Definition at line 273 of file cmlib.h.

◆ CM_CHECK_REGISTRY_KEY_NAME_LENGTH_ZERO

#define CM_CHECK_REGISTRY_KEY_NAME_LENGTH_ZERO   17

Definition at line 254 of file cmlib.h.

◆ CM_CHECK_REGISTRY_KEY_TOO_BIG_THAN_CELL

#define CM_CHECK_REGISTRY_KEY_TOO_BIG_THAN_CELL   18

Definition at line 255 of file cmlib.h.

◆ CM_CHECK_REGISTRY_NODE_NOT_FOUND

#define CM_CHECK_REGISTRY_NODE_NOT_FOUND   11

Definition at line 248 of file cmlib.h.

◆ CM_CHECK_REGISTRY_PURGE_VOLATILES

#define CM_CHECK_REGISTRY_PURGE_VOLATILES   0x2

Definition at line 229 of file cmlib.h.

◆ CM_CHECK_REGISTRY_ROOT_CELL_NOT_FOUND

#define CM_CHECK_REGISTRY_ROOT_CELL_NOT_FOUND   9

Definition at line 246 of file cmlib.h.

◆ CM_CHECK_REGISTRY_SD_INVALID

#define CM_CHECK_REGISTRY_SD_INVALID   2

Definition at line 239 of file cmlib.h.

◆ CM_CHECK_REGISTRY_STABLE_KEYS_ON_VOLATILE

#define CM_CHECK_REGISTRY_STABLE_KEYS_ON_VOLATILE   32

Definition at line 269 of file cmlib.h.

◆ CM_CHECK_REGISTRY_SUBKEY_NOT_FOUND

#define CM_CHECK_REGISTRY_SUBKEY_NOT_FOUND   12

Definition at line 249 of file cmlib.h.

◆ CM_CHECK_REGISTRY_SUBKEYS_LIST_UNALLOCATED

#define CM_CHECK_REGISTRY_SUBKEYS_LIST_UNALLOCATED   33

Definition at line 270 of file cmlib.h.

◆ CM_CHECK_REGISTRY_SUCCESS

#define CM_CHECK_REGISTRY_SUCCESS (   StatusCode)    ((ULONG)(StatusCode) == CM_CHECK_REGISTRY_GOOD)

Definition at line 281 of file cmlib.h.

◆ CM_CHECK_REGISTRY_TREE_TOO_MANY_LEVELS

#define CM_CHECK_REGISTRY_TREE_TOO_MANY_LEVELS   13

Definition at line 250 of file cmlib.h.

◆ CM_CHECK_REGISTRY_VALIDATE_HIVE

#define CM_CHECK_REGISTRY_VALIDATE_HIVE   0x8

Definition at line 231 of file cmlib.h.

◆ CM_CHECK_REGISTRY_VALUE_CELL_DATA_NOT_FOUND

#define CM_CHECK_REGISTRY_VALUE_CELL_DATA_NOT_FOUND   27

Definition at line 264 of file cmlib.h.

◆ CM_CHECK_REGISTRY_VALUE_CELL_NIL

#define CM_CHECK_REGISTRY_VALUE_CELL_NIL   25

Definition at line 262 of file cmlib.h.

◆ CM_CHECK_REGISTRY_VALUE_CELL_SIZE_NOT_SANE

#define CM_CHECK_REGISTRY_VALUE_CELL_SIZE_NOT_SANE   28

Definition at line 265 of file cmlib.h.

◆ CM_CHECK_REGISTRY_VALUE_CELL_UNALLOCATED

#define CM_CHECK_REGISTRY_VALUE_CELL_UNALLOCATED   26

Definition at line 263 of file cmlib.h.

◆ CM_CHECK_REGISTRY_VALUE_LIST_DATA_NOT_FOUND

#define CM_CHECK_REGISTRY_VALUE_LIST_DATA_NOT_FOUND   23

Definition at line 260 of file cmlib.h.

◆ CM_CHECK_REGISTRY_VALUE_LIST_SIZE_NOT_SANE

#define CM_CHECK_REGISTRY_VALUE_LIST_SIZE_NOT_SANE   24

Definition at line 261 of file cmlib.h.

◆ CM_CHECK_REGISTRY_VALUE_LIST_UNALLOCATED

#define CM_CHECK_REGISTRY_VALUE_LIST_UNALLOCATED   22

Definition at line 259 of file cmlib.h.

◆ CMAPI

#define CMAPI   NTAPI

Definition at line 218 of file cmlib.h.

◆ CMLIB_HCELL_DEBUG

#define CMLIB_HCELL_DEBUG   0x01

Definition at line 193 of file cmlib.h.

◆ CMLTRACE

#define CMLTRACE (   x,
  ... 
)     if (x & CmlibTraceLevel) DbgPrint(__VA_ARGS__)

Definition at line 172 of file cmlib.h.

◆ CMP_SECURITY_HASH_LISTS

#define CMP_SECURITY_HASH_LISTS   64

Definition at line 294 of file cmlib.h.

◆ HvGetCell

#define HvGetCell (   Hive,
  Cell 
)     (Hive)->GetCellRoutine(Hive, Cell)

Definition at line 457 of file cmlib.h.

◆ HvReleaseCell

#define HvReleaseCell (   Hive,
  Cell 
)
Value:
do { \
if ((Hive)->ReleaseCellRoutine) \
(Hive)->ReleaseCellRoutine(Hive, Cell); \
} while(0)

Definition at line 460 of file cmlib.h.

◆ ROUND_DOWN

#define ROUND_DOWN (   a,
  b 
)    (((a)/(b))*(b))

Definition at line 197 of file cmlib.h.

◆ ROUND_UP

#define ROUND_UP (   a,
  b 
)    ((((a)+(b)-1)/(b))*(b))

Definition at line 196 of file cmlib.h.

◆ STATIC_CELL_PAIR_COUNT

#define STATIC_CELL_PAIR_COUNT   4

Definition at line 367 of file cmlib.h.

◆ TAG_CM

#define TAG_CM   ' MC'

Definition at line 212 of file cmlib.h.

◆ TAG_CMHIVE

#define TAG_CMHIVE   'vHMC'

Definition at line 214 of file cmlib.h.

◆ TAG_CMSD

#define TAG_CMSD   'DSMC'

Definition at line 215 of file cmlib.h.

◆ TAG_KCB

#define TAG_KCB   'bkMC'

Definition at line 213 of file cmlib.h.

◆ TAG_REGISTRY_STACK

#define TAG_REGISTRY_STACK   'sRMC'

Definition at line 216 of file cmlib.h.

Typedef Documentation

◆ CM_CHECK_REGISTRY_STATUS

Definition at line 223 of file cmlib.h.

◆ CM_USE_COUNT_LOG

◆ CM_USE_COUNT_LOG_ENTRY

◆ CMHIVE

◆ HV_HIVE_CELL_PAIR

◆ HV_TRACK_CELL_REF

◆ PCM_CELL_REMAP_BLOCK

Definition at line 291 of file cmlib.h.

◆ PCM_KEY_CONTROL_BLOCK

Definition at line 290 of file cmlib.h.

◆ PCM_KEY_SECURITY_CACHE_ENTRY

◆ PCM_USE_COUNT_LOG

◆ PCM_USE_COUNT_LOG_ENTRY

◆ PCMHIVE

typedef struct _CMHIVE * PCMHIVE

◆ PHV_HIVE_CELL_PAIR

◆ PHV_TRACK_CELL_REF

Function Documentation

◆ CmCheckRegistry()

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 this function performs a deep check of the registry for the following properties:

  • That the security cache cell of the registry is OK
  • That bins and cells are consistent with each other
  • That the child subkey cell points to the parent
  • That the key itself has sane sizes
  • That the class, values and subkeys lists are valid
  • Much more
Parameters
[in]HiveA pointer to a CM hive of the registry to be checked in question.
[in]FlagsA bit mask flag used to influence the process of volatile keys purging. See Remarks for further information.
Returns
This function returns a CM (Configuration Manager) check registry status code. A code of CM_CHECK_REGISTRY_GOOD of value 0 indicates the registry hive is valid and not corrupted. A non zero unsigned integer value indicates a failure. Consult other private routines in this file for other failure status codes.
Remarks
During a load operation CmCheckRegistry can purge the volatile data of registry (or not) depending on the submitted flag bit mask by the caller. The following supported flags are:

CM_CHECK_REGISTRY_DONT_PURGE_VOLATILES – Tells the function that volatile data purging must not be done.

CM_CHECK_REGISTRY_PURGE_VOLATILES - Tells the function to purge out volatile information data from a registry hive, on demand. Purging doesn't come into action if no volatile data has been found.

CM_CHECK_REGISTRY_BOOTLOADER_PURGE_VOLATILES - A special flag used by FreeLdr and Environ. When this flag is set the function will not clean up the volatile storage but it will unintialize the storage instead (this is the case if the given registry hive for validation is a XP Beta 1 hive or newer). Otherwise it will perform a normal cleanup of the volatile storage.

CM_CHECK_REGISTRY_VALIDATE_HIVE - Tells the function to perform a thorough analysation of the underlying hive's bins and cells before doing validation of the registry tree. HvValidateHive function is called in this case.

CM_CHECK_REGISTRY_FIX_HIVE - Tells the function to fix the target registry hive if it is damaged. Usually this flag comes from a registry repair tool where the user asked to for its damaged hive to be fixed. In this case a self-heal procedure against the hive is performed.

Definition at line 1633 of file cmcheck.c.

1636{
1637 CM_CHECK_REGISTRY_STATUS CmStatusCode;
1638 PHHIVE Hive;
1639 BOOLEAN ShouldFixHive = FALSE;
1640
1641 PAGED_CODE();
1642
1643 /* Bail out if the caller did not give a hive */
1644 if (!RegistryHive)
1645 {
1646 DPRINT1("No registry hive given for check\n");
1648 }
1649
1650#if !defined(CMLIB_HOST) && !defined(_BLDR_)
1651 /*
1652 * The master hive is the root of the registry,
1653 * it holds all other hives together. So do not
1654 * do any validation checks.
1655 */
1656 if (RegistryHive == CmiVolatileHive)
1657 {
1658 DPRINT("This is master registry hive, don't do anything\n");
1660 }
1661#endif
1662
1663 /* Bail out if no valid flag is given */
1669 {
1670 DPRINT1("Invalid flag for registry check given (flag %lu)\n", Flags);
1672 }
1673
1674 /*
1675 * Obtain the hive and check if the caller wants
1676 * that the hive to be validated.
1677 */
1678 Hive = GET_HHIVE(RegistryHive);
1680 {
1681 CmStatusCode = HvValidateHive(Hive);
1682 if (!CM_CHECK_REGISTRY_SUCCESS(CmStatusCode))
1683 {
1684 DPRINT1("The hive is not valid (hive 0x%p, check status code %lu)\n", Hive, CmStatusCode);
1685 return CmStatusCode;
1686 }
1687 }
1688
1689 /*
1690 * A registry repair tool such as the ReactOS Check Registry
1691 * Utility wants the damaged hive to be fixed as we check the
1692 * target hive.
1693 */
1695 {
1696 ShouldFixHive = TRUE;
1697 }
1698
1699 /*
1700 * FIXME: Currently ReactOS does not implement security
1701 * caching algorithms so it's pretty pointless to implement
1702 * security descriptors validation checks at this moment.
1703 * When the time comes to implement these, we would need
1704 * to implement security checks here as well.
1705 */
1706
1707 /* Call the internal API to do the rest of the work bulk */
1708 CmStatusCode = CmpValidateRegistryInternal(Hive, Flags, FALSE, ShouldFixHive);
1709 if (!CM_CHECK_REGISTRY_SUCCESS(CmStatusCode))
1710 {
1711 DPRINT1("The hive is not valid (hive 0x%p, check status code %lu)\n", Hive, CmStatusCode);
1712 return CmStatusCode;
1713 }
1714
1715 return CmStatusCode;
1716}
#define PAGED_CODE()
unsigned char BOOLEAN
#define DPRINT1
Definition: precomp.h:8
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.
Definition: cmcheck.c:1505
#define GET_HHIVE(CmHive)
Definition: cmcheck.c:24
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....
Definition: cmcheck.c:1147
PCMHIVE CmiVolatileHive
Definition: cmsysini.c:16
#define CM_CHECK_REGISTRY_INVALID_PARAMETER
Definition: cmlib.h:238
#define CM_CHECK_REGISTRY_DONT_PURGE_VOLATILES
Definition: cmlib.h:228
#define CM_CHECK_REGISTRY_GOOD
Definition: cmlib.h:237
#define CM_CHECK_REGISTRY_PURGE_VOLATILES
Definition: cmlib.h:229
#define CM_CHECK_REGISTRY_VALIDATE_HIVE
Definition: cmlib.h:231
#define CM_CHECK_REGISTRY_FIX_HIVE
Definition: cmlib.h:232
#define CM_CHECK_REGISTRY_SUCCESS(StatusCode)
Definition: cmlib.h:281
ULONG CM_CHECK_REGISTRY_STATUS
Definition: cmlib.h:223
#define CM_CHECK_REGISTRY_BOOTLOADER_PURGE_VOLATILES
Definition: cmlib.h:230
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define DPRINT
Definition: sndvol32.h:71
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170

Referenced by BiInitializeAndValidateHive(), CmFlushKey(), CmpInitializeHive(), CmSaveKey(), CmSaveMergedKeys(), and RegInitializeHive().

◆ CmCreateRootNode()

BOOLEAN CMAPI CmCreateRootNode ( PHHIVE  Hive,
PCWSTR  Name 
)

Definition at line 17 of file cminit.c.

20{
22 PCM_KEY_NODE KeyCell;
23 HCELL_INDEX RootCellIndex;
24
25 /* Initialize the node name and allocate it */
27 RootCellIndex = HvAllocateCell(Hive,
29 CmpNameSize(Hive, &KeyName),
30 Stable,
31 HCELL_NIL);
32 if (RootCellIndex == HCELL_NIL) return FALSE;
33
34 /* Seutp the base block */
35 Hive->BaseBlock->RootCell = RootCellIndex;
37
38 /* Get the key cell */
39 KeyCell = (PCM_KEY_NODE)HvGetCell(Hive, RootCellIndex);
40 if (!KeyCell)
41 {
42 HvFreeCell(Hive, RootCellIndex);
43 return FALSE;
44 }
45
46 /* Setup the cell */
49 // KeQuerySystemTime(&KeyCell->LastWriteTime);
50 KeyCell->LastWriteTime.QuadPart = 0ULL;
51 KeyCell->Parent = HCELL_NIL;
52 KeyCell->SubKeyCounts[Stable] = 0;
53 KeyCell->SubKeyCounts[Volatile] = 0;
54 KeyCell->SubKeyLists[Stable] = HCELL_NIL;
55 KeyCell->SubKeyLists[Volatile] = HCELL_NIL;
56 KeyCell->ValueList.Count = 0;
57 KeyCell->ValueList.List = HCELL_NIL;
58 KeyCell->Security = HCELL_NIL;
59 KeyCell->Class = HCELL_NIL;
60 KeyCell->ClassLength = 0;
61 KeyCell->MaxNameLen = 0;
62 KeyCell->MaxClassLen = 0;
63 KeyCell->MaxValueNameLen = 0;
64 KeyCell->MaxValueDataLen = 0;
65 KeyCell->NameLength = CmpCopyName(Hive, KeyCell->Name, &KeyName);
66 if (KeyCell->NameLength < KeyName.Length) KeyCell->Flags |= KEY_COMP_NAME;
67
68 /* Return success */
69 HvReleaseCell(Hive, RootCellIndex);
70 return TRUE;
71}
struct _CM_KEY_NODE * PCM_KEY_NODE
#define KEY_COMP_NAME
Definition: cmdata.h:35
#define KEY_NO_DELETE
Definition: cmdata.h:33
#define CM_KEY_NODE_SIGNATURE
Definition: cmdata.h:21
#define KEY_HIVE_ENTRY
Definition: cmdata.h:32
#define HvReleaseCell(Hive, Cell)
Definition: cmlib.h:460
USHORT NTAPI CmpCopyName(IN PHHIVE Hive, OUT PWCHAR Destination, IN PCUNICODE_STRING Source)
Definition: cmname.c:21
ULONG CMAPI HvpHiveHeaderChecksum(PHBASE_BLOCK HiveHeader)
Definition: hivesum.c:17
USHORT NTAPI CmpNameSize(IN PHHIVE Hive, IN PCUNICODE_STRING Name)
Definition: cmname.c:74
VOID CMAPI HvFreeCell(PHHIVE RegistryHive, HCELL_INDEX CellOffset)
Definition: hivecell.c:468
#define HvGetCell(Hive, Cell)
Definition: cmlib.h:457
HCELL_INDEX CMAPI HvAllocateCell(PHHIVE RegistryHive, ULONG Size, HSTORAGE_TYPE Storage, IN HCELL_INDEX Vicinity)
@ Volatile
Definition: hivedata.h:128
@ Stable
Definition: hivedata.h:127
#define HCELL_NIL
Definition: hivedata.h:110
ULONG HCELL_INDEX
Definition: hivedata.h:105
#define ULL(a, b)
Definition: format_msg.c:27
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
HCELL_INDEX List
Definition: cmdata.h:75
ULONG Count
Definition: cmdata.h:74
USHORT Signature
Definition: cmdata.h:92
HCELL_INDEX Parent
Definition: cmdata.h:96
WCHAR Name[ANYSIZE_ARRAY]
Definition: cmdata.h:116
HCELL_INDEX SubKeyLists[HTYPE_COUNT]
Definition: cmdata.h:102
ULONG MaxValueNameLen
Definition: cmdata.h:111
ULONG MaxNameLen
Definition: cmdata.h:109
ULONG SubKeyCounts[HTYPE_COUNT]
Definition: cmdata.h:97
HCELL_INDEX Security
Definition: cmdata.h:107
USHORT NameLength
Definition: cmdata.h:114
USHORT ClassLength
Definition: cmdata.h:115
ULONG MaxClassLen
Definition: cmdata.h:110
HCELL_INDEX Class
Definition: cmdata.h:108
ULONG MaxValueDataLen
Definition: cmdata.h:112
CHILD_LIST ValueList
Definition: cmdata.h:103
USHORT Flags
Definition: cmdata.h:93
LARGE_INTEGER LastWriteTime
Definition: cmdata.h:94
HCELL_INDEX RootCell
Definition: hivedata.h:168
ULONG CheckSum
Definition: hivedata.h:183
PHBASE_BLOCK BaseBlock
Definition: hivedata.h:328
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
LONGLONG QuadPart
Definition: typedefs.h:114
_Must_inspect_result_ _In_ WDFDEVICE _In_ PCUNICODE_STRING KeyName
Definition: wdfdevice.h:2699

Referenced by CmiInitializeHive().

◆ CmIsSelfHealEnabled()

BOOLEAN CMAPI CmIsSelfHealEnabled ( _In_ BOOLEAN  FixHive)

Checks if self healing is permitted by the kernel and/or bootloader. Self healing is also triggered if such a request was prompted by the user to fix a broken hive. Such a request tipically comes from a registry repair tool such as the ReactOS Check Registry Utility.

Parameters
[in]FixHiveIf set to TRUE, self heal is triggered and the target hive will be fixed. Otherwise the hive will not be fixed.
Returns
Returns TRUE if self healing is possible, FALSE otherwise.

Definition at line 369 of file cmheal.c.

371{
372 PAGED_CODE();
373
374 if (FixHive)
375 return TRUE;
376
377#if !defined(CMLIB_HOST) && !defined(_BLDR_)
379 return TRUE;
380#endif
381
382 return FALSE;
383}
ULONG CmpBootType
Definition: cmdata.c:62
BOOLEAN CmpSelfHeal
Definition: cmdata.c:64
#define HBOOT_TYPE_SELF_HEAL
Definition: hivedata.h:89

Referenced by CmpRepairClassOfNodeKey(), CmpRepairKeyNodeSignature(), CmpRepairParentKey(), CmpRepairParentNode(), CmpRepairSubKeyCounts(), CmpRepairSubKeyList(), CmpRepairValueList(), CmpRepairValueListCount(), HvpInitializeMemoryHive(), HvpRecoverDataFromLog(), and HvpRecoverHeaderFromLog().

◆ CmpAddSubKey()

BOOLEAN NTAPI CmpAddSubKey ( IN PHHIVE  Hive,
IN HCELL_INDEX  Parent,
IN HCELL_INDEX  Child 
)

Definition at line 1465 of file cmindex.c.

1468{
1469 PCM_KEY_NODE KeyNode;
1471 PCM_KEY_FAST_INDEX OldIndex;
1473 HCELL_INDEX IndexCell = HCELL_NIL, CellToRelease = HCELL_NIL, LeafCell;
1474 PHCELL_INDEX RootPointer = NULL;
1475 ULONG Type, i;
1476 BOOLEAN IsCompressed;
1477 PAGED_CODE();
1478
1479 /* Get the key node */
1480 KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, Child);
1481 if (!KeyNode)
1482 {
1483 /* Shouldn't happen */
1484 ASSERT(FALSE);
1485 return FALSE;
1486 }
1487
1488 /* Check if the name is compressed */
1489 if (KeyNode->Flags & KEY_COMP_NAME)
1490 {
1491 /* Remember for later */
1492 IsCompressed = TRUE;
1493
1494 /* Create the compressed name and allocate it */
1495 Name.Length = CmpCompressedNameSize(KeyNode->Name, KeyNode->NameLength);
1496 Name.MaximumLength = Name.Length;
1497 Name.Buffer = Hive->Allocate(Name.Length, TRUE, TAG_CM);
1498 if (!Name.Buffer)
1499 {
1500 /* Release the cell and fail */
1501 HvReleaseCell(Hive, Child);
1502 ASSERT(FALSE);
1503 return FALSE;
1504 }
1505
1506 /* Copy the compressed name */
1508 Name.MaximumLength,
1509 KeyNode->Name,
1510 KeyNode->NameLength);
1511 }
1512 else
1513 {
1514 /* Remember for later */
1515 IsCompressed = FALSE;
1516
1517 /* Build the unicode string */
1518 Name.Length = KeyNode->NameLength;
1519 Name.MaximumLength = KeyNode->NameLength;
1520 Name.Buffer = &KeyNode->Name[0];
1521 }
1522
1523 /* Release the cell */
1524 HvReleaseCell(Hive, Child);
1525
1526 /* Get the parent node */
1527 KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, Parent);
1528 if (!KeyNode)
1529 {
1530 /* Not handled */
1531 ASSERT(FALSE);
1532 }
1533
1534 /* Find out the type of the cell, and check if this is the first subkey */
1536 if (!KeyNode->SubKeyCounts[Type])
1537 {
1538 /* Allocate a fast leaf */
1539 IndexCell = HvAllocateCell(Hive, sizeof(CM_KEY_FAST_INDEX), Type, HCELL_NIL);
1540 if (IndexCell == HCELL_NIL)
1541 {
1542 /* Not handled */
1543 ASSERT(FALSE);
1544 }
1545
1546 /* Get the leaf cell */
1547 Index = (PCM_KEY_INDEX)HvGetCell(Hive, IndexCell);
1548 if (!Index)
1549 {
1550 /* Shouldn't happen */
1551 ASSERT(FALSE);
1552 }
1553
1554 /* Now check what kind of hive we're dealing with */
1555 if (Hive->Version >= 5)
1556 {
1557 /* XP Hive: Use hash leaf */
1558 Index->Signature = CM_KEY_HASH_LEAF;
1559 }
1560 else if (Hive->Version >= 3)
1561 {
1562 /* Windows 2000 and ReactOS: Use fast leaf */
1563 Index->Signature = CM_KEY_FAST_LEAF;
1564 }
1565 else
1566 {
1567 /* NT 4: Use index leaf */
1568 Index->Signature = CM_KEY_INDEX_LEAF;
1569 }
1570
1571 /* Setup the index list */
1572 Index->Count = 0;
1573 KeyNode->SubKeyLists[Type] = IndexCell;
1574 }
1575 else
1576 {
1577 /* We already have an index, get it */
1578 Index = (PCM_KEY_INDEX)HvGetCell(Hive, KeyNode->SubKeyLists[Type]);
1579 if (!Index)
1580 {
1581 /* Not handled */
1582 ASSERT(FALSE);
1583 }
1584
1585 /* Remember to release the cell later */
1586 CellToRelease = KeyNode->SubKeyLists[Type];
1587
1588 /* Check if this is a fast leaf that's gotten too full */
1589 if ((Index->Signature == CM_KEY_FAST_LEAF) &&
1590 (Index->Count >= CmpMaxFastIndexPerHblock))
1591 {
1592 DPRINT("Doing Fast->Slow Leaf conversion\n");
1593
1594 /* Mark this cell as dirty */
1595 HvMarkCellDirty(Hive, CellToRelease, FALSE);
1596
1597 /* Convert */
1598 OldIndex = (PCM_KEY_FAST_INDEX)Index;
1599
1600 for (i = 0; i < OldIndex->Count; i++)
1601 {
1602 Index->List[i] = OldIndex->List[i].Cell;
1603 }
1604
1605 /* Set the new type value */
1606 Index->Signature = CM_KEY_INDEX_LEAF;
1607 }
1608 else if (((Index->Signature == CM_KEY_INDEX_LEAF) ||
1609 (Index->Signature == CM_KEY_HASH_LEAF)) &&
1610 (Index->Count >= CmpMaxIndexPerHblock))
1611 {
1612 /* This is an old/hashed leaf that's gotten too large, root it */
1613 IndexCell = HvAllocateCell(Hive,
1614 sizeof(CM_KEY_INDEX) +
1615 sizeof(HCELL_INDEX),
1616 Type,
1617 HCELL_NIL);
1618 if (IndexCell == HCELL_NIL)
1619 {
1620 /* Not handled */
1621 ASSERT(FALSE);
1622 }
1623
1624 /* Get the index cell */
1625 Index = (PCM_KEY_INDEX)HvGetCell(Hive, IndexCell);
1626 if (!Index)
1627 {
1628 /* Shouldn't happen */
1629 ASSERT(FALSE);
1630 }
1631
1632 /* Mark the index as a root, and set the index cell */
1633 Index->Signature = CM_KEY_INDEX_ROOT;
1634 Index->Count = 1;
1635 Index->List[0] = KeyNode->SubKeyLists[Type];
1636 KeyNode->SubKeyLists[Type] = IndexCell;
1637 }
1638 }
1639
1640 /* Now we can choose the leaf cell */
1641 LeafCell = KeyNode->SubKeyLists[Type];
1642
1643 /* Check if we turned the index into a root */
1644 if (Index->Signature == CM_KEY_INDEX_ROOT)
1645 {
1646 DPRINT("Leaf->Root Index Conversion\n");
1647
1648 /* Get the leaf where to add the new entry (the routine will do
1649 * the splitting if necessary)
1650 */
1651 LeafCell = CmpSelectLeaf(Hive, KeyNode, &Name, Type, &RootPointer);
1652 if (LeafCell == HCELL_NIL)
1653 {
1654 /* Not handled */
1655 ASSERT(FALSE);
1656 }
1657 }
1658
1659 /* Add our leaf cell */
1660 LeafCell = CmpAddToLeaf(Hive, LeafCell, Child, &Name);
1661 if (LeafCell == HCELL_NIL)
1662 {
1663 /* Not handled */
1664 ASSERT(FALSE);
1665 }
1666
1667 /* Update the key counts */
1668 KeyNode->SubKeyCounts[Type]++;
1669
1670 /* Check if caller wants us to return the leaf */
1671 if (RootPointer)
1672 {
1673 /* Return it */
1674 *RootPointer = LeafCell;
1675 }
1676 else
1677 {
1678 /* Otherwise, mark it as the list index for the cell */
1679 KeyNode->SubKeyLists[Type] = LeafCell;
1680 }
1681
1682 /* If the name was compressed, free our copy */
1683 if (IsCompressed) Hive->Free(Name.Buffer, 0);
1684
1685 /* Release all our cells */
1686 if (IndexCell != HCELL_NIL) HvReleaseCell(Hive, IndexCell);
1687 if (CellToRelease != HCELL_NIL) HvReleaseCell(Hive, CellToRelease);
1688 HvReleaseCell(Hive, Parent);
1689 return TRUE;
1690}
Type
Definition: Type.h:7
ACPI_PHYSICAL_ADDRESS ACPI_SIZE BOOLEAN Warn UINT32 *TableIdx UINT32 ACPI_TABLE_HEADER *OutTableHeader ACPI_TABLE_HEADER **OutTable ACPI_HANDLE UINT32 ACPI_WALK_CALLBACK ACPI_WALK_CALLBACK void void **ReturnValue UINT32 ACPI_BUFFER *RetPathPtr ACPI_OBJECT_HANDLER void *Data ACPI_OBJECT_HANDLER void **Data ACPI_STRING ACPI_OBJECT_LIST ACPI_BUFFER *ReturnObjectBuffer ACPI_DEVICE_INFO **ReturnBuffer ACPI_HANDLE Parent
Definition: acpixf.h:732
struct NameRec_ * Name
Definition: cdprocs.h:460
#define CM_KEY_INDEX_LEAF
Definition: cmdata.h:14
#define CM_KEY_INDEX_ROOT
Definition: cmdata.h:13
struct _CM_KEY_FAST_INDEX * PCM_KEY_FAST_INDEX
#define CM_KEY_FAST_LEAF
Definition: cmdata.h:15
struct _CM_KEY_INDEX * PCM_KEY_INDEX
#define CM_KEY_HASH_LEAF
Definition: cmdata.h:16
HCELL_INDEX NTAPI CmpSelectLeaf(IN PHHIVE Hive, IN PCM_KEY_NODE KeyNode, IN PCUNICODE_STRING Name, IN HSTORAGE_TYPE Type, IN PHCELL_INDEX *RootCell)
Definition: cmindex.c:1264
#define CmpMaxFastIndexPerHblock
Definition: cmindex.c:19
#define CmpMaxIndexPerHblock
Definition: cmindex.c:23
HCELL_INDEX NTAPI CmpAddToLeaf(IN PHHIVE Hive, IN HCELL_INDEX LeafCell, IN HCELL_INDEX NewKey, IN PCUNICODE_STRING Name)
Definition: cmindex.c:921
VOID NTAPI CmpCopyCompressedName(OUT PWCHAR Destination, IN ULONG DestinationLength, IN PWCHAR Source, IN ULONG SourceLength)
Definition: cmname.c:56
USHORT NTAPI CmpCompressedNameSize(IN PWCHAR Name, IN ULONG Length)
Definition: cmname.c:95
BOOLEAN CMAPI HvMarkCellDirty(PHHIVE RegistryHive, HCELL_INDEX CellOffset, BOOLEAN HoldingLock)
Definition: hivecell.c:109
#define TAG_CM
Definition: cmlib.h:212
#define NULL
Definition: types.h:112
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
Definition: glfuncs.h:248
ULONG * PHCELL_INDEX
Definition: hivedata.h:105
#define HvGetCellType(Cell)
Definition: hivedata.h:120
#define ASSERT(a)
Definition: mode.c:44
HCELL_INDEX Cell
Definition: cmdata.h:165
CM_INDEX List[ANYSIZE_ARRAY]
Definition: cmdata.h:190
uint32_t ULONG
Definition: typedefs.h:59
_In_ WDFCOLLECTION _In_ ULONG Index
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFDEVICE Child
Definition: wdffdo.h:536

Referenced by CmiAddSubKey(), CmpCreateLinkNode(), CmpDeepCopyKeyInternal(), and CmpDoCreate().

◆ CmpAddValueToList()

NTSTATUS NTAPI CmpAddValueToList ( IN PHHIVE  Hive,
IN HCELL_INDEX  ValueCell,
IN ULONG  Index,
IN HSTORAGE_TYPE  StorageType,
IN OUT PCHILD_LIST  ChildList 
)

Definition at line 207 of file cmvalue.c.

212{
213 HCELL_INDEX ListCell;
214 ULONG ChildCount, Length, i;
215 PCELL_DATA CellData;
216 PAGED_CODE();
217
218 /* Sanity check */
219 ASSERT((((LONG)Index) >= 0) && (Index <= ChildList->Count));
220
221 /* Get the number of entries in the child list */
222 ChildCount = ChildList->Count;
223 ChildCount++;
224 if (ChildCount > 1)
225 {
226 ASSERT(ChildList->List != HCELL_NIL);
227
228 /* The cell should be dirty at this point */
229 ASSERT(HvIsCellDirty(Hive, ChildList->List));
230
231 /* Check if we have less then 100 children */
232 if (ChildCount < 100)
233 {
234 /* Allocate just enough as requested */
235 Length = ChildCount * sizeof(HCELL_INDEX);
236 }
237 else
238 {
239 /* Otherwise, we have quite a few, so allocate a batch */
240 Length = ROUND_UP(ChildCount, 100) * sizeof(HCELL_INDEX);
241 if (Length > HBLOCK_SIZE)
242 {
243 /* But make sure we don't allocate beyond our block size */
245 }
246 }
247
248 /* Perform the allocation */
249 ListCell = HvReallocateCell(Hive, ChildList->List, Length);
250 }
251 else
252 {
253 /* This is our first child, so allocate a single cell */
254 ASSERT(ChildList->List == HCELL_NIL);
255 ListCell = HvAllocateCell(Hive, sizeof(HCELL_INDEX), StorageType, HCELL_NIL);
256 }
257
258 /* Fail if we couldn't get a cell */
259 if (ListCell == HCELL_NIL) return STATUS_INSUFFICIENT_RESOURCES;
260
261 /* Set this cell as the child list's list cell */
262 ChildList->List = ListCell;
263
264 /* Get the actual key list memory */
265 CellData = HvGetCell(Hive, ListCell);
266 ASSERT(CellData != NULL);
267
268 /* Loop all the children */
269 for (i = ChildCount - 1; i > Index; i--)
270 {
271 /* Move them all down */
272 CellData->u.KeyList[i] = CellData->u.KeyList[i - 1];
273 }
274
275 /* Insert us on top now */
276 CellData->u.KeyList[Index] = ValueCell;
277 ChildList->Count = ChildCount;
278
279 /* Release the list cell and make sure the value cell is dirty */
280 HvReleaseCell(Hive, ListCell);
281 ASSERT(HvIsCellDirty(Hive, ValueCell));
282
283 /* We're done here */
284 return STATUS_SUCCESS;
285}
BOOLEAN CMAPI HvIsCellDirty(IN PHHIVE Hive, IN HCELL_INDEX Cell)
Definition: hivecell.c:153
HCELL_INDEX CMAPI HvReallocateCell(PHHIVE RegistryHive, HCELL_INDEX CellOffset, ULONG Size)
Definition: hivecell.c:421
#define ROUND_UP(n, align)
Definition: eventvwr.h:34
#define HBLOCK_SIZE
Definition: hivedata.h:42
int Count
Definition: noreturn.cpp:7
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
long LONG
Definition: pedump.c:60
#define STATUS_SUCCESS
Definition: shellext.h:65
HCELL_INDEX KeyList[ANYSIZE_ARRAY]
Definition: cmdata.h:205
union _CELL_DATA::@4303 u
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_CHILD_LIST_CONFIG _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFCHILDLIST * ChildList
Definition: wdfchildlist.h:481

Referenced by CmiAddValueKey(), CmpCopyKeyValueList(), and CmpSetValueKeyNew().

◆ CmpAllocate()

PVOID NTAPI CmpAllocate ( IN SIZE_T  Size,
IN BOOLEAN  Paged,
IN ULONG  Tag 
)

Definition at line 49 of file registry.c.

53{
55 return FrLdrHeapAlloc(Size, Tag);
56}
FORCEINLINE PVOID FrLdrHeapAlloc(SIZE_T MemorySize, ULONG Tag)
Definition: mm.h:174
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
_Must_inspect_result_ _In_ WDFDEVICE _In_ BOOLEAN _In_opt_ PVOID Tag
Definition: wdfdevice.h:4065
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533

Referenced by CmiInitializeHive(), and RegInitializeHive().

◆ CmpCompareCompressedName()

LONG NTAPI CmpCompareCompressedName ( IN PCUNICODE_STRING  SearchName,
IN PWCHAR  CompressedName,
IN ULONG  NameLength 
)

Definition at line 109 of file cmname.c.

112{
113 WCHAR* p;
114 UCHAR* pp;
115 WCHAR chr1, chr2;
116 USHORT SearchLength;
117 LONG Result;
118
119 /* Set the pointers and length and then loop */
120 p = SearchName->Buffer;
121 pp = (PUCHAR)CompressedName;
122 SearchLength = (SearchName->Length / sizeof(WCHAR));
123 while (SearchLength > 0 && NameLength > 0)
124 {
125 /* Get the characters */
126 chr1 = *p++;
127 chr2 = (WCHAR)(*pp++);
128
129 /* Check if we have a direct match */
130 if (chr1 != chr2)
131 {
132 /* See if they match and return result if they don't */
135 if (Result) return Result;
136 }
137
138 /* Next chars */
139 SearchLength--;
140 NameLength--;
141 }
142
143 /* Return the difference directly */
144 return SearchLength - NameLength;
145}
GLfloat GLfloat p
Definition: glext.h:8902
WCHAR NTAPI RtlUpcaseUnicodeChar(_In_ WCHAR Source)
Definition: nlsboot.c:176
unsigned short USHORT
Definition: pedump.c:61
unsigned char * PUCHAR
Definition: typedefs.h:53
_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
Definition: wsk.h:409
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180

Referenced by CmpCompareSubkeys(), CmpDoCompareKeyName(), CmpFindNameInList(), CmpFindValueByNameFromCache(), CmpGetNameControlBlock(), and CmpValidateLexicalOrder().

◆ CmpCompressedNameSize()

USHORT NTAPI CmpCompressedNameSize ( IN PWCHAR  Name,
IN ULONG  Length 
)

Definition at line 95 of file cmname.c.

97{
98 /*
99 * Don't remove this: compressed names are "opaque" and just because
100 * the current implementation turns them into ansi-names doesn't mean
101 * that it will remain that way forever, so -never- assume this code
102 * below internally!
103 */
104 return (USHORT)Length * sizeof(WCHAR);
105}

Referenced by BiEnumerateSubKeys(), CmpAddDriverToList(), CmpAddSubKey(), CmpConstructName(), CmpGetHiveName(), CmpIsSafe(), CmpMarkIndexDirty(), CmpQueryKeyData(), CmpQueryKeyDataFromCache(), CmpQueryKeyValueData(), CmpQueryNameInformation(), and CmpRemoveSubKey().

◆ CmpComputeHashKey()

ULONG NTAPI CmpComputeHashKey ( IN ULONG  Hash,
IN PCUNICODE_STRING  Name,
IN BOOLEAN  AllowSeparators 
)

Definition at line 460 of file cmindex.c.

463{
464 LPWSTR Cp;
465 ULONG Value, i;
466
467 /* Make some sanity checks on our parameters */
468 ASSERT((Name->Length == 0) ||
469 (AllowSeparators) ||
470 (Name->Buffer[0] != OBJ_NAME_PATH_SEPARATOR));
471
472 /* If the name is empty, there is nothing to hash! */
473 if (!Name->Length) return Hash;
474
475 /* Set the buffer and loop every character */
476 Cp = Name->Buffer;
477 for (i = 0; i < Name->Length; i += sizeof(WCHAR), Cp++)
478 {
479 /* Make sure we don't have a separator when we shouldn't */
480 ASSERT(AllowSeparators || (*Cp != OBJ_NAME_PATH_SEPARATOR));
481
482 /* Check what kind of char we have */
483 if (*Cp >= L'a')
484 {
485 /* In the lower case region... is it truly lower case? */
486 if (*Cp < L'z')
487 {
488 /* Yes! Calculate it ourselves! */
489 Value = *Cp - L'a' + L'A';
490 }
491 else
492 {
493 /* No, use the API */
495 }
496 }
497 else
498 {
499 /* Reuse the char, it's already upcased */
500 Value = *Cp;
501 }
502
503 /* Multiply by a prime and add our value */
504 Hash *= 37;
505 Hash += Value;
506 }
507
508 /* Return the hash */
509 return Hash;
510}
#define OBJ_NAME_PATH_SEPARATOR
Definition: arcname_tests.c:25
static int Hash(const char *)
Definition: reader.c:2257
#define L(x)
Definition: ntvdm.h:50
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
WCHAR * LPWSTR
Definition: xmlstorage.h:184

Referenced by CmpAddToLeaf(), and CmpFindSubKeyByHash().

◆ CmpCopyCompressedName()

VOID NTAPI CmpCopyCompressedName ( OUT PWCHAR  Destination,
IN ULONG  DestinationLength,
IN PWCHAR  Source,
IN ULONG  SourceLength 
)

Definition at line 56 of file cmname.c.

60{
61 ULONG i, Length;
62
63 /* Get the actual length to copy */
64 Length = min(DestinationLength / sizeof(WCHAR), SourceLength);
65 for (i = 0; i < Length; i++)
66 {
67 /* Copy each character */
69 }
70}
#define min(a, b)
Definition: monoChain.cc:55
_In_ UINT _In_ UINT _In_ PNDIS_PACKET Source
Definition: ndis.h:3169
_In_ PUNICODE_STRING _Inout_ PUNICODE_STRING Destination
Definition: rtlfuncs.h:3004

Referenced by BiEnumerateSubKeys(), CmpAddDriverToList(), CmpAddSubKey(), CmpGetHiveName(), CmpIsSafe(), CmpMarkIndexDirty(), CmpQueryKeyData(), CmpQueryKeyValueData(), CmpQueryNameInformation(), and CmpRemoveSubKey().

◆ CmpCopyKeyValueList()

NTSTATUS NTAPI CmpCopyKeyValueList ( IN PHHIVE  SourceHive,
IN PCHILD_LIST  SrcValueList,
IN PHHIVE  DestinationHive,
IN OUT PCHILD_LIST  DestValueList,
IN HSTORAGE_TYPE  StorageType 
)

Definition at line 521 of file cmvalue.c.

526{
528 PCELL_DATA SrcListData = NULL, DestListData = NULL;
529 HCELL_INDEX NewValue;
530 ULONG Index;
531
532 PAGED_CODE();
533
534 /* Reset the destination value list */
535 DestValueList->Count = 0;
536 DestValueList->List = HCELL_NIL;
537
538 /* Check if the list is empty */
539 if (!SrcValueList->Count)
540 return STATUS_SUCCESS;
541
542 /* Get the source value list */
543 SrcListData = HvGetCell(SourceHive, SrcValueList->List);
544 ASSERT(SrcListData);
545
546 /* Copy the actual values */
547 for (Index = 0; Index < SrcValueList->Count; Index++)
548 {
549 NewValue = CmpCopyValue(SourceHive,
550 SrcListData->u.KeyList[Index],
551 DestinationHive,
552 StorageType);
553 if (NewValue == HCELL_NIL)
554 {
555 /* Not enough storage space, stop there and cleanup afterwards */
557 break;
558 }
559
560 /* Add this value cell to the child list */
561 Status = CmpAddValueToList(DestinationHive,
562 NewValue,
563 Index,
564 StorageType,
565 DestValueList);
566 if (!NT_SUCCESS(Status))
567 {
568 /* Not enough storage space, stop there */
569
570 /* Cleanup the newly-created value here, the other ones will be cleaned up afterwards */
571 if (!CmpFreeValue(DestinationHive, NewValue))
572 HvFreeCell(DestinationHive, NewValue);
573 break;
574 }
575 }
576
577 /* Revert-cleanup if failure */
578 if (!NT_SUCCESS(Status) && (DestValueList->List != HCELL_NIL))
579 {
580 /* Do not use CmpRemoveValueFromList but directly delete the data */
581
582 /* Get the destination value list */
583 DestListData = HvGetCell(DestinationHive, DestValueList->List);
584 ASSERT(DestListData);
585
586 /* Delete each copied value */
587 while (Index--)
588 {
589 NewValue = DestListData->u.KeyList[Index];
590 if (!CmpFreeValue(DestinationHive, NewValue))
591 HvFreeCell(DestinationHive, NewValue);
592 }
593
594 /* Release and free the list */
595 HvReleaseCell(DestinationHive, DestValueList->List);
596 HvFreeCell(DestinationHive, DestValueList->List);
597
598 DestValueList->Count = 0;
599 DestValueList->List = HCELL_NIL;
600 }
601
602 /* Release the cells */
603 HvReleaseCell(SourceHive, SrcValueList->List);
604
605 return Status;
606}
LONG NTSTATUS
Definition: precomp.h:26
BOOLEAN NTAPI CmpFreeValue(IN PHHIVE Hive, IN HCELL_INDEX Cell)
Definition: cmvalue.c:73
HCELL_INDEX NTAPI CmpCopyValue(IN PHHIVE SourceHive, IN HCELL_INDEX SourceValueCell, IN PHHIVE DestinationHive, IN HSTORAGE_TYPE StorageType)
Definition: cmvalue.c:417
NTSTATUS NTAPI CmpAddValueToList(IN PHHIVE Hive, IN HCELL_INDEX ValueCell, IN ULONG Index, IN HSTORAGE_TYPE StorageType, IN OUT PCHILD_LIST ChildList)
Definition: cmvalue.c:207
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
Status
Definition: gdiplustypes.h:25

Referenced by CmpDeepCopyKeyInternal().

◆ CmpCopyName()

USHORT NTAPI CmpCopyName ( IN PHHIVE  Hive,
OUT PWCHAR  Destination,
IN PCUNICODE_STRING  Source 
)

Definition at line 21 of file cmname.c.

24{
25 ULONG i;
26
27 /* Check for old hives */
28 if (Hive->Version == 1)
29 {
30 /* Just copy the source directly */
31 RtlCopyMemory(Destination, Source->Buffer, Source->Length);
32 return Source->Length;
33 }
34
35 /* For new versions, check for compressed name */
36 for (i = 0; i < (Source->Length / sizeof(WCHAR)); i++)
37 {
38 /* Check if the name is non compressed */
39 if (Source->Buffer[i] > (UCHAR)-1)
40 {
41 /* Do the copy */
42 RtlCopyMemory(Destination, Source->Buffer, Source->Length);
43 return Source->Length;
44 }
45
46 /* Copy this character */
47 ((PCHAR)Destination)[i] = (CHAR)(Source->Buffer[i]);
48 }
49
50 /* Compressed name, return length */
51 return Source->Length / sizeof(WCHAR);
52}
#define CHAR(Char)
#define PCHAR
Definition: match.c:90
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263

Referenced by CmCreateRootNode(), CmiAddValueKey(), CmiCreateSubKey(), CmpCreateLinkNode(), CmpCreateRootNode(), CmpDoCreateChild(), and CmpSetValueKeyNew().

◆ CmpFindNameInList()

BOOLEAN NTAPI CmpFindNameInList ( IN PHHIVE  Hive,
IN PCHILD_LIST  ChildList,
IN PCUNICODE_STRING  Name,
OUT PULONG ChildIndex  OPTIONAL,
OUT PHCELL_INDEX  CellIndex 
)

Definition at line 149 of file cmname.c.

154{
155 PCELL_DATA CellData;
156 HCELL_INDEX CellToRelease = HCELL_NIL;
157 ULONG i;
158 PCM_KEY_VALUE KeyValue;
159 LONG Result;
160 UNICODE_STRING SearchName;
162
163 /* Make sure there's actually something on the list */
164 if (ChildList->Count != 0)
165 {
166 /* Get the cell data */
167 CellData = (PCELL_DATA)HvGetCell(Hive, ChildList->List);
168 if (!CellData)
169 {
170 /* Couldn't get the cell... tell the caller */
171 *CellIndex = HCELL_NIL;
172 return FALSE;
173 }
174
175 /* Now loop every entry */
176 for (i = 0; i < ChildList->Count; i++)
177 {
178 /* Check if we have a cell to release */
179 if (CellToRelease != HCELL_NIL)
180 {
181 /* Release it */
182 HvReleaseCell(Hive, CellToRelease);
183 CellToRelease = HCELL_NIL;
184 }
185
186 /* Get this value */
187 KeyValue = (PCM_KEY_VALUE)HvGetCell(Hive, CellData->u.KeyList[i]);
188 if (!KeyValue)
189 {
190 /* Return with no data found */
191 *CellIndex = HCELL_NIL;
192 Success = FALSE;
193 goto Return;
194 }
195
196 /* Save the cell to release */
197 CellToRelease = CellData->u.KeyList[i];
198
199 /* Check if it's a compressed value name */
200 if (KeyValue->Flags & VALUE_COMP_NAME)
201 {
202 /* Compare compressed names */
204 KeyValue->Name,
205 KeyValue->NameLength);
206 }
207 else
208 {
209 /* Compare the Unicode name directly */
210 SearchName.Length = KeyValue->NameLength;
211 SearchName.MaximumLength = SearchName.Length;
212 SearchName.Buffer = KeyValue->Name;
213 Result = RtlCompareUnicodeString(Name, &SearchName, TRUE);
214 }
215
216 /* Check if we found it */
217 if (!Result)
218 {
219 /* We did... return info to caller */
220 if (ChildIndex) *ChildIndex = i;
221 *CellIndex = CellData->u.KeyList[i];
222
223 /* Set success state */
224 Success = TRUE;
225 goto Return;
226 }
227 }
228
229 /* Got to the end of the list */
230 if (ChildIndex) *ChildIndex = i;
231 *CellIndex = HCELL_NIL;
232
233 /* Nothing found if we got here */
234 Success = TRUE;
235 goto Return;
236 }
237
238 /* Nothing found... check if the caller wanted more info */
239 ASSERT(ChildList->Count == 0);
240 if (ChildIndex) *ChildIndex = 0;
241 *CellIndex = HCELL_NIL;
242
243 /* Nothing found if we got here */
244 return TRUE;
245
246Return:
247 /* Release the first cell we got */
248 if (CellData) HvReleaseCell(Hive, ChildList->List);
249
250 /* Release the secondary one, if we have one */
251 if (CellToRelease) HvReleaseCell(Hive, CellToRelease);
252 return Success;
253}
struct _CELL_DATA * PCELL_DATA
struct _CM_KEY_VALUE * PCM_KEY_VALUE
#define VALUE_COMP_NAME
Definition: cmdata.h:44
LONG NTAPI CmpCompareCompressedName(IN PCUNICODE_STRING SearchName, IN PWCHAR CompressedName, IN ULONG NameLength)
Definition: cmname.c:109
ULONG RtlCompareUnicodeString(PUNICODE_STRING s1, PUNICODE_STRING s2, BOOLEAN UpCase)
Definition: string_lib.cpp:31
@ Success
Definition: eventcreate.c:712
WCHAR Name[ANYSIZE_ARRAY]
Definition: cmdata.h:131
USHORT NameLength
Definition: cmdata.h:125
USHORT Flags
Definition: cmdata.h:129
USHORT MaximumLength
Definition: env_spec_w32.h:370

Referenced by BiGetRegistryValue(), CmDeleteValueKey(), CmpFindValueByName(), CmSetValueKey(), RegDeleteValueW(), and RegSetValueExW().

◆ CmpFindSubKeyByName()

HCELL_INDEX NTAPI CmpFindSubKeyByName ( IN PHHIVE  Hive,
IN PCM_KEY_NODE  Parent,
IN PCUNICODE_STRING  SearchName 
)

Definition at line 683 of file cmindex.c.

686{
687 ULONG i;
688 PCM_KEY_INDEX IndexRoot;
689 HCELL_INDEX SubKey, CellToRelease;
690 ULONG Found;
691
692 /* Loop each storage type */
693 for (i = 0; i < Hive->StorageTypeCount; i++)
694 {
695 /* Make sure the parent node has subkeys */
696 if (Parent->SubKeyCounts[i])
697 {
698 /* Get the Index */
699 IndexRoot = (PCM_KEY_INDEX)HvGetCell(Hive, Parent->SubKeyLists[i]);
700 if (!IndexRoot) return HCELL_NIL;
701
702 /* Get the cell we'll need to release */
703 CellToRelease = Parent->SubKeyLists[i];
704
705 /* Check if this is another index root */
706 if (IndexRoot->Signature == CM_KEY_INDEX_ROOT)
707 {
708 /* Lookup the name in the root */
710 IndexRoot,
711 SearchName,
712 &SubKey);
713
714 /* Release the previous cell */
715 ASSERT(CellToRelease != HCELL_NIL);
716 HvReleaseCell(Hive, CellToRelease);
717
718 /* Make sure we found something valid */
719 if (Found & INVALID_INDEX) break;
720
721 /* Get the new Index Root and set the new cell to be released */
722 if (SubKey == HCELL_NIL) continue;
723 CellToRelease = SubKey;
724 IndexRoot = (PCM_KEY_INDEX)HvGetCell(Hive, SubKey);
725 }
726
727 /* Make sure the signature is what we expect it to be */
728 ASSERT((IndexRoot->Signature == CM_KEY_INDEX_LEAF) ||
729 (IndexRoot->Signature == CM_KEY_FAST_LEAF) ||
730 (IndexRoot->Signature == CM_KEY_HASH_LEAF));
731
732 /* Check if this isn't a hashed leaf */
733 if (IndexRoot->Signature != CM_KEY_HASH_LEAF)
734 {
735 /* Find the subkey in the leaf */
737 IndexRoot,
738 SearchName,
739 &SubKey);
740
741 /* Release the previous cell */
742 ASSERT(CellToRelease != HCELL_NIL);
743 HvReleaseCell(Hive, CellToRelease);
744
745 /* Make sure we found a valid index */
746 if (Found & INVALID_INDEX) break;
747 }
748 else
749 {
750 /* Find the subkey in the hash */
751 SubKey = CmpFindSubKeyByHash(Hive,
752 (PCM_KEY_FAST_INDEX)IndexRoot,
753 SearchName);
754
755 /* Release the previous cell */
756 ASSERT(CellToRelease != HCELL_NIL);
757 HvReleaseCell(Hive, CellToRelease);
758 }
759
760 /* Make sure we got a valid subkey and return it */
761 if (SubKey != HCELL_NIL) return SubKey;
762 }
763 }
764
765 /* If we got here, then we failed */
766 return HCELL_NIL;
767}
return Found
Definition: dirsup.c:1270
ULONG NTAPI CmpFindSubKeyInRoot(IN PHHIVE Hive, IN PCM_KEY_INDEX Index, IN PCUNICODE_STRING SearchName, IN PHCELL_INDEX SubKey)
Definition: cmindex.c:143
static HCELL_INDEX NTAPI CmpFindSubKeyByHash(IN PHHIVE Hive, IN PCM_KEY_FAST_INDEX FastIndex, IN PCUNICODE_STRING SearchName)
Definition: cmindex.c:646
ULONG NTAPI CmpFindSubKeyInLeaf(IN PHHIVE Hive, IN PCM_KEY_INDEX Index, IN PCUNICODE_STRING SearchName, IN PHCELL_INDEX SubKey)
Definition: cmindex.c:358
#define INVALID_INDEX
Definition: cmindex.c:17
USHORT Signature
Definition: cmdata.h:178

Referenced by BiLoadHive(), BiOpenKey(), CmGetSystemControlValues(), CmpDoCreate(), CmpFindControlSet(), CmpFindDrivers(), CmpIsSafe(), CmpParseKey(), CmpSortDriverList(), CmpWalkPath(), RegOpenKey(), and RegpCreateOrOpenKey().

◆ CmpFindSubKeyByNumber()

HCELL_INDEX NTAPI CmpFindSubKeyByNumber ( IN PHHIVE  Hive,
IN PCM_KEY_NODE  Node,
IN ULONG  Number 
)

Definition at line 600 of file cmindex.c.

603{
606
607 /* Check if it's in the stable list */
608 if (Number < Node->SubKeyCounts[Stable])
609 {
610 /* Get the actual key index */
611 Index = (PCM_KEY_INDEX)HvGetCell(Hive, Node->SubKeyLists[Stable]);
612 if (!Index) return HCELL_NIL;
613
614 /* Do a search inside it */
616
617 /* Release the cell and return the result */
618 HvReleaseCell(Hive, Node->SubKeyLists[Stable]);
619 return Result;
620 }
621 else if (Hive->StorageTypeCount > Volatile)
622 {
623 /* It's in the volatile list */
624 Number = Number - Node->SubKeyCounts[Stable];
625 if (Number < Node->SubKeyCounts[Volatile])
626 {
627 /* Get the actual key index */
628 Index = (PCM_KEY_INDEX)HvGetCell(Hive, Node->SubKeyLists[Volatile]);
629 if (!Index) return HCELL_NIL;
630
631 /* Do a search inside it */
633
634 /* Release the cell and return the result */
635 HvReleaseCell(Hive, Node->SubKeyLists[Volatile]);
636 return Result;
637 }
638 }
639
640 /* Nothing was found */
641 return HCELL_NIL;
642}
HCELL_INDEX NTAPI CmpDoFindSubKeyByNumber(IN PHHIVE Hive, IN PCM_KEY_INDEX Index, IN ULONG Number)
Definition: cmindex.c:514
_In_opt_ PENTER_STATE_SYSTEM_HANDLER _In_opt_ PVOID _In_ LONG _In_opt_ LONG volatile * Number
Definition: ntpoapi.h:207
Definition: dlist.c:348

Referenced by BiEnumerateSubKeys(), CmEnumerateKey(), CmpDeepCopyKeyInternal(), CmpFindDrivers(), and CmpValidateRegistryInternal().

◆ CmpFindValueByName()

HCELL_INDEX NTAPI CmpFindValueByName ( IN PHHIVE  Hive,
IN PCM_KEY_NODE  KeyNode,
IN PCUNICODE_STRING  Name 
)

Definition at line 99 of file cmvalue.c.

102{
103 HCELL_INDEX CellIndex;
104
105 /* Call the main function */
106 if (!CmpFindNameInList(Hive,
107 &KeyNode->ValueList,
108 Name,
109 NULL,
110 &CellIndex))
111 {
112 /* Sanity check */
113 ASSERT(CellIndex == HCELL_NIL);
114 }
115
116 /* Return the index */
117 return CellIndex;
118}
BOOLEAN NTAPI CmpFindNameInList(IN PHHIVE Hive, IN PCHILD_LIST ChildList, IN PCUNICODE_STRING Name, OUT PULONG ChildIndex OPTIONAL, OUT PHCELL_INDEX CellIndex)
Definition: cmname.c:149

Referenced by CmGetSystemControlValues(), CmpAddDriverToList(), CmpFindControlSet(), CmpFindTagIndex(), CmpGetSymbolicLink(), CmpIsLoadType(), CmpIsSafe(), CmpSortDriverList(), RegQueryValue(), and RegQueryValueExW().

◆ CmpFree()

VOID NTAPI CmpFree ( IN PVOID  Ptr,
IN ULONG  Quota 
)

Definition at line 60 of file registry.c.

63{
66}
FORCEINLINE VOID FrLdrHeapFree(PVOID MemoryPointer, ULONG Tag)
Definition: mm.h:181
_Must_inspect_result_ _In_ PFSRTL_PER_STREAM_CONTEXT Ptr
Definition: fsrtlfuncs.h:898

Referenced by CmiInitializeHive(), and RegInitializeHive().

◆ CmpFreeKeyByCell()

NTSTATUS NTAPI CmpFreeKeyByCell ( IN PHHIVE  Hive,
IN HCELL_INDEX  Cell,
IN BOOLEAN  Unlink 
)

Definition at line 159 of file cmkeydel.c.

162{
163 PCM_KEY_NODE CellData, ParentData;
164 PCELL_DATA ListData;
165 ULONG i;
167
168 /* Mark the entire key dirty */
169 CmpMarkKeyDirty(Hive, Cell, TRUE);
170
171 /* Get the target node and release it */
172 CellData = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
173 ASSERT(CellData);
174 HvReleaseCell(Hive, Cell);
175
176 /* Make sure we don't have subkeys */
177 ASSERT(CellData->SubKeyCounts[Stable] + CellData->SubKeyCounts[Volatile] == 0);
178
179 /* Check if we have to unlink */
180 if (Unlink)
181 {
182 /* Remove the subkey */
183 Result = CmpRemoveSubKey(Hive, CellData->Parent, Cell);
185
186 /* Get the parent node and release it */
187 ParentData = (PCM_KEY_NODE)HvGetCell(Hive, CellData->Parent);
188 ASSERT(ParentData);
189 HvReleaseCell(Hive, CellData->Parent);
190
191 /* Check if the parent node has no more subkeys */
192 if (ParentData->SubKeyCounts[Stable] + ParentData->SubKeyCounts[Volatile] == 0)
193 {
194 /* Then free the cached name/class lengths */
195 ParentData->MaxNameLen = 0;
196 ParentData->MaxClassLen = 0;
197 }
198 }
199
200 // TODO: Handle predefined keys (Flags: KEY_PREDEF_HANDLE)
201 /* If this is an exit node, we don't have values */
202 if (!(CellData->Flags & KEY_HIVE_EXIT))
203 {
204 /* Check if we have any values */
205 if (CellData->ValueList.Count > 0)
206 {
207 /* Get the value list and release it */
208 ListData = HvGetCell(Hive, CellData->ValueList.List);
209 ASSERT(ListData);
210 HvReleaseCell(Hive, CellData->ValueList.List);
211
212 /* Loop every value */
213 for (i = 0; i < CellData->ValueList.Count; i++)
214 {
215 /* Free it */
216 Result = CmpFreeValue(Hive, ListData->u.KeyList[i]);
217 ASSERT(Result);
218 }
219
220 /* Free the value list */
221 HvFreeCell(Hive, CellData->ValueList.List);
222 }
223
224 /* Free the key security descriptor */
225 CmpFreeSecurityDescriptor(Hive, Cell);
226 }
227
228 /* Free the key body itself, and then return our status */
229 if (!CmpFreeKeyBody(Hive, Cell)) return STATUS_INSUFFICIENT_RESOURCES;
230 return STATUS_SUCCESS;
231}
#define KEY_HIVE_EXIT
Definition: cmdata.h:31
BOOLEAN NTAPI CmpRemoveSubKey(IN PHHIVE Hive, IN HCELL_INDEX ParentKey, IN HCELL_INDEX TargetKey)
Definition: cmindex.c:1694
BOOLEAN NTAPI CmpFreeKeyBody(IN PHHIVE Hive, IN HCELL_INDEX Cell)
Definition: cmkeydel.c:124
BOOLEAN NTAPI CmpMarkKeyDirty(IN PHHIVE Hive, IN HCELL_INDEX Cell, IN BOOLEAN CheckNoSubkeys)
Definition: cmkeydel.c:19
BOOLEAN NTAPI CmpFreeValue(IN PHHIVE Hive, IN HCELL_INDEX Cell)
Definition: cmvalue.c:73
VOID NTAPI CmpFreeSecurityDescriptor(IN PHHIVE Hive, IN HCELL_INDEX Cell)
Definition: cmse.c:65
static int Unlink(const char **args)
Definition: vfdcmd.c:2549

Referenced by BiDeleteKey(), CmDeleteKey(), CmpDoCreate(), CmpUnlinkHiveFromMaster(), and RegDeleteKeyW().

◆ CmpFreeSecurityDescriptor()

VOID NTAPI CmpFreeSecurityDescriptor ( IN PHHIVE  Hive,
IN HCELL_INDEX  Cell 
)

Definition at line 65 of file cmse.c.

67{
68 PCM_KEY_NODE CellData;
69 PCM_KEY_SECURITY SecurityData;
70
71 PAGED_CODE();
72
73 // ASSERT( (((PCMHIVE)Hive)->HiveSecurityLockOwner == KeGetCurrentThread()) || (CmpTestRegistryLockExclusive() == TRUE) );
74
75 CellData = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
76 if (!CellData) return;
77
79
80 // FIXME: ReactOS-specific: check whether this key has a security block.
81 // On Windows there is no such check, all keys seem to have a valid
82 // security block.
83 // If we remove this check on ReactOS (and continue running) then we get
84 // a BSOD at the end...
85 if (CellData->Security == HCELL_NIL)
86 {
87 DPRINT("Cell 0x%08x (data 0x%p) has no security block!\n", Cell, CellData);
88 HvReleaseCell(Hive, Cell);
89 return;
90 }
91
92 SecurityData = (PCM_KEY_SECURITY)HvGetCell(Hive, CellData->Security);
93 if (!SecurityData)
94 {
95 HvReleaseCell(Hive, Cell);
96 return;
97 }
98
100
101 if (SecurityData->ReferenceCount > 1)
102 {
103 SecurityData->ReferenceCount--;
104 }
105 else // if (SecurityData->ReferenceCount <= 1)
106 {
107 CmpRemoveSecurityCellList(Hive, CellData->Security);
108 HvFreeCell(Hive, CellData->Security);
109 }
110
111 CellData->Security = HCELL_NIL;
112 HvReleaseCell(Hive, CellData->Security);
113 HvReleaseCell(Hive, Cell);
114}
#define CM_KEY_SECURITY_SIGNATURE
Definition: cmdata.h:23
struct _CM_KEY_SECURITY * PCM_KEY_SECURITY
VOID NTAPI CmpRemoveSecurityCellList(IN PHHIVE Hive, IN HCELL_INDEX SecurityCell)
Definition: cmse.c:19
ULONG ReferenceCount
Definition: cmdata.h:143
USHORT Signature
Definition: cmdata.h:139

Referenced by CmpFreeKeyByCell().

◆ CmpFreeValue()

BOOLEAN NTAPI CmpFreeValue ( IN PHHIVE  Hive,
IN HCELL_INDEX  Cell 
)

Definition at line 73 of file cmvalue.c.

75{
77 PAGED_CODE();
78
79 /* Get the cell data */
80 Value = (PCM_KEY_VALUE)HvGetCell(Hive, Cell);
81 if (!Value) ASSERT(FALSE);
82
83 /* Free it */
84 if (!CmpFreeValueData(Hive, Value->Data, Value->DataLength))
85 {
86 /* We failed to free the data, return failure */
87 HvReleaseCell(Hive, Cell);
88 return FALSE;
89 }
90
91 /* Release the cell and free it */
92 HvReleaseCell(Hive, Cell);
93 HvFreeCell(Hive, Cell);
94 return TRUE;
95}
BOOLEAN NTAPI CmpFreeValueData(IN PHHIVE Hive, IN HCELL_INDEX DataCell, IN ULONG DataLength)
Definition: cmvalue.c:44

Referenced by CmDeleteValueKey(), CmiAddValueKey(), CmpCopyKeyValueList(), CmpFreeKeyByCell(), CmpSetValueKeyNew(), and RegDeleteValueW().

◆ CmpFreeValueData()

BOOLEAN NTAPI CmpFreeValueData ( IN PHHIVE  Hive,
IN HCELL_INDEX  DataCell,
IN ULONG  DataLength 
)

Definition at line 44 of file cmvalue.c.

47{
48 ULONG KeySize;
49 PAGED_CODE();
50
51 /* If this is a small key, the data is built-in */
52 if (!CmpIsKeyValueSmall(&KeySize, DataLength))
53 {
54 /* If there's no data cell, there's nothing to do */
55 if (DataCell == HCELL_NIL) return TRUE;
56
57 /* Make sure the data cell is allocated */
58 //ASSERT(HvIsCellAllocated(Hive, DataCell));
59
60 /* Unsupported value type */
61 ASSERT_VALUE_BIG(Hive, KeySize);
62
63 /* Normal value, just free the data cell */
64 HvFreeCell(Hive, DataCell);
65 }
66
67 /* Operation complete */
68 return TRUE;
69}
_In_ ULONG _In_opt_ WDFREQUEST _In_opt_ PVOID _In_ size_t _In_ PVOID _In_ size_t _Out_ size_t * DataLength
Definition: cdrom.h:1444
#define ASSERT_VALUE_BIG(h, s)
Definition: cmlib.h:386
static BOOLEAN CmpIsKeyValueSmall(OUT PULONG RealLength, IN ULONG Length)
Definition: cmlib.h:395

Referenced by CmpFreeValue(), and CmpSetValueKeyExisting().

◆ CmpGetValueData()

BOOLEAN NTAPI CmpGetValueData ( IN PHHIVE  Hive,
IN PCM_KEY_VALUE  Value,
OUT PULONG  Length,
OUT PVOID Buffer,
OUT PBOOLEAN  BufferAllocated,
OUT PHCELL_INDEX  CellToRelease 
)

Definition at line 125 of file cmvalue.c.

131{
132 PAGED_CODE();
133
134 /* Sanity check */
135 ASSERT(Value->Signature == CM_KEY_VALUE_SIGNATURE);
136
137 /* Set failure defaults */
138 *BufferAllocated = FALSE;
139 *Buffer = NULL;
140 *CellToRelease = HCELL_NIL;
141
142 /* Check if this is a small key */
143 if (CmpIsKeyValueSmall(Length, Value->DataLength))
144 {
145 /* Return the data immediately */
146 *Buffer = &Value->Data;
147 return TRUE;
148 }
149
150 /* Unsupported at the moment */
151 ASSERT_VALUE_BIG(Hive, *Length);
152
153 /* Get the data from the cell */
154 *Buffer = HvGetCell(Hive, Value->Data);
155 if (!(*Buffer)) return FALSE;
156
157 /* Return success and the cell to be released */
158 *CellToRelease = Value->Data;
159 return TRUE;
160}
Definition: bufpool.h:45
#define CM_KEY_VALUE_SIGNATURE
Definition: cmdata.h:24

Referenced by CmpFindTagIndex(), CmpGetSymbolicLink(), CmpGetValueDataFromCache(), and CmpValueToData().

◆ CmpIsKeyValueBig()

static BOOLEAN CmpIsKeyValueBig ( IN PHHIVE  Hive,
IN ULONG  Length 
)
inlinestatic

Definition at line 416 of file cmlib.h.

418{
419 /* Check if the hive is XP Beta 1 or newer */
420 if (Hive->Version >= HSYS_WHISTLER_BETA1)
421 {
422 /* Check if the key length is valid for a big value key */
424 {
425 /* Yes, this value is big */
426 return TRUE;
427 }
428 }
429
430 /* Not a big value key */
431 return FALSE;
432}
#define CM_KEY_VALUE_BIG
Definition: cmdata.h:50
#define CM_KEY_VALUE_SPECIAL_SIZE
Definition: cmdata.h:51
#define HSYS_WHISTLER_BETA1
Definition: hivedata.h:71

◆ CmpIsKeyValueSmall()

static BOOLEAN CmpIsKeyValueSmall ( OUT PULONG  RealLength,
IN ULONG  Length 
)
inlinestatic

Definition at line 395 of file cmlib.h.

397{
398 /* Check if the length has the special size value */
400 {
401 /* It does, so this is a small key: return the real length */
402 *RealLength = Length - CM_KEY_VALUE_SPECIAL_SIZE;
403 return TRUE;
404 }
405
406 /* This is not a small key, return the length we read */
407 *RealLength = Length;
408 return FALSE;
409}

Referenced by CmGetSystemControlValues(), CmpCopyValue(), CmpFreeValueData(), CmpGetValueData(), CmpMarkValueDataDirty(), CmpQueryKeyValueData(), CmpSetValueKeyExisting(), and CmpValidateValueListByCount().

◆ CmpMarkIndexDirty()

BOOLEAN NTAPI CmpMarkIndexDirty ( IN PHHIVE  Hive,
HCELL_INDEX  ParentKey,
HCELL_INDEX  TargetKey 
)

◆ CmpMarkValueDataDirty()

BOOLEAN NTAPI CmpMarkValueDataDirty ( IN PHHIVE  Hive,
IN PCM_KEY_VALUE  Value 
)

Definition at line 19 of file cmvalue.c.

21{
22 ULONG KeySize;
23 PAGED_CODE();
24
25 /* Make sure there's actually any data */
26 if (Value->Data != HCELL_NIL)
27 {
28 /* If this is a small key, there's no need to have it dirty */
29 if (CmpIsKeyValueSmall(&KeySize, Value->DataLength)) return TRUE;
30
31 /* Check if this is a big key */
32 ASSERT_VALUE_BIG(Hive, KeySize);
33
34 /* Normal value, just mark it dirty */
35 HvMarkCellDirty(Hive, Value->Data, FALSE);
36 }
37
38 /* Operation complete */
39 return TRUE;
40}

Referenced by CmDeleteValueKey(), CmpMarkKeyDirty(), CmpSetValueKeyExisting(), and RegDeleteValueW().

◆ CmpNameSize()

USHORT NTAPI CmpNameSize ( IN PHHIVE  Hive,
IN PCUNICODE_STRING  Name 
)

Definition at line 74 of file cmname.c.

76{
77 ULONG i;
78
79 /* For old hives, just return the length */
80 if (Hive->Version == 1) return Name->Length;
81
82 /* For new versions, check for compressed name */
83 for (i = 0; i < (Name->Length / sizeof(WCHAR)); i++)
84 {
85 /* Check if the name is non compressed */
86 if (Name->Buffer[i] > (UCHAR)-1) return Name->Length;
87 }
88
89 /* Compressed name, return length */
90 return Name->Length / sizeof(WCHAR);
91}

Referenced by CmCreateRootNode(), CmiAddValueKey(), CmiCreateSubKey(), CmpCreateLinkNode(), CmpCreateRootNode(), CmpDoCreateChild(), and CmpSetValueKeyNew().

◆ CmpRemoveSecurityCellList()

VOID NTAPI CmpRemoveSecurityCellList ( IN PHHIVE  Hive,
IN HCELL_INDEX  SecurityCell 
)

Definition at line 19 of file cmse.c.

21{
22 PCM_KEY_SECURITY SecurityData, FlinkCell, BlinkCell;
23
24 PAGED_CODE();
25
26 // ASSERT( (((PCMHIVE)Hive)->HiveSecurityLockOwner == KeGetCurrentThread()) || (CmpTestRegistryLockExclusive() == TRUE) );
27
28 SecurityData = (PCM_KEY_SECURITY)HvGetCell(Hive, SecurityCell);
29 if (!SecurityData) return;
30
31 FlinkCell = (PCM_KEY_SECURITY)HvGetCell(Hive, SecurityData->Flink);
32 if (!FlinkCell)
33 {
34 HvReleaseCell(Hive, SecurityCell);
35 return;
36 }
37
38 BlinkCell = (PCM_KEY_SECURITY)HvGetCell(Hive, SecurityData->Blink);
39 if (!BlinkCell)
40 {
41 HvReleaseCell(Hive, SecurityData->Flink);
42 HvReleaseCell(Hive, SecurityCell);
43 return;
44 }
45
46 /* Sanity checks */
47 ASSERT(FlinkCell->Blink == SecurityCell);
48 ASSERT(BlinkCell->Flink == SecurityCell);
49
50 /* Unlink the security block and free it */
51 FlinkCell->Blink = SecurityData->Blink;
52 BlinkCell->Flink = SecurityData->Flink;
53#ifdef USE_CM_CACHE
54 CmpRemoveFromSecurityCache(Hive, SecurityCell);
55#endif
56
57 /* Release the cells */
58 HvReleaseCell(Hive, SecurityData->Blink);
59 HvReleaseCell(Hive, SecurityData->Flink);
60 HvReleaseCell(Hive, SecurityCell);
61}
HCELL_INDEX Flink
Definition: cmdata.h:141
HCELL_INDEX Blink
Definition: cmdata.h:142

Referenced by CmpFreeSecurityDescriptor().

◆ CmpRemoveSubKey()

BOOLEAN NTAPI CmpRemoveSubKey ( IN PHHIVE  Hive,
IN HCELL_INDEX  ParentKey,
IN HCELL_INDEX  TargetKey 
)

Definition at line 1694 of file cmindex.c.

1697{
1699 UNICODE_STRING SearchName;
1700 BOOLEAN IsCompressed;
1701 WCHAR Buffer[50];
1702 HCELL_INDEX RootCell = HCELL_NIL, LeafCell, ChildCell;
1703 PCM_KEY_INDEX Root = NULL, Leaf;
1705 ULONG Storage, RootIndex = INVALID_INDEX, LeafIndex;
1707 HCELL_INDEX CellToRelease1 = HCELL_NIL, CellToRelease2 = HCELL_NIL;
1708
1709 /* Get the target key node */
1710 Node = (PCM_KEY_NODE)HvGetCell(Hive, TargetKey);
1711 if (!Node) return FALSE;
1712
1713 /* Make sure it's dirty, then release it */
1714 ASSERT(HvIsCellDirty(Hive, TargetKey));
1715 HvReleaseCell(Hive, TargetKey);
1716
1717 /* Check if the name is compressed */
1718 if (Node->Flags & KEY_COMP_NAME)
1719 {
1720 /* Remember for later */
1721 IsCompressed = TRUE;
1722
1723 /* Build the search name */
1724 SearchName.Length = CmpCompressedNameSize(Node->Name,
1725 Node->NameLength);
1726 SearchName.MaximumLength = SearchName.Length;
1727
1728 /* Do we need an extra bufer? */
1729 if (SearchName.MaximumLength > sizeof(Buffer))
1730 {
1731 /* Allocate one */
1732 SearchName.Buffer = Hive->Allocate(SearchName.Length, TRUE, TAG_CM);
1733 if (!SearchName.Buffer) return FALSE;
1734 }
1735 else
1736 {
1737 /* Otherwise, use our local stack buffer */
1738 SearchName.Buffer = Buffer;
1739 }
1740
1741 /* Copy the compressed name */
1742 CmpCopyCompressedName(SearchName.Buffer,
1743 SearchName.MaximumLength,
1744 Node->Name,
1745 Node->NameLength);
1746 }
1747 else
1748 {
1749 /* It's not compressed, build the name directly from the node */
1750 IsCompressed = FALSE;
1751 SearchName.Length = Node->NameLength;
1752 SearchName.MaximumLength = Node->NameLength;
1753 SearchName.Buffer = Node->Name;
1754 }
1755
1756 /* Now get the parent node */
1758 if (!Node) goto Exit;
1759
1760 /* Make sure it's dirty, then release it */
1762 HvReleaseCell(Hive, ParentKey);
1763
1764 /* Get the storage type and make sure it's not empty */
1765 Storage = HvGetCellType(TargetKey);
1766 ASSERT(Node->SubKeyCounts[Storage] != 0);
1767 //ASSERT(HvIsCellAllocated(Hive, Node->SubKeyLists[Storage]));
1768
1769 /* Get the leaf cell now */
1770 LeafCell = Node->SubKeyLists[Storage];
1771 Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, LeafCell);
1772 if (!Leaf) goto Exit;
1773
1774 /* Remember to release it later */
1775 CellToRelease1 = LeafCell;
1776
1777 /* Check if the leaf is a root */
1778 if (Leaf->Signature == CM_KEY_INDEX_ROOT)
1779 {
1780 /* Find the child inside the root */
1781 RootIndex = CmpFindSubKeyInRoot(Hive, Leaf, &SearchName, &ChildCell);
1782 if (RootIndex & INVALID_INDEX) goto Exit;
1783 ASSERT(ChildCell != FALSE);
1784
1785 /* The root cell is now this leaf */
1786 Root = Leaf;
1787 RootCell = LeafCell;
1788
1789 /* And the new leaf is now this child */
1790 LeafCell = ChildCell;
1791 Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, LeafCell);
1792 if (!Leaf) goto Exit;
1793
1794 /* Remember to release it later */
1795 CellToRelease2 = LeafCell;
1796 }
1797
1798 /* Make sure the leaf is valid */
1799 ASSERT((Leaf->Signature == CM_KEY_INDEX_LEAF) ||
1800 (Leaf->Signature == CM_KEY_FAST_LEAF) ||
1801 (Leaf->Signature == CM_KEY_HASH_LEAF));
1802
1803 /* Now get the child in the leaf */
1804 LeafIndex = CmpFindSubKeyInLeaf(Hive, Leaf, &SearchName, &ChildCell);
1805 if (LeafIndex & INVALID_INDEX) goto Exit;
1806 ASSERT(ChildCell != HCELL_NIL);
1807
1808 /* Decrement key counts and check if this was the last leaf entry */
1809 Node->SubKeyCounts[Storage]--;
1810 if (!(--Leaf->Count))
1811 {
1812 /* Free the leaf */
1813 HvFreeCell(Hive, LeafCell);
1814
1815 /* Check if we were inside a root */
1816 if (Root)
1817 {
1818 /* Decrease the root count too, since the leaf is going away */
1819 if (!(--Root->Count))
1820 {
1821 /* The root is gone too,n ow */
1822 HvFreeCell(Hive, RootCell);
1823 Node->SubKeyLists[Storage] = HCELL_NIL;
1824 }
1825 else if (RootIndex < Root->Count)
1826 {
1827 /* Bring everything up by one */
1828 RtlMoveMemory(&Root->List[RootIndex],
1829 &Root->List[RootIndex + 1],
1830 (Root->Count - RootIndex) * sizeof(HCELL_INDEX));
1831 }
1832 }
1833 else
1834 {
1835 /* Otherwise, just clear the cell */
1836 Node->SubKeyLists[Storage] = HCELL_NIL;
1837 }
1838 }
1839 else if (LeafIndex < Leaf->Count)
1840 {
1841 /* Was the leaf a normal index? */
1842 if (Leaf->Signature == CM_KEY_INDEX_LEAF)
1843 {
1844 /* Bring everything up by one */
1845 RtlMoveMemory(&Leaf->List[LeafIndex],
1846 &Leaf->List[LeafIndex + 1],
1847 (Leaf->Count - LeafIndex) * sizeof(HCELL_INDEX));
1848 }
1849 else
1850 {
1851 /* This is a fast index, bring everything up by one */
1852 Child = (PCM_KEY_FAST_INDEX)Leaf;
1853 RtlMoveMemory(&Child->List[LeafIndex],
1854 &Child->List[LeafIndex+1],
1855 (Child->Count - LeafIndex) * sizeof(CM_INDEX));
1856 }
1857 }
1858
1859 /* If we got here, now we're done */
1860 Result = TRUE;
1861
1862Exit:
1863 /* Release any cells we may have been holding */
1864 if (CellToRelease1 != HCELL_NIL) HvReleaseCell(Hive, CellToRelease1);
1865 if (CellToRelease2 != HCELL_NIL) HvReleaseCell(Hive, CellToRelease2);
1866
1867 /* Check if the name was compressed and not inside our local buffer */
1868 if ((IsCompressed) && (SearchName.MaximumLength > sizeof(Buffer)))
1869 {
1870 /* Free the buffer we allocated */
1871 Hive->Free(SearchName.Buffer, 0);
1872 }
1873
1874 /* Return the result */
1875 return Result;
1876}
union node Node
Definition: types.h:1255
static IStorage Storage
Definition: ole2.c:3548
static void Exit(void)
Definition: sock.c:1330
root entry for file system trees
Definition: entries.h:148
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
_Must_inspect_result_ _In_opt_ WDFKEY ParentKey
Definition: wdfregistry.h:69

Referenced by CmpFreeKeyByCell().

◆ CmpRemoveValueFromList()

NTSTATUS NTAPI CmpRemoveValueFromList ( IN PHHIVE  Hive,
IN ULONG  Index,
IN OUT PCHILD_LIST  ChildList 
)

Definition at line 320 of file cmvalue.c.

323{
324 ULONG Count;
325 PCELL_DATA CellData;
326 HCELL_INDEX NewCell;
327 PAGED_CODE();
328
329 /* Sanity check */
330 ASSERT((((LONG)Index) >= 0) && (Index <= ChildList->Count));
331
332 /* Get the new count after removal */
333 Count = ChildList->Count - 1;
334 if (Count > 0)
335 {
336 /* Get the actual list array */
337 CellData = HvGetCell(Hive, ChildList->List);
338 if (!CellData) return STATUS_INSUFFICIENT_RESOURCES;
339
340 /* Make sure cells data have been made dirty */
341 ASSERT(HvIsCellDirty(Hive, ChildList->List));
342 ASSERT(HvIsCellDirty(Hive, CellData->u.KeyList[Index]));
343
344 /* Loop the list */
345 while (Index < Count)
346 {
347 /* Move everything up */
348 CellData->u.KeyList[Index] = CellData->u.KeyList[Index + 1];
349 Index++;
350 }
351
352 /* Re-allocate the cell for the list by decreasing the count */
353 NewCell = HvReallocateCell(Hive,
354 ChildList->List,
355 Count * sizeof(HCELL_INDEX));
356 ASSERT(NewCell != HCELL_NIL);
357 HvReleaseCell(Hive,ChildList->List);
358
359 /* Update the list cell */
360 ChildList->List = NewCell;
361 }
362 else
363 {
364 /* Otherwise, we were the last entry, so free the list entirely */
365 HvFreeCell(Hive, ChildList->List);
366 ChildList->List = HCELL_NIL;
367 }
368
369 /* Update the child list with the new count */
370 ChildList->Count = Count;
371 return STATUS_SUCCESS;
372}

Referenced by CmDeleteValueKey(), and RegDeleteValueW().

◆ CmpRepairClassOfNodeKey()

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.

Parameters
[in,out]HiveA pointer to a hive descriptor containing faulty data.
[in]CurrentCellThe current cell to be marked as dirty.
[in,out]CellDataThe cell data of the current cell of which its class is to be repaired.
[in]FixHiveIf set to TRUE, self heal is triggered and the target hive will be fixed. Otherwise the hive will not be fixed.
Returns
Returns TRUE if the function successfully healed the class of node key, FALSE otherwise.

Definition at line 637 of file cmheal.c.

642{
643 PAGED_CODE();
644
645 /* Is self healing possible? */
646 if (!CmIsSelfHealEnabled(FixHive))
647 {
648 DPRINT1("Self healing not possible\n");
649 return FALSE;
650 }
651
652 /*
653 * Mark the cell where we got the actual
654 * cell data as dirty and fix the class field
655 * of key node.
656 */
657 HvMarkCellDirty(Hive, CurrentCell, FALSE);
658 CellData->u.KeyNode.Class = HCELL_NIL;
659 CellData->u.KeyNode.ClassLength = 0;
660
661 /* Mark the hive as in self healing mode since we repaired it */
662 Hive->BaseBlock->BootType |= HBOOT_TYPE_SELF_HEAL;
663 return TRUE;
664}
BOOLEAN CMAPI CmIsSelfHealEnabled(_In_ BOOLEAN FixHive)
Checks if self healing is permitted by the kernel and/or bootloader. Self healing is also triggered i...
Definition: cmheal.c:369

Referenced by CmpValidateKey().

◆ CmpRepairKeyNodeSignature()

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.

Parameters
[in,out]HiveA pointer to a hive descriptor containing faulty data.
[in]CurrentCellThe current cell to be marked as dirty.
[in,out]CellDataThe cell data of the current cell of which its signature is to be repaired.
[in]FixHiveIf set to TRUE, self heal is triggered and the target hive will be fixed. Otherwise the hive will not be fixed.
Returns
Returns TRUE if the function successfully healed the key node signature, FALSE otherwise.

Definition at line 585 of file cmheal.c.

590{
591 PAGED_CODE();
592
593 /* Is self healing possible? */
594 if (!CmIsSelfHealEnabled(FixHive))
595 {
596 DPRINT1("Self healing not possible\n");
597 return FALSE;
598 }
599
600 /*
601 * Mark the cell where we got the actual
602 * cell data as dirty and fix the key signature.
603 */
604 HvMarkCellDirty(Hive, CurrentCell, FALSE);
605 CellData->u.KeyNode.Signature = CM_KEY_NODE_SIGNATURE;
606
607 /* Mark the hive as in self healing mode since we repaired it */
608 Hive->BaseBlock->BootType |= HBOOT_TYPE_SELF_HEAL;
609 return TRUE;
610}

Referenced by CmpValidateKey().

◆ CmpRepairParentKey()

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.

Parameters
[in,out]HiveA pointer to a hive descriptor containing faulty data.
[in]TargetKeyThe offending target cell to remove from the parent.
[in]ParentKeyThe damaged parent key cell to heal.
[in]FixHiveIf set to TRUE, self heal is triggered and the target hive will be fixed. Otherwise the hive will not be fixed.
Returns
Returns TRUE if the function successfully healed the parent key, FALSE otherwise.

Definition at line 409 of file cmheal.c.

414{
415 PCM_KEY_INDEX KeyIndex;
416 PCM_KEY_NODE KeyNode;
417 BOOLEAN ParentRepaired;
418
419 PAGED_CODE();
420
421 /* The target key must NEVER be NIL! */
422 ASSERT(TargetKey != HCELL_NIL);
423
424 /* Assume the parent hasn't been repaired yet */
425 ParentRepaired = FALSE;
426
427 /* Is self healing possible? */
428 if (!CmIsSelfHealEnabled(FixHive))
429 {
430 DPRINT1("Self healing not possible\n");
431 return ParentRepaired;
432 }
433
434 /* Obtain a node from the parent */
435 KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, ParentKey);
436 if (!KeyNode)
437 {
438 DPRINT1("Couldn't get the parent key node\n");
439 return ParentRepaired;
440 }
441
442 /* Obtain the index as well since we got the parent node */
443 KeyIndex = (PCM_KEY_INDEX)HvGetCell(Hive, KeyNode->SubKeyLists[Stable]);
444 if (!KeyIndex)
445 {
446 DPRINT1("Couldn't get the key index from parent node\n");
448 return ParentRepaired;
449 }
450
451 /* Check if this is a root */
452 if (KeyIndex->Signature == CM_KEY_INDEX_ROOT)
453 {
454 /* It is, call the specific helper to discard the damaged key down the root */
455 ParentRepaired = CmpRemoveSubkeyInRoot(Hive,
456 KeyIndex,
457 TargetKey);
458 }
459 else if ((KeyIndex->Signature == CM_KEY_INDEX_LEAF) ||
460 (KeyIndex->Signature == CM_KEY_FAST_LEAF) ||
461 (KeyIndex->Signature == CM_KEY_HASH_LEAF))
462 {
463 /* Otherwise call the leaf helper */
464 ParentRepaired = CmpRemoveSubKeyInLeaf(Hive,
465 KeyNode,
466 KeyIndex,
467 TargetKey);
468 }
469 else
470 {
471 /*
472 * Generally CmCheckRegistry detects if a key index
473 * in the subkeys list is totally broken (we understand
474 * that if its signature is not root or leaf) and it will
475 * purge the whole subkeys list in such cases. With that
476 * being said, we should never reach this code path. But
477 * if for whatever reason we reach here then something
478 * is seriously wrong.
479 */
480 DPRINT1("The key index signature is invalid (KeyIndex->Signature == %lu)", KeyIndex->Signature);
481 ASSERT(FALSE);
482 }
483
484 /*
485 * If we successfully removed the offending key
486 * cell mark down the parent as dirty and punt down
487 * the subkey count as well. Mark the hive as in
488 * self heal mode as well.
489 */
490 if (ParentRepaired)
491 {
493 KeyNode->SubKeyCounts[Stable]--;
494 Hive->BaseBlock->BootType |= HBOOT_TYPE_SELF_HEAL;
495 DPRINT1("The subkey has been removed, the parent is now repaired\n");
496 }
497
498 HvReleaseCell(Hive, KeyNode->SubKeyLists[Stable]);
500 return ParentRepaired;
501}
static BOOLEAN CmpRemoveSubKeyInLeaf(_In_ PHHIVE Hive, _In_ PCM_KEY_NODE KeyNode, _In_ PCM_KEY_INDEX Leaf, _In_ HCELL_INDEX TargetKey)
Removes the offending subkey from a leaf index.
Definition: cmheal.c:281
static BOOLEAN CmpRemoveSubkeyInRoot(_In_ PHHIVE Hive, _In_ PCM_KEY_INDEX RootIndex, _In_ HCELL_INDEX TargetKey)
Removes the offending subkey from a root index.
Definition: cmheal.c:164

Referenced by CmpValidateRegistryInternal().

◆ CmpRepairParentNode()

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.

Parameters
[in,out]HiveA pointer to a hive descriptor containing faulty data.
[in]CurrentCellThe current cell to be marked as dirty.
[in]ParentCellThe sane parent cell which is used by the function for new parent node assignment.
[in,out]CellDataThe cell data of the current cell of which its parent node is to be repaired.
[in]FixHiveIf set to TRUE, self heal is triggered and the target hive will be fixed. Otherwise the hive will not be fixed.
Returns
Returns TRUE if the function successfully healed the parent node, FALSE otherwise.

Definition at line 532 of file cmheal.c.

538{
539 PAGED_CODE();
540
541 /* Is self healing possible? */
542 if (!CmIsSelfHealEnabled(FixHive))
543 {
544 DPRINT1("Self healing not possible\n");
545 return FALSE;
546 }
547
548 /*
549 * Mark the cell where we got the actual
550 * cell data as dirty and fix the node.
551 */
552 HvMarkCellDirty(Hive, CurrentCell, FALSE);
553 CellData->u.KeyNode.Parent = ParentCell;
554
555 /* Mark the hive as in self healing mode since we repaired it */
556 Hive->BaseBlock->BootType |= HBOOT_TYPE_SELF_HEAL;
557 return TRUE;
558}

Referenced by CmpValidateKey().

◆ CmpRepairSubKeyCounts()

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 a sane count.

Parameters
[in,out]HiveA pointer to a hive descriptor containing faulty data.
[in]CurrentCellThe current cell to be marked as dirty.
[in]CountThe healthy count which is used by the function to fix the subkeys list count.
[in,out]CellDataThe cell data of the current cell of which its subkeys list is to be fixed.
[in]FixHiveIf set to TRUE, self heal is triggered and the target hive will be fixed. Otherwise the hive will not be fixed.
Returns
Returns TRUE if the function successfully healed the subkeys list count, FALSE otherwise.

Definition at line 829 of file cmheal.c.

835{
836 PAGED_CODE();
837
838 /* Is self healing possible? */
839 if (!CmIsSelfHealEnabled(FixHive))
840 {
841 DPRINT1("Self healing not possible\n");
842 return FALSE;
843 }
844
845 /*
846 * Mark the cell where we got the actual
847 * cell data as dirty and fix the subkey
848 * counts.
849 */
850 HvMarkCellDirty(Hive, CurrentCell, FALSE);
851 CellData->u.KeyNode.SubKeyCounts[Stable] = Count;
852
853 /* Mark the hive as in self healing mode since we repaired it */
854 Hive->BaseBlock->BootType |= HBOOT_TYPE_SELF_HEAL;
855 return TRUE;
856}

Referenced by CmpValidateSubKeyList().

◆ CmpRepairSubKeyList()

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 list.

Parameters
[in,out]HiveA pointer to a hive descriptor containing faulty data.
[in]CurrentCellThe current cell to be marked as dirty.
[in,out]CellDataThe cell data of the current cell of which its subkeys list is to be fixed.
[in]FixHiveIf set to TRUE, self heal is triggered and the target hive will be fixed. Otherwise the hive will not be fixed.
Returns
Returns TRUE if the function successfully healed the subkeys list, FALSE otherwise.

Definition at line 883 of file cmheal.c.

888{
889 PAGED_CODE();
890
891 /* Is self healing possible? */
892 if (!CmIsSelfHealEnabled(FixHive))
893 {
894 DPRINT1("Self healing not possible\n");
895 return FALSE;
896 }
897
898 /*
899 * Mark the cell where we got the actual
900 * cell data as dirty and fix the subkey
901 * list.
902 */
903 HvMarkCellDirty(Hive, CurrentCell, FALSE);
904 CellData->u.KeyNode.SubKeyLists[Stable] = HCELL_NIL;
905 CellData->u.KeyNode.SubKeyCounts[Stable] = 0;
906
907 /* Mark the hive as in self healing mode since we repaired it */
908 Hive->BaseBlock->BootType |= HBOOT_TYPE_SELF_HEAL;
909 return TRUE;
910}

Referenced by CmpValidateKey().

◆ CmpRepairValueList()

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.

Parameters
[in,out]HiveA pointer to a hive descriptor containing faulty data.
[in]CurrentCellThe current cell to be marked as dirty.
[in]FixHiveIf set to TRUE, self heal is triggered and the target hive will be fixed. Otherwise the hive will not be fixed.
Returns
Returns TRUE if the function successfully healed the value list, FALSE otherwise.

Definition at line 765 of file cmheal.c.

769{
770 PCM_KEY_NODE ValueListNode;
771
772 PAGED_CODE();
773
774 /* Is self healing possible? */
775 if (!CmIsSelfHealEnabled(FixHive))
776 {
777 DPRINT1("Self healing not possible\n");
778 return FALSE;
779 }
780
781 /* Obtain a node */
782 ValueListNode = (PCM_KEY_NODE)HvGetCell(Hive, CurrentCell);
783 if (!ValueListNode)
784 {
785 DPRINT1("Could not get a node from the current cell\n");
786 return FALSE;
787 }
788
789 /* Purge out the whole list */
790 HvMarkCellDirty(Hive, CurrentCell, FALSE);
791 ValueListNode->ValueList.List = HCELL_NIL;
792 ValueListNode->ValueList.Count = 0;
793
794 Hive->BaseBlock->BootType |= HBOOT_TYPE_SELF_HEAL;
795 HvReleaseCell(Hive, CurrentCell);
796 return TRUE;
797}

Referenced by CmpValidateKey().

◆ CmpRepairValueListCount()

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 value less from the list.

Parameters
[in,out]HiveA pointer to a hive descriptor containing faulty data.
[in]CurrentCellThe current cell to be marked as dirty.
[in]ListCountIndexThe value count index which points to the actual value in the list to be removed.
[in,out]ValueListDataThe value list cell data containing the actual list of which the damaged is to be removed from.
[in]FixHiveIf set to TRUE, self heal is triggered and the target hive will be fixed. Otherwise the hive will not be fixed.
Returns
Returns TRUE if the function successfully healed the value list count, FALSE otherwise.

Definition at line 696 of file cmheal.c.

702{
703 PCM_KEY_NODE ValueListNode;
704
705 PAGED_CODE();
706
707 /* Is self healing possible? */
708 if (!CmIsSelfHealEnabled(FixHive))
709 {
710 DPRINT1("Self healing not possible\n");
711 return FALSE;
712 }
713
714 /*
715 * Obtain a node from the cell that we mark it as dirty.
716 * The node is that of the current cell of which its
717 * value list is being validated.
718 */
719 ValueListNode = (PCM_KEY_NODE)HvGetCell(Hive, CurrentCell);
720 if (!ValueListNode)
721 {
722 DPRINT1("Could not get a node from the current cell\n");
723 return FALSE;
724 }
725
726 /*
727 * Mark the current cell and value list as dirty
728 * as we will be making changes onto them.
729 */
730 HvMarkCellDirty(Hive, CurrentCell, FALSE);
731 HvMarkCellDirty(Hive, ValueListNode->ValueList.List, FALSE);
732
733 /*
734 * Now remove the value from the list and mark the
735 * hive as in self healing mode.
736 */
737 CmpRemoveValueFromValueList(ValueListNode, ValueListData, ListCountIndex);
738 Hive->BaseBlock->BootType |= HBOOT_TYPE_SELF_HEAL;
739 HvReleaseCell(Hive, CurrentCell);
740 return TRUE;
741}
static VOID CmpRemoveValueFromValueList(_Inout_ PCM_KEY_NODE ValueListNode, _Inout_ PCELL_DATA ValueListData, _In_ ULONG Index)
Removes a cell from a key value list node.
Definition: cmheal.c:121

Referenced by CmpValidateValueListByCount().

◆ CmpSetValueDataNew()

NTSTATUS NTAPI CmpSetValueDataNew ( IN PHHIVE  Hive,
IN PVOID  Data,
IN ULONG  DataSize,
IN HSTORAGE_TYPE  StorageType,
IN HCELL_INDEX  ValueCell,
OUT PHCELL_INDEX  DataCell 
)

Definition at line 289 of file cmvalue.c.

295{
296 PCELL_DATA CellData;
297 PAGED_CODE();
299
300 /* Check if this is a big key */
302
303 /* Allocate a data cell */
304 *DataCell = HvAllocateCell(Hive, DataSize, StorageType, HCELL_NIL);
305 if (*DataCell == HCELL_NIL) return STATUS_INSUFFICIENT_RESOURCES;
306
307 /* Get the actual data */
308 CellData = HvGetCell(Hive, *DataCell);
309 if (!CellData) ASSERT(FALSE);
310
311 /* Copy our buffer into it */
312 RtlCopyMemory(CellData, Data, DataSize);
313
314 /* All done */
315 return STATUS_SUCCESS;
316}
#define CM_KEY_VALUE_SMALL
Definition: cmdata.h:49
_In_ NDIS_STATUS _In_ ULONG _In_ USHORT _In_opt_ PVOID _In_ ULONG DataSize
Definition: ndis.h:4755

Referenced by CmpSetValueKeyNew().

◆ CmpValueToData()

PCELL_DATA NTAPI CmpValueToData ( IN PHHIVE  Hive,
IN PCM_KEY_VALUE  Value,
OUT PULONG  Length 
)

Definition at line 167 of file cmvalue.c.

170{
172 BOOLEAN BufferAllocated;
173 HCELL_INDEX CellToRelease;
174 PAGED_CODE();
175
176 /* Sanity check */
177 ASSERT(Hive->ReleaseCellRoutine == NULL);
178
179 /* Get the actual data */
180 if (!CmpGetValueData(Hive,
181 Value,
182 Length,
183 (PVOID*)&Buffer,
184 &BufferAllocated,
185 &CellToRelease))
186 {
187 /* We failed */
188 ASSERT(BufferAllocated == FALSE);
189 ASSERT(Buffer == NULL);
190 return NULL;
191 }
192
193 /* This should never happen! */
194 if (BufferAllocated)
195 {
196 /* Free the buffer and bugcheck */
197 Hive->Free(Buffer, 0);
198 KeBugCheckEx(REGISTRY_ERROR, 8, 0, (ULONG_PTR)Hive, (ULONG_PTR)Value);
199 }
200
201 /* Otherwise, return the cell data */
202 return Buffer;
203}
BOOLEAN NTAPI CmpGetValueData(IN PHHIVE Hive, IN PCM_KEY_VALUE Value, OUT PULONG Length, OUT PVOID *Buffer, OUT PBOOLEAN BufferAllocated, OUT PHCELL_INDEX CellToRelease)
Definition: cmvalue.c:125
VOID NTAPI KeBugCheckEx(_In_ ULONG BugCheckCode, _In_ ULONG_PTR BugCheckParameter1, _In_ ULONG_PTR BugCheckParameter2, _In_ ULONG_PTR BugCheckParameter3, _In_ ULONG_PTR BugCheckParameter4)
Definition: rtlcompat.c:108
uint32_t ULONG_PTR
Definition: typedefs.h:65

Referenced by BiGetRegistryValue(), CmpAddDriverToList(), CmpFindControlSet(), CmpFindTagIndex(), CmpIsLoadType(), CmpIsSafe(), CmpSortDriverList(), and RepGetValueData().

◆ HvAllocateCell()

◆ HvFree()

VOID CMAPI HvFree ( PHHIVE  RegistryHive)

◆ HvFreeCell()

VOID CMAPI HvFreeCell ( PHHIVE  RegistryHive,
HCELL_INDEX  CellOffset 
)

Definition at line 468 of file hivecell.c.

471{
472 PHCELL Free;
473 PHCELL Neighbor;
474 PHBIN Bin;
475 ULONG CellType;
476 ULONG CellBlock;
477
478 ASSERT(RegistryHive->ReadOnly == FALSE);
479
480 CMLTRACE(CMLIB_HCELL_DEBUG, "%s - Hive %p, CellIndex %08lx\n",
481 __FUNCTION__, RegistryHive, CellIndex);
482
483 Free = HvpGetCellHeader(RegistryHive, CellIndex);
484
485 ASSERT(Free->Size < 0);
486
487 Free->Size = -Free->Size;
488
489 CellType = HvGetCellType(CellIndex);
490 CellBlock = HvGetCellBlock(CellIndex);
491
492 /* FIXME: Merge free blocks */
493 Bin = (PHBIN)RegistryHive->Storage[CellType].BlockList[CellBlock].BinAddress;
494
495 if ((CellIndex & ~HCELL_TYPE_MASK) + Free->Size <
496 Bin->FileOffset + Bin->Size)
497 {
498 Neighbor = (PHCELL)((ULONG_PTR)Free + Free->Size);
499 if (Neighbor->Size > 0)
500 {
501 HvpRemoveFree(RegistryHive, Neighbor,
502 ((HCELL_INDEX)((ULONG_PTR)Neighbor - (ULONG_PTR)Bin +
503 Bin->FileOffset)) | (CellIndex & HCELL_TYPE_MASK));
504 Free->Size += Neighbor->Size;
505 }
506 }
507
508 Neighbor = (PHCELL)(Bin + 1);
509 while (Neighbor < Free)
510 {
511 if (Neighbor->Size > 0)
512 {
513 if ((ULONG_PTR)Neighbor + Neighbor->Size == (ULONG_PTR)Free)
514 {
515 HCELL_INDEX NeighborCellIndex =
516 ((HCELL_INDEX)((ULONG_PTR)Neighbor - (ULONG_PTR)Bin +
517 Bin->FileOffset)) | (CellIndex & HCELL_TYPE_MASK);
518
519 if (HvpComputeFreeListIndex(Neighbor->Size) !=
520 HvpComputeFreeListIndex(Neighbor->Size + Free->Size))
521 {
522 HvpRemoveFree(RegistryHive, Neighbor, NeighborCellIndex);
523 Neighbor->Size += Free->Size;
524 HvpAddFree(RegistryHive, Neighbor, NeighborCellIndex);
525 }
526 else
527 Neighbor->Size += Free->Size;
528
529 if (CellType == Stable)
530 HvMarkCellDirty(RegistryHive, NeighborCellIndex, FALSE);
531
532 return;
533 }
534 Neighbor = (PHCELL)((ULONG_PTR)Neighbor + Neighbor->Size);
535 }
536 else
537 {
538 Neighbor = (PHCELL)((ULONG_PTR)Neighbor - Neighbor->Size);
539 }
540 }
541
542 /* Add block to the list of free blocks */
543 HvpAddFree(RegistryHive, Free, CellIndex);
544
545 if (CellType == Stable)
546 HvMarkCellDirty(RegistryHive, CellIndex, FALSE);
547}
Definition: bin.h:44
#define CMLTRACE(x,...)
Definition: cmlib.h:172
#define CMLIB_HCELL_DEBUG
Definition: cmlib.h:193
#define __FUNCTION__
Definition: types.h:116
#define ULONG_PTR
Definition: config.h:101
static __inline PHCELL CMAPI HvpGetCellHeader(PHHIVE RegistryHive, HCELL_INDEX CellIndex)
Definition: hivecell.c:23
static VOID CMAPI HvpRemoveFree(PHHIVE RegistryHive, PHCELL CellBlock, HCELL_INDEX CellIndex)
Definition: hivecell.c:227
static NTSTATUS CMAPI HvpAddFree(PHHIVE RegistryHive, PHCELL FreeBlock, HCELL_INDEX FreeIndex)
Definition: hivecell.c:202
BOOLEAN CMAPI HvMarkCellDirty(PHHIVE RegistryHive, HCELL_INDEX CellIndex, BOOLEAN HoldingLock)
Definition: hivecell.c:109
static __inline ULONG CMAPI HvpComputeFreeListIndex(ULONG Size)
Definition: hivecell.c:174
#define HvGetCellBlock(Cell)
Definition: hivedata.h:122
struct _HCELL * PHCELL
#define HCELL_TYPE_MASK
Definition: hivedata.h:113
struct _HBIN * PHBIN
if(dx< 0)
Definition: linetemp.h:194
PHMAP_ENTRY BlockList
Definition: hivedata.h:303
LONG Size
Definition: hivedata.h:215
DUAL Storage[HTYPE_COUNT]
Definition: hivedata.h:357
BOOLEAN ReadOnly
Definition: hivedata.h:335
ULONG_PTR BinAddress
Definition: hivedata.h:284
_In_opt_ PALLOCATE_FUNCTION _In_opt_ PFREE_FUNCTION Free
Definition: exfuncs.h:815

Referenced by CmCreateRootNode(), CmiAddValueKey(), CmiCreateSubKey(), CmpCopyKeyValueList(), CmpCopyValue(), CmpDeepCopyKeyInternal(), CmpDoCreateChild(), CmpFreeKeyBody(), CmpFreeKeyByCell(), CmpFreeSecurityDescriptor(), CmpFreeValue(), CmpFreeValueData(), CmpRemoveSubKey(), CmpRemoveValueFromList(), CmpSetValueKeyNew(), CmpSplitLeaf(), HvReallocateCell(), and RegSetValueExW().

◆ HvGetCellSize()

◆ HvHiveWillShrink()

BOOLEAN CMAPI HvHiveWillShrink ( IN PHHIVE  RegistryHive)

Referenced by CmFlushKey(), and CmpDoFlushAll().

◆ HvInitialize()

NTSTATUS CMAPI HvInitialize ( PHHIVE  RegistryHive,
ULONG  OperationType,
ULONG  HiveFlags,
ULONG  FileType,
PVOID HiveData  OPTIONAL,
PALLOCATE_ROUTINE  Allocate,
PFREE_ROUTINE  Free,
PFILE_SET_SIZE_ROUTINE  FileSetSize,
PFILE_WRITE_ROUTINE  FileWrite,
PFILE_READ_ROUTINE  FileRead,
PFILE_FLUSH_ROUTINE  FileFlush,
ULONG Cluster  OPTIONAL,
PCUNICODE_STRING FileName  OPTIONAL 
)

◆ HvIsCellAllocated()

BOOLEAN CMAPI HvIsCellAllocated ( IN PHHIVE  RegistryHive,
IN HCELL_INDEX  CellIndex 
)

Definition at line 53 of file hivecell.c.

55{
56 ULONG Type, Block;
57
58 /* If it's a flat hive, the cell is always allocated */
59 if (RegistryHive->Flat)
60 return TRUE;
61
62 /* Otherwise, get the type and make sure it's valid */
63 Type = HvGetCellType(CellIndex);
64 Block = HvGetCellBlock(CellIndex);
65 if (Block >= RegistryHive->Storage[Type].Length)
66 return FALSE;
67
68 /* Try to get the cell block */
69 if (RegistryHive->Storage[Type].BlockList[Block].BlockAddress)
70 return TRUE;
71
72 /* No valid block, fail */
73 return FALSE;
74}

Referenced by CmpValidateClass(), CmpValidateKey(), CmpValidateSubKeyList(), CmpValidateValueList(), and CmpValidateValueListByCount().

◆ HvIsCellDirty()

BOOLEAN CMAPI HvIsCellDirty ( IN PHHIVE  Hive,
IN HCELL_INDEX  Cell 
)

Definition at line 153 of file hivecell.c.

155{
156 BOOLEAN IsDirty = FALSE;
157
158 /* Sanity checks */
159 ASSERT(Hive->ReadOnly == FALSE);
160
161 /* Volatile cells are always "dirty" */
162 if (HvGetCellType(Cell) == Volatile)
163 return TRUE;
164
165 /* Check if the dirty bit is set */
166 if (RtlCheckBit(&Hive->DirtyVector, Cell / HBLOCK_SIZE))
167 IsDirty = TRUE;
168
169 /* Return result as boolean*/
170 return IsDirty;
171}
#define RtlCheckBit(BMH, BP)
Definition: rtlfuncs.h:3152

Referenced by CmDeleteKey(), CmDeleteValueKey(), CmpAddValueToList(), CmpRemoveSubKey(), CmpRemoveValueFromList(), CmpSetValueKeyExisting(), CmpSetValueKeyNew(), RegDeleteKeyW(), and RegDeleteValueW().

◆ HvMarkCellDirty()

BOOLEAN CMAPI HvMarkCellDirty ( PHHIVE  RegistryHive,
HCELL_INDEX  CellOffset,
BOOLEAN  HoldingLock 
)

Definition at line 109 of file hivecell.c.

113{
114 ULONG CellBlock;
115 ULONG CellLastBlock;
116
117 ASSERT(RegistryHive->ReadOnly == FALSE);
118
119 CMLTRACE(CMLIB_HCELL_DEBUG, "%s - Hive %p, CellIndex %08lx, HoldingLock %u\n",
120 __FUNCTION__, RegistryHive, CellIndex, HoldingLock);
121
122 if (HvGetCellType(CellIndex) != Stable)
123 return TRUE;
124
125 CellBlock = HvGetCellBlock(CellIndex);
126 CellLastBlock = HvGetCellBlock(CellIndex + HBLOCK_SIZE - 1);
127
128 RtlSetBits(&RegistryHive->DirtyVector,
129 CellBlock, CellLastBlock - CellBlock);
130 RegistryHive->DirtyCount++;
131
132 /*
133 * FIXME: Querying a lazy flush operation is needed to
134 * ensure that the dirty data is being flushed to disk
135 * accordingly. However, this operation has to be done
136 * in a helper like HvMarkDirty that marks specific parts
137 * of the hive as dirty. Since we do not have such kind
138 * of helper we have to perform an eventual lazy flush
139 * when marking cells as dirty here for the moment being,
140 * so that not only we flush dirty data but also write
141 * logs.
142 */
143#if !defined(CMLIB_HOST) && !defined(_BLDR_)
144 if (!(RegistryHive->HiveFlags & HIVE_NOLAZYFLUSH))
145 {
146 CmpLazyFlush();
147 }
148#endif
149 return TRUE;
150}
VOID NTAPI CmpLazyFlush(VOID)
Definition: cmlazy.c:157
#define HIVE_NOLAZYFLUSH
Definition: hivedata.h:24
NTSYSAPI void WINAPI RtlSetBits(PRTL_BITMAP, ULONG, ULONG)
RTL_BITMAP DirtyVector
Definition: hivedata.h:329
ULONG HiveFlags
Definition: hivedata.h:347
ULONG DirtyCount
Definition: hivedata.h:330

Referenced by CmDeleteValueKey(), CmiAddSubKey(), CmiAddValueKey(), CmpAddSubKey(), CmpAddToLeaf(), CmpCreateLinkNode(), CmpDoCreate(), CmpMarkIndexDirty(), CmpMarkKeyDirty(), CmpMarkValueDataDirty(), CmpPurgeVolatiles(), CmpRemoveSubKeyInLeaf(), CmpRemoveSubkeyInRoot(), CmpRepairClassOfNodeKey(), CmpRepairKeyNodeSignature(), CmpRepairParentKey(), CmpRepairParentNode(), CmpRepairSubKeyCounts(), CmpRepairSubKeyList(), CmpRepairValueList(), CmpRepairValueListCount(), CmpSelectLeaf(), CmpSetValueKeyExisting(), CmpSetValueKeyNew(), CmpSplitLeaf(), CmpValidateClass(), CmSetValueKey(), HvAllocateCell(), HvFreeCell(), RegDeleteValueW(), and RegSetValueExW().

◆ HvpAddBin()

PHBIN CMAPI HvpAddBin ( PHHIVE  RegistryHive,
ULONG  Size,
HSTORAGE_TYPE  Storage 
)

Definition at line 12 of file hivebin.c.

16{
17 PHMAP_ENTRY BlockList;
18 PHBIN Bin;
19 ULONG BinSize;
20 ULONG i;
21 ULONG BitmapSize;
22 ULONG BlockCount;
23 ULONG OldBlockListSize;
24 PHCELL Block;
25
26 BinSize = ROUND_UP(Size + sizeof(HBIN), HBLOCK_SIZE);
27 BlockCount = BinSize / HBLOCK_SIZE;
28
29 Bin = RegistryHive->Allocate(BinSize, TRUE, TAG_CM);
30 if (Bin == NULL)
31 return NULL;
32 RtlZeroMemory(Bin, BinSize);
33
34 Bin->Signature = HV_HBIN_SIGNATURE;
35 Bin->FileOffset = RegistryHive->Storage[Storage].Length *
37 Bin->Size = BinSize;
38
39 /* Allocate new block list */
40 OldBlockListSize = RegistryHive->Storage[Storage].Length;
41 BlockList = RegistryHive->Allocate(sizeof(HMAP_ENTRY) *
42 (OldBlockListSize + BlockCount),
43 TRUE,
44 TAG_CM);
45 if (BlockList == NULL)
46 {
47 RegistryHive->Free(Bin, 0);
48 return NULL;
49 }
50
51 if (OldBlockListSize > 0)
52 {
53 RtlCopyMemory(BlockList, RegistryHive->Storage[Storage].BlockList,
54 OldBlockListSize * sizeof(HMAP_ENTRY));
55 RegistryHive->Free(RegistryHive->Storage[Storage].BlockList, 0);
56 }
57
58 RegistryHive->Storage[Storage].BlockList = BlockList;
59 RegistryHive->Storage[Storage].Length += BlockCount;
60
61 for (i = 0; i < BlockCount; i++)
62 {
63 RegistryHive->Storage[Storage].BlockList[OldBlockListSize + i].BlockAddress =
64 ((ULONG_PTR)Bin + (i * HBLOCK_SIZE));
65 RegistryHive->Storage[Storage].BlockList[OldBlockListSize + i].BinAddress = (ULONG_PTR)Bin;
66 }
67
68 /* Initialize a free block in this heap. */
69 Block = (PHCELL)(Bin + 1);
70 Block->Size = (LONG)(BinSize - sizeof(HBIN));
71
72 if (Storage == Stable)
73 {
74 /* Calculate bitmap size in bytes (always a multiple of 32 bits). */
75 BitmapSize = ROUND_UP(RegistryHive->Storage[Stable].Length,
76 sizeof(ULONG) * 8) / 8;
77
78 /* Grow bitmap if necessary. */
79 if (BitmapSize > RegistryHive->DirtyVector.SizeOfBitMap / 8)
80 {
82
83 BitmapBuffer = RegistryHive->Allocate(BitmapSize, TRUE, TAG_CM);
84 RtlZeroMemory(BitmapBuffer, BitmapSize);
85 if (RegistryHive->DirtyVector.SizeOfBitMap > 0)
86 {
87 ASSERT(RegistryHive->DirtyVector.Buffer);
89 RegistryHive->DirtyVector.Buffer,
90 RegistryHive->DirtyVector.SizeOfBitMap / 8);
91 RegistryHive->Free(RegistryHive->DirtyVector.Buffer, 0);
92 }
94 BitmapSize * 8);
95 }
96
97 /* Mark new bin dirty. */
98 RtlSetBits(&RegistryHive->DirtyVector,
99 Bin->FileOffset / HBLOCK_SIZE,
100 BlockCount);
101
102 /* Update size in the base block */
103 RegistryHive->BaseBlock->Length += BinSize;
104 }
105
106 return Bin;
107}
static ULONG BitmapBuffer[(XMS_BLOCKS+31)/32]
Definition: himem.c:86
#define HV_HBIN_SIGNATURE
Definition: hivedata.h:64
NTSYSAPI void WINAPI RtlInitializeBitMap(PRTL_BITMAP, PULONG, ULONG)
ULONG Length
Definition: hivedata.h:301
ULONG Length
Definition: hivedata.h:171
PALLOCATE_ROUTINE Allocate
Definition: hivedata.h:318
PFREE_ROUTINE Free
Definition: hivedata.h:319
Definition: hivedata.h:282
ULONG_PTR BlockAddress
Definition: hivedata.h:283
ULONG SizeOfBitMap
Definition: typedefs.h:90
PULONG Buffer
Definition: typedefs.h:91
uint32_t * PULONG
Definition: typedefs.h:59
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262

Referenced by HvAllocateCell().

◆ HvpCreateHiveFreeCellList()

NTSTATUS CMAPI HvpCreateHiveFreeCellList ( PHHIVE  Hive)

Definition at line 306 of file hivecell.c.

308{
310 PHCELL FreeBlock;
311 ULONG BlockIndex;
312 ULONG FreeOffset;
313 PHBIN Bin;
315 ULONG Index;
316
317 /* Initialize the free cell list */
318 for (Index = 0; Index < 24; Index++)
319 {
322 }
323
324 BlockOffset = 0;
325 BlockIndex = 0;
326 while (BlockIndex < Hive->Storage[Stable].Length)
327 {
328 Bin = (PHBIN)Hive->Storage[Stable].BlockList[BlockIndex].BinAddress;
329
330 /* Search free blocks and add to list */
331 FreeOffset = sizeof(HBIN);
332 while (FreeOffset < Bin->Size)
333 {
334 FreeBlock = (PHCELL)((ULONG_PTR)Bin + FreeOffset);
335 if (FreeBlock->Size > 0)
336 {
337 Status = HvpAddFree(Hive, FreeBlock, Bin->FileOffset + FreeOffset);
338 if (!NT_SUCCESS(Status))
339 return Status;
340
341 FreeOffset += FreeBlock->Size;
342 }
343 else
344 {
345 FreeOffset -= FreeBlock->Size;
346 }
347 }
348
349 BlockIndex += Bin->Size / HBLOCK_SIZE;
350 BlockOffset += Bin->Size;
351 }
352
353 return STATUS_SUCCESS;
354}
#define BlockOffset(V, L)
Definition: cdprocs.h:1650
HCELL_INDEX FreeDisplay[24]
Definition: hivedata.h:305

Referenced by HvpInitializeMemoryHive().

◆ HvpGetCellData()

PCELL_DATA CMAPI HvpGetCellData ( _In_ PHHIVE  Hive,
_In_ HCELL_INDEX  CellIndex 
)

Definition at line 77 of file hivecell.c.

80{
81 return (PCELL_DATA)(HvpGetCellHeader(Hive, CellIndex) + 1);
82}

Referenced by HvInitialize().

◆ HvpHiveHeaderChecksum()

ULONG CMAPI HvpHiveHeaderChecksum ( PHBASE_BLOCK  HiveHeader)

Definition at line 17 of file hivesum.c.

19{
20 PULONG Buffer = (PULONG)HiveHeader;
21 ULONG Sum = 0;
22 ULONG i;
23
24 for (i = 0; i < 127; i++)
25 Sum ^= Buffer[i];
26 if (Sum == (ULONG)-1)
27 Sum = (ULONG)-2;
28 if (Sum == 0)
29 Sum = 1;
30
31 return Sum;
32}

Referenced by CmCreateRootNode(), HvIsInPlaceBaseBlockValid(), HvpRecoverHeaderFromLog(), HvpVerifyHiveHeader(), HvpWriteHive(), HvpWriteLog(), and RegRecoverDataHive().

◆ HvpVerifyHiveHeader()

BOOLEAN CMAPI HvpVerifyHiveHeader ( _In_ PHBASE_BLOCK  BaseBlock,
_In_ ULONG  FileType 
)

Validates the base block header of a registry file (hive or log).

Parameters
[in]BaseBlockA pointer to a base block header to be validated.
[in]FileTypeThe file type of a registry file to check against the file type of the base block.
Returns
Returns TRUE if the base block header is valid, FALSE otherwise.

Definition at line 49 of file hiveinit.c.

52{
53 if (BaseBlock->Signature != HV_HBLOCK_SIGNATURE ||
54 BaseBlock->Major != HSYS_MAJOR ||
55 BaseBlock->Minor < HSYS_MINOR ||
56 BaseBlock->Type != FileType ||
57 BaseBlock->Format != HBASE_FORMAT_MEMORY ||
58 BaseBlock->Cluster != 1 ||
59 BaseBlock->Sequence1 != BaseBlock->Sequence2 ||
60 HvpHiveHeaderChecksum(BaseBlock) != BaseBlock->CheckSum)
61 {
62 DPRINT1("Verify Hive Header failed:\n");
63 DPRINT1(" Signature: 0x%x, expected 0x%x; Major: 0x%x, expected 0x%x\n",
64 BaseBlock->Signature, HV_HBLOCK_SIGNATURE, BaseBlock->Major, HSYS_MAJOR);
65 DPRINT1(" Minor: 0x%x expected to be >= 0x%x; Type: 0x%x, expected 0x%x\n",
66 BaseBlock->Minor, HSYS_MINOR, BaseBlock->Type, FileType);
67 DPRINT1(" Format: 0x%x, expected 0x%x; Cluster: 0x%x, expected 1\n",
68 BaseBlock->Format, HBASE_FORMAT_MEMORY, BaseBlock->Cluster);
69 DPRINT1(" Sequence: 0x%x, expected 0x%x; Checksum: 0x%x, expected 0x%x\n",
70 BaseBlock->Sequence1, BaseBlock->Sequence2,
71 HvpHiveHeaderChecksum(BaseBlock), BaseBlock->CheckSum);
72
73 return FALSE;
74 }
75
76 return TRUE;
77}
#define HV_HBLOCK_SIGNATURE
Definition: hivedata.h:63
#define HSYS_MINOR
Definition: hivedata.h:70
#define HSYS_MAJOR
Definition: hivedata.h:69
#define HBASE_FORMAT_MEMORY
Definition: hivedata.h:78
_In_ WDFDEVICE _In_ WDF_SPECIAL_FILE_TYPE FileType
Definition: wdfdevice.h:2741

Referenced by HvpGetHiveHeader(), HvpInitializeFlatHive(), HvpInitializeMemoryHive(), HvpRecoverHeaderFromLog(), and RegRecoverHeaderHive().

◆ HvReallocateCell()

HCELL_INDEX CMAPI HvReallocateCell ( PHHIVE  RegistryHive,
HCELL_INDEX  CellOffset,
ULONG  Size 
)

Definition at line 421 of file hivecell.c.

425{
426 PVOID OldCell;
427 PVOID NewCell;
428 LONG OldCellSize;
429 HCELL_INDEX NewCellIndex;
431
432 ASSERT(CellIndex != HCELL_NIL);
433
434 CMLTRACE(CMLIB_HCELL_DEBUG, "%s - Hive %p, CellIndex %08lx, Size %x\n",
435 __FUNCTION__, RegistryHive, CellIndex, Size);
436
437 Storage = HvGetCellType(CellIndex);
438
439 OldCell = HvGetCell(RegistryHive, CellIndex);
440 OldCellSize = HvGetCellSize(RegistryHive, OldCell);
441 ASSERT(OldCellSize > 0);
442
443 /*
444 * If new data size is larger than the current, destroy current
445 * data block and allocate a new one.
446 *
447 * FIXME: Merge with adjacent free cell if possible.
448 * FIXME: Implement shrinking.
449 */
450 if (Size > (ULONG)OldCellSize)
451 {
452 NewCellIndex = HvAllocateCell(RegistryHive, Size, Storage, HCELL_NIL);
453 if (NewCellIndex == HCELL_NIL)
454 return HCELL_NIL;
455
456 NewCell = HvGetCell(RegistryHive, NewCellIndex);
457 RtlCopyMemory(NewCell, OldCell, (SIZE_T)OldCellSize);
458
459 HvFreeCell(RegistryHive, CellIndex);
460
461 return NewCellIndex;
462 }
463
464 return CellIndex;
465}
HCELL_INDEX CMAPI HvAllocateCell(PHHIVE RegistryHive, ULONG Size, HSTORAGE_TYPE Storage, HCELL_INDEX Vicinity)
Definition: hivecell.c:357
LONG CMAPI HvGetCellSize(IN PHHIVE Hive, IN PVOID Address)
Definition: hivecell.c:94
VOID CMAPI HvFreeCell(PHHIVE RegistryHive, HCELL_INDEX CellIndex)
Definition: hivecell.c:468
HSTORAGE_TYPE
Definition: hivedata.h:126
ULONG_PTR SIZE_T
Definition: typedefs.h:80

Referenced by CmpAddToLeaf(), CmpAddValueToList(), CmpRemoveValueFromList(), CmpSetValueKeyExisting(), and CmpSplitLeaf().

◆ HvReleaseFreeCellRefArray()

VOID CMAPI HvReleaseFreeCellRefArray ( IN OUT PHV_TRACK_CELL_REF  CellRef)

Definition at line 634 of file hivecell.c.

636{
637 ULONG i;
638
639 PAGED_CODE();
640
641 ASSERT(CellRef);
642
643 /* Any references in the static array? */
644 if (CellRef->StaticCount > 0)
645 {
646 /* Sanity check */
647 ASSERT(CellRef->StaticCount <= STATIC_CELL_PAIR_COUNT);
648
649 /* Loop over them and release them */
650 for (i = 0; i < CellRef->StaticCount; i++)
651 {
652 HvReleaseCell(CellRef->StaticArray[i].Hive,
653 CellRef->StaticArray[i].Cell);
654 }
655
656 /* We can reuse the static array */
657 CellRef->StaticCount = 0;
658 }
659
660 /* Any references in the dynamic array? */
661 if (CellRef->Count > 0)
662 {
663 /* Sanity checks */
664 ASSERT(CellRef->Count <= CellRef->Max);
665 ASSERT(CellRef->CellArray);
666
667 /* Loop over them and release them */
668 for (i = 0; i < CellRef->Count; i++)
669 {
670 HvReleaseCell(CellRef->CellArray[i].Hive,
671 CellRef->CellArray[i].Cell);
672 }
673
674 /* We can reuse the dynamic array */
675 CmpFree(CellRef->CellArray, 0); // TAG_CM
676 CellRef->CellArray = NULL;
677 CellRef->Count = CellRef->Max = 0;
678 }
679}
VOID NTAPI CmpFree(_In_ PVOID Ptr, _In_ ULONG Quota)
Definition: bootreg.c:105
#define STATIC_CELL_PAIR_COUNT
Definition: cmlib.h:367

Referenced by CmEnumerateKey(), and CmQueryKey().

◆ HvSyncHive()

◆ HvSyncHiveFromRecover()

BOOLEAN CMAPI HvSyncHiveFromRecover ( _In_ PHHIVE  RegistryHive)

Synchronizes a hive with recovered data during a healing/resuscitation operation of the registry.

Parameters
[in]RegistryHiveA pointer to a hive descriptor where data syncing is to be done.
Returns
Returns TRUE if hive syncing during recovery succeeded, FALSE otherwise.

Definition at line 672 of file hivewrt.c.

674{
675 ASSERT(!RegistryHive->ReadOnly);
676 ASSERT(RegistryHive->Signature == HV_HHIVE_SIGNATURE);
677
678 /* Call the private API call to do the deed for us */
679 return HvpWriteHive(RegistryHive, TRUE, HFILE_TYPE_PRIMARY);
680}
#define HV_HHIVE_SIGNATURE
Definition: hivedata.h:62
#define HFILE_TYPE_PRIMARY
Definition: hivedata.h:33
static BOOLEAN CMAPI HvpWriteHive(_In_ PHHIVE RegistryHive, _In_ BOOLEAN OnlyDirty, _In_ ULONG FileType)
Writes data (dirty or non) to a primary hive during syncing operation. Hive writing is also performed...
Definition: hivewrt.c:311

Referenced by HvInitialize().

◆ HvTrackCellRef()

BOOLEAN CMAPI HvTrackCellRef ( IN OUT PHV_TRACK_CELL_REF  CellRef,
IN PHHIVE  Hive,
IN HCELL_INDEX  Cell 
)

Definition at line 554 of file hivecell.c.

558{
559 PHV_HIVE_CELL_PAIR NewCellArray;
560
561 PAGED_CODE();
562
563 /* Sanity checks */
564 ASSERT(CellRef);
565 ASSERT(Hive);
566 ASSERT(Cell != HCELL_NIL);
567
568 /* NOTE: The hive cell is already referenced! */
569
570 /* Less than 4? Use the static array */
571 if (CellRef->StaticCount < STATIC_CELL_PAIR_COUNT)
572 {
573 /* Add the reference */
574 CellRef->StaticArray[CellRef->StaticCount].Hive = Hive;
575 CellRef->StaticArray[CellRef->StaticCount].Cell = Cell;
576 CellRef->StaticCount++;
577 return TRUE;
578 }
579
580 DPRINT("HvTrackCellRef: Static array full, use dynamic array.\n");
581
582 /* Sanity checks */
583 if (CellRef->Max == 0)
584 {
585 /* The dynamic array must not have been allocated already */
586 ASSERT(CellRef->CellArray == NULL);
587 ASSERT(CellRef->Count == 0);
588 }
589 else
590 {
591 /* The dynamic array must be allocated */
592 ASSERT(CellRef->CellArray);
593 }
594 ASSERT(CellRef->Count <= CellRef->Max);
595
596 if (CellRef->Count == CellRef->Max)
597 {
598 /* Allocate a new reference table */
599 NewCellArray = CmpAllocate((CellRef->Max + CELL_REF_INCREMENT) * sizeof(HV_HIVE_CELL_PAIR),
600 TRUE,
601 TAG_CM);
602 if (!NewCellArray)
603 {
604 DPRINT1("HvTrackCellRef: Cannot reallocate the reference table.\n");
605 /* We failed, dereference the hive cell */
606 HvReleaseCell(Hive, Cell);
607 return FALSE;
608 }
609
610 /* Free the old reference table and use the new one */
611 if (CellRef->CellArray)
612 {
613 /* Copy the handles from the old table to the new one */
614 RtlCopyMemory(NewCellArray,
615 CellRef->CellArray,
616 CellRef->Max * sizeof(HV_HIVE_CELL_PAIR));
617 CmpFree(CellRef->CellArray, 0); // TAG_CM
618 }
619 CellRef->CellArray = NewCellArray;
620 CellRef->Max += CELL_REF_INCREMENT;
621 }
622
623 // ASSERT(CellRef->Count < CellRef->Max);
624
625 /* Add the reference */
626 CellRef->CellArray[CellRef->Count].Hive = Hive;
627 CellRef->CellArray[CellRef->Count].Cell = Cell;
628 CellRef->Count++;
629 return TRUE;
630}
PVOID NTAPI CmpAllocate(_In_ SIZE_T Size, _In_ BOOLEAN Paged, _In_ ULONG Tag)
Definition: bootreg.c:90
#define CELL_REF_INCREMENT
Definition: hivecell.c:550

Referenced by CmEnumerateKey(), and CmQueryKey().

◆ HvValidateBin()

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 not corrupt and that the cells are consistent with each other.

Parameters
[in]HiveA pointer to a hive descriptor of which a hive bin is to be validated.
[in]BinA pointer to a bin where its cells are to be validated.
Returns
CM_CHECK_REGISTRY_GOOD is returned if the bin is valid and not corrupt. CM_CHECK_REGISTRY_BIN_SIGNATURE_HEADER_CORRUPT is returned if this bin has a corrupt signature. CM_CHECK_REGISTRY_BAD_FREE_CELL is returned if the free cell has a bogus size. CM_CHECK_REGISTRY_BAD_ALLOC_CELL is returned for the allocated cell has a bogus size.

Definition at line 1413 of file cmcheck.c.

1416{
1417 PHCELL Cell, Basket;
1418
1419 PAGED_CODE();
1420
1421 ASSERT(Bin);
1422 ASSERT(Hive);
1423
1424 /* Ensure that this bin we got has valid signature header */
1425 if (Bin->Signature != HV_HBIN_SIGNATURE)
1426 {
1427 DPRINT1("The bin's signature header is corrupt\n");
1429 }
1430
1431 /*
1432 * Walk over all the cells from this bin and
1433 * validate that they're consistent with the bin.
1434 * Namely we want that each cell from this bin doesn't
1435 * have a bogus size.
1436 */
1437 Basket = (PHCELL)((PUCHAR)Bin + Bin->Size);
1438 for (Cell = GET_CELL_BIN(Bin);
1439 Cell < Basket;
1440 Cell = (PHCELL)((PUCHAR)Cell + abs(Cell->Size)))
1441 {
1442 if (IsFreeCell(Cell))
1443 {
1444 /*
1445 * This cell is free, check that
1446 * the size of this cell is not bogus.
1447 */
1448 if (Cell->Size > Bin->Size ||
1449 Cell->Size == 0)
1450 {
1451 /*
1452 * This cell has too much free space that
1453 * exceeds the boundary of the bin size.
1454 * Otherwise the cell doesn't have actual
1455 * free space (aka Size == 0) which is a
1456 * no go for a bin.
1457 */
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",
1459 Cell, Cell->Size, Bin->Size);
1461 }
1462 }
1463 else
1464 {
1465 /*
1466 * This cell is allocated, make sure that
1467 * the size of this cell is not bogus.
1468 */
1469 if (abs(Cell->Size) > Bin->Size)
1470 {
1471 /*
1472 * This cell allocated too much space
1473 * that exceeds the boundary of the
1474 * bin size.
1475 */
1476 DPRINT1("The allocated cell exceeds the bin size (cell 0x%p, cell size %d, bin size %lu)\n",
1477 Cell, abs(Cell->Size), Bin->Size);
1479 }
1480 }
1481 }
1482
1484}
#define GET_CELL_BIN(Bin)
Definition: cmcheck.c:27
#define CM_CHECK_REGISTRY_BAD_FREE_CELL
Definition: cmlib.h:243
#define CM_CHECK_REGISTRY_BAD_ALLOC_CELL
Definition: cmlib.h:244
#define CM_CHECK_REGISTRY_BIN_SIGNATURE_HEADER_CORRUPT
Definition: cmlib.h:242
#define abs(i)
Definition: fconv.c:206
#define IsFreeCell(Cell)
Definition: hivedata.h:360

Referenced by HvValidateHive().

◆ HvValidateHive()

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.

Parameters
[in]HiveA pointer to a hive descriptor where validation on its hive bins is to be performed.
Returns
CM_CHECK_REGISTRY_GOOD is returned if the hive is valid. CM_CHECK_REGISTRY_HIVE_CORRUPT_SIGNATURE is returned if the hive has a corrupted signature. CM_CHECK_REGISTRY_BIN_SIZE_OR_OFFSET_CORRUPT is returned if the captured bin has a bad size. A failure CM status code is returned otherwise.

Definition at line 1505 of file cmcheck.c.

1507{
1508 CM_CHECK_REGISTRY_STATUS CmStatusCode;
1509 ULONG StorageIndex;
1510 ULONG BlockIndex;
1511 ULONG StorageLength;
1512 PHBIN Bin;
1513
1514 PAGED_CODE();
1515
1516 ASSERT(Hive);
1517
1518 /* Is the hive signature valid? */
1519 if (Hive->Signature != HV_HHIVE_SIGNATURE)
1520 {
1521 DPRINT1("Hive's signature corrupted (signature %lu)\n", Hive->Signature);
1523 }
1524
1525 /*
1526 * Now loop each bin in the storage of this
1527 * hive.
1528 */
1529 for (StorageIndex = 0; StorageIndex < Hive->StorageTypeCount; StorageIndex++)
1530 {
1531 /* Get the storage length at this index */
1532 StorageLength = Hive->Storage[StorageIndex].Length;
1533
1534 for (BlockIndex = 0; BlockIndex < StorageLength;)
1535 {
1536 /* Go to the next if this bin does not exist */
1537 if (Hive->Storage[StorageIndex].BlockList[BlockIndex].BinAddress == (ULONG_PTR)NULL)
1538 {
1539 continue;
1540 }
1541
1542 /*
1543 * Capture this bin and ensure that such
1544 * bin is within the offset and the size
1545 * is not bogus.
1546 */
1547 Bin = GET_HHIVE_BIN(Hive, StorageIndex, BlockIndex);
1548 if (Bin->Size > (StorageLength * HBLOCK_SIZE) ||
1549 (Bin->FileOffset / HBLOCK_SIZE) != BlockIndex)
1550 {
1551 DPRINT1("Bin size or offset is corrupt (bin size %lu, file offset %lu, storage length %lu)\n",
1552 Bin->Size, Bin->FileOffset, StorageLength);
1554 }
1555
1556 /* Validate the rest of the bin */
1557 CmStatusCode = HvValidateBin(Hive, Bin);
1558 if (!CM_CHECK_REGISTRY_SUCCESS(CmStatusCode))
1559 {
1560 DPRINT1("This bin is not valid (bin 0x%p)\n", Bin);
1561 return CmStatusCode;
1562 }
1563
1564 /* Go to the next block */
1565 BlockIndex += Bin->Size / HBLOCK_SIZE;
1566 }
1567 }
1568
1570}
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 ...
Definition: cmcheck.c:1413
#define GET_HHIVE_BIN(Hive, StorageIndex, BlockIndex)
Definition: cmcheck.c:26
#define CM_CHECK_REGISTRY_HIVE_CORRUPT_SIGNATURE
Definition: cmlib.h:240
#define CM_CHECK_REGISTRY_BIN_SIZE_OR_OFFSET_CORRUPT
Definition: cmlib.h:241

Referenced by CmCheckRegistry().

◆ HvWriteAlternateHive()

BOOLEAN CMAPI HvWriteAlternateHive ( _In_ PHHIVE  RegistryHive)

Writes data to an alternate registry hive. An alternate hive is usually backed up by a primary hive. This function is tipically used to force write data into the alternate hive if both hives no longer match.

Parameters
[in]RegistryHiveA pointer to a hive descriptor where data is to be written into.
Returns
Returns TRUE if hive writing has succeeded, FALSE otherwise.

Definition at line 634 of file hivewrt.c.

636{
637 ASSERT(!RegistryHive->ReadOnly);
638 ASSERT(RegistryHive->Signature == HV_HHIVE_SIGNATURE);
639 ASSERT(RegistryHive->Alternate);
640
641#if !defined(_BLDR_)
642 /* Update hive header modification time */
643 KeQuerySystemTime(&RegistryHive->BaseBlock->TimeStamp);
644#endif
645
646 /* Update hive file */
647 if (!HvpWriteHive(RegistryHive, FALSE, HFILE_TYPE_ALTERNATE))
648 {
649 DPRINT1("Failed to write the alternate hive\n");
650 return FALSE;
651 }
652
653 return TRUE;
654}
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
#define HFILE_TYPE_ALTERNATE
Definition: hivedata.h:36

Referenced by _Function_class_().

◆ HvWriteHive()

BOOLEAN CMAPI HvWriteHive ( PHHIVE  RegistryHive)

Variable Documentation

◆ CmlibTraceLevel

ULONG CmlibTraceLevel
extern

Definition at line 12 of file cminit.c.