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.
1394 lines
31 KiB
1394 lines
31 KiB
|
|
#include "precomp.h"
|
|
|
|
CONST WCHAR pszRemoteAccessParamStub[] =
|
|
L"SYSTEM\\CurrentControlSet\\Services\\RemoteAccess\\Parameters\\";
|
|
CONST WCHAR pszEnableIn[] = L"EnableIn";
|
|
CONST WCHAR pszAllowNetworkAccess[] = L"AllowNetworkAccess";
|
|
|
|
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";
|
|
|
|
typedef struct _NAME_NODE
|
|
{
|
|
PWCHAR pszName;
|
|
struct _NAME_NODE* pNext;
|
|
} NAME_NODE;
|
|
|
|
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;
|
|
}
|
|
|
|
DWORD
|
|
RutlEnumFiles(
|
|
IN LPCWSTR pwszSrchPath,
|
|
IN LPCWSTR pwszSrchStr,
|
|
IN RAS_FILE_ENUM_FUNC_CB pCallback,
|
|
IN HANDLE hData)
|
|
{
|
|
DWORD dwErr = NO_ERROR, dwSize = 0;
|
|
PWCHAR pwszFileSearch = NULL;
|
|
HANDLE hSearch = NULL;
|
|
WIN32_FIND_DATA FindFileData;
|
|
|
|
do
|
|
{
|
|
if (!pwszSrchPath || !pwszSrchStr || !pCallback)
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
dwSize = lstrlen(pwszSrchPath) + lstrlen(pwszSrchStr) + 1;
|
|
if (dwSize < 2)
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
pwszFileSearch = RutlAlloc(dwSize * sizeof(WCHAR), TRUE);
|
|
if (!pwszFileSearch)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
|
|
lstrcpy(pwszFileSearch, pwszSrchPath);
|
|
lstrcat(pwszFileSearch, pwszSrchStr);
|
|
|
|
hSearch = FindFirstFile(pwszFileSearch, &FindFileData);
|
|
if (INVALID_HANDLE_VALUE == hSearch)
|
|
{
|
|
dwErr = GetLastError();
|
|
break;
|
|
}
|
|
|
|
for (;;)
|
|
{
|
|
PWCHAR pwszFileName = NULL;
|
|
|
|
dwSize = lstrlen(pwszSrchPath) +
|
|
lstrlen(FindFileData.cFileName) + 1;
|
|
if (dwSize < 2)
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
pwszFileName = RutlAlloc(dwSize * sizeof(WCHAR), TRUE);
|
|
if (!pwszFileName)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
|
|
lstrcpy(pwszFileName, pwszSrchPath);
|
|
lstrcat(pwszFileName, FindFileData.cFileName);
|
|
//
|
|
// Call the callback
|
|
//
|
|
dwErr = pCallback(pwszFileName, FindFileData.cFileName, hData);
|
|
//
|
|
// Clean up
|
|
//
|
|
RutlFree(pwszFileName);
|
|
|
|
if (dwErr)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if (!FindNextFile(hSearch, &FindFileData))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
FindClose(hSearch);
|
|
|
|
} while (FALSE);
|
|
//
|
|
// Clean up
|
|
//
|
|
RutlFree(pwszFileSearch);
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
DWORD
|
|
RutlEnumEventLogs(
|
|
IN LPCWSTR pwszSourceName,
|
|
IN LPCWSTR pwszMsdDll,
|
|
IN DWORD dwMaxEntries,
|
|
IN RAS_EVENT_ENUM_FUNC_CB pCallback,
|
|
IN HANDLE hData)
|
|
{
|
|
DWORD dwErr = NO_ERROR, dwSize, dwRead, dwNeeded, dwCount = 0;
|
|
LPBYTE pBuffer = NULL;
|
|
HANDLE hLog = NULL;
|
|
HMODULE hMod = NULL;
|
|
PEVENTLOGRECORD pevlr = NULL;
|
|
|
|
do
|
|
{
|
|
hLog = OpenEventLog(NULL, pwszSourceName);
|
|
if (!hLog)
|
|
{
|
|
dwErr = GetLastError();
|
|
break;
|
|
}
|
|
|
|
dwSize = 1024 * sizeof(EVENTLOGRECORD);
|
|
|
|
pBuffer = RutlAlloc(dwSize, FALSE);
|
|
if (!pBuffer)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
|
|
hMod = LoadLibrary(pwszMsdDll);
|
|
if (!hMod)
|
|
{
|
|
dwErr = GetLastError();
|
|
break;
|
|
}
|
|
|
|
pevlr = (PEVENTLOGRECORD)pBuffer;
|
|
//
|
|
// Opening the event log positions the file pointer for this
|
|
// handle at the beginning of the log. Read the records
|
|
// sequentially until there are no more.
|
|
//
|
|
for (;;)
|
|
{
|
|
if (!ReadEventLog(
|
|
hLog,
|
|
EVENTLOG_BACKWARDS_READ | EVENTLOG_SEQUENTIAL_READ,
|
|
0,
|
|
pevlr,
|
|
dwSize,
|
|
&dwRead,
|
|
&dwNeeded))
|
|
{
|
|
dwErr = GetLastError();
|
|
break;
|
|
}
|
|
|
|
while ((dwRead > 0) && (dwCount < dwMaxEntries))
|
|
{
|
|
//
|
|
// Call the callback
|
|
//
|
|
if (pCallback(pevlr, hMod, hData))
|
|
{
|
|
dwCount++;
|
|
}
|
|
|
|
dwRead -= pevlr->Length;
|
|
pevlr = (PEVENTLOGRECORD) ((LPBYTE) pevlr + pevlr->Length);
|
|
}
|
|
|
|
if (dwCount >= dwMaxEntries)
|
|
{
|
|
break;
|
|
}
|
|
|
|
pevlr = (PEVENTLOGRECORD)pBuffer;
|
|
}
|
|
|
|
} while (FALSE);
|
|
//
|
|
// Clean up
|
|
//
|
|
if (hMod)
|
|
{
|
|
FreeLibrary(hMod);
|
|
}
|
|
RutlFree(pBuffer);
|
|
if (hLog)
|
|
{
|
|
CloseEventLog(hLog);
|
|
}
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
INT
|
|
RutlStrNCmp(
|
|
IN LPCWSTR psz1,
|
|
IN LPCWSTR psz2,
|
|
IN UINT nlLen)
|
|
{
|
|
UINT i;
|
|
|
|
for (i = 0; i < nlLen; ++i)
|
|
{
|
|
if (*psz1 == *psz2)
|
|
{
|
|
if (*psz1 == g_pwszNull)
|
|
return 0;
|
|
}
|
|
else if (*psz1 < *psz2)
|
|
return -1;
|
|
else
|
|
return 1;
|
|
|
|
++psz1;
|
|
++psz2;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// Returns heap block containing a copy of 0-terminated string 'psz' or
|
|
// NULL on error or is 'psz' is NULL. The output string is converted to
|
|
// MB ANSI. It is caller's responsibility to 'Free' the returned string.
|
|
//
|
|
PCHAR
|
|
RutlStrDupAFromWInternal(
|
|
LPCTSTR psz,
|
|
IN DWORD dwCp)
|
|
{
|
|
CHAR* pszNew = NULL;
|
|
|
|
if (psz)
|
|
{
|
|
DWORD cb;
|
|
|
|
cb = WideCharToMultiByte(dwCp, 0, psz, -1, NULL, 0, NULL, NULL);
|
|
ASSERT(cb);
|
|
|
|
pszNew = (CHAR* )RutlAlloc(cb + 1, FALSE);
|
|
if (!pszNew)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
cb = WideCharToMultiByte(dwCp, 0, psz, -1, pszNew, cb, NULL, NULL);
|
|
if (cb == 0)
|
|
{
|
|
RutlFree(pszNew);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
return pszNew;
|
|
}
|
|
|
|
PCHAR
|
|
RutlStrDupAFromWAnsi(
|
|
LPCTSTR psz)
|
|
{
|
|
return RutlStrDupAFromWInternal(psz, CP_ACP);
|
|
}
|
|
|
|
PCHAR
|
|
RutlStrDupAFromW(
|
|
LPCTSTR psz)
|
|
{
|
|
return RutlStrDupAFromWInternal(psz, CP_UTF8);
|
|
}
|
|
|
|
BOOL
|
|
RutlSecondsSince1970ToSystemTime(
|
|
IN DWORD dwSecondsSince1970,
|
|
OUT SYSTEMTIME* pSystemTime)
|
|
{
|
|
LARGE_INTEGER liTime;
|
|
FILETIME ftUTC;
|
|
FILETIME ftLocal;
|
|
|
|
//
|
|
// Seconds since the start of 1970 -> 64 bit Time value
|
|
//
|
|
RtlSecondsSince1970ToTime(dwSecondsSince1970, &liTime);
|
|
//
|
|
// The time is in UTC. Convert it to local file time
|
|
//
|
|
ftUTC.dwLowDateTime = liTime.LowPart;
|
|
ftUTC.dwHighDateTime = liTime.HighPart;
|
|
|
|
if (FileTimeToLocalFileTime(&ftUTC, &ftLocal) == FALSE)
|
|
{
|
|
return FALSE;
|
|
}
|
|
//
|
|
// Convert local file time to system time.
|
|
//
|
|
if (FileTimeToSystemTime(&ftLocal, pSystemTime) == FALSE)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
LPWSTR
|
|
RutlGetTimeStr(
|
|
ULONG ulTime,
|
|
LPWSTR wszBuf,
|
|
ULONG cchBuf)
|
|
{
|
|
ULONG cch;
|
|
SYSTEMTIME stGenerated;
|
|
|
|
if (RutlSecondsSince1970ToSystemTime(ulTime, &stGenerated))
|
|
{
|
|
cch = GetTimeFormat(LOCALE_USER_DEFAULT,
|
|
0,
|
|
&stGenerated,
|
|
NULL,
|
|
wszBuf,
|
|
cchBuf);
|
|
if (!cch)
|
|
{
|
|
wszBuf[0] = g_pwszNull;
|
|
}
|
|
}
|
|
|
|
return wszBuf;
|
|
}
|
|
|
|
LPWSTR
|
|
RutlGetDateStr(
|
|
ULONG ulDate,
|
|
LPWSTR wszBuf,
|
|
ULONG cchBuf)
|
|
{
|
|
ULONG cch;
|
|
SYSTEMTIME stGenerated;
|
|
|
|
wszBuf[0] = g_pwszNull;
|
|
|
|
do
|
|
{
|
|
if (!RutlSecondsSince1970ToSystemTime(ulDate, &stGenerated))
|
|
{
|
|
break;
|
|
}
|
|
|
|
cch = GetDateFormat(LOCALE_USER_DEFAULT,
|
|
DATE_SHORTDATE,
|
|
&stGenerated,
|
|
NULL,
|
|
wszBuf,
|
|
cchBuf);
|
|
if (!cch)
|
|
{
|
|
wszBuf[0] = g_pwszNull;
|
|
}
|
|
|
|
} while (FALSE);
|
|
|
|
return wszBuf;
|
|
}
|
|
|
|
VOID
|
|
RutlConvertGuidToString(
|
|
IN CONST GUID *pGuid,
|
|
OUT LPWSTR pwszBuffer)
|
|
{
|
|
wsprintf(pwszBuffer, L"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
|
|
pGuid->Data1, pGuid->Data2, pGuid->Data3,
|
|
pGuid->Data4[0], pGuid->Data4[1],
|
|
pGuid->Data4[2], pGuid->Data4[3],
|
|
pGuid->Data4[4], pGuid->Data4[5],
|
|
pGuid->Data4[6], pGuid->Data4[7]);
|
|
}
|
|
|
|
DWORD
|
|
RutlConvertStringToGuid(
|
|
IN LPCWSTR pwszGuid,
|
|
IN USHORT usStringLen,
|
|
OUT GUID *pGuid)
|
|
{
|
|
UNICODE_STRING Temp;
|
|
|
|
Temp.Length = Temp.MaximumLength = usStringLen;
|
|
|
|
Temp.Buffer = (LPWSTR)pwszGuid;
|
|
|
|
if(RtlGUIDFromString(&Temp, pGuid) isnot STATUS_SUCCESS)
|
|
{
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|