Exemple #1
0
        public IEnumerable <EventRecord> ReadEventRecords(int startingOffset)
        {
            int offset = startingOffset;

            while (offset < this.buffer.Length)
            {
                ////verify header
                int signature = BitConverter.ToInt32(this.buffer, offset);
                if (signature != recordSignature)
                {
                    break;
                }

                EventRecord record = new EventRecord();
                record.ChunkOffset = offset;
                offset            += 4;
                record.BlockSize   = BitConverter.ToInt32(this.buffer, offset);

                offset         += 4;
                record.RecordId = BitConverter.ToUInt64(this.buffer, offset);

                offset           += 8;
                record.RecordTime = DateTime.FromFileTime(BitConverter.ToInt64(this.buffer, offset));

                offset += 8;
                FragmentHeader parentFragmentHeader = this.ReadFragmentHeader(record, ref offset);

                BinaryXmlTemplate template = null;
                if (parentFragmentHeader.ContainsTemplateDefinition)
                {
                    template = this.ReadBinaryXmlTemplateRecord(parentFragmentHeader, record, ref offset);
                    int recordOffset = offset;

                    try
                    {
                        template.RootElement = this.ReadBinaryXmlElement(ref recordOffset);
                        offset = recordOffset;
                    }
                    catch (Exception ex)
                    {
                        throw new BinaryXmlReadException(string.Format("Problem reading BinaryXml for record at offset {0} in ElfChunk offset {1}: {2}", record.ChunkOffset, this.fileOffset, ex.Message),
                                                         this.fileOffset,
                                                         record.GetNextRecordOffset());
                    }
                }

                template = this.templates[parentFragmentHeader.TemplateDefinitionOffset];

                ////whether we found a template or not, we should be in position to read value descriptors
                int valuesOffset = offset;
                ValueDescriptor[] descriptors = this.ReadValueDescriptors(ref valuesOffset);

                ////before enumerating the template elements check if the template found the event data yet.
                if (template.RootElement.ValueType == BinaryValueType.BinXmlType)
                {
                    if (!template.RootElement.Children.Any(e => e.Name == "EventData"))
                    {
                        valuesOffset = descriptors[template.RootElement.ValueIndex].Offset;

                        FragmentHeader childFragmentHeader = this.ReadFragmentHeader(record, ref valuesOffset);

                        ////Revisit to see if we really need to store the eventDataTemplate in the Dictionary
                        BinaryXmlTemplate eventDataTemplate = null;
                        if (childFragmentHeader.ContainsTemplateDefinition)
                        {
                            eventDataTemplate             = this.ReadBinaryXmlTemplateRecord(childFragmentHeader, record, ref valuesOffset);
                            eventDataTemplate.RootElement = this.ReadBinaryXmlElement(ref valuesOffset);
                        }

                        eventDataTemplate = this.templates[childFragmentHeader.TemplateDefinitionOffset];

                        template.RootElement.Children.Add(eventDataTemplate.RootElement);
                    }
                    else
                    {
                        ////move the offset forward to the inner value descriptors for event data
                        valuesOffset = descriptors[template.RootElement.ValueIndex].Offset;
                        FragmentHeader instanceHeader = this.ReadFragmentHeader(record, ref valuesOffset);
                    }
                }

                foreach (BinaryXmlElement element in template.RootElement.EnumerateAllChildren().Where(e => e.Name != "Data"))
                {
                    switch (element.Name)
                    {
                    case "Level":
                        byte eventLevel = this.buffer[descriptors[element.ValueIndex].Offset];
                        record.SetEventLevel(eventLevel);
                        break;

                    case "Provider":
                        if (element.Attributes.Count > 0)
                        {
                            if (!string.IsNullOrEmpty(element.Attributes[0].Value))
                            {
                                record.Provider = element.Attributes[0].Value;
                            }
                            else
                            {
                                ////might be optional substitution
                                record.Provider = Encoding.Unicode.GetString(
                                    this.buffer,
                                    descriptors[element.Attributes[0].ValueIndex].Offset,
                                    descriptors[element.Attributes[0].ValueIndex].Size);
                            }
                        }
                        else
                        {
                            record.Provider = "Unknown";
                        }

                        break;

                    case "TimeCreated":
                        BinaryXmlAttribute systemTimeAttribute = element.Attributes.FirstOrDefault(e => e.Name == "SystemTime");
                        if (systemTimeAttribute != null && systemTimeAttribute.ValueType == BinaryValueType.FileTime)
                        {
                            long fileTime = BitConverter.ToInt64(this.buffer, descriptors[systemTimeAttribute.ValueIndex].Offset);
                            record.TimeCreated = DateTime.FromFileTime(fileTime);
                        }

                        break;

                    case "EventData":
                        ValueDescriptor[] eventDataDescriptors = this.ReadValueDescriptors(ref valuesOffset);
                        StringBuilder     message = new StringBuilder();
                        foreach (BinaryXmlElement dataElement in element.EnumerateAllChildren().Where(e =>
                                                                                                      e.Name == "Data" &&
                                                                                                      e.ValueType == BinaryValueType.Utf16StringArray))
                        {
                            ////There is a null terminator at the end of these
                            int dataOffset = eventDataDescriptors[dataElement.ValueIndex].Offset;
                            int dataSize   = eventDataDescriptors[dataElement.ValueIndex].Size;
                            if (dataOffset + dataSize > this.buffer.Length)
                            {
                                ////I think the buffer is recycled by the writer, and not cleaned up afterwards.  I was seeing garbage data after the LastRecordId.
                                ////I believe it just so happened that the garbage started with 0x2A2A0000 which made the logic believe there was a next record in the chunk.
                                ////Even so, I will leave this here just in case this scenario really does occur.
                                throw new EventDataOutsideOfBufferException(
                                          string.Format("Event data is refrenced outside of buffer. Record Offset: {0} BinaryXmlElement.Offset: {1}", this.FileOffset + record.ChunkOffset, dataElement.Offset),
                                          this.fileOffset + 65536,
                                          (int)ElfChunk.HeaderSize);
                            }

                            message.Append(Encoding.Unicode.GetString(this.buffer, dataOffset, dataSize).TrimEnd('\0'));
                        }

                        record.Message = message.ToString();

                        break;
                    }
                }

                offset = record.GetNextRecordOffset();
                yield return(record);

                if (record.RecordId == this.lastRecordId)
                {
                    yield break;
                }
            }
        }
Exemple #2
0
        private BinaryXmlElement ReadBinaryXmlElement(ref int offset)
        {
            bool             hasAttributes = this.buffer[offset] == 0x41;
            BinaryXmlElement element       = new BinaryXmlElement();

            element.Offset = offset;

            ////I don't know what the next two bytes mean
            offset        += 3;
            element.Length = BitConverter.ToInt32(this.buffer, offset) + 7;

            offset += 4;
            int nameOffset = BitConverter.ToInt32(this.buffer, offset);

            element.Name = this.ReadName(ref nameOffset);
            if (nameOffset < element.Offset)
            {
                ////The name was stored with a previous element.  Restore the offset plus the length of pointer for the name
                offset    += 4;
                nameOffset = offset;
            }

            if (hasAttributes)
            {
                int attributesOffset = nameOffset;
                int attributesSize   = BitConverter.ToInt32(this.buffer, attributesOffset);

                attributesOffset += 4;
                offset            = attributesOffset;
                while (hasAttributes)
                {
                    hasAttributes = this.buffer[attributesOffset] == 0x46;
                    attributesOffset++;
                    offset = attributesOffset;

                    ////seems silly because this is getting an offset immeadiately after the offset
                    attributesOffset = BitConverter.ToInt32(this.buffer, attributesOffset);

                    BinaryXmlAttribute attribute = new BinaryXmlAttribute();
                    attribute.Name = this.ReadName(ref attributesOffset);
                    if (attributesOffset < element.Offset)
                    {
                        ////The name was stored with a previous element.  Restore the offset plus the length of pointer for the name
                        attributesOffset = offset + 4;
                    }

                    this.ReadAttribute(attribute, ref attributesOffset);
                    element.Attributes.Add(attribute);
                }

                offset = attributesOffset;
            }
            else
            {
                offset = nameOffset;
            }

            this.ProcessNextXmlToken(element, ref offset);

            while (offset < element.Offset + element.Length &&
                   (this.buffer[offset] == 0x41 || this.buffer[offset] == 0x01))
            {
                element.Children.Add(this.ReadBinaryXmlElement(ref offset));
            }

            this.ProcessNextXmlToken(element, ref offset);
            if (this.buffer[offset] == 0x00)
            {
                ////null terminator for the template
                offset++;
            }

            return(element);
        }