wxdebug.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  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. };
  54. // For each object created derived from CBaseObject (in debug builds) we
  55. // create a descriptor that holds it's name (statically allocated memory)
  56. // and a cookie we assign it. We keep a list of all the active objects
  57. // we have registered so that we can dump a list of remaining objects
  58. typedef struct tag_ObjectDesc {
  59. LPCSTR m_szName;
  60. LPCWSTR m_wszName;
  61. DWORD m_dwCookie;
  62. tag_ObjectDesc *m_pNext;
  63. } ObjectDesc;
  64. #define DLLIMPORT __declspec(dllimport)
  65. #define DLLEXPORT __declspec(dllexport)
  66. #ifdef DEBUG
  67. #define NAME(x) TEXT(x)
  68. // These are used internally by the debug library (PRIVATE)
  69. void WINAPI DbgInitKeyLevels(HKEY hKey, bool fTakeMax);
  70. void WINAPI DbgInitGlobalSettings(bool fTakeMax);
  71. void WINAPI DbgInitModuleSettings(bool fTakeMax);
  72. void WINAPI DbgInitModuleName();
  73. DWORD WINAPI DbgRegisterObjectCreation(
  74. LPCSTR szObjectName, LPCWSTR wszObjectName);
  75. BOOL WINAPI DbgRegisterObjectDestruction(DWORD dwCookie);
  76. // These are the PUBLIC entry points
  77. BOOL WINAPI DbgCheckModuleLevel(DWORD Type,DWORD Level);
  78. void WINAPI DbgSetModuleLevel(DWORD Type,DWORD Level);
  79. void WINAPI DbgSetAutoRefreshLevels(bool fAuto);
  80. // Initialise the library with the module handle
  81. void WINAPI DbgInitialise(HINSTANCE hInst);
  82. void WINAPI DbgTerminate();
  83. void WINAPI DbgDumpObjectRegister();
  84. // Display error and logging to the user
  85. void WINAPI DbgAssert(LPCTSTR pCondition,LPCTSTR pFileName,INT iLine);
  86. void WINAPI DbgBreakPoint(LPCTSTR pCondition,LPCTSTR pFileName,INT iLine);
  87. void WINAPI DbgBreakPoint(LPCTSTR pFileName,INT iLine,__format_string LPCTSTR szFormatString,...);
  88. void WINAPI DbgKernelAssert(LPCTSTR pCondition,LPCTSTR pFileName,INT iLine);
  89. void WINAPI DbgLogInfo(DWORD Type,DWORD Level,__format_string LPCTSTR pFormat,...);
  90. #ifdef UNICODE
  91. void WINAPI DbgLogInfo(DWORD Type,DWORD Level,__format_string LPCSTR pFormat,...);
  92. void WINAPI DbgAssert(LPCSTR pCondition,LPCSTR pFileName,INT iLine);
  93. void WINAPI DbgBreakPoint(LPCSTR pCondition,LPCSTR pFileName,INT iLine);
  94. void WINAPI DbgKernelAssert(LPCSTR pCondition,LPCSTR pFileName,INT iLine);
  95. #endif
  96. void WINAPI DbgOutString(LPCTSTR psz);
  97. // Debug infinite wait stuff
  98. DWORD WINAPI DbgWaitForSingleObject(HANDLE h);
  99. DWORD WINAPI DbgWaitForMultipleObjects(DWORD nCount,
  100. __in_ecount(nCount) CONST HANDLE *lpHandles,
  101. BOOL bWaitAll);
  102. void WINAPI DbgSetWaitTimeout(DWORD dwTimeout);
  103. #ifdef __strmif_h__
  104. // Display a media type: Terse at level 2, verbose at level 5
  105. void WINAPI DisplayType(LPCTSTR label, const AM_MEDIA_TYPE *pmtIn);
  106. // Dump lots of information about a filter graph
  107. void WINAPI DumpGraph(IFilterGraph *pGraph, DWORD dwLevel);
  108. #endif
  109. #define KASSERT(_x_) if (!(_x_)) \
  110. DbgKernelAssert(TEXT(#_x_),TEXT(__FILE__),__LINE__)
  111. // Break on the debugger without putting up a message box
  112. // message goes to debugger instead
  113. #define KDbgBreak(_x_) \
  114. DbgKernelAssert(TEXT(#_x_),TEXT(__FILE__),__LINE__)
  115. // We chose a common name for our ASSERT macro, MFC also uses this name
  116. // So long as the implementation evaluates the condition and handles it
  117. // then we will be ok. Rather than override the behaviour expected we
  118. // will leave whatever first defines ASSERT as the handler (i.e. MFC)
  119. #ifndef ASSERT
  120. #define ASSERT(_x_) if (!(_x_)) \
  121. DbgAssert(TEXT(#_x_),TEXT(__FILE__),__LINE__)
  122. #endif
  123. #define DbgAssertAligned( _ptr_, _alignment_ ) ASSERT( ((DWORD_PTR) (_ptr_)) % (_alignment_) == 0)
  124. // Put up a message box informing the user of a halt
  125. // condition in the program
  126. #define DbgBreak(_x_) \
  127. DbgBreakPoint(TEXT(#_x_),TEXT(__FILE__),__LINE__)
  128. #define EXECUTE_ASSERT(_x_) ASSERT(_x_)
  129. #define DbgLog(_x_) DbgLogInfo _x_
  130. // MFC style trace macros
  131. #define NOTE(_x_) DbgLog((LOG_TRACE,5,TEXT(_x_)))
  132. #define NOTE1(_x_,a) DbgLog((LOG_TRACE,5,TEXT(_x_),a))
  133. #define NOTE2(_x_,a,b) DbgLog((LOG_TRACE,5,TEXT(_x_),a,b))
  134. #define NOTE3(_x_,a,b,c) DbgLog((LOG_TRACE,5,TEXT(_x_),a,b,c))
  135. #define NOTE4(_x_,a,b,c,d) DbgLog((LOG_TRACE,5,TEXT(_x_),a,b,c,d))
  136. #define NOTE5(_x_,a,b,c,d,e) DbgLog((LOG_TRACE,5,TEXT(_x_),a,b,c,d,e))
  137. #else
  138. // Retail builds make public debug functions inert - WARNING the source
  139. // files do not define or build any of the entry points in debug builds
  140. // (public entry points compile to nothing) so if you go trying to call
  141. // any of the private entry points in your source they won't compile
  142. #define NAME(_x_) ((LPTSTR) NULL)
  143. #define DbgInitialise(hInst)
  144. #define DbgTerminate()
  145. #define DbgLog(_x_) 0
  146. #define DbgOutString(psz)
  147. #define DbgAssertAligned( _ptr_, _alignment_ ) 0
  148. #define DbgRegisterObjectCreation(pObjectName)
  149. #define DbgRegisterObjectDestruction(dwCookie)
  150. #define DbgDumpObjectRegister()
  151. #define DbgCheckModuleLevel(Type,Level)
  152. #define DbgSetModuleLevel(Type,Level)
  153. #define DbgSetAutoRefreshLevels(fAuto)
  154. #define DbgWaitForSingleObject(h) WaitForSingleObject(h, INFINITE)
  155. #define DbgWaitForMultipleObjects(nCount, lpHandles, bWaitAll) \
  156. WaitForMultipleObjects(nCount, lpHandles, bWaitAll, INFINITE)
  157. #define DbgSetWaitTimeout(dwTimeout)
  158. #define KDbgBreak(_x_)
  159. #define DbgBreak(_x_)
  160. #define KASSERT(_x_) ((void)0)
  161. #ifndef ASSERT
  162. #define ASSERT(_x_) ((void)0)
  163. #endif
  164. #define EXECUTE_ASSERT(_x_) ((void)(_x_))
  165. // MFC style trace macros
  166. #define NOTE(_x_) ((void)0)
  167. #define NOTE1(_x_,a) ((void)0)
  168. #define NOTE2(_x_,a,b) ((void)0)
  169. #define NOTE3(_x_,a,b,c) ((void)0)
  170. #define NOTE4(_x_,a,b,c,d) ((void)0)
  171. #define NOTE5(_x_,a,b,c,d,e) ((void)0)
  172. #define DisplayType(label, pmtIn) ((void)0)
  173. #define DumpGraph(pGraph, label) ((void)0)
  174. #endif
  175. // Checks a pointer which should be non NULL - can be used as follows.
  176. #define CheckPointer(p,ret) {if((p)==NULL) return (ret);}
  177. // HRESULT Foo(VOID *pBar)
  178. // {
  179. // CheckPointer(pBar,E_INVALIDARG)
  180. // }
  181. //
  182. // Or if the function returns a boolean
  183. //
  184. // BOOL Foo(VOID *pBar)
  185. // {
  186. // CheckPointer(pBar,FALSE)
  187. // }
  188. #define ValidateReadPtr(p,cb) 0
  189. #define ValidateWritePtr(p,cb) 0
  190. #define ValidateReadWritePtr(p,cb) 0
  191. #define ValidateStringPtr(p) 0
  192. #define ValidateStringPtrA(p) 0
  193. #define ValidateStringPtrW(p) 0
  194. #ifdef _OBJBASE_H_
  195. // Outputting GUID names. If you want to include the name
  196. // associated with a GUID (eg CLSID_...) then
  197. //
  198. // GuidNames[yourGUID]
  199. //
  200. // Returns the name defined in uuids.h as a string
  201. typedef struct {
  202. CHAR *szName;
  203. GUID guid;
  204. } GUID_STRING_ENTRY;
  205. class CGuidNameList
  206. {
  207. public:
  208. CHAR *operator [] (const GUID& guid);
  209. };
  210. extern CGuidNameList GuidNames;
  211. #endif
  212. #ifndef REMIND
  213. // REMIND macro - generates warning as reminder to complete coding
  214. // (eg) usage:
  215. //
  216. // #pragma message (REMIND("Add automation support"))
  217. #define QUOTE(x) #x
  218. #define QQUOTE(y) QUOTE(y)
  219. #define REMIND(str) __FILE__ "(" QQUOTE(__LINE__) ") : " str
  220. #endif
  221. // Method to display objects in a useful format
  222. //
  223. // eg If you want to display a LONGLONG ll in a debug string do (eg)
  224. //
  225. // DbgLog((LOG_TRACE, n, TEXT("Value is %s"), (LPCTSTR)CDisp(ll, CDISP_HEX)));
  226. class CDispBasic
  227. {
  228. public:
  229. CDispBasic() {
  230. m_pString = m_String;
  231. };
  232. ~CDispBasic();
  233. protected:
  234. PTCHAR m_pString; // normally points to m_String... unless too much data
  235. TCHAR m_String[50];
  236. };
  237. class CDisp : public CDispBasic
  238. {
  239. public:
  240. CDisp(LONGLONG ll, int Format = CDISP_HEX); // Display a LONGLONG in CDISP_HEX or CDISP_DEC form
  241. CDisp(REFCLSID clsid); // Display a GUID
  242. CDisp(double d); // Display a floating point number
  243. #ifdef __strmif_h__
  244. #ifdef __STREAMS__
  245. CDisp(CRefTime t); // Display a Reference Time
  246. #endif
  247. CDisp(IPin *pPin); // Display a pin as {filter clsid}(pin name)
  248. CDisp(IUnknown *pUnk); // Display a filter or pin
  249. #endif // __strmif_h__
  250. ~CDisp();
  251. // Implement cast to (LPCTSTR) as parameter to logger
  252. operator LPCTSTR() {
  253. return (LPCTSTR)m_pString;
  254. };
  255. };
  256. #if defined(DEBUG)
  257. class CAutoTrace
  258. {
  259. private:
  260. LPCTSTR _szBlkName;
  261. const int _level;
  262. static const TCHAR _szEntering[];
  263. static const TCHAR _szLeaving[];
  264. public:
  265. CAutoTrace(LPCTSTR szBlkName, const int level = 15)
  266. : _szBlkName(szBlkName), _level(level) {
  267. DbgLog((LOG_TRACE, _level, _szEntering, _szBlkName));
  268. }
  269. ~CAutoTrace() {
  270. DbgLog((LOG_TRACE, _level, _szLeaving, _szBlkName));
  271. }
  272. };
  273. #if defined (__FUNCTION__)
  274. #define AMTRACEFN() CAutoTrace __trace(TEXT(__FUNCTION__))
  275. #define AMTRACE(_x_) CAutoTrace __trace(TEXT(__FUNCTION__))
  276. #else
  277. #define AMTRACE(_x_) CAutoTrace __trace _x_
  278. #define AMTRACEFN()
  279. #endif
  280. #else
  281. #define AMTRACE(_x_)
  282. #define AMTRACEFN()
  283. #endif
  284. #endif // __WXDEBUG__