2 // System.Runtime.Remoting.Proxies.RealProxy.cs
5 // Dietmar Maurer (dietmar@ximian.com)
6 // Lluis Sanchez (lsg@ctv.es)
9 // (C) 2001 Ximian, Inc. http://www.ximian.com
13 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
15 // Permission is hereby granted, free of charge, to any person obtaining
16 // a copy of this software and associated documentation files (the
17 // "Software"), to deal in the Software without restriction, including
18 // without limitation the rights to use, copy, modify, merge, publish,
19 // distribute, sublicense, and/or sell copies of the Software, and to
20 // permit persons to whom the Software is furnished to do so, subject to
21 // the following conditions:
23 // The above copyright notice and this permission notice shall be
24 // included in all copies or substantial portions of the Software.
26 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
31 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36 using System
.Reflection
;
37 using System
.Runtime
.Remoting
;
38 using System
.Runtime
.Remoting
.Messaging
;
39 using System
.Runtime
.Remoting
.Activation
;
40 using System
.Runtime
.Remoting
.Contexts
;
41 using System
.Runtime
.CompilerServices
;
42 using System
.Runtime
.Serialization
;
43 using System
.Runtime
.InteropServices
;
45 namespace System
.Runtime
.Remoting
.Proxies
47 #pragma warning disable 169, 649
48 internal class TransparentProxy
{
51 bool _custom_type_info
;
53 #pragma warning restore 169, 649
56 public abstract class RealProxy
{
57 // other classes visible to the runtime
58 // derive from this class so keep these locals
59 // in sync with the definition RealProxy
60 // in object-internals.h
62 #pragma warning disable 169, 414
63 #region Sync with object-internals.h
65 internal Context _targetContext
;
66 MarshalByRefObject _server
;
67 int _targetDomainId
= -1;
68 internal string _targetUri
;
69 internal Identity _objectIdentity
;
73 #pragma warning restore 169, 414
75 protected RealProxy ()
79 protected RealProxy (Type classToProxy
) : this(classToProxy
, IntPtr
.Zero
, null)
83 internal RealProxy (Type classToProxy
, ClientIdentity identity
) : this(classToProxy
, IntPtr
.Zero
, null)
85 _objectIdentity
= identity
;
88 protected RealProxy (Type classToProxy
, IntPtr stub
, object stubData
)
90 if (!classToProxy
.IsMarshalByRef
&& !classToProxy
.IsInterface
)
91 throw new ArgumentException("object must be MarshalByRef");
93 this.class_to_proxy
= classToProxy
;
95 if (stub
!= IntPtr
.Zero
)
96 throw new NotSupportedException ("stub is not used in Mono");
99 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
100 extern static Type
InternalGetProxyType (object transparentProxy
);
102 public Type
GetProxiedType()
104 if (_objTP
== null) {
105 if (class_to_proxy
.IsInterface
) return typeof(MarshalByRefObject
);
106 else return class_to_proxy
;
108 return InternalGetProxyType (_objTP
);
111 public virtual ObjRef
CreateObjRef (Type requestedType
)
113 return RemotingServices
.Marshal ((MarshalByRefObject
) GetTransparentProxy(), null, requestedType
);
116 public virtual void GetObjectData (SerializationInfo info
, StreamingContext context
)
118 Object obj
= GetTransparentProxy();
119 RemotingServices
.GetObjectData (obj
, info
, context
);
122 internal Identity ObjectIdentity
124 get { return _objectIdentity; }
125 set { _objectIdentity = value; }
129 public virtual IntPtr
GetCOMIUnknown (bool fIsMarshalled
)
131 throw new NotImplementedException ();
135 public virtual void SetCOMIUnknown (IntPtr i
)
137 throw new NotImplementedException ();
141 public virtual IntPtr
SupportsInterface (ref Guid iid
)
143 throw new NotImplementedException ();
146 public static object GetStubData (RealProxy rp
)
151 public static void SetStubData (RealProxy rp
, object stubData
)
153 rp
._stubData
= stubData
;
156 public abstract IMessage
Invoke (IMessage msg
);
158 /* this is called from unmanaged code */
159 internal static object PrivateInvoke (RealProxy rp
, IMessage msg
, out Exception exc
,
160 out object [] out_args
)
162 MonoMethodMessage mMsg
= (MonoMethodMessage
) msg
;
163 mMsg
.LogicalCallContext
= CallContext
.CreateLogicalCallContext (true);
164 CallType call_type
= mMsg
.CallType
;
165 bool is_remproxy
= (rp
is RemotingProxy
);
168 IMethodReturnMessage res_msg
= null;
170 if (call_type
== CallType
.BeginInvoke
)
171 // todo: set CallMessage in runtime instead
172 mMsg
.AsyncResult
.CallMessage
= mMsg
;
174 if (call_type
== CallType
.EndInvoke
)
175 res_msg
= (IMethodReturnMessage
)mMsg
.AsyncResult
.EndInvoke ();
177 // Check for constructor msg
178 if (mMsg
.MethodBase
.IsConstructor
)
181 res_msg
= (IMethodReturnMessage
) (rp
as RemotingProxy
).ActivateRemoteObject ((IMethodMessage
) msg
);
183 msg
= new ConstructionCall (rp
.GetProxiedType ());
191 res_msg
= (IMethodReturnMessage
)rp
.Invoke (msg
);
192 } catch (Exception ex
) {
194 if (call_type
== CallType
.BeginInvoke
) {
195 // If async dispatch crashes, don't propagate the exception.
196 // The exception will be raised when calling EndInvoke.
197 mMsg
.AsyncResult
.SyncProcessMessage (new ReturnMessage (ex
, msg
as IMethodCallMessage
));
198 res_msg
= new ReturnMessage (null, null, 0, null, msg
as IMethodCallMessage
);
203 // Note, from begining this code used AsyncResult.IsCompleted for
204 // checking if it was a remoting or custom proxy, but in some
205 // cases the remoting proxy finish before the call returns
206 // causing this method to be called, therefore causing all kind of bugs.
207 if ((!is_remproxy
) && call_type
== CallType
.BeginInvoke
&& !failed
)
209 IMessage asyncMsg
= null;
211 // allow calltype EndInvoke to finish
212 asyncMsg
= mMsg
.AsyncResult
.SyncProcessMessage (res_msg
as IMessage
);
213 out_args
= res_msg
.OutArgs
;
214 res_msg
= new ReturnMessage (asyncMsg
, null, 0, null, res_msg
as IMethodCallMessage
);
218 if (res_msg
.LogicalCallContext
!= null && res_msg
.LogicalCallContext
.HasInfo
)
219 CallContext
.UpdateCurrentCallContext (res_msg
.LogicalCallContext
);
221 exc
= res_msg
.Exception
;
223 // todo: remove throw exception from the runtime invoke
226 throw exc
.FixRemotingException();
228 else if (res_msg
is IConstructionReturnMessage
) {
229 if (out_args
== null)
230 out_args
= res_msg
.OutArgs
;
232 else if (mMsg
.CallType
== CallType
.BeginInvoke
) {
233 // We don't have OutArgs in this case.
235 else if (mMsg
.CallType
== CallType
.Sync
) {
236 out_args
= ProcessResponse (res_msg
, mMsg
);
238 else if (mMsg
.CallType
== CallType
.EndInvoke
) {
239 out_args
= ProcessResponse (res_msg
, mMsg
.AsyncResult
.CallMessage
);
242 if (out_args
== null)
243 out_args
= res_msg
.OutArgs
;
246 return res_msg
.ReturnValue
;
249 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
250 internal extern virtual object InternalGetTransparentProxy (string className
);
252 public virtual object GetTransparentProxy ()
257 IRemotingTypeInfo rti
= this as IRemotingTypeInfo
;
261 if (name
== null || name
== typeof(MarshalByRefObject
).AssemblyQualifiedName
)
262 name
= class_to_proxy
.AssemblyQualifiedName
;
265 name
= class_to_proxy
.AssemblyQualifiedName
;
267 _objTP
= InternalGetTransparentProxy (name
);
274 public IConstructionReturnMessage
InitializeServerObject(IConstructionCallMessage ctorMsg
)
276 throw new NotImplementedException();
279 protected void AttachServer(MarshalByRefObject s
)
284 protected MarshalByRefObject
DetachServer()
286 MarshalByRefObject ob
= _server
;
291 protected MarshalByRefObject
GetUnwrappedServer()
296 internal void SetTargetDomain (int domainId
)
298 _targetDomainId
= domainId
;
301 // Called by the runtime
302 internal object GetAppDomainTarget ()
304 if (_server
== null) {
305 ClientActivatedIdentity identity
= RemotingServices
.GetIdentityForUri (_targetUri
) as ClientActivatedIdentity
;
306 if (identity
== null) throw new RemotingException ("Server for uri '" + _targetUri
+ "' not found");
307 _server
= identity
.GetServerObject ();
312 static object[] ProcessResponse (IMethodReturnMessage mrm
, MonoMethodMessage call
)
316 MethodInfo mi
= (MethodInfo
) call
.MethodBase
;
317 if (mrm
.ReturnValue
!= null && !mi
.ReturnType
.IsInstanceOfType (mrm
.ReturnValue
))
318 throw new InvalidCastException ("Return value has an invalid type");
320 // Check out parameters
325 if (call
.NeedsOutProcessing (out no
))
327 ParameterInfo
[] parameters
= mi
.GetParameters();
328 object[] outArgs
= new object [no
];
331 foreach (ParameterInfo par
in parameters
)
333 if (par
.IsOut
&& !par
.ParameterType
.IsByRef
)
335 // Special marshalling required
336 object outArg
= par
.Position
< mrm
.ArgCount
? mrm
.GetArg (par
.Position
) : null;
337 if (outArg
!= null) {
338 object local
= call
.GetArg (par
.Position
);
339 if (local
== null) throw new RemotingException ("Unexpected null value in local out parameter '" + par
.Name
+ "'");
340 RemotingServices
.UpdateOutArgObject (par
, local
, outArg
);
343 else if (par
.ParameterType
.IsByRef
)
345 object outArg
= par
.Position
< mrm
.ArgCount
? mrm
.GetArg (par
.Position
) : null;
346 if (outArg
!= null && !par
.ParameterType
.GetElementType ().IsInstanceOfType (outArg
))
348 throw new InvalidCastException ("Return argument '" + par
.Name
+ "' has an invalid type");
350 outArgs
[narg
++] = outArg
;
356 return new object [0];