Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / clr / src / BCL / System / Runtime / Remoting / ActivationServices.cs / 1305376 / ActivationServices.cs
// ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== /*============================================================ ** ** File: ActivationServices.cs ** ** Author(s): ** ** Purpose: ** ** ===========================================================*/ namespace System.Runtime.Remoting.Activation { using System; using System.Security; using System.Threading; using System.Runtime.InteropServices; using System.Runtime.Remoting; using System.Runtime.Remoting.Contexts; using System.Runtime.Remoting.Proxies; using System.Runtime.Remoting.Messaging; using System.Runtime.Remoting.Metadata; using System.Collections; using System.Reflection; using System.IO; using System.Runtime.Serialization; using System.Security.Permissions; using System.Globalization; using System.Runtime.CompilerServices; using System.Diagnostics.Contracts; // Implements various activation services internal static class ActivationServices { private static IActivator activator = null; private static Hashtable _proxyTable = new Hashtable(); private static Type proxyAttributeType = typeof(System.Runtime.Remoting.Proxies.ProxyAttribute); [System.Security.SecurityCritical /*auto-generated*/] private static ProxyAttribute _proxyAttribute = new ProxyAttribute(); [ThreadStaticAttribute()] internal static ActivationAttributeStack _attributeStack; internal const String ActivationServiceURI = "RemoteActivationService.rem"; internal const String RemoteActivateKey = "Remote"; internal const String PermissionKey = "Permission"; internal const String ConnectKey = "Connect"; [System.Security.SecuritySafeCritical] // static constructors should be safe to call static ActivationServices() { } // < //1 private static LocalActivator localActivator = null; // ActivationListener is the object that listens to incoming // activation requests. It delegates the incoming request to // the local activator. //2 private static ActivationListener ActivationListener = null; //3 private static Object staticSyncObject = new Object(); //4 private static bool bInitializing = false; // This gets called upon the first attempt to activate // anything that is ContextBound or MarshalByRef [System.Security.SecurityCritical] // auto-generated private static void Startup() { DomainSpecificRemotingData remData = Thread.GetDomain().RemotingData; // wait on the lock if a)activation has not been initialized yet // or b) activation is being initialized by another thread! if ((!remData.ActivationInitialized) || remData.InitializingActivation) { Object configLock = remData.ConfigLock; bool fLocked = false; RuntimeHelpers.PrepareConstrainedRegions(); try { Monitor.Enter(configLock, ref fLocked); remData.InitializingActivation = true; // Ensure that some other thread did not complete // the work while we were waiting on the lock. if (!remData.ActivationInitialized) { // Startup the activation service BCLDebug.Trace("REMOTE","Starting up activation service ",Thread.CurrentContext); //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // NOTE: This should be the first step in Startup! // Otherwise activation will recurse, when we try // to create the ActivationListener (which is MarshalByRef) //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! remData.LocalActivator = new LocalActivator(); // Add the Lifetime service property to the appdomain. // For now we are assuming that this is the only property // If there are more properties, then an existing array // will need to be expanded to add this property // This is activated in RemotingServices.DomainSpecificRemotingData() // IContextProperty[] contextProperties = new IContextProperty[1]; // contextProperties[0] = new System.Runtime.Remoting.LeaseLifeTimeServiceProperty(); // Thread.GetDomain().RemotingData.AppDomainContextProperties = contextProperties; remData.ActivationListener = new ActivationListener(); remData.ActivationInitialized = true; } remData.InitializingActivation = false; } //lock (remData) finally { if (fLocked) { Monitor.Exit(configLock); } } } } [System.Security.SecurityCritical] // auto-generated private static void InitActivationServices() { // If activation services has not been loaded do it now and create // the instace that will service the activation requests. if (null == activator) { activator = GetActivator(); if (null == activator) { Message.DebugOut("Fatal Error... Could not create activator\n"); throw new RemotingException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Remoting_BadInternalState_ActivationFailure"))); } } } // Determine whether the current context is ok for the activation. [System.Security.SecurityCritical] // auto-generated private static MarshalByRefObject IsCurrentContextOK( RuntimeType serverType, Object[] props, bool bNewObj) { Contract.Assert(!serverType.IsInterface,"!serverType.IsInterface"); MarshalByRefObject retObj = null; // Initialize activation services if needed. // (we temporary null out the activation attributes in case // InitActivationServices creates an MBR). InitActivationServices(); // Obtain the method info which will create an instance // of type RealProxy ProxyAttribute pa = GetProxyAttribute(serverType); Contract.Assert(null != pa, "null != pa"); if (Object.ReferenceEquals(pa, DefaultProxyAttribute)) retObj = pa.CreateInstanceInternal(serverType); else { retObj = pa.CreateInstance(serverType); // We called a custom proxy attribute .. make sure it is // returning a server of the correct type. if (retObj != null) { // If a transparent proxy is returned we are fine. // If not then the object's type MUST be compatible // with the type we were requested to activate! if (!RemotingServices.IsTransparentProxy(retObj) && !serverType.IsAssignableFrom(retObj.GetType())) { throw new RemotingException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Remoting_Activation_BadObject"), serverType)); } } } Contract.Assert(null != retObj, "null != retObj"); return retObj; } #if FEATURE_COMINTEROP [System.Security.SecurityCritical] // auto-generated private static MarshalByRefObject CreateObjectForCom( RuntimeType serverType, Object[] props, bool bNewObj) { Contract.Assert(!serverType.IsInterface,"!serverType.IsInterface"); MarshalByRefObject retObj = null; if (PeekActivationAttributes(serverType) != null) throw new NotSupportedException(Environment.GetResourceString("NotSupported_ActivForCom" )); // Initialize activation services if needed InitActivationServices(); // Obtain the method info which will create an instance // of type RealProxy ProxyAttribute pa = GetProxyAttribute(serverType); Contract.Assert(null != pa, "null != pa"); if(pa is ICustomFactory) { retObj = ((ICustomFactory)pa).CreateInstance(serverType); } else { retObj = (MarshalByRefObject)Activator.CreateInstance(serverType, true); } Contract.Assert(null != retObj, "null != retObj"); return retObj; } #endif // FEATURE_COMINTEROP // For types with no proxy attribute, we take the default route of // querying attributes if the current context is suitable for // activation. [System.Security.SecurityCritical] // auto-generated private static bool IsCurrentContextOK(RuntimeType serverType, Object[] props, ref ConstructorCallMessage ctorCallMsg) { //Get callSite attributes Object[] callSiteAttr = PeekActivationAttributes(serverType); // Clear from the attribute stack if (callSiteAttr != null) { PopActivationAttributes(serverType); } Object[] womAttr = new Object[1]; womAttr[0] = GetGlobalAttribute(); // Get the type context attributes Object[] typeAttr = GetContextAttributesForType(serverType); // Get the client context (current context) Context cliCtx = Thread.CurrentContext; // Create a ctorCallMsg with the reqd info ctorCallMsg = new ConstructorCallMessage( callSiteAttr, womAttr, typeAttr, serverType); // This is the activator that handles activation in *all* cases // Based on whether what the activation attributes do.... other // activators may get chained ahead of this one and may take // over the activation process... (possibly) delegating to this // only in the last stage. // Note: currently, this does not get used in the same context (MBR) // scenarios ... because of the 2-step activation model of JIT. ctorCallMsg.Activator = new ConstructionLevelActivator(); // Ask all attributes if they are happy with the current context // NOTE: if someone says no, we do not ask the rest of the attributes // This is why, womAttr (which is the global activation service // attribute) *must* be the first one we query. bool bCtxOK = QueryAttributesIfContextOK(cliCtx, ctorCallMsg, womAttr); if (bCtxOK == true) { bCtxOK = QueryAttributesIfContextOK(cliCtx, ctorCallMsg, callSiteAttr); if (bCtxOK == true) { bCtxOK = QueryAttributesIfContextOK(cliCtx, ctorCallMsg, typeAttr); } } return bCtxOK; } [System.Security.SecurityCritical] // auto-generated private static void CheckForInfrastructurePermission(RuntimeAssembly asm) { // Make a security check to ensure that the context attribute // is from a trusted assembly! if (asm != RemotingServices.s_MscorlibAssembly) { CodeAccessSecurityEngine.CheckAssembly(asm, RemotingServices.s_RemotingInfrastructurePermission); } } [System.Security.SecurityCritical] // auto-generated private static bool QueryAttributesIfContextOK( Context ctx, IConstructionCallMessage ctorMsg, Object[] attributes) { bool bCtxOK = true; if (attributes != null) { for (int i=0; i= ActivatorLevel.Context, "activator level must be at least x-context!"); // Check with ActivationServices if we did a "Connect" with // a remote server during IsContextOK Contract.Assert( ActivationServices.CheckIfConnected(remProxy, ctorMsg) == null, "We shouldn't come through this path on a Connect."); // Client context was not approved for activation ... // This is the more elaborate (real) activation case i.e. // we have to go at least out of the client context to // finish the work. // Prepare for the handoff to Activation Service // Ask various attributes to contribute properties // The attributes may chain in other activators into // the activation chain (to hijack/participate in // the activation process). ActivationServices.GetPropertiesFromAttributes( (IConstructionCallMessage)ctorMsg, ctorMsg.CallSiteActivationAttributes); ActivationServices.GetPropertiesFromAttributes( ctorMsg, ((ConstructorCallMessage)ctorMsg).GetWOMAttributes()); ActivationServices.GetPropertiesFromAttributes( (IConstructionCallMessage)ctorMsg, ((ConstructorCallMessage)ctorMsg).GetTypeAttributes()); // Fetch the client context chain IMessageSink cliCtxChain = Thread.CurrentContext.GetClientContextChain(); // Ask the client context chain to take over from here. IMethodReturnMessage retMsg = (IMethodReturnMessage) cliCtxChain.SyncProcessMessage(ctorMsg); // The return message may not be of type // IConstructionReturnMessage if an exception happens // in the sink chains. ctorRetMsg = retMsg as IConstructionReturnMessage; if (null == retMsg) { throw new RemotingException( Environment.GetResourceString( "Remoting_Activation_Failed")); } else if (retMsg.Exception != null) { throw retMsg.Exception; } } // Note: PropagateOutParameters is now handled by RealProxy // CallContext from retMsg should be already set by RealProxy Contract.Assert( null != ctorRetMsg, "Activate returning null ConstructorReturnMessage"); return ctorRetMsg; } // This function is called by ActivationServices in case // the activation needs to be within the same appdomain. These // are only for ContextBound types. // It is also called to do satisfy remote incoming requests from // the activation services. These could be for both ContextBound // and MarshalByRef types. [System.Security.SecurityCritical] // auto-generated internal static IConstructionReturnMessage DoCrossContextActivation( IConstructionCallMessage reqMsg) { bool bCtxBound = reqMsg.ActivationType.IsContextful; Context serverContext = null; if (bCtxBound) { // If the type is context bound, we need to create // the appropriate context and activate the object inside // it. // < // Create a new Context serverContext = new Context(); // < ArrayList list = (ArrayList) reqMsg.ContextProperties; RuntimeAssembly asm = null; for (int i=0; i retSize-1) { IContextAttribute[] newAttr = new IContextAttribute[2*retSize]; Array.Copy( retAttr, // srcArray 0, // srcIndex newAttr, // destArray 0, // destIndex retSize); // lengthToCopy retAttr = newAttr; retSize = retSize*2; } retAttr[numAttr-1] = attr; } } IContextAttribute[] ctxAttr = new IContextAttribute[numAttr]; Array.Copy(retAttr, ctxAttr, numAttr); return ctxAttr; } // This is called during RS.IsContextOK to check if the new XXX() is configured // to do a direct connect, and if it is we Connect to the URL and return // the proxy. In the second stage, when the constructor executes on the proxy // we will make sure (in Activate) that there are no CTOR args. [System.Security.SecurityCritical] // auto-generated internal static Object ConnectIfNecessary(IConstructionCallMessage ctorMsg) { // If the type being instantiated is configured for Connect // we would have added its URL as the connect key during // LocalActivator::IsContextOK // Look for the connect URL String objURL = (String) ctorMsg.Properties[ConnectKey]; Object proxy = null; if (objURL != null) { // Connect to the URL and return the proxy proxy = RemotingServices.Connect( ctorMsg.ActivationType, objURL); } // If the type is not setup for connecting we return null! return proxy; } // This is really used to distinguish between proxies for completely // within AppDomain activations and the ones from "Connect" during // the second stage (RS::Activate) // For the former, we have to run constructor etc and for the latter // we have to check that there is no non-defaul CTOR. [System.Security.SecurityCritical] // auto-generated internal static Object CheckIfConnected( RemotingProxy proxy, IConstructionCallMessage ctorMsg) { // If we performed a connect, we must have put the URL as // the connectKey in the message. String objURL = (String) ctorMsg.Properties[ConnectKey]; Object tp = null; if (objURL != null) { // We did perform a connect during IsContextOK // Just get the TP from RP and return it. tp = (Object)proxy.GetTransparentProxy(); } // We return null if we do not recognize this proxy! return tp; } internal static void PushActivationAttributes(Type serverType, Object[] attributes) { // There is one such object per thread if (_attributeStack == null) { _attributeStack = new ActivationAttributeStack(); } _attributeStack.Push(serverType, attributes); } internal static Object[] PeekActivationAttributes(Type serverType) { // We can get a peek w/o a prior Push (eg. activation starting // with NewObj) if (_attributeStack == null) { return null; } return _attributeStack.Peek(serverType); } internal static void PopActivationAttributes(Type serverType) { Contract.Assert(_attributeStack != null, "Pop w/o a prior Set()?"); _attributeStack.Pop(serverType); } } // class ActivationServices // This is the local activation helper and also the Attribute // that gets queried about every activation [System.Security.SecurityCritical] // auto-generated internal class LocalActivator: ContextAttribute, IActivator { internal LocalActivator() : base(ActivationServices.ActivationServiceURI) { } // --------------------------------------------------------------- // ContextAttribute functionality // --------------------------------------------------------------- // IContextAttribute::IsContextOK // This will check if a type is configured for remote activation ... // We return 'false' for IsContextOK if it is. [System.Security.SecurityCritical] public override bool IsContextOK( Context ctx, IConstructionCallMessage ctorMsg) { // If the app is not using config mechanism, we don't want // to intercept activation. if (RemotingConfigHandler.Info == null) { return true; } // check if this type is configured for connect // (instead of remote activate) RuntimeType activationType = ctorMsg.ActivationType as RuntimeType; if (activationType == null) throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType")); WellKnownClientTypeEntry wkte = RemotingConfigHandler.IsWellKnownClientType(activationType); String typeURL = (wkte == null ? null : wkte.ObjectUrl); if (typeURL != null) { // this type does have a direct uri, we will try to connect // to it during the activate call. Cache it in the message. ctorMsg.Properties[ActivationServices.ConnectKey] = typeURL; return false; } else { ActivatedClientTypeEntry acte = RemotingConfigHandler.IsRemotelyActivatedClientType(activationType); String appURL = null; if (acte == null) { // This is the case where the config file had no entry for this type. // We should check the callsite attributes for a URL Object[] callsiteAttributes = ctorMsg.CallSiteActivationAttributes; if(null != callsiteAttributes) { for(int i = 0; i < callsiteAttributes.Length; i++) { UrlAttribute attr = callsiteAttributes[i] as UrlAttribute; if(null != attr) { appURL = attr.UrlValue; } } } if(appURL == null) { // We don't really care about intercepting the activation in this case. return true; } } else { appURL = acte.ApplicationUrl; } // Generate the URL of the remote activator String activatorURL = null; if (!appURL.EndsWith("/", StringComparison.Ordinal)) activatorURL = appURL + "/" + ActivationServices.ActivationServiceURI; else activatorURL = appURL + ActivationServices.ActivationServiceURI; // Mark a flag for remote activation // (caching the url of the activation svc of the remote server) ctorMsg.Properties[ActivationServices.RemoteActivateKey] = activatorURL; return false; } } // IContextAttribute::GetPropertiesForNewContext [System.Security.SecurityCritical] public override void GetPropertiesForNewContext( IConstructionCallMessage ctorMsg) { BCLDebug.Log("ActivationSvc:GlobalAttrib::GetPropForNewCtx"); // This is called during RS::Activate .. when we are sure that // activation is at least x-context and this is a real activation // instead of a spoofed connect underneath the "new". Contract.Assert(ctorMsg!=null, "ctorMsg null?"); if (ctorMsg.Properties.Contains(ActivationServices.RemoteActivateKey)) { // Means we did want to intercept activation! String remActivatorURL = (String) ctorMsg.Properties[ActivationServices.RemoteActivateKey]; AppDomainLevelActivator activator = new AppDomainLevelActivator(remActivatorURL); // Chain ourselves at the end of the AppDomainLevel activators Contract.Assert( ctorMsg.Activator != null, "Should have at least x-context activator"); IActivator curr = ctorMsg.Activator; if (curr.Level < ActivatorLevel.AppDomain) { // Common case .. .only x-context activator(s) in chain activator.NextActivator = curr; ctorMsg.Activator = activator; } else if (curr.NextActivator == null) { // Only one activator but not ContextLevel ... // We go at the end of the chain curr.NextActivator = activator; } else { // We will have to walk the chain till the end of the last // AD activator and plug ourselves in. while (curr.NextActivator.Level >= ActivatorLevel.AppDomain) { curr = curr.NextActivator; } Contract.Assert( curr.NextActivator.Level.Equals(ActivatorLevel.Context), "bad ordering of activators!"); activator.NextActivator = curr.NextActivator; curr.NextActivator = activator; } } } // --------------------------------------------------------------- // IActivator functionality // ---------------------------------------------------------------- //IActivator::NextActivator public virtual IActivator NextActivator { // We are a singleton internal infrastructure object. [System.Security.SecurityCritical] get { return null; } // Don't allow a set either. [System.Security.SecurityCritical] set { throw new InvalidOperationException(); } } //IActivator::ActivatorLevel public virtual ActivatorLevel Level { [System.Security.SecurityCritical] get { return ActivatorLevel.AppDomain; } } private static MethodBase GetMethodBase(IConstructionCallMessage msg) { MethodBase mb = msg.MethodBase; if(null == mb) { BCLDebug.Trace("REMOTE", "Method missing w/name ", msg.MethodName); throw new RemotingException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Remoting_Message_MethodMissing"), msg.MethodName, msg.TypeName)); } return mb; } //IActivator::Activate [System.Security.SecurityCritical] [System.Runtime.InteropServices.ComVisible(true)] public virtual IConstructionReturnMessage Activate( IConstructionCallMessage ctorMsg) { // This is where the activation service hooks in to activation // requests. We get called as the activation message is recognized // by the ClientContextTerminatorSink & routed to us. // // NOTE: This gets called for both purely within appDomain activation // and 'real' remote activation scenarios as the request goes out of // the client context. // It also gets called as an incoming remote call is routed to the // local activator by the remote activator object. // BCLDebug.Log("Activation Services:: new Activate()"); if (ctorMsg == null) { throw new ArgumentNullException("ctorMsg"); } Contract.EndContractBlock(); // Check if we have marked this activation to go remote if (ctorMsg.Properties.Contains(ActivationServices.RemoteActivateKey)) { //DBG Console.WriteLine("Attempting remote activation!"); return DoRemoteActivation(ctorMsg); } else { // We must be in either a pure cross context activation or // a remote incoming activation request (in which case we // already checked the permission to create an instance of // this type). if (ctorMsg.Properties.Contains(ActivationServices.PermissionKey)) { Type activationType = ctorMsg.ActivationType; // We are on the server end of a real remote activation // Create a local attribute that contributes the context // properties requested by the remote request Object[] attr = null; if (activationType.IsContextful) { IList cp = ctorMsg.ContextProperties; if (cp != null && cp.Count > 0) { RemotePropertyHolderAttribute rph = new RemotePropertyHolderAttribute(cp); attr = new Object[1]; attr[0] = rph; } } MethodBase mb = GetMethodBase(ctorMsg); RemotingMethodCachedData methodCache = InternalRemotingServices.GetReflectionCachedData(mb); Object[] args = Message.CoerceArgs(ctorMsg, methodCache.Parameters); Object server = Activator.CreateInstance( activationType, args, attr); // check to see if we need to do redirection if (RemotingServices.IsClientProxy(server)) { // The wellknown type is remoted so we must wrap the proxy // with a local object. // The redirection proxy masquerades as an object of the appropriate // type, and forwards incoming messages to the actual proxy. RedirectionProxy redirectedProxy = new RedirectionProxy((MarshalByRefObject)server, activationType); RemotingServices.MarshalInternal(redirectedProxy, null, activationType); server = redirectedProxy; } return ActivationServices.SetupConstructionReply( server, ctorMsg, null); } else { BCLDebug.Log("Attempting X-Context activation!"); // delegate to the Activator in the message return ctorMsg.Activator.Activate(ctorMsg); } } } // This is called by the local activator during an outgoing activation // request. internal static IConstructionReturnMessage DoRemoteActivation( IConstructionCallMessage ctorMsg) { Contract.Assert(ctorMsg != null, "Null ctorMsg"); // < // < BCLDebug.Log("Attempting Connection to remote activation service"); IActivator remActivator = null; String remActivatorURL = (String) ctorMsg.Properties[ActivationServices.RemoteActivateKey]; try { remActivator = (IActivator) RemotingServices.Connect( typeof(System.Runtime.Remoting.Activation.IActivator), remActivatorURL); } catch (Exception e) { throw new RemotingException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Remoting_Activation_ConnectFailed"), e)); } // Remove the remote activate key as its purpose is served. ctorMsg.Properties.Remove(ActivationServices.RemoteActivateKey); // Delegate the work to the remote activator return remActivator.Activate(ctorMsg); } }// class LocalActivator // This is the object that listens to activation requests internal class ActivationListener:MarshalByRefObject, IActivator { // Override lifetime services to make this object live forever... [System.Security.SecurityCritical] // auto-generated public override Object InitializeLifetimeService() { return null; } //IActivator::NextActivator public virtual IActivator NextActivator { // We are a singleton internal infrastructure object. [System.Security.SecurityCritical] // auto-generated get { return null; } // Don't allow a set either. [System.Security.SecurityCritical] // auto-generated set { throw new InvalidOperationException();} } //IActivator::ActivatorLevel public virtual ActivatorLevel Level { [System.Security.SecurityCritical] // auto-generated get {return ActivatorLevel.AppDomain;} } //IActivator::Activate [System.Security.SecurityCritical] // auto-generated [System.Runtime.InteropServices.ComVisible(true)] public virtual IConstructionReturnMessage Activate( IConstructionCallMessage ctorMsg) { BCLDebug.Log("ActivationListener: received new activation request!"); if (ctorMsg == null || RemotingServices.IsTransparentProxy(ctorMsg)) { throw new ArgumentNullException("ctorMsg"); } Contract.EndContractBlock(); // Add the permission key which distinguishes pure-cross context activation from // a remote request (both of which go through DoCrossContextActivation) ctorMsg.Properties[ActivationServices.PermissionKey] = "allowed"; // Check to make sure that this activation type has been allowed. String activationTypeName = ctorMsg.ActivationTypeName; if (!RemotingConfigHandler.IsActivationAllowed(activationTypeName)) { throw new RemotingException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Remoting_Activation_PermissionDenied"), ctorMsg.ActivationTypeName)); } Type activationType = ctorMsg.ActivationType; if (activationType == null) { throw new RemotingException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_BadType"), ctorMsg.ActivationTypeName)); } // Delegate to the local activator for further work return ActivationServices.GetActivator().Activate(ctorMsg); } } // class ActivationListener // This is a lightweight object to help with the activation // at the appDomain level ... it delegates its work to // ActivationServices.LocalActivator ... which is a heavy // object we can't afford to carry around in the ActivatorChain // (since it may get Serialized/Deserialized) [Serializable] // attribute .. the latter shall be turned on during Beta-2! internal class AppDomainLevelActivator : IActivator { IActivator m_NextActivator; // Do we need this? String m_RemActivatorURL; internal AppDomainLevelActivator(String remActivatorURL) { Contract.Assert(remActivatorURL!=null,"Bad activator URL"); m_RemActivatorURL = remActivatorURL; } internal AppDomainLevelActivator(SerializationInfo info, StreamingContext context) { if (info==null) { throw new ArgumentNullException("info"); } Contract.EndContractBlock(); m_NextActivator = (IActivator) info.GetValue("m_NextActivator",typeof(IActivator)); } //IActivator::NextActivator public virtual IActivator NextActivator { [System.Security.SecurityCritical] // auto-generated get { return m_NextActivator; } [System.Security.SecurityCritical] // auto-generated set { m_NextActivator = value; } } //IActivator::ActivatorLevel public virtual ActivatorLevel Level { [System.Security.SecurityCritical] // auto-generated get { return ActivatorLevel.AppDomain; } } //IActivator::Activate [System.Security.SecurityCritical] // auto-generated [System.Runtime.InteropServices.ComVisible(true)] public virtual IConstructionReturnMessage Activate( IConstructionCallMessage ctorMsg) { // This function will get invoked when the ClientContextTerminator sink // notices that an activation request message is passed to it ... it // will route the message to the Activator present inside the ctorMsg // (which happens to be us in this case!) // remove ourselves from the Activator chain ctorMsg.Activator = m_NextActivator; return ActivationServices.GetActivator().Activate(ctorMsg); } } // This is a lightweight object to help with the activation // at the context level ... [Serializable] internal class ContextLevelActivator : IActivator { IActivator m_NextActivator; internal ContextLevelActivator() { m_NextActivator = null; } internal ContextLevelActivator(SerializationInfo info, StreamingContext context) { if (info==null) { throw new ArgumentNullException("info"); } Contract.EndContractBlock(); m_NextActivator = (IActivator) info.GetValue("m_NextActivator",typeof(IActivator)); } //IActivator::NextActivator public virtual IActivator NextActivator { [System.Security.SecurityCritical] // auto-generated get { return m_NextActivator; } [System.Security.SecurityCritical] // auto-generated set { m_NextActivator = value; } } //IActivator::ActivatorLevel public virtual ActivatorLevel Level { [System.Security.SecurityCritical] // auto-generated get { return ActivatorLevel.Context; } } //IActivator::Activate [System.Security.SecurityCritical] // auto-generated [System.Runtime.InteropServices.ComVisible(true)] public virtual IConstructionReturnMessage Activate( IConstructionCallMessage ctorMsg) { // remove ourselves from the Activator chain ctorMsg.Activator = ctorMsg.Activator.NextActivator; // Delegate to remoting services to do the hard work. // This will create a context, enter it, run through // the context sink chain & then delegate to the nex // activator inside the ctorMsg (quite likely to be // the default ConstructionLevelActivator) return ActivationServices.DoCrossContextActivation(ctorMsg); } } // This is a lightweight object to help with the activation // at the appDomain level ... it delegates its work to // ActivationServices.LocalActivator ... which is a heavy // object we can't afford to carry around in the ActivatorChain // (since it may get Serialized/Deserialized) [Serializable] internal class ConstructionLevelActivator : IActivator { internal ConstructionLevelActivator() { } //IActivator::NextActivator public virtual IActivator NextActivator { // The construction level activator is a terminating activator [System.Security.SecurityCritical] // auto-generated get { return null; } // Throw if someone attempts a set [System.Security.SecurityCritical] // auto-generated set { throw new InvalidOperationException(); } } //IActivator::ActivatorLevel public virtual ActivatorLevel Level { [System.Security.SecurityCritical] // auto-generated get { return ActivatorLevel.Construction; } } //IActivator::Activate [System.Security.SecurityCritical] // auto-generated [System.Runtime.InteropServices.ComVisible(true)] public virtual IConstructionReturnMessage Activate( IConstructionCallMessage ctorMsg) { // This function will get invoked when the ClientContextTerminator sink // notices that an activation request message is passed to it ... it // will route the message to the Activator present inside the ctorMsg // (which happens to be us in this case!) // remove ourselves from the Activator chain ctorMsg.Activator = ctorMsg.Activator.NextActivator; return ActivationServices.DoServerContextActivation(ctorMsg); } } // This acts as a pseudo call site attribute and transfers // the context properties carried in from a remote activation request // to the server side activation internal class RemotePropertyHolderAttribute : IContextAttribute { IList _cp; // incoming list of context properties internal RemotePropertyHolderAttribute(IList cp) { _cp = cp; Contract.Assert(cp != null && cp.Count > 0,"Bad _cp?"); } [System.Security.SecurityCritical] // auto-generated [System.Runtime.InteropServices.ComVisible(true)] public virtual bool IsContextOK(Context ctx, IConstructionCallMessage msg) { // The fact that we got instantiated means some remote activation // has contributed non-default context properties to the ctorMsg return false; } // properties are collected in order from callsite, wom & type // attributes ... so we get a first shot at adding properties [System.Security.SecurityCritical] // auto-generated [System.Runtime.InteropServices.ComVisible(true)] public virtual void GetPropertiesForNewContext(IConstructionCallMessage ctorMsg) { for (int i=0; i<_cp.Count; i++) { // Just cycle through the list and add the properties to // the construction message. // We will throw at a later stage if any of these do not // implement IContextProperty ctorMsg.ContextProperties.Add(_cp[i]); } } } // Note: One instance of this class is setup per thread that comes to // managed remoting for activation of MBR types. All access to methods // is by design single-threaded. (Each thread is working on its own object). // In the case of Activator.CreateInstance ... that API does the Push & // Remoting does a Pop() as soon as it has picked up the attributes from // the threadStatic. The CreateInstance API itself does a Pop() too in // a try-finally. (So this does not work very well if the infrastructure // creates an instance of the same MBR type as the outer type being created. // However, to minimize code churn this is the least risky fix we can do. // The full fix would be to pass activationAttributes into the VM through // reflection code and have the VM pass them over to remoting which will // then hand them over to managed remoting helpers. This will also involve // adding attributes as an additional parameter to // ProxyAttribute.CreateInstance() public method. internal class ActivationAttributeStack { Object[] activationTypes; Object[] activationAttributes; int freeIndex; internal ActivationAttributeStack() { activationTypes = new Object[4]; activationAttributes = new Object[4]; freeIndex = 0; } internal void Push(Type typ, Object[] attr) { Contract.Assert(typ!=null, "typ != null"); Contract.Assert(attr!=null, "attr != null"); if (freeIndex == activationTypes.Length) { // Need to grow our arrays ... this will be exceedingly rare Object[] newTypes = new Object[activationTypes.Length * 2]; Object[] newAttr = new Object[activationAttributes.Length * 2]; Contract.Assert(newAttr.Length == newTypes.Length,"These should be in [....]!"); Array.Copy(activationTypes, newTypes, activationTypes.Length); Array.Copy(activationAttributes, newAttr, activationAttributes.Length); activationTypes = newTypes; activationAttributes = newAttr; } activationTypes[freeIndex] = typ; activationAttributes[freeIndex] = attr; freeIndex++; } internal Object[] Peek(Type typ) { Contract.Assert(typ!=null, "typ != null"); if (freeIndex == 0 || activationTypes[freeIndex-1] != (object)typ) { return null; } return (Object[])activationAttributes[freeIndex-1]; } // Note: Read the comments above .. you can have 2 pops for the same // push. We also count on infrastructure code not activating // the same type as the caller causing a recursive activation. internal void Pop(Type typ) { Contract.Assert(typ!=null, "typ != null"); if (freeIndex != 0 && activationTypes[freeIndex-1] == (object)typ) { freeIndex--; // Clear the popped entry activationTypes[freeIndex] = null; activationAttributes[freeIndex] = null; } } } }//namespace // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== /*============================================================ ** ** File: ActivationServices.cs ** ** Author(s): ** ** Purpose: ** ** ===========================================================*/ namespace System.Runtime.Remoting.Activation { using System; using System.Security; using System.Threading; using System.Runtime.InteropServices; using System.Runtime.Remoting; using System.Runtime.Remoting.Contexts; using System.Runtime.Remoting.Proxies; using System.Runtime.Remoting.Messaging; using System.Runtime.Remoting.Metadata; using System.Collections; using System.Reflection; using System.IO; using System.Runtime.Serialization; using System.Security.Permissions; using System.Globalization; using System.Runtime.CompilerServices; using System.Diagnostics.Contracts; // Implements various activation services internal static class ActivationServices { private static IActivator activator = null; private static Hashtable _proxyTable = new Hashtable(); private static Type proxyAttributeType = typeof(System.Runtime.Remoting.Proxies.ProxyAttribute); [System.Security.SecurityCritical /*auto-generated*/] private static ProxyAttribute _proxyAttribute = new ProxyAttribute(); [ThreadStaticAttribute()] internal static ActivationAttributeStack _attributeStack; internal const String ActivationServiceURI = "RemoteActivationService.rem"; internal const String RemoteActivateKey = "Remote"; internal const String PermissionKey = "Permission"; internal const String ConnectKey = "Connect"; [System.Security.SecuritySafeCritical] // static constructors should be safe to call static ActivationServices() { } // < //1 private static LocalActivator localActivator = null; // ActivationListener is the object that listens to incoming // activation requests. It delegates the incoming request to // the local activator. //2 private static ActivationListener ActivationListener = null; //3 private static Object staticSyncObject = new Object(); //4 private static bool bInitializing = false; // This gets called upon the first attempt to activate // anything that is ContextBound or MarshalByRef [System.Security.SecurityCritical] // auto-generated private static void Startup() { DomainSpecificRemotingData remData = Thread.GetDomain().RemotingData; // wait on the lock if a)activation has not been initialized yet // or b) activation is being initialized by another thread! if ((!remData.ActivationInitialized) || remData.InitializingActivation) { Object configLock = remData.ConfigLock; bool fLocked = false; RuntimeHelpers.PrepareConstrainedRegions(); try { Monitor.Enter(configLock, ref fLocked); remData.InitializingActivation = true; // Ensure that some other thread did not complete // the work while we were waiting on the lock. if (!remData.ActivationInitialized) { // Startup the activation service BCLDebug.Trace("REMOTE","Starting up activation service ",Thread.CurrentContext); //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // NOTE: This should be the first step in Startup! // Otherwise activation will recurse, when we try // to create the ActivationListener (which is MarshalByRef) //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! remData.LocalActivator = new LocalActivator(); // Add the Lifetime service property to the appdomain. // For now we are assuming that this is the only property // If there are more properties, then an existing array // will need to be expanded to add this property // This is activated in RemotingServices.DomainSpecificRemotingData() // IContextProperty[] contextProperties = new IContextProperty[1]; // contextProperties[0] = new System.Runtime.Remoting.LeaseLifeTimeServiceProperty(); // Thread.GetDomain().RemotingData.AppDomainContextProperties = contextProperties; remData.ActivationListener = new ActivationListener(); remData.ActivationInitialized = true; } remData.InitializingActivation = false; } //lock (remData) finally { if (fLocked) { Monitor.Exit(configLock); } } } } [System.Security.SecurityCritical] // auto-generated private static void InitActivationServices() { // If activation services has not been loaded do it now and create // the instace that will service the activation requests. if (null == activator) { activator = GetActivator(); if (null == activator) { Message.DebugOut("Fatal Error... Could not create activator\n"); throw new RemotingException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Remoting_BadInternalState_ActivationFailure"))); } } } // Determine whether the current context is ok for the activation. [System.Security.SecurityCritical] // auto-generated private static MarshalByRefObject IsCurrentContextOK( RuntimeType serverType, Object[] props, bool bNewObj) { Contract.Assert(!serverType.IsInterface,"!serverType.IsInterface"); MarshalByRefObject retObj = null; // Initialize activation services if needed. // (we temporary null out the activation attributes in case // InitActivationServices creates an MBR). InitActivationServices(); // Obtain the method info which will create an instance // of type RealProxy ProxyAttribute pa = GetProxyAttribute(serverType); Contract.Assert(null != pa, "null != pa"); if (Object.ReferenceEquals(pa, DefaultProxyAttribute)) retObj = pa.CreateInstanceInternal(serverType); else { retObj = pa.CreateInstance(serverType); // We called a custom proxy attribute .. make sure it is // returning a server of the correct type. if (retObj != null) { // If a transparent proxy is returned we are fine. // If not then the object's type MUST be compatible // with the type we were requested to activate! if (!RemotingServices.IsTransparentProxy(retObj) && !serverType.IsAssignableFrom(retObj.GetType())) { throw new RemotingException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Remoting_Activation_BadObject"), serverType)); } } } Contract.Assert(null != retObj, "null != retObj"); return retObj; } #if FEATURE_COMINTEROP [System.Security.SecurityCritical] // auto-generated private static MarshalByRefObject CreateObjectForCom( RuntimeType serverType, Object[] props, bool bNewObj) { Contract.Assert(!serverType.IsInterface,"!serverType.IsInterface"); MarshalByRefObject retObj = null; if (PeekActivationAttributes(serverType) != null) throw new NotSupportedException(Environment.GetResourceString("NotSupported_ActivForCom" )); // Initialize activation services if needed InitActivationServices(); // Obtain the method info which will create an instance // of type RealProxy ProxyAttribute pa = GetProxyAttribute(serverType); Contract.Assert(null != pa, "null != pa"); if(pa is ICustomFactory) { retObj = ((ICustomFactory)pa).CreateInstance(serverType); } else { retObj = (MarshalByRefObject)Activator.CreateInstance(serverType, true); } Contract.Assert(null != retObj, "null != retObj"); return retObj; } #endif // FEATURE_COMINTEROP // For types with no proxy attribute, we take the default route of // querying attributes if the current context is suitable for // activation. [System.Security.SecurityCritical] // auto-generated private static bool IsCurrentContextOK(RuntimeType serverType, Object[] props, ref ConstructorCallMessage ctorCallMsg) { //Get callSite attributes Object[] callSiteAttr = PeekActivationAttributes(serverType); // Clear from the attribute stack if (callSiteAttr != null) { PopActivationAttributes(serverType); } Object[] womAttr = new Object[1]; womAttr[0] = GetGlobalAttribute(); // Get the type context attributes Object[] typeAttr = GetContextAttributesForType(serverType); // Get the client context (current context) Context cliCtx = Thread.CurrentContext; // Create a ctorCallMsg with the reqd info ctorCallMsg = new ConstructorCallMessage( callSiteAttr, womAttr, typeAttr, serverType); // This is the activator that handles activation in *all* cases // Based on whether what the activation attributes do.... other // activators may get chained ahead of this one and may take // over the activation process... (possibly) delegating to this // only in the last stage. // Note: currently, this does not get used in the same context (MBR) // scenarios ... because of the 2-step activation model of JIT. ctorCallMsg.Activator = new ConstructionLevelActivator(); // Ask all attributes if they are happy with the current context // NOTE: if someone says no, we do not ask the rest of the attributes // This is why, womAttr (which is the global activation service // attribute) *must* be the first one we query. bool bCtxOK = QueryAttributesIfContextOK(cliCtx, ctorCallMsg, womAttr); if (bCtxOK == true) { bCtxOK = QueryAttributesIfContextOK(cliCtx, ctorCallMsg, callSiteAttr); if (bCtxOK == true) { bCtxOK = QueryAttributesIfContextOK(cliCtx, ctorCallMsg, typeAttr); } } return bCtxOK; } [System.Security.SecurityCritical] // auto-generated private static void CheckForInfrastructurePermission(RuntimeAssembly asm) { // Make a security check to ensure that the context attribute // is from a trusted assembly! if (asm != RemotingServices.s_MscorlibAssembly) { CodeAccessSecurityEngine.CheckAssembly(asm, RemotingServices.s_RemotingInfrastructurePermission); } } [System.Security.SecurityCritical] // auto-generated private static bool QueryAttributesIfContextOK( Context ctx, IConstructionCallMessage ctorMsg, Object[] attributes) { bool bCtxOK = true; if (attributes != null) { for (int i=0; i = ActivatorLevel.Context, "activator level must be at least x-context!"); // Check with ActivationServices if we did a "Connect" with // a remote server during IsContextOK Contract.Assert( ActivationServices.CheckIfConnected(remProxy, ctorMsg) == null, "We shouldn't come through this path on a Connect."); // Client context was not approved for activation ... // This is the more elaborate (real) activation case i.e. // we have to go at least out of the client context to // finish the work. // Prepare for the handoff to Activation Service // Ask various attributes to contribute properties // The attributes may chain in other activators into // the activation chain (to hijack/participate in // the activation process). ActivationServices.GetPropertiesFromAttributes( (IConstructionCallMessage)ctorMsg, ctorMsg.CallSiteActivationAttributes); ActivationServices.GetPropertiesFromAttributes( ctorMsg, ((ConstructorCallMessage)ctorMsg).GetWOMAttributes()); ActivationServices.GetPropertiesFromAttributes( (IConstructionCallMessage)ctorMsg, ((ConstructorCallMessage)ctorMsg).GetTypeAttributes()); // Fetch the client context chain IMessageSink cliCtxChain = Thread.CurrentContext.GetClientContextChain(); // Ask the client context chain to take over from here. IMethodReturnMessage retMsg = (IMethodReturnMessage) cliCtxChain.SyncProcessMessage(ctorMsg); // The return message may not be of type // IConstructionReturnMessage if an exception happens // in the sink chains. ctorRetMsg = retMsg as IConstructionReturnMessage; if (null == retMsg) { throw new RemotingException( Environment.GetResourceString( "Remoting_Activation_Failed")); } else if (retMsg.Exception != null) { throw retMsg.Exception; } } // Note: PropagateOutParameters is now handled by RealProxy // CallContext from retMsg should be already set by RealProxy Contract.Assert( null != ctorRetMsg, "Activate returning null ConstructorReturnMessage"); return ctorRetMsg; } // This function is called by ActivationServices in case // the activation needs to be within the same appdomain. These // are only for ContextBound types. // It is also called to do satisfy remote incoming requests from // the activation services. These could be for both ContextBound // and MarshalByRef types. [System.Security.SecurityCritical] // auto-generated internal static IConstructionReturnMessage DoCrossContextActivation( IConstructionCallMessage reqMsg) { bool bCtxBound = reqMsg.ActivationType.IsContextful; Context serverContext = null; if (bCtxBound) { // If the type is context bound, we need to create // the appropriate context and activate the object inside // it. // < // Create a new Context serverContext = new Context(); // < ArrayList list = (ArrayList) reqMsg.ContextProperties; RuntimeAssembly asm = null; for (int i=0; i retSize-1) { IContextAttribute[] newAttr = new IContextAttribute[2*retSize]; Array.Copy( retAttr, // srcArray 0, // srcIndex newAttr, // destArray 0, // destIndex retSize); // lengthToCopy retAttr = newAttr; retSize = retSize*2; } retAttr[numAttr-1] = attr; } } IContextAttribute[] ctxAttr = new IContextAttribute[numAttr]; Array.Copy(retAttr, ctxAttr, numAttr); return ctxAttr; } // This is called during RS.IsContextOK to check if the new XXX() is configured // to do a direct connect, and if it is we Connect to the URL and return // the proxy. In the second stage, when the constructor executes on the proxy // we will make sure (in Activate) that there are no CTOR args. [System.Security.SecurityCritical] // auto-generated internal static Object ConnectIfNecessary(IConstructionCallMessage ctorMsg) { // If the type being instantiated is configured for Connect // we would have added its URL as the connect key during // LocalActivator::IsContextOK // Look for the connect URL String objURL = (String) ctorMsg.Properties[ConnectKey]; Object proxy = null; if (objURL != null) { // Connect to the URL and return the proxy proxy = RemotingServices.Connect( ctorMsg.ActivationType, objURL); } // If the type is not setup for connecting we return null! return proxy; } // This is really used to distinguish between proxies for completely // within AppDomain activations and the ones from "Connect" during // the second stage (RS::Activate) // For the former, we have to run constructor etc and for the latter // we have to check that there is no non-defaul CTOR. [System.Security.SecurityCritical] // auto-generated internal static Object CheckIfConnected( RemotingProxy proxy, IConstructionCallMessage ctorMsg) { // If we performed a connect, we must have put the URL as // the connectKey in the message. String objURL = (String) ctorMsg.Properties[ConnectKey]; Object tp = null; if (objURL != null) { // We did perform a connect during IsContextOK // Just get the TP from RP and return it. tp = (Object)proxy.GetTransparentProxy(); } // We return null if we do not recognize this proxy! return tp; } internal static void PushActivationAttributes(Type serverType, Object[] attributes) { // There is one such object per thread if (_attributeStack == null) { _attributeStack = new ActivationAttributeStack(); } _attributeStack.Push(serverType, attributes); } internal static Object[] PeekActivationAttributes(Type serverType) { // We can get a peek w/o a prior Push (eg. activation starting // with NewObj) if (_attributeStack == null) { return null; } return _attributeStack.Peek(serverType); } internal static void PopActivationAttributes(Type serverType) { Contract.Assert(_attributeStack != null, "Pop w/o a prior Set()?"); _attributeStack.Pop(serverType); } } // class ActivationServices // This is the local activation helper and also the Attribute // that gets queried about every activation [System.Security.SecurityCritical] // auto-generated internal class LocalActivator: ContextAttribute, IActivator { internal LocalActivator() : base(ActivationServices.ActivationServiceURI) { } // --------------------------------------------------------------- // ContextAttribute functionality // --------------------------------------------------------------- // IContextAttribute::IsContextOK // This will check if a type is configured for remote activation ... // We return 'false' for IsContextOK if it is. [System.Security.SecurityCritical] public override bool IsContextOK( Context ctx, IConstructionCallMessage ctorMsg) { // If the app is not using config mechanism, we don't want // to intercept activation. if (RemotingConfigHandler.Info == null) { return true; } // check if this type is configured for connect // (instead of remote activate) RuntimeType activationType = ctorMsg.ActivationType as RuntimeType; if (activationType == null) throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType")); WellKnownClientTypeEntry wkte = RemotingConfigHandler.IsWellKnownClientType(activationType); String typeURL = (wkte == null ? null : wkte.ObjectUrl); if (typeURL != null) { // this type does have a direct uri, we will try to connect // to it during the activate call. Cache it in the message. ctorMsg.Properties[ActivationServices.ConnectKey] = typeURL; return false; } else { ActivatedClientTypeEntry acte = RemotingConfigHandler.IsRemotelyActivatedClientType(activationType); String appURL = null; if (acte == null) { // This is the case where the config file had no entry for this type. // We should check the callsite attributes for a URL Object[] callsiteAttributes = ctorMsg.CallSiteActivationAttributes; if(null != callsiteAttributes) { for(int i = 0; i < callsiteAttributes.Length; i++) { UrlAttribute attr = callsiteAttributes[i] as UrlAttribute; if(null != attr) { appURL = attr.UrlValue; } } } if(appURL == null) { // We don't really care about intercepting the activation in this case. return true; } } else { appURL = acte.ApplicationUrl; } // Generate the URL of the remote activator String activatorURL = null; if (!appURL.EndsWith("/", StringComparison.Ordinal)) activatorURL = appURL + "/" + ActivationServices.ActivationServiceURI; else activatorURL = appURL + ActivationServices.ActivationServiceURI; // Mark a flag for remote activation // (caching the url of the activation svc of the remote server) ctorMsg.Properties[ActivationServices.RemoteActivateKey] = activatorURL; return false; } } // IContextAttribute::GetPropertiesForNewContext [System.Security.SecurityCritical] public override void GetPropertiesForNewContext( IConstructionCallMessage ctorMsg) { BCLDebug.Log("ActivationSvc:GlobalAttrib::GetPropForNewCtx"); // This is called during RS::Activate .. when we are sure that // activation is at least x-context and this is a real activation // instead of a spoofed connect underneath the "new". Contract.Assert(ctorMsg!=null, "ctorMsg null?"); if (ctorMsg.Properties.Contains(ActivationServices.RemoteActivateKey)) { // Means we did want to intercept activation! String remActivatorURL = (String) ctorMsg.Properties[ActivationServices.RemoteActivateKey]; AppDomainLevelActivator activator = new AppDomainLevelActivator(remActivatorURL); // Chain ourselves at the end of the AppDomainLevel activators Contract.Assert( ctorMsg.Activator != null, "Should have at least x-context activator"); IActivator curr = ctorMsg.Activator; if (curr.Level < ActivatorLevel.AppDomain) { // Common case .. .only x-context activator(s) in chain activator.NextActivator = curr; ctorMsg.Activator = activator; } else if (curr.NextActivator == null) { // Only one activator but not ContextLevel ... // We go at the end of the chain curr.NextActivator = activator; } else { // We will have to walk the chain till the end of the last // AD activator and plug ourselves in. while (curr.NextActivator.Level >= ActivatorLevel.AppDomain) { curr = curr.NextActivator; } Contract.Assert( curr.NextActivator.Level.Equals(ActivatorLevel.Context), "bad ordering of activators!"); activator.NextActivator = curr.NextActivator; curr.NextActivator = activator; } } } // --------------------------------------------------------------- // IActivator functionality // ---------------------------------------------------------------- //IActivator::NextActivator public virtual IActivator NextActivator { // We are a singleton internal infrastructure object. [System.Security.SecurityCritical] get { return null; } // Don't allow a set either. [System.Security.SecurityCritical] set { throw new InvalidOperationException(); } } //IActivator::ActivatorLevel public virtual ActivatorLevel Level { [System.Security.SecurityCritical] get { return ActivatorLevel.AppDomain; } } private static MethodBase GetMethodBase(IConstructionCallMessage msg) { MethodBase mb = msg.MethodBase; if(null == mb) { BCLDebug.Trace("REMOTE", "Method missing w/name ", msg.MethodName); throw new RemotingException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Remoting_Message_MethodMissing"), msg.MethodName, msg.TypeName)); } return mb; } //IActivator::Activate [System.Security.SecurityCritical] [System.Runtime.InteropServices.ComVisible(true)] public virtual IConstructionReturnMessage Activate( IConstructionCallMessage ctorMsg) { // This is where the activation service hooks in to activation // requests. We get called as the activation message is recognized // by the ClientContextTerminatorSink & routed to us. // // NOTE: This gets called for both purely within appDomain activation // and 'real' remote activation scenarios as the request goes out of // the client context. // It also gets called as an incoming remote call is routed to the // local activator by the remote activator object. // BCLDebug.Log("Activation Services:: new Activate()"); if (ctorMsg == null) { throw new ArgumentNullException("ctorMsg"); } Contract.EndContractBlock(); // Check if we have marked this activation to go remote if (ctorMsg.Properties.Contains(ActivationServices.RemoteActivateKey)) { //DBG Console.WriteLine("Attempting remote activation!"); return DoRemoteActivation(ctorMsg); } else { // We must be in either a pure cross context activation or // a remote incoming activation request (in which case we // already checked the permission to create an instance of // this type). if (ctorMsg.Properties.Contains(ActivationServices.PermissionKey)) { Type activationType = ctorMsg.ActivationType; // We are on the server end of a real remote activation // Create a local attribute that contributes the context // properties requested by the remote request Object[] attr = null; if (activationType.IsContextful) { IList cp = ctorMsg.ContextProperties; if (cp != null && cp.Count > 0) { RemotePropertyHolderAttribute rph = new RemotePropertyHolderAttribute(cp); attr = new Object[1]; attr[0] = rph; } } MethodBase mb = GetMethodBase(ctorMsg); RemotingMethodCachedData methodCache = InternalRemotingServices.GetReflectionCachedData(mb); Object[] args = Message.CoerceArgs(ctorMsg, methodCache.Parameters); Object server = Activator.CreateInstance( activationType, args, attr); // check to see if we need to do redirection if (RemotingServices.IsClientProxy(server)) { // The wellknown type is remoted so we must wrap the proxy // with a local object. // The redirection proxy masquerades as an object of the appropriate // type, and forwards incoming messages to the actual proxy. RedirectionProxy redirectedProxy = new RedirectionProxy((MarshalByRefObject)server, activationType); RemotingServices.MarshalInternal(redirectedProxy, null, activationType); server = redirectedProxy; } return ActivationServices.SetupConstructionReply( server, ctorMsg, null); } else { BCLDebug.Log("Attempting X-Context activation!"); // delegate to the Activator in the message return ctorMsg.Activator.Activate(ctorMsg); } } } // This is called by the local activator during an outgoing activation // request. internal static IConstructionReturnMessage DoRemoteActivation( IConstructionCallMessage ctorMsg) { Contract.Assert(ctorMsg != null, "Null ctorMsg"); // < // < BCLDebug.Log("Attempting Connection to remote activation service"); IActivator remActivator = null; String remActivatorURL = (String) ctorMsg.Properties[ActivationServices.RemoteActivateKey]; try { remActivator = (IActivator) RemotingServices.Connect( typeof(System.Runtime.Remoting.Activation.IActivator), remActivatorURL); } catch (Exception e) { throw new RemotingException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Remoting_Activation_ConnectFailed"), e)); } // Remove the remote activate key as its purpose is served. ctorMsg.Properties.Remove(ActivationServices.RemoteActivateKey); // Delegate the work to the remote activator return remActivator.Activate(ctorMsg); } }// class LocalActivator // This is the object that listens to activation requests internal class ActivationListener:MarshalByRefObject, IActivator { // Override lifetime services to make this object live forever... [System.Security.SecurityCritical] // auto-generated public override Object InitializeLifetimeService() { return null; } //IActivator::NextActivator public virtual IActivator NextActivator { // We are a singleton internal infrastructure object. [System.Security.SecurityCritical] // auto-generated get { return null; } // Don't allow a set either. [System.Security.SecurityCritical] // auto-generated set { throw new InvalidOperationException();} } //IActivator::ActivatorLevel public virtual ActivatorLevel Level { [System.Security.SecurityCritical] // auto-generated get {return ActivatorLevel.AppDomain;} } //IActivator::Activate [System.Security.SecurityCritical] // auto-generated [System.Runtime.InteropServices.ComVisible(true)] public virtual IConstructionReturnMessage Activate( IConstructionCallMessage ctorMsg) { BCLDebug.Log("ActivationListener: received new activation request!"); if (ctorMsg == null || RemotingServices.IsTransparentProxy(ctorMsg)) { throw new ArgumentNullException("ctorMsg"); } Contract.EndContractBlock(); // Add the permission key which distinguishes pure-cross context activation from // a remote request (both of which go through DoCrossContextActivation) ctorMsg.Properties[ActivationServices.PermissionKey] = "allowed"; // Check to make sure that this activation type has been allowed. String activationTypeName = ctorMsg.ActivationTypeName; if (!RemotingConfigHandler.IsActivationAllowed(activationTypeName)) { throw new RemotingException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Remoting_Activation_PermissionDenied"), ctorMsg.ActivationTypeName)); } Type activationType = ctorMsg.ActivationType; if (activationType == null) { throw new RemotingException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_BadType"), ctorMsg.ActivationTypeName)); } // Delegate to the local activator for further work return ActivationServices.GetActivator().Activate(ctorMsg); } } // class ActivationListener // This is a lightweight object to help with the activation // at the appDomain level ... it delegates its work to // ActivationServices.LocalActivator ... which is a heavy // object we can't afford to carry around in the ActivatorChain // (since it may get Serialized/Deserialized) [Serializable] // attribute .. the latter shall be turned on during Beta-2! internal class AppDomainLevelActivator : IActivator { IActivator m_NextActivator; // Do we need this? String m_RemActivatorURL; internal AppDomainLevelActivator(String remActivatorURL) { Contract.Assert(remActivatorURL!=null,"Bad activator URL"); m_RemActivatorURL = remActivatorURL; } internal AppDomainLevelActivator(SerializationInfo info, StreamingContext context) { if (info==null) { throw new ArgumentNullException("info"); } Contract.EndContractBlock(); m_NextActivator = (IActivator) info.GetValue("m_NextActivator",typeof(IActivator)); } //IActivator::NextActivator public virtual IActivator NextActivator { [System.Security.SecurityCritical] // auto-generated get { return m_NextActivator; } [System.Security.SecurityCritical] // auto-generated set { m_NextActivator = value; } } //IActivator::ActivatorLevel public virtual ActivatorLevel Level { [System.Security.SecurityCritical] // auto-generated get { return ActivatorLevel.AppDomain; } } //IActivator::Activate [System.Security.SecurityCritical] // auto-generated [System.Runtime.InteropServices.ComVisible(true)] public virtual IConstructionReturnMessage Activate( IConstructionCallMessage ctorMsg) { // This function will get invoked when the ClientContextTerminator sink // notices that an activation request message is passed to it ... it // will route the message to the Activator present inside the ctorMsg // (which happens to be us in this case!) // remove ourselves from the Activator chain ctorMsg.Activator = m_NextActivator; return ActivationServices.GetActivator().Activate(ctorMsg); } } // This is a lightweight object to help with the activation // at the context level ... [Serializable] internal class ContextLevelActivator : IActivator { IActivator m_NextActivator; internal ContextLevelActivator() { m_NextActivator = null; } internal ContextLevelActivator(SerializationInfo info, StreamingContext context) { if (info==null) { throw new ArgumentNullException("info"); } Contract.EndContractBlock(); m_NextActivator = (IActivator) info.GetValue("m_NextActivator",typeof(IActivator)); } //IActivator::NextActivator public virtual IActivator NextActivator { [System.Security.SecurityCritical] // auto-generated get { return m_NextActivator; } [System.Security.SecurityCritical] // auto-generated set { m_NextActivator = value; } } //IActivator::ActivatorLevel public virtual ActivatorLevel Level { [System.Security.SecurityCritical] // auto-generated get { return ActivatorLevel.Context; } } //IActivator::Activate [System.Security.SecurityCritical] // auto-generated [System.Runtime.InteropServices.ComVisible(true)] public virtual IConstructionReturnMessage Activate( IConstructionCallMessage ctorMsg) { // remove ourselves from the Activator chain ctorMsg.Activator = ctorMsg.Activator.NextActivator; // Delegate to remoting services to do the hard work. // This will create a context, enter it, run through // the context sink chain & then delegate to the nex // activator inside the ctorMsg (quite likely to be // the default ConstructionLevelActivator) return ActivationServices.DoCrossContextActivation(ctorMsg); } } // This is a lightweight object to help with the activation // at the appDomain level ... it delegates its work to // ActivationServices.LocalActivator ... which is a heavy // object we can't afford to carry around in the ActivatorChain // (since it may get Serialized/Deserialized) [Serializable] internal class ConstructionLevelActivator : IActivator { internal ConstructionLevelActivator() { } //IActivator::NextActivator public virtual IActivator NextActivator { // The construction level activator is a terminating activator [System.Security.SecurityCritical] // auto-generated get { return null; } // Throw if someone attempts a set [System.Security.SecurityCritical] // auto-generated set { throw new InvalidOperationException(); } } //IActivator::ActivatorLevel public virtual ActivatorLevel Level { [System.Security.SecurityCritical] // auto-generated get { return ActivatorLevel.Construction; } } //IActivator::Activate [System.Security.SecurityCritical] // auto-generated [System.Runtime.InteropServices.ComVisible(true)] public virtual IConstructionReturnMessage Activate( IConstructionCallMessage ctorMsg) { // This function will get invoked when the ClientContextTerminator sink // notices that an activation request message is passed to it ... it // will route the message to the Activator present inside the ctorMsg // (which happens to be us in this case!) // remove ourselves from the Activator chain ctorMsg.Activator = ctorMsg.Activator.NextActivator; return ActivationServices.DoServerContextActivation(ctorMsg); } } // This acts as a pseudo call site attribute and transfers // the context properties carried in from a remote activation request // to the server side activation internal class RemotePropertyHolderAttribute : IContextAttribute { IList _cp; // incoming list of context properties internal RemotePropertyHolderAttribute(IList cp) { _cp = cp; Contract.Assert(cp != null && cp.Count > 0,"Bad _cp?"); } [System.Security.SecurityCritical] // auto-generated [System.Runtime.InteropServices.ComVisible(true)] public virtual bool IsContextOK(Context ctx, IConstructionCallMessage msg) { // The fact that we got instantiated means some remote activation // has contributed non-default context properties to the ctorMsg return false; } // properties are collected in order from callsite, wom & type // attributes ... so we get a first shot at adding properties [System.Security.SecurityCritical] // auto-generated [System.Runtime.InteropServices.ComVisible(true)] public virtual void GetPropertiesForNewContext(IConstructionCallMessage ctorMsg) { for (int i=0; i<_cp.Count; i++) { // Just cycle through the list and add the properties to // the construction message. // We will throw at a later stage if any of these do not // implement IContextProperty ctorMsg.ContextProperties.Add(_cp[i]); } } } // Note: One instance of this class is setup per thread that comes to // managed remoting for activation of MBR types. All access to methods // is by design single-threaded. (Each thread is working on its own object). // In the case of Activator.CreateInstance ... that API does the Push & // Remoting does a Pop() as soon as it has picked up the attributes from // the threadStatic. The CreateInstance API itself does a Pop() too in // a try-finally. (So this does not work very well if the infrastructure // creates an instance of the same MBR type as the outer type being created. // However, to minimize code churn this is the least risky fix we can do. // The full fix would be to pass activationAttributes into the VM through // reflection code and have the VM pass them over to remoting which will // then hand them over to managed remoting helpers. This will also involve // adding attributes as an additional parameter to // ProxyAttribute.CreateInstance() public method. internal class ActivationAttributeStack { Object[] activationTypes; Object[] activationAttributes; int freeIndex; internal ActivationAttributeStack() { activationTypes = new Object[4]; activationAttributes = new Object[4]; freeIndex = 0; } internal void Push(Type typ, Object[] attr) { Contract.Assert(typ!=null, "typ != null"); Contract.Assert(attr!=null, "attr != null"); if (freeIndex == activationTypes.Length) { // Need to grow our arrays ... this will be exceedingly rare Object[] newTypes = new Object[activationTypes.Length * 2]; Object[] newAttr = new Object[activationAttributes.Length * 2]; Contract.Assert(newAttr.Length == newTypes.Length,"These should be in [....]!"); Array.Copy(activationTypes, newTypes, activationTypes.Length); Array.Copy(activationAttributes, newAttr, activationAttributes.Length); activationTypes = newTypes; activationAttributes = newAttr; } activationTypes[freeIndex] = typ; activationAttributes[freeIndex] = attr; freeIndex++; } internal Object[] Peek(Type typ) { Contract.Assert(typ!=null, "typ != null"); if (freeIndex == 0 || activationTypes[freeIndex-1] != (object)typ) { return null; } return (Object[])activationAttributes[freeIndex-1]; } // Note: Read the comments above .. you can have 2 pops for the same // push. We also count on infrastructure code not activating // the same type as the caller causing a recursive activation. internal void Pop(Type typ) { Contract.Assert(typ!=null, "typ != null"); if (freeIndex != 0 && activationTypes[freeIndex-1] == (object)typ) { freeIndex--; // Clear the popped entry activationTypes[freeIndex] = null; activationAttributes[freeIndex] = null; } } } }//namespace // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ResourceReader.cs
- NamedPipeTransportSecurityElement.cs
- TextEditorMouse.cs
- DependencyPropertyDescriptor.cs
- ApplicationInfo.cs
- DataSourceCacheDurationConverter.cs
- AsymmetricAlgorithm.cs
- Range.cs
- ScriptResourceAttribute.cs
- IUnknownConstantAttribute.cs
- DataGridViewRowHeaderCell.cs
- EndpointBehaviorElementCollection.cs
- XhtmlBasicTextBoxAdapter.cs
- WebPartManager.cs
- EncoderExceptionFallback.cs
- DataGridViewRowErrorTextNeededEventArgs.cs
- QueryContinueDragEventArgs.cs
- ColumnResizeUndoUnit.cs
- PropVariant.cs
- FixedElement.cs
- EngineSite.cs
- PointKeyFrameCollection.cs
- DeclarativeCatalogPartDesigner.cs
- SharedPersonalizationStateInfo.cs
- ClipboardProcessor.cs
- QilChoice.cs
- DictionaryMarkupSerializer.cs
- WebRequestModulesSection.cs
- RTLAwareMessageBox.cs
- ValueType.cs
- ProfileGroupSettings.cs
- ReadOnlyTernaryTree.cs
- CharStorage.cs
- StoreConnection.cs
- X509ThumbprintKeyIdentifierClause.cs
- DataGridRowAutomationPeer.cs
- SQLUtility.cs
- LayoutTableCell.cs
- Shape.cs
- BinaryFormatterWriter.cs
- HttpCacheVary.cs
- FastEncoder.cs
- XMLUtil.cs
- TreeView.cs
- ValidatingReaderNodeData.cs
- NameSpaceEvent.cs
- TdsRecordBufferSetter.cs
- VectorAnimationUsingKeyFrames.cs
- BitmapEffectGroup.cs
- ResumeStoryboard.cs
- SourceChangedEventArgs.cs
- NativeObjectSecurity.cs
- SelfIssuedAuthProofToken.cs
- SecurityTokenValidationException.cs
- PrintDialog.cs
- EmbeddedMailObject.cs
- ToolStripStatusLabel.cs
- GlyphsSerializer.cs
- CodeExporter.cs
- ProcessMonitor.cs
- DataServiceKeyAttribute.cs
- GridItemCollection.cs
- ToolStrip.cs
- ThreadStartException.cs
- HostTimeoutsElement.cs
- TextDecoration.cs
- XmlParser.cs
- DataTableExtensions.cs
- FormViewPagerRow.cs
- HttpStreamMessage.cs
- ReferencedCollectionType.cs
- Win32Native.cs
- ForwardPositionQuery.cs
- DrawItemEvent.cs
- InstalledVoice.cs
- RouteUrlExpressionBuilder.cs
- PersistenceException.cs
- ControlsConfig.cs
- NameNode.cs
- CodeComment.cs
- SqlXml.cs
- __FastResourceComparer.cs
- KeyInfo.cs
- MessageQueueKey.cs
- EdmToObjectNamespaceMap.cs
- QilLiteral.cs
- Cursor.cs
- ContractNamespaceAttribute.cs
- WindowsListViewItem.cs
- AsymmetricAlgorithm.cs
- FrameDimension.cs
- WorkflowMarkupSerializationException.cs
- CreatingCookieEventArgs.cs
- TextBlock.cs
- BitmapFrame.cs
- BindingElementExtensionElement.cs
- ReachDocumentPageSerializerAsync.cs
- SqlDataSourceStatusEventArgs.cs
- Logging.cs
- CodeChecksumPragma.cs