559 lines
21 KiB
C#
559 lines
21 KiB
C#
// ==++==
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
// ==--==
|
|
/*============================================================
|
|
**
|
|
** File: AssemblyName
|
|
**
|
|
** <OWNER>[....]</OWNER>
|
|
** <OWNER>[....]</OWNER>
|
|
**
|
|
**
|
|
** Purpose: Used for binding and retrieving info about an assembly
|
|
**
|
|
**
|
|
===========================================================*/
|
|
namespace System.Reflection {
|
|
using System;
|
|
using System.IO;
|
|
using System.Configuration.Assemblies;
|
|
using System.Runtime.CompilerServices;
|
|
using CultureInfo = System.Globalization.CultureInfo;
|
|
using System.Runtime.Serialization;
|
|
using System.Security.Permissions;
|
|
using System.Runtime.InteropServices;
|
|
using System.Runtime.Versioning;
|
|
using System.Diagnostics.Contracts;
|
|
|
|
[Serializable]
|
|
[ClassInterface(ClassInterfaceType.None)]
|
|
[ComDefaultInterface(typeof(_AssemblyName))]
|
|
[System.Runtime.InteropServices.ComVisible(true)]
|
|
public sealed class AssemblyName : _AssemblyName, ICloneable, ISerializable, IDeserializationCallback
|
|
{
|
|
//
|
|
// READ ME
|
|
// If you modify any of these fields, you must also update the
|
|
// AssemblyBaseObject structure in object.h
|
|
//
|
|
private String _Name; // Name
|
|
private byte[] _PublicKey;
|
|
private byte[] _PublicKeyToken;
|
|
private CultureInfo _CultureInfo;
|
|
private String _CodeBase; // Potential location to get the file
|
|
private Version _Version;
|
|
|
|
private StrongNameKeyPair _StrongNameKeyPair;
|
|
private SerializationInfo m_siInfo; //A temporary variable which we need during deserialization.
|
|
|
|
private byte[] _HashForControl;
|
|
private AssemblyHashAlgorithm _HashAlgorithm;
|
|
private AssemblyHashAlgorithm _HashAlgorithmForControl;
|
|
|
|
private AssemblyVersionCompatibility _VersionCompatibility;
|
|
private AssemblyNameFlags _Flags;
|
|
|
|
public AssemblyName()
|
|
{
|
|
_HashAlgorithm = AssemblyHashAlgorithm.None;
|
|
_VersionCompatibility = AssemblyVersionCompatibility.SameMachine;
|
|
_Flags = AssemblyNameFlags.None;
|
|
}
|
|
|
|
// Set and get the name of the assembly. If this is a weak Name
|
|
// then it optionally contains a site. For strong assembly names,
|
|
// the name partitions up the strong name's namespace
|
|
public String Name
|
|
{
|
|
get { return _Name; }
|
|
set { _Name = value; }
|
|
}
|
|
|
|
public Version Version
|
|
{
|
|
get {
|
|
return _Version;
|
|
}
|
|
set {
|
|
_Version = value;
|
|
}
|
|
}
|
|
|
|
// Locales, internally the LCID is used for the match.
|
|
public CultureInfo CultureInfo
|
|
{
|
|
get {
|
|
return _CultureInfo;
|
|
}
|
|
set {
|
|
_CultureInfo = value;
|
|
}
|
|
}
|
|
|
|
public String CultureName
|
|
{
|
|
get
|
|
{
|
|
return (_CultureInfo == null) ? null : _CultureInfo.Name;
|
|
}
|
|
}
|
|
|
|
public String CodeBase
|
|
{
|
|
#if FEATURE_CORECLR
|
|
[System.Security.SecurityCritical] // auto-generated
|
|
#endif
|
|
[ResourceExposure(ResourceScope.Machine)]
|
|
get { return _CodeBase; }
|
|
#if FEATURE_CORECLR
|
|
[System.Security.SecurityCritical] // auto-generated
|
|
#endif
|
|
[ResourceExposure(ResourceScope.Machine)]
|
|
set { _CodeBase = value; }
|
|
}
|
|
|
|
public String EscapedCodeBase
|
|
{
|
|
[System.Security.SecuritySafeCritical] // auto-generated
|
|
[ResourceExposure(ResourceScope.Machine)]
|
|
[ResourceConsumption(ResourceScope.Machine)]
|
|
get
|
|
{
|
|
if (_CodeBase == null)
|
|
return null;
|
|
else
|
|
return EscapeCodeBase(_CodeBase);
|
|
}
|
|
}
|
|
|
|
public ProcessorArchitecture ProcessorArchitecture
|
|
{
|
|
get {
|
|
int x = (((int)_Flags) & 0x70) >> 4;
|
|
if(x > 5)
|
|
x = 0;
|
|
return (ProcessorArchitecture)x;
|
|
}
|
|
set {
|
|
int x = ((int)value) & 0x07;
|
|
if(x <= 5) {
|
|
_Flags = (AssemblyNameFlags)((int)_Flags & 0xFFFFFF0F);
|
|
_Flags |= (AssemblyNameFlags)(x << 4);
|
|
}
|
|
}
|
|
}
|
|
|
|
[System.Runtime.InteropServices.ComVisible(false)]
|
|
public AssemblyContentType ContentType
|
|
{
|
|
get
|
|
{
|
|
int x = (((int)_Flags) & 0x00000E00) >> 9;
|
|
if (x > 1)
|
|
x = 0;
|
|
return (AssemblyContentType)x;
|
|
}
|
|
set
|
|
{
|
|
int x = ((int)value) & 0x07;
|
|
if (x <= 1)
|
|
{
|
|
_Flags = (AssemblyNameFlags)((int)_Flags & 0xFFFFF1FF);
|
|
_Flags |= (AssemblyNameFlags)(x << 9);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Make a copy of this assembly name.
|
|
public Object Clone()
|
|
{
|
|
AssemblyName name = new AssemblyName();
|
|
name.Init(_Name,
|
|
_PublicKey,
|
|
_PublicKeyToken,
|
|
_Version,
|
|
_CultureInfo,
|
|
_HashAlgorithm,
|
|
_VersionCompatibility,
|
|
_CodeBase,
|
|
_Flags,
|
|
_StrongNameKeyPair);
|
|
name._HashForControl=_HashForControl;
|
|
name._HashAlgorithmForControl=_HashAlgorithmForControl;
|
|
return name;
|
|
}
|
|
|
|
/*
|
|
* Get the AssemblyName for a given file. This will only work
|
|
* if the file contains an assembly manifest. This method causes
|
|
* the file to be opened and closed.
|
|
*/
|
|
[System.Security.SecuritySafeCritical] // auto-generated
|
|
[ResourceExposure(ResourceScope.None)]
|
|
[ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
|
|
static public AssemblyName GetAssemblyName(String assemblyFile)
|
|
{
|
|
if(assemblyFile == null)
|
|
throw new ArgumentNullException("assemblyFile");
|
|
Contract.EndContractBlock();
|
|
|
|
// Assembly.GetNameInternal() will not demand path discovery
|
|
// permission, so do that first.
|
|
String fullPath = Path.GetFullPathInternal(assemblyFile);
|
|
new FileIOPermission( FileIOPermissionAccess.PathDiscovery, fullPath ).Demand();
|
|
return nGetFileInformation(fullPath);
|
|
}
|
|
|
|
internal void SetHashControl(byte[] hash, AssemblyHashAlgorithm hashAlgorithm)
|
|
{
|
|
_HashForControl=hash;
|
|
_HashAlgorithmForControl=hashAlgorithm;
|
|
}
|
|
|
|
// The public key that is used to verify an assemblies
|
|
// inclusion into the namespace. If the public key associated
|
|
// with the namespace cannot verify the assembly the assembly
|
|
// will fail to load.
|
|
public byte[] GetPublicKey()
|
|
{
|
|
#if FEATURE_LEGACYNETCF
|
|
if (CompatibilitySwitches.IsAppEarlierThanWindowsPhone8 && _PublicKey == null)
|
|
return EmptyArray<Byte>.Value;
|
|
else
|
|
#endif
|
|
return _PublicKey;
|
|
}
|
|
|
|
public void SetPublicKey(byte[] publicKey)
|
|
{
|
|
_PublicKey = publicKey;
|
|
|
|
if (publicKey == null)
|
|
_Flags &= ~AssemblyNameFlags.PublicKey;
|
|
else
|
|
_Flags |= AssemblyNameFlags.PublicKey;
|
|
}
|
|
|
|
// The compressed version of the public key formed from a truncated hash.
|
|
// Will throw a SecurityException if _PublicKey is invalid
|
|
[System.Security.SecuritySafeCritical] // auto-generated
|
|
public byte[] GetPublicKeyToken()
|
|
{
|
|
if (_PublicKeyToken == null)
|
|
_PublicKeyToken = nGetPublicKeyToken();
|
|
return _PublicKeyToken;
|
|
}
|
|
|
|
public void SetPublicKeyToken(byte[] publicKeyToken)
|
|
{
|
|
_PublicKeyToken = publicKeyToken;
|
|
}
|
|
|
|
// Flags modifying the name. So far the only flag is PublicKey, which
|
|
// indicates that a full public key and not the compressed version is
|
|
// present.
|
|
// Processor Architecture flags are set only through ProcessorArchitecture
|
|
// property and can't be set or retrieved directly
|
|
// Content Type flags are set only through ContentType property and can't be
|
|
// set or retrieved directly
|
|
public AssemblyNameFlags Flags
|
|
{
|
|
get { return (AssemblyNameFlags)((uint)_Flags & 0xFFFFF10F); }
|
|
set {
|
|
_Flags &= unchecked((AssemblyNameFlags)0x00000EF0);
|
|
_Flags |= (value & unchecked((AssemblyNameFlags)0xFFFFF10F));
|
|
}
|
|
}
|
|
|
|
public AssemblyHashAlgorithm HashAlgorithm
|
|
{
|
|
get { return _HashAlgorithm; }
|
|
set { _HashAlgorithm = value; }
|
|
}
|
|
|
|
public AssemblyVersionCompatibility VersionCompatibility
|
|
{
|
|
get { return _VersionCompatibility; }
|
|
set { _VersionCompatibility = value; }
|
|
}
|
|
|
|
public StrongNameKeyPair KeyPair
|
|
{
|
|
get { return _StrongNameKeyPair; }
|
|
set { _StrongNameKeyPair = value; }
|
|
}
|
|
|
|
public String FullName
|
|
{
|
|
[System.Security.SecuritySafeCritical] // auto-generated
|
|
get {
|
|
String name = nToString();
|
|
if (CompatibilitySwitches.IsAppEarlierThanWindowsPhone8 && string.IsNullOrEmpty(name))
|
|
return base.ToString();
|
|
|
|
return name;
|
|
}
|
|
}
|
|
|
|
// Returns the stringized version of the assembly name.
|
|
public override String ToString()
|
|
{
|
|
String s = FullName;
|
|
if(s == null)
|
|
return base.ToString();
|
|
else
|
|
return s;
|
|
}
|
|
|
|
[System.Security.SecurityCritical] // auto-generated_required
|
|
public void GetObjectData(SerializationInfo info, StreamingContext context)
|
|
{
|
|
if (info == null)
|
|
throw new ArgumentNullException("info");
|
|
Contract.EndContractBlock();
|
|
|
|
//Allocate the serialization info and serialize our static data.
|
|
info.AddValue("_Name", _Name);
|
|
info.AddValue("_PublicKey", _PublicKey, typeof(byte[]));
|
|
info.AddValue("_PublicKeyToken", _PublicKeyToken, typeof(byte[]));
|
|
#if FEATURE_USE_LCID
|
|
info.AddValue("_CultureInfo", (_CultureInfo == null) ? -1 :_CultureInfo.LCID);
|
|
#endif
|
|
info.AddValue("_CodeBase", _CodeBase);
|
|
info.AddValue("_Version", _Version);
|
|
info.AddValue("_HashAlgorithm", _HashAlgorithm, typeof(AssemblyHashAlgorithm));
|
|
info.AddValue("_HashAlgorithmForControl", _HashAlgorithmForControl, typeof(AssemblyHashAlgorithm));
|
|
info.AddValue("_StrongNameKeyPair", _StrongNameKeyPair, typeof(StrongNameKeyPair));
|
|
info.AddValue("_VersionCompatibility", _VersionCompatibility, typeof(AssemblyVersionCompatibility));
|
|
info.AddValue("_Flags", _Flags, typeof(AssemblyNameFlags));
|
|
info.AddValue("_HashForControl",_HashForControl,typeof(byte[]));
|
|
}
|
|
|
|
public void OnDeserialization(Object sender)
|
|
{
|
|
// Deserialization has already been performed
|
|
if (m_siInfo == null)
|
|
return;
|
|
|
|
_Name = m_siInfo.GetString("_Name");
|
|
_PublicKey = (byte[]) m_siInfo.GetValue("_PublicKey", typeof(byte[]));
|
|
_PublicKeyToken = (byte[]) m_siInfo.GetValue("_PublicKeyToken", typeof(byte[]));
|
|
#if FEATURE_USE_LCID
|
|
int lcid = (int)m_siInfo.GetInt32("_CultureInfo");
|
|
if (lcid != -1)
|
|
_CultureInfo = new CultureInfo(lcid);
|
|
#endif
|
|
|
|
_CodeBase = m_siInfo.GetString("_CodeBase");
|
|
_Version = (Version) m_siInfo.GetValue("_Version", typeof(Version));
|
|
_HashAlgorithm = (AssemblyHashAlgorithm) m_siInfo.GetValue("_HashAlgorithm", typeof(AssemblyHashAlgorithm));
|
|
_StrongNameKeyPair = (StrongNameKeyPair) m_siInfo.GetValue("_StrongNameKeyPair", typeof(StrongNameKeyPair));
|
|
_VersionCompatibility = (AssemblyVersionCompatibility)m_siInfo.GetValue("_VersionCompatibility", typeof(AssemblyVersionCompatibility));
|
|
_Flags = (AssemblyNameFlags) m_siInfo.GetValue("_Flags", typeof(AssemblyNameFlags));
|
|
|
|
try {
|
|
_HashAlgorithmForControl = (AssemblyHashAlgorithm) m_siInfo.GetValue("_HashAlgorithmForControl", typeof(AssemblyHashAlgorithm));
|
|
_HashForControl = (byte[]) m_siInfo.GetValue("_HashForControl", typeof(byte[]));
|
|
}
|
|
catch (SerializationException) { // RTM did not have these defined
|
|
_HashAlgorithmForControl = AssemblyHashAlgorithm.None;
|
|
_HashForControl = null;
|
|
}
|
|
|
|
m_siInfo = null;
|
|
}
|
|
|
|
[System.Security.SecuritySafeCritical] // auto-generated
|
|
public AssemblyName(String assemblyName)
|
|
{
|
|
if (assemblyName == null)
|
|
throw new ArgumentNullException("assemblyName");
|
|
Contract.EndContractBlock();
|
|
if ((assemblyName.Length == 0) ||
|
|
(assemblyName[0] == '\0'))
|
|
throw new ArgumentException(Environment.GetResourceString("Format_StringZeroLength"));
|
|
|
|
_Name = assemblyName;
|
|
nInit();
|
|
}
|
|
|
|
[System.Security.SecuritySafeCritical] // auto-generated
|
|
[ResourceExposure(ResourceScope.None)]
|
|
static public bool ReferenceMatchesDefinition(AssemblyName reference,
|
|
AssemblyName definition)
|
|
{
|
|
// Optimization for common use case
|
|
if (Object.ReferenceEquals(reference, definition))
|
|
{
|
|
return true;
|
|
}
|
|
return ReferenceMatchesDefinitionInternal(reference, definition, true);
|
|
}
|
|
|
|
|
|
/// "parse" tells us to parse the simple name of the assembly as if it was the full name
|
|
/// almost never the right thing to do, but needed for compat
|
|
[System.Security.SecuritySafeCritical] // auto-generated
|
|
[ResourceExposure(ResourceScope.None)]
|
|
[MethodImplAttribute(MethodImplOptions.InternalCall)]
|
|
static internal extern bool ReferenceMatchesDefinitionInternal(AssemblyName reference,
|
|
AssemblyName definition,
|
|
bool parse);
|
|
|
|
|
|
|
|
[System.Security.SecurityCritical] // auto-generated
|
|
[ResourceExposure(ResourceScope.None)]
|
|
[MethodImplAttribute(MethodImplOptions.InternalCall)]
|
|
internal extern void nInit(out RuntimeAssembly assembly, bool forIntrospection, bool raiseResolveEvent);
|
|
|
|
[System.Security.SecurityCritical] // auto-generated
|
|
internal void nInit()
|
|
{
|
|
RuntimeAssembly dummy = null;
|
|
nInit(out dummy, false, false);
|
|
}
|
|
|
|
// Constructs a new AssemblyName during deserialization.
|
|
internal AssemblyName(SerializationInfo info, StreamingContext context)
|
|
{
|
|
//The graph is not valid until OnDeserialization() has been called.
|
|
m_siInfo = info;
|
|
}
|
|
|
|
internal void SetProcArchIndex(PortableExecutableKinds pek, ImageFileMachine ifm)
|
|
{
|
|
ProcessorArchitecture = CalculateProcArchIndex(pek, ifm, _Flags);
|
|
}
|
|
|
|
internal static ProcessorArchitecture CalculateProcArchIndex(PortableExecutableKinds pek, ImageFileMachine ifm, AssemblyNameFlags flags)
|
|
{
|
|
if (((uint)flags & 0xF0) == 0x70)
|
|
return ProcessorArchitecture.None;
|
|
|
|
if ((pek & System.Reflection.PortableExecutableKinds.PE32Plus) == System.Reflection.PortableExecutableKinds.PE32Plus)
|
|
{
|
|
switch (ifm)
|
|
{
|
|
case System.Reflection.ImageFileMachine.IA64:
|
|
return ProcessorArchitecture.IA64;
|
|
case System.Reflection.ImageFileMachine.AMD64:
|
|
return ProcessorArchitecture.Amd64;
|
|
case System.Reflection.ImageFileMachine.I386:
|
|
if ((pek & System.Reflection.PortableExecutableKinds.ILOnly) == System.Reflection.PortableExecutableKinds.ILOnly)
|
|
return ProcessorArchitecture.MSIL;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (ifm == System.Reflection.ImageFileMachine.I386)
|
|
{
|
|
if ((pek & System.Reflection.PortableExecutableKinds.Required32Bit) == System.Reflection.PortableExecutableKinds.Required32Bit)
|
|
return ProcessorArchitecture.X86;
|
|
|
|
if ((pek & System.Reflection.PortableExecutableKinds.ILOnly) == System.Reflection.PortableExecutableKinds.ILOnly)
|
|
return ProcessorArchitecture.MSIL;
|
|
|
|
return ProcessorArchitecture.X86;
|
|
}
|
|
if (ifm == System.Reflection.ImageFileMachine.ARM)
|
|
{
|
|
return ProcessorArchitecture.Arm;
|
|
}
|
|
}
|
|
return ProcessorArchitecture.None;
|
|
}
|
|
|
|
internal void Init(String name,
|
|
byte[] publicKey,
|
|
byte[] publicKeyToken,
|
|
Version version,
|
|
CultureInfo cultureInfo,
|
|
AssemblyHashAlgorithm hashAlgorithm,
|
|
AssemblyVersionCompatibility versionCompatibility,
|
|
String codeBase,
|
|
AssemblyNameFlags flags,
|
|
StrongNameKeyPair keyPair) // Null if ref, matching Assembly if def
|
|
{
|
|
_Name = name;
|
|
|
|
if (publicKey != null) {
|
|
_PublicKey = new byte[publicKey.Length];
|
|
Array.Copy(publicKey, _PublicKey, publicKey.Length);
|
|
}
|
|
|
|
if (publicKeyToken != null) {
|
|
_PublicKeyToken = new byte[publicKeyToken.Length];
|
|
Array.Copy(publicKeyToken, _PublicKeyToken, publicKeyToken.Length);
|
|
}
|
|
|
|
if (version != null)
|
|
_Version = (Version) version.Clone();
|
|
|
|
_CultureInfo = cultureInfo;
|
|
_HashAlgorithm = hashAlgorithm;
|
|
_VersionCompatibility = versionCompatibility;
|
|
_CodeBase = codeBase;
|
|
_Flags = flags;
|
|
_StrongNameKeyPair = keyPair;
|
|
}
|
|
|
|
void _AssemblyName.GetTypeInfoCount(out uint pcTInfo)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
void _AssemblyName.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
void _AssemblyName.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
void _AssemblyName.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
#if FEATURE_APTCA
|
|
internal string GetNameWithPublicKey()
|
|
{
|
|
byte[] key = GetPublicKey();
|
|
|
|
// The following string should not be localized because it is used in security decisions.
|
|
return Name + ", PublicKey=" + System.Security.Util.Hex.EncodeHexString(key);
|
|
}
|
|
#endif
|
|
|
|
// This call opens and closes the file, but does not add the
|
|
// assembly to the domain.
|
|
[System.Security.SecurityCritical] // auto-generated
|
|
[ResourceExposure(ResourceScope.Machine)]
|
|
[MethodImplAttribute(MethodImplOptions.InternalCall)]
|
|
static internal extern AssemblyName nGetFileInformation(String s);
|
|
|
|
[System.Security.SecurityCritical] // auto-generated
|
|
[ResourceExposure(ResourceScope.None)]
|
|
[MethodImplAttribute(MethodImplOptions.InternalCall)]
|
|
private extern String nToString();
|
|
|
|
[System.Security.SecurityCritical] // auto-generated
|
|
[ResourceExposure(ResourceScope.None)]
|
|
[MethodImplAttribute(MethodImplOptions.InternalCall)]
|
|
private extern byte[] nGetPublicKeyToken();
|
|
|
|
[System.Security.SecurityCritical] // auto-generated
|
|
[ResourceExposure(ResourceScope.Machine)]
|
|
[MethodImplAttribute(MethodImplOptions.InternalCall)]
|
|
static internal extern String EscapeCodeBase(String codeBase);
|
|
}
|
|
}
|