DiagnosticEventProvider.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / System.Runtime.DurableInstancing / System / Runtime / Diagnostics / DiagnosticEventProvider.cs / 1305376 / DiagnosticEventProvider.cs

                            //------------------------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------------------------

namespace System.Runtime.Diagnostics 
{
    using System; 
    using Microsoft.Win32; 
    using System.Globalization;
    using System.Runtime.Interop; 
    using System.Threading;
    using System.Security;
    using System.Diagnostics.Eventing;
    using System.Collections.Generic; 
    using System.Security.Permissions;
    using System.Runtime.InteropServices; 
    using System.Runtime.CompilerServices; 
    using System.Diagnostics.CodeAnalysis;
 
    // This is a class defined based on CLR's internal implementation of ETW provider
    // This class should be replaced with CLR's version (whenever avaialble) that exposes callback functionality
    [System.Security.Permissions.HostProtection(MayLeakOnAbort = true)]
    class DiagnosticsEventProvider : IDisposable 
    {
        [SecurityCritical] 
        [Fx.Tag.SecurityNote(Critical = "Calling Unsafe code; usage of UnsafeNativeMethods.EtwEnableCallback")] 
        UnsafeNativeMethods.EtwEnableCallback etwCallback;      // Trace Callback function
 
        long traceRegistrationHandle;                              // Trace Registration Handle
        byte currentTraceLevel;                                    // Tracing Level
        long anyKeywordMask;                                       // Trace Enable Flags
        long allKeywordMask;                                       // Match all keyword 
        bool isProviderEnabled;                                    // Enabled flag from Trace callback
        Guid providerId;                                           // Control Guid 
        int isDisposed;                                            // when 1, provider has unregister 

        [ThreadStatic] 
        static WriteEventErrorCode errorCode; // The last return code stored from a WriteEvent call

        const int basicTypeAllocationBufferSize = 16;
        const int etwMaxNumberArguments = 32; 
        const int etwAPIMaxStringCount = 8;
        const int maxEventDataDescriptors = 128; 
        const int traceEventMaximumSize = 65482; 
        const int traceEventMaximumStringSize = 32724;
        const int WindowsVistaMajorNumber = 6; 

        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
        } 

        [SuppressMessage(FxCop.Category.Design, FxCop.Rule.NestedTypesShouldNotBeVisible)]
        public enum WriteEventErrorCode : int
        { 
            NoError,
            NoFreeBuffers, 
            EventTooBig 
        }
 
        /// 
        /// Constructs a new EventProvider.  This causes the class to be registered with the OS
        /// if an ETW controller turns on the logging then logging will start.
        ///  
        /// The GUID that identifies this provider to the system.
        [SecurityCritical] 
        [PermissionSet(SecurityAction.Demand, Unrestricted = true)] 
        protected DiagnosticsEventProvider(Guid providerGuid)
        { 
            this.providerId = providerGuid;
            EtwRegister();
        }
 
        /// 
        /// This method registers the controlGuid of this class with ETW. 
        /// We need to be running on Vista or above. If not a 
        /// PlatformNotSupported exception will be thrown.
        /// If for some reason the ETW EtwRegister call failed 
        /// a NotSupported exception will be thrown.
        /// 
        [SecurityCritical]
        [SuppressMessage(FxCop.Category.ReliabilityBasic, FxCop.Rule.WrapExceptionsRule, 
            Justification = "Don't trace exceptions thrown from the initialization API.")]
        unsafe void EtwRegister() 
        { 
            this.etwCallback = new UnsafeNativeMethods.EtwEnableCallback(EtwEnableCallBack);
            uint etwRegistrationStatus = UnsafeNativeMethods.EventRegister(ref this.providerId, this.etwCallback, null, ref this.traceRegistrationHandle); 
            if (etwRegistrationStatus != 0)
            {
                throw new InvalidOperationException(SRCore.EtwRegistrationFailed(etwRegistrationStatus.ToString("x", CultureInfo.CurrentCulture)));
            } 
        }
 
        // 
        // implement Dispose Pattern to early deregister from ETW instead 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)
        {
            if ((this.isDisposed != 1) && (Interlocked.Exchange(ref this.isDisposed, 1) == 0)) 
            {
                this.isProviderEnabled = false; 
                Deregister(); 
            }
        } 

        /// 
        /// This method deregisters the controlGuid of this class with ETW.
        ///  
        public virtual void Close()
        { 
            Dispose(); 
        }
 
        ~DiagnosticsEventProvider()
        {
            Dispose(false);
        } 

        ///  
        /// This method un-registers from ETW. 
        /// 
        [SuppressMessage(FxCop.Category.Usage, FxCop.Rule.DoNotIgnoreMethodResults)] 
        [SecurityCritical]
        unsafe void Deregister()
        {
            // Unregister from ETW using the RegHandle saved from 
            // the register call.
            if (this.traceRegistrationHandle != 0) 
            { 
                UnsafeNativeMethods.EventUnregister(this.traceRegistrationHandle);
                this.traceRegistrationHandle = 0; 
            }
        }

        [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
                        ) 
        {
            this.isProviderEnabled = (isEnabled != 0); 
            this.currentTraceLevel = setLevel; 
            this.anyKeywordMask = anyKeyword;
            this.allKeywordMask = allKeyword; 
            OnControllerCommand();
        }

        protected virtual void OnControllerCommand() { } 

        ///  
        /// IsEnabled, method used to test if provider is enabled 
        /// 
        public bool IsEnabled() 
        {
            return this.isProviderEnabled;
        }
 
        /// 
        /// IsEnabled, method used to test if event is enabled 
        ///  
        /// 
        /// Level  to test 
        /// 
        /// 
        /// Keyword  to test
        ///  
        public bool IsEnabled(byte level, long keywords)
        { 
            if (this.isProviderEnabled) 
            {
                if ((level <= this.currentTraceLevel) || 
                    (this.currentTraceLevel == 0)) // This also covers the case of Level == 0.
                {
                    // Check if Keyword is enabled
                    if ((keywords == 0) || 
                        (((keywords & this.anyKeywordMask) != 0) &&
                         ((keywords & this.allKeywordMask) == this.allKeywordMask))) 
                    { 
                        return true;
                    } 
                }
            }

            return false; 
        }
 
        [SuppressMessage(FxCop.Category.Design, FxCop.Rule.UsePropertiesWhereAppropriate)] 
        public static WriteEventErrorCode GetLastWriteEventError()
        { 
            return errorCode;
        }

        // 
        // Helper function to set the last error on the thread
        // 
        static void SetLastError(int error) 
        {
            switch (error) 
            {
                case UnsafeNativeMethods.ERROR_ARITHMETIC_OVERFLOW:
                case UnsafeNativeMethods.ERROR_MORE_DATA:
                    errorCode = WriteEventErrorCode.EventTooBig; 
                    break;
                case UnsafeNativeMethods.ERROR_NOT_ENOUGH_MEMORY: 
                    errorCode = WriteEventErrorCode.NoFreeBuffers; 
                    break;
            } 
        }

        /// 
        /// This routine is used by WriteEvent to unbox the object type and 
        /// to fill the passed in ETW data descriptor.
        ///  
        /// argument to be decoded 
        /// pointer to the descriptor to be filled
        /// storage buffer for storing user data, needed because cant get the address of the object 
        /// null if the object is a basic type other than string. String otherwise

        [SecurityCritical]
        static unsafe string EncodeObject(ref object data, UnsafeNativeMethods.EventData* dataDescriptor, byte* dataBuffer) 
        {
            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->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
            {
                // 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
        /// 
        [Fx.Tag.SecurityNote(Critical = "Calling Unsafe code; usage of EventDescriptor, which is protected by a LinkDemand")] 
        [SecurityCritical]
        public bool WriteMessageEvent(string eventMessage, byte eventLevel, long eventKeywords) 
        { 
            int status = 0;
 
            if (eventMessage == null)
            {
                throw Fx.Exception.AsError(new ArgumentNullException("eventMessage"));
            } 

            if (IsEnabled(eventLevel, eventKeywords)) 
            { 
                if (eventMessage.Length > traceEventMaximumStringSize)
                { 
                    errorCode = WriteEventErrorCode.EventTooBig;
                    return false;
                }
                unsafe 
                {
                    fixed (char* pdata = eventMessage) 
                    { 
                        status = (int)UnsafeNativeMethods.EventWriteString(this.traceRegistrationHandle, 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 
        /// 
        [SecurityCritical] 
        [Fx.Tag.SecurityNote(Critical = "Accesses security critical code WriteMessageEvent")]
        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.
        /// 
        [SuppressMessage(FxCop.Category.Maintainability, FxCop.Rule.AvoidExcessiveComplexity, Justification = "Performance-critical code")] 
        [Fx.Tag.SecurityNote(Critical = "Calling Unsafe code; usage of EventDescriptor, which is protected by a LinkDemand")]
        [SecurityCritical] 
        public bool WriteEvent(ref EventDescriptor eventDescriptor, params  object[] eventPayload) 
        {
            uint status = 0; 

            if (IsEnabled(eventDescriptor.Level, eventDescriptor.Keywords))
            {
                int argCount = 0; 

                Guid correlationId = GetActivityId(); 
                SetActivityId(ref correlationId); 
                unsafe
                { 
                    if ((eventPayload == null)
                        || (eventPayload.Length == 0)
                        || (eventPayload.Length == 1))
                    { 
                        string dataString = null;
                        UnsafeNativeMethods.EventData userData; 
 
                        byte* dataBuffer = stackalloc byte[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 > traceEventMaximumSize)
                        {
                            // 
                            // Maximum size of the event payload plus header is 64k
                            // 
                            errorCode = WriteEventErrorCode.EventTooBig; 
                            return false;
                        } 

                        if (dataString != null)
                        {
                            fixed (char* pdata = dataString) 
                            {
                                userData.DataPointer = (ulong)pdata; 
                                status = UnsafeNativeMethods.EventWrite(this.traceRegistrationHandle, ref eventDescriptor, (uint)argCount, &userData); 
                            }
                        } 
                        else
                        {
                            if (argCount == 0)
                            { 
                                status = UnsafeNativeMethods.EventWrite(this.traceRegistrationHandle, ref eventDescriptor, 0, null);
                            } 
                            else 
                            {
                                status = UnsafeNativeMethods.EventWrite(this.traceRegistrationHandle, ref eventDescriptor, (uint)argCount, &userData); 
                            }

                        }
                    } 
                    else
                    { 
 
                        argCount = eventPayload.Length;
 
                        if (argCount > etwMaxNumberArguments)
                        {
                            //
                            //too many arguments to log 
                            //
                            throw Fx.Exception.AsError(new ArgumentOutOfRangeException("eventPayload", 
                                SRCore.EtwMaxNumberArgumentsExceeded(etwMaxNumberArguments))); 
                        }
 
                        uint totalEventSize = 0;
                        int index;
                        int stringIndex = 0;
                        int[] stringPosition = new int[etwAPIMaxStringCount]; 
                        string[] dataString = new string[etwAPIMaxStringCount];
                        UnsafeNativeMethods.EventData* userData = stackalloc UnsafeNativeMethods.EventData[argCount]; 
                        UnsafeNativeMethods.EventData* userDataPtr = (UnsafeNativeMethods.EventData*)userData; 
                        byte* dataBuffer = stackalloc byte[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 += basicTypeAllocationBufferSize;
                                totalEventSize += userDataPtr->Size; 
                                userDataPtr++; 
                                if (isString != null)
                                { 
                                    if (stringIndex < etwAPIMaxStringCount)
                                    {
                                        dataString[stringIndex] = isString;
                                        stringPosition[stringIndex] = index; 
                                        stringIndex++;
                                    } 
                                    else 
                                    {
                                        throw Fx.Exception.AsError(new ArgumentOutOfRangeException("eventPayload", 
                                            SRCore.EtwAPIMaxStringCountExceeded(etwAPIMaxStringCount)));
                                    }
                                }
                            } 
                        }
 
                        if (totalEventSize > traceEventMaximumSize) 
                        {
                            errorCode = 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 = (UnsafeNativeMethods.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;
                            } 
 
                            status = UnsafeNativeMethods.EventWrite(this.traceRegistrationHandle, 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. 
        /// 
        [Fx.Tag.SecurityNote(Critical = "Calling Unsafe code; usage of EventDescriptor, which is protected by a LinkDemand")] 
        [SecurityCritical] 
        public bool WriteEvent(ref EventDescriptor eventDescriptor, string data)
        { 
            uint status = 0;
            //check all strings for null
            data = (data ?? string.Empty);
 
            if (IsEnabled(eventDescriptor.Level, eventDescriptor.Keywords))
            { 
                if (data.Length > traceEventMaximumStringSize) 
                {
                    errorCode = WriteEventErrorCode.EventTooBig; 
                    return false;
                }

                Guid correlationId = GetActivityId(); 
                SetActivityId(ref correlationId);
 
                UnsafeNativeMethods.EventData userData; 

                userData.Size = (uint)((data.Length + 1) * 2); 
                userData.Reserved = 0;

                unsafe
                { 
                    fixed (char* pdata = data)
                    { 
                        userData.DataPointer = (ulong)pdata; 
                        status = UnsafeNativeMethods.EventWrite(this.traceRegistrationHandle, 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 
        /// 
        [Fx.Tag.SecurityNote(Critical = "Calling Unsafe code; usage of EventDescriptor, which is protected by a LinkDemand")] 
        [SecurityCritical] 
        internal protected bool WriteEvent(ref EventDescriptor eventDescriptor, int dataCount, IntPtr data)
        { 
            uint status = 0;

            Guid correlationId = GetActivityId();
            SetActivityId(ref correlationId); 
            unsafe
            { 
                status = UnsafeNativeMethods.EventWrite(this.traceRegistrationHandle, ref eventDescriptor, (uint)dataCount, (UnsafeNativeMethods.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.
        ///  
        [SuppressMessage(FxCop.Category.Maintainability, FxCop.Rule.AvoidExcessiveComplexity, Justification = "Performance-critical code")]
        [Fx.Tag.SecurityNote(Critical = "Calling Unsafe code; usage of EventDescriptor, which is protected by a LinkDemand")] 
        [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
                { 
                    if ((eventPayload != null) && (eventPayload.Length != 0)) 
                    {
                        int argCount = eventPayload.Length; 
                        if (argCount > etwMaxNumberArguments)
                        {
                            //
                            //too many arguments to log 
                            //
                            throw Fx.Exception.AsError(new ArgumentOutOfRangeException("eventPayload", 
                                SRCore.EtwMaxNumberArgumentsExceeded(etwMaxNumberArguments))); 
                        }
 
                        uint totalEventSize = 0;
                        int index;
                        int stringIndex = 0;
                        int[] stringPosition = new int[etwAPIMaxStringCount]; //used to keep the position of strings in the eventPayload parameter 
                        string[] dataString = new string[etwAPIMaxStringCount]; // string arrays from the eventPayload parameter
                        UnsafeNativeMethods.EventData* userData = stackalloc UnsafeNativeMethods.EventData[argCount]; // allocation for the data descriptors 
                        UnsafeNativeMethods.EventData* userDataPtr = (UnsafeNativeMethods.EventData*)userData; 
                        byte* dataBuffer = stackalloc byte[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 += basicTypeAllocationBufferSize;
                                totalEventSize += userDataPtr->Size; 
                                userDataPtr++; 
                                if (isString != null)
                                { 
                                    if (stringIndex < etwAPIMaxStringCount)
                                    {
                                        dataString[stringIndex] = isString;
                                        stringPosition[stringIndex] = index; 
                                        stringIndex++;
                                    } 
                                    else 
                                    {
                                        throw Fx.Exception.AsError(new ArgumentOutOfRangeException("eventPayload", 
                                            SRCore.EtwAPIMaxStringCountExceeded(etwAPIMaxStringCount)));
                                    }
                                }
                            } 
                        }
 
                        if (totalEventSize > traceEventMaximumSize) 
                        {
                            errorCode = 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 = (UnsafeNativeMethods.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;
                            }
 
                            status = UnsafeNativeMethods.EventWriteTransfer(this.traceRegistrationHandle, ref eventDescriptor, ref activityId, ref relatedActivityId, (uint)argCount, userData);
                        } 
                    } 
                    else
                    { 
                        status = UnsafeNativeMethods.EventWriteTransfer(this.traceRegistrationHandle, ref eventDescriptor, ref activityId, ref relatedActivityId, 0, null);
                    }
                }
            } 

            if (status != 0) 
            { 
                SetLastError((int)status);
                return false; 
            }

            return true;
        } 

        [SecurityCritical] 
        [Fx.Tag.SecurityNote(Critical = "Calling Unsafe code; usage of EventDescriptor, which is protected by a LinkDemand")] 
        protected bool WriteTransferEvent(ref EventDescriptor eventDescriptor, Guid relatedActivityId, int dataCount, IntPtr data)
        { 
            uint status = 0;
            Guid activityId = GetActivityId();
            unsafe
            { 
                status = UnsafeNativeMethods.EventWriteTransfer(this.traceRegistrationHandle,
                                                ref eventDescriptor, 
                                                ref activityId, 
                                                ref relatedActivityId,
                                                (uint)dataCount, 
                                                (UnsafeNativeMethods.EventData*)data);
            }

            if (status != 0) 
            {
                SetLastError((int)status); 
                return false; 
            }
            return true; 
        }

        [SuppressMessage(FxCop.Category.Usage, FxCop.Rule.DoNotIgnoreMethodResults, MessageId = "Microsoft.Win32.UnsafeNativeMethods.EventActivityIdControl(System.Int32,System.Guid@)")]
        [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotIndirectlyExposeMethodsWithLinkDemands, Justification = "SecurityCriticial method")] 
        [SecurityCritical]
        static Guid GetActivityId() 
        { 
            //
 
            object id = System.Diagnostics.Trace.CorrelationManager.ActivityId;
            return id == null ? Guid.Empty : (Guid)id;
        }
 
        [SuppressMessage(FxCop.Category.Usage, FxCop.Rule.DoNotIgnoreMethodResults, MessageId = "System.Runtime.Interop.UnsafeNativeMethods.EventActivityIdControl(System.Int32,System.Guid@)")]
        [SecurityCritical] 
        public static void SetActivityId(ref Guid id) 
        {
            UnsafeNativeMethods.EventActivityIdControl((int)ActivityControl.EVENT_ACTIVITY_CTRL_SET_ID, ref id); 
        }

        [SuppressMessage(FxCop.Category.Usage, FxCop.Rule.DoNotIgnoreMethodResults, MessageId = "System.Runtime.Interop.UnsafeNativeMethods.EventActivityIdControl(System.Int32,System.Guid@)")]
        [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.
//-----------------------------------------------------------------------------

namespace System.Runtime.Diagnostics 
{
    using System; 
    using Microsoft.Win32; 
    using System.Globalization;
    using System.Runtime.Interop; 
    using System.Threading;
    using System.Security;
    using System.Diagnostics.Eventing;
    using System.Collections.Generic; 
    using System.Security.Permissions;
    using System.Runtime.InteropServices; 
    using System.Runtime.CompilerServices; 
    using System.Diagnostics.CodeAnalysis;
 
    // This is a class defined based on CLR's internal implementation of ETW provider
    // This class should be replaced with CLR's version (whenever avaialble) that exposes callback functionality
    [System.Security.Permissions.HostProtection(MayLeakOnAbort = true)]
    class DiagnosticsEventProvider : IDisposable 
    {
        [SecurityCritical] 
        [Fx.Tag.SecurityNote(Critical = "Calling Unsafe code; usage of UnsafeNativeMethods.EtwEnableCallback")] 
        UnsafeNativeMethods.EtwEnableCallback etwCallback;      // Trace Callback function
 
        long traceRegistrationHandle;                              // Trace Registration Handle
        byte currentTraceLevel;                                    // Tracing Level
        long anyKeywordMask;                                       // Trace Enable Flags
        long allKeywordMask;                                       // Match all keyword 
        bool isProviderEnabled;                                    // Enabled flag from Trace callback
        Guid providerId;                                           // Control Guid 
        int isDisposed;                                            // when 1, provider has unregister 

        [ThreadStatic] 
        static WriteEventErrorCode errorCode; // The last return code stored from a WriteEvent call

        const int basicTypeAllocationBufferSize = 16;
        const int etwMaxNumberArguments = 32; 
        const int etwAPIMaxStringCount = 8;
        const int maxEventDataDescriptors = 128; 
        const int traceEventMaximumSize = 65482; 
        const int traceEventMaximumStringSize = 32724;
        const int WindowsVistaMajorNumber = 6; 

        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
        } 

        [SuppressMessage(FxCop.Category.Design, FxCop.Rule.NestedTypesShouldNotBeVisible)]
        public enum WriteEventErrorCode : int
        { 
            NoError,
            NoFreeBuffers, 
            EventTooBig 
        }
 
        /// 
        /// Constructs a new EventProvider.  This causes the class to be registered with the OS
        /// if an ETW controller turns on the logging then logging will start.
        ///  
        /// The GUID that identifies this provider to the system.
        [SecurityCritical] 
        [PermissionSet(SecurityAction.Demand, Unrestricted = true)] 
        protected DiagnosticsEventProvider(Guid providerGuid)
        { 
            this.providerId = providerGuid;
            EtwRegister();
        }
 
        /// 
        /// This method registers the controlGuid of this class with ETW. 
        /// We need to be running on Vista or above. If not a 
        /// PlatformNotSupported exception will be thrown.
        /// If for some reason the ETW EtwRegister call failed 
        /// a NotSupported exception will be thrown.
        /// 
        [SecurityCritical]
        [SuppressMessage(FxCop.Category.ReliabilityBasic, FxCop.Rule.WrapExceptionsRule, 
            Justification = "Don't trace exceptions thrown from the initialization API.")]
        unsafe void EtwRegister() 
        { 
            this.etwCallback = new UnsafeNativeMethods.EtwEnableCallback(EtwEnableCallBack);
            uint etwRegistrationStatus = UnsafeNativeMethods.EventRegister(ref this.providerId, this.etwCallback, null, ref this.traceRegistrationHandle); 
            if (etwRegistrationStatus != 0)
            {
                throw new InvalidOperationException(SRCore.EtwRegistrationFailed(etwRegistrationStatus.ToString("x", CultureInfo.CurrentCulture)));
            } 
        }
 
        // 
        // implement Dispose Pattern to early deregister from ETW instead 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)
        {
            if ((this.isDisposed != 1) && (Interlocked.Exchange(ref this.isDisposed, 1) == 0)) 
            {
                this.isProviderEnabled = false; 
                Deregister(); 
            }
        } 

        /// 
        /// This method deregisters the controlGuid of this class with ETW.
        ///  
        public virtual void Close()
        { 
            Dispose(); 
        }
 
        ~DiagnosticsEventProvider()
        {
            Dispose(false);
        } 

        ///  
        /// This method un-registers from ETW. 
        /// 
        [SuppressMessage(FxCop.Category.Usage, FxCop.Rule.DoNotIgnoreMethodResults)] 
        [SecurityCritical]
        unsafe void Deregister()
        {
            // Unregister from ETW using the RegHandle saved from 
            // the register call.
            if (this.traceRegistrationHandle != 0) 
            { 
                UnsafeNativeMethods.EventUnregister(this.traceRegistrationHandle);
                this.traceRegistrationHandle = 0; 
            }
        }

        [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
                        ) 
        {
            this.isProviderEnabled = (isEnabled != 0); 
            this.currentTraceLevel = setLevel; 
            this.anyKeywordMask = anyKeyword;
            this.allKeywordMask = allKeyword; 
            OnControllerCommand();
        }

        protected virtual void OnControllerCommand() { } 

        ///  
        /// IsEnabled, method used to test if provider is enabled 
        /// 
        public bool IsEnabled() 
        {
            return this.isProviderEnabled;
        }
 
        /// 
        /// IsEnabled, method used to test if event is enabled 
        ///  
        /// 
        /// Level  to test 
        /// 
        /// 
        /// Keyword  to test
        ///  
        public bool IsEnabled(byte level, long keywords)
        { 
            if (this.isProviderEnabled) 
            {
                if ((level <= this.currentTraceLevel) || 
                    (this.currentTraceLevel == 0)) // This also covers the case of Level == 0.
                {
                    // Check if Keyword is enabled
                    if ((keywords == 0) || 
                        (((keywords & this.anyKeywordMask) != 0) &&
                         ((keywords & this.allKeywordMask) == this.allKeywordMask))) 
                    { 
                        return true;
                    } 
                }
            }

            return false; 
        }
 
        [SuppressMessage(FxCop.Category.Design, FxCop.Rule.UsePropertiesWhereAppropriate)] 
        public static WriteEventErrorCode GetLastWriteEventError()
        { 
            return errorCode;
        }

        // 
        // Helper function to set the last error on the thread
        // 
        static void SetLastError(int error) 
        {
            switch (error) 
            {
                case UnsafeNativeMethods.ERROR_ARITHMETIC_OVERFLOW:
                case UnsafeNativeMethods.ERROR_MORE_DATA:
                    errorCode = WriteEventErrorCode.EventTooBig; 
                    break;
                case UnsafeNativeMethods.ERROR_NOT_ENOUGH_MEMORY: 
                    errorCode = WriteEventErrorCode.NoFreeBuffers; 
                    break;
            } 
        }

        /// 
        /// This routine is used by WriteEvent to unbox the object type and 
        /// to fill the passed in ETW data descriptor.
        ///  
        /// argument to be decoded 
        /// pointer to the descriptor to be filled
        /// storage buffer for storing user data, needed because cant get the address of the object 
        /// null if the object is a basic type other than string. String otherwise

        [SecurityCritical]
        static unsafe string EncodeObject(ref object data, UnsafeNativeMethods.EventData* dataDescriptor, byte* dataBuffer) 
        {
            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->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
            {
                // 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
        /// 
        [Fx.Tag.SecurityNote(Critical = "Calling Unsafe code; usage of EventDescriptor, which is protected by a LinkDemand")] 
        [SecurityCritical]
        public bool WriteMessageEvent(string eventMessage, byte eventLevel, long eventKeywords) 
        { 
            int status = 0;
 
            if (eventMessage == null)
            {
                throw Fx.Exception.AsError(new ArgumentNullException("eventMessage"));
            } 

            if (IsEnabled(eventLevel, eventKeywords)) 
            { 
                if (eventMessage.Length > traceEventMaximumStringSize)
                { 
                    errorCode = WriteEventErrorCode.EventTooBig;
                    return false;
                }
                unsafe 
                {
                    fixed (char* pdata = eventMessage) 
                    { 
                        status = (int)UnsafeNativeMethods.EventWriteString(this.traceRegistrationHandle, 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 
        /// 
        [SecurityCritical] 
        [Fx.Tag.SecurityNote(Critical = "Accesses security critical code WriteMessageEvent")]
        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.
        /// 
        [SuppressMessage(FxCop.Category.Maintainability, FxCop.Rule.AvoidExcessiveComplexity, Justification = "Performance-critical code")] 
        [Fx.Tag.SecurityNote(Critical = "Calling Unsafe code; usage of EventDescriptor, which is protected by a LinkDemand")]
        [SecurityCritical] 
        public bool WriteEvent(ref EventDescriptor eventDescriptor, params  object[] eventPayload) 
        {
            uint status = 0; 

            if (IsEnabled(eventDescriptor.Level, eventDescriptor.Keywords))
            {
                int argCount = 0; 

                Guid correlationId = GetActivityId(); 
                SetActivityId(ref correlationId); 
                unsafe
                { 
                    if ((eventPayload == null)
                        || (eventPayload.Length == 0)
                        || (eventPayload.Length == 1))
                    { 
                        string dataString = null;
                        UnsafeNativeMethods.EventData userData; 
 
                        byte* dataBuffer = stackalloc byte[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 > traceEventMaximumSize)
                        {
                            // 
                            // Maximum size of the event payload plus header is 64k
                            // 
                            errorCode = WriteEventErrorCode.EventTooBig; 
                            return false;
                        } 

                        if (dataString != null)
                        {
                            fixed (char* pdata = dataString) 
                            {
                                userData.DataPointer = (ulong)pdata; 
                                status = UnsafeNativeMethods.EventWrite(this.traceRegistrationHandle, ref eventDescriptor, (uint)argCount, &userData); 
                            }
                        } 
                        else
                        {
                            if (argCount == 0)
                            { 
                                status = UnsafeNativeMethods.EventWrite(this.traceRegistrationHandle, ref eventDescriptor, 0, null);
                            } 
                            else 
                            {
                                status = UnsafeNativeMethods.EventWrite(this.traceRegistrationHandle, ref eventDescriptor, (uint)argCount, &userData); 
                            }

                        }
                    } 
                    else
                    { 
 
                        argCount = eventPayload.Length;
 
                        if (argCount > etwMaxNumberArguments)
                        {
                            //
                            //too many arguments to log 
                            //
                            throw Fx.Exception.AsError(new ArgumentOutOfRangeException("eventPayload", 
                                SRCore.EtwMaxNumberArgumentsExceeded(etwMaxNumberArguments))); 
                        }
 
                        uint totalEventSize = 0;
                        int index;
                        int stringIndex = 0;
                        int[] stringPosition = new int[etwAPIMaxStringCount]; 
                        string[] dataString = new string[etwAPIMaxStringCount];
                        UnsafeNativeMethods.EventData* userData = stackalloc UnsafeNativeMethods.EventData[argCount]; 
                        UnsafeNativeMethods.EventData* userDataPtr = (UnsafeNativeMethods.EventData*)userData; 
                        byte* dataBuffer = stackalloc byte[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 += basicTypeAllocationBufferSize;
                                totalEventSize += userDataPtr->Size; 
                                userDataPtr++; 
                                if (isString != null)
                                { 
                                    if (stringIndex < etwAPIMaxStringCount)
                                    {
                                        dataString[stringIndex] = isString;
                                        stringPosition[stringIndex] = index; 
                                        stringIndex++;
                                    } 
                                    else 
                                    {
                                        throw Fx.Exception.AsError(new ArgumentOutOfRangeException("eventPayload", 
                                            SRCore.EtwAPIMaxStringCountExceeded(etwAPIMaxStringCount)));
                                    }
                                }
                            } 
                        }
 
                        if (totalEventSize > traceEventMaximumSize) 
                        {
                            errorCode = 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 = (UnsafeNativeMethods.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;
                            } 
 
                            status = UnsafeNativeMethods.EventWrite(this.traceRegistrationHandle, 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. 
        /// 
        [Fx.Tag.SecurityNote(Critical = "Calling Unsafe code; usage of EventDescriptor, which is protected by a LinkDemand")] 
        [SecurityCritical] 
        public bool WriteEvent(ref EventDescriptor eventDescriptor, string data)
        { 
            uint status = 0;
            //check all strings for null
            data = (data ?? string.Empty);
 
            if (IsEnabled(eventDescriptor.Level, eventDescriptor.Keywords))
            { 
                if (data.Length > traceEventMaximumStringSize) 
                {
                    errorCode = WriteEventErrorCode.EventTooBig; 
                    return false;
                }

                Guid correlationId = GetActivityId(); 
                SetActivityId(ref correlationId);
 
                UnsafeNativeMethods.EventData userData; 

                userData.Size = (uint)((data.Length + 1) * 2); 
                userData.Reserved = 0;

                unsafe
                { 
                    fixed (char* pdata = data)
                    { 
                        userData.DataPointer = (ulong)pdata; 
                        status = UnsafeNativeMethods.EventWrite(this.traceRegistrationHandle, 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 
        /// 
        [Fx.Tag.SecurityNote(Critical = "Calling Unsafe code; usage of EventDescriptor, which is protected by a LinkDemand")] 
        [SecurityCritical] 
        internal protected bool WriteEvent(ref EventDescriptor eventDescriptor, int dataCount, IntPtr data)
        { 
            uint status = 0;

            Guid correlationId = GetActivityId();
            SetActivityId(ref correlationId); 
            unsafe
            { 
                status = UnsafeNativeMethods.EventWrite(this.traceRegistrationHandle, ref eventDescriptor, (uint)dataCount, (UnsafeNativeMethods.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.
        ///  
        [SuppressMessage(FxCop.Category.Maintainability, FxCop.Rule.AvoidExcessiveComplexity, Justification = "Performance-critical code")]
        [Fx.Tag.SecurityNote(Critical = "Calling Unsafe code; usage of EventDescriptor, which is protected by a LinkDemand")] 
        [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
                { 
                    if ((eventPayload != null) && (eventPayload.Length != 0)) 
                    {
                        int argCount = eventPayload.Length; 
                        if (argCount > etwMaxNumberArguments)
                        {
                            //
                            //too many arguments to log 
                            //
                            throw Fx.Exception.AsError(new ArgumentOutOfRangeException("eventPayload", 
                                SRCore.EtwMaxNumberArgumentsExceeded(etwMaxNumberArguments))); 
                        }
 
                        uint totalEventSize = 0;
                        int index;
                        int stringIndex = 0;
                        int[] stringPosition = new int[etwAPIMaxStringCount]; //used to keep the position of strings in the eventPayload parameter 
                        string[] dataString = new string[etwAPIMaxStringCount]; // string arrays from the eventPayload parameter
                        UnsafeNativeMethods.EventData* userData = stackalloc UnsafeNativeMethods.EventData[argCount]; // allocation for the data descriptors 
                        UnsafeNativeMethods.EventData* userDataPtr = (UnsafeNativeMethods.EventData*)userData; 
                        byte* dataBuffer = stackalloc byte[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 += basicTypeAllocationBufferSize;
                                totalEventSize += userDataPtr->Size; 
                                userDataPtr++; 
                                if (isString != null)
                                { 
                                    if (stringIndex < etwAPIMaxStringCount)
                                    {
                                        dataString[stringIndex] = isString;
                                        stringPosition[stringIndex] = index; 
                                        stringIndex++;
                                    } 
                                    else 
                                    {
                                        throw Fx.Exception.AsError(new ArgumentOutOfRangeException("eventPayload", 
                                            SRCore.EtwAPIMaxStringCountExceeded(etwAPIMaxStringCount)));
                                    }
                                }
                            } 
                        }
 
                        if (totalEventSize > traceEventMaximumSize) 
                        {
                            errorCode = 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 = (UnsafeNativeMethods.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;
                            }
 
                            status = UnsafeNativeMethods.EventWriteTransfer(this.traceRegistrationHandle, ref eventDescriptor, ref activityId, ref relatedActivityId, (uint)argCount, userData);
                        } 
                    } 
                    else
                    { 
                        status = UnsafeNativeMethods.EventWriteTransfer(this.traceRegistrationHandle, ref eventDescriptor, ref activityId, ref relatedActivityId, 0, null);
                    }
                }
            } 

            if (status != 0) 
            { 
                SetLastError((int)status);
                return false; 
            }

            return true;
        } 

        [SecurityCritical] 
        [Fx.Tag.SecurityNote(Critical = "Calling Unsafe code; usage of EventDescriptor, which is protected by a LinkDemand")] 
        protected bool WriteTransferEvent(ref EventDescriptor eventDescriptor, Guid relatedActivityId, int dataCount, IntPtr data)
        { 
            uint status = 0;
            Guid activityId = GetActivityId();
            unsafe
            { 
                status = UnsafeNativeMethods.EventWriteTransfer(this.traceRegistrationHandle,
                                                ref eventDescriptor, 
                                                ref activityId, 
                                                ref relatedActivityId,
                                                (uint)dataCount, 
                                                (UnsafeNativeMethods.EventData*)data);
            }

            if (status != 0) 
            {
                SetLastError((int)status); 
                return false; 
            }
            return true; 
        }

        [SuppressMessage(FxCop.Category.Usage, FxCop.Rule.DoNotIgnoreMethodResults, MessageId = "Microsoft.Win32.UnsafeNativeMethods.EventActivityIdControl(System.Int32,System.Guid@)")]
        [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotIndirectlyExposeMethodsWithLinkDemands, Justification = "SecurityCriticial method")] 
        [SecurityCritical]
        static Guid GetActivityId() 
        { 
            //
 
            object id = System.Diagnostics.Trace.CorrelationManager.ActivityId;
            return id == null ? Guid.Empty : (Guid)id;
        }
 
        [SuppressMessage(FxCop.Category.Usage, FxCop.Rule.DoNotIgnoreMethodResults, MessageId = "System.Runtime.Interop.UnsafeNativeMethods.EventActivityIdControl(System.Int32,System.Guid@)")]
        [SecurityCritical] 
        public static void SetActivityId(ref Guid id) 
        {
            UnsafeNativeMethods.EventActivityIdControl((int)ActivityControl.EVENT_ACTIVITY_CTRL_SET_ID, ref id); 
        }

        [SuppressMessage(FxCop.Category.Usage, FxCop.Rule.DoNotIgnoreMethodResults, MessageId = "System.Runtime.Interop.UnsafeNativeMethods.EventActivityIdControl(System.Int32,System.Guid@)")]
        [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

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK