#ifndef __WIADBG_H_INCLUDED #define __WIADBG_H_INCLUDED #if defined(DBG) || defined(_DEBUG) || defined(DEBUG) #define WIA_DEBUG #endif #if defined(WIA_DEBUG) // This will eliminate the warning "conditional expression is constant" // that we get when compiling the do { ... } while (false) stuff in the // debug macros when /W4 is set #pragma warning(disable:4127) #define WIA_DEBUG_CREATE( hInstance, pszModuleName, bDisplayUi, bLogFile)\ do\ {\ _global_pWiaDebugger = CWiaDebugger::Create( hInstance, pszModuleName, bDisplayUi, bLogFile );\ } while (false) #define WIA_DEBUG_EXISTS() (_global_pWiaDebugger != NULL) #define WIA_DEBUG_DESTROY()\ do\ {\ if (NULL != _global_pWiaDebugger) {\ _global_pWiaDebugger->Destroy();\ _global_pWiaDebugger = NULL;\ }\ } while (false) #define WIA_TRACE(args)\ do\ {\ if (NULL != _global_pWiaDebugger)\ _global_pWiaDebugger->WiaTrace args;\ } while (false) #define WIA_ERROR(args)\ do\ {\ if (NULL != _global_pWiaDebugger)\ _global_pWiaDebugger->WiaError args;\ } while (false) #define WIA_PRINT_COLOR(args)\ do\ {\ if (NULL != _global_pWiaDebugger)\ _global_pWiaDebugger->PrintColor args;\ } while (false) #define WIA_SETFLAGS(flags)\ do\ {\ if (NULL != _global_pWiaDebugger)\ _global_pWiaDebugger->SetDebugFlags(flags);\ } while (false) #define WIA_GETFLAGS(flags)\ do\ {\ if (NULL != _global_pWiaDebugger)\ flags = _global_pWiaDebugger->GetDebugFlags();\ } while (false) #define WIA_SETFILEHANDLE(hndl)\ do\ {\ if (NULL != _global_pWiaDebugger)\ _global_pWiaDebugger->SetLogFileHandle;\ } while (false) #ifdef WINNT #define WIA_ASSERT(x)\ do\ {\ if (!(x))\ {\ WIA_ERROR((TEXT("ASSERTION FAILED: %hs(%d): %hs"),__FILE__,__LINE__,#x));\ DebugBreak();\ }\ }\ while (false) #else #define WIA_ASSERT(x)\ do\ {\ if (!(x))\ {\ WIA_ERROR((TEXT("ASSERTION FAILED: %hs(%d): %hs"),__FILE__,__LINE__,#x));\ _asm { int 3 };\ }\ }\ while (false) #endif #define WIA_PUSHFUNCTION(n)\ CDebugFunctionPushPop _debugFunctionPushPop( &_global_pWiaDebugger, n ) #define WIA_DECLARE_DEBUGGER() #define WIA_CHECK_HR(hr,fnc)\ if (FAILED(hr))\ {\ WIA_ERROR((TEXT("%s failed, hr=0x%08X" ), fnc, hr));\ } #define WIA_RETURN_HR(hr)\ if (FAILED(hr))\ {\ WIA_ERROR((TEXT("Returning WiaError (hr=0x%08X)"),hr));\ }\ return hr; #else #define WIA_DEBUG_CREATE(hInstance, pszModuleName, bDisplayUi, bLogFile) #define WIA_DEBUG_EXISTS() (0) #define WIA_DEBUG_DESTROY() #define WIA_TRACE(args) #define WIA_ERROR(args) #define WIA_PRINT_COLOR(args) #define WIA_SETFLAGS(flags) #define WIA_GETFLAGS(flags) #define WIA_SETFILEHANDLE(hndl) #define WIA_ASSERT(x) #define WIA_PUSHFUNCTION(n) #define WIA_DECLARE_DEBUGGER() #define WIA_CHECK_HR(hr,fnc) #define WIA_RETURN_HR(hr) return hr; #endif class CWiaDebugger { private: HWND m_hWnd; HANDLE m_hLogFile; int m_nStackLevel; TCHAR m_szModuleName[MAX_PATH]; BOOL m_bDisplayUi; BOOL m_bLogFile; HANDLE m_hThread; HANDLE m_hStartedEvent; DWORD m_dwThreadId; int m_nFlags; HINSTANCE m_hInstance; enum { m_nBufferMax = 2048 }; private: CWiaDebugger( HINSTANCE hInstance, LPTSTR pszModuleName, BOOL bDisplayUi, BOOL bLogFile, HANDLE hStartedEvent ); DWORD DebugLoop(void); static DWORD ThreadProc( LPVOID pParam ); public: ~CWiaDebugger(void); static CWiaDebugger * __stdcall Create( HINSTANCE hInstance, LPTSTR pszModuleName, BOOL bDisplayUi=TRUE, BOOL bLogFile=TRUE ); void Destroy(void) { PostMessage( WM_CLOSE ); } void PostMessage( UINT uMsg, WPARAM wParam=0, LPARAM lParam=0 ) { if (m_hWnd) ::PostMessage( m_hWnd, uMsg, wParam, lParam ); else PostThreadMessage( m_dwThreadId, uMsg, wParam, lParam ); } const HANDLE ThreadHandle(void) const { return m_hThread; } HANDLE SetLogFileHandle(HANDLE hFile); HANDLE GetLogFileHandle(void); // Various forms of the WiaTrace commands void WiaTrace( LPCWSTR lpszFormat, ... ); void WiaTrace( LPCSTR lpszFormat, ... ); void WiaTrace( HRESULT hr ); // Various forms of the WiaError commands void WiaError( LPCWSTR lpszFormat, ... ); void WiaError( LPCSTR lpszFormat, ... ); void WiaError( HRESULT hr ); // Print in color void PrintColor( COLORREF crColor, LPCWSTR lpszMsg ); void PrintColor( COLORREF crColor, LPCSTR lpszMsg ); // Set the default debug level int SetDebugFlags( int nDebugLevel ); int GetDebugFlags(void); // Call stack indenting int PushLevel( LPCTSTR lpszFunctionName ); int PopLevel( LPCTSTR lpszFunctionName ); int GetStackLevel(void); enum { DebugNone = 0x00000000, DebugToWindow = 0x00000001, DebugToFile = 0x00000002, DebugToDebugger = 0x00000004, DebugPrintThreadId = 0x00010000, DebugPrintModuleName = 0x00020000, DebugMaximum = 0xFFFFFFFF }; protected: void RouteString( LPWSTR lpszMsg, COLORREF nColor ); void RouteString( LPSTR lpszMsg, COLORREF nColor ); void WriteMessageToFile( LPTSTR lpszMsg ); LPTSTR RemoveTrailingCrLf( LPTSTR lpszStr ); LPSTR UnicodeToAnsi( LPSTR lpszAnsi, LPTSTR lpszUnicode ); LPTSTR AnsiToTChar( LPCSTR pszAnsi, LPTSTR pszTChar ); LPTSTR WideToTChar( LPWSTR pszWide, LPTSTR pszTChar ); int AddString( const LPCTSTR sz, COLORREF cr ); void PrependString( LPTSTR lpszTgt, LPCTSTR lpszStr ); void PrependThreadId( LPTSTR lpszMsg ); void PrependModuleName( LPTSTR lpszMsg ); void InsertStackLevelIndent( LPTSTR lpszMsg, int nStackLevel ); }; class CDebugFunctionPushPop { typedef (*CPushFunction)( LPCTSTR ); typedef (*CPopFunction)( LPCTSTR ); CWiaDebugger **m_ppDebugger; CPushFunction m_pfnPush; CPushFunction m_pfnPop; LPCTSTR m_lpszFunctionName; public: CDebugFunctionPushPop( CWiaDebugger **ppDebugger, LPCTSTR lpszFunctionName=NULL ) : m_ppDebugger(ppDebugger), m_lpszFunctionName(lpszFunctionName) { if (m_ppDebugger && *m_ppDebugger) (*m_ppDebugger)->PushLevel(m_lpszFunctionName); } ~CDebugFunctionPushPop(void) { if (m_ppDebugger && *m_ppDebugger) (*m_ppDebugger)->PopLevel(m_lpszFunctionName); } }; #ifdef WIA_DEBUG extern CWiaDebugger *_global_pWiaDebugger; #endif #endif