1 // ==++== 2 // 3 // Copyright (c) Microsoft Corporation. All rights reserved. 4 // 5 // ==--== 6 /*============================================================ 7 ** 8 ** File: ObjRef.cs 9 ** 10 ** 11 ** Purpose: Defines the marshaled object reference class and related 12 ** classes 13 ** 14 ** 15 ** 16 ===========================================================*/ 17 namespace System.Runtime.Remoting { 18 19 using System; 20 using System.Threading; 21 using System.Runtime.InteropServices; 22 using System.Runtime.Remoting; 23 using System.Runtime.Remoting.Channels; 24 using System.Runtime.Remoting.Contexts; 25 using System.Runtime.Remoting.Messaging; 26 using System.Runtime.Remoting.Metadata; 27 using System.Runtime.Serialization; 28 using System.Reflection; 29 using System.Security.Permissions; 30 using Win32Native = Microsoft.Win32.Win32Native; 31 using System.Runtime.ConstrainedExecution; 32 using System.Globalization; 33 34 35 36 //** Purpose: Interface for providing type information. Users can use this 37 //** interface to provide custom type information which is carried 38 //** along with the ObjRef. 39 [System.Runtime.InteropServices.ComVisible(true)] 40 public interface IRemotingTypeInfo 41 { 42 // Return the fully qualified type name 43 String TypeName 44 { 45 [System.Security.SecurityCritical] // auto-generated_required 46 get; 47 [System.Security.SecurityCritical] // auto-generated_required 48 set; 49 } 50 51 // Check whether the given type can be cast to the type this 52 // interface represents 53 [System.Security.SecurityCritical] // auto-generated_required CanCastTo(Type fromType, Object o)54 bool CanCastTo(Type fromType, Object o); 55 } 56 57 //** Purpose: Interface for providing channel information. Users can use this 58 //** interface to provide custom channel information which is carried 59 //** along with the ObjRef. 60 [System.Runtime.InteropServices.ComVisible(true)] 61 public interface IChannelInfo 62 { 63 // Get/Set the channel data for each channel 64 Object[] ChannelData 65 { 66 [System.Security.SecurityCritical] // auto-generated_required 67 get; 68 [System.Security.SecurityCritical] // auto-generated_required 69 set; 70 } 71 } 72 73 //** Purpose: Interface for providing envoy information. Users can use this 74 //** interface to provide custom envoy information which is carried 75 //** along with the ObjRef. 76 [System.Runtime.InteropServices.ComVisible(true)] 77 public interface IEnvoyInfo 78 { 79 // Get/Set the envoy sinks 80 IMessageSink EnvoySinks 81 { 82 [System.Security.SecurityCritical] // auto-generated_required 83 get; 84 [System.Security.SecurityCritical] // auto-generated_required 85 set; 86 } 87 } 88 89 90 91 [Serializable] 92 internal class TypeInfo : IRemotingTypeInfo 93 { 94 private String serverType; 95 private String[] serverHierarchy; 96 private String[] interfacesImplemented; 97 98 // Return the fully qualified type name 99 public virtual String TypeName 100 { 101 [System.Security.SecurityCritical] // auto-generated 102 get { return serverType;} 103 [System.Security.SecurityCritical] // auto-generated 104 set { serverType = value;} 105 } 106 107 // Check whether the given type can be cast to the type this 108 // interface represents 109 [System.Security.SecurityCritical] // auto-generated CanCastTo(Type castType, Object o)110 public virtual bool CanCastTo(Type castType, Object o) 111 { 112 if (null != castType) 113 { 114 // check for System.Object and MBRO since those aren't included in the 115 // heirarchy 116 if ((castType == typeof(MarshalByRefObject)) || 117 (castType == typeof(System.Object))) 118 { 119 return true; 120 } 121 else 122 if (castType.IsInterface) 123 { 124 if (interfacesImplemented != null) 125 return CanCastTo(castType, InterfacesImplemented); 126 else 127 return false; 128 } 129 else 130 if (castType.IsMarshalByRef) 131 { 132 if (CompareTypes(castType, serverType)) 133 return true; 134 135 if ((serverHierarchy != null) && CanCastTo(castType, ServerHierarchy)) 136 return true; 137 } 138 } 139 140 return false; 141 } 142 143 [System.Security.SecurityCritical] // auto-generated GetQualifiedTypeName(RuntimeType type)144 internal static String GetQualifiedTypeName(RuntimeType type) 145 { 146 if (type == null) 147 return null; 148 149 return RemotingServices.GetDefaultQualifiedTypeName(type); 150 } 151 ParseTypeAndAssembly(String typeAndAssembly, out String typeName, out String assemName)152 internal static bool ParseTypeAndAssembly(String typeAndAssembly, out String typeName, out String assemName) 153 { 154 if (typeAndAssembly == null) 155 { 156 typeName = null; 157 assemName = null; 158 return false; 159 } 160 161 int index = typeAndAssembly.IndexOf(','); 162 if (index == -1) 163 { 164 typeName = typeAndAssembly; 165 assemName = null; 166 return true; 167 } 168 169 // type name is everything up to the first comma 170 typeName = typeAndAssembly.Substring(0, index); 171 172 // assembly name is the rest 173 assemName = typeAndAssembly.Substring(index + 1).Trim(); 174 175 return true; 176 } // ParseTypeAndAssembly 177 178 179 [System.Security.SecurityCritical] // auto-generated TypeInfo(RuntimeType typeOfObj)180 internal TypeInfo(RuntimeType typeOfObj) 181 { 182 ServerType = GetQualifiedTypeName(typeOfObj); 183 184 // Compute the length of the server hierarchy 185 RuntimeType currType = (RuntimeType)typeOfObj.BaseType; 186 // typeOfObj is the root of all classes, but not included in the hierarachy. 187 Message.DebugOut("RemotingServices::TypeInfo: Determining length of server heirarchy\n"); 188 int hierarchyLen = 0; 189 while ((currType != typeof(MarshalByRefObject)) && 190 (currType != null)) 191 { 192 currType = (RuntimeType)currType.BaseType; 193 hierarchyLen++; 194 } 195 196 // Allocate an array big enough to store the hierarchy 197 Message.DebugOut("RemotingServices::TypeInfo: Determined length of server heirarchy\n"); 198 String[] serverHierarchy = null; 199 if (hierarchyLen > 0) 200 { 201 serverHierarchy = new String[hierarchyLen]; 202 203 currType = (RuntimeType)typeOfObj.BaseType; 204 for (int i = 0; i < hierarchyLen; i++) 205 { 206 serverHierarchy[i] = GetQualifiedTypeName(currType); 207 currType = (RuntimeType)currType.BaseType; 208 } 209 } 210 211 this.ServerHierarchy = serverHierarchy; 212 213 Message.DebugOut("RemotingServices::TypeInfo: Getting implemented interfaces\n"); 214 // Set the interfaces implemented 215 Type[] interfaces = typeOfObj.GetInterfaces(); 216 String[] interfaceNames = null; 217 // If the requested type itself is an interface we should add that to the 218 // interfaces list as well 219 bool isInterface = typeOfObj.IsInterface; 220 if (interfaces.Length > 0 || isInterface) 221 { 222 interfaceNames = new String[interfaces.Length + (isInterface ? 1 : 0)]; 223 for (int i = 0; i < interfaces.Length; i++) 224 { 225 interfaceNames[i] = GetQualifiedTypeName((RuntimeType)interfaces[i]); 226 } 227 if (isInterface) 228 interfaceNames[interfaceNames.Length - 1] = GetQualifiedTypeName(typeOfObj); 229 } 230 231 this.InterfacesImplemented = interfaceNames; 232 } // TypeInfo 233 234 internal String ServerType 235 { 236 get { return serverType; } 237 set { serverType = value; } 238 } 239 240 private String[] ServerHierarchy 241 { 242 get { return serverHierarchy;} 243 set { serverHierarchy = value;} 244 } 245 246 private String[] InterfacesImplemented 247 { 248 get { return interfacesImplemented;} 249 set { interfacesImplemented = value;} 250 } 251 252 [System.Security.SecurityCritical] // auto-generated CompareTypes(Type type1, String type2)253 private bool CompareTypes(Type type1, String type2) 254 { 255 Type type = RemotingServices.InternalGetTypeFromQualifiedTypeName(type2); 256 257 return type1 == type; 258 } 259 260 [System.Security.SecurityCritical] // auto-generated CanCastTo(Type castType, String[] types)261 private bool CanCastTo(Type castType, String[] types) 262 { 263 bool fCastOK = false; 264 265 // Run through the type names and see if there is a 266 // matching type 267 268 if (null != castType) 269 { 270 for (int i = 0; i < types.Length; i++) 271 { 272 if (CompareTypes(castType,types[i])) 273 { 274 fCastOK = true; 275 break; 276 } 277 } 278 } 279 280 Message.DebugOut("CanCastTo returning " + fCastOK + " for type " + castType.FullName + "\n"); 281 return fCastOK; 282 } 283 } 284 285 [Serializable] 286 internal class DynamicTypeInfo : TypeInfo 287 { 288 [System.Security.SecurityCritical] // auto-generated DynamicTypeInfo(RuntimeType typeOfObj)289 internal DynamicTypeInfo(RuntimeType typeOfObj) : base(typeOfObj) 290 { 291 } 292 [System.Security.SecurityCritical] // auto-generated CanCastTo(Type castType, Object o)293 public override bool CanCastTo(Type castType, Object o) 294 { 295 // < 296 297 return((MarshalByRefObject)o).IsInstanceOfType(castType); 298 } 299 } 300 301 [Serializable] 302 internal sealed class ChannelInfo : IChannelInfo 303 { 304 private Object[] channelData; 305 306 [System.Security.SecurityCritical] // auto-generated ChannelInfo()307 internal ChannelInfo() 308 { 309 ChannelData = ChannelServices.CurrentChannelData; 310 } 311 312 public Object[] ChannelData 313 { 314 [System.Security.SecurityCritical] // auto-generated 315 get { return channelData; } 316 [System.Security.SecurityCritical] // auto-generated 317 set { channelData = value; } 318 } 319 320 } 321 322 [Serializable] 323 internal sealed class EnvoyInfo : IEnvoyInfo 324 { 325 private IMessageSink envoySinks; 326 327 [System.Security.SecurityCritical] // auto-generated CreateEnvoyInfo(ServerIdentity serverID)328 internal static IEnvoyInfo CreateEnvoyInfo(ServerIdentity serverID) 329 { 330 IEnvoyInfo info = null; 331 if (null != serverID) 332 { 333 // Set the envoy sink chain 334 if (serverID.EnvoyChain == null) 335 { 336 // < 337 338 serverID.RaceSetEnvoyChain( 339 serverID.ServerContext.CreateEnvoyChain( 340 serverID.TPOrObject)); 341 } 342 343 // Create an envoy info object only if necessary 344 IMessageSink sink = serverID.EnvoyChain as EnvoyTerminatorSink; 345 if(null == sink) 346 { 347 // The chain consists of more than a terminator sink 348 // Go ahead and create an envoy info structure, otherwise 349 // a null is returned and we recreate the terminator sink 350 // on the other side, automatically. 351 info = new EnvoyInfo(serverID.EnvoyChain); 352 } 353 } 354 355 return info; 356 } 357 358 [System.Security.SecurityCritical] // auto-generated EnvoyInfo(IMessageSink sinks)359 private EnvoyInfo(IMessageSink sinks) 360 { 361 BCLDebug.Assert(null != sinks, "null != sinks"); 362 EnvoySinks = sinks; 363 } 364 365 public IMessageSink EnvoySinks 366 { 367 [System.Security.SecurityCritical] // auto-generated 368 get { return envoySinks;} 369 [System.Security.SecurityCritical] // auto-generated 370 set { envoySinks = value;} 371 } 372 } 373 374 [System.Security.SecurityCritical] // auto-generated_required 375 [Serializable] 376 [SecurityPermissionAttribute(SecurityAction.InheritanceDemand, Flags=SecurityPermissionFlag.Infrastructure)] 377 [System.Runtime.InteropServices.ComVisible(true)] 378 public class ObjRef : IObjectReference, ISerializable 379 { 380 // This flag is used to distinguish between the case where 381 // an actual object was marshaled as compared to the case 382 // where someone wants to pass the ObjRef itself to a remote call 383 internal const int FLG_MARSHALED_OBJECT = 0x00000001; 384 385 // This flag is used to mark a wellknown objRef (i.e. result 386 // of marshaling a proxy that was obtained through a Connect call) 387 internal const int FLG_WELLKNOWN_OBJREF = 0x00000002; 388 389 // This flag is used for a lightweight Object Reference. It is sent to those clients 390 // which are not interested in receiving a full-fledged ObjRef. An example 391 // of such a client will be a mobile device with hard memory and processing 392 // constraints. 393 // NOTE: In this case ALL the fields EXCEPT the uri/flags field are NULL. 394 internal const int FLG_LITE_OBJREF = 0x00000004; 395 396 internal const int FLG_PROXY_ATTRIBUTE = 0x00000008; 397 // 398 //If you change the fields here, you must all change them in 399 //RemotingSurrogate::GetObjectData 400 // 401 internal String uri; 402 internal IRemotingTypeInfo typeInfo; 403 internal IEnvoyInfo envoyInfo; 404 internal IChannelInfo channelInfo; 405 internal int objrefFlags; 406 internal GCHandle srvIdentity; 407 internal int domainID; 408 SetServerIdentity(GCHandle hndSrvIdentity)409 internal void SetServerIdentity(GCHandle hndSrvIdentity) 410 { 411 srvIdentity = hndSrvIdentity; 412 } 413 GetServerIdentity()414 internal GCHandle GetServerIdentity() 415 { 416 return srvIdentity; 417 } 418 SetDomainID(int id)419 internal void SetDomainID(int id) 420 { 421 domainID = id; 422 } 423 GetDomainID()424 internal int GetDomainID() 425 { 426 return domainID; 427 } 428 429 // Static fields 430 private static Type orType = typeof(ObjRef); 431 432 433 // shallow copy constructor used for smuggling. 434 [System.Security.SecurityCritical] // auto-generated ObjRef(ObjRef o)435 private ObjRef(ObjRef o) 436 { 437 BCLDebug.Assert(o.GetType() == typeof(ObjRef), "this should be just an ObjRef"); 438 439 uri = o.uri; 440 typeInfo = o.typeInfo; 441 envoyInfo = o.envoyInfo; 442 channelInfo = o.channelInfo; 443 objrefFlags = o.objrefFlags; 444 SetServerIdentity(o.GetServerIdentity()); 445 SetDomainID(o.GetDomainID()); 446 } // ObjRef 447 448 [System.Security.SecurityCritical] // auto-generated ObjRef(MarshalByRefObject o, Type requestedType)449 public ObjRef(MarshalByRefObject o, Type requestedType) 450 { 451 bool fServer; 452 453 if (o == null) 454 { 455 throw new ArgumentNullException("o"); 456 } 457 RuntimeType rt = requestedType as RuntimeType; 458 if (requestedType != null && rt == null) 459 throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType")); 460 461 Identity id = MarshalByRefObject.GetIdentity(o, out fServer); 462 Init(o, id, rt); 463 } 464 465 [System.Security.SecurityCritical] // auto-generated ObjRef(SerializationInfo info, StreamingContext context)466 protected ObjRef(SerializationInfo info, StreamingContext context) 467 { 468 String url = null; // an objref lite url 469 bool bFoundFIsMarshalled = false; 470 471 SerializationInfoEnumerator e = info.GetEnumerator(); 472 while (e.MoveNext()) 473 { 474 if (e.Name.Equals("uri")) 475 { 476 uri = (String) e.Value; 477 } 478 else if (e.Name.Equals("typeInfo")) 479 { 480 typeInfo = (IRemotingTypeInfo) e.Value; 481 } 482 else if (e.Name.Equals("envoyInfo")) 483 { 484 envoyInfo = (IEnvoyInfo) e.Value; 485 } 486 else if (e.Name.Equals("channelInfo")) 487 { 488 channelInfo = (IChannelInfo) e.Value; 489 } 490 else if (e.Name.Equals("objrefFlags")) 491 { 492 Object o = e.Value; 493 if(o.GetType() == typeof(String)) 494 { 495 objrefFlags = ((IConvertible)o).ToInt32(null); 496 } 497 else 498 { 499 objrefFlags = (int)o; 500 } 501 } 502 else if (e.Name.Equals("fIsMarshalled")) 503 { 504 int value; 505 Object o = e.Value; 506 if(o.GetType() == typeof(String)) 507 value = ((IConvertible)o).ToInt32(null); 508 else 509 value = (int)o; 510 511 if (value == 0) 512 bFoundFIsMarshalled = true; 513 } 514 else if (e.Name.Equals("url")) 515 { 516 url = (String)e.Value; 517 } 518 else if (e.Name.Equals("SrvIdentity")) 519 { 520 SetServerIdentity((GCHandle)e.Value); 521 } 522 else if (e.Name.Equals("DomainId")) 523 { 524 SetDomainID((int)e.Value); 525 } 526 } 527 528 if (!bFoundFIsMarshalled) 529 { 530 // This ObjRef was not passed as a parameter, so we need to unmarshal it. 531 objrefFlags |= FLG_MARSHALED_OBJECT; 532 } 533 else 534 objrefFlags &= ~FLG_MARSHALED_OBJECT; 535 536 // If only url is present, then it is an ObjRefLite. 537 if (url != null) 538 { 539 uri = url; 540 objrefFlags |= FLG_LITE_OBJREF; 541 } 542 543 } // ObjRef .ctor 544 545 546 [System.Security.SecurityCritical] // auto-generated CanSmuggle()547 internal bool CanSmuggle() 548 { 549 // make sure this isn't a derived class or an ObjRefLite 550 if ((this.GetType() != typeof(ObjRef)) || IsObjRefLite()) 551 return false; 552 553 Type typeOfTypeInfo = null; 554 if (typeInfo != null) 555 typeOfTypeInfo = typeInfo.GetType(); 556 557 Type typeOfChannelInfo = null; 558 if (channelInfo != null) 559 typeOfChannelInfo = channelInfo.GetType(); 560 561 if (((typeOfTypeInfo == null) || 562 (typeOfTypeInfo == typeof(TypeInfo)) || 563 (typeOfTypeInfo == typeof(DynamicTypeInfo))) && 564 (envoyInfo == null) && 565 ((typeOfChannelInfo == null) || 566 (typeOfChannelInfo == typeof(ChannelInfo)))) 567 { 568 if (channelInfo != null) 569 { 570 foreach (Object channelData in channelInfo.ChannelData) 571 { 572 // Only consider CrossAppDomainData smuggleable. 573 if (!(channelData is CrossAppDomainData)) 574 { 575 return false; 576 } 577 } 578 } 579 580 return true; 581 } 582 else 583 { 584 return false; 585 } 586 } // CanSmuggle 587 588 [System.Security.SecurityCritical] // auto-generated CreateSmuggleableCopy()589 internal ObjRef CreateSmuggleableCopy() 590 { 591 BCLDebug.Assert(CanSmuggle(), "Caller should have made sure that CanSmuggle() was true first."); 592 593 return new ObjRef(this); 594 } // CreateSmuggleableCopy 595 596 597 [System.Security.SecurityCritical] // auto-generated_required GetObjectData(SerializationInfo info, StreamingContext context)598 public virtual void GetObjectData(SerializationInfo info, StreamingContext context) 599 { 600 if (info==null) { 601 throw new ArgumentNullException("info"); 602 } 603 604 info.SetType(orType); 605 606 if(!IsObjRefLite()) 607 { 608 info.AddValue("uri", uri, typeof(String)); 609 info.AddValue("objrefFlags", (int) objrefFlags); 610 info.AddValue("typeInfo", typeInfo, typeof(IRemotingTypeInfo)); 611 info.AddValue("envoyInfo", envoyInfo, typeof(IEnvoyInfo)); 612 info.AddValue("channelInfo", GetChannelInfoHelper(), typeof(IChannelInfo)); 613 } 614 else 615 { 616 info.AddValue("url", uri, typeof(String)); 617 } 618 } // GetObjectDataHelper 619 620 621 // This method retrieves the channel info object to be serialized. 622 // It does special checking to see if a channel url needs to be bashed 623 // (currently used for switching "http://..." url to "https://...". 624 [System.Security.SecurityCritical] // auto-generated GetChannelInfoHelper()625 private IChannelInfo GetChannelInfoHelper() 626 { 627 ChannelInfo oldChannelInfo = channelInfo as ChannelInfo; 628 if (oldChannelInfo == null) 629 return channelInfo; 630 631 Object[] oldChannelData = oldChannelInfo.ChannelData; 632 if (oldChannelData == null) 633 return oldChannelInfo; 634 635 // < 636 637 638 String[] bashInfo = (String[])CallContext.GetData("__bashChannelUrl"); 639 if (bashInfo == null) 640 return oldChannelInfo; 641 642 String urlToBash = bashInfo[0]; 643 String replacementUrl = bashInfo[1]; 644 645 // Copy channel info and go Microsoft urls. 646 ChannelInfo newChInfo = new ChannelInfo(); 647 newChInfo.ChannelData = new Object[oldChannelData.Length]; 648 for (int co = 0; co < oldChannelData.Length; co++) 649 { 650 newChInfo.ChannelData[co] = oldChannelData[co]; 651 652 // see if this is one of the ones that we need to Microsoft 653 ChannelDataStore channelDataStore = newChInfo.ChannelData[co] as ChannelDataStore; 654 if (channelDataStore != null) 655 { 656 String[] urls = channelDataStore.ChannelUris; 657 if ((urls != null) && (urls.Length == 1) && urls[0].Equals(urlToBash)) 658 { 659 // We want to Microsoft just the url, so we do a shallow copy 660 // and replace the url array with the replacementUrl. 661 ChannelDataStore newChannelDataStore = channelDataStore.InternalShallowCopy(); 662 newChannelDataStore.ChannelUris = new String[1]; 663 newChannelDataStore.ChannelUris[0] = replacementUrl; 664 665 newChInfo.ChannelData[co] = newChannelDataStore; 666 } 667 } 668 } 669 670 return newChInfo; 671 } // GetChannelInfoHelper 672 673 674 675 // Note: The uri will be either objURI (for normal marshals) or 676 // it will be the URL if a wellknown object's proxy is marshaled 677 // Basically we will take whatever the URI getter on Identity gives us 678 679 public virtual String URI 680 { 681 get { return uri;} 682 set { uri = value;} 683 } 684 685 public virtual IRemotingTypeInfo TypeInfo 686 { 687 get { return typeInfo;} 688 set { typeInfo = value;} 689 } 690 691 public virtual IEnvoyInfo EnvoyInfo 692 { 693 get { return envoyInfo;} 694 set { envoyInfo = value;} 695 } 696 697 public virtual IChannelInfo ChannelInfo 698 { 699 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] 700 get { return channelInfo;} 701 set { channelInfo = value;} 702 } 703 704 705 // This is called when doing fix-ups during deserialization 706 [System.Security.SecurityCritical] // auto-generated_required GetRealObject(StreamingContext context)707 public virtual Object GetRealObject(StreamingContext context) 708 { 709 return GetRealObjectHelper(); 710 } 711 // This is the common helper called by serialization / smuggling 712 [System.Security.SecurityCritical] // auto-generated GetRealObjectHelper()713 internal Object GetRealObjectHelper() 714 715 { 716 // Check if we are a result of serialiazing an MBR object 717 // or if someone wanted to pass an ObjRef itself 718 if (!IsMarshaledObject()) 719 { 720 BCLDebug.Trace("REMOTE", "ObjRef.GetRealObject: Returning *this*\n"); 721 return this; 722 } 723 else 724 { 725 // Check if this is a lightweight objref 726 if(IsObjRefLite()) 727 { 728 BCLDebug.Assert(null != uri, "null != uri"); 729 730 // transform the url, if this is a local object (we know it is local 731 // if we find the current application id in the url) 732 int index = uri.IndexOf(RemotingConfiguration.ApplicationId); 733 734 // we need to be past 0, since we have to back up a space and pick up 735 // a slash. 736 if (index > 0) 737 uri = uri.Substring(index - 1); 738 } 739 740 // In the general case, 'this' is the 741 // objref of an activated object 742 743 // It may also be a well known object ref ... which came by 744 // because someone did a Connect(URL) and then passed the proxy 745 // over to a remote method call. 746 747 // The below call handles both cases. 748 bool fRefine = !(GetType() == typeof(ObjRef)); 749 Object ret = RemotingServices.Unmarshal(this, fRefine); 750 751 // Check for COMObject & do some special custom marshaling 752 ret = GetCustomMarshaledCOMObject(ret); 753 754 return ret; 755 } 756 757 } 758 759 [System.Security.SecurityCritical] // auto-generated GetCustomMarshaledCOMObject(Object ret)760 private Object GetCustomMarshaledCOMObject(Object ret) 761 { 762 // Some special work we need to do for __COMObject 763 // (Note that we use typeInfo to detect this case instead of 764 // calling GetType on 'ret' so as to not refine the proxy) 765 DynamicTypeInfo dt = this.TypeInfo as DynamicTypeInfo; 766 if (dt != null) 767 { 768 // This is a COMObject type ... we do the special work 769 // only if it is from the same process but another appDomain 770 // We rely on the x-appDomain channel data in the objRef 771 // to provide us with the answers. 772 Object ret1 = null; 773 IntPtr pUnk = IntPtr.Zero; 774 if (IsFromThisProcess() && !IsFromThisAppDomain()) 775 { 776 try 777 { 778 bool fIsURTAggregated; 779 pUnk = ((__ComObject)ret).GetIUnknown(out fIsURTAggregated); 780 if (pUnk != IntPtr.Zero && !fIsURTAggregated) 781 { 782 // The RCW for an IUnk is per-domain. This call 783 // gets (or creates) the RCW for this pUnk for 784 // the current domain. 785 String srvTypeName = TypeInfo.TypeName; 786 String typeName = null; 787 String assemName = null; 788 789 System.Runtime.Remoting.TypeInfo.ParseTypeAndAssembly(srvTypeName, out typeName, out assemName); 790 BCLDebug.Assert((null != typeName) && (null != assemName), "non-null values expected"); 791 792 Assembly asm = FormatterServices.LoadAssemblyFromStringNoThrow(assemName); 793 if (asm==null) { 794 BCLDebug.Trace("REMOTE", "ObjRef.GetCustomMarshaledCOMObject. AssemblyName is: ", assemName, " but we can't load it."); 795 throw new RemotingException(Environment.GetResourceString("Serialization_AssemblyNotFound", assemName)); 796 } 797 798 Type serverType = asm.GetType(typeName, false, false); 799 if (serverType != null && !serverType.IsVisible) 800 serverType = null; 801 BCLDebug.Assert(serverType!=null, "bad objRef!"); 802 803 ret1 = InteropServices.Marshal.GetTypedObjectForIUnknown(pUnk, serverType); 804 if (ret1 != null) 805 { 806 ret = ret1; 807 } 808 } 809 } 810 finally 811 { 812 if (pUnk != IntPtr.Zero) 813 { 814 InteropServices.Marshal.Release(pUnk); 815 } 816 } 817 } 818 } 819 return ret; 820 } 821 ObjRef()822 public ObjRef() 823 { 824 objrefFlags = 0x0; 825 } 826 IsMarshaledObject()827 internal bool IsMarshaledObject() 828 { 829 return (objrefFlags & FLG_MARSHALED_OBJECT) == FLG_MARSHALED_OBJECT; 830 } 831 SetMarshaledObject()832 internal void SetMarshaledObject() 833 { 834 objrefFlags |= FLG_MARSHALED_OBJECT; 835 } 836 837 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] IsWellKnown()838 internal bool IsWellKnown() 839 { 840 return (objrefFlags & FLG_WELLKNOWN_OBJREF) == FLG_WELLKNOWN_OBJREF; 841 } 842 SetWellKnown()843 internal void SetWellKnown() 844 { 845 objrefFlags |= FLG_WELLKNOWN_OBJREF; 846 } 847 HasProxyAttribute()848 internal bool HasProxyAttribute() 849 { 850 return (objrefFlags & FLG_PROXY_ATTRIBUTE) == FLG_PROXY_ATTRIBUTE; 851 } 852 SetHasProxyAttribute()853 internal void SetHasProxyAttribute() 854 { 855 objrefFlags |= FLG_PROXY_ATTRIBUTE; 856 } 857 IsObjRefLite()858 internal bool IsObjRefLite() 859 { 860 return (objrefFlags & FLG_LITE_OBJREF) == FLG_LITE_OBJREF; 861 } 862 SetObjRefLite()863 internal void SetObjRefLite() 864 { 865 objrefFlags |= FLG_LITE_OBJREF; 866 } 867 868 [System.Security.SecurityCritical] // auto-generated 869 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] GetAppDomainChannelData()870 private CrossAppDomainData GetAppDomainChannelData() 871 { 872 BCLDebug.Assert( 873 ObjRef.IsWellFormed(this), 874 "ObjRef.IsWellFormed()"); 875 876 // Look at the ChannelData part to find CrossAppDomainData 877 int i=0; 878 CrossAppDomainData xadData = null; 879 while (i<ChannelInfo.ChannelData.Length) 880 { 881 xadData = ChannelInfo.ChannelData[i] as CrossAppDomainData; 882 if (null != xadData) 883 { 884 return xadData; 885 } 886 i++; 887 } 888 889 // AdData could be null for user-created objRefs. 890 return null; 891 } 892 893 [System.Security.SecurityCritical] // auto-generated 894 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] IsFromThisProcess()895 public bool IsFromThisProcess() 896 { 897 //Wellknown objects may or may not be in the same process 898 //Hence return false; 899 if (IsWellKnown()) 900 return false; 901 902 CrossAppDomainData xadData = GetAppDomainChannelData(); 903 if (xadData != null) 904 { 905 return xadData.IsFromThisProcess(); 906 } 907 return false; 908 } 909 910 [System.Security.SecurityCritical] // auto-generated IsFromThisAppDomain()911 public bool IsFromThisAppDomain() 912 { 913 CrossAppDomainData xadData = GetAppDomainChannelData(); 914 if (xadData != null) 915 { 916 return xadData.IsFromThisAppDomain(); 917 } 918 return false; 919 } 920 921 // returns the internal context ID for the server context if 922 // it is from the same process && the appDomain of the server 923 // is still valid. If the objRef is from this process, the domain 924 // id found in the objref is always returned. 925 926 [System.Security.SecurityCritical] // auto-generated 927 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] GetServerDomainId()928 internal Int32 GetServerDomainId() 929 { 930 if (!IsFromThisProcess()) 931 return 0; 932 CrossAppDomainData xadData = GetAppDomainChannelData(); 933 BCLDebug.Assert(xadData != null, "bad objRef?"); 934 return xadData.DomainID; 935 936 } 937 938 [System.Security.SecurityCritical] // auto-generated GetServerContext(out int domainId)939 internal IntPtr GetServerContext(out int domainId) 940 { 941 IntPtr contextId = IntPtr.Zero; 942 domainId = 0; 943 if (IsFromThisProcess()) 944 { 945 CrossAppDomainData xadData = GetAppDomainChannelData(); 946 BCLDebug.Assert(xadData != null, "bad objRef?"); 947 domainId = xadData.DomainID; 948 if (AppDomain.IsDomainIdValid(xadData.DomainID)) 949 { 950 contextId = xadData.ContextID; 951 } 952 } 953 return contextId; 954 } 955 956 // 957 // 958 [System.Security.SecurityCritical] // auto-generated Init(Object o, Identity idObj, RuntimeType requestedType)959 internal void Init(Object o, Identity idObj, RuntimeType requestedType) 960 { 961 Message.DebugOut("RemotingServices::FillObjRef: IN"); 962 BCLDebug.Assert(idObj != null,"idObj != null"); 963 964 // Set the URI of the object to be marshaled 965 uri = idObj.URI; 966 967 // Figure out the type 968 MarshalByRefObject obj = idObj.TPOrObject; 969 BCLDebug.Assert(null != obj, "Identity not setup correctly"); 970 971 // Get the type of the object 972 RuntimeType serverType = null; 973 if(!RemotingServices.IsTransparentProxy(obj)) 974 { 975 serverType = (RuntimeType)obj.GetType(); 976 } 977 else 978 { 979 serverType = (RuntimeType)RemotingServices.GetRealProxy(obj).GetProxiedType(); 980 } 981 982 RuntimeType typeOfObj = (null == requestedType ? serverType : requestedType); 983 984 // Make sure that the server and requested types are compatible 985 // (except for objects that implement IMessageSink, since we 986 // just hand off the message instead of invoking the proxy) 987 if ((null != requestedType) && 988 !requestedType.IsAssignableFrom(serverType) && 989 (!typeof(IMessageSink).IsAssignableFrom(serverType))) 990 { 991 throw new RemotingException( 992 String.Format( 993 CultureInfo.CurrentCulture, Environment.GetResourceString( 994 "Remoting_InvalidRequestedType"), 995 requestedType.ToString())); ; 996 } 997 998 // Create the type info 999 if(serverType.IsCOMObject) 1000 { 1001 // __ComObjects need dynamic TypeInfo 1002 DynamicTypeInfo dt = new DynamicTypeInfo(typeOfObj); 1003 TypeInfo = (IRemotingTypeInfo) dt; 1004 } 1005 else 1006 { 1007 RemotingTypeCachedData cache = (RemotingTypeCachedData) 1008 InternalRemotingServices.GetReflectionCachedData(typeOfObj); 1009 1010 TypeInfo = (IRemotingTypeInfo)cache.TypeInfo; 1011 } 1012 1013 if (!idObj.IsWellKnown()) 1014 { 1015 // Create the envoy info 1016 EnvoyInfo = System.Runtime.Remoting.EnvoyInfo.CreateEnvoyInfo(idObj as ServerIdentity); 1017 1018 // Create the channel info 1019 IChannelInfo chan = (IChannelInfo)new ChannelInfo(); 1020 // Make sure the channelInfo only has x-appdomain data since the objref is agile while other 1021 // channelData might not be and regardless this data is useless for an appdomain proxy 1022 if (o is AppDomain){ 1023 Object[] channelData = chan.ChannelData; 1024 int channelDataLength = channelData.Length; 1025 Object[] newChannelData = new Object[channelDataLength]; 1026 // Clone the data so that we dont Microsoft the current appdomain data which is stored 1027 // as a static 1028 Array.Copy(channelData, newChannelData, channelDataLength); 1029 for (int i = 0; i < channelDataLength; i++) 1030 { 1031 if (!(newChannelData[i] is CrossAppDomainData)) 1032 newChannelData[i] = null; 1033 } 1034 chan.ChannelData = newChannelData; 1035 } 1036 ChannelInfo = chan; 1037 1038 if (serverType.HasProxyAttribute) 1039 { 1040 SetHasProxyAttribute(); 1041 } 1042 } 1043 else 1044 { 1045 SetWellKnown(); 1046 } 1047 1048 // See if we should and can use a url obj ref? 1049 if (ShouldUseUrlObjRef()) 1050 { 1051 if (IsWellKnown()) 1052 { 1053 // full uri already supplied. 1054 SetObjRefLite(); 1055 } 1056 else 1057 { 1058 String httpUri = ChannelServices.FindFirstHttpUrlForObject(URI); 1059 if (httpUri != null) 1060 { 1061 URI = httpUri; 1062 SetObjRefLite(); 1063 } 1064 } 1065 } 1066 } // Init 1067 1068 1069 // determines if a particular type should use a url obj ref ShouldUseUrlObjRef()1070 internal static bool ShouldUseUrlObjRef() 1071 { 1072 return RemotingConfigHandler.UrlObjRefMode; 1073 } // ShouldUseUrlObjRef 1074 1075 1076 // Check whether the objref is well formed 1077 [System.Security.SecurityCritical] // auto-generated IsWellFormed(ObjRef objectRef)1078 internal static bool IsWellFormed(ObjRef objectRef) 1079 { 1080 // We skip the wellformed check for wellKnown, 1081 // objref-lite and custom objrefs 1082 bool wellFormed = true; 1083 if ((null == objectRef) || 1084 (null == objectRef.URI) || 1085 (!(objectRef.IsWellKnown() || objectRef.IsObjRefLite() || 1086 objectRef.GetType() != orType) 1087 && (null == objectRef.ChannelInfo))) 1088 { 1089 wellFormed = false; 1090 } 1091 1092 return wellFormed; 1093 } 1094 } // ObjRef 1095 1096 1097 } 1098