The Labs \ Source Viewer \ SSCLI \ System.Runtime.Remoting.Messaging \ RemotingSurrogate

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. namespace System.Runtime.Remoting.Messaging
  16. {
  17.    
  18.     using System;
  19.     using System.Runtime.InteropServices;
  20.     using System.Runtime.Remoting;
  21.     using System.Runtime.Remoting.Metadata;
  22.     using System.Runtime.Remoting.Activation;
  23.     using System.Runtime.Remoting.Proxies;
  24.     using System.Runtime.Serialization;
  25.     using System.Runtime.Serialization.Formatters;
  26.     using System.Text;
  27.     using System.Reflection;
  28.     using System.Threading;
  29.     using System.Globalization;
  30.     using System.Collections;
  31.     using System.Security.Permissions;
  32.     [System.Runtime.InteropServices.ComVisible(true)]
  33.     public delegate bool MessageSurrogateFilter(string key, object value);
  34.    
  35.     [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  36.     [SecurityPermissionAttribute(SecurityAction.InheritanceDemand, Flags = SecurityPermissionFlag.Infrastructure)]
  37.     [System.Runtime.InteropServices.ComVisible(true)]
  38.     public class RemotingSurrogateSelector : ISurrogateSelector
  39.     {
  40.         // Private static data
  41.         private static Type s_IMethodCallMessageType = typeof(IMethodCallMessage);
  42.         private static Type s_IMethodReturnMessageType = typeof(IMethodReturnMessage);
  43.         private static Type s_ObjRefType = typeof(ObjRef);
  44.        
  45.         // Private member data
  46.         private object _rootObj = null;
  47.         private ISurrogateSelector _next = null;
  48.         private RemotingSurrogate _remotingSurrogate = new RemotingSurrogate();
  49.         private ObjRefSurrogate _objRefSurrogate = new ObjRefSurrogate();
  50.         private ISerializationSurrogate _messageSurrogate = null;
  51.         private MessageSurrogateFilter _filter = null;
  52.        
  53.        
  54.         public RemotingSurrogateSelector()
  55.         {
  56.             _messageSurrogate = new MessageSurrogate(this);
  57.         }
  58.        
  59.         public MessageSurrogateFilter Filter {
  60.             get { return _filter; }
  61.             set { _filter = value; }
  62.         }
  63.        
  64.         public void SetRootObject(object obj)
  65.         {
  66.             if (obj == null) {
  67.                 throw new ArgumentNullException("obj");
  68.             }
  69.             _rootObj = obj;
  70.             SoapMessageSurrogate soapMsg = _messageSurrogate as SoapMessageSurrogate;
  71.             if (null != soapMsg) {
  72.                 soapMsg.SetRootObject(_rootObj);
  73.             }
  74.         }
  75.        
  76.         public object GetRootObject()
  77.         {
  78.             return _rootObj;
  79.         }
  80.        
  81.         // Specifies the next ISurrogateSelector to be examined for surrogates if the current
  82.         // instance doesn't have a surrogate for the given type and assembly in the given context.
  83.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
  84.         public virtual void ChainSelector(ISurrogateSelector selector)
  85.         {
  86.             _next = selector;
  87.         }
  88.        
  89.         // Returns the appropriate surrogate for the given type in the given context.
  90.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
  91.         public virtual ISerializationSurrogate GetSurrogate(Type type, StreamingContext context, out ISurrogateSelector ssout)
  92.         {
  93.             if (type == null) {
  94.                 throw new ArgumentNullException("type");
  95.             }
  96.            
  97.             Message.DebugOut("Entered GetSurrogate for " + type.FullName + "\n");
  98.            
  99.             if (type.IsMarshalByRef) {
  100.                 Message.DebugOut("Selected surrogate for " + type.FullName);
  101.                 ssout = this;
  102.                 return _remotingSurrogate;
  103.             }
  104.             else if (s_IMethodCallMessageType.IsAssignableFrom(type) || s_IMethodReturnMessageType.IsAssignableFrom(type)) {
  105.                 ssout = this;
  106.                 return _messageSurrogate;
  107.             }
  108.             else if (s_ObjRefType.IsAssignableFrom(type)) {
  109.                 ssout = this;
  110.                 return _objRefSurrogate;
  111.             }
  112.             else if (_next != null) {
  113.                 return _next.GetSurrogate(type, context, out ssout);
  114.             }
  115.             else {
  116.                 ssout = null;
  117.                 return null;
  118.             }
  119.            
  120.         }
  121.         // GetSurrogate
  122.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
  123.         public virtual ISurrogateSelector GetNextSelector()
  124.         {
  125.             return _next;
  126.         }
  127.        
  128.         public virtual void UseSoapFormat()
  129.         {
  130.             _messageSurrogate = new SoapMessageSurrogate(this);
  131.             ((SoapMessageSurrogate)_messageSurrogate).SetRootObject(_rootObj);
  132.         }
  133.     }
  134.    
  135.     internal class RemotingSurrogate : ISerializationSurrogate
  136.     {
  137.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
  138.         public virtual void GetObjectData(object obj, SerializationInfo info, StreamingContext context)
  139.         {
  140.             if (obj == null) {
  141.                 throw new ArgumentNullException("obj");
  142.             }
  143.            
  144.             if (info == null) {
  145.                 throw new ArgumentNullException("info");
  146.             }
  147.            
  148.             //
  149.             // This code is to special case marshalling types inheriting from RemotingClientProxy
  150.             // Check whether type inherits from RemotingClientProxy and serialize the correct ObjRef
  151.             // after getting the correct proxy to the actual server object
  152.             //
  153.            
  154.             Message.DebugOut("RemotingSurrogate::GetObjectData obj.Type: " + obj.GetType().FullName + " \n");
  155.             if (RemotingServices.IsTransparentProxy(obj)) {
  156.                 RealProxy rp = RemotingServices.GetRealProxy(obj);
  157.                 rp.GetObjectData(info, context);
  158.             }
  159.             else {
  160.                 RemotingServices.GetObjectData(obj, info, context);
  161.             }
  162.         }
  163.        
  164.        
  165.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
  166.         public virtual object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)
  167.         {
  168.             throw new NotSupportedException(Environment.GetResourceString("NotSupported_PopulateData"));
  169.         }
  170.        
  171.     }
  172.     // class RemotingSurrogate
  173.    
  174.     internal class ObjRefSurrogate : ISerializationSurrogate
  175.     {
  176.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
  177.         public virtual void GetObjectData(object obj, SerializationInfo info, StreamingContext context)
  178.         {
  179.             if (obj == null) {
  180.                 throw new ArgumentNullException("obj");
  181.             }
  182.            
  183.             if (info == null) {
  184.                 throw new ArgumentNullException("info");
  185.             }
  186.            
  187.             //
  188.             // This code is to provide special handling for ObjRef's that are supposed
  189.             // to be passed as parameters.
  190.             //
  191.            
  192.             ((ObjRef)obj).GetObjectData(info, context);
  193.             // add flag indicating the ObjRef was passed as a parameter
  194.             info.AddValue("fIsMarshalled", 0);
  195.         }
  196.         // GetObjectData
  197.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
  198.         public virtual object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)
  199.         {
  200.             throw new NotSupportedException(Environment.GetResourceString("NotSupported_PopulateData"));
  201.         }
  202.        
  203.     }
  204.     // class ObjRefSurrogate
  205.    
  206.     internal class SoapMessageSurrogate : ISerializationSurrogate
  207.     {
  208.         // Private static data
  209.         private static Type _voidType = typeof(void);
  210.         private static Type _soapFaultType = typeof(SoapFault);
  211.        
  212.         // Member data
  213.         string DefaultFakeRecordAssemblyName = "http://schemas.microsoft.com/urt/SystemRemotingSoapTopRecord";
  214.         object _rootObj = null;
  215.         RemotingSurrogateSelector _ss;
  216.        
  217.         internal SoapMessageSurrogate(RemotingSurrogateSelector ss)
  218.         {
  219.             _ss = ss;
  220.         }
  221.        
  222.         internal void SetRootObject(object obj)
  223.         {
  224.             _rootObj = obj;
  225.         }
  226.        
  227.         internal virtual string[] GetInArgNames(IMethodCallMessage m, int c)
  228.         {
  229.             string[] names = new string[c];
  230.             for (int i = 0; i < c; i++) {
  231.                 string name = m.GetInArgName(i);
  232.                 if (name == null) {
  233.                     name = "__param" + i;
  234.                 }
  235.                 names[i] = name;
  236.             }
  237.             return names;
  238.         }
  239.        
  240.         internal virtual string[] GetNames(IMethodCallMessage m, int c)
  241.         {
  242.             string[] names = new string[c];
  243.             for (int i = 0; i < c; i++) {
  244.                 string name = m.GetArgName(i);
  245.                 if (name == null) {
  246.                     name = "__param" + i;
  247.                 }
  248.                 names[i] = name;
  249.             }
  250.             return names;
  251.         }
  252.        
  253.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
  254.         public virtual void GetObjectData(object obj, SerializationInfo info, StreamingContext context)
  255.         {
  256.             if (info == null) {
  257.                 throw new ArgumentNullException("info");
  258.             }
  259.            
  260.             if ((obj != null) && (obj != _rootObj)) {
  261.                 (new MessageSurrogate(_ss)).GetObjectData(obj, info, context);
  262.             }
  263.             else {
  264.                 IMethodReturnMessage msg = obj as IMethodReturnMessage;
  265.                 if (null != msg) {
  266.                    
  267.                     if (msg.Exception == null) {
  268.                         string responseElementName;
  269.                         string responseElementNS;
  270.                         string returnElementName;
  271.                        
  272.                         // obtain response element name namespace
  273.                         MethodBase mb = msg.MethodBase;
  274.                         SoapMethodAttribute attr = (SoapMethodAttribute)InternalRemotingServices.GetCachedSoapAttribute(mb);
  275.                         responseElementName = attr.ResponseXmlElementName;
  276.                         responseElementNS = attr.ResponseXmlNamespace;
  277.                         returnElementName = attr.ReturnXmlElementName;
  278.                        
  279.                             /*fOut*/                        ArgMapper mapper = new ArgMapper(msg, true);
  280.                         object[] args = mapper.Args;
  281.                         info.FullTypeName = responseElementName;
  282.                         info.AssemblyName = responseElementNS;
  283.                         Type retType = ((MethodInfo)mb).ReturnType;
  284.                         if (!((retType == null) || (retType == _voidType))) {
  285.                             info.AddValue(returnElementName, msg.ReturnValue, retType);
  286.                         }
  287.                         if (args != null) {
  288.                             Type[] types = mapper.ArgTypes;
  289.                             for (int i = 0; i < args.Length; i++) {
  290.                                 string name;
  291.                                 name = mapper.GetArgName(i);
  292.                                 if ((name == null) || (name.Length == 0)) {
  293.                                     name = "__param" + i;
  294.                                 }
  295.                                 info.AddValue(name, args[i], types[i].IsByRef ? types[i].GetElementType() : types[i]);
  296.                             }
  297.                         }
  298.                     }
  299.                     else {
  300.                         object oClientIsClr = CallContext.GetData("__ClientIsClr");
  301.                         bool bClientIsClr = (oClientIsClr == null) ? true : (bool)oClientIsClr;
  302.                         info.FullTypeName = "FormatterWrapper";
  303.                         info.AssemblyName = DefaultFakeRecordAssemblyName;
  304.                        
  305.                         Exception ex = msg.Exception;
  306.                         StringBuilder sb = new StringBuilder();
  307.                         bool bMustUnderstandError = false;
  308.                         while (ex != null) {
  309.                             if (ex.Message.StartsWith("MustUnderstand", StringComparison.Ordinal))
  310.                                 bMustUnderstandError = true;
  311.                            
  312.                             sb.Append(" **** ");
  313.                             sb.Append(ex.GetType().FullName);
  314.                             sb.Append(" - ");
  315.                             sb.Append(ex.Message);
  316.                            
  317.                             ex = ex.InnerException;
  318.                         }
  319.                        
  320.                         ServerFault serverFault = null;
  321.                         if (bClientIsClr)
  322.                             serverFault = new ServerFault(msg.Exception);
  323.                         else
  324.                             // Clr is the Client use full exception
  325.                             serverFault = new ServerFault(msg.Exception.GetType().AssemblyQualifiedName, sb.ToString(), msg.Exception.StackTrace);
  326.                        
  327.                         string faultType = "Server";
  328.                         if (bMustUnderstandError)
  329.                             faultType = "MustUnderstand";
  330.                        
  331.                         SoapFault soapFault = new SoapFault(faultType, sb.ToString(), null, serverFault);
  332.                         info.AddValue("__WrappedObject", soapFault, _soapFaultType);
  333.                     }
  334.                 }
  335.                 else {
  336.                    
  337.                     IMethodCallMessage mcm = (IMethodCallMessage)obj;
  338.                    
  339.                     // obtain method namespace
  340.                     MethodBase mb = mcm.MethodBase;
  341.                     string methodElementNS = SoapServices.GetXmlNamespaceForMethodCall(mb);
  342.                    
  343.                     object[] args = mcm.InArgs;
  344.                     string[] names = GetInArgNames(mcm, args.Length);
  345.                     Type[] sig = (Type[])mcm.MethodSignature;
  346.                     info.FullTypeName = mcm.MethodName;
  347.                     info.AssemblyName = methodElementNS;
  348.                     RemotingMethodCachedData cache = (RemotingMethodCachedData)InternalRemotingServices.GetReflectionCachedData(mb);
  349.                     int[] requestArgMap = cache.MarshalRequestArgMap;
  350.                    
  351.                    
  352.                     BCLDebug.Assert(args != null || sig.Length == args.Length, "Signature mismatch");
  353.                    
  354.                     for (int i = 0; i < args.Length; i++) {
  355.                         string paramName = null;
  356.                         if ((names[i] == null) || (names[i].Length == 0))
  357.                             paramName = "__param" + i;
  358.                         else
  359.                             paramName = names[i];
  360.                        
  361.                         int sigPosition = requestArgMap[i];
  362.                         Type argType = null;
  363.                        
  364.                         if (sig[sigPosition].IsByRef)
  365.                             argType = sig[sigPosition].GetElementType();
  366.                         else
  367.                             argType = sig[sigPosition];
  368.                        
  369.                         info.AddValue(paramName, args[i], argType);
  370.                     }
  371.                 }
  372.             }
  373.         }
  374.         // GetObjectData
  375.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
  376.         public virtual object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)
  377.         {
  378.             throw new NotSupportedException(Environment.GetResourceString("NotSupported_PopulateData"));
  379.         }
  380.        
  381.     }
  382.    
  383.     internal class MessageSurrogate : ISerializationSurrogate
  384.     {
  385.         // Private static data
  386.         private static Type _constructionCallType = typeof(ConstructionCall);
  387.         private static Type _methodCallType = typeof(MethodCall);
  388.         private static Type _constructionResponseType = typeof(ConstructionResponse);
  389.         private static Type _methodResponseType = typeof(MethodResponse);
  390.         private static Type _exceptionType = typeof(Exception);
  391.         private static Type _objectType = typeof(object);
  392.        
  393.         // Private static member data
  394.         private RemotingSurrogateSelector _ss;
  395.        
  396.         internal MessageSurrogate(RemotingSurrogateSelector ss)
  397.         {
  398.             _ss = ss;
  399.         }
  400.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
  401.         public virtual void GetObjectData(object obj, SerializationInfo info, StreamingContext context)
  402.         {
  403.             if (obj == null) {
  404.                 throw new ArgumentNullException("obj");
  405.             }
  406.            
  407.             if (info == null) {
  408.                 throw new ArgumentNullException("info");
  409.             }
  410.            
  411.             bool returnMessage = false;
  412.             bool constructionMessage = false;
  413.             IMethodMessage msg = obj as IMethodMessage;
  414.             if (null != msg) {
  415.                 IDictionaryEnumerator de = msg.Properties.GetEnumerator();
  416.                 if (msg is IMethodCallMessage) {
  417.                     if (obj is IConstructionCallMessage)
  418.                         constructionMessage = true;
  419.                     info.SetType(constructionMessage ? _constructionCallType : _methodCallType);
  420.                 }
  421.                 else {
  422.                     IMethodReturnMessage mrm = msg as IMethodReturnMessage;
  423.                     if (null != mrm) {
  424.                         returnMessage = true;
  425.                         info.SetType((obj is IConstructionReturnMessage) ? _constructionResponseType : _methodResponseType);
  426.                         if (((IMethodReturnMessage)msg).Exception != null) {
  427.                             info.AddValue("__fault", ((IMethodReturnMessage)msg).Exception, _exceptionType);
  428.                         }
  429.                        
  430.                     }
  431.                     else {
  432.                         throw new RemotingException(Environment.GetResourceString("Remoting_InvalidMsg"));
  433.                     }
  434.                 }
  435.                
  436.                 while (de.MoveNext()) {
  437.                     if ((obj == _ss.GetRootObject()) && (_ss.Filter != null) && _ss.Filter((string)de.Key, de.Value))
  438.                         continue;
  439.                    
  440.                     if (de.Value != null) {
  441.                        
  442.                         string key = de.Key.ToString();
  443.                         if (key.Equals("__CallContext")) {
  444.                             // If the CallContext has only the call Id, then there is no need to put the entire
  445.                             // LogicalCallContext type on the wire
  446.                             LogicalCallContext lcc = (LogicalCallContext)de.Value;
  447.                             if (lcc.HasInfo)
  448.                                 info.AddValue(key, lcc);
  449.                             else
  450.                                 info.AddValue(key, lcc.RemotingData.LogicalCallID);
  451.                         }
  452.                         else if (key.Equals("__MethodSignature")) {
  453.                             if (constructionMessage || RemotingServices.IsMethodOverloaded(msg)) {
  454.                                 info.AddValue(key, de.Value);
  455.                                 continue;
  456.                             }
  457.                             Message.DebugOut("MessageSurrogate::GetObjectData. Method not overloaded, so no MethodSignature \n");
  458.                         }
  459.                         else {
  460.                             #pragma warning disable 1717 // assignment to self
  461.                             returnMessage = returnMessage;
  462.                             #pragma warning restore 1717
  463.                             info.AddValue(key, de.Value);
  464.                         }
  465.                        
  466.                     }
  467.                     else {
  468.                         info.AddValue(de.Key.ToString(), de.Value, _objectType);
  469.                     }
  470.                 }
  471.             }
  472.             else {
  473.                 throw new RemotingException(Environment.GetResourceString("Remoting_InvalidMsg"));
  474.             }
  475.            
  476.         }
  477.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
  478.         public virtual object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)
  479.         {
  480.             throw new NotSupportedException(Environment.GetResourceString("NotSupported_PopulateData"));
  481.         }
  482.     }
  483. }

Developer Fusion