|
|
//---------------------------------------------------------------------------
// 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); } } } }
|