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.
 
 
 
 
 
 

447 lines
11 KiB

//*************************************************************
//
// Debugging functions
//
// Microsoft Confidential
// Copyright (c) Microsoft Corporation 1995
// All rights reserved
//
//*************************************************************
#include "common.hxx"
HINSTANCE ghDllInstance = 0;
//
// Global Variable containing the debugging level. The debug level can be
// modified by both the debug init routine and the event logging init
// routine. Debugging can be enabled even on retail systems through
// registry settings.
//
DWORD gDebugLevel = DL_NONE;
DWORD gDebugBreak = 0;
LOADSTRINGW * pfnLoadStringW = 0;
//
// Debug strings
//
const WCHAR cwszAppMgmt[] = L"APPMGMT (%x.%x) %02d:%02d:%02d:%03d ";
const WCHAR cwszLogTime[] = L"%02d-%02d %02d:%02d:%02d:%03d ";
const WCHAR cwszLogfile[] = L"%SystemRoot%\\Debug\\UserMode\\appmgmt.log";
const WCHAR cwszOldLogfile[] = L"%SystemRoot%\\Debug\\UserMode\\appmgmt.bak";
const WCHAR cwszCRLF[] = L"\r\n";
const char cszCRLF[] = "\r\n";
//*************************************************************
//
// InitDebugSupport()
//
// Sets the debugging level.
// Also checks the registry for a debugging level.
//
//*************************************************************
void InitDebugSupport( DWORD DebugMode )
{
HKEY hKey;
DWORD Size;
DWORD Type;
BOOL bVerbose;
DWORD Status;
BOOL bStatus;
#if DBG
gDebugLevel = DL_NORMAL;
#else
gDebugLevel = DL_NONE;
#endif
gDebugBreak = 0;
Status = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
DIAGNOSTICS_KEY,
0,
KEY_READ,
&hKey );
bVerbose = FALSE;
if ( ERROR_SUCCESS == Status )
{
Size = sizeof(bVerbose);
Status = RegQueryValueEx(
hKey,
DIAGNOSTICS_POLICY_VALUE,
NULL,
&Type,
(LPBYTE) &bVerbose,
&Size );
if ( (ERROR_SUCCESS == Status) && (Type != REG_DWORD) )
bVerbose = FALSE;
Size = sizeof(gDebugLevel);
Status = RegQueryValueEx(
hKey,
DEBUG_KEY_NAME,
NULL,
NULL,
(LPBYTE) &gDebugLevel,
&Size );
if (ERROR_SUCCESS != Status)
{
RegCloseKey(hKey);
return;
}
Size = sizeof(gDebugBreak);
Status = RegQueryValueEx(
hKey,
DEBUGBREAK_KEY_NAME,
NULL,
NULL,
(LPBYTE) &gDebugBreak,
&Size );
RegCloseKey(hKey);
if (ERROR_SUCCESS != Status)
{
return;
}
}
if ( bVerbose )
gDebugLevel |= DL_VERBOSE | DL_EVENTLOG;
if ( gDebugLevel & DL_LOGFILE )
{
WCHAR wszLogFile[MAX_PATH];
WCHAR wszOldLogFile[MAX_PATH];
WIN32_FILE_ATTRIBUTE_DATA FileData;
BOOL bStatusLog;
bStatusLog = GetDebugLogFileName( wszLogFile, sizeof( wszLogFile ) / sizeof( WCHAR ) );
if ( ! bStatusLog )
{
return;
}
if ( DebugMode != DEBUGMODE_POLICY )
return;
bStatusLog = GetFileAttributesEx( wszLogFile, GetFileExInfoStandard, &FileData );
if ( ! bStatusLog )
return;
//
// If the existing log file is more than 50K then we will rename it to a backup
// copy to prevent huge bloating, otherwise we continue to use it.
//
if ( FileData.nFileSizeLow < (50 * 1024) )
return;
Status = ExpandEnvironmentStrings( cwszOldLogfile, wszOldLogFile, sizeof(wszOldLogFile) / sizeof(WCHAR) );
if ( (0 == Status) || (Status > ( sizeof(wszOldLogFile) / sizeof(WCHAR) )) )
return;
DeleteFile( wszOldLogFile );
MoveFile( wszLogFile, wszOldLogFile );
}
}
BOOL DebugLevelOn( DWORD mask )
{
BOOL bOutput = FALSE;
if ( gDebugLevel & DL_VERBOSE )
bOutput = TRUE;
else if ( gDebugLevel & DL_NORMAL )
bOutput = ! (mask & DM_VERBOSE);
#if DBG
else // DL_NONE
bOutput = (mask & DM_ASSERT);
#endif
return bOutput;
}
//*************************************************************
//
// _DebugMsg()
//
// Displays debug messages based on the debug level
// and type of debug message.
//
// Parameters :
// mask - debug message type
// MsgID - debug message id from resource file
// ... - variable number of parameters
//
//*************************************************************
void _DebugMsg(DWORD mask, DWORD MsgID, ...)
{
if ( ! DebugLevelOn( mask ) )
return;
BOOL bEventLogOK;
WCHAR wszDebugTitle[64];
WCHAR wszDebugBuffer[2048]; // Hopefully this will be big enough!
WCHAR wszMsg[MAX_PATH];
va_list VAList;
SYSTEMTIME systime;
bEventLogOK = ! (mask & DM_NO_EVENTLOG);
if ( ! LoadLoadString() )
return;
va_start(VAList, MsgID);
if ( ! ghDllInstance )
ghDllInstance = LoadLibrary( L"appmgmts.dll" );
//
// Event log message ids are in the 100s to 400s, verbose strings are in the
// 1000s to 3000s. For event log messages we must call FormatMessage. For
// other verbose debug output, we use LoadString to get the string resource.
//
if ( MsgID >= 1000 )
{
if ( ! (*pfnLoadStringW)( ghDllInstance, MsgID, wszMsg, MAX_PATH) )
return;
(void) StringCchVPrintf(wszDebugBuffer, sizeof(wszDebugBuffer)/sizeof(wszDebugBuffer[0]), wszMsg, VAList);
}
else
{
DWORD CharsWritten;
CharsWritten = FormatMessage(
FORMAT_MESSAGE_FROM_HMODULE,
ghDllInstance,
MsgID,
0,
wszDebugBuffer,
sizeof(wszDebugBuffer) / sizeof(WCHAR),
&VAList );
if ( 0 == CharsWritten )
return;
}
va_end(VAList);
GetLocalTime( &systime );
(void) StringCchPrintf( wszDebugTitle,
sizeof(wszDebugTitle)/sizeof(wszDebugTitle[0]),
cwszAppMgmt,
GetCurrentProcessId(),
GetCurrentThreadId(),
systime.wHour,
systime.wMinute,
systime.wSecond,
systime.wMilliseconds);
if ( ! (gDebugLevel & DL_NODBGOUT) )
{
OutputDebugString( wszDebugTitle );
OutputDebugString( wszDebugBuffer );
OutputDebugString( cwszCRLF );
}
if ( gDebugLevel & DL_LOGFILE )
{
WCHAR* wszLogFile;
HANDLE hFile;
wszLogFile = new WCHAR[ MAX_PATH ];
if ( wszLogFile && GetDebugLogFileName( wszLogFile, MAX_PATH ) )
{
hFile = OpenUnicodeLogFile(wszLogFile);
if ( hFile != INVALID_HANDLE_VALUE )
{
if ( SetFilePointer (hFile, 0, NULL, FILE_END) != 0xFFFFFFFF )
{
DWORD Size;
WriteFile(
hFile,
(LPCVOID) wszDebugBuffer,
lstrlen(wszDebugBuffer) * sizeof(WCHAR),
&Size,
NULL );
WriteFile(
hFile,
(LPCVOID) cwszCRLF,
lstrlen(cwszCRLF) * sizeof(WCHAR),
&Size,
NULL );
}
}
CloseHandle (hFile);
delete [] wszLogFile;
}
}
if ( bEventLogOK && (gDebugLevel & DL_EVENTLOG) )
((CEventsBase *)gpEvents)->Report( EVENT_APPMGMT_VERBOSE, FALSE, 1, wszDebugBuffer );
#if DBG
if ( mask & DM_ASSERT )
DebugBreak();
#endif
}
void LogTime()
{
if ( ! (gDebugLevel & DL_LOGFILE) )
return;
WCHAR wszDebugBuffer[64];
SYSTEMTIME systime;
HANDLE hFile;
WCHAR wszLogFile[MAX_PATH];
BOOL bStatus;
bStatus = GetDebugLogFileName( wszLogFile, sizeof( wszLogFile ) / sizeof( WCHAR ) );
if ( ! bStatus )
{
return;
}
GetLocalTime( &systime );
(void) StringCchPrintf( wszDebugBuffer,
sizeof(wszDebugBuffer)/sizeof(wszDebugBuffer[0]),
cwszLogTime,
systime.wMonth,
systime.wDay,
systime.wHour,
systime.wMinute,
systime.wSecond,
systime.wMilliseconds);
hFile = OpenUnicodeLogFile(wszLogFile);
if ( INVALID_HANDLE_VALUE == hFile )
return;
if ( SetFilePointer (hFile, 0, NULL, FILE_END) != 0xFFFFFFFF )
{
DWORD Size;
WriteFile(
hFile,
(LPCVOID) wszDebugBuffer,
lstrlen(wszDebugBuffer) * sizeof(WCHAR),
&Size,
NULL );
WriteFile(
hFile,
(LPCVOID) cwszCRLF,
lstrlen(cwszCRLF) * sizeof(WCHAR),
&Size,
NULL );
}
CloseHandle (hFile);
}
HANDLE
OpenUnicodeLogFile (LPCTSTR lpszFilePath)
{
HANDLE hFile;
DWORD Status;
DWORD dwWritten;
Status = ERROR_SUCCESS;
hFile = CreateFile(
lpszFilePath,
FILE_WRITE_DATA | FILE_APPEND_DATA,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if ( INVALID_HANDLE_VALUE == hFile )
{
Status = GetLastError();
}
if ( ERROR_FILE_NOT_FOUND == Status )
{
//
// The file doesn't exist, so we'll try to create it
// with the byte order marker
//
hFile = CreateFile(
lpszFilePath,
FILE_WRITE_DATA | FILE_APPEND_DATA,
FILE_SHARE_READ,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if ( INVALID_HANDLE_VALUE != hFile )
{
BOOL bWritten;
//
// Add the unicode byte order marker to the beginning of the file
// so that APIs know for sure that it is a unicode file.
//
bWritten = WriteFile(
hFile,
L"\xfeff\r\n",
4 * sizeof(WCHAR),
&dwWritten,
NULL);
if ( ! bWritten )
{
CloseHandle( hFile );
}
}
}
return hFile;
}
BOOL
GetDebugLogFileName( WCHAR* wszLogFile, LONG cchLogFile )
{
LONG Status;
Status = ExpandEnvironmentStrings( cwszLogfile, wszLogFile, MAX_PATH );
if ( (0 == Status) || (Status > cchLogFile) )
{
return FALSE;
}
return TRUE;
}