internal ComInvokeBinder( CallInfo callInfo, DynamicMetaObject[] args, bool[] isByRef, BindingRestrictions restrictions, Expression method, Expression dispatch, ComMethodDesc methodDesc ) { Debug.Assert(callInfo != null, "arguments"); Debug.Assert(args != null, "args"); Debug.Assert(isByRef != null, "isByRef"); Debug.Assert(method != null, "method"); Debug.Assert(dispatch != null, "dispatch"); Debug.Assert(TypeUtils.AreReferenceAssignable(typeof(ComMethodDesc), method.Type), "method"); Debug.Assert(TypeUtils.AreReferenceAssignable(typeof(IDispatch), dispatch.Type), "dispatch"); _method = method; _dispatch = dispatch; _methodDesc = methodDesc; _callInfo = callInfo; _args = args; _isByRef = isByRef; _restrictions = restrictions; // Set Instance to some value so that CallBinderHelper has the right number of parameters to work with _instance = dispatch; }
private DynamicMetaObject BindComInvoke(DynamicMetaObject[] args, ComMethodDesc method, CallInfo callInfo, bool[] isByRef, List<ParameterExpression> temps, List<Expression> initTemps) { DynamicMetaObject invoke = new ComInvokeBinder( callInfo, args, isByRef, IDispatchRestriction(), Expression.Constant(method), Expression.Property( Helpers.Convert(Expression, typeof(IDispatchComObject)), typeof(IDispatchComObject).GetProperty("DispatchObject") ), method ).Invoke(); if ((temps != null) && (temps.Any())) { Expression invokeExpression = invoke.Expression; Expression call = Expression.Block(invokeExpression.Type, temps, initTemps.Append(invokeExpression)); invoke = new DynamicMetaObject(call, invoke.Restrictions); } return invoke; }
private DynamicMetaObject BindComInvoke(DynamicMetaObject[] args, ComMethodDesc method, CallInfo callInfo, bool[] isByRef) { return new ComInvokeBinder( callInfo, args, isByRef, IDispatchRestriction(), Expression.Constant(method), Expression.Property( Helpers.Convert(Expression, typeof(IDispatchComObject)), typeof(IDispatchComObject).GetProperty("DispatchObject") ), method ).Invoke(); }
private DynamicMetaObject BindComInvoke(DynamicMetaObject[] args, ComMethodDesc method, CallInfo callInfo, bool[] isByRef) { return(new ComInvokeBinder( callInfo, args, isByRef, IDispatchRestriction(), Expression.Constant(method), Expression.Property( Helpers.Convert(Expression, typeof(IDispatchComObject)), typeof(IDispatchComObject).GetProperty("DispatchObject") ), method ).Invoke()); }
private DynamicMetaObject BindComInvoke(ComMethodDesc method, DynamicMetaObject[] indexes, CallInfo callInfo, bool[] isByRef) { var callable = Expression; var dispCall = Helpers.Convert(callable, typeof(DispCallable)); return new ComInvokeBinder( callInfo, indexes, isByRef, DispCallableRestrictions(), Expression.Constant(method), Expression.Property( dispCall, typeof(DispCallable).GetProperty("DispatchObject") ), method ).Invoke(); }
private bool SlowTryGetSetItem(out ComMethodDesc value) { EnsureScanDefinedMethods(); ComMethodDesc methodDesc = _comTypeDesc.SetItem; // Without type information, we really don't know whether or not we have a property setter. if (methodDesc == null) { string name = "[PROPERTYPUT, DISPID(0)]"; _comTypeDesc.EnsureSetItem(new ComMethodDesc(name, ComDispIds.DISPID_VALUE, ComTypes.INVOKEKIND.INVOKE_PROPERTYPUT)); methodDesc = _comTypeDesc.SetItem; } value = methodDesc; return(true); }
private DynamicMetaObject BindComInvoke(ComMethodDesc method, DynamicMetaObject[] indexes, CallInfo callInfo, bool[] isByRef) { var callable = Expression; var dispCall = Helpers.Convert(callable, typeof(DispCallable)); return(new ComInvokeBinder( callInfo, indexes, isByRef, DispCallableRestrictions(), Expression.Constant(method), Expression.Property( dispCall, typeof(DispCallable).GetProperty("DispatchObject") ), method ).Invoke()); }
internal bool TryGetPropertySetterExplicit(string name, out ComMethodDesc method, Type limitType, bool holdsNull) { EnsureScanDefinedMethods(); int dispId; int hresult = GetIDsOfNames(_dispatchObject, name, out dispId); if (hresult == ComHresults.S_OK) { // we do not know whether we have put or putref here // and we will not guess and pretend we found both. ComMethodDesc put = new ComMethodDesc(name, dispId, ComTypes.INVOKEKIND.INVOKE_PROPERTYPUT); _comTypeDesc.AddPut(name, put); ComMethodDesc putref = new ComMethodDesc(name, dispId, ComTypes.INVOKEKIND.INVOKE_PROPERTYPUTREF); _comTypeDesc.AddPutRef(name, putref); if (ComBinderHelpers.PreferPut(limitType, holdsNull)) { method = put; } else { method = putref; } return(true); } else if (hresult == ComHresults.DISP_E_UNKNOWNNAME) { method = null; return(false); } else { throw Error.CouldNotGetDispId(name, string.Format(CultureInfo.InvariantCulture, "0x{1:X})", hresult)); } }
internal bool TryGetMemberMethodExplicit(string name, out ComMethodDesc method) { EnsureScanDefinedMethods(); int dispId; int hresult = GetIDsOfNames(_dispatchObject, name, out dispId); if (hresult == ComHresults.S_OK) { ComMethodDesc cmd = new ComMethodDesc(name, dispId, ComTypes.INVOKEKIND.INVOKE_FUNC); _comTypeDesc.AddFunc(name, cmd); method = cmd; return(true); } else if (hresult == ComHresults.DISP_E_UNKNOWNNAME) { method = null; return(false); } else { throw Error.CouldNotGetDispId(name, string.Format(CultureInfo.InvariantCulture, "0x{1:X})", hresult)); } }
internal bool TryGetMemberMethodExplicit(string name, out ComMethodDesc method) { EnsureScanDefinedMethods(); int dispId; int hresult = GetIDsOfNames(_dispatchObject, name, out dispId); if (hresult == ComHresults.S_OK) { ComMethodDesc cmd = new ComMethodDesc(name, dispId, ComTypes.INVOKEKIND.INVOKE_FUNC); _comTypeDesc.AddFunc(name, cmd); method = cmd; return true; } else if (hresult == ComHresults.DISP_E_UNKNOWNNAME) { method = null; return false; } else { throw Error.CouldNotGetDispId(name, string.Format(CultureInfo.InvariantCulture, "0x{1:X})", hresult)); } }
internal void EnsureSetItem(ComMethodDesc candidate) { Interlocked.CompareExchange(ref _setItem, candidate, null); }
private void EnsureScanDefinedMethods() { if (_comTypeDesc != null && _comTypeDesc.Funcs != null) { return; } ComTypes.ITypeInfo typeInfo = ComRuntimeHelpers.GetITypeInfoFromIDispatch(DispatchObject, true); if (typeInfo == null) { _comTypeDesc = ComTypeDesc.CreateEmptyTypeDesc(); return; } ComTypes.TYPEATTR typeAttr = ComRuntimeHelpers.GetTypeAttrForTypeInfo(typeInfo); if (_comTypeDesc == null) { lock (s_cacheComTypeDesc) { if (s_cacheComTypeDesc.TryGetValue(typeAttr.guid, out _comTypeDesc) == true && _comTypeDesc.Funcs != null) { return; } } } if (typeAttr.typekind == ComTypes.TYPEKIND.TKIND_INTERFACE) { //We have typeinfo for custom interface. Get typeinfo for Dispatch interface. typeInfo = ComTypeInfo.GetDispatchTypeInfoFromCustomInterfaceTypeInfo(typeInfo); typeAttr = ComRuntimeHelpers.GetTypeAttrForTypeInfo(typeInfo); } if (typeAttr.typekind == ComTypes.TYPEKIND.TKIND_COCLASS) { //We have typeinfo for the COClass. Find the default interface and get typeinfo for default interface. typeInfo = ComTypeInfo.GetDispatchTypeInfoFromCoClassTypeInfo(typeInfo); typeAttr = ComRuntimeHelpers.GetTypeAttrForTypeInfo(typeInfo); } ComTypeDesc typeDesc = ComTypeDesc.FromITypeInfo(typeInfo, typeAttr); ComMethodDesc getItem = null; ComMethodDesc setItem = null; Hashtable funcs = new Hashtable(typeAttr.cFuncs); Hashtable puts = new Hashtable(); Hashtable putrefs = new Hashtable(); for (int definedFuncIndex = 0; definedFuncIndex < typeAttr.cFuncs; definedFuncIndex++) { IntPtr funcDescHandleToRelease = IntPtr.Zero; try { ComTypes.FUNCDESC funcDesc; GetFuncDescForDescIndex(typeInfo, definedFuncIndex, out funcDesc, out funcDescHandleToRelease); if ((funcDesc.wFuncFlags & (int)ComTypes.FUNCFLAGS.FUNCFLAG_FRESTRICTED) != 0) { // This function is not meant for the script user to use. continue; } ComMethodDesc method = new ComMethodDesc(typeInfo, funcDesc); string name = method.Name.ToUpper(System.Globalization.CultureInfo.InvariantCulture); if ((funcDesc.invkind & ComTypes.INVOKEKIND.INVOKE_PROPERTYPUT) != 0) { // If there is a getter for this put, use that ReturnType as the // PropertyType. if (funcs.ContainsKey(name)) { method.InputType = ((ComMethodDesc)funcs[name]).ReturnType; } puts.Add(name, method); // for the special dispId == 0, we need to store // the method descriptor for the Do(SetItem) binder. if (method.DispId == ComDispIds.DISPID_VALUE && setItem == null) { setItem = method; } continue; } if ((funcDesc.invkind & ComTypes.INVOKEKIND.INVOKE_PROPERTYPUTREF) != 0) { // If there is a getter for this put, use that ReturnType as the // PropertyType. if (funcs.ContainsKey(name)) { method.InputType = ((ComMethodDesc)funcs[name]).ReturnType; } putrefs.Add(name, method); // for the special dispId == 0, we need to store // the method descriptor for the Do(SetItem) binder. if (method.DispId == ComDispIds.DISPID_VALUE && setItem == null) { setItem = method; } continue; } if (funcDesc.memid == ComDispIds.DISPID_NEWENUM) { funcs.Add("GETENUMERATOR", method); continue; } // If there is a setter for this put, update the InputType from our // ReturnType. if (puts.ContainsKey(name)) { ((ComMethodDesc)puts[name]).InputType = method.ReturnType; } if (putrefs.ContainsKey(name)) { ((ComMethodDesc)putrefs[name]).InputType = method.ReturnType; } funcs.Add(name, method); // for the special dispId == 0, we need to store the method descriptor // for the Do(GetItem) binder. if (funcDesc.memid == ComDispIds.DISPID_VALUE) { getItem = method; } } finally { if (funcDescHandleToRelease != IntPtr.Zero) { typeInfo.ReleaseFuncDesc(funcDescHandleToRelease); } } } lock (s_cacheComTypeDesc) { ComTypeDesc cachedTypeDesc; if (s_cacheComTypeDesc.TryGetValue(typeAttr.guid, out cachedTypeDesc)) { _comTypeDesc = cachedTypeDesc; } else { _comTypeDesc = typeDesc; s_cacheComTypeDesc.Add(typeAttr.guid, _comTypeDesc); } _comTypeDesc.Funcs = funcs; _comTypeDesc.Puts = puts; _comTypeDesc.PutRefs = putrefs; _comTypeDesc.EnsureGetItem(getItem); _comTypeDesc.EnsureSetItem(setItem); } }
public static DispCallable CreateDispCallable(IDispatchComObject dispatch, ComMethodDesc method) { return(new DispCallable(dispatch, method.Name, method.DispId)); }
internal void AddPutRef(string name, ComMethodDesc method) { name = name.ToUpper(System.Globalization.CultureInfo.InvariantCulture); lock (_putRefs) { _putRefs[name] = method; } }
internal bool TryGetPutRef(string name, out ComMethodDesc method) { name = name.ToUpper(System.Globalization.CultureInfo.InvariantCulture); if (_putRefs.ContainsKey(name)) { method = _putRefs[name] as ComMethodDesc; return true; } method = null; return false; }
public static DispCallable CreateDispCallable(IDispatchComObject dispatch, ComMethodDesc method) { return new DispCallable(dispatch, method.Name, method.DispId); }
private void EnsureScanDefinedMethods() { if (_comTypeDesc != null && _comTypeDesc.Funcs != null) { return; } // // Demand Full Trust to proceed with the operation. // new PermissionSet(PermissionState.Unrestricted).Demand(); ComTypes.ITypeInfo typeInfo = ComRuntimeHelpers.GetITypeInfoFromIDispatch(_dispatchObject, true); if (typeInfo == null) { _comTypeDesc = ComTypeDesc.CreateEmptyTypeDesc(); return; } ComTypes.TYPEATTR typeAttr = ComRuntimeHelpers.GetTypeAttrForTypeInfo(typeInfo); if (_comTypeDesc == null) { lock (_CacheComTypeDesc) { if (_CacheComTypeDesc.TryGetValue(typeAttr.guid, out _comTypeDesc) == true && _comTypeDesc.Funcs != null) { return; } } } ComTypeDesc typeDesc = ComTypeDesc.FromITypeInfo(typeInfo, typeAttr); ComMethodDesc getItem = null; ComMethodDesc setItem = null; Hashtable funcs = new Hashtable(typeAttr.cFuncs); Hashtable puts = new Hashtable(); Hashtable putrefs = new Hashtable(); for (int definedFuncIndex = 0; definedFuncIndex < typeAttr.cFuncs; definedFuncIndex++) { IntPtr funcDescHandleToRelease = IntPtr.Zero; try { ComTypes.FUNCDESC funcDesc; GetFuncDescForDescIndex(typeInfo, definedFuncIndex, out funcDesc, out funcDescHandleToRelease); if ((funcDesc.wFuncFlags & (int)ComTypes.FUNCFLAGS.FUNCFLAG_FRESTRICTED) != 0) { // This function is not meant for the script user to use. continue; } ComMethodDesc method = new ComMethodDesc(typeInfo, funcDesc); string name = method.Name.ToUpper(System.Globalization.CultureInfo.InvariantCulture); if ((funcDesc.invkind & ComTypes.INVOKEKIND.INVOKE_PROPERTYPUT) != 0) { puts.Add(name, method); // for the special dispId == 0, we need to store // the method descriptor for the Do(SetItem) binder. if (method.DispId == ComDispIds.DISPID_VALUE && setItem == null) { setItem = method; } continue; } if ((funcDesc.invkind & ComTypes.INVOKEKIND.INVOKE_PROPERTYPUTREF) != 0) { putrefs.Add(name, method); // for the special dispId == 0, we need to store // the method descriptor for the Do(SetItem) binder. if (method.DispId == ComDispIds.DISPID_VALUE && setItem == null) { setItem = method; } continue; } if (funcDesc.memid == ComDispIds.DISPID_NEWENUM) { funcs.Add("GETENUMERATOR", method); continue; } funcs.Add(name, method); // for the special dispId == 0, we need to store the method descriptor // for the Do(GetItem) binder. if (funcDesc.memid == ComDispIds.DISPID_VALUE) { getItem = method; } } finally { if (funcDescHandleToRelease != IntPtr.Zero) { typeInfo.ReleaseFuncDesc(funcDescHandleToRelease); } } } lock (_CacheComTypeDesc) { ComTypeDesc cachedTypeDesc; if (_CacheComTypeDesc.TryGetValue(typeAttr.guid, out cachedTypeDesc)) { _comTypeDesc = cachedTypeDesc; } else { _comTypeDesc = typeDesc; _CacheComTypeDesc.Add(typeAttr.guid, _comTypeDesc); } _comTypeDesc.Funcs = funcs; _comTypeDesc.Puts = puts; _comTypeDesc.PutRefs = putrefs; _comTypeDesc.EnsureGetItem(getItem); _comTypeDesc.EnsureSetItem(setItem); } }
private DynamicMetaObject BindGetMember(ComMethodDesc method, bool canReturnCallables) { if (method.IsDataMember) { if (method.ParamCount == 0) { return BindComInvoke(DynamicMetaObject.EmptyMetaObjects, method, new CallInfo(0), Utils.EmptyArray<bool>(), null, null); } } // ComGetMemberBinder does not expect callables. Try to call always. if (!canReturnCallables) { return BindComInvoke(DynamicMetaObject.EmptyMetaObjects, method, new CallInfo(0), Utils.EmptyArray<bool>(), null, null); } return new DynamicMetaObject( Expression.Call( typeof(ComRuntimeHelpers).GetMethod("CreateDispCallable"), Helpers.Convert(Expression, typeof(IDispatchComObject)), Expression.Constant(method) ), IDispatchRestriction() ); }
internal bool TryGetMemberMethod(string name, out ComMethodDesc method) { EnsureScanDefinedMethods(); return _comTypeDesc.TryGetFunc(name, out method); }
private bool SlowTryGetSetItem(out ComMethodDesc value) { EnsureScanDefinedMethods(); ComMethodDesc methodDesc = _comTypeDesc.SetItem; // Without type information, we really don't know whether or not we have a property setter. if (methodDesc == null) { string name = "[PROPERTYPUT, DISPID(0)]"; _comTypeDesc.EnsureSetItem(new ComMethodDesc(name, ComDispIds.DISPID_VALUE, ComTypes.INVOKEKIND.INVOKE_PROPERTYPUT)); methodDesc = _comTypeDesc.SetItem; } value = methodDesc; return true; }
internal bool TryGetSetItem(out ComMethodDesc value) { ComMethodDesc methodDesc = _comTypeDesc.SetItem; if (methodDesc != null) { value = methodDesc; return true; } return SlowTryGetSetItem(out value); }
internal bool TryGetMemberMethod(string name, out ComMethodDesc method) { EnsureScanDefinedMethods(); return(_comTypeDesc.TryGetFunc(name, out method)); }
internal bool TryGetPropertySetterExplicit(string name, out ComMethodDesc method, Type limitType, bool holdsNull) { EnsureScanDefinedMethods(); int dispId; int hresult = GetIDsOfNames(_dispatchObject, name, out dispId); if (hresult == ComHresults.S_OK) { // we do not know whether we have put or putref here // and we will not guess and pretend we found both. ComMethodDesc put = new ComMethodDesc(name, dispId, ComTypes.INVOKEKIND.INVOKE_PROPERTYPUT); _comTypeDesc.AddPut(name, put); ComMethodDesc putref = new ComMethodDesc(name, dispId, ComTypes.INVOKEKIND.INVOKE_PROPERTYPUTREF); _comTypeDesc.AddPutRef(name, putref); if (ComBinderHelpers.PreferPut(limitType, holdsNull)) { method = put; } else { method = putref; } return true; } else if (hresult == ComHresults.DISP_E_UNKNOWNNAME) { method = null; return false; } else { throw Error.CouldNotGetDispId(name, string.Format(CultureInfo.InvariantCulture, "0x{1:X})", hresult)); } }
internal bool TryGetPropertySetter(string name, out ComMethodDesc method, Type limitType, bool holdsNull) { EnsureScanDefinedMethods(); if (ComBinderHelpers.PreferPut(limitType, holdsNull)) { return _comTypeDesc.TryGetPut(name, out method) || _comTypeDesc.TryGetPutRef(name, out method); } else { return _comTypeDesc.TryGetPutRef(name, out method) || _comTypeDesc.TryGetPut(name, out method); } }
private DynamicMetaObject BindComInvoke(ComMethodDesc method, DynamicMetaObject[] indexes, CallInfo callInfo, bool[] isByRef, List<ParameterExpression> temps, List<Expression> initTemps) { var callable = Expression; var dispCall = Helpers.Convert(callable, typeof(DispCallable)); DynamicMetaObject invoke = new ComInvokeBinder( callInfo, indexes, isByRef, DispCallableRestrictions(), Expression.Constant(method), Expression.Property( dispCall, typeof(DispCallable).GetProperty("DispatchObject") ), method ).Invoke(); if ((temps != null) && (temps.Any())) { Expression invokeExpression = invoke.Expression; Expression call = Expression.Block(invokeExpression.Type, temps, initTemps.Append(invokeExpression)); invoke = new DynamicMetaObject(call, invoke.Restrictions); } return invoke; }
// this helper prepares arguments for COM binding by transforming ByVal StongBox arguments // into ByRef expressions that represent the argument's Value fields. internal static bool[] ProcessArgumentsForCom(ComMethodDesc method, ref DynamicMetaObject[] args, List<ParameterExpression> temps, List<Expression> initTemps) { Debug.Assert(args != null); DynamicMetaObject[] newArgs = new DynamicMetaObject[args.Length]; bool[] isByRefArg = new bool[args.Length]; for (int i = 0; i < args.Length; i++) { DynamicMetaObject curArgument = args[i]; // set new arg infos to their original values or set default ones // we will do this fixup early so that we can assume we always have // arginfos in COM binder. if (IsByRef(curArgument)) { newArgs[i] = curArgument; isByRefArg[i] = true; } else { if (IsPSReferenceArg(curArgument)) { var restrictions = curArgument.Restrictions.Merge( GetTypeRestrictionForDynamicMetaObject(curArgument) ); // we have restricted this argument to LimitType so we can convert and conversion will be trivial cast. Expression boxedValueAccessor = Expression.Property( Helpers.Convert( curArgument.Expression, curArgument.LimitType ), curArgument.LimitType.GetProperty("Value") ); PSReference value = curArgument.Value as PSReference; object boxedValue = value != null ? value.Value : null; newArgs[i] = new DynamicMetaObject( boxedValueAccessor, restrictions, boxedValue ); isByRefArg[i] = true; } else { if ((method.ParameterInformation != null) && (i < method.ParameterInformation.Length)) { newArgs[i] = new DynamicMetaObject(curArgument.CastOrConvertMethodArgument( method.ParameterInformation[i].parameterType, i.ToString(CultureInfo.InvariantCulture), method.Name, temps, initTemps), curArgument.Restrictions); } else { newArgs[i] = curArgument; } isByRefArg[i] = false; } } } args = newArgs; return isByRefArg; }