Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1081 lines
37 KiB

//---------------------------------------------------------------------------
// File: TraceEvent
//
// A Managed wrapper for Event Tracing for Windows
//
// Author: Melur Raghuraman
// Extended By: Baskar Sridharan (7 June 2002).
// Date: 10 Oct 2001
//---------------------------------------------------------------------------
using System;
using System.Collections;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Reflection;
namespace Microsoft.Win32.Diagnostics
{
//
// TODO: Cover all possible EventTypes
//
[System.CLSCompliant(false)]
public sealed class EventType
{
// Ensure class cannot be instantiated
private EventType() {}
public const uint Info = 0x00; // Information or Point Event
public const uint StartEvent = 0x01; // Start of an activity
public const uint EndEvent = 0x02; // End of an activity
public const uint DcStart = 0x03; // Event at Start of Data Collection
public const uint DcEnd = 0x04; // Event at End of Data Collection
public const uint Extension = 0x05; // Extension Event
public const uint Reply = 0x06; // Request-Reply Event
public const uint Dequeue = 0x07; // Enqueue-Dequeue Event
public const uint Checkpoint = 0x08;// Checkpoint Event
public const uint Reserved = 0x09; // Reserved Event
public const uint Message = 0xFF; // Debug Message Event Type
// new Event Types beyond Win32 types
public const uint Connect = 0x10; // Connect Event Type
public const uint Disconnect = 0x11;// Disconnect Event Type
// Open-Close, Connect-Disconnect, Request-Response
// Send-Receive, Start-End, Enqueue-Dequeue, Lock-Unlock
// Enter-Leave, Parent-child, Read-Write, Create-Delete
// new-dispose, alloc-free, client-server,
// Checkpoint/Marker,
}
[System.CLSCompliant(false)]
internal struct TypeNumberMap
{
internal const byte NULL_NO=0;
internal const byte OBJECT_NO = 1;
internal const byte STRING_NO = 2;
internal const byte SBYTE_NO = 3;
internal const byte BYTE_NO = 4;
internal const byte INT16_NO = 5;
internal const byte UINT16_NO = 6;
internal const byte INT32_NO = 7;
internal const byte UINT32_NO = 8;
internal const byte INT64_NO = 9;
internal const byte UINT64_NO = 10;
internal const byte CHAR_NO = 11;
internal const byte SINGLE_NO = 12;
internal const byte DOUBLE_NO = 13;
internal const byte BOOLEAN_NO = 14;
internal const byte DECIMAL_NO = 15;
}
//
// TODO: Check with Debug Level constants in NT and System.Diagnostics
//
public enum TraceFlags: int
{
Error=1, Warning=2, Info=4, Info1=8, Info2=16, Info3=32, Info4=64, Info5=128, Info6=256, Info7=512, Info8=1024,
Performance=2048, Performance1=4096, Performance2=8192, Performance3=16384, Performance4=32768, Performance5=65536,
Performance6=131072, Performance7=262144, Performance8=524288
}
[Guid("189456B1-2B4C-473f-A249-3856DD93F9D3")]
[System.CLSCompliant(false)]
public interface ITraceMessageDecoder
{
unsafe int DecodeTraceMessage(byte* message, char* buffer, int bufferSize, ref int dataSize);
}
[System.CLSCompliant(false)]
[Guid("748004CA-4959-409a-887C-6546438CF48E")]
public class TraceProvider : ITraceMessageDecoder
{
static private EtwTrace.EtwProc etwProc; // Trace Callback function
private ulong registrationHandle; // Trace Registration Handle
private ulong traceHandle; // Trace Logger Handle from callback
private uint level; // Tracing Level
private uint flags; // Trace Enable Flags
private bool enabled; // Enabled flag from Trace callback
private const byte noOfBytesPerArg = 3;
private string defaultString = "Foo";
private string defaultFmtStr = "Default Format String";
private Hashtable messageFormatTable = new Hashtable();
string applicationName= "CSharp Software Tracing App";
//Default GUID used by Trace Message Strings.
private Guid MessageGuid = new Guid("{b4955bf0-3af1-4740-b475-99055d3fe9aa}");
public TraceProvider()
{
//Such a default constructor is required for COM Interop
}
public TraceProvider(string applicationName, Guid controlGuid)
{
Level = 0;
flags = 0;
IsEnabled= false;
traceHandle = 0;
registrationHandle = 0;
this.applicationName = applicationName; //Currently, we don't use this variable
//
// Register the controlGuid with ETW
//
Register(controlGuid);
}
public TraceProvider(ulong traceHandle)
{
this.traceHandle = traceHandle;
}
~TraceProvider()
{
//
// Unregister from ETW using the registrationHandle saved from
// the register call.
//
EtwTrace.UnregisterTraceGuids(registrationHandle);
GC.KeepAlive(etwProc);
}
public uint Flags
{
get{
return flags;
}
}
internal uint Level
{
get
{
return level;
}
// set should not be public
set
{
level = value;
}
}
public bool IsEnabled
{
get
{
return enabled;
}
set
{
enabled = value;
}
}
//
// This callback function is called by ETW to enable or disable Tracing dynamically
//
public unsafe uint MyCallback(uint requestCode, System.IntPtr context, System.IntPtr bufferSize, byte* byteBuffer)
{
try
{
BaseEvent* buffer = (BaseEvent *)byteBuffer;
switch(requestCode)
{
case EtwTrace.RequestCodes.EnableEvents:
traceHandle = buffer->HistoricalContext;
//traceHandle = EtwTrace.GetTraceLoggerHandle((BaseEvent *)buffer);
flags = (uint)EtwTrace.GetTraceEnableFlags((ulong)buffer->HistoricalContext);
Level = (uint)EtwTrace.GetTraceEnableLevel((ulong)buffer->HistoricalContext);
IsEnabled = true;
break;
case EtwTrace.RequestCodes.DisableEvents:
IsEnabled = false;
traceHandle = 0;
Level = 0 ;
flags = 0 ;
break;
default:
IsEnabled = false;
traceHandle = 0;
break;
}
return 0;
}
catch(Exception e)
{
Console.WriteLine("Exception caught - '{0}'", e.Message);
return 0;//TODO: Shouldn't we be returning a different value here ?
}
}
//
// Registers a Dynamically Generated GUID automatically with an inbuilt callback
//
private unsafe uint Register(Guid controlGuid)
{
uint status;
TraceGuidRegistration guidReg = new TraceGuidRegistration();
Guid dummyGuid = new Guid("{b4955bf0-3af1-4740-b475-99055d3fe9aa}");
etwProc = new EtwTrace.EtwProc(MyCallback);
guidReg.Guid = &dummyGuid;
guidReg.RegHandle = null;
status = EtwTrace.RegisterTraceGuids(etwProc, null, ref controlGuid, 1, ref guidReg, null, null, out registrationHandle);
if (status != 0)
{
Console.WriteLine("Register() call Failed with Status {0}", status);
}
return status;
}
public unsafe uint TraceEvent(Guid eventGuid, uint evtype)
{
BaseEvent ev; // Takes up 192 bytes on the stack
ev.ClientContext = 0;
ev.Guid = eventGuid;
ev.ProviderId = evtype;
ev.BufferSize = 48; // sizeof(EVENT_TRACE_HEADER)
return EtwTrace.TraceEvent(traceHandle, (char*)&ev);
}
//
// This is the 1 object overload
//
public unsafe uint TraceEvent(Guid eventGuid, uint evtype, object data0)
{
return TraceEvent(eventGuid, evtype, data0, null, null, null, null, null, null, null, null);
}
//
// This is the 2 argument overload
//
public unsafe uint TraceEvent(Guid eventGuid, uint evtype, object data0, object data1)
{
return TraceEvent(eventGuid, evtype, data0, data1, null, null, null, null, null, null, null);
}
//
// This is the 3 argument overload
//
public unsafe uint TraceEvent(Guid eventGuid, uint evtype, object data0, object data1, object data2)
{
return TraceEvent(eventGuid, evtype, data0, data1, data2, null, null, null, null, null, null);
}
//
// This is the 4 argument overload
//
public unsafe uint TraceEvent(Guid eventGuid, uint evtype, object data0, object data1, object data2, object data3)
{
return TraceEvent(eventGuid, evtype, data0, data1, data2, data3, null, null, null, null, null);
}
//
// This is the 5 argument overload
//
public unsafe uint TraceEvent(Guid eventGuid, uint evtype, object data0, object data1, object data2, object data3, object data4)
{
return TraceEvent(eventGuid, evtype, data0, data1, data2, data3, data4, null, null, null, null);
}
//
// This is the 6 argument overload
//
public unsafe uint TraceEvent(Guid eventGuid, uint evtype, object data0, object data1, object data2, object data3, object data4, object data5)
{
return TraceEvent(eventGuid, evtype, data0, data1, data2, data3, data4, data5, null, null, null);
}
//
// This is the 7 argument overload
//
public unsafe uint TraceEvent(Guid eventGuid, uint evtype, object data0, object data1, object data2, object data3, object data4, object data5, object data6)
{
return TraceEvent(eventGuid, evtype, data0, data1, data2, data3, data4, data5, data6, null, null);
}
//
// This is the 8 argument overload
//
public unsafe uint TraceEvent(Guid eventGuid, uint evtype, object data0, object data1, object data2, object data3, object data4, object data5, object data6, object data7)
{
return TraceEvent(eventGuid, evtype, data0, data1, data2, data3, data4, data5, data6, data7, null);
}
public unsafe uint TraceEvent(Guid eventGuid, uint evtype, object data0, object data1, object data2, object data3, object data4, object data5, object data6, object data7, object data8)
{
uint status = 0;
BaseEvent ev; // Takes up 192 bytes on the stack
char* buffer = stackalloc char[128];
uint offset = 0;
char* ptr = buffer;
string s0 , s1 , s2 , s3 , s4 , s5 , s6 , s7 , s8;
int stringMask = 0;
uint argCount=0;
s0 = s1 = s2 = s3 = s4 = s5 = s6 = s7 = s8 = defaultString;
ev.Flags = 0x00120000; // define Constants
ev.Guid = eventGuid;
ev.ProviderId = evtype;
MofField *be = null;
if (data0 != null)
{
argCount++;
be = &(&ev.UserData)[0];
if ((s0 = ProcessOneObject(data0, be, ptr, ref offset)) != null)
{
stringMask |= 0x00000001;
}
}
if (data1 != null)
{
argCount++;
be = &(&ev.UserData)[1];
ptr = buffer + offset;
if ((s1 = ProcessOneObject(data1, be, ptr, ref offset)) != null)
{
stringMask |= 0x00000002;
}
}
if (data2 != null)
{
argCount++;
be = &(&ev.UserData)[2];
ptr = buffer + offset;
if ((s2 = ProcessOneObject(data2, be, ptr, ref offset)) != null)
{
stringMask |= 0x00000004;
}
}
if (data3 != null)
{
argCount++;
be = &(&ev.UserData)[3];
ptr = buffer + offset;
if ((s3 = ProcessOneObject(data3, be, ptr, ref offset)) != null)
{
stringMask |= 0x00000008;
}
}
if (data4 != null)
{
argCount++;
be = &(&ev.UserData)[4];
ptr = buffer + offset;
if ((s4 = ProcessOneObject(data4, be, ptr, ref offset)) != null)
{
stringMask |= 0x00000010;
}
}
if (data5 != null)
{
argCount++;
be = &(&ev.UserData)[5];
ptr = buffer + offset;
if ((s5 = ProcessOneObject(data5, be, ptr, ref offset)) != null)
{
stringMask |= 0x00000020;
}
}
if (data6 != null)
{
argCount++;
be = &(&ev.UserData)[6];
ptr = buffer + offset;
if ((s6 = ProcessOneObject(data6, be, ptr, ref offset)) != null)
{
stringMask |= 0x00000040;
}
}
if (data7 != null)
{
argCount++;
be = &(&ev.UserData)[7];
ptr = buffer + offset;
if ((s7 = ProcessOneObject(data7, be, ptr, ref offset)) != null)
{
stringMask |= 0x00000080;
}
}
if (data8 != null)
{
argCount++;
be = &(&ev.UserData)[8];
ptr = buffer + offset;
if ((s8 = ProcessOneObject(data8, be, ptr, ref offset)) != null)
{
stringMask |= 0x00000100;
}
}
//
// Now pin all the strings and use the stringMask to pass them over through
// mofField.
//
fixed (char* vptr0 = s0, vptr1 = s1, vptr2 = s2, vptr3 = s3, vptr4 = s4, vptr5 = s5, vptr6 = s6, vptr7 = s7, vptr8 = s8 )
{
if ((stringMask & 0x00000001) != 0)
{
(&ev.UserData)[0].DataLength = (uint) s0.Length * 2;
(&ev.UserData)[0].DataPointer = (void*)vptr0;
}
if ((stringMask & 0x00000002)!= 0)
{
(&ev.UserData)[1].DataLength = (uint) s1.Length * 2;
(&ev.UserData)[1].DataPointer = (void*)vptr1;
}
if ((stringMask & 0x00000004)!= 0)
{
(&ev.UserData)[2].DataLength = (uint) s2.Length * 2;
(&ev.UserData)[2].DataPointer = (void*)vptr2;
}
if ((stringMask & 0x00000008)!= 0)
{
(&ev.UserData)[3].DataLength = (uint) s3.Length * 2;
(&ev.UserData)[3].DataPointer = (void*)vptr3;
}
if ((stringMask & 0x00000010)!= 0)
{
(&ev.UserData)[4].DataLength = (uint) s4.Length * 2;
(&ev.UserData)[4].DataPointer = (void*)vptr4;
}
if ((stringMask & 0x00000020)!= 0)
{
(&ev.UserData)[5].DataLength = (uint) s5.Length * 2;
(&ev.UserData)[5].DataPointer = (void*)vptr5;
}
if ((stringMask & 0x00000040)!= 0)
{
(&ev.UserData)[6].DataLength = (uint) s6.Length * 2;
(&ev.UserData)[6].DataPointer = (void*)vptr6;
}
if ((stringMask & 0x00000080)!= 0)
{
(&ev.UserData)[7].DataLength = (uint) s7.Length * 2;
(&ev.UserData)[7].DataPointer = (void*)vptr7;
}
if ((stringMask & 0x00000100)!= 0)
{
(&ev.UserData)[8].DataLength = (uint) s8.Length * 2;
(&ev.UserData)[8].DataPointer = (void*)vptr8;
}
ev.BufferSize = 48 + argCount * 16;
status = EtwTrace.TraceEvent(traceHandle, (char*)&ev);
}
return status;
}
private unsafe string ProcessOneObject(object data, MofField * mofField, char* ptr, ref uint offSet)
{
return EncodeObject(data, mofField, ptr, ref offSet, (byte *)null);
}
//TODO[1]: Need to accomodate Win64 alignment issues. Code that might cause problems
// have been tagged with "WIN64 Changes".
private unsafe string EncodeObject(object data, MofField * mofField, char* ptr, ref uint offSet, byte* ptrArgInfo)
{
if (data == null)
{
*ptrArgInfo = (byte)0; //NULL type, WIN64 Changes
*(ushort *)(ptrArgInfo+1) = (ushort)0;
mofField->DataLength = 0;
mofField->DataPointer=(void *)null; //WIN64 Changes (?)
return null;
}
string sRet = data as string;
if (sRet != null)
{
*ptrArgInfo = (byte)2; //WIN64 Changes
*(ushort *)(ptrArgInfo+1) = (ushort)(sRet.Length<65535?sRet.Length:65535); //WIN64 Changes
return sRet;
}
if (data is sbyte)
{
mofField->DataLength = sizeof(sbyte);
*ptrArgInfo = (byte)3; //WIN64 Changes
sbyte* sbyteptr = (sbyte*)ptr;
*sbyteptr = (sbyte) data; //WIN64 Changes
mofField->DataPointer = (void *) sbyteptr;
offSet += sizeof(sbyte);
}
else if (data is byte)
{
mofField->DataLength = sizeof(byte);
*ptrArgInfo = (byte)4; //WIN64 Changes
byte* byteptr = (byte*)ptr;
*byteptr = (byte) data; //WIN64 Changes
mofField->DataPointer = (void *) byteptr;
offSet += sizeof(byte);
}
else if (data is short)
{
mofField->DataLength = sizeof(short);
*ptrArgInfo = (byte)5; //WIN64 Changes
short* shortptr = (short*)ptr;
*shortptr = (short) data; //WIN64 Changes
mofField->DataPointer = (void *) shortptr;
offSet += sizeof(short);
}
else if (data is ushort)
{
mofField->DataLength = sizeof(ushort);
*ptrArgInfo = (byte)6; //WIN64 Changes
ushort* ushortptr = (ushort*)ptr;
*ushortptr = (ushort) data; //WIN64 Changes
mofField->DataPointer = (void *) ushortptr;
offSet += sizeof(ushort);
}
else if (data is int)
{
mofField->DataLength = sizeof(int);
*ptrArgInfo = (byte)7; //WIN64 Changes
int* intptr = (int*)ptr;
*intptr = (int) data; //WIN64 Changes
mofField->DataPointer = (void *) intptr;
offSet += sizeof(int);
}
else if (data is uint )
{
mofField->DataLength = sizeof(uint);
*ptrArgInfo = (byte)8; //WIN64 Changes
uint* uintptr = (uint*)ptr;
*uintptr = (uint) data; //WIN64 Changes
mofField->DataPointer = (void *) uintptr;
offSet += sizeof(uint);
}
else if (data is long )
{
mofField->DataLength = sizeof(long);
*ptrArgInfo = (byte)9; //WIN64 Changes
long* longptr = (long*)ptr;
*longptr = (long) data; //WIN64 Changes
mofField->DataPointer = (void *) longptr;
offSet += sizeof(long);
}
else if (data is ulong )
{
mofField->DataLength = sizeof(ulong);
*ptrArgInfo = (byte)10; //WIN64 Changes
ulong* ulongptr = (ulong*)ptr;
*ulongptr = (ulong) data; //WIN64 Changes
mofField->DataPointer = (void *) ulongptr;
offSet += sizeof(ulong);
}
else if (data is char)
{
mofField->DataLength = sizeof(char);
*ptrArgInfo = (byte)11; //WIN64 Changes
char* charptr = (char*)ptr;
*charptr = (char) data; //WIN64 Changes
mofField->DataPointer = (void *) charptr;
offSet += sizeof(char);
}
else if (data is float)
{
mofField->DataLength = sizeof(float);
*ptrArgInfo = (byte)12; //WIN64 Changes
float* floatptr = (float*)ptr;
*floatptr = (float) data; //WIN64 Changes
mofField->DataPointer = (void *) floatptr;
offSet += sizeof(float);
}
else if (data is double)
{
mofField->DataLength = sizeof(double);
*ptrArgInfo = (byte)13; //WIN64 Changes
double* doubleptr = (double*)ptr;
*doubleptr = (double) data; //WIN64 Changes
mofField->DataPointer = (void *) doubleptr;
offSet += sizeof(double);
}
else if (data is bool)
{
mofField->DataLength = sizeof(bool);
*ptrArgInfo = (byte)14; //WIN64 Changes
bool* boolptr = (bool*)ptr;
*boolptr = (bool) data; //WIN64 Changes
mofField->DataPointer = (void *) boolptr;
offSet += sizeof(bool);
}
else if (data is decimal)
{
mofField->DataLength = (uint)sizeof(decimal);
*ptrArgInfo = (byte)15; //WIN64 Changes
decimal* decimalptr = (decimal*)ptr;
*decimalptr = (decimal) data; //WIN64 Changes
mofField->DataPointer = (void *) decimalptr;
offSet += (uint)sizeof(decimal);
}
else
{
//To our eyes, everything else is a just a string
sRet = data.ToString();
*ptrArgInfo = (byte)2; //WIN64 Changes
*(ushort *)(ptrArgInfo+1) = (ushort)(sRet.Length<65535?sRet.Length:65535); //WIN64 Changes
return sRet;
}
*(ushort *)(ptrArgInfo+1) = (ushort)(mofField->DataLength); //WIN64 Changes (?)
return sRet;
}
private unsafe uint EncodeTraceMessage(Guid eventGuid, uint evtype, byte nargs, object formatstring, object data2, object data3, object data4, object data5, object data6, object data7, object data8, object data9)
{
uint status = 0;
BaseEvent ev; // Takes up 208 bytes on the stack
char* buffer = stackalloc char[144+(1+9*noOfBytesPerArg)/sizeof(char)];//28 characters would be 56 bytes!!!. We are allocating more space than we require.
//Header structure:
//1 byte for number of args
//3 byte for format string type information,
//3 bytes each for the type information for a maximum of 8 arguments
byte *header = (byte *)(buffer+144);
uint offset = 0;
char* ptr = buffer;
string s1 , s2 , s3 , s4 , s5 , s6 , s7 , s8, s9;
int stringMask = 0;
uint argCount=0;
byte *ptrHeader = header;
s1 = s2 = s3 = s4 = s5 = s6 = s7 = s8 = s9 = defaultString;
ev.Flags = 0x00120000; // define Constants
ev.Guid = eventGuid;
//IMP: evtype MUST be the same as the one specified in the typeve field for CSharp in default.tmf
ev.ProviderId = evtype;
MofField *be = null;
if (header != null)
{
be = &(&ev.UserData)[0];
header[0] = (byte)nargs; //WIN64 Changes (?)
be->DataPointer = (void *)header;
be->DataLength = (uint)(1+nargs*noOfBytesPerArg);
}
if (formatstring == null)
formatstring = defaultFmtStr;
if (formatstring != null)
{
//data1 would, in most cases, be the format string
argCount++;
be = &(&ev.UserData)[1];
ptr = buffer + offset;
if ((s1 = EncodeObject(formatstring, be, ptr, ref offset, ++header)) != null)
{
stringMask |= 0x00000002;
}
}
if (argCount <= nargs)
{
argCount++;
be = &(&ev.UserData)[2];
ptr = buffer + offset;
if ((s2 = EncodeObject(data2, be, ptr, ref offset, header+1*noOfBytesPerArg)) != null)
{
stringMask |= 0x00000004;
}
}
if (argCount <= nargs)
{
argCount++;
be = &(&ev.UserData)[3];
ptr = buffer + offset;
if ((s3 = EncodeObject(data3, be, ptr, ref offset, header+2*noOfBytesPerArg)) != null)
{
stringMask |= 0x00000008;
}
}
if (argCount <= nargs)
{
argCount++;
be = &(&ev.UserData)[4];
ptr = buffer + offset;
if ((s4 = EncodeObject(data4, be, ptr, ref offset, header+3*noOfBytesPerArg)) != null)
{
stringMask |= 0x00000010;
}
}
if (argCount <= nargs)
{
argCount++;
be = &(&ev.UserData)[5];
ptr = buffer + offset;
if ((s5 = EncodeObject(data5, be, ptr, ref offset, header+4*noOfBytesPerArg)) != null)
{
stringMask |= 0x00000020;
}
}
if (argCount <= nargs)
{
argCount++;
be = &(&ev.UserData)[6];
ptr = buffer + offset;
if ((s6 = EncodeObject(data6, be, ptr, ref offset,header+5*noOfBytesPerArg)) != null)
{
stringMask |= 0x00000040;
}
}
if (argCount <= nargs)
{
argCount++;
be = &(&ev.UserData)[7];
ptr = buffer + offset;
if ((s7 = EncodeObject(data7, be, ptr, ref offset,header+6*noOfBytesPerArg)) != null)
{
stringMask |= 0x00000080;
}
}
if (argCount <= nargs)
{
argCount++;
be = &(&ev.UserData)[8];
ptr = buffer + offset;
if ((s8 = EncodeObject(data8, be, ptr, ref offset,header+7*noOfBytesPerArg)) != null)
{
stringMask |= 0x00000100;
}
}
if (argCount <= nargs)
{
argCount++;
be = &(&ev.UserData)[9];
ptr = buffer + offset;
if ((s9 = EncodeObject(data9, be, ptr, ref offset, header+8*noOfBytesPerArg)) != null)
{
stringMask |= 0x00000200;
}
}
//
// Now pin all the strings and use the stringMask to pass them over through
// mofField.
//
fixed (char* vptr1 = s1, vptr2 = s2, vptr3 = s3, vptr4 = s4, vptr5 = s5, vptr6 = s6, vptr7 = s7, vptr8 = s8, vptr9 = s9 )
{
if ((stringMask & 0x00000002)!= 0)
{
(&ev.UserData)[1].DataLength = (uint) (s1.Length<65535/2?s1.Length*2:65535);//s1.Length*2;
(&ev.UserData)[1].DataPointer = (void*)(vptr1);
}
if ((stringMask & 0x00000004)!= 0)
{
(&ev.UserData)[2].DataLength = (uint) (s2.Length<65535/2?s2.Length*2:65535);//s2.Length * 2;
(&ev.UserData)[2].DataPointer = (void*)(vptr2);
}
if ((stringMask & 0x00000008)!= 0)
{
(&ev.UserData)[3].DataLength = (uint) (s3.Length<65535/2?s3.Length*2:65535);//s3.Length * 2;
(&ev.UserData)[3].DataPointer = (void*)(vptr3);
}
if ((stringMask & 0x00000010)!= 0)
{
(&ev.UserData)[4].DataLength = (uint) (s4.Length<65535/2?s4.Length*2:65535);//s4.Length * 2;
(&ev.UserData)[4].DataPointer = (void*)(vptr4);
}
if ((stringMask & 0x00000020)!= 0)
{
(&ev.UserData)[5].DataLength = (uint) (s5.Length<65535/2?s5.Length*2:65535);//s5.Length * 2;
(&ev.UserData)[5].DataPointer = (void*)(vptr5);
}
if ((stringMask & 0x00000040)!= 0)
{
(&ev.UserData)[6].DataLength = (uint) (s6.Length<65535/2?s6.Length*2:65535);//s6.Length * 2;
(&ev.UserData)[6].DataPointer = (void*)(vptr6);
}
if ((stringMask & 0x00000080)!= 0)
{
(&ev.UserData)[7].DataLength = (uint) (s7.Length<65535/2?s7.Length*2:65535);//s7.Length * 2;
(&ev.UserData)[7].DataPointer = (void*)(vptr7);
}
if ((stringMask & 0x00000100)!= 0)
{
(&ev.UserData)[8].DataLength = (uint) (s8.Length<65535/2?s8.Length*2:65535);//s8.Length * 2;
(&ev.UserData)[8].DataPointer = (void*)(vptr8);
}
if ((stringMask & 0x00000200)!= 0)
{
(&ev.UserData)[9].DataLength = (uint) (s9.Length<65535/2?s9.Length*2:65535);//s9.Length * 2;
(&ev.UserData)[9].DataPointer = (void*)(vptr9);
}
ev.BufferSize = 48 + (argCount+1) * 16;//the extra mof field is for the header
status = EtwTrace.TraceEvent(traceHandle, (char*)&ev);
}
return status;
}
public unsafe int DecodeTraceMessage(byte* message, char* buffer, int bufferSize /* in chars */, ref int dataSize /*Note: This is # of *chars* and not bytes*/)
{
if (buffer == null || message == null || bufferSize <= 0)
return 0; //TODO[1]: Do we need a more detailed error code ?
try
{
int i=0;
byte nargs = *message;
ushort lenFmtStr = *(ushort *)(message+2);
char* pcFmtStr = (char *)(message+1+nargs*noOfBytesPerArg);//start of the format string
byte* argData = message+1+nargs*noOfBytesPerArg+lenFmtStr*2; //start of the argument data
object[] argObject = new object[nargs];
byte argType;
ushort argLen;
String formatString = new String(pcFmtStr,0,lenFmtStr);
//Excluding the format string
for(i = 0; i < nargs-1; i++)
{
argType = *(message+1+(i+1)*noOfBytesPerArg);
argLen = *(ushort *)(message+1+(i+1)*noOfBytesPerArg+1); //WIN64 Changes (?)
switch(argType)
{
case TypeNumberMap.NULL_NO:
argObject[i] = null;
break;
case TypeNumberMap.STRING_NO:
{
String s;
if (argLen == 0)
s = "";
else s = new String((char *)argData,0,argLen);
argObject[i] = s;
argLen *= 2; //adjust the length
break;
}
case TypeNumberMap.SBYTE_NO:
{
sbyte sb = *(sbyte *)argData; //WIN64 Changes
argObject[i] = sb;
break;
}
case TypeNumberMap.BYTE_NO:
{
byte b = *argData; //WIN64 Changes
argObject[i] = b;
break;
}
case TypeNumberMap.INT16_NO:
{
short s = *(short *)argData; //WIN64 Changes
argObject[i] = s;
break;
}
case TypeNumberMap.UINT16_NO:
{
ushort us = *(ushort *)argData; //WIN64 Changes
argObject[i] = us;
break;
}
case TypeNumberMap.INT32_NO:
{
int id = *(int *)argData; //WIN64 Changes
argObject[i] = id;
break;
}
case TypeNumberMap.UINT32_NO:
{
uint uid = *(uint *)argData; //WIN64 Changes
argObject[i] = uid;
break;
}
case TypeNumberMap.INT64_NO:
{
long l = *(long *)argData; //WIN64 Changes
argObject[i] = l;
break;
}
case TypeNumberMap.UINT64_NO:
{
ulong ul = *(ulong *)argData; //WIN64 Changes
argObject[i] = ul;
break;
}
case TypeNumberMap.CHAR_NO:
{
char c = *(char *)argData; //WIN64 Changes
argObject[i] = c;
break;
}
case TypeNumberMap.SINGLE_NO:
{
float f = *(float *)argData; //WIN64 Changes
argObject[i] = f;
break;
}
case TypeNumberMap.DOUBLE_NO:
{
double d = *(double *)argData; //WIN64 Changes
argObject[i] = d;
break;
}
case TypeNumberMap.BOOLEAN_NO:
{
bool b = *(bool *)argData; //WIN64 Changes
argObject[i] = b;
break;
}
case TypeNumberMap.DECIMAL_NO:
{
decimal d = *(decimal *)argData; //WIN64 Changes
argObject[i] = d;
break;
}
}
argData += argLen;
}
string fStr = String.Format(formatString,argObject);
if (fStr.Length==0)//empty string
fStr="Format string was empty!";
int arrLen = fStr.Length*2;
dataSize = arrLen+1;
fixed(char* carray = fStr.ToCharArray())
{
if (arrLen+1 <= bufferSize)
{
for(i = 0; i < arrLen; i++)
buffer[i] = carray[i]; //WIN64 Changes (?)
//add null terminator
buffer[i+1] = (char)0x00; //WIN64 Changes (?)
return 1;
}
else
{
//TODO[1]: Do we need to copy as many characters as we can ?
//Not sure if it is useful to do so because the caller may have to come back
//with the right buffer size to get all the data. So why copy part of the data twice ?
return 0;
}
}
}
catch(Exception e)
{
Console.WriteLine("Exception caught: {0}", e.Message);
return -1;
}
}
// ========================================================================
// The following are the Message String Wrappers for Software Tracing Messages
// using Flags.
// There are entried for Format string and zero through 8 arguments.
// These are kept small so they will be inlined
// ========================================================================
// Just the format string
public unsafe void TraceMessage(uint traceFlags, object format )
{
if ((traceFlags&Flags) != 0)
{
EncodeTraceMessage(MessageGuid, (int)14,1, format, null, null, null, null, null, null, null, null);
}
}
// Just one argument
public unsafe void TraceMessage(uint traceFlags, object format, object data1 )
{
if ((traceFlags&Flags) != 0)
{
EncodeTraceMessage(MessageGuid, (int)14, 2, format, data1, null, null, null, null, null, null,null);
}
}
// Just two arguments
public unsafe void TraceMessage(uint traceFlags, object format, object data1, object data2 )
{
if ((traceFlags&Flags) != 0)
{
EncodeTraceMessage(MessageGuid, (int)14, 3, format, data1, data2, null, null, null, null, null, null);
}
}
// Just three arguments
public unsafe void TraceMessage(uint traceFlags, object format, object data1, object data2, object data3 )
{
if ((traceFlags&Flags) != 0)
{
EncodeTraceMessage(MessageGuid, (int)14, 4, format, data1, data2, data3, null, null, null, null, null);
}
}
// Just four arguments
public unsafe void TraceMessage(uint traceFlags, object format, object data1, object data2, object data3, object data4 )
{
if ((traceFlags&Flags) != 0)
{
EncodeTraceMessage(MessageGuid, (int)14, 5, format, data1, data2, data3, data4, null, null, null, null);
}
}
// Just five arguments
public unsafe void TraceMessage(uint traceFlags, object format, object data1, object data2, object data3, object data4, object data5 )
{
if ((traceFlags&Flags) != 0)
{
EncodeTraceMessage(MessageGuid, (int)14, 6, format, data1, data2, data3, data4, data5, null, null, null);
}
}
// Just six arguments
public unsafe void TraceMessage(uint traceFlags, object format, object data1, object data2, object data3, object data4, object data5, object data6 )
{
if ((traceFlags&Flags) != 0)
{
EncodeTraceMessage(MessageGuid, (int)14, 7, format, data1, data2, data3, data4, data5, data6, null, null);
}
}
// Just seven arguments
public unsafe void TraceMessage(uint traceFlags, object format, object data1, object data2, object data3, object data4, object data5, object data6, object data7 )
{
if ((traceFlags&Flags) != 0)
{
EncodeTraceMessage(MessageGuid, (int)14, 8, format, data1, data2, data3, data4, data5, data6, data7, null);
}
}
// Just eight arguments
public unsafe void TraceMessage(uint traceFlags, object format, object data1, object data2, object data3, object data4, object data5, object data6, object data7, object data8 )
{
if ((traceFlags&Flags) != 0)
{
EncodeTraceMessage(MessageGuid, (int)14, 9, format, data1, data2, data3, data4, data5, data6, data7, data8);
}
}
}
}