We need you! We're working hard on the next version of Developer Fusion - Let us know what you think we should be up to!

The Labs \ Source Viewer \ SSCLI \ System.Runtime.Remoting.Activation \ ActivationListener

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. /*============================================================
  16. **
  17. **  File:    ActivationServices.cs
  18. **
  19. **  Author(s): 
  20. **
  21. **  Purpose:         
  22. **
  23. **
  24. ===========================================================*/
  25. namespace System.Runtime.Remoting.Activation
  26. {
  27.    
  28.     using System;
  29.     using System.Security;
  30.     using System.Threading;
  31.     using System.Runtime.InteropServices;
  32.     using System.Runtime.Remoting;
  33.     using System.Runtime.Remoting.Contexts;
  34.     using System.Runtime.Remoting.Proxies;
  35.     using System.Runtime.Remoting.Messaging;
  36.     using System.Runtime.Remoting.Metadata;
  37.     using System.Collections;
  38.     using System.Reflection;
  39.     using System.IO;
  40.     using System.Runtime.Serialization;
  41.     using System.Security.Permissions;
  42.     using System.Globalization;
  43.     using System.Runtime.CompilerServices;
  44.    
  45.     // Implements various activation services
  46.     static internal class ActivationServices
  47.     {
  48.        
  49.         private static IActivator activator = null;
  50.        
  51.         private static Hashtable _proxyTable = new Hashtable();
  52.         private static Type proxyAttributeType = typeof(System.Runtime.Remoting.Proxies.ProxyAttribute);
  53.         private static ProxyAttribute _proxyAttribute = new ProxyAttribute();
  54.         [ThreadStaticAttribute()]
  55.         static internal ActivationAttributeStack _attributeStack;
  56.        
  57.         internal const string ActivationServiceURI = "RemoteActivationService.rem";
  58.        
  59.         internal const string RemoteActivateKey = "Remote";
  60.         internal const string PermissionKey = "Permission";
  61.         internal const string ConnectKey = "Connect";
  62.        
  63.        
  64.         //1 private static LocalActivator localActivator = null;
  65.        
  66.         // ActivationListener is the object that listens to incoming
  67.         // activation requests. It delegates the incoming request to
  68.         // the local activator.
  69.         //2 private static ActivationListener ActivationListener = null;
  70.        
  71.         //3 private static Object staticSyncObject = new Object();
  72.         //4 private static bool bInitializing = false;
  73.        
  74.         // This gets called upon the first attempt to activate
  75.         // anything that is ContextBound or MarshalByRef
  76.         private static void Startup()
  77.         {
  78.             DomainSpecificRemotingData remData = Thread.GetDomain().RemotingData;
  79.            
  80.             // wait on the lock if a)activation has not been initialized yet
  81.             // or b) activation is being initialized by another thread!
  82.             if ((!remData.ActivationInitialized) || remData.InitializingActivation) {
  83.                 object configLock = remData.ConfigLock;
  84.                 bool fLocked = false;
  85.                 RuntimeHelpers.PrepareConstrainedRegions();
  86.                 try {
  87.                     Monitor.ReliableEnter(configLock, ref fLocked);
  88.                     remData.InitializingActivation = true;
  89.                     // Ensure that some other thread did not complete
  90.                     // the work while we were waiting on the lock.
  91.                     if (!remData.ActivationInitialized) {
  92.                         // Startup the activation service
  93.                         BCLDebug.Trace("REMOTE", "Starting up activation service ", Thread.CurrentContext);
  94.                        
  95.                         //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  96.                         // NOTE: This should be the first step in Startup!
  97.                         // Otherwise activation will recurse, when we try
  98.                         // to create the ActivationListener (which is MarshalByRef)
  99.                         //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  100.                         remData.LocalActivator = new LocalActivator();
  101.                        
  102.                         // Add the Lifetime service property to the appdomain.
  103.                         // For now we are assuming that this is the only property
  104.                         // If there are more properties, then an existing array
  105.                         // will need to be expanded to add this property
  106.                        
  107.                         // This is activated in RemotingServices.DomainSpecificRemotingData()
  108.                         // IContextProperty[] contextProperties = new IContextProperty[1];
  109.                         // contextProperties[0] = new System.Runtime.Remoting.LeaseLifeTimeServiceProperty();
  110.                         // Thread.GetDomain().RemotingData.AppDomainContextProperties = contextProperties;
  111.                        
  112.                         remData.ActivationListener = new ActivationListener();
  113.                         remData.ActivationInitialized = true;
  114.                        
  115.                     }
  116.                    
  117.                     remData.InitializingActivation = false;
  118.                 }
  119.                 //lock (remData)
  120.                 finally {
  121.                     if (fLocked) {
  122.                         Monitor.Exit(configLock);
  123.                     }
  124.                 }
  125.             }
  126.         }
  127.        
  128.         private static void InitActivationServices()
  129.         {
  130.             // If activation services has not been loaded do it now and create
  131.             // the instace that will service the activation requests.
  132.             if (null == activator) {
  133.                 activator = GetActivator();
  134.                 if (null == activator) {
  135.                     Message.DebugOut("Fatal Error... Could not create activator\n");
  136.                     throw new RemotingException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_BadInternalState_ActivationFailure")));
  137.                 }
  138.             }
  139.         }
  140.        
  141.         // Determine whether the current context is ok for the activation.
  142.         private static MarshalByRefObject IsCurrentContextOK(Type serverType, object[] props, bool bNewObj)
  143.         {
  144.             BCLDebug.Assert(!serverType.IsInterface, "!serverType.IsInterface");
  145.            
  146.             MarshalByRefObject retObj = null;
  147.            
  148.             // Initialize activation services if needed.
  149.             // (we temporary null out the activation attributes in case
  150.             // InitActivationServices creates an MBR).
  151.             InitActivationServices();
  152.            
  153.             // Obtain the method info which will create an instance
  154.             // of type RealProxy
  155.             ProxyAttribute pa = GetProxyAttribute(serverType);
  156.             BCLDebug.Assert(null != pa, "null != pa");
  157.            
  158.             if (Object.ReferenceEquals(pa, DefaultProxyAttribute))
  159.                 retObj = pa.CreateInstanceInternal(serverType);
  160.             else {
  161.                 retObj = pa.CreateInstance(serverType);
  162.                 // We called a custom proxy attribute .. make sure it is
  163.                 // returning a server of the correct type.
  164.                 if (retObj != null) {
  165.                     // If a transparent proxy is returned we are fine.
  166.                     // If not then the object's type MUST be compatible
  167.                     // with the type we were requested to activate!
  168.                     if (!RemotingServices.IsTransparentProxy(retObj) && !serverType.IsAssignableFrom(retObj.GetType())) {
  169.                         throw new RemotingException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_Activation_BadObject"), serverType));
  170.                     }
  171.                 }
  172.             }
  173.             BCLDebug.Assert(null != retObj, "null != retObj");
  174.             return retObj;
  175.         }
  176.        
  177.        
  178.         // For types with no proxy attribute, we take the default route of
  179.         // querying attributes if the current context is suitable for
  180.         // activation.
  181.         private static bool IsCurrentContextOK(Type serverType, object[] props, ref ConstructorCallMessage ctorCallMsg)
  182.         {
  183.             //Get callSite attributes
  184.             object[] callSiteAttr = PeekActivationAttributes(serverType);
  185.            
  186.             // Clear from the attribute stack
  187.             if (callSiteAttr != null) {
  188.                 PopActivationAttributes(serverType);
  189.             }
  190.            
  191.             object[] womAttr = new object[1];
  192.             womAttr[0] = GetGlobalAttribute();
  193.            
  194.             // Get the type context attributes
  195.             object[] typeAttr = GetContextAttributesForType(serverType);
  196.            
  197.             // Get the client context (current context)
  198.             Context cliCtx = Thread.CurrentContext;
  199.            
  200.             // Create a ctorCallMsg with the reqd info
  201.             ctorCallMsg = new ConstructorCallMessage(callSiteAttr, womAttr, typeAttr, serverType);
  202.            
  203.             // This is the activator that handles activation in *all* cases
  204.             // Based on whether what the activation attributes do.... other
  205.             // activators may get chained ahead of this one and may take
  206.             // over the activation process... (possibly) delegating to this
  207.             // only in the last stage.
  208.             // Note: currently, this does not get used in the same context (MBR)
  209.             // scenarios ... because of the 2-step activation model of JIT.
  210.             ctorCallMsg.Activator = new ConstructionLevelActivator();
  211.            
  212.            
  213.             // Ask all attributes if they are happy with the current context
  214.             // NOTE: if someone says no, we do not ask the rest of the attributes
  215.             // This is why, womAttr (which is the global activation service
  216.             // attribute) *must* be the first one we query.
  217.             bool bCtxOK = QueryAttributesIfContextOK(cliCtx, ctorCallMsg, womAttr);
  218.             if (bCtxOK == true) {
  219.                 bCtxOK = QueryAttributesIfContextOK(cliCtx, ctorCallMsg, callSiteAttr);
  220.                 if (bCtxOK == true) {
  221.                     bCtxOK = QueryAttributesIfContextOK(cliCtx, ctorCallMsg, typeAttr);
  222.                 }
  223.             }
  224.            
  225.             return bCtxOK;
  226.         }
  227.        
  228.         private static void CheckForInfrastructurePermission(Assembly asm)
  229.         {
  230.             // Make a security check to ensure that the context attribute
  231.             // is from a trusted assembly!
  232.             if (asm != RemotingServices.s_MscorlibAssembly) {
  233.                 CodeAccessSecurityEngine.CheckAssembly(asm, RemotingServices.s_RemotingInfrastructurePermission);
  234.             }
  235.         }
  236.        
  237.         private static bool QueryAttributesIfContextOK(Context ctx, IConstructionCallMessage ctorMsg, object[] attributes)
  238.         {
  239.             bool bCtxOK = true;
  240.             if (attributes != null) {
  241.                 for (int i = 0; i < attributes.Length; i++) {
  242.                     // All the attributes, including callsite attributes should
  243.                     // expose IContextAttribute. If not, then we throw an
  244.                     // exception.
  245.                     IContextAttribute attr = attributes[i] as IContextAttribute;
  246.                     if (null != attr) {
  247.                         Assembly asm = attr.GetType().Assembly;
  248.                         // Make a security check to ensure that the context attribute
  249.                         // is from a trusted assembly!
  250.                         CheckForInfrastructurePermission(asm);
  251.                        
  252.                         bCtxOK = attr.IsContextOK(ctx, ctorMsg);
  253.                         if (bCtxOK == false) {
  254.                             break;
  255.                         }
  256.                     }
  257.                     else {
  258.                         throw new RemotingException(Environment.GetResourceString("Remoting_Activation_BadAttribute"));
  259.                     }
  260.                 }
  261.             }
  262.             return bCtxOK;
  263.         }
  264.        
  265.         static internal void GetPropertiesFromAttributes(IConstructionCallMessage ctorMsg, object[] attributes)
  266.         {
  267.             if (attributes != null) {
  268.                 for (int i = 0; i < attributes.Length; i++) {
  269.                     // All the attributes, including callsite attributes should
  270.                     // expose IContextAttribute. If not, then we throw an
  271.                     // exception.
  272.                     IContextAttribute attr = attributes[i] as IContextAttribute;
  273.                     if (null != attr) {
  274.                         Assembly asm = attr.GetType().Assembly;
  275.                         // Make a security check to ensure that the context attribute
  276.                         // is from a trusted assembly!
  277.                         CheckForInfrastructurePermission(asm);
  278.                        
  279.                         // We ask each attribute to contribute its properties.
  280.                         // The attributes can examine the current list of properties
  281.                         // from the ctorCallMsg and decide which properties to add.
  282.                        
  283.                         // They can also tweak the Activator chain during this process
  284.                         attr.GetPropertiesForNewContext(ctorMsg);
  285.                     }
  286.                     else {
  287.                         throw new RemotingException(Environment.GetResourceString("Remoting_Activation_BadAttribute"));
  288.                     }
  289.                 }
  290.             }
  291.         }
  292.        
  293.         // Return the default implementation of the proxy attribute
  294.         static internal ProxyAttribute DefaultProxyAttribute {
  295.             get { return _proxyAttribute; }
  296.         }
  297.        
  298.         // Iterate over the custom attributes of the class and see if it
  299.         // defines a ProxyAttribute. If one is not defined then return
  300.         // the default proxy attribute defined by us.
  301.         static internal ProxyAttribute GetProxyAttribute(Type serverType)
  302.         {
  303.            
  304.             BCLDebug.Assert(serverType.IsMarshalByRef, "type should be at least marshal-by-ref");
  305.            
  306.             if (!serverType.HasProxyAttribute)
  307.                 return DefaultProxyAttribute;
  308.            
  309.             // Type has a non-default proxy attribute ... see if we have
  310.             // it cached?
  311.             ProxyAttribute pa = _proxyTable[serverType] as ProxyAttribute;
  312.            
  313.             if (pa == null) {
  314.                 object[] ca = Attribute.GetCustomAttributes(serverType, proxyAttributeType, true);
  315.                 if ((null != ca) && (0 != ca.Length)) {
  316.                     if (!serverType.IsContextful) {
  317.                         throw new RemotingException(Environment.GetResourceString("Remoting_Activation_MBR_ProxyAttribute"));
  318.                     }
  319.                     pa = ca[0] as ProxyAttribute;
  320.                 }
  321.                 BCLDebug.Assert(pa != null, "expect proxy attribute");
  322.                
  323.                 if (!_proxyTable.Contains(serverType)) {
  324.                     lock (_proxyTable) {
  325.                         if (!_proxyTable.Contains(serverType)) {
  326.                             // Create a new entry
  327.                             _proxyTable.Add(serverType, pa);
  328.                         }
  329.                     }
  330.                 }
  331.             }
  332.            
  333.             return pa;
  334.         }
  335.        
  336.         // Creates either an uninitialized object or a proxy depending on
  337.         // whether the current context is OK or not.
  338.         static internal MarshalByRefObject CreateInstance(Type serverType)
  339.         {
  340.             // Use our activation implementation
  341.             MarshalByRefObject retObj = null;
  342.             ConstructorCallMessage ctorCallMsg = null;
  343.             bool bCtxOK = IsCurrentContextOK(serverType, null, ref ctorCallMsg);
  344.             if (bCtxOK && !serverType.IsContextful) {
  345.                 // Marshal by ref case
  346.                 Message.DebugOut("Allocating blank marshal-by-ref object");
  347.                 // We create an uninitialized instance of the actual type and
  348.                 // let the regular jit-activation execute the constructor on it.
  349.                 retObj = RemotingServices.AllocateUninitializedObject(serverType);
  350.             }
  351.             else {
  352.                 // (context not OK) || (serverType is Contextful)
  353.                 // We always return a proxy and the jit-activation's attempt
  354.                 // to execute the constructor gets intercepted by the TP stub
  355.                 // and routed to RemotingServices.Activate() below.
  356.                
  357.                 // if context *is* OK
  358.                 // this is a contextBound type being activated for which
  359.                 // we always create a proxy (proxies-everywhere!)
  360.                
  361.                 // if context *is not* OK
  362.                 // this could be a MarshalByRef or ContextBound type
  363.                 // being activated outside this appDomain
  364.                 // OR
  365.                 // this could be a ContextBound type being activated cross-ctx
  366.                
  367.                 RemotingProxy rp;
  368.                 // See if the object-type is configured for Connect (with a URL)
  369.                 retObj = (MarshalByRefObject)ConnectIfNecessary(ctorCallMsg);
  370.                 if (retObj == null) {
  371.                     // not configured for connect, take the usual route of
  372.                     // creating a proxy
  373.                     Message.DebugOut("Creating remoting proxy for " + serverType.FullName + " in context " + Thread.CurrentContext);
  374.                    
  375.                     rp = new RemotingProxy(serverType);
  376.                    
  377.                     Message.DebugOut("Created remoting proxy\n");
  378.                     retObj = (MarshalByRefObject)rp.GetTransparentProxy();
  379.                 }
  380.                 else {
  381.                     Message.DebugOut("NewObj did a Connect!");
  382.                     rp = (RemotingProxy)RemotingServices.GetRealProxy(retObj);
  383.                 }
  384.                
  385.                 // Store the constructor call message in the proxy
  386.                 rp.ConstructorMessage = ctorCallMsg;
  387.                
  388.                 if (!bCtxOK) {
  389.                    
  390.                     // Chain in the context level activator now
  391.                     ContextLevelActivator activator = new ContextLevelActivator();
  392.                     activator.NextActivator = ctorCallMsg.Activator;
  393.                     ctorCallMsg.Activator = activator;
  394.                 }
  395.                 else {
  396.                     // Set the flag to indicate that the activation
  397.                     // will not be leaving the client context .. in this case
  398.                     // the default construction level activator is enough
  399.                     // to complete the activation process.
  400.                     ctorCallMsg.ActivateInContext = true;
  401.                 }
  402.             }
  403.            
  404.             return retObj;
  405.         }
  406.        
  407.         //
  408.         // NOTE: This is an internal method used by RemotingProxy to do Activation
  409.         //
  410.         // Starts off the activation chain by sending the constructor call message to
  411.         // the activator or the client context sink chain. On return, a constructor
  412.         // return message is made and the out parameters are propagated.
  413.         //
  414.         static internal IConstructionReturnMessage Activate(RemotingProxy remProxy, IConstructionCallMessage ctorMsg)
  415.         {
  416.             IConstructionReturnMessage ctorRetMsg = null;
  417.            
  418.             if (((ConstructorCallMessage)ctorMsg).ActivateInContext) {
  419.                 // The current context was approved for activation
  420.                 BCLDebug.Assert(ctorMsg.Activator.Level == ActivatorLevel.Construction, "activator level must ActivatorLevel.Construction!");
  421.                
  422.                 // This has to be a ContextBound type (proxies-everywhere)
  423.                 BCLDebug.Assert(ctorMsg.ActivationType.IsContextful, "Inconsistent state during activation");
  424.                
  425.                 // Ask the activator in the message to take over
  426.                 ctorRetMsg = ctorMsg.Activator.Activate(ctorMsg);
  427.                
  428.                 if (ctorRetMsg.Exception != null) {
  429.                     throw ctorRetMsg.Exception;
  430.                 }
  431.             }
  432.             else {
  433.                 // Client context was not approved for activation ...
  434.                 BCLDebug.Assert(ctorMsg.Activator.Level >= ActivatorLevel.Context, "activator level must be at least x-context!");
  435.                
  436.                 // Check with ActivationServices if we did a "Connect" with
  437.                 // a remote server during IsContextOK
  438.                 BCLDebug.Assert(ActivationServices.CheckIfConnected(remProxy, ctorMsg) == null, "We shouldn't come through this path on a Connect.");
  439.                
  440.                 // Client context was not approved for activation ...
  441.                 // This is the more elaborate (real) activation case i.e.
  442.                 // we have to go at least out of the client context to
  443.                 // finish the work.
  444.                
  445.                 // Prepare for the handoff to Activation Service
  446.                
  447.                 // Ask various attributes to contribute properties
  448.                 // The attributes may chain in other activators into
  449.                 // the activation chain (to hijack/participate in
  450.                 // the activation process).
  451.                 ActivationServices.GetPropertiesFromAttributes((IConstructionCallMessage)ctorMsg, ctorMsg.CallSiteActivationAttributes);
  452.                
  453.                 ActivationServices.GetPropertiesFromAttributes(ctorMsg, ((ConstructorCallMessage)ctorMsg).GetWOMAttributes());
  454.                
  455.                 ActivationServices.GetPropertiesFromAttributes((IConstructionCallMessage)ctorMsg, ((ConstructorCallMessage)ctorMsg).GetTypeAttributes());
  456.                
  457.                 // Fetch the client context chain
  458.                 IMessageSink cliCtxChain = Thread.CurrentContext.GetClientContextChain();
  459.                
  460.                 // Ask the client context chain to take over from here.
  461.                 IMethodReturnMessage retMsg = (IMethodReturnMessage)cliCtxChain.SyncProcessMessage(ctorMsg);
  462.                
  463.                 ctorRetMsg = retMsg as IConstructionReturnMessage;
  464.                 if (null == retMsg) {
  465.                     throw new RemotingException(Environment.GetResourceString("Remoting_Activation_Failed"));
  466.                 }
  467.                 else if (retMsg.Exception != null) {
  468.                     throw retMsg.Exception;
  469.                 }
  470.             }
  471.             // Note: PropagateOutParameters is now handled by RealProxy
  472.             // CallContext from retMsg should be already set by RealProxy
  473.             BCLDebug.Assert(null != ctorRetMsg, "Activate returning null ConstructorReturnMessage");
  474.            
  475.             return ctorRetMsg;
  476.         }
  477.        
  478.         // This function is called by ActivationServices in case
  479.         // the activation needs to be within the same appdomain. These
  480.         // are only for ContextBound types.
  481.         // It is also called to do satisfy remote incoming requests from
  482.         // the activation services. These could be for both ContextBound
  483.         // and MarshalByRef types.
  484.         static internal IConstructionReturnMessage DoCrossContextActivation(IConstructionCallMessage reqMsg)
  485.         {
  486.             bool bCtxBound = reqMsg.ActivationType.IsContextful;
  487.             Context serverContext = null;
  488.            
  489.             if (bCtxBound) {
  490.                 // If the type is context bound, we need to create
  491.                 // the appropriate context and activate the object inside
  492.                 // it.
  493.                
  494.                 // Create a new Context
  495.                 serverContext = new Context();
  496.                
  497.                
  498.                 ArrayList list = (ArrayList)reqMsg.ContextProperties;
  499.                 Assembly asm = null;
  500.                 for (int i = 0; i < list.Count; i++) {
  501.                     IContextProperty prop = list[i] as IContextProperty;
  502.                     if (null == prop) {
  503.                         throw new RemotingException(Environment.GetResourceString("Remoting_Activation_BadAttribute"));
  504.                     }
  505.                     asm = prop.GetType().Assembly;
  506.                     // Make a security check to ensure that the context property
  507.                     // is from a trusted assembly!
  508.                     CheckForInfrastructurePermission(asm);
  509.                    
  510.                     // This ensures that we don't try to add duplicate
  511.                     // attributes (eg. type attributes common on both client
  512.                     // and server end)
  513.                     if (serverContext.GetProperty(prop.Name) == null) {
  514.                         serverContext.SetProperty(prop);
  515.                     }
  516.                 }
  517.                 // No more property changes to the server context from here.
  518.                 serverContext.Freeze();
  519.                
  520.                 // (This seems like an overkill but that is how it is spec-ed)
  521.                 // Ask each of the properties in the context we formed from
  522.                 // if it is happy with the current context.
  523.                 for (int i = 0; i < list.Count; i++) {
  524.                     if (!((IContextProperty)list[i]).IsNewContextOK(serverContext)) {
  525.                         throw new RemotingException(Environment.GetResourceString("Remoting_Activation_PropertyUnhappy"));
  526.                     }
  527.                 }
  528.             }
  529.            
  530.            
  531.             IConstructionReturnMessage replyMsg;
  532.            
  533.             InternalCrossContextDelegate xctxDel = new InternalCrossContextDelegate(DoCrossContextActivationCallback);
  534.            
  535.             object[] args = new object[] {reqMsg};
  536.            
  537.             if (bCtxBound) {
  538.                 replyMsg = Thread.CurrentThread.InternalCrossContextCallback(serverContext, xctxDel, args) as IConstructionReturnMessage;
  539.             }
  540.             else {
  541.                 replyMsg = xctxDel(args) as IConstructionReturnMessage;
  542.             }
  543.            
  544.             return replyMsg;
  545.         }
  546.        
  547.         static internal object DoCrossContextActivationCallback(object[] args)
  548.         {
  549.             IConstructionCallMessage reqMsg = (IConstructionCallMessage)args[0];
  550.             IConstructionReturnMessage replyMsg = null;
  551.            
  552.             // call the first sink in the server context chain
  553.             IMethodReturnMessage retMsg = (IMethodReturnMessage)Thread.CurrentContext.GetServerContextChain().SyncProcessMessage(reqMsg);
  554.            
  555.             Exception e = null;
  556.             replyMsg = retMsg as IConstructionReturnMessage;
  557.             if (null == replyMsg) {
  558.                 if (retMsg != null) {
  559.                     e = retMsg.Exception;
  560.                 }
  561.                 else {
  562.                     e = new RemotingException(Environment.GetResourceString("Remoting_Activation_Failed"));
  563.                    
  564.                 }
  565.                 replyMsg = new ConstructorReturnMessage(e, null);
  566.                 // We have created our own message ... transfer the callcontext
  567.                 // from the request message.
  568.                 ((ConstructorReturnMessage)replyMsg).SetLogicalCallContext((LogicalCallContext)reqMsg.Properties[Message.CallContextKey]);
  569.             }
  570.            
  571.             return replyMsg;
  572.         }
  573.        
  574.         static internal IConstructionReturnMessage DoServerContextActivation(IConstructionCallMessage reqMsg)
  575.         {
  576.             BCLDebug.Assert(reqMsg != null, "NULL ctorReqMsg");
  577.             Exception e = null;
  578.             Type serverType = reqMsg.ActivationType;
  579.             object serverObj = ActivateWithMessage(serverType, reqMsg, null, out e);
  580.            
  581.             IConstructionReturnMessage replyMsg = SetupConstructionReply(serverObj, reqMsg, e);
  582.            
  583.             BCLDebug.Assert(replyMsg != null, "NULL ctorRetMsg");
  584.             return replyMsg;
  585.         }
  586.        
  587.         static internal IConstructionReturnMessage SetupConstructionReply(object serverObj, IConstructionCallMessage ctorMsg, Exception e)
  588.         {
  589.             IConstructionReturnMessage replyMsg = null;
  590.             if (e == null) {
  591.                 replyMsg = new ConstructorReturnMessage((MarshalByRefObject)serverObj, null, 0, (LogicalCallContext)ctorMsg.Properties[Message.CallContextKey], ctorMsg);
  592.             }
  593.             else {
  594.                 replyMsg = new ConstructorReturnMessage(e, null);
  595.                 // We have created our own message ... transfer the callcontext
  596.                 // from the request message.
  597.                 ((ConstructorReturnMessage)replyMsg).SetLogicalCallContext((LogicalCallContext)ctorMsg.Properties[Message.CallContextKey]);
  598.                
  599.             }
  600.             return replyMsg;
  601.         }
  602.        
  603.         static internal object ActivateWithMessage(Type serverType, IMessage msg, ServerIdentity srvIdToBind, out Exception e)
  604.         {
  605.             object server = null;
  606.             e = null;
  607.            
  608.             // Create a blank instance!
  609.             server = RemotingServices.AllocateUninitializedObject(serverType);
  610.            
  611.             object proxyForObject = null;
  612.             if (serverType.IsContextful) {
  613.                 if (msg is ConstructorCallMessage) {
  614.                     // If it is a strictly x-context activation then
  615.                     // this pointer for the message is the TP that we
  616.                     // returned to JIT in first phase of activation
  617.                     proxyForObject = ((ConstructorCallMessage)msg).GetThisPtr();
  618.                 }
  619.                 else {
  620.                     // we are out of the app-domain, so wrap this object now
  621.                     proxyForObject = null;
  622.                 }
  623.                
  624.                 // This associates the proxy with the real object and sets
  625.                 // up the proxy's native context, ID etc.
  626.                 proxyForObject = RemotingServices.Wrap((ContextBoundObject)server, proxyForObject, false);
  627.                 BCLDebug.Assert(RemotingServices.IsTransparentProxy(proxyForObject), "Wrapped object should be a transparent proxy");
  628.             }
  629.             else {
  630.                 // Since this is an MBR type, something really bad
  631.                 // happened if we are not in the default context
  632.                 if (Thread.CurrentContext != Context.DefaultContext) {
  633.                     throw new RemotingException(Environment.GetResourceString("Remoting_Activation_Failed"));
  634.                 }
  635.                 // Marshal-by-ref case we just return the naked object
  636.                 proxyForObject = server;
  637.             }
  638.            
  639.             // Create the dispatcher which will help run the CTOR
  640.             IMessageSink dispatcher = (IMessageSink)new StackBuilderSink(proxyForObject);
  641.            
  642.             // This call runs the CTOR on the object
  643.             IMethodReturnMessage retMsg = (IMethodReturnMessage)dispatcher.SyncProcessMessage(msg);
  644.            
  645.             if (retMsg.Exception == null) {
  646.                 if (serverType.IsContextful) {
  647.                     // call wrap to finish the operation.
  648.                     return RemotingServices.Wrap((ContextBoundObject)server);
  649.                 }
  650.                 else {
  651.                     return server;
  652.                 }
  653.             }
  654.             else {
  655.                 e = retMsg.Exception;
  656.                 return null;
  657.             }
  658.         }
  659.        
  660.         static internal void StartListeningForRemoteRequests()
  661.         {
  662.             // Get the activation services set up.
  663.             Startup();
  664.             DomainSpecificRemotingData remData = Thread.GetDomain().RemotingData;
  665.             if (!remData.ActivatorListening) {
  666.                 object configLock = remData.ConfigLock;
  667.                 bool fLocked = false;
  668.                 RuntimeHelpers.PrepareConstrainedRegions();
  669.                 try {
  670.                     Monitor.ReliableEnter(configLock, ref fLocked);
  671.                     if (!remData.ActivatorListening) {
  672.                         BCLDebug.Log("Registering remoting activator");
  673.                        
  674.                         // Marshal the object so that it is ready to take remote
  675.                         // calls. We have to create the objref because that is when
  676.                         // the channels start listening for requests.
  677.                         RemotingServices.MarshalInternal(Thread.GetDomain().RemotingData.ActivationListener, ActivationServiceURI, typeof(System.Runtime.Remoting.Activation.IActivator));
  678.                        
  679.                         ServerIdentity srvID = (ServerIdentity)IdentityHolder.ResolveIdentity(ActivationServiceURI);
  680.                        
  681.                         // Set Singleton to prevent lease from being created
  682.                         srvID.SetSingletonObjectMode();
  683.                         //DBG Console.WriteLine("Activator URI: = " + activatorURI);
  684.                         remData.ActivatorListening = true;
  685.                     }
  686.                 }
  687.                 finally {
  688.                     if (fLocked) {
  689.                         Monitor.Exit(configLock);
  690.                     }
  691.                 }
  692.             }
  693.         }
  694.        
  695.         // This returns the local activator
  696.         static internal IActivator GetActivator()
  697.         {
  698.             DomainSpecificRemotingData remData = Thread.GetDomain().RemotingData;
  699.             if (remData.LocalActivator == null) {
  700.                 Startup();
  701.             }
  702.             return (IActivator)remData.LocalActivator;
  703.         }
  704.        
  705.         static internal void Initialize()
  706.         {
  707.             GetActivator();
  708.         }
  709.        
  710.         // This returns the attribute that takes part in every activation
  711.         // The local activator itself exposes that functionality
  712.         static internal ContextAttribute GetGlobalAttribute()
  713.         {
  714.             DomainSpecificRemotingData remData = Thread.GetDomain().RemotingData;
  715.             if (remData.LocalActivator == null) {
  716.                 Startup();
  717.             }
  718.             return (ContextAttribute)remData.LocalActivator;
  719.         }
  720.        
  721.         // This function returns the array of custom attributes of
  722.         // type "ContextAttribute" walking the entire class hierarchy
  723.         // of the serverType
  724.         // If duplicates are found the attribute on the more derived
  725.         // type is kept.
  726.         // The return array may be sparse and is terminated by a NULL.
  727.         static internal IContextAttribute[] GetContextAttributesForType(Type serverType)
  728.         {
  729.             if (!(typeof(ContextBoundObject).IsAssignableFrom(serverType)) || serverType.IsCOMObject) {
  730.                 return new ContextAttribute[0];
  731.             }
  732.            
  733.             Type currType = serverType;
  734.             object[] currAttr = null;
  735.             int retSize = 8;
  736.             IContextAttribute[] retAttr = new IContextAttribute[retSize];
  737.             int numAttr = 0;
  738.            
  739.            
  740.             // Obtain the custom attributes that implement
  741.             // IContextAttribute for this type
  742.             currAttr = currType.GetCustomAttributes(typeof(IContextAttribute), true);
  743.             // recursively on the typeHierarchy
  744.             bool bDupe;
  745.             foreach (IContextAttribute attr in currAttr) {
  746.                 Type attrType = attr.GetType();
  747.                 bDupe = false;
  748.                 for (int i = 0; i < numAttr; i++) {
  749.                     if (attrType.Equals(retAttr[i].GetType())) {
  750.                         bDupe = true;
  751.                         break;
  752.                     }
  753.                 }
  754.                
  755.                 if (!bDupe) {
  756.                     // We must add this attribute to our list
  757.                     numAttr++;
  758.                    
  759.                     // Check if we have enough space to store it
  760.                     // Leaving one spot for a NULL value!
  761.                     if (numAttr > retSize - 1) {
  762.                         IContextAttribute[] newAttr = new IContextAttribute[2 * retSize];
  763.                             // srcArray
  764.                             // srcIndex
  765.                             // destArray
  766.                             // destIndex
  767.                         Array.Copy(retAttr, 0, newAttr, 0, retSize);
  768.                         // lengthToCopy
  769.               &nb