Xamarin Public Jenkins c042cd0c52 Imported Upstream version 4.2.0.179
Former-commit-id: 4610231f55806d2a05ed69e5ff3faa7336cc1479
2015-11-10 15:03:43 +00:00

958 lines
36 KiB
C#

// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// <OWNER>[....]</OWNER>
/*============================================================
**
** 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 !MONO && 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 !MONO && 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
}