Ejemplo n.º 1
0
        [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
            }
        }
Ejemplo n.º 2
0
        [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;
                }
            }
        }