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