|
//-----------------------------------------------------------------------------
// 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);
}
}
}
}
|