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 = value; }
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 string location = Location;
240 if (location != String.Empty) {
241 res = new FileStream [names.Length + 1];
242 res [0] = new FileStream (location, FileMode.Open, FileAccess.Read);
243 for (int i = 0; i < names.Length; ++i)
244 res [i + 1] = new FileStream (names [i], FileMode.Open, FileAccess.Read);
246 res = new FileStream [names.Length];
247 for (int i = 0; i < names.Length; ++i)
248 res [i] = new FileStream (names [i], FileMode.Open, FileAccess.Read);
253 public virtual FileStream GetFile (String name)
256 throw new ArgumentNullException ("name");
257 if (name.Length == 0)
258 throw new ArgumentException ("name");
260 string filename = (string)GetFilesInternal (name, true);
261 if (filename != null)
262 return new FileStream (filename, FileMode.Open, FileAccess.Read);
267 [MethodImplAttribute (MethodImplOptions.InternalCall)]
268 internal extern IntPtr GetManifestResourceInternal (String name, out int size, out Module module);
270 public virtual Stream GetManifestResourceStream (String name)
273 throw new ArgumentNullException ("name");
274 if (name.Length == 0)
275 throw new ArgumentException ("String cannot have zero length.",
278 ManifestResourceInfo info = GetManifestResourceInfo (name);
282 if (info.ReferencedAssembly != null)
283 return info.ReferencedAssembly.GetManifestResourceStream (name);
284 if ((info.FileName != null) && (info.ResourceLocation == 0)) {
287 throw new FileNotFoundException (info.FileName);
292 string filename = Path.Combine (Path.GetDirectoryName (Location),
294 return new FileStream (filename, FileMode.Open, FileAccess.Read);
299 IntPtr data = GetManifestResourceInternal (name, out size, out module);
300 if (data == (IntPtr) 0)
303 IntPtrStream stream = new IntPtrStream (data, size);
305 * The returned pointer points inside metadata, so
306 * we have to increase the refcount of the module, and decrease
307 * it when the stream is finalized.
309 stream.Closed += new EventHandler (new ResourceCloseHandler (module).OnClose);
314 public virtual Stream GetManifestResourceStream (Type type, String name)
321 throw new ArgumentNullException ("type");
325 if (ns == null || ns.Length == 0)
326 return GetManifestResourceStream (name);
328 return GetManifestResourceStream (ns + "." + name);
331 [MethodImplAttribute (MethodImplOptions.InternalCall)]
332 private extern Type[] GetTypes (bool exportedOnly);
334 public virtual Type[] GetTypes ()
336 return GetTypes (false);
339 public virtual Type[] GetExportedTypes ()
341 return GetTypes (true);
344 public virtual Type GetType (String name, Boolean throwOnError)
346 return GetType (name, throwOnError, false);
349 public virtual Type GetType (String name) {
350 return GetType (name, false, false);
353 [MethodImplAttribute (MethodImplOptions.InternalCall)]
354 internal extern Type InternalGetType (Module module, String name, Boolean throwOnError, Boolean ignoreCase);
356 public Type GetType (string name, bool throwOnError, bool ignoreCase)
359 throw new ArgumentNullException (name);
361 return InternalGetType (null, name, throwOnError, ignoreCase);
364 [MethodImplAttribute (MethodImplOptions.InternalCall)]
365 internal extern static void InternalGetAssemblyName (string assemblyFile, AssemblyName aname);
367 [MethodImplAttribute (MethodImplOptions.InternalCall)]
368 static extern void FillName (Assembly ass, AssemblyName aname);
370 [MonoTODO ("copiedName == true is not supported")]
371 public virtual AssemblyName GetName (Boolean copiedName)
373 // CodeBase, which is restricted, will be copied into the AssemblyName object so...
374 if (SecurityManager.SecurityEnabled) {
375 GetCodeBase (true); // this will ensure the Demand is made
377 return UnprotectedGetName ();
380 public virtual AssemblyName GetName ()
382 return GetName (false);
385 // the security runtime requires access to the assemblyname (e.g. to get the strongname)
386 internal virtual AssemblyName UnprotectedGetName ()
388 AssemblyName aname = new AssemblyName ();
389 FillName (this, aname);
393 public override string ToString ()
395 // note: ToString work without requiring CodeBase (so no checks are needed)
397 if (assemblyName != null)
400 AssemblyName aname = new AssemblyName ();
401 FillName (this, aname);
402 assemblyName = aname.ToString ();
407 public static String CreateQualifiedName (String assemblyName, String typeName)
409 return typeName + ", " + assemblyName;
412 public static Assembly GetAssembly (Type type)
415 return type.Assembly;
416 throw new ArgumentNullException ("type");
420 [MethodImplAttribute (MethodImplOptions.InternalCall)]
421 public static extern Assembly GetEntryAssembly();
423 public Assembly GetSatelliteAssembly (CultureInfo culture)
425 return GetSatelliteAssembly (culture, null);
428 public Assembly GetSatelliteAssembly (CultureInfo culture, Version version)
431 throw new ArgumentException ("culture");
433 AssemblyName aname = GetName (true);
435 aname.Version = version;
437 aname.CultureInfo = culture;
438 aname.Name = aname.Name + ".resources";
441 } catch (Exception) {
442 // Try the assembly directory
443 string fullName = Path.Combine (Path.GetDirectoryName (Location), Path.Combine (culture.Name, aname.Name + ".dll"));
444 return LoadFrom (fullName);
448 [MethodImplAttribute (MethodImplOptions.InternalCall)]
449 private extern static Assembly LoadFrom (String assemblyFile, bool refonly);
451 public static Assembly LoadFrom (String assemblyFile)
453 return LoadFrom (assemblyFile, false);
456 public static Assembly LoadFrom (String assemblyFile, Evidence securityEvidence)
458 Assembly a = LoadFrom (assemblyFile, false);
459 if ((a != null) && (securityEvidence != null)) {
460 // merge evidence (i.e. replace defaults with provided evidences)
461 a.Evidence.Merge (securityEvidence);
468 [MonoTODO("This overload is not currently implemented")]
469 // FIXME: What are we missing?
470 public static Assembly LoadFrom (String assemblyFile, Evidence securityEvidence, byte[] hashValue, AssemblyHashAlgorithm hashAlgorithm)
472 if (assemblyFile == null)
473 throw new ArgumentNullException ("assemblyFile");
474 if (assemblyFile == String.Empty)
475 throw new ArgumentException ("Name can't be the empty string", "assemblyFile");
476 throw new NotImplementedException ();
479 public static Assembly LoadFile (String path, Evidence securityEvidence)
482 throw new ArgumentNullException ("path");
483 if (path == String.Empty)
484 throw new ArgumentException ("Path can't be empty", "path");
485 // FIXME: Make this do the right thing
486 return LoadFrom (path, securityEvidence);
489 public static Assembly LoadFile (String path)
491 return LoadFile (path, null);
495 public static Assembly Load (String assemblyString)
497 return AppDomain.CurrentDomain.Load (assemblyString);
500 public static Assembly Load (String assemblyString, Evidence assemblySecurity)
502 return AppDomain.CurrentDomain.Load (assemblyString, assemblySecurity);
505 public static Assembly Load (AssemblyName assemblyRef)
507 return AppDomain.CurrentDomain.Load (assemblyRef);
510 public static Assembly Load (AssemblyName assemblyRef, Evidence assemblySecurity)
512 return AppDomain.CurrentDomain.Load (assemblyRef, assemblySecurity);
515 public static Assembly Load (Byte[] rawAssembly)
517 return AppDomain.CurrentDomain.Load (rawAssembly);
520 public static Assembly Load (Byte[] rawAssembly, Byte[] rawSymbolStore)
522 return AppDomain.CurrentDomain.Load (rawAssembly, rawSymbolStore);
525 public static Assembly Load (Byte[] rawAssembly, Byte[] rawSymbolStore,
526 Evidence securityEvidence)
528 return AppDomain.CurrentDomain.Load (rawAssembly, rawSymbolStore, securityEvidence);
531 #if NET_2_0 || BOOTSTRAP_NET_2_0
532 public static Assembly ReflectionOnlyLoad (byte[] rawAssembly)
534 return AppDomain.CurrentDomain.Load (rawAssembly, null, null, true);
537 public static Assembly ReflectionOnlyLoad (string assemblyName)
539 return AppDomain.CurrentDomain.Load (assemblyName, null, true);
542 public static Assembly ReflectionOnlyLoadFrom (string assemblyFile)
544 if (assemblyFile == null)
545 throw new ArgumentNullException ("assemblyFile");
547 return LoadFrom (assemblyFile, true);
554 public static Assembly LoadWithPartialName (string partialName)
556 return LoadWithPartialName (partialName, null);
559 [MonoTODO ("Not implemented")]
560 public Module LoadModule (string moduleName, byte [] rawModule)
562 throw new NotImplementedException ();
565 [MonoTODO ("Not implemented")]
566 public Module LoadModule (string moduleName, byte [] rawModule, byte [] rawSymbolStore)
568 throw new NotImplementedException ();
571 [MethodImplAttribute (MethodImplOptions.InternalCall)]
572 private static extern Assembly load_with_partial_name (string name, Evidence e);
577 public static Assembly LoadWithPartialName (string partialName, Evidence securityEvidence)
579 return LoadWithPartialName (partialName, securityEvidence, true);
583 * LAMESPEC: It is possible for this method to throw exceptions IF the name supplied
584 * is a valid gac name and contains filesystem entry charachters at the end of the name
585 * ie System/// will throw an exception. However ////System will not as that is canocolized
589 // FIXME: LoadWithPartialName must look cache (no CAS) or read from disk (CAS)
590 internal static Assembly LoadWithPartialName (string partialName, Evidence securityEvidence, bool oldBehavior)
593 throw new NotImplementedException ();
595 if (partialName == null)
596 throw new NullReferenceException ();
598 return load_with_partial_name (partialName, securityEvidence);
601 public Object CreateInstance (String typeName)
603 return CreateInstance (typeName, false);
606 public Object CreateInstance (String typeName, Boolean ignoreCase)
608 Type t = GetType (typeName, false, ignoreCase);
613 return Activator.CreateInstance (t);
614 } catch (InvalidOperationException) {
615 throw new ArgumentException ("It is illegal to invoke a method on a Type loaded via ReflectionOnly methods.");
619 public Object CreateInstance (String typeName, Boolean ignoreCase,
620 BindingFlags bindingAttr, Binder binder,
621 Object[] args, CultureInfo culture,
622 Object[] activationAttributes)
624 Type t = GetType (typeName, false, ignoreCase);
629 return Activator.CreateInstance (t, bindingAttr, binder, args, culture, activationAttributes);
630 } catch (InvalidOperationException) {
631 throw new ArgumentException ("It is illegal to invoke a method on a Type loaded via ReflectionOnly methods.");
635 public Module[] GetLoadedModules ()
637 return GetLoadedModules (false);
640 // FIXME: Currently, the two sets of modules are equal
641 public Module[] GetLoadedModules (bool getResourceModules)
643 return GetModules (getResourceModules);
646 public Module[] GetModules ()
648 return GetModules (false);
651 public Module GetModule (String name)
654 throw new ArgumentNullException ("name");
655 if (name.Length == 0)
656 throw new ArgumentException ("Name can't be empty");
658 Module[] modules = GetModules (true);
659 foreach (Module module in modules) {
660 if (module.ScopeName == name)
667 [MethodImplAttribute (MethodImplOptions.InternalCall)]
668 internal extern Module[] GetModulesInternal ();
670 public Module[] GetModules (bool getResourceModules) {
671 Module[] modules = GetModulesInternal ();
673 if (!getResourceModules) {
674 ArrayList result = new ArrayList (modules.Length);
675 foreach (Module m in modules)
676 if (!m.IsResource ())
678 return (Module[])result.ToArray (typeof (Module));
684 [MethodImplAttribute (MethodImplOptions.InternalCall)]
685 internal extern string[] GetNamespaces ();
687 [MethodImplAttribute (MethodImplOptions.InternalCall)]
688 public extern virtual String[] GetManifestResourceNames ();
690 [MethodImplAttribute (MethodImplOptions.InternalCall)]
691 public extern static Assembly GetExecutingAssembly ();
693 [MethodImplAttribute (MethodImplOptions.InternalCall)]
694 public extern static Assembly GetCallingAssembly ();
696 [MethodImplAttribute (MethodImplOptions.InternalCall)]
697 public extern AssemblyName[] GetReferencedAssemblies ();
699 [MethodImplAttribute (MethodImplOptions.InternalCall)]
700 private extern bool GetManifestResourceInfoInternal (String name, ManifestResourceInfo info);
702 public virtual ManifestResourceInfo GetManifestResourceInfo (String resourceName)
704 if (resourceName == null)
705 throw new ArgumentNullException ("resourceName");
706 if (resourceName.Length == 0)
707 throw new ArgumentException ("String cannot have zero length.");
708 ManifestResourceInfo result = new ManifestResourceInfo ();
709 bool found = GetManifestResourceInfoInternal (resourceName, result);
716 private class ResourceCloseHandler {
720 public ResourceCloseHandler (Module module) {
721 this.module = module;
724 public void OnClose (object sender, EventArgs e) {
725 // The module dtor will take care of things
731 // The following functions are only for the Mono Debugger.
734 [MethodImplAttribute (MethodImplOptions.InternalCall)]
735 internal static extern int MonoDebugger_GetMethodToken (MethodBase method);
738 [MonoTODO ("Always returns zero")]
740 public long HostContext {
745 public Module ManifestModule {
747 return GetManifestModule ();
751 internal virtual Module GetManifestModule () {
752 return GetManifestModuleInternal ();
755 [MethodImplAttribute (MethodImplOptions.InternalCall)]
756 internal extern Module GetManifestModuleInternal ();
759 public virtual extern bool ReflectionOnly {
760 [MethodImplAttribute (MethodImplOptions.InternalCall)]
765 // Code Access Security
767 internal void Resolve ()
770 // FIXME: As we (currently) delay the resolution until the first CAS
771 // Demand it's too late to evaluate the Minimum permission set as a
772 // condition to load the assembly into the AppDomain
773 LoadAssemblyPermissions ();
774 Evidence e = new Evidence (UnprotectedGetEvidence ()); // we need a copy to add PRE
775 e.AddHost (new PermissionRequestEvidence (_minimum, _optional, _refuse));
776 _granted = SecurityManager.ResolvePolicy (e,
777 _minimum, _optional, _refuse, out _denied);
781 internal PermissionSet GrantedPermissionSet {
783 if (_granted == null) {
784 if (SecurityManager.ResolvingPolicyLevel != null) {
785 if (SecurityManager.ResolvingPolicyLevel.IsFullTrustAssembly (this))
786 return DefaultPolicies.FullTrust;
788 return null; // we can't resolve during resolution
796 internal PermissionSet DeniedPermissionSet {
798 // yes we look for granted, as denied may be null
799 if (_granted == null) {
800 if (SecurityManager.ResolvingPolicyLevel != null) {
801 if (SecurityManager.ResolvingPolicyLevel.IsFullTrustAssembly (this))
804 return DefaultPolicies.FullTrust; // deny unrestricted
812 [MethodImplAttribute (MethodImplOptions.InternalCall)]
813 extern internal static bool LoadPermissions (Assembly a,
814 ref IntPtr minimum, ref int minLength,
815 ref IntPtr optional, ref int optLength,
816 ref IntPtr refused, ref int refLength);
818 // Support for SecurityAction.RequestMinimum, RequestOptional and RequestRefuse
819 private void LoadAssemblyPermissions ()
821 IntPtr minimum = IntPtr.Zero, optional = IntPtr.Zero, refused = IntPtr.Zero;
822 int minLength = 0, optLength = 0, refLength = 0;
823 if (LoadPermissions (this, ref minimum, ref minLength, ref optional,
824 ref optLength, ref refused, ref refLength)) {
826 // Note: no need to cache these permission sets as they will only be created once
827 // at assembly resolution time.
829 byte[] data = new byte [minLength];
830 Marshal.Copy (minimum, data, 0, minLength);
831 _minimum = SecurityManager.Decode (data);
834 byte[] data = new byte [optLength];
835 Marshal.Copy (optional, data, 0, optLength);
836 _optional = SecurityManager.Decode (data);
839 byte[] data = new byte [refLength];
840 Marshal.Copy (refused, data, 0, refLength);
841 _refuse = SecurityManager.Decode (data);