Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / clr / src / BCL / System / Runtime / InteropServices / TypeLibConverter.cs / 1305376 / TypeLibConverter.cs
// ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== /*============================================================================== ** ** Class: TypeLibConverter ** ** ** Purpose: Component that implements the ITypeLibConverter interface and ** does the actual work of converting a typelib to metadata and ** vice versa. ** ** =============================================================================*/ #if !FEATURE_CORECLR // current implementation requires reflection only load namespace System.Runtime.InteropServices { using System; using System.Diagnostics.Contracts; using System.Collections; using System.Collections.Generic; using System.Threading; using System.Runtime.InteropServices.TCEAdapterGen; using System.IO; using System.Reflection; using System.Reflection.Emit; using System.Configuration.Assemblies; using Microsoft.Win32; using System.Runtime.CompilerServices; using System.Globalization; using System.Security; using System.Security.Permissions; using System.Runtime.InteropServices.ComTypes; using System.Runtime.Versioning; using WORD = System.UInt16; using DWORD = System.UInt32; using _TYPELIBATTR = System.Runtime.InteropServices.ComTypes.TYPELIBATTR; [Guid("F1C3BF79-C3E4-11d3-88E7-00902754C43A")] [ClassInterface(ClassInterfaceType.None)] [System.Runtime.InteropServices.ComVisible(true)] public sealed class TypeLibConverter : ITypeLibConverter { private const String s_strTypeLibAssemblyTitlePrefix = "TypeLib "; private const String s_strTypeLibAssemblyDescPrefix = "Assembly generated from typelib "; private const int MAX_NAMESPACE_LENGTH = 1024; // // ITypeLibConverter interface. // [System.Security.SecuritySafeCritical] // auto-generated [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)] [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public AssemblyBuilder ConvertTypeLibToAssembly([MarshalAs(UnmanagedType.Interface)] Object typeLib, String asmFileName, int flags, ITypeLibImporterNotifySink notifySink, byte[] publicKey, StrongNameKeyPair keyPair, bool unsafeInterfaces) { return ConvertTypeLibToAssembly(typeLib, asmFileName, (unsafeInterfaces ? TypeLibImporterFlags.UnsafeInterfaces : 0), notifySink, publicKey, keyPair, null, null); } [System.Security.SecuritySafeCritical] // auto-generated [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)] [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public AssemblyBuilder ConvertTypeLibToAssembly([MarshalAs(UnmanagedType.Interface)] Object typeLib, String asmFileName, TypeLibImporterFlags flags, ITypeLibImporterNotifySink notifySink, byte[] publicKey, StrongNameKeyPair keyPair, String asmNamespace, Version asmVersion) { // Validate the arguments. if (typeLib == null) throw new ArgumentNullException("typeLib"); if (asmFileName == null) throw new ArgumentNullException("asmFileName"); if (notifySink == null) throw new ArgumentNullException("notifySink"); if (String.Empty.Equals(asmFileName)) throw new ArgumentException(Environment.GetResourceString("Arg_InvalidFileName"), "asmFileName"); if (asmFileName.Length > Path.MAX_PATH) throw new ArgumentException(Environment.GetResourceString("IO.PathTooLong"), asmFileName); if ((flags & TypeLibImporterFlags.PrimaryInteropAssembly) != 0 && publicKey == null && keyPair == null) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_PIAMustBeStrongNamed")); Contract.EndContractBlock(); ArrayList eventItfInfoList = null; // Determine the AssemblyNameFlags AssemblyNameFlags asmNameFlags = AssemblyNameFlags.None; // Retrieve the assembly name from the typelib. AssemblyName asmName = GetAssemblyNameFromTypelib(typeLib, asmFileName, publicKey, keyPair, asmVersion, asmNameFlags); // Create the dynamic assembly that will contain the converted typelib types. AssemblyBuilder asmBldr = CreateAssemblyForTypeLib(typeLib, asmFileName, asmName, (flags & TypeLibImporterFlags.PrimaryInteropAssembly) != 0, (flags & TypeLibImporterFlags.ReflectionOnlyLoading) != 0, (flags & TypeLibImporterFlags.NoDefineVersionResource) != 0); // Define a dynamic module that will contain the contain the imported types. String strNonQualifiedAsmFileName = Path.GetFileName(asmFileName); ModuleBuilder modBldr = asmBldr.DefineDynamicModule(strNonQualifiedAsmFileName, strNonQualifiedAsmFileName); // If the namespace hasn't been specified, then use the assembly name. if (asmNamespace == null) asmNamespace = asmName.Name; // Create a type resolve handler that will also intercept resolve ref messages // on the sink interface to build up a list of referenced assemblies. TypeResolveHandler typeResolveHandler = new TypeResolveHandler(modBldr, notifySink); // Add a listener for the type resolve events. AppDomain currentDomain = Thread.GetDomain(); ResolveEventHandler resolveHandler = new ResolveEventHandler(typeResolveHandler.ResolveEvent); ResolveEventHandler asmResolveHandler = new ResolveEventHandler(typeResolveHandler.ResolveAsmEvent); ResolveEventHandler ROAsmResolveHandler = new ResolveEventHandler(typeResolveHandler.ResolveROAsmEvent); currentDomain.TypeResolve += resolveHandler; currentDomain.AssemblyResolve += asmResolveHandler; currentDomain.ReflectionOnlyAssemblyResolve += ROAsmResolveHandler; // Convert the types contained in the typelib into metadata and add them to the assembly. nConvertTypeLibToMetadata(typeLib, asmBldr.InternalAssembly, modBldr.InternalModule, asmNamespace, flags, typeResolveHandler, out eventItfInfoList); // Update the COM types in the assembly. UpdateComTypesInAssembly(asmBldr, modBldr); // If there are any event sources then generate the TCE adapters. if (eventItfInfoList.Count > 0) new TCEAdapterGenerator().Process(modBldr, eventItfInfoList); // Remove the listener for the type resolve events. currentDomain.TypeResolve -= resolveHandler; currentDomain.AssemblyResolve -= asmResolveHandler; currentDomain.ReflectionOnlyAssemblyResolve -= ROAsmResolveHandler; // We have finished converting the typelib and now have a fully formed assembly. return asmBldr; } [System.Security.SecuritySafeCritical] // auto-generated [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)] [return : MarshalAs(UnmanagedType.Interface)] public Object ConvertAssemblyToTypeLib(Assembly assembly, String strTypeLibName, TypeLibExporterFlags flags, ITypeLibExporterNotifySink notifySink) { RuntimeAssembly rtAssembly; AssemblyBuilder ab = assembly as AssemblyBuilder; if (ab != null) rtAssembly = ab.InternalAssembly; else rtAssembly = assembly as RuntimeAssembly; return nConvertAssemblyToTypeLib(rtAssembly, strTypeLibName, flags, notifySink); } [System.Security.SecuritySafeCritical] // auto-generated [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public bool GetPrimaryInteropAssembly(Guid g, Int32 major, Int32 minor, Int32 lcid, out String asmName, out String asmCodeBase) { String strTlbId = "{" + g.ToString().ToUpper(CultureInfo.InvariantCulture) + "}"; String strVersion = major.ToString("x", CultureInfo.InvariantCulture) + "." + minor.ToString("x", CultureInfo.InvariantCulture); // Set the two out values to null before we start. asmName = null; asmCodeBase = null; // Try to open the HKEY_CLASS_ROOT\TypeLib key. using (RegistryKey TypeLibKey = Registry.ClassesRoot.OpenSubKey("TypeLib", false)) { if (TypeLibKey != null) { // Try to open the HKEY_CLASS_ROOT\TypeLib\key. using (RegistryKey TypeLibSubKey = TypeLibKey.OpenSubKey(strTlbId)) { if (TypeLibSubKey != null) { // Try to open the HKEY_CLASS_ROOT\TypeLib\ \ key. using (RegistryKey VersionKey = TypeLibSubKey.OpenSubKey(strVersion, false)) { if (VersionKey != null) { // Attempt to retrieve the assembly name and codebase under the version key. asmName = (String)VersionKey.GetValue("PrimaryInteropAssemblyName"); asmCodeBase = (String)VersionKey.GetValue("PrimaryInteropAssemblyCodeBase"); } } } } } } // If the assembly name isn't null, then we found an PIA. return asmName != null; } // // Non native helper methods. // [System.Security.SecurityCritical] // auto-generated [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable private static AssemblyBuilder CreateAssemblyForTypeLib(Object typeLib, String asmFileName, AssemblyName asmName, bool bPrimaryInteropAssembly, bool bReflectionOnly, bool bNoDefineVersionResource) { // Retrieve the current app domain. AppDomain currentDomain = Thread.GetDomain(); // Retrieve the directory from the assembly file name. String dir = null; if (asmFileName != null) { dir = Path.GetDirectoryName(asmFileName); if (String.IsNullOrEmpty(dir)) dir = null; } AssemblyBuilderAccess aba; if (bReflectionOnly) { aba = AssemblyBuilderAccess.ReflectionOnly; } else { aba = AssemblyBuilderAccess.RunAndSave; } // Create the dynamic assembly itself. AssemblyBuilder asmBldr; List assemblyAttributes = new List (); #if !FEATURE_CORECLR // mscorlib.dll must specify the security rules that assemblies it emits are to use, since by // default all assemblies will follow security rule set level 2, and we want to make that an // explicit decision. ConstructorInfo securityRulesCtor = typeof(SecurityRulesAttribute).GetConstructor(new Type[] { typeof(SecurityRuleSet) }); CustomAttributeBuilder securityRulesAttribute = new CustomAttributeBuilder(securityRulesCtor, new object[] { SecurityRuleSet.Level2 }); assemblyAttributes.Add(securityRulesAttribute); #endif // !FEATURE_CORECLR #if FEATURE_REFLECTION_EMIT_REFACTORING asmBldr = AssemblyBuilder.DefineDynamicAssembly(asmName, aba, dir, false, assemblyAttributes); #else //FEATURE_REFLECTION_EMIT_REFACTORING asmBldr = currentDomain.DefineDynamicAssembly(asmName, aba, dir, false, assemblyAttributes); #endif //FEATURE_REFLECTION_EMIT_REFACTORING // Set the Guid custom attribute on the assembly. SetGuidAttributeOnAssembly(asmBldr, typeLib); // Set the imported from COM attribute on the assembly and return it. SetImportedFromTypeLibAttrOnAssembly(asmBldr, typeLib); // Set the version information on the typelib. if (bNoDefineVersionResource) { SetTypeLibVersionAttribute(asmBldr, typeLib); } else { SetVersionInformation(asmBldr, typeLib, asmName); } // If we are generating a PIA, then set the PIA custom attribute. if (bPrimaryInteropAssembly) SetPIAAttributeOnAssembly(asmBldr, typeLib); return asmBldr; } [System.Security.SecurityCritical] // auto-generated internal static AssemblyName GetAssemblyNameFromTypelib(Object typeLib, String asmFileName, byte[] publicKey, StrongNameKeyPair keyPair, Version asmVersion, AssemblyNameFlags asmNameFlags) { // Extract the name of the typelib. String strTypeLibName = null; String strDocString = null; int dwHelpContext = 0; String strHelpFile = null; ITypeLib pTLB = (ITypeLib)typeLib; pTLB.GetDocumentation(-1, out strTypeLibName, out strDocString, out dwHelpContext, out strHelpFile); // Retrieve the name to use for the assembly. if (asmFileName == null) { asmFileName = strTypeLibName; } else { Contract.Assert((asmFileName != null) && (asmFileName.Length > 0), "The assembly file name cannot be an empty string!"); String strFileNameNoPath = Path.GetFileName(asmFileName); String strExtension = Path.GetExtension(asmFileName); // Validate that the extension is valid. bool bExtensionValid = ".dll".Equals(strExtension, StringComparison.OrdinalIgnoreCase); // If the extension is not valid then tell the user and quit. if (!bExtensionValid) throw new ArgumentException(Environment.GetResourceString("Arg_InvalidFileExtension")); // The assembly cannot contain the path nor the extension. asmFileName = strFileNameNoPath.Substring(0, strFileNameNoPath.Length - ".dll".Length); } // If the version information was not specified, then retrieve it from the typelib. if (asmVersion == null) { int major; int minor; Marshal.GetTypeLibVersion(pTLB, out major, out minor); asmVersion = new Version(major, minor, 0, 0); } // Create the assembly name for the imported typelib's assembly. AssemblyName AsmName = new AssemblyName(); AsmName.Init( asmFileName, publicKey, null, asmVersion, null, AssemblyHashAlgorithm.None, AssemblyVersionCompatibility.SameMachine, null, asmNameFlags, keyPair); return AsmName; } private static void UpdateComTypesInAssembly(AssemblyBuilder asmBldr, ModuleBuilder modBldr) { // Retrieve the AssemblyBuilderData associated with the assembly builder. AssemblyBuilderData AsmBldrData = asmBldr.m_assemblyData; // Go through the types in the module and add them as public COM types. Type[] aTypes = modBldr.GetTypes(); int NumTypes = aTypes.Length; for (int cTypes = 0; cTypes < NumTypes; cTypes++) AsmBldrData.AddPublicComType(aTypes[cTypes]); } [System.Security.SecurityCritical] // auto-generated private static void SetGuidAttributeOnAssembly(AssemblyBuilder asmBldr, Object typeLib) { // Retrieve the GuidAttribute constructor. Type []aConsParams = new Type[1] {typeof(String)}; ConstructorInfo GuidAttrCons = typeof(GuidAttribute).GetConstructor(aConsParams); // Create an instance of the custom attribute builder. Object[] aArgs = new Object[1] {Marshal.GetTypeLibGuid((ITypeLib)typeLib).ToString()}; CustomAttributeBuilder GuidCABuilder = new CustomAttributeBuilder(GuidAttrCons, aArgs); // Set the GuidAttribute on the assembly builder. asmBldr.SetCustomAttribute(GuidCABuilder); } [System.Security.SecurityCritical] // auto-generated private static void SetImportedFromTypeLibAttrOnAssembly(AssemblyBuilder asmBldr, Object typeLib) { // Retrieve the ImportedFromTypeLibAttribute constructor. Type []aConsParams = new Type[1] {typeof(String)}; ConstructorInfo ImpFromComAttrCons = typeof(ImportedFromTypeLibAttribute).GetConstructor(aConsParams); // Retrieve the name of the typelib. String strTypeLibName = Marshal.GetTypeLibName((ITypeLib)typeLib); // Create an instance of the custom attribute builder. Object[] aArgs = new Object[1] {strTypeLibName}; CustomAttributeBuilder ImpFromComCABuilder = new CustomAttributeBuilder(ImpFromComAttrCons, aArgs); // Set the ImportedFromTypeLibAttribute on the assembly builder. asmBldr.SetCustomAttribute(ImpFromComCABuilder); } [System.Security.SecurityCritical] // auto-generated private static void SetTypeLibVersionAttribute(AssemblyBuilder asmBldr, Object typeLib) { Type []aConsParams = new Type[2] {typeof(int), typeof(int)}; ConstructorInfo TypeLibVerCons = typeof(TypeLibVersionAttribute).GetConstructor(aConsParams); // Get the typelib version int major; int minor; Marshal.GetTypeLibVersion((ITypeLib)typeLib, out major, out minor); // Create an instance of the custom attribute builder. Object[] aArgs = new Object[2] {major, minor}; CustomAttributeBuilder TypeLibVerBuilder = new CustomAttributeBuilder(TypeLibVerCons, aArgs); // Set the attribute on the assembly builder. asmBldr.SetCustomAttribute(TypeLibVerBuilder); } [System.Security.SecurityCritical] // auto-generated private static void SetVersionInformation(AssemblyBuilder asmBldr, Object typeLib, AssemblyName asmName) { // Extract the name of the typelib. String strTypeLibName = null; String strDocString = null; int dwHelpContext = 0; String strHelpFile = null; ITypeLib pTLB = (ITypeLib)typeLib; pTLB.GetDocumentation(-1, out strTypeLibName, out strDocString, out dwHelpContext, out strHelpFile); // Generate the product name string from the named of the typelib. String strProductName = String.Format(CultureInfo.InvariantCulture, Environment.GetResourceString("TypeLibConverter_ImportedTypeLibProductName"), strTypeLibName); // Set the OS version information. asmBldr.DefineVersionInfoResource(strProductName, asmName.Version.ToString(), null, null, null); // Set the TypeLibVersion attribute SetTypeLibVersionAttribute(asmBldr, typeLib); } [System.Security.SecurityCritical] // auto-generated private static void SetPIAAttributeOnAssembly(AssemblyBuilder asmBldr, Object typeLib) { IntPtr pAttr = Win32Native.NULL; _TYPELIBATTR Attr; ITypeLib pTLB = (ITypeLib)typeLib; int Major = 0; int Minor = 0; // Retrieve the PrimaryInteropAssemblyAttribute constructor. Type []aConsParams = new Type[2] {typeof(int), typeof(int)}; ConstructorInfo PIAAttrCons = typeof(PrimaryInteropAssemblyAttribute).GetConstructor(aConsParams); // Retrieve the major and minor version from the typelib. try { pTLB.GetLibAttr(out pAttr); Attr = (_TYPELIBATTR)Marshal.PtrToStructure(pAttr, typeof(_TYPELIBATTR)); Major = Attr.wMajorVerNum; Minor = Attr.wMinorVerNum; } finally { // Release the typelib attributes. if (pAttr != Win32Native.NULL) pTLB.ReleaseTLibAttr(pAttr); } // Create an instance of the custom attribute builder. Object[] aArgs = new Object[2] {Major, Minor}; CustomAttributeBuilder PIACABuilder = new CustomAttributeBuilder(PIAAttrCons, aArgs); // Set the PrimaryInteropAssemblyAttribute on the assembly builder. asmBldr.SetCustomAttribute(PIACABuilder); } // // Native helper methods. // [System.Security.SecurityCritical] // auto-generated [ResourceExposure(ResourceScope.None)] [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void nConvertTypeLibToMetadata(Object typeLib, RuntimeAssembly asmBldr, RuntimeModule modBldr, String nameSpace, TypeLibImporterFlags flags, ITypeLibImporterNotifySink notifySink, out ArrayList eventItfInfoList); // Must use assembly versioning or GuidAttribute to avoid collisions in typelib export or registration. [System.Security.SecurityCritical] // auto-generated [ResourceExposure(ResourceScope.Machine)] [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern Object nConvertAssemblyToTypeLib(RuntimeAssembly assembly, String strTypeLibName, TypeLibExporterFlags flags, ITypeLibExporterNotifySink notifySink); [System.Security.SecurityCritical] // auto-generated [ResourceExposure(ResourceScope.None)] [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity] internal extern static void LoadInMemoryTypeByName(RuntimeModule module, String className); // // Helper class called when a resolve type event is fired. // private class TypeResolveHandler : ITypeLibImporterNotifySink { public TypeResolveHandler(ModuleBuilder mod, ITypeLibImporterNotifySink userSink) { m_Module = mod; m_UserSink = userSink; } public void ReportEvent(ImporterEventKind eventKind, int eventCode, String eventMsg) { m_UserSink.ReportEvent(eventKind, eventCode, eventMsg); } public Assembly ResolveRef(Object typeLib) { Contract.Ensures(Contract.Result () != null && Contract.Result () is RuntimeAssembly); Contract.EndContractBlock(); // Call the user sink to resolve the reference. Assembly asm = m_UserSink.ResolveRef(typeLib); if (asm == null) throw new ArgumentNullException(); // Return the resolved assembly. We extract the internal assembly because we are called // by the VM which accesses fields of the object directly and does not go via those // delegating properties (the fields are empty if asm is an (external) AssemblyBuilder). RuntimeAssembly rtAssembly = asm as RuntimeAssembly; if (rtAssembly == null) { AssemblyBuilder ab = asm as AssemblyBuilder; if (ab != null) rtAssembly = ab.InternalAssembly; } if (rtAssembly == null) throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeAssembly")); // Add the assembly to the list of assemblies. m_AsmList.Add(rtAssembly); return rtAssembly; } [System.Security.SecurityCritical] // auto-generated public Assembly ResolveEvent(Object sender, ResolveEventArgs args) { // We need to load the type in the resolve event so that we will deal with // cases where we are trying to load the CoClass before the interface has // been loaded. try { LoadInMemoryTypeByName(m_Module.GetNativeHandle(), args.Name); return m_Module.Assembly; } catch (TypeLoadException e) { if (e.ResourceId != System.__HResults.COR_E_TYPELOAD) // type not found throw; } foreach (RuntimeAssembly asm in m_AsmList) { try { asm.GetType(args.Name, true, false); return asm; } catch (TypeLoadException e) { if (e._HResult != System.__HResults.COR_E_TYPELOAD) // type not found throw; } } return null; } public Assembly ResolveAsmEvent(Object sender, ResolveEventArgs args) { foreach (RuntimeAssembly asm in m_AsmList) { if (String.Compare(asm.FullName, args.Name, StringComparison.OrdinalIgnoreCase) == 0) return asm; } return null; } public Assembly ResolveROAsmEvent(Object sender, ResolveEventArgs args) { foreach (RuntimeAssembly asm in m_AsmList) { if (String.Compare(asm.FullName, args.Name, StringComparison.OrdinalIgnoreCase) == 0) return asm; } // We failed to find the referenced assembly in our pre-loaded assemblies, so try to load it based on policy. string asmName = AppDomain.CurrentDomain.ApplyPolicy(args.Name); return Assembly.ReflectionOnlyLoad(asmName); } private ModuleBuilder m_Module; private ITypeLibImporterNotifySink m_UserSink; private List m_AsmList = new List (); } } } #endif // !FEATURE_CORECLR // current implementation requires reflection only load // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== /*============================================================================== ** ** Class: TypeLibConverter ** ** ** Purpose: Component that implements the ITypeLibConverter interface and ** does the actual work of converting a typelib to metadata and ** vice versa. ** ** =============================================================================*/ #if !FEATURE_CORECLR // current implementation requires reflection only load namespace System.Runtime.InteropServices { using System; using System.Diagnostics.Contracts; using System.Collections; using System.Collections.Generic; using System.Threading; using System.Runtime.InteropServices.TCEAdapterGen; using System.IO; using System.Reflection; using System.Reflection.Emit; using System.Configuration.Assemblies; using Microsoft.Win32; using System.Runtime.CompilerServices; using System.Globalization; using System.Security; using System.Security.Permissions; using System.Runtime.InteropServices.ComTypes; using System.Runtime.Versioning; using WORD = System.UInt16; using DWORD = System.UInt32; using _TYPELIBATTR = System.Runtime.InteropServices.ComTypes.TYPELIBATTR; [Guid("F1C3BF79-C3E4-11d3-88E7-00902754C43A")] [ClassInterface(ClassInterfaceType.None)] [System.Runtime.InteropServices.ComVisible(true)] public sealed class TypeLibConverter : ITypeLibConverter { private const String s_strTypeLibAssemblyTitlePrefix = "TypeLib "; private const String s_strTypeLibAssemblyDescPrefix = "Assembly generated from typelib "; private const int MAX_NAMESPACE_LENGTH = 1024; // // ITypeLibConverter interface. // [System.Security.SecuritySafeCritical] // auto-generated [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)] [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public AssemblyBuilder ConvertTypeLibToAssembly([MarshalAs(UnmanagedType.Interface)] Object typeLib, String asmFileName, int flags, ITypeLibImporterNotifySink notifySink, byte[] publicKey, StrongNameKeyPair keyPair, bool unsafeInterfaces) { return ConvertTypeLibToAssembly(typeLib, asmFileName, (unsafeInterfaces ? TypeLibImporterFlags.UnsafeInterfaces : 0), notifySink, publicKey, keyPair, null, null); } [System.Security.SecuritySafeCritical] // auto-generated [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)] [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public AssemblyBuilder ConvertTypeLibToAssembly([MarshalAs(UnmanagedType.Interface)] Object typeLib, String asmFileName, TypeLibImporterFlags flags, ITypeLibImporterNotifySink notifySink, byte[] publicKey, StrongNameKeyPair keyPair, String asmNamespace, Version asmVersion) { // Validate the arguments. if (typeLib == null) throw new ArgumentNullException("typeLib"); if (asmFileName == null) throw new ArgumentNullException("asmFileName"); if (notifySink == null) throw new ArgumentNullException("notifySink"); if (String.Empty.Equals(asmFileName)) throw new ArgumentException(Environment.GetResourceString("Arg_InvalidFileName"), "asmFileName"); if (asmFileName.Length > Path.MAX_PATH) throw new ArgumentException(Environment.GetResourceString("IO.PathTooLong"), asmFileName); if ((flags & TypeLibImporterFlags.PrimaryInteropAssembly) != 0 && publicKey == null && keyPair == null) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_PIAMustBeStrongNamed")); Contract.EndContractBlock(); ArrayList eventItfInfoList = null; // Determine the AssemblyNameFlags AssemblyNameFlags asmNameFlags = AssemblyNameFlags.None; // Retrieve the assembly name from the typelib. AssemblyName asmName = GetAssemblyNameFromTypelib(typeLib, asmFileName, publicKey, keyPair, asmVersion, asmNameFlags); // Create the dynamic assembly that will contain the converted typelib types. AssemblyBuilder asmBldr = CreateAssemblyForTypeLib(typeLib, asmFileName, asmName, (flags & TypeLibImporterFlags.PrimaryInteropAssembly) != 0, (flags & TypeLibImporterFlags.ReflectionOnlyLoading) != 0, (flags & TypeLibImporterFlags.NoDefineVersionResource) != 0); // Define a dynamic module that will contain the contain the imported types. String strNonQualifiedAsmFileName = Path.GetFileName(asmFileName); ModuleBuilder modBldr = asmBldr.DefineDynamicModule(strNonQualifiedAsmFileName, strNonQualifiedAsmFileName); // If the namespace hasn't been specified, then use the assembly name. if (asmNamespace == null) asmNamespace = asmName.Name; // Create a type resolve handler that will also intercept resolve ref messages // on the sink interface to build up a list of referenced assemblies. TypeResolveHandler typeResolveHandler = new TypeResolveHandler(modBldr, notifySink); // Add a listener for the type resolve events. AppDomain currentDomain = Thread.GetDomain(); ResolveEventHandler resolveHandler = new ResolveEventHandler(typeResolveHandler.ResolveEvent); ResolveEventHandler asmResolveHandler = new ResolveEventHandler(typeResolveHandler.ResolveAsmEvent); ResolveEventHandler ROAsmResolveHandler = new ResolveEventHandler(typeResolveHandler.ResolveROAsmEvent); currentDomain.TypeResolve += resolveHandler; currentDomain.AssemblyResolve += asmResolveHandler; currentDomain.ReflectionOnlyAssemblyResolve += ROAsmResolveHandler; // Convert the types contained in the typelib into metadata and add them to the assembly. nConvertTypeLibToMetadata(typeLib, asmBldr.InternalAssembly, modBldr.InternalModule, asmNamespace, flags, typeResolveHandler, out eventItfInfoList); // Update the COM types in the assembly. UpdateComTypesInAssembly(asmBldr, modBldr); // If there are any event sources then generate the TCE adapters. if (eventItfInfoList.Count > 0) new TCEAdapterGenerator().Process(modBldr, eventItfInfoList); // Remove the listener for the type resolve events. currentDomain.TypeResolve -= resolveHandler; currentDomain.AssemblyResolve -= asmResolveHandler; currentDomain.ReflectionOnlyAssemblyResolve -= ROAsmResolveHandler; // We have finished converting the typelib and now have a fully formed assembly. return asmBldr; } [System.Security.SecuritySafeCritical] // auto-generated [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)] [return : MarshalAs(UnmanagedType.Interface)] public Object ConvertAssemblyToTypeLib(Assembly assembly, String strTypeLibName, TypeLibExporterFlags flags, ITypeLibExporterNotifySink notifySink) { RuntimeAssembly rtAssembly; AssemblyBuilder ab = assembly as AssemblyBuilder; if (ab != null) rtAssembly = ab.InternalAssembly; else rtAssembly = assembly as RuntimeAssembly; return nConvertAssemblyToTypeLib(rtAssembly, strTypeLibName, flags, notifySink); } [System.Security.SecuritySafeCritical] // auto-generated [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public bool GetPrimaryInteropAssembly(Guid g, Int32 major, Int32 minor, Int32 lcid, out String asmName, out String asmCodeBase) { String strTlbId = "{" + g.ToString().ToUpper(CultureInfo.InvariantCulture) + "}"; String strVersion = major.ToString("x", CultureInfo.InvariantCulture) + "." + minor.ToString("x", CultureInfo.InvariantCulture); // Set the two out values to null before we start. asmName = null; asmCodeBase = null; // Try to open the HKEY_CLASS_ROOT\TypeLib key. using (RegistryKey TypeLibKey = Registry.ClassesRoot.OpenSubKey("TypeLib", false)) { if (TypeLibKey != null) { // Try to open the HKEY_CLASS_ROOT\TypeLib\ key. using (RegistryKey TypeLibSubKey = TypeLibKey.OpenSubKey(strTlbId)) { if (TypeLibSubKey != null) { // Try to open the HKEY_CLASS_ROOT\TypeLib\ \ key. using (RegistryKey VersionKey = TypeLibSubKey.OpenSubKey(strVersion, false)) { if (VersionKey != null) { // Attempt to retrieve the assembly name and codebase under the version key. asmName = (String)VersionKey.GetValue("PrimaryInteropAssemblyName"); asmCodeBase = (String)VersionKey.GetValue("PrimaryInteropAssemblyCodeBase"); } } } } } } // If the assembly name isn't null, then we found an PIA. return asmName != null; } // // Non native helper methods. // [System.Security.SecurityCritical] // auto-generated [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable private static AssemblyBuilder CreateAssemblyForTypeLib(Object typeLib, String asmFileName, AssemblyName asmName, bool bPrimaryInteropAssembly, bool bReflectionOnly, bool bNoDefineVersionResource) { // Retrieve the current app domain. AppDomain currentDomain = Thread.GetDomain(); // Retrieve the directory from the assembly file name. String dir = null; if (asmFileName != null) { dir = Path.GetDirectoryName(asmFileName); if (String.IsNullOrEmpty(dir)) dir = null; } AssemblyBuilderAccess aba; if (bReflectionOnly) { aba = AssemblyBuilderAccess.ReflectionOnly; } else { aba = AssemblyBuilderAccess.RunAndSave; } // Create the dynamic assembly itself. AssemblyBuilder asmBldr; List assemblyAttributes = new List (); #if !FEATURE_CORECLR // mscorlib.dll must specify the security rules that assemblies it emits are to use, since by // default all assemblies will follow security rule set level 2, and we want to make that an // explicit decision. ConstructorInfo securityRulesCtor = typeof(SecurityRulesAttribute).GetConstructor(new Type[] { typeof(SecurityRuleSet) }); CustomAttributeBuilder securityRulesAttribute = new CustomAttributeBuilder(securityRulesCtor, new object[] { SecurityRuleSet.Level2 }); assemblyAttributes.Add(securityRulesAttribute); #endif // !FEATURE_CORECLR #if FEATURE_REFLECTION_EMIT_REFACTORING asmBldr = AssemblyBuilder.DefineDynamicAssembly(asmName, aba, dir, false, assemblyAttributes); #else //FEATURE_REFLECTION_EMIT_REFACTORING asmBldr = currentDomain.DefineDynamicAssembly(asmName, aba, dir, false, assemblyAttributes); #endif //FEATURE_REFLECTION_EMIT_REFACTORING // Set the Guid custom attribute on the assembly. SetGuidAttributeOnAssembly(asmBldr, typeLib); // Set the imported from COM attribute on the assembly and return it. SetImportedFromTypeLibAttrOnAssembly(asmBldr, typeLib); // Set the version information on the typelib. if (bNoDefineVersionResource) { SetTypeLibVersionAttribute(asmBldr, typeLib); } else { SetVersionInformation(asmBldr, typeLib, asmName); } // If we are generating a PIA, then set the PIA custom attribute. if (bPrimaryInteropAssembly) SetPIAAttributeOnAssembly(asmBldr, typeLib); return asmBldr; } [System.Security.SecurityCritical] // auto-generated internal static AssemblyName GetAssemblyNameFromTypelib(Object typeLib, String asmFileName, byte[] publicKey, StrongNameKeyPair keyPair, Version asmVersion, AssemblyNameFlags asmNameFlags) { // Extract the name of the typelib. String strTypeLibName = null; String strDocString = null; int dwHelpContext = 0; String strHelpFile = null; ITypeLib pTLB = (ITypeLib)typeLib; pTLB.GetDocumentation(-1, out strTypeLibName, out strDocString, out dwHelpContext, out strHelpFile); // Retrieve the name to use for the assembly. if (asmFileName == null) { asmFileName = strTypeLibName; } else { Contract.Assert((asmFileName != null) && (asmFileName.Length > 0), "The assembly file name cannot be an empty string!"); String strFileNameNoPath = Path.GetFileName(asmFileName); String strExtension = Path.GetExtension(asmFileName); // Validate that the extension is valid. bool bExtensionValid = ".dll".Equals(strExtension, StringComparison.OrdinalIgnoreCase); // If the extension is not valid then tell the user and quit. if (!bExtensionValid) throw new ArgumentException(Environment.GetResourceString("Arg_InvalidFileExtension")); // The assembly cannot contain the path nor the extension. asmFileName = strFileNameNoPath.Substring(0, strFileNameNoPath.Length - ".dll".Length); } // If the version information was not specified, then retrieve it from the typelib. if (asmVersion == null) { int major; int minor; Marshal.GetTypeLibVersion(pTLB, out major, out minor); asmVersion = new Version(major, minor, 0, 0); } // Create the assembly name for the imported typelib's assembly. AssemblyName AsmName = new AssemblyName(); AsmName.Init( asmFileName, publicKey, null, asmVersion, null, AssemblyHashAlgorithm.None, AssemblyVersionCompatibility.SameMachine, null, asmNameFlags, keyPair); return AsmName; } private static void UpdateComTypesInAssembly(AssemblyBuilder asmBldr, ModuleBuilder modBldr) { // Retrieve the AssemblyBuilderData associated with the assembly builder. AssemblyBuilderData AsmBldrData = asmBldr.m_assemblyData; // Go through the types in the module and add them as public COM types. Type[] aTypes = modBldr.GetTypes(); int NumTypes = aTypes.Length; for (int cTypes = 0; cTypes < NumTypes; cTypes++) AsmBldrData.AddPublicComType(aTypes[cTypes]); } [System.Security.SecurityCritical] // auto-generated private static void SetGuidAttributeOnAssembly(AssemblyBuilder asmBldr, Object typeLib) { // Retrieve the GuidAttribute constructor. Type []aConsParams = new Type[1] {typeof(String)}; ConstructorInfo GuidAttrCons = typeof(GuidAttribute).GetConstructor(aConsParams); // Create an instance of the custom attribute builder. Object[] aArgs = new Object[1] {Marshal.GetTypeLibGuid((ITypeLib)typeLib).ToString()}; CustomAttributeBuilder GuidCABuilder = new CustomAttributeBuilder(GuidAttrCons, aArgs); // Set the GuidAttribute on the assembly builder. asmBldr.SetCustomAttribute(GuidCABuilder); } [System.Security.SecurityCritical] // auto-generated private static void SetImportedFromTypeLibAttrOnAssembly(AssemblyBuilder asmBldr, Object typeLib) { // Retrieve the ImportedFromTypeLibAttribute constructor. Type []aConsParams = new Type[1] {typeof(String)}; ConstructorInfo ImpFromComAttrCons = typeof(ImportedFromTypeLibAttribute).GetConstructor(aConsParams); // Retrieve the name of the typelib. String strTypeLibName = Marshal.GetTypeLibName((ITypeLib)typeLib); // Create an instance of the custom attribute builder. Object[] aArgs = new Object[1] {strTypeLibName}; CustomAttributeBuilder ImpFromComCABuilder = new CustomAttributeBuilder(ImpFromComAttrCons, aArgs); // Set the ImportedFromTypeLibAttribute on the assembly builder. asmBldr.SetCustomAttribute(ImpFromComCABuilder); } [System.Security.SecurityCritical] // auto-generated private static void SetTypeLibVersionAttribute(AssemblyBuilder asmBldr, Object typeLib) { Type []aConsParams = new Type[2] {typeof(int), typeof(int)}; ConstructorInfo TypeLibVerCons = typeof(TypeLibVersionAttribute).GetConstructor(aConsParams); // Get the typelib version int major; int minor; Marshal.GetTypeLibVersion((ITypeLib)typeLib, out major, out minor); // Create an instance of the custom attribute builder. Object[] aArgs = new Object[2] {major, minor}; CustomAttributeBuilder TypeLibVerBuilder = new CustomAttributeBuilder(TypeLibVerCons, aArgs); // Set the attribute on the assembly builder. asmBldr.SetCustomAttribute(TypeLibVerBuilder); } [System.Security.SecurityCritical] // auto-generated private static void SetVersionInformation(AssemblyBuilder asmBldr, Object typeLib, AssemblyName asmName) { // Extract the name of the typelib. String strTypeLibName = null; String strDocString = null; int dwHelpContext = 0; String strHelpFile = null; ITypeLib pTLB = (ITypeLib)typeLib; pTLB.GetDocumentation(-1, out strTypeLibName, out strDocString, out dwHelpContext, out strHelpFile); // Generate the product name string from the named of the typelib. String strProductName = String.Format(CultureInfo.InvariantCulture, Environment.GetResourceString("TypeLibConverter_ImportedTypeLibProductName"), strTypeLibName); // Set the OS version information. asmBldr.DefineVersionInfoResource(strProductName, asmName.Version.ToString(), null, null, null); // Set the TypeLibVersion attribute SetTypeLibVersionAttribute(asmBldr, typeLib); } [System.Security.SecurityCritical] // auto-generated private static void SetPIAAttributeOnAssembly(AssemblyBuilder asmBldr, Object typeLib) { IntPtr pAttr = Win32Native.NULL; _TYPELIBATTR Attr; ITypeLib pTLB = (ITypeLib)typeLib; int Major = 0; int Minor = 0; // Retrieve the PrimaryInteropAssemblyAttribute constructor. Type []aConsParams = new Type[2] {typeof(int), typeof(int)}; ConstructorInfo PIAAttrCons = typeof(PrimaryInteropAssemblyAttribute).GetConstructor(aConsParams); // Retrieve the major and minor version from the typelib. try { pTLB.GetLibAttr(out pAttr); Attr = (_TYPELIBATTR)Marshal.PtrToStructure(pAttr, typeof(_TYPELIBATTR)); Major = Attr.wMajorVerNum; Minor = Attr.wMinorVerNum; } finally { // Release the typelib attributes. if (pAttr != Win32Native.NULL) pTLB.ReleaseTLibAttr(pAttr); } // Create an instance of the custom attribute builder. Object[] aArgs = new Object[2] {Major, Minor}; CustomAttributeBuilder PIACABuilder = new CustomAttributeBuilder(PIAAttrCons, aArgs); // Set the PrimaryInteropAssemblyAttribute on the assembly builder. asmBldr.SetCustomAttribute(PIACABuilder); } // // Native helper methods. // [System.Security.SecurityCritical] // auto-generated [ResourceExposure(ResourceScope.None)] [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void nConvertTypeLibToMetadata(Object typeLib, RuntimeAssembly asmBldr, RuntimeModule modBldr, String nameSpace, TypeLibImporterFlags flags, ITypeLibImporterNotifySink notifySink, out ArrayList eventItfInfoList); // Must use assembly versioning or GuidAttribute to avoid collisions in typelib export or registration. [System.Security.SecurityCritical] // auto-generated [ResourceExposure(ResourceScope.Machine)] [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern Object nConvertAssemblyToTypeLib(RuntimeAssembly assembly, String strTypeLibName, TypeLibExporterFlags flags, ITypeLibExporterNotifySink notifySink); [System.Security.SecurityCritical] // auto-generated [ResourceExposure(ResourceScope.None)] [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity] internal extern static void LoadInMemoryTypeByName(RuntimeModule module, String className); // // Helper class called when a resolve type event is fired. // private class TypeResolveHandler : ITypeLibImporterNotifySink { public TypeResolveHandler(ModuleBuilder mod, ITypeLibImporterNotifySink userSink) { m_Module = mod; m_UserSink = userSink; } public void ReportEvent(ImporterEventKind eventKind, int eventCode, String eventMsg) { m_UserSink.ReportEvent(eventKind, eventCode, eventMsg); } public Assembly ResolveRef(Object typeLib) { Contract.Ensures(Contract.Result () != null && Contract.Result () is RuntimeAssembly); Contract.EndContractBlock(); // Call the user sink to resolve the reference. Assembly asm = m_UserSink.ResolveRef(typeLib); if (asm == null) throw new ArgumentNullException(); // Return the resolved assembly. We extract the internal assembly because we are called // by the VM which accesses fields of the object directly and does not go via those // delegating properties (the fields are empty if asm is an (external) AssemblyBuilder). RuntimeAssembly rtAssembly = asm as RuntimeAssembly; if (rtAssembly == null) { AssemblyBuilder ab = asm as AssemblyBuilder; if (ab != null) rtAssembly = ab.InternalAssembly; } if (rtAssembly == null) throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeAssembly")); // Add the assembly to the list of assemblies. m_AsmList.Add(rtAssembly); return rtAssembly; } [System.Security.SecurityCritical] // auto-generated public Assembly ResolveEvent(Object sender, ResolveEventArgs args) { // We need to load the type in the resolve event so that we will deal with // cases where we are trying to load the CoClass before the interface has // been loaded. try { LoadInMemoryTypeByName(m_Module.GetNativeHandle(), args.Name); return m_Module.Assembly; } catch (TypeLoadException e) { if (e.ResourceId != System.__HResults.COR_E_TYPELOAD) // type not found throw; } foreach (RuntimeAssembly asm in m_AsmList) { try { asm.GetType(args.Name, true, false); return asm; } catch (TypeLoadException e) { if (e._HResult != System.__HResults.COR_E_TYPELOAD) // type not found throw; } } return null; } public Assembly ResolveAsmEvent(Object sender, ResolveEventArgs args) { foreach (RuntimeAssembly asm in m_AsmList) { if (String.Compare(asm.FullName, args.Name, StringComparison.OrdinalIgnoreCase) == 0) return asm; } return null; } public Assembly ResolveROAsmEvent(Object sender, ResolveEventArgs args) { foreach (RuntimeAssembly asm in m_AsmList) { if (String.Compare(asm.FullName, args.Name, StringComparison.OrdinalIgnoreCase) == 0) return asm; } // We failed to find the referenced assembly in our pre-loaded assemblies, so try to load it based on policy. string asmName = AppDomain.CurrentDomain.ApplyPolicy(args.Name); return Assembly.ReflectionOnlyLoad(asmName); } private ModuleBuilder m_Module; private ITypeLibImporterNotifySink m_UserSink; private List m_AsmList = new List (); } } } #endif // !FEATURE_CORECLR // current implementation requires reflection only load // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- NamedServiceModelExtensionCollectionElement.cs
- TrackingProfile.cs
- ConfigXmlWhitespace.cs
- ActivityMarkupSerializationProvider.cs
- SiteMapDataSourceView.cs
- EntitySetRetriever.cs
- AuthenticationSection.cs
- DropDownList.cs
- DataGrid.cs
- SineEase.cs
- QueryOutputWriter.cs
- DateTimePickerDesigner.cs
- SiteMapHierarchicalDataSourceView.cs
- QueryOutputWriterV1.cs
- SqlMethods.cs
- FormattedText.cs
- PrimitiveXmlSerializers.cs
- SoapExtension.cs
- MonthChangedEventArgs.cs
- BounceEase.cs
- HtmlInputSubmit.cs
- Converter.cs
- DropDownHolder.cs
- RectangleGeometry.cs
- XmlDataLoader.cs
- SqlConnection.cs
- ProcessHostFactoryHelper.cs
- Stylus.cs
- CmsInterop.cs
- FileDialog_Vista.cs
- ObjectListCommandsPage.cs
- ServiceModelConfigurationSection.cs
- OutgoingWebResponseContext.cs
- OutKeywords.cs
- Renderer.cs
- RootBuilder.cs
- SynchronizedInputPattern.cs
- ScrollProperties.cs
- RuntimeWrappedException.cs
- RotationValidation.cs
- Lock.cs
- OptimizedTemplateContentHelper.cs
- SiteMapNode.cs
- BooleanAnimationUsingKeyFrames.cs
- ScalarOps.cs
- Crypto.cs
- GatewayIPAddressInformationCollection.cs
- EntityStoreSchemaFilterEntry.cs
- InstancePersistenceContext.cs
- WebPartEditorApplyVerb.cs
- EntitySqlException.cs
- AccessedThroughPropertyAttribute.cs
- AlphabeticalEnumConverter.cs
- ConstraintCollection.cs
- CheckableControlBaseAdapter.cs
- EntityTemplateFactory.cs
- DateTimeOffsetStorage.cs
- Range.cs
- PriorityRange.cs
- XmlQualifiedNameTest.cs
- AbstractSvcMapFileLoader.cs
- EdmError.cs
- WindowsListBox.cs
- DataBoundControlActionList.cs
- SynchronizationContext.cs
- ImageAnimator.cs
- PrimaryKeyTypeConverter.cs
- XmlEntityReference.cs
- WizardPanelChangingEventArgs.cs
- DetailsViewDeletedEventArgs.cs
- ExpandCollapsePattern.cs
- SystemResources.cs
- PresentationSource.cs
- DBConcurrencyException.cs
- IUnknownConstantAttribute.cs
- MetaChildrenColumn.cs
- TextRangeAdaptor.cs
- XPathNodeList.cs
- ThreadBehavior.cs
- GlyphElement.cs
- URIFormatException.cs
- DataViewManagerListItemTypeDescriptor.cs
- XmlEntityReference.cs
- HtmlPanelAdapter.cs
- HtmlToClrEventProxy.cs
- UnsafeNativeMethodsTablet.cs
- KeyedCollection.cs
- TcpClientSocketManager.cs
- WindowCollection.cs
- AddToCollection.cs
- BaseCodePageEncoding.cs
- SessionStateUtil.cs
- TextRunCache.cs
- WebHttpEndpointElement.cs
- OpenFileDialog.cs
- CategoryGridEntry.cs
- ErrorTolerantObjectWriter.cs
- linebase.cs
- _HeaderInfo.cs
- ArrayWithOffset.cs