/Tools/ETW/traceEvent/TraceEventNativeMethods.cs

# · C# · 865 lines · 653 code · 103 blank · 109 comment · 9 complexity · 362840b172f69f91a95508868708cca2 MD5 · raw file

  1. // Copyright (c) Microsoft Corporation. All rights reserved.
  2. // This file is best viewed using outline mode (Ctrl-M Ctrl-O)
  3. //
  4. // This program uses code hyperlinks available as part of the HyperAddin Visual Studio plug-in.
  5. // It is available from http://www.codeplex.com/hyperAddin
  6. //
  7. using System;
  8. using System.Runtime.InteropServices;
  9. using System.ComponentModel;
  10. using System.Security;
  11. using System.Diagnostics;
  12. using Diagnostics.Tracing.Parsers;
  13. using System.Collections.Generic;
  14. // This moduleFile contains Internal PINVOKE declarations and has no public API surface.
  15. namespace Diagnostics.Tracing.Parsers
  16. {
  17. // TODO use safehandles.
  18. #region Private Classes
  19. /// <summary>
  20. /// TraceEventNativeMethods contains the PINVOKE declarations needed
  21. /// to get at the Win32 TraceEvent infrastructure. It is effectively
  22. /// a port of evntrace.h to C# declarations.
  23. /// </summary>
  24. // [SecuritySafeCritical]
  25. // TODO FIX NOW making this public is dubious (did it for enabling Debug Privilege for attaching profiler)
  26. public unsafe static class TraceEventNativeMethods
  27. {
  28. #region TimeZone type from winbase.h
  29. /// <summary>
  30. /// Time zone info. Used as one field of TRACE_EVENT_LOGFILE, below.
  31. /// Total struct size is 0xac.
  32. /// </summary>
  33. [StructLayout(LayoutKind.Sequential, Size = 0xac, CharSet = CharSet.Unicode)]
  34. internal struct TIME_ZONE_INFORMATION
  35. {
  36. public uint bias;
  37. [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
  38. public string standardName;
  39. [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U2, SizeConst = 8)]
  40. public UInt16[] standardDate;
  41. public uint standardBias;
  42. [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
  43. public string daylightName;
  44. [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U2, SizeConst = 8)]
  45. public UInt16[] daylightDate;
  46. public uint daylightBias;
  47. }
  48. #endregion TimeZone type from winbase.h
  49. #region ETW tracing types from evntrace.h
  50. // Delegates for use with ETW EVENT_TRACE_LOGFILEW struct.
  51. // These are the callbacks that ETW will call while processing a moduleFile
  52. // so that we can process each line of the trace moduleFile.
  53. internal delegate bool EventTraceBufferCallback(
  54. [In] IntPtr logfile); // Really a EVENT_TRACE_LOGFILEW, but more efficient to marshal manually);
  55. internal delegate void EventTraceEventCallback(
  56. [In] EVENT_RECORD* rawData);
  57. internal const ulong INVALID_HANDLE_VALUE = unchecked((ulong)(-1));
  58. internal const uint EVENT_TRACE_REAL_TIME_MODE = 0x00000100;
  59. // EVENT_TRACE_LOGFILE.LogFileMode should be set to PROCESS_TRACE_MODE_EVENT_RECORD
  60. // to consume events using EventRecordCallback
  61. internal const uint PROCESS_TRACE_MODE_EVENT_RECORD = 0x10000000;
  62. internal const uint PROCESS_TRACE_MODE_REAL_TIME = 0x00000100;
  63. internal const uint PROCESS_TRACE_MODE_RAW_TIMESTAMP = 0x00001000;
  64. internal const uint EVENT_TRACE_FILE_MODE_NONE = 0x00000000;
  65. internal const uint EVENT_TRACE_FILE_MODE_SEQUENTIAL = 0x00000001;
  66. internal const uint EVENT_TRACE_FILE_MODE_CIRCULAR = 0x00000002;
  67. internal const uint EVENT_TRACE_FILE_MODE_APPEND = 0x00000004;
  68. internal const uint EVENT_TRACE_FILE_MODE_NEWFILE = 0x00000008;
  69. internal const uint EVENT_TRACE_CONTROL_QUERY = 0;
  70. internal const uint EVENT_TRACE_CONTROL_STOP = 1;
  71. internal const uint EVENT_TRACE_CONTROL_UPDATE = 2;
  72. internal const uint EVENT_TRACE_CONTROL_FLUSH = 3;
  73. internal const uint WNODE_FLAG_TRACED_GUID = 0x00020000;
  74. internal const uint EVENT_TRACE_SYSTEM_LOGGER_MODE = 0x02000000;
  75. /// <summary>
  76. /// EventTraceHeader structure used by EVENT_TRACE_PROPERTIES
  77. /// </summary>
  78. [StructLayout(LayoutKind.Sequential)]
  79. internal struct WNODE_HEADER
  80. {
  81. public UInt32 BufferSize;
  82. public UInt32 ProviderId;
  83. public UInt64 HistoricalContext;
  84. public UInt64 TimeStamp;
  85. public Guid Guid;
  86. public UInt32 ClientContext; // Determines the time stamp resolution
  87. public UInt32 Flags;
  88. }
  89. /// <summary>
  90. /// EVENT_TRACE_PROPERTIES is a structure used by StartTrace, ControlTrace
  91. /// however it can not be used directly in the defintion of these functions
  92. /// because extra information has to be hung off the end of the structure
  93. /// before beinng passed. (LofFileNameOffset, LoggerNameOffset)
  94. /// </summary>
  95. [StructLayout(LayoutKind.Sequential)]
  96. internal struct EVENT_TRACE_PROPERTIES
  97. {
  98. public WNODE_HEADER Wnode; // Timer Resolution determined by the Wnode.ClientContext.
  99. public UInt32 BufferSize;
  100. public UInt32 MinimumBuffers;
  101. public UInt32 MaximumBuffers;
  102. public UInt32 MaximumFileSize;
  103. public UInt32 LogFileMode;
  104. public UInt32 FlushTimer;
  105. public UInt32 EnableFlags;
  106. public Int32 AgeLimit;
  107. public UInt32 NumberOfBuffers;
  108. public UInt32 FreeBuffers;
  109. public UInt32 EventsLost;
  110. public UInt32 BuffersWritten;
  111. public UInt32 LogBuffersLost;
  112. public UInt32 RealTimeBuffersLost;
  113. public IntPtr LoggerThreadId;
  114. public UInt32 LogFileNameOffset;
  115. public UInt32 LoggerNameOffset;
  116. }
  117. // TraceMessage flags
  118. // These flags are overlaid into the node USHORT in the EVENT_TRACE.header.version field.
  119. // These items are packed in order in the packet (MofBuffer), as indicated by the flags.
  120. // I don't know what PerfTimestamp is (size?) or holds.
  121. internal enum TraceMessageFlags : int
  122. {
  123. Sequence = 0x01,
  124. Guid = 0x02,
  125. ComponentId = 0x04,
  126. Timestamp = 0x08,
  127. PerformanceTimestamp = 0x10,
  128. SystemInfo = 0x20,
  129. FlagMask = 0xffff,
  130. }
  131. /// <summary>
  132. /// EventTraceHeader and structure used to defined EVENT_TRACE (the main packet)
  133. /// I have simplified from the original struct definitions. I have
  134. /// omitted alternate union-fields which we don't use.
  135. /// </summary>
  136. [StructLayout(LayoutKind.Sequential)]
  137. internal struct EVENT_TRACE_HEADER
  138. {
  139. public ushort Size;
  140. public ushort FieldTypeFlags; // holds our MarkerFlags too
  141. public byte Type;
  142. public byte Level;
  143. public ushort Version;
  144. public int ThreadId;
  145. public int ProcessId;
  146. public long TimeStamp; // Offset 0x10
  147. public Guid Guid;
  148. // no access to GuidPtr, union'd with guid field
  149. // no access to ClientContext & MatchAnyKeywords, ProcessorTime,
  150. // union'd with kernelTime,userTime
  151. public int KernelTime; // Offset 0x28
  152. public int UserTime;
  153. }
  154. /// <summary>
  155. /// EVENT_TRACE is the structure that represents a single 'packet'
  156. /// of data repesenting a single event.
  157. /// </summary>
  158. [StructLayout(LayoutKind.Sequential)]
  159. internal struct EVENT_TRACE
  160. {
  161. public EVENT_TRACE_HEADER Header;
  162. public uint InstanceId;
  163. public uint ParentInstanceId;
  164. public Guid ParentGuid;
  165. public IntPtr MofData; // PVOID
  166. public int MofLength;
  167. public ETW_BUFFER_CONTEXT BufferContext;
  168. }
  169. /// <summary>
  170. /// TRACE_LOGFILE_HEADER is a header used to define EVENT_TRACE_LOGFILEW.
  171. /// Total struct size is 0x110.
  172. /// </summary>
  173. [StructLayout(LayoutKind.Sequential)]
  174. internal struct TRACE_LOGFILE_HEADER
  175. {
  176. public uint BufferSize;
  177. public uint Version; // This is for the operating system it was collected on. Major, Minor, SubVerMajor, subVerMinor
  178. public uint ProviderVersion;
  179. public uint NumberOfProcessors;
  180. public long EndTime; // 0x10
  181. public uint TimerResolution;
  182. public uint MaximumFileSize;
  183. public uint LogFileMode; // 0x20
  184. public uint BuffersWritten;
  185. public uint StartBuffers;
  186. public uint PointerSize;
  187. public uint EventsLost; // 0x30
  188. public uint CpuSpeedInMHz;
  189. public IntPtr LoggerName; // string, but not CoTaskMemAlloc'd
  190. public IntPtr LogFileName; // string, but not CoTaskMemAlloc'd
  191. public TIME_ZONE_INFORMATION TimeZone; // 0x40 0xac size
  192. public long BootTime;
  193. public long PerfFreq;
  194. public long StartTime;
  195. public uint ReservedFlags;
  196. public uint BuffersLost; // 0x10C?
  197. }
  198. /// <summary>
  199. /// EVENT_TRACE_LOGFILEW Main struct passed to OpenTrace() to be filled in.
  200. /// It represents the collection of ETW events as a whole.
  201. /// </summary>
  202. [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
  203. internal struct EVENT_TRACE_LOGFILEW
  204. {
  205. [MarshalAs(UnmanagedType.LPWStr)]
  206. public string LogFileName;
  207. [MarshalAs(UnmanagedType.LPWStr)]
  208. public string LoggerName;
  209. public Int64 CurrentTime;
  210. public uint BuffersRead;
  211. public uint LogFileMode;
  212. // EVENT_TRACE for the current event. Nulled-out when we are opening files.
  213. // [FieldOffset(0x18)]
  214. public EVENT_TRACE CurrentEvent;
  215. // [FieldOffset(0x70)]
  216. public TRACE_LOGFILE_HEADER LogfileHeader;
  217. // callback before each buffer is read
  218. // [FieldOffset(0x180)]
  219. public EventTraceBufferCallback BufferCallback;
  220. public Int32 BufferSize;
  221. public Int32 Filled;
  222. public Int32 EventsLost;
  223. // callback for every 'event', each line of the trace moduleFile
  224. // [FieldOffset(0x190)]
  225. public EventTraceEventCallback EventCallback;
  226. public Int32 IsKernelTrace; // TRUE for kernel logfile
  227. public IntPtr Context; // reserved for internal use
  228. }
  229. #endregion // ETW tracing types
  230. #region Win8 ETW Support - Windows 8
  231. internal enum TRACE_INFO_CLASS
  232. {
  233. TraceGuidQueryList,
  234. TraceGuidQueryInfo,
  235. TraceGuidQueryProcess,
  236. TraceStackTracingInfo, // This is the last one supported on Win7
  237. // Win 8
  238. TraceSystemTraceEnableFlagsInfo, // Turns on kernel event logger
  239. TraceSampledProfileIntervalInfo, // TRACE_PROFILE_INTERVAL (allows you to set the sampling interval) (Set, Get)
  240. TraceProfileSourceConfigInfo, // int array, turns on all listed sources. (Set)
  241. TraceProfileSourceListInfo, // PROFILE_SOURCE_INFO linked list (converts names to source numbers) (Get)
  242. // Used to collect extra info on other events (currently only context switch).
  243. TracePmcEventListInfo, // CLASSIC_EVENT_ID array (Works like TraceStackTracingInfo)
  244. TracePmcCounterListInfo, // int array
  245. MaxTraceSetInfoClass
  246. };
  247. internal struct CLASSIC_EVENT_ID
  248. {
  249. public Guid EventGuid;
  250. public byte Type;
  251. public fixed byte Reserved[7];
  252. };
  253. internal struct TRACE_PROFILE_INTERVAL // Used for TraceSampledProfileIntervalInfo
  254. {
  255. public int Source;
  256. public int Interval;
  257. };
  258. internal struct PROFILE_SOURCE_INFO
  259. {
  260. public int NextEntryOffset; // relative to the start of this structure, 0 indicates end.
  261. public int Source;
  262. public int MinInterval;
  263. public int MaxInterval;
  264. public ulong Reserved;
  265. // char Description[ANYSIZE_ARRAY];
  266. };
  267. [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true), SuppressUnmanagedCodeSecurityAttribute]
  268. static internal extern int TraceSetInformation(
  269. [In] UInt64 traceHandle,
  270. [In] TRACE_INFO_CLASS InformationClass,
  271. [In] void* TraceInformation,
  272. [In] int InformationLength);
  273. [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true), SuppressUnmanagedCodeSecurityAttribute]
  274. static internal extern int TraceQueryInformation(
  275. [In] UInt64 traceHandle,
  276. [In] TRACE_INFO_CLASS InformationClass,
  277. [Out] void* TraceInformation,
  278. [In] int InformationLength,
  279. [In][Out] ref int ReturnLength);
  280. #endregion
  281. #region ETW tracing types from evntcons.h
  282. /*
  283. ntcons.h:#define EVENT_HEADER_FLAG_EXTENDED_INFO 0x0001
  284. ntcons.h:#define EVENT_HEADER_FLAG_PRIVATE_SESSION 0x0002
  285. ntcons.h:#define EVENT_HEADER_FLAG_STRING_ONLY 0x0004
  286. ntcons.h:#define EVENT_HEADER_FLAG_TRACE_MESSAGE 0x0008
  287. ntcons.h:#define EVENT_HEADER_FLAG_NO_CPUTIME 0x0010
  288. */
  289. internal const ushort EVENT_HEADER_FLAG_STRING_ONLY = 0x0004;
  290. internal const ushort EVENT_HEADER_FLAG_32_BIT_HEADER = 0x0020;
  291. internal const ushort EVENT_HEADER_FLAG_64_BIT_HEADER = 0x0040;
  292. internal const ushort EVENT_HEADER_FLAG_CLASSIC_HEADER = 0x0100;
  293. /// <summary>
  294. /// EventTraceHeader and structure used to define EVENT_TRACE_LOGFILE (the main packet on Vista and above)
  295. /// I have simplified from the original struct definitions. I have
  296. /// omitted alternate union-fields which we don't use.
  297. /// </summary>
  298. [StructLayout(LayoutKind.Sequential)]
  299. internal struct EVENT_HEADER
  300. {
  301. public ushort Size;
  302. public ushort HeaderType;
  303. public ushort Flags; // offset: 0x4
  304. public ushort EventProperty;
  305. public int ThreadId; // offset: 0x8
  306. public int ProcessId; // offset: 0xc
  307. public long TimeStamp; // offset: 0x10
  308. public Guid ProviderId; // offset: 0x18
  309. public ushort Id; // offset: 0x28
  310. public byte Version; // offset: 0x2a
  311. public byte Channel;
  312. public byte Level; // offset: 0x2c
  313. public byte Opcode;
  314. public ushort Task;
  315. public ulong Keyword;
  316. public int KernelTime; // offset: 0x38
  317. public int UserTime; // offset: 0x3C
  318. public Guid ActivityId;
  319. }
  320. /// <summary>
  321. /// Provides context information about the event
  322. /// </summary>
  323. [StructLayout(LayoutKind.Sequential)]
  324. internal struct ETW_BUFFER_CONTEXT
  325. {
  326. public byte ProcessorNumber;
  327. public byte Alignment;
  328. public ushort LoggerId;
  329. }
  330. /// <summary>
  331. /// Defines the layout of an event that ETW delivers
  332. /// </summary>
  333. [StructLayout(LayoutKind.Sequential)]
  334. internal struct EVENT_RECORD
  335. {
  336. public EVENT_HEADER EventHeader; // size: 80
  337. public ETW_BUFFER_CONTEXT BufferContext; // size: 4
  338. public ushort ExtendedDataCount;
  339. public ushort UserDataLength; // offset: 86
  340. public EVENT_HEADER_EXTENDED_DATA_ITEM* ExtendedData;
  341. public IntPtr UserData;
  342. public IntPtr UserContext;
  343. }
  344. // Values for the ExtType field
  345. internal const ushort EVENT_HEADER_EXT_TYPE_RELATED_ACTIVITYID = 0x0001;
  346. internal const ushort EVENT_HEADER_EXT_TYPE_SID = 0x0002;
  347. internal const ushort EVENT_HEADER_EXT_TYPE_TS_ID = 0x0003;
  348. internal const ushort EVENT_HEADER_EXT_TYPE_INSTANCE_INFO = 0x0004;
  349. internal const ushort EVENT_HEADER_EXT_TYPE_STACK_TRACE32 = 0x0005;
  350. internal const ushort EVENT_HEADER_EXT_TYPE_STACK_TRACE64 = 0x0006;
  351. [StructLayout(LayoutKind.Sequential)]
  352. internal struct EVENT_HEADER_EXTENDED_DATA_ITEM
  353. {
  354. public ushort Reserved1;
  355. public ushort ExtType;
  356. public ushort Reserved2;
  357. public ushort DataSize;
  358. public ulong DataPtr;
  359. };
  360. [StructLayout(LayoutKind.Sequential)]
  361. internal struct EVENT_EXTENDED_ITEM_STACK_TRACE32
  362. {
  363. public ulong MatchId;
  364. public fixed uint Address[1]; // Actually variable size
  365. };
  366. [StructLayout(LayoutKind.Sequential)]
  367. internal struct EVENT_EXTENDED_ITEM_STACK_TRACE64
  368. {
  369. public ulong MatchId;
  370. public fixed ulong Address[1]; // Actually variable size
  371. };
  372. [StructLayout(LayoutKind.Explicit)]
  373. unsafe internal struct EVENT_FILTER_DESCRIPTOR
  374. {
  375. [FieldOffset(0)]
  376. public byte* Ptr; // Data
  377. [FieldOffset(8)]
  378. public int Size;
  379. [FieldOffset(12)]
  380. public int Type;
  381. };
  382. #endregion
  383. #region ETW tracing functions
  384. // TRACEHANDLE handle type is a ULONG64 in evntrace.h. Use UInt64 here.
  385. [DllImport("advapi32.dll",
  386. EntryPoint = "OpenTraceW",
  387. CharSet = CharSet.Unicode,
  388. SetLastError = true), SuppressUnmanagedCodeSecurityAttribute]
  389. internal extern static UInt64 OpenTrace(
  390. [In][Out] ref EVENT_TRACE_LOGFILEW logfile);
  391. [DllImport("advapi32.dll", CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurityAttribute]
  392. internal extern static int ProcessTrace(
  393. [In] UInt64[] handleArray,
  394. [In] uint handleCount,
  395. [In] IntPtr StartTime,
  396. [In] IntPtr EndTime);
  397. [DllImport("advapi32.dll", CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurityAttribute]
  398. internal extern static int CloseTrace(
  399. [In] UInt64 traceHandle);
  400. [DllImport("advapi32.dll", CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurityAttribute]
  401. internal extern static int QueryAllTraces(
  402. [In] IntPtr propertyArray,
  403. [In] int propertyArrayCount,
  404. [In][Out] ref int sessionCount);
  405. [DllImport("advapi32.dll", CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurityAttribute]
  406. internal extern static int StartTraceW(
  407. [Out] out UInt64 sessionHandle,
  408. [In] string sessionName,
  409. EVENT_TRACE_PROPERTIES* properties);
  410. [DllImport("advapi32.dll", CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurityAttribute]
  411. internal static extern int EnableTrace(
  412. [In] uint enable,
  413. [In] int enableFlag,
  414. [In] int enableLevel,
  415. [In] ref Guid controlGuid,
  416. [In] ulong sessionHandle);
  417. [DllImport("advapi32.dll", CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurityAttribute]
  418. internal static extern int EnableTraceEx(
  419. [In] ref Guid ProviderId,
  420. [In] Guid* SourceId,
  421. [In] ulong TraceHandle,
  422. [In] int IsEnabled,
  423. [In] byte Level,
  424. [In] ulong MatchAnyKeyword,
  425. [In] ulong MatchAllKeyword,
  426. [In] uint EnableProperty,
  427. [In] EVENT_FILTER_DESCRIPTOR* filterData);
  428. [DllImport("advapi32.dll", CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurityAttribute]
  429. internal static extern int EnableTraceEx2(
  430. [In] ulong TraceHandle,
  431. [In] ref Guid ProviderId,
  432. [In] uint ControlCode, // See EVENT_CONTROL_CODE_*
  433. [In] byte Level,
  434. [In] ulong MatchAnyKeyword,
  435. [In] ulong MatchAllKeyword,
  436. [In] uint Timeout,
  437. [In] ref ENABLE_TRACE_PARAMETERS EnableParameters);
  438. // Values for ENABLE_TRACE_PARAMETERS.Version
  439. internal const uint ENABLE_TRACE_PARAMETERS_VERSION = 1;
  440. // Values for ENABLE_TRACE_PARAMETERS.EnableProperty
  441. internal const uint EVENT_ENABLE_PROPERTY_SID = 0x00000001;
  442. internal const uint EVENT_ENABLE_PROPERTY_TS_ID = 0x00000002;
  443. internal const uint EVENT_ENABLE_PROPERTY_STACK_TRACE = 0x00000004;
  444. internal const uint EVENT_CONTROL_CODE_DISABLE_PROVIDER = 0;
  445. internal const uint EVENT_CONTROL_CODE_ENABLE_PROVIDER = 1;
  446. internal const uint EVENT_CONTROL_CODE_CAPTURE_STATE = 2;
  447. [StructLayout(LayoutKind.Sequential)]
  448. internal struct ENABLE_TRACE_PARAMETERS
  449. {
  450. public uint Version;
  451. public uint EnableProperty;
  452. public uint ControlFlags;
  453. public Guid SourceId;
  454. public EVENT_FILTER_DESCRIPTOR* EnableFilterDesc;
  455. };
  456. [DllImport("advapi32.dll", CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurityAttribute]
  457. internal static extern int ControlTrace(
  458. ulong sessionHandle,
  459. string sessionName,
  460. EVENT_TRACE_PROPERTIES* properties,
  461. uint controlCode);
  462. #endregion // ETW tracing functions
  463. #region ETW Tracing from KernelTraceControl.h (from XPERF distribution)
  464. /// <summary>
  465. /// Used in code:StartKernelTrace to indicate the kernel events that should have stack traces
  466. /// collected for them.
  467. /// </summary>
  468. [StructLayout(LayoutKind.Sequential)]
  469. internal struct STACK_TRACING_EVENT_ID
  470. {
  471. public Guid EventGuid;
  472. public byte Type;
  473. byte Reserved1;
  474. byte Reserved2;
  475. byte Reserved3;
  476. byte Reserved4;
  477. byte Reserved5;
  478. byte Reserved6;
  479. byte Reserved7;
  480. }
  481. [DllImport("KernelTraceControl.dll", CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurityAttribute]
  482. internal extern static int StartKernelTrace(
  483. out UInt64 TraceHandle,
  484. EVENT_TRACE_PROPERTIES* Properties,
  485. STACK_TRACING_EVENT_ID* StackTracingEventIds, // Actually an array of code:STACK_TRACING_EVENT_ID
  486. int cStackTracingEventIds);
  487. [DllImport("KernelTraceControl.dll", CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurityAttribute]
  488. internal extern static int CreateMergedTraceFile(
  489. string wszMergedFileName,
  490. string[] wszTraceFileNames,
  491. int cTraceFileNames,
  492. EVENT_TRACE_MERGE_EXTENDED_DATA dwExtendedDataFlags);
  493. [DllImport("kernel32.dll", SetLastError = true)]
  494. public static extern bool Wow64DisableWow64FsRedirection(ref IntPtr ptr);
  495. [DllImport("kernel32.dll", SetLastError = true)]
  496. public static extern bool Wow64RevertWow64FsRedirection(IntPtr ptr);
  497. // Flags to save extended information to the ETW trace file
  498. [Flags]
  499. public enum EVENT_TRACE_MERGE_EXTENDED_DATA
  500. {
  501. NONE = 0x00,
  502. IMAGEID = 0x01,
  503. BUILDINFO = 0x02,
  504. VOLUME_MAPPING = 0x04,
  505. WINSAT = 0x08,
  506. EVENT_METADATA = 0x10,
  507. }
  508. #endregion
  509. #region Security Entry Points
  510. internal static uint STANDARD_RIGHTS_REQUIRED = 0x000F0000;
  511. internal static uint STANDARD_RIGHTS_READ = 0x00020000;
  512. internal static uint TOKEN_ASSIGN_PRIMARY = 0x0001;
  513. internal static uint TOKEN_DUPLICATE = 0x0002;
  514. internal static uint TOKEN_IMPERSONATE = 0x0004;
  515. internal static uint TOKEN_QUERY = 0x0008;
  516. internal static uint TOKEN_QUERY_SOURCE = 0x0010;
  517. internal static uint TOKEN_ADJUST_PRIVILEGES = 0x0020;
  518. internal static uint TOKEN_ADJUST_GROUPS = 0x0040;
  519. internal static uint TOKEN_ADJUST_SESSIONID = 0x0100;
  520. internal static uint TOKEN_READ = (STANDARD_RIGHTS_READ | TOKEN_QUERY);
  521. public enum TOKEN_ELEVATION_TYPE
  522. {
  523. TokenElevationTypeDefault = 1,
  524. TokenElevationTypeFull = 2,
  525. TokenElevationTypeLimited = 3
  526. }
  527. public enum TOKEN_INFORMATION_CLASS
  528. {
  529. TokenUser = 1,
  530. TokenGroups = 2,
  531. TokenPrivileges = 3,
  532. TokenOwner = 4,
  533. TokenPrimaryGroup = 5,
  534. TokenDefaultDacl = 6,
  535. TokenSource = 7,
  536. TokenType = 8,
  537. TokenImpersonationLevel = 9,
  538. TokenStatistics = 10,
  539. TokenRestrictedSids = 11,
  540. TokenSessionId = 12,
  541. TokenGroupsAndPrivileges = 13,
  542. TokenSessionReference = 14,
  543. TokenSandBoxInert = 15,
  544. TokenAuditPolicy = 16,
  545. TokenOrigin = 17,
  546. TokenElevationType = 18,
  547. TokenLinkedToken = 19,
  548. TokenElevation = 20,
  549. TokenHasRestrictions = 21,
  550. TokenAccessInformation = 22,
  551. TokenVirtualizationAllowed = 23,
  552. TokenVirtualizationEnabled = 24,
  553. TokenIntegrityLevel = 25,
  554. TokenUIAccess = 26,
  555. TokenMandatoryPolicy = 27,
  556. TokenLogonSid = 28,
  557. MaxTokenInfoClass = 29 // MaxTokenInfoClass should always be the last enum
  558. }
  559. [DllImport("advapi32.dll", SetLastError = true), SuppressUnmanagedCodeSecurityAttribute]
  560. [return: MarshalAs(UnmanagedType.Bool)]
  561. private static extern bool OpenProcessToken(
  562. [In] IntPtr ProcessHandle,
  563. [In] UInt32 DesiredAccess,
  564. [Out] out IntPtr TokenHandle);
  565. [DllImport("advapi32.dll", SetLastError = true)]
  566. [return: MarshalAs(UnmanagedType.Bool)]
  567. static extern bool GetTokenInformation(
  568. IntPtr TokenHandle,
  569. TOKEN_INFORMATION_CLASS TokenInformationClass,
  570. IntPtr TokenInformation,
  571. int TokenInformationLength,
  572. out int ReturnLength);
  573. [DllImport("advapi32.dll", SetLastError = true), SuppressUnmanagedCodeSecurityAttribute]
  574. [return: MarshalAs(UnmanagedType.Bool)]
  575. internal static extern bool AdjustTokenPrivileges(
  576. [In] IntPtr TokenHandle,
  577. [In, MarshalAs(UnmanagedType.Bool)]bool DisableAllPrivileges,
  578. [In] ref TOKEN_PRIVILEGES NewState,
  579. [In] UInt32 BufferLength,
  580. // [Out] out TOKEN_PRIVILEGES PreviousState,
  581. [In] IntPtr NullParam,
  582. [In] IntPtr ReturnLength);
  583. // I explicitly DONT capture GetLastError information on this call because it is often used to
  584. // clean up and it is cleaner if GetLastError still points at the orginal error, and not the failure
  585. // in CloseHandle. If we ever care about exact errors of CloseHandle, we can make another entry
  586. // point
  587. [DllImport("kernel32.dll"), SuppressUnmanagedCodeSecurityAttribute]
  588. internal static extern bool CloseHandle([In] IntPtr hHandle);
  589. [StructLayout(LayoutKind.Sequential)]
  590. internal struct TOKEN_PRIVILEGES // taylored for the case where you only have 1.
  591. {
  592. public UInt32 PrivilegeCount;
  593. public LUID Luid;
  594. public UInt32 Attributes;
  595. }
  596. [StructLayout(LayoutKind.Sequential)]
  597. public struct LUID
  598. {
  599. public UInt32 LowPart;
  600. public Int32 HighPart;
  601. }
  602. // Constants for the Attributes field
  603. internal const UInt32 SE_PRIVILEGE_ENABLED_BY_DEFAULT = 0x00000001;
  604. internal const UInt32 SE_PRIVILEGE_ENABLED = 0x00000002;
  605. internal const UInt32 SE_PRIVILEGE_REMOVED = 0x00000004;
  606. internal const UInt32 SE_PRIVILEGE_USED_FOR_ACCESS = 0x80000000;
  607. // Constants for the Luid field
  608. internal const uint SE_SYSTEM_PROFILE_PRIVILEGE = 11;
  609. internal const uint SE_DEBUG_PRIVILEGE = 20;
  610. #endregion
  611. [DllImport("kernel32.dll", SetLastError = true), SuppressUnmanagedCodeSecurityAttribute]
  612. internal static extern void ZeroMemory(IntPtr handle, uint length);
  613. // TODO what is this for?
  614. internal static int GetHRForLastWin32Error()
  615. {
  616. int dwLastError = Marshal.GetLastWin32Error();
  617. if ((dwLastError & 0x80000000) == 0x80000000)
  618. return dwLastError;
  619. else
  620. return (dwLastError & 0x0000FFFF) | unchecked((int)0x80070000);
  621. }
  622. /// <summary>
  623. /// The Sample based profiling requires the SystemProfilePrivilege, This code turns it on.
  624. /// </summary>
  625. internal static void SetSystemProfilePrivilege()
  626. {
  627. SetPrivilege(SE_SYSTEM_PROFILE_PRIVILEGE);
  628. }
  629. // TODO bit of a hack to make this public.
  630. public static void SetDebugPrivilege()
  631. {
  632. SetPrivilege(SE_DEBUG_PRIVILEGE);
  633. }
  634. private static void SetPrivilege(uint privilege)
  635. {
  636. Process process = Process.GetCurrentProcess();
  637. IntPtr tokenHandle = IntPtr.Zero;
  638. bool success = OpenProcessToken(process.Handle, TOKEN_ADJUST_PRIVILEGES, out tokenHandle);
  639. if (!success)
  640. throw new Win32Exception();
  641. GC.KeepAlive(process); // TODO get on SafeHandles.
  642. TOKEN_PRIVILEGES privileges = new TOKEN_PRIVILEGES();
  643. privileges.PrivilegeCount = 1;
  644. privileges.Luid.LowPart = privilege;
  645. privileges.Attributes = SE_PRIVILEGE_ENABLED;
  646. success = AdjustTokenPrivileges(tokenHandle, false, ref privileges, 0, IntPtr.Zero, IntPtr.Zero);
  647. CloseHandle(tokenHandle);
  648. if (!success)
  649. throw new Win32Exception();
  650. }
  651. public static bool? IsElevated()
  652. {
  653. if (Environment.OSVersion.Version.Major < 6)
  654. return true;
  655. Process process = Process.GetCurrentProcess();
  656. IntPtr tokenHandle = IntPtr.Zero;
  657. if (!OpenProcessToken(process.Handle, TOKEN_QUERY, out tokenHandle))
  658. return null;
  659. int tokenIsElevated = 0;
  660. int retSize;
  661. bool success = GetTokenInformation(tokenHandle, TOKEN_INFORMATION_CLASS.TokenElevation, (IntPtr)(&tokenIsElevated), 4, out retSize);
  662. CloseHandle(tokenHandle);
  663. if (!success)
  664. return null;
  665. GC.KeepAlive(process); // TODO get on SafeHandles.
  666. return tokenIsElevated != 0;
  667. }
  668. // TODO why do we need this?
  669. internal static int GetHRFromWin32(int dwErr)
  670. {
  671. return (int)((0 != dwErr) ? (0x80070000 | ((uint)dwErr & 0xffff)) : 0);
  672. }
  673. internal static bool CanSetCpuSamplingRate() { return false; }
  674. internal static bool SetCpuSamplingRate(int interval100ns) { return false; }
  675. internal static void EnableStackCaching(ulong traceHandle) { }
  676. internal struct TRACE_PROVIDER_INFO
  677. {
  678. public Guid ProviderGuid;
  679. public int SchemaSource;
  680. public int ProviderNameOffset;
  681. }
  682. internal struct PROVIDER_ENUMERATION_INFO
  683. {
  684. public int NumberOfProviders;
  685. public int Padding;
  686. // TRACE_PROVIDER_INFO TraceProviderInfoArray[ANYSIZE];
  687. };
  688. [DllImport("tdh.dll"), SuppressUnmanagedCodeSecurityAttribute]
  689. internal static extern int TdhEnumerateProviders(
  690. PROVIDER_ENUMERATION_INFO* pBuffer,
  691. ref int pBufferSize
  692. );
  693. internal enum TRACE_QUERY_INFO_CLASS
  694. {
  695. TraceGuidQueryList,
  696. TraceGuidQueryInfo,
  697. TraceGuidQueryProcess,
  698. TraceStackTracingInfo,
  699. MaxTraceSetInfoClass
  700. };
  701. internal struct TRACE_GUID_INFO
  702. {
  703. public int InstanceCount;
  704. public int Reserved;
  705. };
  706. internal struct TRACE_PROVIDER_INSTANCE_INFO
  707. {
  708. public int NextOffset;
  709. public int EnableCount;
  710. public int Pid;
  711. public int Flags;
  712. };
  713. internal struct TRACE_ENABLE_INFO
  714. {
  715. public int IsEnabled;
  716. public byte Level;
  717. public byte Reserved1;
  718. public ushort LoggerId;
  719. public ushort EnableProperty;
  720. public int Reserved2;
  721. public long MatchAnyKeyword;
  722. public long MatchAllKeyword;
  723. };
  724. [DllImport("advapi32.dll"), SuppressUnmanagedCodeSecurityAttribute]
  725. internal static extern int EnumerateTraceGuidsEx(
  726. TRACE_QUERY_INFO_CLASS TraceQueryInfoClass,
  727. void* InBuffer,
  728. int InBufferSize,
  729. void* OutBuffer,
  730. int OutBufferSize,
  731. ref int ReturnLength);
  732. internal enum EVENT_FIELD_TYPE
  733. {
  734. EventKeywordInformation = 0,
  735. EventLevelInformation = 1,
  736. EventChannelInformation = 2,
  737. EventTaskInformation = 3,
  738. EventOpcodeInformation = 4,
  739. EventInformationMax = 5,
  740. };
  741. internal struct PROVIDER_FIELD_INFOARRAY
  742. {
  743. public int NumberOfElements;
  744. public EVENT_FIELD_TYPE FieldType;
  745. // PROVIDER_FIELD_INFO FieldInfoArray[ANYSIZE_ARRAY];
  746. };
  747. internal struct PROVIDER_FIELD_INFO
  748. {
  749. public int NameOffset;
  750. public int DescriptionOffset;
  751. public long Value;
  752. };
  753. [DllImport("tdh.dll"), SuppressUnmanagedCodeSecurityAttribute]
  754. internal static extern int TdhEnumerateProviderFieldInformation(
  755. ref Guid guid,
  756. EVENT_FIELD_TYPE EventFieldType,
  757. PROVIDER_FIELD_INFOARRAY* pBuffer,
  758. ref int pBufferSize
  759. );
  760. } // end class
  761. #endregion
  762. }