ActivationServices.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / clr / src / BCL / System / Runtime / Remoting / ActivationServices.cs / 1305376 / ActivationServices.cs

                            // ==++== 
//
//   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 IActivator activator = null;
 
        private static Hashtable _proxyTable = new Hashtable();
        private static 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 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; 
        }
 
#if FEATURE_COMINTEROP
        [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; 
        }
#endif // FEATURE_COMINTEROP 
 
        // 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 != RemotingServices.s_MscorlibAssembly) 
            {
                CodeAccessSecurityEngine.CheckAssembly(asm, RemotingServices.s_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= 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 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! 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 [....]!");
                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

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// ==++== 
//
//   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 IActivator activator = null;
 
        private static Hashtable _proxyTable = new Hashtable();
        private static 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 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; 
        }
 
#if FEATURE_COMINTEROP
        [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; 
        }
#endif // FEATURE_COMINTEROP 
 
        // 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 != RemotingServices.s_MscorlibAssembly) 
            {
                CodeAccessSecurityEngine.CheckAssembly(asm, RemotingServices.s_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= 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 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! 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 [....]!");
                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

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK