Source/Tx.Windows/EtwNative/EtwNativeEvent.cs (356 lines of code) (raw):
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Runtime.InteropServices;
using System.Security.Principal;
namespace Tx.Windows
{
/// <summary>
/// EtwNativeEvent represents event from ETW as native structure
/// Note that the structure is not a C# object - it is not on the heap or on the stack
/// instead, it is in ETW's dedicated buffer
/// </summary>
public unsafe struct EtwNativeEvent
{
internal byte* _data;
internal byte* _end;
internal uint _length; // used to remember the last UInt32, and as length to read the following win:Binary
public EVENT_RECORD* record;
#region struct EVENT_HEADER
public UInt16 Size
{
get { return record->EventHeader.Size; }
}
public UInt16 HeaderType
{
get { return record->EventHeader.HeaderType; }
}
public UInt16 Flags
{
get { return record->EventHeader.Flags; }
}
public UInt16 EventProperty
{
get { return record->EventHeader.EventProperty; }
}
public UInt32 ThreadId
{
get { return record->EventHeader.ThreadId; }
}
public UInt32 ProcessId
{
get { return record->EventHeader.ProcessId; }
}
public UInt16 ProcessorId
{
get
{
if ((record->EventHeader.Flags & EtwNativeMethods.EVENT_HEADER_FLAG_PROCESSOR_INDEX) != 0)
{
return record->BufferContext.ProcessorIndex;
}
return record->BufferContext.ProcessorNumber;
}
}
public DateTimeOffset TimeStamp
{
get { return TimeUtil.DateTimeOffsetFromFileTime(record->EventHeader.TimeStamp); }
}
public Int64 TimeStampRaw
{
get { return record->EventHeader.TimeStamp; }
}
public Guid ProviderId
{
get { return record->EventHeader.ProviderId; }
}
public UInt64 ProcessorTime
{
get { return record->EventHeader.ProcessorTime; }
}
public Guid ActivityId
{
get { return record->EventHeader.ActivityId; }
}
#region struct EVENT_DESCRIPTOR
public UInt16 Id
{
get { return record->EventHeader.EventDescriptor.Id; }
}
public byte Version
{
get { return record->EventHeader.EventDescriptor.Version; }
}
public byte Channel
{
get { return record->EventHeader.EventDescriptor.Channel; }
}
public byte Level
{
get { return record->EventHeader.EventDescriptor.Level; }
}
public byte Opcode
{
get { return record->EventHeader.EventDescriptor.Opcode; }
}
public UInt16 Task
{
get { return record->EventHeader.EventDescriptor.Task; }
}
public UInt64 Keyword
{
get { return record->EventHeader.EventDescriptor.Keyword; }
}
#endregion
#endregion
public UInt16 ExtendedDataCount
{
get { return record->ExtendedDataCount; }
}
public UInt16 UserDataLength
{
get { return record->UserDataLength; }
}
public IntPtr ExtendedData
{
get { return record->ExtendedData; }
}
public IntPtr UserData
{
get { return record->UserData; }
}
public IntPtr UserContext
{
get { return record->UserContext; }
}
public byte ReadByte()
{
byte value = *(_data);
_data += sizeof (byte);
return value;
}
public char ReadAnsiChar()
{
byte value = *(_data);
_data += sizeof (byte);
return (char) value;
}
public char ReadChar()
{
char value = *((char*) _data);
_data += sizeof (char);
return value;
}
public double ReadDouble(int length)
{
double value = *((double*) _data);
_data += sizeof (double);
return value;
}
public sbyte ReadInt8()
{
sbyte value = *((sbyte*) _data);
_data += sizeof (sbyte);
return value;
}
public byte ReadUInt8()
{
byte value = *_data;
_data += sizeof (byte);
return value;
}
public short ReadInt16()
{
short value = *((short*) _data);
_data += sizeof (short);
return value;
}
public ushort ReadUInt16()
{
ushort value = *((ushort*) _data);
_data += sizeof (ushort);
return value;
}
public int ReadInt32()
{
int value = *((int*) _data);
_data += sizeof (int);
return value;
}
public uint ReadUInt32()
{
uint value = *((uint*) _data);
_data += sizeof (uint);
_length = value;
return value;
}
public long ReadInt64()
{
long value = *((long*) _data);
_data += sizeof (long);
return value;
}
public ulong ReadUInt64()
{
ulong value = *((ulong*) _data);
_data += sizeof (ulong);
return value;
}
public ulong ReadPointer()
{
if ((Flags & EtwNativeMethods.EVENT_HEADER_FLAG_32_BIT_HEADER) != 0)
{
return ReadUInt32();
}
return ReadUInt64();
}
public bool ReadBoolean()
{
bool value = *((int*) _data) != 0;
_data += 4; // 32 bit value. See: http://msdn.microsoft.com/en-us/library/aa382774(v=vs.85)
return value;
}
public float ReadFloat()
{
float value = *((float*) _data);
_data += sizeof (float);
return value;
}
public double ReadDouble()
{
double value = *((double*) _data);
_data += sizeof (double);
return value;
}
public DateTime ReadFileTime()
{
long value = *((long*) _data);
_data += sizeof (long);
return DateTime.FromFileTimeUtc(value);
}
public DateTime ReadSystemTime()
{
int year = ReadInt16();
int month = ReadInt16();
ReadInt16(); // dayOfWeek
int day = ReadInt16();
int hour = ReadInt16();
int minute = ReadInt16();
int second = ReadInt16();
int milliseconds = ReadInt16();
return new DateTime(year, month, day, hour, minute, second, milliseconds);
}
public Guid ReadGuid()
{
var value = new Guid(
*((int*) _data),
*((short*) (_data + 4)),
*((short*) (_data + 6)),
*(_data + 8),
*(_data + 9),
*(_data + 10),
*(_data + 11),
*(_data + 12),
*(_data + 13),
*(_data + 14),
*(_data + 15));
_data += sizeof (Guid);
return value;
}
public byte[] ReadBytes()
{
var value = new byte[_length];
fixed (byte* pb = value)
{
TypeServiceUtil.MemCopy(_data, pb, (int) _length);
}
_data += _length;
return value;
}
public byte[] ReadBytes(uint length)
{
var value = new byte[length];
fixed (byte* pb = value)
{
TypeServiceUtil.MemCopy(_data, pb, (int)length);
}
_data += length;
return value;
}
public string ReadAnsiString(int length)
{
string str = Marshal.PtrToStringAnsi((IntPtr) _data, length);
_data += length;
return str;
}
public string ReadAnsiString()
{
byte* end;
for (end = _data; end < _end; end++)
{
if (0 == *end)
break;
}
string str = Marshal.PtrToStringAnsi((IntPtr) _data, (int) (end - _data));
int length = (str.Length + 1);
_data += length;
return str;
}
public string ReadUnicodeString()
{
var str = new string((char*) _data);
int maxLength = (int) (_end - _data) >> 1;
if (maxLength <= 0)
return string.Empty;
if (str.Length > maxLength)
str = str.Substring(0, maxLength);
_data += (str.Length + 1) << 1;
return str;
}
public string ReadUnicodeString(int fixedLength)
{
char* end;
int charsRead = 0;
for (end = (char*) _data; end < (char*) _end; end++)
{
if (0 == *end)
break;
if (charsRead == fixedLength)
break;
charsRead++;
}
string str = Marshal.PtrToStringUni((IntPtr) _data, (int)(((byte*)end) - _data) >> 1);
int length = (str.Length + 1) * sizeof(char);
if (fixedLength > 0)
{
_data += fixedLength * sizeof(char);
}
else
{
_data += (length);
}
return str;
}
public string ReadAnsiStringPrefixLen()
{
// reads a string, assuming the lenght was win:UInt32 right before it in the manifest
string str = Marshal.PtrToStringAnsi((IntPtr) _data, (int)_length);
_data += _length;
return str;
}
public string ReadUnicodeStringPrefixLen()
{
// reads a string, assuming the lenght was win:UInt32 right before it in the manifest
var chars = new char[_length];
for (int i = 0; i < _length; i++)
{
chars[i] = (char) ReadInt16();
}
var str = new string(chars);
return str;
}
public string ReadSid()
{
var sid = new SecurityIdentifier((IntPtr) _data);
_data += sid.BinaryLength;
return sid.Value;
}
public void ResetReader()
{
_data = (byte*) UserData.ToPointer();
_end = _data + UserDataLength;
}
}
}