コード例 #1
0
ファイル: ConvCommon.cs プロジェクト: dbremner/clrinterop
        /// <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;
        }
コード例 #2
0
ファイル: ConvCommon.cs プロジェクト: dbremner/clrinterop
        /// <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();
        }