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.

354 lines
11 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. // pptrace.cpp
  3. //
  4. // ABSTRACT:
  5. // The Event Tracing utility is built on top of the NT Event Tracer base services.
  6. // The Event Tracer application programming interface (API) is a set of functions
  7. // that developers can use to access and control all aspects of event tracing. Using
  8. // the Event Tracer API, developers can manage event tracing sessions, generate event
  9. // traces, and receive event traces. The Event Tracer API is divided into sections
  10. // based on the functionality implemented:
  11. //
  12. // Event Trace Controller
  13. // Event Trace Provider
  14. // Event Trace Consumer
  15. //
  16. // Event Trace Controller - implemented in pptracelog.exe
  17. // Event trace controllers start and stop event tracing sessions, manage buffer resources,
  18. // and obtain execution statistics for sessions. Session statistics include the number of
  19. // buffers used, the number of buffers delivered, the number of events and buffers lost,
  20. // and the size and location of the log file, if applicable.
  21. //
  22. // Event Trace Provider - APIs used by all ISAPI/COM components are implemented in this file
  23. // The event trace provider section of the Event Tracer API is where event trace
  24. // providers and classes are registered with the Event Tracer, and event traces and
  25. // event trace instances are generated. After registering to generate traces for one
  26. // or more classes of events, an event trace provider can be enabled or disabled for
  27. // an event tracing session. It is left to the provider to define its interpretation
  28. // of being enabled or disabled. In general, if a provider has been enabled, it will
  29. // generate event traces for the session to record, and while it is disabled, it will not.
  30. //
  31. // Event Trace Consumer - implemented in pptracedmp.exe
  32. // Software that functions as an event trace consumer can select one or more event
  33. // tracing sessions as the source of its event traces. Consumers can receive event
  34. // traces stored in log files, or from sessions that deliver event traces in real-time.
  35. // When processing event traces, a consumer can specify starting and ending times, and
  36. // only events that occur in the specified time frame will be delivered to the consumer.
  37. // A consumer can request events from multiple event tracing sessions simultaneously,
  38. // and the Event Tracer will put the events into chronological order before delivering
  39. // them to the consumer.
  40. // HISTORY:
  41. // 05-15-01 - naiyij created
  42. //
  43. ///////////////////////////////////////////////////////////////////////////////
  44. #include <stdafx.h>
  45. #include <tchar.h>
  46. #include <ole2.h>
  47. #include <wmistr.h>
  48. #include <evntrace.h>
  49. #include <pptrace.h>
  50. #include <ctype.h>
  51. #define MAXIMUM_LOGGERS 32
  52. #define IsEqualGUID(rguid1, rguid2) (!memcmp(rguid1, rguid2, sizeof(GUID)))
  53. GUID TransactionGuid =
  54. {0xce5b1020, 0x8ea9, 0x11d0, 0xa4, 0xec, 0x00, 0xa0, 0xc9, 0x06, 0x29, 0x10};
  55. TRACE_GUID_REGISTRATION TraceGuidReg[] =
  56. {
  57. { (LPGUID)&TransactionGuid,
  58. NULL
  59. }
  60. };
  61. typedef struct _USER_MOF_EVENT {
  62. EVENT_TRACE_HEADER Header;
  63. MOF_FIELD mofData;
  64. } USER_MOF_EVENT, *PUSER_MOF_EVENT;
  65. TRACEHANDLE LoggerHandle;
  66. TRACEHANDLE RegistrationHandle;
  67. namespace PPTraceStatus {
  68. bool TraceOnFlag = false;
  69. UCHAR EnableLevel = 0;
  70. ULONG EnableFlags = 0;
  71. }
  72. // TRACEHANDLE is typedefed as ULONG64
  73. ULONG64 GetTraceHandle()
  74. {
  75. return LoggerHandle;
  76. }
  77. // TRACEHANDLE is typedefed as ULONG64
  78. void SetTraceHandle(ULONG64 TraceHandle)
  79. {
  80. LoggerHandle = TraceHandle;
  81. }
  82. ///////////////////////////////////////////////////////////////////////////
  83. // TraceString
  84. // Genereate a Trace Event with the input string
  85. // unicode version - for future use
  86. ///////////////////////////////////////////////////////////////////////////
  87. ULONG TraceString(UCHAR Level, IN LPCWSTR wszBuf)
  88. {
  89. ULONG status;
  90. PMOF_FIELD mofField;
  91. USER_MOF_EVENT UserMofEvent;
  92. RtlZeroMemory(&UserMofEvent, sizeof(UserMofEvent));
  93. UserMofEvent.Header.Class.Type = EVENT_TRACE_TYPE_INFO;
  94. UserMofEvent.Header.Class.Level = Level;
  95. UserMofEvent.Header.Size = sizeof(UserMofEvent);
  96. UserMofEvent.Header.Flags = WNODE_FLAG_TRACED_GUID;
  97. UserMofEvent.Header.Guid = TransactionGuid;
  98. UserMofEvent.Header.Flags |= WNODE_FLAG_USE_MOF_PTR;
  99. mofField = (PMOF_FIELD) & UserMofEvent.mofData;
  100. mofField->DataPtr = (ULONGLONG) (wszBuf);
  101. mofField->Length = sizeof(WCHAR) * (wcslen(wszBuf) + 1);
  102. status = TraceEvent(LoggerHandle, (PEVENT_TRACE_HEADER) & UserMofEvent);
  103. return status;
  104. }
  105. ///////////////////////////////////////////////////////////////////////////
  106. // TraceString
  107. // Genereate a Trace Event with the input string
  108. // ansi version - used currently
  109. ///////////////////////////////////////////////////////////////////////////
  110. ULONG TraceString(UCHAR Level, IN LPCSTR szBuf)
  111. {
  112. ULONG status;
  113. PMOF_FIELD mofField;
  114. USER_MOF_EVENT UserMofEvent;
  115. RtlZeroMemory(&UserMofEvent, sizeof(UserMofEvent));
  116. UserMofEvent.Header.Class.Type = EVENT_TRACE_TYPE_INFO;
  117. UserMofEvent.Header.Class.Level = Level;
  118. UserMofEvent.Header.Size = sizeof(UserMofEvent);
  119. UserMofEvent.Header.Flags = WNODE_FLAG_TRACED_GUID;
  120. UserMofEvent.Header.Guid = TransactionGuid;
  121. UserMofEvent.Header.Flags |= WNODE_FLAG_USE_MOF_PTR;
  122. mofField = (PMOF_FIELD) & UserMofEvent.mofData;
  123. mofField->DataPtr = (ULONGLONG) (szBuf);
  124. mofField->Length = sizeof(CHAR) * (strlen(szBuf) + 1);
  125. status = TraceEvent(LoggerHandle, (PEVENT_TRACE_HEADER) & UserMofEvent);
  126. return status;
  127. }
  128. //---------------------------------------------------------------------------------------
  129. //
  130. // @func Calls TracePrint to print a string that is potentially longer than MAXSTR
  131. //
  132. // @rdesc does not return any value
  133. //
  134. //---------------------------------------------------------------------------------------
  135. VOID
  136. TracePrintString(
  137. UCHAR Level, //@parm log if current logging level is at least this
  138. LPCSTR szFileAndLine, //@parm ignored
  139. LPCSTR szContext, //@parm which function is this called from
  140. LPCSTR szBuf //@parm the string itself
  141. )
  142. {
  143. ATLASSERT(szContext);
  144. TraceString(Level, szContext);
  145. TraceString(Level, szBuf);
  146. }
  147. ///////////////////////////////////////////////////////////////////////////
  148. // TracePrintBlob
  149. // Generate a trace event with input binary blob
  150. ///////////////////////////////////////////////////////////////////////////
  151. #define TOHEX(h) ((h)>=10 ? 'a' +(h)-10 : '0'+(h))
  152. VOID
  153. TracePrintBlob(
  154. UCHAR Level,
  155. LPCSTR szFileAndLine,
  156. LPCSTR szDesc,
  157. LPBYTE binBlob,
  158. DWORD cSize,
  159. BOOL bUnderscore) //defaults to FALSE
  160. {
  161. // no data generated for the following two cases
  162. if (!PPTraceStatus::TraceOnFlag || Level > PPTraceStatus::EnableLevel)
  163. return;
  164. _ASSERT(szFileAndLine && szDesc);
  165. _ASSERT(*szFileAndLine && *szDesc);
  166. _ASSERT(binBlob && !IsBadReadPtr(binBlob, cSize));
  167. char* pBuf = NULL;
  168. char* pAscii = NULL;
  169. // the buffer to hold the hex version of the blob and other stuff + NULL + @
  170. pBuf = new char [strlen(szFileAndLine) + cSize * 2 + 2];
  171. pAscii = new char [cSize * (bUnderscore ? 2 : 1)+ 1];
  172. if (!pBuf || !pAscii)
  173. {
  174. TraceString(Level, "not enough memory for this trace");
  175. }
  176. else
  177. {
  178. char* pNext = pBuf;
  179. char* pNextAscii = pAscii;
  180. BYTE cValue;
  181. BYTE cHalf;
  182. // convert the blob to hex chars
  183. for (DWORD i = 0; i < cSize; ++i)
  184. {
  185. cValue = *binBlob++;
  186. cHalf = cValue >> 4;
  187. *pNext++ = TOHEX(cHalf);
  188. cHalf = cValue & 0x0f;
  189. *pNext++ = TOHEX(cHalf);
  190. if (isprint(cValue))
  191. {
  192. *pNextAscii++ = cValue;
  193. if (bUnderscore)
  194. *pNextAscii++ = '_';
  195. }
  196. else
  197. {
  198. *pNextAscii++ = '?';
  199. if (bUnderscore)
  200. *pNextAscii++ = '?';
  201. }
  202. }
  203. *pNext++ = '@';
  204. CHAR* pStr = strrchr(szFileAndLine, '\\');
  205. if(pStr)
  206. {
  207. strcpy(pNext, ++pStr);
  208. pNext += strlen(pStr);
  209. }
  210. *pNext = '\0';
  211. *pNextAscii = '\0';
  212. TraceString(Level, szDesc);
  213. TraceString(Level, pAscii);
  214. TraceString(Level, pBuf);
  215. }
  216. if (pBuf)
  217. delete [] pBuf;
  218. if (pAscii)
  219. delete [] pAscii;
  220. }
  221. ///////////////////////////////////////////////////////////////////////////
  222. // TracePrint
  223. // Generate a trace event with input data
  224. ///////////////////////////////////////////////////////////////////////////
  225. VOID
  226. TracePrint(
  227. UCHAR Level,
  228. LPCSTR szFileAndLine,
  229. LPCSTR ParameterList OPTIONAL,
  230. ...
  231. )
  232. {
  233. // no data generated for the following two cases
  234. if (!PPTraceStatus::TraceOnFlag || Level > PPTraceStatus::EnableLevel)
  235. return;
  236. CHAR buf[MAXSTR];
  237. int len = 0;
  238. if (ARGUMENT_PRESENT(ParameterList)) {
  239. va_list parms;
  240. va_start(parms, ParameterList);
  241. len = _vsnprintf(buf, MAXSTR-1, (CHAR*)ParameterList, parms);
  242. if (len < 0) len = MAXSTR - 1;
  243. va_end(parms);
  244. }
  245. if (len < (MAXSTR - 1))
  246. {
  247. CHAR* pStr = strrchr(szFileAndLine, '\\');
  248. if (pStr)
  249. {
  250. pStr++;
  251. _snprintf(buf+len, MAXSTR-len-1, "@%s", pStr);
  252. }
  253. }
  254. TraceString(Level, buf);
  255. }
  256. ///////////////////////////////////////////////////////////////////////////
  257. // CTraceFuncVoid
  258. // Generate trace events for void functions
  259. ///////////////////////////////////////////////////////////////////////////
  260. CTraceFuncVoid::CTraceFuncVoid(UCHAR Level, LPCSTR szFileAndLine, LPCSTR szFuncName, LPCSTR ParameterList, ...) : m_Level(Level)
  261. {
  262. // no data generated for the following two cases
  263. if (!PPTraceStatus::TraceOnFlag || m_Level > PPTraceStatus::EnableLevel)
  264. return;
  265. strncpy(m_szFuncName, szFuncName, MAXNAME-1);
  266. CHAR buf[MAXSTR];
  267. int len = _snprintf(buf, MAXSTR-1, "+%s(", m_szFuncName);
  268. int count = 0;
  269. if (ARGUMENT_PRESENT(ParameterList)) {
  270. va_list parms;
  271. va_start(parms, ParameterList);
  272. count = _vsnprintf(buf+len, MAXSTR-len-1, (CHAR*)ParameterList, parms);
  273. len = (count > 0) ? len + count : MAXSTR - 1;
  274. va_end(parms);
  275. }
  276. if (len < (MAXSTR - 1))
  277. {
  278. CHAR* pStr = strrchr(szFileAndLine, '\\');
  279. if (pStr)
  280. {
  281. pStr++; //remove '\'
  282. _snprintf(buf+len, MAXSTR-len-1, ")@%s", pStr);
  283. }
  284. }
  285. TraceString(m_Level, buf);
  286. };
  287. CTraceFuncVoid::~CTraceFuncVoid()
  288. {
  289. // no data generated for the following two cases
  290. if (!PPTraceStatus::TraceOnFlag || m_Level > PPTraceStatus::EnableLevel)
  291. return;
  292. std::ostringstream ost;
  293. ost << "-" << m_szFuncName << "()";
  294. TraceString(m_Level, ost.str().c_str());
  295. };