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 private IntPtr _mono_assembly;
62 private ResolveEventHolder resolve_event_holder;
63 private Evidence _evidence;
64 internal PermissionSet _minimum; // for SecurityAction.RequestMinimum
65 internal PermissionSet _optional; // for SecurityAction.RequestOptional
66 internal PermissionSet _refuse; // for SecurityAction.RequestRefuse
67 private PermissionSet _granted; // for the resolved assembly granted permissions
68 private PermissionSet _denied; // for the resolved assembly denied permissions
69 private bool fromByteArray;
70 private string assemblyName;
74 resolve_event_holder = new ResolveEventHolder ();
78 // We can't store the event directly in this class, since the
79 // compiler would silently insert the fields before _mono_assembly
81 public event ModuleResolveEventHandler ModuleResolve {
82 [SecurityPermission (SecurityAction.LinkDemand, ControlAppDomain = true)]
84 resolve_event_holder.ModuleResolve += value;
86 [SecurityPermission (SecurityAction.LinkDemand, ControlAppDomain = true)]
88 resolve_event_holder.ModuleResolve -= value;
92 [MethodImplAttribute (MethodImplOptions.InternalCall)]
93 private extern string get_code_base (bool escaped);
95 [MethodImplAttribute (MethodImplOptions.InternalCall)]
96 private extern string get_location ();
98 [MethodImplAttribute (MethodImplOptions.InternalCall)]
99 private extern string InternalImageRuntimeVersion ();
101 [MethodImplAttribute (MethodImplOptions.InternalCall)]
102 private extern bool get_global_assembly_cache ();
104 // SECURITY: this should be the only caller to icall get_code_base
105 private string GetCodeBase (bool escaped)
107 string cb = get_code_base (escaped);
108 if (SecurityManager.SecurityEnabled) {
109 // we cannot divulge local file informations
110 if (String.Compare ("FILE://", 0, cb, 0, 7, true, CultureInfo.InvariantCulture) == 0) {
111 string file = cb.Substring (7);
112 new FileIOPermission (FileIOPermissionAccess.PathDiscovery, file).Demand ();
118 public virtual string CodeBase {
119 get { return GetCodeBase (false); }
122 public virtual string EscapedCodeBase {
123 get { return GetCodeBase (true); }
126 public virtual string FullName {
129 // FIXME: This is wrong, but it gets us going
130 // in the compiler for now
136 public virtual extern MethodInfo EntryPoint {
137 [MethodImplAttribute (MethodImplOptions.InternalCall)]
141 public virtual Evidence Evidence {
142 [SecurityPermission (SecurityAction.Demand, ControlEvidence = true)]
143 get { return UnprotectedGetEvidence (); }
146 // note: the security runtime requires evidences but may be unable to do so...
147 internal Evidence UnprotectedGetEvidence ()
149 // if the host (runtime) hasn't provided it's own evidence...
150 if (_evidence == null) {
151 // ... we will provide our own
153 _evidence = Evidence.GetDefaultHostEvidence (this);
159 public bool GlobalAssemblyCache {
161 return get_global_assembly_cache ();
165 internal bool FromByteArray {
166 set { fromByteArray = true; }
169 public virtual String Location {
174 string loc = get_location ();
175 if ((loc != String.Empty) && SecurityManager.SecurityEnabled) {
176 // we cannot divulge local file informations
177 new FileIOPermission (FileIOPermissionAccess.PathDiscovery, loc).Demand ();
185 public virtual string ImageRuntimeVersion {
187 return InternalImageRuntimeVersion ();
192 [SecurityPermission (SecurityAction.LinkDemand, SerializationFormatter = true)]
193 public virtual void GetObjectData (SerializationInfo info, StreamingContext context)
196 throw new ArgumentNullException ("info");
198 UnitySerializationHolder.GetAssemblyData (this, info, context);
202 public new Type GetType ()
204 return base.GetType ();
208 public virtual bool IsDefined (Type attributeType, bool inherit)
210 return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
213 public virtual object [] GetCustomAttributes (bool inherit)
215 return MonoCustomAttrs.GetCustomAttributes (this, inherit);
218 public virtual object [] GetCustomAttributes (Type attributeType, bool inherit)
220 return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
223 [MethodImplAttribute (MethodImplOptions.InternalCall)]
224 private extern object GetFilesInternal (String name, bool getResourceModules);
226 public virtual FileStream[] GetFiles ()
228 return GetFiles (false);
231 public virtual FileStream [] GetFiles (bool getResourceModules)
233 string[] names = (string[]) GetFilesInternal (null, getResourceModules);
235 return new FileStream [0];
237 FileStream[] res = new FileStream [names.Length];
238 for (int i = 0; i < names.Length; ++i)
239 res [i] = new FileStream (names [i], FileMode.Open, FileAccess.Read);
243 public virtual FileStream GetFile (String name)
246 throw new ArgumentNullException ("name");
247 if (name.Length == 0)
248 throw new ArgumentException ("name");
250 string filename = (string)GetFilesInternal (name, true);
251 if (filename != null)
252 return new FileStream (filename, FileMode.Open, FileAccess.Read);
257 [MethodImplAttribute (MethodImplOptions.InternalCall)]
258 internal extern IntPtr GetManifestResourceInternal (String name, out int size, out Module module);
260 public virtual Stream GetManifestResourceStream (String name)
263 throw new ArgumentNullException ("name");
265 throw new ArgumentException ("name cannot have zero length.");
267 ManifestResourceInfo info = GetManifestResourceInfo (name);
271 if (info.ReferencedAssembly != null)
272 return info.ReferencedAssembly.GetManifestResourceStream (name);
273 if ((info.FileName != null) && (info.ResourceLocation == 0)) {
276 throw new FileNotFoundException (info.FileName);
281 string filename = Path.Combine (Path.GetDirectoryName (Location),
283 return new FileStream (filename, FileMode.Open, FileAccess.Read);
288 IntPtr data = GetManifestResourceInternal (name, out size, out module);
289 if (data == (IntPtr) 0)
292 IntPtrStream stream = new IntPtrStream (data, size);
294 * The returned pointer points inside metadata, so
295 * we have to increase the refcount of the module, and decrease
296 * it when the stream is finalized.
298 stream.Closed += new EventHandler (new ResourceCloseHandler (module).OnClose);
303 public virtual Stream GetManifestResourceStream (Type type, String name)
311 if ((ns == null) || (ns == ""))
312 return GetManifestResourceStream (name);
314 return GetManifestResourceStream (ns + "." + name);
317 [MethodImplAttribute (MethodImplOptions.InternalCall)]
318 private extern Type[] GetTypes (bool exportedOnly);
320 public virtual Type[] GetTypes ()
322 return GetTypes (false);
325 public virtual Type[] GetExportedTypes ()
327 return GetTypes (true);
330 public virtual Type GetType (String name, Boolean throwOnError)
332 return GetType (name, throwOnError, false);
335 public virtual Type GetType (String name) {
336 return GetType (name, false, false);
339 [MethodImplAttribute (MethodImplOptions.InternalCall)]
340 internal extern Type InternalGetType (Module module, String name, Boolean throwOnError, Boolean ignoreCase);
342 public Type GetType (string name, bool throwOnError, bool ignoreCase)
345 throw new ArgumentNullException (name);
347 return InternalGetType (null, name, throwOnError, ignoreCase);
350 [MethodImplAttribute (MethodImplOptions.InternalCall)]
351 internal extern static void InternalGetAssemblyName (string assemblyFile, AssemblyName aname);
353 [MethodImplAttribute (MethodImplOptions.InternalCall)]
354 static extern void FillName (Assembly ass, AssemblyName aname);
356 [MonoTODO ("copiedName == true is not supported")]
357 public virtual AssemblyName GetName (Boolean copiedName)
359 // CodeBase, which is restricted, will be copied into the AssemblyName object so...
360 if (SecurityManager.SecurityEnabled) {
361 GetCodeBase (true); // this will ensure the Demand is made
363 return UnprotectedGetName ();
366 public virtual AssemblyName GetName ()
368 return GetName (false);
371 // the security runtime requires access to the assemblyname (e.g. to get the strongname)
372 internal virtual AssemblyName UnprotectedGetName ()
374 AssemblyName aname = new AssemblyName ();
375 FillName (this, aname);
379 public override string ToString ()
381 // note: ToString work without requiring CodeBase (so no checks are needed)
383 if (assemblyName != null)
386 AssemblyName aname = new AssemblyName ();
387 FillName (this, aname);
388 assemblyName = aname.ToString ();
393 public static String CreateQualifiedName (String assemblyName, String typeName)
395 return typeName + ", " + assemblyName;
398 public static Assembly GetAssembly (Type type)
401 return type.Assembly;
402 throw new ArgumentNullException ("type");
406 [MethodImplAttribute (MethodImplOptions.InternalCall)]
407 public static extern Assembly GetEntryAssembly();
409 public Assembly GetSatelliteAssembly (CultureInfo culture)
411 return GetSatelliteAssembly (culture, null);
414 public Assembly GetSatelliteAssembly (CultureInfo culture, Version version)
417 throw new ArgumentException ("culture");
419 AssemblyName aname = GetName (true);
421 aname.Version = version;
423 aname.CultureInfo = culture;
424 aname.Name = aname.Name + ".resources";
428 [MethodImplAttribute (MethodImplOptions.InternalCall)]
429 private extern static Assembly LoadFrom (String assemblyFile, bool refonly);
431 public static Assembly LoadFrom (String assemblyFile)
433 return LoadFrom (assemblyFile, false);
436 public static Assembly LoadFrom (String assemblyFile, Evidence securityEvidence)
438 Assembly a = LoadFrom (assemblyFile, false);
439 if ((a != null) && (securityEvidence != null)) {
440 // merge evidence (i.e. replace defaults with provided evidences)
441 a.Evidence.Merge (securityEvidence);
448 [MonoTODO("This overload is not currently implemented")]
449 // FIXME: What are we missing?
450 public static Assembly LoadFrom (String assemblyFile, Evidence securityEvidence, byte[] hashValue, AssemblyHashAlgorithm hashAlgorithm)
452 if (assemblyFile == null)
453 throw new ArgumentNullException ("assemblyFile");
454 if (assemblyFile == String.Empty)
455 throw new ArgumentException ("Name can't be the empty string", "assemblyFile");
456 throw new NotImplementedException ();
459 public static Assembly LoadFile (String path, Evidence securityEvidence)
462 throw new ArgumentNullException ("path");
463 if (path == String.Empty)
464 throw new ArgumentException ("Path can't be empty", "path");
465 // FIXME: Make this do the right thing
466 return LoadFrom (path, securityEvidence);
469 public static Assembly LoadFile (String path)
471 return LoadFile (path, null);
475 public static Assembly Load (String assemblyString)
477 return AppDomain.CurrentDomain.Load (assemblyString);
480 public static Assembly Load (String assemblyString, Evidence assemblySecurity)
482 return AppDomain.CurrentDomain.Load (assemblyString, assemblySecurity);
485 public static Assembly Load (AssemblyName assemblyRef)
487 return AppDomain.CurrentDomain.Load (assemblyRef);
490 public static Assembly Load (AssemblyName assemblyRef, Evidence assemblySecurity)
492 return AppDomain.CurrentDomain.Load (assemblyRef, assemblySecurity);
495 public static Assembly Load (Byte[] rawAssembly)
497 return AppDomain.CurrentDomain.Load (rawAssembly);
500 public static Assembly Load (Byte[] rawAssembly, Byte[] rawSymbolStore)
502 return AppDomain.CurrentDomain.Load (rawAssembly, rawSymbolStore);
505 public static Assembly Load (Byte[] rawAssembly, Byte[] rawSymbolStore,
506 Evidence securityEvidence)
508 return AppDomain.CurrentDomain.Load (rawAssembly, rawSymbolStore, securityEvidence);
512 public static Assembly ReflectionOnlyLoad (byte[] rawAssembly)
514 return AppDomain.CurrentDomain.Load (rawAssembly, null, null, true);
517 public static Assembly ReflectionOnlyLoad (string assemblyName)
519 return AppDomain.CurrentDomain.Load (assemblyName, null, true);
522 public static Assembly ReflectionOnlyLoadFrom (string assemblyFile)
524 if (assemblyFile == null)
525 throw new ArgumentNullException ("assemblyFile");
527 return LoadFrom (assemblyFile, true);
534 public static Assembly LoadWithPartialName (string partialName)
536 return LoadWithPartialName (partialName, null);
539 [MonoTODO ("Not implemented")]
540 public Module LoadModule (string moduleName, byte [] rawModule)
542 throw new NotImplementedException ();
545 [MonoTODO ("Not implemented")]
546 public Module LoadModule (string moduleName, byte [] rawModule, byte [] rawSymbolStore)
548 throw new NotImplementedException ();
551 [MethodImplAttribute (MethodImplOptions.InternalCall)]
552 private static extern Assembly load_with_partial_name (string name, Evidence e);
557 public static Assembly LoadWithPartialName (string partialName, Evidence securityEvidence)
559 return LoadWithPartialName (partialName, securityEvidence, true);
563 * LAMESPEC: It is possible for this method to throw exceptions IF the name supplied
564 * is a valid gac name and contains filesystem entry charachters at the end of the name
565 * ie System/// will throw an exception. However ////System will not as that is canocolized
569 // FIXME: LoadWithPartialName must look cache (no CAS) or read from disk (CAS)
570 internal static Assembly LoadWithPartialName (string partialName, Evidence securityEvidence, bool oldBehavior)
573 throw new NotImplementedException ();
575 if (partialName == null)
576 throw new NullReferenceException ();
578 return load_with_partial_name (partialName, securityEvidence);
581 public Object CreateInstance (String typeName)
583 return CreateInstance (typeName, false);
586 public Object CreateInstance (String typeName, Boolean ignoreCase)
588 Type t = GetType (typeName, false, ignoreCase);
593 return Activator.CreateInstance (t);
594 } catch (InvalidOperationException) {
595 throw new ArgumentException ("It is illegal to invoke a method on a Type loaded via ReflectionOnly methods.");
599 public Object CreateInstance (String typeName, Boolean ignoreCase,
600 BindingFlags bindingAttr, Binder binder,
601 Object[] args, CultureInfo culture,
602 Object[] activationAttributes)
604 Type t = GetType (typeName, false, ignoreCase);
609 return Activator.CreateInstance (t, bindingAttr, binder, args, culture, activationAttributes);
610 } catch (InvalidOperationException) {
611 throw new ArgumentException ("It is illegal to invoke a method on a Type loaded via ReflectionOnly methods.");
615 public Module[] GetLoadedModules ()
617 return GetLoadedModules (false);
620 // FIXME: Currently, the two sets of modules are equal
621 public Module[] GetLoadedModules (bool getResourceModules)
623 return GetModules (getResourceModules);
626 public Module[] GetModules ()
628 return GetModules (false);
631 public Module GetModule (String name)
634 throw new ArgumentNullException ("name");
636 throw new ArgumentException ("Name can't be empty");
638 Module[] modules = GetModules (true);
639 foreach (Module module in modules) {
640 if (module.ScopeName == name)
647 [MethodImplAttribute (MethodImplOptions.InternalCall)]
648 internal extern Module[] GetModulesInternal ();
650 public Module[] GetModules (bool getResourceModules) {
651 Module[] modules = GetModulesInternal ();
653 if (!getResourceModules) {
654 ArrayList result = new ArrayList (modules.Length);
655 foreach (Module m in modules)
656 if (!m.IsResource ())
658 return (Module[])result.ToArray (typeof (Module));
664 [MethodImplAttribute (MethodImplOptions.InternalCall)]
665 internal extern string[] GetNamespaces ();
667 [MethodImplAttribute (MethodImplOptions.InternalCall)]
668 public extern virtual String[] GetManifestResourceNames ();
670 [MethodImplAttribute (MethodImplOptions.InternalCall)]
671 public extern static Assembly GetExecutingAssembly ();
673 [MethodImplAttribute (MethodImplOptions.InternalCall)]
674 public extern static Assembly GetCallingAssembly ();
676 [MethodImplAttribute (MethodImplOptions.InternalCall)]
677 public extern AssemblyName[] GetReferencedAssemblies ();
679 [MethodImplAttribute (MethodImplOptions.InternalCall)]
680 private extern bool GetManifestResourceInfoInternal (String name, ManifestResourceInfo info);
682 public virtual ManifestResourceInfo GetManifestResourceInfo (String resourceName)
684 if (resourceName == null)
685 throw new ArgumentNullException ("resourceName");
686 if (resourceName == "")
687 throw new ArgumentException ("String cannot have zero length.");
688 ManifestResourceInfo result = new ManifestResourceInfo ();
689 bool found = GetManifestResourceInfoInternal (resourceName, result);
696 private class ResourceCloseHandler {
700 public ResourceCloseHandler (Module module) {
701 this.module = module;
704 public void OnClose (object sender, EventArgs e) {
705 // The module dtor will take care of things
711 // The following functions are only for the Mono Debugger.
714 [MethodImplAttribute (MethodImplOptions.InternalCall)]
715 internal static extern int MonoDebugger_GetMethodToken (MethodBase method);
718 [MonoTODO ("Always returns zero")]
720 public long HostContext {
725 public extern Module ManifestModule {
726 [MethodImplAttribute (MethodImplOptions.InternalCall)]
731 public virtual extern bool ReflectionOnly {
732 [MethodImplAttribute (MethodImplOptions.InternalCall)]
737 // Code Access Security
739 internal void Resolve ()
742 // FIXME: As we (currently) delay the resolution until the first CAS
743 // Demand it's too late to evaluate the Minimum permission set as a
744 // condition to load the assembly into the AppDomain
745 LoadAssemblyPermissions ();
746 Evidence e = new Evidence (UnprotectedGetEvidence ()); // we need a copy to add PRE
747 e.AddHost (new PermissionRequestEvidence (_minimum, _optional, _refuse));
748 _granted = SecurityManager.ResolvePolicy (e,
749 _minimum, _optional, _refuse, out _denied);
753 internal PermissionSet GrantedPermissionSet {
755 if (_granted == null) {
756 if (SecurityManager.ResolvingPolicyLevel != null) {
757 if (SecurityManager.ResolvingPolicyLevel.IsFullTrustAssembly (this))
758 return DefaultPolicies.FullTrust;
760 return null; // we can't resolve during resolution
768 internal PermissionSet DeniedPermissionSet {
770 // yes we look for granted, as denied may be null
771 if (_granted == null) {
772 if (SecurityManager.ResolvingPolicyLevel != null) {
773 if (SecurityManager.ResolvingPolicyLevel.IsFullTrustAssembly (this))
776 return DefaultPolicies.FullTrust; // deny unrestricted
784 [MethodImplAttribute (MethodImplOptions.InternalCall)]
785 extern internal static bool LoadPermissions (Assembly a,
786 ref IntPtr minimum, ref int minLength,
787 ref IntPtr optional, ref int optLength,
788 ref IntPtr refused, ref int refLength);
790 // Support for SecurityAction.RequestMinimum, RequestOptional and RequestRefuse
791 private void LoadAssemblyPermissions ()
793 IntPtr minimum = IntPtr.Zero, optional = IntPtr.Zero, refused = IntPtr.Zero;
794 int minLength = 0, optLength = 0, refLength = 0;
795 if (LoadPermissions (this, ref minimum, ref minLength, ref optional,
796 ref optLength, ref refused, ref refLength)) {
798 // Note: no need to cache these permission sets as they will only be created once
799 // at assembly resolution time.
801 byte[] data = new byte [minLength];
802 Marshal.Copy (minimum, data, 0, minLength);
803 _minimum = SecurityManager.Decode (data);
806 byte[] data = new byte [optLength];
807 Marshal.Copy (optional, data, 0, optLength);
808 _optional = SecurityManager.Decode (data);
811 byte[] data = new byte [refLength];
812 Marshal.Copy (refused, data, 0, refLength);
813 _refuse = SecurityManager.Decode (data);