Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / mscorlib / system / runtime / remoting / objref.cs
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
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
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
144         internal static String GetQualifiedTypeName(RuntimeType type)
145         {
146             if (type == null)
147                 return null;
148                 
149             return RemotingServices.GetDefaultQualifiedTypeName(type);
150         }
151
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
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
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
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
289         internal DynamicTypeInfo(RuntimeType typeOfObj) : base(typeOfObj)
290         {
291         }
292         [System.Security.SecurityCritical]  // auto-generated
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
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
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
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
409         internal void SetServerIdentity(GCHandle hndSrvIdentity)
410         {
411             srvIdentity = hndSrvIdentity;
412         }
413
414         internal GCHandle GetServerIdentity()
415         {
416             return srvIdentity;
417         }
418
419         internal void SetDomainID(int id)
420         {
421             domainID = id;
422         }
423
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
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
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
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
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
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
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
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
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
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
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
822         public ObjRef()
823         {
824             objrefFlags = 0x0;
825         }
826
827         internal bool IsMarshaledObject()
828         {
829             return (objrefFlags & FLG_MARSHALED_OBJECT) == FLG_MARSHALED_OBJECT;
830         }
831
832         internal void SetMarshaledObject()
833         {
834             objrefFlags |= FLG_MARSHALED_OBJECT;
835         }
836
837         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]  
838         internal bool IsWellKnown()
839         {
840             return (objrefFlags & FLG_WELLKNOWN_OBJREF) == FLG_WELLKNOWN_OBJREF;
841         }
842
843         internal void SetWellKnown()
844         {
845             objrefFlags |= FLG_WELLKNOWN_OBJREF;
846         }
847
848         internal bool HasProxyAttribute()
849         {
850             return (objrefFlags & FLG_PROXY_ATTRIBUTE) == FLG_PROXY_ATTRIBUTE;
851         }
852
853         internal void SetHasProxyAttribute()
854         {
855             objrefFlags |= FLG_PROXY_ATTRIBUTE;
856         }
857
858         internal bool IsObjRefLite()
859         {
860             return (objrefFlags & FLG_LITE_OBJREF) == FLG_LITE_OBJREF;
861         }
862
863         internal void SetObjRefLite()
864         {
865             objrefFlags |= FLG_LITE_OBJREF;
866         }
867
868         [System.Security.SecurityCritical]  // auto-generated
869         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]  
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)]  
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
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)]  
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
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
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
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
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 }