Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

400 lines
12 KiB

  1. /****************************************************************************
  2. Copyright (c) Microsoft Corporation 1997
  3. All rights reserved
  4. File: DEBUG.H
  5. Debugging utilities header
  6. ***************************************************************************/
  7. #ifndef _DEBUG_H_
  8. #define _DEBUG_H_
  9. // Trace Flags
  10. #define TF_ALWAYS 0xFFFFFFFF
  11. #define TF_NEVER 0x00000000
  12. #define TF_QUERYINTERFACE 0x00000001 // Query Interface details
  13. #define TF_FUNC 0x00000002 // Functions entrances w/parameters
  14. #define TF_CALLS 0x00000004 // Function calls
  15. #define TF_MEMORYALLOCS 0x00000008 // Memory Allocations
  16. #define TF_DLL 0x00000010 // DLL specific
  17. #define TF_WM 0x00000020 // Window Messages
  18. #define TF_SCP 0x00000030 // SCP objects
  19. #ifdef DEBUG
  20. #pragma message("BUILD: DEBUG macros being built")
  21. // Globals
  22. extern DWORD g_TraceMemoryIndex;
  23. extern DWORD g_dwCounter;
  24. extern DWORD g_dwTraceFlags;
  25. extern const TCHAR g_szTrue[];
  26. extern const TCHAR g_szFalse[];
  27. // Macros
  28. #define DEFINE_MODULE( _module ) static const TCHAR g_szModule[] = TEXT(_module);
  29. #define __MODULE__ g_szModule
  30. #define DEFINE_THISCLASS( _class ) static const TCHAR g_szClass[] = TEXT(_class);
  31. #define __THISCLASS__ g_szClass
  32. #define DEFINE_SUPER( _super ) static const TCHAR g_szSuper[] = TEXT(_super);
  33. #define __SUPER__ g_szSuper
  34. #if defined(_X86_)
  35. #define DEBUG_BREAK do { _try { _asm int 3 } _except (EXCEPTION_EXECUTE_HANDLER) {;} } while (0)
  36. #else
  37. #define DEBUG_BREAK DebugBreak( );
  38. #endif
  39. #define INITIALIZE_TRACE_MEMORY_PROCESS \
  40. g_TraceMemoryIndex = TlsAlloc( ); \
  41. TlsSetValue( g_TraceMemoryIndex, NULL); \
  42. TraceMessage( TEXT(__FILE__), __LINE__, g_szModule, TF_DLL, TEXT("Thread Memory tracing initialize.\n") )
  43. #define INITIALIZE_TRACE_MEMORY_THREAD \
  44. TlsSetValue( g_TraceMemoryIndex, NULL); \
  45. TraceMessage( TEXT(__FILE__), __LINE__, g_szModule, TF_DLL, TEXT("Thread Memory tracing initialize.\n") )
  46. #define UNINITIALIZE_TRACE_MEMORY \
  47. DebugMemoryCheck( ); \
  48. TraceMessage( TEXT(__FILE__), __LINE__, g_szModule, TF_DLL, TEXT("Memory tracing terminated.\n") )
  49. #ifdef Assert
  50. #undef Assert
  51. #endif
  52. #define Assert( _fn ) \
  53. if ( !(_fn) && AssertMessage( TEXT(__FILE__), __LINE__, g_szModule, TEXT(#_fn), !!(_fn) ) ) DEBUG_BREAK
  54. #ifdef AssertMsg
  55. #undef AssertMsg
  56. #endif
  57. #define AssertMsg( _fn, _msg ) \
  58. if ( !(_fn) && AssertMessage( TEXT(__FILE__), __LINE__, g_szModule, TEXT(_msg), !!(_fn) ) ) DEBUG_BREAK
  59. #define TraceAlloc( _flags, _size ) DebugAlloc( TEXT(__FILE__), __LINE__, g_szModule, _flags, _size, TEXT(#_size) )
  60. #define TraceAllocString( _flags, _size ) DebugAlloc( TEXT(__FILE__), __LINE__, g_szModule, _flags, (_size) * sizeof(TCHAR), TEXT(#_size) )
  61. #define TraceFree( _hmem ) DebugFree( _hmem )
  62. //
  63. // Tracing Macros
  64. //
  65. // All functions that begin with "Trace" are in both DEBUG and RETAIL, but
  66. // in RETAIL they do not spew output.
  67. //
  68. // Displays file, line number, module and "_msg" only if the TF_FUNC is set
  69. // in g_dwTraceFlags.
  70. #define TraceFunc( _msg ) \
  71. InterlockIncrement(g_dwCounter); \
  72. TraceMessage( TEXT(__FILE__), __LINE__, g_szModule, TF_FUNC, TEXT("+ ") TEXT(_msg) );
  73. // Displays file, line number, module, class name and "_msg" only if the
  74. // TF_FUNC is set in g_dwTraceFlags.
  75. #define TraceClsFunc( _msg ) \
  76. InterlockIncrement(g_dwCounter); \
  77. TraceMessage( TEXT(__FILE__), __LINE__, g_szModule, TF_FUNC, TEXT("+ %s::%s"), g_szClass, TEXT(_msg) );
  78. // Return macro for TraceFunc() and TraceClsFunc()
  79. #define TraceFuncExit() { \
  80. TraceMessage( TEXT(__FILE__), __LINE__, g_szModule, TF_FUNC, TEXT("V*\n") ); \
  81. InterlockDecrement(g_dwCounter); \
  82. return; \
  83. }
  84. #define RETURN( _rval ) { \
  85. TraceMessage( TEXT(__FILE__), __LINE__, g_szModule, TF_FUNC, TEXT("V\n") ); \
  86. InterlockDecrement(g_dwCounter); \
  87. return _rval; \
  88. }
  89. // If the value is not S_OK, it will display it.
  90. #define HRETURN( _hr ) { \
  91. if ( _hr ) \
  92. TraceMessage( TEXT(__FILE__), __LINE__, g_szModule, TF_FUNC, TEXT("V hr = 0x%08x\n"), _hr ); \
  93. else \
  94. TraceMessage( TEXT(__FILE__), __LINE__, g_szModule, TF_FUNC, TEXT("V\n") ); \
  95. InterlockDecrement(g_dwCounter); \
  96. return _hr; \
  97. }
  98. // Displays the file, line number, module and function call and return from the
  99. // function call (no return value displayed) for "_fn" only if the TF_CALLS is
  100. // set in g_dwTraceFlags.
  101. #define TraceDo( _fn ) {\
  102. InterlockIncrement(g_dwCounter); \
  103. TraceMessage( TEXT(__FILE__), __LINE__, g_szModule, TF_CALLS, TEXT("+ %s\n"), TEXT(#_fn) ); \
  104. _fn; \
  105. TraceMessage( TEXT(__FILE__), __LINE__, g_szModule, TF_CALLS, TEXT("V\n") ); \
  106. InterlockDecrement(g_dwCounter); \
  107. }
  108. // Displays the file, line number, module and function call and return value
  109. // which is formatted in "_msg" for "_fn" only if the TF_CALLS is set in
  110. // g_dwTraceFlags.
  111. #define TraceMsgDo( _fn, _msg ) {\
  112. InterlockIncrement(g_dwCounter); \
  113. TraceMessage( TEXT(__FILE__), __LINE__, g_szModule, TF_CALLS, TEXT("+ %s\n"), TEXT(#_fn) ); \
  114. TraceMessageDo( TEXT(__FILE__), __LINE__, g_szModule, TF_CALLS, TEXT(_msg), TEXT(#_fn), _fn ); \
  115. InterlockDecrement(g_dwCounter); \
  116. }
  117. // This functions only asserts if the result is ZERO.
  118. #define TraceAssertIfZero( _fn ) \
  119. if ( !(_fn) && AssertMessage( TEXT(__FILE__), __LINE__, g_szModule, TEXT(#_fn), !!(_fn) ) ) DEBUG_BREAK
  120. #define TraceMsgGUID( _flag, _guid ) \
  121. TraceMsg( _flag, TEXT("{%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x}"), \
  122. _guid.Data1, _guid.Data2, _guid.Data3, \
  123. _guid.Data4[0], _guid.Data4[1], _guid.Data4[2], _guid.Data4[3], \
  124. _guid.Data4[4], _guid.Data4[5], _guid.Data4[6], _guid.Data4[7] )
  125. #define ErrorMsg( _fmt, _arg ) \
  126. TraceMessage( TEXT(__FILE__), __LINE__, g_szModule, TF_ALWAYS, TEXT(_fmt), _arg );
  127. //
  128. // Debug Macros
  129. //
  130. // These calls are only compiled in DEBUG. They are a NOP in RETAIL (not even
  131. // compiled in.
  132. //
  133. // Same as TraceDo() but only compiled in DEBUG.
  134. #define DebugDo( _fn ) {\
  135. InterlockIncrement(g_dwCounter); \
  136. DebugMessage( TEXT(__FILE__), __LINE__, g_szModule, TEXT("+ %s\n"), TEXT(#_fn) ); \
  137. _fn; \
  138. DebugMessage( TEXT(__FILE__), __LINE__, g_szModule, TEXT("V\n") ); \
  139. InterlockDecrement(g_dwCounter); \
  140. }
  141. // Same as TraceMsgDo() but only compiled in DEBUG.
  142. #define DebugMsgDo( _fn, _msg ) {\
  143. InterlockIncrement(g_dwCounter); \
  144. DebugMessage( TEXT(__FILE__), __LINE__, g_szModule, TEXT("+ %s\n"), TEXT(#_fn) ); \
  145. DebugMessageDo( TEXT(__FILE__), __LINE__, g_szModule, TEXT(_msg), TEXT(#_fn), _fn); \
  146. InterlockDecrement(g_dwCounter); \
  147. }
  148. //
  149. // HRESULT testing macros
  150. //
  151. // These functions check HRESULT return values and display UI if conditions
  152. // warrant only in DEBUG.
  153. //
  154. // Warning is display if HRESULT is anything but S_OK (0).
  155. #define THR( _fn ) \
  156. TraceHR( TEXT(__FILE__), __LINE__, g_szModule, TEXT(#_fn), _fn )
  157. // Warning is display if HRESULT is anything but S_OK (0).
  158. #define RRETURN( _fn ) { \
  159. RETURN( TraceHR( TEXT(__FILE__), __LINE__, g_szModule, TEXT(#_fn), _fn ) ); \
  160. }
  161. // Warning is display if HRESULT is anything but S_OK (0) only if
  162. // TF_QUERYINTERFACE is set in g_dwTraceFlags, otherwise only a debug message
  163. // will be printed.
  164. #define QIRETURN( _fn, _riid ) { \
  165. if ( !!( TF_QUERYINTERFACE & g_dwTraceFlags ) ) { \
  166. RETURN(TraceHR( TEXT(__FILE__), __LINE__, g_szModule, TEXT(#_fn), _fn )); \
  167. } else if ( hr ) \
  168. DebugMessage( TEXT(__FILE__), __LINE__, g_szModule, TEXT("HRESULT: QueryInterface({%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x}) failed()\n"), _riid.Data1, _riid.Data2, _riid.Data3, _riid.Data4[0], _riid.Data4[1], _riid.Data4[2], _riid.Data4[3], _riid.Data4[4], _riid.Data4[5], _riid.Data4[6], _riid.Data4[7] ); \
  169. RETURN(_fn); \
  170. }
  171. // Warning is display if HRESULT is not S_OK (0) or "_ok".
  172. #define RRETURN1( _hr, _ok ) {\
  173. RETURN(TraceHR( TEXT(__FILE__), __LINE__, g_szModule, TEXT(#_hr), \
  174. ( ( _hr == _ok ) ? S_OK : _hr ) ) ); \
  175. }
  176. //
  177. // Other
  178. //
  179. #define BOOLTOSTRING( _fBool ) ( !!(_fBool) ? g_szTrue : g_szFalse )
  180. //
  181. // Trace/Debug Functions - these do not exist in RETAIL.
  182. //
  183. void
  184. TraceMsg(
  185. DWORD dwCheckFlags,
  186. LPCSTR pszFormat,
  187. ... );
  188. void
  189. TraceMsg(
  190. DWORD dwCheckFlags,
  191. LPCWSTR pszFormat,
  192. ... );
  193. void
  194. DebugMsg(
  195. LPCSTR pszFormat,
  196. ... );
  197. void
  198. DebugMsg(
  199. LPCWSTR pszFormat,
  200. ... );
  201. void
  202. TraceMessage(
  203. LPCTSTR pszFile,
  204. const int uLine,
  205. LPCTSTR pszModule,
  206. DWORD dwCheckFlags,
  207. LPCTSTR pszFormat,
  208. ... );
  209. void
  210. TraceMessageDo(
  211. LPCTSTR pszFile,
  212. const int uLine,
  213. LPCTSTR pszModule,
  214. DWORD dwCheckFlags,
  215. LPCTSTR pszFormat,
  216. LPCTSTR pszFunc,
  217. ... );
  218. void
  219. DebugMessage(
  220. LPCTSTR pszFile,
  221. const int uLine,
  222. LPCTSTR pszModule,
  223. LPCTSTR pszFormat,
  224. ... );
  225. void
  226. DebugMessageDo(
  227. LPCTSTR pszFile,
  228. const int uLine,
  229. LPCTSTR pszModule,
  230. LPCTSTR pszFormat,
  231. LPCTSTR pszFunc,
  232. ... );
  233. BOOL
  234. AssertMessage(
  235. LPCTSTR pszFile,
  236. const int uLine,
  237. LPCTSTR pszModule,
  238. LPCTSTR pszfn,
  239. BOOL fTrue );
  240. HRESULT
  241. TraceHR(
  242. LPCTSTR pszFile,
  243. const int uLine,
  244. LPCTSTR pszModule,
  245. LPCTSTR pszfn,
  246. HRESULT hr );
  247. //
  248. // Memory tracing functions - these are remapped to the "Global" memory
  249. // functions when in RETAIL.
  250. //
  251. HGLOBAL
  252. DebugAlloc(
  253. LPCTSTR pszFile,
  254. const int uLine,
  255. LPCTSTR pszModule,
  256. UINT uFlags,
  257. DWORD dwBytes,
  258. LPCTSTR pszComment );
  259. HGLOBAL
  260. DebugFree(
  261. HGLOBAL hMem );
  262. // The memory functions don't exist in RETAIL.
  263. HGLOBAL
  264. DebugMemoryAdd(
  265. HGLOBAL hglobal,
  266. LPCTSTR pszFile,
  267. const int uLine,
  268. LPCTSTR pszModule,
  269. UINT uFlags,
  270. DWORD dwBytes,
  271. LPCTSTR pszComment );
  272. #define DebugMemoryAddHandle( _handle ) \
  273. DebugMemoryAdd( _handle, TEXT(__FILE__), __LINE__, __MODULE__, GMEM_MOVEABLE, 0, TEXT(#_handle) );
  274. #define DebugMemoryAddAddress( _pv ) \
  275. DebugMemoryAdd( _pv, TEXT(__FILE__), __LINE__, __MODULE__, GMEM_FIXED, 0, TEXT(#_pv) );
  276. #define TraceStrDup( _sz ) \
  277. DebugMemoryAdd( StrDup( _sz ), TEXT(__FILE__), __LINE__, __MODULE__, GMEM_FIXED, 0, TEXT("StrDup(") TEXT(#_sz) TEXT(")") );
  278. void
  279. DebugMemoryDelete(
  280. HGLOBAL hglobal );
  281. void
  282. DebugMemoryCheck( );
  283. #ifdef __cplusplus
  284. extern void* __cdecl operator new( size_t nSize, LPCTSTR pszFile, const int iLine, LPCTSTR pszModule );
  285. #define new new( TEXT(__FILE__), __LINE__, __MODULE__ )
  286. #endif
  287. //
  288. //
  289. #else // it's RETAIL ******************************************************
  290. //
  291. //
  292. // Debugging -> NOPs
  293. #define Assert( _fn )
  294. #define DebugDo( _fn )
  295. #define DebugMsgDo( _fn, _msg )
  296. #define DEFINE_MODULE( _module )
  297. #define DEFINE_THISCLASS( _class )
  298. #define DEFINE_SUPER( _super )
  299. #define BOOLTOSTRING( _fBool ) NULL
  300. #define AssertMsg 1 ? (void)0 : (void)
  301. #define TraceMsg 1 ? (void)0 : (void)
  302. #define TraceMsgGUID( _f, _g )
  303. #define DebugMsg 1 ? (void)0 : (void)
  304. #define ErrorMsg 1 ? (void)0 : (void)
  305. #define TraceMessage 1 ? (void)0 : (void)
  306. #define DebugMessage 1 ? (void)0 : (void)
  307. #define AssertMessage 1 ? (void)0 : (void)
  308. #define TraceHR 1 ? (void)0 : (void)
  309. #define TraceFunc 1 ? (void)0 : (void)
  310. #define TraceClsFunc 1 ? (void)0 : (void)
  311. #define TraceFuncExit()
  312. #define DebugMemoryAddHandle( _handle )
  313. #define DebugMemoryAddAddress( _pv )
  314. #define INITIALIZE_TRACE_MEMORY_PROCESS
  315. #define INITIALIZE_TRACE_MEMORY_THREAD
  316. #define UNINITIALIZE_TRACE_MEMORY
  317. #define DebugMemoryDelete( _h )
  318. // Tracing -> just do operation
  319. #define TraceDo( _fn ) _fn
  320. #define TraceMsgDo( _fn, _msg ) _fn
  321. #define TraceAssertIfZero( _fn ) _fn
  322. // RETURN testing -> do retail
  323. #define THR
  324. #define RETURN( _fn ) return _fn
  325. #define RRETURN( _fn ) return _fn
  326. #define HRETURN( _hr ) return _hr
  327. #define QIRETURN( _qi, _riid ) return _qi
  328. // Memory Functions -> do retail
  329. #define TraceAlloc( _flags, _size ) GlobalAlloc( _flags, _size )
  330. #define TraceAllocString( _flags, _size ) GlobalAlloc( _flags, (_size) * sizeof(TCHAR) )
  331. #define TraceFree( _pv ) GlobalFree( _pv )
  332. #define TraceStrDup( _sz ) StrDup( _sz )
  333. #endif // DBG==1
  334. #endif // _DEBUG_H_