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.

310 lines
7.6 KiB

  1. /**************************************************************************\
  2. *
  3. * Copyright (c) 1998-1999 Microsoft Corporation
  4. *
  5. * Abstract:
  6. *
  7. * Debugging routines
  8. *
  9. * Revision History:
  10. *
  11. * 09/07/1999 agodfrey
  12. * Created it.
  13. *
  14. \**************************************************************************/
  15. #include "global.h"
  16. // Optional callback function for reporting a debug event.
  17. enum GpAltDebugEventLevel
  18. {
  19. GpAltDebugFatal,
  20. GpAltDebugWarning
  21. };
  22. #define GpAltDebugEventFunction 0
  23. //DEBUGEVENTFUNCTION GpAltDebugEventFunction = NULL;
  24. #if DBG
  25. // GpDebugLevel is used to control the amount/severity of debugging messages
  26. // that are actually output.
  27. int GpDebugLevel = DBG_TERSE;
  28. /**************************************************************************\
  29. *
  30. * Function Description:
  31. *
  32. * Removes the path portion of a pathname
  33. *
  34. * Arguments:
  35. *
  36. * [IN] str - pathname to strip
  37. *
  38. * Return Value:
  39. *
  40. * A pointer to the filename portion of the pathname
  41. *
  42. * History:
  43. *
  44. * 09/07/1999 agodfrey
  45. * Moved from Entry\Initialize.cpp
  46. *
  47. \**************************************************************************/
  48. const char*
  49. StripDirPrefix(
  50. const char* str
  51. )
  52. {
  53. const char* p;
  54. p = strrchr(str, '\\');
  55. return p ? p+1 : str;
  56. }
  57. const int maxInputStringSize = 1024;
  58. /**************************************************************************\
  59. *
  60. * Function Description:
  61. *
  62. * Outputs to the debugger
  63. *
  64. * Arguments:
  65. *
  66. * [IN] format - printf-like format string and variable arguments
  67. *
  68. * Return Value:
  69. *
  70. * Zero. This is to conform to NTDLL's definition of DbgPrint.
  71. *
  72. * Notes:
  73. *
  74. * There will be no output if a debugger is not connected.
  75. *
  76. * History:
  77. *
  78. * 09/07/1999 agodfrey
  79. * Moved from Entry\Initialize.cpp
  80. *
  81. \**************************************************************************/
  82. ULONG _cdecl
  83. DbgPrint(
  84. char* format,
  85. ...
  86. )
  87. {
  88. va_list arglist;
  89. va_start(arglist, format);
  90. char buf[maxInputStringSize];
  91. _vsnprintf(buf, maxInputStringSize, format, arglist);
  92. buf[maxInputStringSize-1]=0;
  93. OutputDebugStringA(buf);
  94. va_end(arglist);
  95. return 0;
  96. }
  97. // If we can't allocate memory for the debug string, we'll use this buffer
  98. // in desperation. It's not thread-safe. I *did* say 'desperation'.
  99. static char desperationBuffer[maxInputStringSize];
  100. /**************************************************************************\
  101. *
  102. * Function Description:
  103. *
  104. * Creates a new string, and sprintf's to it.
  105. *
  106. * Arguments:
  107. *
  108. * [IN] format - printf-like format string and variable arguments
  109. *
  110. * Return Value:
  111. *
  112. * The probably-newly-allocated string result.
  113. *
  114. * Notes:
  115. *
  116. * This function is not intended for general use. It guards against memory
  117. * failure by using a global buffer. So, while the caller is responsible
  118. * for freeing the memory, the caller must also check for that buffer.
  119. * i.e. we only want DbgEmitMessage to call this.
  120. *
  121. * It's also only mostly thread-safe, because if we run out of memory,
  122. * we'll use that global buffer in a non-protected way.
  123. *
  124. * This is the only solution I could find so that I could move most of the
  125. * implementation details out of the header file. The root cause is that
  126. * macros don't handle multiple arguments natively, so we have to pass
  127. * the printf arguments as a single macro argument (in parentheses).
  128. * Which means, the function that consumes those arguments can have no
  129. * other arguments.
  130. *
  131. * History:
  132. *
  133. * 02/01/2000 agodfrey
  134. * Created it. Finally, I've found a way to get debug implementation
  135. * details out of the headers.
  136. *
  137. \**************************************************************************/
  138. char * _cdecl
  139. GpParseDebugString(
  140. char* format,
  141. ...
  142. )
  143. {
  144. va_list arglist;
  145. va_start(arglist, format);
  146. // Don't use GpMalloc here so that we can use ASSERT and WARNING in
  147. // our memory allocation routines.
  148. char *newBuf = static_cast<char *>(LocalAlloc(LMEM_FIXED, maxInputStringSize));
  149. if (!newBuf)
  150. {
  151. newBuf = desperationBuffer;
  152. }
  153. _vsnprintf(newBuf, maxInputStringSize, format, arglist);
  154. // Nuke the last byte, because MSDN isn't clear on what _vsnprintf does
  155. // in that case.
  156. newBuf[maxInputStringSize-1]=0;
  157. va_end(arglist);
  158. return newBuf;
  159. }
  160. /**************************************************************************\
  161. *
  162. * Function Description:
  163. *
  164. * Processes a debug event. Frees the message string.
  165. *
  166. * Arguments:
  167. *
  168. * level - The debug level of the event
  169. * file - Should be __FILE__
  170. * line - Should be __LINE__
  171. * message - The debug message.
  172. *
  173. * Notes:
  174. *
  175. * You don't want to call this directly. That would be error-prone.
  176. * Use ASSERT, WARNING, etc.
  177. *
  178. * In Office, it will raise an 'assert' dialog if necessary.
  179. *
  180. * Depending on the debug level, an identifying prefix will be output.
  181. *
  182. * If the debug level is DBG_RIP, will suspend execution (e.g. by
  183. * hitting a breakpoint.)
  184. *
  185. * Note on Office interop:
  186. *
  187. * Under Office, we'll pass WARNINGs and ASSERTs to a reporting function
  188. * they provide. Their function will breakpoint on ASSERTs.
  189. * Lesser events will just be sent to the debugger.
  190. *
  191. * History:
  192. *
  193. * 02/01/2000 agodfrey
  194. * Created it.
  195. *
  196. \**************************************************************************/
  197. void _cdecl
  198. GpLogDebugEvent(
  199. int level,
  200. char *file,
  201. unsigned int line,
  202. char *message
  203. )
  204. {
  205. // We may want to add things to the passed-in message. So we need
  206. // a temporary buffer
  207. const int maxOutputStringSize = maxInputStringSize + 100;
  208. char tempBuffer[maxOutputStringSize+1];
  209. // MSDN's _vsnprintf doc isn't clear on this, so just in case:
  210. tempBuffer[maxOutputStringSize] = 0;
  211. int altDebugLevel = -1;
  212. char *prefix = "";
  213. if (GpDebugLevel <= (level))
  214. {
  215. switch (level)
  216. {
  217. case DBG_WARNING:
  218. prefix = "WRN ";
  219. if (GpAltDebugEventFunction)
  220. {
  221. altDebugLevel = GpAltDebugWarning;
  222. }
  223. break;
  224. case DBG_RIP:
  225. prefix = "RIP ";
  226. if (GpAltDebugEventFunction)
  227. {
  228. altDebugLevel = GpAltDebugFatal;
  229. }
  230. break;
  231. }
  232. // The convention is that we append the trailing \n, not the caller.
  233. // Two reasons:
  234. // 1) Callers tend to forget it.
  235. // 2) More importantly, it encourages the caller to think of each
  236. // call as a separate event. This is important in some cases - e.g.
  237. // when Office produces a popup for each event.
  238. _snprintf(
  239. tempBuffer,
  240. maxOutputStringSize,
  241. "%s%s(%d): %s\n",
  242. prefix,
  243. StripDirPrefix(file),
  244. line,
  245. message
  246. );
  247. if (altDebugLevel >= 0)
  248. {
  249. //GpAltDebugEventFunction(altDebugLevel, tempBuffer);
  250. }
  251. else
  252. {
  253. OutputDebugStringA(tempBuffer);
  254. }
  255. }
  256. // Free the message buffer
  257. if (message != desperationBuffer)
  258. {
  259. LocalFree(message);
  260. }
  261. // Force a breakpoint, if it's warranted.
  262. if ((GpDebugLevel <= DBG_RIP) && (level == DBG_RIP) && (altDebugLevel < 0))
  263. {
  264. DebugBreak();
  265. }
  266. }
  267. #endif // DBG