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.

507 lines
11 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1998, Microsoft Corp. All rights reserved.
  4. //
  5. // FILE
  6. //
  7. // iastrace.cpp
  8. //
  9. // SYNOPSIS
  10. //
  11. // Defines the API into the SA trace facility.
  12. //
  13. // MODIFICATION HISTORY
  14. //
  15. // 08/18/1998 Original version.
  16. // 01/27/1999 Stolen from IAS Project
  17. //
  18. ///////////////////////////////////////////////////////////////////////////////
  19. #include <windows.h>
  20. #include <rtutils.h>
  21. #include <stdlib.h>
  22. #include <stdio.h>
  23. //
  24. // trace libarary name
  25. //
  26. const TCHAR TRACE_LIBRARY [] = TEXT ("rtutils.dll");
  27. const DWORD MAX_DEBUGSTRING_LENGTH = 512;
  28. //
  29. // tracing library method names
  30. //
  31. const char TRACE_REGISTER_FUNC[] = "TraceRegisterExW";
  32. const char TRACE_DEREGISTER_FUNC[] = "TraceDeregisterW";
  33. const char TRACE_VPRINTF_FUNC[] = "TraceVprintfExA";
  34. const char TRACE_PUTS_FUNC[] = "TracePutsExA";
  35. const char TRACE_DUMP_FUNC[] = "TraceDumpExA";
  36. //
  37. // signatures of methods in rtutils.dll
  38. //
  39. typedef DWORD (*PTRACE_REGISTER_FUNC) (
  40. LPCWSTR lpszCallerName,
  41. DWORD dwFlags
  42. );
  43. typedef DWORD (*PTRACE_DEREGISTER_FUNC) (
  44. DWORD dwTraceID
  45. );
  46. typedef DWORD (*PTRACE_VPRINTF_FUNC) (
  47. DWORD dwTraceID,
  48. DWORD dwFlags,
  49. LPCSTR lpszFormat,
  50. va_list arglist
  51. );
  52. typedef DWORD (*PTRACE_PUTS_FUNC) (
  53. DWORD dwTraceID,
  54. DWORD dwFlags,
  55. LPCSTR lpszString
  56. );
  57. typedef DWORD (*PTRACE_DUMP_FUNC) (
  58. DWORD dwTraceID,
  59. DWORD dwFlags,
  60. LPBYTE lpBytes,
  61. DWORD dwByteCount,
  62. DWORD dwGroupSize,
  63. BOOL bAddressPrefix,
  64. LPCSTR lpszPrefix
  65. );
  66. //
  67. // pointer to the functsion in rtutils.dll
  68. //
  69. PTRACE_REGISTER_FUNC pfnTraceRegisterExW = NULL;
  70. PTRACE_DEREGISTER_FUNC pfnTraceDeregisterW = NULL;
  71. PTRACE_VPRINTF_FUNC pfnTraceVprintfExA = NULL;
  72. PTRACE_PUTS_FUNC pfnTracePutsExA = NULL;
  73. PTRACE_DUMP_FUNC pfnTraceDumpExA = NULL;
  74. //
  75. // flags specifies that the tracing is being done for the first time
  76. //
  77. BOOL fFirstTime = TRUE;
  78. //
  79. // this flag is used to signify whether Trace DLL is initialized
  80. // no tracing is done if DLL is not initialized
  81. //
  82. BOOL fInitDLL = FALSE;
  83. //
  84. // new line char
  85. //
  86. CHAR NEWLINE[] = "\n";
  87. //////////
  88. // Flags passed for all trace calls.
  89. //////////
  90. #define SA_TRACE_FLAGS (0x00010000 | TRACE_USE_MASK | TRACE_USE_MSEC)
  91. //////////
  92. // Trace ID for this module.
  93. //////////
  94. DWORD dwTraceID = INVALID_TRACEID;
  95. //////////
  96. // Flag indicating whether the API has been registered.
  97. //////////
  98. BOOL fRegistered = FALSE;
  99. //////////
  100. // Non-zero if the registration code is locked.
  101. //////////
  102. LONG lLocked = 0;
  103. //////////
  104. // Macros to lock/unlock the registration code.
  105. //////////
  106. #define LOCK_TRACE() \
  107. while (InterlockedExchange(&lLocked, 1)) Sleep(5)
  108. #define UNLOCK_TRACE() \
  109. InterlockedExchange(&lLocked, 0)
  110. //
  111. // signature of method used to initialize trace DLL
  112. //
  113. VOID InitializeTraceDLL(
  114. VOID
  115. );
  116. //////////
  117. // Formats an error message from the system message table.
  118. //////////
  119. DWORD
  120. WINAPI
  121. SAFormatSysErr(
  122. DWORD dwError,
  123. PSTR lpBuffer,
  124. DWORD nSize
  125. )
  126. {
  127. DWORD nChar;
  128. // Attempt to format the message using the system message table.
  129. nChar = FormatMessageA(
  130. FORMAT_MESSAGE_FROM_SYSTEM,
  131. NULL,
  132. dwError,
  133. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  134. lpBuffer,
  135. nSize,
  136. NULL
  137. );
  138. if (nChar > 0)
  139. {
  140. // Format succeeded, so strip any trailing newline and exit.
  141. if (lpBuffer[nChar - 1] == '\n')
  142. {
  143. --nChar;
  144. lpBuffer[nChar] = '\0';
  145. if (lpBuffer[nChar - 1] == '\r')
  146. {
  147. --nChar;
  148. lpBuffer[nChar] = '\0';
  149. }
  150. }
  151. goto exit;
  152. }
  153. // Only error condition we can handle is when the message is not found.
  154. if (GetLastError() != ERROR_MR_MID_NOT_FOUND)
  155. {
  156. goto exit;
  157. }
  158. // Do we have enough space for the fallback error message ?
  159. if (nSize < 25)
  160. {
  161. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  162. goto exit;
  163. }
  164. // No entry in the message table, so just format the raw error code.
  165. nChar = wsprintfA(lpBuffer, "Unknown error 0x%0lX", dwError);
  166. exit:
  167. return nChar;
  168. }
  169. //////////
  170. // Deregisters the module.
  171. //////////
  172. VOID
  173. __cdecl
  174. SATraceDeregister( VOID )
  175. {
  176. if (NULL != pfnTraceDeregisterW)
  177. {
  178. pfnTraceDeregisterW(dwTraceID);
  179. }
  180. LOCK_TRACE();
  181. fRegistered = FALSE;
  182. UNLOCK_TRACE();
  183. }
  184. //////////
  185. // Registers the module.
  186. //////////
  187. VOID
  188. WINAPI
  189. SATraceRegister( VOID )
  190. {
  191. LONG state;
  192. DWORD status;
  193. MEMORY_BASIC_INFORMATION mbi;
  194. WCHAR filename[MAX_PATH + 1], *basename, *suffix;
  195. if ((fRegistered) || (NULL == pfnTraceRegisterExW))
  196. {
  197. return;
  198. }
  199. LOCK_TRACE();
  200. //////////
  201. // Now that we have the lock, double check that we need to register.
  202. //////////
  203. //////////
  204. // Find the base address of this module.
  205. //////////
  206. status = VirtualQuery(
  207. SATraceRegister,
  208. &mbi,
  209. sizeof(mbi)
  210. );
  211. if (status == 0) { goto exit; }
  212. //////////
  213. // Get the module filename.
  214. //////////
  215. status = GetModuleFileNameW(
  216. (HINSTANCE)mbi.AllocationBase,
  217. filename,
  218. MAX_PATH
  219. );
  220. if (status == 0) { goto exit; }
  221. //////////
  222. // Strip everything before the last backslash.
  223. //////////
  224. basename = wcsrchr(filename, L'\\');
  225. if (basename == NULL)
  226. {
  227. basename = filename;
  228. }
  229. else
  230. {
  231. ++basename;
  232. }
  233. //////////
  234. // Strip everything after the last dot.
  235. //////////
  236. suffix = wcsrchr(basename, L'.');
  237. if (suffix)
  238. {
  239. *suffix = L'\0';
  240. }
  241. //////////
  242. // Convert to uppercase.
  243. //////////
  244. _wcsupr(basename);
  245. //////////
  246. // Register the module.
  247. //////////
  248. dwTraceID = pfnTraceRegisterExW(basename, 0);
  249. if (dwTraceID != INVALID_TRACEID)
  250. {
  251. fRegistered = TRUE;
  252. //////////
  253. // Deregister when we exit.
  254. //////////
  255. atexit(SATraceDeregister);
  256. }
  257. exit:
  258. UNLOCK_TRACE();
  259. }
  260. VOID
  261. WINAPIV
  262. SATracePrintf(
  263. IN PCSTR szFormat,
  264. ...
  265. )
  266. {
  267. va_list marker;
  268. #if (defined (DEBUG) || defined (_DEBUG))
  269. //
  270. // in case of debug build always output the output string
  271. //
  272. CHAR szDebugString[MAX_DEBUGSTRING_LENGTH +1];
  273. va_start(marker, szFormat);
  274. _vsnprintf (szDebugString, MAX_DEBUGSTRING_LENGTH, szFormat, marker);
  275. szDebugString[MAX_DEBUGSTRING_LENGTH] = '\0';
  276. OutputDebugString (szDebugString);
  277. OutputDebugString (NEWLINE);
  278. va_end(marker);
  279. #endif // (defined (DEBUG) || defined (_DEBUG)
  280. if (fFirstTime) {InitializeTraceDLL();}
  281. if (!fInitDLL) {return;}
  282. SATraceRegister();
  283. if ((fRegistered) && (NULL != pfnTraceVprintfExA))
  284. {
  285. va_start(marker, szFormat);
  286. pfnTraceVprintfExA(
  287. dwTraceID,
  288. SA_TRACE_FLAGS,
  289. szFormat,
  290. marker
  291. );
  292. va_end(marker);
  293. }
  294. }
  295. VOID
  296. WINAPI
  297. SATraceString(
  298. IN PCSTR szString
  299. )
  300. {
  301. #if (defined (DEBUG) || defined (_DEBUG))
  302. //
  303. // in case of debug build always output the output string
  304. //
  305. OutputDebugString (szString);
  306. OutputDebugString (NEWLINE);
  307. #endif // (defined (DEBUG) || defined (_DEBUG)
  308. if (fFirstTime) {InitializeTraceDLL();}
  309. if (!fInitDLL) {return;}
  310. SATraceRegister();
  311. if ((fRegistered) && (NULL != pfnTracePutsExA))
  312. {
  313. pfnTracePutsExA(
  314. dwTraceID,
  315. SA_TRACE_FLAGS,
  316. szString
  317. );
  318. }
  319. }
  320. VOID
  321. WINAPI
  322. SATraceBinary(
  323. IN CONST BYTE* lpbBytes,
  324. IN DWORD dwByteCount
  325. )
  326. {
  327. if (fFirstTime) {InitializeTraceDLL();}
  328. if (!fInitDLL) {return;}
  329. SATraceRegister();
  330. if ((fRegistered) && (NULL != pfnTraceDumpExA))
  331. {
  332. pfnTraceDumpExA(
  333. dwTraceID,
  334. SA_TRACE_FLAGS,
  335. (LPBYTE)lpbBytes,
  336. dwByteCount,
  337. 1,
  338. FALSE,
  339. NULL
  340. );
  341. }
  342. }
  343. VOID
  344. WINAPI
  345. SATraceFailure(
  346. IN PCSTR szFunction,
  347. IN DWORD dwError
  348. )
  349. {
  350. CHAR szMessage[256];
  351. DWORD nChar;
  352. nChar = SAFormatSysErr(
  353. dwError,
  354. szMessage,
  355. sizeof(szMessage)
  356. );
  357. szMessage[nChar] = '\0';
  358. SATracePrintf("%s failed: %s\n", szFunction, szMessage);
  359. }
  360. //
  361. // this is the internal trace method used to initialize platform specific
  362. // stuff
  363. VOID InitializeTraceDLL(
  364. VOID
  365. )
  366. {
  367. OSVERSIONINFO OsInfo;
  368. HINSTANCE hInst = NULL;
  369. DWORD dwSize = sizeof (OSVERSIONINFO);
  370. LOCK_TRACE ();
  371. do
  372. {
  373. if (!fFirstTime) {break;}
  374. fFirstTime = FALSE;
  375. //
  376. // check the platform we are running in
  377. //
  378. ZeroMemory (&OsInfo, dwSize);
  379. OsInfo.dwOSVersionInfoSize = dwSize;
  380. if (!GetVersionEx (&OsInfo)) {break;}
  381. //
  382. // no tracing if this is not NT
  383. //
  384. if (VER_PLATFORM_WIN32_NT != OsInfo.dwPlatformId) {break;}
  385. //
  386. // Load the trace library (rtutils.dll)
  387. //
  388. hInst = LoadLibrary (TRACE_LIBRARY);
  389. if (NULL == hInst) {break;}
  390. //
  391. // get the address of the methods in the DLL
  392. //
  393. pfnTraceRegisterExW = (PTRACE_REGISTER_FUNC)
  394. GetProcAddress (hInst, (LPCSTR)TRACE_REGISTER_FUNC);
  395. if (NULL == pfnTraceRegisterExW) {break;}
  396. pfnTraceDeregisterW = (PTRACE_DEREGISTER_FUNC)
  397. GetProcAddress (hInst, (LPCSTR)TRACE_DEREGISTER_FUNC);
  398. if (NULL == pfnTraceDeregisterW) {break;}
  399. pfnTraceVprintfExA = (PTRACE_VPRINTF_FUNC)
  400. GetProcAddress (hInst, (LPCSTR)TRACE_VPRINTF_FUNC);
  401. if (NULL == pfnTraceVprintfExA) {break;}
  402. pfnTracePutsExA = (PTRACE_PUTS_FUNC)
  403. GetProcAddress (hInst, (LPCSTR)TRACE_PUTS_FUNC);
  404. if (NULL == pfnTracePutsExA) {break;}
  405. pfnTraceDumpExA = (PTRACE_DUMP_FUNC)
  406. GetProcAddress (hInst, (LPCSTR)TRACE_DUMP_FUNC);
  407. if (NULL == pfnTraceDumpExA) {break;}
  408. //
  409. // successfully initialized tracing DLL
  410. //
  411. fInitDLL = TRUE;
  412. }
  413. while (FALSE);
  414. UNLOCK_TRACE();
  415. return;
  416. } // end of InitializeTraceDLL method