WsatEtwTraceListener.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / TransactionBridge / Microsoft / Transactions / Wsat / Protocol / WsatEtwTraceListener.cs / 1 / WsatEtwTraceListener.cs

                            //------------------------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------------------------
namespace Microsoft.Transactions.Wsat.Protocol
{ 
    using System;
    using System.ServiceModel.Channels; 
    using System.ComponentModel; 
    using System.Diagnostics;
    using System.Globalization; 
    using System.IO;
    using System.Net;
    using System.Runtime.InteropServices;
    using System.Runtime.Remoting.Messaging; 
    using System.Text;
    using System.Threading; 
    using System.Xml; 
    using Microsoft.Win32;
 
    using Microsoft.Transactions.Bridge;
    using Microsoft.Transactions.Wsat.Messaging;
    using System.Security;
    using Microsoft.Win32.SafeHandles; 
    using System.Runtime.ConstrainedExecution;
 
    class WsatEtwTraceListener : TraceListener 
    {
        public WsatEtwTraceListener() 
        {
        }

        protected override void Dispose(bool disposing) 
        {
            try 
            { 
                if (disposing)
                { 
                    this.Close();
                }
            }
            finally 
            {
                base.Dispose(disposing); 
            } 
        }
 
        void TraceInternal(TraceEventCache eventCache, string xmlApplicationData, int eventId, TraceEventType type)
        {
            try
            { 
                EtwTrace.Trace(xmlApplicationData, TraceTypeOf(type), eventId);
            } 
            catch(Win32Exception exception) 
            {
                if (DebugTrace.Warning) 
                {
                    DebugTrace.Trace(TraceLevel.Warning, "Exception thrown from ETW Trace : {0} ", exception.Message );
                }
            } 
        }
 
        public override void TraceEvent(TraceEventCache eventCache, String source, TraceEventType severity, int id, string format, params object[] args) 
        {
            TraceInternal(eventCache, null == args ? format : String.Format(CultureInfo.CurrentCulture, format, args), id, severity); 
        }

        public override void TraceEvent(TraceEventCache eventCache, String source, TraceEventType severity, int id, string message)
        { 
            TraceInternal(eventCache, message, id, severity);
        } 
 
        public override void TraceData(TraceEventCache eventCache, String source, TraceEventType severity, int id, object data)
        { 
            TraceInternal(eventCache, data.ToString(), id, severity);
        }

        public override void TraceData(TraceEventCache eventCache, String source, TraceEventType severity, int id, params object[] data) 
        {
            NotSupported(); 
        } 

        public override void TraceTransfer(TraceEventCache eventCache, String source, int id, string message, Guid relatedActivityId) 
        {
            try
            {
                EtwTrace.TraceTransfer(relatedActivityId); 
            }
            catch(Win32Exception exception) 
            { 
                if (DebugTrace.Warning)
                { 
                    DebugTrace.Trace(TraceLevel.Warning, "Exception thrown from ETW Trace : {0} ", exception.Message );
                }
            }
 
        }
 
        static TraceType TraceTypeOf(TraceEventType type) 
        {
            switch (type) 
            {
                case TraceEventType.Transfer:
                    return TraceType.Transfer;
                case TraceEventType.Start: 
                    return TraceType.Start;
                case TraceEventType.Stop: 
                    return TraceType.Stop; 
                case TraceEventType.Suspend:
                    return TraceType.Suspend; 
                case TraceEventType.Resume:
                    return TraceType.Resume;
                default:
                    return TraceType.Trace; 
            }
        } 
 
        public override void Write(string text)
        { 
            WriteLine(text);
        }

        public override void WriteLine(string text) 
        {
            EtwTrace.Trace(text, TraceType.Trace, 0); 
        } 

        void NotSupported() 
        {
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
        }
    } 

 
    enum EtwStructSizes 
    {
        SizeofMofField = 16, 
        SizeofGuid = 16,
        SizeofEventHeader = 48,
        SizeofBaseEvent = 176,
    } 

    //Attempt to be consistent with generic event types from EvnTrace.h 
    enum TraceType : byte 
    {
        Trace       = 0, 
        Start       = 1,
        Stop        = 2,
        Transfer    = 5,
        Suspend     = 10, 
        Resume      = 11,
    } 
 
    static class EtwTrace
    { 
        static Guid WsatTraceGuid = new Guid("{eb6517d4-090c-48ab-825e-adad366406a2}");
        static Guid WsatProviderGuid = new Guid("7f3fe630-462b-47c5-ab07-67ca84934abd");

        const int MaxSupportedStringSize = 65486; 
        static EtwTraceProvider provider;
        static object syncRoot = new object(); 
 
        internal static EtwTraceProvider Provider
        { 
            get
            {
                if (provider == null)
                { 
                    lock (EtwTrace.syncRoot)
                    { 
                        if (provider == null) 
                        {
                            provider = new EtwTraceProvider(WsatProviderGuid, WsatTraceGuid); 
                        }
                    }
                }
                return provider; 
            }
        } 
 
        internal static void Trace(string xml, TraceType type, int eventId)
        { 
            TraceInternal(EtwTrace.GetActivityId(), xml, type, eventId);
        }

        static Guid GetActivityId() 
        {
            object id = System.Diagnostics.Trace.CorrelationManager.ActivityId; 
            return id == null ? Guid.Empty : (Guid)id; 
        }
 
        static internal unsafe uint TraceTransfer(Guid relatedId)
        {
            return TraceTransfer(GetActivityId(), relatedId);
        } 

        static unsafe uint TraceTransfer(Guid activityId, Guid relatedId) 
        { 
            uint result = unchecked((uint)-1);
 
            if (null != Provider && Provider.ShouldTrace)
            {
                Guid2Event evt = new Guid2Event();
                evt.Header.Guid = WsatTraceGuid; 
                evt.Header.Type = (byte)TraceType.Transfer;
                evt.Header.ClientContext = 0; 
                evt.Header.Flags = WnodeFlags.WnodeFlagTracedGuid; 
                evt.Header.BufferSize = (ushort)EtwStructSizes.SizeofEventHeader + 2 * (ushort)EtwStructSizes.SizeofGuid;
 

                evt.Guid1 = activityId;
                evt.Guid2 = relatedId;
 
                if (null != Provider)
                { 
                    result = provider.Trace((MofEvent*)&evt); 
                }
            } 

            return result;
        }
 
        static unsafe uint TraceInternal(Guid guid, string xml, TraceType type, int eventId)
        { 
            uint result = unchecked((uint)-1); 

            if (null != Provider && Provider.ShouldTrace) 
            {
                int dataLength = (xml.Length + 1) * 2 < MaxSupportedStringSize ? (xml.Length + 1) * 2 : MaxSupportedStringSize;

                Mof3Event evt = new Mof3Event(); 
                evt.Header.Guid = WsatTraceGuid;
                evt.Header.Type = (byte)type; 
                evt.Header.ClientContext = 0; 
                evt.Header.Flags = WnodeFlags.WnodeFlagTracedGuid | WnodeFlags.WnodeFlagUseMofPointer;
                evt.Header.BufferSize = (ushort)EtwStructSizes.SizeofEventHeader + 3 * (ushort)EtwStructSizes.SizeofMofField ; 

                evt.Mof2.Length = (uint)dataLength;

                evt.Mof1.Length = 16; 
                evt.Mof1.Data = (IntPtr)(&guid);
 
                evt.Mof3.Length = sizeof(int); 
                evt.Mof3.Data = (IntPtr)(&eventId);
 
                fixed (char* pdata = xml)
                {
                    evt.Mof2.Data = (IntPtr)pdata;
                    if (null != Provider) 
                    {
                        result = provider.Trace((MofEvent*)&evt); 
                    } 
                }
            } 

            return result;
        }
    } 

    internal unsafe delegate uint EtwTraceCallback([In] uint requestCode, 
                                                   [In] System.IntPtr requestContext, 
                                                   [In] System.IntPtr bufferSize,
                                                   [In] byte* buffer); 

    class EtwTraceProvider
    {
        Guid controlGuid; 
        Guid eventClassGuid;
        EtwTraceCallback etwProc; 
        EtwHandle registrationHandle; 
        UInt64 traceHandle;
 
        internal EtwTraceProvider(Guid controlGuid, Guid eventClassGuid)
        {
            Initialize(controlGuid, eventClassGuid);
        } 

        internal bool ShouldTrace { get { return traceHandle != 0; } } 
 
        internal unsafe uint Trace(MofEvent* evt)
        { 
            return EtwNativeMethods.TraceEvent(traceHandle, (char*)evt);
        }

        unsafe void Initialize(Guid ctlGuid, Guid evtClassGuid) 
        {
            this.controlGuid = ctlGuid; 
            this.eventClassGuid = evtClassGuid; 

            TraceGuidRegistration guidReg = new TraceGuidRegistration(); 

            etwProc = new EtwTraceCallback(EtwNotificationCallback);

            guidReg.Guid = &evtClassGuid; 
            guidReg.RegHandle = null;
 
            this.registrationHandle = EtwHandle.RegisterTraceGuids(etwProc, controlGuid, guidReg); 
        }
 
        unsafe uint EtwNotificationCallback(uint requestCode, System.IntPtr context, System.IntPtr bufferSize, byte* buffer)
        {
            if (null == buffer)
            { 
                //note that the return value will be ignored
                return uint.MaxValue; 
            } 

            if (DebugTrace.Info) 
            {
                DebugTrace.Trace(TraceLevel.Info, "EtwNotificationCallback is called!");
            }
 
            EventTraceHeader* eventBuffer = (EventTraceHeader*)buffer;
 
            switch (requestCode) 
            {
                case RequestCodes.EnableEvents: 
                    this.traceHandle = eventBuffer->HistoricalContext;
                    uint flags = EtwNativeMethods.GetTraceEnableFlags(this.traceHandle);
                    int level = EtwNativeMethods.GetTraceEnableLevel(this.traceHandle);
 
                    if (DebugTrace.Info)
                    { 
                        DebugTrace.Trace(TraceLevel.Info, "EtwNotificationCallback: EnableEvents: Current DiagnosticTrace Level {0}", DiagnosticUtility.Level); 
                        DebugTrace.Trace(TraceLevel.Info, "EtwNotificationCallback: EnableEvents: flags = {0} , level = {1}", flags, level);
                    } 

                    using (Process process = Process.GetCurrentProcess())
                    {
                        if (flags == process.Id && level > 0) 
                        {
                            DiagnosticUtility.Level = LevelFromInt(level); 
                            if (DebugTrace.Info) 
                            {
                                DebugTrace.Trace(TraceLevel.Info, "EtwNotificationCallback: New DiagnosticTrace Level {0}", DiagnosticUtility.Level); 
                            }
                        }
                    }
                    break; 
                case RequestCodes.DisableEvents:
                    this.traceHandle = 0; 
                    if (DebugTrace.Info) 
                    {
                        DebugTrace.Trace(TraceLevel.Info, "EtwNotificationCallback: Disabling Session Handle!!"); 
                    }
                    break;
                default:
                    break; 
            }
 
            return 0; 
        }
 
        SourceLevels LevelFromInt(int level)
        {
            SourceLevels result = SourceLevels.Off;
 
            if(level == 6)
            { 
                result = SourceLevels.Off; 
            }
            else if (level == 5) 
            {
                result = SourceLevels.Verbose;
            }
            else if (level == 4) 
            {
                result = SourceLevels.Information; 
            } 
            else if (level == 3)
            { 
                result = SourceLevels.Warning;
            }
            else if (level == 2)
            { 
                result = SourceLevels.Error;
            } 
            else 
            {
                result = SourceLevels.Critical; 
            }

            return result;
        } 
    }
 
    internal static class RequestCodes 
    {
        internal const int GetAllData = 0;        // Never Used 
        internal const int GetSingleInstance = 1; // Never Used
        internal const int SetSingleInstance = 2; // Never Used
        internal const int SetSingleItem = 3;     // Never Used
        internal const int EnableEvents = 4;      // Enable Tracing 
        internal const int DisableEvents = 5;     // Disable Tracing
        internal const int EnableCollection = 6;  // Never Used 
        internal const int DisableCollection = 7; // Never Used 
        internal const int RegInfo = 8;           // Never Used
        internal const int ExecuteMethod = 9;     // Never Used 
    }

    [StructLayout(LayoutKind.Explicit, Size = 48)]
    internal struct EventTraceHeader 
    {
        [FieldOffset(0)] 
        internal ushort BufferSize; 
        [FieldOffset(4)]
        internal byte Type; 
        [FieldOffset(5)]
        internal byte Level;
        [FieldOffset(6)]
        internal short Version; 
        [FieldOffset(8)]
        internal UInt64 HistoricalContext; 
        [FieldOffset(16)] 
        internal Int64 TimeStamp;
        [FieldOffset(24)] 
        internal System.Guid Guid;
        [FieldOffset(40)]
        internal uint ClientContext;
        [FieldOffset(44)] 
        internal uint Flags;
    } 
 
    [StructLayout(LayoutKind.Explicit, Size = 64)]
    internal struct GuidEvent 
    {
        [FieldOffset(0)]
        internal EventTraceHeader Header;
        [FieldOffset(48)] 
        internal Guid Guid;
    } 
 
    [StructLayout(LayoutKind.Explicit, Size = 80)]
    internal struct Guid2Event 
    {
        [FieldOffset(0)]
        internal EventTraceHeader Header;
        [FieldOffset(48)] 
        internal Guid Guid1;
        [FieldOffset(64)] 
        internal Guid Guid2; 
    }
 
    [StructLayout(LayoutKind.Explicit, Size = 64)]
    internal struct MofEvent
    {
        [FieldOffset(0)] 
        internal EventTraceHeader Header;
        [FieldOffset(48)] 
        internal MofField Mof; 
    }
 
    [StructLayout(LayoutKind.Explicit, Size = 96)]
    internal struct Mof3Event
    {
        [FieldOffset(0)] 
        internal EventTraceHeader Header;
        [FieldOffset(48)] 
        internal MofField Mof1; 
        [FieldOffset(64)]
        internal MofField Mof2; 
        [FieldOffset(80)]
        internal MofField Mof3;
    }
 

    [StructLayout(LayoutKind.Explicit, Size = 16)] 
    internal struct MofField 
    {
        [FieldOffset(0)] 
        internal IntPtr Data;
        [FieldOffset(8)]
        internal uint Length;
        [FieldOffset(12)] 
        internal uint Type;
    } 
 
    [StructLayout(LayoutKind.Sequential)]
    internal struct TraceGuidRegistration 
    {
        internal unsafe Guid* Guid;
        internal unsafe void* RegHandle;
    } 

    internal static class WnodeFlags 
    { 
        internal const uint WnodeFlagTracedGuid = 0x00020000;
        internal const uint WnodeFlagLogWnode = 0x00040000; 
        internal const uint WnodeFlagUseGuidPointer = 0x00080000;
        internal const uint WnodeFlagUseMofPointer = 0x00100000;
        internal const uint WnodeFlagUseNoHeader = 0x00200000;
    } 

    static class EtwNativeMethods 
    { 
        [SuppressUnmanagedCodeSecurity]
        [DllImport("advapi32", ExactSpelling = true, EntryPoint = "GetTraceEnableFlags", CharSet = System.Runtime.InteropServices.CharSet.Unicode)] 
        internal static extern uint GetTraceEnableFlags(UInt64 traceHandle);

        [SuppressUnmanagedCodeSecurity]
        [DllImport("advapi32", ExactSpelling = true, EntryPoint = "GetTraceEnableLevel", CharSet = System.Runtime.InteropServices.CharSet.Unicode)] 
        internal static extern byte GetTraceEnableLevel(UInt64 traceHandle);
 
        [SuppressUnmanagedCodeSecurity] 
        [DllImport("advapi32", ExactSpelling = true, EntryPoint = "TraceEvent", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
        internal static extern unsafe uint TraceEvent(UInt64 traceHandle, char* header); 

        [SuppressUnmanagedCodeSecurity]
        [DllImport("advapi32", ExactSpelling = true, EntryPoint = "RegisterTraceGuidsW", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
        internal static extern unsafe uint RegisterTraceGuids([In]EtwTraceCallback cbFunc, [In]void* context, [In] ref System.Guid controlGuid, [In] uint guidCount, ref TraceGuidRegistration guidReg, [In]string mofImagePath, [In] string mofResourceName, [Out] out UInt64 regHandle); 

        [SuppressUnmanagedCodeSecurity] 
        [DllImport("advapi32", ExactSpelling = true, EntryPoint = "UnregisterTraceGuids", CharSet = System.Runtime.InteropServices.CharSet.Unicode)] 
        internal static extern int UnregisterTraceGuids(UInt64 regHandle);
    } 

    // Can't derive from a 'SafeHandle' class because those types change
    // the size of an IntPtr depending on platform (x86/x64). We
    // need a handle with constant size of UInt64 to model 
    // the size of the handle for ETW. Hence, we have to write our own
    // derivation of CriticalFinalizerObject. 
    internal class EtwHandle : CriticalFinalizerObject 
    {
        UInt64 traceHandle; 

        static unsafe internal EtwHandle RegisterTraceGuids(EtwTraceCallback cbFunc, Guid controlGuid, TraceGuidRegistration registration)
        {
            EtwHandle retval = null; 
            UInt64 handle = 0;
            uint status = EtwNativeMethods.RegisterTraceGuids(cbFunc, 
                                                           null, 
                                                           ref controlGuid,
                                                           1, 
                                                           ref registration,
                                                           null,
                                                           null,
                                                           out handle); 
            if (status != 0)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception((int)status)); 
            }
            else 
            {
                retval = new EtwHandle(handle);
            }
            return retval; 
        }
 
        EtwHandle(UInt64 traceHandle) 
        {
            this.traceHandle = traceHandle; 
        }

        ~EtwHandle()
        { 
#pragma warning suppress 56031 // No need to check return value since we are shutting down
            EtwNativeMethods.UnregisterTraceGuids(this.traceHandle); 
        } 
    }
 

}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

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