You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3120 lines
89 KiB
3120 lines
89 KiB
/*++
|
|
|
|
Copyright (c) 1991 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
cmp.h
|
|
|
|
Abstract:
|
|
|
|
This module contains the private (internal) header file for the
|
|
configuration manager.
|
|
|
|
Author:
|
|
|
|
Bryan M. Willman (bryanwi) 10-Sep-91
|
|
|
|
Environment:
|
|
|
|
Kernel mode only.
|
|
|
|
Revision History:
|
|
|
|
13-Jan-99 Dragos C. Sambotin (dragoss) - factoring the data structure declarations
|
|
in \nt\private\ntos\inc\cmdata.h :: to be available from outside.
|
|
--*/
|
|
|
|
#ifndef _CMP_
|
|
#define _CMP_
|
|
|
|
#pragma warning(disable:4214) // bit field types other than int
|
|
#pragma warning(disable:4201) // nameless struct/union
|
|
#pragma warning(disable:4324) // alignment sensitive to declspec
|
|
#pragma warning(disable:4127) // condition expression is constant
|
|
#pragma warning(disable:4115) // named type definition in parentheses
|
|
#pragma warning(disable:4706) // assignment within conditional expression
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Begin SCS (Switch Control Section)
|
|
//
|
|
// 1. Code to check consistency and to help catch bugs: To be turned on when problems
|
|
// appear in that area; Word of caution: some of these switches may affect performance
|
|
//
|
|
#if DBG
|
|
|
|
#define CMP_NOTIFY_POSTBLOCK_CHECK // controls the CmpCheckPostBlock macro, used to check
|
|
// validity and consistency of a notify post block
|
|
|
|
|
|
#define CMP_ENTRYLIST_MANIPULATION // controls the removal of an element from a LIST_ENTRY
|
|
// by setting the Blink and Flink to NULL;
|
|
// macros affected : IsListEmpty and RemoveEmptyList
|
|
// WARNING : to be defined only when not linking against the loader
|
|
|
|
#define CMP_KCB_CACHE_VALIDATION // validates KCB cached members changes by comparing against the knode values.
|
|
// We shall disable this after proven the caching mechanism works OK
|
|
|
|
//#define CMP_CMVIEW_VALIDATION // validates the view mapping mechanism
|
|
|
|
#define CHECK_REGISTRY_USECOUNT // Validates the GetCell/ReleaseCell call matching, to ensure mapped views
|
|
// don't get unmapped while in use
|
|
|
|
//#define SYNC_HIVE_VALIDATION // validate the HvpDoWriteHive paged dirty data algorithm
|
|
// We shall disable this after we catch saving alternate problem
|
|
|
|
//#define HIVE_SECURITY_STATS // collect statistics about security cells
|
|
|
|
//#define CMP_STATS // collect statistics about kcbs
|
|
|
|
//#define WRITE_PROTECTED_REGISTRY_POOL // applies only for registry hives stored in paged pool
|
|
// controls access over registry bins
|
|
|
|
//#define WRITE_PROTECTED_VALUE_CACHE // protects pool allocations used for kcb value cache
|
|
|
|
//#define DRAGOSS_PRIVATE_DEBUG // private debug session
|
|
|
|
//#define CM_CHECK_MAP_NO_READ_SCHEME // validates the mapping code assumption (i.e. each bin map should start
|
|
// with HMAP_NEW_ALLOC; this is true only for mapped bins
|
|
|
|
#define REGISTRY_LOCK_CHECKING // on each Nt API level call, checks the thread has released all locks
|
|
// acquired. We may want to remove it, as it can hide bugs in other components
|
|
// below registry (Ob, Se, Ps, Mm)
|
|
|
|
//#define CM_PERF_ISSUES // keep track of how long CmpInitializeHiveList and CmpConvertHiveToMapped takes
|
|
|
|
|
|
#define CM_CHECK_FOR_ORPHANED_KCBS // check for orphaned kcbs every time we free a hive.
|
|
|
|
#endif //DBG
|
|
|
|
//#define CM_RETRY_CREATE_FILE // when an error is returned from ZwCreateFile calls, retry the call
|
|
|
|
//#define CM_NOTIFY_CHANGED_KCB_FULLPATH // return the full qualified path of the changed kcb in the Buffer arg of NtNotifyChangeKey
|
|
|
|
#if defined(_X86_)
|
|
#define CM_LEAK_STACK_TRACES // keeps stacks traces for opened handles
|
|
#endif //_X86_
|
|
|
|
//
|
|
// 2. these section controls whether or not a certain feature goes into product or not;
|
|
// The goal is to remove these switches as new features are accepted, tested and proven to work
|
|
//
|
|
#ifndef _CM_LDR_
|
|
|
|
#define NT_RENAME_KEY // NtRenameKey API
|
|
|
|
#define NT_UNLOAD_KEY_EX // NtUnloadKeyEx API
|
|
|
|
#endif //_CM_LDR_
|
|
|
|
#define CM_ENABLE_MAPPED_VIEWS // controls whether the mapped views feature (using Cc interfaces) is used
|
|
// by commenting this, registry hives are reverted to paged pool
|
|
// WARNING: This should be always on !!!
|
|
|
|
//#define CM_ENABLE_WRITE_ONLY_BINS // use MmSetPageProtection to catch writes on data not marked dirty
|
|
|
|
#define CM_MAP_NO_READ // this switch contols whether we map (touch all pages) or just pin_no_read
|
|
// now it makes sense to use this as mm will fault in one page at a time for
|
|
// MNW streams
|
|
|
|
#define CM_BREAK_ON_KEY_OPEN // breaks when a key with Flags & KEY_BREAK_ON_OPEN is opened or a subkey is added
|
|
|
|
//#define CM_SAVE_KCB_CACHE // at shutdown, save the kcb cache into a file
|
|
|
|
//#define CM_DYN_SYM_LINK // dynamic symbolic links enabled.
|
|
|
|
//#define HV_TRACK_FREE_SPACE // keep track of the actual free space inside the hive
|
|
|
|
//#define CM_TRACK_QUOTA_LEAKS //captures stack traces at every CmpAllocateXXX
|
|
|
|
//
|
|
// End SCS
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#ifdef CM_DYN_SYM_LINK
|
|
#define REG_DYN_LINK 21 // this should be moved to the proper place
|
|
#endif
|
|
|
|
|
|
#include "ntos.h"
|
|
#include "hive.h"
|
|
#include "wchar.h"
|
|
#include "zwapi.h"
|
|
#include <stdio.h>
|
|
#include <profiles.h>
|
|
|
|
// bugcheck description and defines
|
|
#include "cmpbug.h"
|
|
|
|
#include "kddll.h"
|
|
|
|
// CM data structure declarations
|
|
// file location: \nt\private\ntos\inc
|
|
#include "cmdata.h"
|
|
|
|
|
|
#ifdef CMP_STATS
|
|
VOID
|
|
CmpKcbStat(
|
|
VOID
|
|
);
|
|
#endif
|
|
|
|
#ifndef _CM_LDR_
|
|
#define CmKdPrintEx(_x_) KdPrintEx(_x_)
|
|
#else
|
|
#define CmKdPrintEx(_x_) //nothing
|
|
#endif //_CM_LDR_
|
|
|
|
|
|
#define _64K 64L*1024L //64K
|
|
#define _256K 256L*1024L //256K
|
|
|
|
#define IO_BUFFER_SIZE _64K //64K
|
|
|
|
//
|
|
// this constant defines the size of a Cc view that is mapped -in every time a cell
|
|
// is accessed; It can be any power of 2, no less than 16K and no bigger than 256K
|
|
//
|
|
#define CM_VIEW_SIZE 16L*1024L //16K
|
|
|
|
//
|
|
// control the granularity the primary file grows;
|
|
// Warning: this should be multiple of 4K (HBLOCK_SIZE) !!!
|
|
//
|
|
#define CM_FILE_GROW_INCREMENT 256L*1024L //256K
|
|
|
|
//
|
|
// this controls the maximmum adress space allowed per hive. It should be specified in
|
|
// multiples of 256K
|
|
//
|
|
// 4 means 1 MB
|
|
// 6 means 1.5 MB
|
|
// 12 means 3 MB
|
|
// .....
|
|
//
|
|
#define MAX_MB_PER_HIVE 16 // 4MB
|
|
|
|
|
|
#define MAX_NAME 128
|
|
|
|
#ifdef CMP_ENTRYLIST_MANIPULATION
|
|
#define CmpRemoveEntryList(a) \
|
|
if(((a)->Flink == NULL) && ((a)->Blink == NULL) ) {\
|
|
DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"CmpRemoveEntryList: Entry %08lx\n",a);\
|
|
DbgBreakPoint();\
|
|
}\
|
|
RemoveEntryList(a);\
|
|
(a)->Flink = (a)->Blink = NULL
|
|
|
|
#define CmpClearListEntry(a) (a)->Flink = (a)->Blink = NULL
|
|
|
|
#define CmpIsListEmpty(a) ( ( ((a)->Flink == NULL) && ((a)->Blink == NULL) ) || ( ((a)->Flink != NULL) && ((a)->Blink != NULL) && IsListEmpty(a) ) )
|
|
|
|
#else
|
|
#define CmpRemoveEntryList(a) RemoveEntryList(a)
|
|
#define CmpClearListEntry(a) //nothing
|
|
#define CmpIsListEmpty(a) IsListEmpty(a)
|
|
#endif // CMP_ENTRYLIST_MANIPULATION
|
|
|
|
|
|
extern PCM_TRACE_NOTIFY_ROUTINE CmpTraceRoutine;
|
|
|
|
VOID
|
|
CmpWmiDumpKcb(
|
|
PCM_KEY_CONTROL_BLOCK kcb
|
|
);
|
|
|
|
#define CmpWmiFireEvent(Status,Kcb,ElapsedTime,Index,KeyName,Type) \
|
|
{ \
|
|
PCM_TRACE_NOTIFY_ROUTINE TraceRoutine = CmpTraceRoutine; \
|
|
if( TraceRoutine != NULL ) { \
|
|
(*TraceRoutine)(Status,Kcb,ElapsedTime,Index,KeyName,Type); \
|
|
} \
|
|
}
|
|
|
|
#define StartWmiCmTrace()\
|
|
LARGE_INTEGER StartSystemTime = {0};\
|
|
LARGE_INTEGER EndSystemTime;\
|
|
PVOID HookKcb = NULL;\
|
|
if (CmpTraceRoutine) {\
|
|
PerfTimeStamp(StartSystemTime); \
|
|
}
|
|
|
|
|
|
#define EndWmiCmTrace(Status,Index,KeyName,Type)\
|
|
if (CmpTraceRoutine) {\
|
|
PerfTimeStamp(EndSystemTime); \
|
|
CmpWmiFireEvent(Status,HookKcb,EndSystemTime.QuadPart - StartSystemTime.QuadPart,Index,KeyName,Type);\
|
|
}
|
|
|
|
#define HookKcbForWmiCmTrace(KeyBody) \
|
|
if (CmpTraceRoutine) {\
|
|
if(KeyBody) {\
|
|
HookKcb = KeyBody->KeyControlBlock;\
|
|
}\
|
|
}
|
|
|
|
#define HookKcbFromHandleForWmiCmTrace(KeyHandle) \
|
|
if (CmpTraceRoutine && (KeyHandle)) {\
|
|
PCM_KEY_BODY KeyBody;\
|
|
NTSTATUS status;\
|
|
status = ObReferenceObjectByHandle(\
|
|
KeyHandle,\
|
|
0,\
|
|
CmpKeyObjectType,\
|
|
KeGetPreviousMode(),\
|
|
(PVOID *)(&KeyBody),\
|
|
NULL\
|
|
);\
|
|
if (NT_SUCCESS(status)) {\
|
|
HookKcb = KeyBody->KeyControlBlock;\
|
|
ObDereferenceObject((PVOID)KeyBody);\
|
|
}\
|
|
}
|
|
|
|
#define CmpTraceKcbCreate(kcb) \
|
|
if (CmpTraceRoutine) {\
|
|
CmpWmiDumpKcb(kcb);\
|
|
}
|
|
|
|
#ifdef WRITE_PROTECTED_VALUE_CACHE
|
|
|
|
#define CmpMakeSpecialPoolReadOnly(PoolAddress) \
|
|
{ \
|
|
if( !MmProtectSpecialPool( (PVOID) PoolAddress, PAGE_READONLY) ) \
|
|
CmKdPrintEx((DPFLTR_CONFIG_ID,CML_POOL,"[CmpMakeSpecialPoolReadOnly]: Failed to Mark SpecialPool %p as ReadOnly", PoolAddress )); \
|
|
}
|
|
|
|
#define CmpMakeSpecialPoolReadWrite(PoolAddress) \
|
|
{ \
|
|
if( !MmProtectSpecialPool( (PVOID) PoolAddress, PAGE_READWRITE) ) { \
|
|
CmKdPrintEx((DPFLTR_CONFIG_ID,CML_POOL,"[CmpMakeSpecialPoolReadWrite]: Failed to Mark SpecialPool %p as ReadWrite", PoolAddress )); \
|
|
} \
|
|
}
|
|
#define CmpMakeValueCacheReadOnly(ValueCached,PoolAddress) \
|
|
if(ValueCached) { \
|
|
CmpMakeSpecialPoolReadOnly( PoolAddress );\
|
|
}
|
|
|
|
#define CmpMakeValueCacheReadWrite(ValueCached,PoolAddress) \
|
|
if(ValueCached) { \
|
|
CmpMakeSpecialPoolReadWrite( PoolAddress );\
|
|
}
|
|
|
|
#else
|
|
#define CmpMakeSpecialPoolReadOnly(a) //nothing
|
|
#define CmpMakeSpecialPoolReadWrite(a) //nothing
|
|
#define CmpMakeValueCacheReadOnly(a,b) //nothing
|
|
#define CmpMakeValueCacheReadWrite(a,b) //nothing
|
|
#endif
|
|
|
|
#ifdef WRITE_PROTECTED_REGISTRY_POOL
|
|
|
|
VOID
|
|
HvpMarkBinReadWrite(
|
|
PHHIVE Hive,
|
|
HCELL_INDEX Cell
|
|
);
|
|
|
|
VOID
|
|
HvpChangeBinAllocation(
|
|
PHBIN Bin,
|
|
BOOLEAN ReadOnly
|
|
);
|
|
|
|
VOID
|
|
CmpMarkAllBinsReadOnly(
|
|
PHHIVE Hive
|
|
);
|
|
|
|
#else
|
|
#define HvpChangeBinAllocation(a,b) //nothing
|
|
#define HvpMarkBinReadWrite(a,b) //nothing
|
|
#define CmpMarkAllBinsReadOnly(a) //nothing
|
|
#endif
|
|
|
|
#ifdef POOL_TAGGING
|
|
//
|
|
// Pool Tag
|
|
//
|
|
#define CM_POOL_TAG ' MC'
|
|
#define CM_KCB_TAG 'bkMC'
|
|
#define CM_POSTBLOCK_TAG 'bpMC'
|
|
#define CM_NOTIFYBLOCK_TAG 'bnMC'
|
|
#define CM_POSTEVENT_TAG 'epMC'
|
|
#define CM_POSTAPC_TAG 'apMC'
|
|
#define CM_MAPPEDVIEW_TAG 'wVMC'
|
|
#define CM_SECCACHE_TAG 'cSMC'
|
|
#define CM_DELAYCLOSE_TAG 'cDMC'
|
|
#define CM_STASHBUFFER_TAG 'bSMC'
|
|
#define CM_HVBIN_TAG 'bHMC'
|
|
#define CM_ALLOCATE_TAG 'lAMC'
|
|
|
|
//
|
|
// Find leaks
|
|
//
|
|
#define CM_FIND_LEAK_TAG1 ' 1MC'
|
|
#define CM_FIND_LEAK_TAG2 ' 2MC'
|
|
#define CM_FIND_LEAK_TAG3 ' 3MC'
|
|
#define CM_FIND_LEAK_TAG4 ' 4MC'
|
|
#define CM_FIND_LEAK_TAG5 ' 5MC'
|
|
#define CM_FIND_LEAK_TAG6 ' 6MC'
|
|
#define CM_FIND_LEAK_TAG7 ' 7MC'
|
|
#define CM_FIND_LEAK_TAG8 ' 8MC'
|
|
#define CM_FIND_LEAK_TAG9 ' 9MC'
|
|
#define CM_FIND_LEAK_TAG10 '01MC'
|
|
#define CM_FIND_LEAK_TAG11 '11MC'
|
|
#define CM_FIND_LEAK_TAG12 '21MC'
|
|
#define CM_FIND_LEAK_TAG13 '31MC'
|
|
#define CM_FIND_LEAK_TAG14 '41MC'
|
|
#define CM_FIND_LEAK_TAG15 '51MC'
|
|
#define CM_FIND_LEAK_TAG16 '61MC'
|
|
#define CM_FIND_LEAK_TAG17 '71MC'
|
|
#define CM_FIND_LEAK_TAG18 '81MC'
|
|
#define CM_FIND_LEAK_TAG19 '91MC'
|
|
#define CM_FIND_LEAK_TAG20 '02MC'
|
|
#define CM_FIND_LEAK_TAG21 '12MC'
|
|
#define CM_FIND_LEAK_TAG22 '22MC'
|
|
#define CM_FIND_LEAK_TAG23 '32MC'
|
|
#define CM_FIND_LEAK_TAG24 '42MC'
|
|
#define CM_FIND_LEAK_TAG25 '52MC'
|
|
#define CM_FIND_LEAK_TAG26 '62MC'
|
|
#define CM_FIND_LEAK_TAG27 '72MC'
|
|
#define CM_FIND_LEAK_TAG28 '82MC'
|
|
#define CM_FIND_LEAK_TAG29 '92MC'
|
|
#define CM_FIND_LEAK_TAG30 '03MC'
|
|
#define CM_FIND_LEAK_TAG31 '13MC'
|
|
#define CM_FIND_LEAK_TAG32 '23MC'
|
|
#define CM_FIND_LEAK_TAG33 '33MC'
|
|
#define CM_FIND_LEAK_TAG34 '43MC'
|
|
#define CM_FIND_LEAK_TAG35 '53MC'
|
|
#define CM_FIND_LEAK_TAG36 '63MC'
|
|
#define CM_FIND_LEAK_TAG37 '73MC'
|
|
#define CM_FIND_LEAK_TAG38 '83MC'
|
|
#define CM_FIND_LEAK_TAG39 '93MC'
|
|
#define CM_FIND_LEAK_TAG40 '04MC'
|
|
#define CM_FIND_LEAK_TAG41 '14MC'
|
|
#define CM_FIND_LEAK_TAG42 '24MC'
|
|
#define CM_FIND_LEAK_TAG43 '34MC'
|
|
#define CM_FIND_LEAK_TAG44 '44MC'
|
|
#define CM_FIND_LEAK_TAG45 '54MC'
|
|
|
|
#ifdef _WANT_MACHINE_IDENTIFICATION
|
|
|
|
#define CM_PARSEINI_TAG 'ipMC'
|
|
#define CM_GENINST_TAG 'igMC'
|
|
|
|
#endif
|
|
|
|
//
|
|
// Extra Tags for cache.
|
|
// We may want to merge these tags later.
|
|
//
|
|
#define CM_CACHE_VALUE_INDEX_TAG 'IVMC'
|
|
#define CM_CACHE_VALUE_TAG 'aVMC'
|
|
#define CM_CACHE_INDEX_TAG 'nIMC'
|
|
#define CM_CACHE_VALUE_DATA_TAG 'aDMC'
|
|
#define CM_NAME_TAG 'bNMC'
|
|
|
|
|
|
#define ExAllocatePool(a,b) ExAllocatePoolWithTag(a,b,CM_POOL_TAG)
|
|
#define ExAllocatePoolWithQuota(a,b) ExAllocatePoolWithQuotaTag(a,b,CM_POOL_TAG)
|
|
|
|
PVOID
|
|
CmpAllocateTag(
|
|
ULONG Size,
|
|
BOOLEAN UseForIo,
|
|
ULONG Tag
|
|
);
|
|
#else
|
|
#define CmpAllocateTag(a,b,c) CmpAllocate(a,b,c)
|
|
#endif
|
|
|
|
#define CmRetryExAllocatePoolWithTag(a,b,c,Result) \
|
|
{ \
|
|
ULONG RetryCount = 10; \
|
|
do { \
|
|
Result = ExAllocatePoolWithTag(a,b,c); \
|
|
} while ((!Result) && (RetryCount--)); \
|
|
}
|
|
|
|
|
|
//
|
|
// A variable so can turn on/off certain performance features.
|
|
//
|
|
extern const ULONG CmpCacheOnFlag;
|
|
|
|
#define CM_CACHE_FAKE_KEY 0x00000001 // Create Fake key KCB
|
|
|
|
//
|
|
// This lock protects the KCB cache, including the KCB structures,
|
|
// NameBlock and Value Index.
|
|
//
|
|
|
|
#define MAX_KCB_LOCKS 1024
|
|
extern EX_PUSH_LOCK CmpKcbLock;
|
|
extern PKTHREAD CmpKcbOwner;
|
|
extern EX_PUSH_LOCK CmpKcbLocks[MAX_KCB_LOCKS];
|
|
|
|
//
|
|
// This is \REGISTRY
|
|
//
|
|
extern HANDLE CmpRegistryRootHandle;
|
|
|
|
VOID
|
|
CmpLockKCBTreeExclusive(
|
|
VOID
|
|
);
|
|
VOID
|
|
CmpLockKCBTree(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
CmpUnlockKCBTree(
|
|
);
|
|
|
|
VOID
|
|
CmpLockKCB(
|
|
PCM_KEY_CONTROL_BLOCK Kcb
|
|
);
|
|
|
|
VOID
|
|
CmpUnlockKCB(
|
|
PCM_KEY_CONTROL_BLOCK Kcb
|
|
);
|
|
|
|
//
|
|
// Logging: remember, first 4 levels (0-3) are reserved system-wide
|
|
//
|
|
#define CML_BUGCHECK 4 // fatal errors
|
|
#define CML_EXCEPTION 5 // all exception's
|
|
#define CML_NTAPI 6 // NtApi calls
|
|
#define CML_NTAPI_ARGS 7 // NtApi parameters
|
|
#define CML_CM 8 // Cm level, general
|
|
#define CML_NOTIFY 9 // Notify level, general
|
|
#define CML_HIVE 10 // Hv level, general
|
|
#define CML_IO 11 // IO level
|
|
#define CML_SEC 12 // Security level
|
|
#define CML_INIT 13 // Init level, general
|
|
#define CML_INDEX 14 // Index level, general
|
|
#define CML_BIN_MAP 15 // bin mapping level
|
|
#define CML_FREECELL 16 // Free cell hints
|
|
#define CML_POOL 17 // Pool
|
|
#define CML_LOCKING 18 // Lock/unlock level
|
|
#define CML_FLOW 19 // General flow
|
|
#define CML_PARSE 20 // Parse algorithm
|
|
#define CML_SAVRES 21 // SavRes operations
|
|
|
|
|
|
#define REGCHECKING 1
|
|
|
|
#if DBG
|
|
|
|
#if REGCHECKING
|
|
#define DCmCheckRegistry(a) if(HvHiveChecking) ASSERT(CmCheckRegistry(a, CM_CHECK_REGISTRY_HIVE_CHECK) == 0)
|
|
#else
|
|
#define DCmCheckRegistry(a)
|
|
#endif
|
|
|
|
#else
|
|
#define DCmCheckRegistry(a)
|
|
#endif
|
|
|
|
#ifdef CHECK_REGISTRY_USECOUNT
|
|
VOID
|
|
CmpCheckRegistryUseCount( );
|
|
#endif //CHECK_REGISTRY_USECOUNT
|
|
|
|
#ifdef REGISTRY_LOCK_CHECKING
|
|
ULONG
|
|
CmpCheckLockExceptionFilter(
|
|
IN PEXCEPTION_POINTERS ExceptionPointers
|
|
);
|
|
|
|
//
|
|
// updated to check both registry and kcb
|
|
//
|
|
#define BEGIN_LOCK_CHECKPOINT \
|
|
{ \
|
|
ULONG RegistryLockCountBefore,RegistryLockCountAfter; \
|
|
RegistryLockCountBefore = ExIsResourceAcquiredShared(&CmpRegistryLock); \
|
|
RegistryLockCountBefore += ExIsResourceAcquiredExclusive(&CmpRegistryLock); \
|
|
try {
|
|
|
|
#define END_LOCK_CHECKPOINT \
|
|
} except(CmpCheckLockExceptionFilter(GetExceptionInformation())) {} \
|
|
RegistryLockCountAfter = ExIsResourceAcquiredShared(&CmpRegistryLock); \
|
|
RegistryLockCountAfter += ExIsResourceAcquiredExclusive(&CmpRegistryLock); \
|
|
if( RegistryLockCountBefore != RegistryLockCountAfter ) { \
|
|
CM_BUGCHECK(REGISTRY_ERROR,REGISTRY_LOCK_CHECKPOINT,0,RegistryLockCountBefore,RegistryLockCountAfter); \
|
|
} \
|
|
}
|
|
|
|
|
|
#define BEGIN_KCB_LOCK_GUARD \
|
|
try {
|
|
|
|
#define END_KCB_LOCK_GUARD \
|
|
} except(CmpCheckLockExceptionFilter(GetExceptionInformation())) {}
|
|
|
|
#else
|
|
#define BEGIN_LOCK_CHECKPOINT
|
|
#define END_LOCK_CHECKPOINT
|
|
#define BEGIN_KCB_LOCK_GUARD
|
|
#define END_KCB_LOCK_GUARD
|
|
#endif //REGISTRY_LOCK_CHECKING
|
|
|
|
extern BOOLEAN CmpSpecialBootCondition;
|
|
|
|
#if DBG
|
|
#define ASSERT_CM_LOCK_OWNED() \
|
|
ASSERT( (CmpSpecialBootCondition == TRUE) || (CmpTestRegistryLock() == TRUE) )
|
|
#define ASSERT_CM_LOCK_OWNED_EXCLUSIVE() \
|
|
ASSERT((CmpSpecialBootCondition == TRUE) || (CmpTestRegistryLockExclusive() == TRUE) )
|
|
#define ASSERT_CM_EXCLUSIVE_HIVE_ACCESS(Hive) \
|
|
ASSERT((CmpSpecialBootCondition == TRUE) || (CmpTestRegistryLockExclusive() == TRUE) || (Hive->ReleaseCellRoutine == NULL) )
|
|
#define ASSERT_KCB_LOCK_OWNED_EXCLUSIVE() \
|
|
ASSERT( (CmpTestKCBTreeLockExclusive() == TRUE) || (CmpSpecialBootCondition == TRUE) || (CmpTestRegistryLockExclusive() == TRUE) )
|
|
#else
|
|
#define ASSERT_CM_LOCK_OWNED()
|
|
#define ASSERT_CM_LOCK_OWNED_EXCLUSIVE()
|
|
#define ASSERT_CM_EXCLUSIVE_HIVE_ACCESS(Hive)
|
|
#define ASSERT_KCB_LOCK_OWNED_EXCLUSIVE()
|
|
#endif
|
|
|
|
#if DBG
|
|
#ifndef _CM_LDR_
|
|
#define ASSERT_PASSIVE_LEVEL() \
|
|
{ \
|
|
KIRQL Irql; \
|
|
Irql = KeGetCurrentIrql(); \
|
|
if( KeGetCurrentIrql() != PASSIVE_LEVEL ) { \
|
|
DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"ASSERT_PASSIVE_LEVEL failed ... Irql = %lu\n",Irql); \
|
|
ASSERT( FALSE ); \
|
|
} \
|
|
}
|
|
#endif //_CM_LDR_
|
|
#else
|
|
#define ASSERT_PASSIVE_LEVEL()
|
|
#endif
|
|
|
|
#define VALIDATE_CELL_MAP(LINE,Map,Hive,Address) \
|
|
if( Map == NULL ) { \
|
|
CM_BUGCHECK (REGISTRY_ERROR,BAD_CELL_MAP,(ULONG_PTR)(Hive),(ULONG)(Address),(ULONG)(LINE)) ; \
|
|
}
|
|
|
|
#if DBG
|
|
VOID
|
|
SepDumpSecurityDescriptor(
|
|
IN PSECURITY_DESCRIPTOR SecurityDescriptor,
|
|
IN PSZ TitleString
|
|
);
|
|
|
|
extern BOOLEAN SepDumpSD;
|
|
|
|
#define CmpDumpSecurityDescriptor(x,y) \
|
|
{ \
|
|
SepDumpSD=TRUE; \
|
|
SepDumpSecurityDescriptor(x, y); \
|
|
SepDumpSD=FALSE; \
|
|
}
|
|
#else
|
|
|
|
#define CmpDumpSecurityDescriptor(x,y)
|
|
|
|
#endif
|
|
|
|
|
|
//
|
|
// misc stuff
|
|
//
|
|
|
|
extern UNICODE_STRING CmRegistrySystemCloneName;
|
|
|
|
//
|
|
// Determines whether the Current Control Set used during booting
|
|
// is cloned in order to fully preserve it for being saved
|
|
// as the LKG Control Set.
|
|
//
|
|
|
|
#define CLONE_CONTROL_SET FALSE
|
|
|
|
#if CLONE_CONTROL_SET
|
|
#define CM_NUMBER_OF_MACHINE_HIVES 7
|
|
#else
|
|
#define CM_NUMBER_OF_MACHINE_HIVES 6
|
|
#endif
|
|
|
|
#define NUMBER_TYPES (MaximumType + 1)
|
|
|
|
#define CM_WRAP_LIMIT 0x7fffffff
|
|
|
|
|
|
//
|
|
// Tuning and control constants
|
|
//
|
|
#define CM_MAX_STASH 1024*1024 // If size of data for a set
|
|
// is bigger than this,
|
|
|
|
#define CM_MAX_REASONABLE_VALUES 100 // If number of values for a
|
|
// key is greater than this,
|
|
// round up value list size
|
|
|
|
|
|
//
|
|
// Limit on the number of layers of hive there may be. We allow only
|
|
// the master hive and hives directly linked into it for now, for currently
|
|
// value is always 2..
|
|
//
|
|
|
|
#define MAX_HIVE_LAYERS 2
|
|
|
|
|
|
//
|
|
// structure used to create and sort ordered list of drivers to be loaded.
|
|
// This is also used by the OS Loader when loading the boot drivers.
|
|
// (Particularly the ErrorControl field)
|
|
//
|
|
|
|
typedef struct _BOOT_DRIVER_NODE {
|
|
BOOT_DRIVER_LIST_ENTRY ListEntry;
|
|
UNICODE_STRING Group;
|
|
UNICODE_STRING Name;
|
|
ULONG Tag;
|
|
ULONG ErrorControl;
|
|
} BOOT_DRIVER_NODE, *PBOOT_DRIVER_NODE;
|
|
|
|
//
|
|
// extern for object type pointer
|
|
//
|
|
|
|
extern POBJECT_TYPE CmpKeyObjectType;
|
|
extern POBJECT_TYPE IoFileObjectType;
|
|
|
|
//
|
|
// indexes in CmpMachineHiveList
|
|
//
|
|
#define SYSTEM_HIVE_INDEX 3
|
|
#define CLONE_HIVE_INDEX 6
|
|
|
|
//
|
|
// Miscelaneous Hash routines
|
|
//
|
|
#define RNDM_CONSTANT 314159269 /* default value for "scrambling constant" */
|
|
#define RNDM_PRIME 1000000007 /* prime number, also used for scrambling */
|
|
|
|
#define HASH_KEY(_convkey_) ((RNDM_CONSTANT * (_convkey_)) % RNDM_PRIME)
|
|
|
|
#define GET_HASH_INDEX(Key) HASH_KEY(Key) % CmpHashTableSize
|
|
#define GET_HASH_ENTRY(Table, Key) Table[GET_HASH_INDEX(Key)]
|
|
|
|
//
|
|
// CM_KEY_BODY
|
|
//
|
|
// Same structure used for KEY_ROOT and KEY objects. This is the
|
|
// Cm defined part of the object.
|
|
//
|
|
// This object represents an open instance, several of them could refer
|
|
// to a single key control block.
|
|
//
|
|
#define KEY_BODY_TYPE 0x6b793032 // "ky02"
|
|
|
|
struct _CM_NOTIFY_BLOCK; //forward
|
|
|
|
typedef struct _CM_KEY_BODY {
|
|
ULONG Type;
|
|
PCM_KEY_CONTROL_BLOCK KeyControlBlock;
|
|
struct _CM_NOTIFY_BLOCK *NotifyBlock;
|
|
HANDLE ProcessID; // the owner process
|
|
|
|
#ifdef CM_LEAK_STACK_TRACES
|
|
ULONG Callers;
|
|
PVOID CallerAddress[10];
|
|
#endif //CM_LEAK_STACK_TRACES
|
|
|
|
LIST_ENTRY KeyBodyList; // key_nodes using the same kcb
|
|
} CM_KEY_BODY, *PCM_KEY_BODY;
|
|
|
|
#ifdef CM_LEAK_STACK_TRACES
|
|
// just because we need this #define code inside a macro !
|
|
#define CmpSetNoCallers(KeyBody) KeyBody->Callers = 0
|
|
|
|
#define CmpAddKeyTracker(KeyHandle,mode) \
|
|
if(PoCleanShutdownEnabled() & PO_CLEAN_SHUTDOWN_REGISTRY) { \
|
|
PCM_KEY_BODY KeyBody; \
|
|
NTSTATUS status; \
|
|
status = ObReferenceObjectByHandle( \
|
|
KeyHandle, \
|
|
0, \
|
|
CmpKeyObjectType, \
|
|
mode, \
|
|
(PVOID *)(&KeyBody), \
|
|
NULL \
|
|
); \
|
|
if( NT_SUCCESS(status) ) { \
|
|
KeyBody->Callers = RtlWalkFrameChain(&(KeyBody->CallerAddress[0]), 10, 0); \
|
|
ObDereferenceObject((PVOID)KeyBody); \
|
|
} \
|
|
}
|
|
#else
|
|
#define CmpSetNoCallers(KeyBody) // nothing
|
|
#define CmpAddKeyTracker(KeyHandle,mode) // nothing yet
|
|
#endif //CM_LEAK_STACK_TRACES
|
|
|
|
|
|
#define INIT_KCB_KEYBODY_LIST(kcb) InitializeListHead(&(kcb->KeyBodyListHead))
|
|
|
|
#define ASSERT_KEYBODY_LIST_EMPTY(kcb) ASSERT(IsListEmpty(&(kcb->KeyBodyListHead)) == TRUE)
|
|
|
|
#define ENLIST_KEYBODY_IN_KEYBODY_LIST(KeyBody) \
|
|
ASSERT( KeyBody->KeyControlBlock != NULL ); \
|
|
BEGIN_KCB_LOCK_GUARD; \
|
|
CmpLockKCBTree(); \
|
|
CmpLockKCB(KeyBody->KeyControlBlock); \
|
|
InsertTailList(&(KeyBody->KeyControlBlock->KeyBodyListHead),&(KeyBody->KeyBodyList)); \
|
|
CmpSetNoCallers(KeyBody); \
|
|
CmpUnlockKCB(KeyBody->KeyControlBlock); \
|
|
CmpUnlockKCBTree(); \
|
|
END_KCB_LOCK_GUARD
|
|
|
|
#define DELIST_KEYBODY_FROM_KEYBODY_LIST(KeyBody) \
|
|
ASSERT( KeyBody->KeyControlBlock != NULL ); \
|
|
ASSERT(IsListEmpty(&(KeyBody->KeyControlBlock->KeyBodyListHead)) == FALSE); \
|
|
BEGIN_KCB_LOCK_GUARD; \
|
|
CmpLockKCBTree(); \
|
|
CmpLockKCB(KeyBody->KeyControlBlock); \
|
|
RemoveEntryList(&(KeyBody->KeyBodyList)); \
|
|
CmpUnlockKCB(KeyBody->KeyControlBlock); \
|
|
CmpUnlockKCBTree(); \
|
|
END_KCB_LOCK_GUARD
|
|
|
|
|
|
#define ASSERT_KEY_OBJECT(x) ASSERT(((PCM_KEY_BODY)x)->Type == KEY_BODY_TYPE)
|
|
#define ASSERT_NODE(x) ASSERT(((PCM_KEY_NODE)x)->Signature == CM_KEY_NODE_SIGNATURE)
|
|
#define ASSERT_SECURITY(x) ASSERT(((PCM_KEY_SECURITY)x)->Signature == CM_KEY_SECURITY_SIGNATURE)
|
|
|
|
//
|
|
// CM_POST_KEY_BODY
|
|
//
|
|
// A post block can have attached a keybody which has to be dereferenced
|
|
// when the post block goes out of scope. This structure allows the
|
|
// implementation of keybody "delayed dereferencing". (see CmpPostNotify for comments)
|
|
//
|
|
|
|
typedef struct _CM_POST_KEY_BODY {
|
|
LIST_ENTRY KeyBodyList;
|
|
struct _CM_KEY_BODY *KeyBody; // this key body object
|
|
} CM_POST_KEY_BODY, *PCM_POST_KEY_BODY;
|
|
|
|
|
|
//
|
|
// CM_NOTIFY_BLOCK
|
|
//
|
|
// A notify block tracks an active notification waiting for notification.
|
|
// Any one open instance (CM_KEY_BODY) will refer to at most one
|
|
// notify block. A given key control block may have as many notify
|
|
// blocks refering to it as there are CM_KEY_BODYs refering to it.
|
|
// Notify blocks are attached to hives and sorted by length of name.
|
|
//
|
|
|
|
typedef struct _CM_NOTIFY_BLOCK {
|
|
LIST_ENTRY HiveList; // sorted list of notifies
|
|
LIST_ENTRY PostList; // Posts to fill
|
|
PCM_KEY_CONTROL_BLOCK KeyControlBlock; // Open instance notify is on
|
|
struct _CM_KEY_BODY *KeyBody; // our owning key handle object
|
|
struct {
|
|
ULONG Filter : 30; // Events of interest
|
|
ULONG WatchTree : 1;
|
|
ULONG NotifyPending : 1;
|
|
};
|
|
SECURITY_SUBJECT_CONTEXT SubjectContext; // Security stuff
|
|
} CM_NOTIFY_BLOCK, *PCM_NOTIFY_BLOCK;
|
|
|
|
//
|
|
// CM_POST_BLOCK
|
|
//
|
|
// Whenever a notify call is made, a post block is created and attached
|
|
// to the notify block. Each time an event is posted against the notify,
|
|
// the waiter described by the post block is signaled. (i.e. APC enqueued,
|
|
// event signalled, etc.)
|
|
//
|
|
|
|
//
|
|
// The NotifyType ULONG is a combination of POST_BLOCK_TYPE enum and flags
|
|
//
|
|
|
|
typedef enum _POST_BLOCK_TYPE {
|
|
PostSynchronous = 1,
|
|
PostAsyncUser = 2,
|
|
PostAsyncKernel = 3
|
|
} POST_BLOCK_TYPE;
|
|
|
|
typedef struct _CM_SYNC_POST_BLOCK {
|
|
PKEVENT SystemEvent;
|
|
NTSTATUS Status;
|
|
} CM_SYNC_POST_BLOCK, *PCM_SYNC_POST_BLOCK;
|
|
|
|
typedef struct _CM_ASYNC_USER_POST_BLOCK {
|
|
ULONG Dummy;
|
|
PKEVENT UserEvent;
|
|
PKAPC Apc;
|
|
PIO_STATUS_BLOCK IoStatusBlock;
|
|
} CM_ASYNC_USER_POST_BLOCK, *PCM_ASYNC_USER_POST_BLOCK;
|
|
|
|
typedef struct _CM_ASYNC_KERNEL_POST_BLOCK {
|
|
PKEVENT Event;
|
|
PWORK_QUEUE_ITEM WorkItem;
|
|
WORK_QUEUE_TYPE QueueType;
|
|
} CM_ASYNC_KERNEL_POST_BLOCK, *PCM_ASYNC_KERNEL_POST_BLOCK;
|
|
|
|
typedef union _CM_POST_BLOCK_UNION {
|
|
CM_SYNC_POST_BLOCK Sync;
|
|
CM_ASYNC_USER_POST_BLOCK AsyncUser;
|
|
CM_ASYNC_KERNEL_POST_BLOCK AsyncKernel;
|
|
} CM_POST_BLOCK_UNION, *PCM_POST_BLOCK_UNION;
|
|
|
|
typedef struct _CM_POST_BLOCK {
|
|
#if DBG
|
|
BOOLEAN TraceIntoDebugger;
|
|
#endif
|
|
LIST_ENTRY NotifyList;
|
|
LIST_ENTRY ThreadList;
|
|
LIST_ENTRY CancelPostList; // slave notifications that are attached to this notification
|
|
struct _CM_POST_KEY_BODY *PostKeyBody;
|
|
|
|
#ifdef CM_NOTIFY_CHANGED_KCB_FULLPATH
|
|
PUNICODE_STRING ChangedKcbFullName; // full qualified name of the kcb that triggered this notification
|
|
PVOID CallerBuffer; // used to return full qualified name of the changed kcb to the caller
|
|
ULONG CallerBufferSize; // these are supposed to be filled by CmpAllocatePostBlock
|
|
#endif //CM_NOTIFY_CHANGED_KCB_FULLPATH
|
|
|
|
ULONG NotifyType;
|
|
PCM_POST_BLOCK_UNION u;
|
|
} CM_POST_BLOCK, *PCM_POST_BLOCK;
|
|
|
|
#define REG_NOTIFY_POST_TYPE_MASK (0x0000FFFFL) // mask for finding out the type of the post block
|
|
|
|
#define REG_NOTIFY_MASTER_POST (0x00010000L) // The current post block is a master one
|
|
|
|
//
|
|
// Usefull macros to manipulate the NotifyType field in CM_POST_BLOCK
|
|
//
|
|
#define PostBlockType(_post_) ((POST_BLOCK_TYPE)( ((_post_)->NotifyType) & REG_NOTIFY_POST_TYPE_MASK ))
|
|
|
|
#define IsMasterPostBlock(_post_) ( ((_post_)->NotifyType) & REG_NOTIFY_MASTER_POST )
|
|
#define SetMasterPostBlockFlag(_post_) ( ((_post_)->NotifyType) |= REG_NOTIFY_MASTER_POST )
|
|
#define ClearMasterPostBlockFlag(_post_) ( ((_post_)->NotifyType) &= ~REG_NOTIFY_MASTER_POST )
|
|
|
|
//
|
|
// This lock protects the PostList(s) in Notification objects.
|
|
// It is used to prevent attempts for simultaneous changes of
|
|
// CancelPostList list in PostBlocks
|
|
//
|
|
|
|
extern FAST_MUTEX CmpPostLock;
|
|
#define LOCK_POST_LIST() ExAcquireFastMutexUnsafe(&CmpPostLock)
|
|
#define UNLOCK_POST_LIST() ExReleaseFastMutexUnsafe(&CmpPostLock)
|
|
|
|
|
|
extern FAST_MUTEX CmpStashBufferLock;
|
|
#define LOCK_STASH_BUFFER() ExAcquireFastMutexUnsafe(&CmpStashBufferLock)
|
|
#define UNLOCK_STASH_BUFFER() ExReleaseFastMutexUnsafe(&CmpStashBufferLock)
|
|
|
|
|
|
//
|
|
// protection for CmpHiveListHead
|
|
//
|
|
extern FAST_MUTEX CmpHiveListHeadLock;
|
|
#ifndef _CM_LDR_
|
|
#define LOCK_HIVE_LIST() ExAcquireFastMutexUnsafe(&CmpHiveListHeadLock)
|
|
#define UNLOCK_HIVE_LIST() ExReleaseFastMutexUnsafe(&CmpHiveListHeadLock)
|
|
#else
|
|
#define LOCK_HIVE_LIST() //nothing
|
|
#define UNLOCK_HIVE_LIST() //nothing
|
|
#endif
|
|
|
|
//
|
|
// used by CmpFileWrite, so it doesn't take up so much stack.
|
|
//
|
|
typedef struct _CM_WRITE_BLOCK {
|
|
HANDLE EventHandles[MAXIMUM_WAIT_OBJECTS];
|
|
PKEVENT EventObjects[MAXIMUM_WAIT_OBJECTS];
|
|
KWAIT_BLOCK WaitBlockArray[MAXIMUM_WAIT_OBJECTS];
|
|
IO_STATUS_BLOCK IoStatus[MAXIMUM_WAIT_OBJECTS];
|
|
} CM_WRITE_BLOCK, *PCM_WRITE_BLOCK;
|
|
|
|
//
|
|
// CM data to manipulate views inside the primary hive file
|
|
//
|
|
|
|
//#define MAPPED_VIEWS_PER_HIVE 12 * (_256K / CM_VIEW_SIZE ) // max 3 MB per hive ; we don't really need this
|
|
#define MAX_VIEWS_PER_HIVE MAX_MB_PER_HIVE * ( (_256K) / (CM_VIEW_SIZE) )
|
|
|
|
#define ASSERT_VIEW_MAPPED(a) \
|
|
ASSERT((a)->Size != 0); \
|
|
ASSERT((a)->ViewAddress != 0); \
|
|
ASSERT((a)->Bcb != 0); \
|
|
ASSERT( IsListEmpty(&((a)->LRUViewList)) == FALSE); \
|
|
ASSERT( IsListEmpty(&((a)->PinViewList)) == TRUE)
|
|
|
|
#define ASSERT_VIEW_PINNED(a) \
|
|
ASSERT((a)->Size != 0); \
|
|
ASSERT((a)->ViewAddress != 0); \
|
|
ASSERT((a)->Bcb != 0); \
|
|
ASSERT( IsListEmpty(&((a)->LRUViewList)) == TRUE)
|
|
|
|
typedef struct _CM_VIEW_OF_FILE {
|
|
LIST_ENTRY LRUViewList; // LRU connection ==> when this is empty, the view is pinned
|
|
LIST_ENTRY PinViewList; // list of views pinned into memory ==> when this is empty, the view is in LRU list
|
|
ULONG FileOffset; // file offset at which the mapping starts
|
|
ULONG Size; // size the view maps
|
|
PULONG_PTR ViewAddress; // memory address containing the mapping
|
|
PVOID Bcb; // BCB needed for map/pin/unpin access
|
|
ULONG UseCount; // how many cells are currently in use inside this view
|
|
} CM_VIEW_OF_FILE, *PCM_VIEW_OF_FILE;
|
|
|
|
|
|
//
|
|
// security hash manipulation
|
|
//
|
|
#define CmpSecHashTableSize 64 // size of the hash table
|
|
|
|
typedef struct _CM_KCB_REMAP_BLOCK {
|
|
LIST_ENTRY RemapList;
|
|
PCM_KEY_CONTROL_BLOCK KeyControlBlock;
|
|
HCELL_INDEX OldCellIndex;
|
|
HCELL_INDEX NewCellIndex;
|
|
ULONG ValueCount;
|
|
HCELL_INDEX ValueList;
|
|
} CM_KCB_REMAP_BLOCK, *PCM_KCB_REMAP_BLOCK;
|
|
|
|
typedef struct _CM_CELL_REMAP_BLOCK {
|
|
HCELL_INDEX OldCell;
|
|
HCELL_INDEX NewCell;
|
|
} CM_CELL_REMAP_BLOCK, *PCM_CELL_REMAP_BLOCK;
|
|
|
|
typedef struct _CM_KNODE_REMAP_BLOCK {
|
|
LIST_ENTRY RemapList;
|
|
PCM_KEY_NODE KeyNode;
|
|
HCELL_INDEX NewParent;
|
|
} CM_KNODE_REMAP_BLOCK, *PCM_KNODE_REMAP_BLOCK;
|
|
|
|
//
|
|
// UseCount log
|
|
//
|
|
#ifdef REGISTRY_LOCK_CHECKING
|
|
typedef struct _CM_USE_COUNT_LOG_ENTRY {
|
|
HCELL_INDEX Cell;
|
|
PVOID Stack[7];
|
|
} CM_USE_COUNT_LOG_ENTRY;
|
|
|
|
typedef struct _CM_USE_COUNT_LOG {
|
|
USHORT Next;
|
|
USHORT Size;
|
|
CM_USE_COUNT_LOG_ENTRY Log[32];
|
|
} CM_USE_COUNT_LOG;
|
|
#endif // REGISTRY_LOCK_CHECKING
|
|
|
|
#define CM_CMHIVE_FLAG_UNTRUSTED 1 // hive is untrusted (but it may be inside of a trusted class).
|
|
// ----- Cm version of Hive structure (CMHIVE) -----
|
|
//
|
|
typedef struct _CMHIVE {
|
|
HHIVE Hive;
|
|
HANDLE FileHandles[HFILE_TYPE_MAX];
|
|
LIST_ENTRY NotifyList;
|
|
LIST_ENTRY HiveList; // Used to find hives at shutdown
|
|
PFAST_MUTEX HiveLock; // Used to synchronize operations on the hive (NotifyList and Flush)
|
|
PFAST_MUTEX ViewLock; // Used to control access over the view list, UseCount
|
|
LIST_ENTRY LRUViewListHead; // Head of the same list as above but ordered (LRU)
|
|
LIST_ENTRY PinViewListHead; // Head of the List of Views pinned into memory inside the primary hive file
|
|
#if 0 // it didn't work
|
|
LIST_ENTRY FakeViewListHead; // Used to optimize boot process (fault all the data in in 256K chunks at once)
|
|
#endif
|
|
PFILE_OBJECT FileObject; // FileObject needed for Cc operations on the mapped views
|
|
UNICODE_STRING FileFullPath; // full path of the hive file- needed for CmPrefetchHivePages
|
|
UNICODE_STRING FileUserName; // file name as passed onto NtLoadKey
|
|
USHORT MappedViews; // number of mapped (but not pinned views) i.e. the number of elements in LRUViewList
|
|
USHORT PinnedViews; // number of pinned views i.e. the number of elements in PinViewList
|
|
ULONG UseCount; // how many cells are currently in use inside this hive
|
|
#if 0
|
|
ULONG FakeViews; // number of FakeViews (debug-only)
|
|
#endif
|
|
ULONG SecurityCount; // number of security cells cached
|
|
ULONG SecurityCacheSize; // number of entries in the cache (to avoid memory fragmentation)
|
|
LONG SecurityHitHint; // index of the last cell we've searched on
|
|
PCM_KEY_SECURITY_CACHE_ENTRY SecurityCache; // the security cache
|
|
|
|
// hash table (to retrieve the security cells by descriptor)
|
|
LIST_ENTRY SecurityHash[CmpSecHashTableSize];
|
|
|
|
#ifdef NT_UNLOAD_KEY_EX
|
|
PKEVENT UnloadEvent; // the event to be signaled when the hive unloads
|
|
// this may be valid (not NULL) only in conjunction with
|
|
// a not NULL RootKcb and a TRUE Frozen (below)
|
|
|
|
PCM_KEY_CONTROL_BLOCK RootKcb; // kcb to the root of the hive. We keep a reference on it, which
|
|
// will be released at the time the hive unloads (i.e. it is the last
|
|
// reference somebody has on this kcb); This is should be valid (not NULL)
|
|
// only when the Frozen flag is set to TRUE
|
|
|
|
BOOLEAN Frozen; // set to TRUE when the hive is frozen (no further operations are allowed on
|
|
// this hive
|
|
|
|
PWORK_QUEUE_ITEM UnloadWorkItem; // Work Item to actually perform the late unload
|
|
#endif //NT_UNLOAD_KEY_EX
|
|
|
|
BOOLEAN GrowOnlyMode; // the hive is in "grow only" mode; new cells are allocated past GrowOffset
|
|
ULONG GrowOffset;
|
|
|
|
LIST_ENTRY KcbConvertListHead; // list of CM_KCB_REMAP_BLOCK storing the associations to the new hive.
|
|
LIST_ENTRY KnodeConvertListHead;
|
|
PCM_CELL_REMAP_BLOCK CellRemapArray; // array of mappings used for security cells
|
|
|
|
#ifdef REGISTRY_LOCK_CHECKING
|
|
CM_USE_COUNT_LOG UseCountLog; // track UseCount leaks
|
|
#endif // REGISTRY_LOCK_CHECKING
|
|
ULONG Flags; // CMHIVE specific flags
|
|
LIST_ENTRY TrustClassEntry; // links together the UNTRUSTED hives in the same 'class of trust'
|
|
ULONG FlushCount;
|
|
} CMHIVE, *PCMHIVE;
|
|
|
|
#define CmpUnJoinClassOfTrust(CmHive) \
|
|
if( !IsListEmpty(&(CmHive->TrustClassEntry)) ) { \
|
|
ASSERT(CmHive->Flags&CM_CMHIVE_FLAG_UNTRUSTED); \
|
|
LOCK_HIVE_LIST(); \
|
|
RemoveEntryList(&(CmHive->TrustClassEntry)); \
|
|
UNLOCK_HIVE_LIST(); \
|
|
}
|
|
#define CmpJoinClassOfTrust(_NewHive,_OtherHive) \
|
|
LOCK_HIVE_LIST(); \
|
|
InsertTailList(&(_OtherHive->TrustClassEntry),&(_NewHive->TrustClassEntry));\
|
|
UNLOCK_HIVE_LIST()
|
|
|
|
|
|
#ifdef REGISTRY_LOCK_CHECKING
|
|
#define CmAddUseCountToLog( LOG, CELL, ACTION ) { \
|
|
if( (ACTION) < 0 ) { \
|
|
ULONG i; \
|
|
for(i=0;i<(LOG)->Next;i++) { \
|
|
if( (LOG)->Log[i].Cell == (CELL) ) { \
|
|
RtlMoveMemory(&((LOG)->Log[i]),&((LOG)->Log[i+1]),((LOG)->Next - i - 1)*sizeof(CM_USE_COUNT_LOG_ENTRY));\
|
|
(LOG)->Next -= 1; \
|
|
break; \
|
|
} \
|
|
} \
|
|
} else if( (LOG)->Next < (LOG)->Size ) { \
|
|
RtlWalkFrameChain((LOG)->Log[(LOG)->Next].Stack, \
|
|
sizeof((LOG)->Log[(LOG)->Next].Stack)/sizeof(PVOID), \
|
|
0); \
|
|
(LOG)->Log[(LOG)->Next].Cell = (CELL); \
|
|
(LOG)->Next += 1; \
|
|
} \
|
|
}
|
|
#define CmLogCellRef( HIVE, CELL ) CmAddUseCountToLog( &(((PCMHIVE)(HIVE))->UseCountLog), CELL , 1)
|
|
#define CmLogCellDeRef( HIVE, CELL ) CmAddUseCountToLog( &(((PCMHIVE)(HIVE))->UseCountLog), CELL , -1)
|
|
#else // REGISTRY_LOCK_CHECKING
|
|
#define CmLogCellRef( HIVE, CELL )
|
|
#define CmLogCellDeRef( HIVE, CELL )
|
|
#endif // REGISTRY_LOCK_CHECKING
|
|
|
|
|
|
#ifdef NT_UNLOAD_KEY_EX
|
|
#define IsHiveFrozen(_CmHive_) (((PCMHIVE)(_CmHive_))->Frozen == TRUE)
|
|
#endif
|
|
|
|
#define HiveWritesThroughCache(Hive,FileType) ((FileType == HFILE_TYPE_PRIMARY) && (((PCMHIVE)CONTAINING_RECORD(Hive, CMHIVE, Hive))->FileObject != NULL))
|
|
|
|
|
|
//
|
|
// Delayed close kcb list
|
|
//
|
|
typedef struct _CM_DELAYED_CLOSE_ENTRY {
|
|
LIST_ENTRY DelayedLRUList; // LRU list of entries in the Delayed Close Table
|
|
PCM_KEY_CONTROL_BLOCK KeyControlBlock; // KCB in this entry; NULL if the entry is available
|
|
} CM_DELAYED_CLOSE_ENTRY, *PCM_DELAYED_CLOSE_ENTRY;
|
|
|
|
|
|
//
|
|
// Hive locking support
|
|
//
|
|
//
|
|
#define CmLockHive(_hive_) ASSERT( (_hive_)->HiveLock );\
|
|
ExAcquireFastMutexUnsafe((_hive_)->HiveLock)
|
|
#define CmUnlockHive(_hive_) ASSERT( (_hive_)->HiveLock );\
|
|
ExReleaseFastMutexUnsafe((_hive_)->HiveLock)
|
|
|
|
//
|
|
// View locking support
|
|
//
|
|
#define CmLockHiveViews(_hive_) ASSERT( (_hive_)->ViewLock );\
|
|
ExAcquireFastMutexUnsafe((_hive_)->ViewLock)
|
|
#define CmUnlockHiveViews(_hive_) ASSERT( (_hive_)->ViewLock );\
|
|
ExReleaseFastMutexUnsafe((_hive_)->ViewLock)
|
|
|
|
//
|
|
// Macros
|
|
//
|
|
|
|
//
|
|
// ----- CM_KEY_NODE -----
|
|
//
|
|
#define CmpHKeyNameLen(Key) \
|
|
(((Key)->Flags & KEY_COMP_NAME) ? \
|
|
CmpCompressedNameSize((Key)->Name,(Key)->NameLength) : \
|
|
(Key)->NameLength)
|
|
|
|
#define CmpNcbNameLen(Ncb) \
|
|
(((Ncb)->Compressed) ? \
|
|
CmpCompressedNameSize((Ncb)->Name,(Ncb)->NameLength) : \
|
|
(Ncb)->NameLength)
|
|
|
|
#define CmpHKeyNodeSize(Hive, KeyName) \
|
|
(FIELD_OFFSET(CM_KEY_NODE, Name) + CmpNameSize(Hive, KeyName))
|
|
|
|
|
|
//
|
|
// ----- CM_KEY_VALUE -----
|
|
//
|
|
|
|
|
|
#define CmpValueNameLen(Value) \
|
|
(((Value)->Flags & VALUE_COMP_NAME) ? \
|
|
CmpCompressedNameSize((Value)->Name,(Value)->NameLength) : \
|
|
(Value)->NameLength)
|
|
|
|
#define CmpHKeyValueSize(Hive, ValueName) \
|
|
(FIELD_OFFSET(CM_KEY_VALUE, Name) + CmpNameSize(Hive, ValueName))
|
|
|
|
|
|
//
|
|
// ----- Procedure Prototypes -----
|
|
//
|
|
|
|
//
|
|
// Configuration Manager private procedure prototypes
|
|
//
|
|
|
|
#define REG_OPTION_PREDEF_HANDLE (0x01000000L)
|
|
#define REG_PREDEF_HANDLE_MASK (0x80000000L)
|
|
|
|
typedef struct _CM_PARSE_CONTEXT {
|
|
ULONG TitleIndex;
|
|
UNICODE_STRING Class;
|
|
ULONG CreateOptions;
|
|
ULONG Disposition;
|
|
CM_KEY_REFERENCE ChildHive;
|
|
HANDLE PredefinedHandle;
|
|
BOOLEAN CreateLink;
|
|
BOOLEAN CreateOperation;
|
|
PCMHIVE OriginatingPoint;
|
|
} CM_PARSE_CONTEXT, *PCM_PARSE_CONTEXT;
|
|
|
|
#define CmpParseRecordOriginatingPoint(_Context,_CmHive) \
|
|
if( ARGUMENT_PRESENT(_Context) && (((PCM_PARSE_CONTEXT)(_Context))->OriginatingPoint == NULL) && \
|
|
(((PCMHIVE)_CmHive)->Flags&CM_CMHIVE_FLAG_UNTRUSTED) ){ \
|
|
((PCM_PARSE_CONTEXT)(_Context))->OriginatingPoint = (PCMHIVE)_CmHive; \
|
|
}
|
|
|
|
#define CmpParseGetOriginatingPoint(_Context) ARGUMENT_PRESENT(_Context)?((PCM_PARSE_CONTEXT)(_Context))->OriginatingPoint:NULL
|
|
|
|
NTSTATUS
|
|
CmpParseKey(
|
|
IN PVOID ParseObject,
|
|
IN PVOID ObjectType,
|
|
IN OUT PACCESS_STATE AccessState,
|
|
IN KPROCESSOR_MODE AccessMode,
|
|
IN ULONG Attributes,
|
|
IN OUT PUNICODE_STRING CompleteName,
|
|
IN OUT PUNICODE_STRING RemainingName,
|
|
IN OUT PVOID Context OPTIONAL,
|
|
IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,
|
|
OUT PVOID *Object
|
|
);
|
|
|
|
NTSTATUS
|
|
CmpDoCreate(
|
|
IN PHHIVE Hive,
|
|
IN HCELL_INDEX Cell,
|
|
IN PACCESS_STATE AccessState,
|
|
IN PUNICODE_STRING Name,
|
|
IN KPROCESSOR_MODE AccessMode,
|
|
IN PCM_PARSE_CONTEXT Context,
|
|
IN PCM_KEY_CONTROL_BLOCK ParentKcb,
|
|
IN PCMHIVE OriginatingHive OPTIONAL,
|
|
OUT PVOID *Object
|
|
);
|
|
|
|
NTSTATUS
|
|
CmpDoCreateChild(
|
|
IN PHHIVE Hive,
|
|
IN HCELL_INDEX ParentCell,
|
|
IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
|
|
IN PACCESS_STATE AccessState,
|
|
IN PUNICODE_STRING Name,
|
|
IN KPROCESSOR_MODE AccessMode,
|
|
IN PCM_PARSE_CONTEXT Context,
|
|
IN PCM_KEY_CONTROL_BLOCK ParentKcb,
|
|
IN USHORT Flags,
|
|
OUT PHCELL_INDEX KeyCell,
|
|
OUT PVOID *Object
|
|
);
|
|
|
|
NTSTATUS
|
|
CmpQueryKeyName(
|
|
IN PVOID Object,
|
|
IN BOOLEAN HasObjectName,
|
|
OUT POBJECT_NAME_INFORMATION ObjectNameInfo,
|
|
IN ULONG Length,
|
|
OUT PULONG ReturnLength,
|
|
IN KPROCESSOR_MODE Mode
|
|
);
|
|
|
|
VOID
|
|
CmpDeleteKeyObject(
|
|
IN PVOID Object
|
|
);
|
|
|
|
VOID
|
|
CmpCloseKeyObject(
|
|
IN PEPROCESS Process OPTIONAL,
|
|
IN PVOID Object,
|
|
IN ACCESS_MASK GrantedAccess,
|
|
IN ULONG_PTR ProcessHandleCount,
|
|
IN ULONG_PTR SystemHandleCount
|
|
);
|
|
|
|
NTSTATUS
|
|
CmpSecurityMethod (
|
|
IN PVOID Object,
|
|
IN SECURITY_OPERATION_CODE OperationCode,
|
|
IN PSECURITY_INFORMATION SecurityInformation,
|
|
IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
|
|
IN OUT PULONG CapturedLength,
|
|
IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor,
|
|
IN POOL_TYPE PoolType,
|
|
IN PGENERIC_MAPPING GenericMapping
|
|
);
|
|
|
|
#define KCB_WORKER_CONTINUE 0
|
|
#define KCB_WORKER_DONE 1
|
|
#define KCB_WORKER_DELETE 2
|
|
#define KCB_WORKER_ERROR 3
|
|
|
|
typedef
|
|
ULONG
|
|
(*PKCB_WORKER_ROUTINE) (
|
|
PCM_KEY_CONTROL_BLOCK Current,
|
|
PVOID Context1,
|
|
PVOID Context2
|
|
);
|
|
|
|
|
|
BOOLEAN
|
|
CmpSearchKeyControlBlockTree(
|
|
PKCB_WORKER_ROUTINE WorkerRoutine,
|
|
PVOID Context1,
|
|
PVOID Context2
|
|
);
|
|
|
|
//
|
|
// Wrappers
|
|
//
|
|
|
|
PVOID
|
|
CmpAllocate(
|
|
ULONG Size,
|
|
BOOLEAN UseForIo,
|
|
ULONG Tag
|
|
);
|
|
|
|
VOID
|
|
CmpFree(
|
|
PVOID MemoryBlock,
|
|
ULONG GlobalQuotaSize
|
|
);
|
|
|
|
BOOLEAN
|
|
CmpFileSetSize(
|
|
PHHIVE Hive,
|
|
ULONG FileType,
|
|
ULONG FileSize,
|
|
ULONG OldFileSize
|
|
);
|
|
|
|
NTSTATUS
|
|
CmpDoFileSetSize(
|
|
PHHIVE Hive,
|
|
ULONG FileType,
|
|
ULONG FileSize,
|
|
ULONG OldFileSize
|
|
);
|
|
|
|
BOOLEAN
|
|
CmpFileWrite(
|
|
PHHIVE Hive,
|
|
ULONG FileType,
|
|
PCMP_OFFSET_ARRAY offsetArray,
|
|
ULONG offsetArrayCount,
|
|
PULONG FileOffset
|
|
);
|
|
|
|
BOOLEAN
|
|
CmpFileWriteThroughCache(
|
|
PHHIVE Hive,
|
|
ULONG FileType,
|
|
PCMP_OFFSET_ARRAY offsetArray,
|
|
ULONG offsetArrayCount
|
|
);
|
|
|
|
BOOLEAN
|
|
CmpFileRead (
|
|
PHHIVE Hive,
|
|
ULONG FileType,
|
|
PULONG FileOffset,
|
|
PVOID DataBuffer,
|
|
ULONG DataLength
|
|
);
|
|
|
|
BOOLEAN
|
|
CmpFileFlush (
|
|
PHHIVE Hive,
|
|
ULONG FileType,
|
|
PLARGE_INTEGER FileOffset,
|
|
ULONG Length
|
|
);
|
|
|
|
NTSTATUS
|
|
CmpCreateEvent(
|
|
IN EVENT_TYPE eventType,
|
|
OUT PHANDLE eventHandle,
|
|
OUT PKEVENT *event
|
|
);
|
|
|
|
|
|
//
|
|
// Configuration Manager CM level registry functions
|
|
//
|
|
|
|
NTSTATUS
|
|
CmDeleteKey(
|
|
IN PCM_KEY_BODY KeyBody
|
|
);
|
|
|
|
NTSTATUS
|
|
CmDeleteValueKey(
|
|
IN PCM_KEY_CONTROL_BLOCK KeyControlBlock,
|
|
IN UNICODE_STRING ValueName
|
|
);
|
|
|
|
NTSTATUS
|
|
CmEnumerateKey(
|
|
IN PCM_KEY_CONTROL_BLOCK KeyControlBlock,
|
|
IN ULONG Index,
|
|
IN KEY_INFORMATION_CLASS KeyInformationClass,
|
|
IN PVOID KeyInformation,
|
|
IN ULONG Length,
|
|
IN PULONG ResultLength
|
|
);
|
|
|
|
NTSTATUS
|
|
CmEnumerateValueKey(
|
|
IN PCM_KEY_CONTROL_BLOCK KeyControlBlock,
|
|
IN ULONG Index,
|
|
IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
|
|
IN PVOID KeyValueInformation,
|
|
IN ULONG Length,
|
|
IN PULONG ResultLength
|
|
);
|
|
|
|
NTSTATUS
|
|
CmFlushKey(
|
|
IN PHHIVE Hive,
|
|
IN HCELL_INDEX Cell
|
|
);
|
|
|
|
NTSTATUS
|
|
CmQueryKey(
|
|
IN PCM_KEY_CONTROL_BLOCK KeyControlBlock,
|
|
IN KEY_INFORMATION_CLASS KeyInformationClass,
|
|
IN PVOID KeyInformation,
|
|
IN ULONG Length,
|
|
IN PULONG ResultLength
|
|
);
|
|
|
|
NTSTATUS
|
|
CmQueryValueKey(
|
|
IN PCM_KEY_CONTROL_BLOCK KeyControlBlock,
|
|
IN UNICODE_STRING ValueName,
|
|
IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
|
|
IN PVOID KeyValueInformation,
|
|
IN ULONG Length,
|
|
IN PULONG ResultLength
|
|
);
|
|
|
|
NTSTATUS
|
|
CmQueryMultipleValueKey(
|
|
IN PCM_KEY_CONTROL_BLOCK KeyControlBlock,
|
|
IN PKEY_VALUE_ENTRY ValueEntries,
|
|
IN ULONG EntryCount,
|
|
IN PVOID ValueBuffer,
|
|
IN OUT PULONG BufferLength,
|
|
IN OPTIONAL PULONG ResultLength
|
|
);
|
|
|
|
NTSTATUS
|
|
CmRenameValueKey(
|
|
IN PCM_KEY_CONTROL_BLOCK KeyControlBlock,
|
|
IN UNICODE_STRING SourceValueName,
|
|
IN UNICODE_STRING TargetValueName,
|
|
IN ULONG TargetIndex
|
|
);
|
|
|
|
NTSTATUS
|
|
CmReplaceKey(
|
|
IN PHHIVE Hive,
|
|
IN HCELL_INDEX Cell,
|
|
IN PUNICODE_STRING NewHiveName,
|
|
IN PUNICODE_STRING OldFileName
|
|
);
|
|
|
|
NTSTATUS
|
|
CmRestoreKey(
|
|
IN PCM_KEY_CONTROL_BLOCK KeyControlBlock,
|
|
IN HANDLE FileHandle,
|
|
IN ULONG Flags
|
|
);
|
|
|
|
NTSTATUS
|
|
CmSaveKey(
|
|
IN PCM_KEY_CONTROL_BLOCK KeyControlBlock,
|
|
IN HANDLE FileHandle,
|
|
IN ULONG HiveVersion
|
|
);
|
|
|
|
NTSTATUS
|
|
CmDumpKey(
|
|
IN PCM_KEY_CONTROL_BLOCK KeyControlBlock,
|
|
IN HANDLE FileHandle
|
|
);
|
|
|
|
NTSTATUS
|
|
CmSaveMergedKeys(
|
|
IN PCM_KEY_CONTROL_BLOCK HighPrecedenceKcb,
|
|
IN PCM_KEY_CONTROL_BLOCK LowPrecedenceKcb,
|
|
IN HANDLE FileHandle
|
|
);
|
|
|
|
NTSTATUS
|
|
CmpShiftHiveFreeBins(
|
|
PCMHIVE CmHive,
|
|
PCMHIVE *NewHive
|
|
);
|
|
|
|
NTSTATUS
|
|
CmpOverwriteHive(
|
|
PCMHIVE CmHive,
|
|
PCMHIVE NewHive,
|
|
HCELL_INDEX LinkCell
|
|
);
|
|
|
|
VOID
|
|
CmpSwitchStorageAndRebuildMappings(PCMHIVE OldCmHive,
|
|
PCMHIVE NewHive
|
|
);
|
|
|
|
NTSTATUS
|
|
CmSetValueKey(
|
|
IN PCM_KEY_CONTROL_BLOCK KeyControlBlock,
|
|
IN PUNICODE_STRING ValueName,
|
|
IN ULONG Type,
|
|
IN PVOID Data,
|
|
IN ULONG DataSize
|
|
);
|
|
|
|
NTSTATUS
|
|
CmSetLastWriteTimeKey(
|
|
IN PCM_KEY_CONTROL_BLOCK KeyControlBlock,
|
|
IN PLARGE_INTEGER LastWriteTime
|
|
);
|
|
|
|
NTSTATUS
|
|
CmSetKeyUserFlags(
|
|
IN PCM_KEY_CONTROL_BLOCK KeyControlBlock,
|
|
IN ULONG UserFlags
|
|
);
|
|
|
|
NTSTATUS
|
|
CmpNotifyChangeKey(
|
|
IN PCM_KEY_BODY KeyBody,
|
|
IN PCM_POST_BLOCK PostBlock,
|
|
IN ULONG CompletionFilter,
|
|
IN BOOLEAN WatchTree,
|
|
IN PVOID Buffer,
|
|
IN ULONG BufferSize,
|
|
IN PCM_POST_BLOCK MasterPostBlock
|
|
);
|
|
|
|
NTSTATUS
|
|
CmLoadKey(
|
|
IN POBJECT_ATTRIBUTES TargetKey,
|
|
IN POBJECT_ATTRIBUTES SourceFile,
|
|
IN ULONG Flags,
|
|
IN PCM_KEY_BODY KeyBody
|
|
);
|
|
|
|
NTSTATUS
|
|
CmUnloadKey(
|
|
IN PHHIVE Hive,
|
|
IN HCELL_INDEX Cell,
|
|
IN PCM_KEY_CONTROL_BLOCK Kcb,
|
|
IN ULONG Flags
|
|
);
|
|
|
|
NTSTATUS
|
|
CmMoveKey(
|
|
IN PCM_KEY_CONTROL_BLOCK KeyControlBlock
|
|
);
|
|
|
|
NTSTATUS
|
|
CmCompressKey(
|
|
IN PHHIVE Hive
|
|
);
|
|
|
|
//
|
|
// Procedures private to CM
|
|
//
|
|
|
|
BOOLEAN
|
|
CmpMarkKeyDirty(
|
|
PHHIVE Hive,
|
|
HCELL_INDEX Cell
|
|
#if DBG
|
|
,
|
|
BOOLEAN CheckNoSubkeys
|
|
#endif
|
|
);
|
|
|
|
BOOLEAN
|
|
CmpDoFlushAll(
|
|
BOOLEAN ForceFlush
|
|
);
|
|
|
|
VOID
|
|
CmpFixHiveUsageCount(
|
|
IN PCMHIVE CmHive
|
|
);
|
|
|
|
VOID
|
|
CmpLazyFlush(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
CmpQuotaWarningWorker(
|
|
IN PVOID WorkItem
|
|
);
|
|
|
|
VOID
|
|
CmpComputeGlobalQuotaAllowed(
|
|
VOID
|
|
);
|
|
|
|
BOOLEAN
|
|
CmpClaimGlobalQuota(
|
|
IN ULONG Size
|
|
);
|
|
|
|
VOID
|
|
CmpReleaseGlobalQuota(
|
|
IN ULONG Size
|
|
);
|
|
|
|
VOID
|
|
CmpSetGlobalQuotaAllowed(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
CmpSystemQuotaWarningWorker(
|
|
IN PVOID WorkItem
|
|
);
|
|
|
|
BOOLEAN
|
|
CmpCanGrowSystemHive(
|
|
IN PHHIVE Hive,
|
|
IN ULONG NewLength
|
|
);
|
|
|
|
//
|
|
// security functions (cmse.c)
|
|
//
|
|
|
|
NTSTATUS
|
|
CmpAssignSecurityDescriptor(
|
|
IN PHHIVE Hive,
|
|
IN HCELL_INDEX Cell,
|
|
IN PCM_KEY_NODE Node,
|
|
IN PSECURITY_DESCRIPTOR SecurityDescriptor
|
|
);
|
|
|
|
BOOLEAN
|
|
CmpCheckCreateAccess(
|
|
IN PUNICODE_STRING RelativeName,
|
|
IN PSECURITY_DESCRIPTOR Descriptor,
|
|
IN PACCESS_STATE AccessState,
|
|
IN KPROCESSOR_MODE PreviousMode,
|
|
IN ACCESS_MASK AdditionalAccess,
|
|
OUT PNTSTATUS AccessStatus
|
|
);
|
|
|
|
BOOLEAN
|
|
CmpCheckNotifyAccess(
|
|
IN PCM_NOTIFY_BLOCK NotifyBlock,
|
|
IN PHHIVE Hive,
|
|
IN PCM_KEY_NODE Node
|
|
);
|
|
|
|
PSECURITY_DESCRIPTOR
|
|
CmpHiveRootSecurityDescriptor(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
CmpFreeSecurityDescriptor(
|
|
IN PHHIVE Hive,
|
|
IN HCELL_INDEX Cell
|
|
);
|
|
|
|
|
|
//
|
|
// Access to the registry is serialized by a shared resource, CmpRegistryLock.
|
|
//
|
|
extern ERESOURCE CmpRegistryLock;
|
|
|
|
//
|
|
// Support for "StarveExclusive" mode suring a flush
|
|
//
|
|
extern LONG CmpFlushStarveWriters;
|
|
|
|
#define ENTER_FLUSH_MODE() InterlockedIncrement (&CmpFlushStarveWriters);
|
|
|
|
#if DBG
|
|
#define EXIT_FLUSH_MODE() \
|
|
{ \
|
|
LONG LocalIncrement = (LONG)InterlockedDecrement (&CmpFlushStarveWriters); \
|
|
ASSERT( LocalIncrement >= 0 ); \
|
|
}
|
|
#else
|
|
#define EXIT_FLUSH_MODE() InterlockedDecrement (&CmpFlushStarveWriters)
|
|
#endif
|
|
|
|
|
|
#if 0
|
|
#define CmpLockRegistry() KeEnterCriticalRegion(); \
|
|
ExAcquireResourceShared(&CmpRegistryLock, TRUE)
|
|
|
|
#define CmpLockRegistryExclusive() KeEnterCriticalRegion(); \
|
|
ExAcquireResourceExclusive(&CmpRegistryLock,TRUE)
|
|
|
|
#else
|
|
VOID
|
|
CmpLockRegistryExclusive(
|
|
VOID
|
|
);
|
|
VOID
|
|
CmpLockRegistry(
|
|
VOID
|
|
);
|
|
#endif
|
|
|
|
VOID
|
|
CmpUnlockRegistry(
|
|
);
|
|
|
|
#if DBG
|
|
BOOLEAN
|
|
CmpTestRegistryLock(
|
|
VOID
|
|
);
|
|
BOOLEAN
|
|
CmpTestRegistryLockExclusive(
|
|
VOID
|
|
);
|
|
|
|
BOOLEAN
|
|
CmpTestKCBTreeLockExclusive(
|
|
VOID
|
|
);
|
|
#endif
|
|
|
|
NTSTATUS
|
|
CmpQueryKeyData(
|
|
PHHIVE Hive,
|
|
PCM_KEY_NODE Node,
|
|
KEY_INFORMATION_CLASS KeyInformationClass,
|
|
PVOID KeyInformation,
|
|
ULONG Length,
|
|
PULONG ResultLength
|
|
#if defined(CMP_STATS) || defined(CMP_KCB_CACHE_VALIDATION)
|
|
,
|
|
PCM_KEY_CONTROL_BLOCK Kcb
|
|
#endif
|
|
);
|
|
|
|
NTSTATUS
|
|
CmpQueryKeyDataFromCache(
|
|
PCM_KEY_CONTROL_BLOCK Kcb,
|
|
KEY_INFORMATION_CLASS KeyInformationClass,
|
|
PVOID KeyInformation,
|
|
ULONG Length,
|
|
PULONG ResultLength
|
|
);
|
|
|
|
|
|
BOOLEAN
|
|
CmpFreeKeyBody(
|
|
PHHIVE Hive,
|
|
HCELL_INDEX Cell
|
|
);
|
|
|
|
BOOLEAN
|
|
CmpFreeValue(
|
|
PHHIVE Hive,
|
|
HCELL_INDEX Cell
|
|
);
|
|
|
|
HCELL_INDEX
|
|
CmpFindValueByName(
|
|
PHHIVE Hive,
|
|
PCM_KEY_NODE KeyNode,
|
|
PUNICODE_STRING Name
|
|
);
|
|
|
|
NTSTATUS
|
|
CmpDeleteChildByName(
|
|
PHHIVE Hive,
|
|
HCELL_INDEX Cell,
|
|
UNICODE_STRING Name,
|
|
PHCELL_INDEX ChildCell
|
|
);
|
|
|
|
NTSTATUS
|
|
CmpFreeKeyByCell(
|
|
PHHIVE Hive,
|
|
HCELL_INDEX Cell,
|
|
BOOLEAN Unlink
|
|
);
|
|
|
|
BOOLEAN
|
|
CmpFindNameInList(
|
|
IN PHHIVE Hive,
|
|
IN PCHILD_LIST ChildList,
|
|
IN PUNICODE_STRING Name,
|
|
IN OPTIONAL PULONG ChildIndex,
|
|
OUT PHCELL_INDEX CellIndex
|
|
);
|
|
|
|
HCELL_INDEX
|
|
CmpCopyCell(
|
|
PHHIVE SourceHive,
|
|
HCELL_INDEX SourceCell,
|
|
PHHIVE TargetHive,
|
|
HSTORAGE_TYPE Type
|
|
);
|
|
|
|
HCELL_INDEX
|
|
CmpCopyValue(
|
|
PHHIVE SourceHive,
|
|
HCELL_INDEX SourceValueCell,
|
|
PHHIVE TargetHive,
|
|
HSTORAGE_TYPE Type
|
|
);
|
|
|
|
HCELL_INDEX
|
|
CmpCopyKeyPartial(
|
|
PHHIVE SourceHive,
|
|
HCELL_INDEX SourceKeyCell,
|
|
PHHIVE TargetHive,
|
|
HCELL_INDEX Parent,
|
|
BOOLEAN CopyValues
|
|
);
|
|
|
|
BOOLEAN
|
|
CmpCopySyncTree(
|
|
PHHIVE SourceHive,
|
|
HCELL_INDEX SourceCell,
|
|
PHHIVE TargetHive,
|
|
HCELL_INDEX TargetCell,
|
|
BOOLEAN CopyVolatile,
|
|
CMP_COPY_TYPE CopyType
|
|
);
|
|
|
|
//
|
|
// BOOLEAN
|
|
// CmpCopyTree(
|
|
// PHHIVE SourceHive,
|
|
// HCELL_INDEX SourceCell,
|
|
// PHHIVE TargetHive,
|
|
// HCELL_INDEX TargetCell
|
|
// );
|
|
//
|
|
|
|
#define CmpCopyTree(s,c,t,l) CmpCopySyncTree(s,c,t,l,FALSE,Copy)
|
|
|
|
//
|
|
// BOOLEAN
|
|
// CmpCopyTreeEx(
|
|
// PHHIVE SourceHive,
|
|
// HCELL_INDEX SourceCell,
|
|
// PHHIVE TargetHive,
|
|
// HCELL_INDEX TargetCell,
|
|
// BOOLEAN CopyVolatile
|
|
// );
|
|
//
|
|
|
|
#define CmpCopyTreeEx(s,c,t,l,f) CmpCopySyncTree(s,c,t,l,f,Copy)
|
|
|
|
//
|
|
// BOOLEAN
|
|
// CmpSyncTrees(
|
|
// PHHIVE SourceHive,
|
|
// HCELL_INDEX SourceCell,
|
|
// PHHIVE TargetHive,
|
|
// HCELL_INDEX TargetCell,
|
|
// BOOLEAN CopyVolatile);
|
|
//
|
|
|
|
#define CmpSyncTrees(s,c,t,l,f) CmpCopySyncTree(s,c,t,l,f,Sync)
|
|
|
|
|
|
//
|
|
// BOOLEAN
|
|
// CmpMergeTrees(
|
|
// PHHIVE SourceHive,
|
|
// HCELL_INDEX SourceCell,
|
|
// PHHIVE TargetHive,
|
|
// HCELL_INDEX TargetCell);
|
|
//
|
|
|
|
#define CmpMergeTrees(s,c,t,l) CmpCopySyncTree(s,c,t,l,FALSE,Merge)
|
|
|
|
VOID
|
|
CmpDeleteTree(
|
|
PHHIVE Hive,
|
|
HCELL_INDEX Cell
|
|
);
|
|
|
|
VOID
|
|
CmpSetVersionData(
|
|
VOID
|
|
);
|
|
|
|
NTSTATUS
|
|
CmpInitializeHardwareConfiguration(
|
|
IN PLOADER_PARAMETER_BLOCK LoaderBlock
|
|
);
|
|
|
|
NTSTATUS
|
|
CmpInitializeMachineDependentConfiguration(
|
|
IN PLOADER_PARAMETER_BLOCK LoaderBlock
|
|
);
|
|
|
|
NTSTATUS
|
|
CmpInitializeRegistryNode(
|
|
IN PCONFIGURATION_COMPONENT_DATA CurrentEntry,
|
|
IN HANDLE ParentHandle,
|
|
OUT PHANDLE NewHandle,
|
|
IN INTERFACE_TYPE InterfaceType,
|
|
IN ULONG BusNumber,
|
|
IN PUSHORT DeviceIndexTable
|
|
);
|
|
|
|
NTSTATUS
|
|
CmpInitializeHive(
|
|
PCMHIVE *CmHive,
|
|
ULONG OperationType,
|
|
ULONG HiveFlags,
|
|
ULONG FileType,
|
|
PVOID HiveData OPTIONAL,
|
|
HANDLE Primary,
|
|
HANDLE Log,
|
|
HANDLE External,
|
|
PUNICODE_STRING FileName OPTIONAL,
|
|
ULONG CheckFlags
|
|
);
|
|
|
|
LOGICAL
|
|
CmpDestroyHive(
|
|
IN PHHIVE Hive,
|
|
IN HCELL_INDEX Cell
|
|
);
|
|
|
|
VOID
|
|
CmpInitializeRegistryNames(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
CmpInitializeCache(
|
|
VOID
|
|
);
|
|
|
|
PCM_KEY_CONTROL_BLOCK
|
|
CmpCreateKeyControlBlock(
|
|
PHHIVE Hive,
|
|
HCELL_INDEX Cell,
|
|
PCM_KEY_NODE Node,
|
|
PCM_KEY_CONTROL_BLOCK ParentKcb,
|
|
BOOLEAN FakeKey,
|
|
PUNICODE_STRING KeyName
|
|
);
|
|
|
|
VOID CmpCleanUpKCBCacheTable();
|
|
|
|
typedef struct _QUERY_OPEN_SUBKEYS_CONTEXT {
|
|
ULONG BufferLength;
|
|
PVOID Buffer;
|
|
ULONG RequiredSize;
|
|
NTSTATUS StatusCode;
|
|
ULONG UsedLength;
|
|
PVOID KeyBodyToIgnore;
|
|
PVOID CurrentNameBuffer;
|
|
} QUERY_OPEN_SUBKEYS_CONTEXT, *PQUERY_OPEN_SUBKEYS_CONTEXT;
|
|
|
|
ULONG
|
|
CmpSearchForOpenSubKeys(
|
|
IN PCM_KEY_CONTROL_BLOCK SearchKey,
|
|
IN SUBKEY_SEARCH_TYPE SearchType,
|
|
IN OUT PVOID SearchContext OPTIONAL
|
|
);
|
|
|
|
VOID
|
|
CmpDereferenceKeyControlBlock(
|
|
PCM_KEY_CONTROL_BLOCK KeyControlBlock
|
|
);
|
|
|
|
VOID
|
|
CmpRemoveKeyControlBlock(
|
|
PCM_KEY_CONTROL_BLOCK KeyControlBlock
|
|
);
|
|
|
|
VOID
|
|
CmpReportNotify(
|
|
PCM_KEY_CONTROL_BLOCK KeyControlBlock,
|
|
PHHIVE Hive,
|
|
HCELL_INDEX Cell,
|
|
ULONG NotifyMask
|
|
);
|
|
|
|
VOID
|
|
CmpPostNotify(
|
|
PCM_NOTIFY_BLOCK NotifyBlock,
|
|
PUNICODE_STRING Name OPTIONAL,
|
|
ULONG Filter,
|
|
NTSTATUS Status,
|
|
PLIST_ENTRY ExternalKeyDeref OPTIONAL
|
|
#ifdef CM_NOTIFY_CHANGED_KCB_FULLPATH
|
|
,
|
|
PUNICODE_STRING ChangedKcbName OPTIONAL
|
|
#endif //CM_NOTIFY_CHANGED_KCB_FULLPATH
|
|
);
|
|
|
|
PCM_POST_BLOCK
|
|
CmpAllocatePostBlock(
|
|
IN POST_BLOCK_TYPE BlockType,
|
|
IN ULONG PostFlags,
|
|
IN PCM_KEY_BODY KeyBody,
|
|
IN PCM_POST_BLOCK MasterBlock
|
|
);
|
|
|
|
//
|
|
//PCM_POST_BLOCK
|
|
//CmpAllocateMasterPostBlock(
|
|
// IN POST_BLOCK_TYPE BlockType
|
|
// );
|
|
//
|
|
#define CmpAllocateMasterPostBlock(b) CmpAllocatePostBlock(b,REG_NOTIFY_MASTER_POST,NULL,NULL)
|
|
|
|
//
|
|
//PCM_POST_BLOCK
|
|
//CmpAllocateSlavePostBlock(
|
|
// IN POST_BLOCK_TYPE BlockType,
|
|
// IN PCM_KEY_BODY KeyBody,
|
|
// IN PCM_POST_BLOCK MasterBlock
|
|
// );
|
|
//
|
|
#define CmpAllocateSlavePostBlock(b,k,m) CmpAllocatePostBlock(b,0,k,m)
|
|
|
|
VOID
|
|
CmpFreePostBlock(
|
|
IN PCM_POST_BLOCK PostBlock
|
|
);
|
|
|
|
VOID
|
|
CmpPostApc(
|
|
struct _KAPC *Apc,
|
|
PKNORMAL_ROUTINE *NormalRoutine,
|
|
PVOID *NormalContext,
|
|
PVOID *SystemArgument1,
|
|
PVOID *SystemArgument2
|
|
);
|
|
|
|
VOID
|
|
CmpFlushNotify(
|
|
PCM_KEY_BODY KeyBody,
|
|
BOOLEAN LockHeld
|
|
);
|
|
|
|
VOID
|
|
CmpPostApcRunDown(
|
|
struct _KAPC *Apc
|
|
);
|
|
|
|
NTSTATUS
|
|
CmpOpenHiveFiles(
|
|
PUNICODE_STRING BaseName,
|
|
PWSTR Extension OPTIONAL,
|
|
PHANDLE Primary,
|
|
PHANDLE Secondary,
|
|
PULONG PrimaryDisposition,
|
|
PULONG SecondaryDispoition,
|
|
BOOLEAN CreateAllowed,
|
|
BOOLEAN MarkAsSystemHive,
|
|
BOOLEAN NoBuffering,
|
|
PULONG ClusterSize
|
|
);
|
|
|
|
NTSTATUS
|
|
CmpLinkHiveToMaster(
|
|
PUNICODE_STRING LinkName,
|
|
HANDLE RootDirectory,
|
|
PCMHIVE CmHive,
|
|
BOOLEAN Allocate,
|
|
PSECURITY_DESCRIPTOR SecurityDescriptor
|
|
);
|
|
|
|
NTSTATUS
|
|
CmpSaveBootControlSet(
|
|
IN USHORT ControlSetNum
|
|
);
|
|
|
|
//
|
|
// checkout procedure
|
|
//
|
|
|
|
//
|
|
// Flags to be passed to CmCheckRegistry
|
|
//
|
|
#define CM_CHECK_REGISTRY_CHECK_CLEAN 0x00000001
|
|
#define CM_CHECK_REGISTRY_FORCE_CLEAN 0x00000002
|
|
#define CM_CHECK_REGISTRY_LOADER_CLEAN 0x00000004
|
|
#define CM_CHECK_REGISTRY_SYSTEM_CLEAN 0x00000008
|
|
#define CM_CHECK_REGISTRY_HIVE_CHECK 0x00010000
|
|
|
|
ULONG
|
|
CmCheckRegistry(
|
|
PCMHIVE CmHive,
|
|
ULONG Flags
|
|
);
|
|
|
|
BOOLEAN
|
|
CmpValidateHiveSecurityDescriptors(
|
|
IN PHHIVE Hive,
|
|
OUT PBOOLEAN ResetSD
|
|
);
|
|
|
|
//
|
|
// cmboot - functions for determining driver load lists
|
|
//
|
|
|
|
#define CM_HARDWARE_PROFILE_STR_DATABASE L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\IDConfigDB"
|
|
#define CM_HARDWARE_PROFILE_STR_CCS_HWPROFILE L"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles"
|
|
#define CM_HARDWARE_PROFILE_STR_CCS_CURRENT L"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\Current"
|
|
//
|
|
// Alias table key names in IDConfigDB
|
|
//
|
|
#define CM_HARDWARE_PROFILE_STR_ALIAS L"Alias"
|
|
#define CM_HARDWARE_PROFILE_STR_ACPI_ALIAS L"AcpiAlias"
|
|
#define CM_HARDWARE_PROFILE_STR_HARDWARE_PROFILES L"Hardware Profiles"
|
|
|
|
//
|
|
// Entries in the alias tables (value names)
|
|
//
|
|
#define CM_HARDWARE_PROFILE_STR_DOCKING_STATE L"DockingState"
|
|
#define CM_HARDWARE_PROFILE_STR_CAPABILITIES L"Capabilities"
|
|
#define CM_HARDWARE_PROFILE_STR_DOCKID L"DockID"
|
|
#define CM_HARDWARE_PROFILE_STR_SERIAL_NUMBER L"SerialNumber"
|
|
#define CM_HARDWARE_PROFILE_STR_ACPI_SERIAL_NUMBER L"AcpiSerialNumber"
|
|
#define CM_HARDWARE_PROFILE_STR_PROFILE_NUMBER L"ProfileNumber"
|
|
#define CM_HARDWARE_PROFILE_STR_ALIASABLE L"Aliasable"
|
|
#define CM_HARDWARE_PROFILE_STR_CLONED L"Cloned"
|
|
//
|
|
// Entries in the profile tables.
|
|
//
|
|
#define CM_HARDWARE_PROFILE_STR_PRISTINE L"Pristine"
|
|
#define CM_HARDWARE_PROFILE_STR_PREFERENCE_ORDER L"PreferenceOrder"
|
|
#define CM_HARDWARE_PROFILE_STR_FRIENDLY_NAME L"FriendlyName"
|
|
#define CM_HARDWARE_PROFILE_STR_CURRENT_DOCK_INFO L"CurrentDockInfo"
|
|
#define CM_HARDWARE_PROFILE_STR_HW_PROFILE_GUID L"HwProfileGuid"
|
|
//
|
|
// Entries for the root Hardware Profiles key.
|
|
//
|
|
#define CM_HARDWARE_PROFILE_STR_DOCKED L"Docked"
|
|
#define CM_HARDWARE_PROFILE_STR_UNDOCKED L"Undocked"
|
|
#define CM_HARDWARE_PROFILE_STR_UNKNOWN L"Unknown"
|
|
|
|
//
|
|
// List structure used in config manager init
|
|
//
|
|
|
|
typedef struct _HIVE_LIST_ENTRY {
|
|
PWSTR Name;
|
|
PWSTR BaseName; // MACHINE or USER
|
|
PCMHIVE CmHive;
|
|
ULONG HHiveFlags;
|
|
ULONG CmHiveFlags;
|
|
PCMHIVE CmHive2;
|
|
BOOLEAN ThreadFinished;
|
|
BOOLEAN ThreadStarted;
|
|
BOOLEAN Allocate;
|
|
} HIVE_LIST_ENTRY, *PHIVE_LIST_ENTRY;
|
|
|
|
//
|
|
// structure definitions shared with the boot loader
|
|
// to select the hardware profile.
|
|
//
|
|
typedef struct _CM_HARDWARE_PROFILE {
|
|
ULONG NameLength;
|
|
PWSTR FriendlyName;
|
|
ULONG PreferenceOrder;
|
|
ULONG Id;
|
|
ULONG Flags;
|
|
} CM_HARDWARE_PROFILE, *PCM_HARDWARE_PROFILE;
|
|
|
|
#define CM_HP_FLAGS_ALIASABLE 1
|
|
#define CM_HP_FLAGS_TRUE_MATCH 2
|
|
#define CM_HP_FLAGS_PRISTINE 4
|
|
#define CM_HP_FLAGS_DUPLICATE 8
|
|
|
|
typedef struct _CM_HARDWARE_PROFILE_LIST {
|
|
ULONG MaxProfileCount;
|
|
ULONG CurrentProfileCount;
|
|
CM_HARDWARE_PROFILE Profile[1];
|
|
} CM_HARDWARE_PROFILE_LIST, *PCM_HARDWARE_PROFILE_LIST;
|
|
|
|
typedef struct _CM_HARDWARE_PROFILE_ALIAS {
|
|
ULONG ProfileNumber;
|
|
ULONG DockState;
|
|
ULONG DockID;
|
|
ULONG SerialNumber;
|
|
} CM_HARDWARE_PROFILE_ALIAS, *PCM_HARDWARE_PROFILE_ALIAS;
|
|
|
|
typedef struct _CM_HARDWARE_PROFILE_ALIAS_LIST {
|
|
ULONG MaxAliasCount;
|
|
ULONG CurrentAliasCount;
|
|
CM_HARDWARE_PROFILE_ALIAS Alias[1];
|
|
} CM_HARDWARE_PROFILE_ALIAS_LIST, *PCM_HARDWARE_PROFILE_ALIAS_LIST;
|
|
|
|
typedef struct _CM_HARDWARE_PROFILE_ACPI_ALIAS {
|
|
ULONG ProfileNumber;
|
|
ULONG DockState;
|
|
ULONG SerialLength;
|
|
PCHAR SerialNumber;
|
|
} CM_HARDWARE_PROFILE_ACPI_ALIAS, *PCM_HARDWARE_PROFILE_ACPI_ALIAS;
|
|
|
|
typedef struct _CM_HARDWARE_PROFILE_ACPI_ALIAS_LIST {
|
|
ULONG MaxAliasCount;
|
|
ULONG CurrentAliasCount;
|
|
CM_HARDWARE_PROFILE_ACPI_ALIAS Alias[1];
|
|
} CM_HARDWARE_PROFILE_ACPI_ALIAS_LIST, *PCM_HARDWARE_PROFILE_ACPI_ALIAS_LIST;
|
|
|
|
HCELL_INDEX
|
|
CmpFindControlSet(
|
|
IN PHHIVE SystemHive,
|
|
IN HCELL_INDEX RootCell,
|
|
IN PUNICODE_STRING SelectName,
|
|
OUT PBOOLEAN AutoSelect
|
|
);
|
|
|
|
BOOLEAN
|
|
CmpValidateSelect(
|
|
IN PHHIVE SystemHive,
|
|
IN HCELL_INDEX RootCell
|
|
);
|
|
|
|
BOOLEAN
|
|
CmpFindDrivers(
|
|
IN PHHIVE Hive,
|
|
IN HCELL_INDEX ControlSet,
|
|
IN SERVICE_LOAD_TYPE LoadType,
|
|
IN PWSTR BootFileSystem OPTIONAL,
|
|
IN PLIST_ENTRY DriverListHead
|
|
);
|
|
|
|
BOOLEAN
|
|
CmpFindNLSData(
|
|
IN PHHIVE Hive,
|
|
IN HCELL_INDEX ControlSet,
|
|
OUT PUNICODE_STRING AnsiFilename,
|
|
OUT PUNICODE_STRING OemFilename,
|
|
OUT PUNICODE_STRING CaseTableFilename,
|
|
OUT PUNICODE_STRING OemHalFilename
|
|
);
|
|
|
|
HCELL_INDEX
|
|
CmpFindProfileOption(
|
|
IN PHHIVE Hive,
|
|
IN HCELL_INDEX ControlSet,
|
|
OUT PCM_HARDWARE_PROFILE_LIST *ProfileList,
|
|
OUT PCM_HARDWARE_PROFILE_ALIAS_LIST *AliasList,
|
|
OUT PULONG Timeout
|
|
);
|
|
|
|
VOID
|
|
CmpSetCurrentProfile(
|
|
IN PHHIVE Hive,
|
|
IN HCELL_INDEX ControlSet,
|
|
IN PCM_HARDWARE_PROFILE Profile
|
|
);
|
|
|
|
BOOLEAN
|
|
CmpResolveDriverDependencies(
|
|
IN PLIST_ENTRY DriverListHead
|
|
);
|
|
|
|
BOOLEAN
|
|
CmpSortDriverList(
|
|
IN PHHIVE Hive,
|
|
IN HCELL_INDEX ControlSet,
|
|
IN PLIST_ENTRY DriverListHead
|
|
);
|
|
|
|
HCELL_INDEX
|
|
CmpFindSubKeyByName(
|
|
PHHIVE Hive,
|
|
PCM_KEY_NODE Parent,
|
|
PUNICODE_STRING SearchName
|
|
);
|
|
|
|
HCELL_INDEX
|
|
CmpFindSubKeyByNumber(
|
|
PHHIVE Hive,
|
|
PCM_KEY_NODE Parent,
|
|
ULONG Number
|
|
);
|
|
|
|
BOOLEAN
|
|
CmpAddSubKey(
|
|
PHHIVE Hive,
|
|
HCELL_INDEX Parent,
|
|
HCELL_INDEX Child
|
|
);
|
|
|
|
BOOLEAN
|
|
CmpMarkIndexDirty(
|
|
PHHIVE Hive,
|
|
HCELL_INDEX ParentKey,
|
|
HCELL_INDEX TargetKey
|
|
);
|
|
|
|
BOOLEAN
|
|
CmpRemoveSubKey(
|
|
PHHIVE Hive,
|
|
HCELL_INDEX ParentKey,
|
|
HCELL_INDEX TargetKey
|
|
);
|
|
|
|
BOOLEAN
|
|
CmpGetNextName(
|
|
IN OUT PUNICODE_STRING RemainingName,
|
|
OUT PUNICODE_STRING NextName,
|
|
OUT PBOOLEAN Last
|
|
);
|
|
|
|
NTSTATUS
|
|
CmpAddToHiveFileList(
|
|
PCMHIVE CmHive
|
|
);
|
|
|
|
VOID
|
|
CmpRemoveFromHiveFileList(
|
|
);
|
|
|
|
NTSTATUS
|
|
CmpInitHiveFromFile(
|
|
IN PUNICODE_STRING FileName,
|
|
IN ULONG HiveFlags,
|
|
OUT PCMHIVE *CmHive,
|
|
IN OUT PBOOLEAN Allocate,
|
|
IN OUT PBOOLEAN RegistryLocked,
|
|
IN ULONG CheckFlags
|
|
);
|
|
|
|
NTSTATUS
|
|
CmpCloneHwProfile (
|
|
IN HANDLE IDConfigDB,
|
|
IN HANDLE Parent,
|
|
IN HANDLE OldProfile,
|
|
IN ULONG OldProfileNumber,
|
|
IN USHORT DockingState,
|
|
OUT PHANDLE NewProfile,
|
|
OUT PULONG NewProfileNumber
|
|
);
|
|
|
|
NTSTATUS
|
|
CmpCreateHwProfileFriendlyName (
|
|
IN HANDLE IDConfigDB,
|
|
IN ULONG DockingState,
|
|
IN ULONG NewProfileNumber,
|
|
OUT PUNICODE_STRING FriendlyName
|
|
);
|
|
|
|
typedef
|
|
NTSTATUS
|
|
(*PCM_ACPI_SELECTION_ROUTINE) (
|
|
IN PCM_HARDWARE_PROFILE_LIST ProfileList,
|
|
OUT PULONG ProfileIndexToUse, // Set to -1 for none.
|
|
IN PVOID Context
|
|
);
|
|
|
|
NTSTATUS
|
|
CmSetAcpiHwProfile (
|
|
IN PPROFILE_ACPI_DOCKING_STATE DockState,
|
|
IN PCM_ACPI_SELECTION_ROUTINE,
|
|
IN PVOID Context,
|
|
OUT PHANDLE NewProfile,
|
|
OUT PBOOLEAN ProfileChanged
|
|
);
|
|
|
|
NTSTATUS
|
|
CmpAddAcpiAliasEntry (
|
|
IN HANDLE IDConfigDB,
|
|
IN PPROFILE_ACPI_DOCKING_STATE NewDockState,
|
|
IN ULONG ProfileNumber,
|
|
IN PWCHAR nameBuffer,
|
|
IN PVOID valueBuffer,
|
|
IN ULONG valueBufferLength,
|
|
IN BOOLEAN PreventDuplication
|
|
);
|
|
|
|
//
|
|
// Routines for handling registry compressed names
|
|
//
|
|
USHORT
|
|
CmpNameSize(
|
|
IN PHHIVE Hive,
|
|
IN PUNICODE_STRING Name
|
|
);
|
|
|
|
USHORT
|
|
CmpCopyName(
|
|
IN PHHIVE Hive,
|
|
IN PWCHAR Destination,
|
|
IN PUNICODE_STRING Source
|
|
);
|
|
|
|
VOID
|
|
CmpCopyCompressedName(
|
|
IN PWCHAR Destination,
|
|
IN ULONG DestinationLength,
|
|
IN PWCHAR Source,
|
|
IN ULONG SourceLength
|
|
);
|
|
|
|
USHORT
|
|
CmpCompressedNameSize(
|
|
IN PWCHAR Name,
|
|
IN ULONG Length
|
|
);
|
|
|
|
|
|
//
|
|
// ----- CACHED_DATA -----
|
|
//
|
|
// When values are not cached, List in ValueCache is the Hive cell index to the value list.
|
|
// When they are cached, List will be pointer to the allocation. We distinguish them by
|
|
// marking the lowest bit in the variable to indicate it is a cached allocation.
|
|
//
|
|
// Note that the cell index for value list
|
|
// is stored in the cached allocation. It is not used now but may be in further performance
|
|
// optimization.
|
|
//
|
|
// When value key and vaule data are cached, there is only one allocation for both.
|
|
// Value data is appended that the end of value key. DataCacheType indicates
|
|
// whether data is cached and ValueKeySize tells how big is the value key (so
|
|
// we can calculate the address of cached value data)
|
|
//
|
|
//
|
|
|
|
PCM_NAME_CONTROL_BLOCK
|
|
CmpGetNameControlBlock(
|
|
PUNICODE_STRING NodeName
|
|
);
|
|
|
|
VOID
|
|
CmpDereferenceKeyControlBlockWithLock(
|
|
PCM_KEY_CONTROL_BLOCK KeyControlBlock
|
|
);
|
|
|
|
VOID
|
|
CmpCleanUpSubKeyInfo(
|
|
PCM_KEY_CONTROL_BLOCK KeyControlBlock
|
|
);
|
|
|
|
VOID
|
|
CmpCleanUpKcbValueCache(
|
|
PCM_KEY_CONTROL_BLOCK KeyControlBlock
|
|
);
|
|
|
|
|
|
VOID
|
|
CmpRebuildKcbCache(
|
|
PCM_KEY_CONTROL_BLOCK KeyControlBlock
|
|
);
|
|
|
|
|
|
|
|
/*
|
|
VOID
|
|
CmpSetUpKcbValueCache(
|
|
PCM_KEY_CONTROL_BLOCK KeyControlBlock,
|
|
ULONG Count,
|
|
ULONG_PTR ValueList
|
|
)
|
|
*/
|
|
#define CmpSetUpKcbValueCache(KeyControlBlock,_Count,_List) \
|
|
ASSERT( !(CMP_IS_CELL_CACHED(KeyControlBlock->ValueCache.ValueList)) ); \
|
|
ASSERT( !(KeyControlBlock->ExtFlags & CM_KCB_SYM_LINK_FOUND) ); \
|
|
KeyControlBlock->ValueCache.Count = (ULONG)(_Count); \
|
|
KeyControlBlock->ValueCache.ValueList = (ULONG_PTR)(_List)
|
|
|
|
|
|
VOID
|
|
CmpCleanUpKcbCacheWithLock(
|
|
PCM_KEY_CONTROL_BLOCK KeyControlBlock
|
|
);
|
|
|
|
VOID
|
|
CmpRemoveFromDelayedClose(
|
|
IN PCM_KEY_CONTROL_BLOCK kcb
|
|
);
|
|
|
|
PUNICODE_STRING
|
|
CmpConstructName(
|
|
PCM_KEY_CONTROL_BLOCK kcb
|
|
);
|
|
|
|
PCELL_DATA
|
|
CmpGetValueListFromCache(
|
|
IN PHHIVE Hive,
|
|
IN PCACHED_CHILD_LIST ChildList,
|
|
OUT BOOLEAN *IndexCached,
|
|
OUT PHCELL_INDEX ValueListToRelease
|
|
);
|
|
|
|
PCM_KEY_VALUE
|
|
CmpGetValueKeyFromCache(
|
|
IN PHHIVE Hive,
|
|
IN PCELL_DATA List,
|
|
IN ULONG Index,
|
|
OUT PPCM_CACHED_VALUE *ContainingList,
|
|
IN BOOLEAN IndexCached,
|
|
OUT BOOLEAN *ValueCached,
|
|
OUT PHCELL_INDEX CellToRelease
|
|
);
|
|
|
|
PCM_KEY_VALUE
|
|
CmpFindValueByNameFromCache(
|
|
IN PHHIVE Hive,
|
|
IN PCACHED_CHILD_LIST ChildList,
|
|
IN PUNICODE_STRING Name,
|
|
OUT PPCM_CACHED_VALUE *ContainingList,
|
|
OUT ULONG *Index,
|
|
OUT BOOLEAN *ValueCached,
|
|
OUT PHCELL_INDEX CellToRelease
|
|
);
|
|
|
|
NTSTATUS
|
|
CmpQueryKeyValueData(
|
|
PHHIVE Hive,
|
|
PCM_CACHED_VALUE *ContainingList,
|
|
PCM_KEY_VALUE ValueKey,
|
|
BOOLEAN ValueCached,
|
|
KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
|
|
PVOID KeyValueInformation,
|
|
ULONG Length,
|
|
PULONG ResultLength
|
|
);
|
|
|
|
BOOLEAN
|
|
CmpReferenceKeyControlBlock(
|
|
PCM_KEY_CONTROL_BLOCK KeyControlBlock
|
|
);
|
|
|
|
VOID
|
|
CmpInitializeKeyNameString(PCM_KEY_NODE Cell,
|
|
PUNICODE_STRING KeyName,
|
|
WCHAR *NameBuffer
|
|
);
|
|
|
|
VOID
|
|
CmpInitializeValueNameString(PCM_KEY_VALUE Cell,
|
|
PUNICODE_STRING ValueName,
|
|
WCHAR *NameBuffer
|
|
);
|
|
|
|
VOID
|
|
CmpFlushNotifiesOnKeyBodyList(
|
|
IN PCM_KEY_CONTROL_BLOCK kcb
|
|
);
|
|
|
|
#ifdef CM_NOTIFY_CHANGED_KCB_FULLPATH
|
|
VOID
|
|
CmpFillCallerBuffer(
|
|
PCM_POST_BLOCK PostBlock,
|
|
PUNICODE_STRING ChangedKcbName
|
|
);
|
|
#endif //CM_NOTIFY_CHANGED_KCB_FULLPATH
|
|
|
|
extern ULONG CmpHashTableSize;
|
|
extern PCM_KEY_HASH *CmpCacheTable;
|
|
|
|
#ifdef _WANT_MACHINE_IDENTIFICATION
|
|
|
|
BOOLEAN
|
|
CmpGetBiosDateFromRegistry(
|
|
IN PHHIVE Hive,
|
|
IN HCELL_INDEX ControlSet,
|
|
OUT PUNICODE_STRING Date
|
|
);
|
|
|
|
BOOLEAN
|
|
CmpGetBiosinfoFileNameFromRegistry(
|
|
IN PHHIVE Hive,
|
|
IN HCELL_INDEX ControlSet,
|
|
OUT PUNICODE_STRING InfName
|
|
);
|
|
|
|
|
|
#endif
|
|
|
|
// Utility macro to set the fields of an IO_STATUS_BLOCK. On sundown, 32bit processes
|
|
// will pass in a 32bit Iosb, and 64bit processes will pass in a 64bit Iosb.
|
|
#if defined(_WIN64)
|
|
|
|
#define CmpSetIoStatus(Iosb, s, i, UseIosb32) \
|
|
if ((UseIosb32)) { \
|
|
((PIO_STATUS_BLOCK32)(Iosb))->Status = (NTSTATUS)(s); \
|
|
((PIO_STATUS_BLOCK32)(Iosb))->Information = (ULONG)(i); \
|
|
} \
|
|
else { \
|
|
(Iosb)->Status = (s); \
|
|
(Iosb)->Information = (i); \
|
|
} \
|
|
|
|
#else
|
|
|
|
#define CmpSetIoStatus(Iosb, s, i, UseIosb32) \
|
|
(Iosb)->Status = (s); \
|
|
(Iosb)->Information = (i); \
|
|
|
|
#endif
|
|
|
|
#define CmpCheckIoStatusPointer(AsyncUser) \
|
|
if( (PVOID)((AsyncUser).IoStatusBlock) == (PVOID)(&((AsyncUser).IoStatusBlock)) ) { \
|
|
DbgPrint("IoStatusBlock pointing onto itself AsyncUser = %p\n",&(AsyncUser)); \
|
|
DbgBreakPoint(); \
|
|
}
|
|
|
|
|
|
// Dragos: new functions (prototyping)
|
|
|
|
NTSTATUS
|
|
CmpAquireFileObjectForFile(
|
|
IN PCMHIVE CmHive,
|
|
IN HANDLE FileHandle,
|
|
OUT PFILE_OBJECT *FileObject
|
|
);
|
|
|
|
VOID
|
|
CmpDropFileObjectForHive(
|
|
IN PCMHIVE CmHive
|
|
);
|
|
|
|
VOID
|
|
CmpTouchView(
|
|
IN PCMHIVE CmHive,
|
|
IN PCM_VIEW_OF_FILE CmView,
|
|
IN ULONG Cell
|
|
);
|
|
|
|
NTSTATUS
|
|
CmpMapCmView(
|
|
IN PCMHIVE CmHive,
|
|
IN ULONG FileOffset,
|
|
OUT PCM_VIEW_OF_FILE *CmView,
|
|
IN BOOLEAN MapInited
|
|
);
|
|
|
|
VOID
|
|
CmpInitHiveViewList (
|
|
IN PCMHIVE CmHive
|
|
);
|
|
|
|
VOID
|
|
CmpDestroyHiveViewList (
|
|
IN PCMHIVE CmHive
|
|
);
|
|
|
|
NTSTATUS
|
|
CmpPinCmView (
|
|
IN PCMHIVE CmHive,
|
|
PCM_VIEW_OF_FILE CmView
|
|
);
|
|
VOID
|
|
CmpUnPinCmView (
|
|
IN PCMHIVE CmHive,
|
|
IN PCM_VIEW_OF_FILE CmView,
|
|
IN BOOLEAN SetClean,
|
|
IN BOOLEAN MapIsValid
|
|
);
|
|
|
|
NTSTATUS
|
|
CmpMapThisBin(
|
|
PCMHIVE CmHive,
|
|
HCELL_INDEX Cell,
|
|
BOOLEAN Touch
|
|
);
|
|
#if 0
|
|
VOID
|
|
CmpUnmapAditionalViews(
|
|
IN PCMHIVE CmHive
|
|
);
|
|
|
|
VOID
|
|
CmpUnmapFakeViews(
|
|
IN PCMHIVE CmHive
|
|
);
|
|
|
|
VOID
|
|
CmpMapEntireFileInFakeViews(
|
|
IN PCMHIVE CmHive,
|
|
IN ULONG Length
|
|
);
|
|
|
|
#endif
|
|
|
|
VOID
|
|
CmpInitializeDelayedCloseTable();
|
|
|
|
VOID
|
|
CmpAddToDelayedClose(
|
|
IN PCM_KEY_CONTROL_BLOCK kcb
|
|
);
|
|
|
|
NTSTATUS
|
|
CmpAddValueToList(
|
|
IN PHHIVE Hive,
|
|
IN HCELL_INDEX ValueCell,
|
|
IN ULONG Index,
|
|
IN ULONG Type,
|
|
IN OUT PCHILD_LIST ChildList
|
|
);
|
|
|
|
NTSTATUS
|
|
CmpRemoveValueFromList(
|
|
IN PHHIVE Hive,
|
|
IN ULONG Index,
|
|
IN OUT PCHILD_LIST ChildList
|
|
);
|
|
|
|
BOOLEAN
|
|
CmpGetValueData(IN PHHIVE Hive,
|
|
IN PCM_KEY_VALUE Value,
|
|
OUT PULONG realsize,
|
|
IN OUT PVOID *Buffer,
|
|
OUT PBOOLEAN Allocated,
|
|
OUT PHCELL_INDEX CellToRelease
|
|
);
|
|
|
|
PCELL_DATA
|
|
CmpValueToData(IN PHHIVE Hive,
|
|
IN PCM_KEY_VALUE Value,
|
|
OUT PULONG realsize
|
|
);
|
|
|
|
BOOLEAN
|
|
CmpMarkValueDataDirty( IN PHHIVE Hive,
|
|
IN PCM_KEY_VALUE Value
|
|
);
|
|
|
|
NTSTATUS
|
|
CmpSetValueDataNew(
|
|
IN PHHIVE Hive,
|
|
IN PVOID Data,
|
|
IN ULONG DataSize,
|
|
IN ULONG StorageType,
|
|
IN HCELL_INDEX ValueCell,
|
|
OUT PHCELL_INDEX DataCell
|
|
);
|
|
|
|
NTSTATUS
|
|
CmpSetValueDataExisting(
|
|
IN PHHIVE Hive,
|
|
IN PVOID Data,
|
|
IN ULONG DataSize,
|
|
IN ULONG StorageType,
|
|
IN HCELL_INDEX OldDataCell
|
|
);
|
|
|
|
BOOLEAN
|
|
CmpFreeValueData(
|
|
PHHIVE Hive,
|
|
HCELL_INDEX DataCell,
|
|
ULONG DataLength
|
|
);
|
|
|
|
|
|
NTSTATUS
|
|
CmpAddSecurityCellToCache (
|
|
IN OUT PCMHIVE CmHive,
|
|
IN HCELL_INDEX SecurityCell,
|
|
IN BOOLEAN BuildUp,
|
|
IN PCM_KEY_SECURITY_CACHE SecurityCached
|
|
);
|
|
|
|
BOOLEAN
|
|
CmpFindSecurityCellCacheIndex (
|
|
IN PCMHIVE CmHive,
|
|
IN HCELL_INDEX SecurityCell,
|
|
OUT PULONG Index
|
|
);
|
|
|
|
BOOLEAN
|
|
CmpAdjustSecurityCacheSize (
|
|
IN PCMHIVE CmHive
|
|
);
|
|
|
|
VOID
|
|
CmpRemoveFromSecurityCache (
|
|
IN OUT PCMHIVE CmHive,
|
|
IN HCELL_INDEX SecurityCell
|
|
);
|
|
|
|
VOID
|
|
CmpDestroySecurityCache (
|
|
IN OUT PCMHIVE CmHive
|
|
);
|
|
|
|
|
|
VOID
|
|
CmpInitSecurityCache(
|
|
IN OUT PCMHIVE CmHive
|
|
);
|
|
|
|
BOOLEAN
|
|
CmpRebuildSecurityCache(
|
|
IN OUT PCMHIVE CmHive
|
|
);
|
|
|
|
ULONG
|
|
CmpSecConvKey(
|
|
IN ULONG DescriptorLength,
|
|
IN PULONG Descriptor
|
|
);
|
|
|
|
VOID
|
|
CmpAssignSecurityToKcb(
|
|
IN PCM_KEY_CONTROL_BLOCK Kcb,
|
|
IN HCELL_INDEX SecurityCell
|
|
);
|
|
|
|
BOOLEAN
|
|
CmpBuildSecurityCellMappingArray(
|
|
IN PCMHIVE CmHive
|
|
);
|
|
|
|
|
|
//
|
|
// new function replacing CmpWorker
|
|
//
|
|
VOID
|
|
CmpCmdHiveClose(
|
|
PCMHIVE CmHive
|
|
);
|
|
|
|
VOID
|
|
CmpCmdInit(
|
|
BOOLEAN SetupBoot
|
|
);
|
|
|
|
NTSTATUS
|
|
CmpCmdRenameHive(
|
|
PCMHIVE CmHive,
|
|
POBJECT_NAME_INFORMATION OldName,
|
|
PUNICODE_STRING NewName,
|
|
ULONG NameInfoLength
|
|
);
|
|
|
|
NTSTATUS
|
|
CmpCmdHiveOpen(
|
|
POBJECT_ATTRIBUTES FileAttributes,
|
|
PSECURITY_CLIENT_CONTEXT ImpersonationContext,
|
|
PBOOLEAN Allocate,
|
|
PBOOLEAN RegistryLockAquired,
|
|
PCMHIVE *NewHive,
|
|
ULONG CheckFlags
|
|
);
|
|
|
|
#ifdef NT_RENAME_KEY
|
|
HCELL_INDEX
|
|
CmpDuplicateIndex(
|
|
PHHIVE Hive,
|
|
HCELL_INDEX IndexCell,
|
|
ULONG StorageType
|
|
);
|
|
|
|
NTSTATUS
|
|
CmRenameKey(
|
|
IN PCM_KEY_CONTROL_BLOCK KeyControlBlock,
|
|
IN UNICODE_STRING NewKeyName
|
|
);
|
|
|
|
BOOLEAN
|
|
CmpUpdateParentForEachSon(
|
|
PHHIVE Hive,
|
|
HCELL_INDEX Parent
|
|
);
|
|
#endif //NT_RENAME_KEY
|
|
|
|
#ifdef NT_UNLOAD_KEY_EX
|
|
NTSTATUS
|
|
CmUnloadKeyEx(
|
|
IN PCM_KEY_CONTROL_BLOCK Kcb,
|
|
IN PKEVENT UserEvent
|
|
);
|
|
#endif //NT_UNLOAD_KEY_EX
|
|
|
|
VOID
|
|
CmpShutdownWorkers(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
CmpPrefetchHiveFile(
|
|
IN PFILE_OBJECT FileObject,
|
|
IN ULONG Length
|
|
);
|
|
|
|
#ifdef CM_CHECK_FOR_ORPHANED_KCBS
|
|
VOID
|
|
CmpCheckForOrphanedKcbs(
|
|
PHHIVE Hive
|
|
);
|
|
#else
|
|
|
|
#define CmpCheckForOrphanedKcbs(Hive) //nothing
|
|
#endif //CM_CHECK_FOR_ORPHANED_KCBS
|
|
|
|
#define CM_HIVE_COMPRESS_LEVEL (25)
|
|
|
|
|
|
#define CMP_MAX_REGISTRY_DEPTH 512 // levels
|
|
|
|
typedef struct {
|
|
HCELL_INDEX Cell;
|
|
HCELL_INDEX ParentCell;
|
|
HCELL_INDEX PriorSibling;
|
|
ULONG ChildIndex;
|
|
BOOLEAN CellChecked;
|
|
} CMP_CHECK_REGISTRY_STACK_ENTRY, *PCMP_CHECK_REGISTRY_STACK_ENTRY;
|
|
|
|
|
|
#define CmIsKcbReadOnly(kcb) ((kcb)->ExtFlags & CM_KCB_READ_ONLY_KEY)
|
|
|
|
NTSTATUS
|
|
CmLockKcbForWrite(PCM_KEY_CONTROL_BLOCK KeyControlBlock);
|
|
|
|
//
|
|
// Wrapper to RtlCompareUnicodeString; uses CompareFlags to avoid upcasing names
|
|
//
|
|
|
|
#define CMP_SOURCE_UP 0x00000001
|
|
#define CMP_DEST_UP 0x00000002
|
|
|
|
LONG
|
|
CmpCompareUnicodeString(
|
|
IN PUNICODE_STRING SourceName,
|
|
IN PUNICODE_STRING DestName,
|
|
IN ULONG CompareFlags
|
|
);
|
|
|
|
LONG
|
|
CmpCompareCompressedName(
|
|
IN PUNICODE_STRING SearchName,
|
|
IN PWCHAR CompressedName,
|
|
IN ULONG NameLength,
|
|
IN ULONG CompareFlags
|
|
);
|
|
|
|
LONG
|
|
CmpCompareTwoCompressedNames(
|
|
IN PWCHAR CompressedName1,
|
|
IN ULONG NameLength1,
|
|
IN PWCHAR CompressedName2,
|
|
IN ULONG NameLength2
|
|
);
|
|
|
|
#define INIT_SYSTEMROOT_HIVEPATH L"\\SystemRoot\\System32\\Config\\"
|
|
|
|
|
|
ULONG
|
|
CmpComputeHashKey(
|
|
PUNICODE_STRING Name
|
|
);
|
|
|
|
|
|
ULONG
|
|
CmpComputeHashKeyForCompressedName(
|
|
IN PWCHAR Source,
|
|
IN ULONG SourceLength
|
|
);
|
|
//
|
|
// KCB allocator routines
|
|
//
|
|
VOID CmpInitCmPrivateAlloc();
|
|
VOID CmpDestroyCmPrivateAlloc();
|
|
PCM_KEY_CONTROL_BLOCK CmpAllocateKeyControlBlock( );
|
|
VOID CmpFreeKeyControlBlock( PCM_KEY_CONTROL_BLOCK kcb );
|
|
|
|
|
|
//
|
|
// make handles protected, so we control handle closure
|
|
//
|
|
|
|
#define CmpSetHandleProtection(Handle,Protection) \
|
|
{ \
|
|
OBJECT_HANDLE_FLAG_INFORMATION Ohfi = { FALSE, \
|
|
FALSE \
|
|
}; \
|
|
Ohfi.ProtectFromClose = Protection; \
|
|
ZwSetInformationObject( Handle, \
|
|
ObjectHandleFlagInformation, \
|
|
&Ohfi, \
|
|
sizeof (OBJECT_HANDLE_FLAG_INFORMATION)); \
|
|
}
|
|
|
|
#define CmCloseHandle(Handle) \
|
|
CmpSetHandleProtection(Handle,FALSE); \
|
|
ZwClose(Handle)
|
|
|
|
|
|
VOID
|
|
CmpUpdateSystemHiveHysteresis( PHHIVE Hive,
|
|
ULONG NewLength,
|
|
ULONG OldLength
|
|
);
|
|
|
|
NTSTATUS
|
|
CmpCallCallBacks (
|
|
IN REG_NOTIFY_CLASS Type,
|
|
IN PVOID Argument
|
|
);
|
|
|
|
extern ULONG CmpCallBackCount;
|
|
|
|
#define CmAreCallbacksRegistered() ((CmpCallBackCount != 0) && (0 == ExIsResourceAcquiredShared(&CmpRegistryLock)))
|
|
|
|
#define CmPostCallbackNotification(Type,_Object_,_Status_) \
|
|
if( CmAreCallbacksRegistered() ) { \
|
|
REG_POST_OPERATION_INFORMATION PostInfo; \
|
|
PostInfo.Object = _Object_; \
|
|
PostInfo.Status = _Status_; \
|
|
CmpCallCallBacks(Type,&PostInfo); \
|
|
}
|
|
|
|
//
|
|
// Self healing hives control switch
|
|
//
|
|
extern BOOLEAN CmpSelfHeal;
|
|
extern ULONG CmpBootType;
|
|
|
|
#define CmDoSelfHeal() (CmpSelfHeal || (CmpBootType & (HBOOT_BACKUP|HBOOT_SELFHEAL)))
|
|
|
|
|
|
#define CmMarkSelfHeal(Hive) ( (Hive)->BaseBlock->BootType |= HBOOT_SELFHEAL )
|
|
|
|
/*
|
|
#ifndef _CM_LDR_
|
|
#if DBG
|
|
#define CmMarkSelfHeal(Hive) ( (Hive)->BaseBlock->BootType |= HBOOT_SELFHEAL ); \
|
|
DbgBreakPoint()
|
|
#else
|
|
#define CmMarkSelfHeal(Hive) ( (Hive)->BaseBlock->BootType |= HBOOT_SELFHEAL )
|
|
#endif
|
|
#else
|
|
#define CmMarkSelfHeal(Hive) ( (Hive)->BaseBlock->BootType |= HBOOT_SELFHEAL )
|
|
#endif
|
|
*/
|
|
|
|
BOOLEAN
|
|
CmpRemoveSubKeyCellNoCellRef(
|
|
PHHIVE Hive,
|
|
HCELL_INDEX Parent,
|
|
HCELL_INDEX Child
|
|
);
|
|
|
|
VOID
|
|
CmpRaiseSelfHealWarning(
|
|
IN PUNICODE_STRING HiveName
|
|
);
|
|
|
|
VOID
|
|
CmpRaiseSelfHealWarningForSystemHives();
|
|
|
|
|
|
//
|
|
// Tracking quota leaks helpers
|
|
//
|
|
#ifdef CM_TRACK_QUOTA_LEAKS
|
|
|
|
extern FAST_MUTEX CmpQuotaLeaksMutex;
|
|
|
|
typedef struct _CM_QUOTA_LOG_ENTRY {
|
|
LIST_ENTRY ListEntry;
|
|
PVOID Stack[9];
|
|
ULONG Size;
|
|
} CM_QUOTA_LOG_ENTRY, *PCM_QUOTA_LOG_ENTRY;
|
|
|
|
extern BOOLEAN CmpTrackQuotaEnabled;
|
|
extern LIST_ENTRY CmpTrackQuotaListHead;
|
|
|
|
#define CM_TRACK_QUOTA_START() \
|
|
InitializeListHead(&CmpTrackQuotaListHead); \
|
|
CmpTrackQuotaEnabled = TRUE
|
|
|
|
#define CM_TRACK_QUOTA_STOP() CmpTrackQuotaEnabled = FALSE
|
|
|
|
#else
|
|
#define CM_TRACK_QUOTA_START() //nothing
|
|
#define CM_TRACK_QUOTA_STOP() //nothing
|
|
#endif
|
|
|
|
|
|
//
|
|
// PERF: try inline ascii upcase
|
|
//
|
|
#define CmUpcaseUnicodeChar(c) \
|
|
( ((c) < 'a') ? (c) : ( ((c) > 'z') ? RtlUpcaseUnicodeChar(c) : ((c) - ('a'-'A')) ) )
|
|
|
|
|
|
//
|
|
// Mini NT boot indicator
|
|
//
|
|
extern BOOLEAN CmpMiniNTBoot;
|
|
extern BOOLEAN CmpShareSystemHives;
|
|
|
|
#endif //_CMP_
|