//----------------------------------------------------------------------------- // Copyright (c) Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- namespace System.Activities.Runtime { using System; using System.Runtime; using System.Runtime.Serialization; using System.Security; [DataContract] class FaultCallbackWrapper : CallbackWrapper { static readonly Type faultCallbackType = typeof(FaultCallback); static readonly Type[] faultCallbackParameters = new Type[] { typeof(NativeActivityFaultContext), typeof(Exception), typeof(ActivityInstance) }; public FaultCallbackWrapper(FaultCallback callback, ActivityInstance owningInstance) : base(callback, owningInstance) { } [Fx.Tag.SecurityNote(Critical = "Because we are calling EnsureCallback", Safe = "Safe because the method needs to be part of an Activity and we are casting to the callback type and it has a very specific signature. The author of the callback is buying into being invoked from PT.")] [SecuritySafeCritical] public void Invoke(NativeActivityFaultContext faultContext, Exception propagatedException, ActivityInstance propagatedFrom) { EnsureCallback(faultCallbackType, faultCallbackParameters); FaultCallback faultCallback = (FaultCallback)this.Callback; faultCallback(faultContext, propagatedException, propagatedFrom); } public WorkItem CreateWorkItem(Exception propagatedException, ActivityInstance propagatedFrom, ActivityInstanceReference originalExceptionSource) { return new FaultWorkItem(this, propagatedException, propagatedFrom, originalExceptionSource); } [DataContract] internal class FaultWorkItem : ActivityExecutionWorkItem { FaultCallbackWrapper callbackWrapper; Exception propagatedException; ActivityInstance propagatedFrom; ActivityInstanceReference originalExceptionSource; public FaultWorkItem(FaultCallbackWrapper callbackWrapper, Exception propagatedException, ActivityInstance propagatedFrom, ActivityInstanceReference originalExceptionSource) : base(callbackWrapper.ActivityInstance) { this.callbackWrapper = callbackWrapper; this.propagatedException = propagatedException; this.propagatedFrom = propagatedFrom; this.originalExceptionSource = originalExceptionSource; } public override ActivityInstance OriginalExceptionSource { get { return this.originalExceptionSource.ActivityInstance; } } [DataMember(Name = "callbackWrapper")] internal FaultCallbackWrapper SerializedCallbackWrapper { get { return this.callbackWrapper; } set { this.callbackWrapper = value; } } [DataMember(Name = "propagatedException")] internal Exception SerializedPropagatedException { get { return this.propagatedException; } set { this.propagatedException = value; } } [DataMember(Name = "propagatedFrom")] internal ActivityInstance SerializedPropagatedFrom { get { return this.propagatedFrom; } set { this.propagatedFrom = value; } } [DataMember(Name = "originalExceptionSource")] internal ActivityInstanceReference SerializedOriginalExceptionSource { get { return this.originalExceptionSource; } set { this.originalExceptionSource = value; } } public override void TraceCompleted() { if (TD.CompleteFaultWorkItemIsEnabled()) { TD.CompleteFaultWorkItem(this.ActivityInstance.Activity.GetType().ToString(), this.ActivityInstance.Activity.DisplayName, this.ActivityInstance.Id, this.originalExceptionSource.ActivityInstance.Activity.GetType().ToString(), this.originalExceptionSource.ActivityInstance.Activity.DisplayName, this.originalExceptionSource.ActivityInstance.Id, this.propagatedException); } } public override void TraceScheduled() { if (TD.ScheduleFaultWorkItemIsEnabled()) { TD.ScheduleFaultWorkItem(this.ActivityInstance.Activity.GetType().ToString(), this.ActivityInstance.Activity.DisplayName, this.ActivityInstance.Id, this.originalExceptionSource.ActivityInstance.Activity.GetType().ToString(), this.originalExceptionSource.ActivityInstance.Activity.DisplayName, this.originalExceptionSource.ActivityInstance.Id, this.propagatedException); } } public override void TraceStarting() { if (TD.StartFaultWorkItemIsEnabled()) { TD.StartFaultWorkItem(this.ActivityInstance.Activity.GetType().ToString(), this.ActivityInstance.Activity.DisplayName, this.ActivityInstance.Id, this.originalExceptionSource.ActivityInstance.Activity.GetType().ToString(), this.originalExceptionSource.ActivityInstance.Activity.DisplayName, this.originalExceptionSource.ActivityInstance.Id, this.propagatedException); } } public override bool Execute(ActivityExecutor executor, BookmarkManager bookmarkManager) { NativeActivityFaultContext faultContext = null; try { faultContext = new NativeActivityFaultContext(this.ActivityInstance, executor, bookmarkManager, this.propagatedException, this.originalExceptionSource); this.callbackWrapper.Invoke(faultContext, this.propagatedException, this.propagatedFrom); if (!faultContext.IsFaultHandled) { SetExceptionToPropagateWithoutAbort(this.propagatedException); } } catch (Exception e) { if (Fx.IsFatal(e)) { throw; } this.ExceptionToPropagate = e; } finally { if (faultContext != null) { faultContext.Dispose(); } // Tell the executor to decrement its no persist count persistence of exceptions is disabled. executor.ExitNoPersistForExceptionPropagation(); } return true; } } } }