1 //------------------------------------------------------------------------------
2 // <copyright file="HostingEnvironment.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 //------------------------------------------------------------------------------
7 namespace System.Web.Hosting {
9 using System.Collections;
10 using System.Configuration;
11 using System.Diagnostics.CodeAnalysis;
12 using System.Globalization;
14 using System.Runtime.Caching;
15 using System.Runtime.CompilerServices;
16 using System.Runtime.InteropServices;
17 using System.Runtime.Remoting;
18 using System.Runtime.Remoting.Messaging;
19 using System.Security;
20 using System.Security.Permissions;
21 using System.Security.Policy;
22 using System.Security.Principal;
24 using System.Threading;
25 using System.Threading.Tasks;
27 using System.Web.Caching;
28 using System.Web.Compilation;
29 using System.Web.Configuration;
30 using System.Web.Management;
31 using System.Web.Util;
32 using System.Web.WebSockets;
33 using Microsoft.Win32;
34 using System.Collections.Generic;
37 internal enum HostingEnvironmentFlags {
39 HideFromAppManager = 1,
40 ThrowHostingInitErrors = 2,
41 DontCallAppInitialize = 4,
42 ClientBuildManager = 8,
43 SupportsMultiTargeting = 16,
47 internal class HostingEnvironmentParameters {
48 private HostingEnvironmentFlags _hostingFlags;
49 private ClientBuildManagerParameter _clientBuildManagerParameter;
50 private string _precompTargetPhysicalDir;
51 private string _iisExpressVersion;
53 public HostingEnvironmentFlags HostingFlags {
54 get { return _hostingFlags; }
55 set { _hostingFlags = value; }
58 // Directory where the precompiled site is placed
59 public string PrecompilationTargetPhysicalDirectory {
60 get { return _precompTargetPhysicalDir; }
62 _precompTargetPhysicalDir = FileUtil.FixUpPhysicalDirectory(value);
66 // Determines the behavior of the precompilation
67 public ClientBuildManagerParameter ClientBuildManagerParameter {
68 get { return _clientBuildManagerParameter; }
69 set { _clientBuildManagerParameter = value; }
72 // Determines which config system to load
73 public string IISExpressVersion {
74 get { return _iisExpressVersion; }
75 set { _iisExpressVersion = value; }
78 // Determines what FileChangeMonitor mode to use
79 public FcnMode FcnMode {
84 // Should FileChangesMonitor skip reading and caching DACLs?
85 public bool FcnSkipReadAndCacheDacls {
90 public KeyValuePair<string, bool>[] ClrQuirksSwitches {
96 public sealed class HostingEnvironment : MarshalByRefObject {
98 private static HostingEnvironment _theHostingEnvironment;
99 private EventHandler _onAppDomainUnload;
100 private ApplicationManager _appManager;
101 private HostingEnvironmentParameters _hostingParameters;
102 private IApplicationHost _appHost;
103 private bool _externalAppHost;
104 private IConfigMapPath _configMapPath;
105 private IConfigMapPath2 _configMapPath2;
106 private IntPtr _configToken;
108 private IdentitySection _appIdentity;
109 private IntPtr _appIdentityToken;
110 private bool _appIdentityTokenSet;
112 private String _appId;
113 private VirtualPath _appVirtualPath;
114 private String _appPhysicalPath;
115 private String _siteName;
116 private String _siteID;
117 private String _appConfigPath;
119 private bool _isBusy;
120 private int _busyCount;
122 private volatile static bool _stopListeningWasCalled; // static since it's process-wide
123 private bool _removedFromAppManager;
124 private bool _appDomainShutdownStarted;
125 private bool _shutdownInitiated;
126 private bool _shutdownInProgress;
127 private String _shutDownStack;
129 private int _inTrimCache;
130 private ObjectCacheHost _objectCacheHost;
132 // table of well know objects keyed by type
133 private Hashtable _wellKnownObjects = new Hashtable();
135 // list of registered IRegisteredObject instances, suspend listeners, and background work items
136 private Hashtable _registeredObjects = new Hashtable();
137 private SuspendManager _suspendManager = new SuspendManager();
138 private BackgroundWorkScheduler _backgroundWorkScheduler = null; // created on demand
139 private static readonly Task<object> _completedTask = Task.FromResult<object>(null);
141 // callback to make InitiateShutdown non-blocking
142 private WaitCallback _initiateShutdownWorkItemCallback;
144 // inside app domain idle shutdown logic
145 private IdleTimeoutMonitor _idleTimeoutMonitor;
147 private static IProcessHostSupportFunctions _functions;
148 private static bool _hasBeenRemovedFromAppManangerTable;
150 private const string TemporaryVirtualPathProviderKey = "__TemporaryVirtualPathProvider__";
152 // Determines what FileChangeMonitor mode to use
153 internal static FcnMode FcnMode {
155 if (_theHostingEnvironment != null && _theHostingEnvironment._hostingParameters != null) {
156 return _theHostingEnvironment._hostingParameters.FcnMode;
158 return FcnMode.NotSet;
162 internal static bool FcnSkipReadAndCacheDacls {
164 if (_theHostingEnvironment != null && _theHostingEnvironment._hostingParameters != null) {
165 return _theHostingEnvironment._hostingParameters.FcnSkipReadAndCacheDacls;
171 public override Object InitializeLifetimeService() {
172 return null; // never expire lease
176 [SecurityPermission(SecurityAction.Demand, Unrestricted = true)]
177 public HostingEnvironment() {
178 if (_theHostingEnvironment != null)
179 throw new InvalidOperationException(SR.GetString(SR.Only_1_HostEnv));
181 // remember singleton HostingEnvironment in a static
182 _theHostingEnvironment = this;
184 // start watching for app domain unloading
185 _onAppDomainUnload = new EventHandler(OnAppDomainUnload);
186 Thread.GetDomain().DomainUnload += _onAppDomainUnload;
189 internal long TrimCache(int percent) {
190 if (Interlocked.Exchange(ref _inTrimCache, 1) != 0)
193 long trimmedOrExpired = 0;
194 // do nothing if we're shutting down
195 if (!_shutdownInitiated) {
196 trimmedOrExpired = HttpRuntime.CacheInternal.TrimCache(percent);
197 if (_objectCacheHost != null && !_shutdownInitiated) {
198 trimmedOrExpired += _objectCacheHost.TrimCache(percent);
201 return trimmedOrExpired;
204 Interlocked.Exchange(ref _inTrimCache, 0);
208 private void OnAppDomainUnload(Object unusedObject, EventArgs unusedEventArgs) {
209 Debug.Trace("PipelineRuntime", "HE.OnAppDomainUnload");
211 Thread.GetDomain().DomainUnload -= _onAppDomainUnload;
213 // check for unexpected shutdown
214 if (!_removedFromAppManager) {
215 RemoveThisAppDomainFromAppManagerTableOnce();
218 HttpRuntime.RecoverFromUnexceptedAppDomainUnload();
220 // call Stop on all registered objects with immediate = true
221 StopRegisteredObjects(true);
223 // notify app manager
224 if (_appManager != null) {
225 // disconnect the real app host and substitute it with a bogus one
226 // to avoid exceptions later when app host is called (it normally wouldn't)
227 IApplicationHost originalAppHost = null;
229 if (_externalAppHost) {
230 originalAppHost = _appHost;
231 _appHost = new SimpleApplicationHost(_appVirtualPath, _appPhysicalPath);
232 _externalAppHost = false;
235 IDisposable configSystem = _configMapPath2 as IDisposable;
236 if (configSystem != null) {
237 configSystem.Dispose();
240 _appManager.HostingEnvironmentShutdownComplete(_appId, originalAppHost);
243 // free the config access token
244 if (_configToken != IntPtr.Zero) {
245 UnsafeNativeMethods.CloseHandle(_configToken);
246 _configToken = IntPtr.Zero;
254 // called from app manager right after app domain (and hosting env) is created
255 internal void Initialize(ApplicationManager appManager, IApplicationHost appHost, IConfigMapPathFactory configMapPathFactory, HostingEnvironmentParameters hostingParameters, PolicyLevel policyLevel) {
256 Initialize(appManager, appHost, configMapPathFactory, hostingParameters, policyLevel, null);
259 [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
260 [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification = "We carefully control this method's callers.")]
261 internal void Initialize(ApplicationManager appManager, IApplicationHost appHost, IConfigMapPathFactory configMapPathFactory,
262 HostingEnvironmentParameters hostingParameters, PolicyLevel policyLevel,
263 Exception appDomainCreationException) {
265 _hostingParameters = hostingParameters;
267 HostingEnvironmentFlags hostingFlags = HostingEnvironmentFlags.Default;
268 if (_hostingParameters != null) {
269 hostingFlags = _hostingParameters.HostingFlags;
270 if (_hostingParameters.IISExpressVersion != null) {
271 ServerConfig.IISExpressVersion = _hostingParameters.IISExpressVersion;
275 // Keep track of the app manager, unless HideFromAppManager flag was passed
276 if ((hostingFlags & HostingEnvironmentFlags.HideFromAppManager) == 0)
277 _appManager = appManager;
279 if ((hostingFlags & HostingEnvironmentFlags.ClientBuildManager) != 0) {
280 BuildManagerHost.InClientBuildManager = true;
283 if ((hostingFlags & HostingEnvironmentFlags.SupportsMultiTargeting) != 0) {
284 BuildManagerHost.SupportsMultiTargeting = true;
287 // Set CLR quirks switches before the config system is initialized since config might depend on them
288 if (_hostingParameters != null && _hostingParameters.ClrQuirksSwitches != null && _hostingParameters.ClrQuirksSwitches.Length > 0) {
289 SetClrQuirksSwitches(_hostingParameters.ClrQuirksSwitches);
293 // init config system using private config if applicable
295 if (appHost is ISAPIApplicationHost && !ServerConfig.UseMetabase) {
296 string rootWebConfigPath = ((ISAPIApplicationHost)appHost).ResolveRootWebConfigPath();
297 if (!String.IsNullOrEmpty(rootWebConfigPath)) {
298 Debug.Assert(File.Exists(rootWebConfigPath), "File.Exists(rootWebConfigPath)");
299 HttpConfigurationSystem.RootWebConfigurationFilePath = rootWebConfigPath;
302 // we need to explicit create a COM proxy in this app domain
303 // so we don't go back to the default domain or have lifetime issues
304 // remember support functions
305 IProcessHostSupportFunctions proxyFunctions = ((ISAPIApplicationHost)appHost).SupportFunctions;
306 if (null != proxyFunctions) {
307 _functions = Misc.CreateLocalSupportFunctions(proxyFunctions);
311 _appId = HttpRuntime.AppDomainAppId;
312 _appVirtualPath = HttpRuntime.AppDomainAppVirtualPathObject;
313 _appPhysicalPath = HttpRuntime.AppDomainAppPathInternal;
316 _configMapPath = configMapPathFactory.Create(_appVirtualPath.VirtualPathString, _appPhysicalPath);
317 HttpConfigurationSystem.EnsureInit(_configMapPath, true, false);
319 // attempt to cache and use IConfigMapPath2 provider
320 // which supports VirtualPath's to save on conversions
321 _configMapPath2 = _configMapPath as IConfigMapPath2;
324 _initiateShutdownWorkItemCallback = new WaitCallback(this.InitiateShutdownWorkItemCallback);
326 // notify app manager
327 if (_appManager != null) {
328 _appManager.HostingEnvironmentActivated(CacheMemorySizePressure.EffectiveProcessMemoryLimit);
331 // make sure there is always app host
332 if (_appHost == null) {
333 _appHost = new SimpleApplicationHost(_appVirtualPath, _appPhysicalPath);
336 _externalAppHost = true;
339 // remember the token to access config
340 _configToken = _appHost.GetConfigToken();
342 // Start with a MapPath based virtual path provider
343 _mapPathBasedVirtualPathProvider = new MapPathBasedVirtualPathProvider();
344 _virtualPathProvider = _mapPathBasedVirtualPathProvider;
346 // initiaze HTTP-independent features
347 HttpRuntime.InitializeHostingFeatures(hostingFlags, policyLevel, appDomainCreationException);
349 // VSWhidbey 393259. Do not monitor idle timeout for CBM since Venus
350 // will always restart a new appdomain if old one is shutdown.
351 if (!BuildManagerHost.InClientBuildManager) {
352 // start monitoring for idle inside app domain
353 StartMonitoringForIdleTimeout();
356 // notify app manager if the app domain limit is violated
357 EnforceAppDomainLimit();
359 // get application identity (for explicit impersonation mode)
360 GetApplicationIdentity();
362 // call AppInitialize, unless the flag says not to do it (e.g. CBM scenario).
363 // Also, don't call it if HostingInit failed (VSWhidbey 210495)
364 if(!HttpRuntime.HostingInitFailed) {
366 BuildManager.ExecutePreAppStart();
367 if ((hostingFlags & HostingEnvironmentFlags.DontCallAppInitialize) == 0) {
368 BuildManager.CallAppInitializeMethod();
371 catch (Exception e) {
372 // could throw compilation errors in 'code' - report them with first http request
373 HttpRuntime.InitializationException = e;
375 if ((hostingFlags & HostingEnvironmentFlags.ThrowHostingInitErrors) != 0) {
382 private void InitializeObjectCacheHostPrivate() {
383 // set ObjectCacheHost if the Host is not already set
384 if (ObjectCache.Host == null) {
385 ObjectCacheHost objectCacheHost = new ObjectCacheHost();
386 ObjectCache.Host = objectCacheHost;
387 _objectCacheHost = objectCacheHost;
391 internal static void InitializeObjectCacheHost() {
392 if (_theHostingEnvironment != null) {
393 _theHostingEnvironment.InitializeObjectCacheHostPrivate();
397 private void StartMonitoringForIdleTimeout() {
398 HostingEnvironmentSection hostEnvConfig = RuntimeConfig.GetAppLKGConfig().HostingEnvironment;
400 TimeSpan idleTimeout = (hostEnvConfig != null) ? hostEnvConfig.IdleTimeout : HostingEnvironmentSection.DefaultIdleTimeout;
402 // always create IdleTimeoutMonitor (even if config value is TimeSpan.MaxValue (infinite)
403 // IdleTimeoutMonitor is also needed to keep the last event for app domain set trimming
404 // and the timer is used to trim the application instances
405 _idleTimeoutMonitor = new IdleTimeoutMonitor(idleTimeout);
408 // enforce app domain limit
409 private void EnforceAppDomainLimit() {
410 if (_appManager == null) /// detached app domain
416 ProcessModelSection pmConfig = RuntimeConfig.GetMachineConfig().ProcessModel;
417 limit = pmConfig.MaxAppDomains;
422 if (limit > 0 && _appManager.AppDomainsCount >= limit) {
423 // current app domain doesn't count yet (not in the table)
424 // that's why '>=' above
425 _appManager.ReduceAppDomainsCount(limit);
429 private void GetApplicationIdentity() {
430 // if the explicit impersonation is set, use it instead of UNC identity
432 IdentitySection c = RuntimeConfig.GetAppConfig().Identity;
433 if (c.Impersonate && c.ImpersonateToken != IntPtr.Zero) {
435 _appIdentityToken = c.ImpersonateToken;
438 _appIdentityToken = _configToken;
440 _appIdentityTokenSet = true;
446 private static void SetClrQuirksSwitches(KeyValuePair<string, bool>[] switches) {
447 // First, see if the static API AppContext.SetSwitch even exists.
448 // Type.GetType will return null if the type doesn't exist; it will throw on catastrophic failure.
450 Type appContextType = Type.GetType("System.AppContext, " + AssemblyRef.Mscorlib);
451 if (appContextType == null) {
452 return; // wrong version of mscorlib - do nothing
455 Action<string, bool> setter = (Action<string, bool>)Delegate.CreateDelegate(
456 typeof(Action<string, bool>),
460 throwOnBindFailure: false);
461 if (setter == null) {
462 return; // wrong version of mscorlib - do nothing
465 // Finally, set each switch individually.
467 foreach (var sw in switches) {
468 setter(sw.Key, sw.Value);
473 // If an exception was thrown during initialization, return it.
474 public static Exception InitializationException {
476 return HttpRuntime.InitializationException;
480 // called from app manager (from management APIs)
481 internal ApplicationInfo GetApplicationInfo() {
482 return new ApplicationInfo(_appId, _appVirtualPath, _appPhysicalPath);
488 [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
489 private void StopRegisteredObjects(bool immediate) {
490 if (_registeredObjects.Count > 0) {
491 ArrayList list = new ArrayList();
494 foreach (DictionaryEntry e in _registeredObjects) {
497 // well-known objects first
498 if (IsWellKnownObject(x)) {
507 foreach (IRegisteredObject obj in list) {
517 private void InitiateShutdownWorkItemCallback(Object state /*not used*/) {
518 Debug.Trace("HostingEnvironmentShutdown", "Shutting down: appId=" + _appId);
520 // no registered objects -- shutdown
521 if (_registeredObjects.Count == 0) {
522 Debug.Trace("HostingEnvironmentShutdown", "No registered objects");
523 ShutdownThisAppDomainOnce();
527 // call Stop on all registered objects with immediate = false
528 StopRegisteredObjects(false);
530 // no registered objects -- shutdown now
531 if (_registeredObjects.Count == 0) {
532 Debug.Trace("HostingEnvironmentShutdown", "All registered objects gone after Stop(false)");
533 ShutdownThisAppDomainOnce();
537 // if not everything shutdown synchronously give it some time.
538 int shutdownTimeoutSeconds = HostingEnvironmentSection.DefaultShutdownTimeout;
539 HostingEnvironmentSection hostEnvConfig = RuntimeConfig.GetAppLKGConfig().HostingEnvironment;
540 if (hostEnvConfig != null) {
541 shutdownTimeoutSeconds = (int) hostEnvConfig.ShutdownTimeout.TotalSeconds;
543 Debug.Trace("HostingEnvironmentShutdown", "Waiting for " + shutdownTimeoutSeconds + " sec...");
545 DateTime waitUntil = DateTime.UtcNow.AddSeconds(shutdownTimeoutSeconds);
546 while (_registeredObjects.Count > 0 && DateTime.UtcNow < waitUntil) {
550 Debug.Trace("HostingEnvironmentShutdown", "Shutdown timeout (" + shutdownTimeoutSeconds + " sec) expired");
552 // call Stop on all registered objects with immediate = true
553 StopRegisteredObjects(true);
555 // no registered objects -- shutdown now
556 if (_registeredObjects.Count == 0) {
557 Debug.Trace("HostingEnvironmentShutdown", "All registered objects gone after Stop(true)");
558 ShutdownThisAppDomainOnce();
562 // shutdown regardless
563 Debug.Trace("HostingEnvironmentShutdown", "Forced shutdown: " + _registeredObjects.Count + " registered objects left");
564 _registeredObjects = new Hashtable();
565 ShutdownThisAppDomainOnce();
568 // app domain shutdown logic
569 internal void InitiateShutdownInternal() {
573 Debug.Trace("AppManager", "HostingEnvironment.InitiateShutdownInternal appId=" + _appId);
575 bool proceed = false;
577 if (!_shutdownInitiated) {
579 if (!_shutdownInitiated) {
580 _shutdownInProgress = true;
582 _shutdownInitiated = true;
591 HttpRuntime.SetShutdownReason(ApplicationShutdownReason.HostingEnvironment, "HostingEnvironment initiated shutdown");
593 // Avoid calling Environment.StackTrace if we are in the ClientBuildManager (Dev10 bug 824659)
594 if (!BuildManagerHost.InClientBuildManager) {
595 new EnvironmentPermission(PermissionState.Unrestricted).Assert();
597 _shutDownStack = Environment.StackTrace;
600 CodeAccessPermission.RevertAssert();
604 // waitChangeNotification need not be honored in ClientBuildManager (Dev11 bug 264894)
605 if (!BuildManagerHost.InClientBuildManager) {
606 // this should only be called once, before the cache is disposed, and
607 // the config records are released.
608 HttpRuntime.CoalesceNotifications();
611 RemoveThisAppDomainFromAppManagerTableOnce();
613 // stop all registered objects without blocking
614 ThreadPool.QueueUserWorkItem(this._initiateShutdownWorkItemCallback);
616 } catch (Exception ex) {
617 HandleExceptionFromInitiateShutdownInternal(ex);
624 // InitiateShutdownInternal should never throw an exception, but we have seen cases where
625 // CLR bugs can cause it to fail without running to completion. This could cause an ASP.NET
626 // AppDomain never to unload. If we detect that an exception is thrown, we should DebugBreak
627 // so that the fundamentals team can investigate. Taking the Exception object as a parameter
628 // makes it easy to locate when looking at a stack dump.
629 [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]
630 private static void HandleExceptionFromInitiateShutdownInternal(Exception ex) {
635 internal bool HasBeenRemovedFromAppManagerTable {
637 return _hasBeenRemovedFromAppManangerTable;
640 _hasBeenRemovedFromAppManangerTable = value;
644 private void RemoveThisAppDomainFromAppManagerTableOnce() {
645 bool proceed = false;
646 if (!_removedFromAppManager) {
648 if (!_removedFromAppManager) {
650 _removedFromAppManager = true;
658 if (_appManager != null) {
659 Debug.Trace("AppManager", "Removing HostingEnvironment from AppManager table, appId=" + _appId);
660 _appManager.HostingEnvironmentShutdownInitiated(_appId, this);
663 Debug.Trace("FileChangesMonitorIgnoreSubdirChange",
664 "*** REMOVE APPMANAGER TABLE" + DateTime.Now.ToString("hh:mm:ss.fff", CultureInfo.InvariantCulture)
665 + ": _appId=" + _appId);
669 private void ShutdownThisAppDomainOnce() {
670 bool proceed = false;
672 if (!_appDomainShutdownStarted) {
674 if (!_appDomainShutdownStarted) {
676 _appDomainShutdownStarted = true;
684 Debug.Trace("AppManager", "HostingEnvironment - shutting down AppDomain, appId=" + _appId);
686 // stop the timer used for idle timeout
687 if (_idleTimeoutMonitor != null) {
688 _idleTimeoutMonitor.Stop();
689 _idleTimeoutMonitor = null;
692 while (_inTrimCache == 1) {
696 // close all outstanding WebSocket connections and begin winding down code that consumes them
697 AspNetWebSocketManager.Current.AbortAllAndWait();
700 HttpRuntime.SetUserForcedShutdown();
702 //WOS 1400290: CantUnloadAppDomainException in ISAPI mode, wait until HostingEnvironment.ShutdownThisAppDomainOnce completes
703 _shutdownInProgress = false;
705 HttpRuntime.ShutdownAppDomainWithStackTrace(ApplicationShutdownReason.HostingEnvironment,
706 SR.GetString(SR.Hosting_Env_Restart),
711 // internal methods called by app manager
714 // helper for app manager to implement AppHost.CreateAppHost
715 [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
716 internal ObjectHandle CreateInstance(String assemblyQualifiedName) {
717 Type type = Type.GetType(assemblyQualifiedName, true);
718 return new ObjectHandle(Activator.CreateInstance(type));
721 // start well known object
722 [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
723 internal ObjectHandle CreateWellKnownObjectInstance(String assemblyQualifiedName, bool failIfExists) {
724 Type type = Type.GetType(assemblyQualifiedName, true);
725 IRegisteredObject obj = null;
726 String key = type.FullName;
730 obj = _wellKnownObjects[key] as IRegisteredObject;
733 obj = (IRegisteredObject)Activator.CreateInstance(type);
734 _wellKnownObjects[key] = obj;
741 if (exists && failIfExists) {
742 throw new InvalidOperationException(SR.GetString(SR.Wellknown_object_already_exists, key));
745 return new ObjectHandle(obj);
748 // check if well known object
749 private bool IsWellKnownObject(Object obj) {
751 String key = obj.GetType().FullName;
754 if (_wellKnownObjects[key] == obj) {
762 // find well known object by type
763 internal ObjectHandle FindWellKnownObject(String assemblyQualifiedName) {
764 Type type = Type.GetType(assemblyQualifiedName, true);
765 IRegisteredObject obj = null;
766 String key = type.FullName;
769 obj = _wellKnownObjects[key] as IRegisteredObject;
772 return (obj != null) ? new ObjectHandle(obj) : null;
775 // stop well known object by type
776 [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
777 internal void StopWellKnownObject(String assemblyQualifiedName) {
778 Type type = Type.GetType(assemblyQualifiedName, true);
779 IRegisteredObject obj = null;
780 String key = type.FullName;
783 obj = _wellKnownObjects[key] as IRegisteredObject;
785 _wellKnownObjects.Remove(key);
791 internal bool IsIdle() {
792 bool isBusy = _isBusy;
794 return (!isBusy && _busyCount == 0);
797 internal bool GetIdleValue() {
798 return (!_isBusy && _busyCount == 0);
801 internal void IncrementBusyCountInternal() {
803 Interlocked.Increment(ref _busyCount);
806 internal void DecrementBusyCountInternal() {
808 Interlocked.Decrement(ref _busyCount);
810 // Notify idle timeout monitor
811 IdleTimeoutMonitor itm = _idleTimeoutMonitor;
813 itm.LastEvent = DateTime.UtcNow;
816 internal void IsUnloaded()
821 private void MessageReceivedInternal() {
824 IdleTimeoutMonitor itm = _idleTimeoutMonitor;
826 itm.LastEvent = DateTime.UtcNow;
830 // the busier the app domain the higher the score
831 internal int LruScore {
836 IdleTimeoutMonitor itm = _idleTimeoutMonitor;
841 // return negative number of seconds since last activity
842 return -(int)(DateTime.UtcNow - itm.LastEvent).TotalSeconds;
846 internal static ApplicationManager GetApplicationManager() {
847 if (_theHostingEnvironment == null)
850 return _theHostingEnvironment._appManager;
857 // register protocol handler with hosting environment
858 private void RegisterRunningObjectInternal(IRegisteredObject obj) {
860 _registeredObjects[obj] = obj;
862 ISuspendibleRegisteredObject suspendibleObject = obj as ISuspendibleRegisteredObject;
863 if (suspendibleObject != null) {
864 _suspendManager.RegisterObject(suspendibleObject);
869 // unregister protocol handler from hosting environment
870 private void UnregisterRunningObjectInternal(IRegisteredObject obj) {
871 bool lastOne = false;
874 // if it is a well known object, remove it from that table as well
875 String key = obj.GetType().FullName;
876 if (_wellKnownObjects[key] == obj) {
877 _wellKnownObjects.Remove(key);
880 // remove from running objects list
881 _registeredObjects.Remove(obj);
883 ISuspendibleRegisteredObject suspendibleObject = obj as ISuspendibleRegisteredObject;
884 if (suspendibleObject != null) {
885 _suspendManager.UnregisterObject(suspendibleObject);
888 if (_registeredObjects.Count == 0)
895 // shutdown app domain after last protocol handler is gone
897 InitiateShutdownInternal();
901 [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification = "This method is not dangerous.")]
902 private String GetSiteName() {
903 if (_siteName == null) {
905 if (_siteName == null) {
908 if (_appHost != null) {
910 InternalSecurityPermissions.Unrestricted.Assert();
912 s = _appHost.GetSiteName();
915 CodeAccessPermission.RevertAssert();
920 s = WebConfigurationHost.DefaultSiteName;
931 [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification = "This method is not dangerous.")]
932 private String GetSiteID() {
933 if (_siteID == null) {
935 if (_siteID == null) {
938 if (_appHost != null) {
940 InternalSecurityPermissions.Unrestricted.Assert();
942 s = _appHost.GetSiteID();
945 CodeAccessPermission.RevertAssert();
950 s = WebConfigurationHost.DefaultSiteID;
952 _siteID = s.ToLower(CultureInfo.InvariantCulture);
960 // Return the configPath for the app, e.g. "machine/webroot/1/myapp"
961 private String GetAppConfigPath() {
962 if (_appConfigPath == null) {
963 _appConfigPath = WebConfigurationHost.GetConfigPathFromSiteIDAndVPath(SiteID, ApplicationVirtualPathObject);
966 return _appConfigPath;
969 // Return the call context slot name to use for a virtual path
970 private static string GetFixedMappingSlotName(VirtualPath virtualPath) {
971 return "MapPath_" + virtualPath.VirtualPathString.ToLowerInvariant().GetHashCode().ToString(CultureInfo.InvariantCulture);
975 * Map a virtual path to a physical path. i.e. the physicalPath will be returned
976 * when MapPath is called on the virtual path, bypassing the IApplicationHost
978 private static string GetVirtualPathToFileMapping(VirtualPath virtualPath) {
979 return CallContext.GetData(GetFixedMappingSlotName(virtualPath)) as string;
983 * Map a virtual path to a physical path. i.e. the physicalPath will be returned
984 * when MapPath is called on the virtual path, bypassing the IApplicationHost
986 internal static object AddVirtualPathToFileMapping(
987 VirtualPath virtualPath, string physicalPath) {
989 // Save the mapping in the call context, using a key derived from the
990 // virtual path. The mapping is only valid for the duration of the request.
991 CallContext.SetData(GetFixedMappingSlotName(virtualPath), physicalPath);
993 // Return a mapping object to keep track of the virtual path, and of the current
994 // virtualPathProvider.
995 VirtualPathToFileMappingState state = new VirtualPathToFileMappingState();
996 state.VirtualPath = virtualPath;
997 state.VirtualPathProvider = _theHostingEnvironment._virtualPathProvider;
999 // Always use the MapPathBasedVirtualPathProvider, otherwise the mapping mechanism
1000 // doesn't work (VSWhidbey 420702)
1001 // Set/Get the VPP on the call context so as not to affect other concurrent requests (Dev10 852255)
1002 CallContext.SetData(TemporaryVirtualPathProviderKey, _theHostingEnvironment._mapPathBasedVirtualPathProvider);
1007 internal static void ClearVirtualPathToFileMapping(object state) {
1009 VirtualPathToFileMappingState mapping = (VirtualPathToFileMappingState)state;
1011 // Clear the mapping from the call context
1012 CallContext.SetData(GetFixedMappingSlotName(mapping.VirtualPath), null);
1014 // Restore the previous VirtualPathProvider
1015 // Set/Get the VPP on the call context so as not to affect other concurrent requests (Dev10 852255)
1016 CallContext.SetData(TemporaryVirtualPathProviderKey, null);
1019 private string MapPathActual(VirtualPath virtualPath, bool permitNull)
1021 string result = null;
1023 Debug.Assert(virtualPath != null);
1025 virtualPath.FailIfRelativePath();
1027 VirtualPath reqpath = virtualPath;
1029 if (String.CompareOrdinal(reqpath.VirtualPathString, _appVirtualPath.VirtualPathString) == 0) {
1030 // for application path don't need to call app host
1031 Debug.Trace("MapPath", reqpath +" is the app path");
1032 result = _appPhysicalPath;
1035 using (new ProcessImpersonationContext()) {
1036 // If there is a mapping for this virtual path in the call context, use it
1037 result = GetVirtualPathToFileMapping(reqpath);
1039 if (result == null) {
1040 // call host's mappath
1041 if (_configMapPath == null) {
1042 Debug.Trace("MapPath", "Missing _configMapPath");
1043 throw new InvalidOperationException(SR.GetString(SR.Cannot_map_path, reqpath));
1045 Debug.Trace("MapPath", "call ConfigMapPath (" + reqpath + ")");
1047 // see if the IConfigMapPath provider implements the interface
1050 if (null != _configMapPath2) {
1051 result = _configMapPath2.MapPath(GetSiteID(), reqpath);
1054 result = _configMapPath.MapPath(GetSiteID(), reqpath.VirtualPathString);
1056 if (HttpRuntime.IsMapPathRelaxed)
1057 result = HttpRuntime.GetRelaxedMapPathResult(result);
1059 if (HttpRuntime.IsMapPathRelaxed)
1060 result = HttpRuntime.GetRelaxedMapPathResult(null);
1068 if (String.IsNullOrEmpty(result)) {
1069 Debug.Trace("MapPath", "null Result");
1071 if (HttpRuntime.IsMapPathRelaxed)
1072 result = HttpRuntime.GetRelaxedMapPathResult(null);
1074 throw new InvalidOperationException(SR.GetString(SR.Cannot_map_path, reqpath));
1078 // ensure extra '\\' in the physical path if the virtual path had extra '/'
1079 // and the other way -- no extra '\\' in physical if virtual didn't have it.
1080 if (virtualPath.HasTrailingSlash) {
1081 if (!UrlPath.PathEndsWithExtraSlash(result) && !UrlPath.PathIsDriveRoot(result))
1082 result = result + "\\";
1085 if (UrlPath.PathEndsWithExtraSlash(result) && !UrlPath.PathIsDriveRoot(result))
1086 result = result.Substring(0, result.Length - 1);
1089 Debug.Trace("MapPath", " result=" + result);
1096 // public static methods
1100 // register protocol handler with hosting environment
1101 [SecurityPermission(SecurityAction.Demand, Unrestricted = true)]
1102 public static void RegisterObject(IRegisteredObject obj) {
1103 if (_theHostingEnvironment != null)
1104 _theHostingEnvironment.RegisterRunningObjectInternal(obj);
1108 // unregister protocol handler from hosting environment
1109 [SecurityPermission(SecurityAction.Demand, Unrestricted = true)]
1110 public static void UnregisterObject(IRegisteredObject obj) {
1111 if (_theHostingEnvironment != null)
1112 _theHostingEnvironment.UnregisterRunningObjectInternal(obj);
1115 // Schedules a task which can run in the background, independent of any request.
1116 // This differs from a normal ThreadPool work item in that ASP.NET can keep track
1117 // of how many work items registered through this API are currently running, and
1118 // the ASP.NET runtime will try not to delay AppDomain shutdown until these work
1119 // items have finished executing.
1122 // - This API cannot be called outside of an ASP.NET-managed AppDomain.
1123 // - The caller's ExecutionContext is not flowed to the work item.
1124 // - Scheduled work items are not guaranteed to ever execute, e.g., when AppDomain
1125 // shutdown has already started by the time this API was called.
1126 // - The provided CancellationToken will be signaled when the application is
1127 // shutting down. The work item should make every effort to honor this token.
1128 // If a work item does not honor this token and continues executing it will
1129 // eventually be considered rogue, and the ASP.NET runtime will rudely unload
1130 // the AppDomain without waiting for the work item to finish.
1132 // This overload of QueueBackgroundWorkItem takes a void-returning callback; the
1133 // work item will be considered finished when the callback returns.
1134 [SecurityPermission(SecurityAction.LinkDemand, Unrestricted = true)]
1135 public static void QueueBackgroundWorkItem(Action<CancellationToken> workItem) {
1136 if (workItem == null) {
1137 throw new ArgumentNullException("workItem");
1140 QueueBackgroundWorkItem(ct => { workItem(ct); return _completedTask; });
1143 // See documentation on the other overload for a general API overview.
1145 // This overload of QueueBackgroundWorkItem takes a Task-returning callback; the
1146 // work item will be considered finished when the returned Task transitions to a
1148 [SecurityPermission(SecurityAction.LinkDemand, Unrestricted = true)]
1149 public static void QueueBackgroundWorkItem(Func<CancellationToken, Task> workItem) {
1150 if (workItem == null) {
1151 throw new ArgumentNullException("workItem");
1153 if (_theHostingEnvironment == null) {
1154 throw new InvalidOperationException(); // can only be called within an ASP.NET AppDomain
1157 _theHostingEnvironment.QueueBackgroundWorkItemInternal(workItem);
1160 private void QueueBackgroundWorkItemInternal(Func<CancellationToken, Task> workItem) {
1161 Debug.Assert(workItem != null);
1163 BackgroundWorkScheduler scheduler = Volatile.Read(ref _backgroundWorkScheduler);
1165 // If the scheduler doesn't exist, lazily create it, but only allow one instance to ever be published to the backing field
1166 if (scheduler == null) {
1167 BackgroundWorkScheduler newlyCreatedScheduler = new BackgroundWorkScheduler(UnregisterObject, Misc.WriteUnhandledExceptionToEventLog);
1168 scheduler = Interlocked.CompareExchange(ref _backgroundWorkScheduler, newlyCreatedScheduler, null) ?? newlyCreatedScheduler;
1169 if (scheduler == newlyCreatedScheduler) {
1170 RegisterObject(scheduler); // Only call RegisterObject if we just created the "winning" one
1174 scheduler.ScheduleWorkItem(workItem);
1177 // This event is a simple way to hook IStopListeningRegisteredObject.StopListening
1178 // without needing to call RegisterObject. The same restrictions which apply to
1179 // that method apply to this event.
1180 public static event EventHandler StopListening;
1183 // public static methods for the user code to call
1187 public static void IncrementBusyCount() {
1188 if (_theHostingEnvironment != null)
1189 _theHostingEnvironment.IncrementBusyCountInternal();
1193 public static void DecrementBusyCount() {
1194 if (_theHostingEnvironment != null)
1195 _theHostingEnvironment.DecrementBusyCountInternal();
1199 public static void MessageReceived() {
1200 if (_theHostingEnvironment != null)
1201 _theHostingEnvironment.MessageReceivedInternal();
1204 public static bool InClientBuildManager {
1206 return BuildManagerHost.InClientBuildManager;
1210 public static bool IsHosted {
1212 return (_theHostingEnvironment != null);
1216 internal static bool IsUnderIISProcess {
1218 String process = VersionInfo.ExeName;
1220 return process == "aspnet_wp" ||
1221 process == "w3wp" ||
1222 process == "inetinfo";
1226 internal static bool IsUnderIIS6Process {
1228 return VersionInfo.ExeName == "w3wp";
1232 public static IApplicationHost ApplicationHost {
1233 //DevDivBugs 109864: ASP.NET: path discovery issue - In low trust, it is possible to get the physical path of any virtual path on the machine
1234 [SecurityPermission(SecurityAction.Demand, Unrestricted = true)]
1236 if (_theHostingEnvironment == null)
1239 return _theHostingEnvironment._appHost;
1243 internal static IApplicationHost ApplicationHostInternal {
1245 if (_theHostingEnvironment == null)
1248 return _theHostingEnvironment._appHost;
1252 internal IApplicationHost InternalApplicationHost {
1258 internal static int BusyCount {
1260 if (_theHostingEnvironment == null)
1263 return _theHostingEnvironment._busyCount;
1267 internal static bool ShutdownInitiated {
1269 if (_theHostingEnvironment == null)
1272 return _theHostingEnvironment._shutdownInitiated;
1277 internal static bool ShutdownInProgress {
1279 if (_theHostingEnvironment == null)
1282 return _theHostingEnvironment._shutdownInProgress;
1288 /// <para>The application ID (metabase path in IIS hosting).</para>
1290 public static String ApplicationID {
1292 if (_theHostingEnvironment == null)
1295 InternalSecurityPermissions.AspNetHostingPermissionLevelHigh.Demand();
1296 return _theHostingEnvironment._appId;
1300 internal static String ApplicationIDNoDemand {
1302 if (_theHostingEnvironment == null) {
1306 return _theHostingEnvironment._appId;
1312 /// <para>Physical path to the application root.</para>
1314 public static String ApplicationPhysicalPath {
1316 if (_theHostingEnvironment == null)
1319 InternalSecurityPermissions.AppPathDiscovery.Demand();
1320 return _theHostingEnvironment._appPhysicalPath;
1326 /// <para>Virtual path to the application root.</para>
1328 public static String ApplicationVirtualPath {
1330 return VirtualPath.GetVirtualPathStringNoTrailingSlash(ApplicationVirtualPathObject);
1334 internal static VirtualPath ApplicationVirtualPathObject {
1336 if (_theHostingEnvironment == null)
1339 return _theHostingEnvironment._appVirtualPath;
1345 /// <para>Site name.</para>
1347 public static String SiteName {
1349 if (_theHostingEnvironment == null)
1352 InternalSecurityPermissions.AspNetHostingPermissionLevelMedium.Demand();
1353 return _theHostingEnvironment.GetSiteName();
1357 internal static String SiteNameNoDemand {
1359 if (_theHostingEnvironment == null)
1362 return _theHostingEnvironment.GetSiteName();
1366 internal static String SiteID {
1368 if (_theHostingEnvironment == null)
1371 return _theHostingEnvironment.GetSiteID();
1375 internal static IConfigMapPath ConfigMapPath {
1377 if (_theHostingEnvironment == null)
1380 return _theHostingEnvironment._configMapPath;
1384 internal static String AppConfigPath {
1386 if (_theHostingEnvironment == null) {
1390 return _theHostingEnvironment.GetAppConfigPath();
1394 // See comments in ApplicationManager.CreateAppDomainWithHostingEnvironment. This is the public API to access the
1395 // information we determined in that method. Defaults to 'false' if our AppDomain data isn't present.
1396 public static bool IsDevelopmentEnvironment {
1398 return (AppDomain.CurrentDomain.GetData(".devEnvironment") as bool?) == true;
1405 /// Gets a reference to the System.Web.Cache.Cache object for the current request.
1408 public static Cache Cache {
1409 get { return HttpRuntime.Cache; }
1412 // count of all app domain from app manager
1413 internal static int AppDomainsCount {
1415 ApplicationManager appManager = GetApplicationManager();
1416 return (appManager != null) ? appManager.AppDomainsCount : 0;
1420 internal static HostingEnvironmentParameters HostingParameters {
1422 if (_theHostingEnvironment == null)
1425 return _theHostingEnvironment._hostingParameters;
1429 // Return an integer that is unique for each appdomain. This can be used
1430 // to create things like once-per-appdomain temp files without having different
1431 // processes/appdomains step on each other
1432 private static int s_appDomainUniqueInteger;
1433 internal static int AppDomainUniqueInteger {
1435 if (s_appDomainUniqueInteger == 0) {
1436 s_appDomainUniqueInteger = Guid.NewGuid().GetHashCode();
1439 return s_appDomainUniqueInteger;
1443 public static ApplicationShutdownReason ShutdownReason {
1444 get { return HttpRuntime.ShutdownReason; }
1447 // Was CGlobalModule::OnGlobalStopListening called?
1448 internal static bool StopListeningWasCalled {
1450 return _stopListeningWasCalled;
1454 [SuppressMessage("Microsoft.Reliability", "CA2004:RemoveCallsToGCKeepAlive", Justification = "See comment in function.")]
1455 internal static void SetupStopListeningHandler() {
1456 StopListeningWaitHandle waitHandle = new StopListeningWaitHandle();
1458 RegisteredWaitHandle registeredWaitHandle = null;
1459 registeredWaitHandle = ThreadPool.UnsafeRegisterWaitForSingleObject(waitHandle, (_, __) => {
1460 // Referencing the field from within the callback should be sufficient to keep the GC
1461 // from reclaiming the RegisteredWaitHandle; the race condition is fine.
1462 GC.KeepAlive(registeredWaitHandle);
1463 OnGlobalStopListening();
1464 }, null, Timeout.Infinite, executeOnlyOnce: true);
1467 private static void OnGlobalStopListening() {
1468 _stopListeningWasCalled = true;
1470 EventHandler eventHandler = StopListening;
1471 if (eventHandler != null) {
1472 eventHandler(null /* static means no sender */, EventArgs.Empty);
1475 if (_theHostingEnvironment != null) {
1476 _theHostingEnvironment.FireStopListeningHandlers();
1480 [SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Justification = "'this' always has strong identity.")]
1481 private void FireStopListeningHandlers() {
1482 List<IStopListeningRegisteredObject> listeners = new List<IStopListeningRegisteredObject>();
1484 foreach (DictionaryEntry e in _registeredObjects) {
1485 IStopListeningRegisteredObject listener = e.Key as IStopListeningRegisteredObject;
1486 if (listener != null) {
1487 listeners.Add(listener);
1492 foreach (var listener in listeners) {
1493 listener.StopListening();
1498 /// <para>Initiate app domain unloading for the current app.</para>
1500 [SecurityPermission(SecurityAction.Demand, Unrestricted = true)]
1501 public static void InitiateShutdown() {
1502 if (_theHostingEnvironment != null)
1503 _theHostingEnvironment.InitiateShutdownInternal();
1506 internal static void InitiateShutdownWithoutDemand() {
1507 if (_theHostingEnvironment != null)
1508 _theHostingEnvironment.InitiateShutdownInternal();
1512 // Internal methods for the ApplicationManager to suspend / resume this application.
1513 // Using GCHandle instead of ObjectHandle means we don't need to worry about lease lifetimes.
1516 internal IntPtr SuspendApplication() {
1517 var state = _suspendManager.Suspend();
1518 return GCUtil.RootObject(state);
1521 internal void ResumeApplication(IntPtr state) {
1522 var unwrappedState = GCUtil.UnrootObject(state);
1523 _suspendManager.Resume(unwrappedState);
1527 /// <para>Maps a virtual path to a physical path.</para>
1529 public static string MapPath(string virtualPath) {
1530 return MapPath(VirtualPath.Create(virtualPath));
1533 internal static string MapPath(VirtualPath virtualPath) {
1534 if (_theHostingEnvironment == null)
1537 String path = MapPathInternal(virtualPath);
1540 InternalSecurityPermissions.PathDiscovery(path).Demand();
1545 internal static String MapPathInternal(string virtualPath) {
1546 return MapPathInternal(VirtualPath.Create(virtualPath));
1549 internal static String MapPathInternal(VirtualPath virtualPath) {
1550 if (_theHostingEnvironment == null) {
1554 return _theHostingEnvironment.MapPathActual(virtualPath, false);
1557 internal static String MapPathInternal(string virtualPath, bool permitNull) {
1558 return MapPathInternal(VirtualPath.Create(virtualPath), permitNull);
1561 internal static String MapPathInternal(VirtualPath virtualPath, bool permitNull) {
1562 if (_theHostingEnvironment == null) {
1566 return _theHostingEnvironment.MapPathActual(virtualPath, permitNull);
1569 internal static string MapPathInternal(string virtualPath, string baseVirtualDir, bool allowCrossAppMapping) {
1570 return MapPathInternal(VirtualPath.Create(virtualPath),
1571 VirtualPath.CreateNonRelative(baseVirtualDir), allowCrossAppMapping);
1574 internal static string MapPathInternal(VirtualPath virtualPath, VirtualPath baseVirtualDir, bool allowCrossAppMapping) {
1575 Debug.Assert(baseVirtualDir != null, "baseVirtualDir != null");
1577 // Combine it with the base and reduce
1578 virtualPath = baseVirtualDir.Combine(virtualPath);
1580 if (!allowCrossAppMapping && !virtualPath.IsWithinAppRoot)
1581 throw new ArgumentException(SR.GetString(SR.Cross_app_not_allowed, virtualPath));
1583 return MapPathInternal(virtualPath);
1586 internal static WebApplicationLevel GetPathLevel(String path) {
1587 WebApplicationLevel pathLevel = WebApplicationLevel.AboveApplication;
1589 if (_theHostingEnvironment != null && !String.IsNullOrEmpty(path)) {
1590 String appPath = ApplicationVirtualPath;
1592 if (appPath == "/") {
1594 pathLevel = WebApplicationLevel.AtApplication;
1596 else if (path[0] == '/') {
1597 pathLevel = WebApplicationLevel.BelowApplication;
1601 if (StringUtil.EqualsIgnoreCase(appPath, path)) {
1602 pathLevel = WebApplicationLevel.AtApplication;
1604 else if (path.Length > appPath.Length && path[appPath.Length] == '/' &&
1605 StringUtil.StringStartsWithIgnoreCase(path, appPath)) {
1607 pathLevel = WebApplicationLevel.BelowApplication;
1617 // Impersonation helpers
1619 // user token for the app (hosting / unc)
1620 internal static IntPtr ApplicationIdentityToken {
1622 if (_theHostingEnvironment == null) {
1626 if (_theHostingEnvironment._appIdentityTokenSet)
1627 return _theHostingEnvironment._appIdentityToken;
1629 return _theHostingEnvironment._configToken;
1635 // check if application impersonation != process impersonation
1636 internal static bool HasHostingIdentity {
1638 return (ApplicationIdentityToken != IntPtr.Zero);
1642 // impersonate application identity
1643 [SecurityPermission(SecurityAction.Demand, ControlPrincipal = true)]
1644 public static IDisposable Impersonate() {
1645 return new ApplicationImpersonationContext();
1648 // impersonate the given user identity
1649 [SecurityPermission(SecurityAction.Demand, Unrestricted = true)]
1650 public static IDisposable Impersonate(IntPtr token) {
1651 if (token == IntPtr.Zero) {
1652 return new ProcessImpersonationContext();
1655 return new ImpersonationContext(token);
1659 // impersonate as configured for a given path
1660 [SecurityPermission(SecurityAction.Demand, Unrestricted = true)]
1661 public static IDisposable Impersonate(IntPtr userToken, String virtualPath) {
1662 virtualPath = UrlPath.MakeVirtualPathAppAbsoluteReduceAndCheck(virtualPath);
1664 if (_theHostingEnvironment == null) {
1665 return Impersonate(userToken);
1668 IdentitySection c = RuntimeConfig.GetConfig(virtualPath).Identity;
1669 if (c.Impersonate) {
1670 if (c.ImpersonateToken != IntPtr.Zero) {
1671 return new ImpersonationContext(c.ImpersonateToken);
1674 return new ImpersonationContext(userToken);
1678 return new ApplicationImpersonationContext();
1686 public static IDisposable SetCultures() {
1687 return SetCultures(RuntimeConfig.GetAppLKGConfig().Globalization);
1690 public static IDisposable SetCultures(string virtualPath) {
1691 virtualPath = UrlPath.MakeVirtualPathAppAbsoluteReduceAndCheck(virtualPath);
1692 return SetCultures(RuntimeConfig.GetConfig(virtualPath).Globalization);
1695 private static IDisposable SetCultures(GlobalizationSection gs) {
1696 CultureContext c = new CultureContext();
1699 CultureInfo culture = null;
1700 CultureInfo uiCulture = null;
1702 if (gs.Culture != null && gs.Culture.Length > 0) {
1704 culture = HttpServerUtility.CreateReadOnlyCultureInfo(gs.Culture);
1710 if (gs.UICulture != null && gs.UICulture.Length > 0) {
1712 uiCulture = HttpServerUtility.CreateReadOnlyCultureInfo(gs.UICulture);
1718 c.SetCultures(culture, uiCulture);
1725 class CultureContext : IDisposable {
1726 CultureInfo _savedCulture;
1727 CultureInfo _savedUICulture;
1729 internal CultureContext() {
1732 void IDisposable.Dispose() {
1736 internal void SetCultures(CultureInfo culture, CultureInfo uiCulture) {
1737 CultureInfo currentCulture = Thread.CurrentThread.CurrentCulture;
1738 CultureInfo currentUICulture = Thread.CurrentThread.CurrentUICulture;
1740 if (culture != null && culture != currentCulture) {
1741 Thread.CurrentThread.CurrentCulture = culture;
1742 _savedCulture = currentCulture;
1745 if (uiCulture != null && uiCulture != currentCulture) {
1746 Thread.CurrentThread.CurrentUICulture = uiCulture;
1747 _savedUICulture = currentUICulture;
1751 internal void RestoreCultures() {
1752 if (_savedCulture != null && _savedCulture != Thread.CurrentThread.CurrentCulture) {
1753 Thread.CurrentThread.CurrentCulture = _savedCulture;
1754 _savedCulture = null;
1757 if (_savedUICulture != null && _savedUICulture != Thread.CurrentThread.CurrentUICulture) {
1758 Thread.CurrentThread.CurrentUICulture = _savedUICulture;
1759 _savedUICulture = null;
1765 // VirtualPathProvider related code
1768 private VirtualPathProvider _virtualPathProvider;
1769 private VirtualPathProvider _mapPathBasedVirtualPathProvider;
1772 public static VirtualPathProvider VirtualPathProvider {
1774 if (_theHostingEnvironment == null)
1777 // Set/Get the VPP on the call context so as not to affect other concurrent requests (Dev10 852255)
1778 var tempVPP = CallContext.GetData(TemporaryVirtualPathProviderKey);
1779 if (tempVPP != null) {
1780 return tempVPP as VirtualPathProvider;
1783 return _theHostingEnvironment._virtualPathProvider;
1787 internal static bool UsingMapPathBasedVirtualPathProvider {
1789 if (_theHostingEnvironment == null)
1792 return (_theHostingEnvironment._virtualPathProvider ==
1793 _theHostingEnvironment._mapPathBasedVirtualPathProvider);
1797 // [AspNetHostingPermission(SecurityAction.Demand, Level=AspNetHostingPermissionLevel.High)]
1798 // Removed the above LinkDemand for AspNetHostingPermissionLevel.High. If we decide to add VPP
1799 // support for config in the future, we should have a separate API with a demand for registering
1800 // VPPs supporting configuration.
1801 public static void RegisterVirtualPathProvider(VirtualPathProvider virtualPathProvider) {
1803 if (_theHostingEnvironment == null)
1804 throw new InvalidOperationException();
1806 // Ignore the VirtualPathProvider on precompiled sites (VSWhidbey 368169,404844)
1807 if (BuildManager.IsPrecompiledApp)
1810 RegisterVirtualPathProviderInternal(virtualPathProvider);
1813 internal static void RegisterVirtualPathProviderInternal(VirtualPathProvider virtualPathProvider) {
1814 VirtualPathProvider previous = _theHostingEnvironment._virtualPathProvider;
1815 _theHostingEnvironment._virtualPathProvider = virtualPathProvider;
1817 // Give it the previous provider so it can delegate if needed
1818 virtualPathProvider.Initialize(previous);
1821 // Helper class used to keep track of state when using
1822 // AddVirtualPathToFileMapping & ClearVirtualPathToFileMapping
1823 internal class VirtualPathToFileMappingState {
1824 internal VirtualPath VirtualPath;
1825 internal VirtualPathProvider VirtualPathProvider;
1828 internal static IProcessHostSupportFunctions SupportFunctions {
1837 [SuppressMessage("Microsoft.Naming", "CA1705:LongAcronymsShouldBePascalCased",
1838 Justification="matches casing of config attribute")]
1839 public static int MaxConcurrentRequestsPerCPU {
1841 if (!HttpRuntime.UseIntegratedPipeline) {
1842 throw new PlatformNotSupportedException(SR.GetString(SR.Requires_Iis_Integrated_Mode));
1844 return UnsafeIISMethods.MgdGetMaxConcurrentRequestsPerCPU();
1846 [SecurityPermission(SecurityAction.Demand, Unrestricted = true)]
1848 if (!HttpRuntime.UseIntegratedPipeline) {
1849 throw new PlatformNotSupportedException(SR.GetString(SR.Requires_Iis_Integrated_Mode));
1851 int hr = UnsafeIISMethods.MgdSetMaxConcurrentRequestsPerCPU(value);
1853 case HResults.S_FALSE:
1854 // Because "maxConcurrentRequestsPerCPU" is currently zero, we cannot set the value, since that would
1855 // enable the feature, which can only be done via configuration.
1856 throw new InvalidOperationException(SR.GetString(SR.Queue_limit_is_zero, "maxConcurrentRequestsPerCPU"));
1857 case HResults.E_INVALIDARG:
1858 // The value must be greater than zero. A value of zero would disable the feature, but this can only be done via configuration.
1859 throw new ArgumentException(SR.GetString(SR.Invalid_queue_limit));
1864 [SuppressMessage("Microsoft.Naming", "CA1705:LongAcronymsShouldBePascalCased",
1865 Justification="matches casing of config attribute")]
1866 public static int MaxConcurrentThreadsPerCPU {
1868 if (!HttpRuntime.UseIntegratedPipeline) {
1869 throw new PlatformNotSupportedException(SR.GetString(SR.Requires_Iis_Integrated_Mode));
1871 return UnsafeIISMethods.MgdGetMaxConcurrentThreadsPerCPU();
1873 [SecurityPermission(SecurityAction.Demand, Unrestricted = true)]
1875 if (!HttpRuntime.UseIntegratedPipeline) {
1876 throw new PlatformNotSupportedException(SR.GetString(SR.Requires_Iis_Integrated_Mode));
1878 int hr = UnsafeIISMethods.MgdSetMaxConcurrentThreadsPerCPU(value);
1880 case HResults.S_FALSE:
1881 // Because "maxConcurrentThreadsPerCPU" is currently zero, we cannot set the value, since that would
1882 // enable the feature, which can only be done via configuration.
1883 throw new InvalidOperationException(SR.GetString(SR.Queue_limit_is_zero, "maxConcurrentThreadsPerCPU"));
1884 case HResults.E_INVALIDARG:
1885 // The value must be greater than zero. A value of zero would disable the feature, but this can only be done via configuration.
1886 throw new ArgumentException(SR.GetString(SR.Invalid_queue_limit));
1892 /// Returns the ASP.NET hosted domain.
1894 internal AppDomain HostedAppDomain {
1896 return AppDomain.CurrentDomain;