Exemple #1
0
        private static MethodBuilder CreateMethodInternal(InterfaceInfo info, VarDesc var, InterfaceMemberInfo memberInfo, CreateMethodMode mode, ref bool isConversionLoss)
        {
            bool convertingNewEnumMember = IsNewEnumDispatchProperty(info.ConverterInfo, info.RefTypeInfo, var, memberInfo.Index);

            Type retType = null;
            Type[] paramTypes = null;
            TypeConverter propTypeConverter = new TypeConverter(info.ConverterInfo, info.RefTypeInfo, var.elemdescVar.tdesc, ConversionType.ReturnValue);

            isConversionLoss |= propTypeConverter.IsConversionLoss;
            Type propType = propTypeConverter.ConvertedType;

            int propTypeParamIndex = 0;  // The index of the function parameter that represents the property type
            if (memberInfo.InvokeKind == TypeLibTypes.Interop.INVOKEKIND.INVOKE_PROPERTYGET)
            {
                retType = propType;
                paramTypes = new Type[] { };
                propTypeParamIndex = 0;     // for Type get_XXX(). Index = 0
            }
            else if (memberInfo.InvokeKind == TypeLibTypes.Interop.INVOKEKIND.INVOKE_PROPERTYPUT)
            {
                retType = typeof(void);
                paramTypes = new Type[] { propType };
                propTypeParamIndex = 1;     // for void set_XXX(Type arg). Index = 1
            }
            else
            {
                Debug.Assert(false, "Should not get here!");
            }

            MethodBuilder methodBuilder = CreateMethodCore(info, memberInfo, convertingNewEnumMember, mode, true, retType, paramTypes);
            ProcessParam(info, memberInfo, var.elemdescVar, propTypeConverter, methodBuilder, propTypeParamIndex, "", false, false);

            return methodBuilder;
        }
Exemple #2
0
        private static MethodBuilder CreateMethodCore(InterfaceInfo info, InterfaceMemberInfo memberInfo, bool isNewEnumMember, CreateMethodMode mode, bool isStandardOleCall, Type retType, Type[] paramTypes)
        {
            //
            // vtbl gap support. We only emit vtbl gap for non dispinterfaces
            //
            if (!info.IsCoClass && !info.RefTypeAttr.IsDispatch && mode != CreateMethodMode.EventDelegateMode)
            {
                int pointerSize = GetPointerSize(info.RefTypeInfo);

                int slot = memberInfo.RefFuncDesc.oVft / pointerSize;
                if (slot != info.CurrentSlot)
                {
                    // Make sure slot numbers are monotonically increasing.
                    if (slot < info.CurrentSlot)
                    {
                        info.ConverterInfo.ReportEvent(
                            WarningCode.Wrn_BadVTable,
                            Resource.FormatString("Wrn_BadVTable",
                                new object[] { memberInfo.UniqueName, info.TypeBuilder.FullName, info.ConverterInfo.ModuleBuilder.Name })
                                );

                        throw new TlbImpInvalidTypeConversionException(info.RefTypeInfo);
                    }

                    int gap = slot - info.CurrentSlot;
                    string vtblGapFuncName;
                    if (gap == 1)
                        vtblGapFuncName = string.Format(VTBL_GAP_FORMAT_1, info.CurrentSlot);
                    else
                        vtblGapFuncName = string.Format(VTBL_GAP_FORMAT_N, info.CurrentSlot, gap);

                    MethodBuilder vtblFunc = info.TypeBuilder.DefineMethod(
                        vtblGapFuncName,
                        MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName | MethodAttributes.Abstract);
                    vtblFunc.SetImplementationFlags(MethodImplAttributes.Runtime);

                    info.CurrentSlot = slot;
                }

                ++info.CurrentSlot;
            }

            MethodAttributes attributes = MethodAttributes.Public | MethodAttributes.Virtual;

            string methodName;

            // Determine the name & attributes
            if (mode == CreateMethodMode.EventDelegateMode)
            {
                methodName = INVOKE_METHOD;
            }
            else
            {
                methodName = info.GenerateUniqueMemberName(memberInfo.RecommendedName, paramTypes, MemberTypes.Method);

                // Update the name so that we can know the unique member name in the interface later in override
                if (!info.IsCoClass)
                {
                    memberInfo.UpdateUniqueName(methodName);
                }

                attributes |= System.Reflection.MethodAttributes.HideBySig | System.Reflection.MethodAttributes.NewSlot;
                if (!info.IsCoClass)
                {
                    attributes |= System.Reflection.MethodAttributes.Abstract;
                }
            }

            // Is property? If so, add SpecialName to attributes
            if (!isNewEnumMember && memberInfo.InvokeKind != TypeLibTypes.Interop.INVOKEKIND.INVOKE_FUNC)
                attributes |= MethodAttributes.SpecialName;

            MethodBuilder methodBuilder = info.TypeBuilder.DefineMethod(
                methodName,
                attributes,
                CallingConventions.ExplicitThis | CallingConventions.HasThis,
                retType,
                paramTypes);

            // Set implementation flags
            MethodImplAttributes implAttributes;
            if (mode == CreateMethodMode.EventDelegateMode)
                implAttributes = MethodImplAttributes.Managed | MethodImplAttributes.Runtime;
            else
                implAttributes = MethodImplAttributes.InternalCall | MethodImplAttributes.Runtime;

            if (!isStandardOleCall)
                implAttributes |= MethodImplAttributes.PreserveSig;

            methodBuilder.SetImplementationFlags(implAttributes);

            // Add handling for [id(...)] if necessary
            if (info.EmitDispId || memberInfo.DispIdIsOverridden)
            {
                if (info.IsCoClass && !info.IsDefaultInterface)
                {
                    // Skip non-default interfaces in coclass
                }
                else
                {
                    methodBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForDispId(memberInfo.DispId));
                }
            }

            if (memberInfo.PropertyInfo != null && memberInfo.PropertyInfo.HasInvalidGetter)
            {
                info.ConverterInfo.ReportEvent(
                    WarningCode.Wrn_PropgetWithoutReturn,
                    Resource.FormatString("Wrn_PropgetWithoutReturn",
                        memberInfo.PropertyInfo.RecommendedName,
                        info.TypeBuilder.FullName
                        )
                );
            }

            if (memberInfo.IsProperty && !isNewEnumMember)
            {
                info.PropertyInfo.SetPropertyInfo(memberInfo, methodBuilder);
            }

            // Add a .override instruction for the method for coclass
            if (info.IsCoClass)
            {
                Debug.Assert(info.CurrentImplementingInterface != null);

                using (TypeAttr implementingInterfaceAttr = info.CurrentImplementingInterface.GetTypeAttr())
                {
                    IConvBase convBase = info.ConverterInfo.GetInterface(info.CurrentImplementingInterface, implementingInterfaceAttr);
                    Type interfaceType = convBase.RealManagedType;

                    // Type.GetMethod(Name, ParamList) actually requires all the parameters be loaded (thus created).
                    // Type.GetMethod(Name) won't have this problem.
                    // We can workaround this limitation by having the coclass created after all the other types

                    // Must use UniqueName because it is the right name on the interface.
                    // We should use exact match here.
                    MethodInfo methodInfo = interfaceType.GetMethod(memberInfo.UniqueName,
                        BindingFlags.ExactBinding | BindingFlags.Public | BindingFlags.Instance, null, paramTypes, null);

                    if (methodInfo == null)
                    {
                        string expectedPrototypeString = FormatMethodPrototype(retType, memberInfo.UniqueName, paramTypes);
                        string msg = Resource.FormatString("Err_OverridedMethodNotFoundInImplementedInterface",
                                        new object[] { expectedPrototypeString, interfaceType.FullName,
                                            info.TypeBuilder.FullName, info.TypeBuilder.Assembly.FullName });
                        throw new TlbImpGeneralException(msg, ErrorCode.Err_OverridedMethodNotFoundInImplementedInterface);
                    }

                    info.TypeBuilder.DefineMethodOverride(methodBuilder, methodInfo);
                }
            }

            return methodBuilder;
        }
Exemple #3
0
        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;
        }
Exemple #4
0
        private static void CreateMethod(InterfaceInfo info, InterfaceMemberInfo memberInfo, CreateMethodMode mode)
        {
            MethodBuilder method = null;
            bool isConversionLoss = false;
            switch (memberInfo.MemberType)
            {
                // Handle normal methods as well as accesors for properties
                case InterfaceMemberType.Method:
                    method = CreateMethodInternal(info, memberInfo.RefFuncDesc, memberInfo, mode, ref isConversionLoss);
                    break;

                // Handle properties in dispatch interfaces defined as variables
                case InterfaceMemberType.Variable:
                    method = CreateMethodInternal(info, memberInfo.RefVarDesc, memberInfo, mode, ref isConversionLoss);
                    break;

                default:
                    Debug.Assert(false);
                    break;
            }

            if (method == null)
                return;

            if (isConversionLoss)
            {
                string msg = Resource.FormatString(
                    "Wrn_UnconvertableArgs",
                    info.TypeBuilder.FullName,
                    method.Name);

                info.ConverterInfo.ReportEvent(WarningCode.Wrn_UnconvertableArgs, msg);
            }

            info.IsConversionLoss |= isConversionLoss;
        }