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