public SignatureInfoMatchTarget(TypeInfo interfaceTypeInfo, int functionIndex, ElemDesc elemDesc, int parameterIndex) { if (interfaceTypeInfo == null) throw new ArgumentNullException(nameof(interfaceTypeInfo)); m_interfaceTypeInfo = interfaceTypeInfo; m_functionIndex = functionIndex; m_funcDesc = interfaceTypeInfo.GetFuncDesc(m_functionIndex); m_elemDesc = elemDesc; m_parameterIndex = parameterIndex; if (m_parameterIndex == 0) { m_name = "return"; } else { // the name of the parameter. string[] signatureNames = m_interfaceTypeInfo.GetNames(m_funcDesc.memid, m_funcDesc.cParams + 1); m_name = signatureNames[m_parameterIndex]; if (m_name == null || m_name.Trim().Equals("")) m_name = "_unnamed_arg_" + m_parameterIndex; } // NativeParentFunctionName m_nativeParentFunctionName = m_interfaceTypeInfo.GetDocumentation(m_funcDesc.memid); // NativeSignature m_nativeSignature = (new TlbType2String(interfaceTypeInfo, m_elemDesc.tdesc)).GetTypeString(); }
public ElemDesc(FuncDesc funcdesc, int index) { m_parent = funcdesc; IntPtr pParam = funcdesc.m_funcdesc.lprgelemdescParam; IntPtr pElemDesc = Utils.MovePointer(pParam, index * Marshal.SizeOf(typeof(ELEMDESC))); Init((ELEMDESC)Marshal.PtrToStructure(pElemDesc, typeof(ELEMDESC))); }
public FunctionInfoMatchTarget(TypeInfo parentTypeInfo, int index) { if (parentTypeInfo == null) throw new ArgumentNullException(nameof(parentTypeInfo)); m_interfaceTypeInfo = parentTypeInfo; m_index = index; m_funcDesc = parentTypeInfo.GetFuncDesc(m_index); m_nativeParentTypeName = m_interfaceTypeInfo.GetDocumentation(); }
public ElemDesc(FuncDesc funcdesc, ELEMDESC elemdesc) { m_parent = funcdesc; Init(elemdesc); }
public ElemDesc(FuncDesc funcdesc, int index) { if (funcdesc == null) throw new ArgumentNullException(nameof(funcdesc)); m_parent = funcdesc; IntPtr pParam = funcdesc.m_funcdesc.lprgelemdescParam; IntPtr pElemDesc = Utils.MovePointer(pParam, index * Marshal.SizeOf(typeof(ELEMDESC))); Init( (ELEMDESC) Marshal.PtrToStructure(pElemDesc, typeof(ELEMDESC))); }
/// <summary> /// Get the return type converter for the function /// </summary> public static TypeConverter GetReturnType(InterfaceInfo info, InterfaceMemberInfo memInfo, FuncDesc func, bool isNewEnumMember, TypeConverter returnConverterOverride, List<TypeConverter> parameterConverterOverrideList, out ReturnKind kind, out bool isStandardOleCall, out int returnArgId) { TypeConverter retType = null; returnArgId = -1; kind = ReturnKind.ReturnValue; isStandardOleCall = false; TypeDesc retTypeDesc = func.elemdescFunc.tdesc; // If /preservesig is specified, we perform the PreserveSig transformation, except for dispatch functions. // Because they are not affected by PreserveSig attribute. if ((!func.IsDispatch) && (info.ConverterInfo.Settings.m_isPreserveSig || IsPreserveSigOverride(info, memInfo.Index))) { if (returnConverterOverride != null) { retType = returnConverterOverride; kind = ReturnKind.ReturnValue; } else if (retTypeDesc.vt == (int)VarEnum.VT_VOID) { retType = s_voidTypeConverter; kind = ReturnKind.NoReturn; } else { retType = new TypeConverter(info.ConverterInfo, info.RefTypeInfo, func.elemdescFunc.tdesc, isNewEnumMember, ConversionType.ReturnValue); kind = ReturnKind.ReturnValue; } return retType; } // Inspect the return value // If the return is HRESULT and PreserveSig switch is not specified, we will do the HRESULT transformation // Otherwise, stick to the original return value and use PreserveSigAttribute if (retTypeDesc.vt == (int)VarEnum.VT_HRESULT) { isStandardOleCall = true; } else { if (retTypeDesc.vt != (int)VarEnum.VT_VOID && retTypeDesc.vt != (int)VarEnum.VT_HRESULT) { if (returnConverterOverride != null) retType = returnConverterOverride; else retType = new TypeConverter(info.ConverterInfo, info.RefTypeInfo, func.elemdescFunc.tdesc, isNewEnumMember, ConversionType.ReturnValue); kind = ReturnKind.ReturnValue; } } if (func.funckind == TypeLibTypes.Interop.FUNCKIND.FUNC_DISPATCH && (!info.ConverterInfo.TransformDispRetVal)) { // Skip RetVal => return value transformation for dispatch interface when TransformDispRetVal is not set } else { for (int i = 0; i < func.cParams; ++i) { ElemDesc ret = func.GetElemDesc(i); // In a COM type library, the return parameter is logical and is the last parameter // whereas it is an explicit separate item in managed. if (IsRetVal(info.ConverterInfo, ret.paramdesc, func)) { // Convert last parameter to return value if (retType == null) { returnArgId = i; if (parameterConverterOverrideList[returnArgId] != null) retType = parameterConverterOverrideList[returnArgId]; else retType = new TypeConverter(info.ConverterInfo, info.RefTypeInfo, ret.tdesc, isNewEnumMember, ConversionType.ParamRetVal); kind = ReturnKind.RetValParameter; } else { info.ConverterInfo.ReportEvent( WarningCode.Wrn_AmbiguousReturn, Resource.FormatString("Wrn_AmbiguousReturn", info.RefTypeInfo.GetDocumentation(), info.RefTypeInfo.GetDocumentation(func.memid))); } break; } } } if (retType == null) { if (returnConverterOverride != null) { retType = returnConverterOverride; kind = ReturnKind.ReturnValue; } else { retType = s_voidTypeConverter; kind = ReturnKind.NoReturn; } } return retType; }
/// <summary> /// Check for optional arguments /// </summary> public static void CheckForOptionalArguments(ConverterInfo info, FuncDesc func, out int varArg, out int firstOptArg, out int lastOptArg) { int numOfParams = func.cParams; varArg = firstOptArg = lastOptArg = numOfParams + 1; if (func.cParamsOpt == -1) { // // [vararg] scenario // // For propput/propputref, the last parameter will be the value to be set bool skipPropPutArg = false; if ((func.invkind & (TypeLibTypes.Interop.INVOKEKIND.INVOKE_PROPERTYPUT | TypeLibTypes.Interop.INVOKEKIND.INVOKE_PROPERTYPUTREF)) != 0) skipPropPutArg = true; // vararg will be the last argument except for lcid arguments & retval arguments for (int target = numOfParams - 1; target >= 0; --target) { // skip lcid/retval ParamDesc paramDesc = func.GetElemDesc(target).paramdesc; if (IsRetVal(info, paramDesc, func) || paramDesc.IsLCID) continue; // skip for property if (skipPropPutArg) { skipPropPutArg = false; continue; } varArg = target; break; } Debug.Assert(varArg < numOfParams); } else if (func.cParamsOpt > 0) { // // [optional] scenario // int countOfOptionals = func.cParamsOpt; firstOptArg = 0; // find the first optional arg for (int target = func.cParams - 1; target >= 0; --target) { // The count of optional params does not include any lcid params, nor does // it include the return value, so skip those. ParamDesc param = func.GetElemDesc(target).paramdesc; if (!(param.IsRetval || param.IsRetval)) { if (--countOfOptionals == 0) { firstOptArg = target; break; } } } lastOptArg = firstOptArg + func.cParamsOpt; } }
public static void CreateMethodForDelegate(InterfaceInfo info, FuncDesc funcDesc, int index) { InterfaceMemberInfo memberInfo = new InterfaceMemberInfo(info.ConverterInfo, info.RefTypeInfo, index, INVOKE_METHOD, INVOKE_METHOD, InterfaceMemberType.Method, TypeLibTypes.Interop.INVOKEKIND.INVOKE_FUNC, funcDesc.memid, funcDesc, null); CreateMethod(info, memberInfo, CreateMethodMode.EventDelegateMode); }
/// <summary> /// Figure out types for parameters and return a parameter array /// </summary> /// <returns>TypeConverter[] array for all parameters</returns> public static TypeConverter[] GenerateParameterTypes(InterfaceInfo info, InterfaceMemberInfo memInfo, FuncDesc func, bool isNewEnumMember, int vararg, out int lcidArg, out bool isStandardOleCall, out TypeConverter retTypeConverter, out ReturnKind kind, out int retArgId) { // // Check Lcid Parameter // lcidArg = -1; for (int i = 0; i < func.cParams; ++i) { if (func.GetElemDesc(i).paramdesc.IsLCID) { if (lcidArg >= 0) { info.ConverterInfo.ReportEvent( WarningCode.Wrn_MultipleLcids, Resource.FormatString("Wrn_MultipleLcids", info.RefTypeInfo.GetDocumentation(), info.RefTypeInfo.GetDocumentation(func.memid))); } lcidArg = i; } } // Pre-process for the rule engine // For return value TypeConverter convertToReturnConverter = null; GetRuledReturnTypeConverter(info, memInfo, func, out convertToReturnConverter); // For parameters List<TypeConverter> convertToParameterConverterList; GetRuledParameterTypeConverters(info, memInfo, func, out convertToParameterConverterList); retTypeConverter = GetReturnType(info, memInfo, func, isNewEnumMember, convertToReturnConverter, convertToParameterConverterList, out kind, out isStandardOleCall, out retArgId); if ((retTypeConverter == convertToReturnConverter || convertToParameterConverterList.Contains(retTypeConverter))) { // From convertTo Action. if ((retTypeConverter.ParameterAttributesOverride & ParameterAttributes.In) != ParameterAttributes.None) { Output.WriteWarning(Resource.FormatString("Wrn_ConvertReturnValueToNoneOut", info.RefTypeInfo.GetDocumentation(func.memid)), WarningCode.Wrn_ConvertReturnValueToNoneOut); } retTypeConverter.ParameterAttributesOverride = ParameterAttributes.None; } int cParams = func.cParams; var typeConverterList = new List<TypeConverter>(); short n; for (n = 0; n < cParams; ++n) { ElemDesc elem = func.GetElemDesc(n); ParamDesc paramDesc = elem.paramdesc; // Skip LCID if (paramDesc.IsLCID) continue; // Skip return parameter if (kind == ReturnKind.RetValParameter && n == retArgId) continue; try { ConversionType conversionType; if (n == vararg) conversionType = ConversionType.VarArgParameter; else conversionType = ConversionType.Parameter; if (convertToParameterConverterList[n] != null) { typeConverterList.Add(convertToParameterConverterList[n]); } else { typeConverterList.Add(new TypeConverter( info.ConverterInfo, info.RefTypeInfo, elem.tdesc, paramDesc, false, conversionType)); } } catch (COMException ex) { if ((uint)ex.ErrorCode == HResults.TYPE_E_CANTLOADLIBRARY) { string[] names = info.RefTypeInfo.GetNames(func.memid, func.cParams + 1); string name = names[n + 1]; if (name != String.Empty) { string msg = Resource.FormatString("Wrn_ParamErrorNamed", new object[] { info.RefTypeInfo.GetDocumentation(), name, memInfo.UniqueName }); info.ConverterInfo.ReportEvent(WarningCode.Wrn_ParamErrorNamed, msg); } else { string msg = Resource.FormatString("Wrn_ParamErrorUnnamed", new object[] { info.RefTypeInfo.GetDocumentation(), n, memInfo.UniqueName }); info.ConverterInfo.ReportEvent(WarningCode.Wrn_ParamErrorUnnamed, msg); } } throw; } } return typeConverterList.ToArray(); }
private static bool IsRetVal(ConverterInfo info, ParamDesc paramDesc, FuncDesc funcDesc) { if (paramDesc.IsRetval) { // Don't consider it is a RetVal for dispatch functions unless TransformDispRetVal is true if (funcDesc.funckind == TypeLibTypes.Interop.FUNCKIND.FUNC_DISPATCH && !info.TransformDispRetVal) return false; return true; } return false; }
private static void GetRuledReturnTypeConverter(InterfaceInfo info, InterfaceMemberInfo memInfo, FuncDesc func, out TypeConverter convertToReturnConverter) { convertToReturnConverter = null; Rule convertToRule = null; if (memInfo.Index != -1) { // Is not event delegate. SignatureInfoMatchTarget returnTarget = new SignatureInfoMatchTarget( info.RefTypeInfo, memInfo.Index, func.elemdescFunc, 0); if (info.ConverterInfo.Settings.m_ruleSet != null) { ICategory signatureCategory = SignatureCategory.GetInstance(); AbstractActionManager actionManager = RuleEngine.GetActionManager(); List<Rule> convertToRules = info.ConverterInfo.Settings.m_ruleSet.GetRule( signatureCategory, ConvertToActionDef.GetInstance(), returnTarget); if (convertToRules.Count != 0) { if (convertToRules.Count > 1) { Output.WriteWarning( Resource.FormatString("Wrn_RuleMultipleMatch", ConvertToActionDef.GetInstance().GetActionName()), WarningCode.Wrn_RuleMultipleMatch); } convertToRule = convertToRules[convertToRules.Count - 1]; } } if (convertToRule != null) { var convertToAction = convertToRule.Action as ConvertToAction; Type typeReturn; CustomAttributeBuilder customAttribute; ParameterAttributes fixedParameterAttributes; GetTypeFromConvertToAction(returnTarget, convertToAction, info.ConverterInfo, info.RefTypeInfo, func.elemdescFunc.tdesc, out typeReturn, out customAttribute, out fixedParameterAttributes); convertToReturnConverter = new TypeConverter(typeReturn, customAttribute, fixedParameterAttributes); } } }
private static void GetRuledParameterTypeConverters(InterfaceInfo info, InterfaceMemberInfo memInfo, FuncDesc func, out List<TypeConverter> convertToParameterConverterList) { int cParams = func.cParams; convertToParameterConverterList = new List<TypeConverter>(); short n; for (n = 0; n < cParams; ++n) { ElemDesc elem = func.GetElemDesc(n); ParamDesc paramDesc = elem.paramdesc; // "ConvertTo" for basic types and array // Rule Engine Rule convertToRule = null; if (memInfo.Index != -1) { // Is not event delegate. SignatureInfoMatchTarget target = new SignatureInfoMatchTarget( info.RefTypeInfo, memInfo.Index, elem, n + 1); if (info.ConverterInfo.Settings.m_ruleSet != null) { ICategory signatureCategory = SignatureCategory.GetInstance(); AbstractActionManager actionManager = RuleEngine.GetActionManager(); List<Rule> convertToRules = info.ConverterInfo.Settings.m_ruleSet.GetRule( signatureCategory, ConvertToActionDef.GetInstance(), target); if (convertToRules.Count != 0) { if (convertToRules.Count > 1) { Output.WriteWarning( Resource.FormatString("Wrn_RuleMultipleMatch", ConvertToActionDef.GetInstance().GetActionName()), WarningCode.Wrn_RuleMultipleMatch); } convertToRule = convertToRules[convertToRules.Count - 1]; } } if (convertToRule != null) { var convertToAction = convertToRule.Action as ConvertToAction; Type typeReturn; CustomAttributeBuilder customAttribute; ParameterAttributes fixedParameterAttributes; GetTypeFromConvertToAction(target, convertToAction, info.ConverterInfo, info.RefTypeInfo, elem.tdesc, out typeReturn, out customAttribute, out fixedParameterAttributes); convertToParameterConverterList.Add( new TypeConverter(typeReturn, customAttribute, fixedParameterAttributes)); } else { convertToParameterConverterList.Add(null); } } else { convertToParameterConverterList.Add(null); } } }
private static MethodBuilder CreateMethodInternal(InterfaceInfo info, FuncDesc func, InterfaceMemberInfo memberInfo, CreateMethodMode mode, ref bool isConversionLoss) { bool isNewEnumMember = false; if (info.AllowNewEnum && IsNewEnumFunc(info.ConverterInfo, info.RefTypeInfo, func, memberInfo.Index)) { info.AllowNewEnum = false; isNewEnumMember = true; if (mode == CreateMethodMode.EventDelegateMode) { info.ConverterInfo.ReportEvent( WarningCode.Wrn_EventWithNewEnum, Resource.FormatString("Wrn_EventWithNewEnum", info.RefTypeInfo.GetDocumentation())); } } // // Optional Arguments // int varArg; // index of the vararg argument int firstOptArg; // index of the first optional argument int lastOptArg; // index of the last optional argument CheckForOptionalArguments(info.ConverterInfo, func, out varArg, out firstOptArg, out lastOptArg); // // Figure out types // ReturnKind returnKind; TypeConverter retTypeConverter; Type retType; bool isStandardOleCall; int lcidArg; int retArgId; TypeConverter[] paramTypeConverters = GenerateParameterTypes(info, memberInfo, func, isNewEnumMember, varArg, out lcidArg, out isStandardOleCall, out retTypeConverter, out returnKind, out retArgId); var paramTypes = new Type[paramTypeConverters.Length]; for (int i = 0; i < paramTypeConverters.Length; ++i) paramTypes[i] = paramTypeConverters[i].ConvertedType; if (retTypeConverter != null) retType = retTypeConverter.ConvertedType; else retType = null; MethodBuilder methodBuilder = CreateMethodCore(info, memberInfo, isNewEnumMember, mode, isStandardOleCall, retType, paramTypes); // // Emit LCIDConversionAttribute // if (lcidArg >= 0) methodBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForLCIDConversion(lcidArg)); int cParams = func.cParams; int cParamsIter = cParams; // If there is a return value, skip the last param if (returnKind == ReturnKind.RetValParameter) { ProcessParam(info, memberInfo, func.GetElemDesc(retArgId), retTypeConverter, methodBuilder, 0, "", false, false); isConversionLoss |= retTypeConverter.IsConversionLoss; } else if (returnKind == ReturnKind.ReturnValue) { ProcessParam(info, memberInfo, func.elemdescFunc, retTypeConverter, methodBuilder, 0, "", false, false); isConversionLoss |= retTypeConverter.IsConversionLoss; } // First string is the method name so offset by one String[] saNames = info.RefTypeInfo.GetNames(func.memid, cParams + 1); // // Process parameters // int paramIndex = 0; for (int n = 0; n < cParamsIter; ++n) { ElemDesc elem = func.GetElemDesc(n); // Skip LCID if (elem.paramdesc.IsLCID) continue; // Skip the return parameter if (returnKind == ReturnKind.RetValParameter && n == retArgId) continue; bool isOptionalArg = (n >= firstOptArg && n <= lastOptArg); bool isVarArg = (n == varArg); ProcessParam(info, memberInfo, elem, paramTypeConverters[paramIndex], methodBuilder, paramIndex + 1, saNames[n + 1], isVarArg, isOptionalArg); isConversionLoss |= paramTypeConverters[paramIndex].IsConversionLoss; paramIndex++; } // // Emit TypeLibFuncAttribute if necessary // if (func.wFuncFlags != 0) methodBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForTypeLibFunc((TypeLibFuncFlags)func.wFuncFlags)); // // Handle DefaultMemberAttribute // if (!memberInfo.IsProperty && memberInfo.DispId == WellKnownDispId.DISPID_VALUE) { // DIFF: TlbImpv1 use the type library name while we use the unique name info.ConverterInfo.SetDefaultMember(info.TypeBuilder, methodBuilder.Name); } return methodBuilder; }
/// <summary> /// Is this function a NewEnum function with the right parameters and DISPID? /// </summary> public static bool IsNewEnumFunc(ConverterInfo info, TypeInfo typeInfo, FuncDesc func, int index) { // // Support GUID_DispIdOverride // int dispid = func.memid; GetOverrideDispId(info, typeInfo, index, InterfaceMemberType.Method, ref dispid, false); if (dispid == WellKnownDispId.DISPID_NEWENUM) { TypeDesc typeDesc = null; if (func.funckind == TypeLibTypes.Interop.FUNCKIND.FUNC_DISPATCH) { if (func.IsPropertyGet || func.IsFunc) { if (func.cParams == 0) { typeDesc = func.elemdescFunc.tdesc; } else if (info.TransformDispRetVal && func.cParams == 1 && func.GetElemDesc(0).paramdesc.IsRetval) { typeDesc = func.GetElemDesc(0).tdesc.lptdesc; } } } else if (func.funckind == TypeLibTypes.Interop.FUNCKIND.FUNC_PUREVIRTUAL) { if ((func.cParams == 1) && (func.IsPropertyGet || func.IsFunc) && (func.GetElemDesc(0).paramdesc.IsRetval) && (func.GetElemDesc(0).tdesc.vt == (int)VarEnum.VT_PTR)) { typeDesc = func.GetElemDesc(0).tdesc.lptdesc; } } if (typeDesc != null) { if (typeDesc.vt == (int)VarEnum.VT_UNKNOWN || typeDesc.vt == (int)VarEnum.VT_DISPATCH) { // The member returns an IUnknown* or an IDispatch* which is valid. return true; } else if (typeDesc.vt == (int)VarEnum.VT_PTR) { typeDesc = typeDesc.lptdesc; if (typeDesc.vt == (int)VarEnum.VT_USERDEFINED) { TypeInfo type = typeInfo.GetRefTypeInfo(typeDesc.hreftype); using (TypeAttr attr = type.GetTypeAttr()) { if (attr.Guid == WellKnownGuids.IID_IUnknown || attr.Guid == WellKnownGuids.IID_IDispatch || attr.Guid == WellKnownGuids.IID_IEnumVARIANT) { return true; } } } } } } return false; }