ceabeac73af79242e870daa2d81bc5e7b26b17a9
[mono.git] / mcs / class / IKVM.Reflection / Emit / AssemblyBuilder.cs
1 /*
2   Copyright (C) 2008-2012 Jeroen Frijters
3
4   This software is provided 'as-is', without any express or implied
5   warranty.  In no event will the authors be held liable for any damages
6   arising from the use of this software.
7
8   Permission is granted to anyone to use this software for any purpose,
9   including commercial applications, and to alter it and redistribute it
10   freely, subject to the following restrictions:
11
12   1. The origin of this software must not be misrepresented; you must not
13      claim that you wrote the original software. If you use this software
14      in a product, an acknowledgment in the product documentation would be
15      appreciated but is not required.
16   2. Altered source versions must be plainly marked as such, and must not be
17      misrepresented as being the original software.
18   3. This notice may not be removed or altered from any source distribution.
19
20   Jeroen Frijters
21   jeroen@frijters.net
22   
23 */
24 using System;
25 using System.Collections.Generic;
26 using System.Configuration.Assemblies;
27 using System.IO;
28 using System.Diagnostics;
29 using System.Globalization;
30 using System.Resources;
31 using System.Security.Cryptography;
32 using System.Security;
33 using IKVM.Reflection.Metadata;
34 using IKVM.Reflection.Impl;
35 using IKVM.Reflection.Writer;
36
37 namespace IKVM.Reflection.Emit
38 {
39         public sealed class AssemblyBuilder : Assembly
40         {
41                 private readonly string name;
42                 private ushort majorVersion;
43                 private ushort minorVersion;
44                 private ushort buildVersion;
45                 private ushort revisionVersion;
46                 private string culture;
47                 private AssemblyNameFlags flags;
48                 private AssemblyHashAlgorithm hashAlgorithm;
49                 private StrongNameKeyPair keyPair;
50                 private byte[] publicKey;
51                 internal readonly string dir;
52                 private readonly PermissionSet requiredPermissions;
53                 private readonly PermissionSet optionalPermissions;
54                 private readonly PermissionSet refusedPermissions;
55                 private PEFileKinds fileKind = PEFileKinds.Dll;
56                 private MethodInfo entryPoint;
57                 private VersionInfo versionInfo;
58                 private byte[] win32icon;
59                 private byte[] win32manifest;
60                 private byte[] win32resources;
61                 private string imageRuntimeVersion;
62                 internal int mdStreamVersion = 0x20000;
63                 private Module pseudoManifestModule;
64                 private readonly List<ResourceFile> resourceFiles = new List<ResourceFile>();
65                 private readonly List<ModuleBuilder> modules = new List<ModuleBuilder>();
66                 private readonly List<Module> addedModules = new List<Module>();
67                 private readonly List<CustomAttributeBuilder> customAttributes = new List<CustomAttributeBuilder>();
68                 private readonly List<CustomAttributeBuilder> declarativeSecurity = new List<CustomAttributeBuilder>();
69                 private readonly List<Type> typeForwarders = new List<Type>();
70
71                 private struct ResourceFile
72                 {
73                         internal string Name;
74                         internal string FileName;
75                         internal ResourceAttributes Attributes;
76                         internal ResourceWriter Writer;
77                 }
78
79                 internal AssemblyBuilder(Universe universe, AssemblyName name, string dir, PermissionSet requiredPermissions, PermissionSet optionalPermissions, PermissionSet refusedPermissions)
80                         : base(universe)
81                 {
82                         this.name = name.Name;
83                         SetVersionHelper(name.Version);
84                         if (!string.IsNullOrEmpty(name.Culture))
85                         {
86                                 this.culture = name.Culture;
87                         }
88                         this.flags = name.RawFlags;
89                         this.hashAlgorithm = name.HashAlgorithm;
90                         if (this.hashAlgorithm == AssemblyHashAlgorithm.None)
91                         {
92                                 this.hashAlgorithm = AssemblyHashAlgorithm.SHA1;
93                         }
94                         this.keyPair = name.KeyPair;
95                         if (this.keyPair != null)
96                         {
97                                 this.publicKey = this.keyPair.PublicKey;
98                         }
99                         else
100                         {
101                                 byte[] publicKey = name.GetPublicKey();
102                                 if (publicKey != null && publicKey.Length != 0)
103                                 {
104                                         this.publicKey = (byte[])publicKey.Clone();
105                                 }
106                         }
107                         this.dir = dir ?? ".";
108                         this.requiredPermissions = requiredPermissions;
109                         this.optionalPermissions = optionalPermissions;
110                         this.refusedPermissions = refusedPermissions;
111                         if (universe.HasMscorlib && !universe.Mscorlib.__IsMissing && universe.Mscorlib.ImageRuntimeVersion != null)
112                         {
113                                 this.imageRuntimeVersion = universe.Mscorlib.ImageRuntimeVersion;
114                         }
115                         else
116                         {
117                                 this.imageRuntimeVersion = typeof(object).Assembly.ImageRuntimeVersion;
118                         }
119                 }
120
121                 private void SetVersionHelper(Version version)
122                 {
123                         if (version == null)
124                         {
125                                 majorVersion = 0;
126                                 minorVersion = 0;
127                                 buildVersion = 0;
128                                 revisionVersion = 0;
129                         }
130                         else
131                         {
132                                 majorVersion = (ushort)version.Major;
133                                 minorVersion = (ushort)version.Minor;
134                                 buildVersion = version.Build == -1 ? (ushort)0 : (ushort)version.Build;
135                                 revisionVersion = version.Revision == -1 ? (ushort)0 : (ushort)version.Revision;
136                         }
137                 }
138
139                 private void Rename(AssemblyName oldName)
140                 {
141                         this.fullName = null;
142                         universe.RenameAssembly(this, oldName);
143                 }
144
145                 public void __SetAssemblyVersion(Version version)
146                 {
147                         AssemblyName oldName = GetName();
148                         SetVersionHelper(version);
149                         Rename(oldName);
150                 }
151
152                 public void __SetAssemblyCulture(string cultureName)
153                 {
154                         AssemblyName oldName = GetName();
155                         this.culture = cultureName;
156                         Rename(oldName);
157                 }
158
159                 public void __SetAssemblyKeyPair(StrongNameKeyPair keyPair)
160                 {
161                         AssemblyName oldName = GetName();
162                         this.keyPair = keyPair;
163                         if (keyPair != null)
164                         {
165                                 this.publicKey = keyPair.PublicKey;
166                         }
167                         Rename(oldName);
168                 }
169
170                 // this is used in combination with delay signing
171                 public void __SetAssemblyPublicKey(byte[] publicKey)
172                 {
173                         AssemblyName oldName = GetName();
174                         this.publicKey = publicKey == null ? null : (byte[])publicKey.Clone();
175                         Rename(oldName);
176                 }
177
178                 public void __SetAssemblyAlgorithmId(AssemblyHashAlgorithm hashAlgorithm)
179                 {
180                         this.hashAlgorithm = hashAlgorithm;
181                 }
182
183                 public void __SetAssemblyFlags(AssemblyNameFlags flags)
184                 {
185                         AssemblyName oldName = GetName();
186                         this.flags = flags;
187                         Rename(oldName);
188                 }
189
190                 public override AssemblyNameFlags __AssemblyFlags
191                 {
192                         get { return flags; }
193                 }
194
195                 internal string Name
196                 {
197                         get { return name; }
198                 }
199
200                 public override AssemblyName GetName()
201                 {
202                         AssemblyName n = new AssemblyName();
203                         n.Name = name;
204                         n.Version = new Version(majorVersion, minorVersion, buildVersion, revisionVersion);
205                         n.Culture = culture ?? "";
206                         n.HashAlgorithm = hashAlgorithm;
207                         n.RawFlags = flags;
208                         n.SetPublicKey(publicKey != null ? (byte[])publicKey.Clone() : Empty<byte>.Array);
209                         n.KeyPair = keyPair;
210                         return n;
211                 }
212
213                 public override string Location
214                 {
215                         get { throw new NotSupportedException(); }
216                 }
217
218                 public ModuleBuilder DefineDynamicModule(string name, string fileName)
219                 {
220                         return DefineDynamicModule(name, fileName, false);
221                 }
222
223                 public ModuleBuilder DefineDynamicModule(string name, string fileName, bool emitSymbolInfo)
224                 {
225                         ModuleBuilder module = new ModuleBuilder(this, name, fileName, emitSymbolInfo);
226                         modules.Add(module);
227                         return module;
228                 }
229
230                 public ModuleBuilder GetDynamicModule(string name)
231                 {
232                         foreach (ModuleBuilder module in modules)
233                         {
234                                 if (module.Name == name)
235                                 {
236                                         return module;
237                                 }
238                         }
239                         return null;
240                 }
241
242                 public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
243                 {
244                         SetCustomAttribute(new CustomAttributeBuilder(con, binaryAttribute));
245                 }
246
247                 public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
248                 {
249                         customAttributes.Add(customBuilder);
250                 }
251
252                 public void __AddDeclarativeSecurity(CustomAttributeBuilder customBuilder)
253                 {
254                         declarativeSecurity.Add(customBuilder);
255                 }
256
257                 public void __AddTypeForwarder(Type type)
258                 {
259                         typeForwarders.Add(type);
260                 }
261
262                 public void SetEntryPoint(MethodInfo entryMethod)
263                 {
264                         SetEntryPoint(entryMethod, PEFileKinds.ConsoleApplication);
265                 }
266
267                 public void SetEntryPoint(MethodInfo entryMethod, PEFileKinds fileKind)
268                 {
269                         this.entryPoint = entryMethod;
270                         this.fileKind = fileKind;
271                 }
272
273                 public void __Save(Stream stream, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
274                 {
275                         if (!stream.CanRead || !stream.CanWrite || !stream.CanSeek || stream.Position != 0)
276                         {
277                                 throw new ArgumentException("Stream must support read/write/seek and current position must be zero.", "stream");
278                         }
279                         if (modules.Count != 1)
280                         {
281                                 throw new NotSupportedException("Saving to a stream is only supported for single module assemblies.");
282                         }
283                         SaveImpl(modules[0].fileName, stream, portableExecutableKind, imageFileMachine);
284                 }
285
286                 public void Save(string assemblyFileName)
287                 {
288                         Save(assemblyFileName, PortableExecutableKinds.ILOnly, ImageFileMachine.I386);
289                 }
290
291                 public void Save(string assemblyFileName, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
292                 {
293                         SaveImpl(assemblyFileName, null, portableExecutableKind, imageFileMachine);
294                 }
295
296                 private void SaveImpl(string assemblyFileName, Stream streamOrNull, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
297                 {
298                         ModuleBuilder manifestModule = null;
299
300                         foreach (ModuleBuilder moduleBuilder in modules)
301                         {
302                                 moduleBuilder.SetIsSaved();
303                                 moduleBuilder.PopulatePropertyAndEventTables();
304
305                                 if (manifestModule == null
306                                         && string.Compare(moduleBuilder.fileName, assemblyFileName, StringComparison.OrdinalIgnoreCase) == 0)
307                                 {
308                                         manifestModule = moduleBuilder;
309                                 }
310                         }
311
312                         if (manifestModule == null)
313                         {
314                                 manifestModule = DefineDynamicModule("RefEmit_OnDiskManifestModule", assemblyFileName, false);
315                         }
316
317                         AssemblyTable.Record assemblyRecord = new AssemblyTable.Record();
318                         assemblyRecord.HashAlgId = (int)hashAlgorithm;
319                         assemblyRecord.Name = manifestModule.Strings.Add(name);
320                         assemblyRecord.MajorVersion = majorVersion;
321                         assemblyRecord.MinorVersion = minorVersion;
322                         assemblyRecord.BuildNumber = buildVersion;
323                         assemblyRecord.RevisionNumber = revisionVersion;
324                         if (publicKey != null)
325                         {
326                                 assemblyRecord.PublicKey = manifestModule.Blobs.Add(ByteBuffer.Wrap(publicKey));
327                                 assemblyRecord.Flags = (int)(flags | AssemblyNameFlags.PublicKey);
328                         }
329                         else
330                         {
331                                 assemblyRecord.Flags = (int)(flags & ~AssemblyNameFlags.PublicKey);
332                         }
333                         if (culture != null)
334                         {
335                                 assemblyRecord.Culture = manifestModule.Strings.Add(culture);
336                         }
337                         int token = 0x20000000 + manifestModule.AssemblyTable.AddRecord(assemblyRecord);
338
339 #pragma warning disable 618
340                         // this values are obsolete, but we already know that so we disable the warning
341                         System.Security.Permissions.SecurityAction requestMinimum = System.Security.Permissions.SecurityAction.RequestMinimum;
342                         System.Security.Permissions.SecurityAction requestOptional = System.Security.Permissions.SecurityAction.RequestOptional;
343                         System.Security.Permissions.SecurityAction requestRefuse = System.Security.Permissions.SecurityAction.RequestRefuse;
344 #pragma warning restore 618
345                         if (requiredPermissions != null)
346                         {
347                                 manifestModule.AddDeclarativeSecurity(token, requestMinimum, requiredPermissions);
348                         }
349                         if (optionalPermissions != null)
350                         {
351                                 manifestModule.AddDeclarativeSecurity(token, requestOptional, optionalPermissions);
352                         }
353                         if (refusedPermissions != null)
354                         {
355                                 manifestModule.AddDeclarativeSecurity(token, requestRefuse, refusedPermissions);
356                         }
357
358                         ResourceSection unmanagedResources = versionInfo != null || win32icon != null || win32manifest != null || win32resources != null
359                                 ? new ResourceSection()
360                                 : null;
361
362                         if (versionInfo != null)
363                         {
364                                 versionInfo.SetName(GetName());
365                                 versionInfo.SetFileName(assemblyFileName);
366                                 foreach (CustomAttributeBuilder cab in customAttributes)
367                                 {
368                                         // .NET doesn't support copying blob custom attributes into the version info
369                                         if (!cab.HasBlob)
370                                         {
371                                                 versionInfo.SetAttribute(cab);
372                                         }
373                                 }
374                                 ByteBuffer versionInfoData = new ByteBuffer(512);
375                                 versionInfo.Write(versionInfoData);
376                                 unmanagedResources.AddVersionInfo(versionInfoData);
377                         }
378
379                         if (win32icon != null)
380                         {
381                                 unmanagedResources.AddIcon(win32icon);
382                         }
383
384                         if (win32manifest != null)
385                         {
386                                 unmanagedResources.AddManifest(win32manifest, fileKind == PEFileKinds.Dll ? (ushort)2 : (ushort)1);
387                         }
388
389                         if (win32resources != null)
390                         {
391                                 unmanagedResources.ExtractResources(win32resources);
392                         }
393
394                         foreach (CustomAttributeBuilder cab in customAttributes)
395                         {
396                                 // we intentionally don't filter out the version info (pseudo) custom attributes (to be compatible with .NET)
397                                 manifestModule.SetCustomAttribute(0x20000001, cab);
398                         }
399
400                         manifestModule.AddDeclarativeSecurity(0x20000001, declarativeSecurity);
401
402                         foreach (Type type in typeForwarders)
403                         {
404                                 manifestModule.AddTypeForwarder(type);
405                         }
406
407                         foreach (ResourceFile resfile in resourceFiles)
408                         {
409                                 if (resfile.Writer != null)
410                                 {
411                                         resfile.Writer.Generate();
412                                         resfile.Writer.Close();
413                                 }
414                                 int fileToken = AddFile(manifestModule, resfile.FileName, 1 /*ContainsNoMetaData*/);
415                                 ManifestResourceTable.Record rec = new ManifestResourceTable.Record();
416                                 rec.Offset = 0;
417                                 rec.Flags = (int)resfile.Attributes;
418                                 rec.Name = manifestModule.Strings.Add(resfile.Name);
419                                 rec.Implementation = fileToken;
420                                 manifestModule.ManifestResource.AddRecord(rec);
421                         }
422
423                         int entryPointToken = 0;
424
425                         foreach (ModuleBuilder moduleBuilder in modules)
426                         {
427                                 moduleBuilder.FillAssemblyRefTable();
428                                 moduleBuilder.EmitResources();
429                                 if (moduleBuilder != manifestModule)
430                                 {
431                                         int fileToken;
432                                         if (entryPoint != null && entryPoint.Module == moduleBuilder)
433                                         {
434                                                 ModuleWriter.WriteModule(null, null, moduleBuilder, fileKind, portableExecutableKind, imageFileMachine, moduleBuilder.unmanagedResources, entryPoint.MetadataToken);
435                                                 entryPointToken = fileToken = AddFile(manifestModule, moduleBuilder.fileName, 0 /*ContainsMetaData*/);
436                                         }
437                                         else
438                                         {
439                                                 ModuleWriter.WriteModule(null, null, moduleBuilder, fileKind, portableExecutableKind, imageFileMachine, moduleBuilder.unmanagedResources, 0);
440                                                 fileToken = AddFile(manifestModule, moduleBuilder.fileName, 0 /*ContainsMetaData*/);
441                                         }
442                                         moduleBuilder.ExportTypes(fileToken, manifestModule);
443                                 }
444                         }
445
446                         foreach (Module module in addedModules)
447                         {
448                                 int fileToken = AddFile(manifestModule, module.FullyQualifiedName, 0 /*ContainsMetaData*/);
449                                 module.ExportTypes(fileToken, manifestModule);
450                         }
451
452                         if (entryPointToken == 0 && entryPoint != null)
453                         {
454                                 entryPointToken = entryPoint.MetadataToken;
455                         }
456
457                         // finally, write the manifest module
458                         ModuleWriter.WriteModule(keyPair, publicKey, manifestModule, fileKind, portableExecutableKind, imageFileMachine, unmanagedResources ?? manifestModule.unmanagedResources, entryPointToken, streamOrNull);
459                 }
460
461                 private int AddFile(ModuleBuilder manifestModule, string fileName, int flags)
462                 {
463                         SHA1Managed hash = new SHA1Managed();
464                         string fullPath = fileName;
465                         if (dir != null)
466                         {
467                                 fullPath = Path.Combine(dir, fileName);
468                         }
469                         using (FileStream fs = new FileStream(fullPath, FileMode.Open, FileAccess.Read))
470                         {
471                                 using (CryptoStream cs = new CryptoStream(Stream.Null, hash, CryptoStreamMode.Write))
472                                 {
473                                         byte[] buf = new byte[8192];
474                                         ModuleWriter.HashChunk(fs, cs, buf, (int)fs.Length);
475                                 }
476                         }
477                         return manifestModule.__AddModule(flags, Path.GetFileName(fileName), hash.Hash);
478                 }
479
480                 public void AddResourceFile(string name, string fileName)
481                 {
482                         AddResourceFile(name, fileName, ResourceAttributes.Public);
483                 }
484
485                 public void AddResourceFile(string name, string fileName, ResourceAttributes attribs)
486                 {
487                         ResourceFile resfile = new ResourceFile();
488                         resfile.Name = name;
489                         resfile.FileName = fileName;
490                         resfile.Attributes = attribs;
491                         resourceFiles.Add(resfile);
492                 }
493
494                 public IResourceWriter DefineResource(string name, string description, string fileName)
495                 {
496                         return DefineResource(name, description, fileName, ResourceAttributes.Public);
497                 }
498
499                 public IResourceWriter DefineResource(string name, string description, string fileName, ResourceAttributes attribute)
500                 {
501                         // FXBUG we ignore the description, because there is no such thing
502
503                         string fullPath = fileName;
504                         if (dir != null)
505                         {
506                                 fullPath = Path.Combine(dir, fileName);
507                         }
508                         ResourceWriter rw = new ResourceWriter(fullPath);
509                         ResourceFile resfile;
510                         resfile.Name = name;
511                         resfile.FileName = fileName;
512                         resfile.Attributes = attribute;
513                         resfile.Writer = rw;
514                         resourceFiles.Add(resfile);
515                         return rw;
516                 }
517
518                 public void DefineVersionInfoResource()
519                 {
520                         if (versionInfo != null || win32resources != null)
521                         {
522                                 throw new ArgumentException("Native resource has already been defined.");
523                         }
524                         versionInfo = new VersionInfo();
525                 }
526
527                 public void DefineVersionInfoResource(string product, string productVersion, string company, string copyright, string trademark)
528                 {
529                         if (versionInfo != null || win32resources != null)
530                         {
531                                 throw new ArgumentException("Native resource has already been defined.");
532                         }
533                         versionInfo = new VersionInfo();
534                         versionInfo.product = product;
535                         versionInfo.informationalVersion = productVersion;
536                         versionInfo.company = company;
537                         versionInfo.copyright = copyright;
538                         versionInfo.trademark = trademark;
539                 }
540
541                 public void __DefineIconResource(byte[] iconFile)
542                 {
543                         if (win32icon != null || win32resources != null)
544                         {
545                                 throw new ArgumentException("Native resource has already been defined.");
546                         }
547                         win32icon = (byte[])iconFile.Clone();
548                 }
549
550                 public void __DefineManifestResource(byte[] manifest)
551                 {
552                         if (win32manifest != null || win32resources != null)
553                         {
554                                 throw new ArgumentException("Native resource has already been defined.");
555                         }
556                         win32manifest = (byte[])manifest.Clone();
557                 }
558
559                 public void __DefineUnmanagedResource(byte[] resource)
560                 {
561                         if (versionInfo != null || win32icon != null || win32manifest != null || win32resources != null)
562                         {
563                                 throw new ArgumentException("Native resource has already been defined.");
564                         }
565                         // The standard .NET DefineUnmanagedResource(byte[]) is useless, because it embeds "resource" (as-is) as the .rsrc section,
566                         // but it doesn't set the PE file Resource Directory entry to point to it. That's why we have a renamed version, which behaves
567                         // like DefineUnmanagedResource(string).
568                         win32resources = (byte[])resource.Clone();
569                 }
570
571                 public void DefineUnmanagedResource(string resourceFileName)
572                 {
573                         // This method reads the specified resource file (Win32 .res file) and converts it into the appropriate format and embeds it in the .rsrc section,
574                         // also setting the Resource Directory entry.
575                         __DefineUnmanagedResource(File.ReadAllBytes(resourceFileName));
576                 }
577
578                 public override Type[] GetTypes()
579                 {
580                         List<Type> list = new List<Type>();
581                         foreach (ModuleBuilder module in modules)
582                         {
583                                 module.GetTypesImpl(list);
584                         }
585                         foreach (Module module in addedModules)
586                         {
587                                 module.GetTypesImpl(list);
588                         }
589                         return list.ToArray();
590                 }
591
592                 internal override Type FindType(TypeName typeName)
593                 {
594                         foreach (ModuleBuilder mb in modules)
595                         {
596                                 Type type = mb.FindType(typeName);
597                                 if (type != null)
598                                 {
599                                         return type;
600                                 }
601                         }
602                         foreach (Module module in addedModules)
603                         {
604                                 Type type = module.FindType(typeName);
605                                 if (type != null)
606                                 {
607                                         return type;
608                                 }
609                         }
610                         return null;
611                 }
612
613                 internal override Type FindTypeIgnoreCase(TypeName lowerCaseName)
614                 {
615                         foreach (ModuleBuilder mb in modules)
616                         {
617                                 Type type = mb.FindTypeIgnoreCase(lowerCaseName);
618                                 if (type != null)
619                                 {
620                                         return type;
621                                 }
622                         }
623                         foreach (Module module in addedModules)
624                         {
625                                 Type type = module.FindTypeIgnoreCase(lowerCaseName);
626                                 if (type != null)
627                                 {
628                                         return type;
629                                 }
630                         }
631                         return null;
632                 }
633
634                 public override string ImageRuntimeVersion
635                 {
636                         get { return imageRuntimeVersion; }
637                 }
638
639                 public void __SetImageRuntimeVersion(string imageRuntimeVersion, int mdStreamVersion)
640                 {
641                         this.imageRuntimeVersion = imageRuntimeVersion;
642                         this.mdStreamVersion = mdStreamVersion;
643                 }
644
645                 public override Module ManifestModule
646                 {
647                         get
648                         {
649                                 if (pseudoManifestModule == null)
650                                 {
651                                         pseudoManifestModule = new ManifestModule(this);
652                                 }
653                                 return pseudoManifestModule;
654                         }
655                 }
656
657                 public override MethodInfo EntryPoint
658                 {
659                         get { return entryPoint; }
660                 }
661
662                 public override AssemblyName[] GetReferencedAssemblies()
663                 {
664                         return Empty<AssemblyName>.Array;
665                 }
666
667                 public override Module[] GetLoadedModules(bool getResourceModules)
668                 {
669                         return GetModules(getResourceModules);
670                 }
671
672                 public override Module[] GetModules(bool getResourceModules)
673                 {
674                         List<Module> list = new List<Module>();
675                         foreach (ModuleBuilder module in modules)
676                         {
677                                 if (getResourceModules || !module.IsResource())
678                                 {
679                                         list.Add(module);
680                                 }
681                         }
682                         foreach (Module module in addedModules)
683                         {
684                                 if (getResourceModules || !module.IsResource())
685                                 {
686                                         list.Add(module);
687                                 }
688                         }
689                         return list.ToArray();
690                 }
691
692                 public override Module GetModule(string name)
693                 {
694                         foreach (ModuleBuilder module in modules)
695                         {
696                                 if (module.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase))
697                                 {
698                                         return module;
699                                 }
700                         }
701                         foreach (Module module in addedModules)
702                         {
703                                 if (module.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase))
704                                 {
705                                         return module;
706                                 }
707                         }
708                         return null;
709                 }
710
711                 public Module __AddModule(RawModule module)
712                 {
713                         Module mod = module.ToModule(this);
714                         addedModules.Add(mod);
715                         return mod;
716                 }
717
718                 public override ManifestResourceInfo GetManifestResourceInfo(string resourceName)
719                 {
720                         throw new NotSupportedException();
721                 }
722
723                 public override string[] GetManifestResourceNames()
724                 {
725                         throw new NotSupportedException();
726                 }
727
728                 public override Stream GetManifestResourceStream(string resourceName)
729                 {
730                         throw new NotSupportedException();
731                 }
732
733                 internal override IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
734                 {
735                         List<CustomAttributeData> list = new List<CustomAttributeData>();
736                         foreach (CustomAttributeBuilder cab in customAttributes)
737                         {
738                                 if (attributeType == null || attributeType.IsAssignableFrom(cab.Constructor.DeclaringType))
739                                 {
740                                         list.Add(cab.ToData(this));
741                                 }
742                         }
743                         return list;
744                 }
745
746                 internal bool IsWindowsRuntime
747                 {
748                         get { return (flags & (AssemblyNameFlags)0x200) != 0; }
749                 }
750         }
751
752         sealed class ManifestModule : NonPEModule
753         {
754                 private readonly AssemblyBuilder assembly;
755                 private readonly Guid guid = Guid.NewGuid();
756
757                 internal ManifestModule(AssemblyBuilder assembly)
758                         : base(assembly.universe)
759                 {
760                         this.assembly = assembly;
761                 }
762
763                 public override int MDStreamVersion
764                 {
765                         get { return assembly.mdStreamVersion; }
766                 }
767
768                 public override Assembly Assembly
769                 {
770                         get { return assembly; }
771                 }
772
773                 internal override Type FindType(TypeName typeName)
774                 {
775                         return null;
776                 }
777
778                 internal override Type FindTypeIgnoreCase(TypeName lowerCaseName)
779                 {
780                         return null;
781                 }
782
783                 internal override void  GetTypesImpl(List<Type> list)
784                 {
785                 }
786
787                 public override string FullyQualifiedName
788                 {
789                         get { return Path.Combine(assembly.dir, "RefEmit_InMemoryManifestModule"); }
790                 }
791
792                 public override string Name
793                 {
794                         get { return "<In Memory Module>"; }
795                 }
796
797                 public override Guid ModuleVersionId
798                 {
799                         get { return guid; }
800                 }
801
802                 public override string ScopeName
803                 {
804                         get { return "RefEmit_InMemoryManifestModule"; }
805                 }
806
807                 protected override Exception NotSupportedException()
808                 {
809                         return new InvalidOperationException();
810                 }
811         }
812 }