Merge pull request #495 from nicolas-raoul/fix-for-issue2907-with-no-formatting-changes
[mono.git] / mcs / class / corlib / System.Reflection.Emit / AssemblyBuilder.cs
1 //
2 // System.Reflection.Emit/AssemblyBuilder.cs
3 //
4 // Author:
5 //   Paolo Molaro (lupus@ximian.com)
6 //
7 // (C) 2001 Ximian, Inc.  http://www.ximian.com
8 //
9
10 //
11 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
20 // 
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
23 // 
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 //
32
33 #if !FULL_AOT_RUNTIME
34 using System;
35 using System.Reflection;
36 using System.Resources;
37 using System.IO;
38 using System.Security.Policy;
39 using System.Runtime.Serialization;
40 using System.Globalization;
41 using System.Runtime.CompilerServices;
42 using System.Collections;
43 using System.Collections.Generic;
44 using System.Runtime.InteropServices;
45 using System.Security;
46 using System.Security.Cryptography;
47 using System.Security.Permissions;
48
49 using Mono.Security;
50 using Mono.Security.Cryptography;
51
52 namespace System.Reflection.Emit
53 {
54         internal enum NativeResourceType
55         {
56                 None,
57                 Unmanaged,
58                 Assembly,
59                 Explicit
60         }
61
62         internal struct RefEmitPermissionSet {
63                 public SecurityAction action;
64                 public string pset;
65
66                 public RefEmitPermissionSet (SecurityAction action, string pset) {
67                         this.action = action;
68                         this.pset = pset;
69                 }
70         }
71
72         internal struct MonoResource {
73 #pragma warning disable 649
74                 public byte[] data;
75                 public string name;
76                 public string filename;
77                 public ResourceAttributes attrs;
78                 public int offset;
79                 public Stream stream;
80 #pragma warning restore 649
81         }
82
83         internal struct MonoWin32Resource {
84                 public int res_type;
85                 public int res_id;
86                 public int lang_id;
87                 public byte[] data;
88
89                 public MonoWin32Resource (int res_type, int res_id, int lang_id, byte[] data) {
90                         this.res_type = res_type;
91                         this.res_id = res_id;
92                         this.lang_id = lang_id;
93                         this.data = data;
94                 }
95         }
96
97         internal class GenericInstanceKey {
98                 Type gtd;
99                 internal Type[] args;
100                 int hash_code;
101
102                 internal GenericInstanceKey (Type gtd, Type[] args)
103                 {
104                         this.gtd = gtd;
105                         this.args = args;
106
107                         hash_code = gtd.GetHashCode ();
108                         for (int i = 0; i < args.Length; ++i)
109                                 hash_code ^= args [i].GetHashCode ();
110                 }
111
112                 static bool IsBoundedVector (Type type) {
113                         ArrayType at = type as ArrayType;
114                         if (at != null)
115                                 return at.GetEffectiveRank () == 1;
116                         return type.ToString ().EndsWith ("[*]", StringComparison.Ordinal); /*Super uggly hack, SR doesn't allow one to query for it */
117                 }
118
119                 static bool TypeEquals (Type a, Type b) {
120                         if (a == b)
121                                 return true;
122
123                         if (a.HasElementType) {
124                                 if (!b.HasElementType)
125                                         return false;
126                                 if (!TypeEquals (a.GetElementType (), b.GetElementType ()))
127                                         return false;
128                                 if (a.IsArray) {
129                                         if (!b.IsArray)
130                                                 return false;
131                                         int rank = a.GetArrayRank ();
132                                         if (rank != b.GetArrayRank ())
133                                                 return false;
134                                         if (rank == 1 && IsBoundedVector (a) != IsBoundedVector (b))
135                                                 return false;
136                                 } else if (a.IsByRef) {
137                                         if (!b.IsByRef)
138                                                 return false;
139                                 } else if (a.IsPointer) {
140                                         if (!b.IsPointer)
141                                                 return false;
142                                 }
143                                 return true;
144                         }
145
146                         if (a.IsGenericType) {
147                                 if (!b.IsGenericType)
148                                         return false;
149                                 if (a.IsGenericParameter)
150                                         return a == b;
151                                 if (a.IsGenericParameter) //previous test should have caught it
152                                         return false;
153
154                                 if (a.IsGenericTypeDefinition) {
155                                         if (!b.IsGenericTypeDefinition)
156                                                 return false;
157                                 } else {
158                                         if (b.IsGenericTypeDefinition)
159                                                 return false;
160                                         if (!TypeEquals (a.GetGenericTypeDefinition (), b.GetGenericTypeDefinition ()))
161                                                 return false;
162
163                                         Type[] argsA = a.GetGenericArguments ();
164                                         Type[] argsB = b.GetGenericArguments ();
165                                         for (int i = 0; i < argsA.Length; ++i) {
166                                                 if (!TypeEquals (argsA [i], argsB [i]))
167                                                         return false;
168                                         }
169                                 }
170                         }
171
172                         /*
173                         Now only non-generic, non compound types are left. To properly deal with user
174                         types we would have to call UnderlyingSystemType, but we let them have their
175                         own instantiation as this is MS behavior and mcs (pre C# 4.0, at least) doesn't
176                         depend on proper UT canonicalization.
177                         */
178                         return a == b;
179                 }
180
181                 public override bool Equals (object obj)
182                 {
183                         GenericInstanceKey other = obj as GenericInstanceKey;
184                         if (other == null)
185                                 return false;
186                         if (gtd != other.gtd)
187                                 return false;
188                         for (int i = 0; i < args.Length; ++i) {
189                                 Type a = args [i];
190                                 Type b = other.args [i];
191                                 /*
192                                 We must cannonicalize as much as we can. Using equals means that some resulting types
193                                 won't have the exact same types as the argument ones. 
194                                 For example, flyweight types used array, pointer and byref will should this behavior.
195                                 MCS seens to be resilient to this problem so hopefully this won't show up.   
196                                 */
197                                 if (a != b && !a.Equals (b))
198                                         return false;
199                         }
200                         return true;
201                 }
202
203                 public override int GetHashCode ()
204                 {
205                         return hash_code;
206                 }
207         }
208
209
210         [ComVisible (true)]
211         [ComDefaultInterface (typeof (_AssemblyBuilder))]
212         [ClassInterface (ClassInterfaceType.None)]
213         [StructLayout (LayoutKind.Sequential)]
214         public sealed class AssemblyBuilder : Assembly, _AssemblyBuilder {
215 #pragma warning disable 169, 414, 649
216                 #region Sync with object-internals.h
217                 private UIntPtr dynamic_assembly; /* GC-tracked */
218                 private MethodInfo entry_point;
219                 private ModuleBuilder[] modules;
220                 private string name;
221                 private string dir;
222                 private CustomAttributeBuilder[] cattrs;
223                 private MonoResource[] resources;
224                 byte[] public_key;
225                 string version;
226                 string culture;
227                 uint algid;
228                 uint flags;
229                 PEFileKinds pekind = PEFileKinds.Dll;
230                 bool delay_sign;
231                 uint access;
232                 Module[] loaded_modules;
233                 MonoWin32Resource[] win32_resources;
234                 private RefEmitPermissionSet[] permissions_minimum;
235                 private RefEmitPermissionSet[] permissions_optional;
236                 private RefEmitPermissionSet[] permissions_refused;
237                 PortableExecutableKinds peKind;
238                 ImageFileMachine machine;
239                 bool corlib_internal;
240                 Type[] type_forwarders;
241                 byte[] pktoken;
242                 #endregion
243 #pragma warning restore 169, 414, 649
244                 
245                 internal Type corlib_object_type = typeof (System.Object);
246                 internal Type corlib_value_type = typeof (System.ValueType);
247                 internal Type corlib_enum_type = typeof (System.Enum);
248                 internal Type corlib_void_type = typeof (void);
249                 ArrayList resource_writers = null;
250                 Win32VersionResource version_res;
251                 bool created;
252                 bool is_module_only;
253                 private Mono.Security.StrongName sn;
254                 NativeResourceType native_resource;
255                 string versioninfo_culture;
256
257                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
258                 private static extern void basic_init (AssemblyBuilder ab);
259
260                 /* Keep this in sync with codegen.cs in mcs */
261                 private const AssemblyBuilderAccess COMPILER_ACCESS = (AssemblyBuilderAccess) 0x800;
262
263                 internal AssemblyBuilder (AssemblyName n, string directory, AssemblyBuilderAccess access, bool corlib_internal)
264                 {
265                         /* This is obsolete now, as mcs doesn't use SRE any more */
266                         if ((access & COMPILER_ACCESS) != 0)
267                                 throw new NotImplementedException ("COMPILER_ACCESS is no longer supperted, use a newer mcs.");
268
269 #if MOONLIGHT
270                         // only "Run" is supported by Silverlight
271                         // however SMCS requires more than this but runs outside the CoreCLR sandbox
272                         if (SecurityManager.SecurityEnabled && (access != AssemblyBuilderAccess.Run))
273                                 throw new ArgumentException ("access");
274 #endif
275
276                         if (!Enum.IsDefined (typeof (AssemblyBuilderAccess), access))
277                                 throw new ArgumentException (string.Format (CultureInfo.InvariantCulture,
278                                         "Argument value {0} is not valid.", (int) access),
279                                         "access");
280
281                         name = n.Name;
282                         this.access = (uint)access;
283                         flags = (uint) n.Flags;
284
285                         // don't call GetCurrentDirectory for Run-only builders (CAS may not like that)
286                         if (IsSave && (directory == null || directory.Length == 0)) {
287                                 dir = Directory.GetCurrentDirectory ();
288                         } else {
289                                 dir = directory;
290                         }
291
292                         /* Set defaults from n */
293                         if (n.CultureInfo != null) {
294                                 culture = n.CultureInfo.Name;
295                                 versioninfo_culture = n.CultureInfo.Name;
296                         }
297                         Version v = n.Version;
298                         if (v != null) {
299                                 version = v.ToString ();
300                         }
301
302                         if (n.KeyPair != null) {
303                                 // full keypair is available (for signing)
304                                 sn = n.KeyPair.StrongName ();
305                         } else {
306                                 // public key is available (for delay-signing)
307                                 byte[] pk = n.GetPublicKey ();
308                                 if ((pk != null) && (pk.Length > 0)) {
309                                         sn = new Mono.Security.StrongName (pk);
310                                 }
311                         }
312
313                         if (sn != null)
314                                 flags |= (uint) AssemblyNameFlags.PublicKey;
315
316                         this.corlib_internal = corlib_internal;
317                         if (sn != null) {
318                                 this.pktoken = new byte[sn.PublicKeyToken.Length * 2];
319                                 int pkti = 0;
320                                 foreach (byte pkb in sn.PublicKeyToken) {
321                                         string part = pkb.ToString("x2");
322                                         this.pktoken[pkti++] = (byte)part[0];
323                                         this.pktoken[pkti++] = (byte)part[1];
324                                 }
325                         }
326
327                         basic_init (this);
328                 }
329
330                 public override string CodeBase {
331                         get {
332                                 throw not_supported ();
333                         }
334                 }
335                 
336                 public override MethodInfo EntryPoint {
337                         get {
338                                 return entry_point;
339                         }
340                 }
341
342                 public override string Location {
343                         get {
344                                 throw not_supported ();
345                         }
346                 }
347
348                 /* This is to keep signature compatibility with MS.NET */
349                 public override string ImageRuntimeVersion {
350                         get {
351                                 return base.ImageRuntimeVersion;
352                         }
353                 }
354
355                 [MonoTODO]
356                 public override bool ReflectionOnly {
357                         get { return base.ReflectionOnly; }
358                 }
359
360                 public void AddResourceFile (string name, string fileName)
361                 {
362                         AddResourceFile (name, fileName, ResourceAttributes.Public);
363                 }
364
365                 public void AddResourceFile (string name, string fileName, ResourceAttributes attribute)
366                 {
367                         AddResourceFile (name, fileName, attribute, true);
368                 }
369
370                 private void AddResourceFile (string name, string fileName, ResourceAttributes attribute, bool fileNeedsToExists)
371                 {
372                         check_name_and_filename (name, fileName, fileNeedsToExists);
373
374                         // Resource files are created/searched under the assembly storage
375                         // directory
376                         if (dir != null)
377                                 fileName = Path.Combine (dir, fileName);
378
379                         if (resources != null) {
380                                 MonoResource[] new_r = new MonoResource [resources.Length + 1];
381                                 System.Array.Copy(resources, new_r, resources.Length);
382                                 resources = new_r;
383                         } else {
384                                 resources = new MonoResource [1];
385                         }
386                         int p = resources.Length - 1;
387                         resources [p].name = name;
388                         resources [p].filename = fileName;
389                         resources [p].attrs = attribute;
390                 }
391
392                 internal void AddPermissionRequests (PermissionSet required, PermissionSet optional, PermissionSet refused)
393                 {
394 #if !NET_2_1
395                         if (created)
396                                 throw new InvalidOperationException ("Assembly was already saved.");
397
398                         // required for base Assembly class (so the permissions
399                         // can be used even if the assembly isn't saved to disk)
400                         _minimum = required;
401                         _optional = optional;
402                         _refuse = refused;
403
404                         // required to reuse AddDeclarativeSecurity support 
405                         // already present in the runtime
406                         if (required != null) {
407                                 permissions_minimum = new RefEmitPermissionSet [1];
408                                 permissions_minimum [0] = new RefEmitPermissionSet (
409                                         SecurityAction.RequestMinimum, required.ToXml ().ToString ());
410                         }
411                         if (optional != null) {
412                                 permissions_optional = new RefEmitPermissionSet [1];
413                                 permissions_optional [0] = new RefEmitPermissionSet (
414                                         SecurityAction.RequestOptional, optional.ToXml ().ToString ());
415                         }
416                         if (refused != null) {
417                                 permissions_refused = new RefEmitPermissionSet [1];
418                                 permissions_refused [0] = new RefEmitPermissionSet (
419                                         SecurityAction.RequestRefuse, refused.ToXml ().ToString ());
420                         }
421 #endif
422                 }
423
424                 // Still in use by al.exe
425                 internal void EmbedResourceFile (string name, string fileName)
426                 {
427                         EmbedResourceFile (name, fileName, ResourceAttributes.Public);
428                 }
429
430                 void EmbedResourceFile (string name, string fileName, ResourceAttributes attribute)
431                 {
432                         if (resources != null) {
433                                 MonoResource[] new_r = new MonoResource [resources.Length + 1];
434                                 System.Array.Copy(resources, new_r, resources.Length);
435                                 resources = new_r;
436                         } else {
437                                 resources = new MonoResource [1];
438                         }
439                         int p = resources.Length - 1;
440                         resources [p].name = name;
441                         resources [p].attrs = attribute;
442                         try {
443                                 FileStream s = new FileStream (fileName, FileMode.Open, FileAccess.Read);
444                                 long len = s.Length;
445                                 resources [p].data = new byte [len];
446                                 s.Read (resources [p].data, 0, (int)len);
447                                 s.Close ();
448                         } catch {
449                         }
450                 }
451 /*
452                 internal void EmbedResource (string name, byte[] blob, ResourceAttributes attribute)
453                 {
454                         if (resources != null) {
455                                 MonoResource[] new_r = new MonoResource [resources.Length + 1];
456                                 System.Array.Copy(resources, new_r, resources.Length);
457                                 resources = new_r;
458                         } else {
459                                 resources = new MonoResource [1];
460                         }
461                         int p = resources.Length - 1;
462                         resources [p].name = name;
463                         resources [p].attrs = attribute;
464                         resources [p].data = blob;
465                 }
466 */
467
468                 public ModuleBuilder DefineDynamicModule (string name)
469                 {
470                         return DefineDynamicModule (name, name, false, true);
471                 }
472
473                 public ModuleBuilder DefineDynamicModule (string name, bool emitSymbolInfo)
474                 {
475                         return DefineDynamicModule (name, name, emitSymbolInfo, true);
476                 }
477
478                 public ModuleBuilder DefineDynamicModule(string name, string fileName)
479                 {
480                         return DefineDynamicModule (name, fileName, false, false);
481                 }
482
483                 public ModuleBuilder DefineDynamicModule (string name, string fileName,
484                                                           bool emitSymbolInfo)
485                 {
486                         return DefineDynamicModule (name, fileName, emitSymbolInfo, false);
487                 }
488
489                 private ModuleBuilder DefineDynamicModule (string name, string fileName, bool emitSymbolInfo, bool transient)
490                 {
491                         check_name_and_filename (name, fileName, false);
492
493                         if (!transient) {
494                                 if (Path.GetExtension (fileName) == String.Empty)
495                                         throw new ArgumentException ("Module file name '" + fileName + "' must have file extension.");
496                                 if (!IsSave)
497                                         throw new NotSupportedException ("Persistable modules are not supported in a dynamic assembly created with AssemblyBuilderAccess.Run");
498                                 if (created)
499                                         throw new InvalidOperationException ("Assembly was already saved.");
500                         }
501
502                         ModuleBuilder r = new ModuleBuilder (this, name, fileName, emitSymbolInfo, transient);
503
504                         if ((modules != null) && is_module_only)
505                                 throw new InvalidOperationException ("A module-only assembly can only contain one module.");
506
507                         if (modules != null) {
508                                 ModuleBuilder[] new_modules = new ModuleBuilder [modules.Length + 1];
509                                 System.Array.Copy(modules, new_modules, modules.Length);
510                                 modules = new_modules;
511                         } else {
512                                 modules = new ModuleBuilder [1];
513                         }
514                         modules [modules.Length - 1] = r;
515                         return r;
516                 }
517
518                 public IResourceWriter DefineResource (string name, string description, string fileName)
519                 {
520                         return DefineResource (name, description, fileName, ResourceAttributes.Public);
521                 }
522
523                 public IResourceWriter DefineResource (string name, string description,
524                                                        string fileName, ResourceAttributes attribute)
525                 {
526                         IResourceWriter writer;
527
528                         // description seems to be ignored
529                         AddResourceFile (name, fileName, attribute, false);
530                         writer = new ResourceWriter (fileName);
531                         if (resource_writers == null)
532                                 resource_writers = new ArrayList ();
533                         resource_writers.Add (writer);
534                         return writer;
535                 }
536
537                 private void AddUnmanagedResource (Win32Resource res) {
538                         MemoryStream ms = new MemoryStream ();
539                         res.WriteTo (ms);
540
541                         if (win32_resources != null) {
542                                 MonoWin32Resource[] new_res = new MonoWin32Resource [win32_resources.Length + 1];
543                                 System.Array.Copy (win32_resources, new_res, win32_resources.Length);
544                                 win32_resources = new_res;
545                         }
546                         else
547                                 win32_resources = new MonoWin32Resource [1];
548
549                         win32_resources [win32_resources.Length - 1] = new MonoWin32Resource (res.Type.Id, res.Name.Id, res.Language, ms.ToArray ());
550                 }
551
552                 [MonoTODO ("Not currently implemenented")]
553                 public void DefineUnmanagedResource (byte[] resource)
554                 {
555                         if (resource == null)
556                                 throw new ArgumentNullException ("resource");
557                         if (native_resource != NativeResourceType.None)
558                                 throw new ArgumentException ("Native resource has already been defined.");
559
560                         // avoid definition of more than one unmanaged resource
561                         native_resource = NativeResourceType.Unmanaged;
562
563                         /*
564                          * The format of the argument byte array is not documented
565                          * so this method is impossible to implement.
566                          *
567                          * https://connect.microsoft.com/VisualStudio/feedback/details/95784/fatal-assemblybuilder-defineunmanagedresource-byte-and-modulebuilder-defineunmanagedresource-byte-bugs-renders-them-useless
568                          */
569
570                         throw new NotImplementedException ();
571                 }
572
573                 public void DefineUnmanagedResource (string resourceFileName)
574                 {
575                         if (resourceFileName == null)
576                                 throw new ArgumentNullException ("resourceFileName");
577                         if (resourceFileName.Length == 0)
578                                 throw new ArgumentException ("resourceFileName");
579                         if (!File.Exists (resourceFileName) || Directory.Exists (resourceFileName))
580                                 throw new FileNotFoundException ("File '" + resourceFileName + "' does not exists or is a directory.");
581                         if (native_resource != NativeResourceType.None)
582                                 throw new ArgumentException ("Native resource has already been defined.");
583
584                         // avoid definition of more than one unmanaged resource
585                         native_resource = NativeResourceType.Unmanaged;
586
587                         using (FileStream fs = new FileStream (resourceFileName, FileMode.Open, FileAccess.Read)) {
588                                 Win32ResFileReader reader = new Win32ResFileReader (fs);
589
590                                 foreach (Win32EncodedResource res in reader.ReadResources ()) {
591                                         if (res.Name.IsName || res.Type.IsName)
592                                                 throw new InvalidOperationException ("resource files with named resources or non-default resource types are not supported.");
593
594                                         AddUnmanagedResource (res);
595                                 }
596                         }
597                 }
598
599                 public void DefineVersionInfoResource ()
600                 {
601                         if (native_resource != NativeResourceType.None)
602                                 throw new ArgumentException ("Native resource has already been defined.");
603
604                         // avoid definition of more than one unmanaged resource
605                         native_resource = NativeResourceType.Assembly;
606
607                         version_res = new Win32VersionResource (1, 0, false);
608                 }
609
610                 public void DefineVersionInfoResource (string product, string productVersion,
611                                                        string company, string copyright, string trademark)
612                 {
613                         if (native_resource != NativeResourceType.None)
614                                 throw new ArgumentException ("Native resource has already been defined.");
615
616                         // avoid definition of more than one unmanaged resource
617                         native_resource = NativeResourceType.Explicit;
618
619                         /*
620                          * We can only create the resource later, when the file name and
621                          * the binary version is known.
622                          */
623
624                         version_res = new Win32VersionResource (1, 0, false);
625                         version_res.ProductName = product != null ? product : " ";
626                         version_res.ProductVersion = productVersion != null ? productVersion : " ";
627                         version_res.CompanyName = company != null ? company : " ";
628                         version_res.LegalCopyright = copyright != null ? copyright : " ";
629                         version_res.LegalTrademarks = trademark != null ? trademark : " ";
630                 }
631
632                 private void DefineVersionInfoResourceImpl (string fileName)
633                 {
634                         if (versioninfo_culture != null)
635                                 version_res.FileLanguage = new CultureInfo (versioninfo_culture).LCID;
636                         version_res.Version = version == null ? "0.0.0.0" : version;
637
638                         if (cattrs != null) {
639                                 switch (native_resource) {
640                                 case NativeResourceType.Assembly:
641                                         foreach (CustomAttributeBuilder cb in cattrs) {
642                                                 string attrname = cb.Ctor.ReflectedType.FullName;
643
644                                                 if (attrname == "System.Reflection.AssemblyProductAttribute")
645                                                         version_res.ProductName = cb.string_arg ();
646                                                 else if (attrname == "System.Reflection.AssemblyCompanyAttribute")
647                                                         version_res.CompanyName = cb.string_arg ();
648                                                 else if (attrname == "System.Reflection.AssemblyCopyrightAttribute")
649                                                         version_res.LegalCopyright = cb.string_arg ();
650                                                 else if (attrname == "System.Reflection.AssemblyTrademarkAttribute")
651                                                         version_res.LegalTrademarks = cb.string_arg ();
652                                                 else if (attrname == "System.Reflection.AssemblyCultureAttribute") {
653                                                         version_res.FileLanguage = new CultureInfo (cb.string_arg ()).LCID;
654                                                 } else if (attrname == "System.Reflection.AssemblyFileVersionAttribute") {
655                                                         version_res.FileVersion = cb.string_arg ();
656                                                 } else if (attrname == "System.Reflection.AssemblyInformationalVersionAttribute")
657                                                         version_res.ProductVersion = cb.string_arg ();
658                                                 else if (attrname == "System.Reflection.AssemblyTitleAttribute")
659                                                         version_res.FileDescription = cb.string_arg ();
660                                                 else if (attrname == "System.Reflection.AssemblyDescriptionAttribute")
661                                                         version_res.Comments = cb.string_arg ();
662                                         }
663                                         break;
664                                 case NativeResourceType.Explicit:
665                                         foreach (CustomAttributeBuilder cb in cattrs) {
666                                                 string attrname = cb.Ctor.ReflectedType.FullName;
667
668                                                 if (attrname == "System.Reflection.AssemblyCultureAttribute") {
669                                                         version_res.FileLanguage = new CultureInfo (cb.string_arg ()).LCID;
670                                                 } else if (attrname == "System.Reflection.AssemblyDescriptionAttribute")
671                                                         version_res.Comments = cb.string_arg ();
672                                         }
673                                         break;
674                                 }
675                         }
676
677                         version_res.OriginalFilename = fileName;
678                         version_res.InternalName = Path.GetFileNameWithoutExtension (fileName);
679
680                         AddUnmanagedResource (version_res);
681                 }
682
683                 public ModuleBuilder GetDynamicModule (string name)
684                 {
685                         if (name == null)
686                                 throw new ArgumentNullException ("name");
687                         if (name.Length == 0)
688                                 throw new ArgumentException ("Empty name is not legal.", "name");
689
690                         if (modules != null)
691                                 for (int i = 0; i < modules.Length; ++i)
692                                         if (modules [i].name == name)
693                                                 return modules [i];
694                         return null;
695                 }
696
697                 public override Type[] GetExportedTypes ()
698                 {
699                         throw not_supported ();
700                 }
701
702                 public override FileStream GetFile (string name)
703                 {
704                         throw not_supported ();
705                 }
706
707                 public override FileStream[] GetFiles(bool getResourceModules) {
708                         throw not_supported ();
709                 }
710
711                 internal override Module[] GetModulesInternal () {
712                         if (modules == null)
713                                 return new Module [0];
714                         else
715                                 return (Module[])modules.Clone ();
716                 }
717
718                 internal override Type[] GetTypes (bool exportedOnly) {
719                         Type[] res = null;
720                         if (modules != null) {
721                                 for (int i = 0; i < modules.Length; ++i) {
722                                         Type[] types = modules [i].GetTypes ();
723                                         if (res == null)
724                                                 res = types;
725                                         else {
726                                                 Type[] tmp = new Type [res.Length + types.Length];
727                                                 Array.Copy (res, 0, tmp, 0, res.Length);
728                                                 Array.Copy (types, 0, tmp, res.Length, types.Length);
729                                         }
730                                 }
731                         }
732                         if (loaded_modules != null) {
733                                 for (int i = 0; i < loaded_modules.Length; ++i) {
734                                         Type[] types = loaded_modules [i].GetTypes ();
735                                         if (res == null)
736                                                 res = types;
737                                         else {
738                                                 Type[] tmp = new Type [res.Length + types.Length];
739                                                 Array.Copy (res, 0, tmp, 0, res.Length);
740                                                 Array.Copy (types, 0, tmp, res.Length, types.Length);
741                                         }
742                                 }
743                         }
744
745                         if (res != null) {
746                                 List<Exception> exceptions = null;
747                                 foreach (var type in res) {
748                                         if (type is TypeBuilder) {
749                                                 if (exceptions == null)
750                                                         exceptions = new List <Exception> ();
751                                                 exceptions.Add (new TypeLoadException (string.Format ("Type '{0}' is not finished", type.FullName))); 
752                                         }
753                                 }
754                                 if (exceptions != null)
755                                         throw new ReflectionTypeLoadException (new Type [exceptions.Count], exceptions.ToArray ());
756                         }
757                         
758                         return res == null ? Type.EmptyTypes : res;
759                 }
760
761                 public override ManifestResourceInfo GetManifestResourceInfo(string resourceName) {
762                         throw not_supported ();
763                 }
764
765                 public override string[] GetManifestResourceNames() {
766                         throw not_supported ();
767                 }
768
769                 public override Stream GetManifestResourceStream(string name) {
770                         throw not_supported ();
771                 }
772                 public override Stream GetManifestResourceStream(Type type, string name) {
773                         throw not_supported ();
774                 }
775
776                 internal bool IsSave {
777                         get {
778                                 return access != (uint)AssemblyBuilderAccess.Run;
779                         }
780                 }
781
782                 internal bool IsRun {
783                         get {
784                                 return access == (uint)AssemblyBuilderAccess.Run || access == (uint)AssemblyBuilderAccess.RunAndSave
785 #if NET_4_0
786                                          || access == (uint)AssemblyBuilderAccess.RunAndCollect
787 #endif
788                                 ;
789
790                         }
791                 }
792 /*
793                 internal bool IsCollectible {
794                         get {
795                                 return access == (uint)AssemblyBuilderAccess.RunAndCollect;
796                         }
797                 }
798 */
799                 internal string AssemblyDir {
800                         get {
801                                 return dir;
802                         }
803                 }
804
805                 /*
806                  * Mono extension. If this is set, the assembly can only contain one
807                  * module, access should be Save, and the saved image will not contain an
808                  * assembly manifest.
809                  */
810                 internal bool IsModuleOnly {
811                         get {
812                                 return is_module_only;
813                         }
814                         set {
815                                 is_module_only = value;
816                         }
817                 }
818
819                 ModuleBuilder manifest_module;
820
821                 //
822                 // MS.NET seems to return a ModuleBuilder when GetManifestModule () is called
823                 // on an assemblybuilder.
824                 //
825                 internal override Module GetManifestModule () {
826                         if (manifest_module == null)
827                                 manifest_module = DefineDynamicModule ("Default Dynamic Module");
828                         return manifest_module;
829                 }
830
831                 [MonoLimitation ("No support for PE32+ assemblies for AMD64 and IA64")]
832                 public 
833                 void Save (string assemblyFileName, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
834                 {
835                         this.peKind = portableExecutableKind;
836                         this.machine = imageFileMachine;
837
838                         if ((peKind & PortableExecutableKinds.PE32Plus) != 0 || (peKind & PortableExecutableKinds.Unmanaged32Bit) != 0)
839                                 throw new NotImplementedException (peKind.ToString ());
840                         if (machine == ImageFileMachine.IA64 || machine == ImageFileMachine.AMD64)
841                                 throw new NotImplementedException (machine.ToString ());
842
843                         if (resource_writers != null) {
844                                 foreach (IResourceWriter writer in resource_writers) {
845                                         writer.Generate ();
846                                         writer.Close ();
847                                 }
848                         }
849
850                         // Create a main module if not already created
851                         ModuleBuilder mainModule = null;
852                         if (modules != null) {
853                                 foreach (ModuleBuilder module in modules)
854                                         if (module.FullyQualifiedName == assemblyFileName)
855                                                 mainModule = module;
856                         }
857                         if (mainModule == null)
858                                 mainModule = DefineDynamicModule ("RefEmit_OnDiskManifestModule", assemblyFileName);
859
860                         if (!is_module_only)
861                                 mainModule.IsMain = true;
862
863                         /* 
864                          * Create a new entry point if the one specified
865                          * by the user is in another module.
866                          */
867                         if ((entry_point != null) && entry_point.DeclaringType.Module != mainModule) {
868                                 Type[] paramTypes;
869                                 if (entry_point.GetParameters ().Length == 1)
870                                         paramTypes = new Type [] { typeof (string) };
871                                 else
872                                         paramTypes = Type.EmptyTypes;
873
874                                 MethodBuilder mb = mainModule.DefineGlobalMethod ("__EntryPoint$", MethodAttributes.Static|MethodAttributes.PrivateScope, entry_point.ReturnType, paramTypes);
875                                 ILGenerator ilgen = mb.GetILGenerator ();
876                                 if (paramTypes.Length == 1)
877                                         ilgen.Emit (OpCodes.Ldarg_0);
878                                 ilgen.Emit (OpCodes.Tailcall);
879                                 ilgen.Emit (OpCodes.Call, entry_point);
880                                 ilgen.Emit (OpCodes.Ret);
881
882                                 entry_point = mb;
883                         }
884
885                         if (version_res != null)
886                                 DefineVersionInfoResourceImpl (assemblyFileName);
887
888                         if (sn != null) {
889                                 // runtime needs to value to embed it into the assembly
890                                 public_key = sn.PublicKey;
891                         }
892
893                         foreach (ModuleBuilder module in modules)
894                                 if (module != mainModule)
895                                         module.Save ();
896
897                         // Write out the main module at the end, because it needs to
898                         // contain the hash of the other modules
899                         mainModule.Save ();
900
901                         if ((sn != null) && (sn.CanSign)) {
902                                 sn.Sign (System.IO.Path.Combine (this.AssemblyDir, assemblyFileName));
903                         }
904
905                         created = true;
906                 }
907
908                 public void Save (string assemblyFileName)
909                 {
910                         Save (assemblyFileName, PortableExecutableKinds.ILOnly, ImageFileMachine.I386);
911                 }
912
913                 public void SetEntryPoint (MethodInfo entryMethod)
914                 {
915                         SetEntryPoint (entryMethod, PEFileKinds.ConsoleApplication);
916                 }
917
918                 public void SetEntryPoint (MethodInfo entryMethod, PEFileKinds fileKind)
919                 {
920                         if (entryMethod == null)
921                                 throw new ArgumentNullException ("entryMethod");
922                         if (entryMethod.DeclaringType.Assembly != this)
923                                 throw new InvalidOperationException ("Entry method is not defined in the same assembly.");
924
925                         entry_point = entryMethod;
926                         pekind = fileKind;
927                 }
928
929                 public void SetCustomAttribute( CustomAttributeBuilder customBuilder) 
930                 {
931                         if (customBuilder == null)
932                                 throw new ArgumentNullException ("customBuilder");
933
934                         if (cattrs != null) {
935                                 CustomAttributeBuilder[] new_array = new CustomAttributeBuilder [cattrs.Length + 1];
936                                 cattrs.CopyTo (new_array, 0);
937                                 new_array [cattrs.Length] = customBuilder;
938                                 cattrs = new_array;
939                         } else {
940                                 cattrs = new CustomAttributeBuilder [1];
941                                 cattrs [0] = customBuilder;
942                         }
943                 }
944
945                 [ComVisible (true)]
946                 public void SetCustomAttribute ( ConstructorInfo con, byte[] binaryAttribute) {
947                         if (con == null)
948                                 throw new ArgumentNullException ("con");
949                         if (binaryAttribute == null)
950                                 throw new ArgumentNullException ("binaryAttribute");
951
952                         SetCustomAttribute (new CustomAttributeBuilder (con, binaryAttribute));
953                 }
954
955                 private Exception not_supported () {
956                         // Strange message but this is what MS.NET prints...
957                         return new NotSupportedException ("The invoked member is not supported in a dynamic module.");
958                 }
959
960                 private void check_name_and_filename (string name, string fileName,
961                                                                                           bool fileNeedsToExists) {
962                         if (name == null)
963                                 throw new ArgumentNullException ("name");
964                         if (fileName == null)
965                                 throw new ArgumentNullException ("fileName");
966                         if (name.Length == 0)
967                                 throw new ArgumentException ("Empty name is not legal.", "name");
968                         if (fileName.Length == 0)
969                                 throw new ArgumentException ("Empty file name is not legal.", "fileName");
970                         if (Path.GetFileName (fileName) != fileName)
971                                 throw new ArgumentException ("fileName '" + fileName + "' must not include a path.", "fileName");
972
973                         // Resource files are created/searched under the assembly storage
974                         // directory
975                         string fullFileName = fileName;
976                         if (dir != null)
977                                 fullFileName = Path.Combine (dir, fileName);
978
979                         if (fileNeedsToExists && !File.Exists (fullFileName))
980                                 throw new FileNotFoundException ("Could not find file '" + fileName + "'");
981
982                         if (resources != null) {
983                                 for (int i = 0; i < resources.Length; ++i) {
984                                         if (resources [i].filename == fullFileName)
985                                                 throw new ArgumentException ("Duplicate file name '" + fileName + "'");
986                                         if (resources [i].name == name)
987                                                 throw new ArgumentException ("Duplicate name '" + name + "'");
988                                 }
989                         }
990
991                         if (modules != null) {
992                                 for (int i = 0; i < modules.Length; ++i) {
993                                         // Use fileName instead of fullFileName here
994                                         if (!modules [i].IsTransient () && (modules [i].FileName == fileName))
995                                                 throw new ArgumentException ("Duplicate file name '" + fileName + "'");
996                                         if (modules [i].Name == name)
997                                                 throw new ArgumentException ("Duplicate name '" + name + "'");
998                                 }
999                         }
1000                 }
1001
1002                 private String create_assembly_version (String version) {
1003                         String[] parts = version.Split ('.');
1004                         int[] ver = new int [4] { 0, 0, 0, 0 };
1005
1006                         if ((parts.Length < 0) || (parts.Length > 4))
1007                                 throw new ArgumentException ("The version specified '" + version + "' is invalid");
1008
1009                         for (int i = 0; i < parts.Length; ++i) {
1010                                 if (parts [i] == "*") {
1011                                         DateTime now = DateTime.Now;
1012
1013                                         if (i == 2) {
1014                                                 ver [2] = (now - new DateTime (2000, 1, 1)).Days;
1015                                                 if (parts.Length == 3)
1016                                                         ver [3] = (now.Second + (now.Minute * 60) + (now.Hour * 3600)) / 2;
1017                                         }
1018                                         else
1019                                                 if (i == 3)
1020                                                         ver [3] = (now.Second + (now.Minute * 60) + (now.Hour * 3600)) / 2;
1021                                         else
1022                                                 throw new ArgumentException ("The version specified '" + version + "' is invalid");
1023                                 }
1024                                 else {
1025                                         try {
1026                                                 ver [i] = Int32.Parse (parts [i]);
1027                                         }
1028                                         catch (FormatException) {
1029                                                 throw new ArgumentException ("The version specified '" + version + "' is invalid");
1030                                         }
1031                                 }
1032                         }
1033
1034                         return ver [0] + "." + ver [1] + "." + ver [2] + "." + ver [3];
1035                 }
1036
1037                 private string GetCultureString (string str)
1038                 {
1039                         return (str == "neutral" ? String.Empty : str);
1040                 }
1041
1042                 internal override AssemblyName UnprotectedGetName ()
1043                 {
1044                         AssemblyName an = base.UnprotectedGetName ();
1045                         if (sn != null) {
1046                                 an.SetPublicKey (sn.PublicKey);
1047                                 an.SetPublicKeyToken (sn.PublicKeyToken);
1048                         }
1049                         return an;
1050                 }
1051
1052                 /*Warning, @typeArguments must be a mscorlib internal array. So make a copy before passing it in*/
1053                 internal Type MakeGenericType (Type gtd, Type[] typeArguments)
1054                 {
1055                         return new MonoGenericClass (gtd, typeArguments);
1056                 }
1057
1058                 void _AssemblyBuilder.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
1059                 {
1060                         throw new NotImplementedException ();
1061                 }
1062
1063                 void _AssemblyBuilder.GetTypeInfo (uint iTInfo, uint lcid, IntPtr ppTInfo)
1064                 {
1065                         throw new NotImplementedException ();
1066                 }
1067
1068                 void _AssemblyBuilder.GetTypeInfoCount (out uint pcTInfo)
1069                 {
1070                         throw new NotImplementedException ();
1071                 }
1072
1073                 void _AssemblyBuilder.Invoke (uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
1074                 {
1075                         throw new NotImplementedException ();
1076                 }
1077
1078 #if NET_4_0 || MOONLIGHT || MOBILE
1079                 public override Type GetType (string name, bool throwOnError, bool ignoreCase)
1080                 {
1081                         if (name == null)
1082                                 throw new ArgumentNullException (name);
1083                         if (name.Length == 0)
1084                         throw new ArgumentException ("name", "Name cannot be empty");
1085
1086                         var res = InternalGetType (null, name, throwOnError, ignoreCase);
1087                         if (res is TypeBuilder) {
1088                                 if (throwOnError)
1089                                         throw new TypeLoadException (string.Format ("Could not load type '{0}' from assembly '{1}'", name, this.name));
1090                                 return null;
1091                         }
1092                         return res;
1093                 }
1094
1095                 public override Module GetModule (String name)
1096                 {
1097                         if (name == null)
1098                                 throw new ArgumentNullException ("name");
1099                         if (name.Length == 0)
1100                                 throw new ArgumentException ("Name can't be empty");
1101
1102                         if (modules == null)
1103                                 return null;
1104
1105                         foreach (Module module in modules) {
1106                                 if (module.ScopeName == name)
1107                                         return module;
1108                         }
1109
1110                         return null;
1111                 }
1112
1113                 public override Module[] GetModules (bool getResourceModules)
1114                 {
1115                         Module[] modules = GetModulesInternal ();
1116
1117                         if (!getResourceModules) {
1118                                 var result = new List<Module> (modules.Length);
1119                                 foreach (Module m in modules)
1120                                         if (!m.IsResource ())
1121                                                 result.Add (m);
1122                                 return result.ToArray ();
1123                         }
1124                         return modules;
1125                 }
1126
1127                 public override AssemblyName GetName (bool copiedName)
1128                 {
1129                         return base.GetName (copiedName);
1130                 }
1131
1132                 [MonoTODO ("This always returns an empty array")]
1133                 public override AssemblyName[] GetReferencedAssemblies () {
1134                         return GetReferencedAssemblies (this);
1135                 }
1136
1137                 public override Module[] GetLoadedModules (bool getResourceModules)
1138                 {
1139                         return GetModules (getResourceModules);
1140                 }
1141
1142                 //FIXME MS has issues loading satelite assemblies from SRE
1143                 public override Assembly GetSatelliteAssembly (CultureInfo culture)
1144                 {
1145                         return GetSatelliteAssembly (culture, null, true);
1146                 }
1147
1148                 //FIXME MS has issues loading satelite assemblies from SRE
1149                 public override Assembly GetSatelliteAssembly (CultureInfo culture, Version version)
1150                 {
1151                         return GetSatelliteAssembly (culture, version, true);
1152                 }
1153
1154                 public override Module ManifestModule {
1155                         get {
1156                                 return GetManifestModule ();
1157                         }
1158                 }
1159
1160                 public override bool GlobalAssemblyCache {
1161                         get {
1162                                 return false;
1163                         }
1164                 }
1165
1166                 public override bool IsDynamic {
1167                         get { return true; }
1168                 }
1169
1170                 public override bool Equals (object obj)
1171                 {
1172                         return base.Equals (obj);
1173                 }
1174
1175                 public override int GetHashCode ()
1176                 {
1177                         return base.GetHashCode ();
1178                 }
1179
1180                 public override bool IsDefined (Type attributeType, bool inherit)
1181                 {
1182                         return base.IsDefined (attributeType, inherit);
1183                 }
1184
1185                 public override object[] GetCustomAttributes (bool inherit)
1186                 {
1187                         return base.GetCustomAttributes (inherit);
1188                 }
1189
1190                 public override object[] GetCustomAttributes (Type attributeType, bool inherit)
1191                 {
1192                         return base.GetCustomAttributes (attributeType, inherit);
1193                 }
1194
1195                 public override string FullName {
1196                         get { return base.FullName; }
1197                 }
1198 #endif
1199         }
1200 }
1201 #endif