Tristan Matthews | 0a329cc | 2013-07-17 13:20:14 -0400 | [diff] [blame] | 1 | //------------------------------------------------------------------------------
|
| 2 | // File: WXDebug.h
|
| 3 | //
|
| 4 | // Desc: DirectShow base classes - provides debugging facilities.
|
| 5 | //
|
| 6 | // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
|
| 7 | //------------------------------------------------------------------------------
|
| 8 |
|
| 9 |
|
| 10 | #ifndef __WXDEBUG__
|
| 11 | #define __WXDEBUG__
|
| 12 |
|
| 13 | // This library provides fairly straight forward debugging functionality, this
|
| 14 | // is split into two main sections. The first is assertion handling, there are
|
| 15 | // three types of assertions provided here. The most commonly used one is the
|
| 16 | // ASSERT(condition) macro which will pop up a message box including the file
|
| 17 | // and line number if the condition evaluates to FALSE. Then there is the
|
| 18 | // EXECUTE_ASSERT macro which is the same as ASSERT except the condition will
|
| 19 | // still be executed in NON debug builds. The final type of assertion is the
|
| 20 | // KASSERT macro which is more suitable for pure (perhaps kernel) filters as
|
| 21 | // the condition is printed onto the debugger rather than in a message box.
|
| 22 | //
|
| 23 | // The other part of the debug module facilties is general purpose logging.
|
| 24 | // This is accessed by calling DbgLog(). The function takes a type and level
|
| 25 | // field which define the type of informational string you are presenting and
|
| 26 | // it's relative importance. The type field can be a combination (one or more)
|
| 27 | // of LOG_TIMING, LOG_TRACE, LOG_MEMORY, LOG_LOCKING and LOG_ERROR. The level
|
| 28 | // is a DWORD value where zero defines highest important. Use of zero as the
|
| 29 | // debug logging level is to be encouraged ONLY for major errors or events as
|
| 30 | // they will ALWAYS be displayed on the debugger. Other debug output has it's
|
| 31 | // level matched against the current debug output level stored in the registry
|
| 32 | // for this module and if less than the current setting it will be displayed.
|
| 33 | //
|
| 34 | // Each module or executable has it's own debug output level for each of the
|
| 35 | // five types. These are read in when the DbgInitialise function is called
|
| 36 | // for DLLs linking to STRMBASE.LIB this is done automatically when the DLL
|
| 37 | // is loaded, executables must call it explicitely with the module instance
|
| 38 | // handle given to them through the WINMAIN entry point. An executable must
|
| 39 | // also call DbgTerminate when they have finished to clean up the resources
|
| 40 | // the debug library uses, once again this is done automatically for DLLs
|
| 41 |
|
| 42 | // These are the five different categories of logging information
|
| 43 |
|
| 44 | enum { LOG_TIMING = 0x01, // Timing and performance measurements
|
| 45 | LOG_TRACE = 0x02, // General step point call tracing
|
| 46 | LOG_MEMORY = 0x04, // Memory and object allocation/destruction
|
| 47 | LOG_LOCKING = 0x08, // Locking/unlocking of critical sections
|
| 48 | LOG_ERROR = 0x10, // Debug error notification
|
| 49 | LOG_CUSTOM1 = 0x20,
|
| 50 | LOG_CUSTOM2 = 0x40,
|
| 51 | LOG_CUSTOM3 = 0x80,
|
| 52 | LOG_CUSTOM4 = 0x100,
|
| 53 | LOG_CUSTOM5 = 0x200,
|
| 54 | };
|
| 55 |
|
| 56 | #define LOG_FORCIBLY_SET 0x80000000
|
| 57 |
|
| 58 | enum { CDISP_HEX = 0x01,
|
| 59 | CDISP_DEC = 0x02};
|
| 60 |
|
| 61 | // For each object created derived from CBaseObject (in debug builds) we
|
| 62 | // create a descriptor that holds it's name (statically allocated memory)
|
| 63 | // and a cookie we assign it. We keep a list of all the active objects
|
| 64 | // we have registered so that we can dump a list of remaining objects
|
| 65 |
|
| 66 | typedef struct tag_ObjectDesc {
|
| 67 | LPCSTR m_szName;
|
| 68 | LPCWSTR m_wszName;
|
| 69 | DWORD m_dwCookie;
|
| 70 | tag_ObjectDesc *m_pNext;
|
| 71 | } ObjectDesc;
|
| 72 |
|
| 73 | #define DLLIMPORT __declspec(dllimport)
|
| 74 | #define DLLEXPORT __declspec(dllexport)
|
| 75 |
|
| 76 | #ifdef DEBUG
|
| 77 |
|
| 78 | #define NAME(x) TEXT(x)
|
| 79 |
|
| 80 | // These are used internally by the debug library (PRIVATE)
|
| 81 |
|
| 82 | void WINAPI DbgInitKeyLevels(HKEY hKey, bool fTakeMax);
|
| 83 | void WINAPI DbgInitGlobalSettings(bool fTakeMax);
|
| 84 | void WINAPI DbgInitModuleSettings(bool fTakeMax);
|
| 85 | void WINAPI DbgInitModuleName();
|
| 86 | DWORD WINAPI DbgRegisterObjectCreation(
|
| 87 | LPCSTR szObjectName, LPCWSTR wszObjectName);
|
| 88 |
|
| 89 | BOOL WINAPI DbgRegisterObjectDestruction(DWORD dwCookie);
|
| 90 |
|
| 91 | // These are the PUBLIC entry points
|
| 92 |
|
| 93 | BOOL WINAPI DbgCheckModuleLevel(DWORD Type,DWORD Level);
|
| 94 | void WINAPI DbgSetModuleLevel(DWORD Type,DWORD Level);
|
| 95 | void WINAPI DbgSetAutoRefreshLevels(bool fAuto);
|
| 96 |
|
| 97 | // Initialise the library with the module handle
|
| 98 |
|
| 99 | void WINAPI DbgInitialise(HINSTANCE hInst);
|
| 100 | void WINAPI DbgTerminate();
|
| 101 |
|
| 102 | void WINAPI DbgDumpObjectRegister();
|
| 103 |
|
| 104 | // Display error and logging to the user
|
| 105 |
|
| 106 | void WINAPI DbgAssert(LPCTSTR pCondition,LPCTSTR pFileName,INT iLine);
|
| 107 | void WINAPI DbgBreakPoint(LPCTSTR pCondition,LPCTSTR pFileName,INT iLine);
|
| 108 | void WINAPI DbgBreakPoint(LPCTSTR pFileName,INT iLine,__format_string LPCTSTR szFormatString,...);
|
| 109 |
|
| 110 | void WINAPI DbgKernelAssert(LPCTSTR pCondition,LPCTSTR pFileName,INT iLine);
|
| 111 | void WINAPI DbgLogInfo(DWORD Type,DWORD Level,__format_string LPCTSTR pFormat,...);
|
| 112 | #ifdef UNICODE
|
| 113 | void WINAPI DbgLogInfo(DWORD Type,DWORD Level,__format_string LPCSTR pFormat,...);
|
| 114 | void WINAPI DbgAssert(LPCSTR pCondition,LPCSTR pFileName,INT iLine);
|
| 115 | void WINAPI DbgBreakPoint(LPCSTR pCondition,LPCSTR pFileName,INT iLine);
|
| 116 | void WINAPI DbgKernelAssert(LPCSTR pCondition,LPCSTR pFileName,INT iLine);
|
| 117 | #endif
|
| 118 | void WINAPI DbgOutString(LPCTSTR psz);
|
| 119 |
|
| 120 | // Debug infinite wait stuff
|
| 121 | DWORD WINAPI DbgWaitForSingleObject(HANDLE h);
|
| 122 | DWORD WINAPI DbgWaitForMultipleObjects(DWORD nCount,
|
| 123 | __in_ecount(nCount) CONST HANDLE *lpHandles,
|
| 124 | BOOL bWaitAll);
|
| 125 | void WINAPI DbgSetWaitTimeout(DWORD dwTimeout);
|
| 126 |
|
| 127 | #ifdef __strmif_h__
|
| 128 | // Display a media type: Terse at level 2, verbose at level 5
|
| 129 | void WINAPI DisplayType(LPCTSTR label, const AM_MEDIA_TYPE *pmtIn);
|
| 130 |
|
| 131 | // Dump lots of information about a filter graph
|
| 132 | void WINAPI DumpGraph(IFilterGraph *pGraph, DWORD dwLevel);
|
| 133 | #endif
|
| 134 |
|
| 135 | #define KASSERT(_x_) if (!(_x_)) \
|
| 136 | DbgKernelAssert(TEXT(#_x_),TEXT(__FILE__),__LINE__)
|
| 137 |
|
| 138 | // Break on the debugger without putting up a message box
|
| 139 | // message goes to debugger instead
|
| 140 |
|
| 141 | #define KDbgBreak(_x_) \
|
| 142 | DbgKernelAssert(TEXT(#_x_),TEXT(__FILE__),__LINE__)
|
| 143 |
|
| 144 | // We chose a common name for our ASSERT macro, MFC also uses this name
|
| 145 | // So long as the implementation evaluates the condition and handles it
|
| 146 | // then we will be ok. Rather than override the behaviour expected we
|
| 147 | // will leave whatever first defines ASSERT as the handler (i.e. MFC)
|
| 148 | #ifndef ASSERT
|
| 149 | #define ASSERT(_x_) if (!(_x_)) \
|
| 150 | DbgAssert(TEXT(#_x_),TEXT(__FILE__),__LINE__)
|
| 151 | #endif
|
| 152 |
|
| 153 | #define DbgAssertAligned( _ptr_, _alignment_ ) ASSERT( ((DWORD_PTR) (_ptr_)) % (_alignment_) == 0)
|
| 154 |
|
| 155 | // Put up a message box informing the user of a halt
|
| 156 | // condition in the program
|
| 157 |
|
| 158 | #define DbgBreak(_x_) \
|
| 159 | DbgBreakPoint(TEXT(#_x_),TEXT(__FILE__),__LINE__)
|
| 160 |
|
| 161 | #define EXECUTE_ASSERT(_x_) ASSERT(_x_)
|
| 162 | #define DbgLog(_x_) DbgLogInfo _x_
|
| 163 | // MFC style trace macros
|
| 164 |
|
| 165 | #define NOTE(_x_) DbgLog((LOG_TRACE,5,TEXT(_x_)))
|
| 166 | #define NOTE1(_x_,a) DbgLog((LOG_TRACE,5,TEXT(_x_),a))
|
| 167 | #define NOTE2(_x_,a,b) DbgLog((LOG_TRACE,5,TEXT(_x_),a,b))
|
| 168 | #define NOTE3(_x_,a,b,c) DbgLog((LOG_TRACE,5,TEXT(_x_),a,b,c))
|
| 169 | #define NOTE4(_x_,a,b,c,d) DbgLog((LOG_TRACE,5,TEXT(_x_),a,b,c,d))
|
| 170 | #define NOTE5(_x_,a,b,c,d,e) DbgLog((LOG_TRACE,5,TEXT(_x_),a,b,c,d,e))
|
| 171 |
|
| 172 | #else
|
| 173 |
|
| 174 | // Retail builds make public debug functions inert - WARNING the source
|
| 175 | // files do not define or build any of the entry points in debug builds
|
| 176 | // (public entry points compile to nothing) so if you go trying to call
|
| 177 | // any of the private entry points in your source they won't compile
|
| 178 |
|
| 179 | #define NAME(_x_) ((LPTSTR) NULL)
|
| 180 |
|
| 181 | #define DbgInitialise(hInst)
|
| 182 | #define DbgTerminate()
|
| 183 | #define DbgLog(_x_) 0
|
| 184 | #define DbgOutString(psz)
|
| 185 | #define DbgAssertAligned( _ptr_, _alignment_ ) 0
|
| 186 |
|
| 187 | #define DbgRegisterObjectCreation(pObjectName)
|
| 188 | #define DbgRegisterObjectDestruction(dwCookie)
|
| 189 | #define DbgDumpObjectRegister()
|
| 190 |
|
| 191 | #define DbgCheckModuleLevel(Type,Level)
|
| 192 | #define DbgSetModuleLevel(Type,Level)
|
| 193 | #define DbgSetAutoRefreshLevels(fAuto)
|
| 194 |
|
| 195 | #define DbgWaitForSingleObject(h) WaitForSingleObject(h, INFINITE)
|
| 196 | #define DbgWaitForMultipleObjects(nCount, lpHandles, bWaitAll) \
|
| 197 | WaitForMultipleObjects(nCount, lpHandles, bWaitAll, INFINITE)
|
| 198 | #define DbgSetWaitTimeout(dwTimeout)
|
| 199 |
|
| 200 | #define KDbgBreak(_x_)
|
| 201 | #define DbgBreak(_x_)
|
| 202 |
|
| 203 | #define KASSERT(_x_) ((void)0)
|
| 204 | #ifndef ASSERT
|
| 205 | #define ASSERT(_x_) ((void)0)
|
| 206 | #endif
|
| 207 | #define EXECUTE_ASSERT(_x_) ((void)(_x_))
|
| 208 |
|
| 209 | // MFC style trace macros
|
| 210 |
|
| 211 | #define NOTE(_x_) ((void)0)
|
| 212 | #define NOTE1(_x_,a) ((void)0)
|
| 213 | #define NOTE2(_x_,a,b) ((void)0)
|
| 214 | #define NOTE3(_x_,a,b,c) ((void)0)
|
| 215 | #define NOTE4(_x_,a,b,c,d) ((void)0)
|
| 216 | #define NOTE5(_x_,a,b,c,d,e) ((void)0)
|
| 217 |
|
| 218 | #define DisplayType(label, pmtIn) ((void)0)
|
| 219 | #define DumpGraph(pGraph, label) ((void)0)
|
| 220 | #endif
|
| 221 |
|
| 222 |
|
| 223 | // Checks a pointer which should be non NULL - can be used as follows.
|
| 224 |
|
| 225 | #define CheckPointer(p,ret) {if((p)==NULL) return (ret);}
|
| 226 |
|
| 227 | // HRESULT Foo(VOID *pBar)
|
| 228 | // {
|
| 229 | // CheckPointer(pBar,E_INVALIDARG)
|
| 230 | // }
|
| 231 | //
|
| 232 | // Or if the function returns a boolean
|
| 233 | //
|
| 234 | // BOOL Foo(VOID *pBar)
|
| 235 | // {
|
| 236 | // CheckPointer(pBar,FALSE)
|
| 237 | // }
|
| 238 |
|
| 239 | #define ValidateReadPtr(p,cb) 0
|
| 240 | #define ValidateWritePtr(p,cb) 0
|
| 241 | #define ValidateReadWritePtr(p,cb) 0
|
| 242 | #define ValidateStringPtr(p) 0
|
| 243 | #define ValidateStringPtrA(p) 0
|
| 244 | #define ValidateStringPtrW(p) 0
|
| 245 |
|
| 246 |
|
| 247 | #ifdef _OBJBASE_H_
|
| 248 |
|
| 249 | // Outputting GUID names. If you want to include the name
|
| 250 | // associated with a GUID (eg CLSID_...) then
|
| 251 | //
|
| 252 | // GuidNames[yourGUID]
|
| 253 | //
|
| 254 | // Returns the name defined in uuids.h as a string
|
| 255 |
|
| 256 | typedef struct {
|
| 257 | CHAR *szName;
|
| 258 | GUID guid;
|
| 259 | } GUID_STRING_ENTRY;
|
| 260 |
|
| 261 | class CGuidNameList {
|
| 262 | public:
|
| 263 | CHAR *operator [] (const GUID& guid);
|
| 264 | };
|
| 265 |
|
| 266 | extern CGuidNameList GuidNames;
|
| 267 |
|
| 268 | #endif
|
| 269 |
|
| 270 | #ifndef REMIND
|
| 271 | // REMIND macro - generates warning as reminder to complete coding
|
| 272 | // (eg) usage:
|
| 273 | //
|
| 274 | // #pragma message (REMIND("Add automation support"))
|
| 275 |
|
| 276 |
|
| 277 | #define QUOTE(x) #x
|
| 278 | #define QQUOTE(y) QUOTE(y)
|
| 279 | #define REMIND(str) __FILE__ "(" QQUOTE(__LINE__) ") : " str
|
| 280 | #endif
|
| 281 |
|
| 282 | // Method to display objects in a useful format
|
| 283 | //
|
| 284 | // eg If you want to display a LONGLONG ll in a debug string do (eg)
|
| 285 | //
|
| 286 | // DbgLog((LOG_TRACE, n, TEXT("Value is %s"), (LPCTSTR)CDisp(ll, CDISP_HEX)));
|
| 287 |
|
| 288 |
|
| 289 | class CDispBasic
|
| 290 | {
|
| 291 | public:
|
| 292 | CDispBasic() { m_pString = m_String; };
|
| 293 | ~CDispBasic();
|
| 294 | protected:
|
| 295 | PTCHAR m_pString; // normally points to m_String... unless too much data
|
| 296 | TCHAR m_String[50];
|
| 297 | };
|
| 298 | class CDisp : public CDispBasic
|
| 299 | {
|
| 300 | public:
|
| 301 | CDisp(LONGLONG ll, int Format = CDISP_HEX); // Display a LONGLONG in CDISP_HEX or CDISP_DEC form
|
| 302 | CDisp(REFCLSID clsid); // Display a GUID
|
| 303 | CDisp(double d); // Display a floating point number
|
| 304 | #ifdef __strmif_h__
|
| 305 | #ifdef __STREAMS__
|
| 306 | CDisp(CRefTime t); // Display a Reference Time
|
| 307 | #endif
|
| 308 | CDisp(IPin *pPin); // Display a pin as {filter clsid}(pin name)
|
| 309 | CDisp(IUnknown *pUnk); // Display a filter or pin
|
| 310 | #endif // __strmif_h__
|
| 311 | ~CDisp();
|
| 312 |
|
| 313 | // Implement cast to (LPCTSTR) as parameter to logger
|
| 314 | operator LPCTSTR()
|
| 315 | {
|
| 316 | return (LPCTSTR)m_pString;
|
| 317 | };
|
| 318 | };
|
| 319 |
|
| 320 |
|
| 321 | #if defined(DEBUG)
|
| 322 | class CAutoTrace
|
| 323 | {
|
| 324 | private:
|
| 325 | LPCTSTR _szBlkName;
|
| 326 | const int _level;
|
| 327 | static const TCHAR _szEntering[];
|
| 328 | static const TCHAR _szLeaving[];
|
| 329 | public:
|
| 330 | CAutoTrace(LPCTSTR szBlkName, const int level = 15)
|
| 331 | : _szBlkName(szBlkName), _level(level)
|
| 332 | {DbgLog((LOG_TRACE, _level, _szEntering, _szBlkName));}
|
| 333 |
|
| 334 | ~CAutoTrace()
|
| 335 | {DbgLog((LOG_TRACE, _level, _szLeaving, _szBlkName));}
|
| 336 | };
|
| 337 |
|
| 338 | #if defined (__FUNCTION__)
|
| 339 |
|
| 340 | #define AMTRACEFN() CAutoTrace __trace(TEXT(__FUNCTION__))
|
| 341 | #define AMTRACE(_x_) CAutoTrace __trace(TEXT(__FUNCTION__))
|
| 342 |
|
| 343 | #else
|
| 344 |
|
| 345 | #define AMTRACE(_x_) CAutoTrace __trace _x_
|
| 346 | #define AMTRACEFN()
|
| 347 |
|
| 348 | #endif
|
| 349 |
|
| 350 | #else
|
| 351 |
|
| 352 | #define AMTRACE(_x_)
|
| 353 | #define AMTRACEFN()
|
| 354 |
|
| 355 | #endif
|
| 356 |
|
| 357 | #endif // __WXDEBUG__
|
| 358 |
|
| 359 |
|