/// <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> /// 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(); }