// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
namespace System.Data.Entity
{
using System.IO;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
///
/// Represents a partial trust sandbox
///
public class PartialTrustSandbox : IDisposable
{
private static readonly PartialTrustSandbox _default = new PartialTrustSandbox("Default Partial Trust Sandbox");
private AppDomain _domain;
///
/// Constructs a new partial trust sandbox
///
/// Specify true to grant unrestricted reflection permission
/// Specify an alternate configuration file for the AppDoman. By default, the calling domain's will be used
///
/// If you do not need any special configuration, use the instance.
///
public PartialTrustSandbox(bool grantReflectionPermission = false, string configurationFile = null)
: this("Partial Trust Sandbox " + Guid.NewGuid(), grantReflectionPermission, configurationFile)
{
}
protected PartialTrustSandbox(string domainName, bool grantReflectionPermission = false, string configurationFile = null)
{
var securityConfig = Path.Combine(
RuntimeEnvironment.GetRuntimeDirectory(), "CONFIG",
"web_mediumtrust.config");
var permissionXml = File.ReadAllText(securityConfig).Replace("$AppDir$", Environment.CurrentDirectory);
// ASP.NET's configuration files still use the full policy levels rather than just permission sets,
// so we can either write a lot of code to parse them ourselves, or we can use a deprecated API to
// load them.
#pragma warning disable 0618
var grantSet =
SecurityManager.LoadPolicyLevelFromString(permissionXml, PolicyLevelType.AppDomain).
GetNamedPermissionSet("ASP.Net");
#pragma warning restore 0618
if (grantReflectionPermission)
{
grantSet.AddPermission(new ReflectionPermission(PermissionState.Unrestricted));
}
var info = new AppDomainSetup
{
ApplicationBase = Environment.CurrentDirectory,
PartialTrustVisibleAssemblies = new[]
{
// Add conditional APTCA assemblies that you need to access in partial trust here.
// Do NOT add System.Web here since at least one test relies on it not being treated as conditionally APTCA.
"System.ComponentModel.DataAnnotations, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9"
}
};
info.ConfigurationFile = configurationFile == null
? AppDomain.CurrentDomain.SetupInformation.ConfigurationFile
: configurationFile;
_domain = AppDomain.CreateDomain(domainName, null, info, grantSet, null);
}
~PartialTrustSandbox()
{
Dispose(false);
}
public static PartialTrustSandbox Default
{
get { return _default; }
}
///
/// Creates a new instance of the specified type in the partial trust sandbox and returns a proxy to it.
///
/// The type of object to create
/// A proxy to the instance created in the partial trust sandbox
public T CreateInstance()
{
return (T)CreateInstance(typeof(T));
}
///
/// Creates a new instance of the specified type in the partial trust sandbox and returns a proxy to it.
///
/// The type of object to create
/// A proxy to the instance created in the partial trust sandbox
public object CreateInstance(Type type)
{
HandleDisposed();
return _domain.CreateInstanceAndUnwrap(type.Assembly.FullName, type.FullName);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing
&& _domain != null)
{
AppDomain.Unload(_domain);
_domain = null;
}
}
private void HandleDisposed()
{
if (_domain == null)
{
throw new ObjectDisposedException(null);
}
}
}
}