The Labs \ Source Viewer \ SSCLI \ Microsoft.JScript \ MethodInvoker

  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 Microsoft.JScript
  16. {
  17.     using System;
  18.     using System.Collections;
  19.     using System.Reflection;
  20.     using System.Reflection.Emit;
  21.     using System.Security;
  22.     using System.Security.Permissions;
  23.     using System.Threading;
  24.     using System.Diagnostics;
  25.    
  26.     public abstract class MethodInvoker
  27.     {
  28.        
  29.         #if !DEBUG
  30.         [DebuggerStepThroughAttribute()]
  31.         [DebuggerHiddenAttribute()]
  32.         #endif
  33.         public abstract object Invoke(object thisob, object[] parameters);
  34.        
  35.        
  36.         private static SimpleHashtable invokerFor = new SimpleHashtable(64);
  37.         private static int count = 0;
  38.        
  39.         private static bool DoesCallerRequireFullTrust(MethodInfo method)
  40.         {
  41.             Assembly assembly = method.DeclaringType.Assembly;
  42.             // strongly-named assembly requires full trust or AllowPartiallyTrustedCallersAttribute to be called
  43.             FileIOPermission pathDiscoveryPermission = new FileIOPermission(PermissionState.None);
  44.             pathDiscoveryPermission.AllFiles = FileIOPermissionAccess.PathDiscovery;
  45.             pathDiscoveryPermission.Assert();
  46.             byte[] key = assembly.GetName().GetPublicKey();
  47.             if (key == null || key.Length == 0)
  48.                 return false;
  49.             if (CustomAttribute.GetCustomAttributes(assembly, typeof(AllowPartiallyTrustedCallersAttribute), true).Length != 0)
  50.                 return false;
  51.             return true;
  52.         }
  53.        
  54.         static internal MethodInvoker GetInvokerFor(MethodInfo method)
  55.         {
  56.             // .NET security does not allow Deny, Assert or PermitOnly to be called via
  57.             // Reflection. We are effectively creating our own Reflection layer, so
  58.             // we must do the same thing.
  59.             if (method.DeclaringType == typeof(System.Security.CodeAccessPermission) && (method.Name == "Deny" || method.Name == "Assert" || method.Name == "PermitOnly"))
  60.                 throw new JScriptException(JSError.CannotCallSecurityMethodLateBound);
  61.            
  62.             MethodInvoker invoker = MethodInvoker.invokerFor[method] as MethodInvoker;
  63.             if (invoker != null)
  64.                 return invoker;
  65.             if (!SafeToCall(method))
  66.                 return null;
  67.             bool requiresDemand = DoesCallerRequireFullTrust(method);
  68.             lock (MethodInvoker.invokerFor) {
  69.                 invoker = MethodInvoker.invokerFor[method] as MethodInvoker;
  70.                 if (invoker != null)
  71.                     return invoker;
  72.                 invoker = MethodInvoker.SpitAndInstantiateClassFor(method, requiresDemand);
  73.                 MethodInvoker.invokerFor[method] = invoker;
  74.             }
  75.             return invoker;
  76.         }
  77.        
  78.         private static bool SafeToCall(MethodInfo meth)
  79.         {
  80.             Type t = meth.DeclaringType;
  81.             return (t != null && t != typeof(System.Activator) && t != typeof(System.AppDomain) && t != typeof(System.IO.IsolatedStorage.IsolatedStorageFile) && t != typeof(System.Reflection.Emit.MethodRental) && t != typeof(System.Security.SecurityManager) && !typeof(System.Reflection.Assembly).IsAssignableFrom(t) && !typeof(System.Reflection.MemberInfo).IsAssignableFrom(t) && !typeof(System.Resources.ResourceManager).IsAssignableFrom(t) && !typeof(System.Delegate).IsAssignableFrom(t) && (t.Attributes & TypeAttributes.HasSecurity) == 0 && (meth.Attributes & MethodAttributes.HasSecurity) == 0 && (meth.Attributes & MethodAttributes.PinvokeImpl) == 0);
  82.         }
  83.        
  84.         [ReflectionPermission(SecurityAction.Assert, Unrestricted = true)]
  85.         private static MethodInvoker SpitAndInstantiateClassFor(MethodInfo method, bool requiresDemand)
  86.         {
  87.             TypeBuilder tb = Runtime.ThunkModuleBuilder.DefineType("invoker" + MethodInvoker.count++, TypeAttributes.Public, typeof(MethodInvoker));
  88.             MethodBuilder mb = tb.DefineMethod("Invoke", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.ReuseSlot, typeof(object), new Type[] {typeof(object), typeof(object[])});
  89.            
  90.             if (requiresDemand)
  91.                 mb.AddDeclarativeSecurity(SecurityAction.Demand, new NamedPermissionSet("FullTrust"));
  92.             #if !DEBUG
  93.             mb.SetCustomAttribute(new CustomAttributeBuilder(Runtime.TypeRefs.debuggerStepThroughAttributeCtor, new object[] {}));
  94.             mb.SetCustomAttribute(new CustomAttributeBuilder(Runtime.TypeRefs.debuggerHiddenAttributeCtor, new object[] {}));
  95.             #endif
  96.             ILGenerator il = mb.GetILGenerator();
  97.             if (!method.DeclaringType.IsPublic)
  98.                 method = method.GetBaseDefinition();
  99.             Type obT = method.DeclaringType;
  100.             if (!method.IsStatic) {
  101.                 il.Emit(OpCodes.Ldarg_1);
  102.                 if (obT.IsValueType) {
  103.                     Convert.EmitUnbox(il, obT, Type.GetTypeCode(obT));
  104.                     Convert.EmitLdloca(il, obT);
  105.                 }
  106.                 else {
  107.                     il.Emit(OpCodes.Castclass, obT);
  108.                 }
  109.             }
  110.             ParameterInfo[] parameters = method.GetParameters();
  111.             LocalBuilder[] outTemps = null;
  112.             for (int i = 0int n = parameters.Length; i < n; i++) {
  113.                 il.Emit(OpCodes.Ldarg_2);
  114.                 ConstantWrapper.TranslateToILInt(il, i);
  115.                 Type pt = parameters[i].ParameterType;
  116.                 if (pt.IsByRef) {
  117.                     pt = pt.GetElementType();
  118.                     if (outTemps == null)
  119.                         outTemps = new LocalBuilder[n];
  120.                     outTemps[i] = il.DeclareLocal(pt);
  121.                     il.Emit(OpCodes.Ldelem_Ref);
  122.                     if (pt.IsValueType)
  123.                         Convert.EmitUnbox(il, pt, Type.GetTypeCode(pt));
  124.                     il.Emit(OpCodes.Stloc, outTemps[i]);
  125.                     il.Emit(OpCodes.Ldloca, outTemps[i]);
  126.                 }
  127.                 else {
  128.                     il.Emit(OpCodes.Ldelem_Ref);
  129.                     if (pt.IsValueType)
  130.                         Convert.EmitUnbox(il, pt, Type.GetTypeCode(pt));
  131.                 }
  132.             }
  133.             if (!method.IsStatic && method.IsVirtual && !method.IsFinal && (!obT.IsSealed || !obT.IsValueType))
  134.                 il.Emit(OpCodes.Callvirt, method);
  135.             else
  136.                 il.Emit(OpCodes.Call, method);
  137.             Type rt = method.ReturnType;
  138.             if (rt == typeof(void))
  139.                 il.Emit(OpCodes.Ldnull);
  140.             else if (rt.IsValueType)
  141.                 il.Emit(OpCodes.Box, rt);
  142.             if (outTemps != null) {
  143.                 for (int i = 0int n = parameters.Length; i < n; i++) {
  144.                     LocalBuilder loc = outTemps[i];
  145.                     if (loc != null) {
  146.                         il.Emit(OpCodes.Ldarg_2);
  147.                         ConstantWrapper.TranslateToILInt(il, i);
  148.                         il.Emit(OpCodes.Ldloc, loc);
  149.                         Type pt = parameters[i].ParameterType.GetElementType();
  150.                         if (pt.IsValueType)
  151.                             il.Emit(OpCodes.Box, pt);
  152.                         il.Emit(OpCodes.Stelem_Ref);
  153.                     }
  154.                 }
  155.             }
  156.             il.Emit(OpCodes.Ret);
  157.             Type t = tb.CreateType();
  158.             return (MethodInvoker)Activator.CreateInstance(t);
  159.         }
  160.        
  161.     }
  162.    
  163. }

Developer Fusion