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