Example #1
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);
        }
Example #2
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);
        }
Example #3
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);
        }