Skip to content

Commit 3398506

Browse files
committed
[NETSH] Implement alias, unalias and show alias commands
Alias processing in the command interpreter is not implemented yet.
1 parent 9723245 commit 3398506

File tree

7 files changed

+365
-10
lines changed

7 files changed

+365
-10
lines changed

base/applications/network/netsh/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ include_directories(${REACTOS_SOURCE_DIR}/sdk/lib/conutils)
33
spec2def(netsh.exe netsh.spec ADD_IMPORTLIB)
44

55
list(APPEND SOURCE
6+
alias.c
67
context.c
78
help.c
89
helper.c
Lines changed: 282 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,282 @@
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 alias management functions
5+
* COPYRIGHT: Copyright 2025 Eric Kohl <[email protected]>
6+
*/
7+
8+
/* INCLUDES *******************************************************************/
9+
10+
#include "precomp.h"
11+
12+
#define NDEBUG
13+
#include <debug.h>
14+
15+
/* GLOBALS ********************************************************************/
16+
17+
typedef struct _ALIAS_ENTRY
18+
{
19+
struct _ALIAS_ENTRY *pPrev;
20+
struct _ALIAS_ENTRY *pNext;
21+
22+
PWSTR pszAliasName;
23+
PWSTR pszAlias;
24+
} ALIAS_ENTRY, *PALIAS_ENTRY;
25+
26+
PALIAS_ENTRY AliasListHead = NULL;
27+
PALIAS_ENTRY AliasListTail = NULL;
28+
29+
30+
/* FUNCTIONS ******************************************************************/
31+
32+
static
33+
VOID
34+
ShowAliases(VOID)
35+
{
36+
PALIAS_ENTRY pAliasEntry = NULL;
37+
38+
DPRINT1("ShowAliases()\n");
39+
40+
pAliasEntry = AliasListHead;
41+
while (pAliasEntry)
42+
{
43+
ConPrintf(StdOut, L"%s : %s\n", pAliasEntry->pszAliasName, pAliasEntry->pszAlias);
44+
pAliasEntry = pAliasEntry->pNext;
45+
}
46+
}
47+
48+
49+
static
50+
VOID
51+
ShowAlias(
52+
PWSTR pszAliasName)
53+
{
54+
PALIAS_ENTRY pAliasEntry = NULL;
55+
56+
DPRINT1("ShowAlias(%S)\n", pszAliasName);
57+
58+
pAliasEntry = AliasListHead;
59+
while (pAliasEntry)
60+
{
61+
if (wcscmp(pAliasEntry->pszAliasName, pszAliasName) == 0)
62+
{
63+
ConPrintf(StdOut, L"%s\n", pAliasEntry->pszAlias);
64+
return;
65+
}
66+
67+
pAliasEntry = pAliasEntry->pNext;
68+
}
69+
70+
ConResPrintf(StdOut, IDS_ALIAS_NOT_FOUND, pszAliasName);
71+
}
72+
73+
74+
static
75+
PALIAS_ENTRY
76+
GetAliasEntry(
77+
PWSTR pszAliasName)
78+
{
79+
PALIAS_ENTRY pAliasEntry = NULL;
80+
81+
pAliasEntry = AliasListHead;
82+
while (pAliasEntry)
83+
{
84+
if (wcscmp(pAliasEntry->pszAliasName, pszAliasName) == 0)
85+
return pAliasEntry;
86+
87+
pAliasEntry = pAliasEntry->pNext;
88+
}
89+
90+
return NULL;
91+
}
92+
93+
94+
VOID
95+
InitAliases(VOID)
96+
{
97+
AliasListHead = NULL;
98+
AliasListTail = NULL;
99+
}
100+
101+
102+
VOID
103+
DestroyAliases(VOID)
104+
{
105+
PALIAS_ENTRY pAliasEntry;
106+
107+
while (AliasListHead != NULL)
108+
{
109+
pAliasEntry = AliasListHead;
110+
AliasListHead = AliasListHead->pNext;
111+
112+
HeapFree(GetProcessHeap(), 0, pAliasEntry->pszAliasName);
113+
HeapFree(GetProcessHeap(), 0, pAliasEntry->pszAlias);
114+
HeapFree(GetProcessHeap(), 0, pAliasEntry);
115+
}
116+
117+
AliasListTail = NULL;
118+
}
119+
120+
121+
DWORD
122+
WINAPI
123+
AliasCommand(
124+
LPCWSTR pwszMachine,
125+
LPWSTR *argv,
126+
DWORD dwCurrentIndex,
127+
DWORD dwArgCount,
128+
DWORD dwFlags,
129+
LPCVOID pvData,
130+
BOOL *pbDone)
131+
{
132+
PALIAS_ENTRY pAliasEntry = NULL;
133+
PWSTR pszAlias;
134+
135+
DPRINT("AliasCommand(dwCurrentIndex %lu dwArgCount %lu)\n",
136+
dwCurrentIndex, dwArgCount);
137+
138+
/* Show aliases */
139+
if (dwArgCount - dwCurrentIndex == 0)
140+
{
141+
ShowAliases();
142+
return ERROR_SUCCESS;
143+
}
144+
145+
if (dwArgCount - dwCurrentIndex == 1)
146+
{
147+
ShowAlias(argv[dwCurrentIndex]);
148+
return ERROR_SUCCESS;
149+
}
150+
151+
152+
/* TODO: Check builtin commands */
153+
154+
155+
pAliasEntry = GetAliasEntry(argv[dwCurrentIndex]);
156+
if (pAliasEntry)
157+
{
158+
pszAlias = MergeStrings(&argv[dwCurrentIndex + 1], dwArgCount - dwCurrentIndex - 1);
159+
DPRINT("Alias: %S\n", pszAlias);
160+
if (pszAlias == NULL)
161+
return ERROR_NOT_ENOUGH_MEMORY;
162+
163+
if (pAliasEntry->pszAlias)
164+
HeapFree(GetProcessHeap(), 0, pAliasEntry->pszAlias);
165+
166+
pAliasEntry->pszAlias = pszAlias;
167+
}
168+
else
169+
{
170+
pAliasEntry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ALIAS_ENTRY));
171+
if (pAliasEntry == NULL)
172+
return ERROR_NOT_ENOUGH_MEMORY;
173+
174+
pAliasEntry->pszAliasName = HeapAlloc(GetProcessHeap(), 0,
175+
(wcslen(argv[dwCurrentIndex]) + 1) * sizeof(WCHAR));
176+
if (pAliasEntry->pszAliasName == NULL)
177+
{
178+
HeapFree(GetProcessHeap(), 0, pAliasEntry);
179+
return ERROR_NOT_ENOUGH_MEMORY;
180+
}
181+
182+
wcscpy(pAliasEntry->pszAliasName, argv[dwCurrentIndex]);
183+
DPRINT("AliasName: %S\n", pAliasEntry->pszAliasName);
184+
185+
pAliasEntry->pszAlias = MergeStrings(&argv[dwCurrentIndex + 1], dwArgCount - dwCurrentIndex - 1);
186+
DPRINT("Alias: %S\n", pAliasEntry->pszAlias);
187+
if (pAliasEntry->pszAlias == NULL)
188+
{
189+
HeapFree(GetProcessHeap(), 0, pAliasEntry->pszAliasName);
190+
HeapFree(GetProcessHeap(), 0, pAliasEntry);
191+
return ERROR_NOT_ENOUGH_MEMORY;
192+
}
193+
194+
if (AliasListHead == NULL)
195+
{
196+
AliasListHead = pAliasEntry;
197+
AliasListTail = pAliasEntry;
198+
}
199+
else
200+
{
201+
pAliasEntry->pPrev = AliasListTail;
202+
AliasListTail->pNext = pAliasEntry;
203+
AliasListTail = pAliasEntry;
204+
}
205+
}
206+
207+
DPRINT("Done\n");
208+
209+
return ERROR_OKAY;
210+
}
211+
212+
213+
DWORD
214+
WINAPI
215+
ShowAliasCommand(
216+
LPCWSTR pwszMachine,
217+
LPWSTR *argv,
218+
DWORD dwCurrentIndex,
219+
DWORD dwArgCount,
220+
DWORD dwFlags,
221+
LPCVOID pvData,
222+
BOOL *pbDone)
223+
{
224+
DPRINT("ShowAliasCommand()\n");
225+
226+
ShowAliases();
227+
228+
return ERROR_SUCCESS;
229+
}
230+
231+
232+
DWORD
233+
WINAPI
234+
UnaliasCommand(
235+
LPCWSTR pwszMachine,
236+
LPWSTR *argv,
237+
DWORD dwCurrentIndex,
238+
DWORD dwArgCount,
239+
DWORD dwFlags,
240+
LPCVOID pvData,
241+
BOOL *pbDone)
242+
{
243+
PALIAS_ENTRY pAliasEntry = NULL;
244+
245+
DPRINT("UnaliasCommand()\n");
246+
247+
if (dwArgCount - dwCurrentIndex != 1)
248+
return ERROR_INVALID_SYNTAX;
249+
250+
DPRINT("Alias %S\n", argv[dwCurrentIndex]);
251+
252+
pAliasEntry = AliasListHead;
253+
while (pAliasEntry)
254+
{
255+
if (wcscmp(pAliasEntry->pszAliasName, argv[dwCurrentIndex]) == 0)
256+
{
257+
DPRINT("Alias found %S\n", argv[dwCurrentIndex]);
258+
259+
if (pAliasEntry->pNext != NULL)
260+
pAliasEntry->pNext->pPrev = pAliasEntry->pPrev;
261+
else
262+
AliasListTail = pAliasEntry->pPrev;
263+
264+
if (pAliasEntry->pPrev != NULL)
265+
pAliasEntry->pPrev->pNext = pAliasEntry->pNext;
266+
else
267+
AliasListHead = pAliasEntry->pNext;
268+
269+
HeapFree(GetProcessHeap(), 0, pAliasEntry->pszAliasName);
270+
HeapFree(GetProcessHeap(), 0, pAliasEntry->pszAlias);
271+
HeapFree(GetProcessHeap(), 0, pAliasEntry);
272+
273+
return ERROR_SUCCESS;
274+
}
275+
276+
pAliasEntry = pAliasEntry->pNext;
277+
}
278+
279+
ConResPrintf(StdOut, IDS_ALIAS_NOT_FOUND, argv[dwCurrentIndex]);
280+
281+
return ERROR_SUCCESS;
282+
}

base/applications/network/netsh/context.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -816,6 +816,7 @@ CreateRootContext(VOID)
816816
AddContextCommand(pRootContext, L"..", UpCommand, IDS_HLP_UP, IDS_HLP_UP_EX, 0);
817817
AddContextCommand(pRootContext, L"?", NULL, IDS_HLP_HELP, IDS_HLP_HELP_EX, 0);
818818
AddContextCommand(pRootContext, L"abort", AbortCommand, IDS_HLP_ABORT, IDS_HLP_ABORT_EX, 0);
819+
AddContextCommand(pRootContext, L"alias", AliasCommand, IDS_HLP_ALIAS, IDS_HLP_ALIAS_EX, 0);
819820
AddContextCommand(pRootContext, L"bye", ExitCommand, IDS_HLP_EXIT, IDS_HLP_EXIT_EX, 0);
820821
AddContextCommand(pRootContext, L"commit", CommitCommand, IDS_HLP_COMMIT, IDS_HLP_COMMIT_EX, 0);
821822
AddContextCommand(pRootContext, L"dump", DumpCommand, IDS_HLP_DUMP, IDS_HLP_DUMP_EX, 0);
@@ -827,6 +828,7 @@ CreateRootContext(VOID)
827828
AddContextCommand(pRootContext, L"popd", PopdCommand, IDS_HLP_POPD, IDS_HLP_POPD_EX, 0);
828829
AddContextCommand(pRootContext, L"pushd", PushdCommand, IDS_HLP_PUSHD, IDS_HLP_PUSHD_EX, 0);
829830
AddContextCommand(pRootContext, L"quit", ExitCommand, IDS_HLP_EXIT, IDS_HLP_EXIT_EX, 0);
831+
AddContextCommand(pRootContext, L"unalias", UnaliasCommand, IDS_HLP_UNALIAS, IDS_HLP_UNALIAS_EX, 0);
830832

831833
pGroup = AddCommandGroup(pRootContext, L"add", IDS_HLP_GROUP_ADD, 0);
832834
if (pGroup)
@@ -850,6 +852,7 @@ CreateRootContext(VOID)
850852
pGroup = AddCommandGroup(pRootContext, L"show", IDS_HLP_GROUP_SHOW, 0);
851853
if (pGroup)
852854
{
855+
AddGroupCommand(pGroup, L"alias", ShowAliasCommand, IDS_HLP_SHOW_ALIAS, IDS_HLP_SHOW_ALIAS_EX, 0);
853856
AddGroupCommand(pGroup, L"helper", ShowHelperCommand, IDS_HLP_SHOW_HELPER, IDS_HLP_SHOW_HELPER_EX, 0);
854857
AddGroupCommand(pGroup, L"mode", ShowModeCommand, IDS_HLP_SHOW_MODE, IDS_HLP_SHOW_MODE_EX, 0);
855858
}

base/applications/network/netsh/lang/en-US.rc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ BEGIN
1515
IDS_OPEN_FAILED "The file %ls could not be openend.\n"
1616
IDS_THIS_COMMANDS "\nCommands in this context:\n"
1717
IDS_CONTEXT_COMMANDS "\nCommands in the %s-context:\n"
18+
IDS_ALIAS_NOT_FOUND "The following alias was not found: %s.\n"
1819
END
1920

2021
STRINGTABLE
@@ -51,6 +52,12 @@ BEGIN
5152
IDS_HLP_COMMIT "Commits changes made while in offline mode.\n"
5253
IDS_HLP_COMMIT_EX "\nUsage: %1!s!\n\n Commits changes to the running configuration that were made while in\n\
5354
offline mode. No action is taken for this command while in online\n mode.\n"
55+
IDS_HLP_ALIAS "Adds an alias.\n"
56+
IDS_HLP_ALIAS_EX "\nUsage : %1!s! [alias-name] [string1 string 2 ...]\n\n If no arguments are specified, all aliases will be displayed.\n\
57+
If alias-name is specified, then the equivalent string for it\n will be displayed (if found).\n\
58+
If one or more strings are specified, then alias-name is set to\n these strings.\n"
59+
IDS_HLP_UNALIAS "Deletes an alias.\n"
60+
IDS_HLP_UNALIAS_EX "\nUsage : %1!s! alias-name\n\n Deletes alias alias-name.\n"
5461

5562
IDS_HLP_ADD_HELPER "Installs a helper DLL.\n"
5663
IDS_HLP_ADD_HELPER_EX "\nUsage: %1!s! <dll file name>\n\n Installs the specified helper DLL in netsh.\n"
@@ -64,6 +71,8 @@ BEGIN
6471
IDS_HLP_SET_MODE "Sets the current mode to online or offline.\n"
6572
IDS_HLP_SET_MODE_EX "\nUsage: %1!s! [mode=]{online|offline}\n\n Sets the current mode to online or offline.\n"
6673

74+
IDS_HLP_SHOW_ALIAS "Lists all defined aliases.\n"
75+
IDS_HLP_SHOW_ALIAS_EX "\nUsage: %1!s!\n\n Lists all defined aliases.\n"
6776
IDS_HLP_SHOW_HELPER "Lists all the top-level helpers.\n"
6877
IDS_HLP_SHOW_HELPER_EX "\nUsage: %1!s!\n\n Lists all the top-level helpers.\n"
6978
IDS_HLP_SHOW_MODE "Shows the current mode.\n"
@@ -79,4 +88,5 @@ STRINGTABLE
7988
BEGIN
8089
ERROR_INVALID_SYNTAX "The syntax supplied for this command is not valid. Check help for the correct syntax.\n"
8190
ERROR_CMD_NOT_FOUND "The following command was not found: %1!s!.\n"
91+
ERROR_OKAY "Ok.\n"
8292
END

0 commit comments

Comments
 (0)