You've already forked linux-packaging-mono
Imported Upstream version 4.0.0~alpha1
Former-commit-id: 806294f5ded97629b74c85c09952f2a74fe182d9
This commit is contained in:
337
external/referencesource/mscorlib/system/threading/hostexecutioncontextmanager.cs
vendored
Normal file
337
external/referencesource/mscorlib/system/threading/hostexecutioncontextmanager.cs
vendored
Normal file
@ -0,0 +1,337 @@
|
||||
using System.Diagnostics.Contracts;
|
||||
// ==++==
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
//
|
||||
// <OWNER>[....]</OWNER>
|
||||
/*============================================================
|
||||
**
|
||||
** Class: ExecutionContext
|
||||
**
|
||||
**
|
||||
** Purpose: Capture Host execution context for a thread
|
||||
**
|
||||
**
|
||||
===========================================================*/
|
||||
namespace System.Threading
|
||||
{
|
||||
using System.Security;
|
||||
using System.Runtime.Remoting;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Security.Permissions;
|
||||
using System.Runtime.Remoting.Messaging;
|
||||
using System.Runtime.ConstrainedExecution;
|
||||
using System.Runtime.Versioning;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
|
||||
|
||||
internal class HostExecutionContextSwitcher
|
||||
{
|
||||
internal ExecutionContext executionContext;
|
||||
internal HostExecutionContext previousHostContext;
|
||||
internal HostExecutionContext currentHostContext;
|
||||
|
||||
[System.Security.SecurityCritical] // auto-generated
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
|
||||
static public void Undo(Object switcherObject)
|
||||
{
|
||||
if (switcherObject == null)
|
||||
return;
|
||||
// otherwise call the host
|
||||
HostExecutionContextManager hostMgr = HostExecutionContextManager.GetCurrentHostExecutionContextManager();
|
||||
if (hostMgr != null)
|
||||
{
|
||||
hostMgr.Revert(switcherObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class HostExecutionContext : IDisposable
|
||||
{
|
||||
private Object state;
|
||||
|
||||
protected internal Object State {
|
||||
get {
|
||||
return state;
|
||||
}
|
||||
set {
|
||||
state = value;
|
||||
}
|
||||
}
|
||||
|
||||
public HostExecutionContext()
|
||||
{
|
||||
}
|
||||
|
||||
public HostExecutionContext(Object state)
|
||||
{
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
[System.Security.SecuritySafeCritical] // auto-generated
|
||||
public virtual HostExecutionContext CreateCopy()
|
||||
{
|
||||
Object newState = state;
|
||||
if (state is IUnknownSafeHandle)
|
||||
{
|
||||
// Clone the IUnknown handle
|
||||
newState = ((IUnknownSafeHandle)state).Clone();
|
||||
}
|
||||
return new HostExecutionContext(state);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
public virtual void Dispose(bool disposing)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
[System.Security.SecurityCritical] // auto-generated
|
||||
internal class IUnknownSafeHandle : SafeHandle
|
||||
{
|
||||
public IUnknownSafeHandle() : base(IntPtr.Zero, true)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool IsInvalid {
|
||||
[System.Security.SecurityCritical]
|
||||
get { return handle == IntPtr.Zero; }
|
||||
}
|
||||
|
||||
[System.Security.SecurityCritical]
|
||||
override protected bool ReleaseHandle()
|
||||
{
|
||||
HostExecutionContextManager.ReleaseHostSecurityContext(this.handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
internal Object Clone()
|
||||
{
|
||||
IUnknownSafeHandle unkSafeHandleCloned = new IUnknownSafeHandle();
|
||||
// call into the Hosting API to CLONE the host context
|
||||
// stores the output IUnknown in the safehandle,
|
||||
if (!IsInvalid)
|
||||
{
|
||||
HostExecutionContextManager.CloneHostSecurityContext(this, unkSafeHandleCloned);
|
||||
}
|
||||
return unkSafeHandleCloned;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class HostExecutionContextManager
|
||||
{
|
||||
private static volatile bool _fIsHostedChecked;
|
||||
private static volatile bool _fIsHosted;
|
||||
private static HostExecutionContextManager _hostExecutionContextManager;
|
||||
|
||||
[System.Security.SecurityCritical] // auto-generated
|
||||
[ResourceExposure(ResourceScope.None)]
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
|
||||
[MethodImplAttribute(MethodImplOptions.InternalCall)]
|
||||
static private extern bool HostSecurityManagerPresent();
|
||||
|
||||
[System.Security.SecurityCritical] // auto-generated
|
||||
[ResourceExposure(ResourceScope.None)]
|
||||
[MethodImplAttribute(MethodImplOptions.InternalCall)]
|
||||
static internal extern int ReleaseHostSecurityContext(IntPtr context);
|
||||
|
||||
[System.Security.SecurityCritical] // auto-generated
|
||||
[ResourceExposure(ResourceScope.None)]
|
||||
[MethodImplAttribute(MethodImplOptions.InternalCall)]
|
||||
static internal extern int CloneHostSecurityContext(SafeHandle context, SafeHandle clonedContext);
|
||||
|
||||
[System.Security.SecurityCritical] // auto-generated
|
||||
[ResourceExposure(ResourceScope.None)]
|
||||
[MethodImplAttribute(MethodImplOptions.InternalCall)]
|
||||
static private extern int CaptureHostSecurityContext(SafeHandle capturedContext);
|
||||
|
||||
[System.Security.SecurityCritical] // auto-generated
|
||||
[ResourceExposure(ResourceScope.None)]
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
|
||||
[MethodImplAttribute(MethodImplOptions.InternalCall)]
|
||||
static private extern int SetHostSecurityContext(SafeHandle context, bool fReturnPrevious, SafeHandle prevContext);
|
||||
|
||||
[System.Security.SecurityCritical] // auto-generated
|
||||
internal static bool CheckIfHosted()
|
||||
{
|
||||
if (!_fIsHostedChecked)
|
||||
{
|
||||
_fIsHosted = HostSecurityManagerPresent();
|
||||
_fIsHostedChecked = true;
|
||||
}
|
||||
return _fIsHosted;
|
||||
}
|
||||
|
||||
// capture Host SecurityContext
|
||||
[System.Security.SecuritySafeCritical] // auto-generated
|
||||
public virtual HostExecutionContext Capture()
|
||||
{
|
||||
HostExecutionContext context = null;
|
||||
// check if we are hosted
|
||||
if (CheckIfHosted())
|
||||
{
|
||||
IUnknownSafeHandle unkSafeHandle = new IUnknownSafeHandle();
|
||||
context = new HostExecutionContext(unkSafeHandle);
|
||||
|
||||
// call into the Hosting API to capture the host context
|
||||
// stores the output IUnknown in the safehandle,
|
||||
CaptureHostSecurityContext(unkSafeHandle);
|
||||
}
|
||||
|
||||
// otherwise
|
||||
return context;
|
||||
|
||||
}
|
||||
// Set Host SecurityContext
|
||||
[System.Security.SecurityCritical] // auto-generated_required
|
||||
public virtual Object SetHostExecutionContext(HostExecutionContext hostExecutionContext)
|
||||
{
|
||||
if (hostExecutionContext == null)
|
||||
{
|
||||
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotNewCaptureContext"));
|
||||
}
|
||||
Contract.EndContractBlock();
|
||||
|
||||
HostExecutionContextSwitcher switcher = new HostExecutionContextSwitcher();
|
||||
ExecutionContext currentExecutionContext = Thread.CurrentThread.GetMutableExecutionContext();
|
||||
|
||||
switcher.executionContext = currentExecutionContext;
|
||||
switcher.currentHostContext = hostExecutionContext;
|
||||
switcher.previousHostContext = null;
|
||||
|
||||
if (CheckIfHosted())
|
||||
{
|
||||
if (hostExecutionContext.State is IUnknownSafeHandle)
|
||||
{
|
||||
// setup the previous unknown handle
|
||||
IUnknownSafeHandle unkPrevSafeHandle = new IUnknownSafeHandle();
|
||||
switcher.previousHostContext = new HostExecutionContext(unkPrevSafeHandle);
|
||||
|
||||
// get the current handle
|
||||
IUnknownSafeHandle unkSafeHandle = (IUnknownSafeHandle)hostExecutionContext.State;
|
||||
|
||||
// call into the Hosting API to set the host context
|
||||
// second arg indicates whether we want to retrieve the previous context
|
||||
SetHostSecurityContext(unkSafeHandle,true,unkPrevSafeHandle);
|
||||
}
|
||||
}
|
||||
|
||||
// store the current HostExecutionContext in the ExecutionContext.
|
||||
currentExecutionContext.HostExecutionContext = hostExecutionContext;
|
||||
|
||||
return switcher;
|
||||
}
|
||||
|
||||
// this method needs to be reliable
|
||||
[System.Security.SecurityCritical] // auto-generated_required
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
|
||||
public virtual void Revert(Object previousState)
|
||||
{
|
||||
HostExecutionContextSwitcher hostContextSwitcher = previousState as HostExecutionContextSwitcher;
|
||||
if (hostContextSwitcher == null)
|
||||
{
|
||||
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CannotOverrideSetWithoutRevert"));
|
||||
}
|
||||
|
||||
// check Undo is happening on the correct thread
|
||||
ExecutionContext executionContext = Thread.CurrentThread.GetMutableExecutionContext();
|
||||
|
||||
if (executionContext != hostContextSwitcher.executionContext)
|
||||
{
|
||||
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CannotUseSwitcherOtherThread"));
|
||||
}
|
||||
hostContextSwitcher.executionContext = null; // Make sure switcher cannot be re-used.
|
||||
|
||||
HostExecutionContext revertFromHostContext = executionContext.HostExecutionContext;
|
||||
// if the current host context is not the same as the one in the switcher, then revert is being called out of order
|
||||
if (revertFromHostContext != hostContextSwitcher.currentHostContext)
|
||||
{
|
||||
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CannotUseSwitcherOtherThread"));
|
||||
}
|
||||
|
||||
// get the previous host context
|
||||
HostExecutionContext revertToHostContext = hostContextSwitcher.previousHostContext;
|
||||
|
||||
// now check if we are hosted and revert the context in the host
|
||||
if (CheckIfHosted())
|
||||
{
|
||||
// try restore the previous context as the current context
|
||||
if (revertToHostContext != null && revertToHostContext.State is IUnknownSafeHandle)
|
||||
{
|
||||
IUnknownSafeHandle unkprevSafeHandle = (IUnknownSafeHandle)revertToHostContext.State;
|
||||
// call into the Hosting API to set the host context
|
||||
SetHostSecurityContext(unkprevSafeHandle, false, null);
|
||||
}
|
||||
}
|
||||
|
||||
//restore the previous host context in the executioncontext
|
||||
executionContext.HostExecutionContext = revertToHostContext;
|
||||
|
||||
}
|
||||
|
||||
[System.Security.SecurityCritical] // auto-generated
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static HostExecutionContext CaptureHostExecutionContext()
|
||||
{
|
||||
HostExecutionContext hostContext = null;
|
||||
// capture the host execution context
|
||||
HostExecutionContextManager hostMgr = HostExecutionContextManager.GetCurrentHostExecutionContextManager();
|
||||
if (hostMgr != null)
|
||||
{
|
||||
hostContext = hostMgr.Capture();
|
||||
}
|
||||
return hostContext;
|
||||
}
|
||||
|
||||
[System.Security.SecurityCritical] // auto-generated
|
||||
internal static Object SetHostExecutionContextInternal(HostExecutionContext hostContext)
|
||||
{
|
||||
HostExecutionContextManager hostMgr = HostExecutionContextManager.GetCurrentHostExecutionContextManager();
|
||||
Object switcher = null;
|
||||
if (hostMgr != null)
|
||||
{
|
||||
switcher = hostMgr.SetHostExecutionContext(hostContext);
|
||||
//
|
||||
}
|
||||
return switcher;
|
||||
}
|
||||
|
||||
// retun the HostExecutionContextManager for the current AppDomain
|
||||
[System.Security.SecurityCritical] // auto-generated
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static HostExecutionContextManager GetCurrentHostExecutionContextManager()
|
||||
{
|
||||
// this is called during AppDomainManager initialization, this is a thread safe place
|
||||
// to setup the HostExecutionContextManager for the current AppDomain
|
||||
AppDomainManager mgr = AppDomainManager.CurrentAppDomainManager;
|
||||
if (mgr != null)
|
||||
return mgr.HostExecutionContextManager;
|
||||
return null;
|
||||
}
|
||||
|
||||
// retun the HostExecutionContextManager for the current AppDomain
|
||||
internal static HostExecutionContextManager GetInternalHostExecutionContextManager()
|
||||
{
|
||||
if (_hostExecutionContextManager == null) {
|
||||
// setup the HostExecutionContextManager for the current AppDomain
|
||||
Contract.Assert(_hostExecutionContextManager == null, "HostExecutionContextManager should be null");
|
||||
_hostExecutionContextManager = new HostExecutionContextManager();
|
||||
}
|
||||
return _hostExecutionContextManager;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user