Reactos
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 <eric.kohl@reactos.org>
6 */
7
8/* INCLUDES *******************************************************************/
9
10#include "precomp.h"
11
12#define NDEBUG
13#include <debug.h>
14
15/* GLOBALS ********************************************************************/
16
17typedef 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
26PALIAS_ENTRY AliasListHead = NULL;
27PALIAS_ENTRY AliasListTail = NULL;
28
29
30/* FUNCTIONS ******************************************************************/
31
32static
33VOID
34ShowAliases(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
49static
50VOID
51ShowAlias(
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
74static
75PALIAS_ENTRY
76GetAliasEntry(
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
94VOID
95InitAliases(VOID)
96{
97 AliasListHead = NULL;
98 AliasListTail = NULL;
99}
100
101
102VOID
103DestroyAliases(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
121DWORD
122WINAPI
123AliasCommand(
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
213DWORD
214WINAPI
215ShowAliasCommand(
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
232DWORD
233WINAPI
234UnaliasCommand(
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}