// ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // // [....] /*============================================================ ** ** Class: ExecutionContext ** ** ** Purpose: Capture execution context for a thread ** ** ===========================================================*/ namespace System.Threading { using System; using System.Security; using System.Runtime.Remoting; using System.Security.Principal; using System.Collections; using System.Reflection; using System.Runtime.Serialization; using System.Security.Permissions; using System.Runtime.Remoting.Messaging; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; #if FEATURE_CORRUPTING_EXCEPTIONS using System.Runtime.ExceptionServices; #endif // FEATURE_CORRUPTING_EXCEPTIONS using System.Runtime.ConstrainedExecution; using System.Diagnostics.Contracts; using System.Diagnostics.CodeAnalysis; // helper delegate to statically bind to Wait method internal delegate int WaitDelegate(IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout); internal struct ExecutionContextSwitcher { internal ExecutionContext.Reader outerEC; // previous EC we need to restore on Undo internal bool outerECBelongsToScope; #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK internal SecurityContextSwitcher scsw; #endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK internal Object hecsw; #if !FEATURE_PAL && FEATURE_IMPERSONATION internal WindowsIdentity wi; internal bool cachedAlwaysFlowImpersonationPolicy; internal bool wiIsValid; #endif internal Thread thread; [System.Security.SecurityCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] #if FEATURE_CORRUPTING_EXCEPTIONS [HandleProcessCorruptedStateExceptions] // #endif // FEATURE_CORRUPTING_EXCEPTIONS internal bool UndoNoThrow() { try { Undo(Thread.CurrentThread); } catch { return false; } return true; } [System.Security.SecurityCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] internal void Undo(Thread currentThread) { // // Don't use an uninitialized switcher, or one that's already been used. // if (thread == null) return; // Don't do anything Contract.Assert(currentThread == this.thread); // // Restore the HostExecutionContext before restoring the ExecutionContext. // #if FEATURE_CAS_POLICY if (hecsw != null) HostExecutionContextSwitcher.Undo(hecsw); #endif // FEATURE_CAS_POLICY // // restore the saved Execution Context. Note that this will also restore the // SynchronizationContext, Logical/IllogicalCallContext, etc. // #if !FEATURE_PAL && FEATURE_IMPERSONATION ExecutionContext.Reader innerEC = currentThread.GetExecutionContextReader(); #endif currentThread.SetExecutionContext(outerEC, outerECBelongsToScope); #if DEBUG try { currentThread.ForbidExecutionContextMutation = true; #endif // // Tell the SecurityContext to do the side-effects of restoration. // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK if (scsw.currSC != null) { // Any critical failure inside scsw will cause FailFast scsw.Undo(); } #endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK #if !FEATURE_PAL && FEATURE_IMPERSONATION if (wiIsValid) SecurityContext.RestoreCurrentWI(outerEC, innerEC, wi, cachedAlwaysFlowImpersonationPolicy); #endif thread = null; // this will prevent the switcher object being used again #if DEBUG } finally { currentThread.ForbidExecutionContextMutation = false; } #endif } } public struct AsyncFlowControl: IDisposable { private bool useEC; private ExecutionContext _ec; #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK private SecurityContext _sc; #endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK private Thread _thread; #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK [SecurityCritical] internal void Setup(SecurityContextDisableFlow flags) { useEC = false; Thread currentThread = Thread.CurrentThread; _sc = currentThread.GetMutableExecutionContext().SecurityContext; _sc._disableFlow = flags; _thread = currentThread; } #endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK [SecurityCritical] internal void Setup() { useEC = true; Thread currentThread = Thread.CurrentThread; _ec = currentThread.GetMutableExecutionContext(); _ec.isFlowSuppressed = true; _thread = currentThread; } public void Dispose() { Undo(); } [SecuritySafeCritical] public void Undo() { if (_thread == null) { throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CannotUseAFCMultiple")); } if (_thread != Thread.CurrentThread) { throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CannotUseAFCOtherThread")); } if (useEC) { if (Thread.CurrentThread.GetMutableExecutionContext() != _ec) { throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_AsyncFlowCtrlCtxMismatch")); } ExecutionContext.RestoreFlow(); } #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK else { if (!Thread.CurrentThread.GetExecutionContextReader().SecurityContext.IsSame(_sc)) { throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_AsyncFlowCtrlCtxMismatch")); } SecurityContext.RestoreFlow(); } #endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK _thread = null; } public override int GetHashCode() { // review - [....] return _thread == null ? ToString().GetHashCode() : _thread.GetHashCode(); } public override bool Equals(Object obj) { if (obj is AsyncFlowControl) return Equals((AsyncFlowControl)obj); else return false; } public bool Equals(AsyncFlowControl obj) { return obj.useEC == useEC && obj._ec == _ec && #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK obj._sc == _sc && #endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK obj._thread == _thread; } public static bool operator ==(AsyncFlowControl a, AsyncFlowControl b) { return a.Equals(b); } public static bool operator !=(AsyncFlowControl a, AsyncFlowControl b) { return !(a == b); } } #if FEATURE_CORECLR [System.Security.SecurityCritical] // auto-generated #endif [System.Runtime.InteropServices.ComVisible(true)] public delegate void ContextCallback(Object state); [Serializable] public sealed class ExecutionContext : IDisposable, ISerializable { /*========================================================================= ** Data accessed from managed code that needs to be defined in ** ExecutionContextObject to maintain alignment between the two classes. ** DON'T CHANGE THESE UNLESS YOU MODIFY ExecutionContextObject in vm\object.h =========================================================================*/ #if FEATURE_CAS_POLICY private HostExecutionContext _hostExecutionContext; #endif // FEATURE_CAS_POLICY #if FEATURE_SYNCHRONIZATIONCONTEXT private SynchronizationContext _syncContext; private SynchronizationContext _syncContextNoFlow; #endif // FEATURE_SYNCHRONIZATIONCONTEXT #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK private SecurityContext _securityContext; #endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK [System.Security.SecurityCritical] // auto-generated private LogicalCallContext _logicalCallContext; private IllogicalCallContext _illogicalCallContext; // this call context follows the physical thread enum Flags { None = 0x0, IsNewCapture = 0x1, IsFlowSuppressed = 0x2, IsPreAllocatedDefault = 0x4 } private Flags _flags; internal bool isNewCapture { get { return (_flags & (Flags.IsNewCapture | Flags.IsPreAllocatedDefault)) != Flags.None; } set { Contract.Assert(!IsPreAllocatedDefault); if (value) _flags |= Flags.IsNewCapture; else _flags &= ~Flags.IsNewCapture; } } internal bool isFlowSuppressed { get { return (_flags & Flags.IsFlowSuppressed) != Flags.None; } set { Contract.Assert(!IsPreAllocatedDefault); if (value) _flags |= Flags.IsFlowSuppressed; else _flags &= ~Flags.IsFlowSuppressed; } } private static readonly ExecutionContext s_dummyDefaultEC = new ExecutionContext(isPreAllocatedDefault: true); static internal ExecutionContext PreAllocatedDefault { [SecuritySafeCritical] get { return s_dummyDefaultEC; } } internal bool IsPreAllocatedDefault { get { // we use _flags instead of a direct comparison w/ s_dummyDefaultEC to avoid the static access on // hot code paths. if ((_flags & Flags.IsPreAllocatedDefault) != Flags.None) { Contract.Assert(this == s_dummyDefaultEC); return true; } else { return false; } } } [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] internal ExecutionContext() { } [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] internal ExecutionContext(bool isPreAllocatedDefault) { if (isPreAllocatedDefault) _flags = Flags.IsPreAllocatedDefault; } // Read-only wrapper around ExecutionContext. This enables safe reading of an ExecutionContext without accidentally modifying it. internal struct Reader { ExecutionContext m_ec; public Reader(ExecutionContext ec) { m_ec = ec; } public ExecutionContext DangerousGetRawExecutionContext() { return m_ec; } public bool IsNull { get { return m_ec == null; } } [SecurityCritical] public bool IsDefaultFTContext(bool ignoreSyncCtx) { return m_ec.IsDefaultFTContext(ignoreSyncCtx); } public bool IsFlowSuppressed { #if !FEATURE_CORECLR [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif get { return IsNull ? false : m_ec.isFlowSuppressed; } } //public Thread Thread { get { return m_ec._thread; } } public bool IsSame(ExecutionContext.Reader other) { return m_ec == other.m_ec; } #if FEATURE_SYNCHRONIZATIONCONTEXT public SynchronizationContext SynchronizationContext { get { return IsNull ? null : m_ec.SynchronizationContext; } } public SynchronizationContext SynchronizationContextNoFlow { get { return IsNull ? null : m_ec.SynchronizationContextNoFlow; } } #endif #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK public SecurityContext.Reader SecurityContext { [SecurityCritical] [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new SecurityContext.Reader(IsNull ? null : m_ec.SecurityContext); } } #endif public LogicalCallContext.Reader LogicalCallContext { [SecurityCritical] get { return new LogicalCallContext.Reader(IsNull ? null : m_ec.LogicalCallContext); } } public IllogicalCallContext.Reader IllogicalCallContext { [SecurityCritical] get { return new IllogicalCallContext.Reader(IsNull ? null : m_ec.IllogicalCallContext); } } } internal LogicalCallContext LogicalCallContext { [System.Security.SecurityCritical] // auto-generated get { if (_logicalCallContext == null) { _logicalCallContext = new LogicalCallContext(); } return _logicalCallContext; } [System.Security.SecurityCritical] // auto-generated set { Contract.Assert(this != s_dummyDefaultEC); _logicalCallContext = value; } } internal IllogicalCallContext IllogicalCallContext { get { if (_illogicalCallContext == null) { _illogicalCallContext = new IllogicalCallContext(); } return _illogicalCallContext; } set { Contract.Assert(this != s_dummyDefaultEC); _illogicalCallContext = value; } } #if FEATURE_SYNCHRONIZATIONCONTEXT internal SynchronizationContext SynchronizationContext { [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] get { return _syncContext; } [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] set { Contract.Assert(this != s_dummyDefaultEC); _syncContext = value; } } internal SynchronizationContext SynchronizationContextNoFlow { [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] get { return _syncContextNoFlow; } [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] set { Contract.Assert(this != s_dummyDefaultEC); _syncContextNoFlow = value; } } #endif // #if FEATURE_SYNCHRONIZATIONCONTEXT #if FEATURE_CAS_POLICY internal HostExecutionContext HostExecutionContext { get { return _hostExecutionContext; } set { Contract.Assert(this != s_dummyDefaultEC); _hostExecutionContext = value; } } #endif // FEATURE_CAS_POLICY #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK internal SecurityContext SecurityContext { [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] get { return _securityContext; } [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] set { Contract.Assert(this != s_dummyDefaultEC); // store the new security context _securityContext = value; // perform the reverse link too if (value != null) _securityContext.ExecutionContext = this; } } #endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK public void Dispose() { if(this.IsPreAllocatedDefault) return; //Do nothing if this is the default context #if FEATURE_CAS_POLICY if (_hostExecutionContext != null) _hostExecutionContext.Dispose(); #endif // FEATURE_CAS_POLICY #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK if (_securityContext != null) _securityContext.Dispose(); #endif //FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK } [DynamicSecurityMethod] [System.Security.SecurityCritical] // auto-generated_required public static void Run(ExecutionContext executionContext, ContextCallback callback, Object state) { if (executionContext == null) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NullContext")); if (!executionContext.isNewCapture) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotNewCaptureContext")); Run(executionContext, callback, state, false); } // This method is special from a security perspective - the VM will not allow a stack walk to // continue past the call to ExecutionContext.Run. If you change the signature to this method, make // sure to update SecurityStackWalk::IsSpecialRunFrame in the VM to search for the new signature. [DynamicSecurityMethod] [SecurityCritical] [FriendAccessAllowed] internal static void Run(ExecutionContext executionContext, ContextCallback callback, Object state, bool preserveSyncCtx) { RunInternal(executionContext, callback, state, preserveSyncCtx); } // Actual implementation of Run is here, in a non-DynamicSecurityMethod, because the JIT seems to refuse to inline callees into // a DynamicSecurityMethod. [SecurityCritical] [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "Reviewed for thread safety")] [HandleProcessCorruptedStateExceptions] internal static void RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, bool preserveSyncCtx) { Contract.Assert(executionContext != null); if (executionContext.IsPreAllocatedDefault) { Contract.Assert(executionContext.IsDefaultFTContext(preserveSyncCtx)); } else { Contract.Assert(executionContext.isNewCapture); executionContext.isNewCapture = false; } Thread currentThread = Thread.CurrentThread; ExecutionContextSwitcher ecsw = default(ExecutionContextSwitcher); RuntimeHelpers.PrepareConstrainedRegions(); try { ExecutionContext.Reader ec = currentThread.GetExecutionContextReader(); if ( (ec.IsNull || ec.IsDefaultFTContext(preserveSyncCtx)) && #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK SecurityContext.CurrentlyInDefaultFTSecurityContext(ec) && #endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK executionContext.IsDefaultFTContext(preserveSyncCtx)) { // Neither context is interesting, so we don't need to set the context. // We do need to reset any changes made by the user's callback, // so here we establish a "copy-on-write scope". Any changes will // result in a copy of the context being made, preserving the original // context. EstablishCopyOnWriteScope(currentThread, true, ref ecsw); } else { if (executionContext.IsPreAllocatedDefault) executionContext = executionContext.CreateCopy(); ecsw = SetExecutionContext(executionContext, preserveSyncCtx); } // // Call the user's callback // callback(state); } finally { ecsw.Undo(currentThread); } } [SecurityCritical] static internal void EstablishCopyOnWriteScope(Thread currentThread, bool knownNullWindowsIdentity, ref ExecutionContextSwitcher ecsw) { Contract.Assert(currentThread == Thread.CurrentThread); ecsw.outerEC = currentThread.GetExecutionContextReader(); ecsw.outerECBelongsToScope = currentThread.ExecutionContextBelongsToCurrentScope; #if !FEATURE_PAL && FEATURE_IMPERSONATION ecsw.cachedAlwaysFlowImpersonationPolicy = SecurityContext.AlwaysFlowImpersonationPolicy; if (knownNullWindowsIdentity) Contract.Assert(SecurityContext.GetCurrentWI(ecsw.outerEC, ecsw.cachedAlwaysFlowImpersonationPolicy) == null); else ecsw.wi = SecurityContext.GetCurrentWI(ecsw.outerEC, ecsw.cachedAlwaysFlowImpersonationPolicy); ecsw.wiIsValid = true; #endif currentThread.ExecutionContextBelongsToCurrentScope = false; ecsw.thread = currentThread; } // Sets the given execution context object on the thread. // Returns the previous one. [System.Security.SecurityCritical] // auto-generated [DynamicSecurityMethodAttribute()] [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable #if FEATURE_CORRUPTING_EXCEPTIONS [HandleProcessCorruptedStateExceptions] // #endif // FEATURE_CORRUPTING_EXCEPTIONS internal static ExecutionContextSwitcher SetExecutionContext(ExecutionContext executionContext, bool preserveSyncCtx) { #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; #endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK Contract.Assert(executionContext != null); Contract.Assert(executionContext != s_dummyDefaultEC); // Set up the switcher object to return; ExecutionContextSwitcher ecsw = new ExecutionContextSwitcher(); Thread currentThread = Thread.CurrentThread; ExecutionContext.Reader outerEC = currentThread.GetExecutionContextReader(); ecsw.thread = currentThread; ecsw.outerEC = outerEC; ecsw.outerECBelongsToScope = currentThread.ExecutionContextBelongsToCurrentScope; if (preserveSyncCtx) executionContext.SynchronizationContext = outerEC.SynchronizationContext; executionContext.SynchronizationContextNoFlow = outerEC.SynchronizationContextNoFlow; currentThread.SetExecutionContext(executionContext, belongsToCurrentScope: true); RuntimeHelpers.PrepareConstrainedRegions(); try { #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK //set the security context SecurityContext sc = executionContext.SecurityContext; if (sc != null) { // non-null SC: needs to be set SecurityContext.Reader prevSeC = outerEC.SecurityContext; ecsw.scsw = SecurityContext.SetSecurityContext(sc, prevSeC, false, ref stackMark); } else if (!SecurityContext.CurrentlyInDefaultFTSecurityContext(ecsw.outerEC)) { // null incoming SC, but we're currently not in FT: use static FTSC to set SecurityContext.Reader prevSeC = outerEC.SecurityContext; ecsw.scsw = SecurityContext.SetSecurityContext(SecurityContext.FullTrustSecurityContext, prevSeC, false, ref stackMark); } #endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK #if FEATURE_CAS_POLICY // set the Host Context HostExecutionContext hostContext = executionContext.HostExecutionContext; if (hostContext != null) { ecsw.hecsw = HostExecutionContextManager.SetHostExecutionContextInternal(hostContext); } #endif // FEATURE_CAS_POLICY } catch { ecsw.UndoNoThrow(); throw; } return ecsw; } // // Public CreateCopy. Used to copy captured ExecutionContexts so they can be reused multiple times. // This should only copy the portion of the context that we actually capture. // [SecuritySafeCritical] public ExecutionContext CreateCopy() { if (!isNewCapture) { throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CannotCopyUsedContext")); } ExecutionContext ec = new ExecutionContext(); ec.isNewCapture = true; #if FEATURE_SYNCHRONIZATIONCONTEXT ec._syncContext = _syncContext == null ? null : _syncContext.CreateCopy(); #endif // #if FEATURE_SYNCHRONIZATIONCONTEXT #if FEATURE_CAS_POLICY // capture the host execution context ec._hostExecutionContext = _hostExecutionContext == null ? null : _hostExecutionContext.CreateCopy(); #endif // FEATURE_CAS_POLICY #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK if (_securityContext != null) { ec._securityContext = _securityContext.CreateCopy(); ec._securityContext.ExecutionContext = ec; } #endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK if (this._logicalCallContext != null) ec.LogicalCallContext = (LogicalCallContext)this.LogicalCallContext.Clone(); Contract.Assert(this._illogicalCallContext == null); return ec; } // // Creates a complete copy, used for copy-on-write. // [SecuritySafeCritical] internal ExecutionContext CreateMutableCopy() { Contract.Assert(!this.isNewCapture); ExecutionContext ec = new ExecutionContext(); // We don't deep-copy the SyncCtx, since we're still in the same context after copy-on-write. #if FEATURE_SYNCHRONIZATIONCONTEXT ec._syncContext = this._syncContext; ec._syncContextNoFlow = this._syncContextNoFlow; #endif // #if FEATURE_SYNCHRONIZATIONCONTEXT #if FEATURE_CAS_POLICY // capture the host execution context ec._hostExecutionContext = this._hostExecutionContext == null ? null : _hostExecutionContext.CreateCopy(); #endif // FEATURE_CAS_POLICY #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK if (_securityContext != null) { ec._securityContext = this._securityContext.CreateMutableCopy(); ec._securityContext.ExecutionContext = ec; } #endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK if (this._logicalCallContext != null) ec.LogicalCallContext = (LogicalCallContext)this.LogicalCallContext.Clone(); if (this._illogicalCallContext != null) ec.IllogicalCallContext = (IllogicalCallContext)this.IllogicalCallContext.CreateCopy(); ec.isFlowSuppressed = this.isFlowSuppressed; return ec; } [System.Security.SecurityCritical] // auto-generated_required public static AsyncFlowControl SuppressFlow() { if (IsFlowSuppressed()) { throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CannotSupressFlowMultipleTimes")); } Contract.EndContractBlock(); AsyncFlowControl afc = new AsyncFlowControl(); afc.Setup(); return afc; } [SecuritySafeCritical] public static void RestoreFlow() { ExecutionContext ec = Thread.CurrentThread.GetMutableExecutionContext(); if (!ec.isFlowSuppressed) { throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CannotRestoreUnsupressedFlow")); } ec.isFlowSuppressed = false; } [Pure] public static bool IsFlowSuppressed() { return Thread.CurrentThread.GetExecutionContextReader().IsFlowSuppressed; } [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public static ExecutionContext Capture() { // set up a stack mark for finding the caller StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; return ExecutionContext.Capture(ref stackMark, CaptureOptions.None); } // // Captures an ExecutionContext with optimization for the "default" case, and captures a "null" synchronization context. // When calling ExecutionContext.Run on the returned context, specify ignoreSyncCtx = true // [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable [FriendAccessAllowed] internal static ExecutionContext FastCapture() { // set up a stack mark for finding the caller StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; return ExecutionContext.Capture(ref stackMark, CaptureOptions.IgnoreSyncCtx | CaptureOptions.OptimizeDefaultCase); } [Flags] internal enum CaptureOptions { None = 0x00, IgnoreSyncCtx = 0x01, //Don't flow SynchronizationContext OptimizeDefaultCase = 0x02, //Faster in the typical case, but can't show the result to users // because they could modify the shared default EC. // Use this only if you won't be exposing the captured EC to users. } // internal helper to capture the current execution context using a passed in stack mark [System.Security.SecurityCritical] // auto-generated static internal ExecutionContext Capture(ref StackCrawlMark stackMark, CaptureOptions options) { ExecutionContext.Reader ecCurrent = Thread.CurrentThread.GetExecutionContextReader(); // check to see if Flow is suppressed if (ecCurrent.IsFlowSuppressed) return null; // // Attempt to capture context. There may be nothing to capture... // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK // capture the security context SecurityContext secCtxNew = SecurityContext.Capture(ecCurrent, ref stackMark); #endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK #if FEATURE_CAS_POLICY // capture the host execution context HostExecutionContext hostCtxNew = HostExecutionContextManager.CaptureHostExecutionContext(); #endif // FEATURE_CAS_POLICY #if FEATURE_SYNCHRONIZATIONCONTEXT SynchronizationContext syncCtxNew = null; #endif LogicalCallContext logCtxNew = null; if (!ecCurrent.IsNull) { #if FEATURE_SYNCHRONIZATIONCONTEXT // capture the [....] context if (0 == (options & CaptureOptions.IgnoreSyncCtx)) syncCtxNew = (ecCurrent.SynchronizationContext == null) ? null : ecCurrent.SynchronizationContext.CreateCopy(); #endif // #if FEATURE_SYNCHRONIZATIONCONTEXT // copy over the Logical Call Context if (ecCurrent.LogicalCallContext.HasInfo) logCtxNew = ecCurrent.LogicalCallContext.Clone(); } // // If we didn't get anything but defaults, and we're allowed to return the // dummy default EC, don't bother allocating a new context. // if (0 != (options & CaptureOptions.OptimizeDefaultCase) && #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK secCtxNew == null && #endif #if FEATURE_CAS_POLICY hostCtxNew == null && #endif // FEATURE_CAS_POLICY #if FEATURE_SYNCHRONIZATIONCONTEXT syncCtxNew == null && #endif // #if FEATURE_SYNCHRONIZATIONCONTEXT (logCtxNew == null || !logCtxNew.HasInfo)) { return s_dummyDefaultEC; } // // Allocate the new context, and fill it in. // ExecutionContext ecNew = new ExecutionContext(); #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK ecNew.SecurityContext = secCtxNew; if (ecNew.SecurityContext != null) ecNew.SecurityContext.ExecutionContext = ecNew; #endif #if FEATURE_CAS_POLICY ecNew._hostExecutionContext = hostCtxNew; #endif // FEATURE_CAS_POLICY #if FEATURE_SYNCHRONIZATIONCONTEXT ecNew._syncContext = syncCtxNew; #endif // #if FEATURE_SYNCHRONIZATIONCONTEXT ecNew.LogicalCallContext = logCtxNew; ecNew.isNewCapture = true; return ecNew; } // // Implementation of ISerializable // [System.Security.SecurityCritical] // auto-generated_required public void GetObjectData(SerializationInfo info, StreamingContext context) { if (info==null) throw new ArgumentNullException("info"); Contract.EndContractBlock(); if (_logicalCallContext != null) { info.AddValue("LogicalCallContext", _logicalCallContext, typeof(LogicalCallContext)); } } [System.Security.SecurityCritical] // auto-generated private ExecutionContext(SerializationInfo info, StreamingContext context) { SerializationInfoEnumerator e = info.GetEnumerator(); while (e.MoveNext()) { if (e.Name.Equals("LogicalCallContext")) { _logicalCallContext = (LogicalCallContext) e.Value; } } } // ObjRef .ctor [System.Security.SecurityCritical] // auto-generated internal bool IsDefaultFTContext(bool ignoreSyncCtx) { #if FEATURE_CAS_POLICY if (_hostExecutionContext != null) return false; #endif // FEATURE_CAS_POLICY #if FEATURE_SYNCHRONIZATIONCONTEXT if (!ignoreSyncCtx && _syncContext != null) return false; #endif // #if FEATURE_SYNCHRONIZATIONCONTEXT #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK if (_securityContext != null && !_securityContext.IsDefaultFTSecurityContext()) return false; #endif //#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK if (_logicalCallContext != null && _logicalCallContext.HasInfo) return false; if (_illogicalCallContext != null && _illogicalCallContext.HasUserData) return false; return true; } } // class ExecutionContext }