1 /* $Id: tlist.c,v 1.2 2002/09/03 18:44:18 chorns Exp $
6 * Copyright (c) 2000,2001 Emanuele Aliberti
8 #include <reactos/buildno.h>
18 #define PAGE_SIZE 4096
21 #define ALREADY_PROCESSED ((DWORD)-1)
23 LPWSTR ThreadStateName
[] =
38 int STDCALL
PrintBanner (VOID
)
40 printf ("ReactOS "KERNEL_RELEASE_STR
" T(ask)List\n");
41 printf ("Copyright (c) 2000,2001 Emanuele Aliberti\n\n");
45 int STDCALL
PrintSynopsys (VOID
)
48 printf ("Usage: tlist [-t | PID | -l]\n\n"
49 " -t print the task list tree\n"
50 " PID print module information for this ID\n"
51 " -l print license information\n");
55 int STDCALL
PrintLicense (VOID
)
59 "This program is free software; you can redistribute it and/or modify\n"
60 "it under the terms of the GNU General Public License as published by\n"
61 "the Free Software Foundation; either version 2 of the License, or\n"
62 "(at your option) any later version.\n\n");
64 "This program is distributed in the hope that it will be useful,\n"
65 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
66 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
67 "GNU General Public License for more details.\n\n");
69 "You should have received a copy of the GNU General Public License\n"
70 "along with this program; if not, write to the Free Software\n"
71 "Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n\n");
75 BOOL STDCALL
AcquirePrivileges (VOID
)
77 /* TODO: implement it */
81 PSYSTEM_PROCESS_INFORMATION STDCALL
82 GetProcessAndThreadsInfo (PULONG Size
)
84 NTSTATUS Status
= STATUS_SUCCESS
;
85 PSYSTEM_PROCESS_INFORMATION pInfo
= NULL
;
86 ULONG Length
= PAGE_SIZE
;
87 ULONG RequiredLength
= 0;
91 Status
= NtAllocateVirtualMemory (
96 (MEM_RESERVE
| MEM_COMMIT
),
99 if (!NT_SUCCESS(Status
) || (NULL
== pInfo
))
101 fprintf (stderr
, "%s(%d): Status = 0x%08lx\n",__FUNCTION__
,__LINE__
,Status
);
105 * Obtain required buffer size (well, try to...)
107 if (NtQuerySystemInformation (
108 SystemProcessesAndThreadsInformation
,
112 ) != STATUS_INFO_LENGTH_MISMATCH
)
116 NtFreeVirtualMemory (NtCurrentProcess(), (PVOID
)&pInfo
, & Length
, MEM_RELEASE
);
119 if (!NT_SUCCESS(Status
))
121 NtFreeVirtualMemory (NtCurrentProcess(), (PVOID
)&pInfo
, & Length
, MEM_RELEASE
);
132 ProcessHasDescendants (
134 PSYSTEM_PROCESS_INFORMATION pInfo
139 if (NULL
== pInfo
) return 0;
142 if (ALREADY_PROCESSED
!= pInfo
->ParentProcessId
)
144 if ((Pid
!= pInfo
->ProcessId
) && (Pid
== pInfo
->ParentProcessId
))
149 (PBYTE
) pInfo
+= pInfo
->RelativeOffset
;
151 } while (0 != pInfo
->RelativeOffset
);
159 PSYSTEM_PROCESS_INFORMATION pInfo
,
164 *Module
= (pInfo
->Name
.Length
? pInfo
->Name
.Buffer
: L
"System process");
165 *Title
= L
""; /* TODO: check if the process has any window */
169 int STDCALL
PrintProcessInfoDepth (
170 PSYSTEM_PROCESS_INFORMATION pInfo
,
178 for (d
= 0; d
< Depth
; d
++) printf (" ");
179 GetProcessInfo (pInfo
, & Module
, & Title
);
184 pInfo
->ParentProcessId
,
191 PrintProcessAndDescendants (
192 PSYSTEM_PROCESS_INFORMATION pInfo
,
193 PSYSTEM_PROCESS_INFORMATION pInfoBase
,
199 if (NULL
== pInfo
) return EXIT_FAILURE
;
200 /* Print current pInfo process */
201 PrintProcessInfoDepth (pInfo
, Depth
++);
202 pInfo
->ParentProcessId
= ALREADY_PROCESSED
;
203 /* Save current process' PID */
204 Pid
= pInfo
->ProcessId
;
205 /* Scan and print possible children */
208 if (ALREADY_PROCESSED
!= pInfo
->ParentProcessId
)
210 if (Pid
== pInfo
->ParentProcessId
)
212 if (ProcessHasDescendants (Pid
, pInfoBase
))
214 PrintProcessAndDescendants (
222 PrintProcessInfoDepth (pInfo
, Depth
);
223 pInfo
->ParentProcessId
= ALREADY_PROCESSED
;
227 (PBYTE
) pInfo
+= pInfo
->RelativeOffset
;
229 } while (0 != pInfo
->RelativeOffset
);
234 int STDCALL
PrintProcessList (BOOL DisplayTree
)
236 PSYSTEM_PROCESS_INFORMATION pInfo
= NULL
;
237 PSYSTEM_PROCESS_INFORMATION pInfoBase
= NULL
;
243 pInfo
= GetProcessAndThreadsInfo (& Length
);
244 if (NULL
== pInfo
) return EXIT_FAILURE
;
247 if (FALSE
== DisplayTree
)
249 GetProcessInfo (pInfo
, & Module
, & Title
);
255 pInfo
->ParentProcessId
260 if (ALREADY_PROCESSED
!= pInfo
->ParentProcessId
)
262 PrintProcessAndDescendants (pInfo
, pInfoBase
, 0);
265 (PBYTE
) pInfo
+= pInfo
->RelativeOffset
;
267 } while (0 != pInfo
->RelativeOffset
);
269 NtFreeVirtualMemory (
280 int STDCALL
PrintThreads (PSYSTEM_PROCESS_INFORMATION pInfo
)
282 ULONG ThreadIndex
= 0;
283 NTSTATUS Status
= STATUS_SUCCESS
;
284 HANDLE hThread
= INVALID_HANDLE_VALUE
;
285 OBJECT_ATTRIBUTES Oa
= {0};
286 PVOID Win32StartAddress
= NULL
;
287 THREAD_BASIC_INFORMATION tInfo
= {0};
288 ULONG ReturnLength
= 0;
290 if (NULL
== pInfo
) return EXIT_FAILURE
;
292 wprintf (L
" NumberOfThreads: %d\n", pInfo
->ThreadCount
);
294 for (ThreadIndex
= 0; ThreadIndex
< pInfo
->ThreadCount
; ThreadIndex
++)
296 Status
= NtOpenThread (
298 THREAD_QUERY_INFORMATION
,
300 & pInfo
->ThreadSysInfo
[ThreadIndex
].ClientId
302 if (!NT_SUCCESS(Status
))
307 Status
= NtQueryInformationThread (
309 ThreadBasicInformation
,
314 if (!NT_SUCCESS(Status
))
320 Status
= NtQueryInformationThread (
322 ThreadQuerySetWin32StartAddress
,
323 (PVOID
) & Win32StartAddress
,
324 sizeof Win32StartAddress
,
327 if (!NT_SUCCESS(Status
))
335 /* Now print the collected information */
336 wprintf (L
" %4d Win32StartAddr:0x%08x LastErr:0x%08x State:%s\n",
337 pInfo
->ThreadSysInfo
[ThreadIndex
].ClientId
.UniqueThread
,
339 0 /* FIXME: ((PTEB) tInfo.TebBaseAddress)->LastErrorValue */,
340 ThreadStateName
[pInfo
->ThreadSysInfo
[ThreadIndex
].State
]
346 int STDCALL
PrintModules (VOID
)
352 PSYSTEM_PROCESS_INFORMATION STDCALL
354 PSYSTEM_PROCESS_INFORMATION pInfoBase
,
358 if (NULL
== pInfoBase
) return NULL
;
361 if (Pid
== pInfoBase
->ProcessId
)
365 (PBYTE
) pInfoBase
+= pInfoBase
->RelativeOffset
;
367 } while (0 != pInfoBase
->RelativeOffset
);
372 int STDCALL
PrintProcess (char * PidStr
)
376 OBJECT_ATTRIBUTES Oa
= {0};
377 CLIENT_ID ClientId
= {0, 0};
380 ClientId
.UniqueProcess
= (PVOID
) atol (PidStr
);
382 if (FALSE
== AcquirePrivileges ())
387 Status
= NtOpenProcess (
389 PROCESS_QUERY_INFORMATION
,
393 if (NT_SUCCESS(Status
))
395 ULONG ReturnLength
= 0;
396 PROCESS_BASIC_INFORMATION PsBasic
;
398 PSYSTEM_PROCESS_INFORMATION pInfo
= NULL
;
399 PSYSTEM_PROCESS_INFORMATION pInfoBase
= NULL
;
400 LONG pInfoBaseLength
= 0;
404 Status
= NtQueryInformationProcess (
406 ProcessBasicInformation
,
411 if (!NT_SUCCESS(Status
))
415 Status
= NtQueryInformationProcess (
422 if (!NT_SUCCESS(Status
))
427 pInfoBase
= GetProcessAndThreadsInfo (& pInfoBaseLength
);
428 if (NULL
== pInfoBase
) return EXIT_FAILURE
;
430 pInfo
= GetProcessInfoPid (pInfoBase
, (DWORD
) ClientId
.UniqueProcess
);
431 if (NULL
== pInfo
) return EXIT_FAILURE
;
433 GetProcessInfo (pInfo
, & Module
, & Title
);
435 wprintf (L
"%4d %s\n", ClientId
.UniqueProcess
, Module
);
437 printf (" CWD: %s\n", ""); /* it won't appear if empty */
438 printf (" CmdLine: %s\n", ""); /* it won't appear if empty */
440 printf (" VirtualSize: %5ld kb PeakVirtualSize: %5ld kb\n",
441 ((LONG
) PsVm
.VirtualSize
/ 1024),
442 ((LONG
) PsVm
.PeakVirtualSize
/ 1024)
444 printf (" WorkingSetSize: %5ld kb PeakWorkingSetSize: %5ld kb\n",
445 ((LONG
) PsVm
.WorkingSetSize
/ 1024),
446 ((LONG
) PsVm
.PeakWorkingSetSize
/ 1024)
449 PrintThreads (pInfo
);
453 NtFreeVirtualMemory (
468 int main (int argc
, char * argv
[])
472 return PrintProcessList (FALSE
);
476 if (('-' == argv
[1][0]) && ('\0' == argv
[1][2]))
478 if ('t' == argv
[1][1])
480 return PrintProcessList (TRUE
);
482 if ('l' == argv
[1][1])
484 return PrintLicense ();
487 if (isdigit(argv
[1][0]))
489 return PrintProcess (argv
[1]);
492 return PrintSynopsys ();