EventProvider.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 / clr / src / BCL / System / Diagnostics / Eventing / EventProvider.cs / 1305376 / EventProvider.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// [....] 
//-----------------------------------------------------------------------------
using System; 
using System.Runtime.InteropServices; 
using System.Runtime.CompilerServices;
using Microsoft.Win32; 
using System.Globalization;
using System.Collections.Generic;
using System.Threading;
using System.Security.Permissions; 
using System.Security;
using System.Diagnostics.CodeAnalysis; 
 
namespace System.Diagnostics.Eventing
{ 
    // New in CLR4.0
    internal enum ControllerCommand
    {
        // Strictly Positive numbers are for provider-specific commands, negative number are for 'shared' commands. 256 
        // The first 256 negative numbers are reserved for the framework.
        Update = 0, 
        SendManifest = -1, 
    };
 
    [System.Security.Permissions.HostProtection(MayLeakOnAbort = true)]
    internal partial class EventProvider : IDisposable
    {
        // This is the windows EVENT_DATA_DESCRIPTOR structure.  We expose it because this is what 
        // subclasses of EventProvider use when creating efficient (but unsafe) version of
        // EventWrite.   We do make it a nested type because we really don't expect anyone to use 
        // it except subclasses (and then only rarely). 
        public struct EventData
        { 
            internal unsafe ulong Ptr;
            internal uint Size;
            internal uint Reserved;
        } 

        [System.Security.SecuritySafeCritical] 
        ManifestEtw.EtwEnableCallback m_etwCallback;     // Trace Callback function 

        private long m_regHandle;                        // Trace Registration Handle 
        private byte m_level;                            // Tracing Level
        private long m_anyKeywordMask;                   // Trace Enable Flags
        private long m_allKeywordMask;                   // Match all keyword
        private int m_enabled;                           // Enabled flag from Trace callback 
        private Guid m_providerId;                       // Control Guid
        private int m_disposed;                          // when 1, provider has unregister 
        private bool m_isClassic;                        // Should we use classic (XP) ETW APIs (more efficient than s_isClassic) 
        private static bool s_isClassic;                 // same as m_isClassic for static APIs.
 
        [ThreadStatic]
        private static WriteEventErrorCode s_returnCode; // The last return code

        private const int s_basicTypeAllocationBufferSize = 16; 
        private const int s_etwMaxMumberArguments = 32;
        private const int s_etwAPIMaxStringCount = 8; 
        private const int s_maxEventDataDescriptors = 128; 
        private const int s_traceEventMaximumSize = 65482;
        private const int s_traceEventMaximumStringSize = 32724; 

        [SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")]
        public enum WriteEventErrorCode : int
        { 
            //check mapping to runtime codes
            NoError = 0, 
            NoFreeBuffers = 1, 
            EventTooBig = 2
        } 

        private enum ActivityControl : uint
        {
            EVENT_ACTIVITY_CTRL_GET_ID = 1, 
            EVENT_ACTIVITY_CTRL_SET_ID = 2,
            EVENT_ACTIVITY_CTRL_CREATE_ID = 3, 
            EVENT_ACTIVITY_CTRL_GET_SET_ID = 4, 
            EVENT_ACTIVITY_CTRL_CREATE_SET_ID = 5
        } 

        // 
        // 
        //  
        /// 
        /// Constructs a new EventProvider.  This causes the class to be registered with the OS an 
        /// if a ETW controller turns on the logging then logging will start. 
        /// 
        /// The GUID that identifies this provider to the system. 
        [System.Security.SecurityCritical]
        [PermissionSet(SecurityAction.Demand, Unrestricted = true)]
        [SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "guid")]
        protected EventProvider(Guid providerGuid) 
        {
            m_providerId = providerGuid; 
            s_isClassic = m_isClassic = true; 
            //
            // Register the ProviderId with ETW 
            //
            Register(providerGuid);
        }
 
        internal EventProvider()
        { 
            s_isClassic = m_isClassic = true; 
        }
 
        /// 
        /// This method registers the controlGuid of this class with ETW.
        /// We need to be running on Vista or above. If not an
        /// PlatformNotSupported exception will be thrown. 
        /// If for some reason the ETW Register call failed
        /// a NotSupported exception will be thrown. 
        ///  
        // 
        //  
        // 
        // 
        // 
        [System.Security.SecurityCritical] 
        internal unsafe void Register(Guid providerGuid)
        { 
            m_providerId = providerGuid; 
            uint status;
            m_etwCallback = new ManifestEtw.EtwEnableCallback(EtwEnableCallBack); 

            status = EventRegister(ref m_providerId, m_etwCallback);
            if (status != 0)
            { 
                throw new ArgumentException(Win32Native.GetMessage(unchecked((int)status)));
            } 
        } 

        // 
        // implement Dispose Pattern to early deregister from ETW insted of waiting for
        // the finalizer to call deregistration.
        // Once the user is done with the provider it needs to call Close() or Dispose()
        // If neither are called the finalizer will unregister the provider anyway 
        //
        public void Dispose() 
        { 
            Dispose(true);
            GC.SuppressFinalize(this); 
        }

        // 
        //  
        // 
        [System.Security.SecuritySafeCritical] 
        protected virtual void Dispose(bool disposing) 
        {
            // 
            // explicit cleanup is done by calling Dispose with true from
            // Dispose() or Close(). The disposing arguement is ignored because there
            // are no unmanaged resources.
            // The finalizer calls Dispose with false. 
            //
 
            // 
            // check if the object has been allready disposed
            // 
            if (m_disposed == 1) return;

            if (Interlocked.Exchange(ref m_disposed, 1) != 0)
            { 
                // somebody is allready disposing the provider
                return; 
            } 

            // 
            // Disables Tracing in the provider, then unregister
            //

            m_enabled = 0; 

            Deregister(); 
        } 

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

        ~EventProvider() 
        {
            Dispose(false);
        }
 
        /// 
        /// This method un-registers from ETW. 
        ///  
        // 
        //  
        // 
        //
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "Microsoft.Win32.ManifestEtw.EventUnregister(System.Int64)"), System.Security.SecurityCritical]
        private unsafe void Deregister() 
        {
            // 
            // Unregister from ETW using the RegHandle saved from 
            // the register call.
            // 

            if (m_regHandle != 0)
            {
                EventUnregister(); 
                m_regHandle = 0;
            } 
        } 

        //  
        // 
        // 
        // 
        [System.Security.SecurityCritical] 
        unsafe void EtwEnableCallBack(
                        [In] ref System.Guid sourceId, 
                        [In] int isEnabled, 
                        [In] byte setLevel,
                        [In] long anyKeyword, 
                        [In] long allKeyword,
                        [In] ManifestEtw.EVENT_FILTER_DESCRIPTOR* filterData,
                        [In] void* callbackContext
                        ) 
        {
            m_enabled = isEnabled; 
            m_level = setLevel; 
            m_anyKeywordMask = anyKeyword;
            m_allKeywordMask = allKeyword; 
            ControllerCommand command = Eventing.ControllerCommand.Update;
            IDictionary args = null;

            byte[] data; 
            int keyIndex;
            if (GetDataFromController(filterData, out command, out data, out keyIndex)) 
            { 
                args = new Dictionary(4);
                while (keyIndex < data.Length) 
                {
                    int keyEnd = FindNull(data, keyIndex);
                    int valueIdx = keyEnd + 1;
                    int valueEnd = FindNull(data, valueIdx); 
                    if (valueEnd < data.Length)
                    { 
                        string key = System.Text.Encoding.UTF8.GetString(data, keyIndex, keyEnd - keyIndex); 
                        string value = System.Text.Encoding.UTF8.GetString(data, valueIdx, valueEnd - valueIdx);
                        args[key] = value; 
                    }
                    keyIndex = valueEnd + 1;
                }
            } 
            OnControllerCommand(command, args);
        } 
 
        // New in CLR4.0
        protected virtual void OnControllerCommand(ControllerCommand command, IDictionary arguments) { } 
        protected EventLevel Level { get { return (EventLevel)m_level; } set { m_level = (byte)value; } }
        protected EventKeywords MatchAnyKeyword { get { return (EventKeywords)m_anyKeywordMask; } set { m_anyKeywordMask = (long)value; } }
        protected EventKeywords MatchAllKeyword { get { return (EventKeywords)m_allKeywordMask; } set { m_allKeywordMask = (long)value; } }
 
        static private int FindNull(byte[] buffer, int idx)
        { 
            while (idx < buffer.Length && buffer[idx] != 0) 
                idx++;
            return idx; 
        }

        /// 
        /// Gets any data to be passed from the controller to the provider.  It starts with what is passed 
        /// into the callback, but unfortunately this data is only present for when the provider is active
        /// at the the time the controller issues the command.  To allow for providers to activate after the 
        /// controller issued a command, we also check the registry and use that to get the data.  The function 
        /// returns an array of bytes representing the data, the index into that byte array where the data
        /// starts, and the command being issued associated with that data. 
        /// 
        [System.Security.SecurityCritical]
        private unsafe bool GetDataFromController(ManifestEtw.EVENT_FILTER_DESCRIPTOR* filterData, out ControllerCommand command, out byte[] data, out int dataStart)
        { 
            data = null;
            if (filterData == null) 
            { 
                string regKey = @"\Microsoft\Windows\CurrentVersion\Winevt\Publishers\{" + m_providerId + "}";
                if (System.Runtime.InteropServices.Marshal.SizeOf(typeof(IntPtr)) == 8) 
                    regKey = @"HKEY_LOCAL_MACHINE\Software" + @"\Wow6432Node" + regKey;
                else
                    regKey = @"HKEY_LOCAL_MACHINE\Software" + regKey;
 

                data = Microsoft.Win32.Registry.GetValue(regKey, "ControllerData", null) as byte[]; 
                if (data != null && data.Length >= 4) 
                {
                    // 
                    command = (ControllerCommand)(((data[3] << 8 + data[2]) << 8 + data[1]) << 8 + data[0]);
                    dataStart = 4;
                    return true;
                } 
            }
            else 
            { 
                if (filterData->Ptr != 0 && 0 < filterData->Size && filterData->Size <= 1024)
                { 
                    data = new byte[filterData->Size];
                    Marshal.Copy((IntPtr)filterData->Ptr, data, 0, data.Length);
                }
                command = (ControllerCommand) filterData->Type; 
                dataStart = 0;
                return true; 
            } 

            dataStart = 0; 
            command = ControllerCommand.Update;
            return false;
        }
 
        /// 
        /// IsEnabled, method used to test if provider is enabled 
        ///  
        public bool IsEnabled()
        { 
            return (m_enabled != 0) ? true : false;
        }

        ///  
        /// IsEnabled, method used to test if event is enabled
        ///  
        ///  
        /// Level  to test
        ///  
        /// 
        /// Keyword  to test
        /// 
        public bool IsEnabled(byte level, long keywords) 
        {
            // 
            // If not enabled at all, return false. 
            //
            if (m_enabled == 0) 
            {
                return false;
            }
 
            // This also covers the case of Level == 0.
            if ((level <= m_level) || 
                (m_level == 0)) 
            {
 
                //
                // Check if Keyword is enabled
                //
 
                if ((keywords == 0) ||
                    (((keywords & m_anyKeywordMask) != 0) && 
                     ((keywords & m_allKeywordMask) == m_allKeywordMask))) 
                {
                    return true; 
                }
            }

            return false; 
        }
 
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")] 
        public static WriteEventErrorCode GetLastWriteEventError()
        { 
            return s_returnCode;
        }

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


        //  
        // 
        //  
        //  
        // 
        //  
        // 
        // 
        // 
        //  
        // 
        //  
        //  
        // 
        //  
        // 
        // 
        // 
        //  
        // 
        [System.Security.SecurityCritical] 
        private static unsafe string EncodeObject(ref object data, EventData* dataDescriptor, byte* dataBuffer) 
        /*++
 
        Routine Description:

           This routine is used by WriteEvent to unbox the object type and
           to fill the passed in ETW data descriptor. 

        Arguments: 
 
           data - argument to be decoded
 
           dataDescriptor - pointer to the descriptor to be filled

           dataBuffer - storage buffer for storing user data, needed because cant get the address of the object
 
        Return Value:
 
           null if the object is a basic type other than string. String otherwise 

        --*/ 
        {
            dataDescriptor->Reserved = 0;

            string sRet = data as string; 
            if (sRet != null)
            { 
                dataDescriptor->Size = (uint)((sRet.Length + 1) * 2); 
                return sRet;
            } 

            if (data is IntPtr)
            {
                dataDescriptor->Size = (uint)sizeof(IntPtr); 
                IntPtr* intptrPtr = (IntPtr*)dataBuffer;
                *intptrPtr = (IntPtr)data; 
                dataDescriptor->Ptr = (ulong)intptrPtr; 
            }
            else if (data is int) 
            {
                dataDescriptor->Size = (uint)sizeof(int);
                int* intptrPtr = (int*)dataBuffer;
                *intptrPtr = (int)data; 
                dataDescriptor->Ptr = (ulong)intptrPtr;
            } 
            else if (data is long) 
            {
                dataDescriptor->Size = (uint)sizeof(long); 
                long* longptr = (long*)dataBuffer;
                *longptr = (long)data;
                dataDescriptor->Ptr = (ulong)longptr;
            } 
            else if (data is uint)
            { 
                dataDescriptor->Size = (uint)sizeof(uint); 
                uint* uintptr = (uint*)dataBuffer;
                *uintptr = (uint)data; 
                dataDescriptor->Ptr = (ulong)uintptr;
            }
            else if (data is UInt64)
            { 
                dataDescriptor->Size = (uint)sizeof(ulong);
                UInt64* ulongptr = (ulong*)dataBuffer; 
                *ulongptr = (ulong)data; 
                dataDescriptor->Ptr = (ulong)ulongptr;
            } 
            else if (data is char)
            {
                dataDescriptor->Size = (uint)sizeof(char);
                char* charptr = (char*)dataBuffer; 
                *charptr = (char)data;
                dataDescriptor->Ptr = (ulong)charptr; 
            } 
            else if (data is byte)
            { 
                dataDescriptor->Size = (uint)sizeof(byte);
                byte* byteptr = (byte*)dataBuffer;
                *byteptr = (byte)data;
                dataDescriptor->Ptr = (ulong)byteptr; 
            }
            else if (data is short) 
            { 
                dataDescriptor->Size = (uint)sizeof(short);
                short* shortptr = (short*)dataBuffer; 
                *shortptr = (short)data;
                dataDescriptor->Ptr = (ulong)shortptr;
            }
            else if (data is sbyte) 
            {
                dataDescriptor->Size = (uint)sizeof(sbyte); 
                sbyte* sbyteptr = (sbyte*)dataBuffer; 
                *sbyteptr = (sbyte)data;
                dataDescriptor->Ptr = (ulong)sbyteptr; 
            }
            else if (data is ushort)
            {
                dataDescriptor->Size = (uint)sizeof(ushort); 
                ushort* ushortptr = (ushort*)dataBuffer;
                *ushortptr = (ushort)data; 
                dataDescriptor->Ptr = (ulong)ushortptr; 
            }
            else if (data is float) 
            {
                dataDescriptor->Size = (uint)sizeof(float);
                float* floatptr = (float*)dataBuffer;
                *floatptr = (float)data; 
                dataDescriptor->Ptr = (ulong)floatptr;
            } 
            else if (data is double) 
            {
                dataDescriptor->Size = (uint)sizeof(double); 
                double* doubleptr = (double*)dataBuffer;
                *doubleptr = (double)data;
                dataDescriptor->Ptr = (ulong)doubleptr;
            } 
            else if (data is bool)
            { 
                dataDescriptor->Size = (uint)sizeof(bool); 
                bool* boolptr = (bool*)dataBuffer;
                *boolptr = (bool)data; 
                dataDescriptor->Ptr = (ulong)boolptr;
            }
            else if (data is Guid)
            { 
                dataDescriptor->Size = (uint)sizeof(Guid);
                Guid* guidptr = (Guid*)dataBuffer; 
                *guidptr = (Guid)data; 
                dataDescriptor->Ptr = (ulong)guidptr;
            } 
            else if (data is decimal)
            {
                dataDescriptor->Size = (uint)sizeof(decimal);
                decimal* decimalptr = (decimal*)dataBuffer; 
                *decimalptr = (decimal)data;
                dataDescriptor->Ptr = (ulong)decimalptr; 
            } 
            else if (data is Boolean)
            { 
                dataDescriptor->Size = (uint)sizeof(Boolean);
                Boolean* booleanptr = (Boolean*)dataBuffer;
                *booleanptr = (Boolean)data;
                dataDescriptor->Ptr = (ulong)booleanptr; 
            }
            else 
            { 
                //To our eyes, everything else is a just a string
                sRet = data.ToString(); 
                dataDescriptor->Size = (uint)((sRet.Length + 1) * 2);
                return sRet;
            }
 
            return null;
        } 
 

        ///  
        /// WriteMessageEvent, method to write a string with level and Keyword
        /// 
        /// 
        /// Level  to test 
        /// 
        ///  
        /// Keyword  to test 
        /// 
        //  
        // 
        // 
        // 
        [System.Security.SecuritySafeCritical] 
        public bool WriteMessageEvent(string eventMessage, byte eventLevel, long eventKeywords)
        { 
            int status = 0; 

            if (eventMessage == null) 
            {
                throw new ArgumentNullException("eventMessage");
            }
 
            if (IsEnabled(eventLevel, eventKeywords))
            { 
                if (eventMessage.Length > s_traceEventMaximumStringSize) 
                {
                    s_returnCode = WriteEventErrorCode.EventTooBig; 
                    return false;
                }
                unsafe
                { 
                    fixed (char* pdata = eventMessage)
                    { 
                        status = (int)EventWriteString(eventLevel, eventKeywords, pdata); 
                    }
 
                    if (status != 0)
                    {
                        SetLastError(status);
                        return false; 
                    }
                } 
            } 
            return true;
        } 

        /// 
        /// WriteMessageEvent, method to write a string with level=0 and Keyword=0
        ///  
        /// 
        /// Message to log 
        ///  
        public bool WriteMessageEvent(string eventMessage)
        { 
            return WriteMessageEvent(eventMessage, 0, 0);
        }

 
        /// 
        /// WriteEvent, method to write a parameters with event schema properties 
        ///  
        /// 
        /// Event Descriptor for this event. 
        /// 
        // 
        // 
        //  
        // 
        //  
        //  
        // 
        //  
        // 
        // 
        // 
        //  
        // 
        //  
        //  
        // 
        //  
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification = "Performance-critical code")]
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
        [System.Security.SecuritySafeCritical]
        public bool WriteEvent(ref EventDescriptorInternal eventDescriptor, params  object[] eventPayload) 
        {
            uint status = 0; 
 
            if (IsEnabled(eventDescriptor.Level, eventDescriptor.Keywords))
            { 
                int argCount = 0;

                unsafe
                { 
                    if ((eventPayload == null)
                        || (eventPayload.Length == 0) 
                        || (eventPayload.Length == 1)) 
                    {
                        string dataString = null; 
                        EventData userData;

                        byte* dataBuffer = stackalloc byte[s_basicTypeAllocationBufferSize]; // Assume a max of 16 chars for non-string argument
 
                        userData.Size = 0;
                        if ((eventPayload != null) && (eventPayload.Length != 0)) 
                        { 
                            //
                            // Figure out the type and fill the data descriptor 
                            //
                            dataString = EncodeObject(ref eventPayload[0], &userData, dataBuffer);
                            argCount = 1;
                        } 

                        if (userData.Size > s_traceEventMaximumSize) 
                        { 
                            //
                            // Maximum size of the event payload plus header is 64k 
                            //
                            s_returnCode = WriteEventErrorCode.EventTooBig;
                            return false;
                        } 

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

                        argCount = eventPayload.Length;
 
                        if (argCount > s_etwMaxMumberArguments)
                        { 
                            // 
                            //too many arguments to log
                            // 
                            throw new ArgumentOutOfRangeException("eventPayload",
                                SRETW.GetString(SRETW.ArgumentOutOfRange_MaxArgExceeded, s_etwMaxMumberArguments));
                        }
 
                        uint totalEventSize = 0;
                        int index; 
                        int stringIndex = 0; 
                        int[] stringPosition = new int[s_etwAPIMaxStringCount];
                        string[] dataString = new string[s_etwAPIMaxStringCount]; 
                        EventData* userData = stackalloc EventData[argCount];
                        EventData* userDataPtr = (EventData*)userData;
                        byte* dataBuffer = stackalloc byte[s_basicTypeAllocationBufferSize * argCount]; // Assume 16 chars for non-string argument
                        byte* currentBuffer = dataBuffer; 

                        // 
                        // The loop below goes through all the arguments and fills in the data 
                        // descriptors. For strings save the location in the dataString array.
                        // Caculates the total size of the event by adding the data descriptor 
                        // size value set in EncodeObjec method.
                        //
                        for (index = 0; index < eventPayload.Length; index++)
                        { 
                            if (eventPayload[index] != null)
                            { 
                                string isString; 
                                isString = EncodeObject(ref eventPayload[index], userDataPtr, currentBuffer);
                                currentBuffer += s_basicTypeAllocationBufferSize; 
                                totalEventSize += userDataPtr->Size;
                                userDataPtr++;
                                if (isString != null)
                                { 
                                    if (stringIndex < s_etwAPIMaxStringCount)
                                    { 
                                        dataString[stringIndex] = isString; 
                                        stringPosition[stringIndex] = index;
                                        stringIndex++; 
                                    }
                                    else
                                    {
                                        throw new ArgumentOutOfRangeException("eventPayload", 
                                            SRETW.GetString(SRETW.ArgumentOutOfRange_MaxStringsExceeded, s_etwAPIMaxStringCount));
                                    } 
                                } 
                            }
                        } 

                        if (totalEventSize > s_traceEventMaximumSize)
                        {
                            s_returnCode = WriteEventErrorCode.EventTooBig; 
                            return false;
                        } 
 
                        //
                        // now fix any string arguments and set the pointer on the data descriptor 
                        //
                        fixed (char* v0 = dataString[0], v1 = dataString[1], v2 = dataString[2], v3 = dataString[3],
                                v4 = dataString[4], v5 = dataString[5], v6 = dataString[6], v7 = dataString[7])
                        { 
                            userDataPtr = (EventData*)userData;
                            if (dataString[0] != null) 
                            { 
                                userDataPtr[stringPosition[0]].Ptr = (ulong)v0;
                            } 
                            if (dataString[1] != null)
                            {
                                userDataPtr[stringPosition[1]].Ptr = (ulong)v1;
                            } 
                            if (dataString[2] != null)
                            { 
                                userDataPtr[stringPosition[2]].Ptr = (ulong)v2; 
                            }
                            if (dataString[3] != null) 
                            {
                                userDataPtr[stringPosition[3]].Ptr = (ulong)v3;
                            }
                            if (dataString[4] != null) 
                            {
                                userDataPtr[stringPosition[4]].Ptr = (ulong)v4; 
                            } 
                            if (dataString[5] != null)
                            { 
                                userDataPtr[stringPosition[5]].Ptr = (ulong)v5;
                            }
                            if (dataString[6] != null)
                            { 
                                userDataPtr[stringPosition[6]].Ptr = (ulong)v6;
                            } 
                            if (dataString[7] != null) 
                            {
                                userDataPtr[stringPosition[7]].Ptr = (ulong)v7; 
                            }

                            status = EventWrite(ref eventDescriptor, (uint)argCount, userData);
                        } 

                    } 
                } 
            }
 
            if (status != 0)
            {
                SetLastError((int)status);
                return false; 
            }
 
            return true; 
        }
 
        /// 
        /// WriteEvent, method to write a string with event schema properties
        /// 
        ///  
        /// Event Descriptor for this event.
        ///  
        ///  
        /// string to log.
        ///  
        // 
        // 
        // 
        //  
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] 
        [System.Security.SecurityCritical] 
        public bool WriteEvent(ref EventDescriptorInternal eventDescriptor, string data)
        { 
            uint status = 0;

            if (data == null)
            { 
                throw new ArgumentNullException("dataString");
            } 
 
            if (IsEnabled(eventDescriptor.Level, eventDescriptor.Keywords))
            { 
                if (data.Length > s_traceEventMaximumStringSize)
                {
                    s_returnCode = WriteEventErrorCode.EventTooBig;
                    return false; 
                }
 
                EventData userData; 

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

                unsafe
                { 
                    fixed (char* pdata = data)
                    { 
                        userData.Ptr = (ulong)pdata; 
                        status = EventWrite(ref eventDescriptor, 1, &userData);
                    } 
                }
            }

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

        /// 
        /// WriteEvent, method to be used by generated code on a derived class 
        /// 
        ///  
        /// Event Descriptor for this event. 
        /// 
        ///  
        /// number of event descriptors
        /// 
        /// 
        /// pointer  do the event data 
        /// 
        //  
        //  
        // 
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")] 
        [System.Security.SecuritySafeCritical]
        internal protected bool WriteEvent(ref EventDescriptorInternal eventDescriptor, int dataCount, IntPtr data)
        {
            uint status = 0; 
            unsafe
            { 
                status = EventWrite(ref eventDescriptor, (uint)dataCount, (EventData*)data); 
            }
            if (status != 0) 
            {
                SetLastError((int)status);
                return false;
            } 
            return true;
        } 
 

        ///  
        /// WriteTransferEvent, method to write a parameters with event schema properties
        /// 
        /// 
        /// Event Descriptor for this event. 
        /// 
        //  
        //  
        // 
        //  
        // 
        // 
        // 
        //  
        // 
        //  
        //  
        // 
        //  
        // 
        // 
        // 
        //  
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference", MessageId = "0#")]
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification = "Performance-critical code")] 
        [System.Security.SecurityCritical] 
        public bool WriteTransferEvent(ref EventDescriptorInternal eventDescriptor, Guid relatedActivityId, params object[] eventPayload)
        { 
            uint status = 0;

            if (IsEnabled(eventDescriptor.Level, eventDescriptor.Keywords))
            { 

                Guid activityId = GetActivityId(); 
 
                unsafe
                { 
                    if ((eventPayload != null) && (eventPayload.Length != 0))
                    {
                        int argCount = eventPayload.Length;
                        if (argCount > s_etwMaxMumberArguments) 
                        {
                            // 
                            //too many arguments to log 
                            //
                            throw new ArgumentOutOfRangeException("eventPayload", 
                                SRETW.GetString(SRETW.ArgumentOutOfRange_MaxArgExceeded, s_etwMaxMumberArguments));
                        }

                        uint totalEventSize = 0; 
                        int index;
                        int stringIndex = 0; 
                        int[] stringPosition = new int[s_etwAPIMaxStringCount]; //used to keep the position of strings in the eventPayload parameter 
                        string[] dataString = new string[s_etwAPIMaxStringCount]; // string arrays from the eventPayload parameter
                        EventData* userData = stackalloc EventData[argCount]; // allocation for the data descriptors 
                        EventData* userDataPtr = (EventData*)userData;
                        byte* dataBuffer = stackalloc byte[s_basicTypeAllocationBufferSize * argCount]; // 16 byte for unboxing non-string argument
                        byte* currentBuffer = dataBuffer;
 
                        //
                        // The loop below goes through all the arguments and fills in the data 
                        // descriptors. For strings save the location in the dataString array. 
                        // Caculates the total size of the event by adding the data descriptor
                        // size value set in EncodeObjec method. 
                        //
                        for (index = 0; index < eventPayload.Length; index++)
                        {
                            if (eventPayload[index] != null) 
                            {
                                string isString; 
                                isString = EncodeObject(ref eventPayload[index], userDataPtr, currentBuffer); 
                                currentBuffer += s_basicTypeAllocationBufferSize;
                                totalEventSize += userDataPtr->Size; 
                                userDataPtr++;
                                if (isString != null)
                                {
                                    if (stringIndex < s_etwAPIMaxStringCount) 
                                    {
                                        dataString[stringIndex] = isString; 
                                        stringPosition[stringIndex] = index; 
                                        stringIndex++;
                                    } 
                                    else
                                    {
                                        throw new ArgumentOutOfRangeException("eventPayload",
                                            SRETW.GetString(SRETW.ArgumentOutOfRange_MaxStringsExceeded, s_etwAPIMaxStringCount)); 
                                    }
                                } 
                            } 
                        }
 
                        if (totalEventSize > s_traceEventMaximumSize)
                        {
                            s_returnCode = WriteEventErrorCode.EventTooBig;
                            return false; 
                        }
 
                        fixed (char* v0 = dataString[0], v1 = dataString[1], v2 = dataString[2], v3 = dataString[3], 
                                v4 = dataString[4], v5 = dataString[5], v6 = dataString[6], v7 = dataString[7])
                        { 
                            userDataPtr = (EventData*)userData;
                            if (dataString[0] != null)
                            {
                                userDataPtr[stringPosition[0]].Ptr = (ulong)v0; 
                            }
                            if (dataString[1] != null) 
                            { 
                                userDataPtr[stringPosition[1]].Ptr = (ulong)v1;
                            } 
                            if (dataString[2] != null)
                            {
                                userDataPtr[stringPosition[2]].Ptr = (ulong)v2;
                            } 
                            if (dataString[3] != null)
                            { 
                                userDataPtr[stringPosition[3]].Ptr = (ulong)v3; 
                            }
                            if (dataString[4] != null) 
                            {
                                userDataPtr[stringPosition[4]].Ptr = (ulong)v4;
                            }
                            if (dataString[5] != null) 
                            {
                                userDataPtr[stringPosition[5]].Ptr = (ulong)v5; 
                            } 
                            if (dataString[6] != null)
                            { 
                                userDataPtr[stringPosition[6]].Ptr = (ulong)v6;
                            }
                            if (dataString[7] != null)
                            { 
                                userDataPtr[stringPosition[7]].Ptr = (ulong)v7;
                            } 
 
                            status = EventWriteTransfer(ref eventDescriptor, ref activityId, ref relatedActivityId, (uint)argCount, userData);
                        } 

                    }
                    else
                    { 
                        status = EventWriteTransfer(ref eventDescriptor, ref activityId, ref relatedActivityId, 0, null);
 
                    } 
                }
            } 

            if (status != 0)
            {
                SetLastError((int)status); 
                return false;
            } 
            return true; 
        }
 
        // 
        // 
        // 
        //  
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference", MessageId = "0#")]
        [System.Security.SecurityCritical] 
        protected bool WriteTransferEvent(ref EventDescriptorInternal eventDescriptor, Guid relatedActivityId, int dataCount, IntPtr data) 
        {
            uint status = 0; 
            Guid activityId = GetActivityId();
            unsafe
            {
                status = EventWriteTransfer( 
                                                ref eventDescriptor,
                                                ref activityId, 
                                                ref relatedActivityId, 
                                                (uint)dataCount,
                                                (EventData*)data); 
            }

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

        // 
        // 
        //  
        //
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "Microsoft.Win32.ManifestEtw.EventActivityIdControl(System.Int32,System.Guid@)")] 
        [System.Security.SecurityCritical] 
        private static Guid GetActivityId()
        { 
            //


 

            Guid id = new Guid(); 
            EventActivityIdControl((int)ActivityControl.EVENT_ACTIVITY_CTRL_GET_ID, ref id); 
            return id;
        } 

        // 
        // 
        //  
        //
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "Microsoft.Win32.ManifestEtw.EventActivityIdControl(System.Int32,System.Guid@)")] 
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference", MessageId = "0#")] 
        [System.Security.SecurityCritical]
        public static void SetActivityId(ref Guid id) 
        {
            EventActivityIdControl((int)ActivityControl.EVENT_ACTIVITY_CTRL_SET_ID, ref id);
        }
 
        // 
        //  
        //  
        //
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "Microsoft.Win32.ManifestEtw.EventActivityIdControl(System.Int32,System.Guid@)")] 
        [System.Security.SecurityCritical]
        public static Guid CreateActivityId()
        {
            Guid newId = new Guid(); 
            EventActivityIdControl((int)ActivityControl.EVENT_ACTIVITY_CTRL_CREATE_ID, ref newId);
            return newId; 
        } 

    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// [....] 
//-----------------------------------------------------------------------------
using System; 
using System.Runtime.InteropServices; 
using System.Runtime.CompilerServices;
using Microsoft.Win32; 
using System.Globalization;
using System.Collections.Generic;
using System.Threading;
using System.Security.Permissions; 
using System.Security;
using System.Diagnostics.CodeAnalysis; 
 
namespace System.Diagnostics.Eventing
{ 
    // New in CLR4.0
    internal enum ControllerCommand
    {
        // Strictly Positive numbers are for provider-specific commands, negative number are for 'shared' commands. 256 
        // The first 256 negative numbers are reserved for the framework.
        Update = 0, 
        SendManifest = -1, 
    };
 
    [System.Security.Permissions.HostProtection(MayLeakOnAbort = true)]
    internal partial class EventProvider : IDisposable
    {
        // This is the windows EVENT_DATA_DESCRIPTOR structure.  We expose it because this is what 
        // subclasses of EventProvider use when creating efficient (but unsafe) version of
        // EventWrite.   We do make it a nested type because we really don't expect anyone to use 
        // it except subclasses (and then only rarely). 
        public struct EventData
        { 
            internal unsafe ulong Ptr;
            internal uint Size;
            internal uint Reserved;
        } 

        [System.Security.SecuritySafeCritical] 
        ManifestEtw.EtwEnableCallback m_etwCallback;     // Trace Callback function 

        private long m_regHandle;                        // Trace Registration Handle 
        private byte m_level;                            // Tracing Level
        private long m_anyKeywordMask;                   // Trace Enable Flags
        private long m_allKeywordMask;                   // Match all keyword
        private int m_enabled;                           // Enabled flag from Trace callback 
        private Guid m_providerId;                       // Control Guid
        private int m_disposed;                          // when 1, provider has unregister 
        private bool m_isClassic;                        // Should we use classic (XP) ETW APIs (more efficient than s_isClassic) 
        private static bool s_isClassic;                 // same as m_isClassic for static APIs.
 
        [ThreadStatic]
        private static WriteEventErrorCode s_returnCode; // The last return code

        private const int s_basicTypeAllocationBufferSize = 16; 
        private const int s_etwMaxMumberArguments = 32;
        private const int s_etwAPIMaxStringCount = 8; 
        private const int s_maxEventDataDescriptors = 128; 
        private const int s_traceEventMaximumSize = 65482;
        private const int s_traceEventMaximumStringSize = 32724; 

        [SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")]
        public enum WriteEventErrorCode : int
        { 
            //check mapping to runtime codes
            NoError = 0, 
            NoFreeBuffers = 1, 
            EventTooBig = 2
        } 

        private enum ActivityControl : uint
        {
            EVENT_ACTIVITY_CTRL_GET_ID = 1, 
            EVENT_ACTIVITY_CTRL_SET_ID = 2,
            EVENT_ACTIVITY_CTRL_CREATE_ID = 3, 
            EVENT_ACTIVITY_CTRL_GET_SET_ID = 4, 
            EVENT_ACTIVITY_CTRL_CREATE_SET_ID = 5
        } 

        // 
        // 
        //  
        /// 
        /// Constructs a new EventProvider.  This causes the class to be registered with the OS an 
        /// if a ETW controller turns on the logging then logging will start. 
        /// 
        /// The GUID that identifies this provider to the system. 
        [System.Security.SecurityCritical]
        [PermissionSet(SecurityAction.Demand, Unrestricted = true)]
        [SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "guid")]
        protected EventProvider(Guid providerGuid) 
        {
            m_providerId = providerGuid; 
            s_isClassic = m_isClassic = true; 
            //
            // Register the ProviderId with ETW 
            //
            Register(providerGuid);
        }
 
        internal EventProvider()
        { 
            s_isClassic = m_isClassic = true; 
        }
 
        /// 
        /// This method registers the controlGuid of this class with ETW.
        /// We need to be running on Vista or above. If not an
        /// PlatformNotSupported exception will be thrown. 
        /// If for some reason the ETW Register call failed
        /// a NotSupported exception will be thrown. 
        ///  
        // 
        //  
        // 
        // 
        // 
        [System.Security.SecurityCritical] 
        internal unsafe void Register(Guid providerGuid)
        { 
            m_providerId = providerGuid; 
            uint status;
            m_etwCallback = new ManifestEtw.EtwEnableCallback(EtwEnableCallBack); 

            status = EventRegister(ref m_providerId, m_etwCallback);
            if (status != 0)
            { 
                throw new ArgumentException(Win32Native.GetMessage(unchecked((int)status)));
            } 
        } 

        // 
        // implement Dispose Pattern to early deregister from ETW insted of waiting for
        // the finalizer to call deregistration.
        // Once the user is done with the provider it needs to call Close() or Dispose()
        // If neither are called the finalizer will unregister the provider anyway 
        //
        public void Dispose() 
        { 
            Dispose(true);
            GC.SuppressFinalize(this); 
        }

        // 
        //  
        // 
        [System.Security.SecuritySafeCritical] 
        protected virtual void Dispose(bool disposing) 
        {
            // 
            // explicit cleanup is done by calling Dispose with true from
            // Dispose() or Close(). The disposing arguement is ignored because there
            // are no unmanaged resources.
            // The finalizer calls Dispose with false. 
            //
 
            // 
            // check if the object has been allready disposed
            // 
            if (m_disposed == 1) return;

            if (Interlocked.Exchange(ref m_disposed, 1) != 0)
            { 
                // somebody is allready disposing the provider
                return; 
            } 

            // 
            // Disables Tracing in the provider, then unregister
            //

            m_enabled = 0; 

            Deregister(); 
        } 

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

        ~EventProvider() 
        {
            Dispose(false);
        }
 
        /// 
        /// This method un-registers from ETW. 
        ///  
        // 
        //  
        // 
        //
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "Microsoft.Win32.ManifestEtw.EventUnregister(System.Int64)"), System.Security.SecurityCritical]
        private unsafe void Deregister() 
        {
            // 
            // Unregister from ETW using the RegHandle saved from 
            // the register call.
            // 

            if (m_regHandle != 0)
            {
                EventUnregister(); 
                m_regHandle = 0;
            } 
        } 

        //  
        // 
        // 
        // 
        [System.Security.SecurityCritical] 
        unsafe void EtwEnableCallBack(
                        [In] ref System.Guid sourceId, 
                        [In] int isEnabled, 
                        [In] byte setLevel,
                        [In] long anyKeyword, 
                        [In] long allKeyword,
                        [In] ManifestEtw.EVENT_FILTER_DESCRIPTOR* filterData,
                        [In] void* callbackContext
                        ) 
        {
            m_enabled = isEnabled; 
            m_level = setLevel; 
            m_anyKeywordMask = anyKeyword;
            m_allKeywordMask = allKeyword; 
            ControllerCommand command = Eventing.ControllerCommand.Update;
            IDictionary args = null;

            byte[] data; 
            int keyIndex;
            if (GetDataFromController(filterData, out command, out data, out keyIndex)) 
            { 
                args = new Dictionary(4);
                while (keyIndex < data.Length) 
                {
                    int keyEnd = FindNull(data, keyIndex);
                    int valueIdx = keyEnd + 1;
                    int valueEnd = FindNull(data, valueIdx); 
                    if (valueEnd < data.Length)
                    { 
                        string key = System.Text.Encoding.UTF8.GetString(data, keyIndex, keyEnd - keyIndex); 
                        string value = System.Text.Encoding.UTF8.GetString(data, valueIdx, valueEnd - valueIdx);
                        args[key] = value; 
                    }
                    keyIndex = valueEnd + 1;
                }
            } 
            OnControllerCommand(command, args);
        } 
 
        // New in CLR4.0
        protected virtual void OnControllerCommand(ControllerCommand command, IDictionary arguments) { } 
        protected EventLevel Level { get { return (EventLevel)m_level; } set { m_level = (byte)value; } }
        protected EventKeywords MatchAnyKeyword { get { return (EventKeywords)m_anyKeywordMask; } set { m_anyKeywordMask = (long)value; } }
        protected EventKeywords MatchAllKeyword { get { return (EventKeywords)m_allKeywordMask; } set { m_allKeywordMask = (long)value; } }
 
        static private int FindNull(byte[] buffer, int idx)
        { 
            while (idx < buffer.Length && buffer[idx] != 0) 
                idx++;
            return idx; 
        }

        /// 
        /// Gets any data to be passed from the controller to the provider.  It starts with what is passed 
        /// into the callback, but unfortunately this data is only present for when the provider is active
        /// at the the time the controller issues the command.  To allow for providers to activate after the 
        /// controller issued a command, we also check the registry and use that to get the data.  The function 
        /// returns an array of bytes representing the data, the index into that byte array where the data
        /// starts, and the command being issued associated with that data. 
        /// 
        [System.Security.SecurityCritical]
        private unsafe bool GetDataFromController(ManifestEtw.EVENT_FILTER_DESCRIPTOR* filterData, out ControllerCommand command, out byte[] data, out int dataStart)
        { 
            data = null;
            if (filterData == null) 
            { 
                string regKey = @"\Microsoft\Windows\CurrentVersion\Winevt\Publishers\{" + m_providerId + "}";
                if (System.Runtime.InteropServices.Marshal.SizeOf(typeof(IntPtr)) == 8) 
                    regKey = @"HKEY_LOCAL_MACHINE\Software" + @"\Wow6432Node" + regKey;
                else
                    regKey = @"HKEY_LOCAL_MACHINE\Software" + regKey;
 

                data = Microsoft.Win32.Registry.GetValue(regKey, "ControllerData", null) as byte[]; 
                if (data != null && data.Length >= 4) 
                {
                    // 
                    command = (ControllerCommand)(((data[3] << 8 + data[2]) << 8 + data[1]) << 8 + data[0]);
                    dataStart = 4;
                    return true;
                } 
            }
            else 
            { 
                if (filterData->Ptr != 0 && 0 < filterData->Size && filterData->Size <= 1024)
                { 
                    data = new byte[filterData->Size];
                    Marshal.Copy((IntPtr)filterData->Ptr, data, 0, data.Length);
                }
                command = (ControllerCommand) filterData->Type; 
                dataStart = 0;
                return true; 
            } 

            dataStart = 0; 
            command = ControllerCommand.Update;
            return false;
        }
 
        /// 
        /// IsEnabled, method used to test if provider is enabled 
        ///  
        public bool IsEnabled()
        { 
            return (m_enabled != 0) ? true : false;
        }

        ///  
        /// IsEnabled, method used to test if event is enabled
        ///  
        ///  
        /// Level  to test
        ///  
        /// 
        /// Keyword  to test
        /// 
        public bool IsEnabled(byte level, long keywords) 
        {
            // 
            // If not enabled at all, return false. 
            //
            if (m_enabled == 0) 
            {
                return false;
            }
 
            // This also covers the case of Level == 0.
            if ((level <= m_level) || 
                (m_level == 0)) 
            {
 
                //
                // Check if Keyword is enabled
                //
 
                if ((keywords == 0) ||
                    (((keywords & m_anyKeywordMask) != 0) && 
                     ((keywords & m_allKeywordMask) == m_allKeywordMask))) 
                {
                    return true; 
                }
            }

            return false; 
        }
 
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")] 
        public static WriteEventErrorCode GetLastWriteEventError()
        { 
            return s_returnCode;
        }

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


        //  
        // 
        //  
        //  
        // 
        //  
        // 
        // 
        // 
        //  
        // 
        //  
        //  
        // 
        //  
        // 
        // 
        // 
        //  
        // 
        [System.Security.SecurityCritical] 
        private static unsafe string EncodeObject(ref object data, EventData* dataDescriptor, byte* dataBuffer) 
        /*++
 
        Routine Description:

           This routine is used by WriteEvent to unbox the object type and
           to fill the passed in ETW data descriptor. 

        Arguments: 
 
           data - argument to be decoded
 
           dataDescriptor - pointer to the descriptor to be filled

           dataBuffer - storage buffer for storing user data, needed because cant get the address of the object
 
        Return Value:
 
           null if the object is a basic type other than string. String otherwise 

        --*/ 
        {
            dataDescriptor->Reserved = 0;

            string sRet = data as string; 
            if (sRet != null)
            { 
                dataDescriptor->Size = (uint)((sRet.Length + 1) * 2); 
                return sRet;
            } 

            if (data is IntPtr)
            {
                dataDescriptor->Size = (uint)sizeof(IntPtr); 
                IntPtr* intptrPtr = (IntPtr*)dataBuffer;
                *intptrPtr = (IntPtr)data; 
                dataDescriptor->Ptr = (ulong)intptrPtr; 
            }
            else if (data is int) 
            {
                dataDescriptor->Size = (uint)sizeof(int);
                int* intptrPtr = (int*)dataBuffer;
                *intptrPtr = (int)data; 
                dataDescriptor->Ptr = (ulong)intptrPtr;
            } 
            else if (data is long) 
            {
                dataDescriptor->Size = (uint)sizeof(long); 
                long* longptr = (long*)dataBuffer;
                *longptr = (long)data;
                dataDescriptor->Ptr = (ulong)longptr;
            } 
            else if (data is uint)
            { 
                dataDescriptor->Size = (uint)sizeof(uint); 
                uint* uintptr = (uint*)dataBuffer;
                *uintptr = (uint)data; 
                dataDescriptor->Ptr = (ulong)uintptr;
            }
            else if (data is UInt64)
            { 
                dataDescriptor->Size = (uint)sizeof(ulong);
                UInt64* ulongptr = (ulong*)dataBuffer; 
                *ulongptr = (ulong)data; 
                dataDescriptor->Ptr = (ulong)ulongptr;
            } 
            else if (data is char)
            {
                dataDescriptor->Size = (uint)sizeof(char);
                char* charptr = (char*)dataBuffer; 
                *charptr = (char)data;
                dataDescriptor->Ptr = (ulong)charptr; 
            } 
            else if (data is byte)
            { 
                dataDescriptor->Size = (uint)sizeof(byte);
                byte* byteptr = (byte*)dataBuffer;
                *byteptr = (byte)data;
                dataDescriptor->Ptr = (ulong)byteptr; 
            }
            else if (data is short) 
            { 
                dataDescriptor->Size = (uint)sizeof(short);
                short* shortptr = (short*)dataBuffer; 
                *shortptr = (short)data;
                dataDescriptor->Ptr = (ulong)shortptr;
            }
            else if (data is sbyte) 
            {
                dataDescriptor->Size = (uint)sizeof(sbyte); 
                sbyte* sbyteptr = (sbyte*)dataBuffer; 
                *sbyteptr = (sbyte)data;
                dataDescriptor->Ptr = (ulong)sbyteptr; 
            }
            else if (data is ushort)
            {
                dataDescriptor->Size = (uint)sizeof(ushort); 
                ushort* ushortptr = (ushort*)dataBuffer;
                *ushortptr = (ushort)data; 
                dataDescriptor->Ptr = (ulong)ushortptr; 
            }
            else if (data is float) 
            {
                dataDescriptor->Size = (uint)sizeof(float);
                float* floatptr = (float*)dataBuffer;
                *floatptr = (float)data; 
                dataDescriptor->Ptr = (ulong)floatptr;
            } 
            else if (data is double) 
            {
                dataDescriptor->Size = (uint)sizeof(double); 
                double* doubleptr = (double*)dataBuffer;
                *doubleptr = (double)data;
                dataDescriptor->Ptr = (ulong)doubleptr;
            } 
            else if (data is bool)
            { 
                dataDescriptor->Size = (uint)sizeof(bool); 
                bool* boolptr = (bool*)dataBuffer;
                *boolptr = (bool)data; 
                dataDescriptor->Ptr = (ulong)boolptr;
            }
            else if (data is Guid)
            { 
                dataDescriptor->Size = (uint)sizeof(Guid);
                Guid* guidptr = (Guid*)dataBuffer; 
                *guidptr = (Guid)data; 
                dataDescriptor->Ptr = (ulong)guidptr;
            } 
            else if (data is decimal)
            {
                dataDescriptor->Size = (uint)sizeof(decimal);
                decimal* decimalptr = (decimal*)dataBuffer; 
                *decimalptr = (decimal)data;
                dataDescriptor->Ptr = (ulong)decimalptr; 
            } 
            else if (data is Boolean)
            { 
                dataDescriptor->Size = (uint)sizeof(Boolean);
                Boolean* booleanptr = (Boolean*)dataBuffer;
                *booleanptr = (Boolean)data;
                dataDescriptor->Ptr = (ulong)booleanptr; 
            }
            else 
            { 
                //To our eyes, everything else is a just a string
                sRet = data.ToString(); 
                dataDescriptor->Size = (uint)((sRet.Length + 1) * 2);
                return sRet;
            }
 
            return null;
        } 
 

        ///  
        /// WriteMessageEvent, method to write a string with level and Keyword
        /// 
        /// 
        /// Level  to test 
        /// 
        ///  
        /// Keyword  to test 
        /// 
        //  
        // 
        // 
        // 
        [System.Security.SecuritySafeCritical] 
        public bool WriteMessageEvent(string eventMessage, byte eventLevel, long eventKeywords)
        { 
            int status = 0; 

            if (eventMessage == null) 
            {
                throw new ArgumentNullException("eventMessage");
            }
 
            if (IsEnabled(eventLevel, eventKeywords))
            { 
                if (eventMessage.Length > s_traceEventMaximumStringSize) 
                {
                    s_returnCode = WriteEventErrorCode.EventTooBig; 
                    return false;
                }
                unsafe
                { 
                    fixed (char* pdata = eventMessage)
                    { 
                        status = (int)EventWriteString(eventLevel, eventKeywords, pdata); 
                    }
 
                    if (status != 0)
                    {
                        SetLastError(status);
                        return false; 
                    }
                } 
            } 
            return true;
        } 

        /// 
        /// WriteMessageEvent, method to write a string with level=0 and Keyword=0
        ///  
        /// 
        /// Message to log 
        ///  
        public bool WriteMessageEvent(string eventMessage)
        { 
            return WriteMessageEvent(eventMessage, 0, 0);
        }

 
        /// 
        /// WriteEvent, method to write a parameters with event schema properties 
        ///  
        /// 
        /// Event Descriptor for this event. 
        /// 
        // 
        // 
        //  
        // 
        //  
        //  
        // 
        //  
        // 
        // 
        // 
        //  
        // 
        //  
        //  
        // 
        //  
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification = "Performance-critical code")]
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
        [System.Security.SecuritySafeCritical]
        public bool WriteEvent(ref EventDescriptorInternal eventDescriptor, params  object[] eventPayload) 
        {
            uint status = 0; 
 
            if (IsEnabled(eventDescriptor.Level, eventDescriptor.Keywords))
            { 
                int argCount = 0;

                unsafe
                { 
                    if ((eventPayload == null)
                        || (eventPayload.Length == 0) 
                        || (eventPayload.Length == 1)) 
                    {
                        string dataString = null; 
                        EventData userData;

                        byte* dataBuffer = stackalloc byte[s_basicTypeAllocationBufferSize]; // Assume a max of 16 chars for non-string argument
 
                        userData.Size = 0;
                        if ((eventPayload != null) && (eventPayload.Length != 0)) 
                        { 
                            //
                            // Figure out the type and fill the data descriptor 
                            //
                            dataString = EncodeObject(ref eventPayload[0], &userData, dataBuffer);
                            argCount = 1;
                        } 

                        if (userData.Size > s_traceEventMaximumSize) 
                        { 
                            //
                            // Maximum size of the event payload plus header is 64k 
                            //
                            s_returnCode = WriteEventErrorCode.EventTooBig;
                            return false;
                        } 

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

                        argCount = eventPayload.Length;
 
                        if (argCount > s_etwMaxMumberArguments)
                        { 
                            // 
                            //too many arguments to log
                            // 
                            throw new ArgumentOutOfRangeException("eventPayload",
                                SRETW.GetString(SRETW.ArgumentOutOfRange_MaxArgExceeded, s_etwMaxMumberArguments));
                        }
 
                        uint totalEventSize = 0;
                        int index; 
                        int stringIndex = 0; 
                        int[] stringPosition = new int[s_etwAPIMaxStringCount];
                        string[] dataString = new string[s_etwAPIMaxStringCount]; 
                        EventData* userData = stackalloc EventData[argCount];
                        EventData* userDataPtr = (EventData*)userData;
                        byte* dataBuffer = stackalloc byte[s_basicTypeAllocationBufferSize * argCount]; // Assume 16 chars for non-string argument
                        byte* currentBuffer = dataBuffer; 

                        // 
                        // The loop below goes through all the arguments and fills in the data 
                        // descriptors. For strings save the location in the dataString array.
                        // Caculates the total size of the event by adding the data descriptor 
                        // size value set in EncodeObjec method.
                        //
                        for (index = 0; index < eventPayload.Length; index++)
                        { 
                            if (eventPayload[index] != null)
                            { 
                                string isString; 
                                isString = EncodeObject(ref eventPayload[index], userDataPtr, currentBuffer);
                                currentBuffer += s_basicTypeAllocationBufferSize; 
                                totalEventSize += userDataPtr->Size;
                                userDataPtr++;
                                if (isString != null)
                                { 
                                    if (stringIndex < s_etwAPIMaxStringCount)
                                    { 
                                        dataString[stringIndex] = isString; 
                                        stringPosition[stringIndex] = index;
                                        stringIndex++; 
                                    }
                                    else
                                    {
                                        throw new ArgumentOutOfRangeException("eventPayload", 
                                            SRETW.GetString(SRETW.ArgumentOutOfRange_MaxStringsExceeded, s_etwAPIMaxStringCount));
                                    } 
                                } 
                            }
                        } 

                        if (totalEventSize > s_traceEventMaximumSize)
                        {
                            s_returnCode = WriteEventErrorCode.EventTooBig; 
                            return false;
                        } 
 
                        //
                        // now fix any string arguments and set the pointer on the data descriptor 
                        //
                        fixed (char* v0 = dataString[0], v1 = dataString[1], v2 = dataString[2], v3 = dataString[3],
                                v4 = dataString[4], v5 = dataString[5], v6 = dataString[6], v7 = dataString[7])
                        { 
                            userDataPtr = (EventData*)userData;
                            if (dataString[0] != null) 
                            { 
                                userDataPtr[stringPosition[0]].Ptr = (ulong)v0;
                            } 
                            if (dataString[1] != null)
                            {
                                userDataPtr[stringPosition[1]].Ptr = (ulong)v1;
                            } 
                            if (dataString[2] != null)
                            { 
                                userDataPtr[stringPosition[2]].Ptr = (ulong)v2; 
                            }
                            if (dataString[3] != null) 
                            {
                                userDataPtr[stringPosition[3]].Ptr = (ulong)v3;
                            }
                            if (dataString[4] != null) 
                            {
                                userDataPtr[stringPosition[4]].Ptr = (ulong)v4; 
                            } 
                            if (dataString[5] != null)
                            { 
                                userDataPtr[stringPosition[5]].Ptr = (ulong)v5;
                            }
                            if (dataString[6] != null)
                            { 
                                userDataPtr[stringPosition[6]].Ptr = (ulong)v6;
                            } 
                            if (dataString[7] != null) 
                            {
                                userDataPtr[stringPosition[7]].Ptr = (ulong)v7; 
                            }

                            status = EventWrite(ref eventDescriptor, (uint)argCount, userData);
                        } 

                    } 
                } 
            }
 
            if (status != 0)
            {
                SetLastError((int)status);
                return false; 
            }
 
            return true; 
        }
 
        /// 
        /// WriteEvent, method to write a string with event schema properties
        /// 
        ///  
        /// Event Descriptor for this event.
        ///  
        ///  
        /// string to log.
        ///  
        // 
        // 
        // 
        //  
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] 
        [System.Security.SecurityCritical] 
        public bool WriteEvent(ref EventDescriptorInternal eventDescriptor, string data)
        { 
            uint status = 0;

            if (data == null)
            { 
                throw new ArgumentNullException("dataString");
            } 
 
            if (IsEnabled(eventDescriptor.Level, eventDescriptor.Keywords))
            { 
                if (data.Length > s_traceEventMaximumStringSize)
                {
                    s_returnCode = WriteEventErrorCode.EventTooBig;
                    return false; 
                }
 
                EventData userData; 

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

                unsafe
                { 
                    fixed (char* pdata = data)
                    { 
                        userData.Ptr = (ulong)pdata; 
                        status = EventWrite(ref eventDescriptor, 1, &userData);
                    } 
                }
            }

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

        /// 
        /// WriteEvent, method to be used by generated code on a derived class 
        /// 
        ///  
        /// Event Descriptor for this event. 
        /// 
        ///  
        /// number of event descriptors
        /// 
        /// 
        /// pointer  do the event data 
        /// 
        //  
        //  
        // 
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")] 
        [System.Security.SecuritySafeCritical]
        internal protected bool WriteEvent(ref EventDescriptorInternal eventDescriptor, int dataCount, IntPtr data)
        {
            uint status = 0; 
            unsafe
            { 
                status = EventWrite(ref eventDescriptor, (uint)dataCount, (EventData*)data); 
            }
            if (status != 0) 
            {
                SetLastError((int)status);
                return false;
            } 
            return true;
        } 
 

        ///  
        /// WriteTransferEvent, method to write a parameters with event schema properties
        /// 
        /// 
        /// Event Descriptor for this event. 
        /// 
        //  
        //  
        // 
        //  
        // 
        // 
        // 
        //  
        // 
        //  
        //  
        // 
        //  
        // 
        // 
        // 
        //  
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference", MessageId = "0#")]
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification = "Performance-critical code")] 
        [System.Security.SecurityCritical] 
        public bool WriteTransferEvent(ref EventDescriptorInternal eventDescriptor, Guid relatedActivityId, params object[] eventPayload)
        { 
            uint status = 0;

            if (IsEnabled(eventDescriptor.Level, eventDescriptor.Keywords))
            { 

                Guid activityId = GetActivityId(); 
 
                unsafe
                { 
                    if ((eventPayload != null) && (eventPayload.Length != 0))
                    {
                        int argCount = eventPayload.Length;
                        if (argCount > s_etwMaxMumberArguments) 
                        {
                            // 
                            //too many arguments to log 
                            //
                            throw new ArgumentOutOfRangeException("eventPayload", 
                                SRETW.GetString(SRETW.ArgumentOutOfRange_MaxArgExceeded, s_etwMaxMumberArguments));
                        }

                        uint totalEventSize = 0; 
                        int index;
                        int stringIndex = 0; 
                        int[] stringPosition = new int[s_etwAPIMaxStringCount]; //used to keep the position of strings in the eventPayload parameter 
                        string[] dataString = new string[s_etwAPIMaxStringCount]; // string arrays from the eventPayload parameter
                        EventData* userData = stackalloc EventData[argCount]; // allocation for the data descriptors 
                        EventData* userDataPtr = (EventData*)userData;
                        byte* dataBuffer = stackalloc byte[s_basicTypeAllocationBufferSize * argCount]; // 16 byte for unboxing non-string argument
                        byte* currentBuffer = dataBuffer;
 
                        //
                        // The loop below goes through all the arguments and fills in the data 
                        // descriptors. For strings save the location in the dataString array. 
                        // Caculates the total size of the event by adding the data descriptor
                        // size value set in EncodeObjec method. 
                        //
                        for (index = 0; index < eventPayload.Length; index++)
                        {
                            if (eventPayload[index] != null) 
                            {
                                string isString; 
                                isString = EncodeObject(ref eventPayload[index], userDataPtr, currentBuffer); 
                                currentBuffer += s_basicTypeAllocationBufferSize;
                                totalEventSize += userDataPtr->Size; 
                                userDataPtr++;
                                if (isString != null)
                                {
                                    if (stringIndex < s_etwAPIMaxStringCount) 
                                    {
                                        dataString[stringIndex] = isString; 
                                        stringPosition[stringIndex] = index; 
                                        stringIndex++;
                                    } 
                                    else
                                    {
                                        throw new ArgumentOutOfRangeException("eventPayload",
                                            SRETW.GetString(SRETW.ArgumentOutOfRange_MaxStringsExceeded, s_etwAPIMaxStringCount)); 
                                    }
                                } 
                            } 
                        }
 
                        if (totalEventSize > s_traceEventMaximumSize)
                        {
                            s_returnCode = WriteEventErrorCode.EventTooBig;
                            return false; 
                        }
 
                        fixed (char* v0 = dataString[0], v1 = dataString[1], v2 = dataString[2], v3 = dataString[3], 
                                v4 = dataString[4], v5 = dataString[5], v6 = dataString[6], v7 = dataString[7])
                        { 
                            userDataPtr = (EventData*)userData;
                            if (dataString[0] != null)
                            {
                                userDataPtr[stringPosition[0]].Ptr = (ulong)v0; 
                            }
                            if (dataString[1] != null) 
                            { 
                                userDataPtr[stringPosition[1]].Ptr = (ulong)v1;
                            } 
                            if (dataString[2] != null)
                            {
                                userDataPtr[stringPosition[2]].Ptr = (ulong)v2;
                            } 
                            if (dataString[3] != null)
                            { 
                                userDataPtr[stringPosition[3]].Ptr = (ulong)v3; 
                            }
                            if (dataString[4] != null) 
                            {
                                userDataPtr[stringPosition[4]].Ptr = (ulong)v4;
                            }
                            if (dataString[5] != null) 
                            {
                                userDataPtr[stringPosition[5]].Ptr = (ulong)v5; 
                            } 
                            if (dataString[6] != null)
                            { 
                                userDataPtr[stringPosition[6]].Ptr = (ulong)v6;
                            }
                            if (dataString[7] != null)
                            { 
                                userDataPtr[stringPosition[7]].Ptr = (ulong)v7;
                            } 
 
                            status = EventWriteTransfer(ref eventDescriptor, ref activityId, ref relatedActivityId, (uint)argCount, userData);
                        } 

                    }
                    else
                    { 
                        status = EventWriteTransfer(ref eventDescriptor, ref activityId, ref relatedActivityId, 0, null);
 
                    } 
                }
            } 

            if (status != 0)
            {
                SetLastError((int)status); 
                return false;
            } 
            return true; 
        }
 
        // 
        // 
        // 
        //  
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference", MessageId = "0#")]
        [System.Security.SecurityCritical] 
        protected bool WriteTransferEvent(ref EventDescriptorInternal eventDescriptor, Guid relatedActivityId, int dataCount, IntPtr data) 
        {
            uint status = 0; 
            Guid activityId = GetActivityId();
            unsafe
            {
                status = EventWriteTransfer( 
                                                ref eventDescriptor,
                                                ref activityId, 
                                                ref relatedActivityId, 
                                                (uint)dataCount,
                                                (EventData*)data); 
            }

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

        // 
        // 
        //  
        //
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "Microsoft.Win32.ManifestEtw.EventActivityIdControl(System.Int32,System.Guid@)")] 
        [System.Security.SecurityCritical] 
        private static Guid GetActivityId()
        { 
            //


 

            Guid id = new Guid(); 
            EventActivityIdControl((int)ActivityControl.EVENT_ACTIVITY_CTRL_GET_ID, ref id); 
            return id;
        } 

        // 
        // 
        //  
        //
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "Microsoft.Win32.ManifestEtw.EventActivityIdControl(System.Int32,System.Guid@)")] 
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference", MessageId = "0#")] 
        [System.Security.SecurityCritical]
        public static void SetActivityId(ref Guid id) 
        {
            EventActivityIdControl((int)ActivityControl.EVENT_ACTIVITY_CTRL_SET_ID, ref id);
        }
 
        // 
        //  
        //  
        //
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "Microsoft.Win32.ManifestEtw.EventActivityIdControl(System.Int32,System.Guid@)")] 
        [System.Security.SecurityCritical]
        public static Guid CreateActivityId()
        {
            Guid newId = new Guid(); 
            EventActivityIdControl((int)ActivityControl.EVENT_ACTIVITY_CTRL_CREATE_ID, ref newId);
            return newId; 
        } 

    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

Link Menu

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