Reactos
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
27LPWSTR 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
40void *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
59void PsaiFree(void *ptr)
60{
61 SIZE_T nSize = 0;
62
63 NtFreeVirtualMemory(NtCurrentProcess(), &ptr, &nSize, MEM_RELEASE);
64}
65
66int 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
73int 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
83int 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
103BOOL WINAPI AcquirePrivileges (VOID)
104{
105 /* TODO: implement it */
106 return TRUE;
107}
108
109int WINAPI
110ProcessHasDescendants (
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
135BOOL WINAPI
136GetProcessInfo (
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
147int 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
168int WINAPI
169PrintProcessAndDescendants (
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
212int 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
254int 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
323int WINAPI PrintModules (VOID)
324{
325 /* TODO */
326 return EXIT_SUCCESS;
327}
328
329PSYSTEM_PROCESS_INFORMATION WINAPI
330GetProcessInfoPid (
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
352int 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
442int 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 */