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.
 
 
 
 
 
 

489 lines
13 KiB

#include "precomp.h"
#include "wiadbgp.h"
#ifdef WIA_DEBUG
CWiaDebugger *_global_pWiaDebugger = NULL;
#endif
CWiaDebugger::CWiaDebugger( HINSTANCE hInstance, LPTSTR pszModuleName, BOOL bDisplayUi, BOOL bLogFile, HANDLE hStartedEvent )
: m_bDisplayUi(bDisplayUi),
m_bLogFile(bLogFile),
m_hWnd(NULL),
m_hLogFile(NULL),
m_nStackLevel(0),
m_nFlags(DebugToWindow|DebugToFile|DebugToDebugger|DebugPrintThreadId),
m_hStartedEvent(hStartedEvent),
m_dwThreadId(0),
m_hInstance(hInstance)
{
if (pszModuleName)
lstrcpy( m_szModuleName, pszModuleName );
else lstrcpy( m_szModuleName, TEXT("") );
if (bLogFile)
{
TCHAR szLogFileName[MAX_PATH]=TEXT("");
LPTSTR pPtr=szLogFileName;
GetWindowsDirectory( szLogFileName, MAX_PATH );
while (*pPtr && *pPtr != TEXT('\\'))
pPtr++;
if (*pPtr == TEXT('\\'))
pPtr++;
else pPtr = szLogFileName;
lstrcpy( pPtr, pszModuleName );
for (int i=lstrlen(szLogFileName);i>0;i--)
{
if (szLogFileName[i-1]==TEXT('.'))
{
szLogFileName[i-1]=TEXT('\0');
break;
}
}
lstrcat(szLogFileName, TEXT(".log"));
if ((m_hLogFile = CreateFile(szLogFileName,
GENERIC_WRITE,
FILE_SHARE_WRITE,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL)) == INVALID_HANDLE_VALUE)
{
m_hLogFile = NULL;
m_nFlags &= ~DebugToFile;
OutputDebugString( TEXT("WIADBG: Unable to create log file\n") );
}
else
{
m_nFlags |= DebugToFile;
}
}
}
DWORD CWiaDebugger::DebugLoop(void)
{
if (m_bDisplayUi)
{
m_hWnd = CWiaDebugWindow::Create( m_szModuleName, m_hInstance, true );
ShowWindow( m_hWnd, SW_SHOW );
UpdateWindow( m_hWnd );
}
SetEvent(m_hStartedEvent);
MSG msg;
while (GetMessage(&msg, 0, 0, 0))
{
if (!msg.hwnd)
{
if (msg.message==WM_CLOSE)
PostQuitMessage(0);
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return 0;
}
DWORD CWiaDebugger::ThreadProc( LPVOID pParam )
{
DWORD dwResult = 0;
CWiaDebugger *This = (CWiaDebugger*)pParam;
if (This)
{
dwResult = (DWORD)This->DebugLoop();
delete This;
}
return dwResult;
}
CWiaDebugger::~CWiaDebugger(void)
{
if (m_hThread)
CloseHandle( m_hThread );
}
CWiaDebugger * __stdcall CWiaDebugger::Create( HINSTANCE hInstance, LPTSTR pszModuleName, BOOL bDisplayUi, BOOL bLogFile )
{
CWiaDebugger *pDebugger = NULL;
HANDLE hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
if (hEvent)
{
pDebugger = new CWiaDebugger( hInstance, pszModuleName, bDisplayUi, bLogFile, hEvent );
if (pDebugger)
{
pDebugger->m_hThread = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc, (PVOID)pDebugger, 0, &pDebugger->m_dwThreadId );
if (pDebugger->m_hThread)
{
// Wait for up to 5 seconds. If someone tries to create a debug
// context in the DLL startup code, the wait will fail and
// we'll output a debug message.
if (WAIT_TIMEOUT == WaitForSingleObject( hEvent, 5000 )) {
OutputDebugString(TEXT("Wait failed while creating a debug context. No context creation in DLL startup."));
}
}
else
{
delete pDebugger;
pDebugger = NULL;
}
}
CloseHandle(hEvent);
}
return pDebugger;
}
int CWiaDebugger::AddString( LPCTSTR szStr, COLORREF cr )
{
if (!m_hWnd || !IsWindow(m_hWnd))
{
return -1;
}
LPTSTR pszStr = (LPTSTR)szStr;
if (pszStr)
{
pszStr = (LPTSTR)LocalAlloc(LPTR,(lstrlen(szStr)+1)*sizeof(TCHAR));
if (pszStr)
lstrcpy(pszStr,szStr);
}
SendMessage( m_hWnd, CWiaDebugWindow::sc_nMsgAddString, (WPARAM)pszStr, (LPARAM)cr);
return 1;
}
HANDLE CWiaDebugger::SetLogFileHandle( HANDLE hFile )
{
HANDLE hOld = m_hLogFile;
m_hLogFile = hFile;
return hOld;
}
HANDLE CWiaDebugger::GetLogFileHandle(void)
{
return m_hLogFile;
}
void CWiaDebugger::WiaTrace( LPCWSTR lpszFormat, ... )
{
WCHAR szMsg[m_nBufferMax];
va_list arglist;
va_start(arglist, lpszFormat);
::wvsprintfW(szMsg, lpszFormat, arglist);
va_end(arglist);
RouteString( szMsg, RGB(0,0,0) );
}
void CWiaDebugger::WiaTrace( LPCSTR lpszFormat, ... )
{
CHAR szMsg[m_nBufferMax];
va_list arglist;
va_start(arglist, lpszFormat);
::wvsprintfA(szMsg, lpszFormat, arglist);
va_end(arglist);
RouteString( szMsg, RGB(0,0,0) );
}
void CWiaDebugger::PrintColor( COLORREF crColor, LPCWSTR lpszMsg )
{
WCHAR szMsg[m_nBufferMax];
lstrcpyW( szMsg, lpszMsg );
RouteString( szMsg, crColor );
}
void CWiaDebugger::PrintColor( COLORREF crColor, LPCSTR lpszMsg )
{
CHAR szMsg[m_nBufferMax];
lstrcpyA( szMsg, lpszMsg );
RouteString( szMsg, crColor );
}
void CWiaDebugger::WiaTrace( HRESULT hr )
{
DWORD dwLen;
LPTSTR pMsgBuf;
dwLen = ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&pMsgBuf, 0, NULL);
if (dwLen)
{
RouteString( pMsgBuf, RGB(0,0,0) );
LocalFree(pMsgBuf);
}
else
WiaTrace( TEXT("WiaError: Can't format WiaError message 0x%08X"), hr );
}
void CWiaDebugger::WiaError( LPCWSTR lpszFormat, ... )
{
WCHAR szMsg[m_nBufferMax];
va_list arglist;
va_start(arglist, lpszFormat);
::wvsprintfW( szMsg, lpszFormat, arglist);
va_end(arglist);
RouteString( szMsg, RGB(255,0,0) );
}
void CWiaDebugger::WiaError( HRESULT hr )
{
ULONG ulLen;
LPTSTR pMsgBuf;
ulLen = ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&pMsgBuf, 0, NULL);
if (ulLen)
{
RouteString( pMsgBuf, RGB(255,0,0) );
LocalFree(pMsgBuf);
}
else
WiaError( TEXT("WiaError: Can't format WiaError message 0x%08X"), hr );
}
void CWiaDebugger::WiaError( LPCSTR lpszFormat, ... )
{
CHAR szMsg[m_nBufferMax];
va_list arglist;
va_start(arglist, lpszFormat);
::wvsprintfA(szMsg, lpszFormat, arglist);
va_end(arglist);
RouteString( szMsg, RGB(255,0,0) );
}
LPTSTR CWiaDebugger::RemoveTrailingCrLf( LPTSTR lpszStr )
{
for (int i=lstrlen(lpszStr);i>0;i--)
if (lpszStr[i-1]==TEXT('\n') || lpszStr[i-1]==TEXT('\r'))
lpszStr[i-1]=TEXT('\0');
else break;
return lpszStr;
}
LPSTR CWiaDebugger::UnicodeToAnsi( LPSTR lpszAnsi, LPTSTR lpszUnicode )
{
#if defined(_UNICODE) || defined(UNICODE)
WideCharToMultiByte( CP_ACP, 0, lpszUnicode, -1, lpszAnsi, lstrlen(lpszUnicode)+1, NULL, NULL );
#else
lstrcpy( lpszAnsi, lpszUnicode );
#endif
return lpszAnsi;
}
void CWiaDebugger::WriteMessageToFile( LPTSTR lpszMsg )
{
HANDLE hFile = GetLogFileHandle();
if (hFile != NULL && hFile != INVALID_HANDLE_VALUE)
{
DWORD dwBytes;
CHAR lpszAnsiMsg[m_nBufferMax];
UnicodeToAnsi( lpszAnsiMsg, lpszMsg );
ULONG ulLength = lstrlenA(lpszAnsiMsg);
WriteFile(hFile, lpszAnsiMsg, ulLength, &dwBytes, NULL);
FlushFileBuffers(hFile);
}
}
static BOOL ContainsNonWhitespace( LPTSTR lpszMsg )
{
for (LPTSTR lpszPtr = lpszMsg;*lpszPtr;lpszPtr++)
if (*lpszPtr != TEXT(' ') && *lpszPtr != TEXT('\n') && *lpszPtr != TEXT('\r') && *lpszPtr != TEXT('\t'))
return TRUE;
return FALSE;
}
void CWiaDebugger::PrependString( LPTSTR lpszTgt, LPCTSTR lpszStr )
{
if (ContainsNonWhitespace(lpszTgt))
{
int iLen = lstrlen(lpszTgt);
int iThreadIdLen = lstrlen(lpszStr);
LPTSTR lpszTmp = (LPTSTR)LocalAlloc( LPTR, (iLen + iThreadIdLen + 2)*sizeof(TCHAR));
if (lpszTmp)
{
lstrcpy( lpszTmp, lpszStr );
lstrcat( lpszTmp, TEXT(" ") );
lstrcat( lpszTmp, lpszTgt );
lstrcpy( lpszTgt, lpszTmp );
LocalFree(lpszTmp);
}
}
}
void CWiaDebugger::PrependThreadId( LPTSTR lpszMsg )
{
if (ContainsNonWhitespace(lpszMsg))
{
TCHAR szThreadId[20];
wsprintf( szThreadId, TEXT("[%08X]"), GetCurrentThreadId() );
PrependString( lpszMsg, szThreadId );
}
}
void CWiaDebugger::PrependModuleName( LPTSTR lpszMsg )
{
if (ContainsNonWhitespace(lpszMsg))
{
TCHAR szModuleName[MAX_PATH+1];
lstrcpy( szModuleName, m_szModuleName );
lstrcat( szModuleName, TEXT(":") );
PrependString( lpszMsg, szModuleName );
}
}
void CWiaDebugger::InsertStackLevelIndent( LPTSTR lpszMsg, int nStackLevel )
{
const LPTSTR lpszIndent = TEXT(" ");
TCHAR szTmp[m_nBufferMax], *pstrTmp, *pstrPtr;
pstrTmp=szTmp;
pstrPtr=lpszMsg;
while (pstrPtr && *pstrPtr)
{
// if the current character is a newline and it isn't the
// last character, append the indent string
if (*pstrPtr==TEXT('\n') && ContainsNonWhitespace(pstrPtr))
{
*pstrTmp++ = *pstrPtr++;
for (int i=0;i<nStackLevel;i++)
{
lstrcpy(pstrTmp,lpszIndent);
pstrTmp += lstrlen(lpszIndent);
}
}
// If this is the first character, insert the indent string before the
// first character
else if (pstrPtr == lpszMsg && ContainsNonWhitespace(pstrPtr))
{
for (int i=0;i<nStackLevel;i++)
{
lstrcpy(pstrTmp,lpszIndent);
pstrTmp += lstrlen(lpszIndent);
}
*pstrTmp++ = *pstrPtr++;
}
else *pstrTmp++ = *pstrPtr++;
}
*pstrTmp = TEXT('\0');
lstrcpy( lpszMsg, szTmp );
}
LPTSTR CWiaDebugger::AnsiToTChar( LPCSTR pszAnsi, LPTSTR pszTChar )
{
#if defined(UNICODE) || defined(_UNICODE)
MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, pszAnsi, lstrlenA(pszAnsi)+1, pszTChar, m_nBufferMax );
#else
lstrcpyA( pszTChar, pszAnsi );
#endif
return pszTChar;
}
LPTSTR CWiaDebugger::WideToTChar( LPWSTR pszWide, LPTSTR pszTChar )
{
#if !defined(UNICODE) && !defined(_UNICODE)
WideCharToMultiByte( CP_ACP, 0, pszWide, lstrlenW(pszWide)+1, pszTChar, m_nBufferMax, NULL, NULL );
#else
lstrcpyW( pszTChar, pszWide );
#endif
return pszTChar;
}
void CWiaDebugger::RouteString( LPWSTR lpszMsg, COLORREF nColor )
{
TCHAR szMsg[m_nBufferMax];
WideToTChar( lpszMsg, szMsg );
// Remove extra CRs and LFs - we want to control them
RemoveTrailingCrLf( szMsg );
if (m_nFlags & DebugPrintModuleName)
PrependModuleName( szMsg );
if (m_nFlags & DebugPrintThreadId)
PrependThreadId( szMsg );
InsertStackLevelIndent( szMsg, GetStackLevel() );
if (m_nFlags & DebugToWindow)
AddString( szMsg, nColor );
#ifdef WIA_DEBUG
if (m_nFlags & DebugToDebugger)
{
OutputDebugString( szMsg );
OutputDebugString( TEXT("\n") );
}
#endif
if (m_nFlags & DebugToFile)
{
WriteMessageToFile( szMsg );
WriteMessageToFile( TEXT("\n") );
}
}
void CWiaDebugger::RouteString( LPSTR lpszMsg, COLORREF nColor )
{
TCHAR szMsg[m_nBufferMax];
AnsiToTChar( lpszMsg, szMsg );
// Remove extra CRs and LFs - we want to control them
RemoveTrailingCrLf( szMsg );
if (m_nFlags & DebugPrintModuleName)
PrependModuleName( szMsg );
if (m_nFlags & DebugPrintThreadId)
PrependThreadId( szMsg );
InsertStackLevelIndent( szMsg, GetStackLevel() );
if (m_nFlags & DebugToWindow)
AddString( szMsg, nColor );
#ifdef WIA_DEBUG
if (m_nFlags & DebugToDebugger)
{
OutputDebugString( szMsg );
OutputDebugString( TEXT("\n") );
}
#endif
if (m_nFlags & DebugToFile)
{
WriteMessageToFile( szMsg );
WriteMessageToFile( TEXT("\n") );
}
}
int CWiaDebugger::SetDebugFlags( int nDebugFlags )
{
int nOld = m_nFlags;
m_nFlags = nDebugFlags;
return nOld;
}
int CWiaDebugger::GetDebugFlags(void)
{
return m_nFlags;
}
int CWiaDebugger::GetStackLevel(void)
{
return m_nStackLevel;
}
int CWiaDebugger::PushLevel( LPCTSTR lpszFunctionName )
{
WiaTrace( TEXT("Entering function %s, (Level %d)"), lpszFunctionName, GetStackLevel() );
return m_nStackLevel++;
}
int CWiaDebugger::PopLevel( LPCTSTR lpszFunctionName )
{
m_nStackLevel--;
if (m_nStackLevel < 0)
m_nStackLevel = 0;
if (!m_nStackLevel)
WiaTrace( TEXT("\n") );
return m_nStackLevel;
}