mirror of
https://github.com/reactos/reactos.git
synced 2024-12-04 08:53:32 +08:00
[NETSH] Replace the wine stub by a slightly more functional version
- Implement a basic command interpreter. - Add basic support for helper dlls and contexts. - Add interactive help system with context support. Everything is still under construction and subject to change.
This commit is contained in:
parent
dabe7fba46
commit
d8f9f7f256
@ -1,8 +1,25 @@
|
||||
|
||||
add_definitions(-D__WINESRC__)
|
||||
include_directories(${REACTOS_SOURCE_DIR}/sdk/include/wine)
|
||||
add_executable(netsh netsh.c)
|
||||
target_link_libraries(netsh wine)
|
||||
include_directories(${REACTOS_SOURCE_DIR}/sdk/lib/conutils)
|
||||
spec2def(netsh.exe netsh.spec ADD_IMPORTLIB)
|
||||
|
||||
list(APPEND SOURCE
|
||||
context.c
|
||||
help.c
|
||||
helper.c
|
||||
interpreter.c
|
||||
netsh.c
|
||||
precomp.h)
|
||||
|
||||
add_executable(netsh ${SOURCE} netsh.rc ${CMAKE_CURRENT_BINARY_DIR}/netsh.def)
|
||||
|
||||
set_target_properties(netsh
|
||||
PROPERTIES
|
||||
ENABLE_EXPORTS TRUE
|
||||
DEFINE_SYMBOL "")
|
||||
|
||||
set_module_type(netsh win32cui UNICODE)
|
||||
add_importlibs(netsh msvcrt kernel32 ntdll)
|
||||
target_link_libraries(netsh conutils ${PSEH_LIB})
|
||||
add_importlibs(netsh advapi32 msvcrt user32 kernel32 ntdll)
|
||||
|
||||
add_pch(netsh precomp.h SOURCE)
|
||||
add_cd_file(TARGET netsh DESTINATION reactos/system32 FOR all)
|
||||
|
374
base/applications/network/netsh/context.c
Normal file
374
base/applications/network/netsh/context.c
Normal file
@ -0,0 +1,374 @@
|
||||
/*
|
||||
* PROJECT: ReactOS NetSh
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: Network Shell context management functions
|
||||
* COPYRIGHT: Copyright 2023 Eric Kohl <eric.kohl@reactos.org>
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include "precomp.h"
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
|
||||
PCONTEXT_ENTRY pRootContext = NULL;
|
||||
PCONTEXT_ENTRY pCurrentContext = NULL;
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
PCONTEXT_ENTRY
|
||||
AddContext(
|
||||
PCONTEXT_ENTRY pParentContext,
|
||||
PWSTR pszName,
|
||||
GUID *pGuid)
|
||||
{
|
||||
PCONTEXT_ENTRY pEntry;
|
||||
|
||||
if (pParentContext != NULL && pszName == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Allocate the entry */
|
||||
pEntry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CONTEXT_ENTRY));
|
||||
if (pEntry == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Allocate the name buffer */
|
||||
if (pszName != NULL)
|
||||
{
|
||||
pEntry->pszContextName = HeapAlloc(GetProcessHeap(),
|
||||
HEAP_ZERO_MEMORY,
|
||||
(wcslen(pszName) + 1) * sizeof(WCHAR));
|
||||
if (pEntry->pszContextName == NULL)
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, pEntry);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Fill the entry */
|
||||
wcscpy(pEntry->pszContextName, pszName);
|
||||
}
|
||||
|
||||
pEntry->pParentContext = pParentContext;
|
||||
if (pGuid != NULL)
|
||||
CopyMemory(&pEntry->Guid, pGuid, sizeof(pEntry->Guid));
|
||||
|
||||
/* Insert it */
|
||||
if (pParentContext != NULL)
|
||||
{
|
||||
if (pParentContext->pSubContextHead == NULL && pParentContext->pSubContextTail == NULL)
|
||||
{
|
||||
pParentContext->pSubContextHead = pEntry;
|
||||
pParentContext->pSubContextTail = pEntry;
|
||||
}
|
||||
else
|
||||
{
|
||||
pEntry->pPrev = pParentContext->pSubContextTail;
|
||||
pParentContext->pSubContextTail->pNext = pEntry;
|
||||
pParentContext->pSubContextTail = pEntry;
|
||||
}
|
||||
}
|
||||
|
||||
return pEntry;
|
||||
}
|
||||
|
||||
|
||||
PCOMMAND_ENTRY
|
||||
AddContextCommand(
|
||||
PCONTEXT_ENTRY pContext,
|
||||
LPCWSTR pwszCmdToken,
|
||||
PFN_HANDLE_CMD pfnCmdHandler,
|
||||
DWORD dwShortCmdHelpToken,
|
||||
DWORD dwCmdHlpToken,
|
||||
DWORD dwFlags)
|
||||
{
|
||||
PCOMMAND_ENTRY pEntry;
|
||||
|
||||
if (pfnCmdHandler == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Allocate the entry */
|
||||
pEntry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(COMMAND_ENTRY));
|
||||
if (pEntry == NULL)
|
||||
return NULL;
|
||||
|
||||
pEntry->pwszCmdToken = HeapAlloc(GetProcessHeap(),
|
||||
HEAP_ZERO_MEMORY,
|
||||
(wcslen(pwszCmdToken) + 1) * sizeof(WCHAR));
|
||||
if (pEntry->pwszCmdToken == NULL)
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, pEntry);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wcscpy((LPWSTR)pEntry->pwszCmdToken, pwszCmdToken);
|
||||
|
||||
pEntry->pfnCmdHandler = pfnCmdHandler;
|
||||
pEntry->dwShortCmdHelpToken = dwShortCmdHelpToken;
|
||||
pEntry->dwCmdHlpToken = dwCmdHlpToken;
|
||||
pEntry->dwFlags = dwFlags;
|
||||
|
||||
if (pContext->pCommandListHead == NULL && pContext->pCommandListTail == NULL)
|
||||
{
|
||||
pContext->pCommandListHead = pEntry;
|
||||
pContext->pCommandListTail = pEntry;
|
||||
}
|
||||
else
|
||||
{
|
||||
pEntry->pPrev = pContext->pCommandListTail;
|
||||
pContext->pCommandListTail->pNext = pEntry;
|
||||
pContext->pCommandListTail = pEntry;
|
||||
}
|
||||
|
||||
return pEntry;
|
||||
}
|
||||
|
||||
|
||||
PCOMMAND_GROUP
|
||||
AddCommandGroup(
|
||||
PCONTEXT_ENTRY pContext,
|
||||
LPCWSTR pwszCmdGroupToken,
|
||||
DWORD dwShortCmdHelpToken,
|
||||
DWORD dwFlags)
|
||||
{
|
||||
PCOMMAND_GROUP pEntry;
|
||||
|
||||
/* Allocate the entry */
|
||||
pEntry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(COMMAND_GROUP));
|
||||
if (pEntry == NULL)
|
||||
return NULL;
|
||||
|
||||
pEntry->pwszCmdGroupToken = HeapAlloc(GetProcessHeap(),
|
||||
HEAP_ZERO_MEMORY,
|
||||
(wcslen(pwszCmdGroupToken) + 1) * sizeof(WCHAR));
|
||||
if (pEntry->pwszCmdGroupToken == NULL)
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, pEntry);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wcscpy((LPWSTR)pEntry->pwszCmdGroupToken, pwszCmdGroupToken);
|
||||
pEntry->dwShortCmdHelpToken = dwShortCmdHelpToken;
|
||||
pEntry->dwFlags = dwFlags;
|
||||
|
||||
if (pContext->pGroupListHead == NULL && pContext->pGroupListTail == NULL)
|
||||
{
|
||||
pContext->pGroupListHead = pEntry;
|
||||
pContext->pGroupListTail = pEntry;
|
||||
}
|
||||
else
|
||||
{
|
||||
pEntry->pPrev = pContext->pGroupListTail;
|
||||
pContext->pGroupListTail->pNext = pEntry;
|
||||
pContext->pGroupListTail = pEntry;
|
||||
}
|
||||
|
||||
return pEntry;
|
||||
}
|
||||
|
||||
|
||||
PCOMMAND_ENTRY
|
||||
AddGroupCommand(
|
||||
PCOMMAND_GROUP pGroup,
|
||||
LPCWSTR pwszCmdToken,
|
||||
PFN_HANDLE_CMD pfnCmdHandler,
|
||||
DWORD dwShortCmdHelpToken,
|
||||
DWORD dwCmdHlpToken,
|
||||
DWORD dwFlags)
|
||||
{
|
||||
PCOMMAND_ENTRY pEntry;
|
||||
|
||||
if (pfnCmdHandler == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Allocate the entry */
|
||||
pEntry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(COMMAND_ENTRY));
|
||||
if (pEntry == NULL)
|
||||
return NULL;
|
||||
|
||||
pEntry->pwszCmdToken = HeapAlloc(GetProcessHeap(),
|
||||
HEAP_ZERO_MEMORY,
|
||||
(wcslen(pwszCmdToken) + 1) * sizeof(WCHAR));
|
||||
if (pEntry->pwszCmdToken == NULL)
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, pEntry);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wcscpy((LPWSTR)pEntry->pwszCmdToken, pwszCmdToken);
|
||||
|
||||
pEntry->pfnCmdHandler = pfnCmdHandler;
|
||||
pEntry->dwShortCmdHelpToken = dwShortCmdHelpToken;
|
||||
pEntry->dwCmdHlpToken = dwCmdHlpToken;
|
||||
pEntry->dwFlags = dwFlags;
|
||||
|
||||
if (pGroup->pCommandListHead == NULL && pGroup->pCommandListTail == NULL)
|
||||
{
|
||||
pGroup->pCommandListHead = pEntry;
|
||||
pGroup->pCommandListTail = pEntry;
|
||||
}
|
||||
else
|
||||
{
|
||||
pEntry->pPrev = pGroup->pCommandListTail;
|
||||
pGroup->pCommandListTail->pNext = pEntry;
|
||||
pGroup->pCommandListTail = pEntry;
|
||||
}
|
||||
|
||||
return pEntry;
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
DeleteContext(
|
||||
PWSTR pszName)
|
||||
{
|
||||
/* Delete all commands */
|
||||
/* Delete the context */
|
||||
}
|
||||
|
||||
|
||||
DWORD
|
||||
WINAPI
|
||||
UpCommand(
|
||||
LPCWSTR pwszMachine,
|
||||
LPWSTR *argv,
|
||||
DWORD dwCurrentIndex,
|
||||
DWORD dwArgCount,
|
||||
DWORD dwFlags,
|
||||
LPCVOID pvData,
|
||||
BOOL *pbDone)
|
||||
{
|
||||
if (pCurrentContext != pRootContext)
|
||||
pCurrentContext = pCurrentContext->pParentContext;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
DWORD
|
||||
WINAPI
|
||||
ExitCommand(
|
||||
LPCWSTR pwszMachine,
|
||||
LPWSTR *argv,
|
||||
DWORD dwCurrentIndex,
|
||||
DWORD dwArgCount,
|
||||
DWORD dwFlags,
|
||||
LPCVOID pvData,
|
||||
BOOL *pbDone)
|
||||
{
|
||||
*pbDone = TRUE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
DWORD
|
||||
WINAPI
|
||||
RemCommand(
|
||||
LPCWSTR pwszMachine,
|
||||
LPWSTR *argv,
|
||||
DWORD dwCurrentIndex,
|
||||
DWORD dwArgCount,
|
||||
DWORD dwFlags,
|
||||
LPCVOID pvData,
|
||||
BOOL *pbDone)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
BOOL
|
||||
CreateRootContext(VOID)
|
||||
{
|
||||
PCOMMAND_GROUP pGroup;
|
||||
|
||||
pRootContext = AddContext(NULL, NULL, NULL);
|
||||
DPRINT1("pRootContext: %p\n", pRootContext);
|
||||
if (pRootContext == NULL)
|
||||
return FALSE;
|
||||
|
||||
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);
|
||||
|
||||
pGroup = AddCommandGroup(pRootContext, L"add", IDS_HLP_GROUP_ADD, 0);
|
||||
if (pGroup)
|
||||
{
|
||||
AddGroupCommand(pGroup, L"helper", AddHelperCommand, IDS_HLP_ADD_HELPER, IDS_HLP_ADD_HELPER_EX, 0);
|
||||
}
|
||||
|
||||
pGroup = AddCommandGroup(pRootContext, L"delete", IDS_HLP_GROUP_DELETE, 0);
|
||||
if (pGroup)
|
||||
{
|
||||
AddGroupCommand(pGroup, L"helper", DeleteHelperCommand, IDS_HLP_DEL_HELPER, IDS_HLP_DEL_HELPER_EX, 0);
|
||||
}
|
||||
|
||||
pGroup = AddCommandGroup(pRootContext, L"show", IDS_HLP_GROUP_SHOW, 0);
|
||||
if (pGroup)
|
||||
{
|
||||
AddGroupCommand(pGroup, L"helper", ShowHelperCommand, IDS_HLP_SHOW_HELPER, IDS_HLP_SHOW_HELPER_EX, 0);
|
||||
}
|
||||
|
||||
pCurrentContext = pRootContext;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
DWORD
|
||||
WINAPI
|
||||
RegisterContext(
|
||||
_In_ const NS_CONTEXT_ATTRIBUTES *pChildContext)
|
||||
{
|
||||
PCONTEXT_ENTRY pContext;
|
||||
DWORD i;
|
||||
|
||||
DPRINT1("RegisterContext(%p)\n", pChildContext);
|
||||
if (pChildContext == NULL)
|
||||
{
|
||||
DPRINT1("Invalid child context!\n");
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if ((pChildContext->pwszContext == NULL) ||
|
||||
(wcslen(pChildContext->pwszContext) == 0) ||
|
||||
(wcschr(pChildContext->pwszContext, L' ') != 0) ||
|
||||
(wcschr(pChildContext->pwszContext, L'=') != 0))
|
||||
{
|
||||
DPRINT1("Invalid context name!\n");
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
DPRINT1("Name: %S\n", pChildContext->pwszContext);
|
||||
|
||||
pContext = AddContext(pRootContext, pChildContext->pwszContext, (GUID*)&pChildContext->guidHelper);
|
||||
if (pContext != NULL)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
/* Add command groups */
|
||||
for (i = 0; i < pChildContext->ulNumGroups; i++)
|
||||
{
|
||||
AddCommandGroup(pContext,
|
||||
pChildContext->pCmdGroups[i].pwszCmdGroupToken,
|
||||
pChildContext->pCmdGroups[i].dwShortCmdHelpToken,
|
||||
pChildContext->pCmdGroups[i].dwFlags);
|
||||
}
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
152
base/applications/network/netsh/help.c
Normal file
152
base/applications/network/netsh/help.c
Normal file
@ -0,0 +1,152 @@
|
||||
/*
|
||||
* PROJECT: ReactOS NetSh
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: Network Shell builtin help command and support functions
|
||||
* COPYRIGHT: Copyright 2023 Eric Kohl <eric.kohl@reactos.org>
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include "precomp.h"
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
static
|
||||
VOID
|
||||
GetContextFullName(
|
||||
_In_ PCONTEXT_ENTRY pContext,
|
||||
_Inout_ LPWSTR pszBuffer,
|
||||
_In_ DWORD cchLength)
|
||||
{
|
||||
if (pContext->pParentContext != NULL)
|
||||
{
|
||||
GetContextFullName(pContext->pParentContext, pszBuffer, cchLength);
|
||||
wcscat(pszBuffer, L" ");
|
||||
wcscat(pszBuffer, pContext->pszContextName);
|
||||
}
|
||||
else
|
||||
{
|
||||
wcscpy(pszBuffer, L"netsh");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
VOID
|
||||
HelpContext(
|
||||
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");
|
||||
}
|
||||
else if (pContext == pRootContext)
|
||||
{
|
||||
ConPrintf(StdOut, L"\nCommands in the netsh-context:\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
GetContextFullName(pContext, szBuffer, 80);
|
||||
ConPrintf(StdOut, L"\nCommands in the %s-context:\n", szBuffer);
|
||||
}
|
||||
|
||||
pCommand = pContext->pCommandListHead;
|
||||
while (pCommand != NULL)
|
||||
{
|
||||
if (LoadStringW(pContext->hModule, pCommand->dwShortCmdHelpToken, szBuffer, 80) == 0)
|
||||
szBuffer[0] = UNICODE_NULL;
|
||||
ConPrintf(StdOut, L"%-15s - %s\n", pCommand->pwszCmdToken, szBuffer);
|
||||
pCommand = pCommand->pNext;
|
||||
}
|
||||
|
||||
pGroup = pContext->pGroupListHead;
|
||||
while (pGroup != NULL)
|
||||
{
|
||||
if (LoadStringW(pContext->hModule, pGroup->dwShortCmdHelpToken, szBuffer, 80) == 0)
|
||||
szBuffer[0] = UNICODE_NULL;
|
||||
ConPrintf(StdOut, L"%-15s - %s\n", pGroup->pwszCmdGroupToken, szBuffer);
|
||||
pGroup = pGroup->pNext;
|
||||
}
|
||||
|
||||
pSubContext = pContext->pSubContextHead;
|
||||
while (pSubContext != NULL)
|
||||
{
|
||||
GetContextFullName(pSubContext, szBuffer, 80);
|
||||
ConPrintf(StdOut, L"%-15s - Changes to the \"%s\" context.\n", pSubContext->pszContextName, szBuffer);
|
||||
pSubContext = pSubContext->pNext;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
HelpGroup(
|
||||
PCOMMAND_GROUP pGroup)
|
||||
{
|
||||
PCOMMAND_ENTRY pCommand;
|
||||
WCHAR szBuffer[64];
|
||||
|
||||
ConResPrintf(StdOut, IDS_HELP_HEADER);
|
||||
|
||||
ConPrintf(StdOut, L"\nCommands in this context:\n");
|
||||
|
||||
pCommand = pGroup->pCommandListHead;
|
||||
while (pCommand != NULL)
|
||||
{
|
||||
swprintf(szBuffer, L"%s %s", pGroup->pwszCmdGroupToken, pCommand->pwszCmdToken);
|
||||
ConPrintf(StdOut, L"%-15s - ", szBuffer);
|
||||
ConResPuts(StdOut, pCommand->dwShortCmdHelpToken);
|
||||
pCommand = pCommand->pNext;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DWORD
|
||||
WINAPI
|
||||
HelpCommand(
|
||||
LPCWSTR pwszMachine,
|
||||
LPWSTR *ppwcArguments,
|
||||
DWORD dwCurrentIndex,
|
||||
DWORD dwArgCount,
|
||||
DWORD dwFlags,
|
||||
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;
|
||||
}
|
593
base/applications/network/netsh/helper.c
Normal file
593
base/applications/network/netsh/helper.c
Normal file
@ -0,0 +1,593 @@
|
||||
/*
|
||||
* PROJECT: ReactOS NetSh
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: Network Shell helper dll management and support functions
|
||||
* COPYRIGHT: Copyright 2023 Eric Kohl <eric.kohl@reactos.org>
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include "precomp.h"
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
|
||||
PDLL_LIST_ENTRY pDllListHead = NULL;
|
||||
PDLL_LIST_ENTRY pDllListTail = NULL;
|
||||
|
||||
PHELPER_ENTRY pHelperListHead = NULL;
|
||||
PHELPER_ENTRY pHelperListTail = NULL;
|
||||
|
||||
PDLL_LIST_ENTRY pCurrentDll = NULL;
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
static
|
||||
VOID
|
||||
StartHelpers(VOID)
|
||||
{
|
||||
PHELPER_ENTRY pHelper;
|
||||
DWORD dwError;
|
||||
|
||||
pHelper = pHelperListHead;
|
||||
while (pHelper != NULL)
|
||||
{
|
||||
if (pHelper->bStarted == FALSE)
|
||||
{
|
||||
if (pHelper->Attributes.pfnStart)
|
||||
{
|
||||
dwError = pHelper->Attributes.pfnStart(NULL, 0);
|
||||
if (dwError == ERROR_SUCCESS)
|
||||
pHelper->bStarted = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
pHelper = pHelper->pNext;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
VOID
|
||||
RegisterHelperDll(
|
||||
_In_ PDLL_LIST_ENTRY pEntry)
|
||||
{
|
||||
PWSTR pszValueName = NULL;
|
||||
HKEY hKey;
|
||||
DWORD dwError;
|
||||
|
||||
dwError = RegCreateKeyExW(HKEY_LOCAL_MACHINE,
|
||||
REG_NETSH_PATH,
|
||||
0,
|
||||
NULL,
|
||||
REG_OPTION_NON_VOLATILE,
|
||||
KEY_WRITE,
|
||||
NULL,
|
||||
&hKey,
|
||||
NULL);
|
||||
if (dwError == ERROR_SUCCESS)
|
||||
{
|
||||
RegSetValueExW(hKey,
|
||||
pEntry->pszValueName,
|
||||
0,
|
||||
REG_SZ,
|
||||
(PBYTE)pEntry->pszDllName,
|
||||
(wcslen(pEntry->pszDllName) + 1) * sizeof(WCHAR));
|
||||
|
||||
RegCloseKey(hKey);
|
||||
}
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, pszValueName);
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
VOID
|
||||
FreeHelperDll(
|
||||
_In_ PDLL_LIST_ENTRY pEntry)
|
||||
{
|
||||
if (pEntry->hModule)
|
||||
FreeLibrary(pEntry->hModule);
|
||||
|
||||
if (pEntry->pszValueName)
|
||||
HeapFree(GetProcessHeap(), 0, pEntry->pszValueName);
|
||||
|
||||
if (pEntry->pszShortName)
|
||||
HeapFree(GetProcessHeap(), 0, pEntry->pszShortName);
|
||||
|
||||
if (pEntry->pszDllName)
|
||||
HeapFree(GetProcessHeap(), 0, pEntry->pszDllName);
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, pEntry);
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
DWORD
|
||||
LoadHelperDll(
|
||||
_In_ PWSTR pszDllName,
|
||||
_In_ BOOL bRegister)
|
||||
{
|
||||
PNS_DLL_INIT_FN pInitHelperDll;
|
||||
PDLL_LIST_ENTRY pEntry;
|
||||
PWSTR pszStart, pszEnd;
|
||||
BOOL bInserted = FALSE;
|
||||
DWORD dwError;
|
||||
|
||||
pEntry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DLL_LIST_ENTRY));
|
||||
if (pEntry == NULL)
|
||||
{
|
||||
return ERROR_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
pEntry->pszDllName = HeapAlloc(GetProcessHeap(),
|
||||
HEAP_ZERO_MEMORY,
|
||||
(wcslen(pszDllName) + 1) * sizeof(WCHAR));
|
||||
if (pEntry->pszDllName == NULL)
|
||||
{
|
||||
dwError = ERROR_OUTOFMEMORY;
|
||||
goto done;
|
||||
}
|
||||
|
||||
wcscpy(pEntry->pszDllName, pszDllName);
|
||||
|
||||
pszStart = wcsrchr(pszDllName, L'\\');
|
||||
if (pszStart == NULL)
|
||||
pszStart = pszDllName;
|
||||
|
||||
pEntry->pszShortName = HeapAlloc(GetProcessHeap(),
|
||||
HEAP_ZERO_MEMORY,
|
||||
(wcslen(pszStart) + 1) * sizeof(WCHAR));
|
||||
if (pEntry->pszShortName == NULL)
|
||||
{
|
||||
dwError = ERROR_OUTOFMEMORY;
|
||||
goto done;
|
||||
}
|
||||
|
||||
wcscpy(pEntry->pszShortName, pszStart);
|
||||
|
||||
pEntry->pszValueName = HeapAlloc(GetProcessHeap(),
|
||||
HEAP_ZERO_MEMORY,
|
||||
(wcslen(pEntry->pszShortName) + 1) * sizeof(WCHAR));
|
||||
if (pEntry->pszValueName == NULL)
|
||||
{
|
||||
dwError = ERROR_OUTOFMEMORY;
|
||||
goto done;
|
||||
}
|
||||
|
||||
wcscpy(pEntry->pszValueName, pEntry->pszShortName);
|
||||
|
||||
pszEnd = wcsrchr(pEntry->pszValueName, L'.');
|
||||
if (pszEnd != NULL)
|
||||
*pszEnd = UNICODE_NULL;
|
||||
|
||||
if (pDllListTail == NULL)
|
||||
{
|
||||
pEntry->pPrev = NULL;
|
||||
pEntry->pNext = NULL;
|
||||
pDllListHead = pEntry;
|
||||
pDllListTail = pEntry;
|
||||
}
|
||||
else
|
||||
{
|
||||
pEntry->pPrev = NULL;
|
||||
pEntry->pNext = pDllListHead;
|
||||
pDllListHead->pPrev = pEntry;
|
||||
pDllListHead = pEntry;
|
||||
}
|
||||
|
||||
bInserted = TRUE;
|
||||
|
||||
pEntry->hModule = LoadLibraryW(pEntry->pszDllName);
|
||||
if (pEntry->hModule == NULL)
|
||||
{
|
||||
dwError = GetLastError();
|
||||
DPRINT1("Could not load the helper dll %S (Error: %lu)\n", pEntry->pszDllName, dwError);
|
||||
goto done;
|
||||
}
|
||||
|
||||
pInitHelperDll = (PNS_DLL_INIT_FN)GetProcAddress(pEntry->hModule, "InitHelperDll");
|
||||
if (pInitHelperDll == NULL)
|
||||
{
|
||||
dwError = GetLastError();
|
||||
DPRINT1("Could not find 'InitHelperDll' (Error: %lu)\n", dwError);
|
||||
goto done;
|
||||
}
|
||||
|
||||
pCurrentDll = pEntry;
|
||||
dwError = pInitHelperDll(5, NULL);
|
||||
pCurrentDll = NULL;
|
||||
|
||||
DPRINT1("InitHelperDll returned %lu\n", dwError);
|
||||
if (dwError != ERROR_SUCCESS)
|
||||
{
|
||||
DPRINT1("Call to InitHelperDll failed (Error: %lu)\n", dwError);
|
||||
goto done;
|
||||
}
|
||||
|
||||
// if (pEntry->Attributes.pfnStart)
|
||||
// pEntry->Attributes.pfnStart(NULL, 0);
|
||||
|
||||
if (bRegister)
|
||||
RegisterHelperDll(pEntry);
|
||||
|
||||
done:
|
||||
if (dwError != ERROR_SUCCESS)
|
||||
{
|
||||
if (bInserted)
|
||||
{
|
||||
if (pEntry->pPrev != NULL)
|
||||
pEntry->pPrev->pNext = pEntry->pNext;
|
||||
if (pEntry->pNext != NULL)
|
||||
pEntry->pNext->pPrev = pEntry->pPrev;
|
||||
if (pDllListTail == pEntry)
|
||||
pDllListTail = pEntry->pPrev;
|
||||
if (pDllListHead == pEntry)
|
||||
pDllListHead = pEntry->pNext;
|
||||
pEntry->pPrev = NULL;
|
||||
pEntry->pNext = NULL;
|
||||
}
|
||||
|
||||
FreeHelperDll(pEntry);
|
||||
}
|
||||
|
||||
return dwError;
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
LoadHelpers(VOID)
|
||||
{
|
||||
PWSTR pszNameBuffer = NULL;
|
||||
PWSTR pszValueBuffer = NULL;
|
||||
HKEY hKey;
|
||||
DWORD dwValueCount, dwMaxNameLength, dwMaxValueLength;
|
||||
DWORD dwNameLength, dwValueLength, dwType;
|
||||
DWORD dwIndex, dwError;
|
||||
|
||||
DPRINT1("LoadHelpers()\n");
|
||||
|
||||
dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
|
||||
REG_NETSH_PATH,
|
||||
0,
|
||||
KEY_READ,
|
||||
&hKey);
|
||||
if (dwError != ERROR_SUCCESS)
|
||||
return;
|
||||
|
||||
dwError = RegQueryInfoKeyW(hKey,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&dwValueCount,
|
||||
&dwMaxNameLength,
|
||||
&dwMaxValueLength,
|
||||
NULL,
|
||||
NULL);
|
||||
if (dwError != ERROR_SUCCESS)
|
||||
goto done;
|
||||
|
||||
pszNameBuffer = HeapAlloc(GetProcessHeap(), 0,
|
||||
(dwMaxNameLength + 1) * sizeof(WCHAR));
|
||||
if (pszNameBuffer == NULL)
|
||||
goto done;
|
||||
|
||||
pszValueBuffer = HeapAlloc(GetProcessHeap(), 0,
|
||||
dwMaxValueLength + sizeof(WCHAR));
|
||||
if (pszValueBuffer == NULL)
|
||||
goto done;
|
||||
|
||||
for (dwIndex = 0; dwIndex < dwValueCount; dwIndex++)
|
||||
{
|
||||
dwNameLength = dwMaxNameLength + 1;
|
||||
dwValueLength = dwMaxValueLength + sizeof(WCHAR);
|
||||
dwError = RegEnumValueW(hKey,
|
||||
dwIndex,
|
||||
pszNameBuffer,
|
||||
&dwNameLength,
|
||||
NULL,
|
||||
&dwType,
|
||||
(PBYTE)pszValueBuffer,
|
||||
&dwValueLength);
|
||||
if (dwError != ERROR_SUCCESS)
|
||||
break;
|
||||
|
||||
DPRINT1("Dll: %S --> %S %lu\n", pszNameBuffer, pszValueBuffer, dwError);
|
||||
LoadHelperDll(pszValueBuffer, FALSE);
|
||||
}
|
||||
|
||||
done:
|
||||
if (pszValueBuffer)
|
||||
HeapFree(GetProcessHeap(), 0, pszValueBuffer);
|
||||
|
||||
if (pszNameBuffer)
|
||||
HeapFree(GetProcessHeap(), 0, pszNameBuffer);
|
||||
|
||||
RegCloseKey(hKey);
|
||||
|
||||
StartHelpers();
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
UnloadHelpers(VOID)
|
||||
{
|
||||
PDLL_LIST_ENTRY pEntry;
|
||||
|
||||
while (pDllListHead != NULL)
|
||||
{
|
||||
pEntry = pDllListHead;
|
||||
pDllListHead = pEntry->pNext;
|
||||
|
||||
// if (pEntry->Attributes.pfnStop)
|
||||
// pEntry->Attributes.pfnStop(0);
|
||||
|
||||
FreeHelperDll(pEntry);
|
||||
}
|
||||
|
||||
pDllListTail = NULL;
|
||||
}
|
||||
|
||||
|
||||
PHELPER_ENTRY
|
||||
FindHelper(
|
||||
_In_ const GUID *pguidHelper)
|
||||
{
|
||||
PHELPER_ENTRY pHelper;
|
||||
|
||||
pHelper = pHelperListHead;
|
||||
while (pHelper != NULL)
|
||||
{
|
||||
if (IsEqualGUID(pguidHelper, &pHelper->Attributes.guidHelper))
|
||||
return pHelper;
|
||||
|
||||
pHelper = pHelper->pNext;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
DWORD
|
||||
WINAPI
|
||||
RegisterHelper(
|
||||
_In_ const GUID *pguidParentHelper,
|
||||
_In_ const NS_HELPER_ATTRIBUTES *pHelperAttributes)
|
||||
{
|
||||
PHELPER_ENTRY pHelper = NULL, pParentHelper;
|
||||
DWORD dwError = ERROR_SUCCESS;
|
||||
|
||||
DPRINT("RegisterHelper(%p %p)\n", pguidParentHelper, pHelperAttributes);
|
||||
|
||||
if (FindHelper(&pHelperAttributes->guidHelper) != NULL)
|
||||
{
|
||||
DPRINT1("The Helper has already been registered!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
pHelper = (PHELPER_ENTRY)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(HELPER_ENTRY));
|
||||
if (pHelper == NULL)
|
||||
{
|
||||
dwError = ERROR_OUTOFMEMORY;
|
||||
goto done;
|
||||
}
|
||||
|
||||
CopyMemory(&pHelper->Attributes, pHelperAttributes, sizeof(NS_HELPER_ATTRIBUTES));
|
||||
pHelper->pDllEntry = pCurrentDll;
|
||||
DPRINT("pHelper->pDllEntry: %p\n", pHelper->pDllEntry);
|
||||
|
||||
if (pguidParentHelper == NULL)
|
||||
{
|
||||
if (pHelperListTail == NULL)
|
||||
{
|
||||
pHelperListHead = pHelper;
|
||||
pHelperListTail = pHelper;
|
||||
}
|
||||
else
|
||||
{
|
||||
pHelper->pNext = pHelperListHead;
|
||||
pHelperListHead->pPrev = pHelper;
|
||||
pHelperListHead = pHelper;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pParentHelper = FindHelper(&pHelperAttributes->guidHelper);
|
||||
if (pParentHelper == NULL)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
if (pParentHelper->pSubHelperHead == NULL && pParentHelper->pSubHelperTail == NULL)
|
||||
{
|
||||
pParentHelper->pSubHelperHead = pHelper;
|
||||
pParentHelper->pSubHelperTail = pHelper;
|
||||
}
|
||||
else
|
||||
{
|
||||
pHelper->pPrev = pParentHelper->pSubHelperTail;
|
||||
pParentHelper->pSubHelperTail->pNext = pHelper;
|
||||
pParentHelper->pSubHelperTail = pHelper;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
|
||||
return dwError;
|
||||
}
|
||||
|
||||
|
||||
DWORD
|
||||
WINAPI
|
||||
AddHelperCommand(
|
||||
LPCWSTR pwszMachine,
|
||||
LPWSTR *ppwcArguments,
|
||||
DWORD dwCurrentIndex,
|
||||
DWORD dwArgCount,
|
||||
DWORD dwFlags,
|
||||
LPCVOID pvData,
|
||||
BOOL *pbDone)
|
||||
{
|
||||
DWORD dwError = ERROR_SUCCESS;
|
||||
|
||||
DPRINT("AddHelperCommand()\n");
|
||||
|
||||
if (dwArgCount == 2)
|
||||
{
|
||||
// ConResPrintf(StdErr, IDS_INVALID_SYNTAX);
|
||||
// ConResPrintf(StdErr, IDS_HLP_ADD_HELPER_EX);
|
||||
return 1;
|
||||
}
|
||||
|
||||
dwError = LoadHelperDll(ppwcArguments[2], TRUE);
|
||||
if (dwError != ERROR_SUCCESS)
|
||||
return dwError;
|
||||
|
||||
StartHelpers();
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
DWORD
|
||||
WINAPI
|
||||
DeleteHelperCommand(
|
||||
LPCWSTR pwszMachine,
|
||||
LPWSTR *ppwcArguments,
|
||||
DWORD dwCurrentIndex,
|
||||
DWORD dwArgCount,
|
||||
DWORD dwFlags,
|
||||
LPCVOID pvData,
|
||||
BOOL *pbDone)
|
||||
{
|
||||
PDLL_LIST_ENTRY pEntry;
|
||||
HKEY hKey;
|
||||
DWORD dwError;
|
||||
|
||||
DPRINT("DeleteHelper()\n");
|
||||
|
||||
if (dwArgCount == 2)
|
||||
{
|
||||
// ConResPrintf(StdErr, IDS_INVALID_SYNTAX);
|
||||
// ConResPrintf(StdErr, IDS_HLP_DEL_HELPER_EX);
|
||||
return 1;
|
||||
}
|
||||
|
||||
pEntry = pDllListHead;
|
||||
while (pEntry != NULL)
|
||||
{
|
||||
if (wcscmp(pEntry->pszShortName, ppwcArguments[2]) == 0)
|
||||
{
|
||||
DPRINT1("remove %S\n", pEntry->pszShortName);
|
||||
|
||||
if (pEntry->pPrev != NULL)
|
||||
pEntry->pPrev->pNext = pEntry->pNext;
|
||||
if (pEntry->pNext != NULL)
|
||||
pEntry->pNext->pPrev = pEntry->pPrev;
|
||||
if (pDllListTail == pEntry)
|
||||
pDllListTail = pEntry->pPrev;
|
||||
if (pDllListHead == pEntry)
|
||||
pDllListHead = pEntry->pNext;
|
||||
pEntry->pPrev = NULL;
|
||||
pEntry->pNext = NULL;
|
||||
|
||||
dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
|
||||
REG_NETSH_PATH,
|
||||
0,
|
||||
KEY_WRITE,
|
||||
&hKey);
|
||||
if (dwError == ERROR_SUCCESS)
|
||||
{
|
||||
RegDeleteValue(hKey, pEntry->pszValueName);
|
||||
RegCloseKey(hKey);
|
||||
}
|
||||
|
||||
FreeHelperDll(pEntry);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
pEntry = pEntry->pNext;
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
VOID
|
||||
PrintSubContext(
|
||||
_In_ PCONTEXT_ENTRY pParentContext,
|
||||
_In_ DWORD dwLevel)
|
||||
{
|
||||
PCONTEXT_ENTRY pContext;
|
||||
PHELPER_ENTRY pHelper;
|
||||
WCHAR szPrefix[22];
|
||||
DWORD i;
|
||||
|
||||
if (pParentContext == NULL)
|
||||
return;
|
||||
|
||||
pContext = pParentContext->pSubContextHead;
|
||||
while (pContext != NULL)
|
||||
{
|
||||
pHelper = FindHelper(&pContext->Guid);
|
||||
if (pHelper != NULL)
|
||||
{
|
||||
if (dwLevel > 10)
|
||||
dwLevel = 10;
|
||||
|
||||
for (i = 0; i < dwLevel * 2; i++)
|
||||
szPrefix[i] = L' ';
|
||||
szPrefix[i] = UNICODE_NULL;
|
||||
|
||||
ConPrintf(StdOut, L"{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X} %-16s %s%s\n",
|
||||
pHelper->Attributes.guidHelper.Data1,
|
||||
pHelper->Attributes.guidHelper.Data2,
|
||||
pHelper->Attributes.guidHelper.Data3,
|
||||
pHelper->Attributes.guidHelper.Data4[0],
|
||||
pHelper->Attributes.guidHelper.Data4[1],
|
||||
pHelper->Attributes.guidHelper.Data4[2],
|
||||
pHelper->Attributes.guidHelper.Data4[3],
|
||||
pHelper->Attributes.guidHelper.Data4[4],
|
||||
pHelper->Attributes.guidHelper.Data4[5],
|
||||
pHelper->Attributes.guidHelper.Data4[6],
|
||||
pHelper->Attributes.guidHelper.Data4[7],
|
||||
pHelper->pDllEntry->pszShortName,
|
||||
szPrefix,
|
||||
pContext->pszContextName);
|
||||
}
|
||||
|
||||
PrintSubContext(pContext, dwLevel + 1);
|
||||
|
||||
pContext = pContext->pNext;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DWORD
|
||||
WINAPI
|
||||
ShowHelperCommand(
|
||||
LPCWSTR pwszMachine,
|
||||
LPWSTR *ppwcArguments,
|
||||
DWORD dwCurrentIndex,
|
||||
DWORD dwArgCount,
|
||||
DWORD dwFlags,
|
||||
LPCVOID pvData,
|
||||
BOOL *pbDone)
|
||||
{
|
||||
DPRINT("ShowHelperCommand()\n");
|
||||
|
||||
ConPrintf(StdOut, L"Helper GUID DLL Name Command\n");
|
||||
ConPrintf(StdOut, L"-------------------------------------- ---------------- --------\n");
|
||||
|
||||
if (pRootContext == NULL)
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
PrintSubContext(pRootContext, 0);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
238
base/applications/network/netsh/interpreter.c
Normal file
238
base/applications/network/netsh/interpreter.c
Normal file
@ -0,0 +1,238 @@
|
||||
/*
|
||||
* PROJECT: ReactOS NetSh
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: Network Shell command interpreter
|
||||
* COPYRIGHT: Copyright 2023 Eric Kohl <eric.kohl@reactos.org>
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include "precomp.h"
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
BOOL
|
||||
InterpretCommand(
|
||||
_In_ LPWSTR *argv,
|
||||
_In_ DWORD dwArgCount)
|
||||
{
|
||||
PCONTEXT_ENTRY pContext, pSubContext;
|
||||
PCOMMAND_ENTRY pCommand;
|
||||
PCOMMAND_GROUP pGroup;
|
||||
BOOL bDone = FALSE;
|
||||
DWORD dwHelpLevel = 0;
|
||||
DWORD dwError = ERROR_SUCCESS;
|
||||
|
||||
/* If no args provided */
|
||||
if (dwArgCount == 0)
|
||||
return TRUE;
|
||||
|
||||
if (pCurrentContext == NULL)
|
||||
{
|
||||
DPRINT1("InterpretCmd: invalid context %p\n", pCurrentContext);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((wcsicmp(argv[dwArgCount - 1], L"?") == 0) ||
|
||||
(wcsicmp(argv[dwArgCount - 1], L"help") == 0))
|
||||
{
|
||||
dwHelpLevel = dwArgCount - 1;
|
||||
}
|
||||
|
||||
pContext = pCurrentContext;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
pCommand = pContext->pCommandListHead;
|
||||
while (pCommand != NULL)
|
||||
{
|
||||
if (wcsicmp(argv[0], pCommand->pwszCmdToken) == 0)
|
||||
{
|
||||
if (dwHelpLevel == 1)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
pCommand = pCommand->pNext;
|
||||
}
|
||||
|
||||
pGroup = pContext->pGroupListHead;
|
||||
while (pGroup != NULL)
|
||||
{
|
||||
if (wcsicmp(argv[0], pGroup->pwszCmdGroupToken) == 0)
|
||||
{
|
||||
if (dwHelpLevel == 1)
|
||||
{
|
||||
HelpGroup(pGroup);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
pCommand = pGroup->pCommandListHead;
|
||||
while (pCommand != NULL)
|
||||
{
|
||||
if ((dwArgCount > 1) && (wcsicmp(argv[1], pCommand->pwszCmdToken) == 0))
|
||||
{
|
||||
if (dwHelpLevel == 2)
|
||||
{
|
||||
ConResPrintf(StdOut, pCommand->dwCmdHlpToken);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
dwError = pCommand->pfnCmdHandler(NULL, argv, 1, dwArgCount, 0, NULL, &bDone);
|
||||
if (dwError != ERROR_SUCCESS)
|
||||
{
|
||||
ConPrintf(StdOut, L"Error: %lu\n\n");
|
||||
ConResPrintf(StdOut, pCommand->dwCmdHlpToken);
|
||||
return TRUE;
|
||||
}
|
||||
return !bDone;
|
||||
}
|
||||
}
|
||||
|
||||
pCommand = pCommand->pNext;
|
||||
}
|
||||
|
||||
HelpGroup(pGroup);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
pGroup = pGroup->pNext;
|
||||
}
|
||||
|
||||
if (pContext == pCurrentContext)
|
||||
{
|
||||
pSubContext = pContext->pSubContextHead;
|
||||
while (pSubContext != NULL)
|
||||
{
|
||||
if (wcsicmp(argv[0], pSubContext->pszContextName) == 0)
|
||||
{
|
||||
pCurrentContext = pSubContext;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
pSubContext = pSubContext->pNext;
|
||||
}
|
||||
}
|
||||
|
||||
if (pContext == pRootContext)
|
||||
break;
|
||||
|
||||
pContext = pContext->pParentContext;
|
||||
}
|
||||
|
||||
ConResPrintf(StdErr, IDS_INVALID_COMMAND, argv[0]);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* InterpretScript(char *line):
|
||||
* The main function used for when reading commands from scripts.
|
||||
*/
|
||||
BOOL
|
||||
InterpretScript(
|
||||
_In_ LPWSTR pszInputLine)
|
||||
{
|
||||
LPWSTR args_vector[MAX_ARGS_COUNT];
|
||||
DWORD dwArgCount = 0;
|
||||
BOOL bWhiteSpace = TRUE;
|
||||
LPWSTR ptr;
|
||||
|
||||
memset(args_vector, 0, sizeof(args_vector));
|
||||
|
||||
ptr = pszInputLine;
|
||||
while (*ptr != 0)
|
||||
{
|
||||
if (iswspace(*ptr) || *ptr == L'\n')
|
||||
{
|
||||
*ptr = 0;
|
||||
bWhiteSpace = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((bWhiteSpace != FALSE) && (dwArgCount < MAX_ARGS_COUNT))
|
||||
{
|
||||
args_vector[dwArgCount] = ptr;
|
||||
dwArgCount++;
|
||||
}
|
||||
|
||||
bWhiteSpace = FALSE;
|
||||
}
|
||||
|
||||
ptr++;
|
||||
}
|
||||
|
||||
/* sends the string to find the command */
|
||||
return InterpretCommand(args_vector, dwArgCount);
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
InterpretInteractive(VOID)
|
||||
{
|
||||
WCHAR input_line[MAX_STRING_SIZE];
|
||||
LPWSTR args_vector[MAX_ARGS_COUNT];
|
||||
DWORD dwArgCount = 0;
|
||||
BOOL bWhiteSpace = TRUE;
|
||||
BOOL bRun = TRUE;
|
||||
LPWSTR ptr;
|
||||
|
||||
while (bRun != FALSE)
|
||||
{
|
||||
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)
|
||||
{
|
||||
ConPuts(StdOut, L" ");
|
||||
ConPuts(StdOut, pCurrentContext->pszContextName);
|
||||
}
|
||||
ConPuts(StdOut, L">");
|
||||
|
||||
/* Get input from the user. */
|
||||
fgetws(input_line, MAX_STRING_SIZE, stdin);
|
||||
|
||||
ptr = input_line;
|
||||
while (*ptr != 0)
|
||||
{
|
||||
if (iswspace(*ptr) || *ptr == L'\n')
|
||||
{
|
||||
*ptr = 0;
|
||||
bWhiteSpace = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((bWhiteSpace != FALSE) && (dwArgCount < MAX_ARGS_COUNT))
|
||||
{
|
||||
args_vector[dwArgCount] = ptr;
|
||||
dwArgCount++;
|
||||
}
|
||||
bWhiteSpace = FALSE;
|
||||
}
|
||||
ptr++;
|
||||
}
|
||||
|
||||
/* Send the string to find the command */
|
||||
bRun = InterpretCommand(args_vector, dwArgCount);
|
||||
}
|
||||
}
|
36
base/applications/network/netsh/lang/en-US.rc
Normal file
36
base/applications/network/netsh/lang/en-US.rc
Normal file
@ -0,0 +1,36 @@
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
|
||||
/* Basic application information */
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_APP_USAGE "\nUsage: netsh [-a AliasFile] [-c Context] [-r RemoteMachine] \
|
||||
\n [Command | -f ScriptFile]\n"
|
||||
IDS_INVALID_COMMAND "The following command was not found: %ls.\n"
|
||||
IDS_OPEN_FAILED "The file %ls could not be openend.\n"
|
||||
IDS_INVALID_SYNTAX "The syntax supplied for this command is not valid. Check help for the correct syntax.\n\n"
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_HELP_HEADER "\nThe following commands are available:\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_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"
|
||||
|
||||
IDS_HLP_DEL_HELPER "Removes a helper DLL."
|
||||
IDS_HLP_DEL_HELPER_EX "Syntax: delete helper <dll file name>\n\n Removes the specified helper DLL from netsh.\n\n"
|
||||
|
||||
IDS_HLP_SHOW_HELPER "Lists all the top-level helpers."
|
||||
IDS_HLP_SHOW_HELPER_EX "Syntax: show helper\n\n Lists all the top-level helpers.\n\n"
|
||||
|
||||
IDS_HLP_GROUP_ADD "Adds a configuration entry to a list of entries."
|
||||
IDS_HLP_GROUP_DELETE "Deletes a configuration entry from a list of entries."
|
||||
IDS_HLP_GROUP_SHOW "Displays information."
|
||||
END
|
@ -1,33 +1,254 @@
|
||||
/*
|
||||
* Copyright 2010 Hans Leidekker for CodeWeavers
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
* PROJECT: ReactOS NetSh
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: Network Shell main file
|
||||
* COPYRIGHT: Copyright 2023 Eric Kohl <eric.kohl@reactos.org>
|
||||
*/
|
||||
|
||||
#include <wine/debug.h>
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(netsh);
|
||||
#include "precomp.h"
|
||||
|
||||
int wmain(int argc, WCHAR *argv[])
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
BOOL
|
||||
RunScript(
|
||||
_In_ LPCWSTR filename)
|
||||
{
|
||||
int i;
|
||||
FILE *script;
|
||||
WCHAR tmp_string[MAX_STRING_SIZE];
|
||||
|
||||
WINE_FIXME("stub:");
|
||||
for (i = 0; i < argc; i++)
|
||||
WINE_FIXME(" %s", wine_dbgstr_w(argv[i]));
|
||||
WINE_FIXME("\n");
|
||||
/* Open the file for processing */
|
||||
script = _wfopen(filename, L"r");
|
||||
if (script == NULL)
|
||||
{
|
||||
ConResPrintf(StdErr, IDS_OPEN_FAILED, filename);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Read and process the script */
|
||||
while (fgetws(tmp_string, MAX_STRING_SIZE, script) != NULL)
|
||||
{
|
||||
if (InterpretScript(tmp_string) == FALSE)
|
||||
{
|
||||
fclose(script);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Close the file */
|
||||
fclose(script);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* wmain():
|
||||
* Main entry point of the application.
|
||||
*/
|
||||
int
|
||||
wmain(
|
||||
_In_ int argc,
|
||||
_In_ const LPWSTR argv[])
|
||||
{
|
||||
LPCWSTR tmpBuffer = NULL;
|
||||
LPCWSTR pszFileName = NULL;
|
||||
int index;
|
||||
int result = EXIT_SUCCESS;
|
||||
|
||||
DPRINT("main()\n");
|
||||
|
||||
/* Initialize the Console Standard Streams */
|
||||
ConInitStdStreams();
|
||||
|
||||
/* FIXME: Init code goes here */
|
||||
CreateRootContext();
|
||||
LoadHelpers();
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
/* If there are no command arguments, then go straight to the interpreter */
|
||||
InterpretInteractive();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If there are command arguments, then process them */
|
||||
for (index = 1; index < argc; index++)
|
||||
{
|
||||
if ((argv[index][0] == '/')||
|
||||
(argv[index][0] == '-'))
|
||||
{
|
||||
tmpBuffer = argv[index] + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pszFileName != NULL)
|
||||
{
|
||||
ConResPuts(StdOut, IDS_APP_USAGE);
|
||||
result = EXIT_FAILURE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Run a command from the command line */
|
||||
if (InterpretCommand((LPWSTR*)&argv[index], argc - index) == FALSE)
|
||||
result = EXIT_FAILURE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (_wcsicmp(tmpBuffer, L"?") == 0)
|
||||
{
|
||||
/* Help option */
|
||||
ConResPuts(StdOut, IDS_APP_USAGE);
|
||||
result = EXIT_SUCCESS;
|
||||
goto done;
|
||||
}
|
||||
else if (_wcsicmp(tmpBuffer, L"a") == 0)
|
||||
{
|
||||
/* Aliasfile option */
|
||||
if ((index + 1) < argc)
|
||||
{
|
||||
index++;
|
||||
ConPuts(StdOut, L"\nThe -a option is not implemented yet\n");
|
||||
// aliasfile = argv[index];
|
||||
}
|
||||
else
|
||||
{
|
||||
ConResPuts(StdOut, IDS_APP_USAGE);
|
||||
result = EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
else if (_wcsicmp(tmpBuffer, L"c") == 0)
|
||||
{
|
||||
/* Context option */
|
||||
if ((index + 1) < argc)
|
||||
{
|
||||
index++;
|
||||
ConPuts(StdOut, L"\nThe -c option is not implemented yet\n");
|
||||
// context = argv[index];
|
||||
}
|
||||
else
|
||||
{
|
||||
ConResPuts(StdOut, IDS_APP_USAGE);
|
||||
result = EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
else if (_wcsicmp(tmpBuffer, L"f") == 0)
|
||||
{
|
||||
/* File option */
|
||||
if ((index + 1) < argc)
|
||||
{
|
||||
index++;
|
||||
pszFileName = argv[index];
|
||||
}
|
||||
else
|
||||
{
|
||||
ConResPuts(StdOut, IDS_APP_USAGE);
|
||||
result = EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
else if (_wcsicmp(tmpBuffer, L"r") == 0)
|
||||
{
|
||||
/* Remote option */
|
||||
if ((index + 1) < argc)
|
||||
{
|
||||
index++;
|
||||
ConPuts(StdOut, L"\nThe -r option is not implemented yet\n");
|
||||
// remote = argv[index];
|
||||
}
|
||||
else
|
||||
{
|
||||
ConResPuts(StdOut, IDS_APP_USAGE);
|
||||
result = EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Invalid command */
|
||||
ConResPrintf(StdOut, IDS_INVALID_COMMAND, argv[index]);
|
||||
result = EXIT_FAILURE;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now we process the filename if it exists */
|
||||
if (pszFileName != NULL)
|
||||
{
|
||||
if (RunScript(pszFileName) == FALSE)
|
||||
{
|
||||
result = EXIT_FAILURE;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
/* FIXME: Cleanup code goes here */
|
||||
UnloadHelpers();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
DWORD
|
||||
WINAPI
|
||||
MatchEnumTag(
|
||||
_In_ HANDLE hModule,
|
||||
_In_ LPCWSTR pwcArg,
|
||||
_In_ DWORD dwNumArg,
|
||||
_In_ const TOKEN_VALUE *pEnumTable,
|
||||
_Out_ PDWORD pdwValue)
|
||||
{
|
||||
DPRINT1("MatchEnumTag()\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL
|
||||
WINAPI
|
||||
MatchToken(
|
||||
_In_ LPCWSTR pwszUserToken,
|
||||
_In_ LPCWSTR pwszCmdToken)
|
||||
{
|
||||
DPRINT1("MatchToken %S %S\n", pwszUserToken, pwszCmdToken);
|
||||
return (wcsicmp(pwszUserToken, pwszCmdToken) == 0) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
DWORD
|
||||
CDECL
|
||||
PrintError(
|
||||
_In_opt_ HANDLE hModule,
|
||||
_In_ DWORD dwErrId,
|
||||
...)
|
||||
{
|
||||
DPRINT1("PrintError()\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
DWORD
|
||||
CDECL
|
||||
PrintMessageFromModule(
|
||||
_In_ HANDLE hModule,
|
||||
_In_ DWORD dwMsgId,
|
||||
...)
|
||||
{
|
||||
DPRINT1("PrintMessageFromModule()\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
DWORD
|
||||
CDECL
|
||||
PrintMessage(
|
||||
_In_ LPCWSTR pwszFormat,
|
||||
...)
|
||||
{
|
||||
INT Length;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, pwszFormat);
|
||||
Length = ConPrintf(StdOut, pwszFormat);
|
||||
va_end(ap);
|
||||
|
||||
return Length;
|
||||
}
|
||||
|
15
base/applications/network/netsh/netsh.rc
Normal file
15
base/applications/network/netsh/netsh.rc
Normal file
@ -0,0 +1,15 @@
|
||||
#include <windef.h>
|
||||
|
||||
#include "resource.h"
|
||||
|
||||
#define REACTOS_STR_FILE_DESCRIPTION "Net Shell"
|
||||
#define REACTOS_STR_INTERNAL_NAME "netsh"
|
||||
#define REACTOS_STR_ORIGINAL_FILENAME "netsh.exe"
|
||||
#include <reactos/version.rc>
|
||||
|
||||
/* UTF-8 */
|
||||
#pragma code_page(65001)
|
||||
|
||||
#ifdef LANGUAGE_EN_US
|
||||
#include "lang/en-US.rc"
|
||||
#endif
|
7
base/applications/network/netsh/netsh.spec
Normal file
7
base/applications/network/netsh/netsh.spec
Normal file
@ -0,0 +1,7 @@
|
||||
@ stdcall MatchEnumTag(ptr wstr long ptr ptr)
|
||||
@ stdcall MatchToken(wstr wstr)
|
||||
@ varargs PrintError(ptr long)
|
||||
@ varargs PrintMessage(wstr)
|
||||
@ varargs PrintMessageFromModule(ptr long)
|
||||
@ stdcall RegisterContext(ptr)
|
||||
@ stdcall RegisterHelper(ptr ptr)
|
205
base/applications/network/netsh/precomp.h
Normal file
205
base/applications/network/netsh/precomp.h
Normal file
@ -0,0 +1,205 @@
|
||||
/*
|
||||
* PROJECT: ReactOS NetSh
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: Network Shell main header file
|
||||
* COPYRIGHT: Copyright 2023 Eric Kohl <eric.kohl@reactos.org>
|
||||
*/
|
||||
|
||||
#ifndef PRECOMP_H
|
||||
#define PRECOMP_H
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#define WIN32_NO_STATUS
|
||||
#include <windef.h>
|
||||
#include <winbase.h>
|
||||
#include <winreg.h>
|
||||
#include <wincon.h>
|
||||
#include <winuser.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <conutils.h>
|
||||
#include <netsh.h>
|
||||
|
||||
#include "resource.h"
|
||||
|
||||
|
||||
/* DEFINES *******************************************************************/
|
||||
|
||||
#define MAX_STRING_SIZE 1024
|
||||
#define MAX_ARGS_COUNT 256
|
||||
|
||||
#define REG_NETSH_PATH L"Software\\Microsoft\\NetSh"
|
||||
|
||||
|
||||
/* TYPEDEFS ******************************************************************/
|
||||
|
||||
typedef struct _DLL_LIST_ENTRY
|
||||
{
|
||||
struct _DLL_LIST_ENTRY *pPrev;
|
||||
struct _DLL_LIST_ENTRY *pNext;
|
||||
|
||||
PWSTR pszDllName;
|
||||
PWSTR pszShortName;
|
||||
PWSTR pszValueName;
|
||||
|
||||
HMODULE hModule;
|
||||
|
||||
} DLL_LIST_ENTRY, *PDLL_LIST_ENTRY;
|
||||
|
||||
typedef struct _HELPER_ENTRY
|
||||
{
|
||||
struct _HELPER_ENTRY *pPrev;
|
||||
struct _HELPER_ENTRY *pNext;
|
||||
|
||||
NS_HELPER_ATTRIBUTES Attributes;
|
||||
|
||||
PDLL_LIST_ENTRY pDllEntry;
|
||||
BOOL bStarted;
|
||||
|
||||
struct _HELPER_ENTRY *pSubHelperHead;
|
||||
struct _HELPER_ENTRY *pSubHelperTail;
|
||||
|
||||
} HELPER_ENTRY, *PHELPER_ENTRY;
|
||||
|
||||
|
||||
|
||||
typedef struct _COMMAND_ENTRY
|
||||
{
|
||||
struct _COMMAND_ENTRY *pPrev;
|
||||
struct _COMMAND_ENTRY *pNext;
|
||||
|
||||
LPCWSTR pwszCmdToken;
|
||||
PFN_HANDLE_CMD pfnCmdHandler;
|
||||
DWORD dwShortCmdHelpToken;
|
||||
DWORD dwCmdHlpToken;
|
||||
DWORD dwFlags;
|
||||
} COMMAND_ENTRY, *PCOMMAND_ENTRY;
|
||||
|
||||
typedef struct _COMMAND_GROUP
|
||||
{
|
||||
struct _COMMAND_GROUP *pPrev;
|
||||
struct _COMMAND_GROUP *pNext;
|
||||
|
||||
LPCWSTR pwszCmdGroupToken;
|
||||
DWORD dwShortCmdHelpToken;
|
||||
DWORD dwFlags;
|
||||
|
||||
PCOMMAND_ENTRY pCommandListHead;
|
||||
PCOMMAND_ENTRY pCommandListTail;
|
||||
} COMMAND_GROUP, *PCOMMAND_GROUP;
|
||||
|
||||
typedef struct _CONTEXT_ENTRY
|
||||
{
|
||||
struct _CONTEXT_ENTRY *pPrev;
|
||||
struct _CONTEXT_ENTRY *pNext;
|
||||
|
||||
struct _CONTEXT_ENTRY *pParentContext;
|
||||
|
||||
PWSTR pszContextName;
|
||||
GUID Guid;
|
||||
HMODULE hModule;
|
||||
|
||||
PCOMMAND_ENTRY pCommandListHead;
|
||||
PCOMMAND_ENTRY pCommandListTail;
|
||||
|
||||
PCOMMAND_GROUP pGroupListHead;
|
||||
PCOMMAND_GROUP pGroupListTail;
|
||||
|
||||
struct _CONTEXT_ENTRY *pSubContextHead;
|
||||
struct _CONTEXT_ENTRY *pSubContextTail;
|
||||
} CONTEXT_ENTRY, *PCONTEXT_ENTRY;
|
||||
|
||||
|
||||
/* GLOBAL VARIABLES ***********************************************************/
|
||||
|
||||
extern PCONTEXT_ENTRY pRootContext;
|
||||
extern PCONTEXT_ENTRY pCurrentContext;
|
||||
|
||||
|
||||
/* PROTOTYPES *****************************************************************/
|
||||
|
||||
/* context.c */
|
||||
|
||||
BOOL
|
||||
CreateRootContext(VOID);
|
||||
|
||||
|
||||
/* help.c */
|
||||
DWORD
|
||||
WINAPI
|
||||
HelpCommand(
|
||||
LPCWSTR pwszMachine,
|
||||
LPWSTR *ppwcArguments,
|
||||
DWORD dwCurrentIndex,
|
||||
DWORD dwArgCount,
|
||||
DWORD dwFlags,
|
||||
LPCVOID pvData,
|
||||
BOOL *pbDone);
|
||||
|
||||
VOID
|
||||
HelpGroup(
|
||||
PCOMMAND_GROUP pGroup);
|
||||
|
||||
|
||||
/* helper.c */
|
||||
VOID
|
||||
LoadHelpers(VOID);
|
||||
|
||||
VOID
|
||||
UnloadHelpers(VOID);
|
||||
|
||||
|
||||
DWORD
|
||||
WINAPI
|
||||
AddHelperCommand(
|
||||
LPCWSTR pwszMachine,
|
||||
LPWSTR *ppwcArguments,
|
||||
DWORD dwCurrentIndex,
|
||||
DWORD dwArgCount,
|
||||
DWORD dwFlags,
|
||||
LPCVOID pvData,
|
||||
BOOL *pbDone);
|
||||
|
||||
DWORD
|
||||
WINAPI
|
||||
DeleteHelperCommand(
|
||||
LPCWSTR pwszMachine,
|
||||
LPWSTR *ppwcArguments,
|
||||
DWORD dwCurrentIndex,
|
||||
DWORD dwArgCount,
|
||||
DWORD dwFlags,
|
||||
LPCVOID pvData,
|
||||
BOOL *pbDone);
|
||||
|
||||
DWORD
|
||||
WINAPI
|
||||
ShowHelperCommand(
|
||||
LPCWSTR pwszMachine,
|
||||
PWSTR *ppwcArguments,
|
||||
DWORD dwCurrentIndex,
|
||||
DWORD dwArgCount,
|
||||
DWORD dwFlags,
|
||||
LPCVOID pvData,
|
||||
BOOL *pbDone);
|
||||
|
||||
|
||||
/* interpreter.c */
|
||||
BOOL
|
||||
InterpretScript(
|
||||
LPWSTR pszFileName);
|
||||
|
||||
BOOL
|
||||
InterpretCommand(
|
||||
LPWSTR *argv,
|
||||
DWORD dwArgCount);
|
||||
|
||||
VOID
|
||||
InterpretInteractive(VOID);
|
||||
|
||||
#endif /* PRECOMP_H */
|
37
base/applications/network/netsh/resource.h
Normal file
37
base/applications/network/netsh/resource.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* PROJECT: ReactOS NetSh
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: Network Shell resource id header file
|
||||
* COPYRIGHT: Copyright 2023 Eric Kohl <eric.kohl@reactos.org>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define IDS_NONE -1
|
||||
|
||||
#define IDS_APP_USAGE 100
|
||||
#define IDS_APP_PROMPT 101
|
||||
#define IDS_INVALID_COMMAND 102
|
||||
#define IDS_OPEN_FAILED 103
|
||||
#define IDS_INVALID_SYNTAX 104
|
||||
|
||||
#define IDS_HELP_HEADER 200
|
||||
#define IDS_SUBCONTEXT_HEADER 201
|
||||
|
||||
#define IDS_HLP_EXIT 300
|
||||
#define IDS_HLP_EXIT_EX 301
|
||||
#define IDS_HLP_HELP 302
|
||||
#define IDS_HLP_HELP_EX 303
|
||||
#define IDS_HLP_UP 304
|
||||
#define IDS_HLP_UP_EX 305
|
||||
|
||||
#define IDS_HLP_ADD_HELPER 310
|
||||
#define IDS_HLP_ADD_HELPER_EX 311
|
||||
#define IDS_HLP_DEL_HELPER 312
|
||||
#define IDS_HLP_DEL_HELPER_EX 313
|
||||
#define IDS_HLP_SHOW_HELPER 314
|
||||
#define IDS_HLP_SHOW_HELPER_EX 315
|
||||
|
||||
#define IDS_HLP_GROUP_ADD 320
|
||||
#define IDS_HLP_GROUP_DELETE 321
|
||||
#define IDS_HLP_GROUP_SHOW 322
|
Loading…
Reference in New Issue
Block a user