You've already forked linux-packaging-mono
							
							
		
			
				
	
	
		
			776 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			776 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| //----------------------------------------------------------------------------
 | |
| // Copyright (c) Microsoft Corporation.  All rights reserved.
 | |
| //----------------------------------------------------------------------------
 | |
| 
 | |
| namespace System.ServiceModel.Activation
 | |
| {
 | |
|     using System.Collections.Generic;
 | |
|     using System.Configuration;
 | |
|     using System.Diagnostics.CodeAnalysis;
 | |
|     using System.Globalization;
 | |
|     using System.Net;
 | |
|     using System.Runtime;
 | |
|     using System.Runtime.CompilerServices;
 | |
|     using System.Security;
 | |
|     using System.Security.Authentication.ExtendedProtection;
 | |
|     using System.Security.Permissions;
 | |
|     using System.ServiceModel;
 | |
|     using System.ServiceModel.Channels;
 | |
|     using System.ServiceModel.Description;
 | |
|     using System.Threading;
 | |
|     using System.Transactions;
 | |
|     using System.Web;
 | |
|     using System.Web.Compilation;
 | |
|     using System.Web.Configuration;
 | |
| 
 | |
|     class HostedAspNetEnvironment : AspNetEnvironment
 | |
|     {
 | |
|         // On IIS 8.0 (or later) the "WEBSOCKET_VERSION" server property indicates the WebSocket protocol version supported by the server.
 | |
|         // The IIS WebSocket module sets this property when initialized.
 | |
|         private const string WebSocketVersionServerProperty = "WEBSOCKET_VERSION";
 | |
| 
 | |
|         // Indicates if we determined the WebSocket version. If false, we'll need to check the "WEBSOCKET_VERSION" server property.
 | |
|         private static bool isWebSocketVersionSet = false;
 | |
| 
 | |
|         // Provides the version of the WebSocket protocol supported by IIS.
 | |
|         private static string webSocketVersion;
 | |
| 
 | |
|         // used to cache SiteName|ApplicationVirtualPath
 | |
|         static string cachedServiceReference;
 | |
| 
 | |
|         // used to cache if windows auth is being used
 | |
|         Nullable<bool> isWindowsAuthentication;
 | |
| 
 | |
|         HostedAspNetEnvironment()
 | |
|             : base()
 | |
|         {
 | |
|         }
 | |
| 
 | |
|         public override bool AspNetCompatibilityEnabled
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 return ServiceHostingEnvironment.AspNetCompatibilityEnabled;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public override string ConfigurationPath
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 if (ServiceHostingEnvironment.CurrentVirtualPath != null)
 | |
|                 {
 | |
|                     return ServiceHostingEnvironment.CurrentVirtualPath + "web.config";
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     return base.ConfigurationPath;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public override bool IsConfigurationBased
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 return ServiceHostingEnvironment.IsConfigurationBased;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public override string CurrentVirtualPath
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 return ServiceHostingEnvironment.CurrentVirtualPath;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public override string XamlFileBaseLocation
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 return ServiceHostingEnvironment.XamlFileBaseLocation;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public override bool UsingIntegratedPipeline
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 return HttpRuntime.UsingIntegratedPipeline;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         // Provides the version of the WebSocket protocol supported by IIS.
 | |
|         // Returns null if WebSockets are not supported (because the IIS WebSocketModule is not installed or enabled).
 | |
|         public override string WebSocketVersion
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 return isWebSocketVersionSet ? webSocketVersion : null;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public static void Enable()
 | |
|         {
 | |
|             AspNetEnvironment hostedEnvironment = new HostedAspNetEnvironment();
 | |
|             AspNetEnvironment.Current = hostedEnvironment;
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Tries to set the 'WebSocketVersion' property. The first call of this method sets the property (based on the "WEBSOCKET_VERSION" server property). 
 | |
|         /// Subsequent calls do nothing.
 | |
|         /// </summary>
 | |
|         /// <param name="application">The HttpApplication used to determine the WebSocket version.</param>
 | |
|         /// <remarks>
 | |
|         /// Take caution when calling this method. The method initializes the 'WebSocketVersion' property based on the "WEBSOCKET_VERSION" server variable.
 | |
|         /// This variable gets set by the WebSocketModule when it's loaded by IIS. If you call this method too early (before IIS got a chance to load the module list), 
 | |
|         /// this method might incorrectly set 'WebSocketVersion' to 'null'.
 | |
|         /// </remarks>
 | |
|         public static void TrySetWebSocketVersion(HttpApplication application)
 | |
|         {
 | |
|             if (!isWebSocketVersionSet)
 | |
|             {
 | |
|                 webSocketVersion = application.Request.ServerVariables[WebSocketVersionServerProperty];
 | |
|                 isWebSocketVersionSet = true;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public override void AddHostingBehavior(ServiceHostBase serviceHost, ServiceDescription description)
 | |
|         {
 | |
|             VirtualPathExtension virtualPathExtension = serviceHost.Extensions.Find<VirtualPathExtension>();
 | |
|             if (virtualPathExtension != null)
 | |
|             {
 | |
|                 description.Behaviors.Add(new HostedBindingBehavior(virtualPathExtension));
 | |
|             }
 | |
| 
 | |
|             foreach (ServiceEndpoint endpoint in description.Endpoints)
 | |
|             {
 | |
|                 if (ServiceMetadataBehavior.IsMetadataEndpoint(description, endpoint))
 | |
|                 {
 | |
|                     endpoint.Behaviors.Add(new HostedMetadataExchangeEndpointBehavior());
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public override bool IsWebConfigAboveApplication(object configHostingContext)
 | |
|         {
 | |
|             AspNetPartialTrustHelpers.FailIfInPartialTrustOutsideAspNet();
 | |
| 
 | |
|             WebContext context = configHostingContext as WebContext;
 | |
|             if (context != null)
 | |
|             {
 | |
|                 return context.ApplicationLevel == WebApplicationLevel.AboveApplication;
 | |
|             }
 | |
| 
 | |
|             return false; // if we don't recognize the context we can't enforce the special web.config logic
 | |
|         }
 | |
| 
 | |
|         public override void EnsureCompatibilityRequirements(ServiceDescription description)
 | |
|         {
 | |
|             AspNetCompatibilityRequirementsAttribute aspNetCompatibilityRequirements = description.Behaviors.Find<AspNetCompatibilityRequirementsAttribute>();
 | |
|             if (aspNetCompatibilityRequirements == null)
 | |
|             {
 | |
|                 aspNetCompatibilityRequirements = new AspNetCompatibilityRequirementsAttribute();
 | |
|                 description.Behaviors.Add(aspNetCompatibilityRequirements);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public override bool TryGetFullVirtualPath(out string virtualPath)
 | |
|         {
 | |
|             // subclass will use the virtual path from the compiled string
 | |
|             virtualPath = ServiceHostingEnvironment.FullVirtualPath;
 | |
|             return true;
 | |
|         }
 | |
| 
 | |
|         public override string GetAnnotationFromHost(ServiceHostBase host)
 | |
|         {
 | |
|             //Format Website name\Application Virtual Path|\relative service virtual path|serviceName 
 | |
|             if (host != null && host.Extensions != null)
 | |
|             {
 | |
|                 string serviceName = (host.Description != null) ? host.Description.Name : string.Empty;
 | |
|                 string application = ServiceHostingEnvironment.ApplicationVirtualPath;
 | |
|                 string servicePath = string.Empty;
 | |
|                 VirtualPathExtension extension = host.Extensions.Find<VirtualPathExtension>();
 | |
|                 if (extension != null && extension.VirtualPath != null)
 | |
|                 {
 | |
|                     servicePath = extension.VirtualPath.Replace("~", application + "|");
 | |
|                     return string.Format(CultureInfo.InvariantCulture, "{0}{1}|{2}", ServiceHostingEnvironment.SiteName, servicePath, serviceName);
 | |
|                 }
 | |
|             }
 | |
|             if (string.IsNullOrEmpty(HostedAspNetEnvironment.cachedServiceReference))
 | |
|             {
 | |
|                 HostedAspNetEnvironment.cachedServiceReference = string.Format(CultureInfo.InvariantCulture, "{0}{1}", ServiceHostingEnvironment.SiteName, ServiceHostingEnvironment.ApplicationVirtualPath);
 | |
|             }
 | |
|             return HostedAspNetEnvironment.cachedServiceReference;
 | |
|         }
 | |
| 
 | |
|         [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - can be called outside of user context.")]
 | |
|         public override void EnsureAllReferencedAssemblyLoaded()
 | |
|         {
 | |
|             AspNetPartialTrustHelpers.FailIfInPartialTrustOutsideAspNet();
 | |
|             BuildManager.GetReferencedAssemblies();
 | |
|         }
 | |
| 
 | |
|         public override BaseUriWithWildcard GetBaseUri(string transportScheme, Uri listenUri)
 | |
|         {
 | |
|             BaseUriWithWildcard baseAddress = null;
 | |
|             HostedTransportConfigurationBase hostedConfiguration =
 | |
|                 HostedTransportConfigurationManager.GetConfiguration(transportScheme) as HostedTransportConfigurationBase;
 | |
|             if (hostedConfiguration != null)
 | |
|             {
 | |
|                 baseAddress = hostedConfiguration.FindBaseAddress(listenUri);
 | |
|                 if (baseAddress == null)
 | |
|                 {
 | |
|                     throw FxTrace.Exception.AsError(new InvalidOperationException(SR.Hosting_TransportBindingNotFound(listenUri.ToString())));
 | |
|                 }
 | |
|             }
 | |
|             return baseAddress;
 | |
|         }
 | |
| 
 | |
|         public override void ValidateHttpSettings(string virtualPath, bool isMetadataListener, bool usingDefaultSpnList, ref AuthenticationSchemes bindingElementAuthenticationSchemes, ref ExtendedProtectionPolicy extendedProtectionPolicy, ref string realm)
 | |
|         {
 | |
|             // Verify the authentication settings
 | |
|             AuthenticationSchemes hostSupportedSchemes = HostedTransportConfigurationManager.MetabaseSettings.GetAuthenticationSchemes(virtualPath);
 | |
| 
 | |
|             if ((bindingElementAuthenticationSchemes & hostSupportedSchemes) == 0)
 | |
|             {
 | |
|                 if (bindingElementAuthenticationSchemes == AuthenticationSchemes.Negotiate ||
 | |
|                     bindingElementAuthenticationSchemes == AuthenticationSchemes.Ntlm ||
 | |
|                     bindingElementAuthenticationSchemes == AuthenticationSchemes.IntegratedWindowsAuthentication)
 | |
|                 {
 | |
|                     throw FxTrace.Exception.AsError(new NotSupportedException(SR.Hosting_AuthSchemesRequireWindowsAuth));
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     throw FxTrace.Exception.AsError(new NotSupportedException(SR.Hosting_AuthSchemesRequireOtherAuth(bindingElementAuthenticationSchemes.ToString())));
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             //only use AuthenticationSchemes, which are supported both in IIS and the WCF binding
 | |
|             bindingElementAuthenticationSchemes &= hostSupportedSchemes;
 | |
| 
 | |
|             if (bindingElementAuthenticationSchemes != AuthenticationSchemes.Anonymous)
 | |
|             {
 | |
|                 //Compare the ExtendedProtectionPolicy setttings to IIS
 | |
|                 ExtendedProtectionPolicy iisPolicy = HostedTransportConfigurationManager.MetabaseSettings.GetExtendedProtectionPolicy(virtualPath);
 | |
| 
 | |
|                 if (iisPolicy == null) //OS doesn't support CBT
 | |
|                 {
 | |
|                     if (extendedProtectionPolicy.PolicyEnforcement == PolicyEnforcement.Always)
 | |
|                     {
 | |
|                         throw FxTrace.Exception.AsError(new NotSupportedException(SR.ExtendedProtectionNotSupported));
 | |
|                     }
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     if (isMetadataListener && ChannelBindingUtility.IsDefaultPolicy(extendedProtectionPolicy))
 | |
|                     {
 | |
|                         //push the IIS policy onto the metadataListener if and only if the default policy is 
 | |
|                         //in force. policy for non metadata listeners will still have to match IIS policy.
 | |
|                         extendedProtectionPolicy = iisPolicy;
 | |
|                     }
 | |
|                     else
 | |
|                     {
 | |
|                         if (!ChannelBindingUtility.AreEqual(iisPolicy, extendedProtectionPolicy))
 | |
|                         {
 | |
|                             string mismatchErrorMessage;
 | |
|                             if (iisPolicy.PolicyEnforcement != extendedProtectionPolicy.PolicyEnforcement)
 | |
|                             {
 | |
|                                 mismatchErrorMessage = SR.ExtendedProtectionPolicyEnforcementMismatch(iisPolicy.PolicyEnforcement, extendedProtectionPolicy.PolicyEnforcement);
 | |
|                             }
 | |
|                             else if (iisPolicy.ProtectionScenario != extendedProtectionPolicy.ProtectionScenario)
 | |
|                             {
 | |
|                                 mismatchErrorMessage = SR.ExtendedProtectionPolicyScenarioMismatch(iisPolicy.ProtectionScenario, extendedProtectionPolicy.ProtectionScenario);
 | |
|                             }
 | |
|                             else 
 | |
|                             {
 | |
|                                 Fx.Assert(iisPolicy.CustomChannelBinding != extendedProtectionPolicy.CustomChannelBinding, "new case in ChannelBindingUtility.AreEqual to account for");
 | |
|                                 mismatchErrorMessage = SR.ExtendedProtectionPolicyCustomChannelBindingMismatch;
 | |
|                             }
 | |
| 
 | |
|                             if (mismatchErrorMessage != null)
 | |
|                             {
 | |
|                                 throw FxTrace.Exception.AsError(new NotSupportedException(SR.Hosting_ExtendedProtectionPoliciesMustMatch(mismatchErrorMessage)));
 | |
|                             }
 | |
|                         }
 | |
| 
 | |
|                         //when using the default SPN list we auto generate, we should make sure that the IIS policy is also the default...
 | |
|                         ServiceNameCollection listenerSpnList = usingDefaultSpnList ? null : extendedProtectionPolicy.CustomServiceNames;
 | |
|                         if (!ChannelBindingUtility.IsSubset(iisPolicy.CustomServiceNames, listenerSpnList))
 | |
|                         {
 | |
|                             throw FxTrace.Exception.AsError(new NotSupportedException(SR.Hosting_ExtendedProtectionPoliciesMustMatch(SR.Hosting_ExtendedProtectionSPNListNotSubset)));
 | |
|                         }
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             
 | |
| 
 | |
|             // Do not set realm for Cassini.
 | |
|             if (!ServiceHostingEnvironment.IsSimpleApplicationHost)
 | |
|             {
 | |
|                 // Set the realm
 | |
|                 realm = HostedTransportConfigurationManager.MetabaseSettings.GetRealm(virtualPath);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public override bool ValidateHttpsSettings(string virtualPath, ref bool requireClientCertificate)
 | |
|         {
 | |
|             // Do not validate settings for Cassini. Actually current implementation of Cassini does not support HTTPS.
 | |
|             if (ServiceHostingEnvironment.IsSimpleApplicationHost)
 | |
|             {
 | |
|                 return false;
 | |
|             }
 | |
| 
 | |
|             // Validate Ssl Settings
 | |
|             HttpAccessSslFlags sslFlags = HostedTransportConfigurationManager.MetabaseSettings.GetAccessSslFlags(virtualPath);
 | |
|             HttpAccessSslFlags channelListenerSslFlags = HttpAccessSslFlags.None;
 | |
| 
 | |
|             // Validating SSL flags. SslRequireCert means "require client certificate" in IIS terminology.
 | |
|             if ((sslFlags & HttpAccessSslFlags.SslRequireCert) != 0)
 | |
|             {
 | |
|                 // Require SSL.
 | |
|                 // We apply IIS settings to the ChannelListener to fix the endpoint
 | |
|                 requireClientCertificate = true;
 | |
|             }
 | |
|             else if (requireClientCertificate &&
 | |
|                 // Validating SSL flags. SslNegotiateCert means "accept client certificate" in IIS terminology.
 | |
|                 // We want to allow SslNegotiateCert in IIS to support hosting one endpoint requiring client
 | |
|                 // certificates and another endpoint not using client certificates in the same VirtualDirectory.
 | |
|                 // HttpsChannelListener.ValidateAuthentication ensures that authentication is denied for services
 | |
|                 // requiring client certificates when the client does not present one.
 | |
|                 (sslFlags & HttpAccessSslFlags.SslNegotiateCert) == 0)
 | |
|             {
 | |
|                 // IIS ignores client cert but the binding requires it.
 | |
|                 channelListenerSslFlags |= HttpAccessSslFlags.SslRequireCert;
 | |
| 
 | |
|                 throw FxTrace.Exception.AsError(new NotSupportedException(SR.Hosting_SslSettingsMisconfigured(
 | |
|                     channelListenerSslFlags.ToString(), sslFlags.ToString())));
 | |
|             }
 | |
| 
 | |
|             return (sslFlags & HttpAccessSslFlags.SslMapCert) != 0;
 | |
|         }
 | |
| 
 | |
|         public override void ProcessNotMatchedEndpointAddress(Uri uri, string endpointName)
 | |
|         {
 | |
|             if (!object.ReferenceEquals(uri.Scheme, Uri.UriSchemeHttp) &&
 | |
|                 !object.ReferenceEquals(uri.Scheme, Uri.UriSchemeHttps))
 | |
|             {
 | |
|                 throw FxTrace.Exception.AsError(new InvalidOperationException(SR.Hosting_NonHTTPInCompatibilityMode(endpointName)));
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public override void ValidateCompatibilityRequirements(AspNetCompatibilityRequirementsMode compatibilityMode)
 | |
|         {
 | |
|             if (compatibilityMode == AspNetCompatibilityRequirementsMode.Allowed)
 | |
|             {
 | |
|                 return;
 | |
|             }
 | |
|             else if (ServiceHostingEnvironment.AspNetCompatibilityEnabled &&
 | |
|                 compatibilityMode == AspNetCompatibilityRequirementsMode.NotAllowed)
 | |
|             {
 | |
|                 throw FxTrace.Exception.AsError(new InvalidOperationException(SR.Hosting_ServiceCompatibilityNotAllowed));
 | |
|             }
 | |
|             else if (!ServiceHostingEnvironment.AspNetCompatibilityEnabled &&
 | |
|                 compatibilityMode == AspNetCompatibilityRequirementsMode.Required)
 | |
|             {
 | |
|                 throw FxTrace.Exception.AsError(new InvalidOperationException(SR.Hosting_ServiceCompatibilityRequire));
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public override IAspNetMessageProperty GetHostingProperty(Message message)
 | |
|         {
 | |
|             return GetHostingProperty(message, false);
 | |
|         }
 | |
| 
 | |
|         public override IAspNetMessageProperty GetHostingProperty(Message message, bool removeFromMessage)
 | |
|         {
 | |
|             IAspNetMessageProperty result = null;
 | |
|             object property;
 | |
| 
 | |
|             if (message.Properties.TryGetValue(HostingMessageProperty.Name, out property))
 | |
|             {
 | |
|                 result = (HostingMessageProperty)property;
 | |
|                 if (removeFromMessage)
 | |
|                 {
 | |
|                     message.Properties.Remove(HostingMessageProperty.Name);
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             return result;
 | |
|         }
 | |
| 
 | |
|         public override void PrepareMessageForDispatch(Message message)
 | |
|         {
 | |
|             ReceiveContext context = null;
 | |
|             if (ReceiveContext.TryGet(message, out context) && !(context is ReceiveContextBusyCountWrapper))
 | |
|             {
 | |
|                 ReceiveContextBusyCountWrapper wrapper = new ReceiveContextBusyCountWrapper(context);
 | |
|                 message.Properties.Remove(ReceiveContext.Name);
 | |
|                 message.Properties.Add(ReceiveContext.Name, wrapper);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public override void ApplyHostedContext(TransportChannelListener listener, BindingContext context)
 | |
|         {
 | |
|             VirtualPathExtension virtualPathExtension = context.BindingParameters.Find<VirtualPathExtension>();
 | |
| 
 | |
|             if (virtualPathExtension != null)
 | |
|             {
 | |
|                 HostedMetadataBindingParameter metadataBindingParameter = context.BindingParameters.Find<HostedMetadataBindingParameter>();
 | |
|                 listener.ApplyHostedContext(virtualPathExtension.VirtualPath, metadataBindingParameter != null);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         internal override void AddMetadataBindingParameters(Uri listenUri, KeyedByTypeCollection<IServiceBehavior> serviceBehaviors, BindingParameterCollection bindingParameters)
 | |
|         {
 | |
|             if (serviceBehaviors.Find<HostedBindingBehavior>() != null)
 | |
|             {
 | |
|                 bindingParameters.Add(new HostedMetadataBindingParameter());
 | |
|             }
 | |
| 
 | |
|             VirtualPathExtension virtualPathExtension = bindingParameters.Find<VirtualPathExtension>();
 | |
| 
 | |
|             if (virtualPathExtension != null)
 | |
|             {
 | |
|                 AuthenticationSchemes hostSupportedAuthenticationSchemes = AspNetEnvironment.Current.GetAuthenticationSchemes(listenUri);
 | |
| 
 | |
|                 if (hostSupportedAuthenticationSchemes != AuthenticationSchemes.None)
 | |
|                 {
 | |
|                     if (bindingParameters.Find<AuthenticationSchemesBindingParameter>() == null)
 | |
|                     {
 | |
|                         bindingParameters.Add(new AuthenticationSchemesBindingParameter(hostSupportedAuthenticationSchemes));
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             base.AddMetadataBindingParameters(listenUri, serviceBehaviors, bindingParameters);
 | |
|         }
 | |
| 
 | |
|         internal override bool IsMetadataListener(BindingParameterCollection bindingParameters)
 | |
|         {
 | |
|             return base.IsMetadataListener(bindingParameters) || bindingParameters.Find<HostedMetadataBindingParameter>() != null;
 | |
|         }
 | |
| 
 | |
|         public override void IncrementBusyCount()
 | |
|         {
 | |
|             HostingEnvironmentWrapper.IncrementBusyCount();
 | |
|         }
 | |
| 
 | |
|         public override void DecrementBusyCount()
 | |
|         {
 | |
|             HostingEnvironmentWrapper.DecrementBusyCount();
 | |
|         }
 | |
|         
 | |
|         public override bool TraceIncrementBusyCountIsEnabled()
 | |
|         {
 | |
|             return TD.IncrementBusyCountIsEnabled();
 | |
|         }
 | |
| 
 | |
|         public override bool TraceDecrementBusyCountIsEnabled()
 | |
|         {
 | |
|             return TD.DecrementBusyCountIsEnabled();
 | |
|         }
 | |
|         public override void TraceIncrementBusyCount(string data)
 | |
|         {
 | |
|             if (data == null)
 | |
|             {
 | |
|                 data = SR.DefaultBusyCountSource;
 | |
|             }
 | |
|             TD.IncrementBusyCount(data);
 | |
|         }
 | |
| 
 | |
|         public override void TraceDecrementBusyCount(string data)
 | |
|         {
 | |
|             if (data == null)
 | |
|             {
 | |
|                 data = SR.DefaultBusyCountSource;
 | |
|             }
 | |
|             TD.DecrementBusyCount(data);
 | |
|         }
 | |
| 
 | |
|         public override object GetConfigurationSection(string sectionPath)
 | |
|         {
 | |
|             return GetSectionFromWebConfigurationManager(sectionPath, ServiceHostingEnvironment.FullVirtualPath);
 | |
|         }
 | |
| 
 | |
|         [Fx.Tag.SecurityNote(Critical = "Uses SecurityCritical method UnsafeGetSectionFromWebConfigurationManager which elevates.")]
 | |
|         [SecurityCritical]
 | |
|         public override object UnsafeGetConfigurationSection(string sectionPath)
 | |
|         {
 | |
|             return UnsafeGetSectionFromWebConfigurationManager(sectionPath, ServiceHostingEnvironment.FullVirtualPath);
 | |
|         }
 | |
| 
 | |
|         public override bool IsSimpleApplicationHost
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 return ServiceHostingEnvironment.IsSimpleApplicationHost;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public override AuthenticationSchemes GetAuthenticationSchemes(Uri baseAddress)
 | |
|         {
 | |
|             AspNetPartialTrustHelpers.FailIfInPartialTrustOutsideAspNet();
 | |
| 
 | |
|             string fileName = VirtualPathUtility.GetFileName(baseAddress.AbsolutePath);
 | |
|             string virtualPath = ServiceHostingEnvironment.CurrentVirtualPath;
 | |
|             string completePath;
 | |
|             if (virtualPath != null && virtualPath.EndsWith("/", StringComparison.Ordinal))
 | |
|             {
 | |
|                 completePath = virtualPath + fileName;
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 completePath = string.Format(CultureInfo.InvariantCulture, "{0}/{1}", virtualPath, fileName);
 | |
|             }
 | |
|             AuthenticationSchemes supportedSchemes = HostedTransportConfigurationManager.MetabaseSettings.GetAuthenticationSchemes(completePath);
 | |
| 
 | |
|             return supportedSchemes;
 | |
|         }
 | |
| 
 | |
|         [Fx.Tag.SecurityNote(Critical = "Handles config objects, which should not be leaked.",
 | |
|              Safe = "Doesn't leak config objects out of SecurityCritical code.")]
 | |
|         [SecuritySafeCritical]
 | |
|         [MethodImpl(MethodImplOptions.NoInlining)]
 | |
|         public override bool IsWindowsAuthenticationConfigured()
 | |
|         {
 | |
|             if (!this.isWindowsAuthentication.HasValue)
 | |
|             {
 | |
|                 AspNetPartialTrustHelpers.FailIfInPartialTrustOutsideAspNet();
 | |
| 
 | |
|                 AuthenticationSection authSection = (AuthenticationSection)UnsafeGetConfigurationSection("system.web/authentication");
 | |
|                 if (authSection != null)
 | |
|                 {
 | |
|                     this.isWindowsAuthentication = (authSection.Mode == AuthenticationMode.Windows);
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     this.isWindowsAuthentication = false;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             return this.isWindowsAuthentication.Value;
 | |
|         }
 | |
| 
 | |
|         /// Be sure to update UnsafeGetSectionFromWebConfigurationManager if you modify this method
 | |
|         [MethodImpl(MethodImplOptions.NoInlining)]
 | |
|         static object GetSectionFromWebConfigurationManager(string sectionPath, string virtualPath)
 | |
|         {
 | |
|             AspNetPartialTrustHelpers.FailIfInPartialTrustOutsideAspNet();
 | |
| 
 | |
|             if (virtualPath != null)
 | |
|             {
 | |
|                 return WebConfigurationManager.GetSection(sectionPath, virtualPath);
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 return WebConfigurationManager.GetSection(sectionPath);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         // Be sure to update GetSectionFromWebConfigurationManager if you modify this method
 | |
|         [SuppressMessage(FxCop.Category.Security, FxCop.Rule.SecureAsserts, Justification = "This is from an internal helper class and users have no way to pass arbitrary information to this code.")]
 | |
|         [Fx.Tag.SecurityNote(Critical = "Asserts ConfigurationPermission in order to fetch config from WebConfigurationManager,"
 | |
|             + "caller must guard return value.")]
 | |
|         [SecurityCritical]
 | |
|         [ConfigurationPermission(SecurityAction.Assert, Unrestricted = true)]
 | |
|         [MethodImpl(MethodImplOptions.NoInlining)]
 | |
|         internal static object UnsafeGetSectionFromWebConfigurationManager(string sectionPath, string virtualPath)
 | |
|         {
 | |
|             AspNetPartialTrustHelpers.FailIfInPartialTrustOutsideAspNet();
 | |
| 
 | |
|             if (virtualPath != null)
 | |
|             {
 | |
|                 return WebConfigurationManager.GetSection(sectionPath, virtualPath);
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 return WebConfigurationManager.GetSection(sectionPath);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public override bool IsWithinApp(string absoluteVirtualPath)
 | |
|         {
 | |
|             return HostedTransportConfigurationManager.MetabaseSettings.IsWithinApp(absoluteVirtualPath);
 | |
|         }
 | |
| 
 | |
|         // This class is intended to be empty.
 | |
|         class HostedMetadataBindingParameter
 | |
|         {
 | |
|         }
 | |
| 
 | |
|         class HostedMetadataExchangeEndpointBehavior : IEndpointBehavior
 | |
|         {
 | |
|             void IEndpointBehavior.AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
 | |
|             {
 | |
|                 bindingParameters.Add(new HostedMetadataBindingParameter());
 | |
|             }
 | |
| 
 | |
|             void IEndpointBehavior.ApplyClientBehavior(ServiceEndpoint endpoint, Dispatcher.ClientRuntime clientRuntime)
 | |
|             {
 | |
|             }
 | |
| 
 | |
|             void IEndpointBehavior.ApplyDispatchBehavior(ServiceEndpoint endpoint, Dispatcher.EndpointDispatcher endpointDispatcher)
 | |
|             {
 | |
|             }
 | |
| 
 | |
|             void IEndpointBehavior.Validate(ServiceEndpoint endpoint)
 | |
|             {
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         class ReceiveContextBusyCountWrapper : ReceiveContext
 | |
|         {
 | |
|             ReceiveContext wrappedContext;
 | |
|             //possible values are 0 and 1.
 | |
|             //using an integer to allow usage with Interlocked methods
 | |
|             //synchronized access needed as there could be ---- between calls
 | |
|             //to EndComplete and Tx notification.
 | |
|             int busyCount;
 | |
|             //possible values are 0 and 1
 | |
|             //using an integer to allow usage with Interlocked methods
 | |
|             //synchronized access needed as there could be ---- between calls
 | |
|             //to EndComplete and Tx Status notification.
 | |
|             int ambientTransactionCount;
 | |
| 
 | |
|             internal ReceiveContextBusyCountWrapper(ReceiveContext context)
 | |
|             {
 | |
|                 this.wrappedContext = context;
 | |
|                 this.wrappedContext.Faulted += new EventHandler(OnWrappedContextFaulted);
 | |
|                 AspNetEnvironment.Current.IncrementBusyCount();
 | |
|                 if (AspNetEnvironment.Current.TraceIncrementBusyCountIsEnabled())
 | |
|                 {
 | |
|                     AspNetEnvironment.Current.TraceIncrementBusyCount(this.GetType().FullName);
 | |
|                 }
 | |
|                 Interlocked.Increment(ref busyCount);
 | |
|             }
 | |
| 
 | |
|             protected override void OnAbandon(TimeSpan timeout)
 | |
|             {
 | |
|                 this.wrappedContext.Abandon(timeout);
 | |
|                 DecrementBusyCount();
 | |
|             }
 | |
| 
 | |
|             protected override IAsyncResult OnBeginAbandon(TimeSpan timeout, AsyncCallback callback, object state)
 | |
|             {
 | |
|                 return this.wrappedContext.BeginAbandon(timeout, callback, state);
 | |
|             }
 | |
| 
 | |
|             protected override IAsyncResult OnBeginComplete(TimeSpan timeout, AsyncCallback callback, object state)
 | |
|             {
 | |
|                 RegisterForTransactionNotification(Transaction.Current);
 | |
|                 return this.wrappedContext.BeginComplete(timeout, callback, state);
 | |
|             }
 | |
| 
 | |
|             protected override void OnComplete(TimeSpan timeout)
 | |
|             {
 | |
|                 RegisterForTransactionNotification(Transaction.Current);
 | |
|                 this.wrappedContext.Complete(timeout);
 | |
|                 DecrementOnNoAmbientTransaction();
 | |
| 
 | |
|             }
 | |
| 
 | |
|             protected override void OnEndAbandon(IAsyncResult result)
 | |
|             {
 | |
|                 this.wrappedContext.EndAbandon(result);
 | |
|                 DecrementBusyCount();
 | |
|             }
 | |
| 
 | |
|             protected override void OnEndComplete(IAsyncResult result)
 | |
|             {
 | |
|                 this.wrappedContext.EndComplete(result);
 | |
|                 DecrementOnNoAmbientTransaction();
 | |
|             }
 | |
| 
 | |
|             protected override void OnFaulted()
 | |
|             {
 | |
|                 try
 | |
|                 {
 | |
|                     this.wrappedContext.Fault();
 | |
|                 }
 | |
|                 finally
 | |
|                 {
 | |
|                     base.OnFaulted();
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             void OnWrappedContextFaulted(object sender, EventArgs e)
 | |
|             {
 | |
|                 try
 | |
|                 {
 | |
|                     Fault();
 | |
|                 }
 | |
|                 finally
 | |
|                 {
 | |
|                     DecrementBusyCount();
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             void RegisterForTransactionNotification(Transaction transaction)
 | |
|             {
 | |
|                 if (Transaction.Current != null)
 | |
|                 {
 | |
|                     ReceiveContextEnlistmentNotification notification = new ReceiveContextEnlistmentNotification(this);
 | |
|                     transaction.EnlistVolatile(notification, EnlistmentOptions.None);
 | |
|                     Interlocked.Increment(ref this.ambientTransactionCount);
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             void DecrementOnNoAmbientTransaction()
 | |
|             {
 | |
|                 if (Interlocked.Exchange(ref this.ambientTransactionCount, 0) != 1)
 | |
|                 {
 | |
|                     DecrementBusyCount();
 | |
|                 }
 | |
| 
 | |
|             }
 | |
| 
 | |
|             void DecrementBusyCount()
 | |
|             {
 | |
|                 if (Interlocked.Exchange(ref this.busyCount, 0) == 1)
 | |
|                 {
 | |
|                     AspNetEnvironment.Current.DecrementBusyCount();
 | |
|                     if (AspNetEnvironment.Current.TraceDecrementBusyCountIsEnabled())
 | |
|                     {
 | |
|                         AspNetEnvironment.Current.TraceDecrementBusyCount(this.GetType().FullName);
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             class ReceiveContextEnlistmentNotification : IEnlistmentNotification
 | |
|             {
 | |
|                 ReceiveContextBusyCountWrapper context;
 | |
| 
 | |
|                 internal ReceiveContextEnlistmentNotification(ReceiveContextBusyCountWrapper context)
 | |
|                 {
 | |
|                     this.context = context;
 | |
|                 }
 | |
| 
 | |
|                 public void Commit(Enlistment enlistment)
 | |
|                 {
 | |
|                     this.context.DecrementBusyCount();
 | |
|                     enlistment.Done();
 | |
|                 }
 | |
| 
 | |
|                 public void InDoubt(Enlistment enlistment)
 | |
|                 {
 | |
|                     this.context.DecrementBusyCount();
 | |
|                     enlistment.Done();
 | |
|                 }
 | |
| 
 | |
|                 public void Prepare(PreparingEnlistment preparingEnlistment)
 | |
|                 {
 | |
|                     preparingEnlistment.Prepared();
 | |
|                 }
 | |
| 
 | |
|                 public void Rollback(Enlistment enlistment)
 | |
|                 {
 | |
|                     enlistment.Done();
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 |