1 /* 2 * ReactOS Project 3 * TList 4 * 5 * Copyright (c) 2000,2001 Emanuele Aliberti 6 */ 7 #include <reactos/buildno.h> 8 #define WIN32_NO_STATUS 9 #include <windows.h> 10 #define NTOS_MODE_USER 11 #include <ndk/ntndk.h> 12 13 #include <stdio.h> 14 #include <stdlib.h> 15 #include <string.h> 16 #include <ctype.h> 17 18 #include <epsapi/epsapi.h> 19 #include <getopt.h> 20 21 #ifndef PAGE_SIZE 22 #define PAGE_SIZE 4096 23 #endif 24 25 #define ALREADY_PROCESSED ((DWORD)-1) 26 27 LPWSTR ThreadStateName [] = 28 { 29 L"Initialized", 30 L"Ready", 31 L"Running", 32 L"Standby", 33 L"Terminated", 34 L"Wait", 35 L"Transition", 36 L"Unknown", 37 NULL 38 }; 39 40 void *PsaiMalloc(SIZE_T size) 41 { 42 void * pBuf = NULL; 43 NTSTATUS nErrCode; 44 45 nErrCode = NtAllocateVirtualMemory 46 ( 47 NtCurrentProcess(), 48 &pBuf, 49 0, 50 &size, 51 MEM_COMMIT, 52 PAGE_READWRITE 53 ); 54 55 if(NT_SUCCESS(nErrCode)) return pBuf; 56 else return NULL; 57 } 58 59 void PsaiFree(void *ptr) 60 { 61 SIZE_T nSize = 0; 62 63 NtFreeVirtualMemory(NtCurrentProcess(), &ptr, &nSize, MEM_RELEASE); 64 } 65 66 int WINAPI PrintBanner (VOID) 67 { 68 printf ("ReactOS "KERNEL_VERSION_STR" T(ask)List\n"); 69 printf ("Copyright (c) 2000,2001 Emanuele Aliberti\n\n"); 70 return EXIT_SUCCESS; 71 } 72 73 int WINAPI PrintSynopsys (int nRetVal) 74 { 75 PrintBanner (); 76 printf ("Usage: tlist [-t | PID | -l]\n\n" 77 " -t print the task list tree\n" 78 " PID print module information for this ID\n" 79 " -l print license information\n"); 80 return nRetVal; 81 } 82 83 int WINAPI PrintLicense (VOID) 84 { 85 PrintBanner (); 86 printf ( 87 "This program is free software; you can redistribute it and/or modify\n" 88 "it under the terms of the GNU General Public License as published by\n" 89 "the Free Software Foundation; either version 2 of the License, or\n" 90 "(at your option) any later version.\n\n"); 91 printf ( 92 "This program is distributed in the hope that it will be useful,\n" 93 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" 94 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" 95 "GNU General Public License for more details.\n\n"); 96 printf ( 97 "You should have received a copy of the GNU General Public License\n" 98 "along with this program; if not, write to the Free Software\n" 99 "Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n\n"); 100 return EXIT_SUCCESS; 101 } 102 103 BOOL WINAPI AcquirePrivileges (VOID) 104 { 105 /* TODO: implement it */ 106 return TRUE; 107 } 108 109 int WINAPI 110 ProcessHasDescendants ( 111 HANDLE Pid, 112 PSYSTEM_PROCESS_INFORMATION pInfo 113 ) 114 { 115 LONG Count = 0; 116 117 if (NULL == pInfo) return 0; 118 do { 119 120 if (ALREADY_PROCESSED != HandleToUlong(pInfo->InheritedFromUniqueProcessId)) 121 { 122 if ((Pid != (HANDLE)pInfo->UniqueProcessId) && (Pid == (HANDLE)pInfo->InheritedFromUniqueProcessId)) 123 { 124 ++ Count; 125 } 126 } 127 pInfo = (PSYSTEM_PROCESS_INFORMATION)((PBYTE)pInfo + pInfo->NextEntryOffset); 128 129 } while (0 != pInfo->NextEntryOffset); 130 131 return Count; 132 } 133 134 135 BOOL WINAPI 136 GetProcessInfo ( 137 PSYSTEM_PROCESS_INFORMATION pInfo, 138 LPWSTR * Module, 139 LPWSTR * Title 140 ) 141 { 142 *Module = (pInfo->ImageName.Length ? pInfo->ImageName.Buffer : L"System process"); 143 *Title = L""; /* TODO: check if the process has any window */ 144 return TRUE; 145 } 146 147 int WINAPI PrintProcessInfoDepth ( 148 PSYSTEM_PROCESS_INFORMATION pInfo, 149 LONG Depth 150 ) 151 { 152 INT d = 0; 153 LPWSTR Module = L""; 154 LPWSTR Title = L""; 155 156 for (d = 0; d < Depth; d ++) printf (" "); 157 GetProcessInfo (pInfo, & Module, & Title); 158 wprintf ( 159 L"%s (%d, %d) %s\n", 160 Module, 161 HandleToUlong(pInfo->UniqueProcessId), 162 HandleToUlong(pInfo->InheritedFromUniqueProcessId), 163 Title 164 ); 165 return EXIT_SUCCESS; 166 } 167 168 int WINAPI 169 PrintProcessAndDescendants ( 170 PSYSTEM_PROCESS_INFORMATION pInfo, 171 PSYSTEM_PROCESS_INFORMATION pInfoBase, 172 LONG Depth 173 ) 174 { 175 HANDLE Pid = 0; 176 177 if (NULL == pInfo) return EXIT_FAILURE; 178 /* Print current pInfo process */ 179 PrintProcessInfoDepth (pInfo, Depth ++); 180 pInfo->InheritedFromUniqueProcessId = UlongToHandle(ALREADY_PROCESSED); 181 /* Save current process' PID */ 182 Pid = pInfo->UniqueProcessId; 183 /* Scan and print possible children */ 184 do { 185 186 if (ALREADY_PROCESSED != HandleToUlong(pInfo->InheritedFromUniqueProcessId)) 187 { 188 if (Pid == pInfo->InheritedFromUniqueProcessId) 189 { 190 if (ProcessHasDescendants (Pid, pInfoBase)) 191 { 192 PrintProcessAndDescendants ( 193 pInfo, 194 pInfoBase, 195 Depth 196 ); 197 } 198 else 199 { 200 PrintProcessInfoDepth (pInfo, Depth); 201 pInfo->InheritedFromUniqueProcessId = UlongToHandle(ALREADY_PROCESSED); 202 } 203 } 204 } 205 pInfo = (PSYSTEM_PROCESS_INFORMATION)((PBYTE)pInfo + pInfo->NextEntryOffset); 206 207 } while (0 != pInfo->NextEntryOffset); 208 209 return EXIT_SUCCESS; 210 } 211 212 int WINAPI PrintProcessList (BOOL DisplayTree) 213 { 214 PSYSTEM_PROCESS_INFORMATION pInfo = NULL; 215 PSYSTEM_PROCESS_INFORMATION pInfoBase = NULL; 216 LPWSTR Module = L""; 217 LPWSTR Title = L""; 218 219 if (!NT_SUCCESS(PsaCaptureProcessesAndThreads(&pInfoBase))) 220 return EXIT_FAILURE; 221 222 pInfo = PsaWalkFirstProcess(pInfoBase); 223 224 while (pInfo) 225 { 226 if (FALSE == DisplayTree) 227 { 228 GetProcessInfo (pInfo, & Module, & Title); 229 wprintf ( 230 L"%4d %-16s %s (%04d)\n", 231 HandleToUlong(pInfo->UniqueProcessId), 232 Module, 233 Title, 234 HandleToUlong(pInfo->InheritedFromUniqueProcessId) 235 ); 236 } 237 else 238 { 239 if (ALREADY_PROCESSED != HandleToUlong(pInfo->InheritedFromUniqueProcessId)) 240 { 241 PrintProcessAndDescendants (pInfo, pInfoBase, 0); 242 } 243 } 244 245 pInfo = PsaWalkNextProcess(pInfo); 246 } 247 248 PsaFreeCapture(pInfoBase); 249 250 return EXIT_SUCCESS; 251 } 252 253 254 int WINAPI PrintThreads (PSYSTEM_PROCESS_INFORMATION pInfo) 255 { 256 ULONG i = 0; 257 NTSTATUS Status = STATUS_SUCCESS; 258 HANDLE hThread = INVALID_HANDLE_VALUE; 259 OBJECT_ATTRIBUTES Oa = {0}; 260 PVOID Win32StartAddress = NULL; 261 THREAD_BASIC_INFORMATION tInfo = {0}; 262 ULONG ReturnLength = 0; 263 PSYSTEM_THREAD_INFORMATION CurThread; 264 265 if (NULL == pInfo) return EXIT_FAILURE; 266 267 CurThread = PsaWalkFirstThread(pInfo); 268 269 wprintf (L" NumberOfThreads: %d\n", pInfo->NumberOfThreads); 270 271 for (i = 0; i < pInfo->NumberOfThreads; i ++, CurThread = PsaWalkNextThread(CurThread)) 272 { 273 Status = NtOpenThread ( 274 & hThread, 275 THREAD_QUERY_INFORMATION, 276 & Oa, 277 & CurThread->ClientId 278 ); 279 if (!NT_SUCCESS(Status)) 280 { 281 continue; 282 } 283 284 Status = NtQueryInformationThread ( 285 hThread, 286 ThreadBasicInformation, 287 (PVOID) & tInfo, 288 sizeof tInfo, 289 & ReturnLength 290 ); 291 if (!NT_SUCCESS(Status)) 292 { 293 NtClose (hThread); 294 continue; 295 } 296 297 Status = NtQueryInformationThread ( 298 hThread, 299 ThreadQuerySetWin32StartAddress, 300 (PVOID) & Win32StartAddress, 301 sizeof Win32StartAddress, 302 & ReturnLength 303 ); 304 if (!NT_SUCCESS(Status)) 305 { 306 NtClose (hThread); 307 continue; 308 } 309 310 NtClose (hThread); 311 312 /* Now print the collected information */ 313 wprintf (L" %4d Win32StartAddr:0x%p LastErr:0x%08x State:%s\n", 314 HandleToUlong(CurThread->ClientId.UniqueThread), 315 Win32StartAddress, 316 0 /* FIXME: ((PTEB) tInfo.TebBaseAddress)->LastErrorValue */, 317 ThreadStateName[CurThread->ThreadState] 318 ); 319 } 320 return EXIT_SUCCESS; 321 } 322 323 int WINAPI PrintModules (VOID) 324 { 325 /* TODO */ 326 return EXIT_SUCCESS; 327 } 328 329 PSYSTEM_PROCESS_INFORMATION WINAPI 330 GetProcessInfoPid ( 331 PSYSTEM_PROCESS_INFORMATION pInfoBase, 332 HANDLE Pid 333 ) 334 { 335 if (NULL == pInfoBase) return NULL; 336 337 pInfoBase = PsaWalkFirstProcess(pInfoBase); 338 339 while(pInfoBase) 340 { 341 if (Pid == pInfoBase->UniqueProcessId) 342 { 343 return pInfoBase; 344 } 345 346 pInfoBase = PsaWalkNextProcess(pInfoBase); 347 } 348 349 return NULL; 350 } 351 352 int WINAPI PrintProcess (char * PidStr) 353 { 354 NTSTATUS Status = 0; 355 HANDLE hProcess = 0; 356 OBJECT_ATTRIBUTES Oa = {0}; 357 CLIENT_ID ClientId = {0, 0}; 358 359 360 ClientId.UniqueProcess = UlongToHandle(atol (PidStr)); 361 362 if (FALSE == AcquirePrivileges ()) 363 { 364 return EXIT_FAILURE; 365 } 366 367 Status = NtOpenProcess ( 368 & hProcess, 369 PROCESS_QUERY_INFORMATION, 370 & Oa, 371 & ClientId 372 ); 373 if (NT_SUCCESS(Status)) 374 { 375 ULONG ReturnLength = 0; 376 PROCESS_BASIC_INFORMATION PsBasic; 377 VM_COUNTERS PsVm; 378 PSYSTEM_PROCESS_INFORMATION pInfo = NULL; 379 PSYSTEM_PROCESS_INFORMATION pInfoBase = NULL; 380 LPWSTR Module = L""; 381 LPWSTR Title = L""; 382 383 Status = NtQueryInformationProcess ( 384 hProcess, 385 ProcessBasicInformation, 386 & PsBasic, 387 sizeof (PsBasic), 388 & ReturnLength 389 ); 390 if (!NT_SUCCESS(Status)) 391 { 392 return EXIT_FAILURE; 393 } 394 Status = NtQueryInformationProcess ( 395 hProcess, 396 ProcessVmCounters, 397 & PsVm, 398 sizeof (PsVm), 399 & ReturnLength 400 ); 401 if (!NT_SUCCESS(Status)) 402 { 403 return EXIT_FAILURE; 404 } 405 406 if (!NT_SUCCESS(PsaCaptureProcessesAndThreads (&pInfoBase))) 407 return EXIT_FAILURE; 408 409 pInfo = GetProcessInfoPid (pInfoBase, ClientId.UniqueProcess); 410 if (NULL == pInfo) return EXIT_FAILURE; 411 412 GetProcessInfo (pInfo, & Module, & Title); 413 414 wprintf (L"%4d %s\n", HandleToUlong(ClientId.UniqueProcess), Module); 415 #if 0 416 printf (" CWD: %s\n", ""); /* it won't appear if empty */ 417 printf (" CmdLine: %s\n", ""); /* it won't appear if empty */ 418 #endif 419 printf (" VirtualSize: %5ld kb PeakVirtualSize: %5ld kb\n", 420 ((LONG) PsVm.VirtualSize / 1024), 421 ((LONG) PsVm.PeakVirtualSize / 1024) 422 ); 423 printf (" WorkingSetSize: %5ld kb PeakWorkingSetSize: %5ld kb\n", 424 ((LONG) PsVm.WorkingSetSize / 1024), 425 ((LONG) PsVm.PeakWorkingSetSize / 1024) 426 ); 427 428 PrintThreads (pInfo); 429 430 PrintModules (); 431 432 PsaFreeCapture(pInfoBase); 433 434 NtClose (hProcess); 435 436 return EXIT_SUCCESS; 437 } 438 return EXIT_FAILURE; 439 } 440 441 442 int main (int argc, char * argv []) 443 { 444 int c; 445 446 if(1 == argc) return PrintProcessList(FALSE); 447 448 while((c = getopt(argc, argv, "tl")) != -1) 449 { 450 switch(c) 451 { 452 case 't': return PrintProcessList(TRUE); 453 case 'l': return PrintLicense(); 454 default: return PrintSynopsys(EXIT_FAILURE); 455 } 456 } 457 458 if(isdigit(argv[optind][0])) 459 return PrintProcess (argv[1]); 460 461 return PrintSynopsys(EXIT_SUCCESS); 462 } 463 464 /* EOF */ 465