/******************************************************************************* * SPDebug.h * *-----------* * Description: * This header file contains debug output services for SAPI5 *------------------------------------------------------------------------------- * Copyright (C) 1998-2000 Microsoft Corporation * All Rights Reserved * *------------------------------------------------------------------------------- * Revisions: * ********************************************************************* robch ***/ #pragma once #include #include #ifdef ASSERT_WITH_STACK #include "AssertWithStack.h" #endif LPCTSTR g_szSpDebugKey = TEXT("SPDebug"); LPCTSTR g_szSpDebugFuncTraceReportMode = TEXT("FuncTraceMode"); LPCTSTR g_szSpDebugFuncTraceReportFile = TEXT("FuncTraceFile"); LPCTSTR g_szSpDebugParamInfoReportMode = TEXT("ParamInfoMode"); LPCTSTR g_szSpDebugParamInfoReportFile = TEXT("ParamInfoFile"); LPCTSTR g_szSpDebugDumpInfoReportMode = TEXT("DumpInfoMode"); LPCTSTR g_szSpDebugDumpInfoReportFile = TEXT("DumpInfoFile"); LPCTSTR g_szSpDebugAssertReportMode = TEXT("AssertMode"); LPCTSTR g_szSpDebugAssertReportFile = TEXT("AssertFile"); LPCTSTR g_szSpDebugHRFailReportMode = TEXT("HRFailMode"); LPCTSTR g_szSpDebugHRFailReportFile = TEXT("HRFailFile"); LPCTSTR g_szSpDebugAssertSettingsReReadEachTime = TEXT("AssertSettingsReReadEachTime"); #ifdef _DEBUG class CSpDebug { public: CSpDebug() { m_mutex = NULL; m_reportModePrev = -1; m_hfilePrev = NULL; Read(); } ~CSpDebug() { if (m_mutex != NULL) { CloseHandle(m_mutex); } } BOOL FuncTrace(BOOL fEnter = TRUE) { return fEnter ? Enter(_CRT_WARN, m_FuncTraceMode, m_szFuncTraceFile) : Leave(); } BOOL ParamInfo(BOOL fEnter = TRUE) { return fEnter ? Enter(_CRT_WARN, m_ParamInfoMode, m_szParamInfoFile) : Leave(); } BOOL DumpInfo(BOOL fEnter = TRUE) { return fEnter ? Enter(_CRT_WARN, m_DumpInfoMode, m_szDumpInfoFile) : Leave(); } BOOL Assert(BOOL fEnter = TRUE) { if (m_fAssertSettingsReReadEachTime) Read(); return fEnter ? Enter(_CRT_ASSERT, m_AssertMode, m_szAssertFile) : Leave(); } BOOL HRFail(BOOL fEnter = TRUE) { return fEnter ? Enter(_CRT_WARN, m_HRFailMode, m_szHRFailFile) : Leave(); } private: void Read() { HKEY hkeyDebug; RegCreateKeyEx( HKEY_CLASSES_ROOT, g_szSpDebugKey, 0, NULL, 0, KEY_ALL_ACCESS, NULL, & hkeyDebug, NULL); RegDeleteValue(hkeyDebug, TEXT("CacheSettings")); // BUGBUG: Remove some day DWORD dw = sizeof(m_fAssertSettingsReReadEachTime); if (RegQueryValueEx( hkeyDebug, g_szSpDebugAssertSettingsReReadEachTime, NULL, NULL, LPBYTE(&m_fAssertSettingsReReadEachTime), &dw) != ERROR_SUCCESS) { m_fAssertSettingsReReadEachTime = FALSE; RegSetValueEx( hkeyDebug, g_szSpDebugAssertSettingsReReadEachTime, NULL, REG_DWORD, LPBYTE(&m_fAssertSettingsReReadEachTime), sizeof(m_fAssertSettingsReReadEachTime)); } ReadFor( hkeyDebug, g_szSpDebugFuncTraceReportMode, g_szSpDebugFuncTraceReportFile, &m_FuncTraceMode, m_szFuncTraceFile, 0, TEXT("c:\\spdebug.log")); ReadFor( hkeyDebug, g_szSpDebugParamInfoReportMode, g_szSpDebugParamInfoReportFile, &m_ParamInfoMode, m_szParamInfoFile, 0, TEXT("c:\\spdebug.log")); ReadFor( hkeyDebug, g_szSpDebugDumpInfoReportMode, g_szSpDebugDumpInfoReportFile, &m_DumpInfoMode, m_szDumpInfoFile, _CRTDBG_MODE_DEBUG, TEXT("c:\\spdebug.log")); ReadFor( hkeyDebug, g_szSpDebugAssertReportMode, g_szSpDebugAssertReportFile, &m_AssertMode, m_szAssertFile, _CRTDBG_MODE_WNDW, TEXT("c:\\spdebug.log")); ReadFor( hkeyDebug, g_szSpDebugHRFailReportMode, g_szSpDebugHRFailReportFile, &m_HRFailMode, m_szHRFailFile, _CRTDBG_MODE_DEBUG, TEXT("c:\\spdebug.log")); RegCloseKey(hkeyDebug); } void ReadFor( HKEY hkey, const WCHAR * pszModeValueName, const WCHAR * pszFileValueName, DWORD * pdwModeValue, WCHAR * pszFileValue, DWORD dwDefaultModeValue, const WCHAR * pszDefaultFileValue) { DWORD dw = sizeof(*pdwModeValue); if (RegQueryValueEx( hkey, pszModeValueName, NULL, NULL, LPBYTE(pdwModeValue), &dw) != ERROR_SUCCESS) { *pdwModeValue = dwDefaultModeValue; RegSetValueEx( hkey, pszModeValueName, NULL, REG_DWORD, LPBYTE(pdwModeValue), sizeof(*pdwModeValue)); } dw = MAX_PATH; if (RegQueryValueEx( hkey, pszFileValueName, NULL, NULL, LPBYTE(pszFileValue), &dw) != ERROR_SUCCESS) { _tcscpy(pszFileValue, pszDefaultFileValue); RegSetValueEx( hkey, pszFileValueName, NULL, REG_SZ, LPBYTE(pszFileValue), MAX_PATH); } } BOOL Enter(int reportType, DWORD &reportMode, WCHAR * pszFile) { if (reportMode != 0) { // We'll hold the mutex, until the caller also calls Leave if (m_mutex == NULL) { m_mutex = CreateMutex(NULL, FALSE, _T("SpDebug")); } WaitForSingleObject(m_mutex, INFINITE); m_reportType = reportType; m_reportModePrev = _CrtSetReportMode(reportType, reportMode); if (reportMode & _CRTDBG_MODE_FILE) { HANDLE hfile = CreateFile( pszFile, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, NULL); SetFilePointer(hfile, 0, NULL, FILE_END); m_hfilePrev = (_HFILE)_CrtSetReportFile(reportType, (_HFILE)hfile); } return TRUE; } return FALSE; } BOOL Leave() { int reportMode = _CrtSetReportMode(m_reportType, m_reportModePrev); if (reportMode & _CRTDBG_MODE_FILE) { CloseHandle((_HFILE)_CrtSetReportFile(m_reportType, (_HFILE)m_hfilePrev)); } ReleaseMutex(m_mutex); return TRUE; } private: HANDLE m_mutex; int m_reportType; int m_reportModePrev; _HFILE m_hfilePrev; BOOL m_fAssertSettingsReReadEachTime; DWORD m_FuncTraceMode; WCHAR m_szFuncTraceFile[MAX_PATH + 1]; DWORD m_ParamInfoMode; WCHAR m_szParamInfoFile[MAX_PATH + 1]; DWORD m_DumpInfoMode; WCHAR m_szDumpInfoFile[MAX_PATH + 1]; DWORD m_AssertMode; WCHAR m_szAssertFile[MAX_PATH + 1]; DWORD m_HRFailMode; WCHAR m_szHRFailFile[MAX_PATH + 1]; }; inline CSpDebug *PSpDebug() { static CSpDebug debug; return &debug; } class CSpFuncTrace { public: CSpFuncTrace(PCHAR pFuncName) { m_pFuncName = pFuncName; if (PSpDebug()->FuncTrace()) { _RPT1( _CRT_WARN, "\nEntering Function: %s\n", m_pFuncName ); PSpDebug()->FuncTrace(FALSE); } } ~CSpFuncTrace() { if (PSpDebug()->FuncTrace()) { _RPT1( _CRT_WARN, "Leaving Function: %s\n", m_pFuncName ); PSpDebug()->FuncTrace(FALSE); } } private: PCHAR m_pFuncName; }; #endif // _DEBUG //=== User macros ============================================================== #ifdef _DEBUG #define SPDBG_FUNC(name) \ CSpFuncTrace functrace(name) #ifdef ASSERT_WITH_STACK #define SPDBG_REPORT_ON_FAIL(hr) \ do \ { \ if (FAILED(hr) && PSpDebug()->HRFail()) \ { \ WCHAR *pszStack = \ (WCHAR*)_alloca( \ cchMaxAssertStackLevelStringLen * \ cfrMaxAssertStackLevels + 1); \ GetStringFromStackLevels(0, 10, pszStack); \ _RPT4(_CRT_WARN, \ "%s(%d): Failed HR = %lX\n\n%s\n", \ __FILE__, \ __LINE__, \ (hr), \ pszStack); \ PSpDebug()->HRFail(FALSE); \ } \ } while (0) #else // ASSERT_WITH_STACK #define SPDBG_REPORT_ON_FAIL(hr) \ do \ { \ if (FAILED(hr) && PSpDebug()->HRFail()) \ { \ _RPT3(_CRT_WARN, "%s(%d): Failed HR = %lX\n", __FILE__, __LINE__, (hr) );\ PSpDebug()->HRFail(FALSE); \ } \ } while (0) #endif // ASSERT_WITH_STACK #define SPDBG_ASSERT(expr) \ do \ { \ if (!(expr)) \ { \ if (PSpDebug()->Assert()) \ { \ _ASSERTE( expr ); \ PSpDebug()->Assert(FALSE); \ } \ } \ } \ while (0) #define SPDBG_VERIFY(expr) \ SPDBG_ASSERT(expr) #define SPDBG_PMSG0(format) \ do \ { \ if (PSpDebug()->ParamInfo()) \ { \ _RPT0(_CRT_WARN, format); \ PSpDebug()->ParamInfo(FALSE); \ } \ } while (0) #define SPDBG_PMSG1(format, arg1) \ do \ { \ if (PSpDebug()->ParamInfo()) \ { \ _RPT1(_CRT_WARN, format, arg1); \ PSpDebug()->ParamInfo(FALSE); \ } \ } while (0) #define SPDBG_PMSG2(format, arg1, arg2) \ do \ { \ if (PSpDebug()->ParamInfo()) \ { \ _RPT2(_CRT_WARN, format, arg1, arg2); \ PSpDebug()->ParamInfo(FALSE); \ } \ } while (0) #define SPDBG_PMSG3(format, arg1, arg2, arg3) \ do \ { \ if (PSpDebug()->ParamInfo()) \ { \ _RPT3(_CRT_WARN, format, arg1, arg2, arg3); \ PSpDebug()->ParamInfo(FALSE); \ } \ } while (0) #define SPDBG_PMSG4(format, arg1, arg2, arg3, arg4) \ do \ { \ if (PSpDebug()->ParamInfo()) \ { \ _RPT4(_CRT_WARN, format, arg1, arg2, arg3, arg4); \ PSpDebug()->ParamInfo(FALSE); \ } \ } while (0) #define SPDBG_DMSG0(format) \ do \ { \ if (PSpDebug()->DumpInfo()) \ { \ _RPT0(_CRT_WARN, format); \ PSpDebug()->DumpInfo(FALSE); \ } \ } while (0) #define SPDBG_DMSG1(format, arg1) \ do \ { \ if (PSpDebug()->DumpInfo()) \ { \ _RPT1(_CRT_WARN, format, arg1); \ PSpDebug()->DumpInfo(FALSE); \ } \ } while (0) #define SPDBG_DMSG2(format, arg1, arg2) \ do \ { \ if (PSpDebug()->DumpInfo()) \ { \ _RPT2(_CRT_WARN, format, arg1, arg2); \ PSpDebug()->DumpInfo(FALSE); \ } \ } while (0) #define SPDBG_DMSG3(format, arg1, arg2, arg3) \ do \ { \ if (PSpDebug()->DumpInfo()) \ { \ _RPT3(_CRT_WARN, format, arg1, arg2, arg3); \ PSpDebug()->DumpInfo(FALSE); \ } \ } while (0) #define SPDBG_DMSG4(format, arg1, arg2, arg3, arg4) \ do \ { \ if (PSpDebug()->DumpInfo()) \ { \ _RPT4(_CRT_WARN, format, arg1, arg2, arg3, arg4); \ PSpDebug()->DumpInfo(FALSE); \ } \ } while (0) #else // _DEBUG #define SPDBG_FUNC(name) #define SPDBG_REPORT_ON_FAIL(hr) #define SPDBG_ASSERT(expr) #define SPDBG_VERIFY(expr) expr #define SPDBG_PMSG0(format) #define SPDBG_PMSG1(format, arg1) #define SPDBG_PMSG2(format, arg1, arg2) #define SPDBG_PMSG3(format, arg1, arg2, arg3) #define SPDBG_PMSG4(format, arg1, arg2, arg3, arg4) #define SPDBG_DMSG0(format) #define SPDBG_DMSG1(format, arg1) #define SPDBG_DMSG2(format, arg1, arg2) #define SPDBG_DMSG3(format, arg1, arg2, arg3) #define SPDBG_DMSG4(format, arg1, arg2, arg3, arg4) #endif // _DEBUG