in Source/Tx.Windows/EtwNative/EtwTypeMap.cs [20:191]
public Func<EtwNativeEvent, object> GetTransform(Type outputType)
{
Expression<Func<EtwNativeEvent, SystemEvent>> template = e =>
new SystemEvent
{
Header = new SystemHeader
{
Timestamp = e.TimeStamp.UtcDateTime,
ActivityId = e.ActivityId,
RelatedActivityId =
GetRelatedActivityId(
e.ExtendedDataCount,
e.ExtendedData, e.Flags),
PmcCounters =
GetPmcCounters(
e.ExtendedDataCount,
e.ExtendedData),
ProviderId = e.ProviderId,
EventId = e.Id,
Opcode = e.Opcode,
Version = e.Version,
ProcessId = e.ProcessId,
ProcessorId = e.ProcessorId,
ThreadId = e.ThreadId,
Level = e.Level,
Channel = e.Channel,
Task = e.Task,
Keywords = e.Keyword,
}
};
if (outputType == typeof (SystemEvent))
return template.Compile();
LambdaExpression ex = template;
var mi = (MemberInitExpression) ex.Body;
var bindings = new List<MemberBinding>(mi.Bindings);
ParameterExpression reader = ex.Parameters[0];
PropertyInfo[] properties = outputType.GetProperties();
foreach (PropertyInfo p in properties)
{
var attribute = p.GetCustomAttribute<EventFieldAttribute>();
if (attribute == null) continue;
Expression readExpression = null;
switch (attribute.OriginalType)
{
case "win:Boolean":
readExpression = MakeExpression(r => r.ReadBoolean(), reader);
break;
case "win:Pointer":
readExpression = MakeExpression(r => r.ReadPointer(), reader);
break;
case "win:Int8":
readExpression = MakeExpression(r => r.ReadInt8(), reader);
break;
case "win:UInt8":
readExpression = MakeExpression(r => r.ReadUInt8(), reader);
break;
case "win:Int16":
readExpression = MakeExpression(r => r.ReadInt16(), reader);
break;
case "win:UInt16":
readExpression = MakeExpression(r => r.ReadUInt16(), reader);
break;
case "win:Int32":
readExpression = MakeExpression(r => r.ReadInt32(), reader);
break;
case "win:HexInt32":
case "win:UInt32":
readExpression = MakeExpression(r => r.ReadUInt32(), reader);
break;
case "win:Int64":
readExpression = MakeExpression(r => r.ReadInt64(), reader);
break;
case "win:HexInt64":
case "win:UInt64":
readExpression = MakeExpression(r => r.ReadUInt64(), reader);
break;
case "win:Double":
readExpression = MakeExpression(r => r.ReadDouble(), reader);
break;
case "win:Float":
readExpression = MakeExpression(r => r.ReadFloat(), reader);
break;
case "win:UnicodeString":
if (!String.IsNullOrEmpty(attribute.Length))
{
int len = 0;
if (int.TryParse(attribute.Length, out len))
readExpression = MakeExpression(r => r.ReadUnicodeString(len), reader);
else
readExpression = MakeExpression(r => r.ReadUnicodeStringPrefixLen(), reader);
}
else
{
readExpression = MakeExpression(r => r.ReadUnicodeString(), reader);
}
break;
case "win:AnsiString":
if (!String.IsNullOrEmpty(attribute.Length))
{
int len = 0;
if (int.TryParse(attribute.Length, out len))
readExpression = MakeExpression(r => r.ReadAnsiString(len), reader);
else
readExpression = MakeExpression(r => r.ReadAnsiStringPrefixLen(), reader);
}
else
{
readExpression = MakeExpression(r => r.ReadAnsiString(), reader);
}
break;
case "win:FILETIME":
readExpression = MakeExpression(r => r.ReadFileTime(), reader);
break;
case "win:SYSTEMTIME":
readExpression = MakeExpression(r => r.ReadSystemTime(), reader);
break;
case "win:SID":
readExpression = MakeExpression(r => r.ReadSid(), reader);
break;
case "win:Binary":
// HACK: this is not handling the length
readExpression = MakeExpression(r => r.ReadBytes(), reader);
break;
case "win:GUID":
readExpression = MakeExpression(r => r.ReadGuid(), reader);
break;
default:
throw new NotImplementedException("Unknown primitive type " + attribute.OriginalType);
}
// the following is to handle value maps, that were emitted as enumerations
if (p.PropertyType.IsEnum)
{
readExpression = Expression.Convert(readExpression, p.PropertyType);
}
MemberBinding b = Expression.Bind(p, readExpression);
bindings.Add(b);
}
NewExpression n = Expression.New(outputType);
MemberInitExpression m = Expression.MemberInit(n, bindings.ToArray());
UnaryExpression cast = Expression.Convert(m, typeof (object));
Expression<Func<EtwNativeEvent, object>> exp = Expression.Lambda<Func<EtwNativeEvent, object>>(cast,
ex.Parameters);
return exp.Compile();
}