293 lines
7.4 KiB
C++
293 lines
7.4 KiB
C++
|
//*************************************************************
|
||
|
//
|
||
|
// Debugging functions
|
||
|
//
|
||
|
// Microsoft Confidential
|
||
|
// Copyright (c) Microsoft Corporation 1995
|
||
|
// All rights reserved
|
||
|
//
|
||
|
//*************************************************************
|
||
|
|
||
|
#include "fdeploy.hxx"
|
||
|
|
||
|
//
|
||
|
// 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;
|
||
|
|
||
|
//
|
||
|
// Debug strings
|
||
|
//
|
||
|
|
||
|
const WCHAR cwszTitle[] = L"FDEPLOY (%x) ";
|
||
|
const WCHAR cwszTime[] = L"%02d:%02d:%02d:%03d ";
|
||
|
const WCHAR cwszLogfile[] = L"%SystemRoot%\\Debug\\UserMode\\fdeploy.log";
|
||
|
const WCHAR cwszCRLF[] = L"\r\n";
|
||
|
|
||
|
//
|
||
|
// Registry debug information
|
||
|
//
|
||
|
|
||
|
#define DEBUG_REG_LOCATION L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Diagnostics"
|
||
|
#define DEBUG_KEY_NAME L"FDeployDebugLevel"
|
||
|
#define DEBUGBREAK_KEY_NAME L"FDeployDebugBreak"
|
||
|
|
||
|
//*************************************************************
|
||
|
//
|
||
|
// InitDebugSupport()
|
||
|
//
|
||
|
// Sets the debugging level.
|
||
|
// Also checks the registry for a debugging level.
|
||
|
//
|
||
|
//*************************************************************
|
||
|
void InitDebugSupport()
|
||
|
{
|
||
|
HKEY hKey;
|
||
|
DWORD Size;
|
||
|
DWORD Type;
|
||
|
BOOL bVerbose;
|
||
|
DWORD Status;
|
||
|
|
||
|
#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;
|
||
|
Size = sizeof(bVerbose);
|
||
|
|
||
|
if ( ERROR_SUCCESS == Status )
|
||
|
{
|
||
|
Status = RegQueryValueEx(
|
||
|
hKey,
|
||
|
DIAGNOSTICS_POLICY_VALUE,
|
||
|
NULL,
|
||
|
&Type,
|
||
|
(LPBYTE) &bVerbose,
|
||
|
&Size );
|
||
|
|
||
|
if ( (ERROR_SUCCESS == Status) && (Type != REG_DWORD) )
|
||
|
bVerbose = FALSE;
|
||
|
|
||
|
RegCloseKey(hKey);
|
||
|
}
|
||
|
|
||
|
Status = RegOpenKey(
|
||
|
HKEY_LOCAL_MACHINE,
|
||
|
DEBUG_REG_LOCATION,
|
||
|
&hKey );
|
||
|
|
||
|
if ( ERROR_SUCCESS == Status )
|
||
|
{
|
||
|
Size = sizeof(gDebugLevel);
|
||
|
RegQueryValueEx(
|
||
|
hKey,
|
||
|
DEBUG_KEY_NAME,
|
||
|
NULL,
|
||
|
&Type,
|
||
|
(LPBYTE)&gDebugLevel,
|
||
|
&Size );
|
||
|
|
||
|
Size = sizeof(gDebugBreak);
|
||
|
RegQueryValueEx(
|
||
|
hKey,
|
||
|
DEBUGBREAK_KEY_NAME,
|
||
|
NULL,
|
||
|
&Type,
|
||
|
(LPBYTE)&gDebugBreak,
|
||
|
&Size );
|
||
|
|
||
|
RegCloseKey(hKey);
|
||
|
}
|
||
|
|
||
|
if ( bVerbose )
|
||
|
gDebugLevel |= DL_VERBOSE | DL_EVENTLOG;
|
||
|
}
|
||
|
|
||
|
void ConditionalBreakIntoDebugger()
|
||
|
{
|
||
|
if (gDebugBreak)
|
||
|
{
|
||
|
DebugBreak();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
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, ...)
|
||
|
{
|
||
|
BOOL bEventLogOK;
|
||
|
WCHAR wszDebugTitle[30];
|
||
|
WCHAR wszDebugTime [30];
|
||
|
WCHAR wszDebugBuffer[4*MAX_PATH];
|
||
|
WCHAR wszMsg[MAX_PATH];
|
||
|
va_list VAList;
|
||
|
DWORD dwErrCode;
|
||
|
SYSTEMTIME systime;
|
||
|
|
||
|
bEventLogOK = ! (mask & DM_NO_EVENTLOG);
|
||
|
|
||
|
if ( ! DebugLevelOn( mask ) )
|
||
|
return;
|
||
|
|
||
|
//
|
||
|
// Save the last error code (so the debug output doesn't change it).
|
||
|
//
|
||
|
dwErrCode = GetLastError();
|
||
|
|
||
|
va_start(VAList, MsgID);
|
||
|
|
||
|
//
|
||
|
// Event log message ids start at 101. For these we must call
|
||
|
// FormatMessage. For other verbose debug output, we use
|
||
|
// LoadString to get the string resource.
|
||
|
//
|
||
|
if ( MsgID < 100 )
|
||
|
{
|
||
|
if ( ! LoadString( ghDllInstance, MsgID, wszMsg, MAX_PATH) )
|
||
|
{
|
||
|
SetLastError(dwErrCode);
|
||
|
return;
|
||
|
}
|
||
|
wvsprintf(wszDebugBuffer, wszMsg, VAList);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
DWORD CharsWritten;
|
||
|
|
||
|
CharsWritten = FormatMessage(
|
||
|
FORMAT_MESSAGE_FROM_HMODULE,
|
||
|
ghDllInstance,
|
||
|
MsgID,
|
||
|
0,
|
||
|
wszDebugBuffer,
|
||
|
sizeof(wszDebugBuffer) / sizeof(WCHAR),
|
||
|
&VAList );
|
||
|
|
||
|
if ( 0 == CharsWritten )
|
||
|
{
|
||
|
SetLastError(dwErrCode);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
va_end(VAList);
|
||
|
|
||
|
GetLocalTime( &systime );
|
||
|
wsprintf( wszDebugTitle, cwszTitle, GetCurrentProcessId() );
|
||
|
wsprintf( wszDebugTime, cwszTime, systime.wHour, systime.wMinute,
|
||
|
systime.wSecond, systime.wMilliseconds);
|
||
|
|
||
|
OutputDebugString( wszDebugTitle );
|
||
|
OutputDebugString( wszDebugTime );
|
||
|
OutputDebugString( wszDebugBuffer );
|
||
|
OutputDebugString( cwszCRLF );
|
||
|
|
||
|
if ( gDebugLevel & DL_LOGFILE )
|
||
|
{
|
||
|
HANDLE hFile;
|
||
|
TCHAR cwszExpLogfile [MAX_PATH + 1];
|
||
|
|
||
|
DWORD dwRet = ExpandEnvironmentStrings (cwszLogfile, cwszExpLogfile,
|
||
|
MAX_PATH + 1);
|
||
|
|
||
|
if (0 != dwRet && dwRet <= MAX_PATH)
|
||
|
{
|
||
|
hFile = CreateFile(cwszExpLogfile,
|
||
|
FILE_WRITE_DATA | FILE_APPEND_DATA,
|
||
|
FILE_SHARE_READ,
|
||
|
NULL,
|
||
|
OPEN_ALWAYS,
|
||
|
FILE_ATTRIBUTE_NORMAL,
|
||
|
NULL);
|
||
|
|
||
|
if ( hFile != INVALID_HANDLE_VALUE )
|
||
|
{
|
||
|
if ( SetFilePointer (hFile, 0, NULL, FILE_END) != 0xFFFFFFFF )
|
||
|
{
|
||
|
WCHAR * wszBuffer;
|
||
|
DWORD Size;
|
||
|
|
||
|
Size = lstrlen(wszDebugBuffer) + lstrlen (wszDebugTime) + 1;
|
||
|
wszBuffer = (WCHAR *) alloca (Size * sizeof (WCHAR));
|
||
|
|
||
|
if (wszBuffer)
|
||
|
{
|
||
|
wcscpy (wszBuffer, wszDebugTime);
|
||
|
wcscat (wszBuffer, wszDebugBuffer);
|
||
|
WriteFile(
|
||
|
hFile,
|
||
|
(LPCVOID) wszBuffer,
|
||
|
lstrlen(wszBuffer) * sizeof(WCHAR),
|
||
|
&Size,
|
||
|
NULL );
|
||
|
WriteFile(
|
||
|
hFile,
|
||
|
(LPCVOID) cwszCRLF,
|
||
|
lstrlen(cwszCRLF) * sizeof(WCHAR),
|
||
|
&Size,
|
||
|
NULL );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CloseHandle (hFile);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( bEventLogOK && gpEvents && (gDebugLevel & DL_EVENTLOG) )
|
||
|
gpEvents->Report( EVENT_FDEPLOY_VERBOSE, 1, wszDebugBuffer );
|
||
|
|
||
|
//
|
||
|
// Restore the last error code
|
||
|
//
|
||
|
SetLastError(dwErrCode);
|
||
|
|
||
|
#if DBG
|
||
|
if ( mask & DM_ASSERT )
|
||
|
DebugBreak();
|
||
|
#endif
|
||
|
}
|