Updates referencesource to .NET 4.7
[mono-project.git] / mcs / class / referencesource / System.Web / HttpRuntime.cs
blob8ea7235908757a02beab4276ab26498cdbc6abb9
1 //------------------------------------------------------------------------------
2 // <copyright file="HttpRuntime.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
4 // </copyright>
5 //------------------------------------------------------------------------------
7 /*
8 * The ASP.NET runtime services
10 * Copyright (c) 1998 Microsoft Corporation
13 namespace System.Web {
14 using System;
15 using System.Collections;
16 using System.Configuration;
17 using System.Data;
18 using System.Data.Common;
19 using System.Diagnostics.CodeAnalysis;
20 using System.Globalization;
21 using System.IO;
22 using System.Net;
23 using System.Reflection;
24 using System.Resources;
25 using System.Runtime;
26 using System.Runtime.InteropServices;
27 using System.Runtime.Remoting.Messaging;
28 using System.Security;
29 using System.Security.Cryptography;
30 using System.Security.Permissions;
31 using System.Security.Policy;
32 using System.Security.Principal;
33 using System.Text;
34 using System.Threading;
35 using System.Web;
36 using System.Web.Caching;
37 using System.Web.Compilation;
38 using System.Web.Configuration;
39 using System.Web.Hosting;
40 using System.Web.Management;
41 using System.Web.Security;
42 using System.Web.UI;
43 using System.Web.Util;
44 using System.Xml;
45 using Microsoft.Win32;
47 /// <devdoc>
48 /// <para>Provides a set of ASP.NET runtime services.</para>
49 /// </devdoc>
50 public sealed class HttpRuntime {
52 internal const string codegenDirName = "Temporary ASP.NET Files";
53 internal const string profileFileName = "profileoptimization.prof";
55 private static HttpRuntime _theRuntime; // single instance of the class
56 internal static byte[] s_autogenKeys = new byte[1024];
59 // Names of special ASP.NET directories
62 internal const string BinDirectoryName = "bin";
63 internal const string CodeDirectoryName = "App_Code";
64 internal const string WebRefDirectoryName = "App_WebReferences";
65 internal const string ResourcesDirectoryName = "App_GlobalResources";
66 internal const string LocalResourcesDirectoryName = "App_LocalResources";
67 internal const string DataDirectoryName = "App_Data";
68 internal const string ThemesDirectoryName = "App_Themes";
69 internal const string GlobalThemesDirectoryName = "Themes";
70 internal const string BrowsersDirectoryName = "App_Browsers";
72 private static string DirectorySeparatorString = new string(Path.DirectorySeparatorChar, 1);
73 private static string DoubleDirectorySeparatorString = new string(Path.DirectorySeparatorChar, 2);
74 private static char[] s_InvalidPhysicalPathChars = { '/', '?', '*', '<', '>', '|', '"' };
78 #if OLD
79 // For s_forbiddenDirs and s_forbiddenDirsConstant, see
80 // ndll.h, and RestrictIISFolders in regiis.cxx
82 internal static string[] s_forbiddenDirs = {
83 BinDirectoryName,
84 CodeDirectoryName,
85 DataDirectoryName,
86 ResourcesDirectoryName,
87 WebRefDirectoryName,
90 internal static Int32[] s_forbiddenDirsConstant = {
91 UnsafeNativeMethods.RESTRICT_BIN,
92 UnsafeNativeMethods.RESTRICT_CODE,
93 UnsafeNativeMethods.RESTRICT_DATA,
94 UnsafeNativeMethods.RESTRICT_RESOURCES,
95 UnsafeNativeMethods.RESTRICT_WEBREFERENCES,
97 #endif
99 static HttpRuntime() {
100 AddAppDomainTraceMessage("*HttpRuntime::cctor");
102 StaticInit();
104 _theRuntime = new HttpRuntime();
106 _theRuntime.Init();
108 AddAppDomainTraceMessage("HttpRuntime::cctor*");
111 [SecurityPermission(SecurityAction.LinkDemand, Unrestricted = true)]
112 public HttpRuntime() {
116 // static initialization to get hooked up to the unmanaged code
117 // get installation directory, etc.
120 private static bool s_initialized = false;
121 private static String s_installDirectory;
122 private static bool s_isEngineLoaded = false;
124 // Force the static initialization of this class.
125 internal static void ForceStaticInit() { }
127 private static void StaticInit() {
128 if (s_initialized) {
129 // already initialized
130 return;
133 bool isEngineLoaded = false;
134 bool wasEngineLoadedHere = false;
135 String installDir = null;
137 // load webengine.dll if it is not loaded already
139 #if !FEATURE_PAL // FEATURE_PAL does not enable IIS-based hosting features
141 installDir = RuntimeEnvironment.GetRuntimeDirectory();
143 if (UnsafeNativeMethods.GetModuleHandle(ModName.ENGINE_FULL_NAME) != IntPtr.Zero) {
144 isEngineLoaded = true;
147 // Load webengine.dll if not loaded already
149 if (!isEngineLoaded) {
150 String fullPath = installDir + Path.DirectorySeparatorChar + ModName.ENGINE_FULL_NAME;
152 if (UnsafeNativeMethods.LoadLibrary(fullPath) != IntPtr.Zero) {
153 isEngineLoaded = true;
154 wasEngineLoadedHere = true;
158 if (isEngineLoaded) {
159 UnsafeNativeMethods.InitializeLibrary(false);
161 if (wasEngineLoadedHere) {
162 UnsafeNativeMethods.PerfCounterInitialize();
166 #else // !FEATURE_PAL
167 string p = typeof(object).Module.FullyQualifiedName;
168 installDir = Path.GetDirectoryName(p);
169 #endif // !FEATURE_PAL
171 s_installDirectory = installDir;
172 s_isEngineLoaded = isEngineLoaded;
173 s_initialized = true;
175 PopulateIISVersionInformation();
177 AddAppDomainTraceMessage("Initialize");
181 // Runtime services
184 private NamedPermissionSet _namedPermissionSet;
185 private PolicyLevel _policyLevel;
186 private string _hostSecurityPolicyResolverType = null;
187 private FileChangesMonitor _fcm;
188 private Cache _cachePublic;
189 private bool _isOnUNCShare;
190 private Profiler _profiler;
191 private RequestTimeoutManager _timeoutManager;
192 private RequestQueue _requestQueue;
193 private bool _apartmentThreading;
195 private bool _processRequestInApplicationTrust;
196 private bool _disableProcessRequestInApplicationTrust;
197 private bool _isLegacyCas;
199 // Counters
202 private bool _beforeFirstRequest = true;
203 private DateTime _firstRequestStartTime;
204 private bool _firstRequestCompleted;
205 private bool _userForcedShutdown;
206 private bool _configInited;
207 private bool _fusionInited;
208 private int _activeRequestCount;
209 private volatile bool _disposingHttpRuntime;
210 private DateTime _lastShutdownAttemptTime;
211 private bool _shutdownInProgress;
212 private String _shutDownStack;
213 private String _shutDownMessage;
214 private ApplicationShutdownReason _shutdownReason = ApplicationShutdownReason.None;
215 private string _trustLevel;
216 private string _wpUserId;
217 private bool _shutdownWebEventRaised;
220 // Header Newlines
222 private bool _enableHeaderChecking;
225 // Callbacks
228 private AsyncCallback _requestNotificationCompletionCallback;
229 private AsyncCallback _handlerCompletionCallback;
230 private HttpWorkerRequest.EndOfSendNotification _asyncEndOfSendCallback;
231 private WaitCallback _appDomainUnloadallback;
234 // Initialization error (to be reported on subsequent requests)
237 private Exception _initializationError;
238 private bool _hostingInitFailed; // make such errors non-sticky
239 private Timer _appDomainShutdownTimer = null;
243 // App domain related
246 private String _tempDir;
247 private String _codegenDir;
248 private String _appDomainAppId;
249 private String _appDomainAppPath;
250 private VirtualPath _appDomainAppVPath;
251 private String _appDomainId;
254 // Debugging support
257 private bool _debuggingEnabled = false;
260 // App_Offline.htm support
263 private const string AppOfflineFileName = "App_Offline.htm";
264 private const long MaxAppOfflineFileLength = 1024 * 1024;
265 private byte[] _appOfflineMessage;
268 // Client script support
271 private const string AspNetClientFilesSubDirectory = "asp.netclientfiles";
272 private const string AspNetClientFilesParentVirtualPath = "/aspnet_client/system_web/";
273 private string _clientScriptVirtualPath;
274 private string _clientScriptPhysicalPath;
277 // IIS version and whether we're using the integrated pipeline
279 private static Version _iisVersion;
280 private static bool _useIntegratedPipeline;
283 // Prefetch
285 private static bool _enablePrefetchOptimization;
287 /////////////////////////////////////////////////////////////////////////
288 // 3 steps of initialization:
289 // Init() is called from HttpRuntime cctor
290 // HostingInit() is called by the Hosting Environment
291 // FirstRequestInit() is called on first HTTP request
295 * Context-less initialization (on app domain creation)
297 private void Init() {
298 try {
299 #if !FEATURE_PAL
300 if (Environment.OSVersion.Platform != PlatformID.Win32NT)
301 throw new PlatformNotSupportedException(SR.GetString(SR.RequiresNT));
302 #else // !FEATURE_PAL
303 // ROTORTODO
304 // Do nothing: FEATURE_PAL environment will always support ASP.NET hosting
305 #endif // !FEATURE_PAL
307 _profiler = new Profiler();
308 _timeoutManager = new RequestTimeoutManager();
309 _wpUserId = GetCurrentUserName();
311 _requestNotificationCompletionCallback = new AsyncCallback(this.OnRequestNotificationCompletion);
312 _handlerCompletionCallback = new AsyncCallback(this.OnHandlerCompletion);
313 _asyncEndOfSendCallback = new HttpWorkerRequest.EndOfSendNotification(this.EndOfSendCallback);
314 _appDomainUnloadallback = new WaitCallback(this.ReleaseResourcesAndUnloadAppDomain);
317 // appdomain values
318 if (GetAppDomainString(".appDomain") != null) {
320 Debug.Assert(HostingEnvironment.IsHosted);
322 _appDomainAppId = GetAppDomainString(".appId");
323 _appDomainAppPath = GetAppDomainString(".appPath");
324 _appDomainAppVPath = VirtualPath.CreateNonRelativeTrailingSlash(GetAppDomainString(".appVPath"));
325 _appDomainId = GetAppDomainString(".domainId");
327 _isOnUNCShare = StringUtil.StringStartsWith(_appDomainAppPath, "\\\\");
329 // init perf counters for this appdomain
330 PerfCounters.Open(_appDomainAppId);
332 else {
333 Debug.Assert(!HostingEnvironment.IsHosted);
336 // _appDomainAppPath should be set before file change notifications are initialized
337 // DevDiv 248126: Check httpRuntime fcnMode first before we use the registry key
338 _fcm = new FileChangesMonitor(HostingEnvironment.FcnMode);
340 catch (Exception e) {
341 // remember static initalization error
342 InitializationException = e;
346 private void SetUpDataDirectory() {
348 // Set the DataDirectory (see VSWhidbey 226834) with permission (DevDiv 29614)
349 string dataDirectory = Path.Combine(_appDomainAppPath, DataDirectoryName);
350 AppDomain.CurrentDomain.SetData("DataDirectory", dataDirectory,
351 new FileIOPermission(FileIOPermissionAccess.PathDiscovery, dataDirectory));
354 private void DisposeAppDomainShutdownTimer() {
355 Timer timer = _appDomainShutdownTimer;
356 if (timer != null && Interlocked.CompareExchange(ref _appDomainShutdownTimer, null, timer) == timer) {
357 timer.Dispose();
361 private void AppDomainShutdownTimerCallback(Object state) {
362 try {
363 DisposeAppDomainShutdownTimer();
364 ShutdownAppDomain(ApplicationShutdownReason.InitializationError, "Initialization Error");
366 catch { } // ignore exceptions
370 * Restart the AppDomain in 10 seconds
372 private void StartAppDomainShutdownTimer() {
373 if (_appDomainShutdownTimer == null && !_shutdownInProgress) {
374 lock (this) {
375 if (_appDomainShutdownTimer == null && !_shutdownInProgress) {
376 _appDomainShutdownTimer = new Timer(
377 new TimerCallback(this.AppDomainShutdownTimerCallback),
378 null,
379 10 * 1000,
388 * Initialization from HostingEnvironment of HTTP independent features
390 private void HostingInit(HostingEnvironmentFlags hostingFlags, PolicyLevel policyLevel, Exception appDomainCreationException) {
391 using (new ApplicationImpersonationContext()) {
392 try {
393 // To ignore FCN during initialization
394 _firstRequestStartTime = DateTime.UtcNow;
396 SetUpDataDirectory();
398 // Throw an exception about lack of access to app directory early on
399 EnsureAccessToApplicationDirectory();
401 // Monitor renames to directories we are watching, and notifications on the bin directory
403 // Note that this must be the first monitoring that we do of the application directory.
404 // There is a bug in Windows 2000 Server where notifications on UNC shares do not
405 // happen correctly if:
406 // 1. the directory is monitored for regular notifications
407 // 2. the directory is then monitored for directory renames
408 // 3. the directory is monitored again for regular notifications
409 StartMonitoringDirectoryRenamesAndBinDirectory();
411 // Initialize ObjectCacheHost before config is read, since config relies on the cache
412 if (InitializationException == null) {
413 HostingEnvironment.InitializeObjectCacheHost();
417 // Get the configuration needed to minimally initialize
418 // the components required for a complete configuration system,
419 // especially SetTrustLevel.
421 // We want to do this before calling SetUpCodegenDirectory(),
422 // to remove the risk of the config system loading
423 // codegen assemblies in full trust (VSWhidbey 460506)
425 CacheSection cacheSection;
426 TrustSection trustSection;
427 SecurityPolicySection securityPolicySection;
428 CompilationSection compilationSection;
429 HostingEnvironmentSection hostingEnvironmentSection;
430 Exception configInitException;
432 GetInitConfigSections(
433 out cacheSection,
434 out trustSection,
435 out securityPolicySection,
436 out compilationSection,
437 out hostingEnvironmentSection,
438 out configInitException);
440 // Once the configuration system is initialized, we can read
441 // the cache configuration settings.
443 // Note that we must do this after we start monitoring directory renames,
444 // as reading config will cause file monitoring on the application directory
445 // to occur.
447 // Set up the codegen directory for the app. This needs to be done before we process
448 // the policy file, because it needs to replace the $CodeGen$ token.
449 SetUpCodegenDirectory(compilationSection);
451 if(compilationSection != null) {
452 _enablePrefetchOptimization = compilationSection.EnablePrefetchOptimization;
453 if(_enablePrefetchOptimization) {
454 UnsafeNativeMethods.StartPrefetchActivity((uint)StringUtil.GetStringHashCode(_appDomainAppId));
458 // NOTE: after calling SetUpCodegenDirectory(), and until we call SetTrustLevel(), we are at
459 // risk of codegen assemblies being loaded in full trust. No code that might cause
460 // assembly loading should be added here! This is only valid if the legacyCasModel is set
461 // to true in <trust> section.
463 // Throw the original configuration exception from ApplicationManager if configuration is broken.
464 if (appDomainCreationException != null) {
465 throw appDomainCreationException;
468 if (trustSection == null || String.IsNullOrEmpty(trustSection.Level)) {
469 throw new ConfigurationErrorsException(SR.GetString(SR.Config_section_not_present, "trust"));
472 if (trustSection.LegacyCasModel) {
473 try {
474 _disableProcessRequestInApplicationTrust = false;
475 _isLegacyCas = true;
476 // Set code access policy on the app domain
477 SetTrustLevel(trustSection, securityPolicySection);
479 catch {
480 // throw the original config exception if it exists
481 if (configInitException != null)
482 throw configInitException;
483 throw;
486 else if ((hostingFlags & HostingEnvironmentFlags.ClientBuildManager) != 0) {
487 _trustLevel = "Full";
489 else {
490 _disableProcessRequestInApplicationTrust = true;
491 // Set code access policy properties of the runtime object
492 SetTrustParameters(trustSection, securityPolicySection, policyLevel);
495 // Configure fusion to use directories set in the app config
496 InitFusion(hostingEnvironmentSection);
498 // set the sliding expiration for URL metadata
499 CachedPathData.InitializeUrlMetadataSlidingExpiration(hostingEnvironmentSection);
501 // Complete initialization of configuration.
502 // Note that this needs to be called after SetTrustLevel,
503 // as it indicates that we have the permission set needed
504 // to correctly run configuration section handlers.
505 // As little config should be read before CompleteInit() as possible.
506 // No section that runs before CompleteInit() should demand permissions,
507 // as the permissions set has not yet determined until SetTrustLevel()
508 // is called.
509 HttpConfigurationSystem.CompleteInit();
512 // If an exception occurred loading configuration,
513 // we are now ready to handle exception processing
514 // with the correct trust level set.
516 if (configInitException != null) {
517 throw configInitException;
520 SetThreadPoolLimits();
522 SetAutogenKeys();
524 // Initialize the build manager
525 BuildManager.InitializeBuildManager();
527 if(compilationSection != null && compilationSection.ProfileGuidedOptimizations == ProfileGuidedOptimizationsFlags.All) {
528 ProfileOptimization.SetProfileRoot(_codegenDir);
529 ProfileOptimization.StartProfile(profileFileName);
532 // Determine apartment threading setting
533 InitApartmentThreading();
535 // Init debugging
536 InitDebuggingSupport();
538 _processRequestInApplicationTrust = trustSection.ProcessRequestInApplicationTrust;
540 // Init AppDomain Resource Perf Counters
541 AppDomainResourcePerfCounters.Init();
544 RelaxMapPathIfRequired();
546 catch (Exception e) {
547 _hostingInitFailed = true;
548 InitializationException = e;
550 Debug.Trace("AppDomainFactory", "HostingInit failed. " + e.ToString());
552 if ((hostingFlags & HostingEnvironmentFlags.ThrowHostingInitErrors) != 0)
553 throw;
558 internal static Exception InitializationException {
559 get {
560 return _theRuntime._initializationError;
563 // The exception is "cached" for 10 seconds, then the AppDomain is restarted.
564 set {
565 _theRuntime._initializationError = value;
566 // In v2.0, we shutdown immediately if hostingInitFailed...so we don't need the timer
567 if (!HostingInitFailed) {
568 _theRuntime.StartAppDomainShutdownTimer();
573 internal static bool HostingInitFailed {
574 get {
575 return _theRuntime._hostingInitFailed;
579 internal static void InitializeHostingFeatures(HostingEnvironmentFlags hostingFlags, PolicyLevel policyLevel, Exception appDomainCreationException) {
580 _theRuntime.HostingInit(hostingFlags, policyLevel, appDomainCreationException);
583 internal static bool EnableHeaderChecking {
584 get {
585 return _theRuntime._enableHeaderChecking;
589 internal static bool ProcessRequestInApplicationTrust {
590 get {
591 return _theRuntime._processRequestInApplicationTrust;
595 internal static bool DisableProcessRequestInApplicationTrust {
596 get {
597 return _theRuntime._disableProcessRequestInApplicationTrust;
601 internal static bool IsLegacyCas {
602 get {
603 return _theRuntime._isLegacyCas;
607 internal static byte[] AppOfflineMessage {
608 get {
609 return _theRuntime._appOfflineMessage;
614 * Initialization on first request (context available)
616 private void FirstRequestInit(HttpContext context) {
617 Exception error = null;
619 if (InitializationException == null && _appDomainId != null) {
620 #if DBG
621 HttpContext.SetDebugAssertOnAccessToCurrent(true);
622 #endif
623 try {
624 using (new ApplicationImpersonationContext()) {
625 // Is this necessary? See InitHttpConfiguration
626 CultureInfo savedCulture = Thread.CurrentThread.CurrentCulture;
627 CultureInfo savedUICulture = Thread.CurrentThread.CurrentUICulture;
629 try {
630 // Ensure config system is initialized
631 InitHttpConfiguration(); // be sure config system is set
633 // Check if applicaton is enabled
634 CheckApplicationEnabled();
636 // Check access to temp compilation directory (under hosting identity)
637 CheckAccessToTempDirectory();
639 // Initialize health monitoring
640 InitializeHealthMonitoring();
642 // Init request queue (after reading config)
643 InitRequestQueue();
645 // configure the profiler according to config
646 InitTrace(context);
648 // Start heatbeat for Web Event Health Monitoring
649 HealthMonitoringManager.StartHealthMonitoringHeartbeat();
651 // Remove read and browse access of the bin directory
652 RestrictIISFolders(context);
654 // Preload all assemblies from bin (only if required). ASURT 114486
655 PreloadAssembliesFromBin();
657 // Decide whether or not to encode headers. VsWhidbey 257154
658 InitHeaderEncoding();
660 // Force the current encoder + validator to load so that there's a deterministic
661 // place (here) for an exception to occur if there's a load error
662 HttpEncoder.InitializeOnFirstRequest();
663 RequestValidator.InitializeOnFirstRequest();
665 if (context.WorkerRequest is ISAPIWorkerRequestOutOfProc) {
666 // Make sure that the <processModel> section has no errors
667 ProcessModelSection processModel = RuntimeConfig.GetMachineConfig().ProcessModel;
670 finally {
671 Thread.CurrentThread.CurrentUICulture = savedUICulture;
672 SetCurrentThreadCultureWithAssert(savedCulture);
676 catch (ConfigurationException e) {
677 error = e;
679 catch (Exception e) {
680 // remember second-phase initialization error
681 error = new HttpException(SR.GetString(SR.XSP_init_error, e.Message), e);
683 finally {
684 #if DBG
685 HttpContext.SetDebugAssertOnAccessToCurrent(false);
686 #endif
690 if (InitializationException != null) {
691 // throw cached exception. We need to wrap it in a new exception, otherwise
692 // we lose the original stack.
693 throw new HttpException(InitializationException.Message, InitializationException);
695 else if (error != null) {
696 InitializationException = error;
697 // throw new exception
698 throw error;
701 AddAppDomainTraceMessage("FirstRequestInit");
704 [SecurityPermission(SecurityAction.Assert, ControlThread = true)]
705 internal static void SetCurrentThreadCultureWithAssert(CultureInfo cultureInfo) {
706 Thread.CurrentThread.CurrentCulture = cultureInfo;
709 private void EnsureFirstRequestInit(HttpContext context) {
710 if (_beforeFirstRequest) {
711 lock (this) {
712 if (_beforeFirstRequest) {
713 _firstRequestStartTime = DateTime.UtcNow;
714 FirstRequestInit(context);
715 _beforeFirstRequest = false;
716 context.FirstRequest = true;
722 private void EnsureAccessToApplicationDirectory() {
723 if (!FileUtil.DirectoryAccessible(_appDomainAppPath)) {
725 if (_appDomainAppPath.IndexOf('?') >= 0) {
726 // Possible Unicode when not supported
727 throw new HttpException(SR.GetString(SR.Access_denied_to_unicode_app_dir, _appDomainAppPath));
729 else {
730 throw new HttpException(SR.GetString(SR.Access_denied_to_app_dir, _appDomainAppPath));
735 private void StartMonitoringDirectoryRenamesAndBinDirectory() {
736 _fcm.StartMonitoringDirectoryRenamesAndBinDirectory(AppDomainAppPathInternal, new FileChangeEventHandler(this.OnCriticalDirectoryChange));
740 // Monitor a local resources subdirectory and unload appdomain when it changes
742 internal static void StartListeningToLocalResourcesDirectory(VirtualPath virtualDir) {
743 #if !FEATURE_PAL // FEATURE_PAL does not enable file change notification
744 _theRuntime._fcm.StartListeningToLocalResourcesDirectory(virtualDir);
745 #endif // !FEATURE_PAL
749 // Get the configuration needed to minimally initialize
750 // the components required for a complete configuration system,
752 // Note that if the application configuration file has an error,
753 // AppLKGConfig will still retreive any valid configuration from
754 // that file, or from location directives that apply to the
755 // application path. This implies that an administrator can
756 // lock down an application's trust level in root web.config,
757 // and it will still take effect if the application's web.config
758 // has errors.
760 private void GetInitConfigSections(
761 out CacheSection cacheSection,
762 out TrustSection trustSection,
763 out SecurityPolicySection securityPolicySection,
764 out CompilationSection compilationSection,
765 out HostingEnvironmentSection hostingEnvironmentSection,
766 out Exception initException) {
768 cacheSection = null;
769 trustSection = null;
770 securityPolicySection = null;
771 compilationSection = null;
772 hostingEnvironmentSection = null;
773 initException = null;
775 // AppLKGConfig is guaranteed to not throw an exception.
776 RuntimeConfig appLKGConfig = RuntimeConfig.GetAppLKGConfig();
778 // AppConfig may throw an exception.
779 RuntimeConfig appConfig = null;
780 try {
781 appConfig = RuntimeConfig.GetAppConfig();
783 catch (Exception e) {
784 initException = e;
787 // Cache section
788 if (appConfig != null) {
789 try {
790 cacheSection = appConfig.Cache;
792 catch (Exception e) {
793 if (initException == null) {
794 initException = e;
799 if (cacheSection == null) {
800 cacheSection = appLKGConfig.Cache;
803 // Trust section
804 if (appConfig != null) {
805 try {
806 trustSection = appConfig.Trust;
808 catch (Exception e) {
809 if (initException == null) {
810 initException = e;
815 if (trustSection == null) {
816 trustSection = appLKGConfig.Trust;
819 // SecurityPolicy section
820 if (appConfig != null) {
821 try {
822 securityPolicySection = appConfig.SecurityPolicy;
824 catch (Exception e) {
825 if (initException == null) {
826 initException = e;
831 if (securityPolicySection == null) {
832 securityPolicySection = appLKGConfig.SecurityPolicy;
835 // Compilation section
836 if (appConfig != null) {
837 try {
838 compilationSection = appConfig.Compilation;
840 catch (Exception e) {
841 if (initException == null) {
842 initException = e;
847 if (compilationSection == null) {
848 compilationSection = appLKGConfig.Compilation;
851 // HostingEnvironment section
852 if (appConfig != null) {
853 try {
854 hostingEnvironmentSection = appConfig.HostingEnvironment;
856 catch (Exception e) {
857 if (initException == null) {
858 initException = e;
863 if (hostingEnvironmentSection == null) {
864 hostingEnvironmentSection = appLKGConfig.HostingEnvironment;
868 // Set up the codegen directory for the app
869 [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification = "This call site is trusted.")]
870 private void SetUpCodegenDirectory(CompilationSection compilationSection) {
871 AppDomain appDomain = Thread.GetDomain();
873 string codegenBase;
875 // devdiv 1038337. Passing the corresponding IsDevelopmentEnvironment flag to ConstructSimpleAppName
876 string simpleAppName = System.Web.Hosting.AppManagerAppDomainFactory.ConstructSimpleAppName(
877 AppDomainAppVirtualPath, HostingEnvironment.IsDevelopmentEnvironment);
879 string tempDirectory = null;
881 // These variables are used for error handling
882 string tempDirAttribName = null;
883 string configFileName = null;
884 int configLineNumber = 0;
886 if (compilationSection != null && !String.IsNullOrEmpty(compilationSection.TempDirectory)) {
887 tempDirectory = compilationSection.TempDirectory;
889 compilationSection.GetTempDirectoryErrorInfo(out tempDirAttribName,
890 out configFileName, out configLineNumber);
893 if (tempDirectory != null) {
894 tempDirectory = tempDirectory.Trim();
896 if (!Path.IsPathRooted(tempDirectory)) {
897 // Make sure the path is not relative (VSWhidbey 260075)
898 tempDirectory = null;
900 else {
901 try {
902 // Canonicalize it to avoid problems with spaces (VSWhidbey 229873)
903 tempDirectory = new DirectoryInfo(tempDirectory).FullName;
905 catch {
906 tempDirectory = null;
910 if (tempDirectory == null) {
911 throw new ConfigurationErrorsException(
912 SR.GetString(SR.Invalid_temp_directory, tempDirAttribName),
913 configFileName, configLineNumber);
915 #if FEATURE_PAL
916 } else {
917 System.UInt32 length = 0;
918 StringBuilder sb = null;
919 bool bRet;
921 // Get the required length
922 bRet = UnsafeNativeMethods.GetUserTempDirectory(
923 UnsafeNativeMethods.DeploymentDirectoryType.ddtInstallationDependentDirectory,
924 null, ref length);
926 if (true == bRet) {
927 // now, allocate the string
928 sb = new StringBuilder ((int)length);
930 // call again to get the value
931 bRet = UnsafeNativeMethods.GetUserTempDirectory(
932 UnsafeNativeMethods.DeploymentDirectoryType.ddtInstallationDependentDirectory,
933 sb, ref length);
936 if (false == bRet) {
937 throw new ConfigurationException(
938 HttpRuntime.FormatResourceString(SR.Invalid_temp_directory, tempDirAttribName));
941 tempDirectory = Path.Combine(sb.ToString(), codegenDirName);
944 // Always try to create the ASP.Net temp directory for FEATURE_PAL
945 #endif // FEATURE_PAL
947 // Create the config-specified directory if needed
948 try {
949 Directory.CreateDirectory(tempDirectory);
951 catch (Exception e) {
952 throw new ConfigurationErrorsException(
953 SR.GetString(SR.Invalid_temp_directory, tempDirAttribName),
955 configFileName, configLineNumber);
957 #if !FEATURE_PAL
959 else {
960 tempDirectory = Path.Combine(s_installDirectory, codegenDirName);
962 #endif // !FEATURE_PAL
964 // If we don't have write access to the codegen dir, use the TEMP dir instead.
965 // This will allow non-admin users to work in hosting scenarios (e.g. Venus, aspnet_compiler)
966 if (!System.Web.UI.Util.HasWriteAccessToDirectory(tempDirectory)) {
968 // Don't do this if we are not in a CBM scenario and we're in a service (!UserInteractive),
969 // as TEMP could point to unwanted places.
971 #if !FEATURE_PAL // always fail here
972 if ((!BuildManagerHost.InClientBuildManager) && (!Environment.UserInteractive))
973 #endif // !FEATURE_PAL
975 throw new HttpException(SR.GetString(SR.No_codegen_access,
976 System.Web.UI.Util.GetCurrentAccountName(), tempDirectory));
979 tempDirectory = Path.GetTempPath();
980 Debug.Assert(System.Web.UI.Util.HasWriteAccessToDirectory(tempDirectory));
981 tempDirectory = Path.Combine(tempDirectory, codegenDirName);
984 _tempDir = tempDirectory;
986 codegenBase = Path.Combine(tempDirectory, simpleAppName);
988 #pragma warning disable 0618 // To avoid deprecation warning
989 appDomain.SetDynamicBase(codegenBase);
990 #pragma warning restore 0618
992 _codegenDir = Thread.GetDomain().DynamicDirectory;
994 // Create the codegen directory if needed
995 Directory.CreateDirectory(_codegenDir);
998 private void InitFusion(HostingEnvironmentSection hostingEnvironmentSection) {
1000 AppDomain appDomain = Thread.GetDomain();
1002 // If there is a double backslash in the string, get rid of it (ASURT 122191)
1003 // Make sure to skip the first char, to avoid breaking the UNC case
1004 string appDomainAppPath = _appDomainAppPath;
1005 if (appDomainAppPath.IndexOf(DoubleDirectorySeparatorString, 1, StringComparison.Ordinal) >= 1) {
1006 appDomainAppPath = appDomainAppPath[0] + appDomainAppPath.Substring(1).Replace(DoubleDirectorySeparatorString,
1007 DirectorySeparatorString);
1010 #pragma warning disable 0618 // To avoid deprecation warning
1011 // Allow assemblies from 'bin' to be loaded
1012 appDomain.AppendPrivatePath(appDomainAppPath + BinDirectoryName);
1013 #pragma warning restore 0618
1015 // If shadow copying was disabled via config, turn it off (DevDiv 30864)
1016 if (hostingEnvironmentSection != null && !hostingEnvironmentSection.ShadowCopyBinAssemblies) {
1017 #pragma warning disable 0618 // To avoid deprecation warning
1018 appDomain.ClearShadowCopyPath();
1019 #pragma warning restore 0618
1021 else {
1022 // enable shadow-copying from bin
1023 #pragma warning disable 0618 // To avoid deprecation warning
1024 appDomain.SetShadowCopyPath(appDomainAppPath + BinDirectoryName);
1025 #pragma warning restore 0618
1028 // Get rid of the last part of the directory (the app name), since it will
1029 // be re-appended.
1030 string parentDir = Directory.GetParent(_codegenDir).FullName;
1031 #pragma warning disable 0618 // To avoid deprecation warning
1032 appDomain.SetCachePath(parentDir);
1033 #pragma warning restore 0618
1035 _fusionInited = true;
1038 private void InitRequestQueue() {
1039 RuntimeConfig config = RuntimeConfig.GetAppConfig();
1040 HttpRuntimeSection runtimeConfig = config.HttpRuntime;
1041 ProcessModelSection processConfig = config.ProcessModel;
1043 if (processConfig.AutoConfig) {
1044 _requestQueue = new RequestQueue(
1045 88 * processConfig.CpuCount,
1046 76 * processConfig.CpuCount,
1047 runtimeConfig.AppRequestQueueLimit,
1048 processConfig.ClientConnectedCheck);
1050 else {
1052 // Configuration section handlers cannot validate values based on values
1053 // in other configuration sections, so we validate minFreeThreads and
1054 // minLocalRequestFreeThreads here.
1055 int maxThreads = (processConfig.MaxWorkerThreadsTimesCpuCount < processConfig.MaxIoThreadsTimesCpuCount) ? processConfig.MaxWorkerThreadsTimesCpuCount : processConfig.MaxIoThreadsTimesCpuCount;
1056 // validate minFreeThreads
1057 if (runtimeConfig.MinFreeThreads >= maxThreads) {
1058 if (runtimeConfig.ElementInformation.Properties["minFreeThreads"].LineNumber == 0) {
1059 if (processConfig.ElementInformation.Properties["maxWorkerThreads"].LineNumber != 0) {
1060 throw new ConfigurationErrorsException(SR.GetString(SR.Thread_pool_limit_must_be_greater_than_minFreeThreads, runtimeConfig.MinFreeThreads.ToString(CultureInfo.InvariantCulture)),
1061 processConfig.ElementInformation.Properties["maxWorkerThreads"].Source,
1062 processConfig.ElementInformation.Properties["maxWorkerThreads"].LineNumber);
1064 else {
1065 throw new ConfigurationErrorsException(SR.GetString(SR.Thread_pool_limit_must_be_greater_than_minFreeThreads, runtimeConfig.MinFreeThreads.ToString(CultureInfo.InvariantCulture)),
1066 processConfig.ElementInformation.Properties["maxIoThreads"].Source,
1067 processConfig.ElementInformation.Properties["maxIoThreads"].LineNumber);
1070 else {
1071 throw new ConfigurationErrorsException(SR.GetString(SR.Min_free_threads_must_be_under_thread_pool_limits, maxThreads.ToString(CultureInfo.InvariantCulture)),
1072 runtimeConfig.ElementInformation.Properties["minFreeThreads"].Source,
1073 runtimeConfig.ElementInformation.Properties["minFreeThreads"].LineNumber);
1076 // validate minLocalRequestFreeThreads
1077 if (runtimeConfig.MinLocalRequestFreeThreads > runtimeConfig.MinFreeThreads) {
1078 if (runtimeConfig.ElementInformation.Properties["minLocalRequestFreeThreads"].LineNumber == 0) {
1079 throw new ConfigurationErrorsException(SR.GetString(SR.Local_free_threads_cannot_exceed_free_threads),
1080 processConfig.ElementInformation.Properties["minFreeThreads"].Source,
1081 processConfig.ElementInformation.Properties["minFreeThreads"].LineNumber);
1083 else {
1084 throw new ConfigurationErrorsException(SR.GetString(SR.Local_free_threads_cannot_exceed_free_threads),
1085 runtimeConfig.ElementInformation.Properties["minLocalRequestFreeThreads"].Source,
1086 runtimeConfig.ElementInformation.Properties["minLocalRequestFreeThreads"].LineNumber);
1090 _requestQueue = new RequestQueue(
1091 runtimeConfig.MinFreeThreads,
1092 runtimeConfig.MinLocalRequestFreeThreads,
1093 runtimeConfig.AppRequestQueueLimit,
1094 processConfig.ClientConnectedCheck);
1098 private void InitApartmentThreading() {
1099 HttpRuntimeSection runtimeConfig = RuntimeConfig.GetAppConfig().HttpRuntime;
1101 if (runtimeConfig != null) {
1102 _apartmentThreading = runtimeConfig.ApartmentThreading;
1104 else {
1105 _apartmentThreading = false;
1109 private void InitTrace(HttpContext context) {
1110 TraceSection traceConfig = RuntimeConfig.GetAppConfig().Trace;
1112 Profile.RequestsToProfile = traceConfig.RequestLimit;
1113 Profile.PageOutput = traceConfig.PageOutput;
1114 Profile.OutputMode = TraceMode.SortByTime;
1115 if (traceConfig.TraceMode == TraceDisplayMode.SortByCategory)
1116 Profile.OutputMode = TraceMode.SortByCategory;
1118 Profile.LocalOnly = traceConfig.LocalOnly;
1119 Profile.IsEnabled = traceConfig.Enabled;
1120 Profile.MostRecent = traceConfig.MostRecent;
1121 Profile.Reset();
1123 // the first request's context is created before InitTrace, so
1124 // we need to set this manually. (ASURT 93730)
1125 context.TraceIsEnabled = traceConfig.Enabled;
1126 TraceContext.SetWriteToDiagnosticsTrace(traceConfig.WriteToDiagnosticsTrace);
1129 private void InitDebuggingSupport() {
1130 CompilationSection compConfig = RuntimeConfig.GetAppConfig().Compilation;
1131 _debuggingEnabled = compConfig.Debug;
1135 * Pre-load all the bin assemblies if we're impersonated. This way, if user code
1136 * calls Assembly.Load while impersonated, the assembly will already be loaded, and
1137 * we won't fail due to lack of permissions on the codegen dir (see ASURT 114486)
1139 [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
1140 private void PreloadAssembliesFromBin() {
1141 bool appClientImpersonationEnabled = false;
1143 if (!_isOnUNCShare) {
1144 // if not on UNC share check if config has impersonation enabled (without userName)
1145 IdentitySection c = RuntimeConfig.GetAppConfig().Identity;
1146 if (c.Impersonate && c.ImpersonateToken == IntPtr.Zero)
1147 appClientImpersonationEnabled = true;
1150 if (!appClientImpersonationEnabled)
1151 return;
1153 // Get the path to the bin directory
1154 string binPath = HttpRuntime.BinDirectoryInternal;
1156 DirectoryInfo binPathDirectory = new DirectoryInfo(binPath);
1158 if (!binPathDirectory.Exists)
1159 return;
1161 PreloadAssembliesFromBinRecursive(binPathDirectory);
1164 private void PreloadAssembliesFromBinRecursive(DirectoryInfo dirInfo) {
1166 FileInfo[] binDlls = dirInfo.GetFiles("*.dll");
1168 // Pre-load all the assemblies, ignoring all exceptions
1169 foreach (FileInfo fi in binDlls) {
1170 try { Assembly.Load(System.Web.UI.Util.GetAssemblyNameFromFileName(fi.Name)); }
1171 catch (FileNotFoundException) {
1172 // If Load failed, try LoadFrom (VSWhidbey 493725)
1173 try { Assembly.LoadFrom(fi.FullName); }
1174 catch { }
1176 catch { }
1179 // Recurse on the subdirectories
1180 DirectoryInfo[] subDirs = dirInfo.GetDirectories();
1181 foreach (DirectoryInfo di in subDirs) {
1182 PreloadAssembliesFromBinRecursive(di);
1186 private void SetAutoConfigLimits(ProcessModelSection pmConfig) {
1187 // check if the current limits are ok
1188 int workerMax, ioMax;
1189 ThreadPool.GetMaxThreads(out workerMax, out ioMax);
1191 // only set if different
1192 if (pmConfig.DefaultMaxWorkerThreadsForAutoConfig != workerMax || pmConfig.DefaultMaxIoThreadsForAutoConfig != ioMax) {
1193 Debug.Trace("ThreadPool", "SetThreadLimit: from " + workerMax + "," + ioMax + " to " + pmConfig.DefaultMaxWorkerThreadsForAutoConfig + "," + pmConfig.DefaultMaxIoThreadsForAutoConfig);
1194 UnsafeNativeMethods.SetClrThreadPoolLimits(pmConfig.DefaultMaxWorkerThreadsForAutoConfig, pmConfig.DefaultMaxIoThreadsForAutoConfig, true);
1197 // this is the code equivalent of setting maxconnection
1198 // Dev11 141729: Make autoConfig scale by default
1199 // Dev11 144842: PERF: Consider removing Max connection limit or changing the default value
1200 System.Net.ServicePointManager.DefaultConnectionLimit = Int32.MaxValue;
1202 // we call InitRequestQueue later, from FirstRequestInit, and set minFreeThreads and minLocalRequestFreeThreads
1205 private void SetThreadPoolLimits() {
1206 try {
1207 ProcessModelSection pmConfig = RuntimeConfig.GetMachineConfig().ProcessModel;
1209 if (pmConfig.AutoConfig) {
1210 // use recommendation in http://support.microsoft.com/?id=821268
1211 SetAutoConfigLimits(pmConfig);
1213 else if (pmConfig.MaxWorkerThreadsTimesCpuCount > 0 && pmConfig.MaxIoThreadsTimesCpuCount > 0) {
1214 // check if the current limits are ok
1215 int workerMax, ioMax;
1216 ThreadPool.GetMaxThreads(out workerMax, out ioMax);
1218 // only set if different
1219 if (pmConfig.MaxWorkerThreadsTimesCpuCount != workerMax || pmConfig.MaxIoThreadsTimesCpuCount != ioMax) {
1220 Debug.Trace("ThreadPool", "SetThreadLimit: from " + workerMax + "," + ioMax + " to " + pmConfig.MaxWorkerThreadsTimesCpuCount + "," + pmConfig.MaxIoThreadsTimesCpuCount);
1221 UnsafeNativeMethods.SetClrThreadPoolLimits(pmConfig.MaxWorkerThreadsTimesCpuCount, pmConfig.MaxIoThreadsTimesCpuCount, false);
1225 if (pmConfig.MinWorkerThreadsTimesCpuCount > 0 || pmConfig.MinIoThreadsTimesCpuCount > 0) {
1226 int currentMinWorkerThreads, currentMinIoThreads;
1227 ThreadPool.GetMinThreads(out currentMinWorkerThreads, out currentMinIoThreads);
1229 int newMinWorkerThreads = pmConfig.MinWorkerThreadsTimesCpuCount > 0 ? pmConfig.MinWorkerThreadsTimesCpuCount : currentMinWorkerThreads;
1230 int newMinIoThreads = pmConfig.MinIoThreadsTimesCpuCount > 0 ? pmConfig.MinIoThreadsTimesCpuCount : currentMinIoThreads;
1232 if (newMinWorkerThreads > 0 && newMinIoThreads > 0
1233 && (newMinWorkerThreads != currentMinWorkerThreads || newMinIoThreads != currentMinIoThreads))
1234 ThreadPool.SetMinThreads(newMinWorkerThreads, newMinIoThreads);
1237 catch {
1241 internal static void CheckApplicationEnabled() {
1242 // process App_Offline.htm file
1243 string appOfflineFile = Path.Combine(_theRuntime._appDomainAppPath, AppOfflineFileName);
1244 bool appOfflineFileFound = false;
1246 // monitor even if doesn't exist
1247 _theRuntime._fcm.StartMonitoringFile(appOfflineFile, new FileChangeEventHandler(_theRuntime.OnAppOfflineFileChange));
1249 // read the file into memory
1250 try {
1251 if (File.Exists(appOfflineFile)) {
1252 Debug.Trace("AppOffline", "File " + appOfflineFile + " exists. Using it.");
1254 using (FileStream fs = new FileStream(appOfflineFile, FileMode.Open, FileAccess.Read, FileShare.Read)) {
1255 if (fs.Length <= MaxAppOfflineFileLength) {
1256 int length = (int)fs.Length;
1258 if (length > 0) {
1259 byte[] message = new byte[length];
1261 if (fs.Read(message, 0, length) == length) {
1262 // remember the message
1263 _theRuntime._appOfflineMessage = message;
1264 appOfflineFileFound = true;
1267 else {
1268 // empty file
1269 appOfflineFileFound = true;
1270 _theRuntime._appOfflineMessage = new byte[0];
1276 catch {
1277 // ignore any IO errors reading the file
1280 // throw if there is a valid App_Offline file
1281 if (appOfflineFileFound) {
1282 throw new HttpException(503, String.Empty);
1285 // process the config setting
1286 HttpRuntimeSection runtimeConfig = RuntimeConfig.GetAppConfig().HttpRuntime;
1287 if (!runtimeConfig.Enable) {
1288 // throw 404 on first request init -- this will get cached until config changes
1289 throw new HttpException(404, String.Empty);
1293 [FileIOPermission(SecurityAction.Assert, Unrestricted = true)]
1294 private void CheckAccessToTempDirectory() {
1295 // The original check (in HostingInit) was done under process identity
1296 // this time we do it under hosting identity
1297 if (HostingEnvironment.HasHostingIdentity) {
1298 using (new ApplicationImpersonationContext()) {
1299 if (!System.Web.UI.Util.HasWriteAccessToDirectory(_tempDir)) {
1300 throw new HttpException(SR.GetString(SR.No_codegen_access,
1301 System.Web.UI.Util.GetCurrentAccountName(), _tempDir));
1307 private void InitializeHealthMonitoring() {
1308 #if !FEATURE_PAL // FEATURE_PAL does not enable IIS-based hosting features
1309 ProcessModelSection pmConfig = RuntimeConfig.GetMachineConfig().ProcessModel;
1310 int deadLockInterval = (int)pmConfig.ResponseDeadlockInterval.TotalSeconds;
1311 int requestQueueLimit = pmConfig.RequestQueueLimit;
1312 Debug.Trace("HealthMonitor", "Initalizing: ResponseDeadlockInterval=" + deadLockInterval);
1313 UnsafeNativeMethods.InitializeHealthMonitor(deadLockInterval, requestQueueLimit);
1314 #endif // !FEATURE_PAL
1317 private static void InitHttpConfiguration() {
1318 if (!_theRuntime._configInited) {
1319 _theRuntime._configInited = true;
1321 HttpConfigurationSystem.EnsureInit(null, true, true);
1323 // whenever possible report errors in the user's culture (from machine.config)
1324 // Note: this thread's culture is saved/restored during FirstRequestInit, so this is safe
1325 // see ASURT 81655
1327 GlobalizationSection globConfig = RuntimeConfig.GetAppLKGConfig().Globalization;
1328 if (globConfig != null) {
1329 if (!String.IsNullOrEmpty(globConfig.Culture) &&
1330 !StringUtil.StringStartsWithIgnoreCase(globConfig.Culture, "auto"))
1331 SetCurrentThreadCultureWithAssert(HttpServerUtility.CreateReadOnlyCultureInfo(globConfig.Culture));
1333 if (!String.IsNullOrEmpty(globConfig.UICulture) &&
1334 !StringUtil.StringStartsWithIgnoreCase(globConfig.UICulture, "auto"))
1335 Thread.CurrentThread.CurrentUICulture = HttpServerUtility.CreateReadOnlyCultureInfo(globConfig.UICulture);
1338 // check for errors in <processModel> section
1339 RuntimeConfig appConfig = RuntimeConfig.GetAppConfig();
1340 object section = appConfig.ProcessModel;
1341 // check for errors in <hostingEnvironment> section
1342 section = appConfig.HostingEnvironment;
1346 private void InitHeaderEncoding() {
1347 HttpRuntimeSection runtimeConfig = RuntimeConfig.GetAppConfig().HttpRuntime;
1348 _enableHeaderChecking = runtimeConfig.EnableHeaderChecking;
1351 private static void SetAutogenKeys() {
1352 #if !FEATURE_PAL // FEATURE_PAL does not enable cryptography
1353 byte[] bKeysRandom = new byte[s_autogenKeys.Length];
1354 byte[] bKeysStored = new byte[s_autogenKeys.Length];
1355 bool fGetStoredKeys = false;
1356 RNGCryptoServiceProvider randgen = new RNGCryptoServiceProvider();
1358 // Gernerate random keys
1359 randgen.GetBytes(bKeysRandom);
1361 // If getting stored keys via WorkerRequest object failed, get it directly
1362 if (!fGetStoredKeys)
1363 fGetStoredKeys = (UnsafeNativeMethods.EcbCallISAPI(IntPtr.Zero, UnsafeNativeMethods.CallISAPIFunc.GetAutogenKeys,
1364 bKeysRandom, bKeysRandom.Length, bKeysStored, bKeysStored.Length) == 1);
1366 // If we managed to get stored keys, copy them in; else use random keys
1367 if (fGetStoredKeys)
1368 Buffer.BlockCopy(bKeysStored, 0, s_autogenKeys, 0, s_autogenKeys.Length);
1369 else
1370 Buffer.BlockCopy(bKeysRandom, 0, s_autogenKeys, 0, s_autogenKeys.Length);
1371 #endif // !FEATURE_PAL
1374 internal static void IncrementActivePipelineCount() {
1375 Interlocked.Increment(ref _theRuntime._activeRequestCount);
1376 HostingEnvironment.IncrementBusyCount();
1379 internal static void DecrementActivePipelineCount() {
1380 HostingEnvironment.DecrementBusyCount();
1381 Interlocked.Decrement(ref _theRuntime._activeRequestCount);
1384 internal static void PopulateIISVersionInformation() {
1385 if (IsEngineLoaded) {
1386 uint dwVersion;
1387 bool fIsIntegratedMode;
1388 UnsafeIISMethods.MgdGetIISVersionInformation(out dwVersion, out fIsIntegratedMode);
1390 if (dwVersion != 0) {
1391 // High word is the major version; low word is the minor version (this is MAKELONG format)
1392 _iisVersion = new Version((int)(dwVersion >> 16), (int)(dwVersion & 0xffff));
1393 _useIntegratedPipeline = fIsIntegratedMode;
1398 // 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.
1399 // Should also return the correct version for IIS Express.
1400 public static Version IISVersion {
1401 get {
1402 return _iisVersion;
1406 // DevDivBugs 190952: public method for querying runtime pipeline mode
1407 public static bool UsingIntegratedPipeline {
1408 get {
1409 return UseIntegratedPipeline;
1413 internal static bool UseIntegratedPipeline {
1414 get {
1415 return _useIntegratedPipeline;
1419 internal static bool EnablePrefetchOptimization {
1420 get {
1421 return _enablePrefetchOptimization;
1426 * Process one step of the integrated pipeline
1430 internal static RequestNotificationStatus ProcessRequestNotification(IIS7WorkerRequest wr, HttpContext context)
1432 return _theRuntime.ProcessRequestNotificationPrivate(wr, context);
1435 private RequestNotificationStatus ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) {
1436 RequestNotificationStatus status = RequestNotificationStatus.Pending;
1437 try {
1438 int currentModuleIndex;
1439 bool isPostNotification;
1440 int currentNotification;
1442 // setup the HttpContext for this event/module combo
1443 UnsafeIISMethods.MgdGetCurrentNotificationInfo(wr.RequestContext, out currentModuleIndex, out isPostNotification, out currentNotification);
1445 context.CurrentModuleIndex = currentModuleIndex;
1446 context.IsPostNotification = isPostNotification;
1447 context.CurrentNotification = (RequestNotification) currentNotification;
1448 #if DBG
1449 Debug.Trace("PipelineRuntime", "HttpRuntime::ProcessRequestNotificationPrivate: notification=" + context.CurrentNotification.ToString()
1450 + ", isPost=" + context.IsPostNotification
1451 + ", moduleIndex=" + context.CurrentModuleIndex);
1452 #endif
1454 IHttpHandler handler = null;
1455 if (context.NeedToInitializeApp()) {
1456 #if DBG
1457 Debug.Trace("FileChangesMonitorIgnoreSubdirChange",
1458 "*** FirstNotification " + DateTime.Now.ToString("hh:mm:ss.fff", CultureInfo.InvariantCulture)
1459 + ": _appDomainAppId=" + _appDomainAppId);
1460 #endif
1461 // First request initialization
1462 try {
1463 EnsureFirstRequestInit(context);
1465 catch {
1466 // If we are handling a DEBUG request, ignore the FirstRequestInit exception.
1467 // This allows the HttpDebugHandler to execute, and lets the debugger attach to
1468 // the process (VSWhidbey 358135)
1469 if (!context.Request.IsDebuggingRequest) {
1470 throw;
1474 context.Response.InitResponseWriter();
1475 handler = HttpApplicationFactory.GetApplicationInstance(context);
1476 if (handler == null)
1477 throw new HttpException(SR.GetString(SR.Unable_create_app_object));
1479 if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Infrastructure)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_START_HANDLER, context.WorkerRequest, handler.GetType().FullName, "Start");
1481 HttpApplication app = handler as HttpApplication;
1482 if (app != null) {
1483 // associate the context with an application instance
1484 app.AssignContext(context);
1488 // this may throw, and should be called after app initialization
1489 wr.SynchronizeVariables(context);
1491 if (context.ApplicationInstance != null) {
1492 // process request
1493 IAsyncResult ar = context.ApplicationInstance.BeginProcessRequestNotification(context, _requestNotificationCompletionCallback);
1495 if (ar.CompletedSynchronously) {
1496 status = RequestNotificationStatus.Continue;
1499 else if (handler != null) {
1500 // HttpDebugHandler is processed here
1501 handler.ProcessRequest(context);
1502 status = RequestNotificationStatus.FinishRequest;
1504 else {
1505 status = RequestNotificationStatus.Continue;
1508 catch (Exception e) {
1509 status = RequestNotificationStatus.FinishRequest;
1510 context.Response.InitResponseWriter();
1511 // errors are handled in HttpRuntime::FinishRequestNotification
1512 context.AddError(e);
1515 if (status != RequestNotificationStatus.Pending) {
1516 // we completed synchronously
1517 FinishRequestNotification(wr, context, ref status);
1520 #if DBG
1521 Debug.Trace("PipelineRuntime", "HttpRuntime::ProcessRequestNotificationPrivate: status=" + status.ToString());
1522 #endif
1524 return status;
1527 private void FinishRequestNotification(IIS7WorkerRequest wr, HttpContext context, ref RequestNotificationStatus status) {
1529 Debug.Assert(status != RequestNotificationStatus.Pending, "status != RequestNotificationStatus.Pending");
1531 HttpApplication app = context.ApplicationInstance;
1533 if (context.NotificationContext.RequestCompleted) {
1534 status = RequestNotificationStatus.FinishRequest;
1537 // check if the app offline or whether an error has occurred, and report the condition
1538 context.ReportRuntimeErrorIfExists(ref status);
1540 // we do not return FinishRequest for LogRequest or EndRequest
1541 if (status == RequestNotificationStatus.FinishRequest
1542 && (context.CurrentNotification == RequestNotification.LogRequest
1543 || context.CurrentNotification == RequestNotification.EndRequest)) {
1544 status = RequestNotificationStatus.Continue;
1547 IntPtr requestContext = wr.RequestContext;
1548 bool sendHeaders = UnsafeIISMethods.MgdIsLastNotification(requestContext, status);
1549 try {
1550 context.Response.UpdateNativeResponse(sendHeaders);
1552 catch(Exception e) {
1553 // if we catch an exception here then
1554 // i) clear cached response body bytes on the worker request
1555 // ii) clear the managed headers, the IIS native headers, the mangaged httpwriter response buffers, and the native IIS response buffers
1556 // iii) attempt to format the exception and write it to the response
1557 wr.UnlockCachedResponseBytes();
1558 context.AddError(e);
1559 context.ReportRuntimeErrorIfExists(ref status);
1560 try {
1561 context.Response.UpdateNativeResponse(sendHeaders);
1563 catch {
1567 if (sendHeaders) {
1568 context.FinishPipelineRequest();
1571 // Perf optimization: dispose managed context if possible (no need to try if status is pending)
1572 if (status != RequestNotificationStatus.Pending) {
1573 PipelineRuntime.DisposeHandler(context, requestContext, status);
1577 internal static void FinishPipelineRequest(HttpContext context) {
1578 // Remember that first request is done
1579 _theRuntime._firstRequestCompleted = true;
1581 // need to raise OnRequestCompleted while within the ThreadContext so that things like User, CurrentCulture, etc. are available
1582 context.RaiseOnRequestCompleted();
1584 context.Request.Dispose();
1585 context.Response.Dispose();
1586 HttpApplication app = context.ApplicationInstance;
1587 if(null != app) {
1588 ThreadContext threadContext = context.IndicateCompletionContext;
1589 if (threadContext != null) {
1590 if (!threadContext.HasBeenDisassociatedFromThread) {
1591 lock (threadContext) {
1592 if (!threadContext.HasBeenDisassociatedFromThread) {
1593 threadContext.DisassociateFromCurrentThread();
1594 context.IndicateCompletionContext = null;
1595 context.InIndicateCompletion = false;
1600 app.ReleaseAppInstance();
1603 SetExecutionTimePerformanceCounter(context);
1604 UpdatePerfCounters(context.Response.StatusCode);
1605 if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Infrastructure)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_END_HANDLER, context.WorkerRequest);
1607 // In case of a HostingInit() error, app domain should not stick around
1608 if (HostingInitFailed) {
1609 Debug.Trace("AppDomainFactory", "Shutting down appdomain because of HostingInit error");
1610 ShutdownAppDomain(ApplicationShutdownReason.HostingEnvironment, "HostingInit error");
1616 * Process one request
1618 private void ProcessRequestInternal(HttpWorkerRequest wr) {
1619 // Count active requests
1620 Interlocked.Increment(ref _activeRequestCount);
1622 if (_disposingHttpRuntime) {
1623 // Dev11 333176: An appdomain is unloaded before all requests are served, resulting in System.AppDomainUnloadedException during isapi completion callback
1625 // HttpRuntim.Dispose could have already finished on a different thread when we had no active requests
1626 // In this case we are about to start or already started unloading the appdomain so we will reject the request the safest way possible
1627 try {
1628 wr.SendStatus(503, "Server Too Busy");
1629 wr.SendKnownResponseHeader(HttpWorkerRequest.HeaderContentType, "text/html; charset=utf-8");
1630 byte[] body = Encoding.ASCII.GetBytes("<html><body>Server Too Busy</body></html>");
1631 wr.SendResponseFromMemory(body, body.Length);
1632 // this will flush synchronously because of HttpRuntime.ShutdownInProgress
1633 wr.FlushResponse(true);
1634 wr.EndOfRequest();
1635 } finally {
1636 Interlocked.Decrement(ref _activeRequestCount);
1638 return;
1641 // Construct the Context on HttpWorkerRequest, hook everything together
1642 HttpContext context;
1644 try {
1645 context = new HttpContext(wr, false /* initResponseWriter */);
1647 catch {
1648 try {
1649 // If we fail to create the context for any reason, send back a 400 to make sure
1650 // the request is correctly closed (relates to VSUQFE3962)
1651 wr.SendStatus(400, "Bad Request");
1652 wr.SendKnownResponseHeader(HttpWorkerRequest.HeaderContentType, "text/html; charset=utf-8");
1653 byte[] body = Encoding.ASCII.GetBytes("<html><body>Bad Request</body></html>");
1654 wr.SendResponseFromMemory(body, body.Length);
1655 wr.FlushResponse(true);
1656 wr.EndOfRequest();
1657 return;
1658 } finally {
1659 Interlocked.Decrement(ref _activeRequestCount);
1663 wr.SetEndOfSendNotification(_asyncEndOfSendCallback, context);
1665 HostingEnvironment.IncrementBusyCount();
1667 try {
1668 // First request initialization
1669 try {
1670 EnsureFirstRequestInit(context);
1672 catch {
1673 // If we are handling a DEBUG request, ignore the FirstRequestInit exception.
1674 // This allows the HttpDebugHandler to execute, and lets the debugger attach to
1675 // the process (VSWhidbey 358135)
1676 if (!context.Request.IsDebuggingRequest) {
1677 throw;
1681 // Init response writer (after we have config in first request init)
1682 // no need for impersonation as it is handled in config system
1683 context.Response.InitResponseWriter();
1685 // Get application instance
1686 IHttpHandler app = HttpApplicationFactory.GetApplicationInstance(context);
1688 if (app == null)
1689 throw new HttpException(SR.GetString(SR.Unable_create_app_object));
1691 if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Infrastructure)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_START_HANDLER, context.WorkerRequest, app.GetType().FullName, "Start");
1693 if (app is IHttpAsyncHandler) {
1694 // asynchronous handler
1695 IHttpAsyncHandler asyncHandler = (IHttpAsyncHandler)app;
1696 context.AsyncAppHandler = asyncHandler;
1697 asyncHandler.BeginProcessRequest(context, _handlerCompletionCallback, context);
1699 else {
1700 // synchronous handler
1701 app.ProcessRequest(context);
1702 FinishRequest(context.WorkerRequest, context, null);
1705 catch (Exception e) {
1706 context.Response.InitResponseWriter();
1707 FinishRequest(wr, context, e);
1711 private void RejectRequestInternal(HttpWorkerRequest wr, bool silent) {
1712 // Construct the Context on HttpWorkerRequest, hook everything together
1713 HttpContext context = new HttpContext(wr, false /* initResponseWriter */);
1714 wr.SetEndOfSendNotification(_asyncEndOfSendCallback, context);
1716 // Count active requests
1717 Interlocked.Increment(ref _activeRequestCount);
1718 HostingEnvironment.IncrementBusyCount();
1720 if (silent) {
1721 context.Response.InitResponseWriter();
1722 FinishRequest(wr, context, null);
1724 else {
1725 PerfCounters.IncrementGlobalCounter(GlobalPerfCounter.REQUESTS_REJECTED);
1726 PerfCounters.IncrementCounter(AppPerfCounter.APP_REQUESTS_REJECTED);
1727 try {
1728 throw new HttpException(503, SR.GetString(SR.Server_too_busy));
1730 catch (Exception e) {
1731 context.Response.InitResponseWriter();
1732 FinishRequest(wr, context, e);
1737 internal static void ReportAppOfflineErrorMessage(HttpResponse response, byte[] appOfflineMessage) {
1738 response.StatusCode = 503;
1739 response.ContentType = "text/html";
1740 response.AddHeader("Retry-After", "3600");
1741 response.OutputStream.Write(appOfflineMessage, 0, appOfflineMessage.Length);
1745 * Finish processing request, sync or async
1747 private void FinishRequest(HttpWorkerRequest wr, HttpContext context, Exception e) {
1748 HttpResponse response = context.Response;
1750 if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Infrastructure)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_END_HANDLER, context.WorkerRequest);
1752 SetExecutionTimePerformanceCounter(context);
1754 // Flush in case of no error
1755 if (e == null) {
1756 // impersonate around PreSendHeaders / PreSendContent
1757 using (new ClientImpersonationContext(context, false)) {
1758 try {
1759 // this sends the actual content in most cases
1760 response.FinalFlushAtTheEndOfRequestProcessing();
1762 catch (Exception eFlush) {
1763 e = eFlush;
1768 // Report error if any
1769 if (e != null) {
1770 using (new DisposableHttpContextWrapper(context)) {
1772 // if the custom encoder throws, it might interfere with returning error information
1773 // to the client, so we force use of the default encoder
1774 context.DisableCustomHttpEncoder = true;
1776 if (_appOfflineMessage != null) {
1777 try {
1778 ReportAppOfflineErrorMessage(response, _appOfflineMessage);
1779 response.FinalFlushAtTheEndOfRequestProcessing();
1781 catch {
1784 else {
1785 // when application is on UNC share the code below must
1786 // be run while impersonating the token given by IIS
1787 using (new ApplicationImpersonationContext()) {
1788 try {
1789 try {
1790 // try to report error in a way that could possibly throw (a config exception)
1791 response.ReportRuntimeError(e, true /*canThrow*/, false);
1793 catch (Exception eReport) {
1794 // report the config error in a way that would not throw
1795 response.ReportRuntimeError(eReport, false /*canThrow*/, false);
1798 response.FinalFlushAtTheEndOfRequestProcessing();
1800 catch {
1807 // Remember that first request is done
1808 _firstRequestCompleted = true;
1811 // In case we reporting HostingInit() error, app domain should not stick around
1812 if (_hostingInitFailed) {
1813 Debug.Trace("AppDomainFactory", "Shutting down appdomain because of HostingInit error");
1814 ShutdownAppDomain(ApplicationShutdownReason.HostingEnvironment, "HostingInit error");
1817 // Check status code and increment proper counter
1818 // If it's an error status code (i.e. 400 or higher), increment the proper perf counters
1819 int statusCode = response.StatusCode;
1820 UpdatePerfCounters(statusCode);
1822 context.FinishRequestForCachedPathData(statusCode);
1824 // ---- exceptions from EndOfRequest as they will prevent proper request cleanup
1825 // Since the exceptions are not expected here we want to log them
1826 try {
1827 wr.EndOfRequest();
1829 catch (Exception ex) {
1830 WebBaseEvent.RaiseRuntimeError(ex, this);
1833 // Count active requests
1834 HostingEnvironment.DecrementBusyCount();
1835 Interlocked.Decrement(ref _activeRequestCount);
1837 // Schedule more work if some requests are queued
1838 if (_requestQueue != null)
1839 _requestQueue.ScheduleMoreWorkIfNeeded();
1843 // Make sure shutdown happens only once
1846 private bool InitiateShutdownOnce() {
1847 if (_shutdownInProgress)
1848 return false;
1850 lock (this) {
1851 if (_shutdownInProgress)
1852 return false;
1853 _shutdownInProgress = true;
1856 return true;
1860 // Shutdown this and restart new app domain
1862 [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
1863 private void ReleaseResourcesAndUnloadAppDomain(Object state /*not used*/) {
1864 #if DBG
1865 Debug.Trace("FileChangesMonitorIgnoreSubdirChange",
1866 "*** ReleaseResourcesAndUnloadAppDomain " + DateTime.Now.ToString("hh:mm:ss.fff", CultureInfo.InvariantCulture)
1867 + ": _appDomainAppId=" + _appDomainAppId);
1868 #endif
1869 Debug.Trace("AppDomainFactory", "ReleaseResourcesAndUnloadAppDomain, Id=" + _appDomainAppId
1870 + " DomainId = " + _appDomainId
1871 + " Stack = " + Environment.StackTrace );
1873 try {
1874 PerfCounters.IncrementGlobalCounter(GlobalPerfCounter.APPLICATION_RESTARTS);
1876 catch {
1879 // Release all resources
1880 try {
1881 Dispose();
1883 catch {
1886 Thread.Sleep(250);
1888 AddAppDomainTraceMessage("before Unload");
1890 for (; ; ) {
1891 try {
1892 AppDomain.Unload(Thread.GetDomain());
1894 catch (CannotUnloadAppDomainException) {
1895 Debug.Assert(false);
1897 catch (Exception e) {
1898 Debug.Trace("AppDomainFactory", "AppDomain.Unload exception: " + e + "; Id=" + _appDomainAppId);
1899 if (!BuildManagerHost.InClientBuildManager) {
1900 // Avoid calling Exception.ToString if we are in the ClientBuildManager (Dev10 bug 824659)
1901 AddAppDomainTraceMessage("Unload Exception: " + e);
1903 throw;
1908 private static void SetExecutionTimePerformanceCounter(HttpContext context) {
1909 // Set the Request Execution time perf counter
1910 TimeSpan elapsed = DateTime.UtcNow.Subtract(context.WorkerRequest.GetStartTime());
1911 long milli = elapsed.Ticks / TimeSpan.TicksPerMillisecond;
1913 if (milli > Int32.MaxValue)
1914 milli = Int32.MaxValue;
1916 PerfCounters.SetGlobalCounter(GlobalPerfCounter.REQUEST_EXECUTION_TIME, (int)milli);
1917 PerfCounters.SetCounter(AppPerfCounter.APP_REQUEST_EXEC_TIME, (int)milli);
1920 private static void UpdatePerfCounters(int statusCode) {
1921 if (400 <= statusCode) {
1922 PerfCounters.IncrementCounter(AppPerfCounter.REQUESTS_FAILED);
1923 switch (statusCode) {
1924 case 401: // Not authorized
1925 PerfCounters.IncrementCounter(AppPerfCounter.REQUESTS_NOT_AUTHORIZED);
1926 break;
1927 case 404: // Not found
1928 case 414: // Not found
1929 PerfCounters.IncrementCounter(AppPerfCounter.REQUESTS_NOT_FOUND);
1930 break;
1933 else {
1934 // If status code is not in the 400-599 range (i.e. 200-299 success or 300-399 redirection),
1935 // count it as a successful request.
1936 PerfCounters.IncrementCounter(AppPerfCounter.REQUESTS_SUCCEDED);
1940 private void WaitForRequestsToFinish(int waitTimeoutMs) {
1941 DateTime waitLimit = DateTime.UtcNow.AddMilliseconds(waitTimeoutMs);
1943 for (; ; ) {
1944 if (_activeRequestCount == 0 && (_requestQueue == null || _requestQueue.IsEmpty))
1945 break;
1947 Thread.Sleep(250);
1949 // only apply timeout if a managed debugger is not attached
1950 if (!System.Diagnostics.Debugger.IsAttached && DateTime.UtcNow > waitLimit) {
1951 break; // give it up
1957 * Cleanup of all unmananged state
1959 private void Dispose() {
1960 // get shutdown timeout from config
1961 int drainTimeoutSec = HttpRuntimeSection.DefaultShutdownTimeout;
1962 try {
1963 HttpRuntimeSection runtimeConfig = RuntimeConfig.GetAppLKGConfig().HttpRuntime;
1964 if (runtimeConfig != null) {
1965 drainTimeoutSec = (int)runtimeConfig.ShutdownTimeout.TotalSeconds;
1968 // before aborting compilation give time to drain (new requests are no longer coming at this point)
1969 WaitForRequestsToFinish(drainTimeoutSec * 1000);
1971 // reject remaining queued requests
1972 if (_requestQueue != null)
1973 _requestQueue.Drain();
1974 } finally {
1975 // By this time all new requests should be directed to a newly created app domain
1976 // But there might be requests that got dispatched to this old app domain but have not reached ProcessRequestInternal yet
1977 // Signal ProcessRequestInternal to reject them immediately without initiating async operations
1978 _disposingHttpRuntime = true;
1981 // give it a little more time to drain
1982 WaitForRequestsToFinish((drainTimeoutSec * 1000) / 6);
1985 // wait for pending async io to complete, prior to aborting requests
1986 // this isn't necessary for IIS 7, where the async sends are always done
1987 // from native code with native buffers
1988 System.Web.Hosting.ISAPIWorkerRequestInProcForIIS6.WaitForPendingAsyncIo();
1990 // For IIS7 integrated pipeline, wait until GL_APPLICATION_STOP fires and
1991 // there are no active calls to IndicateCompletion before unloading the AppDomain
1992 if (HttpRuntime.UseIntegratedPipeline) {
1993 PipelineRuntime.WaitForRequestsToDrain();
1995 else {
1996 // wait for all active requests to complete
1997 while (_activeRequestCount != 0) {
1998 Thread.Sleep(250);
2003 // Dispose AppDomainShutdownTimer
2004 DisposeAppDomainShutdownTimer();
2006 // kill all remaining requests (and the timeout timer)
2007 _timeoutManager.Stop();
2008 AppDomainResourcePerfCounters.Stop();
2010 #if !FEATURE_PAL // FEATURE_PAL does not enable IIS-based hosting features
2011 // double check for pending async io
2012 System.Web.Hosting.ISAPIWorkerRequestInProcForIIS6.WaitForPendingAsyncIo();
2014 // stop sqlcachedependency polling
2015 SqlCacheDependencyManager.Dispose((drainTimeoutSec * 1000) / 2);
2016 #endif // !FEATURE_PAL
2017 // cleanup cache (this ends all sessions)
2018 HealthMonitoringManager.IsCacheDisposed = true; // HMM is the only place internally where we care if the Cache is disposed or not.
2019 if (_cachePublic != null) {
2020 var oCache = HttpRuntime.Cache.GetObjectCache(createIfDoesNotExist: false);
2021 var iCache = HttpRuntime.Cache.GetInternalCache(createIfDoesNotExist: false);
2022 if (oCache != null) {
2023 oCache.Dispose();
2025 if (iCache != null) {
2026 iCache.Dispose();
2030 // app on end, cleanup app instances
2031 HttpApplicationFactory.EndApplication(); // call app_onEnd
2033 // stop file changes monitor
2034 _fcm.Stop();
2036 // stop health monitoring timer
2037 HealthMonitoringManager.Shutdown();
2041 * Async completion of IIS7 pipeline (unlike OnHandlerCompletion, this may fire more than once).
2043 private void OnRequestNotificationCompletion(IAsyncResult ar) {
2044 try {
2045 OnRequestNotificationCompletionHelper(ar);
2047 catch(Exception e) {
2048 ApplicationManager.RecordFatalException(e);
2049 throw;
2053 private void OnRequestNotificationCompletionHelper(IAsyncResult ar) {
2054 if (ar.CompletedSynchronously) {
2055 Debug.Trace("PipelineRuntime", "OnRequestNotificationCompletion: completed synchronously");
2056 return;
2059 Debug.Trace("PipelineRuntime", "OnRequestNotificationCompletion: completed asynchronously");
2061 RequestNotificationStatus status = RequestNotificationStatus.Continue;
2062 HttpContext context = (HttpContext) ar.AsyncState;
2063 IIS7WorkerRequest wr = context.WorkerRequest as IIS7WorkerRequest;
2065 try {
2066 context.ApplicationInstance.EndProcessRequestNotification(ar);
2068 catch (Exception e) {
2069 status = RequestNotificationStatus.FinishRequest;
2070 context.AddError(e);
2073 // RequestContext is set to null if this is the last notification, so we need to save it
2074 // for the call to PostCompletion
2075 IntPtr requestContext = wr.RequestContext;
2077 FinishRequestNotification(wr, context, ref status);
2079 // set the notification context to null since we are exiting this notification
2080 context.NotificationContext = null;
2082 // Indicate completion to IIS, so that it can resume
2083 // request processing on an IIS thread
2084 Debug.Trace("PipelineRuntime", "OnRequestNotificationCompletion(" + status + ")");
2085 int result = UnsafeIISMethods.MgdPostCompletion(requestContext, status);
2086 Misc.ThrowIfFailedHr(result);
2090 * Async completion of managed pipeline (called at most one time).
2092 private void OnHandlerCompletion(IAsyncResult ar) {
2093 HttpContext context = (HttpContext)ar.AsyncState;
2095 try {
2096 context.AsyncAppHandler.EndProcessRequest(ar);
2098 catch (Exception e) {
2099 context.AddError(e);
2101 finally {
2102 // no longer keep AsyncAppHandler poiting to the application
2103 // is only needed to call EndProcessRequest
2104 context.AsyncAppHandler = null;
2107 FinishRequest(context.WorkerRequest, context, context.Error);
2111 * Notification from worker request that it is done writing from buffer
2112 * so that the buffers can be recycled
2114 private void EndOfSendCallback(HttpWorkerRequest wr, Object arg) {
2115 Debug.Trace("PipelineRuntime", "HttpRuntime.EndOfSendCallback");
2116 HttpContext context = (HttpContext)arg;
2117 context.Request.Dispose();
2118 context.Response.Dispose();
2122 * Notification when something in the bin directory changed
2124 private void OnCriticalDirectoryChange(Object sender, FileChangeEvent e) {
2125 // shutdown the app domain
2126 Debug.Trace("AppDomainFactory", "Shutting down appdomain because of bin dir change or directory rename." +
2127 " FileName=" + e.FileName + " Action=" + e.Action);
2129 ApplicationShutdownReason reason = ApplicationShutdownReason.None;
2130 string directoryName = new DirectoryInfo(e.FileName).Name;
2132 string message = FileChangesMonitor.GenerateErrorMessage(e.Action);
2133 message = (message != null) ? message + directoryName : directoryName + " dir change or directory rename";
2135 if (StringUtil.EqualsIgnoreCase(directoryName, CodeDirectoryName)) {
2136 reason = ApplicationShutdownReason.CodeDirChangeOrDirectoryRename;
2138 else if (StringUtil.EqualsIgnoreCase(directoryName, ResourcesDirectoryName)) {
2139 reason = ApplicationShutdownReason.ResourcesDirChangeOrDirectoryRename;
2141 else if (StringUtil.EqualsIgnoreCase(directoryName, BrowsersDirectoryName)) {
2142 reason = ApplicationShutdownReason.BrowsersDirChangeOrDirectoryRename;
2144 else if (StringUtil.EqualsIgnoreCase(directoryName, BinDirectoryName)) {
2145 reason = ApplicationShutdownReason.BinDirChangeOrDirectoryRename;
2148 if (e.Action == FileAction.Added) {
2149 // Make sure HttpRuntime does not ignore the appdomain shutdown if a file is added (VSWhidbey 363481)
2150 HttpRuntime.SetUserForcedShutdown();
2152 Debug.Trace("AppDomainFactorySpecial", "Call SetUserForcedShutdown: FileName=" + e.FileName + "; now=" + DateTime.Now);
2155 ShutdownAppDomain(reason, message);
2159 * Coalesce file change notifications to minimize sharing violations and AppDomain restarts (ASURT 147492)
2161 internal static void CoalesceNotifications() {
2162 int waitChangeNotification = HttpRuntimeSection.DefaultWaitChangeNotification;
2163 int maxWaitChangeNotification = HttpRuntimeSection.DefaultMaxWaitChangeNotification;
2164 try {
2165 HttpRuntimeSection config = RuntimeConfig.GetAppLKGConfig().HttpRuntime;
2166 if (config != null) {
2167 waitChangeNotification = config.WaitChangeNotification;
2168 maxWaitChangeNotification = config.MaxWaitChangeNotification;
2171 catch {
2174 if (waitChangeNotification == 0 || maxWaitChangeNotification == 0)
2175 return;
2177 DateTime maxWait = DateTime.UtcNow.AddSeconds(maxWaitChangeNotification);
2178 // Coalesce file change notifications
2179 try {
2180 while (DateTime.UtcNow < maxWait) {
2181 if (DateTime.UtcNow > _theRuntime.LastShutdownAttemptTime.AddSeconds(waitChangeNotification))
2182 break;
2184 Thread.Sleep(250);
2187 catch {
2191 // appdomain shutdown eventhandler
2192 internal static event BuildManagerHostUnloadEventHandler AppDomainShutdown;
2194 internal static void OnAppDomainShutdown(BuildManagerHostUnloadEventArgs e) {
2195 if (AppDomainShutdown != null) {
2196 AppDomainShutdown(_theRuntime, e);
2200 internal static void SetUserForcedShutdown() {
2201 _theRuntime._userForcedShutdown = true;
2205 * Shutdown the current app domain
2207 internal static bool ShutdownAppDomain(ApplicationShutdownReason reason, string message) {
2208 return ShutdownAppDomainWithStackTrace(reason, message, null /*stackTrace*/);
2212 * Shutdown the current app domain with a stack trace. This is useful for callers that are running
2213 * on a QUWI callback, and wouldn't provide a meaningful stack trace by default.
2215 internal static bool ShutdownAppDomainWithStackTrace(ApplicationShutdownReason reason, string message, string stackTrace) {
2216 SetShutdownReason(reason, message);
2217 return ShutdownAppDomain(stackTrace);
2220 private static bool ShutdownAppDomain(string stackTrace) {
2221 #if DBG
2222 Debug.Trace("FileChangesMonitorIgnoreSubdirChange",
2223 "*** ShutdownAppDomain " + DateTime.Now.ToString("hh:mm:ss.fff", CultureInfo.InvariantCulture)
2224 + ": _appDomainAppId=" + HttpRuntime.AppDomainAppId);
2225 #endif
2226 // Ignore notifications during the processing of the first request (ASURT 100335)
2227 // skip this if LastShutdownAttemptTime has been set
2228 if (_theRuntime.LastShutdownAttemptTime == DateTime.MinValue && !_theRuntime._firstRequestCompleted && !_theRuntime._userForcedShutdown) {
2229 // check the timeout (don't disable notifications forever
2230 int delayTimeoutSec = HttpRuntimeSection.DefaultDelayNotificationTimeout;
2232 try {
2233 RuntimeConfig runtimeConfig = RuntimeConfig.GetAppLKGConfig();
2234 if (runtimeConfig != null) {
2235 HttpRuntimeSection runtimeSection = runtimeConfig.HttpRuntime;
2236 if (runtimeSection != null) {
2237 delayTimeoutSec = (int)runtimeSection.DelayNotificationTimeout.TotalSeconds;
2239 if (DateTime.UtcNow < _theRuntime._firstRequestStartTime.AddSeconds(delayTimeoutSec)) {
2240 Debug.Trace("AppDomainFactory", "ShutdownAppDomain IGNORED (1st request is not done yet), Id = " + AppDomainAppId);
2241 return false;
2246 catch {
2250 try {
2251 _theRuntime.RaiseShutdownWebEventOnce();
2253 catch {
2254 // VSWhidbey 444472: if an exception is thrown, we consume it and continue executing the following code.
2257 // Update last time ShutdownAppDomain was called
2258 _theRuntime.LastShutdownAttemptTime = DateTime.UtcNow;
2260 if (!HostingEnvironment.ShutdownInitiated) {
2261 // This shutdown is not triggered by hosting environment - let it do the job
2262 HostingEnvironment.InitiateShutdownWithoutDemand();
2263 return true;
2266 //WOS 1400290: CantUnloadAppDomainException in ISAPI mode, wait until HostingEnvironment.ShutdownThisAppDomainOnce completes
2267 if (HostingEnvironment.ShutdownInProgress) {
2268 return false;
2271 // Make sure we don't go through shutdown logic many times
2272 if (!_theRuntime.InitiateShutdownOnce())
2273 return false;
2275 Debug.Trace("AppDomainFactory", "ShutdownAppDomain, Id = " + AppDomainAppId + ", ShutdownInProgress=" + ShutdownInProgress
2276 + ", ShutdownMessage=" + _theRuntime._shutDownMessage);
2278 if (String.IsNullOrEmpty(stackTrace) && !BuildManagerHost.InClientBuildManager) {
2279 // Avoid calling Environment.StackTrace if we are in the ClientBuildManager (Dev10 bug 824659)
2281 // Instrument to be able to see what's causing a shutdown
2282 new EnvironmentPermission(PermissionState.Unrestricted).Assert();
2283 try {
2284 _theRuntime._shutDownStack = Environment.StackTrace;
2286 finally {
2287 CodeAccessPermission.RevertAssert();
2290 else {
2291 _theRuntime._shutDownStack = stackTrace;
2294 // Notify when appdomain is about to shutdown.
2295 OnAppDomainShutdown(new BuildManagerHostUnloadEventArgs(_theRuntime._shutdownReason));
2297 // unload app domain from another CLR thread
2298 ThreadPool.QueueUserWorkItem(_theRuntime._appDomainUnloadallback);
2300 return true;
2303 internal static void RecoverFromUnexceptedAppDomainUnload() {
2304 if (_theRuntime._shutdownInProgress)
2305 return;
2307 // someone unloaded app domain directly - tell unmanaged code
2308 Debug.Trace("AppDomainFactory", "Unexpected AppDomainUnload");
2309 _theRuntime._shutdownInProgress = true;
2311 // tell unmanaged code not to dispatch requests to this app domain
2312 try {
2313 ISAPIRuntime.RemoveThisAppDomainFromUnmanagedTable();
2314 PipelineRuntime.RemoveThisAppDomainFromUnmanagedTable();
2315 AddAppDomainTraceMessage("AppDomainRestart");
2317 finally {
2318 // release all resources
2319 _theRuntime.Dispose();
2324 * Notification when app-level Config changed
2326 internal static void OnConfigChange(String message) {
2327 Debug.Trace("AppDomainFactory", "Shutting down appdomain because of config change");
2328 ShutdownAppDomain(ApplicationShutdownReason.ConfigurationChange, (message != null) ? message : "CONFIG change");
2331 // Intrumentation to remember the overwhelming file change
2332 internal static void SetShutdownReason(ApplicationShutdownReason reason, String message) {
2333 if (_theRuntime._shutdownReason == ApplicationShutdownReason.None) {
2334 _theRuntime._shutdownReason = reason;
2337 SetShutdownMessage(message);
2340 internal static void SetShutdownMessage(String message) {
2341 if (message != null) {
2342 if (_theRuntime._shutDownMessage == null)
2343 _theRuntime._shutDownMessage = message;
2344 else
2345 _theRuntime._shutDownMessage += "\r\n" + message;
2350 // public method is on HostingEnvironment
2351 internal static ApplicationShutdownReason ShutdownReason {
2352 get { return _theRuntime._shutdownReason; }
2356 // public static APIs
2360 * Process one request
2363 /// <devdoc>
2364 /// <para><SPAN>The method that drives
2365 /// all ASP.NET web processing execution.</SPAN></para>
2366 /// </devdoc>
2367 [AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Medium)]
2368 public static void ProcessRequest(HttpWorkerRequest wr) {
2369 if (wr == null)
2370 throw new ArgumentNullException("wr");
2372 if (HttpRuntime.UseIntegratedPipeline) {
2373 throw new PlatformNotSupportedException(SR.GetString(SR.Method_Not_Supported_By_Iis_Integrated_Mode, "HttpRuntime.ProcessRequest"));
2376 ProcessRequestNoDemand(wr);
2380 internal static void ProcessRequestNoDemand(HttpWorkerRequest wr) {
2381 RequestQueue rq = _theRuntime._requestQueue;
2383 wr.UpdateInitialCounters();
2385 if (rq != null) // could be null before first request
2386 wr = rq.GetRequestToExecute(wr);
2388 if (wr != null) {
2389 CalculateWaitTimeAndUpdatePerfCounter(wr);
2390 wr.ResetStartTime();
2391 ProcessRequestNow(wr);
2396 private static void CalculateWaitTimeAndUpdatePerfCounter(HttpWorkerRequest wr) {
2397 DateTime begin = wr.GetStartTime();
2399 TimeSpan elapsed = DateTime.UtcNow.Subtract(begin);
2400 long milli = elapsed.Ticks / TimeSpan.TicksPerMillisecond;
2402 if (milli > Int32.MaxValue)
2403 milli = Int32.MaxValue;
2405 PerfCounters.SetGlobalCounter(GlobalPerfCounter.REQUEST_WAIT_TIME, (int)milli);
2406 PerfCounters.SetCounter(AppPerfCounter.APP_REQUEST_WAIT_TIME, (int)milli);
2409 internal static void ProcessRequestNow(HttpWorkerRequest wr) {
2410 _theRuntime.ProcessRequestInternal(wr);
2413 internal static void RejectRequestNow(HttpWorkerRequest wr, bool silent) {
2414 _theRuntime.RejectRequestInternal(wr, silent);
2418 /// <devdoc>
2419 /// <para>Removes all items from the cache and shuts down the runtime.</para>
2420 /// </devdoc>
2421 [SecurityPermission(SecurityAction.Demand, Unrestricted = true)]
2422 public static void Close() {
2423 Debug.Trace("AppDomainFactory", "HttpRuntime.Close, ShutdownInProgress=" + ShutdownInProgress);
2424 if (_theRuntime.InitiateShutdownOnce()) {
2425 SetShutdownReason(ApplicationShutdownReason.HttpRuntimeClose, "HttpRuntime.Close is called");
2427 if (HostingEnvironment.IsHosted) {
2428 // go throw initiate shutdown for hosted scenarios
2429 HostingEnvironment.InitiateShutdownWithoutDemand();
2431 else {
2432 _theRuntime.Dispose();
2438 /// <devdoc>
2439 /// <para>Unloads the current app domain.</para>
2440 /// </devdoc>
2441 public static void UnloadAppDomain() {
2442 _theRuntime._userForcedShutdown = true;
2443 ShutdownAppDomain(ApplicationShutdownReason.UnloadAppDomainCalled, "User code called UnloadAppDomain");
2446 private DateTime LastShutdownAttemptTime {
2447 get {
2448 DateTime dt;
2449 lock (this) {
2450 dt = _lastShutdownAttemptTime;
2452 return dt;
2454 set {
2455 lock (this) {
2456 _lastShutdownAttemptTime = value;
2461 internal static Profiler Profile {
2462 get {
2463 return _theRuntime._profiler;
2467 internal static bool IsTrustLevelInitialized {
2468 get {
2469 return !HostingEnvironment.IsHosted || TrustLevel != null;
2473 internal static NamedPermissionSet NamedPermissionSet {
2474 get {
2475 // Make sure we have already initialized the trust level
2479 return _theRuntime._namedPermissionSet;
2483 internal static PolicyLevel PolicyLevel {
2484 get {
2485 return _theRuntime._policyLevel;
2489 internal static string HostSecurityPolicyResolverType {
2490 get {
2491 return _theRuntime._hostSecurityPolicyResolverType;
2495 [AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Unrestricted)]
2496 public static NamedPermissionSet GetNamedPermissionSet() {
2497 NamedPermissionSet namedPermissionSet = _theRuntime._namedPermissionSet;
2498 if (namedPermissionSet == null) {
2499 return null;
2501 else {
2502 return new NamedPermissionSet(namedPermissionSet);
2506 internal static bool IsFullTrust {
2507 get {
2508 // Make sure we have already initialized the trust level
2509 Debug.Assert(IsTrustLevelInitialized);
2511 return (_theRuntime._namedPermissionSet == null);
2516 * Check that the current trust level allows access to a virtual path. Throw if it doesn't,
2518 internal static void CheckVirtualFilePermission(string virtualPath) {
2519 string physicalPath = HostingEnvironment.MapPath(virtualPath);
2520 CheckFilePermission(physicalPath);
2524 * Check that the current trust level allows access to a path. Throw if it doesn't,
2526 internal static void CheckFilePermission(string path) {
2527 CheckFilePermission(path, false);
2530 internal static void CheckFilePermission(string path, bool writePermissions) {
2531 if (!HasFilePermission(path, writePermissions)) {
2532 throw new HttpException(SR.GetString(SR.Access_denied_to_path, GetSafePath(path)));
2536 internal static bool HasFilePermission(string path) {
2537 return HasFilePermission(path, false);
2540 internal static bool HasFilePermission(string path, bool writePermissions) {
2541 // WOS #1523618: need to skip this check for HttpResponse.ReportRuntimeError when reporting an
2542 // InitializationException (e.g., necessary to display line info for ConfigurationException).
2544 if (TrustLevel == null && InitializationException != null) {
2545 return true;
2548 // Make sure we have already initialized the trust level
2549 Debug.Assert(TrustLevel != null || !HostingEnvironment.IsHosted, "TrustLevel != null || !HostingEnvironment.IsHosted");
2551 // If we don't have a NamedPermissionSet, we're in full trust
2552 if (NamedPermissionSet == null)
2553 return true;
2555 bool fAccess = false;
2557 // Check that the user has permission to the path
2558 IPermission allowedPermission = NamedPermissionSet.GetPermission(typeof(FileIOPermission));
2559 if (allowedPermission != null) {
2560 IPermission askedPermission = null;
2561 try {
2562 if (!writePermissions)
2563 askedPermission = new FileIOPermission(FileIOPermissionAccess.Read, path);
2564 else
2565 askedPermission = new FileIOPermission(FileIOPermissionAccess.AllAccess, path);
2567 catch {
2568 // This could happen if the path is not absolute
2569 return false;
2571 fAccess = askedPermission.IsSubsetOf(allowedPermission);
2574 return fAccess;
2577 internal static bool HasWebPermission(Uri uri) {
2579 // Make sure we have already initialized the trust level
2580 Debug.Assert(TrustLevel != null || !HostingEnvironment.IsHosted);
2582 // If we don't have a NamedPermissionSet, we're in full trust
2583 if (NamedPermissionSet == null)
2584 return true;
2586 bool fAccess = false;
2588 // Check that the user has permission to the URI
2589 IPermission allowedPermission = NamedPermissionSet.GetPermission(typeof(WebPermission));
2590 if (allowedPermission != null) {
2591 IPermission askedPermission = null;
2592 try {
2593 askedPermission = new WebPermission(NetworkAccess.Connect, uri.ToString());
2595 catch {
2596 return false;
2598 fAccess = askedPermission.IsSubsetOf(allowedPermission);
2601 return fAccess;
2604 internal static bool HasDbPermission(DbProviderFactory factory) {
2606 // Make sure we have already initialized the trust level
2607 Debug.Assert(TrustLevel != null || !HostingEnvironment.IsHosted);
2609 // If we don't have a NamedPermissionSet, we're in full trust
2610 if (NamedPermissionSet == null)
2611 return true;
2613 bool fAccess = false;
2615 // Check that the user has permission to the provider
2616 CodeAccessPermission askedPermission = factory.CreatePermission(PermissionState.Unrestricted);
2617 if (askedPermission != null) {
2618 IPermission allowedPermission = NamedPermissionSet.GetPermission(askedPermission.GetType());
2619 if (allowedPermission != null) {
2620 fAccess = askedPermission.IsSubsetOf(allowedPermission);
2624 return fAccess;
2627 internal static bool HasPathDiscoveryPermission(string path) {
2628 // WOS #1523618: need to skip this check for HttpResponse.ReportRuntimeError when reporting an
2629 // InitializationException (e.g., necessary to display line info for ConfigurationException).
2631 if (TrustLevel == null && InitializationException != null) {
2632 return true;
2635 // Make sure we have already initialized the trust level
2636 Debug.Assert(TrustLevel != null || !HostingEnvironment.IsHosted);
2638 // If we don't have a NamedPermissionSet, we're in full trust
2639 if (NamedPermissionSet == null)
2640 return true;
2642 bool fAccess = false;
2644 // Check that the user has permission to the path
2645 IPermission allowedPermission = NamedPermissionSet.GetPermission(typeof(FileIOPermission));
2646 if (allowedPermission != null) {
2647 IPermission askedPermission = new FileIOPermission(FileIOPermissionAccess.PathDiscovery, path);
2648 fAccess = askedPermission.IsSubsetOf(allowedPermission);
2651 return fAccess;
2655 internal static bool HasAppPathDiscoveryPermission() {
2656 return HasPathDiscoveryPermission(HttpRuntime.AppDomainAppPathInternal);
2659 internal static string GetSafePath(string path) {
2660 if (String.IsNullOrEmpty(path))
2661 return path;
2663 try {
2664 if (HasPathDiscoveryPermission(path)) // could throw on bad filenames
2665 return path;
2667 catch {
2670 return Path.GetFileName(path);
2674 * Check that the current trust level allows Unmanaged access
2676 internal static bool HasUnmanagedPermission() {
2678 // Make sure we have already initialized the trust level
2679 Debug.Assert(TrustLevel != null || !HostingEnvironment.IsHosted);
2681 // If we don't have a NamedPermissionSet, we're in full trust
2682 if (NamedPermissionSet == null)
2683 return true;
2685 SecurityPermission securityPermission = (SecurityPermission)NamedPermissionSet.GetPermission(
2686 typeof(SecurityPermission));
2687 if (securityPermission == null)
2688 return false;
2690 return (securityPermission.Flags & SecurityPermissionFlag.UnmanagedCode) != 0;
2693 internal static bool HasAspNetHostingPermission(AspNetHostingPermissionLevel level) {
2695 // Make sure we have already initialized the trust level
2700 // If we don't have a NamedPermissionSet, we're in full trust
2701 if (NamedPermissionSet == null)
2702 return true;
2704 AspNetHostingPermission permission = (AspNetHostingPermission)NamedPermissionSet.GetPermission(
2705 typeof(AspNetHostingPermission));
2706 if (permission == null)
2707 return false;
2709 return (permission.Level >= level);
2712 internal static void CheckAspNetHostingPermission(AspNetHostingPermissionLevel level, String errorMessageId) {
2713 if (!HasAspNetHostingPermission(level)) {
2714 throw new HttpException(SR.GetString(errorMessageId));
2718 // If we're not in full trust, fail if the passed in type doesn't have the APTCA bit
2719 internal static void FailIfNoAPTCABit(Type t, ElementInformation elemInfo, string propertyName) {
2721 if (!IsTypeAllowedInConfig(t)) {
2722 if (null != elemInfo) {
2723 PropertyInformation propInfo = elemInfo.Properties[propertyName];
2725 throw new ConfigurationErrorsException(SR.GetString(SR.Type_from_untrusted_assembly, t.FullName),
2726 propInfo.Source, propInfo.LineNumber);
2728 else {
2729 throw new ConfigurationErrorsException(SR.GetString(SR.Type_from_untrusted_assembly, t.FullName));
2734 // If we're not in full trust, fail if the passed in type doesn't have the APTCA bit
2735 internal static void FailIfNoAPTCABit(Type t, XmlNode node) {
2737 if (!IsTypeAllowedInConfig(t)) {
2738 throw new ConfigurationErrorsException(SR.GetString(SR.Type_from_untrusted_assembly, t.FullName),
2739 node);
2743 private static bool HasAPTCABit(Assembly assembly) {
2744 return assembly.IsDefined(typeof(AllowPartiallyTrustedCallersAttribute), inherit: false);
2747 // Check if the type is allowed to be used in config by checking the APTCA bit
2748 internal static bool IsTypeAllowedInConfig(Type t) {
2750 // Allow everything in full trust
2751 if (HttpRuntime.HasAspNetHostingPermission(AspNetHostingPermissionLevel.Unrestricted))
2752 return true;
2754 return IsTypeAccessibleFromPartialTrust(t);
2757 internal static bool IsTypeAccessibleFromPartialTrust(Type t) {
2758 Assembly assembly = t.Assembly;
2760 if (assembly.SecurityRuleSet == SecurityRuleSet.Level1) {
2761 // Level 1 CAS uses transparency as an auditing mechanism rather than an enforcement mechanism, so we can't
2762 // perform a transparency check. Instead, allow the call to go through if:
2763 // (a) the referenced assembly is partially trusted, hence it cannot do anything dangerous; or
2764 // (b) the assembly is fully trusted and has APTCA.
2765 return (!assembly.IsFullyTrusted || HasAPTCABit(assembly));
2767 else {
2768 // ** TEMPORARY **
2769 // Some GACed assemblies register critical modules / handlers. We can't break these scenarios for .NET 4.5, but we should
2770 // remove this APTCA check when we fix DevDiv #85358 and use only the transparency check defined below.
2771 if (HasAPTCABit(assembly)) {
2772 return true;
2774 // ** END TEMPORARY **
2776 // Level 2 CAS uses transparency as an enforcement mechanism, so we can perform a transparency check.
2777 // Transparent and SafeCritical types are safe to use from partial trust code.
2778 return (t.IsSecurityTransparent || t.IsSecuritySafeCritical);
2782 internal static FileChangesMonitor FileChangesMonitor {
2783 get { return _theRuntime._fcm; }
2786 internal static RequestTimeoutManager RequestTimeoutManager {
2787 get { return _theRuntime._timeoutManager; }
2791 /// <devdoc>
2792 /// <para>Provides access to the cache.</para>
2793 /// </devdoc>
2794 public static Cache Cache {
2795 get {
2797 if (HttpRuntime.AspInstallDirectoryInternal == null) {
2798 throw new HttpException(SR.GetString(SR.Aspnet_not_installed, VersionInfo.SystemWebVersion));
2801 Cache cachePublic = _theRuntime._cachePublic;
2802 if (cachePublic == null) {
2803 lock (_theRuntime) {
2804 cachePublic = _theRuntime._cachePublic;
2805 if (cachePublic == null) {
2806 // Create the CACHE object
2807 cachePublic = new Caching.Cache(0);
2808 _theRuntime._cachePublic = cachePublic;
2813 return cachePublic;
2817 /// <devdoc>
2818 /// <para>[To be supplied.]</para>
2819 /// </devdoc>
2820 public static string AspInstallDirectory {
2821 get {
2822 String path = AspInstallDirectoryInternal;
2824 if (path == null) {
2825 throw new HttpException(SR.GetString(SR.Aspnet_not_installed, VersionInfo.SystemWebVersion));
2828 InternalSecurityPermissions.PathDiscovery(path).Demand();
2829 return path;
2833 internal static string AspInstallDirectoryInternal {
2834 get { return s_installDirectory; }
2838 // Return the client script virtual path, e.g. "/aspnet_client/system_web/2_0_50217"
2840 public static string AspClientScriptVirtualPath {
2841 get {
2842 if (_theRuntime._clientScriptVirtualPath == null) {
2843 string aspNetVersion = VersionInfo.SystemWebVersion;
2844 string clientScriptVirtualPath = AspNetClientFilesParentVirtualPath + aspNetVersion.Substring(0, aspNetVersion.LastIndexOf('.')).Replace('.', '_');
2846 _theRuntime._clientScriptVirtualPath = clientScriptVirtualPath;
2849 return _theRuntime._clientScriptVirtualPath;
2853 public static string AspClientScriptPhysicalPath {
2854 get {
2855 String path = AspClientScriptPhysicalPathInternal;
2857 if (path == null) {
2858 throw new HttpException(SR.GetString(SR.Aspnet_not_installed, VersionInfo.SystemWebVersion));
2861 return path;
2866 // Return the client script physical path, e.g. @"c:\windows\microsoft.net\framework\v2.0.50217.0\asp.netclientfiles"
2868 internal static string AspClientScriptPhysicalPathInternal {
2869 get {
2870 if (_theRuntime._clientScriptPhysicalPath == null) {
2871 string clientScriptPhysicalPath = System.IO.Path.Combine(AspInstallDirectoryInternal, AspNetClientFilesSubDirectory);
2873 _theRuntime._clientScriptPhysicalPath = clientScriptPhysicalPath;
2876 return _theRuntime._clientScriptPhysicalPath;
2881 /// <devdoc>
2882 /// <para>[To be supplied.]</para>
2883 /// </devdoc>
2884 public static string ClrInstallDirectory {
2885 get {
2886 String path = ClrInstallDirectoryInternal;
2887 InternalSecurityPermissions.PathDiscovery(path).Demand();
2888 return path;
2892 internal static string ClrInstallDirectoryInternal {
2893 get { return HttpConfigurationSystem.MsCorLibDirectory; }
2898 /// <devdoc>
2899 /// <para>[To be supplied.]</para>
2900 /// </devdoc>
2901 public static string MachineConfigurationDirectory {
2902 get {
2903 String path = MachineConfigurationDirectoryInternal;
2904 InternalSecurityPermissions.PathDiscovery(path).Demand();
2905 return path;
2909 internal static string MachineConfigurationDirectoryInternal {
2910 get { return HttpConfigurationSystem.MachineConfigurationDirectory; }
2913 internal static bool IsEngineLoaded {
2914 get { return s_isEngineLoaded; }
2919 // Static app domain related properties
2923 /// <devdoc>
2924 /// <para>[To be supplied.]</para>
2925 /// </devdoc>
2926 public static String CodegenDir {
2927 get {
2928 String path = CodegenDirInternal;
2929 InternalSecurityPermissions.PathDiscovery(path).Demand();
2930 return path;
2934 internal static string CodegenDirInternal {
2935 get { return _theRuntime._codegenDir; }
2938 internal static string TempDirInternal {
2939 get { return _theRuntime._tempDir; }
2943 /// <devdoc>
2944 /// <para>[To be supplied.]</para>
2945 /// </devdoc>
2946 public static String AppDomainAppId {
2947 get {
2948 return _theRuntime._appDomainAppId;
2952 internal static bool IsAspNetAppDomain {
2953 get { return AppDomainAppId != null; }
2958 /// <devdoc>
2959 /// <para>[To be supplied.]</para>
2960 /// </devdoc>
2961 public static String AppDomainAppPath {
2962 get {
2963 InternalSecurityPermissions.AppPathDiscovery.Demand();
2964 return AppDomainAppPathInternal;
2968 internal static string AppDomainAppPathInternal {
2969 get { return _theRuntime._appDomainAppPath; }
2973 /// <devdoc>
2974 /// <para>[To be supplied.]</para>
2975 /// </devdoc>
2976 public static String AppDomainAppVirtualPath {
2977 get {
2978 return VirtualPath.GetVirtualPathStringNoTrailingSlash(_theRuntime._appDomainAppVPath);
2982 // Save as AppDomainAppVirtualPath, but includes the trailng slash. We can't change
2983 // AppDomainAppVirtualPath since it's public.
2984 internal static String AppDomainAppVirtualPathString {
2985 get {
2986 return VirtualPath.GetVirtualPathString(_theRuntime._appDomainAppVPath);
2990 internal static VirtualPath AppDomainAppVirtualPathObject {
2991 get {
2992 return _theRuntime._appDomainAppVPath;
2996 internal static bool IsPathWithinAppRoot(String path) {
2997 if (AppDomainIdInternal == null)
2998 return true; // app domain not initialized
3000 return UrlPath.IsEqualOrSubpath(AppDomainAppVirtualPathString, path);
3004 /// <devdoc>
3005 /// <para>[To be supplied.]</para>
3006 /// </devdoc>
3007 public static String AppDomainId {
3008 [AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.High)]
3009 get {
3010 return AppDomainIdInternal;
3014 internal static string AppDomainIdInternal {
3015 get { return _theRuntime._appDomainId; }
3020 /// <devdoc>
3021 /// <para>[To be supplied.]</para>
3022 /// </devdoc>
3023 public static String BinDirectory {
3024 get {
3025 String path = BinDirectoryInternal;
3026 InternalSecurityPermissions.PathDiscovery(path).Demand();
3027 return path;
3031 internal static string BinDirectoryInternal {
3032 get { return Path.Combine(_theRuntime._appDomainAppPath, BinDirectoryName) + Path.DirectorySeparatorChar; }
3036 internal static VirtualPath CodeDirectoryVirtualPath {
3037 get { return _theRuntime._appDomainAppVPath.SimpleCombineWithDir(CodeDirectoryName); }
3040 internal static VirtualPath ResourcesDirectoryVirtualPath {
3041 get { return _theRuntime._appDomainAppVPath.SimpleCombineWithDir(ResourcesDirectoryName); }
3044 internal static VirtualPath WebRefDirectoryVirtualPath {
3045 get { return _theRuntime._appDomainAppVPath.SimpleCombineWithDir(WebRefDirectoryName); }
3049 /// <devdoc>
3050 /// <para>[To be supplied.]</para>
3051 /// </devdoc>
3052 public static bool IsOnUNCShare {
3053 [AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Low)]
3054 get {
3055 return IsOnUNCShareInternal;
3059 internal static bool IsOnUNCShareInternal {
3060 get { return _theRuntime._isOnUNCShare; }
3065 // Static helper to retrieve app domain values
3068 private static String GetAppDomainString(String key) {
3069 Object x = Thread.GetDomain().GetData(key);
3071 return x as String;
3074 internal static void AddAppDomainTraceMessage(String message) {
3075 const String appDomainTraceKey = "ASP.NET Domain Trace";
3076 AppDomain d = Thread.GetDomain();
3077 String m = d.GetData(appDomainTraceKey) as String;
3078 d.SetData(appDomainTraceKey, (m != null) ? m + " ... " + message : message);
3081 // Gets the version of the ASP.NET framework the current web applications is targeting.
3082 // This property is normally set via the <httpRuntime> element's "targetFramework"
3083 // attribute. The property is not guaranteed to return a correct value if the current
3084 // AppDomain is not an ASP.NET web application AppDomain.
3085 public static Version TargetFramework {
3086 get {
3087 return BinaryCompatibility.Current.TargetFramework;
3093 // Flags
3096 internal static bool DebuggingEnabled {
3097 get { return _theRuntime._debuggingEnabled; }
3100 internal static bool ConfigInited {
3101 get { return _theRuntime._configInited; }
3104 internal static bool FusionInited {
3105 get { return _theRuntime._fusionInited; }
3108 internal static bool ApartmentThreading {
3109 get { return _theRuntime._apartmentThreading; }
3112 internal static bool ShutdownInProgress {
3113 get { return _theRuntime._shutdownInProgress; }
3116 internal static string TrustLevel {
3117 get { return _theRuntime._trustLevel; }
3120 internal static string WpUserId {
3121 get { return _theRuntime._wpUserId; }
3125 private void SetTrustLevel(TrustSection trustSection, SecurityPolicySection securityPolicySection) {
3126 // Use a temporary variable, since we use the field as a signal that the trust has really
3127 // been set, which is not the case until later in this method.
3128 string trustLevel = trustSection.Level;
3130 if (trustSection.Level == "Full") {
3131 _trustLevel = trustLevel;
3132 return;
3135 if (securityPolicySection == null || securityPolicySection.TrustLevels[trustSection.Level] == null) {
3136 throw new ConfigurationErrorsException(SR.GetString(SR.Unable_to_get_policy_file, trustSection.Level), String.Empty, 0);
3137 // Do not give out configuration information since we don't know what trust level we are
3138 // supposed to be running at. If the information below is added to the error it might expose
3139 // part of the config file that the users does not have permissions to see. VS261145
3140 // ,trustSection.ElementInformation.Properties["level"].Source,
3141 // trustSection.ElementInformation.Properties["level"].LineNumber);
3143 String file = null;
3144 if (trustSection.Level == "Minimal" || trustSection.Level == "Low" ||
3145 trustSection.Level == "Medium" || trustSection.Level == "High") {
3146 file = (String)securityPolicySection.TrustLevels[trustSection.Level].LegacyPolicyFileExpanded;
3148 else {
3149 file = (String)securityPolicySection.TrustLevels[trustSection.Level].PolicyFileExpanded;
3151 if (file == null || !FileUtil.FileExists(file)) {
3152 //if HttpContext.Current.IsCustomErrorEnabled
3153 throw new HttpException(SR.GetString(SR.Unable_to_get_policy_file, trustSection.Level));
3154 //else
3155 // throw new ConfigurationErrorsException(SR.GetString(SR.Unable_to_get_policy_file, trustSection.Level),
3156 // trustSection.Filename, trustSection.LineNumber);
3159 bool foundGacToken = false;
3160 #pragma warning disable 618
3161 PolicyLevel policyLevel = CreatePolicyLevel(file, AppDomainAppPathInternal, CodegenDirInternal, trustSection.OriginUrl, out foundGacToken);
3163 // see if the policy file contained a v1.x UrlMembershipCondition containing
3164 // a GAC token. If so, let's upgrade it by adding a code group granting
3165 // full trust to code from the GAC
3166 if (foundGacToken) {
3167 // walk the code groups at the app domain level and look for one that grants
3168 // access to the GAC with an UrlMembershipCondition.
3169 CodeGroup rootGroup = policyLevel.RootCodeGroup;
3170 bool foundGacCondition = false;
3171 foreach (CodeGroup childGroup in rootGroup.Children) {
3172 if (childGroup.MembershipCondition is GacMembershipCondition) {
3173 foundGacCondition = true;
3175 // if we found the GAC token and also have the GacMembershipCondition
3176 // the policy file needs to be upgraded to just include the GacMembershipCondition
3177 Debug.Assert(!foundGacCondition);
3178 break;
3182 // add one as a child of the toplevel group after
3183 // some sanity checking to make sure it's an ASP.NET policy file
3184 // which always begins with a FirstMatchCodeGroup granting nothing
3185 // this might not upgrade some custom policy files
3186 if (!foundGacCondition) {
3187 if (rootGroup is FirstMatchCodeGroup) {
3188 FirstMatchCodeGroup firstMatch = (FirstMatchCodeGroup)rootGroup;
3189 if (firstMatch.MembershipCondition is AllMembershipCondition &&
3190 firstMatch.PermissionSetName == "Nothing") {
3191 PermissionSet fullTrust = new PermissionSet(PermissionState.Unrestricted);
3193 CodeGroup gacGroup = new UnionCodeGroup(new GacMembershipCondition(),
3194 new PolicyStatement(fullTrust));
3197 // now, walk the current groups and insert our new group
3198 // immediately before the old Gac group
3199 // we'll need to use heuristics for this:
3200 // it will be an UrlMembershipCondition group with full trust
3201 CodeGroup newRoot = new FirstMatchCodeGroup(rootGroup.MembershipCondition, rootGroup.PolicyStatement);
3202 foreach (CodeGroup childGroup in rootGroup.Children) {
3204 // is this the target old $Gac$ group?
3205 // insert our new GacMembershipCondition group ahead of it
3206 if ((childGroup is UnionCodeGroup) &&
3207 (childGroup.MembershipCondition is UrlMembershipCondition) &&
3208 childGroup.PolicyStatement.PermissionSet.IsUnrestricted()) {
3209 if (null != gacGroup) {
3210 newRoot.AddChild(gacGroup);
3211 gacGroup = null;
3215 // append this group to the root group
3216 // AddChild itself does a deep Copy to get any
3217 // child groups so we don't need one here
3218 newRoot.AddChild(childGroup);
3221 policyLevel.RootCodeGroup = newRoot;
3222 //Debug.Trace("internal", "PolicyLevel: " + policyLevel.ToXml());
3226 #pragma warning restore 618
3230 #pragma warning disable 618
3231 AppDomain.CurrentDomain.SetAppDomainPolicy(policyLevel);
3232 _namedPermissionSet = policyLevel.GetNamedPermissionSet(trustSection.PermissionSetName);
3233 #pragma warning restore 618
3235 _trustLevel = trustLevel;
3237 _fcm.StartMonitoringFile(file, new FileChangeEventHandler(this.OnSecurityPolicyFileChange));
3240 #pragma warning disable 618
3241 private static PolicyLevel CreatePolicyLevel(String configFile, String appDir, String binDir, String strOriginUrl, out bool foundGacToken) {
3242 // Read in the config file to a string.
3243 FileStream file = new FileStream(configFile, FileMode.Open, FileAccess.Read);
3244 StreamReader reader = new StreamReader(file, Encoding.UTF8);
3245 String strFileData = reader.ReadToEnd();
3247 reader.Close();
3249 appDir = FileUtil.RemoveTrailingDirectoryBackSlash(appDir);
3250 binDir = FileUtil.RemoveTrailingDirectoryBackSlash(binDir);
3252 strFileData = strFileData.Replace("$AppDir$", appDir);
3253 strFileData = strFileData.Replace("$AppDirUrl$", MakeFileUrl(appDir));
3254 strFileData = strFileData.Replace("$CodeGen$", MakeFileUrl(binDir));
3255 if (strOriginUrl == null)
3256 strOriginUrl = String.Empty;
3257 strFileData = strFileData.Replace("$OriginHost$", strOriginUrl);
3259 // see if the file contains a GAC token
3260 // if so, do the replacement and record the
3261 // fact so that we later add a GacMembershipCondition
3262 // codegroup to the PolicyLevel
3263 int ndx = strFileData.IndexOf("$Gac$", StringComparison.Ordinal);
3264 if (ndx != -1) {
3265 string gacLocation = GetGacLocation();
3266 if (gacLocation != null)
3267 gacLocation = MakeFileUrl(gacLocation);
3268 if (gacLocation == null)
3269 gacLocation = String.Empty;
3271 strFileData = strFileData.Replace("$Gac$", gacLocation);
3272 foundGacToken = true;
3274 else {
3275 foundGacToken = false;
3278 return SecurityManager.LoadPolicyLevelFromString(strFileData, PolicyLevelType.AppDomain);
3280 #pragma warning restore 618
3282 private void SetTrustParameters(TrustSection trustSection, SecurityPolicySection securityPolicySection, PolicyLevel policyLevel) {
3283 _trustLevel = trustSection.Level;
3284 if (_trustLevel != "Full") {
3285 // if we are in partial trust, HostingEnvironment should init HttpRuntime with a non-null PolicyLevel object
3286 Debug.Assert(policyLevel != null);
3288 _namedPermissionSet = policyLevel.GetNamedPermissionSet(trustSection.PermissionSetName);
3289 _policyLevel = policyLevel;
3290 _hostSecurityPolicyResolverType = trustSection.HostSecurityPolicyResolverType;
3291 String file = (String)securityPolicySection.TrustLevels[trustSection.Level].PolicyFileExpanded;
3292 _fcm.StartMonitoringFile(file, new FileChangeEventHandler(this.OnSecurityPolicyFileChange));
3297 * Notification when something in the code-access security policy file changed
3299 private void OnSecurityPolicyFileChange(Object sender, FileChangeEvent e) {
3300 // shutdown the app domain
3301 Debug.Trace("AppDomainFactory", "Shutting down appdomain because code-access security policy file changed");
3302 string message = FileChangesMonitor.GenerateErrorMessage(e.Action, e.FileName);
3303 if (message == null) {
3304 message = "Change in code-access security policy file";
3306 ShutdownAppDomain(ApplicationShutdownReason.ChangeInSecurityPolicyFile,
3307 message);
3311 // notification when app_offline.htm file changed or created
3312 private void OnAppOfflineFileChange(Object sender, FileChangeEvent e) {
3313 // shutdown the app domain
3314 Debug.Trace("AppOffline", AppOfflineFileName + " changed - shutting down the app domain");
3315 Debug.Trace("AppDomainFactory", "Shutting down appdomain because " + AppOfflineFileName + " file changed");
3316 // WOS 1948399: set _userForcedShutdown to avoid DelayNotificationTimeout, since first request has not completed yet in integrated mode;
3317 SetUserForcedShutdown();
3318 string message = FileChangesMonitor.GenerateErrorMessage(e.Action, AppOfflineFileName);
3319 if (message == null) {
3320 message = "Change in " + AppOfflineFileName;
3322 ShutdownAppDomain(ApplicationShutdownReason.ConfigurationChange, message);
3325 internal static String MakeFileUrl(String path) {
3326 Uri uri = new Uri(path);
3327 return uri.ToString();
3330 internal static String GetGacLocation() {
3332 StringBuilder buf = new StringBuilder(262);
3333 int iSize = 260;
3337 if (UnsafeNativeMethods.GetCachePath(2, buf, ref iSize) >= 0)
3338 return buf.ToString();
3339 throw new HttpException(SR.GetString(SR.GetGacLocaltion_failed));
3344 * Remove from metabase all read/write/browse permission from certain subdirs
3347 internal static void RestrictIISFolders(HttpContext context) {
3348 int ret;
3350 HttpWorkerRequest wr = context.WorkerRequest;
3352 Debug.Assert(AppDomainAppId != null);
3354 // Don't do it if we are not running on IIS
3355 if (wr == null || !(wr is System.Web.Hosting.ISAPIWorkerRequest)) {
3356 return;
3359 // Do it only for IIS 5
3360 #if !FEATURE_PAL // FEATURE_PAL does not enable IIS-based hosting features
3361 if (!(wr is System.Web.Hosting.ISAPIWorkerRequestInProcForIIS6))
3362 #endif // !FEATURE_PAL
3364 byte[] bufin;
3365 byte[] bufout = new byte[1]; // Just to keep EcbCallISAPI happy
3367 bufin = BitConverter.GetBytes(UnsafeNativeMethods.RESTRICT_BIN);
3368 ret = context.CallISAPI(UnsafeNativeMethods.CallISAPIFunc.RestrictIISFolders, bufin, bufout);
3369 if (ret != 1) {
3370 // Cannot pass back any HR from inetinfo.exe because CSyncPipeManager::GetDataFromIIS
3371 // does not support passing back any value when there is an error.
3372 Debug.Trace("RestrictIISFolders", "Cannot restrict folder access for '" + AppDomainAppId + "'.");
3378 // Helper to create instances (public vs. internal/private ctors, see 89781)
3381 internal static Object CreateNonPublicInstance(Type type) {
3382 return CreateNonPublicInstance(type, null);
3385 [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
3386 internal static Object CreateNonPublicInstance(Type type, Object[] args) {
3387 return Activator.CreateInstance(
3388 type,
3389 BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.CreateInstance,
3390 null,
3391 args,
3392 null);
3395 internal static Object CreatePublicInstance(Type type) {
3396 return Activator.CreateInstance(type);
3399 #if !DONTUSEFACTORYGENERATOR
3400 // Cache instances of IWebObjectFactory for each Type, which allow us
3401 // to instantiate the objects very efficiently, compared to calling
3402 // Activator.CreateInstance on every call.
3403 private static FactoryGenerator s_factoryGenerator;
3404 private static Hashtable s_factoryCache;
3405 private static bool s_initializedFactory;
3406 private static object s_factoryLock = new Object();
3408 #endif // DONTUSEFACTORYGENERATOR
3411 * Faster implementation of CreatePublicInstance. It generates bits of IL
3412 * on the fly to achieve the improve performance. this should only be used
3413 * in cases where the number of different types to be created is well bounded.
3414 * Otherwise, we would create too much IL, which can bloat the process.
3416 internal static Object FastCreatePublicInstance(Type type) {
3418 #if DONTUSEFACTORYGENERATOR
3419 return CreatePublicInstance(type);
3420 #else
3422 // Only use the factory logic if the assembly is in the GAC, to avoid getting
3423 // assembly conflicts (VSWhidbey 405086)
3424 if (!type.Assembly.GlobalAssemblyCache) {
3425 return CreatePublicInstance(type);
3428 // Create the factory generator on demand
3429 if (!s_initializedFactory) {
3431 // Devdiv 90810 - Synchronize to avoid race condition
3432 lock (s_factoryLock) {
3433 if (!s_initializedFactory) {
3434 s_factoryGenerator = new FactoryGenerator();
3436 // Create the factory cache
3437 s_factoryCache = Hashtable.Synchronized(new Hashtable());
3439 s_initializedFactory = true;
3444 // First, check if it's cached
3445 IWebObjectFactory factory = (IWebObjectFactory)s_factoryCache[type];
3447 if (factory == null) {
3449 Debug.Trace("FastCreatePublicInstance", "Creating generator for type " + type.FullName);
3451 // Create the object factory
3452 factory = s_factoryGenerator.CreateFactory(type);
3454 // Cache the factory
3455 s_factoryCache[type] = factory;
3458 return factory.CreateInstance();
3459 #endif // DONTUSEFACTORYGENERATOR
3462 internal static Object CreatePublicInstance(Type type, Object[] args) {
3463 if (args == null)
3464 return Activator.CreateInstance(type);
3466 return Activator.CreateInstance(type, args);
3469 static string GetCurrentUserName() {
3470 try {
3471 return WindowsIdentity.GetCurrent().Name;
3473 catch {
3474 return null;
3478 void RaiseShutdownWebEventOnce() {
3479 if (!_shutdownWebEventRaised) {
3480 lock (this) {
3481 if (!_shutdownWebEventRaised) {
3482 // Raise Web Event
3483 WebBaseEvent.RaiseSystemEvent(this, WebEventCodes.ApplicationShutdown,
3484 WebApplicationLifetimeEvent.DetailCodeFromShutdownReason(ShutdownReason));
3486 _shutdownWebEventRaised = true;
3492 private static string _DefaultPhysicalPathOnMapPathFailure;
3493 private void RelaxMapPathIfRequired() {
3494 try {
3495 RuntimeConfig config = RuntimeConfig.GetAppConfig();
3496 if (config != null && config.HttpRuntime != null && config.HttpRuntime.RelaxedUrlToFileSystemMapping) {
3497 _DefaultPhysicalPathOnMapPathFailure = Path.Combine(_appDomainAppPath, "NOT_A_VALID_FILESYSTEM_PATH");
3499 } catch {}
3501 internal static bool IsMapPathRelaxed {
3502 get {
3503 return _DefaultPhysicalPathOnMapPathFailure != null;
3506 internal static string GetRelaxedMapPathResult(string originalResult) {
3507 if (!IsMapPathRelaxed) // Feature not enabled?
3508 return originalResult;
3510 if (originalResult == null) // null is never valid: Return the hard coded default physical path
3511 return _DefaultPhysicalPathOnMapPathFailure;
3513 // Does it contain an invalid file-path char?
3514 if (originalResult.IndexOfAny(s_InvalidPhysicalPathChars) >= 0)
3515 return _DefaultPhysicalPathOnMapPathFailure;
3517 // Final check: do the full check to ensure it is valid
3518 try {
3519 bool pathTooLong;
3520 if (FileUtil.IsSuspiciousPhysicalPath(originalResult, out pathTooLong) || pathTooLong)
3521 return _DefaultPhysicalPathOnMapPathFailure;
3522 } catch {
3523 return _DefaultPhysicalPathOnMapPathFailure;
3526 // it is valid
3527 return originalResult;
3532 public enum ApplicationShutdownReason {
3534 None = 0,
3536 HostingEnvironment = 1,
3538 ChangeInGlobalAsax = 2,
3540 ConfigurationChange = 3,
3542 UnloadAppDomainCalled = 4,
3544 ChangeInSecurityPolicyFile = 5,
3546 BinDirChangeOrDirectoryRename = 6,
3548 BrowsersDirChangeOrDirectoryRename = 7,
3550 CodeDirChangeOrDirectoryRename = 8,
3552 ResourcesDirChangeOrDirectoryRename = 9,
3554 IdleTimeout = 10,
3556 PhysicalApplicationPathChanged = 11,
3558 HttpRuntimeClose = 12,
3560 InitializationError = 13,
3562 MaxRecompilationsReached = 14,
3564 BuildManagerChange = 15,