Wed Feb 24 15:47:16 CET 2010 Paolo Molaro <lupus@ximian.com>
[mono.git] / mcs / class / corlib / System.Reflection / Assembly.cs
1 //
2 // System.Reflection/Assembly.cs
3 //
4 // Author:
5 //   Paolo Molaro (lupus@ximian.com)
6 //
7 // (C) 2001 Ximian, Inc.  http://www.ximian.com
8 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 // 
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 // 
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29
30 using System.Security;
31 using System.Security.Policy;
32 using System.Security.Permissions;
33 using System.Runtime.Serialization;
34 using System.Reflection;
35 using System.Reflection.Emit;
36 using System.IO;
37 using System.Globalization;
38 using System.Runtime.CompilerServices;
39 using System.Runtime.InteropServices;
40 using System.Collections;
41 using System.Collections.Generic;
42 using System.Configuration.Assemblies;
43
44 using Mono.Security;
45
46 namespace System.Reflection {
47
48 #pragma warning disable 659 // overrides Equals but not GetHashCode
49
50         [ComVisible (true)]
51         [ComDefaultInterfaceAttribute (typeof (_Assembly))]
52         [Serializable]
53         [ClassInterface(ClassInterfaceType.None)]
54 #if NET_2_1
55         public class Assembly : ICustomAttributeProvider, _Assembly {
56 #else
57         public class Assembly : ICustomAttributeProvider, _Assembly, IEvidenceFactory, ISerializable {
58 #endif
59
60                 internal class ResolveEventHolder {
61                         public event ModuleResolveEventHandler ModuleResolve;
62                 }
63
64                 // Note: changes to fields must be reflected in _MonoReflectionAssembly struct (object-internals.h)
65 #pragma warning disable 649
66                 private IntPtr _mono_assembly;
67 #pragma warning restore 649
68
69                 private ResolveEventHolder resolve_event_holder;
70                 private Evidence _evidence;
71                 internal PermissionSet _minimum;        // for SecurityAction.RequestMinimum
72                 internal PermissionSet _optional;       // for SecurityAction.RequestOptional
73                 internal PermissionSet _refuse;         // for SecurityAction.RequestRefuse
74                 private PermissionSet _granted;         // for the resolved assembly granted permissions
75                 private PermissionSet _denied;          // for the resolved assembly denied permissions
76                 private bool fromByteArray;
77                 private string assemblyName;
78
79                 internal Assembly () 
80                 {
81                         resolve_event_holder = new ResolveEventHolder ();
82                 }
83
84                 //
85                 // We can't store the event directly in this class, since the
86                 // compiler would silently insert the fields before _mono_assembly
87                 //
88                 public event ModuleResolveEventHandler ModuleResolve {
89                         [SecurityPermission (SecurityAction.LinkDemand, ControlAppDomain = true)]
90                         add {
91                                 resolve_event_holder.ModuleResolve += value;
92                         }
93                         [SecurityPermission (SecurityAction.LinkDemand, ControlAppDomain = true)]
94                         remove {
95                                 resolve_event_holder.ModuleResolve -= value;
96                         }
97                 }
98
99                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
100                 private extern string get_code_base (bool escaped);
101
102                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
103                 private extern string get_fullname ();
104
105                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
106                 private extern string get_location ();
107
108                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
109                 private extern string InternalImageRuntimeVersion ();
110
111                 // SECURITY: this should be the only caller to icall get_code_base
112                 private string GetCodeBase (bool escaped)
113                 {
114                         string cb = get_code_base (escaped);
115 #if !NET_2_1
116                         if (SecurityManager.SecurityEnabled) {
117                                 // we cannot divulge local file informations
118                                 if (String.Compare ("FILE://", 0, cb, 0, 7, true, CultureInfo.InvariantCulture) == 0) {
119                                         string file = cb.Substring (7);
120                                         new FileIOPermission (FileIOPermissionAccess.PathDiscovery, file).Demand ();
121                                 }
122                         }
123 #endif
124                         return cb;
125                 }
126
127                 public virtual string CodeBase {
128                         get { return GetCodeBase (false); }
129                 }
130
131                 public virtual string EscapedCodeBase {
132                         get { return GetCodeBase (true); }
133                 }
134
135                 public virtual string FullName {
136                         get {
137                                 //
138                                 // FIXME: This is wrong, but it gets us going
139                                 // in the compiler for now
140                                 //
141                                 return ToString ();
142                         }
143                 }
144
145                 public virtual extern MethodInfo EntryPoint {
146                         [MethodImplAttribute (MethodImplOptions.InternalCall)]
147                         get;
148                 }
149 #if !NET_2_1 || MONOTOUCH
150                 public virtual Evidence Evidence {
151                         [SecurityPermission (SecurityAction.Demand, ControlEvidence = true)]
152                         get { return UnprotectedGetEvidence (); }
153                 }
154
155                 // note: the security runtime requires evidences but may be unable to do so...
156                 internal Evidence UnprotectedGetEvidence ()
157                 {
158                         // if the host (runtime) hasn't provided it's own evidence...
159                         if (_evidence == null) {
160                                 // ... we will provide our own
161                                 lock (this) {
162                                         _evidence = Evidence.GetDefaultHostEvidence (this);
163                                 }
164                         }
165                         return _evidence;
166                 }
167
168                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
169                 private extern bool get_global_assembly_cache ();
170
171                 public bool GlobalAssemblyCache {
172                         get {
173                                 return get_global_assembly_cache ();
174                         }
175                 }
176 #endif
177                 internal bool FromByteArray {
178                         set { fromByteArray = value; }
179                 }
180
181                 public virtual String Location {
182                         get {
183                                 if (fromByteArray)
184                                         return String.Empty;
185
186                                 string loc = get_location ();
187 #if !NET_2_1
188                                 if ((loc != String.Empty) && SecurityManager.SecurityEnabled) {
189                                         // we cannot divulge local file informations
190                                         new FileIOPermission (FileIOPermissionAccess.PathDiscovery, loc).Demand ();
191                                 }
192 #endif
193                                 return loc;
194                         }
195                 }
196
197                 [ComVisible (false)]
198                 public virtual string ImageRuntimeVersion {
199                         get {
200                                 return InternalImageRuntimeVersion ();
201                         }
202                 }
203
204                 [SecurityPermission (SecurityAction.LinkDemand, SerializationFormatter = true)]
205                 public virtual void GetObjectData (SerializationInfo info, StreamingContext context)
206                 {
207                         if (info == null)
208                                 throw new ArgumentNullException ("info");
209
210                         UnitySerializationHolder.GetAssemblyData (this, info, context);
211                 }
212
213                 public virtual bool IsDefined (Type attributeType, bool inherit)
214                 {
215                         return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
216                 }
217
218                 public virtual object [] GetCustomAttributes (bool inherit)
219                 {
220                         return MonoCustomAttrs.GetCustomAttributes (this, inherit);
221                 }
222
223                 public virtual object [] GetCustomAttributes (Type attributeType, bool inherit)
224                 {
225                         return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
226                 }
227
228                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
229                 private extern object GetFilesInternal (String name, bool getResourceModules);
230
231                 public virtual FileStream[] GetFiles ()
232                 {
233                         return GetFiles (false);
234                 }
235
236                 public virtual FileStream [] GetFiles (bool getResourceModules)
237                 {
238                         string[] names = (string[]) GetFilesInternal (null, getResourceModules);
239                         if (names == null)
240                                 return new FileStream [0];
241
242                         string location = Location;
243
244                         FileStream[] res;
245                         if (location != String.Empty) {
246                                 res = new FileStream [names.Length + 1];
247                                 res [0] = new FileStream (location, FileMode.Open, FileAccess.Read);
248                                 for (int i = 0; i < names.Length; ++i)
249                                         res [i + 1] = new FileStream (names [i], FileMode.Open, FileAccess.Read);
250                         } else {
251                                 res = new FileStream [names.Length];
252                                 for (int i = 0; i < names.Length; ++i)
253                                         res [i] = new FileStream (names [i], FileMode.Open, FileAccess.Read);
254                         }
255                         return res;
256                 }
257
258                 public virtual FileStream GetFile (String name)
259                 {
260                         if (name == null)
261                                 throw new ArgumentNullException (null, "Name cannot be null.");
262                         if (name.Length == 0)
263                                 throw new ArgumentException ("Empty name is not valid");
264
265                         string filename = (string)GetFilesInternal (name, true);
266                         if (filename != null)
267                                 return new FileStream (filename, FileMode.Open, FileAccess.Read);
268                         else
269                                 return null;
270                 }
271
272                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
273                 internal extern IntPtr GetManifestResourceInternal (String name, out int size, out Module module);
274
275                 public virtual Stream GetManifestResourceStream (String name)
276                 {
277                         if (name == null)
278                                 throw new ArgumentNullException ("name");
279                         if (name.Length == 0)
280                                 throw new ArgumentException ("String cannot have zero length.",
281                                         "name");
282
283                         ManifestResourceInfo info = GetManifestResourceInfo (name);
284                         if (info == null)
285                                 return null;
286
287                         if (info.ReferencedAssembly != null)
288                                 return info.ReferencedAssembly.GetManifestResourceStream (name);
289                         if ((info.FileName != null) && (info.ResourceLocation == 0)) {
290                                 if (fromByteArray)
291                                         throw new FileNotFoundException (info.FileName);
292
293                                 string location = Path.GetDirectoryName (Location);
294                                 string filename = Path.Combine (location, info.FileName);
295 #if NET_2_1 && !MONOTOUCH
296                                 // we don't control the content of 'info.FileName' so we want to make sure we keep to ourselves
297                                 filename = Path.GetFullPath (filename);
298                                 if (!filename.StartsWith (location))
299                                         throw new SecurityException ("non-rooted access to manifest resource");
300 #endif
301                                 return new FileStream (filename, FileMode.Open, FileAccess.Read);
302                         }
303
304                         int size;
305                         Module module;
306                         IntPtr data = GetManifestResourceInternal (name, out size, out module);
307                         if (data == (IntPtr) 0)
308                                 return null;
309                         else {
310                                 UnmanagedMemoryStream stream;
311                                 unsafe {
312                                         stream = new UnmanagedMemoryStream ((byte*) data, size);
313                                 }
314                                 /* 
315                                  * The returned pointer points inside metadata, so
316                                  * we have to increase the refcount of the module, and decrease
317                                  * it when the stream is finalized.
318                                  */
319                                 stream.Closed += new EventHandler (new ResourceCloseHandler (module).OnClose);
320                                 return stream;
321                         }
322                 }
323
324                 public virtual Stream GetManifestResourceStream (Type type, String name)
325                 {
326                         string ns;
327                         if (type != null) {
328                                 ns = type.Namespace;
329                         } else {
330                                 if (name == null)
331                                         throw new ArgumentNullException ("type");
332                                 ns = null;
333                         }
334
335                         if (ns == null || ns.Length == 0)
336                                 return GetManifestResourceStream (name);
337                         else
338                                 return GetManifestResourceStream (ns + "." + name);
339                 }
340
341                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
342                 internal virtual extern Type[] GetTypes (bool exportedOnly);
343                 
344                 public virtual Type[] GetTypes ()
345                 {
346                         return GetTypes (false);
347                 }
348
349                 public virtual Type[] GetExportedTypes ()
350                 {
351                         return GetTypes (true);
352                 }
353
354                 public virtual Type GetType (String name, Boolean throwOnError)
355                 {
356                         return GetType (name, throwOnError, false);
357                 }
358
359                 public virtual Type GetType (String name) {
360                         return GetType (name, false, false);
361                 }
362
363                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
364                 internal extern Type InternalGetType (Module module, String name, Boolean throwOnError, Boolean ignoreCase);
365
366                 public Type GetType (string name, bool throwOnError, bool ignoreCase)
367                 {
368                         if (name == null)
369                                 throw new ArgumentNullException (name);
370                         if (name.Length == 0)
371                         throw new ArgumentException ("name", "Name cannot be empty");
372
373                         return InternalGetType (null, name, throwOnError, ignoreCase);
374                 }
375
376                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
377                 internal extern static void InternalGetAssemblyName (string assemblyFile, AssemblyName aname);
378
379                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
380                 static extern void FillName (Assembly ass, AssemblyName aname);
381
382                 [MonoTODO ("copiedName == true is not supported")]
383                 public virtual AssemblyName GetName (Boolean copiedName)
384                 {
385                         // CodeBase, which is restricted, will be copied into the AssemblyName object so...
386                         if (SecurityManager.SecurityEnabled) {
387                                 GetCodeBase (true); // this will ensure the Demand is made
388                         }
389                         return UnprotectedGetName ();
390                 }
391
392                 public virtual AssemblyName GetName ()
393                 {
394                         return GetName (false);
395                 }
396
397                 // the security runtime requires access to the assemblyname (e.g. to get the strongname)
398                 internal virtual AssemblyName UnprotectedGetName ()
399                 {
400                         AssemblyName aname = new AssemblyName ();
401                         FillName (this, aname);
402                         return aname;
403                 }
404
405                 public override string ToString ()
406                 {
407                         // note: ToString work without requiring CodeBase (so no checks are needed)
408
409                         if (assemblyName != null)
410                                 return assemblyName;
411
412                         assemblyName = get_fullname ();
413                         return assemblyName;
414                 }
415
416                 public static String CreateQualifiedName (String assemblyName, String typeName) 
417                 {
418                         return typeName + ", " + assemblyName;
419                 }
420
421                 public static Assembly GetAssembly (Type type)
422                 {
423                         if (type != null)
424                                 return type.Assembly;
425                         throw new ArgumentNullException ("type");
426                 }
427
428
429                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
430                 public static extern Assembly GetEntryAssembly();
431
432                 public Assembly GetSatelliteAssembly (CultureInfo culture)
433                 {
434                         return GetSatelliteAssembly (culture, null, true);
435                 }
436
437                 public Assembly GetSatelliteAssembly (CultureInfo culture, Version version)
438                 {
439                         return GetSatelliteAssembly (culture, version, true);
440                 }
441
442                 internal Assembly GetSatelliteAssemblyNoThrow (CultureInfo culture, Version version)
443                 {
444                         return GetSatelliteAssembly (culture, version, false);
445                 }
446
447                 private Assembly GetSatelliteAssembly (CultureInfo culture, Version version, bool throwOnError)
448                 {
449                         if (culture == null)
450                                 throw new ArgumentException ("culture");
451
452                         AssemblyName aname = GetName (true);
453                         if (version != null)
454                                 aname.Version = version;
455
456                         aname.CultureInfo = culture;
457                         aname.Name = aname.Name + ".resources";
458                         Assembly assembly;
459
460                         try {
461                                 assembly = AppDomain.CurrentDomain.LoadSatellite (aname, false);
462                                 if (assembly != null)
463                                         return assembly;
464                         } catch (FileNotFoundException) {
465                                 assembly = null;
466                                 // ignore
467                         }
468
469                         // Try the assembly directory
470                         string location = Path.GetDirectoryName (Location);
471                         string fullName = Path.Combine (location, Path.Combine (culture.Name, aname.Name + ".dll"));
472 #if NET_2_1 && !MONOTOUCH
473                         // it's unlikely that culture.Name or aname.Name could contain stuff like ".." but...
474                         fullName = Path.GetFullPath (fullName);
475                         if (!fullName.StartsWith (location)) {
476                                 if (throwOnError)
477                                         throw new SecurityException ("non-rooted access to satellite assembly");
478                                 return null;
479                         }
480 #endif
481                         if (!throwOnError && !File.Exists (fullName))
482                                 return null;
483
484                         return LoadFrom (fullName);
485                 }
486                 
487                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
488                 private extern static Assembly LoadFrom (String assemblyFile, bool refonly);
489
490                 public static Assembly LoadFrom (String assemblyFile)
491                 {
492                         return LoadFrom (assemblyFile, false);
493                 }
494
495                 public static Assembly LoadFrom (String assemblyFile, Evidence securityEvidence)
496                 {
497                         Assembly a = LoadFrom (assemblyFile, false);
498 #if !NET_2_1
499                         if ((a != null) && (securityEvidence != null)) {
500                                 // merge evidence (i.e. replace defaults with provided evidences)
501                                 a.Evidence.Merge (securityEvidence);
502                         }
503 #endif
504                         return a;
505                 }
506
507                 [MonoTODO("This overload is not currently implemented")]
508                 // FIXME: What are we missing?
509                 public static Assembly LoadFrom (String assemblyFile, Evidence securityEvidence, byte[] hashValue, AssemblyHashAlgorithm hashAlgorithm)
510                 {
511                         if (assemblyFile == null)
512                                 throw new ArgumentNullException ("assemblyFile");
513                         if (assemblyFile == String.Empty)
514                                 throw new ArgumentException ("Name can't be the empty string", "assemblyFile");
515                         throw new NotImplementedException ();
516                 }
517
518                 public static Assembly LoadFile (String path, Evidence securityEvidence)
519                 {
520                         if (path == null)
521                                 throw new ArgumentNullException ("path");
522                         if (path == String.Empty)
523                                 throw new ArgumentException ("Path can't be empty", "path");
524                         // FIXME: Make this do the right thing
525                         return LoadFrom (path, securityEvidence);
526                 }
527
528                 public static Assembly LoadFile (String path)
529                 {
530                         return LoadFile (path, null);
531                 }
532
533                 public static Assembly Load (String assemblyString)
534                 {
535                         return AppDomain.CurrentDomain.Load (assemblyString);
536                 }
537                 
538                 public static Assembly Load (String assemblyString, Evidence assemblySecurity)
539                 {
540                         return AppDomain.CurrentDomain.Load (assemblyString, assemblySecurity);
541                 }
542
543                 public static Assembly Load (AssemblyName assemblyRef)
544                 {
545                         return AppDomain.CurrentDomain.Load (assemblyRef);
546                 }
547
548                 public static Assembly Load (AssemblyName assemblyRef, Evidence assemblySecurity)
549                 {
550                         return AppDomain.CurrentDomain.Load (assemblyRef, assemblySecurity);
551                 }
552
553                 public static Assembly Load (Byte[] rawAssembly)
554                 {
555                         return AppDomain.CurrentDomain.Load (rawAssembly);
556                 }
557
558                 public static Assembly Load (Byte[] rawAssembly, Byte[] rawSymbolStore)
559                 {
560                         return AppDomain.CurrentDomain.Load (rawAssembly, rawSymbolStore);
561                 }
562
563                 public static Assembly Load (Byte[] rawAssembly, Byte[] rawSymbolStore,
564                                              Evidence securityEvidence)
565                 {
566                         return AppDomain.CurrentDomain.Load (rawAssembly, rawSymbolStore, securityEvidence);
567                 }
568
569                 public static Assembly ReflectionOnlyLoad (byte[] rawAssembly)
570                 {
571                         return AppDomain.CurrentDomain.Load (rawAssembly, null, null, true);
572                 }
573
574                 public static Assembly ReflectionOnlyLoad (string assemblyString) 
575                 {
576                         return AppDomain.CurrentDomain.Load (assemblyString, null, true);
577                 }
578
579                 public static Assembly ReflectionOnlyLoadFrom (string assemblyFile) 
580                 {
581                         if (assemblyFile == null)
582                                 throw new ArgumentNullException ("assemblyFile");
583                         
584                         return LoadFrom (assemblyFile, true);
585                 }
586
587                 public static Assembly LoadWithPartialName (string partialName)
588                 {
589                         return LoadWithPartialName (partialName, null);
590                 }
591
592                 [MonoTODO ("Not implemented")]
593                 public Module LoadModule (string moduleName, byte [] rawModule)
594                 {
595                         throw new NotImplementedException ();
596                 }
597
598                 [MonoTODO ("Not implemented")]
599                 public Module LoadModule (string moduleName, byte [] rawModule, byte [] rawSymbolStore)
600                 {
601                         throw new NotImplementedException ();
602                 }
603
604                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
605                 private static extern Assembly load_with_partial_name (string name, Evidence e);
606
607                 public static Assembly LoadWithPartialName (string partialName, Evidence securityEvidence)
608                 {
609                         return LoadWithPartialName (partialName, securityEvidence, true);
610                 }
611
612                 /**
613                  * LAMESPEC: It is possible for this method to throw exceptions IF the name supplied
614                  * is a valid gac name and contains filesystem entry charachters at the end of the name
615                  * ie System/// will throw an exception. However ////System will not as that is canocolized
616                  * out of the name.
617                  */
618
619                 // FIXME: LoadWithPartialName must look cache (no CAS) or read from disk (CAS)
620                 internal static Assembly LoadWithPartialName (string partialName, Evidence securityEvidence, bool oldBehavior)
621                 {
622                         if (!oldBehavior)
623                                 throw new NotImplementedException ();
624
625                         if (partialName == null)
626                                 throw new NullReferenceException ();
627
628                         return load_with_partial_name (partialName, securityEvidence);
629                 }
630
631                 public Object CreateInstance (String typeName) 
632                 {
633                         return CreateInstance (typeName, false);
634                 }
635
636                 public Object CreateInstance (String typeName, Boolean ignoreCase)
637                 {
638                         Type t = GetType (typeName, false, ignoreCase);
639                         if (t == null)
640                                 return null;
641
642                         try {
643                                 return Activator.CreateInstance (t);
644                         } catch (InvalidOperationException) {
645                                 throw new ArgumentException ("It is illegal to invoke a method on a Type loaded via ReflectionOnly methods.");
646                         }
647                 }
648
649                 public Object CreateInstance (String typeName, Boolean ignoreCase,
650                                               BindingFlags bindingAttr, Binder binder,
651                                               Object[] args, CultureInfo culture,
652                                               Object[] activationAttributes)
653                 {
654                         Type t = GetType (typeName, false, ignoreCase);
655                         if (t == null)
656                                 return null;
657
658                         try {
659                                 return Activator.CreateInstance (t, bindingAttr, binder, args, culture, activationAttributes);
660                         } catch (InvalidOperationException) {
661                                 throw new ArgumentException ("It is illegal to invoke a method on a Type loaded via ReflectionOnly methods.");
662                         }
663                 }
664
665                 public Module[] GetLoadedModules ()
666                 {
667                         return GetLoadedModules (false);
668                 }
669
670                 // FIXME: Currently, the two sets of modules are equal
671                 public Module[] GetLoadedModules (bool getResourceModules)
672                 {
673                         return GetModules (getResourceModules);
674                 }
675
676                 public Module[] GetModules ()
677                 {
678                         return GetModules (false);
679                 }
680
681                 public Module GetModule (String name)
682                 {
683                         if (name == null)
684                                 throw new ArgumentNullException ("name");
685                         if (name.Length == 0)
686                                 throw new ArgumentException ("Name can't be empty");
687
688                         Module[] modules = GetModules (true);
689                         foreach (Module module in modules) {
690                                 if (module.ScopeName == name)
691                                         return module;
692                         }
693
694                         return null;
695                 }
696
697                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
698                 internal virtual extern Module[] GetModulesInternal ();
699
700                 public Module[] GetModules (bool getResourceModules) {
701                         Module[] modules = GetModulesInternal ();
702
703                         if (!getResourceModules) {
704                                 ArrayList result = new ArrayList (modules.Length);
705                                 foreach (Module m in modules)
706                                         if (!m.IsResource ())
707                                                 result.Add (m);
708                                 return (Module[])result.ToArray (typeof (Module));
709                         }
710                         else
711                                 return modules;
712                 }
713
714                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
715                 internal extern string[] GetNamespaces ();
716                 
717                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
718                 public extern virtual String[] GetManifestResourceNames ();
719
720                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
721                 public extern static Assembly GetExecutingAssembly ();
722
723                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
724                 public extern static Assembly GetCallingAssembly ();
725
726                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
727                 public extern AssemblyName[] GetReferencedAssemblies ();
728
729                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
730                 private extern bool GetManifestResourceInfoInternal (String name, ManifestResourceInfo info);
731
732                 public virtual ManifestResourceInfo GetManifestResourceInfo (String resourceName)
733                 {
734                         if (resourceName == null)
735                                 throw new ArgumentNullException ("resourceName");
736                         if (resourceName.Length == 0)
737                                 throw new ArgumentException ("String cannot have zero length.");
738                         ManifestResourceInfo result = new ManifestResourceInfo ();
739                         bool found = GetManifestResourceInfoInternal (resourceName, result);
740                         if (found)
741                                 return result;
742                         else
743                                 return null;
744                 }
745
746                 private class ResourceCloseHandler {
747 #pragma warning disable 169, 414
748                         Module module;
749 #pragma warning restore 169, 414                        
750
751                         public ResourceCloseHandler (Module module) {
752                                 this.module = module;
753                         }
754
755                         public void OnClose (object sender, EventArgs e) {
756                                 // The module dtor will take care of things
757                                 module = null;
758                         }
759                 }
760
761                 //
762                 // The following functions are only for the Mono Debugger.
763                 //
764
765                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
766                 internal static extern int MonoDebugger_GetMethodToken (MethodBase method);
767
768                 [MonoTODO ("Currently it always returns zero")]
769                 [ComVisible (false)]
770                 public long HostContext {
771                         get { return 0; }
772                 }
773
774                 [ComVisible (false)]
775                 public Module ManifestModule {
776                         get {
777                                 return GetManifestModule ();
778                         }
779                 }
780
781                 internal virtual Module GetManifestModule () {
782                         return GetManifestModuleInternal ();
783                 }
784
785                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
786                 internal extern Module GetManifestModuleInternal ();
787
788                 [ComVisible (false)]
789                 public virtual extern bool ReflectionOnly {
790                         [MethodImplAttribute (MethodImplOptions.InternalCall)]
791                         get;
792                 }
793
794                 public override bool Equals (object o)
795                 {
796                         if (((object) this) == o)
797                                 return true;
798
799                         if (o == null)
800                                 return false;
801                         
802                         Assembly other = (Assembly) o;
803                         return other._mono_assembly == _mono_assembly;
804                 }
805                 
806 #if NET_4_0
807                 public virtual IList<CustomAttributeData> GetCustomAttributesData () {
808                         return CustomAttributeData.GetCustomAttributes (this);
809                 }
810 #endif
811
812 #if !NET_2_1 || MONOTOUCH
813                 // Code Access Security
814
815                 internal void Resolve () 
816                 {
817                         lock (this) {
818                                 // FIXME: As we (currently) delay the resolution until the first CAS
819                                 // Demand it's too late to evaluate the Minimum permission set as a 
820                                 // condition to load the assembly into the AppDomain
821                                 LoadAssemblyPermissions ();
822                                 Evidence e = new Evidence (UnprotectedGetEvidence ()); // we need a copy to add PRE
823                                 e.AddHost (new PermissionRequestEvidence (_minimum, _optional, _refuse));
824                                 _granted = SecurityManager.ResolvePolicy (e,
825                                         _minimum, _optional, _refuse, out _denied);
826                         }
827                 }
828
829                 internal PermissionSet GrantedPermissionSet {
830                         get {
831                                 if (_granted == null) {
832                                         if (SecurityManager.ResolvingPolicyLevel != null) {
833                                                 if (SecurityManager.ResolvingPolicyLevel.IsFullTrustAssembly (this))
834                                                         return DefaultPolicies.FullTrust;
835                                                 else
836                                                         return null; // we can't resolve during resolution
837                                         }
838                                         Resolve ();
839                                 }
840                                 return _granted;
841                         }
842                 }
843
844                 internal PermissionSet DeniedPermissionSet {
845                         get {
846                                 // yes we look for granted, as denied may be null
847                                 if (_granted == null) {
848                                         if (SecurityManager.ResolvingPolicyLevel != null) {
849                                                 if (SecurityManager.ResolvingPolicyLevel.IsFullTrustAssembly (this))
850                                                         return null;
851                                                 else
852                                                         return DefaultPolicies.FullTrust; // deny unrestricted
853                                         }
854                                         Resolve ();
855                                 }
856                                 return _denied;
857                         }
858                 }
859
860                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
861                 extern internal static bool LoadPermissions (Assembly a, 
862                         ref IntPtr minimum, ref int minLength,
863                         ref IntPtr optional, ref int optLength,
864                         ref IntPtr refused, ref int refLength);
865
866                 // Support for SecurityAction.RequestMinimum, RequestOptional and RequestRefuse
867                 private void LoadAssemblyPermissions ()
868                 {
869                         IntPtr minimum = IntPtr.Zero, optional = IntPtr.Zero, refused = IntPtr.Zero;
870                         int minLength = 0, optLength = 0, refLength = 0;
871                         if (LoadPermissions (this, ref minimum, ref minLength, ref optional,
872                                 ref optLength, ref refused, ref refLength)) {
873
874                                 // Note: no need to cache these permission sets as they will only be created once
875                                 // at assembly resolution time.
876                                 if (minLength > 0) {
877                                         byte[] data = new byte [minLength];
878                                         Marshal.Copy (minimum, data, 0, minLength);
879                                         _minimum = SecurityManager.Decode (data);
880                                 }
881                                 if (optLength > 0) {
882                                         byte[] data = new byte [optLength];
883                                         Marshal.Copy (optional, data, 0, optLength);
884                                         _optional = SecurityManager.Decode (data);
885                                 }
886                                 if (refLength > 0) {
887                                         byte[] data = new byte [refLength];
888                                         Marshal.Copy (refused, data, 0, refLength);
889                                         _refuse = SecurityManager.Decode (data);
890                                 }
891                         }
892                 }
893 #endif
894         }
895 }
896
897 #pragma warning restore 659