private void Initialize(EventRecord eventRecord)
        {
            int        size            = 0;
            const uint BufferTooSmall  = 122;
            const uint ElementNotFound = 1168;

            this._traceEventInfo = new TraceEventInfo();
            int error = NativeMethods.TdhGetEventInformation(ref eventRecord, 0, IntPtr.Zero, IntPtr.Zero, ref size);

            if (error == ElementNotFound)
            {
                // Nothing else to do here.
                this._hasProperties = false;
                return;
            }
            this._hasProperties = true;

            if (error != BufferTooSmall)
            {
                throw new System.ComponentModel.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.
            Marshal.PtrToStructure(this._address, _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      = new EventPropertyInfo();
                    Marshal.PtrToStructure(structPtr, info);
                    this._eventPropertyInfoArray[i] = info;
                }
            }

            // Get the opcode name
            if (_traceEventInfo.OpcodeNameOffset > 0)
            {
                this.EventName = Marshal.PtrToStringUni(new IntPtr(_address.ToInt64() + _traceEventInfo.OpcodeNameOffset));
            }
        }
        internal IList <PropertyItem> GetProperties(EventRecord eventRecord)
        {
            // We only support top level properties and simple types
            IList <PropertyItem> properties = new List <PropertyItem>();

            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;

                    if (eventRecord.UserData == IntPtr.Zero)
                    {
                        mapName = string.Empty;
                        value   = string.Empty;
                        length  = info.LengthPropertyIndex;
                    }
                    else
                    {
                        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(new PropertyItem(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(new PropertyItem("__ExtraPayload", array));
                }
            }
            else
            {
                // NOTE: It is just a guess that this is an Unicode string
                string str = Marshal.PtrToStringUni(eventRecord.UserData);

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

            return(properties);
        }
        private object ReadPropertyValue(EventPropertyInfo info, IntPtr dataPtr, out string mapName, out int length)
        {
            length = info.LengthPropertyIndex;

            if (info.NonStructTypeValue.MapNameOffset != 0)
            {
                mapName = Marshal.PtrToStringUni(new IntPtr(this._address.ToInt64() + info.NonStructTypeValue.MapNameOffset));
            }
            else
            {
                mapName = string.Empty;
            }

            switch (info.NonStructTypeValue.InType)
            {
            case TdhInType.Null:
                break;

            case TdhInType.UnicodeString:
            {
                string str = Marshal.PtrToStringUni(dataPtr);
                length = (str.Length + 1) * sizeof(char);
                return(str);
            }

            case TdhInType.AnsiString:
            {
                string str = Marshal.PtrToStringAnsi(dataPtr);
                length = (str.Length + 1);
                return(str);
            }

            case TdhInType.Int8:
                return((sbyte)Marshal.ReadByte(dataPtr));

            case TdhInType.UInt8:
                return(Marshal.ReadByte(dataPtr));

            case TdhInType.Int16:
                return(Marshal.ReadInt16(dataPtr));

            case TdhInType.UInt16:
                return((uint)Marshal.ReadInt16(dataPtr));

            case TdhInType.Int32:
                return(Marshal.ReadInt32(dataPtr));

            case TdhInType.UInt32:
                return((uint)Marshal.ReadInt32(dataPtr));

            case TdhInType.Int64:
                return(Marshal.ReadInt64(dataPtr));

            case TdhInType.UInt64:
                return((ulong)Marshal.ReadInt64(dataPtr));

            case TdhInType.Float:
                return(BitConverter.ToSingle(BitConverter.GetBytes(Marshal.ReadInt32(dataPtr)), 0));

            case TdhInType.Double:
                return(BitConverter.ToDouble(BitConverter.GetBytes(Marshal.ReadInt64(dataPtr)), 0));

            case TdhInType.Boolean:
                return((bool)(Marshal.ReadInt32(dataPtr) != 0));

            case TdhInType.Binary:
                break;

            case TdhInType.Guid:
                return(new Guid(
                           Marshal.ReadInt32(dataPtr),
                           Marshal.ReadInt16(dataPtr, 4),
                           Marshal.ReadInt16(dataPtr, 6),
                           Marshal.ReadByte(dataPtr, 8),
                           Marshal.ReadByte(dataPtr, 9),
                           Marshal.ReadByte(dataPtr, 10),
                           Marshal.ReadByte(dataPtr, 11),
                           Marshal.ReadByte(dataPtr, 12),
                           Marshal.ReadByte(dataPtr, 13),
                           Marshal.ReadByte(dataPtr, 14),
                           Marshal.ReadByte(dataPtr, 15)
                           ));

            case TdhInType.Pointer:
                return(Marshal.ReadIntPtr(dataPtr));

            case TdhInType.FileTime:
                return(Marshal.ReadInt64(dataPtr));

            case TdhInType.SystemTime:
            {
                SYSTEMTIME st = new SYSTEMTIME();
                Marshal.PtrToStructure(dataPtr, st);
                return(st);
            }

            case TdhInType.SID:
                //TODO: use ConvertSidToStringSid
                return("SID");

            case TdhInType.HexInt32:
                break;

            case TdhInType.HexInt64:
                break;

            case TdhInType.CountedString:
                break;

            case TdhInType.CountedAnsiString:
                break;

            case TdhInType.ReversedCountedString:
                break;

            case TdhInType.ReversedCountedAnsiString:
                break;

            case TdhInType.NonNullTerminatedString:
                break;

            case TdhInType.NonNullTerminatedAnsiString:
                break;

            case TdhInType.UnicodeChar:
                break;

            case TdhInType.AnsiChar:
                break;

            case TdhInType.SizeT:
                break;

            case TdhInType.HexDump:
                break;

            case TdhInType.WbemSID:
                break;

            default:
                break;
            }

            Debugger.Break();
            return(null);
        }