5 * Copyright (c) 2000,2001 Emanuele Aliberti
7 #include <reactos/buildno.h>
8 #define WIN32_NO_STATUS
10 #define NTOS_MODE_USER
11 #include <ndk/ntndk.h>
18 #include <epsapi/epsapi.h>
22 #define PAGE_SIZE 4096
25 #define ALREADY_PROCESSED ((DWORD)-1)
27 LPWSTR ThreadStateName
[] =
40 void *PsaiMalloc(SIZE_T size
)
45 nErrCode
= NtAllocateVirtualMemory
55 if(NT_SUCCESS(nErrCode
)) return pBuf
;
59 void PsaiFree(void *ptr
)
63 NtFreeVirtualMemory(NtCurrentProcess(), &ptr
, &nSize
, MEM_RELEASE
);
66 int WINAPI
PrintBanner (VOID
)
68 printf ("ReactOS "KERNEL_RELEASE_STR
" T(ask)List\n");
69 printf ("Copyright (c) 2000,2001 Emanuele Aliberti\n\n");
73 int WINAPI
PrintSynopsys (int nRetVal
)
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");
83 int WINAPI
PrintLicense (VOID
)
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");
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");
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");
103 BOOL WINAPI
AcquirePrivileges (VOID
)
105 /* TODO: implement it */
110 ProcessHasDescendants (
112 PSYSTEM_PROCESS_INFORMATION pInfo
117 if (NULL
== pInfo
) return 0;
120 if (ALREADY_PROCESSED
!= (DWORD
)pInfo
->InheritedFromUniqueProcessId
)
122 if ((Pid
!= (HANDLE
)pInfo
->UniqueProcessId
) && (Pid
== (HANDLE
)pInfo
->InheritedFromUniqueProcessId
))
127 pInfo
= (PSYSTEM_PROCESS_INFORMATION
)((PBYTE
)pInfo
+ pInfo
->NextEntryOffset
);
129 } while (0 != pInfo
->NextEntryOffset
);
137 PSYSTEM_PROCESS_INFORMATION pInfo
,
142 *Module
= (pInfo
->ImageName
.Length
? pInfo
->ImageName
.Buffer
: L
"System process");
143 *Title
= L
""; /* TODO: check if the process has any window */
147 int WINAPI
PrintProcessInfoDepth (
148 PSYSTEM_PROCESS_INFORMATION pInfo
,
156 for (d
= 0; d
< Depth
; d
++) printf (" ");
157 GetProcessInfo (pInfo
, & Module
, & Title
);
161 pInfo
->UniqueProcessId
,
162 pInfo
->InheritedFromUniqueProcessId
,
169 PrintProcessAndDescendants (
170 PSYSTEM_PROCESS_INFORMATION pInfo
,
171 PSYSTEM_PROCESS_INFORMATION pInfoBase
,
177 if (NULL
== pInfo
) return EXIT_FAILURE
;
178 /* Print current pInfo process */
179 PrintProcessInfoDepth (pInfo
, Depth
++);
180 pInfo
->InheritedFromUniqueProcessId
= (HANDLE
)ALREADY_PROCESSED
;
181 /* Save current process' PID */
182 Pid
= pInfo
->UniqueProcessId
;
183 /* Scan and print possible children */
186 if (ALREADY_PROCESSED
!= (DWORD
)pInfo
->InheritedFromUniqueProcessId
)
188 if (Pid
== pInfo
->InheritedFromUniqueProcessId
)
190 if (ProcessHasDescendants (Pid
, pInfoBase
))
192 PrintProcessAndDescendants (
200 PrintProcessInfoDepth (pInfo
, Depth
);
201 pInfo
->InheritedFromUniqueProcessId
= (HANDLE
)ALREADY_PROCESSED
;
205 pInfo
= (PSYSTEM_PROCESS_INFORMATION
)((PBYTE
)pInfo
+ pInfo
->NextEntryOffset
);
207 } while (0 != pInfo
->NextEntryOffset
);
212 int WINAPI
PrintProcessList (BOOL DisplayTree
)
214 PSYSTEM_PROCESS_INFORMATION pInfo
= NULL
;
215 PSYSTEM_PROCESS_INFORMATION pInfoBase
= NULL
;
219 if (!NT_SUCCESS(PsaCaptureProcessesAndThreads(&pInfoBase
)))
222 pInfo
= PsaWalkFirstProcess(pInfoBase
);
226 if (FALSE
== DisplayTree
)
228 GetProcessInfo (pInfo
, & Module
, & Title
);
231 pInfo
->UniqueProcessId
,
234 pInfo
->InheritedFromUniqueProcessId
239 if (ALREADY_PROCESSED
!= (DWORD
)pInfo
->InheritedFromUniqueProcessId
)
241 PrintProcessAndDescendants (pInfo
, pInfoBase
, 0);
245 pInfo
= PsaWalkNextProcess(pInfo
);
248 PsaFreeCapture(pInfoBase
);
254 int WINAPI
PrintThreads (PSYSTEM_PROCESS_INFORMATION pInfo
)
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
;
265 if (NULL
== pInfo
) return EXIT_FAILURE
;
267 CurThread
= PsaWalkFirstThread(pInfo
);
269 wprintf (L
" NumberOfThreads: %d\n", pInfo
->NumberOfThreads
);
271 for (i
= 0; i
< pInfo
->NumberOfThreads
; i
++, CurThread
= PsaWalkNextThread(CurThread
))
273 Status
= NtOpenThread (
275 THREAD_QUERY_INFORMATION
,
277 & CurThread
->ClientId
279 if (!NT_SUCCESS(Status
))
284 Status
= NtQueryInformationThread (
286 ThreadBasicInformation
,
291 if (!NT_SUCCESS(Status
))
297 Status
= NtQueryInformationThread (
299 ThreadQuerySetWin32StartAddress
,
300 (PVOID
) & Win32StartAddress
,
301 sizeof Win32StartAddress
,
304 if (!NT_SUCCESS(Status
))
312 /* Now print the collected information */
313 wprintf (L
" %4d Win32StartAddr:0x%08x LastErr:0x%08x State:%s\n",
314 CurThread
->ClientId
.UniqueThread
,
316 0 /* FIXME: ((PTEB) tInfo.TebBaseAddress)->LastErrorValue */,
317 ThreadStateName
[CurThread
->ThreadState
]
323 int WINAPI
PrintModules (VOID
)
329 PSYSTEM_PROCESS_INFORMATION WINAPI
331 PSYSTEM_PROCESS_INFORMATION pInfoBase
,
335 if (NULL
== pInfoBase
) return NULL
;
337 pInfoBase
= PsaWalkFirstProcess(pInfoBase
);
341 if (Pid
== pInfoBase
->UniqueProcessId
)
346 pInfoBase
= PsaWalkNextProcess(pInfoBase
);
352 int WINAPI
PrintProcess (char * PidStr
)
356 OBJECT_ATTRIBUTES Oa
= {0};
357 CLIENT_ID ClientId
= {0, 0};
360 ClientId
.UniqueProcess
= (PVOID
) atol (PidStr
);
362 if (FALSE
== AcquirePrivileges ())
367 Status
= NtOpenProcess (
369 PROCESS_QUERY_INFORMATION
,
373 if (NT_SUCCESS(Status
))
375 ULONG ReturnLength
= 0;
376 PROCESS_BASIC_INFORMATION PsBasic
;
378 PSYSTEM_PROCESS_INFORMATION pInfo
= NULL
;
379 PSYSTEM_PROCESS_INFORMATION pInfoBase
= NULL
;
383 Status
= NtQueryInformationProcess (
385 ProcessBasicInformation
,
390 if (!NT_SUCCESS(Status
))
394 Status
= NtQueryInformationProcess (
401 if (!NT_SUCCESS(Status
))
406 if (!NT_SUCCESS(PsaCaptureProcessesAndThreads (&pInfoBase
)))
409 pInfo
= GetProcessInfoPid (pInfoBase
, ClientId
.UniqueProcess
);
410 if (NULL
== pInfo
) return EXIT_FAILURE
;
412 GetProcessInfo (pInfo
, & Module
, & Title
);
414 wprintf (L
"%4d %s\n", ClientId
.UniqueProcess
, Module
);
416 printf (" CWD: %s\n", ""); /* it won't appear if empty */
417 printf (" CmdLine: %s\n", ""); /* it won't appear if empty */
419 printf (" VirtualSize: %5ld kb PeakVirtualSize: %5ld kb\n",
420 ((LONG
) PsVm
.VirtualSize
/ 1024),
421 ((LONG
) PsVm
.PeakVirtualSize
/ 1024)
423 printf (" WorkingSetSize: %5ld kb PeakWorkingSetSize: %5ld kb\n",
424 ((LONG
) PsVm
.WorkingSetSize
/ 1024),
425 ((LONG
) PsVm
.PeakWorkingSetSize
/ 1024)
428 PrintThreads (pInfo
);
432 PsaFreeCapture(pInfoBase
);
442 int main (int argc
, char * argv
[])
446 if(1 == argc
) return PrintProcessList(FALSE
);
448 while((c
= getopt(argc
, argv
, "tl")) != -1)
452 case 't': return PrintProcessList(TRUE
);
453 case 'l': return PrintLicense();
454 default: return PrintSynopsys(EXIT_FAILURE
);
458 if(isdigit(argv
[optind
][0]))
459 return PrintProcess (argv
[1]);
461 return PrintSynopsys(EXIT_SUCCESS
);