summaryrefslogtreecommitdiffstats
path: root/tools/Sandcastle/Source/CCI/AssemblyCache.cs
diff options
context:
space:
mode:
authorAndrew Arnott <andrewarnott@gmail.com>2009-09-20 21:18:59 -0700
committerAndrew Arnott <andrewarnott@gmail.com>2009-09-21 08:06:22 -0700
commitbbe3f9cc9c8a1e5909273c1a162a63ea7a66afd8 (patch)
treec91f66e642c4d26fca266e226b3f2765f546d700 /tools/Sandcastle/Source/CCI/AssemblyCache.cs
parent627014f0bbc3fd576277375e70f8391d150b0a67 (diff)
downloadDotNetOpenAuth-bbe3f9cc9c8a1e5909273c1a162a63ea7a66afd8.zip
DotNetOpenAuth-bbe3f9cc9c8a1e5909273c1a162a63ea7a66afd8.tar.gz
DotNetOpenAuth-bbe3f9cc9c8a1e5909273c1a162a63ea7a66afd8.tar.bz2
Switched out the Sandcastle binaries for the source code.
Diffstat (limited to 'tools/Sandcastle/Source/CCI/AssemblyCache.cs')
-rw-r--r--tools/Sandcastle/Source/CCI/AssemblyCache.cs351
1 files changed, 351 insertions, 0 deletions
diff --git a/tools/Sandcastle/Source/CCI/AssemblyCache.cs b/tools/Sandcastle/Source/CCI/AssemblyCache.cs
new file mode 100644
index 0000000..72d36cb
--- /dev/null
+++ b/tools/Sandcastle/Source/CCI/AssemblyCache.cs
@@ -0,0 +1,351 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+#if !ROTOR
+using System;
+using System.Collections;
+using System.Diagnostics;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Text;
+
+#if CCINamespace
+namespace Microsoft.Cci{
+#else
+namespace System.Compiler
+{
+#endif
+#if !FxCop
+ public
+#endif
+ class GlobalAssemblyCache
+ {
+ private GlobalAssemblyCache() { }
+ private static readonly object Lock = new object();
+ private static bool FusionLoaded;
+
+ /// <param name="codeBaseUri">Uri pointing to the assembly</param>
+ public static bool Contains(Uri codeBaseUri)
+ {
+ if (codeBaseUri == null) { Debug.Fail("codeBaseUri == null"); return false; }
+ lock (GlobalAssemblyCache.Lock)
+ {
+ if (!GlobalAssemblyCache.FusionLoaded)
+ {
+ GlobalAssemblyCache.FusionLoaded = true;
+ System.Reflection.Assembly systemAssembly = typeof(object).Assembly;
+ //^ assume systemAssembly != null && systemAssembly.Location != null;
+ string dir = Path.GetDirectoryName(systemAssembly.Location);
+ //^ assume dir != null;
+ GlobalAssemblyCache.LoadLibrary(Path.Combine(dir, "fusion.dll"));
+ }
+ IAssemblyEnum assemblyEnum;
+ int rc = GlobalAssemblyCache.CreateAssemblyEnum(out assemblyEnum, null, null, ASM_CACHE.GAC, 0);
+ if (rc < 0 || assemblyEnum == null) return false;
+ IApplicationContext applicationContext;
+ IAssemblyName currentName;
+ while (assemblyEnum.GetNextAssembly(out applicationContext, out currentName, 0) == 0)
+ {
+ //^ assume currentName != null;
+ AssemblyName assemblyName = new AssemblyName(currentName);
+ string scheme = codeBaseUri.Scheme;
+ if (scheme != null && assemblyName.CodeBase.StartsWith(scheme))
+ {
+ try
+ {
+ Uri foundUri = new Uri(assemblyName.CodeBase);
+ if (codeBaseUri.Equals(foundUri)) return true;
+#if !FxCop
+ }
+ catch (Exception)
+ {
+#else
+ }finally{
+#endif
+ }
+ }
+ }
+ return false;
+ }
+ }
+ /// <summary>
+ /// Returns the original location of the corresponding assembly if available, otherwise returns the location of the shadow copy.
+ /// If the corresponding assembly is not in the GAC, null is returned.
+ /// </summary>
+ public static string GetLocation(AssemblyReference assemblyReference)
+ {
+ if (assemblyReference == null) { Debug.Fail("assemblyReference == null"); return null; }
+ lock (GlobalAssemblyCache.Lock)
+ {
+ if (!GlobalAssemblyCache.FusionLoaded)
+ {
+ GlobalAssemblyCache.FusionLoaded = true;
+ System.Reflection.Assembly systemAssembly = typeof(object).Assembly;
+ //^ assume systemAssembly != null && systemAssembly.Location != null;
+ string dir = Path.GetDirectoryName(systemAssembly.Location);
+ //^ assume dir != null;
+ GlobalAssemblyCache.LoadLibrary(Path.Combine(dir, "fusion.dll"));
+ }
+ IAssemblyEnum assemblyEnum;
+ CreateAssemblyEnum(out assemblyEnum, null, null, ASM_CACHE.GAC, 0);
+ if (assemblyEnum == null) return null;
+ IApplicationContext applicationContext;
+ IAssemblyName currentName;
+ while (assemblyEnum.GetNextAssembly(out applicationContext, out currentName, 0) == 0)
+ {
+ //^ assume currentName != null;
+ AssemblyName aName = new AssemblyName(currentName);
+ if (assemblyReference.Matches(aName.Name, aName.Version, aName.Culture, aName.PublicKeyToken))
+ {
+ string codeBase = aName.CodeBase;
+ if (codeBase != null && codeBase.StartsWith("file:///"))
+ return codeBase.Substring(8);
+ return aName.GetLocation();
+ }
+ }
+ return null;
+ }
+ }
+
+ [DllImport("kernel32.dll", CharSet = CharSet.Ansi)]
+ private static extern IntPtr LoadLibrary(string lpFileName);
+ [DllImport("fusion.dll", CharSet = CharSet.Auto)]
+ private static extern int CreateAssemblyEnum(out IAssemblyEnum ppEnum, IApplicationContext pAppCtx, IAssemblyName pName, uint dwFlags, int pvReserved);
+ private class ASM_CACHE
+ {
+ private ASM_CACHE() { }
+ public const uint ZAP = 1;
+ public const uint GAC = 2;
+ public const uint DOWNLOAD = 4;
+ }
+ }
+ internal class AssemblyName
+ {
+ IAssemblyName/*!*/ assemblyName;
+
+ internal AssemblyName(IAssemblyName/*!*/ assemblyName)
+ {
+ this.assemblyName = assemblyName;
+ //^ base();
+ }
+
+ internal string/*!*/ Name
+ {
+ //set {this.WriteString(ASM_NAME.NAME, value);}
+ get { return this.ReadString(ASM_NAME.NAME); }
+ }
+ internal Version Version
+ {
+ //set{
+ // if (value == null) throw new ArgumentNullException();
+ // this.WriteUInt16(ASM_NAME.MAJOR_VERSION, (ushort)value.Major);
+ // this.WriteUInt16(ASM_NAME.MINOR_VERSION, (ushort)value.Minor);
+ // this.WriteUInt16(ASM_NAME.BUILD_NUMBER, (ushort)value.Build);
+ // this.WriteUInt16(ASM_NAME.REVISION_NUMBER, (ushort)value.Revision);
+ //}
+ get
+ {
+ int major = this.ReadUInt16(ASM_NAME.MAJOR_VERSION);
+ int minor = this.ReadUInt16(ASM_NAME.MINOR_VERSION);
+ int build = this.ReadUInt16(ASM_NAME.BUILD_NUMBER);
+ int revision = this.ReadUInt16(ASM_NAME.REVISION_NUMBER);
+ return new Version(major, minor, build, revision);
+ }
+ }
+ internal string/*!*/ Culture
+ {
+ //set {this.WriteString(ASM_NAME.CULTURE, value);}
+ get { return this.ReadString(ASM_NAME.CULTURE); }
+ }
+ internal byte[]/*!*/ PublicKeyToken
+ {
+ //set {this.WriteBytes(ASM_NAME.PUBLIC_KEY_TOKEN, value); }
+ get { return this.ReadBytes(ASM_NAME.PUBLIC_KEY_TOKEN); }
+ }
+ internal string StrongName
+ {
+ get
+ {
+ uint size = 0;
+ this.assemblyName.GetDisplayName(null, ref size, (uint)AssemblyNameDisplayFlags.ALL);
+ if (size == 0) return "";
+ StringBuilder strongName = new StringBuilder((int)size);
+ this.assemblyName.GetDisplayName(strongName, ref size, (uint)AssemblyNameDisplayFlags.ALL);
+ return strongName.ToString();
+ }
+ }
+ internal string/*!*/ CodeBase
+ {
+ //set {this.WriteString(ASM_NAME.CODEBASE_URL, value);}
+ get { return this.ReadString(ASM_NAME.CODEBASE_URL); }
+ }
+ public override string ToString()
+ {
+ return this.StrongName;
+ }
+ internal string GetLocation()
+ {
+ IAssemblyCache assemblyCache;
+ CreateAssemblyCache(out assemblyCache, 0);
+ if (assemblyCache == null) return null;
+ ASSEMBLY_INFO assemblyInfo = new ASSEMBLY_INFO();
+ assemblyInfo.cbAssemblyInfo = (uint)Marshal.SizeOf(typeof(ASSEMBLY_INFO));
+ assemblyCache.QueryAssemblyInfo(ASSEMBLYINFO_FLAG.VALIDATE | ASSEMBLYINFO_FLAG.GETSIZE, this.StrongName, ref assemblyInfo);
+ if (assemblyInfo.cbAssemblyInfo == 0) return null;
+ assemblyInfo.pszCurrentAssemblyPathBuf = new string(new char[assemblyInfo.cchBuf]);
+ assemblyCache.QueryAssemblyInfo(ASSEMBLYINFO_FLAG.VALIDATE | ASSEMBLYINFO_FLAG.GETSIZE, this.StrongName, ref assemblyInfo);
+ String value = assemblyInfo.pszCurrentAssemblyPathBuf;
+ return value;
+ }
+ private string/*!*/ ReadString(uint assemblyNameProperty)
+ {
+ uint size = 0;
+ this.assemblyName.GetProperty(assemblyNameProperty, IntPtr.Zero, ref size);
+ if (size == 0 || size > Int16.MaxValue) return String.Empty;
+ IntPtr ptr = Marshal.AllocHGlobal((int)size);
+ this.assemblyName.GetProperty(assemblyNameProperty, ptr, ref size);
+ String str = Marshal.PtrToStringUni(ptr);
+ //^ assume str != null;
+ Marshal.FreeHGlobal(ptr);
+ return str;
+ }
+ private ushort ReadUInt16(uint assemblyNameProperty)
+ {
+ uint size = 0;
+ this.assemblyName.GetProperty(assemblyNameProperty, IntPtr.Zero, ref size);
+ IntPtr ptr = Marshal.AllocHGlobal((int)size);
+ this.assemblyName.GetProperty(assemblyNameProperty, ptr, ref size);
+ ushort value = (ushort)Marshal.ReadInt16(ptr);
+ Marshal.FreeHGlobal(ptr);
+ return value;
+ }
+ private byte[]/*!*/ ReadBytes(uint assemblyNameProperty)
+ {
+ uint size = 0;
+ this.assemblyName.GetProperty(assemblyNameProperty, IntPtr.Zero, ref size);
+ IntPtr ptr = Marshal.AllocHGlobal((int)size);
+ this.assemblyName.GetProperty(assemblyNameProperty, ptr, ref size);
+ byte[] value = new byte[(int)size];
+ Marshal.Copy(ptr, value, 0, (int)size);
+ Marshal.FreeHGlobal(ptr);
+ return value;
+ }
+
+ [DllImport("fusion.dll", CharSet = CharSet.Auto)]
+ private static extern int CreateAssemblyCache(out IAssemblyCache ppAsmCache, uint dwReserved);
+ private class CREATE_ASM_NAME_OBJ_FLAGS
+ {
+ private CREATE_ASM_NAME_OBJ_FLAGS() { }
+ public const uint CANOF_PARSE_DISPLAY_NAME = 0x1;
+ public const uint CANOF_SET_DEFAULT_VALUES = 0x2;
+ }
+ private class ASM_NAME
+ {
+ private ASM_NAME() { }
+ public const uint PUBLIC_KEY = 0;
+ public const uint PUBLIC_KEY_TOKEN = 1;
+ public const uint HASH_VALUE = 2;
+ public const uint NAME = 3;
+ public const uint MAJOR_VERSION = 4;
+ public const uint MINOR_VERSION = 5;
+ public const uint BUILD_NUMBER = 6;
+ public const uint REVISION_NUMBER = 7;
+ public const uint CULTURE = 8;
+ public const uint PROCESSOR_ID_ARRAY = 9;
+ public const uint OSINFO_ARRAY = 10;
+ public const uint HASH_ALGID = 11;
+ public const uint ALIAS = 12;
+ public const uint CODEBASE_URL = 13;
+ public const uint CODEBASE_LASTMOD = 14;
+ public const uint NULL_PUBLIC_KEY = 15;
+ public const uint NULL_PUBLIC_KEY_TOKEN = 16;
+ public const uint CUSTOM = 17;
+ public const uint NULL_CUSTOM = 18;
+ public const uint MVID = 19;
+ public const uint _32_BIT_ONLY = 20;
+ }
+ [Flags]
+ internal enum AssemblyNameDisplayFlags
+ {
+ VERSION = 0x01,
+ CULTURE = 0x02,
+ PUBLIC_KEY_TOKEN = 0x04,
+ PROCESSORARCHITECTURE = 0x20,
+ RETARGETABLE = 0x80,
+ ALL = VERSION | CULTURE | PUBLIC_KEY_TOKEN | PROCESSORARCHITECTURE | RETARGETABLE
+ }
+ private class ASSEMBLYINFO_FLAG
+ {
+ private ASSEMBLYINFO_FLAG() { }
+ public const uint VALIDATE = 1;
+ public const uint GETSIZE = 2;
+ }
+ [StructLayout(LayoutKind.Sequential)]
+ private struct ASSEMBLY_INFO
+ {
+ public uint cbAssemblyInfo;
+ public uint dwAssemblyFlags;
+ public ulong uliAssemblySizeInKB;
+ [MarshalAs(UnmanagedType.LPWStr)]
+ public string pszCurrentAssemblyPathBuf;
+ public uint cchBuf;
+ }
+ [ComImport(), Guid("E707DCDE-D1CD-11D2-BAB9-00C04F8ECEAE"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ private interface IAssemblyCache
+ {
+ [PreserveSig()]
+ int UninstallAssembly(uint dwFlags, [MarshalAs(UnmanagedType.LPWStr)] string pszAssemblyName, IntPtr pvReserved, int pulDisposition);
+ [PreserveSig()]
+ int QueryAssemblyInfo(uint dwFlags, [MarshalAs(UnmanagedType.LPWStr)] string pszAssemblyName, ref ASSEMBLY_INFO pAsmInfo);
+ [PreserveSig()]
+ int CreateAssemblyCacheItem(uint dwFlags, IntPtr pvReserved, out object ppAsmItem, [MarshalAs(UnmanagedType.LPWStr)] string pszAssemblyName);
+ [PreserveSig()]
+ int CreateAssemblyScavenger(out object ppAsmScavenger);
+ [PreserveSig()]
+ int InstallAssembly(uint dwFlags, [MarshalAs(UnmanagedType.LPWStr)] string pszManifestFilePath, IntPtr pvReserved);
+ }
+ }
+ [ComImport(), Guid("CD193BC0-B4BC-11D2-9833-00C04FC31D2E"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ interface IAssemblyName
+ {
+ [PreserveSig()]
+ int SetProperty(uint PropertyId, IntPtr pvProperty, uint cbProperty);
+ [PreserveSig()]
+ int GetProperty(uint PropertyId, IntPtr pvProperty, ref uint pcbProperty);
+ [PreserveSig()]
+ int Finalize();
+ [PreserveSig()]
+ int GetDisplayName(StringBuilder szDisplayName, ref uint pccDisplayName, uint dwDisplayFlags);
+ [PreserveSig()]
+ int BindToObject(object refIID, object pAsmBindSink, IApplicationContext pApplicationContext, [MarshalAs(UnmanagedType.LPWStr)] string szCodeBase, long llFlags, int pvReserved, uint cbReserved, out int ppv);
+ [PreserveSig()]
+ int GetName(out uint lpcwBuffer, out int pwzName);
+ [PreserveSig()]
+ int GetVersion(out uint pdwVersionHi, out uint pdwVersionLow);
+ [PreserveSig()]
+ int IsEqual(IAssemblyName pName, uint dwCmpFlags);
+ [PreserveSig()]
+ int Clone(out IAssemblyName pName);
+ }
+ [ComImport(), Guid("7C23FF90-33AF-11D3-95DA-00A024A85B51"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ interface IApplicationContext
+ {
+ void SetContextNameObject(IAssemblyName pName);
+ void GetContextNameObject(out IAssemblyName ppName);
+ void Set([MarshalAs(UnmanagedType.LPWStr)] string szName, int pvValue, uint cbValue, uint dwFlags);
+ void Get([MarshalAs(UnmanagedType.LPWStr)] string szName, out int pvValue, ref uint pcbValue, uint dwFlags);
+ void GetDynamicDirectory(out int wzDynamicDir, ref uint pdwSize);
+ }
+ [ComImport(), Guid("21B8916C-F28E-11D2-A473-00C04F8EF448"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ interface IAssemblyEnum
+ {
+ [PreserveSig()]
+ int GetNextAssembly(out IApplicationContext ppAppCtx, out IAssemblyName ppName, uint dwFlags);
+ [PreserveSig()]
+ int Reset();
+ [PreserveSig()]
+ int Clone(out IAssemblyEnum ppEnum);
+ }
+}
+#else
+//TODO: provide a way to query ROTOR GAC
+#endif