802414cc09158ba555d853256a9491765e03b0bb
[mono.git] / mcs / class / referencesource / mscorlib / system / reflection / assemblyname.cs
1 // ==++==
2 // 
3 //   Copyright (c) Microsoft Corporation.  All rights reserved.
4 // 
5 // ==--==
6 /*============================================================
7 **
8 ** File:    AssemblyName
9 ** 
10 ** <OWNER>Microsoft</OWNER>
11 ** <OWNER>Microsoft</OWNER>
12 **
13 **
14 ** Purpose: Used for binding and retrieving info about an assembly
15 **
16 **
17 ===========================================================*/
18 namespace System.Reflection {
19     using System;
20     using System.IO;
21     using System.Configuration.Assemblies;
22     using System.Runtime.CompilerServices;
23     using CultureInfo = System.Globalization.CultureInfo;
24     using System.Runtime.Serialization;
25     using System.Security.Permissions;
26     using System.Runtime.InteropServices;
27     using System.Runtime.Versioning;
28     using System.Diagnostics.Contracts;
29
30     [Serializable]
31     [ClassInterface(ClassInterfaceType.None)]
32     [ComDefaultInterface(typeof(_AssemblyName))]
33 [System.Runtime.InteropServices.ComVisible(true)]
34     public sealed class AssemblyName : _AssemblyName, ICloneable, ISerializable, IDeserializationCallback
35     {
36         //
37         // READ ME
38         // If you modify any of these fields, you must also update the 
39         // AssemblyBaseObject structure in object.h
40         //
41         private String          _Name;                  // Name
42         private byte[]          _PublicKey;
43         private byte[]          _PublicKeyToken;
44         private CultureInfo     _CultureInfo;
45         private String          _CodeBase;              // Potential location to get the file
46         private Version         _Version;
47         
48         private StrongNameKeyPair            _StrongNameKeyPair;
49
50 #if FEATURE_SERIALIZATION
51         private SerializationInfo m_siInfo; //A temporary variable which we need during deserialization.
52 #endif
53
54         private byte[]                _HashForControl;
55         private AssemblyHashAlgorithm _HashAlgorithm;
56         private AssemblyHashAlgorithm _HashAlgorithmForControl;
57
58         private AssemblyVersionCompatibility _VersionCompatibility;
59         private AssemblyNameFlags            _Flags;
60        
61         public AssemblyName()
62         { 
63             _HashAlgorithm = AssemblyHashAlgorithm.None;
64             _VersionCompatibility = AssemblyVersionCompatibility.SameMachine;
65             _Flags = AssemblyNameFlags.None;
66         }
67     
68         // Set and get the name of the assembly. If this is a weak Name
69         // then it optionally contains a site. For strong assembly names, 
70         // the name partitions up the strong name's namespace
71         public String Name
72         {
73             get { return _Name; }
74             set { _Name = value; }
75         }
76
77         public Version Version
78         {
79             get { 
80                 return _Version;
81             }
82             set { 
83                 _Version = value;
84             }
85         }
86
87         // Locales, internally the LCID is used for the match.
88         public CultureInfo CultureInfo
89         {
90             get {
91                 return _CultureInfo;
92             }
93             set { 
94                 _CultureInfo = value; 
95             }
96         }
97
98         public String CultureName
99         {
100             get {
101                 return (_CultureInfo == null) ? null : _CultureInfo.Name;
102             }
103             set {
104                 _CultureInfo = (value == null) ? null : new CultureInfo(value);
105             }
106         }
107     
108         public String CodeBase
109         {
110             #if FEATURE_CORECLR
111             [System.Security.SecurityCritical] // auto-generated
112             #endif
113             [ResourceExposure(ResourceScope.Machine)]
114             get { return _CodeBase; }
115             #if FEATURE_CORECLR
116             [System.Security.SecurityCritical] // auto-generated
117             #endif
118             [ResourceExposure(ResourceScope.Machine)]
119             set { _CodeBase = value; }
120         }
121     
122         public String EscapedCodeBase
123         {
124             [System.Security.SecuritySafeCritical]  // auto-generated
125             [ResourceExposure(ResourceScope.Machine)]
126             [ResourceConsumption(ResourceScope.Machine)]
127             get
128             {
129                 if (_CodeBase == null)
130                     return null;
131                 else
132                     return EscapeCodeBase(_CodeBase);
133             }
134         }
135     
136         public ProcessorArchitecture  ProcessorArchitecture
137         {
138             get {
139                 int x = (((int)_Flags) & 0x70) >> 4;
140                 if(x > 5) 
141                     x = 0;
142                 return (ProcessorArchitecture)x;
143             }
144             set {
145                 int x = ((int)value) & 0x07;
146                 if(x <= 5) {
147                     _Flags = (AssemblyNameFlags)((int)_Flags & 0xFFFFFF0F);
148                     _Flags |= (AssemblyNameFlags)(x << 4);
149                 }
150             }
151         }
152
153         [System.Runtime.InteropServices.ComVisible(false)]
154         public AssemblyContentType ContentType
155         {
156             get
157             {
158                 int x = (((int)_Flags) & 0x00000E00) >> 9;
159                 if (x > 1)
160                     x = 0;
161                 return (AssemblyContentType)x;
162             }
163             set
164             {
165                 int x = ((int)value) & 0x07;
166                 if (x <= 1)
167                 {
168                     _Flags = (AssemblyNameFlags)((int)_Flags & 0xFFFFF1FF);
169                     _Flags |= (AssemblyNameFlags)(x << 9);
170                 }
171             }
172         }
173          
174         
175
176         // Make a copy of this assembly name.
177         public Object Clone()
178         {
179             AssemblyName name = new AssemblyName();
180             name.Init(_Name,
181                       _PublicKey,
182                       _PublicKeyToken,
183                       _Version,
184                       _CultureInfo,
185                       _HashAlgorithm,
186                       _VersionCompatibility,
187                       _CodeBase,
188                       _Flags,
189                       _StrongNameKeyPair);
190             name._HashForControl=_HashForControl;
191             name._HashAlgorithmForControl=_HashAlgorithmForControl;
192             return name;
193         }
194
195         /*
196          * Get the AssemblyName for a given file. This will only work
197          * if the file contains an assembly manifest. This method causes
198          * the file to be opened and closed.
199          */
200         [System.Security.SecuritySafeCritical]  // auto-generated
201         [ResourceExposure(ResourceScope.None)]
202         [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
203         static public AssemblyName GetAssemblyName(String assemblyFile)
204         {
205             if(assemblyFile == null)
206                 throw new ArgumentNullException("assemblyFile");
207             Contract.EndContractBlock();
208
209             // Assembly.GetNameInternal() will not demand path discovery 
210             //  permission, so do that first.
211             String fullPath = Path.GetFullPathInternal(assemblyFile);
212             new FileIOPermission( FileIOPermissionAccess.PathDiscovery, fullPath ).Demand();
213             return nGetFileInformation(fullPath);
214         }
215     
216         internal void SetHashControl(byte[] hash, AssemblyHashAlgorithm hashAlgorithm)
217         {
218              _HashForControl=hash;
219              _HashAlgorithmForControl=hashAlgorithm;
220         }
221
222         // The public key that is used to verify an assemblies
223         // inclusion into the namespace. If the public key associated
224         // with the namespace cannot verify the assembly the assembly
225         // will fail to load.
226         public byte[] GetPublicKey()
227         {
228 #if FEATURE_LEGACYNETCF
229             if (CompatibilitySwitches.IsAppEarlierThanWindowsPhone8 && _PublicKey == null)
230                 return EmptyArray<Byte>.Value;
231             else
232 #endif
233                 return _PublicKey;
234         }
235
236         public void SetPublicKey(byte[] publicKey)
237         {
238             _PublicKey = publicKey;
239
240             if (publicKey == null)
241                 _Flags &= ~AssemblyNameFlags.PublicKey;
242             else
243                 _Flags |= AssemblyNameFlags.PublicKey;
244         }
245
246         // The compressed version of the public key formed from a truncated hash.
247         // Will throw a SecurityException if _PublicKey is invalid
248         [System.Security.SecuritySafeCritical]  // auto-generated
249         public byte[] GetPublicKeyToken()
250         {
251             if (_PublicKeyToken == null)
252                 _PublicKeyToken = nGetPublicKeyToken();
253             return _PublicKeyToken;
254         }
255
256         public void SetPublicKeyToken(byte[] publicKeyToken)
257         {
258             _PublicKeyToken = publicKeyToken;
259         }
260
261         // Flags modifying the name. So far the only flag is PublicKey, which
262         // indicates that a full public key and not the compressed version is
263         // present. 
264         // Processor Architecture flags are set only through ProcessorArchitecture
265         // property and can't be set or retrieved directly
266         // Content Type flags are set only through ContentType property and can't be 
267         // set or retrieved directly
268         public AssemblyNameFlags Flags
269         {
270             get { return (AssemblyNameFlags)((uint)_Flags & 0xFFFFF10F); }
271             set {
272                 _Flags &= unchecked((AssemblyNameFlags)0x00000EF0);
273                 _Flags |= (value & unchecked((AssemblyNameFlags)0xFFFFF10F));
274             }
275         }
276
277         public AssemblyHashAlgorithm HashAlgorithm
278         {
279             get { return _HashAlgorithm; }
280             set { _HashAlgorithm = value; }
281         }
282         
283         public AssemblyVersionCompatibility VersionCompatibility
284         {
285             get { return _VersionCompatibility; }
286             set { _VersionCompatibility = value; }
287         }
288
289         public StrongNameKeyPair KeyPair
290         {
291             get { return _StrongNameKeyPair; }
292             set { _StrongNameKeyPair = value; }
293         }
294        
295         public String FullName
296         {
297             [System.Security.SecuritySafeCritical]  // auto-generated
298             get {
299                 String name = nToString();
300                 if (CompatibilitySwitches.IsAppEarlierThanWindowsPhone8 && string.IsNullOrEmpty(name))
301                     return base.ToString();
302
303                 return name;
304             }
305         }
306     
307         // Returns the stringized version of the assembly name.
308         public override String ToString()
309         {
310             String s = FullName;
311             if(s == null) 
312                 return base.ToString();
313             else 
314                 return s;
315         }
316
317 #if FEATURE_SERIALIZATION
318         [System.Security.SecurityCritical]  // auto-generated_required
319         public void GetObjectData(SerializationInfo info, StreamingContext context)
320         {
321             if (info == null)
322                 throw new ArgumentNullException("info");
323             Contract.EndContractBlock();
324
325             //Allocate the serialization info and serialize our static data.
326             info.AddValue("_Name", _Name);
327             info.AddValue("_PublicKey", _PublicKey, typeof(byte[]));
328             info.AddValue("_PublicKeyToken", _PublicKeyToken, typeof(byte[]));
329 #if FEATURE_USE_LCID            
330             info.AddValue("_CultureInfo", (_CultureInfo == null) ? -1 :_CultureInfo.LCID);
331 #endif
332             info.AddValue("_CodeBase", _CodeBase);
333             info.AddValue("_Version", _Version);
334             info.AddValue("_HashAlgorithm", _HashAlgorithm, typeof(AssemblyHashAlgorithm));
335             info.AddValue("_HashAlgorithmForControl", _HashAlgorithmForControl, typeof(AssemblyHashAlgorithm));
336             info.AddValue("_StrongNameKeyPair", _StrongNameKeyPair, typeof(StrongNameKeyPair));
337             info.AddValue("_VersionCompatibility", _VersionCompatibility, typeof(AssemblyVersionCompatibility));
338             info.AddValue("_Flags", _Flags, typeof(AssemblyNameFlags));
339             info.AddValue("_HashForControl",_HashForControl,typeof(byte[]));
340        }
341
342         public void OnDeserialization(Object sender)
343         {
344             // Deserialization has already been performed
345             if (m_siInfo == null)
346                 return;
347
348             _Name = m_siInfo.GetString("_Name");
349             _PublicKey = (byte[]) m_siInfo.GetValue("_PublicKey", typeof(byte[]));
350             _PublicKeyToken = (byte[]) m_siInfo.GetValue("_PublicKeyToken", typeof(byte[]));
351 #if FEATURE_USE_LCID
352             int lcid = (int)m_siInfo.GetInt32("_CultureInfo");
353             if (lcid != -1)
354                 _CultureInfo = new CultureInfo(lcid);
355 #endif            
356
357             _CodeBase = m_siInfo.GetString("_CodeBase");
358             _Version = (Version) m_siInfo.GetValue("_Version", typeof(Version));
359             _HashAlgorithm = (AssemblyHashAlgorithm) m_siInfo.GetValue("_HashAlgorithm", typeof(AssemblyHashAlgorithm));
360             _StrongNameKeyPair = (StrongNameKeyPair) m_siInfo.GetValue("_StrongNameKeyPair", typeof(StrongNameKeyPair));
361             _VersionCompatibility = (AssemblyVersionCompatibility)m_siInfo.GetValue("_VersionCompatibility", typeof(AssemblyVersionCompatibility));
362             _Flags = (AssemblyNameFlags) m_siInfo.GetValue("_Flags", typeof(AssemblyNameFlags));
363
364             try {
365                 _HashAlgorithmForControl = (AssemblyHashAlgorithm) m_siInfo.GetValue("_HashAlgorithmForControl", typeof(AssemblyHashAlgorithm));
366                 _HashForControl = (byte[]) m_siInfo.GetValue("_HashForControl", typeof(byte[]));    
367             }
368             catch (SerializationException) { // RTM did not have these defined
369                 _HashAlgorithmForControl = AssemblyHashAlgorithm.None;
370                 _HashForControl = null;
371             }
372
373             m_siInfo = null;
374         }
375
376         // Constructs a new AssemblyName during deserialization.
377         internal AssemblyName(SerializationInfo info, StreamingContext context)
378         {
379             //The graph is not valid until OnDeserialization() has been called.
380             m_siInfo = info; 
381         }
382 #endif // FEATURE_SERIALIZATION
383
384         [System.Security.SecuritySafeCritical]  // auto-generated
385         public AssemblyName(String assemblyName)
386         {
387             if (assemblyName == null)
388                 throw new ArgumentNullException("assemblyName");
389             Contract.EndContractBlock();
390             if ((assemblyName.Length == 0) ||
391                 (assemblyName[0] == '\0'))
392                 throw new ArgumentException(Environment.GetResourceString("Format_StringZeroLength"));
393
394             _Name = assemblyName;
395             nInit();
396         }
397
398         [System.Security.SecuritySafeCritical]  // auto-generated
399         [ResourceExposure(ResourceScope.None)]
400         static public bool ReferenceMatchesDefinition(AssemblyName reference,
401                                                              AssemblyName definition)
402         {
403             // Optimization for common use case
404             if (Object.ReferenceEquals(reference, definition))
405             {
406                 return true;
407             }
408             return ReferenceMatchesDefinitionInternal(reference, definition, true);
409         }
410
411         
412         /// "parse" tells us to parse the simple name of the assembly as if it was the full name
413         /// almost never the right thing to do, but needed for compat
414         [System.Security.SecuritySafeCritical]  // auto-generated
415         [ResourceExposure(ResourceScope.None)]
416         [MethodImplAttribute(MethodImplOptions.InternalCall)]
417         static internal extern bool ReferenceMatchesDefinitionInternal(AssemblyName reference,
418                                                                      AssemblyName definition,
419                                                                      bool parse);  
420
421
422
423         [System.Security.SecurityCritical]  // auto-generated
424         [ResourceExposure(ResourceScope.None)]
425         [MethodImplAttribute(MethodImplOptions.InternalCall)]
426         internal extern void nInit(out RuntimeAssembly assembly, bool forIntrospection, bool raiseResolveEvent);
427
428         [System.Security.SecurityCritical]  // auto-generated
429         internal void nInit()
430         {
431             RuntimeAssembly dummy = null;
432             nInit(out dummy, false, false);
433         }
434
435         internal void SetProcArchIndex(PortableExecutableKinds pek, ImageFileMachine ifm)
436         {
437             ProcessorArchitecture = CalculateProcArchIndex(pek, ifm, _Flags);
438         }
439
440         internal static ProcessorArchitecture CalculateProcArchIndex(PortableExecutableKinds pek, ImageFileMachine ifm, AssemblyNameFlags flags)
441         {
442             if (((uint)flags & 0xF0) == 0x70)
443                 return ProcessorArchitecture.None;
444
445             if ((pek & System.Reflection.PortableExecutableKinds.PE32Plus) == System.Reflection.PortableExecutableKinds.PE32Plus)
446             {
447                 switch (ifm)
448                 {
449                     case System.Reflection.ImageFileMachine.IA64:
450                         return ProcessorArchitecture.IA64;
451                     case System.Reflection.ImageFileMachine.AMD64:
452                         return ProcessorArchitecture.Amd64;
453                     case System.Reflection.ImageFileMachine.I386:
454                         if ((pek & System.Reflection.PortableExecutableKinds.ILOnly) == System.Reflection.PortableExecutableKinds.ILOnly)
455                             return ProcessorArchitecture.MSIL;
456                         break;
457                 }
458             }
459             else
460             {
461                 if (ifm == System.Reflection.ImageFileMachine.I386)
462                 {
463                     if ((pek & System.Reflection.PortableExecutableKinds.Required32Bit) == System.Reflection.PortableExecutableKinds.Required32Bit)
464                         return ProcessorArchitecture.X86;
465
466                     if ((pek & System.Reflection.PortableExecutableKinds.ILOnly) == System.Reflection.PortableExecutableKinds.ILOnly)
467                         return ProcessorArchitecture.MSIL;
468
469                     return ProcessorArchitecture.X86;
470                 }
471                 if (ifm == System.Reflection.ImageFileMachine.ARM)
472                 {
473                     return ProcessorArchitecture.Arm;
474                 }
475             }
476             return ProcessorArchitecture.None;
477         }
478
479         internal void Init(String name, 
480                            byte[] publicKey,
481                            byte[] publicKeyToken,
482                            Version version,
483                            CultureInfo cultureInfo,
484                            AssemblyHashAlgorithm hashAlgorithm,
485                            AssemblyVersionCompatibility versionCompatibility,
486                            String codeBase,
487                            AssemblyNameFlags flags,
488                            StrongNameKeyPair keyPair) // Null if ref, matching Assembly if def
489         {
490             _Name = name;
491
492             if (publicKey != null) {
493                 _PublicKey = new byte[publicKey.Length];
494                 Array.Copy(publicKey, _PublicKey, publicKey.Length);
495             }
496     
497             if (publicKeyToken != null) {
498                 _PublicKeyToken = new byte[publicKeyToken.Length];
499                 Array.Copy(publicKeyToken, _PublicKeyToken, publicKeyToken.Length);
500             }
501     
502             if (version != null)
503                 _Version = (Version) version.Clone();
504
505             _CultureInfo = cultureInfo;
506             _HashAlgorithm = hashAlgorithm;
507             _VersionCompatibility = versionCompatibility;
508             _CodeBase = codeBase;
509             _Flags = flags;
510             _StrongNameKeyPair = keyPair;
511         }
512
513 #if !FEATURE_CORECLR
514         void _AssemblyName.GetTypeInfoCount(out uint pcTInfo)
515         {
516             throw new NotImplementedException();
517         }
518
519         void _AssemblyName.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo)
520         {
521             throw new NotImplementedException();
522         }
523
524         void _AssemblyName.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
525         {
526             throw new NotImplementedException();
527         }
528
529         void _AssemblyName.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
530         {
531             throw new NotImplementedException();
532         }
533 #endif
534
535 #if FEATURE_APTCA
536         internal string GetNameWithPublicKey()
537         {
538             byte[] key = GetPublicKey();
539
540             // The following string should not be localized because it is used in security decisions.
541             return Name + ", PublicKey=" + System.Security.Util.Hex.EncodeHexString(key);
542         }
543 #endif
544
545         // This call opens and closes the file, but does not add the
546         // assembly to the domain.
547         [System.Security.SecurityCritical]  // auto-generated
548         [ResourceExposure(ResourceScope.Machine)]
549         [MethodImplAttribute(MethodImplOptions.InternalCall)]
550         static internal extern AssemblyName nGetFileInformation(String s);
551
552         [System.Security.SecurityCritical]  // auto-generated
553         [ResourceExposure(ResourceScope.None)]
554         [MethodImplAttribute(MethodImplOptions.InternalCall)]
555         private extern String nToString();
556
557         [System.Security.SecurityCritical]  // auto-generated
558         [ResourceExposure(ResourceScope.None)]
559         [MethodImplAttribute(MethodImplOptions.InternalCall)]
560         private extern byte[] nGetPublicKeyToken();
561     
562         [System.Security.SecurityCritical]  // auto-generated
563         [ResourceExposure(ResourceScope.Machine)]
564         [MethodImplAttribute(MethodImplOptions.InternalCall)]
565         static internal extern String EscapeCodeBase(String codeBase);
566     }
567 }