summaryrefslogtreecommitdiff
path: root/src/mscorlib/src/System/Runtime/InteropServices/TypeLibConverter.cs
blob: 650af9c4e653f34bbbe9d9fa5ed24c3e54515015 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

/*=============================================================================
**
**
**
** 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)]
        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)]
        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
        [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);
        }

        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\<TLBID> key.            
                    using (RegistryKey TypeLibSubKey = TypeLibKey.OpenSubKey(strTlbId))
                    {
                        if (TypeLibSubKey != null)
                        {
                            // Try to open the HKEY_CLASS_ROOT\TypeLib\<TLBID>\<Major.Minor> 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
        [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<CustomAttributeBuilder> assemblyAttributes = new List<CustomAttributeBuilder>();
#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

            asmBldr = currentDomain.DefineDynamicAssembly(asmName, aba, dir, false, assemblyAttributes);

            // 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 = IntPtr.Zero;
            _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 != IntPtr.Zero)
                    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
        [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
        [MethodImplAttribute(MethodImplOptions.InternalCall)] 
        private static extern Object nConvertAssemblyToTypeLib(RuntimeAssembly assembly, String strTypeLibName, TypeLibExporterFlags flags, ITypeLibExporterNotifySink notifySink);

        [System.Security.SecurityCritical]  // auto-generated
        [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<Assembly>() != null && Contract.Result<Assembly>() 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<RuntimeAssembly> m_AsmList = new List<RuntimeAssembly>();
        }
    }
}
#endif // !FEATURE_CORECLR // current implementation requires reflection only load