AssemblyName.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452
  1. //
  2. // System.Reflection/AssemblyName.cs
  3. //
  4. // Authors:
  5. // Paolo Molaro ([email protected])
  6. // Sebastien Pouliot <[email protected]>
  7. //
  8. // (C) 2001 Ximian, Inc. http://www.ximian.com
  9. // Portions (C) 2002 Motus Technologies Inc. (http://www.motus.com)
  10. // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
  11. //
  12. // Permission is hereby granted, free of charge, to any person obtaining
  13. // a copy of this software and associated documentation files (the
  14. // "Software"), to deal in the Software without restriction, including
  15. // without limitation the rights to use, copy, modify, merge, publish,
  16. // distribute, sublicense, and/or sell copies of the Software, and to
  17. // permit persons to whom the Software is furnished to do so, subject to
  18. // the following conditions:
  19. //
  20. // The above copyright notice and this permission notice shall be
  21. // included in all copies or substantial portions of the Software.
  22. //
  23. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  24. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  25. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  26. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  27. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  28. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  29. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  30. //
  31. using System.Configuration.Assemblies;
  32. using System.Globalization;
  33. using System.Runtime.Serialization;
  34. using System.Security;
  35. using System.Security.Cryptography;
  36. using System.Security.Permissions;
  37. using System.Text;
  38. using System.Runtime.InteropServices;
  39. using System.Runtime.CompilerServices;
  40. using System.IO;
  41. using Mono.Security;
  42. using Mono.Security.Cryptography;
  43. namespace System.Reflection {
  44. // References:
  45. // a. Uniform Resource Identifiers (URI): Generic Syntax
  46. // http://www.ietf.org/rfc/rfc2396.txt
  47. [ComVisible (true)]
  48. [ComDefaultInterfaceAttribute (typeof (_AssemblyName))]
  49. [Serializable]
  50. [ClassInterfaceAttribute (ClassInterfaceType.None)]
  51. [StructLayout (LayoutKind.Sequential)]
  52. #if MOBILE
  53. public sealed class AssemblyName : ICloneable, ISerializable, IDeserializationCallback {
  54. #else
  55. public sealed class AssemblyName : ICloneable, ISerializable, IDeserializationCallback, _AssemblyName {
  56. #endif
  57. #pragma warning disable 169
  58. #region Synch with object-internals.h
  59. string name;
  60. string codebase;
  61. int major, minor, build, revision;
  62. CultureInfo cultureinfo;
  63. AssemblyNameFlags flags;
  64. AssemblyHashAlgorithm hashalg;
  65. StrongNameKeyPair keypair;
  66. byte[] publicKey;
  67. byte[] keyToken;
  68. AssemblyVersionCompatibility versioncompat;
  69. Version version;
  70. ProcessorArchitecture processor_architecture = ProcessorArchitecture.None;
  71. #endregion
  72. #pragma warning restore 169
  73. AssemblyContentType contentType;
  74. public AssemblyName ()
  75. {
  76. // defaults
  77. versioncompat = AssemblyVersionCompatibility.SameMachine;
  78. }
  79. [MethodImpl (MethodImplOptions.InternalCall)]
  80. static extern bool ParseName (AssemblyName aname, string assemblyName);
  81. public AssemblyName (string assemblyName)
  82. {
  83. if (assemblyName == null)
  84. throw new ArgumentNullException ("assemblyName");
  85. if (assemblyName.Length < 1)
  86. throw new ArgumentException ("assemblyName cannot have zero length.");
  87. if (!ParseName (this, assemblyName))
  88. throw new FileLoadException ("The assembly name is invalid.");
  89. }
  90. [MonoLimitation ("Not used, as the values are too limited; Mono supports more")]
  91. public ProcessorArchitecture ProcessorArchitecture {
  92. get {
  93. return processor_architecture;
  94. }
  95. set {
  96. processor_architecture = value;
  97. }
  98. }
  99. internal AssemblyName (SerializationInfo si, StreamingContext sc)
  100. {
  101. name = si.GetString ("_Name");
  102. codebase = si.GetString ("_CodeBase");
  103. version = (Version)si.GetValue ("_Version", typeof (Version));
  104. publicKey = (byte[])si.GetValue ("_PublicKey", typeof (byte[]));
  105. keyToken = (byte[])si.GetValue ("_PublicKeyToken", typeof (byte[]));
  106. hashalg = (AssemblyHashAlgorithm)si.GetValue ("_HashAlgorithm", typeof (AssemblyHashAlgorithm));
  107. keypair = (StrongNameKeyPair)si.GetValue ("_StrongNameKeyPair", typeof (StrongNameKeyPair));
  108. versioncompat = (AssemblyVersionCompatibility)si.GetValue ("_VersionCompatibility", typeof (AssemblyVersionCompatibility));
  109. flags = (AssemblyNameFlags)si.GetValue ("_Flags", typeof (AssemblyNameFlags));
  110. int lcid = si.GetInt32 ("_CultureInfo");
  111. if (lcid != -1) cultureinfo = new CultureInfo (lcid);
  112. }
  113. public string Name {
  114. get { return name; }
  115. set { name = value; }
  116. }
  117. public string CodeBase {
  118. get { return codebase; }
  119. set { codebase = value; }
  120. }
  121. public string EscapedCodeBase {
  122. get {
  123. if (codebase == null)
  124. return null;
  125. return Uri.EscapeString (codebase, false, true, true);
  126. }
  127. }
  128. public CultureInfo CultureInfo {
  129. get { return cultureinfo; }
  130. set { cultureinfo = value; }
  131. }
  132. public AssemblyNameFlags Flags {
  133. get { return flags; }
  134. set { flags = value; }
  135. }
  136. public string FullName {
  137. get {
  138. if (name == null)
  139. return string.Empty;
  140. StringBuilder fname = new StringBuilder ();
  141. if (Char.IsWhiteSpace (name [0]))
  142. fname.Append ("\"" + name + "\"");
  143. else
  144. fname.Append (name);
  145. if (Version != null) {
  146. fname.Append (", Version=");
  147. fname.Append (Version.ToString ());
  148. }
  149. if (cultureinfo != null) {
  150. fname.Append (", Culture=");
  151. if (cultureinfo.LCID == CultureInfo.InvariantCulture.LCID)
  152. fname.Append ("neutral");
  153. else
  154. fname.Append (cultureinfo.Name);
  155. }
  156. byte [] pub_tok = InternalGetPublicKeyToken ();
  157. if (pub_tok != null) {
  158. if (pub_tok.Length == 0)
  159. fname.Append (", PublicKeyToken=null");
  160. else {
  161. fname.Append (", PublicKeyToken=");
  162. for (int i = 0; i < pub_tok.Length; i++)
  163. fname.Append (pub_tok[i].ToString ("x2"));
  164. }
  165. }
  166. if ((Flags & AssemblyNameFlags.Retargetable) != 0)
  167. fname.Append (", Retargetable=Yes");
  168. return fname.ToString ();
  169. }
  170. }
  171. public AssemblyHashAlgorithm HashAlgorithm {
  172. get { return hashalg; }
  173. set { hashalg = value; }
  174. }
  175. public StrongNameKeyPair KeyPair {
  176. get { return keypair; }
  177. set { keypair = value; }
  178. }
  179. public Version Version {
  180. get {
  181. return version;
  182. }
  183. set {
  184. version = value;
  185. if (value == null)
  186. major = minor = build = revision = 0;
  187. else {
  188. major = value.Major;
  189. minor = value.Minor;
  190. build = value.Build;
  191. revision = value.Revision;
  192. }
  193. }
  194. }
  195. public AssemblyVersionCompatibility VersionCompatibility {
  196. get { return versioncompat; }
  197. set { versioncompat = value; }
  198. }
  199. public override string ToString ()
  200. {
  201. string name = FullName;
  202. return (name != null) ? name : base.ToString ();
  203. }
  204. public byte[] GetPublicKey()
  205. {
  206. return publicKey;
  207. }
  208. public byte[] GetPublicKeyToken ()
  209. {
  210. if (keyToken != null)
  211. return keyToken;
  212. if (publicKey == null)
  213. return null;
  214. if (publicKey.Length == 0)
  215. return EmptyArray<byte>.Value;
  216. if (!IsPublicKeyValid)
  217. throw new SecurityException ("The public key is not valid.");
  218. keyToken = ComputePublicKeyToken ();
  219. return keyToken;
  220. }
  221. private bool IsPublicKeyValid {
  222. get {
  223. // check for ECMA key
  224. if (publicKey.Length == 16) {
  225. int i = 0;
  226. int sum = 0;
  227. while (i < publicKey.Length)
  228. sum += publicKey [i++];
  229. if (sum == 4)
  230. return true;
  231. }
  232. switch (publicKey [0]) {
  233. case 0x00: // public key inside a header
  234. if (publicKey.Length > 12 && publicKey [12] == 0x06) {
  235. #if MOBILE
  236. return true;
  237. #else
  238. try {
  239. CryptoConvert.FromCapiPublicKeyBlob (
  240. publicKey, 12);
  241. return true;
  242. } catch (CryptographicException) {
  243. }
  244. #endif
  245. }
  246. break;
  247. case 0x06: // public key
  248. #if MOBILE
  249. return true;
  250. #else
  251. try {
  252. CryptoConvert.FromCapiPublicKeyBlob (publicKey);
  253. return true;
  254. } catch (CryptographicException) {
  255. }
  256. break;
  257. #endif
  258. case 0x07: // private key
  259. break;
  260. }
  261. return false;
  262. }
  263. }
  264. private byte [] InternalGetPublicKeyToken ()
  265. {
  266. if (keyToken != null)
  267. return keyToken;
  268. if (publicKey == null)
  269. return null;
  270. if (publicKey.Length == 0)
  271. return EmptyArray<byte>.Value;
  272. if (!IsPublicKeyValid)
  273. throw new SecurityException ("The public key is not valid.");
  274. return ComputePublicKeyToken ();
  275. }
  276. [MethodImplAttribute (MethodImplOptions.InternalCall)]
  277. extern unsafe static void get_public_token (byte* token, byte* pubkey, int len);
  278. private unsafe byte [] ComputePublicKeyToken ()
  279. {
  280. byte [] token = new byte [8];
  281. fixed (byte* pkt = token)
  282. fixed (byte *pk = publicKey)
  283. get_public_token (pkt, pk, publicKey.Length);
  284. return token;
  285. }
  286. public static bool ReferenceMatchesDefinition (AssemblyName reference, AssemblyName definition)
  287. {
  288. if (reference == null)
  289. throw new ArgumentNullException ("reference");
  290. if (definition == null)
  291. throw new ArgumentNullException ("definition");
  292. // we only compare the simple assembly name to be consistent with MS .NET,
  293. // which is the result of a bug in their implementation (see https://connect.microsoft.com/VisualStudio/feedback/details/752902)
  294. return string.Equals (reference.Name, definition.Name, StringComparison.OrdinalIgnoreCase);
  295. }
  296. public void SetPublicKey (byte[] publicKey)
  297. {
  298. if (publicKey == null)
  299. flags ^= AssemblyNameFlags.PublicKey;
  300. else
  301. flags |= AssemblyNameFlags.PublicKey;
  302. this.publicKey = publicKey;
  303. }
  304. public void SetPublicKeyToken (byte[] publicKeyToken)
  305. {
  306. keyToken = publicKeyToken;
  307. }
  308. [SecurityPermission (SecurityAction.Demand, SerializationFormatter = true)]
  309. public void GetObjectData (SerializationInfo info, StreamingContext context)
  310. {
  311. if (info == null)
  312. throw new ArgumentNullException ("info");
  313. info.AddValue ("_Name", name);
  314. info.AddValue ("_PublicKey", publicKey);
  315. info.AddValue ("_PublicKeyToken", keyToken);
  316. info.AddValue ("_CultureInfo", cultureinfo != null ? cultureinfo.LCID : -1);
  317. info.AddValue ("_CodeBase", codebase);
  318. info.AddValue ("_Version", Version);
  319. info.AddValue ("_HashAlgorithm", hashalg);
  320. info.AddValue ("_HashAlgorithmForControl", AssemblyHashAlgorithm.None);
  321. info.AddValue ("_StrongNameKeyPair", keypair);
  322. info.AddValue ("_VersionCompatibility", versioncompat);
  323. info.AddValue ("_Flags", flags);
  324. info.AddValue ("_HashForControl", null);
  325. }
  326. public object Clone()
  327. {
  328. AssemblyName an = new AssemblyName ();
  329. an.name = name;
  330. an.codebase = codebase;
  331. an.major = major;
  332. an.minor = minor;
  333. an.build = build;
  334. an.revision = revision;
  335. an.version = version;
  336. an.cultureinfo = cultureinfo;
  337. an.flags = flags;
  338. an.hashalg = hashalg;
  339. an.keypair = keypair;
  340. an.publicKey = publicKey;
  341. an.keyToken = keyToken;
  342. an.versioncompat = versioncompat;
  343. an.processor_architecture = processor_architecture;
  344. return an;
  345. }
  346. public void OnDeserialization (object sender)
  347. {
  348. Version = version;
  349. }
  350. public static AssemblyName GetAssemblyName (string assemblyFile)
  351. {
  352. if (assemblyFile == null)
  353. throw new ArgumentNullException ("assemblyFile");
  354. AssemblyName aname = new AssemblyName ();
  355. Assembly.InternalGetAssemblyName (Path.GetFullPath (assemblyFile), aname);
  356. return aname;
  357. }
  358. #if !MOBILE
  359. void _AssemblyName.GetIDsOfNames ([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
  360. {
  361. throw new NotImplementedException ();
  362. }
  363. void _AssemblyName.GetTypeInfo (uint iTInfo, uint lcid, IntPtr ppTInfo)
  364. {
  365. throw new NotImplementedException ();
  366. }
  367. void _AssemblyName.GetTypeInfoCount (out uint pcTInfo)
  368. {
  369. throw new NotImplementedException ();
  370. }
  371. void _AssemblyName.Invoke (uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams,
  372. IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
  373. {
  374. throw new NotImplementedException ();
  375. }
  376. #endif
  377. public string CultureName {
  378. get {
  379. if (cultureinfo == null)
  380. return null;
  381. if (cultureinfo.LCID == CultureInfo.InvariantCulture.LCID)
  382. return "neutral";
  383. return cultureinfo.Name;
  384. }
  385. }
  386. [ComVisibleAttribute(false)]
  387. public AssemblyContentType ContentType {
  388. get {
  389. return contentType;
  390. }
  391. set {
  392. contentType = value;
  393. }
  394. }
  395. }
  396. }