1*c2c66affSColin Finck /*
2*c2c66affSColin Finck  *  ReactOS ps - process list console viewer
3*c2c66affSColin Finck  *
4*c2c66affSColin Finck  *  ps.c
5*c2c66affSColin Finck  *
6*c2c66affSColin Finck  *  This program is free software; you can redistribute it and/or modify
7*c2c66affSColin Finck  *  it under the terms of the GNU General Public License as published by
8*c2c66affSColin Finck  *  the Free Software Foundation; either version 2 of the License, or
9*c2c66affSColin Finck  *  (at your option) any later version.
10*c2c66affSColin Finck  *
11*c2c66affSColin Finck  *  This program is distributed in the hope that it will be useful,
12*c2c66affSColin Finck  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13*c2c66affSColin Finck  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*c2c66affSColin Finck  *  GNU General Public License for more details.
15*c2c66affSColin Finck  *
16*c2c66affSColin Finck  *  You should have received a copy of the GNU General Public License
17*c2c66affSColin Finck  *  along with this program; if not, write to the Free Software
18*c2c66affSColin Finck  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19*c2c66affSColin Finck  */
20*c2c66affSColin Finck /*
21*c2c66affSColin Finck     Thanks to Filip Navara patch for fixing the Xp crash problem.
22*c2c66affSColin Finck */
23*c2c66affSColin Finck 
24*c2c66affSColin Finck #define NTOS_MODE_USER
25*c2c66affSColin Finck #define WIN32_NO_STATUS
26*c2c66affSColin Finck #include <windows.h>
27*c2c66affSColin Finck #include <ndk/ntndk.h>
28*c2c66affSColin Finck 
29*c2c66affSColin Finck typedef struct _SYSTEM_THREADS
30*c2c66affSColin Finck  {
31*c2c66affSColin Finck     LARGE_INTEGER KernelTime;
32*c2c66affSColin Finck     LARGE_INTEGER UserTime;
33*c2c66affSColin Finck     LARGE_INTEGER CreateTime;
34*c2c66affSColin Finck     ULONG WaitTime;
35*c2c66affSColin Finck     PVOID StartAddress;
36*c2c66affSColin Finck     CLIENT_ID ClientId;
37*c2c66affSColin Finck     KPRIORITY Priority;
38*c2c66affSColin Finck     LONG BasePriority;
39*c2c66affSColin Finck     ULONG ContextSwitches;
40*c2c66affSColin Finck     ULONG ThreadState;
41*c2c66affSColin Finck     ULONG WaitReason;
42*c2c66affSColin Finck  } SYSTEM_THREADS, *PSYSTEM_THREADS;
43*c2c66affSColin Finck 
44*c2c66affSColin Finck  typedef struct _SYSTEM_PROCESSES
45*c2c66affSColin Finck  {
46*c2c66affSColin Finck     ULONG NextEntryOffset;
47*c2c66affSColin Finck     ULONG NumberOfThreads;
48*c2c66affSColin Finck     LARGE_INTEGER SpareLi1;
49*c2c66affSColin Finck     LARGE_INTEGER SpareLi2;
50*c2c66affSColin Finck     LARGE_INTEGER SpareLi3;
51*c2c66affSColin Finck     LARGE_INTEGER CreateTime;
52*c2c66affSColin Finck     LARGE_INTEGER UserTime;
53*c2c66affSColin Finck     LARGE_INTEGER KernelTime;
54*c2c66affSColin Finck     UNICODE_STRING ImageName;
55*c2c66affSColin Finck     KPRIORITY BasePriority;
56*c2c66affSColin Finck     HANDLE UniqueProcessId;
57*c2c66affSColin Finck     HANDLE InheritedFromUniqueProcessId;
58*c2c66affSColin Finck     ULONG HandleCount;
59*c2c66affSColin Finck     ULONG SessionId;
60*c2c66affSColin Finck     ULONG PageDirectoryFrame;
61*c2c66affSColin Finck 
62*c2c66affSColin Finck     /*
63*c2c66affSColin Finck      * This part corresponds to VM_COUNTERS_EX.
64*c2c66affSColin Finck      * NOTE: *NOT* THE SAME AS VM_COUNTERS!
65*c2c66affSColin Finck      */
66*c2c66affSColin Finck     ULONG PeakVirtualSize;
67*c2c66affSColin Finck     ULONG VirtualSize;
68*c2c66affSColin Finck     ULONG PageFaultCount;
69*c2c66affSColin Finck     ULONG PeakWorkingSetSize;
70*c2c66affSColin Finck     ULONG WorkingSetSize;
71*c2c66affSColin Finck     ULONG QuotaPeakPagedPoolUsage;
72*c2c66affSColin Finck     ULONG QuotaPagedPoolUsage;
73*c2c66affSColin Finck     ULONG QuotaPeakNonPagedPoolUsage;
74*c2c66affSColin Finck     ULONG QuotaNonPagedPoolUsage;
75*c2c66affSColin Finck     ULONG PagefileUsage;
76*c2c66affSColin Finck     ULONG PeakPagefileUsage;
77*c2c66affSColin Finck     ULONG PrivateUsage;
78*c2c66affSColin Finck 
79*c2c66affSColin Finck     /* This part corresponds to IO_COUNTERS */
80*c2c66affSColin Finck     LARGE_INTEGER ReadOperationCount;
81*c2c66affSColin Finck     LARGE_INTEGER WriteOperationCount;
82*c2c66affSColin Finck     LARGE_INTEGER OtherOperationCount;
83*c2c66affSColin Finck     LARGE_INTEGER ReadTransferCount;
84*c2c66affSColin Finck     LARGE_INTEGER WriteTransferCount;
85*c2c66affSColin Finck     LARGE_INTEGER OtherTransferCount;
86*c2c66affSColin Finck 
87*c2c66affSColin Finck          SYSTEM_THREADS       Threads [1];
88*c2c66affSColin Finck  } SYSTEM_PROCESSES, *PSYSTEM_PROCESSES;
89*c2c66affSColin Finck 
90*c2c66affSColin Finck 
91*c2c66affSColin Finck //                     x00000000 00000000 000:00:00  000:00:00 ()
92*c2c66affSColin Finck static char title[]  = "P     PID     PPID     KTime      UTime   NAME\n";
93*c2c66affSColin Finck static char title1[] = "t              TID     KTime      UTime   State      WaitResson\n";
94*c2c66affSColin Finck static char title2[] = "w     PID     Hwnd  WndStile        TID   WndName\n";
95*c2c66affSColin Finck 
96*c2c66affSColin Finck 
97*c2c66affSColin Finck struct status {
98*c2c66affSColin Finck     DWORD state;
99*c2c66affSColin Finck     const char  desc[10];
100*c2c66affSColin Finck }   thread_stat[8 + 1] = {
101*c2c66affSColin Finck     {0,	"Init      "},
102*c2c66affSColin Finck     {1,	"Ready     "},
103*c2c66affSColin Finck     {2,	"Running   "},
104*c2c66affSColin Finck     {3,	"Standby   "},
105*c2c66affSColin Finck     {4,	"Terminated"},
106*c2c66affSColin Finck     {5,	"Wait      "},
107*c2c66affSColin Finck     {6,	"Transition"},
108*c2c66affSColin Finck     {7, "Unknown   "},
109*c2c66affSColin Finck     {-1,"    ?     "}
110*c2c66affSColin Finck };
111*c2c66affSColin Finck 
112*c2c66affSColin Finck struct waitres {
113*c2c66affSColin Finck     DWORD state;
114*c2c66affSColin Finck     char  desc[17];
115*c2c66affSColin Finck }   waitreason[35 + 1] = {
116*c2c66affSColin Finck    {0, "Executive        "},
117*c2c66affSColin Finck    {1, "FreePage         "},
118*c2c66affSColin Finck    {2, "PageIn           "},
119*c2c66affSColin Finck    {3, "PoolAllocation   "},
120*c2c66affSColin Finck    {4, "DelayExecution   "},
121*c2c66affSColin Finck    {5, "Suspended        "},
122*c2c66affSColin Finck    {6, "UserRequest      "},
123*c2c66affSColin Finck    {7, "WrExecutive      "},
124*c2c66affSColin Finck    {8, "WrFreePage       "},
125*c2c66affSColin Finck    {9, "WrPageIn         "},
126*c2c66affSColin Finck    {10,"WrPoolAllocation "},
127*c2c66affSColin Finck    {11,"WrDelayExecution "},
128*c2c66affSColin Finck    {12,"WrSuspended      "},
129*c2c66affSColin Finck    {13,"WrUserRequest    "},
130*c2c66affSColin Finck    {14,"WrEventPair      "},
131*c2c66affSColin Finck    {15,"WrQueue          "},
132*c2c66affSColin Finck    {16,"WrLpcReceive     "},
133*c2c66affSColin Finck    {17,"WrLpcReply       "},
134*c2c66affSColin Finck    {18,"WrVirtualMemory  "},
135*c2c66affSColin Finck    {19,"WrPageOut        "},
136*c2c66affSColin Finck    {20,"WrRendezvous     "},
137*c2c66affSColin Finck    {21,"Spare2           "},
138*c2c66affSColin Finck    {22,"WrGuardedMutex   "},
139*c2c66affSColin Finck    {23,"Spare4           "},
140*c2c66affSColin Finck    {24,"Spare5           "},
141*c2c66affSColin Finck    {25,"Spare6           "},
142*c2c66affSColin Finck    {26,"WrKernel         "},
143*c2c66affSColin Finck    {27,"WrResource       "},
144*c2c66affSColin Finck    {28,"WrPushLock       "},
145*c2c66affSColin Finck    {29,"WrMutex          "},
146*c2c66affSColin Finck    {30,"WrQuantumEnd     "},
147*c2c66affSColin Finck    {31,"WrDispatchInt    "},
148*c2c66affSColin Finck    {32,"WrPreempted      "},
149*c2c66affSColin Finck    {33,"WrYieldExecution "},
150*c2c66affSColin Finck    {34,"MaximumWaitReason"},
151*c2c66affSColin Finck    {-1,"       ?         "}
152*c2c66affSColin Finck };
153*c2c66affSColin Finck 
154*c2c66affSColin Finck static BOOL CALLBACK
EnumThreadProc(HWND hwnd,LPARAM lp)155*c2c66affSColin Finck EnumThreadProc(HWND hwnd, LPARAM lp)
156*c2c66affSColin Finck {
157*c2c66affSColin Finck 	DWORD r, pid, tid;
158*c2c66affSColin Finck 	LONG style;
159*c2c66affSColin Finck 	char buf[256];
160*c2c66affSColin Finck     HANDLE Stdout = GetStdHandle(STD_OUTPUT_HANDLE);
161*c2c66affSColin Finck 
162*c2c66affSColin Finck 	GetWindowText(hwnd, (LPTSTR)lp, 30);
163*c2c66affSColin Finck 
164*c2c66affSColin Finck 	if(hwnd != 0)
165*c2c66affSColin Finck 	{
166*c2c66affSColin Finck 	style = GetWindowLong(hwnd, GWL_STYLE);
167*c2c66affSColin Finck 
168*c2c66affSColin Finck 	tid = GetWindowThreadProcessId(hwnd, &pid);
169*c2c66affSColin Finck 
170*c2c66affSColin Finck 	wsprintf (buf,"w%8d %8x  %08x   %8d   %s\n",pid, hwnd , style, tid, lp );
171*c2c66affSColin Finck        	WriteFile(Stdout, buf, lstrlen(buf), &r, NULL);
172*c2c66affSColin Finck        	}
173*c2c66affSColin Finck 	return (TRUE);
174*c2c66affSColin Finck }
175*c2c66affSColin Finck 
main()176*c2c66affSColin Finck int main()
177*c2c66affSColin Finck {
178*c2c66affSColin Finck     DWORD r;
179*c2c66affSColin Finck     ANSI_STRING astring;
180*c2c66affSColin Finck     HANDLE Stdout = GetStdHandle(STD_OUTPUT_HANDLE);
181*c2c66affSColin Finck     PSYSTEM_PROCESSES SystemProcesses = NULL;
182*c2c66affSColin Finck     PSYSTEM_PROCESSES CurrentProcess;
183*c2c66affSColin Finck     ULONG BufferSize, ReturnSize;
184*c2c66affSColin Finck     NTSTATUS Status;
185*c2c66affSColin Finck     char buf[256];
186*c2c66affSColin Finck     char buf1[256];
187*c2c66affSColin Finck 
188*c2c66affSColin Finck     WriteFile(Stdout, title, lstrlen(title), &r, NULL);
189*c2c66affSColin Finck     WriteFile(Stdout, title1, lstrlen(title1), &r, NULL);
190*c2c66affSColin Finck     WriteFile(Stdout, title2, lstrlen(title2), &r, NULL);
191*c2c66affSColin Finck 
192*c2c66affSColin Finck     /* Get process information. */
193*c2c66affSColin Finck     BufferSize = 0;
194*c2c66affSColin Finck     do
195*c2c66affSColin Finck     {
196*c2c66affSColin Finck         BufferSize += 0x10000;
197*c2c66affSColin Finck         SystemProcesses = HeapAlloc(GetProcessHeap(), 0, BufferSize);
198*c2c66affSColin Finck         Status = NtQuerySystemInformation(SystemProcessInformation,
199*c2c66affSColin Finck                                           SystemProcesses, BufferSize,
200*c2c66affSColin Finck                                           &ReturnSize);
201*c2c66affSColin Finck         if (Status == STATUS_INFO_LENGTH_MISMATCH)
202*c2c66affSColin Finck             HeapFree(GetProcessHeap(), 0, SystemProcesses);
203*c2c66affSColin Finck     } while (Status == STATUS_INFO_LENGTH_MISMATCH);
204*c2c66affSColin Finck 
205*c2c66affSColin Finck     /* If querying system information failed, bail out. */
206*c2c66affSColin Finck     if (!NT_SUCCESS(Status))
207*c2c66affSColin Finck         return 1;
208*c2c66affSColin Finck 
209*c2c66affSColin Finck     /* For every process print the information. */
210*c2c66affSColin Finck     CurrentProcess = SystemProcesses;
211*c2c66affSColin Finck     while (CurrentProcess->NextEntryOffset != 0)
212*c2c66affSColin Finck     {
213*c2c66affSColin Finck         int hour, hour1, thour, thour1;
214*c2c66affSColin Finck         unsigned char minute, minute1, tmin, tmin1;
215*c2c66affSColin Finck         unsigned char  seconds, seconds1, tsec, tsec1;
216*c2c66affSColin Finck 
217*c2c66affSColin Finck 	unsigned int ti;
218*c2c66affSColin Finck 	LARGE_INTEGER ptime;
219*c2c66affSColin Finck 
220*c2c66affSColin Finck 	ptime.QuadPart = CurrentProcess->KernelTime.QuadPart;
221*c2c66affSColin Finck 	hour    = (ptime.QuadPart / (10000000LL * 3600LL));
222*c2c66affSColin Finck 	minute  = (ptime.QuadPart / (10000000LL * 60LL)) % 60LL;
223*c2c66affSColin Finck 	seconds = (ptime.QuadPart / 10000000LL) % 60LL;
224*c2c66affSColin Finck 
225*c2c66affSColin Finck 	ptime.QuadPart = CurrentProcess->UserTime.QuadPart;
226*c2c66affSColin Finck 	hour1    = (ptime.QuadPart / (10000000LL * 3600LL));
227*c2c66affSColin Finck 	minute1  = (ptime.QuadPart / (10000000LL * 60LL)) % 60LL;
228*c2c66affSColin Finck 	seconds1 = (ptime.QuadPart / 10000000LL) % 60LL;
229*c2c66affSColin Finck 
230*c2c66affSColin Finck 	RtlUnicodeStringToAnsiString(&astring, &CurrentProcess->ImageName, TRUE);
231*c2c66affSColin Finck 
232*c2c66affSColin Finck         wsprintf(buf,"P%8d %8d %3d:%02d:%02d  %3d:%02d:%02d   ProcName: %s\n",
233*c2c66affSColin Finck                  CurrentProcess->UniqueProcessId, CurrentProcess->InheritedFromUniqueProcessId,
234*c2c66affSColin Finck                  hour, minute, seconds, hour1, minute1, seconds1,
235*c2c66affSColin Finck                  astring.Buffer);
236*c2c66affSColin Finck         WriteFile(stdout, buf, lstrlen(buf), &r, NULL);
237*c2c66affSColin Finck 
238*c2c66affSColin Finck         RtlFreeAnsiString(&astring);
239*c2c66affSColin Finck 
240*c2c66affSColin Finck 	for (ti = 0; ti < CurrentProcess->NumberOfThreads; ti++)
241*c2c66affSColin Finck 	   {
242*c2c66affSColin Finck 		struct status *statt;
243*c2c66affSColin Finck 		struct waitres *waitt;
244*c2c66affSColin Finck 		char szWindowName[30] = {" "};
245*c2c66affSColin Finck 
246*c2c66affSColin Finck 		ptime = CurrentProcess->Threads[ti].KernelTime;
247*c2c66affSColin Finck 		thour = (ptime.QuadPart / (10000000LL * 3600LL));
248*c2c66affSColin Finck 		tmin  = (ptime.QuadPart / (10000000LL * 60LL)) % 60LL;
249*c2c66affSColin Finck 		tsec  = (ptime.QuadPart / 10000000LL) % 60LL;
250*c2c66affSColin Finck 
251*c2c66affSColin Finck 		ptime = CurrentProcess->Threads[ti].UserTime;
252*c2c66affSColin Finck 		thour1 = (ptime.QuadPart / (10000000LL * 3600LL));
253*c2c66affSColin Finck 		tmin1  = (ptime.QuadPart / (10000000LL * 60LL)) % 60LL;
254*c2c66affSColin Finck 		tsec1  = (ptime.QuadPart / 10000000LL) % 60LL;
255*c2c66affSColin Finck 
256*c2c66affSColin Finck 		statt = thread_stat;
257*c2c66affSColin Finck                 while (statt->state != CurrentProcess->Threads[ti].ThreadState  && statt->state >= 0)
258*c2c66affSColin Finck                 	statt++;
259*c2c66affSColin Finck 
260*c2c66affSColin Finck 		waitt = waitreason;
261*c2c66affSColin Finck                 while (waitt->state != CurrentProcess->Threads[ti].WaitReason  && waitt->state >= 0)
262*c2c66affSColin Finck                         waitt++;
263*c2c66affSColin Finck 
264*c2c66affSColin Finck 		wsprintf (buf1,
265*c2c66affSColin Finck 		          "t%         %8d %3d:%02d:%02d  %3d:%02d:%02d   %s %s\n",
266*c2c66affSColin Finck 		          CurrentProcess->Threads[ti].ClientId.UniqueThread,
267*c2c66affSColin Finck 		          thour, tmin, tsec, thour1, tmin1, tsec1,
268*c2c66affSColin Finck 		          statt->desc , waitt->desc);
269*c2c66affSColin Finck         	WriteFile(stdout, buf1, lstrlen(buf1), &r, NULL);
270*c2c66affSColin Finck 
271*c2c66affSColin Finck 		EnumThreadWindows(PtrToUlong(CurrentProcess->Threads[ti].ClientId.UniqueThread),
272*c2c66affSColin Finck 		                  (WNDENUMPROC) EnumThreadProc,
273*c2c66affSColin Finck 		                  (LPARAM)(LPTSTR) szWindowName );
274*c2c66affSColin Finck 	   }
275*c2c66affSColin Finck 
276*c2c66affSColin Finck 	   CurrentProcess = (PSYSTEM_PROCESSES)((ULONG_PTR)CurrentProcess +
277*c2c66affSColin Finck 	                     (ULONG_PTR)CurrentProcess->NextEntryOffset);
278*c2c66affSColin Finck 	}
279*c2c66affSColin Finck   	return (0);
280*c2c66affSColin Finck }
281