ReactOS 0.4.16-dev-2613-g9533ad7
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(UINT uID, UINT MaxWidth, BOOL bAlignLeft)
49{
52 PrintString(StringBuffer, MaxWidth, bAlignLeft);
53}
54
55// Print a number, aligned to right.
56// MaxWidth is the width for printing.
57// the number WILL NOT be truncated if it's longer than MaxWidth
59{
60 ConPrintf(StdOut, L"%*lld", MaxWidth, Number);
61}
62
63// Print memory size using KB as unit, with comma-separated number, aligned to right.
64// MaxWidth is the width for printing.
65// the number WILL be truncated if it's longer than MaxWidth
66BOOL PrintMemory(SIZE_T MemorySizeByte, UINT MaxWidth)
67{
68 SIZE_T MemorySize = MemorySizeByte >> 10;
69
70 WCHAR NumberString[27] = { 0 }; // length 26 is enough to display ULLONG_MAX in decimal with comma, one more for zero-terminated.
71 C_ASSERT(sizeof(SIZE_T) <= 8);
72
73 PWCHAR pNumberStr = NumberString;
74
75 // calculate the length
76 UINT PrintLength = 0;
77 SIZE_T Tmp = MemorySize;
78 UINT Mod = 1;
79
80 do
81 {
82 Tmp /= 10;
83 PrintLength++;
84 Mod *= 10;
85 } while (Tmp);
86
87 for (UINT i = PrintLength; i; i--)
88 {
89 Mod /= 10;
90 *pNumberStr = L'0' + (MemorySize / Mod);
91 MemorySize %= Mod;
92 pNumberStr++;
93
94 if (i != 1 && i % 3 == 1)
95 {
96 *pNumberStr = L',';
97 pNumberStr++;
98 }
99 }
100
101 WCHAR FormatStr[RES_STR_MAXLEN];
102 LoadStringW(NULL, IDS_MEMORY_STR, FormatStr, _countof(FormatStr));
103
104 WCHAR String[RES_STR_MAXLEN + _countof(NumberString)] = { 0 };
105 StringCchPrintfW(String, _countof(String), FormatStr, NumberString);
106 PrintString(String, MaxWidth, FALSE);
107
108 return TRUE;
109}
110
112{
114 PrintSpace(1);
116 PrintSpace(1);
118 PrintSpace(1);
120
121 ConPuts(StdOut, L"\n");
122
124 PrintSpace(1);
126 PrintSpace(1);
128 PrintSpace(1);
130
131 ConPuts(StdOut, L"\n");
132}
133
135{
136 // Call NtQuerySystemInformation for the process information
137 ULONG ProcessInfoBufferLength = 0;
139 PBYTE ProcessInfoBuffer = NULL;
140
141 // Get the buffer size we need
143
144 // New process/thread might appear before we call for the actual data.
145 // Try to avoid this by retrying several times.
147 {
148 // (Re)allocate buffer
149 ProcessInfoBufferLength = ResultLength;
150 ResultLength = 0;
151 if (ProcessInfoBuffer)
152 {
153 PBYTE NewProcessInfoBuffer = HeapReAlloc(GetProcessHeap(), 0,
154 ProcessInfoBuffer,
155 ProcessInfoBufferLength);
156 if (NewProcessInfoBuffer)
157 {
158 ProcessInfoBuffer = NewProcessInfoBuffer;
159 }
160 else
161 {
162 // out of memory
164 HeapFree(GetProcessHeap(), 0, ProcessInfoBuffer);
165 return FALSE;
166 }
167 }
168 else
169 {
170 ProcessInfoBuffer = HeapAlloc(GetProcessHeap(), 0, ProcessInfoBufferLength);
171 if (!ProcessInfoBuffer)
172 {
173 // out of memory
175 return FALSE;
176 }
177 }
178
179 // Query information
181 ProcessInfoBuffer,
182 ProcessInfoBufferLength,
183 &ResultLength);
185 {
186 break;
187 }
188 }
189
190 if (!NT_SUCCESS(Status))
191 {
192 // tried NT_SYSTEM_QUERY_MAX_RETRY times, or failed with some other reason
194 HeapFree(GetProcessHeap(), 0, ProcessInfoBuffer);
195 return FALSE;
196 }
197
198 ConPuts(StdOut, L"\n");
199
200 if (!bNoHeader)
201 PrintHeader();
202
204 pSPI = (PSYSTEM_PROCESS_INFORMATION)ProcessInfoBuffer;
205 while (pSPI)
206 {
207 PrintString(pSPI->UniqueProcessId ? pSPI->ImageName.Buffer : L"System Idle Process", COLUMNWIDTH_IMAGENAME, TRUE);
208 PrintSpace(1);
210 PrintSpace(1);
212 PrintSpace(1);
214
215 ConPuts(StdOut, L"\n");
216
217 if (pSPI->NextEntryOffset == 0)
218 break;
219 pSPI = (PSYSTEM_PROCESS_INFORMATION)((LPBYTE)pSPI + pSPI->NextEntryOffset);
220 }
221
222 HeapFree(GetProcessHeap(), 0, ProcessInfoBuffer);
223 return TRUE;
224}
225
227{
228 if (szOption[0] != L'/' && szOption[0] != L'-')
229 {
230 return OPTION_INVALID;
231 }
232 szOption++;
233
234 for (UINT i = 0; i < _countof(OptionList); i++)
235 {
236 if (!_wcsicmp(OptionList[i], szOption))
237 {
238 return i;
239 }
240 }
241 return OPTION_INVALID;
242}
243
245{
246 BOOL bHasHelp = FALSE, bHasNoHeader = FALSE;
247
248 for (INT i = 1; i < argc; i++)
249 {
250 INT Option = GetOptionType(argv[i]);
251
252 switch (Option)
253 {
254 case OPTION_HELP:
255 {
256 if (bHasHelp)
257 {
258 // -? already specified
261 return FALSE;
262 }
263 bHasHelp = TRUE;
264 break;
265 }
266 case OPTION_NOHEADER:
267 {
268 if (bHasNoHeader)
269 {
270 // -nh already specified
273 return FALSE;
274 }
275 bHasNoHeader = TRUE;
276 break;
277 }
278 case OPTION_INVALID:
279 default:
280 {
283 return FALSE;
284 }
285 }
286 }
287
288 if (bHasHelp)
289 {
290 if (argc > 2) // any arguments other than -? exists
291 {
294 return FALSE;
295 }
296 else
297 {
300 return FALSE;
301 }
302 }
303 else
304 {
305 EnumProcessAndPrint(bHasNoHeader);
306 }
307 return TRUE;
308}
309
310int wmain(int argc, WCHAR **argv)
311{
312 /* Initialize the Console Standard Streams */
314
316 {
317 return 1;
318 }
319 return 0;
320}
#define IDS_USAGE
Definition: resource.h:3
#define IDS_OUT_OF_MEMORY
Definition: resource.h:7
#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
_In_ PSCSI_REQUEST_BLOCK _Out_ NTSTATUS _Inout_ BOOLEAN * Retry
Definition: classpnp.h:312
void ConPuts(FILE *fp, LPCWSTR psz)
Definition: conutils_noros.h:8
#define ConInitStdStreams()
Definition: conutils_noros.h:5
void ConPrintf(FILE *fp, LPCWSTR psz,...)
#define StdOut
Definition: conutils_noros.h:6
#define StdErr
Definition: conutils_noros.h:7
#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
MonoAssembly int argc
Definition: metahost.c:107
_ACRTIMP int __cdecl _wcsicmp(const wchar_t *, const wchar_t *)
Definition: wcs.c:159
#define L(x)
Definition: resources.c:13
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 Number
Definition: haltypes.h:1872
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
INT __cdecl ConResMsgPrintf(IN PCON_STREAM Stream, IN DWORD dwFlags, IN UINT uID,...)
Definition: outstream.c:1458
BYTE * PBYTE
Definition: pedump.c:66
short WCHAR
Definition: pedump.c:58
_In_ UINT uID
Definition: shlwapi.h:156
int wmain()
#define LoadStringW
Definition: utils.h:64
#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:1077
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:244
#define OPTION_NOHEADER
Definition: tasklist.c:16
VOID PrintResString(UINT uID, UINT MaxWidth, BOOL bAlignLeft)
Definition: tasklist.c:48
static PCWSTR OptionList[]
Definition: tasklist.c:12
BOOL EnumProcessAndPrint(BOOL bNoHeader)
Definition: tasklist.c:134
INT GetOptionType(LPCWSTR szOption)
Definition: tasklist.c:226
#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:58
BOOL PrintMemory(SIZE_T MemorySizeByte, UINT MaxWidth)
Definition: tasklist.c:66
VOID PrintSplitLine(UINT Length)
Definition: tasklist.c:22
VOID PrintHeader(VOID)
Definition: tasklist.c:111
VOID PrintSpace(UINT Length)
Definition: tasklist.c:31
#define OPTION_HELP
Definition: tasklist.c:15
#define NT_SYSTEM_QUERY_MAX_RETRY
Definition: tasklist.h:23
#define COLUMNWIDTH_MEMUSAGE
Definition: tasklist.h:28
#define COLUMNWIDTH_PID
Definition: tasklist.h:26
#define COLUMNWIDTH_IMAGENAME
Definition: tasklist.h:25
#define COLUMNWIDTH_SESSION
Definition: tasklist.h:27
int32_t INT_PTR
Definition: typedefs.h:64
const uint16_t * PCWSTR
Definition: typedefs.h:57
const uint16_t * LPCWSTR
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:3782
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFSTRING String
Definition: wdfdevice.h:2439