windows-nt/Source/XPSP1/NT/net/rras/netsh/aaaa/utils.cpp

995 lines
24 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 1999 Microsoft Corporation
//
// Module Name:
//
// utils.c
//
// Abstract:
//
// utils functions
//
// Revision History:
//
// Thierry Perraut 04/07/1999
//
//////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include <netsh.h>
#include "aaaamontr.h"
#include "strdefs.h"
#include "rmstring.h"
#include "aaaamon.h"
#include "context.h"
#include <rtutils.h>
#include "utils.h"
#include "base64tool.h"
const WCHAR c_szCurrentBuildNumber[] = L"CurrentBuildNumber";
const WCHAR c_szWinVersionPath[] =
L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion";
const WCHAR c_szAssignFmt[] = L"%s = %s";
const WCHAR pszAAAAEngineParamStub[] =
L"SYSTEM\\CurrentControlSet\\Services\\AAAAEngine\\Parameters\\";
AAAA_ALLOC_FN RutlAlloc;
AAAA_DWORDDUP_FN RutlDwordDup;
AAAA_CREATE_DUMP_FILE_FN RutlCreateDumpFile;
AAAA_CLOSE_DUMP_FILE_FN RutlCloseDumpFile;
AAAA_ASSIGN_FROM_TOKENS_FN RutlAssignmentFromTokens;
AAAA_STRDUP_FN RutlStrDup;
AAAA_FREE_FN RutlFree;
AAAA_GET_OS_VERSION_FN RutlGetOsVersion;
AAAA_GET_TAG_TOKEN_FN RutlGetTagToken;
AAAA_IS_HELP_TOKEN_FN RutlIsHelpToken;
//////////////////////////////////////////////////////////////////////////////
// RutlGetTagToken
//
// 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
WINAPI
RutlGetTagToken(
IN HANDLE hModule,
IN PWCHAR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN PTAG_TYPE pttTagToken,
IN DWORD dwNumTags,
OUT PDWORD pdwOut
)
{
PWCHAR pwcTag,pwcTagVal,pwszArg = NULL;
//
// This function assumes that every argument has a tag
// It goes ahead and removes the tag.
//
for ( DWORD i = dwCurrentIndex; i < dwArgCount; ++i )
{
DWORD len = wcslen(ppwcArguments[i]);
if ( !len )
{
//
// something wrong with arg
//
pdwOut[i] = static_cast<DWORD> (-1);
continue;
}
pwszArg = static_cast<unsigned short *>(RutlAlloc(
(len + 1) * sizeof(WCHAR),
FALSE));
if ( !pwszArg )
{
DisplayError(NULL, 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 )
{
DisplayMessage(g_hModule,
ERROR_NO_TAG,
ppwcArguments[i]);
RutlFree(pwszArg);
return ERROR_INVALID_PARAMETER;
}
//
// Got the tag. Now try to match it
//
BOOL bFound = FALSE;
pdwOut[i - dwCurrentIndex] = (DWORD) -1;
for ( DWORD 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
{
DisplayError(NULL,
ERROR_INVALID_OPTION_TAG,
pwcTag);
RutlFree(pwszArg);
return ERROR_INVALID_OPTION_TAG;
}
RutlFree(pwszArg);
}
return NO_ERROR;
}
//////////////////////////////////////////////////////////////////////////////
// RutlCreateDumpFile
//////////////////////////////////////////////////////////////////////////////
DWORD
WINAPI
RutlCreateDumpFile(
IN PWCHAR pwszName,
OUT PHANDLE phFile
)
{
HANDLE hFile;
*phFile = NULL;
// Create/open the file
hFile = CreateFileW(pwszName,
GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_DELETE,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if ( hFile == INVALID_HANDLE_VALUE )
{
return GetLastError();
}
// Go to the end of the file
SetFilePointer(hFile, 0, NULL, FILE_END);
*phFile = hFile;
return NO_ERROR;
}
//////////////////////////////////////////////////////////////////////////////
// RutlCloseDumpFile
//////////////////////////////////////////////////////////////////////////////
VOID
WINAPI
RutlCloseDumpFile(HANDLE hFile)
{
CloseHandle(hFile);
}
//////////////////////////////////////////////////////////////////////////////
//
// RutlAlloc
//
// Returns an allocated block of memory conditionally
// zeroed of the given size.
//
//////////////////////////////////////////////////////////////////////////////
PVOID
WINAPI
RutlAlloc(
IN DWORD dwBytes,
IN BOOL bZero
)
{
DWORD dwFlags = 0;
if ( bZero )
{
dwFlags |= HEAP_ZERO_MEMORY;
}
return HeapAlloc(GetProcessHeap(), dwFlags, dwBytes);
}
//////////////////////////////////////////////////////////////////////////////
//
// RutlFree
//
// Conditionally free's a pointer if it is non-null
//
//////////////////////////////////////////////////////////////////////////////
VOID
WINAPI
RutlFree(
IN PVOID pvData
)
{
HeapFree(GetProcessHeap(), 0, pvData);
}
//////////////////////////////////////////////////////////////////////////////
//
// RutlStrDup
//
// Uses RutlAlloc to copy a string
//
//////////////////////////////////////////////////////////////////////////////
PWCHAR
WINAPI
RutlStrDup(
IN PWCHAR pwszSrc
)
{
PWCHAR pszRet = NULL;
DWORD dwLen;
if (( !pwszSrc ) || ((dwLen = wcslen(pwszSrc)) == 0))
{
return NULL;
}
pszRet = static_cast<PWCHAR>(RutlAlloc((dwLen + 1) * sizeof(WCHAR),FALSE));
if ( pszRet )
{
wcscpy(pszRet, pwszSrc);
}
return pszRet;
}
//////////////////////////////////////////////////////////////////////////////
// RutlDwordDup
//
// Uses RutlAlloc to copy a dword
//
//////////////////////////////////////////////////////////////////////////////
LPDWORD
WINAPI
RutlDwordDup(
IN DWORD dwSrc
)
{
LPDWORD lpdwRet = NULL;
lpdwRet = static_cast<LPDWORD>(RutlAlloc(sizeof(DWORD), FALSE));
if ( lpdwRet )
{
*lpdwRet = dwSrc;
}
return lpdwRet;
}
//////////////////////////////////////////////////////////////////////////////
//
// RutlGetOsVersion
//
// Returns the build number of operating system
//
//////////////////////////////////////////////////////////////////////////////
DWORD
WINAPI
RutlGetOsVersion(
IN PWCHAR pwszRouter,
OUT LPDWORD lpdwVersion)
{
DWORD dwErr, dwType = REG_SZ, dwLength;
HKEY hkMachine = NULL, hkVersion = NULL;
WCHAR pszBuildNumber[64];
PWCHAR pszMachine = pwszRouter;
//
// Validate and initialize
//
if ( !lpdwVersion )
{
return ERROR_INVALID_PARAMETER;
}
*lpdwVersion = FALSE;
do
{
//
// Connect to the remote server
//
dwErr = RegConnectRegistry(
pszMachine,
HKEY_LOCAL_MACHINE,
&hkMachine);
if ( dwErr != ERROR_SUCCESS )
{
break;
}
//
// Open the windows version key
//
dwErr = RegOpenKeyEx(
hkMachine,
c_szWinVersionPath,
0,
KEY_QUERY_VALUE,
&hkVersion
);
if ( dwErr != NO_ERROR )
{
break;
}
//
// Read in the current version key
//
dwLength = sizeof(pszBuildNumber);
dwErr = RegQueryValueEx (
hkVersion,
c_szCurrentBuildNumber,
NULL,
&dwType,
(BYTE*)pszBuildNumber,
&dwLength
);
if ( dwErr != NO_ERROR )
{
break;
}
*lpdwVersion = static_cast<DWORD>(wcstol(pszBuildNumber, NULL, 10));
} while (FALSE);
// Cleanup
if ( hkVersion )
{
RegCloseKey( hkVersion );
}
if ( hkMachine )
{
RegCloseKey( hkMachine );
}
return dwErr;
}
//////////////////////////////////////////////////////////////////////////////
//
// RutlParseOptions
//
// Routine Description:
//
// Based on an array of tag types returns which options are
// included in the given command line.
//
// Arguments:
//
// ppwcArguments - Argument array
// dwCurrentIndex - ppwcArguments[dwCurrentIndex] is the first arg
// dwArgCount - ppwcArguments[dwArgCount - 1] is the last arg
//
// Return Value:
//
// NO_ERROR
//
//////////////////////////////////////////////////////////////////////////////
DWORD
WINAPI
RutlParseOptions(
IN PWCHAR* ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwNumArgs,
IN TAG_TYPE* rgTags,
IN DWORD dwTagCount,
OUT LPDWORD* ppdwTagTypes
)
{
LPDWORD pdwTagType;
DWORD i, dwErr = NO_ERROR;
// If there are no arguments, there's nothing to to
//
if ( !dwNumArgs )
{
return NO_ERROR;
}
// Set up the table of present options
pdwTagType = static_cast<LPDWORD>(RutlAlloc(
dwArgCount * sizeof(DWORD),
TRUE
));
if( !pdwTagType )
{
DisplayError(NULL, ERROR_NOT_ENOUGH_MEMORY);
return ERROR_NOT_ENOUGH_MEMORY;
}
do {
//
// The argument has a tag. Assume all of them have tags
//
if( wcsstr(ppwcArguments[dwCurrentIndex], NETSH_ARG_DELIMITER) )
{
dwErr = RutlGetTagToken(
g_hModule,
ppwcArguments,
dwCurrentIndex,
dwArgCount,
rgTags,
dwTagCount,
pdwTagType);
if( dwErr != NO_ERROR )
{
if( dwErr == ERROR_INVALID_OPTION_TAG )
{
dwErr = ERROR_INVALID_SYNTAX;
break;
}
}
}
else
{
//
// No tags - all args must be in order
//
for( i = 0; i < dwNumArgs; ++i )
{
pdwTagType[i] = i;
}
}
} while (FALSE);
// Cleanup
{
if ( dwErr == NO_ERROR )
{
*ppdwTagTypes = pdwTagType;
}
else
{
RutlFree(pdwTagType);
}
}
return dwErr;
}
//////////////////////////////////////////////////////////////////////////////
//
// RutlIsHelpToken
//
//////////////////////////////////////////////////////////////////////////////
BOOL
WINAPI
RutlIsHelpToken(PWCHAR pwszToken)
{
if( MatchToken(pwszToken, CMD_AAAA_HELP1) )
{
return TRUE;
}
if( MatchToken(pwszToken, CMD_AAAA_HELP2) )
{
return TRUE;
}
return FALSE;
}
//////////////////////////////////////////////////////////////////////////////
//
// RutlAssignmentFromTokens
//
//////////////////////////////////////////////////////////////////////////////
PWCHAR
WINAPI
RutlAssignmentFromTokens(
IN HINSTANCE hModule,
IN PWCHAR pwszToken,
IN PWCHAR pszString
)
{
PWCHAR pszRet = NULL, pszCmd = NULL;
DWORD dwErr = NO_ERROR, dwSize;
do
{
pszCmd = pwszToken;
// Compute the string lenghth needed
//
dwSize = wcslen(pszString) +
wcslen(pszCmd) +
wcslen(c_szAssignFmt) +
1;
dwSize *= sizeof(WCHAR);
// Allocate the return value
pszRet = (PWCHAR) RutlAlloc(dwSize, FALSE);
if (pszRet == NULL)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
break;
}
// Copy in the command assignment
_snwprintf(
pszRet,
dwSize,
c_szAssignFmt,
pszCmd,
pszString
);
} while ( FALSE );
// Cleanup
{
if ( dwErr != NO_ERROR )
{
if ( pszRet )
{
RutlFree(pszRet);
}
pszRet = NULL;
}
}
return pszRet;
}
//////////////////////////////////////////////////////////////////////////////
//
// RutlRegReadDword
//
//////////////////////////////////////////////////////////////////////////////
DWORD
RutlRegReadDword(
IN HKEY hKey,
IN PWCHAR pszValName,
OUT LPDWORD lpdwValue
)
{
DWORD dwSize = sizeof(DWORD), dwType = REG_DWORD, dwErr;
dwErr = RegQueryValueExW(
hKey,
pszValName,
NULL,
&dwType,
(LPBYTE)lpdwValue,
&dwSize);
if ( dwErr == ERROR_FILE_NOT_FOUND )
{
dwErr = NO_ERROR;
}
return dwErr;
}
//////////////////////////////////////////////////////////////////////////////
//
// RutlRegReadString
//
//////////////////////////////////////////////////////////////////////////////
DWORD
RutlRegReadString(
IN HKEY hKey,
IN PWCHAR pszValName,
OUT PWCHAR* ppszValue
)
{
DWORD dwErr = NO_ERROR, dwSize = 0;
*ppszValue = NULL;
// Findout how big the buffer should be
//
dwErr = RegQueryValueExW(
hKey,
pszValName,
NULL,
NULL,
NULL,
&dwSize);
if ( dwErr == ERROR_FILE_NOT_FOUND )
{
return NO_ERROR;
}
if ( dwErr != ERROR_SUCCESS )
{
return dwErr;
}
// Allocate the string
//
*ppszValue = (PWCHAR) RutlAlloc(dwSize, TRUE);
if ( ! *ppszValue )
{
return ERROR_NOT_ENOUGH_MEMORY;
}
// Read the value in and return
//
dwErr = RegQueryValueExW(
hKey,
pszValName,
NULL,
NULL,
(LPBYTE)*ppszValue,
&dwSize);
return dwErr;
}
//////////////////////////////////////////////////////////////////////////////
//
// RutlRegReadString
//
//////////////////////////////////////////////////////////////////////////////
DWORD
RutlRegWriteDword(
IN HKEY hKey,
IN PWCHAR pszValName,
IN DWORD dwValue
)
{
return RegSetValueExW(
hKey,
pszValName,
0,
REG_DWORD,
(LPBYTE)&dwValue,
sizeof(DWORD));
}
//////////////////////////////////////////////////////////////////////////////
//
// RutlRegWriteString
//
//////////////////////////////////////////////////////////////////////////////
DWORD
RutlRegWriteString(
IN HKEY hKey,
IN PWCHAR pszValName,
IN PWCHAR pszValue
)
{
return RegSetValueExW(
hKey,
pszValName,
0,
REG_SZ,
(LPBYTE)pszValue,
(wcslen(pszValue) + 1) * sizeof(WCHAR));
}
//////////////////////////////////////////////////////////////////////////////
//RutlParse
//
// Generic parse
//
//////////////////////////////////////////////////////////////////////////////
DWORD
RutlParse(
IN PWCHAR* ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN BOOL* pbDone,
OUT AAAAMON_CMD_ARG* pAaaaArgs,
IN DWORD dwAaaaArgCount
)
{
DWORD i, dwNumArgs, dwErr, dwLevel = 0;
LPDWORD pdwTagType = NULL;
TAG_TYPE* pTags = NULL;
AAAAMON_CMD_ARG* pArg = NULL;
if ( !dwAaaaArgCount )
{
return ERROR_INVALID_PARAMETER;
}
do
{
// Initialize
dwNumArgs = dwArgCount - dwCurrentIndex;
// Generate a list of the tags
//
pTags = (TAG_TYPE*)
RutlAlloc(dwAaaaArgCount * sizeof(TAG_TYPE), TRUE);
if ( !pTags )
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
break;
}
for ( i = 0; i < dwAaaaArgCount; ++i )
{
CopyMemory(&pTags[i], &pAaaaArgs[i].rgTag, sizeof(TAG_TYPE));
}
// Get the list of present options
//
dwErr = RutlParseOptions(
ppwcArguments,
dwCurrentIndex,
dwArgCount,
dwNumArgs,
pTags,
dwAaaaArgCount,
&pdwTagType);
if ( dwErr != NO_ERROR )
{
break;
}
// Copy the tag info back
//
for ( i = 0; i < dwAaaaArgCount; ++i )
{
CopyMemory(&pAaaaArgs[i].rgTag, &pTags[i], sizeof(TAG_TYPE));
}
for( i = 0; i < dwNumArgs; ++i )
{
// Validate the current argument
//
if ( pdwTagType[i] >= dwAaaaArgCount )
{
i = dwNumArgs;
dwErr = ERROR_INVALID_SYNTAX;
break;
}
pArg = &pAaaaArgs[pdwTagType[i]];
// Get the value of the argument
//
switch ( pArg->dwType )
{
case AAAAMONTR_CMD_TYPE_STRING:
{
pArg->Val.pszValue =
RutlStrDup(ppwcArguments[i + dwCurrentIndex]);
break;
}
case AAAAMONTR_CMD_TYPE_ENUM:
{
dwErr = MatchEnumTag(g_hModule,
ppwcArguments[i + dwCurrentIndex],
pArg->dwEnumCount,
pArg->rgEnums,
&(pArg->Val.dwValue));
if(dwErr != NO_ERROR)
{
RutlDispTokenErrMsg(
g_hModule,
EMSG_BAD_OPTION_VALUE,
pArg->rgTag.pwszTag,
ppwcArguments[i + dwCurrentIndex]);
i = dwNumArgs;
dwErr = ERROR_INVALID_PARAMETER;
}
break;
}
}
if ( dwErr != NO_ERROR )
{
break;
}
// Mark the argument as present if needed
//
if ( pArg->rgTag.bPresent )
{
dwErr = ERROR_TAG_ALREADY_PRESENT;
i = dwNumArgs;
break;
}
pArg->rgTag.bPresent = TRUE;
}
if( dwErr != NO_ERROR )
{
break;
}
// Make sure that all of the required parameters have
// been included.
//
for ( i = 0; i < dwAaaaArgCount; ++i )
{
if ( (pAaaaArgs[i].rgTag.dwRequired & NS_REQ_PRESENT)
&& !pAaaaArgs[i].rgTag.bPresent )
{
DisplayMessage(g_hModule, EMSG_CANT_FIND_EOPT);
dwErr = ERROR_INVALID_SYNTAX;
break;
}
}
if ( dwErr != NO_ERROR )
{
break;
}
} while (FALSE);
// Cleanup
{
if ( pTags )
{
RutlFree(pTags);
}
if ( pdwTagType )
{
RutlFree(pdwTagType);
}
}
return dwErr;
}
//////////////////////////////////////////////////////////////////////////////
// RefreshIASService
//
// Send a control 128 (refresh)to IAS
//
//////////////////////////////////////////////////////////////////////////////
HRESULT RefreshIASService()
{
SC_HANDLE hManager = OpenSCManager(
NULL,
SERVICES_ACTIVE_DATABASE,
SC_MANAGER_CONNECT |
SC_MANAGER_ENUMERATE_SERVICE |
SC_MANAGER_QUERY_LOCK_STATUS
);
if ( !hManager )
{
return E_FAIL;
}
SC_HANDLE hService = OpenServiceW(
hManager,
L"IAS",
SERVICE_USER_DEFINED_CONTROL |
SERVICE_QUERY_STATUS
);
if ( !hService )
{
CloseServiceHandle(hManager);
return E_FAIL;
}
SERVICE_STATUS ServiceStatus;
BOOL bResultOk = QueryServiceStatus(
hService,
&ServiceStatus
);
HRESULT hres;
if ( bResultOk )
{
if ( (SERVICE_STOPPED == ServiceStatus.dwCurrentState) ||
(SERVICE_STOP_PENDING == ServiceStatus.dwCurrentState))
{
//////////////////////////////////////////////////
// service not running = nothing to do to refresh
//////////////////////////////////////////////////
hres = S_OK;
}
else
{
/////////////////////////////////////////////////////
// the service is running thus send the refresh code
/////////////////////////////////////////////////////
BOOL bControlOk = ControlService(
hService,
128,
&ServiceStatus
);
if ( bControlOk == FALSE )
{
hres = E_FAIL;
}
else
{
hres = S_OK;
}
}
}
else
{
hres = E_FAIL;
}
//////////
// clean
//////////
CloseServiceHandle(hService);
CloseServiceHandle(hManager);
// hres is always defined here.
return hres;
}