Source code of Windows XP (NT5)
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.

968 lines
27 KiB

  1. //depot/main/Base/ntos/config/cmworker.c#14 - integrate change 19035 (text)
  2. /*++
  3. Copyright (c) 1992 Microsoft Corporation
  4. Module Name:
  5. cmworker.c
  6. Abstract:
  7. This module contains support for the worker thread of the registry.
  8. The worker thread (actually an executive worker thread is used) is
  9. required for operations that must take place in the context of the
  10. system process. (particularly file I/O)
  11. Author:
  12. John Vert (jvert) 21-Oct-1992
  13. Revision History:
  14. --*/
  15. #include "cmp.h"
  16. extern LIST_ENTRY CmpHiveListHead;
  17. VOID
  18. CmpInitializeHiveList(
  19. VOID
  20. );
  21. //
  22. // ----- LAZY FLUSH CONTROL -----
  23. //
  24. // LAZY_FLUSH_INTERVAL_IN_SECONDS controls how many seconds will elapse
  25. // between when the hive is marked dirty and when the lazy flush worker
  26. // thread is queued to write the data to disk.
  27. //
  28. #define LAZY_FLUSH_INTERVAL_IN_SECONDS 5
  29. //
  30. // LAZY_FLUSH_TIMEOUT_IN_SECONDS controls how long the lazy flush worker
  31. // thread will wait for the registry lock before giving up and queueing
  32. // the lazy flush timer again.
  33. //
  34. #define LAZY_FLUSH_TIMEOUT_IN_SECONDS 1
  35. #define SECOND_MULT 10*1000*1000 // 10->mic, 1000->mil, 1000->second
  36. PKPROCESS CmpSystemProcess;
  37. KTIMER CmpLazyFlushTimer;
  38. KDPC CmpLazyFlushDpc;
  39. WORK_QUEUE_ITEM CmpLazyWorkItem;
  40. BOOLEAN CmpLazyFlushPending = FALSE;
  41. BOOLEAN CmpForceForceFlush = FALSE;
  42. BOOLEAN CmpHoldLazyFlush = TRUE;
  43. BOOLEAN CmpDontGrowLogFile = FALSE;
  44. extern BOOLEAN CmpNoWrite;
  45. extern BOOLEAN CmpWasSetupBoot;
  46. extern BOOLEAN HvShutdownComplete;
  47. extern BOOLEAN CmpProfileLoaded;
  48. //
  49. // Indicate whether the "disk full" popup has been triggered yet or not.
  50. //
  51. extern BOOLEAN CmpDiskFullWorkerPopupDisplayed;
  52. //
  53. // set to true if disk full when trying to save the changes made between system hive loading and registry initalization
  54. //
  55. extern BOOLEAN CmpCannotWriteConfiguration;
  56. extern UNICODE_STRING SystemHiveFullPathName;
  57. extern HIVE_LIST_ENTRY CmpMachineHiveList[];
  58. extern BOOLEAN CmpTrackHiveClose;
  59. #if DBG
  60. PKTHREAD CmpCallerThread = NULL;
  61. #endif
  62. #ifdef CMP_STATS
  63. #define KCB_STAT_INTERVAL_IN_SECONDS 120 // 2 min.
  64. extern struct {
  65. ULONG CmpMaxKcbNo;
  66. ULONG CmpKcbNo;
  67. ULONG CmpStatNo;
  68. ULONG CmpNtCreateKeyNo;
  69. ULONG CmpNtDeleteKeyNo;
  70. ULONG CmpNtDeleteValueKeyNo;
  71. ULONG CmpNtEnumerateKeyNo;
  72. ULONG CmpNtEnumerateValueKeyNo;
  73. ULONG CmpNtFlushKeyNo;
  74. ULONG CmpNtNotifyChangeMultipleKeysNo;
  75. ULONG CmpNtOpenKeyNo;
  76. ULONG CmpNtQueryKeyNo;
  77. ULONG CmpNtQueryValueKeyNo;
  78. ULONG CmpNtQueryMultipleValueKeyNo;
  79. ULONG CmpNtRestoreKeyNo;
  80. ULONG CmpNtSaveKeyNo;
  81. ULONG CmpNtSaveMergedKeysNo;
  82. ULONG CmpNtSetValueKeyNo;
  83. ULONG CmpNtLoadKeyNo;
  84. ULONG CmpNtUnloadKeyNo;
  85. ULONG CmpNtSetInformationKeyNo;
  86. ULONG CmpNtReplaceKeyNo;
  87. ULONG CmpNtQueryOpenSubKeysNo;
  88. } CmpStatsDebug;
  89. KTIMER CmpKcbStatTimer;
  90. KDPC CmpKcbStatDpc;
  91. KSPIN_LOCK CmpKcbStatLock;
  92. BOOLEAN CmpKcbStatShutdown;
  93. VOID
  94. CmpKcbStatDpcRoutine(
  95. IN PKDPC Dpc,
  96. IN PVOID DeferredContext,
  97. IN PVOID SystemArgument1,
  98. IN PVOID SystemArgument2
  99. );
  100. extern ULONG CmpNtFakeCreate;
  101. struct {
  102. ULONG BasicInformation;
  103. UINT64 BasicInformationTimeCounter;
  104. UINT64 BasicInformationTimeElapsed;
  105. ULONG NodeInformation;
  106. UINT64 NodeInformationTimeCounter;
  107. UINT64 NodeInformationTimeElapsed;
  108. ULONG FullInformation;
  109. UINT64 FullInformationTimeCounter;
  110. UINT64 FullInformationTimeElapsed;
  111. ULONG EnumerateKeyBasicInformation;
  112. UINT64 EnumerateKeyBasicInformationTimeCounter;
  113. UINT64 EnumerateKeyBasicInformationTimeElapsed;
  114. ULONG EnumerateKeyNodeInformation;
  115. UINT64 EnumerateKeyNodeInformationTimeCounter;
  116. UINT64 EnumerateKeyNodeInformationTimeElapsed;
  117. ULONG EnumerateKeyFullInformation;
  118. UINT64 EnumerateKeyFullInformationTimeCounter;
  119. UINT64 EnumerateKeyFullInformationTimeElapsed;
  120. } CmpQueryKeyDataDebug = {0};
  121. #endif
  122. VOID
  123. CmpLazyFlushWorker(
  124. IN PVOID Parameter
  125. );
  126. VOID
  127. CmpLazyFlushDpcRoutine(
  128. IN PKDPC Dpc,
  129. IN PVOID DeferredContext,
  130. IN PVOID SystemArgument1,
  131. IN PVOID SystemArgument2
  132. );
  133. VOID
  134. CmpDiskFullWarningWorker(
  135. IN PVOID WorkItem
  136. );
  137. VOID
  138. CmpDiskFullWarning(
  139. VOID
  140. );
  141. #ifdef ALLOC_PRAGMA
  142. #pragma alloc_text(PAGE,CmpLazyFlush)
  143. #pragma alloc_text(PAGE,CmpLazyFlushWorker)
  144. #pragma alloc_text(PAGE,CmpDiskFullWarningWorker)
  145. #pragma alloc_text(PAGE,CmpDiskFullWarning)
  146. #pragma alloc_text(PAGE,CmpCmdHiveClose)
  147. #pragma alloc_text(PAGE,CmpCmdInit)
  148. #pragma alloc_text(PAGE,CmpCmdRenameHive)
  149. #pragma alloc_text(PAGE,CmpCmdHiveOpen)
  150. #pragma alloc_text(PAGE,CmSetLazyFlushState)
  151. #ifndef CMP_STATS
  152. #pragma alloc_text(PAGE,CmpShutdownWorkers)
  153. #endif
  154. #endif
  155. VOID
  156. CmpCmdHiveClose(
  157. PCMHIVE CmHive
  158. )
  159. /*++
  160. Routine Description:
  161. Closes all the file handles for the specified hive
  162. Arguments:
  163. CmHive - the hive to close
  164. Return Value:
  165. none
  166. --*/
  167. {
  168. ULONG i;
  169. IO_STATUS_BLOCK IoStatusBlock;
  170. FILE_BASIC_INFORMATION BasicInfo;
  171. LARGE_INTEGER systemtime;
  172. BOOLEAN oldFlag;
  173. PAGED_CODE();
  174. //
  175. // disable hard error popups, to workaround ObAttachProcessStack
  176. //
  177. oldFlag = IoSetThreadHardErrorMode(FALSE);
  178. //
  179. // Close the files associated with this hive.
  180. //
  181. ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
  182. for (i=0; i<HFILE_TYPE_MAX; i++) {
  183. if (CmHive->FileHandles[i] != NULL) {
  184. //
  185. // attempt to set change the last write time (profile guys are relying on it!)
  186. //
  187. if( i == HFILE_TYPE_PRIMARY ) {
  188. if( NT_SUCCESS(ZwQueryInformationFile(
  189. CmHive->FileHandles[i],
  190. &IoStatusBlock,
  191. &BasicInfo,
  192. sizeof(BasicInfo),
  193. FileBasicInformation) ) ) {
  194. KeQuerySystemTime(&systemtime);
  195. BasicInfo.LastWriteTime = systemtime;
  196. BasicInfo.LastAccessTime = systemtime;
  197. ZwSetInformationFile(
  198. CmHive->FileHandles[i],
  199. &IoStatusBlock,
  200. &BasicInfo,
  201. sizeof(BasicInfo),
  202. FileBasicInformation
  203. );
  204. }
  205. CmpTrackHiveClose = TRUE;
  206. CmCloseHandle(CmHive->FileHandles[i]);
  207. CmpTrackHiveClose = FALSE;
  208. } else {
  209. CmCloseHandle(CmHive->FileHandles[i]);
  210. }
  211. CmHive->FileHandles[i] = NULL;
  212. }
  213. }
  214. //
  215. // restore hard error popups mode
  216. //
  217. IoSetThreadHardErrorMode(oldFlag);
  218. }
  219. VOID
  220. CmpCmdInit(
  221. BOOLEAN SetupBoot
  222. )
  223. /*++
  224. Routine Description:
  225. Initializes cm globals and flushes all hives to the disk.
  226. Arguments:
  227. SetupBoot - whether the boot is from setup or a regular boot
  228. Return Value:
  229. none
  230. --*/
  231. {
  232. PAGED_CODE();
  233. ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
  234. //
  235. // Initialize lazy flush timer and DPC
  236. //
  237. KeInitializeDpc(&CmpLazyFlushDpc,
  238. CmpLazyFlushDpcRoutine,
  239. NULL);
  240. KeInitializeTimer(&CmpLazyFlushTimer);
  241. ExInitializeWorkItem(&CmpLazyWorkItem, CmpLazyFlushWorker, NULL);
  242. #ifdef CMP_STATS
  243. KeInitializeDpc(&CmpKcbStatDpc,
  244. CmpKcbStatDpcRoutine,
  245. NULL);
  246. KeInitializeTimer(&CmpKcbStatTimer);
  247. KeInitializeSpinLock(&CmpKcbStatLock);
  248. CmpKcbStatShutdown = FALSE;
  249. #endif
  250. CmpNoWrite = CmpMiniNTBoot;
  251. CmpWasSetupBoot = SetupBoot;
  252. if (SetupBoot == FALSE) {
  253. CmpInitializeHiveList();
  254. }
  255. //
  256. // Since we are done with initialization,
  257. // disable the hive sharing
  258. //
  259. if (CmpMiniNTBoot && CmpShareSystemHives) {
  260. CmpShareSystemHives = FALSE;
  261. }
  262. #ifdef CMP_STATS
  263. CmpKcbStat();
  264. #endif
  265. }
  266. NTSTATUS
  267. CmpCmdRenameHive(
  268. PCMHIVE CmHive,
  269. POBJECT_NAME_INFORMATION OldName,
  270. PUNICODE_STRING NewName,
  271. ULONG NameInfoLength
  272. )
  273. /*++
  274. Routine Description:
  275. rename a cmhive's primary handle
  276. replaces old REG_CMD_RENAME_HIVE worker case
  277. Arguments:
  278. CmHive - hive to rename
  279. OldName - old name information
  280. NewName - the new name for the file
  281. NameInfoLength - sizeof name information structure
  282. Return Value:
  283. <TBD>
  284. --*/
  285. {
  286. NTSTATUS Status;
  287. HANDLE Handle;
  288. PFILE_RENAME_INFORMATION RenameInfo;
  289. IO_STATUS_BLOCK IoStatusBlock;
  290. PAGED_CODE();
  291. ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
  292. //
  293. // Rename a CmHive's primary handle
  294. //
  295. Handle = CmHive->FileHandles[HFILE_TYPE_PRIMARY];
  296. if (OldName != NULL) {
  297. ASSERT_PASSIVE_LEVEL();
  298. Status = ZwQueryObject(Handle,
  299. ObjectNameInformation,
  300. OldName,
  301. NameInfoLength,
  302. &NameInfoLength);
  303. if (!NT_SUCCESS(Status)) {
  304. return Status;
  305. }
  306. }
  307. RenameInfo = ExAllocatePool(PagedPool,
  308. sizeof(FILE_RENAME_INFORMATION) + NewName->Length);
  309. if (RenameInfo == NULL) {
  310. return STATUS_INSUFFICIENT_RESOURCES;
  311. }
  312. RenameInfo->ReplaceIfExists = FALSE;
  313. RenameInfo->RootDirectory = NULL;
  314. RenameInfo->FileNameLength = NewName->Length;
  315. RtlCopyMemory(RenameInfo->FileName,
  316. NewName->Buffer,
  317. NewName->Length);
  318. Status = ZwSetInformationFile(Handle,
  319. &IoStatusBlock,
  320. (PVOID)RenameInfo,
  321. sizeof(FILE_RENAME_INFORMATION) +
  322. NewName->Length,
  323. FileRenameInformation);
  324. ExFreePool(RenameInfo);
  325. return Status;
  326. }
  327. NTSTATUS
  328. CmpCmdHiveOpen(
  329. POBJECT_ATTRIBUTES FileAttributes,
  330. PSECURITY_CLIENT_CONTEXT ImpersonationContext,
  331. PBOOLEAN Allocate,
  332. PBOOLEAN RegistryLockAquired, // needed to avoid recursivity deadlock with ZwCreate calls calling back into registry
  333. PCMHIVE *NewHive,
  334. ULONG CheckFlags
  335. )
  336. /*++
  337. Routine Description:
  338. replaces old REG_CMD_HIVE_OPEN worker case
  339. Arguments:
  340. Return Value:
  341. <TBD>
  342. --*/
  343. {
  344. PUNICODE_STRING FileName;
  345. NTSTATUS Status;
  346. HANDLE NullHandle;
  347. PAGED_CODE();
  348. //
  349. // Open the file.
  350. //
  351. FileName = FileAttributes->ObjectName;
  352. Status = CmpInitHiveFromFile(FileName,
  353. 0,
  354. NewHive,
  355. Allocate,
  356. RegistryLockAquired,
  357. CheckFlags);
  358. //
  359. // NT Servers will return STATUS_ACCESS_DENIED. Netware 3.1x
  360. // servers could return any of the other error codes if the GUEST
  361. // account is disabled.
  362. //
  363. if (((Status == STATUS_ACCESS_DENIED) ||
  364. (Status == STATUS_NO_SUCH_USER) ||
  365. (Status == STATUS_WRONG_PASSWORD) ||
  366. (Status == STATUS_ACCOUNT_EXPIRED) ||
  367. (Status == STATUS_ACCOUNT_DISABLED) ||
  368. (Status == STATUS_ACCOUNT_RESTRICTION)) &&
  369. (ImpersonationContext != NULL)) {
  370. //
  371. // Impersonate the caller and try it again. This
  372. // lets us open hives on a remote machine.
  373. //
  374. Status = SeImpersonateClientEx(
  375. ImpersonationContext,
  376. NULL);
  377. if ( NT_SUCCESS( Status ) ) {
  378. Status = CmpInitHiveFromFile(FileName,
  379. 0,
  380. NewHive,
  381. Allocate,
  382. RegistryLockAquired,
  383. CheckFlags);
  384. NullHandle = NULL;
  385. PsRevertToSelf();
  386. }
  387. }
  388. return Status;
  389. }
  390. VOID
  391. CmpLazyFlush(
  392. VOID
  393. )
  394. /*++
  395. Routine Description:
  396. This routine resets the registry timer to go off at a specified interval
  397. in the future (LAZY_FLUSH_INTERVAL_IN_SECONDS).
  398. Arguments:
  399. None
  400. Return Value:
  401. None.
  402. --*/
  403. {
  404. LARGE_INTEGER DueTime;
  405. PAGED_CODE();
  406. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_IO,"CmpLazyFlush: setting lazy flush timer\n"));
  407. if ((!CmpNoWrite) && (!CmpHoldLazyFlush)) {
  408. DueTime.QuadPart = Int32x32To64(LAZY_FLUSH_INTERVAL_IN_SECONDS,
  409. - SECOND_MULT);
  410. //
  411. // Indicate relative time
  412. //
  413. KeSetTimer(&CmpLazyFlushTimer,
  414. DueTime,
  415. &CmpLazyFlushDpc);
  416. }
  417. }
  418. VOID
  419. CmpLazyFlushDpcRoutine(
  420. IN PKDPC Dpc,
  421. IN PVOID DeferredContext,
  422. IN PVOID SystemArgument1,
  423. IN PVOID SystemArgument2
  424. )
  425. /*++
  426. Routine Description:
  427. This is the DPC routine triggered by the lazy flush timer. All it does
  428. is queue a work item to an executive worker thread. The work item will
  429. do the actual lazy flush to disk.
  430. Arguments:
  431. Dpc - Supplies a pointer to the DPC object.
  432. DeferredContext - not used
  433. SystemArgument1 - not used
  434. SystemArgument2 - not used
  435. Return Value:
  436. None.
  437. --*/
  438. {
  439. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_IO,"CmpLazyFlushDpc: queuing lazy flush work item\n"));
  440. if ((!CmpLazyFlushPending) && (!CmpHoldLazyFlush)) {
  441. CmpLazyFlushPending = TRUE;
  442. ExQueueWorkItem(&CmpLazyWorkItem, DelayedWorkQueue);
  443. }
  444. }
  445. VOID
  446. CmpLazyFlushWorker(
  447. IN PVOID Parameter
  448. )
  449. /*++
  450. Routine Description:
  451. Worker routine called to do a lazy flush. Called by an executive worker
  452. thread in the system process.
  453. Arguments:
  454. Parameter - not used.
  455. Return Value:
  456. None.
  457. --*/
  458. {
  459. BOOLEAN Result = TRUE;
  460. BOOLEAN ForceFlush;
  461. PAGED_CODE();
  462. if( CmpHoldLazyFlush ) {
  463. //
  464. // lazy flush mode is disabled
  465. //
  466. return;
  467. }
  468. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_IO,"CmpLazyFlushWorker: flushing hives\n"));
  469. ForceFlush = CmpForceForceFlush;
  470. if(ForceFlush == TRUE) {
  471. //
  472. // something bad happened and we may need to fix hive's use count
  473. //
  474. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL,"CmpLazyFlushWorker: Force Flush - getting the reglock exclusive\n"));
  475. CmpLockRegistryExclusive();
  476. } else {
  477. CmpLockRegistry();
  478. ENTER_FLUSH_MODE();
  479. }
  480. if (!HvShutdownComplete) {
  481. //
  482. // this call will set CmpForceForceFlush to the right value
  483. //
  484. Result = CmpDoFlushAll(ForceFlush);
  485. } else {
  486. CmpForceForceFlush = FALSE;
  487. }
  488. if( ForceFlush == FALSE ) {
  489. EXIT_FLUSH_MODE();
  490. }
  491. CmpLazyFlushPending = FALSE;
  492. CmpUnlockRegistry();
  493. if( CmpCannotWriteConfiguration ) {
  494. //
  495. // Disk full; system hive has not been saved at initialization
  496. //
  497. if(Result) {
  498. //
  499. // All hives were saved; No need for disk full warning anymore
  500. //
  501. CmpCannotWriteConfiguration = FALSE;
  502. } else {
  503. //
  504. // Issue another hard error (if not already displayed) and postpone a lazy flush operation
  505. //
  506. CmpDiskFullWarning();
  507. CmpLazyFlush();
  508. }
  509. }
  510. }
  511. VOID
  512. CmpDiskFullWarningWorker(
  513. IN PVOID WorkItem
  514. )
  515. /*++
  516. Routine Description:
  517. Displays hard error popup that indicates the disk is full.
  518. Arguments:
  519. WorkItem - Supplies pointer to the work item. This routine will
  520. free the work item.
  521. Return Value:
  522. None.
  523. --*/
  524. {
  525. NTSTATUS Status;
  526. ULONG Response;
  527. ExFreePool(WorkItem);
  528. Status = ExRaiseHardError(STATUS_DISK_FULL,
  529. 0,
  530. 0,
  531. NULL,
  532. OptionOk,
  533. &Response);
  534. }
  535. VOID
  536. CmpDiskFullWarning(
  537. VOID
  538. )
  539. /*++
  540. Routine Description:
  541. Raises a hard error of type STATUS_DISK_FULL if wasn't already raised
  542. Arguments:
  543. None
  544. Return Value:
  545. None
  546. --*/
  547. {
  548. PWORK_QUEUE_ITEM WorkItem;
  549. if( (!CmpDiskFullWorkerPopupDisplayed) && (CmpCannotWriteConfiguration) && (ExReadyForErrors) && (CmpProfileLoaded) ) {
  550. //
  551. // Queue work item to display popup
  552. //
  553. WorkItem = ExAllocatePool(NonPagedPool, sizeof(WORK_QUEUE_ITEM));
  554. if (WorkItem != NULL) {
  555. CmpDiskFullWorkerPopupDisplayed = TRUE;
  556. ExInitializeWorkItem(WorkItem,
  557. CmpDiskFullWarningWorker,
  558. WorkItem);
  559. ExQueueWorkItem(WorkItem, DelayedWorkQueue);
  560. }
  561. }
  562. }
  563. VOID
  564. CmpShutdownWorkers(
  565. VOID
  566. )
  567. /*++
  568. Routine Description:
  569. Shuts down the lazy flush worker (by killing the timer)
  570. Arguments:
  571. None
  572. Return Value:
  573. None
  574. --*/
  575. {
  576. PAGED_CODE();
  577. KeCancelTimer(&CmpLazyFlushTimer);
  578. #ifdef CMP_STATS
  579. {
  580. KIRQL OldIrql;
  581. KeAcquireSpinLock(&CmpKcbStatLock, &OldIrql);
  582. CmpKcbStatShutdown = TRUE;
  583. KeCancelTimer(&CmpKcbStatTimer);
  584. KeReleaseSpinLock(&CmpKcbStatLock, OldIrql);
  585. }
  586. #endif
  587. }
  588. VOID
  589. CmSetLazyFlushState(BOOLEAN Enable)
  590. /*++
  591. Routine Description:
  592. Enables/Disables the lazy flusher; Designed for the standby/resume case, where
  593. we we don't want the lazy flush to fire off, blocking registry writers until the
  594. disk wakes up.
  595. Arguments:
  596. Enable - TRUE = enable; FALSE = disable
  597. Return Value:
  598. None.
  599. --*/
  600. {
  601. PAGED_CODE();
  602. CmpDontGrowLogFile = CmpHoldLazyFlush = !Enable;
  603. }
  604. #ifdef CMP_STATS
  605. VOID
  606. CmpKcbStat(
  607. VOID
  608. )
  609. /*++
  610. Routine Description:
  611. This routine resets the KcbStat timer to go off at a specified interval
  612. in the future
  613. Arguments:
  614. None
  615. Return Value:
  616. None.
  617. --*/
  618. {
  619. LARGE_INTEGER DueTime;
  620. KIRQL OldIrql;
  621. DueTime.QuadPart = Int32x32To64(KCB_STAT_INTERVAL_IN_SECONDS,
  622. - SECOND_MULT);
  623. //
  624. // Indicate relative time
  625. //
  626. KeAcquireSpinLock(&CmpKcbStatLock, &OldIrql);
  627. if (! CmpKcbStatShutdown) {
  628. KeSetTimer(&CmpKcbStatTimer,
  629. DueTime,
  630. &CmpKcbStatDpc);
  631. }
  632. KeReleaseSpinLock(&CmpKcbStatLock, OldIrql);
  633. }
  634. VOID
  635. CmpKcbStatDpcRoutine(
  636. IN PKDPC Dpc,
  637. IN PVOID DeferredContext,
  638. IN PVOID SystemArgument1,
  639. IN PVOID SystemArgument2
  640. )
  641. /*++
  642. Routine Description:
  643. Dumps the kcb stats in the debugger and then reschedules another
  644. Dpc in the future
  645. Arguments:
  646. Dpc - Supplies a pointer to the DPC object.
  647. DeferredContext - not used
  648. SystemArgument1 - not used
  649. SystemArgument2 - not used
  650. Return Value:
  651. None.
  652. --*/
  653. {
  654. #ifndef _CM_LDR_
  655. DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL,"\n*********************************************************************\n");
  656. DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL, "* Stat No %8lu KcbNo = %8lu [MaxKcbNo = %8lu] *\n",++CmpStatsDebug.CmpStatNo,CmpStatsDebug.CmpKcbNo,CmpStatsDebug.CmpMaxKcbNo);
  657. DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL, "*********************************************************************\n");
  658. DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL, "* *\n");
  659. DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL, "* [Nt]API [No. Of]Calls *\n");
  660. DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL, "*-------------------------------------------------------------------*\n");
  661. DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL, "* NtCreateKey %8lu Opens = %8lu *\n",CmpStatsDebug.CmpNtCreateKeyNo,CmpNtFakeCreate);
  662. DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL, "* NtOpenKey %8lu *\n",CmpStatsDebug.CmpNtOpenKeyNo);
  663. DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL, "* NtEnumerateKey %8lu *\n",CmpStatsDebug.CmpNtEnumerateKeyNo);
  664. DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL, "* NtQueryKey %8lu *\n",CmpStatsDebug.CmpNtQueryKeyNo);
  665. DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL, "* NtDeleteKey %8lu *\n",CmpStatsDebug.CmpNtDeleteKeyNo);
  666. DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL, "* NtSetInformationKey %8lu *\n",CmpStatsDebug.CmpNtSetInformationKeyNo);
  667. DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL, "*-------------------------------------------------------------------*\n");
  668. DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL, "* NtSetValueKey %8lu *\n",CmpStatsDebug.CmpNtSetValueKeyNo);
  669. DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL, "* NtEnumerateValueKey %8lu *\n",CmpStatsDebug.CmpNtEnumerateValueKeyNo);
  670. DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL, "* NtQueryValueKey %8lu *\n",CmpStatsDebug.CmpNtQueryValueKeyNo);
  671. DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL, "* NtQueryMultipleValueKey %8lu *\n",CmpStatsDebug.CmpNtQueryMultipleValueKeyNo);
  672. DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL, "* NtDeleteValueKey %8lu *\n",CmpStatsDebug.CmpNtDeleteValueKeyNo);
  673. DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL, "*-------------------------------------------------------------------*\n");
  674. DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL, "* NtFlushKey %8lu *\n",CmpStatsDebug.CmpNtFlushKeyNo);
  675. DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL, "* NtLoadKey %8lu *\n",CmpStatsDebug.CmpNtLoadKeyNo);
  676. DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL, "* NtUnloadKey %8lu *\n",CmpStatsDebug.CmpNtUnloadKeyNo);
  677. DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL, "* NtSaveKey %8lu *\n",CmpStatsDebug.CmpNtSaveKeyNo);
  678. DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL, "* NtSaveMergedKeys %8lu *\n",CmpStatsDebug.CmpNtSaveMergedKeysNo);
  679. DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL, "* NtRestoreKey %8lu *\n",CmpStatsDebug.CmpNtRestoreKeyNo);
  680. DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL, "* NtReplaceKey %8lu *\n",CmpStatsDebug.CmpNtReplaceKeyNo);
  681. DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL, "*-------------------------------------------------------------------*\n");
  682. DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL, "* NtNotifyChgMultplKeys %8lu *\n",CmpStatsDebug.CmpNtNotifyChangeMultipleKeysNo);
  683. DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL, "* NtQueryOpenSubKeys %8lu *\n",CmpStatsDebug.CmpNtQueryOpenSubKeysNo);
  684. DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL, "*-------------------------------------------------------------------*\n");
  685. DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL, "* [No.Of]Calls [Time] *\n");
  686. DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL, "*-------------------------------------------------------------------*\n");
  687. DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL, "* NtQueryKey(KeyBasicInformation) %8lu %8lu *\n",
  688. CmpQueryKeyDataDebug.BasicInformation,
  689. (ULONG)(CmpQueryKeyDataDebug.BasicInformationTimeCounter?CmpQueryKeyDataDebug.BasicInformationTimeElapsed/CmpQueryKeyDataDebug.BasicInformationTimeCounter:0));
  690. CmpQueryKeyDataDebug.BasicInformationTimeCounter = 0;
  691. CmpQueryKeyDataDebug.BasicInformationTimeElapsed = 0;
  692. DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL, "* NtQueryKey(KeyNodeInformation ) %8lu %8lu *\n",
  693. CmpQueryKeyDataDebug.NodeInformation,
  694. (ULONG)(CmpQueryKeyDataDebug.NodeInformationTimeCounter?CmpQueryKeyDataDebug.NodeInformationTimeElapsed/CmpQueryKeyDataDebug.NodeInformationTimeCounter:0));
  695. CmpQueryKeyDataDebug.NodeInformationTimeCounter = 0;
  696. CmpQueryKeyDataDebug.NodeInformationTimeElapsed = 0;
  697. DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL, "* NtQueryKey(KeyFullInformation ) %8lu %8lu *\n",
  698. CmpQueryKeyDataDebug.FullInformation,
  699. (ULONG)(CmpQueryKeyDataDebug.FullInformationTimeCounter?CmpQueryKeyDataDebug.FullInformationTimeElapsed/CmpQueryKeyDataDebug.FullInformationTimeCounter:0));
  700. CmpQueryKeyDataDebug.FullInformationTimeCounter = 0;
  701. CmpQueryKeyDataDebug.FullInformationTimeElapsed = 0;
  702. DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL, "* NtEnumerateKey(KeyBasicInformation) %8lu %8lu *\n",
  703. CmpQueryKeyDataDebug.EnumerateKeyBasicInformation,
  704. (ULONG)(CmpQueryKeyDataDebug.EnumerateKeyBasicInformationTimeCounter?CmpQueryKeyDataDebug.EnumerateKeyBasicInformationTimeElapsed/CmpQueryKeyDataDebug.EnumerateKeyBasicInformationTimeCounter:0));
  705. CmpQueryKeyDataDebug.EnumerateKeyBasicInformationTimeCounter = 0;
  706. CmpQueryKeyDataDebug.EnumerateKeyBasicInformationTimeElapsed = 0;
  707. DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL, "* NtEnumerateKey(KeyNodeInformation ) %8lu %8lu *\n",
  708. CmpQueryKeyDataDebug.EnumerateKeyNodeInformation,
  709. (ULONG)(CmpQueryKeyDataDebug.EnumerateKeyNodeInformationTimeCounter?CmpQueryKeyDataDebug.EnumerateKeyNodeInformationTimeElapsed/CmpQueryKeyDataDebug.EnumerateKeyNodeInformationTimeCounter:0));
  710. CmpQueryKeyDataDebug.EnumerateKeyNodeInformationTimeCounter = 0;
  711. CmpQueryKeyDataDebug.EnumerateKeyNodeInformationTimeElapsed = 0;
  712. DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL, "* NtEnumerateKey(KeyFullInformation ) %8lu %8lu *\n",
  713. CmpQueryKeyDataDebug.EnumerateKeyFullInformation,
  714. (ULONG)(CmpQueryKeyDataDebug.EnumerateKeyFullInformationTimeCounter?CmpQueryKeyDataDebug.EnumerateKeyFullInformationTimeElapsed/CmpQueryKeyDataDebug.EnumerateKeyFullInformationTimeCounter:0));
  715. CmpQueryKeyDataDebug.EnumerateKeyFullInformationTimeCounter = 0;
  716. CmpQueryKeyDataDebug.EnumerateKeyFullInformationTimeElapsed = 0;
  717. DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL, "*********************************************************************\n\n");
  718. //
  719. // reschedule
  720. //
  721. #endif //_CM_LDR_
  722. CmpKcbStat();
  723. }
  724. #endif