WebEvents.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / xsp / System / Web / Management / WebEvents.cs / 1305376 / WebEvents.cs

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

namespace System.Web.Management { 
    using System; 
    using System.Web;
    using System.Diagnostics; 
    using System.Security.Principal;
    using System.Threading;
    using System.Reflection;
    using System.Text; 
    using System.Web.Util;
    using System.Web.Configuration; 
    using System.Configuration.Provider; 
    using System.Collections;
    using System.Collections.Generic; 
    using System.Configuration;
    using System.Security;
    using Debug=System.Web.Util.Debug;
    using System.Web.Hosting; 
    using System.Web.UI;
    using System.Globalization; 
    using System.Runtime.Remoting.Messaging; 
    using System.Security.Permissions;
    using System.Web.Caching; 

    // This enum matches the native one enum WebEventType (in webevent.h).
    internal enum WebEventType : int {
        WEBEVENT_BASE_EVENT = 0, 
        WEBEVENT_MANAGEMENT_EVENT,
        WEBEVENT_APP_LIFETIME_EVENT, 
        WEBEVENT_REQUEST_EVENT, 
        WEBEVENT_HEARTBEAT_EVENT,
        WEBEVENT_BASE_ERROR_EVENT, 
        WEBEVENT_REQUEST_ERROR_EVENT,
        WEBEVENT_ERROR_EVENT,
        WEBEVENT_AUDIT_EVENT,
        WEBEVENT_SUCCESS_AUDIT_EVENT, 
        WEBEVENT_AUTHENTICATION_SUCCESS_AUDIT_EVENT,
        WEBEVENT_FAILURE_AUDIT_EVENT, 
        WEBEVENT_AUTHENTICATION_FAILURE_AUDIT_EVENT, 
        WEBEVENT_VIEWSTATE_FAILURE_AUDIT_EVENT,
    }; 

    internal enum WebEventFieldType : int {
        String = 0,
        Int = 1, 
        Bool = 2,
        Long = 3, 
        Date = 4, 
    }
 
    // Used for marshalling over to IIS Trace
    internal class WebEventFieldData {
        string _name;
        public string Name { 
            get {
                return _name; 
            } 
        }
 
        string _data;
        public string Data {
            get {
                return _data; 
            }
        } 
 
        WebEventFieldType _type;
        public WebEventFieldType Type { 
            get {
                return _type;
            }
        } 

        public WebEventFieldData(string name, string data, WebEventFieldType type) { 
            _name = name; 
            _data = data;
            _type = type; 
        }
    }

 
    // Interface for event provider
    public abstract class WebEventProvider : ProviderBase { 
 
        // methods
        public abstract void ProcessEvent(WebBaseEvent raisedEvent); 
        public abstract void Shutdown();
        public abstract void Flush();

        int _exceptionLogged; 

        internal void LogException(Exception e) { 
            // In order to not overflow the eventlog, we only log one exception per provider instance. 
            if (Interlocked.CompareExchange( ref _exceptionLogged, 1, 0) == 0) {
                // Log all errors in eventlog 
                UnsafeNativeMethods.LogWebeventProviderFailure(
                                        HttpRuntime.AppDomainAppVirtualPath,
                                        Name,
                                        e.ToString()); 
            }
        } 
    } 

    // Interface for custom event evaluator 

    public interface IWebEventCustomEvaluator {
        bool CanFire(WebBaseEvent raisedEvent, RuleFiringRecord record);
    } 

    //////////////// 
    // Events 
    ////////////////
 
    public class WebBaseEvent {
        DateTime        _eventTimeUtc;
        int             _code;
        int             _detailCode; 
        Object          _source;
        string          _message; 
        long            _sequenceNumber; 
        long            _occurrenceNumber;
        Guid            _id  = Guid.Empty; 

        static long                         s_globalSequenceNumber = 0;
        static WebApplicationInformation    s_applicationInfo = new WebApplicationInformation();
        const string                        WEBEVENT_RAISE_IN_PROGRESS = "_WEvtRIP"; 

        // A array that cache the result of eventCode to SystemEventType mapping. 
        static readonly SystemEventType[,]  s_eventCodeToSystemEventTypeMappings = new SystemEventType[WebEventCodes.GetEventArrayDimensionSize(0), 
                                                                  WebEventCodes.GetEventArrayDimensionSize(1)];
 
        // A array that store the # of occurrence per custom event code.
        static readonly long[,]             s_eventCodeOccurrence = new long[WebEventCodes.GetEventArrayDimensionSize(0),
                                                                  WebEventCodes.GetEventArrayDimensionSize(1)];
 
        static Hashtable                    s_customEventCodeOccurrence = new Hashtable();
        #pragma warning disable 0649 
        static ReadWriteSpinLock            s_lockCustomEventCodeOccurrence; 
        #pragma warning restore 0649
 
        static WebBaseEvent() {

            // Initialize the mappings.  We will fill up each entry on demand by calling
            // SystemEventTypeFromEventCode(). 

            for (int i = 0; i < s_eventCodeToSystemEventTypeMappings.GetLength(0); i++) { 
                for (int j = 0; j < s_eventCodeToSystemEventTypeMappings.GetLength(1); j++) { 
                    s_eventCodeToSystemEventTypeMappings[i,j] = SystemEventType.Unknown;
                } 
            }

            for (int i = 0; i < s_eventCodeOccurrence.GetLength(0); i++) {
                for (int j = 0; j < s_eventCodeOccurrence.GetLength(1); j++) { 
                    s_eventCodeOccurrence[i,j] = 0;
                } 
            } 
        }
 
        void Init(string message, Object eventSource, int eventCode, int eventDetailCode) {
            if (eventCode < 0) {
                throw new ArgumentOutOfRangeException("eventCode",
                    SR.GetString(SR.Invalid_eventCode_error)); 
            }
 
            if (eventDetailCode < 0) { 
                throw new ArgumentOutOfRangeException("eventDetailCode",
                    SR.GetString(SR.Invalid_eventDetailCode_error)); 
            }

            _code = eventCode;
            _detailCode = eventDetailCode; 
            _source = eventSource;
            _eventTimeUtc = DateTime.UtcNow; 
            _message = message; 

            // Creation of _id is always delayed until it's needed. 
        }

        // ctors
        internal protected WebBaseEvent(string message, Object eventSource, int eventCode) { 
            Init(message, eventSource, eventCode, WebEventCodes.UndefinedEventDetailCode);
        } 
 
        internal protected WebBaseEvent(string message, Object eventSource, int eventCode, int eventDetailCode) {
            Init(message, eventSource, eventCode, eventDetailCode); 
        }

        internal WebBaseEvent() {
            // For creating dummy event.  See GetSystemDummyEvent() 
        }
 
        internal bool IsSystemEvent { 
            get {
                return (_code < WebEventCodes.WebExtendedBase); 
            }
        }

        // Properties 

        public DateTime EventTime { get { return _eventTimeUtc.ToLocalTime(); } } 
 
        public DateTime EventTimeUtc { get { return _eventTimeUtc; } }
 
        public String Message { get { return _message; } }

        public Object EventSource { get { return _source; } }
 
        public long EventSequence { get { return _sequenceNumber; } }
 
        public long EventOccurrence { get { return _occurrenceNumber; } } 

        public int EventCode { get { return _code; } } 

        public int EventDetailCode { get { return _detailCode; } }

        public Guid EventID { 
            get {
                if (_id == Guid.Empty) { 
                    lock(this) { 
                        if (_id == Guid.Empty) {
                            _id = Guid.NewGuid(); 
                        }
                    }
                }
 
                return _id;
            } 
        } 

        public static WebApplicationInformation ApplicationInformation { 
            get { return s_applicationInfo; }
        }

        virtual internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) { 
            formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_code, EventCode.ToString(CultureInfo.InstalledUICulture)));
            formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_message, Message)); 
            formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_time, EventTime.ToString(CultureInfo.InstalledUICulture))); 
            formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_time_Utc, EventTimeUtc.ToString(CultureInfo.InstalledUICulture)));
            formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_id, EventID.ToString("N", CultureInfo.InstalledUICulture))); 
            formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_sequence, EventSequence.ToString(CultureInfo.InstalledUICulture)));
            formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_occurrence, EventOccurrence.ToString(CultureInfo.InstalledUICulture)));
            formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_detail_code, EventDetailCode.ToString(CultureInfo.InstalledUICulture)));
 
            if (includeAppInfo) {
                formatter.AppendLine(String.Empty); 
                formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_application_information)); 
                formatter.IndentationLevel += 1;
                ApplicationInformation.FormatToString(formatter); 
                formatter.IndentationLevel -= 1;
            }
        }
 

        public override string ToString() { 
            return ToString(true, true); 
        }
 
        public virtual string ToString(bool includeAppInfo, bool includeCustomEventDetails) {
            WebEventFormatter   formatter = new WebEventFormatter();

            FormatToString(formatter, includeAppInfo); 

            if (!IsSystemEvent && includeCustomEventDetails) { 
                formatter.AppendLine(String.Empty); 
                formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_custom_event_details));
                formatter.IndentationLevel += 1; 
                FormatCustomEventDetails(formatter);
                formatter.IndentationLevel -= 1;
            }
 
            return formatter.ToString();
        } 
 
        virtual public void FormatCustomEventDetails(WebEventFormatter formatter) {
        } 

        internal int InferEtwTraceVerbosity() {
            WebEventType type = WebBaseEvent.WebEventTypeFromWebEvent(this);
            switch (type) { 
                case WebEventType.WEBEVENT_VIEWSTATE_FAILURE_AUDIT_EVENT:
                case WebEventType.WEBEVENT_BASE_ERROR_EVENT: 
                case WebEventType.WEBEVENT_REQUEST_ERROR_EVENT: 
                case WebEventType.WEBEVENT_FAILURE_AUDIT_EVENT:
                case WebEventType.WEBEVENT_AUTHENTICATION_FAILURE_AUDIT_EVENT: 
                case WebEventType.WEBEVENT_ERROR_EVENT:
                    return EtwTraceLevel.Warning;
                case WebEventType.WEBEVENT_AUDIT_EVENT:
                case WebEventType.WEBEVENT_SUCCESS_AUDIT_EVENT: 
                case WebEventType.WEBEVENT_AUTHENTICATION_SUCCESS_AUDIT_EVENT:
                    return EtwTraceLevel.Information; 
                case WebEventType.WEBEVENT_BASE_EVENT: 
                case WebEventType.WEBEVENT_MANAGEMENT_EVENT:
                case WebEventType.WEBEVENT_REQUEST_EVENT: 
                default:
                    return EtwTraceLevel.Verbose;
            }
        } 

        internal void DeconstructWebEvent(out int eventType, out int fieldCount, out string[] fieldNames, out int[] fieldTypes, out string[] fieldData) { 
            List fields = new List(); 

            eventType = (int)WebBaseEvent.WebEventTypeFromWebEvent(this); 
            GenerateFieldsForMarshal(fields);
            fieldCount = fields.Count;
            fieldNames = new string[fieldCount];
            fieldData = new string[fieldCount]; 
            fieldTypes = new int[fieldCount];
 
            for (int i = 0; i < fieldCount; ++i) { 
                fieldNames[i] = fields[i].Name;
                fieldData[i] = fields[i].Data; 
                fieldTypes[i] = (int)fields[i].Type;
            }
        }
 
        internal virtual void GenerateFieldsForMarshal(List fields) {
            fields.Add(new WebEventFieldData("EventTime", EventTimeUtc.ToString(), WebEventFieldType.String)); 
            fields.Add(new WebEventFieldData("EventID", EventID.ToString(), WebEventFieldType.String)); 
            fields.Add(new WebEventFieldData("EventMessage", Message, WebEventFieldType.String));
            fields.Add(new WebEventFieldData("ApplicationDomain", WebBaseEvent.ApplicationInformation.ApplicationDomain, WebEventFieldType.String)); 
            fields.Add(new WebEventFieldData("TrustLevel", WebBaseEvent.ApplicationInformation.TrustLevel, WebEventFieldType.String));
            fields.Add(new WebEventFieldData("ApplicationVirtualPath", WebBaseEvent.ApplicationInformation.ApplicationVirtualPath, WebEventFieldType.String));
            fields.Add(new WebEventFieldData("ApplicationPath", WebBaseEvent.ApplicationInformation.ApplicationPath, WebEventFieldType.String));
            fields.Add(new WebEventFieldData("MachineName", WebBaseEvent.ApplicationInformation.MachineName, WebEventFieldType.String)); 
            fields.Add(new WebEventFieldData("EventCode", EventCode.ToString(CultureInfo.InstalledUICulture), WebEventFieldType.Int));
            fields.Add(new WebEventFieldData("EventDetailCode", EventDetailCode.ToString(CultureInfo.InstalledUICulture), WebEventFieldType.Int)); 
            fields.Add(new WebEventFieldData("SequenceNumber", EventSequence.ToString(CultureInfo.InstalledUICulture), WebEventFieldType.Long)); 
            fields.Add(new WebEventFieldData("Occurrence", EventOccurrence.ToString(CultureInfo.InstalledUICulture), WebEventFieldType.Long));
        } 

        internal virtual void PreProcessEventInit() {
        }
 
        static void FindEventCode(Exception e, ref int eventCode, ref int eventDetailsCode, ref Exception eStack) {
            eventDetailsCode = WebEventCodes.UndefinedEventDetailCode; 
 
            if (e is ConfigurationException) {
                eventCode = WebEventCodes.WebErrorConfigurationError; 
            }
            else if (e is HttpRequestValidationException) {
                eventCode = WebEventCodes.RuntimeErrorValidationFailure;
            } 
            else if (e is HttpCompileException) {
                eventCode = WebEventCodes.WebErrorCompilationError; 
            } 
            else if (e is SecurityException) {
                eventCode = WebEventCodes.AuditUnhandledSecurityException; 
            }
            else if (e is UnauthorizedAccessException) {
                eventCode = WebEventCodes.AuditUnhandledAccessException;
            } 
            else  if (e is HttpParseException) {
                eventCode = WebEventCodes.WebErrorParserError; 
            } 
            else if (e is HttpException && e.InnerException is ViewStateException) {
                ViewStateException vse = (ViewStateException)e.InnerException; 
                eventCode = WebEventCodes.AuditInvalidViewStateFailure;
                if (vse._macValidationError) {
                    eventDetailsCode = WebEventCodes.InvalidViewStateMac;
                } 
                else {
                    eventDetailsCode = WebEventCodes.InvalidViewState; 
                } 

                eStack = vse; 
            }
            else if (e is HttpException && ((HttpException)e).WebEventCode != WebEventCodes.UndefinedEventCode) {
                eventCode = ((HttpException)e).WebEventCode;
            } 
            else {
                // We don't know what it is.  Let's see if we can find it out by using the inner exception. 
 
                if (e.InnerException != null) {
                    // We will call FindEventCode recusively to find out if e.InnerException is the real one. 

                    if (eStack == null) {
                        // Set eStack here.  If the recursive call ends up landing in
                        // WebEventCodes.RuntimeErrorUnhandledException, we'll use the original 
                        // inner exception as our final result.
                        eStack = e.InnerException; 
                    } 

                    FindEventCode(e.InnerException, ref eventCode, ref eventDetailsCode, ref eStack); 
                }
                else {
                    // It doesn't have an inner exception.  Just return the generic unhandled-exception
                    eventCode = WebEventCodes.RuntimeErrorUnhandledException; 
                }
            } 
 
            if (eStack == null) {
                eStack = e; 
            }
        }

        static internal void RaiseRuntimeError(Exception e, object source) { 
            Debug.Trace("WebEventRaiseError", "Error Event is raised; type=" + e.GetType().Name);
 
            if (!HealthMonitoringManager.Enabled) { 
                return;
            } 

            try {
                int         eventCode = WebEventCodes.UndefinedEventCode;
                int         eventDetailsCode = WebEventCodes.UndefinedEventDetailCode; 
                HttpContext context = HttpContext.Current;
                Exception   eStack = null; 
 
                if (context != null) {
                    Page    page = context.Handler as Page; 

                    // Errors from Transacted pages can be wrapped by a
                    // HttpException
                    if (page != null && 
                        page.IsTransacted &&
                        e.GetType() == typeof(HttpException) && 
                        e.InnerException != null) { 

                        e = e.InnerException; 
                    }
                }

                FindEventCode(e, ref eventCode, ref eventDetailsCode, ref eStack); 
                WebBaseEvent.RaiseSystemEvent(source, eventCode, eventDetailsCode, eStack);
            } 
            catch { 
            }
        } 

        virtual internal protected void IncrementPerfCounters() {
            PerfCounters.IncrementCounter(AppPerfCounter.EVENTS_TOTAL);
        } 

        class CustomEventCodeOccurrence { 
            internal long    _occurrence; 
        }
 
        internal void IncrementTotalCounters(int index0, int index1) {
            _sequenceNumber = Interlocked.Increment(ref s_globalSequenceNumber);

            if (index0 != -1) { 
                _occurrenceNumber = Interlocked.Increment(ref s_eventCodeOccurrence[index0, index1]);
            } 
            else { 
                CustomEventCodeOccurrence ceco = (CustomEventCodeOccurrence)s_customEventCodeOccurrence[_code];
 
                if (ceco == null) {
                    s_lockCustomEventCodeOccurrence.AcquireWriterLock();
                    try {
                        ceco = (CustomEventCodeOccurrence)s_customEventCodeOccurrence[_code]; 
                        if (ceco == null) {
                            ceco = new CustomEventCodeOccurrence(); 
                            s_customEventCodeOccurrence[_code] = ceco; 
                        }
                    } 
                    finally {
                        s_lockCustomEventCodeOccurrence.ReleaseWriterLock();
                    }
                } 

                _occurrenceNumber = Interlocked.Increment(ref ceco._occurrence); 
            } 
        }
 
        [AspNetHostingPermission(SecurityAction.Demand, Level=AspNetHostingPermissionLevel.Medium)]
        virtual public void Raise() {
            Raise(this);
        } 

        // Internally raised events don't go thru this method.  They go directly to RaiseSystemEvent --> RaiseInternal 
        [AspNetHostingPermission(SecurityAction.Demand, Level=AspNetHostingPermissionLevel.Medium)] 
        static public void Raise(WebBaseEvent eventRaised) {
            if (eventRaised.EventCode < WebEventCodes.WebExtendedBase) { 
                throw new HttpException(SR.GetString(SR.System_eventCode_not_allowed,
                        eventRaised.EventCode.ToString(CultureInfo.CurrentCulture),
                        WebEventCodes.WebExtendedBase.ToString(CultureInfo.CurrentCulture)));
            } 

            if (!HealthMonitoringManager.Enabled) { 
                Debug.Trace( 
                    "WebEventRaiseDetails", "Can't fire event because we are disabled or we can't configure HealthMonManager");
                return; 
            }

            RaiseInternal(eventRaised, null, -1, -1);
        } 

        static internal void RaiseInternal(WebBaseEvent eventRaised, ArrayList firingRuleInfos, int index0, int index1) { 
            bool    preProcessEventInitCalled = false; 
            bool    inProgressSet = false;
            object  o; 
            ProcessImpersonationContext ictx = null;
            HttpContext context = HttpContext.Current;

            Debug.Trace( 
                "WebEventRaiseDetails", "Event is raised; event class = " + eventRaised.GetType().Name);
 
            // Use CallContext to make sure we detect an infinite loop where a provider calls Raise(). 
            o = CallContext.GetData(WEBEVENT_RAISE_IN_PROGRESS);
            if (o != null && (bool)o) { 
                Debug.Trace(
                    "WebEventRaiseDetails", "An event is raised while we're raising an event.  Ignore it.");
                return;
            } 

            eventRaised.IncrementPerfCounters(); 
            eventRaised.IncrementTotalCounters(index0, index1); 

            // Find the list of rules that match this event 
            if (firingRuleInfos == null) {
                HealthMonitoringManager manager = HealthMonitoringManager.Manager();

                Debug.Assert(manager != null, "manager != null"); 

                firingRuleInfos = manager._sectionHelper.FindFiringRuleInfos(eventRaised.GetType(), eventRaised.EventCode); 
            } 

            if (firingRuleInfos.Count == 0) { 
                return;
            }

            try { 
                bool[]  matchingProviderArray = null;
 
                if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Infrastructure) && context != null) 
                    EtwTrace.Trace(EtwTraceType.ETW_TYPE_WEB_EVENT_RAISE_START,
                                   context.WorkerRequest, 
                                   eventRaised.GetType().FullName,
                                   eventRaised.EventCode.ToString(CultureInfo.InstalledUICulture),
                                   eventRaised.EventDetailCode.ToString(CultureInfo.InstalledUICulture),
                                   null); 

                try { 
                    foreach (HealthMonitoringSectionHelper.FiringRuleInfo firingRuleInfo in firingRuleInfos) { 
                        HealthMonitoringSectionHelper.RuleInfo  ruleInfo = firingRuleInfo._ruleInfo;
                        RuleFiringRecord record = ruleInfo._ruleFiringRecord; 

                        // Check if we should fire the event based on its throttling settings
                        if (!record.CheckAndUpdate(eventRaised)) {
                            Debug.Trace("WebEventRaiseDetails", 
                                    "Throttling settings not met; not fired");
                            continue; 
                        } 

                        // It's valid for a rule to have no referenced provider 
                        if (ruleInfo._referencedProvider != null) {
                            if (!preProcessEventInitCalled) {
                                // The event may need to do pre-ProcessEvent initialization
                                eventRaised.PreProcessEventInit(); 
                                preProcessEventInitCalled = true;
                            } 
 
                            // For rule infos that share the same provider, the _indexOfFirstRuleInfoWithSameProvider field
                            // is the index of the first ruleInfo among them.  We use that index in the boolean array 
                            // matchingProviderArray to remember if we've already fired that provider.
                            // This is for the scenario where several rules are pointing to the same provider,
                            // and even if >1 rule actually fire and pass all throttling check,
                            // the provider is stilled fired only once. 
                            if (firingRuleInfo._indexOfFirstRuleInfoWithSameProvider != -1) {
                                if (matchingProviderArray == null) { 
                                    matchingProviderArray = new bool[firingRuleInfos.Count]; 
                                }
 
                                if (matchingProviderArray[firingRuleInfo._indexOfFirstRuleInfoWithSameProvider]) {
                                    Debug.Trace("WebEventRaiseDetails",
                                            "Rule with a matching provider already fired.");
                                    continue; 
                                }
 
                                matchingProviderArray[firingRuleInfo._indexOfFirstRuleInfoWithSameProvider] = true; 
                            }
 
                            if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Infrastructure) && context != null)
                                EtwTrace.Trace(EtwTraceType.ETW_TYPE_WEB_EVENT_DELIVER_START,
                                               context.WorkerRequest,
                                               ruleInfo._ruleSettings.Provider, 
                                               ruleInfo._ruleSettings.Name,
                                               ruleInfo._ruleSettings.EventName, 
                                               null); 

                            // In retail build, ignore errors from provider 
                            try {
                                if (ictx == null) {
                                    ictx = new ProcessImpersonationContext();
                                } 

                                if (!inProgressSet) { 
                                    CallContext.SetData(WEBEVENT_RAISE_IN_PROGRESS, true); 
                                    inProgressSet = true;
                                } 

                                Debug.Trace("WebEventRaiseDetails", "Calling ProcessEvent under " + HttpApplication.GetCurrentWindowsIdentityWithAssert().Name);
                                ruleInfo._referencedProvider.ProcessEvent(eventRaised);
                            } 
                            catch (Exception e) {
                                try { 
                                    ruleInfo._referencedProvider.LogException(e); 
                                }
                                catch { 
                                    // ignore all errors
                                }
                            }
                            finally { 
                                if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Infrastructure) && context != null)
                                    EtwTrace.Trace(EtwTraceType.ETW_TYPE_WEB_EVENT_DELIVER_END, 
                                                   context.WorkerRequest); 
                            }
                        } 
                    }
                }
                finally {
                    // Resume client impersonation 
                    if (ictx != null) {
                        ictx.Undo(); 
                    } 

                    if (inProgressSet) { 
                        CallContext.FreeNamedDataSlot(WEBEVENT_RAISE_IN_PROGRESS);
                    }

                    if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Infrastructure) && context != null) 
                        EtwTrace.Trace(EtwTraceType.ETW_TYPE_WEB_EVENT_RAISE_END,
                                       context.WorkerRequest); 
                } 
            }
            catch { throw; }    // Prevent Exception Filter Security Issue (ASURT 122835) 
        }

        internal static void RaiseSystemEvent(string message, object source, int eventCode, int eventDetailCode, Exception exception) {
            RaiseSystemEventInternal(message, source, eventCode, eventDetailCode, exception, null); 
        }
 
        internal static void RaiseSystemEvent(object source, int eventCode) { 
            RaiseSystemEventInternal(null, source, eventCode, WebEventCodes.UndefinedEventDetailCode, null, null);
        } 

        internal static void RaiseSystemEvent(object source, int eventCode, int eventDetailCode) {
            RaiseSystemEventInternal(null, source, eventCode, eventDetailCode, null, null);
        } 

        internal static void RaiseSystemEvent(object source, int eventCode, int eventDetailCode, Exception exception) { 
            RaiseSystemEventInternal(null, source, eventCode, eventDetailCode, exception, null); 
        }
 
        internal static void RaiseSystemEvent(object source, int eventCode, string nameToAuthenticate) {
            RaiseSystemEventInternal(null, source, eventCode, WebEventCodes.UndefinedEventDetailCode, null, nameToAuthenticate);
        }
 
        [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
        static void RaiseSystemEventInternal(string message, object source, 
                        int eventCode, int eventDetailCode, Exception exception, 
                        string nameToAuthenticate) {
            HealthMonitoringManager manager; 
            ArrayList       firingRuleInfos;
            SystemEventTypeInfo typeInfo;
            SystemEventType     systemEventType;
            int                 index0, index1; 

            Debug.Trace( 
                "WebEventRaiseDetails", "RaiseSystemEventInternal called; eventCode=" + eventCode + "; eventDetailCode=" + eventDetailCode); 

            if (!HealthMonitoringManager.Enabled) { 
                Debug.Trace(
                    "WebEventRaiseDetails", "Can't fire event because we are disabled or we can't configure HealthMonManager");
                return;
            } 

            WebEventCodes.GetEventArrayIndexsFromEventCode(eventCode, out index0, out index1); 
 
            GetSystemEventTypeInfo(eventCode, index0, index1, out typeInfo, out systemEventType);
            if (typeInfo == null) { 
                Debug.Assert(false, "Unexpected system event code = " + eventCode);
                return;
            }
 
            manager = HealthMonitoringManager.Manager();
 
            // Figure out if there is any provider that subscribes to it 
            firingRuleInfos = manager._sectionHelper.FindFiringRuleInfos(typeInfo._type, eventCode);
            if (firingRuleInfos.Count == 0) { 
                // Even if we're not firing it, we still have to increment some global counters
                typeInfo._dummyEvent.IncrementPerfCounters();
                typeInfo._dummyEvent.IncrementTotalCounters(index0, index1);
            } 
            else {
                // We will fire the event 
                WebBaseEvent.RaiseInternal( 
                                NewEventFromSystemEventType(false, systemEventType, message, source, eventCode, eventDetailCode,
                                                        exception, nameToAuthenticate), 
                                firingRuleInfos, index0, index1);
            }
        }
 
        // An enum of all the types of web event we will fire
        enum SystemEventType { 
            Unknown = -1, 
            WebApplicationLifetimeEvent,
            WebHeartbeatEvent, 
            WebRequestEvent,
            WebRequestErrorEvent,
            WebErrorEvent,
            WebAuthenticationSuccessAuditEvent, 
            WebSuccessAuditEvent,
            WebAuthenticationFailureAuditEvent, 
            WebFailureAuditEvent, 
            WebViewStateFailureAuditEvent,
            Last 
        };

        class SystemEventTypeInfo {
            internal WebBaseEvent       _dummyEvent;    // For calling IncrementPerfCounters. See RaiseSystemEventInternal for details. 
            internal Type               _type;
 
            internal SystemEventTypeInfo(WebBaseEvent dummyEvent) { 
                _dummyEvent = dummyEvent;
                _type = dummyEvent.GetType(); 
            }
        };

        // An array to cache the event type info for each system event type 
        static SystemEventTypeInfo[]    s_systemEventTypeInfos = new SystemEventTypeInfo[(int)SystemEventType.Last];
 
        static void GetSystemEventTypeInfo(int eventCode, int index0, int index1, 
                        out SystemEventTypeInfo info, out SystemEventType systemEventType) {
 
            // Figure out what SystemEventType this eventCode maps to.
            // For each eventCode, we store the result in a cache.
            systemEventType = s_eventCodeToSystemEventTypeMappings[index0, index1];
            if (systemEventType == SystemEventType.Unknown) { 
                systemEventType = SystemEventTypeFromEventCode(eventCode);
                s_eventCodeToSystemEventTypeMappings[index0, index1] = systemEventType; 
            } 

            // Based on the systemEventType, we read the SystemEventTypeInfo.  For each 
            // event type, we also cache the info
            info = s_systemEventTypeInfos[(int)systemEventType];
            if (info != null) {
                return; 
            }
 
            info = new SystemEventTypeInfo(CreateDummySystemEvent(systemEventType)); 
            s_systemEventTypeInfos[(int)systemEventType] = info;
        } 

        static SystemEventType SystemEventTypeFromEventCode(int eventCode) {
            if (eventCode >= WebEventCodes.ApplicationCodeBase &&
                eventCode <= WebEventCodes.ApplicationCodeBaseLast) { 
                switch(eventCode) {
                    case WebEventCodes.ApplicationStart: 
                    case WebEventCodes.ApplicationShutdown: 
                    case WebEventCodes.ApplicationCompilationStart:
                    case WebEventCodes.ApplicationCompilationEnd: 
                        return SystemEventType.WebApplicationLifetimeEvent;

                    case WebEventCodes.ApplicationHeartbeat:
                        return SystemEventType.WebHeartbeatEvent; 
                }
            } 
 
            if (eventCode >= WebEventCodes.RequestCodeBase &&
                eventCode <= WebEventCodes.RequestCodeBaseLast) { 
                switch(eventCode) {

                    case WebEventCodes.RequestTransactionComplete:
                    case WebEventCodes.RequestTransactionAbort: 
                        return SystemEventType.WebRequestEvent;
                } 
            } 

            if (eventCode >= WebEventCodes.ErrorCodeBase && 
                eventCode <= WebEventCodes.ErrorCodeBaseLast) {
                switch(eventCode) {
                    case WebEventCodes.RuntimeErrorRequestAbort:
                    case WebEventCodes.RuntimeErrorViewStateFailure: 
                    case WebEventCodes.RuntimeErrorValidationFailure:
                    case WebEventCodes.RuntimeErrorPostTooLarge: 
                    case WebEventCodes.RuntimeErrorUnhandledException: 
                        return SystemEventType.WebRequestErrorEvent;
 
                    case WebEventCodes.WebErrorParserError:
                    case WebEventCodes.WebErrorCompilationError:
                    case WebEventCodes.WebErrorConfigurationError:
                    case WebEventCodes.WebErrorOtherError: 
                    case WebEventCodes.WebErrorPropertyDeserializationError:
                    case WebEventCodes.WebErrorObjectStateFormatterDeserializationError: 
                        return SystemEventType.WebErrorEvent; 
                }
            } 

            if (eventCode >= WebEventCodes.AuditCodeBase &&
                eventCode <= WebEventCodes.AuditCodeBaseLast) {
                switch(eventCode) { 
                    case WebEventCodes.AuditFormsAuthenticationSuccess:
                    case WebEventCodes.AuditMembershipAuthenticationSuccess: 
                        return SystemEventType.WebAuthenticationSuccessAuditEvent; 

                    case WebEventCodes.AuditUrlAuthorizationSuccess: 
                    case WebEventCodes.AuditFileAuthorizationSuccess:
                        return SystemEventType.WebSuccessAuditEvent;

                    case WebEventCodes.AuditFormsAuthenticationFailure: 
                    case WebEventCodes.AuditMembershipAuthenticationFailure:
                        return SystemEventType.WebAuthenticationFailureAuditEvent; 
 
                    case WebEventCodes.AuditUrlAuthorizationFailure:
                    case WebEventCodes.AuditFileAuthorizationFailure: 
                    case WebEventCodes.AuditUnhandledSecurityException:
                    case WebEventCodes.AuditUnhandledAccessException:
                        return SystemEventType.WebFailureAuditEvent;
 
                    case WebEventCodes.AuditInvalidViewStateFailure:
                        return SystemEventType.WebViewStateFailureAuditEvent; 
                } 
            }
 
            if (eventCode >= WebEventCodes.MiscCodeBase &&
                eventCode <= WebEventCodes.MiscCodeBaseLast) {
                switch(eventCode) {
                    case WebEventCodes.WebEventProviderInformation: 
                        Debug.Assert(false, "WebEventProviderInformation shouldn't be used to Raise an event");
                        return SystemEventType.Unknown; 
                } 
            }
 
            return SystemEventType.Unknown;
        }

        static WebBaseEvent CreateDummySystemEvent(SystemEventType systemEventType) { 
            return NewEventFromSystemEventType(true, systemEventType, null,
                        null, 0, 0, null, null); 
        } 

        static WebBaseEvent NewEventFromSystemEventType(bool createDummy, SystemEventType systemEventType, string message, 
                        object source,int eventCode, int eventDetailCode, Exception exception,
                        string nameToAuthenticate) {
            // If createDummy == true, it means we're only creating a dummy event for the sake of using
            // it to call IncrementPerfCounters() 

            if (!createDummy && message == null) { 
                message = WebEventCodes.MessageFromEventCode(eventCode, eventDetailCode); 
            }
 
            // Code view note for the future:
            // If the number of systemEventType increases tremendoulsy, we may need to
            // avoid using switch, and change to use a "factory" to create new event.
 
            switch(systemEventType) {
                case SystemEventType.WebApplicationLifetimeEvent: 
                    return createDummy ? new WebApplicationLifetimeEvent() : new WebApplicationLifetimeEvent(message, source, eventCode, eventDetailCode); 

                case SystemEventType.WebHeartbeatEvent: 
                    return createDummy ? new WebHeartbeatEvent() : new WebHeartbeatEvent(message, eventCode);

                case SystemEventType.WebRequestEvent:
                    return createDummy ? new WebRequestEvent() : new WebRequestEvent(message, source, eventCode, eventDetailCode); 

                case SystemEventType. WebRequestErrorEvent: 
                    return createDummy ? new WebRequestErrorEvent() : new WebRequestErrorEvent(message, source, eventCode, eventDetailCode, exception); 

                case SystemEventType.WebErrorEvent: 
                    return createDummy ? new WebErrorEvent() : new WebErrorEvent(message, source, eventCode, eventDetailCode, exception);

                case SystemEventType.WebAuthenticationSuccessAuditEvent:
                    return createDummy ? new WebAuthenticationSuccessAuditEvent() : new WebAuthenticationSuccessAuditEvent(message, source, eventCode, eventDetailCode, nameToAuthenticate); 

                case SystemEventType.WebSuccessAuditEvent: 
                    return createDummy ? new WebSuccessAuditEvent() : new WebSuccessAuditEvent(message, source, eventCode, eventDetailCode); 

                case SystemEventType.WebAuthenticationFailureAuditEvent: 
                    return createDummy ? new WebAuthenticationFailureAuditEvent() : new WebAuthenticationFailureAuditEvent(message, source, eventCode, eventDetailCode, nameToAuthenticate);

                case SystemEventType.WebFailureAuditEvent:
                    return createDummy ? new WebFailureAuditEvent() : new WebFailureAuditEvent(message, source, eventCode, eventDetailCode); 

                case SystemEventType.WebViewStateFailureAuditEvent: 
                    return createDummy ? new WebViewStateFailureAuditEvent() : new WebViewStateFailureAuditEvent(message, source, eventCode, eventDetailCode, (System.Web.UI.ViewStateException)exception); 

                default: 
                    Debug.Assert(false, "Unexpected event type = " + systemEventType);
                    return null;
            }
        } 

        static string CreateWebEventResourceCacheKey(String key) { 
            return CacheInternal.PrefixWebEventResource + key; 
        }
 
        internal static String FormatResourceStringWithCache(String key) {
            CacheInternal cacheInternal = HttpRuntime.CacheInternal;

            // HealthMonitoring, in some scenarios, can call into the cache hundreds of 
            // times during shutdown, after the cache has been disposed.  To improve
            // shutdown performance, skip the cache when it is disposed. 
            if (cacheInternal.IsDisposed) { 
                return SR.Resources.GetString(key, CultureInfo.InstalledUICulture);
            } 

            string s;

            string cacheKey = CreateWebEventResourceCacheKey(key); 

            s = (string) cacheInternal.Get(cacheKey); 
            if (s != null) { 
                return s;
            } 

            s = SR.Resources.GetString(key, CultureInfo.InstalledUICulture);
            if (s != null) {
                cacheInternal.UtcInsert(cacheKey, s); 
            }
 
            return s; 
        }
 
        internal static String FormatResourceStringWithCache(String key, String arg0) {
            string fmt = FormatResourceStringWithCache(key);
            return(fmt != null) ? String.Format(fmt, arg0) : null;
        } 

        internal static WebEventType WebEventTypeFromWebEvent(WebBaseEvent eventRaised) { 
            // Note: 
            // eventRaised can belong to one of the following classes, or can inherit from one of them.
            // In order to figure out precisely the WebEventType closest to the type of eventRaised, 
            // we will start our comparison from the leaf nodes in the class hierarchy and work our
            // way up.

            // Webevent class hierarchy (with the info contained in each class): 

            /* 
 
            - WebBaseEvent (basic)
                - WebManagementEvent (+ WebProcessInformation) 
                    - WebHeartbeatEvent (+ WebProcessStatistics)
                    - WebApplicationLifetimeEvent
                    - WebRequestEvent (+ WebRequestInformation)
                    - WebBaseErrorEvent (+ Exception) 
                        - WebRequestErrorEvent (+ WebRequestInformation + WebThreadInformation)
                        - WebErrorEvent (+ WebRequestInformation + WebThreadInformation) 
                    - WebAuditEvent (+ WebRequestInformation) 
                        - WebSuccessAuditEvent
                            - WebAuthenticationSuccessAuditEvent (+ NameToAuthenticate) 
                        - WebFailureAuditEvent
                            - WebAuthenticationFailureAuditEvent (+ NameToAuthenticate)
                            - WebViewStateFailureAuditEvent (+ ViewStateException)
            */ 

            // Hierarchy level 5 
 
            if (eventRaised is WebAuthenticationSuccessAuditEvent) {
                return WebEventType.WEBEVENT_AUTHENTICATION_SUCCESS_AUDIT_EVENT; 
            }

            if (eventRaised is WebAuthenticationFailureAuditEvent) {
                return WebEventType.WEBEVENT_AUTHENTICATION_FAILURE_AUDIT_EVENT; 
            }
 
            if (eventRaised is WebViewStateFailureAuditEvent) { 
                return WebEventType.WEBEVENT_VIEWSTATE_FAILURE_AUDIT_EVENT;
            } 

            // Hierarchy level 4

            if (eventRaised is WebRequestErrorEvent) { 
                return WebEventType.WEBEVENT_REQUEST_ERROR_EVENT;
            } 
 
            if (eventRaised is WebErrorEvent) {
                return WebEventType.WEBEVENT_ERROR_EVENT; 
            }

            if (eventRaised is WebSuccessAuditEvent) {
                return WebEventType.WEBEVENT_SUCCESS_AUDIT_EVENT; 
            }
 
            if (eventRaised is WebFailureAuditEvent) { 
                return WebEventType.WEBEVENT_FAILURE_AUDIT_EVENT;
            } 

            // Hierarchy level 3

            if (eventRaised is WebHeartbeatEvent) { 
                return WebEventType.WEBEVENT_HEARTBEAT_EVENT;
            } 
 
            if (eventRaised is WebApplicationLifetimeEvent) {
                return WebEventType.WEBEVENT_APP_LIFETIME_EVENT; 
            }

            if (eventRaised is WebRequestEvent) {
                return WebEventType.WEBEVENT_REQUEST_EVENT; 
            }
 
            if (eventRaised is WebBaseErrorEvent) { 
                return WebEventType.WEBEVENT_BASE_ERROR_EVENT;
            } 

            if (eventRaised is WebAuditEvent) {
                return WebEventType.WEBEVENT_AUDIT_EVENT;
            } 

            // Hierarchy level 2 
 
            if (eventRaised is WebManagementEvent) {
                return WebEventType.WEBEVENT_MANAGEMENT_EVENT; 
            }

            // Hierarchy level 1
 
            return WebEventType.WEBEVENT_BASE_EVENT;
        } 
 
        static internal void RaisePropertyDeserializationWebErrorEvent(SettingsProperty property, object source, Exception exception) {
            if (HttpContext.Current == null) { 
                return;
            }

            WebBaseEvent.RaiseSystemEvent( 
                SR.GetString(SR.Webevent_msg_Property_Deserialization,
                            property.Name, property.SerializeAs.ToString(), property.PropertyType.AssemblyQualifiedName ), 
                source, 
                WebEventCodes.WebErrorPropertyDeserializationError,
                WebEventCodes.UndefinedEventDetailCode, 
                exception);
        }
    }
 
    public class WebEventFormatter {
        int             _level; 
        StringBuilder   _sb; 
        int             _tabSize;
 
        void AddTab() {
            int level = _level;

            while (level > 0) { 
                _sb.Append(' ', _tabSize);
                level--; 
            } 
        }
 
        internal WebEventFormatter() {
            _level = 0;
            _sb = new StringBuilder();
            _tabSize = 4; 
        }
 
        public void AppendLine(string s) { 
            AddTab();
            _sb.Append(s); 
            _sb.Append('\n');
        }

        new public string ToString() { 
            return _sb.ToString();
        } 
 
        public int IndentationLevel {
            get { return _level; } 
            set { _level = Math.Max(value, 0); }
        }

        public int TabSize { 
            get { return _tabSize; }
            set { _tabSize = Math.Max(value, 0); } 
        } 
    }
 
    // This class is a base class for all events that require application and process information.
    //
    // WebManagementEvent is the base class for all our webevent classes (except for WebBaseEvent)
    // Please note that we allow customer to inherit from our webevent classes to make it easier to 
    // create custom webevent that contains useful information.
    // However, WebManagementEvent (and other child events) contains sensitive information (e.g. process id, process account name) 
    // that cannot be obtained unless in full-trust. 
    //
    // In non-fulltrust app, we still want code inside system.web.dll to create these webevents 
    // even if there is user code on the stack (we either assert or call unmanaged code to get those info).
    // So to protect these full-trust information from non-fulltrust app, we InheritanceDemand FullTrust
    // if the customer wants to inherit from WebManagementEvent.
    // 
    // For details, see VSWhidbey 256684.
    // 
    [PermissionSet(SecurityAction.InheritanceDemand, Unrestricted = true)] 
    public class WebManagementEvent : WebBaseEvent {
        static WebProcessInformation        s_processInfo = new WebProcessInformation(); 

        internal protected WebManagementEvent(string message, object eventSource, int eventCode)
            :base(message, eventSource, eventCode) {
        } 

        internal protected WebManagementEvent(string message, object eventSource, int eventCode, int eventDetailCode) 
            :base(message, eventSource, eventCode, eventDetailCode) { 
        }
 
        internal WebManagementEvent() {
            // For creating dummy event.  See GetSystemDummyEvent()
        }
 
        // properties
        public WebProcessInformation ProcessInformation { 
            get { return s_processInfo; } 
        }
 
        internal override void GenerateFieldsForMarshal(List fields) {
            base.GenerateFieldsForMarshal(fields);
            fields.Add(new WebEventFieldData("AccountName", ProcessInformation.AccountName, WebEventFieldType.String));
            fields.Add(new WebEventFieldData("ProcessName", ProcessInformation.ProcessName, WebEventFieldType.String)); 
            fields.Add(new WebEventFieldData("ProcessID", ProcessInformation.ProcessID.ToString(CultureInfo.InstalledUICulture), WebEventFieldType.Int));
        } 
 
        override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) {
            base.FormatToString(formatter, includeAppInfo); 

            formatter.AppendLine(String.Empty);
            formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_process_information));
 
            formatter.IndentationLevel += 1;
            ProcessInformation.FormatToString(formatter); 
            formatter.IndentationLevel -= 1; 
        }
 
    }


    // This event is raised at periodic intervals (default 30 seconds) and provides information 
    // relative to the state of the running appdomin.
 
    public class WebHeartbeatEvent : WebManagementEvent { 
        static WebProcessStatistics    s_procStats = new WebProcessStatistics();
 
        internal protected WebHeartbeatEvent(string message, int eventCode)
            :base(message, null, eventCode)
        {
        } 

        internal WebHeartbeatEvent() { 
            // For creating dummy event.  See GetSystemDummyEvent() 
        }
 

        public WebProcessStatistics ProcessStatistics {get {return s_procStats;}}

        override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) { 
            base.FormatToString(formatter, includeAppInfo);
 
            formatter.AppendLine(String.Empty); 
            formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_process_statistics));
 
            formatter.IndentationLevel += 1;
            s_procStats.FormatToString(formatter);
            formatter.IndentationLevel -= 1;
        } 
    }
 
 
    // This event represents a notable event in the lifetime of an application (app domain)
    // including startup and shutdown events.  When an app domain is terminated, the reason 
    // will be expressed in the Message field (e.g. compilation threshold exceed, Shutdown
    // called explicitly, etc.).

    public class WebApplicationLifetimeEvent : WebManagementEvent { 

        internal protected WebApplicationLifetimeEvent(string message, object eventSource, int eventCode) 
            :base(message, eventSource, eventCode) 
        {
        } 


        internal protected WebApplicationLifetimeEvent(string message, object eventSource, int eventCode, int eventDetailCode)
            :base(message, eventSource, eventCode, eventDetailCode) 
        {
        } 
 
        internal WebApplicationLifetimeEvent() {
            // For creating dummy event.  See GetSystemDummyEvent() 
        }

        static internal int DetailCodeFromShutdownReason(ApplicationShutdownReason reason) {
            switch (reason) { 
            case ApplicationShutdownReason.HostingEnvironment:
                return WebEventCodes.ApplicationShutdownHostingEnvironment; 
 
            case ApplicationShutdownReason.ChangeInGlobalAsax:
                return WebEventCodes.ApplicationShutdownChangeInGlobalAsax; 

            case ApplicationShutdownReason.ConfigurationChange:
                return WebEventCodes.ApplicationShutdownConfigurationChange;
 
            case ApplicationShutdownReason.UnloadAppDomainCalled:
                return WebEventCodes.ApplicationShutdownUnloadAppDomainCalled; 
 
            case ApplicationShutdownReason.ChangeInSecurityPolicyFile:
                return WebEventCodes.ApplicationShutdownChangeInSecurityPolicyFile; 

            case ApplicationShutdownReason.BinDirChangeOrDirectoryRename:
                return WebEventCodes.ApplicationShutdownBinDirChangeOrDirectoryRename;
 
            case ApplicationShutdownReason.BrowsersDirChangeOrDirectoryRename:
                return WebEventCodes.ApplicationShutdownBrowsersDirChangeOrDirectoryRename; 
 
            case ApplicationShutdownReason.CodeDirChangeOrDirectoryRename:
                return WebEventCodes.ApplicationShutdownCodeDirChangeOrDirectoryRename; 

            case ApplicationShutdownReason.ResourcesDirChangeOrDirectoryRename:
                return WebEventCodes.ApplicationShutdownResourcesDirChangeOrDirectoryRename;
 
            case ApplicationShutdownReason.IdleTimeout:
                return WebEventCodes.ApplicationShutdownIdleTimeout; 
 
            case ApplicationShutdownReason.PhysicalApplicationPathChanged:
                return WebEventCodes.ApplicationShutdownPhysicalApplicationPathChanged; 

            case ApplicationShutdownReason.HttpRuntimeClose:
                return WebEventCodes.ApplicationShutdownHttpRuntimeClose;
 
            case ApplicationShutdownReason.InitializationError:
                return WebEventCodes.ApplicationShutdownInitializationError; 
 
            case ApplicationShutdownReason.MaxRecompilationsReached:
                return WebEventCodes.ApplicationShutdownMaxRecompilationsReached; 

            case ApplicationShutdownReason.BuildManagerChange:
                return WebEventCodes.ApplicationShutdownBuildManagerChange;
 
            default:
                return WebEventCodes.ApplicationShutdownUnknown; 
            } 
        }
 
        override internal protected void IncrementPerfCounters() {
            base.IncrementPerfCounters();
            PerfCounters.IncrementCounter(AppPerfCounter.EVENTS_APP);
        } 
    }
 
    // This class serves as a base for non-error events that provide 
    public class WebRequestEvent : WebManagementEvent {
        WebRequestInformation   _requestInfo; 

        override internal void PreProcessEventInit() {
            base.PreProcessEventInit();
            InitRequestInformation(); 
        }
 
        internal protected WebRequestEvent(string message, object eventSource, int eventCode) 
        :base(message, eventSource, eventCode)
        { 
        }

        internal protected WebRequestEvent(string message, object eventSource, int eventCode, int eventDetailCode)
            :base(message, eventSource, eventCode, eventDetailCode) 
        {
        } 
 
        internal WebRequestEvent() {
            // For creating dummy event.  See GetSystemDummyEvent() 
        }

        void InitRequestInformation() {
            if (_requestInfo == null) { 
                _requestInfo = new WebRequestInformation();
            } 
        } 

        public WebRequestInformation RequestInformation { 
            get {
                InitRequestInformation();
                return _requestInfo;
            } 
        }
 
        internal override void GenerateFieldsForMarshal(List fields) { 
            base.GenerateFieldsForMarshal(fields);
            fields.Add(new WebEventFieldData("RequestUrl", RequestInformation.RequestUrl, WebEventFieldType.String)); 
            fields.Add(new WebEventFieldData("RequestPath", RequestInformation.RequestPath, WebEventFieldType.String));
            fields.Add(new WebEventFieldData("UserHostAddress", RequestInformation.UserHostAddress, WebEventFieldType.String));
            fields.Add(new WebEventFieldData("UserName", RequestInformation.Principal.Identity.Name, WebEventFieldType.String));
            fields.Add(new WebEventFieldData("UserAuthenticated", RequestInformation.Principal.Identity.IsAuthenticated.ToString(), WebEventFieldType.Bool)); 
            fields.Add(new WebEventFieldData("UserAuthenticationType", RequestInformation.Principal.Identity.AuthenticationType, WebEventFieldType.String));
            fields.Add(new WebEventFieldData("RequestThreadAccountName", RequestInformation.ThreadAccountName, WebEventFieldType.String)); 
        } 

        override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) { 
            base.FormatToString(formatter, includeAppInfo);

            formatter.AppendLine(String.Empty);
            formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_request_information)); 

            formatter.IndentationLevel += 1; 
            RequestInformation.FormatToString(formatter); 
            formatter.IndentationLevel -= 1;
        } 

        override internal protected void IncrementPerfCounters() {
            base.IncrementPerfCounters();
            PerfCounters.IncrementCounter(AppPerfCounter.EVENTS_WEB_REQ); 
        }
    } 
 
    // This is the base class for all error events.
    public class WebBaseErrorEvent : WebManagementEvent { 
        Exception               _exception;

        void Init(Exception e) {
            _exception = e; 
        }
 
        internal protected WebBaseErrorEvent(string message, object eventSource, int eventCode, Exception e) 
            :base(message, eventSource, eventCode)
        { 
            Init(e);
        }

        internal protected WebBaseErrorEvent(string message, object eventSource, int eventCode, int eventDetailCode, Exception e) 
            :base(message, eventSource, eventCode, eventDetailCode)
        { 
            Init(e); 
        }
 
        internal WebBaseErrorEvent() {
            // For creating dummy event.  See GetSystemDummyEvent()
        }
 
        public Exception ErrorException {
            get { return _exception; } 
        } 

        override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) { 
            base.FormatToString(formatter, includeAppInfo);

            if (_exception == null) {
                return; 
            }
 
            Exception   ex = _exception; 

            // Please note we arbitrary pick a level limit per bug VSWhidbey 143859 
            for (int level = 0;
                  ex != null && level <= 2;
                  ex = ex.InnerException, level++)  {
 
                formatter.AppendLine(String.Empty);
 
                if (level == 0) { 
                    formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_exception_information));
                } 
                else {
                    formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_inner_exception_information, level.ToString(CultureInfo.InstalledUICulture)));
                }
 
                formatter.IndentationLevel += 1;
                formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_exception_type, ex.GetType().ToString())); 
                formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_exception_message, ex.Message)); 
                formatter.IndentationLevel -= 1;
            } 
        }

        internal override void GenerateFieldsForMarshal(List fields) {
            base.GenerateFieldsForMarshal(fields); 
            fields.Add(new WebEventFieldData("ExceptionType", ErrorException.GetType().ToString(), WebEventFieldType.String));
            fields.Add(new WebEventFieldData("ExceptionMessage", ErrorException.Message, WebEventFieldType.String)); 
        } 

        override internal protected void IncrementPerfCounters() { 
            base.IncrementPerfCounters();
            PerfCounters.IncrementCounter(AppPerfCounter.EVENTS_ERROR);
            PerfCounters.IncrementGlobalCounter(GlobalPerfCounter.GLOBAL_EVENTS_ERROR);
        } 
    }
 
    // This class contains information about systemic errors, e.g. things related to 
    // configuration or application code (parser errors, compilation errors).
 
    public class WebErrorEvent : WebBaseErrorEvent {
        WebRequestInformation   _requestInfo;
        WebThreadInformation    _threadInfo;
 
        void Init(Exception e) {
        } 
 
        override internal void PreProcessEventInit() {
            base.PreProcessEventInit(); 
            InitRequestInformation();
            InitThreadInformation();
        }
 
        internal protected WebErrorEvent(string message, object eventSource, int eventCode, Exception exception)
            :base(message, eventSource, eventCode, exception) 
        { 
            Init(exception);
        } 

        internal protected WebErrorEvent(string message, object eventSource, int eventCode, int eventDetailCode, Exception exception)
            :base(message, eventSource, eventCode, eventDetailCode, exception)
        { 
            Init(exception);
        } 
 
        internal WebErrorEvent() {
            // For creating dummy event.  See GetSystemDummyEvent() 
        }

        void InitRequestInformation() {
            if (_requestInfo == null) { 
                _requestInfo = new WebRequestInformation();
            } 
        } 

        public WebRequestInformation RequestInformation { 
            get {
                InitRequestInformation();
                return _requestInfo;
            } 
        }
 
        void InitThreadInformation() { 
            if (_threadInfo == null) {
                _threadInfo = new WebThreadInformation(base.ErrorException); 
            }
        }

        public WebThreadInformation ThreadInformation { 
            get {
                InitThreadInformation(); 
                return _threadInfo; 
            }
        } 

        override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) {
            base.FormatToString(formatter, includeAppInfo);
 
            formatter.AppendLine(String.Empty);
            formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_request_information)); 
 
            formatter.IndentationLevel += 1;
            RequestInformation.FormatToString(formatter); 
            formatter.IndentationLevel -= 1;

            formatter.AppendLine(String.Empty);
            formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_thread_information)); 

            formatter.IndentationLevel += 1; 
            ThreadInformation.FormatToString(formatter); 
            formatter.IndentationLevel -= 1;
        } 

        internal override void GenerateFieldsForMarshal(List fields) {
            base.GenerateFieldsForMarshal(fields);
            fields.Add(new WebEventFieldData("RequestUrl", RequestInformation.RequestUrl, WebEventFieldType.String)); 
            fields.Add(new WebEventFieldData("RequestPath", RequestInformation.RequestPath, WebEventFieldType.String));
            fields.Add(new WebEventFieldData("UserHostAddress", RequestInformation.UserHostAddress, WebEventFieldType.String)); 
            fields.Add(new WebEventFieldData("UserName", RequestInformation.Principal.Identity.Name, WebEventFieldType.String)); 
            fields.Add(new WebEventFieldData("UserAuthenticated", RequestInformation.Principal.Identity.IsAuthenticated.ToString(), WebEventFieldType.Bool));
            fields.Add(new WebEventFieldData("UserAuthenticationType", RequestInformation.Principal.Identity.AuthenticationType, WebEventFieldType.String)); 
            fields.Add(new WebEventFieldData("RequestThreadAccountName", RequestInformation.ThreadAccountName, WebEventFieldType.String));
            fields.Add(new WebEventFieldData("ThreadID", ThreadInformation.ThreadID.ToString(CultureInfo.InstalledUICulture), WebEventFieldType.Int));
            fields.Add(new WebEventFieldData("ThreadAccountName", ThreadInformation.ThreadAccountName, WebEventFieldType.String));
            fields.Add(new WebEventFieldData("StackTrace", ThreadInformation.StackTrace, WebEventFieldType.String)); 
            fields.Add(new WebEventFieldData("IsImpersonating", ThreadInformation.IsImpersonating.ToString(), WebEventFieldType.Bool));
        } 
 
        override internal protected void IncrementPerfCounters() {
            base.IncrementPerfCounters(); 
            PerfCounters.IncrementCounter(AppPerfCounter.EVENTS_HTTP_INFRA_ERROR);
            PerfCounters.IncrementGlobalCounter(GlobalPerfCounter.GLOBAL_EVENTS_HTTP_INFRA_ERROR);
        }
    } 

    // This class provides information about errors that occur while servicing a request. 
    // This include unhandled exceptions, viewstate errors, input validation errors, etc. 
    public class WebRequestErrorEvent : WebBaseErrorEvent {
        WebRequestInformation   _requestInfo; 
        WebThreadInformation    _threadInfo;

        void Init(Exception e) {
        } 

        override internal void PreProcessEventInit() { 
            base.PreProcessEventInit(); 
            InitRequestInformation();
            InitThreadInformation(); 
        }

        internal protected WebRequestErrorEvent(string message, object eventSource, int eventCode, Exception exception)
            :base(message, eventSource, eventCode, exception) 
        {
            Init(exception); 
        } 

        internal protected WebRequestErrorEvent(string message, object eventSource, int eventCode, int eventDetailCode, Exception exception) 
            :base(message, eventSource, eventCode, eventDetailCode, exception)
        {
            Init(exception);
        } 

        internal WebRequestErrorEvent() { 
            // For creating dummy event.  See GetSystemDummyEvent() 
        }
 
        // properties

        void InitRequestInformation() {
            if (_requestInfo == null) { 
                _requestInfo = new WebRequestInformation();
            } 
        } 

        public WebRequestInformation RequestInformation { 
            get {
                InitRequestInformation();
                return _requestInfo;
            } 
        }
 
        void InitThreadInformation() { 
            if (_threadInfo == null) {
                _threadInfo = new WebThreadInformation(base.ErrorException); 
            }
        }

        public WebThreadInformation ThreadInformation { 
            get {
                InitThreadInformation(); 
                return _threadInfo; 
            }
        } 

        override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) {
            base.FormatToString(formatter, includeAppInfo);
 
            formatter.AppendLine(String.Empty);
            formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_request_information)); 
 
            formatter.IndentationLevel += 1;
            RequestInformation.FormatToString(formatter); 
            formatter.IndentationLevel -= 1;

            formatter.AppendLine(String.Empty);
            formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_thread_information)); 

            formatter.IndentationLevel += 1; 
            ThreadInformation.FormatToString(formatter); 
            formatter.IndentationLevel -= 1;
        } 

        internal override void GenerateFieldsForMarshal(List fields) {
            base.GenerateFieldsForMarshal(fields);
            fields.Add(new WebEventFieldData("RequestUrl", RequestInformation.RequestUrl, WebEventFieldType.String)); 
            fields.Add(new WebEventFieldData("RequestPath", RequestInformation.RequestPath, WebEventFieldType.String));
            fields.Add(new WebEventFieldData("UserHostAddress", RequestInformation.UserHostAddress, WebEventFieldType.String)); 
            fields.Add(new WebEventFieldData("UserName", RequestInformation.Principal.Identity.Name, WebEventFieldType.String)); 
            fields.Add(new WebEventFieldData("UserAuthenticated", RequestInformation.Principal.Identity.IsAuthenticated.ToString(), WebEventFieldType.Bool));
            fields.Add(new WebEventFieldData("UserAuthenticationType", RequestInformation.Principal.Identity.AuthenticationType, WebEventFieldType.String)); 
            fields.Add(new WebEventFieldData("RequestThreadAccountName", RequestInformation.ThreadAccountName, WebEventFieldType.String));
            fields.Add(new WebEventFieldData("ThreadID", ThreadInformation.ThreadID.ToString(CultureInfo.InstalledUICulture), WebEventFieldType.Int));
            fields.Add(new WebEventFieldData("ThreadAccountName", ThreadInformation.ThreadAccountName, WebEventFieldType.String));
            fields.Add(new WebEventFieldData("StackTrace", ThreadInformation.StackTrace, WebEventFieldType.String)); 
            fields.Add(new WebEventFieldData("IsImpersonating", ThreadInformation.IsImpersonating.ToString(), WebEventFieldType.Bool));
        } 
 
        override internal protected void IncrementPerfCounters() {
            base.IncrementPerfCounters(); 
            PerfCounters.IncrementCounter(AppPerfCounter.EVENTS_HTTP_REQ_ERROR);
            PerfCounters.IncrementGlobalCounter(GlobalPerfCounter.GLOBAL_EVENTS_HTTP_REQ_ERROR);
        }
    } 

 
    // The base class for all audit events. 

    public class WebAuditEvent : WebManagementEvent { 
        WebRequestInformation   _requestInfo;

        override internal void PreProcessEventInit() {
            base.PreProcessEventInit(); 
            InitRequestInformation();
        } 
 
        internal protected WebAuditEvent(string message, object eventSource, int eventCode)
            :base(message, eventSource, eventCode) 
        {
        }

        internal protected WebAuditEvent(string message, object eventSource, int eventCode, int eventDetailCode) 
            :base(message, eventSource, eventCode, eventDetailCode)
        { 
        } 

        internal WebAuditEvent() { 
            // For creating dummy event.  See GetSystemDummyEvent()
        }

        void InitRequestInformation() { 
            if (_requestInfo == null) {
                _requestInfo = new WebRequestInformation(); 
            } 
        }
 
        public WebRequestInformation RequestInformation {
            get {
                InitRequestInformation();
                return _requestInfo; 
            }
        } 
 
        internal override void GenerateFieldsForMarshal(List fields) {
            base.GenerateFieldsForMarshal(fields); 
            fields.Add(new WebEventFieldData("RequestUrl", RequestInformation.RequestUrl, WebEventFieldType.String));
            fields.Add(new WebEventFieldData("RequestPath", RequestInformation.RequestPath, WebEventFieldType.String));
            fields.Add(new WebEventFieldData("UserHostAddress", RequestInformation.UserHostAddress, WebEventFieldType.String));
            fields.Add(new WebEventFieldData("UserName", RequestInformation.Principal.Identity.Name, WebEventFieldType.String)); 
            fields.Add(new WebEventFieldData("UserAuthenticated", RequestInformation.Principal.Identity.IsAuthenticated.ToString(), WebEventFieldType.Bool));
            fields.Add(new WebEventFieldData("UserAuthenticationType", RequestInformation.Principal.Identity.AuthenticationType, WebEventFieldType.String)); 
            fields.Add(new WebEventFieldData("RequestThreadAccountName", RequestInformation.ThreadAccountName, WebEventFieldType.String)); 
        }
 
        override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) {
            base.FormatToString(formatter, includeAppInfo);

            formatter.AppendLine(String.Empty); 
            formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_request_information));
 
            formatter.IndentationLevel += 1; 
            RequestInformation.FormatToString(formatter);
            formatter.IndentationLevel -= 1; 
        }
    }

 
    // This class provides information about all failure audits.  In most cases,
    // applications will only want to enable failure audits. 
 
    public class WebFailureAuditEvent : WebAuditEvent {
        internal protected WebFailureAuditEvent(string message, object eventSource, int eventCode) 
            :base(message, eventSource, eventCode)
        {
        }
 
        internal protected WebFailureAuditEvent(string message, object eventSource, int eventCode, int eventDetailCode)
            :base(message, eventSource, eventCode, eventDetailCode) 
        { 
        }
 
        internal WebFailureAuditEvent() {
            // For creating dummy event.  See GetSystemDummyEvent()
        }
 
        override internal protected void IncrementPerfCounters() {
            base.IncrementPerfCounters(); 
            PerfCounters.IncrementCounter(AppPerfCounter.AUDIT_FAIL); 
            PerfCounters.IncrementGlobalCounter(GlobalPerfCounter.GLOBAL_AUDIT_FAIL);
        } 
    }

    public class WebAuthenticationFailureAuditEvent : WebFailureAuditEvent {
 
        string  _nameToAuthenticate;
 
        void Init(string name) { 
            _nameToAuthenticate = name;
        } 

        internal protected WebAuthenticationFailureAuditEvent(string message, object eventSource, int eventCode, string nameToAuthenticate)
            :base(message, eventSource, eventCode)
        { 
            Init(nameToAuthenticate);
        } 
 

        internal protected WebAuthenticationFailureAuditEvent(string message, object eventSource, int eventCode, int eventDetailCode, string nameToAuthenticate) 
            :base(message, eventSource, eventCode, eventDetailCode)
        {
            Init(nameToAuthenticate);
        } 

        internal WebAuthenticationFailureAuditEvent() { 
            // For creating dummy event.  See GetSystemDummyEvent() 
        }
 
        public string NameToAuthenticate {
            get { return _nameToAuthenticate; }
        }
 
        internal override void GenerateFieldsForMarshal(List fields) {
            base.GenerateFieldsForMarshal(fields); 
            fields.Add(new WebEventFieldData("NameToAuthenticate", NameToAuthenticate, WebEventFieldType.String)); 
        }
 
        override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) {
            base.FormatToString(formatter, includeAppInfo);

            formatter.AppendLine(String.Empty); 
            formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_name_to_authenticate, _nameToAuthenticate));
 
        } 
    }
 
    public class WebViewStateFailureAuditEvent : WebFailureAuditEvent {

        ViewStateException  _viewStateException;
 
        internal protected WebViewStateFailureAuditEvent(string message, object eventSource, int eventCode, ViewStateException viewStateException)
            :base(message, eventSource, eventCode) 
        { 
            _viewStateException = viewStateException;
        } 


        internal protected WebViewStateFailureAuditEvent(string message, object eventSource, int eventCode, int eventDetailCode, ViewStateException viewStateException)
            :base(message, eventSource, eventCode, eventDetailCode) 
        {
            _viewStateException = viewStateException; 
        } 

        internal WebViewStateFailureAuditEvent() { 
            // For creating dummy event.  See GetSystemDummyEvent()
        }

        public ViewStateException ViewStateException { 
            get { return _viewStateException; }
        } 
 
        internal override void GenerateFieldsForMarshal(List fields) {
            base.GenerateFieldsForMarshal(fields); 
            fields.Add(new WebEventFieldData("ViewStateExceptionMessage", ViewStateException.Message, WebEventFieldType.String));
            fields.Add(new WebEventFieldData("RemoteAddress", ViewStateException.RemoteAddress, WebEventFieldType.String));
            fields.Add(new WebEventFieldData("RemotePort", ViewStateException.RemotePort, WebEventFieldType.String));
            fields.Add(new WebEventFieldData("UserAgent", ViewStateException.UserAgent, WebEventFieldType.String)); 
            fields.Add(new WebEventFieldData("PersistedState", ViewStateException.PersistedState, WebEventFieldType.String));
            fields.Add(new WebEventFieldData("Path", ViewStateException.Path, WebEventFieldType.String)); 
            fields.Add(new WebEventFieldData("Referer", ViewStateException.Referer, WebEventFieldType.String)); 
        }
 
        override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) {
            base.FormatToString(formatter, includeAppInfo);

            formatter.AppendLine(String.Empty); 
            formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_ViewStateException_information));
            formatter.IndentationLevel += 1; 
            formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_exception_message, _viewStateException.Message)); 

            formatter.IndentationLevel -= 1; 
        }

    }
 

    // This class provides information about all success audits.  In most cases, 
    // applications will only want to enable failure audits. 

    public class WebSuccessAuditEvent : WebAuditEvent { 
        internal protected WebSuccessAuditEvent(string message, object eventSource, int eventCode)
            :base(message, eventSource, eventCode)
        {
        } 

        internal protected WebSuccessAuditEvent(string message, object eventSource, int eventCode, int eventDetailCode) 
            :base(message, eventSource, eventCode, eventDetailCode) 
        {
        } 

        internal WebSuccessAuditEvent() {
            // For creating dummy event.  See GetSystemDummyEvent()
        } 

        override internal protected void IncrementPerfCounters() { 
            base.IncrementPerfCounters(); 
            PerfCounters.IncrementCounter(AppPerfCounter.AUDIT_SUCCESS);
            PerfCounters.IncrementGlobalCounter(GlobalPerfCounter.GLOBAL_AUDIT_SUCCESS); 
        }
    }

    public class WebAuthenticationSuccessAuditEvent : WebSuccessAuditEvent { 

        string  _nameToAuthenticate; 
 
        void Init(string name) {
            _nameToAuthenticate = name; 
        }

        internal protected WebAuthenticationSuccessAuditEvent(string message, object eventSource, int eventCode, string nameToAuthenticate)
            :base(message, eventSource, eventCode) 
        {
            Init(nameToAuthenticate); 
        } 

        internal protected WebAuthenticationSuccessAuditEvent(string message, object eventSource, int eventCode, int eventDetailCode, string nameToAuthenticate) 
            :base(message, eventSource, eventCode, eventDetailCode)
        {
            Init(nameToAuthenticate);
        } 

        internal WebAuthenticationSuccessAuditEvent() { 
            // For creating dummy event.  See GetSystemDummyEvent() 
        }
 
        public string NameToAuthenticate {
            get { return _nameToAuthenticate; }
        }
 
        internal override void GenerateFieldsForMarshal(List fields) {
            base.GenerateFieldsForMarshal(fields); 
            fields.Add(new WebEventFieldData("NameToAuthenticate", NameToAuthenticate, WebEventFieldType.String)); 
        }
 
        override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) {
            base.FormatToString(formatter, includeAppInfo);

            formatter.AppendLine(String.Empty); 
            formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_name_to_authenticate, _nameToAuthenticate));
        } 
    } 

 
    ////////////////
    // Information
    ////////////////
 
    public sealed class WebProcessInformation {
        // The information is per worker process instance. 
 
        int     _processId;
        string  _processName; 
        string  _accountName;

        internal WebProcessInformation() {
            // Can't use Process.ProcessName because it requires the running 
            // account to be part of the Performance Monitor Users group.
            StringBuilder buf = new StringBuilder(256); 
            if (UnsafeNativeMethods.GetModuleFileName(IntPtr.Zero, buf, 256) == 0) { 
                _processName = String.Empty;
            } 
            else {
                int lastIndex;

                _processName = buf.ToString(); 
                lastIndex = _processName.LastIndexOf('\\');
                if (lastIndex != -1) { 
                    _processName = _processName.Substring(lastIndex + 1); 
                }
            } 

            _processId = SafeNativeMethods.GetCurrentProcessId() ;
            _accountName = HttpRuntime.WpUserId;
        } 

        public int ProcessID { get { return _processId; } } 
 
        public string ProcessName { get { return _processName; } }
 
        public string AccountName { get { return (_accountName != null ? _accountName : String.Empty); } }

        public void FormatToString(WebEventFormatter formatter) {
            formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_process_id, ProcessID.ToString(CultureInfo.InstalledUICulture))); 
            formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_process_name, ProcessName));
            formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_account_name, AccountName)); 
        } 
    }
 
    public sealed class WebApplicationInformation {
        // The information is per appdomain.

        string  _appDomain; 
        string  _trustLevel;
        string  _appUrl; 
        string  _appPath; 
        string  _machineName;
 
        internal WebApplicationInformation() {
            _appDomain = Thread.GetDomain().FriendlyName;
            _trustLevel = HttpRuntime.TrustLevel;
            _appUrl = HttpRuntime.AppDomainAppVirtualPath; 

            try { 
                // We will get an exception if it's a non-ASP.NET app. 
                _appPath = HttpRuntime.AppDomainAppPathInternal;
            } 
            catch {
                _appPath = null;
            }
#if FEATURE_PAL // FEATURE_PAL does not fully implement Environment.MachineName 
            _machineName = "dummymachinename";
#else // FEATURE_PAL 
            _machineName = GetMachineNameWithAssert(); 
#endif // FEATURE_PAL
        } 

        public string ApplicationDomain { get { return _appDomain; } }

        public string TrustLevel { get { return _trustLevel; } } 

        public string ApplicationVirtualPath { get { return _appUrl; } } 
 
        public string ApplicationPath { get { return _appPath; } }
 
        public string MachineName { get { return _machineName; } }

        public void FormatToString(WebEventFormatter formatter) {
            formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_application_domain, ApplicationDomain)); 
            formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_trust_level, TrustLevel));
            formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_application_virtual_path, ApplicationVirtualPath)); 
            formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_application_path, ApplicationPath)); 
            formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_machine_name, MachineName));
        } 

        [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
        private string GetMachineNameWithAssert() {
            return Environment.MachineName; 
        }
 
        public override string ToString() { 
            WebEventFormatter formatter = new WebEventFormatter();
 
            FormatToString(formatter);
            return formatter.ToString();
        }
    } 

    public sealed class WebRequestInformation { 
 
        string      _requestUrl;
        string      _requestPath; 
        IPrincipal  _iprincipal;
        string      _userHostAddress = null;
        string      _accountName;
 
        internal    WebRequestInformation() {
            // Need to Assert() in order to get request information regardless of trust level. See VSWhidbey 416733 
            InternalSecurityPermissions.ControlPrincipal.Assert(); 

            HttpContext context = HttpContext.Current; 
            HttpRequest request = null;

            if (context != null) {
                bool hideRequestResponseOriginal = context.HideRequestResponse; 
                context.HideRequestResponse = false;
                request = context.Request; 
                context.HideRequestResponse = hideRequestResponseOriginal; 

                _iprincipal = context.User; 
            } else {
                _iprincipal = null;
            }
 
            if (request == null) {
                _requestUrl = String.Empty; 
                _requestPath = String.Empty; 
                _userHostAddress = String.Empty;
            } 
            else {
                _requestUrl = request.UrlInternal;
                _requestPath = request.Path;
                _userHostAddress = request.UserHostAddress; 
            }
            _accountName = WindowsIdentity.GetCurrent().Name; 
        } 

        // The information is per request. 

        public string RequestUrl {get {return _requestUrl;}}

        public string RequestPath {get {return _requestPath;}} 

        public IPrincipal Principal {get {return _iprincipal;}} 
 
        public string UserHostAddress { get { return _userHostAddress;} }
 
        public string ThreadAccountName {get {return _accountName;}}

        public void FormatToString(WebEventFormatter formatter) {
            string      user; 
            string      authType;
            bool        authed; 
 
            if (Principal == null) {
                user = String.Empty; 
                authType = String.Empty;
                authed = false;
            }
            else { 
                IIdentity    id = Principal.Identity;
 
                user = id.Name; 
                authed = id.IsAuthenticated;
                authType = id.AuthenticationType; 
            }

            formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_request_url, RequestUrl));
            formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_request_path, RequestPath)); 
            formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_user_host_address, UserHostAddress));
            formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_user, user)); 
 
            if (authed) {
                formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_is_authenticated)); 
            }
            else {
                formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_is_not_authenticated));
            } 
            formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_authentication_type, authType));
            formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_thread_account_name, ThreadAccountName)); 
 
        }
    } 


    // Note that even all the information contained in WebProcessStatistics is obtained from static variables,
    // but we still don't want this class to be static. 
    //
    // Currently, WebProcessStatistics can be obtained only thru WebHeartbeatEvent, which in turn can be 
    // created only by Full-trust app thru class inheritance. (System.Web.dll will also internally create it 
    // and the object will be available to our provider.)  Thus, WebProcessStatistics is available only
    // to Full-trust app or provider. 
    //
    // But if we make WebProcessStatistics static, then all its public methods have to be static, and
    // they'll be fully available to all users.  No good.
    public class WebProcessStatistics { 
        static DateTime     s_startTime = DateTime.MinValue;
        static DateTime     s_lastUpdated = DateTime.MinValue; 
        static int          s_threadCount; 
        static long         s_workingSet;
        static long         s_peakWorkingSet; 
        static long         s_managedHeapSize;
        static int          s_appdomainCount;
        static int          s_requestsExecuting;
        static int          s_requestsQueued; 
        static int          s_requestsRejected;
        static bool         s_getCurrentProcFailed = false; 
        static object       s_lockObject = new object(); 

        static TimeSpan      TS_ONE_SECOND = new TimeSpan(0, 0, 1); 

        static WebProcessStatistics() {
            try {
#if !FEATURE_PAL // FEATURE_PAL does not support this.  Make into a noop. 
                s_startTime = Process.GetCurrentProcess().StartTime;
#endif // !FEATURE_PAL 
            } 
            catch {
                s_getCurrentProcFailed = true; 
            }
        }

        void Update() { 
            DateTime    now = DateTime.Now;
 
            if (now - s_lastUpdated < TS_ONE_SECOND) { 
                return;
            } 

            lock (s_lockObject) {
                if (now - s_lastUpdated < TS_ONE_SECOND) {
                    return; 
                }
 
                if (!s_getCurrentProcFailed) { 
                    Process process = Process.GetCurrentProcess();
#if !FEATURE_PAL // FEATURE_PAL does not support these Process properties 

                    s_threadCount = process.Threads.Count;
                    s_workingSet = (long)process.WorkingSet64;
                    s_peakWorkingSet = (long)process.PeakWorkingSet64; 
#else
                    throw new NotImplementedException ("ROTORTODO"); 
#endif 
                }
 
                s_managedHeapSize = GC.GetTotalMemory(false);

                s_appdomainCount = HostingEnvironment.AppDomainsCount;
 
                s_requestsExecuting = PerfCounters.GetGlobalCounter(GlobalPerfCounter.REQUESTS_CURRENT);
                s_requestsQueued = PerfCounters.GetGlobalCounter(GlobalPerfCounter.REQUESTS_QUEUED); 
                s_requestsRejected = PerfCounters.GetGlobalCounter(GlobalPerfCounter.REQUESTS_REJECTED); 

                s_lastUpdated = now; 
            }
        }

 
        public DateTime ProcessStartTime {get {Update(); return s_startTime;}}
 
        public int ThreadCount {get {Update(); return s_threadCount;}} 

        public long WorkingSet {get {Update(); return s_workingSet;}} 

        public long PeakWorkingSet {get {Update(); return s_peakWorkingSet;}}

        public long ManagedHeapSize {get {Update(); return s_managedHeapSize;}} 

        public int AppDomainCount {get {Update(); return s_appdomainCount;}} 
 
        public int RequestsExecuting {get {Update(); return s_requestsExecuting;}}
 
        public int RequestsQueued {get {Update(); return s_requestsQueued;}}

        public int RequestsRejected {get {Update(); return s_requestsRejected;}}
 

        virtual public void FormatToString(WebEventFormatter formatter) { 
            formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_process_start_time, ProcessStartTime.ToString(CultureInfo.InstalledUICulture))); 
            formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_thread_count, ThreadCount.ToString(CultureInfo.InstalledUICulture)));
            formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_working_set, WorkingSet.ToString(CultureInfo.InstalledUICulture))); 
            formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_peak_working_set, PeakWorkingSet.ToString(CultureInfo.InstalledUICulture)));
            formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_managed_heap_size, ManagedHeapSize.ToString(CultureInfo.InstalledUICulture)));

            formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_application_domain_count, AppDomainCount.ToString(CultureInfo.InstalledUICulture))); 
            formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_requests_executing, RequestsExecuting.ToString(CultureInfo.InstalledUICulture)));
            formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_request_queued, RequestsQueued.ToString(CultureInfo.InstalledUICulture))); 
            formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_request_rejected, RequestsRejected.ToString(CultureInfo.InstalledUICulture))); 
        }
    } 

    public sealed class WebThreadInformation {
        int     _threadId;
        string  _accountName; 
        string  _stackTrace;
        bool    _isImpersonating; 
        internal const string IsImpersonatingKey = "ASPIMPERSONATING"; 

        internal WebThreadInformation(Exception exception) { 
            _threadId = Thread.CurrentThread.ManagedThreadId;
            _accountName = HttpApplication.GetCurrentWindowsIdentityWithAssert().Name;

            if (exception != null) { 
                _stackTrace = new StackTrace(exception, true).ToString();
                _isImpersonating = exception.Data.Contains(IsImpersonatingKey); 
            } 
            else {
                _stackTrace = String.Empty; 
                _isImpersonating = false;
            }
        }
 

        public int ThreadID {get {return _threadId;}} 
 
        public string ThreadAccountName {get {return _accountName;}}
 
        public string StackTrace {get {return _stackTrace;}}

        public bool IsImpersonating {get {return _isImpersonating;}}
 

        public void FormatToString(WebEventFormatter formatter) { 
            formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_thread_id, ThreadID.ToString(CultureInfo.InstalledUICulture))); 
            formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_thread_account_name, ThreadAccountName));
 
            if (IsImpersonating) {
                formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_is_impersonating));
            }
            else { 
                formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_is_not_impersonating));
            } 
 
            formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_stack_trace, StackTrace));
        } 
    }

    // Class that represents the firing record (how many times, last firing time, etc)
    // for each rule that inherits from WebBaseEvent. 

    public sealed class RuleFiringRecord { 
        internal DateTime   _lastFired; 
        internal int        _timesRaised;
        internal int        _updatingLastFired; 

        static TimeSpan     TS_ONE_SECOND = new TimeSpan(0, 0, 1);

        public DateTime LastFired { get { return _lastFired; } } 

 
        public int TimesRaised { get { return _timesRaised; } } 

        // Point to the ruleInfo that is used by this class 
        internal HealthMonitoringSectionHelper.RuleInfo    _ruleInfo;

        internal RuleFiringRecord(HealthMonitoringSectionHelper.RuleInfo ruleInfo) {
 
            Debug.Assert(ruleInfo != null, "ruleInfo != null");
 
            _ruleInfo = ruleInfo; 

            _lastFired = DateTime.MinValue; 
            _timesRaised = 0;
            _updatingLastFired = 0;
        }
 
        void UpdateLastFired(DateTime now, bool alreadyLocked) {
            TimeSpan    tsDiff = now - _lastFired; 
 
            if (tsDiff < TS_ONE_SECOND) {
                // If _lastFired was updated within one second, don't bother. 
                return;
            }

            if (!alreadyLocked) { 
                // If several threads are firing at the same time, only one thread will
                // update record._lastFired. 
                if (Interlocked.CompareExchange(ref _updatingLastFired, 1, 0) == 0) { 
                    try {
                        _lastFired = now; 
                    }
                    finally {
                        Interlocked.Exchange(ref _updatingLastFired, 0);
                    } 
                }
            } 
            else { 
                _lastFired = now;
            } 
        }

        // Note: this method is thread safe
        internal bool CheckAndUpdate(WebBaseEvent eventRaised) { 
            DateTime    now = DateTime.Now;
            int         timesRaised; 
            HealthMonitoringManager manager = HealthMonitoringManager.Manager(); 

            timesRaised = Interlocked.Increment(ref _timesRaised); 

            if (manager == null) {
                // Won't fire because we cannot configure healthmonitor
                Debug.Trace("RuleFiringRecord", "Can't configure healthmonitor"); 
                return false;
            } 
 
            // Call custom evaluator first
            if (_ruleInfo._customEvaluatorType != null) { 

                IWebEventCustomEvaluator    icustom = (IWebEventCustomEvaluator)
                        manager._sectionHelper._customEvaluatorInstances[_ruleInfo._customEvaluatorType];
 
#if (!DBG)
                try { 
#endif 
                    // The event may need to do pre-ProcessEvent initialization
                    eventRaised.PreProcessEventInit(); 

                    if (!icustom.CanFire(eventRaised, this)) {
                        Debug.Trace("RuleFiringRecord", "Custom evaluator returns false.");
                        return false; 
                    }
#if (!DBG) 
                } 
                catch {
                    Debug.Trace("RuleFiringRecord", "Hit an exception when calling Custom evaluator"); 
                    // Return if we hit an error
                    return false;
                }
#endif 
            }
 
            if (timesRaised < _ruleInfo._minInstances) { 
                Debug.Trace("RuleFiringRecord",
                        "MinInterval not met; timesRaised=" + timesRaised + 
                        "; _minInstances=" + _ruleInfo._minInstances);
                return false;
            }
 
            if (timesRaised > _ruleInfo._maxLimit) {
                Debug.Trace("RuleFiringRecord", 
                        "MaxLimit exceeded; timesRaised=" + timesRaised + 
                        "; _maxLimit=" + _ruleInfo._maxLimit);
                return false; 
            }

            // Last step: Check MinInterval and update _lastFired
 
            if (_ruleInfo._minInterval == TimeSpan.Zero) {
                UpdateLastFired(now, false); 
                return true; 
            }
 
            if ((now - _lastFired) <= _ruleInfo._minInterval) {
                Debug.Trace("RuleFiringRecord",
                        "MinInterval not met; now=" + now +
                        "; _lastFired=" + _lastFired + 
                        "; _ruleInfo._minInterval=" + _ruleInfo._minInterval);
                return false; 
            } 

            // The lock is to prevent multiple threads from passing the 
            // same test simultaneously.
            lock (this) {
                if ((now - _lastFired) <= _ruleInfo._minInterval) {
                    Debug.Trace("RuleFiringRecord", 
                            "MinInterval not met; now=" + now +
                            "; _lastFired=" + _lastFired + 
                            "; _ruleInfo._tsMinInterval=" + _ruleInfo._minInterval); 
                    return false;
                } 

                UpdateLastFired(now, true);
                return true;
            } 
        }
 
    } 

    internal class HealthMonitoringManager { 
        internal HealthMonitoringSectionHelper          _sectionHelper;
        internal bool           _enabled = false;

        static Timer            s_heartbeatTimer = null; 
        static HealthMonitoringManager s_manager = null;
        static bool             s_inited = false; 
        static bool             s_initing = false; 
        static object           s_lockObject = new object();
 
        // If this method returns null, it means we failed during configuration.
        internal static HealthMonitoringManager Manager() {

            if (s_initing) { 
                Debug.Assert(!s_inited);
                // If this is true, that means we are calling WebEventBase.Raise while 
                // we are initializing.  That means Init() has caused a config exception. 
                return null;
            } 

            if (s_inited) {
                return s_manager;
            } 

            lock (s_lockObject) { 
                if (s_inited) { 
                    return s_manager;
                } 

                try {
                    Debug.Assert(s_manager == null);
                    s_initing = true; 
                    s_manager = new HealthMonitoringManager();;
                } 
                finally { 
                    s_initing = false;
                    s_inited = true; 
                }
            }

            return s_manager; 
        }
 
        internal static bool Enabled { 
            get {
                HealthMonitoringManager manager = HealthMonitoringManager.Manager(); 
                if (manager == null) {
                    return false;
                }
 
                return manager._enabled;
            } 
        } 

        internal static void StartHealthMonitoringHeartbeat() { 
            HealthMonitoringManager manager = Manager();
            if (manager == null) {
                Debug.Trace(
                    "HealthMonitoringManager", "Can't fire heartbeat because we cannot configure HealthMon"); 
                return;
            } 
 
            if (!manager._enabled) {
                Debug.Trace( 
                    "WebEventRaiseDetails", "Can't fire heartbeat because we are disabled");
                return;
            }
 
            manager.StartHeartbeatTimer();
        } 
 
        private HealthMonitoringManager() {
            _sectionHelper = HealthMonitoringSectionHelper.GetHelper(); 

            _enabled = _sectionHelper.Enabled;

            if (!_enabled) { 
                return;
            } 
        } 

        internal static void Shutdown() { 
            WebEventManager.Shutdown();
            Dispose();
        }
 
        internal static void Dispose() {
            // Make sure this function won't throw 
            try { 
                if (s_heartbeatTimer != null) {
                    s_heartbeatTimer.Dispose(); 
                    s_heartbeatTimer = null;
                }
            }
            catch { 
            }
        } 
 
        internal void HeartbeatCallback(object state) {
            Debug.Assert(HealthMonitoringManager.Enabled); 
            WebBaseEvent.RaiseSystemEvent(null, WebEventCodes.ApplicationHeartbeat);
        }

        internal void StartHeartbeatTimer() { 
            TimeSpan interval = _sectionHelper.HealthMonitoringSection.HeartbeatInterval;
 
            if (interval == TimeSpan.Zero) { 
                return;
            } 

#if DBG
            if (!Debug.IsTagPresent("Timer") || Debug.IsTagEnabled("Timer"))
#endif 
            {
                s_heartbeatTimer = new Timer(new TimerCallback(this.HeartbeatCallback), null, 
                    TimeSpan.Zero, interval); 
            }
        } 

        internal static HealthMonitoringSectionHelper.ProviderInstances ProviderInstances {
            get {
                HealthMonitoringManager manager = Manager(); 

                if (manager == null) { 
                    return null; 
                }
 
                if (!manager._enabled) {
                    return null;
                }
 
                return manager._sectionHelper._providerInstances;
            } 
        } 
    }
 
    public sealed class WebBaseEventCollection : ReadOnlyCollectionBase
    {
        public WebBaseEventCollection(ICollection events) {
            if (events == null) { 
                throw new ArgumentNullException("events");
            } 
 
            foreach (WebBaseEvent eventRaised in events) {
                InnerList.Add(eventRaised); 
            }
        }

        internal WebBaseEventCollection(WebBaseEvent eventRaised) { 
            if (eventRaised == null) {
                throw new ArgumentNullException("eventRaised"); 
            } 

            InnerList.Add(eventRaised); 
        }

        // overloaded collection access methods
        public WebBaseEvent this[int index] { 
            get {
                return (WebBaseEvent) InnerList[index]; 
            } 
        }
 
        public int IndexOf(WebBaseEvent value) {
            return InnerList.IndexOf(value);
        }
 
        public bool Contains(WebBaseEvent value) {
            return InnerList.Contains(value); 
        } 
    }
 
    public static class WebEventManager
    {

        [SecurityPermission(SecurityAction.Demand, Unrestricted=true)] 
        public static void Flush(string providerName) {
            HealthMonitoringSectionHelper.ProviderInstances   providers = HealthMonitoringManager.ProviderInstances; 
 
            if (providers == null) {
                return; 
            }

            if (!providers.ContainsKey(providerName)) {
                throw new ArgumentException(SR.GetString(SR.Health_mon_provider_not_found, providerName)); 
            }
 
            using (new ApplicationImpersonationContext()) { 
                providers[providerName].Flush();
            } 
        }

        [SecurityPermission(SecurityAction.Demand, Unrestricted=true)]
        public static void Flush() { 
            HealthMonitoringSectionHelper.ProviderInstances providers = HealthMonitoringManager.ProviderInstances;
 
            if (providers == null) { 
                return;
            } 

            using (new ApplicationImpersonationContext()) {
                foreach(DictionaryEntry de in providers) {
                    WebEventProvider    provider = (WebEventProvider)de.Value; 

                    Debug.Trace("WebEventManager", "Flushing provider " + provider.Name); 
                    provider.Flush(); 
                }
            } 
        }

        internal static void Shutdown() {
            HealthMonitoringSectionHelper.ProviderInstances   providers = HealthMonitoringManager.ProviderInstances; 

            if (providers == null) { 
                return; 
            }
 
            foreach(DictionaryEntry de in providers) {
                WebEventProvider    provider = (WebEventProvider)de.Value;

                Debug.Trace("WebEventManager", "Shutting down provider " + provider.Name); 
                provider.Shutdown();
            } 
        } 
    }
 
}


// 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