Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / clr / src / BCL / System / Diagnostics / Eventing / EventProvider.cs / 1305376 / EventProvider.cs
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// [....]
//-----------------------------------------------------------------------------
using System;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using Microsoft.Win32;
using System.Globalization;
using System.Collections.Generic;
using System.Threading;
using System.Security.Permissions;
using System.Security;
using System.Diagnostics.CodeAnalysis;
namespace System.Diagnostics.Eventing
{
// New in CLR4.0
internal enum ControllerCommand
{
// Strictly Positive numbers are for provider-specific commands, negative number are for 'shared' commands. 256
// The first 256 negative numbers are reserved for the framework.
Update = 0,
SendManifest = -1,
};
[System.Security.Permissions.HostProtection(MayLeakOnAbort = true)]
internal partial class EventProvider : IDisposable
{
// This is the windows EVENT_DATA_DESCRIPTOR structure. We expose it because this is what
// subclasses of EventProvider use when creating efficient (but unsafe) version of
// EventWrite. We do make it a nested type because we really don't expect anyone to use
// it except subclasses (and then only rarely).
public struct EventData
{
internal unsafe ulong Ptr;
internal uint Size;
internal uint Reserved;
}
[System.Security.SecuritySafeCritical]
ManifestEtw.EtwEnableCallback m_etwCallback; // Trace Callback function
private long m_regHandle; // Trace Registration Handle
private byte m_level; // Tracing Level
private long m_anyKeywordMask; // Trace Enable Flags
private long m_allKeywordMask; // Match all keyword
private int m_enabled; // Enabled flag from Trace callback
private Guid m_providerId; // Control Guid
private int m_disposed; // when 1, provider has unregister
private bool m_isClassic; // Should we use classic (XP) ETW APIs (more efficient than s_isClassic)
private static bool s_isClassic; // same as m_isClassic for static APIs.
[ThreadStatic]
private static WriteEventErrorCode s_returnCode; // The last return code
private const int s_basicTypeAllocationBufferSize = 16;
private const int s_etwMaxMumberArguments = 32;
private const int s_etwAPIMaxStringCount = 8;
private const int s_maxEventDataDescriptors = 128;
private const int s_traceEventMaximumSize = 65482;
private const int s_traceEventMaximumStringSize = 32724;
[SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")]
public enum WriteEventErrorCode : int
{
//check mapping to runtime codes
NoError = 0,
NoFreeBuffers = 1,
EventTooBig = 2
}
private enum ActivityControl : uint
{
EVENT_ACTIVITY_CTRL_GET_ID = 1,
EVENT_ACTIVITY_CTRL_SET_ID = 2,
EVENT_ACTIVITY_CTRL_CREATE_ID = 3,
EVENT_ACTIVITY_CTRL_GET_SET_ID = 4,
EVENT_ACTIVITY_CTRL_CREATE_SET_ID = 5
}
//
//
//
///
/// Constructs a new EventProvider. This causes the class to be registered with the OS an
/// if a ETW controller turns on the logging then logging will start.
///
/// The GUID that identifies this provider to the system.
[System.Security.SecurityCritical]
[PermissionSet(SecurityAction.Demand, Unrestricted = true)]
[SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "guid")]
protected EventProvider(Guid providerGuid)
{
m_providerId = providerGuid;
s_isClassic = m_isClassic = true;
//
// Register the ProviderId with ETW
//
Register(providerGuid);
}
internal EventProvider()
{
s_isClassic = m_isClassic = true;
}
///
/// This method registers the controlGuid of this class with ETW.
/// We need to be running on Vista or above. If not an
/// PlatformNotSupported exception will be thrown.
/// If for some reason the ETW Register call failed
/// a NotSupported exception will be thrown.
///
//
//
//
//
//
[System.Security.SecurityCritical]
internal unsafe void Register(Guid providerGuid)
{
m_providerId = providerGuid;
uint status;
m_etwCallback = new ManifestEtw.EtwEnableCallback(EtwEnableCallBack);
status = EventRegister(ref m_providerId, m_etwCallback);
if (status != 0)
{
throw new ArgumentException(Win32Native.GetMessage(unchecked((int)status)));
}
}
//
// implement Dispose Pattern to early deregister from ETW insted of waiting for
// the finalizer to call deregistration.
// Once the user is done with the provider it needs to call Close() or Dispose()
// If neither are called the finalizer will unregister the provider anyway
//
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
//
//
//
[System.Security.SecuritySafeCritical]
protected virtual void Dispose(bool disposing)
{
//
// explicit cleanup is done by calling Dispose with true from
// Dispose() or Close(). The disposing arguement is ignored because there
// are no unmanaged resources.
// The finalizer calls Dispose with false.
//
//
// check if the object has been allready disposed
//
if (m_disposed == 1) return;
if (Interlocked.Exchange(ref m_disposed, 1) != 0)
{
// somebody is allready disposing the provider
return;
}
//
// Disables Tracing in the provider, then unregister
//
m_enabled = 0;
Deregister();
}
///
/// This method deregisters the controlGuid of this class with ETW.
///
///
public virtual void Close()
{
Dispose();
}
~EventProvider()
{
Dispose(false);
}
///
/// This method un-registers from ETW.
///
//
//
//
//
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "Microsoft.Win32.ManifestEtw.EventUnregister(System.Int64)"), System.Security.SecurityCritical]
private unsafe void Deregister()
{
//
// Unregister from ETW using the RegHandle saved from
// the register call.
//
if (m_regHandle != 0)
{
EventUnregister();
m_regHandle = 0;
}
}
//
//
//
//
[System.Security.SecurityCritical]
unsafe void EtwEnableCallBack(
[In] ref System.Guid sourceId,
[In] int isEnabled,
[In] byte setLevel,
[In] long anyKeyword,
[In] long allKeyword,
[In] ManifestEtw.EVENT_FILTER_DESCRIPTOR* filterData,
[In] void* callbackContext
)
{
m_enabled = isEnabled;
m_level = setLevel;
m_anyKeywordMask = anyKeyword;
m_allKeywordMask = allKeyword;
ControllerCommand command = Eventing.ControllerCommand.Update;
IDictionary args = null;
byte[] data;
int keyIndex;
if (GetDataFromController(filterData, out command, out data, out keyIndex))
{
args = new Dictionary(4);
while (keyIndex < data.Length)
{
int keyEnd = FindNull(data, keyIndex);
int valueIdx = keyEnd + 1;
int valueEnd = FindNull(data, valueIdx);
if (valueEnd < data.Length)
{
string key = System.Text.Encoding.UTF8.GetString(data, keyIndex, keyEnd - keyIndex);
string value = System.Text.Encoding.UTF8.GetString(data, valueIdx, valueEnd - valueIdx);
args[key] = value;
}
keyIndex = valueEnd + 1;
}
}
OnControllerCommand(command, args);
}
// New in CLR4.0
protected virtual void OnControllerCommand(ControllerCommand command, IDictionary arguments) { }
protected EventLevel Level { get { return (EventLevel)m_level; } set { m_level = (byte)value; } }
protected EventKeywords MatchAnyKeyword { get { return (EventKeywords)m_anyKeywordMask; } set { m_anyKeywordMask = (long)value; } }
protected EventKeywords MatchAllKeyword { get { return (EventKeywords)m_allKeywordMask; } set { m_allKeywordMask = (long)value; } }
static private int FindNull(byte[] buffer, int idx)
{
while (idx < buffer.Length && buffer[idx] != 0)
idx++;
return idx;
}
///
/// Gets any data to be passed from the controller to the provider. It starts with what is passed
/// into the callback, but unfortunately this data is only present for when the provider is active
/// at the the time the controller issues the command. To allow for providers to activate after the
/// controller issued a command, we also check the registry and use that to get the data. The function
/// returns an array of bytes representing the data, the index into that byte array where the data
/// starts, and the command being issued associated with that data.
///
[System.Security.SecurityCritical]
private unsafe bool GetDataFromController(ManifestEtw.EVENT_FILTER_DESCRIPTOR* filterData, out ControllerCommand command, out byte[] data, out int dataStart)
{
data = null;
if (filterData == null)
{
string regKey = @"\Microsoft\Windows\CurrentVersion\Winevt\Publishers\{" + m_providerId + "}";
if (System.Runtime.InteropServices.Marshal.SizeOf(typeof(IntPtr)) == 8)
regKey = @"HKEY_LOCAL_MACHINE\Software" + @"\Wow6432Node" + regKey;
else
regKey = @"HKEY_LOCAL_MACHINE\Software" + regKey;
data = Microsoft.Win32.Registry.GetValue(regKey, "ControllerData", null) as byte[];
if (data != null && data.Length >= 4)
{
//
command = (ControllerCommand)(((data[3] << 8 + data[2]) << 8 + data[1]) << 8 + data[0]);
dataStart = 4;
return true;
}
}
else
{
if (filterData->Ptr != 0 && 0 < filterData->Size && filterData->Size <= 1024)
{
data = new byte[filterData->Size];
Marshal.Copy((IntPtr)filterData->Ptr, data, 0, data.Length);
}
command = (ControllerCommand) filterData->Type;
dataStart = 0;
return true;
}
dataStart = 0;
command = ControllerCommand.Update;
return false;
}
///
/// IsEnabled, method used to test if provider is enabled
///
public bool IsEnabled()
{
return (m_enabled != 0) ? true : false;
}
///
/// IsEnabled, method used to test if event is enabled
///
///
/// Level to test
///
///
/// Keyword to test
///
public bool IsEnabled(byte level, long keywords)
{
//
// If not enabled at all, return false.
//
if (m_enabled == 0)
{
return false;
}
// This also covers the case of Level == 0.
if ((level <= m_level) ||
(m_level == 0))
{
//
// Check if Keyword is enabled
//
if ((keywords == 0) ||
(((keywords & m_anyKeywordMask) != 0) &&
((keywords & m_allKeywordMask) == m_allKeywordMask)))
{
return true;
}
}
return false;
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
public static WriteEventErrorCode GetLastWriteEventError()
{
return s_returnCode;
}
//
// Helper function to set the last error on the thread
//
private static void SetLastError(int error)
{
switch (error)
{
case ManifestEtw.ERROR_ARITHMETIC_OVERFLOW:
case ManifestEtw.ERROR_MORE_DATA:
s_returnCode = WriteEventErrorCode.EventTooBig;
break;
case ManifestEtw.ERROR_NOT_ENOUGH_MEMORY:
s_returnCode = WriteEventErrorCode.NoFreeBuffers;
break;
}
}
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
[System.Security.SecurityCritical]
private static unsafe string EncodeObject(ref object data, EventData* dataDescriptor, byte* dataBuffer)
/*++
Routine Description:
This routine is used by WriteEvent to unbox the object type and
to fill the passed in ETW data descriptor.
Arguments:
data - argument to be decoded
dataDescriptor - pointer to the descriptor to be filled
dataBuffer - storage buffer for storing user data, needed because cant get the address of the object
Return Value:
null if the object is a basic type other than string. String otherwise
--*/
{
dataDescriptor->Reserved = 0;
string sRet = data as string;
if (sRet != null)
{
dataDescriptor->Size = (uint)((sRet.Length + 1) * 2);
return sRet;
}
if (data is IntPtr)
{
dataDescriptor->Size = (uint)sizeof(IntPtr);
IntPtr* intptrPtr = (IntPtr*)dataBuffer;
*intptrPtr = (IntPtr)data;
dataDescriptor->Ptr = (ulong)intptrPtr;
}
else if (data is int)
{
dataDescriptor->Size = (uint)sizeof(int);
int* intptrPtr = (int*)dataBuffer;
*intptrPtr = (int)data;
dataDescriptor->Ptr = (ulong)intptrPtr;
}
else if (data is long)
{
dataDescriptor->Size = (uint)sizeof(long);
long* longptr = (long*)dataBuffer;
*longptr = (long)data;
dataDescriptor->Ptr = (ulong)longptr;
}
else if (data is uint)
{
dataDescriptor->Size = (uint)sizeof(uint);
uint* uintptr = (uint*)dataBuffer;
*uintptr = (uint)data;
dataDescriptor->Ptr = (ulong)uintptr;
}
else if (data is UInt64)
{
dataDescriptor->Size = (uint)sizeof(ulong);
UInt64* ulongptr = (ulong*)dataBuffer;
*ulongptr = (ulong)data;
dataDescriptor->Ptr = (ulong)ulongptr;
}
else if (data is char)
{
dataDescriptor->Size = (uint)sizeof(char);
char* charptr = (char*)dataBuffer;
*charptr = (char)data;
dataDescriptor->Ptr = (ulong)charptr;
}
else if (data is byte)
{
dataDescriptor->Size = (uint)sizeof(byte);
byte* byteptr = (byte*)dataBuffer;
*byteptr = (byte)data;
dataDescriptor->Ptr = (ulong)byteptr;
}
else if (data is short)
{
dataDescriptor->Size = (uint)sizeof(short);
short* shortptr = (short*)dataBuffer;
*shortptr = (short)data;
dataDescriptor->Ptr = (ulong)shortptr;
}
else if (data is sbyte)
{
dataDescriptor->Size = (uint)sizeof(sbyte);
sbyte* sbyteptr = (sbyte*)dataBuffer;
*sbyteptr = (sbyte)data;
dataDescriptor->Ptr = (ulong)sbyteptr;
}
else if (data is ushort)
{
dataDescriptor->Size = (uint)sizeof(ushort);
ushort* ushortptr = (ushort*)dataBuffer;
*ushortptr = (ushort)data;
dataDescriptor->Ptr = (ulong)ushortptr;
}
else if (data is float)
{
dataDescriptor->Size = (uint)sizeof(float);
float* floatptr = (float*)dataBuffer;
*floatptr = (float)data;
dataDescriptor->Ptr = (ulong)floatptr;
}
else if (data is double)
{
dataDescriptor->Size = (uint)sizeof(double);
double* doubleptr = (double*)dataBuffer;
*doubleptr = (double)data;
dataDescriptor->Ptr = (ulong)doubleptr;
}
else if (data is bool)
{
dataDescriptor->Size = (uint)sizeof(bool);
bool* boolptr = (bool*)dataBuffer;
*boolptr = (bool)data;
dataDescriptor->Ptr = (ulong)boolptr;
}
else if (data is Guid)
{
dataDescriptor->Size = (uint)sizeof(Guid);
Guid* guidptr = (Guid*)dataBuffer;
*guidptr = (Guid)data;
dataDescriptor->Ptr = (ulong)guidptr;
}
else if (data is decimal)
{
dataDescriptor->Size = (uint)sizeof(decimal);
decimal* decimalptr = (decimal*)dataBuffer;
*decimalptr = (decimal)data;
dataDescriptor->Ptr = (ulong)decimalptr;
}
else if (data is Boolean)
{
dataDescriptor->Size = (uint)sizeof(Boolean);
Boolean* booleanptr = (Boolean*)dataBuffer;
*booleanptr = (Boolean)data;
dataDescriptor->Ptr = (ulong)booleanptr;
}
else
{
//To our eyes, everything else is a just a string
sRet = data.ToString();
dataDescriptor->Size = (uint)((sRet.Length + 1) * 2);
return sRet;
}
return null;
}
///
/// WriteMessageEvent, method to write a string with level and Keyword
///
///
/// Level to test
///
///
/// Keyword to test
///
//
//
//
//
[System.Security.SecuritySafeCritical]
public bool WriteMessageEvent(string eventMessage, byte eventLevel, long eventKeywords)
{
int status = 0;
if (eventMessage == null)
{
throw new ArgumentNullException("eventMessage");
}
if (IsEnabled(eventLevel, eventKeywords))
{
if (eventMessage.Length > s_traceEventMaximumStringSize)
{
s_returnCode = WriteEventErrorCode.EventTooBig;
return false;
}
unsafe
{
fixed (char* pdata = eventMessage)
{
status = (int)EventWriteString(eventLevel, eventKeywords, pdata);
}
if (status != 0)
{
SetLastError(status);
return false;
}
}
}
return true;
}
///
/// WriteMessageEvent, method to write a string with level=0 and Keyword=0
///
///
/// Message to log
///
public bool WriteMessageEvent(string eventMessage)
{
return WriteMessageEvent(eventMessage, 0, 0);
}
///
/// WriteEvent, method to write a parameters with event schema properties
///
///
/// Event Descriptor for this event.
///
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification = "Performance-critical code")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
[System.Security.SecuritySafeCritical]
public bool WriteEvent(ref EventDescriptorInternal eventDescriptor, params object[] eventPayload)
{
uint status = 0;
if (IsEnabled(eventDescriptor.Level, eventDescriptor.Keywords))
{
int argCount = 0;
unsafe
{
if ((eventPayload == null)
|| (eventPayload.Length == 0)
|| (eventPayload.Length == 1))
{
string dataString = null;
EventData userData;
byte* dataBuffer = stackalloc byte[s_basicTypeAllocationBufferSize]; // Assume a max of 16 chars for non-string argument
userData.Size = 0;
if ((eventPayload != null) && (eventPayload.Length != 0))
{
//
// Figure out the type and fill the data descriptor
//
dataString = EncodeObject(ref eventPayload[0], &userData, dataBuffer);
argCount = 1;
}
if (userData.Size > s_traceEventMaximumSize)
{
//
// Maximum size of the event payload plus header is 64k
//
s_returnCode = WriteEventErrorCode.EventTooBig;
return false;
}
if (dataString != null)
{
fixed (char* pdata = dataString)
{
userData.Ptr = (ulong)pdata;
status = EventWrite(ref eventDescriptor, (uint)argCount, &userData);
}
}
else
{
if (argCount == 0)
{
status = EventWrite(ref eventDescriptor, 0, null);
}
else
{
status = EventWrite(ref eventDescriptor, (uint)argCount, &userData);
}
}
}
else
{
argCount = eventPayload.Length;
if (argCount > s_etwMaxMumberArguments)
{
//
//too many arguments to log
//
throw new ArgumentOutOfRangeException("eventPayload",
SRETW.GetString(SRETW.ArgumentOutOfRange_MaxArgExceeded, s_etwMaxMumberArguments));
}
uint totalEventSize = 0;
int index;
int stringIndex = 0;
int[] stringPosition = new int[s_etwAPIMaxStringCount];
string[] dataString = new string[s_etwAPIMaxStringCount];
EventData* userData = stackalloc EventData[argCount];
EventData* userDataPtr = (EventData*)userData;
byte* dataBuffer = stackalloc byte[s_basicTypeAllocationBufferSize * argCount]; // Assume 16 chars for non-string argument
byte* currentBuffer = dataBuffer;
//
// The loop below goes through all the arguments and fills in the data
// descriptors. For strings save the location in the dataString array.
// Caculates the total size of the event by adding the data descriptor
// size value set in EncodeObjec method.
//
for (index = 0; index < eventPayload.Length; index++)
{
if (eventPayload[index] != null)
{
string isString;
isString = EncodeObject(ref eventPayload[index], userDataPtr, currentBuffer);
currentBuffer += s_basicTypeAllocationBufferSize;
totalEventSize += userDataPtr->Size;
userDataPtr++;
if (isString != null)
{
if (stringIndex < s_etwAPIMaxStringCount)
{
dataString[stringIndex] = isString;
stringPosition[stringIndex] = index;
stringIndex++;
}
else
{
throw new ArgumentOutOfRangeException("eventPayload",
SRETW.GetString(SRETW.ArgumentOutOfRange_MaxStringsExceeded, s_etwAPIMaxStringCount));
}
}
}
}
if (totalEventSize > s_traceEventMaximumSize)
{
s_returnCode = WriteEventErrorCode.EventTooBig;
return false;
}
//
// now fix any string arguments and set the pointer on the data descriptor
//
fixed (char* v0 = dataString[0], v1 = dataString[1], v2 = dataString[2], v3 = dataString[3],
v4 = dataString[4], v5 = dataString[5], v6 = dataString[6], v7 = dataString[7])
{
userDataPtr = (EventData*)userData;
if (dataString[0] != null)
{
userDataPtr[stringPosition[0]].Ptr = (ulong)v0;
}
if (dataString[1] != null)
{
userDataPtr[stringPosition[1]].Ptr = (ulong)v1;
}
if (dataString[2] != null)
{
userDataPtr[stringPosition[2]].Ptr = (ulong)v2;
}
if (dataString[3] != null)
{
userDataPtr[stringPosition[3]].Ptr = (ulong)v3;
}
if (dataString[4] != null)
{
userDataPtr[stringPosition[4]].Ptr = (ulong)v4;
}
if (dataString[5] != null)
{
userDataPtr[stringPosition[5]].Ptr = (ulong)v5;
}
if (dataString[6] != null)
{
userDataPtr[stringPosition[6]].Ptr = (ulong)v6;
}
if (dataString[7] != null)
{
userDataPtr[stringPosition[7]].Ptr = (ulong)v7;
}
status = EventWrite(ref eventDescriptor, (uint)argCount, userData);
}
}
}
}
if (status != 0)
{
SetLastError((int)status);
return false;
}
return true;
}
///
/// WriteEvent, method to write a string with event schema properties
///
///
/// Event Descriptor for this event.
///
///
/// string to log.
///
//
//
//
//
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")]
[System.Security.SecurityCritical]
public bool WriteEvent(ref EventDescriptorInternal eventDescriptor, string data)
{
uint status = 0;
if (data == null)
{
throw new ArgumentNullException("dataString");
}
if (IsEnabled(eventDescriptor.Level, eventDescriptor.Keywords))
{
if (data.Length > s_traceEventMaximumStringSize)
{
s_returnCode = WriteEventErrorCode.EventTooBig;
return false;
}
EventData userData;
userData.Size = (uint)((data.Length + 1) * 2);
userData.Reserved = 0;
unsafe
{
fixed (char* pdata = data)
{
userData.Ptr = (ulong)pdata;
status = EventWrite(ref eventDescriptor, 1, &userData);
}
}
}
if (status != 0)
{
SetLastError((int)status);
return false;
}
return true;
}
///
/// WriteEvent, method to be used by generated code on a derived class
///
///
/// Event Descriptor for this event.
///
///
/// number of event descriptors
///
///
/// pointer do the event data
///
//
//
//
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
[System.Security.SecuritySafeCritical]
internal protected bool WriteEvent(ref EventDescriptorInternal eventDescriptor, int dataCount, IntPtr data)
{
uint status = 0;
unsafe
{
status = EventWrite(ref eventDescriptor, (uint)dataCount, (EventData*)data);
}
if (status != 0)
{
SetLastError((int)status);
return false;
}
return true;
}
///
/// WriteTransferEvent, method to write a parameters with event schema properties
///
///
/// Event Descriptor for this event.
///
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference", MessageId = "0#")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification = "Performance-critical code")]
[System.Security.SecurityCritical]
public bool WriteTransferEvent(ref EventDescriptorInternal eventDescriptor, Guid relatedActivityId, params object[] eventPayload)
{
uint status = 0;
if (IsEnabled(eventDescriptor.Level, eventDescriptor.Keywords))
{
Guid activityId = GetActivityId();
unsafe
{
if ((eventPayload != null) && (eventPayload.Length != 0))
{
int argCount = eventPayload.Length;
if (argCount > s_etwMaxMumberArguments)
{
//
//too many arguments to log
//
throw new ArgumentOutOfRangeException("eventPayload",
SRETW.GetString(SRETW.ArgumentOutOfRange_MaxArgExceeded, s_etwMaxMumberArguments));
}
uint totalEventSize = 0;
int index;
int stringIndex = 0;
int[] stringPosition = new int[s_etwAPIMaxStringCount]; //used to keep the position of strings in the eventPayload parameter
string[] dataString = new string[s_etwAPIMaxStringCount]; // string arrays from the eventPayload parameter
EventData* userData = stackalloc EventData[argCount]; // allocation for the data descriptors
EventData* userDataPtr = (EventData*)userData;
byte* dataBuffer = stackalloc byte[s_basicTypeAllocationBufferSize * argCount]; // 16 byte for unboxing non-string argument
byte* currentBuffer = dataBuffer;
//
// The loop below goes through all the arguments and fills in the data
// descriptors. For strings save the location in the dataString array.
// Caculates the total size of the event by adding the data descriptor
// size value set in EncodeObjec method.
//
for (index = 0; index < eventPayload.Length; index++)
{
if (eventPayload[index] != null)
{
string isString;
isString = EncodeObject(ref eventPayload[index], userDataPtr, currentBuffer);
currentBuffer += s_basicTypeAllocationBufferSize;
totalEventSize += userDataPtr->Size;
userDataPtr++;
if (isString != null)
{
if (stringIndex < s_etwAPIMaxStringCount)
{
dataString[stringIndex] = isString;
stringPosition[stringIndex] = index;
stringIndex++;
}
else
{
throw new ArgumentOutOfRangeException("eventPayload",
SRETW.GetString(SRETW.ArgumentOutOfRange_MaxStringsExceeded, s_etwAPIMaxStringCount));
}
}
}
}
if (totalEventSize > s_traceEventMaximumSize)
{
s_returnCode = WriteEventErrorCode.EventTooBig;
return false;
}
fixed (char* v0 = dataString[0], v1 = dataString[1], v2 = dataString[2], v3 = dataString[3],
v4 = dataString[4], v5 = dataString[5], v6 = dataString[6], v7 = dataString[7])
{
userDataPtr = (EventData*)userData;
if (dataString[0] != null)
{
userDataPtr[stringPosition[0]].Ptr = (ulong)v0;
}
if (dataString[1] != null)
{
userDataPtr[stringPosition[1]].Ptr = (ulong)v1;
}
if (dataString[2] != null)
{
userDataPtr[stringPosition[2]].Ptr = (ulong)v2;
}
if (dataString[3] != null)
{
userDataPtr[stringPosition[3]].Ptr = (ulong)v3;
}
if (dataString[4] != null)
{
userDataPtr[stringPosition[4]].Ptr = (ulong)v4;
}
if (dataString[5] != null)
{
userDataPtr[stringPosition[5]].Ptr = (ulong)v5;
}
if (dataString[6] != null)
{
userDataPtr[stringPosition[6]].Ptr = (ulong)v6;
}
if (dataString[7] != null)
{
userDataPtr[stringPosition[7]].Ptr = (ulong)v7;
}
status = EventWriteTransfer(ref eventDescriptor, ref activityId, ref relatedActivityId, (uint)argCount, userData);
}
}
else
{
status = EventWriteTransfer(ref eventDescriptor, ref activityId, ref relatedActivityId, 0, null);
}
}
}
if (status != 0)
{
SetLastError((int)status);
return false;
}
return true;
}
//
//
//
//
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference", MessageId = "0#")]
[System.Security.SecurityCritical]
protected bool WriteTransferEvent(ref EventDescriptorInternal eventDescriptor, Guid relatedActivityId, int dataCount, IntPtr data)
{
uint status = 0;
Guid activityId = GetActivityId();
unsafe
{
status = EventWriteTransfer(
ref eventDescriptor,
ref activityId,
ref relatedActivityId,
(uint)dataCount,
(EventData*)data);
}
if (status != 0)
{
SetLastError((int)status);
return false;
}
return true;
}
//
//
//
//
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "Microsoft.Win32.ManifestEtw.EventActivityIdControl(System.Int32,System.Guid@)")]
[System.Security.SecurityCritical]
private static Guid GetActivityId()
{
//
Guid id = new Guid();
EventActivityIdControl((int)ActivityControl.EVENT_ACTIVITY_CTRL_GET_ID, ref id);
return id;
}
//
//
//
//
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "Microsoft.Win32.ManifestEtw.EventActivityIdControl(System.Int32,System.Guid@)")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference", MessageId = "0#")]
[System.Security.SecurityCritical]
public static void SetActivityId(ref Guid id)
{
EventActivityIdControl((int)ActivityControl.EVENT_ACTIVITY_CTRL_SET_ID, ref id);
}
//
//
//
//
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "Microsoft.Win32.ManifestEtw.EventActivityIdControl(System.Int32,System.Guid@)")]
[System.Security.SecurityCritical]
public static Guid CreateActivityId()
{
Guid newId = new Guid();
EventActivityIdControl((int)ActivityControl.EVENT_ACTIVITY_CTRL_CREATE_ID, ref newId);
return newId;
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// [....]
//-----------------------------------------------------------------------------
using System;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using Microsoft.Win32;
using System.Globalization;
using System.Collections.Generic;
using System.Threading;
using System.Security.Permissions;
using System.Security;
using System.Diagnostics.CodeAnalysis;
namespace System.Diagnostics.Eventing
{
// New in CLR4.0
internal enum ControllerCommand
{
// Strictly Positive numbers are for provider-specific commands, negative number are for 'shared' commands. 256
// The first 256 negative numbers are reserved for the framework.
Update = 0,
SendManifest = -1,
};
[System.Security.Permissions.HostProtection(MayLeakOnAbort = true)]
internal partial class EventProvider : IDisposable
{
// This is the windows EVENT_DATA_DESCRIPTOR structure. We expose it because this is what
// subclasses of EventProvider use when creating efficient (but unsafe) version of
// EventWrite. We do make it a nested type because we really don't expect anyone to use
// it except subclasses (and then only rarely).
public struct EventData
{
internal unsafe ulong Ptr;
internal uint Size;
internal uint Reserved;
}
[System.Security.SecuritySafeCritical]
ManifestEtw.EtwEnableCallback m_etwCallback; // Trace Callback function
private long m_regHandle; // Trace Registration Handle
private byte m_level; // Tracing Level
private long m_anyKeywordMask; // Trace Enable Flags
private long m_allKeywordMask; // Match all keyword
private int m_enabled; // Enabled flag from Trace callback
private Guid m_providerId; // Control Guid
private int m_disposed; // when 1, provider has unregister
private bool m_isClassic; // Should we use classic (XP) ETW APIs (more efficient than s_isClassic)
private static bool s_isClassic; // same as m_isClassic for static APIs.
[ThreadStatic]
private static WriteEventErrorCode s_returnCode; // The last return code
private const int s_basicTypeAllocationBufferSize = 16;
private const int s_etwMaxMumberArguments = 32;
private const int s_etwAPIMaxStringCount = 8;
private const int s_maxEventDataDescriptors = 128;
private const int s_traceEventMaximumSize = 65482;
private const int s_traceEventMaximumStringSize = 32724;
[SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")]
public enum WriteEventErrorCode : int
{
//check mapping to runtime codes
NoError = 0,
NoFreeBuffers = 1,
EventTooBig = 2
}
private enum ActivityControl : uint
{
EVENT_ACTIVITY_CTRL_GET_ID = 1,
EVENT_ACTIVITY_CTRL_SET_ID = 2,
EVENT_ACTIVITY_CTRL_CREATE_ID = 3,
EVENT_ACTIVITY_CTRL_GET_SET_ID = 4,
EVENT_ACTIVITY_CTRL_CREATE_SET_ID = 5
}
//
//
//
///
/// Constructs a new EventProvider. This causes the class to be registered with the OS an
/// if a ETW controller turns on the logging then logging will start.
///
/// The GUID that identifies this provider to the system.
[System.Security.SecurityCritical]
[PermissionSet(SecurityAction.Demand, Unrestricted = true)]
[SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "guid")]
protected EventProvider(Guid providerGuid)
{
m_providerId = providerGuid;
s_isClassic = m_isClassic = true;
//
// Register the ProviderId with ETW
//
Register(providerGuid);
}
internal EventProvider()
{
s_isClassic = m_isClassic = true;
}
///
/// This method registers the controlGuid of this class with ETW.
/// We need to be running on Vista or above. If not an
/// PlatformNotSupported exception will be thrown.
/// If for some reason the ETW Register call failed
/// a NotSupported exception will be thrown.
///
//
//
//
//
//
[System.Security.SecurityCritical]
internal unsafe void Register(Guid providerGuid)
{
m_providerId = providerGuid;
uint status;
m_etwCallback = new ManifestEtw.EtwEnableCallback(EtwEnableCallBack);
status = EventRegister(ref m_providerId, m_etwCallback);
if (status != 0)
{
throw new ArgumentException(Win32Native.GetMessage(unchecked((int)status)));
}
}
//
// implement Dispose Pattern to early deregister from ETW insted of waiting for
// the finalizer to call deregistration.
// Once the user is done with the provider it needs to call Close() or Dispose()
// If neither are called the finalizer will unregister the provider anyway
//
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
//
//
//
[System.Security.SecuritySafeCritical]
protected virtual void Dispose(bool disposing)
{
//
// explicit cleanup is done by calling Dispose with true from
// Dispose() or Close(). The disposing arguement is ignored because there
// are no unmanaged resources.
// The finalizer calls Dispose with false.
//
//
// check if the object has been allready disposed
//
if (m_disposed == 1) return;
if (Interlocked.Exchange(ref m_disposed, 1) != 0)
{
// somebody is allready disposing the provider
return;
}
//
// Disables Tracing in the provider, then unregister
//
m_enabled = 0;
Deregister();
}
///
/// This method deregisters the controlGuid of this class with ETW.
///
///
public virtual void Close()
{
Dispose();
}
~EventProvider()
{
Dispose(false);
}
///
/// This method un-registers from ETW.
///
//
//
//
//
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "Microsoft.Win32.ManifestEtw.EventUnregister(System.Int64)"), System.Security.SecurityCritical]
private unsafe void Deregister()
{
//
// Unregister from ETW using the RegHandle saved from
// the register call.
//
if (m_regHandle != 0)
{
EventUnregister();
m_regHandle = 0;
}
}
//
//
//
//
[System.Security.SecurityCritical]
unsafe void EtwEnableCallBack(
[In] ref System.Guid sourceId,
[In] int isEnabled,
[In] byte setLevel,
[In] long anyKeyword,
[In] long allKeyword,
[In] ManifestEtw.EVENT_FILTER_DESCRIPTOR* filterData,
[In] void* callbackContext
)
{
m_enabled = isEnabled;
m_level = setLevel;
m_anyKeywordMask = anyKeyword;
m_allKeywordMask = allKeyword;
ControllerCommand command = Eventing.ControllerCommand.Update;
IDictionary args = null;
byte[] data;
int keyIndex;
if (GetDataFromController(filterData, out command, out data, out keyIndex))
{
args = new Dictionary(4);
while (keyIndex < data.Length)
{
int keyEnd = FindNull(data, keyIndex);
int valueIdx = keyEnd + 1;
int valueEnd = FindNull(data, valueIdx);
if (valueEnd < data.Length)
{
string key = System.Text.Encoding.UTF8.GetString(data, keyIndex, keyEnd - keyIndex);
string value = System.Text.Encoding.UTF8.GetString(data, valueIdx, valueEnd - valueIdx);
args[key] = value;
}
keyIndex = valueEnd + 1;
}
}
OnControllerCommand(command, args);
}
// New in CLR4.0
protected virtual void OnControllerCommand(ControllerCommand command, IDictionary arguments) { }
protected EventLevel Level { get { return (EventLevel)m_level; } set { m_level = (byte)value; } }
protected EventKeywords MatchAnyKeyword { get { return (EventKeywords)m_anyKeywordMask; } set { m_anyKeywordMask = (long)value; } }
protected EventKeywords MatchAllKeyword { get { return (EventKeywords)m_allKeywordMask; } set { m_allKeywordMask = (long)value; } }
static private int FindNull(byte[] buffer, int idx)
{
while (idx < buffer.Length && buffer[idx] != 0)
idx++;
return idx;
}
///
/// Gets any data to be passed from the controller to the provider. It starts with what is passed
/// into the callback, but unfortunately this data is only present for when the provider is active
/// at the the time the controller issues the command. To allow for providers to activate after the
/// controller issued a command, we also check the registry and use that to get the data. The function
/// returns an array of bytes representing the data, the index into that byte array where the data
/// starts, and the command being issued associated with that data.
///
[System.Security.SecurityCritical]
private unsafe bool GetDataFromController(ManifestEtw.EVENT_FILTER_DESCRIPTOR* filterData, out ControllerCommand command, out byte[] data, out int dataStart)
{
data = null;
if (filterData == null)
{
string regKey = @"\Microsoft\Windows\CurrentVersion\Winevt\Publishers\{" + m_providerId + "}";
if (System.Runtime.InteropServices.Marshal.SizeOf(typeof(IntPtr)) == 8)
regKey = @"HKEY_LOCAL_MACHINE\Software" + @"\Wow6432Node" + regKey;
else
regKey = @"HKEY_LOCAL_MACHINE\Software" + regKey;
data = Microsoft.Win32.Registry.GetValue(regKey, "ControllerData", null) as byte[];
if (data != null && data.Length >= 4)
{
//
command = (ControllerCommand)(((data[3] << 8 + data[2]) << 8 + data[1]) << 8 + data[0]);
dataStart = 4;
return true;
}
}
else
{
if (filterData->Ptr != 0 && 0 < filterData->Size && filterData->Size <= 1024)
{
data = new byte[filterData->Size];
Marshal.Copy((IntPtr)filterData->Ptr, data, 0, data.Length);
}
command = (ControllerCommand) filterData->Type;
dataStart = 0;
return true;
}
dataStart = 0;
command = ControllerCommand.Update;
return false;
}
///
/// IsEnabled, method used to test if provider is enabled
///
public bool IsEnabled()
{
return (m_enabled != 0) ? true : false;
}
///
/// IsEnabled, method used to test if event is enabled
///
///
/// Level to test
///
///
/// Keyword to test
///
public bool IsEnabled(byte level, long keywords)
{
//
// If not enabled at all, return false.
//
if (m_enabled == 0)
{
return false;
}
// This also covers the case of Level == 0.
if ((level <= m_level) ||
(m_level == 0))
{
//
// Check if Keyword is enabled
//
if ((keywords == 0) ||
(((keywords & m_anyKeywordMask) != 0) &&
((keywords & m_allKeywordMask) == m_allKeywordMask)))
{
return true;
}
}
return false;
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
public static WriteEventErrorCode GetLastWriteEventError()
{
return s_returnCode;
}
//
// Helper function to set the last error on the thread
//
private static void SetLastError(int error)
{
switch (error)
{
case ManifestEtw.ERROR_ARITHMETIC_OVERFLOW:
case ManifestEtw.ERROR_MORE_DATA:
s_returnCode = WriteEventErrorCode.EventTooBig;
break;
case ManifestEtw.ERROR_NOT_ENOUGH_MEMORY:
s_returnCode = WriteEventErrorCode.NoFreeBuffers;
break;
}
}
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
[System.Security.SecurityCritical]
private static unsafe string EncodeObject(ref object data, EventData* dataDescriptor, byte* dataBuffer)
/*++
Routine Description:
This routine is used by WriteEvent to unbox the object type and
to fill the passed in ETW data descriptor.
Arguments:
data - argument to be decoded
dataDescriptor - pointer to the descriptor to be filled
dataBuffer - storage buffer for storing user data, needed because cant get the address of the object
Return Value:
null if the object is a basic type other than string. String otherwise
--*/
{
dataDescriptor->Reserved = 0;
string sRet = data as string;
if (sRet != null)
{
dataDescriptor->Size = (uint)((sRet.Length + 1) * 2);
return sRet;
}
if (data is IntPtr)
{
dataDescriptor->Size = (uint)sizeof(IntPtr);
IntPtr* intptrPtr = (IntPtr*)dataBuffer;
*intptrPtr = (IntPtr)data;
dataDescriptor->Ptr = (ulong)intptrPtr;
}
else if (data is int)
{
dataDescriptor->Size = (uint)sizeof(int);
int* intptrPtr = (int*)dataBuffer;
*intptrPtr = (int)data;
dataDescriptor->Ptr = (ulong)intptrPtr;
}
else if (data is long)
{
dataDescriptor->Size = (uint)sizeof(long);
long* longptr = (long*)dataBuffer;
*longptr = (long)data;
dataDescriptor->Ptr = (ulong)longptr;
}
else if (data is uint)
{
dataDescriptor->Size = (uint)sizeof(uint);
uint* uintptr = (uint*)dataBuffer;
*uintptr = (uint)data;
dataDescriptor->Ptr = (ulong)uintptr;
}
else if (data is UInt64)
{
dataDescriptor->Size = (uint)sizeof(ulong);
UInt64* ulongptr = (ulong*)dataBuffer;
*ulongptr = (ulong)data;
dataDescriptor->Ptr = (ulong)ulongptr;
}
else if (data is char)
{
dataDescriptor->Size = (uint)sizeof(char);
char* charptr = (char*)dataBuffer;
*charptr = (char)data;
dataDescriptor->Ptr = (ulong)charptr;
}
else if (data is byte)
{
dataDescriptor->Size = (uint)sizeof(byte);
byte* byteptr = (byte*)dataBuffer;
*byteptr = (byte)data;
dataDescriptor->Ptr = (ulong)byteptr;
}
else if (data is short)
{
dataDescriptor->Size = (uint)sizeof(short);
short* shortptr = (short*)dataBuffer;
*shortptr = (short)data;
dataDescriptor->Ptr = (ulong)shortptr;
}
else if (data is sbyte)
{
dataDescriptor->Size = (uint)sizeof(sbyte);
sbyte* sbyteptr = (sbyte*)dataBuffer;
*sbyteptr = (sbyte)data;
dataDescriptor->Ptr = (ulong)sbyteptr;
}
else if (data is ushort)
{
dataDescriptor->Size = (uint)sizeof(ushort);
ushort* ushortptr = (ushort*)dataBuffer;
*ushortptr = (ushort)data;
dataDescriptor->Ptr = (ulong)ushortptr;
}
else if (data is float)
{
dataDescriptor->Size = (uint)sizeof(float);
float* floatptr = (float*)dataBuffer;
*floatptr = (float)data;
dataDescriptor->Ptr = (ulong)floatptr;
}
else if (data is double)
{
dataDescriptor->Size = (uint)sizeof(double);
double* doubleptr = (double*)dataBuffer;
*doubleptr = (double)data;
dataDescriptor->Ptr = (ulong)doubleptr;
}
else if (data is bool)
{
dataDescriptor->Size = (uint)sizeof(bool);
bool* boolptr = (bool*)dataBuffer;
*boolptr = (bool)data;
dataDescriptor->Ptr = (ulong)boolptr;
}
else if (data is Guid)
{
dataDescriptor->Size = (uint)sizeof(Guid);
Guid* guidptr = (Guid*)dataBuffer;
*guidptr = (Guid)data;
dataDescriptor->Ptr = (ulong)guidptr;
}
else if (data is decimal)
{
dataDescriptor->Size = (uint)sizeof(decimal);
decimal* decimalptr = (decimal*)dataBuffer;
*decimalptr = (decimal)data;
dataDescriptor->Ptr = (ulong)decimalptr;
}
else if (data is Boolean)
{
dataDescriptor->Size = (uint)sizeof(Boolean);
Boolean* booleanptr = (Boolean*)dataBuffer;
*booleanptr = (Boolean)data;
dataDescriptor->Ptr = (ulong)booleanptr;
}
else
{
//To our eyes, everything else is a just a string
sRet = data.ToString();
dataDescriptor->Size = (uint)((sRet.Length + 1) * 2);
return sRet;
}
return null;
}
///
/// WriteMessageEvent, method to write a string with level and Keyword
///
///
/// Level to test
///
///
/// Keyword to test
///
//
//
//
//
[System.Security.SecuritySafeCritical]
public bool WriteMessageEvent(string eventMessage, byte eventLevel, long eventKeywords)
{
int status = 0;
if (eventMessage == null)
{
throw new ArgumentNullException("eventMessage");
}
if (IsEnabled(eventLevel, eventKeywords))
{
if (eventMessage.Length > s_traceEventMaximumStringSize)
{
s_returnCode = WriteEventErrorCode.EventTooBig;
return false;
}
unsafe
{
fixed (char* pdata = eventMessage)
{
status = (int)EventWriteString(eventLevel, eventKeywords, pdata);
}
if (status != 0)
{
SetLastError(status);
return false;
}
}
}
return true;
}
///
/// WriteMessageEvent, method to write a string with level=0 and Keyword=0
///
///
/// Message to log
///
public bool WriteMessageEvent(string eventMessage)
{
return WriteMessageEvent(eventMessage, 0, 0);
}
///
/// WriteEvent, method to write a parameters with event schema properties
///
///
/// Event Descriptor for this event.
///
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification = "Performance-critical code")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
[System.Security.SecuritySafeCritical]
public bool WriteEvent(ref EventDescriptorInternal eventDescriptor, params object[] eventPayload)
{
uint status = 0;
if (IsEnabled(eventDescriptor.Level, eventDescriptor.Keywords))
{
int argCount = 0;
unsafe
{
if ((eventPayload == null)
|| (eventPayload.Length == 0)
|| (eventPayload.Length == 1))
{
string dataString = null;
EventData userData;
byte* dataBuffer = stackalloc byte[s_basicTypeAllocationBufferSize]; // Assume a max of 16 chars for non-string argument
userData.Size = 0;
if ((eventPayload != null) && (eventPayload.Length != 0))
{
//
// Figure out the type and fill the data descriptor
//
dataString = EncodeObject(ref eventPayload[0], &userData, dataBuffer);
argCount = 1;
}
if (userData.Size > s_traceEventMaximumSize)
{
//
// Maximum size of the event payload plus header is 64k
//
s_returnCode = WriteEventErrorCode.EventTooBig;
return false;
}
if (dataString != null)
{
fixed (char* pdata = dataString)
{
userData.Ptr = (ulong)pdata;
status = EventWrite(ref eventDescriptor, (uint)argCount, &userData);
}
}
else
{
if (argCount == 0)
{
status = EventWrite(ref eventDescriptor, 0, null);
}
else
{
status = EventWrite(ref eventDescriptor, (uint)argCount, &userData);
}
}
}
else
{
argCount = eventPayload.Length;
if (argCount > s_etwMaxMumberArguments)
{
//
//too many arguments to log
//
throw new ArgumentOutOfRangeException("eventPayload",
SRETW.GetString(SRETW.ArgumentOutOfRange_MaxArgExceeded, s_etwMaxMumberArguments));
}
uint totalEventSize = 0;
int index;
int stringIndex = 0;
int[] stringPosition = new int[s_etwAPIMaxStringCount];
string[] dataString = new string[s_etwAPIMaxStringCount];
EventData* userData = stackalloc EventData[argCount];
EventData* userDataPtr = (EventData*)userData;
byte* dataBuffer = stackalloc byte[s_basicTypeAllocationBufferSize * argCount]; // Assume 16 chars for non-string argument
byte* currentBuffer = dataBuffer;
//
// The loop below goes through all the arguments and fills in the data
// descriptors. For strings save the location in the dataString array.
// Caculates the total size of the event by adding the data descriptor
// size value set in EncodeObjec method.
//
for (index = 0; index < eventPayload.Length; index++)
{
if (eventPayload[index] != null)
{
string isString;
isString = EncodeObject(ref eventPayload[index], userDataPtr, currentBuffer);
currentBuffer += s_basicTypeAllocationBufferSize;
totalEventSize += userDataPtr->Size;
userDataPtr++;
if (isString != null)
{
if (stringIndex < s_etwAPIMaxStringCount)
{
dataString[stringIndex] = isString;
stringPosition[stringIndex] = index;
stringIndex++;
}
else
{
throw new ArgumentOutOfRangeException("eventPayload",
SRETW.GetString(SRETW.ArgumentOutOfRange_MaxStringsExceeded, s_etwAPIMaxStringCount));
}
}
}
}
if (totalEventSize > s_traceEventMaximumSize)
{
s_returnCode = WriteEventErrorCode.EventTooBig;
return false;
}
//
// now fix any string arguments and set the pointer on the data descriptor
//
fixed (char* v0 = dataString[0], v1 = dataString[1], v2 = dataString[2], v3 = dataString[3],
v4 = dataString[4], v5 = dataString[5], v6 = dataString[6], v7 = dataString[7])
{
userDataPtr = (EventData*)userData;
if (dataString[0] != null)
{
userDataPtr[stringPosition[0]].Ptr = (ulong)v0;
}
if (dataString[1] != null)
{
userDataPtr[stringPosition[1]].Ptr = (ulong)v1;
}
if (dataString[2] != null)
{
userDataPtr[stringPosition[2]].Ptr = (ulong)v2;
}
if (dataString[3] != null)
{
userDataPtr[stringPosition[3]].Ptr = (ulong)v3;
}
if (dataString[4] != null)
{
userDataPtr[stringPosition[4]].Ptr = (ulong)v4;
}
if (dataString[5] != null)
{
userDataPtr[stringPosition[5]].Ptr = (ulong)v5;
}
if (dataString[6] != null)
{
userDataPtr[stringPosition[6]].Ptr = (ulong)v6;
}
if (dataString[7] != null)
{
userDataPtr[stringPosition[7]].Ptr = (ulong)v7;
}
status = EventWrite(ref eventDescriptor, (uint)argCount, userData);
}
}
}
}
if (status != 0)
{
SetLastError((int)status);
return false;
}
return true;
}
///
/// WriteEvent, method to write a string with event schema properties
///
///
/// Event Descriptor for this event.
///
///
/// string to log.
///
//
//
//
//
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")]
[System.Security.SecurityCritical]
public bool WriteEvent(ref EventDescriptorInternal eventDescriptor, string data)
{
uint status = 0;
if (data == null)
{
throw new ArgumentNullException("dataString");
}
if (IsEnabled(eventDescriptor.Level, eventDescriptor.Keywords))
{
if (data.Length > s_traceEventMaximumStringSize)
{
s_returnCode = WriteEventErrorCode.EventTooBig;
return false;
}
EventData userData;
userData.Size = (uint)((data.Length + 1) * 2);
userData.Reserved = 0;
unsafe
{
fixed (char* pdata = data)
{
userData.Ptr = (ulong)pdata;
status = EventWrite(ref eventDescriptor, 1, &userData);
}
}
}
if (status != 0)
{
SetLastError((int)status);
return false;
}
return true;
}
///
/// WriteEvent, method to be used by generated code on a derived class
///
///
/// Event Descriptor for this event.
///
///
/// number of event descriptors
///
///
/// pointer do the event data
///
//
//
//
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
[System.Security.SecuritySafeCritical]
internal protected bool WriteEvent(ref EventDescriptorInternal eventDescriptor, int dataCount, IntPtr data)
{
uint status = 0;
unsafe
{
status = EventWrite(ref eventDescriptor, (uint)dataCount, (EventData*)data);
}
if (status != 0)
{
SetLastError((int)status);
return false;
}
return true;
}
///
/// WriteTransferEvent, method to write a parameters with event schema properties
///
///
/// Event Descriptor for this event.
///
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference", MessageId = "0#")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification = "Performance-critical code")]
[System.Security.SecurityCritical]
public bool WriteTransferEvent(ref EventDescriptorInternal eventDescriptor, Guid relatedActivityId, params object[] eventPayload)
{
uint status = 0;
if (IsEnabled(eventDescriptor.Level, eventDescriptor.Keywords))
{
Guid activityId = GetActivityId();
unsafe
{
if ((eventPayload != null) && (eventPayload.Length != 0))
{
int argCount = eventPayload.Length;
if (argCount > s_etwMaxMumberArguments)
{
//
//too many arguments to log
//
throw new ArgumentOutOfRangeException("eventPayload",
SRETW.GetString(SRETW.ArgumentOutOfRange_MaxArgExceeded, s_etwMaxMumberArguments));
}
uint totalEventSize = 0;
int index;
int stringIndex = 0;
int[] stringPosition = new int[s_etwAPIMaxStringCount]; //used to keep the position of strings in the eventPayload parameter
string[] dataString = new string[s_etwAPIMaxStringCount]; // string arrays from the eventPayload parameter
EventData* userData = stackalloc EventData[argCount]; // allocation for the data descriptors
EventData* userDataPtr = (EventData*)userData;
byte* dataBuffer = stackalloc byte[s_basicTypeAllocationBufferSize * argCount]; // 16 byte for unboxing non-string argument
byte* currentBuffer = dataBuffer;
//
// The loop below goes through all the arguments and fills in the data
// descriptors. For strings save the location in the dataString array.
// Caculates the total size of the event by adding the data descriptor
// size value set in EncodeObjec method.
//
for (index = 0; index < eventPayload.Length; index++)
{
if (eventPayload[index] != null)
{
string isString;
isString = EncodeObject(ref eventPayload[index], userDataPtr, currentBuffer);
currentBuffer += s_basicTypeAllocationBufferSize;
totalEventSize += userDataPtr->Size;
userDataPtr++;
if (isString != null)
{
if (stringIndex < s_etwAPIMaxStringCount)
{
dataString[stringIndex] = isString;
stringPosition[stringIndex] = index;
stringIndex++;
}
else
{
throw new ArgumentOutOfRangeException("eventPayload",
SRETW.GetString(SRETW.ArgumentOutOfRange_MaxStringsExceeded, s_etwAPIMaxStringCount));
}
}
}
}
if (totalEventSize > s_traceEventMaximumSize)
{
s_returnCode = WriteEventErrorCode.EventTooBig;
return false;
}
fixed (char* v0 = dataString[0], v1 = dataString[1], v2 = dataString[2], v3 = dataString[3],
v4 = dataString[4], v5 = dataString[5], v6 = dataString[6], v7 = dataString[7])
{
userDataPtr = (EventData*)userData;
if (dataString[0] != null)
{
userDataPtr[stringPosition[0]].Ptr = (ulong)v0;
}
if (dataString[1] != null)
{
userDataPtr[stringPosition[1]].Ptr = (ulong)v1;
}
if (dataString[2] != null)
{
userDataPtr[stringPosition[2]].Ptr = (ulong)v2;
}
if (dataString[3] != null)
{
userDataPtr[stringPosition[3]].Ptr = (ulong)v3;
}
if (dataString[4] != null)
{
userDataPtr[stringPosition[4]].Ptr = (ulong)v4;
}
if (dataString[5] != null)
{
userDataPtr[stringPosition[5]].Ptr = (ulong)v5;
}
if (dataString[6] != null)
{
userDataPtr[stringPosition[6]].Ptr = (ulong)v6;
}
if (dataString[7] != null)
{
userDataPtr[stringPosition[7]].Ptr = (ulong)v7;
}
status = EventWriteTransfer(ref eventDescriptor, ref activityId, ref relatedActivityId, (uint)argCount, userData);
}
}
else
{
status = EventWriteTransfer(ref eventDescriptor, ref activityId, ref relatedActivityId, 0, null);
}
}
}
if (status != 0)
{
SetLastError((int)status);
return false;
}
return true;
}
//
//
//
//
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference", MessageId = "0#")]
[System.Security.SecurityCritical]
protected bool WriteTransferEvent(ref EventDescriptorInternal eventDescriptor, Guid relatedActivityId, int dataCount, IntPtr data)
{
uint status = 0;
Guid activityId = GetActivityId();
unsafe
{
status = EventWriteTransfer(
ref eventDescriptor,
ref activityId,
ref relatedActivityId,
(uint)dataCount,
(EventData*)data);
}
if (status != 0)
{
SetLastError((int)status);
return false;
}
return true;
}
//
//
//
//
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "Microsoft.Win32.ManifestEtw.EventActivityIdControl(System.Int32,System.Guid@)")]
[System.Security.SecurityCritical]
private static Guid GetActivityId()
{
//
Guid id = new Guid();
EventActivityIdControl((int)ActivityControl.EVENT_ACTIVITY_CTRL_GET_ID, ref id);
return id;
}
//
//
//
//
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "Microsoft.Win32.ManifestEtw.EventActivityIdControl(System.Int32,System.Guid@)")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference", MessageId = "0#")]
[System.Security.SecurityCritical]
public static void SetActivityId(ref Guid id)
{
EventActivityIdControl((int)ActivityControl.EVENT_ACTIVITY_CTRL_SET_ID, ref id);
}
//
//
//
//
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "Microsoft.Win32.ManifestEtw.EventActivityIdControl(System.Int32,System.Guid@)")]
[System.Security.SecurityCritical]
public static Guid CreateActivityId()
{
Guid newId = new Guid();
EventActivityIdControl((int)ActivityControl.EVENT_ACTIVITY_CTRL_CREATE_ID, ref newId);
return newId;
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- EnvironmentPermission.cs
- SolidBrush.cs
- StreamWriter.cs
- ColorContextHelper.cs
- DllNotFoundException.cs
- SQLSingleStorage.cs
- NativeMethods.cs
- SessionEndingCancelEventArgs.cs
- ComponentChangedEvent.cs
- ImageMap.cs
- DataGridViewRowHeaderCell.cs
- QuaternionAnimation.cs
- WmpBitmapDecoder.cs
- EmptyReadOnlyDictionaryInternal.cs
- TemplateParser.cs
- NotFiniteNumberException.cs
- MetadataItemEmitter.cs
- EventLogger.cs
- RectIndependentAnimationStorage.cs
- SamlAssertionKeyIdentifierClause.cs
- DataService.cs
- GatewayDefinition.cs
- HtmlElementErrorEventArgs.cs
- BuildProviderCollection.cs
- QuaternionValueSerializer.cs
- BitmapEffectDrawingContextState.cs
- FileVersionInfo.cs
- MergePropertyDescriptor.cs
- SocketElement.cs
- IIS7WorkerRequest.cs
- FocusChangedEventArgs.cs
- ConfigUtil.cs
- BindingSource.cs
- CalloutQueueItem.cs
- OneOf.cs
- OperationAbortedException.cs
- XmlEncodedRawTextWriter.cs
- InputLangChangeRequestEvent.cs
- MessagePropertyDescription.cs
- HitTestDrawingContextWalker.cs
- BufferAllocator.cs
- ClassHandlersStore.cs
- basevalidator.cs
- RenamedEventArgs.cs
- ServiceSettingsResponseInfo.cs
- RotateTransform3D.cs
- PasswordRecovery.cs
- DataBindingHandlerAttribute.cs
- Profiler.cs
- TabControl.cs
- CommandConverter.cs
- SafeBitVector32.cs
- KnownIds.cs
- ContactManager.cs
- SqlCachedBuffer.cs
- GenericEnumConverter.cs
- Utils.cs
- RangeValuePattern.cs
- ObjectStateEntry.cs
- SqlProfileProvider.cs
- DaylightTime.cs
- PerformanceCounters.cs
- XmlUnspecifiedAttribute.cs
- WorkflowPersistenceContext.cs
- XmlBindingWorker.cs
- ExpressionWriter.cs
- ClientSettings.cs
- DataObjectPastingEventArgs.cs
- ContextItem.cs
- MdiWindowListItemConverter.cs
- ProcessStartInfo.cs
- RichTextBoxConstants.cs
- SecurityCookieModeValidator.cs
- AVElementHelper.cs
- Enum.cs
- QuadraticBezierSegment.cs
- DeclaredTypeValidatorAttribute.cs
- XsltContext.cs
- MdiWindowListStrip.cs
- CodePageUtils.cs
- SolidColorBrush.cs
- SHA384Managed.cs
- OpenTypeLayout.cs
- SelectedDatesCollection.cs
- UnsafeNativeMethods.cs
- SetStoryboardSpeedRatio.cs
- ThemeConfigurationDialog.cs
- TextPointerBase.cs
- LingerOption.cs
- SpellerError.cs
- EntityCommandExecutionException.cs
- DataGridViewBand.cs
- SafeNativeMethods.cs
- AccessedThroughPropertyAttribute.cs
- TypeLibConverter.cs
- LabelDesigner.cs
- AttachedPropertyDescriptor.cs
- PaperSize.cs
- _KerberosClient.cs
- ResourceContainer.cs