File: system\runtime\remoting\objref.cs
Project: ndp\clr\src\bcl\mscorlib.csproj (mscorlib)
// ==++==
// 
//   Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// ==--==
/*============================================================
**
** File:    ObjRef.cs
**
**
** Purpose: Defines the marshaled object reference class and related 
**          classes
**
**
**
===========================================================*/
namespace System.Runtime.Remoting {
 
    using System;
    using System.Threading;
    using System.Runtime.InteropServices;
    using System.Runtime.Remoting;
    using System.Runtime.Remoting.Channels;
    using System.Runtime.Remoting.Contexts;
    using System.Runtime.Remoting.Messaging;    
    using System.Runtime.Remoting.Metadata;
    using System.Runtime.Serialization;
    using System.Reflection;
    using System.Security.Permissions;
    using Win32Native = Microsoft.Win32.Win32Native;
    using System.Runtime.ConstrainedExecution;
    using System.Globalization;
    
 
    
    //** Purpose: Interface for providing type information. Users can use this
    //**          interface to provide custom type information which is carried
    //**          along with the ObjRef.
    [System.Runtime.InteropServices.ComVisible(true)]
    public interface IRemotingTypeInfo
    {
        // Return the fully qualified type name 
        String TypeName
        {
            [System.Security.SecurityCritical]  // auto-generated_required
            get;
            [System.Security.SecurityCritical]  // auto-generated_required
            set;
        }
 
        // Check whether the given type can be cast to the type this
        // interface represents
        [System.Security.SecurityCritical]  // auto-generated_required
        bool CanCastTo(Type fromType, Object o);    
    }
 
    //** Purpose: Interface for providing channel information. Users can use this
    //**          interface to provide custom channel information which is carried
    //**          along with the ObjRef.
    [System.Runtime.InteropServices.ComVisible(true)]
    public interface IChannelInfo
    {
        // Get/Set the channel data for each channel 
        Object[] ChannelData
        {
            [System.Security.SecurityCritical]  // auto-generated_required
            get;
            [System.Security.SecurityCritical]  // auto-generated_required
            set;
        }
    }
 
    //** Purpose: Interface for providing envoy information. Users can use this
    //**          interface to provide custom envoy information which is carried
    //**          along with the ObjRef.
    [System.Runtime.InteropServices.ComVisible(true)]
    public interface IEnvoyInfo
    {
        // Get/Set the envoy sinks 
        IMessageSink EnvoySinks
        {
            [System.Security.SecurityCritical]  // auto-generated_required
            get;
            [System.Security.SecurityCritical]  // auto-generated_required
            set;
        }
    }
 
    
 
    [Serializable]
    internal class TypeInfo : IRemotingTypeInfo
    {   
        private String              serverType;
        private String[]            serverHierarchy;
        private String[]            interfacesImplemented;
 
        // Return the fully qualified type name 
        public virtual String TypeName
        {
            [System.Security.SecurityCritical]  // auto-generated
            get { return serverType;}
            [System.Security.SecurityCritical]  // auto-generated
            set { serverType = value;}
        }
 
        // Check whether the given type can be cast to the type this
        // interface represents
        [System.Security.SecurityCritical]  // auto-generated
        public virtual bool CanCastTo(Type castType, Object o)
        {
            if (null != castType)
            {
                // check for System.Object and MBRO since those aren't included in the
                //   heirarchy
                if ((castType == typeof(MarshalByRefObject)) ||
                    (castType == typeof(System.Object)))
                {
                    return true;
                }
                else
                if (castType.IsInterface)
                { 
                    if (interfacesImplemented != null)
                        return CanCastTo(castType, InterfacesImplemented);
                    else
                        return false;
                }
                else
                if (castType.IsMarshalByRef)                
                {
                    if (CompareTypes(castType, serverType))
                        return true;
                
                    if ((serverHierarchy != null) && CanCastTo(castType, ServerHierarchy))
                        return true;
                }
            }
 
            return false;
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        internal static String GetQualifiedTypeName(RuntimeType type)
        {
            if (type == null)
                return null;
                
            return RemotingServices.GetDefaultQualifiedTypeName(type);
        }
 
        internal static bool ParseTypeAndAssembly(String typeAndAssembly, out String typeName, out String assemName)
        {
            if (typeAndAssembly == null)
            {
                typeName = null;
                assemName = null;
                return false;
            }
            
            int index = typeAndAssembly.IndexOf(',');
            if (index == -1)
            {
                typeName = typeAndAssembly;
                assemName = null;
                return true;
            }
 
            // type name is everything up to the first comma
            typeName = typeAndAssembly.Substring(0, index); 
 
            // assembly name is the rest
            assemName = typeAndAssembly.Substring(index + 1).Trim();
                        
            return true;
        } // ParseTypeAndAssembly
        
 
        [System.Security.SecurityCritical]  // auto-generated
        internal TypeInfo(RuntimeType typeOfObj)
        {
            ServerType = GetQualifiedTypeName(typeOfObj);        
 
            // Compute the length of the server hierarchy
            RuntimeType currType = (RuntimeType)typeOfObj.BaseType;
            // typeOfObj is the root of all classes, but not included in the hierarachy.
            Message.DebugOut("RemotingServices::TypeInfo: Determining length of server heirarchy\n");
            int hierarchyLen = 0;
            while ((currType != typeof(MarshalByRefObject)) && 
                   (currType != null))
            {
                currType = (RuntimeType)currType.BaseType;
                hierarchyLen++;
            }
 
            // Allocate an array big enough to store the hierarchy            
            Message.DebugOut("RemotingServices::TypeInfo: Determined length of server heirarchy\n");
            String[] serverHierarchy = null;
            if (hierarchyLen > 0)
            {
                serverHierarchy = new String[hierarchyLen]; 
            
                currType = (RuntimeType)typeOfObj.BaseType;
                for (int i = 0; i < hierarchyLen; i++)
                {
                    serverHierarchy[i] = GetQualifiedTypeName(currType);
                    currType = (RuntimeType)currType.BaseType;
                }
            }
 
            this.ServerHierarchy = serverHierarchy;
 
            Message.DebugOut("RemotingServices::TypeInfo: Getting implemented interfaces\n");
            // Set the interfaces implemented
            Type[] interfaces = typeOfObj.GetInterfaces();
            String[] interfaceNames = null;
            // If the requested type itself is an interface we should add that to the
            // interfaces list as well
            bool isInterface = typeOfObj.IsInterface;
            if (interfaces.Length > 0 || isInterface)
            {
                interfaceNames = new String[interfaces.Length + (isInterface ? 1 : 0)];
                for (int i = 0; i < interfaces.Length; i++)
                {
                    interfaceNames[i] = GetQualifiedTypeName((RuntimeType)interfaces[i]);
                }
                if (isInterface)
                    interfaceNames[interfaceNames.Length - 1] = GetQualifiedTypeName(typeOfObj); 
            }
 
            this.InterfacesImplemented = interfaceNames;
        } // TypeInfo
 
        internal String ServerType 
        {
            get { return serverType; }
            set { serverType = value; }
        }
 
        private String[] ServerHierarchy
        {
            get { return serverHierarchy;}
            set { serverHierarchy = value;}
        }
 
        private String[] InterfacesImplemented
        {
            get { return interfacesImplemented;}
            set { interfacesImplemented = value;}
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        private bool CompareTypes(Type type1, String type2)
        {
            Type type = RemotingServices.InternalGetTypeFromQualifiedTypeName(type2);
 
            return type1 == type;
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        private bool CanCastTo(Type castType, String[] types)
        {
            bool fCastOK = false;
 
            // Run through the type names and see if there is a 
            // matching type
            
            if (null != castType)
            {
                for (int i = 0; i < types.Length; i++)
                {
                    if (CompareTypes(castType,types[i]))
                    {
                        fCastOK = true;
                        break;
                    }
                }
            }
 
            Message.DebugOut("CanCastTo returning " + fCastOK + " for type " + castType.FullName + "\n");
            return fCastOK;
        }
    }
 
    [Serializable]
    internal class DynamicTypeInfo : TypeInfo
    {
        [System.Security.SecurityCritical]  // auto-generated
        internal DynamicTypeInfo(RuntimeType typeOfObj) : base(typeOfObj)
        {
        }
        [System.Security.SecurityCritical]  // auto-generated
        public override bool CanCastTo(Type castType, Object o)
        {
            // <
 
            return((MarshalByRefObject)o).IsInstanceOfType(castType);
        }
    }
 
    [Serializable]
    internal sealed class ChannelInfo : IChannelInfo
    {
        private Object[]     channelData;
 
        [System.Security.SecurityCritical]  // auto-generated
        internal ChannelInfo()
        {
            ChannelData = ChannelServices.CurrentChannelData;
        }
 
        public Object[] ChannelData
        {
            [System.Security.SecurityCritical]  // auto-generated
            get { return channelData; }
            [System.Security.SecurityCritical]  // auto-generated
            set { channelData = value; }
        }             
 
    }
 
    [Serializable]
    internal sealed class EnvoyInfo : IEnvoyInfo
    {
        private IMessageSink envoySinks;
 
        [System.Security.SecurityCritical]  // auto-generated
        internal static IEnvoyInfo CreateEnvoyInfo(ServerIdentity serverID)
        {
            IEnvoyInfo info = null;
            if (null != serverID)
            {
                // Set the envoy sink chain
                if (serverID.EnvoyChain == null)
                {
                    // <
 
                    serverID.RaceSetEnvoyChain(
                        serverID.ServerContext.CreateEnvoyChain(
                            serverID.TPOrObject));
                }
 
                // Create an envoy info object only if necessary
                IMessageSink sink = serverID.EnvoyChain as EnvoyTerminatorSink;
                if(null == sink)
                {
                    // The chain consists of more than a terminator sink
                    // Go ahead and create an envoy info structure, otherwise
                    // a null is returned and we recreate the terminator sink
                    // on the other side, automatically.
                    info = new EnvoyInfo(serverID.EnvoyChain);
                }
            }
 
            return info;
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        private EnvoyInfo(IMessageSink sinks)
        {
            BCLDebug.Assert(null != sinks, "null != sinks");
            EnvoySinks = sinks;
        }
 
        public IMessageSink EnvoySinks
        {
            [System.Security.SecurityCritical]  // auto-generated
            get { return envoySinks;}
            [System.Security.SecurityCritical]  // auto-generated
            set { envoySinks = value;}
        }
    }
 
    [System.Security.SecurityCritical]  // auto-generated_required
    [Serializable]
    [SecurityPermissionAttribute(SecurityAction.InheritanceDemand, Flags=SecurityPermissionFlag.Infrastructure)]    
    [System.Runtime.InteropServices.ComVisible(true)]
    public class ObjRef : IObjectReference, ISerializable
    {
        // This flag is used to distinguish between the case where
        // an actual object was marshaled as compared to the case
        // where someone wants to pass the ObjRef itself to a remote call
        internal const int FLG_MARSHALED_OBJECT  = 0x00000001;
 
        // This flag is used to mark a wellknown objRef (i.e. result
        // of marshaling a proxy that was obtained through a Connect call)
        internal const int FLG_WELLKNOWN_OBJREF  = 0x00000002;
 
        // This flag is used for a lightweight Object Reference. It is sent to those clients
        // which are not interested in receiving a full-fledged ObjRef. An example
        // of such a client will be a mobile device with hard memory and processing
        // constraints. 
        // NOTE: In this case ALL the fields EXCEPT the uri/flags field are NULL.
        internal const int FLG_LITE_OBJREF       = 0x00000004;
 
        internal const int FLG_PROXY_ATTRIBUTE   = 0x00000008;
        //
        //If you change the fields here, you must all change them in 
        //RemotingSurrogate::GetObjectData
        //
        internal String                 uri;
        internal IRemotingTypeInfo      typeInfo;
        internal IEnvoyInfo             envoyInfo;
        internal IChannelInfo           channelInfo;
        internal int                    objrefFlags;
        internal GCHandle               srvIdentity;
        internal int                    domainID;
 
        internal void SetServerIdentity(GCHandle hndSrvIdentity)
        {
            srvIdentity = hndSrvIdentity;
        }
 
        internal GCHandle GetServerIdentity()
        {
            return srvIdentity;
        }
 
        internal void SetDomainID(int id)
        {
            domainID = id;
        }
 
        internal int GetDomainID()
        {
            return domainID;
        }
        
        // Static fields
        private static Type orType = typeof(ObjRef);
 
 
        // shallow copy constructor used for smuggling.
        [System.Security.SecurityCritical]  // auto-generated
        private ObjRef(ObjRef o)
        {
            BCLDebug.Assert(o.GetType() == typeof(ObjRef), "this should be just an ObjRef");
 
            uri = o.uri;
            typeInfo = o.typeInfo;
            envoyInfo = o.envoyInfo;
            channelInfo = o.channelInfo;
            objrefFlags = o.objrefFlags;
            SetServerIdentity(o.GetServerIdentity());
            SetDomainID(o.GetDomainID());
        } // ObjRef
 
        [System.Security.SecurityCritical]  // auto-generated
        public ObjRef(MarshalByRefObject o, Type requestedType)
        {
            bool fServer;
            
            if (o == null)
            {
                throw new ArgumentNullException("o");
            }
            RuntimeType rt = requestedType as RuntimeType;
            if (requestedType != null && rt == null)
                throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"));
 
            Identity id = MarshalByRefObject.GetIdentity(o, out fServer);
            Init(o, id, rt);
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        protected ObjRef(SerializationInfo info, StreamingContext context) 
        {
            String url = null; // an objref lite url
            bool bFoundFIsMarshalled = false;
        
            SerializationInfoEnumerator e = info.GetEnumerator();
            while (e.MoveNext())
            {
                if (e.Name.Equals("uri"))
                {
                    uri = (String) e.Value;
                }
                else if (e.Name.Equals("typeInfo"))
                {
                    typeInfo = (IRemotingTypeInfo) e.Value;
                }
                else if (e.Name.Equals("envoyInfo"))
                {
                    envoyInfo = (IEnvoyInfo) e.Value;
                }
                else if (e.Name.Equals("channelInfo"))
                {
                    channelInfo = (IChannelInfo) e.Value;
                }
                else if (e.Name.Equals("objrefFlags"))
                {
                    Object o = e.Value;
                    if(o.GetType() == typeof(String))
                    {
                        objrefFlags = ((IConvertible)o).ToInt32(null);
                    }
                    else
                    {
                        objrefFlags = (int)o;
                    }
                }
                else if (e.Name.Equals("fIsMarshalled"))
                {
                    int value;
                    Object o = e.Value;
                    if(o.GetType() == typeof(String))
                        value = ((IConvertible)o).ToInt32(null);
                    else
                        value = (int)o;
 
                    if (value == 0)
                        bFoundFIsMarshalled = true;                                        
                }            
                else if (e.Name.Equals("url"))
                {
                    url = (String)e.Value;
                }
                else if (e.Name.Equals("SrvIdentity"))
                {
                    SetServerIdentity((GCHandle)e.Value);
                }
                else if (e.Name.Equals("DomainId"))
                {
                    SetDomainID((int)e.Value);
                }
            }
 
            if (!bFoundFIsMarshalled)
            {
                // This ObjRef was not passed as a parameter, so we need to unmarshal it.
                objrefFlags |= FLG_MARSHALED_OBJECT; 
            }
            else
                objrefFlags &= ~FLG_MARSHALED_OBJECT;
 
            // If only url is present, then it is an ObjRefLite.
            if (url != null)
            {
                uri = url;
                objrefFlags |= FLG_LITE_OBJREF;
            }
            
        } // ObjRef .ctor
        
 
        [System.Security.SecurityCritical]  // auto-generated
        internal bool CanSmuggle()
        {
            // make sure this isn't a derived class or an ObjRefLite
            if ((this.GetType() != typeof(ObjRef)) || IsObjRefLite())
                return false;
            
            Type typeOfTypeInfo = null;
            if (typeInfo != null)
                typeOfTypeInfo = typeInfo.GetType();
 
            Type typeOfChannelInfo = null;
            if (channelInfo != null)
                typeOfChannelInfo = channelInfo.GetType();
            
            if (((typeOfTypeInfo == null) ||
                 (typeOfTypeInfo == typeof(TypeInfo)) ||
                 (typeOfTypeInfo == typeof(DynamicTypeInfo))) &&
                (envoyInfo == null) &&
                ((typeOfChannelInfo == null) ||
                 (typeOfChannelInfo == typeof(ChannelInfo))))
            {
                if (channelInfo != null)
                {
                    foreach (Object channelData in channelInfo.ChannelData)
                    {
                        // Only consider CrossAppDomainData smuggleable.
                        if (!(channelData is CrossAppDomainData))
                        {
                            return false;
                        }
                    }
                }
 
                return true;
            }
            else
            {
                return false;
            }
        } // CanSmuggle
 
        [System.Security.SecurityCritical]  // auto-generated
        internal ObjRef CreateSmuggleableCopy()
        {
            BCLDebug.Assert(CanSmuggle(), "Caller should have made sure that CanSmuggle() was true first.");
 
            return new ObjRef(this);
        } // CreateSmuggleableCopy
        
 
        [System.Security.SecurityCritical]  // auto-generated_required
        public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            if (info==null) {
                throw new ArgumentNullException("info");
            }
 
            info.SetType(orType);
 
            if(!IsObjRefLite())
            {
                info.AddValue("uri", uri, typeof(String));
                info.AddValue("objrefFlags", (int) objrefFlags);
                info.AddValue("typeInfo", typeInfo, typeof(IRemotingTypeInfo));
                info.AddValue("envoyInfo", envoyInfo, typeof(IEnvoyInfo));
                info.AddValue("channelInfo", GetChannelInfoHelper(), typeof(IChannelInfo));
            }
            else
            {
                info.AddValue("url", uri, typeof(String));
            }
        } // GetObjectDataHelper
 
 
        // This method retrieves the channel info object to be serialized.
        // It does special checking to see if a channel url needs to be bashed
        // (currently used for switching "http://..." url to "https://...".
        [System.Security.SecurityCritical]  // auto-generated
        private IChannelInfo GetChannelInfoHelper()
        {
            ChannelInfo oldChannelInfo = channelInfo as ChannelInfo;
            if (oldChannelInfo == null)
                return channelInfo;
 
            Object[] oldChannelData = oldChannelInfo.ChannelData;
            if (oldChannelData == null)
                return oldChannelInfo;
 
            // <
 
 
            String[] bashInfo = (String[])CallContext.GetData("__bashChannelUrl");
            if (bashInfo == null)
                return oldChannelInfo;
 
            String urlToBash = bashInfo[0];
            String replacementUrl = bashInfo[1];
 
            // Copy channel info and go Microsoft urls.
            ChannelInfo newChInfo = new ChannelInfo();
            newChInfo.ChannelData = new Object[oldChannelData.Length];
            for (int co = 0; co < oldChannelData.Length; co++)
            {
                newChInfo.ChannelData[co] = oldChannelData[co];
 
                // see if this is one of the ones that we need to Microsoft
                ChannelDataStore channelDataStore = newChInfo.ChannelData[co] as ChannelDataStore;
                if (channelDataStore != null)
                {
                    String[] urls = channelDataStore.ChannelUris;
                    if ((urls != null) && (urls.Length == 1) && urls[0].Equals(urlToBash))
                    {
                        // We want to Microsoft just the url, so we do a shallow copy
                        // and replace the url array with the replacementUrl.
                        ChannelDataStore newChannelDataStore = channelDataStore.InternalShallowCopy();
                        newChannelDataStore.ChannelUris = new String[1];
                        newChannelDataStore.ChannelUris[0] = replacementUrl;
 
                        newChInfo.ChannelData[co] = newChannelDataStore;
                    }
                }
            }                      
 
            return newChInfo;
        } // GetChannelInfoHelper
            
        
        
        // Note: The uri will be either objURI (for normal marshals) or
        // it will be the URL if a wellknown object's proxy is marshaled
        // Basically we will take whatever the URI getter on Identity gives us
 
        public virtual String URI 
        {
            get { return uri;}
            set { uri = value;}
        }
 
        public virtual IRemotingTypeInfo TypeInfo 
        {
            get { return typeInfo;}
            set { typeInfo = value;}
        }
 
        public virtual IEnvoyInfo EnvoyInfo
        {
            get { return envoyInfo;}
            set { envoyInfo = value;}
        }
 
        public virtual IChannelInfo ChannelInfo 
        {
            [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]          
            get { return channelInfo;}
            set { channelInfo = value;}
        }
 
 
        // This is called when doing fix-ups during deserialization
        [System.Security.SecurityCritical]  // auto-generated_required
        public virtual Object GetRealObject(StreamingContext context)
        {
            return GetRealObjectHelper();
        }
        // This is the common helper called by serialization / smuggling 
        [System.Security.SecurityCritical]  // auto-generated
        internal Object GetRealObjectHelper()
 
        {
            // Check if we are a result of serialiazing an MBR object
            // or if someone wanted to pass an ObjRef itself 
            if (!IsMarshaledObject())
            {
                BCLDebug.Trace("REMOTE", "ObjRef.GetRealObject: Returning *this*\n");                
                return this;
            }
            else
            {
                // Check if this is a lightweight objref
                if(IsObjRefLite())
                {
                    BCLDebug.Assert(null != uri, "null != uri");
                    
                    // transform the url, if this is a local object (we know it is local
                    //   if we find the current application id in the url)
                    int index = uri.IndexOf(RemotingConfiguration.ApplicationId);
 
                    // we need to be past 0, since we have to back up a space and pick up
                    //   a slash.
                    if (index > 0)
                        uri = uri.Substring(index - 1);                   
                }
            
                // In the general case, 'this' is the 
                // objref of an activated object
 
                // It may also be a well known object ref ... which came by
                // because someone did a Connect(URL) and then passed the proxy
                // over to a remote method call.
 
                // The below call handles both cases.
                bool fRefine = !(GetType() == typeof(ObjRef));
                Object ret = RemotingServices.Unmarshal(this, fRefine);
 
                // Check for COMObject & do some special custom marshaling
                ret = GetCustomMarshaledCOMObject(ret);
 
                return ret;
            }
 
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        private Object GetCustomMarshaledCOMObject(Object ret)
        {
            // Some special work we need to do for __COMObject 
            // (Note that we use typeInfo to detect this case instead of
            // calling GetType on 'ret' so as to not refine the proxy)
            DynamicTypeInfo dt = this.TypeInfo as DynamicTypeInfo;
            if (dt != null)
            {
                // This is a COMObject type ... we do the special work 
                // only if it is from the same process but another appDomain
                // We rely on the x-appDomain channel data in the objRef
                // to provide us with the answers.
                Object ret1 = null;
                IntPtr pUnk = IntPtr.Zero;
                if (IsFromThisProcess() && !IsFromThisAppDomain())
                {
                    try
                    {
                        bool fIsURTAggregated;
                        pUnk = ((__ComObject)ret).GetIUnknown(out fIsURTAggregated);
                        if (pUnk != IntPtr.Zero && !fIsURTAggregated)
                        {
                            // The RCW for an IUnk is per-domain. This call
                            // gets (or creates) the RCW for this pUnk for
                            // the current domain.
                            String srvTypeName = TypeInfo.TypeName;
                            String typeName = null;
                            String assemName = null;
 
                            System.Runtime.Remoting.TypeInfo.ParseTypeAndAssembly(srvTypeName, out typeName, out assemName);
                            BCLDebug.Assert((null != typeName) && (null != assemName), "non-null values expected");
 
                            Assembly asm = FormatterServices.LoadAssemblyFromStringNoThrow(assemName);
                            if (asm==null) {
                                BCLDebug.Trace("REMOTE", "ObjRef.GetCustomMarshaledCOMObject. AssemblyName is: ", assemName, " but we can't load it.");
                                throw new RemotingException(Environment.GetResourceString("Serialization_AssemblyNotFound", assemName));
                            }
 
                            Type serverType = asm.GetType(typeName, false, false);
                            if (serverType != null && !serverType.IsVisible) 
                                serverType = null;
                            BCLDebug.Assert(serverType!=null, "bad objRef!");
 
                            ret1 = InteropServices.Marshal.GetTypedObjectForIUnknown(pUnk, serverType);
                            if (ret1 != null)
                            {
                                ret = ret1;
                            }    
                        }                                
                    }
                    finally
                    {
                        if (pUnk != IntPtr.Zero)
                        {
                            InteropServices.Marshal.Release(pUnk);
                        }                            
                    }                        
                }
            }
            return ret;
        }
 
        public ObjRef()
        {
            objrefFlags = 0x0;
        }
 
        internal bool IsMarshaledObject()
        {
            return (objrefFlags & FLG_MARSHALED_OBJECT) == FLG_MARSHALED_OBJECT;
        }
 
        internal void SetMarshaledObject()
        {
            objrefFlags |= FLG_MARSHALED_OBJECT;
        }
 
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]  
        internal bool IsWellKnown()
        {
            return (objrefFlags & FLG_WELLKNOWN_OBJREF) == FLG_WELLKNOWN_OBJREF;
        }
 
        internal void SetWellKnown()
        {
            objrefFlags |= FLG_WELLKNOWN_OBJREF;
        }
 
        internal bool HasProxyAttribute()
        {
            return (objrefFlags & FLG_PROXY_ATTRIBUTE) == FLG_PROXY_ATTRIBUTE;
        }
 
        internal void SetHasProxyAttribute()
        {
            objrefFlags |= FLG_PROXY_ATTRIBUTE;
        }
 
        internal bool IsObjRefLite()
        {
            return (objrefFlags & FLG_LITE_OBJREF) == FLG_LITE_OBJREF;
        }
 
        internal void SetObjRefLite()
        {
            objrefFlags |= FLG_LITE_OBJREF;
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]  
        private CrossAppDomainData GetAppDomainChannelData()
        {            
            BCLDebug.Assert(
                ObjRef.IsWellFormed(this), 
                "ObjRef.IsWellFormed()");
                
            // Look at the ChannelData part to find CrossAppDomainData
            int i=0;
            CrossAppDomainData xadData = null;
            while (i<ChannelInfo.ChannelData.Length)
            {
                xadData = ChannelInfo.ChannelData[i] as CrossAppDomainData;
                if (null != xadData)
                {
                    return xadData;
                }
                i++;
            }
 
            // AdData could be null for user-created objRefs.
            return null;
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]  
        public bool IsFromThisProcess()
        {
            //Wellknown objects may or may not be in the same process
            //Hence return false;
            if (IsWellKnown())
                return false;
 
            CrossAppDomainData xadData = GetAppDomainChannelData();
            if (xadData != null)
            {
                return xadData.IsFromThisProcess();
            }
            return false;
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        public bool IsFromThisAppDomain()
        {
            CrossAppDomainData xadData = GetAppDomainChannelData();
            if (xadData != null)
            {
                return xadData.IsFromThisAppDomain();
            }
            return false;
        }
 
        // returns the internal context ID for the server context if
        // it is from the same process && the appDomain of the server
        // is still valid. If the objRef is from this process, the domain
        // id found in the objref is always returned.
 
        [System.Security.SecurityCritical]  // auto-generated
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]  
        internal Int32 GetServerDomainId()
        {
            if (!IsFromThisProcess())
                return 0;
            CrossAppDomainData xadData = GetAppDomainChannelData();
            BCLDebug.Assert(xadData != null, "bad objRef?");
            return xadData.DomainID;
 
        }
        
        [System.Security.SecurityCritical]  // auto-generated
        internal IntPtr GetServerContext(out int domainId)
        {
            IntPtr contextId = IntPtr.Zero;
            domainId = 0;
            if (IsFromThisProcess())
            {
                CrossAppDomainData xadData = GetAppDomainChannelData();
                BCLDebug.Assert(xadData != null, "bad objRef?");
                domainId = xadData.DomainID;
                if (AppDomain.IsDomainIdValid(xadData.DomainID))
                {
                    contextId = xadData.ContextID;
                }
            }
            return contextId;
        }
 
       //
       //
        [System.Security.SecurityCritical]  // auto-generated
        internal void Init(Object o, Identity idObj, RuntimeType requestedType)
        {        
            Message.DebugOut("RemotingServices::FillObjRef: IN");
            BCLDebug.Assert(idObj != null,"idObj != null");
 
            // Set the URI of the object to be marshaled            
            uri = idObj.URI;
 
            // Figure out the type 
            MarshalByRefObject obj = idObj.TPOrObject;
            BCLDebug.Assert(null != obj, "Identity not setup correctly");
 
            // Get the type of the object
            RuntimeType serverType = null;
            if(!RemotingServices.IsTransparentProxy(obj))
            {
                serverType = (RuntimeType)obj.GetType();
            }
            else
            {
                serverType = (RuntimeType)RemotingServices.GetRealProxy(obj).GetProxiedType();
            }
 
            RuntimeType typeOfObj = (null == requestedType ? serverType : requestedType);
 
            // Make sure that the server and requested types are compatible
            //  (except for objects that implement IMessageSink, since we 
            //   just hand off the message instead of invoking the proxy)
            if ((null != requestedType) &&
                !requestedType.IsAssignableFrom(serverType) &&
                (!typeof(IMessageSink).IsAssignableFrom(serverType)))
            {
                throw new RemotingException(
                    String.Format(
                        CultureInfo.CurrentCulture, Environment.GetResourceString(
                            "Remoting_InvalidRequestedType"), 
                        requestedType.ToString())); ;
            }
 
            // Create the type info
            if(serverType.IsCOMObject)
            {
                // __ComObjects need dynamic TypeInfo
                DynamicTypeInfo dt = new DynamicTypeInfo(typeOfObj);
                TypeInfo = (IRemotingTypeInfo) dt;
            }
            else
            {
                RemotingTypeCachedData cache = (RemotingTypeCachedData)
                    InternalRemotingServices.GetReflectionCachedData(typeOfObj);
            
                TypeInfo = (IRemotingTypeInfo)cache.TypeInfo;
            }
    
            if (!idObj.IsWellKnown())
            {
                // Create the envoy info
                EnvoyInfo = System.Runtime.Remoting.EnvoyInfo.CreateEnvoyInfo(idObj as ServerIdentity);
 
                // Create the channel info 
                IChannelInfo chan = (IChannelInfo)new ChannelInfo();
                // Make sure the channelInfo only has x-appdomain data since the objref is agile while other
                // channelData might not be and regardless this data is useless for an appdomain proxy
                if (o is AppDomain){
                    Object[] channelData = chan.ChannelData;
                    int channelDataLength = channelData.Length;
                    Object[] newChannelData = new Object[channelDataLength];
                    // Clone the data so that we dont Microsoft the current appdomain data which is stored
                    // as a static
                    Array.Copy(channelData, newChannelData, channelDataLength);
                    for (int i = 0; i < channelDataLength; i++)
                    {
                        if (!(newChannelData[i] is CrossAppDomainData))
                            newChannelData[i] = null;
                    }
                    chan.ChannelData = newChannelData;
                }
                ChannelInfo = chan;
 
                if (serverType.HasProxyAttribute)
                {
                    SetHasProxyAttribute();
                }
            }
            else
            {
                SetWellKnown();
            }
 
            // See if we should and can use a url obj ref?
            if (ShouldUseUrlObjRef())
            {
                if (IsWellKnown())
                {
                    // full uri already supplied.
                    SetObjRefLite();
                }
                else
                {
                    String httpUri = ChannelServices.FindFirstHttpUrlForObject(URI);
                    if (httpUri != null)
                    {
                        URI = httpUri;
                        SetObjRefLite();
                    }
                }
            }
        } // Init
 
 
        // determines if a particular type should use a url obj ref
        internal static bool ShouldUseUrlObjRef()
        {
            return RemotingConfigHandler.UrlObjRefMode;
        } // ShouldUseUrlObjRef
        
 
        // Check whether the objref is well formed
        [System.Security.SecurityCritical]  // auto-generated
        internal static bool IsWellFormed(ObjRef objectRef)
        {
            // We skip the wellformed check for wellKnown, 
            // objref-lite and custom objrefs
            bool wellFormed = true;
            if ((null == objectRef) ||
                (null == objectRef.URI) ||
                (!(objectRef.IsWellKnown()  || objectRef.IsObjRefLite() ||
                   objectRef.GetType() != orType)
                    && (null == objectRef.ChannelInfo)))
            {
                wellFormed = false;
            }
            
            return wellFormed;
        }
    } // ObjRef 
   
    
}