/* * DEBUG code - Contains declarations and macros for include debug support; * Contains null definitions when !_DEBUG */ #ifndef _DEBUG_H_ #define _DEBUG_H_ #ifndef RC_INVOKED #ifdef _DEBUG #define DBGSTATE " Debug is on" #else #define DBGSTATE " Debug is off" #endif #endif /* RC_INVOKED */ #include //these are bogus APIs (they do nothing) STDAPI_(BOOL) ValidateAllObjects( BOOL fSuspicious ); STDAPI_(void) DumpAllObjects( void ); #ifdef _DEBUG BOOL InstallHooks(void); BOOL UnInstallHooks(void); #undef ASSERTDATA #ifdef _MAC #ifdef __cplusplus extern "C" { #endif void OutputDebugString(const char *); #ifdef __cplusplus } #endif #endif #define ASSERTDATA static char _szAssertFile[]= __FILE__; #undef Assert // MAC compiler barfs on '(void)0'. #ifdef _MAC #define Assert(a) { if (!(a)) FnAssert(#a, NULL, _szAssertFile, __LINE__); } #undef AssertSz #define AssertSz(a, b) { if (!(a)) FnAssert(#a, b, _szAssertFile, __LINE__); } #else #undef AssertSz #define AssertSz(a,b) ((a) ? NOERROR : FnAssert(#a, b, _szAssertFile, __LINE__)) #endif #undef Verify #define Verify(a) Assert(a) #undef Puts #define Puts(s) OutputDebugString(s) #define ASSERT(cond, msg) #else // !_DEBUG #define ASSERTDATA #define Assert(a) #define AssertSz(a, b) #define Verify(a) (a) #define ASSERT(cond, msg) #define Puts(s) #endif // _DEBUG #ifdef __cplusplus interface IDebugStream; /* * Class CBool wraps boolean values in such a way that they are * readily distinguishable fron integers by the compiler so we can * overload the stream << operator. */ class FAR CBool { BOOL value; public: CBool (BOOL& b) {value = b;} operator BOOL( void ) { return value; } }; /* * Class CHwnd wraps HWND values in such a way that they are * readily distinguishable from UINTS by the compiler so we can * overload the stream << operator */ class FAR CHwnd { HWND m_hwnd; public: CHwnd (HWND hwnd) {m_hwnd = hwnd; } operator HWND( void ) {return m_hwnd;} }; /* * Class CAtom wraps ATOM values in such a way that they are * readily distinguishable from UINTS by the compiler so we can * overload the stream << operator */ class FAR CAtom { ATOM m_atom; public: CAtom (ATOM atom) {m_atom = atom; } operator ATOM( void ) {return m_atom; } }; /* * IDebugStream is a stream to be used for debug output. One * implementation uses the OutputDebugString function of Windows. * * The style is modeled on that of AT&T streams, and so uses * overloaded operators. You can write to a stream in the * following ways: * * *pdbstm << pUnk; // calls the IDebug::Dump function to * display the object, if IDebug is supported. * int n; * *pdbstm << n; // writes n in decimal * * LPSTR sz; * *pdbstm << sz; // writes a string * * CBool b(TRUE); * *pdbstm << b; // writes True or False * * void FAR * pv; * *pdbstm << pv; // writes the address pv in hex * * char ch; * *pdbstm << ch; // writes the character * * ATOM atom; * *pdbstm << CAtom(atom); // writes the string extracted from the atom * * HWND hwnd; * *pdbstm << CHwnd(hwnd); // writes the info about a window handle * * These can be chained together, as such (somewhat artificial * example): * * REFCLSID rclsid; * pUnk->GetClass(&rclsid); * *pdbstm << rclsid << " at " << (void FAR *)pUnk <<':' << pUnk; * * This produces something like: * * CFoo at A7360008: * * The other useful feature is the Indent and UnIndent functions * which allow an object to print some information, indent, print * the info on its member objects, and unindent. This gives * nicely formatted output. * * WARNING: do not (while implementing Dump) write * * *pdbstm << pUnkOuter * * since this will do a QueryInterface for IDebug, and start * recursing! It is acceptable to write * * *pdbstm << (VOID FAR *)pUnkOuter * * as this will simply write the address of pUnkOuter. * */ interface IDebugStream : public IUnknown { STDMETHOD_(IDebugStream&, operator << ) ( IUnknown FAR * pDebug ) = 0; STDMETHOD_(IDebugStream&, operator << ) ( REFCLSID rclsid ) = 0; STDMETHOD_(IDebugStream&, operator << ) ( int n ) = 0; STDMETHOD_(IDebugStream&, operator << ) ( long l ) = 0; STDMETHOD_(IDebugStream&, operator << ) ( ULONG l ) = 0; STDMETHOD_(IDebugStream&, operator << ) ( LPSTR sz ) = 0; STDMETHOD_(IDebugStream&, operator << ) ( char ch ) = 0; STDMETHOD_(IDebugStream&, operator << ) ( void FAR * pv ) = 0; STDMETHOD_(IDebugStream&, operator << ) ( CBool b ) = 0; STDMETHOD_(IDebugStream&, operator << ) ( CHwnd hwnd ) = 0; STDMETHOD_(IDebugStream&, operator << ) ( CAtom atom ) = 0; STDMETHOD_(IDebugStream&, Tab )( void ) = 0; STDMETHOD_(IDebugStream&, Indent )( void ) = 0; STDMETHOD_(IDebugStream&, UnIndent )( void ) = 0; STDMETHOD_(IDebugStream&, Return )( void ) = 0; STDMETHOD_(IDebugStream&, LF )( void ) = 0; }; STDAPI_(IDebugStream FAR*) MakeDebugStream( short margin=70, short tabsize=4, BOOL fHeader=1); interface IDebug { STDMETHOD_(void, Dump )( IDebugStream FAR * pdbstm ) = 0; STDMETHOD_(BOOL, IsValid )( BOOL fSuspicious = FALSE ) = 0; #ifdef NEVER __export IDebug(void); __export ~IDebug(void); private: #if _DEBUG IDebug FAR * pIDPrev; IDebug FAR * pIDNext; friend void STDAPICALLTYPE DumpAllObjects( void ); friend BOOL STDAPICALLTYPE ValidateAllObjects( BOOL fSuspicious ); #endif #endif }; #ifdef _MAC typedef short HFILE; #endif /************************************************************************* ** The following functions can be used to log debug messages to a file ** and simutaneously write them to the dbwin debug window. ** The CDebugStream implementation automatically writes to a debug ** log file called "debug.log" in the current working directory. ** NOTE: The functions are only intended for C programmers. C++ ** programmers should use the "MakeDebugStream" instead. *************************************************************************/ // Open a log file. STDAPI_(HFILE) DbgLogOpen(LPSTR lpszFile, LPSTR lpszMode); // Close the log file. STDAPI_(void) DbgLogClose(HFILE fh); // Write to debug log and debug window (used with cvw.exe or dbwin.exe). STDAPI_(void) DbgLogOutputDebugString(HFILE fh, LPSTR lpsz); // Write to debug log only. STDAPI_(void) DbgLogWrite(HFILE fh, LPSTR lpsz); // Write the current Date and Time to the log file. STDAPI_(void) DbgLogTimeStamp(HFILE fh, LPSTR lpsz); // Write a banner separater to the log to separate sections. STDAPI_(void) DbgLogWriteBanner(HFILE fh, LPSTR lpsz); /* * STDDEBDECL macro - helper for debug declaration * */ #ifdef _DEBUG #ifdef _MAC //#define STDDEBDECL(cclassname,classname) //#if 0 #define STDDEBDECL(cclassname,classname) NESTED_CLASS(cclassname, CDebug):IDebug { public: \ NC1(cclassname,CDebug)( cclassname FAR * p##classname ) { m_p##classname = p##classname;} \ ~##NC1(cclassname,CDebug)(void){} \ STDMETHOD_(void, Dump)(THIS_ IDebugStream FAR * pdbstm ); \ STDMETHOD_(BOOL, IsValid)(THIS_ BOOL fSuspicious ); \ private: cclassname FAR* m_p##classname; }; \ DECLARE_NC2(cclassname, CDebug) \ NC(cclassname, CDebug) m_Debug; //#endif #else // _MAC #define STDDEBDECL(ignore, classname ) implement CDebug:public IDebug { public: \ CDebug( C##classname FAR * p##classname ) { m_p##classname = p##classname;} \ ~CDebug(void) {} \ STDMETHOD_(void, Dump)(IDebugStream FAR * pdbstm ); \ STDMETHOD_(BOOL, IsValid)(BOOL fSuspicious ); \ private: C##classname FAR* m_p##classname; }; \ DECLARE_NC(C##classname, CDebug) \ CDebug m_Debug; #endif //#ifdef _MAC //#define CONSTRUCT_DEBUG //#else #define CONSTRUCT_DEBUG m_Debug(this), //#endif #else // _DEBUG // no debugging #define STDDEBDECL(cclassname,classname) #define CONSTRUCT_DEBUG #endif // _DEBUG #endif __cplusplus #endif !_DEBUG_H_