[System.Security.SecurityCritical] // auto-generated void ReturnCallContextToThread(Thread currentThread, IMessage retMsg, int msgFlags, LogicalCallContext currCtx) { if (msgFlags == Message.Sync) { if (retMsg == null) return; IMethodReturnMessage mrm = retMsg as IMethodReturnMessage; if (mrm == null) return; LogicalCallContext retCtx = mrm.LogicalCallContext; if (retCtx == null) { currentThread.GetMutableExecutionContext().LogicalCallContext = currCtx; return; } if (!(mrm is StackBasedReturnMessage)) { ExecutionContext ec = currentThread.GetMutableExecutionContext(); LogicalCallContext oldCtx = ec.LogicalCallContext; ec.LogicalCallContext = retCtx; if ((Object)oldCtx != (Object)retCtx) { // If the new call context does not match the old call context, // we must have gone remote. We need to keep the preserve // the principal from the original call context. IPrincipal principal = oldCtx.Principal; if (principal != null) retCtx.Principal = principal; } } //for other types (async/one-way etc) there is nothing to be //done as we have just finished processing BeginInvoke or EndInvoke } }
[System.Security.SecurityCritical] // auto-generated private void PrivateInvoke(ref MessageData msgData, int type) { IMessage reqMsg = null; CallType callType = (CallType)type; IMessage retMsg = null; int msgFlags = -1; // Used only for Construction case RemotingProxy rp = null; // Create a message object based on the type of call if (CallType.MethodCall == callType) { Message msg = new Message(); msg.InitFields(msgData); reqMsg = msg; msgFlags = msg.GetCallType(); } else if (CallType.ConstructorCall == (CallType)callType) { // We use msgFlags to handle CallContext around // the virtual call to Invoke() msgFlags = Message.Sync; rp = this as RemotingProxy; ConstructorCallMessage ctorMsg = null; bool bIsWellKnown = false; if (!IsRemotingProxy()) { // Create a new constructor call message // < ctorMsg = new ConstructorCallMessage(null, null, null, (RuntimeType)GetProxiedType()); } else { // Extract the constructor message set in the first step of activation. ctorMsg = rp.ConstructorMessage; // If the proxy is a wellknown client proxy, we don't // need to run the c'tor. Identity id = rp.IdentityObject; if (id != null) { bIsWellKnown = id.IsWellKnown(); } } if ((null == ctorMsg) || bIsWellKnown) { // This is also used to short-circuit the activation path // when we have a well known proxy that has already been // initialized (there's a race condition if we don't do this). // // This is a special case, where we have a remoting proxy // but the constructormessage hasn't been setup. // so let us just bail out.. // this is currently used by ServicedComponent's for cross appdomain // pooling: <EMAIL>[....]</EMAIL> // ctorMsg = new ConstructorCallMessage(null, null, null, (RuntimeType)GetProxiedType()); // Set the constructor frame info in the CCM ctorMsg.SetFrame(msgData); reqMsg = ctorMsg; // If this was the default ctor, check that default .ctor was called. if (bIsWellKnown) { Contract.Assert(rp != null, "RemotingProxy expected here!"); // Clear any cached ctorMsg on the RemotingProxy rp.ConstructorMessage = null; // We did execute a Connect. Throw if the client // code is also trying to use a non-default constructor at // the same time. if (ctorMsg.ArgCount != 0) { throw new RemotingException( Environment.GetResourceString( "Remoting_Activation_WellKnownCTOR")); } } // Create a constructor return message retMsg = new ConstructorReturnMessage((MarshalByRefObject)GetTransparentProxy(), null, 0, null, ctorMsg); } else { // Set the constructor frame info in the CCM ctorMsg.SetFrame(msgData); reqMsg = ctorMsg; } } else { Contract.Assert(false, "Unknown call type"); } // Make sure that outgoing remote calls are counted. ChannelServices.IncrementRemoteCalls(); // For non-remoting proxies, EndAsync should not call Invoke() // because the proxy cannot support Async and the call has already // finished executing in BeginAsync if (!IsRemotingProxy() && ((msgFlags & Message.EndAsync) == Message.EndAsync)) { Message msg = reqMsg as Message; retMsg = EndInvokeHelper(msg, true); Contract.Assert(null != retMsg, "null != retMsg"); } // Invoke Contract.Assert(null != reqMsg, "null != reqMsg"); if (null == retMsg) { // NOTE: there are cases where we setup a return message // and we don't want the activation call to go through // refer to the note above for ServicedComponents and Cross Appdomain // pooling LogicalCallContext cctx = null; Thread currentThread = Thread.CurrentThread; // Pick up or clone the call context from the thread // and install it in the reqMsg as appropriate cctx = currentThread.GetMutableExecutionContext().LogicalCallContext; SetCallContextInMessage(reqMsg, msgFlags, cctx); // Add the outgoing "Header"'s to the message. cctx.PropagateOutgoingHeadersToMessage(reqMsg); retMsg = Invoke(reqMsg); // Get the call context returned and set it on the thread ReturnCallContextToThread(currentThread, retMsg, msgFlags, cctx); // Pull response "Header"'s out of the message Thread.CurrentThread.GetMutableExecutionContext().LogicalCallContext.PropagateIncomingHeadersToCallContext(retMsg); } if (!IsRemotingProxy() && ((msgFlags & Message.BeginAsync) == Message.BeginAsync)) { // This was a begin-async on a non-Remoting Proxy. For V-1 they // cannot support Async and end up doing a [....] call. We need // to fill up here to make the call look like async to // the caller. // Create the async result to return Message msg = reqMsg as Message; AsyncResult ar = new AsyncResult(msg); // Tell the async result that the call has actually completed // so it can hold on to the return message. ar.SyncProcessMessage(retMsg); // create a returnMessage to propagate just the asyncResult back // to the caller's stack. retMsg = new ReturnMessage(ar, null, 0, null /*cctx*/, msg); } // Propagate out parameters HandleReturnMessage(reqMsg, retMsg); // For constructor calls do some extra bookkeeping if (CallType.ConstructorCall == callType) { // NOTE: It is the responsiblity of the callee to propagate // the out parameters // Everything went well, we are ready to return // a proxy to the caller // Extract the return value MarshalByRefObject retObj = null; IConstructionReturnMessage ctorRetMsg = retMsg as IConstructionReturnMessage; if (null == ctorRetMsg) { throw new RemotingException( Environment.GetResourceString("Remoting_Proxy_BadReturnTypeForActivation")); } ConstructorReturnMessage crm = ctorRetMsg as ConstructorReturnMessage; if (null != crm) { // If return message is of type ConstructorReturnMessage // this is an in-appDomain activation. So no unmarshaling // needed. retObj = (MarshalByRefObject)crm.GetObject(); if (retObj == null) { throw new RemotingException( Environment.GetResourceString("Remoting_Activation_NullReturnValue")); } } else { // Fetch the objRef out of the returned message and unmarshal it retObj = (MarshalByRefObject)RemotingServices.InternalUnmarshal( (ObjRef)ctorRetMsg.ReturnValue, GetTransparentProxy(), true /*fRefine*/); if (retObj == null) { throw new RemotingException( Environment.GetResourceString("Remoting_Activation_NullFromInternalUnmarshal")); } } if (retObj != (MarshalByRefObject)GetTransparentProxy()) { throw new RemotingException( Environment.GetResourceString( "Remoting_Activation_InconsistentState")); } if (IsRemotingProxy()) { // Clear any cached ctorMsg on the RemotingProxy rp.ConstructorMessage = null; } } }