// --edklog.c-------------------------------------------------------------------
//
// Functions to log debugging information in DEBUG builds.
//
// Copyright (C) Microsoft Corp. 1986-1996. All Rights Reserved.
// -----------------------------------------------------------------------------
#define _PRIVATE_EDKDEBUG_H
#define _PRIVATE_MEMORY_H
#include "edk.h"
#define REPORT_ERROR(x) \
_WriteDebugString( \
"***** error: %s, %lu, [%08lX] *****\n", __FILE__,__LINE__,(x))
#define DECL_FENCE(_name) ULONG _dbg_##_name = 0xAAAAAAAA
#define TEST_FENCE(_name) \
{ \
if(_dbg_##_name != 0xAAAAAAAA) \
{ \
_WriteDebugString( \
"***** error: %s, %lu, memory overwrite at tag '%s'! *****\n", \
__FILE__,__LINE__,#_name); \
} \
}
DECL_FENCE(EDKDEBUG1);
static BOOL fDebugLevel[D_LAST] =
{
TRUE,
TRUE,
TRUE,
TRUE,
TRUE,
TRUE,
TRUE
};
DECL_FENCE(EDKDEBUG2);
static BOOL IsAssertOff = TRUE;
DECL_FENCE(EDKDEBUG3);
static BOOL IsDebugOff = FALSE;
DECL_FENCE(EDKDEBUG4);
static CHAR szFileName[MAX_PATH+1] = {0};
DECL_FENCE(EDKDEBUG5);
static FILE* fp = NULL;
DECL_FENCE(EDKDEBUG6);
static CRITICAL_SECTION cs = {0};
DECL_FENCE(EDKDEBUG7);
#define TEST_ALL_FENCES \
{ \
TEST_FENCE(EDKDEBUG1); \
TEST_FENCE(EDKDEBUG2); \
TEST_FENCE(EDKDEBUG3); \
TEST_FENCE(EDKDEBUG4); \
TEST_FENCE(EDKDEBUG5); \
TEST_FENCE(EDKDEBUG6); \
TEST_FENCE(EDKDEBUG7); \
}
//$--_WriteDebugString----------------------------------------------------------
//
// Write a string to the debugger output window.
//
// -----------------------------------------------------------------------------
void _WriteDebugString( // RETURNS: nothing
IN LPSTR lpszFormat, // format string
...) // arguments
{
char lpsz[BUFSIZ+1] = {0};
va_list va_alist = {0};
SetLastError(ERROR_SUCCESS);
__try
{
va_start( va_alist, lpszFormat );
_vsnprintf( lpsz, BUFSIZ, lpszFormat, va_alist );
va_end( va_alist );
OutputDebugString(lpsz);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
SetLastError(_exception_code());
}
}
//$--_StatusShowAssert----------------------------------------------------------
//
// Status of the assert prompt.
//
// -----------------------------------------------------------------------------
BOOL _StatusShowAssert( // RETURNS: TRUE if assert prompt
void) // no arguments
{
TEST_ALL_FENCES // Check for memory overwrites in global variables
return(!IsAssertOff);
}
//$--_StatusDebugFile-----------------------------------------------------------
//
// Status of the debug log file.
//
// -----------------------------------------------------------------------------
BOOL _StatusDebugFile( // RETURNS: TRUE if debug log available
void) // no arguments
{
BOOL fStatus = TRUE;
TEST_ALL_FENCES // Check for memory overwrites in global variables
if((fp == NULL) || (IsDebugOff == TRUE))
{
fStatus = FALSE;
}
return(fStatus);
}
//$--_StatusDebugLevel----------------------------------------------------------
//
// Status of the debug level.
//
// -----------------------------------------------------------------------------
BOOL _StatusDebugLevel( // RETURNS: nothing
IN DEBUGLEVEL level) // debug level
{
BOOL fStatus = TRUE;
TEST_ALL_FENCES // Check for memory overwrites in global variables
if( (_StatusDebugFile() == FALSE) ||
(level >= D_LAST) ||
(fDebugLevel[(int)level] == FALSE))
{
fStatus = FALSE;
}
return(fStatus);
}
//$--_LockDebugFile-------------------------------------------------------------
//
// Lock the debug log file.
//
// -----------------------------------------------------------------------------
void _LockDebugFile( // RETURNS: nothing
void) // no arguments
{
CHAR sz[BUFSIZ+1] = {0};
TEST_ALL_FENCES // Check for memory overwrites in global variables
__try
{
EnterCriticalSection(&cs);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
REPORT_ERROR(_exception_code());
}
}
//$--_UnlockDebugFile-----------------------------------------------------------
//
// Unlock the debug log file.
//
// -----------------------------------------------------------------------------
void _UnlockDebugFile( // RETURNS: nothing
void) // no arguments
{
CHAR sz[BUFSIZ+1] = {0};
TEST_ALL_FENCES // Check for memory overwrites in global variables
__try
{
LeaveCriticalSection(&cs);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
REPORT_ERROR(_exception_code());
}
}
//$--_WriteDebugFile------------------------------------------------------------
//
// Write to the debug log file.
//
// -----------------------------------------------------------------------------
void _WriteDebugFile( // RETURNS: nothing
IN LPSTR lpszFormat, // format string
...) // arguments
{
va_list va_alist = {0};
TEST_ALL_FENCES // Check for memory overwrites in global variables
if(fp == NULL)
{
REPORT_ERROR(ERROR_INVALID_PARAMETER);
goto cleanup;
}
__try
{
EnterCriticalSection(&cs);
__try
{
va_start( va_alist, lpszFormat );
vfprintf( fp, lpszFormat, va_alist );
va_end( va_alist );
fflush(fp);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
REPORT_ERROR(_exception_code());
}
LeaveCriticalSection(&cs);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
REPORT_ERROR(_exception_code());
}
cleanup:
return;
}
//$--SetDebugLevel--------------------------------------------------------------
// Set debug levels to log.
// -----------------------------------------------------------------------------
static void SetDebugLevel( // RETURNS: nothing
IN LPSTR lpszLevel) // textized debug level
{
int level = 0;
char* lpszToken = NULL;
char buf[BUFSIZ+1] = {0};
TEST_ALL_FENCES // Check for memory overwrites in global variables
if(lpszLevel == NULL)
{
goto cleanup;
}
if(IsBadStringPtrA(lpszLevel, INFINITE))
{
REPORT_ERROR(ERROR_INVALID_PARAMETER);
goto cleanup;
}
IsDebugOff = TRUE;
for(level = 0; level < D_LAST; level++)
{
// Turn the debug level off
fDebugLevel[level] = FALSE;
}
strncpy(buf, lpszLevel, BUFSIZ);
buf[BUFSIZ] = 0;
lpszToken = strtok(buf,", ");
while(lpszToken != NULL)
{
if(!_stricmp("D_PUBLIC", lpszToken))
{
// Turn the debug level on
fDebugLevel[(int)D_PUBLIC] = TRUE; IsDebugOff = FALSE;
}
else if(!_stricmp("D_PRIVATE", lpszToken))
{
// Turn the debug level on
fDebugLevel[(int)D_PRIVATE] = TRUE; IsDebugOff = FALSE;
}
else if(!_stricmp("D_ERROR", lpszToken))
{
// Turn the debug level on
fDebugLevel[(int)D_ERROR] = TRUE; IsDebugOff = FALSE;
}
else if(!_stricmp("D_WARNING", lpszToken))
{
// Turn the debug level on
fDebugLevel[(int)D_WARNING] = TRUE; IsDebugOff = FALSE;
}
else if(!_stricmp("D_STATUS", lpszToken))
{
// Turn the debug level on
fDebugLevel[(int)D_STATUS] = TRUE; IsDebugOff = FALSE;
}
else if(!_stricmp("D_ACTION", lpszToken))
{
// Turn the debug level on
fDebugLevel[(int)D_ACTION] = TRUE; IsDebugOff = FALSE;
}
else if(!_stricmp("D_OTHER", lpszToken))
{
// Turn the debug level on
fDebugLevel[(int)D_OTHER] = TRUE; IsDebugOff = FALSE;
}
lpszToken = strtok(NULL, ", ");
}
cleanup:
return;
}
//$--_InitDebugFile-------------------------------------------------------------
//
// Initialize the debug log file.
//
// -----------------------------------------------------------------------------
void _InitDebugFile( // RETURNS: nothing
void) // no arguments
{
HANDLE hT = NULL;
DWORD dwT = 0;
CHAR szMutexName[MAX_PATH+1] = {0};
CHAR szTempPath[MAX_PATH+1] = {0}; // temporary file name path
TEST_ALL_FENCES // Check for memory overwrites in global variables
if((fp == NULL) && (IsDebugOff == FALSE))
{
_snprintf(szMutexName, MAX_PATH, "EDK%08lX", GetCurrentProcessId());
hT = CreateMutex(NULL, FALSE, szMutexName);
if(hT == NULL)
{
REPORT_ERROR(GetLastError());
return;
}
if((hT != NULL) && (GetLastError() == ERROR_ALREADY_EXISTS))
{
__try
{
dwT = WaitForSingleObject(hT, INFINITE);
if((dwT == WAIT_OBJECT_0) || (dwT == WAIT_ABANDONED))
{
ReleaseMutex(hT);
}
CloseHandle(hT);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
REPORT_ERROR(_exception_code());
}
return;
}
dwT = WaitForSingleObject(hT, INFINITE);
if((dwT == WAIT_OBJECT_0) || (dwT == WAIT_ABANDONED))
{
LPSTR lpsz = NULL;
InitializeCriticalSection(&cs);
SetDebugLevel(getenv("EDK_DEBUG"));
if(IsDebugOff == FALSE)
{
lpsz = getenv("EDK_DEBUG_FILE");
if(lpsz == NULL)
{
// Create a file in the temporary file directory
// with name equal to "EDKxxx.log".
dwT = GetTempPath(
MAX_PATH,// length of buffer
szTempPath);// string buffer
if ( dwT != 0 )
{
// If TEMP has been removed, we'll create it
(VOID)CreateDirectory(
szTempPath,
NULL);
dwT = GetTempFileName(
szTempPath,// temporary file path
EDK_LOG_FILE_PREFIX,// log file prefix
0,// creates unique file name
szFileName);// file name buffer
if ( dwT != 0 )
{
UINT iFileSuffix = 0;
// Delete the edk*.tmp file created as a side
// effect of GetTempFileName().
(VOID)DeleteFile(szFileName);
// Replace .TMP suffix with .LOG suffix.
iFileSuffix = cbStrLenA(szFileName) - sizeof("TMP");
lstrcpyA( &szFileName[iFileSuffix], EDK_LOG_FILE_SUFFIX);
}
else
{
REPORT_ERROR(GetLastError());
}
}
else
{
REPORT_ERROR(GetLastError());
}
}
else
{
strncpy((char *)szFileName, lpsz, MAX_PATH);
}
szFileName[MAX_PATH] = 0;
if((fp = fopen(szFileName, "w")) == NULL)
{
REPORT_ERROR(ERROR_INVALID_PARAMETER);
}
}
lpsz = getenv("EDK_ASSERT");
if((lpsz != NULL) && (lstrcmpiA(lpsz, "TRUE") == 0))
{
IsAssertOff = FALSE;
}
ReleaseMutex(hT);
}
else
{
REPORT_ERROR(GetLastError());
}
CloseHandle(hT);
}
}