windows-nt/Source/XPSP1/NT/net/rras/netsh/ras/utils.c
2020-09-26 16:20:57 +08:00

1047 lines
22 KiB
C

#include "precomp.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 c_szAssignFmt10[] = L"%s = %d";
const WCHAR c_szAssignFmt16[] = L"%s = %x";
WCHAR pszRemoteAccessParamStub[] =
L"SYSTEM\\CurrentControlSet\\Services\\RemoteAccess\\Parameters\\";
WCHAR pszEnableIn[] = L"EnableIn";
WCHAR pszAllowNetworkAccess[] = L"AllowNetworkAccess";
typedef struct _NAME_NODE
{
PWCHAR pszName;
struct _NAME_NODE* pNext;
} NAME_NODE;
#if 0
DWORD
RutlDispTokenErrMsg(
IN HANDLE hModule,
IN DWORD dwMsgId,
IN DWORD dwTagId,
IN LPCWSTR pwszValue
)
/*++
Routine Description:
Displays error message with token arguments.
Arguments:
dwMsgId - Message to be printed
dwTagId - The tag string id
pwszValue - the value specified for the tag in the
Return Value:
NO_ERROR
--*/
{
PWCHAR pwszTag;
pwszTag = MakeString(hModule,
dwTagId);
DisplayMessage(hModule,
dwMsgId,
pwszValue,
pwszTag);
FreeString(pwszTag);
return NO_ERROR;
}
#endif
DWORD
WINAPI
RutlGetTagToken(
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 = NULL;
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 = RutlAlloc((len + 1) * sizeof(WCHAR), FALSE);
if (pwszArg is NULL)
{
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 is NULL)
{
DisplayMessage(g_hModule,
ERROR_NO_TAG,
ppwcArguments[i]);
RutlFree(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
{
DisplayError(NULL,
ERROR_INVALID_OPTION_TAG,
pwcTag);
RutlFree(pwszArg);
return ERROR_INVALID_OPTION_TAG;
}
RutlFree(pwszArg);
}
return NO_ERROR;
}
DWORD
WINAPI
RutlCreateDumpFile(
IN LPCWSTR 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;
}
VOID
WINAPI
RutlCloseDumpFile(
HANDLE hFile
)
{
CloseHandle(hFile);
}
//
// Returns an allocated block of memory conditionally
// zeroed of the given size.
//
PVOID
WINAPI
RutlAlloc(
IN DWORD dwBytes,
IN BOOL bZero
)
{
PVOID pvRet;
DWORD dwFlags = 0;
if (bZero)
{
dwFlags |= HEAP_ZERO_MEMORY;
}
return HeapAlloc(GetProcessHeap(), dwFlags, dwBytes);
}
//
// Conditionally free's a pointer if it is non-null
//
VOID
WINAPI
RutlFree(
IN PVOID pvData
)
{
if (pvData)
{
HeapFree(GetProcessHeap(), 0, pvData);
}
}
//
// Uses RutlAlloc to copy a string
//
PWCHAR
WINAPI
RutlStrDup(
IN LPCWSTR pwszSrc
)
{
PWCHAR pszRet = NULL;
DWORD dwLen;
if ((pwszSrc is NULL) or
((dwLen = wcslen(pwszSrc)) == 0)
)
{
return NULL;
}
pszRet = (PWCHAR) RutlAlloc((dwLen + 1) * sizeof(WCHAR), FALSE);
if (pszRet isnot NULL)
{
wcscpy(pszRet, pwszSrc);
}
return pszRet;
}
//
// Uses RutlAlloc to copy a dword
//
LPDWORD
WINAPI
RutlDwordDup(
IN DWORD dwSrc
)
{
LPDWORD lpdwRet = NULL;
lpdwRet = (LPDWORD) RutlAlloc(sizeof(DWORD), FALSE);
if (lpdwRet isnot NULL)
{
*lpdwRet = dwSrc;
}
return lpdwRet;
}
//
// Returns the build number of operating system
//
DWORD
WINAPI
RutlGetOsVersion(
IN RASMON_SERVERINFO *pServerInfo
)
{
DWORD dwErr, dwType = REG_SZ, dwLength;
HKEY hkVersion = NULL;
WCHAR pszBuildNumber[64];
//
// Initialize
//
pServerInfo->dwBuild = 0;
do
{
//
// Connect to the remote server
//
dwErr = RegConnectRegistry(
pServerInfo->pszServer,
HKEY_LOCAL_MACHINE,
&pServerInfo->hkMachine);
if ( dwErr != ERROR_SUCCESS )
{
break;
}
//
// Open the windows version key
//
dwErr = RegOpenKeyEx(
pServerInfo->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;
}
pServerInfo->dwBuild = (DWORD) wcstol(pszBuildNumber, NULL, 10);
} while (FALSE);
// Cleanup
{
if ( hkVersion )
{
RegCloseKey( hkVersion );
}
}
return dwErr;
}
DWORD
WINAPI
RutlParseOptions(
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwNumArgs,
IN TAG_TYPE* rgTags,
IN DWORD dwTagCount,
OUT LPDWORD* ppdwTagTypes)
/*++
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
--*/
{
LPDWORD pdwTagType;
DWORD i, dwErr = NO_ERROR;
// If there are no arguments, there's nothing to to
//
if ( dwNumArgs == 0 )
{
return NO_ERROR;
}
// Set up the table of present options
pdwTagType = (LPDWORD) RutlAlloc(dwArgCount * sizeof(DWORD), TRUE);
if(pdwTagType is NULL)
{
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 isnot NO_ERROR)
{
if(dwErr is 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 is NO_ERROR)
{
*ppdwTagTypes = pdwTagType;
}
else
{
RutlFree(pdwTagType);
}
}
return dwErr;
}
BOOL
WINAPI
RutlIsHelpToken(
PWCHAR pwszToken
)
{
if(MatchToken(pwszToken, CMD_RAS_HELP1))
return TRUE;
if(MatchToken(pwszToken, CMD_RAS_HELP2))
return TRUE;
return FALSE;
}
PWCHAR
WINAPI
RutlAssignmentFromTokens(
IN HINSTANCE hModule,
IN LPCWSTR pwszToken,
IN LPCWSTR pszString)
{
PWCHAR pszRet = NULL;
LPCWSTR 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 is NULL)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
break;
}
// Copy in the command assignment
wsprintfW(pszRet, c_szAssignFmt, pszCmd, pszString);
} while (FALSE);
// Cleanup
{
if (dwErr isnot NO_ERROR)
{
if (pszRet isnot NULL)
{
RutlFree(pszRet);
}
pszRet = NULL;
}
}
return pszRet;
}
PWCHAR
WINAPI
RutlAssignmentFromTokenAndDword(
IN HINSTANCE hModule,
IN LPCWSTR pwszToken,
IN DWORD dwDword,
IN DWORD dwRadius)
{
PWCHAR pszRet = NULL;
LPCWSTR pszCmd = NULL;
DWORD dwErr = NO_ERROR, dwSize;
do
{
pszCmd = pwszToken;
// Compute the string length needed
//
dwSize = 64 +
wcslen(pszCmd) +
wcslen(c_szAssignFmt10) +
1;
dwSize *= sizeof(WCHAR);
// Allocate the return value
pszRet = (PWCHAR) RutlAlloc(dwSize, FALSE);
if (pszRet is NULL)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
break;
}
// Copy in the command assignment
if (dwRadius == 10)
{
wsprintfW(pszRet, c_szAssignFmt10, pszCmd, dwDword);
}
else
{
wsprintfW(pszRet, c_szAssignFmt16, pszCmd, dwDword);
}
} while (FALSE);
// Cleanup
{
if (dwErr isnot NO_ERROR)
{
if (pszRet isnot NULL)
{
RutlFree(pszRet);
}
pszRet = NULL;
}
}
return pszRet;
}
DWORD
RutlRegReadDword(
IN HKEY hKey,
IN LPCWSTR 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;
}
DWORD
RutlRegReadString(
IN HKEY hKey,
IN LPCWSTR pszValName,
OUT LPWSTR* 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 == NULL)
{
return ERROR_NOT_ENOUGH_MEMORY;
}
// Read the value in and return
//
dwErr = RegQueryValueExW(
hKey,
pszValName,
NULL,
NULL,
(LPBYTE)*ppszValue,
&dwSize);
return dwErr;
}
DWORD
RutlRegWriteDword(
IN HKEY hKey,
IN LPCWSTR pszValName,
IN DWORD dwValue)
{
return RegSetValueExW(
hKey,
pszValName,
0,
REG_DWORD,
(LPBYTE)&dwValue,
sizeof(DWORD));
}
DWORD
RutlRegWriteString(
IN HKEY hKey,
IN LPCWSTR pszValName,
IN LPCWSTR pszValue)
{
return RegSetValueExW(
hKey,
pszValName,
0,
REG_SZ,
(LPBYTE)pszValue,
(wcslen(pszValue) + 1) * sizeof(WCHAR));
}
//
// Enumerates all of the subkeys of a given key
//
DWORD
RutlRegEnumKeys(
IN HKEY hkKey,
IN RAS_REGKEY_ENUM_FUNC_CB pCallback,
IN HANDLE hData)
{
DWORD dwErr = NO_ERROR, i, dwNameSize = 0, dwCurSize = 0;
DWORD dwCount = 0;
HKEY hkCurKey = NULL;
PWCHAR pszName = NULL;
NAME_NODE *pHead = NULL, *pTemp = NULL;
do
{
// Find out how many sub keys there are
//
dwErr = RegQueryInfoKeyW(
hkKey,
NULL,
NULL,
NULL,
&dwCount,
&dwNameSize,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL);
if (dwErr != ERROR_SUCCESS)
{
return dwErr;
}
dwNameSize++;
// Allocate the name buffer
//
pszName = (PWCHAR) RutlAlloc(dwNameSize * sizeof(WCHAR), FALSE);
if (pszName == NULL)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
break;
}
// Loop through the keys building the list
//
for (i = 0; i < dwCount; i++)
{
dwCurSize = dwNameSize;
// Get the name of the current key
//
dwErr = RegEnumKeyExW(
hkKey,
i,
pszName,
&dwCurSize,
0,
NULL,
NULL,
NULL);
if (dwErr != ERROR_SUCCESS)
{
continue;
}
// Add the key to the list
//
pTemp = (NAME_NODE*) RutlAlloc(sizeof(NAME_NODE), TRUE);
if (pTemp == NULL)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
break;
}
pTemp->pszName = RutlStrDup(pszName);
if (pTemp->pszName == NULL)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
break;
}
pTemp->pNext = pHead;
pHead = pTemp;
}
BREAK_ON_DWERR(dwErr);
// Now loop through the list, calling the callback.
// The reason the items are added to a list like this
// is that this allows the callback to safely delete
// the reg key without messing up the enumeration
//
pTemp = pHead;
while (pTemp)
{
// Open the subkey
//
dwErr = RegOpenKeyExW(
hkKey,
pTemp->pszName,
0,
KEY_ALL_ACCESS,
&hkCurKey);
if (dwErr != ERROR_SUCCESS)
{
continue;
}
// Call the callback
//
dwErr = pCallback(pTemp->pszName, hkCurKey, hData);
RegCloseKey(hkCurKey);
if (dwErr != NO_ERROR)
{
break;
}
pTemp = pTemp->pNext;
}
} while (FALSE);
// Cleanup
{
RutlFree(pszName);
while (pHead)
{
RutlFree(pHead->pszName);
pTemp = pHead->pNext;
RutlFree(pHead);
pHead = pTemp;
}
}
return dwErr;
}
//
// Generic parse
//
DWORD
RutlParse(
IN OUT LPWSTR* ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN BOOL* pbDone,
OUT RASMON_CMD_ARG* pRasArgs,
IN DWORD dwRasArgCount)
{
DWORD i, dwNumArgs, dwErr, dwLevel = 0;
LPDWORD pdwTagType = NULL;
TAG_TYPE* pTags = NULL;
RASMON_CMD_ARG* pArg = NULL;
if (dwRasArgCount == 0)
{
return ERROR_INVALID_PARAMETER;
}
do {
// Initialize
dwNumArgs = dwArgCount - dwCurrentIndex;
// Generate a list of the tags
//
pTags = (TAG_TYPE*)
RutlAlloc(dwRasArgCount * sizeof(TAG_TYPE), TRUE);
if (pTags == NULL)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
break;
}
for (i = 0; i < dwRasArgCount; i++)
{
CopyMemory(&pTags[i], &pRasArgs[i].rgTag, sizeof(TAG_TYPE));
}
// Get the list of present options
//
dwErr = RutlParseOptions(
ppwcArguments,
dwCurrentIndex,
dwArgCount,
dwNumArgs,
pTags,
dwRasArgCount,
&pdwTagType);
if (dwErr isnot NO_ERROR)
{
break;
}
// Copy the tag info back
//
for (i = 0; i < dwRasArgCount; i++)
{
CopyMemory(&pRasArgs[i].rgTag, &pTags[i], sizeof(TAG_TYPE));
}
for(i = 0; i < dwNumArgs; i++)
{
// Validate the current argument
//
if (pdwTagType[i] >= dwRasArgCount)
{
i = dwNumArgs;
dwErr = ERROR_INVALID_SYNTAX;
break;
}
pArg = &pRasArgs[pdwTagType[i]];
// Get the value of the argument
//
switch (pArg->dwType)
{
case RASMONTR_CMD_TYPE_STRING:
pArg->Val.pszValue =
RutlStrDup(ppwcArguments[i + dwCurrentIndex]);
break;
case RASMONTR_CMD_TYPE_DWORD:
pArg->Val.dwValue =
_wtol(ppwcArguments[i + dwCurrentIndex]);
break;
case RASMONTR_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 isnot NO_ERROR)
{
break;
}
// Make sure that all of the required parameters have
// been included.
//
for (i = 0; i < dwRasArgCount; i++)
{
if ((pRasArgs[i].rgTag.dwRequired & NS_REQ_PRESENT)
&& !pRasArgs[i].rgTag.bPresent)
{
DisplayMessage(g_hModule, EMSG_CANT_FIND_EOPT);
dwErr = ERROR_INVALID_SYNTAX;
break;
}
}
if(dwErr isnot NO_ERROR)
{
break;
}
} while (FALSE);
// Cleanup
{
if (pTags)
{
RutlFree(pTags);
}
if (pdwTagType)
{
RutlFree(pdwTagType);
}
}
return dwErr;
}