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