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.
 
 
 
 
 
 

750 lines
19 KiB

/*++
Copyright (C) 1996-2001 Microsoft Corporation
Module Name:
WBEMUTIL.CPP
Abstract:
General utility functions.
History:
a-raymcc 17-Apr-96 Created.
--*/
#include "precomp.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <stdio.h>
#include <wbemutil.h>
#include <corex.h>
#include "reg.h"
#include "sync.h"
#include <statsync.h>
#include <ARRTEMPL.H>
static BOOL g_bMachineDown = FALSE;
BOOL WbemGetMachineShutdown()
{
return g_bMachineDown;
};
BOOL WbemSetMachineShutdown(BOOL bVal)
{
BOOL bTmp = g_bMachineDown;
g_bMachineDown = bVal;
return bTmp;
}
class AutoRevert
{
private:
HANDLE oldToken_;
BOOL SetThrTokResult_;
bool self_;
public:
AutoRevert();
~AutoRevert();
void dismiss();
bool self(){ return self_;}
};
AutoRevert::AutoRevert():oldToken_(NULL),self_(true),SetThrTokResult_(FALSE)
{
if (OpenThreadToken(GetCurrentThread(),TOKEN_IMPERSONATE,TRUE,&oldToken_))
{
RevertToSelf();
}
else
{
if (GetLastError() != ERROR_NO_TOKEN)
self_ = false;
};
}
AutoRevert::~AutoRevert()
{
dismiss();
}
void AutoRevert::dismiss()
{
if (oldToken_)
{
// if the handle has been opened with TOKEN_IMPERSONATE
// and if nobody has touched the SD for the ETHREAD object, this will work
SetThrTokResult_ = SetThreadToken(NULL,oldToken_);
CloseHandle(oldToken_);
}
}
//***************************************************************************
//
// BOOL isunialpha(wchar_t c)
//
// Used to test if a wide character is a unicode character or underscore.
//
// Parameters:
// c = The character being tested.
// Return value:
// TRUE if OK.
//
//***************************************************************************
BOOL POLARITY isunialpha(wchar_t c)
{
if(c == 0x5f || (0x41 <= c && c <= 0x5a) ||
(0x61 <= c && c <= 0x7a) || (0x80 <= c && c <= 0xfffd))
return TRUE;
else
return FALSE;
}
//***************************************************************************
//
// BOOL isunialphanum(char_t c)
//
// Used to test if a wide character is string suitable for identifiers.
//
// Parameters:
// pwc = The character being tested.
// Return value:
// TRUE if OK.
//
//***************************************************************************
BOOL POLARITY isunialphanum(wchar_t c)
{
if(isunialpha(c))
return TRUE;
else
return wbem_iswdigit(c);
}
BOOL IsValidElementName( LPCWSTR wszName, DWORD MaxAllow )
{
if(wszName[0] == 0)
return FALSE;
if(wszName[0] == '_')
return FALSE;
const WCHAR* pwc = wszName;
LPCWSTR pTail = wszName+MaxAllow+1;
// Check the first letter
// ======================
// this is for compatibility with IWbemPathParser
if (iswspace(pwc[0]))
return FALSE;
if(!isunialpha(*pwc))
return FALSE;
pwc++;
// Check the rest
// ==============
while(*pwc && (pwc < pTail))
{
if(!isunialphanum(*pwc))
return FALSE;
pwc++;
}
if ( pwc == pTail ) return FALSE;
if (iswspace(*(pwc-1)))
return FALSE;
if(pwc[-1] == '_')
return FALSE;
return TRUE;
}
// Can't use overloading and/or default parameters because
// "C" files use these guys. No, I'm not happy about
// this!
BOOL IsValidElementName2( LPCWSTR wszName,DWORD MaxAllow, BOOL bAllowUnderscore )
{
if(wszName[0] == 0)
return FALSE;
if(!bAllowUnderscore && wszName[0] == '_')
return FALSE;
const WCHAR* pwc = wszName;
LPCWSTR pTail = wszName+MaxAllow+1;
// Check the first letter
// ======================
// this is for compatibility with IWbemPathParser
if (iswspace(pwc[0]))
return FALSE;
if(!isunialpha(*pwc))
return FALSE;
pwc++;
// Check the rest
// ==============
while(*pwc && (pwc < pTail))
{
if(!isunialphanum(*pwc))
return FALSE;
pwc++;
}
if ( pwc == pTail ) return FALSE;
if (iswspace(*(pwc-1)))
return FALSE;
if(!bAllowUnderscore && pwc[-1] == '_')
return FALSE;
return TRUE;
}
BLOB POLARITY BlobCopy(const BLOB *pSrc)
{
BLOB Blob;
BYTE *p = new BYTE[pSrc->cbSize];
// Check for allocation failure
if ( NULL == p )
{
throw CX_MemoryException();
}
Blob.cbSize = pSrc->cbSize;
Blob.pBlobData = p;
memcpy(p, pSrc->pBlobData, Blob.cbSize);
return Blob;
}
void POLARITY BlobAssign(BLOB *pBlob, LPVOID pBytes, DWORD dwCount, BOOL bAcquire)
{
BYTE *pSrc = 0;
if (bAcquire)
pSrc = (BYTE *) pBytes;
else {
pSrc = new BYTE[dwCount];
// Check for allocation failure
if ( NULL == pSrc )
{
throw CX_MemoryException();
}
memcpy(pSrc, pBytes, dwCount);
}
pBlob->cbSize = dwCount;
pBlob->pBlobData = pSrc;
}
void POLARITY BlobClear(BLOB *pSrc)
{
if (pSrc->pBlobData)
delete pSrc->pBlobData;
pSrc->pBlobData = 0;
pSrc->cbSize = 0;
}
class __Trace
{
struct ARMutex
{
HANDLE h_;
ARMutex(HANDLE h):h_(h){}
~ARMutex(){ ReleaseMutex(h_);}
};
public:
enum { REG_CHECK_INTERVAL =1000 * 60 };
DWORD m_dwLogging;
DWORD m_dwMaxLogSize;
DWORD m_dwTimeLastRegCheck;
wchar_t m_szLoggingDirectory[MAX_PATH+1];
char m_szTraceBuffer[2048];
char m_szTraceBuffer2[4096];
wchar_t m_szBackupFileName[MAX_PATH+1];
wchar_t m_szLogFileName[MAX_PATH+1];
static const wchar_t *m_szLogFileNames[];
BOOL LoggingLevelEnabled(DWORD dwLevel);
DWORD GetLoggingLevel();
int Trace(char caller, const char *fmt, va_list &argptr);
__Trace();
~__Trace();
HANDLE get_logfile(const wchar_t * name );
private:
void ReadLogDirectory();
void ReReadRegistry();
HANDLE buffers_lock_;
};
const wchar_t * __Trace::m_szLogFileNames[] =
{ FILENAME_PREFIX_CORE TEXT(".log"),
FILENAME_PREFIX_EXE TEXT(".log"),
FILENAME_PREFIX_ESS TEXT(".log"),
FILENAME_PREFIX_CLI_MARSH TEXT(".log"),
FILENAME_PREFIX_SERV_MARSH TEXT(".log"),
FILENAME_PREFIX_QUERY TEXT(".log"),
FILENAME_PROFIX_MOFCOMP TEXT(".log"),
FILENAME_PROFIX_EVENTLOG TEXT(".log"),
FILENAME_PROFIX_WBEMDISP TEXT(".log"),
FILENAME_PROFIX_STDPROV TEXT(".log"),
FILENAME_PROFIX_WMIPROV TEXT(".log"),
FILENAME_PROFIX_WMIOLEDB TEXT(".log"),
FILENAME_PREFIX_WMIADAP TEXT(".log"),
FILENAME_PREFIX_REPDRV TEXT(".log"),
FILENAME_PREFIX_PROVSS TEXT(".log"),
FILENAME_PREFIX_EVTPROV TEXT(".log"),
FILENAME_PREFIX_VIEWPROV TEXT(".log"),
FILENAME_PREFIX_DSPROV TEXT(".log"),
FILENAME_PREFIX_SNMPPROV TEXT(".log"),
FILENAME_PREFIX_PROVTHRD TEXT(".log")
};
__Trace __g_traceInfo;
__Trace::__Trace()
: m_dwLogging(1),
m_dwMaxLogSize(65536),
m_dwTimeLastRegCheck(GetTickCount())
{
buffers_lock_ = CreateMutexA(0,0,0);
if (NULL == buffers_lock_)
{
CStaticCritSec::SetFailure();
return;
}
ReadLogDirectory();
ReReadRegistry();
}
__Trace::~__Trace()
{
if (buffers_lock_) CloseHandle(buffers_lock_);
};
void __Trace::ReReadRegistry()
{
Registry r(WBEM_REG_WINMGMT, KEY_READ);
//Get the logging level
if (r.GetDWORDStr(TEXT("Logging"), &m_dwLogging) != Registry::no_error)
{
m_dwLogging = 1;
r.SetDWORDStr(TEXT("Logging"), m_dwLogging);
}
//Get the maximum log file size
if (r.GetDWORDStr(TEXT("Log File Max Size"), &m_dwMaxLogSize) != Registry::no_error)
{
m_dwMaxLogSize = 65536;
r.SetDWORDStr(TEXT("Log File Max Size"), m_dwMaxLogSize);
}
}
void __Trace::ReadLogDirectory()
{
Registry r(WBEM_REG_WINMGMT);
//Retrieve the logging directory
TCHAR *tmpStr = 0;
if ((r.GetStr(TEXT("Logging Directory"), &tmpStr) == Registry::failed) ||
(lstrlen(tmpStr) > (MAX_PATH)))
{
delete [] tmpStr; //Just in case someone was trying for a buffer overrun with a long path in the registry...
if (GetSystemDirectory(m_szLoggingDirectory, MAX_PATH+1) == 0)
{
StringCchCopy(m_szLoggingDirectory, MAX_PATH+1, TEXT("c:\\"));
}
else
{
StringCchCat(m_szLoggingDirectory, MAX_PATH+1, TEXT("\\WBEM\\Logs\\"));
r.SetStr(TEXT("Logging Directory"), m_szLoggingDirectory);
}
}
else
{
StringCchCopy(m_szLoggingDirectory, MAX_PATH+1, tmpStr);
//make sure there is a '\' on the end of the path...
if (m_szLoggingDirectory[lstrlen(m_szLoggingDirectory) - 1] != '\\')
{
StringCchCat(m_szLoggingDirectory, MAX_PATH+1,TEXT("\\"));
r.SetStr(TEXT("Logging Directory"), m_szLoggingDirectory);
}
delete [] tmpStr;
}
//Make sure directory exists
WbemCreateDirectory(m_szLoggingDirectory);
}
HANDLE __Trace::get_logfile(const wchar_t * file_name )
{
AutoRevert revert;
if (revert.self()==false)
return INVALID_HANDLE_VALUE;
HANDLE hTraceFile = INVALID_HANDLE_VALUE;
bool bDoneWrite = false;
//Keep trying to open the file
while (!bDoneWrite)
{
while (hTraceFile == INVALID_HANDLE_VALUE)
{
if (WaitForSingleObject(buffers_lock_,-1)==WAIT_FAILED)
return INVALID_HANDLE_VALUE;
StringCchCopy(m_szLogFileName, MAX_PATH+1, m_szLoggingDirectory);;
StringCchCat(m_szLogFileName, MAX_PATH+1, file_name);
hTraceFile = ::CreateFileW( m_szLogFileName,
GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_DELETE,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL|FILE_ATTRIBUTE_NOT_CONTENT_INDEXED,
NULL );
if ( hTraceFile == INVALID_HANDLE_VALUE )
{
ReleaseMutex(buffers_lock_);
if (GetLastError() == ERROR_SHARING_VIOLATION)
{
Sleep(20);
}
else
{
return INVALID_HANDLE_VALUE;
}
}
}
ARMutex arm(buffers_lock_);
//
// Now move the file pointer to the end of the file
//
LARGE_INTEGER liSize;
liSize.QuadPart = 0;
if ( !::SetFilePointerEx( hTraceFile,
liSize,
NULL,
FILE_END ) )
{
CloseHandle( hTraceFile );
return INVALID_HANDLE_VALUE;
}
bDoneWrite = true;
//Rename file if file length is exceeded
LARGE_INTEGER liMaxSize;
liMaxSize.QuadPart = m_dwMaxLogSize;
if (GetFileSizeEx(hTraceFile, &liSize))
{
if (liSize.QuadPart > liMaxSize.QuadPart)
{
StringCchCopy(m_szBackupFileName, MAX_PATH+1, m_szLogFileName);
StringCchCopy(m_szBackupFileName + lstrlen(m_szBackupFileName) - 3, MAX_PATH+1, TEXT("lo_"));
DeleteFile(m_szBackupFileName);
if (MoveFile(m_szLogFileName, m_szBackupFileName) == 0)
{
if ( liSize.QuadPart < liMaxSize.QuadPart*2)
return hTraceFile;
else
{
CloseHandle(hTraceFile);
return INVALID_HANDLE_VALUE;
};
}
//Need to re-open the file!
bDoneWrite = false;
CloseHandle(hTraceFile);
hTraceFile = INVALID_HANDLE_VALUE;
}
}
}
return hTraceFile;
};
int __Trace::Trace(char caller, const char *fmt, va_list &argptr)
{
HANDLE hTraceFile = INVALID_HANDLE_VALUE;
try
{
if (caller >= (sizeof(m_szLogFileNames) / sizeof(char)))
caller = 0;
hTraceFile = get_logfile(m_szLogFileNames[caller]);
if (hTraceFile == INVALID_HANDLE_VALUE)
return 0;
CCloseMe ch(hTraceFile);
if (WaitForSingleObject(buffers_lock_,-1)==WAIT_FAILED)
return 0;
ARMutex arm(buffers_lock_);
// Get time.
// =========
char timebuf[64];
time_t now = time(0);
struct tm *local = localtime(&now);
if(local)
{
StringCchCopyA(timebuf, 64, asctime(local));
timebuf[strlen(timebuf) - 1] = 0; // O
}
else
{
StringCchCopyA(timebuf, 64, "??");
}
//Put time in start of log
StringCchPrintfA(m_szTraceBuffer, 2048, "(%s.%d) : ", timebuf, GetTickCount());
//Format the user string
int nLen = strlen(m_szTraceBuffer);
StringCchVPrintfA(m_szTraceBuffer + nLen, 2048 - nLen, fmt, argptr);
//Unfortunately, lots of people only put \n in the string, so we need to convert the string...
int nLen2 = 0;
char *p = m_szTraceBuffer;
char *p2 = m_szTraceBuffer2;
for (; *p; p++,p2++,nLen2++)
{
if (*p == '\n')
{
*p2 = '\r';
p2++;
nLen2++;
*p2 = '\n';
}
else
{
*p2 = *p;
}
}
*p2 = '\0';
//
// Write to file :
//
DWORD dwWritten;
::WriteFile( hTraceFile, m_szTraceBuffer2, nLen2, &dwWritten, NULL);
return 1;
}
catch(...)
{
return 0;
}
}
BOOL __Trace::LoggingLevelEnabled(DWORD dwLevel)
{
if (!WbemGetMachineShutdown()) // prevent touching registry during machine shutdown
{
DWORD dwCurTicks = GetTickCount();
if (dwCurTicks - m_dwTimeLastRegCheck > REG_CHECK_INTERVAL)
{
ReReadRegistry();
m_dwTimeLastRegCheck = dwCurTicks;
}
}
if ((dwLevel > m_dwLogging))
return FALSE;
else
return TRUE;
}
DWORD __Trace::GetLoggingLevel()
{
if (!WbemGetMachineShutdown()) // prevent touching registry during machine shutdown
{
DWORD dwCurTicks = GetTickCount();
if (dwCurTicks - m_dwTimeLastRegCheck > REG_CHECK_INTERVAL)
{
ReReadRegistry();
m_dwTimeLastRegCheck = dwCurTicks;
}
}
return m_dwLogging;
};
DWORD GetLoggingLevelEnabled()
{
return __g_traceInfo.GetLoggingLevel();
}
BOOL LoggingLevelEnabled(DWORD dwLevel)
{
return __g_traceInfo.LoggingLevelEnabled(dwLevel);
}
int ErrorTrace(char caller, const char *fmt, ...)
{
if (__g_traceInfo.LoggingLevelEnabled(1))
{
va_list argptr;
va_start(argptr, fmt);
__g_traceInfo.Trace(caller, fmt, argptr);
va_end(argptr);
return 1;
}
else
return 0;
}
int DebugTrace(char caller, const char *fmt, ...)
{
if (__g_traceInfo.LoggingLevelEnabled(2))
{
va_list argptr;
va_start(argptr, fmt);
__g_traceInfo.Trace(caller, fmt, argptr);
va_end(argptr);
return 1;
}
else
return 0;
}
int CriticalFailADAPTrace(const char *string)
//
// The intention of this trace function is to be used in situations where catastrophic events
// may have occured where the state of the heap may be in question. The function uses only
// stack variables. Note that if a heap corruption has occured there is a small chance that
// the global object __g_traceInfo may have been damaged.
{
return ErrorTrace(LOG_WMIADAP, "**CRITICAL FAILURE** %s", string);
}
// Helper for quick wchar to multibyte conversions. Caller muts
// free the returned pointer
BOOL POLARITY AllocWCHARToMBS( WCHAR* pWstr, char** ppStr )
{
if ( NULL == pWstr )
{
return FALSE;
}
// Get the length allocate space and copy the string
long lLen = wcstombs(NULL, pWstr, 0);
*ppStr = new char[lLen + 1];
if (*ppStr == 0)
return FALSE;
wcstombs( *ppStr, pWstr, lLen + 1 );
return TRUE;
}
LPTSTR GetWbemWorkDir( void )
{
LPTSTR pWorkDir = NULL;
Registry r1(WBEM_REG_WINMGMT);
if (r1.GetStr(TEXT("Working Directory"), &pWorkDir))
{
size_t bufferLength = MAX_PATH + 1 + lstrlen(TEXT("\\WBEM"));
wmilib::auto_buffer<TCHAR> p(new TCHAR[bufferLength]);
if (NULL == p.get()) return NULL;
DWORD dwRet = GetSystemDirectory(p.get(), MAX_PATH + 1);
if (0 == dwRet) return NULL;
if (dwRet > MAX_PATH)
{
bufferLength = 4 + 1 + dwRet;
p.reset(new TCHAR[bufferLength]);
if (NULL == p.get()) return NULL;
if (0 == GetSystemDirectory(p.get(), dwRet + 1)) return NULL;
}
StringCchCat(p.get(), bufferLength, TEXT("\\WBEM"));
pWorkDir = p.release();
}
return pWorkDir;
}
LPTSTR GetWMIADAPCmdLine( int nExtra )
{
LPTSTR pWorkDir = GetWbemWorkDir();
CVectorDeleteMe<TCHAR> vdm( pWorkDir );
if ( NULL == pWorkDir )
{
return NULL;
}
// Buffer should be big enough for two quotes, WMIADAP.EXE and cmdline switches
size_t bufferLength = lstrlen( pWorkDir ) + lstrlen(TEXT("\\\\?\\\\WMIADAP.EXE")) + nExtra + 1;
LPTSTR pCmdLine = new TCHAR[bufferLength];
if ( NULL == pCmdLine )
{
return NULL;
}
StringCchPrintf( pCmdLine,bufferLength, TEXT("\\\\?\\%s\\WMIADAP.EXE"), pWorkDir );
return pCmdLine;
}
BOOL IsNtSetupRunning()
{
HKEY hKey;
long lRes = RegOpenKeyExW(HKEY_LOCAL_MACHINE,L"system\\Setup",0, KEY_READ, &hKey);
if(ERROR_SUCCESS != lRes) return FALSE;
DWORD dwSetupRunning;
DWORD dwLen = sizeof(DWORD);
lRes = RegQueryValueExW(hKey, L"SystemSetupInProgress", NULL, NULL,(LPBYTE)&dwSetupRunning, &dwLen);
RegCloseKey(hKey);
if(lRes == ERROR_SUCCESS && (dwSetupRunning == 1))
{
return TRUE;
}
return FALSE;
}