//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1999 // // File: debug.h // // Contents: Debug routines and miscelaneous stuff. // // Classes: None. // // History: 24-Mar-97 EricB Created // // Notes on Error Handling: The general rule is that errors will be reported // to the user as close to the detection of the error as possible. There are // two exceptions to this rule. First, utility routines that don't take an // HWND parameter (or a page object pointer) don't report errors because we // want a window handle so that the error dialogs will be modal. Second, // there are some circumstances where the error needs to be interpreted at a // higher level. These exceptions should be noted where they occur. // //---------------------------------------------------------------------------- #ifndef __DEBUG_HXX__ #define __DEBUG_HXX__ // macros #define ByteOffset(base, offset) (((LPBYTE)base)+offset) //+---------------------------------------------------------------------------- // Macro: LOAD_STRING // Purpose: attempts to load a string, takes "action" if fails //----------------------------------------------------------------------------- #define LOAD_STRING(ids, wcs, len, action) \ if (!LoadString(g_hInstance, ids, wcs, len - 1)) \ { \ DWORD dwErr = GetLastError(); \ dspDebugOut((DEB_ERROR, "LoadString of " #ids " failed with error %lu\n", dwErr)); \ action; \ } //+---------------------------------------------------------------------------- // Function: LoadStringReport // Purpose: attempts to load a string, returns FALSE and gives error message // if a failure occurs. //----------------------------------------------------------------------------- BOOL LoadStringReport(int ids, PTSTR ptsz, int len, HWND hwnd); // // debugging support // #if DBG == 1 #ifndef APINOT #ifdef _X86_ #define APINOT _stdcall #else #define APINOT _cdecl #endif #endif #ifdef __cplusplus extern "C" { #define EXTRNC "C" #else #define EXTRNC #endif // smprintf should only be called from xxDebugOut() void APINOT smprintf( unsigned long ulCompMask, char const *pszComp, char const *ppszfmt, va_list ArgList); void APINOT SmAssertEx( char const *pszFile, int iLine, char const *pszMsg); int APINOT PopUpError( char const *pszMsg, int iLine, char const *pszFile); void APINOT CheckInit(char * pInfoLevelString, unsigned long * InfoLevel); #define DSP_DEBUG_BUF_SIZE (512) #ifdef __cplusplus } #endif // __cplusplus // // Debug print macros // #define DEB_ERROR 0x00000001 // exported error paths #define DEB_WARN 0x00000002 // exported warnings #define DEB_TRACE 0x00000004 // exported trace messages #define DEB_DBGOUT 0x00000010 // Output to debugger #define DEB_STDOUT 0x00000020 // Output to stdout #define DEB_IERROR 0x00000100 // internal error paths #define DEB_IWARN 0x00000200 // internal warnings #define DEB_ITRACE 0x00000400 // internal trace messages #define DEB_USER1 0x00010000 // User defined #define DEB_USER2 0x00020000 // User defined #define DEB_USER3 0x00040000 // User defined #define DEB_USER4 0x00080000 // User defined #define DEB_USER5 0x00100000 // User defined #define DEB_USER6 0x00200000 // User defined #define DEB_USER7 0x00400000 // User defined #define DEB_USER8 0x00800000 // User defined #define DEB_USER9 0x01000000 // User defined #define DEB_USER10 0x02000000 // User defined #define DEB_USER11 0x04000000 // User defined #define DEB_USER12 0x08000000 // User defined #define DEB_USER13 0x10000000 // User defined #define DEB_USER14 0x20000000 // User defined #define DEB_USER15 0x40000000 // User defined #define DEB_NOCOMPNAME 0x80000000 // suppress component name #define DEB_FORCE 0x7fffffff // force message #define ASSRT_MESSAGE 0x00000001 // Output a message #define ASSRT_BREAK 0x00000002 // Int 3 on assertion #define ASSRT_POPUP 0x00000004 // And popup message //+---------------------------------------------------------------------- // // DECLARE_DEBUG(comp) // DECLARE_INFOLEVEL(comp) // // This macro defines xxDebugOut where xx is the component prefix // to be defined. This declares a static variable 'xxInfoLevel', which // can be used to control the type of xxDebugOut messages printed to // the terminal. For example, xxInfoLevel may be set at the debug terminal. // This will enable the user to turn debugging messages on or off, based // on the type desired. The predefined types are defined below. Component // specific values should use the upper 24 bits // // To Use: // // 1) In your components main include file, include the line // DECLARE_DEBUG(comp) // where comp is your component prefix // // 2) In one of your components source files, include the line // DECLARE_INFOLEVEL(comp) // where comp is your component prefix. This will define the // global variable that will control output. // // It is suggested that any component define bits be combined with // existing bits. For example, if you had a specific error path that you // wanted, you might define DEB__ERRORxxx as being // // (0x100 | DEB_ERROR) // // This way, we can turn on DEB_ERROR and get the error, or just 0x100 // and get only your error. // //----------------------------------------------------------------------- #ifndef DEF_INFOLEVEL #define DEF_INFOLEVEL (DEB_ERROR | DEB_WARN) #endif #define DECLARE_INFOLEVEL(comp) \ extern EXTRNC unsigned long comp##InfoLevel = DEF_INFOLEVEL;\ extern EXTRNC char* comp##InfoLevelString = #comp; #ifdef __cplusplus #define DECLARE_DEBUG(comp) \ extern EXTRNC unsigned long comp##InfoLevel; \ extern EXTRNC char *comp##InfoLevelString; \ _inline void \ comp##InlineDebugOut(unsigned long fDebugMask, char const *pszfmt, ...) \ { \ CheckInit(comp##InfoLevelString, &comp##InfoLevel); \ if (comp##InfoLevel & fDebugMask) \ { \ va_list va; \ va_start (va, pszfmt); \ smprintf(fDebugMask, comp##InfoLevelString, pszfmt, va);\ va_end(va); \ } \ } \ \ class comp##CDbgTrace\ {\ private:\ unsigned long _ulFlags;\ char const * const _pszName;\ public:\ comp##CDbgTrace(unsigned long ulFlags, char const * const pszName);\ ~comp##CDbgTrace();\ };\ \ inline comp##CDbgTrace::comp##CDbgTrace(\ unsigned long ulFlags,\ char const * const pszName)\ : _ulFlags(ulFlags), _pszName(pszName)\ {\ comp##InlineDebugOut(_ulFlags, "Entering %s\n", _pszName);\ }\ \ inline comp##CDbgTrace::~comp##CDbgTrace()\ {\ comp##InlineDebugOut(_ulFlags, "Exiting %s\n", _pszName);\ } #else // ! __cplusplus #define DECLARE_DEBUG(comp) \ extern EXTRNC unsigned long comp##InfoLevel; \ extern EXTRNC char *comp##InfoLevelString; \ _inline void \ comp##InlineDebugOut(unsigned long fDebugMask, char const *pszfmt, ...) \ { \ CheckInit(comp##InfoLevelString, &comp##InfoLevel); if (comp##InfoLevel & fDebugMask) \ { \ va_list va; \ va_start (va, pszfmt); \ smprintf(fDebugMask, comp##InfoLevelString, pszfmt, va);\ va_end(va); \ } \ } #endif // ! __cplusplus DECLARE_DEBUG(DsProp) #define dspDebugOut(x) DsPropInlineDebugOut x #define dspAssert(x) (void)((x) || (SmAssertEx(__FILE__, __LINE__, #x),0)) #include "dscmn.h" #define ERR_OUT(msg, hr) \ if (SUCCEEDED(hr)) { \ dspDebugOut((DEB_ERROR, #msg "\n")); \ } else { \ dspDebugOut((DEB_ERROR, #msg " failed with error 0x%x\n", hr)); \ ReportError(hr, 0, 0); \ } #define REPORT_ERROR(hr, hwnd) \ dspDebugOut((DEB_ERROR, "**** ERROR RETURN <%s @line %d> -> %08lx\n", \ __FILE__, __LINE__, hr)); \ ReportError(hr, 0, hwnd); #define REPORT_ERROR_FORMAT(hr, ids, hwnd) \ dspDebugOut((DEB_ERROR, "**** ERROR RETURN <%s @line %d> -> %08lx\n", \ __FILE__, __LINE__, hr)); \ ReportError(hr, ids, hwnd); #define ERR_MSG(id, hwnd) \ dspDebugOut((DEB_ERROR, "**** ERROR <%s @line %d> msg string ID: %d\n", \ __FILE__, __LINE__, id)); \ ErrMsg(id, hwnd); #define CHECK_HRESULT(hr, action) \ if (FAILED(hr)) { \ dspDebugOut((DEB_ERROR, "**** ERROR RETURN <%s @line %d> -> %08lx\n", \ __FILE__, __LINE__, hr)); \ action; \ } #define CHECK_HRESULT_REPORT(hr, hwnd, action) \ if (FAILED(hr)) { \ dspDebugOut((DEB_ERROR, "**** ERROR RETURN <%s @line %d> -> %08lx\n", \ __FILE__, __LINE__, hr)); \ ReportError(hr, 0, hwnd); \ action; \ } #define CHECK_NULL(ptr, action) \ if (ptr == NULL) { \ dspDebugOut((DEB_ERROR, "**** ERROR RETURN <%s @line %d> -> NULL ptr\n", \ __FILE__, __LINE__)); \ action; \ } #define CHECK_NULL_REPORT(ptr, hwnd, action) \ if (ptr == NULL) { \ dspDebugOut((DEB_ERROR, "**** ERROR RETURN <%s @line %d> -> NULL ptr\n", \ __FILE__, __LINE__)); \ ReportError(E_OUTOFMEMORY, 0, hwnd); \ action; \ } #define CHECK_WIN32(err, action) \ if (err != ERROR_SUCCESS) { \ dspDebugOut((DEB_ERROR, "**** ERROR RETURN <%s @line %d> -> %d\n", \ __FILE__, __LINE__, err)); \ action; \ } #define CHECK_WIN32_REPORT(err, hwnd, action) \ if (err != ERROR_SUCCESS) { \ dspDebugOut((DEB_ERROR, "**** ERROR RETURN <%s @line %d> -> %d\n", \ __FILE__, __LINE__, err)); \ ReportError(err, 0, hwnd); \ action; \ } #define CHECK_STATUS(err, action) \ if (!NT_SUCCESS(err)) { \ dspDebugOut((DEB_ERROR, "**** ERROR RETURN <%s @line %d> -> 0x%08x\n", \ __FILE__, __LINE__, err)); \ action; \ } #define CHECK_STATUS_REPORT(err, hwnd, action) \ if (!NT_SUCCESS(err)) { \ dspDebugOut((DEB_ERROR, "**** ERROR RETURN <%s @line %d> -> 0x%08x\n", \ __FILE__, __LINE__, err)); \ ReportError(RtlNtStatusToDosError(err), 0, hwnd); \ action; \ } #define CHECK_LSA_STATUS(err, action) \ if (!NT_SUCCESS(err)) { \ dspDebugOut((DEB_ERROR, "**** ERROR RETURN <%s @line %d> -> 0x%08x\n", \ __FILE__, __LINE__, err)); \ action; \ } #define CHECK_LSA_STATUS_REPORT(err, hwnd, action) \ if (!NT_SUCCESS(err)) { \ dspDebugOut((DEB_ERROR, "**** ERROR RETURN <%s @line %d> -> 0x%08x\n", \ __FILE__, __LINE__, err)); \ ReportError(LsaNtStatusToWinError(err), 0, hwnd); \ action; \ } #define TRACER(ClassName,MethodName) \ dspDebugOut((DEB_TRACE, #ClassName"::"#MethodName"(0x%p)\n", this)); \ if (DsPropInfoLevel & DEB_USER5) HeapValidate(GetProcessHeap(), 0, NULL); #define TRACE(ClassName,MethodName) \ dspDebugOut((DEB_USER1, #ClassName"::"#MethodName"(0x%p)\n", this)); \ if (DsPropInfoLevel & DEB_USER5) HeapValidate(GetProcessHeap(), 0, NULL); #define TRACE2(ClassName,MethodName) \ dspDebugOut((DEB_USER2, #ClassName"::"#MethodName"(0x%p)\n", this)); \ if (DsPropInfoLevel & DEB_USER5) HeapValidate(GetProcessHeap(), 0, NULL); #define TRACE3(ClassName,MethodName) \ dspDebugOut((DEB_USER3, #ClassName"::"#MethodName"(0x%p)\n", this)); \ if (DsPropInfoLevel & DEB_USER5) HeapValidate(GetProcessHeap(), 0, NULL); #define TRACE_FUNCTION(FunctionName) \ dspDebugOut((DEB_USER1, #FunctionName"\n")); #define TRACE_FUNCTION3(FunctionName) \ dspDebugOut((DEB_USER3, #FunctionName"\n")); #define DBG_OUT(String) \ dspDebugOut((DEB_ITRACE, String "\n")); #define DBG_OUT3(String) \ dspDebugOut((DEB_USER3, String "\n")); #else // DBG != 1 #define DECLARE_DEBUG(comp) #define DECLARE_INFOLEVEL(comp) #define dspDebugOut(x) #define dspAssert(x) #include "dscmn.h" #define ERR_OUT(msg, hr) \ ReportError(hr, 0, 0); #define REPORT_ERROR(hr, hwnd) ReportError(hr, 0, hwnd); #define REPORT_ERROR_FORMAT(hr, ids, hwnd) ReportError(hr, ids, hwnd); #define ERR_MSG(id, hwnd) \ ErrMsg(id, hwnd); #define CHECK_HRESULT(hr, action) \ if (FAILED(hr)) { \ action; \ } #define CHECK_HRESULT_H(hr, hwnd, action) \ if (FAILED(hr)) { \ action; \ } #define CHECK_HRESULT_REPORT(hr, hwnd, action) \ if (FAILED(hr)) { \ ReportError(hr, 0, hwnd); \ action; \ } #define CHECK_NULL(ptr, action) \ if (ptr == NULL) { \ action; \ } #define CHECK_NULL_REPORT(ptr, hwnd, action) \ if (ptr == NULL) { \ ReportError(E_OUTOFMEMORY, 0, hwnd); \ action; \ } #define CHECK_WIN32(err, action) \ if (err != ERROR_SUCCESS) { \ ReportError(err, 0); \ action; \ } #define CHECK_WIN32_REPORT(err, hwnd, action) \ if (err != ERROR_SUCCESS) { \ ReportError(err, 0, hwnd); \ action; \ } #define CHECK_STATUS(err, action) \ if (!NT_SUCCESS(err)) { \ action; \ } #define CHECK_STATUS_REPORT(err, hwnd, action) \ if (!NT_SUCCESS(err)) { \ ReportError(err, 0, hwnd); \ action; \ } #define CHECK_LSA_STATUS(err, action) \ if (!NT_SUCCESS(err)) { \ action; \ } #define CHECK_LSA_STATUS_REPORT(err, hwnd, action) \ if (!NT_SUCCESS(err)) { \ ReportError(LsaNtStatusToWinError(err), 0, hwnd); \ action; \ } #define TRACER(ClassName,MethodName) #define TRACE(ClassName,MethodName) #define TRACE2(ClassName,MethodName) #define TRACE3(ClassName,MethodName) #define TRACE_FUNCTION(FunctionName) #define TRACE_FUNCTION3(FunctionName) #define DBG_OUT(String) #define DBG_OUT3(String) #endif // DBG == 1 #endif // __DEBUG_HXX__