ReactOS 0.4.16-dev-122-g325d74c
tasklist.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Tasklist Command
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Displays a list of currently running processes on the computer.
5 * COPYRIGHT: Copyright 2021 He Yang <1160386205@qq.com>
6 */
7
8#include "tasklist.h"
9
10// the strings in OptionList are the command-line options.
11// should always correspond with the defines below, in sequence (except OPTION_INVALID)
12static PCWSTR OptionList[] = { L"?", L"nh" };
13
14#define OPTION_INVALID -1
15#define OPTION_HELP 0
16#define OPTION_NOHEADER 1
17
18// the max string length PrintResString can handle
19#define RES_STR_MAXLEN 64
20
21// Print split line
23{
24 for (; Length; Length--)
25 {
26 ConPuts(StdOut, L"=");
27 }
28}
29
30// Print spaces
32{
33 ConPrintf(StdOut, L"%*ls", (INT)Length, L"");
34}
35
36// Print a string.
37// if bAlignLeft == TRUE then aligned to left, otherwise aligned to right
38// MaxWidth is the width for printing.
39VOID PrintString(LPCWSTR String, UINT MaxWidth, BOOL bAlignLeft)
40{
41 ConPrintf(StdOut, bAlignLeft ? L"%-*.*ls" : L"%*.*ls", MaxWidth, MaxWidth, String);
42}
43
44// Print a string from resource
45// if bAlignLeft == TRUE then aligned to left, otherwise aligned to right
46// MaxWidth is the width for printing.
47// The string WILL be truncated if it's longer than RES_STR_MAXLEN
48VOID PrintResString(HINSTANCE hInstance, UINT uID, UINT MaxWidth, BOOL bAlignLeft)
49{
50 if (!hInstance)
51 return;
52
55 PrintString(StringBuffer, MaxWidth, bAlignLeft);
56}
57
58// Print a number, aligned to right.
59// MaxWidth is the width for printing.
60// the number WILL NOT be truncated if it's longer than MaxWidth
62{
63 ConPrintf(StdOut, L"%*lld", MaxWidth, Number);
64}
65
66// Print memory size using KB as unit, with comma-separated number, aligned to right.
67// MaxWidth is the width for printing.
68// the number WILL be truncated if it's longer than MaxWidth
69BOOL PrintMemory(SIZE_T MemorySizeByte, UINT MaxWidth, HINSTANCE hInstance)
70{
71 if (!hInstance)
72 return FALSE;
73
74 SIZE_T MemorySize = MemorySizeByte >> 10;
75
76 WCHAR NumberString[27] = { 0 }; // length 26 is enough to display ULLONG_MAX in decimal with comma, one more for zero-terminated.
77 C_ASSERT(sizeof(SIZE_T) <= 8);
78
79 PWCHAR pNumberStr = NumberString;
80
81 // calculate the length
82 UINT PrintLength = 0;
83 SIZE_T Tmp = MemorySize;
84 UINT Mod = 1;
85
86 do
87 {
88 Tmp /= 10;
89 PrintLength++;
90 Mod *= 10;
91 } while (Tmp);
92
93 for (UINT i = PrintLength; i; i--)
94 {
95 Mod /= 10;
96 *pNumberStr = L'0' + (MemorySize / Mod);
97 MemorySize %= Mod;
98 pNumberStr++;
99
100 if (i != 1 && i % 3 == 1)
101 {
102 *pNumberStr = L',';
103 pNumberStr++;
104 }
105 }
106
107 WCHAR FormatStr[RES_STR_MAXLEN];
108 LoadStringW(hInstance, IDS_MEMORY_STR, FormatStr, _countof(FormatStr));
109
110 WCHAR String[RES_STR_MAXLEN + _countof(NumberString)] = { 0 };
111
112 StringCchPrintfW(String, _countof(String), FormatStr, NumberString);
113 PrintString(String, MaxWidth, FALSE);
114
115 return TRUE;
116}
117
119{
120 if (!hInstance)
121 return;
122
124 PrintSpace(1);
126 PrintSpace(1);
128 PrintSpace(1);
130
131 ConPuts(StdOut, L"\n");
132
134 PrintSpace(1);
136 PrintSpace(1);
138 PrintSpace(1);
140
141 ConPuts(StdOut, L"\n");
142}
143
145{
146 // Call NtQuerySystemInformation for the process information
147 ULONG ProcessInfoBufferLength = 0;
149 PBYTE ProcessInfoBuffer = NULL;
150
151 // Get the buffer size we need
153
154 // New process/thread might appear before we call for the actual data.
155 // Try to avoid this by retrying several times.
157 {
158 // (Re)allocate buffer
159 ProcessInfoBufferLength = ResultLength;
160 ResultLength = 0;
161 if (ProcessInfoBuffer)
162 {
163 PBYTE NewProcessInfoBuffer = HeapReAlloc(GetProcessHeap(), 0,
164 ProcessInfoBuffer,
165 ProcessInfoBufferLength);
166 if (NewProcessInfoBuffer)
167 {
168 ProcessInfoBuffer = NewProcessInfoBuffer;
169 }
170 else
171 {
172 // out of memory
174 HeapFree(GetProcessHeap(), 0, ProcessInfoBuffer);
175 return FALSE;
176 }
177 }
178 else
179 {
180 ProcessInfoBuffer = HeapAlloc(GetProcessHeap(), 0, ProcessInfoBufferLength);
181 if (!ProcessInfoBuffer)
182 {
183 // out of memory
185 return FALSE;
186 }
187 }
188
189 // Query information
191 ProcessInfoBuffer,
192 ProcessInfoBufferLength,
193 &ResultLength);
195 {
196 break;
197 }
198 }
199
200 if (!NT_SUCCESS(Status))
201 {
202 // tried NT_SYSTEM_QUERY_MAX_RETRY times, or failed with some other reason
204 HeapFree(GetProcessHeap(), 0, ProcessInfoBuffer);
205 return FALSE;
206 }
207
210
211 ConPuts(StdOut, L"\n");
212
213 if (!bNoHeader)
214 {
216 }
217
219 pSPI = (PSYSTEM_PROCESS_INFORMATION)ProcessInfoBuffer;
220 while (pSPI)
221 {
222 PrintString(pSPI->UniqueProcessId ? pSPI->ImageName.Buffer : L"System Idle Process", COLUMNWIDTH_IMAGENAME, TRUE);
223 PrintSpace(1);
225 PrintSpace(1);
227 PrintSpace(1);
229
230 ConPuts(StdOut, L"\n");
231
232 if (pSPI->NextEntryOffset == 0)
233 break;
234 pSPI = (PSYSTEM_PROCESS_INFORMATION)((LPBYTE)pSPI + pSPI->NextEntryOffset);
235 }
236
237 HeapFree(GetProcessHeap(), 0, ProcessInfoBuffer);
238 return TRUE;
239}
240
242{
243 if (szOption[0] != L'/' && szOption[0] != L'-')
244 {
245 return OPTION_INVALID;
246 }
247 szOption++;
248
249 for (UINT i = 0; i < _countof(OptionList); i++)
250 {
251 if (!_wcsicmp(OptionList[i], szOption))
252 {
253 return i;
254 }
255 }
256 return OPTION_INVALID;
257}
258
260{
261 BOOL bHasHelp = FALSE, bHasNoHeader = FALSE;
262
263 for (INT i = 1; i < argc; i++)
264 {
265 INT Option = GetOptionType(argv[i]);
266
267 switch (Option)
268 {
269 case OPTION_HELP:
270 {
271 if (bHasHelp)
272 {
273 // -? already specified
276 return FALSE;
277 }
278 bHasHelp = TRUE;
279 break;
280 }
281 case OPTION_NOHEADER:
282 {
283 if (bHasNoHeader)
284 {
285 // -nh already specified
288 return FALSE;
289 }
290 bHasNoHeader = TRUE;
291 break;
292 }
293 case OPTION_INVALID:
294 default:
295 {
298 return FALSE;
299 }
300 }
301 }
302
303 if (bHasHelp)
304 {
305 if (argc > 2) // any arguments other than -? exists
306 {
309 return FALSE;
310 }
311 else
312 {
315 return FALSE;
316 }
317 }
318 else
319 {
320 EnumProcessAndPrint(bHasNoHeader);
321 }
322 return TRUE;
323}
324
325int wmain(int argc, WCHAR **argv)
326{
327 /* Initialize the Console Standard Streams */
329
331 {
332 return 1;
333 }
334 return 0;
335}
static int argc
Definition: ServiceArgs.c:12
#define IDS_USAGE
Definition: resource.h:3
void ConPuts(FILE *fp, LPCWSTR psz)
Definition: fc.c:16
#define ConInitStdStreams()
Definition: fc.c:13
void ConPrintf(FILE *fp, LPCWSTR psz,...)
Definition: fc.c:20
#define StdOut
Definition: fc.c:14
#define StdErr
Definition: fc.c:15
#define IDS_OUT_OF_MEMORY
Definition: resource.h:5
#define IDS_DESCRIPTION
Definition: resource.h:4
#define IDS_HEADER_IMAGENAME
Definition: resource.h:11
#define IDS_MEMORY_STR
Definition: resource.h:16
#define IDS_INVALID_OPTION
Definition: resource.h:7
#define IDS_INVALID_SYNTAX
Definition: resource.h:6
#define IDS_OPTION_TOO_MUCH
Definition: resource.h:5
#define IDS_HEADER_MEMUSAGE
Definition: resource.h:14
#define IDS_HEADER_PID
Definition: resource.h:12
#define IDS_HEADER_SESSION
Definition: resource.h:13
#define IDS_ENUM_FAILED
Definition: resource.h:8
LONG NTSTATUS
Definition: precomp.h:26
HINSTANCE hInstance
Definition: charmap.c:19
_In_ PSCSI_REQUEST_BLOCK _Out_ NTSTATUS _Inout_ BOOLEAN * Retry
Definition: classpnp.h:312
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define GetProcessHeap()
Definition: compat.h:736
#define HeapAlloc
Definition: compat.h:733
#define HeapReAlloc
Definition: compat.h:734
#define HeapFree(x, y, z)
Definition: compat.h:735
HMODULE WINAPI GetModuleHandleW(LPCWSTR lpModuleName)
Definition: loader.c:838
#define assert(x)
Definition: debug.h:53
unsigned int BOOL
Definition: ntddk_ex.h:94
@ SystemProcessInformation
Definition: ntddk_ex.h:16
Status
Definition: gdiplustypes.h:25
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define C_ASSERT(e)
Definition: intsafe.h:73
WCHAR StringBuffer[156]
Definition: ldrinit.c:41
#define argv
Definition: mplay32.c:18
unsigned int UINT
Definition: ndis.h:50
struct _SYSTEM_PROCESS_INFORMATION * PSYSTEM_PROCESS_INFORMATION
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
_In_opt_ PENTER_STATE_SYSTEM_HANDLER _In_opt_ PVOID _In_ LONG _In_opt_ LONG volatile * Number
Definition: ntpoapi.h:207
#define L(x)
Definition: ntvdm.h:50
INT __cdecl ConResMsgPrintf(IN PCON_STREAM Stream, IN DWORD dwFlags, IN UINT uID,...)
Definition: outstream.c:1461
BYTE * PBYTE
Definition: pedump.c:66
int wmain()
_Check_return_ _CRTIMP int __cdecl _wcsicmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
#define _countof(array)
Definition: sndvol32.h:70
NTSYSAPI NTSTATUS NTAPI NtQuerySystemInformation(IN SYSTEM_INFORMATION_CLASS SystemInfoClass, OUT PVOID SystemInfoBuffer, IN ULONG SystemInfoBufferSize, OUT PULONG BytesReturned OPTIONAL)
STRSAFEAPI StringCchPrintfW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszFormat,...)
Definition: strsafe.h:530
UNICODE_STRING ImageName
Definition: extypes.h:902
static CONST DWORD MemorySize[]
Definition: svga.c:32
#define RES_STR_MAXLEN
Definition: tasklist.c:19
BOOL ProcessArguments(INT argc, WCHAR **argv)
Definition: tasklist.c:259
BOOL PrintMemory(SIZE_T MemorySizeByte, UINT MaxWidth, HINSTANCE hInstance)
Definition: tasklist.c:69
#define OPTION_NOHEADER
Definition: tasklist.c:16
static PCWSTR OptionList[]
Definition: tasklist.c:12
VOID PrintHeader(HINSTANCE hInstance)
Definition: tasklist.c:118
BOOL EnumProcessAndPrint(BOOL bNoHeader)
Definition: tasklist.c:144
INT GetOptionType(LPCWSTR szOption)
Definition: tasklist.c:241
#define OPTION_INVALID
Definition: tasklist.c:14
VOID PrintString(LPCWSTR String, UINT MaxWidth, BOOL bAlignLeft)
Definition: tasklist.c:39
VOID PrintNum(LONGLONG Number, UINT MaxWidth)
Definition: tasklist.c:61
VOID PrintResString(HINSTANCE hInstance, UINT uID, UINT MaxWidth, BOOL bAlignLeft)
Definition: tasklist.c:48
VOID PrintSplitLine(UINT Length)
Definition: tasklist.c:22
VOID PrintSpace(UINT Length)
Definition: tasklist.c:31
#define OPTION_HELP
Definition: tasklist.c:15
#define NT_SYSTEM_QUERY_MAX_RETRY
Definition: tasklist.h:24
#define COLUMNWIDTH_MEMUSAGE
Definition: tasklist.h:29
#define COLUMNWIDTH_PID
Definition: tasklist.h:27
#define COLUMNWIDTH_IMAGENAME
Definition: tasklist.h:26
#define COLUMNWIDTH_SESSION
Definition: tasklist.h:28
int32_t INT_PTR
Definition: typedefs.h:64
const uint16_t * PCWSTR
Definition: typedefs.h:57
unsigned char * LPBYTE
Definition: typedefs.h:53
int64_t LONGLONG
Definition: typedefs.h:68
ULONG_PTR SIZE_T
Definition: typedefs.h:80
int32_t INT
Definition: typedefs.h:58
uint16_t * PWCHAR
Definition: typedefs.h:56
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
#define STATUS_INFO_LENGTH_MISMATCH
Definition: udferr_usr.h:133
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG _Out_ PULONG ResultLength
Definition: wdfdevice.h:3776
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFSTRING String
Definition: wdfdevice.h:2433
int WINAPI LoadStringW(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_writes_to_(cchBufferMax, return+1) LPWSTR lpBuffer, _In_ int cchBufferMax)
__wchar_t WCHAR
Definition: xmlstorage.h:180
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185