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.

435 lines
18 KiB

  1. #ifndef _INC_DSKQUOTA_DEBUG_H
  2. #define _INC_DSKQUOTA_DEBUG_H
  3. ///////////////////////////////////////////////////////////////////////////////
  4. /* File: debug.h
  5. Description: Provides debugging macros to support tracing, debugger print
  6. statements, error message debugger output and assertions.
  7. I'm sure you're saying "why ANOTHER debugger output implementation".
  8. There are many around but I haven't found one that is as flexible and
  9. consistent as I would like. This library suports the concept of
  10. both functional "masks" and detail "levels" to control the quantity
  11. of debugger output.
  12. Masks let you control debugger output based on program function. For
  13. instance, if you tag a DBGPRINT statement with the mask DM_XYZ, it
  14. will only be activated if the global variable DebugParams::PrintMask
  15. has the DM_XYZ bit set.
  16. Levels let you control debugger output based on a level of desired
  17. detail. Sometimes you just want to see the basic functions happening
  18. but other times, you need to see everything that's going on. This
  19. leveling allows you to specify at which level a macro is enabled.
  20. The library is designed to be activated with the DEBUG macro.
  21. If DBG is not defined as 1, there is no trace of this code in your
  22. product.
  23. Revision History:
  24. Date Description Programmer
  25. -------- --------------------------------------------------- ----------
  26. 01/19/98 Replaced module with version from CSC cache viewer. BrianAu
  27. */
  28. ///////////////////////////////////////////////////////////////////////////////
  29. #if DBG // Only include file contents if DBG is defined as 1.
  30. # ifndef STRICT
  31. # define STRICT // STRICT is required
  32. # endif
  33. # ifndef _WINDOWS_
  34. # include <windows.h>
  35. # endif
  36. # ifndef _INC_STDARG
  37. # include <stdarg.h> // For va_list stuff.
  38. # endif
  39. //
  40. // If DBG is NOT defined as 1, none of this is included in your source.
  41. // The library is designed so that without DBG defined as 1, there is no trace of
  42. // this code in your product.
  43. //
  44. // The following 4 macros are placed in the program to generate debugger output.
  45. //
  46. // DBGTRACE - Place at entry to function. Will print message on entry and on exit.
  47. // DBGPRINT - For printing general program status messages to debugger.
  48. // DBGERROR - For printing error messages to debugger.
  49. // DBGASSERT - Conventional assert macro.
  50. //
  51. // There are a couple of forms for the DBGTRACE and DBGPRINT macros. The most
  52. // basic form, assumes a mask of -1 and a level of 0. This ensures the macro is
  53. // enabled if any bit in the associated DebugParams mask is set and the associated
  54. // DebugParams level is greater than 0. The second version allows you to explicitly
  55. // set the mask and level for the specific macro.
  56. //
  57. // DBGTRACE((TEXT("MyFunction")));
  58. // DBGPRINT((TEXT("Thread ID = %d"), GetCurrentThreadId()));
  59. // | |
  60. // +------- All args enclosed in parens (1) ----+
  61. //
  62. // or:
  63. //
  64. // DBGTRACE((DM_REGISTRY, 2, TEXT("MyFunction")));
  65. // DBGPRINT((DM_REGISTRY, 2, TEXT("Thread ID = %d"), GetCurrentThreadId()));
  66. // | |
  67. // | +-- Level
  68. // +-- Mask
  69. //
  70. //
  71. // (1) So that no debug code is included in your retail product when DBG is not
  72. // defined as 1, the entire set of arguments to the DBGTRACE, DBGPRINT and DBGERROR macros
  73. // must be enclosed in parentheses. This produces a single argument to the macro
  74. // which can be eliminated when DBG is not defined as 1 (See example above).
  75. //
  76. // The DBGERROR and DBGASSERT macros do not take mask and level arguments. The
  77. // mask is fixed at -1 and the level is fixed at 0 for both.
  78. //
  79. //
  80. #define DBGTRACE(x) DebugTrace _TraceThis(TEXT(__FILE__), __LINE__); _TraceThis.Enter x
  81. #define DBGPRINT(x) DebugPrint(DebugParams::ePrint, TEXT(__FILE__),__LINE__).Print x
  82. #define DBGERROR(x) DebugError(TEXT(__FILE__),__LINE__).Error x
  83. #define DBGASSERT(test) ((test) ? (void)0 : DebugAssert(TEXT(__FILE__),__LINE__, TEXT("Assert failed: \"")TEXT(#test)TEXT("\"")))
  84. //
  85. // The following macros set the global control variables that affect the 4 debugger
  86. // output macros. All they do is set the static values in the DebugParams class.
  87. // By default, DBGTRACE and DBGPRINT are silent. You must activate them with the
  88. // appropriate DBGxxxxxMASK macro. DBGTRACE and DBGASSERT are always active whenever
  89. // DBG is defined as 1.
  90. //
  91. // DBGMODULE - Sets the "module name" included in debugger output.
  92. // DBGPRINTMASK - Sets the "mask" value applied to DBGPRINT macros.
  93. // DBGPRINTLEVEL - Sets the "level" value applied to DBGPRINT macros.
  94. // DBGPRINTVERBOSE - Controls if DBGPRINT output includes filename and line no.
  95. // DBGTRACEMASK - Sets the "mask" value applied to DBGTRACE macros.
  96. // DBGTRACELEVEL - Sets the "level" value applied to DBGTRACE macros.
  97. // DBGTRACEVERBOSE - Controls if DBGTRACE output includes filename and line no.
  98. // This is helpful if you're tracing overloaded C++ functions.
  99. // DBGMASK - Sets the "mask" for both DBGPRINT and DBGTRACE macros.
  100. // Same as calling DBGPRINTMASK(x) and DBGTRACEMASK(x)
  101. // DBGLEVEL - Sets the "level" for both DBGPRINT and DBGTRACE macros.
  102. // Same as calling DBGPRINTLEVEL(x) and DBGTRACELEVEL(x)
  103. // DBGVERBOSE - Sets the "verbose" flag for both DBGPRINT and DBGTRACE macros.
  104. // Same as calling DBGPRINTVERBOSE(x) and DBGTRACEVERBOSE(x)
  105. // DBGTRACEONEXIT - Enables DBGTRACE output on exit from functions.
  106. //
  107. #define DBGMODULE(modname) DebugParams::SetModule(modname)
  108. #define DBGPRINTMASK(mask) DebugParams::SetPrintMask((ULONGLONG)mask)
  109. #define DBGPRINTLEVEL(level) DebugParams::SetPrintLevel(level)
  110. #define DBGPRINTVERBOSE(tf) DebugParams::SetPrintVerbose(tf)
  111. #define DBGTRACEMASK(mask) DebugParams::SetTraceMask((ULONGLONG)mask)
  112. #define DBGTRACELEVEL(level) DebugParams::SetTraceLevel(level)
  113. #define DBGTRACEVERBOSE(tf) DebugParams::SetTraceVerbose(tf)
  114. #define DBGMASK(mask) DebugParams::SetDebugMask((ULONGLONG)mask);
  115. #define DBGLEVEL(level) DebugParams::SetDebugLevel(level);
  116. #define DBGVERBOSE(tf) DebugParams::SetDebugVerbose(tf);
  117. #define DBGTRACEONEXIT(tf) DebugParams::SetTraceOnExit(tf);
  118. //
  119. // Pre-defined debug "levels".
  120. // You can use whatever level values you want. I've found that using more
  121. // than 3 is confusing. Basically, you want to define macro levels as
  122. // "show me fundamental stuff", "show me more detail" and "show me everything".
  123. // These three macros make it easier to stick to 3 levels.
  124. // "DL_" = "Debug Level"
  125. //
  126. #define DL_HIGH 0 // "Show me fundamental stuff" - high priority
  127. #define DL_MID 1 // "Show me more detail" - mid priority
  128. #define DL_LOW 2 // "Show me everything" - low priority
  129. //
  130. // Some pre-defined debug mask values that I thought might be useful.
  131. // These are not application-specific. You can interpret them as you
  132. // wish. I've listed my interpretation in the comments. In general,
  133. // application function-specific mask values are more useful. For
  134. // example, you might create one called DM_DUMPSYMTAB to dump the
  135. // contents of a symbol table at a specific point during execution.
  136. // Create new mask values using the DBGCREATEMASK(x) macro defined below.
  137. // "DM_" = "Debug Mask"
  138. //
  139. #define DM_NONE (ULONGLONG)0x0000000000000000 // No debugging.
  140. #define DM_NOW (ULONGLONG)0x0000000000000001 // Activate temporarily
  141. #define DM_CTOR (ULONGLONG)0x0000000000000002 // C++ ctors and dtors
  142. #define DM_REG (ULONGLONG)0x0000000000000004 // Registry functions.
  143. #define DM_FILE (ULONGLONG)0x0000000000000008 // File accesses.
  144. #define DM_GDI (ULONGLONG)0x0000000000000010 // GDI functions.
  145. #define DM_MEM (ULONGLONG)0x0000000000000011 // Memory functions.
  146. #define DM_NET (ULONGLONG)0x0000000000000012 // Network functions.
  147. #define DM_WEB (ULONGLONG)0x0000000000000014 // Web browsing functions.
  148. #define DM_DLG (ULONGLONG)0x0000000000000018 // Dialog messages.
  149. #define DM_WND (ULONGLONG)0x0000000000000020 // Window messages.
  150. #define DM_ALL (ULONGLONG)0xffffffffffffffff // Activate always.
  151. //
  152. // Lower 16 bits reserved for pre-defined mask values.
  153. // This leaves 48 mask values that the app can define.
  154. // Use this macro to create app-specific values.
  155. //
  156. // i.e.
  157. // #define DBGMASK_XYZ DBGCREATEMASK(0x0001)
  158. // #define DBGMASK_ABC DBCCREATEMASK(0x0002)
  159. //
  160. #define DBGCREATEMASK(value) (ULONGLONG)((ULONGLONG)value << 16)
  161. //
  162. // Macro to print out an IID for debugging QI functions.
  163. //
  164. #define DBGPRINTIID(mask, level, riid) \
  165. { \
  166. TCHAR szTemp[50]; \
  167. StringFromGUID2(riid, szTemp, ARRAYSIZE(szTemp)); \
  168. DBGPRINT((mask, level, TEXT("IID = %s"), szTemp)); \
  169. }
  170. //
  171. // For storing debug info in registry.
  172. //
  173. struct DebugRegParams
  174. {
  175. ULONGLONG PrintMask;
  176. ULONGLONG TraceMask;
  177. UINT PrintLevel;
  178. UINT TraceLevel;
  179. bool PrintVerbose;
  180. bool TraceVerbose;
  181. bool TraceOnExit;
  182. };
  183. //
  184. // Global debug parameters.
  185. //
  186. struct DebugParams
  187. {
  188. //
  189. // Enumeration representing each of the debugging functions.
  190. //
  191. enum Type { eTrace = 0, ePrint, eAssert, eTypeMax };
  192. //
  193. // Enumeration representing each of the debug parameters.
  194. //
  195. enum Item { eMask = 0, eLevel, eVerbose, eItemMax };
  196. //
  197. // "Mask" that controls if a debugging function is enabled depending upon
  198. // a desired function in the application domain. Each bit in the mask
  199. // corresponds to a given program function. If at runtime, the bitwise
  200. // OR of this value and the "mask" value passed to the debugging function
  201. // is non-zero, the function is considered "mask enabled".
  202. // If a function is both "level enabled" and "mask enabled", it
  203. // performs it's prescribed duties.
  204. // These values can be set by using the following macros:
  205. //
  206. // DBGPRINTMASK(x) - Sets mask for DBGPRINT only.
  207. // DBGTRACEMASK(x) - Sets mask for DBGTRACE only.
  208. // DBGMASK(x) - Sets mask for both.
  209. //
  210. // Note that there's no mask value for DebugAssert or DebugError.
  211. // These classes are always mask-enabled when DBG is defined as 1.
  212. //
  213. static ULONGLONG PrintMask;
  214. static ULONGLONG TraceMask;
  215. //
  216. // "Level" at which debug output is "enabled".
  217. // If at runtime, this value is >= the "level" value passed to the
  218. // debugging function, the function is considered "level enabled".
  219. // If a function is both "level enabled" and "mask enabled", it
  220. // performs it's prescribed duties.
  221. // It is recommended that the set of allowable levels be limited
  222. // to avoid undue complexity. The library doesn't impose a restriction
  223. // on allowable values. However, I've found [0,1,2] to be sufficient.
  224. // These values can be set by using the following macros:
  225. //
  226. // DBGPRINTLEVEL(x) - Sets level for DBGPRINT only.
  227. // DBGTRACELEVEL(x) - Sets level for DBGTRACE only.
  228. // DBGLEVEL(x) - Sets level for both.
  229. //
  230. // Note that there's no level value for DebugAssert or DebugError.
  231. // These classes are always level-enabled when DBG is defined as 1.
  232. //
  233. static UINT PrintLevel;
  234. static UINT TraceLevel;
  235. //
  236. // Flag to indicate if the debugger output should include the filename
  237. // and line number where the debug statement resides in the source file.
  238. // These values can be set by using the following macros:
  239. //
  240. // DBGPRINTVERBOSE(x) - Sets the verbose flag for DBGPRINT only.
  241. // DBGTRACEVERBOSE(x) - Sets the verbose flag for DBGTRACE only.
  242. // DBGVERBOSE(x) - Sets the verbose flag for both.
  243. //
  244. // Note that there's no verbose flag for DebugAssert or DebugError.
  245. // These classes always output verbose information.
  246. //
  247. static bool PrintVerbose;
  248. static bool TraceVerbose;
  249. //
  250. // Flag to indicate if DBGTRACE output is generated when leaving a function.
  251. // This value can be set by using the following macro:
  252. //
  253. // DBGTRACEONEXIT
  254. //
  255. // 1 = Generate output [default]
  256. // 0 = Don't generate output.
  257. //
  258. static bool TraceOnExit;
  259. //
  260. // Address of the name string for the "current" module. This name will be
  261. // included with each debugger message.
  262. // It can be set using the DBGMODULE(name) macro.
  263. //
  264. static LPCTSTR m_pszModule;
  265. //
  266. // Some helper functions used by the DebugXxxxx classes.
  267. //
  268. static LPCTSTR SetModule(LPCTSTR pszModule);
  269. static void SetDebugMask(ULONGLONG llMask);
  270. static ULONGLONG SetPrintMask(ULONGLONG llMask)
  271. { return SetMask(llMask, ePrint); }
  272. static ULONGLONG SetTraceMask(ULONGLONG llMask)
  273. { return SetMask(llMask, eTrace); }
  274. static void SetDebugLevel(UINT uLevel);
  275. static UINT SetPrintLevel(UINT uLevel)
  276. { return SetLevel(uLevel, ePrint); }
  277. static UINT SetTraceLevel(UINT uLevel)
  278. { return SetLevel(uLevel, eTrace); }
  279. static void SetDebugVerbose(bool bVerbose);
  280. static bool SetPrintVerbose(bool bVerbose)
  281. { return SetVerbose(bVerbose, ePrint); }
  282. static bool SetTraceVerbose(bool bVerbose)
  283. { return SetVerbose(bVerbose, eTrace); }
  284. static void SetTraceOnExit(bool bTrace);
  285. static void *GetItemPtr(DebugParams::Item item, DebugParams::Type type);
  286. private:
  287. static ULONGLONG SetMask(ULONGLONG llMask, enum Type type);
  288. static UINT SetLevel(UINT uLevel, enum Type type);
  289. static bool SetVerbose(bool bVerbose, enum Type type);
  290. };
  291. //
  292. // Class that prints a message an "ENTER" message upon construction
  293. // and a "LEAVE" message upon destruction. It is intended that the client
  294. // place a DBGTRACE macro at the start of each function.
  295. // Depending on the current debug "level" and "mask" (see DebugParams),
  296. // a message is printed to the debugger. When the object goes out of scope,
  297. // another message is automatically printed to the debugger.
  298. // This class is only intended to be instantiated through the
  299. // DBGTRACE(x) macro.
  300. //
  301. class DebugTrace
  302. {
  303. public:
  304. DebugTrace(LPCTSTR pszFile, INT iLineNo);
  305. ~DebugTrace(void);
  306. void Enter(void) const { m_llMask = (ULONGLONG)0; }
  307. void Enter(LPCTSTR pszBlockName) const;
  308. void Enter(ULONGLONG llMask, UINT uLevel, LPCTSTR pszBlockName) const;
  309. void Enter(LPCTSTR pszBlockName, LPCTSTR pszFmt, ...) const;
  310. void Enter(ULONGLONG llMask, UINT uLevel, LPCTSTR pszBlockName, LPCTSTR pszFmt, ...) const;
  311. private:
  312. INT m_iLineNo; // Macro's source line number.
  313. LPCTSTR m_pszFile; // Macro's source file name.
  314. mutable ULONGLONG m_llMask; // Macro's "mask".
  315. mutable UINT m_uLevel; // Macro's "level".
  316. mutable LPCTSTR m_pszBlockName; // Ptr to string to print.
  317. static const ULONGLONG DEFMASK; // Default mask for DebugTrace.
  318. static const UINT DEFLEVEL; // Default level for DebugTrace.
  319. };
  320. //
  321. // Class for printing general messages to the debugger output.
  322. // Place a DBGPRINT macro wherever you want to send interesting output to
  323. // the debugger. Note that DebugError specifically handles error message output.
  324. // Note that the DebugPrint class is used by the DebugAssert, DebugError
  325. // and DebugTrace to perform debugger output. The m_type member is used
  326. // to identify which class the output is being produced for.
  327. // This class is only intended to be instantiated through the
  328. // DBGPRINT(x) macro.
  329. //
  330. class DebugPrint
  331. {
  332. public:
  333. DebugPrint(DebugParams::Type type, LPCTSTR pszFile, INT iLineNo);
  334. void Print(void) const { };
  335. void Print(LPCTSTR pszFmt, ...) const;
  336. void Print(ULONGLONG llMask, UINT uLevel, LPCTSTR pszFmt, ...) const;
  337. void Print(ULONGLONG llMask, UINT uLevel, LPCTSTR pszFmt, va_list args) const;
  338. private:
  339. INT m_iLineNo; // Macro's source line number.
  340. LPCTSTR m_pszFile; // Macro's source file name.
  341. DebugParams::Type m_type; // Type of printing being done.
  342. static const ULONGLONG DEFMASK; // Default mask for DebugPrint.
  343. static const UINT DEFLEVEL; // Default level for DebugPrint.
  344. static bool AnyBitSet(ULONGLONG llMask, ULONGLONG llTest);
  345. };
  346. //
  347. // Specialization of the DebugPrint class. It's just a DebugPrint with the
  348. // mask fixed at -1 and the level fixed at 0 so that DBGERROR messages are
  349. // always output when DBG is defined as 1. Note private inheritance prevents
  350. // someone from calling DebugError::Print(). They must call
  351. // DebugError.Error() which calls DebugPrint::Print after setting a
  352. // default mask and level.
  353. //
  354. class DebugError : private DebugPrint
  355. {
  356. public:
  357. DebugError(LPCTSTR pszFile, INT iLineNo);
  358. void Error(LPCTSTR pszFmt, ...) const;
  359. };
  360. //
  361. // Creating a DebugAssert object automatically fires an assertion after
  362. // printing out the debug information.
  363. //
  364. class DebugAssert
  365. {
  366. public:
  367. DebugAssert(LPCTSTR pszFile, INT iLineNo, LPCTSTR pszTest);
  368. };
  369. #else // DBG
  370. #define DBGTRACE(x)
  371. #define DBGPRINT(x)
  372. #define DBGERROR(x)
  373. #define DBGASSERT(test)
  374. #define DBGMODULE(modname)
  375. #define DBGPRINTMASK(mask)
  376. #define DBGPRINTLEVEL(level)
  377. #define DBGPRINTVERBOSE(tf)
  378. #define DBGTRACEMASK(mask)
  379. #define DBGTRACELEVEL(level)
  380. #define DBGTRACEVERBOSE(tf)
  381. #define DBGMASK(mask)
  382. #define DBGLEVEL(level)
  383. #define DBGVERBOSE(tf)
  384. #define DBGTRACEONEXIT(tf)
  385. #define DBGPRINTIID(mask, level, riid)
  386. #endif // DBG
  387. #endif // _INC_DSKQUOTA_DEBUG_H