Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / mscorlib / system / runtime / remoting / activationservices.cs
1 // ==++==
2 // 
3 //   Copyright (c) Microsoft Corporation.  All rights reserved.
4 // 
5 // ==--==
6 /*============================================================
7 **
8 **  File:    ActivationServices.cs
9 **
10 **  Author(s):  
11 **
12 **  Purpose:           
13 **
14 **
15 ===========================================================*/
16 namespace System.Runtime.Remoting.Activation {
17
18     using System;
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;
29     using System.IO;
30     using System.Runtime.Serialization;
31     using System.Security.Permissions;
32     using System.Globalization;
33     using System.Runtime.CompilerServices;
34     using System.Diagnostics.Contracts;
35
36     // Implements various activation services
37     internal static class ActivationServices
38     {
39
40         private static volatile IActivator activator = null;     
41         
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;
49
50         internal const String ActivationServiceURI = "RemoteActivationService.rem";
51
52         internal const String RemoteActivateKey = "Remote";
53         internal const String PermissionKey = "Permission";
54         internal const String ConnectKey = "Connect";
55
56         [System.Security.SecuritySafeCritical] // static constructors should be safe to call
57         static ActivationServices()
58         { }
59
60         // <
61
62
63
64
65
66         //1 private static LocalActivator  localActivator = null;
67
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;
72
73         //3 private static Object staticSyncObject = new Object();
74         //4 private static bool bInitializing = false;
75
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()
80         {            
81             DomainSpecificRemotingData remData = Thread.GetDomain().RemotingData;
82
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)
87             {
88                 Object configLock = remData.ConfigLock;
89                 bool fLocked = false;
90                 RuntimeHelpers.PrepareConstrainedRegions();
91                 try
92                 {
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)
98                     {
99                         // Startup the activation service
100                         BCLDebug.Trace("REMOTE","Starting up activation service ",Thread.CurrentContext);
101
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();
108
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
113
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;
118
119                         remData.ActivationListener = new ActivationListener();
120                         remData.ActivationInitialized = true;
121
122                     }
123                     
124                     remData.InitializingActivation = false;
125                 } //lock (remData)
126                 finally
127                 {
128                     if (fLocked)
129                     {
130                         Monitor.Exit(configLock);
131                     }
132                 }
133             }
134         }            
135            
136         [System.Security.SecurityCritical]  // auto-generated
137         private static void InitActivationServices()
138         {
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)
142             {
143                 activator = GetActivator();
144                 if (null == activator)
145                 {
146                     Message.DebugOut("Fatal Error... Could not create activator\n");                
147                     throw new RemotingException(
148                         String.Format(
149                             CultureInfo.CurrentCulture, Environment.GetResourceString(
150                                 "Remoting_BadInternalState_ActivationFailure")));
151                 }
152             }
153         }
154
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)
159         {
160             Contract.Assert(!serverType.IsInterface,"!serverType.IsInterface");
161
162             MarshalByRefObject retObj = null;
163             
164             // Initialize activation services if needed.
165             //   (we temporary null out the activation attributes in case
166             //    InitActivationServices creates an MBR).            
167             InitActivationServices();            
168             
169             // Obtain the method info which will create an instance 
170             // of type RealProxy
171             ProxyAttribute pa = GetProxyAttribute(serverType);
172             Contract.Assert(null != pa, "null != pa");
173
174             if (Object.ReferenceEquals(pa, DefaultProxyAttribute))
175                 retObj = pa.CreateInstanceInternal(serverType);
176             else            
177             {
178                 retObj = pa.CreateInstance(serverType);
179                 // We called a custom proxy attribute .. make sure it is 
180                 // returning a server of the correct type.
181                 if (retObj != null)
182                 {
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()))
188                     {
189                         throw new RemotingException(
190                             String.Format(
191                                 CultureInfo.CurrentCulture, Environment.GetResourceString(
192                                     "Remoting_Activation_BadObject"),
193                             serverType));
194                     }
195                 }
196             }
197             Contract.Assert(null != retObj, "null != retObj");
198             return retObj;
199         }
200
201         [System.Security.SecurityCritical]  // auto-generated
202         private static MarshalByRefObject CreateObjectForCom(
203             RuntimeType serverType, Object[] props, bool bNewObj)
204         {
205             Contract.Assert(!serverType.IsInterface,"!serverType.IsInterface");
206
207             MarshalByRefObject retObj = null;
208             
209             if (PeekActivationAttributes(serverType) != null)
210                 throw new NotSupportedException(Environment.GetResourceString("NotSupported_ActivForCom" ));
211
212             // Initialize activation services if needed
213             InitActivationServices();
214                                                
215             // Obtain the method info which will create an instance 
216             // of type RealProxy
217             ProxyAttribute pa = GetProxyAttribute(serverType);
218             Contract.Assert(null != pa, "null != pa");
219
220             if(pa is ICustomFactory)
221             {
222                 retObj = ((ICustomFactory)pa).CreateInstance(serverType);
223             }
224             else
225             {
226                 retObj = (MarshalByRefObject)Activator.CreateInstance(serverType, true);
227             }
228
229             Contract.Assert(null != retObj, "null != retObj");
230             return retObj;
231         }
232
233         // For types with no proxy attribute, we take the default route of 
234         // querying attributes if the current context is suitable for 
235         // activation.
236         [System.Security.SecurityCritical]  // auto-generated
237         private static bool IsCurrentContextOK(RuntimeType serverType, Object[] props, 
238                                                ref ConstructorCallMessage ctorCallMsg)
239         {
240              //Get callSite attributes
241             Object[] callSiteAttr = PeekActivationAttributes(serverType);
242
243             // Clear from the attribute stack
244             if (callSiteAttr != null)
245             {
246                 PopActivationAttributes(serverType);
247             }
248             
249             Object[] womAttr = new Object[1];
250             womAttr[0] = GetGlobalAttribute();
251
252             // Get the type context attributes
253             Object[] typeAttr = GetContextAttributesForType(serverType);
254
255             // Get the client context (current context)                                                             
256             Context cliCtx = Thread.CurrentContext;
257
258             // Create a ctorCallMsg with the reqd info 
259             ctorCallMsg = 
260                 new ConstructorCallMessage(
261                     callSiteAttr,
262                     womAttr,
263                     typeAttr,
264                     serverType);
265
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();
274
275
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, 
281                                                      ctorCallMsg,
282                                                      womAttr);
283             if (bCtxOK == true)
284             {
285                 bCtxOK = QueryAttributesIfContextOK(cliCtx, 
286                                                     ctorCallMsg,
287                                                     callSiteAttr);
288                 if (bCtxOK == true)
289                 {
290                     bCtxOK = QueryAttributesIfContextOK(cliCtx, 
291                                                         ctorCallMsg,
292                                                         typeAttr);
293                 }
294             }
295
296             return bCtxOK;
297         }
298
299         [System.Security.SecurityCritical]  // auto-generated
300         private static void CheckForInfrastructurePermission(RuntimeAssembly asm)
301         {
302             // Make a security check to ensure that the context attribute
303             // is from a trusted assembly!
304             if (asm != s_MscorlibAssembly)
305             {
306                 SecurityPermission remotingInfrastructurePermission = new SecurityPermission(SecurityPermissionFlag.Infrastructure);
307                 CodeAccessSecurityEngine.CheckAssembly(asm, remotingInfrastructurePermission);
308             }
309         }
310
311         [System.Security.SecurityCritical]  // auto-generated
312         private static bool QueryAttributesIfContextOK(
313             Context ctx, IConstructionCallMessage ctorMsg, Object[] attributes) 
314         {       
315             bool bCtxOK = true;
316             if (attributes != null)
317             {
318                 for (int i=0; i<attributes.Length; i++)
319                 {
320                     // All the attributes, including callsite attributes should 
321                     // expose IContextAttribute. If not, then we throw an 
322                     // exception.
323                     IContextAttribute attr = attributes[i] as IContextAttribute;
324                     if(null != attr)
325                     { 
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);
330                     
331                         bCtxOK = attr.IsContextOK(ctx, ctorMsg);
332                         if (bCtxOK == false)
333                         {
334                             break;
335                         }
336                     }                        
337                     else
338                     {
339                         throw new RemotingException(
340                                 Environment.GetResourceString(
341                                     "Remoting_Activation_BadAttribute"));
342                     }
343                 }
344             }
345             return bCtxOK;
346         }
347
348         [System.Security.SecurityCritical]  // auto-generated
349         internal static void GetPropertiesFromAttributes(
350             IConstructionCallMessage ctorMsg, Object[] attributes)
351         {
352             if (attributes != null)
353             {
354                 for (int i=0; i<attributes.Length; i++)
355                 {
356                     // All the attributes, including callsite attributes should 
357                     // expose IContextAttribute. If not, then we throw an 
358                     // exception.
359                     IContextAttribute attr = attributes[i] as IContextAttribute;
360                     if(null != attr) 
361                     {
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);
366                     
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.
370
371                         // They can also tweak the Activator chain during this process
372                         attr.GetPropertiesForNewContext(ctorMsg);
373                     }
374                     else
375                     {
376                         throw new RemotingException(
377                             Environment.GetResourceString(
378                                 "Remoting_Activation_BadAttribute"));
379                     }
380                 }
381             }
382         }
383
384         // Return the default implementation of the proxy attribute
385         internal static ProxyAttribute DefaultProxyAttribute
386         {
387             [System.Security.SecurityCritical]  // auto-generated
388             get { return _proxyAttribute; }
389         }
390
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)
396         {
397             
398             Contract.Assert(    
399                 serverType.IsMarshalByRef,
400                 "type should be at least marshal-by-ref");
401
402             if (!serverType.HasProxyAttribute)
403                 return DefaultProxyAttribute;
404                     
405             // Type has a non-default proxy attribute ... see if we have
406             // it cached?
407             ProxyAttribute pa = _proxyTable[serverType] as ProxyAttribute;
408
409             if (pa == null)
410             {   
411                 Object[] ca = Attribute.GetCustomAttributes(
412                                             serverType, 
413                                             proxyAttributeType, 
414                                             true);
415                 if((null != ca) && (0 != ca.Length))
416                 {                    
417                     if (!serverType.IsContextful)
418                     {
419                         throw new RemotingException(
420                                     Environment.GetResourceString(
421                                     "Remoting_Activation_MBR_ProxyAttribute"));
422                     }
423                     pa = ca[0] as ProxyAttribute;
424                 }
425                 Contract.Assert(pa!=null, "expect proxy attribute");
426
427                 if(!_proxyTable.Contains(serverType))
428                 {
429                     lock(_proxyTable)
430                     {
431                         if(!_proxyTable.Contains(serverType))
432                         {
433                             // Create a new entry
434                             _proxyTable.Add(serverType, pa);
435                         }
436                     }                    
437                 }
438             }
439
440             return pa;
441         }
442
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)
447         {
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)
453             {
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);
459             }
460             else 
461             {
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.
466
467                 // if context *is* OK 
468                 // this is a contextBound type being activated for which 
469                 // we always create a proxy (proxies-everywhere!)
470
471                 // if context *is not* OK 
472                 // this could be a MarshalByRef or ContextBound type 
473                 // being activated outside this appDomain 
474                 // OR
475                 // this could be a ContextBound type being activated cross-ctx 
476
477                 RemotingProxy rp;
478                 // See if the object-type is configured for Connect (with a URL)
479                 retObj = (MarshalByRefObject)ConnectIfNecessary(ctorCallMsg);
480                 if (retObj == null)
481                 {
482                     // not configured for connect, take the usual route of 
483                     // creating a proxy
484                     Message.DebugOut("Creating remoting proxy for " + 
485                                  serverType.FullName + " in context " + 
486                                  Thread.CurrentContext);  
487
488                     rp = new RemotingProxy(serverType);
489
490                     Message.DebugOut("Created remoting proxy\n");
491                     retObj = (MarshalByRefObject)rp.GetTransparentProxy();
492                 }
493                 else
494                 {
495                     Message.DebugOut("NewObj did a Connect!");
496                     rp = (RemotingProxy)RemotingServices.GetRealProxy(retObj);                    
497                 }                    
498
499                 // Store the constructor call message in the proxy
500                 rp.ConstructorMessage = ctorCallMsg;
501
502                 if (!bCtxOK)
503                 {
504
505                     // Chain in the context level activator now
506                     ContextLevelActivator activator = new ContextLevelActivator();
507                     activator.NextActivator = ctorCallMsg.Activator; 
508                     ctorCallMsg.Activator = activator;
509                 }
510                 else
511                 {
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;
517                 }
518             }
519
520             return retObj;
521         }
522
523         //
524         // NOTE: This is an internal method used by RemotingProxy to do Activation
525         // 
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.
529         //
530         [System.Security.SecurityCritical]  // auto-generated
531         internal static IConstructionReturnMessage Activate(
532             RemotingProxy remProxy, IConstructionCallMessage ctorMsg)
533         {
534             IConstructionReturnMessage ctorRetMsg = null;
535
536             if (((ConstructorCallMessage)ctorMsg).ActivateInContext)
537             {
538                 // The current context was approved for activation
539                 Contract.Assert(
540                     ctorMsg.Activator.Level == ActivatorLevel.Construction,
541                     "activator level must ActivatorLevel.Construction!");
542
543                 // This has to be a ContextBound type (proxies-everywhere)
544                 Contract.Assert(ctorMsg.ActivationType.IsContextful, 
545                                 "Inconsistent state during activation");
546
547                 // Ask the activator in the message to take over
548                 ctorRetMsg = ctorMsg.Activator.Activate(ctorMsg);
549
550                 if (ctorRetMsg.Exception != null)
551                 {
552                     throw ctorRetMsg.Exception;
553                 }
554             }
555             else
556             {
557                 // Client context was not approved for activation ...
558                 Contract.Assert(
559                     ctorMsg.Activator.Level >= ActivatorLevel.Context,
560                     "activator level must be at least x-context!");
561
562                 // Check with ActivationServices if we did a "Connect" with
563                 // a remote server during IsContextOK
564                 Contract.Assert(
565                     ActivationServices.CheckIfConnected(remProxy, ctorMsg) == null,
566                     "We shouldn't come through this path on a Connect.");                    
567
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 
571                 // finish the work.
572
573                 // Prepare for the handoff to Activation Service
574
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);
582
583                 ActivationServices.GetPropertiesFromAttributes(
584                     ctorMsg, 
585                     ((ConstructorCallMessage)ctorMsg).GetWOMAttributes());
586
587                 ActivationServices.GetPropertiesFromAttributes(
588                     (IConstructionCallMessage)ctorMsg, 
589                 ((ConstructorCallMessage)ctorMsg).GetTypeAttributes());       
590
591                 // Fetch the client context chain
592                 IMessageSink cliCtxChain = 
593                 Thread.CurrentContext.GetClientContextChain();
594
595                 // Ask the client context chain to take over from here.
596                 IMethodReturnMessage retMsg =  
597                     (IMethodReturnMessage)
598                         cliCtxChain.SyncProcessMessage(ctorMsg);
599
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;
604                 if (null == retMsg)
605                 {
606                     throw new RemotingException(
607                         Environment.GetResourceString(
608                             "Remoting_Activation_Failed"));
609                 }
610                 else if (retMsg.Exception != null)
611                 {
612                     throw retMsg.Exception;
613                 }                                
614             }
615             // Note: PropagateOutParameters is now handled by RealProxy
616             // CallContext from retMsg should be already set by RealProxy
617             Contract.Assert(
618                 null != ctorRetMsg, 
619                 "Activate returning null ConstructorReturnMessage");
620                 
621             return ctorRetMsg;
622         }
623
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)
633         {           
634             bool bCtxBound = reqMsg.ActivationType.IsContextful;
635             Context serverContext = null;
636             
637             if (bCtxBound)
638             {
639                 // If the type is context bound, we need to create 
640                 // the appropriate context and activate the object inside
641                 // it.
642                 // <
643
644                 // Create a new Context
645                 serverContext = new Context();              
646
647                 // <
648
649
650
651                 
652                 ArrayList list = (ArrayList) reqMsg.ContextProperties;
653                 RuntimeAssembly asm = null;
654                 for (int i=0; i<list.Count; i++)
655                 {
656                     IContextProperty prop = list[i] as IContextProperty;
657                     if (null == prop)
658                     {
659                         throw new RemotingException(
660                             Environment.GetResourceString(
661                                 "Remoting_Activation_BadAttribute"));
662                     }
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);
667
668                     // This ensures that we don't try to add duplicate
669                     // attributes (eg. type attributes common on both client
670                     // and server end)
671                     if (serverContext.GetProperty(prop.Name) == null)
672                     {
673                         serverContext.SetProperty(prop);
674                     }
675                 }
676                 // No more property changes to the server context from here.
677                 serverContext.Freeze();
678
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++)
683                 {
684                     if (!((IContextProperty)list[i]).IsNewContextOK(
685                         serverContext))
686                     {
687                         throw new RemotingException(
688                             Environment.GetResourceString(
689                                 "Remoting_Activation_PropertyUnhappy"));
690                     }
691                 }
692             }
693
694
695             IConstructionReturnMessage  replyMsg;
696
697             InternalCrossContextDelegate xctxDel = 
698                 new InternalCrossContextDelegate(DoCrossContextActivationCallback);
699
700             Object[] args = new Object[] { reqMsg };
701             
702             if (bCtxBound)
703             {
704                 replyMsg = Thread.CurrentThread.InternalCrossContextCallback(
705                     serverContext, xctxDel, args) as IConstructionReturnMessage;
706             }
707             else
708             {
709                 replyMsg = xctxDel(args) as IConstructionReturnMessage;
710             }
711
712             return replyMsg;
713         }
714
715         [System.Security.SecurityCritical]  // auto-generated
716         internal static Object DoCrossContextActivationCallback(Object[] args)
717         {
718             IConstructionCallMessage    reqMsg   = (IConstructionCallMessage) args[0]; 
719             IConstructionReturnMessage  replyMsg = null;
720                 
721             // call the first sink in the server context chain
722             // <
723             IMethodReturnMessage retMsg =  (IMethodReturnMessage) 
724                     Thread.CurrentContext.GetServerContextChain().SyncProcessMessage(reqMsg);
725         
726             // The return message may not be of type
727             // IConstructionReturnMessage if an exception happens
728             // in the sink chains.
729             Exception e = null;
730             replyMsg = retMsg as IConstructionReturnMessage;
731             if (null == replyMsg)
732             {
733                 if (retMsg != null)
734                 {
735                     e = retMsg.Exception;
736                 }
737                 else
738                 {
739                     e = new RemotingException(
740                             Environment.GetResourceString(
741                                 "Remoting_Activation_Failed"));
742         
743                 }
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(
748                         (LogicalCallContext)
749                         reqMsg.Properties[Message.CallContextKey]);
750             }
751
752             return replyMsg;
753         }
754
755         [System.Security.SecurityCritical]  // auto-generated
756         internal static IConstructionReturnMessage DoServerContextActivation(
757             IConstructionCallMessage reqMsg)
758         {
759             Contract.Assert(reqMsg!=null, "NULL ctorReqMsg");
760             Exception e=null;
761             Type serverType = reqMsg.ActivationType;
762             Object serverObj = ActivateWithMessage(
763                                     serverType, 
764                                     reqMsg, 
765                                     null,
766                                     out e);
767
768             IConstructionReturnMessage replyMsg = 
769                 SetupConstructionReply(serverObj, reqMsg, e);
770
771             Contract.Assert(replyMsg!=null, "NULL ctorRetMsg");
772             return replyMsg;
773         }
774
775         [System.Security.SecurityCritical]  // auto-generated
776         internal static IConstructionReturnMessage SetupConstructionReply(
777             Object serverObj,
778             IConstructionCallMessage ctorMsg,
779             Exception e)
780         {
781             IConstructionReturnMessage replyMsg = null;
782             if (e == null)
783             {
784                 replyMsg =
785                     new ConstructorReturnMessage(
786                         (MarshalByRefObject)serverObj,
787                         null,   // <
788                                 // if ctor-s with ref/out are supported</
789                         0,
790                         (LogicalCallContext)
791                             ctorMsg.Properties[Message.CallContextKey],
792                         ctorMsg);
793             }
794             else
795             {
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(
800                         (LogicalCallContext)
801                             ctorMsg.Properties[Message.CallContextKey]);
802
803             }
804             return replyMsg;
805         }
806
807         [System.Security.SecurityCritical]  // auto-generated
808         internal static Object ActivateWithMessage(
809             Type serverType, IMessage msg, ServerIdentity srvIdToBind,
810             out Exception e)
811         {
812             Object server = null;
813             e = null;
814
815             // Create a blank instance!
816             server = RemotingServices.AllocateUninitializedObject(serverType);
817
818             Object proxyForObject = null;
819             if (serverType.IsContextful)
820             {
821                 if (msg is ConstructorCallMessage)
822                 {
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();
827                 }
828                 else
829                 {
830                     // we are out of the app-domain, so wrap this object now
831                     proxyForObject = null;
832                 }
833
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,
838                                         proxyForObject, 
839                                         false);
840                 Contract.Assert(
841                     RemotingServices.IsTransparentProxy(proxyForObject),
842                     "Wrapped object should be a transparent proxy");
843             }
844             else
845             {
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)
849                 {
850                     throw new RemotingException(
851                         Environment.GetResourceString(
852                             "Remoting_Activation_Failed"));
853                 }
854                 // Marshal-by-ref case we just return the object
855                 proxyForObject = server;                                
856             }
857
858             // Create the dispatcher which will help run the CTOR
859             IMessageSink dispatcher = (IMessageSink)new StackBuilderSink(proxyForObject);
860
861             // This call runs the CTOR on the object
862             IMethodReturnMessage retMsg = (IMethodReturnMessage) 
863                                         dispatcher.SyncProcessMessage(msg);
864
865             if (retMsg.Exception == null)
866             {
867                 if (serverType.IsContextful)
868                 {
869                     // call wrap to finish the operation.
870                     return RemotingServices.Wrap((ContextBoundObject)server);
871                 }
872                 else
873                 {
874                     return server;
875                 }
876             }
877             else
878             {
879                 e = retMsg.Exception;
880                 return null;
881             }
882         }
883
884         [System.Security.SecurityCritical]  // auto-generated
885         internal static void StartListeningForRemoteRequests()
886         {
887             // Get the activation services set up.
888             Startup();
889             DomainSpecificRemotingData remData = Thread.GetDomain().RemotingData;
890             if (!remData.ActivatorListening)
891             {
892                 Object configLock = remData.ConfigLock;
893                 bool fLocked = false;
894                 RuntimeHelpers.PrepareConstrainedRegions();
895                 try
896                 {
897                     Monitor.Enter(configLock, ref fLocked);
898                     if (!remData.ActivatorListening)
899                     {
900                         BCLDebug.Log("Registering remoting activator");
901
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)); 
909                             
910                         ServerIdentity srvID = (ServerIdentity)
911                             IdentityHolder.ResolveIdentity(ActivationServiceURI);
912
913                         // Set Singleton to prevent lease from being created
914                         srvID.SetSingletonObjectMode();
915                         //DBG Console.WriteLine("Activator URI: = " + activatorURI);
916                         remData.ActivatorListening = true;
917                     }
918                 }
919                 finally
920                 {
921                     if (fLocked)
922                     {
923                         Monitor.Exit(configLock);
924                     }
925                 }
926             }
927         }
928
929         // This returns the local activator
930         [System.Security.SecurityCritical]  // auto-generated
931         internal static IActivator GetActivator()
932         {
933             DomainSpecificRemotingData remData = Thread.GetDomain().RemotingData;
934             if (remData.LocalActivator == null)
935             {
936                 Startup();
937             }
938             return (IActivator)remData.LocalActivator;
939         }
940
941         [System.Security.SecurityCritical]  // auto-generated
942         internal static void Initialize()
943         {
944             GetActivator();
945         }
946
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()
951         {
952             DomainSpecificRemotingData remData = Thread.GetDomain().RemotingData;
953             if (remData.LocalActivator == null)
954             {
955                 Startup();
956             }
957             return (ContextAttribute)remData.LocalActivator;
958         }
959             
960         // This function returns the array of custom attributes of
961         // type "ContextAttribute" walking the entire class hierarchy
962         // of the serverType
963         // If duplicates are found the attribute on the more derived
964         // type is kept.
965         // The return array may be sparse and is terminated by a NULL.
966         [System.Security.SecurityCritical]
967         internal static IContextAttribute[] GetContextAttributesForType(Type serverType)
968         {
969             if (!(typeof(ContextBoundObject).IsAssignableFrom(serverType)) ||
970                 serverType.IsCOMObject)
971             {
972                 return new ContextAttribute[0];
973             }
974
975             Type currType = serverType;
976             Object[] currAttr = null;
977             int retSize = 8;
978             IContextAttribute[] retAttr = new IContextAttribute[retSize];
979             int numAttr = 0;
980     
981     
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
987             Boolean bDupe;                             
988             foreach (IContextAttribute attr in currAttr)
989             {
990                 Type attrType = attr.GetType();
991                 bDupe = false;
992                 for (int i=0; i<numAttr; i++)
993                 {
994                     if (attrType.Equals(retAttr[i].GetType()))
995                     {
996                         bDupe = true;
997                         break;
998                     }
999                 }
1000
1001                 if (!bDupe)
1002                 { 
1003                     // We must add this attribute to our list
1004                     numAttr++;
1005                      
1006                     // Check if we have enough space to store it
1007                     // Leaving one spot for a NULL value!
1008                     if (numAttr > retSize-1)
1009                     {
1010                         IContextAttribute[] newAttr = new IContextAttribute[2*retSize];
1011                         Array.Copy(
1012                             retAttr,     // srcArray
1013                             0,          // srcIndex
1014                             newAttr,    // destArray
1015                             0,          // destIndex
1016                             retSize);   // lengthToCopy
1017                         retAttr = newAttr;
1018                         retSize = retSize*2;
1019                     }
1020                     retAttr[numAttr-1] = attr;
1021                 }
1022             }
1023            
1024             IContextAttribute[] ctxAttr = new IContextAttribute[numAttr];
1025             Array.Copy(retAttr, ctxAttr, numAttr);
1026             return ctxAttr;
1027         }  
1028                               
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)
1035         {
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
1039
1040             // Look for the connect URL
1041             String objURL = (String) ctorMsg.Properties[ConnectKey];
1042             Object proxy = null;
1043             if (objURL != null)
1044             {   
1045                 // Connect to the URL and return the proxy
1046                 proxy = RemotingServices.Connect(
1047                                         ctorMsg.ActivationType,
1048                                         objURL);
1049             }
1050
1051             // If the type is not setup for connecting we return null!
1052             return proxy;                                            
1053         }                                        
1054
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)
1063         {
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];
1068             Object tp = null;
1069
1070             if (objURL != null)
1071             {   
1072                 // We did perform a connect during IsContextOK 
1073                 // Just get the TP from RP and return it.
1074                 tp = (Object)proxy.GetTransparentProxy();
1075             } 
1076             // We return null if we do not recognize this proxy!
1077             return tp;                                            
1078         }
1079         
1080         internal static void PushActivationAttributes(Type serverType, Object[] attributes)
1081         {
1082             // There is one such object per thread
1083             if (_attributeStack == null)
1084             {            
1085                 _attributeStack = new ActivationAttributeStack();
1086             }
1087             _attributeStack.Push(serverType, attributes);
1088         }
1089
1090         internal static Object[] PeekActivationAttributes(Type serverType)
1091         {
1092             // We can get a peek w/o a prior Push (eg. activation starting
1093             // with NewObj)
1094             if (_attributeStack == null)
1095             {            
1096                 return null;
1097             }
1098             return _attributeStack.Peek(serverType);
1099         }
1100         
1101         internal static void PopActivationAttributes(Type serverType)
1102         {
1103             Contract.Assert(_attributeStack != null, "Pop w/o a prior Set()?");
1104             _attributeStack.Pop(serverType);
1105         }        
1106     } // class ActivationServices    
1107
1108
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
1113     {
1114         internal LocalActivator()
1115             : base(ActivationServices.ActivationServiceURI)
1116         {
1117         
1118         }
1119
1120         // ---------------------------------------------------------------        
1121         // ContextAttribute functionality
1122         // ---------------------------------------------------------------        
1123
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)
1130         {
1131
1132             // If the app is not using config mechanism, we don't want
1133             // to intercept activation.
1134             if (RemotingConfigHandler.Info == null)
1135             {
1136                 return true;
1137             }
1138
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"));
1144
1145             WellKnownClientTypeEntry wkte = 
1146                 RemotingConfigHandler.IsWellKnownClientType(activationType);
1147             String typeURL = (wkte == null ? null : wkte.ObjectUrl);
1148
1149             if (typeURL != null)
1150             {
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;
1154                 return false;
1155             }
1156             else
1157             {
1158                 ActivatedClientTypeEntry acte = 
1159                     RemotingConfigHandler.IsRemotelyActivatedClientType(activationType);
1160
1161                 String appURL = null;
1162
1163                 if (acte == null)
1164                 {
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)
1169                     {
1170                         for(int i = 0; i < callsiteAttributes.Length; i++)
1171                         {
1172                             UrlAttribute attr = callsiteAttributes[i] as UrlAttribute;
1173                             if(null != attr)
1174                             {
1175                                 appURL = attr.UrlValue; 
1176                             }
1177                         }
1178                     }
1179                         
1180                     if(appURL == null)
1181                     {
1182                         // We don't really care about intercepting the activation in this case.
1183                         return true;
1184                     }
1185                 }
1186                 else
1187                 {
1188                     appURL = acte.ApplicationUrl;
1189                 }
1190
1191                 // Generate the URL of the remote activator                    
1192                 String activatorURL = null;
1193                 if (!appURL.EndsWith("/", StringComparison.Ordinal))
1194                     activatorURL = appURL + "/" + ActivationServices.ActivationServiceURI;
1195                 else
1196                     activatorURL = appURL + ActivationServices.ActivationServiceURI;
1197                             
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;
1201                 return false;
1202             }
1203         }
1204                 
1205         // IContextAttribute::GetPropertiesForNewContext
1206         [System.Security.SecurityCritical]
1207         public override void GetPropertiesForNewContext(
1208             IConstructionCallMessage ctorMsg)
1209         {            
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))
1216             {
1217                 // Means we did want to intercept activation!
1218                 String remActivatorURL = (String)
1219                     ctorMsg.Properties[ActivationServices.RemoteActivateKey];
1220                 
1221                 AppDomainLevelActivator activator = 
1222                     new AppDomainLevelActivator(remActivatorURL);
1223                 // Chain ourselves at the end of the AppDomainLevel activators
1224                 Contract.Assert(
1225                         ctorMsg.Activator != null, 
1226                         "Should have at least x-context activator");
1227                 IActivator curr = ctorMsg.Activator;
1228                 
1229                 if (curr.Level < ActivatorLevel.AppDomain)
1230                 {
1231                     // Common case .. .only x-context activator(s) in chain
1232                     activator.NextActivator = curr;
1233                     ctorMsg.Activator = activator;
1234                 }
1235                 else if (curr.NextActivator == null)
1236                 {  
1237                     // Only one activator but not ContextLevel ...
1238                     // We go at the end of the chain 
1239                     curr.NextActivator = activator;
1240                 }
1241                 else
1242                 {
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)
1246                     {                        
1247                         curr = curr.NextActivator;
1248                     }
1249                     Contract.Assert(
1250                         curr.NextActivator.Level.Equals(ActivatorLevel.Context),
1251                         "bad ordering of activators!");
1252                     activator.NextActivator = curr.NextActivator;
1253                     curr.NextActivator = activator;
1254                 }                                
1255             }
1256         }                     
1257
1258         // ---------------------------------------------------------------        
1259         // IActivator functionality
1260         // ---------------------------------------------------------------        
1261         //IActivator::NextActivator
1262         public virtual IActivator NextActivator 
1263         {
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(); }
1270         }
1271
1272         //IActivator::ActivatorLevel
1273         public virtual ActivatorLevel Level
1274         {
1275             [System.Security.SecurityCritical]
1276             get { return ActivatorLevel.AppDomain; }
1277         }
1278                 
1279         private static MethodBase GetMethodBase(IConstructionCallMessage msg)
1280         {
1281             MethodBase mb = msg.MethodBase;
1282             if(null == mb)      
1283             {
1284                 BCLDebug.Trace("REMOTE", "Method missing w/name ", msg.MethodName);
1285                     throw new RemotingException(
1286                         String.Format(
1287                             CultureInfo.CurrentCulture, Environment.GetResourceString(
1288                                 "Remoting_Message_MethodMissing"),
1289                             msg.MethodName,
1290                             msg.TypeName));
1291             }
1292                     
1293             return mb;
1294         }
1295
1296         //IActivator::Activate
1297         [System.Security.SecurityCritical]
1298         [System.Runtime.InteropServices.ComVisible(true)]
1299         public virtual IConstructionReturnMessage Activate(
1300             IConstructionCallMessage ctorMsg)
1301         {
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. 
1305             //
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.
1311             //
1312             BCLDebug.Log("Activation Services:: new Activate()");
1313             if (ctorMsg == null)
1314             {
1315                 throw new ArgumentNullException("ctorMsg");
1316             }
1317             Contract.EndContractBlock();
1318             
1319             // Check if we have marked this activation to go remote 
1320             if (ctorMsg.Properties.Contains(ActivationServices.RemoteActivateKey))
1321             {
1322                 //DBG Console.WriteLine("Attempting remote activation!");
1323                                 
1324                 return DoRemoteActivation(ctorMsg);
1325             }
1326             else
1327             {                
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
1331                 // this type).
1332                 if (ctorMsg.Properties.Contains(ActivationServices.PermissionKey))
1333                 { 
1334                     Type activationType = ctorMsg.ActivationType;                    
1335
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)
1341                     {
1342                     IList cp = ctorMsg.ContextProperties;
1343                     if (cp != null && cp.Count > 0)
1344                     {
1345                         RemotePropertyHolderAttribute rph = new RemotePropertyHolderAttribute(cp);
1346                         attr = new Object[1];
1347                         attr[0] = rph;
1348                     }
1349                     }
1350                     MethodBase mb = GetMethodBase(ctorMsg); 
1351                     RemotingMethodCachedData methodCache = 
1352                                             InternalRemotingServices.GetReflectionCachedData(mb);
1353                     Object[] args = Message.CoerceArgs(ctorMsg, methodCache.Parameters);
1354                     
1355                     Object server = Activator.CreateInstance(
1356                         activationType, 
1357                         args,
1358                         attr);
1359
1360                     // check to see if we need to do redirection
1361                     if (RemotingServices.IsClientProxy(server))
1362                     {
1363                         // The wellknown type is remoted so we must wrap the proxy
1364                         // with a local object.
1365
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);
1371
1372                         server = redirectedProxy;
1373                     }                        
1374                      
1375                     return ActivationServices.SetupConstructionReply(
1376                         server, ctorMsg, null);
1377                 }
1378                 else
1379                 {
1380                     BCLDebug.Log("Attempting X-Context activation!");
1381                     // delegate to the Activator in the message 
1382                     return ctorMsg.Activator.Activate(ctorMsg);
1383                 }
1384             }
1385         }
1386
1387
1388         // This is called by the local activator during an outgoing activation
1389         // request.
1390         internal static IConstructionReturnMessage DoRemoteActivation(
1391             IConstructionCallMessage ctorMsg)
1392         {
1393             Contract.Assert(ctorMsg != null, "Null ctorMsg");
1394
1395             // <
1396
1397
1398
1399
1400             // <
1401
1402
1403             
1404             BCLDebug.Log("Attempting Connection to remote activation service");
1405             IActivator remActivator = null;
1406             String remActivatorURL = (String)
1407                 ctorMsg.Properties[ActivationServices.RemoteActivateKey];
1408             try 
1409             {
1410                 remActivator = (IActivator) 
1411                     RemotingServices.Connect(
1412                         typeof(System.Runtime.Remoting.Activation.IActivator),
1413                         remActivatorURL);
1414                                     
1415             }
1416             catch (Exception e)
1417             {
1418                 throw new RemotingException(
1419                     String.Format(
1420                         CultureInfo.CurrentCulture, Environment.GetResourceString(
1421                             "Remoting_Activation_ConnectFailed"),
1422                         e));
1423             }
1424             // Remove the remote activate key as its purpose is served.
1425             ctorMsg.Properties.Remove(ActivationServices.RemoteActivateKey);
1426
1427             // Delegate the work to the remote activator
1428             return remActivator.Activate(ctorMsg);                        
1429         }
1430         
1431     }// class LocalActivator
1432
1433     // This is the object that listens to activation requests
1434     internal class ActivationListener:MarshalByRefObject, IActivator
1435     {
1436         // Override lifetime services to make this object live forever...
1437         [System.Security.SecurityCritical]  // auto-generated
1438         public override Object InitializeLifetimeService()
1439         {
1440            return null;
1441         }
1442
1443         //IActivator::NextActivator
1444         public virtual IActivator NextActivator 
1445         {
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();}
1452         }
1453
1454         //IActivator::ActivatorLevel
1455         public virtual ActivatorLevel Level
1456         {
1457             [System.Security.SecurityCritical]  // auto-generated
1458             get {return ActivatorLevel.AppDomain;}
1459         }
1460     
1461         //IActivator::Activate
1462 [System.Security.SecurityCritical]  // auto-generated
1463 [System.Runtime.InteropServices.ComVisible(true)]
1464         public virtual IConstructionReturnMessage Activate(
1465             IConstructionCallMessage ctorMsg)
1466         {
1467             BCLDebug.Log("ActivationListener: received new activation request!");
1468             if (ctorMsg == null || RemotingServices.IsTransparentProxy(ctorMsg))
1469             {
1470                 throw new ArgumentNullException("ctorMsg");
1471             }
1472             Contract.EndContractBlock();
1473             
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";
1477
1478             // Check to make sure that this activation type has been allowed.
1479             String activationTypeName = ctorMsg.ActivationTypeName;
1480             if (!RemotingConfigHandler.IsActivationAllowed(activationTypeName))
1481             {
1482                 throw new RemotingException(
1483                     String.Format(
1484                         CultureInfo.CurrentCulture, Environment.GetResourceString(
1485                             "Remoting_Activation_PermissionDenied"),
1486                         ctorMsg.ActivationTypeName));
1487             }
1488
1489             Type activationType = ctorMsg.ActivationType;
1490             if (activationType == null)
1491             {
1492                 throw new RemotingException(
1493                     String.Format(
1494                         CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_BadType"),
1495                         ctorMsg.ActivationTypeName));
1496             }
1497             
1498             // Delegate to the local activator for further work
1499             return ActivationServices.GetActivator().Activate(ctorMsg);
1500         }        
1501
1502         
1503     }   // class ActivationListener
1504
1505
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)
1511  [Serializable]
1512     // attribute .. the latter shall be turned on during Beta-2!</
1513     internal class AppDomainLevelActivator : IActivator
1514     {
1515         IActivator m_NextActivator;        
1516
1517         // Do we need this?
1518         String m_RemActivatorURL;
1519         
1520         internal AppDomainLevelActivator(String remActivatorURL)
1521         {
1522             Contract.Assert(remActivatorURL!=null,"Bad activator URL");
1523             m_RemActivatorURL = remActivatorURL;
1524         }
1525
1526         internal AppDomainLevelActivator(SerializationInfo info, StreamingContext context) {
1527             if (info==null)
1528             {
1529                 throw new ArgumentNullException("info");
1530             }
1531             Contract.EndContractBlock();
1532             m_NextActivator = (IActivator) info.GetValue("m_NextActivator",typeof(IActivator));
1533         }
1534
1535         //IActivator::NextActivator
1536         public virtual IActivator NextActivator 
1537         {            
1538             [System.Security.SecurityCritical]  // auto-generated
1539             get { return m_NextActivator; }
1540             [System.Security.SecurityCritical]  // auto-generated
1541             set { m_NextActivator = value; }
1542         }
1543
1544         //IActivator::ActivatorLevel
1545         public virtual ActivatorLevel Level
1546         {
1547             [System.Security.SecurityCritical]  // auto-generated
1548             get { return ActivatorLevel.AppDomain; }
1549         }
1550
1551         //IActivator::Activate
1552 [System.Security.SecurityCritical]  // auto-generated
1553 [System.Runtime.InteropServices.ComVisible(true)]
1554         public virtual IConstructionReturnMessage Activate(
1555             IConstructionCallMessage ctorMsg)
1556         {
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!)
1561
1562             // remove ourselves from the Activator chain
1563             ctorMsg.Activator = m_NextActivator;
1564             return ActivationServices.GetActivator().Activate(ctorMsg);            
1565         }
1566     }
1567
1568     // This is a lightweight object to help with the activation
1569     // at the context level ...     
1570     [Serializable]
1571     internal class ContextLevelActivator : IActivator
1572     {                
1573         IActivator m_NextActivator;
1574         internal ContextLevelActivator()
1575         {
1576             m_NextActivator = null;
1577         }
1578         
1579         internal ContextLevelActivator(SerializationInfo info, StreamingContext context) 
1580         {
1581             if (info==null)
1582             {
1583                 throw new ArgumentNullException("info");
1584             }
1585             Contract.EndContractBlock();
1586             m_NextActivator = (IActivator) info.GetValue("m_NextActivator",typeof(IActivator));
1587         }
1588
1589         //IActivator::NextActivator
1590         public virtual IActivator NextActivator 
1591         {            
1592             [System.Security.SecurityCritical]  // auto-generated
1593             get { return m_NextActivator; }
1594             [System.Security.SecurityCritical]  // auto-generated
1595             set { m_NextActivator = value; }
1596         }
1597
1598         //IActivator::ActivatorLevel
1599         public virtual ActivatorLevel Level
1600         {
1601             [System.Security.SecurityCritical]  // auto-generated
1602             get { return ActivatorLevel.Context; }
1603         }
1604
1605         //IActivator::Activate
1606 [System.Security.SecurityCritical]  // auto-generated
1607 [System.Runtime.InteropServices.ComVisible(true)]
1608         public virtual IConstructionReturnMessage Activate(
1609             IConstructionCallMessage ctorMsg)
1610         {
1611             // remove ourselves from the Activator chain
1612             ctorMsg.Activator = ctorMsg.Activator.NextActivator;
1613             
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);
1620         }        
1621     }
1622
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)
1628     [Serializable]
1629     internal class ConstructionLevelActivator : IActivator
1630     {                
1631         internal ConstructionLevelActivator()
1632         {
1633         
1634         }
1635
1636
1637         //IActivator::NextActivator
1638         public virtual IActivator NextActivator 
1639         {            
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(); }
1646         }
1647
1648         //IActivator::ActivatorLevel
1649         public virtual ActivatorLevel Level
1650         {
1651             [System.Security.SecurityCritical]  // auto-generated
1652             get { return ActivatorLevel.Construction; }
1653         }
1654
1655         //IActivator::Activate
1656 [System.Security.SecurityCritical]  // auto-generated
1657 [System.Runtime.InteropServices.ComVisible(true)]
1658         public virtual IConstructionReturnMessage Activate(
1659             IConstructionCallMessage ctorMsg)
1660         {
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!)
1665
1666             // remove ourselves from the Activator chain
1667             ctorMsg.Activator = ctorMsg.Activator.NextActivator;
1668             return ActivationServices.DoServerContextActivation(ctorMsg);            
1669         }
1670     }
1671
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
1676     {
1677         IList _cp;      // incoming list of context properties
1678         internal RemotePropertyHolderAttribute(IList cp)
1679         {
1680             _cp = cp;
1681             Contract.Assert(cp != null && cp.Count > 0,"Bad _cp?");
1682         }
1683 [System.Security.SecurityCritical]  // auto-generated
1684 [System.Runtime.InteropServices.ComVisible(true)]
1685         public virtual bool IsContextOK(Context ctx, IConstructionCallMessage msg)
1686         {
1687             // The fact that we got instantiated means some remote activation
1688             // has contributed non-default context properties to the ctorMsg
1689             return false;
1690         }
1691
1692
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)
1698         {
1699             for (int i=0; i<_cp.Count; i++)
1700             {
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]);
1706             }
1707         }
1708     }
1709         
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).
1713
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.
1725
1726     internal class ActivationAttributeStack
1727     {
1728         Object[] activationTypes;
1729         Object[] activationAttributes;
1730         int freeIndex;
1731         internal ActivationAttributeStack()
1732         {
1733             activationTypes = new Object[4];
1734             activationAttributes = new Object[4];
1735             freeIndex = 0;
1736         }
1737
1738         internal void Push(Type typ, Object[] attr)
1739         {
1740             Contract.Assert(typ!=null, "typ != null");                    
1741             Contract.Assert(attr!=null, "attr != null");        
1742
1743             if (freeIndex == activationTypes.Length)
1744             {
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;
1753             }
1754             activationTypes[freeIndex] = typ;
1755             activationAttributes[freeIndex] = attr;
1756             freeIndex++;
1757         }
1758
1759         internal Object[] Peek(Type typ)
1760         {
1761             Contract.Assert(typ!=null, "typ != null");
1762             if (freeIndex == 0 || activationTypes[freeIndex-1] != (object)typ)
1763             {
1764                 return null;
1765             }
1766             return (Object[])activationAttributes[freeIndex-1];
1767         }
1768
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)
1773         {
1774             Contract.Assert(typ!=null, "typ != null");
1775             if (freeIndex != 0 && activationTypes[freeIndex-1] == (object)typ)
1776             {                
1777                 freeIndex--;
1778                 // Clear the popped entry
1779                 activationTypes[freeIndex] = null;
1780                 activationAttributes[freeIndex] = null;
1781             }
1782         }
1783     }
1784 }//namespace