WindowsXP-SP1/windows/oleacc/oleacc/debug.cpp
2020-09-30 16:53:49 +02:00

391 lines
10 KiB
C++

// Copyright (c) 2000 Microsoft Corporation
// --------------------------------------------------------------------------
//
// debug
//
// Assert, OutputDebugString-like replacements
//
// See debug.h for usage details.
//
//
// --------------------------------------------------------------------------
#include <windows.h>
#include "debug.h"
#include <tchar.h>
#include <stdarg.h>
#include "types6432.h"
#define ARRAYLEN(a) (sizeof(a)/sizeof(a[0]))
#define TRACE_HRESULT 0x01
#define TRACE_Win32 0x02
void OutputDebugStringDBWIN( LPCTSTR lpOutputString, ...);
void WriteFilename( LPCTSTR pPath, LPTSTR szBuf, int cbBuf );
LPCTSTR g_pLevelStrs [ ] =
{
TEXT("DBG"),
TEXT("INF"),
TEXT("WRN"),
TEXT("ERR"),
TEXT("PRM"),
TEXT("PRW"),
TEXT("IOP"),
TEXT("AST"),
TEXT("AST"),
TEXT("CAL"),
TEXT("RET"),
TEXT("???"),
};
DWORD g_dwTLSIndex = 0;
// enough for 10 4-space indents - 10*4 spaces
LPCTSTR g_szIndent = TEXT(" ");
static
void InternalTrace( LPCTSTR pszFile, ULONG uLineNo, DWORD dwLevel, DWORD dwFlags, const void * pThis, HRESULT hr, LPCTSTR pszWhere, LPCTSTR pszStr )
{
// Only produce output if this mutex exists...
HANDLE hTestMutex = OpenMutex( SYNCHRONIZE, FALSE, TEXT("oleacc-msaa-use-dbwin") );
if( ! hTestMutex )
return;
CloseHandle( hTestMutex );
if( dwLevel >= ARRAYLEN( g_pLevelStrs ) )
dwLevel = ARRAYLEN( g_pLevelStrs ) - 1; // "???" unknown entry
if( ! pszFile )
pszFile = TEXT("[missing file]");;
LPCTSTR pszWhereSep = ( pszWhere && pszStr ) ? TEXT(": ") : TEXT("");
if( ! pszStr && ! pszWhere )
pszStr = TEXT("[missing string]");
else
{
if( ! pszWhere )
pszWhere = TEXT("");
if( ! pszStr )
pszStr = TEXT("");
}
// Basic message stuff - pid, tid... (also pass this and use object ptr?)
// TODO - allow naming of threads?
DWORD pid = GetCurrentProcessId();
DWORD tid = GetCurrentThreadId();
// Generate indent for call/ret...
// TODO - make this thread safe + atomic
if( g_dwTLSIndex == 0 )
{
g_dwTLSIndex = TlsAlloc();
}
DWORD dwIndent = PtrToInt( TlsGetValue( g_dwTLSIndex ) );
if( dwLevel == _TRACE_RET )
{
dwIndent--;
TlsSetValue( g_dwTLSIndex, IntToPtr( dwIndent ) );
}
DWORD dwDisplayIndent = dwIndent;
if( dwDisplayIndent > 10 )
dwDisplayIndent = 10;
if( dwLevel == _TRACE_CALL )
{
dwIndent++;
TlsSetValue( g_dwTLSIndex, IntToPtr( dwIndent ) );
}
// Step to the end of the canned indent string, then back dwIndent*4 spaces.
// (Don't use sizeof(), since it will include the terminating NUL)
LPCTSTR pszIndent = (g_szIndent + 40) - (dwDisplayIndent * 4);
// Extract filename from path:
TCHAR szFN[ 64 ];
WriteFilename( pszFile, szFN, ARRAYLEN( szFN ) );
TCHAR msg[ 1025 ];
if( pThis )
{
if( dwFlags & TRACE_HRESULT )
{
wsprintf( msg, TEXT("%d:%d %s%s %s:%d this=0x%lx hr=0x%lx %s%s%s\r\n"),
pid, tid,
pszIndent, g_pLevelStrs[ dwLevel ], szFN, uLineNo,
pThis, hr,
pszWhere, pszWhereSep, pszStr );
}
else
{
wsprintf( msg, TEXT("%d:%d %s%s %s:%d this=0x%lx %s%s%s\r\n"),
pid, tid,
pszIndent, g_pLevelStrs[ dwLevel ], szFN, uLineNo,
pThis,
pszWhere, pszWhereSep, pszStr );
}
}
else
{
if( dwFlags & TRACE_HRESULT )
{
wsprintf( msg, TEXT("%d:%d %s%s %s:%d hr=0x%lx %s%s%s\r\n"),
pid, tid,
pszIndent, g_pLevelStrs[ dwLevel ], szFN, uLineNo,
hr,
pszWhere, pszWhereSep, pszStr );
}
else
{
wsprintf( msg, TEXT("%d:%d %s%s %s:%d %s%s%s\r\n"),
pid, tid,
pszIndent, g_pLevelStrs[ dwLevel ], szFN, uLineNo,
pszWhere, pszWhereSep, pszStr );
}
}
//
OutputDebugString( msg );
// On w9x, also use the DBWIN mutex technique...
OSVERSIONINFO VerInfo;
VerInfo.dwOSVersionInfoSize = sizeof( VerInfo );
if( GetVersionEx( & VerInfo )
&& VerInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS )
{
OutputDebugStringDBWIN( msg );
}
#ifdef DEBUG
if( dwLevel == _TRACE_ASSERT_D || dwLevel == _TRACE_ERR )
{
DebugBreak();
}
#endif // DEBUG
}
void _Trace( LPCTSTR pFile, ULONG uLineNo, DWORD dwLevel, const void * pThis, LPCTSTR pszWhere, LPCTSTR pszStr )
{
InternalTrace( pFile, uLineNo, dwLevel, 0, pThis, 0, pszWhere, pszStr );
}
void _TraceHR( LPCTSTR pFile, ULONG uLineNo, DWORD dwLevel, const void * pThis, LPCTSTR pszWhere, HRESULT hr, LPCTSTR pszStr )
{
InternalTrace( pFile, uLineNo, dwLevel, TRACE_HRESULT, pThis, hr, pszWhere, pszStr );
}
void _TraceW32( LPCTSTR pFile, ULONG uLineNo, DWORD dwLevel, const void * pThis, LPCTSTR pszWhere, LPCTSTR pszStr )
{
InternalTrace( pFile, uLineNo, dwLevel, TRACE_Win32, pThis, 0, pszWhere, pszStr );
}
void _Trace( LPCTSTR pFile, ULONG uLineNo, DWORD dwLevel, const void * pThis, LPCTSTR pszWhere, LPCTSTR pszStr, va_list alist )
{
TCHAR szBuf[ 1025 ];
LPCTSTR pszBuf;
if( pszStr )
{
wvsprintf( szBuf, pszStr, alist );
pszBuf = szBuf;
}
else
{
pszBuf = NULL;
}
InternalTrace( pFile, uLineNo, dwLevel, 0, pThis, 0, pszWhere, pszBuf );
}
void _TraceHR( LPCTSTR pFile, ULONG uLineNo, DWORD dwLevel, const void * pThis, LPCTSTR pszWhere, HRESULT hr, LPCTSTR pszStr, va_list alist )
{
TCHAR szBuf[ 1025 ];
LPCTSTR pszBuf;
if( pszStr )
{
wvsprintf( szBuf, pszStr, alist );
pszBuf = szBuf;
}
else
{
pszBuf = NULL;
}
InternalTrace( pFile, uLineNo, dwLevel, TRACE_HRESULT, pThis, hr, pszWhere, pszBuf );
}
void _TraceW32( LPCTSTR pFile, ULONG uLineNo, DWORD dwLevel, const void * pThis, LPCTSTR pszWhere, LPCTSTR pszStr, va_list alist )
{
TCHAR szBuf[ 1025 ];
LPCTSTR pszBuf;
if( pszStr )
{
wvsprintf( szBuf, pszStr, alist );
pszBuf = szBuf;
}
else
{
pszBuf = NULL;
}
InternalTrace( pFile, uLineNo, dwLevel, TRACE_Win32, pThis, 0, pszWhere, pszBuf );
}
// Add just the 'filename' part of the full path, minus base and extention.
// So for "g:\dev\vss\msaa\common\file.cpp", write "file".
// The start of this string is that last found ':', '\', or start of string if those are not present.
// The end of this string is the last '.' found after the start position, otherwise the end of the string.
void WriteFilename( LPCTSTR pPath, LPTSTR szBuf, int cBuf )
{
LPCTSTR pScan = pPath;
LPCTSTR pStart = pPath;
LPCTSTR pEnd = NULL;
// Scan through the filename till we hit the end...
while( *pScan != '\0' )
{
// Found a dot - remember it - if we don't hit a directory separator,
// then this marks the end of the name part of the path.
if( *pScan == '.' )
{
pEnd = pScan;
pScan++;
}
// Found a directory separator - reset markers for start and end of
// name part...
if( *pScan == '\\' || *pScan == '/' || *pScan == ':' )
{
pScan++; // skip over separator char
pStart = pScan;
pEnd = NULL;
}
else
{
pScan++;
}
}
if( pEnd == NULL )
pEnd = pScan;
// Copy as much as we can (leaving space for NUL) to out buffer
// (int) cast keeps 64bit compiler happy
int cToCopy = (int)(pEnd - pStart);
if( cToCopy > cBuf - 1 )
cToCopy = cBuf - 1;
memcpy( szBuf, pStart, cToCopy * sizeof( TCHAR ) );
szBuf[ cToCopy ] = '\0';
}
void OutputDebugStringDBWIN( LPCTSTR lpOutputString, ... )
{
// create the output buffer
TCHAR achBuffer[1025];
va_list args;
va_start(args, lpOutputString);
wvsprintf(achBuffer, lpOutputString, args);
va_end(args);
// make sure DBWIN is open and waiting
HANDLE heventDBWIN = OpenEvent(EVENT_MODIFY_STATE, FALSE, TEXT("DBWIN_BUFFER_READY"));
if( !heventDBWIN )
{
return;
}
// get a handle to the data synch object
HANDLE heventData = OpenEvent(EVENT_MODIFY_STATE, FALSE, TEXT("DBWIN_DATA_READY"));
if ( !heventData )
{
CloseHandle(heventDBWIN);
return;
}
HANDLE hSharedFile = CreateFileMapping((HANDLE)-1, NULL, PAGE_READWRITE, 0, 4096, TEXT("DBWIN_BUFFER"));
if (!hSharedFile)
{
CloseHandle(heventDBWIN);
CloseHandle(heventData);
return;
}
// Note - this is an ANSI CHAR pointer, not a TCHAR one.
LPSTR lpszSharedMem = (LPSTR)MapViewOfFile(hSharedFile, FILE_MAP_WRITE, 0, 0, 512);
if (!lpszSharedMem)
{
CloseHandle(heventDBWIN);
CloseHandle(heventData);
return;
}
// wait for buffer event
WaitForSingleObject(heventDBWIN, INFINITE);
#ifdef UNICODE
CHAR achANSIBuffer[ 1025 ];
WideCharToMultiByte( CP_ACP, 0, achBuffer, -1, achANSIBuffer, ARRAYLEN( achANSIBuffer ), NULL, NULL );
#else
LPCSTR achANSIBuffer = achBuffer;
#endif
// write it to the shared memory
*((LPDWORD)lpszSharedMem) = GetCurrentProcessId();
wsprintfA(lpszSharedMem + sizeof(DWORD), "%s", achANSIBuffer);
// signal data ready event
SetEvent(heventData);
// clean up handles
CloseHandle(hSharedFile);
CloseHandle(heventData);
CloseHandle(heventDBWIN);
return;
}