1 // ==++==
2 //
3 //   Copyright (c) Microsoft Corporation.  All rights reserved.
4 //
5 // ==--==
6 /*============================================================
7 **
8 ** File:    RemotingProxy.cs
9 **
10 **
11 ** Purpose: Defines the general purpose remoting proxy
12 **
13 **
14 ===========================================================*/
15 namespace System.Runtime.Remoting.Proxies {
16     using System.Threading;
17     using System.Runtime.Remoting.Activation;
18     using System.Runtime.Remoting.Messaging;
19     using System.Runtime.Remoting.Contexts;
20     using System.Runtime.Remoting.Channels;
21     using System;
22     using MethodInfo = System.Reflection.MethodInfo;
23     using MethodBase = System.Reflection.MethodBase;
24     using System.Globalization;
25     // Remoting proxy
26     [System.Security.SecurityCritical]  // auto-generated
27     internal class RemotingProxy : RealProxy, IRemotingTypeInfo
28     {
29         // Static Fields
30         private static MethodInfo _getTypeMethod = typeof(System.Object).GetMethod("GetType");
31         private static MethodInfo _getHashCodeMethod = typeof(System.Object).GetMethod("GetHashCode");
32 
33         private static RuntimeType s_typeofObject = (RuntimeType)typeof(System.Object);
34         private static RuntimeType s_typeofMarshalByRefObject = (RuntimeType)typeof(System.MarshalByRefObject);
35 
36         //*******************WARNING******************************************
37         // If you change the names of these fields then change the corresponding
38         // names in remoting.cpp
39         //********************************************************************
40         private ConstructorCallMessage _ccm;
41         private int _ctorThread;
42 
43 
44         // Constructor
RemotingProxy(Type serverType)45         public RemotingProxy(Type serverType)
46         : base(serverType)
47         {
48         }
49 
RemotingProxy()50         private RemotingProxy()
51         {
52             // Prevent anyone from creating a blank instance of a proxy
53             // without the underlying server type
54         }
55 
56         internal int CtorThread
57         {
58             get
59             {
60                 return _ctorThread;
61             }
62             set
63             {
64                 //NOTE : the assert below is correct for activated objects.
65                 //But for a connected object (where new XXX() does a Connect()
66                 //the InternalActivate codepath may execute twice .. since
67                 //we would be returning the same proxy for multiple calls to
68                 //new XXX() & JIT would try to execute the default .ctor on
69                 //the returned proxy.
70 
71                 //BCLDebug.Assert(_ctorThread == 0, "ctorThread already set??");
72                 _ctorThread = value;
73             }
74         }
75 
76         // This is used when a TP is called with SyncProcessMessage
CallProcessMessage(IMessageSink ms, IMessage reqMsg, ArrayWithSize proxySinks, Thread currentThread, Context currentContext, bool bSkippingContextChain)77         internal static IMessage CallProcessMessage(IMessageSink ms,
78                                                     IMessage reqMsg,
79                                                     ArrayWithSize proxySinks,
80                                                     Thread currentThread,
81                                                     Context currentContext,
82                                                     bool bSkippingContextChain)
83         {
84             // Notify Dynamic Sinks: CALL starting
85             if (proxySinks != null)
86             {
87                 DynamicPropertyHolder.NotifyDynamicSinks(
88                                             reqMsg,
89                                             proxySinks,
90                                             true,   // bCliSide
91                                             true,   // bStart
92                                             false); // bAsync
93             }
94 
95             bool bHasDynamicSinks = false;
96             if (bSkippingContextChain)
97             {
98                 // this would have been done in the client context terminator sink
99                 bHasDynamicSinks =
100                     currentContext.NotifyDynamicSinks(reqMsg,
101                         true,   // bCliSide
102                         true,   // bStart
103                         false,  // bAsync
104                         true);  // bNotifyGlobals
105 
106                 ChannelServices.NotifyProfiler(reqMsg, RemotingProfilerEvent.ClientSend);
107             }
108 
109             if (ms == null)
110             {
111                 throw new RemotingException(
112                     Environment.GetResourceString(
113                         "Remoting_Proxy_NoChannelSink"));
114             }
115 
116             IMessage retMsg = ms.SyncProcessMessage(reqMsg);
117 
118             if (bSkippingContextChain)
119             {
120                 // this would have been done in the client context terminator sink
121                 ChannelServices.NotifyProfiler(retMsg, RemotingProfilerEvent.ClientReceive);
122 
123                 if (bHasDynamicSinks)
124                 {
125                     currentContext.NotifyDynamicSinks(
126                         retMsg,
127                         true,   // bCliSide
128                         false,   // bStart
129                         false,  // bAsync
130                         true);  // bNotifyGlobals
131                 }
132             }
133 
134             IMethodReturnMessage mrm = retMsg as IMethodReturnMessage;
135             if (retMsg == null || mrm == null)
136             {
137                 throw new RemotingException(
138                     Environment.GetResourceString("Remoting_Message_BadType"));
139             }
140 
141             // notify DynamicSinks: CALL returned
142             if (proxySinks != null)
143             {
144                 DynamicPropertyHolder.NotifyDynamicSinks(
145                                             retMsg,
146                                             proxySinks,
147                                             true,   // bCliSide
148                                             false,  // bStart
149                                             false); // bAsync
150             }
151 
152 
153             return retMsg;
154         }
155 
156         // Implement Invoke
157         [System.Security.SecurityCritical]
Invoke(IMessage reqMsg)158         public override IMessage Invoke(IMessage reqMsg)
159         {
160             // Dispatch based on whether its a constructor call
161             // or a method call
162 
163             IConstructionCallMessage ccm = reqMsg as IConstructionCallMessage;
164 
165             if(ccm != null)
166             {
167                 // Activate
168                 return InternalActivate(ccm);
169             }
170             else
171             {
172                 // Handle regular method calls
173 
174                 // Check that the initialization has completed
175                 if(!Initialized)
176                 {
177                     // This covers the case where an object may call out
178                     // on another object passing its "this" pointer during its
179                     // .ctor.
180                     // The other object attempting to call on the this pointer
181                     // (in x-context case) would be calling on a proxy not
182                     // marked fully initialized.
183                     // <
184 
185 
186 
187                     // Let the original constructor thread go through but
188                     // throw for other threads.
189                     if (CtorThread == Thread.CurrentThread.GetHashCode())
190                     {
191                         ServerIdentity srvId = IdentityObject as ServerIdentity;
192                         BCLDebug.Assert(
193                             srvId != null
194                             &&
195                             ((ServerIdentity)IdentityObject).ServerContext != null,
196                             "Wrap may associate with wrong context!");
197 
198                         // If we are here, the server object passed itself
199                         // out to another x-context object during the .ctor
200                         // That guy is calling us back. Let us call Wrap()
201                         // earlier than usual so that envoy & channel sinks
202                         // get set up!
203                         // <
204 
205 
206 
207                         RemotingServices.Wrap(
208                             (ContextBoundObject) this.UnwrappedServerObject);
209 
210                     }
211                     else
212                     {
213                         // Throw an exception to indicate that we are
214                         // calling on a proxy while the constructor call
215                         // is still running.
216                         throw new RemotingException(Environment.GetResourceString("Remoting_Proxy_InvalidCall"));
217                     }
218 
219                 }
220 
221                 // Dispatch
222                 int callType = Message.Sync;
223                 Message msg = reqMsg as Message;
224                 if (msg != null)
225                 {
226                     callType = msg.GetCallType();
227                 }
228 
229                 return InternalInvoke((IMethodCallMessage)reqMsg, false, callType);
230             }
231 
232         } // Invoke
233 
234 
235         // This is called for all remoted calls on a TP except Ctors
236         // The method called may be Sync, Async or OneWay(special case of Async)
237         // In the Async case we come here for both BeginInvoke & EndInvoke
InternalInvoke( IMethodCallMessage reqMcmMsg, bool useDispatchMessage, int callType)238         internal virtual IMessage InternalInvoke(
239             IMethodCallMessage reqMcmMsg, bool useDispatchMessage, int callType)
240         {
241             Message reqMsg = reqMcmMsg as Message;
242             if ((reqMsg == null) && (callType != Message.Sync))
243             {
244                 // Only the synchronous call type is supported for messages that
245                 //   aren't of type Message.
246                 throw new RemotingException(
247                     Environment.GetResourceString("Remoting_Proxy_InvalidCallType"));
248             }
249 
250             IMessage retMsg = null;
251             Thread currentThread = Thread.CurrentThread;
252 
253             // pick up call context from the thread
254             LogicalCallContext cctx = currentThread.GetMutableExecutionContext().LogicalCallContext;
255 
256             Identity idObj = IdentityObject;
257             ServerIdentity serverID = idObj as ServerIdentity;
258             if ((null != serverID) && idObj.IsFullyDisconnected())
259             {
260                 throw new ArgumentException(
261                    Environment.GetResourceString("Remoting_ServerObjectNotFound", reqMcmMsg.Uri));
262             }
263 
264             // Short-circuit calls to Object::GetType and Object::GetHashCode
265             MethodBase mb = reqMcmMsg.MethodBase;
266             if(_getTypeMethod == mb)
267             {
268                 // Time to load the true type of the remote object....
269                 Type t = GetProxiedType();
270                 return new ReturnMessage(t, null, 0, cctx, reqMcmMsg);
271             }
272 
273             if (_getHashCodeMethod == mb)
274             {
275                 int hashCode = idObj.GetHashCode();
276                 return new ReturnMessage(hashCode, null, 0, cctx, reqMcmMsg);
277             }
278 
279             // check for channel sink
280             if (idObj.ChannelSink == null)
281             {
282                 IMessageSink chnlSink = null;
283                 IMessageSink envoySink = null;
284                 // If channelSink is null try to Create them again
285                 // the objref should be correctly fixed up at this point
286                 if(!idObj.ObjectRef.IsObjRefLite())
287                 {
288                     RemotingServices.CreateEnvoyAndChannelSinks(null, idObj.ObjectRef, out chnlSink, out envoySink);
289                 }
290                 else
291                 {
292                     RemotingServices.CreateEnvoyAndChannelSinks(idObj.ObjURI, null, out chnlSink, out envoySink);
293                 }
294                 // Set the envoy and channel sinks in a thread safe manner
295                 RemotingServices.SetEnvoyAndChannelSinks(idObj, chnlSink, envoySink);
296 
297                 // If the channel sink is still null then throw
298                 if(idObj.ChannelSink == null)
299                 {
300                     throw new RemotingException(
301                         Environment.GetResourceString("Remoting_Proxy_NoChannelSink"));
302                 }
303             }
304 
305             // Set the identity in the message object
306             IInternalMessage iim = (IInternalMessage)reqMcmMsg;
307             iim.IdentityObject = idObj;
308 
309             if (null != serverID)
310             {
311                 Message.DebugOut("Setting serveridentity on message \n");
312                 iim.ServerIdentityObject = serverID;
313 
314             }
315             else
316             {
317                 // We need to set the URI only for identities that
318                 // are not the server identities. The uri is used to
319                 // dispatch methods for objects outside the appdomain.
320                 // Inside the appdomain (xcontext case) we dispatch
321                 // by getting the server object from the server identity.
322                iim.SetURI(idObj.URI);
323             }
324 
325             Message.DebugOut("InternalInvoke. Dispatching based on class type\n");
326             AsyncResult ar = null;
327             switch (callType)
328             {
329             case Message.Sync:
330                 Message.DebugOut("RemotingProxy.Invoke Call: SyncProcessMsg\n");
331                 BCLDebug.Assert(!useDispatchMessage,"!useDispatchMessage");
332                 bool bSkipContextChain = false;
333                 Context currentContext = currentThread.GetCurrentContextInternal();
334                 IMessageSink nextSink = idObj.EnvoyChain;
335 
336                 // if we are in the default context, there can be no
337                 // client context chain, so we can skip the intermediate
338                 // calls if there are no envoy sinks
339 
340                 if (currentContext.IsDefaultContext)
341                 {
342                     if (nextSink is EnvoyTerminatorSink)
343                     {
344                         bSkipContextChain = true;
345 
346                         // jump directly to the channel sink
347                         nextSink = idObj.ChannelSink;
348                     }
349                 }
350 
351                 retMsg = CallProcessMessage(nextSink,
352                                             reqMcmMsg,
353                                             idObj.ProxySideDynamicSinks,
354                                             currentThread,
355                                             currentContext,
356                                             bSkipContextChain);
357 
358                 break;
359 
360             case Message.BeginAsync:
361             case Message.BeginAsync | Message.OneWay:
362                 // For async calls we clone the call context from the thread
363                 // This is a limited clone (we dont deep copy the user data)
364                 cctx = (LogicalCallContext) cctx.Clone();
365                 iim.SetCallContext(cctx);
366 
367                 ar = new AsyncResult(reqMsg);
368 
369                 InternalInvokeAsync(ar, reqMsg, useDispatchMessage, callType);
370 
371                 Message.DebugOut("Propagate out params for BeginAsync\n");
372                 retMsg = new ReturnMessage(ar, null, 0, null/*cctx*/, reqMsg);
373                 break;
374 
375             case Message.OneWay:
376                 // For async calls we clone the call context from the thread
377                 // This is a limited clone (we dont deep copy the user data)
378                 cctx = (LogicalCallContext) cctx.Clone();
379                 iim.SetCallContext(cctx);
380                 InternalInvokeAsync(null, reqMsg, useDispatchMessage, callType);
381                 retMsg = new ReturnMessage(null, null, 0, null/*cctx*/, reqMcmMsg);
382                 break;
383 
384             case (Message.EndAsync | Message.OneWay):
385                 retMsg = new ReturnMessage(null, null, 0, null/*cctx*/, reqMcmMsg);
386                 break;
387 
388             case Message.EndAsync:
389                 // For endAsync, we merge back the returned callContext
390                 // into the thread's callContext
391                 retMsg = RealProxy.EndInvokeHelper(reqMsg, true);
392                 break;
393             }
394 
395             return retMsg;
396         }
397 
398 
399         // This is called from InternalInvoke above when someone makes an
400         // Async (or a one way) call on a TP
InternalInvokeAsync(IMessageSink ar, Message reqMsg, bool useDispatchMessage, int callType)401         internal void InternalInvokeAsync(IMessageSink ar,  Message reqMsg,
402             bool useDispatchMessage, int callType)
403         {
404             IMessageCtrl cc = null;
405             Identity idObj = IdentityObject;
406             ServerIdentity serverID = idObj as ServerIdentity;
407             MethodCall cpyMsg= new MethodCall(reqMsg);
408             IInternalMessage iim = ((IInternalMessage)cpyMsg);
409 
410             // Set the identity in the message object
411             iim.IdentityObject = idObj;
412             if (null != serverID)
413             {
414                 Message.DebugOut("Setting SrvID on deser msg\n");
415                 iim.ServerIdentityObject = serverID;
416             }
417 
418             if (useDispatchMessage)
419             {
420                 Message.DebugOut(
421                     "RemotingProxy.Invoke: Calling AsyncDispatchMessage\n");
422 
423                 BCLDebug.Assert(ar != null,"ar != null");
424                 BCLDebug.Assert( (callType & Message.BeginAsync) != 0,
425                                 "BeginAsync flag not set!");
426 
427                 Message.DebugOut("Calling AsynDispatchMessage \n");
428                 cc = ChannelServices.AsyncDispatchMessage(
429                                         cpyMsg,
430                                         ((callType & Message.OneWay) != 0)
431                                         ? null : ar);
432             }
433             else if (null != idObj.EnvoyChain)
434             {
435                 Message.DebugOut("RemotingProxy.Invoke: Calling AsyncProcessMsg on the envoy chain\n");
436 
437                 cc = idObj.EnvoyChain.AsyncProcessMessage(
438                                         cpyMsg,
439                                         ((callType & Message.OneWay) != 0)
440                                         ? null : ar);
441             }
442             else
443             {
444                 // Channel sink cannot be null since it is the last sink in
445                 // the client context
446                 // Assert if Invoke is called without a channel sink
447                 BCLDebug.Assert(false, "How did we get here?");
448 
449                 throw new InvalidOperationException(
450                     Environment.GetResourceString("Remoting_Proxy_InvalidState"));
451             }
452 
453             if ((callType & Message.BeginAsync) != 0)
454             {
455 
456                 if ((callType & Message.OneWay) != 0)
457                 {
458                     ar.SyncProcessMessage(null);
459                 }
460             }
461         }
462 
463         // New method for activators.
464 
465         // This gets called during remoting intercepted activation when
466         // JIT tries to run a constructor on a TP (which remoting gave it
467         // in place of an actual uninitialized instance of the expected type)
InternalActivate(IConstructionCallMessage ctorMsg)468         private IConstructionReturnMessage InternalActivate(IConstructionCallMessage ctorMsg)
469         {
470             // Remember the hashcode of the constructor thread.
471             CtorThread = Thread.CurrentThread.GetHashCode();
472 
473             IConstructionReturnMessage ctorRetMsg = ActivationServices.Activate(this, ctorMsg);
474 
475             // Set the flag to indicate that the object is initialized
476             // Note: this assert is not valid for WKOs
477             //BCLDebug.Assert(!Initialized, "Proxy marked as initialized before activation call completed");
478             Initialized = true;
479 
480             return ctorRetMsg;
481         }
482 
483         // Invoke for case where call is in the same context as the server object
484         // (This special static method is used for AsyncDelegate-s ... this is called
485         // directly from the EE)
Invoke(Object NotUsed, ref MessageData msgData)486         private static void Invoke(Object NotUsed, ref MessageData msgData)
487         {
488             Message m = new Message();
489             m.InitFields(msgData);
490 
491             Object thisPtr = m.GetThisPtr();
492             Delegate d;
493             if ((d = thisPtr as Delegate) != null)
494             {
495                 // <
496 
497                 RemotingProxy rp = (RemotingProxy)
498                     RemotingServices.GetRealProxy(d.Target);
499 
500                 if (rp != null)
501                 {
502                     rp.InternalInvoke(m, true, m.GetCallType());
503                 }
504                 else
505                 {
506                     int callType = m.GetCallType();
507                     AsyncResult ar;
508                     switch (callType)
509                     {
510                     case Message.BeginAsync:
511                     case Message.BeginAsync | Message.OneWay:
512                         // pick up call context from the thread
513                         m.Properties[Message.CallContextKey] =
514                             Thread.CurrentThread.GetMutableExecutionContext().LogicalCallContext.Clone();
515                         ar = new AsyncResult(m);
516                         AgileAsyncWorkerItem  workItem =
517                             new AgileAsyncWorkerItem(
518                                     m,
519                                     ((callType & Message.OneWay) != 0) ?
520                                         null : ar, d.Target);
521 
522                         ThreadPool.QueueUserWorkItem(
523                             new WaitCallback(
524                                     AgileAsyncWorkerItem.ThreadPoolCallBack),
525                             workItem);
526 
527                         if ((callType & Message.OneWay) != 0)
528                         {
529                             ar.SyncProcessMessage(null);
530                         }
531                         m.PropagateOutParameters(null, ar);
532                         break;
533                     case (Message.EndAsync | Message.OneWay):
534                         return;
535 
536                     case Message.EndAsync:
537                         // This will also merge back the call context
538                         // onto the thread that called EndAsync
539                         RealProxy.EndInvokeHelper(m, false);
540                         break;
541                     default:
542                         BCLDebug.Assert(
543                             false,
544                             "Should never be here. Sync delegate code for agile object ended up in remoting");
545                         break;
546                     }
547                 }
548             }
549             else
550             {
551                 // Static invoke called with incorrect this pointer ...
552                 throw new RemotingException(
553                     Environment.GetResourceString(
554                         "Remoting_Default"));
555             }
556         }
557 
558         internal ConstructorCallMessage ConstructorMessage
559         {
560             get
561             {
562                 return _ccm;
563             }
564 
565             set
566             {
567                 _ccm = value;
568             }
569         }
570 
571         //
572         // IRemotingTypeInfo interface
573         //
574 
575         // Obtain the fully qualified name of the type that the proxy represents
576         public String TypeName
577         {
578             [System.Security.SecurityCritical]
579             get
580             {
581                 return GetProxiedType().FullName;
582             }
583 
584             [System.Security.SecurityCritical]
585             set
586             {
587                 throw new NotSupportedException();
588             }
589         }
590 
591         // interop methods
592         [System.Security.SecurityCritical]
GetCOMIUnknown(bool fIsBeingMarshalled)593         public override IntPtr GetCOMIUnknown(bool fIsBeingMarshalled)
594         {
595             IntPtr pUnk = IntPtr.Zero;
596             Object otp = GetTransparentProxy();
597             bool fIsXProcess = RemotingServices.IsObjectOutOfProcess(otp);
598             if (fIsXProcess)
599             {
600                 // we are in a different process
601                 if (fIsBeingMarshalled)
602                 {
603                     // we need to go to the server to get the real IUnknown
604                     pUnk =  MarshalByRefObject.GetComIUnknown((MarshalByRefObject)otp);
605                 }
606                 else
607                 {
608                     // create an IUnknown here
609                     pUnk =  MarshalByRefObject.GetComIUnknown((MarshalByRefObject)otp);
610                 }
611             }
612             else
613             {
614                 bool fIsXAppDomain = RemotingServices.IsObjectOutOfAppDomain(otp);
615                 // we are in the same proces, ask the object for its IUnknown
616                 if (fIsXAppDomain)
617                 {
618                     // do an appdomain switch
619                     pUnk = ((MarshalByRefObject)otp).GetComIUnknown(fIsBeingMarshalled);
620                 }
621                 else
622                 {
623                     // otherwise go ahead and create a CCW here
624                     pUnk = MarshalByRefObject.GetComIUnknown((MarshalByRefObject)otp);
625                 }
626             }
627 
628             return pUnk;
629         }
630 
631         [System.Security.SecurityCritical]
SetCOMIUnknown(IntPtr i)632         public override void SetCOMIUnknown(IntPtr i)
633         {
634             // for now ignore this
635         }
636 
637         // Check whether we can cast the transparent proxy to the given type
638         [System.Security.SecurityCritical]
CanCastTo(Type castType, Object o)639         public bool CanCastTo(Type castType, Object o)
640         {
641             if (castType == null)
642                 throw new ArgumentNullException("castType");
643 
644             RuntimeType rtType = castType as RuntimeType;
645             if (rtType == null)
646                 throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"));
647 
648             bool fCastOK = false;
649 
650             // The identity should be non-null
651             BCLDebug.Assert(null != IdentityObject,"null != IdentityObject");
652 
653             Message.DebugOut("CheckCast for identity " + IdentityObject.GetType());
654 
655             if ((rtType == s_typeofObject) ||
656                 (rtType == s_typeofMarshalByRefObject))
657             {
658                 return true;
659             }
660 
661             // Get the objref of the proxy
662             ObjRef oRef = IdentityObject.ObjectRef;
663 
664             // If the object ref is non-null then check against the type info
665             // stored in the it
666             if (null != oRef)
667             {
668                 Object oTP = GetTransparentProxy();
669 
670                 // Check that there is a matching type in the server object
671                 // hierarchy represented in the objref
672                 Message.DebugOut("Calling CanCastTo for type " + rtType);
673                 IRemotingTypeInfo typeInfo = oRef.TypeInfo;
674                 if(null != typeInfo)
675                 {
676                     fCastOK = typeInfo.CanCastTo(rtType, oTP);
677                     if (!fCastOK && typeInfo.GetType()==typeof(TypeInfo) && oRef.IsWellKnown() )
678                     {
679                         fCastOK = CanCastToWK(rtType);
680                     }
681                 }
682                 else
683                 {
684                     if (oRef.IsObjRefLite())
685                     {
686                         // we should do a dynamic cast across the network
687                         fCastOK = MarshalByRefObject.CanCastToXmlTypeHelper(rtType, (MarshalByRefObject)o);
688                     }
689                 }
690             }
691             // This is a well known object which does not have a backing ObjRef
692             else
693             {
694                 fCastOK = CanCastToWK(rtType);
695             }
696             return fCastOK;
697         }
698 
699         // WellKnown proxies we always allow casts to interfaces, and allow
700         // casting down a single branch in the type hierarchy (both are on good
701         // faith. The calls are failed on server side if a bogus cast is done)
CanCastToWK(Type castType)702         bool CanCastToWK(Type castType)
703         {
704             Message.DebugOut( "CheckCast for well known objects and type " + castType);
705             bool fCastOK = false;
706             // Check whether the type to which we want to cast is
707             // compatible with the current type
708             if(castType.IsClass)
709             {
710                 fCastOK = GetProxiedType().IsAssignableFrom(castType);
711             }
712             else
713             {
714                 // NOTE: we are coming here also for x-context proxies
715                 // when unmanaged code cannot determine if the cast is not
716                 // okay <
717                 if (!(IdentityObject is ServerIdentity))
718                 {
719                     BCLDebug.Assert(
720                         IdentityObject.URI != null,
721                         "Bad WellKnown ID");
722                     // Always allow interface casts to succeed. If the
723                     // interface is not supported by the well known object
724                     // then we will throw an exception when the interface
725                     // is invoked.
726                     fCastOK = true;
727                 }
728             }
729 
730             return fCastOK;
731         }
732     }
733 
734 
735     internal class AgileAsyncWorkerItem
736     {
737         private IMethodCallMessage _message;
738         private AsyncResult        _ar;
739         private Object             _target;
740 
741         [System.Security.SecurityCritical]  // auto-generated
AgileAsyncWorkerItem(IMethodCallMessage message, AsyncResult ar, Object target)742         public AgileAsyncWorkerItem(IMethodCallMessage message, AsyncResult ar, Object target)
743         {
744             _message = new MethodCall(message);
745             _ar = ar;
746             _target = target;
747         }
748 
749         [System.Security.SecurityCritical]  // auto-generated
ThreadPoolCallBack(Object o)750         public static void ThreadPoolCallBack(Object o)
751         {
752             ((AgileAsyncWorkerItem) o).DoAsyncCall();
753         }
754 
755 
756         [System.Security.SecurityCritical]  // auto-generated
DoAsyncCall()757         public void DoAsyncCall()
758         {
759             (new StackBuilderSink(_target)).AsyncProcessMessage(_message, _ar);
760         }
761     }
762 
763 }
764