ReactOS 0.4.17-dev-573-g8315b8c
help.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS NetSh
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Network Shell builtin help command and support functions
5 * COPYRIGHT: Copyright 2023 Eric Kohl <eric.kohl@reactos.org>
6 */
7
8/* INCLUDES *******************************************************************/
9
10#include "precomp.h"
11
12#define NDEBUG
13#include <debug.h>
14
15#define HUGE_HELP_BUFFER_SIZE 2048
16#define SMALL_HELP_BUFFER_SIZE 160
17#define TINY_HELP_BUFFER_SIZE 80
18
19typedef enum
20{
25
26typedef struct
27{
31 union
32 {
36 } Pointer;
38
39
40/* FUNCTIONS ******************************************************************/
41
42static
43VOID
45 _In_ PCONTEXT_ENTRY pContext,
46 _Inout_ LPWSTR pszBuffer,
47 _In_ DWORD cchLength)
48{
49 if (pContext != pRootContext)
50 {
51 GetContextFullName(pContext->pParentContext, pszBuffer, cchLength);
52 wcscat(pszBuffer, L" ");
53 wcscat(pszBuffer, pContext->pszContextName);
54 }
55 else
56 {
57 wcscpy(pszBuffer, pContext->pszContextName);
58 }
59}
60
61
62static
63VOID
65 _In_ PCONTEXT_ENTRY pContext)
66{
67 if (pContext == pCurrentContext)
68 {
70 }
71 else
72 {
74 GetContextFullName(pContext, szBuffer, _countof(szBuffer));
76 }
77}
78
79
80static
81VOID
83 _In_ PCONTEXT_ENTRY pContext,
84 _In_ PCOMMAND_GROUP pGroup)
85{
86 PCOMMAND_ENTRY pCommand;
89
90 for (pCommand = pGroup->pCommandListHead; pCommand != NULL; pCommand = pCommand->pNext)
91 {
92 DPRINT("CheckVersion (Command) %S %S", pGroup->pwszCmdGroupToken, pCommand->pwszCmdToken);
93 if (!CheckOsVersion(pCommand->pfnOsVersionCheck))
94 continue;
95
96 if (((pCommand->dwFlags & CMD_FLAG_LOCAL) && (g_pszMachine != NULL)) ||
97 ((pCommand->dwFlags & CMD_FLAG_ONLINE) && (g_bOnline == FALSE)) ||
98 (pCommand->dwFlags & CMD_FLAG_HIDDEN))
99 continue;
100
101 _swprintf(szBuffer1, L"%s %s", pGroup->pwszCmdGroupToken, pCommand->pwszCmdToken);
102 LoadStringW(pContext->hModule, pCommand->dwShortCmdHelpToken, szBuffer2, _countof(szBuffer2));
103
104 ConPrintf(StdOut, L"%-15s - %s", szBuffer1, szBuffer2);
105 }
106}
107
108
109static
110int
112 _In_ const void *p1,
113 _In_ const void *p2)
114{
115 return _wcsicmp(((PHELP_ENTRY)p1)->pszCommand, ((PHELP_ENTRY)p2)->pszCommand);
116}
117
118
119static
120VOID
122 _In_ PCONTEXT_ENTRY pContext)
123{
124 PCOMMAND_ENTRY pCommand;
125 PCOMMAND_GROUP pGroup;
126 PCONTEXT_ENTRY pSubContext;
127 PHELP_ENTRY pHelpArray = NULL;
128 DWORD dwCount = 0, dwIndex;
130
131 DPRINT("PrintContext()\n");
132
133 if (pContext != pRootContext)
134 PrintContext(pContext->pParentContext);
135
137
138 /* Count short commands */
139 for (pCommand = pContext->pCommandListHead; pCommand != NULL; pCommand = pCommand->pNext)
140 {
141 if (!CheckOsVersion(pCommand->pfnOsVersionCheck))
142 continue;
143
144 if (((pCommand->dwFlags & CMD_FLAG_LOCAL) && (g_pszMachine != NULL)) ||
145 ((pCommand->dwFlags & CMD_FLAG_ONLINE) && (g_bOnline == FALSE)) ||
146 (pCommand->dwFlags & CMD_FLAG_HIDDEN))
147 continue;
148
149 dwCount++;
150 }
151
152 /* Count short groups */
153 for (pGroup = pContext->pGroupListHead; pGroup != NULL; pGroup = pGroup->pNext)
154 {
155 if (!CheckOsVersion(pGroup->pfnOsVersionCheck))
156 continue;
157
158 if (((pGroup->dwFlags & CMD_FLAG_LOCAL) && (g_pszMachine != NULL)) ||
159 ((pGroup->dwFlags & CMD_FLAG_ONLINE) && (g_bOnline == FALSE)) ||
160 (pGroup->dwFlags & CMD_FLAG_HIDDEN))
161 continue;
162
163 dwCount++;
164 }
165
166 /* Count short subcontexts */
167 for (pSubContext = pContext->pSubContextHead; pSubContext != NULL; pSubContext = pSubContext->pNext)
168 {
169 if (!CheckOsVersion(pSubContext->pfnOsVersionCheck))
170 continue;
171
172 if (((pSubContext->dwFlags & CMD_FLAG_LOCAL) && (g_pszMachine != NULL)) ||
173 ((pSubContext->dwFlags & CMD_FLAG_ONLINE) && (g_bOnline == FALSE)) ||
174 (pSubContext->dwFlags & CMD_FLAG_HIDDEN))
175 continue;
176
177 dwCount++;
178 }
179
180 pHelpArray = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwCount * sizeof(HELP_ENTRY));
181 if (pHelpArray == NULL)
182 return;
183
184 dwIndex = 0;
185
186 /* Add short commands */
187 for (pCommand = pContext->pCommandListHead; pCommand != NULL; pCommand = pCommand->pNext)
188 {
189 if (!CheckOsVersion(pCommand->pfnOsVersionCheck))
190 continue;
191
192 if (((pCommand->dwFlags & CMD_FLAG_LOCAL) && (g_pszMachine != NULL)) ||
193 ((pCommand->dwFlags & CMD_FLAG_ONLINE) && (g_bOnline == FALSE)) ||
194 (pCommand->dwFlags & CMD_FLAG_HIDDEN))
195 continue;
196
197 pHelpArray[dwIndex].Type = Command;
198 pHelpArray[dwIndex].pszCommand = pCommand->pwszCmdToken;
199 pHelpArray[dwIndex].dwHelpId = pCommand->dwShortCmdHelpToken;
200 pHelpArray[dwIndex].Pointer.pCommand = pCommand;
201 dwIndex++;
202 }
203
204 /* Add short groups */
205 for (pGroup = pContext->pGroupListHead; pGroup != NULL; pGroup = pGroup->pNext)
206 {
207 if (!CheckOsVersion(pGroup->pfnOsVersionCheck))
208 continue;
209
210 if (((pGroup->dwFlags & CMD_FLAG_LOCAL) && (g_pszMachine != NULL)) ||
211 ((pGroup->dwFlags & CMD_FLAG_ONLINE) && (g_bOnline == FALSE)) ||
212 (pGroup->dwFlags & CMD_FLAG_HIDDEN))
213 continue;
214
215 pHelpArray[dwIndex].Type = Group;
216 pHelpArray[dwIndex].pszCommand = pGroup->pwszCmdGroupToken;
217 pHelpArray[dwIndex].dwHelpId = pGroup->dwShortCmdHelpToken;
218 pHelpArray[dwIndex].Pointer.pGroup = pGroup;
219 dwIndex++;
220 }
221
222 /* Count short subcontexts */
223 for (pSubContext = pContext->pSubContextHead; pSubContext != NULL; pSubContext = pSubContext->pNext)
224 {
225 if (!CheckOsVersion(pSubContext->pfnOsVersionCheck))
226 continue;
227
228 if (((pSubContext->dwFlags & CMD_FLAG_LOCAL) && (g_pszMachine != NULL)) ||
229 ((pSubContext->dwFlags & CMD_FLAG_ONLINE) && (g_bOnline == FALSE)) ||
230 (pSubContext->dwFlags & CMD_FLAG_HIDDEN))
231 continue;
232
233 pHelpArray[dwIndex].Type = SubContext;
234 pHelpArray[dwIndex].pszCommand = pSubContext->pszContextName;
235 pHelpArray[dwIndex].Pointer.pSubContext = pSubContext;
236 dwIndex++;
237 }
238
239 qsort(pHelpArray, dwCount, sizeof(HELP_ENTRY), HelpCompare);
240
241 for (dwIndex = 0; dwIndex < dwCount; dwIndex++)
242 {
243 switch (pHelpArray[dwIndex].Type)
244 {
245 case Command:
246 if (LoadStringW(pContext->hModule, pHelpArray[dwIndex].dwHelpId, szBuffer, _countof(szBuffer)) == 0)
247 szBuffer[0] = UNICODE_NULL;
248 ConPrintf(StdOut, L"%-15s - %s", pHelpArray[dwIndex].pszCommand, szBuffer);
249 break;
250
251 case Group:
252 if (LoadStringW(pContext->hModule, pHelpArray[dwIndex].dwHelpId, szBuffer, _countof(szBuffer)) == 0)
253 szBuffer[0] = UNICODE_NULL;
254 ConPrintf(StdOut, L"%-15s - %s", pHelpArray[dwIndex].pszCommand, szBuffer);
255 break;
256
257 case SubContext:
258 GetContextFullName(pHelpArray[dwIndex].Pointer.pSubContext, szBuffer, _countof(szBuffer));
259 ConPrintf(StdOut, L"%-15s - Changes to the \"%s\" context.\n", pHelpArray[dwIndex].pszCommand, szBuffer);
260 break;
261 }
262 }
263
264 if (pHelpArray)
265 HeapFree(GetProcessHeap(), 0, pHelpArray);
266}
267
268
269static
270int
272 _In_ const void *p1,
273 _In_ const void *p2)
274{
275 return _wcsicmp((*((PCONTEXT_ENTRY*)p1))->pszContextName, (*((PCONTEXT_ENTRY*)p2))->pszContextName);
276}
277
278
279static
280VOID
282 _In_ PCONTEXT_ENTRY pContext)
283{
284 PCONTEXT_ENTRY pSubContext, *pSubContextArray = NULL;
285 DWORD dwCount, dwIndex;
286
287 if (pContext->pSubContextHead == NULL)
288 return;
289
290 dwCount = 0;
291 for (pSubContext = pContext->pSubContextHead; pSubContext != NULL; pSubContext = pSubContext->pNext)
292 {
293 if (!CheckOsVersion(pSubContext->pfnOsVersionCheck))
294 continue;
295
296 if (((pSubContext->dwFlags & CMD_FLAG_LOCAL) && (g_pszMachine != NULL)) ||
297 ((pSubContext->dwFlags & CMD_FLAG_ONLINE) && (g_bOnline == FALSE)) ||
298 (pSubContext->dwFlags & CMD_FLAG_HIDDEN))
299 continue;
300
301 dwCount++;
302 }
303
304 pSubContextArray = HeapAlloc(GetProcessHeap(), 0, dwCount * sizeof(PCONTEXT_ENTRY));
305 if (pSubContextArray == NULL)
306 return;
307
308 dwIndex = 0;
309 for (pSubContext = pContext->pSubContextHead; pSubContext != NULL; pSubContext = pSubContext->pNext)
310 {
311 if (!CheckOsVersion(pSubContext->pfnOsVersionCheck))
312 continue;
313
314 if (((pSubContext->dwFlags & CMD_FLAG_LOCAL) && (g_pszMachine != NULL)) ||
315 ((pSubContext->dwFlags & CMD_FLAG_ONLINE) && (g_bOnline == FALSE)) ||
316 (pSubContext->dwFlags & CMD_FLAG_HIDDEN))
317 continue;
318
319 pSubContextArray[dwIndex] = pSubContext;
320 dwIndex++;
321 }
322
323 qsort(pSubContextArray, dwCount, sizeof(PCONTEXT_ENTRY), SubContextCompare);
324
326 for (dwIndex = 0; dwIndex < dwCount; dwIndex++)
327 {
328 ConPrintf(StdOut, L" %s", pSubContextArray[dwIndex]->pszContextName);
329 }
330 ConPuts(StdOut, L"\n");
331
332 HeapFree(GetProcessHeap(), 0, pSubContextArray);
333}
334
335
336VOID
338 _In_ PCONTEXT_ENTRY pContext,
339 _In_ PCOMMAND_GROUP pGroup,
340 _In_ PCOMMAND_ENTRY pCommand)
341{
342 LPWSTR pszCommandBuffer;
343 DWORD_PTR Args[2];
344 DWORD dwLength = 1;
345
346 DPRINT("PrintCommandHelp(%p %p %p)\n", pContext, pGroup, pCommand);
347
348 if (!CheckOsVersion(pCommand->pfnOsVersionCheck))
349 return;
350
351 if (((pCommand->dwFlags & CMD_FLAG_LOCAL) && (g_pszMachine != NULL)) ||
352 ((pCommand->dwFlags & CMD_FLAG_ONLINE) && (g_bOnline == FALSE)) ||
353 (pCommand->dwFlags & CMD_FLAG_HIDDEN))
354 return;
355
356 dwLength += wcslen(pCommand->pwszCmdToken);
357 if (pGroup)
358 dwLength += (wcslen(pGroup->pwszCmdGroupToken) + 1);
359
360 pszCommandBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength * sizeof(WCHAR));
361 if (pszCommandBuffer == NULL)
362 return;
363
364 _swprintf(pszCommandBuffer, L"%s%s%s",
365 (pGroup) ? pGroup->pwszCmdGroupToken : L"",
366 (pGroup) ? L" " : L"",
367 pCommand->pwszCmdToken);
368
369 Args[0] = (DWORD_PTR)pszCommandBuffer;
370 Args[1] = (DWORD_PTR)NULL;
371
373 pContext->hModule,
375 pCommand->dwCmdHlpToken,
377 (va_list *)&Args);
378 ConPuts(StdOut, L"\n");
379
380 HeapFree(GetProcessHeap(), 0, pszCommandBuffer);
381}
382
383
384VOID
386 _In_ PCONTEXT_ENTRY pContext,
387 _In_ LPWSTR pszGroupName,
388 _In_ BOOL bRecurse)
389{
390 PCOMMAND_GROUP pGroup;
391
392 if (bRecurse)
393 {
394 if (pContext != pRootContext)
395 PrintGroupHelp(pContext->pParentContext, pszGroupName, bRecurse);
396 }
397
398 pGroup = pContext->pGroupListHead;
399 while (pGroup != NULL)
400 {
401 if (_wcsicmp(pszGroupName, pGroup->pwszCmdGroupToken) == 0)
402 {
404 PrintShortGroupCommands(pContext, pGroup);
405 }
406 pGroup = pGroup->pNext;
407 }
408}
409
410
411VOID
413 _In_ PCONTEXT_ENTRY pContext)
414{
416 PrintContext(pContext);
417 PrintSubcontexts(pContext);
419}
Type
Definition: Type.h:7
char ** Args
Definition: acdebug.h:353
BOOL g_bOnline
Definition: context.c:33
PCONTEXT_ENTRY pRootContext
Definition: context.c:26
PCONTEXT_ENTRY pCurrentContext
Definition: context.c:27
PWSTR g_pszMachine
Definition: context.c:32
static VOID PrintShortGroupCommands(_In_ PCONTEXT_ENTRY pContext, _In_ PCOMMAND_GROUP pGroup)
Definition: help.c:82
VOID PrintCommandHelp(_In_ PCONTEXT_ENTRY pContext, _In_ PCOMMAND_GROUP pGroup, _In_ PCOMMAND_ENTRY pCommand)
Definition: help.c:337
static int HelpCompare(_In_ const void *p1, _In_ const void *p2)
Definition: help.c:111
static VOID PrintSubcontexts(_In_ PCONTEXT_ENTRY pContext)
Definition: help.c:281
static VOID PrintCurrentContextHeader(_In_ PCONTEXT_ENTRY pContext)
Definition: help.c:64
struct HELP_ENTRY * PHELP_ENTRY
enum HELP_TYPE * PHELP_TYPE
static VOID GetContextFullName(_In_ PCONTEXT_ENTRY pContext, _Inout_ LPWSTR pszBuffer, _In_ DWORD cchLength)
Definition: help.c:44
static int SubContextCompare(_In_ const void *p1, _In_ const void *p2)
Definition: help.c:271
#define SMALL_HELP_BUFFER_SIZE
Definition: help.c:16
HELP_TYPE
Definition: help.c:20
@ Group
Definition: help.c:22
@ SubContext
Definition: help.c:23
@ Command
Definition: help.c:21
static VOID PrintContext(_In_ PCONTEXT_ENTRY pContext)
Definition: help.c:121
#define TINY_HELP_BUFFER_SIZE
Definition: help.c:17
VOID PrintGroupHelp(_In_ PCONTEXT_ENTRY pContext, _In_ LPWSTR pszGroupName, _In_ BOOL bRecurse)
Definition: help.c:385
VOID PrintContextHelp(_In_ PCONTEXT_ENTRY pContext)
Definition: help.c:412
BOOL CheckOsVersion(_In_ PNS_OSVERSIONCHECK pfnOsVersionCheck)
Definition: wmi.c:35
#define IDS_CONTEXT_COMMANDS
Definition: resource.h:16
#define IDS_HELP_FOOTER
Definition: resource.h:20
#define IDS_THIS_COMMANDS
Definition: resource.h:15
#define IDS_HELP_HEADER
Definition: resource.h:19
#define IDS_SUBCONTEXT_HEADER
Definition: resource.h:21
void ConPuts(FILE *fp, LPCWSTR psz)
Definition: conutils_noros.h:8
void ConPrintf(FILE *fp, LPCWSTR psz,...)
#define StdOut
Definition: conutils_noros.h:6
void ConResPrintf(FILE *fp, UINT nID,...)
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
#define GetProcessHeap()
Definition: compat.h:736
#define HeapAlloc
Definition: compat.h:733
#define HeapFree(x, y, z)
Definition: compat.h:735
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
static DWORD DWORD * dwLength
Definition: fusion.c:86
_ACRTIMP int __cdecl _wcsicmp(const wchar_t *, const wchar_t *)
Definition: wcs.c:164
_ACRTIMP size_t __cdecl wcslen(const wchar_t *)
Definition: wcs.c:2988
_ACRTIMP void __cdecl qsort(void *, size_t, size_t, int(__cdecl *)(const void *, const void *))
char * va_list
Definition: vadefs.h:50
#define L(x)
Definition: resources.c:13
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
#define _swprintf(buf, format,...)
Definition: sprintf.c:56
@ CMD_FLAG_ONLINE
Definition: netsh.h:45
@ CMD_FLAG_HIDDEN
Definition: netsh.h:46
@ CMD_FLAG_LOCAL
Definition: netsh.h:44
#define _Inout_
Definition: no_sal2.h:162
#define _In_
Definition: no_sal2.h:158
#define UNICODE_NULL
INT ConResMsgPrintfExV(IN PCON_STREAM Stream, IN HINSTANCE hInstance OPTIONAL, IN DWORD dwFlags, IN UINT uID, IN LANGID LanguageId, IN va_list *Arguments OPTIONAL)
Definition: outstream.c:1216
short WCHAR
Definition: pedump.c:58
wcscat
wcscpy
#define LoadStringW
Definition: utils.h:64
#define DPRINT
Definition: sndvol32.h:73
#define _countof(array)
Definition: sndvol32.h:70
Definition: help.c:27
HELP_TYPE Type
Definition: help.c:28
union HELP_ENTRY::@19 Pointer
PWSTR pszCommand
Definition: help.c:29
DWORD dwHelpId
Definition: help.c:30
PCONTEXT_ENTRY pSubContext
Definition: help.c:35
PCOMMAND_ENTRY pCommand
Definition: help.c:33
PCOMMAND_GROUP pGroup
Definition: help.c:34
Definition: precomp.h:74
PWSTR pwszCmdToken
Definition: precomp.h:78
PNS_OSVERSIONCHECK pfnOsVersionCheck
Definition: precomp.h:83
DWORD dwShortCmdHelpToken
Definition: precomp.h:80
DWORD dwFlags
Definition: precomp.h:82
struct _COMMAND_ENTRY * pNext
Definition: precomp.h:76
PNS_OSVERSIONCHECK pfnOsVersionCheck
Definition: precomp.h:94
DWORD dwFlags
Definition: precomp.h:93
struct _COMMAND_GROUP * pNext
Definition: precomp.h:89
PWSTR pwszCmdGroupToken
Definition: precomp.h:91
DWORD dwShortCmdHelpToken
Definition: precomp.h:92
Definition: precomp.h:101
PWSTR pszContextName
Definition: precomp.h:108
struct _CONTEXT_ENTRY * pSubContextHead
Definition: precomp.h:124
struct _CONTEXT_ENTRY * pNext
Definition: precomp.h:103
PNS_OSVERSIONCHECK pfnOsVersionCheck
Definition: precomp.h:116
DWORD dwFlags
Definition: precomp.h:112
#define LANG_USER_DEFAULT
Definition: tnerror.cpp:50
#define DWORD_PTR
Definition: treelist.c:76
uint16_t * PWSTR
Definition: typedefs.h:56
uint32_t DWORD_PTR
Definition: typedefs.h:65
uint16_t * LPWSTR
Definition: typedefs.h:56
#define FORMAT_MESSAGE_ARGUMENT_ARRAY
Definition: winbase.h:401