File: HttpContext.cs
Project: ndp\fx\src\xsp\system\Web\System.Web.csproj (System.Web)
//------------------------------------------------------------------------------
// <copyright file="HttpContext.cs" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
 
/*
 * HttpContext class
 *
 * Copyright (c) 1999 Microsoft Corporation
 */
 
namespace System.Web {
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Configuration;
    using System.Diagnostics.CodeAnalysis;
    using System.Globalization;
    using System.Linq;
    using System.Net;
    using System.Reflection;
    using System.Runtime.CompilerServices;
    using System.Runtime.Remoting.Messaging;
    using System.Security.Permissions;
    using System.Security.Principal;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Web.Caching;
    using System.Web.Compilation;
    using System.Web.Configuration;
    using System.Web.Hosting;
    using System.Web.Instrumentation;
    using System.Web.Management;
    using System.Web.Profile;
    using System.Web.Security;
    using System.Web.SessionState;
    using System.Web.UI;
    using System.Web.Util;
    using System.Web.WebSockets;
 
 
    /// <devdoc>
    ///    <para>Encapsulates
    ///       all HTTP-specific
    ///       context used by the HTTP server to process Web requests.</para>
    /// <para>System.Web.IHttpModules and System.Web.IHttpHandler instances are provided a
    ///    reference to an appropriate HttpContext object. For example
    ///    the Request and Response
    ///    objects.</para>
    /// </devdoc>
    [SuppressMessage("Microsoft.Usage", "CA2302:FlagServiceProviders", Justification = "The service provider implementation is only for specific types which are not com interop types.")]
    public sealed class HttpContext : IServiceProvider, IPrincipalContainer
    {
 
        internal static readonly Assembly SystemWebAssembly = typeof(HttpContext).Assembly;
        private static volatile bool s_eurlSet;
        private static string s_eurl;
 
        private IHttpAsyncHandler  _asyncAppHandler;   // application as handler (not always HttpApplication)
        private AsyncPreloadModeFlags _asyncPreloadModeFlags;
        private bool               _asyncPreloadModeFlagsSet;
        private HttpApplication    _appInstance;
        private IHttpHandler       _handler;
        [DoNotReset]
        private HttpRequest        _request;
        private HttpResponse       _response;
        private HttpServerUtility  _server;
        private Stack              _traceContextStack;
        private TraceContext       _topTraceContext;
        [DoNotReset]
        private Hashtable          _items;
        private ArrayList          _errors;
        private Exception          _tempError;
        private bool               _errorCleared;
        [DoNotReset]
        private IPrincipalContainer _principalContainer;
        [DoNotReset]
        internal ProfileBase       _Profile;
        [DoNotReset]
        private DateTime           _utcTimestamp;
        [DoNotReset]
        private HttpWorkerRequest  _wr;
        private VirtualPath        _configurationPath;
        internal bool              _skipAuthorization;
        [DoNotReset]
        private CultureInfo        _dynamicCulture;
        [DoNotReset]
        private CultureInfo        _dynamicUICulture;
        private int                _serverExecuteDepth;
        private Stack              _handlerStack;
        private bool               _preventPostback;
        private bool               _runtimeErrorReported;
        private PageInstrumentationService _pageInstrumentationService = null;
        private ReadOnlyCollection<string> _webSocketRequestedProtocols;
 
        // timeout support
        [DoNotReset]
        private CancellationTokenHelper _timeoutCancellationTokenHelper; // used for TimedOutToken
 
        private long       _timeoutStartTimeUtcTicks = -1; // should always be accessed atomically; -1 means uninitialized
        private long       _timeoutTicks = -1; // should always be accessed atomically; -1 means uninitialized
        private int        _timeoutState;   // 0=non-cancelable, 1=cancelable, -1=canceled
        private DoubleLink _timeoutLink;    // link in the timeout's manager list
        private bool       _threadAbortOnTimeout = true; // whether we should Thread.Abort() this thread when it times out
        private Thread     _thread;
 
        // cached configuration
        private CachedPathData _configurationPathData; // Cached data if _configurationPath != null
        private CachedPathData _filePathData;   // Cached data of the file being requested
 
        // Sql Cache Dependency
        private string _sqlDependencyCookie;
 
        // Session State
        volatile SessionStateModule _sessionStateModule;
        volatile bool               _delayedSessionState;   // Delayed session state item
 
        // non-compiled pages
        private TemplateControl _templateControl;
 
        // integrated pipeline state
 
        // For the virtual Disposing / Disposed events
        private SubscriptionQueue<Action<HttpContext>> _requestCompletedQueue;
        [DoNotReset]
        private SubscriptionQueue<IDisposable> _pipelineCompletedQueue;
 
        // keep synchronized with mgdhandler.hxx
        private const int FLAG_NONE                          =   0x0;
        private const int FLAG_CHANGE_IN_SERVER_VARIABLES    =   0x1;
        private const int FLAG_CHANGE_IN_REQUEST_HEADERS     =   0x2;
        private const int FLAG_CHANGE_IN_RESPONSE_HEADERS    =   0x4;
        private const int FLAG_CHANGE_IN_USER_OBJECT         =   0x8;
        private const int FLAG_SEND_RESPONSE_HEADERS         =  0x10;
        private const int FLAG_RESPONSE_HEADERS_SENT         =  0x20;
        internal const int FLAG_ETW_PROVIDER_ENABLED         =  0x40;
        private const int FLAG_CHANGE_IN_RESPONSE_STATUS     =  0x80;
 
        private volatile NotificationContext _notificationContext;
        private bool _isAppInitialized;
        [DoNotReset]
        private bool _isIntegratedPipeline;
        private bool _finishPipelineRequestCalled;
        [DoNotReset]
        private bool _impersonationEnabled;
 
        internal bool HideRequestResponse;
        internal volatile bool InIndicateCompletion;
        internal volatile ThreadContext IndicateCompletionContext = null;
        internal volatile Thread ThreadInsideIndicateCompletion = null;
 
 
        // This field is a surrogate for the HttpContext object itself. Our HostExecutionContextManager
        // shouldn't capture a reference to the HttpContext itself since these references could be long-lived,
        // e.g. if they're captured by a call to ThreadPool.QueueUserWorkItem or a Timer. This would cause the
        // associated HttpContext object graph to be long-lived, which would negatively affect performance.
        // Instead we capture a reference to this 'Id' object, which allows the HostExecutionContextManager
        // to compare the original captured HttpContext with the current HttpContext without actually
        // holding on to the original HttpContext instance.
        [DoNotReset]
        internal readonly object ThreadContextId = new object();
 
        // synchronization context (for EAP / TAP models)
        private AspNetSynchronizationContextBase _syncContext;
 
        // This field doesn't need to be volatile since it will only ever be written to by a single thread, and when that thread
        // later reads the field it will be guaranteed non-null. We don't care what other threads see, since it will never be
        // equal to Thread.CurrentThread for them regardless of whether those threads are seeing the latest value of this field.
        // This field should not be marked [DoNotReset] since we want it to be cleared when WebSocket processing begins.
        internal Thread _threadWhichStartedWebSocketTransition;
 
        // WebSocket state
        [DoNotReset]
        private WebSocketTransitionState _webSocketTransitionState; // see comments in WebSocketTransitionState.cs for detailed info on this enum
        [DoNotReset]
        private string _webSocketNegotiatedProtocol;
 
        // see comments on WebSocketInitStatus for what all of these codes mean
        private WebSocketInitStatus GetWebSocketInitStatus() {
            IIS7WorkerRequest iis7wr =_wr as IIS7WorkerRequest;
            if (iis7wr == null) {
                return WebSocketInitStatus.RequiresIntegratedMode;
            }
 
            if (CurrentNotification <= RequestNotification.BeginRequest) {
                return WebSocketInitStatus.CannotCallFromBeginRequest;
            }
 
            if (!iis7wr.IsWebSocketRequest()) {
                if (iis7wr.IsWebSocketModuleActive()) {
                    return WebSocketInitStatus.NotAWebSocketRequest;
                }
                else {
                    return WebSocketInitStatus.NativeModuleNotEnabled;
                }
            }
 
            if (iis7wr.GetIsChildRequest()) {
                return WebSocketInitStatus.CurrentRequestIsChildRequest;
            }
 
            return WebSocketInitStatus.Success;
        }
      
        // Returns true if the request contained the initial WebSocket handshake
        // and IIS's WebSocket module is active.
        public bool IsWebSocketRequest {
            get {
                // If AcceptWebSocketRequest has already been called and run to completion, then this
                // is obviously a WebSocket request and we can skip further checks (which might throw).
                if (IsWebSocketRequestUpgrading) {
                    return true;
                }
 
                switch (GetWebSocketInitStatus()) {
                    case WebSocketInitStatus.RequiresIntegratedMode:
                        throw new PlatformNotSupportedException(SR.GetString(SR.Requires_Iis_Integrated_Mode));
 
                    case WebSocketInitStatus.CannotCallFromBeginRequest:
                        throw new InvalidOperationException(SR.GetString(SR.WebSockets_CannotBeCalledDuringBeginRequest));
 
                    case WebSocketInitStatus.Success:
                        return true;
 
                    default:
                        return false;
                }
            }
        }
 
        // While unwinding an HTTP request this indicates if the developer 
        // told ASP.NET that they wanted to transition to a websocket request
        public bool IsWebSocketRequestUpgrading {
            get { return (WebSocketTransitionState >= WebSocketTransitionState.AcceptWebSocketRequestCalled); }
        }
 
        internal bool HasWebSocketRequestTransitionStarted {
            get { return WebSocketTransitionState >= WebSocketTransitionState.TransitionStarted; }
        }
 
        internal bool HasWebSocketRequestTransitionCompleted {
            get { return WebSocketTransitionState >= WebSocketTransitionState.TransitionCompleted; }
        }
 
        internal WebSocketTransitionState WebSocketTransitionState {
            get { return _webSocketTransitionState; }
            private set { _webSocketTransitionState = value; }
        }
 
        // Returns the ordered list of protocols requested by the client,
        // or an empty collection if this wasn't a WebSocket request or there was no list present.
        public IList<string> WebSocketRequestedProtocols {
            get {
                if (IsWebSocketRequest) {
                    if (_webSocketRequestedProtocols == null) {
                        string rawHeaderValue = _wr.GetUnknownRequestHeader("Sec-WebSocket-Protocol");
                        IList<string> requestedProtocols = SubProtocolUtil.ParseHeader(rawHeaderValue); // checks for invalid values
                        _webSocketRequestedProtocols = new ReadOnlyCollection<string>(requestedProtocols ?? new string[0]);
                    }
                    return _webSocketRequestedProtocols;
                }
                else {
                    // not a WebSocket request
                    return null;
                }
            }
        }
 
        // Returns the negotiated protocol (sent from the server to the client) for a
        // WebSocket request.
        public string WebSocketNegotiatedProtocol {
            get { return _webSocketNegotiatedProtocol; }
        }
 
        public void AcceptWebSocketRequest(Func<AspNetWebSocketContext, Task> userFunc) {
            AcceptWebSocketRequest(userFunc, null);
        }
 
        [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification = "This is a safe critical method.")]
        public void AcceptWebSocketRequest(Func<AspNetWebSocketContext, Task> userFunc, AspNetWebSocketOptions options) {
            // Begin argument & state checking
 
            // We throw different error codes depending on the check that failed. Things that are
            // server configuration errors (WebSockets not enabled) or developer errors (called this
            // method with bad parameters) result in an appropriate exception type. Things that are
            // remote errors (e.g. bad parameters from the client) result in an HTTP 4xx.
 
            if (userFunc == null) {
                throw new ArgumentNullException("userFunc");
            }
 
            if (IsWebSocketRequestUpgrading) {
                // this method cannot be called multiple times
                throw new InvalidOperationException(SR.GetString(SR.WebSockets_AcceptWebSocketRequestCanOnlyBeCalledOnce));
            }
 
            // DevDiv #384514: Task<T> doesn't work correctly using the legacy SynchronizationContext setting. Since
            // WebSockets operation requires correct Task<T> behavior, we should forbid using the feature when legacy
            // mode is enabled.
            SynchronizationContextUtil.ValidateModeForWebSockets();
 
            switch (GetWebSocketInitStatus()) {
                case WebSocketInitStatus.RequiresIntegratedMode:
                    throw new PlatformNotSupportedException(SR.GetString(SR.Requires_Iis_Integrated_Mode));
 
                case WebSocketInitStatus.CannotCallFromBeginRequest:
                    throw new InvalidOperationException(SR.GetString(SR.WebSockets_CannotBeCalledDuringBeginRequest));
 
                case WebSocketInitStatus.NativeModuleNotEnabled:
                    throw new PlatformNotSupportedException(SR.GetString(SR.WebSockets_WebSocketModuleNotEnabled));
 
                case WebSocketInitStatus.NotAWebSocketRequest:
                    throw new HttpException((int)HttpStatusCode.BadRequest, SR.GetString(SR.WebSockets_NotAWebSocketRequest));
 
                case WebSocketInitStatus.CurrentRequestIsChildRequest:
                    throw new InvalidOperationException(SR.GetString(SR.WebSockets_CannotBeCalledDuringChildExecute));
 
                case WebSocketInitStatus.Success:
                    break;
 
                default:
                    // fallback error message - not a WebSocket request
                    throw new HttpException(SR.GetString(SR.WebSockets_UnknownErrorWhileAccepting));
            }
 
            if (CurrentNotification > RequestNotification.ExecuteRequestHandler) {
                // it is too late to call this method
                throw new InvalidOperationException(SR.GetString(SR.WebSockets_CannotBeCalledAfterHandlerExecute));
            }
            // End argument & state checking
 
            IIS7WorkerRequest wr = (IIS7WorkerRequest)_wr;
 
            // Begin options checking and parsing
            if (options != null && options.RequireSameOrigin) {
                if (!WebSocketUtil.IsSameOriginRequest(wr)) {
                    // use Forbidden (HTTP 403) since it's not an authentication error; it's a usage error
                    throw new HttpException((int)HttpStatusCode.Forbidden, SR.GetString(SR.WebSockets_OriginCheckFailed));
                }
            }
 
            string subprotocol = null;
            if (options != null && !String.IsNullOrEmpty(options.SubProtocol)) {
                // AspNetWebSocketOptions.set_SubProtocol() already checked that the provided value is valid
                subprotocol = options.SubProtocol;
            }
 
            if (subprotocol != null) {
                IList<string> incomingProtocols = WebSocketRequestedProtocols;
                if (incomingProtocols == null || !incomingProtocols.Contains(subprotocol, StringComparer.Ordinal)) {
                    // The caller requested a subprotocol that wasn't in the list of accepted protocols coming from the client.
                    // This is disallowed by the WebSockets protocol spec, Sec. 5.2.2 (#2).
                    throw new ArgumentException(SR.GetString(SR.WebSockets_SubProtocolCannotBeNegotiated, subprotocol), "options");
                }
            }
            // End options checking and parsing
 
            wr.AcceptWebSocket();
 
            // transition: Inactive -> AcceptWebSocketRequestCalled
            TransitionToWebSocketState(WebSocketTransitionState.AcceptWebSocketRequestCalled);
 
            Response.StatusCode = (int)HttpStatusCode.SwitchingProtocols; // 101
            if (subprotocol != null) {
                Response.AppendHeader("Sec-WebSocket-Protocol", subprotocol);
                _webSocketNegotiatedProtocol = subprotocol;
            }
            RootedObjects.WebSocketPipeline = new WebSocketPipeline(RootedObjects, this, userFunc, subprotocol);
        }
 
        internal void TransitionToWebSocketState(WebSocketTransitionState newState) {
            // Make sure the state transition is happening in the correct order
#if DBG
            WebSocketTransitionState expectedOldState = checked(newState - 1);
            Debug.Assert(WebSocketTransitionState == expectedOldState, String.Format(CultureInfo.InvariantCulture, "Expected WebSocketTransitionState to be '{0}', but it was '{1}'.", expectedOldState, WebSocketTransitionState));
#endif
 
            WebSocketTransitionState = newState;
            if (newState == Web.WebSocketTransitionState.TransitionStarted) {
                _threadWhichStartedWebSocketTransition = Thread.CurrentThread;
            }
        }
 
        internal bool DidCurrentThreadStartWebSocketTransition {
            get {
                return _threadWhichStartedWebSocketTransition == Thread.CurrentThread;
            }
        }
 
        // helper that throws an exception if we have transitioned the current request to a WebSocket request
        internal void EnsureHasNotTransitionedToWebSocket() {
            if (HasWebSocketRequestTransitionCompleted) {
                throw new NotSupportedException(SR.GetString(SR.WebSockets_MethodNotAvailableDuringWebSocketProcessing));
            }
        }
 
        internal bool FirstRequest {get; set;}
 
        // session state support
        private bool _requiresSessionStateFromHandler;
        internal bool RequiresSessionState {
            get {
                switch (SessionStateBehavior) {
                    case SessionStateBehavior.Required:
                    case SessionStateBehavior.ReadOnly:
                        return true;
                    case SessionStateBehavior.Disabled:
                        return false;
                    case SessionStateBehavior.Default:
                    default:
                        return _requiresSessionStateFromHandler;
                }
            }
        }
 
        private bool _readOnlySessionStateFromHandler;
        internal bool ReadOnlySessionState {
            get {
                switch (SessionStateBehavior) {
                    case SessionStateBehavior.ReadOnly:
                        return true;
                    case SessionStateBehavior.Required:
                    case SessionStateBehavior.Disabled:
                        return false;
                    case SessionStateBehavior.Default:
                    default:
                        return _readOnlySessionStateFromHandler;
                }
            }
        }
        internal bool InAspCompatMode;
 
        private IHttpHandler _remapHandler = null;
 
        /// <include file='doc\HttpContext.uex' path='docs/doc[@for="HttpContext.HttpContext"]/*' />
        /// <devdoc>
        ///    <para>
        ///       Initializes a new instance of the HttpContext class.
        ///    </para>
        /// </devdoc>
        public HttpContext(HttpRequest request, HttpResponse response) {
            Init(request, response);
            request.Context = this;
            response.Context = this;
        }
 
 
        /// <devdoc>
        ///    <para>
        ///       Initializes a new instance of the HttpContext class.
        ///    </para>
        /// </devdoc>
        public HttpContext(HttpWorkerRequest wr) {
            _wr = wr;
            Init(new HttpRequest(wr, this), new HttpResponse(wr, this));
            _response.InitResponseWriter();
        }
 
        // ctor used in HttpRuntime
        internal HttpContext(HttpWorkerRequest wr, bool initResponseWriter) {
            _wr = wr;
            Init(new HttpRequest(wr, this), new HttpResponse(wr, this));
 
            if (initResponseWriter)
                _response.InitResponseWriter();
 
            PerfCounters.IncrementCounter(AppPerfCounter.REQUESTS_EXECUTING);
        }
 
        private void Init(HttpRequest request, HttpResponse response) {
            _request = request;
            _response = response;
            _utcTimestamp = DateTime.UtcNow;
            _principalContainer = this;
 
            if (_wr is IIS7WorkerRequest) {
                _isIntegratedPipeline = true;
            }
 
            if (!(_wr is System.Web.SessionState.StateHttpWorkerRequest))
                CookielessHelper.RemoveCookielessValuesFromPath(); // This ensures that the cookieless-helper is initialized and
            // rewrites the path if the URI contains cookieless form-auth ticket, session-id, etc.
 
            Profiler p = HttpRuntime.Profile;
            if (p != null && p.IsEnabled)
                _topTraceContext = new TraceContext(this);
 
            // rewrite path in order to remove "/eurl.axd/guid", if it was
            // added to the URL by aspnet_filter.dll.
            string eurl = GetEurl();
            if (!String.IsNullOrEmpty(eurl)) {
                string path = request.Path;
                int idxStartEurl = path.Length - eurl.Length;
                bool hasTrailingSlash = (path[path.Length - 1] == '/');
                if (hasTrailingSlash) {
                    idxStartEurl--;
                }
                if (idxStartEurl >= 0
                    && StringUtil.Equals(path, idxStartEurl, eurl, 0, eurl.Length)) {                    
                    // restore original URL
                    int originalUrlLen = idxStartEurl;
                    if (hasTrailingSlash) {
                        originalUrlLen++;
                    }
                    string originalUrl = path.Substring(0, originalUrlLen);
                    // Dev10 835901: We don't call HttpContext.RewritePath(path) because the 
                    // original path may contain '?' encoded as %3F, and RewritePath
                    // would interpret what follows as the query string.  So instead, we
                    // clear ConfigurationPath and call InternalRewritePath directly.
                    ConfigurationPath = null;
                    Request.InternalRewritePath(VirtualPath.Create(originalUrl), null, true);
                }
            }
        }
 
        // We have a feature that directs extensionless URLs
        // into managed code by appending "/eurl.axd/guid" to the path.  On IIS 6.0,
        // we restore the URL as soon as we get into managed code.  Here we  get the
        // actual value of "/eurl.axd/guid" and remember it.
        private string GetEurl() {
            // only used on IIS 6.0
            if (!(_wr is ISAPIWorkerRequestInProcForIIS6)
                || (_wr is ISAPIWorkerRequestInProcForIIS7)) {
                return null;
            }
 
            string eurl = s_eurl;
            if (eurl == null && !s_eurlSet) {
                try {
                    IntPtr pBuffer = UnsafeNativeMethods.GetExtensionlessUrlAppendage();
                    if (pBuffer != IntPtr.Zero) {
                        eurl = StringUtil.StringFromWCharPtr(pBuffer, UnsafeNativeMethods.lstrlenW(pBuffer));
                    }
                }
                catch {} // ignore all exceptions
                s_eurl = eurl;
                s_eurlSet = true;
            }
            return eurl;
        }
 
        // Current HttpContext off the call context
#if DBG
        internal static void SetDebugAssertOnAccessToCurrent(bool doAssert) {
            if (doAssert) {
                CallContext.SetData("__ContextAssert", String.Empty);
            }
            else {
                CallContext.SetData("__ContextAssert", null);
            }
        }
 
        private static bool NeedDebugAssertOnAccessToCurrent {
            get {
                return (CallContext.GetData("__ContextAssert") != null);
            }
        }
#endif
 
        /// <devdoc>
        ///    <para>Returns the current HttpContext object.</para>
        /// </devdoc>
        public static HttpContext Current {
            get {
#if DBG
                if (NeedDebugAssertOnAccessToCurrent) {
                    Debug.Assert(ContextBase.Current != null);
                }
#endif
                return ContextBase.Current as HttpContext;
            }
 
            set {
                ContextBase.Current = value;
            }
        }
 
        //
        //  Root / unroot for the duration of async operation
        //  These are only used for the classic pipeline. The integrated pipeline uses a different rooting mechanism.
        //
 
        private IntPtr _rootedPtr;
 
        [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification = "This is a safe critical method.")]
        internal void Root() {
            _rootedPtr = GCUtil.RootObject(this);
        }
 
        internal void Unroot() {
            GCUtil.UnrootObject(_rootedPtr);
            _rootedPtr = IntPtr.Zero;
        }
 
        internal void FinishPipelineRequest() {
            if (!_finishPipelineRequestCalled) {
                _finishPipelineRequestCalled = true;
                HttpRuntime.FinishPipelineRequest(this);
            }
        }
 
        // This is a virtual event which occurs when the HTTP part of this request is winding down, e.g. after EndRequest
        // but before the WebSockets pipeline kicks in. The HttpContext is still available for inspection and is provided
        // as a parameter to the supplied callback.
        [SuppressMessage("Microsoft.Design", "CA1030:UseEventsWhereAppropriate", Justification = @"The normal event pattern doesn't work between HttpContext and HttpContextBase since the signatures differ.")]
        public ISubscriptionToken AddOnRequestCompleted(Action<HttpContext> callback) {
            if (callback == null) {
                throw new ArgumentNullException("callback");
            }
 
            return _requestCompletedQueue.Enqueue(callback);
        }
 
        internal void RaiseOnRequestCompleted() {
            // The callbacks really shouldn't throw exceptions, but we have a catch block just in case.
            // Since there's nobody else that can listen for these errors (the request is unwinding and
            // user code will no longer run), we'll just log the error.
            try {
                _requestCompletedQueue.FireAndComplete(action => action(this));
            }
            catch (Exception e) {
                WebBaseEvent.RaiseRuntimeError(e, this);
            }
            finally {
                // Dispose of TimedOutToken so that nobody tries using it after this point.
                DisposeTimedOutToken();
            }
        }
 
        // Allows an object's Dispose() method to be called when the pipeline part of this request is completed, e.g.
        // after both the HTTP part and the WebSockets loop have completed. The HttpContext is not available for
        // inspection, and HttpContext.Current will be null.
        [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification = "This is a safe critical method.")]
        public ISubscriptionToken DisposeOnPipelineCompleted(IDisposable target) {
            if (target == null) {
                throw new ArgumentNullException("target");
            }
 
            if (RootedObjects != null) {
                // integrated pipeline
                return RootedObjects.DisposeOnPipelineCompleted(target);
            }
            else {
                // classic pipeline
                return _pipelineCompletedQueue.Enqueue(target);
            }
        }
 
        internal void RaiseOnPipelineCompleted() {
            // The callbacks really shouldn't throw exceptions, but we have a catch block just in case.
            // Since there's nobody else that can listen for these errors (the request is unwinding and
            // user code will no longer run), we'll just log the error.
            try {
                _pipelineCompletedQueue.FireAndComplete(disposable => disposable.Dispose());
            }
            catch (Exception e) {
                WebBaseEvent.RaiseRuntimeError(e, null);
            }
        }
 
        internal void ValidatePath() {
            CachedPathData pathData = GetConfigurationPathData();
            pathData.ValidatePath(_request.PhysicalPathInternal);
        }
 
 
        // IServiceProvider implementation
 
        /// <internalonly/>
        Object IServiceProvider.GetService(Type service) {
            Object obj;
 
            if (service == typeof(HttpWorkerRequest)) {
                InternalSecurityPermissions.UnmanagedCode.Demand();
                obj = _wr;
            }
            else if (service == typeof(HttpRequest))
                obj = Request;
            else if (service == typeof(HttpResponse))
                obj = Response;
            else if (service == typeof(HttpApplication))
                obj = ApplicationInstance;
            else if (service == typeof(HttpApplicationState))
                obj = Application;
            else if (service == typeof(HttpSessionState))
                obj = Session;
            else if (service == typeof(HttpServerUtility))
                obj = Server;
            else
                obj = null;
 
            return obj;
        }
 
        //
        // Async app handler is remembered for the duration of execution of the
        // request when application happens to be IHttpAsyncHandler. It is needed
        // for HttpRuntime to remember the object on which to call OnEndRequest.
        //
        // The assumption is that application is a IHttpAsyncHandler, not always
        // HttpApplication.
        //
        internal IHttpAsyncHandler AsyncAppHandler {
            get { return _asyncAppHandler; }
            set { _asyncAppHandler = value; }
        }
 
        public AsyncPreloadModeFlags AsyncPreloadMode {
            get {
                if (!_asyncPreloadModeFlagsSet) {
                    _asyncPreloadModeFlags = RuntimeConfig.GetConfig(this).HttpRuntime.AsyncPreloadMode;
                    _asyncPreloadModeFlagsSet = true;
                }
                return _asyncPreloadModeFlags;
            }
            set {
                _asyncPreloadModeFlags = value; 
                _asyncPreloadModeFlagsSet = true;
            }
        }
 
        // If this flag is not set, the AspNetSynchronizationContext associated with this request will throw
        // exceptions when it detects the application misusing the async API. This can occur if somebody
        // tries to call SynchronizationContext.Post / OperationStarted / etc. during a part of the
        // pipeline where we weren't expecting asynchronous work to take place, if there is still
        // outstanding asynchronous work when an asynchronous module or handler signals completion, etc.
        // It is meant as a safety net to let developers know early on when they're writing async code
        // which doesn't fit our expected patterns and where that code likely has negative side effects.
        // 
        // This flag is respected only by AspNetSynchronizationContext; it has no effect when the
        // legacy sync context is in use.
        [EditorBrowsable(EditorBrowsableState.Advanced)]
        public bool AllowAsyncDuringSyncStages {
            get {
                return SyncContext.AllowAsyncDuringSyncStages;
            }
            set {
                SyncContext.AllowAsyncDuringSyncStages = value;
            }
        }
 
        /// <devdoc>
        ///    <para>Retrieves a reference to the application object for the current Http request.</para>
        /// </devdoc>
        public HttpApplication ApplicationInstance {
            get {
                return _appInstance;
            }
            set {
                // For integrated pipeline, once this is set to a non-null value, it can only be set to null.
                // The setter should never have been made public.  It probably happened in 1.0, before it was possible
                // to have getter and setter with different accessibility.
                if (_isIntegratedPipeline && _appInstance != null && value != null) {
                    throw new InvalidOperationException(SR.GetString(SR.Application_instance_cannot_be_changed));
                }
                else {
                    _appInstance = value;
 
                    // Use HttpApplication instance custom allocator provider
                    if (_isIntegratedPipeline) {
                        // The provider allows null - everyone should fallback to default implementation
                        IAllocatorProvider allocator = _appInstance != null ? _appInstance.AllocatorProvider : null;
 
                        _response.SetAllocatorProvider(allocator);
                        ((IIS7WorkerRequest)_wr).AllocatorProvider = allocator;
                    }
                }
            }
        }
 
 
        /// <devdoc>
        ///    <para>
        ///       Retrieves a reference to the application object for the current
        ///       Http request.
        ///    </para>
        /// </devdoc>
        public HttpApplicationState Application {
            get { return HttpApplicationFactory.ApplicationState; }
        }
 
 
        // flag to suppress use of custom HttpEncoder registered in web.config
        // for example, yellow error pages should use the default encoder rather than a custom encoder
        internal bool DisableCustomHttpEncoder {
            get;
            set;
        }
 
 
        /// <devdoc>
        ///    <para>
        ///       Retrieves or assigns a reference to the <see cref='System.Web.IHttpHandler'/>
        ///       object for the current request.
        ///    </para>
        /// </devdoc>
        public IHttpHandler Handler {
            get { return _handler;}
            set {
                _handler = value;
                _requiresSessionStateFromHandler = false;
                _readOnlySessionStateFromHandler = false;
                InAspCompatMode = false;
                if (_handler != null) {
                    if (_handler is IRequiresSessionState) {
                        _requiresSessionStateFromHandler = true;
                    }
                    if (_handler is IReadOnlySessionState) {
                        _readOnlySessionStateFromHandler = true;
                    }
                    Page page = _handler as Page;
                    if (page != null && page.IsInAspCompatMode) {
                        InAspCompatMode = true;
                    }
                }
            }
        }
 
 
        /// <devdoc>
        ///    <para>
        ///       Retrieves or assigns a reference to the <see cref='System.Web.IHttpHandler'/>
        ///       object for the previous handler;
        ///    </para>
        /// </devdoc>
 
        public IHttpHandler PreviousHandler {
            get {
                if (_handlerStack == null || _handlerStack.Count == 0)
                    return null;
 
                return (IHttpHandler)_handlerStack.Peek();
            }
        }
 
 
        /// <devdoc>
        ///    <para>
        ///       Retrieves or assigns a reference to the <see cref='System.Web.IHttpHandler'/>
        ///       object for the current executing handler;
        ///    </para>
        /// </devdoc>
        private IHttpHandler _currentHandler = null;
 
        public IHttpHandler CurrentHandler {
            get {
                if (_currentHandler == null)
                    _currentHandler = _handler;
 
                return _currentHandler;
            }
        }
 
        internal void RestoreCurrentHandler() {
            _currentHandler = (IHttpHandler)_handlerStack.Pop();
        }
 
        internal void SetCurrentHandler(IHttpHandler newtHandler) {
            if (_handlerStack == null) {
                _handlerStack = new Stack();
            }
            _handlerStack.Push(CurrentHandler);
 
            _currentHandler = newtHandler;
        }
 
        /// <devdoc>
        ///    <para>
        ///       Set custom mapping handler processing the request <see cref='System.Web.IHttpHandler'/>
        ///    </para>
        /// </devdoc>
        public void RemapHandler(IHttpHandler handler) {
            EnsureHasNotTransitionedToWebSocket();
 
            IIS7WorkerRequest wr = _wr as IIS7WorkerRequest;
 
            if (wr != null) {
                // Remap handler not allowed after ResolveRequestCache notification
                if (_notificationContext.CurrentNotification >= RequestNotification.MapRequestHandler) {
                    throw new InvalidOperationException(SR.GetString(SR.Invoke_before_pipeline_event, "HttpContext.RemapHandler", "HttpApplication.MapRequestHandler"));
                }
 
                string handlerTypeName = null;
                string handlerName = null;
 
                if (handler != null) {
                    Type handlerType = handler.GetType();
 
                    handlerTypeName = handlerType.AssemblyQualifiedName;
                    handlerName = handlerType.FullName;
                }
 
                wr.SetRemapHandler(handlerTypeName, handlerName);
            }
 
            _remapHandler = handler;
        }
 
        internal IHttpHandler RemapHandlerInstance {
            get {
                return _remapHandler;
            }
        }
 
        /// <devdoc>
        ///    <para>
        ///       Retrieves a reference to the target <see cref='System.Web.HttpRequest'/>
        ///       object for the current request.
        ///    </para>
        /// </devdoc>
        public HttpRequest Request {
            get {
                 if (HideRequestResponse)
                    throw new HttpException(SR.GetString(SR.Request_not_available));
                return _request;
            }
        }
 
 
        /// <devdoc>
        ///    <para>
        ///       Retrieves a reference to the <see cref='System.Web.HttpResponse'/>
        ///       object for the current response.
        ///    </para>
        /// </devdoc>
        public HttpResponse Response {
            get {
                if (HideRequestResponse || HasWebSocketRequestTransitionCompleted)
                    throw new HttpException(SR.GetString(SR.Response_not_available));
                return _response;
            }
        }
 
 
        internal IHttpHandler TopHandler {
            get {
                if (_handlerStack == null) {
                    return _handler;
                }
                object[] handlers = _handlerStack.ToArray();
                if (handlers == null || handlers.Length == 0) {
                    return _handler;
                }
                return (IHttpHandler)handlers[handlers.Length - 1];
            }
        }
 
 
        /// <devdoc>
        /// <para>Retrieves a reference to the <see cref='System.Web.TraceContext'/> object for the current
        ///    response.</para>
        /// </devdoc>
        public TraceContext Trace {
            get {
                if (_topTraceContext == null)
                    _topTraceContext = new TraceContext(this);
                return _topTraceContext;
            }
        }
 
        internal bool TraceIsEnabled {
            get {
                if (_topTraceContext == null)
                    return false;
 
                return _topTraceContext.IsEnabled;
            }
            set {
                if (value)
                    _topTraceContext = new TraceContext(this);
            }
 
        }
 
 
 
        /// <devdoc>
        ///    <para>
        ///       Retrieves a key-value collection that can be used to
        ///       build up and share data between an <see cref='System.Web.IHttpModule'/> and an <see cref='System.Web.IHttpHandler'/>
        ///       during a
        ///       request.
        ///    </para>
        /// </devdoc>
        public IDictionary Items {
            get {
                if (_items == null)
                    _items = new Hashtable();
 
                return _items;
            }
        }
 
 
        /// <devdoc>
        ///    <para>
        ///       Gets a reference to the <see cref='System.Web.SessionState'/> instance for the current request.
        ///    </para>
        /// </devdoc>
        public HttpSessionState Session {
            get {
                if (HasWebSocketRequestTransitionCompleted) {
                    // Session is unavailable at this point
                    return null;
                }
 
                if (_delayedSessionState) {
                    lock (this) {
                        if (_delayedSessionState) {
                            Debug.Assert(_sessionStateModule != null, "_sessionStateModule != null");
 
                            // If it's not null, it means we have a delayed session state item
                            _sessionStateModule.InitStateStoreItem(true);
                            _delayedSessionState = false;
                        }
                    }
                }
 
                return(HttpSessionState)Items[SessionStateUtility.SESSION_KEY];
            }
        }
 
        [MethodImpl(MethodImplOptions.NoInlining)]
        internal void EnsureSessionStateIfNecessary() {
            if (_sessionStateModule == null)
            {
                // If _sessionStateModule is null, we wouldn't be able to call 
                // _sessionStateModule.EnsureStateStoreItemLocked(), so we return here.
                // _sessionStateModule could be null in the following cases,
                // 1. No session state acquired.
                // 2. HttpResponse.Flush() happens after session state being released.
                // 3. The session state module in use is not System.Web.SessionState.SessionStateModule.
                //
                // This method is for the in-framework SessionStateModule only.
                //  OOB SessionStateModule can achieve this by using HttpResponse.AddOnSendingHeaders. 
                return;
            }
 
            HttpSessionState session = (HttpSessionState)Items[SessionStateUtility.SESSION_KEY];
 
            if (session != null &&                                 // The session has been initiated
                session.Count > 0 &&                               // The session state is used
                !string.IsNullOrEmpty(session.SessionID)) {        // Ensure the session Id is valid - it will force to create new if didn't exist
                _sessionStateModule.EnsureStateStoreItemLocked();  // Lock the item if in use
            }
        }
 
 
        internal void AddHttpSessionStateModule(SessionStateModule module, bool delayed) {
            if (_sessionStateModule != null && _sessionStateModule != module) {
                throw new HttpException(SR.GetString(SR.Cant_have_multiple_session_module));
            }
            _sessionStateModule = module;
            _delayedSessionState = delayed;
        }
 
        internal void RemoveHttpSessionStateModule() {
            _delayedSessionState = false;
            _sessionStateModule = null;
        }
 
 
        /// <devdoc>
        ///    <para>
        ///       Gets a reference to the <see cref='System.Web.HttpServerUtility'/>
        ///       for the current
        ///       request.
        ///    </para>
        /// </devdoc>
        public HttpServerUtility Server {
            get {
                // create only on demand
                if (_server == null)
                    _server = new HttpServerUtility(this);
                return _server;
            }
        }
 
        // if the context has an error, report it, but only one time
        internal void ReportRuntimeErrorIfExists(ref RequestNotificationStatus status) {
            Exception e = Error;
 
            if (e == null || _runtimeErrorReported) {
                return;
            }
 
            // WOS 1921799: custom errors don't work in integrated mode if there's an initialization exception
            if (_notificationContext != null && CurrentModuleIndex == -1) {
                try {
                    IIS7WorkerRequest wr = _wr as IIS7WorkerRequest;
                    if (Request.QueryString["aspxerrorpath"] != null
                        && wr != null
                        && String.IsNullOrEmpty(wr.GetManagedHandlerType())
                        && wr.GetCurrentModuleName() == PipelineRuntime.InitExceptionModuleName) {
                        status = RequestNotificationStatus.Continue;   // allow non-managed handler to execute request
                        return;
                    }
                }
                catch {
                }
            }
 
            _runtimeErrorReported = true;
 
            if (HttpRuntime.AppOfflineMessage != null) {
                try {
                    // report app offline error
                    Response.TrySkipIisCustomErrors = true;
                    HttpRuntime.ReportAppOfflineErrorMessage(Response, HttpRuntime.AppOfflineMessage);
 
                }
                catch {
                }
            }
            else {
                // report error exception
                using (new DisposableHttpContextWrapper(this)) {
 
                    // if the custom encoder throws, it might interfere with returning error information
                    // to the client, so we force use of the default encoder
                    DisableCustomHttpEncoder = true;
 
                    // when application is on UNC share the code below must
                    // be run while impersonating the token given by IIS
                    using (new ApplicationImpersonationContext()) {
 
                        try {
                            try {
                                // try to report error in a way that could possibly throw (a config exception)
                                Response.ReportRuntimeError(e, true /*canThrow*/, false);
                            }
                            catch (Exception eReport) {
                                // report the config error in a way that would not throw
                                Response.ReportRuntimeError(eReport, false /*canThrow*/, false);
                            }
                        }
                        catch (Exception) {
                        }
                    }
                }
            }
 
            status = RequestNotificationStatus.FinishRequest;
            return;
        }
 
        /// <devdoc>
        ///    <para>
        ///       Gets the
        ///       first error (if any) accumulated during request processing.
        ///    </para>
        /// </devdoc>
        public Exception Error {
            get {
                if (_tempError != null)
                    return _tempError;
                if (_errors == null || _errors.Count == 0 || _errorCleared)
                    return null;
                return (Exception)_errors[0];
            }
        }
 
        //
        // Temp error (yet to be caught on app level)
        // to be reported as Server.GetLastError() but could be cleared later
        //
        internal Exception TempError {
            get { return _tempError; }
            set { _tempError = value; }
        }
 
 
        /// <devdoc>
        ///    <para>
        ///       An array (collection) of errors accumulated while processing a
        ///       request.
        ///    </para>
        /// </devdoc>
        public Exception[] AllErrors {
            get {
                int n = (_errors != null) ? _errors.Count : 0;
 
                if (n == 0)
                    return null;
 
                Exception[] errors = new Exception[n];
                _errors.CopyTo(0, errors, 0, n);
                return errors;
            }
        }
 
 
        /// <devdoc>
        ///    <para>
        ///       Registers an error for the current request.
        ///    </para>
        /// </devdoc>
        public void AddError(Exception errorInfo) {
            if (_errors == null)
                _errors = new ArrayList();
 
            _errors.Add(errorInfo);
 
            if (_isIntegratedPipeline && _notificationContext != null) {
                // set the error on the current notification context
                _notificationContext.Error = errorInfo;
            }
        }
 
 
        /// <devdoc>
        ///    <para>
        ///       Clears all errors for the current request.
        ///    </para>
        /// </devdoc>
        public void ClearError() {
            if (_tempError != null)
                _tempError = null;
            else
                _errorCleared = true;
 
            if (_isIntegratedPipeline && _notificationContext != null) {
                // clear the error on the current notification context
                _notificationContext.Error = null;
            }
        }
 
 
        /// <devdoc>
        ///    <para>
        ///       IPrincipal security information.
        ///    </para>
        /// </devdoc>
        public IPrincipal User {
            get { return _principalContainer.Principal; }
 
            [SecurityPermission(SecurityAction.Demand, ControlPrincipal=true)]
            set {
                SetPrincipalNoDemand(value);
            }
        }
 
        IPrincipal IPrincipalContainer.Principal {
            get;
            set;
        }
 
        // route all internals call to the principal (that don't have luring attacks)
        // through this method so we can centralize reporting
        // Before this, some auth modules were assigning directly to _user
        internal void SetPrincipalNoDemand(IPrincipal principal, bool needToSetNativePrincipal) {
            _principalContainer.Principal = principal;
 
            // push changes through to native side
            if (needToSetNativePrincipal
                && _isIntegratedPipeline
                && _notificationContext.CurrentNotification == RequestNotification.AuthenticateRequest) {
 
                IntPtr pManagedPrincipal = IntPtr.Zero;
                IIS7WorkerRequest wr = (IIS7WorkerRequest)_wr;
                wr.SetPrincipal(principal);
            }
        }
 
        internal void SetPrincipalNoDemand(IPrincipal principal) {
            SetPrincipalNoDemand(principal, true /*needToSetNativePrincipal*/);
        }
 
        [DoNotReset]
        internal bool _ProfileDelayLoad = false;
 
        public ProfileBase  Profile {
            get {
                if (_Profile == null && _ProfileDelayLoad)
                    _Profile = ProfileBase.Create(Request.IsAuthenticated ? User.Identity.Name : Request.AnonymousID, Request.IsAuthenticated);
                return _Profile;
            }
        }
 
        internal SessionStateBehavior SessionStateBehavior { get; set; }
 
        [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate",
          Justification = "An internal property already exists. This method does additional work.")]
        public void SetSessionStateBehavior(SessionStateBehavior sessionStateBehavior) {
            if (_notificationContext != null && _notificationContext.CurrentNotification >= RequestNotification.AcquireRequestState) {
                throw new InvalidOperationException(SR.GetString(SR.Invoke_before_pipeline_event, "HttpContext.SetSessionStateBehavior", "HttpApplication.AcquireRequestState"));
            }
 
            SessionStateBehavior = sessionStateBehavior;
        }
 
 
        public bool SkipAuthorization {
            get { return _skipAuthorization;}
 
            [SecurityPermission(SecurityAction.Demand, ControlPrincipal=true)]
            set {
                SetSkipAuthorizationNoDemand(value, false);
            }
        }
 
        internal void SetSkipAuthorizationNoDemand(bool value, bool managedOnly)
        {
            if (HttpRuntime.UseIntegratedPipeline
                && !managedOnly
                && value != _skipAuthorization) {
 
                // For integrated mode, persist changes to SkipAuthorization
                // in the IS_LOGIN_PAGE server variable.  When this server variable exists
                // and the value is not "0", IIS skips authorization.
 
                _request.SetSkipAuthorization(value);
            }
 
            _skipAuthorization = value;
        }
 
        // Pointer to the RootedObjects element, which contains information that needs to be flowed
        // between the HttpContext and the WebSocket, such as the current principal.
        [DoNotReset]
        private RootedObjects _rootedObjects;
        
        internal RootedObjects RootedObjects {
            get {
                return _rootedObjects;
            }
            set {
                // Sync the Principal between the containers
                SwitchPrincipalContainer(value);
                _rootedObjects = value;
            }
        }
 
        private void SwitchPrincipalContainer(IPrincipalContainer newPrincipalContainer) {
            if (newPrincipalContainer == null) {
                newPrincipalContainer = this;
            }
 
            // Ensure new container contains the current principal
            IPrincipal currentPrincipal = _principalContainer.Principal;
            newPrincipalContainer.Principal = currentPrincipal;
            _principalContainer = newPrincipalContainer;
        }
 
        /// <devdoc>
        ///    <para>
        ///       Is this request in debug mode?
        ///    </para>
        /// </devdoc>
        public bool IsDebuggingEnabled {
            get {
                try {
                    return CompilationUtil.IsDebuggingEnabled(this);
                }
                catch {
                    // in case of config errors don't throw
                    return false;
                }
            }
        }
 
 
        /// <devdoc>
        ///    <para>
        ///       Is this custom error enabled for this request?
        ///    </para>
        /// </devdoc>
        public bool IsCustomErrorEnabled {
            get {
                return CustomErrorsSection.GetSettings(this).CustomErrorsEnabled(_request);
            }
        }
 
        internal TemplateControl TemplateControl {
            get {
                return _templateControl;
            }
            set {
                _templateControl = value;
            }
        }
 
 
        /// <devdoc>
        ///    <para>Gets the initial timestamp of the current request.</para>
        /// </devdoc>
        public DateTime Timestamp {
            get { return _utcTimestamp.ToLocalTime();}
        }
 
        internal DateTime UtcTimestamp {
            get { return _utcTimestamp;}
        }
 
        internal HttpWorkerRequest WorkerRequest {
            get { return _wr;}
        }
 
 
        /// <devdoc>
        ///    <para>
        ///       Gets a reference to the System.Web.Cache.Cache object for the current request.
        ///    </para>
        /// </devdoc>
        public Cache Cache {
            get { return HttpRuntime.Cache;}
        }
 
        /// <summary>
        /// Gets a reference to the System.Web.Instrumentation.PageInstrumentationService instance for this request. Guaranteed not to be null (barring private reflection magic).
        /// </summary>
        public PageInstrumentationService PageInstrumentation {
            get { 
                if(_pageInstrumentationService == null) {
                    _pageInstrumentationService = new PageInstrumentationService();
                }
                return _pageInstrumentationService;
            }
        }
 
        /*
         * The virtual path used to get config settings.  This allows the user
         * to specify a non default config path, without having to pass it to every
         * configuration call.
         */
        internal VirtualPath ConfigurationPath {
            get {
                if (_configurationPath == null)
                    _configurationPath = _request.FilePathObject;
 
                return _configurationPath;
            }
 
            set {
                _configurationPath = value;
                _configurationPathData = null;
                _filePathData = null;
            }
        }
 
        internal CachedPathData GetFilePathData() {
            if (_filePathData == null) {
                _filePathData = CachedPathData.GetVirtualPathData(_request.FilePathObject, false);
            }
 
            return _filePathData;
        }
 
        internal CachedPathData GetConfigurationPathData() {
            if (_configurationPath == null) {
                return GetFilePathData();
            }
 
            // 
            if (_configurationPathData == null) {
                _configurationPathData = CachedPathData.GetVirtualPathData(_configurationPath, true);
            }
 
            return _configurationPathData;
        }
 
        internal CachedPathData GetPathData(VirtualPath path) {
            if (path != null) {
                if (path.Equals(_request.FilePathObject)) {
                    return GetFilePathData();
                }
 
                if (_configurationPath != null && path.Equals(_configurationPath)) {
                    return GetConfigurationPathData();
                }
            }
 
            return CachedPathData.GetVirtualPathData(path, false);
        }
 
        internal void FinishRequestForCachedPathData(int statusCode) {
            // Remove the cached path data for a file path if the first request for it
            // does not succeed due to a bad request. Otherwise we could be vulnerable
            // to a DOS attack.
            if (_filePathData != null && !_filePathData.CompletedFirstRequest) {
                if (400 <= statusCode && statusCode < 500) {
                    CachedPathData.RemoveBadPathData(_filePathData);
                }
                else {
                    CachedPathData.MarkCompleted(_filePathData);
                }
            }
        }
 
        /*
         * Uses the Config system to get the specified configuraiton
         */
        [Obsolete("The recommended alternative is System.Web.Configuration.WebConfigurationManager.GetWebApplicationSection in System.Web.dll. http://go.microsoft.com/fwlink/?linkid=14202")]
        public static object GetAppConfig(String name) {
            return WebConfigurationManager.GetWebApplicationSection(name);
        }
 
        [Obsolete("The recommended alternative is System.Web.HttpContext.GetSection in System.Web.dll. http://go.microsoft.com/fwlink/?linkid=14202")]
        public object GetConfig(String name) {
            return GetSection(name);
        }
 
        public object GetSection(String sectionName) {
            if (HttpConfigurationSystem.UseHttpConfigurationSystem) {
                return GetConfigurationPathData().ConfigRecord.GetSection(sectionName);
            }
            else {
                return ConfigurationManager.GetSection(sectionName);
            }
        }
 
        internal RuntimeConfig GetRuntimeConfig() {
            return GetConfigurationPathData().RuntimeConfig;
        }
 
        internal RuntimeConfig GetRuntimeConfig(VirtualPath path) {
            return GetPathData(path).RuntimeConfig;
        }
 
        public void RewritePath(String path) {
            RewritePath(path, true);
        }
 
        /*
         * Called by the URL rewrite module to modify the path for downstream modules
         */
 
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        public void RewritePath(String path, bool rebaseClientPath) {
            if (path == null)
                throw new ArgumentNullException("path");
 
            // extract query string
            String qs = null;
            int iqs = path.IndexOf('?');
            if (iqs >= 0) {
                qs = (iqs < path.Length-1) ? path.Substring(iqs+1) : String.Empty;
                path = path.Substring(0, iqs);
            }
 
            // resolve relative path
            VirtualPath virtualPath = VirtualPath.Create(path);
            virtualPath = Request.FilePathObject.Combine(virtualPath);
 
            // disallow paths outside of app
            virtualPath.FailIfNotWithinAppRoot();
 
            // clear things that depend on path
            ConfigurationPath = null;
 
            // rewrite path on request
            Request.InternalRewritePath(virtualPath, qs, rebaseClientPath);
        }
 
 
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        public void RewritePath(String filePath, String pathInfo, String queryString) {
            RewritePath(VirtualPath.CreateAllowNull(filePath), VirtualPath.CreateAllowNull(pathInfo),
                queryString, false /*setClientFilePath*/);
        }
        public void RewritePath(string filePath, string pathInfo, String queryString, bool setClientFilePath)
        {
            RewritePath(VirtualPath.CreateAllowNull(filePath), VirtualPath.CreateAllowNull(pathInfo), queryString, setClientFilePath);
        }
        internal void RewritePath(VirtualPath filePath, VirtualPath pathInfo, String queryString, bool setClientFilePath) {
            EnsureHasNotTransitionedToWebSocket();
 
            if (filePath == null)
                throw new ArgumentNullException("filePath");
 
            // resolve relative path
            filePath = Request.FilePathObject.Combine(filePath);
 
            // disallow paths outside of app
            filePath.FailIfNotWithinAppRoot();
 
            // clear things that depend on path
            ConfigurationPath = null;
 
            // rewrite path on request
            Request.InternalRewritePath(filePath, pathInfo, queryString, setClientFilePath);
        }
 
        internal CultureInfo DynamicCulture {
            get { return _dynamicCulture; }
            set { _dynamicCulture = value; }
        }
 
        internal CultureInfo DynamicUICulture {
            get { return _dynamicUICulture; }
            set { _dynamicUICulture = value; }
        }
 
        public static object GetGlobalResourceObject(string classKey, string resourceKey) {
            return GetGlobalResourceObject(classKey, resourceKey, null);
        }
 
        public static object GetGlobalResourceObject(string classKey, string resourceKey, CultureInfo culture) {
            return ResourceExpressionBuilder.GetGlobalResourceObject(classKey, resourceKey, null, null, culture);
        }
 
        public static object GetLocalResourceObject(string virtualPath, string resourceKey) {
            return GetLocalResourceObject(virtualPath, resourceKey, null);
        }
 
        public static object GetLocalResourceObject(string virtualPath, string resourceKey, CultureInfo culture) {
            IResourceProvider pageProvider = ResourceExpressionBuilder.GetLocalResourceProvider(
                VirtualPath.Create(virtualPath));
            return ResourceExpressionBuilder.GetResourceObject(pageProvider, resourceKey, culture);
        }
 
        internal int ServerExecuteDepth {
            get { return _serverExecuteDepth; }
            set { _serverExecuteDepth = value; }
        }
 
        internal bool PreventPostback {
            get { return _preventPostback; }
            set { _preventPostback = value; }
        }
 
        //
        // Timeout support
        //
 
        internal Thread CurrentThread {
            get {
                return _thread;
            }
            set {
                _thread = value;
            }
        }
 
        // Property is thread-safe since needs to be accessed by RequestTimeoutManager in addition to
        // normal request threads.
        internal TimeSpan Timeout {
            get {
                long ticks = EnsureTimeout();
                return TimeSpan.FromTicks(ticks);
            }
 
            set {
                Interlocked.Exchange(ref _timeoutTicks, value.Ticks);
            }
        }
 
        // Access via HttpRequest.TimedOutToken instead.
        internal CancellationToken TimedOutToken {
            get {
                // If we are the first call site to observe the token, then create it in the non-canceled state.
                CancellationTokenHelper helper = LazyInitializer.EnsureInitialized(ref _timeoutCancellationTokenHelper, () => new CancellationTokenHelper(canceled: false));
                return helper.Token;
            }
        }
 
        /// <summary>
        /// Determines whether the ASP.NET runtime calls Thread.Abort() on the thread servicing this request when
        /// the request times out. Default value is 'true'.
        /// </summary>
        /// <remarks>
        /// Handlers and modules that are using Request.TimedOutToken to implement cooperative cancellation may
        /// wish to disable the rude Thread.Abort behavior that ASP.NET has historically performed when a request
        /// times out. This can help developers make sure that their g----ful cancellation + cleanup routines
        /// will run without interruption by ASP.NET.
        /// 
        /// The rules for determining when a thread is aborted are somewhat complicated, so applications shouldn't
        /// try to depend on them. Currently, the behavior is:
        /// 
        /// - The thread will be aborted at some point after Request.TimedOutToken is canceled. The abort might not
        ///   occur immediately afterward, as the "should Thread.Abort" timer is separate from the "should signal
        ///   the CancellationToken" timer.
        /// 
        /// - We generally don't abort threads that are processing async modules or handlers. There are some
        ///   exceptions. E.g., during certain parts of the lifecycle for async WebForms pages, the thread can be
        ///   a candidate to be aborted when a timeout occurs.
        ///   
        /// If a developer sets this property to 'false', ASP.NET will not automatically display a "Request timed
        /// out" YSOD when a timeout occurs. If this happens the application is responsible for setting the response
        /// content appropriately.
        /// </remarks>
        public bool ThreadAbortOnTimeout {
            get { return Volatile.Read(ref _threadAbortOnTimeout); }
            set { Volatile.Write(ref _threadAbortOnTimeout, value); }
        }
 
        private void DisposeTimedOutToken() {
            // If we are the first call site to observe the token, then create it in the disposed state.
            CancellationTokenHelper helper = LazyInitializer.EnsureInitialized(ref _timeoutCancellationTokenHelper, () => CancellationTokenHelper.StaticDisposed);
            helper.Dispose();
        }
 
        internal long EnsureTimeout() {
            // Calls to Volatile.* are atomic, even for 64-bit fields.
            long ticks = Volatile.Read(ref _timeoutTicks);
            if (ticks == -1) {
                // Only go to config if the value hasn't yet been initialized.
                HttpRuntimeSection cfg = RuntimeConfig.GetConfig(this).HttpRuntime;
                ticks = cfg.ExecutionTimeout.Ticks;
 
                // If another thread already came in and initialized _timeoutTicks,
                // return that value instead of the value we just read from config.
                long originalTicks = Interlocked.CompareExchange(ref _timeoutTicks, ticks, -1);
                if (originalTicks != -1) {
                    ticks = originalTicks;
                }
            }
 
            return ticks;
        }
 
        internal DoubleLink TimeoutLink {
            get { return _timeoutLink;}
            set { _timeoutLink = value;}
        }
 
        /*
 
        Notes on the following 5 functions:
 
        Execution can be cancelled only during certain periods, when inside the catch
        block for ThreadAbortException.  These periods are marked with the value of
        _timeoutState of 1.
 
        There is potential [rare] race condition when the timeout thread would call
        thread.abort but the execution logic in the meantime escapes the catch block.
        To avoid such race conditions _timeoutState of -1 (cancelled) is introduced.
        The timeout thread sets _timeoutState to -1 before thread abort and the
        unwinding logic just waits for the exception in this case. The wait cannot
        be done in EndCancellablePeriod because the function is call from inside of
        a finally block and thus would wait indefinetely. That's why another function
        WaitForExceptionIfCancelled had been added.
 
        Originally _timeoutStartTime was set in BeginCancellablePeriod. However, that means
        we'll call UtcNow everytime we call ExecuteStep, which is too expensive. So to save
        CPU time we created a new method SetStartTime() which is called by the caller of
        ExecuteStep.
 
        */
 
        internal void BeginCancellablePeriod() {
            // It could be caused by an exception in OnThreadStart
            if (Volatile.Read(ref _timeoutStartTimeUtcTicks) == -1) {
                SetStartTime();
            }
 
            Volatile.Write(ref _timeoutState, 1);
        }
 
        internal void SetStartTime() {
            Interlocked.Exchange(ref _timeoutStartTimeUtcTicks, DateTime.UtcNow.Ticks);
        }
 
        internal void EndCancellablePeriod() {
            Interlocked.CompareExchange(ref _timeoutState, 0, 1);
        }
 
        internal void WaitForExceptionIfCancelled() {
            while (Volatile.Read(ref _timeoutState) == -1)
                Thread.Sleep(100);
        }
 
        internal bool IsInCancellablePeriod {
            get { return (Volatile.Read(ref _timeoutState) == 1); }
        }
 
        internal Thread MustTimeout(DateTime utcNow) {
            // Note: The TimedOutToken is keyed off of the HttpContext creation time, not the most recent async
            // completion time (like the Thread.Abort logic later in this method).
 
            if (_utcTimestamp + Timeout < utcNow) {
                // If we are the first call site to observe the token, then create it in the canceled state.
                CancellationTokenHelper helper = LazyInitializer.EnsureInitialized(ref _timeoutCancellationTokenHelper, () => new CancellationTokenHelper(canceled: true));
                helper.Cancel();
            }
 
            if (Volatile.Read(ref _timeoutState) == 1 && ThreadAbortOnTimeout) {  // fast check
                long expirationUtcTicks = Volatile.Read(ref _timeoutStartTimeUtcTicks) + Timeout.Ticks; // don't care about overflow
                if (expirationUtcTicks < utcNow.Ticks) {
                    // don't abort in debug mode
                    try {
                        if (CompilationUtil.IsDebuggingEnabled(this) || System.Diagnostics.Debugger.IsAttached)
                            return null;
                    }
                    catch {
                        // ignore config errors
                        return null;
                    }
 
                    // abort the thread only if in cancelable state, avoiding race conditions
                    // the caller MUST timeout if the return is true
                    if (Interlocked.CompareExchange(ref _timeoutState, -1, 1) == 1) {
                        if (_wr.IsInReadEntitySync) {
                            AbortConnection();
                        }
                        return _thread;
                    }
                }
            }
 
            return null;
        }
 
        internal bool HasTimeoutExpired {
            get {
                // Check if it is allowed to timeout
                if (Volatile.Read(ref _timeoutState) != 1 || !ThreadAbortOnTimeout) {
                    return false;
                }
 
                // Check if the timeout has expired
                long expirationUtcTicks = Volatile.Read(ref _timeoutStartTimeUtcTicks) + Timeout.Ticks; // don't care about overflow
                if (expirationUtcTicks >= DateTime.UtcNow.Ticks) {
                    return false;
                }
 
                // Dont't timeout when in debug
                try {
                    if (CompilationUtil.IsDebuggingEnabled(this) || System.Diagnostics.Debugger.IsAttached) {
                        return false;
                    }
                }
                catch {
                    // ignore config errors
                    return false;
                }
 
                return true;
            }
        }
 
        // call a delegate within cancellable period (possibly throwing timeout exception)
        internal void InvokeCancellableCallback(WaitCallback callback, Object state) {
            if (IsInCancellablePeriod) {
                // call directly
                callback(state);
                return;
            }
 
            try {
                BeginCancellablePeriod();  // request can be cancelled from this point
 
                try {
                    callback(state);
                }
                finally {
                    EndCancellablePeriod();  // request can be cancelled until this point
                }
 
                WaitForExceptionIfCancelled();  // wait outside of finally
            }
            catch (ThreadAbortException e) {
                if (e.ExceptionState != null &&
                    e.ExceptionState is HttpApplication.CancelModuleException &&
                    ((HttpApplication.CancelModuleException)e.ExceptionState).Timeout) {
 
                    Thread.ResetAbort();
                    PerfCounters.IncrementCounter(AppPerfCounter.REQUESTS_TIMED_OUT);
 
                    throw new HttpException(SR.GetString(SR.Request_timed_out),
                                        null, WebEventCodes.RuntimeErrorRequestAbort);
                }
            }
        }
 
        internal void PushTraceContext() {
            if (_traceContextStack == null) {
                _traceContextStack = new Stack();
            }
 
            // push current TraceContext on stack
            _traceContextStack.Push(_topTraceContext);
 
            // now make a new one for the top if necessary
            if (_topTraceContext != null) {
                TraceContext tc = new TraceContext(this);
                _topTraceContext.CopySettingsTo(tc);
                _topTraceContext = tc;
            }
        }
 
        internal void PopTraceContext() {
            Debug.Assert(_traceContextStack != null);
            _topTraceContext = (TraceContext) _traceContextStack.Pop();
        }
 
        internal bool RequestRequiresAuthorization()  {
#if !FEATURE_PAL // FEATURE_PAL does not enable IIS-based hosting features
            // if current user is anonymous, then trivially, this page does not require authorization
            if (!User.Identity.IsAuthenticated)
                return false;
 
            // Ask each of the authorization modules
            return
                ( FileAuthorizationModule.RequestRequiresAuthorization(this) ||
                  UrlAuthorizationModule.RequestRequiresAuthorization(this)   );
#else // !FEATURE_PAL
                return false; // ROTORTODO
#endif // !FEATURE_PAL
        }
 
        internal int CallISAPI(UnsafeNativeMethods.CallISAPIFunc iFunction, byte [] bufIn, byte [] bufOut) {
 
            if (_wr == null || !(_wr is System.Web.Hosting.ISAPIWorkerRequest))
                throw new HttpException(SR.GetString(SR.Cannot_call_ISAPI_functions));
#if !FEATURE_PAL // FEATURE_PAL does not enable IIS-based hosting features
            return ((System.Web.Hosting.ISAPIWorkerRequest) _wr).CallISAPI(iFunction, bufIn, bufOut);
#else // !FEATURE_PAL
                throw new NotImplementedException ("ROTORTODO");
#endif // !FEATURE_PAL
        }
 
        internal void SendEmptyResponse() {
#if !FEATURE_PAL // FEATURE_PAL does not enable IIS-based hosting features
            if (_wr != null  && (_wr is System.Web.Hosting.ISAPIWorkerRequest))
                ((System.Web.Hosting.ISAPIWorkerRequest) _wr).SendEmptyResponse();
#endif // !FEATURE_PAL
        }
 
        private  CookielessHelperClass _CookielessHelper;
        internal CookielessHelperClass  CookielessHelper {
            get {
                if (_CookielessHelper == null)
                    _CookielessHelper = new CookielessHelperClass(this);
                return _CookielessHelper;
            }
        }
 
 
        // When a thread enters the pipeline, we may need to set the cookie in the CallContext.
        internal void ResetSqlDependencyCookie() {
            if (_sqlDependencyCookie != null) {
                System.Runtime.Remoting.Messaging.CallContext.LogicalSetData(SqlCacheDependency.SQL9_OUTPUT_CACHE_DEPENDENCY_COOKIE, _sqlDependencyCookie);
            }
        }
 
        // When a thread leaves the pipeline, we may need to remove the cookie from the CallContext.
        internal void RemoveSqlDependencyCookie() {
            if (_sqlDependencyCookie != null) {
                System.Runtime.Remoting.Messaging.CallContext.LogicalSetData(SqlCacheDependency.SQL9_OUTPUT_CACHE_DEPENDENCY_COOKIE, null);
            }
        }
 
        internal string SqlDependencyCookie {
            get {
                return _sqlDependencyCookie;
            }
 
            set {
                _sqlDependencyCookie = value;
                System.Runtime.Remoting.Messaging.CallContext.LogicalSetData(SqlCacheDependency.SQL9_OUTPUT_CACHE_DEPENDENCY_COOKIE, value);
            }
        }
 
        //
        // integrated pipeline related
        //
        internal NotificationContext NotificationContext {
            get { return _notificationContext; }
            set { _notificationContext = value; }
        }
 
        public RequestNotification CurrentNotification {
            get {
                EnsureHasNotTransitionedToWebSocket();
 
                if (!HttpRuntime.UseIntegratedPipeline) {
                    throw new PlatformNotSupportedException(SR.GetString(SR.Requires_Iis_Integrated_Mode));
                }
 
                return _notificationContext.CurrentNotification;
            }
            internal set {
                if (!HttpRuntime.UseIntegratedPipeline) {
                    throw new PlatformNotSupportedException(SR.GetString(SR.Requires_Iis_Integrated_Mode));
                }
 
                _notificationContext.CurrentNotification = value;
            }
        }
 
        internal bool IsChangeInServerVars {
            get { return (_notificationContext.CurrentNotificationFlags & FLAG_CHANGE_IN_SERVER_VARIABLES) == FLAG_CHANGE_IN_SERVER_VARIABLES; }
        }
 
        internal bool IsChangeInRequestHeaders {
            get { return (_notificationContext.CurrentNotificationFlags & FLAG_CHANGE_IN_REQUEST_HEADERS) == FLAG_CHANGE_IN_REQUEST_HEADERS; }
        }
 
        internal bool IsChangeInResponseHeaders {
            get { return (_notificationContext.CurrentNotificationFlags & FLAG_CHANGE_IN_RESPONSE_HEADERS) == FLAG_CHANGE_IN_RESPONSE_HEADERS; }
        }
 
        internal bool IsChangeInResponseStatus {
            get { return (_notificationContext.CurrentNotificationFlags & FLAG_CHANGE_IN_RESPONSE_STATUS) == FLAG_CHANGE_IN_RESPONSE_STATUS; }
        }
 
        internal bool IsChangeInUserPrincipal {
            get { return (_notificationContext.CurrentNotificationFlags & FLAG_CHANGE_IN_USER_OBJECT) == FLAG_CHANGE_IN_USER_OBJECT; }
        }
 
        internal bool IsRuntimeErrorReported {
            get { return _runtimeErrorReported; }
        }
 
        internal bool IsSendResponseHeaders {
            get { return (_notificationContext.CurrentNotificationFlags & FLAG_SEND_RESPONSE_HEADERS) == FLAG_SEND_RESPONSE_HEADERS; }
        }
 
        internal void SetImpersonationEnabled() {
            IdentitySection c = RuntimeConfig.GetConfig(this).Identity;
            _impersonationEnabled = (c != null && c.Impersonate);
        }
 
        internal bool UsesImpersonation {
            get {
                // if we're on a UNC share and we have a UNC token, then use impersonation for all notifications
                if (HttpRuntime.IsOnUNCShareInternal && HostingEnvironment.ApplicationIdentityToken != IntPtr.Zero) {
                    return true;
                }
                // if <identity impersonate=/> is false, then don't use impersonation
                if (!_impersonationEnabled) {
                    return false;
                }
                // the notification context won't be available after we have completed the transition
                if (HasWebSocketRequestTransitionCompleted) {
                    return true;
                }
 
                // if this notification is after AuthenticateRequest and not a SendResponse notification, use impersonation
                return (((_notificationContext.CurrentNotification == RequestNotification.AuthenticateRequest && _notificationContext.IsPostNotification)
                        || _notificationContext.CurrentNotification > RequestNotification.AuthenticateRequest)
                        && _notificationContext.CurrentNotification != RequestNotification.SendResponse);
            }
        }
 
        internal bool AreResponseHeadersSent {
            get { return (_notificationContext.CurrentNotificationFlags & FLAG_RESPONSE_HEADERS_SENT) == FLAG_RESPONSE_HEADERS_SENT; }
        }
 
        internal bool NeedToInitializeApp() {
            bool needToInit = !_isAppInitialized;
            if (needToInit) {
                _isAppInitialized = true;
            }
            return needToInit;
        }
 
        // flags passed in on the call to PipelineRuntime::ProcessRequestNotification
        internal int CurrentNotificationFlags {
            get {
                return _notificationContext.CurrentNotificationFlags;
            }
            set {
                _notificationContext.CurrentNotificationFlags = value;
            }
        }
 
        // index of the current "module" running the request
        // into the application module array
        internal int CurrentModuleIndex {
            get {
                return _notificationContext.CurrentModuleIndex;
            }
            set {
                _notificationContext.CurrentModuleIndex = value;
            }
        }
 
        // Each module has a PipelineModuleStepContainer
        // which stores/manages a list of event handlers
        // that correspond to each RequestNotification.
        // CurrentModuleEventIndex is the index (for the current
        // module) of the current event handler.
        // This will be greater than one when a single
        // module registers multiple delegates for a single event.
        // e.g.
        // app.BeginRequest += Foo;
        // app.BeginRequest += Bar;
        internal int CurrentModuleEventIndex {
            get {
                return _notificationContext.CurrentModuleEventIndex;
            }
            set {
                _notificationContext.CurrentModuleEventIndex = value;
            }
        }
 
        internal void DisableNotifications(RequestNotification notifications, RequestNotification postNotifications) {
            IIS7WorkerRequest wr = _wr as IIS7WorkerRequest;
            if (null != wr) {
                wr.DisableNotifications(notifications, postNotifications);
            }
        }
 
        public bool IsPostNotification {
            get {
                EnsureHasNotTransitionedToWebSocket();
 
                if (!HttpRuntime.UseIntegratedPipeline) {
                    throw new PlatformNotSupportedException(SR.GetString(SR.Requires_Iis_Integrated_Mode));
                }
                return _notificationContext.IsPostNotification;
            }
            internal set {
                if (!HttpRuntime.UseIntegratedPipeline) {
                    throw new PlatformNotSupportedException(SR.GetString(SR.Requires_Iis_Integrated_Mode));
                }
                _notificationContext.IsPostNotification = value;
            }
 
        }
 
        // user token for the request
        [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification = "This is a safe critical method.")]
        internal IntPtr ClientIdentityToken {
            get {
                if (_wr != null) {
                    return _wr.GetUserToken();
                }
                else {
                    return IntPtr.Zero;
                }
            }
        }
 
        // is configured to impersonate client?
        internal bool IsClientImpersonationConfigured {
            get {
                try {
                    IdentitySection c = RuntimeConfig.GetConfig(this).Identity;
                    return (c != null && c.Impersonate && c.ImpersonateToken == IntPtr.Zero);
                }
                catch {
                    // this property should not throw as it is used in the error reporting pass
                    // config errors will be reported elsewhere
                    return false;
                }
            }
        }
 
        internal IntPtr ImpersonationToken {
            get {
                // by default use app identity
                IntPtr token = HostingEnvironment.ApplicationIdentityToken;
                IdentitySection c = RuntimeConfig.GetConfig(this).Identity;
                if (c != null) {
                    if (c.Impersonate) {
                        token = (c.ImpersonateToken != IntPtr.Zero) ? c.ImpersonateToken : ClientIdentityToken;
                    }
                    else {
                        // for non-UNC case impersonate="false" means "don't impersonate",
                        // but there is a special case for UNC shares - even if
                        // impersonate="false" we still impersonate the UNC identity
                        // (hosting identity). and this is how v1.x works as well
                        if (!HttpRuntime.IsOnUNCShareInternal) {
                            token = IntPtr.Zero;
                        }
                    }
                }
                return token;
            }
        }
 
        internal AspNetSynchronizationContextBase SyncContext {
            get {
                if (_syncContext == null) {
                    _syncContext = CreateNewAspNetSynchronizationContext();
                }
 
                return _syncContext;
            }
            set {
                _syncContext = value;
            }
        }
 
        internal AspNetSynchronizationContextBase InstallNewAspNetSynchronizationContext() {
            AspNetSynchronizationContextBase syncContext = _syncContext;
 
            if (syncContext != null && syncContext == AsyncOperationManager.SynchronizationContext) {
                // using current ASP.NET synchronization context - switch it
                _syncContext = CreateNewAspNetSynchronizationContext();
                AsyncOperationManager.SynchronizationContext = _syncContext;
                return syncContext;
            }
 
            return null;
        }
 
        private AspNetSynchronizationContextBase CreateNewAspNetSynchronizationContext() {
            if (!AppSettings.UseTaskFriendlySynchronizationContext) {
                return new LegacyAspNetSynchronizationContext(ApplicationInstance);
            }
            else {
                return new AspNetSynchronizationContext(ApplicationInstance);
            }
        }
 
        [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification = "This is a safe critical method.")]
        internal void RestoreSavedAspNetSynchronizationContext(AspNetSynchronizationContextBase syncContext) {
            AsyncOperationManager.SynchronizationContext = syncContext;
            _syncContext = syncContext;
        }
 
        internal string[] UserLanguagesFromContext() {
            return (Request != null) ? Request.UserLanguages : null;
        }
 
        // References should be nulled a.s.a.p. to reduce working set
        internal void ClearReferences() {
            _appInstance = null;
            _handler = null;
            _handlerStack = null;
            _currentHandler = null;
            _remapHandler = null;
            if (_isIntegratedPipeline) {
                if (!HasWebSocketRequestTransitionStarted) {
                    // Items is also used by AspNetWebSocketContext and should only be cleared if we're not transitioning to WebSockets
                    _items = null;
                }
                _syncContext = null;
            }
        }
 
        internal void CompleteTransitionToWebSocket() {
            ClearReferencesForWebSocketProcessing();
 
            // transition: TransitionStarted -> TransitionCompleted
            TransitionToWebSocketState(WebSocketTransitionState.TransitionCompleted);
        }
 
        // This is much stronger than just ClearReferences; it tries to free absolutely as much memory as possible.
        // Some necessary items (like _wr, etc.) are preserved. The reason we want to modify this particular instance
        // in-place rather than create a new instance is that it is likely that references to this object still exist,
        // and we don't want the existence of those references to cause memory leaks.
        private void ClearReferencesForWebSocketProcessing() {
            HttpResponse response = _response;
 
            // everything not marked [DoNotReset] should be eligible for garbage collection
            ReflectionUtil.Reset(this);
 
            // Miscellaneous steps:
            _request.ClearReferencesForWebSocketProcessing(); // also clean up the HttpRequest instance
            if (response != null) {
                // HttpResponse is off-limits, but it is possible that the developer accidentally maintained a reference
                // to it, e.g. via a closure. We'll release the HttpResponse's references to all its data to prevent
                // this from causing memory problems.
                ReflectionUtil.Reset(response);
            }
        }
 
        internal CultureInfo CultureFromConfig(string configString, bool requireSpecific) {
            //auto
            if(StringUtil.EqualsIgnoreCase(configString, HttpApplication.AutoCulture)) {
                string[] userLanguages = UserLanguagesFromContext();
                if (userLanguages != null) {
                    try {
                        return CultureUtil.CreateReadOnlyCulture(userLanguages, requireSpecific);
                    }
                    catch {
                        return null;
                    }
                }
                else {
                    return null;
                }
            }
            else if(StringUtil.StringStartsWithIgnoreCase(configString, "auto:")) {
                string[] userLanguages = UserLanguagesFromContext();
                if (userLanguages != null) {
                    try {
                        return CultureUtil.CreateReadOnlyCulture(userLanguages, requireSpecific);
                    }
                    catch {
                        return CultureUtil.CreateReadOnlyCulture(configString.Substring(5 /* "auto:".Length */), requireSpecific);
                    }
                }
                else {
                    return CultureUtil.CreateReadOnlyCulture(configString.Substring(5 /* "auto:".Length */), requireSpecific);
                }
            }
 
            return CultureUtil.CreateReadOnlyCulture(configString, requireSpecific);
        }
 
        private enum WebSocketInitStatus {
            Success, // iiswsock.dll is active and has told us that the current request is a WebSocket request
            RequiresIntegratedMode, // WebSockets requires integrated mode, and the current server is not Integrated mode
            CannotCallFromBeginRequest, // We need to wait for BeginRequest to complete before the module has set the server variables
            NativeModuleNotEnabled, // iiswsock.dll isn't active in the pipeline
            NotAWebSocketRequest, // iiswsock.dll is active, but the current request is not a WebSocket request
            CurrentRequestIsChildRequest, // We are currently inside of a child request (IHttpContext::ExecuteRequest)
        }
 
        private void AbortConnection() {
            IIS7WorkerRequest wr = _wr as IIS7WorkerRequest;
 
            if (wr != null) { 
                // Direct API Abort is suported in integrated mode only
                wr.AbortConnection();
            }
            else {
                // Close in classic mode acts as Abort (see HSE_REQ_CLOSE_CONNECTION) 
                // It closes the underlined connection
                _wr.CloseConnection();
            }
        }
    }
 
    //
    // Helper class to add/remove HttpContext to/from CallContext
    //
    // using (new DisposableHttpContextWrapper(context)) {
    //     // this code will have HttpContext.Current working
    // }
    //
 
    internal class DisposableHttpContextWrapper : IDisposable {
        private bool _needToUndo;
        private HttpContext _savedContext;
 
        internal static HttpContext SwitchContext(HttpContext context) {
            return ContextBase.SwitchContext(context) as HttpContext;
        }
 
        internal DisposableHttpContextWrapper(HttpContext context) {
            if (context != null) {
                _savedContext = SwitchContext(context);
                _needToUndo = (_savedContext != context);
            }
        }
 
        void IDisposable.Dispose() {
            if (_needToUndo) {
                SwitchContext(_savedContext);
                _savedContext = null;
                _needToUndo = false;
            }
        }
    }
}