1 /* **************************************************************************** 2 * 3 * Copyright (c) Microsoft Corporation. 4 * 5 * This source code is subject to terms and conditions of the Microsoft Public License. A 6 * copy of the license can be found in the License.html file at the root of this distribution. If 7 * you cannot locate the Microsoft Public License, please send an email to 8 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 9 * by the terms of the Microsoft Public License. 10 * 11 * You must not remove this notice, or any other, from this software. 12 * 13 * 14 * ***************************************************************************/ 15 using System; using Microsoft; 16 17 18 #if !SILVERLIGHT 19 20 #if CODEPLEX_40 21 using System.Linq.Expressions; 22 #else 23 using Microsoft.Linq.Expressions; 24 #endif 25 using System.Security; 26 using System.Security.Permissions; 27 28 #if CODEPLEX_40 29 namespace System.Dynamic { 30 #else 31 namespace Microsoft.Scripting { 32 #endif 33 internal class DispCallableMetaObject : DynamicMetaObject { 34 private readonly DispCallable _callable; 35 DispCallableMetaObject(Expression expression, DispCallable callable)36 internal DispCallableMetaObject(Expression expression, DispCallable callable) 37 : base(expression, BindingRestrictions.Empty, callable) { 38 _callable = callable; 39 } 40 BindGetIndex(GetIndexBinder binder, DynamicMetaObject[] indexes)41 public override DynamicMetaObject BindGetIndex(GetIndexBinder binder, DynamicMetaObject[] indexes) { 42 return BindGetOrInvoke(indexes, binder.CallInfo) ?? 43 base.BindGetIndex(binder, indexes); 44 } 45 BindInvoke(InvokeBinder binder, DynamicMetaObject[] args)46 public override DynamicMetaObject BindInvoke(InvokeBinder binder, DynamicMetaObject[] args) { 47 return BindGetOrInvoke(args, binder.CallInfo) ?? 48 base.BindInvoke(binder, args); 49 } 50 51 #if CLR2 52 [SecurityCritical, SecurityTreatAsSafe] 53 #else 54 [SecuritySafeCritical] 55 #endif BindGetOrInvoke(DynamicMetaObject[] args, CallInfo callInfo)56 private DynamicMetaObject BindGetOrInvoke(DynamicMetaObject[] args, CallInfo callInfo) { 57 // 58 // Demand Full Trust to proceed with the binding. 59 // 60 61 new PermissionSet(PermissionState.Unrestricted).Demand(); 62 63 ComMethodDesc method; 64 var target = _callable.DispatchComObject; 65 var name = _callable.MemberName; 66 67 if (target.TryGetMemberMethod(name, out method) || 68 target.TryGetMemberMethodExplicit(name, out method)) { 69 70 bool[] isByRef = ComBinderHelpers.ProcessArgumentsForCom(ref args); 71 return BindComInvoke(method, args, callInfo, isByRef); 72 } 73 return null; 74 } 75 76 #if CLR2 77 [SecurityCritical, SecurityTreatAsSafe] 78 #else 79 [SecuritySafeCritical] 80 #endif BindSetIndex(SetIndexBinder binder, DynamicMetaObject[] indexes, DynamicMetaObject value)81 public override DynamicMetaObject BindSetIndex(SetIndexBinder binder, DynamicMetaObject[] indexes, DynamicMetaObject value) { 82 // 83 // Demand Full Trust to proceed with the binding. 84 // 85 86 new PermissionSet(PermissionState.Unrestricted).Demand(); 87 88 ComMethodDesc method; 89 var target = _callable.DispatchComObject; 90 var name = _callable.MemberName; 91 92 bool holdsNull = value.Value == null && value.HasValue; 93 if (target.TryGetPropertySetter(name, out method, value.LimitType, holdsNull) || 94 target.TryGetPropertySetterExplicit(name, out method, value.LimitType, holdsNull)) { 95 96 bool[] isByRef = ComBinderHelpers.ProcessArgumentsForCom(ref indexes); 97 isByRef = isByRef.AddLast(false); 98 var result = BindComInvoke(method, indexes.AddLast(value), binder.CallInfo, isByRef); 99 100 // Make sure to return the value; some languages need it. 101 return new DynamicMetaObject( 102 Expression.Block(result.Expression, Expression.Convert(value.Expression, typeof(object))), 103 result.Restrictions 104 ); 105 } 106 107 return base.BindSetIndex(binder, indexes, value); 108 } 109 110 [SecurityCritical] BindComInvoke(ComMethodDesc method, DynamicMetaObject[] indexes, CallInfo callInfo, bool[] isByRef)111 private DynamicMetaObject BindComInvoke(ComMethodDesc method, DynamicMetaObject[] indexes, CallInfo callInfo, bool[] isByRef) { 112 var callable = Expression; 113 var dispCall = Helpers.Convert(callable, typeof(DispCallable)); 114 115 return new ComInvokeBinder( 116 callInfo, 117 indexes, 118 isByRef, 119 DispCallableRestrictions(), 120 Expression.Constant(method), 121 Expression.Property( 122 dispCall, 123 typeof(DispCallable).GetProperty("DispatchObject") 124 ), 125 method 126 ).Invoke(); 127 } 128 129 [SecurityCritical] DispCallableRestrictions()130 private BindingRestrictions DispCallableRestrictions() { 131 var callable = Expression; 132 133 var callableTypeRestrictions = BindingRestrictions.GetTypeRestriction(callable, typeof(DispCallable)); 134 var dispCall = Helpers.Convert(callable, typeof(DispCallable)); 135 var dispatch = Expression.Property(dispCall, typeof(DispCallable).GetProperty("DispatchComObject")); 136 var dispId = Expression.Property(dispCall, typeof(DispCallable).GetProperty("DispId")); 137 138 var dispatchRestriction = IDispatchMetaObject.IDispatchRestriction(dispatch, _callable.DispatchComObject.ComTypeDesc); 139 var memberRestriction = BindingRestrictions.GetExpressionRestriction( 140 Expression.Equal(dispId, Expression.Constant(_callable.DispId)) 141 ); 142 143 return callableTypeRestrictions.Merge(dispatchRestriction).Merge(memberRestriction); 144 } 145 } 146 } 147 148 #endif 149