File: system\runtime\remoting\activationservices.cs
Project: ndp\clr\src\bcl\mscorlib.csproj (mscorlib)
// ==++==
// 
//   Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// ==--==
/*============================================================
**
**  File:    ActivationServices.cs
**
**  Author(s):  
**
**  Purpose:           
**
**
===========================================================*/
namespace System.Runtime.Remoting.Activation {
 
    using System;
    using System.Security;
    using System.Threading;
    using System.Runtime.InteropServices;
    using System.Runtime.Remoting;
    using System.Runtime.Remoting.Contexts;
    using System.Runtime.Remoting.Proxies;
    using System.Runtime.Remoting.Messaging;
    using System.Runtime.Remoting.Metadata;
    using System.Collections;
    using System.Reflection;
    using System.IO;
    using System.Runtime.Serialization;
    using System.Security.Permissions;
    using System.Globalization;
    using System.Runtime.CompilerServices;
    using System.Diagnostics.Contracts;
 
    // Implements various activation services
    internal static class ActivationServices
    {
 
        private static volatile IActivator activator = null;     
        
        private static Hashtable _proxyTable = new Hashtable();
        private static readonly Type proxyAttributeType = typeof(System.Runtime.Remoting.Proxies.ProxyAttribute); 
        [System.Security.SecurityCritical] // auto-generated
        private static ProxyAttribute _proxyAttribute = new ProxyAttribute();
        [ThreadStaticAttribute()]
        internal static ActivationAttributeStack _attributeStack;
        internal static readonly Assembly s_MscorlibAssembly = typeof(Object).Assembly;
 
        internal const String ActivationServiceURI = "RemoteActivationService.rem";
 
        internal const String RemoteActivateKey = "Remote";
        internal const String PermissionKey = "Permission";
        internal const String ConnectKey = "Connect";
 
        [System.Security.SecuritySafeCritical] // static constructors should be safe to call
        static ActivationServices()
        { }
 
        // <
 
 
 
 
 
        //1 private static LocalActivator  localActivator = null;
 
        // ActivationListener is the object that listens to incoming
        // activation requests. It delegates the incoming request to 
        // the local activator.
        //2 private static ActivationListener ActivationListener = null;
 
        //3 private static Object staticSyncObject = new Object();
        //4 private static bool bInitializing = false;
 
        // This gets called upon the first attempt to activate
        // anything that is ContextBound or MarshalByRef
        [System.Security.SecurityCritical]  // auto-generated
        private static void Startup()
        {            
            DomainSpecificRemotingData remData = Thread.GetDomain().RemotingData;
 
            // wait on the lock if a)activation has not been initialized yet
            // or b) activation is being initialized by another thread!
            if ((!remData.ActivationInitialized) 
               || remData.InitializingActivation)
            {
                Object configLock = remData.ConfigLock;
                bool fLocked = false;
                RuntimeHelpers.PrepareConstrainedRegions();
                try
                {
                    Monitor.Enter(configLock, ref fLocked);
                    remData.InitializingActivation = true;
                    // Ensure that some other thread did not complete
                    // the work while we were waiting on the lock.
                    if (!remData.ActivationInitialized)
                    {
                        // Startup the activation service
                        BCLDebug.Trace("REMOTE","Starting up activation service ",Thread.CurrentContext);
 
                        //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                        // NOTE: This should be the first step in Startup!
                        // Otherwise activation will recurse, when we try
                        // to create the ActivationListener (which is MarshalByRef)
                        //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                        remData.LocalActivator = new LocalActivator();
 
                        // Add the Lifetime service property to the appdomain.
                        // For now we are assuming that this is the only property
                        // If there are more properties, then an existing array
                        // will need to be expanded to add this property
 
                        // This is activated in RemotingServices.DomainSpecificRemotingData()
                        // IContextProperty[] contextProperties = new IContextProperty[1];
                        // contextProperties[0] = new System.Runtime.Remoting.LeaseLifeTimeServiceProperty();
                        // Thread.GetDomain().RemotingData.AppDomainContextProperties = contextProperties;
 
                        remData.ActivationListener = new ActivationListener();
                        remData.ActivationInitialized = true;
 
                    }
                    
                    remData.InitializingActivation = false;
                } //lock (remData)
                finally
                {
                    if (fLocked)
                    {
                        Monitor.Exit(configLock);
                    }
                }
            }
        }            
           
        [System.Security.SecurityCritical]  // auto-generated
        private static void InitActivationServices()
        {
            // If activation services has not been loaded do it now and create 
            // the instace that will service the activation requests.
            if (null == activator)
            {
                activator = GetActivator();
                if (null == activator)
                {
                    Message.DebugOut("Fatal Error... Could not create activator\n");                
                    throw new RemotingException(
                        String.Format(
                            CultureInfo.CurrentCulture, Environment.GetResourceString(
                                "Remoting_BadInternalState_ActivationFailure")));
                }
            }
        }
 
        // Determine whether the current context is ok for the activation.  
        [System.Security.SecurityCritical]  // auto-generated
        private static MarshalByRefObject IsCurrentContextOK(
            RuntimeType serverType, Object[] props, bool bNewObj)
        {
            Contract.Assert(!serverType.IsInterface,"!serverType.IsInterface");
 
            MarshalByRefObject retObj = null;
            
            // Initialize activation services if needed.
            //   (we temporary null out the activation attributes in case
            //    InitActivationServices creates an MBR).            
            InitActivationServices();            
            
            // Obtain the method info which will create an instance 
            // of type RealProxy
            ProxyAttribute pa = GetProxyAttribute(serverType);
            Contract.Assert(null != pa, "null != pa");
 
            if (Object.ReferenceEquals(pa, DefaultProxyAttribute))
                retObj = pa.CreateInstanceInternal(serverType);
            else            
            {
                retObj = pa.CreateInstance(serverType);
                // We called a custom proxy attribute .. make sure it is 
                // returning a server of the correct type.
                if (retObj != null)
                {
                    // If a transparent proxy is returned we are fine.
                    // If not then the object's type MUST be compatible
                    // with the type we were requested to activate!
                    if (!RemotingServices.IsTransparentProxy(retObj) 
                        && !serverType.IsAssignableFrom(retObj.GetType()))
                    {
                        throw new RemotingException(
                            String.Format(
                                CultureInfo.CurrentCulture, Environment.GetResourceString(
                                    "Remoting_Activation_BadObject"),
                            serverType));
                    }
                }
            }
            Contract.Assert(null != retObj, "null != retObj");
            return retObj;
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        private static MarshalByRefObject CreateObjectForCom(
            RuntimeType serverType, Object[] props, bool bNewObj)
        {
            Contract.Assert(!serverType.IsInterface,"!serverType.IsInterface");
 
            MarshalByRefObject retObj = null;
            
            if (PeekActivationAttributes(serverType) != null)
                throw new NotSupportedException(Environment.GetResourceString("NotSupported_ActivForCom" ));
 
            // Initialize activation services if needed
            InitActivationServices();
                                               
            // Obtain the method info which will create an instance 
            // of type RealProxy
            ProxyAttribute pa = GetProxyAttribute(serverType);
            Contract.Assert(null != pa, "null != pa");
 
            if(pa is ICustomFactory)
            {
                retObj = ((ICustomFactory)pa).CreateInstance(serverType);
            }
            else
            {
                retObj = (MarshalByRefObject)Activator.CreateInstance(serverType, true);
            }
 
            Contract.Assert(null != retObj, "null != retObj");
            return retObj;
        }
 
        // For types with no proxy attribute, we take the default route of 
        // querying attributes if the current context is suitable for 
        // activation.
        [System.Security.SecurityCritical]  // auto-generated
        private static bool IsCurrentContextOK(RuntimeType serverType, Object[] props, 
                                               ref ConstructorCallMessage ctorCallMsg)
        {
             //Get callSite attributes
            Object[] callSiteAttr = PeekActivationAttributes(serverType);
 
            // Clear from the attribute stack
            if (callSiteAttr != null)
            {
                PopActivationAttributes(serverType);
            }
            
            Object[] womAttr = new Object[1];
            womAttr[0] = GetGlobalAttribute();
 
            // Get the type context attributes
            Object[] typeAttr = GetContextAttributesForType(serverType);
 
            // Get the client context (current context)                                                             
            Context cliCtx = Thread.CurrentContext;
 
            // Create a ctorCallMsg with the reqd info 
            ctorCallMsg = 
                new ConstructorCallMessage(
                    callSiteAttr,
                    womAttr,
                    typeAttr,
                    serverType);
 
            // This is the activator that handles activation in *all* cases 
            // Based on whether what the activation attributes do.... other
            // activators may get chained ahead of this one and may take
            // over the activation process... (possibly) delegating to this
            // only in the last stage.
            // Note: currently, this does not get used in the same context (MBR)
            // scenarios ... because of the 2-step activation model of JIT.
            ctorCallMsg.Activator = new ConstructionLevelActivator();
 
 
            // Ask all attributes if they are happy with the current context
            // NOTE: if someone says no, we do not ask the rest of the attributes
            // This is why, womAttr (which is the global activation service
            // attribute) *must* be the first one we query.
            bool bCtxOK = QueryAttributesIfContextOK(cliCtx, 
                                                     ctorCallMsg,
                                                     womAttr);
            if (bCtxOK == true)
            {
                bCtxOK = QueryAttributesIfContextOK(cliCtx, 
                                                    ctorCallMsg,
                                                    callSiteAttr);
                if (bCtxOK == true)
                {
                    bCtxOK = QueryAttributesIfContextOK(cliCtx, 
                                                        ctorCallMsg,
                                                        typeAttr);
                }
            }
 
            return bCtxOK;
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        private static void CheckForInfrastructurePermission(RuntimeAssembly asm)
        {
            // Make a security check to ensure that the context attribute
            // is from a trusted assembly!
            if (asm != s_MscorlibAssembly)
            {
                SecurityPermission remotingInfrastructurePermission = new SecurityPermission(SecurityPermissionFlag.Infrastructure);
                CodeAccessSecurityEngine.CheckAssembly(asm, remotingInfrastructurePermission);
            }
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        private static bool QueryAttributesIfContextOK(
            Context ctx, IConstructionCallMessage ctorMsg, Object[] attributes) 
        {       
            bool bCtxOK = true;
            if (attributes != null)
            {
                for (int i=0; i<attributes.Length; i++)
                {
                    // All the attributes, including callsite attributes should 
                    // expose IContextAttribute. If not, then we throw an 
                    // exception.
                    IContextAttribute attr = attributes[i] as IContextAttribute;
                    if(null != attr)
                    { 
                        RuntimeAssembly asm = (RuntimeAssembly)attr.GetType().Assembly; 
                        // Make a security check to ensure that the context attribute
                        // is from a trusted assembly!
                        CheckForInfrastructurePermission(asm);
                    
                        bCtxOK = attr.IsContextOK(ctx, ctorMsg);
                        if (bCtxOK == false)
                        {
                            break;
                        }
                    }                        
                    else
                    {
                        throw new RemotingException(
                                Environment.GetResourceString(
                                    "Remoting_Activation_BadAttribute"));
                    }
                }
            }
            return bCtxOK;
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        internal static void GetPropertiesFromAttributes(
            IConstructionCallMessage ctorMsg, Object[] attributes)
        {
            if (attributes != null)
            {
                for (int i=0; i<attributes.Length; i++)
                {
                    // All the attributes, including callsite attributes should 
                    // expose IContextAttribute. If not, then we throw an 
                    // exception.
                    IContextAttribute attr = attributes[i] as IContextAttribute;
                    if(null != attr) 
                    {
                        RuntimeAssembly asm = (RuntimeAssembly)attr.GetType().Assembly; 
                        // Make a security check to ensure that the context attribute
                        // is from a trusted assembly!
                        CheckForInfrastructurePermission(asm);
                    
                        // We ask each attribute to contribute its properties.
                        // The attributes can examine the current list of properties
                        // from the ctorCallMsg and decide which properties to add.
 
                        // They can also tweak the Activator chain during this process
                        attr.GetPropertiesForNewContext(ctorMsg);
                    }
                    else
                    {
                        throw new RemotingException(
                            Environment.GetResourceString(
                                "Remoting_Activation_BadAttribute"));
                    }
                }
            }
        }
 
        // Return the default implementation of the proxy attribute
        internal static ProxyAttribute DefaultProxyAttribute
        {
            [System.Security.SecurityCritical]  // auto-generated
            get { return _proxyAttribute; }
        }
 
        // Iterate over the custom attributes of the class and see if it 
        // defines a ProxyAttribute. If one is not defined then return
        // the default proxy attribute defined by us.
        [System.Security.SecurityCritical]  // auto-generated
        internal static ProxyAttribute GetProxyAttribute(Type serverType)
        {
            
            Contract.Assert(    
                serverType.IsMarshalByRef,
                "type should be at least marshal-by-ref");
 
            if (!serverType.HasProxyAttribute)
                return DefaultProxyAttribute;
                    
            // Type has a non-default proxy attribute ... see if we have
            // it cached?
            ProxyAttribute pa = _proxyTable[serverType] as ProxyAttribute;
 
            if (pa == null)
            {   
                Object[] ca = Attribute.GetCustomAttributes(
                                            serverType, 
                                            proxyAttributeType, 
                                            true);
                if((null != ca) && (0 != ca.Length))
                {                    
                    if (!serverType.IsContextful)
                    {
                        throw new RemotingException(
                                    Environment.GetResourceString(
                                    "Remoting_Activation_MBR_ProxyAttribute"));
                    }
                    pa = ca[0] as ProxyAttribute;
                }
                Contract.Assert(pa!=null, "expect proxy attribute");
 
                if(!_proxyTable.Contains(serverType))
                {
                    lock(_proxyTable)
                    {
                        if(!_proxyTable.Contains(serverType))
                        {
                            // Create a new entry
                            _proxyTable.Add(serverType, pa);
                        }
                    }                    
                }
            }
 
            return pa;
        }
 
        // Creates either an uninitialized object or a proxy depending on 
        // whether the current context is OK or not.
        [System.Security.SecurityCritical]  // auto-generated
        internal static MarshalByRefObject CreateInstance(RuntimeType serverType)
        {
            // Use our activation implementation               
            MarshalByRefObject retObj = null;
            ConstructorCallMessage ctorCallMsg = null;
            bool bCtxOK = IsCurrentContextOK(serverType, null, ref ctorCallMsg);
            if (bCtxOK && !serverType.IsContextful)
            {
                // Marshal by ref case
                Message.DebugOut("Allocating blank marshal-by-ref object"); 
                // We create an uninitialized instance of the actual type and
                // let the regular jit-activation execute the constructor on it.
                retObj = RemotingServices.AllocateUninitializedObject(serverType);
            }
            else 
            {
                //  (context not OK) || (serverType is Contextful)
                // We always return a proxy and the jit-activation's attempt
                // to execute the constructor gets intercepted by the TP stub
                // and routed to RemotingServices.Activate() below.
 
                // if context *is* OK 
                // this is a contextBound type being activated for which 
                // we always create a proxy (proxies-everywhere!)
 
                // if context *is not* OK 
                // this could be a MarshalByRef or ContextBound type 
                // being activated outside this appDomain 
                // OR
                // this could be a ContextBound type being activated cross-ctx 
 
                RemotingProxy rp;
                // See if the object-type is configured for Connect (with a URL)
                retObj = (MarshalByRefObject)ConnectIfNecessary(ctorCallMsg);
                if (retObj == null)
                {
                    // not configured for connect, take the usual route of 
                    // creating a proxy
                    Message.DebugOut("Creating remoting proxy for " + 
                                 serverType.FullName + " in context " + 
                                 Thread.CurrentContext);  
 
                    rp = new RemotingProxy(serverType);
 
                    Message.DebugOut("Created remoting proxy\n");
                    retObj = (MarshalByRefObject)rp.GetTransparentProxy();
                }
                else
                {
                    Message.DebugOut("NewObj did a Connect!");
                    rp = (RemotingProxy)RemotingServices.GetRealProxy(retObj);                    
                }                    
 
                // Store the constructor call message in the proxy
                rp.ConstructorMessage = ctorCallMsg;
 
                if (!bCtxOK)
                {
 
                    // Chain in the context level activator now
                    ContextLevelActivator activator = new ContextLevelActivator();
                    activator.NextActivator = ctorCallMsg.Activator; 
                    ctorCallMsg.Activator = activator;
                }
                else
                {
                    // Set the flag to indicate that the activation
                    // will not be leaving the client context .. in this case
                    // the default construction level activator is enough
                    // to complete the activation process.
                    ctorCallMsg.ActivateInContext = true;
                }
            }
 
            return retObj;
        }
 
        //
        // NOTE: This is an internal method used by RemotingProxy to do Activation
        // 
        // Starts off the activation chain by sending the constructor call message to 
        // the activator or the client context sink chain. On return, a constructor
        // return message is made and the out parameters are propagated.
        //
        [System.Security.SecurityCritical]  // auto-generated
        internal static IConstructionReturnMessage Activate(
            RemotingProxy remProxy, IConstructionCallMessage ctorMsg)
        {
            IConstructionReturnMessage ctorRetMsg = null;
 
            if (((ConstructorCallMessage)ctorMsg).ActivateInContext)
            {
                // The current context was approved for activation
                Contract.Assert(
                    ctorMsg.Activator.Level == ActivatorLevel.Construction,
                    "activator level must ActivatorLevel.Construction!");
 
                // This has to be a ContextBound type (proxies-everywhere)
                Contract.Assert(ctorMsg.ActivationType.IsContextful, 
                                "Inconsistent state during activation");
 
                // Ask the activator in the message to take over
                ctorRetMsg = ctorMsg.Activator.Activate(ctorMsg);
 
                if (ctorRetMsg.Exception != null)
                {
                    throw ctorRetMsg.Exception;
                }
            }
            else
            {
                // Client context was not approved for activation ...
                Contract.Assert(
                    ctorMsg.Activator.Level >= ActivatorLevel.Context,
                    "activator level must be at least x-context!");
 
                // Check with ActivationServices if we did a "Connect" with
                // a remote server during IsContextOK
                Contract.Assert(
                    ActivationServices.CheckIfConnected(remProxy, ctorMsg) == null,
                    "We shouldn't come through this path on a Connect.");                    
 
                // Client context was not approved for activation ...
                // This is the more elaborate (real) activation case i.e.
                // we have to go at least out of the client context to 
                // finish the work.
 
                // Prepare for the handoff to Activation Service
 
                // Ask various attributes to contribute properties
                // The attributes may chain in other activators into
                // the activation chain (to hijack/participate in
                // the activation process).
                ActivationServices.GetPropertiesFromAttributes(
                    (IConstructionCallMessage)ctorMsg, 
                    ctorMsg.CallSiteActivationAttributes);
 
                ActivationServices.GetPropertiesFromAttributes(
                    ctorMsg, 
                    ((ConstructorCallMessage)ctorMsg).GetWOMAttributes());
 
                ActivationServices.GetPropertiesFromAttributes(
                    (IConstructionCallMessage)ctorMsg, 
                ((ConstructorCallMessage)ctorMsg).GetTypeAttributes());       
 
                // Fetch the client context chain
                IMessageSink cliCtxChain = 
                Thread.CurrentContext.GetClientContextChain();
 
                // Ask the client context chain to take over from here.
                IMethodReturnMessage retMsg =  
                    (IMethodReturnMessage)
                        cliCtxChain.SyncProcessMessage(ctorMsg);
 
                // The return message may not be of type
                // IConstructionReturnMessage if an exception happens
                // in the sink chains.
                ctorRetMsg = retMsg as IConstructionReturnMessage;
                if (null == retMsg)
                {
                    throw new RemotingException(
                        Environment.GetResourceString(
                            "Remoting_Activation_Failed"));
                }
                else if (retMsg.Exception != null)
                {
                    throw retMsg.Exception;
                }                                
            }
            // Note: PropagateOutParameters is now handled by RealProxy
            // CallContext from retMsg should be already set by RealProxy
            Contract.Assert(
                null != ctorRetMsg, 
                "Activate returning null ConstructorReturnMessage");
                
            return ctorRetMsg;
        }
 
        // This function is called by ActivationServices in case
        // the activation needs to be within the same appdomain. These
        // are only for ContextBound types.
        // It is also called to do satisfy remote incoming requests from
        // the activation services. These could be for both ContextBound
        // and MarshalByRef types.
        [System.Security.SecurityCritical]  // auto-generated
        internal static IConstructionReturnMessage DoCrossContextActivation(
            IConstructionCallMessage reqMsg)
        {           
            bool bCtxBound = reqMsg.ActivationType.IsContextful;
            Context serverContext = null;
            
            if (bCtxBound)
            {
                // If the type is context bound, we need to create 
                // the appropriate context and activate the object inside
                // it.
                // <
 
                // Create a new Context
                serverContext = new Context();              
 
                // <
 
 
 
                
                ArrayList list = (ArrayList) reqMsg.ContextProperties;
                RuntimeAssembly asm = null;
                for (int i=0; i<list.Count; i++)
                {
                    IContextProperty prop = list[i] as IContextProperty;
                    if (null == prop)
                    {
                        throw new RemotingException(
                            Environment.GetResourceString(
                                "Remoting_Activation_BadAttribute"));
                    }
                    asm = (RuntimeAssembly)prop.GetType().Assembly;
                    // Make a security check to ensure that the context property
                    // is from a trusted assembly!
                    CheckForInfrastructurePermission(asm);
 
                    // This ensures that we don't try to add duplicate
                    // attributes (eg. type attributes common on both client
                    // and server end)
                    if (serverContext.GetProperty(prop.Name) == null)
                    {
                        serverContext.SetProperty(prop);
                    }
                }
                // No more property changes to the server context from here.
                serverContext.Freeze();
 
                // (This seems like an overkill but that is how it is spec-ed)
                // Ask each of the properties in the context we formed from
                // if it is happy with the current context.
                for (int i=0; i<list.Count;i++)
                {
                    if (!((IContextProperty)list[i]).IsNewContextOK(
                        serverContext))
                    {
                        throw new RemotingException(
                            Environment.GetResourceString(
                                "Remoting_Activation_PropertyUnhappy"));
                    }
                }
            }
 
 
            IConstructionReturnMessage  replyMsg;
 
            InternalCrossContextDelegate xctxDel = 
                new InternalCrossContextDelegate(DoCrossContextActivationCallback);
 
            Object[] args = new Object[] { reqMsg };
            
            if (bCtxBound)
            {
                replyMsg = Thread.CurrentThread.InternalCrossContextCallback(
                    serverContext, xctxDel, args) as IConstructionReturnMessage;
            }
            else
            {
                replyMsg = xctxDel(args) as IConstructionReturnMessage;
            }
 
            return replyMsg;
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        internal static Object DoCrossContextActivationCallback(Object[] args)
        {
            IConstructionCallMessage    reqMsg   = (IConstructionCallMessage) args[0]; 
            IConstructionReturnMessage  replyMsg = null;
                
            // call the first sink in the server context chain
            // <
            IMethodReturnMessage retMsg =  (IMethodReturnMessage) 
                    Thread.CurrentContext.GetServerContextChain().SyncProcessMessage(reqMsg);
        
            // The return message may not be of type
            // IConstructionReturnMessage if an exception happens
            // in the sink chains.
            Exception e = null;
            replyMsg = retMsg as IConstructionReturnMessage;
            if (null == replyMsg)
            {
                if (retMsg != null)
                {
                    e = retMsg.Exception;
                }
                else
                {
                    e = new RemotingException(
                            Environment.GetResourceString(
                                "Remoting_Activation_Failed"));
        
                }
                replyMsg = new ConstructorReturnMessage(e,null); 
                // We have created our own message ... transfer the callcontext
                // from the request message.
                ((ConstructorReturnMessage)replyMsg).SetLogicalCallContext(
                        (LogicalCallContext)
                        reqMsg.Properties[Message.CallContextKey]);
            }
 
            return replyMsg;
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        internal static IConstructionReturnMessage DoServerContextActivation(
            IConstructionCallMessage reqMsg)
        {
            Contract.Assert(reqMsg!=null, "NULL ctorReqMsg");
            Exception e=null;
            Type serverType = reqMsg.ActivationType;
            Object serverObj = ActivateWithMessage(
                                    serverType, 
                                    reqMsg, 
                                    null,
                                    out e);
 
            IConstructionReturnMessage replyMsg = 
                SetupConstructionReply(serverObj, reqMsg, e);
 
            Contract.Assert(replyMsg!=null, "NULL ctorRetMsg");
            return replyMsg;
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        internal static IConstructionReturnMessage SetupConstructionReply(
            Object serverObj,
            IConstructionCallMessage ctorMsg,
            Exception e)
        {
            IConstructionReturnMessage replyMsg = null;
            if (e == null)
            {
                replyMsg =
                    new ConstructorReturnMessage(
                        (MarshalByRefObject)serverObj,
                        null,   // <
                                // if ctor-s with ref/out are supported</
                        0,
                        (LogicalCallContext)
                            ctorMsg.Properties[Message.CallContextKey],
                        ctorMsg);
            }
            else
            {
                replyMsg = new ConstructorReturnMessage(e,null);
                // We have created our own message ... transfer the callcontext
                // from the request message.
                ((ConstructorReturnMessage)replyMsg).SetLogicalCallContext(
                        (LogicalCallContext)
                            ctorMsg.Properties[Message.CallContextKey]);
 
            }
            return replyMsg;
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        internal static Object ActivateWithMessage(
            Type serverType, IMessage msg, ServerIdentity srvIdToBind,
            out Exception e)
        {
            Object server = null;
            e = null;
 
            // Create a blank instance!
            server = RemotingServices.AllocateUninitializedObject(serverType);
 
            Object proxyForObject = null;
            if (serverType.IsContextful)
            {
                if (msg is ConstructorCallMessage)
                {
                    // If it is a strictly x-context activation then
                    // this pointer for the message is the TP that we
                    // returned to JIT in first phase of activation
                    proxyForObject = ((ConstructorCallMessage)msg).GetThisPtr();
                }
                else
                {
                    // we are out of the app-domain, so wrap this object now
                    proxyForObject = null;
                }
 
                // This associates the proxy with the real object and sets
                // up the proxy's native context, ID etc.
                proxyForObject = RemotingServices.Wrap(
                                        (ContextBoundObject)server,
                                        proxyForObject, 
                                        false);
                Contract.Assert(
                    RemotingServices.IsTransparentProxy(proxyForObject),
                    "Wrapped object should be a transparent proxy");
            }
            else
            {
                // Since this is an MBR type, something really bad
                // happened if we are not in the default context
                if (Thread.CurrentContext != Context.DefaultContext)
                {
                    throw new RemotingException(
                        Environment.GetResourceString(
                            "Remoting_Activation_Failed"));
                }
                // Marshal-by-ref case we just return the object
                proxyForObject = server;                                
            }
 
            // Create the dispatcher which will help run the CTOR
            IMessageSink dispatcher = (IMessageSink)new StackBuilderSink(proxyForObject);
 
            // This call runs the CTOR on the object
            IMethodReturnMessage retMsg = (IMethodReturnMessage) 
                                        dispatcher.SyncProcessMessage(msg);
 
            if (retMsg.Exception == null)
            {
                if (serverType.IsContextful)
                {
                    // call wrap to finish the operation.
                    return RemotingServices.Wrap((ContextBoundObject)server);
                }
                else
                {
                    return server;
                }
            }
            else
            {
                e = retMsg.Exception;
                return null;
            }
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        internal static void StartListeningForRemoteRequests()
        {
            // Get the activation services set up.
            Startup();
            DomainSpecificRemotingData remData = Thread.GetDomain().RemotingData;
            if (!remData.ActivatorListening)
            {
                Object configLock = remData.ConfigLock;
                bool fLocked = false;
                RuntimeHelpers.PrepareConstrainedRegions();
                try
                {
                    Monitor.Enter(configLock, ref fLocked);
                    if (!remData.ActivatorListening)
                    {
                        BCLDebug.Log("Registering remoting activator");
 
                        // Marshal the object so that it is ready to take remote
                        // calls. We have to create the objref because that is when
                        // the channels start listening for requests.
                        RemotingServices.MarshalInternal(
                            Thread.GetDomain().RemotingData.ActivationListener, 
                            ActivationServiceURI,
                            typeof(System.Runtime.Remoting.Activation.IActivator)); 
                            
                        ServerIdentity srvID = (ServerIdentity)
                            IdentityHolder.ResolveIdentity(ActivationServiceURI);
 
                        // Set Singleton to prevent lease from being created
                        srvID.SetSingletonObjectMode();
                        //DBG Console.WriteLine("Activator URI: = " + activatorURI);
                        remData.ActivatorListening = true;
                    }
                }
                finally
                {
                    if (fLocked)
                    {
                        Monitor.Exit(configLock);
                    }
                }
            }
        }
 
        // This returns the local activator
        [System.Security.SecurityCritical]  // auto-generated
        internal static IActivator GetActivator()
        {
            DomainSpecificRemotingData remData = Thread.GetDomain().RemotingData;
            if (remData.LocalActivator == null)
            {
                Startup();
            }
            return (IActivator)remData.LocalActivator;
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        internal static void Initialize()
        {
            GetActivator();
        }
 
        // This returns the attribute that takes part in every activation
        // The local activator itself exposes that functionality
        [System.Security.SecurityCritical]  // auto-generated
        internal static ContextAttribute GetGlobalAttribute()
        {
            DomainSpecificRemotingData remData = Thread.GetDomain().RemotingData;
            if (remData.LocalActivator == null)
            {
                Startup();
            }
            return (ContextAttribute)remData.LocalActivator;
        }
            
        // This function returns the array of custom attributes of
        // type "ContextAttribute" walking the entire class hierarchy
        // of the serverType
        // If duplicates are found the attribute on the more derived
        // type is kept.
        // The return array may be sparse and is terminated by a NULL.
        [System.Security.SecurityCritical]
        internal static IContextAttribute[] GetContextAttributesForType(Type serverType)
        {
            if (!(typeof(ContextBoundObject).IsAssignableFrom(serverType)) ||
                serverType.IsCOMObject)
            {
                return new ContextAttribute[0];
            }
 
            Type currType = serverType;
            Object[] currAttr = null;
            int retSize = 8;
            IContextAttribute[] retAttr = new IContextAttribute[retSize];
            int numAttr = 0;
    
    
            // Obtain the custom attributes that implement 
            // IContextAttribute for this type
            currAttr = currType.GetCustomAttributes(
                                    typeof(IContextAttribute),
                                    true);  // recursively on the typeHierarchy
            Boolean bDupe;                             
            foreach (IContextAttribute attr in currAttr)
            {
                Type attrType = attr.GetType();
                bDupe = false;
                for (int i=0; i<numAttr; i++)
                {
                    if (attrType.Equals(retAttr[i].GetType()))
                    {
                        bDupe = true;
                        break;
                    }
                }
 
                if (!bDupe)
                { 
                    // We must add this attribute to our list
                    numAttr++;
                     
                    // Check if we have enough space to store it
                    // Leaving one spot for a NULL value!
                    if (numAttr > retSize-1)
                    {
                        IContextAttribute[] newAttr = new IContextAttribute[2*retSize];
                        Array.Copy(
                            retAttr,     // srcArray
                            0,          // srcIndex
                            newAttr,    // destArray
                            0,          // destIndex
                            retSize);   // lengthToCopy
                        retAttr = newAttr;
                        retSize = retSize*2;
                    }
                    retAttr[numAttr-1] = attr;
                }
            }
           
            IContextAttribute[] ctxAttr = new IContextAttribute[numAttr];
            Array.Copy(retAttr, ctxAttr, numAttr);
            return ctxAttr;
        }  
                              
        // This is called during RS.IsContextOK to check if the new XXX() is configured
        // to do a direct connect, and if it is we Connect to the URL and return
        // the proxy. In the second stage, when the constructor executes on the proxy
        // we will make sure (in Activate) that there are no CTOR args.
        [System.Security.SecurityCritical]  // auto-generated
        internal static Object ConnectIfNecessary(IConstructionCallMessage ctorMsg)
        {
            // If the type being instantiated is configured for Connect
            // we would have added its URL as the connect key during 
            // LocalActivator::IsContextOK
 
            // Look for the connect URL
            String objURL = (String) ctorMsg.Properties[ConnectKey];
            Object proxy = null;
            if (objURL != null)
            {   
                // Connect to the URL and return the proxy
                proxy = RemotingServices.Connect(
                                        ctorMsg.ActivationType,
                                        objURL);
            }
 
            // If the type is not setup for connecting we return null!
            return proxy;                                            
        }                                        
 
        // This is really used to distinguish between proxies for completely 
        // within AppDomain activations and the ones from "Connect" during
        // the second stage (RS::Activate)
        // For the former, we have to run constructor etc and for the latter
        // we have to check that there is no non-defaul CTOR.
        [System.Security.SecurityCritical]  // auto-generated
        internal static Object CheckIfConnected(
            RemotingProxy proxy, IConstructionCallMessage ctorMsg)
        {
            // If we performed a connect, we must have put the URL as
            // the connectKey in the message.
            String objURL = (String)
                            ctorMsg.Properties[ConnectKey];
            Object tp = null;
 
            if (objURL != null)
            {   
                // We did perform a connect during IsContextOK 
                // Just get the TP from RP and return it.
                tp = (Object)proxy.GetTransparentProxy();
            } 
            // We return null if we do not recognize this proxy!
            return tp;                                            
        }
        
        internal static void PushActivationAttributes(Type serverType, Object[] attributes)
        {
            // There is one such object per thread
            if (_attributeStack == null)
            {            
                _attributeStack = new ActivationAttributeStack();
            }
            _attributeStack.Push(serverType, attributes);
        }
 
        internal static Object[] PeekActivationAttributes(Type serverType)
        {
            // We can get a peek w/o a prior Push (eg. activation starting
            // with NewObj)
            if (_attributeStack == null)
            {            
                return null;
            }
            return _attributeStack.Peek(serverType);
        }
        
        internal static void PopActivationAttributes(Type serverType)
        {
            Contract.Assert(_attributeStack != null, "Pop w/o a prior Set()?");
            _attributeStack.Pop(serverType);
        }        
    } // class ActivationServices    
 
 
    // This is the local activation helper and also the Attribute 
    // that gets queried about every activation
    [System.Security.SecurityCritical]  // auto-generated
    internal class LocalActivator: ContextAttribute, IActivator
    {
        internal LocalActivator()
            : base(ActivationServices.ActivationServiceURI)
        {
        
        }
 
        // ---------------------------------------------------------------        
        // ContextAttribute functionality
        // ---------------------------------------------------------------        
 
        // IContextAttribute::IsContextOK
        // This will check if a type is configured for remote activation ... 
        // We return 'false' for IsContextOK if it is.
        [System.Security.SecurityCritical]
        public override bool IsContextOK(
            Context ctx, IConstructionCallMessage ctorMsg)
        {
 
            // If the app is not using config mechanism, we don't want
            // to intercept activation.
            if (RemotingConfigHandler.Info == null)
            {
                return true;
            }
 
            // check if this type is configured for connect 
            // (instead of remote activate)
            RuntimeType activationType = ctorMsg.ActivationType as RuntimeType;
            if (activationType == null)
                throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"));
 
            WellKnownClientTypeEntry wkte = 
                RemotingConfigHandler.IsWellKnownClientType(activationType);
            String typeURL = (wkte == null ? null : wkte.ObjectUrl);
 
            if (typeURL != null)
            {
                // this type does have a direct uri, we will try to connect 
                // to it during the activate call. Cache it in the message.
                ctorMsg.Properties[ActivationServices.ConnectKey] = typeURL;
                return false;
            }
            else
            {
                ActivatedClientTypeEntry acte = 
                    RemotingConfigHandler.IsRemotelyActivatedClientType(activationType);
 
                String appURL = null;
 
                if (acte == null)
                {
                    // This is the case where the config file had no entry for this type.
                    // We should check the callsite attributes for a URL
                    Object[] callsiteAttributes = ctorMsg.CallSiteActivationAttributes;
                    if(null != callsiteAttributes)
                    {
                        for(int i = 0; i < callsiteAttributes.Length; i++)
                        {
                            UrlAttribute attr = callsiteAttributes[i] as UrlAttribute;
                            if(null != attr)
                            {
                                appURL = attr.UrlValue; 
                            }
                        }
                    }
                        
                    if(appURL == null)
                    {
                        // We don't really care about intercepting the activation in this case.
                        return true;
                    }
                }
                else
                {
                    appURL = acte.ApplicationUrl;
                }
 
                // Generate the URL of the remote activator                    
                String activatorURL = null;
                if (!appURL.EndsWith("/", StringComparison.Ordinal))
                    activatorURL = appURL + "/" + ActivationServices.ActivationServiceURI;
                else
                    activatorURL = appURL + ActivationServices.ActivationServiceURI;
                            
                // Mark a flag for remote activation 
                // (caching the url of the activation svc of the remote server)
                ctorMsg.Properties[ActivationServices.RemoteActivateKey] = activatorURL;
                return false;
            }
        }
                
        // IContextAttribute::GetPropertiesForNewContext
        [System.Security.SecurityCritical]
        public override void GetPropertiesForNewContext(
            IConstructionCallMessage ctorMsg)
        {            
            BCLDebug.Log("ActivationSvc:GlobalAttrib::GetPropForNewCtx");
            // This is called during RS::Activate .. when we are sure that
            // activation is at least x-context and this is a real activation
            // instead of a spoofed connect underneath the "new".
            Contract.Assert(ctorMsg!=null, "ctorMsg null?");
            if (ctorMsg.Properties.Contains(ActivationServices.RemoteActivateKey))
            {
                // Means we did want to intercept activation!
                String remActivatorURL = (String)
                    ctorMsg.Properties[ActivationServices.RemoteActivateKey];
                
                AppDomainLevelActivator activator = 
                    new AppDomainLevelActivator(remActivatorURL);
                // Chain ourselves at the end of the AppDomainLevel activators
                Contract.Assert(
                        ctorMsg.Activator != null, 
                        "Should have at least x-context activator");
                IActivator curr = ctorMsg.Activator;
                
                if (curr.Level < ActivatorLevel.AppDomain)
                {
                    // Common case .. .only x-context activator(s) in chain
                    activator.NextActivator = curr;
                    ctorMsg.Activator = activator;
                }
                else if (curr.NextActivator == null)
                {  
                    // Only one activator but not ContextLevel ...
                    // We go at the end of the chain 
                    curr.NextActivator = activator;
                }
                else
                {
                    // We will have to walk the chain till the end of the last
                    // AD activator and plug ourselves in.
                    while (curr.NextActivator.Level >= ActivatorLevel.AppDomain)
                    {                        
                        curr = curr.NextActivator;
                    }
                    Contract.Assert(
                        curr.NextActivator.Level.Equals(ActivatorLevel.Context),
                        "bad ordering of activators!");
                    activator.NextActivator = curr.NextActivator;
                    curr.NextActivator = activator;
                }                                
            }
        }                     
 
        // ---------------------------------------------------------------        
        // IActivator functionality
        // ---------------------------------------------------------------        
        //IActivator::NextActivator
        public virtual IActivator NextActivator 
        {
            // We are a singleton internal infrastructure object.
            [System.Security.SecurityCritical]
            get { return null; }
            // Don't allow a set either.
            [System.Security.SecurityCritical]
            set { throw new InvalidOperationException(); }
        }
 
        //IActivator::ActivatorLevel
        public virtual ActivatorLevel Level
        {
            [System.Security.SecurityCritical]
            get { return ActivatorLevel.AppDomain; }
        }
                
        private static MethodBase GetMethodBase(IConstructionCallMessage msg)
        {
            MethodBase mb = msg.MethodBase;
            if(null == mb)      
            {
                BCLDebug.Trace("REMOTE", "Method missing w/name ", msg.MethodName);
                    throw new RemotingException(
                        String.Format(
                            CultureInfo.CurrentCulture, Environment.GetResourceString(
                                "Remoting_Message_MethodMissing"),
                            msg.MethodName,
                            msg.TypeName));
            }
                    
            return mb;
        }
 
        //IActivator::Activate
        [System.Security.SecurityCritical]
        [System.Runtime.InteropServices.ComVisible(true)]
        public virtual IConstructionReturnMessage Activate(
            IConstructionCallMessage ctorMsg)
        {
            // This is where the activation service hooks in to activation
            // requests. We get called as the activation message is recognized
            // by the ClientContextTerminatorSink & routed to us. 
            //
            // NOTE: This gets called for both purely within appDomain activation
            // and 'real' remote activation scenarios as the request goes out of
            // the client context.
            // It also gets called as an incoming remote call is routed to the
            // local activator by the remote activator object.
            //
            BCLDebug.Log("Activation Services:: new Activate()");
            if (ctorMsg == null)
            {
                throw new ArgumentNullException("ctorMsg");
            }
            Contract.EndContractBlock();
            
            // Check if we have marked this activation to go remote 
            if (ctorMsg.Properties.Contains(ActivationServices.RemoteActivateKey))
            {
                //DBG Console.WriteLine("Attempting remote activation!");
                                
                return DoRemoteActivation(ctorMsg);
            }
            else
            {                
                // We must be in either a pure cross context activation or
                // a remote incoming activation request (in which case we
                // already checked the permission to create an instance of
                // this type).
                if (ctorMsg.Properties.Contains(ActivationServices.PermissionKey))
                { 
                    Type activationType = ctorMsg.ActivationType;                    
 
                    // We are on the server end of a real remote activation
                    // Create a local attribute that contributes the context
                    // properties requested by the remote request
                    Object[] attr = null;
                    if (activationType.IsContextful)
                    {
                    IList cp = ctorMsg.ContextProperties;
                    if (cp != null && cp.Count > 0)
                    {
                        RemotePropertyHolderAttribute rph = new RemotePropertyHolderAttribute(cp);
                        attr = new Object[1];
                        attr[0] = rph;
                    }
                    }
                    MethodBase mb = GetMethodBase(ctorMsg); 
                    RemotingMethodCachedData methodCache = 
                                            InternalRemotingServices.GetReflectionCachedData(mb);
                    Object[] args = Message.CoerceArgs(ctorMsg, methodCache.Parameters);
                    
                    Object server = Activator.CreateInstance(
                        activationType, 
                        args,
                        attr);
 
                    // check to see if we need to do redirection
                    if (RemotingServices.IsClientProxy(server))
                    {
                        // The wellknown type is remoted so we must wrap the proxy
                        // with a local object.
 
                        // The redirection proxy masquerades as an object of the appropriate
                        // type, and forwards incoming messages to the actual proxy.
                        RedirectionProxy redirectedProxy = 
                            new RedirectionProxy((MarshalByRefObject)server, activationType);
                        RemotingServices.MarshalInternal(redirectedProxy, null, activationType);
 
                        server = redirectedProxy;
                    }                        
                     
                    return ActivationServices.SetupConstructionReply(
                        server, ctorMsg, null);
                }
                else
                {
                    BCLDebug.Log("Attempting X-Context activation!");
                    // delegate to the Activator in the message 
                    return ctorMsg.Activator.Activate(ctorMsg);
                }
            }
        }
 
 
        // This is called by the local activator during an outgoing activation
        // request.
        internal static IConstructionReturnMessage DoRemoteActivation(
            IConstructionCallMessage ctorMsg)
        {
            Contract.Assert(ctorMsg != null, "Null ctorMsg");
 
            // <
 
 
 
 
            // <
 
 
            
            BCLDebug.Log("Attempting Connection to remote activation service");
            IActivator remActivator = null;
            String remActivatorURL = (String)
                ctorMsg.Properties[ActivationServices.RemoteActivateKey];
            try 
            {
                remActivator = (IActivator) 
                    RemotingServices.Connect(
                        typeof(System.Runtime.Remoting.Activation.IActivator),
                        remActivatorURL);
                                    
            }
            catch (Exception e)
            {
                throw new RemotingException(
                    String.Format(
                        CultureInfo.CurrentCulture, Environment.GetResourceString(
                            "Remoting_Activation_ConnectFailed"),
                        e));
            }
            // Remove the remote activate key as its purpose is served.
            ctorMsg.Properties.Remove(ActivationServices.RemoteActivateKey);
 
            // Delegate the work to the remote activator
            return remActivator.Activate(ctorMsg);                        
        }
        
    }// class LocalActivator
 
    // This is the object that listens to activation requests
    internal class ActivationListener:MarshalByRefObject, IActivator
    {
        // Override lifetime services to make this object live forever...
        [System.Security.SecurityCritical]  // auto-generated
        public override Object InitializeLifetimeService()
        {
           return null;
        }
 
        //IActivator::NextActivator
        public virtual IActivator NextActivator 
        {
            // We are a singleton internal infrastructure object.
            [System.Security.SecurityCritical]  // auto-generated
            get { return null; }
            // Don't allow a set either.
            [System.Security.SecurityCritical]  // auto-generated
            set { throw new InvalidOperationException();}
        }
 
        //IActivator::ActivatorLevel
        public virtual ActivatorLevel Level
        {
            [System.Security.SecurityCritical]  // auto-generated
            get {return ActivatorLevel.AppDomain;}
        }
    
        //IActivator::Activate
[System.Security.SecurityCritical]  // auto-generated
[System.Runtime.InteropServices.ComVisible(true)]
        public virtual IConstructionReturnMessage Activate(
            IConstructionCallMessage ctorMsg)
        {
            BCLDebug.Log("ActivationListener: received new activation request!");
            if (ctorMsg == null || RemotingServices.IsTransparentProxy(ctorMsg))
            {
                throw new ArgumentNullException("ctorMsg");
            }
            Contract.EndContractBlock();
            
            // Add the permission key which distinguishes pure-cross context activation from
            // a remote request (both of which go through DoCrossContextActivation)
            ctorMsg.Properties[ActivationServices.PermissionKey] = "allowed";
 
            // Check to make sure that this activation type has been allowed.
            String activationTypeName = ctorMsg.ActivationTypeName;
            if (!RemotingConfigHandler.IsActivationAllowed(activationTypeName))
            {
                throw new RemotingException(
                    String.Format(
                        CultureInfo.CurrentCulture, Environment.GetResourceString(
                            "Remoting_Activation_PermissionDenied"),
                        ctorMsg.ActivationTypeName));
            }
 
            Type activationType = ctorMsg.ActivationType;
            if (activationType == null)
            {
                throw new RemotingException(
                    String.Format(
                        CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_BadType"),
                        ctorMsg.ActivationTypeName));
            }
            
            // Delegate to the local activator for further work
            return ActivationServices.GetActivator().Activate(ctorMsg);
        }        
 
        
    }   // class ActivationListener
 
 
    // This is a lightweight object to help with the activation
    // at the appDomain level ... it delegates its work to 
    // ActivationServices.LocalActivator ... which is a heavy 
    // object we can't afford to carry around in the ActivatorChain
    // (since it may get Serialized/Deserialized)
 [Serializable]
    // attribute .. the latter shall be turned on during Beta-2!</
    internal class AppDomainLevelActivator : IActivator
    {
        IActivator m_NextActivator;        
 
        // Do we need this?
        String m_RemActivatorURL;
        
        internal AppDomainLevelActivator(String remActivatorURL)
        {
            Contract.Assert(remActivatorURL!=null,"Bad activator URL");
            m_RemActivatorURL = remActivatorURL;
        }
 
        internal AppDomainLevelActivator(SerializationInfo info, StreamingContext context) {
            if (info==null)
            {
                throw new ArgumentNullException("info");
            }
            Contract.EndContractBlock();
            m_NextActivator = (IActivator) info.GetValue("m_NextActivator",typeof(IActivator));
        }
 
        //IActivator::NextActivator
        public virtual IActivator NextActivator 
        {            
            [System.Security.SecurityCritical]  // auto-generated
            get { return m_NextActivator; }
            [System.Security.SecurityCritical]  // auto-generated
            set { m_NextActivator = value; }
        }
 
        //IActivator::ActivatorLevel
        public virtual ActivatorLevel Level
        {
            [System.Security.SecurityCritical]  // auto-generated
            get { return ActivatorLevel.AppDomain; }
        }
 
        //IActivator::Activate
[System.Security.SecurityCritical]  // auto-generated
[System.Runtime.InteropServices.ComVisible(true)]
        public virtual IConstructionReturnMessage Activate(
            IConstructionCallMessage ctorMsg)
        {
            // This function will get invoked when the ClientContextTerminator sink
            // notices that an activation request message is passed to it ... it
            // will route the message to the Activator present inside the ctorMsg
            // (which happens to be us in this case!)
 
            // remove ourselves from the Activator chain
            ctorMsg.Activator = m_NextActivator;
            return ActivationServices.GetActivator().Activate(ctorMsg);            
        }
    }
 
    // This is a lightweight object to help with the activation
    // at the context level ...     
    [Serializable]
    internal class ContextLevelActivator : IActivator
    {                
        IActivator m_NextActivator;
        internal ContextLevelActivator()
        {
            m_NextActivator = null;
        }
        
        internal ContextLevelActivator(SerializationInfo info, StreamingContext context) 
        {
            if (info==null)
            {
                throw new ArgumentNullException("info");
            }
            Contract.EndContractBlock();
            m_NextActivator = (IActivator) info.GetValue("m_NextActivator",typeof(IActivator));
        }
 
        //IActivator::NextActivator
        public virtual IActivator NextActivator 
        {            
            [System.Security.SecurityCritical]  // auto-generated
            get { return m_NextActivator; }
            [System.Security.SecurityCritical]  // auto-generated
            set { m_NextActivator = value; }
        }
 
        //IActivator::ActivatorLevel
        public virtual ActivatorLevel Level
        {
            [System.Security.SecurityCritical]  // auto-generated
            get { return ActivatorLevel.Context; }
        }
 
        //IActivator::Activate
[System.Security.SecurityCritical]  // auto-generated
[System.Runtime.InteropServices.ComVisible(true)]
        public virtual IConstructionReturnMessage Activate(
            IConstructionCallMessage ctorMsg)
        {
            // remove ourselves from the Activator chain
            ctorMsg.Activator = ctorMsg.Activator.NextActivator;
            
            // Delegate to remoting services to do the hard work.
            // This will create a context, enter it, run through
            // the context sink chain & then delegate to the nex
            // activator inside the ctorMsg (quite likely to be 
            // the default ConstructionLevelActivator)
            return ActivationServices.DoCrossContextActivation(ctorMsg);
        }        
    }
 
    // This is a lightweight object to help with the activation
    // at the appDomain level ... it delegates its work to 
    // ActivationServices.LocalActivator ... which is a heavy 
    // object we can't afford to carry around in the ActivatorChain
    // (since it may get Serialized/Deserialized)
    [Serializable]
    internal class ConstructionLevelActivator : IActivator
    {                
        internal ConstructionLevelActivator()
        {
        
        }
 
 
        //IActivator::NextActivator
        public virtual IActivator NextActivator 
        {            
            // The construction level activator is a terminating activator
            [System.Security.SecurityCritical]  // auto-generated
            get { return null; }
            // Throw if someone attempts a set
            [System.Security.SecurityCritical]  // auto-generated
            set { throw new InvalidOperationException(); }
        }
 
        //IActivator::ActivatorLevel
        public virtual ActivatorLevel Level
        {
            [System.Security.SecurityCritical]  // auto-generated
            get { return ActivatorLevel.Construction; }
        }
 
        //IActivator::Activate
[System.Security.SecurityCritical]  // auto-generated
[System.Runtime.InteropServices.ComVisible(true)]
        public virtual IConstructionReturnMessage Activate(
            IConstructionCallMessage ctorMsg)
        {
            // This function will get invoked when the ClientContextTerminator sink
            // notices that an activation request message is passed to it ... it
            // will route the message to the Activator present inside the ctorMsg
            // (which happens to be us in this case!)
 
            // remove ourselves from the Activator chain
            ctorMsg.Activator = ctorMsg.Activator.NextActivator;
            return ActivationServices.DoServerContextActivation(ctorMsg);            
        }
    }
 
    // This acts as a pseudo call site attribute and transfers 
    // the context properties carried in from a remote activation request
    // to the server side activation 
    internal class RemotePropertyHolderAttribute : IContextAttribute
    {
        IList _cp;      // incoming list of context properties
        internal RemotePropertyHolderAttribute(IList cp)
        {
            _cp = cp;
            Contract.Assert(cp != null && cp.Count > 0,"Bad _cp?");
        }
[System.Security.SecurityCritical]  // auto-generated
[System.Runtime.InteropServices.ComVisible(true)]
        public virtual bool IsContextOK(Context ctx, IConstructionCallMessage msg)
        {
            // The fact that we got instantiated means some remote activation
            // has contributed non-default context properties to the ctorMsg
            return false;
        }
 
 
        // properties are collected in order from callsite, wom & type 
        // attributes ... so we get a first shot at adding properties
[System.Security.SecurityCritical]  // auto-generated
[System.Runtime.InteropServices.ComVisible(true)]
        public virtual void GetPropertiesForNewContext(IConstructionCallMessage ctorMsg)
        {
            for (int i=0; i<_cp.Count; i++)
            {
                // Just cycle through the list and add the properties to 
                // the construction message.
                // We will throw at a later stage if any of these do not
                // implement IContextProperty
                ctorMsg.ContextProperties.Add(_cp[i]);
            }
        }
    }
        
    // Note: One instance of this class is setup per thread that comes to
    // managed remoting for activation of MBR types. All access to methods
    // is by design single-threaded. (Each thread is working on its own object).
 
    // In the case of Activator.CreateInstance ... that API does the Push &
    // Remoting does a Pop() as soon as it has picked up the attributes from
    // the threadStatic. The CreateInstance API itself does a Pop() too in 
    // a try-finally. (So this does not work very well if the infrastructure 
    // creates an instance of the same MBR type as the outer type being created.
    // However, to minimize code churn this is the least risky fix we can do.
    // The full fix would be to pass activationAttributes into the VM through
    // reflection code and have the VM pass them over to remoting which will
    // then hand them over to managed remoting helpers. This will also involve
    // adding attributes as an additional parameter to 
    // ProxyAttribute.CreateInstance() public method.
 
    internal class ActivationAttributeStack
    {
        Object[] activationTypes;
        Object[] activationAttributes;
        int freeIndex;
        internal ActivationAttributeStack()
        {
            activationTypes = new Object[4];
            activationAttributes = new Object[4];
            freeIndex = 0;
        }
 
        internal void Push(Type typ, Object[] attr)
        {
            Contract.Assert(typ!=null, "typ != null");                    
            Contract.Assert(attr!=null, "attr != null");        
 
            if (freeIndex == activationTypes.Length)
            {
                // Need to grow our arrays ... this will be exceedingly rare
                Object[] newTypes = new Object[activationTypes.Length * 2];
                Object[] newAttr = new Object[activationAttributes.Length * 2];
                Contract.Assert(newAttr.Length == newTypes.Length,"These should be in sync!");
                Array.Copy(activationTypes, newTypes, activationTypes.Length);
                Array.Copy(activationAttributes, newAttr, activationAttributes.Length);    
                activationTypes = newTypes;
                activationAttributes = newAttr;
            }
            activationTypes[freeIndex] = typ;
            activationAttributes[freeIndex] = attr;
            freeIndex++;
        }
 
        internal Object[] Peek(Type typ)
        {
            Contract.Assert(typ!=null, "typ != null");
            if (freeIndex == 0 || activationTypes[freeIndex-1] != (object)typ)
            {
                return null;
            }
            return (Object[])activationAttributes[freeIndex-1];
        }
 
        // Note: Read the comments above .. you can have 2 pops for the same 
        // push. We also count on infrastructure code not activating 
        // the same type as the caller causing a recursive activation.
        internal void Pop(Type typ)
        {
            Contract.Assert(typ!=null, "typ != null");
            if (freeIndex != 0 && activationTypes[freeIndex-1] == (object)typ)
            {                
                freeIndex--;
                // Clear the popped entry
                activationTypes[freeIndex] = null;
                activationAttributes[freeIndex] = null;
            }
        }
    }
}//namespace