ApplicationManager.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / xsp / System / Web / Hosting / ApplicationManager.cs / 1599808 / ApplicationManager.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

 
namespace System.Web.Hosting { 
    using System;
    using System.Collections; 
    using System.Collections.Generic;
    using System.Configuration;
    using System.Configuration.Internal;
    using System.Diagnostics.CodeAnalysis; 
    using System.Globalization;
    using System.IO; 
    using System.Runtime.InteropServices; 
    using System.Runtime.Remoting;
    using System.Security; 
    using System.Security.Permissions;
    using System.Security.Policy;
    using System.Threading;
    using System.Web; 
    using System.Web.Configuration;
    using System.Web.Util; 
    using System.Web.Compilation; 
    using System.Text;
    using System.Reflection; 

    public enum HostSecurityPolicyResults {
        DefaultPolicy = 0,
        FullTrust = 1, 
        AppDomainTrust = 2,
        Nothing = 3 
    }; 

    [PermissionSet(SecurityAction.InheritanceDemand, Unrestricted = true)] 
    public class HostSecurityPolicyResolver {
        public virtual HostSecurityPolicyResults ResolvePolicy(Evidence evidence) {
            return HostSecurityPolicyResults.DefaultPolicy;
        } 
    }
 
 

    internal class LockableAppDomainContext { 
        internal HostingEnvironment HostEnv { get; set; }
        internal string PreloadContext { get; set; }
        internal bool RetryingPreload { get; set; }
 
        internal LockableAppDomainContext() {
        } 
    } 

    public sealed class ApplicationManager : MarshalByRefObject { 

        private static Object _applicationManagerStaticLock = new Object();

        // open count (when last close goes to 0 it shuts down everything) 
        int _openCount = 0;
        bool _shutdownInProgress = false; 
 
        // table of app domains (LockableAppDomainContext objects) by app id
        // To simplify per-appdomain synchronization we will never remove LockableAppDomainContext objects from this table even when the AD is unloaded 
        // We may need to fix it if profiling shows a noticeable impact on performance
        private Dictionary  _appDomains = new Dictionary(StringComparer.OrdinalIgnoreCase);
        // count of HostingEnvironment instances that is referenced in _appDomains collection
        private int _accessibleHostingEnvCount; 

        // could differ from _appDomains or _accessibleHostingEnvCount count (host env is active some time after it is removed) 
        private int _activeHostingEnvCount; 

        // pending callback to respond to ping (typed as Object to do Interlocked operations) 
        private Object _pendingPingCallback;
        // delegate OnRespondToPing
        private WaitCallback _onRespondToPingWaitCallback;
 
        // single instance of app manager
        private static ApplicationManager _theAppManager; 
 
        // single instance of cache manager
        private static CacheManager _cm; 

        // store fatal exception to assist debugging
        private static Exception _fatalException = null;
 
        internal ApplicationManager() {
            _onRespondToPingWaitCallback = new WaitCallback(this.OnRespondToPingWaitCallback); 
 
            // VSWhidbey 555767: Need better logging for unhandled exceptions (http://support.microsoft.com/?id=911816)
            // We only add a handler in the default domain because it will be notified when an unhandled exception 
            // occurs in ANY domain.
            // WOS 1983175: (weird) only the handler in the default domain is notified when there is an AV in a native module
            // while we're in a call to MgdIndicateCompletion.
            AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(OnUnhandledException); 
        }
 
        private void InitCacheManager(long privateBytesLimit) { 
            if (_cm == null) {
                lock (_applicationManagerStaticLock) { 
                    if (_cm == null && !_shutdownInProgress) {
                        _cm = new CacheManager(this, privateBytesLimit);
                    }
                } 
            }
        } 
 
        private void DisposeCacheManager() {
            if (_cm != null) { 
                lock (_applicationManagerStaticLock) {
                    if (_cm != null) {
                        _cm.Dispose();
                        _cm = null; 
                    }
                } 
            } 
        }
 
        // Each cache must update the total with the difference between it's current size and it's previous size.
        // To reduce cross-domain costs, this also returns the updated total size.
        internal long GetUpdatedTotalCacheSize(long sizeUpdate) {
            CacheManager cm = _cm; 
            return (cm != null) ? cm.GetUpdatedTotalCacheSize(sizeUpdate) : 0;
        } 
 
        internal long TrimCaches(int percent) {
            long trimmedOrExpired = 0; 
            Dictionary apps = CloneAppDomainsCollection();
            foreach (LockableAppDomainContext ac in apps.Values) {
                lock (ac) {
                    HostingEnvironment env = ac.HostEnv; 
                    if (_shutdownInProgress) {
                        break; 
                    } 
                    if (env == null) {
                        continue; 
                    }
                    trimmedOrExpired += env.TrimCache(percent);
                }
            } 
            return trimmedOrExpired;
        } 
 
        internal bool ShutdownInProgress {
            get { 
                return _shutdownInProgress;
            }
        }
 
        internal static void RecordFatalException(Exception e) {
            RecordFatalException(AppDomain.CurrentDomain, e); 
        } 

        internal static void RecordFatalException(AppDomain appDomain, Exception e) { 
            // store the exception from the first caller to assist debugging
            object originalValue = Interlocked.CompareExchange(ref _fatalException, e, null);

            if (originalValue == null) { 
                // create event log entry
                Misc.WriteUnhandledExceptionToEventLog(appDomain, e); 
            } 
        }
 
        private static void OnUnhandledException(Object sender, UnhandledExceptionEventArgs eventArgs) {
            // if the CLR is not terminating, ignore the notification
            if (!eventArgs.IsTerminating) {
                return; 
            }
 
            Exception exception = eventArgs.ExceptionObject as Exception; 
            if (exception == null) {
                return; 
            }

            AppDomain appDomain = sender as AppDomain;
            if (appDomain == null) { 
                return;
            } 
 
            RecordFatalException(appDomain, exception);
        } 

        public override Object InitializeLifetimeService() {
            return null; // never expire lease
        } 

        // 
        // public ApplicationManager methods 
        //
 

        public static ApplicationManager GetApplicationManager() {
            if (_theAppManager == null) {
                lock (_applicationManagerStaticLock) { 
                    if (_theAppManager == null) {
                        if (HostingEnvironment.IsHosted) 
                            _theAppManager = HostingEnvironment.GetApplicationManager(); 

                        if (_theAppManager == null) 
                            _theAppManager = new ApplicationManager();
                    }
                }
            } 

            return _theAppManager; 
        } 

 
        [SecurityPermission(SecurityAction.Demand, Unrestricted=true)]
        public void Open() {
            Interlocked.Increment(ref _openCount);
        } 

 
        [SecurityPermission(SecurityAction.Demand, Unrestricted = true)] 
        public void Close() {
            if (Interlocked.Decrement(ref _openCount) > 0) 
                return;

            // need to shutdown everything
            ShutdownAll(); 
        }
 
        private string CreateSimpleAppID(VirtualPath virtualPath, string physicalPath, string siteName) { 
            // Put together some unique app id
            string appId = String.Concat(virtualPath.VirtualPathString, physicalPath); 

            if (!String.IsNullOrEmpty(siteName)) {
                appId = String.Concat(appId, siteName);
            } 

            return appId.GetHashCode().ToString("x", CultureInfo.InvariantCulture); 
        } 

        [SecurityPermission(SecurityAction.Demand, Unrestricted = true)] 
        public IRegisteredObject CreateObject(IApplicationHost appHost, Type type) {
            if (appHost == null) {
                throw new ArgumentNullException("appHost");
            } 
            if (type == null) {
                throw new ArgumentNullException("type"); 
            } 

            string appID = CreateSimpleAppID(appHost); 
            return CreateObjectInternal(appID, type, appHost, false);
        }

        [SecurityPermission(SecurityAction.Demand, UnmanagedCode=true)] 
        public IRegisteredObject CreateObject(String appId, Type type, string virtualPath, string physicalPath, bool failIfExists) {
            return CreateObject(appId, type, virtualPath, physicalPath, failIfExists, false /*throwOnError*/); 
        } 

        [SecurityPermission(SecurityAction.Demand, Unrestricted = true)] 
        public IRegisteredObject CreateObject(String appId, Type type, string virtualPath, string physicalPath,
                                              bool failIfExists, bool throwOnError) {
            // check args
            if (appId == null) 
                throw new ArgumentNullException("appId");
 
            SimpleApplicationHost appHost = new SimpleApplicationHost(VirtualPath.CreateAbsolute(virtualPath), physicalPath); 

            // if throw on error flag is set, create hosting parameters accordingly 
            HostingEnvironmentParameters hostingParameters = null;

            if (throwOnError) {
                hostingParameters = new HostingEnvironmentParameters(); 
                hostingParameters.HostingFlags = HostingEnvironmentFlags.ThrowHostingInitErrors;
 
            } 

            // call the internal method 
            return CreateObjectInternal(appId, type, appHost, failIfExists, hostingParameters);
        }

        [SecurityPermission(SecurityAction.Demand, Unrestricted = true)] 
        internal IRegisteredObject CreateObjectInternal(String appId, Type type, IApplicationHost appHost, bool failIfExists) {
            // check args 
            if (appId == null) 
                throw new ArgumentNullException("appId");
 
            if (type == null)
                throw new ArgumentNullException("type");

            if (appHost == null) 
                throw new ArgumentNullException("appHost");
 
            // call the internal method 
            return CreateObjectInternal(appId, type, appHost, failIfExists, null /*hostingParameters*/);
        } 

        [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
        internal IRegisteredObject CreateObjectInternal(
                                        String appId, 
                                        Type type,
                                        IApplicationHost appHost, 
                                        bool failIfExists, 
                                        HostingEnvironmentParameters hostingParameters) {
 
            // check that type is as IRegisteredObject
            if (!typeof(IRegisteredObject).IsAssignableFrom(type))
                throw new ArgumentException(SR.GetString(SR.Not_IRegisteredObject, type.FullName), "type");
 
            // get hosting environment
            HostingEnvironment env = GetAppDomainWithHostingEnvironment(appId, appHost, hostingParameters); 
 
            // create the managed object in the worker app domain
            // When marshaling Type, the AppDomain must have FileIoPermission to the assembly, which is not 
            // always the case, so we marshal the assembly qualified name instead
            ObjectHandle h = env.CreateWellKnownObjectInstance(type.AssemblyQualifiedName, failIfExists);
            return (h != null) ? h.Unwrap() as IRegisteredObject : null;
        } 

        internal IRegisteredObject CreateObjectWithDefaultAppHostAndAppId( 
                                        String physicalPath, 
                                        string virtualPath,
                                        Type type, 
                                        out String appId) {
            return CreateObjectWithDefaultAppHostAndAppId(physicalPath,
                VirtualPath.CreateNonRelative(virtualPath), type, out appId);
        } 

        internal IRegisteredObject CreateObjectWithDefaultAppHostAndAppId( 
                                        String physicalPath, 
                                        VirtualPath virtualPath,
                                        Type type, 
                                        out String appId) {

            HostingEnvironmentParameters hostingParameters = new HostingEnvironmentParameters();
            hostingParameters.HostingFlags = HostingEnvironmentFlags.DontCallAppInitialize; 

            return CreateObjectWithDefaultAppHostAndAppId( 
                        physicalPath, 
                        virtualPath,
                        type, 
                        false,
                        hostingParameters,
                        out appId);
        } 

        internal IRegisteredObject CreateObjectWithDefaultAppHostAndAppId( 
                                        String physicalPath, 
                                        VirtualPath virtualPath,
                                        Type type, 
                                        bool failIfExists,
                                        HostingEnvironmentParameters hostingParameters,
                                        out String appId) {
 
            IApplicationHost appHost;
#if !FEATURE_PAL // FEATURE_PAL does not enable IIS-based hosting features 
            if (physicalPath == null) { 

                // If the physical path is null, we use an ISAPIApplicationHost based 
                // on the virtual path (or metabase id).

                // Make sure the static HttpRuntime is created so isapi assembly can be loaded properly.
                HttpRuntime.ForceStaticInit(); 

                ISAPIApplicationHost isapiAppHost = new ISAPIApplicationHost(virtualPath.VirtualPathString, null, true); 
 
                appHost = isapiAppHost;
                appId = isapiAppHost.AppId; 
                virtualPath = VirtualPath.Create(appHost.GetVirtualPath());
                physicalPath = FileUtil.FixUpPhysicalDirectory(appHost.GetPhysicalPath());
            }
            else { 
#endif // !FEATURE_PAL
                // If the physical path was passed in, don't use an Isapi host. Instead, 
                // use a simple app host which does simple virtual to physical mappings 

                // Put together some unique app id 
                appId = CreateSimpleAppID(virtualPath, physicalPath, null);

                appHost = new SimpleApplicationHost(virtualPath, physicalPath);
            } 

            string precompTargetPhysicalDir = hostingParameters.PrecompilationTargetPhysicalDirectory; 
            if (precompTargetPhysicalDir != null) { 
                // Make sure the target physical dir has no relation with the source
                BuildManager.VerifyUnrelatedSourceAndDest(physicalPath, precompTargetPhysicalDir); 

                // Change the appID so we use a different codegendir in precompile for deployment scenario,
                // this ensures we don't use or pollute the regular codegen files.  Also, use different
                // ID's depending on whether the precompilation is Updatable (VSWhidbey 383239) 
                if ((hostingParameters.ClientBuildManagerParameter != null) &&
                    (hostingParameters.ClientBuildManagerParameter.PrecompilationFlags & PrecompilationFlags.Updatable) == 0) 
                    appId = appId + "_precompile"; 
                else
                    appId = appId + "_precompile_u"; 
            }

            return CreateObjectInternal(appId, type, appHost, failIfExists, hostingParameters);
        } 

 
        [SecurityPermission(SecurityAction.Demand, Unrestricted = true)] 
        public IRegisteredObject GetObject(String appId, Type type) {
            // check args 
            if (appId == null)
                throw new ArgumentNullException("appId");
            if (type == null)
                throw new ArgumentNullException("type"); 

            LockableAppDomainContext ac = GetLockableAppDomainContext(appId); 
            lock (ac) { 
                HostingEnvironment env = ac.HostEnv;
                if (env == null) 
                    return null;

                // find the instance by type
                // When marshaling Type, the AppDomain must have FileIoPermission to the assembly, which is not 
                // always the case, so we marshal the assembly qualified name instead
                ObjectHandle h = env.FindWellKnownObject(type.AssemblyQualifiedName); 
                return (h != null) ? h.Unwrap() as IRegisteredObject : null; 
            }
        } 

        [SecurityPermission(SecurityAction.Demand, Unrestricted = true)]
        public AppDomain GetAppDomain(string appId) {
            if (appId == null) { 
                throw new ArgumentNullException("appId");
            } 
 
            LockableAppDomainContext ac = GetLockableAppDomainContext(appId);
            lock (ac) { 
                HostingEnvironment env = ac.HostEnv;
                if (env == null) {
                    return null;
                } 

                return env.HostedAppDomain; 
            } 
        }
 
        public AppDomain GetAppDomain(IApplicationHost appHost) {
            if (appHost == null) {
                throw new ArgumentNullException("appHost");
            } 
            string appID = CreateSimpleAppID(appHost);
            return GetAppDomain(appID); 
        } 

        private string CreateSimpleAppID(IApplicationHost appHost) { 
            if (appHost == null) {
                throw new ArgumentNullException("appHost");
            }
            return CreateSimpleAppID(VirtualPath.Create(appHost.GetVirtualPath()), 
                                     appHost.GetPhysicalPath(), appHost.GetSiteName());
        } 
 

        // if a "well-known" object of the specified type already exists in the application, 
        // remove the app from the managed application table.  This is
        // used in IIS7 integrated mode when IIS7 determines that it is necessary to create
        // a new application and shutdown the old one.
        internal void RemoveFromTableIfRuntimeExists(String appId, Type runtimeType) { 
            // check args
            if (appId == null) 
                throw new ArgumentNullException("appId"); 
            if (runtimeType == null)
                throw new ArgumentNullException("runtimeType"); 

            LockableAppDomainContext ac = GetLockableAppDomainContext(appId);
            lock (ac) {
                // get hosting environment 
                HostingEnvironment env = ac.HostEnv;
                if (env == null) 
                    return; 

                // find the instance by type 
                // When marshaling Type, the AppDomain must have FileIoPermission to the assembly, which is not
                // always the case, so we marshal the assembly qualified name instead
                ObjectHandle h = env.FindWellKnownObject(runtimeType.AssemblyQualifiedName);
                if (h != null) 
                {
                    // ensure that it is removed from _appDomains by calling 
                    // HostingEnvironmentShutdownInitiated directly. 
                    HostingEnvironmentShutdownInitiated(appId, env);
                } 
            }
        }

        [SecurityPermission(SecurityAction.Demand, Unrestricted = true)] 
        public void StopObject(String appId, Type type) {
            // check args 
            if (appId == null) 
                throw new ArgumentNullException("appId");
            if (type == null) 
                throw new ArgumentNullException("type");

            LockableAppDomainContext ac = GetLockableAppDomainContext(appId);
            lock (ac) { 
                HostingEnvironment env = ac.HostEnv;
                if (env != null) { 
                    // When marshaling Type, the AppDomain must have FileIoPermission to the assembly, which is not 
                    // always the case, so we marshal the assembly qualified name instead
                    env.StopWellKnownObject(type.AssemblyQualifiedName); 
                }
            }
        }
 

        public bool IsIdle() { 
            Dictionary apps = CloneAppDomainsCollection(); 

            foreach (LockableAppDomainContext ac in apps.Values) { 
                lock (ac) {
                    HostingEnvironment env = ac.HostEnv;
                    bool idle = (null == env) ? true : env.IsIdle();
 
                    if (!idle)
                        return false; 
                } 
            }
 
            return true;
        }

 
        [SecurityPermission(SecurityAction.Demand, Unrestricted = true)]
        public void ShutdownApplication(String appId) { 
            if (appId == null) 
                throw new ArgumentNullException("appId");
 
            LockableAppDomainContext ac = GetLockableAppDomainContext(appId);
            lock (ac) {
                if (ac.HostEnv != null) {
                    ac.HostEnv.InitiateShutdownInternal(); 
                }
            } 
        } 

 
        [SecurityPermission(SecurityAction.Demand, Unrestricted = true)]
        public void ShutdownAll() {
            _shutdownInProgress = true;
            Dictionary  oldTable = null; 

            DisposeCacheManager(); 
 
            lock (this) {
                oldTable = _appDomains; 
                // don't keep references to hosting environments anymore
                _appDomains = new Dictionary(StringComparer.OrdinalIgnoreCase);
            }
 

            foreach (KeyValuePair  p in oldTable) { 
                LockableAppDomainContext ac = p.Value; 
                lock (ac) {
                    HostingEnvironment env = ac.HostEnv; 
                    if (null != env) {
                        env.InitiateShutdownInternal();
                    }
                } 
            }
 
            for (int iter=0; _activeHostingEnvCount > 0 && iter < 3000; iter++) // Wait at most 5 minutes 
                Thread.Sleep(100);
        } 


        [SecurityPermission(SecurityAction.Demand, Unrestricted = true)]
        public ApplicationInfo[] GetRunningApplications() { 
            ArrayList appList = new ArrayList();
 
            Dictionary apps = CloneAppDomainsCollection(); 

            foreach (LockableAppDomainContext ac in apps.Values) { 
                lock (ac) {
                    HostingEnvironment env = ac.HostEnv;
                    if (env != null) {
                        appList.Add(env.GetApplicationInfo()); 
                    }
                } 
            } 

            int n = appList.Count; 
            ApplicationInfo[] result = new ApplicationInfo[n];

            if (n > 0) {
                appList.CopyTo(result); 
            }
 
            return result; 
        }
 
        internal AppDomainInfo [] GetAppDomainInfos()
        {
            ArrayList appList = new ArrayList();
            Dictionary apps = CloneAppDomainsCollection(); 

            foreach (LockableAppDomainContext ac in apps.Values) { 
                lock (ac) { 
                    HostingEnvironment hostEnv = ac.HostEnv;
                    if (hostEnv == null) { 
                        continue;
                    }

                    IApplicationHost appHost = hostEnv.InternalApplicationHost; 
                    ApplicationInfo appInfo = hostEnv.GetApplicationInfo();
                    int siteId = 0; 
 
                    if (appHost != null) {
                        try { 
                            siteId = Int32.Parse(appHost.GetSiteID(), CultureInfo.InvariantCulture);
                        }
                        catch {
                        } 
                    }
 
                    AppDomainInfo appDomainInfo = new AppDomainInfo(appInfo.ID, 
                                                      appInfo.VirtualPath,
                                                      appInfo.PhysicalPath, 
                                                      siteId,
                                                      hostEnv.GetIdleValue());

                    appList.Add(appDomainInfo); 
                }
            } 
 
            return (AppDomainInfo[]) appList.ToArray(typeof(AppDomainInfo));
        } 

        //
        // ping implementation
        // 

        // called from process host 
        internal void Ping(IProcessPingCallback callback) { 
            if (callback == null || _pendingPingCallback != null)
                return; 

            // remember active callback but only if none is remembered already
            if (Interlocked.CompareExchange(ref _pendingPingCallback, callback, null) == null) {
                // queue a work item to respond to ping 
                ThreadPool.QueueUserWorkItem(_onRespondToPingWaitCallback);
            } 
        } 

        // threadpool callback (also called on some activity from hosting environment) 
        internal void OnRespondToPingWaitCallback(Object state) {
            RespondToPingIfNeeded();
        }
 
        // respond to ping on callback
        internal void RespondToPingIfNeeded() { 
            IProcessPingCallback callback = _pendingPingCallback as IProcessPingCallback; 

            // make sure we call the callback once 
            if (callback != null) {
                if (Interlocked.CompareExchange(ref _pendingPingCallback, null, callback) == callback) {
                    callback.Respond();
                } 
            }
        } 
 
        //
        // communication with hosting environments 
        //

        internal void HostingEnvironmentActivated(long privateBytesLimit) {
            int count = Interlocked.Increment(ref _activeHostingEnvCount); 

            // initialize CacheManager once, without blocking 
            if (count == 1) { 
                InitCacheManager(privateBytesLimit);
            } 
        }

        internal void HostingEnvironmentShutdownComplete(String appId, IApplicationHost appHost) {
            try { 
                if (appHost != null) {
                    // make sure application host can be GC'd 
                    MarshalByRefObject realApplicationHost = appHost as MarshalByRefObject; 
                    if (realApplicationHost != null) {
                        RemotingServices.Disconnect(realApplicationHost); 
                    }
                }
            }
            finally { 
                Interlocked.Decrement(ref _activeHostingEnvCount);
            } 
        } 

        internal void HostingEnvironmentShutdownInitiated(String appId, HostingEnvironment env) { 
            if (!_shutdownInProgress) { // don't bother during shutdown (while enumerating)
                LockableAppDomainContext ac = GetLockableAppDomainContext (appId);

                lock (ac){ 
                    if (!env.HasBeenRemovedFromAppManagerTable) {
                        env.HasBeenRemovedFromAppManagerTable = true; 
 
                        ac.HostEnv = null;
                        Interlocked.Decrement(ref _accessibleHostingEnvCount); 

                        // Autorestart the application right away
                        if (ac.PreloadContext != null && !ac.RetryingPreload) {
                            ProcessHost.PreloadApplicationIfNotShuttingdown(appId, ac); 
                        }
                    } 
                } 
            }
        } 

        internal int AppDomainsCount {
            get { return _accessibleHostingEnvCount; }
        } 

 
        internal void ReduceAppDomainsCount(int limit) { 
            //
 



            Dictionary apps = CloneAppDomainsCollection(); 
            while (_accessibleHostingEnvCount >= limit && !_shutdownInProgress)
            { 
                LockableAppDomainContext bestCandidateForShutdown = null; 
                int bestCandidateLruScore = 0;
 
                foreach (LockableAppDomainContext ac in apps.Values) {
                    // Don't lock on LockableAppDomainContext before we check that ac.HostEnv != null.
                    // Otherwise we may end up with a deadlock between 2 app domains trying to unload each other
                    HostingEnvironment h = ac.HostEnv; 
                    if (h == null) {
                        continue; 
                    } 
                    lock (ac) {
                        h = ac.HostEnv; 

                        // Avoid ---- by checking again under lock
                        if (h == null) {
                            continue; 
                        }
                        int newLruScore = h.LruScore; 
 
                        if (bestCandidateForShutdown == null || bestCandidateForShutdown.HostEnv == null ||
                                newLruScore < bestCandidateLruScore) { 

                            bestCandidateLruScore = newLruScore;
                            bestCandidateForShutdown = ac;
                        } 
                    }
                } 
 
                if (bestCandidateForShutdown == null)
                    break; 

                lock (bestCandidateForShutdown) {
                    if (bestCandidateForShutdown.HostEnv != null) {
                        bestCandidateForShutdown.HostEnv.InitiateShutdownInternal(); 
                    }
                } 
            } 
        }
 
        //
        // helper to support legacy APIs (AppHost.CreateAppHost)
        //
 
        internal ObjectHandle CreateInstanceInNewWorkerAppDomain(
                                Type type, 
                                String appId, 
                                VirtualPath virtualPath,
                                String physicalPath) { 

            Debug.Trace("AppManager", "CreateObjectInNewWorkerAppDomain, type=" + type.FullName);

            IApplicationHost appHost = new SimpleApplicationHost(virtualPath, physicalPath); 

            HostingEnvironmentParameters hostingParameters = new HostingEnvironmentParameters(); 
            hostingParameters.HostingFlags = HostingEnvironmentFlags.HideFromAppManager; 

            HostingEnvironment env = CreateAppDomainWithHostingEnvironmentAndReportErrors(appId, appHost, hostingParameters); 
            // When marshaling Type, the AppDomain must have FileIoPermission to the assembly, which is not
            // always the case, so we marshal the assembly qualified name instead
            return env.CreateInstance(type.AssemblyQualifiedName);
        } 

        // 
        // helpers to facilitate app domain creation 
        //
        private HostingEnvironment GetAppDomainWithHostingEnvironment(String appId, IApplicationHost appHost, HostingEnvironmentParameters hostingParameters) { 
            LockableAppDomainContext ac = GetLockableAppDomainContext (appId);

            lock (ac) {
                HostingEnvironment env = ac.HostEnv; 

                if (env != null) { 
                    try { 
                        env.IsUnloaded();
                    } catch(AppDomainUnloadedException) { 
                        env = null;
                    }
                }
                if (env == null) { 
                    env = CreateAppDomainWithHostingEnvironmentAndReportErrors(appId, appHost, hostingParameters);
                    ac.HostEnv = env; 
                    Interlocked.Increment(ref _accessibleHostingEnvCount); 
                }
 
                return env;
            }

        } 

        private HostingEnvironment CreateAppDomainWithHostingEnvironmentAndReportErrors( 
                                        String appId, 
                                        IApplicationHost appHost,
                                        HostingEnvironmentParameters hostingParameters) { 
            try {
                return CreateAppDomainWithHostingEnvironment(appId, appHost, hostingParameters);
            }
            catch (Exception e) { 
                Misc.ReportUnhandledException(e, new string[] {SR.GetString(SR.Failed_to_initialize_AppDomain), appId});
                throw; 
            } 
        }
 
        private HostingEnvironment CreateAppDomainWithHostingEnvironment(
                                                String appId,
                                                IApplicationHost appHost,
                                                HostingEnvironmentParameters hostingParameters) { 

            String physicalPath = appHost.GetPhysicalPath(); 
            if (!StringUtil.StringEndsWith(physicalPath, Path.DirectorySeparatorChar)) 
                physicalPath = physicalPath + Path.DirectorySeparatorChar;
 
            String domainId = ConstructAppDomainId(appId);
            String appName = (StringUtil.GetStringHashCode(String.Concat(appId.ToLower(CultureInfo.InvariantCulture),
                physicalPath.ToLower(CultureInfo.InvariantCulture)))).ToString("x", CultureInfo.InvariantCulture);
            VirtualPath virtualPath = VirtualPath.Create(appHost.GetVirtualPath()); 

            Debug.Trace("AppManager", "CreateAppDomainWithHostingEnvironment, path=" + physicalPath + "; appId=" + appId + "; domainId=" + domainId); 
 
            IDictionary bindings = new Hashtable(20);
            AppDomainSetup setup = new AppDomainSetup(); 
            PopulateDomainBindings(domainId, appId, appName, physicalPath, virtualPath, setup, bindings);

            //  Create the app domain
 
            AppDomain appDomain = null;
            Exception appDomainCreationException = null; 
 
            string siteID = appHost.GetSiteID();
            string appSegment = virtualPath.VirtualPathStringNoTrailingSlash; 
            bool isLegacyCas = false;
            bool inClientBuildManager = false;
            Configuration appConfig = null;
            PolicyLevel policyLevel = null; 
            PermissionSet permissionSet = null;
            StrongName[] fullTrustAssemblies = null; 
            string[] defaultPartialTrustVisibleAssemblies = new[] { "System.Web, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293", 
                                                                    "System.Web.Extensions, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9",
                                                                    "System.Web.Abstractions, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9", 
                                                                    "System.Web.Routing, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9",
                                                                    "System.ComponentModel.DataAnnotations, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9",
                                                                    "System.Web.DynamicData, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9",
                                                                    "System.Web.DataVisualization, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9", 
                                                                    "System.Web.ApplicationServices, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9" };
 
            Exception appDomainStartupConfigurationException = null; 
            ImpersonationContext ictxConfig = null;
            IntPtr uncTokenConfig = IntPtr.Zero; 
            HostingEnvironmentFlags hostingFlags = HostingEnvironmentFlags.Default;
            if (hostingParameters != null) {
                hostingFlags = hostingParameters.HostingFlags;
                if ((hostingFlags & HostingEnvironmentFlags.ClientBuildManager) != 0) { 
                    inClientBuildManager = true;
                    // The default hosting policy in VS has changed (from MultiDomainHost to MultiDomain), 
                    // so we need to specify explicitly to allow generated assemblies 
                    // to be unloaded subsequently. (Dev10 bug)
                    setup.LoaderOptimization = LoaderOptimization.MultiDomainHost; 
                }
            }
            try {
                uncTokenConfig = appHost.GetConfigToken(); 
                if (uncTokenConfig != IntPtr.Zero) {
                    ictxConfig = new ImpersonationContext(uncTokenConfig); 
                } 

                try { 
                    //Hosted by IIS, we already have an IISMap.
                    if (appHost is ISAPIApplicationHost) {
                        string cacheKey = System.Web.Caching.CacheInternal.PrefixMapPath + siteID + virtualPath.VirtualPathString;
                        MapPathCacheInfo cacheInfo = (MapPathCacheInfo)HttpRuntime.CacheInternal.Remove(cacheKey); 
                        appConfig = WebConfigurationManager.OpenWebConfiguration(appSegment, siteID);
                    } 
                    // For non-IIS hosting scenarios, we need to get config map from application host in a generic way. 
                    else {
                        WebConfigurationFileMap fileMap = new WebConfigurationFileMap(); 
                        IConfigMapPathFactory configMapPathFactory2 = appHost.GetConfigMapPathFactory();
                        IConfigMapPath configMapPath = configMapPathFactory2.Create(virtualPath.VirtualPathString, physicalPath);
                        string dir = null;
                        string fileName = null; 
                        string subDir = "/";
                        // add root mapping 
                        configMapPath.GetPathConfigFilename(siteID, subDir, out dir, out fileName); 
                        if (dir != null) {
                            fileMap.VirtualDirectories.Add(subDir, new VirtualDirectoryMapping(Path.GetFullPath(dir), true)); 
                        }
                        // add subdir mappings
                        string[] subDirs = appSegment.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
                        foreach (string s in subDirs) { 
                            subDir = subDir + s;
                            configMapPath.GetPathConfigFilename(siteID, subDir, out dir, out fileName); 
                            if (dir != null) { 
                                fileMap.VirtualDirectories.Add(subDir, new VirtualDirectoryMapping(Path.GetFullPath(dir), true));
                            } 
                            subDir = subDir + "/";
                        }
                        // open mapped web config for application
                        appConfig = WebConfigurationManager.OpenMappedWebConfiguration(fileMap, appSegment, siteID); 
                    }
                    TrustSection trustSection = (TrustSection)appConfig.GetSection("system.web/trust"); 
                    if (trustSection == null || String.IsNullOrEmpty(trustSection.Level)) { 
                        throw new ConfigurationErrorsException(SR.GetString(SR.Config_section_not_present, "trust"));
                    } 

                    bool trustSectionLegacyCasModel = trustSection.LegacyCasModel;
                    if (trustSectionLegacyCasModel) {
                        SetNetFx40LegacySecurityPolicy(setup); 
                    }
 
                    if (inClientBuildManager) { 
                        permissionSet = new PermissionSet(PermissionState.Unrestricted);
                        setup.PartialTrustVisibleAssemblies = defaultPartialTrustVisibleAssemblies; 
                    }
                    else {
                        isLegacyCas = trustSectionLegacyCasModel;
                        if (!isLegacyCas) { 
                            if (trustSection.Level == "Full") {
                                permissionSet = new PermissionSet(PermissionState.Unrestricted); 
                                setup.PartialTrustVisibleAssemblies = defaultPartialTrustVisibleAssemblies; 
                            }
                            else { 
                                SecurityPolicySection securityPolicySection = (SecurityPolicySection)appConfig.GetSection("system.web/securityPolicy");
                                CompilationSection compilationSection = (CompilationSection)appConfig.GetSection("system.web/compilation");
                                FullTrustAssembliesSection fullTrustAssembliesSection = (FullTrustAssembliesSection)appConfig.GetSection("system.web/fullTrustAssemblies");
                                policyLevel = GetPartialTrustPolicyLevel(trustSection, securityPolicySection, compilationSection, physicalPath, virtualPath); 
                                permissionSet = policyLevel.GetNamedPermissionSet(trustSection.PermissionSetName);
                                if (permissionSet == null) { 
                                    throw new ConfigurationErrorsException(SR.GetString(SR.Permission_set_not_found, trustSection.PermissionSetName)); 
                                }
 
                                //read full trust assemblies and populate the strong name list.
                                if (fullTrustAssembliesSection != null) {
                                    FullTrustAssemblyCollection fullTrustAssembliesCollection = fullTrustAssembliesSection.FullTrustAssemblies;
                                    if (fullTrustAssembliesCollection != null && fullTrustAssembliesCollection.Count != 0) { 
                                        fullTrustAssemblies = new StrongName[fullTrustAssembliesCollection.Count];
                                        for (int i = 0; i < fullTrustAssembliesCollection.Count; i++) { 
                                            fullTrustAssemblies[i] = CreateStrongName(fullTrustAssembliesCollection[i].AssemblyName, 
                                                                                      fullTrustAssembliesCollection[i].Version,
                                                                                      fullTrustAssembliesCollection[i].PublicKey); 
                                        }
                                    }
                                }
 
                                // Setup HostSecurityManager
                                setup.AppDomainManagerType = typeof(AspNetAppDomainManager).FullName; 
                                setup.AppDomainManagerAssembly = typeof(AspNetAppDomainManager).Assembly.FullName; 
                            }
                        } 
                        if (trustSection.Level != "Full") {
                            PartialTrustVisibleAssembliesSection partialTrustVisibleAssembliesSection = (PartialTrustVisibleAssembliesSection)appConfig.GetSection("system.web/partialTrustVisibleAssemblies");
                            string[] partialTrustVisibleAssemblies = null;
                            if (partialTrustVisibleAssembliesSection != null) { 
                                PartialTrustVisibleAssemblyCollection partialTrustVisibleAssembliesCollection = partialTrustVisibleAssembliesSection.PartialTrustVisibleAssemblies;
                                if (partialTrustVisibleAssembliesCollection != null && partialTrustVisibleAssembliesCollection.Count != 0) { 
                                    partialTrustVisibleAssemblies = new string[partialTrustVisibleAssembliesCollection.Count + defaultPartialTrustVisibleAssemblies.Length]; 
                                    for (int i = 0; i < partialTrustVisibleAssembliesCollection.Count; i++) {
                                        partialTrustVisibleAssemblies[i] = partialTrustVisibleAssembliesCollection[i].AssemblyName + 
                                            ", PublicKey=" +
                                            NormalizePublicKeyBlob(partialTrustVisibleAssembliesCollection[i].PublicKey);
                                    }
                                    defaultPartialTrustVisibleAssemblies.CopyTo(partialTrustVisibleAssemblies, partialTrustVisibleAssembliesCollection.Count); 
                                }
                            } 
                            if (partialTrustVisibleAssemblies == null) { 
                                partialTrustVisibleAssemblies = defaultPartialTrustVisibleAssemblies;
                            } 
                            setup.PartialTrustVisibleAssemblies = partialTrustVisibleAssemblies;
                        }
                    }
                } 
                catch (Exception e) {
                    appDomainStartupConfigurationException = e; 
                    permissionSet = new PermissionSet(PermissionState.Unrestricted); 
                }
 
                try {
                    if (isLegacyCas) {
                        appDomain = AppDomain.CreateDomain(domainId,
#if FEATURE_PAL // FEATURE_PAL: hack to avoid non-supported hosting features 
                                                           null,
#else // FEATURE_PAL 
GetDefaultDomainIdentity(), 
#endif // FEATURE_PAL
setup); 
                    }
                    else {
                        appDomain = AppDomain.CreateDomain(domainId,
#if FEATURE_PAL // FEATURE_PAL: hack to avoid non-supported hosting features 
                                                           null,
#else // FEATURE_PAL 
GetDefaultDomainIdentity(), 
#endif // FEATURE_PAL
setup, 
                                                           permissionSet,
                                                           fullTrustAssemblies /* fully trusted assemblies list: null means only trust GAC assemblies */);
                    }
                    foreach (DictionaryEntry e in bindings) 
                        appDomain.SetData((String)e.Key, (String)e.Value);
                } 
                catch (Exception e) { 
                    Debug.Trace("AppManager", "AppDomain.CreateDomain failed", e);
                    appDomainCreationException = e; 
                }
            }
            finally {
                if (ictxConfig != null) { 
                    ictxConfig.Undo();
                    ictxConfig = null; 
                } 
                if (uncTokenConfig != IntPtr.Zero) {
                    UnsafeNativeMethods.CloseHandle(uncTokenConfig); 
                    uncTokenConfig = IntPtr.Zero;
                }
            }
 
            if (appDomain == null) {
                throw new SystemException(SR.GetString(SR.Cannot_create_AppDomain), appDomainCreationException); 
            } 

            // Create hosting environment in the new app domain 

            Type hostType = typeof(HostingEnvironment);
            String module = hostType.Module.Assembly.FullName;
            String typeName = hostType.FullName; 
            ObjectHandle h = null;
 
            // impersonate UNC identity, if any 
            ImpersonationContext ictx = null;
            IntPtr uncToken = IntPtr.Zero; 

            //
            // fetching config can fail due to a ---- with the
            // native config reader 
            // if that has happened, force a flush
            // 
            int maxRetries = 10; 
            int numRetries = 0;
 
            while (numRetries < maxRetries) {
                try {
                    uncToken = appHost.GetConfigToken();
                    // no throw, so break 
                    break;
                } 
                catch (InvalidOperationException) { 
                    numRetries++;
                    System.Threading.Thread.Sleep(250); 
                }
            }

 
            if (uncToken != IntPtr.Zero) {
                try { 
                    ictx = new ImpersonationContext(uncToken); 
                }
                catch { 
                }
                finally {
                    UnsafeNativeMethods.CloseHandle(uncToken);
                } 
            }
 
            try { 

                // Create the hosting environment in the app domain 
#if DBG
                try {
                    h = Activator.CreateInstance(appDomain, module, typeName);
                } 
                catch (Exception e) {
                    Debug.Trace("AppManager", "appDomain.CreateInstance failed; identity=" + System.Security.Principal.WindowsIdentity.GetCurrent().Name, e); 
                    throw; 
                }
#else 
                h = Activator.CreateInstance(appDomain, module, typeName);
#endif
            }
            finally { 
                // revert impersonation
                if (ictx != null) 
                    ictx.Undo(); 

                if (h == null) { 
                    AppDomain.Unload(appDomain);
                }
            }
 
            HostingEnvironment env = (h != null) ? h.Unwrap() as HostingEnvironment : null;
 
            if (env == null) 
                throw new SystemException(SR.GetString(SR.Cannot_create_HostEnv));
 
            // iniitalize the hosting environment
            IConfigMapPathFactory configMapPathFactory = appHost.GetConfigMapPathFactory();
            if (appDomainStartupConfigurationException == null) {
                env.Initialize(this, appHost, configMapPathFactory, hostingParameters, policyLevel); 
            }
            else { 
                env.Initialize(this, appHost, configMapPathFactory, hostingParameters, policyLevel, appDomainStartupConfigurationException); 
            }
            return env; 
        }

        private static void SetNetFx40LegacySecurityPolicy(AppDomainSetup setup) {
            // Allow the appdomain to use legacy CAS 
            var compatSwitches = new List();
            compatSwitches.Add("NetFx40_LegacySecurityPolicy"); 
            setup.SetCompatibilitySwitches(compatSwitches); 
        }
 
        private static string NormalizePublicKeyBlob(string publicKey) {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < publicKey.Length; i++) {
                if (!Char.IsWhiteSpace(publicKey[i])) { 
                    sb.Append(publicKey[i]);
                } 
            } 
            publicKey = sb.ToString();
            return publicKey; 
        }

        private static StrongName CreateStrongName(string assemblyName, string version, string publicKeyString) {
            byte[] publicKey = null; 
            StrongName strongName = null;
            publicKeyString = NormalizePublicKeyBlob(publicKeyString); 
            int publicKeySize = publicKeyString.Length / 2; 
            publicKey = new byte[publicKeySize];
            for (int i = 0; i < publicKeySize; i++) { 
                publicKey[i] = Byte.Parse(publicKeyString.Substring(i * 2, 2), System.Globalization.NumberStyles.HexNumber, CultureInfo.InvariantCulture);
            }
            StrongNamePublicKeyBlob keyBlob = new StrongNamePublicKeyBlob(publicKey);
            strongName = new StrongName(keyBlob, assemblyName, new Version(version)); 
            return strongName;
        } 
 
        private static PolicyLevel GetPartialTrustPolicyLevel(
                TrustSection trustSection, SecurityPolicySection securityPolicySection, 
                CompilationSection compilationSection, string physicalPath, VirtualPath virtualPath) {
            if (securityPolicySection == null || securityPolicySection.TrustLevels[trustSection.Level] == null) {
                throw new ConfigurationErrorsException(SR.GetString(SR.Unable_to_get_policy_file, trustSection.Level), String.Empty, 0);
            } 
            String configFile = (String)securityPolicySection.TrustLevels[trustSection.Level].PolicyFileExpanded;
            if (configFile == null || !FileUtil.FileExists(configFile)) { 
                throw new HttpException(SR.GetString(SR.Unable_to_get_policy_file, trustSection.Level)); 
            }
            PolicyLevel policyLevel = null; 
            String appDir = FileUtil.RemoveTrailingDirectoryBackSlash(physicalPath);
            String appDirUrl = HttpRuntime.MakeFileUrl(appDir);

            // setup $CodeGen$ replacement 
            string tempDirectory = null;
            // These variables are used for error handling 
            string tempDirAttribName = null; 
            string configFileName = null;
            int configLineNumber = 0; 
            if (compilationSection != null && !String.IsNullOrEmpty(compilationSection.TempDirectory)) {
                tempDirectory = compilationSection.TempDirectory;
                compilationSection.GetTempDirectoryErrorInfo(out tempDirAttribName,
                    out configFileName, out configLineNumber); 
            }
            if (tempDirectory != null) { 
                tempDirectory = tempDirectory.Trim(); 
                if (!Path.IsPathRooted(tempDirectory)) {
                    // Make sure the path is not relative (VSWhidbey 260075) 
                    tempDirectory = null;
                }
                else {
                    try { 
                        // Canonicalize it to avoid problems with spaces (VSWhidbey 229873)
                        tempDirectory = new DirectoryInfo(tempDirectory).FullName; 
                    } 
                    catch {
                        tempDirectory = null; 
                    }
                }
                if (tempDirectory == null) {
                    throw new ConfigurationErrorsException( 
                        SR.GetString(SR.Invalid_temp_directory, tempDirAttribName),
                        configFileName, configLineNumber); 
                } 
                // Create the config-specified directory if needed
                try { 
                    Directory.CreateDirectory(tempDirectory);
                }
                catch (Exception e) {
                    throw new ConfigurationErrorsException( 
                        SR.GetString(SR.Invalid_temp_directory, tempDirAttribName),
                        e, 
                        configFileName, configLineNumber); 
                }
            } 
            else {
                tempDirectory = Path.Combine(RuntimeEnvironment.GetRuntimeDirectory(), HttpRuntime.codegenDirName);
            }
            // If we don't have write access to the codegen dir, use the TEMP dir instead. 
            // This will allow non-admin users to work in hosting scenarios (e.g. Venus, aspnet_compiler)
            if (!System.Web.UI.Util.HasWriteAccessToDirectory(tempDirectory)) { 
                // Don't do this if we're in a service (!UserInteractive), as TEMP 
                // could point to unwanted places.
                if (!Environment.UserInteractive) { 
                    throw new HttpException(SR.GetString(SR.No_codegen_access,
                        System.Web.UI.Util.GetCurrentAccountName(), tempDirectory));
                }
                tempDirectory = Path.GetTempPath(); 
                Debug.Assert(System.Web.UI.Util.HasWriteAccessToDirectory(tempDirectory));
                tempDirectory = Path.Combine(tempDirectory, HttpRuntime.codegenDirName); 
            } 
            String simpleAppName = System.Web.Hosting.AppManagerAppDomainFactory.ConstructSimpleAppName(
                VirtualPath.GetVirtualPathStringNoTrailingSlash(virtualPath)); 
            String binDir = Path.Combine(tempDirectory, simpleAppName);
            binDir = FileUtil.RemoveTrailingDirectoryBackSlash(binDir);
            String binDirUrl = HttpRuntime.MakeFileUrl(binDir);
 
            String originUrl = trustSection.OriginUrl;
            FileStream file = new FileStream(configFile, FileMode.Open, FileAccess.Read); 
            StreamReader reader = new StreamReader(file, Encoding.UTF8); 
            String strFileData = reader.ReadToEnd();
            reader.Close(); 
            strFileData = strFileData.Replace("$AppDir$", appDir);
            strFileData = strFileData.Replace("$AppDirUrl$", appDirUrl);
            strFileData = strFileData.Replace("$CodeGen$", binDirUrl);
            if (originUrl == null) 
                originUrl = String.Empty;
            strFileData = strFileData.Replace("$OriginHost$", originUrl); 
            String gacLocation = null; 
            if (strFileData.IndexOf("$Gac$", StringComparison.Ordinal) != -1) {
                gacLocation = HttpRuntime.GetGacLocation(); 
                if (gacLocation != null)
                    gacLocation = HttpRuntime.MakeFileUrl(gacLocation);
                if (gacLocation == null)
                    gacLocation = String.Empty; 
                strFileData = strFileData.Replace("$Gac$", gacLocation);
            } 
#pragma warning disable 618 // ASP is reading their grant set out of legacy policy level files 
            policyLevel = SecurityManager.LoadPolicyLevelFromString(strFileData, PolicyLevelType.AppDomain);
            if (policyLevel == null) { 
                throw new ConfigurationErrorsException(SR.GetString(SR.Unable_to_get_policy_file, trustSection.Level));
            }
            // Found GAC Token
            if (gacLocation != null) { 
                // walk the code groups at the app domain level and look for one that grants
                // access to the GAC with an UrlMembershipCondition. 
                CodeGroup rootGroup = policyLevel.RootCodeGroup; 
                bool foundGacCondition = false;
                foreach (CodeGroup childGroup in rootGroup.Children) { 
                    if (childGroup.MembershipCondition is GacMembershipCondition) {
                        foundGacCondition = true;
                        // if we found the GAC token and also have the GacMembershipCondition
                        // the policy file needs to be upgraded to just include the GacMembershipCondition 
                        Debug.Assert(!foundGacCondition);
                        break; 
                    } 
                }
                // add one as a child of the toplevel group after 
                // some sanity checking to make sure it's an ASP.NET policy file
                // which always begins with a FirstMatchCodeGroup granting nothing
                // this might not upgrade some custom policy files
                if (!foundGacCondition) { 
                    if (rootGroup is FirstMatchCodeGroup) {
                        FirstMatchCodeGroup firstMatch = (FirstMatchCodeGroup)rootGroup; 
                        if (firstMatch.MembershipCondition is AllMembershipCondition && 
                            firstMatch.PermissionSetName == "Nothing") {
                            PermissionSet fullTrust = new PermissionSet(PermissionState.Unrestricted); 
                            CodeGroup gacGroup = new UnionCodeGroup(new GacMembershipCondition(),
                                                                    new PolicyStatement(fullTrust));
                            // now, walk the current groups and insert our new group immediately before the old Gac group
                            // we'll need to use heuristics for this: it will be an UrlMembershipCondition group with full trust 
                            CodeGroup newRoot = new FirstMatchCodeGroup(rootGroup.MembershipCondition, rootGroup.PolicyStatement);
                            foreach (CodeGroup childGroup in rootGroup.Children) { 
                                // is this the target old $Gac$ group? 
                                // insert our new GacMembershipCondition group ahead of it
                                if ((childGroup is UnionCodeGroup) && 
                                    (childGroup.MembershipCondition is UrlMembershipCondition) &&
                                    childGroup.PolicyStatement.PermissionSet.IsUnrestricted()) {
                                    if (null != gacGroup) {
                                        newRoot.AddChild(gacGroup); 
                                        gacGroup = null;
                                    } 
                                } 
                                // append this group to the root group
                                // AddChild itself does a deep Copy to get any 
                                // child groups so we don't need one here
                                newRoot.AddChild(childGroup);
                            }
                            policyLevel.RootCodeGroup = newRoot; 
                        }
                    } 
                } 
            }
            return policyLevel; 
#pragma warning restore 618
        }

        internal class AspNetAppDomainManager : AppDomainManager { 
            private HostSecurityManager aspNetHostSecurityManager = null;
 
            public AspNetAppDomainManager() { 
                aspNetHostSecurityManager = new AspNetHostSecurityManager();
            } 

            public override HostSecurityManager HostSecurityManager {
                get {
                    return aspNetHostSecurityManager; 
                }
            } 
        } 

        internal class AspNetHostSecurityManager : HostSecurityManager { 
            private PermissionSet Nothing = new PermissionSet(PermissionState.None);
            private PermissionSet FullTrust = new PermissionSet(PermissionState.Unrestricted);
            private HostSecurityPolicyResolver hostSecurityPolicyResolver = null;
 
            public override HostSecurityManagerOptions Flags {
                get { 
                    return HostSecurityManagerOptions.HostResolvePolicy; 
                }
            } 

            [SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.SerializationFormatter)]
            public override PermissionSet ResolvePolicy(Evidence evidence) {
                if (base.ResolvePolicy(evidence).IsUnrestricted()) { 
                    return FullTrust;
                } 
 
                if (!String.IsNullOrEmpty(HttpRuntime.HostSecurityPolicyResolverType) && hostSecurityPolicyResolver == null) {
                    hostSecurityPolicyResolver = Activator.CreateInstance( 
                        Type.GetType(HttpRuntime.HostSecurityPolicyResolverType)) as HostSecurityPolicyResolver;
                }

                if (hostSecurityPolicyResolver != null) { 
                    switch (hostSecurityPolicyResolver.ResolvePolicy(evidence)) {
                        case HostSecurityPolicyResults.FullTrust: 
                            return FullTrust; 
                        case HostSecurityPolicyResults.AppDomainTrust:
                            return HttpRuntime.NamedPermissionSet; 
                        case HostSecurityPolicyResults.Nothing:
                            return Nothing;
                        case HostSecurityPolicyResults.DefaultPolicy:
                            break; 
                    }
                } 
 
                if (HttpRuntime.PolicyLevel == null || HttpRuntime.PolicyLevel.Resolve(evidence).PermissionSet.IsUnrestricted())
                    return FullTrust; 
                else if (HttpRuntime.PolicyLevel.Resolve(evidence).PermissionSet.Equals(Nothing))
                    return Nothing;
                else
                    return HttpRuntime.NamedPermissionSet; 
            }
        } 
 
        private static void PopulateDomainBindings(String domainId, String appId, String appName,
                                                    String appPath, VirtualPath appVPath, 
                                                    AppDomainSetup setup, IDictionary dict) {
            // assembly loading settings

            // We put both the old and new bin dir names on the private bin path 
            setup.PrivateBinPathProbe   = "*";  // disable loading from app base
            setup.ShadowCopyFiles       = "true"; 
            setup.ApplicationBase       = appPath; 
            setup.ApplicationName       = appName;
            setup.ConfigurationFile     = HttpConfigurationSystem.WebConfigFileName; 

            // Disallow code download, since it's unreliable in services (ASURT 123836/127606)
            setup.DisallowCodeDownload  = true;
 
            // internal settings
            dict.Add(".appDomain",     "*"); 
            dict.Add(".appId",         appId); 
            dict.Add(".appPath",       appPath);
            dict.Add(".appVPath",      appVPath.VirtualPathString); 
            dict.Add(".domainId",      domainId);
        }

        private static Evidence GetDefaultDomainIdentity() { 
            Evidence evidence = AppDomain.CurrentDomain.Evidence; // CurrentDomain.Evidence returns a clone so we can modify it if we need
            bool hasZone = evidence.GetHostEvidence() != null; 
            bool hasUrl = evidence.GetHostEvidence() != null; 

            if (!hasZone) 
                evidence.AddHostEvidence(new Zone(SecurityZone.MyComputer));

            if (!hasUrl)
                evidence.AddHostEvidence(new Url("ms-internal-microsoft-asp-net-webhost-20")); 

            return evidence; 
        } 

        private static int s_domainCount = 0; 
        private static Object s_domainCountLock = new Object();

        private static String ConstructAppDomainId(String id) {
            int domainCount = 0; 
            lock (s_domainCountLock) {
                domainCount = ++s_domainCount; 
            } 
            return id + "-" + domainCount.ToString(NumberFormatInfo.InvariantInfo) + "-" + DateTime.UtcNow.ToFileTime().ToString();
        } 

        internal LockableAppDomainContext GetLockableAppDomainContext (string appId) {
            lock (this) {
                LockableAppDomainContext ac; 
                if (!_appDomains.TryGetValue(appId, out ac)) {
                    ac = new LockableAppDomainContext(); 
                    _appDomains.Add (appId, ac); 
                }
 
                return ac;
            }
        }
 
        // take a copy of _appDomains collection so that it can be used without locking on ApplicationManager
        private Dictionary CloneAppDomainsCollection() { 
            lock (this) { 
                return new Dictionary(_appDomains, StringComparer.OrdinalIgnoreCase);
            } 
        }

    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

 
namespace System.Web.Hosting { 
    using System;
    using System.Collections; 
    using System.Collections.Generic;
    using System.Configuration;
    using System.Configuration.Internal;
    using System.Diagnostics.CodeAnalysis; 
    using System.Globalization;
    using System.IO; 
    using System.Runtime.InteropServices; 
    using System.Runtime.Remoting;
    using System.Security; 
    using System.Security.Permissions;
    using System.Security.Policy;
    using System.Threading;
    using System.Web; 
    using System.Web.Configuration;
    using System.Web.Util; 
    using System.Web.Compilation; 
    using System.Text;
    using System.Reflection; 

    public enum HostSecurityPolicyResults {
        DefaultPolicy = 0,
        FullTrust = 1, 
        AppDomainTrust = 2,
        Nothing = 3 
    }; 

    [PermissionSet(SecurityAction.InheritanceDemand, Unrestricted = true)] 
    public class HostSecurityPolicyResolver {
        public virtual HostSecurityPolicyResults ResolvePolicy(Evidence evidence) {
            return HostSecurityPolicyResults.DefaultPolicy;
        } 
    }
 
 

    internal class LockableAppDomainContext { 
        internal HostingEnvironment HostEnv { get; set; }
        internal string PreloadContext { get; set; }
        internal bool RetryingPreload { get; set; }
 
        internal LockableAppDomainContext() {
        } 
    } 

    public sealed class ApplicationManager : MarshalByRefObject { 

        private static Object _applicationManagerStaticLock = new Object();

        // open count (when last close goes to 0 it shuts down everything) 
        int _openCount = 0;
        bool _shutdownInProgress = false; 
 
        // table of app domains (LockableAppDomainContext objects) by app id
        // To simplify per-appdomain synchronization we will never remove LockableAppDomainContext objects from this table even when the AD is unloaded 
        // We may need to fix it if profiling shows a noticeable impact on performance
        private Dictionary  _appDomains = new Dictionary(StringComparer.OrdinalIgnoreCase);
        // count of HostingEnvironment instances that is referenced in _appDomains collection
        private int _accessibleHostingEnvCount; 

        // could differ from _appDomains or _accessibleHostingEnvCount count (host env is active some time after it is removed) 
        private int _activeHostingEnvCount; 

        // pending callback to respond to ping (typed as Object to do Interlocked operations) 
        private Object _pendingPingCallback;
        // delegate OnRespondToPing
        private WaitCallback _onRespondToPingWaitCallback;
 
        // single instance of app manager
        private static ApplicationManager _theAppManager; 
 
        // single instance of cache manager
        private static CacheManager _cm; 

        // store fatal exception to assist debugging
        private static Exception _fatalException = null;
 
        internal ApplicationManager() {
            _onRespondToPingWaitCallback = new WaitCallback(this.OnRespondToPingWaitCallback); 
 
            // VSWhidbey 555767: Need better logging for unhandled exceptions (http://support.microsoft.com/?id=911816)
            // We only add a handler in the default domain because it will be notified when an unhandled exception 
            // occurs in ANY domain.
            // WOS 1983175: (weird) only the handler in the default domain is notified when there is an AV in a native module
            // while we're in a call to MgdIndicateCompletion.
            AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(OnUnhandledException); 
        }
 
        private void InitCacheManager(long privateBytesLimit) { 
            if (_cm == null) {
                lock (_applicationManagerStaticLock) { 
                    if (_cm == null && !_shutdownInProgress) {
                        _cm = new CacheManager(this, privateBytesLimit);
                    }
                } 
            }
        } 
 
        private void DisposeCacheManager() {
            if (_cm != null) { 
                lock (_applicationManagerStaticLock) {
                    if (_cm != null) {
                        _cm.Dispose();
                        _cm = null; 
                    }
                } 
            } 
        }
 
        // Each cache must update the total with the difference between it's current size and it's previous size.
        // To reduce cross-domain costs, this also returns the updated total size.
        internal long GetUpdatedTotalCacheSize(long sizeUpdate) {
            CacheManager cm = _cm; 
            return (cm != null) ? cm.GetUpdatedTotalCacheSize(sizeUpdate) : 0;
        } 
 
        internal long TrimCaches(int percent) {
            long trimmedOrExpired = 0; 
            Dictionary apps = CloneAppDomainsCollection();
            foreach (LockableAppDomainContext ac in apps.Values) {
                lock (ac) {
                    HostingEnvironment env = ac.HostEnv; 
                    if (_shutdownInProgress) {
                        break; 
                    } 
                    if (env == null) {
                        continue; 
                    }
                    trimmedOrExpired += env.TrimCache(percent);
                }
            } 
            return trimmedOrExpired;
        } 
 
        internal bool ShutdownInProgress {
            get { 
                return _shutdownInProgress;
            }
        }
 
        internal static void RecordFatalException(Exception e) {
            RecordFatalException(AppDomain.CurrentDomain, e); 
        } 

        internal static void RecordFatalException(AppDomain appDomain, Exception e) { 
            // store the exception from the first caller to assist debugging
            object originalValue = Interlocked.CompareExchange(ref _fatalException, e, null);

            if (originalValue == null) { 
                // create event log entry
                Misc.WriteUnhandledExceptionToEventLog(appDomain, e); 
            } 
        }
 
        private static void OnUnhandledException(Object sender, UnhandledExceptionEventArgs eventArgs) {
            // if the CLR is not terminating, ignore the notification
            if (!eventArgs.IsTerminating) {
                return; 
            }
 
            Exception exception = eventArgs.ExceptionObject as Exception; 
            if (exception == null) {
                return; 
            }

            AppDomain appDomain = sender as AppDomain;
            if (appDomain == null) { 
                return;
            } 
 
            RecordFatalException(appDomain, exception);
        } 

        public override Object InitializeLifetimeService() {
            return null; // never expire lease
        } 

        // 
        // public ApplicationManager methods 
        //
 

        public static ApplicationManager GetApplicationManager() {
            if (_theAppManager == null) {
                lock (_applicationManagerStaticLock) { 
                    if (_theAppManager == null) {
                        if (HostingEnvironment.IsHosted) 
                            _theAppManager = HostingEnvironment.GetApplicationManager(); 

                        if (_theAppManager == null) 
                            _theAppManager = new ApplicationManager();
                    }
                }
            } 

            return _theAppManager; 
        } 

 
        [SecurityPermission(SecurityAction.Demand, Unrestricted=true)]
        public void Open() {
            Interlocked.Increment(ref _openCount);
        } 

 
        [SecurityPermission(SecurityAction.Demand, Unrestricted = true)] 
        public void Close() {
            if (Interlocked.Decrement(ref _openCount) > 0) 
                return;

            // need to shutdown everything
            ShutdownAll(); 
        }
 
        private string CreateSimpleAppID(VirtualPath virtualPath, string physicalPath, string siteName) { 
            // Put together some unique app id
            string appId = String.Concat(virtualPath.VirtualPathString, physicalPath); 

            if (!String.IsNullOrEmpty(siteName)) {
                appId = String.Concat(appId, siteName);
            } 

            return appId.GetHashCode().ToString("x", CultureInfo.InvariantCulture); 
        } 

        [SecurityPermission(SecurityAction.Demand, Unrestricted = true)] 
        public IRegisteredObject CreateObject(IApplicationHost appHost, Type type) {
            if (appHost == null) {
                throw new ArgumentNullException("appHost");
            } 
            if (type == null) {
                throw new ArgumentNullException("type"); 
            } 

            string appID = CreateSimpleAppID(appHost); 
            return CreateObjectInternal(appID, type, appHost, false);
        }

        [SecurityPermission(SecurityAction.Demand, UnmanagedCode=true)] 
        public IRegisteredObject CreateObject(String appId, Type type, string virtualPath, string physicalPath, bool failIfExists) {
            return CreateObject(appId, type, virtualPath, physicalPath, failIfExists, false /*throwOnError*/); 
        } 

        [SecurityPermission(SecurityAction.Demand, Unrestricted = true)] 
        public IRegisteredObject CreateObject(String appId, Type type, string virtualPath, string physicalPath,
                                              bool failIfExists, bool throwOnError) {
            // check args
            if (appId == null) 
                throw new ArgumentNullException("appId");
 
            SimpleApplicationHost appHost = new SimpleApplicationHost(VirtualPath.CreateAbsolute(virtualPath), physicalPath); 

            // if throw on error flag is set, create hosting parameters accordingly 
            HostingEnvironmentParameters hostingParameters = null;

            if (throwOnError) {
                hostingParameters = new HostingEnvironmentParameters(); 
                hostingParameters.HostingFlags = HostingEnvironmentFlags.ThrowHostingInitErrors;
 
            } 

            // call the internal method 
            return CreateObjectInternal(appId, type, appHost, failIfExists, hostingParameters);
        }

        [SecurityPermission(SecurityAction.Demand, Unrestricted = true)] 
        internal IRegisteredObject CreateObjectInternal(String appId, Type type, IApplicationHost appHost, bool failIfExists) {
            // check args 
            if (appId == null) 
                throw new ArgumentNullException("appId");
 
            if (type == null)
                throw new ArgumentNullException("type");

            if (appHost == null) 
                throw new ArgumentNullException("appHost");
 
            // call the internal method 
            return CreateObjectInternal(appId, type, appHost, failIfExists, null /*hostingParameters*/);
        } 

        [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
        internal IRegisteredObject CreateObjectInternal(
                                        String appId, 
                                        Type type,
                                        IApplicationHost appHost, 
                                        bool failIfExists, 
                                        HostingEnvironmentParameters hostingParameters) {
 
            // check that type is as IRegisteredObject
            if (!typeof(IRegisteredObject).IsAssignableFrom(type))
                throw new ArgumentException(SR.GetString(SR.Not_IRegisteredObject, type.FullName), "type");
 
            // get hosting environment
            HostingEnvironment env = GetAppDomainWithHostingEnvironment(appId, appHost, hostingParameters); 
 
            // create the managed object in the worker app domain
            // When marshaling Type, the AppDomain must have FileIoPermission to the assembly, which is not 
            // always the case, so we marshal the assembly qualified name instead
            ObjectHandle h = env.CreateWellKnownObjectInstance(type.AssemblyQualifiedName, failIfExists);
            return (h != null) ? h.Unwrap() as IRegisteredObject : null;
        } 

        internal IRegisteredObject CreateObjectWithDefaultAppHostAndAppId( 
                                        String physicalPath, 
                                        string virtualPath,
                                        Type type, 
                                        out String appId) {
            return CreateObjectWithDefaultAppHostAndAppId(physicalPath,
                VirtualPath.CreateNonRelative(virtualPath), type, out appId);
        } 

        internal IRegisteredObject CreateObjectWithDefaultAppHostAndAppId( 
                                        String physicalPath, 
                                        VirtualPath virtualPath,
                                        Type type, 
                                        out String appId) {

            HostingEnvironmentParameters hostingParameters = new HostingEnvironmentParameters();
            hostingParameters.HostingFlags = HostingEnvironmentFlags.DontCallAppInitialize; 

            return CreateObjectWithDefaultAppHostAndAppId( 
                        physicalPath, 
                        virtualPath,
                        type, 
                        false,
                        hostingParameters,
                        out appId);
        } 

        internal IRegisteredObject CreateObjectWithDefaultAppHostAndAppId( 
                                        String physicalPath, 
                                        VirtualPath virtualPath,
                                        Type type, 
                                        bool failIfExists,
                                        HostingEnvironmentParameters hostingParameters,
                                        out String appId) {
 
            IApplicationHost appHost;
#if !FEATURE_PAL // FEATURE_PAL does not enable IIS-based hosting features 
            if (physicalPath == null) { 

                // If the physical path is null, we use an ISAPIApplicationHost based 
                // on the virtual path (or metabase id).

                // Make sure the static HttpRuntime is created so isapi assembly can be loaded properly.
                HttpRuntime.ForceStaticInit(); 

                ISAPIApplicationHost isapiAppHost = new ISAPIApplicationHost(virtualPath.VirtualPathString, null, true); 
 
                appHost = isapiAppHost;
                appId = isapiAppHost.AppId; 
                virtualPath = VirtualPath.Create(appHost.GetVirtualPath());
                physicalPath = FileUtil.FixUpPhysicalDirectory(appHost.GetPhysicalPath());
            }
            else { 
#endif // !FEATURE_PAL
                // If the physical path was passed in, don't use an Isapi host. Instead, 
                // use a simple app host which does simple virtual to physical mappings 

                // Put together some unique app id 
                appId = CreateSimpleAppID(virtualPath, physicalPath, null);

                appHost = new SimpleApplicationHost(virtualPath, physicalPath);
            } 

            string precompTargetPhysicalDir = hostingParameters.PrecompilationTargetPhysicalDirectory; 
            if (precompTargetPhysicalDir != null) { 
                // Make sure the target physical dir has no relation with the source
                BuildManager.VerifyUnrelatedSourceAndDest(physicalPath, precompTargetPhysicalDir); 

                // Change the appID so we use a different codegendir in precompile for deployment scenario,
                // this ensures we don't use or pollute the regular codegen files.  Also, use different
                // ID's depending on whether the precompilation is Updatable (VSWhidbey 383239) 
                if ((hostingParameters.ClientBuildManagerParameter != null) &&
                    (hostingParameters.ClientBuildManagerParameter.PrecompilationFlags & PrecompilationFlags.Updatable) == 0) 
                    appId = appId + "_precompile"; 
                else
                    appId = appId + "_precompile_u"; 
            }

            return CreateObjectInternal(appId, type, appHost, failIfExists, hostingParameters);
        } 

 
        [SecurityPermission(SecurityAction.Demand, Unrestricted = true)] 
        public IRegisteredObject GetObject(String appId, Type type) {
            // check args 
            if (appId == null)
                throw new ArgumentNullException("appId");
            if (type == null)
                throw new ArgumentNullException("type"); 

            LockableAppDomainContext ac = GetLockableAppDomainContext(appId); 
            lock (ac) { 
                HostingEnvironment env = ac.HostEnv;
                if (env == null) 
                    return null;

                // find the instance by type
                // When marshaling Type, the AppDomain must have FileIoPermission to the assembly, which is not 
                // always the case, so we marshal the assembly qualified name instead
                ObjectHandle h = env.FindWellKnownObject(type.AssemblyQualifiedName); 
                return (h != null) ? h.Unwrap() as IRegisteredObject : null; 
            }
        } 

        [SecurityPermission(SecurityAction.Demand, Unrestricted = true)]
        public AppDomain GetAppDomain(string appId) {
            if (appId == null) { 
                throw new ArgumentNullException("appId");
            } 
 
            LockableAppDomainContext ac = GetLockableAppDomainContext(appId);
            lock (ac) { 
                HostingEnvironment env = ac.HostEnv;
                if (env == null) {
                    return null;
                } 

                return env.HostedAppDomain; 
            } 
        }
 
        public AppDomain GetAppDomain(IApplicationHost appHost) {
            if (appHost == null) {
                throw new ArgumentNullException("appHost");
            } 
            string appID = CreateSimpleAppID(appHost);
            return GetAppDomain(appID); 
        } 

        private string CreateSimpleAppID(IApplicationHost appHost) { 
            if (appHost == null) {
                throw new ArgumentNullException("appHost");
            }
            return CreateSimpleAppID(VirtualPath.Create(appHost.GetVirtualPath()), 
                                     appHost.GetPhysicalPath(), appHost.GetSiteName());
        } 
 

        // if a "well-known" object of the specified type already exists in the application, 
        // remove the app from the managed application table.  This is
        // used in IIS7 integrated mode when IIS7 determines that it is necessary to create
        // a new application and shutdown the old one.
        internal void RemoveFromTableIfRuntimeExists(String appId, Type runtimeType) { 
            // check args
            if (appId == null) 
                throw new ArgumentNullException("appId"); 
            if (runtimeType == null)
                throw new ArgumentNullException("runtimeType"); 

            LockableAppDomainContext ac = GetLockableAppDomainContext(appId);
            lock (ac) {
                // get hosting environment 
                HostingEnvironment env = ac.HostEnv;
                if (env == null) 
                    return; 

                // find the instance by type 
                // When marshaling Type, the AppDomain must have FileIoPermission to the assembly, which is not
                // always the case, so we marshal the assembly qualified name instead
                ObjectHandle h = env.FindWellKnownObject(runtimeType.AssemblyQualifiedName);
                if (h != null) 
                {
                    // ensure that it is removed from _appDomains by calling 
                    // HostingEnvironmentShutdownInitiated directly. 
                    HostingEnvironmentShutdownInitiated(appId, env);
                } 
            }
        }

        [SecurityPermission(SecurityAction.Demand, Unrestricted = true)] 
        public void StopObject(String appId, Type type) {
            // check args 
            if (appId == null) 
                throw new ArgumentNullException("appId");
            if (type == null) 
                throw new ArgumentNullException("type");

            LockableAppDomainContext ac = GetLockableAppDomainContext(appId);
            lock (ac) { 
                HostingEnvironment env = ac.HostEnv;
                if (env != null) { 
                    // When marshaling Type, the AppDomain must have FileIoPermission to the assembly, which is not 
                    // always the case, so we marshal the assembly qualified name instead
                    env.StopWellKnownObject(type.AssemblyQualifiedName); 
                }
            }
        }
 

        public bool IsIdle() { 
            Dictionary apps = CloneAppDomainsCollection(); 

            foreach (LockableAppDomainContext ac in apps.Values) { 
                lock (ac) {
                    HostingEnvironment env = ac.HostEnv;
                    bool idle = (null == env) ? true : env.IsIdle();
 
                    if (!idle)
                        return false; 
                } 
            }
 
            return true;
        }

 
        [SecurityPermission(SecurityAction.Demand, Unrestricted = true)]
        public void ShutdownApplication(String appId) { 
            if (appId == null) 
                throw new ArgumentNullException("appId");
 
            LockableAppDomainContext ac = GetLockableAppDomainContext(appId);
            lock (ac) {
                if (ac.HostEnv != null) {
                    ac.HostEnv.InitiateShutdownInternal(); 
                }
            } 
        } 

 
        [SecurityPermission(SecurityAction.Demand, Unrestricted = true)]
        public void ShutdownAll() {
            _shutdownInProgress = true;
            Dictionary  oldTable = null; 

            DisposeCacheManager(); 
 
            lock (this) {
                oldTable = _appDomains; 
                // don't keep references to hosting environments anymore
                _appDomains = new Dictionary(StringComparer.OrdinalIgnoreCase);
            }
 

            foreach (KeyValuePair  p in oldTable) { 
                LockableAppDomainContext ac = p.Value; 
                lock (ac) {
                    HostingEnvironment env = ac.HostEnv; 
                    if (null != env) {
                        env.InitiateShutdownInternal();
                    }
                } 
            }
 
            for (int iter=0; _activeHostingEnvCount > 0 && iter < 3000; iter++) // Wait at most 5 minutes 
                Thread.Sleep(100);
        } 


        [SecurityPermission(SecurityAction.Demand, Unrestricted = true)]
        public ApplicationInfo[] GetRunningApplications() { 
            ArrayList appList = new ArrayList();
 
            Dictionary apps = CloneAppDomainsCollection(); 

            foreach (LockableAppDomainContext ac in apps.Values) { 
                lock (ac) {
                    HostingEnvironment env = ac.HostEnv;
                    if (env != null) {
                        appList.Add(env.GetApplicationInfo()); 
                    }
                } 
            } 

            int n = appList.Count; 
            ApplicationInfo[] result = new ApplicationInfo[n];

            if (n > 0) {
                appList.CopyTo(result); 
            }
 
            return result; 
        }
 
        internal AppDomainInfo [] GetAppDomainInfos()
        {
            ArrayList appList = new ArrayList();
            Dictionary apps = CloneAppDomainsCollection(); 

            foreach (LockableAppDomainContext ac in apps.Values) { 
                lock (ac) { 
                    HostingEnvironment hostEnv = ac.HostEnv;
                    if (hostEnv == null) { 
                        continue;
                    }

                    IApplicationHost appHost = hostEnv.InternalApplicationHost; 
                    ApplicationInfo appInfo = hostEnv.GetApplicationInfo();
                    int siteId = 0; 
 
                    if (appHost != null) {
                        try { 
                            siteId = Int32.Parse(appHost.GetSiteID(), CultureInfo.InvariantCulture);
                        }
                        catch {
                        } 
                    }
 
                    AppDomainInfo appDomainInfo = new AppDomainInfo(appInfo.ID, 
                                                      appInfo.VirtualPath,
                                                      appInfo.PhysicalPath, 
                                                      siteId,
                                                      hostEnv.GetIdleValue());

                    appList.Add(appDomainInfo); 
                }
            } 
 
            return (AppDomainInfo[]) appList.ToArray(typeof(AppDomainInfo));
        } 

        //
        // ping implementation
        // 

        // called from process host 
        internal void Ping(IProcessPingCallback callback) { 
            if (callback == null || _pendingPingCallback != null)
                return; 

            // remember active callback but only if none is remembered already
            if (Interlocked.CompareExchange(ref _pendingPingCallback, callback, null) == null) {
                // queue a work item to respond to ping 
                ThreadPool.QueueUserWorkItem(_onRespondToPingWaitCallback);
            } 
        } 

        // threadpool callback (also called on some activity from hosting environment) 
        internal void OnRespondToPingWaitCallback(Object state) {
            RespondToPingIfNeeded();
        }
 
        // respond to ping on callback
        internal void RespondToPingIfNeeded() { 
            IProcessPingCallback callback = _pendingPingCallback as IProcessPingCallback; 

            // make sure we call the callback once 
            if (callback != null) {
                if (Interlocked.CompareExchange(ref _pendingPingCallback, null, callback) == callback) {
                    callback.Respond();
                } 
            }
        } 
 
        //
        // communication with hosting environments 
        //

        internal void HostingEnvironmentActivated(long privateBytesLimit) {
            int count = Interlocked.Increment(ref _activeHostingEnvCount); 

            // initialize CacheManager once, without blocking 
            if (count == 1) { 
                InitCacheManager(privateBytesLimit);
            } 
        }

        internal void HostingEnvironmentShutdownComplete(String appId, IApplicationHost appHost) {
            try { 
                if (appHost != null) {
                    // make sure application host can be GC'd 
                    MarshalByRefObject realApplicationHost = appHost as MarshalByRefObject; 
                    if (realApplicationHost != null) {
                        RemotingServices.Disconnect(realApplicationHost); 
                    }
                }
            }
            finally { 
                Interlocked.Decrement(ref _activeHostingEnvCount);
            } 
        } 

        internal void HostingEnvironmentShutdownInitiated(String appId, HostingEnvironment env) { 
            if (!_shutdownInProgress) { // don't bother during shutdown (while enumerating)
                LockableAppDomainContext ac = GetLockableAppDomainContext (appId);

                lock (ac){ 
                    if (!env.HasBeenRemovedFromAppManagerTable) {
                        env.HasBeenRemovedFromAppManagerTable = true; 
 
                        ac.HostEnv = null;
                        Interlocked.Decrement(ref _accessibleHostingEnvCount); 

                        // Autorestart the application right away
                        if (ac.PreloadContext != null && !ac.RetryingPreload) {
                            ProcessHost.PreloadApplicationIfNotShuttingdown(appId, ac); 
                        }
                    } 
                } 
            }
        } 

        internal int AppDomainsCount {
            get { return _accessibleHostingEnvCount; }
        } 

 
        internal void ReduceAppDomainsCount(int limit) { 
            //
 



            Dictionary apps = CloneAppDomainsCollection(); 
            while (_accessibleHostingEnvCount >= limit && !_shutdownInProgress)
            { 
                LockableAppDomainContext bestCandidateForShutdown = null; 
                int bestCandidateLruScore = 0;
 
                foreach (LockableAppDomainContext ac in apps.Values) {
                    // Don't lock on LockableAppDomainContext before we check that ac.HostEnv != null.
                    // Otherwise we may end up with a deadlock between 2 app domains trying to unload each other
                    HostingEnvironment h = ac.HostEnv; 
                    if (h == null) {
                        continue; 
                    } 
                    lock (ac) {
                        h = ac.HostEnv; 

                        // Avoid ---- by checking again under lock
                        if (h == null) {
                            continue; 
                        }
                        int newLruScore = h.LruScore; 
 
                        if (bestCandidateForShutdown == null || bestCandidateForShutdown.HostEnv == null ||
                                newLruScore < bestCandidateLruScore) { 

                            bestCandidateLruScore = newLruScore;
                            bestCandidateForShutdown = ac;
                        } 
                    }
                } 
 
                if (bestCandidateForShutdown == null)
                    break; 

                lock (bestCandidateForShutdown) {
                    if (bestCandidateForShutdown.HostEnv != null) {
                        bestCandidateForShutdown.HostEnv.InitiateShutdownInternal(); 
                    }
                } 
            } 
        }
 
        //
        // helper to support legacy APIs (AppHost.CreateAppHost)
        //
 
        internal ObjectHandle CreateInstanceInNewWorkerAppDomain(
                                Type type, 
                                String appId, 
                                VirtualPath virtualPath,
                                String physicalPath) { 

            Debug.Trace("AppManager", "CreateObjectInNewWorkerAppDomain, type=" + type.FullName);

            IApplicationHost appHost = new SimpleApplicationHost(virtualPath, physicalPath); 

            HostingEnvironmentParameters hostingParameters = new HostingEnvironmentParameters(); 
            hostingParameters.HostingFlags = HostingEnvironmentFlags.HideFromAppManager; 

            HostingEnvironment env = CreateAppDomainWithHostingEnvironmentAndReportErrors(appId, appHost, hostingParameters); 
            // When marshaling Type, the AppDomain must have FileIoPermission to the assembly, which is not
            // always the case, so we marshal the assembly qualified name instead
            return env.CreateInstance(type.AssemblyQualifiedName);
        } 

        // 
        // helpers to facilitate app domain creation 
        //
        private HostingEnvironment GetAppDomainWithHostingEnvironment(String appId, IApplicationHost appHost, HostingEnvironmentParameters hostingParameters) { 
            LockableAppDomainContext ac = GetLockableAppDomainContext (appId);

            lock (ac) {
                HostingEnvironment env = ac.HostEnv; 

                if (env != null) { 
                    try { 
                        env.IsUnloaded();
                    } catch(AppDomainUnloadedException) { 
                        env = null;
                    }
                }
                if (env == null) { 
                    env = CreateAppDomainWithHostingEnvironmentAndReportErrors(appId, appHost, hostingParameters);
                    ac.HostEnv = env; 
                    Interlocked.Increment(ref _accessibleHostingEnvCount); 
                }
 
                return env;
            }

        } 

        private HostingEnvironment CreateAppDomainWithHostingEnvironmentAndReportErrors( 
                                        String appId, 
                                        IApplicationHost appHost,
                                        HostingEnvironmentParameters hostingParameters) { 
            try {
                return CreateAppDomainWithHostingEnvironment(appId, appHost, hostingParameters);
            }
            catch (Exception e) { 
                Misc.ReportUnhandledException(e, new string[] {SR.GetString(SR.Failed_to_initialize_AppDomain), appId});
                throw; 
            } 
        }
 
        private HostingEnvironment CreateAppDomainWithHostingEnvironment(
                                                String appId,
                                                IApplicationHost appHost,
                                                HostingEnvironmentParameters hostingParameters) { 

            String physicalPath = appHost.GetPhysicalPath(); 
            if (!StringUtil.StringEndsWith(physicalPath, Path.DirectorySeparatorChar)) 
                physicalPath = physicalPath + Path.DirectorySeparatorChar;
 
            String domainId = ConstructAppDomainId(appId);
            String appName = (StringUtil.GetStringHashCode(String.Concat(appId.ToLower(CultureInfo.InvariantCulture),
                physicalPath.ToLower(CultureInfo.InvariantCulture)))).ToString("x", CultureInfo.InvariantCulture);
            VirtualPath virtualPath = VirtualPath.Create(appHost.GetVirtualPath()); 

            Debug.Trace("AppManager", "CreateAppDomainWithHostingEnvironment, path=" + physicalPath + "; appId=" + appId + "; domainId=" + domainId); 
 
            IDictionary bindings = new Hashtable(20);
            AppDomainSetup setup = new AppDomainSetup(); 
            PopulateDomainBindings(domainId, appId, appName, physicalPath, virtualPath, setup, bindings);

            //  Create the app domain
 
            AppDomain appDomain = null;
            Exception appDomainCreationException = null; 
 
            string siteID = appHost.GetSiteID();
            string appSegment = virtualPath.VirtualPathStringNoTrailingSlash; 
            bool isLegacyCas = false;
            bool inClientBuildManager = false;
            Configuration appConfig = null;
            PolicyLevel policyLevel = null; 
            PermissionSet permissionSet = null;
            StrongName[] fullTrustAssemblies = null; 
            string[] defaultPartialTrustVisibleAssemblies = new[] { "System.Web, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293", 
                                                                    "System.Web.Extensions, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9",
                                                                    "System.Web.Abstractions, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9", 
                                                                    "System.Web.Routing, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9",
                                                                    "System.ComponentModel.DataAnnotations, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9",
                                                                    "System.Web.DynamicData, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9",
                                                                    "System.Web.DataVisualization, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9", 
                                                                    "System.Web.ApplicationServices, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9" };
 
            Exception appDomainStartupConfigurationException = null; 
            ImpersonationContext ictxConfig = null;
            IntPtr uncTokenConfig = IntPtr.Zero; 
            HostingEnvironmentFlags hostingFlags = HostingEnvironmentFlags.Default;
            if (hostingParameters != null) {
                hostingFlags = hostingParameters.HostingFlags;
                if ((hostingFlags & HostingEnvironmentFlags.ClientBuildManager) != 0) { 
                    inClientBuildManager = true;
                    // The default hosting policy in VS has changed (from MultiDomainHost to MultiDomain), 
                    // so we need to specify explicitly to allow generated assemblies 
                    // to be unloaded subsequently. (Dev10 bug)
                    setup.LoaderOptimization = LoaderOptimization.MultiDomainHost; 
                }
            }
            try {
                uncTokenConfig = appHost.GetConfigToken(); 
                if (uncTokenConfig != IntPtr.Zero) {
                    ictxConfig = new ImpersonationContext(uncTokenConfig); 
                } 

                try { 
                    //Hosted by IIS, we already have an IISMap.
                    if (appHost is ISAPIApplicationHost) {
                        string cacheKey = System.Web.Caching.CacheInternal.PrefixMapPath + siteID + virtualPath.VirtualPathString;
                        MapPathCacheInfo cacheInfo = (MapPathCacheInfo)HttpRuntime.CacheInternal.Remove(cacheKey); 
                        appConfig = WebConfigurationManager.OpenWebConfiguration(appSegment, siteID);
                    } 
                    // For non-IIS hosting scenarios, we need to get config map from application host in a generic way. 
                    else {
                        WebConfigurationFileMap fileMap = new WebConfigurationFileMap(); 
                        IConfigMapPathFactory configMapPathFactory2 = appHost.GetConfigMapPathFactory();
                        IConfigMapPath configMapPath = configMapPathFactory2.Create(virtualPath.VirtualPathString, physicalPath);
                        string dir = null;
                        string fileName = null; 
                        string subDir = "/";
                        // add root mapping 
                        configMapPath.GetPathConfigFilename(siteID, subDir, out dir, out fileName); 
                        if (dir != null) {
                            fileMap.VirtualDirectories.Add(subDir, new VirtualDirectoryMapping(Path.GetFullPath(dir), true)); 
                        }
                        // add subdir mappings
                        string[] subDirs = appSegment.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
                        foreach (string s in subDirs) { 
                            subDir = subDir + s;
                            configMapPath.GetPathConfigFilename(siteID, subDir, out dir, out fileName); 
                            if (dir != null) { 
                                fileMap.VirtualDirectories.Add(subDir, new VirtualDirectoryMapping(Path.GetFullPath(dir), true));
                            } 
                            subDir = subDir + "/";
                        }
                        // open mapped web config for application
                        appConfig = WebConfigurationManager.OpenMappedWebConfiguration(fileMap, appSegment, siteID); 
                    }
                    TrustSection trustSection = (TrustSection)appConfig.GetSection("system.web/trust"); 
                    if (trustSection == null || String.IsNullOrEmpty(trustSection.Level)) { 
                        throw new ConfigurationErrorsException(SR.GetString(SR.Config_section_not_present, "trust"));
                    } 

                    bool trustSectionLegacyCasModel = trustSection.LegacyCasModel;
                    if (trustSectionLegacyCasModel) {
                        SetNetFx40LegacySecurityPolicy(setup); 
                    }
 
                    if (inClientBuildManager) { 
                        permissionSet = new PermissionSet(PermissionState.Unrestricted);
                        setup.PartialTrustVisibleAssemblies = defaultPartialTrustVisibleAssemblies; 
                    }
                    else {
                        isLegacyCas = trustSectionLegacyCasModel;
                        if (!isLegacyCas) { 
                            if (trustSection.Level == "Full") {
                                permissionSet = new PermissionSet(PermissionState.Unrestricted); 
                                setup.PartialTrustVisibleAssemblies = defaultPartialTrustVisibleAssemblies; 
                            }
                            else { 
                                SecurityPolicySection securityPolicySection = (SecurityPolicySection)appConfig.GetSection("system.web/securityPolicy");
                                CompilationSection compilationSection = (CompilationSection)appConfig.GetSection("system.web/compilation");
                                FullTrustAssembliesSection fullTrustAssembliesSection = (FullTrustAssembliesSection)appConfig.GetSection("system.web/fullTrustAssemblies");
                                policyLevel = GetPartialTrustPolicyLevel(trustSection, securityPolicySection, compilationSection, physicalPath, virtualPath); 
                                permissionSet = policyLevel.GetNamedPermissionSet(trustSection.PermissionSetName);
                                if (permissionSet == null) { 
                                    throw new ConfigurationErrorsException(SR.GetString(SR.Permission_set_not_found, trustSection.PermissionSetName)); 
                                }
 
                                //read full trust assemblies and populate the strong name list.
                                if (fullTrustAssembliesSection != null) {
                                    FullTrustAssemblyCollection fullTrustAssembliesCollection = fullTrustAssembliesSection.FullTrustAssemblies;
                                    if (fullTrustAssembliesCollection != null && fullTrustAssembliesCollection.Count != 0) { 
                                        fullTrustAssemblies = new StrongName[fullTrustAssembliesCollection.Count];
                                        for (int i = 0; i < fullTrustAssembliesCollection.Count; i++) { 
                                            fullTrustAssemblies[i] = CreateStrongName(fullTrustAssembliesCollection[i].AssemblyName, 
                                                                                      fullTrustAssembliesCollection[i].Version,
                                                                                      fullTrustAssembliesCollection[i].PublicKey); 
                                        }
                                    }
                                }
 
                                // Setup HostSecurityManager
                                setup.AppDomainManagerType = typeof(AspNetAppDomainManager).FullName; 
                                setup.AppDomainManagerAssembly = typeof(AspNetAppDomainManager).Assembly.FullName; 
                            }
                        } 
                        if (trustSection.Level != "Full") {
                            PartialTrustVisibleAssembliesSection partialTrustVisibleAssembliesSection = (PartialTrustVisibleAssembliesSection)appConfig.GetSection("system.web/partialTrustVisibleAssemblies");
                            string[] partialTrustVisibleAssemblies = null;
                            if (partialTrustVisibleAssembliesSection != null) { 
                                PartialTrustVisibleAssemblyCollection partialTrustVisibleAssembliesCollection = partialTrustVisibleAssembliesSection.PartialTrustVisibleAssemblies;
                                if (partialTrustVisibleAssembliesCollection != null && partialTrustVisibleAssembliesCollection.Count != 0) { 
                                    partialTrustVisibleAssemblies = new string[partialTrustVisibleAssembliesCollection.Count + defaultPartialTrustVisibleAssemblies.Length]; 
                                    for (int i = 0; i < partialTrustVisibleAssembliesCollection.Count; i++) {
                                        partialTrustVisibleAssemblies[i] = partialTrustVisibleAssembliesCollection[i].AssemblyName + 
                                            ", PublicKey=" +
                                            NormalizePublicKeyBlob(partialTrustVisibleAssembliesCollection[i].PublicKey);
                                    }
                                    defaultPartialTrustVisibleAssemblies.CopyTo(partialTrustVisibleAssemblies, partialTrustVisibleAssembliesCollection.Count); 
                                }
                            } 
                            if (partialTrustVisibleAssemblies == null) { 
                                partialTrustVisibleAssemblies = defaultPartialTrustVisibleAssemblies;
                            } 
                            setup.PartialTrustVisibleAssemblies = partialTrustVisibleAssemblies;
                        }
                    }
                } 
                catch (Exception e) {
                    appDomainStartupConfigurationException = e; 
                    permissionSet = new PermissionSet(PermissionState.Unrestricted); 
                }
 
                try {
                    if (isLegacyCas) {
                        appDomain = AppDomain.CreateDomain(domainId,
#if FEATURE_PAL // FEATURE_PAL: hack to avoid non-supported hosting features 
                                                           null,
#else // FEATURE_PAL 
GetDefaultDomainIdentity(), 
#endif // FEATURE_PAL
setup); 
                    }
                    else {
                        appDomain = AppDomain.CreateDomain(domainId,
#if FEATURE_PAL // FEATURE_PAL: hack to avoid non-supported hosting features 
                                                           null,
#else // FEATURE_PAL 
GetDefaultDomainIdentity(), 
#endif // FEATURE_PAL
setup, 
                                                           permissionSet,
                                                           fullTrustAssemblies /* fully trusted assemblies list: null means only trust GAC assemblies */);
                    }
                    foreach (DictionaryEntry e in bindings) 
                        appDomain.SetData((String)e.Key, (String)e.Value);
                } 
                catch (Exception e) { 
                    Debug.Trace("AppManager", "AppDomain.CreateDomain failed", e);
                    appDomainCreationException = e; 
                }
            }
            finally {
                if (ictxConfig != null) { 
                    ictxConfig.Undo();
                    ictxConfig = null; 
                } 
                if (uncTokenConfig != IntPtr.Zero) {
                    UnsafeNativeMethods.CloseHandle(uncTokenConfig); 
                    uncTokenConfig = IntPtr.Zero;
                }
            }
 
            if (appDomain == null) {
                throw new SystemException(SR.GetString(SR.Cannot_create_AppDomain), appDomainCreationException); 
            } 

            // Create hosting environment in the new app domain 

            Type hostType = typeof(HostingEnvironment);
            String module = hostType.Module.Assembly.FullName;
            String typeName = hostType.FullName; 
            ObjectHandle h = null;
 
            // impersonate UNC identity, if any 
            ImpersonationContext ictx = null;
            IntPtr uncToken = IntPtr.Zero; 

            //
            // fetching config can fail due to a ---- with the
            // native config reader 
            // if that has happened, force a flush
            // 
            int maxRetries = 10; 
            int numRetries = 0;
 
            while (numRetries < maxRetries) {
                try {
                    uncToken = appHost.GetConfigToken();
                    // no throw, so break 
                    break;
                } 
                catch (InvalidOperationException) { 
                    numRetries++;
                    System.Threading.Thread.Sleep(250); 
                }
            }

 
            if (uncToken != IntPtr.Zero) {
                try { 
                    ictx = new ImpersonationContext(uncToken); 
                }
                catch { 
                }
                finally {
                    UnsafeNativeMethods.CloseHandle(uncToken);
                } 
            }
 
            try { 

                // Create the hosting environment in the app domain 
#if DBG
                try {
                    h = Activator.CreateInstance(appDomain, module, typeName);
                } 
                catch (Exception e) {
                    Debug.Trace("AppManager", "appDomain.CreateInstance failed; identity=" + System.Security.Principal.WindowsIdentity.GetCurrent().Name, e); 
                    throw; 
                }
#else 
                h = Activator.CreateInstance(appDomain, module, typeName);
#endif
            }
            finally { 
                // revert impersonation
                if (ictx != null) 
                    ictx.Undo(); 

                if (h == null) { 
                    AppDomain.Unload(appDomain);
                }
            }
 
            HostingEnvironment env = (h != null) ? h.Unwrap() as HostingEnvironment : null;
 
            if (env == null) 
                throw new SystemException(SR.GetString(SR.Cannot_create_HostEnv));
 
            // iniitalize the hosting environment
            IConfigMapPathFactory configMapPathFactory = appHost.GetConfigMapPathFactory();
            if (appDomainStartupConfigurationException == null) {
                env.Initialize(this, appHost, configMapPathFactory, hostingParameters, policyLevel); 
            }
            else { 
                env.Initialize(this, appHost, configMapPathFactory, hostingParameters, policyLevel, appDomainStartupConfigurationException); 
            }
            return env; 
        }

        private static void SetNetFx40LegacySecurityPolicy(AppDomainSetup setup) {
            // Allow the appdomain to use legacy CAS 
            var compatSwitches = new List();
            compatSwitches.Add("NetFx40_LegacySecurityPolicy"); 
            setup.SetCompatibilitySwitches(compatSwitches); 
        }
 
        private static string NormalizePublicKeyBlob(string publicKey) {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < publicKey.Length; i++) {
                if (!Char.IsWhiteSpace(publicKey[i])) { 
                    sb.Append(publicKey[i]);
                } 
            } 
            publicKey = sb.ToString();
            return publicKey; 
        }

        private static StrongName CreateStrongName(string assemblyName, string version, string publicKeyString) {
            byte[] publicKey = null; 
            StrongName strongName = null;
            publicKeyString = NormalizePublicKeyBlob(publicKeyString); 
            int publicKeySize = publicKeyString.Length / 2; 
            publicKey = new byte[publicKeySize];
            for (int i = 0; i < publicKeySize; i++) { 
                publicKey[i] = Byte.Parse(publicKeyString.Substring(i * 2, 2), System.Globalization.NumberStyles.HexNumber, CultureInfo.InvariantCulture);
            }
            StrongNamePublicKeyBlob keyBlob = new StrongNamePublicKeyBlob(publicKey);
            strongName = new StrongName(keyBlob, assemblyName, new Version(version)); 
            return strongName;
        } 
 
        private static PolicyLevel GetPartialTrustPolicyLevel(
                TrustSection trustSection, SecurityPolicySection securityPolicySection, 
                CompilationSection compilationSection, string physicalPath, VirtualPath virtualPath) {
            if (securityPolicySection == null || securityPolicySection.TrustLevels[trustSection.Level] == null) {
                throw new ConfigurationErrorsException(SR.GetString(SR.Unable_to_get_policy_file, trustSection.Level), String.Empty, 0);
            } 
            String configFile = (String)securityPolicySection.TrustLevels[trustSection.Level].PolicyFileExpanded;
            if (configFile == null || !FileUtil.FileExists(configFile)) { 
                throw new HttpException(SR.GetString(SR.Unable_to_get_policy_file, trustSection.Level)); 
            }
            PolicyLevel policyLevel = null; 
            String appDir = FileUtil.RemoveTrailingDirectoryBackSlash(physicalPath);
            String appDirUrl = HttpRuntime.MakeFileUrl(appDir);

            // setup $CodeGen$ replacement 
            string tempDirectory = null;
            // These variables are used for error handling 
            string tempDirAttribName = null; 
            string configFileName = null;
            int configLineNumber = 0; 
            if (compilationSection != null && !String.IsNullOrEmpty(compilationSection.TempDirectory)) {
                tempDirectory = compilationSection.TempDirectory;
                compilationSection.GetTempDirectoryErrorInfo(out tempDirAttribName,
                    out configFileName, out configLineNumber); 
            }
            if (tempDirectory != null) { 
                tempDirectory = tempDirectory.Trim(); 
                if (!Path.IsPathRooted(tempDirectory)) {
                    // Make sure the path is not relative (VSWhidbey 260075) 
                    tempDirectory = null;
                }
                else {
                    try { 
                        // Canonicalize it to avoid problems with spaces (VSWhidbey 229873)
                        tempDirectory = new DirectoryInfo(tempDirectory).FullName; 
                    } 
                    catch {
                        tempDirectory = null; 
                    }
                }
                if (tempDirectory == null) {
                    throw new ConfigurationErrorsException( 
                        SR.GetString(SR.Invalid_temp_directory, tempDirAttribName),
                        configFileName, configLineNumber); 
                } 
                // Create the config-specified directory if needed
                try { 
                    Directory.CreateDirectory(tempDirectory);
                }
                catch (Exception e) {
                    throw new ConfigurationErrorsException( 
                        SR.GetString(SR.Invalid_temp_directory, tempDirAttribName),
                        e, 
                        configFileName, configLineNumber); 
                }
            } 
            else {
                tempDirectory = Path.Combine(RuntimeEnvironment.GetRuntimeDirectory(), HttpRuntime.codegenDirName);
            }
            // If we don't have write access to the codegen dir, use the TEMP dir instead. 
            // This will allow non-admin users to work in hosting scenarios (e.g. Venus, aspnet_compiler)
            if (!System.Web.UI.Util.HasWriteAccessToDirectory(tempDirectory)) { 
                // Don't do this if we're in a service (!UserInteractive), as TEMP 
                // could point to unwanted places.
                if (!Environment.UserInteractive) { 
                    throw new HttpException(SR.GetString(SR.No_codegen_access,
                        System.Web.UI.Util.GetCurrentAccountName(), tempDirectory));
                }
                tempDirectory = Path.GetTempPath(); 
                Debug.Assert(System.Web.UI.Util.HasWriteAccessToDirectory(tempDirectory));
                tempDirectory = Path.Combine(tempDirectory, HttpRuntime.codegenDirName); 
            } 
            String simpleAppName = System.Web.Hosting.AppManagerAppDomainFactory.ConstructSimpleAppName(
                VirtualPath.GetVirtualPathStringNoTrailingSlash(virtualPath)); 
            String binDir = Path.Combine(tempDirectory, simpleAppName);
            binDir = FileUtil.RemoveTrailingDirectoryBackSlash(binDir);
            String binDirUrl = HttpRuntime.MakeFileUrl(binDir);
 
            String originUrl = trustSection.OriginUrl;
            FileStream file = new FileStream(configFile, FileMode.Open, FileAccess.Read); 
            StreamReader reader = new StreamReader(file, Encoding.UTF8); 
            String strFileData = reader.ReadToEnd();
            reader.Close(); 
            strFileData = strFileData.Replace("$AppDir$", appDir);
            strFileData = strFileData.Replace("$AppDirUrl$", appDirUrl);
            strFileData = strFileData.Replace("$CodeGen$", binDirUrl);
            if (originUrl == null) 
                originUrl = String.Empty;
            strFileData = strFileData.Replace("$OriginHost$", originUrl); 
            String gacLocation = null; 
            if (strFileData.IndexOf("$Gac$", StringComparison.Ordinal) != -1) {
                gacLocation = HttpRuntime.GetGacLocation(); 
                if (gacLocation != null)
                    gacLocation = HttpRuntime.MakeFileUrl(gacLocation);
                if (gacLocation == null)
                    gacLocation = String.Empty; 
                strFileData = strFileData.Replace("$Gac$", gacLocation);
            } 
#pragma warning disable 618 // ASP is reading their grant set out of legacy policy level files 
            policyLevel = SecurityManager.LoadPolicyLevelFromString(strFileData, PolicyLevelType.AppDomain);
            if (policyLevel == null) { 
                throw new ConfigurationErrorsException(SR.GetString(SR.Unable_to_get_policy_file, trustSection.Level));
            }
            // Found GAC Token
            if (gacLocation != null) { 
                // walk the code groups at the app domain level and look for one that grants
                // access to the GAC with an UrlMembershipCondition. 
                CodeGroup rootGroup = policyLevel.RootCodeGroup; 
                bool foundGacCondition = false;
                foreach (CodeGroup childGroup in rootGroup.Children) { 
                    if (childGroup.MembershipCondition is GacMembershipCondition) {
                        foundGacCondition = true;
                        // if we found the GAC token and also have the GacMembershipCondition
                        // the policy file needs to be upgraded to just include the GacMembershipCondition 
                        Debug.Assert(!foundGacCondition);
                        break; 
                    } 
                }
                // add one as a child of the toplevel group after 
                // some sanity checking to make sure it's an ASP.NET policy file
                // which always begins with a FirstMatchCodeGroup granting nothing
                // this might not upgrade some custom policy files
                if (!foundGacCondition) { 
                    if (rootGroup is FirstMatchCodeGroup) {
                        FirstMatchCodeGroup firstMatch = (FirstMatchCodeGroup)rootGroup; 
                        if (firstMatch.MembershipCondition is AllMembershipCondition && 
                            firstMatch.PermissionSetName == "Nothing") {
                            PermissionSet fullTrust = new PermissionSet(PermissionState.Unrestricted); 
                            CodeGroup gacGroup = new UnionCodeGroup(new GacMembershipCondition(),
                                                                    new PolicyStatement(fullTrust));
                            // now, walk the current groups and insert our new group immediately before the old Gac group
                            // we'll need to use heuristics for this: it will be an UrlMembershipCondition group with full trust 
                            CodeGroup newRoot = new FirstMatchCodeGroup(rootGroup.MembershipCondition, rootGroup.PolicyStatement);
                            foreach (CodeGroup childGroup in rootGroup.Children) { 
                                // is this the target old $Gac$ group? 
                                // insert our new GacMembershipCondition group ahead of it
                                if ((childGroup is UnionCodeGroup) && 
                                    (childGroup.MembershipCondition is UrlMembershipCondition) &&
                                    childGroup.PolicyStatement.PermissionSet.IsUnrestricted()) {
                                    if (null != gacGroup) {
                                        newRoot.AddChild(gacGroup); 
                                        gacGroup = null;
                                    } 
                                } 
                                // append this group to the root group
                                // AddChild itself does a deep Copy to get any 
                                // child groups so we don't need one here
                                newRoot.AddChild(childGroup);
                            }
                            policyLevel.RootCodeGroup = newRoot; 
                        }
                    } 
                } 
            }
            return policyLevel; 
#pragma warning restore 618
        }

        internal class AspNetAppDomainManager : AppDomainManager { 
            private HostSecurityManager aspNetHostSecurityManager = null;
 
            public AspNetAppDomainManager() { 
                aspNetHostSecurityManager = new AspNetHostSecurityManager();
            } 

            public override HostSecurityManager HostSecurityManager {
                get {
                    return aspNetHostSecurityManager; 
                }
            } 
        } 

        internal class AspNetHostSecurityManager : HostSecurityManager { 
            private PermissionSet Nothing = new PermissionSet(PermissionState.None);
            private PermissionSet FullTrust = new PermissionSet(PermissionState.Unrestricted);
            private HostSecurityPolicyResolver hostSecurityPolicyResolver = null;
 
            public override HostSecurityManagerOptions Flags {
                get { 
                    return HostSecurityManagerOptions.HostResolvePolicy; 
                }
            } 

            [SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.SerializationFormatter)]
            public override PermissionSet ResolvePolicy(Evidence evidence) {
                if (base.ResolvePolicy(evidence).IsUnrestricted()) { 
                    return FullTrust;
                } 
 
                if (!String.IsNullOrEmpty(HttpRuntime.HostSecurityPolicyResolverType) && hostSecurityPolicyResolver == null) {
                    hostSecurityPolicyResolver = Activator.CreateInstance( 
                        Type.GetType(HttpRuntime.HostSecurityPolicyResolverType)) as HostSecurityPolicyResolver;
                }

                if (hostSecurityPolicyResolver != null) { 
                    switch (hostSecurityPolicyResolver.ResolvePolicy(evidence)) {
                        case HostSecurityPolicyResults.FullTrust: 
                            return FullTrust; 
                        case HostSecurityPolicyResults.AppDomainTrust:
                            return HttpRuntime.NamedPermissionSet; 
                        case HostSecurityPolicyResults.Nothing:
                            return Nothing;
                        case HostSecurityPolicyResults.DefaultPolicy:
                            break; 
                    }
                } 
 
                if (HttpRuntime.PolicyLevel == null || HttpRuntime.PolicyLevel.Resolve(evidence).PermissionSet.IsUnrestricted())
                    return FullTrust; 
                else if (HttpRuntime.PolicyLevel.Resolve(evidence).PermissionSet.Equals(Nothing))
                    return Nothing;
                else
                    return HttpRuntime.NamedPermissionSet; 
            }
        } 
 
        private static void PopulateDomainBindings(String domainId, String appId, String appName,
                                                    String appPath, VirtualPath appVPath, 
                                                    AppDomainSetup setup, IDictionary dict) {
            // assembly loading settings

            // We put both the old and new bin dir names on the private bin path 
            setup.PrivateBinPathProbe   = "*";  // disable loading from app base
            setup.ShadowCopyFiles       = "true"; 
            setup.ApplicationBase       = appPath; 
            setup.ApplicationName       = appName;
            setup.ConfigurationFile     = HttpConfigurationSystem.WebConfigFileName; 

            // Disallow code download, since it's unreliable in services (ASURT 123836/127606)
            setup.DisallowCodeDownload  = true;
 
            // internal settings
            dict.Add(".appDomain",     "*"); 
            dict.Add(".appId",         appId); 
            dict.Add(".appPath",       appPath);
            dict.Add(".appVPath",      appVPath.VirtualPathString); 
            dict.Add(".domainId",      domainId);
        }

        private static Evidence GetDefaultDomainIdentity() { 
            Evidence evidence = AppDomain.CurrentDomain.Evidence; // CurrentDomain.Evidence returns a clone so we can modify it if we need
            bool hasZone = evidence.GetHostEvidence() != null; 
            bool hasUrl = evidence.GetHostEvidence() != null; 

            if (!hasZone) 
                evidence.AddHostEvidence(new Zone(SecurityZone.MyComputer));

            if (!hasUrl)
                evidence.AddHostEvidence(new Url("ms-internal-microsoft-asp-net-webhost-20")); 

            return evidence; 
        } 

        private static int s_domainCount = 0; 
        private static Object s_domainCountLock = new Object();

        private static String ConstructAppDomainId(String id) {
            int domainCount = 0; 
            lock (s_domainCountLock) {
                domainCount = ++s_domainCount; 
            } 
            return id + "-" + domainCount.ToString(NumberFormatInfo.InvariantInfo) + "-" + DateTime.UtcNow.ToFileTime().ToString();
        } 

        internal LockableAppDomainContext GetLockableAppDomainContext (string appId) {
            lock (this) {
                LockableAppDomainContext ac; 
                if (!_appDomains.TryGetValue(appId, out ac)) {
                    ac = new LockableAppDomainContext(); 
                    _appDomains.Add (appId, ac); 
                }
 
                return ac;
            }
        }
 
        // take a copy of _appDomains collection so that it can be used without locking on ApplicationManager
        private Dictionary CloneAppDomainsCollection() { 
            lock (this) { 
                return new Dictionary(_appDomains, StringComparer.OrdinalIgnoreCase);
            } 
        }

    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK