File: HttpRuntime.cs
Project: ndp\fx\src\xsp\system\Web\System.Web.csproj (System.Web)
//------------------------------------------------------------------------------
// <copyright file="HttpRuntime.cs" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
 
/*
 * The ASP.NET runtime services
 *
 * Copyright (c) 1998 Microsoft Corporation
 */
 
namespace System.Web {
    using System;
    using System.Collections;
    using System.Configuration;
    using System.Data;
    using System.Data.Common;
    using System.Diagnostics.CodeAnalysis;
    using System.Globalization;
    using System.IO;
    using System.Net;
    using System.Reflection;
    using System.Resources;
    using System.Runtime;
    using System.Runtime.InteropServices;
    using System.Runtime.Remoting.Messaging;
    using System.Security;
    using System.Security.Cryptography;
    using System.Security.Permissions;
    using System.Security.Policy;
    using System.Security.Principal;
    using System.Text;
    using System.Threading;
    using System.Web;
    using System.Web.Caching;
    using System.Web.Compilation;
    using System.Web.Configuration;
    using System.Web.Hosting;
    using System.Web.Management;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.Util;
    using System.Xml;
    using Microsoft.Win32;
 
    /// <devdoc>
    ///    <para>Provides a set of ASP.NET runtime services.</para>
    /// </devdoc>
    public sealed class HttpRuntime {
 
        internal const string codegenDirName = "Temporary ASP.NET Files";
        internal const string profileFileName = "profileoptimization.prof";
 
        private static HttpRuntime _theRuntime;   // single instance of the class
        internal static byte[] s_autogenKeys = new byte[1024];
 
        //
        // Names of special ASP.NET directories
        //
 
        internal const string BinDirectoryName = "bin";
        internal const string CodeDirectoryName = "App_Code";
        internal const string WebRefDirectoryName = "App_WebReferences";
        internal const string ResourcesDirectoryName = "App_GlobalResources";
        internal const string LocalResourcesDirectoryName = "App_LocalResources";
        internal const string DataDirectoryName = "App_Data";
        internal const string ThemesDirectoryName = "App_Themes";
        internal const string GlobalThemesDirectoryName = "Themes";
        internal const string BrowsersDirectoryName = "App_Browsers";
 
        private static string DirectorySeparatorString = new string(Path.DirectorySeparatorChar, 1);
        private static string DoubleDirectorySeparatorString = new string(Path.DirectorySeparatorChar, 2);
        private static char[] s_InvalidPhysicalPathChars = { '/', '?', '*', '<', '>', '|', '"' };
 
 
 
#if OLD
        // For s_forbiddenDirs and s_forbiddenDirsConstant, see
        // ndll.h, and RestrictIISFolders in regiis.cxx
 
        internal static string[]    s_forbiddenDirs =   {
                                        BinDirectoryName,
                                        CodeDirectoryName,
                                        DataDirectoryName,
                                        ResourcesDirectoryName,
                                        WebRefDirectoryName,
                                    };
 
        internal static Int32[]     s_forbiddenDirsConstant = {
                                        UnsafeNativeMethods.RESTRICT_BIN,
                                        UnsafeNativeMethods.RESTRICT_CODE,
                                        UnsafeNativeMethods.RESTRICT_DATA,
                                        UnsafeNativeMethods.RESTRICT_RESOURCES,
                                        UnsafeNativeMethods.RESTRICT_WEBREFERENCES,
                                    };
#endif
 
        static HttpRuntime() {
            AddAppDomainTraceMessage("*HttpRuntime::cctor");
 
            StaticInit();
 
            _theRuntime = new HttpRuntime();
 
            _theRuntime.Init();
 
            AddAppDomainTraceMessage("HttpRuntime::cctor*");
        }
 
        [SecurityPermission(SecurityAction.LinkDemand, Unrestricted = true)]
        public HttpRuntime() {
        }
 
        //
        // static initialization to get hooked up to the unmanaged code
        // get installation directory, etc.
        //
 
        private static bool s_initialized = false;
        private static String s_installDirectory;
        private static bool s_isEngineLoaded = false;
 
        // Force the static initialization of this class.
        internal static void ForceStaticInit() { }
 
        private static void StaticInit() {
            if (s_initialized) {
                // already initialized
                return;
            }
 
            bool isEngineLoaded = false;
            bool wasEngineLoadedHere = false;
            String installDir = null;
 
            // load webengine.dll if it is not loaded already
 
#if !FEATURE_PAL // FEATURE_PAL does not enable IIS-based hosting features
 
            installDir = RuntimeEnvironment.GetRuntimeDirectory();
 
            if (UnsafeNativeMethods.GetModuleHandle(ModName.ENGINE_FULL_NAME) != IntPtr.Zero) {
                isEngineLoaded = true;
            }
 
            // Load webengine.dll if not loaded already
 
            if (!isEngineLoaded) {
                String fullPath = installDir + Path.DirectorySeparatorChar + ModName.ENGINE_FULL_NAME;
 
                if (UnsafeNativeMethods.LoadLibrary(fullPath) != IntPtr.Zero) {
                    isEngineLoaded = true;
                    wasEngineLoadedHere = true;
                }
            }
 
            if (isEngineLoaded) {
                UnsafeNativeMethods.InitializeLibrary(false);
 
                if (wasEngineLoadedHere) {
                    UnsafeNativeMethods.PerfCounterInitialize();
                }
            }
 
#else // !FEATURE_PAL
            string p = typeof(object).Module.FullyQualifiedName;
            installDir = Path.GetDirectoryName(p);
#endif // !FEATURE_PAL
 
            s_installDirectory = installDir;
            s_isEngineLoaded = isEngineLoaded;
            s_initialized = true;
 
            PopulateIISVersionInformation();
 
            AddAppDomainTraceMessage("Initialize");
        }
 
        //
        // Runtime services
        //
 
        private NamedPermissionSet _namedPermissionSet;
        private PolicyLevel _policyLevel;
        private string _hostSecurityPolicyResolverType = null;
        private FileChangesMonitor _fcm;
        private Cache _cachePublic;
        private bool _isOnUNCShare;
        private Profiler _profiler;
        private RequestTimeoutManager _timeoutManager;
        private RequestQueue _requestQueue;
        private bool _apartmentThreading;
 
        private bool _processRequestInApplicationTrust;
        private bool _disableProcessRequestInApplicationTrust;
        private bool _isLegacyCas;
        //
        // Counters
        //
 
        private bool _beforeFirstRequest = true;
        private DateTime _firstRequestStartTime;
        private bool _firstRequestCompleted;
        private bool _userForcedShutdown;
        private bool _configInited;
        private bool _fusionInited;
        private int _activeRequestCount;
        private volatile bool _disposingHttpRuntime;
        private DateTime _lastShutdownAttemptTime;
        private bool _shutdownInProgress;
        private String _shutDownStack;
        private String _shutDownMessage;
        private ApplicationShutdownReason _shutdownReason = ApplicationShutdownReason.None;
        private string _trustLevel;
        private string _wpUserId;
        private bool _shutdownWebEventRaised;
 
        //
        // Header Newlines
        //
        private bool _enableHeaderChecking;
 
        //
        // Callbacks
        //
 
        private AsyncCallback _requestNotificationCompletionCallback;
        private AsyncCallback _handlerCompletionCallback;
        private HttpWorkerRequest.EndOfSendNotification _asyncEndOfSendCallback;
        private WaitCallback _appDomainUnloadallback;
 
        //
        // Initialization error (to be reported on subsequent requests)
        //
 
        private Exception _initializationError;
        private bool _hostingInitFailed; // make such errors non-sticky
        private Timer _appDomainShutdownTimer = null;
 
 
        //
        // App domain related
        //
 
        private String _tempDir;
        private String _codegenDir;
        private String _appDomainAppId;
        private String _appDomainAppPath;
        private VirtualPath _appDomainAppVPath;
        private String _appDomainId;
 
        //
        // Debugging support
        //
 
        private bool _debuggingEnabled = false;
 
        //
        // App_Offline.htm support
        //
 
        private const string AppOfflineFileName = "App_Offline.htm";
        private const long MaxAppOfflineFileLength = 1024 * 1024;
        private byte[] _appOfflineMessage;
 
        //
        // Client script support
        //
 
        private const string AspNetClientFilesSubDirectory = "asp.netclientfiles";
        private const string AspNetClientFilesParentVirtualPath = "/aspnet_client/system_web/";
        private string _clientScriptVirtualPath;
        private string _clientScriptPhysicalPath;
 
        //
        // IIS version and whether we're using the integrated pipeline
        //
        private static Version _iisVersion;
        private static bool _useIntegratedPipeline;
 
        //
        // Prefetch
        //
        private static bool _enablePrefetchOptimization;
 
        /////////////////////////////////////////////////////////////////////////
        // 3 steps of initialization:
        //     Init() is called from HttpRuntime cctor
        //     HostingInit() is called by the Hosting Environment
        //     FirstRequestInit() is called on first HTTP request
        //
 
        /*
         * Context-less initialization (on app domain creation)
         */
        private void Init() {
            try {
#if !FEATURE_PAL
                if (Environment.OSVersion.Platform != PlatformID.Win32NT)
                    throw new PlatformNotSupportedException(SR.GetString(SR.RequiresNT));
#else // !FEATURE_PAL
                // ROTORTODO
                // Do nothing: FEATURE_PAL environment will always support ASP.NET hosting
#endif // !FEATURE_PAL
 
                _profiler = new Profiler();
                _timeoutManager = new RequestTimeoutManager();
                _wpUserId = GetCurrentUserName();
 
                _requestNotificationCompletionCallback = new AsyncCallback(this.OnRequestNotificationCompletion);
                _handlerCompletionCallback = new AsyncCallback(this.OnHandlerCompletion);
                _asyncEndOfSendCallback = new HttpWorkerRequest.EndOfSendNotification(this.EndOfSendCallback);
                _appDomainUnloadallback = new WaitCallback(this.ReleaseResourcesAndUnloadAppDomain);
 
 
                // appdomain values
                if (GetAppDomainString(".appDomain") != null) {
 
                    Debug.Assert(HostingEnvironment.IsHosted);
 
                    _appDomainAppId = GetAppDomainString(".appId");
                    _appDomainAppPath = GetAppDomainString(".appPath");
                    _appDomainAppVPath = VirtualPath.CreateNonRelativeTrailingSlash(GetAppDomainString(".appVPath"));
                    _appDomainId = GetAppDomainString(".domainId");
 
                    _isOnUNCShare = StringUtil.StringStartsWith(_appDomainAppPath, "\\\\");
 
                    // init perf counters for this appdomain
                    PerfCounters.Open(_appDomainAppId);
                }
                else {
                    Debug.Assert(!HostingEnvironment.IsHosted);
                }
 
                // _appDomainAppPath should be set before file change notifications are initialized
                // DevDiv 248126: Check httpRuntime fcnMode first before we use the registry key
                _fcm = new FileChangesMonitor(HostingEnvironment.FcnMode);
            }
            catch (Exception e) {
                // remember static initalization error
                InitializationException = e;
            }
        }
 
        private void SetUpDataDirectory() {
 
            // Set the DataDirectory (see VSWhidbey 226834) with permission (DevDiv 29614)
            string dataDirectory = Path.Combine(_appDomainAppPath, DataDirectoryName);
            AppDomain.CurrentDomain.SetData("DataDirectory", dataDirectory,
                    new FileIOPermission(FileIOPermissionAccess.PathDiscovery, dataDirectory));
        }
 
        private void DisposeAppDomainShutdownTimer() {
            Timer timer = _appDomainShutdownTimer;
            if (timer != null && Interlocked.CompareExchange(ref _appDomainShutdownTimer, null, timer) == timer) {
                timer.Dispose();
            }
        }
 
        private void AppDomainShutdownTimerCallback(Object state) {
            try {
                DisposeAppDomainShutdownTimer();
                ShutdownAppDomain(ApplicationShutdownReason.InitializationError, "Initialization Error");
            }
            catch { } // ignore exceptions
        }
 
        /*
         * Restart the AppDomain in 10 seconds
         */
        private void StartAppDomainShutdownTimer() {
            if (_appDomainShutdownTimer == null && !_shutdownInProgress) {
                lock (this) {
                    if (_appDomainShutdownTimer == null && !_shutdownInProgress) {
                        _appDomainShutdownTimer = new Timer(
                            new TimerCallback(this.AppDomainShutdownTimerCallback),
                            null,
                            10 * 1000,
                            0);
                    }
                }
            }
        }
 
 
        /*
         * Initialization from HostingEnvironment of HTTP independent features
         */
        private void HostingInit(HostingEnvironmentFlags hostingFlags, PolicyLevel policyLevel, Exception appDomainCreationException) {
            using (new ApplicationImpersonationContext()) {
                try {
                    // To ignore FCN during initialization
                    _firstRequestStartTime = DateTime.UtcNow;
 
                    SetUpDataDirectory();
 
                    // Throw an exception about lack of access to app directory early on
                    EnsureAccessToApplicationDirectory();
 
                    // Monitor renames to directories we are watching, and notifications on the bin directory
                    //
                    // Note that this must be the first monitoring that we do of the application directory.
                    // There is a bug in Windows 2000 Server where notifications on UNC shares do not
                    // happen correctly if:
                    //      1. the directory is monitored for regular notifications
                    //      2. the directory is then monitored for directory renames
                    //      3. the directory is monitored again for regular notifications
                    StartMonitoringDirectoryRenamesAndBinDirectory();
 
                    // Initialize ObjectCacheHost before config is read, since config relies on the cache
                    if (InitializationException == null) {
                        HostingEnvironment.InitializeObjectCacheHost();
                    }
 
                    //
                    // Get the configuration needed to minimally initialize
                    // the components required for a complete configuration system,
                    // especially SetTrustLevel.
                    //
                    // We want to do this before calling SetUpCodegenDirectory(),
                    // to remove the risk of the config system loading
                    // codegen assemblies in full trust (VSWhidbey 460506)
                    //
                    CacheSection cacheSection;
                    TrustSection trustSection;
                    SecurityPolicySection securityPolicySection;
                    CompilationSection compilationSection;
                    HostingEnvironmentSection hostingEnvironmentSection;
                    Exception configInitException;
 
                    GetInitConfigSections(
                            out cacheSection,
                            out trustSection,
                            out securityPolicySection,
                            out compilationSection,
                            out hostingEnvironmentSection,
                            out configInitException);
 
                    // Once the configuration system is initialized, we can read
                    // the cache configuration settings.
                    //
                    // Note that we must do this after we start monitoring directory renames,
                    // as reading config will cause file monitoring on the application directory
                    // to occur.
 
                    // Set up the codegen directory for the app.  This needs to be done before we process
                    // the policy file, because it needs to replace the $CodeGen$ token.
                    SetUpCodegenDirectory(compilationSection);
 
                    if(compilationSection != null) {
                        _enablePrefetchOptimization = compilationSection.EnablePrefetchOptimization;
                        if(_enablePrefetchOptimization) {
                            UnsafeNativeMethods.StartPrefetchActivity((uint)StringUtil.GetStringHashCode(_appDomainAppId));
                        }
                    }
 
                    // NOTE: after calling SetUpCodegenDirectory(), and until we call SetTrustLevel(), we are at
                    // risk of codegen assemblies being loaded in full trust.  No code that might cause
                    // assembly loading should be added here! This is only valid if the legacyCasModel is set
                    // to true in <trust> section.
 
                    // Throw the original configuration exception from ApplicationManager if configuration is broken.
                    if (appDomainCreationException != null) {
                        throw appDomainCreationException;
                    }
 
                    if (trustSection == null || String.IsNullOrEmpty(trustSection.Level)) {
                        throw new ConfigurationErrorsException(SR.GetString(SR.Config_section_not_present, "trust"));
                    }
 
                    if (trustSection.LegacyCasModel) {
                        try {
                            _disableProcessRequestInApplicationTrust = false;
                            _isLegacyCas = true;
                            // Set code access policy on the app domain
                            SetTrustLevel(trustSection, securityPolicySection);
                        }
                        catch {
                            // throw the original config exception if it exists
                            if (configInitException != null)
                                throw configInitException;
                            throw;
                        }
                    }
                    else if ((hostingFlags & HostingEnvironmentFlags.ClientBuildManager) != 0) {
                        _trustLevel = "Full";
                    }
                    else {
                        _disableProcessRequestInApplicationTrust = true;
                        // Set code access policy properties of the runtime object
                        SetTrustParameters(trustSection, securityPolicySection, policyLevel);
                    }
 
                    // Configure fusion to use directories set in the app config
                    InitFusion(hostingEnvironmentSection);
 
                    // set the sliding expiration for URL metadata
                    CachedPathData.InitializeUrlMetadataSlidingExpiration(hostingEnvironmentSection);
 
                    // Complete initialization of configuration.
                    // Note that this needs to be called after SetTrustLevel,
                    // as it indicates that we have the permission set needed
                    // to correctly run configuration section handlers.
                    // As little config should be read before CompleteInit() as possible.
                    // No section that runs before CompleteInit() should demand permissions,
                    // as the permissions set has not yet determined until SetTrustLevel()
                    // is called.
                    HttpConfigurationSystem.CompleteInit();
 
                    //
                    // If an exception occurred loading configuration,
                    // we are now ready to handle exception processing
                    // with the correct trust level set.
                    //
                    if (configInitException != null) {
                        throw configInitException;
                    }
 
                    SetThreadPoolLimits();
 
                    SetAutogenKeys();
 
                    // Initialize the build manager
                    BuildManager.InitializeBuildManager();
 
                    if(compilationSection != null && compilationSection.ProfileGuidedOptimizations == ProfileGuidedOptimizationsFlags.All) {
                        ProfileOptimization.SetProfileRoot(_codegenDir);
                        ProfileOptimization.StartProfile(profileFileName);
                    }
 
                    // Determine apartment threading setting
                    InitApartmentThreading();
 
                    // Init debugging
                    InitDebuggingSupport();
 
                    _processRequestInApplicationTrust = trustSection.ProcessRequestInApplicationTrust;
 
                    // Init AppDomain Resource Perf Counters
                    AppDomainResourcePerfCounters.Init();
 
 
                    RelaxMapPathIfRequired();
                }
                catch (Exception e) {
                    _hostingInitFailed = true;
                    InitializationException = e;
 
                    Debug.Trace("AppDomainFactory", "HostingInit failed. " + e.ToString());
 
                    if ((hostingFlags & HostingEnvironmentFlags.ThrowHostingInitErrors) != 0)
                        throw;
                }
            }
        }
 
        internal static Exception InitializationException {
            get {
                return _theRuntime._initializationError;
            }
 
            // The exception is "cached" for 10 seconds, then the AppDomain is restarted.
            set {
                _theRuntime._initializationError = value;
                // In v2.0, we shutdown immediately if hostingInitFailed...so we don't need the timer
                if (!HostingInitFailed) {
                    _theRuntime.StartAppDomainShutdownTimer();
                }
            }
        }
 
        internal static bool HostingInitFailed {
            get {
                return _theRuntime._hostingInitFailed;
            }
        }
 
        internal static void InitializeHostingFeatures(HostingEnvironmentFlags hostingFlags, PolicyLevel policyLevel, Exception appDomainCreationException) {
            _theRuntime.HostingInit(hostingFlags, policyLevel, appDomainCreationException);
        }
 
        internal static bool EnableHeaderChecking {
            get {
                return _theRuntime._enableHeaderChecking;
            }
        }
 
        internal static bool ProcessRequestInApplicationTrust {
            get {
                return _theRuntime._processRequestInApplicationTrust;
            }
        }
 
        internal static bool DisableProcessRequestInApplicationTrust {
            get {
                return _theRuntime._disableProcessRequestInApplicationTrust;
            }
        }
 
        internal static bool IsLegacyCas {
            get {
                return _theRuntime._isLegacyCas;
            }
        }
 
        internal static byte[] AppOfflineMessage {
            get {
                return _theRuntime._appOfflineMessage;
            }
        }
 
        /*
         * Initialization on first request (context available)
         */
        private void FirstRequestInit(HttpContext context) {
            Exception error = null;
 
            if (InitializationException == null && _appDomainId != null) {
#if DBG
                HttpContext.SetDebugAssertOnAccessToCurrent(true);
#endif
                try {
                    using (new ApplicationImpersonationContext()) {
                        // Is this necessary?  See InitHttpConfiguration
                        CultureInfo savedCulture = Thread.CurrentThread.CurrentCulture;
                        CultureInfo savedUICulture = Thread.CurrentThread.CurrentUICulture;
 
                        try {
                            // Ensure config system is initialized
                            InitHttpConfiguration(); // be sure config system is set
 
                            // Check if applicaton is enabled
                            CheckApplicationEnabled();
 
                            // Check access to temp compilation directory (under hosting identity)
                            CheckAccessToTempDirectory();
 
                            // Initialize health monitoring
                            InitializeHealthMonitoring();
 
                            // Init request queue (after reading config)
                            InitRequestQueue();
 
                            // configure the profiler according to config
                            InitTrace(context);
 
                            // Start heatbeat for Web Event Health Monitoring
                            HealthMonitoringManager.StartHealthMonitoringHeartbeat();
 
                            // Remove read and browse access of the bin directory
                            RestrictIISFolders(context);
 
                            // Preload all assemblies from bin (only if required).  ASURT 114486
                            PreloadAssembliesFromBin();
 
                            // Decide whether or not to encode headers.  VsWhidbey 257154
                            InitHeaderEncoding();
 
                            // Force the current encoder + validator to load so that there's a deterministic
                            // place (here) for an exception to occur if there's a load error
                            HttpEncoder.InitializeOnFirstRequest();
                            RequestValidator.InitializeOnFirstRequest();
 
                            if (context.WorkerRequest is ISAPIWorkerRequestOutOfProc) {
                                // Make sure that the <processModel> section has no errors
                                ProcessModelSection processModel = RuntimeConfig.GetMachineConfig().ProcessModel;
                            }
                        }
                        finally {
                            Thread.CurrentThread.CurrentUICulture = savedUICulture;
                            SetCurrentThreadCultureWithAssert(savedCulture);
                        }
                    }
                }
                catch (ConfigurationException e) {
                    error = e;
                }
                catch (Exception e) {
                    // remember second-phase initialization error
                    error = new HttpException(SR.GetString(SR.XSP_init_error, e.Message), e);
                }
                finally {
#if DBG
                    HttpContext.SetDebugAssertOnAccessToCurrent(false);
#endif
                }
            }
 
            if (InitializationException != null) {
                // throw cached exception.  We need to wrap it in a new exception, otherwise
                // we lose the original stack.
                throw new HttpException(InitializationException.Message, InitializationException);
            }
            else if (error != null) {
                InitializationException = error;
                // throw new exception
                throw error;
            }
 
            AddAppDomainTraceMessage("FirstRequestInit");
        }
 
        [SecurityPermission(SecurityAction.Assert, ControlThread = true)]
        internal static void SetCurrentThreadCultureWithAssert(CultureInfo cultureInfo) {
            Thread.CurrentThread.CurrentCulture = cultureInfo;
        }
 
        private void EnsureFirstRequestInit(HttpContext context) {
            if (_beforeFirstRequest) {
                lock (this) {
                    if (_beforeFirstRequest) {
                        _firstRequestStartTime = DateTime.UtcNow;
                        FirstRequestInit(context);
                        _beforeFirstRequest = false;
                        context.FirstRequest = true;
                    }
                }
            }
        }
 
        private void EnsureAccessToApplicationDirectory() {
            if (!FileUtil.DirectoryAccessible(_appDomainAppPath)) {
                // 
                if (_appDomainAppPath.IndexOf('?') >= 0) {
                    // Possible Unicode when not supported
                    throw new HttpException(SR.GetString(SR.Access_denied_to_unicode_app_dir, _appDomainAppPath));
                }
                else {
                    throw new HttpException(SR.GetString(SR.Access_denied_to_app_dir, _appDomainAppPath));
                }
            }
        }
 
        private void StartMonitoringDirectoryRenamesAndBinDirectory() {
            _fcm.StartMonitoringDirectoryRenamesAndBinDirectory(AppDomainAppPathInternal, new FileChangeEventHandler(this.OnCriticalDirectoryChange));
        }
 
        //
        // Monitor a local resources subdirectory and unload appdomain when it changes
        //
        internal static void StartListeningToLocalResourcesDirectory(VirtualPath virtualDir) {
#if !FEATURE_PAL // FEATURE_PAL does not enable file change notification
            _theRuntime._fcm.StartListeningToLocalResourcesDirectory(virtualDir);
#endif // !FEATURE_PAL
        }
 
        //
        // Get the configuration needed to minimally initialize
        // the components required for a complete configuration system,
        //
        // Note that if the application configuration file has an error,
        // AppLKGConfig will still retreive any valid configuration from
        // that file, or from location directives that apply to the
        // application path. This implies that an administrator can
        // lock down an application's trust level in root web.config,
        // and it will still take effect if the application's web.config
        // has errors.
        //
        private void GetInitConfigSections(
                out CacheSection cacheSection,
                out TrustSection trustSection,
                out SecurityPolicySection securityPolicySection,
                out CompilationSection compilationSection,
                out HostingEnvironmentSection hostingEnvironmentSection,
                out Exception initException) {
 
            cacheSection = null;
            trustSection = null;
            securityPolicySection = null;
            compilationSection = null;
            hostingEnvironmentSection = null;
            initException = null;
 
            // AppLKGConfig is guaranteed to not throw an exception.
            RuntimeConfig appLKGConfig = RuntimeConfig.GetAppLKGConfig();
 
            // AppConfig may throw an exception.
            RuntimeConfig appConfig = null;
            try {
                appConfig = RuntimeConfig.GetAppConfig();
            }
            catch (Exception e) {
                initException = e;
            }
 
            // Cache section
            if (appConfig != null) {
                try {
                    cacheSection = appConfig.Cache;
                }
                catch (Exception e) {
                    if (initException == null) {
                        initException = e;
                    }
                }
            }
 
            if (cacheSection == null) {
                cacheSection = appLKGConfig.Cache;
            }
 
            // Trust section
            if (appConfig != null) {
                try {
                    trustSection = appConfig.Trust;
                }
                catch (Exception e) {
                    if (initException == null) {
                        initException = e;
                    }
                }
            }
 
            if (trustSection == null) {
                trustSection = appLKGConfig.Trust;
            }
 
            // SecurityPolicy section
            if (appConfig != null) {
                try {
                    securityPolicySection = appConfig.SecurityPolicy;
                }
                catch (Exception e) {
                    if (initException == null) {
                        initException = e;
                    }
                }
            }
 
            if (securityPolicySection == null) {
                securityPolicySection = appLKGConfig.SecurityPolicy;
            }
 
            // Compilation section
            if (appConfig != null) {
                try {
                    compilationSection = appConfig.Compilation;
                }
                catch (Exception e) {
                    if (initException == null) {
                        initException = e;
                    }
                }
            }
 
            if (compilationSection == null) {
                compilationSection = appLKGConfig.Compilation;
            }
 
            // HostingEnvironment section
            if (appConfig != null) {
                try {
                    hostingEnvironmentSection = appConfig.HostingEnvironment;
                }
                catch (Exception e) {
                    if (initException == null) {
                        initException = e;
                    }
                }
            }
 
            if (hostingEnvironmentSection == null) {
                hostingEnvironmentSection = appLKGConfig.HostingEnvironment;
            }
        }
 
        // Set up the codegen directory for the app
        [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification = "This call site is trusted.")]
        private void SetUpCodegenDirectory(CompilationSection compilationSection) {
            AppDomain appDomain = Thread.GetDomain();
 
            string codegenBase;
            
            // devdiv 1038337. Passing the corresponding IsDevelopmentEnvironment flag to ConstructSimpleAppName
            string simpleAppName = System.Web.Hosting.AppManagerAppDomainFactory.ConstructSimpleAppName(
                AppDomainAppVirtualPath, HostingEnvironment.IsDevelopmentEnvironment);
 
            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);
                }
#if FEATURE_PAL
            } else {
                System.UInt32 length = 0;
                StringBuilder sb = null;
                bool bRet;
 
                // Get the required length
                bRet = UnsafeNativeMethods.GetUserTempDirectory(
                                    UnsafeNativeMethods.DeploymentDirectoryType.ddtInstallationDependentDirectory,
                                    null, ref length);
 
                if (true == bRet) {
                    // now, allocate the string
                    sb = new StringBuilder ((int)length);
 
                    // call again to get the value
                    bRet = UnsafeNativeMethods.GetUserTempDirectory(
                                    UnsafeNativeMethods.DeploymentDirectoryType.ddtInstallationDependentDirectory,
                                    sb, ref length);
                }
 
                if (false == bRet) {
                    throw new ConfigurationException(
                        HttpRuntime.FormatResourceString(SR.Invalid_temp_directory, tempDirAttribName));
                }
 
                tempDirectory = Path.Combine(sb.ToString(), codegenDirName);
            }
 
            // Always try to create the ASP.Net temp directory for FEATURE_PAL
#endif // FEATURE_PAL
 
                // 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);
                }
#if !FEATURE_PAL
            }
            else {
                tempDirectory = Path.Combine(s_installDirectory, codegenDirName);
            }
#endif // !FEATURE_PAL
 
            // 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 are not in a CBM scenario and we're in a service (!UserInteractive), 
                // as TEMP could point to unwanted places.
 
#if !FEATURE_PAL // always fail here
                if ((!BuildManagerHost.InClientBuildManager) && (!Environment.UserInteractive))
#endif // !FEATURE_PAL
                {
                    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, codegenDirName);
            }
 
            _tempDir = tempDirectory;
 
            codegenBase = Path.Combine(tempDirectory, simpleAppName);
 
#pragma warning disable 0618    // To avoid deprecation warning
            appDomain.SetDynamicBase(codegenBase);
#pragma warning restore 0618
 
            _codegenDir = Thread.GetDomain().DynamicDirectory;
 
            // Create the codegen directory if needed
            Directory.CreateDirectory(_codegenDir);
        }
 
        private void InitFusion(HostingEnvironmentSection hostingEnvironmentSection) {
 
            AppDomain appDomain = Thread.GetDomain();
 
            // If there is a double backslash in the string, get rid of it (ASURT 122191)
            // Make sure to skip the first char, to avoid breaking the UNC case
            string appDomainAppPath = _appDomainAppPath;
            if (appDomainAppPath.IndexOf(DoubleDirectorySeparatorString, 1, StringComparison.Ordinal) >= 1) {
                appDomainAppPath = appDomainAppPath[0] + appDomainAppPath.Substring(1).Replace(DoubleDirectorySeparatorString,
                    DirectorySeparatorString);
            }
 
#pragma warning disable 0618    // To avoid deprecation warning
            // Allow assemblies from 'bin' to be loaded
            appDomain.AppendPrivatePath(appDomainAppPath + BinDirectoryName);
#pragma warning restore 0618
 
            // If shadow copying was disabled via config, turn it off (DevDiv 30864)
            if (hostingEnvironmentSection != null && !hostingEnvironmentSection.ShadowCopyBinAssemblies) {
#pragma warning disable 0618    // To avoid deprecation warning
                appDomain.ClearShadowCopyPath();
#pragma warning restore 0618
            }
            else {
                // enable shadow-copying from bin
#pragma warning disable 0618    // To avoid deprecation warning
                appDomain.SetShadowCopyPath(appDomainAppPath + BinDirectoryName);
#pragma warning restore 0618
            }
 
            // Get rid of the last part of the directory (the app name), since it will
            // be re-appended.
            string parentDir = Directory.GetParent(_codegenDir).FullName;
#pragma warning disable 0618    // To avoid deprecation warning
            appDomain.SetCachePath(parentDir);
#pragma warning restore 0618
 
            _fusionInited = true;
        }
 
        private void InitRequestQueue() {
            RuntimeConfig config = RuntimeConfig.GetAppConfig();
            HttpRuntimeSection runtimeConfig = config.HttpRuntime;
            ProcessModelSection processConfig = config.ProcessModel;
 
            if (processConfig.AutoConfig) {
                _requestQueue = new RequestQueue(
                    88 * processConfig.CpuCount,
                    76 * processConfig.CpuCount,
                    runtimeConfig.AppRequestQueueLimit,
                    processConfig.ClientConnectedCheck);
            }
            else {
 
                // Configuration section handlers cannot validate values based on values
                // in other configuration sections, so we validate minFreeThreads and
                // minLocalRequestFreeThreads here.
                int maxThreads = (processConfig.MaxWorkerThreadsTimesCpuCount < processConfig.MaxIoThreadsTimesCpuCount) ? processConfig.MaxWorkerThreadsTimesCpuCount : processConfig.MaxIoThreadsTimesCpuCount;
                // validate minFreeThreads
                if (runtimeConfig.MinFreeThreads >= maxThreads) {
                    if (runtimeConfig.ElementInformation.Properties["minFreeThreads"].LineNumber == 0) {
                        if (processConfig.ElementInformation.Properties["maxWorkerThreads"].LineNumber != 0) {
                            throw new ConfigurationErrorsException(SR.GetString(SR.Thread_pool_limit_must_be_greater_than_minFreeThreads, runtimeConfig.MinFreeThreads.ToString(CultureInfo.InvariantCulture)),
                                                                   processConfig.ElementInformation.Properties["maxWorkerThreads"].Source,
                                                                   processConfig.ElementInformation.Properties["maxWorkerThreads"].LineNumber);
                        }
                        else {
                            throw new ConfigurationErrorsException(SR.GetString(SR.Thread_pool_limit_must_be_greater_than_minFreeThreads, runtimeConfig.MinFreeThreads.ToString(CultureInfo.InvariantCulture)),
                                                                   processConfig.ElementInformation.Properties["maxIoThreads"].Source,
                                                                   processConfig.ElementInformation.Properties["maxIoThreads"].LineNumber);
                        }
                    }
                    else {
                        throw new ConfigurationErrorsException(SR.GetString(SR.Min_free_threads_must_be_under_thread_pool_limits, maxThreads.ToString(CultureInfo.InvariantCulture)),
                                                               runtimeConfig.ElementInformation.Properties["minFreeThreads"].Source,
                                                               runtimeConfig.ElementInformation.Properties["minFreeThreads"].LineNumber);
                    }
                }
                // validate minLocalRequestFreeThreads
                if (runtimeConfig.MinLocalRequestFreeThreads > runtimeConfig.MinFreeThreads) {
                    if (runtimeConfig.ElementInformation.Properties["minLocalRequestFreeThreads"].LineNumber == 0) {
                        throw new ConfigurationErrorsException(SR.GetString(SR.Local_free_threads_cannot_exceed_free_threads),
                                                               processConfig.ElementInformation.Properties["minFreeThreads"].Source,
                                                               processConfig.ElementInformation.Properties["minFreeThreads"].LineNumber);
                    }
                    else {
                        throw new ConfigurationErrorsException(SR.GetString(SR.Local_free_threads_cannot_exceed_free_threads),
                                                               runtimeConfig.ElementInformation.Properties["minLocalRequestFreeThreads"].Source,
                                                               runtimeConfig.ElementInformation.Properties["minLocalRequestFreeThreads"].LineNumber);
                    }
                }
 
                _requestQueue = new RequestQueue(
                    runtimeConfig.MinFreeThreads,
                    runtimeConfig.MinLocalRequestFreeThreads,
                    runtimeConfig.AppRequestQueueLimit,
                    processConfig.ClientConnectedCheck);
            }
        }
 
        private void InitApartmentThreading() {
            HttpRuntimeSection runtimeConfig = RuntimeConfig.GetAppConfig().HttpRuntime;
 
            if (runtimeConfig != null) {
                _apartmentThreading = runtimeConfig.ApartmentThreading;
            }
            else {
                _apartmentThreading = false;
            }
        }
 
        private void InitTrace(HttpContext context) {
            TraceSection traceConfig = RuntimeConfig.GetAppConfig().Trace;
 
            Profile.RequestsToProfile = traceConfig.RequestLimit;
            Profile.PageOutput = traceConfig.PageOutput;
            Profile.OutputMode = TraceMode.SortByTime;
            if (traceConfig.TraceMode == TraceDisplayMode.SortByCategory)
                Profile.OutputMode = TraceMode.SortByCategory;
 
            Profile.LocalOnly = traceConfig.LocalOnly;
            Profile.IsEnabled = traceConfig.Enabled;
            Profile.MostRecent = traceConfig.MostRecent;
            Profile.Reset();
 
            // the first request's context is created before InitTrace, so
            // we need to set this manually. (ASURT 93730)
            context.TraceIsEnabled = traceConfig.Enabled;
            TraceContext.SetWriteToDiagnosticsTrace(traceConfig.WriteToDiagnosticsTrace);
        }
 
        private void InitDebuggingSupport() {
            CompilationSection compConfig = RuntimeConfig.GetAppConfig().Compilation;
            _debuggingEnabled = compConfig.Debug;
        }
 
        /*
         * Pre-load all the bin assemblies if we're impersonated.  This way, if user code
         * calls Assembly.Load while impersonated, the assembly will already be loaded, and
         * we won't fail due to lack of permissions on the codegen dir (see ASURT 114486)
         */
        [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
        private void PreloadAssembliesFromBin() {
            bool appClientImpersonationEnabled = false;
 
            if (!_isOnUNCShare) {
                // if not on UNC share check if config has impersonation enabled (without userName)
                IdentitySection c = RuntimeConfig.GetAppConfig().Identity;
                if (c.Impersonate && c.ImpersonateToken == IntPtr.Zero)
                    appClientImpersonationEnabled = true;
            }
 
            if (!appClientImpersonationEnabled)
                return;
 
            // Get the path to the bin directory
            string binPath = HttpRuntime.BinDirectoryInternal;
 
            DirectoryInfo binPathDirectory = new DirectoryInfo(binPath);
 
            if (!binPathDirectory.Exists)
                return;
 
            PreloadAssembliesFromBinRecursive(binPathDirectory);
        }
 
        private void PreloadAssembliesFromBinRecursive(DirectoryInfo dirInfo) {
 
            FileInfo[] binDlls = dirInfo.GetFiles("*.dll");
 
            // Pre-load all the assemblies, ignoring all exceptions
            foreach (FileInfo fi in binDlls) {
                try { Assembly.Load(System.Web.UI.Util.GetAssemblyNameFromFileName(fi.Name)); }
                catch (FileNotFoundException) {
                    // If Load failed, try LoadFrom (VSWhidbey 493725)
                    try { Assembly.LoadFrom(fi.FullName); }
                    catch { }
                }
                catch { }
            }
 
            // Recurse on the subdirectories
            DirectoryInfo[] subDirs = dirInfo.GetDirectories();
            foreach (DirectoryInfo di in subDirs) {
                PreloadAssembliesFromBinRecursive(di);
            }
        }
 
        private void SetAutoConfigLimits(ProcessModelSection pmConfig) {
            // check if the current limits are ok
            int workerMax, ioMax;
            ThreadPool.GetMaxThreads(out workerMax, out ioMax);
 
            // only set if different
            if (pmConfig.DefaultMaxWorkerThreadsForAutoConfig != workerMax || pmConfig.DefaultMaxIoThreadsForAutoConfig != ioMax) {
                Debug.Trace("ThreadPool", "SetThreadLimit: from " + workerMax + "," + ioMax + " to " + pmConfig.DefaultMaxWorkerThreadsForAutoConfig + "," + pmConfig.DefaultMaxIoThreadsForAutoConfig);
                UnsafeNativeMethods.SetClrThreadPoolLimits(pmConfig.DefaultMaxWorkerThreadsForAutoConfig, pmConfig.DefaultMaxIoThreadsForAutoConfig, true);
            }
 
            // this is the code equivalent of setting maxconnection
            // Dev11 141729: Make autoConfig scale by default
            // Dev11 144842: PERF: Consider removing Max connection limit or changing the default value
            System.Net.ServicePointManager.DefaultConnectionLimit = Int32.MaxValue;
 
            // we call InitRequestQueue later, from FirstRequestInit, and set minFreeThreads and minLocalRequestFreeThreads
        }
 
        private void SetThreadPoolLimits() {
            try {
                ProcessModelSection pmConfig = RuntimeConfig.GetMachineConfig().ProcessModel;
 
                if (pmConfig.AutoConfig) {
                    // use recommendation in http://support.microsoft.com/?id=821268
                    SetAutoConfigLimits(pmConfig);
                }
                else if (pmConfig.MaxWorkerThreadsTimesCpuCount > 0 && pmConfig.MaxIoThreadsTimesCpuCount > 0) {
                    // check if the current limits are ok
                    int workerMax, ioMax;
                    ThreadPool.GetMaxThreads(out workerMax, out ioMax);
 
                    // only set if different
                    if (pmConfig.MaxWorkerThreadsTimesCpuCount != workerMax || pmConfig.MaxIoThreadsTimesCpuCount != ioMax) {
                        Debug.Trace("ThreadPool", "SetThreadLimit: from " + workerMax + "," + ioMax + " to " + pmConfig.MaxWorkerThreadsTimesCpuCount + "," + pmConfig.MaxIoThreadsTimesCpuCount);
                        UnsafeNativeMethods.SetClrThreadPoolLimits(pmConfig.MaxWorkerThreadsTimesCpuCount, pmConfig.MaxIoThreadsTimesCpuCount, false);
                    }
                }
 
                if (pmConfig.MinWorkerThreadsTimesCpuCount > 0 || pmConfig.MinIoThreadsTimesCpuCount > 0) {
                    int currentMinWorkerThreads, currentMinIoThreads;
                    ThreadPool.GetMinThreads(out currentMinWorkerThreads, out currentMinIoThreads);
 
                    int newMinWorkerThreads = pmConfig.MinWorkerThreadsTimesCpuCount > 0 ? pmConfig.MinWorkerThreadsTimesCpuCount : currentMinWorkerThreads;
                    int newMinIoThreads = pmConfig.MinIoThreadsTimesCpuCount > 0 ? pmConfig.MinIoThreadsTimesCpuCount : currentMinIoThreads;
 
                    if (newMinWorkerThreads > 0 && newMinIoThreads > 0
                        && (newMinWorkerThreads != currentMinWorkerThreads || newMinIoThreads != currentMinIoThreads))
                        ThreadPool.SetMinThreads(newMinWorkerThreads, newMinIoThreads);
                }
            }
            catch {
            }
        }
 
        internal static void CheckApplicationEnabled() {
            // process App_Offline.htm file
            string appOfflineFile = Path.Combine(_theRuntime._appDomainAppPath, AppOfflineFileName);
            bool appOfflineFileFound = false;
 
            // monitor even if doesn't exist
            _theRuntime._fcm.StartMonitoringFile(appOfflineFile, new FileChangeEventHandler(_theRuntime.OnAppOfflineFileChange));
 
            // read the file into memory
            try {
                if (File.Exists(appOfflineFile)) {
                    Debug.Trace("AppOffline", "File " + appOfflineFile + " exists. Using it.");
 
                    using (FileStream fs = new FileStream(appOfflineFile, FileMode.Open, FileAccess.Read, FileShare.Read)) {
                        if (fs.Length <= MaxAppOfflineFileLength) {
                            int length = (int)fs.Length;
 
                            if (length > 0) {
                                byte[] message = new byte[length];
 
                                if (fs.Read(message, 0, length) == length) {
                                    // remember the message
                                    _theRuntime._appOfflineMessage = message;
                                    appOfflineFileFound = true;
                                }
                            }
                            else {
                                // empty file
                                appOfflineFileFound = true;
                                _theRuntime._appOfflineMessage = new byte[0];
                            }
                        }
                    }
                }
            }
            catch {
                // ignore any IO errors reading the file
            }
 
            // throw if there is a valid App_Offline file
            if (appOfflineFileFound) {
                throw new HttpException(503, String.Empty);
            }
 
            // process the config setting
            HttpRuntimeSection runtimeConfig = RuntimeConfig.GetAppConfig().HttpRuntime;
            if (!runtimeConfig.Enable) {
                // throw 404 on first request init -- this will get cached until config changes
                throw new HttpException(404, String.Empty);
            }
        }
 
        [FileIOPermission(SecurityAction.Assert, Unrestricted = true)]
        private void CheckAccessToTempDirectory() {
            // The original check (in HostingInit) was done under process identity
            // this time we do it under hosting identity
            if (HostingEnvironment.HasHostingIdentity) {
                using (new ApplicationImpersonationContext()) {
                    if (!System.Web.UI.Util.HasWriteAccessToDirectory(_tempDir)) {
                        throw new HttpException(SR.GetString(SR.No_codegen_access,
                            System.Web.UI.Util.GetCurrentAccountName(), _tempDir));
                    }
                }
            }
        }
 
        private void InitializeHealthMonitoring() {
#if !FEATURE_PAL // FEATURE_PAL does not enable IIS-based hosting features
            ProcessModelSection pmConfig = RuntimeConfig.GetMachineConfig().ProcessModel;
            int deadLockInterval = (int)pmConfig.ResponseDeadlockInterval.TotalSeconds;
            int requestQueueLimit = pmConfig.RequestQueueLimit;
            Debug.Trace("HealthMonitor", "Initalizing: ResponseDeadlockInterval=" + deadLockInterval);
            UnsafeNativeMethods.InitializeHealthMonitor(deadLockInterval, requestQueueLimit);
#endif // !FEATURE_PAL
        }
 
        private static void InitHttpConfiguration() {
            if (!_theRuntime._configInited) {
                _theRuntime._configInited = true;
 
                HttpConfigurationSystem.EnsureInit(null, true, true);
 
                // whenever possible report errors in the user's culture (from machine.config)
                // Note: this thread's culture is saved/restored during FirstRequestInit, so this is safe
                // see ASURT 81655
 
                GlobalizationSection globConfig = RuntimeConfig.GetAppLKGConfig().Globalization;
                if (globConfig != null) {
                    if (!String.IsNullOrEmpty(globConfig.Culture) &&
                        !StringUtil.StringStartsWithIgnoreCase(globConfig.Culture, "auto"))
                        SetCurrentThreadCultureWithAssert(HttpServerUtility.CreateReadOnlyCultureInfo(globConfig.Culture));
 
                    if (!String.IsNullOrEmpty(globConfig.UICulture) &&
                        !StringUtil.StringStartsWithIgnoreCase(globConfig.UICulture, "auto"))
                        Thread.CurrentThread.CurrentUICulture = HttpServerUtility.CreateReadOnlyCultureInfo(globConfig.UICulture);
                }
 
                // check for errors in <processModel> section
                RuntimeConfig appConfig = RuntimeConfig.GetAppConfig();
                object section = appConfig.ProcessModel;
                // check for errors in <hostingEnvironment> section
                section = appConfig.HostingEnvironment;
            }
        }
 
        private void InitHeaderEncoding() {
            HttpRuntimeSection runtimeConfig = RuntimeConfig.GetAppConfig().HttpRuntime;
            _enableHeaderChecking = runtimeConfig.EnableHeaderChecking;
        }
 
        private static void SetAutogenKeys() {
#if !FEATURE_PAL // FEATURE_PAL does not enable cryptography
            byte[] bKeysRandom = new byte[s_autogenKeys.Length];
            byte[] bKeysStored = new byte[s_autogenKeys.Length];
            bool fGetStoredKeys = false;
            RNGCryptoServiceProvider randgen = new RNGCryptoServiceProvider();
 
            // Gernerate random keys
            randgen.GetBytes(bKeysRandom);
 
            // If getting stored keys via WorkerRequest object failed, get it directly
            if (!fGetStoredKeys)
                fGetStoredKeys = (UnsafeNativeMethods.EcbCallISAPI(IntPtr.Zero, UnsafeNativeMethods.CallISAPIFunc.GetAutogenKeys,
                                                                   bKeysRandom, bKeysRandom.Length, bKeysStored, bKeysStored.Length) == 1);
 
            // If we managed to get stored keys, copy them in; else use random keys
            if (fGetStoredKeys)
                Buffer.BlockCopy(bKeysStored, 0, s_autogenKeys, 0, s_autogenKeys.Length);
            else
                Buffer.BlockCopy(bKeysRandom, 0, s_autogenKeys, 0, s_autogenKeys.Length);
#endif // !FEATURE_PAL
        }
 
        internal static void IncrementActivePipelineCount() {
            Interlocked.Increment(ref _theRuntime._activeRequestCount);
            HostingEnvironment.IncrementBusyCount();
        }
 
        internal static void DecrementActivePipelineCount() {
            HostingEnvironment.DecrementBusyCount();
            Interlocked.Decrement(ref _theRuntime._activeRequestCount);
        }
 
        internal static void PopulateIISVersionInformation() {
            if (IsEngineLoaded) {
                uint dwVersion;
                bool fIsIntegratedMode;
                UnsafeIISMethods.MgdGetIISVersionInformation(out dwVersion, out fIsIntegratedMode);
 
                if (dwVersion != 0) {
                    // High word is the major version; low word is the minor version (this is MAKELONG format)
                    _iisVersion = new Version((int)(dwVersion >> 16), (int)(dwVersion & 0xffff));
                    _useIntegratedPipeline = fIsIntegratedMode;
                }
            }
        }
 
        // Gets the version of IIS (7.0, 7.5, 8.0, etc.) that is hosting this application, or null if this application isn't IIS-hosted.
        // Should also return the correct version for IIS Express.
        public static Version IISVersion {
            get {
                return _iisVersion;
            }
        }
 
        // DevDivBugs 190952: public method for querying runtime pipeline mode
        public static bool UsingIntegratedPipeline {
            get {
                return UseIntegratedPipeline;
            }
        }
 
        internal static bool UseIntegratedPipeline {
            get {
                return _useIntegratedPipeline;
            }
        }
 
        internal static bool EnablePrefetchOptimization {
            get {
                return _enablePrefetchOptimization;
            }
        }
 
        /*
         * Process one step of the integrated pipeline
         *
         */
 
        internal static RequestNotificationStatus ProcessRequestNotification(IIS7WorkerRequest wr, HttpContext context)
        {
            return _theRuntime.ProcessRequestNotificationPrivate(wr, context);
        }
 
        private RequestNotificationStatus ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) {
            RequestNotificationStatus status = RequestNotificationStatus.Pending;
            try {
                int currentModuleIndex;
                bool isPostNotification;
                int currentNotification;
 
                // setup the HttpContext for this event/module combo
                UnsafeIISMethods.MgdGetCurrentNotificationInfo(wr.RequestContext, out currentModuleIndex, out isPostNotification, out currentNotification);
 
                context.CurrentModuleIndex = currentModuleIndex;
                context.IsPostNotification = isPostNotification;
                context.CurrentNotification = (RequestNotification) currentNotification;
#if DBG
                Debug.Trace("PipelineRuntime", "HttpRuntime::ProcessRequestNotificationPrivate: notification=" + context.CurrentNotification.ToString()
                            + ", isPost=" + context.IsPostNotification
                            + ", moduleIndex=" + context.CurrentModuleIndex);
#endif
 
                IHttpHandler handler = null;
                if (context.NeedToInitializeApp()) {
#if DBG
                    Debug.Trace("FileChangesMonitorIgnoreSubdirChange",
                                "*** FirstNotification " + DateTime.Now.ToString("hh:mm:ss.fff", CultureInfo.InvariantCulture)
                                + ": _appDomainAppId=" + _appDomainAppId);
#endif
                    // First request initialization
                    try {
                        EnsureFirstRequestInit(context);
                    }
                    catch {
                        // If we are handling a DEBUG request, ignore the FirstRequestInit exception.
                        // This allows the HttpDebugHandler to execute, and lets the debugger attach to
                        // the process (VSWhidbey 358135)
                        if (!context.Request.IsDebuggingRequest) {
                            throw;
                        }
                    }
 
                    context.Response.InitResponseWriter();
                    handler = HttpApplicationFactory.GetApplicationInstance(context);
                    if (handler == null)
                        throw new HttpException(SR.GetString(SR.Unable_create_app_object));
 
                    if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Infrastructure)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_START_HANDLER, context.WorkerRequest, handler.GetType().FullName, "Start");
 
                    HttpApplication app = handler as HttpApplication;
                    if (app != null) {
                        // associate the context with an application instance
                        app.AssignContext(context);
                    }
                }
 
                // this may throw, and should be called after app initialization
                wr.SynchronizeVariables(context);
 
                if (context.ApplicationInstance != null) {
                    // process request
                    IAsyncResult ar = context.ApplicationInstance.BeginProcessRequestNotification(context, _requestNotificationCompletionCallback);
 
                    if (ar.CompletedSynchronously) {
                        status = RequestNotificationStatus.Continue;
                    }
                }
                else if (handler != null) {
                    // HttpDebugHandler is processed here
                    handler.ProcessRequest(context);
                    status = RequestNotificationStatus.FinishRequest;
                }
                else {
                    status = RequestNotificationStatus.Continue;
                }
            }
            catch (Exception e) {
                status = RequestNotificationStatus.FinishRequest;
                context.Response.InitResponseWriter();
                // errors are handled in HttpRuntime::FinishRequestNotification
                context.AddError(e);
            }
 
            if (status != RequestNotificationStatus.Pending) {
                // we completed synchronously
                FinishRequestNotification(wr, context, ref status);
            }
 
#if DBG
            Debug.Trace("PipelineRuntime", "HttpRuntime::ProcessRequestNotificationPrivate: status=" + status.ToString());
#endif
 
            return status;
        }
 
        private void FinishRequestNotification(IIS7WorkerRequest wr, HttpContext context, ref RequestNotificationStatus status) {
 
            Debug.Assert(status != RequestNotificationStatus.Pending, "status != RequestNotificationStatus.Pending");
 
            HttpApplication app = context.ApplicationInstance;
 
            if (context.NotificationContext.RequestCompleted) {
                status = RequestNotificationStatus.FinishRequest;
            }
 
            // check if the app offline or whether an error has occurred, and report the condition
            context.ReportRuntimeErrorIfExists(ref status);
 
            // we do not return FinishRequest for LogRequest or EndRequest
            if (status == RequestNotificationStatus.FinishRequest
                && (context.CurrentNotification == RequestNotification.LogRequest
                    || context.CurrentNotification == RequestNotification.EndRequest)) {
                status = RequestNotificationStatus.Continue;
            }
 
            IntPtr requestContext = wr.RequestContext;
            bool sendHeaders = UnsafeIISMethods.MgdIsLastNotification(requestContext, status);
            try {
                context.Response.UpdateNativeResponse(sendHeaders);
            }
            catch(Exception e) {
                // if we catch an exception here then
                // i) clear cached response body bytes on the worker request
                // ii) clear the managed headers, the IIS native headers, the mangaged httpwriter response buffers, and the native IIS response buffers
                // iii) attempt to format the exception and write it to the response
                wr.UnlockCachedResponseBytes();
                context.AddError(e);
                context.ReportRuntimeErrorIfExists(ref status);
                try {
                    context.Response.UpdateNativeResponse(sendHeaders);
                }
                catch {
                }
            }
 
            if (sendHeaders) {
                context.FinishPipelineRequest();
            }
 
            // Perf optimization: dispose managed context if possible (no need to try if status is pending)
            if (status != RequestNotificationStatus.Pending) {
                PipelineRuntime.DisposeHandler(context, requestContext, status);
            }
        }
 
        internal static void FinishPipelineRequest(HttpContext context) {
            // Remember that first request is done
            _theRuntime._firstRequestCompleted = true;
 
            // need to raise OnRequestCompleted while within the ThreadContext so that things like User, CurrentCulture, etc. are available
            context.RaiseOnRequestCompleted();
 
            context.Request.Dispose();
            context.Response.Dispose();
            HttpApplication app = context.ApplicationInstance;
            if(null != app) {
                ThreadContext threadContext = context.IndicateCompletionContext;
                if (threadContext != null) {
                    if (!threadContext.HasBeenDisassociatedFromThread) {
                        lock (threadContext) {
                            if (!threadContext.HasBeenDisassociatedFromThread) {
                                threadContext.DisassociateFromCurrentThread();
                                context.IndicateCompletionContext = null;
                                context.InIndicateCompletion = false;
                            }
                        }
                    }
                }
                app.ReleaseAppInstance();
            }
 
            SetExecutionTimePerformanceCounter(context);
            UpdatePerfCounters(context.Response.StatusCode);
            if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Infrastructure)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_END_HANDLER, context.WorkerRequest);
 
            // In case of a HostingInit() error, app domain should not stick around
            if (HostingInitFailed) {
                Debug.Trace("AppDomainFactory", "Shutting down appdomain because of HostingInit error");
                ShutdownAppDomain(ApplicationShutdownReason.HostingEnvironment, "HostingInit error");
            }
        }
 
 
        /*
         * Process one request
         */
        private void ProcessRequestInternal(HttpWorkerRequest wr) {
            // Count active requests
            Interlocked.Increment(ref _activeRequestCount);
 
            if (_disposingHttpRuntime) {
                // Dev11 333176: An appdomain is unloaded before all requests are served, resulting in System.AppDomainUnloadedException during isapi completion callback
                //
                // HttpRuntim.Dispose could have already finished on a different thread when we had no active requests
                // In this case we are about to start or already started unloading the appdomain so we will reject the request the safest way possible
                try {
                    wr.SendStatus(503, "Server Too Busy");
                    wr.SendKnownResponseHeader(HttpWorkerRequest.HeaderContentType, "text/html; charset=utf-8");
                    byte[] body = Encoding.ASCII.GetBytes("<html><body>Server Too Busy</body></html>");
                    wr.SendResponseFromMemory(body, body.Length);
                    // this will flush synchronously because of HttpRuntime.ShutdownInProgress
                    wr.FlushResponse(true);
                    wr.EndOfRequest();
                } finally {
                    Interlocked.Decrement(ref _activeRequestCount);
                }
                return;
            }
 
            // Construct the Context on HttpWorkerRequest, hook everything together
            HttpContext context;
 
            try {
                context = new HttpContext(wr, false /* initResponseWriter */);
            } 
            catch {
                try {
                    // If we fail to create the context for any reason, send back a 400 to make sure
                    // the request is correctly closed (relates to VSUQFE3962)
                    wr.SendStatus(400, "Bad Request");
                    wr.SendKnownResponseHeader(HttpWorkerRequest.HeaderContentType, "text/html; charset=utf-8");
                    byte[] body = Encoding.ASCII.GetBytes("<html><body>Bad Request</body></html>");
                    wr.SendResponseFromMemory(body, body.Length);
                    wr.FlushResponse(true);
                    wr.EndOfRequest();
                    return;
                } finally {
                    Interlocked.Decrement(ref _activeRequestCount);
                }
            }
 
            wr.SetEndOfSendNotification(_asyncEndOfSendCallback, context);
 
            HostingEnvironment.IncrementBusyCount();
 
            try {
                // First request initialization
                try {
                    EnsureFirstRequestInit(context);
                }
                catch {
                    // If we are handling a DEBUG request, ignore the FirstRequestInit exception.
                    // This allows the HttpDebugHandler to execute, and lets the debugger attach to
                    // the process (VSWhidbey 358135)
                    if (!context.Request.IsDebuggingRequest) {
                        throw;
                    }
                }
 
                // Init response writer (after we have config in first request init)
                // no need for impersonation as it is handled in config system
                context.Response.InitResponseWriter();
 
                // Get application instance
                IHttpHandler app = HttpApplicationFactory.GetApplicationInstance(context);
 
                if (app == null)
                    throw new HttpException(SR.GetString(SR.Unable_create_app_object));
 
                if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Infrastructure)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_START_HANDLER, context.WorkerRequest, app.GetType().FullName, "Start");
 
                if (app is IHttpAsyncHandler) {
                    // asynchronous handler
                    IHttpAsyncHandler asyncHandler = (IHttpAsyncHandler)app;
                    context.AsyncAppHandler = asyncHandler;
                    asyncHandler.BeginProcessRequest(context, _handlerCompletionCallback, context);
                }
                else {
                    // synchronous handler
                    app.ProcessRequest(context);
                    FinishRequest(context.WorkerRequest, context, null);
                }
            }
            catch (Exception e) {
                context.Response.InitResponseWriter();
                FinishRequest(wr, context, e);
            }
        }
 
        private void RejectRequestInternal(HttpWorkerRequest wr, bool silent) {
            // Construct the Context on HttpWorkerRequest, hook everything together
            HttpContext context = new HttpContext(wr, false /* initResponseWriter */);
            wr.SetEndOfSendNotification(_asyncEndOfSendCallback, context);
 
            // Count active requests
            Interlocked.Increment(ref _activeRequestCount);
            HostingEnvironment.IncrementBusyCount();
 
            if (silent) {
                context.Response.InitResponseWriter();
                FinishRequest(wr, context, null);
            }
            else {
                PerfCounters.IncrementGlobalCounter(GlobalPerfCounter.REQUESTS_REJECTED);
                PerfCounters.IncrementCounter(AppPerfCounter.APP_REQUESTS_REJECTED);
                try {
                    throw new HttpException(503, SR.GetString(SR.Server_too_busy));
                }
                catch (Exception e) {
                    context.Response.InitResponseWriter();
                    FinishRequest(wr, context, e);
                }
            }
        }
 
        internal static void ReportAppOfflineErrorMessage(HttpResponse response, byte[] appOfflineMessage) {
            response.StatusCode = 503;
            response.ContentType = "text/html";
            response.AddHeader("Retry-After", "3600");
            response.OutputStream.Write(appOfflineMessage, 0, appOfflineMessage.Length);
        }
 
        /*
         * Finish processing request, sync or async
         */
        private void FinishRequest(HttpWorkerRequest wr, HttpContext context, Exception e) {
            HttpResponse response = context.Response;
 
            if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Infrastructure)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_END_HANDLER, context.WorkerRequest);
 
            SetExecutionTimePerformanceCounter(context);
 
            // Flush in case of no error
            if (e == null) {
                // impersonate around PreSendHeaders / PreSendContent
                using (new ClientImpersonationContext(context, false)) {
                    try {
                        // this sends the actual content in most cases
                        response.FinalFlushAtTheEndOfRequestProcessing();
                    }
                    catch (Exception eFlush) {
                        e = eFlush;
                    }
                }
            }
 
            // Report error if any
            if (e != null) {
                using (new DisposableHttpContextWrapper(context)) {
 
                    // if the custom encoder throws, it might interfere with returning error information
                    // to the client, so we force use of the default encoder
                    context.DisableCustomHttpEncoder = true;
 
                    if (_appOfflineMessage != null) {
                        try {
                            ReportAppOfflineErrorMessage(response, _appOfflineMessage);
                            response.FinalFlushAtTheEndOfRequestProcessing();
                        }
                        catch {
                        }
                    }
                    else {
                        // when application is on UNC share the code below must
                        // be run while impersonating the token given by IIS
                        using (new ApplicationImpersonationContext()) {
                            try {
                                try {
                                    // try to report error in a way that could possibly throw (a config exception)
                                    response.ReportRuntimeError(e, true /*canThrow*/, false);
                                }
                                catch (Exception eReport) {
                                    // report the config error in a way that would not throw
                                    response.ReportRuntimeError(eReport, false /*canThrow*/, false);
                                }
 
                                response.FinalFlushAtTheEndOfRequestProcessing();
                            }
                            catch {
                            }
                        }
                    }
                }
            }
 
            // Remember that first request is done
            _firstRequestCompleted = true;
 
 
            // In case we reporting HostingInit() error, app domain should not stick around
            if (_hostingInitFailed) {
                Debug.Trace("AppDomainFactory", "Shutting down appdomain because of HostingInit error");
                ShutdownAppDomain(ApplicationShutdownReason.HostingEnvironment, "HostingInit error");
            }
 
            // Check status code and increment proper counter
            // If it's an error status code (i.e. 400 or higher), increment the proper perf counters
            int statusCode = response.StatusCode;
            UpdatePerfCounters(statusCode);
 
            context.FinishRequestForCachedPathData(statusCode);
 
            // ---- exceptions from EndOfRequest as they will prevent proper request cleanup
            // Since the exceptions are not expected here we want to log them
            try {
                wr.EndOfRequest();
            }
            catch (Exception ex) {
                WebBaseEvent.RaiseRuntimeError(ex, this);
            }
 
            // Count active requests
            HostingEnvironment.DecrementBusyCount();
            Interlocked.Decrement(ref _activeRequestCount);
 
            // Schedule more work if some requests are queued
            if (_requestQueue != null)
                _requestQueue.ScheduleMoreWorkIfNeeded();
        }
 
        //
        // Make sure shutdown happens only once
        //
 
        private bool InitiateShutdownOnce() {
            if (_shutdownInProgress)
                return false;
 
            lock (this) {
                if (_shutdownInProgress)
                    return false;
                _shutdownInProgress = true;
            }
 
            return true;
        }
 
        //
        // Shutdown this and restart new app domain
        //
        [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
        private void ReleaseResourcesAndUnloadAppDomain(Object state /*not used*/) {
#if DBG
            Debug.Trace("FileChangesMonitorIgnoreSubdirChange",
                        "*** ReleaseResourcesAndUnloadAppDomain " + DateTime.Now.ToString("hh:mm:ss.fff", CultureInfo.InvariantCulture)
                        + ": _appDomainAppId=" + _appDomainAppId);
#endif
            Debug.Trace("AppDomainFactory", "ReleaseResourcesAndUnloadAppDomain, Id=" + _appDomainAppId
                        + " DomainId = " + _appDomainId
                        + " Stack = " + Environment.StackTrace );
 
            try {
                PerfCounters.IncrementGlobalCounter(GlobalPerfCounter.APPLICATION_RESTARTS);
            }
            catch {
            }
 
            // Release all resources
            try {
                Dispose();
            }
            catch {
            }
 
            Thread.Sleep(250);
 
            AddAppDomainTraceMessage("before Unload");
 
            for (; ; ) {
                try {
                    AppDomain.Unload(Thread.GetDomain());
                }
                catch (CannotUnloadAppDomainException) {
                    Debug.Assert(false);
                }
                catch (Exception e) {
                    Debug.Trace("AppDomainFactory", "AppDomain.Unload exception: " + e + "; Id=" + _appDomainAppId);
                    if (!BuildManagerHost.InClientBuildManager) {
                        // Avoid calling Exception.ToString if we are in the ClientBuildManager (Dev10 bug 824659)
                        AddAppDomainTraceMessage("Unload Exception: " + e);
                    }
                    throw;
                }
            }
        }
 
        private static void SetExecutionTimePerformanceCounter(HttpContext context) {
            // Set the Request Execution time perf counter
            TimeSpan elapsed = DateTime.UtcNow.Subtract(context.WorkerRequest.GetStartTime());
            long milli = elapsed.Ticks / TimeSpan.TicksPerMillisecond;
 
            if (milli > Int32.MaxValue)
                milli = Int32.MaxValue;
 
            PerfCounters.SetGlobalCounter(GlobalPerfCounter.REQUEST_EXECUTION_TIME, (int)milli);
            PerfCounters.SetCounter(AppPerfCounter.APP_REQUEST_EXEC_TIME, (int)milli);
        }
 
        private static void UpdatePerfCounters(int statusCode) {
            if (400 <= statusCode) {
                PerfCounters.IncrementCounter(AppPerfCounter.REQUESTS_FAILED);
                switch (statusCode) {
                    case 401: // Not authorized
                        PerfCounters.IncrementCounter(AppPerfCounter.REQUESTS_NOT_AUTHORIZED);
                        break;
                    case 404: // Not found
                    case 414: // Not found
                        PerfCounters.IncrementCounter(AppPerfCounter.REQUESTS_NOT_FOUND);
                        break;
                }
            }
            else {
                // If status code is not in the 400-599 range (i.e. 200-299 success or 300-399 redirection),
                // count it as a successful request.
                PerfCounters.IncrementCounter(AppPerfCounter.REQUESTS_SUCCEDED);
            }
        }
 
        private void WaitForRequestsToFinish(int waitTimeoutMs) {
            DateTime waitLimit = DateTime.UtcNow.AddMilliseconds(waitTimeoutMs);
 
            for (; ; ) {
                if (_activeRequestCount == 0 && (_requestQueue == null || _requestQueue.IsEmpty))
                    break;
 
                Thread.Sleep(250);
 
                // only apply timeout if a managed debugger is not attached
                if (!System.Diagnostics.Debugger.IsAttached && DateTime.UtcNow > waitLimit) {
                    break; // give it up
                }
            }
        }
 
        /*
         * Cleanup of all unmananged state
         */
        private void Dispose() {
            // get shutdown timeout from config
            int drainTimeoutSec = HttpRuntimeSection.DefaultShutdownTimeout;
            try {
                HttpRuntimeSection runtimeConfig = RuntimeConfig.GetAppLKGConfig().HttpRuntime;
                if (runtimeConfig != null) {
                    drainTimeoutSec = (int)runtimeConfig.ShutdownTimeout.TotalSeconds;
                }
 
                // before aborting compilation give time to drain (new requests are no longer coming at this point)
                WaitForRequestsToFinish(drainTimeoutSec * 1000);
 
                // reject remaining queued requests
                if (_requestQueue != null)
                    _requestQueue.Drain();
            } finally {
                // By this time all new requests should be directed to a newly created app domain
                // But there might be requests that got dispatched to this old app domain but have not reached ProcessRequestInternal yet
                // Signal ProcessRequestInternal to reject them immediately without initiating async operations
                _disposingHttpRuntime = true;
            }
 
            // give it a little more time to drain
            WaitForRequestsToFinish((drainTimeoutSec * 1000) / 6);
 
 
            // wait for pending async io to complete,  prior to aborting requests
            // this isn't necessary for IIS 7, where the async sends are always done
            // from native code with native buffers
            System.Web.Hosting.ISAPIWorkerRequestInProcForIIS6.WaitForPendingAsyncIo();
 
            // For IIS7 integrated pipeline, wait until GL_APPLICATION_STOP fires and
            // there are no active calls to IndicateCompletion before unloading the AppDomain
            if (HttpRuntime.UseIntegratedPipeline) {
                PipelineRuntime.WaitForRequestsToDrain();
            }
            else {
                // wait for all active requests to complete
                while (_activeRequestCount != 0) {
                    Thread.Sleep(250);
                }
            }
 
 
            // Dispose AppDomainShutdownTimer
            DisposeAppDomainShutdownTimer();
 
            // kill all remaining requests (and the timeout timer)
            _timeoutManager.Stop();
            AppDomainResourcePerfCounters.Stop();                 
 
#if !FEATURE_PAL // FEATURE_PAL does not enable IIS-based hosting features
            // double check for pending async io
            System.Web.Hosting.ISAPIWorkerRequestInProcForIIS6.WaitForPendingAsyncIo();
 
            // stop sqlcachedependency polling
            SqlCacheDependencyManager.Dispose((drainTimeoutSec * 1000) / 2);
#endif // !FEATURE_PAL
            // cleanup cache (this ends all sessions)
            HealthMonitoringManager.IsCacheDisposed = true; // HMM is the only place internally where we care if the Cache is disposed or not.
            if (_cachePublic != null) {
                var oCache = HttpRuntime.Cache.GetObjectCache(createIfDoesNotExist: false);
                var iCache = HttpRuntime.Cache.GetInternalCache(createIfDoesNotExist: false);
                if (oCache != null) {
                    oCache.Dispose();
                }
                if (iCache != null) {
                    iCache.Dispose();
                }
            }
 
            // app on end, cleanup app instances
            HttpApplicationFactory.EndApplication();  // call app_onEnd
 
            // stop file changes monitor
            _fcm.Stop();
 
            // stop health monitoring timer
            HealthMonitoringManager.Shutdown();
        }
 
        /*
         * Async completion of IIS7 pipeline (unlike OnHandlerCompletion, this may fire more than once).
         */
        private void OnRequestNotificationCompletion(IAsyncResult ar) {
            try {
                OnRequestNotificationCompletionHelper(ar);
            }
            catch(Exception e) {
                ApplicationManager.RecordFatalException(e);
                throw;
            }
        }
 
        private void OnRequestNotificationCompletionHelper(IAsyncResult ar) {
            if (ar.CompletedSynchronously) {
                Debug.Trace("PipelineRuntime", "OnRequestNotificationCompletion: completed synchronously");
                return;
            }
 
            Debug.Trace("PipelineRuntime", "OnRequestNotificationCompletion: completed asynchronously");
 
            RequestNotificationStatus status = RequestNotificationStatus.Continue;
            HttpContext context = (HttpContext) ar.AsyncState;
            IIS7WorkerRequest wr = context.WorkerRequest as IIS7WorkerRequest;
 
            try {
                context.ApplicationInstance.EndProcessRequestNotification(ar);
            }
            catch (Exception e) {
                status = RequestNotificationStatus.FinishRequest;
                context.AddError(e);
            }
 
            // RequestContext is set to null if this is the last notification, so we need to save it
            // for the call to PostCompletion
            IntPtr requestContext = wr.RequestContext;
 
            FinishRequestNotification(wr, context, ref status);
 
            // set the notification context to null since we are exiting this notification
            context.NotificationContext = null;
 
            // Indicate completion to IIS, so that it can resume
            // request processing on an IIS thread
            Debug.Trace("PipelineRuntime", "OnRequestNotificationCompletion(" + status + ")");
            int result = UnsafeIISMethods.MgdPostCompletion(requestContext, status);
            Misc.ThrowIfFailedHr(result);
        }
 
        /*
         * Async completion of managed pipeline (called at most one time).
         */
        private void OnHandlerCompletion(IAsyncResult ar) {
            HttpContext context = (HttpContext)ar.AsyncState;
 
            try {
                context.AsyncAppHandler.EndProcessRequest(ar);
            }
            catch (Exception e) {
                context.AddError(e);
            }
            finally {
                // no longer keep AsyncAppHandler poiting to the application
                // is only needed to call EndProcessRequest
                context.AsyncAppHandler = null;
            }
 
            FinishRequest(context.WorkerRequest, context, context.Error);
        }
 
        /*
         * Notification from worker request that it is done writing from buffer
         * so that the buffers can be recycled
         */
        private void EndOfSendCallback(HttpWorkerRequest wr, Object arg) {
            Debug.Trace("PipelineRuntime", "HttpRuntime.EndOfSendCallback");
            HttpContext context = (HttpContext)arg;
            context.Request.Dispose();
            context.Response.Dispose();
        }
 
        /*
         * Notification when something in the bin directory changed
         */
        private void OnCriticalDirectoryChange(Object sender, FileChangeEvent e) {
            // shutdown the app domain
            Debug.Trace("AppDomainFactory", "Shutting down appdomain because of bin dir change or directory rename." +
                " FileName=" + e.FileName + " Action=" + e.Action);
 
            ApplicationShutdownReason reason = ApplicationShutdownReason.None;
            string directoryName = new DirectoryInfo(e.FileName).Name;
 
            string message = FileChangesMonitor.GenerateErrorMessage(e.Action);
            message = (message != null) ? message + directoryName : directoryName + " dir change or directory rename";
 
            if (StringUtil.EqualsIgnoreCase(directoryName, CodeDirectoryName)) {
                reason = ApplicationShutdownReason.CodeDirChangeOrDirectoryRename;
            }
            else if (StringUtil.EqualsIgnoreCase(directoryName, ResourcesDirectoryName)) {
                reason = ApplicationShutdownReason.ResourcesDirChangeOrDirectoryRename;
            }
            else if (StringUtil.EqualsIgnoreCase(directoryName, BrowsersDirectoryName)) {
                reason = ApplicationShutdownReason.BrowsersDirChangeOrDirectoryRename;
            }
            else if (StringUtil.EqualsIgnoreCase(directoryName, BinDirectoryName)) {
                reason = ApplicationShutdownReason.BinDirChangeOrDirectoryRename;
            }
 
            if (e.Action == FileAction.Added) {
                // Make sure HttpRuntime does not ignore the appdomain shutdown if a file is added (VSWhidbey 363481)
                HttpRuntime.SetUserForcedShutdown();
 
                Debug.Trace("AppDomainFactorySpecial", "Call SetUserForcedShutdown: FileName=" + e.FileName + "; now=" + DateTime.Now);
            }
 
            ShutdownAppDomain(reason, message);
        }
 
        /**
         * Coalesce file change notifications to minimize sharing violations and AppDomain restarts (ASURT 147492)
         */
        internal static void CoalesceNotifications() {
            int waitChangeNotification = HttpRuntimeSection.DefaultWaitChangeNotification;
            int maxWaitChangeNotification = HttpRuntimeSection.DefaultMaxWaitChangeNotification;
            try {
                HttpRuntimeSection config = RuntimeConfig.GetAppLKGConfig().HttpRuntime;
                if (config != null) {
                    waitChangeNotification = config.WaitChangeNotification;
                    maxWaitChangeNotification = config.MaxWaitChangeNotification;
                }
            }
            catch {
            }
 
            if (waitChangeNotification == 0 || maxWaitChangeNotification == 0)
                return;
 
            DateTime maxWait = DateTime.UtcNow.AddSeconds(maxWaitChangeNotification);
            // Coalesce file change notifications
            try {
                while (DateTime.UtcNow < maxWait) {
                    if (DateTime.UtcNow > _theRuntime.LastShutdownAttemptTime.AddSeconds(waitChangeNotification))
                        break;
 
                    Thread.Sleep(250);
                }
            }
            catch {
            }
        }
 
        // appdomain shutdown eventhandler
        internal static event BuildManagerHostUnloadEventHandler AppDomainShutdown;
 
        internal static void OnAppDomainShutdown(BuildManagerHostUnloadEventArgs e) {
            if (AppDomainShutdown != null) {
                AppDomainShutdown(_theRuntime, e);
            }
        }
 
        internal static void SetUserForcedShutdown() {
            _theRuntime._userForcedShutdown = true;
        }
 
        /*
         * Shutdown the current app domain
         */
        internal static bool ShutdownAppDomain(ApplicationShutdownReason reason, string message) {
            return ShutdownAppDomainWithStackTrace(reason, message, null /*stackTrace*/);
        }
 
        /*
         * Shutdown the current app domain with a stack trace.  This is useful for callers that are running
         * on a QUWI callback, and wouldn't provide a meaningful stack trace by default.
         */
        internal static bool ShutdownAppDomainWithStackTrace(ApplicationShutdownReason reason, string message, string stackTrace) {
            SetShutdownReason(reason, message);
            return ShutdownAppDomain(stackTrace);
        }
 
        private static bool ShutdownAppDomain(string stackTrace) {
#if DBG
            Debug.Trace("FileChangesMonitorIgnoreSubdirChange",
                        "*** ShutdownAppDomain " + DateTime.Now.ToString("hh:mm:ss.fff", CultureInfo.InvariantCulture)
                        + ": _appDomainAppId=" + HttpRuntime.AppDomainAppId);
#endif
            // Ignore notifications during the processing of the first request (ASURT 100335)
            // skip this if LastShutdownAttemptTime has been set
            if (_theRuntime.LastShutdownAttemptTime == DateTime.MinValue && !_theRuntime._firstRequestCompleted && !_theRuntime._userForcedShutdown) {
                // check the timeout (don't disable notifications forever
                int delayTimeoutSec = HttpRuntimeSection.DefaultDelayNotificationTimeout;
 
                try {
                    RuntimeConfig runtimeConfig = RuntimeConfig.GetAppLKGConfig();
                    if (runtimeConfig != null) {
                        HttpRuntimeSection runtimeSection = runtimeConfig.HttpRuntime;
                        if (runtimeSection != null) {
                            delayTimeoutSec = (int)runtimeSection.DelayNotificationTimeout.TotalSeconds;
 
                            if (DateTime.UtcNow < _theRuntime._firstRequestStartTime.AddSeconds(delayTimeoutSec)) {
                                Debug.Trace("AppDomainFactory", "ShutdownAppDomain IGNORED (1st request is not done yet), Id = " + AppDomainAppId);
                                return false;
                            }
                        }
                    }
                }
                catch {
                }
            }
 
            try {
                _theRuntime.RaiseShutdownWebEventOnce();
            }
            catch {
                // VSWhidbey 444472: if an exception is thrown, we consume it and continue executing the following code.
            }
 
            // Update last time ShutdownAppDomain was called
            _theRuntime.LastShutdownAttemptTime = DateTime.UtcNow;
 
            if (!HostingEnvironment.ShutdownInitiated) {
                // This shutdown is not triggered by hosting environment - let it do the job
                HostingEnvironment.InitiateShutdownWithoutDemand();
                return true;
            }
 
            //WOS 1400290: CantUnloadAppDomainException in ISAPI mode, wait until HostingEnvironment.ShutdownThisAppDomainOnce completes
            if (HostingEnvironment.ShutdownInProgress) {
                return false;
            }
 
            // Make sure we don't go through shutdown logic many times
            if (!_theRuntime.InitiateShutdownOnce())
                return false;
 
            Debug.Trace("AppDomainFactory", "ShutdownAppDomain, Id = " + AppDomainAppId + ", ShutdownInProgress=" + ShutdownInProgress
                        + ", ShutdownMessage=" + _theRuntime._shutDownMessage);
 
            if (String.IsNullOrEmpty(stackTrace) && !BuildManagerHost.InClientBuildManager) {
                // Avoid calling Environment.StackTrace if we are in the ClientBuildManager (Dev10 bug 824659)
 
                // Instrument to be able to see what's causing a shutdown
                new EnvironmentPermission(PermissionState.Unrestricted).Assert();
                try {
                    _theRuntime._shutDownStack = Environment.StackTrace;
                }
                finally {
                    CodeAccessPermission.RevertAssert();
                }
            }
            else {
                _theRuntime._shutDownStack = stackTrace;
            }
 
            // Notify when appdomain is about to shutdown.
            OnAppDomainShutdown(new BuildManagerHostUnloadEventArgs(_theRuntime._shutdownReason));
 
            // unload app domain from another CLR thread
            ThreadPool.QueueUserWorkItem(_theRuntime._appDomainUnloadallback);
 
            return true;
        }
 
        internal static void RecoverFromUnexceptedAppDomainUnload() {
            if (_theRuntime._shutdownInProgress)
                return;
 
            // someone unloaded app domain directly - tell unmanaged code
            Debug.Trace("AppDomainFactory", "Unexpected AppDomainUnload");
            _theRuntime._shutdownInProgress = true;
 
            // tell unmanaged code not to dispatch requests to this app domain
            try {
                ISAPIRuntime.RemoveThisAppDomainFromUnmanagedTable();
                PipelineRuntime.RemoveThisAppDomainFromUnmanagedTable();
                AddAppDomainTraceMessage("AppDomainRestart");
            }
            finally {
                // release all resources
                _theRuntime.Dispose();
            }
        }
 
        /*
         * Notification when app-level Config changed
         */
         internal static void OnConfigChange(String message) {
            Debug.Trace("AppDomainFactory", "Shutting down appdomain because of config change");
            ShutdownAppDomain(ApplicationShutdownReason.ConfigurationChange, (message != null) ? message : "CONFIG change");
        }
 
        // Intrumentation to remember the overwhelming file change
        internal static void SetShutdownReason(ApplicationShutdownReason reason, String message) {
            if (_theRuntime._shutdownReason == ApplicationShutdownReason.None) {
                _theRuntime._shutdownReason = reason;
            }
 
            SetShutdownMessage(message);
        }
 
        internal static void SetShutdownMessage(String message) {
            if (message != null) {
                if (_theRuntime._shutDownMessage == null)
                    _theRuntime._shutDownMessage = message;
                else
                    _theRuntime._shutDownMessage += "\r\n" + message;
            }
        }
 
 
        // public method is on HostingEnvironment
        internal static ApplicationShutdownReason ShutdownReason {
            get { return _theRuntime._shutdownReason; }
        }
 
        //
        // public static APIs
        //
 
        /*
         * Process one request
         */
 
        /// <devdoc>
        ///    <para><SPAN>The method that drives
        ///       all ASP.NET web processing execution.</SPAN></para>
        /// </devdoc>
        [AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Medium)]
        public static void ProcessRequest(HttpWorkerRequest wr) {
            if (wr == null)
                throw new ArgumentNullException("wr");
 
            if (HttpRuntime.UseIntegratedPipeline) {
                throw new PlatformNotSupportedException(SR.GetString(SR.Method_Not_Supported_By_Iis_Integrated_Mode, "HttpRuntime.ProcessRequest"));
            }
 
            ProcessRequestNoDemand(wr);
        }
 
 
        internal static void ProcessRequestNoDemand(HttpWorkerRequest wr) {
            RequestQueue rq = _theRuntime._requestQueue;
 
            wr.UpdateInitialCounters();
 
            if (rq != null)  // could be null before first request
                wr = rq.GetRequestToExecute(wr);
 
            if (wr != null) {
                CalculateWaitTimeAndUpdatePerfCounter(wr);
                wr.ResetStartTime();
                ProcessRequestNow(wr);
            }
        }
 
 
        private static void CalculateWaitTimeAndUpdatePerfCounter(HttpWorkerRequest wr) {
            DateTime begin = wr.GetStartTime();
 
            TimeSpan elapsed = DateTime.UtcNow.Subtract(begin);
            long milli = elapsed.Ticks / TimeSpan.TicksPerMillisecond;
 
            if (milli > Int32.MaxValue)
                milli = Int32.MaxValue;
 
            PerfCounters.SetGlobalCounter(GlobalPerfCounter.REQUEST_WAIT_TIME, (int)milli);
            PerfCounters.SetCounter(AppPerfCounter.APP_REQUEST_WAIT_TIME, (int)milli);
        }
 
        internal static void ProcessRequestNow(HttpWorkerRequest wr) {
            _theRuntime.ProcessRequestInternal(wr);
        }
 
        internal static void RejectRequestNow(HttpWorkerRequest wr, bool silent) {
            _theRuntime.RejectRequestInternal(wr, silent);
        }
 
 
        /// <devdoc>
        ///       <para>Removes all items from the cache and shuts down the runtime.</para>
        ///    </devdoc>
        [SecurityPermission(SecurityAction.Demand, Unrestricted = true)]
        public static void Close() {
            Debug.Trace("AppDomainFactory", "HttpRuntime.Close, ShutdownInProgress=" + ShutdownInProgress);
            if (_theRuntime.InitiateShutdownOnce()) {
                SetShutdownReason(ApplicationShutdownReason.HttpRuntimeClose, "HttpRuntime.Close is called");
 
                if (HostingEnvironment.IsHosted) {
                    // go throw initiate shutdown for hosted scenarios
                    HostingEnvironment.InitiateShutdownWithoutDemand();
                }
                else {
                    _theRuntime.Dispose();
                }
            }
        }
 
 
        /// <devdoc>
        ///       <para>Unloads the current app domain.</para>
        ///    </devdoc>
        public static void UnloadAppDomain() {
            _theRuntime._userForcedShutdown = true;
            ShutdownAppDomain(ApplicationShutdownReason.UnloadAppDomainCalled, "User code called UnloadAppDomain");
        }
 
        private DateTime LastShutdownAttemptTime {
            get {
                DateTime dt;
                lock (this) {
                    dt = _lastShutdownAttemptTime;
                }
                return dt;
            }
            set {
                lock (this) {
                    _lastShutdownAttemptTime = value;
                }
            }
        }
 
        internal static Profiler Profile {
            get {
                return _theRuntime._profiler;
            }
        }
 
        internal static bool IsTrustLevelInitialized {
            get {
                return !HostingEnvironment.IsHosted || TrustLevel != null;
            }
        }
 
        internal static NamedPermissionSet NamedPermissionSet {
            get {
                // Make sure we have already initialized the trust level
                // 
 
 
                return _theRuntime._namedPermissionSet;
            }
        }
 
        internal static PolicyLevel PolicyLevel {
            get {
                return _theRuntime._policyLevel;
            }
        }
 
        internal static string HostSecurityPolicyResolverType {
            get {
                return _theRuntime._hostSecurityPolicyResolverType;
            }
        }
 
        [AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Unrestricted)]
        public static NamedPermissionSet GetNamedPermissionSet() {
            NamedPermissionSet namedPermissionSet = _theRuntime._namedPermissionSet;
            if (namedPermissionSet == null) {
                return null;
            }
            else {
                return new NamedPermissionSet(namedPermissionSet);
            }
        }
 
        internal static bool IsFullTrust {
            get {
                // Make sure we have already initialized the trust level
                Debug.Assert(IsTrustLevelInitialized);
 
                return (_theRuntime._namedPermissionSet == null);
            }
        }
 
        /*
         * Check that the current trust level allows access to a virtual path.  Throw if it doesn't,
         */
        internal static void CheckVirtualFilePermission(string virtualPath) {
            string physicalPath = HostingEnvironment.MapPath(virtualPath);
            CheckFilePermission(physicalPath);
        }
 
        /*
         * Check that the current trust level allows access to a path.  Throw if it doesn't,
         */
        internal static void CheckFilePermission(string path) {
            CheckFilePermission(path, false);
        }
 
        internal static void CheckFilePermission(string path, bool writePermissions) {
            if (!HasFilePermission(path, writePermissions)) {
                throw new HttpException(SR.GetString(SR.Access_denied_to_path, GetSafePath(path)));
            }
        }
 
        internal static bool HasFilePermission(string path) {
            return HasFilePermission(path, false);
        }
 
        internal static bool HasFilePermission(string path, bool writePermissions) {
            // WOS #1523618: need to skip this check for HttpResponse.ReportRuntimeError when reporting an
            // InitializationException (e.g., necessary to display line info for ConfigurationException).
 
            if (TrustLevel == null && InitializationException != null) {
                return true;
            }
 
            // Make sure we have already initialized the trust level
            Debug.Assert(TrustLevel != null || !HostingEnvironment.IsHosted, "TrustLevel != null || !HostingEnvironment.IsHosted");
 
            // If we don't have a NamedPermissionSet, we're in full trust
            if (NamedPermissionSet == null)
                return true;
 
            bool fAccess = false;
 
            // Check that the user has permission to the path
            IPermission allowedPermission = NamedPermissionSet.GetPermission(typeof(FileIOPermission));
            if (allowedPermission != null) {
                IPermission askedPermission = null;
                try {
                    if (!writePermissions)
                        askedPermission = new FileIOPermission(FileIOPermissionAccess.Read, path);
                    else
                        askedPermission = new FileIOPermission(FileIOPermissionAccess.AllAccess, path);
                }
                catch {
                    // This could happen if the path is not absolute
                    return false;
                }
                fAccess = askedPermission.IsSubsetOf(allowedPermission);
            }
 
            return fAccess;
        }
 
        internal static bool HasWebPermission(Uri uri) {
 
            // Make sure we have already initialized the trust level
            Debug.Assert(TrustLevel != null || !HostingEnvironment.IsHosted);
 
            // If we don't have a NamedPermissionSet, we're in full trust
            if (NamedPermissionSet == null)
                return true;
 
            bool fAccess = false;
 
            // Check that the user has permission to the URI
            IPermission allowedPermission = NamedPermissionSet.GetPermission(typeof(WebPermission));
            if (allowedPermission != null) {
                IPermission askedPermission = null;
                try {
                    askedPermission = new WebPermission(NetworkAccess.Connect, uri.ToString());
                }
                catch {
                    return false;
                }
                fAccess = askedPermission.IsSubsetOf(allowedPermission);
            }
 
            return fAccess;
        }
 
        internal static bool HasDbPermission(DbProviderFactory factory) {
 
            // Make sure we have already initialized the trust level
            Debug.Assert(TrustLevel != null || !HostingEnvironment.IsHosted);
 
            // If we don't have a NamedPermissionSet, we're in full trust
            if (NamedPermissionSet == null)
                return true;
 
            bool fAccess = false;
 
            // Check that the user has permission to the provider
            CodeAccessPermission askedPermission = factory.CreatePermission(PermissionState.Unrestricted);
            if (askedPermission != null) {
                IPermission allowedPermission = NamedPermissionSet.GetPermission(askedPermission.GetType());
                if (allowedPermission != null) {
                    fAccess = askedPermission.IsSubsetOf(allowedPermission);
                }
            }
 
            return fAccess;
        }
 
        internal static bool HasPathDiscoveryPermission(string path) {
            // WOS #1523618: need to skip this check for HttpResponse.ReportRuntimeError when reporting an
            // InitializationException (e.g., necessary to display line info for ConfigurationException).
 
            if (TrustLevel == null && InitializationException != null) {
                return true;
            }
 
            // Make sure we have already initialized the trust level
            Debug.Assert(TrustLevel != null || !HostingEnvironment.IsHosted);
 
            // If we don't have a NamedPermissionSet, we're in full trust
            if (NamedPermissionSet == null)
                return true;
 
            bool fAccess = false;
 
            // Check that the user has permission to the path
            IPermission allowedPermission = NamedPermissionSet.GetPermission(typeof(FileIOPermission));
            if (allowedPermission != null) {
                IPermission askedPermission = new FileIOPermission(FileIOPermissionAccess.PathDiscovery, path);
                fAccess = askedPermission.IsSubsetOf(allowedPermission);
            }
 
            return fAccess;
 
        }
 
        internal static bool HasAppPathDiscoveryPermission() {
            return HasPathDiscoveryPermission(HttpRuntime.AppDomainAppPathInternal);
        }
 
        internal static string GetSafePath(string path) {
            if (String.IsNullOrEmpty(path))
                return path;
 
            try {
                if (HasPathDiscoveryPermission(path)) // could throw on bad filenames
                    return path;
            }
            catch {
            }
 
            return Path.GetFileName(path);
        }
 
        /*
         * Check that the current trust level allows Unmanaged access
         */
        internal static bool HasUnmanagedPermission() {
 
            // Make sure we have already initialized the trust level
            Debug.Assert(TrustLevel != null || !HostingEnvironment.IsHosted);
 
            // If we don't have a NamedPermissionSet, we're in full trust
            if (NamedPermissionSet == null)
                return true;
 
            SecurityPermission securityPermission = (SecurityPermission)NamedPermissionSet.GetPermission(
                typeof(SecurityPermission));
            if (securityPermission == null)
                return false;
 
            return (securityPermission.Flags & SecurityPermissionFlag.UnmanagedCode) != 0;
        }
 
        internal static bool HasAspNetHostingPermission(AspNetHostingPermissionLevel level) {
 
            // Make sure we have already initialized the trust level
            // 
 
 
 
            // If we don't have a NamedPermissionSet, we're in full trust
            if (NamedPermissionSet == null)
                return true;
 
            AspNetHostingPermission permission = (AspNetHostingPermission)NamedPermissionSet.GetPermission(
                typeof(AspNetHostingPermission));
            if (permission == null)
                return false;
 
            return (permission.Level >= level);
        }
 
        internal static void CheckAspNetHostingPermission(AspNetHostingPermissionLevel level, String errorMessageId) {
            if (!HasAspNetHostingPermission(level)) {
                throw new HttpException(SR.GetString(errorMessageId));
            }
        }
 
        // If we're not in full trust, fail if the passed in type doesn't have the APTCA bit
        internal static void FailIfNoAPTCABit(Type t, ElementInformation elemInfo, string propertyName) {
 
            if (!IsTypeAllowedInConfig(t)) {
                if (null != elemInfo) {
                    PropertyInformation propInfo = elemInfo.Properties[propertyName];
 
                    throw new ConfigurationErrorsException(SR.GetString(SR.Type_from_untrusted_assembly, t.FullName),
                    propInfo.Source, propInfo.LineNumber);
                }
                else {
                    throw new ConfigurationErrorsException(SR.GetString(SR.Type_from_untrusted_assembly, t.FullName));
                }
            }
        }
 
        // If we're not in full trust, fail if the passed in type doesn't have the APTCA bit
        internal static void FailIfNoAPTCABit(Type t, XmlNode node) {
 
            if (!IsTypeAllowedInConfig(t)) {
                throw new ConfigurationErrorsException(SR.GetString(SR.Type_from_untrusted_assembly, t.FullName),
                    node);
            }
        }
 
        private static bool HasAPTCABit(Assembly assembly) {
            return assembly.IsDefined(typeof(AllowPartiallyTrustedCallersAttribute), inherit: false);
        }
 
        // Check if the type is allowed to be used in config by checking the APTCA bit
        internal static bool IsTypeAllowedInConfig(Type t) {
 
            // Allow everything in full trust
            if (HttpRuntime.HasAspNetHostingPermission(AspNetHostingPermissionLevel.Unrestricted))
                return true;
 
            return IsTypeAccessibleFromPartialTrust(t);
        }
 
        internal static bool IsTypeAccessibleFromPartialTrust(Type t) {
            Assembly assembly = t.Assembly;
            
            if (assembly.SecurityRuleSet == SecurityRuleSet.Level1) {
                // Level 1 CAS uses transparency as an auditing mechanism rather than an enforcement mechanism, so we can't
                // perform a transparency check. Instead, allow the call to go through if:
                // (a) the referenced assembly is partially trusted, hence it cannot do anything dangerous; or
                // (b) the assembly is fully trusted and has APTCA.
                return (!assembly.IsFullyTrusted || HasAPTCABit(assembly));
            }
            else {
                // ** TEMPORARY **
                // Some GACed assemblies register critical modules / handlers. We can't break these scenarios for .NET 4.5, but we should
                // remove this APTCA check when we fix DevDiv #85358 and use only the transparency check defined below.
                if (HasAPTCABit(assembly)) {
                    return true;
                }
                // ** END TEMPORARY **
 
                // Level 2 CAS uses transparency as an enforcement mechanism, so we can perform a transparency check.
                // Transparent and SafeCritical types are safe to use from partial trust code.
                return (t.IsSecurityTransparent || t.IsSecuritySafeCritical);
            }
        }
 
        internal static FileChangesMonitor FileChangesMonitor {
            get { return _theRuntime._fcm; }
        }
 
        internal static RequestTimeoutManager RequestTimeoutManager {
            get { return _theRuntime._timeoutManager; }
        }
 
 
        /// <devdoc>
        ///    <para>Provides access to the cache.</para>
        /// </devdoc>
        public static Cache Cache {
            get {
 
                if (HttpRuntime.AspInstallDirectoryInternal == null) {
                    throw new HttpException(SR.GetString(SR.Aspnet_not_installed, VersionInfo.SystemWebVersion));
                }
 
                Cache cachePublic = _theRuntime._cachePublic;
                if (cachePublic == null) {
                    lock (_theRuntime) {
                        cachePublic = _theRuntime._cachePublic;
                        if (cachePublic == null) {
                            // Create the CACHE object
                            cachePublic = new Caching.Cache(0);
                            _theRuntime._cachePublic = cachePublic;
                        }
                    }
                }
 
                return cachePublic;
            }
        }
 
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        public static string AspInstallDirectory {
            get {
                String path = AspInstallDirectoryInternal;
 
                if (path == null) {
                    throw new HttpException(SR.GetString(SR.Aspnet_not_installed, VersionInfo.SystemWebVersion));
                }
 
                InternalSecurityPermissions.PathDiscovery(path).Demand();
                return path;
            }
        }
 
        internal static string AspInstallDirectoryInternal {
            get { return s_installDirectory; }
        }
 
        //
        // Return the client script virtual path, e.g. "/aspnet_client/system_web/2_0_50217"
        //
        public static string AspClientScriptVirtualPath {
            get {
                if (_theRuntime._clientScriptVirtualPath == null) {
                    string aspNetVersion = VersionInfo.SystemWebVersion;
                    string clientScriptVirtualPath = AspNetClientFilesParentVirtualPath + aspNetVersion.Substring(0, aspNetVersion.LastIndexOf('.')).Replace('.', '_');
 
                    _theRuntime._clientScriptVirtualPath = clientScriptVirtualPath;
                }
 
                return _theRuntime._clientScriptVirtualPath;
            }
        }
 
        public static string AspClientScriptPhysicalPath {
            get {
                String path = AspClientScriptPhysicalPathInternal;
 
                if (path == null) {
                    throw new HttpException(SR.GetString(SR.Aspnet_not_installed, VersionInfo.SystemWebVersion));
                }
 
                return path;
            }
        }
 
        //
        // Return the client script physical path, e.g. @"c:\windows\microsoft.net\framework\v2.0.50217.0\asp.netclientfiles"
        //
        internal static string AspClientScriptPhysicalPathInternal {
            get {
                if (_theRuntime._clientScriptPhysicalPath == null) {
                    string clientScriptPhysicalPath = System.IO.Path.Combine(AspInstallDirectoryInternal, AspNetClientFilesSubDirectory);
 
                    _theRuntime._clientScriptPhysicalPath = clientScriptPhysicalPath;
                }
 
                return _theRuntime._clientScriptPhysicalPath;
            }
        }
 
 
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        public static string ClrInstallDirectory {
            get {
                String path = ClrInstallDirectoryInternal;
                InternalSecurityPermissions.PathDiscovery(path).Demand();
                return path;
            }
        }
 
        internal static string ClrInstallDirectoryInternal {
            get { return HttpConfigurationSystem.MsCorLibDirectory; }
        }
 
 
 
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        public static string MachineConfigurationDirectory {
            get {
                String path = MachineConfigurationDirectoryInternal;
                InternalSecurityPermissions.PathDiscovery(path).Demand();
                return path;
            }
        }
 
        internal static string MachineConfigurationDirectoryInternal {
            get { return HttpConfigurationSystem.MachineConfigurationDirectory; }
        }
 
        internal static bool IsEngineLoaded {
            get { return s_isEngineLoaded; }
        }
 
 
        //
        //  Static app domain related properties
        //
 
 
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        public static String CodegenDir {
            get {
                String path = CodegenDirInternal;
                InternalSecurityPermissions.PathDiscovery(path).Demand();
                return path;
            }
        }
 
        internal static string CodegenDirInternal {
            get { return _theRuntime._codegenDir; }
        }
 
        internal static string TempDirInternal {
            get { return _theRuntime._tempDir; }
        }
 
 
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        public static String AppDomainAppId {
            get {
                return _theRuntime._appDomainAppId;
            }
        }
 
        internal static bool IsAspNetAppDomain {
            get { return AppDomainAppId != null; }
        }
 
 
 
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        public static String AppDomainAppPath {
            get {
                InternalSecurityPermissions.AppPathDiscovery.Demand();
                return AppDomainAppPathInternal;
            }
        }
 
        internal static string AppDomainAppPathInternal {
            get { return _theRuntime._appDomainAppPath; }
        }
 
 
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        public static String AppDomainAppVirtualPath {
            get {
                return VirtualPath.GetVirtualPathStringNoTrailingSlash(_theRuntime._appDomainAppVPath);
            }
        }
 
        // Save as AppDomainAppVirtualPath, but includes the trailng slash.  We can't change
        // AppDomainAppVirtualPath since it's public.
        internal static String AppDomainAppVirtualPathString {
            get {
                return VirtualPath.GetVirtualPathString(_theRuntime._appDomainAppVPath);
            }
        }
 
        internal static VirtualPath AppDomainAppVirtualPathObject {
            get {
                return _theRuntime._appDomainAppVPath;
            }
        }
 
        internal static bool IsPathWithinAppRoot(String path) {
            if (AppDomainIdInternal == null)
                return true;    // app domain not initialized
 
            return UrlPath.IsEqualOrSubpath(AppDomainAppVirtualPathString, path);
        }
 
 
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        public static String AppDomainId {
            [AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.High)]
            get {
                return AppDomainIdInternal;
            }
        }
 
        internal static string AppDomainIdInternal {
            get { return _theRuntime._appDomainId; }
        }
 
 
 
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        public static String BinDirectory {
            get {
                String path = BinDirectoryInternal;
                InternalSecurityPermissions.PathDiscovery(path).Demand();
                return path;
            }
        }
 
        internal static string BinDirectoryInternal {
            get { return Path.Combine(_theRuntime._appDomainAppPath, BinDirectoryName) + Path.DirectorySeparatorChar; }
 
        }
 
        internal static VirtualPath CodeDirectoryVirtualPath {
            get { return _theRuntime._appDomainAppVPath.SimpleCombineWithDir(CodeDirectoryName); }
        }
 
        internal static VirtualPath ResourcesDirectoryVirtualPath {
            get { return _theRuntime._appDomainAppVPath.SimpleCombineWithDir(ResourcesDirectoryName); }
        }
 
        internal static VirtualPath WebRefDirectoryVirtualPath {
            get { return _theRuntime._appDomainAppVPath.SimpleCombineWithDir(WebRefDirectoryName); }
        }
 
 
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        public static bool IsOnUNCShare {
            [AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Low)]
            get {
                return IsOnUNCShareInternal;
            }
        }
 
        internal static bool IsOnUNCShareInternal {
            get { return _theRuntime._isOnUNCShare; }
        }
 
 
        //
        //  Static helper to retrieve app domain values
        //
 
        private static String GetAppDomainString(String key) {
            Object x = Thread.GetDomain().GetData(key);
 
            return x as String;
        }
 
        internal static void AddAppDomainTraceMessage(String message) {
            const String appDomainTraceKey = "ASP.NET Domain Trace";
            AppDomain d = Thread.GetDomain();
            String m = d.GetData(appDomainTraceKey) as String;
            d.SetData(appDomainTraceKey, (m != null) ? m + " ... " + message : message);
        }
 
        // Gets the version of the ASP.NET framework the current web applications is targeting.
        // This property is normally set via the <httpRuntime> element's "targetFramework"
        // attribute. The property is not guaranteed to return a correct value if the current
        // AppDomain is not an ASP.NET web application AppDomain.
        public static Version TargetFramework {
            get {
                return BinaryCompatibility.Current.TargetFramework;
            }
        }
 
 
        //
        //  Flags
        //
 
        internal static bool DebuggingEnabled {
            get { return _theRuntime._debuggingEnabled; }
        }
 
        internal static bool ConfigInited {
            get { return _theRuntime._configInited; }
        }
 
        internal static bool FusionInited {
            get { return _theRuntime._fusionInited; }
        }
 
        internal static bool ApartmentThreading {
            get { return _theRuntime._apartmentThreading; }
        }
 
        internal static bool ShutdownInProgress {
            get { return _theRuntime._shutdownInProgress; }
        }
 
        internal static string TrustLevel {
            get { return _theRuntime._trustLevel; }
        }
 
        internal static string WpUserId {
            get { return _theRuntime._wpUserId; }
        }
 
 
        private void SetTrustLevel(TrustSection trustSection, SecurityPolicySection securityPolicySection) {
            // Use a temporary variable, since we use the field as a signal that the trust has really
            // been set, which is not the case until later in this method.
            string trustLevel = trustSection.Level;
 
            if (trustSection.Level == "Full") {
                _trustLevel = trustLevel;
                return;
            }
 
            if (securityPolicySection == null || securityPolicySection.TrustLevels[trustSection.Level] == null) {
                throw new ConfigurationErrorsException(SR.GetString(SR.Unable_to_get_policy_file, trustSection.Level), String.Empty, 0);
                //             Do not give out configuration information since we don't know what trust level we are
                //             supposed to be running at.  If the information below is added to the error it might expose
                //             part of the config file that the users does not have permissions to see. VS261145
                //            ,trustSection.ElementInformation.Properties["level"].Source,
                //            trustSection.ElementInformation.Properties["level"].LineNumber);
            }
            String file = null;
            if (trustSection.Level == "Minimal" || trustSection.Level == "Low" ||
                trustSection.Level == "Medium" || trustSection.Level == "High") {
                file = (String)securityPolicySection.TrustLevels[trustSection.Level].LegacyPolicyFileExpanded;
            }
            else {
                file = (String)securityPolicySection.TrustLevels[trustSection.Level].PolicyFileExpanded;
            }
            if (file == null || !FileUtil.FileExists(file)) {
                //if HttpContext.Current.IsCustomErrorEnabled
                throw new HttpException(SR.GetString(SR.Unable_to_get_policy_file, trustSection.Level));
                //else
                //    throw new ConfigurationErrorsException(SR.GetString(SR.Unable_to_get_policy_file, trustSection.Level),
                //        trustSection.Filename, trustSection.LineNumber);
            }
 
            bool foundGacToken = false;
#pragma warning disable 618
            PolicyLevel policyLevel = CreatePolicyLevel(file, AppDomainAppPathInternal, CodegenDirInternal, trustSection.OriginUrl, out foundGacToken);
 
            // see if the policy file contained a v1.x UrlMembershipCondition containing
            // a GAC token.  If so, let's upgrade it by adding a code group granting
            // full trust to code from the GAC
            if (foundGacToken) {
                // 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;
                            //Debug.Trace("internal", "PolicyLevel: " + policyLevel.ToXml());
                        }
                    }
                }
#pragma warning restore 618
            }
 
 
#pragma warning disable 618
            AppDomain.CurrentDomain.SetAppDomainPolicy(policyLevel);
            _namedPermissionSet = policyLevel.GetNamedPermissionSet(trustSection.PermissionSetName);
#pragma warning restore 618
 
            _trustLevel = trustLevel;
 
            _fcm.StartMonitoringFile(file, new FileChangeEventHandler(this.OnSecurityPolicyFileChange));
        }
 
#pragma warning disable 618
        private static PolicyLevel CreatePolicyLevel(String configFile, String appDir, String binDir, String strOriginUrl, out bool foundGacToken) {
            // Read in the config file to a string.
            FileStream file = new FileStream(configFile, FileMode.Open, FileAccess.Read);
            StreamReader reader = new StreamReader(file, Encoding.UTF8);
            String strFileData = reader.ReadToEnd();
 
            reader.Close();
 
            appDir = FileUtil.RemoveTrailingDirectoryBackSlash(appDir);
            binDir = FileUtil.RemoveTrailingDirectoryBackSlash(binDir);
 
            strFileData = strFileData.Replace("$AppDir$", appDir);
            strFileData = strFileData.Replace("$AppDirUrl$", MakeFileUrl(appDir));
            strFileData = strFileData.Replace("$CodeGen$", MakeFileUrl(binDir));
            if (strOriginUrl == null)
                strOriginUrl = String.Empty;
            strFileData = strFileData.Replace("$OriginHost$", strOriginUrl);
 
            // see if the file contains a GAC token
            // if so, do the replacement and record the
            // fact so that we later add a GacMembershipCondition
            // codegroup to the PolicyLevel
            int ndx = strFileData.IndexOf("$Gac$", StringComparison.Ordinal);
            if (ndx != -1) {
                string gacLocation = GetGacLocation();
                if (gacLocation != null)
                    gacLocation = MakeFileUrl(gacLocation);
                if (gacLocation == null)
                    gacLocation = String.Empty;
 
                strFileData = strFileData.Replace("$Gac$", gacLocation);
                foundGacToken = true;
            }
            else {
                foundGacToken = false;
            }
 
            return SecurityManager.LoadPolicyLevelFromString(strFileData, PolicyLevelType.AppDomain);
        }
#pragma warning restore 618
 
        private void SetTrustParameters(TrustSection trustSection, SecurityPolicySection securityPolicySection, PolicyLevel policyLevel) {
            _trustLevel = trustSection.Level;
            if (_trustLevel != "Full") {
                // if we are in partial trust, HostingEnvironment should init HttpRuntime with a non-null PolicyLevel object
                Debug.Assert(policyLevel != null);
 
                _namedPermissionSet = policyLevel.GetNamedPermissionSet(trustSection.PermissionSetName);
                _policyLevel = policyLevel;
                _hostSecurityPolicyResolverType = trustSection.HostSecurityPolicyResolverType;
                String file = (String)securityPolicySection.TrustLevels[trustSection.Level].PolicyFileExpanded;
                _fcm.StartMonitoringFile(file, new FileChangeEventHandler(this.OnSecurityPolicyFileChange));
            }
        }
 
        /*
         * Notification when something in the code-access security policy file changed
         */
        private void OnSecurityPolicyFileChange(Object sender, FileChangeEvent e) {
            // shutdown the app domain
            Debug.Trace("AppDomainFactory", "Shutting down appdomain because code-access security policy file changed");
            string message = FileChangesMonitor.GenerateErrorMessage(e.Action, e.FileName);
            if (message == null) {
                message = "Change in code-access security policy file";
            }
            ShutdownAppDomain(ApplicationShutdownReason.ChangeInSecurityPolicyFile,
                              message);
        }
 
 
        // notification when app_offline.htm file changed or created
        private void OnAppOfflineFileChange(Object sender, FileChangeEvent e) {
            // shutdown the app domain
            Debug.Trace("AppOffline", AppOfflineFileName + " changed - shutting down the app domain");
            Debug.Trace("AppDomainFactory", "Shutting down appdomain because " + AppOfflineFileName + " file changed");
            // WOS 1948399: set _userForcedShutdown to avoid DelayNotificationTimeout, since first request has not completed yet in integrated mode;
            SetUserForcedShutdown();
            string message = FileChangesMonitor.GenerateErrorMessage(e.Action, AppOfflineFileName);
            if (message == null) {
                message = "Change in " + AppOfflineFileName;
            }
            ShutdownAppDomain(ApplicationShutdownReason.ConfigurationChange, message);
        }
 
        internal static String MakeFileUrl(String path) {
            Uri uri = new Uri(path);
            return uri.ToString();
        }
 
        internal static String GetGacLocation() {
 
            StringBuilder buf = new StringBuilder(262);
            int iSize = 260;
 
            // 
 
            if (UnsafeNativeMethods.GetCachePath(2, buf, ref iSize) >= 0)
                return buf.ToString();
            throw new HttpException(SR.GetString(SR.GetGacLocaltion_failed));
        }
 
 
        /*
         * Remove from metabase all read/write/browse permission from certain subdirs
         *
         */
        internal static void RestrictIISFolders(HttpContext context) {
            int ret;
 
            HttpWorkerRequest wr = context.WorkerRequest;
 
            Debug.Assert(AppDomainAppId != null);
 
            // Don't do it if we are not running on IIS
            if (wr == null || !(wr is System.Web.Hosting.ISAPIWorkerRequest)) {
                return;
            }
 
            // Do it only for IIS 5
#if !FEATURE_PAL // FEATURE_PAL does not enable IIS-based hosting features
            if (!(wr is System.Web.Hosting.ISAPIWorkerRequestInProcForIIS6))
#endif // !FEATURE_PAL
 {
                byte[] bufin;
                byte[] bufout = new byte[1];   // Just to keep EcbCallISAPI happy
 
                bufin = BitConverter.GetBytes(UnsafeNativeMethods.RESTRICT_BIN);
                ret = context.CallISAPI(UnsafeNativeMethods.CallISAPIFunc.RestrictIISFolders, bufin, bufout);
                if (ret != 1) {
                    // Cannot pass back any HR from inetinfo.exe because CSyncPipeManager::GetDataFromIIS
                    // does not support passing back any value when there is an error.
                    Debug.Trace("RestrictIISFolders", "Cannot restrict folder access for '" + AppDomainAppId + "'.");
                }
            }
        }
 
        /// <devdoc>
        ///     <para>Get/Set an IServiceProvider instance which will be responsible for
        ///           service instance creation, e.g. moudle/handler/page/user control/custom control
        ///     </para>
        /// </devdoc>
        public static IServiceProvider WebObjectActivator { get; set; }
 
        internal static Object CreateNonPublicInstanceByWebObjectActivator(Type type) {
            var activator = WebObjectActivator;
 
            if (activator != null) {
                return activator.GetService(type);
            }
 
            return CreateNonPublicInstance(type, null);
        }
 
        internal static Object CreatePublicInstanceByWebObjectActivator(Type type) {
            var activator = WebObjectActivator;
 
            if (activator != null) {
                return activator.GetService(type);
            }
 
            return CreatePublicInstance(type);
        }
 
        //
        // Helper to create instances (public vs. internal/private ctors, see 89781)
        //
 
        internal static Object CreateNonPublicInstance(Type type) {
            return CreateNonPublicInstance(type, null);
        }
 
        [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
        internal static Object CreateNonPublicInstance(Type type, Object[] args) {
            return Activator.CreateInstance(
                type,
                BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.CreateInstance,
                null,
                args,
                null);
        }
 
        internal static Object CreatePublicInstance(Type type) {
            return Activator.CreateInstance(type);
        }
 
#if !DONTUSEFACTORYGENERATOR
        // Cache instances of IWebObjectFactory for each Type, which allow us
        // to instantiate the objects very efficiently, compared to calling
        // Activator.CreateInstance on every call.
        private static FactoryGenerator s_factoryGenerator;
        private static Hashtable s_factoryCache;
        private static bool s_initializedFactory;
        private static object s_factoryLock = new Object();
 
#endif // DONTUSEFACTORYGENERATOR
 
        /*
         * Faster implementation of CreatePublicInstance.  It generates bits of IL
         * on the fly to achieve the improve performance.  this should only be used
         * in cases where the number of different types to be created is well bounded.
         * Otherwise, we would create too much IL, which can bloat the process.
         */
        internal static Object FastCreatePublicInstance(Type type) {
 
#if DONTUSEFACTORYGENERATOR
            return CreatePublicInstance(type);
#else
 
            // Only use the factory logic if the assembly is in the GAC, to avoid getting
            // assembly conflicts (VSWhidbey 405086)
            if (!type.Assembly.GlobalAssemblyCache) {
                return CreatePublicInstance(type);
            }
 
            // Create the factory generator on demand
            if (!s_initializedFactory) {
 
                // Devdiv 90810 - Synchronize to avoid race condition
                lock (s_factoryLock) {
                    if (!s_initializedFactory) {
                        s_factoryGenerator = new FactoryGenerator();
 
                        // Create the factory cache
                        s_factoryCache = Hashtable.Synchronized(new Hashtable());
 
                        s_initializedFactory = true;
                    }
                }
            }
 
            // First, check if it's cached
            IWebObjectFactory factory = (IWebObjectFactory)s_factoryCache[type];
 
            if (factory == null) {
 
                Debug.Trace("FastCreatePublicInstance", "Creating generator for type " + type.FullName);
 
                // Create the object factory
                factory = s_factoryGenerator.CreateFactory(type);
 
                // Cache the factory
                s_factoryCache[type] = factory;
            }
 
            return factory.CreateInstance();
#endif // DONTUSEFACTORYGENERATOR
        }
 
        internal static Object CreatePublicInstance(Type type, Object[] args) {
            if (args == null)
                return Activator.CreateInstance(type);
 
            return Activator.CreateInstance(type, args);
        }
 
        static string GetCurrentUserName() {
            try {
                return WindowsIdentity.GetCurrent().Name;
            }
            catch {
                return null;
            }
        }
 
        void RaiseShutdownWebEventOnce() {
            if (!_shutdownWebEventRaised) {
                lock (this) {
                    if (!_shutdownWebEventRaised) {
                        // Raise Web Event
                        WebBaseEvent.RaiseSystemEvent(this, WebEventCodes.ApplicationShutdown,
                                WebApplicationLifetimeEvent.DetailCodeFromShutdownReason(ShutdownReason));
 
                        _shutdownWebEventRaised = true;
                    }
                }
            }
        }
 
        private static string _DefaultPhysicalPathOnMapPathFailure;
        private void RelaxMapPathIfRequired() {
            try {
                RuntimeConfig config = RuntimeConfig.GetAppConfig();
                if (config != null && config.HttpRuntime != null && config.HttpRuntime.RelaxedUrlToFileSystemMapping) {
                    _DefaultPhysicalPathOnMapPathFailure = Path.Combine(_appDomainAppPath, "NOT_A_VALID_FILESYSTEM_PATH");
                }
            } catch {}
        }
        internal static bool IsMapPathRelaxed {
            get {
                return _DefaultPhysicalPathOnMapPathFailure != null;
            }
        }
        internal static string GetRelaxedMapPathResult(string originalResult) {
            if (!IsMapPathRelaxed) // Feature not enabled?
                return originalResult;
 
            if (originalResult == null) // null is never valid: Return the hard coded default physical path
                return _DefaultPhysicalPathOnMapPathFailure;
 
            // Does it contain an invalid file-path char?
            if (originalResult.IndexOfAny(s_InvalidPhysicalPathChars) >= 0)
                return _DefaultPhysicalPathOnMapPathFailure;
 
            // Final check: do the full check to ensure it is valid
            try {
                bool pathTooLong;
                if (FileUtil.IsSuspiciousPhysicalPath(originalResult, out pathTooLong) || pathTooLong)
                    return _DefaultPhysicalPathOnMapPathFailure;
            } catch {
                return _DefaultPhysicalPathOnMapPathFailure;
            }
 
            // it is valid
            return originalResult;
        }
    }
 
 
    public enum ApplicationShutdownReason {
 
        None = 0,
 
        HostingEnvironment = 1,
 
        ChangeInGlobalAsax = 2,
 
        ConfigurationChange = 3,
 
        UnloadAppDomainCalled = 4,
 
        ChangeInSecurityPolicyFile = 5,
 
        BinDirChangeOrDirectoryRename = 6,
 
        BrowsersDirChangeOrDirectoryRename = 7,
 
        CodeDirChangeOrDirectoryRename = 8,
 
        ResourcesDirChangeOrDirectoryRename = 9,
 
        IdleTimeout = 10,
 
        PhysicalApplicationPathChanged = 11,
 
        HttpRuntimeClose = 12,
 
        InitializationError = 13,
 
        MaxRecompilationsReached = 14,
 
        BuildManagerChange = 15,
    };
 
 
}