示例#1
0
        /// <summary>
        /// Gets the generated managed name from the namespace & typeinfo name
        /// </summary>
        private string GetGeneratedManagedName(TypeInfo type, bool useDefaultNamespace)
        {
            string docName = type.GetDocumentation();

            //
            // Figure out assembly namespace (using best guess)
            //
            string tlbNamespace;

            if (useDefaultNamespace)
            {
                tlbNamespace = GetNamespaceForTypeLib(type, m_typeLib);
            }
            else
            {
                TypeLib typeLib = type.GetContainingTypeLib();
                tlbNamespace = GetNamespaceForTypeLib(type, typeLib);
            }

            if (string.IsNullOrEmpty(tlbNamespace))
            {
                return(docName);
            }
            else
            {
                return(tlbNamespace + "." + docName);
            }
        }
示例#2
0
        public string GetCustomNamespaceForTypeLib(TypeLib typeLib)
        {
            //
            // Support for GUID_ManagedName (for namespace)
            // Favor the custom name over everything else including /namespace option
            //
            string customManagedNamespace = typeLib.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);
                }

                return(customManagedNamespace);
            }

            return(null);
        }
示例#3
0
        /// <summary>
        /// Gets the namespace for the type lib
        /// </summary>
        private string GetNamespaceForTypeLib(TypeInfo type, TypeLib typeLib)
        {
            using (TypeLibAttr attr = typeLib.GetLibAttr())
            {
                string tlbNamespace = GetCustomNamespaceForTypeLib(typeLib);
                if (tlbNamespace != null)
                {
                    return(tlbNamespace);
                }

                if (attr.guid == m_libid)
                {
                    tlbNamespace = m_settings.m_namespace;
                }
                else
                {
                    tlbNamespace = typeLib.GetDocumentation();

                    if (tlbNamespace.IndexOfAny(m_invalidChars) >= 0)
                    {
                        string tlbFilePath;
                        Guid   tlbGuid = attr.guid;
                        int    hr      = TypeLib.QueryPathOfRegTypeLib(ref tlbGuid, (ushort)attr.wMajorVerNum, (ushort)attr.wMinorVerNum, (int)attr.lcid, out tlbFilePath);

                        ReportEvent(
                            WarningCode.Wrn_InvalidNamespace,
                            Resource.FormatString("Wrn_InvalidNamespace", tlbFilePath, tlbNamespace));

                        throw new TlbImpInvalidTypeConversionException(type);
                    }
                }

                return(tlbNamespace);
            }
        }
示例#4
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);
            }
        }
示例#5
0
        public ConverterAssemblyInfo(ConverterInfo info, Assembly assembly, TypeLib typeLib)
        {
            m_assembly = assembly;
            m_typeLib  = typeLib;
            m_info     = info;

            m_classInterfaceMap = new ClassInterfaceMap(m_typeLib);

            // Try GUID_ManagedName
            m_tlbNamespace = m_info.GetCustomNamespaceForTypeLib(typeLib);
            if (m_tlbNamespace == null)
            {
                // Try to use the namespace of the first type
                Type[] types = assembly.GetTypes();
                if (types.Length > 0)
                {
                    m_tlbNamespace = types[0].Namespace;
                }
            }

            // Otherwise use the type library name
            if (m_tlbNamespace == null)
            {
                m_tlbNamespace = m_typeLib.GetDocumentation();
            }
        }
示例#6
0
        public ClassInterfaceMap(TypeLib typeLib)
        {
            m_typeLib = typeLib;
            m_defaultInterfaceInfoList = new List <DefaultInterfaceInfo>();

            Collect();
        }
示例#7
0
        /// <summary>
        /// Is this type a StdOle2.Guid? The test is done using the GUID of type library
        /// </summary>
        /// <param name="type">The type</param>
        /// <returns>True if this type is a StdOle2.Guid</returns>
        private bool _IsStdOleGuid(TypeInfo type)
        {
            TypeLib typeLib = type.GetContainingTypeLib();

            using (TypeLibAttr typeLibAttr = typeLib.GetLibAttr())
            {
                if (type.GetDocumentation() == "GUID" &&
                    typeLibAttr.guid == WellKnownGuids.TYPELIBID_STDOLE2)
                {
                    return(true);
                }
            }

            return(false);
        }
示例#8
0
        public ConverterInfo(ModuleBuilder moduleBuilder, TypeLib typeLib, System.Runtime.InteropServices.ITypeLibImporterNotifySink resolver, ConverterSettings settings)
        {
            m_moduleBuilder = moduleBuilder;
            m_typeLib       = typeLib;
            m_resolver      = resolver;

            using (TypeLibAttr attr = m_typeLib.GetLibAttr())
            {
                m_libid = attr.guid;
            }

            m_typeLibMappingTable  = new Dictionary <Guid, ConverterAssemblyInfo>();
            m_symbolTable          = new Dictionary <string, IConvBase>();
            m_settings             = settings;
            m_memberTables         = new Dictionary <string, MemberTable>();
            m_typeTable            = new Hashtable();
            m_bTransformDispRetVal = (settings.m_flags & TypeLibImporterFlags.TransformDispRetVals) != 0;
            m_defaultMemberTable   = new Dictionary <TypeBuilder, bool>();

            BuildGlobalNameTable();
        }
示例#9
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());
        }
示例#10
0
        private bool ResolveInternal(TypeInfo type, ConvType convType, out IConvBase convBase)
        {
            IConvBase ret = null;

            // See if it is already mapped
            if (!m_symbolTable.TryGetValue(GetInternalEncodedManagedName(type, convType), out ret))
            {
                TypeLib typeLib = type.GetContainingTypeLib();
                Guid    libid;
                using (TypeLibAttr libAttr = typeLib.GetLibAttr())
                {
                    libid = libAttr.guid;
                }
                // See if this is defined in a different type library
                if (libid != m_libid)
                {
                    ConverterAssemblyInfo converterAssemblyInfo = null;
                    // See if we have not already imported this assembly
                    if (!m_typeLibMappingTable.TryGetValue(libid, out converterAssemblyInfo))
                    {
                        Assembly assembly = null;
                        string   asmName  = typeLib.GetCustData(CustomAttributeGuids.GUID_ExportedFromComPlus) as string;
                        if (asmName != null)
                        {
                            try
                            {
                                assembly = Assembly.ReflectionOnlyLoad(asmName);
                            }
                            catch (Exception)
                            {
                            }
                        }

                        if (assembly == null)
                        {
                            try
                            {
                                assembly = m_resolver.ResolveRef(typeLib.GetTypeLib());
                            }
                            catch (TlbImpResolveRefFailWrapperException)
                            {
                                // Avoid wrapping wrapper with wrapper exception
                                throw;
                            }
                            catch (Exception ex)
                            {
                                throw new TlbImpResolveRefFailWrapperException(ex);
                            }
                        }

                        if (assembly == null)
                        {
                            // null means that the resolver has failed and we should skip this failure and continue with the next type
                            throw new TlbImpInvalidTypeConversionException(type);
                        }

                        converterAssemblyInfo = new ConverterAssemblyInfo(this, assembly, typeLib);
                        m_typeLibMappingTable.Add(libid, converterAssemblyInfo);
                    }

                    string expectedName;
                    Type   convertedType = converterAssemblyInfo.ResolveType(type, convType, out expectedName);
                    if (convertedType == null)
                    {
                        throw new TlbImpGeneralException(
                                  Resource.FormatString("Err_CanotFindReferencedType", expectedName, converterAssemblyInfo.Assembly.FullName),
                                  ErrorCode.Err_CanotFindReferencedType);
                    }
                    else
                    {
                        // Create external IConvBase instance
                        switch (convType)
                        {
                        case ConvType.Interface:
                            ret = new ConvInterfaceExternal(this, type, convertedType, converterAssemblyInfo);
                            break;

                        case ConvType.Enum:
                            ret = new ConvEnumExternal(this, type, convertedType);
                            break;

                        case ConvType.Struct:
                            ret = new ConvStructExternal(this, type, convertedType);
                            break;

                        case ConvType.Union:
                            ret = new ConvUnionExternal(this, type, convertedType);
                            break;

                        case ConvType.ClassInterface:
                            Debug.Assert(false, "Only ConvCoClassExternal can create ConvClassInterfaceExternal");
                            break;

                        case ConvType.EventInterface:
                            Debug.Assert(false, "We should not reference a external event interface!");
                            break;

                        case ConvType.CoClass:
                            ret = new ConvCoClassExternal(this, type, convertedType, converterAssemblyInfo);
                            break;
                        }
                    }
                }
            }
            convBase = ret;
            return(ret != null);
        }
示例#11
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);
        }
示例#12
0
        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;
        }