1 // Copyright (c) Microsoft. All rights reserved.
2 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 
4 using System;
5 using System.IO;
6 using System.Text;
7 using System.Reflection;
8 using System.Runtime.InteropServices;
9 using Microsoft.Build.Shared;
10 using System.Collections.Generic;
11 using System.Collections;
12 using System.Globalization;
13 using System.Linq;
14 using System.Runtime.ExceptionServices;
15 using System.Text.RegularExpressions;
16 
17 namespace Microsoft.Build.Tasks
18 {
19 #if FEATURE_COM_INTEROP
20     /// <summary>
21     /// The original ITypeInfo interface in the CLR has incorrect definitions for GetRefTypeOfImplType and GetRefTypeInfo.
22     /// It uses ints for marshalling handles which will result in a crash on 64 bit systems. This is a temporary interface
23     /// for use until the one in the CLR is fixed. When it is we can go back to using ITypeInfo.
24     /// </summary>
25     [Guid("00020401-0000-0000-C000-000000000046")]
26     [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
27     [ComImport]
28     public interface IFixedTypeInfo
29     {
GetTypeAttr(out IntPtr ppTypeAttr)30         void GetTypeAttr(out IntPtr ppTypeAttr);
GetTypeComp(out System.Runtime.InteropServices.ComTypes.ITypeComp ppTComp)31         void GetTypeComp(out System.Runtime.InteropServices.ComTypes.ITypeComp ppTComp);
GetFuncDesc(int index, out IntPtr ppFuncDesc)32         void GetFuncDesc(int index, out IntPtr ppFuncDesc);
GetVarDesc(int index, out IntPtr ppVarDesc)33         void GetVarDesc(int index, out IntPtr ppVarDesc);
GetNames(int memid, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2), Out] String[] rgBstrNames, int cMaxNames, out int pcNames)34         void GetNames(int memid, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2), Out] String[] rgBstrNames, int cMaxNames, out int pcNames);
GetRefTypeOfImplType(int index, out IntPtr href)35         void GetRefTypeOfImplType(int index, out IntPtr href);
GetImplTypeFlags(int index, out System.Runtime.InteropServices.ComTypes.IMPLTYPEFLAGS pImplTypeFlags)36         void GetImplTypeFlags(int index, out System.Runtime.InteropServices.ComTypes.IMPLTYPEFLAGS pImplTypeFlags);
GetIDsOfNames([MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 1), In] String[] rgszNames, int cNames, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1), Out] int[] pMemId)37         void GetIDsOfNames([MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 1), In] String[] rgszNames, int cNames, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1), Out] int[] pMemId);
Invoke([MarshalAs(UnmanagedType.IUnknown)] Object pvInstance, int memid, Int16 wFlags, ref System.Runtime.InteropServices.ComTypes.DISPPARAMS pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, out int puArgErr)38         void Invoke([MarshalAs(UnmanagedType.IUnknown)] Object pvInstance, int memid, Int16 wFlags, ref System.Runtime.InteropServices.ComTypes.DISPPARAMS pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, out int puArgErr);
GetDocumentation(int index, out String strName, out String strDocString, out int dwHelpContext, out String strHelpFile)39         void GetDocumentation(int index, out String strName, out String strDocString, out int dwHelpContext, out String strHelpFile);
GetDllEntry(int memid, System.Runtime.InteropServices.ComTypes.INVOKEKIND invKind, IntPtr pBstrDllName, IntPtr pBstrName, IntPtr pwOrdinal)40         void GetDllEntry(int memid, System.Runtime.InteropServices.ComTypes.INVOKEKIND invKind, IntPtr pBstrDllName, IntPtr pBstrName, IntPtr pwOrdinal);
GetRefTypeInfo(IntPtr hRef, out IFixedTypeInfo ppTI)41         void GetRefTypeInfo(IntPtr hRef, out IFixedTypeInfo ppTI);
AddressOfMember(int memid, System.Runtime.InteropServices.ComTypes.INVOKEKIND invKind, out IntPtr ppv)42         void AddressOfMember(int memid, System.Runtime.InteropServices.ComTypes.INVOKEKIND invKind, out IntPtr ppv);
CreateInstance([MarshalAs(UnmanagedType.IUnknown)] Object pUnkOuter, [In] ref Guid riid, [MarshalAs(UnmanagedType.IUnknown), Out] out Object ppvObj)43         void CreateInstance([MarshalAs(UnmanagedType.IUnknown)] Object pUnkOuter, [In] ref Guid riid, [MarshalAs(UnmanagedType.IUnknown), Out] out Object ppvObj);
GetMops(int memid, out String pBstrMops)44         void GetMops(int memid, out String pBstrMops);
GetContainingTypeLib(out System.Runtime.InteropServices.ComTypes.ITypeLib ppTLB, out int pIndex)45         void GetContainingTypeLib(out System.Runtime.InteropServices.ComTypes.ITypeLib ppTLB, out int pIndex);
46         [PreserveSig]
ReleaseTypeAttr(IntPtr pTypeAttr)47         void ReleaseTypeAttr(IntPtr pTypeAttr);
48         [PreserveSig]
ReleaseFuncDesc(IntPtr pFuncDesc)49         void ReleaseFuncDesc(IntPtr pFuncDesc);
50         [PreserveSig]
ReleaseVarDesc(IntPtr pVarDesc)51         void ReleaseVarDesc(IntPtr pVarDesc);
52     }
53 
54     [GuidAttribute("00020406-0000-0000-C000-000000000046")]
55     [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
56     [ComImport]
57     internal interface UCOMICreateITypeLib
58     {
CreateTypeInfo()59         void CreateTypeInfo();
SetName()60         void SetName();
SetVersion()61         void SetVersion();
SetGuid()62         void SetGuid();
SetDocString()63         void SetDocString();
SetHelpFileName()64         void SetHelpFileName();
SetHelpContext()65         void SetHelpContext();
SetLcid()66         void SetLcid();
SetLibFlags()67         void SetLibFlags();
SaveAllChanges()68         void SaveAllChanges();
69     }
70 
71     [ComImport]
72     [Guid("E5CB7A31-7512-11d2-89CE-0080C792E5D8")]
73     [TypeLibType(TypeLibTypeFlags.FCanCreate)]
74     [ClassInterface(ClassInterfaceType.None)]
75     internal class CorMetaDataDispenser
76     {
77     }
78 
79     [ComImport]
80     [Guid("809c652e-7396-11d2-9771-00a0c9b4d50c")]
81     [InterfaceType(ComInterfaceType.InterfaceIsIUnknown /*0x0001*/)]
82     [TypeLibType(TypeLibTypeFlags.FRestricted /*0x0200*/)]
83     internal interface IMetaDataDispenser
84     {
85         [return: MarshalAs(UnmanagedType.Interface)]
DefineScope([In] ref Guid rclsid, [In] UInt32 dwCreateFlags, [In] ref Guid riid)86         object DefineScope([In] ref Guid rclsid, [In] UInt32 dwCreateFlags, [In] ref Guid riid);
87 
88         [return: MarshalAs(UnmanagedType.Interface)]
OpenScope([In][MarshalAs(UnmanagedType.LPWStr)] string szScope, [In] UInt32 dwOpenFlags, [In] ref Guid riid)89         object OpenScope([In][MarshalAs(UnmanagedType.LPWStr)]  string szScope, [In] UInt32 dwOpenFlags, [In] ref Guid riid);
90 
91         [return: MarshalAs(UnmanagedType.Interface)]
OpenScopeOnMemory([In] IntPtr pData, [In] UInt32 cbData, [In] UInt32 dwOpenFlags, [In] ref Guid riid)92         object OpenScopeOnMemory([In] IntPtr pData, [In] UInt32 cbData, [In] UInt32 dwOpenFlags, [In] ref Guid riid);
93     }
94 
95     [ComImport]
96     [Guid("7DAC8207-D3AE-4c75-9B67-92801A497D44")]
97     [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
98     internal interface IMetaDataImport
99     {
100         // PreserveSig because this method is an exception that
101         // actually returns void, not HRESULT.
102         [PreserveSig]
CloseEnum()103         void CloseEnum();
CountEnum(IntPtr iRef, ref System.UInt32 ulCount)104         void CountEnum(IntPtr iRef, ref System.UInt32 ulCount);
ResetEnum()105         void ResetEnum();
EnumTypeDefs()106         void EnumTypeDefs();
EnumInterfaceImpls()107         void EnumInterfaceImpls();
EnumTypeRefs()108         void EnumTypeRefs();
FindTypeDefByName()109         void FindTypeDefByName();
GetScopeProps()110         void GetScopeProps();
GetModuleFromScope()111         void GetModuleFromScope();
GetTypeDefProps()112         void GetTypeDefProps();
GetInterfaceImplProps()113         void GetInterfaceImplProps();
GetTypeRefProps()114         void GetTypeRefProps();
ResolveTypeRef()115         void ResolveTypeRef();
EnumMembers()116         void EnumMembers();
EnumMembersWithName()117         void EnumMembersWithName();
EnumMethods()118         void EnumMethods();
EnumMethodsWithName()119         void EnumMethodsWithName();
EnumFields()120         void EnumFields();
EnumFieldsWithName()121         void EnumFieldsWithName();
EnumParams()122         void EnumParams();
EnumMemberRefs()123         void EnumMemberRefs();
EnumMethodImpls()124         void EnumMethodImpls();
EnumPermissionSets()125         void EnumPermissionSets();
FindMember()126         void FindMember();
FindMethod()127         void FindMethod();
FindField()128         void FindField();
FindMemberRef()129         void FindMemberRef();
GetMethodProps()130         void GetMethodProps();
GetMemberRefProps()131         void GetMemberRefProps();
EnumProperties()132         void EnumProperties();
EnumEvents()133         void EnumEvents();
GetEventProps()134         void GetEventProps();
EnumMethodSemantics()135         void EnumMethodSemantics();
GetMethodSemantics()136         void GetMethodSemantics();
GetClassLayout()137         void GetClassLayout();
GetFieldMarshal()138         void GetFieldMarshal();
GetRVA()139         void GetRVA();
GetPermissionSetProps()140         void GetPermissionSetProps();
GetSigFromToken()141         void GetSigFromToken();
GetModuleRefProps()142         void GetModuleRefProps();
EnumModuleRefs()143         void EnumModuleRefs();
GetTypeSpecFromToken()144         void GetTypeSpecFromToken();
GetNameFromToken()145         void GetNameFromToken();
EnumUnresolvedMethods()146         void EnumUnresolvedMethods();
GetUserString()147         void GetUserString();
GetPinvokeMap()148         void GetPinvokeMap();
EnumSignatures()149         void EnumSignatures();
EnumTypeSpecs()150         void EnumTypeSpecs();
EnumUserStrings()151         void EnumUserStrings();
GetParamForMethodIndex()152         void GetParamForMethodIndex();
EnumCustomAttributes()153         void EnumCustomAttributes();
GetCustomAttributeProps()154         void GetCustomAttributeProps();
FindTypeRef()155         void FindTypeRef();
GetMemberProps()156         void GetMemberProps();
GetFieldProps()157         void GetFieldProps();
GetPropertyProps()158         void GetPropertyProps();
GetParamProps()159         void GetParamProps();
GetCustomAttributeByName()160         void GetCustomAttributeByName();
IsValidToken()161         void IsValidToken();  // Note: Need preservesig for this if ever going to be used.
GetNestedClassProps()162         void GetNestedClassProps();
GetNativeCallConvFromSig()163         void GetNativeCallConvFromSig();
IsGlobal()164         void IsGlobal();
165     }
166 
167     [ComImport]
168     [Guid("FCE5EFA0-8BBA-4f8e-A036-8F2022B08466")]
169     [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
170     internal interface IMetaDataImport2
171     {
CloseEnum()172         void CloseEnum();
CountEnum()173         void CountEnum();
ResetEnum()174         void ResetEnum();
EnumTypeDefs()175         void EnumTypeDefs();
EnumInterfaceImpls()176         void EnumInterfaceImpls();
EnumTypeRefs()177         void EnumTypeRefs();
FindTypeDefByName()178         void FindTypeDefByName();
GetScopeProps()179         void GetScopeProps();
GetModuleFromScope()180         void GetModuleFromScope();
GetTypeDefProps()181         void GetTypeDefProps();
GetInterfaceImplProps()182         void GetInterfaceImplProps();
GetTypeRefProps()183         void GetTypeRefProps();
ResolveTypeRef()184         void ResolveTypeRef();
EnumMembers()185         void EnumMembers();
EnumMembersWithName()186         void EnumMembersWithName();
EnumMethods()187         void EnumMethods();
EnumMethodsWithName()188         void EnumMethodsWithName();
EnumFields()189         void EnumFields();
EnumFieldsWithName()190         void EnumFieldsWithName();
EnumParams()191         void EnumParams();
EnumMemberRefs()192         void EnumMemberRefs();
EnumMethodImpls()193         void EnumMethodImpls();
EnumPermissionSets()194         void EnumPermissionSets();
FindMember()195         void FindMember();
FindMethod()196         void FindMethod();
FindField()197         void FindField();
FindMemberRef()198         void FindMemberRef();
GetMethodProps()199         void GetMethodProps();
GetMemberRefProps()200         void GetMemberRefProps();
EnumProperties()201         void EnumProperties();
EnumEvents()202         void EnumEvents();
GetEventProps()203         void GetEventProps();
EnumMethodSemantics()204         void EnumMethodSemantics();
GetMethodSemantics()205         void GetMethodSemantics();
GetClassLayout()206         void GetClassLayout();
GetFieldMarshal()207         void GetFieldMarshal();
GetRVA()208         void GetRVA();
GetPermissionSetProps()209         void GetPermissionSetProps();
GetSigFromToken()210         void GetSigFromToken();
GetModuleRefProps()211         void GetModuleRefProps();
EnumModuleRefs()212         void EnumModuleRefs();
GetTypeSpecFromToken()213         void GetTypeSpecFromToken();
GetNameFromToken()214         void GetNameFromToken();
EnumUnresolvedMethods()215         void EnumUnresolvedMethods();
GetUserString()216         void GetUserString();
GetPinvokeMap()217         void GetPinvokeMap();
EnumSignatures()218         void EnumSignatures();
EnumTypeSpecs()219         void EnumTypeSpecs();
EnumUserStrings()220         void EnumUserStrings();
GetParamForMethodIndex()221         void GetParamForMethodIndex();
EnumCustomAttributes()222         void EnumCustomAttributes();
GetCustomAttributeProps()223         void GetCustomAttributeProps();
FindTypeRef()224         void FindTypeRef();
GetMemberProps()225         void GetMemberProps();
GetFieldProps()226         void GetFieldProps();
GetPropertyProps()227         void GetPropertyProps();
GetParamProps()228         void GetParamProps();
229         [PreserveSig]
GetCustomAttributeByName(UInt32 mdTokenObj, [MarshalAs(UnmanagedType.LPWStr)] string szName, out IntPtr ppData, out uint pDataSize)230         int GetCustomAttributeByName(UInt32 mdTokenObj, [MarshalAs(UnmanagedType.LPWStr)] string szName, out IntPtr ppData, out uint pDataSize);
IsValidToken()231         void IsValidToken();
GetNestedClassProps()232         void GetNestedClassProps();
GetNativeCallConvFromSig()233         void GetNativeCallConvFromSig();
IsGlobal()234         void IsGlobal();
EnumGenericParams()235         void EnumGenericParams();
GetGenericParamProps()236         void GetGenericParamProps();
GetMethodSpecProps()237         void GetMethodSpecProps();
EnumGenericParamConstraints()238         void EnumGenericParamConstraints();
GetGenericParamConstraintProps()239         void GetGenericParamConstraintProps();
GetPEKind(out UInt32 pdwPEKind, out UInt32 pdwMachine)240         void GetPEKind(out UInt32 pdwPEKind, out UInt32 pdwMachine);
GetVersionString([MarshalAs(UnmanagedType.LPArray)] char[] pwzBuf, UInt32 ccBufSize, out UInt32 pccBufSize)241         void GetVersionString([MarshalAs(UnmanagedType.LPArray)] char[] pwzBuf, UInt32 ccBufSize, out UInt32 pccBufSize);
242     }
243 
244     // Flags for OpenScope
245     internal enum CorOpenFlags
246     {
247         ofRead = 0x00000000,     // Open scope for read
248         ofWrite = 0x00000001,     // Open scope for write.
249         ofCopyMemory = 0x00000002,     // Open scope with memory. Ask metadata to maintain its own copy of memory.
250         ofCacheImage = 0x00000004,     // EE maps but does not do relocations or verify image
251         ofNoTypeLib = 0x00000080,     // Don't OpenScope on a typelib.
252     };
253 
254     [ComImport]
255     [Guid("EE62470B-E94B-424e-9B7C-2F00C9249F93")]
256     [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
257     internal interface IMetaDataAssemblyImport
258     {
GetAssemblyProps(UInt32 mdAsm, out IntPtr pPublicKeyPtr, out UInt32 ucbPublicKeyPtr, out UInt32 uHashAlg, [MarshalAs(UnmanagedType.LPArray)] char[] strName, UInt32 cchNameIn, out UInt32 cchNameRequired, IntPtr amdInfo, out UInt32 dwFlags)259         void GetAssemblyProps(UInt32 mdAsm, out IntPtr pPublicKeyPtr, out UInt32 ucbPublicKeyPtr, out UInt32 uHashAlg, [MarshalAs(UnmanagedType.LPArray)] char[] strName, UInt32 cchNameIn, out UInt32 cchNameRequired, IntPtr amdInfo, out UInt32 dwFlags);
GetAssemblyRefProps(UInt32 mdAsmRef, out IntPtr ppbPublicKeyOrToken, out UInt32 pcbPublicKeyOrToken, [MarshalAs(UnmanagedType.LPArray)] char[] strName, UInt32 cchNameIn, out UInt32 pchNameOut, IntPtr amdInfo, out IntPtr ppbHashValue, out UInt32 pcbHashValue, out UInt32 pdwAssemblyRefFlags)260         void GetAssemblyRefProps(UInt32 mdAsmRef, out IntPtr ppbPublicKeyOrToken, out UInt32 pcbPublicKeyOrToken, [MarshalAs(UnmanagedType.LPArray)] char[] strName, UInt32 cchNameIn, out UInt32 pchNameOut, IntPtr amdInfo, out IntPtr ppbHashValue, out UInt32 pcbHashValue, out UInt32 pdwAssemblyRefFlags);
GetFileProps([In] UInt32 mdFile, [MarshalAs(UnmanagedType.LPArray)] char[] strName, UInt32 cchName, out UInt32 cchNameRequired, out IntPtr bHashData, out UInt32 cchHashBytes, out UInt32 dwFileFlags)261         void GetFileProps([In] UInt32 mdFile, [MarshalAs(UnmanagedType.LPArray)] char[] strName, UInt32 cchName, out UInt32 cchNameRequired, out IntPtr bHashData, out UInt32 cchHashBytes, out UInt32 dwFileFlags);
GetExportedTypeProps()262         void GetExportedTypeProps();
GetManifestResourceProps()263         void GetManifestResourceProps();
EnumAssemblyRefs([In, Out] ref IntPtr phEnum, [MarshalAs(UnmanagedType.LPArray), Out] UInt32[] asmRefs, System.UInt32 asmRefCount, out System.UInt32 iFetched)264         void EnumAssemblyRefs([In, Out] ref IntPtr phEnum, [MarshalAs(UnmanagedType.LPArray), Out] UInt32[] asmRefs, System.UInt32 asmRefCount, out System.UInt32 iFetched);
EnumFiles([In, Out] ref IntPtr phEnum, [MarshalAs(UnmanagedType.LPArray), Out] UInt32[] fileRefs, System.UInt32 fileRefCount, out System.UInt32 iFetched)265         void EnumFiles([In, Out] ref IntPtr phEnum, [MarshalAs(UnmanagedType.LPArray), Out] UInt32[] fileRefs, System.UInt32 fileRefCount, out System.UInt32 iFetched);
EnumExportedTypes()266         void EnumExportedTypes();
EnumManifestResources()267         void EnumManifestResources();
GetAssemblyFromScope(out UInt32 mdAsm)268         void GetAssemblyFromScope(out UInt32 mdAsm);
FindExportedTypeByName()269         void FindExportedTypeByName();
FindManifestResourceByName()270         void FindManifestResourceByName();
271         // PreserveSig because this method is an exception that
272         // actually returns void, not HRESULT.
273         [PreserveSig]
CloseEnum([In] IntPtr phEnum)274         void CloseEnum([In] IntPtr phEnum);
FindAssembliesByName()275         void FindAssembliesByName();
276     }
277 
278     [ComImport]
279     [Guid("00000001-0000-0000-c000-000000000046")]
280     [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
281     internal interface IClassFactory
282     {
CreateInstance([MarshalAs(UnmanagedType.IUnknown)] object pUnkOuter, ref Guid riid, [MarshalAs(UnmanagedType.IUnknown), Out] out object ppvObject)283         void CreateInstance([MarshalAs(UnmanagedType.IUnknown)] object pUnkOuter, ref Guid riid, [MarshalAs(UnmanagedType.IUnknown), Out] out object ppvObject);
LockServer(bool fLock)284         void LockServer(bool fLock);
285     }
286 
287     // Subset of CorAssemblyFlags from corhdr.h
288     internal enum CorAssemblyFlags : uint
289     {
290         afPublicKey = 0x0001,            // The assembly ref holds the full (unhashed) public key.
291         afRetargetable = 0x0100            // The assembly can be retargeted (at runtime) to an
292                                            //  assembly from a different publisher.
293     };
294 
295     /*
296     From cor.h:
297         typedef struct
298         {
299             USHORT      usMajorVersion;         // Major Version.
300             USHORT      usMinorVersion;         // Minor Version.
301             USHORT      usBuildNumber;          // Build Number.
302             USHORT      usRevisionNumber;       // Revision Number.
303             LPWSTR      szLocale;               // Locale.
304             ULONG       cbLocale;               // [IN/OUT] Size of the buffer in wide chars/Actual size.
305             DWORD       *rProcessor;            // Processor ID array.
306             ULONG       ulProcessor;            // [IN/OUT] Size of the Processor ID array/Actual # of entries filled in.
307             OSINFO      *rOS;                   // OSINFO array.
308             ULONG       ulOS;                   // [IN/OUT]Size of the OSINFO array/Actual # of entries filled in.
309         } ASSEMBLYMETADATA;
310     */
311     [StructLayout(LayoutKind.Sequential)]
312     internal struct ASSEMBLYMETADATA
313     {
314         public UInt16 usMajorVersion;
315         public UInt16 usMinorVersion;
316         public UInt16 usBuildNumber;
317         public UInt16 usRevisionNumber;
318         public IntPtr rpLocale;
319         public UInt32 cchLocale;
320         public IntPtr rpProcessors;
321         public UInt32 cProcessors;
322         public IntPtr rOses;
323         public UInt32 cOses;
324     }
325 
326     internal enum ASSEMBLYINFO_FLAG
327     {
328         VALIDATE = 1,
329         GETSIZE = 2
330     }
331 
332     [StructLayout(LayoutKind.Sequential)]
333     internal struct ASSEMBLY_INFO
334     {
335         public uint cbAssemblyInfo;
336         public uint dwAssemblyFlags;
337         public ulong uliAssemblySizeInKB;
338         [MarshalAs(UnmanagedType.LPWStr)]
339         public string pszCurrentAssemblyPathBuf;
340         public uint cchBuf;
341     }
342 
343     [ComImport(), Guid("E707DCDE-D1CD-11D2-BAB9-00C04F8ECEAE"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
344     internal interface IAssemblyCache
345     {
346         /* Unused.
347         [PreserveSig()]
348         int UninstallAssembly(uint dwFlags, [MarshalAs(UnmanagedType.LPWStr)] string pszAssemblyName, IntPtr pvReserved, int pulDisposition);
349          */
UninstallAssembly()350         int UninstallAssembly();
351 
352         [PreserveSig()]
QueryAssemblyInfo(uint dwFlags, [MarshalAs(UnmanagedType.LPWStr)] string pszAssemblyName, ref ASSEMBLY_INFO pAsmInfo)353         uint QueryAssemblyInfo(uint dwFlags, [MarshalAs(UnmanagedType.LPWStr)] string pszAssemblyName, ref ASSEMBLY_INFO pAsmInfo);
354 
355         /* Unused.
356         [PreserveSig()]
357         int CreateAssemblyCacheItem(uint dwFlags, IntPtr pvReserved, out object ppAsmItem, [MarshalAs(UnmanagedType.LPWStr)] string pszAssemblyName);
358          */
CreateAssemblyCacheItem()359         int CreateAssemblyCacheItem();
360 
361         /* Unused.
362         [PreserveSig()]
363         int CreateAssemblyScavenger(out object ppAsmScavenger);
364          */
CreateAssemblyScavenger()365         int CreateAssemblyScavenger();
366 
367         /* Unused.
368         [PreserveSig()]
369         int InstallAssembly(uint dwFlags, [MarshalAs(UnmanagedType.LPWStr)] string pszManifestFilePath, IntPtr pvReserved);
370          */
InstallAssembly()371         int InstallAssembly();
372     }
373 
374     [Flags]
375     internal enum AssemblyCacheFlags
376     {
377         ZAP = 1,
378         GAC = 2,
379         DOWNLOAD = 4
380     }
381 
382     [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("CD193BC0-B4BC-11d2-9833-00C04FC31D2E")]
383     internal interface IAssemblyName
384     {
385         [PreserveSig()]
SetProperty( int PropertyId, IntPtr pvProperty, int cbProperty)386         int SetProperty(
387                 int PropertyId,
388                 IntPtr pvProperty,
389                 int cbProperty);
390 
391         [PreserveSig()]
GetProperty( int PropertyId, IntPtr pvProperty, ref int pcbProperty)392         int GetProperty(
393                 int PropertyId,
394                 IntPtr pvProperty,
395                 ref int pcbProperty);
396 
397         [PreserveSig()]
Finalize()398         int Finalize();
399 
400         [PreserveSig()]
GetDisplayName( StringBuilder pDisplayName, ref int pccDisplayName, int displayFlags)401         int GetDisplayName(
402                 StringBuilder pDisplayName,
403                 ref int pccDisplayName,
404                 int displayFlags);
405 
406         [PreserveSig()]
Reserved(ref Guid guid, Object obj1, Object obj2, String string1, Int64 llFlags, IntPtr pvReserved, int cbReserved, out IntPtr ppv)407         int Reserved(ref Guid guid,
408             Object obj1,
409             Object obj2,
410             String string1,
411             Int64 llFlags,
412             IntPtr pvReserved,
413             int cbReserved,
414             out IntPtr ppv);
415 
416         [PreserveSig()]
GetName( ref int pccBuffer, StringBuilder pwzName)417         int GetName(
418                 ref int pccBuffer,
419                 StringBuilder pwzName);
420 
421         [PreserveSig()]
GetVersion( out int versionHi, out int versionLow)422         int GetVersion(
423                 out int versionHi,
424                 out int versionLow);
425         [PreserveSig()]
IsEqual( IAssemblyName pAsmName, int cmpFlags)426         int IsEqual(
427                 IAssemblyName pAsmName,
428                 int cmpFlags);
429 
430         [PreserveSig()]
Clone(out IAssemblyName pAsmName)431         int Clone(out IAssemblyName pAsmName);
432     }// IAssemblyName
433 
434     [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("21b8916c-f28e-11d2-a473-00c04f8ef448")]
435     internal interface IAssemblyEnum
436     {
437         [PreserveSig()]
GetNextAssembly( IntPtr pvReserved, out IAssemblyName ppName, int flags)438         int GetNextAssembly(
439                 IntPtr pvReserved,
440                 out IAssemblyName ppName,
441                 int flags);
442         [PreserveSig()]
Reset()443         int Reset();
444         [PreserveSig()]
Clone(out IAssemblyEnum ppEnum)445         int Clone(out IAssemblyEnum ppEnum);
446     }// IAssemblyEnum
447 
448     internal enum CreateAssemblyNameObjectFlags
449     {
450         CANOF_DEFAULT = 0,
451         CANOF_PARSE_DISPLAY_NAME = 1,
452     }
453 
454     [Flags]
455     internal enum AssemblyNameDisplayFlags
456     {
457         VERSION = 0x01,
458         CULTURE = 0x02,
459         PUBLIC_KEY_TOKEN = 0x04,
460         PROCESSORARCHITECTURE = 0x20,
461         RETARGETABLE = 0x80,
462         // This enum will change in the future to include
463         // more attributes.
464         ALL = VERSION
465                                     | CULTURE
466                                     | PUBLIC_KEY_TOKEN
467                                     | PROCESSORARCHITECTURE
468                                     | RETARGETABLE
469     }
470 
471 #endif
472 
473     [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
474     internal struct STARTUPINFO
475     {
476         internal Int32 cb;
477         internal string lpReserved;
478         internal string lpDesktop;
479         internal string lpTitle;
480         internal Int32 dwX;
481         internal Int32 dwY;
482         internal Int32 dwXSize;
483         internal Int32 dwYSize;
484         internal Int32 dwXCountChars;
485         internal Int32 dwYCountChars;
486         internal Int32 dwFillAttribute;
487         internal Int32 dwFlags;
488         internal Int16 wShowWindow;
489         internal Int16 cbReserved2;
490         internal IntPtr lpReserved2;
491         internal IntPtr hStdInput;
492         internal IntPtr hStdOutput;
493         internal IntPtr hStdError;
494     }
495 
496     [StructLayout(LayoutKind.Sequential)]
497     internal struct PROCESS_INFORMATION
498     {
499         public IntPtr hProcess;
500         public IntPtr hThread;
501         public int dwProcessId;
502         public int dwThreadId;
503     }
504 
505     internal enum SymbolicLink
506     {
507         File = 0,
508         Directory = 1
509     }
510 
511     /// <summary>
512     /// Interop methods.
513     /// </summary>
514     internal static class NativeMethods
515     {
516         #region Constants
517 
518         internal static readonly IntPtr NullPtr = IntPtr.Zero;
519         internal static readonly IntPtr InvalidIntPtr = new IntPtr((int)-1);
520 
521         internal const uint NORMAL_PRIORITY_CLASS = 0x0020;
522         internal const uint CREATE_NO_WINDOW = 0x08000000;
523         internal const Int32 STARTF_USESTDHANDLES = 0x00000100;
524         internal const int ERROR_SUCCESS = 0;
525 
526         internal const int TYPE_E_REGISTRYACCESS = -2147319780;
527         internal const int TYPE_E_CANTLOADLIBRARY = -2147312566;
528 
529         internal const int HRESULT_E_CLASSNOTREGISTERED = -2147221164;
530 
531         internal const int ERROR_ACCESS_DENIED = -2147024891; // ACL'd or r/o
532         internal const int ERROR_SHARING_VIOLATION = -2147024864; // File locked by another use
533 
534         internal static Guid GUID_TYPELIB_NAMESPACE = new Guid("{0F21F359-AB84-41E8-9A78-36D110E6D2F9}");
535         internal static Guid GUID_ExportedFromComPlus = new Guid("{90883f05-3d28-11d2-8f17-00a0c9a6186d}");
536 
537         internal static Guid IID_IUnknown = new Guid("{00000000-0000-0000-C000-000000000046}");
538         internal static Guid IID_IDispatch = new Guid("{00020400-0000-0000-C000-000000000046}");
539         internal static Guid IID_ITypeInfo = new Guid("{00020401-0000-0000-C000-000000000046}");
540         internal static Guid IID_IEnumVariant = new Guid("{00020404-0000-0000-C000-000000000046}");
541         internal static Guid IID_IDispatchEx = new Guid("{A6EF9860-C720-11D0-9337-00A0C90DCAA9}");
542 
543         internal static Guid IID_StdOle = new Guid("{00020430-0000-0000-C000-000000000046}");
544 
545         // used in LoadTypeLibEx
546         internal enum REGKIND
547         {
548             REGKIND_DEFAULT = 0,
549             REGKIND_REGISTER = 1,
550             REGKIND_NONE = 2,
551             REGKIND_LOAD_TLB_AS_32BIT = 0x20,
552             REGKIND_LOAD_TLB_AS_64BIT = 0x40,
553         }
554 
555         // Set of IMAGE_FILE constants which represent the processor architectures for native assemblies.
556         internal const UInt16 IMAGE_FILE_MACHINE_UNKNOWN = 0x0; //	The contents of this field are assumed to be applicable to any machine type
557         internal const UInt16 IMAGE_FILE_MACHINE_INVALID = UInt16.MaxValue; // Invalid value for the machine type.
558         internal const UInt16 IMAGE_FILE_MACHINE_AMD64 = 0x8664; //	x64
559         internal const UInt16 IMAGE_FILE_MACHINE_ARM = 0x1c0; // ARM little endian
560         internal const UInt16 IMAGE_FILE_MACHINE_ARMV7 = 0x1c4; // ARMv7 (or higher) Thumb mode only
561         internal const UInt16 IMAGE_FILE_MACHINE_I386 = 0x14c; // Intel 386 or later processors and compatible processors
562         internal const UInt16 IMAGE_FILE_MACHINE_IA64 = 0x200; // Intel Itanium processor family
563         internal const UInt16 IMAGE_FILE_MACHINE_R4000 = 0x166; // Used to test a architecture we do not expect to reference
564 
565         internal const uint GENERIC_READ = 0x80000000;
566 
567         internal const uint PAGE_READONLY = 0x02;
568 
569         internal const uint FILE_MAP_READ = 0x04;
570 
571         internal const uint FILE_TYPE_DISK = 0x01;
572 
573         internal const int SE_ERR_ACCESSDENIED = 5;
574 
575         // CryptoApi flags and constants
576         [Flags]
577         internal enum CryptFlags
578         {
579             Exportable = 0x1,
580             UserProtected = 0x2,
581             MachineKeySet = 0x20,
582             UserKeySet = 0x1000
583         }
584 
585         internal enum KeySpec
586         {
587             AT_KEYEXCHANGE = 1,
588             AT_SIGNATURE = 2
589         }
590 
591         internal enum BlobType
592         {
593             SIMPLEBLOB = 0x1,
594             PUBLICKEYBLOB = 0x6,
595             PRIVATEKEYBLOB = 0x7,
596             PLAINTEXTKEYBLOB = 0x8,
597             OPAQUEKEYBLOB = 0x9,
598             PUBLICKEYBLOBEX = 0xA,
599             SYMMETRICWRAPKEYBLOB = 0xB,
600         }
601 
602         [Flags]
603         internal enum CertStoreClose
604         {
605             CERT_CLOSE_STORE_FORCE_FLAG = 0x00000001,
606             CERT_CLOSE_STORE_CHECK_FLAG = 0x00000002,
607         }
608 
609         [Flags]
610         internal enum MoveFileFlags
611         {
612             MOVEFILE_REPLACE_EXISTING = 0x00000001,
613             MOVEFILE_COPY_ALLOWED = 0x00000002,
614             MOVEFILE_DELAY_UNTIL_REBOOT = 0x00000004,
615             MOVEFILE_WRITE_THROUGH = 0x00000008,
616             MOVEFILE_CREATE_HARDLINK = 0x00000010,
617             MOVEFILE_FAIL_IF_NOT_TRACKABLE = 0x00000020
618         }
619 
620         #endregion
621 
622         #region NT header stuff
623 
624         internal const uint IMAGE_NT_OPTIONAL_HDR32_MAGIC = 0x10b;
625         internal const uint IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20b;
626 
627         internal const uint IMAGE_DIRECTORY_ENTRY_COMHEADER = 14;
628 
629         internal const uint COMIMAGE_FLAGS_STRONGNAMESIGNED = 0x08;
630 
631         [StructLayout(LayoutKind.Sequential)]
632         internal struct IMAGE_FILE_HEADER
633         {
634             internal ushort Machine;
635             internal ushort NumberOfSections;
636             internal uint TimeDateStamp;
637             internal uint PointerToSymbolTable;
638             internal uint NumberOfSymbols;
639             internal ushort SizeOfOptionalHeader;
640             internal ushort Characteristics;
641         }
642 
643         [StructLayout(LayoutKind.Sequential)]
644         internal struct IMAGE_DATA_DIRECTORY
645         {
646             internal uint VirtualAddress;
647             internal uint Size;
648         }
649 
650         [StructLayout(LayoutKind.Sequential)]
651         internal struct IMAGE_OPTIONAL_HEADER32
652         {
653             internal ushort Magic;
654             internal byte MajorLinkerVersion;
655             internal byte MinorLinkerVersion;
656             internal uint SizeOfCode;
657             internal uint SizeOfInitializedData;
658             internal uint SizeOfUninitializedData;
659             internal uint AddressOfEntryPoint;
660             internal uint BaseOfCode;
661             internal uint BaseOfData;
662             internal uint ImageBase;
663             internal uint SectionAlignment;
664             internal uint FileAlignment;
665             internal ushort MajorOperatingSystemVersion;
666             internal ushort MinorOperatingSystemVersion;
667             internal ushort MajorImageVersion;
668             internal ushort MinorImageVersion;
669             internal ushort MajorSubsystemVersion;
670             internal ushort MinorSubsystemVersion;
671             internal uint Win32VersionValue;
672             internal uint SizeOfImage;
673             internal uint SizeOfHeaders;
674             internal uint CheckSum;
675             internal ushort Subsystem;
676             internal ushort DllCharacteristics;
677             internal uint SizeOfStackReserve;
678             internal uint SizeOfStackCommit;
679             internal uint SizeOfHeapReserve;
680             internal uint SizeOfHeapCommit;
681             internal uint LoaderFlags;
682             internal uint NumberOfRvaAndSizes;
683 
684             // should be:
685             // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] internal IMAGE_DATA_DIRECTORY[] DataDirectory;
686             // but fixed size arrays only work with simple types, so I have to use ulongs and convert them to IMAGE_DATA_DIRECTORY structs
687             // Fortunately, IMAGE_DATA_DIRECTORY is only 8 bytes long... (whew)
688             [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
689             internal ulong[] DataDirectory;
690         }
691 
692         [StructLayout(LayoutKind.Sequential)]
693         internal struct IMAGE_OPTIONAL_HEADER64
694         {
695             internal ushort Magic;
696             internal byte MajorLinkerVersion;
697             internal byte MinorLinkerVersion;
698             internal uint SizeOfCode;
699             internal uint SizeOfInitializedData;
700             internal uint SizeOfUninitializedData;
701             internal uint AddressOfEntryPoint;
702             internal uint BaseOfCode;
703             internal ulong ImageBase;
704             internal uint SectionAlignment;
705             internal uint FileAlignment;
706             internal ushort MajorOperatingSystemVersion;
707             internal ushort MinorOperatingSystemVersion;
708             internal ushort MajorImageVersion;
709             internal ushort MinorImageVersion;
710             internal ushort MajorSubsystemVersion;
711             internal ushort MinorSubsystemVersion;
712             internal uint Win32VersionValue;
713             internal uint SizeOfImage;
714             internal uint SizeOfHeaders;
715             internal uint CheckSum;
716             internal ushort Subsystem;
717             internal ushort DllCharacteristics;
718             internal ulong SizeOfStackReserve;
719             internal ulong SizeOfStackCommit;
720             internal ulong SizeOfHeapReserve;
721             internal ulong SizeOfHeapCommit;
722             internal uint LoaderFlags;
723             internal uint NumberOfRvaAndSizes;
724 
725             // should be:
726             // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] internal IMAGE_DATA_DIRECTORY[] DataDirectory;
727             // but fixed size arrays only work with simple types, so I have to use ulongs and convert them to IMAGE_DATA_DIRECTORY structs
728             // Fortunately, IMAGE_DATA_DIRECTORY is only 8 bytes long... (whew)
729             [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
730             internal ulong[] DataDirectory;
731         }
732 
733         [StructLayout(LayoutKind.Sequential)]
734         internal struct IMAGE_NT_HEADERS32
735         {
736             internal uint signature;
737             internal IMAGE_FILE_HEADER fileHeader;
738             internal IMAGE_OPTIONAL_HEADER32 optionalHeader;
739         }
740 
741         [StructLayout(LayoutKind.Sequential)]
742         internal struct IMAGE_NT_HEADERS64
743         {
744             internal uint signature;
745             internal IMAGE_FILE_HEADER fileHeader;
746             internal IMAGE_OPTIONAL_HEADER64 optionalHeader;
747         }
748 
749         [StructLayout(LayoutKind.Sequential)]
750         internal struct IMAGE_COR20_HEADER
751         {
752             internal uint cb;
753             internal ushort MajorRuntimeVersion;
754             internal ushort MinorRuntimeVersion;
755             internal IMAGE_DATA_DIRECTORY MetaData;
756             internal uint Flags;
757             internal uint EntryPointTokenOrEntryPointRVA;
758             internal IMAGE_DATA_DIRECTORY Resources;
759             internal IMAGE_DATA_DIRECTORY StrongNameSignature;
760             internal IMAGE_DATA_DIRECTORY CodeManagerTable;
761             internal IMAGE_DATA_DIRECTORY VTableFixups;
762             internal IMAGE_DATA_DIRECTORY ExportAddressTableJumps;
763             internal IMAGE_DATA_DIRECTORY ManagedNativeHeader;
764         }
765 
766         [StructLayout(LayoutKind.Sequential)]
767         internal struct CRYPTOAPI_BLOB
768         {
769             internal uint cbData;
770             internal IntPtr pbData;
771         }
772 
773         #endregion
774 
775         #region PInvoke
776         private const string Crypt32DLL = "crypt32.dll";
777         private const string Advapi32DLL = "advapi32.dll";
778         private const string MscoreeDLL = "mscoree.dll";
779 
780         //------------------------------------------------------------------------------
781         // CreateHardLink
782         //------------------------------------------------------------------------------
783         [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
CreateHardLink(string newFileName, string exitingFileName, IntPtr securityAttributes)784         private static extern bool CreateHardLink(string newFileName, string exitingFileName, IntPtr securityAttributes);
785 
786         [DllImport("libc", SetLastError = true)]
link(string oldpath, string newpath)787         internal static extern int link(string oldpath, string newpath);
788 
MakeHardLink(string newFileName, string exitingFileName, ref string errorMessage)789         internal static bool MakeHardLink(string newFileName, string exitingFileName, ref string errorMessage)
790         {
791             bool hardLinkCreated;
792             if (NativeMethodsShared.IsWindows)
793             {
794                 hardLinkCreated = CreateHardLink(newFileName, exitingFileName, IntPtr.Zero /* reserved, must be NULL */);
795                 errorMessage = hardLinkCreated ? null : Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error()).Message;
796             }
797             else
798             {
799                 hardLinkCreated = link(exitingFileName, newFileName) == 0;
800                 errorMessage = hardLinkCreated ? null : "The link() library call failed with the following error code: " + Marshal.GetLastWin32Error();
801             }
802 
803             return hardLinkCreated;
804         }
805 
806         //------------------------------------------------------------------------------
807         // CreateSymbolicLink
808         //------------------------------------------------------------------------------
809         [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
CreateSymbolicLink(string symLinkFileName, string targetFileName, SymbolicLink dwFlags)810         internal static extern bool CreateSymbolicLink(string symLinkFileName, string targetFileName, SymbolicLink dwFlags);
811 
812         [DllImport("libc", SetLastError = true)]
symlink(string oldpath, string newpath)813         internal static extern int symlink(string oldpath, string newpath);
814 
MakeSymbolicLink(string newFileName, string exitingFileName, ref string errorMessage)815         internal static bool MakeSymbolicLink(string newFileName, string exitingFileName, ref string errorMessage)
816         {
817             bool symbolicLinkCreated;
818             if (NativeMethodsShared.IsWindows)
819             {
820                 symbolicLinkCreated = CreateSymbolicLink(newFileName, exitingFileName, SymbolicLink.File);
821                 errorMessage = symbolicLinkCreated ? null : Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error()).Message;
822             }
823             else
824             {
825                 symbolicLinkCreated = symlink(exitingFileName, newFileName) == 0;
826                 errorMessage = symbolicLinkCreated ? null : "The link() library call failed with the following error code: " + Marshal.GetLastWin32Error();
827             }
828 
829             return symbolicLinkCreated;
830         }
831 
832         //------------------------------------------------------------------------------
833         // MoveFileEx
834         //------------------------------------------------------------------------------
835         [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "MoveFileEx")]
MoveFileExWindows( [In] string existingFileName, [In] string newFileName, [In] MoveFileFlags flags )836         internal static extern bool MoveFileExWindows
837         (
838             [In] string existingFileName,
839             [In] string newFileName,
840             [In] MoveFileFlags flags
841         );
842 
843         /// <summary>
844         /// Add implementation of this function when not running on windows. The implementation is
845         /// not complete, of course, but should work for most common cases.
846         /// </summary>
847         /// <param name="existingFileName"></param>
848         /// <param name="newFileName"></param>
849         /// <param name="flags"></param>
850         /// <returns></returns>
MoveFileEx(string existingFileName, string newFileName, MoveFileFlags flags)851         internal static bool MoveFileEx(string existingFileName, string newFileName, MoveFileFlags flags)
852         {
853             if (NativeMethodsShared.IsWindows)
854             {
855                 return MoveFileExWindows(existingFileName, newFileName, flags);
856             }
857 
858             if (!File.Exists(existingFileName))
859             {
860                 return false;
861             }
862 
863             var targetExists = File.Exists(newFileName);
864 
865             if (targetExists
866                 && ((flags & MoveFileFlags.MOVEFILE_REPLACE_EXISTING) != MoveFileFlags.MOVEFILE_REPLACE_EXISTING))
867             {
868                 return false;
869             }
870 
871             if (targetExists && (File.GetAttributes(newFileName) & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
872             {
873                 throw new System.IO.IOException("Moving target is read-only");
874             }
875 
876             if (string.Equals(existingFileName, newFileName, StringComparison.Ordinal))
877             {
878                 return true;
879             }
880 
881             if (targetExists)
882             {
883                 File.Delete(newFileName);
884             }
885 
886             File.Move(existingFileName, newFileName);
887             return true;
888         }
889 
890         //------------------------------------------------------------------------------
891         // RegisterTypeLib
892         //------------------------------------------------------------------------------
893         [DllImport("oleaut32", PreserveSig = false, EntryPoint = "RegisterTypeLib")]
RegisterTypeLib([In, MarshalAs(UnmanagedType.Interface)] object pTypeLib, [In, MarshalAs(UnmanagedType.LPWStr)] string szFullPath, [In, MarshalAs(UnmanagedType.LPWStr)] string szHelpDir)894         internal static extern void RegisterTypeLib([In, MarshalAs(UnmanagedType.Interface)] object pTypeLib, [In, MarshalAs(UnmanagedType.LPWStr)] string szFullPath, [In, MarshalAs(UnmanagedType.LPWStr)] string szHelpDir);
895 
896         //------------------------------------------------------------------------------
897         // UnRegisterTypeLib
898         //------------------------------------------------------------------------------
899         [DllImport("oleaut32", PreserveSig = false, EntryPoint = "UnRegisterTypeLib")]
UnregisterTypeLib( [In] ref Guid guid, [In] short wMajorVerNum, [In] short wMinorVerNum, [In] int lcid, [In] System.Runtime.InteropServices.ComTypes.SYSKIND syskind )900         internal static extern void UnregisterTypeLib
901         (
902             [In] ref Guid guid,
903             [In] short wMajorVerNum,
904             [In] short wMinorVerNum,
905             [In] int lcid,
906             [In] System.Runtime.InteropServices.ComTypes.SYSKIND syskind
907         );
908 
909         //------------------------------------------------------------------------------
910         // LoadTypeLib
911         //------------------------------------------------------------------------------
912         [DllImport("oleaut32", PreserveSig = false, EntryPoint = "LoadTypeLibEx")]
913         [return: MarshalAs(UnmanagedType.Interface)]
LoadTypeLibEx([In, MarshalAs(UnmanagedType.LPWStr)] string szFullPath, [In] int regKind)914         internal static extern object LoadTypeLibEx([In, MarshalAs(UnmanagedType.LPWStr)] string szFullPath, [In] int regKind);
915 
916         //------------------------------------------------------------------------------
917         // LoadRegTypeLib
918         //------------------------------------------------------------------------------
919         [DllImport("oleaut32", PreserveSig = false)]
920         [return: MarshalAs(UnmanagedType.Interface)]
LoadRegTypeLib([In] ref Guid clsid, [In] short majorVersion, [In] short minorVersion, [In] int lcid)921         internal static extern object LoadRegTypeLib([In] ref Guid clsid, [In] short majorVersion, [In] short minorVersion, [In] int lcid);
922 
923         //------------------------------------------------------------------------------
924         // QueryPathOfRegTypeLib
925         //------------------------------------------------------------------------------
926         [DllImport("oleaut32", PreserveSig = false)]
927         [return: MarshalAs(UnmanagedType.BStr)]
QueryPathOfRegTypeLib([In] ref Guid clsid, [In] short majorVersion, [In] short minorVersion, [In] int lcid)928         internal static extern string QueryPathOfRegTypeLib([In] ref Guid clsid, [In] short majorVersion, [In] short minorVersion, [In] int lcid);
929 
930         //------------------------------------------------------------------------------
931         // CreateFile
932         //------------------------------------------------------------------------------
933         [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
CreateFile(string lpFileName, uint dwDesiredAccess, FileShare dwShareMode, IntPtr lpSecurityAttributes, FileMode dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile)934         internal static extern IntPtr CreateFile(string lpFileName, uint dwDesiredAccess, FileShare dwShareMode,
935             IntPtr lpSecurityAttributes, FileMode dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile);
936 
937         //------------------------------------------------------------------------------
938         // GetFileType
939         //------------------------------------------------------------------------------
940         [DllImport("kernel32.dll", SetLastError = true)]
GetFileType(IntPtr hFile)941         internal static extern uint GetFileType(IntPtr hFile);
942 
943         //------------------------------------------------------------------------------
944         // CloseHandle
945         //------------------------------------------------------------------------------
946         [DllImport("kernel32.dll", SetLastError = true)]
947         [return: MarshalAs(UnmanagedType.Bool)]
CloseHandle(IntPtr hObject)948         internal static extern bool CloseHandle(IntPtr hObject);
949 
950         //------------------------------------------------------------------------------
951         // CreateFileMapping
952         //------------------------------------------------------------------------------
953         [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
CreateFileMapping(IntPtr hFile, IntPtr lpFileMappingAttributes, uint flProtect, uint dwMaximumSizeHigh, uint dwMaximumSizeLow, string lpName)954         internal static extern IntPtr CreateFileMapping(IntPtr hFile, IntPtr lpFileMappingAttributes, uint flProtect,
955             uint dwMaximumSizeHigh, uint dwMaximumSizeLow, string lpName);
956 
957         //------------------------------------------------------------------------------
958         // MapViewOfFile
959         //------------------------------------------------------------------------------
960         [DllImport("kernel32.dll", SetLastError = true)]
MapViewOfFile(IntPtr hFileMapping, uint dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow, IntPtr dwNumberOfBytesToMap)961         internal static extern IntPtr MapViewOfFile(IntPtr hFileMapping, uint dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow, IntPtr dwNumberOfBytesToMap);
962 
963         //------------------------------------------------------------------------------
964         // UnmapViewOfFile
965         //------------------------------------------------------------------------------
966         [DllImport("kernel32.dll", SetLastError = true)]
967         [return: MarshalAs(UnmanagedType.Bool)]
UnmapViewOfFile(IntPtr lpBaseAddress)968         internal static extern bool UnmapViewOfFile(IntPtr lpBaseAddress);
969 
970         //------------------------------------------------------------------------------
971         // CreateProcess
972         //------------------------------------------------------------------------------
973         [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
974         [return: MarshalAs(UnmanagedType.Bool)]
CreateProcess( string lpApplicationName, string lpCommandLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, [In, MarshalAs(UnmanagedType.Bool)] bool bInheritHandles, uint dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, [In] ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation )975         internal static extern bool CreateProcess
976         (
977             string lpApplicationName,
978             string lpCommandLine,
979             IntPtr lpProcessAttributes,
980             IntPtr lpThreadAttributes,
981             [In, MarshalAs(UnmanagedType.Bool)]
982             bool bInheritHandles,
983             uint dwCreationFlags,
984             IntPtr lpEnvironment,
985             string lpCurrentDirectory,
986             [In] ref STARTUPINFO lpStartupInfo,
987             out PROCESS_INFORMATION lpProcessInformation
988         );
989 
990         //------------------------------------------------------------------------------
991         // ImageNtHeader
992         //------------------------------------------------------------------------------
993         [DllImport("dbghelp.dll", SetLastError = true)]
ImageNtHeader(IntPtr imageBase)994         internal static extern IntPtr ImageNtHeader(IntPtr imageBase);
995 
996         //------------------------------------------------------------------------------
997         // ImageRvaToVa
998         //------------------------------------------------------------------------------
999         [DllImport("dbghelp.dll", SetLastError = true)]
ImageRvaToVa(IntPtr ntHeaders, IntPtr imageBase, uint Rva, out IntPtr LastRvaSection)1000         internal static extern IntPtr ImageRvaToVa(IntPtr ntHeaders, IntPtr imageBase, uint Rva, out IntPtr LastRvaSection);
1001 
1002         [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
GetLogicalDrives()1003         private static extern uint GetLogicalDrives();
1004 
AllDrivesMapped()1005         internal static bool AllDrivesMapped()
1006         {
1007             const uint AllDriveMask = 0x0cffffff;
1008             if (NativeMethodsShared.IsWindows)
1009             {
1010                 var driveMask = GetLogicalDrives();
1011                 // All drives are taken if the value has all 26 bits set
1012                 return driveMask >= AllDriveMask;
1013             }
1014 
1015             return false;
1016         }
1017 
1018 #if FEATURE_COM_INTEROP
1019         //------------------------------------------------------------------------------
1020         // CreateAssemblyCache
1021         //------------------------------------------------------------------------------
1022         [DllImport("fusion.dll")]
CreateAssemblyCache(out IAssemblyCache ppAsmCache, uint dwReserved)1023         internal static extern uint CreateAssemblyCache(out IAssemblyCache ppAsmCache, uint dwReserved);
1024 
1025         [DllImport("fusion.dll")]
CreateAssemblyEnum( out IAssemblyEnum ppEnum, IntPtr pUnkReserved, IAssemblyName pName, AssemblyCacheFlags flags, IntPtr pvReserved)1026         internal static extern int CreateAssemblyEnum(
1027                 out IAssemblyEnum ppEnum,
1028                 IntPtr pUnkReserved,
1029                 IAssemblyName pName,
1030                 AssemblyCacheFlags flags,
1031                 IntPtr pvReserved);
1032 
1033         [DllImport("fusion.dll")]
CreateAssemblyNameObject( out IAssemblyName ppAssemblyNameObj, [MarshalAs(UnmanagedType.LPWStr)] String szAssemblyName, CreateAssemblyNameObjectFlags flags, IntPtr pvReserved)1034         internal static extern int CreateAssemblyNameObject(
1035                 out IAssemblyName ppAssemblyNameObj,
1036                 [MarshalAs(UnmanagedType.LPWStr)]
1037                 String szAssemblyName,
1038                 CreateAssemblyNameObjectFlags flags,
1039                 IntPtr pvReserved);
1040 
1041         /// <summary>
1042         /// GetCachePath from fusion.dll.
1043         /// Using StringBuilder here is a way to pass a preallocated buffer of characters to (native) functions that require it.
1044         /// A common design pattern in unmanaged C++ is calling a function twice, once to determine the length of the string
1045         /// and then again to pass the client-allocated character buffer. StringBuilder is the most straightforward way
1046         /// to allocate a mutable buffer of characters and pass it around.
1047         /// </summary>
1048         [DllImport("fusion.dll", CharSet = CharSet.Unicode)]
GetCachePath(AssemblyCacheFlags cacheFlags, StringBuilder cachePath, ref int pcchPath)1049         internal static extern int GetCachePath(AssemblyCacheFlags cacheFlags, StringBuilder cachePath, ref int pcchPath);
1050 #endif
1051 
1052         /*------------------------------------------------------------------------------
1053         CompareAssemblyIdentity
1054         The Fusion API to compare two assembly identities to determine whether or not they are equivalent is now available. This new API is exported from mscorwks.dll, which you can access via mscoree's GetRealProcAddress. The function prototype is defined in fusion.h as follows:
1055 
1056         STDAPI CompareAssemblyIdentity(LPCWSTR pwzAssemblyIdentity1,
1057                                     BOOL fUnified1,
1058                                     LPCWSTR pwzAssemblyIdentity2,
1059                                     BOOL fUnified2,
1060                                     BOOL *pfEquivalent,
1061                                     AssemblyComparisonResult *pResult);
1062 
1063 typedef enum _tagAssemblyComparisonResult
1064 {
1065     ACR_Unknown,                    // Unknown
1066     ACR_EquivalentFullMatch,        // all fields match
1067     ACR_EquivalentWeakNamed,        // match based on weak-name, version numbers ignored
1068     ACR_EquivalentFXUnified,        // match based on FX-unification of version numbers
1069     ACR_EquivalentUnified,          // match based on legacy-unification of version numbers
1070     ACR_NonEquivalentVersion,       // all fields match except version field
1071     ACR_NonEquivalent,              // no match
1072 
1073     ACR_EquivalentPartialMatch,
1074     ACR_EquivalentPartialWeakNamed,
1075     ACR_EquivalentPartialUnified,
1076     ACR_EquivalentPartialFXUnified,
1077     ACR_NonEquivalentPartialVersion
1078 } AssemblyComparisonResult;
1079 
1080         Parameters:
1081             [in] LPCWSTR pwzAssemblyIdentity1 : Textual identity of the first assembly to be compared
1082             [in] BOOL fUnified1               : Flag to indicate user-specified unification for pwzAssemblyIdentity1 (see below)
1083             [in] LPCWSTR pwzAssemblyIdentity2 : Textual identity of the second assembly to be compared
1084             [in] BOOL fUnified2               : Flag to inidcate user-specified unification for pwzAssemblyIdentity2 (see below)
1085             [out] BOOL *pfEquivalent          : Boolean indicating whether the identities are equivalent
1086             [out] AssemblyComparisonResult *pResult : Contains detailed information about the comparison result
1087 
1088         This API will check whether or not pwzAssemblyIdentity1 and pwzAssemblyIdentity2 are equivalent. Both of these identities must be full-specified (name, version, pkt, culture). The pfEquivalent parameter will be set to TRUE if one (or more) of the following conditions is true:
1089 
1090         a) The assembly identities are equivalent. For strongly-named assemblies this means full match on (name, version, pkt, culture); for simply-named assemblies this means a match on (name, culture)
1091 
1092         b) The assemblies being compared are FX assemblies (even if the version numbers are not the same, these will compare as equivalent by way of unification)
1093 
1094         c) The assemblies are not FX assemblies but are equivalent because fUnified1 and/or fUnified2 were set.
1095 
1096         The fUnified flag is used to indicate that all versions up to the version number of the strongly-named assembly are considered equivalent to itself. For example, if pwzAssemblyIdentity1 is "foo, version=5.0.0.0, culture=neutral, publicKeyToken=...." and fUnified1==TRUE, then this means to treat all versions of the assembly in the range 0.0.0.0-5.0.0.0 to be equivalent to "foo, version=5.0.0.0, culture=neutral, publicKeyToken=...". If pwzAssemblyIdentity2 is the same as pwzAssemblyIdentity1, except has a lower version number (e.g. version range 0.0.0.0-5.0.0.0), then the API will return that the identities are equivalent. If pwzAssemblyIdentity2 is the same as pwzAssemblyIdentity1, but has a greater version number than 5.0.0.0 then the two identities will only be equivalent if fUnified2 is set.
1097 
1098         The AssemblyComparisonResult gives you information about why the identities compared as equal or not equal. The description of the meaning of each ACR_* return value is described in the declaration above.
1099         ------------------------------------------------------------------------------*/
1100         [DllImport("fusion.dll", CharSet = CharSet.Unicode, EntryPoint = "CompareAssemblyIdentity")]
CompareAssemblyIdentityWindows( string pwzAssemblyIdentity1, [MarshalAs(UnmanagedType.Bool)] bool fUnified1, string pwzAssemblyIdentity2, [MarshalAs(UnmanagedType.Bool)] bool fUnified2, [MarshalAs(UnmanagedType.Bool)] out bool pfEquivalent, out AssemblyComparisonResult pResult )1101         internal static extern int CompareAssemblyIdentityWindows
1102             (
1103                 string pwzAssemblyIdentity1,
1104                 [MarshalAs(UnmanagedType.Bool)] bool fUnified1,
1105                 string pwzAssemblyIdentity2,
1106                 [MarshalAs(UnmanagedType.Bool)] bool fUnified2,
1107                 [MarshalAs(UnmanagedType.Bool)] out bool pfEquivalent,
1108                 out AssemblyComparisonResult pResult
1109             );
1110 
1111         // TODO: Verify correctness of this implementation and
1112         // extend to more cases.
CompareAssemblyIdentity( string assemblyIdentity1, bool fUnified1, string assemblyIdentity2, bool fUnified2, out bool pfEquivalent, out AssemblyComparisonResult pResult)1113         internal static void CompareAssemblyIdentity(
1114             string assemblyIdentity1,
1115             bool fUnified1,
1116             string assemblyIdentity2,
1117             bool fUnified2,
1118             out bool pfEquivalent,
1119             out AssemblyComparisonResult pResult)
1120         {
1121 #if FEATURE_FUSION_COMPAREASSEMBLYIDENTITY
1122             if (NativeMethodsShared.IsWindows)
1123             {
1124                 CompareAssemblyIdentityWindows(
1125                     assemblyIdentity1,
1126                     fUnified1,
1127                     assemblyIdentity2,
1128                     fUnified2,
1129                     out pfEquivalent,
1130                     out pResult);
1131             }
1132 #endif
1133 
1134             AssemblyName an1 = new AssemblyName(assemblyIdentity1);
1135             AssemblyName an2 = new AssemblyName(assemblyIdentity2);
1136 
1137             //pfEquivalent = AssemblyName.ReferenceMatchesDefinition(an1, an2);
1138             pfEquivalent = RefMatchesDef(an1, an2);
1139             if (pfEquivalent)
1140             {
1141                 pResult = AssemblyComparisonResult.ACR_EquivalentFullMatch;
1142                 return;
1143             }
1144 
1145             if (!an1.Name.Equals(an2.Name, StringComparison.OrdinalIgnoreCase))
1146             {
1147                 pResult = AssemblyComparisonResult.ACR_NonEquivalent;
1148                 pfEquivalent = false;
1149                 return;
1150             }
1151 
1152             var versionCompare = an1.Version.CompareTo(an2.Version);
1153 
1154             if ((versionCompare < 0 && fUnified2) || (versionCompare > 0 && fUnified1))
1155             {
1156                 pResult = AssemblyComparisonResult.ACR_NonEquivalentVersion;
1157                 pfEquivalent = true;
1158                 return;
1159             }
1160 
1161             if (versionCompare == 0)
1162             {
1163                 pResult = AssemblyComparisonResult.ACR_EquivalentFullMatch;
1164                 pfEquivalent = true;
1165                 return;
1166             }
1167 
1168             pResult = pfEquivalent ? AssemblyComparisonResult.ACR_EquivalentFullMatch : AssemblyComparisonResult.ACR_NonEquivalent;
1169         }
1170 
1171         //  Based on coreclr baseassemblyspec.cpp (https://github.com/dotnet/coreclr/blob/4cf8a6b082d9bb1789facd996d8265d3908757b2/src/vm/baseassemblyspec.cpp#L330)
1172         private static bool RefMatchesDef(AssemblyName @ref, AssemblyName def)
1173         {
1174             if (IsStrongNamed(@ref))
1175             {
1176                 return IsStrongNamed(def) && CompareRefToDef(@ref, def);
1177             }
1178             else
1179             {
1180                 return @ref.Name.Equals(def.Name, StringComparison.OrdinalIgnoreCase);
1181             }
1182         }
1183 
1184         // Based on coreclr baseassemblyspec.inl (https://github.com/dotnet/coreclr/blob/32f0f9721afb584b4a14d69135bea7ddc129f755/src/vm/baseassemblyspec.inl#L679-L683)
IsStrongNamed(AssemblyName assembly)1185         private static bool IsStrongNamed(AssemblyName assembly)
1186         {
1187             var refPkt = assembly.GetPublicKeyToken();
1188             return refPkt != null && refPkt.Length != 0;
1189         }
1190 
1191         //  Based on https://github.com/dotnet/coreclr/blob/4cf8a6b082d9bb1789facd996d8265d3908757b2/src/vm/baseassemblyspec.cpp#L241
1192         private static bool CompareRefToDef(AssemblyName @ref, AssemblyName def)
1193         {
1194             if (!@ref.Name.Equals(def.Name, StringComparison.OrdinalIgnoreCase))
1195             {
1196                 return false;
1197             }
1198 
1199             byte[] rpkt = @ref.GetPublicKeyToken();
1200             byte[] dpkt = def.GetPublicKeyToken();
1201 
1202             if (rpkt.Length != dpkt.Length)
1203             {
1204                 return false;
1205             }
1206 
1207             for (int i = 0; i < rpkt.Length; i++)
1208             {
1209                 if (rpkt[i] != dpkt[i])
1210                 {
1211                     return false;
1212                 }
1213             }
1214 
1215             if (@ref.Version != def.Version)
1216             {
1217                 return false;
1218             }
1219 
1220             if (@ref.CultureName != null &&
1221                 @ref.CultureName != def.CultureName)
1222             {
1223                 return false;
1224             }
1225 
1226             return true;
1227         }
1228 
1229         internal enum AssemblyComparisonResult
1230         {
1231             ACR_Unknown,                    // Unknown
1232             ACR_EquivalentFullMatch,        // all fields match
1233             ACR_EquivalentWeakNamed,        // match based on weak-name, version numbers ignored
1234             ACR_EquivalentFXUnified,        // match based on FX-unification of version numbers
1235             ACR_EquivalentUnified,          // match based on legacy-unification of version numbers
1236             ACR_NonEquivalentVersion,       // all fields match except version field
1237             ACR_NonEquivalent,              // no match
1238 
1239             ACR_EquivalentPartialMatch,
1240             ACR_EquivalentPartialWeakNamed,
1241             ACR_EquivalentPartialUnified,
1242             ACR_EquivalentPartialFXUnified,
1243             ACR_NonEquivalentPartialVersion
1244         }
1245 
1246         //------------------------------------------------------------------------------
1247         // PFXImportCertStore
1248         //------------------------------------------------------------------------------
1249         [DllImport(Crypt32DLL, SetLastError = true, CharSet = CharSet.Unicode)]
PFXImportCertStore([In] IntPtr blob, [In] string password, [In] CryptFlags flags)1250         internal static extern IntPtr PFXImportCertStore([In] IntPtr blob, [In] string password, [In] CryptFlags flags);
1251 
1252         //------------------------------------------------------------------------------
1253         // CertCloseStore
1254         //------------------------------------------------------------------------------
1255         [DllImport(Crypt32DLL, SetLastError = true)]
1256         [return: MarshalAs(UnmanagedType.Bool)]
CertCloseStore([In] IntPtr CertStore, CertStoreClose Flags)1257         internal static extern bool CertCloseStore([In]   IntPtr CertStore, CertStoreClose Flags);
1258 
1259         //------------------------------------------------------------------------------
1260         // CertEnumCertificatesInStore
1261         //------------------------------------------------------------------------------
1262         [DllImport(Crypt32DLL, SetLastError = true)]
CertEnumCertificatesInStore([In] IntPtr CertStore, [In] IntPtr PrevCertContext)1263         internal static extern IntPtr CertEnumCertificatesInStore([In]   IntPtr CertStore, [In]   IntPtr PrevCertContext);
1264 
1265         //------------------------------------------------------------------------------
1266         // CryptAcquireCertificatePrivateKey
1267         //------------------------------------------------------------------------------
1268         [DllImport(Crypt32DLL, SetLastError = true)]
1269         [return: MarshalAs(UnmanagedType.Bool)]
CryptAcquireCertificatePrivateKey([In] IntPtr CertContext, [In] uint flags, [In] IntPtr reserved, [In, Out] ref IntPtr CryptProv, [In, Out] ref KeySpec KeySpec, [In, Out, MarshalAs(UnmanagedType.Bool)] ref bool CallerFreeProv)1270         internal static extern bool CryptAcquireCertificatePrivateKey([In] IntPtr CertContext, [In] uint flags, [In] IntPtr reserved, [In, Out] ref IntPtr CryptProv, [In, Out] ref KeySpec KeySpec, [In, Out, MarshalAs(UnmanagedType.Bool)] ref bool CallerFreeProv);
1271 
1272         //------------------------------------------------------------------------------
1273         // CryptGetUserKey
1274         //------------------------------------------------------------------------------
1275         [DllImport(Advapi32DLL, SetLastError = true)]
1276         [return: MarshalAs(UnmanagedType.Bool)]
CryptGetUserKey([In] IntPtr CryptProv, [In] KeySpec KeySpec, [In, Out] ref IntPtr Key)1277         internal static extern bool CryptGetUserKey([In] IntPtr CryptProv, [In] KeySpec KeySpec, [In, Out] ref IntPtr Key);
1278 
1279         //------------------------------------------------------------------------------
1280         // CryptExportKey
1281         //------------------------------------------------------------------------------
1282         [DllImport(Advapi32DLL, SetLastError = true)]
1283         [return: MarshalAs(UnmanagedType.Bool)]
CryptExportKey([In] IntPtr Key, [In] IntPtr ExpKey, [In] BlobType type, [In] uint Flags, [In] IntPtr Data, [In, Out] ref uint DataLen)1284         internal static extern bool CryptExportKey([In] IntPtr Key, [In] IntPtr ExpKey, [In] BlobType type, [In] uint Flags, [In] IntPtr Data, [In, Out] ref uint DataLen);
1285 
1286         //------------------------------------------------------------------------------
1287         // CryptDestroyKey
1288         //------------------------------------------------------------------------------
1289         [DllImport(Advapi32DLL, SetLastError = true)]
1290         [return: MarshalAs(UnmanagedType.Bool)]
CryptDestroyKey(IntPtr hKey)1291         internal static extern bool CryptDestroyKey(IntPtr hKey);
1292 
1293         //------------------------------------------------------------------------------
1294         // CryptReleaseContext
1295         //------------------------------------------------------------------------------
1296         [DllImport(Advapi32DLL, SetLastError = true)]
1297         [return: MarshalAs(UnmanagedType.Bool)]
CryptReleaseContext([In] IntPtr Prov, [In] uint Flags)1298         internal extern static bool CryptReleaseContext([In] IntPtr Prov, [In] uint Flags);
1299 
1300         //------------------------------------------------------------------------------
1301         // CertFreeCertificateContext
1302         //------------------------------------------------------------------------------
1303         [DllImport(Crypt32DLL, SetLastError = true)]
1304         [return: MarshalAs(UnmanagedType.Bool)]
CertFreeCertificateContext(IntPtr CertContext)1305         internal static extern bool CertFreeCertificateContext(IntPtr CertContext);
1306 
1307 #if FEATURE_MSCOREE
1308         /// <summary>
1309         /// Get the runtime version for a given file
1310         /// </summary>
1311         /// <param name="szFullPath">The path of the file to be examined</param>
1312         /// <param name="szBuffer">The buffer allocated for the version information that is returned.</param>
1313         /// <param name="cchBuffer">The size, in wide characters, of szBuffer</param>
1314         /// <param name="dwLength">The size, in bytes, of the returned szBuffer.</param>
1315         /// <returns>HResult</returns>
1316         [DllImport(MscoreeDLL, SetLastError = true, CharSet = CharSet.Unicode)]
GetFileVersion(String szFullPath, StringBuilder szBuffer, int cchBuffer, out uint dwLength)1317         internal static extern uint GetFileVersion(String szFullPath, StringBuilder szBuffer, int cchBuffer, out uint dwLength);
1318 #endif
1319         #endregion
1320 
1321         #region Methods
1322 #if FEATURE_HANDLEPROCESSCORRUPTEDSTATEEXCEPTIONS
1323         /// <summary>
1324         /// Given a pointer to a metadata blob, read the string parameter from it.  Returns true if
1325         /// a valid string was constructed and false otherwise.
1326         ///
1327         /// Adapted from bizapps\server\designers\models\packagemodel\nativemethods.cs (TryReadStringArgument) and
1328         /// the original ARD implementation in vsproject\compsvcspkg\enumcomplus.cpp (GetStringCustomAttribute)
1329         /// This code was taken from the vsproject\ReferenceManager\Providers\NativeMethods.cs
1330         /// </summary>
1331         [HandleProcessCorruptedStateExceptions]
TryReadMetadataString(string fullPath, IntPtr attrData, uint attrDataSize, out string strValue)1332         internal static unsafe bool TryReadMetadataString(string fullPath, IntPtr attrData, uint attrDataSize, out string strValue)
1333         {
1334             IntPtr attrDataPostProlog = IntPtr.Zero;
1335             int attrDataOffset = 0;
1336             int strLen = 0;
1337             int i = 0;
1338             strValue = null;
1339 
1340             try
1341             {
1342                 // Blob structure for an attribute with a constructor receiving one string
1343                 // and no named parameters:
1344                 //
1345                 //     [2 bytes] Prolog: unsigned int16 with value 0x0001
1346                 //     [1, 2 or 4 bytes] PackedLen: Number of bytes of string parameter
1347                 //     [PackedLen bytes] String parameter encoded as UTF8
1348                 //     [1 byte] Name Parameter Count: Named parameter count equal to 0
1349 
1350                 // Minimum size is 4-bytes (Prolog + PackedLen).  Prolog must be 0x0001.
1351                 if ((attrDataSize >= 4) && (Marshal.ReadInt16(attrData, attrDataOffset) == 1))
1352                 {
1353                     int preReadOffset = 2; // pass the prolog
1354                     attrDataPostProlog = attrData + preReadOffset;
1355 
1356                     // Get the offset at which the uncompressed data starts, and the
1357                     // length of the uncompressed data.
1358                     attrDataOffset = CorSigUncompressData(attrDataPostProlog, out strLen);
1359 
1360                     if (strLen != -1)
1361                     {
1362                         // the full size of the blob we were passed in should be sufficient to
1363                         // cover the prolog, compressed string length, and actual string.
1364                         if (attrDataSize >= preReadOffset + attrDataOffset + strLen)
1365                         {
1366                             // Read in the uncompressed data
1367                             byte[] bytes = new byte[(int)strLen];
1368                             for (i = 0; i < strLen; i++)
1369                             {
1370                                 bytes[i] = Marshal.ReadByte(attrDataPostProlog, attrDataOffset + i);
1371                             }
1372 
1373                             // And convert it to the output string.
1374                             strValue = new String(Encoding.UTF8.GetChars(bytes));
1375                         }
1376                         else
1377                         {
1378                             return false;
1379                         }
1380                     }
1381                 }
1382                 else
1383                 {
1384                     return false;
1385                 }
1386             }
1387             catch (AccessViolationException)
1388             {
1389                 // The Marshal.ReadXXXX functions throw AVs when they're fed an invalid pointer, and very occasionally,
1390                 // for some reason, on what seem to be otherwise perfectly valid assemblies (it must be
1391                 // intermittent given that otherwise the user would be completely unable to use the reference
1392                 // manager), the pointer that we generate to look up the AssemblyTitle is apparently invalid,
1393                 // or for some reason Marshal.ReadByte thinks it is.
1394                 //
1395                 return false;
1396             }
1397 
1398             return (strValue != null);
1399         }
1400 #endif
1401         /// <summary>
1402         /// Returns the number of bytes that compressed data -- the length of the uncompressed
1403         /// data -- takes up, and has an out value of the length of the string.
1404         ///
1405         /// Decompression algorithm stolen from ndp\clr\src\toolbox\mdbg\corapi\metadata\cormetadata.cs, which
1406         /// was translated from the base implementation in ndp\clr\src\inc\cor.h
1407         /// This code was taken from the vsproject\ReferenceManager\Providers\NativeMethods.cs
1408         /// </summary>
1409         /// <param name="data">Pointer to the beginning of the data block</param>
1410         /// <param name="uncompressedDataLength">Length of the uncompressed data block</param>
CorSigUncompressData(IntPtr data, out int uncompressedDataLength)1411         internal static unsafe int CorSigUncompressData(IntPtr data, out int uncompressedDataLength)
1412         {
1413             // As described in bizapps\server\designers\models\packagemodel\nativemethods.cs:
1414             // The maximum encodable integer is 29 bits long, 0x1FFFFFFF. The compression algorithm used is as follows (bit 0 is the least significant bit):
1415             // - If the value lies between 0 (0x00) and 127 (0x7F), inclusive, encode as a one-byte integer (bit 7 is clear, value held in bits 6 through 0)
1416             // - If the value lies between 2^8 (0x80) and 2^14 - 1 (0x3FFF), inclusive, encode as a 2-byte integer with bit 15 set, bit 14 clear (value held in bits 13 through 0)
1417             // - Otherwise, encode as a 4-byte integer, with bit 31 set, bit 30 set, bit 29 clear (value held in bits 28 through 0)
1418             // - A null string should be represented with the reserved single byte 0xFF, and no following data
1419             int count = -1;
1420             byte* bytes = (byte*)(data);
1421             uncompressedDataLength = 0;
1422 
1423             // Smallest.
1424             if ((*bytes & 0x80) == 0x00)       // 0??? ????
1425             {
1426                 uncompressedDataLength = *bytes;
1427                 count = 1;
1428             }
1429             // Medium.
1430             else if ((*bytes & 0xC0) == 0x80)  // 10?? ????
1431             {
1432                 uncompressedDataLength = (int)(((*bytes & 0x3f) << 8 | *(bytes + 1)));
1433                 count = 2;
1434             }
1435             else if ((*bytes & 0xE0) == 0xC0)      // 110? ????
1436             {
1437                 uncompressedDataLength = (int)(((*bytes & 0x1f) << 24 | *(bytes + 1) << 16 | *(bytes + 2) << 8 | *(bytes + 3)));
1438                 count = 4;
1439             }
1440 
1441             return count;
1442         }
1443         #endregion
1444         #region InternalClass
1445 #if FEATURE_COM_INTEROP
1446         /// <summary>
1447         /// This class is a wrapper over the native GAC enumeration API.
1448         /// </summary>
1449         [ComVisible(false)]
1450         internal class AssemblyCacheEnum : IEnumerable<AssemblyNameExtension>
1451         {
1452             /// <summary>
1453             /// Path to the gac
1454             /// </summary>
1455             private static string s_gacPath = Path.Combine(NativeMethodsShared.FrameworkBasePath, "gac");
1456 
1457             /// <summary>
1458             /// Regex for directory version parsing
1459             /// </summary>
1460             private static Regex s_assemblyVersionRegex = new Regex(
1461                 @"^([.\d]+)_([^_]*)_([a-fA-F\d]{16})$",
1462                 RegexOptions.CultureInvariant | RegexOptions.Compiled);
1463 
1464             /// <summary>
1465             /// The IAssemblyEnum interface which allows us to ask for the next assembly from the GAC enumeration.
1466             /// </summary>
1467             private IAssemblyEnum _assemblyEnum;
1468 
1469             /// <summary>
1470             /// For non-Windows implementation, we need assembly name
1471             /// </summary>
1472             private AssemblyName _assemblyNameVersion;
1473 
1474             /// <summary>
1475             /// For non-Windows implementation, we need assembly name
1476             /// </summary>
1477             private IEnumerable<string> _gacDirectories;
1478 
1479             /// <summary>
1480             /// Are we done going through the enumeration.
1481             /// </summary>
1482             private bool _done;
1483 
1484             // null means enumerate all the assemblies
AssemblyCacheEnum(String assemblyName)1485             internal AssemblyCacheEnum(String assemblyName)
1486             {
1487                 InitializeEnum(assemblyName);
1488             }
1489 
1490             /// <summary>
1491             /// Initialize the GAC Enum
1492             /// </summary>
1493             /// <param name="assemblyName"></param>
InitializeEnum(String assemblyName)1494             private void InitializeEnum(String assemblyName)
1495             {
1496                 if (NativeMethodsShared.IsWindows)
1497                 {
1498                     IAssemblyName fusionName = null;
1499 
1500                     int hr = 0;
1501                     try
1502                     {
1503                         if (assemblyName != null)
1504                         {
1505                             hr = CreateAssemblyNameObject(
1506                                 out fusionName,
1507                                 assemblyName,
1508                                 CreateAssemblyNameObjectFlags.CANOF_PARSE_DISPLAY_NAME
1509                                 /* parse components assuming the assemblyName is a fusion name, this does not have to be a full fusion name*/,
1510                                 IntPtr.Zero);
1511                         }
1512 
1513                         if (hr >= 0)
1514                         {
1515                             hr = CreateAssemblyEnum(
1516                                 out _assemblyEnum,
1517                                 IntPtr.Zero,
1518                                 fusionName,
1519                                 AssemblyCacheFlags.GAC,
1520                                 IntPtr.Zero);
1521                         }
1522                     }
1523                     catch (Exception e)
1524                     {
1525                         hr = e.HResult;
1526                     }
1527 
1528                     if (hr < 0)
1529                     {
1530                         _assemblyEnum = null;
1531                     }
1532                 }
1533                 else
1534                 {
1535                     if (Directory.Exists(s_gacPath))
1536                     {
1537                         if (!string.IsNullOrWhiteSpace(assemblyName))
1538                         {
1539                             _assemblyNameVersion = new AssemblyName(assemblyName);
1540                             _gacDirectories = Directory.EnumerateDirectories(s_gacPath, _assemblyNameVersion.Name);
1541                         }
1542                         else
1543                         {
1544                             _gacDirectories = Directory.EnumerateDirectories(s_gacPath);
1545                         }
1546                     }
1547                     else
1548                     {
1549                         _gacDirectories = Array.Empty<string>();
1550                     }
1551                 }
1552             }
1553 
GetEnumerator()1554             public IEnumerator<AssemblyNameExtension> GetEnumerator()
1555             {
1556                 if (NativeMethodsShared.IsWindows)
1557                 {
1558                     int hr = 0;
1559                     IAssemblyName fusionName = null;
1560 
1561                     if (_assemblyEnum == null)
1562                     {
1563                         yield break;
1564                     }
1565 
1566                     if (_done)
1567                     {
1568                         yield break;
1569                     }
1570 
1571                     while (!_done)
1572                     {
1573                         // Now get next IAssemblyName from m_AssemblyEnum
1574                         hr = _assemblyEnum.GetNextAssembly((IntPtr)0, out fusionName, 0);
1575 
1576                         if (hr < 0)
1577                         {
1578                             Marshal.ThrowExceptionForHR(hr);
1579                         }
1580 
1581                         if (fusionName != null)
1582                         {
1583                             string assemblyFusionName = GetFullName(fusionName);
1584                             yield return new AssemblyNameExtension(assemblyFusionName);
1585                         }
1586                         else
1587                         {
1588                             _done = true;
1589                             yield break;
1590                         }
1591                     }
1592                 }
1593                 else
1594                 {
1595                     foreach (var dir in _gacDirectories)
1596                     {
1597                         var assemblyName = Path.GetFileName(dir);
1598                         if (!string.IsNullOrWhiteSpace(assemblyName))
1599                         {
1600                             foreach (var version in Directory.EnumerateDirectories(dir))
1601                             {
1602                                 var versionString = Path.GetFileName(version);
1603                                 if (!string.IsNullOrWhiteSpace(versionString))
1604                                 {
1605                                     var match = s_assemblyVersionRegex.Match(versionString);
1606                                     if (match.Success)
1607                                     {
1608                                         var name = new AssemblyName
1609                                         {
1610                                             Name = assemblyName,
1611                                             CultureInfo =
1612                                                                !string.IsNullOrWhiteSpace(
1613                                                                    match.Groups[2].Value)
1614                                                                    ? new CultureInfo(
1615                                                                          match.Groups[2].Value)
1616                                                                    : CultureInfo.InvariantCulture
1617                                         };
1618                                         if (!string.IsNullOrEmpty(match.Groups[1].Value))
1619                                         {
1620                                             name.Version = new Version(match.Groups[1].Value);
1621                                         }
1622                                         if (!string.IsNullOrWhiteSpace(match.Groups[3].Value))
1623                                         {
1624                                             var value = match.Groups[3].Value;
1625                                             name.SetPublicKeyToken(
1626                                                 Enumerable.Range(0, 16)
1627                                                     .Where(x => x % 2 == 0)
1628                                                     .Select(x => Convert.ToByte(value.Substring(x, 2), 16)).ToArray());
1629                                         }
1630 
1631                                         yield return new AssemblyNameExtension(name);
1632                                     }
1633                                 }
1634                             }
1635                         }
1636                     }
1637                 }
1638             }
1639 
GetFullName(IAssemblyName fusionAsmName)1640             private static string GetFullName(IAssemblyName fusionAsmName)
1641             {
1642                 int ilen = 1024;
1643                 StringBuilder sDisplayName = new StringBuilder(ilen);
1644                 int hr = fusionAsmName.GetDisplayName(sDisplayName, ref ilen, (int)AssemblyNameDisplayFlags.ALL);
1645                 if (hr < 0)
1646                 {
1647                     Marshal.ThrowExceptionForHR(hr);
1648                 }
1649 
1650                 return sDisplayName.ToString();
1651             }
1652 
IEnumerable.GetEnumerator()1653             IEnumerator IEnumerable.GetEnumerator()
1654             {
1655                 return (IEnumerator)GetEnumerator();
1656             }
1657 
AssemblyPathFromStrongName(string strongName)1658             public static string AssemblyPathFromStrongName(string strongName)
1659             {
1660                 var assemblyNameVersion = new AssemblyName(strongName);
1661                 var path = Path.Combine(s_gacPath, assemblyNameVersion.Name);
1662 
1663                 // See if we can find the name as a directory in the GAC
1664                 if (Directory.Exists(path))
1665                 {
1666                     // Since we have a strong name, create the path to the dll
1667                     path = Path.Combine(
1668                         path,
1669                         string.Format(
1670                             "{0}_{1}_{2}",
1671                             assemblyNameVersion.Version.ToString(4),
1672                             assemblyNameVersion.CultureName != "neutral" ? assemblyNameVersion.CultureName : string.Empty,
1673                             assemblyNameVersion.GetPublicKeyToken()
1674                                 .Aggregate(new StringBuilder(), (builder, v) => builder.Append(v.ToString("x2")))),
1675                         assemblyNameVersion.Name + ".dll");
1676 
1677                     if (File.Exists(path))
1678                     {
1679                         return path;
1680                     }
1681                 }
1682 
1683                 return null;
1684             }
1685         }
1686 #endif
1687         #endregion
1688     }
1689 }
1690