示例#1
0
        /// <summary>
        /// Get the event delegate for specified method in the source interface. Create a new one if necessary
        /// </summary>
        /// <param name="index">Function index</param>
        /// <returns>The delegate type</returns>
        public Type GetEventDelegate(InterfaceMemberInfo memberInfo)
        {
            TypeInfo type = memberInfo.RefTypeInfo;

            using (TypeAttr attr = type.GetTypeAttr())
            {
                // Create m_delegateTypes on demand
                if (m_delegateTypes == null)
                {
                    m_delegateTypes = new Dictionary <InterfaceMemberInfo, Type>();
                }

                //
                // Check if we already have a delegate type for method n
                //
                if (!m_delegateTypes.ContainsKey(memberInfo))
                {
                    //
                    // If not, create a new delegate
                    //
                    FuncDesc func = type.GetFuncDesc(memberInfo.Index);

                    string eventName    = type.GetDocumentation(func.memid);
                    string delegateName = m_info.GetRecommendedManagedName(m_convInterface.RefTypeInfo, ConvType.Interface, true) + "_" + type.GetDocumentation(func.memid) + "EventHandler";

                    // Deal with name collisions
                    delegateName = m_info.GetUniqueManagedName(delegateName);

                    TypeBuilder delegateTypeBuilder = m_info.ModuleBuilder.DefineType(
                        delegateName,
                        TypeAttributes.Public | TypeAttributes.Sealed,
                        typeof(MulticastDelegate)
                        );

                    // Create constructor for the delegate
                    ConstructorBuilder delegateCtorBuilder = delegateTypeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, new Type[] { typeof(Object), typeof(UIntPtr) });
                    delegateCtorBuilder.SetImplementationFlags(MethodImplAttributes.Runtime | MethodImplAttributes.Managed);

                    // Create methods for the delegate
                    InterfaceInfo interfaceInfoForDelegate = new InterfaceInfo(m_info, delegateTypeBuilder, false, type, attr, false, true);
                    interfaceInfoForDelegate.AllowNewEnum = !m_convInterface.ImplementsIEnumerable;
                    ConvCommon.CreateMethodForDelegate(interfaceInfoForDelegate, func, memberInfo.Index);

                    // Emit ComVisibleAttribute(false)
                    delegateTypeBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForComVisible(false));

                    // Emit TypeLibTypeAttribute(TypeLibTypeFlags.FHidden) to hide it from object browser in VB
                    delegateTypeBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForTypeLibType(TypeLibTypeFlags.FHidden));

                    // Create the delegate
                    m_delegateTypes[memberInfo] = delegateTypeBuilder.CreateType();
                }
            }

            return(m_delegateTypes[memberInfo]);
        }
示例#2
0
        /// <summary>
        /// Implement methods in parent interfaces
        /// </summary>
        private void HandleParentInterface(TypeInfo type, bool bSource, ref bool isConversionLoss, bool isDefault)
        {
            using (TypeAttr attr = type.GetTypeAttr())
            {
                InterfaceInfo interfaceInfo = new InterfaceInfo(m_info, m_typeBuilder, ConvCommon.InterfaceSupportsDispatch(type, attr), type, attr, true, bSource, type);
                interfaceInfo.IsDefaultInterface = isDefault;

                if (bSource)
                {
                    // When adding override methods to the interface, we need to use the event interface for source interfaces
                    ConvCommon.CreateEventInterfaceCommon(interfaceInfo);
                }
                else
                {
                    ConvCommon.CreateInterfaceCommon(interfaceInfo);
                }

                isConversionLoss |= interfaceInfo.IsConversionLoss;
            }
        }
示例#3
0
        /// <summary>
        /// Create the event interface
        /// </summary>
        public override void OnCreate()
        {
            if (m_type != null) return;

            string name = m_convInterface.ManagedName;

            m_convInterface.Create();

            using (TypeAttr attr = m_convInterface.RefTypeInfo.GetTypeAttr())
            {

                //
                // Emit attributes
                //

                //
                // Emit [ComEventInterfaceAttribute(...)]
                //
                ConstructorInfo ctorComEventInterface = typeof(ComEventInterfaceAttribute).GetConstructor(
                    BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
                    null,
                    new Type[] { typeof(Type), typeof(Type) },
                    null);

                //
                // Build the blob manually before creating the event interface / provider types.
                // We only need to give the name of the types, in order to simplify creation logic and avoid dependency
                //
                CustomAttributeBlobBuilder blobBuilder = new CustomAttributeBlobBuilder();

                string eventInterfaceFullyQualifiedName = name;
                if (m_convInterface.ConvScope == ConvScope.External)
                    eventInterfaceFullyQualifiedName = m_convInterface.ManagedType.AssemblyQualifiedName;

                blobBuilder.AddFixedArg(eventInterfaceFullyQualifiedName);                      // source interface

                // Handle event provider name generation collision scenario
                m_eventProviderName = m_info.GetUniqueManagedName(
                    m_info.GetRecommendedManagedName(m_convInterface.RefTypeInfo, ConvType.Interface, true) + "_EventProvider");

                blobBuilder.AddFixedArg(m_eventProviderName);   // corresponding event provider
                m_typeBuilder.SetCustomAttribute(ctorComEventInterface, blobBuilder.GetBlob());

                //
                // Emit ComVisibleAttribute(false)
                //
                m_typeBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForComVisible(false));

                //
                // Emit TypeLibTypeAttribute for TYPEFLAG_FHIDDEN
                //
                m_typeBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForTypeLibType(TypeLibTypeFlags.FHidden));

                bool isConversionLoss = false;

                //
                // Verify if the type has any properties
                //
                Type interfaceType = m_convInterface.RealManagedType;
                if (interfaceType.GetProperties().Length > 0)
                {
                    // Emit a warning and we'll skip the properties
                    m_info.ReportEvent(
                        WarningCode.Wrn_NoPropsInEvents,
                        Resource.FormatString("Wrn_NoPropsInEvents", RefTypeInfo.GetDocumentation()));

                    isConversionLoss = true;
                }

                //
                // Create event interface
                //

                InterfaceInfo eventInterfaceInfo = new InterfaceInfo(m_info, m_typeBuilder, false, m_convInterface.RefTypeInfo, attr, false, true);

                ConvCommon.CreateEventInterfaceCommon(eventInterfaceInfo);
                isConversionLoss |= eventInterfaceInfo.IsConversionLoss;

                //
                // Emit ComConversionLossAttribute if necessary
                //
                if (eventInterfaceInfo.IsConversionLoss)
                {
                    m_typeBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForComConversionLoss());
                }
            }

            m_type = m_typeBuilder.CreateType();
        }
示例#4
0
        /// <summary>
        /// Implement methods in parent interfaces
        /// </summary>
        private void HandleParentInterface(TypeInfo type, bool bSource, ref bool isConversionLoss, bool isDefault)
        {
            using (TypeAttr attr = type.GetTypeAttr())
            {
                InterfaceInfo interfaceInfo = new InterfaceInfo(m_info, m_typeBuilder, ConvCommon.InterfaceSupportsDispatch(type, attr), type, attr, true, bSource, type);
                interfaceInfo.IsDefaultInterface = isDefault;

                if (bSource)
                    // When adding override methods to the interface, we need to use the event interface for source interfaces
                    ConvCommon.CreateEventInterfaceCommon(interfaceInfo);
                else
                    ConvCommon.CreateInterfaceCommon(interfaceInfo);

                isConversionLoss |= interfaceInfo.IsConversionLoss;
            }
        }
示例#5
0
 public PropertyInfo(InterfaceInfo info)
 {
     m_info = info;
     Debug.Assert(info != null);
 }
示例#6
0
 public PropertyInfo(InterfaceInfo info)
 {
     m_info = info;
     Debug.Assert(info != null);
 }
示例#7
0
 public static int GetIndexOfFirstMethod(InterfaceInfo info)
 {
     TypeInfo type = info.RefTypeInfo;
     TypeAttr attr = info.RefTypeAttr;
     return GetIndexOfFirstMethod(type, attr);
 }
示例#8
0
 public static void CreateMethodForInterface(InterfaceInfo info, InterfaceMemberInfo memberInfo)
 {
     CreateMethod(info, memberInfo, CreateMethodMode.InterfaceMethodMode);
 }
示例#9
0
        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);
                }
            }
        }
示例#10
0
        /// <summary>
        /// Create methods using the InterfaceInfo
        /// </summary>
        private static void CreateMethods(InterfaceInfo info)
        {
            //
            // Stop if info is already IUnknown. Doesn't stop for IDispatch because we want to convert the members of IDispatch
            //
            if (WellKnownGuids.IID_IUnknown == info.RefTypeAttr.Guid)
                return;

            //
            // Create methods for parent interface. We need to duplicate them.
            //
            if (info.RefTypeAttr.cImplTypes == 1)
            {
                TypeInfo parent = info.RefTypeInfo.GetRefType(0);
                using (TypeAttr parentAttr = parent.GetTypeAttr())
                {
                    if (WellKnownGuids.IID_IUnknown != parentAttr.Guid && WellKnownGuids.IID_IDispatch != parentAttr.Guid)
                    {
                        InterfaceInfo parentInterfaceInfo = new InterfaceInfo(info.ConverterInfo, info.TypeBuilder, info.EmitDispId, parent, parentAttr, info.IsCoClass, info.IsSource, info.CurrentImplementingInterface);
                        parentInterfaceInfo.IsDefaultInterface = info.IsDefaultInterface;
                        parentInterfaceInfo.CurrentSlot = info.CurrentSlot;
                        ConvCommon.CreateInterfaceCommon(parentInterfaceInfo);
                        info.CurrentSlot = parentInterfaceInfo.CurrentSlot;

                        /*
                        info.PushType(parent, parentAttr);
                        CreateMethods(info);
                        info.PopType();
                         */
                    }
                    else
                    {
                        // Initialize v-table slot for IUnknown/IDispatch
                        info.CurrentSlot = parentAttr.cbSizeVft / parentAttr.cbSizeInstance;
                    }
                }
            }

            //
            // Create methods for normal methods & property accessors
            //
            IConvInterface convInterface = (IConvInterface)info.ConverterInfo.GetTypeRef(ConvType.Interface, info.RefTypeInfo);

            info.AllowNewEnum = !convInterface.ImplementsIEnumerable;

            foreach (InterfaceMemberInfo memberInfo in convInterface.AllMembers)
            {
                CreateMethodForInterface(info, memberInfo);
            }

            //
            // Generate the properties
            //
            info.PropertyInfo.GenerateProperties();
        }
示例#11
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;
        }
示例#12
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;
        }
示例#13
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;
        }
示例#14
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;
        }
示例#15
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="info">The interfaceInfo</param>
        /// <param name="isCreateEventInterface">
        /// True if we are creating event interface, false if creating a normal interface
        /// </param>
        public static void CreateInterfaceCommonInternal(InterfaceInfo info, bool isCreateEventInterface)
        {
            bool bIsIDispatchBasedOnInterface = false;

            // I finally figured this part out
            // For dual interfaces, it has a "funky" TKIND_DISPATCH|TKIND_DUAL interface with a parter of TKIND_INTERFACE|TKIND_DUAL interface
            // The first one is pretty bad and has duplicated all the interface members of its parent, which is not we want
            // We want the second v-table interface
            // So, if we indeed has seen this kind of interface, prefer its partner
            // However, we should not blindly get the partner because those two interfaces partners with each other
            // So we need to first test to see if the interface is both dispatch & dual, and then get its partner interface
            if (info.RefTypeAttr.IsDual && info.RefTypeAttr.IsDispatch)
            {
                TypeInfo typeReferencedType = info.RefTypeInfo.GetRefTypeNoComThrow();
                if (typeReferencedType != null)
                {
                    using (TypeAttr attrReferencedType = typeReferencedType.GetTypeAttr())
                    {
                        // Either eliminate the type stack stuff or put PropertyInfo stuff elsewhere
                        // We cannot keep properties on the same interface info as it will cause problems
                        info.PushType(typeReferencedType, attrReferencedType);
                        if (isCreateEventInterface)
                            CreateEventMethods(info);
                        else
                            CreateMethods(info);
                        info.PopType();
                        bIsIDispatchBasedOnInterface = true;
                    }
                }
            }

            if (!bIsIDispatchBasedOnInterface)
            {
                if (isCreateEventInterface)
                    CreateEventMethods(info);
                else
                    CreateMethods(info);
            }
        }
示例#16
0
 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);
 }
示例#17
0
 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);
         }
     }
 }
示例#18
0
        /// <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();
        }
示例#19
0
 private static bool IsPreserveSigOverride(InterfaceInfo interfaceInfo, int index)
 {
     // Check rule engine
     if (interfaceInfo.ConverterInfo.Settings.m_ruleSet != null)
     {
         ICategory functionCategory = FunctionCategory.GetInstance();
         FunctionInfoMatchTarget target =
             new FunctionInfoMatchTarget(interfaceInfo.RefTypeInfo, index);
         AbstractActionManager actionManager = RuleEngine.GetActionManager();
         List<Rule> preserveSigRules = interfaceInfo.ConverterInfo.Settings.m_ruleSet.GetRule(
             functionCategory, PreserveSigActionDef.GetInstance(),
             target);
         if (preserveSigRules.Count != 0)
             return true;
     }
     return false;
 }
示例#20
0
        /// <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;
        }
示例#21
0
        /// <summary>
        /// Process parameters and apply attributes
        /// </summary>
        private static void ProcessParam(InterfaceInfo info, InterfaceMemberInfo memInfo, ElemDesc desc,
            TypeConverter converter, MethodBuilder methodBuilder, int index, string strname,
            bool isVarArg, bool isOptionalArg)
        {
            ParamDesc param = desc.paramdesc;
            ParameterAttributes attributes = ParameterAttributes.None;
            if (converter.ParameterAttributesOverride != ParameterAttributes.None)
            {
                attributes = converter.ParameterAttributesOverride;
            }
            else
            {
                //
                // Determine in/out/opt
                // Don't emit [In], [Out] for return type
                //
                if (index != 0)
                {
                    // Always emit in/out information according to type library
                    if (param.IsIn)
                    {
                        attributes |= ParameterAttributes.In;
                    }

                    if (param.IsOut)
                    {
                        attributes |= ParameterAttributes.Out;
                    }

                    if (param.IsOpt || isOptionalArg)
                    {
                        attributes |= ParameterAttributes.Optional;
                    }
                }
            }

            //
            // Define the parameter
            //
            ParameterBuilder parameterBuilder = methodBuilder.DefineParameter(index, attributes, strname);

            //
            // Apply MarshalAs attribute
            //
            converter.ApplyAttributes(parameterBuilder);

            //
            // Support for vararg
            //
            if (isVarArg)
            {
                parameterBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForParamArray());
            }

            //
            // Support for default value
            //
            if (desc.paramdesc.HasDefault && desc.paramdesc.lpVarValue != IntPtr.Zero)
                SetDefaultValue(desc, converter.ConvertedType, parameterBuilder);
        }
示例#22
0
        /// <summary>
        /// Generate properties for Functions
        /// </summary>
        public void GenerateProperty(InterfaceInfo info, TypeBuilder typebuilder)
        {
            // Generate property using unique name
            string uniqueName = info.GenerateUniqueMemberName(
                m_propertyInfo.RecommendedName,
                null,
                MemberTypes.Property);

            //
            // Convert the signature
            //
            Type[] paramTypes = null;
            Type retType = null;

            if (m_propertyInfo.Kind == PropertyKind.VarProperty)
            {
                // Converting variable to property. There are no parameters at all
                TypeConverter typeConverter = m_propertyInfo.GetPropertyTypeConverter(info.ConverterInfo, info.RefTypeInfo);
                info.IsConversionLoss |= typeConverter.IsConversionLoss;
                retType = typeConverter.ConvertedType;
            }
            else
            {
                // If /preservesig is specified, do not generate property, and only
                // the getter and setter functions are enough.
                // Property requires that the property getter must return the real property value, and the first parameter of
                // the setter must be the property value. While, the /preservesig switch will change the prototype of the setters and
                // getters, which is different from what the compiler expected.
                // So we do not support the Property if the /preservesig is specified.
                if (info.ConverterInfo.Settings.m_isPreserveSig &&
                    (m_propertyInfo.BestFuncDesc != null && !m_propertyInfo.BestFuncDesc.IsDispatch))
                {
                    if (TlbImpCode.TlbImpCode.s_Options.m_bVerboseMode)
                        FormattedOutput.Output.WriteInfo(Resource.FormatString("Msg_PropertyIsOmitted",
                                                                               m_propertyInfo.RecommendedName,
                                                                               m_propertyInfo.RefTypeInfo.GetDocumentation()),
                                                         MessageCode.Msg_PropertyIsOmitted);
                    return;
                }

                // Converting propget/propput/propputref functions to property.
                TypeConverter typeConverter = m_propertyInfo.GetPropertyTypeConverter(info.ConverterInfo, info.RefTypeInfo);
                retType = typeConverter.ConvertedType;
                info.IsConversionLoss |= typeConverter.IsConversionLoss;

                FuncDesc bestFuncDesc = m_propertyInfo.BestFuncDesc;

                // if we have a [vararg]
                int varArg, firstOptArg, lastOptArg;

                if (bestFuncDesc.cParamsOpt == -1)
                    ConvCommon.CheckForOptionalArguments(info.ConverterInfo, bestFuncDesc, out varArg, out firstOptArg, out lastOptArg);
                else
                    varArg = -1;

                var paramTypeList = new List<Type>();

                // Find the index part of the property's signature
                bool skipLastRetVal = (bestFuncDesc.IsPropertyPut || bestFuncDesc.IsPropertyPutRef);
                for (int i = 0; i < bestFuncDesc.cParams; ++i)
                {
                    ElemDesc elemDesc = bestFuncDesc.GetElemDesc(i);
                    ParamDesc paramDesc = elemDesc.paramdesc;

                    // Skip LCID/RetVal
                    if (paramDesc.IsLCID || paramDesc.IsRetval)
                        continue;

                    // Skip the "new value" parameter for putters
                    if (skipLastRetVal)
                    {
                        skipLastRetVal = false;
                        continue;
                    }

                    ConversionType conversionType;
                    if (i == varArg)
                        conversionType = ConversionType.VarArgParameter;
                    else
                        conversionType = ConversionType.Parameter;

                    TypeConverter paramTypeConverter = new TypeConverter(info.ConverterInfo, info.RefTypeInfo, elemDesc.tdesc, conversionType);
                    info.IsConversionLoss |= paramTypeConverter.IsConversionLoss;
                    paramTypeList.Add(paramTypeConverter.ConvertedType);
                }

                paramTypes = paramTypeList.ToArray();
            }

            // Define the property
            PropertyBuilder propertyBuilder = typebuilder.DefineProperty(uniqueName, PropertyAttributes.HasDefault, retType, paramTypes);

            if (info.IsCoClass && !info.IsDefaultInterface)
            {
                // Skip non-default interfaces / implemented interfaces (when we are creating coclass)
            }
            else
            {
                // Emit dispatch id attribute
                propertyBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForDispId(m_propertyInfo.DispId));
            }

            // We don't need to emit MarshalAs for properties because the get/set functions should already have them
            // Emitting MarshalAs for property will hang up CLR!!
            if (m_methodGet != null)
            {
                propertyBuilder.SetGetMethod(m_methodGet);
            }

            // Has both propPut & propPutRef?
            if (m_methodPut != null && m_methodPutRef != null)
            {
                propertyBuilder.SetSetMethod(m_methodPutRef);
                propertyBuilder.AddOtherMethod(m_methodPut);
            }
            else
            {
                if (m_methodPut != null)
                {
                    propertyBuilder.SetSetMethod(m_methodPut);
                }
                else if (m_methodPutRef != null)
                {
                    propertyBuilder.SetSetMethod(m_methodPutRef);
                }
            }

            //
            // Handle DefaultMemberAttribute
            //
            if (m_propertyInfo.DispId == WellKnownDispId.DISPID_VALUE)
            {
                // DIFF: TlbImpv1 use the type library name while we use the unique name
                info.ConverterInfo.SetDefaultMember(info.TypeBuilder, uniqueName);
            }

            // Handle alias information
            ConvCommon.HandleAlias(info.ConverterInfo, info.RefTypeInfo, m_propertyInfo.PropertyTypeDesc, propertyBuilder);
        }
示例#23
0
 /// <summary>
 /// Create methods for a event interface
 /// </summary>
 /// <param name="eventInterfaceInfo">
 /// InterfaceInfo for the source interface, including the type builder for the event interface. 
 /// Note that you can pass whatever type builder you want.
 /// </param>
 public static void CreateEventInterfaceCommon(InterfaceInfo eventInterfaceInfo)
 {
     CreateInterfaceCommonInternal(eventInterfaceInfo, true);
 }
示例#24
0
        /// <summary>
        /// Create the event interface
        /// </summary>
        public override void OnCreate()
        {
            if (m_type != null)
            {
                return;
            }

            string name = m_convInterface.ManagedName;

            m_convInterface.Create();

            using (TypeAttr attr = m_convInterface.RefTypeInfo.GetTypeAttr())
            {
                //
                // Emit attributes
                //

                //
                // Emit [ComEventInterfaceAttribute(...)]
                //
                ConstructorInfo ctorComEventInterface = typeof(ComEventInterfaceAttribute).GetConstructor(
                    BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
                    null,
                    new Type[] { typeof(Type), typeof(Type) },
                    null);

                //
                // Build the blob manually before creating the event interface / provider types.
                // We only need to give the name of the types, in order to simplify creation logic and avoid dependency
                //
                CustomAttributeBlobBuilder blobBuilder = new CustomAttributeBlobBuilder();

                string eventInterfaceFullyQualifiedName = name;
                if (m_convInterface.ConvScope == ConvScope.External)
                {
                    eventInterfaceFullyQualifiedName = m_convInterface.ManagedType.AssemblyQualifiedName;
                }

                blobBuilder.AddFixedArg(eventInterfaceFullyQualifiedName);                      // source interface

                // Handle event provider name generation collision scenario
                m_eventProviderName = m_info.GetUniqueManagedName(
                    m_info.GetRecommendedManagedName(m_convInterface.RefTypeInfo, ConvType.Interface, true) + "_EventProvider");

                blobBuilder.AddFixedArg(m_eventProviderName);   // corresponding event provider
                m_typeBuilder.SetCustomAttribute(ctorComEventInterface, blobBuilder.GetBlob());

                //
                // Emit ComVisibleAttribute(false)
                //
                m_typeBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForComVisible(false));

                //
                // Emit TypeLibTypeAttribute for TYPEFLAG_FHIDDEN
                //
                m_typeBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForTypeLibType(TypeLibTypeFlags.FHidden));

                bool isConversionLoss = false;

                //
                // Verify if the type has any properties
                //
                Type interfaceType = m_convInterface.RealManagedType;
                if (interfaceType.GetProperties().Length > 0)
                {
                    // Emit a warning and we'll skip the properties
                    m_info.ReportEvent(
                        WarningCode.Wrn_NoPropsInEvents,
                        Resource.FormatString("Wrn_NoPropsInEvents", RefTypeInfo.GetDocumentation()));

                    isConversionLoss = true;
                }

                //
                // Create event interface
                //

                InterfaceInfo eventInterfaceInfo = new InterfaceInfo(m_info, m_typeBuilder, false, m_convInterface.RefTypeInfo, attr, false, true);

                ConvCommon.CreateEventInterfaceCommon(eventInterfaceInfo);
                isConversionLoss |= eventInterfaceInfo.IsConversionLoss;

                //
                // Emit ComConversionLossAttribute if necessary
                //
                if (eventInterfaceInfo.IsConversionLoss)
                {
                    m_typeBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForComConversionLoss());
                }
            }

            m_type = m_typeBuilder.CreateType();
        }
示例#25
0
        /// <summary>
        /// Create methods on event interface recursively
        /// </summary>
        /// <param name="eventInterfaceInfo">InterfaceInfo of the event interface</param>
        public static void CreateEventMethods(InterfaceInfo eventInterfaceInfo)
        {
            IConvInterface convInterface = (IConvInterface)eventInterfaceInfo.ConverterInfo.GetInterface(eventInterfaceInfo.RefTypeInfo, eventInterfaceInfo.RefTypeAttr);
            if (convInterface.EventInterface == null)
            {
                convInterface.DefineEventInterface();
            }

            //
            // If we are creating the co-class, create the real event interface first in case it doesn't exist yet
            // Note that as event interface doesn't have inheritance, we'll have to do it outside of CreateEventMethodsInternal
            //
            if (eventInterfaceInfo.IsCoClass)
                convInterface.EventInterface.Create();

            // Then create the methods
            CreateEventMethodsInternal(convInterface.EventInterface, eventInterfaceInfo);
        }
示例#26
0
        /// <summary>
        /// Generate properties for Functions
        /// </summary>
        public void GenerateProperty(InterfaceInfo info, TypeBuilder typebuilder)
        {
            // Generate property using unique name
            string uniqueName = info.GenerateUniqueMemberName(
                m_propertyInfo.RecommendedName,
                null,
                MemberTypes.Property);

            //
            // Convert the signature
            //
            Type[] paramTypes = null;
            Type   retType    = null;

            if (m_propertyInfo.Kind == PropertyKind.VarProperty)
            {
                // Converting variable to property. There are no parameters at all
                TypeConverter typeConverter = m_propertyInfo.GetPropertyTypeConverter(info.ConverterInfo, info.RefTypeInfo);
                info.IsConversionLoss |= typeConverter.IsConversionLoss;
                retType = typeConverter.ConvertedType;
            }
            else
            {
                // If /preservesig is specified, do not generate property, and only
                // the getter and setter functions are enough.
                // Property requires that the property getter must return the real property value, and the first parameter of
                // the setter must be the property value. While, the /preservesig switch will change the prototype of the setters and
                // getters, which is different from what the compiler expected.
                // So we do not support the Property if the /preservesig is specified.
                if (info.ConverterInfo.Settings.m_isPreserveSig &&
                    (m_propertyInfo.BestFuncDesc != null && !m_propertyInfo.BestFuncDesc.IsDispatch))
                {
                    if (TlbImpCode.TlbImpCode.s_Options.m_bVerboseMode)
                    {
                        FormattedOutput.Output.WriteInfo(Resource.FormatString("Msg_PropertyIsOmitted",
                                                                               m_propertyInfo.RecommendedName,
                                                                               m_propertyInfo.RefTypeInfo.GetDocumentation()),
                                                         MessageCode.Msg_PropertyIsOmitted);
                    }
                    return;
                }

                // Converting propget/propput/propputref functions to property.
                TypeConverter typeConverter = m_propertyInfo.GetPropertyTypeConverter(info.ConverterInfo, info.RefTypeInfo);
                retType = typeConverter.ConvertedType;
                info.IsConversionLoss |= typeConverter.IsConversionLoss;

                FuncDesc bestFuncDesc = m_propertyInfo.BestFuncDesc;

                // if we have a [vararg]
                int varArg, firstOptArg, lastOptArg;

                if (bestFuncDesc.cParamsOpt == -1)
                {
                    ConvCommon.CheckForOptionalArguments(info.ConverterInfo, bestFuncDesc, out varArg, out firstOptArg, out lastOptArg);
                }
                else
                {
                    varArg = -1;
                }

                List <Type> paramTypeList = new List <Type>();

                // Find the index part of the property's signature
                bool skipLastRetVal = (bestFuncDesc.IsPropertyPut || bestFuncDesc.IsPropertyPutRef);
                for (int i = 0; i < bestFuncDesc.cParams; ++i)
                {
                    ElemDesc  elemDesc  = bestFuncDesc.GetElemDesc(i);
                    ParamDesc paramDesc = elemDesc.paramdesc;

                    // Skip LCID/RetVal
                    if (paramDesc.IsLCID || paramDesc.IsRetval)
                    {
                        continue;
                    }

                    // Skip the "new value" parameter for putters
                    if (skipLastRetVal)
                    {
                        skipLastRetVal = false;
                        continue;
                    }

                    ConversionType conversionType;
                    if (i == varArg)
                    {
                        conversionType = ConversionType.VarArgParameter;
                    }
                    else
                    {
                        conversionType = ConversionType.Parameter;
                    }

                    TypeConverter paramTypeConverter = new TypeConverter(info.ConverterInfo, info.RefTypeInfo, elemDesc.tdesc, conversionType);
                    info.IsConversionLoss |= paramTypeConverter.IsConversionLoss;
                    paramTypeList.Add(paramTypeConverter.ConvertedType);
                }

                paramTypes = paramTypeList.ToArray();
            }

            // Define the property
            PropertyBuilder propertyBuilder = typebuilder.DefineProperty(uniqueName, PropertyAttributes.HasDefault, retType, paramTypes);

            if (info.IsCoClass && !info.IsDefaultInterface)
            {
                // Skip non-default interfaces / implemented interfaces (when we are creating coclass)
            }
            else
            {
                // Emit dispatch id attribute
                propertyBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForDispId(m_propertyInfo.DispId));
            }

            // We don't need to emit MarshalAs for properties because the get/set functions should already have them
            // Emitting MarshalAs for property will hang up CLR!!
            if (m_methodGet != null)
            {
                propertyBuilder.SetGetMethod(m_methodGet);
            }

            // Has both propPut & propPutRef?
            if (m_methodPut != null && m_methodPutRef != null)
            {
                propertyBuilder.SetSetMethod(m_methodPutRef);
                propertyBuilder.AddOtherMethod(m_methodPut);
            }
            else
            {
                if (m_methodPut != null)
                {
                    propertyBuilder.SetSetMethod(m_methodPut);
                }
                else if (m_methodPutRef != null)
                {
                    propertyBuilder.SetSetMethod(m_methodPutRef);
                }
            }

            //
            // Handle DefaultMemberAttribute
            //
            if (m_propertyInfo.DispId == WellKnownDispId.DISPID_VALUE)
            {
                // DIFF: TlbImpv1 use the type library name while we use the unique name
                info.ConverterInfo.SetDefaultMember(info.TypeBuilder, uniqueName);
            }

            // Handle alias information
            ConvCommon.HandleAlias(info.ConverterInfo, info.RefTypeInfo, m_propertyInfo.PropertyTypeDesc, propertyBuilder);
        }
示例#27
0
        public static void CreateEventMethodsInternal(IConvEventInterface convEventInterface, InterfaceInfo eventInterfaceInfo)
        {
            //
            // Stop if info is already IUnknown. Doesn't stop for IDispatch because we want to convert the members of IDispatch
            //
            if (WellKnownGuids.IID_IUnknown == eventInterfaceInfo.RefTypeAttr.Guid)
                return;

            //
            // Create methods for parent interface. We need to duplicate them.
            //
            if (eventInterfaceInfo.RefTypeAttr.cImplTypes == 1)
            {
                TypeInfo parent = eventInterfaceInfo.RefTypeInfo.GetRefType(0);
                using (TypeAttr parentAttr = parent.GetTypeAttr())
                {
                    if (WellKnownGuids.IID_IUnknown != parentAttr.Guid && WellKnownGuids.IID_IDispatch != parentAttr.Guid)
                    {
                        InterfaceInfo parentInterfaceInfo = new InterfaceInfo(eventInterfaceInfo.ConverterInfo, eventInterfaceInfo.TypeBuilder, eventInterfaceInfo.EmitDispId, parent, parentAttr, eventInterfaceInfo.IsCoClass, eventInterfaceInfo.IsSource, eventInterfaceInfo.CurrentImplementingInterface);
                        parentInterfaceInfo.IsDefaultInterface = eventInterfaceInfo.IsDefaultInterface;
                        parentInterfaceInfo.CurrentSlot = eventInterfaceInfo.CurrentSlot;
                        ConvCommon.CreateEventMethodsInternal(convEventInterface, parentInterfaceInfo);
                        eventInterfaceInfo.CurrentSlot = parentInterfaceInfo.CurrentSlot;

                        /*
                        info.PushType(parent, parentAttr);
                        CreateMethods(info);
                        info.PopType();
                         */
                    }
                    else
                    {
                        // Initialize v-table slot for IUnknown/IDispatch
                        eventInterfaceInfo.CurrentSlot = parentAttr.cbSizeVft / parentAttr.cbSizeInstance;
                    }
                }
            }

            ConverterInfo converterInfo = eventInterfaceInfo.ConverterInfo;
            TypeInfo type = eventInterfaceInfo.RefTypeInfo;

            ModuleBuilder moduleBuilder = eventInterfaceInfo.ConverterInfo.ModuleBuilder;

            TypeAttr attr = eventInterfaceInfo.RefTypeAttr;

            // If we are creating the co-class, create the real event interface first in case it doesn't exist yet
            IConvInterface convInterface = (IConvInterface)converterInfo.GetInterface(type, attr);

            // For every method in the source interface
            foreach (InterfaceMemberInfo memInfo in convInterface.AllMembers)
            {
                if (memInfo.IsProperty) continue;

                FuncDesc func = memInfo.RefFuncDesc;

                // Get/Create the event delegate.
                Type delegateType = convEventInterface.GetEventDelegate(memInfo);

                // Need to use the same name as the source interface, otherwise TCEAdapterGenerator will fail
                string eventName = memInfo.UniqueName;

                MethodAttributes methodAttributes =
                    MethodAttributes.Public | MethodAttributes.HideBySig |
                    MethodAttributes.NewSlot | MethodAttributes.Virtual;
                if (!eventInterfaceInfo.IsCoClass)
                {
                    methodAttributes |= System.Reflection.MethodAttributes.Abstract;
                }

                TypeBuilder eventInterfaceType = eventInterfaceInfo.TypeBuilder;

                Type[] paramTypes = new Type[] { delegateType };

                //
                // Defined add_<Event> method
                // Note: We are passing null into GenerateUniqueMemberName so that add_XXX/remove_XXX doesn't take overloading into
                // account. The reason is that we want to keep the add_XXX/remove_XXX methods aligned with the name of the event,
                // which also doesn't consider overloading
                //
                MethodBuilder addMethodBuilder = eventInterfaceType.DefineMethod(
                    // Generate unique name
                    eventInterfaceInfo.GenerateUniqueMemberName("add_" + eventName, null, MemberTypes.Method),
                    methodAttributes,
                    typeof(void),
                    paramTypes
                    );

                addMethodBuilder.SetImplementationFlags(MethodImplAttributes.Runtime | MethodImplAttributes.Managed | MethodImplAttributes.InternalCall);

                // Do a member override for add_<Event> method if we are creating the method for coclass
                if (eventInterfaceInfo.IsCoClass)
                {
                    Debug.Assert(eventInterfaceInfo.CurrentImplementingInterface != null);

                    Type implementingInterfaceType = convEventInterface.RealManagedType;

                    // It is not possible to have a name conflict in event interface, so always use "add_XXX"
                    MethodInfo methodInfo = implementingInterfaceType.GetMethod("add_" + eventName, paramTypes);
                    eventInterfaceInfo.TypeBuilder.DefineMethodOverride(addMethodBuilder, methodInfo);
                }

                //
                // Define remove_<Event> method
                // Note: We are passing null into GenerateUniqueMemberName so that add_XXX/remove_XXX doesn't take overloading into
                // account. The reason is that we want to keep the add_XXX/remove_XXX methods aligned with the name of the event,
                // which also doesn't consider overloading
                //
                MethodBuilder removeMethodBuilder = eventInterfaceType.DefineMethod(
                    eventInterfaceInfo.GenerateUniqueMemberName("remove_" + eventName, null, MemberTypes.Method),
                    methodAttributes,
                    typeof(void),
                    paramTypes
                    );

                removeMethodBuilder.SetImplementationFlags(MethodImplAttributes.Runtime | MethodImplAttributes.Managed | MethodImplAttributes.InternalCall);

                // Do a member override for remove_<Event> method if we are creating the method for coclass
                if (eventInterfaceInfo.IsCoClass)
                {
                    Debug.Assert(eventInterfaceInfo.CurrentImplementingInterface != null);

                    Type implementingInterfaceType = convEventInterface.RealManagedType;

                    // It is not possible to have a name conflict in event interface, so always use "remove_XXX"
                    MethodInfo methodInfo = implementingInterfaceType.GetMethod("remove_" + eventName, paramTypes);
                    eventInterfaceType.DefineMethodOverride(removeMethodBuilder, methodInfo);
                }

                //
                // Define event
                //
                EventBuilder eventBuilder = eventInterfaceType.DefineEvent(
                    eventInterfaceInfo.GenerateUniqueMemberName(eventName, null, MemberTypes.Event),
                    EventAttributes.None,
                    delegateType);
                eventBuilder.SetAddOnMethod(addMethodBuilder);
                eventBuilder.SetRemoveOnMethod(removeMethodBuilder);
            }
        }
示例#28
0
 /// <summary>
 /// This one should be the entry point as it deals with the funky partner interfaces
 /// </summary>
 /// <param name="info"></param>
 public static void CreateInterfaceCommon(InterfaceInfo info)
 {
     CreateInterfaceCommonInternal(info, false);
 }
示例#29
0
        /// <summary>
        /// Get the event delegate for specified method in the source interface. Create a new one if necessary
        /// </summary>
        /// <param name="index">Function index</param>
        /// <returns>The delegate type</returns>
        public Type GetEventDelegate(InterfaceMemberInfo memberInfo)
        {
            TypeInfo type = memberInfo.RefTypeInfo;
            using (TypeAttr attr = type.GetTypeAttr())
            {
                // Create m_delegateTypes on demand
                if (m_delegateTypes == null)
                {
                    m_delegateTypes = new Dictionary<InterfaceMemberInfo, Type>();
                }

                //
                // Check if we already have a delegate type for method n
                //
                if (!m_delegateTypes.ContainsKey(memberInfo))
                {
                    //
                    // If not, create a new delegate
                    //
                    FuncDesc func = type.GetFuncDesc(memberInfo.Index);

                    string eventName = type.GetDocumentation(func.memid);
                    string delegateName = m_info.GetRecommendedManagedName(m_convInterface.RefTypeInfo, ConvType.Interface, true) + "_" + type.GetDocumentation(func.memid) + "EventHandler";

                    // Deal with name collisions
                    delegateName = m_info.GetUniqueManagedName(delegateName);

                    TypeBuilder delegateTypeBuilder = m_info.ModuleBuilder.DefineType(
                        delegateName,
                        TypeAttributes.Public | TypeAttributes.Sealed,
                        typeof(MulticastDelegate)
                    );

                    // Create constructor for the delegate
                    ConstructorBuilder delegateCtorBuilder = delegateTypeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, new Type[] { typeof(Object), typeof(UIntPtr) });
                    delegateCtorBuilder.SetImplementationFlags(MethodImplAttributes.Runtime | MethodImplAttributes.Managed);

                    // Create methods for the delegate
                    InterfaceInfo interfaceInfoForDelegate = new InterfaceInfo(m_info, delegateTypeBuilder, false, type, attr, false, true);
                    interfaceInfoForDelegate.AllowNewEnum = !m_convInterface.ImplementsIEnumerable;
                    ConvCommon.CreateMethodForDelegate(interfaceInfoForDelegate, func, memberInfo.Index);

                    // Emit ComVisibleAttribute(false)
                    delegateTypeBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForComVisible(false));

                    // Emit TypeLibTypeAttribute(TypeLibTypeFlags.FHidden) to hide it from object browser in VB
                    delegateTypeBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForTypeLibType(TypeLibTypeFlags.FHidden));

                    // Create the delegate
                    m_delegateTypes[memberInfo] = delegateTypeBuilder.CreateType();
                }
            }

            return m_delegateTypes[memberInfo];
        }