2004-02-13 Sebastien Pouliot <sebastien@ximian.com>
[mono.git] / mcs / class / corlib / System.Runtime.Remoting.Proxies / RealProxy.cs
index 31ac3798a62044459aa8d73a5aaa28abf0e3f954..84eb8823ca95a62f6ad5a4d43f4b81478d037b62 100644 (file)
 //
 
 using System;
+using System.Reflection;
 using System.Runtime.Remoting;
 using System.Runtime.Remoting.Messaging;
+using System.Runtime.Remoting.Activation;
+using System.Runtime.Remoting.Contexts;
 using System.Runtime.CompilerServices;
 using System.Runtime.Serialization;
 
@@ -21,13 +24,17 @@ namespace System.Runtime.Remoting.Proxies
        internal class TransparentProxy {
                public RealProxy _rp;
                IntPtr _class;
+               bool _custom_type_info;
        }
        
        public abstract class RealProxy {
 
                Type class_to_proxy;
+               internal Context _targetContext;
+               MarshalByRefObject _server;
                internal Identity _objectIdentity;
                Object _objTP;
+               object _stubData;
 
                protected RealProxy ()
                {
@@ -54,14 +61,15 @@ namespace System.Runtime.Remoting.Proxies
                        _objTP = InternalGetTransparentProxy();
                }
 
-               public virtual Type GetProxiedType() 
+               public Type GetProxiedType() 
                {
-                       return class_to_proxy;
+                       if (class_to_proxy.IsInterface) return typeof (MarshalByRefObject);
+                       else return class_to_proxy;
                }
 
                public virtual ObjRef CreateObjRef (Type requestedType)
                {
-                       return _objectIdentity.CreateObjRef (requestedType);
+                       return RemotingServices.Marshal ((MarshalByRefObject) GetTransparentProxy(), null, requestedType);
                }
 
                public virtual void GetObjectData (SerializationInfo info, StreamingContext context)
@@ -73,6 +81,35 @@ namespace System.Runtime.Remoting.Proxies
                internal Identity ObjectIdentity
                {
                        get { return _objectIdentity; }
+                       set { _objectIdentity = value; }
+               }
+               
+               [MonoTODO]
+               public virtual IntPtr GetCOMIUnknown (bool fIsMarshalled)
+               {
+                       throw new NotImplementedException ();
+               }
+               
+               [MonoTODO]
+               public virtual void SetCOMIUnknown (IntPtr i)
+               {
+                       throw new NotImplementedException ();
+               }
+               
+               [MonoTODO]
+               public virtual IntPtr SupportsInterface (ref Guid iid)
+               {
+                       throw new NotImplementedException ();
+               }
+               
+               public static object GetStubData (RealProxy rp)
+               {
+                       return rp._stubData;
+               }
+               
+               public static void SetStubData (RealProxy rp, object stubData)
+               {
+                       rp._stubData = stubData;
                }
 
                public abstract IMessage Invoke (IMessage msg);
@@ -81,24 +118,119 @@ namespace System.Runtime.Remoting.Proxies
                internal static object PrivateInvoke (RealProxy rp, IMessage msg, out Exception exc,
                                                      out object [] out_args)
                {
+                       MonoMethodMessage mMsg = (MonoMethodMessage) msg;
+                       mMsg.LogicalCallContext = CallContext.CreateLogicalCallContext();
+                       
+                       if (mMsg.CallType == CallType.BeginInvoke) 
+                               mMsg.AsyncResult.CallMessage = mMsg;    // TODO: do this in the runtime
+
                        IMethodReturnMessage res_msg = (IMethodReturnMessage)rp.Invoke (msg);
 
+                       if (res_msg.LogicalCallContext != null && res_msg.LogicalCallContext.HasInfo)
+                               CallContext.UpdateCurrentCallContext (res_msg.LogicalCallContext);
+
                        exc = res_msg.Exception;
-                       out_args = res_msg.OutArgs;
 
                        // todo: remove throw exception from the runtime invoke
-                       if (null != exc) 
+                       if (null != exc) {
+                               out_args = null;
                                throw exc.FixRemotingException();
+                       }
+                       else if (res_msg is IConstructionReturnMessage || mMsg.CallType == CallType.BeginInvoke) {
+                               out_args = res_msg.OutArgs;
+                       }
+                       else if (mMsg.CallType == CallType.Sync) {
+                               out_args = ProcessResponse (res_msg, mMsg);
+                       }
+                       else if (mMsg.CallType == CallType.EndInvoke) {
+                               out_args = ProcessResponse (res_msg, mMsg.AsyncResult.CallMessage);
+                       }
+                       else {
+                               out_args = res_msg.OutArgs;
+                       }
 
                        return res_msg.ReturnValue;
                }
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               public extern virtual object InternalGetTransparentProxy ();
+               internal extern virtual object InternalGetTransparentProxy ();
 
                public virtual object GetTransparentProxy () 
                {
                        return _objTP;
                }
+
+               [MonoTODO]
+               public IConstructionReturnMessage InitializeServerObject(IConstructionCallMessage ctorMsg)
+               {
+                       throw new NotImplementedException();
+               }
+
+               protected void AttachServer(MarshalByRefObject s)
+               {
+                       _server = s;
+               }
+
+               protected MarshalByRefObject DetachServer()
+               {
+                       MarshalByRefObject ob = _server;
+                       _server = null;
+                       return ob;
+               }
+
+               protected MarshalByRefObject GetUnwrappedServer()
+               {
+                       return _server;
+               }
+
+               static object[] ProcessResponse (IMethodReturnMessage mrm, IMethodCallMessage call)
+               {
+                       // Check return type
+
+                       MethodInfo mi = (MethodInfo) call.MethodBase;
+                       if (mrm.ReturnValue != null && !mi.ReturnType.IsInstanceOfType (mrm.ReturnValue))
+                               throw new RemotingException ("Return value has an invalid type");
+
+                       // Check out parameters
+
+                       if (mrm.OutArgCount > 0)
+                       {
+                               ParameterInfo[] parameters = mi.GetParameters();
+                               int no = 0;
+                               foreach (ParameterInfo par in parameters)
+                                       if (par.ParameterType.IsByRef) no++;
+                               
+                               object[] outArgs = new object [no];
+                               int narg = 0;
+                               int nout = 0;
+       
+                               foreach (ParameterInfo par in parameters)
+                               {
+                                       if (par.IsOut && !par.ParameterType.IsByRef)
+                                       {
+                                               // Special marshalling required
+                                               
+                                               object outArg = mrm.GetOutArg (nout++);
+                                               if (outArg != null) {
+                                                       object local = call.GetArg (par.Position);
+                                                       if (local == null) throw new RemotingException ("Unexpected null value in local out parameter '" + par.Position + " " + par.Name + "'");
+                                                       RemotingServices.UpdateOutArgObject (par, local, outArg);
+                                               }
+                                       }
+                                       else if (par.ParameterType.IsByRef)
+                                       {
+                                               object outArg = mrm.GetOutArg (nout++);
+                                               if (outArg != null && !par.ParameterType.IsInstanceOfType (outArg))
+                                               {
+                                                       throw new RemotingException ("Return argument '" + par.Name + "' has an invalid type");
+                                               }
+                                               outArgs [narg++] = outArg;
+                                       }
+                               }
+                               return outArgs;
+                       }
+                       else
+                               return new object [0];
+               }
        }
 }