The Labs \ Source Viewer \ SSCLI \ System.Runtime.Remoting \ DelayLoadClientChannelEntry

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. /*============================================================
  16. **
  17. ** File:    Configuration.cs
  18. **
  19. **
  20. ** Purpose: Classes used for reading and storing configuration
  21. **
  22. **
  23. ===========================================================*/
  24. namespace System.Runtime.Remoting
  25. {
  26.    
  27.     using System.Runtime.Remoting.Activation;
  28.     using System.Runtime.Remoting.Channels;
  29.     using System.Runtime.Remoting.Contexts;
  30.     using System.Runtime.Remoting.Lifetime;
  31.     using System.Runtime.Remoting.Messaging;
  32.     using System.Runtime.Remoting.Metadata;
  33.     using System.Runtime.InteropServices;
  34.     using System.Runtime.Serialization;
  35.     using System.Threading;
  36.     using System.IO;
  37.     using System.Security;
  38.     using System.Security.Permissions;
  39.     using System.Collections;
  40.     using System.Reflection;
  41.     using System.Globalization;
  42.     using System.Runtime.Versioning;
  43.    
  44.     [Serializable()]
  45.     [System.Runtime.InteropServices.ComVisible(true)]
  46.     public enum WellKnownObjectMode
  47.     {
  48.         Singleton = 1,
  49.         SingleCall = 2
  50.     }
  51.    
  52.     // This is the class that plays the role of per-appDomain statics
  53.     // till we have the real functionality.
  54.     internal class DomainSpecificRemotingData
  55.     {
  56.         const int ACTIVATION_INITIALIZING = 1;
  57.         const int ACTIVATION_INITIALIZED = 2;
  58.         const int ACTIVATOR_LISTENING = 4;
  59.        
  60.         LocalActivator _LocalActivator;
  61.         ActivationListener _ActivationListener;
  62.         IContextProperty[] _appDomainProperties;
  63.         int _flags;
  64.         object _ConfigLock;
  65.         ChannelServicesData _ChannelServicesData;
  66.         LeaseManager _LeaseManager;
  67.         ReaderWriterLock _IDTableLock;
  68.        
  69.         internal DomainSpecificRemotingData()
  70.         {
  71.             _flags = 0;
  72.             _ConfigLock = new object();
  73.             _ChannelServicesData = new ChannelServicesData();
  74.             _IDTableLock = new ReaderWriterLock();
  75.            
  76.             // Add the Lifetime service property to the appdomain.
  77.             // For now we are assuming that this is the only property
  78.             // If there are more properties, then an existing array
  79.             // will need to be expanded to add this property
  80.             // The property needs to be added here so that the default context
  81.             // for an appdomain has lifetime services activated
  82.            
  83.             _appDomainProperties = new IContextProperty[1];
  84.             _appDomainProperties[0] = new System.Runtime.Remoting.Lifetime.LeaseLifeTimeServiceProperty();
  85.         }
  86.        
  87.         internal LeaseManager LeaseManager {
  88.             get { return _LeaseManager; }
  89.             set { _LeaseManager = value; }
  90.         }
  91.        
  92.        
  93.         // This lock object is exposed for various objects that need to synchronize
  94.         // there configuration behavior.
  95.         internal object ConfigLock {
  96.             get { return _ConfigLock; }
  97.         }
  98.        
  99.         // This is the rwlock used by the uri table functions
  100.         internal ReaderWriterLock IDTableLock {
  101.             get { return _IDTableLock; }
  102.         }
  103.        
  104.        
  105.         internal LocalActivator LocalActivator {
  106.             get { return _LocalActivator; }
  107.             set { _LocalActivator = value; }
  108.         }
  109.        
  110.         internal ActivationListener ActivationListener {
  111.             get { return _ActivationListener; }
  112.             set { _ActivationListener = value; }
  113.         }
  114.        
  115.         // access to InitializingActivation, ActivationInitialized
  116.         // and ActivatorListening should be guarded by ConfigLock
  117.         // by the caller.
  118.         internal bool InitializingActivation {
  119.             get { return (_flags & ACTIVATION_INITIALIZING) == ACTIVATION_INITIALIZING; }
  120.             set {
  121.                 if (value == true) {
  122.                     _flags = _flags | ACTIVATION_INITIALIZING;
  123.                 }
  124.                 else {
  125.                     _flags = _flags & ~ACTIVATION_INITIALIZING;
  126.                 }
  127.             }
  128.         }
  129.        
  130.         internal bool ActivationInitialized {
  131.             get { return (_flags & ACTIVATION_INITIALIZED) == ACTIVATION_INITIALIZED; }
  132.             set {
  133.                 if (value == true) {
  134.                     _flags = _flags | ACTIVATION_INITIALIZED;
  135.                 }
  136.                 else {
  137.                     _flags = _flags & ~ACTIVATION_INITIALIZED;
  138.                 }
  139.             }
  140.         }
  141.        
  142.        
  143.         internal bool ActivatorListening {
  144.             get { return (_flags & ACTIVATOR_LISTENING) == ACTIVATOR_LISTENING; }
  145.             set {
  146.                 if (value == true) {
  147.                     _flags = _flags | ACTIVATOR_LISTENING;
  148.                 }
  149.                 else {
  150.                     _flags = _flags & ~ACTIVATOR_LISTENING;
  151.                 }
  152.             }
  153.         }
  154.        
  155.        
  156.        
  157.         internal IContextProperty[] AppDomainContextProperties {
  158.             get { return _appDomainProperties; }
  159.         }
  160.        
  161.         internal ChannelServicesData ChannelServicesData {
  162.             get { return _ChannelServicesData; }
  163.         }
  164.     }
  165.     // class DomainSpecificRemotingData
  166.    
  167.    
  168.    
  169.     //------------------------------------------------------------------
  170.     //--------------------- Remoting Configuration ---------------------
  171.     //------------------------------------------------------------------
  172.     static internal class RemotingConfigHandler
  173.     {
  174.         static string _applicationName;
  175.         static CustomErrorsModes _errorMode = CustomErrorsModes.RemoteOnly;
  176.         static bool _errorsModeSet = false;
  177.         static bool _bMachineConfigLoaded = false;
  178.         static bool _bUrlObjRefMode = false;
  179.        
  180.         static Queue _delayLoadChannelConfigQueue = new Queue();
  181.         // queue of channels we might be able to use
  182.        
  183.         // All functions of RemotingConfigHandler operate upon the config
  184.         // data stored on a per appDomain basis
  185.         public static RemotingConfigInfo Info = new RemotingConfigInfo();
  186.        
  187.         private const string _machineConfigFilename = "machine.config";
  188.        
  189.        
  190.         static internal string ApplicationName {
  191.             get {
  192.                 if (_applicationName == null) {
  193.                     throw new RemotingException(Environment.GetResourceString("Remoting_Config_NoAppName"));
  194.                 }
  195.                 return _applicationName;
  196.             }
  197.            
  198.             set {
  199.                 if (_applicationName != null) {
  200.                     throw new RemotingException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_Config_AppNameSet"), _applicationName));
  201.                 }
  202.                
  203.                 _applicationName = value;
  204.                
  205.                 // get rid of any starting or trailing slashes
  206.                 char[] slash = new char[] {'/'};
  207.                 if (_applicationName.StartsWith("/", StringComparison.Ordinal))
  208.                     _applicationName = _applicationName.TrimStart(slash);
  209.                 if (_applicationName.EndsWith("/", StringComparison.Ordinal))
  210.                     _applicationName = _applicationName.TrimEnd(slash);
  211.             }
  212.         }
  213.        
  214.         static internal bool HasApplicationNameBeenSet()
  215.         {
  216.             return _applicationName != null;
  217.         }
  218.        
  219.         static internal bool UrlObjRefMode {
  220.             get { return _bUrlObjRefMode; }
  221.         }
  222.        
  223.         static internal CustomErrorsModes CustomErrorsMode {
  224.             get { return _errorMode; }
  225.             set {
  226.                 if (_errorsModeSet)
  227.                     throw new RemotingException(Environment.GetResourceString("Remoting_Config_ErrorsModeSet"));
  228.                
  229.                 _errorsModeSet = true;
  230.                 _errorMode = value;
  231.             }
  232.         }
  233.        
  234.        
  235.         static internal IMessageSink FindDelayLoadChannelForCreateMessageSink(string url, object data, out string objectURI)
  236.         {
  237.             LoadMachineConfigIfNecessary();
  238.            
  239.             objectURI = null;
  240.             IMessageSink msgSink = null;
  241.            
  242.             foreach (DelayLoadClientChannelEntry entry in _delayLoadChannelConfigQueue) {
  243.                 IChannelSender channel = entry.Channel;
  244.                
  245.                 // if the channel is null, that means it has already been registered.
  246.                 if (channel != null) {
  247.                     msgSink = channel.CreateMessageSink(url, data, out objectURI);
  248.                     if (msgSink != null) {
  249.                         entry.RegisterChannel();
  250.                         return msgSink;
  251.                     }
  252.                 }
  253.             }
  254.            
  255.             return null;
  256.         }
  257.         // FindChannelForCreateMessageSink
  258.        
  259.        
  260.         [ResourceExposure(ResourceScope.None)]
  261.         [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
  262.         static void LoadMachineConfigIfNecessary()
  263.         {
  264.             // Load the machine.config file if we haven't already
  265.             if (!_bMachineConfigLoaded) {
  266.                 lock (Info) {
  267.                     if (!_bMachineConfigLoaded) {
  268.                         RemotingXmlConfigFileData configData = RemotingXmlConfigFileParser.ParseDefaultConfiguration();
  269.                         if (configData != null)
  270.                             /*ensureSecurity*/                            ConfigureRemoting(configData, false);
  271.                        
  272.                         string machineDirectory = System.Security.Util.Config.MachineDirectory;
  273.                         string longFileName = machineDirectory + _machineConfigFilename;
  274.                         new FileIOPermission(FileIOPermissionAccess.Read, longFileName).Assert();
  275.                        
  276.                         configData = LoadConfigurationFromXmlFile(longFileName);
  277.                        
  278.                         if (configData != null)
  279.                             /*ensureSecurity*/                            ConfigureRemoting(configData, false);
  280.                        
  281.                         _bMachineConfigLoaded = true;
  282.                     }
  283.                 }
  284.             }
  285.         }
  286.         // LoadMachineConfigIfNecessary
  287.        
  288.         [ResourceExposure(ResourceScope.Machine)]
  289.         [ResourceConsumption(ResourceScope.Machine)]
  290.         static internal void DoConfiguration(string filename, bool ensureSecurity)
  291.         {
  292.             LoadMachineConfigIfNecessary();
  293.            
  294.             // load specified config file
  295.             RemotingXmlConfigFileData configData = LoadConfigurationFromXmlFile(filename);
  296.            
  297.             // Configure remoting based on data loaded from the config file.
  298.             // By design, we do nothing if no remoting config information was
  299.             // present in the file.
  300.             if (configData != null)
  301.                 ConfigureRemoting(configData, ensureSecurity);
  302.         }
  303.        
  304.         [ResourceExposure(ResourceScope.Machine)]
  305.         [ResourceConsumption(ResourceScope.Machine)]
  306.         private static RemotingXmlConfigFileData LoadConfigurationFromXmlFile(string filename)
  307.         {
  308.             try {
  309.                 if (filename != null)
  310.                     return RemotingXmlConfigFileParser.ParseConfigFile(filename);
  311.                 else
  312.                     return null;
  313.             }
  314.             catch (Exception e) {
  315.                 Exception inner = e.InnerException as FileNotFoundException;
  316.                 if (inner != null) {
  317.                     // if the file is missing, this gives a clearer message
  318.                     e = inner;
  319.                 }
  320.                 throw new RemotingException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_Config_ReadFailure"), filename, e));
  321.             }
  322.         }
  323.         // LoadConfigurationFromXmlFile
  324.        
  325.         private static void ConfigureRemoting(RemotingXmlConfigFileData configData, bool ensureSecurity)
  326.         {
  327.             try {
  328.                 string appName = configData.ApplicationName;
  329.                 if (appName != null)
  330.                     ApplicationName = appName;
  331.                
  332.                 if (configData.CustomErrors != null)
  333.                     _errorMode = configData.CustomErrors.Mode;
  334.                
  335.                 // configure channels
  336.                 ConfigureChannels(configData, ensureSecurity);
  337.                
  338.                 // configure lifetime
  339.                 if (configData.Lifetime != null) {
  340.                     if (configData.Lifetime.IsLeaseTimeSet)
  341.                         LifetimeServices.LeaseTime = configData.Lifetime.LeaseTime;
  342.                     if (configData.Lifetime.IsRenewOnCallTimeSet)
  343.                         LifetimeServices.RenewOnCallTime = configData.Lifetime.RenewOnCallTime;
  344.                     if (configData.Lifetime.IsSponsorshipTimeoutSet)
  345.                         LifetimeServices.SponsorshipTimeout = configData.Lifetime.SponsorshipTimeout;
  346.                     if (configData.Lifetime.IsLeaseManagerPollTimeSet)
  347.                         LifetimeServices.LeaseManagerPollTime = configData.Lifetime.LeaseManagerPollTime;
  348.                 }
  349.                
  350.                 _bUrlObjRefMode = configData.UrlObjRefMode;
  351.                
  352.                 // configure other entries
  353.                 Info.StoreRemoteAppEntries(configData);
  354.                 Info.StoreActivatedExports(configData);
  355.                 Info.StoreInteropEntries(configData);
  356.                 Info.StoreWellKnownExports(configData);
  357.                
  358.                 // start up activation listener if there are any activated objects exposed
  359.                 if (configData.ServerActivatedEntries.Count > 0)
  360.                     ActivationServices.StartListeningForRemoteRequests();
  361.             }
  362.             catch (Exception e) {
  363.                 throw new RemotingException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_Config_ConfigurationFailure"), e));
  364.             }
  365.         }
  366.         // ConfigureRemoting
  367.        
  368.         // configures channels loaded from remoting config file.
  369.         private static void ConfigureChannels(RemotingXmlConfigFileData configData, bool ensureSecurity)
  370.         {
  371.             // Register our x-context & x-AD channels first
  372.             RemotingServices.RegisterWellKnownChannels();
  373.            
  374.             foreach (RemotingXmlConfigFileData.ChannelEntry entry in configData.ChannelEntries) {
  375.                 if (!entry.DelayLoad) {
  376.                     IChannel chnl = CreateChannelFromConfigEntry(entry);
  377.                     ChannelServices.RegisterChannel(chnl, ensureSecurity);
  378.                 }
  379.                 else
  380.                     _delayLoadChannelConfigQueue.Enqueue(new DelayLoadClientChannelEntry(entry, ensureSecurity));
  381.             }
  382.         }
  383.         // ConfigureChannels
  384.        
  385.         static internal IChannel CreateChannelFromConfigEntry(RemotingXmlConfigFileData.ChannelEntry entry)
  386.         {
  387.             Type type = RemotingConfigInfo.LoadType(entry.TypeName, entry.AssemblyName);
  388.            
  389.             bool isServerChannel = typeof(IChannelReceiver).IsAssignableFrom(type);
  390.             bool isClientChannel = typeof(IChannelSender).IsAssignableFrom(type);
  391.            
  392.             IClientChannelSinkProvider clientProviderChain = null;
  393.             IServerChannelSinkProvider serverProviderChain = null;
  394.            
  395.             if (entry.ClientSinkProviders.Count > 0)
  396.                 clientProviderChain = CreateClientChannelSinkProviderChain(entry.ClientSinkProviders);
  397.             if (entry.ServerSinkProviders.Count > 0)
  398.                 serverProviderChain = CreateServerChannelSinkProviderChain(entry.ServerSinkProviders);
  399.            
  400.             // construct argument list
  401.             object[] args;
  402.            
  403.             if (isServerChannel && isClientChannel) {
  404.                 args = new object[3];
  405.                 args[0] = entry.Properties;
  406.                 args[1] = clientProviderChain;
  407.                 args[2] = serverProviderChain;
  408.             }
  409.             else if (isServerChannel) {
  410.                 args = new object[2];
  411.                 args[0] = entry.Properties;
  412.                 args[1] = serverProviderChain;
  413.             }
  414.             else if (isClientChannel) {
  415.                 args = new object[2];
  416.                 args[0] = entry.Properties;
  417.                 args[1] = clientProviderChain;
  418.             }
  419.             else {
  420.                 throw new RemotingException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_Config_InvalidChannelType"), type.FullName));
  421.             }
  422.            
  423.             IChannel channel = null;
  424.            
  425.             try {
  426.                 channel = (IChannel)Activator.CreateInstance(type, BindingFlags.Instance | BindingFlags.Public | BindingFlags.CreateInstance, null, args, null, null);
  427.                
  428.             }
  429.             catch (MissingMethodException) {
  430.                 string ctor = null;
  431.                
  432.                 if (isServerChannel && isClientChannel)
  433.                     ctor = "MyChannel(IDictionary properties, IClientChannelSinkProvider clientSinkProvider, IServerChannelSinkProvider serverSinkProvider)";
  434.                 else if (isServerChannel)
  435.                     ctor = "MyChannel(IDictionary properties, IServerChannelSinkProvider serverSinkProvider)";
  436.                 else if (isClientChannel)
  437.                     ctor = "MyChannel(IDictionary properties, IClientChannelSinkProvider clientSinkProvider)";
  438.                
  439.                 throw new RemotingException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_Config_ChannelMissingCtor"), type.FullName, ctor));
  440.             }
  441.            
  442.             return channel;
  443.         }
  444.         // CreateChannelFromEntry
  445.        
  446.         // create a client sink provider chain
  447.         private static IClientChannelSinkProvider CreateClientChannelSinkProviderChain(ArrayList entries)
  448.         {
  449.             IClientChannelSinkProvider chain = null;
  450.             IClientChannelSinkProvider current = null;
  451.            
  452.             foreach (RemotingXmlConfigFileData.SinkProviderEntry entry in entries) {
  453.                 if (chain == null) {
  454.                     chain = (IClientChannelSinkProvider)CreateChannelSinkProvider(entry, false);
  455.                     current = chain;
  456.                 }
  457.                 else {
  458.                     current.Next = (IClientChannelSinkProvider)CreateChannelSinkProvider(entry, false);
  459.                     current = current.Next;
  460.                 }
  461.             }
  462.            
  463.             return chain;
  464.         }
  465.         // CreateClientChannelSinkProviderChain
  466.        
  467.         // create a client sink provider chain
  468.         private static IServerChannelSinkProvider CreateServerChannelSinkProviderChain(ArrayList entries)
  469.         {
  470.             IServerChannelSinkProvider chain = null;
  471.             IServerChannelSinkProvider current = null;
  472.            
  473.             foreach (RemotingXmlConfigFileData.SinkProviderEntry entry in entries) {
  474.                 if (chain == null) {
  475.                     chain = (IServerChannelSinkProvider)CreateChannelSinkProvider(entry, true);
  476.                     current = chain;
  477.                 }
  478.                 else {
  479.                     current.Next = (IServerChannelSinkProvider)CreateChannelSinkProvider(entry, true);
  480.                     current = current.Next;
  481.                 }
  482.             }
  483.            
  484.             return chain;
  485.         }
  486.         // CreateServerChannelSinkProviderChain
  487.        
  488.         // create a sink provider from the config file data
  489.         private static object CreateChannelSinkProvider(RemotingXmlConfigFileData.SinkProviderEntry entry, bool bServer)
  490.         {
  491.             object sinkProvider = null;
  492.            
  493.             Type type = RemotingConfigInfo.LoadType(entry.TypeName, entry.AssemblyName);
  494.            
  495.             if (bServer) {
  496.                 // make sure this is a client provider
  497.                 if (!typeof(IServerChannelSinkProvider).IsAssignableFrom(type)) {
  498.                     throw new RemotingException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_Config_InvalidSinkProviderType"), type.FullName, "IServerChannelSinkProvider"));
  499.                 }
  500.             }
  501.             else {
  502.                 // make sure this is a server provider
  503.                 if (!typeof(IClientChannelSinkProvider).IsAssignableFrom(type)) {
  504.                     throw new RemotingException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_Config_InvalidSinkProviderType"), type.FullName, "IClientChannelSinkProvider"));
  505.                 }
  506.             }
  507.            
  508.             // check to see if something labelled as a formatter is a formatter
  509.             if (entry.IsFormatter) {
  510.                 if ((bServer && !typeof(IServerFormatterSinkProvider).IsAssignableFrom(type)) || (!bServer && !typeof(IClientFormatterSinkProvider).IsAssignableFrom(type))) {
  511.                     throw new RemotingException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_Config_SinkProviderNotFormatter"), type.FullName));
  512.                 }
  513.             }
  514.            
  515.             // setup the argument list and call the constructor
  516.             object[] args = new object[2];
  517.             args[0] = entry.Properties;
  518.             args[1] = entry.ProviderData;
  519.            
  520.             try {
  521.                 sinkProvider = Activator.CreateInstance(type, BindingFlags.Instance | BindingFlags.Public | BindingFlags.CreateInstance, null, args, null, null);
  522.             }
  523.             catch (MissingMethodException) {
  524.                 throw new RemotingException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_Config_SinkProviderMissingCtor"), type.FullName, "MySinkProvider(IDictionary properties, ICollection providerData)"));
  525.             }
  526.            
  527.             return sinkProvider;
  528.         }
  529.         // CreateChannelSinkProvider
  530.         // This is used at the client end to check if an activation needs
  531.         // to go remote.
  532.         static internal ActivatedClientTypeEntry IsRemotelyActivatedClientType(Type svrType)
  533.         {
  534.             RemotingTypeCachedData cache = (RemotingTypeCachedData)InternalRemotingServices.GetReflectionCachedData(svrType);
  535.            
  536.             string assemblyName = cache.SimpleAssemblyName;
  537.             ActivatedClientTypeEntry entry = Info.QueryRemoteActivate(svrType.FullName, assemblyName);
  538.            
  539.             if (entry == null) {
  540.                 // If not found try with the full assembly name
  541.                 string fullAssemblyName = cache.AssemblyName;
  542.                 entry = Info.QueryRemoteActivate(svrType.FullName, fullAssemblyName);
  543.                 if (entry == null) {
  544.                     // If still not found try with partial type name (without namespace)
  545.                     entry = Info.QueryRemoteActivate(svrType.Name, assemblyName);
  546.                 }
  547.             }
  548.             return entry;
  549.         }
  550.         // IsRemotelyActivatedClientType
  551.        
  552.         // This is used at the client end to check if an activation needs
  553.         // to go remote.
  554.         static internal ActivatedClientTypeEntry IsRemotelyActivatedClientType(string typeName, string assemblyName)
  555.         {
  556.             return Info.QueryRemoteActivate(typeName, assemblyName);
  557.         }
  558.        
  559.        
  560.         // This is used at the client end to check if a "new Foo" needs to
  561.         // happen via a Connect() under the covers.
  562.         static internal WellKnownClientTypeEntry IsWellKnownClientType(Type svrType)
  563.         {
  564.             RemotingTypeCachedData cache = (RemotingTypeCachedData)InternalRemotingServices.GetReflectionCachedData(svrType);
  565.            
  566.             string assemblyName = cache.SimpleAssemblyName;
  567.             WellKnownClientTypeEntry wke = Info.QueryConnect(svrType.FullName, assemblyName);
  568.             if (wke == null) {
  569.                 wke = Info.QueryConnect(svrType.Name, assemblyName);
  570.             }
  571.             return wke;
  572.         }
  573.        
  574.         // This is used at the client end to check if a "new Foo" needs to
  575.         // happen via a Connect() under the covers.
  576.         static internal WellKnownClientTypeEntry IsWellKnownClientType(string typeName, string assemblyName)
  577.         {
  578.             return Info.QueryConnect(typeName, assemblyName);
  579.         }
  580.        
  581.         //
  582.         // helper functions for processing and parsing data
  583.         //
  584.         private static void ParseGenericType(string typeAssem, int indexStart, out string typeName, out string assemName)
  585.         {
  586.             int len = typeAssem.Length;
  587.             int depth = 1;
  588.            
  589.             int index = indexStart;
  590.             while (depth > 0 && (++index < len - 1)) {
  591.                 if (typeAssem[index] == '[') {
  592.                     depth++;
  593.                 }
  594.                 else if (typeAssem[index] == ']') {
  595.                     depth--;
  596.                 }
  597.             }
  598.            
  599.             if (depth > 0 || index >= len) {
  600.                 typeName = null;
  601.                 assemName = null;
  602.             }
  603.             else {
  604.                 index = typeAssem.IndexOf(',', index);
  605.                 // comma must be present, and can't be last character
  606.                 if ((index >= 0) && (index < (len - 1))) {
  607.                     typeName = typeAssem.Substring(0, index).Trim();
  608.                     assemName = typeAssem.Substring(index + 1).Trim();
  609.                 }
  610.                 else {
  611.                     typeName = null;
  612.                     assemName = null;
  613.                 }
  614.             }
  615.         }
  616.        
  617.         static internal void ParseType(string typeAssem, out string typeName, out string assemName)
  618.         {
  619.             string value = typeAssem;
  620.            
  621.             int genericTypeIndex = value.IndexOf("[");
  622.             if ((genericTypeIndex >= 0) && (genericTypeIndex < (value.Length - 1))) {
  623.                 ParseGenericType(value, genericTypeIndex, out typeName, out assemName);
  624.             }
  625.             else {
  626.                 int index = value.IndexOf(",");
  627.                
  628.                 // comma must be present, and can't be last character
  629.                 if ((index >= 0) && (index < (value.Length - 1))) {
  630.                     typeName = value.Substring(0, index).Trim();
  631.                     assemName = value.Substring(index + 1).Trim();
  632.                 }
  633.                 else {
  634.                     typeName = null;
  635.                     assemName = null;
  636.                 }
  637.             }
  638.         }
  639.         // ParseType
  640.         // This is used at the server end to check if a type being activated
  641.         // is explicitly allowed by the server.
  642.         static internal bool IsActivationAllowed(Type svrType)
  643.         {
  644.             if (svrType == null)
  645.                 return false;
  646.            
  647.             RemotingTypeCachedData cache = (RemotingTypeCachedData)InternalRemotingServices.GetReflectionCachedData(svrType);
  648.            
  649.             string assemblyName = cache.SimpleAssemblyName;
  650.            
  651.             return Info.ActivationAllowed(svrType.FullName, assemblyName);
  652.         }
  653.         // IsActivationAllowed
  654.         // This is the flavor that we call from the activation listener
  655.         // code path. This ensures that we don't load a type before checking
  656.         // that it is configured for remote activation
  657.         static internal bool IsActivationAllowed(string TypeName)
  658.         {
  659.             string svrTypeName = RemotingServices.InternalGetTypeNameFromQualifiedTypeName(TypeName);
  660.             if (svrTypeName == null) {
  661.                 return false;
  662.             }
  663.             string typeName;
  664.             string asmName;
  665.            
  666.             ParseType(svrTypeName, out typeName, out asmName);
  667.             if (asmName == null)
  668.                 return false;
  669.            
  670.             int index = asmName.IndexOf(',');
  671.             if (index != -1) {
  672.                 // strip off the version info
  673.                 asmName = asmName.Substring(0, index);
  674.             }
  675.             return Info.ActivationAllowed(typeName, asmName);
  676.         }
  677.        
  678.         // helper for Configuration::RegisterActivatedServiceType
  679.         static internal void RegisterActivatedServiceType(ActivatedServiceTypeEntry entry)
  680.         {
  681.             Info.AddActivatedType(entry.TypeName, entry.AssemblyName, entry.ContextAttributes);
  682.         }
  683.         // RegisterActivatedServiceType
  684.        
  685.         // helper for Configuration::RegisterWellKnownServiceType
  686.         static internal void RegisterWellKnownServiceType(WellKnownServiceTypeEntry entry)
  687.         {
  688.             BCLDebug.Trace("REMOTE", "Adding well known service type for " + entry.ObjectUri);
  689.             string serverType = entry.TypeName;
  690.             string asmName = entry.AssemblyName;
  691.             string URI = entry.ObjectUri;
  692.             WellKnownObjectMode mode = entry.Mode;
  693.            
  694.             lock (Info) {
  695.                 // We make an entry in our config tables so as to keep
  696.                 // both the file-based and programmatic config in sync.
  697.                 Info.AddWellKnownEntry(entry);
  698.             }
  699.         }
  700.         // RegisterWellKnownServiceType
  701.        
  702.         // helper for Configuration::RegisterActivatedClientType
  703.         static internal void RegisterActivatedClientType(ActivatedClientTypeEntry entry)
  704.         {
  705.             Info.AddActivatedClientType(entry);
  706.         }
  707.        
  708.         // helper for Configuration::RegisterWellKnownClientType
  709.         static internal void RegisterWellKnownClientType(WellKnownClientTypeEntry entry)
  710.         {
  711.             Info.AddWellKnownClientType(entry);
  712.         }
  713.        
  714.         //helper for Configuration::GetServerTypeForUri
  715.         static internal Type GetServerTypeForUri(string URI)
  716.         {
  717.             URI = Identity.RemoveAppNameOrAppGuidIfNecessary(URI);
  718.             return Info.GetServerTypeForUri(URI);
  719.         }
  720.        
  721.         // helper for Configuration::GetRegisteredActivatedServiceTypes
  722.         static internal ActivatedServiceTypeEntry[] GetRegisteredActivatedServiceTypes()
  723.         {
  724.             return Info.GetRegisteredActivatedServiceTypes();
  725.         }
  726.         // GetRegisteredActivatedServiceTypes
  727.         // helper for Configuration::GetRegisteredWellKnownServiceTypes
  728.         static internal WellKnownServiceTypeEntry[] GetRegisteredWellKnownServiceTypes()
  729.         {
  730.             return Info.GetRegisteredWellKnownServiceTypes();
  731.         }
  732.         // GetRegisteredWellKnownServiceTypes
  733.         // helper for Configuration::GetRegisteredActivatedClientTypes
  734.         static internal ActivatedClientTypeEntry[] GetRegisteredActivatedClientTypes()
  735.         {
  736.             return Info.GetRegisteredActivatedClientTypes();
  737.         }
  738.         // GetRegisteredActivatedClientTypes
  739.         // helper for Configuration::GetRegisteredWellKnownClientTypes
  740.         static internal WellKnownClientTypeEntry[] GetRegisteredWellKnownClientTypes()
  741.         {
  742.             return Info.GetRegisteredWellKnownClientTypes();
  743.         }
  744.         // GetRegisteredWellKnownClientTypes
  745.        
  746.         // helper for creating well known objects on demand
  747.         static internal ServerIdentity CreateWellKnownObject(string uri)
  748.         {
  749.             uri = Identity.RemoveAppNameOrAppGuidIfNecessary(uri);
  750.             return Info.StartupWellKnownObject(uri);
  751.         }
  752.        
  753.        
  754.         internal class RemotingConfigInfo
  755.         {
  756.             Hashtable _exportableClasses;
  757.             // list of objects that can be client-activated
  758.             // (this should be a StringTable since we only use the key,
  759.             // but that type was removed from the BCL :( )
  760.             Hashtable _remoteTypeInfo;
  761.             Hashtable _remoteAppInfo;
  762.             Hashtable _wellKnownExportInfo;
  763.             //well known exports indexed by object URI in lower-case
  764.             static char[] SepSpace = {' '};
  765.             static char[] SepPound = {'#'};
  766.             static char[] SepSemiColon = {';'};
  767.             static char[] SepEquals = {'='};
  768.            
  769.             private static object s_wkoStartLock = new object();
  770.             private static PermissionSet s_fullTrust = new PermissionSet(PermissionState.Unrestricted);
  771.            
  772.             internal RemotingConfigInfo()
  773.             {
  774.                 _remoteTypeInfo = Hashtable.Synchronized(new Hashtable());
  775.                
  776.                 _exportableClasses = Hashtable.Synchronized(new Hashtable());
  777.                
  778.                 _remoteAppInfo = Hashtable.Synchronized(new Hashtable());
  779.                 _wellKnownExportInfo = Hashtable.Synchronized(new Hashtable());
  780.             }
  781.            
  782.            
  783.             // encodes type name and assembly name into one string for purposes of
  784.             // indexing in lists and hash tables
  785.             private string EncodeTypeAndAssemblyNames(string typeName, string assemblyName)
  786.             {
  787.                 return typeName + ", " + assemblyName.ToLower(CultureInfo.InvariantCulture);
  788.             }
  789.            
  790.            
  791.             //
  792.             // XML Configuration Helper Functions
  793.             //
  794.            
  795.             internal void StoreActivatedExports(RemotingXmlConfigFileData configData)
  796.             {
  797.                 foreach (RemotingXmlConfigFileData.TypeEntry entry in configData.ServerActivatedEntries) {
  798.                     ActivatedServiceTypeEntry aste = new ActivatedServiceTypeEntry(entry.TypeName, entry.AssemblyName);
  799.                     aste.ContextAttributes = CreateContextAttributesFromConfigEntries(entry.ContextAttributes);
  800.                    
  801.                     RemotingConfiguration.RegisterActivatedServiceType(aste);
  802.                 }
  803.             }
  804.             // StoreActivatedExports
  805.             internal void StoreInteropEntries(RemotingXmlConfigFileData configData)
  806.             {
  807.                 // process interop xml element entries
  808.                 foreach (RemotingXmlConfigFileData.InteropXmlElementEntry entry in configData.InteropXmlElementEntries) {
  809.                     Assembly assembly = Assembly.Load(entry.UrtAssemblyName);
  810.                     Type type = assembly.GetType(entry.UrtTypeName);
  811.                     SoapServices.RegisterInteropXmlElement(entry.XmlElementName, entry.XmlElementNamespace, type);
  812.                 }
  813.                
  814.                 // process interop xml type entries
  815.                 foreach (RemotingXmlConfigFileData.InteropXmlTypeEntry entry in configData.InteropXmlTypeEntries) {
  816.                     Assembly assembly = Assembly.Load(entry.UrtAssemblyName);
  817.                     Type type = assembly.GetType(entry.UrtTypeName);
  818.                     SoapServices.RegisterInteropXmlType(entry.XmlTypeName, entry.XmlTypeNamespace, type);
  819.                 }
  820.                
  821.                 // process preload entries
  822.                 foreach (RemotingXmlConfigFileData.PreLoadEntry entry in configData.PreLoadEntries) {
  823.                     Assembly assembly = Assembly.Load(entry.AssemblyName);
  824.                    
  825.                     if (entry.TypeName != null) {
  826.                         Type type = assembly.GetType(entry.TypeName);
  827.                         SoapServices.PreLoad(type);
  828.                     }
  829.                     else {
  830.                         SoapServices.PreLoad(assembly);
  831.                     }
  832.                 }
  833.             }
  834.             // StoreInteropEntries
  835.             internal void StoreRemoteAppEntries(RemotingXmlConfigFileData configData)
  836.             {
  837.                 char[] slash = new char[] {'/'};
  838.                
  839.                 // add each remote app to the table
  840.                 foreach (RemotingXmlConfigFileData.RemoteAppEntry remApp in configData.RemoteAppEntries) {
  841.                     // form complete application uri by combining specified uri with app-name
  842.                     // (make sure appUri ends with slash, and that app name doesn't start,
  843.                     // with one. then make sure that the combined form has no trailing slashes).
  844.                     string appUri = remApp.AppUri;
  845.                     if ((appUri != null) && !appUri.EndsWith("/", StringComparison.Ordinal))
  846.                         appUri = appUri.TrimEnd(slash);
  847.                    
  848.                     // add each client activated type for this remote app
  849.                     foreach (RemotingXmlConfigFileData.TypeEntry cae in remApp.ActivatedObjects) {
  850.                         ActivatedClientTypeEntry acte = new ActivatedClientTypeEntry(cae.TypeName, cae.AssemblyName, appUri);
  851.                         acte.ContextAttributes = CreateContextAttributesFromConfigEntries(cae.ContextAttributes);
  852.                        
  853.                         RemotingConfiguration.RegisterActivatedClientType(acte);
  854.                     }
  855.                    
  856.                     // add each well known object for this remote app
  857.                     foreach (RemotingXmlConfigFileData.ClientWellKnownEntry cwke in remApp.WellKnownObjects) {
  858.                         WellKnownClientTypeEntry wke = new WellKnownClientTypeEntry(cwke.TypeName, cwke.AssemblyName, cwke.Url);
  859.                         wke.ApplicationUrl = appUri;
  860.                        
  861.                         RemotingConfiguration.RegisterWellKnownClientType(wke);
  862.                     }
  863.                 }
  864.             }
  865.             // StoreRemoteAppEntries
  866.             internal void StoreWellKnownExports(RemotingXmlConfigFileData configData)
  867.             {
  868.                
  869.                 foreach (RemotingXmlConfigFileData.ServerWellKnownEntry entry in configData.ServerWellKnownEntries) {
  870.                     WellKnownServiceTypeEntry wke = new WellKnownServiceTypeEntry(entry.TypeName, entry.AssemblyName, entry.ObjectURI, entry.ObjectMode);
  871.                     wke.ContextAttributes = null;
  872.                    
  873.                     // Register the well known entry but do not startup the object
  874.                     RemotingConfigHandler.RegisterWellKnownServiceType(wke);
  875.                 }
  876.             }
  877.             // StoreWellKnownExports
  878.            
  879.             // helper functions for above configuration helpers
  880.            
  881.             static IContextAttribute[] CreateContextAttributesFromConfigEntries(ArrayList contextAttributes)
  882.             {
  883.                 // create context attribute entry list
  884.                 int numAttrs = contextAttributes.Count;
  885.                 if (numAttrs == 0)
  886.                     return null;
  887.                
  888.                 IContextAttribute[] attrs = new IContextAttribute[numAttrs];
  889.                
  890.                 int co = 0;
  891.                 foreach (RemotingXmlConfigFileData.ContextAttributeEntry cae in contextAttributes) {
  892.                     Assembly asm = Assembly.Load(cae.AssemblyName);
  893.                    
  894.                     IContextAttribute attr = null;
  895.                     Hashtable properties = cae.Properties;
  896.                     if ((properties != null) && (properties.Count > 0)) {
  897.                         object[] args = new object[1];
  898.                         args[0] = properties;
  899.                        
  900.                         // We explicitly allow the ability to create internal
  901.                         // only attributes
  902.                         attr = (IContextAttribute)Activator.CreateInstance(asm.GetType(cae.TypeName, false, false), BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.CreateInstance, null, args, null, null);
  903.                     }
  904.                     else {
  905.                         attr = (IContextAttribute)Activator.CreateInstance(asm.GetType(cae.TypeName, false, false), true);
  906.                     }
  907.                    
  908.                     attrs[co++] = attr;
  909.                 }
  910.                
  911.                 return attrs;
  912.             }
  913.             // CreateContextAttributesFromConfigEntries
  914.             //
  915.             // end of XML configuration helper functions
  916.             //
  917.            
  918.             internal bool ActivationAllowed(string typeName, string assemblyName)
  919.             {
  920.                 // the assembly name is stored in lower-case to let it be case-insensitive
  921.                 return _exportableClasses.ContainsKey(EncodeTypeAndAssemblyNames(typeName, assemblyName));
  922.             }
  923.            
  924.             internal ActivatedClientTypeEntry QueryRemoteActivate(string typeName, string assemblyName)
  925.             {
  926.                 string index = EncodeTypeAndAssemblyNames(typeName, assemblyName);
  927.                
  928.                 ActivatedClientTypeEntry typeEntry = _remoteTypeInfo[index] as ActivatedClientTypeEntry;
  929.                 if (typeEntry == null)
  930.                     return null;
  931.                
  932.                 if (typeEntry.GetRemoteAppEntry() == null) {
  933.                     RemoteAppEntry appEntry = (RemoteAppEntry)_remoteAppInfo[typeEntry.ApplicationUrl];
  934.                     if (appEntry == null) {
  935.                         throw new RemotingException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_Activation_MissingRemoteAppEntry"), typeEntry.ApplicationUrl));
  936.                     }
  937.                     typeEntry.CacheRemoteAppEntry(appEntry);
  938.                 }
  939.                 return typeEntry;
  940.             }
  941.            
  942.             internal WellKnownClientTypeEntry QueryConnect(string typeName, string assemblyName)
  943.             {
  944.                 string index = EncodeTypeAndAssemblyNames(typeName, assemblyName);
  945.                
  946.                 WellKnownClientTypeEntry typeEntry = _remoteTypeInfo[index] as WellKnownClientTypeEntry;
  947.                 if (typeEntry == null)
  948.                     return null;
  949.                
  950.                 return typeEntry;
  951.             }
  952.            
  953.             //
  954.             // helper functions to retrieve registered types
  955.             //
  956.            
  957.            
  958.             internal ActivatedServiceTypeEntry[] GetRegisteredActivatedServiceTypes()
  959.             {
  960.                 ActivatedServiceTypeEntry[] entries = new ActivatedServiceTypeEntry[_exportableClasses.Count];
  961.                
  962.                 int co = 0;
  963.                 foreach (DictionaryEntry dictEntry in _exportableClasses) {
  964.                     entries[co++] = (ActivatedServiceTypeEntry)dictEntry.Value;
  965.                 }
  966.                
  967.                 return entries;
  968.             }
  969.             // GetRegisteredActivatedServiceTypes
  970.            
  971.             internal WellKnownServiceTypeEntry[] GetRegisteredWellKnownServiceTypes()
  972.             {
  973.                 WellKnownServiceTypeEntry[] entries = new WellKnownServiceTypeEntry[_wellKnownExportInfo.Count];
  974.                
  975.                 int co = 0;
  976.                 foreach (DictionaryEntry dictEntry in _wellKnownExportInfo) {
  977.                     WellKnownServiceTypeEntry entry = (WellKnownServiceTypeEntry)dictEntry.Value;
  978.                    
  979.                     WellKnownServiceTypeEntry wkste = new WellKnownServiceTypeEntry(entry.TypeName, entry.AssemblyName, entry.ObjectUri, entry.Mode);
  980.                    
  981.                     wkste.ContextAttributes = entry.ContextAttributes;
  982.                    
  983.                     entries[co++] = wkste;
  984.                 }
  985.                
  986.                 return entries;
  987.             }
  988.             // GetRegisteredWellKnownServiceTypes
  989.            
  990.             internal ActivatedClientTypeEntry[] GetRegisteredActivatedClientTypes()
  991.             {
  992.                 // count number of well known client types
  993.                 int count = 0;
  994.                 foreach (DictionaryEntry dictEntry in _remoteTypeInfo) {
  995.                     ActivatedClientTypeEntry entry = dictEntry.Value as ActivatedClientTypeEntry;
  996.                     if (entry != null)
  997.                         count++;
  998.                 }
  999.                
  1000.                 ActivatedClientTypeEntry[] entries = new ActivatedClientTypeEntry[count];
  1001.                
  1002.                 int co = 0;
  1003.                 foreach (DictionaryEntry dictEntry in _remoteTypeInfo) {
  1004.                     ActivatedClientTypeEntry entry = dictEntry.Value as ActivatedClientTypeEntry;
  1005.                    
  1006.                     if (entry != null) {
  1007.                         // retrieve application url
  1008.                         string appUrl = null;
  1009.                         RemoteAppEntry remApp = entry.GetRemoteAppEntry();
  1010.                         if (remApp != null)
  1011.                             appUrl = remApp.GetAppURI();
  1012.                        
  1013.                         ActivatedClientTypeEntry wkcte = new ActivatedClientTypeEntry(entry.TypeName, entry.AssemblyName, appUrl);
  1014.                        
  1015.                         // Fetch the context attributes
  1016.                         wkcte.ContextAttributes = entry.ContextAttributes;
  1017.                        
  1018.                         entries[co++] = wkcte;
  1019.                     }
  1020.                    
  1021.                 }
  1022.                
  1023.                 return entries;
  1024.             }
  1025.             // GetRegisteredActivatedClientTypes
  1026.            
  1027.             internal WellKnownClientTypeEntry[] GetRegisteredWellKnownClientTypes()
  1028.             {
  1029.                 // count number of well known client types
  1030.                 int count = 0;
  1031.                 foreach (DictionaryEntry dictEntry in _remoteTypeInfo) {
  1032.                     WellKnownClientTypeEntry entry = dictEntry.Value as WellKnownClientTypeEntry;
  1033.                     if (entry != null)
  1034.                         count++;
  1035.                 }
  1036.                
  1037.                 WellKnownClientTypeEntry[] entries = new WellKnownClientTypeEntry[count];
  1038.                
  1039.                 int co = 0;
  1040.                 foreach (DictionaryEntry dictEntry in _remoteTypeInfo) {
  1041.                     WellKnownClientTypeEntry entry = dictEntry.Value as WellKnownClientTypeEntry;
  1042.                    
  1043.                     if (entry != null) {
  1044.                         WellKnownClientTypeEntry wkcte = new WellKnownClientTypeEntry(entry.TypeName, entry.AssemblyName, entry.ObjectUrl);
  1045.                        
  1046.                         // see if there is an associated app
  1047.                         RemoteAppEntry remApp = entry.GetRemoteAppEntry();
  1048.                         if (remApp != null)
  1049.                             wkcte.ApplicationUrl = remApp.GetAppURI();
  1050.                        
  1051.                         entries[co++] = wkcte;
  1052.                     }
  1053.                    
  1054.                 }
  1055.                
  1056.                 return entries;
  1057.             }
  1058.             // GetRegisteredWellKnownClientTypes
  1059.            
  1060.             //
  1061.             // end of helper functions to retrieve registered types
  1062.             //
  1063.            
  1064.             internal void AddActivatedType(string typeName, string assemblyName, IContextAttribute[] contextAttributes)
  1065.             {
  1066.                 if (typeName == null)
  1067.                     throw new ArgumentNullException("typeName");
  1068.                 if (assemblyName == null)
  1069.                     throw new ArgumentNullException("assemblyName");
  1070.                
  1071.                 if (CheckForRedirectedClientType(typeName, assemblyName)) {
  1072.                     throw new RemotingException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_Config_CantUseRedirectedTypeForWellKnownService"), typeName, assemblyName));
  1073.                 }
  1074.                
  1075.                 ActivatedServiceTypeEntry aste = new ActivatedServiceTypeEntry(typeName, assemblyName);
  1076.                 aste.ContextAttributes = contextAttributes;
  1077.                
  1078.                 // The assembly name is stored in lowercase to let it be case-insensitive.
  1079.                 string key = EncodeTypeAndAssemblyNames(typeName, assemblyName);
  1080.                 _exportableClasses.Add(key, aste);
  1081.             }
  1082.             // AddActivatedType
  1083.            
  1084.             // determines if either a wellknown or activated service type entry
  1085.             // is associated with the given type name and assembly name
  1086.             private bool CheckForServiceEntryWithType(string typeName, string asmName)
  1087.             {
  1088.                 return CheckForWellKnownServiceEntryWithType(typeName, asmName) || ActivationAllowed(typeName, asmName);
  1089.             }
  1090.             // CheckForServiceEntryWithType
  1091.             private bool CheckForWellKnownServiceEntryWithType(string typeName, string asmName)
  1092.             {
  1093.                 foreach (DictionaryEntry entry in _wellKnownExportInfo) {
  1094.                     WellKnownServiceTypeEntry svc = (WellKnownServiceTypeEntry)entry.Value;
  1095.                     if (typeName == svc.TypeName) {
  1096.                         bool match = false;
  1097.                        
  1098.                         // need to ignore version while checking
  1099.                         if (asmName == svc.AssemblyName)
  1100.                             match = true;
  1101.                         else {
  1102.                             // only well known service entry can have version info
  1103.                             if (String.Compare(svc.AssemblyName, 0, asmName, 0, asmName.Length, StringComparison.OrdinalIgnoreCase) == 0) {
  1104.                                 // if asmName != svc.AssemblyName and svc.AssemblyName
  1105.                                 // starts with asmName we know that svc.AssemblyName is
  1106.                                 // longer. If the next character is a comma, then the
  1107.                                 // assembly names match except for version numbers
  1108.                                 // which is ok.
  1109.                                 if (svc.AssemblyName[asmName.Length] == ',')
  1110.                                     match = true;
  1111.                             }
  1112.                         }
  1113.                        
  1114.                         // We were trying to redirect
  1115.                         if (match)
  1116.                             return true;
  1117.                     }
  1118.                 }
  1119.                
  1120.                 return false;
  1121.             }
  1122.             // CheckForWellKnownServiceEntryOfType
  1123.            
  1124.             // returns true if activation for the type has been redirected.
  1125.             private bool CheckForRedirectedClientType(string typeName, string asmName)
  1126.             {
  1127.                 // if asmName has version information, remove it.
  1128.                 int index = asmName.IndexOf(",");
  1129.                 if (index != -1)
  1130.                     asmName = asmName.Substring(0, index);
  1131.                
  1132.                 return (QueryRemoteActivate(typeName, asmName) != null) || (QueryConnect(typeName, asmName) != null);
  1133.             }
  1134.             // CheckForRedirectedClientType
  1135.            
  1136.             internal void AddActivatedClientType(ActivatedClientTypeEntry entry)
  1137.             {
  1138.                 if (CheckForRedirectedClientType(entry.TypeName, entry.AssemblyName)) {
  1139.                     throw new RemotingException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_Config_TypeAlreadyRedirected"), entry.TypeName, entry.AssemblyName));
  1140.                 }
  1141.                
  1142.                 if (CheckForServiceEntryWithType(entry.TypeName, entry.AssemblyName)) {
  1143.                     throw new RemotingException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_Config_CantRedirectActivationOfWellKnownService"), entry.TypeName, entry.AssemblyName));
  1144.                 }
  1145.                
  1146.                 string appUrl = entry.ApplicationUrl;
  1147.                 RemoteAppEntry appEntry = (RemoteAppEntry)_remoteAppInfo[appUrl];
  1148.                 if (appEntry == null) {
  1149.                     appEntry = new RemoteAppEntry(appUrl, appUrl);
  1150.                     _remoteAppInfo.Add(appUrl, appEntry);
  1151.                 }
  1152.                
  1153.                 if (appEntry != null) {
  1154.                     entry.CacheRemoteAppEntry(appEntry);
  1155.                 }
  1156.                
  1157.                 string index = EncodeTypeAndAssemblyNames(entry.TypeName, entry.AssemblyName);
  1158.                 _remoteTypeInfo.Add(index, entry);
  1159.             }
  1160.             // AddActivatedClientType
  1161.            
  1162.             internal void AddWellKnownClientType(WellKnownClientTypeEntry entry)
  1163.             {
  1164.                 if (CheckForRedirectedClientType(entry.TypeName, entry.AssemblyName)) {
  1165.                     throw new RemotingException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_Config_TypeAlreadyRedirected"), entry.TypeName, entry.AssemblyName));
  1166.                 }
  1167.                
  1168.                 if (CheckForServiceEntryWithType(entry.TypeName, entry.AssemblyName)) {
  1169.                     throw new RemotingException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_Config_CantRedirectActivationOfWellKnownService"), entry.TypeName, entry.AssemblyName));
  1170.                 }
  1171.                
  1172.                
  1173.                 string appUrl = entry.ApplicationUrl;
  1174.                
  1175.                 RemoteAppEntry appEntry = null;
  1176.                 if (appUrl != null) {
  1177.                     appEntry = (RemoteAppEntry)_remoteAppInfo[appUrl];
  1178.                     if (appEntry == null) {
  1179.                         appEntry = new RemoteAppEntry(appUrl, appUrl);
  1180.                         _remoteAppInfo.Add(appUrl, appEntry);
  1181.                     }
  1182.                 }
  1183.                
  1184.                 if (appEntry != null)
  1185.                     entry.CacheRemoteAppEntry(appEntry);
  1186.                
  1187.                 string index = EncodeTypeAndAssemblyNames(entry.TypeName, entry.AssemblyName);
  1188.                 _remoteTypeInfo.Add(index, entry);
  1189.             }
  1190.             // AddWellKnownClientType
  1191.            
  1192.            
  1193.             // This is to add programmatically registered well known objects
  1194.             // so that we keep all this data in one place
  1195.             internal void AddWellKnownEntry(WellKnownServiceTypeEntry entry)
  1196.             {
  1197.                 AddWellKnownEntry(entry, true);
  1198.             }
  1199.            
  1200.             internal void AddWellKnownEntry(WellKnownServiceTypeEntry entry, bool fReplace)
  1201.             {
  1202.                 if (CheckForRedirectedClientType(entry.TypeName, entry.AssemblyName)) {
  1203.                     throw new RemotingException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_Config_CantUseRedirectedTypeForWellKnownService"), entry.TypeName, entry.AssemblyName));
  1204.                 }
  1205.                
  1206.                 string key = entry.ObjectUri.ToLower(CultureInfo.InvariantCulture);
  1207.                
  1208.                 if (fReplace) {
  1209.                     // Registering a well known object twice replaces the old one, so
  1210.                     // we null out the old entry in the identity table after adding
  1211.                     // this one. The identity will be recreated the next time someone
  1212.                     // asks for this object.
  1213.                     _wellKnownExportInfo[key] = entry;
  1214.                    
  1215.                     IdentityHolder.RemoveIdentity(entry.ObjectUri);
  1216.                 }
  1217.                 else {
  1218.                     _wellKnownExportInfo.Add(key, entry);
  1219.                 }
  1220.                
  1221.             }
  1222.            
  1223.             //This API exposes a way to get server type information wiihout booting the object
  1224.             internal Type GetServerTypeForUri(string URI)
  1225.             {
  1226.                 BCLDebug.Assert(null != URI, "null != URI");
  1227.                
  1228.                 Type serverType = null;
  1229.                 string uriLower = URI.ToLower(CultureInfo.InvariantCulture);
  1230.                
  1231.                 WellKnownServiceTypeEntry entry = (WellKnownServiceTypeEntry)_wellKnownExportInfo[uriLower];
  1232.                
  1233.                 if (entry != null) {
  1234.                     serverType = LoadType(entry.TypeName, entry.AssemblyName);
  1235.                 }
  1236.                
  1237.                 return serverType;
  1238.             }
  1239.            
  1240.             internal ServerIdentity StartupWellKnownObject(string URI)
  1241.             {
  1242.                 BCLDebug.Assert(null != URI, "null != URI");
  1243.                
  1244.                 string uriLower = URI.ToLower(CultureInfo.InvariantCulture);
  1245.                 ServerIdentity ident = null;
  1246.                
  1247.                 WellKnownServiceTypeEntry entry = (WellKnownServiceTypeEntry)_wellKnownExportInfo[uriLower];
  1248.                 if (entry != null) {
  1249.                     ident = StartupWellKnownObject(entry.AssemblyName, entry.TypeName, entry.ObjectUri, entry.Mode);
  1250.                    
  1251.                 }
  1252.                
  1253.                 return ident;
  1254.             }
  1255.            
  1256.             internal ServerIdentity StartupWellKnownObject(string asmName, string svrTypeName, string URI, WellKnownObjectMode mode)
  1257.             {
  1258.                 return StartupWellKnownObject(asmName, svrTypeName, URI, mode, false);
  1259.             }
  1260.            
  1261.             internal ServerIdentity StartupWellKnownObject(string asmName, string svrTypeName, string URI, WellKnownObjectMode mode, bool fReplace)
  1262.             {
  1263.                 lock (s_wkoStartLock) {
  1264.                     MarshalByRefObject obj = null;
  1265.                     ServerIdentity srvID = null;
  1266.                    
  1267.                     // attempt to load the type
  1268.                     Type serverType = LoadType(svrTypeName, asmName);
  1269.                    
  1270.                     // make sure the well known object derives from MarshalByRefObject
  1271.                     if (!serverType.IsMarshalByRef) {
  1272.                         throw new RemotingException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_WellKnown_MustBeMBR"), svrTypeName));
  1273.                     }
  1274.                    
  1275.                     // make sure that no one beat us to creating
  1276.                     // the well known object
  1277.                     srvID = (ServerIdentity)IdentityHolder.ResolveIdentity(URI);
  1278.                     if ((srvID != null) && srvID.IsRemoteDisconnected()) {
  1279.                         IdentityHolder.RemoveIdentity(URI);
  1280.                         srvID = null;
  1281.                     }
  1282.                    
  1283.                     if (srvID == null) {
  1284.                         //WellKnown type instances need to be created under full trust
  1285.                         //since the permission set might have been restricted by the channel
  1286.                         //pipeline.
  1287.                         //This assert is protected by Infrastructure link demands.
  1288.                         s_fullTrust.Assert();
  1289.                         try {
  1290.                             obj = (MarshalByRefObject)Activator.CreateInstance(serverType, true);
  1291.                            
  1292.                             if (RemotingServices.IsClientProxy(obj)) {
  1293.                                 // The wellknown type is remoted so we must wrap the proxy
  1294.                                 // with a local object.
  1295.                                
  1296.                                 // The redirection proxy masquerades as an object of the appropriate
  1297.                                 // type, and forwards incoming messages to the actual proxy.
  1298.                                 RedirectionProxy redirectedProxy = new RedirectionProxy(obj, serverType);
  1299.                                 redirectedProxy.ObjectMode = mode;
  1300.                                 RemotingServices.MarshalInternal(redirectedProxy, URI, serverType);
  1301.                                
  1302.                                 srvID = (ServerIdentity)IdentityHolder.ResolveIdentity(URI);
  1303.                                 BCLDebug.Assert(null != srvID, "null != srvID");
  1304.                                
  1305.                                 // The redirection proxy handles SingleCall versus Singleton,
  1306.                                 // so we always set its mode to Singleton.
  1307.                                 srvID.SetSingletonObjectMode();
  1308.                             }
  1309.                             else if (serverType.IsCOMObject && (mode == WellKnownObjectMode.Singleton)) {
  1310.                                 // Singleton COM objects are wrapped, so that they will be
  1311.                                 // recreated when an RPC server not available is thrown
  1312.                                 // if dllhost.exe is killed.
  1313.                                 ComRedirectionProxy comRedirectedProxy = new ComRedirectionProxy(obj, serverType);
  1314.                                 RemotingServices.MarshalInternal(comRedirectedProxy, URI, serverType);
  1315.                                
  1316.                                 srvID = (ServerIdentity)IdentityHolder.ResolveIdentity(URI);
  1317.                                 BCLDebug.Assert(null != srvID, "null != srvID");
  1318.                                
  1319.                                 // Only singleton COM objects are redirected this way.
  1320.                                 srvID.SetSingletonObjectMode();
  1321.                             }
  1322.                             else {
  1323.                                 // make sure the object didn't Marshal itself.
  1324.                                 string tempUri = RemotingServices.GetObjectUri(obj);
  1325.                                 if (tempUri != null) {
  1326.                                     throw new RemotingException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_WellKnown_CtorCantMarshal"), URI));
  1327.                                 }
  1328.                                
  1329.                                 RemotingServices.MarshalInternal(obj, URI, serverType);
  1330.                                
  1331.                                 srvID = (ServerIdentity)IdentityHolder.ResolveIdentity(URI);
  1332.                                 BCLDebug.Assert(null != srvID, "null != srvID");
  1333.                                
  1334.                                 if (mode == WellKnownObjectMode.SingleCall) {
  1335.                                     // We need to set a special flag in the serverId
  1336.                                     // so that every dispatch to this type creates
  1337.                                     // a new instance of the server object
  1338.                                     srvID.SetSingleCallObjectMode();
  1339.                                 }
  1340.                                 else {
  1341.                                     srvID.SetSingletonObjectMode();
  1342.                                 }
  1343.                             }
  1344.                         }
  1345.                         catch {
  1346.                             throw;
  1347.                         }
  1348.                         finally {
  1349.                             SecurityPermission.RevertAssert();
  1350.                         }
  1351.                     }
  1352.                    
  1353.                     BCLDebug.Assert(null != srvID, "null != srvID");
  1354.                     return srvID;
  1355.                 }
  1356.             }
  1357.             // StartupWellKnownObject
  1358.            
  1359.             static internal Type LoadType(string typeName, string assemblyName)
  1360.             {
  1361.                 Assembly asm = null;
  1362.                 // All the LoadType callers have been protected by
  1363.                 // Infrastructure LinkDemand, it is safe to assert
  1364.                 // this permission.
  1365.                 // Assembly.Load demands FileIO when the target
  1366.                 // assembly is the same as the executable running.
  1367.                 new FileIOPermission(PermissionState.Unrestricted).Assert();
  1368.                 try {
  1369.                     asm = Assembly.Load(assemblyName);
  1370.                 }
  1371.                 finally {
  1372.                     CodeAccessPermission.RevertAssert();
  1373.                 }
  1374.                
  1375.                 if (asm == null) {
  1376.                     throw new RemotingException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_AssemblyLoadFailed"), assemblyName));
  1377.                 }
  1378.                
  1379.                 Type type = asm.GetType(typeName, false, false);
  1380.                 if (type == null) {
  1381.                     throw new RemotingException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_BadType"), typeName + ", " + assemblyName));
  1382.                 }
  1383.                
  1384.                 return type;
  1385.             }
  1386.             // LoadType
  1387.            
  1388.            
  1389.         }
  1390.         // class RemotingConfigInfo
  1391.     }
  1392.     // class RemotingConfigHandler
  1393.    
  1394.    
  1395.     internal class DelayLoadClientChannelEntry
  1396.     {
  1397.         private RemotingXmlConfigFileData.ChannelEntry _entry;
  1398.         private IChannelSender _channel;
  1399.         private bool _bRegistered;
  1400.         private bool _ensureSecurity;
  1401.        
  1402.         internal DelayLoadClientChannelEntry(RemotingXmlConfigFileData.ChannelEntry entry, bool ensureSecurity)
  1403.         {
  1404.             _entry = entry;
  1405.             _channel = null;
  1406.             _bRegistered = false;
  1407.             _ensureSecurity = ensureSecurity;
  1408.         }
  1409.        
  1410.         internal IChannelSender Channel {
  1411.             get {
  1412.                 // If this method returns null, that means the channel has already been registered.
  1413.                
  1414.                 // NOTE: Access to delay load client entries is synchronized at a higher level.
  1415.                 if (_channel == null) {
  1416.                     if (!_bRegistered) {
  1417.                         _channel = (IChannelSender)RemotingConfigHandler.CreateChannelFromConfigEntry(_entry);
  1418.                         _entry = null;
  1419.                     }
  1420.                 }
  1421.                
  1422.                 return _channel;
  1423.             }
  1424.         }
  1425.         // get
  1426.         // Channel
  1427.         internal void RegisterChannel()
  1428.         {
  1429.             BCLDebug.Assert(_channel != null, "channel shouldn't be null");
  1430.            
  1431.             // NOTE: Access to delay load client entries is synchronized at a higher level.
  1432.             ChannelServices.RegisterChannel(_channel, _ensureSecurity);
  1433.             _bRegistered = true;
  1434.             _channel = null;
  1435.         }
  1436.         // RegisterChannel
  1437.     }
  1438.     // class DelayLoadChannelEntry
  1439.    
  1440.    
  1441. }
  1442. // namespace

Developer Fusion