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.

499 lines
12 KiB

  1. /*++
  2. Copyright (c) 1997-1999 Microsoft Corporation
  3. Module Name:
  4. mspdebug.cpp
  5. Abstract:
  6. This module contains the debugging support for the MSPs.
  7. --*/
  8. #include "precomp.h"
  9. #pragma hdrstop
  10. #include <stdio.h>
  11. #include <strsafe.h>
  12. //
  13. // no need to build this code if MSPLOG is not defined
  14. //
  15. #ifdef MSPLOG
  16. #define MAXDEBUGSTRINGLENGTH 513
  17. static DWORD sg_dwTraceID = INVALID_TRACEID;
  18. static const ULONG MAX_KEY_LENGTH = 100;
  19. static const DWORD DEFAULT_DEBUGGER_MASK = 0xffff0000;
  20. static char sg_szTraceName[MAX_KEY_LENGTH]; // saves name of dll
  21. static DWORD sg_dwTracingToDebugger = 0;
  22. static DWORD sg_dwTracingToConsole = 0;
  23. static DWORD sg_dwTracingToFile = 0;
  24. static DWORD sg_dwDebuggerMask = 0;
  25. //
  26. // this flag indicates whether any tracing needs to be done at all
  27. //
  28. BOOL g_bMSPBaseTracingOn = FALSE;
  29. BOOL NTAPI MSPLogRegister(LPCTSTR szName)
  30. {
  31. HKEY hTracingKey;
  32. char szTracingKey[MAX_KEY_LENGTH];
  33. const char szDebuggerTracingEnableValue[] = "EnableDebuggerTracing";
  34. const char szConsoleTracingEnableValue[] = "EnableConsoleTracing";
  35. const char szFileTracingEnableValue[] = "EnableFileTracing";
  36. const char szTracingMaskValue[] = "ConsoleTracingMask";
  37. sg_dwTracingToDebugger = 0;
  38. sg_dwTracingToConsole = 0;
  39. sg_dwTracingToFile = 0;
  40. #ifdef UNICODE
  41. HRESULT hr = StringCchPrintfA(szTracingKey,
  42. MAX_KEY_LENGTH,
  43. "Software\\Microsoft\\Tracing\\%ls",
  44. szName);
  45. #else
  46. HRESULT hr = StringCchPrintfA(szTracingKey,
  47. MAX_KEY_LENGTH,
  48. "Software\\Microsoft\\Tracing\\%s",
  49. szName);
  50. #endif
  51. if (FAILED(hr))
  52. {
  53. //
  54. // if this assert fires, the chances are the name string passed to us
  55. // by the MSP is too long. the msp developer needs to address that.
  56. //
  57. _ASSERTE(FALSE);
  58. return FALSE;
  59. }
  60. _ASSERTE(sg_dwTraceID == INVALID_TRACEID);
  61. if ( ERROR_SUCCESS == RegOpenKeyExA(HKEY_LOCAL_MACHINE,
  62. szTracingKey,
  63. 0,
  64. KEY_READ,
  65. &hTracingKey) )
  66. {
  67. DWORD dwDataSize = sizeof (DWORD);
  68. DWORD dwDataType;
  69. LONG lRc = RegQueryValueExA(hTracingKey,
  70. szDebuggerTracingEnableValue,
  71. 0,
  72. &dwDataType,
  73. (LPBYTE) &sg_dwTracingToDebugger,
  74. &dwDataSize);
  75. if (ERROR_SUCCESS != lRc)
  76. {
  77. sg_dwTracingToDebugger = 0;
  78. }
  79. lRc = RegQueryValueExA(hTracingKey,
  80. szConsoleTracingEnableValue,
  81. 0,
  82. &dwDataType,
  83. (LPBYTE) &sg_dwTracingToConsole,
  84. &dwDataSize);
  85. if (ERROR_SUCCESS != lRc)
  86. {
  87. sg_dwTracingToConsole = 0;
  88. }
  89. lRc = RegQueryValueExA(hTracingKey,
  90. szFileTracingEnableValue,
  91. 0,
  92. &dwDataType,
  93. (LPBYTE) &sg_dwTracingToFile,
  94. &dwDataSize);
  95. if (ERROR_SUCCESS != lRc)
  96. {
  97. sg_dwTracingToFile = 0;
  98. }
  99. lRc = RegQueryValueExA(hTracingKey,
  100. szTracingMaskValue,
  101. 0,
  102. &dwDataType,
  103. (LPBYTE) &sg_dwDebuggerMask,
  104. &dwDataSize);
  105. if (ERROR_SUCCESS != lRc)
  106. {
  107. sg_dwDebuggerMask = DEFAULT_DEBUGGER_MASK;
  108. }
  109. RegCloseKey (hTracingKey);
  110. }
  111. else
  112. {
  113. //
  114. // the key could not be opened. in case the key does not exist,
  115. // register with rtutils so that the reg keys get created
  116. //
  117. #ifdef UNICODE
  118. hr = StringCchPrintfA(sg_szTraceName, MAX_KEY_LENGTH, "%ls", szName);
  119. #else
  120. hr = StringCchPrintfA(sg_szTraceName, MAX_KEY_LENGTH, "%s", szName);
  121. #endif
  122. if (FAILED(hr))
  123. {
  124. //
  125. // if this assert fires, the chances are the name string passed to us
  126. // by the MSP is too long. the msp developer needs to address that.
  127. //
  128. _ASSERTE(FALSE);
  129. return FALSE;
  130. }
  131. //
  132. // tracing should not have been initialized
  133. //
  134. sg_dwTraceID = TraceRegister(szName);
  135. if (sg_dwTraceID != INVALID_TRACEID)
  136. {
  137. g_bMSPBaseTracingOn = TRUE;
  138. }
  139. return TRUE;
  140. }
  141. //
  142. // are we asked to do any tracing at all?
  143. //
  144. if ( (0 != sg_dwTracingToDebugger) ||
  145. (0 != sg_dwTracingToConsole ) ||
  146. (0 != sg_dwTracingToFile ) )
  147. {
  148. //
  149. // see if we need to register with rtutils
  150. //
  151. if ( (0 != sg_dwTracingToConsole ) || (0 != sg_dwTracingToFile) )
  152. {
  153. //
  154. // rtutils tracing is enabled. register with rtutils
  155. //
  156. #ifdef UNICODE
  157. hr = StringCchPrintfA(sg_szTraceName, MAX_KEY_LENGTH, "%ls", szName);
  158. #else
  159. hr = StringCchPrintfA(sg_szTraceName, MAX_KEY_LENGTH, "%s", szName);
  160. #endif
  161. if (FAILED(hr))
  162. {
  163. //
  164. // if this assert fires, the chances are the name string passed to us
  165. // by the MSP is too long. the msp developer needs to address that.
  166. //
  167. _ASSERTE(FALSE);
  168. return FALSE;
  169. }
  170. //
  171. // tracing should not have been initialized
  172. //
  173. _ASSERTE(sg_dwTraceID == INVALID_TRACEID);
  174. //
  175. // register
  176. //
  177. sg_dwTraceID = TraceRegister(szName);
  178. }
  179. //
  180. // if debugger tracing, or succeeded registering with rtutils, we are all set
  181. //
  182. if ( (0 != sg_dwTracingToDebugger) || (sg_dwTraceID != INVALID_TRACEID) )
  183. {
  184. //
  185. // some tracing is enabled. set the global flag
  186. //
  187. g_bMSPBaseTracingOn = TRUE;
  188. return TRUE;
  189. }
  190. else
  191. {
  192. //
  193. // registration did not go through and debugger logging is off
  194. //
  195. return FALSE;
  196. }
  197. }
  198. //
  199. // logging is not enabled. nothing to do
  200. //
  201. return TRUE;
  202. }
  203. void NTAPI MSPLogDeRegister()
  204. {
  205. if (g_bMSPBaseTracingOn)
  206. {
  207. sg_dwTracingToDebugger = 0;
  208. sg_dwTracingToConsole = 0;
  209. sg_dwTracingToFile = 0;
  210. //
  211. // if we registered tracing, unregister now
  212. //
  213. if ( sg_dwTraceID != INVALID_TRACEID )
  214. {
  215. TraceDeregister(sg_dwTraceID);
  216. sg_dwTraceID = INVALID_TRACEID;
  217. }
  218. }
  219. }
  220. void NTAPI LogPrint(IN DWORD dwDbgLevel, IN LPCSTR lpszFormat, IN ...)
  221. /*++
  222. Routine Description:
  223. Formats the incoming debug message & calls TraceVprintfEx to print it.
  224. Arguments:
  225. dwDbgLevel - The type of the message.
  226. lpszFormat - printf-style format string, followed by appropriate
  227. list of arguments
  228. Return Value:
  229. --*/
  230. {
  231. static char * message[] =
  232. {
  233. "ERROR",
  234. "WARNING",
  235. "INFO",
  236. "TRACE",
  237. "EVENT",
  238. "INVALID TRACE LEVEL"
  239. };
  240. char szTraceBuf[MAXDEBUGSTRINGLENGTH];
  241. DWORD dwIndex;
  242. if ( ( sg_dwTracingToDebugger > 0 ) &&
  243. ( 0 != ( dwDbgLevel & sg_dwDebuggerMask ) ) )
  244. {
  245. switch(dwDbgLevel)
  246. {
  247. case MSP_ERROR: dwIndex = 0; break;
  248. case MSP_WARN: dwIndex = 1; break;
  249. case MSP_INFO: dwIndex = 2; break;
  250. case MSP_TRACE: dwIndex = 3; break;
  251. case MSP_EVENT: dwIndex = 4; break;
  252. default: dwIndex = 5; break;
  253. }
  254. // retrieve local time
  255. SYSTEMTIME SystemTime;
  256. GetLocalTime(&SystemTime);
  257. HRESULT hr =
  258. StringCchPrintfA(szTraceBuf,
  259. MAXDEBUGSTRINGLENGTH,
  260. "%s:[%02u:%02u:%02u.%03u,tid=%x:]%s: ",
  261. sg_szTraceName,
  262. SystemTime.wHour,
  263. SystemTime.wMinute,
  264. SystemTime.wSecond,
  265. SystemTime.wMilliseconds,
  266. GetCurrentThreadId(),
  267. message[dwIndex]);
  268. if (FAILED(hr))
  269. {
  270. //
  271. // if this assert fires, there is a good chance a bug was
  272. // introduced in this function
  273. //
  274. _ASSERTE(FALSE);
  275. return;
  276. }
  277. va_list ap;
  278. va_start(ap, lpszFormat);
  279. size_t nStringLength = 0;
  280. hr = StringCchLengthA(szTraceBuf,
  281. MAXDEBUGSTRINGLENGTH,
  282. &nStringLength);
  283. if (FAILED(hr))
  284. {
  285. //
  286. // if this assert fires, there is a good chance a bug was
  287. // introduced in this function
  288. //
  289. _ASSERTE(FALSE);
  290. return;
  291. }
  292. if (nStringLength >= MAXDEBUGSTRINGLENGTH)
  293. {
  294. //
  295. // the string is too long, was a bug introduced in this function?
  296. //
  297. _ASSERTE(FALSE);
  298. return;
  299. }
  300. hr = StringCchVPrintfA(&szTraceBuf[nStringLength],
  301. MAXDEBUGSTRINGLENGTH - nStringLength,
  302. lpszFormat,
  303. ap
  304. );
  305. if (FAILED(hr))
  306. {
  307. //
  308. // the string the msp code is trying to log is too long. assert to
  309. // indicate this, but proceed to logging it (StringCchVPrintfA
  310. // guarantees that in case of ERROR_INSUFFICIENT_BUFFER, the
  311. // string is remain null-terminated).
  312. //
  313. _ASSERTE(FALSE);
  314. if (ERROR_INSUFFICIENT_BUFFER != hr)
  315. {
  316. return;
  317. }
  318. }
  319. hr = StringCchCatA(szTraceBuf, MAXDEBUGSTRINGLENGTH,"\n");
  320. // in case of failure, the string is likely to be too long. debugbreak,
  321. // and proceed to logging, in which case the string will not be ended
  322. // with '\n'
  323. _ASSERTE(SUCCEEDED(hr));
  324. OutputDebugStringA (szTraceBuf);
  325. va_end(ap);
  326. }
  327. if (sg_dwTraceID != INVALID_TRACEID)
  328. {
  329. if ( ( sg_dwTracingToConsole > 0 ) || ( sg_dwTracingToFile > 0 ) )
  330. {
  331. switch(dwDbgLevel)
  332. {
  333. case MSP_ERROR: dwIndex = 0; break;
  334. case MSP_WARN: dwIndex = 1; break;
  335. case MSP_INFO: dwIndex = 2; break;
  336. case MSP_TRACE: dwIndex = 3; break;
  337. case MSP_EVENT: dwIndex = 4; break;
  338. default: dwIndex = 5; break;
  339. }
  340. HRESULT hr = StringCchPrintfA(szTraceBuf,
  341. MAXDEBUGSTRINGLENGTH,
  342. "[%s] %s",
  343. message[dwIndex],
  344. lpszFormat);
  345. if (FAILED(hr))
  346. {
  347. // the string we are trying to log is too long (or there is an
  348. // unexpected error). do not proceed to logging, since we
  349. // cannot afford to loose the formatting information contained
  350. // in the string -- that would confuse TraceVprintfExA()
  351. _ASSERTE(FALSE);
  352. return;
  353. }
  354. va_list arglist;
  355. va_start(arglist, lpszFormat);
  356. TraceVprintfExA(sg_dwTraceID, dwDbgLevel | TRACE_USE_MSEC, szTraceBuf, arglist);
  357. va_end(arglist);
  358. }
  359. }
  360. }
  361. #endif // MSPLOG
  362. // eof