mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1046 lines
22 KiB
1046 lines
22 KiB
|
|
#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;
|
|
|
|
}
|
|
|
|
|
|
|