1014 lines
22 KiB
C
1014 lines
22 KiB
C
/*++
|
|
|
|
Copyright (c) 1998 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
routing\netsh\ipx\ipxmon\ipxmon.c
|
|
|
|
Abstract:
|
|
|
|
IPX Command dispatcher.
|
|
|
|
Revision History:
|
|
|
|
V Raman 11/25/98 Created
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
//
|
|
// Guid for IPMON.DLL
|
|
//
|
|
// {b1641451-84b8-11d2-b940-3078302c2030}
|
|
//
|
|
|
|
static const GUID g_MyGuid = IPXMONTR_GUID;
|
|
|
|
|
|
//
|
|
// Well known ROUTING guid
|
|
//
|
|
|
|
static const GUID g_RoutingGuid = ROUTING_GUID;
|
|
|
|
//
|
|
// IPX monitor version
|
|
//
|
|
|
|
#define IPX_HELPER_VERSION 1
|
|
|
|
//
|
|
// random wrapper macros
|
|
//
|
|
|
|
#define MALLOC(x) HeapAlloc( GetProcessHeap(), 0, x )
|
|
#define REALLOC(x,y) HeapReAlloc( GetProcessHeap(), 0, x, y )
|
|
#define FREE(x) HeapFree( GetProcessHeap(), 0, x )
|
|
|
|
//
|
|
// The table of Add, Delete, Set and Show Commands for IPX RTR MGR
|
|
// To add a command to one of the command groups, just add the
|
|
// CMD_ENTRY to the correct table. To add a new cmd group, create its
|
|
// cmd table and then add the group entry to group table
|
|
//
|
|
|
|
//
|
|
// The commands are prefix-matched with the command-line, in sequential
|
|
// order. So a command like 'ADD INTERFACE FILTER' must come before
|
|
// the command 'ADD INTERFACE' in the table. Likewise,
|
|
// a command like 'ADD ROUTE' must come before the command
|
|
// 'ADD ROUTEPREF' in the table.
|
|
//
|
|
|
|
CMD_ENTRY g_IpxAddCmdTable[] =
|
|
{
|
|
CREATE_CMD_ENTRY( IPX_ADD_ROUTE, HandleIpxAddRoute),
|
|
CREATE_CMD_ENTRY( IPX_ADD_SERVICE, HandleIpxAddService ),
|
|
CREATE_CMD_ENTRY( IPX_ADD_FILTER, HandleIpxAddFilter ),
|
|
CREATE_CMD_ENTRY( IPX_ADD_INTERFACE, HandleIpxAddInterface )
|
|
};
|
|
|
|
|
|
CMD_ENTRY g_IpxDelCmdTable[] =
|
|
{
|
|
CREATE_CMD_ENTRY( IPX_DELETE_ROUTE, HandleIpxDelRoute ),
|
|
CREATE_CMD_ENTRY( IPX_DELETE_SERVICE, HandleIpxDelService ),
|
|
CREATE_CMD_ENTRY( IPX_DELETE_FILTER, HandleIpxDelFilter ),
|
|
CREATE_CMD_ENTRY( IPX_DELETE_INTERFACE, HandleIpxDelInterface )
|
|
};
|
|
|
|
|
|
CMD_ENTRY g_IpxSetCmdTable[] =
|
|
{
|
|
CREATE_CMD_ENTRY( IPX_SET_ROUTE, HandleIpxSetRoute ),
|
|
CREATE_CMD_ENTRY( IPX_SET_SERVICE, HandleIpxSetService ),
|
|
CREATE_CMD_ENTRY( IPX_SET_FILTER, HandleIpxSetFilter ),
|
|
CREATE_CMD_ENTRY( IPX_SET_INTERFACE, HandleIpxSetInterface ),
|
|
CREATE_CMD_ENTRY( IPX_SET_GLOBAL, HandleIpxSetLoglevel )
|
|
};
|
|
|
|
|
|
CMD_ENTRY g_IpxShowCmdTable[] =
|
|
{
|
|
CREATE_CMD_ENTRY( IPX_SHOW_ROUTE, HandleIpxShowRoute ),
|
|
CREATE_CMD_ENTRY( IPX_SHOW_SERVICE, HandleIpxShowService),
|
|
CREATE_CMD_ENTRY( IPX_SHOW_FILTER, HandleIpxShowFilter ),
|
|
CREATE_CMD_ENTRY( IPX_SHOW_INTERFACE, HandleIpxShowInterface ),
|
|
CREATE_CMD_ENTRY( IPX_SHOW_GLOBAL, HandleIpxShowLoglevel ),
|
|
CREATE_CMD_ENTRY( IPX_SHOW_ROUTETABLE, HandleIpxShowRouteTable ),
|
|
CREATE_CMD_ENTRY( IPX_SHOW_SERVICETABLE,HandleIpxShowServiceTable ),
|
|
};
|
|
|
|
|
|
CMD_GROUP_ENTRY g_IpxCmdGroups[] =
|
|
{
|
|
CREATE_CMD_GROUP_ENTRY( GROUP_ADD, g_IpxAddCmdTable ),
|
|
CREATE_CMD_GROUP_ENTRY( GROUP_DELETE, g_IpxDelCmdTable ),
|
|
CREATE_CMD_GROUP_ENTRY( GROUP_SET, g_IpxSetCmdTable ),
|
|
CREATE_CMD_GROUP_ENTRY( GROUP_SHOW, g_IpxShowCmdTable )
|
|
};
|
|
|
|
ULONG g_ulNumGroups = sizeof(g_IpxCmdGroups)/sizeof(CMD_GROUP_ENTRY);
|
|
|
|
|
|
|
|
//
|
|
// Top level commands
|
|
//
|
|
|
|
CMD_ENTRY g_IpxCmds[] =
|
|
{
|
|
CREATE_CMD_ENTRY( IPX_UPDATE, HandleIpxUpdate )
|
|
};
|
|
|
|
ULONG g_ulNumTopCmds = sizeof(g_IpxCmds)/sizeof(CMD_ENTRY);
|
|
|
|
//
|
|
// Handle to this DLL
|
|
//
|
|
|
|
HANDLE g_hModule;
|
|
|
|
|
|
//
|
|
// Handle to router being administered
|
|
//
|
|
|
|
HANDLE g_hMprConfig;
|
|
HANDLE g_hMprAdmin;
|
|
HANDLE g_hMIBServer;
|
|
|
|
|
|
//
|
|
// Commit mode
|
|
//
|
|
|
|
BOOL g_bCommit;
|
|
|
|
DWORD ParentVersion;
|
|
BOOL g_bIpxDirty = FALSE;
|
|
NS_CONTEXT_CONNECT_FN IpxConnect;
|
|
NS_CONTEXT_SUBENTRY_FN IpxSubEntry;
|
|
|
|
//
|
|
// Variable that stores whether or not the helper has been
|
|
// initialized
|
|
//
|
|
|
|
ULONG g_ulInitCount;
|
|
|
|
|
|
//
|
|
// Router name
|
|
//
|
|
|
|
PWCHAR g_pwszRouter = NULL;
|
|
|
|
|
|
//
|
|
// Prototype declarations for functions in this file
|
|
//
|
|
|
|
DWORD
|
|
WINAPI
|
|
IpxUnInit(
|
|
IN DWORD dwReserved
|
|
);
|
|
|
|
BOOL
|
|
IsHelpToken(
|
|
PWCHAR pwszToken
|
|
);
|
|
|
|
|
|
BOOL
|
|
IA64VersionCheck
|
|
(
|
|
IN UINT CIMOSType, // WMI: Win32_OperatingSystem OSType
|
|
IN UINT CIMOSProductSuite, // WMI: Win32_OperatingSystem OSProductSuite
|
|
IN LPCWSTR CIMOSVersion, // WMI: Win32_OperatingSystem Version
|
|
IN LPCWSTR CIMOSBuildNumber, // WMI: Win32_OperatingSystem BuildNumber
|
|
IN LPCWSTR CIMServicePackMajorVersion, // WMI: Win32_OperatingSystem ServicePackMajorVersion
|
|
IN LPCWSTR CIMServicePackMinorVersion, // WMI: Win32_OperatingSystem ServicePackMinorVersion
|
|
IN UINT CIMProcessorArchitecture, // WMI: Win32_Processor Architecture
|
|
IN DWORD dwReserved
|
|
)
|
|
{
|
|
if (CIMProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) // IA64=6 (x86 == 0)
|
|
return TRUE;
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
WINAPI
|
|
IpxStartHelper(
|
|
IN CONST GUID *pguidParent,
|
|
IN DWORD dwVersion
|
|
)
|
|
/*++
|
|
|
|
Routine Description :
|
|
|
|
Registers the contexts supported by this helper
|
|
|
|
Arguements :
|
|
|
|
pguidParent - NETSH guid
|
|
|
|
Return value :
|
|
|
|
Don't know
|
|
|
|
--*/
|
|
{
|
|
DWORD dwErr;
|
|
NS_CONTEXT_ATTRIBUTES attMyAttributes;
|
|
PNS_PRIV_CONTEXT_ATTRIBUTES pNsPrivContextAttributes;
|
|
|
|
pNsPrivContextAttributes = MALLOC(sizeof(NS_PRIV_CONTEXT_ATTRIBUTES));
|
|
if (!pNsPrivContextAttributes)
|
|
{
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
ParentVersion = dwVersion;
|
|
|
|
ZeroMemory( &attMyAttributes, sizeof(NS_CONTEXT_ATTRIBUTES));
|
|
ZeroMemory(pNsPrivContextAttributes, sizeof(NS_PRIV_CONTEXT_ATTRIBUTES));
|
|
|
|
attMyAttributes.pwszContext = L"ipx";
|
|
attMyAttributes.guidHelper = g_MyGuid;
|
|
attMyAttributes.dwVersion = 1;
|
|
attMyAttributes.dwFlags = 0;
|
|
attMyAttributes.ulNumTopCmds = g_ulNumTopCmds;
|
|
attMyAttributes.pTopCmds = (CMD_ENTRY (*)[])&g_IpxCmds;
|
|
attMyAttributes.ulNumGroups = g_ulNumGroups;
|
|
attMyAttributes.pCmdGroups = (CMD_GROUP_ENTRY (*)[])&g_IpxCmdGroups;
|
|
attMyAttributes.pfnCommitFn = NULL;
|
|
attMyAttributes.pfnDumpFn = IpxDump;
|
|
attMyAttributes.pfnConnectFn= IpxConnect;
|
|
attMyAttributes.pfnOsVersionCheck = IA64VersionCheck;
|
|
|
|
pNsPrivContextAttributes->pfnEntryFn = NULL;
|
|
pNsPrivContextAttributes->pfnSubEntryFn = IpxSubEntry;
|
|
attMyAttributes.pReserved = pNsPrivContextAttributes;
|
|
|
|
dwErr = RegisterContext( &attMyAttributes );
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
|
|
DWORD
|
|
WINAPI
|
|
InitHelperDll(
|
|
IN DWORD dwNetshVersion,
|
|
OUT PNS_DLL_ATTRIBUTES pDllTable
|
|
)
|
|
/*++
|
|
|
|
Routine Description :
|
|
|
|
initialize this helper DLL
|
|
|
|
|
|
Arguements :
|
|
|
|
pUtilityTable - List of helper functions from the SHELL
|
|
|
|
pDllTable - Callbacks into this helper DLL passed back to the shell
|
|
|
|
|
|
Return value :
|
|
|
|
NO_ERROR - Success
|
|
|
|
--*/
|
|
{
|
|
DWORD dwErr;
|
|
NS_HELPER_ATTRIBUTES attMyAttributes;
|
|
|
|
|
|
//
|
|
// See if this is the first time we are being called
|
|
//
|
|
|
|
if ( InterlockedIncrement( &g_ulInitCount ) isnot 1 )
|
|
{
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
//
|
|
// Connect to router config. Also serves as a check to
|
|
// see if the router is configured on the machine
|
|
//
|
|
|
|
dwErr = MprConfigServerConnect( NULL, &g_hMprConfig );
|
|
|
|
if( dwErr isnot NO_ERROR )
|
|
{
|
|
DisplayError( NULL, dwErr );
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
pDllTable->dwVersion = NETSH_VERSION_50;
|
|
pDllTable->pfnStopFn = StopHelperDll;
|
|
|
|
|
|
//
|
|
// Register helpers
|
|
//
|
|
|
|
ZeroMemory( &attMyAttributes, sizeof(attMyAttributes) );
|
|
attMyAttributes.guidHelper = g_MyGuid;
|
|
attMyAttributes.dwVersion = IPX_HELPER_VERSION;
|
|
attMyAttributes.pfnStart = IpxStartHelper;
|
|
attMyAttributes.pfnStop = NULL;
|
|
|
|
RegisterHelper( &g_RoutingGuid, &attMyAttributes );
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
DWORD
|
|
WINAPI
|
|
StopHelperDll(
|
|
IN DWORD dwReserved
|
|
)
|
|
/*++
|
|
|
|
Routine Description :
|
|
|
|
Arguements :
|
|
|
|
Return value :
|
|
|
|
--*/
|
|
{
|
|
if ( InterlockedDecrement( &g_ulInitCount ) isnot 0 )
|
|
{
|
|
return NO_ERROR;
|
|
}
|
|
|
|
#if 0
|
|
IpxCommit(NETSH_FLUSH);
|
|
#endif
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
IpxDllEntry(
|
|
HINSTANCE hInstDll,
|
|
DWORD fdwReason,
|
|
LPVOID pReserved
|
|
)
|
|
/*++
|
|
|
|
Routine Description :
|
|
|
|
Arguements :
|
|
|
|
Return value :
|
|
|
|
--*/
|
|
{
|
|
|
|
switch (fdwReason)
|
|
{
|
|
case DLL_PROCESS_ATTACH:
|
|
{
|
|
g_hModule = hInstDll;
|
|
|
|
DisableThreadLibraryCalls(hInstDll);
|
|
|
|
break;
|
|
}
|
|
case DLL_PROCESS_DETACH:
|
|
{
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
DWORD
|
|
ConnectToRouter(
|
|
IN LPCWSTR pwszRouter
|
|
)
|
|
{
|
|
DWORD rc, dwErr;
|
|
|
|
if (g_pwszRouter != pwszRouter)
|
|
{
|
|
if (g_hMprConfig)
|
|
{
|
|
MprConfigServerDisconnect(g_hMprConfig);
|
|
g_hMprConfig = NULL;
|
|
}
|
|
|
|
if (g_hMprAdmin)
|
|
{
|
|
MprAdminServerDisconnect(g_hMprAdmin);
|
|
g_hMprAdmin = NULL;
|
|
}
|
|
|
|
if (g_hMIBServer)
|
|
{
|
|
MprAdminMIBServerDisconnect(g_hMIBServer);
|
|
g_hMIBServer = NULL;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Connect to router config if required
|
|
// (when is this ever required)
|
|
//
|
|
|
|
if ( !g_hMprConfig )
|
|
{
|
|
dwErr = MprConfigServerConnect( (LPWSTR)pwszRouter, &g_hMprConfig );
|
|
|
|
if ( dwErr isnot NO_ERROR )
|
|
{
|
|
return ERROR_CONNECT_REMOTE_CONFIG;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Check to see if router is running. If so, get the handles
|
|
//
|
|
|
|
do
|
|
{
|
|
if ( MprAdminIsServiceRunning( (LPWSTR)pwszRouter ) )
|
|
{
|
|
if ( MprAdminServerConnect( (LPWSTR)pwszRouter, &g_hMprAdmin ) ==
|
|
NO_ERROR )
|
|
{
|
|
if ( MprAdminMIBServerConnect( (LPWSTR)pwszRouter, &g_hMIBServer ) ==
|
|
NO_ERROR )
|
|
{
|
|
// DEBUG("Got server handle");
|
|
break;
|
|
}
|
|
|
|
else
|
|
{
|
|
MprAdminServerDisconnect( g_hMprAdmin );
|
|
}
|
|
}
|
|
}
|
|
|
|
g_hMprAdmin = g_hMIBServer = NULL;
|
|
|
|
} while (FALSE);
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
DWORD WINAPI
|
|
IpxConnect(
|
|
IN LPCWSTR pwszRouter
|
|
)
|
|
{
|
|
// If context info is dirty, reregister it
|
|
if (g_bIpxDirty)
|
|
{
|
|
IpxStartHelper(NULL, ParentVersion);
|
|
}
|
|
|
|
return ConnectToRouter(pwszRouter);
|
|
}
|
|
|
|
BOOL
|
|
IsHelpToken(
|
|
PWCHAR pwszToken
|
|
)
|
|
/*++
|
|
|
|
Routine Description :
|
|
|
|
Arguements :
|
|
|
|
Return value :
|
|
|
|
--*/
|
|
{
|
|
if( MatchToken( pwszToken, CMD_IPX_HELP1 ) )
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
if( MatchToken( pwszToken, CMD_IPX_HELP2 ) )
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
IsReservedKeyWord(
|
|
PWCHAR pwszToken
|
|
)
|
|
/*++
|
|
|
|
Routine Description :
|
|
|
|
Arguements :
|
|
|
|
Return value :
|
|
|
|
--*/
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
MungeArguments(
|
|
IN OUT LPWSTR *ppwcArguments,
|
|
IN DWORD dwArgCount,
|
|
OUT PBYTE *ppbNewArg,
|
|
OUT PDWORD pdwNewArgCount,
|
|
OUT PBOOL pbFreeArg
|
|
)
|
|
/*++
|
|
|
|
Routine Description :
|
|
|
|
To conform to the routemon style of command line, the netsh command line
|
|
is munged. Munging involves adding a space after the '=' for each
|
|
"Option=Value" pair on the command line to convert it to "Option= Value".
|
|
|
|
In addition, the first command line arguement is set to the process name
|
|
"netsh" and all the remaining arguements are shifted one down. Again
|
|
for conformance reasons.
|
|
|
|
Arguements :
|
|
|
|
ppwcArguments - Current argument list
|
|
|
|
dwArgCount - Number of args in ppwcArguments
|
|
|
|
pbNewArg - Pointer to a buffer that will contain the munged arglist
|
|
|
|
pdwNewArgCount - New argument count after munging
|
|
|
|
pbFreeArg - TRUE if pbNewArg needs to be freed by the invoker.
|
|
|
|
|
|
Return value :
|
|
|
|
NO_ERROR - Success
|
|
|
|
ERROR_NOT_ENOUGH_MEMORY - Memory alloc failed
|
|
|
|
--*/
|
|
{
|
|
|
|
DWORD dwIndex, dwInd, dwErr;
|
|
|
|
BOOL bPresent = FALSE;
|
|
|
|
PWCHAR *ppwcArgs;
|
|
|
|
|
|
|
|
*pbFreeArg = FALSE;
|
|
|
|
|
|
//
|
|
// Scan arguement list to see if any are of the form "Option=Value"
|
|
//
|
|
|
|
for ( dwIndex = 0; dwIndex < dwArgCount; dwIndex++ )
|
|
{
|
|
if ( wcsstr( ppwcArguments[ dwIndex ], NETSH_ARG_DELIMITER ) )
|
|
{
|
|
//
|
|
// there is an = in this arguement
|
|
//
|
|
|
|
bPresent = TRUE;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// if none of the args have an '=', then return the arg. list as is
|
|
//
|
|
|
|
if ( !bPresent )
|
|
{
|
|
*ppbNewArg = (PBYTE) ppwcArguments;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Args. of the form "option=value" are present
|
|
//
|
|
|
|
ppwcArgs = (PWCHAR *) HeapAlloc(
|
|
GetProcessHeap(), 0, 2 * dwArgCount * sizeof( PWCHAR )
|
|
);
|
|
|
|
if ( ppwcArgs == NULL )
|
|
{
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
|
|
ZeroMemory( ppwcArgs, 2 * dwArgCount * sizeof( PWCHAR ) );
|
|
|
|
|
|
//
|
|
// Copy args that do not have an '=' as is
|
|
//
|
|
|
|
for ( dwInd = 0; dwInd < dwIndex; dwInd++ )
|
|
{
|
|
DWORD dwLen = ( wcslen( ppwcArguments[ dwInd ] ) + 1 ) * sizeof( WCHAR );
|
|
|
|
ppwcArgs[ dwInd ] = (PWCHAR) HeapAlloc(
|
|
GetProcessHeap(), 0,
|
|
( wcslen( ppwcArguments[ dwInd ] ) + 1 )
|
|
* sizeof( WCHAR )
|
|
);
|
|
|
|
if ( ppwcArgs[ dwInd ] == NULL )
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
goto cleanup;
|
|
}
|
|
|
|
wcscpy( ppwcArgs[ dwInd ], ppwcArguments[ dwInd ] );
|
|
}
|
|
|
|
|
|
//
|
|
// Convert args. of the form "option=value" to the form "option= value".
|
|
// The space is what its all about
|
|
//
|
|
|
|
for ( dwInd = dwIndex; dwIndex < dwArgCount; dwInd++, dwIndex++ )
|
|
{
|
|
//
|
|
// Check if this arg. has an '=' sign
|
|
//
|
|
|
|
if ( wcsstr( ppwcArguments[ dwIndex ], NETSH_ARG_DELIMITER ) )
|
|
{
|
|
//
|
|
// arg is of the form "option=value"
|
|
//
|
|
// break it into 2 arguments of the form
|
|
// arg(i) == option=
|
|
// argv(i+1) == value
|
|
//
|
|
|
|
PWCHAR pw1, pw2;
|
|
|
|
DWORD dwLen;
|
|
|
|
|
|
pw1 = wcstok( ppwcArguments[ dwIndex ], NETSH_ARG_DELIMITER );
|
|
|
|
pw2 = wcstok( NULL, NETSH_ARG_DELIMITER );
|
|
|
|
dwLen = ( wcslen( pw1 ) + 2 ) * sizeof( WCHAR );
|
|
|
|
dwLen = ( wcslen( pw2 ) + 1 ) * sizeof( WCHAR );
|
|
|
|
|
|
ppwcArgs[ dwInd ] = (PWCHAR) HeapAlloc(
|
|
GetProcessHeap(), 0,
|
|
( wcslen( pw1 ) + 2 ) * sizeof( WCHAR )
|
|
);
|
|
|
|
ppwcArgs[ dwInd + 1] = (PWCHAR) HeapAlloc(
|
|
GetProcessHeap(), 0,
|
|
( wcslen( pw2 ) + 1 ) * sizeof( WCHAR )
|
|
);
|
|
|
|
|
|
if ( ( ppwcArgs[ dwInd ] == NULL ) ||
|
|
( ppwcArgs[ dwInd + 1 ] == NULL ) )
|
|
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
goto cleanup;
|
|
}
|
|
|
|
wcscpy( ppwcArgs[ dwInd ], pw1 );
|
|
|
|
wcscat( ppwcArgs[ dwInd++ ], NETSH_ARG_DELIMITER );
|
|
|
|
wcscpy( ppwcArgs[ dwInd ], pw2 );
|
|
|
|
(*pdwNewArgCount)++;
|
|
}
|
|
|
|
else
|
|
{
|
|
//
|
|
// no = in this arg, copy as is
|
|
//
|
|
|
|
ppwcArgs[ dwInd ] = (PWCHAR) HeapAlloc(
|
|
GetProcessHeap(), 0,
|
|
( wcslen( ppwcArguments[ dwIndex ] ) + 1 )
|
|
* sizeof( WCHAR )
|
|
);
|
|
|
|
if ( ppwcArgs[ dwInd ] == NULL )
|
|
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
goto cleanup;
|
|
}
|
|
|
|
wcscpy( ppwcArgs[ dwInd ], ppwcArguments[ dwIndex ] );
|
|
}
|
|
}
|
|
|
|
*pbFreeArg = TRUE;
|
|
|
|
*ppbNewArg = (PBYTE) ppwcArgs;
|
|
|
|
return NO_ERROR;
|
|
|
|
|
|
|
|
cleanup :
|
|
|
|
//
|
|
// Error. Free all allocations
|
|
//
|
|
|
|
for ( dwInd = 0; dwInd < 2 * dwArgCount; dwInd++ )
|
|
{
|
|
if ( ppwcArgs[ dwInd ] )
|
|
{
|
|
HeapFree( GetProcessHeap(), 0, ppwcArgs[ dwInd ] );
|
|
}
|
|
}
|
|
|
|
if ( ppwcArgs )
|
|
{
|
|
HeapFree( GetProcessHeap(), 0, ppwcArgs );
|
|
}
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
|
|
VOID
|
|
FreeArgTable(
|
|
IN DWORD dwArgCount,
|
|
IN OUT LPWSTR *ppwcArgs
|
|
)
|
|
/*++
|
|
|
|
Routine Description :
|
|
|
|
Frees the allocations for the argument table
|
|
|
|
Arguments :
|
|
|
|
dwArgCount - number of arguments in ppwcArguments
|
|
ppwcArgs - Table of arguments
|
|
|
|
Return Value :
|
|
|
|
--*/
|
|
{
|
|
DWORD dwInd;
|
|
|
|
for ( dwInd = 0; dwInd < 2 * dwArgCount; dwInd++ )
|
|
{
|
|
if ( ppwcArgs[ dwInd ] )
|
|
{
|
|
HeapFree( GetProcessHeap(), 0, ppwcArgs[ dwInd ] );
|
|
}
|
|
}
|
|
|
|
if ( ppwcArgs )
|
|
{
|
|
HeapFree( GetProcessHeap(), 0, ppwcArgs );
|
|
}
|
|
}
|
|
|
|
DWORD
|
|
GetTagToken(
|
|
IN HANDLE hModule,
|
|
IN OUT LPWSTR *ppwcArguments,
|
|
IN DWORD dwCurrentIndex,
|
|
IN DWORD dwArgCount,
|
|
IN PTAG_TYPE pttTagToken,
|
|
IN DWORD dwNumTags,
|
|
OUT PDWORD pdwOut
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Identifies each argument based on its tag. It assumes that each argument
|
|
has a tag. It also removes tag= from each argument.
|
|
|
|
Arguments:
|
|
|
|
ppwcArguments - The argument array. Each argument has tag=value form
|
|
dwCurrentIndex - ppwcArguments[dwCurrentIndex] is first arg.
|
|
dwArgCount - ppwcArguments[dwArgCount - 1] is last arg.
|
|
pttTagToken - Array of tag token ids that are allowed in the args
|
|
dwNumTags - Size of pttTagToken
|
|
pdwOut - Array identifying the type of each argument.
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR, ERROR_INVALID_PARAMETER, ERROR_INVALID_OPTION_TAG
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD i,j,len;
|
|
PWCHAR pwcTag,pwcTagVal,pwszArg;
|
|
BOOL bFound = FALSE;
|
|
|
|
//
|
|
// This function assumes that every argument has a tag
|
|
// It goes ahead and removes the tag.
|
|
//
|
|
|
|
for (i = dwCurrentIndex; i < dwArgCount; i++)
|
|
{
|
|
len = wcslen(ppwcArguments[i]);
|
|
|
|
if (len is 0)
|
|
{
|
|
//
|
|
// something wrong with arg
|
|
//
|
|
|
|
pdwOut[i] = (DWORD) -1;
|
|
continue;
|
|
}
|
|
|
|
pwszArg = HeapAlloc(GetProcessHeap(),0,(len + 1) * sizeof(WCHAR));
|
|
|
|
if (pwszArg is NULL)
|
|
{
|
|
DisplayError(g_hModule, ERROR_NOT_ENOUGH_MEMORY);
|
|
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
wcscpy(pwszArg, ppwcArguments[i]);
|
|
|
|
pwcTag = wcstok(pwszArg, NETSH_ARG_DELIMITER);
|
|
|
|
//
|
|
// Got the first part
|
|
// Now if next call returns NULL then there was no tag
|
|
//
|
|
|
|
pwcTagVal = wcstok((PWCHAR)NULL, NETSH_ARG_DELIMITER);
|
|
|
|
if (pwcTagVal is NULL)
|
|
{
|
|
// DisplayMessage(g_hModule, MSG_IP_TAG_NOT_PRESENT, ppwcArguments[i] );
|
|
HeapFree(GetProcessHeap(),0,pwszArg);
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// Got the tag. Now try to match it
|
|
//
|
|
|
|
bFound = FALSE;
|
|
pdwOut[i - dwCurrentIndex] = (DWORD) -1;
|
|
|
|
for ( j = 0; j < dwNumTags; j++)
|
|
{
|
|
if (MatchToken(pwcTag, pttTagToken[j].pwszTag))
|
|
{
|
|
//
|
|
// Tag matched
|
|
//
|
|
|
|
bFound = TRUE;
|
|
pdwOut[i - dwCurrentIndex] = j;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (bFound)
|
|
{
|
|
//
|
|
// Remove tag from the argument
|
|
//
|
|
|
|
wcscpy(ppwcArguments[i], pwcTagVal);
|
|
}
|
|
else
|
|
{
|
|
//DisplayMessage(g_hModule, MSG_IP_INVALID_TAG, pwcTag);
|
|
HeapFree(GetProcessHeap(),0,pwszArg);
|
|
return ERROR_INVALID_OPTION_TAG;
|
|
}
|
|
|
|
HeapFree(GetProcessHeap(),0,pwszArg);
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
DWORD WINAPI
|
|
IpxSubEntry(
|
|
IN const NS_CONTEXT_ATTRIBUTES *pSubContext,
|
|
IN LPCWSTR pwszMachine,
|
|
IN OUT LPWSTR *ppwcArguments,
|
|
IN DWORD dwArgCount,
|
|
IN DWORD dwFlags,
|
|
IN PVOID pvData,
|
|
OUT LPWSTR pwcNewContext
|
|
)
|
|
{
|
|
DWORD dwErr,
|
|
dwNewArgCount = dwArgCount;
|
|
PWCHAR *ppwcNewArg = NULL;
|
|
BOOL bFreeNewArg;
|
|
PNS_PRIV_CONTEXT_ATTRIBUTES pNsPrivContextAttributes = pSubContext->pReserved;
|
|
|
|
dwErr = MungeArguments( ppwcArguments,
|
|
dwArgCount,
|
|
(PBYTE*) &ppwcNewArg,
|
|
&dwNewArgCount,
|
|
&bFreeNewArg );
|
|
|
|
if (dwErr isnot NO_ERROR )
|
|
{
|
|
return dwErr;
|
|
}
|
|
|
|
if ( (pNsPrivContextAttributes) && (pNsPrivContextAttributes->pfnEntryFn) )
|
|
{
|
|
dwErr = (*pNsPrivContextAttributes->pfnEntryFn)( pwszMachine,
|
|
ppwcNewArg,
|
|
dwNewArgCount,
|
|
dwFlags,
|
|
g_hMIBServer,
|
|
pwcNewContext );
|
|
}
|
|
else
|
|
{
|
|
dwErr = GenericMonitor(pSubContext,
|
|
pwszMachine,
|
|
ppwcNewArg,
|
|
dwNewArgCount,
|
|
dwFlags,
|
|
g_hMIBServer,
|
|
pwcNewContext );
|
|
}
|
|
|
|
if ( bFreeNewArg )
|
|
{
|
|
FreeArgTable( dwArgCount, ppwcNewArg );
|
|
}
|
|
|
|
return dwErr;
|
|
}
|