Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1422 lines
41 KiB

  1. #include "pviewp.h"
  2. #include <port1632.h>
  3. #include <string.h>
  4. #include <stdlib.h>
  5. ULONG PageSize = 4096;
  6. #ifdef DBG
  7. #define ODS OutputDebugString
  8. #else
  9. #define ODS
  10. #endif
  11. #define BUFSIZE 64*1024
  12. INT_PTR CALLBACK
  13. ExplodeDlgProc(
  14. HWND hwnd,
  15. UINT wMsg,
  16. WPARAM wParam,
  17. LPARAM lParam
  18. );
  19. VOID
  20. SetProcessFields(
  21. PSYSTEM_PROCESS_INFORMATION ProcessInfo,
  22. HWND hwnd
  23. );
  24. VOID
  25. SetThreadFields(
  26. PSYSTEM_THREAD_INFORMATION ThreadInfo,
  27. HWND hwnd
  28. );
  29. VOID
  30. InitProcessList(HWND hwnd);
  31. int MyX = 0;
  32. int MyY = 0;
  33. int dxSuperTaskman;
  34. int dySuperTaskman;
  35. int dxScreen;
  36. int dyScreen;
  37. PSYSTEM_PROCESS_INFORMATION DlgProcessInfo;
  38. BOOL Refresh = TRUE;
  39. PUCHAR g_pLargeBuffer; // UCHAR LargeBuffer1[64*1024];
  40. DWORD g_dwBufSize;
  41. SYSTEM_TIMEOFDAY_INFORMATION RefreshTimeOfDayInfo;
  42. HANDLE hEvent;
  43. HANDLE hMutex;
  44. HANDLE hSemaphore;
  45. HANDLE hSection;
  46. CHAR LastProcess[256];
  47. CHAR LastThread[256];
  48. CHAR LastModule[256];
  49. CHAR Buffer[512];
  50. INT_PTR CALLBACK
  51. ExplodeDlgProc(
  52. HWND hwnd,
  53. UINT wMsg,
  54. WPARAM wParam,
  55. LPARAM lParam)
  56. {
  57. int nIndex;
  58. HWND ThreadList;
  59. HWND ProcessList;
  60. PSYSTEM_PROCESS_INFORMATION ProcessInfo;
  61. PSYSTEM_THREAD_INFORMATION ThreadInfo;
  62. HANDLE hProcess;
  63. switch (wMsg) {
  64. case WM_INITDIALOG:
  65. g_dwBufSize = BUFSIZE;
  66. g_pLargeBuffer = ( PUCHAR )malloc( sizeof( UCHAR ) * g_dwBufSize );
  67. if( g_pLargeBuffer == NULL )
  68. {
  69. EndDialog(hwnd, 0);
  70. return FALSE;
  71. }
  72. if (!RegisterHotKey(hwnd, 1, MOD_CONTROL | MOD_ALT, VK_ESCAPE) ) {
  73. EndDialog(hwnd, 0);
  74. return(FALSE);
  75. }
  76. ProcessInfo = NULL;
  77. DlgProcessInfo = ProcessInfo;
  78. wParam = 1;
  79. //
  80. // Tidy up the system menu
  81. //
  82. DeleteMenu(GetSystemMenu(hwnd, FALSE), SC_MAXIMIZE, MF_BYCOMMAND);
  83. DeleteMenu(GetSystemMenu(hwnd, FALSE), SC_SIZE, MF_BYCOMMAND);
  84. //
  85. // Hide acleditting controls if we can't handle them
  86. //
  87. if (!InitializeAclEditor()) {
  88. DbgPrint("PVIEW: Acl editor failed to initialize, ACL editting disabled\n");
  89. ShowWindow(GetDlgItem(hwnd, PXPLODE_SECURITY_GROUP), SW_HIDE);
  90. ShowWindow(GetDlgItem(hwnd, PXPLODE_PROCESS_ACL), SW_HIDE);
  91. ShowWindow(GetDlgItem(hwnd, PXPLODE_THREAD_ACL), SW_HIDE);
  92. ShowWindow(GetDlgItem(hwnd, PXPLODE_PROCESS_TOKEN_ACL), SW_HIDE);
  93. ShowWindow(GetDlgItem(hwnd, PXPLODE_THREAD_TOKEN_ACL), SW_HIDE);
  94. ShowWindow(GetDlgItem(hwnd, PXPLODE_TOKEN_GROUP), SW_HIDE);
  95. ShowWindow(GetDlgItem(hwnd, PXPLODE_PROCESS_TOKEN), SW_HIDE);
  96. ShowWindow(GetDlgItem(hwnd, PXPLODE_THREAD_TOKEN), SW_HIDE);
  97. }
  98. //
  99. // fall thru
  100. //
  101. case WM_HOTKEY:
  102. if ( wParam == 1 ) {
  103. PSYSTEM_PROCESS_INFORMATION ProcessInfo;
  104. NTSTATUS status;
  105. ULONG TotalOffset = 0;
  106. do
  107. {
  108. // re-read systemprocess info until we get the entire buffer ( if possible )
  109. status = NtQuerySystemInformation(
  110. SystemProcessInformation,
  111. ( PVOID )g_pLargeBuffer, // LargeBuffer1,
  112. g_dwBufSize, //sizeof(LargeBuffer1),
  113. NULL
  114. );
  115. if( status != STATUS_INFO_LENGTH_MISMATCH )
  116. {
  117. break;
  118. }
  119. ODS( "OnHotKey resizing g_pLargeBuffer\n" );
  120. g_dwBufSize *= 2;
  121. if( g_pLargeBuffer != NULL )
  122. {
  123. free( g_pLargeBuffer );
  124. }
  125. g_pLargeBuffer = ( PUCHAR )malloc( sizeof( UCHAR ) * g_dwBufSize );
  126. if( g_pLargeBuffer == NULL )
  127. {
  128. ODS( "Failed to re allocate mem in OnHotKey\n" );
  129. EndDialog( hwnd , 0 );
  130. return FALSE;
  131. }
  132. }while( 1 );
  133. if (!NT_SUCCESS(status)) {
  134. EndDialog(hwnd, 0);
  135. return(FALSE);
  136. }
  137. ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)g_pLargeBuffer;
  138. DlgProcessInfo = ProcessInfo;
  139. Refresh = TRUE;
  140. InitProcessList(hwnd);
  141. Refresh = FALSE;
  142. ProcessList = GetDlgItem(hwnd, PXPLODE_PROCESS_LIST);
  143. nIndex = (int)SendMessage(ProcessList, CB_GETCURSEL, 0, 0);
  144. ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)SendMessage(
  145. ProcessList,
  146. CB_GETITEMDATA,
  147. nIndex,
  148. 0
  149. );
  150. if ( !ProcessInfo || CB_ERR == (LONG_PTR)ProcessInfo ) {
  151. ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)g_pLargeBuffer;
  152. }
  153. DlgProcessInfo = ProcessInfo;
  154. SetProcessFields(ProcessInfo,hwnd);
  155. SetForegroundWindow(hwnd);
  156. ShowWindow(hwnd, SW_NORMAL);
  157. }
  158. return FALSE;
  159. case WM_SYSCOMMAND:
  160. switch (wParam & 0xfff0) {
  161. case SC_CLOSE:
  162. EndDialog(hwnd, 0);
  163. return(TRUE);
  164. }
  165. return(FALSE);
  166. case WM_COMMAND:
  167. switch(LOWORD(wParam)) {
  168. case PXPLODE_THREAD_LIST:
  169. switch ( HIWORD(wParam) ) {
  170. case LBN_DBLCLK:
  171. case LBN_SELCHANGE:
  172. ThreadList = GetDlgItem(hwnd, PXPLODE_THREAD_LIST);
  173. nIndex = (int)SendMessage(ThreadList, LB_GETCURSEL, 0, 0);
  174. ThreadInfo = (PSYSTEM_THREAD_INFORMATION)SendMessage(
  175. ThreadList,
  176. LB_GETITEMDATA,
  177. nIndex,
  178. 0
  179. );
  180. if ( !ThreadInfo || LB_ERR == (LONG_PTR)ThreadInfo ) {
  181. break;
  182. }
  183. SetThreadFields(ThreadInfo,hwnd);
  184. break;
  185. }
  186. break;
  187. case PXPLODE_IMAGE_COMMIT:
  188. switch ( HIWORD(wParam) ) {
  189. case CBN_DBLCLK:
  190. case CBN_SELCHANGE:
  191. UpdateImageCommit(hwnd);
  192. break;
  193. }
  194. break;
  195. case PXPLODE_PROCESS_LIST:
  196. ProcessList = GetDlgItem(hwnd, PXPLODE_PROCESS_LIST);
  197. switch ( HIWORD(wParam) ) {
  198. case CBN_DBLCLK:
  199. case CBN_SELCHANGE:
  200. nIndex = (int)SendMessage(ProcessList, CB_GETCURSEL, 0, 0);
  201. SendMessage(ProcessList, CB_GETLBTEXT, nIndex, (LPARAM)LastProcess);
  202. ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)SendMessage(
  203. ProcessList,
  204. CB_GETITEMDATA,
  205. nIndex,
  206. 0
  207. );
  208. if ( !ProcessInfo || CB_ERR == (LONG_PTR)ProcessInfo ) {
  209. break;
  210. }
  211. DlgProcessInfo = ProcessInfo;
  212. SetProcessFields(ProcessInfo,hwnd);
  213. break;
  214. }
  215. break;
  216. case PXPLODE_EXIT:
  217. EndDialog(hwnd, 0);
  218. break;
  219. case PXPLODE_PRIORITY_NORMAL:
  220. hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,HandleToUlong(DlgProcessInfo->UniqueProcessId));
  221. SetPriorityClass(hProcess,NORMAL_PRIORITY_CLASS);
  222. CloseHandle(hProcess);
  223. goto refresh;
  224. break;
  225. case PXPLODE_PRIORITY_HIGH:
  226. hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,HandleToUlong(DlgProcessInfo->UniqueProcessId));
  227. SetPriorityClass(hProcess,HIGH_PRIORITY_CLASS);
  228. CloseHandle(hProcess);
  229. goto refresh;
  230. break;
  231. case PXPLODE_PRIORITY_IDL:
  232. hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,HandleToUlong(DlgProcessInfo->UniqueProcessId));
  233. SetPriorityClass(hProcess,IDLE_PRIORITY_CLASS);
  234. CloseHandle(hProcess);
  235. goto refresh;
  236. break;
  237. case PXPLODE_HIDE:
  238. ShowWindow(hwnd,SW_HIDE);
  239. break;
  240. case PXPLODE_SHOWHEAPS:
  241. case PXPLODE_DUMPTOFILE:
  242. MessageBox(hwnd,"This function not implemented yet","Not Implemented",MB_ICONSTOP|MB_OK);
  243. break;
  244. case PXPLODE_PROCESS_ACL:
  245. case PXPLODE_PROCESS_TOKEN_ACL:
  246. case PXPLODE_PROCESS_TOKEN:
  247. {
  248. WCHAR Name[100];
  249. HANDLE Process;
  250. HANDLE Token;
  251. ProcessList = GetDlgItem(hwnd, PXPLODE_PROCESS_LIST);
  252. nIndex = (int)SendMessage(ProcessList, CB_GETCURSEL, 0, 0);
  253. ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)SendMessage(
  254. ProcessList,
  255. CB_GETITEMDATA,
  256. nIndex,
  257. 0
  258. );
  259. if ( !ProcessInfo || CB_ERR == (LONG_PTR)ProcessInfo ) {
  260. break;
  261. }
  262. SendMessageW(ProcessList, CB_GETLBTEXT, nIndex, (LPARAM)Name);
  263. switch(LOWORD(wParam)) {
  264. case PXPLODE_PROCESS_ACL:
  265. Process = OpenProcess(MAXIMUM_ALLOWED, FALSE, HandleToUlong(ProcessInfo->UniqueProcessId));
  266. if (Process != NULL) {
  267. EditNtObjectSecurity(hwnd, Process, Name);
  268. CloseHandle(Process);
  269. } else {
  270. DbgPrint("Failed to open process for max allowed, error = %d\n", GetLastError());
  271. }
  272. break;
  273. default:
  274. Process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, HandleToUlong(ProcessInfo->UniqueProcessId));
  275. if (Process != NULL) {
  276. if (OpenProcessToken(Process, MAXIMUM_ALLOWED, &Token)) {
  277. if (LOWORD(wParam) == PXPLODE_PROCESS_TOKEN_ACL) {
  278. EditNtObjectSecurity(hwnd, Token, Name);
  279. } else {
  280. HANDLE Token2;
  281. if (OpenProcessToken(Process, TOKEN_QUERY, &Token2)) {
  282. CloseHandle(Token2);
  283. EditToken(hwnd, Token, Name);
  284. } else {
  285. MessageBox(hwnd,
  286. "You do not have permission to view the token on this process",
  287. "Access Denied", MB_ICONSTOP | MB_OK);
  288. }
  289. }
  290. CloseHandle(Token);
  291. } else {
  292. MessageBox(hwnd,
  293. "You do not have permission to access the token on this process",
  294. "Access Denied", MB_ICONSTOP | MB_OK);
  295. }
  296. CloseHandle(Process);
  297. } else {
  298. DbgPrint("Failed to open process for query information, error = %d\n", GetLastError());
  299. }
  300. break;
  301. }
  302. break;
  303. }
  304. case PXPLODE_THREAD_ACL:
  305. case PXPLODE_THREAD_TOKEN_ACL:
  306. case PXPLODE_THREAD_TOKEN:
  307. {
  308. WCHAR Name[100];
  309. HANDLE Thread;
  310. HANDLE Token;
  311. ThreadList = GetDlgItem(hwnd, PXPLODE_THREAD_LIST);
  312. nIndex = (int)SendMessage(ThreadList, LB_GETCURSEL, 0, 0);
  313. ThreadInfo = (PSYSTEM_THREAD_INFORMATION)SendMessage(
  314. ThreadList,
  315. LB_GETITEMDATA,
  316. nIndex,
  317. 0
  318. );
  319. if ( !ThreadInfo || LB_ERR == (LONG_PTR)ThreadInfo ) {
  320. break;
  321. }
  322. SendMessageW(ThreadList, LB_GETTEXT, nIndex, (LPARAM)Name);
  323. switch(LOWORD(wParam)) {
  324. case PXPLODE_THREAD_ACL:
  325. Thread = OpenThread(MAXIMUM_ALLOWED, FALSE, HandleToUlong(ThreadInfo->ClientId.UniqueThread));
  326. if (Thread != NULL) {
  327. EditNtObjectSecurity(hwnd, Thread, Name);
  328. CloseHandle(Thread);
  329. } else {
  330. DbgPrint("Failed to open thread for max allowed, error = %d\n", GetLastError());
  331. }
  332. break;
  333. default:
  334. Thread = OpenThread(THREAD_QUERY_INFORMATION, FALSE, HandleToUlong(ThreadInfo->ClientId.UniqueThread));
  335. if (Thread != NULL) {
  336. if (OpenThreadToken(Thread, MAXIMUM_ALLOWED, TRUE, &Token)) {
  337. if (LOWORD(wParam) == PXPLODE_THREAD_TOKEN_ACL) {
  338. EditNtObjectSecurity(hwnd, Token, Name);
  339. } else {
  340. HANDLE Token2;
  341. if (OpenThreadToken(Thread, TOKEN_QUERY, TRUE, &Token2)) {
  342. CloseHandle(Token2);
  343. EditToken(hwnd, Token, Name);
  344. } else {
  345. MessageBox(hwnd,
  346. "You do not have permission to view the token on this thread",
  347. "Access Denied", MB_ICONSTOP | MB_OK);
  348. }
  349. }
  350. CloseHandle(Token);
  351. } else {
  352. DbgPrint("Failed to open thread token for max allowed, error = %d\n", GetLastError());
  353. }
  354. CloseHandle(Thread);
  355. } else {
  356. DbgPrint("Failed to open thread for query information, error = %d\n", GetLastError());
  357. }
  358. break;
  359. }
  360. break;
  361. }
  362. case PXPLODE_TERMINATE:
  363. hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,HandleToUlong(DlgProcessInfo->UniqueProcessId));
  364. wsprintf(Buffer,"Selecting OK will terminate %s... Do you really want to do this ?",LastProcess);
  365. if ( MessageBox(hwnd,Buffer,"Terminate Process",MB_ICONSTOP|MB_OKCANCEL) == IDOK ) {
  366. TerminateProcess(hProcess,99);
  367. }
  368. CloseHandle(hProcess);
  369. //
  370. // fall thru
  371. //
  372. case PXPLODE_REFRESH:
  373. refresh:
  374. {
  375. PSYSTEM_PROCESS_INFORMATION ProcessInfo;
  376. NTSTATUS status;
  377. ULONG TotalOffset = 0;
  378. ProcessList = GetDlgItem(hwnd, PXPLODE_PROCESS_LIST);
  379. do
  380. {
  381. status = NtQuerySystemInformation(
  382. SystemProcessInformation,
  383. ( PVOID )g_pLargeBuffer,
  384. g_dwBufSize,
  385. NULL
  386. );
  387. if( status != STATUS_INFO_LENGTH_MISMATCH )
  388. {
  389. break;
  390. }
  391. if( g_pLargeBuffer != NULL )
  392. {
  393. free( g_pLargeBuffer );
  394. }
  395. g_dwBufSize *= 2;
  396. g_pLargeBuffer = ( PUCHAR )malloc( sizeof( UCHAR ) * g_dwBufSize );
  397. if( g_pLargeBuffer == NULL )
  398. {
  399. ODS( "Failed to re allocate mem in OnPXPLODE_REFRESH\n" );
  400. EndDialog( hwnd , 0 );
  401. return FALSE;
  402. }
  403. }while( 1 );
  404. if (!NT_SUCCESS(status)) {
  405. ExitProcess(status);
  406. }
  407. ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)g_pLargeBuffer;
  408. DlgProcessInfo = ProcessInfo;
  409. Refresh = TRUE;
  410. InitProcessList(hwnd);
  411. Refresh = FALSE;
  412. nIndex = (int)SendMessage(ProcessList, CB_GETCURSEL, 0, 0);
  413. ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)SendMessage(
  414. ProcessList,
  415. CB_GETITEMDATA,
  416. nIndex,
  417. 0
  418. );
  419. if ( !ProcessInfo || CB_ERR == (LONG_PTR)ProcessInfo ) {
  420. ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)g_pLargeBuffer;
  421. }
  422. DlgProcessInfo = ProcessInfo;
  423. SetProcessFields(ProcessInfo,hwnd);
  424. }
  425. return FALSE;
  426. }
  427. default:
  428. return FALSE;
  429. }
  430. return TRUE;
  431. }
  432. int __cdecl main(
  433. int argc,
  434. char *argv[],
  435. char *envp[])
  436. {
  437. hEvent = CreateEvent(NULL,TRUE,TRUE,NULL);
  438. hSemaphore = CreateSemaphore(NULL,1,256,NULL);
  439. hMutex = CreateMutex(NULL,FALSE,NULL);
  440. hSection = CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_READWRITE,0,8192,NULL);
  441. DialogBoxParam(NULL,
  442. MAKEINTRESOURCE(PXPLODEDLG),
  443. NULL,
  444. ExplodeDlgProc,
  445. (LPARAM)0
  446. );
  447. if( g_pLargeBuffer != NULL )
  448. {
  449. ODS( "Freeing buffer\n" );
  450. free( g_pLargeBuffer );
  451. }
  452. return 0;
  453. argc;
  454. argv;
  455. envp;
  456. }
  457. VOID
  458. SetProcessFields(
  459. PSYSTEM_PROCESS_INFORMATION ProcessInfo,
  460. HWND hwnd
  461. )
  462. {
  463. TIME_FIELDS UserTime;
  464. TIME_FIELDS KernelTime;
  465. TIME_FIELDS RunTime;
  466. LARGE_INTEGER Time;
  467. CHAR TimeString[15];
  468. CHAR szTempField[MAXTASKNAMELEN];
  469. CHAR szTemp[80];
  470. HANDLE hProcess;
  471. HWND ThreadList,ProcessList;
  472. int i, nIndex;
  473. PSYSTEM_THREAD_INFORMATION ThreadInfo;
  474. PCHAR p;
  475. ANSI_STRING pname;
  476. pname.Buffer = NULL;
  477. hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,HandleToUlong(ProcessInfo->UniqueProcessId));
  478. //
  479. // Set process name and process id
  480. //
  481. if ( ProcessInfo->ImageName.Buffer ) {
  482. RtlUnicodeStringToAnsiString(&pname,(PUNICODE_STRING)&ProcessInfo->ImageName,TRUE);
  483. p = strrchr(pname.Buffer,'\\');
  484. if ( p ) {
  485. p++;
  486. }
  487. else {
  488. p = pname.Buffer;
  489. }
  490. }
  491. else {
  492. p = "System Process";
  493. }
  494. SetDlgItemText(
  495. hwnd,
  496. PXPLODE_IMAGENAME,
  497. p
  498. );
  499. SetDlgItemInt(
  500. hwnd,
  501. PXPLODE_PROCESS_ID,
  502. (UINT)HandleToUlong(ProcessInfo->UniqueProcessId),
  503. FALSE
  504. );
  505. if ( pname.Buffer ) {
  506. RtlFreeAnsiString(&pname);
  507. }
  508. //
  509. // Set process priority
  510. //
  511. if ( ProcessInfo->BasePriority < 7 ) {
  512. CheckRadioButton(hwnd,PXPLODE_PRIORITY_IDL,PXPLODE_PRIORITY_HIGH,PXPLODE_PRIORITY_IDL);
  513. }
  514. else if ( ProcessInfo->BasePriority < 10 ) {
  515. CheckRadioButton(hwnd,PXPLODE_PRIORITY_IDL,PXPLODE_PRIORITY_HIGH,PXPLODE_PRIORITY_NORMAL);
  516. }
  517. else {
  518. CheckRadioButton(hwnd,PXPLODE_PRIORITY_IDL,PXPLODE_PRIORITY_HIGH,PXPLODE_PRIORITY_HIGH);
  519. }
  520. //
  521. // Compute address space utilization
  522. //
  523. ComputeVaSpace(hwnd,hProcess);
  524. //
  525. // Compute runtimes
  526. //
  527. RtlTimeToTimeFields ( &ProcessInfo->UserTime, &UserTime);
  528. RtlTimeToTimeFields ( &ProcessInfo->KernelTime, &KernelTime);
  529. RtlTimeToTimeFields ( &ProcessInfo->UserTime, &UserTime);
  530. RtlTimeToTimeFields ( &ProcessInfo->KernelTime, &KernelTime);
  531. Time.QuadPart = RefreshTimeOfDayInfo.CurrentTime.QuadPart - ProcessInfo->CreateTime.QuadPart;
  532. RtlTimeToTimeFields ( &Time, &RunTime);
  533. wsprintf(TimeString,"%3ld:%02ld:%02ld.%03ld",
  534. RunTime.Hour,
  535. RunTime.Minute,
  536. RunTime.Second,
  537. RunTime.Milliseconds
  538. );
  539. SetDlgItemText(
  540. hwnd,
  541. PXPLODE_ELAPSED_TIME,
  542. TimeString
  543. );
  544. wsprintf(TimeString,"%3ld:%02ld:%02ld.%03ld",
  545. UserTime.Hour,
  546. UserTime.Minute,
  547. UserTime.Second,
  548. UserTime.Milliseconds
  549. );
  550. SetDlgItemText(
  551. hwnd,
  552. PXPLODE_USER_TIME,
  553. TimeString
  554. );
  555. wsprintf(TimeString,"%3ld:%02ld:%02ld.%03ld",
  556. KernelTime.Hour,
  557. KernelTime.Minute,
  558. KernelTime.Second,
  559. KernelTime.Milliseconds
  560. );
  561. SetDlgItemText(
  562. hwnd,
  563. PXPLODE_KERNEL_TIME,
  564. TimeString
  565. );
  566. //
  567. // Set I/O Counts
  568. //
  569. #if 0
  570. SetDlgItemInt(
  571. hwnd,
  572. PXPLODE_READ_XFER,
  573. ProcessInfo->ReadTransferCount.LowPart,
  574. FALSE
  575. );
  576. SetDlgItemInt(
  577. hwnd,
  578. PXPLODE_WRITE_XFER,
  579. ProcessInfo->WriteTransferCount.LowPart,
  580. FALSE
  581. );
  582. SetDlgItemInt(
  583. hwnd,
  584. PXPLODE_OTHER_XFER,
  585. ProcessInfo->OtherTransferCount.LowPart,
  586. FALSE
  587. );
  588. SetDlgItemInt(
  589. hwnd,
  590. PXPLODE_READ_OPS,
  591. ProcessInfo->ReadOperationCount,
  592. FALSE
  593. );
  594. SetDlgItemInt(
  595. hwnd,
  596. PXPLODE_WRITE_OPS,
  597. ProcessInfo->WriteOperationCount,
  598. FALSE
  599. );
  600. SetDlgItemInt(
  601. hwnd,
  602. PXPLODE_OTHER_OPS,
  603. ProcessInfo->OtherOperationCount,
  604. FALSE
  605. );
  606. #endif
  607. //
  608. // Set memory management stats
  609. //
  610. wsprintf(szTemp,"%d Kb",ProcessInfo->PeakVirtualSize/1024);
  611. SetDlgItemText(
  612. hwnd,
  613. PXPLODE_PEAK_VSIZE,
  614. szTemp
  615. );
  616. wsprintf(szTemp,"%d Kb",ProcessInfo->VirtualSize/1024);
  617. SetDlgItemText(
  618. hwnd,
  619. PXPLODE_VSIZE,
  620. szTemp
  621. );
  622. SetDlgItemInt(
  623. hwnd,
  624. PXPLODE_PFCOUNT,
  625. ProcessInfo->PageFaultCount,
  626. FALSE
  627. );
  628. wsprintf(szTemp,"%d Kb",(ProcessInfo->PeakWorkingSetSize)/1024);
  629. SetDlgItemText(
  630. hwnd,
  631. PXPLODE_PEAK_WS,
  632. szTemp
  633. );
  634. wsprintf(szTemp,"%d Kb",(ProcessInfo->WorkingSetSize)/1024);
  635. SetDlgItemText(
  636. hwnd,
  637. PXPLODE_WS,
  638. szTemp
  639. );
  640. wsprintf(szTemp,"%d Kb",(ProcessInfo->PeakPagefileUsage)/1024);
  641. SetDlgItemText(
  642. hwnd,
  643. PXPLODE_PEAK_PF,
  644. szTemp
  645. );
  646. wsprintf(szTemp,"%d Kb",(ProcessInfo->PagefileUsage)/1024);
  647. SetDlgItemText(
  648. hwnd,
  649. PXPLODE_PF,
  650. szTemp
  651. );
  652. wsprintf(szTemp,"%d Kb",(ProcessInfo->PrivatePageCount)/1024);
  653. SetDlgItemText(
  654. hwnd,
  655. PXPLODE_PRIVATE_PAGE,
  656. szTemp
  657. );
  658. wsprintf(szTemp,"%d Kb",ProcessInfo->QuotaPeakPagedPoolUsage/1024);
  659. SetDlgItemText(
  660. hwnd,
  661. PXPLODE_PEAK_PAGED,
  662. szTemp
  663. );
  664. wsprintf(szTemp,"%d Kb",ProcessInfo->QuotaPagedPoolUsage/1024);
  665. SetDlgItemText(
  666. hwnd,
  667. PXPLODE_PAGED,
  668. szTemp
  669. );
  670. wsprintf(szTemp,"%d Kb",ProcessInfo->QuotaPeakNonPagedPoolUsage/1024);
  671. SetDlgItemText(
  672. hwnd,
  673. PXPLODE_PEAK_NONPAGED,
  674. szTemp
  675. );
  676. wsprintf(szTemp,"%d Kb",ProcessInfo->QuotaNonPagedPoolUsage/1024);
  677. SetDlgItemText(
  678. hwnd,
  679. PXPLODE_NONPAGED,
  680. szTemp
  681. );
  682. wsprintf(szTemp,"%d Kb",ProcessInfo->QuotaPeakPagedPoolUsage/1024);
  683. SetDlgItemText(
  684. hwnd,
  685. PXPLODE_PEAK_PAGED,
  686. szTemp
  687. );
  688. //
  689. // Get the usage and limits
  690. //
  691. {
  692. NTSTATUS Status;
  693. POOLED_USAGE_AND_LIMITS PooledInfo;
  694. Status = NtQueryInformationProcess(
  695. hProcess,
  696. ProcessPooledUsageAndLimits,
  697. &PooledInfo,
  698. sizeof(PooledInfo),
  699. NULL
  700. );
  701. if ( !NT_SUCCESS(Status) ) {
  702. RtlZeroMemory(&PooledInfo,sizeof(PooledInfo));
  703. }
  704. //
  705. // non paged
  706. //
  707. wsprintf(szTempField,"%d Kb",
  708. PooledInfo.PeakNonPagedPoolUsage/1024
  709. );
  710. SetDlgItemText(
  711. hwnd,
  712. PXPLODE_QNONPEAK,
  713. szTempField
  714. );
  715. wsprintf(szTempField,"%d Kb",
  716. PooledInfo.NonPagedPoolUsage/1024
  717. );
  718. SetDlgItemText(
  719. hwnd,
  720. PXPLODE_QNONCUR,
  721. szTempField
  722. );
  723. if (PooledInfo.NonPagedPoolLimit != (SIZE_T)-1 ) {
  724. wsprintf(szTempField,"%d Kb",
  725. PooledInfo.NonPagedPoolLimit/1024
  726. );
  727. }
  728. else {
  729. strcpy(szTempField,"Unlimited");
  730. }
  731. SetDlgItemText(
  732. hwnd,
  733. PXPLODE_QNONLIM,
  734. szTempField
  735. );
  736. //
  737. // paged
  738. //
  739. wsprintf(szTempField,"%d Kb",
  740. PooledInfo.PeakPagedPoolUsage/1024
  741. );
  742. SetDlgItemText(
  743. hwnd,
  744. PXPLODE_QPGPEAK,
  745. szTempField
  746. );
  747. wsprintf(szTempField,"%d Kb",
  748. PooledInfo.PagedPoolUsage/1024
  749. );
  750. SetDlgItemText(
  751. hwnd,
  752. PXPLODE_QPGCUR,
  753. szTempField
  754. );
  755. if (PooledInfo.PagedPoolLimit != (SIZE_T)-1) {
  756. wsprintf(szTempField,"%d Kb",
  757. PooledInfo.PagedPoolLimit/1024
  758. );
  759. }
  760. else {
  761. strcpy(szTempField,"Unlimited");
  762. }
  763. SetDlgItemText(
  764. hwnd,
  765. PXPLODE_QPGLIM,
  766. szTempField
  767. );
  768. //
  769. // page file
  770. //
  771. wsprintf(szTempField,"%d Kb",
  772. PooledInfo.PeakPagefileUsage*4
  773. );
  774. SetDlgItemText(
  775. hwnd,
  776. PXPLODE_QPFPEAK,
  777. szTempField
  778. );
  779. wsprintf(szTempField,"%d Kb",
  780. PooledInfo.PagefileUsage*4
  781. );
  782. SetDlgItemText(
  783. hwnd,
  784. PXPLODE_QPFCUR,
  785. szTempField
  786. );
  787. if (PooledInfo.PagefileLimit != (SIZE_T)-1) {
  788. wsprintf(szTempField,"%d Kb",
  789. PooledInfo.PagefileLimit*4
  790. );
  791. }
  792. else {
  793. strcpy(szTempField,"Unlimited");
  794. }
  795. SetDlgItemText(
  796. hwnd,
  797. PXPLODE_QPFLIM,
  798. szTempField
  799. );
  800. }
  801. //
  802. // Locate the thread list box
  803. // and clear it
  804. //
  805. i = 0;
  806. ThreadList = GetDlgItem(hwnd, PXPLODE_THREAD_LIST);
  807. // SendMessage(ThreadList, WM_SETREDRAW, FALSE, 0);
  808. SendMessage(ThreadList, LB_RESETCONTENT, 0, 0);
  809. SendMessage(ThreadList, LB_SETITEMDATA, 0L, 0L);
  810. ThreadInfo = (PSYSTEM_THREAD_INFORMATION)(ProcessInfo + 1);
  811. while (i < (int)ProcessInfo->NumberOfThreads) {
  812. wsprintf(szTempField,"%d",
  813. ThreadInfo->ClientId.UniqueThread
  814. );
  815. nIndex = (int)SendMessage(
  816. ThreadList,
  817. LB_ADDSTRING,
  818. 0,
  819. (LPARAM)(LPSTR)szTempField
  820. );
  821. SendMessage(
  822. ThreadList,
  823. LB_SETITEMDATA,
  824. nIndex,
  825. (LPARAM)ThreadInfo
  826. );
  827. if ( i == 0 ) {
  828. SetThreadFields(ThreadInfo,hwnd);
  829. }
  830. ThreadInfo += 1;
  831. i += 1;
  832. }
  833. SendMessage(ThreadList, LB_SETCURSEL, 0, 0);
  834. SetDlgItemInt(
  835. hwnd,
  836. PXPLODE_THREAD_COUNT,
  837. ProcessInfo->NumberOfThreads,
  838. FALSE
  839. );
  840. // Redraw the list now that all items have been inserted.
  841. // SendMessage(ThreadList, WM_SETREDRAW, TRUE, 0);
  842. // InvalidateRect(ThreadList, NULL, TRUE);
  843. ProcessList = GetDlgItem(hwnd, PXPLODE_PROCESS_LIST);
  844. SetFocus(ProcessList);
  845. if ( hProcess ) {
  846. CloseHandle(hProcess);
  847. }
  848. //
  849. // If we can't get at the process (maybe it's process 0?)
  850. // then don't let people try and edit the security on it or it's token.
  851. //
  852. hProcess = OpenProcess(MAXIMUM_ALLOWED,FALSE,HandleToUlong(ProcessInfo->UniqueProcessId));
  853. EnableWindow(GetDlgItem(hwnd, PXPLODE_PROCESS_ACL), hProcess != NULL);
  854. EnableWindow(GetDlgItem(hwnd, PXPLODE_PROCESS_TOKEN), hProcess != NULL);
  855. EnableWindow(GetDlgItem(hwnd, PXPLODE_PROCESS_TOKEN_ACL), hProcess != NULL);
  856. if (hProcess) {
  857. CloseHandle(hProcess);
  858. }
  859. }
  860. VOID
  861. SetThreadFields(
  862. PSYSTEM_THREAD_INFORMATION ThreadInfo,
  863. HWND hwnd
  864. )
  865. {
  866. TIME_FIELDS UserTime;
  867. TIME_FIELDS KernelTime;
  868. TIME_FIELDS RunTime;
  869. LARGE_INTEGER Time;
  870. CHAR TimeString[15];
  871. CHAR StartString[32];
  872. HANDLE hThread;
  873. CONTEXT ThreadContext;
  874. NTSTATUS Status;
  875. OBJECT_ATTRIBUTES Obja;
  876. ULONG_PTR PcValue;
  877. //
  878. // Display the selected thread information
  879. //
  880. //
  881. // Compute runtimes
  882. //
  883. RtlTimeToTimeFields ( &ThreadInfo->UserTime, &UserTime);
  884. RtlTimeToTimeFields ( &ThreadInfo->KernelTime, &KernelTime);
  885. RtlTimeToTimeFields ( &ThreadInfo->UserTime, &UserTime);
  886. RtlTimeToTimeFields ( &ThreadInfo->KernelTime, &KernelTime);
  887. Time.QuadPart = RefreshTimeOfDayInfo.CurrentTime.QuadPart - ThreadInfo->CreateTime.QuadPart;
  888. RtlTimeToTimeFields ( &Time, &RunTime);
  889. wsprintf(TimeString,"%3ld:%02ld:%02ld.%03ld",
  890. RunTime.Hour,
  891. RunTime.Minute,
  892. RunTime.Second,
  893. RunTime.Milliseconds
  894. );
  895. SetDlgItemText(
  896. hwnd,
  897. PXPLODE_THREADELAPSED_TIME,
  898. TimeString
  899. );
  900. wsprintf(TimeString,"%3ld:%02ld:%02ld.%03ld",
  901. UserTime.Hour,
  902. UserTime.Minute,
  903. UserTime.Second,
  904. UserTime.Milliseconds
  905. );
  906. SetDlgItemText(
  907. hwnd,
  908. PXPLODE_THREADUSER_TIME,
  909. TimeString
  910. );
  911. wsprintf(TimeString,"%3ld:%02ld:%02ld.%03ld",
  912. KernelTime.Hour,
  913. KernelTime.Minute,
  914. KernelTime.Second,
  915. KernelTime.Milliseconds
  916. );
  917. SetDlgItemText(
  918. hwnd,
  919. PXPLODE_THREADKERNEL_TIME,
  920. TimeString
  921. );
  922. wsprintf(StartString,"0x%p",
  923. ThreadInfo->StartAddress
  924. );
  925. SetDlgItemText(
  926. hwnd,
  927. PXPLODE_THREAD_START,
  928. StartString
  929. );
  930. //
  931. // Do the priority Group
  932. //
  933. SetDlgItemInt(
  934. hwnd,
  935. PXPLODE_THREAD_DYNAMIC,
  936. ThreadInfo->Priority,
  937. FALSE
  938. );
  939. switch ( ThreadInfo->BasePriority - DlgProcessInfo->BasePriority ) {
  940. case 2:
  941. CheckRadioButton(
  942. hwnd,
  943. PXPLODE_THREAD_HIGHEST,
  944. PXPLODE_THREAD_LOWEST,
  945. PXPLODE_THREAD_HIGHEST
  946. );
  947. break;
  948. case 1:
  949. CheckRadioButton(
  950. hwnd,
  951. PXPLODE_THREAD_HIGHEST,
  952. PXPLODE_THREAD_LOWEST,
  953. PXPLODE_THREAD_ABOVE
  954. );
  955. break;
  956. case -1:
  957. CheckRadioButton(
  958. hwnd,
  959. PXPLODE_THREAD_HIGHEST,
  960. PXPLODE_THREAD_LOWEST,
  961. PXPLODE_THREAD_BELOW
  962. );
  963. break;
  964. case -2:
  965. CheckRadioButton(
  966. hwnd,
  967. PXPLODE_THREAD_HIGHEST,
  968. PXPLODE_THREAD_LOWEST,
  969. PXPLODE_THREAD_LOWEST
  970. );
  971. break;
  972. case 0:
  973. default:
  974. CheckRadioButton(
  975. hwnd,
  976. PXPLODE_THREAD_HIGHEST,
  977. PXPLODE_THREAD_LOWEST,
  978. PXPLODE_THREAD_NORMAL
  979. );
  980. break;
  981. }
  982. //
  983. // Complete thread information
  984. //
  985. SetDlgItemInt(
  986. hwnd,
  987. PXPLODE_THREAD_SWITCHES,
  988. ThreadInfo->ContextSwitches,
  989. FALSE
  990. );
  991. PcValue = 0;
  992. InitializeObjectAttributes(&Obja, NULL, 0, NULL, NULL);
  993. Status = NtOpenThread(
  994. &hThread,
  995. THREAD_GET_CONTEXT,
  996. &Obja,
  997. &ThreadInfo->ClientId
  998. );
  999. if ( NT_SUCCESS(Status) ) {
  1000. ThreadContext.ContextFlags = CONTEXT_CONTROL;
  1001. Status = NtGetContextThread(hThread,&ThreadContext);
  1002. NtClose(hThread);
  1003. if ( NT_SUCCESS(Status) ) {
  1004. PcValue = (ULONG_PTR) CONTEXT_TO_PROGRAM_COUNTER(&ThreadContext);
  1005. }
  1006. }
  1007. if ( PcValue ) {
  1008. wsprintf(StartString,"0x%p",
  1009. PcValue
  1010. );
  1011. SetDlgItemText(
  1012. hwnd,
  1013. PXPLODE_THREAD_PC,
  1014. StartString
  1015. );
  1016. }
  1017. else {
  1018. SetDlgItemText(
  1019. hwnd,
  1020. PXPLODE_THREAD_PC,
  1021. "Unknown"
  1022. );
  1023. }
  1024. //
  1025. // Disable the thread buttons if we can't get at the thread or it's token
  1026. //
  1027. {
  1028. HANDLE Thread;
  1029. HANDLE Token;
  1030. BOOL ThreadOK = FALSE;
  1031. BOOL GotToken = FALSE;
  1032. Thread = OpenThread(MAXIMUM_ALLOWED, FALSE, HandleToUlong(ThreadInfo->ClientId.UniqueThread));
  1033. if (Thread != NULL) {
  1034. ThreadOK = TRUE;
  1035. if (OpenThreadToken(Thread, MAXIMUM_ALLOWED, TRUE, &Token)) {
  1036. GotToken = TRUE;
  1037. CloseHandle(Token);
  1038. }
  1039. CloseHandle(Thread);
  1040. }
  1041. EnableWindow(GetDlgItem(hwnd, PXPLODE_THREAD_ACL), ThreadOK);
  1042. EnableWindow(GetDlgItem(hwnd, PXPLODE_THREAD_TOKEN), GotToken);
  1043. EnableWindow(GetDlgItem(hwnd, PXPLODE_THREAD_TOKEN_ACL), GotToken);
  1044. }
  1045. }
  1046. VOID
  1047. InitProcessList(HWND hwnd)
  1048. {
  1049. int nIndex,i,sel;
  1050. HWND ProcessList;
  1051. PSYSTEM_PROCESS_INFORMATION ProcessInfo;
  1052. PSYSTEM_THREAD_INFORMATION ThreadInfo;
  1053. char szTempField[MAXTASKNAMELEN];
  1054. POBJECT_TYPE_INFORMATION ObjectInfo;
  1055. WCHAR Buffer[ 256 ];
  1056. ULONG TotalOffset;
  1057. TIME_FIELDS RefreshTime;
  1058. CHAR TimeString[15];
  1059. PCHAR p;
  1060. ANSI_STRING pname;
  1061. NtQuerySystemInformation(
  1062. SystemTimeOfDayInformation,
  1063. &RefreshTimeOfDayInfo,
  1064. sizeof(SYSTEM_TIMEOFDAY_INFORMATION),
  1065. NULL
  1066. );
  1067. RtlTimeToTimeFields ( &RefreshTimeOfDayInfo.CurrentTime, &RefreshTime);
  1068. wsprintf(TimeString,"%3ld:%02ld:%02ld.%03ld",
  1069. RefreshTime.Hour,
  1070. RefreshTime.Minute,
  1071. RefreshTime.Second,
  1072. RefreshTime.Milliseconds
  1073. );
  1074. SetDlgItemText(
  1075. hwnd,
  1076. PXPLODE_REFRESH_TIME,
  1077. TimeString
  1078. );
  1079. //
  1080. // Compute ObjectCounts
  1081. //
  1082. ObjectInfo = (POBJECT_TYPE_INFORMATION)Buffer;
  1083. NtQueryObject( NtCurrentProcess(),
  1084. ObjectTypeInformation,
  1085. ObjectInfo,
  1086. sizeof( Buffer ),
  1087. NULL
  1088. );
  1089. wsprintf(szTempField,"Process Objects %d",ObjectInfo->TotalNumberOfObjects);
  1090. SetDlgItemText(
  1091. hwnd,
  1092. PXPLODE_PROCESS_OBJECT,
  1093. szTempField
  1094. );
  1095. NtQueryObject( NtCurrentThread(),
  1096. ObjectTypeInformation,
  1097. ObjectInfo,
  1098. sizeof( Buffer ),
  1099. NULL
  1100. );
  1101. wsprintf(szTempField,"Thread Objects %d",ObjectInfo->TotalNumberOfObjects);
  1102. SetDlgItemText(
  1103. hwnd,
  1104. PXPLODE_THREAD_OBJECT,
  1105. szTempField
  1106. );
  1107. NtQueryObject( hEvent,
  1108. ObjectTypeInformation,
  1109. ObjectInfo,
  1110. sizeof( Buffer ),
  1111. NULL
  1112. );
  1113. wsprintf(szTempField,"Event Objects %d",ObjectInfo->TotalNumberOfObjects);
  1114. SetDlgItemText(
  1115. hwnd,
  1116. PXPLODE_EVENT_OBJECT,
  1117. szTempField
  1118. );
  1119. NtQueryObject( hSemaphore,
  1120. ObjectTypeInformation,
  1121. ObjectInfo,
  1122. sizeof( Buffer ),
  1123. NULL
  1124. );
  1125. wsprintf(szTempField,"Semaphore Objects %d",ObjectInfo->TotalNumberOfObjects);
  1126. SetDlgItemText(
  1127. hwnd,
  1128. PXPLODE_SEMAPHORE_OBJECT,
  1129. szTempField
  1130. );
  1131. NtQueryObject( hMutex,
  1132. ObjectTypeInformation,
  1133. ObjectInfo,
  1134. sizeof( Buffer ),
  1135. NULL
  1136. );
  1137. wsprintf(szTempField,"Mutex Objects %d",ObjectInfo->TotalNumberOfObjects);
  1138. SetDlgItemText(
  1139. hwnd,
  1140. PXPLODE_MUTEX_OBJECT,
  1141. szTempField
  1142. );
  1143. NtQueryObject( hSection,
  1144. ObjectTypeInformation,
  1145. ObjectInfo,
  1146. sizeof( Buffer ),
  1147. NULL
  1148. );
  1149. wsprintf(szTempField,"Section Objects %d",ObjectInfo->TotalNumberOfObjects);
  1150. SetDlgItemText(
  1151. hwnd,
  1152. PXPLODE_SECTION_OBJECT,
  1153. szTempField
  1154. );
  1155. ProcessList = GetDlgItem(hwnd, PXPLODE_PROCESS_LIST);
  1156. // Don't redraw the list as items are deleted/inserted.
  1157. // SendMessage(ProcessList, WM_SETREDRAW, FALSE, 0);
  1158. SendMessage(ProcessList, CB_RESETCONTENT, 0, 0);
  1159. ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)g_pLargeBuffer;
  1160. SendMessage(ProcessList, CB_SETITEMDATA, 0L, 0L);
  1161. sel = -1;
  1162. TotalOffset = 0;
  1163. while (TRUE) {
  1164. pname.Buffer = NULL;
  1165. if ( ProcessInfo->ImageName.Buffer ) {
  1166. RtlUnicodeStringToAnsiString(&pname,(PUNICODE_STRING)&ProcessInfo->ImageName,TRUE);
  1167. p = strrchr(pname.Buffer,'\\');
  1168. if ( p ) {
  1169. p++;
  1170. }
  1171. else {
  1172. p = pname.Buffer;
  1173. }
  1174. }
  1175. else {
  1176. p = "System Process";
  1177. }
  1178. wsprintf(szTempField,"%d %s",
  1179. ProcessInfo->UniqueProcessId,
  1180. p
  1181. );
  1182. RtlFreeAnsiString(&pname);
  1183. nIndex = (int)SendMessage(
  1184. ProcessList,
  1185. CB_ADDSTRING,
  1186. 0,
  1187. (LPARAM)(LPSTR)szTempField
  1188. );
  1189. if ( DlgProcessInfo ) {
  1190. if ( ProcessInfo == DlgProcessInfo ) {
  1191. sel = nIndex;
  1192. }
  1193. }
  1194. else {
  1195. sel = 0;
  1196. }
  1197. SendMessage(
  1198. ProcessList,
  1199. CB_SETITEMDATA,
  1200. nIndex,
  1201. (LPARAM)ProcessInfo
  1202. );
  1203. i = 0;
  1204. ThreadInfo = (PSYSTEM_THREAD_INFORMATION)(ProcessInfo + 1);
  1205. while (i < (int)ProcessInfo->NumberOfThreads) {
  1206. ThreadInfo += 1;
  1207. i += 1;
  1208. }
  1209. if (ProcessInfo->NextEntryOffset == 0) {
  1210. break;
  1211. }
  1212. TotalOffset += ProcessInfo->NextEntryOffset;
  1213. ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)&g_pLargeBuffer[TotalOffset];
  1214. }
  1215. if ( LastProcess[0] ) {
  1216. nIndex = (int)SendMessage(ProcessList, CB_FINDSTRING, (WPARAM)-1, (LPARAM)LastProcess);
  1217. if ( nIndex != CB_ERR ) {
  1218. sel = nIndex;
  1219. }
  1220. }
  1221. SendMessage(ProcessList, CB_SETCURSEL, sel, 0);
  1222. SendMessage(ProcessList, CB_GETLBTEXT, sel, (LPARAM)LastProcess);
  1223. DlgProcessInfo = (PSYSTEM_PROCESS_INFORMATION)&g_pLargeBuffer[0];
  1224. // Redraw the list now that all items have been inserted.
  1225. // SendMessage(ProcessList, WM_SETREDRAW, TRUE, 0);
  1226. // InvalidateRect(ProcessList, NULL, TRUE);
  1227. }