Leaked source code of windows server 2003
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

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. cmp.h
  5. Abstract:
  6. This module contains the private (internal) header file for the
  7. configuration manager.
  8. Author:
  9. Bryan M. Willman (bryanwi) 10-Sep-91
  10. Environment:
  11. Kernel mode only.
  12. Revision History:
  13. 13-Jan-99 Dragos C. Sambotin (dragoss) - factoring the data structure declarations
  14. in \nt\private\ntos\inc\cmdata.h :: to be available from outside.
  15. --*/
  16. #ifndef _CMP_
  17. #define _CMP_
  18. #pragma warning(disable:4214) // bit field types other than int
  19. #pragma warning(disable:4201) // nameless struct/union
  20. #pragma warning(disable:4324) // alignment sensitive to declspec
  21. #pragma warning(disable:4127) // condition expression is constant
  22. #pragma warning(disable:4115) // named type definition in parentheses
  23. #pragma warning(disable:4706) // assignment within conditional expression
  24. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  25. // Begin SCS (Switch Control Section)
  26. //
  27. // 1. Code to check consistency and to help catch bugs: To be turned on when problems
  28. // appear in that area; Word of caution: some of these switches may affect performance
  29. //
  30. #if DBG
  31. #define CMP_NOTIFY_POSTBLOCK_CHECK // controls the CmpCheckPostBlock macro, used to check
  32. // validity and consistency of a notify post block
  33. #define CMP_ENTRYLIST_MANIPULATION // controls the removal of an element from a LIST_ENTRY
  34. // by setting the Blink and Flink to NULL;
  35. // macros affected : IsListEmpty and RemoveEmptyList
  36. // WARNING : to be defined only when not linking against the loader
  37. #define CMP_KCB_CACHE_VALIDATION // validates KCB cached members changes by comparing against the knode values.
  38. // We shall disable this after proven the caching mechanism works OK
  39. //#define CMP_CMVIEW_VALIDATION // validates the view mapping mechanism
  40. #define CHECK_REGISTRY_USECOUNT // Validates the GetCell/ReleaseCell call matching, to ensure mapped views
  41. // don't get unmapped while in use
  42. //#define SYNC_HIVE_VALIDATION // validate the HvpDoWriteHive paged dirty data algorithm
  43. // We shall disable this after we catch saving alternate problem
  44. //#define HIVE_SECURITY_STATS // collect statistics about security cells
  45. //#define CMP_STATS // collect statistics about kcbs
  46. //#define WRITE_PROTECTED_REGISTRY_POOL // applies only for registry hives stored in paged pool
  47. // controls access over registry bins
  48. //#define WRITE_PROTECTED_VALUE_CACHE // protects pool allocations used for kcb value cache
  49. //#define DRAGOSS_PRIVATE_DEBUG // private debug session
  50. //#define CM_CHECK_MAP_NO_READ_SCHEME // validates the mapping code assumption (i.e. each bin map should start
  51. // with HMAP_NEW_ALLOC; this is true only for mapped bins
  52. #define REGISTRY_LOCK_CHECKING // on each Nt API level call, checks the thread has released all locks
  53. // acquired. We may want to remove it, as it can hide bugs in other components
  54. // below registry (Ob, Se, Ps, Mm)
  55. //#define CM_PERF_ISSUES // keep track of how long CmpInitializeHiveList and CmpConvertHiveToMapped takes
  56. #define CM_CHECK_FOR_ORPHANED_KCBS // check for orphaned kcbs every time we free a hive.
  57. #endif //DBG
  58. //#define CM_RETRY_CREATE_FILE // when an error is returned from ZwCreateFile calls, retry the call
  59. //#define CM_NOTIFY_CHANGED_KCB_FULLPATH // return the full qualified path of the changed kcb in the Buffer arg of NtNotifyChangeKey
  60. #if defined(_X86_)
  61. #define CM_LEAK_STACK_TRACES // keeps stacks traces for opened handles
  62. #endif //_X86_
  63. //
  64. // 2. these section controls whether or not a certain feature goes into product or not;
  65. // The goal is to remove these switches as new features are accepted, tested and proven to work
  66. //
  67. #ifndef _CM_LDR_
  68. #define NT_RENAME_KEY // NtRenameKey API
  69. #define NT_UNLOAD_KEY_EX // NtUnloadKeyEx API
  70. #endif //_CM_LDR_
  71. #define CM_ENABLE_MAPPED_VIEWS // controls whether the mapped views feature (using Cc interfaces) is used
  72. // by commenting this, registry hives are reverted to paged pool
  73. // WARNING: This should be always on !!!
  74. //#define CM_ENABLE_WRITE_ONLY_BINS // use MmSetPageProtection to catch writes on data not marked dirty
  75. #define CM_MAP_NO_READ // this switch contols whether we map (touch all pages) or just pin_no_read
  76. // now it makes sense to use this as mm will fault in one page at a time for
  77. // MNW streams
  78. #define CM_BREAK_ON_KEY_OPEN // breaks when a key with Flags & KEY_BREAK_ON_OPEN is opened or a subkey is added
  79. //#define CM_SAVE_KCB_CACHE // at shutdown, save the kcb cache into a file
  80. //#define CM_DYN_SYM_LINK // dynamic symbolic links enabled.
  81. //#define HV_TRACK_FREE_SPACE // keep track of the actual free space inside the hive
  82. //#define CM_TRACK_QUOTA_LEAKS //captures stack traces at every CmpAllocateXXX
  83. //
  84. // End SCS
  85. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  86. #ifdef CM_DYN_SYM_LINK
  87. #define REG_DYN_LINK 21 // this should be moved to the proper place
  88. #endif
  89. #include "ntos.h"
  90. #include "hive.h"
  91. #include "wchar.h"
  92. #include "zwapi.h"
  93. #include <stdio.h>
  94. #include <profiles.h>
  95. // bugcheck description and defines
  96. #include "cmpbug.h"
  97. #include "kddll.h"
  98. // CM data structure declarations
  99. // file location: \nt\private\ntos\inc
  100. #include "cmdata.h"
  101. #ifdef CMP_STATS
  102. VOID
  103. CmpKcbStat(
  104. VOID
  105. );
  106. #endif
  107. #ifndef _CM_LDR_
  108. #define CmKdPrintEx(_x_) KdPrintEx(_x_)
  109. #else
  110. #define CmKdPrintEx(_x_) //nothing
  111. #endif //_CM_LDR_
  112. #define _64K 64L*1024L //64K
  113. #define _256K 256L*1024L //256K
  114. #define IO_BUFFER_SIZE _64K //64K
  115. //
  116. // this constant defines the size of a Cc view that is mapped -in every time a cell
  117. // is accessed; It can be any power of 2, no less than 16K and no bigger than 256K
  118. //
  119. #define CM_VIEW_SIZE 16L*1024L //16K
  120. //
  121. // control the granularity the primary file grows;
  122. // Warning: this should be multiple of 4K (HBLOCK_SIZE) !!!
  123. //
  124. #define CM_FILE_GROW_INCREMENT 256L*1024L //256K
  125. //
  126. // this controls the maximmum adress space allowed per hive. It should be specified in
  127. // multiples of 256K
  128. //
  129. // 4 means 1 MB
  130. // 6 means 1.5 MB
  131. // 12 means 3 MB
  132. // .....
  133. //
  134. #define MAX_MB_PER_HIVE 16 // 4MB
  135. #define MAX_NAME 128
  136. #ifdef CMP_ENTRYLIST_MANIPULATION
  137. #define CmpRemoveEntryList(a) \
  138. if(((a)->Flink == NULL) && ((a)->Blink == NULL) ) {\
  139. DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"CmpRemoveEntryList: Entry %08lx\n",a);\
  140. DbgBreakPoint();\
  141. }\
  142. RemoveEntryList(a);\
  143. (a)->Flink = (a)->Blink = NULL
  144. #define CmpClearListEntry(a) (a)->Flink = (a)->Blink = NULL
  145. #define CmpIsListEmpty(a) ( ( ((a)->Flink == NULL) && ((a)->Blink == NULL) ) || ( ((a)->Flink != NULL) && ((a)->Blink != NULL) && IsListEmpty(a) ) )
  146. #else
  147. #define CmpRemoveEntryList(a) RemoveEntryList(a)
  148. #define CmpClearListEntry(a) //nothing
  149. #define CmpIsListEmpty(a) IsListEmpty(a)
  150. #endif // CMP_ENTRYLIST_MANIPULATION
  151. extern PCM_TRACE_NOTIFY_ROUTINE CmpTraceRoutine;
  152. VOID
  153. CmpWmiDumpKcb(
  154. PCM_KEY_CONTROL_BLOCK kcb
  155. );
  156. #define CmpWmiFireEvent(Status,Kcb,ElapsedTime,Index,KeyName,Type) \
  157. { \
  158. PCM_TRACE_NOTIFY_ROUTINE TraceRoutine = CmpTraceRoutine; \
  159. if( TraceRoutine != NULL ) { \
  160. (*TraceRoutine)(Status,Kcb,ElapsedTime,Index,KeyName,Type); \
  161. } \
  162. }
  163. #define StartWmiCmTrace()\
  164. LARGE_INTEGER StartSystemTime = {0};\
  165. LARGE_INTEGER EndSystemTime;\
  166. PVOID HookKcb = NULL;\
  167. if (CmpTraceRoutine) {\
  168. PerfTimeStamp(StartSystemTime); \
  169. }
  170. #define EndWmiCmTrace(Status,Index,KeyName,Type)\
  171. if (CmpTraceRoutine) {\
  172. PerfTimeStamp(EndSystemTime); \
  173. CmpWmiFireEvent(Status,HookKcb,EndSystemTime.QuadPart - StartSystemTime.QuadPart,Index,KeyName,Type);\
  174. }
  175. #define HookKcbForWmiCmTrace(KeyBody) \
  176. if (CmpTraceRoutine) {\
  177. if(KeyBody) {\
  178. HookKcb = KeyBody->KeyControlBlock;\
  179. }\
  180. }
  181. #define HookKcbFromHandleForWmiCmTrace(KeyHandle) \
  182. if (CmpTraceRoutine && (KeyHandle)) {\
  183. PCM_KEY_BODY KeyBody;\
  184. NTSTATUS status;\
  185. status = ObReferenceObjectByHandle(\
  186. KeyHandle,\
  187. 0,\
  188. CmpKeyObjectType,\
  189. KeGetPreviousMode(),\
  190. (PVOID *)(&KeyBody),\
  191. NULL\
  192. );\
  193. if (NT_SUCCESS(status)) {\
  194. HookKcb = KeyBody->KeyControlBlock;\
  195. ObDereferenceObject((PVOID)KeyBody);\
  196. }\
  197. }
  198. #define CmpTraceKcbCreate(kcb) \
  199. if (CmpTraceRoutine) {\
  200. CmpWmiDumpKcb(kcb);\
  201. }
  202. #ifdef WRITE_PROTECTED_VALUE_CACHE
  203. #define CmpMakeSpecialPoolReadOnly(PoolAddress) \
  204. { \
  205. if( !MmProtectSpecialPool( (PVOID) PoolAddress, PAGE_READONLY) ) \
  206. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_POOL,"[CmpMakeSpecialPoolReadOnly]: Failed to Mark SpecialPool %p as ReadOnly", PoolAddress )); \
  207. }
  208. #define CmpMakeSpecialPoolReadWrite(PoolAddress) \
  209. { \
  210. if( !MmProtectSpecialPool( (PVOID) PoolAddress, PAGE_READWRITE) ) { \
  211. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_POOL,"[CmpMakeSpecialPoolReadWrite]: Failed to Mark SpecialPool %p as ReadWrite", PoolAddress )); \
  212. } \
  213. }
  214. #define CmpMakeValueCacheReadOnly(ValueCached,PoolAddress) \
  215. if(ValueCached) { \
  216. CmpMakeSpecialPoolReadOnly( PoolAddress );\
  217. }
  218. #define CmpMakeValueCacheReadWrite(ValueCached,PoolAddress) \
  219. if(ValueCached) { \
  220. CmpMakeSpecialPoolReadWrite( PoolAddress );\
  221. }
  222. #else
  223. #define CmpMakeSpecialPoolReadOnly(a) //nothing
  224. #define CmpMakeSpecialPoolReadWrite(a) //nothing
  225. #define CmpMakeValueCacheReadOnly(a,b) //nothing
  226. #define CmpMakeValueCacheReadWrite(a,b) //nothing
  227. #endif
  228. #ifdef WRITE_PROTECTED_REGISTRY_POOL
  229. VOID
  230. HvpMarkBinReadWrite(
  231. PHHIVE Hive,
  232. HCELL_INDEX Cell
  233. );
  234. VOID
  235. HvpChangeBinAllocation(
  236. PHBIN Bin,
  237. BOOLEAN ReadOnly
  238. );
  239. VOID
  240. CmpMarkAllBinsReadOnly(
  241. PHHIVE Hive
  242. );
  243. #else
  244. #define HvpChangeBinAllocation(a,b) //nothing
  245. #define HvpMarkBinReadWrite(a,b) //nothing
  246. #define CmpMarkAllBinsReadOnly(a) //nothing
  247. #endif
  248. #ifdef POOL_TAGGING
  249. //
  250. // Pool Tag
  251. //
  252. #define CM_POOL_TAG ' MC'
  253. #define CM_KCB_TAG 'bkMC'
  254. #define CM_POSTBLOCK_TAG 'bpMC'
  255. #define CM_NOTIFYBLOCK_TAG 'bnMC'
  256. #define CM_POSTEVENT_TAG 'epMC'
  257. #define CM_POSTAPC_TAG 'apMC'
  258. #define CM_MAPPEDVIEW_TAG 'wVMC'
  259. #define CM_SECCACHE_TAG 'cSMC'
  260. #define CM_DELAYCLOSE_TAG 'cDMC'
  261. #define CM_STASHBUFFER_TAG 'bSMC'
  262. #define CM_HVBIN_TAG 'bHMC'
  263. #define CM_ALLOCATE_TAG 'lAMC'
  264. //
  265. // Find leaks
  266. //
  267. #define CM_FIND_LEAK_TAG1 ' 1MC'
  268. #define CM_FIND_LEAK_TAG2 ' 2MC'
  269. #define CM_FIND_LEAK_TAG3 ' 3MC'
  270. #define CM_FIND_LEAK_TAG4 ' 4MC'
  271. #define CM_FIND_LEAK_TAG5 ' 5MC'
  272. #define CM_FIND_LEAK_TAG6 ' 6MC'
  273. #define CM_FIND_LEAK_TAG7 ' 7MC'
  274. #define CM_FIND_LEAK_TAG8 ' 8MC'
  275. #define CM_FIND_LEAK_TAG9 ' 9MC'
  276. #define CM_FIND_LEAK_TAG10 '01MC'
  277. #define CM_FIND_LEAK_TAG11 '11MC'
  278. #define CM_FIND_LEAK_TAG12 '21MC'
  279. #define CM_FIND_LEAK_TAG13 '31MC'
  280. #define CM_FIND_LEAK_TAG14 '41MC'
  281. #define CM_FIND_LEAK_TAG15 '51MC'
  282. #define CM_FIND_LEAK_TAG16 '61MC'
  283. #define CM_FIND_LEAK_TAG17 '71MC'
  284. #define CM_FIND_LEAK_TAG18 '81MC'
  285. #define CM_FIND_LEAK_TAG19 '91MC'
  286. #define CM_FIND_LEAK_TAG20 '02MC'
  287. #define CM_FIND_LEAK_TAG21 '12MC'
  288. #define CM_FIND_LEAK_TAG22 '22MC'
  289. #define CM_FIND_LEAK_TAG23 '32MC'
  290. #define CM_FIND_LEAK_TAG24 '42MC'
  291. #define CM_FIND_LEAK_TAG25 '52MC'
  292. #define CM_FIND_LEAK_TAG26 '62MC'
  293. #define CM_FIND_LEAK_TAG27 '72MC'
  294. #define CM_FIND_LEAK_TAG28 '82MC'
  295. #define CM_FIND_LEAK_TAG29 '92MC'
  296. #define CM_FIND_LEAK_TAG30 '03MC'
  297. #define CM_FIND_LEAK_TAG31 '13MC'
  298. #define CM_FIND_LEAK_TAG32 '23MC'
  299. #define CM_FIND_LEAK_TAG33 '33MC'
  300. #define CM_FIND_LEAK_TAG34 '43MC'
  301. #define CM_FIND_LEAK_TAG35 '53MC'
  302. #define CM_FIND_LEAK_TAG36 '63MC'
  303. #define CM_FIND_LEAK_TAG37 '73MC'
  304. #define CM_FIND_LEAK_TAG38 '83MC'
  305. #define CM_FIND_LEAK_TAG39 '93MC'
  306. #define CM_FIND_LEAK_TAG40 '04MC'
  307. #define CM_FIND_LEAK_TAG41 '14MC'
  308. #define CM_FIND_LEAK_TAG42 '24MC'
  309. #define CM_FIND_LEAK_TAG43 '34MC'
  310. #define CM_FIND_LEAK_TAG44 '44MC'
  311. #define CM_FIND_LEAK_TAG45 '54MC'
  312. #ifdef _WANT_MACHINE_IDENTIFICATION
  313. #define CM_PARSEINI_TAG 'ipMC'
  314. #define CM_GENINST_TAG 'igMC'
  315. #endif
  316. //
  317. // Extra Tags for cache.
  318. // We may want to merge these tags later.
  319. //
  320. #define CM_CACHE_VALUE_INDEX_TAG 'IVMC'
  321. #define CM_CACHE_VALUE_TAG 'aVMC'
  322. #define CM_CACHE_INDEX_TAG 'nIMC'
  323. #define CM_CACHE_VALUE_DATA_TAG 'aDMC'
  324. #define CM_NAME_TAG 'bNMC'
  325. #define ExAllocatePool(a,b) ExAllocatePoolWithTag(a,b,CM_POOL_TAG)
  326. #define ExAllocatePoolWithQuota(a,b) ExAllocatePoolWithQuotaTag(a,b,CM_POOL_TAG)
  327. PVOID
  328. CmpAllocateTag(
  329. ULONG Size,
  330. BOOLEAN UseForIo,
  331. ULONG Tag
  332. );
  333. #else
  334. #define CmpAllocateTag(a,b,c) CmpAllocate(a,b,c)
  335. #endif
  336. #define CmRetryExAllocatePoolWithTag(a,b,c,Result) \
  337. { \
  338. ULONG RetryCount = 10; \
  339. do { \
  340. Result = ExAllocatePoolWithTag(a,b,c); \
  341. } while ((!Result) && (RetryCount--)); \
  342. }
  343. //
  344. // A variable so can turn on/off certain performance features.
  345. //
  346. extern const ULONG CmpCacheOnFlag;
  347. #define CM_CACHE_FAKE_KEY 0x00000001 // Create Fake key KCB
  348. //
  349. // This lock protects the KCB cache, including the KCB structures,
  350. // NameBlock and Value Index.
  351. //
  352. #define MAX_KCB_LOCKS 1024
  353. extern EX_PUSH_LOCK CmpKcbLock;
  354. extern PKTHREAD CmpKcbOwner;
  355. extern EX_PUSH_LOCK CmpKcbLocks[MAX_KCB_LOCKS];
  356. //
  357. // This is \REGISTRY
  358. //
  359. extern HANDLE CmpRegistryRootHandle;
  360. VOID
  361. CmpLockKCBTreeExclusive(
  362. VOID
  363. );
  364. VOID
  365. CmpLockKCBTree(
  366. VOID
  367. );
  368. VOID
  369. CmpUnlockKCBTree(
  370. );
  371. VOID
  372. CmpLockKCB(
  373. PCM_KEY_CONTROL_BLOCK Kcb
  374. );
  375. VOID
  376. CmpUnlockKCB(
  377. PCM_KEY_CONTROL_BLOCK Kcb
  378. );
  379. //
  380. // Logging: remember, first 4 levels (0-3) are reserved system-wide
  381. //
  382. #define CML_BUGCHECK 4 // fatal errors
  383. #define CML_EXCEPTION 5 // all exception's
  384. #define CML_NTAPI 6 // NtApi calls
  385. #define CML_NTAPI_ARGS 7 // NtApi parameters
  386. #define CML_CM 8 // Cm level, general
  387. #define CML_NOTIFY 9 // Notify level, general
  388. #define CML_HIVE 10 // Hv level, general
  389. #define CML_IO 11 // IO level
  390. #define CML_SEC 12 // Security level
  391. #define CML_INIT 13 // Init level, general
  392. #define CML_INDEX 14 // Index level, general
  393. #define CML_BIN_MAP 15 // bin mapping level
  394. #define CML_FREECELL 16 // Free cell hints
  395. #define CML_POOL 17 // Pool
  396. #define CML_LOCKING 18 // Lock/unlock level
  397. #define CML_FLOW 19 // General flow
  398. #define CML_PARSE 20 // Parse algorithm
  399. #define CML_SAVRES 21 // SavRes operations
  400. #define REGCHECKING 1
  401. #if DBG
  402. #if REGCHECKING
  403. #define DCmCheckRegistry(a) if(HvHiveChecking) ASSERT(CmCheckRegistry(a, CM_CHECK_REGISTRY_HIVE_CHECK) == 0)
  404. #else
  405. #define DCmCheckRegistry(a)
  406. #endif
  407. #else
  408. #define DCmCheckRegistry(a)
  409. #endif
  410. #ifdef CHECK_REGISTRY_USECOUNT
  411. VOID
  412. CmpCheckRegistryUseCount( );
  413. #endif //CHECK_REGISTRY_USECOUNT
  414. #ifdef REGISTRY_LOCK_CHECKING
  415. ULONG
  416. CmpCheckLockExceptionFilter(
  417. IN PEXCEPTION_POINTERS ExceptionPointers
  418. );
  419. //
  420. // updated to check both registry and kcb
  421. //
  422. #define BEGIN_LOCK_CHECKPOINT \
  423. { \
  424. ULONG RegistryLockCountBefore,RegistryLockCountAfter; \
  425. RegistryLockCountBefore = ExIsResourceAcquiredShared(&CmpRegistryLock); \
  426. RegistryLockCountBefore += ExIsResourceAcquiredExclusive(&CmpRegistryLock); \
  427. try {
  428. #define END_LOCK_CHECKPOINT \
  429. } except(CmpCheckLockExceptionFilter(GetExceptionInformation())) {} \
  430. RegistryLockCountAfter = ExIsResourceAcquiredShared(&CmpRegistryLock); \
  431. RegistryLockCountAfter += ExIsResourceAcquiredExclusive(&CmpRegistryLock); \
  432. if( RegistryLockCountBefore != RegistryLockCountAfter ) { \
  433. CM_BUGCHECK(REGISTRY_ERROR,REGISTRY_LOCK_CHECKPOINT,0,RegistryLockCountBefore,RegistryLockCountAfter); \
  434. } \
  435. }
  436. #define BEGIN_KCB_LOCK_GUARD \
  437. try {
  438. #define END_KCB_LOCK_GUARD \
  439. } except(CmpCheckLockExceptionFilter(GetExceptionInformation())) {}
  440. #else
  441. #define BEGIN_LOCK_CHECKPOINT
  442. #define END_LOCK_CHECKPOINT
  443. #define BEGIN_KCB_LOCK_GUARD
  444. #define END_KCB_LOCK_GUARD
  445. #endif //REGISTRY_LOCK_CHECKING
  446. extern BOOLEAN CmpSpecialBootCondition;
  447. #if DBG
  448. #define ASSERT_CM_LOCK_OWNED() \
  449. ASSERT( (CmpSpecialBootCondition == TRUE) || (CmpTestRegistryLock() == TRUE) )
  450. #define ASSERT_CM_LOCK_OWNED_EXCLUSIVE() \
  451. ASSERT((CmpSpecialBootCondition == TRUE) || (CmpTestRegistryLockExclusive() == TRUE) )
  452. #define ASSERT_CM_EXCLUSIVE_HIVE_ACCESS(Hive) \
  453. ASSERT((CmpSpecialBootCondition == TRUE) || (CmpTestRegistryLockExclusive() == TRUE) || (Hive->ReleaseCellRoutine == NULL) )
  454. #define ASSERT_KCB_LOCK_OWNED_EXCLUSIVE() \
  455. ASSERT( (CmpTestKCBTreeLockExclusive() == TRUE) || (CmpSpecialBootCondition == TRUE) || (CmpTestRegistryLockExclusive() == TRUE) )
  456. #else
  457. #define ASSERT_CM_LOCK_OWNED()
  458. #define ASSERT_CM_LOCK_OWNED_EXCLUSIVE()
  459. #define ASSERT_CM_EXCLUSIVE_HIVE_ACCESS(Hive)
  460. #define ASSERT_KCB_LOCK_OWNED_EXCLUSIVE()
  461. #endif
  462. #if DBG
  463. #ifndef _CM_LDR_
  464. #define ASSERT_PASSIVE_LEVEL() \
  465. { \
  466. KIRQL Irql; \
  467. Irql = KeGetCurrentIrql(); \
  468. if( KeGetCurrentIrql() != PASSIVE_LEVEL ) { \
  469. DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"ASSERT_PASSIVE_LEVEL failed ... Irql = %lu\n",Irql); \
  470. ASSERT( FALSE ); \
  471. } \
  472. }
  473. #endif //_CM_LDR_
  474. #else
  475. #define ASSERT_PASSIVE_LEVEL()
  476. #endif
  477. #define VALIDATE_CELL_MAP(LINE,Map,Hive,Address) \
  478. if( Map == NULL ) { \
  479. CM_BUGCHECK (REGISTRY_ERROR,BAD_CELL_MAP,(ULONG_PTR)(Hive),(ULONG)(Address),(ULONG)(LINE)) ; \
  480. }
  481. #if DBG
  482. VOID
  483. SepDumpSecurityDescriptor(
  484. IN PSECURITY_DESCRIPTOR SecurityDescriptor,
  485. IN PSZ TitleString
  486. );
  487. extern BOOLEAN SepDumpSD;
  488. #define CmpDumpSecurityDescriptor(x,y) \
  489. { \
  490. SepDumpSD=TRUE; \
  491. SepDumpSecurityDescriptor(x, y); \
  492. SepDumpSD=FALSE; \
  493. }
  494. #else
  495. #define CmpDumpSecurityDescriptor(x,y)
  496. #endif
  497. //
  498. // misc stuff
  499. //
  500. extern UNICODE_STRING CmRegistrySystemCloneName;
  501. //
  502. // Determines whether the Current Control Set used during booting
  503. // is cloned in order to fully preserve it for being saved
  504. // as the LKG Control Set.
  505. //
  506. #define CLONE_CONTROL_SET FALSE
  507. #if CLONE_CONTROL_SET
  508. #define CM_NUMBER_OF_MACHINE_HIVES 7
  509. #else
  510. #define CM_NUMBER_OF_MACHINE_HIVES 6
  511. #endif
  512. #define NUMBER_TYPES (MaximumType + 1)
  513. #define CM_WRAP_LIMIT 0x7fffffff
  514. //
  515. // Tuning and control constants
  516. //
  517. #define CM_MAX_STASH 1024*1024 // If size of data for a set
  518. // is bigger than this,
  519. #define CM_MAX_REASONABLE_VALUES 100 // If number of values for a
  520. // key is greater than this,
  521. // round up value list size
  522. //
  523. // Limit on the number of layers of hive there may be. We allow only
  524. // the master hive and hives directly linked into it for now, for currently
  525. // value is always 2..
  526. //
  527. #define MAX_HIVE_LAYERS 2
  528. //
  529. // structure used to create and sort ordered list of drivers to be loaded.
  530. // This is also used by the OS Loader when loading the boot drivers.
  531. // (Particularly the ErrorControl field)
  532. //
  533. typedef struct _BOOT_DRIVER_NODE {
  534. BOOT_DRIVER_LIST_ENTRY ListEntry;
  535. UNICODE_STRING Group;
  536. UNICODE_STRING Name;
  537. ULONG Tag;
  538. ULONG ErrorControl;
  539. } BOOT_DRIVER_NODE, *PBOOT_DRIVER_NODE;
  540. //
  541. // extern for object type pointer
  542. //
  543. extern POBJECT_TYPE CmpKeyObjectType;
  544. extern POBJECT_TYPE IoFileObjectType;
  545. //
  546. // indexes in CmpMachineHiveList
  547. //
  548. #define SYSTEM_HIVE_INDEX 3
  549. #define CLONE_HIVE_INDEX 6
  550. //
  551. // Miscelaneous Hash routines
  552. //
  553. #define RNDM_CONSTANT 314159269 /* default value for "scrambling constant" */
  554. #define RNDM_PRIME 1000000007 /* prime number, also used for scrambling */
  555. #define HASH_KEY(_convkey_) ((RNDM_CONSTANT * (_convkey_)) % RNDM_PRIME)
  556. #define GET_HASH_INDEX(Key) HASH_KEY(Key) % CmpHashTableSize
  557. #define GET_HASH_ENTRY(Table, Key) Table[GET_HASH_INDEX(Key)]
  558. //
  559. // CM_KEY_BODY
  560. //
  561. // Same structure used for KEY_ROOT and KEY objects. This is the
  562. // Cm defined part of the object.
  563. //
  564. // This object represents an open instance, several of them could refer
  565. // to a single key control block.
  566. //
  567. #define KEY_BODY_TYPE 0x6b793032 // "ky02"
  568. struct _CM_NOTIFY_BLOCK; //forward
  569. typedef struct _CM_KEY_BODY {
  570. ULONG Type;
  571. PCM_KEY_CONTROL_BLOCK KeyControlBlock;
  572. struct _CM_NOTIFY_BLOCK *NotifyBlock;
  573. HANDLE ProcessID; // the owner process
  574. #ifdef CM_LEAK_STACK_TRACES
  575. ULONG Callers;
  576. PVOID CallerAddress[10];
  577. #endif //CM_LEAK_STACK_TRACES
  578. LIST_ENTRY KeyBodyList; // key_nodes using the same kcb
  579. } CM_KEY_BODY, *PCM_KEY_BODY;
  580. #ifdef CM_LEAK_STACK_TRACES
  581. // just because we need this #define code inside a macro !
  582. #define CmpSetNoCallers(KeyBody) KeyBody->Callers = 0
  583. #define CmpAddKeyTracker(KeyHandle,mode) \
  584. if(PoCleanShutdownEnabled() & PO_CLEAN_SHUTDOWN_REGISTRY) { \
  585. PCM_KEY_BODY KeyBody; \
  586. NTSTATUS status; \
  587. status = ObReferenceObjectByHandle( \
  588. KeyHandle, \
  589. 0, \
  590. CmpKeyObjectType, \
  591. mode, \
  592. (PVOID *)(&KeyBody), \
  593. NULL \
  594. ); \
  595. if( NT_SUCCESS(status) ) { \
  596. KeyBody->Callers = RtlWalkFrameChain(&(KeyBody->CallerAddress[0]), 10, 0); \
  597. ObDereferenceObject((PVOID)KeyBody); \
  598. } \
  599. }
  600. #else
  601. #define CmpSetNoCallers(KeyBody) // nothing
  602. #define CmpAddKeyTracker(KeyHandle,mode) // nothing yet
  603. #endif //CM_LEAK_STACK_TRACES
  604. #define INIT_KCB_KEYBODY_LIST(kcb) InitializeListHead(&(kcb->KeyBodyListHead))
  605. #define ASSERT_KEYBODY_LIST_EMPTY(kcb) ASSERT(IsListEmpty(&(kcb->KeyBodyListHead)) == TRUE)
  606. #define ENLIST_KEYBODY_IN_KEYBODY_LIST(KeyBody) \
  607. ASSERT( KeyBody->KeyControlBlock != NULL ); \
  608. BEGIN_KCB_LOCK_GUARD; \
  609. CmpLockKCBTree(); \
  610. CmpLockKCB(KeyBody->KeyControlBlock); \
  611. InsertTailList(&(KeyBody->KeyControlBlock->KeyBodyListHead),&(KeyBody->KeyBodyList)); \
  612. CmpSetNoCallers(KeyBody); \
  613. CmpUnlockKCB(KeyBody->KeyControlBlock); \
  614. CmpUnlockKCBTree(); \
  615. END_KCB_LOCK_GUARD
  616. #define DELIST_KEYBODY_FROM_KEYBODY_LIST(KeyBody) \
  617. ASSERT( KeyBody->KeyControlBlock != NULL ); \
  618. ASSERT(IsListEmpty(&(KeyBody->KeyControlBlock->KeyBodyListHead)) == FALSE); \
  619. BEGIN_KCB_LOCK_GUARD; \
  620. CmpLockKCBTree(); \
  621. CmpLockKCB(KeyBody->KeyControlBlock); \
  622. RemoveEntryList(&(KeyBody->KeyBodyList)); \
  623. CmpUnlockKCB(KeyBody->KeyControlBlock); \
  624. CmpUnlockKCBTree(); \
  625. END_KCB_LOCK_GUARD
  626. #define ASSERT_KEY_OBJECT(x) ASSERT(((PCM_KEY_BODY)x)->Type == KEY_BODY_TYPE)
  627. #define ASSERT_NODE(x) ASSERT(((PCM_KEY_NODE)x)->Signature == CM_KEY_NODE_SIGNATURE)
  628. #define ASSERT_SECURITY(x) ASSERT(((PCM_KEY_SECURITY)x)->Signature == CM_KEY_SECURITY_SIGNATURE)
  629. //
  630. // CM_POST_KEY_BODY
  631. //
  632. // A post block can have attached a keybody which has to be dereferenced
  633. // when the post block goes out of scope. This structure allows the
  634. // implementation of keybody "delayed dereferencing". (see CmpPostNotify for comments)
  635. //
  636. typedef struct _CM_POST_KEY_BODY {
  637. LIST_ENTRY KeyBodyList;
  638. struct _CM_KEY_BODY *KeyBody; // this key body object
  639. } CM_POST_KEY_BODY, *PCM_POST_KEY_BODY;
  640. //
  641. // CM_NOTIFY_BLOCK
  642. //
  643. // A notify block tracks an active notification waiting for notification.
  644. // Any one open instance (CM_KEY_BODY) will refer to at most one
  645. // notify block. A given key control block may have as many notify
  646. // blocks refering to it as there are CM_KEY_BODYs refering to it.
  647. // Notify blocks are attached to hives and sorted by length of name.
  648. //
  649. typedef struct _CM_NOTIFY_BLOCK {
  650. LIST_ENTRY HiveList; // sorted list of notifies
  651. LIST_ENTRY PostList; // Posts to fill
  652. PCM_KEY_CONTROL_BLOCK KeyControlBlock; // Open instance notify is on
  653. struct _CM_KEY_BODY *KeyBody; // our owning key handle object
  654. struct {
  655. ULONG Filter : 30; // Events of interest
  656. ULONG WatchTree : 1;
  657. ULONG NotifyPending : 1;
  658. };
  659. SECURITY_SUBJECT_CONTEXT SubjectContext; // Security stuff
  660. } CM_NOTIFY_BLOCK, *PCM_NOTIFY_BLOCK;
  661. //
  662. // CM_POST_BLOCK
  663. //
  664. // Whenever a notify call is made, a post block is created and attached
  665. // to the notify block. Each time an event is posted against the notify,
  666. // the waiter described by the post block is signaled. (i.e. APC enqueued,
  667. // event signalled, etc.)
  668. //
  669. //
  670. // The NotifyType ULONG is a combination of POST_BLOCK_TYPE enum and flags
  671. //
  672. typedef enum _POST_BLOCK_TYPE {
  673. PostSynchronous = 1,
  674. PostAsyncUser = 2,
  675. PostAsyncKernel = 3
  676. } POST_BLOCK_TYPE;
  677. typedef struct _CM_SYNC_POST_BLOCK {
  678. PKEVENT SystemEvent;
  679. NTSTATUS Status;
  680. } CM_SYNC_POST_BLOCK, *PCM_SYNC_POST_BLOCK;
  681. typedef struct _CM_ASYNC_USER_POST_BLOCK {
  682. ULONG Dummy;
  683. PKEVENT UserEvent;
  684. PKAPC Apc;
  685. PIO_STATUS_BLOCK IoStatusBlock;
  686. } CM_ASYNC_USER_POST_BLOCK, *PCM_ASYNC_USER_POST_BLOCK;
  687. typedef struct _CM_ASYNC_KERNEL_POST_BLOCK {
  688. PKEVENT Event;
  689. PWORK_QUEUE_ITEM WorkItem;
  690. WORK_QUEUE_TYPE QueueType;
  691. } CM_ASYNC_KERNEL_POST_BLOCK, *PCM_ASYNC_KERNEL_POST_BLOCK;
  692. typedef union _CM_POST_BLOCK_UNION {
  693. CM_SYNC_POST_BLOCK Sync;
  694. CM_ASYNC_USER_POST_BLOCK AsyncUser;
  695. CM_ASYNC_KERNEL_POST_BLOCK AsyncKernel;
  696. } CM_POST_BLOCK_UNION, *PCM_POST_BLOCK_UNION;
  697. typedef struct _CM_POST_BLOCK {
  698. #if DBG
  699. BOOLEAN TraceIntoDebugger;
  700. #endif
  701. LIST_ENTRY NotifyList;
  702. LIST_ENTRY ThreadList;
  703. LIST_ENTRY CancelPostList; // slave notifications that are attached to this notification
  704. struct _CM_POST_KEY_BODY *PostKeyBody;
  705. #ifdef CM_NOTIFY_CHANGED_KCB_FULLPATH
  706. PUNICODE_STRING ChangedKcbFullName; // full qualified name of the kcb that triggered this notification
  707. PVOID CallerBuffer; // used to return full qualified name of the changed kcb to the caller
  708. ULONG CallerBufferSize; // these are supposed to be filled by CmpAllocatePostBlock
  709. #endif //CM_NOTIFY_CHANGED_KCB_FULLPATH
  710. ULONG NotifyType;
  711. PCM_POST_BLOCK_UNION u;
  712. } CM_POST_BLOCK, *PCM_POST_BLOCK;
  713. #define REG_NOTIFY_POST_TYPE_MASK (0x0000FFFFL) // mask for finding out the type of the post block
  714. #define REG_NOTIFY_MASTER_POST (0x00010000L) // The current post block is a master one
  715. //
  716. // Usefull macros to manipulate the NotifyType field in CM_POST_BLOCK
  717. //
  718. #define PostBlockType(_post_) ((POST_BLOCK_TYPE)( ((_post_)->NotifyType) & REG_NOTIFY_POST_TYPE_MASK ))
  719. #define IsMasterPostBlock(_post_) ( ((_post_)->NotifyType) & REG_NOTIFY_MASTER_POST )
  720. #define SetMasterPostBlockFlag(_post_) ( ((_post_)->NotifyType) |= REG_NOTIFY_MASTER_POST )
  721. #define ClearMasterPostBlockFlag(_post_) ( ((_post_)->NotifyType) &= ~REG_NOTIFY_MASTER_POST )
  722. //
  723. // This lock protects the PostList(s) in Notification objects.
  724. // It is used to prevent attempts for simultaneous changes of
  725. // CancelPostList list in PostBlocks
  726. //
  727. extern FAST_MUTEX CmpPostLock;
  728. #define LOCK_POST_LIST() ExAcquireFastMutexUnsafe(&CmpPostLock)
  729. #define UNLOCK_POST_LIST() ExReleaseFastMutexUnsafe(&CmpPostLock)
  730. extern FAST_MUTEX CmpStashBufferLock;
  731. #define LOCK_STASH_BUFFER() ExAcquireFastMutexUnsafe(&CmpStashBufferLock)
  732. #define UNLOCK_STASH_BUFFER() ExReleaseFastMutexUnsafe(&CmpStashBufferLock)
  733. //
  734. // protection for CmpHiveListHead
  735. //
  736. extern FAST_MUTEX CmpHiveListHeadLock;
  737. #ifndef _CM_LDR_
  738. #define LOCK_HIVE_LIST() ExAcquireFastMutexUnsafe(&CmpHiveListHeadLock)
  739. #define UNLOCK_HIVE_LIST() ExReleaseFastMutexUnsafe(&CmpHiveListHeadLock)
  740. #else
  741. #define LOCK_HIVE_LIST() //nothing
  742. #define UNLOCK_HIVE_LIST() //nothing
  743. #endif
  744. //
  745. // used by CmpFileWrite, so it doesn't take up so much stack.
  746. //
  747. typedef struct _CM_WRITE_BLOCK {
  748. HANDLE EventHandles[MAXIMUM_WAIT_OBJECTS];
  749. PKEVENT EventObjects[MAXIMUM_WAIT_OBJECTS];
  750. KWAIT_BLOCK WaitBlockArray[MAXIMUM_WAIT_OBJECTS];
  751. IO_STATUS_BLOCK IoStatus[MAXIMUM_WAIT_OBJECTS];
  752. } CM_WRITE_BLOCK, *PCM_WRITE_BLOCK;
  753. //
  754. // CM data to manipulate views inside the primary hive file
  755. //
  756. //#define MAPPED_VIEWS_PER_HIVE 12 * (_256K / CM_VIEW_SIZE ) // max 3 MB per hive ; we don't really need this
  757. #define MAX_VIEWS_PER_HIVE MAX_MB_PER_HIVE * ( (_256K) / (CM_VIEW_SIZE) )
  758. #define ASSERT_VIEW_MAPPED(a) \
  759. ASSERT((a)->Size != 0); \
  760. ASSERT((a)->ViewAddress != 0); \
  761. ASSERT((a)->Bcb != 0); \
  762. ASSERT( IsListEmpty(&((a)->LRUViewList)) == FALSE); \
  763. ASSERT( IsListEmpty(&((a)->PinViewList)) == TRUE)
  764. #define ASSERT_VIEW_PINNED(a) \
  765. ASSERT((a)->Size != 0); \
  766. ASSERT((a)->ViewAddress != 0); \
  767. ASSERT((a)->Bcb != 0); \
  768. ASSERT( IsListEmpty(&((a)->LRUViewList)) == TRUE)
  769. typedef struct _CM_VIEW_OF_FILE {
  770. LIST_ENTRY LRUViewList; // LRU connection ==> when this is empty, the view is pinned
  771. LIST_ENTRY PinViewList; // list of views pinned into memory ==> when this is empty, the view is in LRU list
  772. ULONG FileOffset; // file offset at which the mapping starts
  773. ULONG Size; // size the view maps
  774. PULONG_PTR ViewAddress; // memory address containing the mapping
  775. PVOID Bcb; // BCB needed for map/pin/unpin access
  776. ULONG UseCount; // how many cells are currently in use inside this view
  777. } CM_VIEW_OF_FILE, *PCM_VIEW_OF_FILE;
  778. //
  779. // security hash manipulation
  780. //
  781. #define CmpSecHashTableSize 64 // size of the hash table
  782. typedef struct _CM_KCB_REMAP_BLOCK {
  783. LIST_ENTRY RemapList;
  784. PCM_KEY_CONTROL_BLOCK KeyControlBlock;
  785. HCELL_INDEX OldCellIndex;
  786. HCELL_INDEX NewCellIndex;
  787. ULONG ValueCount;
  788. HCELL_INDEX ValueList;
  789. } CM_KCB_REMAP_BLOCK, *PCM_KCB_REMAP_BLOCK;
  790. typedef struct _CM_CELL_REMAP_BLOCK {
  791. HCELL_INDEX OldCell;
  792. HCELL_INDEX NewCell;
  793. } CM_CELL_REMAP_BLOCK, *PCM_CELL_REMAP_BLOCK;
  794. typedef struct _CM_KNODE_REMAP_BLOCK {
  795. LIST_ENTRY RemapList;
  796. PCM_KEY_NODE KeyNode;
  797. HCELL_INDEX NewParent;
  798. } CM_KNODE_REMAP_BLOCK, *PCM_KNODE_REMAP_BLOCK;
  799. //
  800. // UseCount log
  801. //
  802. #ifdef REGISTRY_LOCK_CHECKING
  803. typedef struct _CM_USE_COUNT_LOG_ENTRY {
  804. HCELL_INDEX Cell;
  805. PVOID Stack[7];
  806. } CM_USE_COUNT_LOG_ENTRY;
  807. typedef struct _CM_USE_COUNT_LOG {
  808. USHORT Next;
  809. USHORT Size;
  810. CM_USE_COUNT_LOG_ENTRY Log[32];
  811. } CM_USE_COUNT_LOG;
  812. #endif // REGISTRY_LOCK_CHECKING
  813. #define CM_CMHIVE_FLAG_UNTRUSTED 1 // hive is untrusted (but it may be inside of a trusted class).
  814. // ----- Cm version of Hive structure (CMHIVE) -----
  815. //
  816. typedef struct _CMHIVE {
  817. HHIVE Hive;
  818. HANDLE FileHandles[HFILE_TYPE_MAX];
  819. LIST_ENTRY NotifyList;
  820. LIST_ENTRY HiveList; // Used to find hives at shutdown
  821. PFAST_MUTEX HiveLock; // Used to synchronize operations on the hive (NotifyList and Flush)
  822. PFAST_MUTEX ViewLock; // Used to control access over the view list, UseCount
  823. LIST_ENTRY LRUViewListHead; // Head of the same list as above but ordered (LRU)
  824. LIST_ENTRY PinViewListHead; // Head of the List of Views pinned into memory inside the primary hive file
  825. #if 0 // it didn't work
  826. LIST_ENTRY FakeViewListHead; // Used to optimize boot process (fault all the data in in 256K chunks at once)
  827. #endif
  828. PFILE_OBJECT FileObject; // FileObject needed for Cc operations on the mapped views
  829. UNICODE_STRING FileFullPath; // full path of the hive file- needed for CmPrefetchHivePages
  830. UNICODE_STRING FileUserName; // file name as passed onto NtLoadKey
  831. USHORT MappedViews; // number of mapped (but not pinned views) i.e. the number of elements in LRUViewList
  832. USHORT PinnedViews; // number of pinned views i.e. the number of elements in PinViewList
  833. ULONG UseCount; // how many cells are currently in use inside this hive
  834. #if 0
  835. ULONG FakeViews; // number of FakeViews (debug-only)
  836. #endif
  837. ULONG SecurityCount; // number of security cells cached
  838. ULONG SecurityCacheSize; // number of entries in the cache (to avoid memory fragmentation)
  839. LONG SecurityHitHint; // index of the last cell we've searched on
  840. PCM_KEY_SECURITY_CACHE_ENTRY SecurityCache; // the security cache
  841. // hash table (to retrieve the security cells by descriptor)
  842. LIST_ENTRY SecurityHash[CmpSecHashTableSize];
  843. #ifdef NT_UNLOAD_KEY_EX
  844. PKEVENT UnloadEvent; // the event to be signaled when the hive unloads
  845. // this may be valid (not NULL) only in conjunction with
  846. // a not NULL RootKcb and a TRUE Frozen (below)
  847. PCM_KEY_CONTROL_BLOCK RootKcb; // kcb to the root of the hive. We keep a reference on it, which
  848. // will be released at the time the hive unloads (i.e. it is the last
  849. // reference somebody has on this kcb); This is should be valid (not NULL)
  850. // only when the Frozen flag is set to TRUE
  851. BOOLEAN Frozen; // set to TRUE when the hive is frozen (no further operations are allowed on
  852. // this hive
  853. PWORK_QUEUE_ITEM UnloadWorkItem; // Work Item to actually perform the late unload
  854. #endif //NT_UNLOAD_KEY_EX
  855. BOOLEAN GrowOnlyMode; // the hive is in "grow only" mode; new cells are allocated past GrowOffset
  856. ULONG GrowOffset;
  857. LIST_ENTRY KcbConvertListHead; // list of CM_KCB_REMAP_BLOCK storing the associations to the new hive.
  858. LIST_ENTRY KnodeConvertListHead;
  859. PCM_CELL_REMAP_BLOCK CellRemapArray; // array of mappings used for security cells
  860. #ifdef REGISTRY_LOCK_CHECKING
  861. CM_USE_COUNT_LOG UseCountLog; // track UseCount leaks
  862. #endif // REGISTRY_LOCK_CHECKING
  863. ULONG Flags; // CMHIVE specific flags
  864. LIST_ENTRY TrustClassEntry; // links together the UNTRUSTED hives in the same 'class of trust'
  865. ULONG FlushCount;
  866. } CMHIVE, *PCMHIVE;
  867. #define CmpUnJoinClassOfTrust(CmHive) \
  868. if( !IsListEmpty(&(CmHive->TrustClassEntry)) ) { \
  869. ASSERT(CmHive->Flags&CM_CMHIVE_FLAG_UNTRUSTED); \
  870. LOCK_HIVE_LIST(); \
  871. RemoveEntryList(&(CmHive->TrustClassEntry)); \
  872. UNLOCK_HIVE_LIST(); \
  873. }
  874. #define CmpJoinClassOfTrust(_NewHive,_OtherHive) \
  875. LOCK_HIVE_LIST(); \
  876. InsertTailList(&(_OtherHive->TrustClassEntry),&(_NewHive->TrustClassEntry));\
  877. UNLOCK_HIVE_LIST()
  878. #ifdef REGISTRY_LOCK_CHECKING
  879. #define CmAddUseCountToLog( LOG, CELL, ACTION ) { \
  880. if( (ACTION) < 0 ) { \
  881. ULONG i; \
  882. for(i=0;i<(LOG)->Next;i++) { \
  883. if( (LOG)->Log[i].Cell == (CELL) ) { \
  884. RtlMoveMemory(&((LOG)->Log[i]),&((LOG)->Log[i+1]),((LOG)->Next - i - 1)*sizeof(CM_USE_COUNT_LOG_ENTRY));\
  885. (LOG)->Next -= 1; \
  886. break; \
  887. } \
  888. } \
  889. } else if( (LOG)->Next < (LOG)->Size ) { \
  890. RtlWalkFrameChain((LOG)->Log[(LOG)->Next].Stack, \
  891. sizeof((LOG)->Log[(LOG)->Next].Stack)/sizeof(PVOID), \
  892. 0); \
  893. (LOG)->Log[(LOG)->Next].Cell = (CELL); \
  894. (LOG)->Next += 1; \
  895. } \
  896. }
  897. #define CmLogCellRef( HIVE, CELL ) CmAddUseCountToLog( &(((PCMHIVE)(HIVE))->UseCountLog), CELL , 1)
  898. #define CmLogCellDeRef( HIVE, CELL ) CmAddUseCountToLog( &(((PCMHIVE)(HIVE))->UseCountLog), CELL , -1)
  899. #else // REGISTRY_LOCK_CHECKING
  900. #define CmLogCellRef( HIVE, CELL )
  901. #define CmLogCellDeRef( HIVE, CELL )
  902. #endif // REGISTRY_LOCK_CHECKING
  903. #ifdef NT_UNLOAD_KEY_EX
  904. #define IsHiveFrozen(_CmHive_) (((PCMHIVE)(_CmHive_))->Frozen == TRUE)
  905. #endif
  906. #define HiveWritesThroughCache(Hive,FileType) ((FileType == HFILE_TYPE_PRIMARY) && (((PCMHIVE)CONTAINING_RECORD(Hive, CMHIVE, Hive))->FileObject != NULL))
  907. //
  908. // Delayed close kcb list
  909. //
  910. typedef struct _CM_DELAYED_CLOSE_ENTRY {
  911. LIST_ENTRY DelayedLRUList; // LRU list of entries in the Delayed Close Table
  912. PCM_KEY_CONTROL_BLOCK KeyControlBlock; // KCB in this entry; NULL if the entry is available
  913. } CM_DELAYED_CLOSE_ENTRY, *PCM_DELAYED_CLOSE_ENTRY;
  914. //
  915. // Hive locking support
  916. //
  917. //
  918. #define CmLockHive(_hive_) ASSERT( (_hive_)->HiveLock );\
  919. ExAcquireFastMutexUnsafe((_hive_)->HiveLock)
  920. #define CmUnlockHive(_hive_) ASSERT( (_hive_)->HiveLock );\
  921. ExReleaseFastMutexUnsafe((_hive_)->HiveLock)
  922. //
  923. // View locking support
  924. //
  925. #define CmLockHiveViews(_hive_) ASSERT( (_hive_)->ViewLock );\
  926. ExAcquireFastMutexUnsafe((_hive_)->ViewLock)
  927. #define CmUnlockHiveViews(_hive_) ASSERT( (_hive_)->ViewLock );\
  928. ExReleaseFastMutexUnsafe((_hive_)->ViewLock)
  929. //
  930. // Macros
  931. //
  932. //
  933. // ----- CM_KEY_NODE -----
  934. //
  935. #define CmpHKeyNameLen(Key) \
  936. (((Key)->Flags & KEY_COMP_NAME) ? \
  937. CmpCompressedNameSize((Key)->Name,(Key)->NameLength) : \
  938. (Key)->NameLength)
  939. #define CmpNcbNameLen(Ncb) \
  940. (((Ncb)->Compressed) ? \
  941. CmpCompressedNameSize((Ncb)->Name,(Ncb)->NameLength) : \
  942. (Ncb)->NameLength)
  943. #define CmpHKeyNodeSize(Hive, KeyName) \
  944. (FIELD_OFFSET(CM_KEY_NODE, Name) + CmpNameSize(Hive, KeyName))
  945. //
  946. // ----- CM_KEY_VALUE -----
  947. //
  948. #define CmpValueNameLen(Value) \
  949. (((Value)->Flags & VALUE_COMP_NAME) ? \
  950. CmpCompressedNameSize((Value)->Name,(Value)->NameLength) : \
  951. (Value)->NameLength)
  952. #define CmpHKeyValueSize(Hive, ValueName) \
  953. (FIELD_OFFSET(CM_KEY_VALUE, Name) + CmpNameSize(Hive, ValueName))
  954. //
  955. // ----- Procedure Prototypes -----
  956. //
  957. //
  958. // Configuration Manager private procedure prototypes
  959. //
  960. #define REG_OPTION_PREDEF_HANDLE (0x01000000L)
  961. #define REG_PREDEF_HANDLE_MASK (0x80000000L)
  962. typedef struct _CM_PARSE_CONTEXT {
  963. ULONG TitleIndex;
  964. UNICODE_STRING Class;
  965. ULONG CreateOptions;
  966. ULONG Disposition;
  967. CM_KEY_REFERENCE ChildHive;
  968. HANDLE PredefinedHandle;
  969. BOOLEAN CreateLink;
  970. BOOLEAN CreateOperation;
  971. PCMHIVE OriginatingPoint;
  972. } CM_PARSE_CONTEXT, *PCM_PARSE_CONTEXT;
  973. #define CmpParseRecordOriginatingPoint(_Context,_CmHive) \
  974. if( ARGUMENT_PRESENT(_Context) && (((PCM_PARSE_CONTEXT)(_Context))->OriginatingPoint == NULL) && \
  975. (((PCMHIVE)_CmHive)->Flags&CM_CMHIVE_FLAG_UNTRUSTED) ){ \
  976. ((PCM_PARSE_CONTEXT)(_Context))->OriginatingPoint = (PCMHIVE)_CmHive; \
  977. }
  978. #define CmpParseGetOriginatingPoint(_Context) ARGUMENT_PRESENT(_Context)?((PCM_PARSE_CONTEXT)(_Context))->OriginatingPoint:NULL
  979. NTSTATUS
  980. CmpParseKey(
  981. IN PVOID ParseObject,
  982. IN PVOID ObjectType,
  983. IN OUT PACCESS_STATE AccessState,
  984. IN KPROCESSOR_MODE AccessMode,
  985. IN ULONG Attributes,
  986. IN OUT PUNICODE_STRING CompleteName,
  987. IN OUT PUNICODE_STRING RemainingName,
  988. IN OUT PVOID Context OPTIONAL,
  989. IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,
  990. OUT PVOID *Object
  991. );
  992. NTSTATUS
  993. CmpDoCreate(
  994. IN PHHIVE Hive,
  995. IN HCELL_INDEX Cell,
  996. IN PACCESS_STATE AccessState,
  997. IN PUNICODE_STRING Name,
  998. IN KPROCESSOR_MODE AccessMode,
  999. IN PCM_PARSE_CONTEXT Context,
  1000. IN PCM_KEY_CONTROL_BLOCK ParentKcb,
  1001. IN PCMHIVE OriginatingHive OPTIONAL,
  1002. OUT PVOID *Object
  1003. );
  1004. NTSTATUS
  1005. CmpDoCreateChild(
  1006. IN PHHIVE Hive,
  1007. IN HCELL_INDEX ParentCell,
  1008. IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
  1009. IN PACCESS_STATE AccessState,
  1010. IN PUNICODE_STRING Name,
  1011. IN KPROCESSOR_MODE AccessMode,
  1012. IN PCM_PARSE_CONTEXT Context,
  1013. IN PCM_KEY_CONTROL_BLOCK ParentKcb,
  1014. IN USHORT Flags,
  1015. OUT PHCELL_INDEX KeyCell,
  1016. OUT PVOID *Object
  1017. );
  1018. NTSTATUS
  1019. CmpQueryKeyName(
  1020. IN PVOID Object,
  1021. IN BOOLEAN HasObjectName,
  1022. OUT POBJECT_NAME_INFORMATION ObjectNameInfo,
  1023. IN ULONG Length,
  1024. OUT PULONG ReturnLength,
  1025. IN KPROCESSOR_MODE Mode
  1026. );
  1027. VOID
  1028. CmpDeleteKeyObject(
  1029. IN PVOID Object
  1030. );
  1031. VOID
  1032. CmpCloseKeyObject(
  1033. IN PEPROCESS Process OPTIONAL,
  1034. IN PVOID Object,
  1035. IN ACCESS_MASK GrantedAccess,
  1036. IN ULONG_PTR ProcessHandleCount,
  1037. IN ULONG_PTR SystemHandleCount
  1038. );
  1039. NTSTATUS
  1040. CmpSecurityMethod (
  1041. IN PVOID Object,
  1042. IN SECURITY_OPERATION_CODE OperationCode,
  1043. IN PSECURITY_INFORMATION SecurityInformation,
  1044. IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
  1045. IN OUT PULONG CapturedLength,
  1046. IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor,
  1047. IN POOL_TYPE PoolType,
  1048. IN PGENERIC_MAPPING GenericMapping
  1049. );
  1050. #define KCB_WORKER_CONTINUE 0
  1051. #define KCB_WORKER_DONE 1
  1052. #define KCB_WORKER_DELETE 2
  1053. #define KCB_WORKER_ERROR 3
  1054. typedef
  1055. ULONG
  1056. (*PKCB_WORKER_ROUTINE) (
  1057. PCM_KEY_CONTROL_BLOCK Current,
  1058. PVOID Context1,
  1059. PVOID Context2
  1060. );
  1061. BOOLEAN
  1062. CmpSearchKeyControlBlockTree(
  1063. PKCB_WORKER_ROUTINE WorkerRoutine,
  1064. PVOID Context1,
  1065. PVOID Context2
  1066. );
  1067. //
  1068. // Wrappers
  1069. //
  1070. PVOID
  1071. CmpAllocate(
  1072. ULONG Size,
  1073. BOOLEAN UseForIo,
  1074. ULONG Tag
  1075. );
  1076. VOID
  1077. CmpFree(
  1078. PVOID MemoryBlock,
  1079. ULONG GlobalQuotaSize
  1080. );
  1081. BOOLEAN
  1082. CmpFileSetSize(
  1083. PHHIVE Hive,
  1084. ULONG FileType,
  1085. ULONG FileSize,
  1086. ULONG OldFileSize
  1087. );
  1088. NTSTATUS
  1089. CmpDoFileSetSize(
  1090. PHHIVE Hive,
  1091. ULONG FileType,
  1092. ULONG FileSize,
  1093. ULONG OldFileSize
  1094. );
  1095. BOOLEAN
  1096. CmpFileWrite(
  1097. PHHIVE Hive,
  1098. ULONG FileType,
  1099. PCMP_OFFSET_ARRAY offsetArray,
  1100. ULONG offsetArrayCount,
  1101. PULONG FileOffset
  1102. );
  1103. BOOLEAN
  1104. CmpFileWriteThroughCache(
  1105. PHHIVE Hive,
  1106. ULONG FileType,
  1107. PCMP_OFFSET_ARRAY offsetArray,
  1108. ULONG offsetArrayCount
  1109. );
  1110. BOOLEAN
  1111. CmpFileRead (
  1112. PHHIVE Hive,
  1113. ULONG FileType,
  1114. PULONG FileOffset,
  1115. PVOID DataBuffer,
  1116. ULONG DataLength
  1117. );
  1118. BOOLEAN
  1119. CmpFileFlush (
  1120. PHHIVE Hive,
  1121. ULONG FileType,
  1122. PLARGE_INTEGER FileOffset,
  1123. ULONG Length
  1124. );
  1125. NTSTATUS
  1126. CmpCreateEvent(
  1127. IN EVENT_TYPE eventType,
  1128. OUT PHANDLE eventHandle,
  1129. OUT PKEVENT *event
  1130. );
  1131. //
  1132. // Configuration Manager CM level registry functions
  1133. //
  1134. NTSTATUS
  1135. CmDeleteKey(
  1136. IN PCM_KEY_BODY KeyBody
  1137. );
  1138. NTSTATUS
  1139. CmDeleteValueKey(
  1140. IN PCM_KEY_CONTROL_BLOCK KeyControlBlock,
  1141. IN UNICODE_STRING ValueName
  1142. );
  1143. NTSTATUS
  1144. CmEnumerateKey(
  1145. IN PCM_KEY_CONTROL_BLOCK KeyControlBlock,
  1146. IN ULONG Index,
  1147. IN KEY_INFORMATION_CLASS KeyInformationClass,
  1148. IN PVOID KeyInformation,
  1149. IN ULONG Length,
  1150. IN PULONG ResultLength
  1151. );
  1152. NTSTATUS
  1153. CmEnumerateValueKey(
  1154. IN PCM_KEY_CONTROL_BLOCK KeyControlBlock,
  1155. IN ULONG Index,
  1156. IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
  1157. IN PVOID KeyValueInformation,
  1158. IN ULONG Length,
  1159. IN PULONG ResultLength
  1160. );
  1161. NTSTATUS
  1162. CmFlushKey(
  1163. IN PHHIVE Hive,
  1164. IN HCELL_INDEX Cell
  1165. );
  1166. NTSTATUS
  1167. CmQueryKey(
  1168. IN PCM_KEY_CONTROL_BLOCK KeyControlBlock,
  1169. IN KEY_INFORMATION_CLASS KeyInformationClass,
  1170. IN PVOID KeyInformation,
  1171. IN ULONG Length,
  1172. IN PULONG ResultLength
  1173. );
  1174. NTSTATUS
  1175. CmQueryValueKey(
  1176. IN PCM_KEY_CONTROL_BLOCK KeyControlBlock,
  1177. IN UNICODE_STRING ValueName,
  1178. IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
  1179. IN PVOID KeyValueInformation,
  1180. IN ULONG Length,
  1181. IN PULONG ResultLength
  1182. );
  1183. NTSTATUS
  1184. CmQueryMultipleValueKey(
  1185. IN PCM_KEY_CONTROL_BLOCK KeyControlBlock,
  1186. IN PKEY_VALUE_ENTRY ValueEntries,
  1187. IN ULONG EntryCount,
  1188. IN PVOID ValueBuffer,
  1189. IN OUT PULONG BufferLength,
  1190. IN OPTIONAL PULONG ResultLength
  1191. );
  1192. NTSTATUS
  1193. CmRenameValueKey(
  1194. IN PCM_KEY_CONTROL_BLOCK KeyControlBlock,
  1195. IN UNICODE_STRING SourceValueName,
  1196. IN UNICODE_STRING TargetValueName,
  1197. IN ULONG TargetIndex
  1198. );
  1199. NTSTATUS
  1200. CmReplaceKey(
  1201. IN PHHIVE Hive,
  1202. IN HCELL_INDEX Cell,
  1203. IN PUNICODE_STRING NewHiveName,
  1204. IN PUNICODE_STRING OldFileName
  1205. );
  1206. NTSTATUS
  1207. CmRestoreKey(
  1208. IN PCM_KEY_CONTROL_BLOCK KeyControlBlock,
  1209. IN HANDLE FileHandle,
  1210. IN ULONG Flags
  1211. );
  1212. NTSTATUS
  1213. CmSaveKey(
  1214. IN PCM_KEY_CONTROL_BLOCK KeyControlBlock,
  1215. IN HANDLE FileHandle,
  1216. IN ULONG HiveVersion
  1217. );
  1218. NTSTATUS
  1219. CmDumpKey(
  1220. IN PCM_KEY_CONTROL_BLOCK KeyControlBlock,
  1221. IN HANDLE FileHandle
  1222. );
  1223. NTSTATUS
  1224. CmSaveMergedKeys(
  1225. IN PCM_KEY_CONTROL_BLOCK HighPrecedenceKcb,
  1226. IN PCM_KEY_CONTROL_BLOCK LowPrecedenceKcb,
  1227. IN HANDLE FileHandle
  1228. );
  1229. NTSTATUS
  1230. CmpShiftHiveFreeBins(
  1231. PCMHIVE CmHive,
  1232. PCMHIVE *NewHive
  1233. );
  1234. NTSTATUS
  1235. CmpOverwriteHive(
  1236. PCMHIVE CmHive,
  1237. PCMHIVE NewHive,
  1238. HCELL_INDEX LinkCell
  1239. );
  1240. VOID
  1241. CmpSwitchStorageAndRebuildMappings(PCMHIVE OldCmHive,
  1242. PCMHIVE NewHive
  1243. );
  1244. NTSTATUS
  1245. CmSetValueKey(
  1246. IN PCM_KEY_CONTROL_BLOCK KeyControlBlock,
  1247. IN PUNICODE_STRING ValueName,
  1248. IN ULONG Type,
  1249. IN PVOID Data,
  1250. IN ULONG DataSize
  1251. );
  1252. NTSTATUS
  1253. CmSetLastWriteTimeKey(
  1254. IN PCM_KEY_CONTROL_BLOCK KeyControlBlock,
  1255. IN PLARGE_INTEGER LastWriteTime
  1256. );
  1257. NTSTATUS
  1258. CmSetKeyUserFlags(
  1259. IN PCM_KEY_CONTROL_BLOCK KeyControlBlock,
  1260. IN ULONG UserFlags
  1261. );
  1262. NTSTATUS
  1263. CmpNotifyChangeKey(
  1264. IN PCM_KEY_BODY KeyBody,
  1265. IN PCM_POST_BLOCK PostBlock,
  1266. IN ULONG CompletionFilter,
  1267. IN BOOLEAN WatchTree,
  1268. IN PVOID Buffer,
  1269. IN ULONG BufferSize,
  1270. IN PCM_POST_BLOCK MasterPostBlock
  1271. );
  1272. NTSTATUS
  1273. CmLoadKey(
  1274. IN POBJECT_ATTRIBUTES TargetKey,
  1275. IN POBJECT_ATTRIBUTES SourceFile,
  1276. IN ULONG Flags,
  1277. IN PCM_KEY_BODY KeyBody
  1278. );
  1279. NTSTATUS
  1280. CmUnloadKey(
  1281. IN PHHIVE Hive,
  1282. IN HCELL_INDEX Cell,
  1283. IN PCM_KEY_CONTROL_BLOCK Kcb,
  1284. IN ULONG Flags
  1285. );
  1286. NTSTATUS
  1287. CmMoveKey(
  1288. IN PCM_KEY_CONTROL_BLOCK KeyControlBlock
  1289. );
  1290. NTSTATUS
  1291. CmCompressKey(
  1292. IN PHHIVE Hive
  1293. );
  1294. //
  1295. // Procedures private to CM
  1296. //
  1297. BOOLEAN
  1298. CmpMarkKeyDirty(
  1299. PHHIVE Hive,
  1300. HCELL_INDEX Cell
  1301. #if DBG
  1302. ,
  1303. BOOLEAN CheckNoSubkeys
  1304. #endif
  1305. );
  1306. BOOLEAN
  1307. CmpDoFlushAll(
  1308. BOOLEAN ForceFlush
  1309. );
  1310. VOID
  1311. CmpFixHiveUsageCount(
  1312. IN PCMHIVE CmHive
  1313. );
  1314. VOID
  1315. CmpLazyFlush(
  1316. VOID
  1317. );
  1318. VOID
  1319. CmpQuotaWarningWorker(
  1320. IN PVOID WorkItem
  1321. );
  1322. VOID
  1323. CmpComputeGlobalQuotaAllowed(
  1324. VOID
  1325. );
  1326. BOOLEAN
  1327. CmpClaimGlobalQuota(
  1328. IN ULONG Size
  1329. );
  1330. VOID
  1331. CmpReleaseGlobalQuota(
  1332. IN ULONG Size
  1333. );
  1334. VOID
  1335. CmpSetGlobalQuotaAllowed(
  1336. VOID
  1337. );
  1338. VOID
  1339. CmpSystemQuotaWarningWorker(
  1340. IN PVOID WorkItem
  1341. );
  1342. BOOLEAN
  1343. CmpCanGrowSystemHive(
  1344. IN PHHIVE Hive,
  1345. IN ULONG NewLength
  1346. );
  1347. //
  1348. // security functions (cmse.c)
  1349. //
  1350. NTSTATUS
  1351. CmpAssignSecurityDescriptor(
  1352. IN PHHIVE Hive,
  1353. IN HCELL_INDEX Cell,
  1354. IN PCM_KEY_NODE Node,
  1355. IN PSECURITY_DESCRIPTOR SecurityDescriptor
  1356. );
  1357. BOOLEAN
  1358. CmpCheckCreateAccess(
  1359. IN PUNICODE_STRING RelativeName,
  1360. IN PSECURITY_DESCRIPTOR Descriptor,
  1361. IN PACCESS_STATE AccessState,
  1362. IN KPROCESSOR_MODE PreviousMode,
  1363. IN ACCESS_MASK AdditionalAccess,
  1364. OUT PNTSTATUS AccessStatus
  1365. );
  1366. BOOLEAN
  1367. CmpCheckNotifyAccess(
  1368. IN PCM_NOTIFY_BLOCK NotifyBlock,
  1369. IN PHHIVE Hive,
  1370. IN PCM_KEY_NODE Node
  1371. );
  1372. PSECURITY_DESCRIPTOR
  1373. CmpHiveRootSecurityDescriptor(
  1374. VOID
  1375. );
  1376. VOID
  1377. CmpFreeSecurityDescriptor(
  1378. IN PHHIVE Hive,
  1379. IN HCELL_INDEX Cell
  1380. );
  1381. //
  1382. // Access to the registry is serialized by a shared resource, CmpRegistryLock.
  1383. //
  1384. extern ERESOURCE CmpRegistryLock;
  1385. //
  1386. // Support for "StarveExclusive" mode suring a flush
  1387. //
  1388. extern LONG CmpFlushStarveWriters;
  1389. #define ENTER_FLUSH_MODE() InterlockedIncrement (&CmpFlushStarveWriters);
  1390. #if DBG
  1391. #define EXIT_FLUSH_MODE() \
  1392. { \
  1393. LONG LocalIncrement = (LONG)InterlockedDecrement (&CmpFlushStarveWriters); \
  1394. ASSERT( LocalIncrement >= 0 ); \
  1395. }
  1396. #else
  1397. #define EXIT_FLUSH_MODE() InterlockedDecrement (&CmpFlushStarveWriters)
  1398. #endif
  1399. #if 0
  1400. #define CmpLockRegistry() KeEnterCriticalRegion(); \
  1401. ExAcquireResourceShared(&CmpRegistryLock, TRUE)
  1402. #define CmpLockRegistryExclusive() KeEnterCriticalRegion(); \
  1403. ExAcquireResourceExclusive(&CmpRegistryLock,TRUE)
  1404. #else
  1405. VOID
  1406. CmpLockRegistryExclusive(
  1407. VOID
  1408. );
  1409. VOID
  1410. CmpLockRegistry(
  1411. VOID
  1412. );
  1413. #endif
  1414. VOID
  1415. CmpUnlockRegistry(
  1416. );
  1417. #if DBG
  1418. BOOLEAN
  1419. CmpTestRegistryLock(
  1420. VOID
  1421. );
  1422. BOOLEAN
  1423. CmpTestRegistryLockExclusive(
  1424. VOID
  1425. );
  1426. BOOLEAN
  1427. CmpTestKCBTreeLockExclusive(
  1428. VOID
  1429. );
  1430. #endif
  1431. NTSTATUS
  1432. CmpQueryKeyData(
  1433. PHHIVE Hive,
  1434. PCM_KEY_NODE Node,
  1435. KEY_INFORMATION_CLASS KeyInformationClass,
  1436. PVOID KeyInformation,
  1437. ULONG Length,
  1438. PULONG ResultLength
  1439. #if defined(CMP_STATS) || defined(CMP_KCB_CACHE_VALIDATION)
  1440. ,
  1441. PCM_KEY_CONTROL_BLOCK Kcb
  1442. #endif
  1443. );
  1444. NTSTATUS
  1445. CmpQueryKeyDataFromCache(
  1446. PCM_KEY_CONTROL_BLOCK Kcb,
  1447. KEY_INFORMATION_CLASS KeyInformationClass,
  1448. PVOID KeyInformation,
  1449. ULONG Length,
  1450. PULONG ResultLength
  1451. );
  1452. BOOLEAN
  1453. CmpFreeKeyBody(
  1454. PHHIVE Hive,
  1455. HCELL_INDEX Cell
  1456. );
  1457. BOOLEAN
  1458. CmpFreeValue(
  1459. PHHIVE Hive,
  1460. HCELL_INDEX Cell
  1461. );
  1462. HCELL_INDEX
  1463. CmpFindValueByName(
  1464. PHHIVE Hive,
  1465. PCM_KEY_NODE KeyNode,
  1466. PUNICODE_STRING Name
  1467. );
  1468. NTSTATUS
  1469. CmpDeleteChildByName(
  1470. PHHIVE Hive,
  1471. HCELL_INDEX Cell,
  1472. UNICODE_STRING Name,
  1473. PHCELL_INDEX ChildCell
  1474. );
  1475. NTSTATUS
  1476. CmpFreeKeyByCell(
  1477. PHHIVE Hive,
  1478. HCELL_INDEX Cell,
  1479. BOOLEAN Unlink
  1480. );
  1481. BOOLEAN
  1482. CmpFindNameInList(
  1483. IN PHHIVE Hive,
  1484. IN PCHILD_LIST ChildList,
  1485. IN PUNICODE_STRING Name,
  1486. IN OPTIONAL PULONG ChildIndex,
  1487. OUT PHCELL_INDEX CellIndex
  1488. );
  1489. HCELL_INDEX
  1490. CmpCopyCell(
  1491. PHHIVE SourceHive,
  1492. HCELL_INDEX SourceCell,
  1493. PHHIVE TargetHive,
  1494. HSTORAGE_TYPE Type
  1495. );
  1496. HCELL_INDEX
  1497. CmpCopyValue(
  1498. PHHIVE SourceHive,
  1499. HCELL_INDEX SourceValueCell,
  1500. PHHIVE TargetHive,
  1501. HSTORAGE_TYPE Type
  1502. );
  1503. HCELL_INDEX
  1504. CmpCopyKeyPartial(
  1505. PHHIVE SourceHive,
  1506. HCELL_INDEX SourceKeyCell,
  1507. PHHIVE TargetHive,
  1508. HCELL_INDEX Parent,
  1509. BOOLEAN CopyValues
  1510. );
  1511. BOOLEAN
  1512. CmpCopySyncTree(
  1513. PHHIVE SourceHive,
  1514. HCELL_INDEX SourceCell,
  1515. PHHIVE TargetHive,
  1516. HCELL_INDEX TargetCell,
  1517. BOOLEAN CopyVolatile,
  1518. CMP_COPY_TYPE CopyType
  1519. );
  1520. //
  1521. // BOOLEAN
  1522. // CmpCopyTree(
  1523. // PHHIVE SourceHive,
  1524. // HCELL_INDEX SourceCell,
  1525. // PHHIVE TargetHive,
  1526. // HCELL_INDEX TargetCell
  1527. // );
  1528. //
  1529. #define CmpCopyTree(s,c,t,l) CmpCopySyncTree(s,c,t,l,FALSE,Copy)
  1530. //
  1531. // BOOLEAN
  1532. // CmpCopyTreeEx(
  1533. // PHHIVE SourceHive,
  1534. // HCELL_INDEX SourceCell,
  1535. // PHHIVE TargetHive,
  1536. // HCELL_INDEX TargetCell,
  1537. // BOOLEAN CopyVolatile
  1538. // );
  1539. //
  1540. #define CmpCopyTreeEx(s,c,t,l,f) CmpCopySyncTree(s,c,t,l,f,Copy)
  1541. //
  1542. // BOOLEAN
  1543. // CmpSyncTrees(
  1544. // PHHIVE SourceHive,
  1545. // HCELL_INDEX SourceCell,
  1546. // PHHIVE TargetHive,
  1547. // HCELL_INDEX TargetCell,
  1548. // BOOLEAN CopyVolatile);
  1549. //
  1550. #define CmpSyncTrees(s,c,t,l,f) CmpCopySyncTree(s,c,t,l,f,Sync)
  1551. //
  1552. // BOOLEAN
  1553. // CmpMergeTrees(
  1554. // PHHIVE SourceHive,
  1555. // HCELL_INDEX SourceCell,
  1556. // PHHIVE TargetHive,
  1557. // HCELL_INDEX TargetCell);
  1558. //
  1559. #define CmpMergeTrees(s,c,t,l) CmpCopySyncTree(s,c,t,l,FALSE,Merge)
  1560. VOID
  1561. CmpDeleteTree(
  1562. PHHIVE Hive,
  1563. HCELL_INDEX Cell
  1564. );
  1565. VOID
  1566. CmpSetVersionData(
  1567. VOID
  1568. );
  1569. NTSTATUS
  1570. CmpInitializeHardwareConfiguration(
  1571. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  1572. );
  1573. NTSTATUS
  1574. CmpInitializeMachineDependentConfiguration(
  1575. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  1576. );
  1577. NTSTATUS
  1578. CmpInitializeRegistryNode(
  1579. IN PCONFIGURATION_COMPONENT_DATA CurrentEntry,
  1580. IN HANDLE ParentHandle,
  1581. OUT PHANDLE NewHandle,
  1582. IN INTERFACE_TYPE InterfaceType,
  1583. IN ULONG BusNumber,
  1584. IN PUSHORT DeviceIndexTable
  1585. );
  1586. NTSTATUS
  1587. CmpInitializeHive(
  1588. PCMHIVE *CmHive,
  1589. ULONG OperationType,
  1590. ULONG HiveFlags,
  1591. ULONG FileType,
  1592. PVOID HiveData OPTIONAL,
  1593. HANDLE Primary,
  1594. HANDLE Log,
  1595. HANDLE External,
  1596. PUNICODE_STRING FileName OPTIONAL,
  1597. ULONG CheckFlags
  1598. );
  1599. LOGICAL
  1600. CmpDestroyHive(
  1601. IN PHHIVE Hive,
  1602. IN HCELL_INDEX Cell
  1603. );
  1604. VOID
  1605. CmpInitializeRegistryNames(
  1606. VOID
  1607. );
  1608. VOID
  1609. CmpInitializeCache(
  1610. VOID
  1611. );
  1612. PCM_KEY_CONTROL_BLOCK
  1613. CmpCreateKeyControlBlock(
  1614. PHHIVE Hive,
  1615. HCELL_INDEX Cell,
  1616. PCM_KEY_NODE Node,
  1617. PCM_KEY_CONTROL_BLOCK ParentKcb,
  1618. BOOLEAN FakeKey,
  1619. PUNICODE_STRING KeyName
  1620. );
  1621. VOID CmpCleanUpKCBCacheTable();
  1622. typedef struct _QUERY_OPEN_SUBKEYS_CONTEXT {
  1623. ULONG BufferLength;
  1624. PVOID Buffer;
  1625. ULONG RequiredSize;
  1626. NTSTATUS StatusCode;
  1627. ULONG UsedLength;
  1628. PVOID KeyBodyToIgnore;
  1629. PVOID CurrentNameBuffer;
  1630. } QUERY_OPEN_SUBKEYS_CONTEXT, *PQUERY_OPEN_SUBKEYS_CONTEXT;
  1631. ULONG
  1632. CmpSearchForOpenSubKeys(
  1633. IN PCM_KEY_CONTROL_BLOCK SearchKey,
  1634. IN SUBKEY_SEARCH_TYPE SearchType,
  1635. IN OUT PVOID SearchContext OPTIONAL
  1636. );
  1637. VOID
  1638. CmpDereferenceKeyControlBlock(
  1639. PCM_KEY_CONTROL_BLOCK KeyControlBlock
  1640. );
  1641. VOID
  1642. CmpRemoveKeyControlBlock(
  1643. PCM_KEY_CONTROL_BLOCK KeyControlBlock
  1644. );
  1645. VOID
  1646. CmpReportNotify(
  1647. PCM_KEY_CONTROL_BLOCK KeyControlBlock,
  1648. PHHIVE Hive,
  1649. HCELL_INDEX Cell,
  1650. ULONG NotifyMask
  1651. );
  1652. VOID
  1653. CmpPostNotify(
  1654. PCM_NOTIFY_BLOCK NotifyBlock,
  1655. PUNICODE_STRING Name OPTIONAL,
  1656. ULONG Filter,
  1657. NTSTATUS Status,
  1658. PLIST_ENTRY ExternalKeyDeref OPTIONAL
  1659. #ifdef CM_NOTIFY_CHANGED_KCB_FULLPATH
  1660. ,
  1661. PUNICODE_STRING ChangedKcbName OPTIONAL
  1662. #endif //CM_NOTIFY_CHANGED_KCB_FULLPATH
  1663. );
  1664. PCM_POST_BLOCK
  1665. CmpAllocatePostBlock(
  1666. IN POST_BLOCK_TYPE BlockType,
  1667. IN ULONG PostFlags,
  1668. IN PCM_KEY_BODY KeyBody,
  1669. IN PCM_POST_BLOCK MasterBlock
  1670. );
  1671. //
  1672. //PCM_POST_BLOCK
  1673. //CmpAllocateMasterPostBlock(
  1674. // IN POST_BLOCK_TYPE BlockType
  1675. // );
  1676. //
  1677. #define CmpAllocateMasterPostBlock(b) CmpAllocatePostBlock(b,REG_NOTIFY_MASTER_POST,NULL,NULL)
  1678. //
  1679. //PCM_POST_BLOCK
  1680. //CmpAllocateSlavePostBlock(
  1681. // IN POST_BLOCK_TYPE BlockType,
  1682. // IN PCM_KEY_BODY KeyBody,
  1683. // IN PCM_POST_BLOCK MasterBlock
  1684. // );
  1685. //
  1686. #define CmpAllocateSlavePostBlock(b,k,m) CmpAllocatePostBlock(b,0,k,m)
  1687. VOID
  1688. CmpFreePostBlock(
  1689. IN PCM_POST_BLOCK PostBlock
  1690. );
  1691. VOID
  1692. CmpPostApc(
  1693. struct _KAPC *Apc,
  1694. PKNORMAL_ROUTINE *NormalRoutine,
  1695. PVOID *NormalContext,
  1696. PVOID *SystemArgument1,
  1697. PVOID *SystemArgument2
  1698. );
  1699. VOID
  1700. CmpFlushNotify(
  1701. PCM_KEY_BODY KeyBody,
  1702. BOOLEAN LockHeld
  1703. );
  1704. VOID
  1705. CmpPostApcRunDown(
  1706. struct _KAPC *Apc
  1707. );
  1708. NTSTATUS
  1709. CmpOpenHiveFiles(
  1710. PUNICODE_STRING BaseName,
  1711. PWSTR Extension OPTIONAL,
  1712. PHANDLE Primary,
  1713. PHANDLE Secondary,
  1714. PULONG PrimaryDisposition,
  1715. PULONG SecondaryDispoition,
  1716. BOOLEAN CreateAllowed,
  1717. BOOLEAN MarkAsSystemHive,
  1718. BOOLEAN NoBuffering,
  1719. PULONG ClusterSize
  1720. );
  1721. NTSTATUS
  1722. CmpLinkHiveToMaster(
  1723. PUNICODE_STRING LinkName,
  1724. HANDLE RootDirectory,
  1725. PCMHIVE CmHive,
  1726. BOOLEAN Allocate,
  1727. PSECURITY_DESCRIPTOR SecurityDescriptor
  1728. );
  1729. NTSTATUS
  1730. CmpSaveBootControlSet(
  1731. IN USHORT ControlSetNum
  1732. );
  1733. //
  1734. // checkout procedure
  1735. //
  1736. //
  1737. // Flags to be passed to CmCheckRegistry
  1738. //
  1739. #define CM_CHECK_REGISTRY_CHECK_CLEAN 0x00000001
  1740. #define CM_CHECK_REGISTRY_FORCE_CLEAN 0x00000002
  1741. #define CM_CHECK_REGISTRY_LOADER_CLEAN 0x00000004
  1742. #define CM_CHECK_REGISTRY_SYSTEM_CLEAN 0x00000008
  1743. #define CM_CHECK_REGISTRY_HIVE_CHECK 0x00010000
  1744. ULONG
  1745. CmCheckRegistry(
  1746. PCMHIVE CmHive,
  1747. ULONG Flags
  1748. );
  1749. BOOLEAN
  1750. CmpValidateHiveSecurityDescriptors(
  1751. IN PHHIVE Hive,
  1752. OUT PBOOLEAN ResetSD
  1753. );
  1754. //
  1755. // cmboot - functions for determining driver load lists
  1756. //
  1757. #define CM_HARDWARE_PROFILE_STR_DATABASE L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\IDConfigDB"
  1758. #define CM_HARDWARE_PROFILE_STR_CCS_HWPROFILE L"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles"
  1759. #define CM_HARDWARE_PROFILE_STR_CCS_CURRENT L"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\Current"
  1760. //
  1761. // Alias table key names in IDConfigDB
  1762. //
  1763. #define CM_HARDWARE_PROFILE_STR_ALIAS L"Alias"
  1764. #define CM_HARDWARE_PROFILE_STR_ACPI_ALIAS L"AcpiAlias"
  1765. #define CM_HARDWARE_PROFILE_STR_HARDWARE_PROFILES L"Hardware Profiles"
  1766. //
  1767. // Entries in the alias tables (value names)
  1768. //
  1769. #define CM_HARDWARE_PROFILE_STR_DOCKING_STATE L"DockingState"
  1770. #define CM_HARDWARE_PROFILE_STR_CAPABILITIES L"Capabilities"
  1771. #define CM_HARDWARE_PROFILE_STR_DOCKID L"DockID"
  1772. #define CM_HARDWARE_PROFILE_STR_SERIAL_NUMBER L"SerialNumber"
  1773. #define CM_HARDWARE_PROFILE_STR_ACPI_SERIAL_NUMBER L"AcpiSerialNumber"
  1774. #define CM_HARDWARE_PROFILE_STR_PROFILE_NUMBER L"ProfileNumber"
  1775. #define CM_HARDWARE_PROFILE_STR_ALIASABLE L"Aliasable"
  1776. #define CM_HARDWARE_PROFILE_STR_CLONED L"Cloned"
  1777. //
  1778. // Entries in the profile tables.
  1779. //
  1780. #define CM_HARDWARE_PROFILE_STR_PRISTINE L"Pristine"
  1781. #define CM_HARDWARE_PROFILE_STR_PREFERENCE_ORDER L"PreferenceOrder"
  1782. #define CM_HARDWARE_PROFILE_STR_FRIENDLY_NAME L"FriendlyName"
  1783. #define CM_HARDWARE_PROFILE_STR_CURRENT_DOCK_INFO L"CurrentDockInfo"
  1784. #define CM_HARDWARE_PROFILE_STR_HW_PROFILE_GUID L"HwProfileGuid"
  1785. //
  1786. // Entries for the root Hardware Profiles key.
  1787. //
  1788. #define CM_HARDWARE_PROFILE_STR_DOCKED L"Docked"
  1789. #define CM_HARDWARE_PROFILE_STR_UNDOCKED L"Undocked"
  1790. #define CM_HARDWARE_PROFILE_STR_UNKNOWN L"Unknown"
  1791. //
  1792. // List structure used in config manager init
  1793. //
  1794. typedef struct _HIVE_LIST_ENTRY {
  1795. PWSTR Name;
  1796. PWSTR BaseName; // MACHINE or USER
  1797. PCMHIVE CmHive;
  1798. ULONG HHiveFlags;
  1799. ULONG CmHiveFlags;
  1800. PCMHIVE CmHive2;
  1801. BOOLEAN ThreadFinished;
  1802. BOOLEAN ThreadStarted;
  1803. BOOLEAN Allocate;
  1804. } HIVE_LIST_ENTRY, *PHIVE_LIST_ENTRY;
  1805. //
  1806. // structure definitions shared with the boot loader
  1807. // to select the hardware profile.
  1808. //
  1809. typedef struct _CM_HARDWARE_PROFILE {
  1810. ULONG NameLength;
  1811. PWSTR FriendlyName;
  1812. ULONG PreferenceOrder;
  1813. ULONG Id;
  1814. ULONG Flags;
  1815. } CM_HARDWARE_PROFILE, *PCM_HARDWARE_PROFILE;
  1816. #define CM_HP_FLAGS_ALIASABLE 1
  1817. #define CM_HP_FLAGS_TRUE_MATCH 2
  1818. #define CM_HP_FLAGS_PRISTINE 4
  1819. #define CM_HP_FLAGS_DUPLICATE 8
  1820. typedef struct _CM_HARDWARE_PROFILE_LIST {
  1821. ULONG MaxProfileCount;
  1822. ULONG CurrentProfileCount;
  1823. CM_HARDWARE_PROFILE Profile[1];
  1824. } CM_HARDWARE_PROFILE_LIST, *PCM_HARDWARE_PROFILE_LIST;
  1825. typedef struct _CM_HARDWARE_PROFILE_ALIAS {
  1826. ULONG ProfileNumber;
  1827. ULONG DockState;
  1828. ULONG DockID;
  1829. ULONG SerialNumber;
  1830. } CM_HARDWARE_PROFILE_ALIAS, *PCM_HARDWARE_PROFILE_ALIAS;
  1831. typedef struct _CM_HARDWARE_PROFILE_ALIAS_LIST {
  1832. ULONG MaxAliasCount;
  1833. ULONG CurrentAliasCount;
  1834. CM_HARDWARE_PROFILE_ALIAS Alias[1];
  1835. } CM_HARDWARE_PROFILE_ALIAS_LIST, *PCM_HARDWARE_PROFILE_ALIAS_LIST;
  1836. typedef struct _CM_HARDWARE_PROFILE_ACPI_ALIAS {
  1837. ULONG ProfileNumber;
  1838. ULONG DockState;
  1839. ULONG SerialLength;
  1840. PCHAR SerialNumber;
  1841. } CM_HARDWARE_PROFILE_ACPI_ALIAS, *PCM_HARDWARE_PROFILE_ACPI_ALIAS;
  1842. typedef struct _CM_HARDWARE_PROFILE_ACPI_ALIAS_LIST {
  1843. ULONG MaxAliasCount;
  1844. ULONG CurrentAliasCount;
  1845. CM_HARDWARE_PROFILE_ACPI_ALIAS Alias[1];
  1846. } CM_HARDWARE_PROFILE_ACPI_ALIAS_LIST, *PCM_HARDWARE_PROFILE_ACPI_ALIAS_LIST;
  1847. HCELL_INDEX
  1848. CmpFindControlSet(
  1849. IN PHHIVE SystemHive,
  1850. IN HCELL_INDEX RootCell,
  1851. IN PUNICODE_STRING SelectName,
  1852. OUT PBOOLEAN AutoSelect
  1853. );
  1854. BOOLEAN
  1855. CmpValidateSelect(
  1856. IN PHHIVE SystemHive,
  1857. IN HCELL_INDEX RootCell
  1858. );
  1859. BOOLEAN
  1860. CmpFindDrivers(
  1861. IN PHHIVE Hive,
  1862. IN HCELL_INDEX ControlSet,
  1863. IN SERVICE_LOAD_TYPE LoadType,
  1864. IN PWSTR BootFileSystem OPTIONAL,
  1865. IN PLIST_ENTRY DriverListHead
  1866. );
  1867. BOOLEAN
  1868. CmpFindNLSData(
  1869. IN PHHIVE Hive,
  1870. IN HCELL_INDEX ControlSet,
  1871. OUT PUNICODE_STRING AnsiFilename,
  1872. OUT PUNICODE_STRING OemFilename,
  1873. OUT PUNICODE_STRING CaseTableFilename,
  1874. OUT PUNICODE_STRING OemHalFilename
  1875. );
  1876. HCELL_INDEX
  1877. CmpFindProfileOption(
  1878. IN PHHIVE Hive,
  1879. IN HCELL_INDEX ControlSet,
  1880. OUT PCM_HARDWARE_PROFILE_LIST *ProfileList,
  1881. OUT PCM_HARDWARE_PROFILE_ALIAS_LIST *AliasList,
  1882. OUT PULONG Timeout
  1883. );
  1884. VOID
  1885. CmpSetCurrentProfile(
  1886. IN PHHIVE Hive,
  1887. IN HCELL_INDEX ControlSet,
  1888. IN PCM_HARDWARE_PROFILE Profile
  1889. );
  1890. BOOLEAN
  1891. CmpResolveDriverDependencies(
  1892. IN PLIST_ENTRY DriverListHead
  1893. );
  1894. BOOLEAN
  1895. CmpSortDriverList(
  1896. IN PHHIVE Hive,
  1897. IN HCELL_INDEX ControlSet,
  1898. IN PLIST_ENTRY DriverListHead
  1899. );
  1900. HCELL_INDEX
  1901. CmpFindSubKeyByName(
  1902. PHHIVE Hive,
  1903. PCM_KEY_NODE Parent,
  1904. PUNICODE_STRING SearchName
  1905. );
  1906. HCELL_INDEX
  1907. CmpFindSubKeyByNumber(
  1908. PHHIVE Hive,
  1909. PCM_KEY_NODE Parent,
  1910. ULONG Number
  1911. );
  1912. BOOLEAN
  1913. CmpAddSubKey(
  1914. PHHIVE Hive,
  1915. HCELL_INDEX Parent,
  1916. HCELL_INDEX Child
  1917. );
  1918. BOOLEAN
  1919. CmpMarkIndexDirty(
  1920. PHHIVE Hive,
  1921. HCELL_INDEX ParentKey,
  1922. HCELL_INDEX TargetKey
  1923. );
  1924. BOOLEAN
  1925. CmpRemoveSubKey(
  1926. PHHIVE Hive,
  1927. HCELL_INDEX ParentKey,
  1928. HCELL_INDEX TargetKey
  1929. );
  1930. BOOLEAN
  1931. CmpGetNextName(
  1932. IN OUT PUNICODE_STRING RemainingName,
  1933. OUT PUNICODE_STRING NextName,
  1934. OUT PBOOLEAN Last
  1935. );
  1936. NTSTATUS
  1937. CmpAddToHiveFileList(
  1938. PCMHIVE CmHive
  1939. );
  1940. VOID
  1941. CmpRemoveFromHiveFileList(
  1942. );
  1943. NTSTATUS
  1944. CmpInitHiveFromFile(
  1945. IN PUNICODE_STRING FileName,
  1946. IN ULONG HiveFlags,
  1947. OUT PCMHIVE *CmHive,
  1948. IN OUT PBOOLEAN Allocate,
  1949. IN OUT PBOOLEAN RegistryLocked,
  1950. IN ULONG CheckFlags
  1951. );
  1952. NTSTATUS
  1953. CmpCloneHwProfile (
  1954. IN HANDLE IDConfigDB,
  1955. IN HANDLE Parent,
  1956. IN HANDLE OldProfile,
  1957. IN ULONG OldProfileNumber,
  1958. IN USHORT DockingState,
  1959. OUT PHANDLE NewProfile,
  1960. OUT PULONG NewProfileNumber
  1961. );
  1962. NTSTATUS
  1963. CmpCreateHwProfileFriendlyName (
  1964. IN HANDLE IDConfigDB,
  1965. IN ULONG DockingState,
  1966. IN ULONG NewProfileNumber,
  1967. OUT PUNICODE_STRING FriendlyName
  1968. );
  1969. typedef
  1970. NTSTATUS
  1971. (*PCM_ACPI_SELECTION_ROUTINE) (
  1972. IN PCM_HARDWARE_PROFILE_LIST ProfileList,
  1973. OUT PULONG ProfileIndexToUse, // Set to -1 for none.
  1974. IN PVOID Context
  1975. );
  1976. NTSTATUS
  1977. CmSetAcpiHwProfile (
  1978. IN PPROFILE_ACPI_DOCKING_STATE DockState,
  1979. IN PCM_ACPI_SELECTION_ROUTINE,
  1980. IN PVOID Context,
  1981. OUT PHANDLE NewProfile,
  1982. OUT PBOOLEAN ProfileChanged
  1983. );
  1984. NTSTATUS
  1985. CmpAddAcpiAliasEntry (
  1986. IN HANDLE IDConfigDB,
  1987. IN PPROFILE_ACPI_DOCKING_STATE NewDockState,
  1988. IN ULONG ProfileNumber,
  1989. IN PWCHAR nameBuffer,
  1990. IN PVOID valueBuffer,
  1991. IN ULONG valueBufferLength,
  1992. IN BOOLEAN PreventDuplication
  1993. );
  1994. //
  1995. // Routines for handling registry compressed names
  1996. //
  1997. USHORT
  1998. CmpNameSize(
  1999. IN PHHIVE Hive,
  2000. IN PUNICODE_STRING Name
  2001. );
  2002. USHORT
  2003. CmpCopyName(
  2004. IN PHHIVE Hive,
  2005. IN PWCHAR Destination,
  2006. IN PUNICODE_STRING Source
  2007. );
  2008. VOID
  2009. CmpCopyCompressedName(
  2010. IN PWCHAR Destination,
  2011. IN ULONG DestinationLength,
  2012. IN PWCHAR Source,
  2013. IN ULONG SourceLength
  2014. );
  2015. USHORT
  2016. CmpCompressedNameSize(
  2017. IN PWCHAR Name,
  2018. IN ULONG Length
  2019. );
  2020. //
  2021. // ----- CACHED_DATA -----
  2022. //
  2023. // When values are not cached, List in ValueCache is the Hive cell index to the value list.
  2024. // When they are cached, List will be pointer to the allocation. We distinguish them by
  2025. // marking the lowest bit in the variable to indicate it is a cached allocation.
  2026. //
  2027. // Note that the cell index for value list
  2028. // is stored in the cached allocation. It is not used now but may be in further performance
  2029. // optimization.
  2030. //
  2031. // When value key and vaule data are cached, there is only one allocation for both.
  2032. // Value data is appended that the end of value key. DataCacheType indicates
  2033. // whether data is cached and ValueKeySize tells how big is the value key (so
  2034. // we can calculate the address of cached value data)
  2035. //
  2036. //
  2037. PCM_NAME_CONTROL_BLOCK
  2038. CmpGetNameControlBlock(
  2039. PUNICODE_STRING NodeName
  2040. );
  2041. VOID
  2042. CmpDereferenceKeyControlBlockWithLock(
  2043. PCM_KEY_CONTROL_BLOCK KeyControlBlock
  2044. );
  2045. VOID
  2046. CmpCleanUpSubKeyInfo(
  2047. PCM_KEY_CONTROL_BLOCK KeyControlBlock
  2048. );
  2049. VOID
  2050. CmpCleanUpKcbValueCache(
  2051. PCM_KEY_CONTROL_BLOCK KeyControlBlock
  2052. );
  2053. VOID
  2054. CmpRebuildKcbCache(
  2055. PCM_KEY_CONTROL_BLOCK KeyControlBlock
  2056. );
  2057. /*
  2058. VOID
  2059. CmpSetUpKcbValueCache(
  2060. PCM_KEY_CONTROL_BLOCK KeyControlBlock,
  2061. ULONG Count,
  2062. ULONG_PTR ValueList
  2063. )
  2064. */
  2065. #define CmpSetUpKcbValueCache(KeyControlBlock,_Count,_List) \
  2066. ASSERT( !(CMP_IS_CELL_CACHED(KeyControlBlock->ValueCache.ValueList)) ); \
  2067. ASSERT( !(KeyControlBlock->ExtFlags & CM_KCB_SYM_LINK_FOUND) ); \
  2068. KeyControlBlock->ValueCache.Count = (ULONG)(_Count); \
  2069. KeyControlBlock->ValueCache.ValueList = (ULONG_PTR)(_List)
  2070. VOID
  2071. CmpCleanUpKcbCacheWithLock(
  2072. PCM_KEY_CONTROL_BLOCK KeyControlBlock
  2073. );
  2074. VOID
  2075. CmpRemoveFromDelayedClose(
  2076. IN PCM_KEY_CONTROL_BLOCK kcb
  2077. );
  2078. PUNICODE_STRING
  2079. CmpConstructName(
  2080. PCM_KEY_CONTROL_BLOCK kcb
  2081. );
  2082. PCELL_DATA
  2083. CmpGetValueListFromCache(
  2084. IN PHHIVE Hive,
  2085. IN PCACHED_CHILD_LIST ChildList,
  2086. OUT BOOLEAN *IndexCached,
  2087. OUT PHCELL_INDEX ValueListToRelease
  2088. );
  2089. PCM_KEY_VALUE
  2090. CmpGetValueKeyFromCache(
  2091. IN PHHIVE Hive,
  2092. IN PCELL_DATA List,
  2093. IN ULONG Index,
  2094. OUT PPCM_CACHED_VALUE *ContainingList,
  2095. IN BOOLEAN IndexCached,
  2096. OUT BOOLEAN *ValueCached,
  2097. OUT PHCELL_INDEX CellToRelease
  2098. );
  2099. PCM_KEY_VALUE
  2100. CmpFindValueByNameFromCache(
  2101. IN PHHIVE Hive,
  2102. IN PCACHED_CHILD_LIST ChildList,
  2103. IN PUNICODE_STRING Name,
  2104. OUT PPCM_CACHED_VALUE *ContainingList,
  2105. OUT ULONG *Index,
  2106. OUT BOOLEAN *ValueCached,
  2107. OUT PHCELL_INDEX CellToRelease
  2108. );
  2109. NTSTATUS
  2110. CmpQueryKeyValueData(
  2111. PHHIVE Hive,
  2112. PCM_CACHED_VALUE *ContainingList,
  2113. PCM_KEY_VALUE ValueKey,
  2114. BOOLEAN ValueCached,
  2115. KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
  2116. PVOID KeyValueInformation,
  2117. ULONG Length,
  2118. PULONG ResultLength
  2119. );
  2120. BOOLEAN
  2121. CmpReferenceKeyControlBlock(
  2122. PCM_KEY_CONTROL_BLOCK KeyControlBlock
  2123. );
  2124. VOID
  2125. CmpInitializeKeyNameString(PCM_KEY_NODE Cell,
  2126. PUNICODE_STRING KeyName,
  2127. WCHAR *NameBuffer
  2128. );
  2129. VOID
  2130. CmpInitializeValueNameString(PCM_KEY_VALUE Cell,
  2131. PUNICODE_STRING ValueName,
  2132. WCHAR *NameBuffer
  2133. );
  2134. VOID
  2135. CmpFlushNotifiesOnKeyBodyList(
  2136. IN PCM_KEY_CONTROL_BLOCK kcb
  2137. );
  2138. #ifdef CM_NOTIFY_CHANGED_KCB_FULLPATH
  2139. VOID
  2140. CmpFillCallerBuffer(
  2141. PCM_POST_BLOCK PostBlock,
  2142. PUNICODE_STRING ChangedKcbName
  2143. );
  2144. #endif //CM_NOTIFY_CHANGED_KCB_FULLPATH
  2145. extern ULONG CmpHashTableSize;
  2146. extern PCM_KEY_HASH *CmpCacheTable;
  2147. #ifdef _WANT_MACHINE_IDENTIFICATION
  2148. BOOLEAN
  2149. CmpGetBiosDateFromRegistry(
  2150. IN PHHIVE Hive,
  2151. IN HCELL_INDEX ControlSet,
  2152. OUT PUNICODE_STRING Date
  2153. );
  2154. BOOLEAN
  2155. CmpGetBiosinfoFileNameFromRegistry(
  2156. IN PHHIVE Hive,
  2157. IN HCELL_INDEX ControlSet,
  2158. OUT PUNICODE_STRING InfName
  2159. );
  2160. #endif
  2161. // Utility macro to set the fields of an IO_STATUS_BLOCK. On sundown, 32bit processes
  2162. // will pass in a 32bit Iosb, and 64bit processes will pass in a 64bit Iosb.
  2163. #if defined(_WIN64)
  2164. #define CmpSetIoStatus(Iosb, s, i, UseIosb32) \
  2165. if ((UseIosb32)) { \
  2166. ((PIO_STATUS_BLOCK32)(Iosb))->Status = (NTSTATUS)(s); \
  2167. ((PIO_STATUS_BLOCK32)(Iosb))->Information = (ULONG)(i); \
  2168. } \
  2169. else { \
  2170. (Iosb)->Status = (s); \
  2171. (Iosb)->Information = (i); \
  2172. } \
  2173. #else
  2174. #define CmpSetIoStatus(Iosb, s, i, UseIosb32) \
  2175. (Iosb)->Status = (s); \
  2176. (Iosb)->Information = (i); \
  2177. #endif
  2178. #define CmpCheckIoStatusPointer(AsyncUser) \
  2179. if( (PVOID)((AsyncUser).IoStatusBlock) == (PVOID)(&((AsyncUser).IoStatusBlock)) ) { \
  2180. DbgPrint("IoStatusBlock pointing onto itself AsyncUser = %p\n",&(AsyncUser)); \
  2181. DbgBreakPoint(); \
  2182. }
  2183. // Dragos: new functions (prototyping)
  2184. NTSTATUS
  2185. CmpAquireFileObjectForFile(
  2186. IN PCMHIVE CmHive,
  2187. IN HANDLE FileHandle,
  2188. OUT PFILE_OBJECT *FileObject
  2189. );
  2190. VOID
  2191. CmpDropFileObjectForHive(
  2192. IN PCMHIVE CmHive
  2193. );
  2194. VOID
  2195. CmpTouchView(
  2196. IN PCMHIVE CmHive,
  2197. IN PCM_VIEW_OF_FILE CmView,
  2198. IN ULONG Cell
  2199. );
  2200. NTSTATUS
  2201. CmpMapCmView(
  2202. IN PCMHIVE CmHive,
  2203. IN ULONG FileOffset,
  2204. OUT PCM_VIEW_OF_FILE *CmView,
  2205. IN BOOLEAN MapInited
  2206. );
  2207. VOID
  2208. CmpInitHiveViewList (
  2209. IN PCMHIVE CmHive
  2210. );
  2211. VOID
  2212. CmpDestroyHiveViewList (
  2213. IN PCMHIVE CmHive
  2214. );
  2215. NTSTATUS
  2216. CmpPinCmView (
  2217. IN PCMHIVE CmHive,
  2218. PCM_VIEW_OF_FILE CmView
  2219. );
  2220. VOID
  2221. CmpUnPinCmView (
  2222. IN PCMHIVE CmHive,
  2223. IN PCM_VIEW_OF_FILE CmView,
  2224. IN BOOLEAN SetClean,
  2225. IN BOOLEAN MapIsValid
  2226. );
  2227. NTSTATUS
  2228. CmpMapThisBin(
  2229. PCMHIVE CmHive,
  2230. HCELL_INDEX Cell,
  2231. BOOLEAN Touch
  2232. );
  2233. #if 0
  2234. VOID
  2235. CmpUnmapAditionalViews(
  2236. IN PCMHIVE CmHive
  2237. );
  2238. VOID
  2239. CmpUnmapFakeViews(
  2240. IN PCMHIVE CmHive
  2241. );
  2242. VOID
  2243. CmpMapEntireFileInFakeViews(
  2244. IN PCMHIVE CmHive,
  2245. IN ULONG Length
  2246. );
  2247. #endif
  2248. VOID
  2249. CmpInitializeDelayedCloseTable();
  2250. VOID
  2251. CmpAddToDelayedClose(
  2252. IN PCM_KEY_CONTROL_BLOCK kcb
  2253. );
  2254. NTSTATUS
  2255. CmpAddValueToList(
  2256. IN PHHIVE Hive,
  2257. IN HCELL_INDEX ValueCell,
  2258. IN ULONG Index,
  2259. IN ULONG Type,
  2260. IN OUT PCHILD_LIST ChildList
  2261. );
  2262. NTSTATUS
  2263. CmpRemoveValueFromList(
  2264. IN PHHIVE Hive,
  2265. IN ULONG Index,
  2266. IN OUT PCHILD_LIST ChildList
  2267. );
  2268. BOOLEAN
  2269. CmpGetValueData(IN PHHIVE Hive,
  2270. IN PCM_KEY_VALUE Value,
  2271. OUT PULONG realsize,
  2272. IN OUT PVOID *Buffer,
  2273. OUT PBOOLEAN Allocated,
  2274. OUT PHCELL_INDEX CellToRelease
  2275. );
  2276. PCELL_DATA
  2277. CmpValueToData(IN PHHIVE Hive,
  2278. IN PCM_KEY_VALUE Value,
  2279. OUT PULONG realsize
  2280. );
  2281. BOOLEAN
  2282. CmpMarkValueDataDirty( IN PHHIVE Hive,
  2283. IN PCM_KEY_VALUE Value
  2284. );
  2285. NTSTATUS
  2286. CmpSetValueDataNew(
  2287. IN PHHIVE Hive,
  2288. IN PVOID Data,
  2289. IN ULONG DataSize,
  2290. IN ULONG StorageType,
  2291. IN HCELL_INDEX ValueCell,
  2292. OUT PHCELL_INDEX DataCell
  2293. );
  2294. NTSTATUS
  2295. CmpSetValueDataExisting(
  2296. IN PHHIVE Hive,
  2297. IN PVOID Data,
  2298. IN ULONG DataSize,
  2299. IN ULONG StorageType,
  2300. IN HCELL_INDEX OldDataCell
  2301. );
  2302. BOOLEAN
  2303. CmpFreeValueData(
  2304. PHHIVE Hive,
  2305. HCELL_INDEX DataCell,
  2306. ULONG DataLength
  2307. );
  2308. NTSTATUS
  2309. CmpAddSecurityCellToCache (
  2310. IN OUT PCMHIVE CmHive,
  2311. IN HCELL_INDEX SecurityCell,
  2312. IN BOOLEAN BuildUp,
  2313. IN PCM_KEY_SECURITY_CACHE SecurityCached
  2314. );
  2315. BOOLEAN
  2316. CmpFindSecurityCellCacheIndex (
  2317. IN PCMHIVE CmHive,
  2318. IN HCELL_INDEX SecurityCell,
  2319. OUT PULONG Index
  2320. );
  2321. BOOLEAN
  2322. CmpAdjustSecurityCacheSize (
  2323. IN PCMHIVE CmHive
  2324. );
  2325. VOID
  2326. CmpRemoveFromSecurityCache (
  2327. IN OUT PCMHIVE CmHive,
  2328. IN HCELL_INDEX SecurityCell
  2329. );
  2330. VOID
  2331. CmpDestroySecurityCache (
  2332. IN OUT PCMHIVE CmHive
  2333. );
  2334. VOID
  2335. CmpInitSecurityCache(
  2336. IN OUT PCMHIVE CmHive
  2337. );
  2338. BOOLEAN
  2339. CmpRebuildSecurityCache(
  2340. IN OUT PCMHIVE CmHive
  2341. );
  2342. ULONG
  2343. CmpSecConvKey(
  2344. IN ULONG DescriptorLength,
  2345. IN PULONG Descriptor
  2346. );
  2347. VOID
  2348. CmpAssignSecurityToKcb(
  2349. IN PCM_KEY_CONTROL_BLOCK Kcb,
  2350. IN HCELL_INDEX SecurityCell
  2351. );
  2352. BOOLEAN
  2353. CmpBuildSecurityCellMappingArray(
  2354. IN PCMHIVE CmHive
  2355. );
  2356. //
  2357. // new function replacing CmpWorker
  2358. //
  2359. VOID
  2360. CmpCmdHiveClose(
  2361. PCMHIVE CmHive
  2362. );
  2363. VOID
  2364. CmpCmdInit(
  2365. BOOLEAN SetupBoot
  2366. );
  2367. NTSTATUS
  2368. CmpCmdRenameHive(
  2369. PCMHIVE CmHive,
  2370. POBJECT_NAME_INFORMATION OldName,
  2371. PUNICODE_STRING NewName,
  2372. ULONG NameInfoLength
  2373. );
  2374. NTSTATUS
  2375. CmpCmdHiveOpen(
  2376. POBJECT_ATTRIBUTES FileAttributes,
  2377. PSECURITY_CLIENT_CONTEXT ImpersonationContext,
  2378. PBOOLEAN Allocate,
  2379. PBOOLEAN RegistryLockAquired,
  2380. PCMHIVE *NewHive,
  2381. ULONG CheckFlags
  2382. );
  2383. #ifdef NT_RENAME_KEY
  2384. HCELL_INDEX
  2385. CmpDuplicateIndex(
  2386. PHHIVE Hive,
  2387. HCELL_INDEX IndexCell,
  2388. ULONG StorageType
  2389. );
  2390. NTSTATUS
  2391. CmRenameKey(
  2392. IN PCM_KEY_CONTROL_BLOCK KeyControlBlock,
  2393. IN UNICODE_STRING NewKeyName
  2394. );
  2395. BOOLEAN
  2396. CmpUpdateParentForEachSon(
  2397. PHHIVE Hive,
  2398. HCELL_INDEX Parent
  2399. );
  2400. #endif //NT_RENAME_KEY
  2401. #ifdef NT_UNLOAD_KEY_EX
  2402. NTSTATUS
  2403. CmUnloadKeyEx(
  2404. IN PCM_KEY_CONTROL_BLOCK Kcb,
  2405. IN PKEVENT UserEvent
  2406. );
  2407. #endif //NT_UNLOAD_KEY_EX
  2408. VOID
  2409. CmpShutdownWorkers(
  2410. VOID
  2411. );
  2412. VOID
  2413. CmpPrefetchHiveFile(
  2414. IN PFILE_OBJECT FileObject,
  2415. IN ULONG Length
  2416. );
  2417. #ifdef CM_CHECK_FOR_ORPHANED_KCBS
  2418. VOID
  2419. CmpCheckForOrphanedKcbs(
  2420. PHHIVE Hive
  2421. );
  2422. #else
  2423. #define CmpCheckForOrphanedKcbs(Hive) //nothing
  2424. #endif //CM_CHECK_FOR_ORPHANED_KCBS
  2425. #define CM_HIVE_COMPRESS_LEVEL (25)
  2426. #define CMP_MAX_REGISTRY_DEPTH 512 // levels
  2427. typedef struct {
  2428. HCELL_INDEX Cell;
  2429. HCELL_INDEX ParentCell;
  2430. HCELL_INDEX PriorSibling;
  2431. ULONG ChildIndex;
  2432. BOOLEAN CellChecked;
  2433. } CMP_CHECK_REGISTRY_STACK_ENTRY, *PCMP_CHECK_REGISTRY_STACK_ENTRY;
  2434. #define CmIsKcbReadOnly(kcb) ((kcb)->ExtFlags & CM_KCB_READ_ONLY_KEY)
  2435. NTSTATUS
  2436. CmLockKcbForWrite(PCM_KEY_CONTROL_BLOCK KeyControlBlock);
  2437. //
  2438. // Wrapper to RtlCompareUnicodeString; uses CompareFlags to avoid upcasing names
  2439. //
  2440. #define CMP_SOURCE_UP 0x00000001
  2441. #define CMP_DEST_UP 0x00000002
  2442. LONG
  2443. CmpCompareUnicodeString(
  2444. IN PUNICODE_STRING SourceName,
  2445. IN PUNICODE_STRING DestName,
  2446. IN ULONG CompareFlags
  2447. );
  2448. LONG
  2449. CmpCompareCompressedName(
  2450. IN PUNICODE_STRING SearchName,
  2451. IN PWCHAR CompressedName,
  2452. IN ULONG NameLength,
  2453. IN ULONG CompareFlags
  2454. );
  2455. LONG
  2456. CmpCompareTwoCompressedNames(
  2457. IN PWCHAR CompressedName1,
  2458. IN ULONG NameLength1,
  2459. IN PWCHAR CompressedName2,
  2460. IN ULONG NameLength2
  2461. );
  2462. #define INIT_SYSTEMROOT_HIVEPATH L"\\SystemRoot\\System32\\Config\\"
  2463. ULONG
  2464. CmpComputeHashKey(
  2465. PUNICODE_STRING Name
  2466. );
  2467. ULONG
  2468. CmpComputeHashKeyForCompressedName(
  2469. IN PWCHAR Source,
  2470. IN ULONG SourceLength
  2471. );
  2472. //
  2473. // KCB allocator routines
  2474. //
  2475. VOID CmpInitCmPrivateAlloc();
  2476. VOID CmpDestroyCmPrivateAlloc();
  2477. PCM_KEY_CONTROL_BLOCK CmpAllocateKeyControlBlock( );
  2478. VOID CmpFreeKeyControlBlock( PCM_KEY_CONTROL_BLOCK kcb );
  2479. //
  2480. // make handles protected, so we control handle closure
  2481. //
  2482. #define CmpSetHandleProtection(Handle,Protection) \
  2483. { \
  2484. OBJECT_HANDLE_FLAG_INFORMATION Ohfi = { FALSE, \
  2485. FALSE \
  2486. }; \
  2487. Ohfi.ProtectFromClose = Protection; \
  2488. ZwSetInformationObject( Handle, \
  2489. ObjectHandleFlagInformation, \
  2490. &Ohfi, \
  2491. sizeof (OBJECT_HANDLE_FLAG_INFORMATION)); \
  2492. }
  2493. #define CmCloseHandle(Handle) \
  2494. CmpSetHandleProtection(Handle,FALSE); \
  2495. ZwClose(Handle)
  2496. VOID
  2497. CmpUpdateSystemHiveHysteresis( PHHIVE Hive,
  2498. ULONG NewLength,
  2499. ULONG OldLength
  2500. );
  2501. NTSTATUS
  2502. CmpCallCallBacks (
  2503. IN REG_NOTIFY_CLASS Type,
  2504. IN PVOID Argument
  2505. );
  2506. extern ULONG CmpCallBackCount;
  2507. #define CmAreCallbacksRegistered() ((CmpCallBackCount != 0) && (0 == ExIsResourceAcquiredShared(&CmpRegistryLock)))
  2508. #define CmPostCallbackNotification(Type,_Object_,_Status_) \
  2509. if( CmAreCallbacksRegistered() ) { \
  2510. REG_POST_OPERATION_INFORMATION PostInfo; \
  2511. PostInfo.Object = _Object_; \
  2512. PostInfo.Status = _Status_; \
  2513. CmpCallCallBacks(Type,&PostInfo); \
  2514. }
  2515. //
  2516. // Self healing hives control switch
  2517. //
  2518. extern BOOLEAN CmpSelfHeal;
  2519. extern ULONG CmpBootType;
  2520. #define CmDoSelfHeal() (CmpSelfHeal || (CmpBootType & (HBOOT_BACKUP|HBOOT_SELFHEAL)))
  2521. #define CmMarkSelfHeal(Hive) ( (Hive)->BaseBlock->BootType |= HBOOT_SELFHEAL )
  2522. /*
  2523. #ifndef _CM_LDR_
  2524. #if DBG
  2525. #define CmMarkSelfHeal(Hive) ( (Hive)->BaseBlock->BootType |= HBOOT_SELFHEAL ); \
  2526. DbgBreakPoint()
  2527. #else
  2528. #define CmMarkSelfHeal(Hive) ( (Hive)->BaseBlock->BootType |= HBOOT_SELFHEAL )
  2529. #endif
  2530. #else
  2531. #define CmMarkSelfHeal(Hive) ( (Hive)->BaseBlock->BootType |= HBOOT_SELFHEAL )
  2532. #endif
  2533. */
  2534. BOOLEAN
  2535. CmpRemoveSubKeyCellNoCellRef(
  2536. PHHIVE Hive,
  2537. HCELL_INDEX Parent,
  2538. HCELL_INDEX Child
  2539. );
  2540. VOID
  2541. CmpRaiseSelfHealWarning(
  2542. IN PUNICODE_STRING HiveName
  2543. );
  2544. VOID
  2545. CmpRaiseSelfHealWarningForSystemHives();
  2546. //
  2547. // Tracking quota leaks helpers
  2548. //
  2549. #ifdef CM_TRACK_QUOTA_LEAKS
  2550. extern FAST_MUTEX CmpQuotaLeaksMutex;
  2551. typedef struct _CM_QUOTA_LOG_ENTRY {
  2552. LIST_ENTRY ListEntry;
  2553. PVOID Stack[9];
  2554. ULONG Size;
  2555. } CM_QUOTA_LOG_ENTRY, *PCM_QUOTA_LOG_ENTRY;
  2556. extern BOOLEAN CmpTrackQuotaEnabled;
  2557. extern LIST_ENTRY CmpTrackQuotaListHead;
  2558. #define CM_TRACK_QUOTA_START() \
  2559. InitializeListHead(&CmpTrackQuotaListHead); \
  2560. CmpTrackQuotaEnabled = TRUE
  2561. #define CM_TRACK_QUOTA_STOP() CmpTrackQuotaEnabled = FALSE
  2562. #else
  2563. #define CM_TRACK_QUOTA_START() //nothing
  2564. #define CM_TRACK_QUOTA_STOP() //nothing
  2565. #endif
  2566. //
  2567. // PERF: try inline ascii upcase
  2568. //
  2569. #define CmUpcaseUnicodeChar(c) \
  2570. ( ((c) < 'a') ? (c) : ( ((c) > 'z') ? RtlUpcaseUnicodeChar(c) : ((c) - ('a'-'A')) ) )
  2571. //
  2572. // Mini NT boot indicator
  2573. //
  2574. extern BOOLEAN CmpMiniNTBoot;
  2575. extern BOOLEAN CmpShareSystemHives;
  2576. #endif //_CMP_