New tests.
[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 using System;
34 using System.Reflection;
35 using System.Resources;
36 using System.IO;
37 using System.Security.Policy;
38 using System.Runtime.Serialization;
39 using System.Globalization;
40 using System.Runtime.CompilerServices;
41 using System.Collections;
42 using System.Runtime.InteropServices;
43 using System.Security;
44 using System.Security.Cryptography;
45 using System.Security.Permissions;
46
47 using Mono.Security;
48 using Mono.Security.Cryptography;
49
50 namespace System.Reflection.Emit
51 {
52         internal enum NativeResourceType
53         {
54                 None,
55                 Unmanaged,
56                 Assembly,
57                 Explicit
58         }
59
60         internal struct RefEmitPermissionSet {
61                 public SecurityAction action;
62                 public string pset;
63
64                 public RefEmitPermissionSet (SecurityAction action, string pset) {
65                         this.action = action;
66                         this.pset = pset;
67                 }
68         }
69
70         internal struct MonoResource {
71                 public byte[] data;
72                 public string name;
73                 public string filename;
74                 public ResourceAttributes attrs;
75                 public int offset;
76                 public Stream stream;
77         }
78
79         internal struct MonoWin32Resource {
80                 public int res_type;
81                 public int res_id;
82                 public int lang_id;
83                 public byte[] data;
84
85                 public MonoWin32Resource (int res_type, int res_id, int lang_id, byte[] data) {
86                         this.res_type = res_type;
87                         this.res_id = res_id;
88                         this.lang_id = lang_id;
89                         this.data = data;
90                 }
91         }
92
93 #if NET_2_0
94         [ComVisible (true)]
95         [ComDefaultInterface (typeof (_AssemblyBuilder))]
96 #endif
97         [ClassInterface (ClassInterfaceType.None)]
98         public sealed class AssemblyBuilder : Assembly, _AssemblyBuilder {
99                 #region Sync with object-internals.h
100                 private UIntPtr dynamic_assembly; /* GC-tracked */
101                 private MethodInfo entry_point;
102                 private ModuleBuilder[] modules;
103                 private string name;
104                 private string dir;
105                 private CustomAttributeBuilder[] cattrs;
106                 private MonoResource[] resources;
107                 byte[] public_key;
108                 string version;
109                 string culture;
110                 uint algid;
111                 uint flags;
112                 PEFileKinds pekind = PEFileKinds.Dll;
113                 bool delay_sign;
114                 uint access;
115                 Module[] loaded_modules;
116                 MonoWin32Resource[] win32_resources;
117                 private RefEmitPermissionSet[] permissions_minimum;
118                 private RefEmitPermissionSet[] permissions_optional;
119                 private RefEmitPermissionSet[] permissions_refused;
120                 PortableExecutableKinds peKind;
121                 ImageFileMachine machine;
122                 bool corlib_internal;
123                 Type[] type_forwarders;
124                 #endregion
125                 internal Type corlib_object_type = typeof (System.Object);
126                 internal Type corlib_value_type = typeof (System.ValueType);
127                 internal Type corlib_enum_type = typeof (System.Enum);
128                 internal Type corlib_void_type = typeof (void);
129                 ArrayList resource_writers = null;
130                 Win32VersionResource version_res;
131                 bool created;
132                 bool is_module_only;
133                 private Mono.Security.StrongName sn;
134                 NativeResourceType native_resource;
135                 readonly bool is_compiler_context;
136                 string versioninfo_culture;
137
138                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
139                 private static extern void basic_init (AssemblyBuilder ab);
140
141                 /* Keep this in sync with codegen.cs in mcs */
142                 private const AssemblyBuilderAccess COMPILER_ACCESS = (AssemblyBuilderAccess) 0x800;
143
144                 internal AssemblyBuilder (AssemblyName n, string directory, AssemblyBuilderAccess access, bool corlib_internal)
145                 {
146 #if BOOTSTRAP_WITH_OLDLIB
147                         is_compiler_context = true;
148 #else
149                         is_compiler_context = (access & COMPILER_ACCESS) != 0;
150 #endif
151
152                         // remove Mono specific flag to allow enum check to pass
153                         access &= ~COMPILER_ACCESS;
154
155 #if NET_2_0
156                         if (!Enum.IsDefined (typeof (AssemblyBuilderAccess), access))
157                                 throw new ArgumentException (string.Format (CultureInfo.InvariantCulture,
158                                         "Argument value {0} is not valid.", (int) access),
159                                         "access");
160 #endif
161
162                         name = n.Name;
163                         this.access = (uint)access;
164                         flags = (uint) n.Flags;
165
166                         // don't call GetCurrentDirectory for Run-only builders (CAS may not like that)
167                         if (IsSave && (directory == null || directory.Length == 0)) {
168                                 dir = Directory.GetCurrentDirectory ();
169                         } else {
170                                 dir = directory;
171                         }
172
173                         /* Set defaults from n */
174                         if (n.CultureInfo != null) {
175                                 culture = n.CultureInfo.Name;
176                                 versioninfo_culture = n.CultureInfo.Name;
177                         }
178                         Version v = n.Version;
179                         if (v != null) {
180                                 version = v.ToString ();
181                         }
182
183                         if (n.KeyPair != null) {
184                                 // full keypair is available (for signing)
185                                 sn = n.KeyPair.StrongName ();
186                         }
187                         else {
188                                 // public key is available (for delay-signing)
189                                 byte[] pk = n.GetPublicKey ();
190                                 if ((pk != null) && (pk.Length > 0)) {
191                                         sn = new Mono.Security.StrongName (pk);
192                                 }
193                         }
194
195                         this.corlib_internal = corlib_internal;
196
197                         basic_init (this);
198                 }
199
200                 public override string CodeBase {
201                         get {
202                                 throw not_supported ();
203                         }
204                 }
205                 
206                 public override MethodInfo EntryPoint {
207                         get {
208                                 return entry_point;
209                         }
210                 }
211
212                 public override string Location {
213                         get {
214                                 throw not_supported ();
215                         }
216                 }
217
218 #if NET_1_1
219                 /* This is to keep signature compatibility with MS.NET */
220                 public override string ImageRuntimeVersion {
221                         get {
222                                 return base.ImageRuntimeVersion;
223                         }
224                 }
225 #endif
226
227 #if NET_2_0
228                 [MonoTODO]
229                 public override bool ReflectionOnly {
230                         get { return base.ReflectionOnly; }
231                 }
232 #endif
233
234                 public void AddResourceFile (string name, string fileName)
235                 {
236                         AddResourceFile (name, fileName, ResourceAttributes.Public);
237                 }
238
239                 public void AddResourceFile (string name, string fileName, ResourceAttributes attribute)
240                 {
241                         AddResourceFile (name, fileName, attribute, true);
242                 }
243
244                 private void AddResourceFile (string name, string fileName, ResourceAttributes attribute, bool fileNeedsToExists)
245                 {
246                         check_name_and_filename (name, fileName, fileNeedsToExists);
247
248                         // Resource files are created/searched under the assembly storage
249                         // directory
250                         if (dir != null)
251                                 fileName = Path.Combine (dir, fileName);
252
253                         if (resources != null) {
254                                 MonoResource[] new_r = new MonoResource [resources.Length + 1];
255                                 System.Array.Copy(resources, new_r, resources.Length);
256                                 resources = new_r;
257                         } else {
258                                 resources = new MonoResource [1];
259                         }
260                         int p = resources.Length - 1;
261                         resources [p].name = name;
262                         resources [p].filename = fileName;
263                         resources [p].attrs = attribute;
264                 }
265
266                 /// <summary>
267                 /// Don't change the method name and parameters order. It is used by mcs 
268                 /// </summary>
269                 internal void AddPermissionRequests (PermissionSet required, PermissionSet optional, PermissionSet refused)
270                 {
271                         if (created)
272                                 throw new InvalidOperationException ("Assembly was already saved.");
273
274                         // required for base Assembly class (so the permissions
275                         // can be used even if the assembly isn't saved to disk)
276                         _minimum = required;
277                         _optional = optional;
278                         _refuse = refused;
279
280                         // required to reuse AddDeclarativeSecurity support 
281                         // already present in the runtime
282                         if (required != null) {
283                                 permissions_minimum = new RefEmitPermissionSet [1];
284                                 permissions_minimum [0] = new RefEmitPermissionSet (
285                                         SecurityAction.RequestMinimum, required.ToXml ().ToString ());
286                         }
287                         if (optional != null) {
288                                 permissions_optional = new RefEmitPermissionSet [1];
289                                 permissions_optional [0] = new RefEmitPermissionSet (
290                                         SecurityAction.RequestOptional, optional.ToXml ().ToString ());
291                         }
292                         if (refused != null) {
293                                 permissions_refused = new RefEmitPermissionSet [1];
294                                 permissions_refused [0] = new RefEmitPermissionSet (
295                                         SecurityAction.RequestRefuse, refused.ToXml ().ToString ());
296                         }
297                 }
298
299                 internal void EmbedResourceFile (string name, string fileName)
300                 {
301                         EmbedResourceFile (name, fileName, ResourceAttributes.Public);
302                 }
303
304                 internal void EmbedResourceFile (string name, string fileName, ResourceAttributes attribute)
305                 {
306                         if (resources != null) {
307                                 MonoResource[] new_r = new MonoResource [resources.Length + 1];
308                                 System.Array.Copy(resources, new_r, resources.Length);
309                                 resources = new_r;
310                         } else {
311                                 resources = new MonoResource [1];
312                         }
313                         int p = resources.Length - 1;
314                         resources [p].name = name;
315                         resources [p].attrs = attribute;
316                         try {
317                                 FileStream s = new FileStream (fileName, FileMode.Open, FileAccess.Read);
318                                 long len = s.Length;
319                                 resources [p].data = new byte [len];
320                                 s.Read (resources [p].data, 0, (int)len);
321                                 s.Close ();
322                         } catch {
323                                 /* do something */
324                         }
325                 }
326
327                 internal void EmbedResource (string name, byte[] blob, ResourceAttributes attribute)
328                 {
329                         if (resources != null) {
330                                 MonoResource[] new_r = new MonoResource [resources.Length + 1];
331                                 System.Array.Copy(resources, new_r, resources.Length);
332                                 resources = new_r;
333                         } else {
334                                 resources = new MonoResource [1];
335                         }
336                         int p = resources.Length - 1;
337                         resources [p].name = name;
338                         resources [p].attrs = attribute;
339                         resources [p].data = blob;
340                 }
341
342 #if NET_2_0
343                 internal void AddTypeForwarder (Type t) {
344                         if (t == null)
345                                 throw new ArgumentNullException ("t");
346
347                         if (type_forwarders == null) {
348                                 type_forwarders = new Type [1] { t };
349                         } else {
350                                 Type[] arr = new Type [type_forwarders.Length + 1];
351                                 Array.Copy (type_forwarders, arr, type_forwarders.Length);
352                                 type_forwarders = arr;
353                         }
354                 }
355 #endif
356
357                 public ModuleBuilder DefineDynamicModule (string name)
358                 {
359                         return DefineDynamicModule (name, name, false, true);
360                 }
361
362                 public ModuleBuilder DefineDynamicModule (string name, bool emitSymbolInfo)
363                 {
364                         return DefineDynamicModule (name, name, emitSymbolInfo, true);
365                 }
366
367                 public ModuleBuilder DefineDynamicModule(string name, string fileName)
368                 {
369                         return DefineDynamicModule (name, fileName, false, false);
370                 }
371
372                 public ModuleBuilder DefineDynamicModule (string name, string fileName,
373                                                           bool emitSymbolInfo)
374                 {
375                         return DefineDynamicModule (name, fileName, emitSymbolInfo, false);
376                 }
377
378                 private ModuleBuilder DefineDynamicModule (string name, string fileName, bool emitSymbolInfo, bool transient)
379                 {
380                         check_name_and_filename (name, fileName, false);
381
382                         if (!transient) {
383                                 if (Path.GetExtension (fileName) == String.Empty)
384                                         throw new ArgumentException ("Module file name '" + fileName + "' must have file extension.");
385                                 if (!IsSave)
386                                         throw new NotSupportedException ("Persistable modules are not supported in a dynamic assembly created with AssemblyBuilderAccess.Run");
387                                 if (created)
388                                         throw new InvalidOperationException ("Assembly was already saved.");
389                         }
390
391                         ModuleBuilder r = new ModuleBuilder (this, name, fileName, emitSymbolInfo, transient);
392
393                         if ((modules != null) && is_module_only)
394                                 throw new InvalidOperationException ("A module-only assembly can only contain one module.");
395
396                         if (modules != null) {
397                                 ModuleBuilder[] new_modules = new ModuleBuilder [modules.Length + 1];
398                                 System.Array.Copy(modules, new_modules, modules.Length);
399                                 modules = new_modules;
400                         } else {
401                                 modules = new ModuleBuilder [1];
402                         }
403                         modules [modules.Length - 1] = r;
404                         return r;
405                 }
406
407                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
408                 private extern Module InternalAddModule (string fileName);
409
410                 /*
411                  * Mono extension to support /addmodule in mcs.
412                  */
413                 internal Module AddModule (string fileName)
414                 {
415                         if (fileName == null)
416                                 throw new ArgumentNullException (fileName);
417
418                         Module m = InternalAddModule (fileName);
419
420                         if (loaded_modules != null) {
421                                 Module[] new_modules = new Module [loaded_modules.Length + 1];
422                                 System.Array.Copy (loaded_modules, new_modules, loaded_modules.Length);
423                                 loaded_modules = new_modules;
424                         } else {
425                                 loaded_modules = new Module [1];
426                         }
427                         loaded_modules [loaded_modules.Length - 1] = m;
428
429                         return m;
430                 }
431
432                 public IResourceWriter DefineResource (string name, string description, string fileName)
433                 {
434                         return DefineResource (name, description, fileName, ResourceAttributes.Public);
435                 }
436
437                 public IResourceWriter DefineResource (string name, string description,
438                                                        string fileName, ResourceAttributes attribute)
439                 {
440                         IResourceWriter writer;
441
442                         // description seems to be ignored
443                         AddResourceFile (name, fileName, attribute, false);
444                         writer = new ResourceWriter (fileName);
445                         if (resource_writers == null)
446                                 resource_writers = new ArrayList ();
447                         resource_writers.Add (writer);
448                         return writer;
449                 }
450
451                 private void AddUnmanagedResource (Win32Resource res) {
452                         MemoryStream ms = new MemoryStream ();
453                         res.WriteTo (ms);
454
455                         if (win32_resources != null) {
456                                 MonoWin32Resource[] new_res = new MonoWin32Resource [win32_resources.Length + 1];
457                                 System.Array.Copy (win32_resources, new_res, win32_resources.Length);
458                                 win32_resources = new_res;
459                         }
460                         else
461                                 win32_resources = new MonoWin32Resource [1];
462
463                         win32_resources [win32_resources.Length - 1] = new MonoWin32Resource (res.Type.Id, res.Name.Id, res.Language, ms.ToArray ());
464                 }
465
466                 [MonoTODO ("Not currently implemenented")]
467                 public void DefineUnmanagedResource (byte[] resource)
468                 {
469                         if (resource == null)
470                                 throw new ArgumentNullException ("resource");
471                         if (native_resource != NativeResourceType.None)
472                                 throw new ArgumentException ("Native resource has already been defined.");
473
474                         // avoid definition of more than one unmanaged resource
475                         native_resource = NativeResourceType.Unmanaged;
476
477                         /*
478                          * The format of the argument byte array is not documented
479                          * so this method is impossible to implement.
480                          */
481
482                         throw new NotImplementedException ();
483                 }
484
485                 public void DefineUnmanagedResource (string resourceFileName)
486                 {
487                         if (resourceFileName == null)
488                                 throw new ArgumentNullException ("resourceFileName");
489                         if (resourceFileName.Length == 0)
490                                 throw new ArgumentException ("resourceFileName");
491                         if (!File.Exists (resourceFileName) || Directory.Exists (resourceFileName))
492                                 throw new FileNotFoundException ("File '" + resourceFileName + "' does not exists or is a directory.");
493                         if (native_resource != NativeResourceType.None)
494                                 throw new ArgumentException ("Native resource has already been defined.");
495
496                         // avoid definition of more than one unmanaged resource
497                         native_resource = NativeResourceType.Unmanaged;
498
499                         using (FileStream fs = new FileStream (resourceFileName, FileMode.Open, FileAccess.Read)) {
500                                 Win32ResFileReader reader = new Win32ResFileReader (fs);
501
502                                 foreach (Win32EncodedResource res in reader.ReadResources ()) {
503                                         if (res.Name.IsName || res.Type.IsName)
504                                                 throw new InvalidOperationException ("resource files with named resources or non-default resource types are not supported.");
505
506                                         AddUnmanagedResource (res);
507                                 }
508                         }
509                 }
510
511                 public void DefineVersionInfoResource ()
512                 {
513                         if (native_resource != NativeResourceType.None)
514                                 throw new ArgumentException ("Native resource has already been defined.");
515
516                         // avoid definition of more than one unmanaged resource
517                         native_resource = NativeResourceType.Assembly;
518
519                         version_res = new Win32VersionResource (1, 0, IsCompilerContext);
520                 }
521
522                 public void DefineVersionInfoResource (string product, string productVersion,
523                                                        string company, string copyright, string trademark)
524                 {
525                         if (native_resource != NativeResourceType.None)
526                                 throw new ArgumentException ("Native resource has already been defined.");
527
528                         // avoid definition of more than one unmanaged resource
529                         native_resource = NativeResourceType.Explicit;
530
531                         /*
532                          * We can only create the resource later, when the file name and
533                          * the binary version is known.
534                          */
535
536                         version_res = new Win32VersionResource (1, 0, false);
537                         version_res.ProductName = product != null ? product : " ";
538                         version_res.ProductVersion = productVersion != null ? productVersion : " ";
539                         version_res.CompanyName = company != null ? company : " ";
540                         version_res.LegalCopyright = copyright != null ? copyright : " ";
541                         version_res.LegalTrademarks = trademark != null ? trademark : " ";
542                 }
543
544                 /* 
545                  * Mono extension to support /win32icon in mcs
546                  */
547                 internal void DefineIconResource (string iconFileName)
548                 {
549                         if (iconFileName == null)
550                                 throw new ArgumentNullException ("iconFileName");
551                         if (iconFileName.Length == 0)
552                                 throw new ArgumentException ("iconFileName");
553                         if (!File.Exists (iconFileName) || Directory.Exists (iconFileName))
554                                 throw new FileNotFoundException ("File '" + iconFileName + "' does not exists or is a directory.");
555
556                         using (FileStream fs = new FileStream (iconFileName, FileMode.Open, FileAccess.Read)) {
557                                 Win32IconFileReader reader = new Win32IconFileReader (fs);
558                                 
559                                 ICONDIRENTRY[] entries = reader.ReadIcons ();
560
561                                 Win32IconResource[] icons = new Win32IconResource [entries.Length];
562                                 for (int i = 0; i < entries.Length; ++i) {
563                                         icons [i] = new Win32IconResource (i + 1, 0, entries [i]);
564                                         AddUnmanagedResource (icons [i]);
565                                 }
566
567                                 Win32GroupIconResource group = new Win32GroupIconResource (1, 0, icons);
568                                 AddUnmanagedResource (group);
569                         }
570                 }
571
572                 private void DefineVersionInfoResourceImpl (string fileName)
573                 {
574                         if (versioninfo_culture != null)
575                                 version_res.FileLanguage = new CultureInfo (versioninfo_culture).LCID;
576                         version_res.Version = version == null ? "0.0.0.0" : version;
577
578                         if (cattrs != null) {
579                                 switch (native_resource) {
580                                 case NativeResourceType.Assembly:
581                                         foreach (CustomAttributeBuilder cb in cattrs) {
582                                                 string attrname = cb.Ctor.ReflectedType.FullName;
583
584                                                 if (attrname == "System.Reflection.AssemblyProductAttribute")
585                                                         version_res.ProductName = cb.string_arg ();
586                                                 else if (attrname == "System.Reflection.AssemblyCompanyAttribute")
587                                                         version_res.CompanyName = cb.string_arg ();
588                                                 else if (attrname == "System.Reflection.AssemblyCopyrightAttribute")
589                                                         version_res.LegalCopyright = cb.string_arg ();
590                                                 else if (attrname == "System.Reflection.AssemblyTrademarkAttribute")
591                                                         version_res.LegalTrademarks = cb.string_arg ();
592                                                 else if (attrname == "System.Reflection.AssemblyCultureAttribute") {
593                                                         if (!IsCompilerContext)
594                                                                 version_res.FileLanguage = new CultureInfo (cb.string_arg ()).LCID;
595                                                 } else if (attrname == "System.Reflection.AssemblyFileVersionAttribute") {
596                                                         string fileversion = cb.string_arg ();
597                                                         if (!IsCompilerContext || fileversion != null && fileversion.Length != 0)
598                                                                 version_res.FileVersion = fileversion;
599                                                 } else if (attrname == "System.Reflection.AssemblyInformationalVersionAttribute")
600                                                         version_res.ProductVersion = cb.string_arg ();
601                                                 else if (attrname == "System.Reflection.AssemblyTitleAttribute")
602                                                         version_res.FileDescription = cb.string_arg ();
603                                                 else if (attrname == "System.Reflection.AssemblyDescriptionAttribute")
604                                                         version_res.Comments = cb.string_arg ();
605                                         }
606                                         break;
607                                 case NativeResourceType.Explicit:
608                                         foreach (CustomAttributeBuilder cb in cattrs) {
609                                                 string attrname = cb.Ctor.ReflectedType.FullName;
610
611                                                 if (attrname == "System.Reflection.AssemblyCultureAttribute") {
612                                                         if (!IsCompilerContext)
613                                                                 version_res.FileLanguage = new CultureInfo (cb.string_arg ()).LCID;
614                                                 } else if (attrname == "System.Reflection.AssemblyDescriptionAttribute")
615                                                         version_res.Comments = cb.string_arg ();
616                                         }
617                                         break;
618                                 }
619                         }
620
621                         version_res.OriginalFilename = fileName;
622
623                         if (IsCompilerContext) {
624                                 version_res.InternalName = fileName;
625                                 if (version_res.ProductVersion.Trim ().Length == 0)
626                                         version_res.ProductVersion = version_res.FileVersion;
627                         } else {
628                                 version_res.InternalName = Path.GetFileNameWithoutExtension (fileName);
629                         }
630
631                         AddUnmanagedResource (version_res);
632                 }
633
634                 public ModuleBuilder GetDynamicModule (string name)
635                 {
636                         if (name == null)
637                                 throw new ArgumentNullException ("name");
638                         if (name.Length == 0)
639                                 throw new ArgumentException ("Empty name is not legal.", "name");
640
641                         if (modules != null)
642                                 for (int i = 0; i < modules.Length; ++i)
643                                         if (modules [i].name == name)
644                                                 return modules [i];
645                         return null;
646                 }
647
648                 public override Type[] GetExportedTypes ()
649                 {
650                         throw not_supported ();
651                 }
652
653                 public override FileStream GetFile (string name)
654                 {
655                         throw not_supported ();
656                 }
657
658                 public override FileStream[] GetFiles(bool getResourceModules) {
659                         throw not_supported ();
660                 }
661
662                 internal override Module[] GetModulesInternal () {
663                         if (modules == null)
664                                 return new Module [0];
665                         else
666                                 return (Module[])modules.Clone ();
667                 }
668
669                 internal override Type[] GetTypes (bool exportedOnly) {
670                         Type[] res = null;
671                         if (modules != null) {
672                                 for (int i = 0; i < modules.Length; ++i) {
673                                         Type[] types = modules [i].GetTypes ();
674                                         if (res == null)
675                                                 res = types;
676                                         else {
677                                                 Type[] tmp = new Type [res.Length + types.Length];
678                                                 Array.Copy (res, 0, tmp, 0, res.Length);
679                                                 Array.Copy (types, 0, tmp, res.Length, types.Length);
680                                         }
681                                 }
682                         }
683                         if (loaded_modules != null) {
684                                 for (int i = 0; i < loaded_modules.Length; ++i) {
685                                         Type[] types = loaded_modules [i].GetTypes ();
686                                         if (res == null)
687                                                 res = types;
688                                         else {
689                                                 Type[] tmp = new Type [res.Length + types.Length];
690                                                 Array.Copy (res, 0, tmp, 0, res.Length);
691                                                 Array.Copy (types, 0, tmp, res.Length, types.Length);
692                                         }
693                                 }
694                         }
695
696                         return res == null ? Type.EmptyTypes : res;
697                 }
698
699                 public override ManifestResourceInfo GetManifestResourceInfo(string resourceName) {
700                         throw not_supported ();
701                 }
702
703                 public override string[] GetManifestResourceNames() {
704                         throw not_supported ();
705                 }
706
707                 public override Stream GetManifestResourceStream(string name) {
708                         throw not_supported ();
709                 }
710                 public override Stream GetManifestResourceStream(Type type, string name) {
711                         throw not_supported ();
712                 }
713
714                 /*
715                  * This is set when the the AssemblyBuilder is created by (g)mcs
716                  * or vbnc.
717                  */
718                 internal bool IsCompilerContext
719                 {
720                         get { return is_compiler_context; }
721                 }
722
723                 internal bool IsSave {
724                         get {
725                                 return access != (uint)AssemblyBuilderAccess.Run;
726                         }
727                 }
728
729                 internal string AssemblyDir {
730                         get {
731                                 return dir;
732                         }
733                 }
734
735                 /*
736                  * Mono extension. If this is set, the assembly can only contain one
737                  * module, access should be Save, and the saved image will not contain an
738                  * assembly manifest.
739                  */
740                 internal bool IsModuleOnly {
741                         get {
742                                 return is_module_only;
743                         }
744                         set {
745                                 is_module_only = value;
746                         }
747                 }
748
749 #if NET_2_0 || BOOTSTRAP_NET_2_0
750                 ModuleBuilder manifest_module;
751
752                 //
753                 // MS.NET seems to return a ModuleBuilder when GetManifestModule () is called
754                 // on an assemblybuilder.
755                 //
756                 internal override Module GetManifestModule () {
757                         if (manifest_module == null)
758                                 manifest_module = DefineDynamicModule ("Default Dynamic Module");
759                         return manifest_module;
760                 }
761 #endif
762
763 #if NET_2_0
764                 public 
765 #else
766                 internal
767 #endif
768                 void Save (string assemblyFileName, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
769                 {
770                         this.peKind = portableExecutableKind;
771                         this.machine = imageFileMachine;
772
773                         if (resource_writers != null) {
774                                 foreach (IResourceWriter writer in resource_writers) {
775                                         writer.Generate ();
776                                         writer.Close ();
777                                 }
778                         }
779
780                         // Create a main module if not already created
781                         ModuleBuilder mainModule = null;
782                         if (modules != null) {
783                                 foreach (ModuleBuilder module in modules)
784                                         if (module.FullyQualifiedName == assemblyFileName)
785                                                 mainModule = module;
786                         }
787                         if (mainModule == null)
788                                 mainModule = DefineDynamicModule ("RefEmit_OnDiskManifestModule", assemblyFileName);
789
790                         if (!is_module_only)
791                                 mainModule.IsMain = true;
792
793                         /* 
794                          * Create a new entry point if the one specified
795                          * by the user is in another module.
796                          */
797                         if ((entry_point != null) && entry_point.DeclaringType.Module != mainModule) {
798                                 Type[] paramTypes;
799                                 if (entry_point.GetParameters ().Length == 1)
800                                         paramTypes = new Type [] { typeof (string) };
801                                 else
802                                         paramTypes = Type.EmptyTypes;
803
804                                 MethodBuilder mb = mainModule.DefineGlobalMethod ("__EntryPoint$", MethodAttributes.Static|MethodAttributes.PrivateScope, entry_point.ReturnType, paramTypes);
805                                 ILGenerator ilgen = mb.GetILGenerator ();
806                                 if (paramTypes.Length == 1)
807                                         ilgen.Emit (OpCodes.Ldarg_0);
808                                 ilgen.Emit (OpCodes.Tailcall);
809                                 ilgen.Emit (OpCodes.Call, entry_point);
810                                 ilgen.Emit (OpCodes.Ret);
811
812                                 entry_point = mb;
813                         }
814
815                         if (version_res != null)
816                                 DefineVersionInfoResourceImpl (assemblyFileName);
817
818                         if (sn != null) {
819                                 // runtime needs to value to embed it into the assembly
820                                 public_key = sn.PublicKey;
821                         }
822
823                         foreach (ModuleBuilder module in modules)
824                                 if (module != mainModule)
825                                         module.Save ();
826
827                         // Write out the main module at the end, because it needs to
828                         // contain the hash of the other modules
829                         mainModule.Save ();
830
831                         if ((sn != null) && (sn.CanSign)) {
832                                 sn.Sign (System.IO.Path.Combine (this.AssemblyDir, assemblyFileName));
833                         }
834
835                         created = true;
836                 }
837
838                 public void Save (string assemblyFileName)
839                 {
840                         Save (assemblyFileName, PortableExecutableKinds.ILOnly, ImageFileMachine.I386);
841                 }
842
843                 public void SetEntryPoint (MethodInfo entryMethod)
844                 {
845                         SetEntryPoint (entryMethod, PEFileKinds.ConsoleApplication);
846                 }
847
848                 public void SetEntryPoint (MethodInfo entryMethod, PEFileKinds fileKind)
849                 {
850                         if (entryMethod == null)
851                                 throw new ArgumentNullException ("entryMethod");
852                         if (entryMethod.DeclaringType.Assembly != this)
853                                 throw new InvalidOperationException ("Entry method is not defined in the same assembly.");
854
855                         entry_point = entryMethod;
856                         pekind = fileKind;
857                 }
858
859                 public void SetCustomAttribute( CustomAttributeBuilder customBuilder) 
860                 {
861                         if (customBuilder == null)
862                                 throw new ArgumentNullException ("customBuilder");
863
864                         if (IsCompilerContext) {
865                                 string attrname = customBuilder.Ctor.ReflectedType.FullName;
866                                 byte [] data;
867                                 int pos;
868
869                                 if (attrname == "System.Reflection.AssemblyVersionAttribute") {
870                                         version = create_assembly_version (customBuilder.string_arg ());
871                                         return;
872                                 } else if (attrname == "System.Reflection.AssemblyCultureAttribute") {
873                                         culture = GetCultureString (customBuilder.string_arg ());
874                                 } else if (attrname == "System.Reflection.AssemblyAlgorithmIdAttribute") {
875                                         data = customBuilder.Data;
876                                         pos = 2;
877                                         algid = (uint) data [pos];
878                                         algid |= ((uint) data [pos + 1]) << 8;
879                                         algid |= ((uint) data [pos + 2]) << 16;
880                                         algid |= ((uint) data [pos + 3]) << 24;
881                                 } else if (attrname == "System.Reflection.AssemblyFlagsAttribute") {
882                                         data = customBuilder.Data;
883                                         pos = 2;
884                                         flags = (uint) data [pos];
885                                         flags |= ((uint) data [pos + 1]) << 8;
886                                         flags |= ((uint) data [pos + 2]) << 16;
887                                         flags |= ((uint) data [pos + 3]) << 24;
888                                 }
889                         }
890
891                         if (cattrs != null) {
892                                 CustomAttributeBuilder[] new_array = new CustomAttributeBuilder [cattrs.Length + 1];
893                                 cattrs.CopyTo (new_array, 0);
894                                 new_array [cattrs.Length] = customBuilder;
895                                 cattrs = new_array;
896                         } else {
897                                 cattrs = new CustomAttributeBuilder [1];
898                                 cattrs [0] = customBuilder;
899                         }
900                 }
901
902 #if NET_2_0
903                 [ComVisible (true)]
904 #endif
905                 public void SetCustomAttribute ( ConstructorInfo con, byte[] binaryAttribute) {
906                         if (con == null)
907                                 throw new ArgumentNullException ("con");
908                         if (binaryAttribute == null)
909                                 throw new ArgumentNullException ("binaryAttribute");
910
911                         SetCustomAttribute (new CustomAttributeBuilder (con, binaryAttribute));
912                 }
913
914                 internal void SetCorlibTypeBuilders (Type corlib_object_type, Type corlib_value_type, Type corlib_enum_type) {
915                         this.corlib_object_type = corlib_object_type;
916                         this.corlib_value_type = corlib_value_type;
917                         this.corlib_enum_type = corlib_enum_type;
918                 }
919
920                 internal void SetCorlibTypeBuilders (Type corlib_object_type, Type corlib_value_type, Type corlib_enum_type, Type corlib_void_type)
921                 {
922                         SetCorlibTypeBuilders (corlib_object_type, corlib_value_type, corlib_enum_type);
923                         this.corlib_void_type = corlib_void_type;
924                 }
925
926                 private Exception not_supported () {
927                         // Strange message but this is what MS.NET prints...
928                         return new NotSupportedException ("The invoked member is not supported in a dynamic module.");
929                 }
930
931                 private void check_name_and_filename (string name, string fileName,
932                                                                                           bool fileNeedsToExists) {
933                         if (name == null)
934                                 throw new ArgumentNullException ("name");
935                         if (fileName == null)
936                                 throw new ArgumentNullException ("fileName");
937                         if (name.Length == 0)
938                                 throw new ArgumentException ("Empty name is not legal.", "name");
939                         if (fileName.Length == 0)
940                                 throw new ArgumentException ("Empty file name is not legal.", "fileName");
941                         if (Path.GetFileName (fileName) != fileName)
942                                 throw new ArgumentException ("fileName '" + fileName + "' must not include a path.", "fileName");
943
944                         // Resource files are created/searched under the assembly storage
945                         // directory
946                         string fullFileName = fileName;
947                         if (dir != null)
948                                 fullFileName = Path.Combine (dir, fileName);
949
950                         if (fileNeedsToExists && !File.Exists (fullFileName))
951                                 throw new FileNotFoundException ("Could not find file '" + fileName + "'");
952
953                         if (resources != null) {
954                                 for (int i = 0; i < resources.Length; ++i) {
955                                         if (resources [i].filename == fullFileName)
956                                                 throw new ArgumentException ("Duplicate file name '" + fileName + "'");
957                                         if (resources [i].name == name)
958                                                 throw new ArgumentException ("Duplicate name '" + name + "'");
959                                 }
960                         }
961
962                         if (modules != null) {
963                                 for (int i = 0; i < modules.Length; ++i) {
964                                         // Use fileName instead of fullFileName here
965                                         if (!modules [i].IsTransient () && (modules [i].FileName == fileName))
966                                                 throw new ArgumentException ("Duplicate file name '" + fileName + "'");
967                                         if (modules [i].Name == name)
968                                                 throw new ArgumentException ("Duplicate name '" + name + "'");
969                                 }
970                         }
971                 }
972
973                 private String create_assembly_version (String version) {
974                         String[] parts = version.Split ('.');
975                         int[] ver = new int [4] { 0, 0, 0, 0 };
976
977                         if ((parts.Length < 0) || (parts.Length > 4))
978                                 throw new ArgumentException ("The version specified '" + version + "' is invalid");
979
980                         for (int i = 0; i < parts.Length; ++i) {
981                                 if (parts [i] == "*") {
982                                         DateTime now = DateTime.Now;
983
984                                         if (i == 2) {
985                                                 ver [2] = (now - new DateTime (2000, 1, 1)).Days;
986                                                 if (parts.Length == 3)
987                                                         ver [3] = (now.Second + (now.Minute * 60) + (now.Hour * 3600)) / 2;
988                                         }
989                                         else
990                                                 if (i == 3)
991                                                         ver [3] = (now.Second + (now.Minute * 60) + (now.Hour * 3600)) / 2;
992                                         else
993                                                 throw new ArgumentException ("The version specified '" + version + "' is invalid");
994                                 }
995                                 else {
996                                         try {
997                                                 ver [i] = Int32.Parse (parts [i]);
998                                         }
999                                         catch (FormatException) {
1000                                                 throw new ArgumentException ("The version specified '" + version + "' is invalid");
1001                                         }
1002                                 }
1003                         }
1004
1005                         return ver [0] + "." + ver [1] + "." + ver [2] + "." + ver [3];
1006                 }
1007
1008                 private string GetCultureString (string str)
1009                 {
1010                         return (str == "neutral" ? String.Empty : str);
1011                 }
1012
1013                 internal override AssemblyName UnprotectedGetName ()
1014                 {
1015                         AssemblyName an = base.UnprotectedGetName ();
1016                         if (sn != null) {
1017                                 an.SetPublicKey (sn.PublicKey);
1018                                 an.SetPublicKeyToken (sn.PublicKeyToken);
1019                         }
1020                         return an;
1021                 }
1022
1023                 void _AssemblyBuilder.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
1024                 {
1025                         throw new NotImplementedException ();
1026                 }
1027
1028                 void _AssemblyBuilder.GetTypeInfo (uint iTInfo, uint lcid, IntPtr ppTInfo)
1029                 {
1030                         throw new NotImplementedException ();
1031                 }
1032
1033                 void _AssemblyBuilder.GetTypeInfoCount (out uint pcTInfo)
1034                 {
1035                         throw new NotImplementedException ();
1036                 }
1037
1038                 void _AssemblyBuilder.Invoke (uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
1039                 {
1040                         throw new NotImplementedException ();
1041                 }
1042         }
1043 }