[NETSH] Context stack and helper improvements

- Add the context stack including the PUSHD and POPD commands.
- Add the required changes to the HELP command and command execution to support the context stack.
- Add support for sub helpers.
This commit is contained in:
Eric Kohl
2025-08-23 11:06:19 +02:00
parent 359205bccc
commit 3f6639031c
8 changed files with 585 additions and 129 deletions

View File

@@ -14,9 +14,21 @@
/* GLOBALS ********************************************************************/
typedef struct _CONTEXT_STACK_ENTRY
{
struct _CONTEXT_STACK_ENTRY *pPrev;
struct _CONTEXT_STACK_ENTRY *pNext;
PCONTEXT_ENTRY pContext;
} CONTEXT_STACK_ENTRY, *PCONTEXT_STACK_ENTRY;
PCONTEXT_ENTRY pRootContext = NULL;
PCONTEXT_ENTRY pCurrentContext = NULL;
PCONTEXT_STACK_ENTRY pContextStackHead = NULL;
PCONTEXT_STACK_ENTRY pContextStackTail = NULL;
/* FUNCTIONS ******************************************************************/
PCONTEXT_ENTRY
@@ -135,6 +147,8 @@ AddCommandGroup(
{
PCOMMAND_GROUP pEntry;
DPRINT("AddCommandGroup(%S %lu)\n", pwszCmdGroupToken, dwShortCmdHelpToken);
/* Allocate the entry */
pEntry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(COMMAND_GROUP));
if (pEntry == NULL)
@@ -220,10 +234,68 @@ AddGroupCommand(
}
VOID
RemoveContextFromStack(
_In_ PCONTEXT_ENTRY pContextEntry)
{
PCONTEXT_STACK_ENTRY pStackEntry, pNextEntry;
if (pContextStackHead == NULL)
return;
pStackEntry = pContextStackHead;
while (1)
{
if (pStackEntry->pContext == pContextEntry)
{
if (pStackEntry == pContextStackHead && pStackEntry == pContextStackHead)
{
pContextStackHead = NULL;
pContextStackTail = NULL;
HeapFree(GetProcessHeap(), 0, pStackEntry);
return;
}
else if (pStackEntry == pContextStackHead)
{
pStackEntry->pNext->pPrev = NULL;
pContextStackHead = pStackEntry->pNext;
HeapFree(GetProcessHeap(), 0, pStackEntry);
pStackEntry = pContextStackHead;
}
else if (pStackEntry == pContextStackTail)
{
pStackEntry->pPrev->pNext = NULL;
pContextStackTail = pStackEntry->pPrev;
HeapFree(GetProcessHeap(), 0, pStackEntry);
return;
}
else
{
pNextEntry = pStackEntry->pNext;
pStackEntry->pPrev->pNext = pStackEntry->pNext;
pStackEntry->pNext->pPrev = pStackEntry->pPrev;
HeapFree(GetProcessHeap(), 0, pStackEntry);
pStackEntry = pNextEntry;
}
}
else
{
if (pStackEntry == pContextStackTail)
return;
pStackEntry = pStackEntry->pNext;
}
}
}
VOID
DeleteContext(
PWSTR pszName)
{
/* Remove the context from the stack */
/* RemoveContextFromStack(); */
/* Delete all commands */
/* Delete the context */
}
@@ -278,6 +350,81 @@ RemCommand(
}
DWORD
WINAPI
PopdCommand(
LPCWSTR pwszMachine,
LPWSTR *argv,
DWORD dwCurrentIndex,
DWORD dwArgCount,
DWORD dwFlags,
LPCVOID pvData,
BOOL *pbDone)
{
PCONTEXT_STACK_ENTRY pEntry;
DPRINT("PopdCommand()\n");
if (pContextStackHead == NULL)
return 0;
pEntry = pContextStackHead;
pCurrentContext = pEntry->pContext;
if (pContextStackTail == pEntry)
{
pContextStackHead = NULL;
pContextStackTail = NULL;
}
else
{
pContextStackHead = pEntry->pNext;
pContextStackHead->pPrev = NULL;
}
HeapFree(GetProcessHeap(), 0, pEntry);
return 0;
}
DWORD
WINAPI
PushdCommand(
LPCWSTR pwszMachine,
LPWSTR *argv,
DWORD dwCurrentIndex,
DWORD dwArgCount,
DWORD dwFlags,
LPCVOID pvData,
_Out_ BOOL *pbDone)
{
PCONTEXT_STACK_ENTRY pEntry;
DPRINT("PushdCommand()\n");
pEntry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CONTEXT_STACK_ENTRY));
if (pEntry == NULL)
return 1;
pEntry->pContext = pCurrentContext;
if (pContextStackHead == NULL)
{
pContextStackHead = pEntry;
pContextStackTail = pEntry;
}
else
{
pEntry->pNext = pContextStackHead;
pContextStackHead->pPrev = pEntry;
pContextStackHead = pEntry;
}
return 0;
}
BOOL
CreateRootContext(VOID)
{
@@ -290,12 +437,14 @@ CreateRootContext(VOID)
pRootContext->hModule = GetModuleHandle(NULL);
AddContextCommand(pRootContext, L"..", UpCommand, IDS_HLP_UP, IDS_HLP_UP_EX, 0);
AddContextCommand(pRootContext, L"?", HelpCommand, IDS_HLP_HELP, IDS_HLP_HELP_EX, 0);
AddContextCommand(pRootContext, L"bye", ExitCommand, IDS_HLP_EXIT, IDS_HLP_EXIT_EX, 0);
AddContextCommand(pRootContext, L"exit", ExitCommand, IDS_HLP_EXIT, IDS_HLP_EXIT_EX, 0);
AddContextCommand(pRootContext, L"help", HelpCommand, IDS_HLP_HELP, IDS_HLP_HELP_EX, 0);
AddContextCommand(pRootContext, L"quit", ExitCommand, IDS_HLP_EXIT, IDS_HLP_EXIT_EX, 0);
AddContextCommand(pRootContext, L"..", UpCommand, IDS_HLP_UP, IDS_HLP_UP_EX, 0);
AddContextCommand(pRootContext, L"?", NULL, IDS_HLP_HELP, IDS_HLP_HELP_EX, 0);
AddContextCommand(pRootContext, L"bye", ExitCommand, IDS_HLP_EXIT, IDS_HLP_EXIT_EX, 0);
AddContextCommand(pRootContext, L"exit", ExitCommand, IDS_HLP_EXIT, IDS_HLP_EXIT_EX, 0);
AddContextCommand(pRootContext, L"help", NULL, IDS_HLP_HELP, IDS_HLP_HELP_EX, 0);
AddContextCommand(pRootContext, L"popd", PopdCommand, IDS_HLP_POPD, IDS_HLP_POPD_EX, 0);
AddContextCommand(pRootContext, L"pushd", PushdCommand, IDS_HLP_PUSHD, IDS_HLP_PUSHD_EX, 0);
AddContextCommand(pRootContext, L"quit", ExitCommand, IDS_HLP_EXIT, IDS_HLP_EXIT_EX, 0);
pGroup = AddCommandGroup(pRootContext, L"add", IDS_HLP_GROUP_ADD, 0);
if (pGroup)
@@ -326,8 +475,10 @@ WINAPI
RegisterContext(
_In_ const NS_CONTEXT_ATTRIBUTES *pChildContext)
{
PHELPER_ENTRY pHelper;
PCONTEXT_ENTRY pContext;
DWORD i;
PCOMMAND_GROUP pGroup;
DWORD i, j;
DPRINT1("RegisterContext(%p)\n", pChildContext);
if (pChildContext == NULL)
@@ -345,30 +496,59 @@ RegisterContext(
return ERROR_INVALID_PARAMETER;
}
DPRINT1("Name: %S\n", pChildContext->pwszContext);
DPRINT("Name: %S\n", pChildContext->pwszContext);
DPRINT("Groups: %lu\n", pChildContext->ulNumGroups);
DPRINT("Top commands: %lu\n", pChildContext->ulNumTopCmds);
pHelper = FindHelper(&pChildContext->guidHelper, pHelperListHead);
pContext = AddContext(pRootContext, pChildContext->pwszContext, (GUID*)&pChildContext->guidHelper);
if (pContext != NULL)
{
if ((pHelper != NULL) && (pHelper->pDllEntry != NULL))
{
pContext->hModule = pHelper->pDllEntry->hModule;
}
for (i = 0; i < pChildContext->ulNumTopCmds; i++)
{
AddContextCommand(pContext,
pChildContext->pTopCmds[i].pwszCmdToken,
pChildContext->pTopCmds[i].pfnCmdHandler,
pChildContext->pTopCmds[i].dwShortCmdHelpToken,
pChildContext->pTopCmds[i].dwCmdHlpToken,
pChildContext->pTopCmds[i].dwFlags);
pChildContext->pTopCmds[i].pwszCmdToken,
pChildContext->pTopCmds[i].pfnCmdHandler,
pChildContext->pTopCmds[i].dwShortCmdHelpToken,
pChildContext->pTopCmds[i].dwCmdHlpToken,
pChildContext->pTopCmds[i].dwFlags);
}
/* Add command groups */
for (i = 0; i < pChildContext->ulNumGroups; i++)
{
AddCommandGroup(pContext,
pChildContext->pCmdGroups[i].pwszCmdGroupToken,
pChildContext->pCmdGroups[i].dwShortCmdHelpToken,
pChildContext->pCmdGroups[i].dwFlags);
pGroup = AddCommandGroup(pContext,
pChildContext->pCmdGroups[i].pwszCmdGroupToken,
pChildContext->pCmdGroups[i].dwShortCmdHelpToken,
pChildContext->pCmdGroups[i].dwFlags);
if (pGroup != NULL)
{
for (j = 0; j < pChildContext->pCmdGroups[i].ulCmdGroupSize; j++)
{
AddGroupCommand(pGroup,
pChildContext->pCmdGroups[i].pCmdGroup[j].pwszCmdToken,
pChildContext->pCmdGroups[i].pCmdGroup[j].pfnCmdHandler,
pChildContext->pCmdGroups[i].pCmdGroup[j].dwShortCmdHelpToken,
pChildContext->pCmdGroups[i].pCmdGroup[j].dwCmdHlpToken,
pChildContext->pCmdGroups[i].pCmdGroup[j].dwFlags);
}
}
}
}
return ERROR_SUCCESS;
}
VOID
CleanupContext(VOID)
{
/* Delete the context stack */
}

View File

@@ -36,17 +36,11 @@ GetContextFullName(
static
VOID
HelpContext(
PCONTEXT_ENTRY pContext)
PrintCurrentContextHeader(
_In_ PCONTEXT_ENTRY pContext)
{
PCONTEXT_ENTRY pSubContext;
PCOMMAND_ENTRY pCommand;
PCOMMAND_GROUP pGroup;
WCHAR szBuffer[80];
if (pContext != pRootContext)
HelpContext(pContext->pParentContext);
if (pContext == pCurrentContext)
{
ConPrintf(StdOut, L"\nCommands in this context:\n");
@@ -60,6 +54,16 @@ HelpContext(
GetContextFullName(pContext, szBuffer, 80);
ConPrintf(StdOut, L"\nCommands in the %s-context:\n", szBuffer);
}
}
static
VOID
PrintShortCommands(
_In_ PCONTEXT_ENTRY pContext)
{
PCOMMAND_ENTRY pCommand;
WCHAR szBuffer[80];
pCommand = pContext->pCommandListHead;
while (pCommand != NULL)
@@ -69,6 +73,16 @@ HelpContext(
ConPrintf(StdOut, L"%-15s - %s\n", pCommand->pwszCmdToken, szBuffer);
pCommand = pCommand->pNext;
}
}
static
VOID
PrintShortGroups(
_In_ PCONTEXT_ENTRY pContext)
{
PCOMMAND_GROUP pGroup;
WCHAR szBuffer[80];
pGroup = pContext->pGroupListHead;
while (pGroup != NULL)
@@ -78,6 +92,16 @@ HelpContext(
ConPrintf(StdOut, L"%-15s - %s\n", pGroup->pwszCmdGroupToken, szBuffer);
pGroup = pGroup->pNext;
}
}
static
VOID
PrintShortSubContexts(
_In_ PCONTEXT_ENTRY pContext)
{
PCONTEXT_ENTRY pSubContext;
WCHAR szBuffer[80];
pSubContext = pContext->pSubContextHead;
while (pSubContext != NULL)
@@ -88,29 +112,203 @@ HelpContext(
}
}
static
VOID
HelpGroup(
PCOMMAND_GROUP pGroup)
PrintShortGroupCommands(
_In_ PCONTEXT_ENTRY pContext,
_In_ PCOMMAND_GROUP pGroup)
{
PCOMMAND_ENTRY pCommand;
WCHAR szBuffer[64];
ConResPrintf(StdOut, IDS_HELP_HEADER);
ConPrintf(StdOut, L"\nCommands in this context:\n");
WCHAR szBuffer1[64];
WCHAR szBuffer2[80];
pCommand = pGroup->pCommandListHead;
while (pCommand != NULL)
{
swprintf(szBuffer, L"%s %s", pGroup->pwszCmdGroupToken, pCommand->pwszCmdToken);
ConPrintf(StdOut, L"%-15s - ", szBuffer);
ConResPuts(StdOut, pCommand->dwShortCmdHelpToken);
swprintf(szBuffer1, L"%s %s", pGroup->pwszCmdGroupToken, pCommand->pwszCmdToken);
LoadStringW(pContext->hModule, pCommand->dwShortCmdHelpToken, szBuffer2, 80);
ConPrintf(StdOut, L"%-15s - %s\n", szBuffer1, szBuffer2);
pCommand = pCommand->pNext;
}
}
static
VOID
PrintLongCommand(
_In_ PCONTEXT_ENTRY pContext,
_In_ PCOMMAND_ENTRY pCommand)
{
WCHAR szBuffer[80];
LoadStringW(pContext->hModule, pCommand->dwCmdHlpToken, szBuffer, 80);
ConPrintf(StdOut, szBuffer);
}
static
VOID
PrintContext(
_In_ PCONTEXT_ENTRY pContext)
{
DPRINT1("PrintContext()\n");
if (pContext != pRootContext)
PrintContext(pContext->pParentContext);
PrintCurrentContextHeader(pContext);
PrintShortCommands(pContext);
PrintShortGroups(pContext);
PrintShortSubContexts(pContext);
}
static
VOID
PrintGroup(
_In_ PCONTEXT_ENTRY pContext,
_In_ LPWSTR pszGroupName,
_In_ BOOL bRecurse)
{
PCOMMAND_GROUP pGroup;
if (bRecurse)
{
if (pContext != pRootContext)
PrintGroup(pContext->pParentContext, pszGroupName, bRecurse);
}
pGroup = pContext->pGroupListHead;
while (pGroup != NULL)
{
if (_wcsicmp(pszGroupName, pGroup->pwszCmdGroupToken) == 0)
{
PrintCurrentContextHeader(pContext);
PrintShortGroupCommands(pContext, pGroup);
}
pGroup = pGroup->pNext;
}
}
static
VOID
PrintSubcontexts(
_In_ PCONTEXT_ENTRY pContext)
{
if (pCurrentContext->pSubContextHead != NULL)
{
ConResPrintf(StdOut, IDS_SUBCONTEXT_HEADER);
pContext = pCurrentContext->pSubContextHead;
while (pContext != NULL)
{
ConPrintf(StdOut, L" %s", pContext->pszContextName);
pContext = pContext->pNext;
}
ConPuts(StdOut, L"\n");
}
}
BOOL
ProcessHelp(
_In_ PCONTEXT_ENTRY pContext,
_In_ DWORD dwArgCount,
_In_ LPWSTR *argv,
_In_ DWORD dwCurrentIndex,
_In_ DWORD dwHelpLevel)
{
PCONTEXT_ENTRY pSubContext;
PCOMMAND_ENTRY pCommand;
PCOMMAND_GROUP pGroup;
DPRINT("ProcessHelp(dwCurrentIndex %lu dwArgCount %lu dwHelpLevel %lu)\n", dwCurrentIndex, dwArgCount, dwHelpLevel);
if (dwHelpLevel == dwCurrentIndex)
{
ConResPrintf(StdOut, IDS_HELP_HEADER);
PrintContext(pContext);
PrintSubcontexts(pContext);
ConResPrintf(StdOut, IDS_HELP_FOOTER);
return TRUE;
}
pCommand = pContext->pCommandListHead;
while (pCommand != NULL)
{
if (_wcsicmp(argv[dwCurrentIndex], pCommand->pwszCmdToken) == 0)
{
if (dwHelpLevel == dwCurrentIndex + 1)
{
PrintLongCommand(pContext, pCommand);
return TRUE;
}
}
pCommand = pCommand->pNext;
}
pGroup = pContext->pGroupListHead;
while (pGroup != NULL)
{
if (_wcsicmp(argv[dwCurrentIndex], pGroup->pwszCmdGroupToken) == 0)
{
if (dwHelpLevel == dwCurrentIndex + 1)
{
ConResPrintf(StdOut, IDS_HELP_HEADER);
PrintGroup(pContext, argv[dwCurrentIndex], (dwHelpLevel == 1));
return TRUE;
}
pCommand = pGroup->pCommandListHead;
while (pCommand != NULL)
{
if ((dwArgCount > dwCurrentIndex + 1) && (_wcsicmp(argv[dwCurrentIndex + 1], pCommand->pwszCmdToken) == 0))
{
if (dwHelpLevel == dwCurrentIndex + 2)
{
PrintLongCommand(pContext, pCommand);
return TRUE;
}
}
pCommand = pCommand->pNext;
}
// ConResPrintf(StdOut, IDS_HELP_HEADER);
// PrintGroup(pContext, pGroup);
return FALSE;
}
pGroup = pGroup->pNext;
}
if (pContext == pCurrentContext)
{
pSubContext = pContext->pSubContextHead;
while (pSubContext != NULL)
{
if (_wcsicmp(argv[dwCurrentIndex], pSubContext->pszContextName) == 0)
{
return ProcessHelp(pSubContext,
dwArgCount,
argv,
dwCurrentIndex + 1,
dwHelpLevel);
}
pSubContext = pSubContext->pNext;
}
}
return FALSE;
}
DWORD
WINAPI
HelpCommand(
@@ -122,31 +320,5 @@ HelpCommand(
LPCVOID pvData,
BOOL *pbDone)
{
PCONTEXT_ENTRY pContext;
ConResPrintf(StdOut, IDS_HELP_HEADER);
pContext = pCurrentContext;
if (pContext == NULL)
{
DPRINT1("HelpCommand: invalid context %p\n", pContext);
return 1;
}
HelpContext(pContext);
if (pCurrentContext->pSubContextHead != NULL)
{
ConResPrintf(StdOut, IDS_SUBCONTEXT_HEADER);
pContext = pCurrentContext->pSubContextHead;
while (pContext != NULL)
{
ConPrintf(StdOut, L" %s", pContext->pszContextName);
pContext = pContext->pNext;
}
ConPuts(StdOut, L"\n");
}
ConPuts(StdOut, L"\n");
return ERROR_SUCCESS;
}

View File

@@ -26,12 +26,12 @@ PDLL_LIST_ENTRY pCurrentDll = NULL;
static
VOID
StartHelpers(VOID)
StartHelpers(
PHELPER_ENTRY pHelper)
{
PHELPER_ENTRY pHelper;
PHELPER_ENTRY pSubHelper;
DWORD dwError;
pHelper = pHelperListHead;
while (pHelper != NULL)
{
if (pHelper->bStarted == FALSE)
@@ -44,6 +44,13 @@ StartHelpers(VOID)
}
}
pSubHelper = pHelper->pSubHelperHead;
while (pSubHelper != NULL)
{
StartHelpers(pSubHelper);
pSubHelper = pSubHelper->pNext;
}
pHelper = pHelper->pNext;
}
}
@@ -310,7 +317,7 @@ done:
RegCloseKey(hKey);
StartHelpers();
StartHelpers(pHelperListHead);
}
@@ -336,16 +343,21 @@ UnloadHelpers(VOID)
PHELPER_ENTRY
FindHelper(
_In_ const GUID *pguidHelper)
_In_ const GUID *pguidHelper,
_In_ PHELPER_ENTRY pHelper)
{
PHELPER_ENTRY pHelper;
PHELPER_ENTRY pFoundHelper;
pHelper = pHelperListHead;
// pHelper = pHelperListHead;
while (pHelper != NULL)
{
if (IsEqualGUID(pguidHelper, &pHelper->Attributes.guidHelper))
return pHelper;
pFoundHelper = FindHelper(pguidHelper, pHelper->pSubHelperHead);
if (pFoundHelper)
return pFoundHelper;
pHelper = pHelper->pNext;
}
@@ -364,7 +376,7 @@ RegisterHelper(
DPRINT("RegisterHelper(%p %p)\n", pguidParentHelper, pHelperAttributes);
if (FindHelper(&pHelperAttributes->guidHelper) != NULL)
if (FindHelper(&pHelperAttributes->guidHelper, pHelperListHead) != NULL)
{
DPRINT1("The Helper has already been registered!\n");
return 1;
@@ -397,9 +409,12 @@ RegisterHelper(
}
else
{
pParentHelper = FindHelper(&pHelperAttributes->guidHelper);
pParentHelper = FindHelper(pguidParentHelper, pHelperListHead);
if (pParentHelper == NULL)
{
DPRINT("Parent helper not found!\n");
return ERROR_INVALID_PARAMETER;
}
if (pParentHelper->pSubHelperHead == NULL && pParentHelper->pSubHelperTail == NULL)
{
@@ -446,7 +461,7 @@ AddHelperCommand(
if (dwError != ERROR_SUCCESS)
return dwError;
StartHelpers();
StartHelpers(pHelperListHead);
return ERROR_SUCCESS;
}
@@ -528,13 +543,15 @@ PrintSubContext(
WCHAR szPrefix[22];
DWORD i;
DPRINT("PrintSubContext(%p %lu)\n", pParentContext, dwLevel);
if (pParentContext == NULL)
return;
pContext = pParentContext->pSubContextHead;
while (pContext != NULL)
{
pHelper = FindHelper(&pContext->Guid);
pHelper = FindHelper(&pContext->Guid, pHelperListHead);
if (pHelper != NULL)
{
if (dwLevel > 10)
@@ -542,7 +559,9 @@ PrintSubContext(
for (i = 0; i < dwLevel * 2; i++)
szPrefix[i] = L' ';
szPrefix[i] = UNICODE_NULL;
szPrefix[dwLevel * 2] = UNICODE_NULL;
DPRINT("Level %lu \"%S\" %S\n", dwLevel, szPrefix, pContext->pszContextName);
ConPrintf(StdOut, L"{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X} %-16s %s%s\n",
pHelper->Attributes.guidHelper.Data1,

View File

@@ -15,15 +15,17 @@
/* FUNCTIONS *****************************************************************/
BOOL
InterpretCommand(
ProcessCommand(
_In_ PCONTEXT_ENTRY pContext,
_In_ DWORD dwArgCount,
_In_ LPWSTR *argv,
_In_ DWORD dwArgCount)
_In_ DWORD dwCurrentIndex,
_In_ DWORD dwHelpLevel,
_Inout_ PBOOL bDone)
{
PCONTEXT_ENTRY pContext, pSubContext;
PCONTEXT_ENTRY pSubContext;
PCOMMAND_ENTRY pCommand;
PCOMMAND_GROUP pGroup;
BOOL bDone = FALSE;
DWORD dwHelpLevel = 0;
DWORD dwError = ERROR_SUCCESS;
/* If no args provided */
@@ -51,21 +53,13 @@ InterpretCommand(
{
if (_wcsicmp(argv[0], pCommand->pwszCmdToken) == 0)
{
if (dwHelpLevel == 1)
dwError = pCommand->pfnCmdHandler(NULL, argv, dwCurrentIndex, dwArgCount, 0, NULL, bDone);
if (dwError != ERROR_SUCCESS)
{
ConPrintf(StdOut, L"Error: %lu\n\n", dwError);
ConResPrintf(StdOut, pCommand->dwCmdHlpToken);
return TRUE;
}
else
{
dwError = pCommand->pfnCmdHandler(NULL, argv, 0, dwArgCount, 0, NULL, &bDone);
if (dwError != ERROR_SUCCESS)
{
ConPrintf(StdOut, L"Error: %lu\n\n");
ConResPrintf(StdOut, pCommand->dwCmdHlpToken);
}
return !bDone;
}
return TRUE;
}
pCommand = pCommand->pNext;
@@ -76,40 +70,33 @@ InterpretCommand(
{
if (_wcsicmp(argv[0], pGroup->pwszCmdGroupToken) == 0)
{
if (dwHelpLevel == 1)
if (dwArgCount == 1)
{
HelpGroup(pGroup);
ProcessHelp(pContext, dwArgCount, argv, dwCurrentIndex, dwHelpLevel + 1);
return TRUE;
}
pCommand = pGroup->pCommandListHead;
while (pCommand != NULL)
else
{
if ((dwArgCount > 1) && (_wcsicmp(argv[1], pCommand->pwszCmdToken) == 0))
pCommand = pGroup->pCommandListHead;
while (pCommand != NULL)
{
if (dwHelpLevel == 2)
if ((dwArgCount > 1) && (_wcsicmp(argv[1], pCommand->pwszCmdToken) == 0))
// if ((dwArgCount > dwCurrentIndex + 1) && (wcsicmp(argv[dwCurrentIndex + 1], pCommand->pwszCmdToken) == 0))
{
ConResPrintf(StdOut, pCommand->dwCmdHlpToken);
return TRUE;
}
else
{
dwError = pCommand->pfnCmdHandler(NULL, argv, 1, dwArgCount, 0, NULL, &bDone);
dwError = pCommand->pfnCmdHandler(NULL, argv, dwCurrentIndex + 1, dwArgCount, 0, NULL, bDone);
if (dwError != ERROR_SUCCESS)
{
ConPrintf(StdOut, L"Error: %lu\n\n");
ConPrintf(StdOut, L"Error: %lu\n\n", dwError);
ConResPrintf(StdOut, pCommand->dwCmdHlpToken);
return TRUE;
}
return !bDone;
return TRUE;
}
pCommand = pCommand->pNext;
}
pCommand = pCommand->pNext;
return FALSE;
}
HelpGroup(pGroup);
return TRUE;
}
pGroup = pGroup->pNext;
@@ -122,8 +109,21 @@ InterpretCommand(
{
if (_wcsicmp(argv[0], pSubContext->pszContextName) == 0)
{
pCurrentContext = pSubContext;
return TRUE;
DPRINT("%S ==> dwCurrentIndex: %lu dwArgCount: %lu\n", argv[dwCurrentIndex], dwCurrentIndex, dwArgCount);
if (dwArgCount == dwCurrentIndex + 1)
{
pCurrentContext = pSubContext;
return TRUE;
}
else
{
return ProcessCommand(pSubContext,
dwArgCount,
argv,
dwCurrentIndex + 1,
dwHelpLevel,
bDone);
}
}
pSubContext = pSubContext->pNext;
@@ -136,9 +136,44 @@ InterpretCommand(
pContext = pContext->pParentContext;
}
ConResPrintf(StdErr, IDS_INVALID_COMMAND, argv[0]);
return FALSE;
}
return TRUE;
BOOL
InterpretCommand(
_In_ LPWSTR *argv,
_In_ DWORD dwArgCount,
_Inout_ PBOOL bDone)
{
/* If no args provided */
if (dwArgCount == 0)
return TRUE;
if (pCurrentContext == NULL)
{
DPRINT("InterpretCmd: invalid context %p\n", pCurrentContext);
return FALSE;
}
if ((_wcsicmp(argv[dwArgCount - 1], L"?") == 0) ||
(_wcsicmp(argv[dwArgCount - 1], L"help") == 0))
{
return ProcessHelp(pCurrentContext,
dwArgCount,
argv,
0,
dwArgCount - 1);
}
else
{
return ProcessCommand(pCurrentContext,
dwArgCount,
argv,
0,
0,
bDone);
}
}
@@ -153,6 +188,7 @@ InterpretScript(
LPWSTR args_vector[MAX_ARGS_COUNT];
DWORD dwArgCount = 0;
BOOL bWhiteSpace = TRUE;
BOOL bDone = FALSE;
LPWSTR ptr;
memset(args_vector, 0, sizeof(args_vector));
@@ -180,7 +216,7 @@ InterpretScript(
}
/* sends the string to find the command */
return InterpretCommand(args_vector, dwArgCount);
return InterpretCommand(args_vector, dwArgCount, &bDone) == ERROR_SUCCESS;
}
@@ -191,16 +227,15 @@ InterpretInteractive(VOID)
LPWSTR args_vector[MAX_ARGS_COUNT];
DWORD dwArgCount = 0;
BOOL bWhiteSpace = TRUE;
BOOL bRun = TRUE;
BOOL bDone = FALSE;
LPWSTR ptr;
while (bRun != FALSE)
for (;;)
{
dwArgCount = 0;
memset(args_vector, 0, sizeof(args_vector));
/* Shown just before the input where the user places commands */
// ConResPuts(StdOut, IDS_APP_PROMPT);
ConPuts(StdOut, L"netsh");
if (pCurrentContext != pRootContext)
{
@@ -233,6 +268,12 @@ InterpretInteractive(VOID)
}
/* Send the string to find the command */
bRun = InterpretCommand(args_vector, dwArgCount);
if (InterpretCommand(args_vector, dwArgCount, &bDone) == FALSE)
{
ConResPrintf(StdErr, IDS_INVALID_COMMAND, input_line);
}
if (bDone)
break;
}
}

View File

@@ -19,14 +19,20 @@ END
STRINGTABLE
BEGIN
IDS_HELP_HEADER "\nThe following commands are available:\n"
IDS_HELP_HEADER "\nThe following commands are available:\n"
IDS_HELP_FOOTER "\nHelp Footer\n\n"
IDS_SUBCONTEXT_HEADER "\nThe following sub-contexts are available:\n"
IDS_HLP_UP "Goes up one context level."
IDS_HLP_UP_EX "Syntax: ..\n\n Goes up one context level.\n\n"
IDS_HLP_EXIT "Exits the program."
IDS_HLP_EXIT_EX "Syntax: exit\n\n Exits the program.\n\n"
IDS_HLP_HELP "Displays a list of commands."
IDS_HLP_HELP_EX "Syntax: help\n\n Displays a list of commands.\n\n"
IDS_HLP_POPD "Changes to the context on the stack."
IDS_HLP_POPD_EX "Syntax: popd\n\n Changes to the context on the stack.\n\n"
IDS_HLP_PUSHD "Stores the current context on the stack."
IDS_HLP_PUSHD_EX "Syntax: pushd\n\n Stores the current context on the stack.\n\n"
IDS_HLP_ADD_HELPER "Installs a helper DLL."
IDS_HLP_ADD_HELPER_EX "Syntax: add helper <dll file name>\n\n Installs the specified helper DLL in netsh.\n\n"

View File

@@ -58,8 +58,9 @@ wmain(
LPCWSTR pszFileName = NULL;
int index;
int result = EXIT_SUCCESS;
BOOL bDone = FALSE;
DPRINT("main()\n");
DPRINT("wmain(%S)\n", GetCommandLineW());
/* Initialize the Console Standard Streams */
ConInitStdStreams();
@@ -93,7 +94,7 @@ wmain(
}
/* Run a command from the command line */
if (InterpretCommand((LPWSTR*)&argv[index], argc - index) == FALSE)
if (InterpretCommand((LPWSTR*)&argv[index], argc - index, &bDone) != ERROR_SUCCESS)
result = EXIT_FAILURE;
goto done;
}
@@ -186,6 +187,7 @@ wmain(
done:
/* FIXME: Cleanup code goes here */
CleanupContext();
UnloadHelpers();
return result;
@@ -247,7 +249,7 @@ PrintMessage(
va_list ap;
va_start(ap, pwszFormat);
Length = ConPrintf(StdOut, pwszFormat);
Length = ConPrintfV(StdOut, pwszFormat, ap);
va_end(ap);
return Length;

View File

@@ -100,6 +100,7 @@ typedef struct _CONTEXT_ENTRY
struct _CONTEXT_ENTRY *pNext;
struct _CONTEXT_ENTRY *pParentContext;
// PHELPER_ENTRY pHelper;
PWSTR pszContextName;
GUID Guid;
@@ -121,6 +122,7 @@ typedef struct _CONTEXT_ENTRY
extern PCONTEXT_ENTRY pRootContext;
extern PCONTEXT_ENTRY pCurrentContext;
extern PHELPER_ENTRY pHelperListHead;
/* PROTOTYPES *****************************************************************/
@@ -129,8 +131,21 @@ extern PCONTEXT_ENTRY pCurrentContext;
BOOL
CreateRootContext(VOID);
VOID
CleanupContext(VOID);
/* help.c */
BOOL
ProcessHelp(
_In_ PCONTEXT_ENTRY pContext,
_In_ DWORD dwCurrentIndex,
_In_ LPWSTR *argv,
_In_ DWORD dwArgCount,
_In_ DWORD dwHelpLevel);
DWORD
WINAPI
HelpCommand(
@@ -142,10 +157,21 @@ HelpCommand(
LPCVOID pvData,
BOOL *pbDone);
#if 0
VOID
HelpGroup(
PCOMMAND_GROUP pGroup);
PCONTEXT_ENTRY pContext,
LPWSTR pszGroupName,
BOOL bRecurse);
VOID
HelpContext(
PCONTEXT_ENTRY pContext);
VOID
HelpSubcontexts(
PCONTEXT_ENTRY pContext);
#endif
/* helper.c */
VOID
@@ -154,6 +180,10 @@ LoadHelpers(VOID);
VOID
UnloadHelpers(VOID);
PHELPER_ENTRY
FindHelper(
_In_ const GUID *pguidHelper,
_In_ PHELPER_ENTRY pHelper);
DWORD
WINAPI
@@ -192,12 +222,13 @@ ShowHelperCommand(
/* interpreter.c */
BOOL
InterpretScript(
LPWSTR pszFileName);
_In_ LPWSTR pszFileName);
BOOL
InterpretCommand(
LPWSTR *argv,
DWORD dwArgCount);
_In_ LPWSTR *argv,
_In_ DWORD dwArgCount,
_Inout_ PBOOL bDone);
VOID
InterpretInteractive(VOID);

View File

@@ -16,7 +16,8 @@
#define IDS_INVALID_SYNTAX 104
#define IDS_HELP_HEADER 200
#define IDS_SUBCONTEXT_HEADER 201
#define IDS_HELP_FOOTER 201
#define IDS_SUBCONTEXT_HEADER 202
#define IDS_HLP_EXIT 300
#define IDS_HLP_EXIT_EX 301
@@ -24,6 +25,10 @@
#define IDS_HLP_HELP_EX 303
#define IDS_HLP_UP 304
#define IDS_HLP_UP_EX 305
#define IDS_HLP_POPD 306
#define IDS_HLP_POPD_EX 307
#define IDS_HLP_PUSHD 308
#define IDS_HLP_PUSHD_EX 309
#define IDS_HLP_ADD_HELPER 310
#define IDS_HLP_ADD_HELPER_EX 311