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.

1900 lines
52 KiB

  1. //
  2. // Systrack - System resource tracking
  3. // Copyright (c) Microsoft Corporation, 1998
  4. //
  5. //
  6. // module: systrack.cxx
  7. // author: silviuc
  8. // created: Mon Nov 09 12:20:41 1998
  9. //
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <stdarg.h>
  13. #include <time.h>
  14. extern "C" {
  15. #include <nt.h>
  16. #include <ntrtl.h>
  17. #include <nturtl.h>
  18. }
  19. #include <windows.h>
  20. #include <common.ver>
  21. #define VERSION_DEFINITION_MODULE
  22. #include "version.hxx"
  23. #define DEBUGINFO_DEFINITION_MODULE
  24. #include "debug.hxx"
  25. #include "pooltag.hxx"
  26. #include "process.hxx"
  27. #include "memory.hxx"
  28. #include "systrack.hxx"
  29. #define BUFFER_SIZE_STEP ( 128 * 1024 )
  30. void PrintCurrentTime ();
  31. void PrintSystemBasicInformation ();
  32. void PrintSystemPerformanceInformation ();
  33. void PrintSystemProcessInformation (BOOL ShortDump);
  34. void PrintSystemPoolDetailedInformation ();
  35. void PrintSystemPoolTagInformation ();
  36. void PrintProcessStackInformation ();
  37. VOID
  38. GetProcessStackInfo (
  39. PSYSTEM_PROCESS_INFORMATION Info,
  40. PSIZE_T MaxSize,
  41. PSIZE_T TotalSize,
  42. PBOOL ErrorsFound
  43. );
  44. //
  45. // Functions:
  46. //
  47. // Help
  48. //
  49. // Decription:
  50. //
  51. // Prints help information to the stdout. Exits with status code 1.
  52. //
  53. static void
  54. Help ()
  55. {
  56. static char help_text [] =
  57. " \n"
  58. "systrack - System resource tracking --" BUILD_MACHINE_TAG "\n"
  59. VER_LEGALCOPYRIGHT_STR "\n"
  60. " \n"
  61. " systrack [INFO-CLASS] \n"
  62. " \n"
  63. " <> : if no class specified, print process information. \n"
  64. " /system : print system basic information. \n"
  65. " /process : print process information. \n"
  66. " /stack : print stack usage information for all processes. \n"
  67. " /performance: print performance information. \n"
  68. " /pool : print pool tag information (pool tags should be enabled). \n"
  69. " /pooldetailed : print pool information (only checked builds). \n"
  70. " /all : print everything. \n"
  71. " \n"
  72. " /trackpool PERIOD DELTA \n"
  73. " /trackpooltag PERIOD PATTERN DELTA \n"
  74. " /trackprocess PERIOD HANDLE THREAD WSET VSIZE PFILE \n"
  75. " /trackprocessid PERIOD ID HANDLE THREAD WSET VSIZE PFILE \n"
  76. " /trackavailablepages PERIOD DELTA \n"
  77. " /trackcommittedpages PERIOD DELTA \n"
  78. " /trackcommitlimit PERIOD DELTA \n"
  79. " /trackpagefaultcount PERIOD DELTA \n"
  80. " /tracksystemcalls PERIOD DELTA \n"
  81. " /tracktotalsystemdriverpages PERIOD DELTA \n"
  82. " /tracktotalsystemcodepages PERIOD DELTA \n"
  83. " \n"
  84. " /help TOPIC detailed help for the topic (e.g. process, trackpool, \n"
  85. " trackprocessid, etc.). \n"
  86. " ?, /? help \n"
  87. " -version version information \n"
  88. " \n"
  89. "Examples: \n"
  90. " \n"
  91. " systrack /trackpool 1000 10000 \n"
  92. " \n"
  93. " Polls every 1000ms the kernel pools and will print every pool tag \n"
  94. " whose pool usage increased by more than 10000 bytes. \n"
  95. " \n"
  96. " systrack /trackpooltag 1000 \"G*\" 10000 \n"
  97. " \n"
  98. " Polls every 1000ms the kernel pools and will print every pool tag \n"
  99. " that matches the pattern if its pool usage increased by more \n"
  100. " than 10000 bytes. \n"
  101. " \n"
  102. " systrack /trackprocess 1000 5 5 1000000 1000000 1000000 \n"
  103. " \n"
  104. " Polls every 1000ms the processes running and prints every process \n"
  105. " whose handle count increased by more than 5 or thread count \n"
  106. " increased by more than 5 or working set size increased by more \n"
  107. " than 1000000 or virtual size increased by more than 1000000 or \n"
  108. " pagefile usage increased by more than 1000000. \n"
  109. " \n"
  110. " systrack /trackprocessid 1000 136 5 5 1000000 1000000 1000000 \n"
  111. " \n"
  112. " Polls every 1000ms the process with id 136 and reports if the \n"
  113. " handle count increased by more than 5 or thread count \n"
  114. " increased by more than 5 or working set size increased by more \n"
  115. " than 1000000 or virtual size increased by more than 1000000 or \n"
  116. " pagefile usage increased by more than 1000000. \n"
  117. " \n"
  118. " \n";
  119. printf (help_text);
  120. exit (1);
  121. }
  122. //
  123. // Functions:
  124. //
  125. // DetailedHelp
  126. //
  127. // Decription:
  128. //
  129. // Prints help information to the stdout for a specific topic.
  130. // Exits with status code 1.
  131. //
  132. static void
  133. DetailedHelp (
  134. char * Topic)
  135. {
  136. char * help_text;
  137. if (_stricmp (Topic, "system") == 0) {
  138. help_text =
  139. "systrack /system \n"
  140. " \n"
  141. " \n";
  142. }
  143. else if (_stricmp (Topic, "process") == 0) {
  144. help_text =
  145. "systrack /proces \n"
  146. " \n"
  147. " \n";
  148. }
  149. else if (_stricmp (Topic, "performance") == 0) {
  150. help_text =
  151. "systrack /performance \n"
  152. " \n"
  153. " \n";
  154. }
  155. else if (_stricmp (Topic, "trackprocess") == 0) {
  156. help_text =
  157. "systrack /trackprocess \n"
  158. " \n"
  159. " \n";
  160. }
  161. else if (_stricmp (Topic, "trackprocessid") == 0) {
  162. help_text =
  163. "systrack /system \n"
  164. " \n"
  165. " \n";
  166. }
  167. else if (_stricmp (Topic, "trackpool") == 0) {
  168. help_text =
  169. "systrack /trackpool \n"
  170. " \n"
  171. " \n";
  172. }
  173. else if (_stricmp (Topic, "trackpooltag") == 0) {
  174. help_text =
  175. "systrack /trackpooltag \n"
  176. " \n"
  177. " \n";
  178. }
  179. else {
  180. printf ("Unknown help topic %s \n", Topic);
  181. exit (1);
  182. }
  183. printf (help_text, VERSION_INFORMATION_VERSION);
  184. exit (1);
  185. }
  186. //
  187. // Function:
  188. //
  189. // main
  190. //
  191. // Description:
  192. //
  193. // ?, -?, /? - print help information.
  194. // -version - print version information
  195. //
  196. // default (system, process, pool)
  197. // /process
  198. // /stack
  199. // /system
  200. // /performance
  201. // /pool
  202. // /pooldetailed
  203. //
  204. //
  205. void _cdecl
  206. main (int argc, char *argv[])
  207. {
  208. if (argc == 2 && _stricmp (argv[1], "?") == 0)
  209. Help ();
  210. else if (argc == 2 && _stricmp (argv[1], "/?") == 0)
  211. Help ();
  212. else if (argc == 2 && _stricmp (argv[1], "-?") == 0)
  213. Help ();
  214. else if (argc == 2 && _stricmp (argv[1], "-h") == 0)
  215. Help ();
  216. else if (argc == 2 && _stricmp (argv[1], "/h") == 0)
  217. Help ();
  218. // if (argc == 3 && _stricmp (argv[1], "/help") == 0)
  219. // DetailedHelp (argv[2]);
  220. if (argc == 2 && _stricmp (argv[1], "-version") == 0)
  221. dump_version_information ();
  222. try
  223. {
  224. //
  225. // Here comes the code ...
  226. //
  227. PrintCurrentTime ();
  228. if (argc == 1)
  229. {
  230. //
  231. // <> default options
  232. //
  233. // PrintSystemBasicInformation ();
  234. PrintSystemProcessInformation (TRUE);
  235. // PrintSystemPoolTagInformation ();
  236. }
  237. else if (argc == 2 && _stricmp (argv[1], "/stack") == 0)
  238. {
  239. //
  240. // /stack option
  241. //
  242. PrintProcessStackInformation ();
  243. }
  244. else if (argc == 2 && _stricmp (argv[1], "/all") == 0)
  245. {
  246. //
  247. // /all option
  248. //
  249. PrintSystemBasicInformation ();
  250. PrintSystemPerformanceInformation ();
  251. PrintSystemProcessInformation (FALSE);
  252. PrintSystemPoolTagInformation ();
  253. PrintSystemPoolDetailedInformation ();
  254. }
  255. else if (argc == 4 && _stricmp (argv[1], "/trackpool") == 0)
  256. {
  257. //
  258. // /trackpool PERIOD DELTA
  259. //
  260. ULONG Delta;
  261. ULONG Period;
  262. Period = atoi (argv[2]);
  263. Delta = atoi (argv[3]);
  264. if (Delta == 0)
  265. Delta = 8192;
  266. if (Period == 0)
  267. Period = 1000;
  268. SystemPoolTrack (Period, Delta);
  269. }
  270. else if (argc == 5 && _stricmp (argv[1], "/trackpooltag") == 0)
  271. {
  272. //
  273. // /trackpooltag PERIOD PATTERN DELTA
  274. //
  275. ULONG Delta;
  276. ULONG Period;
  277. UCHAR * Pattern;
  278. Period = atoi (argv[2]);
  279. Pattern = (UCHAR *)(argv[3]);
  280. Delta = atoi (argv[4]);
  281. if (Delta == 0)
  282. Delta = 8192;
  283. if (Period == 0)
  284. Period = 1000;
  285. SystemPoolTagTrack (Period, Pattern, Delta);
  286. }
  287. else if (argc == 8 && _stricmp (argv[1], "/trackprocess") == 0)
  288. {
  289. //
  290. // /trackprocess PERIOD HANDLES THREADS WSET VSIZE PFILE
  291. //
  292. ULONG DeltaHandles;
  293. ULONG DeltaThreads;
  294. ULONG DeltaWorkingSet;
  295. SIZE_T DeltaVirtualSize;
  296. SIZE_T DeltaPagefileUsage;
  297. ULONG Period;
  298. Period = atoi (argv[2]);
  299. DeltaHandles = atoi (argv[3]);
  300. DeltaThreads = atoi (argv[4]);
  301. DeltaWorkingSet = atoi (argv[5]);
  302. DeltaVirtualSize = atoi (argv[6]);
  303. DeltaPagefileUsage = atoi (argv[7]);
  304. if (Period == 0)
  305. Period = 1000;
  306. if (DeltaHandles == 0)
  307. DeltaHandles = 32;
  308. if (DeltaThreads == 0)
  309. DeltaThreads = 8;
  310. if (DeltaWorkingSet == 0)
  311. DeltaWorkingSet = 0x100000;
  312. if (DeltaVirtualSize == 0)
  313. DeltaVirtualSize = 0x100000;
  314. if (DeltaPagefileUsage == 0)
  315. DeltaPagefileUsage = 0x100000;
  316. SystemProcessTrack (Period,
  317. DeltaHandles, DeltaThreads, DeltaWorkingSet,
  318. DeltaVirtualSize, DeltaPagefileUsage);
  319. }
  320. else if (argc == 9 && _stricmp (argv[1], "/trackprocessid") == 0)
  321. {
  322. //
  323. // /trackprocessid PERIOD ID HANDLES THREADS WSET VSIZE PFILE
  324. //
  325. ULONG ProcessId;
  326. ULONG DeltaHandles;
  327. ULONG DeltaThreads;
  328. ULONG DeltaWorkingSet;
  329. SIZE_T DeltaVirtualSize;
  330. SIZE_T DeltaPagefileUsage;
  331. ULONG Period;
  332. Period = atoi (argv[2]);
  333. ProcessId = atoi (argv[3]);
  334. DeltaHandles = atoi (argv[4]);
  335. DeltaThreads = atoi (argv[5]);
  336. DeltaWorkingSet = atoi (argv[6]);
  337. DeltaVirtualSize = atoi (argv[7]);
  338. DeltaPagefileUsage = atoi (argv[8]);
  339. if (Period == 0)
  340. Period = 1000;
  341. if (ProcessId == 0) {
  342. printf ("Bad process id %s\n", argv[3]);
  343. exit (1);
  344. }
  345. if (DeltaHandles == 0)
  346. DeltaHandles = 32;
  347. if (DeltaThreads == 0)
  348. DeltaThreads = 8;
  349. if (DeltaWorkingSet == 0)
  350. DeltaWorkingSet = 0x100000;
  351. if (DeltaVirtualSize == 0)
  352. DeltaVirtualSize = 0x100000;
  353. if (DeltaPagefileUsage == 0)
  354. DeltaPagefileUsage = 0x100000;
  355. SystemProcessIdTrack (Period, ProcessId,
  356. DeltaHandles, DeltaThreads, DeltaWorkingSet,
  357. DeltaVirtualSize, DeltaPagefileUsage);
  358. }
  359. else if (argc == 4 && _stricmp (argv[1], "/trackavailablepages") == 0)
  360. {
  361. //
  362. // /trackavailablepages PERIOD DELTA
  363. //
  364. LONG Delta;
  365. ULONG Period;
  366. Period = atoi (argv[2]);
  367. Delta = atoi (argv[3]);
  368. if (Period == 0)
  369. Period = 1000;
  370. if (Delta == 0)
  371. Delta = 100;
  372. //
  373. // We track decreasing values therefore delta should be negative.
  374. //
  375. TrackPerformanceCounter (argv[1], TRACK_AVAILABLE_PAGES, Period, -Delta);
  376. }
  377. else if (argc == 4 && _stricmp (argv[1], "/trackcommittedpages") == 0)
  378. {
  379. //
  380. // /trackcommittedpages PERIOD DELTA
  381. //
  382. LONG Delta;
  383. ULONG Period;
  384. Period = atoi (argv[2]);
  385. Delta = atoi (argv[3]);
  386. if (Period == 0)
  387. Period = 1000;
  388. if (Delta == 0)
  389. Delta = 100;
  390. //
  391. // We track increasing values therefore delta should be positive.
  392. //
  393. TrackPerformanceCounter (argv[1], TRACK_COMMITTED_PAGES, Period, Delta);
  394. }
  395. else if (argc == 4 && _stricmp (argv[1], "/trackcommitlimit") == 0)
  396. {
  397. //
  398. // /trackcommitlimit PERIOD DELTA
  399. //
  400. LONG Delta;
  401. ULONG Period;
  402. Period = atoi (argv[2]);
  403. Delta = atoi (argv[3]);
  404. if (Period == 0)
  405. Period = 1000;
  406. if (Delta == 0)
  407. Delta = 100;
  408. //
  409. // We track increasing values therefore delta should be positive.
  410. //
  411. TrackPerformanceCounter (argv[1], TRACK_COMMIT_LIMIT, Period, Delta);
  412. }
  413. else if (argc == 4 && _stricmp (argv[1], "/trackpagefaultcount") == 0)
  414. {
  415. //
  416. // /trackpagefaultcount PERIOD DELTA
  417. //
  418. LONG Delta;
  419. ULONG Period;
  420. Period = atoi (argv[2]);
  421. Delta = atoi (argv[3]);
  422. if (Period == 0)
  423. Period = 1000;
  424. if (Delta == 0)
  425. Delta = 100;
  426. //
  427. // We track increasing values therefore delta should be positive.
  428. //
  429. TrackPerformanceCounter (argv[1], TRACK_PAGE_FAULT_COUNT, Period, Delta);
  430. }
  431. else if (argc == 4 && _stricmp (argv[1], "/tracksystemcalls") == 0)
  432. {
  433. //
  434. // /tracksystemcalls PERIOD DELTA
  435. //
  436. LONG Delta;
  437. ULONG Period;
  438. Period = atoi (argv[2]);
  439. Delta = atoi (argv[3]);
  440. if (Period == 0)
  441. Period = 1000;
  442. if (Delta == 0)
  443. Delta = 100;
  444. //
  445. // We track increasing values therefore delta should be positive.
  446. //
  447. TrackPerformanceCounter (argv[1], TRACK_SYSTEM_CALLS, Period, Delta);
  448. }
  449. else if (argc == 4 && _stricmp (argv[1], "/tracktotalsystemdriverpages") == 0)
  450. {
  451. //
  452. // /tracktotalsystemdriverpages PERIOD DELTA
  453. //
  454. LONG Delta;
  455. ULONG Period;
  456. Period = atoi (argv[2]);
  457. Delta = atoi (argv[3]);
  458. if (Period == 0)
  459. Period = 1000;
  460. if (Delta == 0)
  461. Delta = 100;
  462. //
  463. // We track increasing values therefore delta should be positive.
  464. //
  465. TrackPerformanceCounter (argv[1], TRACK_TOTAL_SYSTEM_DRIVER_PAGES, Period, Delta);
  466. }
  467. else if (argc == 4 && _stricmp (argv[1], "/tracktotalsystemcodepages") == 0)
  468. {
  469. //
  470. // /tracktotalsystemcodepages PERIOD DELTA
  471. //
  472. LONG Delta;
  473. ULONG Period;
  474. Period = atoi (argv[2]);
  475. Delta = atoi (argv[3]);
  476. if (Period == 0)
  477. Period = 1000;
  478. if (Delta == 0)
  479. Delta = 100;
  480. //
  481. // We track increasing values therefore delta should be positive.
  482. //
  483. TrackPerformanceCounter (argv[1], TRACK_TOTAL_SYSTEM_CODE_PAGES, Period, Delta);
  484. }
  485. else
  486. {
  487. for (int Count = 1; Count < argc; Count++)
  488. {
  489. if (_stricmp (argv[Count], "/system") == 0)
  490. PrintSystemBasicInformation ();
  491. else if (_stricmp (argv[Count], "/performance") == 0)
  492. PrintSystemPerformanceInformation ();
  493. else if (_stricmp (argv[Count], "/process") == 0)
  494. PrintSystemProcessInformation (TRUE);
  495. else if (_stricmp (argv[Count], "/pool") == 0)
  496. PrintSystemPoolTagInformation ();
  497. else if (_stricmp (argv[Count], "/pooldetailed") == 0)
  498. PrintSystemPoolDetailedInformation ();
  499. else
  500. Help ();
  501. }
  502. }
  503. }
  504. catch (...)
  505. {
  506. printf ("unexpected exception ...\n");
  507. fflush (stdout);
  508. exit (1);
  509. }
  510. exit (0);
  511. }
  512. //
  513. // Function:
  514. //
  515. // PrintCurrentTime
  516. //
  517. // Description:
  518. //
  519. // Prints current time, machine name, etc.
  520. //
  521. //
  522. void PrintCurrentTime ()
  523. {
  524. TCHAR MachineName [32];
  525. LPCTSTR TimeString;
  526. time_t Time;
  527. DWORD Result;
  528. if (GetEnvironmentVariable (TEXT("COMPUTERNAME"), MachineName, sizeof MachineName) == 0)
  529. strcpy (MachineName, "unknown");
  530. time (&Time);
  531. TimeString = asctime (localtime (&Time));
  532. printf ("Systrack - System resource tracking, %s\n", VERSION_INFORMATION_VERSION);
  533. printf ("Machine: %s\n", MachineName);
  534. printf ("Time: %s\n", TimeString);
  535. fflush( stdout );
  536. }
  537. //////////////////////////////////////////////////////////////////////
  538. //////////////////////////////////////////////////////////////////////
  539. //////////////////////////////////////////////////////////////////////
  540. //
  541. // Macro:
  542. //
  543. // _dump_, _dump_quad_ (object, field)
  544. //
  545. // Description:
  546. //
  547. // Handy macros to dump the fields of a structure.
  548. //
  549. #define _dump_(object,field) printf ("%-30s %08X (%u)\n", #field, (ULONG)(object->field), (ULONG)(object->field))
  550. #define _dump_quad_(object,field) printf ("%-30s %I64X (%I64u)\n", #field, (object->field.QuadPart), (object->field.QuadPart))
  551. //
  552. // Local:
  553. //
  554. // InfoBuffer
  555. //
  556. // Description:
  557. //
  558. // Large enough structure to hold theinformation returned by
  559. // NtQuerySystemInformation. I've opted for this solution because
  560. // systrack can run under heavy stress conditions and we do not
  561. // to allocate big chunks of memory dynamically in such a situation.
  562. //
  563. // Note. If we decide to multithread the application we will need a
  564. // critical section to protect the information buffer.
  565. // CRITICAL_SECTION InfoBufferLock;
  566. //
  567. static TCHAR InfoBuffer [0x40000];
  568. //
  569. // Local:
  570. //
  571. // PoolTagInformationBuffer
  572. //
  573. // Description:
  574. //
  575. // Buffer for NtQuerySystemInformation( SystemPoolTagInformation ).
  576. // Its size is grown by QueryPoolTagInformationIterative if necessary.
  577. // The length of the buffer is held in PoolTagInformationBufferLength.
  578. //
  579. static TCHAR *PoolTagInformationBuffer = NULL;
  580. //
  581. // Local:
  582. //
  583. // PoolTagInformationBufferLength
  584. //
  585. // Description:
  586. //
  587. // The current length of PoolTagInformationBuffer.
  588. //
  589. size_t PoolTagInformationBufferLength = 0;
  590. //
  591. // Function:
  592. //
  593. // QueryPoolTagInformationIterative
  594. //
  595. // Description:
  596. //
  597. // ARGUMENTS:
  598. //
  599. // CurrentBuffer - a pointer to the buffer currently used for
  600. // NtQuerySystemInformation( SystemPoolTagInformation ).
  601. // It will be allocated if NULL or its size grown
  602. // if necessary.
  603. //
  604. // CurrentBufferSize - a pointer to a variable that holds the current
  605. // size of the buffer.
  606. //
  607. // RETURNS:
  608. //
  609. // NTSTATUS returned by NtQuerySystemInformation or
  610. // STATUS_INSUFFICIENT_RESOURCES if the buffer must grow and the
  611. // heap allocation for it fails.
  612. //
  613. NTSTATUS
  614. QueryPoolTagInformationIterative(
  615. TCHAR **CurrentBuffer,
  616. size_t *CurrentBufferSize
  617. )
  618. {
  619. size_t NewBufferSize;
  620. NTSTATUS ReturnedStatus = STATUS_SUCCESS;
  621. if( CurrentBuffer == NULL || CurrentBufferSize == NULL ) {
  622. return STATUS_INVALID_PARAMETER;
  623. }
  624. if( *CurrentBufferSize == 0 || *CurrentBuffer == NULL ) {
  625. //
  626. // there is no buffer allocated yet
  627. //
  628. NewBufferSize = sizeof( TCHAR ) * BUFFER_SIZE_STEP;
  629. *CurrentBuffer = (TCHAR *) malloc( NewBufferSize );
  630. if( *CurrentBuffer != NULL ) {
  631. *CurrentBufferSize = NewBufferSize;
  632. } else {
  633. //
  634. // insufficient memory
  635. //
  636. ReturnedStatus = STATUS_INSUFFICIENT_RESOURCES;
  637. }
  638. }
  639. //
  640. // iterate by buffer's size
  641. //
  642. while( *CurrentBuffer != NULL ) {
  643. ReturnedStatus = NtQuerySystemInformation (
  644. SystemPoolTagInformation,
  645. *CurrentBuffer,
  646. (ULONG)*CurrentBufferSize,
  647. NULL );
  648. if( ! NT_SUCCESS(ReturnedStatus) ) {
  649. //
  650. // free the current buffer
  651. //
  652. free( *CurrentBuffer );
  653. *CurrentBuffer = NULL;
  654. if (ReturnedStatus == STATUS_INFO_LENGTH_MISMATCH) {
  655. //
  656. // try with a greater buffer size
  657. //
  658. NewBufferSize = *CurrentBufferSize + BUFFER_SIZE_STEP;
  659. *CurrentBuffer = (TCHAR *) malloc( NewBufferSize );
  660. if( *CurrentBuffer != NULL ) {
  661. //
  662. // allocated new buffer
  663. //
  664. *CurrentBufferSize = NewBufferSize;
  665. } else {
  666. //
  667. // insufficient memory
  668. //
  669. ReturnedStatus = STATUS_INSUFFICIENT_RESOURCES;
  670. *CurrentBufferSize = 0;
  671. }
  672. } else {
  673. *CurrentBufferSize = 0;
  674. }
  675. } else {
  676. //
  677. // NtQuerySystemInformation returned success
  678. //
  679. break;
  680. }
  681. }
  682. return ReturnedStatus;
  683. }
  684. //
  685. // Function:
  686. //
  687. // QuerySystemPoolTagInformation
  688. //
  689. // Description:
  690. //
  691. // Fills InfoBuffer with SystemPoolTagInformation and returns
  692. // a pointer to it.
  693. //
  694. PVOID
  695. QuerySystemPoolTagInformation ()
  696. {
  697. NTSTATUS Status;
  698. ULONG RealLength;
  699. //
  700. // SystemPoolTagInformation
  701. //
  702. Status = QueryPoolTagInformationIterative(
  703. &PoolTagInformationBuffer,
  704. &PoolTagInformationBufferLength );
  705. if (! NT_SUCCESS(Status))
  706. printf ("NtQuerySystemInformation(pooltag): error %08X\n",
  707. Status);
  708. return NT_SUCCESS(Status) ? PoolTagInformationBuffer : NULL;
  709. }
  710. //
  711. // Function:
  712. //
  713. // QuerySystemProcessInformation
  714. //
  715. // Description:
  716. //
  717. // Fills InfoBuffer with SystemProcessInformation and returns
  718. // a pointer to it.
  719. //
  720. PVOID
  721. QuerySystemProcessInformation ()
  722. {
  723. NTSTATUS Status;
  724. ULONG RealLength;
  725. //
  726. // SystemProcessInformation
  727. //
  728. Status = NtQuerySystemInformation (
  729. SystemProcessInformation,
  730. InfoBuffer,
  731. sizeof InfoBuffer,
  732. &RealLength);
  733. if (! NT_SUCCESS(Status))
  734. printf ("NtQuerySystemInformation(process): error %08X\n",
  735. Status);
  736. return NT_SUCCESS(Status) ? InfoBuffer : NULL;
  737. }
  738. //
  739. // Function:
  740. //
  741. // QuerySystemPerformanceInformation
  742. //
  743. // Description:
  744. //
  745. // Fills InfoBuffer with SystemPerformanceInformation and returns
  746. // a pointer to it.
  747. //
  748. PVOID
  749. QuerySystemPerformanceInformation ()
  750. {
  751. NTSTATUS Status;
  752. ULONG RealLength;
  753. //
  754. // SystemPerformanceInformation
  755. //
  756. Status = NtQuerySystemInformation (
  757. SystemPerformanceInformation,
  758. InfoBuffer,
  759. sizeof InfoBuffer,
  760. &RealLength);
  761. if (! NT_SUCCESS(Status))
  762. printf ("NtQuerySystemInformation(performance): error %08X\n",
  763. Status);
  764. return NT_SUCCESS(Status) ? InfoBuffer : NULL;
  765. }
  766. //
  767. // Function:
  768. //
  769. // PrintSystemBasicInformation
  770. //
  771. // Description:
  772. //
  773. // Prints SystemPerformanceInformation.
  774. //
  775. //
  776. void PrintSystemBasicInformation ()
  777. {
  778. NTSTATUS Status;
  779. ULONG RealLength;
  780. printf ("\n- - - - - - - - - - - - - - - - - - - - - - - - - - - ");
  781. printf ("- - - - - - - - - - - - - - - - - - - - - - - - - - - \n");
  782. printf ("System basic information \n");
  783. printf ("- - - - - - - - - - - - - - - - - - - - - - - - - - - ");
  784. printf ("- - - - - - - - - - - - - - - - - - - - - - - - - - - \n");
  785. fflush( stdout );
  786. //
  787. // SystemBasicInformation
  788. //
  789. Status = NtQuerySystemInformation (
  790. SystemBasicInformation,
  791. InfoBuffer,
  792. sizeof (SYSTEM_BASIC_INFORMATION),
  793. &RealLength);
  794. if (! NT_SUCCESS(Status))
  795. {
  796. printf ("NtQuerySystemInformation(Basic): error %08X\n", Status);
  797. return;
  798. }
  799. {
  800. PSYSTEM_BASIC_INFORMATION Info = (PSYSTEM_BASIC_INFORMATION)InfoBuffer;
  801. _dump_(Info, PageSize);
  802. _dump_(Info, NumberOfPhysicalPages);
  803. _dump_(Info, LowestPhysicalPageNumber);
  804. _dump_(Info, HighestPhysicalPageNumber);
  805. _dump_(Info, AllocationGranularity);
  806. _dump_(Info, MinimumUserModeAddress);
  807. _dump_(Info, MaximumUserModeAddress);
  808. _dump_(Info, ActiveProcessorsAffinityMask);
  809. _dump_(Info, NumberOfProcessors);
  810. }
  811. }
  812. //
  813. // Function:
  814. //
  815. // PrintSystemPerformanceInformation
  816. //
  817. // Description:
  818. //
  819. // Prints systemPerformanceInformation.
  820. //
  821. void PrintSystemPerformanceInformation ()
  822. {
  823. NTSTATUS Status;
  824. ULONG RealLength;
  825. printf ("\n- - - - - - - - - - - - - - - - - - - - - - - - - - - ");
  826. printf ("- - - - - - - - - - - - - - - - - - - - - - - - - - - \n");
  827. printf ("System performance information \n");
  828. printf ("- - - - - - - - - - - - - - - - - - - - - - - - - - - ");
  829. printf ("- - - - - - - - - - - - - - - - - - - - - - - - - - - \n");
  830. fflush( stdout );
  831. //
  832. // SystemPerformanceInformation
  833. //
  834. Status = NtQuerySystemInformation (
  835. SystemPerformanceInformation,
  836. InfoBuffer,
  837. sizeof (SYSTEM_PERFORMANCE_INFORMATION),
  838. &RealLength);
  839. if (! NT_SUCCESS(Status))
  840. {
  841. printf ("NtQuerySystemInformation(Performance): error %08X\n", Status);
  842. return;
  843. }
  844. {
  845. PSYSTEM_PERFORMANCE_INFORMATION Info = (PSYSTEM_PERFORMANCE_INFORMATION)InfoBuffer;
  846. _dump_quad_ (Info, IdleProcessTime);
  847. _dump_quad_ (Info, IoReadTransferCount);
  848. _dump_quad_ (Info, IoWriteTransferCount);
  849. _dump_quad_ (Info, IoOtherTransferCount);
  850. _dump_ (Info, IoReadOperationCount);
  851. _dump_ (Info, IoWriteOperationCount);
  852. _dump_ (Info, IoOtherOperationCount);
  853. _dump_ (Info, AvailablePages);
  854. _dump_ (Info, CommittedPages);
  855. _dump_ (Info, CommitLimit);
  856. _dump_ (Info, PeakCommitment);
  857. _dump_ (Info, PageFaultCount);
  858. _dump_ (Info, CopyOnWriteCount);
  859. _dump_ (Info, TransitionCount);
  860. _dump_ (Info, CacheTransitionCount);
  861. _dump_ (Info, DemandZeroCount);
  862. _dump_ (Info, PageReadCount);
  863. _dump_ (Info, PageReadIoCount);
  864. _dump_ (Info, CacheReadCount);
  865. _dump_ (Info, CacheIoCount);
  866. _dump_ (Info, DirtyPagesWriteCount);
  867. _dump_ (Info, DirtyWriteIoCount);
  868. _dump_ (Info, MappedPagesWriteCount);
  869. _dump_ (Info, MappedWriteIoCount);
  870. _dump_ (Info, PagedPoolPages);
  871. _dump_ (Info, NonPagedPoolPages);
  872. _dump_ (Info, PagedPoolAllocs);
  873. _dump_ (Info, PagedPoolFrees);
  874. _dump_ (Info, NonPagedPoolAllocs);
  875. _dump_ (Info, NonPagedPoolFrees);
  876. _dump_ (Info, FreeSystemPtes);
  877. _dump_ (Info, ResidentSystemCodePage);
  878. _dump_ (Info, TotalSystemDriverPages);
  879. _dump_ (Info, TotalSystemCodePages);
  880. _dump_ (Info, NonPagedPoolLookasideHits);
  881. _dump_ (Info, PagedPoolLookasideHits);
  882. #if 0
  883. _dump_ (Info, Spare3Count);
  884. #endif
  885. _dump_ (Info, ResidentSystemCachePage);
  886. _dump_ (Info, ResidentPagedPoolPage);
  887. _dump_ (Info, ResidentSystemDriverPage);
  888. _dump_ (Info, CcFastReadNoWait);
  889. _dump_ (Info, CcFastReadWait);
  890. _dump_ (Info, CcFastReadResourceMiss);
  891. _dump_ (Info, CcFastReadNotPossible);
  892. _dump_ (Info, CcFastMdlReadNoWait);
  893. _dump_ (Info, CcFastMdlReadWait);
  894. _dump_ (Info, CcFastMdlReadResourceMiss);
  895. _dump_ (Info, CcFastMdlReadNotPossible);
  896. _dump_ (Info, CcMapDataNoWait);
  897. _dump_ (Info, CcMapDataWait);
  898. _dump_ (Info, CcMapDataNoWaitMiss);
  899. _dump_ (Info, CcMapDataWaitMiss);
  900. _dump_ (Info, CcPinMappedDataCount);
  901. _dump_ (Info, CcPinReadNoWait);
  902. _dump_ (Info, CcPinReadWait);
  903. _dump_ (Info, CcPinReadNoWaitMiss);
  904. _dump_ (Info, CcPinReadWaitMiss);
  905. _dump_ (Info, CcCopyReadNoWait);
  906. _dump_ (Info, CcCopyReadWait);
  907. _dump_ (Info, CcCopyReadNoWaitMiss);
  908. _dump_ (Info, CcCopyReadWaitMiss);
  909. _dump_ (Info, CcMdlReadNoWait);
  910. _dump_ (Info, CcMdlReadWait);
  911. _dump_ (Info, CcMdlReadNoWaitMiss);
  912. _dump_ (Info, CcMdlReadWaitMiss);
  913. _dump_ (Info, CcReadAheadIos);
  914. _dump_ (Info, CcLazyWriteIos);
  915. _dump_ (Info, CcLazyWritePages);
  916. _dump_ (Info, CcDataFlushes);
  917. _dump_ (Info, CcDataPages);
  918. _dump_ (Info, ContextSwitches);
  919. _dump_ (Info, FirstLevelTbFills);
  920. _dump_ (Info, SecondLevelTbFills);
  921. _dump_ (Info, SystemCalls);
  922. }
  923. }
  924. //
  925. // Function:
  926. //
  927. // PrintSystemProcessInformation
  928. //
  929. // Description:
  930. //
  931. // Prints SystemProcessInformation.
  932. //
  933. // Details:
  934. //
  935. // These are the fields of a SYSTEM_PROCESS_INFORMATION structure:
  936. //
  937. // ULONG NextEntryOffset;
  938. // ULONG NumberOfThreads;
  939. // LARGE_INTEGER SpareLi1;
  940. // LARGE_INTEGER SpareLi2;
  941. // LARGE_INTEGER SpareLi3;
  942. // LARGE_INTEGER CreateTime;
  943. // LARGE_INTEGER UserTime;
  944. // LARGE_INTEGER KernelTime;
  945. // UNICODE_STRING ImageName;
  946. // KPRIORITY BasePriority;
  947. // HANDLE UniqueProcessId;
  948. // HANDLE InheritedFromUniqueProcessId;
  949. // ULONG HandleCount;
  950. // ULONG SessionId;
  951. // ULONG SpareUl3;
  952. // SIZE_T PeakVirtualSize;
  953. // SIZE_T VirtualSize;
  954. // ULONG PageFaultCount;
  955. // ULONG PeakWorkingSetSize;
  956. // ULONG WorkingSetSize;
  957. // SIZE_T QuotaPeakPagedPoolUsage;
  958. // SIZE_T QuotaPagedPoolUsage;
  959. // SIZE_T QuotaPeakNonPagedPoolUsage;
  960. // SIZE_T QuotaNonPagedPoolUsage;
  961. // SIZE_T PagefileUsage;
  962. // SIZE_T PeakPagefileUsage;
  963. // SIZE_T PrivatePageCount;
  964. // LARGE_INTEGER ReadOperationCount;
  965. // LARGE_INTEGER WriteOperationCount;
  966. // LARGE_INTEGER OtherOperationCount;
  967. // LARGE_INTEGER ReadTransferCount;
  968. // LARGE_INTEGER WriteTransferCount;
  969. // LARGE_INTEGER OtherTransferCount;
  970. //
  971. void PrintSystemProcessInformation (
  972. BOOL ShortDump)
  973. {
  974. NTSTATUS Status;
  975. ULONG RealLength;
  976. SYSTEM_BASIC_INFORMATION SysInfo;
  977. BOOL FinishNextTime = FALSE;
  978. if (ShortDump)
  979. {
  980. printf ("\n- - - - - - - - - - - - - - - - - - - - - - - - - - - ");
  981. printf ("- - - - - - - - - - - - - - - - - - - - - -\n");
  982. printf ("System process information \n");
  983. printf ("- - - - - - - - - - - - - - - - - - - - - - - - - - - ");
  984. printf ("- - - - - - - - - - - - - - - - - - - - - -\n");
  985. }
  986. else
  987. {
  988. printf ("\n- - - - - - - - - - - - - - - - - - - - - - - - - - - ");
  989. printf ("- - - - - - - - - - - - - - - - - - - - - - - - - - - \n");
  990. printf ("System process information \n");
  991. printf ("- - - - - - - - - - - - - - - - - - - - - - - - - - - ");
  992. printf ("- - - - - - - - - - - - - - - - - - - - - - - - - - - \n");
  993. }
  994. fflush( stdout );
  995. //
  996. // SystemBasicInformation
  997. //
  998. Status = NtQuerySystemInformation (
  999. SystemBasicInformation,
  1000. &SysInfo,
  1001. sizeof (SysInfo),
  1002. &RealLength);
  1003. if (! NT_SUCCESS(Status))
  1004. {
  1005. printf ("NtQuerySystemInformation(Basic): error %08X\n", Status);
  1006. return;
  1007. }
  1008. //
  1009. // SystemProcessInformation
  1010. //
  1011. Status = NtQuerySystemInformation (
  1012. SystemProcessInformation,
  1013. InfoBuffer,
  1014. sizeof InfoBuffer,
  1015. &RealLength);
  1016. if (! NT_SUCCESS(Status))
  1017. {
  1018. printf ("NtQuerySystemInformation(Process): error %08X\n", Status);
  1019. return;
  1020. }
  1021. {
  1022. PSYSTEM_PROCESS_INFORMATION Info = (PSYSTEM_PROCESS_INFORMATION)InfoBuffer;
  1023. if (ShortDump)
  1024. {
  1025. printf ("%-15s %-5s %-5s %-4s %-5s %-8s %-8s %-5s %-5s %-6s %-5s %-5s %-5s\n",
  1026. "Process",
  1027. "Id",
  1028. "Sess",
  1029. "Pri",
  1030. "Thrds",
  1031. "Faults",
  1032. "Handles",
  1033. "Utime",
  1034. "Ktime",
  1035. "Wset",
  1036. "Vsize",
  1037. "Pfile",
  1038. "I/O");
  1039. printf ("%-15s %-5s %-5s %-4s %-5s %-8s %-8s %-5s %-5s %-6s %-5s %-5s %-5s\n",
  1040. "",
  1041. "",
  1042. "",
  1043. "",
  1044. "",
  1045. "",
  1046. "",
  1047. "%",
  1048. "%",
  1049. "pages",
  1050. "Mb",
  1051. "Mb",
  1052. "x1000");
  1053. }
  1054. else
  1055. {
  1056. printf ("%-15s %-5s %-5s %-4s %-5s %-8s %-8s %-5s %-5s %-6s %-5s %-5s %-5s %-5s %-5s\n",
  1057. "Process",
  1058. "Id",
  1059. "Sess",
  1060. "Pri",
  1061. "Thrds",
  1062. "Faults",
  1063. "Handles",
  1064. "Utime",
  1065. "Ktime",
  1066. "Wset",
  1067. "Vsize",
  1068. "Pfile",
  1069. "I/O",
  1070. "Npool",
  1071. "Ppool");
  1072. printf ("%-15s %-5s %-5s %-4s %-5s %-8s %-8s %-5s %-5s %-6s %-5s %-5s %-5s %-5s %-5s\n",
  1073. "",
  1074. "",
  1075. "",
  1076. "",
  1077. "",
  1078. "",
  1079. "",
  1080. "%",
  1081. "%",
  1082. "pages",
  1083. "Mb",
  1084. "Mb",
  1085. "x1000",
  1086. "Mb",
  1087. "Mb");
  1088. }
  1089. if (ShortDump)
  1090. {
  1091. printf ("- - - - - - - - - - - - - - - - - - - - - - - - - - - ");
  1092. printf ("- - - - - - - - - - - - - - - - - - - - - -\n");
  1093. }
  1094. else
  1095. {
  1096. printf ("- - - - - - - - - - - - - - - - - - - - - - - - - - - ");
  1097. printf ("- - - - - - - - - - - - - - - - - - - - - - - - - - - \n");
  1098. }
  1099. fflush( stdout );
  1100. for (FinishNextTime = FALSE ;
  1101. FinishNextTime == FALSE;
  1102. Info = (PSYSTEM_PROCESS_INFORMATION)((ULONG_PTR)Info + Info->NextEntryOffset))
  1103. {
  1104. if (Info->NextEntryOffset == 0)
  1105. FinishNextTime = TRUE;
  1106. //
  1107. // User time vs Kernel time.
  1108. //
  1109. ULONG UserPercent, KernelPercent;
  1110. UserPercent = (ULONG)((Info->UserTime.QuadPart) * 100
  1111. / (Info->UserTime.QuadPart + Info->KernelTime.QuadPart));
  1112. KernelPercent = 100 - UserPercent;
  1113. //
  1114. // I/O total count.
  1115. //
  1116. LARGE_INTEGER IoTotalCount;
  1117. IoTotalCount.QuadPart = Info->ReadOperationCount.QuadPart
  1118. + Info->WriteOperationCount.QuadPart
  1119. + Info->OtherOperationCount.QuadPart;
  1120. IoTotalCount.QuadPart /= 1000;
  1121. //
  1122. // Image name (special case the idle process).
  1123. //
  1124. if (Info->ImageName.Buffer == NULL)
  1125. printf ("%-15s ", "Idle");
  1126. else
  1127. printf ("%-15ws ", Info->ImageName.Buffer);
  1128. //
  1129. // Print the stuff.
  1130. //
  1131. if (ShortDump)
  1132. {
  1133. printf ("%-5I64u %-5u %-4u %-5u %-8u %-8u %-5u %-5u %-6u %-5u %-5u %-5I64u\n",
  1134. (ULONG64)((ULONG_PTR)(Info->UniqueProcessId)),
  1135. Info->SessionId,
  1136. Info->BasePriority,
  1137. Info->NumberOfThreads,
  1138. Info->PageFaultCount,
  1139. Info->HandleCount,
  1140. UserPercent,
  1141. KernelPercent,
  1142. Info->WorkingSetSize / SysInfo.PageSize,
  1143. Info->VirtualSize / 0x100000,
  1144. Info->PagefileUsage / 0x100000,
  1145. (IoTotalCount.QuadPart));
  1146. }
  1147. else
  1148. {
  1149. printf ("%-5I64u %-5u %-4u %-5u %-8u %-8u %-5u %-5u %-6u %-5u %-5u %-5I64u %-5u %-5u\n",
  1150. (ULONG64)((ULONG_PTR)(Info->UniqueProcessId)),
  1151. Info->SessionId,
  1152. Info->BasePriority,
  1153. Info->NumberOfThreads,
  1154. Info->PageFaultCount,
  1155. Info->HandleCount,
  1156. UserPercent,
  1157. KernelPercent,
  1158. Info->WorkingSetSize / SysInfo.PageSize,
  1159. Info->VirtualSize / 0x100000,
  1160. Info->PagefileUsage / 0x100000,
  1161. (IoTotalCount.QuadPart),
  1162. Info->QuotaNonPagedPoolUsage / 0x100000,
  1163. Info->QuotaPagedPoolUsage / 0x100000);
  1164. }
  1165. fflush( stdout );
  1166. }
  1167. }
  1168. }
  1169. //
  1170. // Function:
  1171. //
  1172. // PrintSystemPoolDetailedInformation
  1173. //
  1174. // Description:
  1175. //
  1176. // Prints systemNonPagedPoolInformation and systemPagedPoolInformation.
  1177. // The function returns something meaningful only on checked builds.
  1178. //
  1179. // typedef struct _SYSTEM_POOL_ENTRY {
  1180. // BOOLEAN Allocated;
  1181. // BOOLEAN Spare0;
  1182. // USHORT AllocatorBackTraceIndex;
  1183. // ULONG Size;
  1184. // union {
  1185. // UCHAR Tag[4];
  1186. // ULONG TagUlong;
  1187. // PVOID ProcessChargedQuota;
  1188. // };
  1189. // } SYSTEM_POOL_ENTRY, *PSYSTEM_POOL_ENTRY;
  1190. //
  1191. // typedef struct _SYSTEM_POOL_INFORMATION {
  1192. // SIZE_T TotalSize;
  1193. // PVOID FirstEntry;
  1194. // USHORT EntryOverhead;
  1195. // BOOLEAN PoolTagPresent;
  1196. // BOOLEAN Spare0;
  1197. // ULONG NumberOfEntries;
  1198. // SYSTEM_POOL_ENTRY Entries[1];
  1199. // } SYSTEM_POOL_INFORMATION, *PSYSTEM_POOL_INFORMATION;
  1200. //
  1201. void PrintSystemPoolDetailedInformation ()
  1202. {
  1203. NTSTATUS Status;
  1204. ULONG RealLength;
  1205. printf ("\n- - - - - - - - - - - - - - - - - - - - - - - - - - - ");
  1206. printf ("- - - - - - - - - - - - - - - - - - - - - - - - - - - \n");
  1207. printf ("System pool detailed information \n");
  1208. printf ("- - - - - - - - - - - - - - - - - - - - - - - - - - - ");
  1209. printf ("- - - - - - - - - - - - - - - - - - - - - - - - - - - \n");
  1210. fflush( stdout );
  1211. //
  1212. // SystemPoolInformation
  1213. //
  1214. Status = NtQuerySystemInformation (
  1215. SystemNonPagedPoolInformation,
  1216. InfoBuffer,
  1217. sizeof InfoBuffer,
  1218. &RealLength);
  1219. if (! NT_SUCCESS(Status))
  1220. {
  1221. printf ("NtQuerySystemInformation(NonPagedPool): error %08X\n", Status);
  1222. return;
  1223. }
  1224. {
  1225. ULONG Index;
  1226. PSYSTEM_POOL_INFORMATION Info = (PSYSTEM_POOL_INFORMATION)InfoBuffer;
  1227. for (Index = 0; Index < Info->NumberOfEntries; Index++)
  1228. {
  1229. if (Index != 0 && Index%5 == 0)
  1230. printf ("\n");
  1231. printf ("%c%c%c%c %-5u ",
  1232. Info->Entries[Index].Tag[0],
  1233. Info->Entries[Index].Tag[1],
  1234. Info->Entries[Index].Tag[2],
  1235. Info->Entries[Index].Tag[3],
  1236. Info->Entries[Index].Size);
  1237. }
  1238. fflush( stdout );
  1239. }
  1240. }
  1241. //
  1242. // Function:
  1243. //
  1244. // PrintSystemPoolTagInformation
  1245. //
  1246. // Description:
  1247. //
  1248. // Prints SystemPoolTagInformation.
  1249. //
  1250. // typedef struct _SYSTEM_POOLTAG {
  1251. // union {
  1252. // UCHAR Tag[4];
  1253. // ULONG TagUlong;
  1254. // };
  1255. // ULONG PagedAllocs;
  1256. // ULONG PagedFrees;
  1257. // SIZE_T PagedUsed;
  1258. // ULONG NonPagedAllocs;
  1259. // ULONG NonPagedFrees;
  1260. // SIZE_T NonPagedUsed;
  1261. // } SYSTEM_POOLTAG, *PSYSTEM_POOLTAG;
  1262. //
  1263. // typedef struct _SYSTEM_POOLTAG_INFORMATION {
  1264. // ULONG Count;
  1265. // SYSTEM_POOLTAG TagInfo[1];
  1266. // } SYSTEM_POOLTAG_INFORMATION, *PSYSTEM_POOLTAG_INFORMATION;
  1267. //
  1268. void PrintSystemPoolTagInformation ()
  1269. {
  1270. NTSTATUS Status;
  1271. ULONG RealLength;
  1272. printf ("\n- - - - - - - - - - - - - - - - - - - - - - - - - - - ");
  1273. printf ("- - - - - - - - - - - - - - - - - - - - - - - - - - - \n");
  1274. printf ("System pool tag information \n");
  1275. printf ("- - - - - - - - - - - - - - - - - - - - - - - - - - - ");
  1276. printf ("- - - - - - - - - - - - - - - - - - - - - - - - - - - \n");
  1277. printf ("%-4s %-8s %-8s %-8s %-8s %-8s %-8s\n",
  1278. "Tag",
  1279. "NP used", "P used",
  1280. "NP alloc", "NP free",
  1281. "P alloc", "P free");
  1282. printf ("%-4s %-8s %-8s %-8s %-8s %-8s %-8s\n",
  1283. "",
  1284. "x bytes", "x bytes",
  1285. "x ops", "x ops",
  1286. "x ops", "x ops");
  1287. printf ("- - - - - - - - - - - - - - - - - - - - - - - - - - - ");
  1288. printf ("- - - - - - - - - - - - - - - - - - - - - - - - - - - \n");
  1289. fflush( stdout );
  1290. //
  1291. // SystemPoolTagInformation
  1292. //
  1293. Status = NtQuerySystemInformation (
  1294. SystemPoolTagInformation,
  1295. InfoBuffer,
  1296. sizeof InfoBuffer,
  1297. &RealLength);
  1298. if (! NT_SUCCESS(Status))
  1299. {
  1300. printf ("NtQuerySystemInformation(PoolTag): error %08X\n", Status);
  1301. return;
  1302. }
  1303. {
  1304. ULONG Index;
  1305. PSYSTEM_POOLTAG_INFORMATION Info = (PSYSTEM_POOLTAG_INFORMATION)InfoBuffer;
  1306. for (Index = 0; Index < Info->Count; Index++)
  1307. {
  1308. printf ("%c%c%c%c %-8u %-8u %-8u %-8u %-8u %-8u\n",
  1309. Info->TagInfo[Index].Tag[0],
  1310. Info->TagInfo[Index].Tag[1],
  1311. Info->TagInfo[Index].Tag[2],
  1312. Info->TagInfo[Index].Tag[3],
  1313. Info->TagInfo[Index].NonPagedUsed,
  1314. Info->TagInfo[Index].PagedUsed,
  1315. Info->TagInfo[Index].NonPagedAllocs,
  1316. Info->TagInfo[Index].NonPagedFrees,
  1317. Info->TagInfo[Index].PagedAllocs,
  1318. Info->TagInfo[Index].PagedFrees);
  1319. }
  1320. fflush( stdout );
  1321. }
  1322. }
  1323. //
  1324. // Function:
  1325. //
  1326. // PrintProcessStackInformation
  1327. //
  1328. // Description:
  1329. //
  1330. // Prints stack usage information for each process.
  1331. //
  1332. BOOL
  1333. ComputeMaxStackInProcess (
  1334. DWORD Pid,
  1335. PSIZE_T MaxSize,
  1336. PSIZE_T TotalSize);
  1337. VOID
  1338. PrintProcessStackInformation (
  1339. VOID
  1340. )
  1341. {
  1342. NTSTATUS Status;
  1343. ULONG RealLength;
  1344. SYSTEM_BASIC_INFORMATION SysInfo;
  1345. BOOL FinishNextTime = FALSE;
  1346. BOOL ErrorsFound = FALSE;
  1347. SIZE_T MaxStack = 0;
  1348. SIZE_T TotalStack = 0;
  1349. BOOLEAN WasEnabled;
  1350. printf ("\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n");
  1351. printf ("Process stack information \n");
  1352. printf ("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n");
  1353. //
  1354. // SystemBasicInformation
  1355. //
  1356. Status = NtQuerySystemInformation (
  1357. SystemBasicInformation,
  1358. &SysInfo,
  1359. sizeof (SysInfo),
  1360. &RealLength);
  1361. if (! NT_SUCCESS(Status)) {
  1362. printf ("NtQuerySystemInformation(Basic): error %08X\n", Status);
  1363. return;
  1364. }
  1365. //
  1366. // SystemProcessInformation
  1367. //
  1368. Status = NtQuerySystemInformation (SystemProcessInformation,
  1369. InfoBuffer,
  1370. sizeof InfoBuffer,
  1371. &RealLength);
  1372. if (! NT_SUCCESS(Status)) {
  1373. printf ("NtQuerySystemInformation(Process): error %08X\n", Status);
  1374. return;
  1375. }
  1376. //
  1377. // Get debug privilege.
  1378. //
  1379. Status = RtlAdjustPrivilege(SE_DEBUG_PRIVILEGE,
  1380. TRUE,
  1381. FALSE,
  1382. &WasEnabled);
  1383. if (! NT_SUCCESS(Status)) {
  1384. printf("Failed to enable debug privilege (%X) \n", Status);
  1385. }
  1386. {
  1387. PSYSTEM_PROCESS_INFORMATION Info = (PSYSTEM_PROCESS_INFORMATION)InfoBuffer;
  1388. printf ("%-15s %-5s %-5s %-4s %-5s %-8s %-5s %-5s\n",
  1389. "",
  1390. "",
  1391. "",
  1392. "",
  1393. "",
  1394. "",
  1395. "Total",
  1396. "Max");
  1397. printf ("%-15s %-5s %-5s %-4s %-5s %-8s %-5s %-5s\n",
  1398. "Process",
  1399. "Id",
  1400. "Sess",
  1401. "Pri",
  1402. "Thrds",
  1403. "Handles",
  1404. "stack",
  1405. "stack");
  1406. printf ("%-15s %-5s %-5s %-4s %-5s %-8s %-5s %-5s\n",
  1407. "",
  1408. "",
  1409. "",
  1410. "",
  1411. "",
  1412. "",
  1413. "Kb",
  1414. "Kb");
  1415. printf ("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n");
  1416. for (FinishNextTime = FALSE ;
  1417. FinishNextTime == FALSE;
  1418. Info = (PSYSTEM_PROCESS_INFORMATION)((ULONG_PTR)Info + Info->NextEntryOffset)) {
  1419. if (Info->NextEntryOffset == 0)
  1420. FinishNextTime = TRUE;
  1421. //
  1422. // User time vs Kernel time.
  1423. //
  1424. ULONG UserPercent, KernelPercent;
  1425. UserPercent = (ULONG)((Info->UserTime.QuadPart) * 100
  1426. / (Info->UserTime.QuadPart + Info->KernelTime.QuadPart));
  1427. KernelPercent = 100 - UserPercent;
  1428. //
  1429. // I/O total count.
  1430. //
  1431. LARGE_INTEGER IoTotalCount;
  1432. IoTotalCount.QuadPart = Info->ReadOperationCount.QuadPart
  1433. + Info->WriteOperationCount.QuadPart
  1434. + Info->OtherOperationCount.QuadPart;
  1435. IoTotalCount.QuadPart /= 1000;
  1436. //
  1437. // Image name (special case the idle process).
  1438. //
  1439. if (Info->ImageName.Buffer == NULL) {
  1440. printf ("%-15s ", "Idle");
  1441. }
  1442. else {
  1443. printf ("%-15ws ", Info->ImageName.Buffer);
  1444. }
  1445. //
  1446. // Compute stack info by iterating all threads in the process.
  1447. //
  1448. GetProcessStackInfo (Info, &MaxStack, &TotalStack, &ErrorsFound);
  1449. //
  1450. // Print the stuff.
  1451. //
  1452. printf ("%-5I64u %-5u %-4u %-5u %-8u %-5u %-5u\n",
  1453. (ULONG64)((ULONG_PTR)(Info->UniqueProcessId)),
  1454. Info->SessionId,
  1455. Info->BasePriority,
  1456. Info->NumberOfThreads,
  1457. Info->HandleCount,
  1458. (ULONG)(TotalStack/1024),
  1459. (ULONG)(MaxStack/1024));
  1460. }
  1461. }
  1462. printf(
  1463. " \n"
  1464. " * Total stack: total committed memory used for stacks by all threads \n"
  1465. " in the process. \n"
  1466. " * Max stack: the biggest committed stack in the process. \n"
  1467. " \n");
  1468. }
  1469. VOID
  1470. GetProcessStackInfo (
  1471. PSYSTEM_PROCESS_INFORMATION Info,
  1472. PSIZE_T MaxSize,
  1473. PSIZE_T TotalSize,
  1474. PBOOL ErrorsFound
  1475. )
  1476. {
  1477. ULONG Ti;
  1478. HANDLE Id;
  1479. HANDLE Thread;
  1480. HANDLE Process;
  1481. THREAD_BASIC_INFORMATION ThreadInfo;
  1482. TEB TebInfo;
  1483. SIZE_T BytesRead;
  1484. BOOL ReadResult;
  1485. NTSTATUS Status;
  1486. SIZE_T StackSize;
  1487. BOOLEAN WasEnabled;
  1488. *MaxSize = 0;
  1489. *TotalSize = 0;
  1490. *ErrorsFound = FALSE;
  1491. //
  1492. // Open the process.
  1493. //
  1494. Process = OpenProcess (PROCESS_VM_READ,
  1495. FALSE,
  1496. HandleToUlong(Info->UniqueProcessId));
  1497. if (Process == FALSE) {
  1498. //printf("Failed to open process %p (error %u) \n", Info->UniqueProcessId, GetLastError());
  1499. *ErrorsFound = TRUE;
  1500. return;
  1501. }
  1502. //
  1503. // Iterate all threads in the process and for each determine the
  1504. // thread ID, open the thread and query for TEB address. Finally
  1505. // read user mode stack sizes from the TEB.
  1506. //
  1507. for (Ti = 0; Ti < Info->NumberOfThreads; Ti += 1) {
  1508. Id = ((PSYSTEM_THREAD_INFORMATION)(Info + 1) + Ti)->ClientId.UniqueThread;
  1509. Thread = OpenThread (THREAD_QUERY_INFORMATION,
  1510. FALSE,
  1511. HandleToUlong(Id));
  1512. if (Thread == NULL) {
  1513. //printf("failed to open thread %u \n", GetLastError());
  1514. *ErrorsFound = TRUE;
  1515. continue;
  1516. }
  1517. Status = NtQueryInformationThread (Thread,
  1518. ThreadBasicInformation,
  1519. &ThreadInfo,
  1520. sizeof ThreadInfo,
  1521. NULL);
  1522. if (!NT_SUCCESS(Status)) {
  1523. //printf("query thread failed with %X \n", Status);
  1524. *ErrorsFound = TRUE;
  1525. CloseHandle (Thread);
  1526. continue;
  1527. }
  1528. ReadResult = ReadProcessMemory (Process,
  1529. ThreadInfo.TebBaseAddress,
  1530. &TebInfo,
  1531. sizeof TebInfo,
  1532. &BytesRead);
  1533. if (ReadResult == FALSE) {
  1534. //printf("failed to read teb with %u \n", GetLastError());
  1535. *ErrorsFound = TRUE;
  1536. CloseHandle (Thread);
  1537. continue;
  1538. }
  1539. StackSize = (SIZE_T)(TebInfo.NtTib.StackBase) - (SIZE_T)(TebInfo.NtTib.StackLimit);
  1540. *TotalSize += StackSize;
  1541. if (StackSize > *MaxSize) {
  1542. *MaxSize = StackSize;
  1543. }
  1544. CloseHandle (Thread);
  1545. }
  1546. CloseHandle (Process);
  1547. }
  1548. //////////////////////////////////////////////////////////////////////
  1549. //////////////////////////////////////////////////////////////////////
  1550. //////////////////////////////////////////////////////////////////////
  1551. //
  1552. // Function:
  1553. //
  1554. // DebugMessage
  1555. //
  1556. // Description:
  1557. //
  1558. // Printf like function that prints a message into debugger.
  1559. //
  1560. void __cdecl DebugMessage (char *fmt, ...)
  1561. {
  1562. va_list prms;
  1563. char Buffer [1024];
  1564. va_start (prms, fmt);
  1565. vsprintf (Buffer, fmt, prms);
  1566. OutputDebugString (Buffer);
  1567. va_end (prms);
  1568. }
  1569. //
  1570. // end of module: systrack.cxx
  1571. //