wxdebug.h 12 KB

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