/// <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();
        }
Exemple #2
0
            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;
 }