/// <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(); }
public IEventTraceOperand Build(int eventMetadataTableIndex) { var buffer = (byte *)this.traceEventInfo; EVENT_PROPERTY_INFO *eventPropertyInfoArr = (EVENT_PROPERTY_INFO *)&this.traceEventInfo->EventPropertyInfoArray; string provider = this.BuildName("Provider", this.traceEventInfo->ProviderGuid.ToString(), this.traceEventInfo->ProviderNameOffset); string task = this.BuildName("EventID", this.traceEventInfo->Id.ToString(), this.traceEventInfo->TaskNameOffset); string opcode = this.BuildName("Opcode", this.traceEventInfo->Opcode.ToString(), this.traceEventInfo->OpcodeNameOffset); var topLevelOperands = this.IterateProperties(buffer, 0, (int)traceEventInfo->TopLevelPropertyCount, eventPropertyInfoArr); return(new EventTraceOperand(new EventMetadata(this.traceEventInfo->ProviderGuid, this.traceEventInfo->Id, this.traceEventInfo->Version, provider + "/" + task + "/" + opcode, this.flatPropertyList.Select(t => t.Metadata).ToArray()), eventMetadataTableIndex, topLevelOperands)); }
public IEventTraceOperand Build(int eventMetadataTableIndex) { var buffer = (byte *)this.traceEventInfo; EVENT_PROPERTY_INFO *eventPropertyInfoArr = (EVENT_PROPERTY_INFO *)&this.traceEventInfo->EventPropertyInfoArray; string provider = this.BuildName("Provider", this.traceEventInfo->ProviderGuid.ToString(), this.traceEventInfo->ProviderNameOffset); string task = this.BuildName("EventID", this.traceEventInfo->Id.ToString(), this.traceEventInfo->TaskNameOffset); string opcode = this.BuildName("Opcode", this.traceEventInfo->Opcode.ToString(), this.traceEventInfo->OpcodeNameOffset); string message = this.BuildName("EventMessage", "0", this.traceEventInfo->EventMessageOffset); //WPP properties not supported int end = this.traceEventInfo->DecodingSource == DECODING_SOURCE.DecodingSourceWPP ? 0 : (int)traceEventInfo->TopLevelPropertyCount; var topLevelOperands = this.IterateProperties(buffer, 0, end, eventPropertyInfoArr); return(new EventTraceOperand(new EventMetadata(this.traceEventInfo->ProviderGuid, this.traceEventInfo->Id, this.traceEventInfo->Version, provider + "/" + task + "/" + opcode, this.flatPropertyList.Select(t => t.Metadata).ToArray(), message), eventMetadataTableIndex, topLevelOperands)); }
private List <EventTracePropertyOperand> IterateProperties(byte *buffer, List <EventTracePropertyOperand> operands, int start, int end, EVENT_PROPERTY_INFO *eventPropertyInfoArr) { var returnList = new List <EventTracePropertyOperand>(); for (int i = start; i < end; ++i) { var eventPropertyInfo = &eventPropertyInfoArr[i]; string propertyName = new string((char *)&buffer[eventPropertyInfo->NameOffset]); int structchildren = eventPropertyInfo->StructType.NumOfStructMembers; bool isStruct = (eventPropertyInfo->Flags & PROPERTY_FLAGS.PropertyStruct) == PROPERTY_FLAGS.PropertyStruct; bool isVariableArray = (eventPropertyInfo->Flags & PROPERTY_FLAGS.PropertyParamCount) == PROPERTY_FLAGS.PropertyParamCount; bool isFixedArray = (eventPropertyInfo->Flags & PROPERTY_FLAGS.PropertyParamFixedCount) == PROPERTY_FLAGS.PropertyParamFixedCount; bool isVariableLength = (eventPropertyInfo->Flags & PROPERTY_FLAGS.PropertyParamLength) == PROPERTY_FLAGS.PropertyParamLength; bool isFixedLength = (eventPropertyInfo->Flags & PROPERTY_FLAGS.PropertyParamFixedLength) == PROPERTY_FLAGS.PropertyParamFixedLength; bool isWbemXmlFragment = (eventPropertyInfo->Flags & PROPERTY_FLAGS.PropertyWBEMXmlFragment) == PROPERTY_FLAGS.PropertyWBEMXmlFragment; // NOTE: Do not remove this special case, there are cases like this, we just assume it's a fixed array if (!isFixedArray && !isVariableArray && eventPropertyInfo->count > 1) { isFixedArray = true; } string mapName = null; Dictionary <uint, string> mapOfValues = null; if (eventPropertyInfo->NonStructType.MapNameOffset != 0) { byte *mapBuffer = (byte *)0; uint bufferSize; var fakeEventRecord = new EVENT_RECORD { ProviderId = this.traceEventInfo->ProviderGuid }; mapName = new string((char *)&buffer[eventPropertyInfo->NonStructType.MapNameOffset]); Tdh.GetEventMapInformation(&fakeEventRecord, mapName, mapBuffer, out bufferSize); mapBuffer = (byte *)Marshal.AllocHGlobal((int)bufferSize); Tdh.GetEventMapInformation(&fakeEventRecord, mapName, mapBuffer, out bufferSize); EVENT_MAP_INFO *mapInfo = (EVENT_MAP_INFO *)mapBuffer; if (mapInfo->MapEntryValueType == MAP_VALUETYPE.EVENTMAP_ENTRY_VALUETYPE_ULONG) { var mapEntry = (EVENT_MAP_ENTRY *)&mapInfo->MapEntryArray; mapOfValues = new Dictionary <uint, string>(); for (int j = 0; j < mapInfo->EntryCount; ++j) { var offset = mapEntry[j].OutputOffset; if (offset > bufferSize) { // TDH has a bug (it seems) that is giving rogue values here // We should log this } else { var mapEntryValue = mapEntry[j].Value; string mapEntryName; if (!mapOfValues.TryGetValue(mapEntryValue, out mapEntryName)) { mapEntryName = new string((char *)&mapBuffer[offset]); mapOfValues.Add(mapEntryValue, mapEntryName); } } } } Marshal.FreeHGlobal((IntPtr)mapBuffer); } /* save important information in an object */ var operand = new EventTracePropertyOperand( new PropertyMetadata((TDH_IN_TYPE)eventPropertyInfo->NonStructType.InType, (TDH_OUT_TYPE)eventPropertyInfo->NonStructType.OutType, propertyName, mapOfValues != null, isStruct, isStruct ? structchildren : 0, new MapInformation(mapName, mapOfValues)), i, isVariableArray, isFixedArray, isVariableLength, isFixedLength, isWbemXmlFragment); this.flatPropertyList.Add(operand); operands.Add(operand); returnList.Add(operand); /* if this references a previous field, we need to capture that as a local */ if (isVariableArray) { var reference = operands[eventPropertyInfo->countPropertyIndex]; reference.IsReferencedByOtherProperties = true; operand.SetVariableArraySize(reference); } else if (isFixedArray) { operand.SetFixedArraySize(eventPropertyInfo->count); } /* if this references a previous field, we need to capture that as a local */ if (isVariableLength) { var reference = operands[eventPropertyInfo->lengthPropertyIndex]; reference.IsReferencedByOtherProperties = true; operand.SetVariableLengthSize(reference); } else if (isFixedLength) { operand.SetFixedLengthSize(eventPropertyInfo->length); } if ((eventPropertyInfo->Flags & PROPERTY_FLAGS.PropertyStruct) == PROPERTY_FLAGS.PropertyStruct) { var innerProps = this.IterateProperties( buffer, operands, eventPropertyInfo->StructType.StructStartIndex, eventPropertyInfo->StructType.StructStartIndex + eventPropertyInfo->StructType.NumOfStructMembers, eventPropertyInfoArr); foreach (var innerProp in innerProps) { operand.Children.Add(innerProp); } } } return(returnList); }
private List <EventTracePropertyOperand> IterateProperties(byte *buffer, int start, int end, EVENT_PROPERTY_INFO *eventPropertyInfoArr) { var operands = new List <EventTracePropertyOperand>(); return(this.IterateProperties(buffer, operands, start, end, eventPropertyInfoArr)); }
protected override DynamicTraceEventData TryLookup(TraceEvent unknownEvent) { DynamicTraceEventData ret = null; // TODO react if 4K is not big enough, cache the buffer?, handle more types, handle structs... int buffSize = 4096; byte *buffer = (byte *)System.Runtime.InteropServices.Marshal.AllocHGlobal(buffSize); int status = TdhGetEventInformation(unknownEvent.eventRecord, 0, null, buffer, &buffSize); if (status == 0) { TRACE_EVENT_INFO * eventInfo = (TRACE_EVENT_INFO *)buffer; EVENT_PROPERTY_INFO *propertyInfos = &eventInfo->EventPropertyInfoArray; string taskName = null; if (eventInfo->TaskNameOffset != 0) { taskName = (new string((char *)(&buffer[eventInfo->TaskNameOffset]))).Trim(); } string opcodeName = null; if (eventInfo->OpcodeNameOffset != 0) { opcodeName = (new string((char *)(&buffer[eventInfo->OpcodeNameOffset]))).Trim(); if (opcodeName.StartsWith("win:")) { opcodeName = opcodeName.Substring(4); } } string providerName = "UnknownProvider"; if (eventInfo->ProviderNameOffset != 0) { providerName = new string((char *)(&buffer[eventInfo->ProviderNameOffset])); } var eventID = unknownEvent.ClassicProvider ? TraceEventID.Illegal : unknownEvent.eventID; var newTemplate = new DynamicTraceEventData(null, (int)eventID, (int)unknownEvent.task, taskName, unknownEvent.taskGuid, (int)unknownEvent.Opcode, opcodeName, unknownEvent.ProviderGuid, providerName); newTemplate.payloadNames = new string[eventInfo->TopLevelPropertyCount]; newTemplate.payloadFetches = new DynamicTraceEventData.PayloadFetch[eventInfo->TopLevelPropertyCount]; ushort offset = 0; for (int i = 0; i < eventInfo->TopLevelPropertyCount; i++) { var propertyInfo = &propertyInfos[i]; var propertyName = new string((char *)(&buffer[propertyInfo->NameOffset])); // Remove anything that does not look like an ID (.e.g space) newTemplate.payloadNames[i] = Regex.Replace(propertyName, "[^A-Za-z0-9_]", ""); newTemplate.payloadFetches[i].type = GetTypeForTdhInType(propertyInfo->InType); // Determine whether the size variable or not, and set 'size' based on that. ushort size = DynamicTraceEventData.UNKNOWN_SIZE; // is this dynamically sized with another field specifying the length? if ((propertyInfo->Flags & PROPERTY_FLAGS.ParamLength) != 0) { if (propertyInfo->LengthOrLengthIndex == i - 1) { if (propertyInfos[i - 1].LengthOrLengthIndex == 4) { size = DynamicTraceEventData.COUNT32_PRECEEDS; } else if (propertyInfos[i - 1].LengthOrLengthIndex == 2) { size = DynamicTraceEventData.COUNT16_PRECEEDS; } else { Trace.WriteLine("WARNING: Unexpected dynamic length, giving up"); } } if (size != DynamicTraceEventData.UNKNOWN_SIZE && propertyInfo->InType == TdhInputType.AnsiString) { size |= DynamicTraceEventData.IS_ANSI; } } else { if (propertyInfo->InType == TdhInputType.AnsiString) { size = DynamicTraceEventData.NULL_TERMINATED | DynamicTraceEventData.IS_ANSI; } else if (propertyInfo->InType == TdhInputType.UnicodeString) { size = DynamicTraceEventData.NULL_TERMINATED; } else if (propertyInfo->InType == TdhInputType.Pointer) { size = DynamicTraceEventData.POINTER_SIZE; } else { // No, then it it fixed size (but give up if it is too big) var fixedSize = propertyInfo->CountOrCountIndex * propertyInfo->LengthOrLengthIndex; if (fixedSize < 0x7FF0) { size = (ushort)fixedSize; if (propertyInfo->InType == TdhInputType.AnsiString) { size += 0x8000; } } } } // Currently we give up on any other flags (arrays, structs). if ((propertyInfo->Flags & ~PROPERTY_FLAGS.ParamLength) != 0) { size = DynamicTraceEventData.UNKNOWN_SIZE; } newTemplate.payloadFetches[i].size = (ushort)size; newTemplate.payloadFetches[i].offset = offset; if (size >= DynamicTraceEventData.SPECIAL_SIZES) { offset = ushort.MaxValue; // Indicate that the offset must be computed at run time. } else if (offset != ushort.MaxValue) { Debug.Assert(offset + size < ushort.MaxValue); offset += size; } } ret = newTemplate; // return this as the event template for this lookup. } System.Runtime.InteropServices.Marshal.FreeHGlobal((IntPtr)buffer); return(ret); }
public EventPropertyInfoCPtr(EVENT_PROPERTY_INFO *pEventPropertyInfo) { this.pEventPropertyInfo = pEventPropertyInfo; }