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