private void ReadProcessStartEvent(ref EtwNativeEvent traceEvent) { if (traceEvent.Version == 0) { // <data name="ProcessID" inType="win:UInt32" outType="win:PID"></data> // <data name="CreateTime" inType="win:FILETIME" outType="xs:dateTime"></data> // <data name="ParentProcessID" inType="win:UInt32" outType="win:PID"></data> // <data name="SessionID" inType="win:UInt32" outType="xs:unsignedInt"></data> // <data name="ImageName" inType="win:UnicodeString" outType="xs:string"></data> EventHandler<ProcessEventArgs> handler = this.ProcessStarted; if (handler != null) { int processId = (int)traceEvent.ReadUInt32(); DateTime createTime = traceEvent.ReadFileTime(); traceEvent.ReadUInt32(); // ignore traceEvent.ReadUInt32(); // ignore string imageName = traceEvent.ReadUnicodeString(); ProcessEventArgs e = new ProcessEventArgs() { Id = processId, ImageName = imageName, Timestamp = createTime }; handler(this, e); } } }
/// <summary> /// This function copies the information from the native TRACE_EVENT_INFO structure /// to property information in this oject /// </summary> /// <param name="buffer">IntPtr to TRACE_EVENT_INFO structure</param> void CopyMetadata(IntPtr buffer, ref EtwNativeEvent e) { TRACE_EVENT_INFO *info = (TRACE_EVENT_INFO *)buffer; byte * start = (byte *)info; byte * end = start + sizeof(TRACE_EVENT_INFO); _template = new Dictionary <string, object>(); _template.Add("Provider", CopyString(start, info->ProviderNameOffset)); _template.Add("Level", CopyString(start, info->LevelNameOffset)); _template.Add("Task", CopyString(start, info->TaskNameOffset)); _template.Add("Opcode", CopyString(start, info->OpcodeNameOffset)); _template.Add("Channel", CopyString(start, info->ChannelNameOffset)); _formatString = TranslateFormatString(CopyString(start, info->EventMessageOffset)); EVENT_PROPERTY_INFO *prop = (EVENT_PROPERTY_INFO *)end; var propList = new List <EtwPropertyInfo>(); for (int i = 0; i < info->TopLevelPropertyCount; i++) { var propInfo = prop + i; var name = CopyString(start, propInfo->NameOffset); var type = (TdhInType)(*propInfo).NonStructTypeValue.InType; var outType = (TdhOutType)(*propInfo).NonStructTypeValue.OutType; EtwPropertyInfo property = null; if (propInfo->Flags == PROPERTY_FLAGS.PropertyParamLength) { string lenPropertyName = propList[(int)(propInfo->LengthPropertyIndex)].Name; property = new EtwPropertyInfo { Name = name, Type = type, OutType = outType, LengthPropertyName = lenPropertyName }; } else { ushort len = (*propInfo).LengthPropertyIndex; property = new EtwPropertyInfo { Name = name, Length = len, Type = type, OutType = outType }; } if (propInfo->NonStructTypeValue.MapNameOffset > 0) { string mapName = CopyString(start, propInfo->NonStructTypeValue.MapNameOffset); property.ValueMap = ReadTdhMap(mapName, ref e); } propList.Add(property); } _properties = propList.ToArray(); }
private void OnNext(EtwNativeEvent traceEvent) { // An event is uniquely identified by 3 values -- provider ID, event ID, event version if (traceEvent.ProviderId == KernelProcessProviderId) { switch (traceEvent.Id) { case ProcessStartId: this.ReadProcessStartEvent(ref traceEvent); break; case ProcessStopId: this.ReadProcessStopEvent(ref traceEvent); break; } } }
public EtwTdhEventInfo(ref EtwNativeEvent e) { IntPtr buffer = IntPtr.Zero; try { buffer = ReadTdhMetadata(ref e); CopyMetadata(buffer, ref e); } finally { if (buffer != IntPtr.Zero) { Marshal.FreeHGlobal(buffer); } } }
Dictionary <uint, string> ReadTdhMap(string mapName, ref EtwNativeEvent e) { IntPtr pMapName = Marshal.StringToBSTR(mapName); int bufferSize = 0; int status = EtwNativeMethods.TdhGetEventMapInformation( ref *e.record, pMapName, IntPtr.Zero, ref bufferSize); if (122 != status) // ERROR_INSUFFICIENT_BUFFER { throw new Exception("Unexpected TDH status " + status); } var mybuffer = Marshal.AllocHGlobal(bufferSize); status = EtwNativeMethods.TdhGetEventMapInformation( ref *e.record, pMapName, mybuffer, ref bufferSize); if (status != 0) { throw new Exception("TDH status " + status); } EVENT_MAP_INFO *mapInfo = (EVENT_MAP_INFO *)mybuffer; byte * startMap = (byte *)mapInfo; var name1 = CopyString(startMap, mapInfo->NameOffset); byte * endMap = startMap + sizeof(EVENT_MAP_INFO); var map = new Dictionary <uint, string>(); for (int i = 0; i < mapInfo->EntryCount; i++) { EVENT_MAP_ENTRY *mapEntry = (EVENT_MAP_ENTRY *)endMap + i; uint value = mapEntry->Value; string name = CopyString(startMap, mapEntry->OutputOffset); map.Add(value, name); } return(map); }
/// <summary> /// Method to read ETW event as per the metadata stored in this class /// </summary> /// <param name="e">The ETW native event helper class for one-time read</param> /// <returns></returns> public IDictionary <string, object> Deserialize(ref EtwNativeEvent e) { Dictionary <string, object> instance = new Dictionary <string, object>(_template); instance.Add("EventId", e.Id); instance.Add("Version", e.Version); instance.Add("TimeCreated", e.TimeStamp.DateTime); instance.Add("ProcessId", e.ProcessId); instance.Add("ThreadId", e.ThreadId); instance.Add("ActivityId", e.ActivityId); Dictionary <string, object> eventData = new Dictionary <string, object>(); List <object> values = new List <object>(); foreach (var p in _properties) { uint len = p.Length; if (p.LengthPropertyName != null) { len = (uint)eventData[p.LengthPropertyName]; } object value = GetValue(p.Type, len, ref e); value = FormatValue(p, value); value = EtwTdhPostFormat.ApplyFormatting(e.ProviderId, e.Id, p.Name, value); eventData.Add(p.Name, value); values.Add(value); } instance.Add("EventData", eventData); if (_formatString == null) { instance.Add("Message", null); } else { string message = String.Format(_formatString, values.ToArray()); instance.Add("Message", message); } return(instance); }
internal EventManifest ParseManifest(EtwNativeEvent etwNativeEvent) { EventManifest result = null; if (etwNativeEvent.ProviderId == this.etwProviderId) { switch (etwNativeEvent.Id) { case 3: result = ParseRegularManifest(etwNativeEvent); break; case 4: result = this.ParseChunkedManifest(etwNativeEvent); break; } } return result; }
private static BinaryEnvelope ParseV0(EtwNativeEvent etwNativeEvent) { // Reading like this ensures that if exception is thrown, we know what failed long occurenceFileTimeUtc = etwNativeEvent.ReadInt64(); long receiveFileTimeUtc = etwNativeEvent.ReadInt64(); string protocol = etwNativeEvent.ReadUnicodeString(); bool isValid = !(protocol ?? string.Empty).StartsWith(@"rceException: ", StringComparison.OrdinalIgnoreCase); string source; string manifestId; uint eventPayloadLength; byte[] eventPayload; if (isValid) { source = etwNativeEvent.ReadUnicodeString(); manifestId = etwNativeEvent.ReadUnicodeString(); eventPayloadLength = etwNativeEvent.ReadUInt32(); // There is a side-effect being used here with the binary length. // Payload overflow events also could be saved with event Id 0 eventPayload = (eventPayloadLength < 65000) ? etwNativeEvent.ReadBytes() : new byte[0]; } else { protocol = string.Empty; source = string.Empty; manifestId = string.Empty; eventPayloadLength = 0; eventPayload = new byte[0]; } return new BinaryEnvelope { ActivityId = etwNativeEvent.ActivityId, OccurenceFileTimeUtc = occurenceFileTimeUtc, ReceiveFileTimeUtc = receiveFileTimeUtc, Protocol = protocol, Source = source, PayloadId = manifestId, EventPayload = eventPayload, EventPayloadLength = eventPayloadLength }; }
/// <summary> /// This function reads the event metadata from TDH into globally allocated buffer /// It is caller's responsibility to free the memory by calling Marshal.FreeHGlobal /// </summary> /// <param name="e">ETW native event interop wrapper structure</param> /// <returns>Pointer to newly allocated TRACE_EVENT_INFO structure</returns> IntPtr ReadTdhMetadata(ref EtwNativeEvent e) { int bufferSize = 0; int status = EtwNativeMethods.TdhGetEventInformation(ref *e.record, 0, IntPtr.Zero, IntPtr.Zero, ref bufferSize); if (122 != status) // ERROR_INSUFFICIENT_BUFFER { throw new Exception("Unexpected TDH status " + status); } var mybuffer = Marshal.AllocHGlobal(bufferSize); status = EtwNativeMethods.TdhGetEventInformation(ref *e.record, 0, IntPtr.Zero, mybuffer, ref bufferSize); if (status != 0) { throw new Exception("TDH status " + status); } return(mybuffer); }
private static EventManifest ParseRegularManifest(EtwNativeEvent etwNativeEvent) { // EventId is one. This is a log written using EventSource Byte Array logging support. // Reading like this ensures that if exception is thrown, we know what failed long occurenceFileTimeUtc = etwNativeEvent.ReadInt64(); long receiveFileTimeUtc = etwNativeEvent.ReadInt64(); string protocol = etwNativeEvent.ReadUnicodeString(); string source = etwNativeEvent.ReadUnicodeString(); string manifestId = etwNativeEvent.ReadUnicodeString(); string manifest = etwNativeEvent.ReadUnicodeString(); return new EventManifest { ActivityId = etwNativeEvent.ActivityId, OccurenceFileTimeUtc = occurenceFileTimeUtc, ReceiveFileTimeUtc = receiveFileTimeUtc, Protocol = protocol, Source = source, ManifestId = manifestId, Manifest = manifest, }; }
static void CustomCallback(EtwNativeEvent evt) { if (evt.Id != 11) return; evt.ReadUInt32(); // skip PID uint size = evt.ReadUInt32(); uint daddr = evt.ReadUInt32(); lock (_lock) { StatisticsBucket bucket = null; if (!_statistics.TryGetValue(daddr, out bucket)) { bucket = new StatisticsBucket { Total = size }; _statistics.Add(daddr, bucket); return; } bucket.Total += size; } }
internal BinaryEnvelope Parse(EtwNativeEvent etwNativeEvent) { BinaryEnvelope result = null; if (etwNativeEvent.ProviderId == this.etwProviderId) { switch (etwNativeEvent.Id) { case 0: result = ParseV0(etwNativeEvent); break; case 1: result = ParseV1(etwNativeEvent); break; case 2: result = this.ParseV2(etwNativeEvent); break; } } return result; }
public IDictionary <string, object> Deserialize(ref EtwNativeEvent e) { SequenceNumber++; Dictionary <uint, EtwTdhEventInfo> providerInfo = null; if (!_cache.TryGetValue(e.ProviderId, out providerInfo)) { providerInfo = new Dictionary <uint, EtwTdhEventInfo>(); _cache.Add(e.ProviderId, providerInfo); } EtwTdhEventInfo info = null; if (!providerInfo.TryGetValue(e.Id, out info)) { info = new EtwTdhEventInfo(ref e); providerInfo.Add(e.Id, info); } var result = info.Deserialize(ref e); return(result); }
private static Envelope ParseV1(EtwNativeEvent etwNativeEvent) { // EventId is one. This is a log written using EventSource Byte Array logging support. // Reading like this ensures that if exception is thrown, we know what failed long occurenceFileTimeUtc = etwNativeEvent.ReadInt64(); long receiveFileTimeUtc = etwNativeEvent.ReadInt64(); string protocol = etwNativeEvent.ReadUnicodeString(); string source = etwNativeEvent.ReadUnicodeString(); string manifestId = etwNativeEvent.ReadUnicodeString(); uint eventPayloadLength = etwNativeEvent.ReadUInt32(); // There is a side-effect being used here with the binary length. etwNativeEvent.ReadInt32(); // EventSource based byte array writer actually stores the byte array length here. Skip 4 bytes to account for it. byte[] eventPayload = etwNativeEvent.ReadBytes(); return new Envelope( occurenceFileTimeUtc >= 0 ? DateTimeOffset.FromFileTime(occurenceFileTimeUtc) : DateTimeOffset.MinValue, receiveFileTimeUtc >= 0 ? DateTimeOffset.FromFileTime(receiveFileTimeUtc) : DateTimeOffset.MinValue, protocol, source, manifestId, eventPayload, null); }
static object GetValue(TdhInType type, uint len, ref EtwNativeEvent evt) { // please keep the code below in the same order is the reader methods in EtwNativeEvent switch (type) { case TdhInType.AnsiChar: return(evt.ReadAnsiChar()); case TdhInType.UnicodeChar: return(evt.ReadChar()); case TdhInType.Int8: return(evt.ReadByte()); case TdhInType.UInt8: return(evt.ReadUInt8()); case TdhInType.Int16: return(evt.ReadInt16()); case TdhInType.UInt16: return(evt.ReadUInt16()); case TdhInType.Int32: return(evt.ReadInt32()); case TdhInType.UInt32: case TdhInType.HexInt32: return(evt.ReadUInt32()); case TdhInType.Int64: return(evt.ReadInt64()); case TdhInType.UInt64: case TdhInType.HexInt64: return(evt.ReadUInt64()); case TdhInType.Pointer: return(evt.ReadPointer()); case TdhInType.Boolean: return(evt.ReadBoolean()); case TdhInType.Float: return(evt.ReadFloat()); case TdhInType.Double: return(evt.ReadDouble()); case TdhInType.FileTime: return(evt.ReadFileTime()); case TdhInType.SystemTime: return(evt.ReadSystemTime()); case TdhInType.Guid: return(evt.ReadGuid()); case TdhInType.Binary: return(evt.ReadBytes(len)); case TdhInType.UnicodeString: if (len > 0) { return(evt.ReadUnicodeString((int)len)); } else { return(evt.ReadUnicodeString()); } case TdhInType.AnsiString: return(evt.ReadAnsiString()); default: throw new Exception("Unknown type " + type.ToString()); } }
/// <summary> /// Method to read ETW event as per the metadata stored in this class /// </summary> /// <param name="e">The ETW native event helper class for one-time read</param> /// <returns></returns> public IDictionary <string, object> Deserialize(ref EtwNativeEvent e) { Dictionary <string, object> instance = new Dictionary <string, object>(_template) { { "EventId", e.Id }, { "Version", e.Version }, { "TimeCreated", e.TimeStamp.UtcDateTime }, { "ProcessId", e.ProcessId }, { "ThreadId", e.ThreadId }, { "ActivityId", e.ActivityId } }; Dictionary <string, object> eventData = new Dictionary <string, object>(); List <object> values = new List <object>(); foreach (var p in _properties) { uint len = p.Length; if (p.LengthPropertyName != null) { try { string num = Convert.ToString(eventData[p.LengthPropertyName]); if (num.StartsWith("0x", StringComparison.CurrentCultureIgnoreCase)) { num = num.Substring(2); len = uint.Parse(num, System.Globalization.NumberStyles.HexNumber); } else { len = Convert.ToUInt32(num); } } catch (Exception ex) { ex.Data["ProviderGuid"] = e.ProviderId; throw; } } try { object value = GetValue(p.Type, len, ref e); value = FormatValue(p, value); value = EtwTdhPostFormat.ApplyFormatting(e.ProviderId, e.Id, p.Name, value); eventData.Add(p.Name, value); values.Add(value); } catch (Exception) { eventData.Add(p.Name, "Exception on retrieving value"); } } instance.Add("EventData", eventData); if (_formatString == null) { instance.Add("Message", null); } else { string message = string.Format(_formatString, values.ToArray()); instance.Add("Message", message); } return(instance); }
public EtwTdhEvent(EtwTdhDeserializer deserializer, EtwNativeEvent nativeEvent) { _deserializer = deserializer; _nativeEvent = nativeEvent; }
private EventManifest ParseChunkedManifest(EtwNativeEvent etwNativeEvent) { uint packageId = etwNativeEvent.ReadUInt32(); long occurenceFileTimeUtc = etwNativeEvent.ReadInt64(); long receiveFileTimeUtc = etwNativeEvent.ReadInt64(); string protocol = etwNativeEvent.ReadUnicodeString(); string source = etwNativeEvent.ReadUnicodeString(); string manifestId = etwNativeEvent.ReadUnicodeString(); uint chunkCount = etwNativeEvent.ReadUInt32(); uint currentChunkNumber = etwNativeEvent.ReadUInt32(); string manifest = etwNativeEvent.ReadUnicodeString(); if (chunkCount == 1) { this.manifestCache.Clear(); return new EventManifest { ActivityId = etwNativeEvent.ActivityId, OccurenceFileTimeUtc = occurenceFileTimeUtc, ReceiveFileTimeUtc = receiveFileTimeUtc, Protocol = protocol, Source = source, ManifestId = manifestId, Manifest = manifest }; } else if (chunkCount > currentChunkNumber) { if (this.currentManifestPackageId != packageId || this.manifestCache.Count != currentChunkNumber) { this.manifestCache.Clear(); this.currentManifestPackageId = packageId; } this.manifestCache.Add(manifest); if (chunkCount == (currentChunkNumber + 1)) { string payload = string.Join("", this.manifestCache.ToArray()); this.manifestCache.Clear(); return new EventManifest { ActivityId = etwNativeEvent.ActivityId, OccurenceFileTimeUtc = occurenceFileTimeUtc, ReceiveFileTimeUtc = receiveFileTimeUtc, Protocol = protocol, Source = source, ManifestId = manifestId, Manifest = payload, }; } } else { this.manifestCache.Clear(); } return null; }
private static BinaryEnvelope ParseV1(EtwNativeEvent etwNativeEvent) { // EventId is one. This is a log written using EventSource Byte Array logging support. // Reading like this ensures that if exception is thrown, we know what failed long occurenceFileTimeUtc = etwNativeEvent.ReadInt64(); long receiveFileTimeUtc = etwNativeEvent.ReadInt64(); string protocol = etwNativeEvent.ReadUnicodeString(); string source = etwNativeEvent.ReadUnicodeString(); string manifestId = etwNativeEvent.ReadUnicodeString(); uint eventPayloadLength = etwNativeEvent.ReadUInt32(); // There is a side-effect being used here with the binary length. etwNativeEvent.ReadInt32(); // EventSource based byte array writer actually stores the byte array length here. Skip 4 bytes to account for it. byte[] eventPayload = etwNativeEvent.ReadBytes(); return new BinaryEnvelope { ActivityId = etwNativeEvent.ActivityId, OccurenceFileTimeUtc = occurenceFileTimeUtc, ReceiveFileTimeUtc = receiveFileTimeUtc, Protocol = protocol, Source = source, PayloadId = manifestId, EventPayload = eventPayload, EventPayloadLength = eventPayloadLength }; }
private void ReadProcessStopEvent(ref EtwNativeEvent traceEvent) { switch (traceEvent.Version) { case 0: case 1: // Both version 0 and version 1 have the same initial fields: // // <data name="ProcessID" inType="win:UInt32" outType="win:PID"></data> // <data name="CreateTime" inType="win:FILETIME" outType="xs:dateTime"></data> // <data name="ExitTime" inType="win:FILETIME" outType="xs:dateTime"></data> // <data name="ExitCode" inType="win:UInt32" outType="xs:unsignedInt"></data> EventHandler<ProcessEventArgs> handler = this.ProcessStopped; if (handler != null) { int processId = (int)traceEvent.ReadUInt32(); traceEvent.ReadFileTime(); // ignore DateTime exitTime = traceEvent.ReadFileTime(); int exitCode = (int)traceEvent.ReadUInt32(); ProcessEventArgs e = new ProcessEventArgs() { ExitCode = exitCode, Id = processId, Timestamp = exitTime }; handler(this, e); } break; } }
private Envelope ParseV2(EtwNativeEvent etwNativeEvent) { uint packageId = etwNativeEvent.ReadUInt32(); long occurenceFileTimeUtc = etwNativeEvent.ReadInt64(); long receiveFileTimeUtc = etwNativeEvent.ReadInt64(); string protocol = etwNativeEvent.ReadUnicodeString(); string source = etwNativeEvent.ReadUnicodeString(); string manifestId = etwNativeEvent.ReadUnicodeString(); uint chunkCount = etwNativeEvent.ReadUInt32(); uint currentChunkNumber = etwNativeEvent.ReadUInt32(); uint eventPayloadLength = etwNativeEvent.ReadUInt32(); // There is a side-effect being used here with the binary length. etwNativeEvent.ReadUInt32(); byte[] eventPayload = etwNativeEvent.ReadBytes(); if (chunkCount == 1) { this.eventCache.Clear(); return new Envelope( occurenceFileTimeUtc >= 0 ? DateTimeOffset.FromFileTime(occurenceFileTimeUtc) : DateTimeOffset.MinValue, receiveFileTimeUtc >= 0 ? DateTimeOffset.FromFileTime(receiveFileTimeUtc) : DateTimeOffset.MinValue, protocol, source, manifestId, eventPayload, null); } else if (chunkCount > currentChunkNumber) { if (this.currentEventPackageId != packageId || this.eventCache.Count != currentChunkNumber) { this.eventCache.Clear(); this.currentEventPackageId = packageId; } this.eventCache.Add(eventPayload); if (chunkCount == (currentChunkNumber + 1)) { var payload = ByteArrayHelper.Join(this.eventCache); this.eventCache.Clear(); return new Envelope( occurenceFileTimeUtc >= 0 ? DateTimeOffset.FromFileTime(occurenceFileTimeUtc) : DateTimeOffset.MinValue, receiveFileTimeUtc >= 0 ? DateTimeOffset.FromFileTime(receiveFileTimeUtc) : DateTimeOffset.MinValue, protocol, source, manifestId, eventPayload, null); } } else { this.eventCache.Clear(); } return null; }
private BinaryEnvelope ParseV2(EtwNativeEvent etwNativeEvent) { uint packageId = etwNativeEvent.ReadUInt32(); long occurenceFileTimeUtc = etwNativeEvent.ReadInt64(); long receiveFileTimeUtc = etwNativeEvent.ReadInt64(); string protocol = etwNativeEvent.ReadUnicodeString(); string source = etwNativeEvent.ReadUnicodeString(); string manifestId = etwNativeEvent.ReadUnicodeString(); uint chunkCount = etwNativeEvent.ReadUInt32(); uint currentChunkNumber = etwNativeEvent.ReadUInt32(); uint eventPayloadLength = etwNativeEvent.ReadUInt32(); // There is a side-effect being used here with the binary length. etwNativeEvent.ReadUInt32(); byte[] eventPayload = etwNativeEvent.ReadBytes(); if (chunkCount == 1) { this.eventCache.Clear(); return new BinaryEnvelope { ActivityId = etwNativeEvent.ActivityId, OccurenceFileTimeUtc = occurenceFileTimeUtc, ReceiveFileTimeUtc = receiveFileTimeUtc, Protocol = protocol, Source = source, PayloadId = manifestId, EventPayload = eventPayload, EventPayloadLength = eventPayloadLength }; } else if (chunkCount > currentChunkNumber) { if (this.currentEventPackageId != packageId || this.eventCache.Count != currentChunkNumber) { this.eventCache.Clear(); this.currentEventPackageId = packageId; } this.eventCache.Add(eventPayload); if (chunkCount == (currentChunkNumber + 1)) { var payload = ByteArrayHelper.Join(this.eventCache); this.eventCache.Clear(); return new BinaryEnvelope { ActivityId = etwNativeEvent.ActivityId, OccurenceFileTimeUtc = occurenceFileTimeUtc, ReceiveFileTimeUtc = receiveFileTimeUtc, Protocol = protocol, Source = source, PayloadId = manifestId, EventPayload = payload, EventPayloadLength = unchecked((uint)(payload.Length)), }; } } else { this.eventCache.Clear(); } return null; }