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.

288 lines
5.1 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 IAS trace facility.
  12. //
  13. // MODIFICATION HISTORY
  14. //
  15. // 08/18/1998 Original version.
  16. //
  17. ///////////////////////////////////////////////////////////////////////////////
  18. #include <windows.h>
  19. #include <stdlib.h>
  20. #include <rtutils.h>
  21. //////////
  22. // Flags passed for all trace calls.
  23. //////////
  24. #define IAS_TRACE_FLAGS (0x00010000 | TRACE_USE_MASK | TRACE_USE_MSEC \
  25. | TRACE_USE_DATE)
  26. //////////
  27. // Trace ID for this module.
  28. //////////
  29. DWORD dwTraceID = INVALID_TRACEID;
  30. //////////
  31. // Flag indicating whether the API has been registered.
  32. //////////
  33. BOOL fRegistered = FALSE;
  34. //////////
  35. // Non-zero if the registration code is locked.
  36. //////////
  37. LONG lLocked = 0;
  38. //////////
  39. // Macros to lock/unlock the registration code.
  40. //////////
  41. #define LOCK_TRACE() \
  42. while (InterlockedExchange(&lLocked, 1)) Sleep(5)
  43. #define UNLOCK_TRACE() \
  44. InterlockedExchange(&lLocked, 0)
  45. //////////
  46. // Formats an error message from the system message table.
  47. //////////
  48. DWORD
  49. WINAPI
  50. IASFormatSysErr(
  51. DWORD dwError,
  52. PSTR lpBuffer,
  53. DWORD nSize
  54. )
  55. {
  56. DWORD nChar;
  57. // Attempt to format the message using the system message table.
  58. nChar = FormatMessageA(
  59. FORMAT_MESSAGE_FROM_SYSTEM,
  60. NULL,
  61. dwError,
  62. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  63. lpBuffer,
  64. nSize,
  65. NULL
  66. );
  67. if (nChar > 0)
  68. {
  69. // Format succeeded, so strip any trailing newline and exit.
  70. if (lpBuffer[nChar - 1] == '\n')
  71. {
  72. --nChar;
  73. lpBuffer[nChar] = '\0';
  74. if (lpBuffer[nChar - 1] == '\r')
  75. {
  76. --nChar;
  77. lpBuffer[nChar] = '\0';
  78. }
  79. }
  80. goto exit;
  81. }
  82. // Only error condition we can handle is when the message is not found.
  83. if (GetLastError() != ERROR_MR_MID_NOT_FOUND)
  84. {
  85. goto exit;
  86. }
  87. // Do we have enough space for the fallback error message ?
  88. if (nSize < 25)
  89. {
  90. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  91. goto exit;
  92. }
  93. // No entry in the message table, so just format the raw error code.
  94. nChar = wsprintfA(lpBuffer, "Unknown error 0x%0lX", dwError);
  95. exit:
  96. return nChar;
  97. }
  98. //////////
  99. // Deregisters the module.
  100. //////////
  101. VOID
  102. __cdecl
  103. IASTraceDeregister( VOID )
  104. {
  105. TraceDeregisterW(dwTraceID);
  106. LOCK_TRACE();
  107. fRegistered = FALSE;
  108. UNLOCK_TRACE();
  109. }
  110. //////////
  111. // Registers the module.
  112. //////////
  113. VOID
  114. WINAPI
  115. IASTraceRegister( VOID )
  116. {
  117. LONG state;
  118. DWORD status;
  119. MEMORY_BASIC_INFORMATION mbi;
  120. WCHAR filename[MAX_PATH + 1], *basename, *suffix;
  121. LOCK_TRACE();
  122. //////////
  123. // Now that we have the lock, double check that we need to register.
  124. //////////
  125. if (fRegistered) { goto exit; }
  126. //////////
  127. // Find the base address of this module.
  128. //////////
  129. if (!VirtualQuery(IASTraceRegister, &mbi, sizeof(mbi))) { goto exit; }
  130. //////////
  131. // Get the module filename.
  132. //////////
  133. status = GetModuleFileNameW(
  134. (HINSTANCE)mbi.AllocationBase,
  135. filename,
  136. MAX_PATH
  137. );
  138. if (status == 0) { goto exit; }
  139. //////////
  140. // Strip everything before the last backslash.
  141. //////////
  142. basename = wcsrchr(filename, L'\\');
  143. if (basename == NULL)
  144. {
  145. basename = filename;
  146. }
  147. else
  148. {
  149. ++basename;
  150. }
  151. //////////
  152. // Strip everything after the last dot.
  153. //////////
  154. suffix = wcsrchr(basename, L'.');
  155. if (suffix)
  156. {
  157. *suffix = L'\0';
  158. }
  159. //////////
  160. // Convert to uppercase.
  161. //////////
  162. _wcsupr(basename);
  163. //////////
  164. // Register the module.
  165. //////////
  166. dwTraceID = TraceRegisterExW(basename, 0);
  167. fRegistered = TRUE;
  168. //////////
  169. // Deregister when we exit.
  170. //////////
  171. atexit(IASTraceDeregister);
  172. exit:
  173. UNLOCK_TRACE();
  174. }
  175. VOID
  176. WINAPIV
  177. IASTracePrintf(
  178. IN PCSTR szFormat,
  179. ...
  180. )
  181. {
  182. va_list marker;
  183. if (!fRegistered) { IASTraceRegister(); }
  184. va_start(marker, szFormat);
  185. TraceVprintfExA(
  186. dwTraceID,
  187. IAS_TRACE_FLAGS,
  188. szFormat,
  189. marker
  190. );
  191. va_end(marker);
  192. }
  193. VOID
  194. WINAPI
  195. IASTraceString(
  196. IN PCSTR szString
  197. )
  198. {
  199. if (!fRegistered) { IASTraceRegister(); }
  200. TracePutsExA(
  201. dwTraceID,
  202. IAS_TRACE_FLAGS,
  203. szString
  204. );
  205. }
  206. VOID
  207. WINAPI
  208. IASTraceBinary(
  209. IN CONST BYTE* lpbBytes,
  210. IN DWORD dwByteCount
  211. )
  212. {
  213. if (!fRegistered) { IASTraceRegister(); }
  214. TraceDumpExA(
  215. dwTraceID,
  216. IAS_TRACE_FLAGS,
  217. (LPBYTE)lpbBytes,
  218. dwByteCount,
  219. 1,
  220. FALSE,
  221. NULL
  222. );
  223. }
  224. VOID
  225. WINAPI
  226. IASTraceFailure(
  227. IN PCSTR szFunction,
  228. IN DWORD dwError
  229. )
  230. {
  231. CHAR szMessage[256];
  232. DWORD nChar;
  233. nChar = IASFormatSysErr(
  234. dwError,
  235. szMessage,
  236. sizeof(szMessage)
  237. );
  238. szMessage[nChar] = '\0';
  239. IASTracePrintf("%s failed: %s", szFunction, szMessage);
  240. }