2 // System.Reflection/Assembly.cs
5 // Paolo Molaro (lupus@ximian.com)
7 // (C) 2001 Ximian, Inc. http://www.ximian.com
8 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
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:
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
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.
30 using System.Security;
31 using System.Security.Policy;
32 using System.Security.Permissions;
33 using System.Runtime.Serialization;
34 using System.Reflection.Emit;
36 using System.Globalization;
37 using System.Runtime.CompilerServices;
38 using System.Runtime.InteropServices;
39 using System.Collections;
40 using System.Configuration.Assemblies;
44 namespace System.Reflection {
48 [ComDefaultInterfaceAttribute (typeof (_Assembly))]
51 [ClassInterface(ClassInterfaceType.None)]
52 public class Assembly : System.Reflection.ICustomAttributeProvider, _Assembly,
53 System.Security.IEvidenceFactory, System.Runtime.Serialization.ISerializable {
55 internal class ResolveEventHolder {
56 public event ModuleResolveEventHandler ModuleResolve;
59 // Note: changes to fields must be reflected in _MonoReflectionAssembly struct (object-internals.h)
60 #pragma warning disable 169
61 private IntPtr _mono_assembly;
62 #pragma warning restore 169
64 private ResolveEventHolder resolve_event_holder;
65 private Evidence _evidence;
66 internal PermissionSet _minimum; // for SecurityAction.RequestMinimum
67 internal PermissionSet _optional; // for SecurityAction.RequestOptional
68 internal PermissionSet _refuse; // for SecurityAction.RequestRefuse
69 private PermissionSet _granted; // for the resolved assembly granted permissions
70 private PermissionSet _denied; // for the resolved assembly denied permissions
71 private bool fromByteArray;
72 private string assemblyName;
76 resolve_event_holder = new ResolveEventHolder ();
80 // We can't store the event directly in this class, since the
81 // compiler would silently insert the fields before _mono_assembly
83 public event ModuleResolveEventHandler ModuleResolve {
84 [SecurityPermission (SecurityAction.LinkDemand, ControlAppDomain = true)]
86 resolve_event_holder.ModuleResolve += value;
88 [SecurityPermission (SecurityAction.LinkDemand, ControlAppDomain = true)]
90 resolve_event_holder.ModuleResolve -= value;
94 [MethodImplAttribute (MethodImplOptions.InternalCall)]
95 private extern string get_code_base (bool escaped);
97 [MethodImplAttribute (MethodImplOptions.InternalCall)]
98 private extern string get_fullname ();
100 [MethodImplAttribute (MethodImplOptions.InternalCall)]
101 private extern string get_location ();
103 [MethodImplAttribute (MethodImplOptions.InternalCall)]
104 private extern string InternalImageRuntimeVersion ();
106 [MethodImplAttribute (MethodImplOptions.InternalCall)]
107 private extern bool get_global_assembly_cache ();
109 // SECURITY: this should be the only caller to icall get_code_base
110 private string GetCodeBase (bool escaped)
112 string cb = get_code_base (escaped);
113 if (SecurityManager.SecurityEnabled) {
114 // we cannot divulge local file informations
115 if (String.Compare ("FILE://", 0, cb, 0, 7, true, CultureInfo.InvariantCulture) == 0) {
116 string file = cb.Substring (7);
117 new FileIOPermission (FileIOPermissionAccess.PathDiscovery, file).Demand ();
123 public virtual string CodeBase {
124 get { return GetCodeBase (false); }
127 public virtual string EscapedCodeBase {
128 get { return GetCodeBase (true); }
131 public virtual string FullName {
134 // FIXME: This is wrong, but it gets us going
135 // in the compiler for now
141 public virtual extern MethodInfo EntryPoint {
142 [MethodImplAttribute (MethodImplOptions.InternalCall)]
146 public virtual Evidence Evidence {
147 [SecurityPermission (SecurityAction.Demand, ControlEvidence = true)]
148 get { return UnprotectedGetEvidence (); }
151 // note: the security runtime requires evidences but may be unable to do so...
152 internal Evidence UnprotectedGetEvidence ()
154 // if the host (runtime) hasn't provided it's own evidence...
155 if (_evidence == null) {
156 // ... we will provide our own
158 _evidence = Evidence.GetDefaultHostEvidence (this);
164 public bool GlobalAssemblyCache {
166 return get_global_assembly_cache ();
170 internal bool FromByteArray {
171 set { fromByteArray = value; }
174 public virtual String Location {
179 string loc = get_location ();
180 if ((loc != String.Empty) && SecurityManager.SecurityEnabled) {
181 // we cannot divulge local file informations
182 new FileIOPermission (FileIOPermissionAccess.PathDiscovery, loc).Demand ();
190 public virtual string ImageRuntimeVersion {
192 return InternalImageRuntimeVersion ();
197 [SecurityPermission (SecurityAction.LinkDemand, SerializationFormatter = true)]
198 public virtual void GetObjectData (SerializationInfo info, StreamingContext context)
201 throw new ArgumentNullException ("info");
203 UnitySerializationHolder.GetAssemblyData (this, info, context);
207 public new Type GetType ()
209 return base.GetType ();
213 public virtual bool IsDefined (Type attributeType, bool inherit)
215 return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
218 public virtual object [] GetCustomAttributes (bool inherit)
220 return MonoCustomAttrs.GetCustomAttributes (this, inherit);
223 public virtual object [] GetCustomAttributes (Type attributeType, bool inherit)
225 return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
228 [MethodImplAttribute (MethodImplOptions.InternalCall)]
229 private extern object GetFilesInternal (String name, bool getResourceModules);
231 public virtual FileStream[] GetFiles ()
233 return GetFiles (false);
236 public virtual FileStream [] GetFiles (bool getResourceModules)
238 string[] names = (string[]) GetFilesInternal (null, getResourceModules);
240 return new FileStream [0];
242 string location = Location;
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);
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);
258 public virtual FileStream GetFile (String name)
261 throw new ArgumentNullException (null, "Name cannot be null.");
262 if (name.Length == 0)
263 throw new ArgumentException ("Empty name is not valid");
265 string filename = (string)GetFilesInternal (name, true);
266 if (filename != null)
267 return new FileStream (filename, FileMode.Open, FileAccess.Read);
272 [MethodImplAttribute (MethodImplOptions.InternalCall)]
273 internal extern IntPtr GetManifestResourceInternal (String name, out int size, out Module module);
275 public virtual Stream GetManifestResourceStream (String name)
278 throw new ArgumentNullException ("name");
279 if (name.Length == 0)
280 throw new ArgumentException ("String cannot have zero length.",
283 ManifestResourceInfo info = GetManifestResourceInfo (name);
287 if (info.ReferencedAssembly != null)
288 return info.ReferencedAssembly.GetManifestResourceStream (name);
289 if ((info.FileName != null) && (info.ResourceLocation == 0)) {
292 throw new FileNotFoundException (info.FileName);
297 string filename = Path.Combine (Path.GetDirectoryName (Location),
299 return new FileStream (filename, FileMode.Open, FileAccess.Read);
304 IntPtr data = GetManifestResourceInternal (name, out size, out module);
305 if (data == (IntPtr) 0)
309 UnmanagedMemoryStream stream;
311 stream = new UnmanagedMemoryStream ((byte*) data, size);
314 IntPtrStream stream = new IntPtrStream (data, size);
317 * The returned pointer points inside metadata, so
318 * we have to increase the refcount of the module, and decrease
319 * it when the stream is finalized.
321 stream.Closed += new EventHandler (new ResourceCloseHandler (module).OnClose);
326 public virtual Stream GetManifestResourceStream (Type type, String name)
333 throw new ArgumentNullException ("type");
337 if (ns == null || ns.Length == 0)
338 return GetManifestResourceStream (name);
340 return GetManifestResourceStream (ns + "." + name);
343 [MethodImplAttribute (MethodImplOptions.InternalCall)]
344 internal virtual extern Type[] GetTypes (bool exportedOnly);
346 public virtual Type[] GetTypes ()
348 return GetTypes (false);
351 public virtual Type[] GetExportedTypes ()
353 return GetTypes (true);
356 public virtual Type GetType (String name, Boolean throwOnError)
358 return GetType (name, throwOnError, false);
361 public virtual Type GetType (String name) {
362 return GetType (name, false, false);
365 [MethodImplAttribute (MethodImplOptions.InternalCall)]
366 internal extern Type InternalGetType (Module module, String name, Boolean throwOnError, Boolean ignoreCase);
368 public Type GetType (string name, bool throwOnError, bool ignoreCase)
371 throw new ArgumentNullException (name);
373 return InternalGetType (null, name, throwOnError, ignoreCase);
376 [MethodImplAttribute (MethodImplOptions.InternalCall)]
377 internal extern static void InternalGetAssemblyName (string assemblyFile, AssemblyName aname);
379 [MethodImplAttribute (MethodImplOptions.InternalCall)]
380 static extern void FillName (Assembly ass, AssemblyName aname);
382 [MonoTODO ("copiedName == true is not supported")]
383 public virtual AssemblyName GetName (Boolean copiedName)
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
389 return UnprotectedGetName ();
392 public virtual AssemblyName GetName ()
394 return GetName (false);
397 // the security runtime requires access to the assemblyname (e.g. to get the strongname)
398 internal virtual AssemblyName UnprotectedGetName ()
400 AssemblyName aname = new AssemblyName ();
401 FillName (this, aname);
405 public override string ToString ()
407 // note: ToString work without requiring CodeBase (so no checks are needed)
409 if (assemblyName != null)
412 assemblyName = get_fullname ();
416 public static String CreateQualifiedName (String assemblyName, String typeName)
418 return typeName + ", " + assemblyName;
421 public static Assembly GetAssembly (Type type)
424 return type.Assembly;
425 throw new ArgumentNullException ("type");
429 [MethodImplAttribute (MethodImplOptions.InternalCall)]
430 public static extern Assembly GetEntryAssembly();
432 public Assembly GetSatelliteAssembly (CultureInfo culture)
434 return GetSatelliteAssembly (culture, null);
437 public Assembly GetSatelliteAssembly (CultureInfo culture, Version version)
440 throw new ArgumentException ("culture");
442 AssemblyName aname = GetName (true);
444 aname.Version = version;
446 aname.CultureInfo = culture;
447 aname.Name = aname.Name + ".resources";
450 } catch (Exception) {
451 // Try the assembly directory
452 string fullName = Path.Combine (Path.GetDirectoryName (Location), Path.Combine (culture.Name, aname.Name + ".dll"));
453 return LoadFrom (fullName);
457 [MethodImplAttribute (MethodImplOptions.InternalCall)]
458 private extern static Assembly LoadFrom (String assemblyFile, bool refonly);
460 public static Assembly LoadFrom (String assemblyFile)
462 return LoadFrom (assemblyFile, false);
465 public static Assembly LoadFrom (String assemblyFile, Evidence securityEvidence)
467 Assembly a = LoadFrom (assemblyFile, false);
468 if ((a != null) && (securityEvidence != null)) {
469 // merge evidence (i.e. replace defaults with provided evidences)
470 a.Evidence.Merge (securityEvidence);
477 [MonoTODO("This overload is not currently implemented")]
478 // FIXME: What are we missing?
479 public static Assembly LoadFrom (String assemblyFile, Evidence securityEvidence, byte[] hashValue, AssemblyHashAlgorithm hashAlgorithm)
481 if (assemblyFile == null)
482 throw new ArgumentNullException ("assemblyFile");
483 if (assemblyFile == String.Empty)
484 throw new ArgumentException ("Name can't be the empty string", "assemblyFile");
485 throw new NotImplementedException ();
488 public static Assembly LoadFile (String path, Evidence securityEvidence)
491 throw new ArgumentNullException ("path");
492 if (path == String.Empty)
493 throw new ArgumentException ("Path can't be empty", "path");
494 // FIXME: Make this do the right thing
495 return LoadFrom (path, securityEvidence);
498 public static Assembly LoadFile (String path)
500 return LoadFile (path, null);
504 public static Assembly Load (String assemblyString)
506 return AppDomain.CurrentDomain.Load (assemblyString);
509 public static Assembly Load (String assemblyString, Evidence assemblySecurity)
511 return AppDomain.CurrentDomain.Load (assemblyString, assemblySecurity);
514 public static Assembly Load (AssemblyName assemblyRef)
516 return AppDomain.CurrentDomain.Load (assemblyRef);
519 public static Assembly Load (AssemblyName assemblyRef, Evidence assemblySecurity)
521 return AppDomain.CurrentDomain.Load (assemblyRef, assemblySecurity);
524 public static Assembly Load (Byte[] rawAssembly)
526 return AppDomain.CurrentDomain.Load (rawAssembly);
529 public static Assembly Load (Byte[] rawAssembly, Byte[] rawSymbolStore)
531 return AppDomain.CurrentDomain.Load (rawAssembly, rawSymbolStore);
534 public static Assembly Load (Byte[] rawAssembly, Byte[] rawSymbolStore,
535 Evidence securityEvidence)
537 return AppDomain.CurrentDomain.Load (rawAssembly, rawSymbolStore, securityEvidence);
540 #if NET_2_0 || BOOTSTRAP_NET_2_0
541 public static Assembly ReflectionOnlyLoad (byte[] rawAssembly)
543 return AppDomain.CurrentDomain.Load (rawAssembly, null, null, true);
546 public static Assembly ReflectionOnlyLoad (string assemblyString)
548 return AppDomain.CurrentDomain.Load (assemblyString, null, true);
551 public static Assembly ReflectionOnlyLoadFrom (string assemblyFile)
553 if (assemblyFile == null)
554 throw new ArgumentNullException ("assemblyFile");
556 return LoadFrom (assemblyFile, true);
563 public static Assembly LoadWithPartialName (string partialName)
565 return LoadWithPartialName (partialName, null);
568 [MonoTODO ("Not implemented")]
569 public Module LoadModule (string moduleName, byte [] rawModule)
571 throw new NotImplementedException ();
574 [MonoTODO ("Not implemented")]
575 public Module LoadModule (string moduleName, byte [] rawModule, byte [] rawSymbolStore)
577 throw new NotImplementedException ();
580 [MethodImplAttribute (MethodImplOptions.InternalCall)]
581 private static extern Assembly load_with_partial_name (string name, Evidence e);
586 public static Assembly LoadWithPartialName (string partialName, Evidence securityEvidence)
588 return LoadWithPartialName (partialName, securityEvidence, true);
592 * LAMESPEC: It is possible for this method to throw exceptions IF the name supplied
593 * is a valid gac name and contains filesystem entry charachters at the end of the name
594 * ie System/// will throw an exception. However ////System will not as that is canocolized
598 // FIXME: LoadWithPartialName must look cache (no CAS) or read from disk (CAS)
599 internal static Assembly LoadWithPartialName (string partialName, Evidence securityEvidence, bool oldBehavior)
602 throw new NotImplementedException ();
604 if (partialName == null)
605 throw new NullReferenceException ();
607 return load_with_partial_name (partialName, securityEvidence);
610 public Object CreateInstance (String typeName)
612 return CreateInstance (typeName, false);
615 public Object CreateInstance (String typeName, Boolean ignoreCase)
617 Type t = GetType (typeName, false, ignoreCase);
622 return Activator.CreateInstance (t);
623 } catch (InvalidOperationException) {
624 throw new ArgumentException ("It is illegal to invoke a method on a Type loaded via ReflectionOnly methods.");
628 public Object CreateInstance (String typeName, Boolean ignoreCase,
629 BindingFlags bindingAttr, Binder binder,
630 Object[] args, CultureInfo culture,
631 Object[] activationAttributes)
633 Type t = GetType (typeName, false, ignoreCase);
638 return Activator.CreateInstance (t, bindingAttr, binder, args, culture, activationAttributes);
639 } catch (InvalidOperationException) {
640 throw new ArgumentException ("It is illegal to invoke a method on a Type loaded via ReflectionOnly methods.");
644 public Module[] GetLoadedModules ()
646 return GetLoadedModules (false);
649 // FIXME: Currently, the two sets of modules are equal
650 public Module[] GetLoadedModules (bool getResourceModules)
652 return GetModules (getResourceModules);
655 public Module[] GetModules ()
657 return GetModules (false);
660 public Module GetModule (String name)
663 throw new ArgumentNullException ("name");
664 if (name.Length == 0)
665 throw new ArgumentException ("Name can't be empty");
667 Module[] modules = GetModules (true);
668 foreach (Module module in modules) {
669 if (module.ScopeName == name)
676 [MethodImplAttribute (MethodImplOptions.InternalCall)]
677 internal virtual extern Module[] GetModulesInternal ();
679 public Module[] GetModules (bool getResourceModules) {
680 Module[] modules = GetModulesInternal ();
682 if (!getResourceModules) {
683 ArrayList result = new ArrayList (modules.Length);
684 foreach (Module m in modules)
685 if (!m.IsResource ())
687 return (Module[])result.ToArray (typeof (Module));
693 [MethodImplAttribute (MethodImplOptions.InternalCall)]
694 internal extern string[] GetNamespaces ();
696 [MethodImplAttribute (MethodImplOptions.InternalCall)]
697 public extern virtual String[] GetManifestResourceNames ();
699 [MethodImplAttribute (MethodImplOptions.InternalCall)]
700 public extern static Assembly GetExecutingAssembly ();
702 [MethodImplAttribute (MethodImplOptions.InternalCall)]
703 public extern static Assembly GetCallingAssembly ();
705 [MethodImplAttribute (MethodImplOptions.InternalCall)]
706 public extern AssemblyName[] GetReferencedAssemblies ();
708 [MethodImplAttribute (MethodImplOptions.InternalCall)]
709 private extern bool GetManifestResourceInfoInternal (String name, ManifestResourceInfo info);
711 public virtual ManifestResourceInfo GetManifestResourceInfo (String resourceName)
713 if (resourceName == null)
714 throw new ArgumentNullException ("resourceName");
715 if (resourceName.Length == 0)
716 throw new ArgumentException ("String cannot have zero length.");
717 ManifestResourceInfo result = new ManifestResourceInfo ();
718 bool found = GetManifestResourceInfoInternal (resourceName, result);
725 private class ResourceCloseHandler {
726 #pragma warning disable 169, 414
728 #pragma warning restore 169, 414
730 public ResourceCloseHandler (Module module) {
731 this.module = module;
734 public void OnClose (object sender, EventArgs e) {
735 // The module dtor will take care of things
741 // The following functions are only for the Mono Debugger.
744 [MethodImplAttribute (MethodImplOptions.InternalCall)]
745 internal static extern int MonoDebugger_GetMethodToken (MethodBase method);
747 #if NET_2_0 || BOOTSTRAP_NET_2_0
748 [MonoTODO ("Always returns zero")]
750 public long HostContext {
755 public Module ManifestModule {
757 return GetManifestModule ();
761 internal virtual Module GetManifestModule () {
762 return GetManifestModuleInternal ();
765 [MethodImplAttribute (MethodImplOptions.InternalCall)]
766 internal extern Module GetManifestModuleInternal ();
769 public virtual extern bool ReflectionOnly {
770 [MethodImplAttribute (MethodImplOptions.InternalCall)]
775 // Code Access Security
777 internal void Resolve ()
780 // FIXME: As we (currently) delay the resolution until the first CAS
781 // Demand it's too late to evaluate the Minimum permission set as a
782 // condition to load the assembly into the AppDomain
783 LoadAssemblyPermissions ();
784 Evidence e = new Evidence (UnprotectedGetEvidence ()); // we need a copy to add PRE
785 e.AddHost (new PermissionRequestEvidence (_minimum, _optional, _refuse));
786 _granted = SecurityManager.ResolvePolicy (e,
787 _minimum, _optional, _refuse, out _denied);
791 internal PermissionSet GrantedPermissionSet {
793 if (_granted == null) {
794 if (SecurityManager.ResolvingPolicyLevel != null) {
795 if (SecurityManager.ResolvingPolicyLevel.IsFullTrustAssembly (this))
796 return DefaultPolicies.FullTrust;
798 return null; // we can't resolve during resolution
806 internal PermissionSet DeniedPermissionSet {
808 // yes we look for granted, as denied may be null
809 if (_granted == null) {
810 if (SecurityManager.ResolvingPolicyLevel != null) {
811 if (SecurityManager.ResolvingPolicyLevel.IsFullTrustAssembly (this))
814 return DefaultPolicies.FullTrust; // deny unrestricted
822 [MethodImplAttribute (MethodImplOptions.InternalCall)]
823 extern internal static bool LoadPermissions (Assembly a,
824 ref IntPtr minimum, ref int minLength,
825 ref IntPtr optional, ref int optLength,
826 ref IntPtr refused, ref int refLength);
828 // Support for SecurityAction.RequestMinimum, RequestOptional and RequestRefuse
829 private void LoadAssemblyPermissions ()
831 IntPtr minimum = IntPtr.Zero, optional = IntPtr.Zero, refused = IntPtr.Zero;
832 int minLength = 0, optLength = 0, refLength = 0;
833 if (LoadPermissions (this, ref minimum, ref minLength, ref optional,
834 ref optLength, ref refused, ref refLength)) {
836 // Note: no need to cache these permission sets as they will only be created once
837 // at assembly resolution time.
839 byte[] data = new byte [minLength];
840 Marshal.Copy (minimum, data, 0, minLength);
841 _minimum = SecurityManager.Decode (data);
844 byte[] data = new byte [optLength];
845 Marshal.Copy (optional, data, 0, optLength);
846 _optional = SecurityManager.Decode (data);
849 byte[] data = new byte [refLength];
850 Marshal.Copy (refused, data, 0, refLength);
851 _refuse = SecurityManager.Decode (data);