|
|
//====== Assertion/Debug output APIs =================================
#undef CDECL
#define CDECL _cdecl
#if defined(DECLARE_DEBUG) && defined(DEBUG)
//
// Declare module-specific debug strings
//
// When including this header in your private header file, do not
// define DECLARE_DEBUG. But do define DECLARE_DEBUG in one of the
// source files in your project, and then include this header file.
//
// You may also define the following:
//
// SZ_DEBUGINI - the .ini file used to set debug flags
// SZ_DEBUGSECTION - the section in the .ini file specific to
// the module component.
// SZ_MODULE - ansi version of the name of your module.
//
//
// (These are deliberately CHAR)
EXTERN_C const CHAR FAR c_szCcshellIniFile[] = SZ_DEBUGINI; EXTERN_C const CHAR FAR c_szCcshellIniSecDebug[] = SZ_DEBUGSECTION;
EXTERN_C const WCHAR FAR c_wszTrace[] = L"t " TEXTW(SZ_MODULE) L" "; EXTERN_C const WCHAR FAR c_wszErrorDbg[] = L"err " TEXTW(SZ_MODULE) L" "; EXTERN_C const WCHAR FAR c_wszWarningDbg[] = L"wn " TEXTW(SZ_MODULE) L" "; EXTERN_C const WCHAR FAR c_wszAssertMsg[] = TEXTW(SZ_MODULE) L" Assert: "; EXTERN_C const WCHAR FAR c_wszAssertFailed[] = TEXTW(SZ_MODULE) L" Assert %s, line %d: (%s)\r\n";
// (These are deliberately CHAR)
EXTERN_C const CHAR FAR c_szTrace[] = "t " SZ_MODULE " "; EXTERN_C const CHAR FAR c_szErrorDbg[] = "err " SZ_MODULE " "; EXTERN_C const CHAR FAR c_szWarningDbg[] = "wn " SZ_MODULE " "; EXTERN_C const CHAR FAR c_szAssertMsg[] = SZ_MODULE " Assert: "; EXTERN_C const CHAR FAR c_szAssertFailed[] = SZ_MODULE " Assert %s, line %d: (%s)\r\n";
#endif // DECLARE_DEBUG && DEBUG
#if defined(DECLARE_DEBUG) && defined(PRODUCT_PROF)
EXTERN_C const CHAR FAR c_szCcshellIniFile[] = SZ_DEBUGINI; EXTERN_C const CHAR FAR c_szCcshellIniSecDebug[] = SZ_DEBUGSECTION; #endif
#ifdef __cplusplus
extern "C" { #endif
#if !defined(DECLARE_DEBUG)
//
// Debug macros and validation code
//
#undef Assert
#undef AssertE
#undef AssertMsg
#undef AssertStrLen
#undef DebugMsg
#undef FullDebugMsg
#undef ASSERT
#undef EVAL
// Access these globals to determine which debug flags are set.
// These globals are modified by CcshellGetDebugFlags(), which
// reads an .ini file and sets the appropriate flags.
//
// g_dwDumpFlags - bits are application specific. Typically
// used for dumping structures.
// g_dwBreakFlags - uses BF_* flags. The remaining bits are
// application specific. Used to determine
// when to break into the debugger.
// g_dwTraceFlags - uses TF_* flags. The remaining bits are
// application specific. Used to display
// debug trace messages.
// g_dwFuncTraceFlags - bits are application specific. When
// TF_FUNC is set, CcshellFuncMsg uses this
// value to determine which function traces
// to display.
// g_dwProtoype - bits are application specific. Use it for
// anything.
// g_dwProfileCAP - bits are application specific. Used to
// control ICECAP profiling.
//
extern DWORD g_dwDumpFlags; extern DWORD g_dwBreakFlags; extern DWORD g_dwTraceFlags; #ifdef DEBUG
extern DWORD g_dwPrototype; #else
#define g_dwPrototype 0
#endif
extern DWORD g_dwFuncTraceFlags;
#if defined(DEBUG) || defined(PRODUCT_PROF)
BOOL CcshellGetDebugFlags(void); #else
#define CcshellGetDebugFlags() 0
#endif
// Break flags for g_dwBreakFlags
#define BF_ONVALIDATE 0x00000001 // Break on assertions or validation
#define BF_ONAPIENTER 0x00000002 // Break on entering an API
#define BF_ONERRORMSG 0x00000004 // Break on TF_ERROR
#define BF_ONWARNMSG 0x00000008 // Break on TF_WARNING
// Trace flags for g_dwTraceFlags
#define TF_ALWAYS 0xFFFFFFFF
#define TF_NEVER 0x00000000
#define TF_WARNING 0x00000001
#define TF_ERROR 0x00000002
#define TF_GENERAL 0x00000004 // Standard messages
#define TF_FUNC 0x00000008 // Trace function calls
// (Upper 28 bits reserved for custom use per-module)
// Old, archaic debug flags.
// BUGBUG (scotth): the following flags will be phased out over time.
#ifdef DM_TRACE
#undef DM_TRACE
#undef DM_WARNING
#undef DM_ERROR
#endif
#define DM_TRACE TF_GENERAL // OBSOLETE Trace messages
#define DM_WARNING TF_WARNING // OBSOLETE Warning
#define DM_ERROR TF_ERROR // OBSOLETE Error
// Use this macro to declare message text that will be placed
// in the CODE segment (useful if DS is getting full)
//
// Ex: DEBUGTEXT(szMsg, "Invalid whatever: %d");
//
#define DEBUGTEXT(sz, msg) /* ;Internal */ \
static const TCHAR sz[] = msg;
#ifndef NOSHELLDEBUG // Others have own versions of these.
#ifdef DEBUG
#ifdef WIN16
#define DEBUG_BREAK { _asm int 3 }
#else
#ifdef _X86_
// Use int 3 so we stop immediately in the source
#define DEBUG_BREAK { _asm int 3 }
#else
#define DEBUG_BREAK DebugBreak();
#endif
#endif
// Prototypes for debug functions
void CcshellStackEnter(void); void CcshellStackLeave(void);
BOOL CDECL CcshellAssertFailedA(LPCSTR szFile, int line, LPCSTR pszEval, BOOL bBreak); BOOL CDECL CcshellAssertFailedW(LPCWSTR szFile, int line, LPCWSTR pwszEval, BOOL bBreak);
void CDECL CcshellDebugMsgW(DWORD mask, LPCWSTR pszMsg, ...); void CDECL CcshellDebugMsgA(DWORD mask, LPCSTR pszMsg, ...); void CDECL CcshellFuncMsgW(DWORD mask, LPCWSTR pszMsg, ...); void CDECL CcshellFuncMsgA(DWORD mask, LPCSTR pszMsg, ...); void CDECL CcshellAssertMsgW(BOOL bAssert, LPCWSTR pszMsg, ...); void CDECL CcshellAssertMsgA(BOOL bAssert, LPCSTR pszMsg, ...);
void CDECL _AssertMsgA(BOOL f, LPCSTR pszMsg, ...); void CDECL _AssertMsgW(BOOL f, LPCWSTR pszMsg, ...); void CDECL _DebugMsgA(DWORD flag, LPCSTR psz, ...); void CDECL _DebugMsgW(DWORD flag, LPCWSTR psz, ...);
void _AssertStrLenA(LPCSTR pszStr, int iLen); void _AssertStrLenW(LPCWSTR pwzStr, int iLen);
#ifdef UNICODE
#define CcshellAssertFailed CcshellAssertFailedW
#define CcshellDebugMsg CcshellDebugMsgW
#define CcshellFuncMsg CcshellFuncMsgW
#define CcshellAssertMsg CcshellAssertMsgW
#define _AssertMsg _AssertMsgW
#define _AssertStrLen _AssertStrLenW
#define _DebugMsg _DebugMsgW
#else
#define CcshellAssertFailed CcshellAssertFailedA
#define CcshellDebugMsg CcshellDebugMsgA
#define CcshellFuncMsg CcshellFuncMsgA
#define CcshellAssertMsg CcshellAssertMsgA
#define _AssertMsg _AssertMsgA
#define _AssertStrLen _AssertStrLenA
#define _DebugMsg _DebugMsgA
#endif
// Explanation of debug macros:
//
// ----
// Assert(f)
// ASSERT(f)
//
// Generates a "Assert file.c, line x (eval)" message if f is NOT true.
// The g_dwBreakFlags global governs whether the function DebugBreaks.
//
// ----
// AssertE(f)
//
// Works like Assert, except (f) is also executed in the retail
// version as well.
//
// ----
// EVAL(f)
//
// Evaluates the expression (f). The expression is always evaluated,
// even in retail builds. But the macro only asserts in the debug
// build. This macro may only be used on logical expressions, eg:
//
// if (EVAL(exp))
// // do something
//
// ----
// TraceMsg(mask, sz, args...)
//
// Generate wsprintf-formatted msg using specified trace mask.
// The g_dwTraceFlags global governs whether message is displayed.
//
// The sz parameter is always ANSI; TraceMsg correctly converts it
// to unicode if necessary. This is so you don't have to wrap your
// debug strings with TEXT().
//
// ----
// DebugMsg(mask, sz, args...)
//
// OBSOLETE!
// Like TraceMsg, except you must wrap the sz parameter with TEXT().
//
// ----
// AssertMsg(bAssert, sz, args...)
//
// Generate wsprintf-formatted msg if the assertion is false.
// The g_dwBreakFlags global governs whether the function DebugBreaks.
//
// The sz parameter is always ANSI; AssertMsg correctly converts it
// to unicode if necessary. This is so you don't have to wrap your
// debug strings with TEXT().
//
#define ASSERT(f) \
{ \ DEBUGTEXT(szFile, TEXT(__FILE__)); \ if (!(f) && CcshellAssertFailed(szFile, __LINE__, TEXT(#f), FALSE)) \ DEBUG_BREAK; \ }
#ifdef DISALLOW_Assert
#define Assert(f) Dont_use_Assert___Use_ASSERT
#else
#define Assert(f) ASSERT(f)
#endif
#define AssertE(f) ASSERT(f)
#define EVAL(exp) \
((exp) || (CcshellAssertFailed(TEXT(__FILE__), __LINE__, TEXT(#exp), TRUE), 0))
// Use TraceMsg instead of DebugMsg. DebugMsg is obsolete.
#define AssertMsg _AssertMsg
#define AssertStrLen _AssertStrLen
#define AssertStrLenA _AssertStrLenA
#define AssertStrLenW _AssertStrLenW
#ifdef DISALLOW_DebugMsg
#define DebugMsg Dont_use_DebugMsg___Use_TraceMsg
#else
#define DebugMsg _DebugMsg
#endif
#ifdef FULL_DEBUG
#define FullDebugMsg _DebugMsg
#else
#define FullDebugMsg 1 ? (void)0 : (void)
#endif
#define Dbg_SafeStrA(psz) (SAFECAST(psz, LPCSTR), (psz) ? (psz) : "NULL string")
#ifndef WIN16
#define Dbg_SafeStrW(psz) (SAFECAST(psz, LPCWSTR), (psz) ? (psz) : L"NULL string")
#else
#define Dbg_SafeStrW(psz) (SAFECAST(psz, LPCWSTR), (psz) ? (psz) : TEXT("NULL string"))
#endif
#ifdef UNICODE
#define Dbg_SafeStr Dbg_SafeStrW
#else
#define Dbg_SafeStr Dbg_SafeStrA
#endif
#define ASSERT_MSGW CcshellAssertMsgW
#define ASSERT_MSGA CcshellAssertMsgA
#define ASSERT_MSG CcshellAssertMsg
#define TraceMsgW CcshellDebugMsgW
#define TraceMsgA CcshellDebugMsgA
#define TraceMsg CcshellDebugMsg
#define FUNC_MSG CcshellFuncMsg
// Debug function enter
// DBG_ENTER(flag, fn) -- Generates a function entry debug spew for
// a function
//
#define DBG_ENTER(flagFTF, fn) \
(FUNC_MSG(flagFTF, " > " #fn "()"), \ CcshellStackEnter())
// DBG_ENTER_TYPE(flag, fn, dw, pfnStrFromType) -- Generates a function entry debug
// spew for functions that accept <type>.
//
#define DBG_ENTER_TYPE(flagFTF, fn, dw, pfnStrFromType) \
(FUNC_MSG(flagFTF, " < " #fn "(..., %s, ...)", (LPCTSTR)pfnStrFromType(dw)), \ CcshellStackEnter())
// DBG_ENTER_SZ(flag, fn, sz) -- Generates a function entry debug spew for
// a function that accepts a string as one of its
// parameters.
//
#define DBG_ENTER_SZ(flagFTF, fn, sz) \
(FUNC_MSG(flagFTF, " > " #fn "(..., \"%s\",...)", Dbg_SafeStr(sz)), \ CcshellStackEnter())
// Debug function exit
// DBG_EXIT(flag, fn) -- Generates a function exit debug spew
//
#define DBG_EXIT(flagFTF, fn) \
(CcshellStackLeave(), \ FUNC_MSG(flagFTF, " < " #fn "()"))
// DBG_EXIT_TYPE(flag, fn, dw, pfnStrFromType) -- Generates a function exit debug
// spew for functions that return <type>.
//
#define DBG_EXIT_TYPE(flagFTF, fn, dw, pfnStrFromType) \
(CcshellStackLeave(), \ FUNC_MSG(flagFTF, " < " #fn "() with %s", (LPCTSTR)pfnStrFromType(dw)))
// DBG_EXIT_INT(flag, fn, us) -- Generates a function exit debug spew for
// functions that return an INT.
//
#define DBG_EXIT_INT(flagFTF, fn, n) \
(CcshellStackLeave(), \ FUNC_MSG(flagFTF, " < " #fn "() with %d", (int)(n)))
// DBG_EXIT_BOOL(flag, fn, b) -- Generates a function exit debug spew for
// functions that return a boolean.
//
#define DBG_EXIT_BOOL(flagFTF, fn, b) \
(CcshellStackLeave(), \ FUNC_MSG(flagFTF, " < " #fn "() with %s", (b) ? (LPTSTR)TEXT("TRUE") : (LPTSTR)TEXT("FALSE")))
// DBG_EXIT_UL(flag, fn, ul) -- Generates a function exit debug spew for
// functions that return a ULONG.
//
#define DBG_EXIT_UL(flagFTF, fn, ul) \
(CcshellStackLeave(), \ FUNC_MSG(flagFTF, " < " #fn "() with %#08lx", (ULONG)(ul)))
#define DBG_EXIT_DWORD DBG_EXIT_UL
// DBG_EXIT_HRES(flag, fn, hres) -- Generates a function exit debug spew for
// functions that return an HRESULT.
//
#define DBG_EXIT_HRES(flagFTF, fn, hres) DBG_EXIT_TYPE(flagFTF, fn, hres, Dbg_GetHRESULTName)
#else // DEBUG
#define Assert(f)
#define AssertE(f) (f)
#define ASSERT(f)
#define AssertMsg 1 ? (void)0 : (void)
#define AssertStrLen(lpStr, iLen)
#define DebugMsg 1 ? (void)0 : (void)
#define FullDebugMsg 1 ? (void)0 : (void)
#define EVAL(exp) ((exp) != 0)
#define Dbg_SafeStr 1 ? (void)0 : (void)
#define TraceMsgA 1 ? (void)0 : (void)
#define TraceMsgW 1 ? (void)0 : (void)
#ifdef UNICODE
#define TraceMsg TraceMsgW
#else
#define TraceMsg TraceMsgA
#endif
#define FUNC_MSG 1 ? (void)0 : (void)
#define ASSERT_MSGA TraceMsgA
#define ASSERT_MSGW TraceMsgW
#define ASSERT_MSG TraceMsg
#define DBG_ENTER(flagFTF, fn)
#define DBG_ENTER_TYPE(flagFTF, fn, dw, pfn)
#define DBG_ENTER_SZ(flagFTF, fn, sz)
#define DBG_EXIT(flagFTF, fn)
#define DBG_EXIT_INT(flagFTF, fn, n)
#define DBG_EXIT_BOOL(flagFTF, fn, b)
#define DBG_EXIT_UL(flagFTF, fn, ul)
#define DBG_EXIT_DWORD DBG_EXIT_UL
#define DBG_EXIT_TYPE(flagFTF, fn, dw, pfn)
#define DBG_EXIT_HRES(flagFTF, fn, hres)
#endif // DEBUG
#endif // NOSHELLDEBUG
//
// Debug dump helper functions
//
#ifdef DEBUG
LPCTSTR Dbg_GetCFName(UINT ucf); LPCTSTR Dbg_GetHRESULTName(HRESULT hr); LPCTSTR Dbg_GetREFIIDName(REFIID riid); LPCTSTR Dbg_GetVTName(VARTYPE vt);
#else
#define Dbg_GetCFName(ucf) (void)0
#define Dbg_GetHRESULTName(hr) (void)0
#define Dbg_GetREFIIDName(riid) (void)0
#define Dbg_GetVTName(vt) (void)0
#endif // DEBUG
// Parameter validation macros
#include "validate.h"
#endif // DECLARE_DEBUG
#ifdef PRODUCT_PROF
int __stdcall StartCAP(void); // start profiling
int __stdcall StopCAP(void); // stop profiling until StartCAP
int __stdcall SuspendCAP(void); // suspend profiling until ResumeCAP
int __stdcall ResumeCAP(void); // resume profiling
int __stdcall StartCAPAll(void); // process-wide start profiling
int __stdcall StopCAPAll(void); // process-wide stop profiling
int __stdcall SuspendCAPAll(void); // process-wide suspend profiling
int __stdcall ResumeCAPAll(void); // process-wide resume profiling
void __stdcall MarkCAP(long lMark); // write mark to MEA
extern DWORD g_dwProfileCAP; #else
#define StartCAP() 0
#define StopCAP() 0
#define SuspendCAP() 0
#define ResumeCAP() 0
#define StartCAPAll() 0
#define StopCAPAll() 0
#define SuspendCAPAll() 0
#define ResumeCAPAll() 0
#define MarkCAP(n) 0
#define g_dwProfileCAP 0
#endif
#ifdef __cplusplus
}; #endif
|