ReactOS 0.4.16-dev-2613-g9533ad7
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 pCommand = pGroup->pCommandListHead;
91 while (pCommand != NULL)
92 {
93 swprintf(szBuffer1, L"%s %s", pGroup->pwszCmdGroupToken, pCommand->pwszCmdToken);
94 LoadStringW(pContext->hModule, pCommand->dwShortCmdHelpToken, szBuffer2, _countof(szBuffer2));
95
96 ConPrintf(StdOut, L"%-15s - %s", szBuffer1, szBuffer2);
97 pCommand = pCommand->pNext;
98 }
99}
100
101
102static
103int
105 _In_ const void *p1,
106 _In_ const void *p2)
107{
108 return _wcsicmp(((PHELP_ENTRY)p1)->pszCommand, ((PHELP_ENTRY)p2)->pszCommand);
109}
110
111
112static
113VOID
115 _In_ PCONTEXT_ENTRY pContext)
116{
117 PCOMMAND_ENTRY pCommand;
118 PCOMMAND_GROUP pGroup;
119 PCONTEXT_ENTRY pSubContext;
120 PHELP_ENTRY pHelpArray = NULL;
121 DWORD dwCount = 0, dwIndex;
123
124 DPRINT("PrintContext()\n");
125
126 if (pContext != pRootContext)
127 PrintContext(pContext->pParentContext);
128
130
131 /* Count short commands */
132 pCommand = pContext->pCommandListHead;
133 while (pCommand != NULL)
134 {
135 dwCount++;
136 pCommand = pCommand->pNext;
137 }
138
139 /* Count short groups */
140 pGroup = pContext->pGroupListHead;
141 while (pGroup != NULL)
142 {
143 dwCount++;
144 pGroup = pGroup->pNext;
145 }
146
147 /* Count short subcontexts */
148 pSubContext = pContext->pSubContextHead;
149 while (pSubContext != NULL)
150 {
151 dwCount++;
152 pSubContext = pSubContext->pNext;
153 }
154
155 pHelpArray = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwCount * sizeof(HELP_ENTRY));
156 if (pHelpArray == NULL)
157 return;
158
159 dwIndex = 0;
160
161 /* Add short commands */
162 pCommand = pContext->pCommandListHead;
163 while (pCommand != NULL)
164 {
165 pHelpArray[dwIndex].Type = Command;
166 pHelpArray[dwIndex].pszCommand = pCommand->pwszCmdToken;
167 pHelpArray[dwIndex].dwHelpId = pCommand->dwShortCmdHelpToken;
168// pHelpArray[dwIndex].Pointer.pCommand = pCommand;
169 dwIndex++;
170 pCommand = pCommand->pNext;
171 }
172
173 /* Add short groups */
174 pGroup = pContext->pGroupListHead;
175 while (pGroup != NULL)
176 {
177 pHelpArray[dwIndex].Type = Group;
178 pHelpArray[dwIndex].pszCommand = pGroup->pwszCmdGroupToken;
179 pHelpArray[dwIndex].dwHelpId = pGroup->dwShortCmdHelpToken;
180// pHelpArray[dwIndex].Pointer.pGroup = pGroup;
181 dwIndex++;
182 pGroup = pGroup->pNext;
183 }
184
185 /* Count short subcontexts */
186 pSubContext = pContext->pSubContextHead;
187 while (pSubContext != NULL)
188 {
189 pHelpArray[dwIndex].Type = SubContext;
190 pHelpArray[dwIndex].pszCommand = pSubContext->pszContextName;
191 pHelpArray[dwIndex].Pointer.pSubContext = pSubContext;
192 dwIndex++;
193 pSubContext = pSubContext->pNext;
194 }
195
196 qsort(pHelpArray, dwCount, sizeof(HELP_ENTRY), HelpCompare);
197
198 for (dwIndex = 0; dwIndex < dwCount; dwIndex++)
199 {
200 switch (pHelpArray[dwIndex].Type)
201 {
202 case Command:
203 case Group:
204 if (LoadStringW(pContext->hModule, pHelpArray[dwIndex].dwHelpId, szBuffer, _countof(szBuffer)) == 0)
205 szBuffer[0] = UNICODE_NULL;
206 ConPrintf(StdOut, L"%-15s - %s", pHelpArray[dwIndex].pszCommand, szBuffer);
207 break;
208
209 case SubContext:
210 GetContextFullName(pHelpArray[dwIndex].Pointer.pSubContext, szBuffer, _countof(szBuffer));
211 ConPrintf(StdOut, L"%-15s - Changes to the \"%s\" context.\n", pHelpArray[dwIndex].pszCommand, szBuffer);
212 break;
213 }
214 }
215
216 if (pHelpArray)
217 HeapFree(GetProcessHeap(), 0, pHelpArray);
218}
219
220
221static
222int
224 _In_ const void *p1,
225 _In_ const void *p2)
226{
227 return _wcsicmp((*((PCONTEXT_ENTRY*)p1))->pszContextName, (*((PCONTEXT_ENTRY*)p2))->pszContextName);
228}
229
230
231static
232VOID
234 _In_ PCONTEXT_ENTRY pContext)
235{
236 PCONTEXT_ENTRY pSubContext, *pSubContextArray = NULL;
237 DWORD dwCount, dwIndex;
238
239 if (pContext->pSubContextHead == NULL)
240 return;
241
242 dwCount = 0;
243 pSubContext = pContext->pSubContextHead;
244 while (pSubContext != NULL)
245 {
246 dwCount++;
247 pSubContext = pSubContext->pNext;
248 }
249
250 pSubContextArray = HeapAlloc(GetProcessHeap(), 0, dwCount * sizeof(PCONTEXT_ENTRY));
251 if (pSubContextArray == NULL)
252 return;
253
254 dwIndex = 0;
255 pSubContext = pContext->pSubContextHead;
256 while (pSubContext != NULL)
257 {
258 pSubContextArray[dwIndex] = pSubContext;
259 dwIndex++;
260 pSubContext = pSubContext->pNext;
261 }
262
263 qsort(pSubContextArray, dwCount, sizeof(PCONTEXT_ENTRY), SubContextCompare);
264
266 for (dwIndex = 0; dwIndex < dwCount; dwIndex++)
267 {
268 ConPrintf(StdOut, L" %s", pSubContextArray[dwIndex]->pszContextName);
269 }
270 ConPuts(StdOut, L"\n");
271
272 HeapFree(GetProcessHeap(), 0, pSubContextArray);
273}
274
275
276VOID
278 _In_ PCONTEXT_ENTRY pContext,
279 _In_ PCOMMAND_GROUP pGroup,
280 _In_ PCOMMAND_ENTRY pCommand)
281{
282 LPWSTR pszCommandBuffer;
283 DWORD_PTR Args[2];
284
285 DPRINT("PrintCommandHelp(%p %p %p)\n", pContext, pGroup, pCommand);
286
287 pszCommandBuffer = HeapAlloc(GetProcessHeap(), 0, TINY_HELP_BUFFER_SIZE * sizeof(WCHAR));
288 if (pszCommandBuffer == NULL)
289 return;
290
291 wcscpy(pszCommandBuffer, pCommand->pwszCmdToken);
292 if (pGroup)
293 {
294 wcscat(pszCommandBuffer, L" ");
295 wcscat(pszCommandBuffer, pGroup->pwszCmdGroupToken);
296 }
297
298 Args[0] = (DWORD_PTR)pszCommandBuffer;
299 Args[1] = (DWORD_PTR)NULL;
300
302 pContext->hModule,
304 pCommand->dwCmdHlpToken,
306 (va_list *)&Args);
307 ConPuts(StdOut, L"\n");
308
309 HeapFree(GetProcessHeap(), 0, pszCommandBuffer);
310}
311
312
313VOID
315 _In_ PCONTEXT_ENTRY pContext,
316 _In_ LPWSTR pszGroupName,
317 _In_ BOOL bRecurse)
318{
319 PCOMMAND_GROUP pGroup;
320
321 if (bRecurse)
322 {
323 if (pContext != pRootContext)
324 PrintGroupHelp(pContext->pParentContext, pszGroupName, bRecurse);
325 }
326
327 pGroup = pContext->pGroupListHead;
328 while (pGroup != NULL)
329 {
330 if (_wcsicmp(pszGroupName, pGroup->pwszCmdGroupToken) == 0)
331 {
333 PrintShortGroupCommands(pContext, pGroup);
334 }
335 pGroup = pGroup->pNext;
336 }
337}
338
339
340VOID
342 _In_ PCONTEXT_ENTRY pContext)
343{
345 PrintContext(pContext);
346 PrintSubcontexts(pContext);
348}
Type
Definition: Type.h:7
char ** Args
Definition: acdebug.h:353
PCONTEXT_ENTRY pRootContext
Definition: context.c:26
PCONTEXT_ENTRY pCurrentContext
Definition: context.c:27
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:277
static int HelpCompare(_In_ const void *p1, _In_ const void *p2)
Definition: help.c:104
static VOID PrintSubcontexts(_In_ PCONTEXT_ENTRY pContext)
Definition: help.c:233
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:223
#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:114
#define TINY_HELP_BUFFER_SIZE
Definition: help.c:17
VOID PrintGroupHelp(_In_ PCONTEXT_ENTRY pContext, _In_ LPWSTR pszGroupName, _In_ BOOL bRecurse)
Definition: help.c:314
VOID PrintContextHelp(_In_ PCONTEXT_ENTRY pContext)
Definition: help.c:341
#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 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
_ACRTIMP int __cdecl _wcsicmp(const wchar_t *, const wchar_t *)
Definition: wcs.c:159
_ACRTIMP void __cdecl qsort(void *, size_t, size_t, int(__cdecl *)(const void *, const void *))
char * va_list
Definition: vadefs.h:50
#define swprintf
Definition: precomp.h:40
#define L(x)
Definition: resources.c:13
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
#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:73
PWSTR pwszCmdToken
Definition: precomp.h:77
DWORD dwShortCmdHelpToken
Definition: precomp.h:79
struct _COMMAND_ENTRY * pNext
Definition: precomp.h:75
struct _COMMAND_GROUP * pNext
Definition: precomp.h:87
PWSTR pwszCmdGroupToken
Definition: precomp.h:89
DWORD dwShortCmdHelpToken
Definition: precomp.h:90
Definition: precomp.h:98
PWSTR pszContextName
Definition: precomp.h:105
struct _CONTEXT_ENTRY * pSubContextHead
Definition: precomp.h:119
struct _CONTEXT_ENTRY * pNext
Definition: precomp.h:100
#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