|
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
//
// File: RemotingServices.cs
//
// <OWNER>Microsoft</OWNER>
//
// Author(s): <EMAIL>Gopal Kakivaya (GopalK)</EMAIL>
//
// Purpose: Defines various remoting related services such as
// marshal, unmarshal, connect, wrap, unwrap etc.
//
//
namespace System.Runtime.Remoting {
using System;
using System.Text;
using System.Collections;
using System.Runtime.Serialization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using CultureInfo = System.Globalization.CultureInfo;
using System.Runtime.InteropServices;
using System.Threading;
using System.Runtime.Remoting.Activation;
using System.Runtime.Remoting.Contexts;
using System.Runtime.Remoting.Lifetime;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Metadata;
using System.Runtime.Remoting.Proxies;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Services;
using RemotingConfigInfo = System.Runtime.Remoting.RemotingConfigHandler.RemotingConfigInfo;
using System.Runtime.Serialization.Formatters.Binary;
using System.Security.Permissions;
using System.Runtime.ConstrainedExecution;
using System.Runtime.Versioning;
using System.Diagnostics.Contracts;
// Implements various remoting services
[System.Runtime.InteropServices.ComVisible(true)]
public static class RemotingServices
{
private const BindingFlags LookupAll = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;
private const String FieldGetterName = "FieldGetter";
private const String FieldSetterName = "FieldSetter";
private const String IsInstanceOfTypeName = "IsInstanceOfType";
private const String CanCastToXmlTypeName = "CanCastToXmlType";
private const String InvokeMemberName = "InvokeMember";
private static volatile MethodBase s_FieldGetterMB;
private static volatile MethodBase s_FieldSetterMB;
private static volatile MethodBase s_IsInstanceOfTypeMB;
private static volatile MethodBase s_CanCastToXmlTypeMB;
private static volatile MethodBase s_InvokeMemberMB;
private static volatile bool s_bRemoteActivationConfigured;
// have we registered the well known channels
private static volatile bool s_bRegisteredWellKnownChannels;
// are we in the middle of registering well known channels
private static bool s_bInProcessOfRegisteringWellKnownChannels;
private static readonly Object s_delayLoadChannelLock = new Object();
//
//Native Static Methods
//
[System.Security.SecuritySafeCritical] // auto-generated
[Pure]
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall),
ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
public static extern bool IsTransparentProxy(Object proxy);
// Check whether the given object's context is the same as
// the current context.
//
//
//
[System.Security.SecuritySafeCritical] // auto-generated
public static bool IsObjectOutOfContext(Object tp)
{
if (!IsTransparentProxy(tp))
{
return false;
}
RealProxy rp = GetRealProxy(tp);
Identity id = rp.IdentityObject;
ServerIdentity serverID = id as ServerIdentity;
if ((null == serverID) || !(rp is RemotingProxy))
{
return true;
}
return(Thread.CurrentContext != serverID.ServerContext);
}
// Check whether the given object's app domain is the same as
// the current app domain
//
//
//
public static bool IsObjectOutOfAppDomain(Object tp)
{
return IsClientProxy(tp);
} // IsObjectOutOfAppDomain
internal static bool IsClientProxy(Object obj)
{
MarshalByRefObject mbr = obj as MarshalByRefObject;
if (mbr == null)
return false;
bool bIsClientProxy = false;
bool fServer;
Identity id = MarshalByRefObject.GetIdentity(mbr, out fServer);
// If the identity is null, this is defintely a locally hosted object;
// otherwise...(see if statement below).
if (id != null)
{
if (!(id is ServerIdentity))
bIsClientProxy = true;
}
return bIsClientProxy;
} // IsClientProxy
// Check whether the given object's process is the same as
// the current process
//
//
//
[System.Security.SecurityCritical] // auto-generated
internal static bool IsObjectOutOfProcess(Object tp)
{
if (!IsTransparentProxy(tp))
return false;
RealProxy rp = GetRealProxy(tp);
Identity id = rp.IdentityObject;
if (id is ServerIdentity)
return false;
else
{
if (null != id)
{
ObjRef objRef = id.ObjectRef;
if (objRef != null && objRef.IsFromThisProcess())
{
return false;
}
else
{
return true;
}
}
// assume out of process
return true;
}
} // IsObjectOutOfProcess
// Get the real proxy backing the transparent proxy
//
//
//
[System.Security.SecurityCritical] // auto-generated_required
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
public static extern RealProxy GetRealProxy(Object proxy);
// Create a transparent proxy given an instance of a real proxy and type
//
//
//
[System.Security.SecurityCritical] // auto-generated
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern Object CreateTransparentProxy(
RealProxy rp,
RuntimeType typeToProxy,
IntPtr stub,
Object stubData);
// Note: for each of these calls that take a RuntimeXXX reflection
// structure, there is a wrapper that takes XXX and throws if it is
// not a RuntimeXXX. This is to avoid clutter in code where these
// methods are called. <BUGNUM>(48721)</BUGNUM> <
[System.Security.SecurityCritical] // auto-generated
internal static Object CreateTransparentProxy(
RealProxy rp,
Type typeToProxy,
IntPtr stub,
Object stubData)
{
RuntimeType rTypeToProxy = typeToProxy as RuntimeType;
if (rTypeToProxy == null)
throw new ArgumentException(
String.Format(
CultureInfo.CurrentCulture, Environment.GetResourceString(
"Argument_WrongType"),
"typeToProxy"
)
);
return CreateTransparentProxy(
rp,
rTypeToProxy,
stub,
stubData);
}
// Allocate an uninitialized object of the given type.
//
//
//
[System.Security.SecurityCritical] // auto-generated
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern MarshalByRefObject AllocateUninitializedObject(
RuntimeType objectType);
[System.Security.SecurityCritical] // auto-generated
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern void CallDefaultCtor(Object o);
[System.Security.SecurityCritical] // auto-generated
internal static MarshalByRefObject AllocateUninitializedObject(
Type objectType)
{
RuntimeType rObjectType = objectType as RuntimeType;
if (rObjectType == null)
throw new ArgumentException(
String.Format(
CultureInfo.CurrentCulture, Environment.GetResourceString(
"Argument_WrongType"),
"objectType"
)
);
return AllocateUninitializedObject(
rObjectType);
}
// Allocate an Initialized object of the given type.
// runs the default constructor
//
//
[System.Security.SecurityCritical] // auto-generated
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern MarshalByRefObject AllocateInitializedObject(
RuntimeType objectType);
[System.Security.SecurityCritical] // auto-generated
internal static MarshalByRefObject AllocateInitializedObject(
Type objectType)
{
RuntimeType rObjectType = objectType as RuntimeType;
if (rObjectType == null)
throw new ArgumentException(
String.Format(
CultureInfo.CurrentCulture, Environment.GetResourceString(
"Argument_WrongType"),
"objectType"
)
);
return AllocateInitializedObject(
rObjectType);
}
[System.Security.SecurityCritical] // auto-generated
internal static bool RegisterWellKnownChannels()
{
// Any code coming through this method MUST not exit
// until the well known channels have been registered
// (unless we are reentering in the call to
// RefreshChannelData() while registering a well known
// channel).
if (!s_bRegisteredWellKnownChannels)
{
bool fLocked = false;
Object configLock = Thread.GetDomain().RemotingData.ConfigLock;
RuntimeHelpers.PrepareConstrainedRegions();
try
{
Monitor.Enter(configLock, ref fLocked);
if (!s_bRegisteredWellKnownChannels &&
!s_bInProcessOfRegisteringWellKnownChannels)
{
// we set this flag true before registering channels to prevent reentrancy
// when we go to refresh the channel data at the end of the call to
// ChannelServices.RegisterChannel().
s_bInProcessOfRegisteringWellKnownChannels = true;
CrossAppDomainChannel.RegisterChannel();
s_bRegisteredWellKnownChannels = true;
}
}
finally
{
if (fLocked)
{
Monitor.Exit(configLock);
}
}
}
return true;
} // RegisterWellKnownChannels
[System.Security.SecurityCritical] // auto-generated
internal static void InternalSetRemoteActivationConfigured()
{
if (!s_bRemoteActivationConfigured)
{
nSetRemoteActivationConfigured();
s_bRemoteActivationConfigured = true;
}
} // InternalSetRemoteActivationConfigured
[System.Security.SecurityCritical] // auto-generated
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern void nSetRemoteActivationConfigured();
[System.Security.SecurityCritical] // auto-generated_required
public static String GetSessionIdForMethodMessage(IMethodMessage msg)
{
return msg.Uri;
} // GetSessionIdForMessage
[System.Security.SecuritySafeCritical] // auto-generated
public static Object GetLifetimeService(MarshalByRefObject obj)
{
if(null != obj)
{
return obj.GetLifetimeService();
}
else
{
return null;
}
}
[System.Security.SecurityCritical] // auto-generated_required
public static String GetObjectUri(MarshalByRefObject obj)
{
// Retrieve the uri for the object. If it doesn't have an identity
// we'll just return null (this encompasses the case of an actual
// object not having been marshalled yet.
bool fServer;
Identity id = MarshalByRefObject.GetIdentity(obj, out fServer);
if(null != id)
return id.URI;
else
return null;
} // GetObjectUri
[System.Security.SecuritySafeCritical] // auto-generated
[SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.RemotingConfiguration)]
public static void SetObjectUriForMarshal( MarshalByRefObject obj, String uri)
{
// if obj is ever Marshal'd it should use this uri. If a uri has
// already been assigned to the object, it should throw.
Message.DebugOut("Entered SetObjectUriForMarshal \n");
Identity idObj = null;
Identity srvIdObj = null;
bool fServer;
idObj = MarshalByRefObject.GetIdentity(obj, out fServer);
srvIdObj = idObj as ServerIdentity;
// Ensure that if we have a transparent proxy then we are not given a remoting
// proxy. This routine should only be called for objects that
// live in this AppDomains.
if ((idObj != null) &&
(srvIdObj == null)) // <-- means idObj is not a ServerIdentity
{
throw new RemotingException(
Environment.GetResourceString(
"Remoting_SetObjectUriForMarshal__ObjectNeedsToBeLocal"));
}
if ((idObj != null) && (idObj.URI != null))
{
throw new RemotingException(
Environment.GetResourceString(
"Remoting_SetObjectUriForMarshal__UriExists"));
}
if (idObj == null)
{
// obj is not ContextBound
Contract.Assert(!(obj is ContextBoundObject), "ContextBoundObject's shouldn't get here.");
// Create a new server identity and add it to the
// table. IdentityHolder will take care of ----s
Context serverCtx = null;
serverCtx = Thread.GetDomain().GetDefaultContext();
Contract.Assert(null != serverCtx, "null != serverCtx");
ServerIdentity serverID = new ServerIdentity(obj, serverCtx, uri);
// set the identity
idObj = obj.__RaceSetServerIdentity(serverID);
Contract.Assert(idObj == MarshalByRefObject.GetIdentity(obj), "Bad ID state!" );
// If our serverID isn't used then someone else marshalled the object
// before we could set the uri.
if (idObj != serverID)
{
throw new RemotingException(
Environment.GetResourceString(
"Remoting_SetObjectUriForMarshal__UriExists"));
}
}
else
{
// This is the ContextBoundObject case
Contract.Assert(obj is ContextBoundObject, "Object should have been a ContextBoundObject.");
idObj.SetOrCreateURI(uri, true);
}
Message.DebugOut("Created ServerIdentity \n");
} // SetObjectUriForMarshal
[System.Security.SecuritySafeCritical] // auto-generated
[SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.RemotingConfiguration)]
public static ObjRef Marshal(MarshalByRefObject Obj)
{
return MarshalInternal(Obj, null, null);
}
[System.Security.SecuritySafeCritical] // auto-generated
[SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.RemotingConfiguration)]
public static ObjRef Marshal(MarshalByRefObject Obj, String URI)
{
return MarshalInternal(Obj, URI, null);
}
[System.Security.SecuritySafeCritical] // auto-generated
[SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.RemotingConfiguration)]
public static ObjRef Marshal(MarshalByRefObject Obj, String ObjURI, Type RequestedType)
{
return MarshalInternal(Obj, ObjURI, RequestedType);
}
// Internal flavor without security!
[System.Security.SecurityCritical] // auto-generated
internal static ObjRef MarshalInternal(MarshalByRefObject Obj, String ObjURI, Type RequestedType)
{
return MarshalInternal(Obj, ObjURI, RequestedType, true);
}
// Internal flavor without security!
[System.Security.SecurityCritical] // auto-generated
internal static ObjRef MarshalInternal(MarshalByRefObject Obj, String ObjURI, Type RequestedType, bool updateChannelData)
{
return MarshalInternal(Obj, ObjURI, RequestedType, updateChannelData, isInitializing: false);
}
// Internal flavor without security!
[System.Security.SecurityCritical] // auto-generated
internal static ObjRef MarshalInternal(MarshalByRefObject Obj, String ObjURI, Type RequestedType, bool updateChannelData, bool isInitializing)
{
BCLDebug.Trace("REMOTE", "Entered Marshal for URI" + ObjURI + "\n");
if (null == Obj)
return null;
ObjRef objectRef = null;
Identity idObj = null;
idObj = GetOrCreateIdentity(Obj, ObjURI, isInitializing);
if (RequestedType != null)
{
ServerIdentity srvIdObj = idObj as ServerIdentity;
if (srvIdObj != null)
{
// If more than one thread, marshals with different types the
// results would be non-deterministic, so we just let the last
// call win (also allows type to be marshalled a second time
// to change the exposed type).
srvIdObj.ServerType = RequestedType;
srvIdObj.MarshaledAsSpecificType = true;
}
}
// If there is no objref associated with the identity then go ahead
// and create one and stick it back into the identity object
#if _DEBUG
idObj.AssertValid();
#endif
Contract.Assert(null != idObj.ObjURI,"null != idObj.ObjURI");
Message.DebugOut("RemotingServices::Marshal: trying to create objref\n");
// We should definitely have an identity object at this point of time
Contract.Assert(null != idObj,"null != idObj");
// Extract the objref from the identity
objectRef = idObj.ObjectRef;
if (null == objectRef)
{
Message.DebugOut("RemotingServices::Marshal: really trying to create objref\n");
if (IsTransparentProxy(Obj))
{
RealProxy realProxy = GetRealProxy(Obj);
Contract.Assert(null != realProxy,"null != realProxy");
objectRef = realProxy.CreateObjRef(RequestedType);
}
else
{
// Create a new object ref which contains the default information
objectRef = Obj.CreateObjRef(RequestedType);
}
Message.DebugOut("RemotingServices::Marshal: created objref\n");
if (idObj == null || objectRef == null)
throw new ArgumentException(Environment.GetResourceString("Argument_InvalidMarshalByRefObject"), "Obj");
// The ObjectRef property setter will take care of ----s
objectRef = idObj.RaceSetObjRef(objectRef);
}
// Retime lease on every marshal on the server side
// and extend lease on every marshal on the client side <EMAIL>- GopalK</EMAIL>
ServerIdentity srvId = idObj as ServerIdentity;
if (srvId != null)
{
// Ensure that the lease is started soon as the object is
// marshaled.
MarshalByRefObject obj = null;
// This call forces creation of the lifetime lease sink.
srvId.GetServerObjectChain(out obj);
// Server side ... object being marshaled => give it another
// full lease
Lease lease = idObj.Lease;
if (lease != null)
{
// We always make Identity reference our own Lease though
// the actual object implements its own ILease object.
// This seems completely broken. Further, ILease interface
// should have the activate method. <EMAIL>- GopalK</EMAIL>
// This lock ensures coordination with the lifetime service
// which might have decided to Disconnect the object about
// the same time as it is being marshaled
lock (lease)
{
if (lease.CurrentState == LeaseState.Expired)
{
// Lease.Renew is a no-op if LeaseState==Expired
// So we do a full ActivateLease
lease.ActivateLease();
}
else
{
// Lease is still around. Just increase the time
lease.RenewInternal(idObj.Lease.InitialLeaseTime);
}
}
}
// Every marshal should also ensure that the channel data
// being carried in the objRef reflects the latest data from
// regisetered channels
// <
if (updateChannelData && objectRef.ChannelInfo != null)
{
// Create the channel info
Object[] channelData = ChannelServices.CurrentChannelData;
// 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 (!(Obj is AppDomain))
objectRef.ChannelInfo.ChannelData = channelData;
else
{
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;
}
objectRef.ChannelInfo.ChannelData = newChannelData;
}
}
}
else
{
#if false
/*
*/
ILease lease = idObj.Lease;
if (lease == null)
{
lease = (ILease)Obj.GetLifetimeService();
}
if (lease != null)
{
lease.Renew(lease.RenewOnCallTime);
}
#endif
}
// Notify TrackingServices that an object has been marshaled
// NOTE: This call also keeps the object alive otherwise GC
// can report it as dead anytime inside this call when it thinks
// that the object will no longer be referenced, either inside
// this call or outside.
/* <
*/
TrackingServices.MarshaledObject(Obj, objectRef);
return objectRef;
}
// Gets or generates the identity if one is not present and then returns
// it to the caller.
[System.Security.SecurityCritical] // auto-generated
private static Identity GetOrCreateIdentity(
MarshalByRefObject Obj,
String ObjURI,
bool isInitializing)
{
int idOpsFlags = IdOps.StrongIdentity;
// DevDiv 720951 and 911924:
// This flag is propagated into the new ServerIdentity to indicate
// it is not yet ready for use. CreateWellKnownObject is the only
// code path that sets it to 'true'.
if (isInitializing)
{
idOpsFlags |= IdOps.IsInitializing;
}
Identity idObj = null;
if (IsTransparentProxy(Obj))
{
Message.DebugOut("Marshaling proxy \n");
RealProxy realProxy = GetRealProxy(Obj);
Contract.Assert(null != realProxy,"null != realProxy");
idObj = realProxy.IdentityObject;
if(null == idObj)
{
// passing the strongIdentity flag will ensure that a weak
// reference to the identity will get converted to a strong
// one so as to keep the object alive (and in control of
// lifeTimeServices)
idObj = IdentityHolder.FindOrCreateServerIdentity(
Obj,
ObjURI,
idOpsFlags);
idObj.RaceSetTransparentProxy(Obj);
}
// At this point of time we should have an identity
Contract.Assert(null != idObj, "null != idObj");
ServerIdentity srvID = idObj as ServerIdentity;
if (srvID != null)
{
// We are marshaling a proxy with a serverIdentity
// associated with it but with no URI generated yet.
// For a genuine proxy case we will always have a URI
// AND it will be a client ID!
// So if we are here this must be a SrvID
// for a ContextBoundObject
Contract.Assert(srvID != null && Obj is ContextBoundObject,
"This case should only be hit for ContextBoundObjects & ServerIdentity!");
Message.DebugOut("Marshal::Looking up server side identity \n");
#if _DEBUG
srvID.AssertValid();
#endif
// passing the strongIdentity flag will ensure that a weak
// reference to the identity will get converted to a strong
// one so as to keep the object alive (and in control of
// lifeTimeServices)
idObj = IdentityHolder.FindOrCreateServerIdentity(
srvID.TPOrObject,
ObjURI,
idOpsFlags);
// if an objURI was specified we need to make sure that
// the same one was used.
if ((null != ObjURI) &&
(ObjURI != Identity.RemoveAppNameOrAppGuidIfNecessary(
idObj.ObjURI)))
{
throw new RemotingException(
Environment.GetResourceString(
"Remoting_URIExists"));
}
// We create a unique ID for an object and never
// change it!
Contract.Assert(srvID == idObj, "Bad ID Table state!");
}
else
{
// We are marshaling a proxy with a (client)Identity associated with it
// It must already have a URI.
Message.DebugOut("Marshal::Client side identity \n");
Contract.Assert(idObj.ObjURI != null, "Client side id without URI!");
//
// One cannot associate a URI with a proxy generated by us
// because either a URI was generated at the server side for the object
// it represents or it is a well known object in which case the URI is known.
//
// For custom proxies this restriction is relaxed because we treat the
// transparent proxy as the server object for such cases.
//
if ((null != ObjURI) && (ObjURI != idObj.ObjURI))
{
throw new RemotingException(
Environment.GetResourceString(
"Remoting_URIToProxy"));
}
}
Contract.Assert(null != idObj.ObjURI,"null != idObj.ObjURI");
}
else
{
// Find or Add the object identity to the identity table
Message.DebugOut("Marshaling object \n");
// passing the strongIdentity flag will ensure that a weak
// reference to the identity will get converted to a strong
// one so as to keep the object alive (and in control of
// lifeTimeServices)
// The object may have an ID if it was marshaled but its lease
// timed out.
#if _DEBUG
ServerIdentity idTmp =
(ServerIdentity) MarshalByRefObject.GetIdentity(Obj);
#endif
idObj = IdentityHolder.FindOrCreateServerIdentity(
Obj,
ObjURI,
idOpsFlags);
// If the object had an ID to begin with that is the one
// we must have set in the table.
#if _DEBUG
Contract.Assert(idTmp==null || idTmp == idObj, "Bad ID Table state!");
#endif
}
return idObj;
}
[System.Security.SecurityCritical] // auto-generated_required
public static void GetObjectData(Object obj, SerializationInfo info, StreamingContext context)
{
if (obj == null)
{
throw new ArgumentNullException("obj");
}
if (info==null) {
throw new ArgumentNullException("info");
}
Contract.EndContractBlock();
ObjRef or = RemotingServices.MarshalInternal(
(MarshalByRefObject)obj,
null,
null);
or.GetObjectData(info, context);
} // GetObjectData
[System.Security.SecurityCritical] // auto-generated_required
public static Object Unmarshal(ObjRef objectRef)
{
return InternalUnmarshal(objectRef, null, false);
}
[System.Security.SecurityCritical] // auto-generated_required
public static Object Unmarshal(ObjRef objectRef, bool fRefine)
{
return InternalUnmarshal(objectRef, null, fRefine);
}
[System.Security.SecurityCritical] // auto-generated_required
[System.Runtime.InteropServices.ComVisible(true)]
public static Object Connect(Type classToProxy, String url)
{
return Unmarshal(classToProxy, url, null);
}
[System.Security.SecurityCritical] // auto-generated_required
[System.Runtime.InteropServices.ComVisible(true)]
public static Object Connect(Type classToProxy, String url, Object data)
{
return Unmarshal(classToProxy, url, data);
}
[System.Security.SecurityCritical] // auto-generated_required
public static bool Disconnect(MarshalByRefObject obj)
{
return Disconnect(obj, true);
}
[System.Security.SecurityCritical] // auto-generated
internal static bool Disconnect(MarshalByRefObject obj, bool bResetURI)
{
if (obj == null)
{
throw new ArgumentNullException("obj");
}
Contract.EndContractBlock();
BCLDebug.Trace("REMOTE", "RemotingServices.Disconnect ", obj, " for context ", Thread.CurrentContext);
// We can extract the identity either from the remoting proxy or
// the server object depending on whether we are in the
// context/appdomain that the object was created in or outside
// the context/appdomain.
bool fServer;
Identity idrem = MarshalByRefObject.GetIdentity(obj, out fServer);
// remove the identity entry for this object (if it exists)
bool fDisconnect = false;
if(idrem != null)
{
// Disconnect is supported only on the server side currently
if(idrem is ServerIdentity)
{
// Disconnect is a no op if the object was never marshaled
if(idrem.IsInIDTable())
{
// When a user calls Disconnect we reset the URI but
// when lifetime service calls Disconnect we don't
IdentityHolder.RemoveIdentity(idrem.URI, bResetURI);
fDisconnect = true;
}
}
else
{
// <
throw new RemotingException(
Environment.GetResourceString("Remoting_CantDisconnectClientProxy"));
}
// Notify TrackingServices that an object has been disconnected
TrackingServices.DisconnectedObject(obj);
}
Message.DebugOut("Disconnect:: returning " + fDisconnect +
" for context " + Thread.CurrentContext +
"\n");
return fDisconnect;
}
[System.Security.SecurityCritical] // auto-generated_required
public static IMessageSink GetEnvoyChainForProxy(MarshalByRefObject obj)
{
IMessageSink envoyChain = null;
// Extract the envoy chain only if the object is a proxy
if(IsObjectOutOfContext(obj))
{
RealProxy rp = GetRealProxy(obj);
Identity id = rp.IdentityObject;
if(null != id)
{
envoyChain = id.EnvoyChain;
}
}
return envoyChain;
}
[System.Security.SecurityCritical] // auto-generated_required
public static ObjRef GetObjRefForProxy(MarshalByRefObject obj)
{
ObjRef objRef = null;
if (!IsTransparentProxy(obj))
{
throw new RemotingException(
Environment.GetResourceString(
"Remoting_Proxy_BadType"));
}
RealProxy rp = GetRealProxy(obj);
Identity id = rp.IdentityObject;
if (null != id)
{
objRef = id.ObjectRef;
}
return objRef;
}
[System.Security.SecurityCritical] // auto-generated
internal static Object Unmarshal(Type classToProxy, String url)
{
return Unmarshal(classToProxy, url, null);
}
[System.Security.SecurityCritical] // auto-generated
internal static Object Unmarshal(Type classToProxy, String url, Object data)
{
if (null == classToProxy)
{
throw new ArgumentNullException("classToProxy");
}
if (null == url)
{
throw new ArgumentNullException("url");
}
Contract.EndContractBlock();
if (!classToProxy.IsMarshalByRef && !classToProxy.IsInterface)
{
throw new RemotingException(
Environment.GetResourceString(
"Remoting_NotRemotableByReference"));
}
BCLDebug.Trace("REMOTE", "RemotingService::Unmarshal for URL" + url + "and for Type" + classToProxy);
// See if we have already unmarshaled this (wellKnown) url
Identity idObj = IdentityHolder.ResolveIdentity(url);
Object proxy = null;
if (idObj == null
|| idObj.ChannelSink == null || idObj.EnvoyChain == null)
{
String objectURI = null;
IMessageSink chnlSink = null;
IMessageSink envoySink = null;
// Create the envoy and channel sinks
objectURI = CreateEnvoyAndChannelSinks(url, data, out chnlSink, out envoySink);
// ensure that we were able to create a channel sink
if (chnlSink == null)
{
throw new RemotingException(
String.Format(
CultureInfo.CurrentCulture, Environment.GetResourceString(
"Remoting_Connect_CantCreateChannelSink"),
url));
}
// Do not allow Connect() with null objUri (eg. http://localhost/)
if (objectURI == null)
{
throw new ArgumentException(
Environment.GetResourceString(
"Argument_InvalidUrl"));
}
#if false
// GopalK: Return the server object if the object uri is in the IDTable and is of type
// ServerIdentity and the object URI starts with application name
ServerIdentity srvId =
IdentityHolder.ResolveIdentity(objectURI) as ServerIdentity;
if (srvId != null
&& objectURI.StartsWith(RemotingConfigHandler.ApplicationName, StringComparison.Ordinal))
{
return srvId.ServerObject;
}
#endif
// Try to find an existing identity or create a new one
// Note: we create an identity entry hashed with the full url. This
// means that the same well known object could have multiple
// identities on the client side if it is connected through urls
// that have different string representations.
// <
idObj = IdentityHolder.FindOrCreateIdentity(objectURI, url, null);
// Set the envoy and channel sinks in a thread safe manner
SetEnvoyAndChannelSinks(idObj, chnlSink, envoySink);
}
// Get the proxy represented by the identity object
proxy = GetOrCreateProxy(classToProxy, idObj);
Message.DebugOut("RemotingService::Unmarshal returning ");
return proxy;
}
[System.Security.SecurityCritical] // auto-generated
internal static Object Wrap(ContextBoundObject obj)
{
return Wrap(obj, null, true);
}
[System.Security.SecurityCritical] // auto-generated
internal static Object Wrap(ContextBoundObject obj, Object proxy, bool fCreateSinks)
{
Message.DebugOut("Entering Wrap for context " + Thread.CurrentContext + "\n");
if ((null != obj) && (!IsTransparentProxy(obj)))
{
Contract.Assert(obj.GetType().IsContextful,"objType.IsContextful");
Message.DebugOut("Wrapping object \n");
Identity idObj = null;
if (proxy != null)
{
// We will come here for strictly x-context activations
// since a proxy has already been created and supplied
// through the construction message frame (GetThisPtr()).
RealProxy rp = GetRealProxy(proxy);
if (rp.UnwrappedServerObject == null)
{
rp.AttachServerHelper(obj);
}
idObj = MarshalByRefObject.GetIdentity(obj);
}
else
{
// Proxy is null when Wrap() is called the second
// time during activation
// It also will be null when a ContextBoundObject
// is being activated from a remote client.
idObj = IdentityHolder.FindOrCreateServerIdentity(
obj,
null,
IdOps.None);
}
//********************WARNING*******************************
// Always create the proxy before calling out to user code
// so that any recursive calls by JIT to wrap will return this
// proxy.
//**********************************************************
// Get the proxy represented by the identity object
proxy = GetOrCreateProxy(idObj, proxy, true);
// EXTENSIBILITY:
GetRealProxy(proxy).Wrap();
if (fCreateSinks)
{
IMessageSink chnlSink = null;
IMessageSink envoySink = null;
// Create the envoy sinks and channel sink
CreateEnvoyAndChannelSinks((MarshalByRefObject)proxy, null, out chnlSink, out envoySink);
// Set the envoy and channel sinks in a thread safe manner
SetEnvoyAndChannelSinks(idObj, chnlSink, envoySink);
}
// This will handle the case where we call Wrap() with
// a null proxy for real remote activation of ContextFul types.
RealProxy rp2 = GetRealProxy(proxy);
if (rp2.UnwrappedServerObject == null)
{
rp2.AttachServerHelper(obj);
}
Message.DebugOut("Leaving Wrap with proxy \n");
return proxy;
}
else
{
Message.DebugOut("Leaving Wrap with passed in object\n");
// Default return value is the object itself
return obj;
}
} // Wrap
// This relies on the fact that no object uri is allowed to contain a slash
// (in some cases, we might want to do something intelligent by parsing
// the uri with the right channel, but that isn't possible in all cases).
internal static String GetObjectUriFromFullUri(String fullUri)
{
if (fullUri == null)
return null;
int index = fullUri.LastIndexOf('/');
if (index == -1)
return fullUri;
return fullUri.Substring(index + 1);
} // GetObjectUriFromFullUri
//
//
[System.Security.SecurityCritical] // auto-generated
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern Object Unwrap(ContextBoundObject obj);
[System.Security.SecurityCritical] // auto-generated
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern Object AlwaysUnwrap(ContextBoundObject obj);
// This method does the actual work of Ma
//
[System.Security.SecurityCritical] // auto-generated
internal static Object InternalUnmarshal(
ObjRef objectRef,
Object proxy,
bool fRefine)
{
Object obj = null;
Identity idObj = null;
Context currContext = Thread.CurrentContext;
Message.DebugOut("RemotingServices::InternalUnmarshal: <Begin> Current context id: " + (currContext.ContextID).ToString("x") + "\n");
// This routine can be supplied a custom objref or an objref
// generated by us. We do some sanity checking on the objref
// to make sure that it is valid
if (!ObjRef.IsWellFormed(objectRef))
{
throw new ArgumentException(
String.Format(
CultureInfo.CurrentCulture, Environment.GetResourceString(
"Argument_BadObjRef"),
"Unmarshal"));
}
// If it is a well known objectRef we need to just connect to
// the URL inside the objectRef.
if (objectRef.IsWellKnown())
{
obj = Unmarshal(
typeof(System.MarshalByRefObject),
objectRef.URI);
// ensure that we cache the objectRef in the ID
// this contains type-info and we need it for
// validating casts on the wellknown proxy
// Note: this code path will be relatively rare ... the case
// when a well known proxy is passed to a remote call
// Otherwise it will be wise to another internal flavor of
// Unmarshal call that returns the identity as an out param.
idObj = IdentityHolder.ResolveIdentity(objectRef.URI);
if (idObj.ObjectRef == null)
{
idObj.RaceSetObjRef(objectRef);
}
return obj;
}
Message.DebugOut("RemotingService::InternalUnmarshal IN URI" + objectRef.URI);
// Get the identity for the URI
idObj = IdentityHolder.FindOrCreateIdentity(objectRef.URI, null, objectRef);
currContext = Thread.CurrentContext;
Message.DebugOut("RemotingServices::Unmarshal: <after FindOrCreateIdentity> Current context id: " +
(currContext.ContextID).ToString("x") + "\n");
// If we successfully completed the above method then we should
// have an identity object
BCLDebug.Assert(null != idObj,"null != idObj");
Message.DebugOut("RemotingService::InternalUnmarshal IN URI" + objectRef.URI);
Message.DebugOut("RemotingServices::InternalUnmarshal: <Begin> Current context id: " +
(currContext.ContextID).ToString("x") + "\n");
// Check whether we are on the server side or client-side
ServerIdentity serverID = idObj as ServerIdentity;
if ( serverID != null )
{
Message.DebugOut("RemotingServices::InternalUnmarshal: Unmarshalling ServerIdentity\n");
// SERVER SIDE
// We are in the app domain of the server object.
// If we are in the same context as the server then
// just return the server object else return the proxy
currContext = Thread.CurrentContext;
Message.DebugOut("RemotingServices::InternalUnmarshal: Current context id: " +
(currContext.ContextID).ToString("x") + "\n");
Message.DebugOut("RemotingServices::InternalUnmarshal: ServerContext id: " +
(serverID.ServerContext.ContextID).ToString("x") + "\n");
if (!serverID.IsContextBound)
{
BCLDebug.Assert(serverID.ServerType.IsMarshalByRef,
"Object must be at least MarshalByRef in order to be marshaled");
if (proxy != null)
{
throw new ArgumentException(
String.Format(
CultureInfo.CurrentCulture, Environment.GetResourceString(
"Remoting_BadInternalState_ProxySameAppDomain")));
}
obj = serverID.TPOrObject;
}
else
{
Message.DebugOut("RemotingServices::InternalUnmarshal: Contexts don't match, returning proxy\n");
IMessageSink chnlSink = null;
IMessageSink envoySink = null;
// Create the envoy sinks and channel sink
CreateEnvoyAndChannelSinks(
(MarshalByRefObject)serverID.TPOrObject,
null,
out chnlSink,
out envoySink);
// Set the envoy and channel sinks in a thread safe manner
SetEnvoyAndChannelSinks(idObj, chnlSink, envoySink);
// Get or create the proxy and return
obj = GetOrCreateProxy(idObj, proxy, true);
// This will be a TP
BCLDebug.Assert(IsTransparentProxy(obj), "Unexpected server");
}
}
else
{
// CLIENT SIDE
Message.DebugOut("RemotingServices::InternalUnmarshal: Unmarshalling Client-side Identity\n");
IMessageSink chnlSink = null;
IMessageSink envoySink = null;
// Create the envoy sinks and channel sink
if (!objectRef.IsObjRefLite())
CreateEnvoyAndChannelSinks(null, objectRef, out chnlSink, out envoySink);
else
CreateEnvoyAndChannelSinks(objectRef.URI, null, out chnlSink, out envoySink);
// Set the envoy and channel sinks in a thread safe manner
SetEnvoyAndChannelSinks(idObj, chnlSink, envoySink);
if (objectRef.HasProxyAttribute())
{
fRefine = true;
}
// Get or create the proxy and return
obj = GetOrCreateProxy(idObj, proxy, fRefine);
}
// Notify TrackingServices that we unmarshaled an object
TrackingServices.UnmarshaledObject(obj, objectRef);
// Return the proxy
Message.DebugOut("RemotingService::InternalUnmarshl OUT \n");
return obj;
}
//
//
[System.Security.SecurityCritical] // auto-generated
private static Object GetOrCreateProxy(
Identity idObj, Object proxy, bool fRefine)
{
Message.DebugOut("Entering GetOrCreateProxy for given proxy\n");
// If we are not supplied a proxy then we have to find an existing
// proxy or create one
if (null == proxy)
{
// Get the type of the server object
Type serverType;
ServerIdentity serverID = idObj as ServerIdentity;
if (null != serverID)
{
serverType = serverID.ServerType; // ServerObject.GetType();
}
else
{
BCLDebug.Assert(ObjRef.IsWellFormed(idObj.ObjectRef),
"ObjRef.IsWellFormed(idObj.ObjectRef)");
IRemotingTypeInfo serverTypeInfo = idObj.ObjectRef.TypeInfo;
// For system generated type info we create the proxy for
// object type. Later, when the proxy is cast to the appropriate
// type we will update its internal state to refer to the cast type
// This way we avoid loading the server type till cast time.
//
// For type info generated by others we have no choice but to
// load the type provided by the typeinfo. Sometimes, we
// use this second approach even if the typeinfo has been
// generated by us because this saves us an extra checkcast.
// A typical example of this usage will be when we are
// unmarshaling in parameters. We know that the unmarshal will
// be followed by a check cast to ensure that the parameter type
// matches the signature type, so we do both in one step.
serverType = null;
if (((serverTypeInfo is TypeInfo) && !fRefine) ||
(serverTypeInfo == null))
{
serverType = typeof(System.MarshalByRefObject);
}
else
{
String typeName = serverTypeInfo.TypeName;
if (typeName != null)
{
String typeNamespace = null;
String assemNamespace = null;
TypeInfo.ParseTypeAndAssembly(typeName, out typeNamespace, out assemNamespace);
Assembly assem = FormatterServices.LoadAssemblyFromStringNoThrow(assemNamespace);
if (assem != null)
{
serverType = assem.GetType(typeNamespace, false, false);
}
}
}
if (null == serverType)
{
throw new RemotingException(
String.Format(
CultureInfo.CurrentCulture, Environment.GetResourceString(
"Remoting_BadType"),
serverTypeInfo.TypeName));
}
}
Message.DebugOut("Creating Proxy for type " + serverType.FullName + "\n");
proxy = SetOrCreateProxy(idObj, serverType, null);
}
else
{
// We have been supplied with a proxy. Set that proxy in
// the identity object
// Assert that this the activation case only as this code path is
// not thread safe otherwise! (We call Wrap to associate an object
// with its proxy during activation).
BCLDebug.Assert(
((RemotingProxy)GetRealProxy(proxy)).ConstructorMessage!=null,
"Only expect to be here during activation!");
proxy = SetOrCreateProxy(idObj, null, proxy);
}
// At this point we should have a non-null transparent proxy
if (proxy == null)
throw new RemotingException(Environment.GetResourceString("Remoting_UnexpectedNullTP"));
BCLDebug.Assert(IsTransparentProxy(proxy),"IsTransparentProxy(proxy)");
Message.DebugOut("Leaving GetOrCreateProxy for given proxy\n");
// Return the underlying transparent proxy
return proxy;
}
//
//
// This version of GetOrCreateProxy is used for Connect(URI, type)
[System.Security.SecurityCritical] // auto-generated
private static Object GetOrCreateProxy(Type classToProxy, Identity idObj)
{
Message.DebugOut("Entering GetOrCreateProxy for given class\n");
Object proxy = idObj.TPOrObject;
if (null == proxy)
{
// Create the proxy
proxy = SetOrCreateProxy(idObj, classToProxy, null);
}
// proxy from idObj may be non-null if we are doing a Connect
// under new XXX() ... also if we are connecting to a remote URL
// which we previously connected.
// If we are in the same domain as the server object then we
// can check for type compatibility of the proxy with the given
// type. Otherwise, we will defer this check to method call time.
// If we do not do this now then we run the risk of returning
// a proxy which is different from the type given.
// <
ServerIdentity serverID = idObj as ServerIdentity;
if (null != serverID)
{
// Check for type compatibility
Type serverType = serverID.ServerType;
if (!classToProxy.IsAssignableFrom(serverType))
{
throw new InvalidCastException(
String.Format(
CultureInfo.CurrentCulture, Environment.GetResourceString(
"InvalidCast_FromTo"),
serverType.FullName,
classToProxy.FullName));
}
}
// At this point we should have a non-null transparent proxy
BCLDebug.Assert(null != proxy && IsTransparentProxy(proxy),"null != proxy && IsTransparentProxy(proxy)");
Message.DebugOut("Leaving GetOrCreateProxy for given class\n");
return proxy;
}
[System.Security.SecurityCritical] // auto-generated
private static MarshalByRefObject SetOrCreateProxy(
Identity idObj, Type classToProxy, Object proxy)
{
Message.DebugOut("Entering SetOrCreateProxy for type \n");
RealProxy realProxy = null;
// If a proxy has not been supplied create one
if (null == proxy)
{
// Create a remoting proxy
Message.DebugOut("SetOrCreateProxy::Creating Proxy for " +
classToProxy.FullName + "\n");
ServerIdentity srvID = idObj as ServerIdentity;
if (idObj.ObjectRef != null)
{
ProxyAttribute pa = ActivationServices.GetProxyAttribute(classToProxy);
realProxy = pa.CreateProxy(idObj.ObjectRef,
classToProxy,
null, //
null); //
}
if(null == realProxy)
{
// The custom proxy attribute does not want to create a proxy. We create a default
// proxy in this case.
ProxyAttribute defaultProxyAttribute = ActivationServices.DefaultProxyAttribute;
realProxy = defaultProxyAttribute.CreateProxy(idObj.ObjectRef,
classToProxy,
null,
(null == srvID ? null :
srvID.ServerContext));
}
}
else
{
BCLDebug.Assert(IsTransparentProxy(proxy),"IsTransparentProxy(proxy)");
// Extract the remoting proxy from the transparent proxy
Message.DebugOut("SetOrCreateProxy::Proxy already created \n");
realProxy = GetRealProxy(proxy);
}
BCLDebug.Assert(null != realProxy,"null != realProxy");
// Set the back reference to the identity in the proxy object
realProxy.IdentityObject = idObj;
// Set the reference to the proxy in the identity object
proxy = realProxy.GetTransparentProxy();
proxy = idObj.RaceSetTransparentProxy(proxy);
Message.DebugOut("Leaving SetOrCreateProxy\n");
// return the transparent proxy
return (MarshalByRefObject)proxy;
}
// Check
private static bool AreChannelDataElementsNull(Object[] channelData)
{
foreach(Object o in channelData)
{
if (o != null)
return false;
}
return true;
}
[System.Security.SecurityCritical] // auto-generated
internal static void CreateEnvoyAndChannelSinks(
MarshalByRefObject tpOrObject,
ObjRef objectRef,
out IMessageSink chnlSink,
out IMessageSink envoySink)
{
Message.DebugOut("Creating envoy and channel sinks \n");
BCLDebug.Assert(
((null != tpOrObject) || (null != objectRef)),
"((null != tpOrObject) || (null != objectRef)");
// Set the out parameters
chnlSink = null;
envoySink = null;
if (null == objectRef)
{
// If the objectRef is not present this is a cross context case
// and we should set the cross context channel sink
chnlSink = ChannelServices.GetCrossContextChannelSink();
envoySink = Thread.CurrentContext.CreateEnvoyChain(tpOrObject);
}
else
{
// Extract the channel from the channel data and name embedded
// inside the objectRef
Object[] channelData = objectRef.ChannelInfo.ChannelData;
if (channelData != null && !AreChannelDataElementsNull(channelData))
{
for (int i = 0; i < channelData.Length; i++)
{
// Get the first availabe sink
chnlSink = ChannelServices.CreateMessageSink(channelData[i]);
if (null != chnlSink)
{
break;
}
}
// if chnkSink is still null, try to find a channel that can service
// this uri.
if (null == chnlSink)
{
// NOTE: careful! we are calling user code here after holding
// the delayLoadChannelLock (channel ctor-s for arbitrary channels
// will run while the lock is held).
lock (s_delayLoadChannelLock)
{
// Check once to ensure that noone beat us in a ----
for (int i = 0; i < channelData.Length; i++)
{
// Get the first availabe sink
chnlSink = ChannelServices.CreateMessageSink(channelData[i]);
if (null != chnlSink)
{
break;
}
}
if (null == chnlSink)
{
// We don't have a sink
foreach (Object data in channelData)
{
String objectURI;
chnlSink =
RemotingConfigHandler.FindDelayLoadChannelForCreateMessageSink(
null, data, out objectURI);
if (null != chnlSink)
break;
}
}
}
}
}
// Extract the envoy sinks from the objectRef
if ((null != objectRef.EnvoyInfo) &&
(null != objectRef.EnvoyInfo.EnvoySinks))
{
envoySink = objectRef.EnvoyInfo.EnvoySinks;
}
else
{
envoySink = EnvoyTerminatorSink.MessageSink;
}
}
}
[System.Security.SecurityCritical] // auto-generated
internal static String CreateEnvoyAndChannelSinks(String url,
Object data,
out IMessageSink chnlSink,
out IMessageSink envoySink)
{
BCLDebug.Assert(null != url,"null != url");
String objectURI = null;
objectURI = CreateChannelSink(url, data, out chnlSink);
envoySink = EnvoyTerminatorSink.MessageSink;
return objectURI;
}
[System.Security.SecurityCritical] // auto-generated
private static String CreateChannelSink(String url, Object data, out IMessageSink chnlSink)
{
BCLDebug.Assert(null != url,"null != url");
String objectURI = null;
chnlSink = ChannelServices.CreateMessageSink(url, data, out objectURI);
// if chnkSink is still null, try to find a channel that can service this uri.
if (null == chnlSink)
{
lock (s_delayLoadChannelLock)
{
chnlSink = ChannelServices.CreateMessageSink(url, data, out objectURI);
if (null == chnlSink)
{
chnlSink =
RemotingConfigHandler.FindDelayLoadChannelForCreateMessageSink(
url, data, out objectURI);
}
}
}
return objectURI;
} // CreateChannelSinks
internal static void SetEnvoyAndChannelSinks(Identity idObj,
IMessageSink chnlSink,
IMessageSink envoySink)
{
Message.DebugOut("Setting up envoy and channel sinks \n");
BCLDebug.Assert(null != idObj,"null != idObj");
// Decide if we need to set the envoy sink chain
if (null == idObj.ChannelSink)
{
if (null != chnlSink)
{
idObj.RaceSetChannelSink(chnlSink);
}
}
// Decide if we need to set the envoy sink chain
if (null == idObj.EnvoyChain)
{
if (null != envoySink)
{
idObj.RaceSetEnvoyChain(envoySink);
}
else
{
throw new RemotingException(
String.Format(
CultureInfo.CurrentCulture, Environment.GetResourceString(
"Remoting_BadInternalState_FailEnvoySink")));
}
}
}
// Check whether the transparent proxy backing the real proxy
// is assignable from the given type.
[System.Security.SecurityCritical] // auto-generated
private static bool CheckCast(RealProxy rp, RuntimeType castType)
{
// NOTE: This is the point where JIT_CheckCastClass ultimately
// lands up in the managed world if the object being cast is
// a transparent proxy.
// If we are here, it means that walking the current EEClass
// up the chain inside the EE was unable to verify the cast.
Message.DebugOut("Entered CheckCast for type " + castType);
bool fCastOK = false;
BCLDebug.Assert(rp != null, "Shouldn't be called with null real proxy.");
// Always return true if cast is to System.Object
if (castType == typeof(Object))
return true;
// We do not allow casting to non-interface types that do not extend
// from System.MarshalByRefObject
if (!castType.IsInterface && !castType.IsMarshalByRef)
return false;
// Note: this is a bit of a hack to allow deserialization of WellKnown
// object refs (in the well known cases, we always return TRUE for
// interface casts but doing so messes us up in the case when
// the object manager is trying to resolve object references since
// it ends up thinking that the proxy we returned needs to be resolved
// further).
if (castType != typeof(IObjectReference))
{
IRemotingTypeInfo typeInfo = rp as IRemotingTypeInfo;
if(null != typeInfo)
{
fCastOK = typeInfo.CanCastTo(castType, rp.GetTransparentProxy());
}
else
{
// The proxy does not implement IRemotingTypeInfo, so we should
// try to do casting based on the ObjRef type info.
Identity id = rp.IdentityObject;
if (id != null)
{
ObjRef objRef = id.ObjectRef;
if (objRef != null)
{
typeInfo = objRef.TypeInfo;
if (typeInfo != null)
{
fCastOK = typeInfo.CanCastTo(castType, rp.GetTransparentProxy());
}
}
}
}
}
Message.DebugOut("CheckCast returning " + fCastOK);
return fCastOK;
}
[System.Security.SecurityCritical] // auto-generated
internal static bool ProxyCheckCast(RealProxy rp, RuntimeType castType)
{
return CheckCast(rp, castType);
} // ProxyCheckCast
/*
**CheckCast
**Action: When a proxy to an object is serialized, the MethodTable is only
** expanded on an on-demand basis. For purely managed operations, this
** happens in a transparent fashion. However, for delegates (and
** potentially other types) we need to force this expansion to happen.
**Returns: The newly expanded object. Returns the identity if no expansion is required.
**Arguments: objToExpand -- The object to be expanded.
** type -- the type to which to expand it.
**Exceptions: None.
*/
[System.Security.SecurityCritical] // auto-generated
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern Object CheckCast(Object objToExpand, RuntimeType type);
[System.Security.SecurityCritical] // auto-generated
internal static GCHandle CreateDelegateInvocation(WaitCallback waitDelegate, Object state)
{
Object[] delegateCallToken = new Object[2];
delegateCallToken[0] = waitDelegate;
delegateCallToken[1] = state;
return System.Runtime.InteropServices.GCHandle.Alloc(delegateCallToken);
}
[System.Security.SecurityCritical] // auto-generated
internal static void DisposeDelegateInvocation(GCHandle delegateCallToken)
{
delegateCallToken.Free();
}
[System.Security.SecurityCritical] // auto-generated
internal static Object CreateProxyForDomain(int appDomainId, IntPtr defCtxID)
{
AppDomain proxy = null;
ObjRef objRef = CreateDataForDomain(appDomainId, defCtxID);
// Unmarshal the objref in the old app domain
proxy = (AppDomain)Unmarshal(objRef);
return proxy;
} // CreateProxyForDomain
[System.Security.SecurityCritical] // auto-generated
internal static Object CreateDataForDomainCallback(Object[] args)
{
// Ensure that the well known channels are registered in this domain too
RegisterWellKnownChannels();
// Marshal the app domain object
ObjRef objref = MarshalInternal(
Thread.CurrentContext.AppDomain,
null,
null,
false);
ServerIdentity si = (ServerIdentity)MarshalByRefObject.GetIdentity(Thread.CurrentContext.AppDomain);
si.SetHandle();
objref.SetServerIdentity(si.GetHandle());
objref.SetDomainID(AppDomain.CurrentDomain.GetId());
return objref;
}
[System.Security.SecurityCritical] // auto-generated
internal static ObjRef CreateDataForDomain(int appDomainId, IntPtr defCtxID)
{
// This is a subroutine of CreateProxyForDomain
// so we can segregate the object references
// from different app domains into different frames. This is
// important for the app domain leak checking code.
Message.DebugOut("Creating proxy for domain " + appDomainId + "\n");
RegisterWellKnownChannels();
InternalCrossContextDelegate xctxDel = new InternalCrossContextDelegate(CreateDataForDomainCallback);
return (ObjRef) Thread.CurrentThread.InternalCrossContextCallback(null, defCtxID, appDomainId, xctxDel, null);
} // CreateDataForDomain
[System.Security.SecurityCritical] // auto-generated_required
public static MethodBase GetMethodBaseFromMethodMessage(IMethodMessage msg)
{
MethodBase mb = InternalGetMethodBaseFromMethodMessage(msg);
return mb;
}
[System.Security.SecurityCritical] // auto-generated
internal static MethodBase InternalGetMethodBaseFromMethodMessage(IMethodMessage msg)
{
if(null == msg)
{
return null;
}
Type t = RemotingServices.InternalGetTypeFromQualifiedTypeName(msg.TypeName);
if (t == null)
{
throw new RemotingException(
String.Format(
CultureInfo.CurrentCulture, Environment.GetResourceString(
"Remoting_BadType"),
msg.TypeName));
}
// Use the signature, type and method name to determine the
// methodbase via reflection.
Type[] signature = (Type[])msg.MethodSignature;
return GetMethodBase(msg, t, signature);
}
[System.Security.SecurityCritical] // auto-generated_required
public static bool IsMethodOverloaded(IMethodMessage msg)
{
RemotingMethodCachedData cache =
InternalRemotingServices.GetReflectionCachedData(msg.MethodBase);
return cache.IsOverloaded();
} // IsMethodOverloaded
[System.Security.SecurityCritical] // auto-generated
private static MethodBase GetMethodBase(IMethodMessage msg, Type t, Type[] signature)
{
MethodBase mb = null;
// Get the reflection object depending on whether it is a
// constructor call or a method call.
if((msg is IConstructionCallMessage) ||
(msg is IConstructionReturnMessage))
{
if((null == signature))
{
BCLDebug.Trace("REMOTE", "RemotingServices.MethodBaseFromMethodCallMessage with null sig ", msg.MethodName);
ConstructorInfo[] ci;
RuntimeType rt = t as RuntimeType;
if (rt == null)
ci = t.GetConstructors();
else
ci = rt.GetConstructors();
if(1 != ci.Length)
{
// There is more than one constructor defined but
// we do not have a signature to differentiate between
// them.
throw new AmbiguousMatchException(
Environment.GetResourceString(
"Remoting_AmbiguousCTOR"));
}
mb = ci[0];
}
else
{
BCLDebug.Trace("REMOTE", "RemotingServices.MethodBaseFromMethodCallMessage with non-null sig ", msg.MethodName, " ", signature.Length);
RuntimeType rt = t as RuntimeType;
if (rt == null)
mb = t.GetConstructor(signature);
else
mb = rt.GetConstructor(signature);
}
}
else if((msg is IMethodCallMessage) || (msg is IMethodReturnMessage))
{
// We demand reflection permission in the api that calls this
// for non-public types
if(null == signature)
{
BCLDebug.Trace("REMOTE", "RemotingServices.MethodBaseFromMethodCallMessage with null sig ", msg.MethodName);
RuntimeType rt = t as RuntimeType;
if (rt == null)
mb = t.GetMethod(msg.MethodName, RemotingServices.LookupAll);
else
mb = rt.GetMethod(msg.MethodName, RemotingServices.LookupAll);
}
else
{
BCLDebug.Trace("REMOTE", "RemotingServices.MethodBaseFromMethodCallMessage with non-null sig ", msg.MethodName, " ", signature.Length);
RuntimeType rt = t as RuntimeType;
if (rt == null)
mb = t.GetMethod(msg.MethodName, RemotingServices.LookupAll, null, signature, null);
else
mb = rt.GetMethod(msg.MethodName, RemotingServices.LookupAll, null, CallingConventions.Any, signature, null);
}
}
return mb;
}
[System.Security.SecurityCritical] // auto-generated
internal static bool IsMethodAllowedRemotely(MethodBase method)
{
// MarhsalByRefObject.InvokeMember is allowed to be invoked remotely. It is a wrapper for a com method as represented in managed
// code. The managed code was generated by tlbimpl. A test does not have to be made to make sure that the COM object method is public because
// the tlbimpl will only generate methods which can be invoked remotely.
if (s_FieldGetterMB == null ||
s_FieldSetterMB == null ||
s_IsInstanceOfTypeMB == null ||
s_InvokeMemberMB == null ||
s_CanCastToXmlTypeMB == null)
{
System.Security.CodeAccessPermission.Assert(true);
if (s_FieldGetterMB == null)
s_FieldGetterMB = typeof(Object).GetMethod(FieldGetterName,RemotingServices.LookupAll);
if (s_FieldSetterMB == null)
s_FieldSetterMB = typeof(Object).GetMethod(FieldSetterName, RemotingServices.LookupAll);
if (s_IsInstanceOfTypeMB == null)
{
s_IsInstanceOfTypeMB =
typeof(MarshalByRefObject).GetMethod(
IsInstanceOfTypeName, RemotingServices.LookupAll);
}
if (s_CanCastToXmlTypeMB == null)
{
s_CanCastToXmlTypeMB =
typeof(MarshalByRefObject).GetMethod(
CanCastToXmlTypeName, RemotingServices.LookupAll);
}
if (s_InvokeMemberMB == null)
{
s_InvokeMemberMB =
typeof(MarshalByRefObject).GetMethod(
InvokeMemberName, RemotingServices.LookupAll);
}
}
return
method == s_FieldGetterMB ||
method == s_FieldSetterMB ||
method == s_IsInstanceOfTypeMB ||
method == s_InvokeMemberMB ||
method == s_CanCastToXmlTypeMB;
}
[System.Security.SecurityCritical] // auto-generated_required
public static bool IsOneWay(MethodBase method)
{
if (method == null)
return false;
RemotingMethodCachedData cache =
InternalRemotingServices.GetReflectionCachedData(method);
return cache.IsOneWayMethod();
}
// Given a method base object, see if we can find an async version of the
// method on the same class.
internal static bool FindAsyncMethodVersion(MethodInfo method,
out MethodInfo beginMethod,
out MethodInfo endMethod)
{
beginMethod = null;
endMethod = null;
// determine names of Begin/End versions
String beginName = "Begin" + method.Name;
String endName = "End" + method.Name;
// determine parameter lists for Begin/End versions
ArrayList beginParameters = new ArrayList();
ArrayList endParameters = new ArrayList();
Type beginReturnType = typeof(IAsyncResult);
Type endReturnType = method.ReturnType;
ParameterInfo[] paramList = method.GetParameters();
foreach (ParameterInfo param in paramList)
{
if (param.IsOut)
endParameters.Add(param);
else
if (param.ParameterType.IsByRef)
{
beginParameters.Add(param);
endParameters.Add(param);
}
else
{
// it's an in parameter
beginParameters.Add(param);
}
}
beginParameters.Add(typeof(AsyncCallback));
beginParameters.Add(typeof(Object));
endParameters.Add(typeof(IAsyncResult));
// try to match these signatures with the methods on the type
Type type = method.DeclaringType;
MethodInfo[] methods = type.GetMethods();
foreach (MethodInfo mi in methods)
{
ParameterInfo[] parameterList = mi.GetParameters();
// see if return value is IAsyncResult
if (mi.Name.Equals(beginName) &&
(mi.ReturnType == beginReturnType) &&
CompareParameterList(beginParameters, parameterList))
{
beginMethod = mi;
}
else
if (mi.Name.Equals(endName) &&
(mi.ReturnType == endReturnType) &&
CompareParameterList(endParameters, parameterList))
{
endMethod = mi;
}
}
if ((beginMethod != null) && (endMethod != null))
return true;
else
return false;
} // FindAsyncMethodVersion
// Helper function for FindAsyncMethodVersion
private static bool CompareParameterList(ArrayList params1, ParameterInfo[] params2)
{
// params1 contains a list of parameters (and possibly some types which are
// assumed to be in parameters)
// param2 just contains the list of parameters from some method
if (params1.Count != params2.Length)
return false;
int co = 0;
foreach (Object obj in params1)
{
ParameterInfo param = params2[co];
ParameterInfo pi = obj as ParameterInfo;
if (null != pi)
{
if ((pi.ParameterType != param.ParameterType) ||
(pi.IsIn != param.IsIn) ||
(pi.IsOut != param.IsOut))
{
return false;
}
}
else
if (((Type)obj != param.ParameterType) && param.IsIn)
return false;
co++;
}
return true;
} // CompareParameterList
[System.Security.SecurityCritical] // auto-generated_required
public static Type GetServerTypeForUri(String URI)
{
Type svrType = null;
if(null != URI)
{
ServerIdentity srvID = (ServerIdentity)IdentityHolder.ResolveIdentity(URI);
if(null == srvID)
{
// Check if this a well-known object which needs to be faulted in
svrType = RemotingConfigHandler.GetServerTypeForUri(URI);
}
else
{
svrType = srvID.ServerType;
}
}
return svrType;
}
// This method is called after an appdomain is unloaded from the
// current domain.
[System.Security.SecurityCritical] // auto-generated
internal static void DomainUnloaded(Int32 domainID)
{
// Remove any client side identities, presumably the driver
// domain has released all references to proxies in the unloaded
// domain.
IdentityHolder.FlushIdentityTable();
// Remove the cross domain channel sink for the unloaded domain
CrossAppDomainSink.DomainUnloaded(domainID);
}
// This method is called from the VM and helps the appdomain
// folks to get to the server appdomain from a proxy. This is
// expected to be called on strictly cross domain proxies.
//
// This returns the unmanaged context object for the proxy.
// We fetch the appDomain out of the context in the VM.
// This will return NULL (or 0) if the server for the proxy is
// not from this process or if the server domain is invalid
// or if there is not enough information to determine the server
// context.
[System.Security.SecurityCritical] // auto-generated
internal static IntPtr GetServerContextForProxy(Object tp)
{
ObjRef objRef = null;
bool bSameDomain;
int domainId;
return GetServerContextForProxy(
tp,
out objRef,
out bSameDomain,
out domainId);
}
// This returns the domain ID if the proxy is from this process
// whether or not the domain is valid!
[System.Security.SecurityCritical] // auto-generated
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
internal static int GetServerDomainIdForProxy(Object tp)
{
Contract.Assert(IsTransparentProxy(tp),"Must be called only for TPs");
RealProxy rp=GetRealProxy(tp);
Identity id = rp.IdentityObject;
return id.ObjectRef.GetServerDomainId();
}
// This will retrieve the server domain and context id
[System.Security.SecurityCritical] // auto-generated
internal static void GetServerContextAndDomainIdForProxy(Object tp,
out IntPtr contextId,
out int domainId)
{
ObjRef objRef;
bool bSameDomain;
contextId =
GetServerContextForProxy(
tp,
out objRef,
out bSameDomain,
out domainId);
} // GetServerContextAndDomainIdForProxy
// This is a helper for the methods above.
// NOTE:: Returns the unmanaged server context for a proxy
// This is *NOT* the same as "public int Context::ContextID"
[System.Security.SecurityCritical] // auto-generated
private static IntPtr GetServerContextForProxy(
Object tp, out ObjRef objRef, out bool bSameDomain, out int domainId)
{
// Note: the contextId we return from here should be the address
// of the unmanaged (VM) context object or NULL.
IntPtr contextId = IntPtr.Zero;
objRef = null;
bSameDomain = false;
domainId = 0;
if (IsTransparentProxy(tp))
{
// This is a transparent proxy. Try to obtain the backing
// RealProxy from it.
RealProxy rp = GetRealProxy(tp);
// Get the identity from the realproxy
Identity id = rp.IdentityObject;
if(null != id)
{
ServerIdentity serverID = id as ServerIdentity;
if (null != serverID)
{
// We are in the app domain of the server
bSameDomain = true;
contextId = serverID.ServerContext.InternalContextID;
domainId = Thread.GetDomain().GetId();
}
else
{
// Server is from another app domain
// (possibly from another process)
objRef = id.ObjectRef;
if (objRef != null)
{
contextId = objRef.GetServerContext(out domainId);
}
else
{
// Proxy does not have an associated ObjRef
// <
//Contract.Assert(false, "Found proxy without an objref");
contextId = IntPtr.Zero;
}
}
}
else
{
// This was probably a custom proxy other than RemotingProxy
Contract.Assert(
!(rp is RemotingProxy),
"!(rp is RemotingProxy)");
contextId = Context.DefaultContext.InternalContextID;
}
}
return contextId;
}
// Return the server context of the object provided if the object
// was born in the current appdomain, else return null.
//
// NOTE: This returns the managed context object that the server
// is associated with ...
// <
[System.Security.SecurityCritical] // auto-generated
internal static Context GetServerContext(MarshalByRefObject obj)
{
Context serverCtx = null;
if(!IsTransparentProxy(obj) && (obj is ContextBoundObject))
{
// The object is native to the current context.
serverCtx = Thread.CurrentContext;
}
else
{
RealProxy rp = GetRealProxy(obj);
Identity id = rp.IdentityObject;
ServerIdentity serverID = id as ServerIdentity;
if(null != serverID)
{
// The object was born in the current appdomain.
// Extract the server context.
serverCtx = serverID.ServerContext;
}
}
return serverCtx;
}
// Return the actual type of the server object given the proxy
//
//
[System.Security.SecurityCritical] // auto-generated
private static Object GetType(Object tp)
{
Contract.Assert(IsTransparentProxy(tp), "IsTransparentProxy(tp)");
Type serverType = null;
RealProxy rp = GetRealProxy(tp);
Identity id = rp.IdentityObject;
Contract.Assert(!(id is ServerIdentity), "(!id is ServerIdentity)");
if((null != id) && (null != id.ObjectRef) &&
(null != id.ObjectRef.TypeInfo))
{
IRemotingTypeInfo serverTypeInfo = id.ObjectRef.TypeInfo;
String typeName = serverTypeInfo.TypeName;
if (typeName != null)
{
serverType = InternalGetTypeFromQualifiedTypeName(typeName);
}
}
return serverType;
}
[System.Security.SecurityCritical] // auto-generated
internal static byte[] MarshalToBuffer(Object o, bool crossRuntime)
{
if (crossRuntime)
{
// Making a call on a MBRO cross-process or cross-runtime likely fails in most common
// scenarios. We check for signs that Remoting is really expected by the user.
if (RemotingServices.IsTransparentProxy(o))
{
if (RemotingServices.GetRealProxy(o) is RemotingProxy)
{
// the object uses a default proxy - it means that Remoting may not be expected
if (ChannelServices.RegisteredChannels.Length == 0)
{
return null;
}
}
}
else
{
MarshalByRefObject mbro = o as MarshalByRefObject;
if (mbro != null)
{
ProxyAttribute proxyAttr = ActivationServices.GetProxyAttribute(mbro.GetType());
if (proxyAttr == ActivationServices.DefaultProxyAttribute)
{
// the object does not use a custom proxy - it means that Remoting may not be expected
if (ChannelServices.RegisteredChannels.Length == 0)
{
return null;
}
}
}
}
}
// serialize headers and args together using the binary formatter
MemoryStream stm = new MemoryStream();
RemotingSurrogateSelector ss = new RemotingSurrogateSelector();
BinaryFormatter fmt = new BinaryFormatter();
fmt.SurrogateSelector = ss;
fmt.Context = new StreamingContext(StreamingContextStates.Other);
fmt.Serialize(stm, o, null, false /* No Security check */);
return stm.GetBuffer();
}
[System.Security.SecurityCritical] // auto-generated
internal static Object UnmarshalFromBuffer(byte [] b, bool crossRuntime)
{
MemoryStream stm = new MemoryStream(b);
BinaryFormatter fmt = new BinaryFormatter();
fmt.AssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple; //*******Add this line
fmt.SurrogateSelector = null;
fmt.Context = new StreamingContext(StreamingContextStates.Other);
Object o = fmt.Deserialize(stm, null, false /* No Security check */);
if (crossRuntime && RemotingServices.IsTransparentProxy(o))
{
// Making a call on a MBRO cross-process or cross-runtime likely fails in most common
// scenarios. We check for signs that Remoting is really expected by the user.
if (!(RemotingServices.GetRealProxy(o) is RemotingProxy))
{
// the object uses a non-default proxy - this means that Remoting is expected
return o;
}
if (ChannelServices.RegisteredChannels.Length == 0)
{
// the object uses the default Remoting proxy but there are no channels registered
return null;
}
// make a dummy call on the proxy and if it passes use Remoting (the caller of this method
// catches exceptions and interprets them as fallback to COM)
o.GetHashCode();
}
return o;
}
internal static Object UnmarshalReturnMessageFromBuffer(byte [] b, IMethodCallMessage msg)
{
MemoryStream stm = new MemoryStream(b);
BinaryFormatter fmt = new BinaryFormatter();
fmt.SurrogateSelector = null;
fmt.Context = new StreamingContext(StreamingContextStates.Other);
Object o = fmt.DeserializeMethodResponse(stm, null, (IMethodCallMessage)msg);
//= fmt.Deserialize(stm, null, false /* No Security check */);
return o;
}
[System.Security.SecurityCritical] // auto-generated_required
public static IMethodReturnMessage ExecuteMessage(MarshalByRefObject target,
IMethodCallMessage reqMsg)
{
// Argument validation
if(null == target)
{
throw new ArgumentNullException("target");
}
Contract.EndContractBlock();
RealProxy rp = GetRealProxy(target);
// Check for context match
if( rp is RemotingProxy
&& !rp.DoContextsMatch() )
{
throw new RemotingException(
Environment.GetResourceString("Remoting_Proxy_WrongContext"));
}
// Dispatch the message
StackBuilderSink dispatcher = new StackBuilderSink(target);
// dispatch the message
IMethodReturnMessage retMsg = (IMethodReturnMessage)dispatcher.SyncProcessMessage(reqMsg);
return retMsg;
} // ExecuteMessage
//
// Methods for mapping and resolving qualified type names
// A qualified type name describes the name that we use in the ObjRef and
// message TypeName. It consists either of the actual type name or
// "<typeId>:typename" where for now "soap:<soap type name>" is the only
// supported alternative. <
// This is used by the cached type data to figure out which type name
// to use (this should never be publicly exposed; GetDefaultQualifiedTypeName should,
// if anything at all)
[System.Security.SecurityCritical] // auto-generated
internal static String DetermineDefaultQualifiedTypeName(Type type)
{
if (type == null)
throw new ArgumentNullException("type");
Contract.EndContractBlock();
// see if there is an xml type name
String xmlTypeName = null;
String xmlTypeNamespace = null;
if (SoapServices.GetXmlTypeForInteropType(type, out xmlTypeName, out xmlTypeNamespace))
{
return "soap:" + xmlTypeName + ", " + xmlTypeNamespace;
}
// there are no special mappings, so use the fully qualified CLR type name
// <
return type.AssemblyQualifiedName;
} // DetermineDefaultQualifiedTypeName
// retrieves type name from the cache data which uses DetermineDefaultQualifiedTypeName
[System.Security.SecurityCritical] // auto-generated
internal static String GetDefaultQualifiedTypeName(RuntimeType type)
{
RemotingTypeCachedData cache = (RemotingTypeCachedData)
InternalRemotingServices.GetReflectionCachedData(type);
return cache.QualifiedTypeName;
} // GetDefaultQualifiedTypeName
internal static String InternalGetClrTypeNameFromQualifiedTypeName(String qualifiedTypeName)
{
// look to see if this is a clr type name
if (qualifiedTypeName.Length > 4) // length of "clr:"
{
if (String.CompareOrdinal(qualifiedTypeName, 0, "clr:", 0, 4) == 0)
{
// strip "clr:" off the front
String actualTypeName = qualifiedTypeName.Substring(4);
return actualTypeName;
}
}
return null;
}
private static int IsSoapType(String qualifiedTypeName)
{
// look to see if this is a soap type name
if (qualifiedTypeName.Length > 5) // length of "soap:"
{
if (String.CompareOrdinal(qualifiedTypeName, 0, "soap:", 0, 5) == 0)
{
// find comma starting from just past "soap:"
return qualifiedTypeName.IndexOf(',', 5);
}
}
return -1;
}
[System.Security.SecurityCritical] // auto-generated
internal static String InternalGetSoapTypeNameFromQualifiedTypeName(String xmlTypeName, String xmlTypeNamespace)
{
// This must be the default encoding of the soap type (or the type wasn't
// preloaded).
String typeNamespace;
String assemblyName;
if (!SoapServices.DecodeXmlNamespaceForClrTypeNamespace(
xmlTypeNamespace,
out typeNamespace, out assemblyName))
{
return null;
}
String typeName;
if ((typeNamespace != null) && (typeNamespace.Length > 0))
typeName = typeNamespace + "." + xmlTypeName;
else
typeName = xmlTypeName;
try
{
String fullTypeName = typeName + ", " + assemblyName;
return fullTypeName;
}
catch
{
// We ignore errors and will just return null below since the type
// isn't set.
}
return null;
}
[System.Security.SecurityCritical] // auto-generated
internal static String InternalGetTypeNameFromQualifiedTypeName(String qualifiedTypeName)
{
if (qualifiedTypeName == null)
throw new ArgumentNullException("qualifiedTypeName");
Contract.EndContractBlock();
String decodedName = InternalGetClrTypeNameFromQualifiedTypeName(qualifiedTypeName);
if (decodedName != null)
{
return decodedName;
}
int index = IsSoapType(qualifiedTypeName);
if (index != -1)
{
// This is a soap type name. We need to parse it and try to
// find the actual type. Format is "soap:xmlTypeName, xmlTypeNamespace"
String xmlTypeName = qualifiedTypeName.Substring(5, index - 5);
// +2 is to skip the comma and following space
String xmlTypeNamespace =
qualifiedTypeName.Substring(index + 2, qualifiedTypeName.Length - (index + 2));
decodedName = InternalGetSoapTypeNameFromQualifiedTypeName(xmlTypeName, xmlTypeNamespace);
if (decodedName != null)
{
return decodedName;
}
}
//no prefix return same
return qualifiedTypeName;
}
// Retrieves type based on qualified type names. This does not do security checks
// so don't expose this publicly (at least not directly). It returns null if the
// type cannot be loaded.
[System.Security.SecurityCritical] // auto-generated
internal static RuntimeType InternalGetTypeFromQualifiedTypeName(String qualifiedTypeName, bool partialFallback)
{
if (qualifiedTypeName == null)
throw new ArgumentNullException("qualifiedTypeName");
Contract.EndContractBlock();
String decodedName = InternalGetClrTypeNameFromQualifiedTypeName(qualifiedTypeName);
if (decodedName != null)
{
return LoadClrTypeWithPartialBindFallback(decodedName, partialFallback);
}
int index = IsSoapType(qualifiedTypeName);
if (index != -1)
{
// This is a soap type name. We need to parse it and try to
// find the actual type. Format is "soap:xmlTypeName, xmlTypeNamespace"
String xmlTypeName = qualifiedTypeName.Substring(5, index - 5);
// +2 is to skip the comma and following space
String xmlTypeNamespace =
qualifiedTypeName.Substring(index + 2, qualifiedTypeName.Length - (index + 2));
RuntimeType type = (RuntimeType)SoapServices.GetInteropTypeFromXmlType(xmlTypeName, xmlTypeNamespace);
if (type != null)
{
return type;
}
decodedName = InternalGetSoapTypeNameFromQualifiedTypeName(xmlTypeName, xmlTypeNamespace);
if (decodedName != null)
{
return LoadClrTypeWithPartialBindFallback(decodedName, true);
}
}
// There is no prefix, so assume this is a normal CLR type name.
return LoadClrTypeWithPartialBindFallback(qualifiedTypeName, partialFallback);
} // InternalGetTypeFromQualifiedTypeName
[System.Security.SecurityCritical] // auto-generated
internal static Type InternalGetTypeFromQualifiedTypeName(String qualifiedTypeName)
{
return InternalGetTypeFromQualifiedTypeName(qualifiedTypeName, true);
}
[MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
private unsafe static RuntimeType LoadClrTypeWithPartialBindFallback(String typeName, bool partialFallback)
{
// Try to load a type with fully qualified name if partialFallback is not requested
if (!partialFallback)
{
return (RuntimeType)Type.GetType(typeName, false);
}
else
{
// A hack
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
return RuntimeTypeHandle.GetTypeByName(typeName, false, false, false, ref stackMark, true /* hack */);
}
} // LoadClrTypeWithPartialBindFallback
//
// end of Methods for mapping and resolving qualified type names
//
//
// These are used by the profiling code to profile remoting.
//
[System.Security.SecurityCritical] // auto-generated
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern bool CORProfilerTrackRemoting();
[System.Security.SecurityCritical] // auto-generated
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern bool CORProfilerTrackRemotingCookie();
[System.Security.SecurityCritical] // auto-generated
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern bool CORProfilerTrackRemotingAsync();
[System.Security.SecurityCritical] // auto-generated
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern void CORProfilerRemotingClientSendingMessage(out Guid id, bool fIsAsync);
[System.Security.SecurityCritical] // auto-generated
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern void CORProfilerRemotingClientReceivingReply(Guid id, bool fIsAsync);
[System.Security.SecurityCritical] // auto-generated
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern void CORProfilerRemotingServerReceivingMessage(Guid id, bool fIsAsync);
[System.Security.SecurityCritical] // auto-generated
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern void CORProfilerRemotingServerSendingReply(out Guid id, bool fIsAsync);
[System.Security.SecurityCritical] // auto-generated_required
[System.Diagnostics.Conditional("REMOTING_PERF")]
[Obsolete("Use of this method is not recommended. The LogRemotingStage existed for internal diagnostic purposes only.")]
public static void LogRemotingStage(int stage) {}
[System.Security.SecurityCritical] // auto-generated
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern void ResetInterfaceCache(Object proxy);
} // RemotingServices
[System.Security.SecurityCritical] // auto-generated_required
[System.Runtime.InteropServices.ComVisible(true)]
public class InternalRemotingServices
{
[System.Security.SecurityCritical] // auto-generated
[System.Diagnostics.Conditional("_LOGGING")]
public static void DebugOutChnl(String s)
{
// BCLDebug.Trace("REMOTINGCHANNELS", "CHNL:" + s + "\n");
Message.OutToUnmanagedDebugger("CHNL:"+s+"\n");
// Console.WriteLine("CHNL:"+s+"\n");
}
[System.Diagnostics.Conditional("_LOGGING")]
public static void RemotingTrace(params Object[]messages)
{
BCLDebug.Trace("REMOTINGCHANNELS",messages);
}
[System.Diagnostics.Conditional("_DEBUG")]
public static void RemotingAssert(bool condition, String message)
{
Contract.Assert(condition, message);
}
[System.Security.SecurityCritical] // auto-generated
[CLSCompliant(false)]
public static void SetServerIdentity(MethodCall m, Object srvID)
{
IInternalMessage im = (IInternalMessage) m;
im.ServerIdentityObject = (ServerIdentity)srvID;
}
// access attribute cached on the reflection object
internal static RemotingMethodCachedData GetReflectionCachedData(MethodBase mi)
{
RuntimeMethodInfo rmi = null;
RuntimeConstructorInfo rci = null;
if ((rmi = mi as RuntimeMethodInfo) != null)
{
return rmi.RemotingCache;
}
else if ((rci = mi as RuntimeConstructorInfo) != null)
{
return rci.RemotingCache;
}
else
throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeReflectionObject"));
}
internal static RemotingTypeCachedData GetReflectionCachedData(RuntimeType type)
{
return type.RemotingCache;
}
internal static RemotingCachedData GetReflectionCachedData(MemberInfo mi)
{
MethodBase mb = null;
RuntimeType rt = null;
RuntimeFieldInfo rfi = null;
SerializationFieldInfo sfi = null;
if ((mb = mi as MethodBase) != null)
return GetReflectionCachedData(mb);
else if ((rt = mi as RuntimeType) != null)
return GetReflectionCachedData(rt);
else if ((rfi = mi as RuntimeFieldInfo) != null)
return rfi.RemotingCache;
else if ((sfi = mi as SerializationFieldInfo) != null)
return sfi.RemotingCache;
else
throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeReflectionObject"));
}
internal static RemotingCachedData GetReflectionCachedData(RuntimeParameterInfo reflectionObject)
{
return reflectionObject.RemotingCache;
}
[System.Security.SecurityCritical] // auto-generated
public static SoapAttribute GetCachedSoapAttribute(Object reflectionObject)
{
MemberInfo mi = reflectionObject as MemberInfo;
RuntimeParameterInfo parameter = reflectionObject as RuntimeParameterInfo;
if (mi != null)
return GetReflectionCachedData(mi).GetSoapAttribute();
else if (parameter != null)
return GetReflectionCachedData(parameter).GetSoapAttribute();
else
return null;
} // GetCachedSoapAttribute
} // InternalRemotingServices
}
|