diff options
Diffstat (limited to 'utils/sapi51/include/spdebug.h')
| -rw-r--r-- | utils/sapi51/include/spdebug.h | 636 |
1 files changed, 636 insertions, 0 deletions
diff --git a/utils/sapi51/include/spdebug.h b/utils/sapi51/include/spdebug.h new file mode 100644 index 0000000..da9a7ee --- /dev/null +++ b/utils/sapi51/include/spdebug.h @@ -0,0 +1,636 @@ +/******************************************************************************* +* SPDebug.h * +*-----------* +* Description: +* This header file contains debug output services for SAPI5 +*------------------------------------------------------------------------------- +* Copyright (c) Microsoft Corporation. All rights reserved. +*******************************************************************************/ + +#pragma once + +#include <TCHAR.h> +#include <crtdbg.h> + +#ifdef ASSERT_WITH_STACK +#include "AssertWithStack.h" +#endif + +const TCHAR g_szSpDebugKey[] = _T("SPDebug"); +const TCHAR g_szSpDebugFuncTraceReportMode[] = _T("FuncTraceMode"); +const TCHAR g_szSpDebugFuncTraceReportFile[] = _T("FuncTraceFile"); +const TCHAR g_szSpDebugParamInfoReportMode[] = _T("ParamInfoMode"); +const TCHAR g_szSpDebugParamInfoReportFile[] = _T("ParamInfoFile"); +const TCHAR g_szSpDebugDumpInfoReportMode[] = _T("DumpInfoMode"); +const TCHAR g_szSpDebugDumpInfoReportFile[] = _T("DumpInfoFile"); +const TCHAR g_szSpDebugAssertReportMode[] = _T("AssertMode"); +const TCHAR g_szSpDebugAssertReportFile[] = _T("AssertFile"); +const TCHAR g_szSpDebugHRFailReportMode[] = _T("HRFailMode"); +const TCHAR g_szSpDebugHRFailReportFile[] = _T("HRFailFile"); + +const TCHAR g_szSpDebugAssertSettingsReReadEachTime[] = _T("AssertSettingsReReadEachTime"); +const TCHAR g_szSpDebugServerOnStart[] = _T("DebugServerOnStart"); +const TCHAR g_szSpDebugClientOnStart[] = _T("DebugClientOnStart"); + +const TCHAR g_szSpDebugLog[] = _T("c:\\spdebug.log"); + +#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(); + } + + BOOL DebugServerOnStart() + { + return m_fDebugServerOnStart; + } + + BOOL DebugClientOnStart() + { + return m_fDebugClientOnStart; + } + +private: + + void Read() + { + HKEY hkeyDebug; + RegCreateKeyEx( + HKEY_CLASSES_ROOT, + g_szSpDebugKey, + 0, + NULL, + 0, + KEY_READ | KEY_WRITE, + NULL, + &hkeyDebug, + NULL); + if (hkeyDebug == NULL) + { + RegCreateKeyEx( + HKEY_CLASSES_ROOT, + g_szSpDebugKey, + 0, + NULL, + 0, + KEY_READ, + NULL, + &hkeyDebug, + NULL); + } + + 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, + g_szSpDebugLog); + ReadFor( + hkeyDebug, + g_szSpDebugParamInfoReportMode, + g_szSpDebugParamInfoReportFile, + &m_ParamInfoMode, + m_szParamInfoFile, + 0, + g_szSpDebugLog); + ReadFor( + hkeyDebug, + g_szSpDebugDumpInfoReportMode, + g_szSpDebugDumpInfoReportFile, + &m_DumpInfoMode, + m_szDumpInfoFile, + _CRTDBG_MODE_DEBUG, + g_szSpDebugLog); + ReadFor( + hkeyDebug, + g_szSpDebugAssertReportMode, + g_szSpDebugAssertReportFile, + &m_AssertMode, + m_szAssertFile, + _CRTDBG_MODE_WNDW, + g_szSpDebugLog); + ReadFor( + hkeyDebug, + g_szSpDebugHRFailReportMode, + g_szSpDebugHRFailReportFile, + &m_HRFailMode, + m_szHRFailFile, + _CRTDBG_MODE_DEBUG, + g_szSpDebugLog); + + dw = sizeof(m_fDebugServerOnStart); + if (RegQueryValueEx( + hkeyDebug, + g_szSpDebugServerOnStart, + NULL, + NULL, + LPBYTE(&m_fDebugServerOnStart), + &dw) != ERROR_SUCCESS) + { + m_fDebugServerOnStart = FALSE; + RegSetValueEx( + hkeyDebug, + g_szSpDebugServerOnStart, + NULL, + REG_DWORD, + LPBYTE(&m_fDebugServerOnStart), + sizeof(m_fDebugServerOnStart)); + } + + dw = sizeof(m_fDebugClientOnStart); + if (RegQueryValueEx( + hkeyDebug, + g_szSpDebugClientOnStart, + NULL, + NULL, + LPBYTE(&m_fDebugClientOnStart), + &dw) != ERROR_SUCCESS) + { + m_fDebugClientOnStart = FALSE; + RegSetValueEx( + hkeyDebug, + g_szSpDebugClientOnStart, + NULL, + REG_DWORD, + LPBYTE(&m_fDebugClientOnStart), + sizeof(m_fDebugClientOnStart)); + } + + RegCloseKey(hkeyDebug); + } + + void ReadFor( + HKEY hkey, + const TCHAR * pszModeValueName, + const TCHAR * pszFileValueName, + DWORD * pdwModeValue, + TCHAR * pszFileValue, + DWORD dwDefaultModeValue, + const TCHAR * 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, TCHAR * 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; + TCHAR m_szFuncTraceFile[MAX_PATH + 1]; + DWORD m_ParamInfoMode; + TCHAR m_szParamInfoFile[MAX_PATH + 1]; + DWORD m_DumpInfoMode; + TCHAR m_szDumpInfoFile[MAX_PATH + 1]; + DWORD m_AssertMode; + TCHAR m_szAssertFile[MAX_PATH + 1]; + DWORD m_HRFailMode; + TCHAR m_szHRFailFile[MAX_PATH + 1]; + + BOOL m_fDebugServerOnStart; + BOOL m_fDebugClientOnStart; +}; + +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) + +#if defined(ASSERT_WITH_STACK) && !defined(_WIN64) +#define SPDBG_REPORT_ON_FAIL(hr) \ + do \ + { \ + HRESULT _hr = (hr); \ + if (FAILED(_hr) && PSpDebug()->HRFail()) \ + { \ + SYSTEMTIME sysTime; \ + GetLocalTime(&sysTime); \ + CHAR pszHrWithTime[100]; \ + sprintf(pszHrWithTime, "%lX\n\n%d.%d.%d %02d:%02d:%02d", \ + _hr, \ + sysTime.wMonth,sysTime.wDay,sysTime.wYear, \ + sysTime.wHour,sysTime.wMinute,sysTime.wSecond); \ + PCHAR pszStack = \ + (PCHAR)_alloca( \ + cchMaxAssertStackLevelStringLen * \ + cfrMaxAssertStackLevels + 1); \ + GetStringFromStackLevels(0, 10, pszStack); \ + _RPT4(_CRT_WARN, \ + "%s(%d): Failed HR = %s\n\n%s\n", \ + __FILE__, \ + __LINE__, \ + pszHrWithTime, \ + pszStack); \ + PSpDebug()->HRFail(FALSE); \ + } \ + } while (0) +#else // ASSERT_WITH_STACK & !_WIN64 +#define SPDBG_REPORT_ON_FAIL(hr) \ + do \ + { \ + HRESULT _hr = (hr); \ + 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) + +#define SPDBG_RETURN(hr) \ + { \ + HRESULT __hr = (hr); \ + if (FAILED(__hr)) \ + { \ + SPDBG_REPORT_ON_FAIL(__hr); \ + } \ + return __hr; \ + } + +#define SPDBG_DEBUG_SERVER_ON_START() \ + { \ + if (PSpDebug()->DebugServerOnStart()) \ + { \ + if (MessageBox( \ + GetDesktopWindow(), \ + _T("Attach Debugger to the SAPI Server process?"), \ + _T("SAPI"), \ + MB_YESNO) == IDYES) \ + { \ + USES_CONVERSION; \ + TCHAR szCommand[MAX_PATH + 1]; \ + wsprintf( \ + szCommand, \ + _T("msdev -p %d"), \ + GetCurrentProcessId()); \ + system(T2A(szCommand)); \ + } \ + } \ + } + +#define SPDBG_DEBUG_CLIENT_ON_START() \ + { \ + if (PSpDebug()->DebugClientOnStart()) \ + { \ + TCHAR szModule[MAX_PATH + 1]; \ + szModule[0] = '\0'; \ + TCHAR * pszSapiServer = \ + _T("sapisvr.exe"); \ + GetModuleFileName( \ + NULL, \ + szModule, \ + MAX_PATH); \ + if ((_tcslen(szModule) <= \ + _tcslen(pszSapiServer) || \ + _tcsicmp( \ + szModule + \ + _tcslen(szModule) - \ + _tcslen(pszSapiServer), \ + pszSapiServer) != 0) && \ + MessageBox( \ + GetDesktopWindow(), \ + _T("Attach Debugger to the SAPI Client process?"), \ + _T("SAPI"), \ + MB_YESNO) == IDYES) \ + { \ + USES_CONVERSION; \ + TCHAR szCommand[MAX_PATH + 1]; \ + wsprintf( \ + szCommand, \ + _T("msdev -p %d"), \ + GetCurrentProcessId()); \ + system(T2A(szCommand)); \ + } \ + } \ + } + +#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) +#define SPDBG_RETURN(hr) return (hr) +#define SPDBG_DEBUG_SERVER_ON_START() +#define SPDBG_DEBUG_CLIENT_ON_START() + +#endif // _DEBUG |