internal PropertyBag GetProperties(EventRecord eventRecord)
        {
            // We only support top level properties and simple types
            PropertyBag properties = new PropertyBag(_traceEventInfo.TopLevelPropertyCount);

            if (this._hasProperties) {

                int offset = 0;

                for (int i = 0; i < _traceEventInfo.TopLevelPropertyCount; i++) {
                    EventPropertyInfo info = _eventPropertyInfoArray[i];

                    // Read the current property name
                    string propertyName = Marshal.PtrToStringUni(new IntPtr(_address.ToInt64() + info.NameOffset));

                    object value;
                    string mapName;
                    int length;
                    IntPtr dataPtr = new IntPtr(eventRecord.UserData.ToInt64() + offset);

                    value = ReadPropertyValue(info, dataPtr, out mapName, out length);

                    // If we have a map name, return both map name and map value as a pair.
                    if (!string.IsNullOrEmpty(mapName)) {
                        value = new KeyValuePair<string, object>(mapName, value);
                    }

                    offset += length;
                    properties.Add(propertyName, value);
                }

                if (offset < eventRecord.UserDataLength) {
                    //
                    // There is some extra information not mapped.
                    //
                    IntPtr dataPtr = new IntPtr(eventRecord.UserData.ToInt64() + offset);
                    int length = eventRecord.UserDataLength - offset;
                    byte[] array = new byte[length];

                    for (int index = 0; index < length; index++) {
                        array[index] = Marshal.ReadByte(dataPtr, index);
                    }

                    properties.Add("__ExtraPayload", array);
                }
            }
            else {
                // NOTE: It is just a guess that this is an Unicode string
                string str = Marshal.PtrToStringUni(eventRecord.UserData);

                properties.Add("EventData", str);
            }

            return properties;
        }
        private EventArrivedEventArgs CreateEventArgsFromEventRecord(EventRecord eventRecord)
        {
            byte eventOpcode = eventRecord.EventHeader.EventDescriptor.Opcode;
            TraceEventInfoWrapper traceEventInfo;
            bool shouldDispose = false;

            // Find the event information (schema).
            int index = this.traceEventInfoCache.IndexOfKey(eventOpcode);
            if (index >= 0) {
                traceEventInfo = this.traceEventInfoCache.Values[index];
            }
            else {
                traceEventInfo = new TraceEventInfoWrapper(eventRecord);
                try {
                    this.traceEventInfoCache.Add(eventOpcode, traceEventInfo);
                }
                catch (ArgumentException) {
                    // Some other thread added this entry.
                    shouldDispose = true;
                }
            }

            // Get the properties using the current event information (schema).
            PropertyBag properties = traceEventInfo.GetProperties(eventRecord);
            // Dispose the event information because it doesn't live in the cache
            if (shouldDispose) {
                traceEventInfo.Dispose();
            }

            EventArrivedEventArgs args = new EventArrivedEventArgs(eventOpcode, properties);

            return args;
        }
 internal TraceEventInfoWrapper(EventRecord eventRecord)
 {
     Initialize(eventRecord);
 }
        private void Initialize(EventRecord eventRecord)
        {
            int size = 0;
            const uint BufferTooSmall = 122;
            const uint ErrorlementNotFound = 1168;

            int error = NativeMethods.TdhGetEventInformation(ref eventRecord, 0, IntPtr.Zero, IntPtr.Zero, ref size);
            if (error == ErrorlementNotFound) {
                // Nothing else to do here.
                this._hasProperties = false;
                return;
            }
            this._hasProperties = true;

            if (error != BufferTooSmall) {
                throw new Win32Exception(error);
            }

            // Get the event information (schema)
            this._address = Marshal.AllocHGlobal(size);
            error = NativeMethods.TdhGetEventInformation(ref eventRecord, 0, IntPtr.Zero, _address, ref size);
            if (error != 0) {
                throw new System.ComponentModel.Win32Exception(error);
            }

            // Marshal the first part of the trace event information.
            _traceEventInfo = (TraceEventInfo)Marshal.PtrToStructure(this._address, typeof(TraceEventInfo));

            // Marshal the second part of the trace event information, the array of property info.
            int actualSize = Marshal.SizeOf(this._traceEventInfo);
            if (size != actualSize) {
                int structSize = Marshal.SizeOf(typeof(EventPropertyInfo));
                int itemsLeft = (size - actualSize) / structSize;

                this._eventPropertyInfoArray = new EventPropertyInfo[itemsLeft];
                long baseAddress = _address.ToInt64() + actualSize;
                for (int i = 0; i < itemsLeft; i++) {
                    IntPtr structPtr = new IntPtr(baseAddress + (i * structSize));
                    EventPropertyInfo info = (EventPropertyInfo)Marshal.PtrToStructure(structPtr, typeof(EventPropertyInfo));
                    this._eventPropertyInfoArray[i] = info;
                }
            }

            // Get the opcode name
            if (_traceEventInfo.OpcodeNameOffset > 0) {
                this.EventName = Marshal.PtrToStringUni(new IntPtr(_address.ToInt64() + _traceEventInfo.OpcodeNameOffset));
            }
        }