Exemple #1
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));
            }
        }
Exemple #2
0
        public AssemblyBuilder CreateAssemblyBuilder(AssemblyName name, TypeLib tlb, TypeLibImporterFlags flags)
        {
            using (TypeLibAttr attr = tlb.GetLibAttr())
            {
                // New assembly as well as loaded assembly should be all in a ReflectionOnly context as we don't need to run the code
                AssemblyBuilder assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(name, AssemblyBuilderAccess.ReflectionOnly);

                // Handle the type library name
                assemblyBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForImportedFromTypeLib(tlb.GetDocumentation()));

                // Handle the type library version
                assemblyBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForTypeLibVersion(attr.wMajorVerNum, attr.wMinorVerNum));

                // Handle the LIBID
                assemblyBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForGuid(attr.guid));

                // If we are generating a PIA, then set the PIA custom attribute.
                if ((flags & TypeLibImporterFlags.PrimaryInteropAssembly) != 0)
                {
                    assemblyBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForPrimaryInteropAssembly(attr.wMajorVerNum, attr.wMinorVerNum));
                }

                return(assemblyBuilder);
            }
        }
Exemple #3
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);
        }
        /// <summary>
        /// Does the type need custom marshaler for marshalling?
        /// </summary>
        /// <returns>Whether we need to use custom marshaler</returns>
        private bool TryUseCustomMarshaler(Guid iid, out Type result)
        {
            result = null;

            if (iid == WellKnownGuids.IID_IDispatchEx)
            {
                Type type = typeof(System.Runtime.InteropServices.CustomMarshalers.ExpandoToDispatchExMarshaler);
                m_attribute = CustomAttributeHelper.GetBuilderForMarshalAsCustomMarshaler(type, "IExpando");
                SetUnmanagedType(UnmanagedType.CustomMarshaler);
                result = typeof(System.Runtime.InteropServices.Expando.IExpando);
                return(true);
            }
            else if (iid == WellKnownGuids.IID_IEnumVARIANT)
            {
                Type type = typeof(System.Runtime.InteropServices.CustomMarshalers.EnumeratorToEnumVariantMarshaler);
                m_attribute = CustomAttributeHelper.GetBuilderForMarshalAsCustomMarshaler(type, null);
                SetUnmanagedType(UnmanagedType.CustomMarshaler);
                result = typeof(System.Collections.IEnumerator);
                return(true);
            }
            else if (iid == WellKnownGuids.IID_ITypeInfo)
            {
                Type type = typeof(System.Runtime.InteropServices.CustomMarshalers.TypeToTypeInfoMarshaler);
                m_attribute = CustomAttributeHelper.GetBuilderForMarshalAsCustomMarshaler(type, null);
                SetUnmanagedType(UnmanagedType.CustomMarshaler);
                result = typeof(Type);
                return(true);
            }

            return(false);
        }
Exemple #5
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);
        }
 public void SetDefaultMember(TypeBuilder typeBuilder, string name)
 {
     if (!m_defaultMemberTable.ContainsKey(typeBuilder))
     {
         typeBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForDefaultMember(name));
         m_defaultMemberTable.Add(typeBuilder, true);
     }
 }
        /// <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]);
        }
Exemple #8
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 #9
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 #10
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 #11
0
        protected void DefineType(ConverterInfo info, TypeInfo typeInfo, bool dealWithAlias)
        {
            m_info     = info;
            m_typeInfo = typeInfo;

            if (dealWithAlias)
            {
                m_nonAliasedTypeInfo = ConvCommon.GetAlias(typeInfo);
            }
            else
            {
                m_nonAliasedTypeInfo = typeInfo;
            }

            try
            {
                OnDefineType();

                //
                // Emit SuppressUnmanagedCodeSecurityAttribute for /unsafe switch
                //
                if ((m_info.Settings.m_flags & TypeLibImporterFlags.UnsafeInterfaces) != 0)
                {
                    if (ConvType != ConvType.ClassInterface && ConvType != ConvType.EventInterface)
                    {
                        m_typeBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForSuppressUnmanagedCodeSecurity());
                    }
                }
            }
            catch (ReflectionTypeLoadException)
            {
                throw; // Fatal failure. Throw
            }
            catch (TlbImpResolveRefFailWrapperException)
            {
                throw; // Fatal failure. Throw
            }
            catch (TlbImpGeneralException)
            {
                throw; // Fatal failure. Throw
            }
            catch (Exception)
            {
                string name = String.Empty;
                if (m_typeInfo != null)
                {
                    try
                    {
                        name = m_typeInfo.GetDocumentation();
                    }
                    catch (Exception)
                    {
                    }
                }

                if (name != String.Empty)
                {
                    string msg = Resource.FormatString("Wrn_InvalidTypeInfo", name);
                    m_info.ReportEvent(WarningCode.Wrn_InvalidTypeInfo, msg);
                }
                else
                {
                    string msg = Resource.FormatString("Wrn_InvalidTypeInfo_Unnamed");
                    m_info.ReportEvent(WarningCode.Wrn_InvalidTypeInfo_Unnamed, msg);
                }

                // When failure, try to create the type anyway
                if (m_typeBuilder != null)
                {
                    m_type = m_typeBuilder.CreateType();
                }
            }
        }
Exemple #12
0
        /// <summary>
        /// Generate properties for Functions
        /// </summary>
        public void GenerateProperty(InterfaceInfo info, TypeBuilder typebuilder)
        {
            // Generate property using unique name
            string uniqueName = info.GenerateUniqueMemberName(
                m_propertyInfo.RecommendedName,
                null,
                MemberTypes.Property);

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

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

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

                FuncDesc bestFuncDesc = m_propertyInfo.BestFuncDesc;

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

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

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

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

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

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

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

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

                paramTypes = paramTypeList.ToArray();
            }

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

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

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

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

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

            // Handle alias information
            ConvCommon.HandleAlias(info.ConverterInfo, info.RefTypeInfo, m_propertyInfo.PropertyTypeDesc, propertyBuilder);
        }
        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;
        }
        /// <summary>
        /// Create the event interface
        /// </summary>
        public override void OnCreate()
        {
            if (m_type != null)
            {
                return;
            }

            string name = m_convInterface.ManagedName;

            m_convInterface.Create();

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

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

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

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

                blobBuilder.AddFixedArg(eventInterfaceFullyQualifiedName);                      // source interface

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

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

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

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

                bool isConversionLoss = false;

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

                    isConversionLoss = true;
                }

                //
                // Create event interface
                //

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

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

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

            m_type = m_typeBuilder.CreateType();
        }
Exemple #15
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)
            {
                m_convInterface.AssociateWithExclusiveClassInterface(this as IConvClassInterface);
            }

            // Emit GuidAttribute, which is the same as the default interface, if it exists
            if (defaultInterfaceType != null)
            {
                ConvCommon.DefineGuid(m_convInterface.RefTypeInfo, m_convInterface.RefNonAliasedTypeInfo, 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;

            m_typeBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForCoClass(typeRefCoClass));
        }
Exemple #16
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 #17
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);
            }
        }
        protected void DefineType(ConverterInfo info, TypeInfo typeInfo, bool dealWithAlias)
        {
            m_info     = info;
            m_typeInfo = typeInfo;

            if (dealWithAlias)
            {
                m_nonAliasedTypeInfo = ConvCommon.GetAlias(typeInfo);
            }
            else
            {
                m_nonAliasedTypeInfo = typeInfo;
            }

            try
            {
                OnDefineType();

                //
                // Emit SuppressUnmanagedCodeSecurityAttribute for /unsafe switch
                //
                if ((m_info.Settings.m_flags & TypeLibImporterFlags.UnsafeInterfaces) != 0)
                {
                    if (ConvType != ConvType.ClassInterface && ConvType != ConvType.EventInterface)
                    {
                        m_typeBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForSuppressUnmanagedCodeSecurity());
                    }
                }

                // Rule Engine AddAttributeAction
                if (m_info.Settings.m_ruleSet != null)
                {
                    ICategory           category = TypeCategory.GetInstance();
                    TypeInfoMatchTarget target   = null;
                    using (TypeAttr attr = m_typeInfo.GetTypeAttr())
                    {
                        TypeLibTypes.Interop.TYPEKIND kind = attr.typekind;
                        target = new TypeInfoMatchTarget(m_typeInfo.GetContainingTypeLib(), m_typeInfo, kind);
                    }
                    AbstractActionManager actionManager     = RuleEngine.GetActionManager();
                    List <Rule>           addAttributeRules = m_info.Settings.m_ruleSet.GetRule(
                        category, AddAttributeActionDef.GetInstance(), target);
                    foreach (Rule rule in addAttributeRules)
                    {
                        AddAttributeAction addAttributeAction = rule.Action as AddAttributeAction;
                        ConstructorInfo    attributeCtor;
                        byte[]             blob;
                        bool success = true;
                        if (addAttributeAction.GetCustomAttribute(out attributeCtor, out blob))
                        {
                            try
                            {
                                m_typeBuilder.SetCustomAttribute(attributeCtor, blob);
                            }
                            catch (Exception)
                            {
                                success = false;
                            }
                        }
                        else
                        {
                            success = false;
                        }
                        if (!success)
                        {
                            string name = m_typeInfo.GetDocumentation();
                            string msg  = Resource.FormatString("Wrn_AddCustomAttributeFailed",
                                                                addAttributeAction.TypeName, name);
                            m_info.ReportEvent(WarningCode.Wrn_AddCustomAttributeFailed, msg);
                        }
                    }
                }
            }
            catch (ReflectionTypeLoadException)
            {
                throw; // Fatal failure. Throw
            }
            catch (TlbImpResolveRefFailWrapperException)
            {
                throw; // Fatal failure. Throw
            }
            catch (TlbImpGeneralException)
            {
                throw; // Fatal failure. Throw
            }
            catch (Exception)
            {
                string name = String.Empty;
                if (m_typeInfo != null)
                {
                    try
                    {
                        name = m_typeInfo.GetDocumentation();
                    }
                    catch (Exception)
                    {
                    }
                }

                if (name != String.Empty)
                {
                    string msg = Resource.FormatString("Wrn_InvalidTypeInfo", name);
                    m_info.ReportEvent(WarningCode.Wrn_InvalidTypeInfo, msg);
                }
                else
                {
                    string msg = Resource.FormatString("Wrn_InvalidTypeInfo_Unnamed");
                    m_info.ReportEvent(WarningCode.Wrn_InvalidTypeInfo_Unnamed, msg);
                }

                // When failure, try to create the type anyway
                if (m_typeBuilder != null)
                {
                    m_type = m_typeBuilder.CreateType();
                }
            }
        }