Leaked source code of windows server 2003
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

#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;
}