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