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.
480 lines
15 KiB
480 lines
15 KiB
//====== 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
|