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.

889 lines
28 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. top.c
  5. Abstract:
  6. This module contains the NT/Win32 Top threads Meter
  7. Author:
  8. Another Mark Lucovsky (markl) / Lou Perazzoli (loup) production 5-Aug-1991
  9. Revision History:
  10. --*/
  11. #include "perfmtrp.h"
  12. #include <stdlib.h>
  13. #define BUFFER_SIZE 64*1024
  14. #define CPU_THREAD 0
  15. #define CPU_PROCESS 1
  16. #define FAULTS 2
  17. #define WORKING_SET 3
  18. #define CONTEXT_SWITCHES 4
  19. #define SYSTEM_CALLS 5
  20. PUCHAR g_pLargeBuffer1 = NULL;
  21. PUCHAR g_pLargeBuffer2 = NULL;
  22. DWORD g_dwBufSize1;
  23. DWORD g_dwBufSize2;
  24. WCHAR *NoNameFound = L"No Name Found";
  25. UCHAR *StateTable[] = {
  26. "Initialized",
  27. "Ready",
  28. "Running",
  29. "Standby",
  30. "Terminated",
  31. "Wait:",
  32. "Transition",
  33. "Unknown",
  34. "Unknown",
  35. "Unknown",
  36. "Unknown",
  37. "Unknown"
  38. };
  39. UCHAR *WaitTable[] = {
  40. "Executive",
  41. "FreePage",
  42. "PageIn",
  43. "PoolAllocation",
  44. "DelayExecution",
  45. "Suspended",
  46. "UserRequest",
  47. "Executive",
  48. "FreePage",
  49. "PageIn",
  50. "PoolAllocation",
  51. "DelayExecution",
  52. "Suspended",
  53. "UserRequest",
  54. "EventPairHigh",
  55. "EventPairLow",
  56. "LpcReceive",
  57. "LpcReply",
  58. "Spare1",
  59. "Spare2",
  60. "Spare3",
  61. "Spare4",
  62. "Spare5",
  63. "Spare6",
  64. "Spare7",
  65. "Spare8",
  66. "Spare9",
  67. "Unknown",
  68. "Unknown",
  69. "Unknown",
  70. "Unknown"
  71. };
  72. UCHAR *Empty = " ";
  73. PSYSTEM_PROCESS_INFORMATION
  74. FindMatchedProcess (
  75. IN PSYSTEM_PROCESS_INFORMATION ProcessToMatch,
  76. IN PUCHAR SystemInfoBuffer,
  77. IN PULONG Hint
  78. );
  79. PSYSTEM_THREAD_INFORMATION
  80. FindMatchedThread (
  81. IN PSYSTEM_THREAD_INFORMATION ThreadToMatch,
  82. IN PSYSTEM_PROCESS_INFORMATION MatchedProcess
  83. );
  84. typedef struct _TOPCPU {
  85. LARGE_INTEGER TotalTime;
  86. PSYSTEM_PROCESS_INFORMATION ProcessInfo;
  87. PSYSTEM_PROCESS_INFORMATION MatchedProcess;
  88. ULONG Value;
  89. } TOPCPU, *PTOPCPU;
  90. TOPCPU TopCpu[1000];
  91. int
  92. __cdecl main( argc, argv )
  93. int argc;
  94. char *argv[];
  95. {
  96. NTSTATUS Status;
  97. int i,j;
  98. ULONG DelayTimeMsec;
  99. ULONG DelayTimeTicks;
  100. COORD dest,cp;
  101. SMALL_RECT Sm;
  102. CHAR_INFO ci;
  103. CONSOLE_SCREEN_BUFFER_INFO sbi;
  104. KPRIORITY SetBasePriority;
  105. INPUT_RECORD InputRecord;
  106. HANDLE ScreenHandle;
  107. BOOLEAN Active;
  108. DWORD NumRead;
  109. SMALL_RECT Window;
  110. PSYSTEM_THREAD_INFORMATION Thread;
  111. PSYSTEM_THREAD_INFORMATION MatchedThread;
  112. PUCHAR PreviousBuffer;
  113. PUCHAR CurrentBuffer;
  114. PUCHAR TempBuffer;
  115. ULONG Hint;
  116. ULONG Offset1;
  117. int num;
  118. int Type;
  119. ULONG ContextSwitches;
  120. PSYSTEM_PROCESS_INFORMATION CurProcessInfo;
  121. PSYSTEM_PROCESS_INFORMATION MatchedProcess;
  122. LARGE_INTEGER LARGE_ZERO={0,0};
  123. LARGE_INTEGER Ktime;
  124. LARGE_INTEGER Utime;
  125. LARGE_INTEGER TotalTime;
  126. TIME_FIELDS TimeOut;
  127. PTOPCPU PTopCpu;
  128. BOOLEAN bToggle = TRUE;
  129. PDWORD pdwBufSize = NULL;
  130. SetBasePriority = (KPRIORITY) 12;
  131. NtSetInformationProcess(
  132. NtCurrentProcess(),
  133. ProcessBasePriority,
  134. (PVOID) &SetBasePriority,
  135. sizeof(SetBasePriority)
  136. );
  137. GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE),&sbi);
  138. DelayTimeMsec = 2500;
  139. DelayTimeTicks = DelayTimeMsec * 10000;
  140. Window.Left = 0;
  141. Window.Top = 0;
  142. Window.Right = 79;
  143. Window.Bottom = 23;
  144. dest.X = 0;
  145. dest.Y = 23;
  146. ci.Char.AsciiChar = ' ';
  147. ci.Attributes = sbi.wAttributes;
  148. SetConsoleWindowInfo(GetStdHandle(STD_OUTPUT_HANDLE),
  149. TRUE,
  150. &Window
  151. );
  152. cp.X = 0;
  153. cp.Y = 0;
  154. Sm.Left = 0;
  155. Sm.Top = 0;
  156. Sm.Right = 79;
  157. Sm.Bottom = 22;
  158. ScrollConsoleScreenBuffer(
  159. GetStdHandle(STD_OUTPUT_HANDLE),
  160. &Sm,
  161. NULL,
  162. dest,
  163. &ci
  164. );
  165. SetConsoleCursorPosition(
  166. GetStdHandle(STD_OUTPUT_HANDLE),
  167. cp
  168. );
  169. printf( " %% Pid Tid Pri Key Start Address ImageName\n");
  170. printf( "___________________________________________________________________\n");
  171. cp.X = 0;
  172. cp.Y = 2;
  173. Sm.Left = 0;
  174. Sm.Top = 2;
  175. Sm.Right = 79;
  176. Sm.Bottom = 22;
  177. ScreenHandle = GetStdHandle (STD_INPUT_HANDLE);
  178. // allocate space for the buffer
  179. g_dwBufSize1 = BUFFER_SIZE;
  180. g_dwBufSize2 = BUFFER_SIZE;
  181. g_pLargeBuffer1 = ( PUCHAR )malloc( sizeof( UCHAR ) * g_dwBufSize1 );
  182. if( g_pLargeBuffer1 == NULL )
  183. {
  184. return 0;
  185. }
  186. g_pLargeBuffer2 = ( PUCHAR )malloc( sizeof( UCHAR ) * g_dwBufSize2 );
  187. if( g_pLargeBuffer2 == NULL )
  188. {
  189. return 0;
  190. }
  191. retry0:
  192. Status = NtQuerySystemInformation(
  193. SystemProcessInformation,
  194. g_pLargeBuffer1,
  195. g_dwBufSize1,
  196. NULL
  197. );
  198. if( Status == STATUS_INFO_LENGTH_MISMATCH )
  199. {
  200. g_dwBufSize1 *= 2;
  201. if( g_pLargeBuffer1 != NULL )
  202. {
  203. free( g_pLargeBuffer1 );
  204. }
  205. g_pLargeBuffer1 = ( PUCHAR )malloc( sizeof( UCHAR ) * g_dwBufSize1 );
  206. if( g_pLargeBuffer1 == NULL )
  207. {
  208. return 0;
  209. }
  210. }
  211. if ( !NT_SUCCESS(Status) ) {
  212. printf("Query Failed %lx\n",Status);
  213. goto retry0;
  214. }
  215. Sleep(DelayTimeMsec);
  216. retry01:
  217. NtSetInformationProcess(
  218. NtCurrentProcess(),
  219. ProcessBasePriority,
  220. (PVOID) &SetBasePriority,
  221. sizeof(SetBasePriority)
  222. );
  223. Status = NtQuerySystemInformation(
  224. SystemProcessInformation,
  225. g_pLargeBuffer2,
  226. g_dwBufSize2,
  227. NULL
  228. );
  229. if( Status == STATUS_INFO_LENGTH_MISMATCH )
  230. {
  231. g_dwBufSize2 *= 2;
  232. if( g_pLargeBuffer2 != NULL )
  233. {
  234. free( g_pLargeBuffer2 );
  235. }
  236. g_pLargeBuffer2 = ( PUCHAR )malloc( sizeof( UCHAR ) * g_dwBufSize2 );
  237. if( g_pLargeBuffer2 == NULL )
  238. {
  239. if( g_pLargeBuffer1 != NULL )
  240. {
  241. free( g_pLargeBuffer1 );
  242. }
  243. return 0;
  244. }
  245. }
  246. if ( !NT_SUCCESS(Status) ) {
  247. printf("Query Failed %lx\n",Status);
  248. goto retry01;
  249. }
  250. PreviousBuffer = &g_pLargeBuffer1[0];
  251. CurrentBuffer = &g_pLargeBuffer2[0];
  252. Active = TRUE;
  253. Type = CPU_PROCESS;
  254. while(TRUE) {
  255. waitkey:
  256. while (PeekConsoleInput (ScreenHandle, &InputRecord, 1, &NumRead) && NumRead != 0) {
  257. if (!ReadConsoleInput (ScreenHandle, &InputRecord, 1, &NumRead)) {
  258. break;
  259. }
  260. if (InputRecord.EventType == KEY_EVENT) {
  261. switch (InputRecord.Event.KeyEvent.uChar.AsciiChar) {
  262. case 'q':
  263. case 'Q':
  264. {
  265. if( CurrentBuffer != NULL )
  266. {
  267. free( CurrentBuffer );
  268. }
  269. if( PreviousBuffer != NULL )
  270. {
  271. free( PreviousBuffer );
  272. }
  273. ExitProcess(0);
  274. }
  275. break;
  276. case 'p':
  277. case 'P':
  278. Active = FALSE;
  279. break;
  280. case 'c':
  281. case 'C':
  282. Type = CPU_PROCESS;
  283. break;
  284. case 'f':
  285. case 'F':
  286. Type = FAULTS;
  287. break;
  288. case 's':
  289. case 'S':
  290. Type = CONTEXT_SWITCHES;
  291. break;
  292. case 't':
  293. case 'T':
  294. Type = CPU_THREAD;
  295. break;
  296. case 'w':
  297. case 'W':
  298. Type = WORKING_SET;
  299. break;
  300. default:
  301. Active = TRUE;
  302. break;
  303. }
  304. }
  305. }
  306. if ( !Active ) {
  307. goto waitkey;
  308. }
  309. ScrollConsoleScreenBuffer(
  310. GetStdHandle(STD_OUTPUT_HANDLE),
  311. &Sm,
  312. NULL,
  313. dest,
  314. &ci
  315. );
  316. SetConsoleCursorPosition(
  317. GetStdHandle(STD_OUTPUT_HANDLE),
  318. cp
  319. );
  320. //
  321. // Calculate top CPU users and display information.
  322. //
  323. //
  324. // Cross check previous process/thread info against current
  325. // process/thread info.
  326. //
  327. Offset1 = 0;
  328. num = 0;
  329. Hint = 0;
  330. TotalTime = LARGE_ZERO;
  331. while (TRUE) {
  332. CurProcessInfo = (PSYSTEM_PROCESS_INFORMATION)&CurrentBuffer[Offset1];
  333. //
  334. // Find the corresponding process in the previous array.
  335. //
  336. MatchedProcess = FindMatchedProcess (CurProcessInfo,
  337. PreviousBuffer,
  338. &Hint);
  339. switch (Type) {
  340. case CPU_PROCESS:
  341. case CPU_THREAD:
  342. if (MatchedProcess == NULL) {
  343. TopCpu[num].TotalTime = Ktime;
  344. TopCpu[num].TotalTime.QuadPart =
  345. TopCpu[num].TotalTime.QuadPart +
  346. Utime.QuadPart;
  347. TotalTime.QuadPart = TotalTime.QuadPart +
  348. TopCpu[num].TotalTime.QuadPart;
  349. TopCpu[num].ProcessInfo = CurProcessInfo;
  350. TopCpu[num].MatchedProcess = NULL;
  351. num += 1;
  352. } else {
  353. Ktime.QuadPart = CurProcessInfo->KernelTime.QuadPart -
  354. MatchedProcess->KernelTime.QuadPart;
  355. Utime.QuadPart = CurProcessInfo->UserTime.QuadPart -
  356. MatchedProcess->UserTime.QuadPart;
  357. if ((Ktime.QuadPart != 0) ||
  358. (Utime.QuadPart != 0)) {
  359. TopCpu[num].TotalTime = Ktime;
  360. TopCpu[num].TotalTime.QuadPart =
  361. TopCpu[num].TotalTime.QuadPart +
  362. Utime.QuadPart;
  363. TotalTime.QuadPart = TotalTime.QuadPart +
  364. TopCpu[num].TotalTime.QuadPart;
  365. TopCpu[num].ProcessInfo = CurProcessInfo;
  366. TopCpu[num].MatchedProcess = MatchedProcess;
  367. num += 1;
  368. }
  369. }
  370. if (CurProcessInfo->NextEntryOffset == 0) {
  371. for (i=0;i<num;i++) {
  372. PTopCpu = &TopCpu[i];
  373. Ktime.QuadPart =
  374. PTopCpu->ProcessInfo->KernelTime.QuadPart +
  375. PTopCpu->ProcessInfo->UserTime.QuadPart;
  376. RtlTimeToTimeFields ( &Ktime, &TimeOut);
  377. printf( "%4ld%% %p %7ld %7ld %7ld %3ld:%02ld:%02ld.%03ld %ws\n",
  378. (PTopCpu->TotalTime.LowPart*100)/TotalTime.LowPart,
  379. PTopCpu->ProcessInfo->UniqueProcessId,
  380. PTopCpu->ProcessInfo->PageFaultCount,
  381. PTopCpu->ProcessInfo->WorkingSetSize,
  382. PTopCpu->ProcessInfo->PrivatePageCount,
  383. TimeOut.Hour,
  384. TimeOut.Minute,
  385. TimeOut.Second,
  386. TimeOut.Milliseconds,
  387. (PTopCpu->ProcessInfo->ImageName.Buffer != NULL) ?
  388. PTopCpu->ProcessInfo->ImageName.Buffer :
  389. NoNameFound);
  390. Thread = (PSYSTEM_THREAD_INFORMATION)(TopCpu[i].ProcessInfo + 1);
  391. if (Type == CPU_THREAD) {
  392. for (j = 0;
  393. j < (int)TopCpu[i].ProcessInfo->NumberOfThreads;
  394. j++) {
  395. if (TopCpu[i].MatchedProcess == NULL) {
  396. MatchedThread = NULL;
  397. } else {
  398. MatchedThread = FindMatchedThread (
  399. Thread,
  400. TopCpu[i].MatchedProcess
  401. );
  402. }
  403. if (MatchedThread == NULL) {
  404. Ktime.QuadPart =
  405. Thread->KernelTime.QuadPart +
  406. Thread->UserTime.QuadPart;
  407. } else {
  408. Ktime.QuadPart =
  409. Thread->KernelTime.QuadPart -
  410. MatchedThread->KernelTime.QuadPart;
  411. Utime.QuadPart =
  412. Thread->UserTime.QuadPart -
  413. MatchedThread->UserTime.QuadPart;
  414. Ktime.QuadPart =
  415. Ktime.QuadPart +
  416. Utime.QuadPart;
  417. }
  418. if (Ktime.LowPart != 0) {
  419. printf(" %4ld%% TID%p Cs %5ld\n",
  420. (Ktime.LowPart*100)/TotalTime.LowPart,
  421. Thread->ClientId.UniqueThread,
  422. Thread->ContextSwitches);
  423. }
  424. Thread += 1;
  425. }
  426. }
  427. }
  428. }
  429. break;
  430. case FAULTS:
  431. if (MatchedProcess == NULL) {
  432. TopCpu[num].Value = CurProcessInfo->PageFaultCount;
  433. TopCpu[num].ProcessInfo = CurProcessInfo;
  434. num += 1;
  435. } else {
  436. TopCpu[num].Value = CurProcessInfo->PageFaultCount -
  437. MatchedProcess->PageFaultCount;
  438. if (TopCpu[num].Value != 0) {
  439. TopCpu[num].ProcessInfo = CurProcessInfo;
  440. num += 1;
  441. }
  442. }
  443. if (CurProcessInfo->NextEntryOffset == 0) {
  444. for (i=0;i<num;i++) {
  445. PTopCpu = &TopCpu[i];
  446. Ktime.QuadPart =
  447. PTopCpu->ProcessInfo->KernelTime.QuadPart +
  448. PTopCpu->ProcessInfo->UserTime.QuadPart;
  449. RtlTimeToTimeFields ( &Ktime, &TimeOut);
  450. printf( "Pf: %4ld %p %7ld %7ld %7ld %3ld:%02ld:%02ld.%03ld %ws\n",
  451. PTopCpu->Value,
  452. PTopCpu->ProcessInfo->UniqueProcessId,
  453. PTopCpu->ProcessInfo->PageFaultCount,
  454. PTopCpu->ProcessInfo->WorkingSetSize,
  455. PTopCpu->ProcessInfo->PrivatePageCount,
  456. TimeOut.Hour,
  457. TimeOut.Minute,
  458. TimeOut.Second,
  459. TimeOut.Milliseconds,
  460. (PTopCpu->ProcessInfo->ImageName.Buffer != NULL) ?
  461. PTopCpu->ProcessInfo->ImageName.Buffer :
  462. NoNameFound);
  463. }
  464. }
  465. break;
  466. case WORKING_SET:
  467. if (MatchedProcess == NULL) {
  468. TopCpu[num].Value = CurProcessInfo->PageFaultCount;
  469. TopCpu[num].ProcessInfo = CurProcessInfo;
  470. num += 1;
  471. } else {
  472. if (CurProcessInfo->WorkingSetSize !=
  473. MatchedProcess->WorkingSetSize) {
  474. TopCpu[num].Value =
  475. (ULONG)(CurProcessInfo->WorkingSetSize - MatchedProcess->WorkingSetSize);
  476. TopCpu[num].ProcessInfo = CurProcessInfo;
  477. num += 1;
  478. }
  479. }
  480. if (CurProcessInfo->NextEntryOffset == 0) {
  481. for (i=0;i<num;i++) {
  482. PTopCpu = &TopCpu[i];
  483. Ktime.QuadPart =
  484. PTopCpu->ProcessInfo->KernelTime.QuadPart +
  485. PTopCpu->ProcessInfo->UserTime.QuadPart;
  486. RtlTimeToTimeFields ( &Ktime, &TimeOut);
  487. printf( "Ws: %4ld %p %7ld %7ld %7ld %3ld:%02ld:%02ld.%03ld %ws\n",
  488. PTopCpu->Value,
  489. PTopCpu->ProcessInfo->UniqueProcessId,
  490. PTopCpu->ProcessInfo->PageFaultCount,
  491. PTopCpu->ProcessInfo->WorkingSetSize,
  492. PTopCpu->ProcessInfo->PrivatePageCount,
  493. TimeOut.Hour,
  494. TimeOut.Minute,
  495. TimeOut.Second,
  496. TimeOut.Milliseconds,
  497. (PTopCpu->ProcessInfo->ImageName.Buffer != NULL) ?
  498. PTopCpu->ProcessInfo->ImageName.Buffer :
  499. NoNameFound);
  500. }
  501. }
  502. break;
  503. case CONTEXT_SWITCHES:
  504. Thread = (PSYSTEM_THREAD_INFORMATION)(CurProcessInfo + 1);
  505. TopCpu[num].Value = 0;
  506. if (MatchedProcess == NULL) {
  507. for (j = 0; j < (int)CurProcessInfo->NumberOfThreads; j++ ) {
  508. TopCpu[num].Value += Thread->ContextSwitches;
  509. Thread += 1;
  510. }
  511. if (TopCpu[num].Value != 0) {
  512. TopCpu[num].ProcessInfo = CurProcessInfo;
  513. TopCpu[num].MatchedProcess = NULL;
  514. num += 1;
  515. }
  516. } else {
  517. for (j = 0; j < (int)CurProcessInfo->NumberOfThreads; j++ ) {
  518. MatchedThread = FindMatchedThread (
  519. Thread,
  520. MatchedProcess
  521. );
  522. if (MatchedThread == NULL) {
  523. TopCpu[num].Value += Thread->ContextSwitches;
  524. } else {
  525. TopCpu[num].Value +=
  526. Thread->ContextSwitches - MatchedThread->ContextSwitches;
  527. }
  528. Thread += 1;
  529. }
  530. if (TopCpu[num].Value != 0) {
  531. TopCpu[num].ProcessInfo = CurProcessInfo;
  532. TopCpu[num].MatchedProcess = MatchedProcess;
  533. num += 1;
  534. }
  535. }
  536. if (CurProcessInfo->NextEntryOffset == 0) {
  537. for (i=0;i<num;i++) {
  538. PTopCpu = &TopCpu[i];
  539. Ktime.QuadPart =
  540. PTopCpu->ProcessInfo->KernelTime.QuadPart +
  541. PTopCpu->ProcessInfo->UserTime.QuadPart;
  542. RtlTimeToTimeFields ( &Ktime, &TimeOut);
  543. printf( "Cs: %4ld %p %7ld %7ld %7ld %3ld:%02ld:%02ld.%03ld %ws\n",
  544. PTopCpu->Value,
  545. PTopCpu->ProcessInfo->UniqueProcessId,
  546. PTopCpu->ProcessInfo->PageFaultCount,
  547. PTopCpu->ProcessInfo->WorkingSetSize,
  548. PTopCpu->ProcessInfo->PrivatePageCount,
  549. TimeOut.Hour,
  550. TimeOut.Minute,
  551. TimeOut.Second,
  552. TimeOut.Milliseconds,
  553. (PTopCpu->ProcessInfo->ImageName.Buffer != NULL) ?
  554. PTopCpu->ProcessInfo->ImageName.Buffer :
  555. NoNameFound);
  556. Thread = (PSYSTEM_THREAD_INFORMATION)(TopCpu[i].ProcessInfo + 1);
  557. for (j = 0;
  558. j < (int)TopCpu[i].ProcessInfo->NumberOfThreads;
  559. j++) {
  560. ContextSwitches = 0;
  561. if (TopCpu[i].MatchedProcess == NULL) {
  562. MatchedThread = NULL;
  563. } else {
  564. MatchedThread = FindMatchedThread (
  565. Thread,
  566. TopCpu[i].MatchedProcess
  567. );
  568. }
  569. if (MatchedThread == NULL) {
  570. ContextSwitches = Thread->ContextSwitches;
  571. } else {
  572. ContextSwitches =
  573. Thread->ContextSwitches -
  574. MatchedThread->ContextSwitches;
  575. }
  576. if (ContextSwitches != 0) {
  577. printf("\t TID%p Cs %5ld%+3ld\n",
  578. Thread->ClientId.UniqueThread,
  579. Thread->ContextSwitches,
  580. ContextSwitches);
  581. }
  582. Thread += 1;
  583. }
  584. }
  585. }
  586. break;
  587. default:
  588. break;
  589. } //end switch
  590. if (CurProcessInfo->NextEntryOffset == 0) {
  591. break;
  592. }
  593. Offset1 += CurProcessInfo->NextEntryOffset;
  594. } //end while
  595. /*
  596. two snapshot buffers are maintained and swapped around
  597. since these buffers are now dynamic keep the bufsize in
  598. sync
  599. */
  600. TempBuffer = PreviousBuffer;
  601. PreviousBuffer = CurrentBuffer;
  602. CurrentBuffer = TempBuffer;
  603. pdwBufSize = bToggle ? &g_dwBufSize1 : &g_dwBufSize2;
  604. bToggle = !bToggle;
  605. retry1:
  606. Sleep(DelayTimeMsec);
  607. NtSetInformationProcess(
  608. NtCurrentProcess(),
  609. ProcessBasePriority,
  610. (PVOID) &SetBasePriority,
  611. sizeof(SetBasePriority)
  612. );
  613. Status = NtQuerySystemInformation(
  614. SystemProcessInformation,
  615. ( PVOID)CurrentBuffer,
  616. *pdwBufSize,
  617. NULL
  618. );
  619. if( Status == STATUS_INFO_LENGTH_MISMATCH )
  620. {
  621. *pdwBufSize *= 2;
  622. if( CurrentBuffer != NULL )
  623. {
  624. free( CurrentBuffer );
  625. }
  626. CurrentBuffer = ( PUCHAR )malloc( sizeof( UCHAR ) * ( *pdwBufSize ) );
  627. if( CurrentBuffer == NULL )
  628. {
  629. if( PreviousBuffer != NULL )
  630. {
  631. free( PreviousBuffer );
  632. }
  633. return 0;
  634. }
  635. }
  636. if ( !NT_SUCCESS(Status) ) {
  637. printf("Query Failed %lx\n",Status);
  638. goto retry1;
  639. }
  640. }
  641. return(0);
  642. }
  643. PSYSTEM_PROCESS_INFORMATION
  644. FindMatchedProcess (
  645. IN PSYSTEM_PROCESS_INFORMATION ProcessToMatch,
  646. IN PUCHAR SystemInfoBuffer,
  647. IN OUT PULONG Hint
  648. )
  649. /*++
  650. Routine Description:
  651. This procedure finds the process which corresponds to the ProcessToMatch.
  652. It returns the address of the matching Process, or NULL if no
  653. matching process was found.
  654. Arguments:
  655. ProcessToMatch - Supplies a pointer to the target thread to match.
  656. SystemInfoBuffer - Supples a pointer to the system information
  657. buffer in which to locate the process.
  658. Hint - Supplies and returns a hint for optimizing the searches.
  659. Return Value:
  660. Address of the corresponding Process or NULL.
  661. --*/
  662. {
  663. PSYSTEM_PROCESS_INFORMATION Process;
  664. ULONG Offset2;
  665. Offset2 = *Hint;
  666. while (TRUE) {
  667. Process = (PSYSTEM_PROCESS_INFORMATION)&SystemInfoBuffer[Offset2];
  668. if ((Process->UniqueProcessId ==
  669. ProcessToMatch->UniqueProcessId) &&
  670. ((Process->CreateTime.QuadPart ==
  671. ProcessToMatch->CreateTime.QuadPart))) {
  672. *Hint = Offset2 + Process->NextEntryOffset;
  673. return(Process);
  674. }
  675. Offset2 += Process->NextEntryOffset;
  676. if (Offset2 == *Hint) {
  677. *Hint = 0;
  678. return(NULL);
  679. }
  680. if (Process->NextEntryOffset == 0) {
  681. if (*Hint == 0) {
  682. return(NULL);
  683. }
  684. Offset2 = 0;
  685. }
  686. }
  687. }
  688. PSYSTEM_THREAD_INFORMATION
  689. FindMatchedThread (
  690. IN PSYSTEM_THREAD_INFORMATION ThreadToMatch,
  691. IN PSYSTEM_PROCESS_INFORMATION MatchedProcess
  692. )
  693. /*++
  694. Routine Description:
  695. This procedure finds thread which corresponds to the ThreadToMatch.
  696. It returns the address of the matching thread, or NULL if no
  697. matching thread was found.
  698. Arguments:
  699. ThreadToMatch - Supplies a pointer to the target thread to match.
  700. MatchedProcess - Supples a pointer to the process which contains
  701. the target thread. The thread information
  702. must follow this process, i.e., this block was
  703. obtain from a NtQuerySystemInformation specifying
  704. PROCESS_INFORMATION.
  705. Return Value:
  706. Address of the corresponding thread from MatchedProcess or NULL.
  707. --*/
  708. {
  709. PSYSTEM_THREAD_INFORMATION Thread;
  710. ULONG i;
  711. Thread = (PSYSTEM_THREAD_INFORMATION)(MatchedProcess + 1);
  712. for (i = 0; i < MatchedProcess->NumberOfThreads; i++) {
  713. if ((Thread->ClientId.UniqueThread ==
  714. ThreadToMatch->ClientId.UniqueThread) &&
  715. ((Thread->CreateTime.QuadPart ==
  716. ThreadToMatch->CreateTime.QuadPart))) {
  717. return(Thread);
  718. }
  719. Thread += 1;
  720. }
  721. return(NULL);
  722. }