Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Core / 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.ComponentModel; using System.Collections.Generic; using System.Threading; using System.Security.Permissions; using System.Security; using System.Diagnostics.CodeAnalysis; namespace System.Diagnostics.Eventing{ [System.Security.Permissions.HostProtection(MayLeakOnAbort = true)] public class EventProvider : IDisposable { UnsafeNativeMethods.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 static LocalDataStoreSlot s_returnCodeSlot; // thread slot to keep last error private static bool s_platformNotSupported = (Environment.OSVersion.Version.Major < 6); private static bool s_preWin7 = (Environment.OSVersion.Version.Major < 6 || (Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor < 1)); 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 } [StructLayout(LayoutKind.Explicit, Size = 16)] private struct EventData { [FieldOffset(0)] internal ulong DataPointer; [FieldOffset(8)] internal uint Size; [FieldOffset(12)] internal int Reserved; } 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 } ////// Constructor for EventProvider class. /// /// /// Unique GUID among all trace sources running on a system /// //// [System.Security.SecurityCritical] [PermissionSet(SecurityAction.Demand, Unrestricted = true)] [SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "guid")] public EventProvider(Guid providerGuid) { m_providerId = providerGuid; s_returnCodeSlot = Thread.AllocateDataSlot(); Thread.SetData(s_returnCodeSlot, (int)WriteEventErrorCode.NoError); // // EtwRegister the ProviderId with ETW // EtwRegister(); } ///// /// 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 EtwRegister call failed /// a NotSupported exception will be thrown. /// //// [System.Security.SecurityCritical] private unsafe void EtwRegister() { uint status; // // Check only the mayor version // if (s_platformNotSupported) { throw new PlatformNotSupportedException(SR.GetString(SR.NotSupported_DownLevelVista)); } m_etwCallback = new UnsafeNativeMethods.EtwEnableCallback(EtwEnableCallBack); status = UnsafeNativeMethods.EventRegister(ref m_providerId, m_etwCallback, null, ref m_regHandle); if (status != 0) { throw new Win32Exception((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.Security.SecurityCritical] private unsafe void Deregister() { // // Unregister from ETW using the RegHandle saved from // the register call. // if (m_regHandle != 0) { UnsafeNativeMethods.EventUnregister(m_regHandle); 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] void* filterData, [In] void* callbackContext ) { m_enabled = isEnabled; m_level = setLevel; m_anyKeywordMask = anyKeyword; m_allKeywordMask = allKeyword; return; } ///// // /// 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; } public static WriteEventErrorCode GetLastWriteEventError() { object lastError = Thread.GetData(s_returnCodeSlot); if (lastError == null) { return WriteEventErrorCode.NoError; } else { return (WriteEventErrorCode)(int)lastError; } } // // Helper function to set the last error on the thread // private static void SetLastError(int error){ switch (error) { case UnsafeNativeMethods.ERROR_ARITHMETIC_OVERFLOW: case UnsafeNativeMethods.ERROR_MORE_DATA: Thread.SetData(s_returnCodeSlot, (int)WriteEventErrorCode.EventTooBig); break; case UnsafeNativeMethods.ERROR_NOT_ENOUGH_MEMORY: Thread.SetData(s_returnCodeSlot, (int)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 == null) { dataDescriptor->Size = 0; dataDescriptor->DataPointer = 0; } else if (data is IntPtr) { dataDescriptor->Size = (uint)sizeof(IntPtr); IntPtr* intptrPtr = (IntPtr*)dataBuffer; *intptrPtr = (IntPtr)data; dataDescriptor->DataPointer = (ulong)intptrPtr; } else if (data is int) { dataDescriptor->Size = (uint)sizeof(int); int* intptrPtr = (int*)dataBuffer; *intptrPtr = (int)data; dataDescriptor->DataPointer = (ulong)intptrPtr; } else if (data is long) { dataDescriptor->Size = (uint)sizeof(long); long* longptr = (long*)dataBuffer; *longptr = (long)data; dataDescriptor->DataPointer = (ulong)longptr; } else if (data is uint) { dataDescriptor->Size = (uint)sizeof(uint); uint* uintptr = (uint*)dataBuffer; *uintptr = (uint)data; dataDescriptor->DataPointer = (ulong)uintptr; } else if (data is UInt64) { dataDescriptor->Size = (uint)sizeof(ulong); UInt64* ulongptr = (ulong*)dataBuffer; *ulongptr = (ulong)data; dataDescriptor->DataPointer = (ulong)ulongptr; } else if (data is char) { dataDescriptor->Size = (uint)sizeof(char); char* charptr = (char*)dataBuffer; *charptr = (char)data; dataDescriptor->DataPointer = (ulong)charptr; } else if (data is byte) { dataDescriptor->Size = (uint)sizeof(byte); byte* byteptr = (byte*)dataBuffer; *byteptr = (byte)data; dataDescriptor->DataPointer = (ulong)byteptr; } else if (data is short) { dataDescriptor->Size = (uint)sizeof(short); short* shortptr = (short*)dataBuffer; *shortptr = (short)data; dataDescriptor->DataPointer = (ulong)shortptr; } else if (data is sbyte) { dataDescriptor->Size = (uint)sizeof(sbyte); sbyte* sbyteptr = (sbyte*)dataBuffer; *sbyteptr = (sbyte)data; dataDescriptor->DataPointer = (ulong)sbyteptr; } else if (data is ushort) { dataDescriptor->Size = (uint)sizeof(ushort); ushort* ushortptr = (ushort*)dataBuffer; *ushortptr = (ushort)data; dataDescriptor->DataPointer = (ulong)ushortptr; } else if (data is float) { dataDescriptor->Size = (uint)sizeof(float); float* floatptr = (float*)dataBuffer; *floatptr = (float)data; dataDescriptor->DataPointer = (ulong)floatptr; } else if (data is double) { dataDescriptor->Size = (uint)sizeof(double); double* doubleptr = (double*)dataBuffer; *doubleptr = (double)data; dataDescriptor->DataPointer = (ulong)doubleptr; } else if (data is bool) { dataDescriptor->Size = (uint)sizeof(bool); bool* boolptr = (bool*)dataBuffer; *boolptr = (bool)data; dataDescriptor->DataPointer = (ulong)boolptr; } else if (data is Guid) { dataDescriptor->Size = (uint)sizeof(Guid); Guid* guidptr = (Guid*)dataBuffer; *guidptr = (Guid)data; dataDescriptor->DataPointer = (ulong)guidptr; } else if (data is decimal) { dataDescriptor->Size = (uint)sizeof(decimal); decimal* decimalptr = (decimal*)dataBuffer; *decimalptr = (decimal)data; dataDescriptor->DataPointer = (ulong)decimalptr; } else if (data is Boolean) { dataDescriptor->Size = (uint)sizeof(Boolean); Boolean* booleanptr = (Boolean*)dataBuffer; *booleanptr = (Boolean)data; dataDescriptor->DataPointer = (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. /// The activity ID will be propagated only if the call stays on the same native thread as SetActivityId(). /// /// /// Level to test /// /// /// Keyword to test /// //// [System.Security.SecurityCritical] 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) { Thread.SetData(s_returnCodeSlot, (int)WriteEventErrorCode.EventTooBig); return false; } unsafe { fixed (char* pdata = eventMessage) { status = (int)UnsafeNativeMethods.EventWriteString(m_regHandle, eventLevel, eventKeywords, pdata); } if (status != 0) { SetLastError(status); return false; } } } return true; } ///// // /// WriteMessageEvent, method to write a string with level=0 and Keyword=0 /// The activity ID will be propagated only if the call stays on the same native thread as SetActivityId(). /// /// /// Message to log /// public bool WriteMessageEvent(string eventMessage) { return WriteMessageEvent(eventMessage, 0, 0); } ////// WriteEvent method to write parameters with event schema properties /// /// /// Event Descriptor for this event. /// public bool WriteEvent(ref EventDescriptor eventDescriptor, params object[] eventPayload) { return WriteTransferEvent(ref eventDescriptor, Guid.Empty, eventPayload); } ////// WriteEvent, method to write a string with event schema properties /// /// /// Event Descriptor for this event. /// /// /// string to log. /// //// [System.Security.SecurityCritical] [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] public bool WriteEvent(ref EventDescriptor eventDescriptor, string data) { uint status = 0; if (data == null) { throw new ArgumentNullException("dataString"); } if (IsEnabled(eventDescriptor.Level, eventDescriptor.Keywords)) { if (data.Length > s_traceEventMaximumStringSize) { Thread.SetData(s_returnCodeSlot, (int)WriteEventErrorCode.EventTooBig); return false; } EventData userData; userData.Size = (uint)((data.Length +1)* 2); userData.Reserved = 0; unsafe { fixed (char* pdata = data) { Guid activityId = GetActivityId(); userData.DataPointer = (ulong)pdata; if (s_preWin7) { status = UnsafeNativeMethods.EventWrite(m_regHandle, ref eventDescriptor, 1, &userData); } else { status = UnsafeNativeMethods.EventWriteTransfer(m_regHandle, ref eventDescriptor, (activityId == Guid.Empty) ? null : &activityId, null, 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.Security.SecurityCritical] protected bool WriteEvent(ref EventDescriptor eventDescriptor, int dataCount, IntPtr data) { uint status = 0; unsafe { if (s_preWin7) { status = UnsafeNativeMethods.EventWrite( m_regHandle, ref eventDescriptor, (uint)dataCount, (void*)data); } else { Guid activityId = GetActivityId(); status = UnsafeNativeMethods.EventWriteTransfer( m_regHandle, ref eventDescriptor, (activityId == Guid.Empty) ? null : &activityId, null, (uint)dataCount, (void*)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.Security.SecurityCritical] public bool WriteTransferEvent(ref EventDescriptor eventDescriptor, Guid relatedActivityId, params object[] eventPayload) { uint status = 0; if (IsEnabled(eventDescriptor.Level, eventDescriptor.Keywords)) { Guid activityId = GetActivityId(); unsafe { int argCount = 0; EventData* userDataPtr = null; if ((eventPayload != null) && (eventPayload.Length != 0)) { argCount = eventPayload.Length; if (argCount > s_etwMaxMumberArguments) { // //too many arguments to log // throw new ArgumentOutOfRangeException("eventPayload", SR.GetString(SR.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 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++) { 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", SR.GetString(SR.ArgumentOutOfRange_MaxStringsExceeded, s_etwAPIMaxStringCount)); } } } if (totalEventSize > s_traceEventMaximumSize) { Thread.SetData(s_returnCodeSlot, (int)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]].DataPointer = (ulong)v0; } if (dataString[1] != null) { userDataPtr[stringPosition[1]].DataPointer = (ulong)v1; } if (dataString[2] != null) { userDataPtr[stringPosition[2]].DataPointer = (ulong)v2; } if (dataString[3] != null) { userDataPtr[stringPosition[3]].DataPointer = (ulong)v3; } if (dataString[4] != null) { userDataPtr[stringPosition[4]].DataPointer = (ulong)v4; } if (dataString[5] != null) { userDataPtr[stringPosition[5]].DataPointer = (ulong)v5; } if (dataString[6] != null) { userDataPtr[stringPosition[6]].DataPointer = (ulong)v6; } if (dataString[7] != null) { userDataPtr[stringPosition[7]].DataPointer = (ulong)v7; } } } if (relatedActivityId == Guid.Empty && s_preWin7) { // If relatedActivityId is Guid.Empty, this is not a real transfer: just call EventWrite(). // For pre-Win7 platforms we cannot set the activityId from CorrelationManager // because we cannot set relatedActivityId to null (Win7 bug 116784) status = UnsafeNativeMethods.EventWrite (m_regHandle, ref eventDescriptor, (uint)argCount, userDataPtr); } else { status = UnsafeNativeMethods.EventWriteTransfer (m_regHandle, ref eventDescriptor, (activityId == Guid.Empty) ? null : &activityId, (relatedActivityId == Guid.Empty && !s_preWin7)? null : &relatedActivityId, (uint)argCount, userDataPtr); } } } if (status != 0) { SetLastError((int)status); return false; } return true; } //// // // // // // // // // // // // // // // // [System.Security.SecurityCritical] protected bool WriteTransferEvent(ref EventDescriptor eventDescriptor, Guid relatedActivityId, int dataCount, IntPtr data) { uint status = 0; Guid activityId = GetActivityId(); unsafe { status = UnsafeNativeMethods.EventWriteTransfer( m_regHandle, ref eventDescriptor, (activityId == Guid.Empty) ? null : &activityId, &relatedActivityId, (uint)dataCount, (void*)data); } if (status != 0) { SetLastError((int)status); return false; } return true; } //// // // [System.Security.SecurityCritical] private static Guid GetActivityId() { return Trace.CorrelationManager.ActivityId; } //// // [System.Security.SecurityCritical] public static void SetActivityId(ref Guid id) { Trace.CorrelationManager.ActivityId = id; UnsafeNativeMethods.EventActivityIdControl((int)ActivityControl.EVENT_ACTIVITY_CTRL_SET_ID, ref id); } //// // [System.Security.SecurityCritical] public static Guid CreateActivityId() { Guid newId = new Guid(); UnsafeNativeMethods.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.ComponentModel; using System.Collections.Generic; using System.Threading; using System.Security.Permissions; using System.Security; using System.Diagnostics.CodeAnalysis; namespace System.Diagnostics.Eventing{ [System.Security.Permissions.HostProtection(MayLeakOnAbort = true)] public class EventProvider : IDisposable { UnsafeNativeMethods.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 static LocalDataStoreSlot s_returnCodeSlot; // thread slot to keep last error private static bool s_platformNotSupported = (Environment.OSVersion.Version.Major < 6); private static bool s_preWin7 = (Environment.OSVersion.Version.Major < 6 || (Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor < 1)); 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 } [StructLayout(LayoutKind.Explicit, Size = 16)] private struct EventData { [FieldOffset(0)] internal ulong DataPointer; [FieldOffset(8)] internal uint Size; [FieldOffset(12)] internal int Reserved; } 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 } ////// Constructor for EventProvider class. /// /// /// Unique GUID among all trace sources running on a system /// //// [System.Security.SecurityCritical] [PermissionSet(SecurityAction.Demand, Unrestricted = true)] [SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "guid")] public EventProvider(Guid providerGuid) { m_providerId = providerGuid; s_returnCodeSlot = Thread.AllocateDataSlot(); Thread.SetData(s_returnCodeSlot, (int)WriteEventErrorCode.NoError); // // EtwRegister the ProviderId with ETW // EtwRegister(); } ///// /// 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 EtwRegister call failed /// a NotSupported exception will be thrown. /// //// [System.Security.SecurityCritical] private unsafe void EtwRegister() { uint status; // // Check only the mayor version // if (s_platformNotSupported) { throw new PlatformNotSupportedException(SR.GetString(SR.NotSupported_DownLevelVista)); } m_etwCallback = new UnsafeNativeMethods.EtwEnableCallback(EtwEnableCallBack); status = UnsafeNativeMethods.EventRegister(ref m_providerId, m_etwCallback, null, ref m_regHandle); if (status != 0) { throw new Win32Exception((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.Security.SecurityCritical] private unsafe void Deregister() { // // Unregister from ETW using the RegHandle saved from // the register call. // if (m_regHandle != 0) { UnsafeNativeMethods.EventUnregister(m_regHandle); 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] void* filterData, [In] void* callbackContext ) { m_enabled = isEnabled; m_level = setLevel; m_anyKeywordMask = anyKeyword; m_allKeywordMask = allKeyword; return; } ///// // /// 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; } public static WriteEventErrorCode GetLastWriteEventError() { object lastError = Thread.GetData(s_returnCodeSlot); if (lastError == null) { return WriteEventErrorCode.NoError; } else { return (WriteEventErrorCode)(int)lastError; } } // // Helper function to set the last error on the thread // private static void SetLastError(int error){ switch (error) { case UnsafeNativeMethods.ERROR_ARITHMETIC_OVERFLOW: case UnsafeNativeMethods.ERROR_MORE_DATA: Thread.SetData(s_returnCodeSlot, (int)WriteEventErrorCode.EventTooBig); break; case UnsafeNativeMethods.ERROR_NOT_ENOUGH_MEMORY: Thread.SetData(s_returnCodeSlot, (int)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 == null) { dataDescriptor->Size = 0; dataDescriptor->DataPointer = 0; } else if (data is IntPtr) { dataDescriptor->Size = (uint)sizeof(IntPtr); IntPtr* intptrPtr = (IntPtr*)dataBuffer; *intptrPtr = (IntPtr)data; dataDescriptor->DataPointer = (ulong)intptrPtr; } else if (data is int) { dataDescriptor->Size = (uint)sizeof(int); int* intptrPtr = (int*)dataBuffer; *intptrPtr = (int)data; dataDescriptor->DataPointer = (ulong)intptrPtr; } else if (data is long) { dataDescriptor->Size = (uint)sizeof(long); long* longptr = (long*)dataBuffer; *longptr = (long)data; dataDescriptor->DataPointer = (ulong)longptr; } else if (data is uint) { dataDescriptor->Size = (uint)sizeof(uint); uint* uintptr = (uint*)dataBuffer; *uintptr = (uint)data; dataDescriptor->DataPointer = (ulong)uintptr; } else if (data is UInt64) { dataDescriptor->Size = (uint)sizeof(ulong); UInt64* ulongptr = (ulong*)dataBuffer; *ulongptr = (ulong)data; dataDescriptor->DataPointer = (ulong)ulongptr; } else if (data is char) { dataDescriptor->Size = (uint)sizeof(char); char* charptr = (char*)dataBuffer; *charptr = (char)data; dataDescriptor->DataPointer = (ulong)charptr; } else if (data is byte) { dataDescriptor->Size = (uint)sizeof(byte); byte* byteptr = (byte*)dataBuffer; *byteptr = (byte)data; dataDescriptor->DataPointer = (ulong)byteptr; } else if (data is short) { dataDescriptor->Size = (uint)sizeof(short); short* shortptr = (short*)dataBuffer; *shortptr = (short)data; dataDescriptor->DataPointer = (ulong)shortptr; } else if (data is sbyte) { dataDescriptor->Size = (uint)sizeof(sbyte); sbyte* sbyteptr = (sbyte*)dataBuffer; *sbyteptr = (sbyte)data; dataDescriptor->DataPointer = (ulong)sbyteptr; } else if (data is ushort) { dataDescriptor->Size = (uint)sizeof(ushort); ushort* ushortptr = (ushort*)dataBuffer; *ushortptr = (ushort)data; dataDescriptor->DataPointer = (ulong)ushortptr; } else if (data is float) { dataDescriptor->Size = (uint)sizeof(float); float* floatptr = (float*)dataBuffer; *floatptr = (float)data; dataDescriptor->DataPointer = (ulong)floatptr; } else if (data is double) { dataDescriptor->Size = (uint)sizeof(double); double* doubleptr = (double*)dataBuffer; *doubleptr = (double)data; dataDescriptor->DataPointer = (ulong)doubleptr; } else if (data is bool) { dataDescriptor->Size = (uint)sizeof(bool); bool* boolptr = (bool*)dataBuffer; *boolptr = (bool)data; dataDescriptor->DataPointer = (ulong)boolptr; } else if (data is Guid) { dataDescriptor->Size = (uint)sizeof(Guid); Guid* guidptr = (Guid*)dataBuffer; *guidptr = (Guid)data; dataDescriptor->DataPointer = (ulong)guidptr; } else if (data is decimal) { dataDescriptor->Size = (uint)sizeof(decimal); decimal* decimalptr = (decimal*)dataBuffer; *decimalptr = (decimal)data; dataDescriptor->DataPointer = (ulong)decimalptr; } else if (data is Boolean) { dataDescriptor->Size = (uint)sizeof(Boolean); Boolean* booleanptr = (Boolean*)dataBuffer; *booleanptr = (Boolean)data; dataDescriptor->DataPointer = (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. /// The activity ID will be propagated only if the call stays on the same native thread as SetActivityId(). /// /// /// Level to test /// /// /// Keyword to test /// //// [System.Security.SecurityCritical] 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) { Thread.SetData(s_returnCodeSlot, (int)WriteEventErrorCode.EventTooBig); return false; } unsafe { fixed (char* pdata = eventMessage) { status = (int)UnsafeNativeMethods.EventWriteString(m_regHandle, eventLevel, eventKeywords, pdata); } if (status != 0) { SetLastError(status); return false; } } } return true; } ///// // /// WriteMessageEvent, method to write a string with level=0 and Keyword=0 /// The activity ID will be propagated only if the call stays on the same native thread as SetActivityId(). /// /// /// Message to log /// public bool WriteMessageEvent(string eventMessage) { return WriteMessageEvent(eventMessage, 0, 0); } ////// WriteEvent method to write parameters with event schema properties /// /// /// Event Descriptor for this event. /// public bool WriteEvent(ref EventDescriptor eventDescriptor, params object[] eventPayload) { return WriteTransferEvent(ref eventDescriptor, Guid.Empty, eventPayload); } ////// WriteEvent, method to write a string with event schema properties /// /// /// Event Descriptor for this event. /// /// /// string to log. /// //// [System.Security.SecurityCritical] [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] public bool WriteEvent(ref EventDescriptor eventDescriptor, string data) { uint status = 0; if (data == null) { throw new ArgumentNullException("dataString"); } if (IsEnabled(eventDescriptor.Level, eventDescriptor.Keywords)) { if (data.Length > s_traceEventMaximumStringSize) { Thread.SetData(s_returnCodeSlot, (int)WriteEventErrorCode.EventTooBig); return false; } EventData userData; userData.Size = (uint)((data.Length +1)* 2); userData.Reserved = 0; unsafe { fixed (char* pdata = data) { Guid activityId = GetActivityId(); userData.DataPointer = (ulong)pdata; if (s_preWin7) { status = UnsafeNativeMethods.EventWrite(m_regHandle, ref eventDescriptor, 1, &userData); } else { status = UnsafeNativeMethods.EventWriteTransfer(m_regHandle, ref eventDescriptor, (activityId == Guid.Empty) ? null : &activityId, null, 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.Security.SecurityCritical] protected bool WriteEvent(ref EventDescriptor eventDescriptor, int dataCount, IntPtr data) { uint status = 0; unsafe { if (s_preWin7) { status = UnsafeNativeMethods.EventWrite( m_regHandle, ref eventDescriptor, (uint)dataCount, (void*)data); } else { Guid activityId = GetActivityId(); status = UnsafeNativeMethods.EventWriteTransfer( m_regHandle, ref eventDescriptor, (activityId == Guid.Empty) ? null : &activityId, null, (uint)dataCount, (void*)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.Security.SecurityCritical] public bool WriteTransferEvent(ref EventDescriptor eventDescriptor, Guid relatedActivityId, params object[] eventPayload) { uint status = 0; if (IsEnabled(eventDescriptor.Level, eventDescriptor.Keywords)) { Guid activityId = GetActivityId(); unsafe { int argCount = 0; EventData* userDataPtr = null; if ((eventPayload != null) && (eventPayload.Length != 0)) { argCount = eventPayload.Length; if (argCount > s_etwMaxMumberArguments) { // //too many arguments to log // throw new ArgumentOutOfRangeException("eventPayload", SR.GetString(SR.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 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++) { 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", SR.GetString(SR.ArgumentOutOfRange_MaxStringsExceeded, s_etwAPIMaxStringCount)); } } } if (totalEventSize > s_traceEventMaximumSize) { Thread.SetData(s_returnCodeSlot, (int)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]].DataPointer = (ulong)v0; } if (dataString[1] != null) { userDataPtr[stringPosition[1]].DataPointer = (ulong)v1; } if (dataString[2] != null) { userDataPtr[stringPosition[2]].DataPointer = (ulong)v2; } if (dataString[3] != null) { userDataPtr[stringPosition[3]].DataPointer = (ulong)v3; } if (dataString[4] != null) { userDataPtr[stringPosition[4]].DataPointer = (ulong)v4; } if (dataString[5] != null) { userDataPtr[stringPosition[5]].DataPointer = (ulong)v5; } if (dataString[6] != null) { userDataPtr[stringPosition[6]].DataPointer = (ulong)v6; } if (dataString[7] != null) { userDataPtr[stringPosition[7]].DataPointer = (ulong)v7; } } } if (relatedActivityId == Guid.Empty && s_preWin7) { // If relatedActivityId is Guid.Empty, this is not a real transfer: just call EventWrite(). // For pre-Win7 platforms we cannot set the activityId from CorrelationManager // because we cannot set relatedActivityId to null (Win7 bug 116784) status = UnsafeNativeMethods.EventWrite (m_regHandle, ref eventDescriptor, (uint)argCount, userDataPtr); } else { status = UnsafeNativeMethods.EventWriteTransfer (m_regHandle, ref eventDescriptor, (activityId == Guid.Empty) ? null : &activityId, (relatedActivityId == Guid.Empty && !s_preWin7)? null : &relatedActivityId, (uint)argCount, userDataPtr); } } } if (status != 0) { SetLastError((int)status); return false; } return true; } //// // // // // // // // // // // // // // // // [System.Security.SecurityCritical] protected bool WriteTransferEvent(ref EventDescriptor eventDescriptor, Guid relatedActivityId, int dataCount, IntPtr data) { uint status = 0; Guid activityId = GetActivityId(); unsafe { status = UnsafeNativeMethods.EventWriteTransfer( m_regHandle, ref eventDescriptor, (activityId == Guid.Empty) ? null : &activityId, &relatedActivityId, (uint)dataCount, (void*)data); } if (status != 0) { SetLastError((int)status); return false; } return true; } //// // // [System.Security.SecurityCritical] private static Guid GetActivityId() { return Trace.CorrelationManager.ActivityId; } //// // [System.Security.SecurityCritical] public static void SetActivityId(ref Guid id) { Trace.CorrelationManager.ActivityId = id; UnsafeNativeMethods.EventActivityIdControl((int)ActivityControl.EVENT_ACTIVITY_CTRL_SET_ID, ref id); } //// // [System.Security.SecurityCritical] public static Guid CreateActivityId() { Guid newId = new Guid(); UnsafeNativeMethods.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
- CapiHashAlgorithm.cs
- OleDbStruct.cs
- MemberDescriptor.cs
- CustomErrorsSectionWrapper.cs
- SvcMapFile.cs
- WebBrowserUriTypeConverter.cs
- UIServiceHelper.cs
- XmlComplianceUtil.cs
- CssClassPropertyAttribute.cs
- XmlSchemaValidationException.cs
- CollectionViewProxy.cs
- DataGridItemEventArgs.cs
- ExtendedPropertyInfo.cs
- ApplicationCommands.cs
- PrintDialog.cs
- ECDiffieHellmanCngPublicKey.cs
- PointConverter.cs
- Propagator.Evaluator.cs
- WebBrowserHelper.cs
- DPTypeDescriptorContext.cs
- EmptyStringExpandableObjectConverter.cs
- CultureData.cs
- TextAction.cs
- XLinq.cs
- SqlOuterApplyReducer.cs
- XmlNodeReader.cs
- OleDbDataReader.cs
- MachineKeySection.cs
- SqlErrorCollection.cs
- HwndKeyboardInputProvider.cs
- PointAnimation.cs
- RequestTimeoutManager.cs
- ForeignKeyConstraint.cs
- RadialGradientBrush.cs
- InstanceHandleReference.cs
- ProfileInfo.cs
- MultiBinding.cs
- BasicAsyncResult.cs
- DispatcherObject.cs
- DependencyPropertyHelper.cs
- DataGridViewComboBoxColumnDesigner.cs
- XmlEventCache.cs
- PeerPresenceInfo.cs
- GlyphRun.cs
- TreeNodeConverter.cs
- PropertyTab.cs
- TransformationRules.cs
- HttpCapabilitiesBase.cs
- DecodeHelper.cs
- MenuItem.cs
- PasswordTextNavigator.cs
- MetadataSection.cs
- InstanceNormalEvent.cs
- ButtonChrome.cs
- AssemblyAssociatedContentFileAttribute.cs
- AssemblyName.cs
- CodeTypeConstructor.cs
- Formatter.cs
- ValidationEventArgs.cs
- SqlBooleanizer.cs
- Debug.cs
- DataGridViewRowsAddedEventArgs.cs
- PlacementWorkspace.cs
- RSAOAEPKeyExchangeDeformatter.cs
- XamlStyleSerializer.cs
- DataSourceControlBuilder.cs
- DeferredReference.cs
- EncoderExceptionFallback.cs
- QueryAccessibilityHelpEvent.cs
- SessionState.cs
- DataPagerFieldItem.cs
- ListMarkerLine.cs
- DetailsViewUpdateEventArgs.cs
- JoinGraph.cs
- PerfCounterSection.cs
- StringInfo.cs
- TypefaceMap.cs
- CultureSpecificCharacterBufferRange.cs
- SchemaTypeEmitter.cs
- SystemIPv6InterfaceProperties.cs
- UIElementHelper.cs
- TrailingSpaceComparer.cs
- ObjectCache.cs
- ReturnType.cs
- DataServiceCollectionOfT.cs
- BaseTemplateParser.cs
- HeaderCollection.cs
- EncryptedHeader.cs
- InvalidCastException.cs
- InlineCollection.cs
- ObjectTokenCategory.cs
- SimpleHandlerBuildProvider.cs
- XmlCustomFormatter.cs
- ErrorFormatter.cs
- Win32.cs
- DataSourceCache.cs
- UnaryOperationBinder.cs
- XamlParser.cs
- EpmSyndicationContentSerializer.cs
- SchemaNotation.cs