/* * ReactOS Project * TList * * Copyright (c) 2000,2001 Emanuele Aliberti */ #include #define WIN32_NO_STATUS #include #define NTOS_MODE_USER #include #include #include #include #include #include #include #ifndef PAGE_SIZE #define PAGE_SIZE 4096 #endif #define ALREADY_PROCESSED ((DWORD)-1) LPWSTR ThreadStateName [] = { L"Initialized", L"Ready", L"Running", L"Standby", L"Terminated", L"Wait", L"Transition", L"Unknown", NULL }; void *PsaiMalloc(SIZE_T size) { void * pBuf = NULL; NTSTATUS nErrCode; nErrCode = NtAllocateVirtualMemory ( NtCurrentProcess(), &pBuf, 0, (PULONG)&size, MEM_COMMIT, PAGE_READWRITE ); if(NT_SUCCESS(nErrCode)) return pBuf; else return NULL; } void PsaiFree(void *ptr) { ULONG nSize = 0; NtFreeVirtualMemory(NtCurrentProcess(), &ptr, &nSize, MEM_RELEASE); } int STDCALL PrintBanner (VOID) { printf ("ReactOS "KERNEL_RELEASE_STR" T(ask)List\n"); printf ("Copyright (c) 2000,2001 Emanuele Aliberti\n\n"); return EXIT_SUCCESS; } int STDCALL PrintSynopsys (int nRetVal) { PrintBanner (); printf ("Usage: tlist [-t | PID | -l]\n\n" " -t print the task list tree\n" " PID print module information for this ID\n" " -l print license information\n"); return nRetVal; } int STDCALL PrintLicense (VOID) { PrintBanner (); printf ( "This program is free software; you can redistribute it and/or modify\n" "it under the terms of the GNU General Public License as published by\n" "the Free Software Foundation; either version 2 of the License, or\n" "(at your option) any later version.\n\n"); printf ( "This program is distributed in the hope that it will be useful,\n" "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" "GNU General Public License for more details.\n\n"); printf ( "You should have received a copy of the GNU General Public License\n" "along with this program; if not, write to the Free Software\n" "Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n\n"); return EXIT_SUCCESS; } BOOL STDCALL AcquirePrivileges (VOID) { /* TODO: implement it */ return TRUE; } int STDCALL ProcessHasDescendants ( HANDLE Pid, PSYSTEM_PROCESS_INFORMATION pInfo ) { LONG Count = 0; if (NULL == pInfo) return 0; do { if (ALREADY_PROCESSED != (DWORD)pInfo->InheritedFromUniqueProcessId) { if ((Pid != (HANDLE)pInfo->UniqueProcessId) && (Pid == (HANDLE)pInfo->InheritedFromUniqueProcessId)) { ++ Count; } } pInfo = (PSYSTEM_PROCESS_INFORMATION)((PBYTE)pInfo + pInfo->NextEntryOffset); } while (0 != pInfo->NextEntryOffset); return Count; } BOOL STDCALL GetProcessInfo ( PSYSTEM_PROCESS_INFORMATION pInfo, LPWSTR * Module, LPWSTR * Title ) { *Module = (pInfo->ImageName.Length ? pInfo->ImageName.Buffer : L"System process"); *Title = L""; /* TODO: check if the process has any window */ return TRUE; } int STDCALL PrintProcessInfoDepth ( PSYSTEM_PROCESS_INFORMATION pInfo, LONG Depth ) { INT d = 0; LPWSTR Module = L""; LPWSTR Title = L""; for (d = 0; d < Depth; d ++) printf (" "); GetProcessInfo (pInfo, & Module, & Title); wprintf ( L"%s (%d, %d) %s\n", Module, pInfo->UniqueProcessId, pInfo->InheritedFromUniqueProcessId, Title ); return EXIT_SUCCESS; } int STDCALL PrintProcessAndDescendants ( PSYSTEM_PROCESS_INFORMATION pInfo, PSYSTEM_PROCESS_INFORMATION pInfoBase, LONG Depth ) { HANDLE Pid = 0; if (NULL == pInfo) return EXIT_FAILURE; /* Print current pInfo process */ PrintProcessInfoDepth (pInfo, Depth ++); pInfo->InheritedFromUniqueProcessId = (HANDLE)ALREADY_PROCESSED; /* Save current process' PID */ Pid = pInfo->UniqueProcessId; /* Scan and print possible children */ do { if (ALREADY_PROCESSED != (DWORD)pInfo->InheritedFromUniqueProcessId) { if (Pid == pInfo->InheritedFromUniqueProcessId) { if (ProcessHasDescendants (Pid, pInfoBase)) { PrintProcessAndDescendants ( pInfo, pInfoBase, Depth ); } else { PrintProcessInfoDepth (pInfo, Depth); pInfo->InheritedFromUniqueProcessId = (HANDLE)ALREADY_PROCESSED; } } } pInfo = (PSYSTEM_PROCESS_INFORMATION)((PBYTE)pInfo + pInfo->NextEntryOffset); } while (0 != pInfo->NextEntryOffset); return EXIT_SUCCESS; } int STDCALL PrintProcessList (BOOL DisplayTree) { PSYSTEM_PROCESS_INFORMATION pInfo = NULL; PSYSTEM_PROCESS_INFORMATION pInfoBase = NULL; LPWSTR Module = L""; LPWSTR Title = L""; if (!NT_SUCCESS(PsaCaptureProcessesAndThreads(&pInfoBase))) return EXIT_FAILURE; pInfo = PsaWalkFirstProcess(pInfoBase); while (pInfo) { if (FALSE == DisplayTree) { GetProcessInfo (pInfo, & Module, & Title); wprintf ( L"%4d %-16s %s\n", pInfo->UniqueProcessId, Module, Title, pInfo->InheritedFromUniqueProcessId ); } else { if (ALREADY_PROCESSED != (DWORD)pInfo->InheritedFromUniqueProcessId) { PrintProcessAndDescendants (pInfo, pInfoBase, 0); } } pInfo = PsaWalkNextProcess(pInfo); } PsaFreeCapture(pInfoBase); return EXIT_SUCCESS; } int STDCALL PrintThreads (PSYSTEM_PROCESS_INFORMATION pInfo) { ULONG i = 0; NTSTATUS Status = STATUS_SUCCESS; HANDLE hThread = INVALID_HANDLE_VALUE; OBJECT_ATTRIBUTES Oa = {0}; PVOID Win32StartAddress = NULL; THREAD_BASIC_INFORMATION tInfo = {0}; ULONG ReturnLength = 0; PSYSTEM_THREAD_INFORMATION CurThread; if (NULL == pInfo) return EXIT_FAILURE; CurThread = PsaWalkFirstThread(pInfo); wprintf (L" NumberOfThreads: %d\n", pInfo->NumberOfThreads); for (i = 0; i < pInfo->NumberOfThreads; i ++, CurThread = PsaWalkNextThread(CurThread)) { Status = NtOpenThread ( & hThread, THREAD_QUERY_INFORMATION, & Oa, & CurThread->ClientId ); if (!NT_SUCCESS(Status)) { continue; } Status = NtQueryInformationThread ( hThread, ThreadBasicInformation, (PVOID) & tInfo, sizeof tInfo, & ReturnLength ); if (!NT_SUCCESS(Status)) { NtClose (hThread); continue; } Status = NtQueryInformationThread ( hThread, ThreadQuerySetWin32StartAddress, (PVOID) & Win32StartAddress, sizeof Win32StartAddress, & ReturnLength ); if (!NT_SUCCESS(Status)) { NtClose (hThread); continue; } NtClose (hThread); /* Now print the collected information */ wprintf (L" %4d Win32StartAddr:0x%08x LastErr:0x%08x State:%s\n", CurThread->ClientId.UniqueThread, Win32StartAddress, 0 /* FIXME: ((PTEB) tInfo.TebBaseAddress)->LastErrorValue */, ThreadStateName[CurThread->ThreadState] ); } return EXIT_SUCCESS; } int STDCALL PrintModules (VOID) { /* TODO */ return EXIT_SUCCESS; } PSYSTEM_PROCESS_INFORMATION STDCALL GetProcessInfoPid ( PSYSTEM_PROCESS_INFORMATION pInfoBase, HANDLE Pid ) { if (NULL == pInfoBase) return NULL; pInfoBase = PsaWalkFirstProcess(pInfoBase); while(pInfoBase) { if (Pid == pInfoBase->UniqueProcessId) { return pInfoBase; } pInfoBase = PsaWalkNextProcess(pInfoBase); } return NULL; } int STDCALL PrintProcess (char * PidStr) { NTSTATUS Status = 0; HANDLE hProcess = 0; OBJECT_ATTRIBUTES Oa = {0}; CLIENT_ID ClientId = {0, 0}; ClientId.UniqueProcess = (PVOID) atol (PidStr); if (FALSE == AcquirePrivileges ()) { return EXIT_FAILURE; } Status = NtOpenProcess ( & hProcess, PROCESS_QUERY_INFORMATION, & Oa, & ClientId ); if (NT_SUCCESS(Status)) { ULONG ReturnLength = 0; PROCESS_BASIC_INFORMATION PsBasic; VM_COUNTERS PsVm; PSYSTEM_PROCESS_INFORMATION pInfo = NULL; PSYSTEM_PROCESS_INFORMATION pInfoBase = NULL; LPWSTR Module = L""; LPWSTR Title = L""; Status = NtQueryInformationProcess ( hProcess, ProcessBasicInformation, & PsBasic, sizeof (PsBasic), & ReturnLength ); if (!NT_SUCCESS(Status)) { return EXIT_FAILURE; } Status = NtQueryInformationProcess ( hProcess, ProcessVmCounters, & PsVm, sizeof (PsVm), & ReturnLength ); if (!NT_SUCCESS(Status)) { return EXIT_FAILURE; } if (!NT_SUCCESS(PsaCaptureProcessesAndThreads (&pInfoBase))) return EXIT_FAILURE; pInfo = GetProcessInfoPid (pInfoBase, ClientId.UniqueProcess); if (NULL == pInfo) return EXIT_FAILURE; GetProcessInfo (pInfo, & Module, & Title); wprintf (L"%4d %s\n", ClientId.UniqueProcess, Module); #if 0 printf (" CWD: %s\n", ""); /* it won't appear if empty */ printf (" CmdLine: %s\n", ""); /* it won't appear if empty */ #endif printf (" VirtualSize: %5ld kb PeakVirtualSize: %5ld kb\n", ((LONG) PsVm.VirtualSize / 1024), ((LONG) PsVm.PeakVirtualSize / 1024) ); printf (" WorkingSetSize: %5ld kb PeakWorkingSetSize: %5ld kb\n", ((LONG) PsVm.WorkingSetSize / 1024), ((LONG) PsVm.PeakWorkingSetSize / 1024) ); PrintThreads (pInfo); PrintModules (); PsaFreeCapture(pInfoBase); NtClose (hProcess); return EXIT_SUCCESS; } return EXIT_FAILURE; } int main (int argc, char * argv []) { int c; if(1 == argc) return PrintProcessList(FALSE); while((c = getopt(argc, argv, "tl")) != -1) { switch(c) { case 't': return PrintProcessList(TRUE); case 'l': return PrintLicense(); default: return PrintSynopsys(EXIT_FAILURE); } } if(isdigit(argv[optind][0])) return PrintProcess (argv[1]); return PrintSynopsys(EXIT_SUCCESS); } /* EOF */