3 // Copyright (c) Microsoft Corporation. All rights reserved.
6 /*============================================================
8 ** File: ActivationServices.cs
15 ===========================================================*/
16 namespace System.Runtime.Remoting.Activation {
19 using System.Security;
20 using System.Threading;
21 using System.Runtime.InteropServices;
22 using System.Runtime.Remoting;
23 using System.Runtime.Remoting.Contexts;
24 using System.Runtime.Remoting.Proxies;
25 using System.Runtime.Remoting.Messaging;
26 using System.Runtime.Remoting.Metadata;
27 using System.Collections;
28 using System.Reflection;
30 using System.Runtime.Serialization;
31 using System.Security.Permissions;
32 using System.Globalization;
33 using System.Runtime.CompilerServices;
34 using System.Diagnostics.Contracts;
36 // Implements various activation services
37 internal static class ActivationServices
40 private static volatile IActivator activator = null;
42 private static Hashtable _proxyTable = new Hashtable();
43 private static readonly Type proxyAttributeType = typeof(System.Runtime.Remoting.Proxies.ProxyAttribute);
44 [System.Security.SecurityCritical] // auto-generated
45 private static ProxyAttribute _proxyAttribute = new ProxyAttribute();
46 [ThreadStaticAttribute()]
47 internal static ActivationAttributeStack _attributeStack;
48 internal static readonly Assembly s_MscorlibAssembly = typeof(Object).Assembly;
50 internal const String ActivationServiceURI = "RemoteActivationService.rem";
52 internal const String RemoteActivateKey = "Remote";
53 internal const String PermissionKey = "Permission";
54 internal const String ConnectKey = "Connect";
56 [System.Security.SecuritySafeCritical] // static constructors should be safe to call
57 static ActivationServices()
66 //1 private static LocalActivator localActivator = null;
68 // ActivationListener is the object that listens to incoming
69 // activation requests. It delegates the incoming request to
70 // the local activator.
71 //2 private static ActivationListener ActivationListener = null;
73 //3 private static Object staticSyncObject = new Object();
74 //4 private static bool bInitializing = false;
76 // This gets called upon the first attempt to activate
77 // anything that is ContextBound or MarshalByRef
78 [System.Security.SecurityCritical] // auto-generated
79 private static void Startup()
81 DomainSpecificRemotingData remData = Thread.GetDomain().RemotingData;
83 // wait on the lock if a)activation has not been initialized yet
84 // or b) activation is being initialized by another thread!
85 if ((!remData.ActivationInitialized)
86 || remData.InitializingActivation)
88 Object configLock = remData.ConfigLock;
90 RuntimeHelpers.PrepareConstrainedRegions();
93 Monitor.Enter(configLock, ref fLocked);
94 remData.InitializingActivation = true;
95 // Ensure that some other thread did not complete
96 // the work while we were waiting on the lock.
97 if (!remData.ActivationInitialized)
99 // Startup the activation service
100 BCLDebug.Trace("REMOTE","Starting up activation service ",Thread.CurrentContext);
102 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
103 // NOTE: This should be the first step in Startup!
104 // Otherwise activation will recurse, when we try
105 // to create the ActivationListener (which is MarshalByRef)
106 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
107 remData.LocalActivator = new LocalActivator();
109 // Add the Lifetime service property to the appdomain.
110 // For now we are assuming that this is the only property
111 // If there are more properties, then an existing array
112 // will need to be expanded to add this property
114 // This is activated in RemotingServices.DomainSpecificRemotingData()
115 // IContextProperty[] contextProperties = new IContextProperty[1];
116 // contextProperties[0] = new System.Runtime.Remoting.LeaseLifeTimeServiceProperty();
117 // Thread.GetDomain().RemotingData.AppDomainContextProperties = contextProperties;
119 remData.ActivationListener = new ActivationListener();
120 remData.ActivationInitialized = true;
124 remData.InitializingActivation = false;
130 Monitor.Exit(configLock);
136 [System.Security.SecurityCritical] // auto-generated
137 private static void InitActivationServices()
139 // If activation services has not been loaded do it now and create
140 // the instace that will service the activation requests.
141 if (null == activator)
143 activator = GetActivator();
144 if (null == activator)
146 Message.DebugOut("Fatal Error... Could not create activator\n");
147 throw new RemotingException(
149 CultureInfo.CurrentCulture, Environment.GetResourceString(
150 "Remoting_BadInternalState_ActivationFailure")));
155 // Determine whether the current context is ok for the activation.
156 [System.Security.SecurityCritical] // auto-generated
157 private static MarshalByRefObject IsCurrentContextOK(
158 RuntimeType serverType, Object[] props, bool bNewObj)
160 Contract.Assert(!serverType.IsInterface,"!serverType.IsInterface");
162 MarshalByRefObject retObj = null;
164 // Initialize activation services if needed.
165 // (we temporary null out the activation attributes in case
166 // InitActivationServices creates an MBR).
167 InitActivationServices();
169 // Obtain the method info which will create an instance
171 ProxyAttribute pa = GetProxyAttribute(serverType);
172 Contract.Assert(null != pa, "null != pa");
174 if (Object.ReferenceEquals(pa, DefaultProxyAttribute))
175 retObj = pa.CreateInstanceInternal(serverType);
178 retObj = pa.CreateInstance(serverType);
179 // We called a custom proxy attribute .. make sure it is
180 // returning a server of the correct type.
183 // If a transparent proxy is returned we are fine.
184 // If not then the object's type MUST be compatible
185 // with the type we were requested to activate!
186 if (!RemotingServices.IsTransparentProxy(retObj)
187 && !serverType.IsAssignableFrom(retObj.GetType()))
189 throw new RemotingException(
191 CultureInfo.CurrentCulture, Environment.GetResourceString(
192 "Remoting_Activation_BadObject"),
197 Contract.Assert(null != retObj, "null != retObj");
201 [System.Security.SecurityCritical] // auto-generated
202 private static MarshalByRefObject CreateObjectForCom(
203 RuntimeType serverType, Object[] props, bool bNewObj)
205 Contract.Assert(!serverType.IsInterface,"!serverType.IsInterface");
207 MarshalByRefObject retObj = null;
209 if (PeekActivationAttributes(serverType) != null)
210 throw new NotSupportedException(Environment.GetResourceString("NotSupported_ActivForCom" ));
212 // Initialize activation services if needed
213 InitActivationServices();
215 // Obtain the method info which will create an instance
217 ProxyAttribute pa = GetProxyAttribute(serverType);
218 Contract.Assert(null != pa, "null != pa");
220 if(pa is ICustomFactory)
222 retObj = ((ICustomFactory)pa).CreateInstance(serverType);
226 retObj = (MarshalByRefObject)Activator.CreateInstance(serverType, true);
229 Contract.Assert(null != retObj, "null != retObj");
233 // For types with no proxy attribute, we take the default route of
234 // querying attributes if the current context is suitable for
236 [System.Security.SecurityCritical] // auto-generated
237 private static bool IsCurrentContextOK(RuntimeType serverType, Object[] props,
238 ref ConstructorCallMessage ctorCallMsg)
240 //Get callSite attributes
241 Object[] callSiteAttr = PeekActivationAttributes(serverType);
243 // Clear from the attribute stack
244 if (callSiteAttr != null)
246 PopActivationAttributes(serverType);
249 Object[] womAttr = new Object[1];
250 womAttr[0] = GetGlobalAttribute();
252 // Get the type context attributes
253 Object[] typeAttr = GetContextAttributesForType(serverType);
255 // Get the client context (current context)
256 Context cliCtx = Thread.CurrentContext;
258 // Create a ctorCallMsg with the reqd info
260 new ConstructorCallMessage(
266 // This is the activator that handles activation in *all* cases
267 // Based on whether what the activation attributes do.... other
268 // activators may get chained ahead of this one and may take
269 // over the activation process... (possibly) delegating to this
270 // only in the last stage.
271 // Note: currently, this does not get used in the same context (MBR)
272 // scenarios ... because of the 2-step activation model of JIT.
273 ctorCallMsg.Activator = new ConstructionLevelActivator();
276 // Ask all attributes if they are happy with the current context
277 // NOTE: if someone says no, we do not ask the rest of the attributes
278 // This is why, womAttr (which is the global activation service
279 // attribute) *must* be the first one we query.
280 bool bCtxOK = QueryAttributesIfContextOK(cliCtx,
285 bCtxOK = QueryAttributesIfContextOK(cliCtx,
290 bCtxOK = QueryAttributesIfContextOK(cliCtx,
299 [System.Security.SecurityCritical] // auto-generated
300 private static void CheckForInfrastructurePermission(RuntimeAssembly asm)
302 // Make a security check to ensure that the context attribute
303 // is from a trusted assembly!
304 if (asm != s_MscorlibAssembly)
306 SecurityPermission remotingInfrastructurePermission = new SecurityPermission(SecurityPermissionFlag.Infrastructure);
307 CodeAccessSecurityEngine.CheckAssembly(asm, remotingInfrastructurePermission);
311 [System.Security.SecurityCritical] // auto-generated
312 private static bool QueryAttributesIfContextOK(
313 Context ctx, IConstructionCallMessage ctorMsg, Object[] attributes)
316 if (attributes != null)
318 for (int i=0; i<attributes.Length; i++)
320 // All the attributes, including callsite attributes should
321 // expose IContextAttribute. If not, then we throw an
323 IContextAttribute attr = attributes[i] as IContextAttribute;
326 RuntimeAssembly asm = (RuntimeAssembly)attr.GetType().Assembly;
327 // Make a security check to ensure that the context attribute
328 // is from a trusted assembly!
329 CheckForInfrastructurePermission(asm);
331 bCtxOK = attr.IsContextOK(ctx, ctorMsg);
339 throw new RemotingException(
340 Environment.GetResourceString(
341 "Remoting_Activation_BadAttribute"));
348 [System.Security.SecurityCritical] // auto-generated
349 internal static void GetPropertiesFromAttributes(
350 IConstructionCallMessage ctorMsg, Object[] attributes)
352 if (attributes != null)
354 for (int i=0; i<attributes.Length; i++)
356 // All the attributes, including callsite attributes should
357 // expose IContextAttribute. If not, then we throw an
359 IContextAttribute attr = attributes[i] as IContextAttribute;
362 RuntimeAssembly asm = (RuntimeAssembly)attr.GetType().Assembly;
363 // Make a security check to ensure that the context attribute
364 // is from a trusted assembly!
365 CheckForInfrastructurePermission(asm);
367 // We ask each attribute to contribute its properties.
368 // The attributes can examine the current list of properties
369 // from the ctorCallMsg and decide which properties to add.
371 // They can also tweak the Activator chain during this process
372 attr.GetPropertiesForNewContext(ctorMsg);
376 throw new RemotingException(
377 Environment.GetResourceString(
378 "Remoting_Activation_BadAttribute"));
384 // Return the default implementation of the proxy attribute
385 internal static ProxyAttribute DefaultProxyAttribute
387 [System.Security.SecurityCritical] // auto-generated
388 get { return _proxyAttribute; }
391 // Iterate over the custom attributes of the class and see if it
392 // defines a ProxyAttribute. If one is not defined then return
393 // the default proxy attribute defined by us.
394 [System.Security.SecurityCritical] // auto-generated
395 internal static ProxyAttribute GetProxyAttribute(Type serverType)
399 serverType.IsMarshalByRef,
400 "type should be at least marshal-by-ref");
402 if (!serverType.HasProxyAttribute)
403 return DefaultProxyAttribute;
405 // Type has a non-default proxy attribute ... see if we have
407 ProxyAttribute pa = _proxyTable[serverType] as ProxyAttribute;
411 Object[] ca = Attribute.GetCustomAttributes(
415 if((null != ca) && (0 != ca.Length))
417 if (!serverType.IsContextful)
419 throw new RemotingException(
420 Environment.GetResourceString(
421 "Remoting_Activation_MBR_ProxyAttribute"));
423 pa = ca[0] as ProxyAttribute;
425 Contract.Assert(pa!=null, "expect proxy attribute");
427 if(!_proxyTable.Contains(serverType))
431 if(!_proxyTable.Contains(serverType))
433 // Create a new entry
434 _proxyTable.Add(serverType, pa);
443 // Creates either an uninitialized object or a proxy depending on
444 // whether the current context is OK or not.
445 [System.Security.SecurityCritical] // auto-generated
446 internal static MarshalByRefObject CreateInstance(RuntimeType serverType)
448 // Use our activation implementation
449 MarshalByRefObject retObj = null;
450 ConstructorCallMessage ctorCallMsg = null;
451 bool bCtxOK = IsCurrentContextOK(serverType, null, ref ctorCallMsg);
452 if (bCtxOK && !serverType.IsContextful)
454 // Marshal by ref case
455 Message.DebugOut("Allocating blank marshal-by-ref object");
456 // We create an uninitialized instance of the actual type and
457 // let the regular jit-activation execute the constructor on it.
458 retObj = RemotingServices.AllocateUninitializedObject(serverType);
462 // (context not OK) || (serverType is Contextful)
463 // We always return a proxy and the jit-activation's attempt
464 // to execute the constructor gets intercepted by the TP stub
465 // and routed to RemotingServices.Activate() below.
467 // if context *is* OK
468 // this is a contextBound type being activated for which
469 // we always create a proxy (proxies-everywhere!)
471 // if context *is not* OK
472 // this could be a MarshalByRef or ContextBound type
473 // being activated outside this appDomain
475 // this could be a ContextBound type being activated cross-ctx
478 // See if the object-type is configured for Connect (with a URL)
479 retObj = (MarshalByRefObject)ConnectIfNecessary(ctorCallMsg);
482 // not configured for connect, take the usual route of
484 Message.DebugOut("Creating remoting proxy for " +
485 serverType.FullName + " in context " +
486 Thread.CurrentContext);
488 rp = new RemotingProxy(serverType);
490 Message.DebugOut("Created remoting proxy\n");
491 retObj = (MarshalByRefObject)rp.GetTransparentProxy();
495 Message.DebugOut("NewObj did a Connect!");
496 rp = (RemotingProxy)RemotingServices.GetRealProxy(retObj);
499 // Store the constructor call message in the proxy
500 rp.ConstructorMessage = ctorCallMsg;
505 // Chain in the context level activator now
506 ContextLevelActivator activator = new ContextLevelActivator();
507 activator.NextActivator = ctorCallMsg.Activator;
508 ctorCallMsg.Activator = activator;
512 // Set the flag to indicate that the activation
513 // will not be leaving the client context .. in this case
514 // the default construction level activator is enough
515 // to complete the activation process.
516 ctorCallMsg.ActivateInContext = true;
524 // NOTE: This is an internal method used by RemotingProxy to do Activation
526 // Starts off the activation chain by sending the constructor call message to
527 // the activator or the client context sink chain. On return, a constructor
528 // return message is made and the out parameters are propagated.
530 [System.Security.SecurityCritical] // auto-generated
531 internal static IConstructionReturnMessage Activate(
532 RemotingProxy remProxy, IConstructionCallMessage ctorMsg)
534 IConstructionReturnMessage ctorRetMsg = null;
536 if (((ConstructorCallMessage)ctorMsg).ActivateInContext)
538 // The current context was approved for activation
540 ctorMsg.Activator.Level == ActivatorLevel.Construction,
541 "activator level must ActivatorLevel.Construction!");
543 // This has to be a ContextBound type (proxies-everywhere)
544 Contract.Assert(ctorMsg.ActivationType.IsContextful,
545 "Inconsistent state during activation");
547 // Ask the activator in the message to take over
548 ctorRetMsg = ctorMsg.Activator.Activate(ctorMsg);
550 if (ctorRetMsg.Exception != null)
552 throw ctorRetMsg.Exception;
557 // Client context was not approved for activation ...
559 ctorMsg.Activator.Level >= ActivatorLevel.Context,
560 "activator level must be at least x-context!");
562 // Check with ActivationServices if we did a "Connect" with
563 // a remote server during IsContextOK
565 ActivationServices.CheckIfConnected(remProxy, ctorMsg) == null,
566 "We shouldn't come through this path on a Connect.");
568 // Client context was not approved for activation ...
569 // This is the more elaborate (real) activation case i.e.
570 // we have to go at least out of the client context to
573 // Prepare for the handoff to Activation Service
575 // Ask various attributes to contribute properties
576 // The attributes may chain in other activators into
577 // the activation chain (to hijack/participate in
578 // the activation process).
579 ActivationServices.GetPropertiesFromAttributes(
580 (IConstructionCallMessage)ctorMsg,
581 ctorMsg.CallSiteActivationAttributes);
583 ActivationServices.GetPropertiesFromAttributes(
585 ((ConstructorCallMessage)ctorMsg).GetWOMAttributes());
587 ActivationServices.GetPropertiesFromAttributes(
588 (IConstructionCallMessage)ctorMsg,
589 ((ConstructorCallMessage)ctorMsg).GetTypeAttributes());
591 // Fetch the client context chain
592 IMessageSink cliCtxChain =
593 Thread.CurrentContext.GetClientContextChain();
595 // Ask the client context chain to take over from here.
596 IMethodReturnMessage retMsg =
597 (IMethodReturnMessage)
598 cliCtxChain.SyncProcessMessage(ctorMsg);
600 // The return message may not be of type
601 // IConstructionReturnMessage if an exception happens
602 // in the sink chains.
603 ctorRetMsg = retMsg as IConstructionReturnMessage;
606 throw new RemotingException(
607 Environment.GetResourceString(
608 "Remoting_Activation_Failed"));
610 else if (retMsg.Exception != null)
612 throw retMsg.Exception;
615 // Note: PropagateOutParameters is now handled by RealProxy
616 // CallContext from retMsg should be already set by RealProxy
619 "Activate returning null ConstructorReturnMessage");
624 // This function is called by ActivationServices in case
625 // the activation needs to be within the same appdomain. These
626 // are only for ContextBound types.
627 // It is also called to do satisfy remote incoming requests from
628 // the activation services. These could be for both ContextBound
629 // and MarshalByRef types.
630 [System.Security.SecurityCritical] // auto-generated
631 internal static IConstructionReturnMessage DoCrossContextActivation(
632 IConstructionCallMessage reqMsg)
634 bool bCtxBound = reqMsg.ActivationType.IsContextful;
635 Context serverContext = null;
639 // If the type is context bound, we need to create
640 // the appropriate context and activate the object inside
644 // Create a new Context
645 serverContext = new Context();
652 ArrayList list = (ArrayList) reqMsg.ContextProperties;
653 RuntimeAssembly asm = null;
654 for (int i=0; i<list.Count; i++)
656 IContextProperty prop = list[i] as IContextProperty;
659 throw new RemotingException(
660 Environment.GetResourceString(
661 "Remoting_Activation_BadAttribute"));
663 asm = (RuntimeAssembly)prop.GetType().Assembly;
664 // Make a security check to ensure that the context property
665 // is from a trusted assembly!
666 CheckForInfrastructurePermission(asm);
668 // This ensures that we don't try to add duplicate
669 // attributes (eg. type attributes common on both client
671 if (serverContext.GetProperty(prop.Name) == null)
673 serverContext.SetProperty(prop);
676 // No more property changes to the server context from here.
677 serverContext.Freeze();
679 // (This seems like an overkill but that is how it is spec-ed)
680 // Ask each of the properties in the context we formed from
681 // if it is happy with the current context.
682 for (int i=0; i<list.Count;i++)
684 if (!((IContextProperty)list[i]).IsNewContextOK(
687 throw new RemotingException(
688 Environment.GetResourceString(
689 "Remoting_Activation_PropertyUnhappy"));
695 IConstructionReturnMessage replyMsg;
697 InternalCrossContextDelegate xctxDel =
698 new InternalCrossContextDelegate(DoCrossContextActivationCallback);
700 Object[] args = new Object[] { reqMsg };
704 replyMsg = Thread.CurrentThread.InternalCrossContextCallback(
705 serverContext, xctxDel, args) as IConstructionReturnMessage;
709 replyMsg = xctxDel(args) as IConstructionReturnMessage;
715 [System.Security.SecurityCritical] // auto-generated
716 internal static Object DoCrossContextActivationCallback(Object[] args)
718 IConstructionCallMessage reqMsg = (IConstructionCallMessage) args[0];
719 IConstructionReturnMessage replyMsg = null;
721 // call the first sink in the server context chain
723 IMethodReturnMessage retMsg = (IMethodReturnMessage)
724 Thread.CurrentContext.GetServerContextChain().SyncProcessMessage(reqMsg);
726 // The return message may not be of type
727 // IConstructionReturnMessage if an exception happens
728 // in the sink chains.
730 replyMsg = retMsg as IConstructionReturnMessage;
731 if (null == replyMsg)
735 e = retMsg.Exception;
739 e = new RemotingException(
740 Environment.GetResourceString(
741 "Remoting_Activation_Failed"));
744 replyMsg = new ConstructorReturnMessage(e,null);
745 // We have created our own message ... transfer the callcontext
746 // from the request message.
747 ((ConstructorReturnMessage)replyMsg).SetLogicalCallContext(
749 reqMsg.Properties[Message.CallContextKey]);
755 [System.Security.SecurityCritical] // auto-generated
756 internal static IConstructionReturnMessage DoServerContextActivation(
757 IConstructionCallMessage reqMsg)
759 Contract.Assert(reqMsg!=null, "NULL ctorReqMsg");
761 Type serverType = reqMsg.ActivationType;
762 Object serverObj = ActivateWithMessage(
768 IConstructionReturnMessage replyMsg =
769 SetupConstructionReply(serverObj, reqMsg, e);
771 Contract.Assert(replyMsg!=null, "NULL ctorRetMsg");
775 [System.Security.SecurityCritical] // auto-generated
776 internal static IConstructionReturnMessage SetupConstructionReply(
778 IConstructionCallMessage ctorMsg,
781 IConstructionReturnMessage replyMsg = null;
785 new ConstructorReturnMessage(
786 (MarshalByRefObject)serverObj,
788 // if ctor-s with ref/out are supported</
791 ctorMsg.Properties[Message.CallContextKey],
796 replyMsg = new ConstructorReturnMessage(e,null);
797 // We have created our own message ... transfer the callcontext
798 // from the request message.
799 ((ConstructorReturnMessage)replyMsg).SetLogicalCallContext(
801 ctorMsg.Properties[Message.CallContextKey]);
807 [System.Security.SecurityCritical] // auto-generated
808 internal static Object ActivateWithMessage(
809 Type serverType, IMessage msg, ServerIdentity srvIdToBind,
812 Object server = null;
815 // Create a blank instance!
816 server = RemotingServices.AllocateUninitializedObject(serverType);
818 Object proxyForObject = null;
819 if (serverType.IsContextful)
821 if (msg is ConstructorCallMessage)
823 // If it is a strictly x-context activation then
824 // this pointer for the message is the TP that we
825 // returned to JIT in first phase of activation
826 proxyForObject = ((ConstructorCallMessage)msg).GetThisPtr();
830 // we are out of the app-domain, so wrap this object now
831 proxyForObject = null;
834 // This associates the proxy with the real object and sets
835 // up the proxy's native context, ID etc.
836 proxyForObject = RemotingServices.Wrap(
837 (ContextBoundObject)server,
841 RemotingServices.IsTransparentProxy(proxyForObject),
842 "Wrapped object should be a transparent proxy");
846 // Since this is an MBR type, something really bad
847 // happened if we are not in the default context
848 if (Thread.CurrentContext != Context.DefaultContext)
850 throw new RemotingException(
851 Environment.GetResourceString(
852 "Remoting_Activation_Failed"));
854 // Marshal-by-ref case we just return the object
855 proxyForObject = server;
858 // Create the dispatcher which will help run the CTOR
859 IMessageSink dispatcher = (IMessageSink)new StackBuilderSink(proxyForObject);
861 // This call runs the CTOR on the object
862 IMethodReturnMessage retMsg = (IMethodReturnMessage)
863 dispatcher.SyncProcessMessage(msg);
865 if (retMsg.Exception == null)
867 if (serverType.IsContextful)
869 // call wrap to finish the operation.
870 return RemotingServices.Wrap((ContextBoundObject)server);
879 e = retMsg.Exception;
884 [System.Security.SecurityCritical] // auto-generated
885 internal static void StartListeningForRemoteRequests()
887 // Get the activation services set up.
889 DomainSpecificRemotingData remData = Thread.GetDomain().RemotingData;
890 if (!remData.ActivatorListening)
892 Object configLock = remData.ConfigLock;
893 bool fLocked = false;
894 RuntimeHelpers.PrepareConstrainedRegions();
897 Monitor.Enter(configLock, ref fLocked);
898 if (!remData.ActivatorListening)
900 BCLDebug.Log("Registering remoting activator");
902 // Marshal the object so that it is ready to take remote
903 // calls. We have to create the objref because that is when
904 // the channels start listening for requests.
905 RemotingServices.MarshalInternal(
906 Thread.GetDomain().RemotingData.ActivationListener,
907 ActivationServiceURI,
908 typeof(System.Runtime.Remoting.Activation.IActivator));
910 ServerIdentity srvID = (ServerIdentity)
911 IdentityHolder.ResolveIdentity(ActivationServiceURI);
913 // Set Singleton to prevent lease from being created
914 srvID.SetSingletonObjectMode();
915 //DBG Console.WriteLine("Activator URI: = " + activatorURI);
916 remData.ActivatorListening = true;
923 Monitor.Exit(configLock);
929 // This returns the local activator
930 [System.Security.SecurityCritical] // auto-generated
931 internal static IActivator GetActivator()
933 DomainSpecificRemotingData remData = Thread.GetDomain().RemotingData;
934 if (remData.LocalActivator == null)
938 return (IActivator)remData.LocalActivator;
941 [System.Security.SecurityCritical] // auto-generated
942 internal static void Initialize()
947 // This returns the attribute that takes part in every activation
948 // The local activator itself exposes that functionality
949 [System.Security.SecurityCritical] // auto-generated
950 internal static ContextAttribute GetGlobalAttribute()
952 DomainSpecificRemotingData remData = Thread.GetDomain().RemotingData;
953 if (remData.LocalActivator == null)
957 return (ContextAttribute)remData.LocalActivator;
960 // This function returns the array of custom attributes of
961 // type "ContextAttribute" walking the entire class hierarchy
963 // If duplicates are found the attribute on the more derived
965 // The return array may be sparse and is terminated by a NULL.
966 [System.Security.SecurityCritical]
967 internal static IContextAttribute[] GetContextAttributesForType(Type serverType)
969 if (!(typeof(ContextBoundObject).IsAssignableFrom(serverType)) ||
970 serverType.IsCOMObject)
972 return new ContextAttribute[0];
975 Type currType = serverType;
976 Object[] currAttr = null;
978 IContextAttribute[] retAttr = new IContextAttribute[retSize];
982 // Obtain the custom attributes that implement
983 // IContextAttribute for this type
984 currAttr = currType.GetCustomAttributes(
985 typeof(IContextAttribute),
986 true); // recursively on the typeHierarchy
988 foreach (IContextAttribute attr in currAttr)
990 Type attrType = attr.GetType();
992 for (int i=0; i<numAttr; i++)
994 if (attrType.Equals(retAttr[i].GetType()))
1003 // We must add this attribute to our list
1006 // Check if we have enough space to store it
1007 // Leaving one spot for a NULL value!
1008 if (numAttr > retSize-1)
1010 IContextAttribute[] newAttr = new IContextAttribute[2*retSize];
1012 retAttr, // srcArray
1014 newAttr, // destArray
1016 retSize); // lengthToCopy
1018 retSize = retSize*2;
1020 retAttr[numAttr-1] = attr;
1024 IContextAttribute[] ctxAttr = new IContextAttribute[numAttr];
1025 Array.Copy(retAttr, ctxAttr, numAttr);
1029 // This is called during RS.IsContextOK to check if the new XXX() is configured
1030 // to do a direct connect, and if it is we Connect to the URL and return
1031 // the proxy. In the second stage, when the constructor executes on the proxy
1032 // we will make sure (in Activate) that there are no CTOR args.
1033 [System.Security.SecurityCritical] // auto-generated
1034 internal static Object ConnectIfNecessary(IConstructionCallMessage ctorMsg)
1036 // If the type being instantiated is configured for Connect
1037 // we would have added its URL as the connect key during
1038 // LocalActivator::IsContextOK
1040 // Look for the connect URL
1041 String objURL = (String) ctorMsg.Properties[ConnectKey];
1042 Object proxy = null;
1045 // Connect to the URL and return the proxy
1046 proxy = RemotingServices.Connect(
1047 ctorMsg.ActivationType,
1051 // If the type is not setup for connecting we return null!
1055 // This is really used to distinguish between proxies for completely
1056 // within AppDomain activations and the ones from "Connect" during
1057 // the second stage (RS::Activate)
1058 // For the former, we have to run constructor etc and for the latter
1059 // we have to check that there is no non-defaul CTOR.
1060 [System.Security.SecurityCritical] // auto-generated
1061 internal static Object CheckIfConnected(
1062 RemotingProxy proxy, IConstructionCallMessage ctorMsg)
1064 // If we performed a connect, we must have put the URL as
1065 // the connectKey in the message.
1066 String objURL = (String)
1067 ctorMsg.Properties[ConnectKey];
1072 // We did perform a connect during IsContextOK
1073 // Just get the TP from RP and return it.
1074 tp = (Object)proxy.GetTransparentProxy();
1076 // We return null if we do not recognize this proxy!
1080 internal static void PushActivationAttributes(Type serverType, Object[] attributes)
1082 // There is one such object per thread
1083 if (_attributeStack == null)
1085 _attributeStack = new ActivationAttributeStack();
1087 _attributeStack.Push(serverType, attributes);
1090 internal static Object[] PeekActivationAttributes(Type serverType)
1092 // We can get a peek w/o a prior Push (eg. activation starting
1094 if (_attributeStack == null)
1098 return _attributeStack.Peek(serverType);
1101 internal static void PopActivationAttributes(Type serverType)
1103 Contract.Assert(_attributeStack != null, "Pop w/o a prior Set()?");
1104 _attributeStack.Pop(serverType);
1106 } // class ActivationServices
1109 // This is the local activation helper and also the Attribute
1110 // that gets queried about every activation
1111 [System.Security.SecurityCritical] // auto-generated
1112 internal class LocalActivator: ContextAttribute, IActivator
1114 internal LocalActivator()
1115 : base(ActivationServices.ActivationServiceURI)
1120 // ---------------------------------------------------------------
1121 // ContextAttribute functionality
1122 // ---------------------------------------------------------------
1124 // IContextAttribute::IsContextOK
1125 // This will check if a type is configured for remote activation ...
1126 // We return 'false' for IsContextOK if it is.
1127 [System.Security.SecurityCritical]
1128 public override bool IsContextOK(
1129 Context ctx, IConstructionCallMessage ctorMsg)
1132 // If the app is not using config mechanism, we don't want
1133 // to intercept activation.
1134 if (RemotingConfigHandler.Info == null)
1139 // check if this type is configured for connect
1140 // (instead of remote activate)
1141 RuntimeType activationType = ctorMsg.ActivationType as RuntimeType;
1142 if (activationType == null)
1143 throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"));
1145 WellKnownClientTypeEntry wkte =
1146 RemotingConfigHandler.IsWellKnownClientType(activationType);
1147 String typeURL = (wkte == null ? null : wkte.ObjectUrl);
1149 if (typeURL != null)
1151 // this type does have a direct uri, we will try to connect
1152 // to it during the activate call. Cache it in the message.
1153 ctorMsg.Properties[ActivationServices.ConnectKey] = typeURL;
1158 ActivatedClientTypeEntry acte =
1159 RemotingConfigHandler.IsRemotelyActivatedClientType(activationType);
1161 String appURL = null;
1165 // This is the case where the config file had no entry for this type.
1166 // We should check the callsite attributes for a URL
1167 Object[] callsiteAttributes = ctorMsg.CallSiteActivationAttributes;
1168 if(null != callsiteAttributes)
1170 for(int i = 0; i < callsiteAttributes.Length; i++)
1172 UrlAttribute attr = callsiteAttributes[i] as UrlAttribute;
1175 appURL = attr.UrlValue;
1182 // We don't really care about intercepting the activation in this case.
1188 appURL = acte.ApplicationUrl;
1191 // Generate the URL of the remote activator
1192 String activatorURL = null;
1193 if (!appURL.EndsWith("/", StringComparison.Ordinal))
1194 activatorURL = appURL + "/" + ActivationServices.ActivationServiceURI;
1196 activatorURL = appURL + ActivationServices.ActivationServiceURI;
1198 // Mark a flag for remote activation
1199 // (caching the url of the activation svc of the remote server)
1200 ctorMsg.Properties[ActivationServices.RemoteActivateKey] = activatorURL;
1205 // IContextAttribute::GetPropertiesForNewContext
1206 [System.Security.SecurityCritical]
1207 public override void GetPropertiesForNewContext(
1208 IConstructionCallMessage ctorMsg)
1210 BCLDebug.Log("ActivationSvc:GlobalAttrib::GetPropForNewCtx");
1211 // This is called during RS::Activate .. when we are sure that
1212 // activation is at least x-context and this is a real activation
1213 // instead of a spoofed connect underneath the "new".
1214 Contract.Assert(ctorMsg!=null, "ctorMsg null?");
1215 if (ctorMsg.Properties.Contains(ActivationServices.RemoteActivateKey))
1217 // Means we did want to intercept activation!
1218 String remActivatorURL = (String)
1219 ctorMsg.Properties[ActivationServices.RemoteActivateKey];
1221 AppDomainLevelActivator activator =
1222 new AppDomainLevelActivator(remActivatorURL);
1223 // Chain ourselves at the end of the AppDomainLevel activators
1225 ctorMsg.Activator != null,
1226 "Should have at least x-context activator");
1227 IActivator curr = ctorMsg.Activator;
1229 if (curr.Level < ActivatorLevel.AppDomain)
1231 // Common case .. .only x-context activator(s) in chain
1232 activator.NextActivator = curr;
1233 ctorMsg.Activator = activator;
1235 else if (curr.NextActivator == null)
1237 // Only one activator but not ContextLevel ...
1238 // We go at the end of the chain
1239 curr.NextActivator = activator;
1243 // We will have to walk the chain till the end of the last
1244 // AD activator and plug ourselves in.
1245 while (curr.NextActivator.Level >= ActivatorLevel.AppDomain)
1247 curr = curr.NextActivator;
1250 curr.NextActivator.Level.Equals(ActivatorLevel.Context),
1251 "bad ordering of activators!");
1252 activator.NextActivator = curr.NextActivator;
1253 curr.NextActivator = activator;
1258 // ---------------------------------------------------------------
1259 // IActivator functionality
1260 // ---------------------------------------------------------------
1261 //IActivator::NextActivator
1262 public virtual IActivator NextActivator
1264 // We are a singleton internal infrastructure object.
1265 [System.Security.SecurityCritical]
1266 get { return null; }
1267 // Don't allow a set either.
1268 [System.Security.SecurityCritical]
1269 set { throw new InvalidOperationException(); }
1272 //IActivator::ActivatorLevel
1273 public virtual ActivatorLevel Level
1275 [System.Security.SecurityCritical]
1276 get { return ActivatorLevel.AppDomain; }
1279 private static MethodBase GetMethodBase(IConstructionCallMessage msg)
1281 MethodBase mb = msg.MethodBase;
1284 BCLDebug.Trace("REMOTE", "Method missing w/name ", msg.MethodName);
1285 throw new RemotingException(
1287 CultureInfo.CurrentCulture, Environment.GetResourceString(
1288 "Remoting_Message_MethodMissing"),
1296 //IActivator::Activate
1297 [System.Security.SecurityCritical]
1298 [System.Runtime.InteropServices.ComVisible(true)]
1299 public virtual IConstructionReturnMessage Activate(
1300 IConstructionCallMessage ctorMsg)
1302 // This is where the activation service hooks in to activation
1303 // requests. We get called as the activation message is recognized
1304 // by the ClientContextTerminatorSink & routed to us.
1306 // NOTE: This gets called for both purely within appDomain activation
1307 // and 'real' remote activation scenarios as the request goes out of
1308 // the client context.
1309 // It also gets called as an incoming remote call is routed to the
1310 // local activator by the remote activator object.
1312 BCLDebug.Log("Activation Services:: new Activate()");
1313 if (ctorMsg == null)
1315 throw new ArgumentNullException("ctorMsg");
1317 Contract.EndContractBlock();
1319 // Check if we have marked this activation to go remote
1320 if (ctorMsg.Properties.Contains(ActivationServices.RemoteActivateKey))
1322 //DBG Console.WriteLine("Attempting remote activation!");
1324 return DoRemoteActivation(ctorMsg);
1328 // We must be in either a pure cross context activation or
1329 // a remote incoming activation request (in which case we
1330 // already checked the permission to create an instance of
1332 if (ctorMsg.Properties.Contains(ActivationServices.PermissionKey))
1334 Type activationType = ctorMsg.ActivationType;
1336 // We are on the server end of a real remote activation
1337 // Create a local attribute that contributes the context
1338 // properties requested by the remote request
1339 Object[] attr = null;
1340 if (activationType.IsContextful)
1342 IList cp = ctorMsg.ContextProperties;
1343 if (cp != null && cp.Count > 0)
1345 RemotePropertyHolderAttribute rph = new RemotePropertyHolderAttribute(cp);
1346 attr = new Object[1];
1350 MethodBase mb = GetMethodBase(ctorMsg);
1351 RemotingMethodCachedData methodCache =
1352 InternalRemotingServices.GetReflectionCachedData(mb);
1353 Object[] args = Message.CoerceArgs(ctorMsg, methodCache.Parameters);
1355 Object server = Activator.CreateInstance(
1360 // check to see if we need to do redirection
1361 if (RemotingServices.IsClientProxy(server))
1363 // The wellknown type is remoted so we must wrap the proxy
1364 // with a local object.
1366 // The redirection proxy masquerades as an object of the appropriate
1367 // type, and forwards incoming messages to the actual proxy.
1368 RedirectionProxy redirectedProxy =
1369 new RedirectionProxy((MarshalByRefObject)server, activationType);
1370 RemotingServices.MarshalInternal(redirectedProxy, null, activationType);
1372 server = redirectedProxy;
1375 return ActivationServices.SetupConstructionReply(
1376 server, ctorMsg, null);
1380 BCLDebug.Log("Attempting X-Context activation!");
1381 // delegate to the Activator in the message
1382 return ctorMsg.Activator.Activate(ctorMsg);
1388 // This is called by the local activator during an outgoing activation
1390 internal static IConstructionReturnMessage DoRemoteActivation(
1391 IConstructionCallMessage ctorMsg)
1393 Contract.Assert(ctorMsg != null, "Null ctorMsg");
1404 BCLDebug.Log("Attempting Connection to remote activation service");
1405 IActivator remActivator = null;
1406 String remActivatorURL = (String)
1407 ctorMsg.Properties[ActivationServices.RemoteActivateKey];
1410 remActivator = (IActivator)
1411 RemotingServices.Connect(
1412 typeof(System.Runtime.Remoting.Activation.IActivator),
1418 throw new RemotingException(
1420 CultureInfo.CurrentCulture, Environment.GetResourceString(
1421 "Remoting_Activation_ConnectFailed"),
1424 // Remove the remote activate key as its purpose is served.
1425 ctorMsg.Properties.Remove(ActivationServices.RemoteActivateKey);
1427 // Delegate the work to the remote activator
1428 return remActivator.Activate(ctorMsg);
1431 }// class LocalActivator
1433 // This is the object that listens to activation requests
1434 internal class ActivationListener:MarshalByRefObject, IActivator
1436 // Override lifetime services to make this object live forever...
1437 [System.Security.SecurityCritical] // auto-generated
1438 public override Object InitializeLifetimeService()
1443 //IActivator::NextActivator
1444 public virtual IActivator NextActivator
1446 // We are a singleton internal infrastructure object.
1447 [System.Security.SecurityCritical] // auto-generated
1448 get { return null; }
1449 // Don't allow a set either.
1450 [System.Security.SecurityCritical] // auto-generated
1451 set { throw new InvalidOperationException();}
1454 //IActivator::ActivatorLevel
1455 public virtual ActivatorLevel Level
1457 [System.Security.SecurityCritical] // auto-generated
1458 get {return ActivatorLevel.AppDomain;}
1461 //IActivator::Activate
1462 [System.Security.SecurityCritical] // auto-generated
1463 [System.Runtime.InteropServices.ComVisible(true)]
1464 public virtual IConstructionReturnMessage Activate(
1465 IConstructionCallMessage ctorMsg)
1467 BCLDebug.Log("ActivationListener: received new activation request!");
1468 if (ctorMsg == null || RemotingServices.IsTransparentProxy(ctorMsg))
1470 throw new ArgumentNullException("ctorMsg");
1472 Contract.EndContractBlock();
1474 // Add the permission key which distinguishes pure-cross context activation from
1475 // a remote request (both of which go through DoCrossContextActivation)
1476 ctorMsg.Properties[ActivationServices.PermissionKey] = "allowed";
1478 // Check to make sure that this activation type has been allowed.
1479 String activationTypeName = ctorMsg.ActivationTypeName;
1480 if (!RemotingConfigHandler.IsActivationAllowed(activationTypeName))
1482 throw new RemotingException(
1484 CultureInfo.CurrentCulture, Environment.GetResourceString(
1485 "Remoting_Activation_PermissionDenied"),
1486 ctorMsg.ActivationTypeName));
1489 Type activationType = ctorMsg.ActivationType;
1490 if (activationType == null)
1492 throw new RemotingException(
1494 CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_BadType"),
1495 ctorMsg.ActivationTypeName));
1498 // Delegate to the local activator for further work
1499 return ActivationServices.GetActivator().Activate(ctorMsg);
1503 } // class ActivationListener
1506 // This is a lightweight object to help with the activation
1507 // at the appDomain level ... it delegates its work to
1508 // ActivationServices.LocalActivator ... which is a heavy
1509 // object we can't afford to carry around in the ActivatorChain
1510 // (since it may get Serialized/Deserialized)
1512 // attribute .. the latter shall be turned on during Beta-2!</
1513 internal class AppDomainLevelActivator : IActivator
1515 IActivator m_NextActivator;
1518 String m_RemActivatorURL;
1520 internal AppDomainLevelActivator(String remActivatorURL)
1522 Contract.Assert(remActivatorURL!=null,"Bad activator URL");
1523 m_RemActivatorURL = remActivatorURL;
1526 internal AppDomainLevelActivator(SerializationInfo info, StreamingContext context) {
1529 throw new ArgumentNullException("info");
1531 Contract.EndContractBlock();
1532 m_NextActivator = (IActivator) info.GetValue("m_NextActivator",typeof(IActivator));
1535 //IActivator::NextActivator
1536 public virtual IActivator NextActivator
1538 [System.Security.SecurityCritical] // auto-generated
1539 get { return m_NextActivator; }
1540 [System.Security.SecurityCritical] // auto-generated
1541 set { m_NextActivator = value; }
1544 //IActivator::ActivatorLevel
1545 public virtual ActivatorLevel Level
1547 [System.Security.SecurityCritical] // auto-generated
1548 get { return ActivatorLevel.AppDomain; }
1551 //IActivator::Activate
1552 [System.Security.SecurityCritical] // auto-generated
1553 [System.Runtime.InteropServices.ComVisible(true)]
1554 public virtual IConstructionReturnMessage Activate(
1555 IConstructionCallMessage ctorMsg)
1557 // This function will get invoked when the ClientContextTerminator sink
1558 // notices that an activation request message is passed to it ... it
1559 // will route the message to the Activator present inside the ctorMsg
1560 // (which happens to be us in this case!)
1562 // remove ourselves from the Activator chain
1563 ctorMsg.Activator = m_NextActivator;
1564 return ActivationServices.GetActivator().Activate(ctorMsg);
1568 // This is a lightweight object to help with the activation
1569 // at the context level ...
1571 internal class ContextLevelActivator : IActivator
1573 IActivator m_NextActivator;
1574 internal ContextLevelActivator()
1576 m_NextActivator = null;
1579 internal ContextLevelActivator(SerializationInfo info, StreamingContext context)
1583 throw new ArgumentNullException("info");
1585 Contract.EndContractBlock();
1586 m_NextActivator = (IActivator) info.GetValue("m_NextActivator",typeof(IActivator));
1589 //IActivator::NextActivator
1590 public virtual IActivator NextActivator
1592 [System.Security.SecurityCritical] // auto-generated
1593 get { return m_NextActivator; }
1594 [System.Security.SecurityCritical] // auto-generated
1595 set { m_NextActivator = value; }
1598 //IActivator::ActivatorLevel
1599 public virtual ActivatorLevel Level
1601 [System.Security.SecurityCritical] // auto-generated
1602 get { return ActivatorLevel.Context; }
1605 //IActivator::Activate
1606 [System.Security.SecurityCritical] // auto-generated
1607 [System.Runtime.InteropServices.ComVisible(true)]
1608 public virtual IConstructionReturnMessage Activate(
1609 IConstructionCallMessage ctorMsg)
1611 // remove ourselves from the Activator chain
1612 ctorMsg.Activator = ctorMsg.Activator.NextActivator;
1614 // Delegate to remoting services to do the hard work.
1615 // This will create a context, enter it, run through
1616 // the context sink chain & then delegate to the nex
1617 // activator inside the ctorMsg (quite likely to be
1618 // the default ConstructionLevelActivator)
1619 return ActivationServices.DoCrossContextActivation(ctorMsg);
1623 // This is a lightweight object to help with the activation
1624 // at the appDomain level ... it delegates its work to
1625 // ActivationServices.LocalActivator ... which is a heavy
1626 // object we can't afford to carry around in the ActivatorChain
1627 // (since it may get Serialized/Deserialized)
1629 internal class ConstructionLevelActivator : IActivator
1631 internal ConstructionLevelActivator()
1637 //IActivator::NextActivator
1638 public virtual IActivator NextActivator
1640 // The construction level activator is a terminating activator
1641 [System.Security.SecurityCritical] // auto-generated
1642 get { return null; }
1643 // Throw if someone attempts a set
1644 [System.Security.SecurityCritical] // auto-generated
1645 set { throw new InvalidOperationException(); }
1648 //IActivator::ActivatorLevel
1649 public virtual ActivatorLevel Level
1651 [System.Security.SecurityCritical] // auto-generated
1652 get { return ActivatorLevel.Construction; }
1655 //IActivator::Activate
1656 [System.Security.SecurityCritical] // auto-generated
1657 [System.Runtime.InteropServices.ComVisible(true)]
1658 public virtual IConstructionReturnMessage Activate(
1659 IConstructionCallMessage ctorMsg)
1661 // This function will get invoked when the ClientContextTerminator sink
1662 // notices that an activation request message is passed to it ... it
1663 // will route the message to the Activator present inside the ctorMsg
1664 // (which happens to be us in this case!)
1666 // remove ourselves from the Activator chain
1667 ctorMsg.Activator = ctorMsg.Activator.NextActivator;
1668 return ActivationServices.DoServerContextActivation(ctorMsg);
1672 // This acts as a pseudo call site attribute and transfers
1673 // the context properties carried in from a remote activation request
1674 // to the server side activation
1675 internal class RemotePropertyHolderAttribute : IContextAttribute
1677 IList _cp; // incoming list of context properties
1678 internal RemotePropertyHolderAttribute(IList cp)
1681 Contract.Assert(cp != null && cp.Count > 0,"Bad _cp?");
1683 [System.Security.SecurityCritical] // auto-generated
1684 [System.Runtime.InteropServices.ComVisible(true)]
1685 public virtual bool IsContextOK(Context ctx, IConstructionCallMessage msg)
1687 // The fact that we got instantiated means some remote activation
1688 // has contributed non-default context properties to the ctorMsg
1693 // properties are collected in order from callsite, wom & type
1694 // attributes ... so we get a first shot at adding properties
1695 [System.Security.SecurityCritical] // auto-generated
1696 [System.Runtime.InteropServices.ComVisible(true)]
1697 public virtual void GetPropertiesForNewContext(IConstructionCallMessage ctorMsg)
1699 for (int i=0; i<_cp.Count; i++)
1701 // Just cycle through the list and add the properties to
1702 // the construction message.
1703 // We will throw at a later stage if any of these do not
1704 // implement IContextProperty
1705 ctorMsg.ContextProperties.Add(_cp[i]);
1710 // Note: One instance of this class is setup per thread that comes to
1711 // managed remoting for activation of MBR types. All access to methods
1712 // is by design single-threaded. (Each thread is working on its own object).
1714 // In the case of Activator.CreateInstance ... that API does the Push &
1715 // Remoting does a Pop() as soon as it has picked up the attributes from
1716 // the threadStatic. The CreateInstance API itself does a Pop() too in
1717 // a try-finally. (So this does not work very well if the infrastructure
1718 // creates an instance of the same MBR type as the outer type being created.
1719 // However, to minimize code churn this is the least risky fix we can do.
1720 // The full fix would be to pass activationAttributes into the VM through
1721 // reflection code and have the VM pass them over to remoting which will
1722 // then hand them over to managed remoting helpers. This will also involve
1723 // adding attributes as an additional parameter to
1724 // ProxyAttribute.CreateInstance() public method.
1726 internal class ActivationAttributeStack
1728 Object[] activationTypes;
1729 Object[] activationAttributes;
1731 internal ActivationAttributeStack()
1733 activationTypes = new Object[4];
1734 activationAttributes = new Object[4];
1738 internal void Push(Type typ, Object[] attr)
1740 Contract.Assert(typ!=null, "typ != null");
1741 Contract.Assert(attr!=null, "attr != null");
1743 if (freeIndex == activationTypes.Length)
1745 // Need to grow our arrays ... this will be exceedingly rare
1746 Object[] newTypes = new Object[activationTypes.Length * 2];
1747 Object[] newAttr = new Object[activationAttributes.Length * 2];
1748 Contract.Assert(newAttr.Length == newTypes.Length,"These should be in sync!");
1749 Array.Copy(activationTypes, newTypes, activationTypes.Length);
1750 Array.Copy(activationAttributes, newAttr, activationAttributes.Length);
1751 activationTypes = newTypes;
1752 activationAttributes = newAttr;
1754 activationTypes[freeIndex] = typ;
1755 activationAttributes[freeIndex] = attr;
1759 internal Object[] Peek(Type typ)
1761 Contract.Assert(typ!=null, "typ != null");
1762 if (freeIndex == 0 || activationTypes[freeIndex-1] != (object)typ)
1766 return (Object[])activationAttributes[freeIndex-1];
1769 // Note: Read the comments above .. you can have 2 pops for the same
1770 // push. We also count on infrastructure code not activating
1771 // the same type as the caller causing a recursive activation.
1772 internal void Pop(Type typ)
1774 Contract.Assert(typ!=null, "typ != null");
1775 if (freeIndex != 0 && activationTypes[freeIndex-1] == (object)typ)
1778 // Clear the popped entry
1779 activationTypes[freeIndex] = null;
1780 activationAttributes[freeIndex] = null;