File: System\ServiceModel\Dispatcher\ExceptionHandler.cs
Project: ndp\cdf\src\WCF\ServiceModel\System.ServiceModel.csproj (System.ServiceModel)
//-----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------------------------
 
namespace System.ServiceModel.Dispatcher
{
    using System.Diagnostics;
    using System.Runtime;
    using System.Runtime.ConstrainedExecution;
    using System.Security;
    using System.Security.Permissions;
    using System.ServiceModel;
 
    public abstract class ExceptionHandler
    {
        static readonly ExceptionHandler alwaysHandle = new AlwaysHandleExceptionHandler();
 
        static ExceptionHandler transportExceptionHandler = alwaysHandle;
 
        public static ExceptionHandler AlwaysHandle
        {
            get
            {
                return alwaysHandle;
            }
        }
 
        public static ExceptionHandler AsynchronousThreadExceptionHandler
        {
            [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
            get
            {
                // 
                HandlerWrapper wrapper = (HandlerWrapper)Fx.AsynchronousThreadExceptionHandler;
                return wrapper == null ? null : wrapper.Handler;
            }
 
            [Fx.Tag.SecurityNote(Critical = "Calls a LinkDemanded method (Fx setter) and critical method (HandlerWrapper ctor)",
                Safe = "protected with LinkDemand")]
            [SecuritySafeCritical]
            [SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
            set
            {
                Fx.AsynchronousThreadExceptionHandler = value == null ? null : new HandlerWrapper(value);
            }
        }
 
        public static ExceptionHandler TransportExceptionHandler
        {
            get
            {
                return transportExceptionHandler;
            }
 
            set
            {
                transportExceptionHandler = value;
            }
        }
 
        // Returns true if the exception has been handled.  If it returns false or
        // throws a different exception, the original exception will be rethrown.
        public abstract bool HandleException(Exception exception);
 
 
        class AlwaysHandleExceptionHandler : ExceptionHandler
        {
            [Fx.Tag.SecurityNote(Miscellaneous = "this function can be called from within a CER, must not call into PT code")]
            public override bool HandleException(Exception exception)
            {
                return true;
            }
        }
 
        internal static bool HandleTransportExceptionHelper(Exception exception)
        {
            if (exception == null)
            {
                throw Fx.AssertAndThrow("Null exception passed to HandleTransportExceptionHelper.");
            }
 
            ExceptionHandler handler = TransportExceptionHandler;
            if (handler == null)
            {
                return false;
            }
 
            try
            {
                if (!handler.HandleException(exception))
                {
                    return false;
                }
            }
            catch (Exception thrownException)
            {
                if (Fx.IsFatal(thrownException))
                {
                    throw;
                }
 
                DiagnosticUtility.TraceHandledException(thrownException, TraceEventType.Error);
                return false;
            }
 
            DiagnosticUtility.TraceHandledException(exception, TraceEventType.Error);
            return true;
        }
 
 
        class HandlerWrapper : Fx.ExceptionHandler
        {
            [Fx.Tag.SecurityNote(Critical = "Cannot let PT code alter the handler wrapped by this class.")]
            [SecurityCritical]
            readonly ExceptionHandler handler;
 
            [Fx.Tag.SecurityNote(Critical = "Cannot let PT code alter the handler wrapped by this class.")]
            [SecurityCritical]
            public HandlerWrapper(ExceptionHandler handler)
            {
                Fx.Assert(handler != null, "Cannot wrap a null handler.");
                this.handler = handler;
            }
 
            public ExceptionHandler Handler
            {
                [Fx.Tag.SecurityNote(Critical = "Access security-critical field.", Safe = "Ok to read field.")]
                [SecuritySafeCritical]
                [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
                get
                {
                    return this.handler;
                }
            }
 
            [Fx.Tag.SecurityNote(Critical = "Access security-critical field.", Safe = "Ok to call handler.",
                Miscellaneous = "Called in a CER, must not call into PT code.")]
            [SecuritySafeCritical]
            public override bool HandleException(Exception exception)
            {
                return this.handler.HandleException(exception);
            }
        }
    }
}