355 lines
10 KiB
C++
355 lines
10 KiB
C++
|
|
// Ruler
|
|
// 1 2 3 4 5 6 7 8
|
|
//345678901234567890123456789012345678901234567890123456789012345678901234567890
|
|
|
|
/********************************************************************/
|
|
/* */
|
|
/* The standard layout. */
|
|
/* */
|
|
/* The standard layout for 'cpp' files in this code is as */
|
|
/* follows: */
|
|
/* */
|
|
/* 1. Include files. */
|
|
/* 2. Constants local to the class. */
|
|
/* 3. Data structures local to the class. */
|
|
/* 4. Data initializations. */
|
|
/* 5. Static functions. */
|
|
/* 6. Class functions. */
|
|
/* */
|
|
/* The constructor is typically the first function, class */
|
|
/* member functions appear in alphabetical order with the */
|
|
/* destructor appearing at the end of the file. Any section */
|
|
/* or function this is not required is simply omitted. */
|
|
/* */
|
|
/********************************************************************/
|
|
|
|
#include "LibraryPCH.hpp"
|
|
|
|
#include "Global.hpp"
|
|
#include "Spinlock.hpp"
|
|
|
|
/********************************************************************/
|
|
/* */
|
|
/* Constants local to the class. */
|
|
/* */
|
|
/* The constants supplied here control various debug settings. */
|
|
/* */
|
|
/********************************************************************/
|
|
|
|
CONST SBIT32 MaxDebugFileName = 128;
|
|
CONST SBIT32 DebugBufferSize = 512;
|
|
#ifdef ENABLE_DEBUG_FILE
|
|
|
|
/********************************************************************/
|
|
/* */
|
|
/* Static member initialization. */
|
|
/* */
|
|
/* Static member initialization sets the initial value for all */
|
|
/* static members. */
|
|
/* */
|
|
/********************************************************************/
|
|
|
|
STATIC CHAR DebugModuleName[ MaxDebugFileName ] = "";
|
|
STATIC SPINLOCK Spinlock;
|
|
|
|
/********************************************************************/
|
|
/* */
|
|
/* Debug file name. */
|
|
/* */
|
|
/* We sometimes want to change the debug file name to prevent */
|
|
/* the debug file being overwritten by a DLLs output or a later */
|
|
/* run of the same application. */
|
|
/* */
|
|
/********************************************************************/
|
|
|
|
HANDLE DebugFileHandle( VOID )
|
|
{
|
|
AUTO CHAR FileName[ MaxDebugFileName ];
|
|
STATIC HANDLE DebugFile = INVALID_HANDLE_VALUE;
|
|
|
|
//
|
|
// We will open the debug file if it is not
|
|
// already open.
|
|
//
|
|
if ( DebugFile == INVALID_HANDLE_VALUE )
|
|
{
|
|
//
|
|
// Construct the full file name.
|
|
//
|
|
sprintf
|
|
(
|
|
FileName,
|
|
"C:\\Temp\\DebugTrace%s.log",
|
|
DebugModuleName
|
|
);
|
|
|
|
//
|
|
// Now lets try to open the file.
|
|
//
|
|
DebugFile =
|
|
(
|
|
CreateFile
|
|
(
|
|
((LPCTSTR) FileName),
|
|
(GENERIC_READ | GENERIC_WRITE),
|
|
FILE_SHARE_READ,
|
|
NULL,
|
|
CREATE_ALWAYS,
|
|
NULL,
|
|
NULL
|
|
)
|
|
);
|
|
|
|
//
|
|
// When the file will not open for some reason
|
|
// we try an alternative path.
|
|
//
|
|
if ( DebugFile == INVALID_HANDLE_VALUE )
|
|
{
|
|
//
|
|
// Construct the alternate file name.
|
|
//
|
|
sprintf
|
|
(
|
|
FileName,
|
|
"C:\\DebugTrace%s.log",
|
|
DebugModuleName
|
|
);
|
|
|
|
//
|
|
// Try again using an alternative name.
|
|
//
|
|
DebugFile =
|
|
(
|
|
CreateFile
|
|
(
|
|
((LPCTSTR) FileName),
|
|
(GENERIC_READ | GENERIC_WRITE),
|
|
FILE_SHARE_READ,
|
|
NULL,
|
|
CREATE_ALWAYS,
|
|
NULL,
|
|
NULL
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
return DebugFile;
|
|
}
|
|
|
|
/********************************************************************/
|
|
/* */
|
|
/* Debug file name. */
|
|
/* */
|
|
/* We sometimes want to change the debug file name to prevent */
|
|
/* the debug file being overwritten by a DLLs output or a later */
|
|
/* run of the same application. */
|
|
/* */
|
|
/********************************************************************/
|
|
|
|
VOID DebugFileName( CONST CHAR *FileName )
|
|
{
|
|
AUTO CHAR EditBuffer[ MaxDebugFileName ];
|
|
REGISTER CHAR *Current;
|
|
|
|
//
|
|
// Copy the file name into an edit buffer
|
|
// so we can remove any directories or
|
|
// trailing names.
|
|
//
|
|
strncpy( EditBuffer,FileName,MaxDebugFileName );
|
|
|
|
EditBuffer[ (MaxDebugFileName-1) ] = '\0';
|
|
|
|
//
|
|
// Scan backwards to remove any suffix.
|
|
//
|
|
for
|
|
(
|
|
Current = & EditBuffer[ (strlen( EditBuffer )-1) ];
|
|
(Current > EditBuffer) && ((*Current) != '.') && ((*Current) != '\\');
|
|
Current --
|
|
);
|
|
|
|
if ( (Current > EditBuffer) && (*Current) == '.' )
|
|
{ (*Current) = '\0'; }
|
|
|
|
//
|
|
// Scan backwards to the first directory name.
|
|
//
|
|
for
|
|
(
|
|
Current = & EditBuffer[ (strlen( EditBuffer )-1) ];
|
|
(Current > EditBuffer) && ((*Current) != '\\');
|
|
Current --
|
|
);
|
|
|
|
if ( (*Current) == '\\' )
|
|
{ Current ++; }
|
|
|
|
//
|
|
// Copy the edited file name.
|
|
//
|
|
DebugModuleName[0] = '-';
|
|
|
|
strncpy( & DebugModuleName[1],Current,(MaxDebugFileName-1) );
|
|
}
|
|
#endif
|
|
|
|
/********************************************************************/
|
|
/* */
|
|
/* Debug printing. */
|
|
/* */
|
|
/* We sometimes need to print message during debugging. We */
|
|
/* do this using the following 'printf' like function. */
|
|
/* */
|
|
/********************************************************************/
|
|
|
|
VOID DebugPrint( CONST CHAR *Format,... )
|
|
{
|
|
AUTO CHAR Buffer[ DebugBufferSize ];
|
|
|
|
//
|
|
// Start of variable arguments.
|
|
//
|
|
va_list Arguments;
|
|
|
|
va_start(Arguments, Format);
|
|
|
|
//
|
|
// Format the string to be printed.
|
|
//
|
|
_vsnprintf
|
|
(
|
|
Buffer,
|
|
(DebugBufferSize-1),
|
|
Format,
|
|
Arguments
|
|
);
|
|
|
|
//
|
|
// Force null termination.
|
|
//
|
|
Buffer[ (DebugBufferSize-1) ] = '\0';
|
|
|
|
#ifdef ENABLE_DEBUG_FILE
|
|
//
|
|
// Claim a spinlock to prevent multiple
|
|
// threads executing overlapping writes.
|
|
//
|
|
Spinlock.ClaimLock();
|
|
|
|
//
|
|
// We will write to the debug file if there
|
|
// is a valid handle.
|
|
//
|
|
if ( DebugFileHandle() != INVALID_HANDLE_VALUE )
|
|
{
|
|
REGISTER CHAR *Current = Buffer;
|
|
REGISTER SBIT32 Length;
|
|
|
|
//
|
|
// A number of windows applications are too
|
|
// stupid to understand a simple '\n'. So
|
|
// here we convert all "\n" to "\r\n".
|
|
//
|
|
for ( /* void */;(*Current) != '\0';Current += Length )
|
|
{
|
|
STATIC DWORD Written;
|
|
|
|
//
|
|
// Count the characters until the next
|
|
// newline or end of string.
|
|
//
|
|
for
|
|
(
|
|
Length=0;
|
|
((Current[ Length ] != '\n') && (Current[ Length ] != '\0'));
|
|
Length ++
|
|
);
|
|
|
|
//
|
|
// Write the string and then add a return
|
|
// newline sequence.
|
|
//
|
|
WriteFile
|
|
(
|
|
DebugFileHandle(),
|
|
((LPCVOID) Current),
|
|
((DWORD) Length),
|
|
& Written,
|
|
NULL
|
|
);
|
|
|
|
//
|
|
// Generate a newline (if needed).
|
|
//
|
|
if ( Current[ Length ] == '\n' )
|
|
{
|
|
WriteFile
|
|
(
|
|
DebugFileHandle(),
|
|
((LPCVOID) "\r\n"),
|
|
((DWORD) (sizeof("\r\n") - 1)),
|
|
& Written,
|
|
NULL
|
|
);
|
|
|
|
Length ++;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Flush the file buffers.
|
|
//
|
|
FlushFileBuffers( DebugFileHandle() );
|
|
}
|
|
|
|
//
|
|
// Release any lock claimed earlier.
|
|
//
|
|
Spinlock.ReleaseLock();
|
|
#else
|
|
//
|
|
// Write to the debug window.
|
|
//
|
|
OutputDebugString( Buffer );
|
|
#endif
|
|
|
|
//
|
|
// End of variable arguments.
|
|
//
|
|
va_end( Arguments );
|
|
}
|
|
|
|
/********************************************************************/
|
|
/* */
|
|
/* Software failure. */
|
|
/* */
|
|
/* We know that when this function is called the application */
|
|
/* has failed so we simply try to cleanly exit in the vain */
|
|
/* hope that the failure can be caught and corrected. */
|
|
/* */
|
|
/********************************************************************/
|
|
|
|
VOID Failure( char *Message,BOOLEAN Report )
|
|
{
|
|
//
|
|
// Report the fault to the debug stream
|
|
// (if required).
|
|
//
|
|
if ( Report )
|
|
{ DebugPrint( "*** Software Failure: %s ***\n",Message ); }
|
|
|
|
//
|
|
// Raise an exception.
|
|
//
|
|
#ifdef DISABLE_STRUCTURED_EXCEPTIONS
|
|
throw ((FAULT) Message);
|
|
#else
|
|
RaiseException( 1,0,1,((CONST DWORD*) Message) );
|
|
#endif
|
|
}
|