1 //------------------------------------------------------------------------------
2 // <copyright file="HttpRuntime.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 //------------------------------------------------------------------------------
8 * The ASP.NET runtime services
10 * Copyright (c) 1998 Microsoft Corporation
13 namespace System
.Web
{
15 using System
.Collections
;
16 using System
.Configuration
;
18 using System
.Data
.Common
;
19 using System
.Diagnostics
.CodeAnalysis
;
20 using System
.Globalization
;
23 using System
.Reflection
;
24 using System
.Resources
;
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
;
34 using System
.Threading
;
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
;
43 using System
.Web
.Util
;
45 using Microsoft
.Win32
;
48 /// <para>Provides a set of ASP.NET runtime services.</para>
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
= { '/', '?', '*', '<', '>', '|', '"' }
;
79 // For s_forbiddenDirs and s_forbiddenDirsConstant, see
80 // ndll.h, and RestrictIISFolders in regiis.cxx
82 internal static string[] s_forbiddenDirs
= {
86 ResourcesDirectoryName
,
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
,
99 static HttpRuntime() {
100 AddAppDomainTraceMessage("*HttpRuntime::cctor");
104 _theRuntime
= new HttpRuntime();
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() {
129 // already initialized
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");
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
;
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
;
222 private bool _enableHeaderChecking
;
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
;
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
;
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() {
300 if (Environment
.OSVersion
.Platform
!= PlatformID
.Win32NT
)
301 throw new PlatformNotSupportedException(SR
.GetString(SR
.RequiresNT
));
302 #else // !FEATURE_PAL
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
);
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
);
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
) {
361 private void AppDomainShutdownTimerCallback(Object state
) {
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
) {
375 if (_appDomainShutdownTimer
== null && !_shutdownInProgress
) {
376 _appDomainShutdownTimer
= new Timer(
377 new TimerCallback(this.AppDomainShutdownTimerCallback
),
388 * Initialization from HostingEnvironment of HTTP independent features
390 private void HostingInit(HostingEnvironmentFlags hostingFlags
, PolicyLevel policyLevel
, Exception appDomainCreationException
) {
391 using (new ApplicationImpersonationContext()) {
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(
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
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
) {
474 _disableProcessRequestInApplicationTrust
= false;
476 // Set code access policy on the app domain
477 SetTrustLevel(trustSection
, securityPolicySection
);
480 // throw the original config exception if it exists
481 if (configInitException
!= null)
482 throw configInitException
;
486 else if ((hostingFlags
& HostingEnvironmentFlags
.ClientBuildManager
) != 0) {
487 _trustLevel
= "Full";
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()
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();
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();
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)
558 internal static Exception InitializationException
{
560 return _theRuntime
._initializationError
;
563 // The exception is "cached" for 10 seconds, then the AppDomain is restarted.
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
{
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
{
585 return _theRuntime
._enableHeaderChecking
;
589 internal static bool ProcessRequestInApplicationTrust
{
591 return _theRuntime
._processRequestInApplicationTrust
;
595 internal static bool DisableProcessRequestInApplicationTrust
{
597 return _theRuntime
._disableProcessRequestInApplicationTrust
;
601 internal static bool IsLegacyCas
{
603 return _theRuntime
._isLegacyCas
;
607 internal static byte[] AppOfflineMessage
{
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) {
621 HttpContext
.SetDebugAssertOnAccessToCurrent(true);
624 using (new ApplicationImpersonationContext()) {
625 // Is this necessary? See InitHttpConfiguration
626 CultureInfo savedCulture
= Thread
.CurrentThread
.CurrentCulture
;
627 CultureInfo savedUICulture
= Thread
.CurrentThread
.CurrentUICulture
;
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)
645 // configure the profiler according to config
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
;
671 Thread
.CurrentThread
.CurrentUICulture
= savedUICulture
;
672 SetCurrentThreadCultureWithAssert(savedCulture
);
676 catch (ConfigurationException e
) {
679 catch (Exception e
) {
680 // remember second-phase initialization error
681 error
= new HttpException(SR
.GetString(SR
.XSP_init_error
, e
.Message
), e
);
685 HttpContext
.SetDebugAssertOnAccessToCurrent(false);
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
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
) {
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
));
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
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
) {
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;
781 appConfig
= RuntimeConfig
.GetAppConfig();
783 catch (Exception e
) {
788 if (appConfig
!= null) {
790 cacheSection
= appConfig
.Cache
;
792 catch (Exception e
) {
793 if (initException
== null) {
799 if (cacheSection
== null) {
800 cacheSection
= appLKGConfig
.Cache
;
804 if (appConfig
!= null) {
806 trustSection
= appConfig
.Trust
;
808 catch (Exception e
) {
809 if (initException
== null) {
815 if (trustSection
== null) {
816 trustSection
= appLKGConfig
.Trust
;
819 // SecurityPolicy section
820 if (appConfig
!= null) {
822 securityPolicySection
= appConfig
.SecurityPolicy
;
824 catch (Exception e
) {
825 if (initException
== null) {
831 if (securityPolicySection
== null) {
832 securityPolicySection
= appLKGConfig
.SecurityPolicy
;
835 // Compilation section
836 if (appConfig
!= null) {
838 compilationSection
= appConfig
.Compilation
;
840 catch (Exception e
) {
841 if (initException
== null) {
847 if (compilationSection
== null) {
848 compilationSection
= appLKGConfig
.Compilation
;
851 // HostingEnvironment section
852 if (appConfig
!= null) {
854 hostingEnvironmentSection
= appConfig
.HostingEnvironment
;
856 catch (Exception e
) {
857 if (initException
== null) {
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();
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;
902 // Canonicalize it to avoid problems with spaces (VSWhidbey 229873)
903 tempDirectory
= new DirectoryInfo(tempDirectory
).FullName
;
906 tempDirectory
= null;
910 if (tempDirectory
== null) {
911 throw new ConfigurationErrorsException(
912 SR
.GetString(SR
.Invalid_temp_directory
, tempDirAttribName
),
913 configFileName
, configLineNumber
);
917 System
.UInt32 length
= 0;
918 StringBuilder sb
= null;
921 // Get the required length
922 bRet
= UnsafeNativeMethods
.GetUserTempDirectory(
923 UnsafeNativeMethods
.DeploymentDirectoryType
.ddtInstallationDependentDirectory
,
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
,
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
949 Directory
.CreateDirectory(tempDirectory
);
951 catch (Exception e
) {
952 throw new ConfigurationErrorsException(
953 SR
.GetString(SR
.Invalid_temp_directory
, tempDirAttribName
),
955 configFileName
, configLineNumber
);
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
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
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
);
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
);
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
);
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
);
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
;
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
;
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
)
1153 // Get the path to the bin directory
1154 string binPath
= HttpRuntime
.BinDirectoryInternal
;
1156 DirectoryInfo binPathDirectory
= new DirectoryInfo(binPath
);
1158 if (!binPathDirectory
.Exists
)
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); }
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() {
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
);
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
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
;
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;
1269 appOfflineFileFound
= true;
1270 _theRuntime
._appOfflineMessage
= new byte[0];
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
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
1368 Buffer
.BlockCopy(bKeysStored
, 0, s_autogenKeys
, 0, s_autogenKeys
.Length
);
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
) {
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
{
1406 // DevDivBugs 190952: public method for querying runtime pipeline mode
1407 public static bool UsingIntegratedPipeline
{
1409 return UseIntegratedPipeline
;
1413 internal static bool UseIntegratedPipeline
{
1415 return _useIntegratedPipeline
;
1419 internal static bool EnablePrefetchOptimization
{
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
;
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
;
1449 Debug
.Trace("PipelineRuntime", "HttpRuntime::ProcessRequestNotificationPrivate: notification=" + context
.CurrentNotification
.ToString()
1450 + ", isPost=" + context
.IsPostNotification
1451 + ", moduleIndex=" + context
.CurrentModuleIndex
);
1454 IHttpHandler handler
= null;
1455 if (context
.NeedToInitializeApp()) {
1457 Debug
.Trace("FileChangesMonitorIgnoreSubdirChange",
1458 "*** FirstNotification " + DateTime
.Now
.ToString("hh:mm:ss.fff", CultureInfo
.InvariantCulture
)
1459 + ": _appDomainAppId=" + _appDomainAppId
);
1461 // First request initialization
1463 EnsureFirstRequestInit(context
);
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
) {
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
;
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) {
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
;
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
);
1521 Debug
.Trace("PipelineRuntime", "HttpRuntime::ProcessRequestNotificationPrivate: status=" + status
.ToString());
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
);
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
);
1561 context
.Response
.UpdateNativeResponse(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
;
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
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);
1636 Interlocked
.Decrement(ref _activeRequestCount
);
1641 // Construct the Context on HttpWorkerRequest, hook everything together
1642 HttpContext context
;
1645 context
= new HttpContext(wr
, false /* initResponseWriter */);
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);
1659 Interlocked
.Decrement(ref _activeRequestCount
);
1663 wr
.SetEndOfSendNotification(_asyncEndOfSendCallback
, context
);
1665 HostingEnvironment
.IncrementBusyCount();
1668 // First request initialization
1670 EnsureFirstRequestInit(context
);
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
) {
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
);
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
);
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();
1721 context
.Response
.InitResponseWriter();
1722 FinishRequest(wr
, context
, null);
1725 PerfCounters
.IncrementGlobalCounter(GlobalPerfCounter
.REQUESTS_REJECTED
);
1726 PerfCounters
.IncrementCounter(AppPerfCounter
.APP_REQUESTS_REJECTED
);
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
1756 // impersonate around PreSendHeaders / PreSendContent
1757 using (new ClientImpersonationContext(context
, false)) {
1759 // this sends the actual content in most cases
1760 response
.FinalFlushAtTheEndOfRequestProcessing();
1762 catch (Exception eFlush
) {
1768 // Report error if any
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) {
1778 ReportAppOfflineErrorMessage(response
, _appOfflineMessage
);
1779 response
.FinalFlushAtTheEndOfRequestProcessing();
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()) {
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();
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
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
)
1851 if (_shutdownInProgress
)
1853 _shutdownInProgress
= true;
1860 // Shutdown this and restart new app domain
1862 [PermissionSet(SecurityAction
.Assert
, Unrestricted
= true)]
1863 private void ReleaseResourcesAndUnloadAppDomain(Object state
/*not used*/) {
1865 Debug
.Trace("FileChangesMonitorIgnoreSubdirChange",
1866 "*** ReleaseResourcesAndUnloadAppDomain " + DateTime
.Now
.ToString("hh:mm:ss.fff", CultureInfo
.InvariantCulture
)
1867 + ": _appDomainAppId=" + _appDomainAppId
);
1869 Debug
.Trace("AppDomainFactory", "ReleaseResourcesAndUnloadAppDomain, Id=" + _appDomainAppId
1870 + " DomainId = " + _appDomainId
1871 + " Stack = " + Environment
.StackTrace
);
1874 PerfCounters
.IncrementGlobalCounter(GlobalPerfCounter
.APPLICATION_RESTARTS
);
1879 // Release all resources
1888 AddAppDomainTraceMessage("before Unload");
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
);
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
);
1927 case 404: // Not found
1928 case 414: // Not found
1929 PerfCounters
.IncrementCounter(AppPerfCounter
.REQUESTS_NOT_FOUND
);
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
);
1944 if (_activeRequestCount
== 0 && (_requestQueue
== null || _requestQueue
.IsEmpty
))
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
;
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();
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();
1996 // wait for all active requests to complete
1997 while (_activeRequestCount
!= 0) {
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) {
2025 if (iCache
!= null) {
2030 // app on end, cleanup app instances
2031 HttpApplicationFactory
.EndApplication(); // call app_onEnd
2033 // stop file changes monitor
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
) {
2045 OnRequestNotificationCompletionHelper(ar
);
2047 catch(Exception e
) {
2048 ApplicationManager
.RecordFatalException(e
);
2053 private void OnRequestNotificationCompletionHelper(IAsyncResult ar
) {
2054 if (ar
.CompletedSynchronously
) {
2055 Debug
.Trace("PipelineRuntime", "OnRequestNotificationCompletion: completed synchronously");
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
;
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
;
2096 context
.AsyncAppHandler
.EndProcessRequest(ar
);
2098 catch (Exception e
) {
2099 context
.AddError(e
);
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
;
2165 HttpRuntimeSection config
= RuntimeConfig
.GetAppLKGConfig().HttpRuntime
;
2166 if (config
!= null) {
2167 waitChangeNotification
= config
.WaitChangeNotification
;
2168 maxWaitChangeNotification
= config
.MaxWaitChangeNotification
;
2174 if (waitChangeNotification
== 0 || maxWaitChangeNotification
== 0)
2177 DateTime maxWait
= DateTime
.UtcNow
.AddSeconds(maxWaitChangeNotification
);
2178 // Coalesce file change notifications
2180 while (DateTime
.UtcNow
< maxWait
) {
2181 if (DateTime
.UtcNow
> _theRuntime
.LastShutdownAttemptTime
.AddSeconds(waitChangeNotification
))
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
) {
2222 Debug
.Trace("FileChangesMonitorIgnoreSubdirChange",
2223 "*** ShutdownAppDomain " + DateTime
.Now
.ToString("hh:mm:ss.fff", CultureInfo
.InvariantCulture
)
2224 + ": _appDomainAppId=" + HttpRuntime
.AppDomainAppId
);
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
;
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
);
2251 _theRuntime
.RaiseShutdownWebEventOnce();
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();
2266 //WOS 1400290: CantUnloadAppDomainException in ISAPI mode, wait until HostingEnvironment.ShutdownThisAppDomainOnce completes
2267 if (HostingEnvironment
.ShutdownInProgress
) {
2271 // Make sure we don't go through shutdown logic many times
2272 if (!_theRuntime
.InitiateShutdownOnce())
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();
2284 _theRuntime
._shutDownStack
= Environment
.StackTrace
;
2287 CodeAccessPermission
.RevertAssert();
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
);
2303 internal static void RecoverFromUnexceptedAppDomainUnload() {
2304 if (_theRuntime
._shutdownInProgress
)
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
2313 ISAPIRuntime
.RemoveThisAppDomainFromUnmanagedTable();
2314 PipelineRuntime
.RemoveThisAppDomainFromUnmanagedTable();
2315 AddAppDomainTraceMessage("AppDomainRestart");
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
;
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
2364 /// <para><SPAN>The method that drives
2365 /// all ASP.NET web processing execution.</SPAN></para>
2367 [AspNetHostingPermission(SecurityAction
.Demand
, Level
= AspNetHostingPermissionLevel
.Medium
)]
2368 public static void ProcessRequest(HttpWorkerRequest wr
) {
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
);
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
);
2419 /// <para>Removes all items from the cache and shuts down the runtime.</para>
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();
2432 _theRuntime
.Dispose();
2439 /// <para>Unloads the current app domain.</para>
2441 public static void UnloadAppDomain() {
2442 _theRuntime
._userForcedShutdown
= true;
2443 ShutdownAppDomain(ApplicationShutdownReason
.UnloadAppDomainCalled
, "User code called UnloadAppDomain");
2446 private DateTime LastShutdownAttemptTime
{
2450 dt
= _lastShutdownAttemptTime
;
2456 _lastShutdownAttemptTime
= value;
2461 internal static Profiler Profile
{
2463 return _theRuntime
._profiler
;
2467 internal static bool IsTrustLevelInitialized
{
2469 return !HostingEnvironment
.IsHosted
|| TrustLevel
!= null;
2473 internal static NamedPermissionSet NamedPermissionSet
{
2475 // Make sure we have already initialized the trust level
2479 return _theRuntime
._namedPermissionSet
;
2483 internal static PolicyLevel PolicyLevel
{
2485 return _theRuntime
._policyLevel
;
2489 internal static string HostSecurityPolicyResolverType
{
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) {
2502 return new NamedPermissionSet(namedPermissionSet
);
2506 internal static bool IsFullTrust
{
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) {
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)
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;
2562 if (!writePermissions
)
2563 askedPermission
= new FileIOPermission(FileIOPermissionAccess
.Read
, path
);
2565 askedPermission
= new FileIOPermission(FileIOPermissionAccess
.AllAccess
, path
);
2568 // This could happen if the path is not absolute
2571 fAccess
= askedPermission
.IsSubsetOf(allowedPermission
);
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)
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;
2593 askedPermission
= new WebPermission(NetworkAccess
.Connect
, uri
.ToString());
2598 fAccess
= askedPermission
.IsSubsetOf(allowedPermission
);
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)
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
);
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) {
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)
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
);
2655 internal static bool HasAppPathDiscoveryPermission() {
2656 return HasPathDiscoveryPermission(HttpRuntime
.AppDomainAppPathInternal
);
2659 internal static string GetSafePath(string path
) {
2660 if (String
.IsNullOrEmpty(path
))
2664 if (HasPathDiscoveryPermission(path
)) // could throw on bad filenames
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)
2685 SecurityPermission securityPermission
= (SecurityPermission
)NamedPermissionSet
.GetPermission(
2686 typeof(SecurityPermission
));
2687 if (securityPermission
== null)
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)
2704 AspNetHostingPermission permission
= (AspNetHostingPermission
)NamedPermissionSet
.GetPermission(
2705 typeof(AspNetHostingPermission
));
2706 if (permission
== null)
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
);
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
),
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
))
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
));
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
)) {
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; }
2792 /// <para>Provides access to the cache.</para>
2794 public static Cache Cache
{
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
;
2818 /// <para>[To be supplied.]</para>
2820 public static string AspInstallDirectory
{
2822 String path
= AspInstallDirectoryInternal
;
2825 throw new HttpException(SR
.GetString(SR
.Aspnet_not_installed
, VersionInfo
.SystemWebVersion
));
2828 InternalSecurityPermissions
.PathDiscovery(path
).Demand();
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
{
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
{
2855 String path
= AspClientScriptPhysicalPathInternal
;
2858 throw new HttpException(SR
.GetString(SR
.Aspnet_not_installed
, VersionInfo
.SystemWebVersion
));
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
{
2870 if (_theRuntime
._clientScriptPhysicalPath
== null) {
2871 string clientScriptPhysicalPath
= System
.IO
.Path
.Combine(AspInstallDirectoryInternal
, AspNetClientFilesSubDirectory
);
2873 _theRuntime
._clientScriptPhysicalPath
= clientScriptPhysicalPath
;
2876 return _theRuntime
._clientScriptPhysicalPath
;
2882 /// <para>[To be supplied.]</para>
2884 public static string ClrInstallDirectory
{
2886 String path
= ClrInstallDirectoryInternal
;
2887 InternalSecurityPermissions
.PathDiscovery(path
).Demand();
2892 internal static string ClrInstallDirectoryInternal
{
2893 get { return HttpConfigurationSystem.MsCorLibDirectory; }
2899 /// <para>[To be supplied.]</para>
2901 public static string MachineConfigurationDirectory
{
2903 String path
= MachineConfigurationDirectoryInternal
;
2904 InternalSecurityPermissions
.PathDiscovery(path
).Demand();
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
2924 /// <para>[To be supplied.]</para>
2926 public static String CodegenDir
{
2928 String path
= CodegenDirInternal
;
2929 InternalSecurityPermissions
.PathDiscovery(path
).Demand();
2934 internal static string CodegenDirInternal
{
2935 get { return _theRuntime._codegenDir; }
2938 internal static string TempDirInternal
{
2939 get { return _theRuntime._tempDir; }
2944 /// <para>[To be supplied.]</para>
2946 public static String AppDomainAppId
{
2948 return _theRuntime
._appDomainAppId
;
2952 internal static bool IsAspNetAppDomain
{
2953 get { return AppDomainAppId != null; }
2959 /// <para>[To be supplied.]</para>
2961 public static String AppDomainAppPath
{
2963 InternalSecurityPermissions
.AppPathDiscovery
.Demand();
2964 return AppDomainAppPathInternal
;
2968 internal static string AppDomainAppPathInternal
{
2969 get { return _theRuntime._appDomainAppPath; }
2974 /// <para>[To be supplied.]</para>
2976 public static String AppDomainAppVirtualPath
{
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
{
2986 return VirtualPath
.GetVirtualPathString(_theRuntime
._appDomainAppVPath
);
2990 internal static VirtualPath AppDomainAppVirtualPathObject
{
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
);
3005 /// <para>[To be supplied.]</para>
3007 public static String AppDomainId
{
3008 [AspNetHostingPermission(SecurityAction
.Demand
, Level
= AspNetHostingPermissionLevel
.High
)]
3010 return AppDomainIdInternal
;
3014 internal static string AppDomainIdInternal
{
3015 get { return _theRuntime._appDomainId; }
3021 /// <para>[To be supplied.]</para>
3023 public static String BinDirectory
{
3025 String path
= BinDirectoryInternal
;
3026 InternalSecurityPermissions
.PathDiscovery(path
).Demand();
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); }
3050 /// <para>[To be supplied.]</para>
3052 public static bool IsOnUNCShare
{
3053 [AspNetHostingPermission(SecurityAction
.Demand
, Level
= AspNetHostingPermissionLevel
.Low
)]
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
);
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
{
3087 return BinaryCompatibility
.Current
.TargetFramework
;
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
;
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);
3144 if (trustSection
.Level
== "Minimal" || trustSection
.Level
== "Low" ||
3145 trustSection
.Level
== "Medium" || trustSection
.Level
== "High") {
3146 file
= (String
)securityPolicySection
.TrustLevels
[trustSection
.Level
].LegacyPolicyFileExpanded
;
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
));
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
);
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
);
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();
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
);
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;
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
,
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);
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
) {
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
)) {
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
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
);
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(
3389 BindingFlags
.Instance
| BindingFlags
.NonPublic
| BindingFlags
.Public
| BindingFlags
.CreateInstance
,
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
);
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
) {
3464 return Activator
.CreateInstance(type
);
3466 return Activator
.CreateInstance(type
, args
);
3469 static string GetCurrentUserName() {
3471 return WindowsIdentity
.GetCurrent().Name
;
3478 void RaiseShutdownWebEventOnce() {
3479 if (!_shutdownWebEventRaised
) {
3481 if (!_shutdownWebEventRaised
) {
3483 WebBaseEvent
.RaiseSystemEvent(this, WebEventCodes
.ApplicationShutdown
,
3484 WebApplicationLifetimeEvent
.DetailCodeFromShutdownReason(ShutdownReason
));
3486 _shutdownWebEventRaised
= true;
3492 private static string _DefaultPhysicalPathOnMapPathFailure
;
3493 private void RelaxMapPathIfRequired() {
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");
3501 internal static bool IsMapPathRelaxed
{
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
3520 if (FileUtil
.IsSuspiciousPhysicalPath(originalResult
, out pathTooLong
) || pathTooLong
)
3521 return _DefaultPhysicalPathOnMapPathFailure
;
3523 return _DefaultPhysicalPathOnMapPathFailure
;
3527 return originalResult
;
3532 public enum ApplicationShutdownReason
{
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,
3556 PhysicalApplicationPathChanged
= 11,
3558 HttpRuntimeClose
= 12,
3560 InitializationError
= 13,
3562 MaxRecompilationsReached
= 14,
3564 BuildManagerChange
= 15,