ServiceHostingEnvironment.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / WCF / System.ServiceModel.Activation / System / ServiceModel / ServiceHostingEnvironment.cs / 1438166 / ServiceHostingEnvironment.cs

                            //---------------------------------------------------------------------------- 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//---------------------------------------------------------------------------
namespace System.ServiceModel
{ 
    using System.Collections;
    using System.Collections.Generic; 
    using System.Configuration; 
    using System.Diagnostics;
    using System.Globalization; 
    using System.Reflection;
    using System.Runtime;
    using System.Runtime.Diagnostics;
    using System.Runtime.CompilerServices; 
    using System.Security;
    using System.Security.Permissions; 
    using System.ServiceModel.Activation; 
    using System.ServiceModel.Channels;
    using System.ServiceModel.Configuration; 
    using System.ServiceModel.Activation.Diagnostics;
    using System.ServiceModel.Description;
    using System.Threading;
    using System.Web; 
    using System.Web.Compilation;
    using System.Web.Configuration; 
    using System.Web.Hosting; 
    using System.Web.Routing;
    using System.Xaml.Hosting.Configuration; 
    using System.Text;
    using SR2 = System.ServiceModel.Activation.SR;
    using TD2 = System.ServiceModel.Diagnostics.Application.TD;
 
    [TypeForwardedFrom("System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
    public static class ServiceHostingEnvironment 
    { 
        static object syncRoot = new object();
        static HostingManager hostingManager; 
        static bool isHosted;
        static bool isSimpleApplicationHost;
        static Int64 requestCount;
        static bool didAssemblyCheck; 
        static bool isApplicationDomainHosted;
        static bool canGetHtmlErrorMessage = true; 
        static string siteName; 
        static string applicationVirtualPath;
        static string serviceActivationElementPath; 

        internal const string VerbPost = "POST";
        internal const string ISAPIApplicationIdPrefix = "/LM/W3SVC/";
        internal const string RelativeVirtualPathPrefix = "~"; 
        internal const string ServiceParserDelimiter = "|";
        internal const string RootVirtualPath = "~/"; 
        internal const string PathSeparatorString = "/"; 

        const char FileExtensionSeparator = '.'; 
        const char UriSchemeSeparator = ':';
        const char PathSeparator = '/';
        const string SystemWebComma = "System.Web,";
 
        [Fx.Tag.SecurityNote(Critical = "Calls into an unsafe UnsafeLogEvent method.",
            Safe = "Event identities cannot be spoofed as they are constants determined inside the method.")] 
        [SecuritySafeCritical] 
        static void OnUnhandledException(object sender, UnhandledExceptionEventArgs e)
        { 
            if (DiagnosticUtility.ShouldTraceError)
            {
                Exception exception = e.ExceptionObject as Exception;
                DiagnosticUtility.UnsafeEventLog.UnsafeLogEvent(TraceEventType.Error, System.ServiceModel.Diagnostics.EventLogCategory.WebHost, System.ServiceModel.Diagnostics.EventLogEventId.WebHostUnhandledException, true, 
                    TraceUtility.CreateSourceString(sender),
                    exception == null ? string.Empty : exception.ToString()); 
            } 
        }
 
        [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - called by ProcessRequest outside of the restricted SecurityContext.")]
        public static bool AspNetCompatibilityEnabled
        {
            [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - can be called outside of user context.")] 
            get
            { 
                if (!IsHosted) 
                {
                    return false; 
                }

                return IsAspNetCompatibilityEnabled();
            } 
        }
 
        [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - called by ProcessRequest outside of the restricted SecurityContext.")] 
        public static bool MultipleSiteBindingsEnabled
        { 
            [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - can be called outside of user context.")]
            get
            {
                if (!IsHosted) 
                    return false;
 
                return IsMultipleSiteBindingsEnabledEnabled(); 
            }
        } 

        [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - called by ServiceHostFactory.CreateServiceHost.")]
        internal static Uri[] PrefixFilters
        { 
            [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview")]
            get 
            { 
                if (!IsHosted)
                { 
                    return null;
                }

                return GetBaseAddressPrefixFilters(); 
            }
        } 
 
        [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - can be called outside of user context.")]
        [MethodImpl(MethodImplOptions.NoInlining)] 
        static bool IsAspNetCompatibilityEnabled()
        {
            return hostingManager.AspNetCompatibilityEnabled;
        } 

        [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - can be called outside of user context.")] 
        [MethodImpl(MethodImplOptions.NoInlining)] 
        static bool IsMultipleSiteBindingsEnabledEnabled()
        { 
            return hostingManager.MultipleSiteBindingsEnabled;
        }

        [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - can be called outside of user context.")] 
        [MethodImpl(MethodImplOptions.NoInlining)]
        static Uri[] GetBaseAddressPrefixFilters() 
        { 
            return hostingManager.BaseAddressPrefixFilters;
        } 

        public static void EnsureServiceAvailable(string virtualPath)
        {
            if (string.IsNullOrEmpty(virtualPath)) 
            {
                throw FxTrace.Exception.ArgumentNull("virtualPath"); 
            } 

            if (virtualPath.IndexOf(UriSchemeSeparator) > 0) 
            {
                throw FxTrace.Exception.Argument("virtualPath", SR2.Hosting_AddressIsAbsoluteUri(virtualPath));
            }
 
            EnsureInitialized();
            virtualPath = NormalizeVirtualPath(virtualPath); 
            EnsureServiceAvailableFast(virtualPath); 
        }
 
        internal static void EnsureServiceAvailableFast(string relativeVirtualPath)
        {
            try
            { 
                hostingManager.EnsureServiceAvailable(relativeVirtualPath);
            } 
            catch (ServiceActivationException exception) 
            {
                LogServiceActivationException(exception); 

                throw;
            }
        } 

        [Fx.Tag.SecurityNote(Critical = "Calls into an unsafe UnsafeLogEvent method.", 
            Safe = "Event identities cannot be spoofed as they are constants determined inside the method.")] 
        [SecuritySafeCritical]
        private static void LogServiceActivationException(ServiceActivationException exception) 
        {
            if (exception.InnerException is HttpException)
            {
                string messageAsString = SafeTryGetHtmlErrorMessage((HttpException)exception.InnerException); 
                if (string.IsNullOrEmpty(messageAsString))
                { 
                    messageAsString = exception.Message; 
                }
                DiagnosticUtility.UnsafeEventLog.UnsafeLogEvent(TraceEventType.Error, System.ServiceModel.Diagnostics.EventLogCategory.WebHost, System.ServiceModel.Diagnostics.EventLogEventId.WebHostHttpError, true, 
                    TraceUtility.CreateSourceString(hostingManager),
                    messageAsString, exception.ToString());
            }
            else 
            {
                DiagnosticUtility.UnsafeEventLog.UnsafeLogEvent(TraceEventType.Error, System.ServiceModel.Diagnostics.EventLogCategory.WebHost, System.ServiceModel.Diagnostics.EventLogEventId.WebHostFailedToProcessRequest, true, 
                    TraceUtility.CreateSourceString(hostingManager), exception.ToString()); 
            }
            if (TD2.ServiceExceptionIsEnabled()) 
            {
                TD2.ServiceException(exception.ToString(), typeof(ServiceActivationException).FullName);

            } 
        }
 
        static string SafeTryGetHtmlErrorMessage(HttpException exception) 
        {
            if (exception != null && canGetHtmlErrorMessage) 
            {
                try
                {
                    return exception.GetHtmlErrorMessage(); 
                }
                catch (SecurityException e) 
                { 
                    canGetHtmlErrorMessage = false;
 
                    // not re-throwing on purpose
                    if (DiagnosticUtility.ShouldTraceWarning)
                    {
                        DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Warning); 
                    }
                } 
            } 
            return null;
        } 

        [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - can be called outside of user context.")]
        internal static void IncrementRequestCount()
        { 
            Interlocked.Increment(ref requestCount);
            if (TD.WebHostRequestStartIsEnabled()) 
            { 
                TD.WebHostRequestStart();
            } 
        }

        internal static void DecrementRequestCount()
        { 
            Interlocked.Decrement(ref requestCount);
            Fx.Assert(requestCount >= 0, "Request count should always be non-nagative."); 
            if (requestCount == 0) 
            {
                if (hostingManager != null) 
                {
                    hostingManager.NotifyAllRequestDone();
                }
            } 
            if (TD.WebHostRequestStopIsEnabled())
            { 
                TD.WebHostRequestStop(); 
            }
        } 

        internal static string CurrentVirtualPath
        {
            get 
            {
                Fx.Assert(IsHosted, "CurrentVirtualPath should not be called from non web-hosted environment."); 
                return HostingManager.CurrentVirtualPath; 
            }
        } 

        internal static string ServiceActivationElementPath
        {
            get 
            {
                if (ServiceHostingEnvironment.serviceActivationElementPath == null) 
                { 
                    ServiceHostingEnvironment.serviceActivationElementPath = string.Format(CultureInfo.CurrentCulture, "{0}/{1}",
                        ConfigurationStrings.ServiceHostingEnvironmentSectionPath, ConfigurationStrings.ServiceActivations); 
                }
                return ServiceHostingEnvironment.serviceActivationElementPath;
            }
        } 

        internal static string SiteName 
        { 
            get
            { 
                if (ServiceHostingEnvironment.siteName == null)
                {
                    ServiceHostingEnvironment.siteName = HostingEnvironment.SiteName;
                } 
                return ServiceHostingEnvironment.siteName;
            } 
        } 

        internal static string ApplicationVirtualPath 
        {
            get
            {
                if (ServiceHostingEnvironment.applicationVirtualPath == null) 
                {
                    ServiceHostingEnvironment.applicationVirtualPath = HostingEnvironment.ApplicationVirtualPath; 
                } 
                return ServiceHostingEnvironment.applicationVirtualPath;
            } 
        }
        internal static string FullVirtualPath
        {
            get 
            {
                Fx.Assert(IsHosted, "FullVirtualPath should not be called from non web-hosted environment."); 
                return HostingManager.FullVirtualPath; 
            }
        } 
        internal static string XamlFileBaseLocation
        {
            get
            { 
                Fx.Assert(IsHosted, "XamlFileBaseLocation should not be called from non web-hosted environment.");
                return HostingManager.XamlFileBaseLocation; 
            } 
        }
        internal static bool IsConfigurationBased 
        {
            get
            {
                Fx.Assert(IsHosted, "IsConfigurationBased should not be called from non web-hosted environment."); 
                return HostingManager.IsConfigurationBased;
            } 
        } 

        [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - called by ProcessRequest outside of the restricted SecurityContext.")] 
        internal static ServiceType GetServiceType(string extension)
        {
            Fx.Assert(IsHosted, "GetServiceType should not be called from non web-hosted environment.");
            return hostingManager.GetServiceType(extension); 
        }
 
 
        internal static bool EnsureWorkflowService(string path)
        { 
            Fx.Assert(IsHosted, "EnsureWorkflowService should not be called from non web-hosted environment.");

            PathInfo pathInfo = PathCache.EnsurePathInfo(path);
            return pathInfo.IsWorkflowService(); 
        }
 
        internal static bool IsRecycling 
        {
            get 
            {
                Fx.Assert(IsHosted, "IsRecycling should not be called from non web-hosted environment.");
                return hostingManager.IsRecycling;
            } 
        }
 
        static object ThisLock 
        {
            get 
            {
                return syncRoot;
            }
        } 

        [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - called by ProcessRequest outside of the restricted SecurityContext.")] 
        internal static bool IsConfigurationBasedService(HttpApplication application) 
        {
            Fx.Assert(IsHosted, "IsConfigurationBased should not be called from non web-hosted environment."); 
            string dummyString;
            return IsConfigurationBasedService(application, out dummyString);
        }
 
        [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - called by MsmqHostedTransportManager outside of the restricted SecurityContext.")]
        internal static bool IsConfigurationBasedService(string virtualPath) 
        { 
            Fx.Assert(IsHosted, "IsConfigurationBased should not be called from non web-hosted environment.");
            return hostingManager.IsConfigurationBasedServiceVirtualPath(virtualPath); 
        }

        [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - called by ProcessRequest outside of the restricted SecurityContext.")]
        internal static bool IsConfigurationBasedService(HttpApplication application, out string matchedVirtualPath) 
        {
            Fx.Assert(IsHosted, "IsConfigurationBased should not be called from non web-hosted environment."); 
            bool isCBAService = false; 
            matchedVirtualPath = null;
            string virtualPath = application.Request.AppRelativeCurrentExecutionFilePath; 
            if (!string.IsNullOrEmpty(virtualPath) && hostingManager.IsConfigurationBasedServiceVirtualPath(virtualPath))
            {
                matchedVirtualPath = virtualPath;
                isCBAService = true; 
            }
            return isCBAService; 
        } 

        [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - called by ProcessRequest outside of the restricted SecurityContext.")] 
        internal static void SafeEnsureInitialized()
        {
            if (hostingManager == null)
            { 
                AspNetPartialTrustHelpers.PartialTrustInvoke(new ContextCallback(OnEnsureInitialized), null);
            } 
        } 

        [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - can be called outside of user context.")] 
        internal static void EnsureAllReferencedAssemblyLoaded()
        {
            BuildManager.GetReferencedAssemblies();
        } 

        static void OnEnsureInitialized(object state) 
        { 
            EnsureInitialized();
        } 

        internal static void EnsureInitialized()
        {
            System.ServiceModel.Diagnostics.TraceUtility.SetEtwProviderId(); 
            if (hostingManager != null)
            { 
                return; 
            }
 
            FxTrace.Trace.SetAnnotation(() => System.ServiceModel.Diagnostics.TraceUtility.GetAnnotation(OperationContext.Current));

            lock (ThisLock)
            { 
                if (hostingManager != null)
                { 
                    return; 
                }
 
                if (!HostingEnvironmentWrapper.IsHosted)
                {
                    throw FxTrace.Exception.AsError(new InvalidOperationException(SR.GetString(SR.Hosting_ProcessNotExecutingUnderHostedContext, "ServiceHostingEnvironment.EnsureServiceAvailable")));
                } 

                HostingManager tempHostingManager = new HostingManager(); 
 
                // register the following code when we use the service environment class
                // the first time 
                HookADUnhandledExceptionEvent();

                Thread.MemoryBarrier();
 
                isSimpleApplicationHost = GetIsSimpleApplicationHost();
 
                HostedAspNetEnvironment.Enable(); 
                hostingManager = tempHostingManager;
                isHosted = true; 
            }
        }

        [Fx.Tag.SecurityNote(Critical = "Satisfies a LinkDemand for SecurityPermission(ControlAppDomain) on HookADUnhandledExceptionEvent.", 
            Safe = "No control flow in for handler.")]
        [SecuritySafeCritical] 
        static void HookADUnhandledExceptionEvent() 
        {
            AppDomain.CurrentDomain.UnhandledException += OnUnhandledException; 

        }

        [Fx.Tag.SecurityNote(Critical = "Uses SecurityCritical property UnsafeApplicationID to get application id with an elevation.", 
            Safe = "Processes result into a simple bool which is not protected.")]
        [SecuritySafeCritical] 
        static bool GetIsSimpleApplicationHost() 
        {
            // ASPNET won't provide API to check Cassini. But it's safe and performant to check only 
            // the ApplicationID prefix (MessageBus Bug 24832).
            return (string.Compare(ISAPIApplicationIdPrefix, 0,
                    HostingEnvironmentWrapper.UnsafeApplicationID, 0, ISAPIApplicationIdPrefix.Length, StringComparison.OrdinalIgnoreCase) != 0);
        } 

        // customer input can be "/appname//filename" or "~//filename, we will normalize them to application relative one 
        // i.e., "~//filename 
        internal static string NormalizeVirtualPath(string virtualPath)
        { 
            string processedVirtualPath = null;

            try
            { 
                // Convert the virtual path to relative if not already is.
                processedVirtualPath = VirtualPathUtility.ToAppRelative(virtualPath, HostingEnvironmentWrapper.ApplicationVirtualPath); 
            } 
            catch (HttpException exception)
            { 
                // We want to throw an ArgumentException.
                throw FxTrace.Exception.AsError(new ArgumentException(exception.Message, "virtualPath", exception));
            }
 
            if (string.IsNullOrEmpty(processedVirtualPath) ||
                !processedVirtualPath.StartsWith(RelativeVirtualPathPrefix, StringComparison.Ordinal)) 
            { 
                throw FxTrace.Exception.Argument("virtualPath",
                    SR2.Hosting_AddressPointsOutsideTheVirtualDirectory(virtualPath, HostingEnvironmentWrapper.ApplicationVirtualPath)); 
            }

            // Find the position to start.
            int pos = processedVirtualPath.IndexOf(FileExtensionSeparator); 

            while (pos > 0) 
            { 
                // Search inside the processedVirtualPath to find the extension.
                pos = processedVirtualPath.IndexOf(PathSeparator, pos + 1); 

                string subVirtualPath = (pos == -1) ? processedVirtualPath : processedVirtualPath.Substring(0, pos);
                string extension = VirtualPathUtility.GetExtension(subVirtualPath);
                if ((!string.IsNullOrEmpty(extension)) && 
                     ServiceHostingEnvironment.GetServiceType(extension)!=ServiceType.Unknown)
                { 
                    // Remove the pathinfo. 
                    return subVirtualPath;
                } 
            }

            throw FxTrace.Exception.AsError(new EndpointNotFoundException(SR2.Hosting_ServiceNotExist(virtualPath)));
        } 

        internal static bool IsHosted 
        { 
            [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - can be called outside of user context.")]
            get 
            {
                return isHosted;
            }
        } 

        internal static bool IsSimpleApplicationHost 
        { 
            get
            { 
                Fx.Assert(IsHosted, "IsSimpleApplicationHost should not be called from non web-hosted environment.");
                return isSimpleApplicationHost;
            }
        } 

        internal static bool ApplicationDomainHosted 
        { 
            get
            { 
                if (didAssemblyCheck)
                {
                    return isApplicationDomainHosted;
                } 

                Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); 
                for (int i = 0; i < assemblies.Length; i++) 
                {
                    if (string.Compare(assemblies[i].FullName, 0, SystemWebComma, 0, SystemWebComma.Length, StringComparison.OrdinalIgnoreCase) == 0) 
                    {
                        isApplicationDomainHosted = IsApplicationDomainHosted();
                        break;
                    } 
                }
 
                didAssemblyCheck = true; 
                return isApplicationDomainHosted;
            } 
        }

        [Fx.Tag.SecurityNote(Critical = "Assert a demand for AspNetHostingPermission.",
            Safe = "Only queries if we are hosted - no actual action is initiated, no critical information is leaking.")] 
        [MethodImpl(MethodImplOptions.NoInlining)]
        [SecuritySafeCritical] 
        [AspNetHostingPermission(SecurityAction.Assert, Level = AspNetHostingPermissionLevel.Minimal)] 
        static bool IsApplicationDomainHosted()
        { 
            return HostingEnvironment.IsHosted;
        }
        internal enum ServiceType
        { 
            Unknown = 0,
            WCF, 
            Workflow 
        }
 
        class HostingManager : IRegisteredObject
        {
            readonly Hashtable directory;
            readonly ExtensionHelper extensions; 
            bool aspNetCompatibilityEnabled;
            bool multipleSiteBindingsEnabled; 
            bool isUnregistered; 
            bool isRecycling;
            bool isStopStarted; 
            static bool canDebugPrint = true;
            static object syncRoot = new object();
            Uri[] baseAddressPrefixFilters;
            Hashtable serviceActivations; 
            //used to track if HostingEnvironment.RegisterObject has been called.
            bool isRegistered; 
 
            // One instance per appdomain, don't need to be disposed.
            ManualResetEvent allRequestDoneInStop = new ManualResetEvent(false); 

            [Fx.Tag.SecurityNote(Critical = "Admin-provided value that allows for machine resource allocation.")]
            [SecurityCritical]
            int minFreeMemoryPercentageToActivateService; 

            [ThreadStatic] 
            static string currentVirtualPath; 

            [ThreadStatic] 
            static string fullVirtualPath;

            [ThreadStatic]
            static string xamlFileBaseLocation; 

            [ThreadStatic] 
            static bool isConfigurationBased; 

            [ThreadStatic] 
            static bool isAspNetRoutedRequest;

            internal HostingManager()
            { 
                this.directory = new Hashtable(16, StringComparer.OrdinalIgnoreCase);
                this.extensions = new ExtensionHelper(); 
                LoadConfigParameters(); 
            }
 

            [Fx.Tag.SecurityNote(Critical = "Uses SecurityCritical method UnsafeGetSection to get config with an elevation. Sets minFreeMemoryPercentageToActivateService",
                Safe = "Does not leak config objects.")]
            [SecuritySafeCritical] 
            void LoadConfigParameters()
            { 
                ServiceHostingEnvironmentSection section = ServiceHostingEnvironmentSection.UnsafeGetSection(); 
                this.aspNetCompatibilityEnabled = section.AspNetCompatibilityEnabled;
                this.multipleSiteBindingsEnabled = section.MultipleSiteBindingsEnabled; 
                this.minFreeMemoryPercentageToActivateService = section.MinFreeMemoryPercentageToActivateService;
                List prefixFilters = new List();

                foreach (BaseAddressPrefixFilterElement element in section.BaseAddressPrefixFilters) 
                {
                    prefixFilters.Add(element.Prefix); 
                } 
                this.baseAddressPrefixFilters = prefixFilters.ToArray();
                this.serviceActivations = new Hashtable(StringComparer.CurrentCultureIgnoreCase); 
                foreach (ServiceActivationElement element in section.ServiceActivations)
                {
                    if (string.IsNullOrEmpty(element.Factory) && string.IsNullOrEmpty(element.Service))
                    { 
                        throw FxTrace.Exception.AsError(new ConfigurationErrorsException(SR2.Hosting_NoServiceAndFactorySpecifiedForFilelessService(ConfigurationStrings.Factory, ConfigurationStrings.Service, element.RelativeAddress, ServiceActivationElementPath)));
                    } 
 
                    string normalizedRelativeAddress = NormalizedRelativeAddress(element.RelativeAddress);
                    string value = string.Format(CultureInfo.CurrentCulture, "{0}|{1}|{2}", normalizedRelativeAddress, element.Factory, element.Service); 

                    try
                    {
                        this.serviceActivations.Add(normalizedRelativeAddress, value); 
                        if (TD.CBAEntryReadIsEnabled())
                        { 
                            TD.CBAEntryRead(element.RelativeAddress, normalizedRelativeAddress); 
                        }
                    } 
                    catch (ArgumentException)
                    {
                        throw FxTrace.Exception.AsError(new ConfigurationErrorsException(SR2.Hosting_RelativeAddressHasBeenAdded(element.RelativeAddress, ServiceActivationElementPath)));
                    } 
                }
            } 
 
            [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - can be called outside of user context.")]
            internal ServiceType GetServiceType(string extension) 
            {
                return extensions.GetServiceType(extension);
            }
 
            internal bool AspNetCompatibilityEnabled
            { 
                [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - can be called outside of user context.")] 
                get
                { 
                    return this.aspNetCompatibilityEnabled;
                }
            }
 
            internal bool MultipleSiteBindingsEnabled
            { 
                [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - can be called outside of user context.")] 
                get
                { 
                    return this.multipleSiteBindingsEnabled;
                }
            }
 
            internal Uri[] BaseAddressPrefixFilters
            { 
                [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - can be called outside of user context.")] 
                get
                { 
                    return this.baseAddressPrefixFilters;
                }
            }
 
            internal static string CurrentVirtualPath
            { 
                get 
                {
                    return currentVirtualPath; 
                }
            }

            internal static string FullVirtualPath 
            {
                get 
                { 
                    return fullVirtualPath;
                } 
            }

            internal static string XamlFileBaseLocation
            { 
                get
                { 
                    return xamlFileBaseLocation; 
                }
            } 

            internal static bool IsConfigurationBased
            {
                get 
                {
                    return isConfigurationBased; 
                } 
            }
 
            internal static object ThisLock
            {
                get
                { 
                    return syncRoot;
                } 
            } 

            internal bool IsRecycling 
            {
                get
                {
                    return isRecycling; 
                }
            } 
 
            internal string NormalizedRelativeAddress(string relativeAddress)
            { 
                // since it is almost impossible for us to validate the format of a relativeAddress
                // we just take what users' inputs but we need to normalize them with a formal format
                // so that we can index them in a table.
                // we will convert "[folder/]filename.extension" to "~/[folder/]filename.extension" 
                string originalRelativeAddress = relativeAddress;
 
                try 
                {
                    if (VirtualPathUtility.IsAbsolute(relativeAddress)) 
                    {
                        throw FxTrace.Exception.AsError(new ConfigurationErrorsException(SR2.Hosting_RelativeAddressFormatError(relativeAddress)));
                    }
 
                    relativeAddress = VirtualPathUtility.Combine(RootVirtualPath, relativeAddress);
                    string extension = VirtualPathUtility.GetExtension(relativeAddress); 
                    if (string.IsNullOrEmpty(extension)) 
                    {
                        throw FxTrace.Exception.AsError(new ConfigurationErrorsException(SR2.Hosting_NoValidExtensionFoundForRegistedFilelessService(originalRelativeAddress, ServiceActivationElementPath))); 
                    }
                    else if (GetServiceType(extension)==ServiceType.Unknown)
                    {
                        throw FxTrace.Exception.AsError(new ConfigurationErrorsException(SR2.Hosting_RelativeAddressExtensionNotSupportError(extension, originalRelativeAddress, ServiceActivationElementPath))); 
                    }
                } 
                // since we did Empty/Null string checking in configuration element validator, we should not hit ArgumentException, just catch HttpException for invalid characher 
                catch (HttpException ex)
                { 
                    throw FxTrace.Exception.AsError(new ConfigurationErrorsException(SR2.Hosting_RelativeAddressFormatError(originalRelativeAddress), ex));
                }
                return relativeAddress;
            } 

            [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - can be called outside of user context.")] 
            internal bool IsConfigurationBasedServiceVirtualPath(string normalizedVirtualPath) 
            {
                return this.serviceActivations.ContainsKey(normalizedVirtualPath); 
            }

            [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - can be called outside of user context.")]
            internal bool TryGetCompiledCustomStringFromCBA(string normalizedVirtualPath, out string compiledCustomString) 
            {
                compiledCustomString = null; 
                bool isCBAService = false; 
                if (isConfigurationBased)
                { 
                    compiledCustomString = (string)serviceActivations[normalizedVirtualPath];
                    isCBAService = true;
                }
                return isCBAService; 
            }
 
            internal void EnsureServiceAvailable(string normalizedVirtualPath) 
            {
                TryDebugPrint("HostingManager.EnsureServiceAvailable(" + normalizedVirtualPath + ")"); 

                ServiceActivationInfo activationInfo = null;

                // 1. Try finding the service without a lock. 
                activationInfo = (ServiceActivationInfo)this.directory[normalizedVirtualPath];
                if (activationInfo != null && activationInfo.Service != null) 
                { 
                    return;
                } 

                isAspNetRoutedRequest = ServiceRouteHandler.IsActiveAspNetRoute(normalizedVirtualPath);
                isConfigurationBased = IsConfigurationBasedServiceVirtualPath(normalizedVirtualPath);
 
                // 2. Use global lock to create ServiceActivationInfo if necessary.
                lock (ThisLock) 
                { 
                    if (!isRegistered)
                    { 
                        RegisterObject();
                        isRegistered = true;
                    }
                    activationInfo = (ServiceActivationInfo)this.directory[normalizedVirtualPath]; 
                    if (activationInfo != null && activationInfo.Service != null)
                    { 
                        return; 
                    }
 
                    FailActivationIfRecyling(normalizedVirtualPath);
                    if (activationInfo == null)
                    {
                        // Check service file existence if not config based activation or aspnet routing. 
                        if (!isAspNetRoutedRequest && !isConfigurationBased
                             && !HostingEnvironmentWrapper.ServiceFileExists(normalizedVirtualPath)) 
                        { 
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                                new EndpointNotFoundException( 
                                        SR2.Hosting_ServiceNotExist(
                                        VirtualPathUtility.ToAbsolute(normalizedVirtualPath, HostingEnvironmentWrapper.ApplicationVirtualPath))));
                        }
 
                        activationInfo = new ServiceActivationInfo(normalizedVirtualPath);
                        directory.Add(normalizedVirtualPath, activationInfo); 
                    } 
                }
 
                // 3. Use local lock to activate the service.
                ServiceHostBase newService = null;
                lock (activationInfo)
                { 
                    if (activationInfo.Service != null)
                    { 
                        // The service has been activated by another thread. 
                        return;
                    } 

                    FailActivationIfRecyling(normalizedVirtualPath);
                    try
                    { 
                        CheckMemoryGates();
 
                        newService = ActivateService(normalizedVirtualPath); 

                        // We need to lock and check IsRecycling here because it could ---- with Abort method. 
                        lock (ThisLock)
                        {
                            if (!IsRecycling)
                            { 
                                activationInfo.Service = newService;
                            } 
                        } 

                        if (DiagnosticUtility.ShouldTraceInformation) 
                        {
                            TraceUtility.TraceEvent(
                                TraceEventType.Information, TraceCode.WebHostServiceActivated, SR2.TraceCodeWebHostServiceActivated,
                                new StringTraceRecord("VirtualPath", VirtualPathUtility.ToAbsolute(normalizedVirtualPath, HostingEnvironmentWrapper.ApplicationVirtualPath)), this, (Exception)null); 
                        }
                        if (TD.ServiceHostStartedIsEnabled()) 
                        { 
                            string serviceName = string.Empty;
                            ServiceHostBase host = newService as ServiceHostBase; 
                            if (host != null)
                            {
                                if (null != host.Description.ServiceType)
                                { 
                                    serviceName = host.Description.ServiceType.FullName;
                                } 
                                else 
                                {
                                    serviceName = host.Description.Namespace + host.Description.Name; 
                                }
                            }
                            if(string.IsNullOrEmpty(serviceName))
                            { 
                                serviceName = SR2.ServiceTypeUnknown;
                            } 
 
                            string servicePath = normalizedVirtualPath.Replace("~", ServiceHostingEnvironment.ApplicationVirtualPath + "|");
                            string hostReference = string.Format(CultureInfo.InvariantCulture, "{0}{1}|{2}", ServiceHostingEnvironment.SiteName, servicePath, host.Description.Name); 
                            TD.ServiceHostStarted(serviceName, hostReference);
                        }
                    }
                    catch (HttpCompileException ex) 
                    {
                        throw FxTrace.Exception.AsError( 
                            new ServiceActivationException(SR2.Hosting_ServiceCannotBeActivated(VirtualPathUtility.ToAbsolute(normalizedVirtualPath, HostingEnvironmentWrapper.ApplicationVirtualPath), ex.Message), ex)); 
                    }
                    catch (ServiceActivationException) 
                    {
                        throw;
                    }
                    catch (Exception ex) 
                    {
                        // If it is a fatal exception, don't wrap it. 
                        if (Fx.IsFatal(ex)) 
                        {
                            throw; 
                        }

                        throw FxTrace.Exception.AsError(
                            new ServiceActivationException(SR2.Hosting_ServiceCannotBeActivated(VirtualPathUtility.ToAbsolute(normalizedVirtualPath, HostingEnvironmentWrapper.ApplicationVirtualPath), ex.Message), ex)); 
                    }
                    finally 
                    { 
                        currentVirtualPath = null;
                        fullVirtualPath = null; 
                        xamlFileBaseLocation = null;
                    }
                }
 
                if (activationInfo.Service == null)
                { 
                    Fx.Assert( 
                        IsRecycling && (newService != null),
                        "Must happen in recycling state, also new service must has been created."); 

                    newService.Abort();
                }
 
                FailActivationIfRecyling(normalizedVirtualPath);
            } 
 
            [Fx.Tag.SecurityNote(Critical = "Accesses minFreeMemoryPercentageToActivateService, calls Check.",
                Safe = "No input / output, safe operation if called with administrator-provided value.")] 
            [SecuritySafeCritical]
            void CheckMemoryGates()
            {
                ServiceMemoryGates.Check(this.minFreeMemoryPercentageToActivateService); 
            }
 
            ServiceHostBase ActivateService(string normalizedVirtualPath) 
            {
                ServiceHostBase service = CreateService(normalizedVirtualPath); 

                service.Closed += this.OnServiceClosed;
                service.Faulted += this.OnServiceFaulted;
 
                FailActivationIfRecyling(normalizedVirtualPath);
 
                try 
                {
                    if (TD.ServiceHostOpenStartIsEnabled()) 
                    {
                        TD.ServiceHostOpenStart();
                    }
                    service.Open(); 
                    if (TD.ServiceHostOpenStopIsEnabled())
                    { 
                        TD.ServiceHostOpenStop(); 
                    }
                } 
                finally
                {
                    if (service.State != CommunicationState.Opened)
                    { 
                        // Abort the service to clear possible cached information.
                        service.Abort(); 
                    } 
                }
                if (TD.AspNetRoutingServiceIsEnabled() && isAspNetRoutedRequest) 
                {
                    TD.AspNetRoutingService(normalizedVirtualPath);
                }
 
                return service;
            } 
 
            // Why this triple try blocks instead of using "using" statement:
            // 1. "using" will do the impersonation prior to entering the try, 
            //    which leaves an opertunity to Thread.Abort this thread and get it to exit the method still impersonated.
            // 2. put the assignment of unsafeImpersonate in a finally block
            //    in order to prevent Threat.Abort after impersonation but before the assignment.
            // 3. the finally of a "using" doesn't run until exception filters higher up the stack have executed. 
            //    they will do so in the impersonated context if an exception is thrown inside the try.
            // In sumary, this should prevent the thread from existing this method well still impersonated. 
            [Fx.Tag.SecurityNote(Critical = "Uses SecurityCritical method UnsafeImpersonate to establish the impersonation context.", 
                Safe = "Does not leak anything, does not let caller influence impersonation.")]
            [SecuritySafeCritical] 
            string GetCompiledCustomString(string normalizedVirtualPath)
            {
                try
                { 
                    IDisposable unsafeImpersonate = null;
                    try 
                    { 
                        string result = null;
                        if (!this.TryGetCompiledCustomStringFromCBA(normalizedVirtualPath, out result)) 
                        {
                            try
                            {
                            } 
                            finally
                            { 
                                unsafeImpersonate = HostingEnvironmentWrapper.UnsafeImpersonate(); 
                            }
                            result = BuildManager.GetCompiledCustomString(normalizedVirtualPath); 
                        }
                        return result;
                    }
                    finally 
                    {
                        if (null != unsafeImpersonate) 
                        { 
                            unsafeImpersonate.Dispose();
                        } 
                    }
                }
                catch
                { 
                    throw;
                } 
            } 

            [SecuritySafeCritical] 
            internal Type GetCompiledType(string normalizedVirtualPath)
            {
                try
                { 
                    IDisposable unsafeImpersonate = null;
                    try 
                    { 
                        try
                        { 
                        }
                        finally
                        {
                            unsafeImpersonate = HostingEnvironmentWrapper.UnsafeImpersonate(); 
                        }
                        return BuildManager.GetCompiledType(normalizedVirtualPath); 
                    } 
                    finally
                    { 
                        if (null != unsafeImpersonate)
                        {
                            unsafeImpersonate.Dispose();
                        } 
                    }
                } 
                catch 
                {
                    throw; 
                }
            }

            static Uri[] FilterBaseAddressList(Uri[] baseAddresses, Uri[] prefixFilters) 
            {
                // Precondition assumption: 
                // filterAddresses only contains one Uri per scheme. 
                // Enforced by throwing exception when duplicates found.
                List results = new List(); 
                Dictionary schemeMappings = new Dictionary();

                foreach (Uri filterUri in prefixFilters)
                { 
                    if (!schemeMappings.ContainsKey(filterUri.Scheme))
                    { 
                        schemeMappings.Add(filterUri.Scheme, filterUri); 
                    }
                    else 
                    {
                        throw FxTrace.Exception.AsError(new InvalidOperationException(SR.GetString(SR.BaseAddressDuplicateScheme, filterUri.Scheme)));
                    }
                } 

                foreach (Uri baseUri in baseAddresses) 
                { 
                    string scheme = baseUri.Scheme;
                    if (schemeMappings.ContainsKey(scheme)) 
                    {
                        Uri filterUri = schemeMappings[scheme];

                        if ((baseUri.Port == filterUri.Port) && 
                           (string.Compare(baseUri.Host, filterUri.Host, StringComparison.OrdinalIgnoreCase) == 0))
                        { 
                            results.Add(baseUri); 
                        }
                    } 
                    else
                    {
                        results.Add(baseUri);
                    } 
                }
                return results.ToArray(); 
            } 

            ServiceHostBase CreateService(string normalizedVirtualPath) 
            {
                string virtualPath;
                string factoryType = "";
                string constructorString; 
                ServiceHostBase service = null;
                ServiceHostFactoryBase factory = null; 
                string[] compiledStrings = null; 
                string compiledString = "";
 
                if (TD.CompilationStartIsEnabled())
                {
                    TD.CompilationStart();
                } 

                // 0. Check AspNet Routing vs CBA 
                // check whether there is a conflict between CBA and AspNetRouting 
                // if there is a conflict, using AspNet routing policy to decide which service should be activated
                // we treat CBA as file. RouteExistingFiles is false means Routing should not override File 
                // Todo: when there is a conflict between file/CBA adn route and routing policy was changed dynamically, we still use the old service CSD105890
                if (isAspNetRoutedRequest && isConfigurationBased)
                {
                    if (!RouteTable.Routes.RouteExistingFiles) 
                    {
                        ServiceRouteHandler.MarkARouteAsInactive(normalizedVirtualPath); 
                        isAspNetRoutedRequest = false; 
                    }
                    else 
                    {
                        isConfigurationBased = false;
                    }
                } 

                // 1. Compile the service 
                // The expected format is: 
                //      ||
                // The first two cannot be empty. 
                if (!isAspNetRoutedRequest)
                {
                    compiledString = GetCompiledCustomString(normalizedVirtualPath);
                    if (string.IsNullOrEmpty(compiledString)) 
                    {
                        // Assume it is a workflow service - optimize by not calling BuildManager.GetCompiledType 
                        // but we need to convert the filename to case sensitive one from the physical file 
                        // e.g., incoming request with ~/file.xamlx but physical file has name FiLe.Xamlx
                        // we should convert the virtualPath to ~/FiLe.Xamlx, so that mex can show right case 
                        // we cannot make directory path case sensitive as we cannot get this path info with right case
                        string fileName = HostingEnvironmentWrapper.GetServiceFile(normalizedVirtualPath).Name;
                        string pathSegment = normalizedVirtualPath.Substring(0, normalizedVirtualPath.LastIndexOf(PathSeparator) + 1);
                        normalizedVirtualPath = String.Format(CultureInfo.CurrentCulture, "{0}{1}", pathSegment, fileName); 
                        constructorString = virtualPath = normalizedVirtualPath;
                        factory = CreateWorkflowServiceHostFactory(normalizedVirtualPath); 
                    } 
                    else
                    { 
                        TryDebugPrint("HostingManager.CreateService() BuildManager.GetCompiledCustomString() returned compiledString: " + compiledString);
                        compiledStrings = compiledString.Split(ServiceParserDelimiter.ToCharArray());
                        if (compiledStrings.Length < 3)
                        { 
                            throw FxTrace.Exception.AsError(new InvalidOperationException(SR2.Hosting_CompilationResultInvalid(normalizedVirtualPath)));
                        } 
                        virtualPath = compiledStrings[0]; 
                        factoryType = compiledStrings[1];
                        constructorString = compiledStrings[2]; 
                    }
                }
                else
                { 
                    ServiceDeploymentInfo serviceInfo = ServiceRouteHandler.GetServiceInfo(normalizedVirtualPath);
                    // use the registered virtualpath to ensure correct case in asp.net route 
                    virtualPath = serviceInfo.VirtualPath; 
                    constructorString = serviceInfo.ServiceType;
                    factory = serviceInfo.ServiceHostFactory; 
                }

                // We get the virtual path from compiled string so that it will have the correct case.
                // normalizedVirtualPath should be application relative e.g., ~/service.svc 
                // absolute path start with / and application name, e.g., /appName/service.svc
                normalizedVirtualPath = virtualPath; 
 
                // convert relative virtualpath to app absolute one for consistency, since we gave an absolute path in compiledcustomstring previously
                // xamlx, CBA, and AspNet routing use relative virtualpath, while configuration/administration needs an absolute one 
                virtualPath = VirtualPathUtility.ToAbsolute(virtualPath);

                // 2. Add the base addresses
                Uri[] baseAddresses = HostedTransportConfigurationManager.GetBaseAddresses(virtualPath); 
                Uri[] prefixFilters = ServiceHostingEnvironment.PrefixFilters;
 
                if (!this.multipleSiteBindingsEnabled && prefixFilters != null && prefixFilters.Length > 0) 
                {
                    baseAddresses = FilterBaseAddressList(baseAddresses, prefixFilters); 
                }

                fullVirtualPath = virtualPath;
                if (fullVirtualPath.Length == 0) 
                {
                    fullVirtualPath = "/"; 
                } 

                // Get the current virtual path (full path except for the .svc file name). 
                currentVirtualPath = virtualPath.Substring(0, virtualPath.LastIndexOf(PathSeparator));
                if (currentVirtualPath.Length == 0)
                {
                    currentVirtualPath = "/"; 
                    xamlFileBaseLocation = RootVirtualPath;
                } 
                else 
                {
                    // add trailing slash to support ../a.xamlx in the case .xamlx file is wrapped with .svc 
                    // otherwise when combining ~/sub with ../a.xamlx, VirtualPathUtility will return wrong value ~/a.xamlx
                    xamlFileBaseLocation = VirtualPathUtility.AppendTrailingSlash(currentVirtualPath);
                }
 
                if (isConfigurationBased)
                { 
                    xamlFileBaseLocation = RootVirtualPath; 
                    if (TD.CBAMatchFoundIsEnabled())
                    { 
                        TD.CBAMatchFound(normalizedVirtualPath);
                    }
                }
 
                if (TD.ServiceHostFactoryCreationStartIsEnabled())
                { 
                    TD.ServiceHostFactoryCreationStart(); 
                }
 
                // 3. Create service
                if (factory == null)
                {
                    if (string.IsNullOrEmpty(factoryType)) 
                    {
                        Fx.Assert(!string.IsNullOrEmpty(compiledString), "The compiled string can't be null or empty"); 
                        factory = new ServiceHostFactory(); 
                    }
                    else 
                    {
                        Type compiledType = Type.GetType(factoryType);
                        //check the type from the assemblies in current domain
                        //since compiledcustomstring does not contain fullname for configured virtual path 
                        if (compiledType == null && isConfigurationBased)
                        { 
                            EnsureAllReferencedAssemblyLoaded(); 
                            Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
                            for (int i = 0; i < assemblies.Length; i++) 
                            {
                                compiledType = assemblies[i].GetType(factoryType, false);
                                if (compiledType != null)
                                { 
                                    break;
                                } 
                            } 
                        }
                        if (compiledType == null) 
                        {
                            throw FxTrace.Exception.AsError(new InvalidOperationException(SR2.Hosting_FactoryTypeNotResolved(factoryType)));
                        }
                        if (!typeof(ServiceHostFactoryBase).IsAssignableFrom(compiledType)) 
                        {
                            throw FxTrace.Exception.AsError(new InvalidOperationException(SR2.Hosting_IServiceHostNotImplemented(factoryType))); 
                        } 
                        ConstructorInfo ctor = compiledType.GetConstructor(new Type[] { });
                        if (ctor == null) 
                        {
                            throw FxTrace.Exception.AsError(new InvalidOperationException(SR2.Hosting_NoDefaultCtor(factoryType)));
                        }
                        factory = (ServiceHostFactoryBase)ctor.Invoke(new object[] { }); 
                    }
                } 
 
                if (TD.ServiceHostFactoryCreationStopIsEnabled())
                { 
                    TD.ServiceHostFactoryCreationStop();
                }

                // Push assembly context into ServiceHostFactory 
                // it is OK for us to ignore CBA case here since no referenced assembly in compiledString for CBA
                // but do not do it for AspNet routing, since there is no compiledString 
                if (factory is ServiceHostFactory && !isConfigurationBased && !isAspNetRoutedRequest) 
                {
                    Fx.Assert(!string.IsNullOrEmpty(compiledString), "The compiled string can't be null or empty"); 
                    for (int index = 3; index < compiledStrings.Length; ++index)
                    {
                        ((ServiceHostFactory)factory).AddAssemblyReference(compiledStrings[index]);
                    } 
                }
 
                if (TD.CreateServiceHostStartIsEnabled()) 
                {
                    TD.CreateServiceHostStart(); 
                }

                service = factory.CreateServiceHost(constructorString, baseAddresses);
 
                if (TD.CreateServiceHostStopIsEnabled())
                { 
                    TD.CreateServiceHostStop(); 
                }
 
                if (service == null)
                {
                    throw FxTrace.Exception.AsError(new InvalidOperationException(SR2.Hosting_ServiceHostBaseIsNull(constructorString)));
                } 

                // 4. Create VirtualPathExtension for ServiceHostBase 
                service.Extensions.Add(new VirtualPathExtension(normalizedVirtualPath, ServiceHostingEnvironment.ApplicationVirtualPath, ServiceHostingEnvironment.SiteName)); 

                if (service.Description != null) 
                {
                    service.Description.Behaviors.Add(new ApplyHostConfigurationBehavior());
                    if (this.multipleSiteBindingsEnabled &&
                        service.Description.Behaviors.Find() == null) 
                    {
                        service.Description.Behaviors.Add(new UseRequestHeadersForMetadataAddressBehavior()); 
                    } 
                }
 
                if (TD.CompilationStopIsEnabled())
                {
                    TD.CompilationStop();
                } 

                return service; 
            } 

            //NoInlining - we don't want to load Workflow dlls while activating 3.0 services 
            [MethodImpl(MethodImplOptions.NoInlining)]
            ServiceHostFactoryBase CreateWorkflowServiceHostFactory(string path)
            {
                return PathCache.EnsurePathInfo(path).ServiceModelActivationHandler.GetFactory(); 
            }
 
            void FailActivationIfRecyling(string normalizedVirtualPath) 
            {
                if (IsRecycling) 
                {
                    InvalidOperationException exception = new InvalidOperationException(
                        SR2.Hosting_EnvironmentShuttingDown(normalizedVirtualPath,
                        HostingEnvironmentWrapper.ApplicationVirtualPath)); 
                    throw FxTrace.Exception.AsError(new ServiceActivationException(exception.Message, exception));
                } 
            } 

            public void Stop(bool immediate) 
            {
                if (!immediate)
                {
                    // Try to wait for all requests to be done, then close all the ServiceHosts. 
                    ActionItem.Schedule(new Action(WaitAndCloseCallback), this);
                } 
                else 
                {
                    // Will execute here only if HostingEnvironment.UnregisterObject hasn't been called. 
                    Abort();
                }
            }
 
            [Conditional("DEBUG")]
            static void TryDebugPrint(string message) 
            { 
                if (canDebugPrint)
                { 
                    try
                    {
                        Debug.Print(message);
                    } 
                    catch (SecurityException e)
                    { 
                        canDebugPrint = false; 

                        // not re-throwing on purpose 
                        if (DiagnosticUtility.ShouldTraceWarning)
                        {
                            DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Warning);
                        } 
                    }
                } 
            } 

            void OnServiceClosed(object sender, EventArgs e) 
            {
                lock (ThisLock)
                {
                    if (!isRecycling) 
                    {
                        ServiceHostBase closedService = (ServiceHostBase)sender; 
                        string key = null; 
                        foreach (string address in directory.Keys)
                        { 
                            if (((ServiceActivationInfo)this.directory[address]).Service == closedService)
                            {
                                key = address;
                                break; 
                            }
                        } 
 
                        if (key != null)
                        { 
                            directory.Remove(key);
                        }
                    }
                } 
            }
 
            void OnServiceFaulted(object sender, EventArgs e) 
            {
                ((ServiceHostBase)sender).Abort(); 
            }

            internal void NotifyAllRequestDone()
            { 
                if (isStopStarted)
                { 
                    allRequestDoneInStop.Set(); 
                }
            } 

            void Abort()
            {
                allRequestDoneInStop.Set(); 

                Stack list = null; 
                lock (ThisLock) 
                {
                    // We need to set isRecycling inside lock because we want to make sure no 
                    // new request will be handed once we start to shut down.
                    isRecycling = true;

                    if (UnregisterObject()) 
                    {
                        return; 
                    } 

                    // Make a copy of directory. 
                    list = new Stack(this.directory);
                }

                // Enumerate all the ServiceHosts, abort them one by one. 
                while (list.Count > 0)
                { 
                    DictionaryEntry entry = (DictionaryEntry)list.Pop(); 
                    ServiceActivationInfo activationInfo = (ServiceActivationInfo)entry.Value;
                    if (activationInfo.Service != null) 
                    {
                        activationInfo.Service.Abort();
                    }
 
                    RemoveCachedService((string)entry.Key);
                } 
            } 

            void WaitAndCloseCallback(object obj) 
            {
                isStopStarted = true;
                if (ServiceHostingEnvironment.requestCount != 0)
                { 
                    allRequestDoneInStop.WaitOne();
                } 
 
                Stack list = null;
                lock (ThisLock) 
                {
                    if (UnregisterObject())
                    {
                        return; 
                    }
                    // Make a copy of directory. 
                    list = new Stack(directory); 
                }
 
                // Enumerate all the ServiceHosts, close them one by one.
                AsyncCallback callback = null;
                while (list.Count > 0)
                { 
                    DictionaryEntry entry = (DictionaryEntry)list.Pop();
                    ServiceActivationInfo activationInfo = (ServiceActivationInfo)entry.Value; 
                    if (activationInfo.Service != null) 
                    {
                        // We will try to close all the services asynchronously. 
                        if (callback == null)
                        {
                            callback = Fx.ThunkCallback(new AsyncCallback(OnCloseService));
                        } 

                        IAsyncResult result = null; 
                        try 
                        {
                            // Set timeout to MaxValue and so that only ASP.NET setting is used. 
                            result = activationInfo.Service.BeginClose(TimeSpan.MaxValue, callback, entry);
                        }
                        catch (Exception exception)
                        { 
                            // If BeginClose throw an exception, abort should already have been called.
                            if (!Fx.IsFatal(exception)) 
                            { 
                                LogServiceCloseError((string)entry.Key, exception);
                            } 

                            if (!(exception is CommunicationException))
                            {
                                throw; 
                            }
 
                            // We will remove the service and continue processing other services 
                            // if a CommunicationException happened.
                            RemoveCachedService((string)entry.Key); 
                        }

                        if (result != null && result.CompletedSynchronously)
                        { 
                            EndCloseService(result);
                        } 
                    } 
                    else
                    { 
                        RemoveCachedService((string)entry.Key);
                    }
                }
            } 

            void OnCloseService(IAsyncResult result) 
            { 
                if (!result.CompletedSynchronously)
                { 
                    EndCloseService(result);
                }
            }
 
            void EndCloseService(IAsyncResult result)
            { 
                DictionaryEntry item = (DictionaryEntry)result.AsyncState; 

                try 
                {
                    ((ServiceActivationInfo)item.Value).Service.EndClose(result);
                }
                catch (Exception exception) 
                {
                    //If EndClose throw an exception, abort should already have been called. 
                    if (Fx.IsFatal(exception)) 
                    {
                        throw; 
                    }

                    LogServiceCloseError((string)item.Key, exception);
                } 

                RemoveCachedService((string)item.Key); 
            } 

            void RemoveCachedService(string path) 
            {
                lock (ThisLock)
                {
                    // At the time when we just removed all the service, we will unregister 
                    // from HostingEnvironement.
                    directory.Remove(path); 
 
                    UnregisterObject();
                } 
            }

            void LogServiceCloseError(string virtualPath, Exception exception)
            { 
                if (DiagnosticUtility.ShouldTraceError)
                { 
                    TraceUtility.TraceEvent(TraceEventType.Error, TraceCode.WebHostServiceCloseFailed, SR2.TraceCodeWebHostServiceCloseFailed, 
                        new StringTraceRecord("VirtualPath", VirtualPathUtility.ToAbsolute(virtualPath, HostingEnvironmentWrapper.ApplicationVirtualPath)),
                        this, exception); 
                }
            }

            [Fx.Tag.SecurityNote(Critical = "Uses HostingEnvironmentWrapper.UnsafeRegisterObject which is critical.", 
                Safe = "Does not allow the caller to control the variable -- only registers 'this'.")]
            [SecuritySafeCritical] 
            void RegisterObject() 
            {
                HostingEnvironmentWrapper.UnsafeRegisterObject(this); 
            }

            // Note : this method should only be called under lock of ThisLock.
            [Fx.Tag.SecurityNote(Critical = "Uses HostingEnvironmentWrapper.UnsafeRegisterObject which is critical.", 
                Safe = "Does not allow the caller to control the variable -- only registers 'this'.")]
            [SecuritySafeCritical] 
            bool UnregisterObject() 
            {
                if (directory.Count == 0) 
                {
                    if (!isUnregistered)
                    {
                        isUnregistered = true; 
                        HostingEnvironmentWrapper.UnsafeUnregisterObject(this);
                    } 
                    return true; 
                }
 
                return false;
            }

            class ExtensionHelper 
            {
                readonly IDictionary buildProviders; 
 
                [Fx.Tag.SecurityNote(Critical = "Loads config through an elevation and stores results.",
                    Safe = "Stores results in BuildProviderInfo instances which restrict access to the BuildProvider config object.")] 
                [SecuritySafeCritical]
                public ExtensionHelper()
                {
                    buildProviders = new Dictionary(8, StringComparer.OrdinalIgnoreCase); 
                    CompilationSection compilationSection = (CompilationSection)HostedAspNetEnvironment.UnsafeGetSectionFromWebConfigurationManager("system.web/compilation", null);
                    foreach (System.Web.Configuration.BuildProvider buildProvider in compilationSection.BuildProviders) 
                    { 
                        buildProviders.Add(buildProvider.Extension, new BuildProviderInfo(buildProvider));
                    } 
                }

                [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - can be called outside of user context.")]
                public ServiceType GetServiceType(string extension) 
                {
                    ServiceType serviceType = ServiceType.Unknown; 
                    BuildProviderInfo info; 
                    if (buildProviders.TryGetValue(extension, out info))
                    { 
                        if (info.IsSupported)
                        {
                            serviceType = ServiceType.WCF;
                        } 
                        else if (info.IsXamlBuildProvider)
                        { 
                            serviceType = ServiceType.Workflow; 
                        }
                    } 
                    return serviceType;
                }
            }
        } 

        class ServiceActivationInfo 
        { 
            string virtualPath;
            ServiceHostBase service; 
            public ServiceActivationInfo(string virtualPath)
            {
                this.virtualPath = virtualPath;
            } 

            public ServiceHostBase Service 
            { 
                get
                { 
                    return this.service;
                }

                set 
                {
                    this.service = value; 
                } 
            }
        } 

        class BuildProviderInfo
        {
            [Fx.Tag.SecurityNote(Critical = "Stores the result of an elevation.")] 
            [SecurityCritical]
            System.Web.Configuration.BuildProvider buildProvider; 
 
            bool initialized;
            bool isSupported; 
            bool isXamlBuildProvider;
            object thisLock = new object();

            [Fx.Tag.SecurityNote(Critical = "Stores the result of an elevation.", 
                Safe = "Stores it in a Critical field.")]
            [SecuritySafeCritical] 
            public BuildProviderInfo(System.Web.Configuration.BuildProvider buildProvider) 
            {
                this.buildProvider = buildProvider; 
            }

            string BuildProviderType
            { 
                [Fx.Tag.SecurityNote(Critical = "Accesses the SecurityCritical buildProvider field.",
                    Safe = "Returns the Type property, which is allowed; doesn't leak the BuildProvider instance.")] 
                [SecuritySafeCritical] 
                get { return buildProvider.Type; }
            } 

            [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - can be called outside of user context.")]
            public bool IsSupported
            { 
                get
                { 
                    EnsureInitialized(); 
                    return this.isSupported;
                } 
            }

            [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - can be called outside of user context.")]
            public bool IsXamlBuildProvider 
            {
                get 
                { 
                    EnsureInitialized();
                    return this.isXamlBuildProvider; 
                }

            }
 
            [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - can be called outside of user context.")]
            void EnsureInitialized() 
            { 
                if (initialized)
                { 
                    return;
                }

                lock (thisLock) 
                {
                    if (initialized) 
                    { 
                        return;
                    } 

                    Type type = Type.GetType(BuildProviderType, false);
                    if (type == null)
                    { 
                        Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
                        for (int i = 0; i < assemblies.Length; i++) 
                        { 
                            type = assemblies[i].GetType(BuildProviderType, false);
                            if (type != null) 
                            {
                                break;
                            }
                        } 
                    }
 
                    if (type != null) 
                    {
                        object[] attributes = ServiceReflector.GetCustomAttributes(type, typeof(ServiceActivationBuildProviderAttribute), true); 
                        if (attributes.Length > 0)
                        {
                            this.isSupported = true;
                        } 
                        else
                        { 
                            //to accomodate for subclasses of XamlBuildProvider 
                            if (typeof(System.Xaml.Hosting.XamlBuildProvider).IsAssignableFrom(type))
                            { 
                                this.isXamlBuildProvider = true;
                            }
                        }
                    } 

                    ClearBuildProvider(); 
                    initialized = true; 
                }
            } 

            [Fx.Tag.SecurityNote(Critical = "Accesses the SecurityCritical buildProvider field. Can be called outside user context.",
                Safe = "Just clears it, doesn't leak anything.")]
            [SecuritySafeCritical] 
            void ClearBuildProvider()
            { 
                this.buildProvider = null; 
            }
        } 

        static class PathCache
        {
            static Hashtable pathCache = new Hashtable(StringComparer.OrdinalIgnoreCase); 
            static object writeLock = new object();
 
            public static PathInfo EnsurePathInfo(string path) 
            {
                PathInfo pathInfo = (PathInfo)pathCache[path]; 
                if (pathInfo != null)
                {
                    return pathInfo;
                } 

                lock (writeLock) 
                { 
                    pathInfo = (PathInfo)pathCache[path];
                    if (pathInfo != null) 
                    {
                        return pathInfo;
                    }
 
                    if (HostingEnvironmentWrapper.ServiceFileExists(path))
                    { 
                        pathInfo = new PathInfo(path); 
                        pathCache.Add(path, pathInfo);
                        return pathInfo; 
                    }
                    else
                    {
                        throw FxTrace.Exception.AsError(new EndpointNotFoundException(SR2.Hosting_ServiceNotExist(path))); 
                    }
                } 
            } 
        }
 
        class PathInfo
        {
            string path;
            PathType type; 
            object writeLock;
            Type hostedXamlType; 
            Type serviceModelActivationHandlerType; 
            IServiceModelActivationHandler serviceModelActivationHandler;
 
            public PathInfo(string path)
            {
                this.type = PathType.Unknown;
                this.path = path; 
                this.writeLock = new object();
            } 
 
            public IServiceModelActivationHandler ServiceModelActivationHandler
            { 
                get
                {
                    if (this.serviceModelActivationHandler == null)
                    { 
                        if (IsWorkflowService())
                        { 
                            this.serviceModelActivationHandler = 
                                CreateServiceModelActivationHandler(serviceModelActivationHandlerType) as IServiceModelActivationHandler;
                        } 
                        else
                        {
                            //The control can come here when the hosted file is a valid XAML (service OR otherwise) but is configured with
                            //a handler that does NOT implement IServiceModelActivationHandler and aspnetCompat=true 
                            throw FxTrace.Exception.AsError(
                                new EndpointNotFoundException(SR2.Hosting_InvalidHandlerForWorkflowService( 
                                    this.serviceModelActivationHandlerType.FullName, this.hostedXamlType.FullName, this.path))); 
                        }
                    } 
                    return this.serviceModelActivationHandler;
                }
            }
 
            static object CreateServiceModelActivationHandler(Type type)
            { 
                //The handler/factory should have an empty constructor but need not be public 
                return Activator.CreateInstance(type,
                BindingFlags.CreateInstance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, 
                null, null, null);
            }

            public bool IsWorkflowService() 
            {
                if (this.type == PathType.Unknown) 
                { 
                    //Cache won't be available if it is invoked first time
                    //Use a local "lock" specifically for this url 
                    lock (this.writeLock)
                    {
                        if (this.type == PathType.Unknown)
                        { 
                            hostedXamlType = hostingManager.GetCompiledType(this.path);
                            if (IsConfiguredWithSMActivationHandler()) 
                            { 
                                this.type = PathType.WorkflowService;
                            } 
                            else
                            {
                                this.type = PathType.NotWorkflowService;
                            } 
                        }
                    } 
                } 
                if (this.type == PathType.WorkflowService)
                { 
                    return true;
                }
                return false;
            } 

            bool IsConfiguredWithSMActivationHandler() 
            { 
                if (XamlHostingConfiguration.TryGetHttpHandlerType(this.path, this.hostedXamlType, out this.serviceModelActivationHandlerType))
                { 
                    if (typeof(IServiceModelActivationHandler).IsAssignableFrom(this.serviceModelActivationHandlerType))
                    {
                        return true;
                    } 
                }
                return false; 
            } 
            enum PathType
            { 
                Unknown,
                WorkflowService,
                NotWorkflowService
            } 
        }
    } 
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.


                        

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK