[NETSH] Implement the -r (remote) option and set machine command

Also:
- Start all usage texts with a newline.
- Add some error messages.
- Fix a bug in the command interpreter.
This commit is contained in:
Eric Kohl
2025-11-02 22:37:16 +01:00
parent 4ad647fb5c
commit 420799228d
6 changed files with 111 additions and 34 deletions

View File

@@ -29,6 +29,8 @@ PCONTEXT_ENTRY pCurrentContext = NULL;
PCONTEXT_STACK_ENTRY pContextStackHead = NULL;
PCONTEXT_STACK_ENTRY pContextStackTail = NULL;
PWSTR pszMachine = NULL;
static BOOL bOnline = TRUE;
/* FUNCTIONS ******************************************************************/
@@ -707,6 +709,43 @@ PushdCommand(
}
DWORD
WINAPI
SetMachineCommand(
_In_ LPCWSTR pwszMachine,
_In_ LPWSTR *argv,
_In_ DWORD dwCurrentIndex,
_In_ DWORD dwArgCount,
_In_ DWORD dwFlags,
_In_ LPCVOID pvData,
_Out_ BOOL *pbDone)
{
DWORD dwError = ERROR_SUCCESS;
DPRINT("SetMachineCommand(pwszMachine %S dwCurrentIndex %lu dwArgCount %lu)\n",
pwszMachine, dwCurrentIndex, dwArgCount);
if ((dwArgCount - dwCurrentIndex) > 1)
return ERROR_SHOW_USAGE;
if (pszMachine != NULL)
{
HeapFree(GetProcessHeap(), 0, pszMachine);
pszMachine = NULL;
}
if ((dwArgCount - dwCurrentIndex) == 1)
{
pszMachine = HeapAlloc(GetProcessHeap(), 0, (sizeof(argv[dwCurrentIndex]) + 1) * sizeof(WCHAR));
if (pszMachine == NULL)
return ERROR_NOT_ENOUGH_MEMORY;
wcscpy(pszMachine, argv[dwCurrentIndex]);
}
return dwError;
}
DWORD
WINAPI
SetModeCommand(
@@ -720,9 +759,10 @@ SetModeCommand(
{
DWORD dwError = ERROR_SUCCESS;
DPRINT("SetModeCommand()\n");
DPRINT("SetModeCommand(pwszMachine %S dwCurrentIndex %lu dwArgCount %lu)\n",
pwszMachine, dwCurrentIndex, dwArgCount);
if (dwArgCount != 3)
if ((dwArgCount - dwCurrentIndex) != 1)
return ERROR_SHOW_USAGE;
if (!_wcsicmp(argv[dwCurrentIndex], L"offline"))
@@ -771,7 +811,7 @@ CreateRootContext(VOID)
if (pRootContext == NULL)
return FALSE;
pRootContext->hModule = GetModuleHandle(NULL);
pRootContext->hModule = hModule;
AddContextCommand(pRootContext, L"..", UpCommand, IDS_HLP_UP, IDS_HLP_UP_EX, 0);
AddContextCommand(pRootContext, L"?", NULL, IDS_HLP_HELP, IDS_HLP_HELP_EX, 0);
@@ -803,7 +843,8 @@ CreateRootContext(VOID)
pGroup = AddCommandGroup(pRootContext, L"set", IDS_HLP_GROUP_SET, 0);
if (pGroup)
{
AddGroupCommand(pGroup, L"mode", SetModeCommand, IDS_HLP_SET_MODE, IDS_HLP_SET_MODE_EX, 0);
AddGroupCommand(pGroup, L"machine", SetMachineCommand, IDS_HLP_SET_MACHINE, IDS_HLP_SET_MACHINE_EX, 0);
AddGroupCommand(pGroup, L"mode", SetModeCommand, IDS_HLP_SET_MODE, IDS_HLP_SET_MODE_EX, 0);
}
pGroup = AddCommandGroup(pRootContext, L"show", IDS_HLP_GROUP_SHOW, 0);

View File

@@ -205,7 +205,7 @@ InterpretCommand(
if (pCommand->pfnCmdHandler != NULL)
{
dwArgIndex++;
dwError = pCommand->pfnCmdHandler(NULL, argv, dwArgIndex, dwArgCount, 0, NULL, bDone);
dwError = pCommand->pfnCmdHandler(pszMachine, argv, dwArgIndex, dwArgCount, 0, NULL, bDone);
if (dwError != ERROR_SUCCESS)
{
if (dwError == ERROR_SHOW_USAGE)
@@ -317,7 +317,8 @@ InterpretCommand(
}
}
return ERROR_CMD_NOT_FOUND;
/* Done */
return ERROR_SUCCESS;
}
@@ -365,7 +366,7 @@ InterpretLine(
VOID
PrintPrompt(
PCONTEXT_ENTRY pContext)
_In_ PCONTEXT_ENTRY pContext)
{
if (pContext != pRootContext)
{
@@ -394,6 +395,8 @@ InterpretInteractive(VOID)
memset(args_vector, 0, sizeof(args_vector));
/* Shown just before the input where the user places commands */
if (pszMachine)
ConPrintf(StdOut, L"[%s] ", pszMachine);
PrintPrompt(pCurrentContext);
ConPuts(StdOut, L">");
@@ -423,7 +426,9 @@ InterpretInteractive(VOID)
dwError = InterpretCommand(args_vector, dwArgCount, &bDone);
if (dwError == ERROR_CMD_NOT_FOUND)
{
ConResPrintf(StdErr, IDS_INVALID_COMMAND, input_line);
PWSTR pszCommandString = MergeStrings(args_vector, dwArgCount);
ConResPrintf(StdErr, IDS_INVALID_COMMAND, pszCommandString);
HeapFree(GetProcessHeap(), 0, pszCommandString);
}
if (bDone)

View File

@@ -26,47 +26,50 @@ BEGIN
IDS_SUBCONTEXT_HEADER "\nThe following sub-contexts are available:\n"
IDS_HLP_UP "Goes up one context level.\n"
IDS_HLP_UP_EX "Usage: %1!s!\n\n Goes up one context level.\n"
IDS_HLP_UP_EX "\nUsage: %1!s!\n\n Goes up one context level.\n"
IDS_HLP_EXIT "Exits the program.\n"
IDS_HLP_EXIT_EX "Usage: %1!s!\n\n Exits the program.\n"
IDS_HLP_EXIT_EX "\nUsage: %1!s!\n\n Exits the program.\n"
IDS_HLP_HELP "Displays a list of commands.\n"
IDS_HLP_HELP_EX "Usage: %1!s!\n\n Displays a list of commands.\n"
IDS_HLP_HELP_EX "\nUsage: %1!s!\n\n Displays a list of commands.\n"
IDS_HLP_POPD "Changes to the context on the stack.\n"
IDS_HLP_POPD_EX "Usage: %1!s!\n\n Changes to the context on the stack.\n"
IDS_HLP_POPD_EX "\nUsage: %1!s!\n\n Changes to the context on the stack.\n"
IDS_HLP_PUSHD "Stores the current context on the stack.\n"
IDS_HLP_PUSHD_EX "Usage: %1!s!\n\n Stores the current context on the stack.\n"
IDS_HLP_PUSHD_EX "\nUsage: %1!s!\n\n Stores the current context on the stack.\n"
IDS_HLP_EXEC "Runs a script file.\n"
IDS_HLP_EXEC_EX "Usage: %1!s! <script file name>\n\n Loads the script file and runs it.\n"
IDS_HLP_EXEC_EX "\nUsage: %1!s! <script file name>\n\n Loads the script file and runs it.\n"
IDS_HLP_DUMP "Displays a configuration script.\n"
IDS_HLP_DUMP_EX "Usage: %1!s!\n\n Creates a script that contains the current configuration. If saved to a\n\
IDS_HLP_DUMP_EX "\nUsage: %1!s!\n\n Creates a script that contains the current configuration. If saved to a\n\
file, the script can be used to altered configuration settings.\n"
IDS_HLP_OFFLINE "Sets the current mode to offline.\n"
IDS_HLP_OFFLINE_EX "Usage: %1!s!\n\n Sets the current mode to offline. Changes made while in offline mode\n\
IDS_HLP_OFFLINE_EX "\nUsage: %1!s!\n\n Sets the current mode to offline. Changes made while in offline mode\n\
are saved and made in the running configuration when the mode is\n switched back to online.\n"
IDS_HLP_ONLINE "Sets the current mode to online.\n"
IDS_HLP_ONLINE_EX "Usage: %1!s!\n\n Sets the current mode to online. Changes made while in online mode are\n\
IDS_HLP_ONLINE_EX "\nUsage: %1!s!\n\n Sets the current mode to online. Changes made while in online mode are\n\
immediately reflected in the running configuration. If changes are\n made while in offline mode, they are reflected in the running\n\
configuration when the mode is switched back to online.\n"
IDS_HLP_ABORT "Discards changes made while in offline mode.\n"
IDS_HLP_ABORT_EX "Usage: %1!s!\n\n Discards changes made while in the offline mode. This does not affect\n\
IDS_HLP_ABORT_EX "\nUsage: %1!s!\n\n Discards changes made while in the offline mode. This does not affect\n\
changes made while in online mode.\n"
IDS_HLP_COMMIT "Commits changes made while in offline mode.\n"
IDS_HLP_COMMIT_EX "Usage: %1!s!\n\n Commits changes to the running configuration that were made while in\n\
IDS_HLP_COMMIT_EX "\nUsage: %1!s!\n\n Commits changes to the running configuration that were made while in\n\
offline mode. No action is taken for this command while in online\n mode.\n"
IDS_HLP_ADD_HELPER "Installs a helper DLL.\n"
IDS_HLP_ADD_HELPER_EX "Usage: %1!s! <dll file name>\n\n Installs the specified helper DLL in netsh.\n"
IDS_HLP_ADD_HELPER_EX "\nUsage: %1!s! <dll file name>\n\n Installs the specified helper DLL in netsh.\n"
IDS_HLP_DEL_HELPER "Removes a helper DLL.\n"
IDS_HLP_DEL_HELPER_EX "Usage: %1!s! <dll file name>\n\n Removes the specified helper DLL from netsh.\n"
IDS_HLP_DEL_HELPER_EX "\nUsage: %1!s! <dll file name>\n\n Removes the specified helper DLL from netsh.\n"
IDS_HLP_SET_MACHINE "Sets the current machine on which to operate.\n"
IDS_HLP_SET_MACHINE_EX "\nUsage: %1!s! [[name=]<string>]\n\n Sets the current machine on which to operate. If a machine name\n\
is not specified, the local machine is used.\n"
IDS_HLP_SET_MODE "Sets the current mode to online or offline.\n"
IDS_HLP_SET_MODE_EX "Usage: %1!s! [mode=]{online|offline}\n\n Sets the current mode to online or offline.\n"
IDS_HLP_SET_MODE_EX "\nUsage: %1!s! [mode=]{online|offline}\n\n Sets the current mode to online or offline.\n"
IDS_HLP_SHOW_HELPER "Lists all the top-level helpers.\n"
IDS_HLP_SHOW_HELPER_EX "Usage: %1!s!\n\n Lists all the top-level helpers.\n"
IDS_HLP_SHOW_HELPER_EX "\nUsage: %1!s!\n\n Lists all the top-level helpers.\n"
IDS_HLP_SHOW_MODE "Shows the current mode.\n"
IDS_HLP_SHOW_MODE_EX "Usage: %1!s!\n\n Shows the current mode (offline or online).\n"
IDS_HLP_SHOW_MODE_EX "\nUsage: %1!s!\n\n Shows the current mode (offline or online).\n"
IDS_HLP_GROUP_ADD "Adds a configuration entry to a list of entries.\n"
IDS_HLP_GROUP_DELETE "Deletes a configuration entry from a list of entries.\n"

View File

@@ -12,6 +12,10 @@
#define NDEBUG
#include <debug.h>
/* GLOBALS ********************************************************************/
HMODULE hModule = NULL;
/* FUNCTIONS ******************************************************************/
DWORD
@@ -95,6 +99,8 @@ wmain(
DPRINT("wmain(%S)\n", GetCommandLineW());
hModule = GetModuleHandle(NULL);
/* Initialize the Console Standard Streams */
ConInitStdStreams();
@@ -171,8 +177,15 @@ wmain(
if ((index + 1) < argc)
{
index++;
ConPuts(StdOut, L"\nThe -r option is not implemented yet\n");
// remote = argv[index];
pszMachine = HeapAlloc(GetProcessHeap(), 0, (wcslen(argv[index]) + 1) * sizeof(WCHAR));
if (pszMachine == NULL)
{
dwError = ERROR_NOT_ENOUGH_MEMORY;
PrintError(hModule, dwError);
goto done;
}
wcscpy(pszMachine, argv[index]);
}
else
{
@@ -192,8 +205,14 @@ wmain(
else if (pszCommand == NULL)
{
pszCommand = MergeStrings((LPWSTR*)&argv[index], argc - index);
if (pszCommand)
break;
if (pszCommand == NULL)
{
dwError = ERROR_NOT_ENOUGH_MEMORY;
PrintError(hModule, dwError);
goto done;
}
break;
}
}
}
@@ -222,8 +241,12 @@ wmain(
done:
/* FIXME: Cleanup code goes here */
if (pszMachine != NULL)
HeapFree(GetProcessHeap(), 0, pszMachine);
if (pszCommand != NULL)
HeapFree(GetProcessHeap(), 0, pszCommand);
CleanupContext();
UnloadHelpers();

View File

@@ -132,6 +132,9 @@ extern PCONTEXT_ENTRY pCurrentContext;
extern PHELPER_ENTRY pHelperListHead;
extern HMODULE hModule;
extern PWSTR pszMachine;
/* PROTOTYPES *****************************************************************/
/* context.c */

View File

@@ -48,12 +48,14 @@
#define IDS_HLP_ADD_HELPER_EX 341
#define IDS_HLP_DEL_HELPER 342
#define IDS_HLP_DEL_HELPER_EX 343
#define IDS_HLP_SET_MODE 344
#define IDS_HLP_SET_MODE_EX 345
#define IDS_HLP_SHOW_HELPER 346
#define IDS_HLP_SHOW_HELPER_EX 347
#define IDS_HLP_SHOW_MODE 348
#define IDS_HLP_SHOW_MODE_EX 349
#define IDS_HLP_SET_MACHINE 344
#define IDS_HLP_SET_MACHINE_EX 345
#define IDS_HLP_SET_MODE 346
#define IDS_HLP_SET_MODE_EX 347
#define IDS_HLP_SHOW_HELPER 348
#define IDS_HLP_SHOW_HELPER_EX 349
#define IDS_HLP_SHOW_MODE 350
#define IDS_HLP_SHOW_MODE_EX 351
#define IDS_HLP_GROUP_ADD 360
#define IDS_HLP_GROUP_DELETE 361