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.

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