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.
 
 
 
 
 
 

725 lines
19 KiB

/*++
Copyright (c) 1997-1999 Microsoft Corporation
Module Name:
Utils.c
Abstract:
Contains utility methods which are used throughout the project.
--*/
#ifndef UNICODE
#define UNICODE 1
#endif
#ifndef _UNICODE
#define _UNICODE 1
#endif
// Define the following to use the minimum of shlwapip.h
#ifndef NO_SHLWAPI_PATH
#define NO_SHLWAPI_PATH
#endif
#ifndef NO_SHLWAPI_REG
#define NO_SHLWAPI_REG
#endif
#ifndef NO_SHLWAPI_UALSTR
#define NO_SHLWAPI_UALSTR
#endif
#ifndef NO_SHLWAPI_STREAM
#define NO_SHLWAPI_STREAM
#endif
#ifndef NO_SHLWAPI_HTTP
#define NO_SHLWAPI_HTTP
#endif
#ifndef NO_SHLWAPI_INTERNAL
#define NO_SHLWAPI_INTERNAL
#endif
#ifndef NO_SHLWAPI_GDI
#define NO_SHLWAPI_GDI
#endif
#ifndef NO_SHLWAPI_UNITHUNK
#define NO_SHLWAPI_UNITHUNK
#endif
#ifndef NO_SHLWAPI_TPS
#define NO_SHLWAPI_TPS
#endif
#ifndef NO_SHLWAPI_MLUI
#define NO_SHLWAPI_MLUI
#endif
#include <shlwapi.h> // For PlaReadRegistryIndirectStringValue
#include <shlwapip.h> // For PlaReadRegistryIndirectStringValue
#include <sddl.h>
#include <assert.h>
#include <stdlib.h>
#include <pdhp.h>
// Disable 64-bit warnings in math.h
#if _MSC_VER >= 1200
#pragma warning(push)
#endif
#pragma warning ( disable : 4032 )
#include <math.h>
#if _MSC_VER >= 1200
#pragma warning(pop)
#endif
#include <strsafe.h>
#include "common.h"
// Time conversion constants
#define SECONDS_IN_DAY 86400
#define SECONDS_IN_HOUR 3600
#define SECONDS_IN_MINUTE 60
#define INDIRECT_STRING_LEN 9
LPCWSTR cszFormatIndirect = L"%s Indirect";
// Forward definitions - to be moved to pdhpla
PDH_FUNCTION
PlaReadRegistryIndirectStringValue (
HKEY hKey,
LPCWSTR cwszValueName,
LPWSTR *pszBuffer,
UINT* pcchBufLen
);
BOOL __stdcall
GetLocalFileTime (
LONGLONG *pFileTime
)
{
BOOL bResult;
SYSTEMTIME st;
assert ( NULL != pFileTime );
GetLocalTime ( &st );
//
// The only error for SystemTimeToFileTime is STATUS_INVALID_PARAMETER.
//
bResult = SystemTimeToFileTime (&st, (LPFILETIME)pFileTime);
return bResult;
}
BOOL __stdcall
MakeStringFromInfo (
PALERT_INFO_BLOCK pInfo,
LPWSTR szBuffer,
LPDWORD pcchBufferLength
)
{
HRESULT hr = S_OK;
BOOL bStatus = FALSE;
DWORD dwLenReqd;
size_t cchMaxLocalBufLen = 0;
size_t cchLocalBufLen = 0;
dwLenReqd = lstrlen ( pInfo->szCounterPath );
dwLenReqd += 1; // sizeof inequality char
dwLenReqd += SLQ_MAX_VALUE_LEN; // max size of value in chars
dwLenReqd += 1; // term NULL
if (dwLenReqd <= *pcchBufferLength) {
//
// Copy info block contents to a string buffer
//
cchMaxLocalBufLen = *pcchBufferLength;
hr = StringCchPrintf (
szBuffer,
cchMaxLocalBufLen,
L"%s%s%0.23g",
pInfo->szCounterPath,
(((pInfo->dwFlags & AIBF_OVER) == AIBF_OVER) ? L">" : L"<"),
pInfo->dLimit );
// Returned buffer length does not include final NULL character.
if ( SUCCEEDED (hr) ) {
hr = StringCchLength ( szBuffer, cchMaxLocalBufLen, &cchLocalBufLen );
if ( SUCCEEDED (hr) ) {
*pcchBufferLength = (DWORD)cchLocalBufLen + 1;
bStatus = TRUE;
}
}
}
return bStatus;
}
BOOL __stdcall
MakeInfoFromString (
LPCWSTR szBuffer,
PALERT_INFO_BLOCK pInfo,
LPDWORD pdwBufferSize
)
{
LPCWSTR szSrc;
LPWSTR szDst;
DWORD dwSizeUsed;
DWORD dwSizeLimit = *pdwBufferSize - sizeof(WCHAR);
dwSizeUsed = sizeof(ALERT_INFO_BLOCK);
szSrc = szBuffer;
szDst = (LPWSTR)&pInfo[1];
pInfo->szCounterPath = szDst;
// copy the string
while (dwSizeUsed < dwSizeLimit) {
if ((*szSrc == L'<') || (*szSrc == L'>')) break;
*szDst++ = *szSrc++;
dwSizeUsed += sizeof(WCHAR);
}
if (dwSizeUsed < dwSizeLimit) {
*szDst++ = 0; // NULL term the string
dwSizeUsed += sizeof(WCHAR);
}
pInfo->dwFlags = ((*szSrc == L'>') ? AIBF_OVER : AIBF_UNDER);
szSrc++;
//
// Get limit value
//
pInfo->dLimit = _wtof(szSrc);
// write size of buffer used
pInfo->dwSize = dwSizeUsed;
if (dwSizeUsed <= *pdwBufferSize) {
return TRUE;
}
else {
return FALSE;
}
}
void _stdcall
ReplaceBlanksWithUnderscores(
LPWSTR szName )
{
PdhiPlaFormatBlanksW( NULL, szName );
}
void _stdcall
TimeInfoToMilliseconds (
SLQ_TIME_INFO* pTimeInfo,
LONGLONG* pllmsecs)
{
assert ( SLQ_TT_DTYPE_UNITS == pTimeInfo->wDataType );
//
// Trusted caller, no check for NULL pointers.
//
TimeInfoToTics ( pTimeInfo, pllmsecs );
*pllmsecs /= FILETIME_TICS_PER_MILLISECOND;
return;
}
void _stdcall
TimeInfoToTics (
SLQ_TIME_INFO* pTimeInfo,
LONGLONG* pllTics)
{
assert ( SLQ_TT_DTYPE_UNITS == pTimeInfo->wDataType );
//
// Trusted caller, no check for NULL pointers.
//
switch (pTimeInfo->dwUnitType) {
case SLQ_TT_UTYPE_SECONDS:
*pllTics = pTimeInfo->dwValue;
break;
case SLQ_TT_UTYPE_MINUTES:
*pllTics = pTimeInfo->dwValue * SECONDS_IN_MINUTE;
break;
case SLQ_TT_UTYPE_HOURS:
*pllTics = pTimeInfo->dwValue * SECONDS_IN_HOUR;
break;
case SLQ_TT_UTYPE_DAYS:
*pllTics = pTimeInfo->dwValue * SECONDS_IN_DAY;
break;
default:
*pllTics = 0;
}
*pllTics *= FILETIME_TICS_PER_SECOND;
return;
}
PDH_FUNCTION
PlaReadRegistryIndirectStringValue (
HKEY hKey,
LPCWSTR pcszValueName,
LPWSTR* pszBuffer,
UINT* pcchBufLen
)
{
//
// Reads the indirect string value from under hKey and
// frees any existing buffer referenced by pszBuffer,
// then allocates a new buffer returning it with the
// string value read from the registry and the length
// of the buffer in characters (string length including
// NULL terminator)
//
PDH_STATUS pdhStatus = ERROR_SUCCESS;
HRESULT hr = NOERROR;
LPWSTR szNewStringBuffer = NULL;
UINT cchLocalBufLen = 0;
const UINT cchLocalBufLenGrow = MAX_PATH;
assert ( NULL != hKey );
assert ( NULL != pcszValueName );
assert ( NULL != pszBuffer );
assert ( NULL != pcchBufLen );
if ( NULL != hKey ) {
if ( ( NULL != pcszValueName )
&& ( NULL != pszBuffer )
&& ( NULL != pcchBufLen ) ) {
// find out the size of the required buffer
do {
/*
* allocate a large(r) buffer for the string
*/
if ( NULL != szNewStringBuffer ) {
G_FREE ( szNewStringBuffer );
szNewStringBuffer = NULL;
}
cchLocalBufLen += cchLocalBufLenGrow;
szNewStringBuffer = (LPWSTR)G_ALLOC( cchLocalBufLen*sizeof(WCHAR));
if ( NULL != szNewStringBuffer ) {
hr = SHLoadRegUIStringW (
hKey,
pcszValueName,
szNewStringBuffer,
cchLocalBufLen);
//
// Called method might not have set the terminating NULL.
//
szNewStringBuffer[cchLocalBufLen - 1] = L'\0';
/*
* If we filled up the buffer, we'll pessimistically assume that
* there's more data available. We'll loop around, grow the buffer,
* and try again.
*/
} else {
pdhStatus = ERROR_OUTOFMEMORY;
break;
}
} while ( (ULONG)lstrlen( szNewStringBuffer ) == cchLocalBufLen-1
&& SUCCEEDED ( hr ) );
if ( NULL != szNewStringBuffer ) {
if ( 0 == lstrlen (szNewStringBuffer) ) {
// nothing to read
pdhStatus = ERROR_NO_DATA;
} else {
if ( FAILED ( hr ) ) {
// Unable to read buffer
// Translate hr to pdhStatus
assert ( E_INVALIDARG != hr );
if ( E_OUTOFMEMORY == hr ) {
pdhStatus = ERROR_OUTOFMEMORY;
} else {
pdhStatus = ERROR_NO_DATA;
}
}
}
}
} else {
pdhStatus = ERROR_INVALID_PARAMETER;
}
} else {
// null key
pdhStatus = ERROR_BADKEY;
}
if ( ERROR_SUCCESS != pdhStatus ) {
if ( NULL != szNewStringBuffer ) {
G_FREE (szNewStringBuffer);
szNewStringBuffer = NULL;
cchLocalBufLen = 0;
}
} else {
// then delete the old buffer and replace it with
// the new one
if ( NULL != *pszBuffer ) {
G_FREE (*pszBuffer );
}
*pszBuffer = szNewStringBuffer;
*pcchBufLen = cchLocalBufLen;
}
return pdhStatus;
}
DWORD
SmReadRegistryIndirectStringValue (
HKEY hKey,
LPCWSTR szValueName,
LPCWSTR szDefault,
LPWSTR* pszBuffer,
UINT* pcchBufLen
)
//
// reads the string value "szValueName" from under hKey and
// frees any existing buffer referenced by pszBuffer,
// then allocates a new buffer returning it with the
// string value read from the registry and the size of the
// buffer in characters, including the terminating null.
//
{
DWORD dwStatus = ERROR_SUCCESS;
HRESULT hr = S_OK;
LPWSTR szNewStringBuffer = NULL;
UINT cchLocalBufLen = 0;
LPWSTR szIndirectValueName = NULL;
UINT uiValueNameLen = 0;
DWORD dwType;
DWORD dwBufferSize = 0;
if ( NULL == hKey ) {
assert ( FALSE );
dwStatus = ERROR_BADKEY;
}
else if ( ( NULL == pcchBufLen ) ||
( NULL == pszBuffer ) ||
( NULL == szValueName ) ) {
assert ( FALSE );
dwStatus = ERROR_INVALID_PARAMETER;
}
if (dwStatus == ERROR_SUCCESS) {
uiValueNameLen = lstrlen ( szValueName ) + INDIRECT_STRING_LEN + 1;
szIndirectValueName = G_ALLOC ( uiValueNameLen * sizeof(WCHAR) );
if ( NULL != szIndirectValueName ) {
StringCchPrintf (
szIndirectValueName,
uiValueNameLen,
cszFormatIndirect,
szValueName );
//
// PlaReadxxx guarantees NULL terminated return string.
//
dwStatus = PlaReadRegistryIndirectStringValue (
hKey,
szIndirectValueName,
&szNewStringBuffer,
&cchLocalBufLen );
if ( ERROR_SUCCESS == dwStatus) {
if ( 0 == lstrlen( szNewStringBuffer ) ) {
// nothing to read
dwStatus = ERROR_NO_DATA;
}
} // else dwStatus has error
G_FREE ( szIndirectValueName );
} else {
dwStatus = ERROR_NOT_ENOUGH_MEMORY;
}
if ( ERROR_NO_DATA == dwStatus ) {
//
// There might be something to read under the non-indirect field.
// Find out the size of the required buffer.
//
dwStatus = RegQueryValueExW (
hKey,
szValueName,
NULL,
&dwType,
NULL,
&dwBufferSize);
if (dwStatus == ERROR_SUCCESS) {
// NULL character size is 2 bytes
if (dwBufferSize > 2) {
// then there's something to read
szNewStringBuffer = (WCHAR*) G_ALLOC ( dwBufferSize );
if (szNewStringBuffer != NULL) {
dwType = 0;
dwStatus = RegQueryValueExW (
hKey,
szValueName,
NULL,
&dwType,
(LPBYTE)szNewStringBuffer,
&dwBufferSize);
cchLocalBufLen = dwBufferSize/sizeof(WCHAR);
szNewStringBuffer[cchLocalBufLen - 1] = L'\0';
cchLocalBufLen = lstrlenW ( szNewStringBuffer ) + 1;
if ( 1 == cchLocalBufLen ) {
dwStatus = ERROR_NO_DATA;
}
} else {
// Todo: Report event for this case.
dwStatus = ERROR_OUTOFMEMORY;
}
} else {
// nothing to read
dwStatus = ERROR_NO_DATA;
}
}
}
if ( ERROR_SUCCESS != dwStatus ) {
if ( NULL != szNewStringBuffer ) {
G_FREE ( szNewStringBuffer );
szNewStringBuffer = NULL;
cchLocalBufLen = 0;
}
// apply default
if ( NULL != szDefault ) {
cchLocalBufLen = lstrlen(szDefault) + 1;
if ( 1 < cchLocalBufLen ) {
szNewStringBuffer = (WCHAR*) G_ALLOC ( cchLocalBufLen * sizeof (WCHAR) );
if ( NULL != szNewStringBuffer ) {
hr = StringCchCopy ( szNewStringBuffer, cchLocalBufLen, szDefault );
dwStatus = HRESULT_CODE( hr );
} else {
dwStatus = ERROR_OUTOFMEMORY;
}
}
} // else no default so no data returned
}
if ( ERROR_SUCCESS == dwStatus ) {
// Delete the old buffer and replace it with
// the new one.
if ( NULL != *pszBuffer ) {
G_FREE (*pszBuffer );
}
*pszBuffer = szNewStringBuffer;
*pcchBufLen = cchLocalBufLen;
} else {
//
// If error then delete the buffer
// Leave the original buffer pointer as is.
//
if ( NULL != szNewStringBuffer ) {
G_FREE ( szNewStringBuffer );
*pcchBufLen = 0;
}
}
}
return dwStatus;
}
DWORD
RegisterCurrentFile( HKEY hkeyQuery, LPWSTR szFileName, DWORD dwSubIndex )
{
DWORD dwStatus = ERROR_SUCCESS;
LPWSTR szLocalFileName = NULL;
BOOL bLocalAlloc = FALSE;
DWORD dwSize = 0;
size_t cchLocalBufLen = 0;
if( szFileName != NULL ){
if( dwSubIndex == (-1) ){
//
// The only time this will get called with a (-1) is the first time
// trace is building the file name.
//
dwSize = (DWORD)((BYTE*)&szFileName[wcslen( szFileName )] -
(BYTE*)&szFileName[0]);
// 32 is the max size of all formatting and extention characters.
dwSize += 32 * sizeof(WCHAR);
szLocalFileName = (LPWSTR)G_ALLOC( dwSize );
if( NULL != szLocalFileName ) {
bLocalAlloc = TRUE;
cchLocalBufLen = dwSize/(sizeof(WCHAR));
//
// No file name length restriction.
//
StringCchPrintf (
szLocalFileName,
cchLocalBufLen,
szFileName,
1 );
} else {
dwStatus = ERROR_OUTOFMEMORY;
}
} else {
szLocalFileName = szFileName;
//
// No file name length restriction.
//
if ( SUCCEEDED ( StringCchLength ( szLocalFileName, STRSAFE_MAX_CCH, &cchLocalBufLen ) ) ) {
dwSize = (cchLocalBufLen + 1) * sizeof(WCHAR);
} else {
dwStatus = ERROR_INVALID_NAME;
}
}
// dwSize = (DWORD)((BYTE*)&szLocalFileName[wcslen( szLocalFileName )] -
// (BYTE*)&szLocalFileName[0]);
if ( ERROR_SUCCESS == dwStatus ) {
dwStatus = RegSetValueExW (
hkeyQuery,
L"Current Log File Name",
0L,
REG_SZ,
(CONST BYTE *)szLocalFileName,
dwSize );
}
} else {
dwStatus = ERROR_INVALID_PARAMETER;
}
if( bLocalAlloc && NULL != szLocalFileName ){
G_FREE( szLocalFileName );
}
return dwStatus;
}
ULONG
__stdcall
ahextoi( LPWSTR s )
{
long len;
ULONG num, base, hex;
len = (long) wcslen(s);
if (len == 0) {
return 0;
}
hex = 0;
base = 1;
num = 0;
while (-- len >= 0) {
if (s[len] >= L'0' && s[len] <= L'9'){
num = s[len] - L'0';
}else if (s[len] >= L'a' && s[len] <= L'f'){
num = (s[len] - L'a') + 10;
}else if (s[len] >= L'A' && s[len] <= L'F'){
num = (s[len] - L'A') + 10;
}else if( s[len] == L'x' || s[len] == L'X'){
break;
}else{
continue;
}
hex += num * base;
base = base * 16;
}
return hex;
}
BOOL
PerfCreateDirectory(LPWSTR szDirectory)
/*++
Routine Description:
The function create a SECURITY_ATTRIBUTES structure used by
"Performance Logs and Alerts" when creating a directory to
hold log files.
The security policy is as following:
Admin - Full control
System - Full control
Performance Logging -
Performance Monitoring - Read & Execute, List folder contents
Network
Arguments:
None
Return Value:
Return the newly created SECURITY_ATTRIBUTES if success,
otherwise return NULL
--*/
{
SECURITY_ATTRIBUTES sa;
WCHAR* szSD = L"D:"
L"(A;OICI;GA;;;SY)(A;OICI;GA;;;BA)"
L"(A;OICI;FRFWFXSDRC;;;NS)"
L"(A;OICI;FRFWFXSDRC;;;LU)"
L"(A;OICI;FRFX;;;MU)";
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = FALSE;
if (ConvertStringSecurityDescriptorToSecurityDescriptor(
szSD,
SDDL_REVISION_1,
&(sa.lpSecurityDescriptor),
NULL)) {
if (CreateDirectory(szDirectory, &sa)) {
return TRUE;
}
}
return FALSE;
}