public AssemblyBuilder DoProcess( Object typeLib, string asmFilename, TypeLibImporterFlags flags, ITypeLibImporterNotifySink notifySink, byte[] publicKey, StrongNameKeyPair keyPair, string asmNamespace, Version asmVersion, bool isVersion2, bool isPreserveSig, string ruleSetFileName) { m_resolver = notifySink; TypeLib tlb = new TypeLib((TypeLibTypes.Interop.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 = 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; RuleEngine.InitRuleEngine(new TlbImpActionManager(), new TlbImpCategoryManager(), new TlbImpConditionManager(), new TlbImpOperatorManager()); if (ruleSetFileName != null) { try { RuleFileParser parser = new RuleFileParser(ruleSetFileName); settings.m_ruleSet = parser.Parse(); } catch (Exception ex) { Output.WriteWarning(Resource.FormatString("Wrn_LoadRuleFileFailed", ruleSetFileName, ex.Message), WarningCode.Wrn_LoadRuleFileFailed); settings.m_ruleSet = null; } } else { settings.m_ruleSet = null; } 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 // var coclassList = new List<TypeInfo>(); int nCount = tlb.GetTypeInfoCount(); for (int n = 0; n < nCount; ++n) { try { TypeInfo type = tlb.GetTypeInfo(n); string strType = type.GetDocumentation(); using (TypeAttr attr = type.GetTypeAttr()) { TypeLibTypes.Interop.TYPEKIND kind = attr.typekind; TypeInfo typeToProcess; TypeAttr attrToProcess; if (kind == TypeLibTypes.Interop.TYPEKIND.TKIND_ALIAS) { ConvCommon.ResolveAlias(type, attr.tdescAlias, out typeToProcess, out attrToProcess); if (attrToProcess.typekind == TypeLibTypes.Interop.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 TypeLibTypes.Interop.TYPEKIND.TKIND_COCLASS: coclassList.Add(typeToProcess); break; case TypeLibTypes.Interop.TYPEKIND.TKIND_ENUM: m_converterInfo.GetEnum(typeToProcess, attrToProcess); break; case TypeLibTypes.Interop.TYPEKIND.TKIND_DISPATCH: case TypeLibTypes.Interop.TYPEKIND.TKIND_INTERFACE: m_converterInfo.GetInterface(typeToProcess, attrToProcess); break; case TypeLibTypes.Interop.TYPEKIND.TKIND_MODULE: m_converterInfo.GetModule(typeToProcess, attrToProcess); break; case TypeLibTypes.Interop.TYPEKIND.TKIND_RECORD: m_converterInfo.GetStruct(typeToProcess, attrToProcess); break; case TypeLibTypes.Interop.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 // var eventAdapterGenerator = new Event.TCEAdapterGenerator(); var eventItfList = new List<Event.EventItfInfo>(); foreach (IConvBase symbol in m_converterInfo.GetAllConvBase) { var convInterface = symbol as IConvInterface; if (convInterface != null) { if (convInterface.EventInterface != null) { Debug.Assert(convInterface.EventInterface is ConvEventInterfaceLocal); var 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; }
public int ResolveTypeLib(string simpleName, Guid tlbId, int lcid, ushort majorVersion, ushort minorVersion, TypeLibTypes.Interop.SYSKIND syskind, out string bstrPathName) { // Remember the type lib info s_MissingTypeLibInfo = new TypeLibInfo(); s_MissingTypeLibInfo.name = simpleName; s_MissingTypeLibInfo.guid = tlbId; s_MissingTypeLibInfo.majorVersion = majorVersion; s_MissingTypeLibInfo.minorVersion = minorVersion; // // Find this type library in list of referenced type libraries // foreach (string pathName in s_RefTypeLibraries.Keys) { TypeLib refTypeLib = new TypeLib(s_RefTypeLibraries[pathName] as TypeLibTypes.Interop.ITypeLib); TypeLibAttr libAttr = refTypeLib.GetLibAttr(); if (libAttr.guid == tlbId) { if (libAttr.wMajorVerNum == majorVersion && libAttr.wMinorVerNum == minorVersion) { // Resolved to a matching type lib bstrPathName = pathName; return 0; } } } // // Find using GUID // int hr = TypeLib.QueryPathOfRegTypeLib(ref tlbId, majorVersion, minorVersion, lcid, out bstrPathName); if (hr >= 0) { // Try loading the type library and verify guid/version hr = TryLoadTypeLib(bstrPathName, simpleName, tlbId, majorVersion, minorVersion); if (hr >= 0) return hr; } // // Try to load current directory // bstrPathName = Path.Combine(Directory.GetCurrentDirectory(), simpleName); if (File.Exists(bstrPathName)) { // Try loading the type library guid/version hr = TryLoadTypeLib(bstrPathName, simpleName, tlbId, majorVersion, minorVersion); if (hr >= 0) return hr; } if (TlbImpCode.s_Options.m_bVerboseMode) { Output.WriteInfo( Resource.FormatString("Msg_TypeLibRefResolveFailed", new object[] { simpleName, majorVersion.ToString() + "." + minorVersion, tlbId.ToString() }), MessageCode.Msg_TypeLibRefResolveFailed); } return -1; }
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; } }
/// <summary> /// Try to load the type library and verify guid/version /// </summary> /// <returns>HRESULT. >=0 if succeeds, otherwise failed</returns> private static int TryLoadTypeLib(string pathName, string simpleName, Guid tlbId, ushort majorVersion, ushort minorVersion) { TypeLibTypes.Interop.ITypeLib typeLib; int hr = TypeLib.LoadTypeLib(pathName, out typeLib); if (hr >= 0) { s_RefTypeLibraries.Add(pathName, typeLib as System.Runtime.InteropServices.ComTypes.ITypeLib); TypeLib refTypeLib = new TypeLib(typeLib); TypeLibAttr libAttr = refTypeLib.GetLibAttr(); if (libAttr.guid == tlbId && libAttr.wMajorVerNum == majorVersion && libAttr.wMinorVerNum == minorVersion) { if (TlbImpCode.s_Options.m_bVerboseMode) { Output.WriteInfo( Resource.FormatString("Msg_TypeLibRefResolved", new object[] { simpleName, majorVersion.ToString() + "." + minorVersion, tlbId.ToString(), pathName }), MessageCode.Msg_TypeLibRefResolved); } return 0; } else { if (TlbImpCode.s_Options.m_bVerboseMode) { Output.WriteInfo( Resource.FormatString("Msg_TypeLibRefMismatch", new object[] { simpleName, majorVersion.ToString() + "." + minorVersion, tlbId.ToString(), simpleName, libAttr.wMajorVerNum.ToString() + "." + libAttr.wMajorVerNum.ToString(), libAttr.guid, pathName }), MessageCode.Msg_TypeLibRefMismatch); } return -1; } } return hr; }