Leaked source code of windows server 2003
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.

516 lines
13 KiB

  1. // Copyright (c) 1997-1999 Microsoft Corporation
  2. //
  3. // debug logging tools
  4. //
  5. // 8-13-97 sburns
  6. #ifndef LOG_HPP_INCLUDED
  7. #define LOG_HPP_INCLUDED
  8. // Log provides an interface to a singleton application logging facility.
  9. namespace Burnslib
  10. {
  11. class Log
  12. {
  13. public:
  14. // use these to set DEFAULT_LOGGING_OPTIONS
  15. //
  16. // During CRT startup of our module (i.e. before main, WinMain, or
  17. // DllMain), the debug code examines the DWORD LogFlags value under the
  18. // registry key named by REG_ADMIN_RUNTIME_OPTIONS\LOGFILE_NAME. If the
  19. // value is not present, it is created and DEFAULT_LOGGING_OPTIONS is
  20. // written there. If the value is present, it is read.
  21. //
  22. // The HIWORD is a bit mask specifying the destination of the logging
  23. // output.
  24. //
  25. // The LOWORD of that value contains a bitmask of the various debug
  26. // message types to be output:
  27. // cause LOG output to go to a log file named RUNTIME_NAME.log
  28. static const DWORD OUTPUT_TO_FILE = (1 << 16);
  29. // cause LOG output to go to OutputDebugString
  30. static const DWORD OUTPUT_TO_DEBUGGER = (1 << 17);
  31. // cause LOG output to go to SpewView application
  32. static const DWORD OUTPUT_TO_SPEWVIEW = (1 << 18);
  33. // cause LOG output to be appended to a log file named RUNTIME_NAME.log
  34. static const DWORD OUTPUT_APPEND_TO_FILE = (1 << 19);
  35. // output object construction/destruction
  36. static const DWORD OUTPUT_CTORS = (1 << 0);
  37. // output calls to AddRef/Release
  38. static const DWORD OUTPUT_ADDREFS = (1 << 1);
  39. // output function call entry
  40. static const DWORD OUTPUT_FUNCCALLS = (1 << 2);
  41. // output trace messages
  42. static const DWORD OUTPUT_LOGS = (1 << 3);
  43. // output log header
  44. static const DWORD OUTPUT_HEADER = (1 << 4);
  45. // output error messages
  46. static const DWORD OUTPUT_ERRORS = (1 << 5);
  47. // output time-of-day on each log line
  48. static const DWORD OUTPUT_TIME_OF_DAY = (1 << 6);
  49. // output time-since-start on each log line
  50. static const DWORD OUTPUT_RUN_TIME = (1 << 7);
  51. // output function/scope exits
  52. static const DWORD OUTPUT_SCOPE_EXIT = (1 << 8);
  53. static const DWORD OUTPUT_MUTE = 0;
  54. static const DWORD OUTPUT_FULL_VOLUME =
  55. Log::OUTPUT_TO_FILE
  56. | Log::OUTPUT_TO_DEBUGGER
  57. | Log::OUTPUT_TO_SPEWVIEW
  58. | Log::OUTPUT_CTORS
  59. | Log::OUTPUT_ADDREFS
  60. | Log::OUTPUT_FUNCCALLS
  61. | Log::OUTPUT_LOGS
  62. | Log::OUTPUT_HEADER
  63. | Log::OUTPUT_ERRORS
  64. | Log::OUTPUT_TIME_OF_DAY
  65. | Log::OUTPUT_RUN_TIME
  66. | Log::OUTPUT_SCOPE_EXIT;
  67. static const DWORD OUTPUT_TYPICAL =
  68. Log::OUTPUT_TO_FILE
  69. | Log::OUTPUT_TO_DEBUGGER
  70. | Log::OUTPUT_FUNCCALLS
  71. | Log::OUTPUT_LOGS
  72. | Log::OUTPUT_HEADER
  73. | Log::OUTPUT_ERRORS;
  74. // Returns a pointer to the single Burnslib::Log instance.
  75. static
  76. Log*
  77. GetInstance();
  78. // Called by the initialization machinery to tear down the debugging setup.
  79. // This takes place during static de-initialization, after
  80. // main/WinMain/DllMain(DLL_PROCESS_DETACH) has returned.
  81. static
  82. void
  83. Cleanup();
  84. // Dumps text to the log for the given logging type.
  85. //
  86. // type - log type of text.
  87. //
  88. // text - text to dump.
  89. //
  90. // file - filename of source file producing text.
  91. //
  92. // line - line number in source file producing text.
  93. void
  94. WriteLn(
  95. WORD type,
  96. const String& text);
  97. // const String& file,
  98. // unsigned line);
  99. // A ScopeTracer object emits text to the log upon construction and
  100. // destruction. Place one at the beggining of a lexical scope, and it
  101. // will log when the scope is entered and exited.
  102. // See LOG_SCOPE, LOG_CTOR, LOG_DTOR, LOG_FUNCTION,
  103. // LOG_FUNCTION2
  104. class ScopeTracer
  105. {
  106. public:
  107. // Constructs a new instance, and logs it's creation.
  108. //
  109. // type - the logging type for the log output
  110. //
  111. // message - the text to be emited on construction and destruction
  112. ScopeTracer(
  113. DWORD type,
  114. const String& message);
  115. ~ScopeTracer();
  116. private:
  117. String message;
  118. DWORD type;
  119. };
  120. friend class ScopeTracer;
  121. private:
  122. explicit Log(const String& logBaseName);
  123. ~Log();
  124. HRESULT
  125. AdjustLogMargin(int delta);
  126. String
  127. ComposeSpewLine(const String& text);
  128. // Closes and deletes the single Burnslib::Log instance. If GetInstance
  129. // is called after this point, then a new instance will be created.
  130. static
  131. void
  132. KillInstance();
  133. size_t
  134. GetLogMargin();
  135. void
  136. Indent();
  137. // Returns true if the log file is open, false if not.
  138. bool
  139. IsOpen() const
  140. {
  141. return fileHandle != INVALID_HANDLE_VALUE;
  142. }
  143. void
  144. Outdent();
  145. void
  146. ReadLogFlags();
  147. // This does all the work, really.
  148. void
  149. UnguardedWriteLn(DWORD type, const String& text);
  150. DWORD
  151. DebugType()
  152. {
  153. // mask off the HIWORD for now.
  154. return LOWORD(flags);
  155. }
  156. bool
  157. ShouldLogToFile()
  158. {
  159. return (flags & OUTPUT_TO_FILE) ? true : false;
  160. }
  161. bool
  162. ShouldAppendLogToFile()
  163. {
  164. return (flags & OUTPUT_APPEND_TO_FILE) ? true : false;
  165. }
  166. bool
  167. ShouldLogToDebugger()
  168. {
  169. return (flags & OUTPUT_TO_DEBUGGER) ? true : false;
  170. }
  171. bool
  172. ShouldLogToSpewView()
  173. {
  174. return (flags & OUTPUT_TO_SPEWVIEW) ? true : false;
  175. }
  176. bool
  177. ShouldLogTimeOfDay()
  178. {
  179. return (flags & OUTPUT_TIME_OF_DAY) ? true : false;
  180. }
  181. bool
  182. ShouldLogRunTime()
  183. {
  184. return (flags & OUTPUT_RUN_TIME) ? true : false;
  185. }
  186. void
  187. WriteHeader();
  188. void
  189. WriteHeaderModule(HMODULE moduleHandle);
  190. String baseName;
  191. HANDLE fileHandle;
  192. DWORD flags;
  193. HANDLE spewviewHandle;
  194. String spewviewPipeName;
  195. unsigned traceLineNumber;
  196. CRITICAL_SECTION critsec;
  197. DWORD logfileMarginTlsIndex;
  198. // not implemented; no instance copying allowed.
  199. Log(const Log&);
  200. const Log& operator=(const Log&);
  201. };
  202. // CODEWORK: purge these aliases
  203. const DWORD OUTPUT_MUTE = Log::OUTPUT_MUTE;
  204. const DWORD OUTPUT_FULL_VOLUME = Log::OUTPUT_FULL_VOLUME;
  205. const DWORD OUTPUT_TYPICAL = Log::OUTPUT_TYPICAL;
  206. } // namespace Burnslib
  207. #ifdef LOGGING_BUILD
  208. // The logging feature offers the ability to cause output spew at the opening
  209. // and closing of a lexical scope. This can be done at arbitrary scope with
  210. // the LOG_SCOPE macro, or (more commonly) at function scope with the
  211. // LOG_FUNCTION/2 macros. Specializations of LOG_FUNCTION include LOG_CTOR/2,
  212. // LOG_DTOR/2, LOG_ADDREF, and LOG_RELEASE. Refer to the following table:
  213. //
  214. // Spew macro Output spewed (spewn?) when this flag is set
  215. //
  216. // LOG_SCOPE OUTPUT_LOGS
  217. // LOG_FUNCTION OUTPUT_FUNCCALLS
  218. // LOG_FUNCTION2 OUTPUT_FUNCCALLS
  219. // LOG_CTOR OUTPUT_CTORS
  220. // LOG_CTOR2 OUTPUT_CTORS
  221. // LOG_DTOR OUTPUT_CTORS
  222. // LOG_DTOR2 OUTPUT_CTORS
  223. // LOG_ADDREF OUTPUT_ADDREFS
  224. // LOG_RELEASE OUTPUT_ADDREFS
  225. // LOG_LOG_EGGS_AND_SPAM_LOG To be implemented
  226. //
  227. // At the point where the LOG macro is executed, if the corresponding flag
  228. // is set, a line starting with "Enter " is output. Subsequent output is then
  229. // indented. At the point where the lexical scope enclosing the macro ends,
  230. // if the OUTPUT_SCOPE_EXIT flag is set, a line starting with "Exit" is
  231. // output. Subsequent output is aligned with the next most recent Enter, i.e.
  232. // outdented.
  233. //
  234. // If the flag corresponding to a LOG macro is not set, then no "Enter" or
  235. // "Exit" lines are output.
  236. #define LOGT(type, msg) \
  237. { /* open scope */ \
  238. Burnslib::Log* _dlog = Burnslib::Log::GetInstance(); \
  239. if (_dlog) \
  240. { \
  241. _dlog->WriteLn(type, msg); \
  242. } \
  243. } /* close scope */ \
  244. #define LOG(msg) LOGT(Burnslib::Log::OUTPUT_LOGS, msg)
  245. #define LOG_LAST_WINERROR() \
  246. LOGT( \
  247. Burnslib::Log::OUTPUT_ERRORS, \
  248. String::format( \
  249. L"GetLastError = 0x%1!08X!", \
  250. ::GetLastError())) \
  251. \
  252. #define LOG_SCOPET(type, msg) \
  253. Burnslib::Log::ScopeTracer __tracer(type, msg)
  254. #define LOG_SCOPE(msg) \
  255. LOG_SCOPET( \
  256. Burnslib::Log::OUTPUT_LOGS, \
  257. msg)
  258. #define LOG_CTOR(classname) \
  259. LOG_SCOPET(Burnslib::Log::OUTPUT_CTORS, L"ctor: " TEXT(#classname))
  260. #define LOG_CTOR2(classname, msg) \
  261. LOG_SCOPET( \
  262. Burnslib::Log::OUTPUT_CTORS, \
  263. String(L"ctor: " TEXT(#classname) L" ") \
  264. + String(msg))
  265. #define LOG_DTOR(classname) \
  266. LOG_SCOPET(Burnslib::Log::OUTPUT_CTORS, L"dtor: " TEXT(#classname))
  267. #define LOG_DTOR2(classname, msg) \
  268. LOG_SCOPET( \
  269. Burnslib::Log::OUTPUT_CTORS, \
  270. String(L"dtor: " TEXT(#classname) L" ") \
  271. + String(msg))
  272. #define LOG_ADDREF(classname) \
  273. LOGT( \
  274. Burnslib::Log::OUTPUT_ADDREFS, \
  275. L"AddRef: " TEXT(#classname))
  276. #define LOG_RELEASE(classname) \
  277. LOGT( \
  278. Burnslib::Log::OUTPUT_ADDREFS, \
  279. L"Release: " TEXT(#classname))
  280. #define LOG_FUNCTION(func) \
  281. LOG_SCOPET( \
  282. Burnslib::Log::OUTPUT_FUNCCALLS, \
  283. TEXT(#func))
  284. #define LOG_FUNCTION2(func, s) \
  285. LOG_SCOPET( \
  286. Burnslib::Log::OUTPUT_FUNCCALLS, \
  287. String(TEXT(#func) L" ").append(s))
  288. #define LOG_HRESULT(hr) \
  289. LOGT( \
  290. Burnslib::Log::OUTPUT_ERRORS, \
  291. String::format(L"HRESULT = 0x%1!08X!", hr))
  292. #define LOG_BOOL(boolexpr) \
  293. LOGT( \
  294. Burnslib::Log::OUTPUT_LOGS, \
  295. String::format( \
  296. L"%1 = %2", \
  297. TEXT(#boolexpr), \
  298. (boolexpr) ? L"true" : L"false"))
  299. #else // LOGGING_BUILD
  300. #define LOGL(type, msg)
  301. #define LOG(msg)
  302. #define LOG_LAST_WINERROR()
  303. #define LOG_SCOPEL(type, msg)
  304. #define LOG_SCOPE(msg)
  305. #define LOG_CTOR(classname)
  306. #define LOG_CTOR2(classname, msg)
  307. #define LOG_DTOR(classname)
  308. #define LOG_DTOR2(classname, msg)
  309. #define LOG_ADDREF(classname)
  310. #define LOG_RELEASE(classname)
  311. #define LOG_FUNCTION(func)
  312. #define LOG_FUNCTION2(func, s)
  313. #define LOG_HRESULT(hr)
  314. #define LOG_BOOL(boolexpr)
  315. #endif // LOGGING_BUILD
  316. #endif // LOG_HPP_INCLUDED