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