public IConvBase GetStruct(TypeInfo type, TypeAttr attr)
        {
            IConvStruct convStruct = (IConvStruct)GetTypeRef(ConvType.Struct, type);

            convStruct.Create();
            return(convStruct);
        }
Exemple #2
0
 private string GetChangeManagedNameActionResult(TypeInfo typeInfo,
                                                 ConvType convType, string oldName)
 {
     if (Settings.m_ruleSet != null)
     {
         ICategory           category = TypeCategory.GetInstance();
         TypeInfoMatchTarget target   = null;
         using (TypeAttr attr = typeInfo.GetTypeAttr())
         {
             TypeLibTypes.Interop.TYPEKIND kind = attr.typekind;
             target = new TypeInfoMatchTarget(typeInfo.GetContainingTypeLib(), typeInfo, kind);
         }
         AbstractActionManager actionManager   = RuleEngine.GetActionManager();
         List <Rule>           changeNameRules = Settings.m_ruleSet.GetRule(
             category, ChangeManagedNameActionDef.GetInstance(), target);
         if (changeNameRules.Count != 0)
         {
             if (changeNameRules.Count > 1)
             {
                 Output.WriteWarning(Resource.FormatString("Wrn_RuleMultipleMatch",
                                                           ChangeManagedNameActionDef.GetInstance()),
                                     WarningCode.Wrn_RuleMultipleMatch);
             }
             Rule   changeNameRule = changeNameRules[changeNameRules.Count - 1];
             int    namespaceSplit = oldName.LastIndexOf('.');
             string oldNamespace   = "";
             if (namespaceSplit != -1)
             {
                 oldNamespace = oldName.Substring(0, namespaceSplit + 1);
             }
             return(oldNamespace + (changeNameRule.Action as ChangeManagedNameAction).NewName);
         }
     }
     return(oldName);
 }
Exemple #3
0
        private void CreateField(TypeInfo type, TypeAttr attr, VarDesc var, ref bool isConversionLoss)
        {
            TypeDesc      fieldTypeDesc = var.elemdescVar.tdesc;
            TypeConverter typeConverter = new TypeConverter(m_info, type, fieldTypeDesc, ConversionType.Field);
            Type          fieldType     = typeConverter.ConvertedType;
            string        fieldName     = type.GetDocumentation(var.memid);
            FieldBuilder  field         = m_typeBuilder.DefineField(fieldName, fieldType, FieldAttributes.Public);

            typeConverter.ApplyAttributes(field);

            isConversionLoss |= typeConverter.IsConversionLoss;

            //
            // Emit ComConversionLossAttribute for fields if necessary
            //
            if (typeConverter.IsConversionLoss)
            {
                field.SetCustomAttribute(CustomAttributeHelper.GetBuilderForComConversionLoss());

                //
                // Emit Wrn_UnconvertableField warning
                //
                m_info.ReportEvent(
                    WarningCode.Wrn_UnconvertableField,
                    Resource.FormatString("Wrn_UnconvertableField", type.GetDocumentation(), fieldName));
            }

            //
            // Emit TypeLibVarAttribute if necessary
            //
            if (var.wVarFlags != 0)
            {
                field.SetCustomAttribute(CustomAttributeHelper.GetBuilderForTypeLibVar((TypeLibVarFlags)var.wVarFlags));
            }
        }
        public IConvBase GetUnion(TypeInfo type, TypeAttr attr)
        {
            IConvUnion convUnion = (IConvUnion)GetTypeRef(ConvType.Union, type);

            convUnion.Create();
            return(convUnion);
        }
        public IConvBase GetEnum(TypeInfo type, TypeAttr attr)
        {
            IConvEnum convEnum = (IConvEnum)GetTypeRef(ConvType.Enum, type);

            convEnum.Create();
            return(convEnum);
        }
Exemple #6
0
        protected override void OnDefineType()
        {
            TypeInfo typeInfo = RefNonAliasedTypeInfo;

            // Creates the enum type
            m_typeBuilder = ConvCommon.DefineTypeHelper(
                m_info,
                RefTypeInfo,
                RefNonAliasedTypeInfo,
                TypeAttributes.Public | TypeAttributes.Sealed,
                typeof(Enum),
                ConvType.Enum
                );

            // The field must be created here so that TypeBuilder can calculate a hash...
            // Need to create a special field to hold the enum data
            FieldBuilder field = m_typeBuilder.DefineField(
                "value__",
                typeof(Int32),
                FieldAttributes.Public | FieldAttributes.SpecialName);

            // Handle [TypeLibType(...)] if evaluate to non-0
            using (TypeAttr refTypeAttr = RefTypeInfo.GetTypeAttr())
            {
                if (refTypeAttr.wTypeFlags != 0)
                {
                    m_typeBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForTypeLibType((TypeLibTypeFlags)refTypeAttr.wTypeFlags));
                }
            }

            m_info.AddToSymbolTable(RefTypeInfo, ConvType.Enum, this);
            m_info.RegisterType(m_typeBuilder, this);
        }
        public IConvBase GetModule(TypeInfo type, TypeAttr attr)
        {
            IConvModule convModule = (IConvModule)GetTypeRef(ConvType.Module, type);

            convModule.Create();
            return(convModule);
        }
        public IConvBase GetCoClass(TypeInfo type, TypeAttr attr)
        {
            IConvCoClass convCoClass = (IConvCoClass)GetTypeRef(ConvType.CoClass, type);

            convCoClass.Create();
            return(convCoClass);
        }
        // Helpers to perform actual definitions for types.
        public IConvBase GetInterface(TypeInfo type, TypeAttr attr)
        {
            IConvInterface convInterface = (IConvInterface)GetTypeRef(ConvType.Interface, type);

            convInterface.Create();
            return(convInterface);
        }
Exemple #10
0
        protected override void OnDefineType()
        {
            TypeInfo typeInfo = RefNonAliasedTypeInfo;

            m_typeBuilder = ConvCommon.DefineTypeHelper(
                m_info,
                RefTypeInfo,
                RefNonAliasedTypeInfo,
                TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.ExplicitLayout,
                typeof(ValueType),
                ConvType.Union
                );

            // Handle [TypeLibType(...)] if evaluate to non-0
            using (TypeAttr refTypeAttr = RefTypeInfo.GetTypeAttr())
            {
                if (refTypeAttr.wTypeFlags != 0)
                {
                    m_typeBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForTypeLibType((TypeLibTypeFlags)refTypeAttr.wTypeFlags));
                }
            }

            m_info.AddToSymbolTable(RefTypeInfo, ConvType.Union, this);
            m_info.RegisterType(m_typeBuilder, this);
        }
        /// <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]);
        }
        /// <summary>
        /// Build global name table for existing types in the type library
        /// The reason we need to put those names into the table first is that
        /// their name should not be changed because they come from existing types
        /// </summary>
        private void BuildGlobalNameTable()
        {
            m_globalNameTable    = new SortedDictionary <string, string>();
            m_globalManagedNames = new SortedDictionary <string, string>();

            //
            // Traverse each type and add the names into the type. Their names are already in the type library
            // and should not be changed
            //
            int nCount = m_typeLib.GetTypeInfoCount();

            for (int n = 0; n < nCount; ++n)
            {
                try
                {
                    TypeInfo type = m_typeLib.GetTypeInfo(n);
                    using (TypeAttr attr = type.GetTypeAttr())
                    {
                        switch (attr.typekind)
                        {
                        case TYPEKIND.TKIND_COCLASS:
                            // class interface use the original name of the coclass, and coclass use the generated name XXXClass
                            GetUniqueManagedName(type, ConvType.ClassInterface);
                            break;

                        case TYPEKIND.TKIND_INTERFACE:
                            GetUniqueManagedName(type, ConvType.Interface);
                            break;

                        case TYPEKIND.TKIND_RECORD:
                            GetUniqueManagedName(type, ConvType.Struct);
                            break;

                        case TYPEKIND.TKIND_UNION:
                            GetUniqueManagedName(type, ConvType.Union);
                            break;

                        case TYPEKIND.TKIND_ENUM:
                            GetUniqueManagedName(type, ConvType.Enum);
                            break;

                        case TYPEKIND.TKIND_MODULE:
                            GetUniqueManagedName(type, ConvType.Module);
                            break;
                        }
                    }
                }
                catch (TlbImpInvalidTypeConversionException)
                {
                    // Swallow this exception. Usually it is caused by duplicated managed name which we can definitely ignore this
                }
            }
        }
Exemple #13
0
        public override void OnCreate()
        {
            string name = ManagedName;

            if (m_type != null)
            {
                return;
            }

            TypeInfo typeInfo = RefNonAliasedTypeInfo;

            using (TypeAttr typeAttr = typeInfo.GetTypeAttr())
            {
                //
                // Create fields
                //
                int  cVars            = typeAttr.cVars;
                bool isConversionLoss = false;

                for (int n = 0; n < cVars; ++n)
                {
                    using (VarDesc var = typeInfo.GetVarDesc(n))
                    {
                        CreateField(typeInfo, typeAttr, var, ref isConversionLoss);
                    }
                }

                //
                // Emit StructLayout(LayoutKind.Sequential, Pack=cbAlignment)
                //
                m_typeBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForStructLayout(LayoutKind.Explicit, typeAttr.cbAlignment, typeAttr.cbSizeInstance));

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

                //
                // Emit SerializableAttribute for /transform:serializablevalueclasses
                //
                if ((m_info.Settings.m_flags & TypeLibImporterFlags.SerializableValueClasses) != 0)
                {
                    m_typeBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForSerializable());
                }

                m_type = m_typeBuilder.CreateType();
            }
        }
Exemple #14
0
        /// <summary>
        /// Test whether the specified VT_RECORD contains any field that can be converted to a managed reference type
        /// </summary>
        private bool HasObjectFields(TypeInfo typeInfo)
        {
            TypeAttr typeAttr = typeInfo.GetTypeAttr();

            for (int i = 0; i < typeAttr.cVars; ++i)
            {
                VarDesc var = typeInfo.GetVarDesc(i);
                if (IsObjectType(typeInfo, var.elemdescVar.tdesc))
                {
                    return(true);
                }
            }

            return(false);
        }
        private bool RuleEngineResolveRedirection(RuleSet ruleSet, TypeInfo typeInfo,
                                                  out Type convertedType)
        {
            convertedType = null;
            if (ruleSet != null)
            {
                ICategory category = TypeCategory.GetInstance();
                TypeLibTypes.Interop.TYPEKIND typeKind;
                using (TypeAttr attr = typeInfo.GetTypeAttr())
                {
                    typeKind = attr.typekind;
                }
                TypeInfoMatchTarget target = new TypeInfoMatchTarget(typeInfo.GetContainingTypeLib(),
                                                                     typeInfo, typeKind);
                AbstractActionManager actionManager  = RuleEngine.GetActionManager();
                List <Rule>           resolveToRules = ruleSet.GetRule(
                    category, ResolveToActionDef.GetInstance(), target);
                if (resolveToRules.Count != 0)
                {
                    if (resolveToRules.Count > 1)
                    {
                        Output.WriteWarning(Resource.FormatString("Wrn_RuleMultipleMatch",
                                                                  ResolveToActionDef.GetInstance().GetActionName()),
                                            WarningCode.Wrn_RuleMultipleMatch);
                    }
                    Rule resolveToRule =
                        resolveToRules[resolveToRules.Count - 1];

                    ResolveToAction action =
                        resolveToRule.Action as ResolveToAction;
                    try
                    {
                        Assembly assembly = Assembly.ReflectionOnlyLoad(action.AssemblyName);
                        convertedType = assembly.GetType(action.ManagedTypeFullName);
                        return(true);
                    }
                    catch (Exception)
                    {
                        Output.WriteWarning(Resource.FormatString("Wrn_CannotLoadResolveToType",
                                                                  action.ManagedTypeFullName, action.AssemblyName),
                                            WarningCode.Wrn_CannotLoadResolveToType);
                    }
                }
            }
            return(false);
        }
Exemple #16
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;
            }
        }
Exemple #17
0
        private void CreateField(TypeInfo type, TypeAttr attr, VarDesc var, ref bool isConversionLoss)
        {
            if (IsObjectType(type, var.elemdescVar.tdesc))
            {
                isConversionLoss = true;
            }
            else
            {
                TypeConverter typeConverter = new TypeConverter(m_info, type, var.elemdescVar.tdesc, ConversionType.Field);
                Type          fieldType     = typeConverter.ConvertedType;

                // TlbImp2 will only skip reference types, instead of skipping every field
                // Also, TlbImp1 will skip ValueType *, which doesn't make any sense. TlbImp2 will keep ValueType * as IntPtr

                string fieldName = type.GetDocumentation(var.memid);
                // Generates the [FieldOffset(0)] layout declarations that approximate unions in managed code
                FieldBuilder field = m_typeBuilder.DefineField(fieldName, fieldType, FieldAttributes.Public);
                field.SetCustomAttribute(CustomAttributeHelper.GetBuilderForFieldOffset(0));
                typeConverter.ApplyAttributes(field);

                isConversionLoss |= typeConverter.IsConversionLoss;

                //
                // Emit ComConversionLossAttribute for fields if necessary
                //
                if (typeConverter.IsConversionLoss)
                {
                    field.SetCustomAttribute(CustomAttributeHelper.GetBuilderForComConversionLoss());

                    //
                    // Emit Wrn_UnconvertableField warning
                    //
                    m_info.ReportEvent(
                        WarningCode.Wrn_UnconvertableField,
                        Resource.FormatString("Wrn_UnconvertableField", type.GetDocumentation(), fieldName));
                }
            }
        }
Exemple #18
0
        /// <summary>
        /// Generate the special internal call constructor for RCW's
        /// </summary>
        private void CreateConstructor()
        {
            MethodAttributes methodAttributes;

            TypeInfo typeInfo = RefNonAliasedTypeInfo;

            using (TypeAttr typeAttr = typeInfo.GetTypeAttr())
            {
                if (typeAttr.IsCanCreate)
                {
                    methodAttributes = MethodAttributes.Public;
                }
                else
                {
                    methodAttributes = MethodAttributes.Assembly;
                }
            }

            ConstructorBuilder method         = m_typeBuilder.DefineDefaultConstructor(methodAttributes);
            ConstructorInfo    ctorMethodImpl = typeof(MethodImplAttribute).GetConstructor(new Type[] { typeof(MethodImplOptions) });

            method.SetImplementationFlags(MethodImplAttributes.InternalCall | MethodImplAttributes.Runtime);
        }
Exemple #19
0
        protected override void OnDefineType()
        {
            TypeInfo typeInfo = RefNonAliasedTypeInfo;

            using (TypeAttr typeAttr = typeInfo.GetTypeAttr())
            {
                string name = m_info.GetUniqueManagedName(RefTypeInfo, ConvType.Module);

                // Create the managed type for the module
                // It should be abstract & sealed, which is the same as a static class in C#
                // Also, reflection will create a default constructor for you if the class has no constructor,
                // except if the class is interface, valuetype, enum, or a static class, so this works pretty well
                // except that this is slightly different than tlbimpv1, as tlbimpv1 the class is not sealed
                m_typeBuilder = m_info.ModuleBuilder.DefineType(name,
                                                                TypeAttributes.Public | TypeAttributes.Abstract | TypeAttributes.Sealed,
                                                                typeof(Object));

                // Handle [Guid(...)] custom attribute
                ConvCommon.DefineGuid(RefTypeInfo, RefNonAliasedTypeInfo, m_typeBuilder);

                // Handle [TypeLibType(...)] if evaluate to non-0
                using (TypeAttr refTypeAttr = RefTypeInfo.GetTypeAttr())
                {
                    if (refTypeAttr.wTypeFlags != 0)
                    {
                        m_typeBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForTypeLibType((TypeLibTypeFlags)refTypeAttr.wTypeFlags));
                    }
                }
            }

            // Add to symbol table automatically
            m_info.AddToSymbolTable(RefTypeInfo, ConvType.Module, this);

            // Register type
            m_info.RegisterType(m_typeBuilder, this);
        }
Exemple #20
0
        /// <summary>
        /// Create the type for coclass
        /// </summary>
        public override void OnCreate()
        {
            //
            // Avoid duplicate creation
            //
            if (m_type != null)
            {
                return;
            }

            //
            // Create constructor
            // This is created before creating other methods because if anything fails, the constructor would still be valid
            // Otherwise reflection API will try to create one for us which will have incorrect setting (such as no internalcall flag)
            CreateConstructor();

            bool isConversionLoss = false;

            TypeInfo typeInfo = RefNonAliasedTypeInfo;

            if ((m_info.Settings.m_flags & TypeLibImporterFlags.PreventClassMembers) == 0)
            {
                using (TypeAttr attr = typeInfo.GetTypeAttr())
                {
                    Dictionary <Guid, bool> processedInterfaces = new Dictionary <Guid, bool>();

                    // Iterate through every interface and override the methods
                    // Process the default interface first
                    for (int m = 0; m < 2; ++m)
                    {
                        int nCount = attr.cImplTypes;
                        for (int n = 0; n < nCount; ++n)
                        {
                            IMPLTYPEFLAGS flags    = typeInfo.GetImplTypeFlags(n);
                            bool          bDefault = (flags & IMPLTYPEFLAGS.IMPLTYPEFLAG_FDEFAULT) != 0;
                            bool          bSource  = (flags & IMPLTYPEFLAGS.IMPLTYPEFLAG_FSOURCE) != 0;

                            // Use exclusive or to process just the default interface on the first pass
                            if (bDefault ^ m == 1)
                            {
                                TypeInfo typeImpl = typeInfo.GetRefType(n);
                                using (TypeAttr attrImpl = typeImpl.GetTypeAttr())
                                {
                                    if (attrImpl.Guid == WellKnownGuids.IID_IUnknown || attrImpl.Guid == WellKnownGuids.IID_IDispatch)
                                    {
                                        continue;
                                    }

                                    // Skip non-dispatch interfaces that doesn't derive from IUnknown
                                    if (!attrImpl.IsDispatch && !ConvCommon.IsDerivedFromIUnknown(typeImpl))
                                    {
                                        continue;
                                    }

                                    // Skip duplicate interfaces in type library
                                    // In .IDL you can actually write:
                                    // coclass A
                                    // {
                                    //     interface IA;
                                    //     interface IA;
                                    //     ...
                                    // }
                                    //
                                    if (!processedInterfaces.ContainsKey(attrImpl.Guid))
                                    {
                                        HandleParentInterface(typeImpl, bSource, ref isConversionLoss, bDefault);
                                        processedInterfaces.Add(attrImpl.Guid, true);
                                    }
                                }
                            }
                        }
                    }
                }
            }

            //
            // Emit ComConversionLoss attribute if necessary
            //
            if (isConversionLoss)
            {
                m_typeBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForComConversionLoss());
            }

            m_type = m_typeBuilder.CreateType();
        }
Exemple #21
0
        protected override void OnDefineType()
        {
            TypeInfo typeInfo = RefNonAliasedTypeInfo;

            using (TypeAttr attr = typeInfo.GetTypeAttr())
            {
                string name = m_info.GetUniqueManagedName(RefTypeInfo, ConvType.CoClass);

                //
                // Collect information for a list of interfaces & event interface types
                //
                List <Type> intfList                 = new List <Type>(); // interface list
                List <Type> eventIntfList            = new List <Type>(); // event interface list
                TypeInfo    defaultInterfaceTypeInfo = null;

                int nCount = attr.cImplTypes;

                string sourceInterfaceNames  = String.Empty;
                bool   hasDefaultInterface   = false;
                bool   implementsIEnumerable = ConvCommon.ExplicitlyImplementsIEnumerable(typeInfo, attr);

                for (int n = 0; n < nCount; ++n)
                {
                    IMPLTYPEFLAGS flags     = typeInfo.GetImplTypeFlags(n);
                    bool          isDefault = (flags & IMPLTYPEFLAGS.IMPLTYPEFLAG_FDEFAULT) != 0;
                    bool          isSource  = (flags & IMPLTYPEFLAGS.IMPLTYPEFLAG_FSOURCE) != 0;

                    TypeInfo typeImpl = typeInfo.GetRefType(n);

                    using (TypeAttr attrImpl = typeImpl.GetTypeAttr())
                    {
                        // Skip IUnknown & IDispatch
                        if (attrImpl.Guid == WellKnownGuids.IID_IDispatch || attrImpl.Guid == WellKnownGuids.IID_IUnknown)
                        {
                            continue;
                        }

                        // Skip non-dispatch interfaces that doesn't derive from IUnknown
                        if (!attrImpl.IsDispatch && !ConvCommon.IsDerivedFromIUnknown(typeImpl))
                        {
                            continue;
                        }

                        IConvInterface convInterface = (IConvInterface)m_info.GetTypeRef(ConvType.Interface, typeImpl);

                        // For source interfaces, try create the event interface
                        // Could be already created if it is the default source interface
                        if (isSource)
                        {
                            convInterface.DefineEventInterface();
                        }

                        // Use the RealManagedType (avoid getting the class interface)
                        Type typeRef = convInterface.RealManagedType;

                        // Append the source interface name to the list for the ComSourceInterfacesAttribute
                        if (isSource)
                        {
                            string interfaceName;
                            if (convInterface.ConvScope == ConvScope.External)
                            {
                                interfaceName = typeRef.AssemblyQualifiedName + "\0";
                            }
                            else
                            {
                                interfaceName = typeRef.FullName + "\0";
                            }

                            // Insert default source interface to the beginning
                            if (isDefault)
                            {
                                sourceInterfaceNames = interfaceName + sourceInterfaceNames;
                            }
                            else
                            {
                                sourceInterfaceNames = sourceInterfaceNames + interfaceName;
                            }
                        }

                        if (isDefault)
                        {
                            // Add the real interface first
                            if (isSource)
                            {
                                // For source interface, use the event interface instead
                                // Insert to the beginning
                                eventIntfList.Insert(0, convInterface.EventInterface.ManagedType);
                            }
                            else
                            {
                                m_defaultInterface = convInterface;

                                // Insert to the beginning
                                intfList.Insert(0, typeRef);
                                hasDefaultInterface      = true;
                                defaultInterfaceTypeInfo = typeImpl;
                            }
                        }
                        else
                        {
                            if (isSource)
                            {
                                // For source interface, add the event interface instead
                                eventIntfList.Add(convInterface.EventInterface.ManagedType);
                            }
                            else
                            {
                                if (m_defaultInterface == null)
                                {
                                    m_defaultInterface       = convInterface;
                                    defaultInterfaceTypeInfo = typeImpl;
                                }

                                intfList.Add(typeRef);
                            }
                        }
                    }
                }

                //
                // Get class interface
                //
                m_classInterface = m_info.GetTypeRef(ConvType.ClassInterface, RefTypeInfo) as IConvClassInterface;
                if (m_classInterface == null)
                {
                    throw new TlbImpInvalidTypeConversionException(RefTypeInfo);
                }

                //
                // Build implemented type list in a specific order
                //
                List <Type> implTypeList = new List <Type>();
                if (hasDefaultInterface)
                {
                    implTypeList.Add(intfList[0]);
                    intfList.RemoveAt(0);

                    implTypeList.Add(m_classInterface.ManagedType);
                }
                else
                {
                    implTypeList.Add(m_classInterface.ManagedType);
                    if (intfList.Count > 0)
                    {
                        implTypeList.Add(intfList[0]);
                        intfList.RemoveAt(0);
                    }
                }

                if (eventIntfList.Count > 0)
                {
                    implTypeList.Add(eventIntfList[0]);
                    eventIntfList.RemoveAt(0);
                }

                implTypeList.AddRange(intfList);
                implTypeList.AddRange(eventIntfList);

                // Check to see if the default interface has a member with a DISPID of DISPID_NEWENUM.
                if (defaultInterfaceTypeInfo != null)
                {
                    if (!implementsIEnumerable && ConvCommon.HasNewEnumMember(m_info, defaultInterfaceTypeInfo))
                    {
                        implTypeList.Add(typeof(System.Collections.IEnumerable));
                    }
                }

                // Check to see if the IEnumerable Custom Value exists on the CoClass if doesn't inherit from IEnumerable yet
                if (!implTypeList.Contains(typeof(System.Collections.IEnumerable)))
                {
                    if (ConvCommon.HasForceIEnumerableCustomAttribute(typeInfo))
                    {
                        implTypeList.Add(typeof(System.Collections.IEnumerable));
                    }
                }

                // Define the type
                m_typeBuilder = m_info.ModuleBuilder.DefineType(name,
                                                                TypeAttributes.Public | TypeAttributes.Import,
                                                                typeof(Object),
                                                                implTypeList.ToArray());

                // Handle [Guid(...)] custom attribute
                ConvCommon.DefineGuid(RefTypeInfo, RefNonAliasedTypeInfo, m_typeBuilder);

                // Handle [ClassInterface(ClassInterfaceType.None)]
                m_typeBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForClassInterface(ClassInterfaceType.None));

                // Handle [TypeLibType(...)] if evaluate to non-0
                using (TypeAttr refTypeAttr = RefTypeInfo.GetTypeAttr())
                {
                    if (refTypeAttr.wTypeFlags != 0)
                    {
                        m_typeBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForTypeLibType((TypeLibTypeFlags)refTypeAttr.wTypeFlags));
                    }
                }

                // Handle [ComSourceInterfacesAttribute]
                if (sourceInterfaceNames != String.Empty)
                {
                    sourceInterfaceNames += "\0";
                    m_typeBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForComSourceInterfaces(sourceInterfaceNames));
                }

                // Add to symbol table automatically
                m_info.AddToSymbolTable(RefTypeInfo, ConvType.CoClass, this);

                // Register type
                m_info.RegisterType(m_typeBuilder, this);
            }
        }
Exemple #22
0
        /// <summary>
        /// Test whether the typeDesc corresponds to a managed reference type
        /// </summary>
        private bool IsObjectType(TypeInfo typeInfo, TypeDesc typeDesc)
        {
            int nativeIndirection = 0;
            int vt = typeDesc.vt;

            // Strip off leading VT_PTR and VT_BYREF
            while (vt == (int)VarEnum.VT_PTR)
            {
                typeDesc = typeDesc.lptdesc;
                vt       = typeDesc.vt;
                nativeIndirection++;
            }

            if ((vt & (int)VarEnum.VT_BYREF) != 0)
            {
                vt &= ~(int)VarEnum.VT_BYREF;
                nativeIndirection++;
            }

            // Determine if the field is/has object type.
            Debug.Assert(vt != (int)VarEnum.VT_PTR);

            switch ((VarEnum)vt)
            {
            // These are object types.
            case VarEnum.VT_BSTR:
            case VarEnum.VT_DISPATCH:
            case VarEnum.VT_VARIANT:
            case VarEnum.VT_UNKNOWN:
            case VarEnum.VT_SAFEARRAY:
            case VarEnum.VT_LPSTR:
            case VarEnum.VT_LPWSTR:
                return(true);

            // A user-defined may or may not be/contain Object type.
            case VarEnum.VT_USERDEFINED:
                // User defined type.  Get the TypeInfo.
                TypeInfo refTypeInfo = typeInfo.GetRefTypeInfo(typeDesc.hreftype);
                TypeAttr refTypeAttr = refTypeInfo.GetTypeAttr();

                // Some user defined class.  Is it a value class, or a VOS class?
                switch (refTypeAttr.typekind)
                {
                // Alias -- Is the aliased thing an Object type?
                case TYPEKIND.TKIND_ALIAS:
                    return(IsObjectType(refTypeInfo, refTypeAttr.tdescAlias));

                // Record/Enum/Union -- Does it contain an Object type?
                case TYPEKIND.TKIND_RECORD:
                case TYPEKIND.TKIND_ENUM:
                case TYPEKIND.TKIND_UNION:
                    // Byref/Ptrto record is Object.  Contained record might be.
                    if (nativeIndirection > 0)
                    {
                        return(true);
                    }
                    else
                    {
                        return(HasObjectFields(refTypeInfo));
                    }

                // Class/Interface -- An Object Type.
                case TYPEKIND.TKIND_INTERFACE:
                case TYPEKIND.TKIND_DISPATCH:
                case TYPEKIND.TKIND_COCLASS:
                    return(true);

                default:
                    return(true);
                }     // switch (psAttrAlias->typekind)

            case VarEnum.VT_CY:
            case VarEnum.VT_DATE:
            case VarEnum.VT_DECIMAL:
                // Pointer to the value type is an object.  Contained one isn't.
                if (nativeIndirection > 0)
                {
                    return(true);
                }
                else
                {
                    return(false);
                }

            // A fixed array is an Object type.
            case VarEnum.VT_CARRAY:
                return(true);

            // Other types I4, etc., are not Object types.
            default:
                return(false);
            } // switch (vt=pType->vt)
        }
        private void _Convert()
        {
            VarEnum vt = (VarEnum)m_typeDesc.vt;

            // Strip out VT_PTR
            while (vt == VarEnum.VT_PTR)
            {
                m_typeDesc = m_typeDesc.lptdesc;
                vt         = (VarEnum)m_typeDesc.vt;
                m_nativeIndirections++;
            }

            // Strip out VT_BYREF
            if ((vt & VarEnum.VT_BYREF) != 0)
            {
                vt &= ~VarEnum.VT_BYREF;
                m_nativeIndirections++;
            }

            //
            // Find the corresponding type and save it in result and store the custom attribute in m_attribute
            //
            Type result = null;

            m_attribute = null;
            switch (vt)
            {
            case VarEnum.VT_HRESULT:
                result      = typeof(int);
                m_attribute = CustomAttributeHelper.GetBuilderForMarshalAs(UnmanagedType.Error);
                SetUnmanagedType(UnmanagedType.Error);
                break;

            case VarEnum.VT_VOID:
                result = typeof(void);
                break;

            case VarEnum.VT_UINT:
                result = typeof(uint);
                break;

            case VarEnum.VT_INT:
                result = typeof(int);
                break;

            case VarEnum.VT_UI1:
                result = typeof(byte);
                break;

            case VarEnum.VT_UI2:
                result = typeof(ushort);
                break;

            case VarEnum.VT_UI4:
                result = typeof(uint);
                break;

            case VarEnum.VT_UI8:
                result = typeof(ulong);
                break;

            case VarEnum.VT_I1:
                result = typeof(sbyte);
                break;

            case VarEnum.VT_I2:
                result = typeof(short);
                break;

            case VarEnum.VT_I4:
                result = typeof(int);
                break;

            case VarEnum.VT_I8:
                result = typeof(long);
                break;

            case VarEnum.VT_R4:
                result = typeof(float);
                break;

            case VarEnum.VT_R8:
                result = typeof(double);
                break;

            case VarEnum.VT_ERROR:
                result      = typeof(int);
                m_attribute = CustomAttributeHelper.GetBuilderForMarshalAs(UnmanagedType.Error);
                SetUnmanagedType(UnmanagedType.Error);

                break;

            case VarEnum.VT_BSTR:
                result      = typeof(string);
                m_attribute = CustomAttributeHelper.GetBuilderForMarshalAs(UnmanagedType.BStr);
                SetUnmanagedType(UnmanagedType.BStr);

                // BSTR => string is special as BSTR are actually OLECHAR*, so we should add one indirection
                m_nativeIndirections++;
                break;

            case VarEnum.VT_DISPATCH:
                if (m_convertingNewEnumMember)
                {
                    // When we are creating a new enum member, convert IDispatch to IEnumVariant
                    TryUseCustomMarshaler(WellKnownGuids.IID_IEnumVARIANT, out result);
                }
                else
                {
                    result      = typeof(object);
                    m_attribute = CustomAttributeHelper.GetBuilderForMarshalAs(UnmanagedType.IDispatch);
                    SetUnmanagedType(UnmanagedType.IDispatch);
                }

                // VT_DISPATCH => IDispatch *
                m_nativeIndirections++;

                break;

            case VarEnum.VT_UNKNOWN:
                if (m_convertingNewEnumMember)
                {
                    // When we are creating a new enum member, convert IUnknown to IEnumVariant
                    TryUseCustomMarshaler(WellKnownGuids.IID_IEnumVARIANT, out result);
                }
                else
                {
                    result      = typeof(object);
                    m_attribute = CustomAttributeHelper.GetBuilderForMarshalAs(UnmanagedType.IUnknown);
                    SetUnmanagedType(UnmanagedType.IUnknown);
                }

                // VT_UNKNOWN => IUnknown *
                m_nativeIndirections++;

                break;

            case VarEnum.VT_LPSTR:
                result      = typeof(string);
                m_attribute = CustomAttributeHelper.GetBuilderForMarshalAs(UnmanagedType.LPStr);
                SetUnmanagedType(UnmanagedType.LPStr);
                m_nativeIndirections++;
                break;

            case VarEnum.VT_LPWSTR:
                result      = typeof(string);
                m_attribute = CustomAttributeHelper.GetBuilderForMarshalAs(UnmanagedType.LPWStr);
                SetUnmanagedType(UnmanagedType.LPWStr);
                m_nativeIndirections++;
                break;

            case VarEnum.VT_PTR:
                Debug.Assert(false, "Should not get here");
                break;

            case VarEnum.VT_SAFEARRAY:
            {
                TypeDesc arrayDesc       = m_typeDesc.lpadesc.tdescElem;
                VarEnum  arrayVt         = (VarEnum)arrayDesc.vt;
                Type     userDefinedType = null;

                TypeConverter elemTypeConverter = new TypeConverter(m_info, m_typeInfo, arrayDesc, ConversionType.Element);
                Type          elemType          = elemTypeConverter.ConvertedType;

                // Determine the right VT for MarshalAs attribute
                bool pointerArray = false;
                if (arrayVt == VarEnum.VT_PTR)
                {
                    arrayDesc    = arrayDesc.lptdesc;
                    arrayVt      = (VarEnum)arrayDesc.vt;
                    pointerArray = true;

                    // We don't support marshalling pointers in array except UserType* & void*
                    if (arrayVt != VarEnum.VT_USERDEFINED && arrayVt != VarEnum.VT_VOID)
                    {
                        arrayVt          = VarEnum.VT_INT;
                        m_conversionLoss = true;
                    }
                }

                //
                // Emit UserDefinedSubType if necessary
                //
                if (arrayVt == VarEnum.VT_USERDEFINED)
                {
                    if (elemType.IsEnum)
                    {
                        if (pointerArray)
                        {
                            arrayVt          = VarEnum.VT_INT;
                            m_conversionLoss = true;
                        }
                        else
                        {
                            // For enums, using VT_RECORD is better than VT_I4
                            // Within the runtime, if you specify VT_I4 for enums in SafeArray, we treat it the same way as VT_RECORD
                            // Reflection API also accepts VT_RECORD instead of VT_I4
                            arrayVt = VarEnum.VT_RECORD;
                        }
                    }
                    else if (elemType.IsValueType)
                    {
                        if (pointerArray)
                        {
                            arrayVt          = VarEnum.VT_INT;
                            m_conversionLoss = true;
                        }
                        else
                        {
                            arrayVt = VarEnum.VT_RECORD;
                        }
                    }
                    else if (elemType.IsInterface)
                    {
                        if (pointerArray)
                        {
                            // decide VT_UNKNOWN / VT_DISPATCH
                            if (InterfaceSupportsDispatch(elemType))
                            {
                                arrayVt = VarEnum.VT_DISPATCH;
                            }
                            else
                            {
                                arrayVt = VarEnum.VT_UNKNOWN;
                            }
                        }
                        else
                        {
                            arrayVt          = VarEnum.VT_INT;
                            m_conversionLoss = true;
                        }
                    }
                    else if (elemType == typeof(object) && !elemTypeConverter.UseDefaultMarshal &&
                             (elemTypeConverter.UnmanagedType == UnmanagedType.IUnknown))
                    {
                        // Special case for object that doesn't have default interface and will be marshalled as IUnknown
                        arrayVt = VarEnum.VT_UNKNOWN;
                    }

                    userDefinedType = elemType;
                }

                m_conversionLoss |= elemTypeConverter.IsConversionLoss;

                // Transform to System.Array if /sysarray is set and not vararg
                if (((m_info.Settings.m_flags & TypeLibImporterFlags.SafeArrayAsSystemArray) != 0) &&
                    m_conversionType != ConversionType.VarArgParameter)
                {
                    result = typeof(System.Array);
                }
                else
                {
                    result = elemType.MakeArrayType();

                    // Don't need SafeArrayUserDefinedSubType for non System.Array case
                    userDefinedType = null;
                }

                // TlbImp doesn't have this check for vt == VT_RECORD/VT_UNKNOWN/VT_DISPATCH therefore
                // it will emit SafeArrayUserDefinedSubType even it is not necessary/not valid
                // TlbImp2 will take this into account
                if ((userDefinedType != null) && (arrayVt == VarEnum.VT_RECORD || arrayVt == VarEnum.VT_UNKNOWN || arrayVt == VarEnum.VT_DISPATCH))
                {
                    // The name of the type would be full name in TlbImp2
                    m_attribute = CustomAttributeHelper.GetBuilderForMarshalAsSafeArrayAndUserDefinedSubType(arrayVt, userDefinedType);
                }
                else
                {
                    // Use I4 for enums when SafeArrayUserDefinedSubType is not specified
                    if (elemType.IsEnum && arrayVt == VarEnum.VT_RECORD)
                    {
                        arrayVt = VarEnum.VT_I4;
                    }
                    m_attribute = CustomAttributeHelper.GetBuilderForMarshalAsSafeArray(arrayVt);
                }

                SetUnmanagedType(UnmanagedType.SafeArray);

                // SafeArray <=> array is special because SafeArray is similar to Element*
                m_nativeIndirections++;

                break;
            }

            case VarEnum.VT_RECORD:
            case VarEnum.VT_USERDEFINED:
            {
                // Handle structs, interfaces, enums, and unions

                // Check if any ResolveTo Rule applied.
                TypeInfo refType = m_typeInfo.GetRefTypeInfo(m_typeDesc.hreftype);
                TypeAttr refAttr = refType.GetTypeAttr();
                Type     resolveToType;
                if (RuleEngineResolveRedirection(m_info.Settings.m_ruleSet, refType,
                                                 out resolveToType))
                {
                    result = resolveToType;
                    break;
                }

                // Support for aliasing
                TypeInfo realType;
                TypeAttr realAttr;
                ConvCommon.ResolveAlias(m_typeInfo, m_typeDesc, out realType, out realAttr);

                // Alias for a built-in type?
                if (realAttr.typekind == TypeLibTypes.Interop.TYPEKIND.TKIND_ALIAS)
                {
                    // Recurse to convert the built-in type
                    TypeConverter builtinType = new TypeConverter(m_info, realType, realAttr.tdescAlias, m_conversionType);
                    result      = builtinType.ConvertedType;
                    m_attribute = builtinType.m_attribute;
                }
                else
                {
                    // Otherwise, we must have a non-aliased type, and it is a user defined type
                    // We should use the TypeInfo that this TypeDesc refers to
                    realType = m_typeDesc.GetUserDefinedTypeInfo(m_typeInfo);
                    TypeLibTypes.Interop.TYPEKIND typeKind = realAttr.typekind;

                    using (realAttr = realType.GetTypeAttr())
                    {
                        TypeLib typeLib = realType.GetContainingTypeLib();

                        // Convert StdOle2.Guid to System.Guid
                        if (_IsStdOleGuid(realType))
                        {
                            result      = typeof(Guid);
                            m_attribute = null;
                            ResetUnmanagedType();
                        }
                        else if (realAttr.Guid == WellKnownGuids.IID_IUnknown)
                        {
                            // Occasional goto makes sense
                            // If VT_USERDEFINE *, and the VT_USERDEFINE is actually a VT_UNKNOWN => IUnknown *, we need to decrease the m_nativeIndirections
                            // to compensate for the m_nativeIndirections++ in VT_UNKNOWN
                            m_nativeIndirections--;
                            goto case VarEnum.VT_UNKNOWN;
                        }
                        else if (realAttr.Guid == WellKnownGuids.IID_IDispatch)
                        {
                            // Occasional goto makes sense
                            // See the IID_IUnknown case for why we need to --
                            m_nativeIndirections--;
                            goto case VarEnum.VT_DISPATCH;
                        }
                        else
                        {
                            // Need to use CustomMarshaler?
                            Type customMarshalerResultType;
                            if (TryUseCustomMarshaler(realAttr.Guid, out customMarshalerResultType))
                            {
                                result = customMarshalerResultType;
                            }
                            else
                            {
                                IConvBase ret = m_info.GetTypeRef(ConvCommon.TypeKindToConvType(typeKind), realType);

                                if (m_conversionType == ConversionType.Field)
                                {
                                    // Too bad. Reflection API requires that the field type must be created before creating
                                    // the struct/union type

                                    // Only process indirection = 0 case because > 1 case will be converted to IntPtr
                                    // Otherwise it will leads to a infinite recursion, if you consider the following scenario:
                                    // struct A
                                    // {
                                    //      struct B
                                    //      {
                                    //          struct A *a;
                                    //      } b;
                                    // }
                                    if (ret is ConvUnionLocal && m_nativeIndirections == 0)
                                    {
                                        ConvUnionLocal convUnion = ret as ConvUnionLocal;
                                        convUnion.Create();
                                    }
                                    else if (ret is ConvStructLocal && m_nativeIndirections == 0)
                                    {
                                        ConvStructLocal convStruct = ret as ConvStructLocal;
                                        convStruct.Create();
                                    }
                                    else if (ret is ConvEnumLocal && m_nativeIndirections == 0)
                                    {
                                        ConvEnumLocal convEnum = ret as ConvEnumLocal;
                                        convEnum.Create();
                                    }
                                }

                                result = ret.ManagedType;

                                // Don't reply on result.IsInterface as we have some weird scenarios like refering to a exported type lib
                                // which has interfaces that are class interfaces and have the same name as a class.
                                // For example, manage class M has a class interface _M, and their managed name are both M
                                if (ret.ConvType == ConvType.Interface || ret.ConvType == ConvType.EventInterface || ret.ConvType == ConvType.ClassInterface)
                                {
                                    m_attribute = CustomAttributeHelper.GetBuilderForMarshalAs(UnmanagedType.Interface);
                                    SetUnmanagedType(UnmanagedType.Interface);
                                }

                                if (ret.ConvType == ConvType.CoClass)
                                {
                                    // We need to convert CoClass to default interface (could be converted to class interface if it is exclusive) in signatures
                                    Debug.Assert(ret is IConvCoClass);
                                    IConvCoClass convCoClass = ret as IConvCoClass;
                                    if (convCoClass.DefaultInterface != null)
                                    {
                                        // Use the default interface
                                        result      = convCoClass.DefaultInterface.ManagedType;
                                        m_attribute = CustomAttributeHelper.GetBuilderForMarshalAs(UnmanagedType.Interface);
                                        SetUnmanagedType(UnmanagedType.Interface);
                                    }
                                    else
                                    {
                                        // The coclass has no default interface (source interface excluded)
                                        // Marshal it as IUnknown
                                        result      = typeof(object);
                                        m_attribute = CustomAttributeHelper.GetBuilderForMarshalAs(UnmanagedType.IUnknown);
                                        SetUnmanagedType(UnmanagedType.IUnknown);
                                    }
                                }
                            }
                        }
                    }
                }
            }

            break;

            case VarEnum.VT_VARIANT:
                result      = typeof(object);
                m_attribute = CustomAttributeHelper.GetBuilderForMarshalAs(UnmanagedType.Struct);
                SetUnmanagedType(UnmanagedType.Struct);

                // object is special that it will be marshaled to VARIANT
                // because we'll think object as having one indirection, now we are one indirection less,
                // so we need add 1 to m_indirections
                m_nativeIndirections++;
                break;

            case VarEnum.VT_CY:
                result      = typeof(System.Decimal);
                m_attribute = CustomAttributeHelper.GetBuilderForMarshalAs(UnmanagedType.Currency);
                SetUnmanagedType(UnmanagedType.Currency);

                break;

            case VarEnum.VT_DATE:
                result = typeof(System.DateTime);
                break;

            case VarEnum.VT_DECIMAL:
                result = typeof(System.Decimal);
                break;


            case VarEnum.VT_CARRAY:
            {
                TypeDesc      elemTypeDesc      = m_typeDesc.lptdesc;
                TypeConverter elemTypeConverter = new TypeConverter(m_info, m_typeInfo, elemTypeDesc, ConversionType.Element);
                Type          elemType          = elemTypeConverter.ConvertedType;
                result = elemType.MakeArrayType();

                m_conversionLoss |= elemTypeConverter.IsConversionLoss;

                uint             elements = 1;
                SAFEARRAYBOUND[] bounds   = m_typeDesc.lpadesc.Bounds;
                foreach (SAFEARRAYBOUND bound in bounds)
                {
                    elements *= bound.cElements;
                }

                // SizeConst can only hold Int32.MaxValue
                if (elements <= Int32.MaxValue)
                {
                    UnmanagedType arrayType;
                    if (m_conversionType == ConversionType.Field)
                    {
                        arrayType = UnmanagedType.ByValArray;
                    }
                    else
                    {
                        arrayType = UnmanagedType.LPArray;
                    }

                    if (elemTypeConverter.UseDefaultMarshal)
                    {
                        m_attribute = CustomAttributeHelper.GetBuilderForMarshalAsConstArray(arrayType, (int)elements);
                    }
                    else
                    {
                        if (elemTypeConverter.UnmanagedType == UnmanagedType.BStr ||
                            elemTypeConverter.UnmanagedType == UnmanagedType.LPStr ||
                            elemTypeConverter.UnmanagedType == UnmanagedType.LPWStr ||
                            elemTypeConverter.UnmanagedType == UnmanagedType.VariantBool)
                        {
                            m_attribute = CustomAttributeHelper.GetBuilderForMarshalAsConstArray(arrayType, (int)elements, elemTypeConverter.UnmanagedType);
                        }
                        else
                        {
                            m_attribute = CustomAttributeHelper.GetBuilderForMarshalAsConstArray(arrayType, (int)elements);
                        }
                    }

                    SetUnmanagedType(arrayType);
                }
                else
                {
                    m_nativeIndirections = 0;
                    result      = typeof(IntPtr);
                    m_attribute = null;
                    ResetUnmanagedType();
                    m_conversionLoss = true;
                }
            }
            break;

            case VarEnum.VT_BOOL:
                // For VT_BOOL in fields, use short if v2 switch is not specified.
                if (m_conversionType == ConversionType.Field)
                {
                    if (m_info.Settings.m_isVersion2)
                    {
                        result      = typeof(bool);
                        m_attribute = CustomAttributeHelper.GetBuilderForMarshalAs(UnmanagedType.VariantBool);
                        SetUnmanagedType(UnmanagedType.VariantBool);
                    }
                    else
                    {
                        result = typeof(short);
                    }
                }
                else
                {
                    result = typeof(bool);
                    SetUnmanagedType(UnmanagedType.VariantBool);
                }
                break;

            default:
                m_info.ReportEvent(
                    WarningCode.Wrn_BadVtType,
                    Resource.FormatString("Wrn_BadVtType", (int)vt, m_typeInfo.GetDocumentation()));
                result           = typeof(IntPtr);
                m_conversionLoss = true;
                break;
            }

            //
            // String -> StringBuilder special case
            //
            if (result == typeof(string))
            {
                if (_IsParamOut() && m_nativeIndirections == 1 && (m_conversionType == ConversionType.Parameter || m_conversionType == ConversionType.VarArgParameter))
                {
                    // [out] or [in, out] LPSTR/LPWSTR scenario
                    if (vt != VarEnum.VT_BSTR)
                    {
                        // String is immutable and cannot be [out]/[in, out]. We can convert to StringBuilder
                        result = typeof(StringBuilder);
                    }
                    else // VT_BSTR
                    {
                        // VT_BSTR is also immutable. So conversion loss here
                        m_conversionLoss     = true;
                        result               = typeof(IntPtr);
                        m_attribute          = null;
                        m_nativeIndirections = 0;
                        ResetUnmanagedType();
                    }
                }
            }

            // Special rule for void* => IntPtr
            if (result == typeof(void))
            {
                result = typeof(IntPtr);

                switch (m_conversionType)
                {
                case ConversionType.Element:
                    m_nativeIndirections = 0;
                    break;

                case ConversionType.Field:
                    m_nativeIndirections = 0;
                    break;

                default:
                    if (m_nativeIndirections > 1)
                    {
                        m_nativeIndirections = 1;
                    }
                    else
                    {
                        m_nativeIndirections = 0;
                    }
                    break;
                }
            }

            //
            // If the type is already a byref type, remove the byref and add extra indirection(s).
            // This is necessary to avoid trying to call MakeByRef on the byref type
            //
            if (result.IsByRef)
            {
                result = result.GetElementType();
                if (result.IsValueType)
                {
                    m_nativeIndirections++;     // Value& = Value *
                }
                else
                {
                    m_nativeIndirections += 2;  // RefType& = RefType**
                }
            }

            //
            // Process indirection
            //
            if (m_nativeIndirections > 0)
            {
                if (result.IsValueType)
                {
                    switch (m_conversionType)
                    {
                    case ConversionType.VarArgParameter:
                    case ConversionType.Parameter:
                        // Decimal/Guid can support extra level of indirection using LpStruct in parameters
                        // LpStruct has no effect in other places and for other types
                        // Only use LpStruct for scenarios like GUID **
                        // This is different from old TlbImp. Old TlbImp will use IntPtr
                        if ((result == typeof(Decimal) || result == typeof(Guid)) && m_nativeIndirections == 2)
                        {
                            m_nativeIndirections--;
                            m_attribute = CustomAttributeHelper.GetBuilderForMarshalAs(UnmanagedType.LPStruct);
                            ResetUnmanagedType();
                            SetUnmanagedType(UnmanagedType.LPStruct);
                        }

                        if (m_nativeIndirections >= 2)
                        {
                            m_conversionLoss = true;
                            result           = typeof(IntPtr);
                            m_attribute      = null;
                            ResetUnmanagedType();
                        }
                        else if (m_nativeIndirections > 0)
                        {
                            result = result.MakeByRefType();
                        }

                        break;

                    case ConversionType.Field:
                        m_conversionLoss = true;
                        result           = typeof(IntPtr);
                        m_attribute      = null;
                        ResetUnmanagedType();
                        break;

                    case ConversionType.ParamRetVal:
                        m_nativeIndirections--;
                        goto case ConversionType.ReturnValue;
                    // Fall through to ConversionType.ReturnValue

                    case ConversionType.ReturnValue:
                        if (m_nativeIndirections >= 1)
                        {
                            m_conversionLoss = true;
                            result           = typeof(IntPtr);
                            m_attribute      = null;
                            ResetUnmanagedType();
                        }
                        break;

                    case ConversionType.Element:
                        m_conversionLoss = true;
                        result           = typeof(IntPtr);
                        m_attribute      = null;
                        ResetUnmanagedType();
                        break;
                    }
                }
                else
                {
                    switch (m_conversionType)
                    {
                    case ConversionType.Field:
                        // ** => IntPtr, ConversionLoss
                        if (m_nativeIndirections > 1)
                        {
                            result           = typeof(IntPtr);
                            m_conversionLoss = true;
                            m_attribute      = null;
                            ResetUnmanagedType();
                        }
                        break;

                    case ConversionType.VarArgParameter:
                    case ConversionType.Parameter:
                        if (m_nativeIndirections > 2)
                        {
                            result           = typeof(IntPtr);
                            m_conversionLoss = true;
                            m_attribute      = null;
                            ResetUnmanagedType();
                        }
                        else if (m_nativeIndirections == 2)
                        {
                            result = result.MakeByRefType();
                        }
                        break;

                    case ConversionType.ParamRetVal:
                        m_nativeIndirections--;
                        goto case ConversionType.ReturnValue;
                    // Fall through to ConversionType.ReturnValue

                    case ConversionType.ReturnValue:
                        if (m_nativeIndirections > 1)
                        {
                            result           = typeof(IntPtr);
                            m_conversionLoss = true;
                            m_attribute      = null;
                            ResetUnmanagedType();
                        }
                        break;

                    case ConversionType.Element:
                        if (m_nativeIndirections > 1)
                        {
                            m_conversionLoss = true;
                            result           = typeof(IntPtr);
                            m_attribute      = null;
                            ResetUnmanagedType();
                        }
                        break;
                    }
                }
            }

            m_convertedType = result;
        }
 public InterfaceInfo(ConverterInfo info, TypeBuilder typeBuilder, bool supportsDispatch, TypeInfo type, TypeAttr attr, bool bCoClass)
 {
     Init(info, typeBuilder, supportsDispatch, type, attr, bCoClass, false, null);
 }
Exemple #25
0
        protected override void OnDefineType()
        {
            string classInterfaceName = m_info.GetUniqueManagedName(m_coclassTypeInfo, ConvType.ClassInterface);

            Type defaultInterfaceType       = null;
            Type defaultSourceInterfaceType = null;

            m_convInterface       = null;
            m_convSourceInterface = null;

            //
            // Convert default interface
            //
            if (m_defaultInterfaceTypeInfo != null)
            {
                m_convInterface = (IConvInterface)m_info.GetTypeRef(ConvType.Interface, m_defaultInterfaceTypeInfo);
                // Don't create the interface because we haven't associated the default interface with the class interface yet
                // We don't want to create anything in the "Define" stage
                //m_convInterface.Create();
                defaultInterfaceType = m_convInterface.ManagedType;
            }

            //
            // Convert default source interface
            //
            if (m_defaultSourceInterfaceTypeInfo != null)
            {
                m_convSourceInterface = (IConvInterface)m_info.GetTypeRef(ConvType.Interface, m_defaultSourceInterfaceTypeInfo);
                // Don't create the interface because we haven't associated the default interface with the class interface yet
                // We don't want to create anything in the "Define" stage
                // m_convSourceInterface.Create();
                Type sourceInterfaceType = m_convSourceInterface.RealManagedType;
                IConvEventInterface convEventInterface = m_convSourceInterface.DefineEventInterface();
                // Don't create the interface because we haven't associated the default interface with the class interface yet
                // We don't want to create anything in the "Define" stage
                // convEventInterface.Create();
                defaultSourceInterfaceType = m_convSourceInterface.EventInterface.ManagedType;
            }

            //
            // Prepare list of implemented interfaces
            //
            List <Type> implTypes = new List <Type>();

            if (defaultInterfaceType != null)
            {
                implTypes.Add(defaultInterfaceType);
            }
            if (defaultSourceInterfaceType != null)
            {
                implTypes.Add(defaultSourceInterfaceType);
            }

            // Create the class interface
            m_typeBuilder = m_info.ModuleBuilder.DefineType(
                classInterfaceName,
                TypeAttributes.Public | TypeAttributes.Interface | TypeAttributes.Abstract | TypeAttributes.Import,
                null,
                implTypes.ToArray());

            // Link to it so that ManagedType will return the class interface while GetWrappedInterfaceType will return the
            // real interface
            // This must be done before creating the coclass because coclass needs this information
            // Only do so when the default interface is exclusively belongs to one coclass

            if (m_convInterface != null && m_isExclusive)
            {
                // Check if the default interface -> class interface relationship exists in the default
                // interface's type lib. That means we only need to check if the default interface and
                // the coclass are in the same type library.
                TypeLib typeLib = m_convInterface.RefTypeInfo.GetContainingTypeLib();
                Guid    libIdOfDefaultInterface;
                using (TypeLibAttr libAttr = typeLib.GetLibAttr())
                {
                    libIdOfDefaultInterface = libAttr.guid;
                }
                Guid    libIdOfCoclass;
                TypeLib coclassTypeLib = m_coclassTypeInfo.GetContainingTypeLib();
                using (TypeLibAttr libAttr = coclassTypeLib.GetLibAttr())
                {
                    libIdOfCoclass = libAttr.guid;
                }
                if (libIdOfDefaultInterface.Equals(libIdOfCoclass))
                {
                    m_convInterface.AssociateWithExclusiveClassInterface(this as IConvClassInterface);
                }
            }

            // Emit GuidAttribute, which is the same as the default interface, if it exists
            // If there is no default Interface here, and the coclass implements IDispatch or IUnknown as non-source
            // interface, we use the IDispatch or IUnknown's guid.
            if (defaultInterfaceType != null)
            {
                ConvCommon.DefineGuid(m_convInterface.RefTypeInfo, m_convInterface.RefNonAliasedTypeInfo, m_typeBuilder);
            }
            else
            {
                TypeInfo ImplementedIDispatchOrIUnknownTypeInfo = null;
                using (TypeAttr attr = m_coclassTypeInfo.GetTypeAttr())
                {
                    for (int m = 0; m < attr.cImplTypes; ++m)
                    {
                        TypeLibTypes.Interop.IMPLTYPEFLAGS flags = m_coclassTypeInfo.GetImplTypeFlags(m);
                        bool bDefault = (flags & TypeLibTypes.Interop.IMPLTYPEFLAGS.IMPLTYPEFLAG_FDEFAULT) != 0;
                        bool bSource  = (flags & TypeLibTypes.Interop.IMPLTYPEFLAGS.IMPLTYPEFLAG_FSOURCE) != 0;

                        TypeInfo typeImpl = m_coclassTypeInfo.GetRefType(m);
                        using (TypeAttr attrImpl = typeImpl.GetTypeAttr())
                        {
                            if (attrImpl.Guid == WellKnownGuids.IID_IDispatch ||
                                attrImpl.Guid == WellKnownGuids.IID_IUnknown)
                            {
                                // If more than one IDispatch or IUnknown exist, we will pick the default one;
                                // If none of them is with the default flag, pick the first one.
                                if (!bSource && (bDefault || ImplementedIDispatchOrIUnknownTypeInfo == null))
                                {
                                    ImplementedIDispatchOrIUnknownTypeInfo = typeImpl;
                                }
                            }
                        }
                    }
                }
                if (ImplementedIDispatchOrIUnknownTypeInfo != null)
                {
                    ConvCommon.DefineGuid(ImplementedIDispatchOrIUnknownTypeInfo,
                                          ImplementedIDispatchOrIUnknownTypeInfo, m_typeBuilder);
                }
            }

            // Make sure we know about the class interface before we go to define the coclass in the next statement
            m_info.RegisterType(m_typeBuilder, this);
            m_info.AddToSymbolTable(m_coclassTypeInfo, ConvType.ClassInterface, this);

            // Handle [CoClass(typeof(...))]
            Type            typeRefCoClass       = m_info.GetTypeRef(ConvType.CoClass, m_coclassTypeInfo).ManagedType;
            ConstructorInfo ctorCoClassAttribute = typeof(CoClassAttribute).GetConstructor(
                new Type[] { typeof(Type) });
            // For back compatibility, use full name to create CoClassAttribute, instead of assembly qualified name.
            CustomAttributeBlobBuilder blobBuilder = new CustomAttributeBlobBuilder();

            blobBuilder.AddFixedArg(typeRefCoClass.FullName);
            m_typeBuilder.SetCustomAttribute(ctorCoClassAttribute, blobBuilder.GetBlob());
        }
 public InterfaceInfo(ConverterInfo info, TypeBuilder typeBuilder, bool supportsDispatch, TypeInfo type, TypeAttr attr, bool bCoClass, bool bSource, TypeInfo implementingInterface)
 {
     Init(info, typeBuilder, supportsDispatch, type, attr, bCoClass, bSource, implementingInterface);
 }
        private void Init(ConverterInfo info, TypeBuilder typeBuilder, bool emitDispId, TypeInfo type, TypeAttr attr, bool bCoClass, bool bSource, TypeInfo implementingInterface)
        {
            m_typeStack = new Stack <TypeInfo>();

            m_attrStack = new Stack <TypeAttr>();
            PushType(type, attr);

            m_info                         = info;
            m_typeBuilder                  = typeBuilder;
            m_emitDispId                   = emitDispId;
            m_bCoClass                     = bCoClass;
            m_propertyInfo                 = new PropertyInfo(this);
            m_bSource                      = bSource;
            IsConversionLoss               = false;
            IsDefaultInterface             = false;
            m_currentSlot                  = 0;
            m_currentImplementingInterface = implementingInterface;
        }
 public void PushType(TypeInfo type, TypeAttr attr)
 {
     m_typeStack.Push(type);
     m_attrStack.Push(attr);
 }
Exemple #29
0
        public AssemblyBuilder DoProcess(
            Object typeLib,
            string asmFilename,
            TypeLibImporterFlags flags,
            ITypeLibImporterNotifySink notifySink,
            byte[] publicKey,
            StrongNameKeyPair keyPair,
            string asmNamespace,
            Version asmVersion,
            bool isVersion2,
            bool isPreserveSig,
            bool isRemoveEnumPrefix)
        {
            m_resolver = notifySink;

            TypeLib tlb = new TypeLib((ITypeLib)typeLib);

            if (asmNamespace == null)
            {
                asmNamespace = tlb.GetDocumentation();

                string fileName = System.IO.Path.GetFileNameWithoutExtension(asmFilename);
                if (fileName != asmNamespace)
                {
                    asmNamespace = fileName;
                }

                //
                // Support for GUID_ManagedName (for namespace)
                //
                string customManagedNamespace = tlb.GetCustData(CustomAttributeGuids.GUID_ManagedName) as string;
                if (customManagedNamespace != null)
                {
                    customManagedNamespace = customManagedNamespace.Trim();
                    if (customManagedNamespace.ToUpper().EndsWith(".DLL"))
                    {
                        customManagedNamespace = customManagedNamespace.Substring(0, customManagedNamespace.Length - 4);
                    }
                    else if (customManagedNamespace.ToUpper().EndsWith(".EXE"))
                    {
                        customManagedNamespace = customManagedNamespace.Substring(0, customManagedNamespace.Length - 4);
                    }

                    asmNamespace = customManagedNamespace;
                }
            }

            //
            // Check for GUID_ExportedFromComPlus
            //
            object value = tlb.GetCustData(CustomAttributeGuids.GUID_ExportedFromComPlus);

            if (value != null)
            {
                // Make this a critical failure, instead of returning null which will be ignored.
                throw new TlbImpGeneralException(Resource.FormatString("Err_CircularImport", asmNamespace), ErrorCode.Err_CircularImport);
            }

            string strModuleName = asmFilename;

            if (asmFilename.Contains("\\"))
            {
                int nIndex;
                for (nIndex = strModuleName.Length; strModuleName[nIndex - 1] != '\\'; --nIndex)
                {
                    ;
                }
                strModuleName = strModuleName.Substring(nIndex);
            }

            // If the version information was not specified, then retrieve it from the typelib.
            if (asmVersion == null)
            {
                using (TypeLibAttr attr = tlb.GetLibAttr())
                {
                    asmVersion = new Version(attr.wMajorVerNum, attr.wMinorVerNum, 0, 0);
                }
            }

            // Assembly name should not have .DLL
            // while module name must contain the .DLL
            string strAsmName = String.Copy(strModuleName);

            if (strAsmName.EndsWith(".DLL", StringComparison.InvariantCultureIgnoreCase))
            {
                strAsmName = strAsmName.Substring(0, strAsmName.Length - 4);
            }

            AssemblyName assemblyName = new AssemblyName();

            assemblyName.Name = strAsmName;
            assemblyName.SetPublicKey(publicKey);
            assemblyName.Version = asmVersion;
            assemblyName.KeyPair = keyPair;

            m_assemblyBuilder = CreateAssemblyBuilder(assemblyName, tlb, flags);

            m_moduleBuilder = CreateModuleBuilder(m_assemblyBuilder, strModuleName);

            // Add a listener for the reflection load only resolve events.
            AppDomain           currentDomain     = Thread.GetDomain();
            ResolveEventHandler asmResolveHandler = new ResolveEventHandler(ReflectionOnlyResolveAsmEvent);

            currentDomain.ReflectionOnlyAssemblyResolve += asmResolveHandler;

            ConverterSettings settings;

            settings.m_isGenerateClassInterfaces = true;
            settings.m_namespace          = asmNamespace;
            settings.m_flags              = flags;
            settings.m_isVersion2         = isVersion2;
            settings.m_isPreserveSig      = isPreserveSig;
            settings.m_isRemoveEnumPrefix = isRemoveEnumPrefix;

            m_converterInfo = new ConverterInfo(m_moduleBuilder, tlb, m_resolver, settings);

            //
            // Generate class interfaces
            // NOTE:
            // We have to create class interface ahead of time because of the need to convert default interfaces to
            // class interfafces. However, this creates another problem that the event interface is always named first
            // before the other interfaces, because we need to create the type builder for the event interface first
            // so that we can create a class interface that implement it. But in the previous version of TlbImp,
            // it doesn't have to do that because it can directly create a typeref with the class interface name,
            // without actually creating anything like the TypeBuilder. The result is that the name would be different
            // with interop assemblies generated by old tlbimp in this case.
            // Given the nature of reflection API, this cannot be easily workarounded unless we switch to metadata APIs.
            // I believe this is acceptable because this only happens when:
            // 1. People decide to migrate newer .NET framework
            // 2. The event interface name conflicts with a normal interface
            //
            // In this case the problem can be easily fixed with a global refactoring, so I wouldn't worry about that
            //
            if (m_converterInfo.GenerateClassInterfaces)
            {
                CreateClassInterfaces();
            }

            //
            // Generate the remaining types except coclass
            // Because during creating coclass, we require every type, including all the referenced type to be created
            // This is a restriction of reflection API that when you override a method in parent interface, the method info
            // is needed so the type must be already created and loaded
            //
            List <TypeInfo> coclassList = new List <TypeInfo>();
            int             nCount      = tlb.GetTypeInfoCount();

            for (int n = 0; n < nCount; ++n)
            {
                TypeInfo type = null;
                try
                {
                    type = tlb.GetTypeInfo(n);
                    string strType = type.GetDocumentation();

                    TypeInfo typeToProcess;
                    TypeAttr attrToProcess;

                    using (TypeAttr attr = type.GetTypeAttr())
                    {
                        TYPEKIND kind = attr.typekind;
                        if (kind == TYPEKIND.TKIND_ALIAS)
                        {
                            ConvCommon.ResolveAlias(type, attr.tdescAlias, out typeToProcess, out attrToProcess);
                            if (attrToProcess.typekind == TYPEKIND.TKIND_ALIAS)
                            {
                                continue;
                            }
                            else
                            {
                                // We need to duplicate the definition of the user defined type in the name of the alias
                                kind          = attrToProcess.typekind;
                                typeToProcess = type;
                                attrToProcess = attr;
                            }
                        }
                        else
                        {
                            typeToProcess = type;
                            attrToProcess = attr;
                        }

                        switch (kind)
                        {
                        // Process coclass later because of reflection API requirements
                        case TYPEKIND.TKIND_COCLASS:
                            coclassList.Add(typeToProcess);
                            break;

                        case TYPEKIND.TKIND_ENUM:
                            m_converterInfo.GetEnum(typeToProcess, attrToProcess);
                            break;

                        case TYPEKIND.TKIND_DISPATCH:
                        case TYPEKIND.TKIND_INTERFACE:
                            m_converterInfo.GetInterface(typeToProcess, attrToProcess);
                            break;

                        case TYPEKIND.TKIND_MODULE:
                            m_converterInfo.GetModule(typeToProcess, attrToProcess);
                            break;

                        case TYPEKIND.TKIND_RECORD:
                            m_converterInfo.GetStruct(typeToProcess, attrToProcess);
                            break;

                        case TYPEKIND.TKIND_UNION:
                            m_converterInfo.GetUnion(typeToProcess, attrToProcess);
                            break;
                        }

                        m_converterInfo.ReportEvent(
                            MessageCode.Msg_TypeInfoImported,
                            Resource.FormatString("Msg_TypeInfoImported", typeToProcess.GetDocumentation()));
                    }
                }
                catch (ReflectionTypeLoadException)
                {
                    throw; // Fatal failure. Throw
                }
                catch (TlbImpResolveRefFailWrapperException)
                {
                    throw; // Fatal failure. Throw
                }
                catch (TlbImpGeneralException)
                {
                    throw; // Fatal failure. Throw
                }
                catch (TypeLoadException)
                {
                    throw; // TypeLoadException is critical. Throw.
                }
                catch (Exception)
                {
                }
            }

            // Process coclass after processing all the other types
            foreach (TypeInfo type in coclassList)
            {
                using (TypeAttr attr = type.GetTypeAttr())
                {
                    try
                    {
                        m_converterInfo.GetCoClass(type, attr);
                    }
                    catch (ReflectionTypeLoadException)
                    {
                        throw; // Fatal failure. Throw
                    }
                    catch (TlbImpResolveRefFailWrapperException)
                    {
                        throw; // Fatal failure. Throw
                    }
                    catch (TlbImpGeneralException)
                    {
                        throw; // Fatal failure. Throw
                    }
                    catch (TypeLoadException)
                    {
                        throw; // TypeLoadException is critical. Throw.
                    }
                    catch (Exception)
                    {
                    }
                }
            }

            //
            // Build an array of EventItfInfo & generate event provider / event sink helpers
            //

            Event.TCEAdapterGenerator eventAdapterGenerator = new Event.TCEAdapterGenerator();
            List <Event.EventItfInfo> eventItfList          = new List <Event.EventItfInfo>();

            foreach (IConvBase symbol in m_converterInfo.GetAllConvBase)
            {
                IConvInterface convInterface = symbol as IConvInterface;
                if (convInterface != null)
                {
                    if (convInterface.EventInterface != null)
                    {
                        Debug.Assert(convInterface.EventInterface is ConvEventInterfaceLocal);
                        ConvEventInterfaceLocal local = convInterface.EventInterface as ConvEventInterfaceLocal;

                        Type eventInterfaceType = convInterface.EventInterface.ManagedType;

                        // Build EventItfInfo and add to the list
                        Type               sourceInterfaceType = convInterface.ManagedType;
                        string             sourceInterfaceName = sourceInterfaceType.FullName;
                        Event.EventItfInfo eventItfInfo        = new Event.EventItfInfo(
                            eventInterfaceType.FullName,
                            sourceInterfaceName,
                            local.EventProviderName,
                            eventInterfaceType,
                            convInterface.ManagedType);
                        eventItfList.Add(eventItfInfo);
                    }
                }
            }

            eventAdapterGenerator.Process(m_moduleBuilder, eventItfList);

            return(m_assemblyBuilder);
        }
Exemple #30
0
        /// <summary>
        /// Collect information
        /// </summary>
        private void Collect()
        {
            // Remember all the interface name to coclass name mapping
            Hashtable interfaceToCoClassMapping = new Hashtable();

            //
            // For every coclass
            //
            int nCount = m_typeLib.GetTypeInfoCount();

            for (int n = 0; n < nCount; ++n)
            {
                TypeInfo type = m_typeLib.GetTypeInfo(n);
                //
                // Walk the list of implemented interfaces
                //
                using (TypeAttr attr = type.GetTypeAttr())
                {
                    if (attr.typekind == TYPEKIND.TKIND_COCLASS)
                    {
                        DefaultInterfaceInfo defaultInterfaceInfo = new DefaultInterfaceInfo();
                        defaultInterfaceInfo.coclass     = type;
                        defaultInterfaceInfo.coclassName = type.GetDocumentation();

                        for (int m = 0; m < attr.cImplTypes; ++m)
                        {
                            IMPLTYPEFLAGS flags    = type.GetImplTypeFlags(m);
                            bool          bDefault = (flags & IMPLTYPEFLAGS.IMPLTYPEFLAG_FDEFAULT) != 0;

                            // For invalid default interfaces, such as
                            // coclass MyObj
                            // {
                            //     [default] interface IUnknown;
                            //     interface IA;
                            // }
                            // to use the first valid interface, which is IA;
                            // if (!bDefault) continue;

                            bool bSource = (flags & IMPLTYPEFLAGS.IMPLTYPEFLAG_FSOURCE) != 0;

                            TypeInfo typeImpl = type.GetRefType(m);

                            using (TypeAttr attrImpl = typeImpl.GetTypeAttr())
                            {
                                // Skip IUnknown & IDispatch
                                if (attrImpl.Guid == WellKnownGuids.IID_IDispatch ||
                                    attrImpl.Guid == WellKnownGuids.IID_IUnknown)
                                {
                                    continue;
                                }

                                // Skip non-dispatch interfaces that doesn't derive from IUnknown
                                if (!attrImpl.IsDispatch && !ConvCommon.IsDerivedFromIUnknown(typeImpl))
                                {
                                    continue;
                                }

                                string name = typeImpl.GetDocumentation();

                                if (bSource)
                                {
                                    // Default source interface
                                    if (bDefault ||                                             // If explicitly stated as default, use that
                                        defaultInterfaceInfo.defaultSourceInterface == null)    // otherwise, try to use the first one
                                    {
                                        defaultInterfaceInfo.defaultSourceInterface     = typeImpl;
                                        defaultInterfaceInfo.defaultSourceInterfaceName = name;
                                    }
                                }
                                else
                                {
                                    // Default interface
                                    if (bDefault ||                                     // If explicitly stated as default, use that
                                        defaultInterfaceInfo.defaultInterface == null)  // otherwise, try to use the first one
                                    {
                                        defaultInterfaceInfo.defaultInterface     = typeImpl;
                                        defaultInterfaceInfo.defaultInterfaceName = name;
                                    }
                                }
                            }
                        }

                        //
                        // Walk through the list of implemented interfaces again. This time we remember all the implemented interfaces (including base)
                        //
                        for (int m = 0; m < attr.cImplTypes; ++m)
                        {
                            TypeInfo typeImpl = type.GetRefType(m);
                            string   name     = typeImpl.GetDocumentation();

                            while (typeImpl != null)
                            {
                                // If we arleady seen this interface
                                if (interfaceToCoClassMapping.Contains(name))
                                {
                                    // and if it is for a different interface
                                    if ((string)interfaceToCoClassMapping[name] != defaultInterfaceInfo.coclassName)
                                    {
                                        // Set the name to null so that we know we've seen other interfaces
                                        interfaceToCoClassMapping[name] = null;
                                    }
                                }
                                else
                                {
                                    interfaceToCoClassMapping.Add(name, defaultInterfaceInfo.coclassName);
                                }

                                TypeAttr attrImpl = typeImpl.GetTypeAttr();
                                if (attrImpl.cImplTypes == 1)
                                {
                                    typeImpl = typeImpl.GetRefType(0);
                                }
                                else
                                {
                                    typeImpl = null;
                                }
                            }
                        }

                        // We do allow coclass that doesn't have any 'valid' default interfaces to have a class interface
                        // For example,
                        // coclass MyObject {
                        //     [default] interface IUnknown;
                        // }
                        m_defaultInterfaceInfoList.Add(defaultInterfaceInfo);
                    }
                }
            }

            foreach (DefaultInterfaceInfo defaultInterfaceInfo in m_defaultInterfaceInfoList)
            {
                bool isExclusive = true;
                if (defaultInterfaceInfo.defaultInterface != null)
                {
                    if (interfaceToCoClassMapping.Contains(defaultInterfaceInfo.defaultInterfaceName))
                    {
                        if (interfaceToCoClassMapping[defaultInterfaceInfo.defaultInterfaceName] == null)
                        {
                            isExclusive = false;
                        }
                    }
                    defaultInterfaceInfo.isExclusive = isExclusive;
                }
            }
        }