|
|
|
@ -16,8 +16,11 @@
@@ -16,8 +16,11 @@
|
|
|
|
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
|
|
|
// DEALINGS IN THE SOFTWARE.
|
|
|
|
|
|
|
|
|
|
#nullable enable |
|
|
|
|
|
|
|
|
|
using System; |
|
|
|
|
using System.Collections.Generic; |
|
|
|
|
using System.Diagnostics.CodeAnalysis; |
|
|
|
|
using System.IO; |
|
|
|
|
using System.Linq; |
|
|
|
|
using System.Reflection.Metadata; |
|
|
|
@ -64,13 +67,13 @@ namespace ICSharpCode.Decompiler.Metadata
@@ -64,13 +67,13 @@ namespace ICSharpCode.Decompiler.Metadata
|
|
|
|
|
readonly bool throwOnError; |
|
|
|
|
readonly PEStreamOptions streamOptions; |
|
|
|
|
readonly MetadataReaderOptions metadataOptions; |
|
|
|
|
readonly string mainAssemblyFileName; |
|
|
|
|
readonly string baseDirectory; |
|
|
|
|
readonly List<string> directories = new List<string>(); |
|
|
|
|
readonly string? mainAssemblyFileName; |
|
|
|
|
readonly string? baseDirectory; |
|
|
|
|
readonly List<string?> directories = new List<string?>(); |
|
|
|
|
static readonly List<string> gac_paths = GetGacPaths(); |
|
|
|
|
static readonly DecompilerRuntime decompilerRuntime; |
|
|
|
|
|
|
|
|
|
public void AddSearchDirectory(string directory) |
|
|
|
|
public void AddSearchDirectory(string? directory) |
|
|
|
|
{ |
|
|
|
|
directories.Add(directory); |
|
|
|
|
if (dotNetCorePathFinder.IsValueCreated) |
|
|
|
@ -79,7 +82,7 @@ namespace ICSharpCode.Decompiler.Metadata
@@ -79,7 +82,7 @@ namespace ICSharpCode.Decompiler.Metadata
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void RemoveSearchDirectory(string directory) |
|
|
|
|
public void RemoveSearchDirectory(string? directory) |
|
|
|
|
{ |
|
|
|
|
directories.Remove(directory); |
|
|
|
|
if (dotNetCorePathFinder.IsValueCreated) |
|
|
|
@ -88,7 +91,7 @@ namespace ICSharpCode.Decompiler.Metadata
@@ -88,7 +91,7 @@ namespace ICSharpCode.Decompiler.Metadata
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public string[] GetSearchDirectories() |
|
|
|
|
public string?[] GetSearchDirectories() |
|
|
|
|
{ |
|
|
|
|
return directories.ToArray(); |
|
|
|
|
} |
|
|
|
@ -121,8 +124,8 @@ namespace ICSharpCode.Decompiler.Metadata
@@ -121,8 +124,8 @@ namespace ICSharpCode.Decompiler.Metadata
|
|
|
|
|
/// If omitted, falling back to "Microsoft.NETCore.App" and this is ignored in case of classic .NET</param>
|
|
|
|
|
/// <param name="streamOptions">Options used for the <see cref="PEReader"/>.</param>
|
|
|
|
|
/// <param name="metadataOptions">Options used for the <see cref="MetadataReader"/>.</param>
|
|
|
|
|
public UniversalAssemblyResolver(string mainAssemblyFileName, bool throwOnError, string targetFramework, |
|
|
|
|
string runtimePack = null, PEStreamOptions streamOptions = PEStreamOptions.Default, MetadataReaderOptions metadataOptions = MetadataReaderOptions.Default) |
|
|
|
|
public UniversalAssemblyResolver(string? mainAssemblyFileName, bool throwOnError, string? targetFramework, |
|
|
|
|
string? runtimePack = null, PEStreamOptions streamOptions = PEStreamOptions.Default, MetadataReaderOptions metadataOptions = MetadataReaderOptions.Default) |
|
|
|
|
{ |
|
|
|
|
this.mainAssemblyFileName = mainAssemblyFileName; |
|
|
|
|
this.throwOnError = throwOnError; |
|
|
|
@ -162,7 +165,7 @@ namespace ICSharpCode.Decompiler.Metadata
@@ -162,7 +165,7 @@ namespace ICSharpCode.Decompiler.Metadata
|
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Version version = null; |
|
|
|
|
Version? version = null; |
|
|
|
|
|
|
|
|
|
for (int i = 1; i < tokens.Length; i++) |
|
|
|
|
{ |
|
|
|
@ -191,20 +194,20 @@ namespace ICSharpCode.Decompiler.Metadata
@@ -191,20 +194,20 @@ namespace ICSharpCode.Decompiler.Metadata
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#if !VSADDIN
|
|
|
|
|
public PEFile Resolve(IAssemblyReference name) |
|
|
|
|
public PEFile? Resolve(IAssemblyReference name) |
|
|
|
|
{ |
|
|
|
|
var file = FindAssemblyFile(name); |
|
|
|
|
return CreatePEFileFromFileName(file, ex => new ResolutionException(name, file, ex)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public PEFile ResolveModule(PEFile mainModule, string moduleName) |
|
|
|
|
public PEFile? ResolveModule(PEFile mainModule, string moduleName) |
|
|
|
|
{ |
|
|
|
|
string baseDirectory = Path.GetDirectoryName(mainModule.FileName); |
|
|
|
|
string moduleFileName = Path.Combine(baseDirectory, moduleName); |
|
|
|
|
return CreatePEFileFromFileName(moduleFileName, ex => new ResolutionException(mainModule.FileName, moduleName, moduleFileName, ex)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private PEFile CreatePEFileFromFileName(string fileName, Func<Exception?, Exception> makeException) |
|
|
|
|
private PEFile? CreatePEFileFromFileName(string? fileName, Func<Exception?, Exception> makeException) |
|
|
|
|
{ |
|
|
|
|
if (fileName == null) |
|
|
|
|
{ |
|
|
|
@ -231,30 +234,30 @@ namespace ICSharpCode.Decompiler.Metadata
@@ -231,30 +234,30 @@ namespace ICSharpCode.Decompiler.Metadata
|
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public Task<PEFile> ResolveAsync(IAssemblyReference name) |
|
|
|
|
public Task<PEFile?> ResolveAsync(IAssemblyReference name) |
|
|
|
|
{ |
|
|
|
|
return Task.Run(() => Resolve(name)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public Task<PEFile> ResolveModuleAsync(PEFile mainModule, string moduleName) |
|
|
|
|
public Task<PEFile?> ResolveModuleAsync(PEFile mainModule, string moduleName) |
|
|
|
|
{ |
|
|
|
|
return Task.Run(() => ResolveModule(mainModule, moduleName)); |
|
|
|
|
} |
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
public override bool IsSharedAssembly(IAssemblyReference reference, out string runtimePack) |
|
|
|
|
public override bool IsSharedAssembly(IAssemblyReference reference, [NotNullWhen(true)] out string? runtimePack) |
|
|
|
|
{ |
|
|
|
|
return dotNetCorePathFinder.Value.TryResolveDotNetCoreShared(reference, out runtimePack) != null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public string FindAssemblyFile(IAssemblyReference name) |
|
|
|
|
public string? FindAssemblyFile(IAssemblyReference name) |
|
|
|
|
{ |
|
|
|
|
if (name.IsWindowsRuntime) |
|
|
|
|
{ |
|
|
|
|
return FindWindowsMetadataFile(name); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
string file; |
|
|
|
|
string? file; |
|
|
|
|
switch (targetFrameworkIdentifier) |
|
|
|
|
{ |
|
|
|
|
case TargetFrameworkIdentifier.NETCoreApp: |
|
|
|
@ -291,14 +294,14 @@ namespace ICSharpCode.Decompiler.Metadata
@@ -291,14 +294,14 @@ namespace ICSharpCode.Decompiler.Metadata
|
|
|
|
|
return dotNetCorePathFinder; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
string FindWindowsMetadataFile(IAssemblyReference name) |
|
|
|
|
string? FindWindowsMetadataFile(IAssemblyReference name) |
|
|
|
|
{ |
|
|
|
|
// Finding Windows Metadata (winmd) is currently only supported on Windows.
|
|
|
|
|
if (Environment.OSVersion.Platform != PlatformID.Win32NT) |
|
|
|
|
return null; |
|
|
|
|
|
|
|
|
|
// TODO : Find a way to detect the base directory for the required Windows SDK.
|
|
|
|
|
string basePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "Windows Kits", "10", "References"); |
|
|
|
|
string? basePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "Windows Kits", "10", "References"); |
|
|
|
|
|
|
|
|
|
if (!Directory.Exists(basePath)) |
|
|
|
|
return FindWindowsMetadataInSystemDirectory(name); |
|
|
|
@ -332,7 +335,7 @@ namespace ICSharpCode.Decompiler.Metadata
@@ -332,7 +335,7 @@ namespace ICSharpCode.Decompiler.Metadata
|
|
|
|
|
return file; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
string FindWindowsMetadataInSystemDirectory(IAssemblyReference name) |
|
|
|
|
string? FindWindowsMetadataInSystemDirectory(IAssemblyReference name) |
|
|
|
|
{ |
|
|
|
|
string file = Path.Combine(Environment.SystemDirectory, "WinMetadata", name.Name + ".winmd"); |
|
|
|
|
if (File.Exists(file)) |
|
|
|
@ -343,7 +346,7 @@ namespace ICSharpCode.Decompiler.Metadata
@@ -343,7 +346,7 @@ namespace ICSharpCode.Decompiler.Metadata
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// This only works on Windows
|
|
|
|
|
/// </summary>
|
|
|
|
|
string ResolveSilverlight(IAssemblyReference name, Version version) |
|
|
|
|
string? ResolveSilverlight(IAssemblyReference name, Version? version) |
|
|
|
|
{ |
|
|
|
|
string[] targetFrameworkSearchPaths = { |
|
|
|
|
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "Microsoft Silverlight"), |
|
|
|
@ -362,19 +365,19 @@ namespace ICSharpCode.Decompiler.Metadata
@@ -362,19 +365,19 @@ namespace ICSharpCode.Decompiler.Metadata
|
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
string FindClosestVersionDirectory(string basePath, Version version) |
|
|
|
|
string FindClosestVersionDirectory(string? basePath, Version? version) |
|
|
|
|
{ |
|
|
|
|
string path = null; |
|
|
|
|
string? path = null; |
|
|
|
|
foreach (var folder in new DirectoryInfo(basePath).GetDirectories().Select(d => DotNetCorePathFinder.ConvertToVersion(d.Name)) |
|
|
|
|
.Where(v => v.Item1 != null).OrderByDescending(v => v.Item1)) |
|
|
|
|
{ |
|
|
|
|
if (path == null || folder.Item1 >= version) |
|
|
|
|
if (path == null || version == null || folder.Item1 >= version) |
|
|
|
|
path = folder.Item2; |
|
|
|
|
} |
|
|
|
|
return path ?? version.ToString(); |
|
|
|
|
return path ?? version?.ToString() ?? "."; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
string ResolveInternal(IAssemblyReference name) |
|
|
|
|
string? ResolveInternal(IAssemblyReference name) |
|
|
|
|
{ |
|
|
|
|
if (name == null) |
|
|
|
|
throw new ArgumentNullException(nameof(name)); |
|
|
|
@ -421,11 +424,11 @@ namespace ICSharpCode.Decompiler.Metadata
@@ -421,11 +424,11 @@ namespace ICSharpCode.Decompiler.Metadata
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#region .NET / mono GAC handling
|
|
|
|
|
string SearchDirectory(IAssemblyReference name, IEnumerable<string> directories) |
|
|
|
|
string? SearchDirectory(IAssemblyReference name, IEnumerable<string?> directories) |
|
|
|
|
{ |
|
|
|
|
foreach (var directory in directories) |
|
|
|
|
{ |
|
|
|
|
string file = SearchDirectory(name, directory); |
|
|
|
|
string? file = SearchDirectory(name, directory); |
|
|
|
|
if (file != null) |
|
|
|
|
return file; |
|
|
|
|
} |
|
|
|
@ -438,7 +441,7 @@ namespace ICSharpCode.Decompiler.Metadata
@@ -438,7 +441,7 @@ namespace ICSharpCode.Decompiler.Metadata
|
|
|
|
|
return IsZeroOrAllOnes(reference.Version) || reference.IsRetargetable; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
string SearchDirectory(IAssemblyReference name, string directory) |
|
|
|
|
string? SearchDirectory(IAssemblyReference name, string? directory) |
|
|
|
|
{ |
|
|
|
|
var extensions = name.IsWindowsRuntime ? new[] { ".winmd", ".dll" } : new[] { ".dll", ".exe" }; |
|
|
|
|
foreach (var extension in extensions) |
|
|
|
@ -458,7 +461,7 @@ namespace ICSharpCode.Decompiler.Metadata
@@ -458,7 +461,7 @@ namespace ICSharpCode.Decompiler.Metadata
|
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static bool IsZeroOrAllOnes(Version version) |
|
|
|
|
static bool IsZeroOrAllOnes(Version? version) |
|
|
|
|
{ |
|
|
|
|
return version == null |
|
|
|
|
|| (version.Major == 0 && version.Minor == 0 && version.Build == 0 && version.Revision == 0) |
|
|
|
@ -467,7 +470,7 @@ namespace ICSharpCode.Decompiler.Metadata
@@ -467,7 +470,7 @@ namespace ICSharpCode.Decompiler.Metadata
|
|
|
|
|
|
|
|
|
|
internal static Version ZeroVersion = new Version(0, 0, 0, 0); |
|
|
|
|
|
|
|
|
|
string GetCorlib(IAssemblyReference reference) |
|
|
|
|
string? GetCorlib(IAssemblyReference reference) |
|
|
|
|
{ |
|
|
|
|
var version = reference.Version; |
|
|
|
|
var corlib = typeof(object).Assembly.GetName(); |
|
|
|
@ -481,15 +484,19 @@ namespace ICSharpCode.Decompiler.Metadata
@@ -481,15 +484,19 @@ namespace ICSharpCode.Decompiler.Metadata
|
|
|
|
|
if (reference.PublicKeyToken == null) |
|
|
|
|
return null; |
|
|
|
|
|
|
|
|
|
string path; |
|
|
|
|
string? path; |
|
|
|
|
if (decompilerRuntime == DecompilerRuntime.Mono) |
|
|
|
|
{ |
|
|
|
|
path = GetMonoMscorlibBasePath(version); |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
else if (version != null) |
|
|
|
|
{ |
|
|
|
|
path = GetMscorlibBasePath(version, reference.PublicKeyToken.ToHexString(8)); |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
path = null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (path == null) |
|
|
|
|
return null; |
|
|
|
@ -501,9 +508,9 @@ namespace ICSharpCode.Decompiler.Metadata
@@ -501,9 +508,9 @@ namespace ICSharpCode.Decompiler.Metadata
|
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
string GetMscorlibBasePath(Version version, string publicKeyToken) |
|
|
|
|
string? GetMscorlibBasePath(Version version, string? publicKeyToken) |
|
|
|
|
{ |
|
|
|
|
string GetSubFolderForVersion() |
|
|
|
|
string? GetSubFolderForVersion() |
|
|
|
|
{ |
|
|
|
|
switch (version.Major) |
|
|
|
|
{ |
|
|
|
@ -540,7 +547,7 @@ namespace ICSharpCode.Decompiler.Metadata
@@ -540,7 +547,7 @@ namespace ICSharpCode.Decompiler.Metadata
|
|
|
|
|
Path.Combine(rootPath, "Framework64") |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
string folder = GetSubFolderForVersion(); |
|
|
|
|
string? folder = GetSubFolderForVersion(); |
|
|
|
|
|
|
|
|
|
if (folder != null) |
|
|
|
|
{ |
|
|
|
@ -558,7 +565,7 @@ namespace ICSharpCode.Decompiler.Metadata
@@ -558,7 +565,7 @@ namespace ICSharpCode.Decompiler.Metadata
|
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
string GetMonoMscorlibBasePath(Version version) |
|
|
|
|
string? GetMonoMscorlibBasePath(Version? version) |
|
|
|
|
{ |
|
|
|
|
var path = Directory.GetParent(typeof(object).Module.FullyQualifiedName).Parent.FullName; |
|
|
|
|
if (version.Major == 1) |
|
|
|
@ -614,7 +621,7 @@ namespace ICSharpCode.Decompiler.Metadata
@@ -614,7 +621,7 @@ namespace ICSharpCode.Decompiler.Metadata
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
var gac_path = Path.Combine(Path.Combine(Path.Combine(prefix, "lib"), "mono"), "gac"); |
|
|
|
|
if (Directory.Exists(gac_path) && !paths.Contains(gac)) |
|
|
|
|
if (Directory.Exists(gac_path) && !paths.Contains(gac_path)) |
|
|
|
|
paths.Add(gac_path); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -629,7 +636,7 @@ namespace ICSharpCode.Decompiler.Metadata
@@ -629,7 +636,7 @@ namespace ICSharpCode.Decompiler.Metadata
|
|
|
|
|
"gac"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public static string GetAssemblyInGac(IAssemblyReference reference) |
|
|
|
|
public static string? GetAssemblyInGac(IAssemblyReference reference) |
|
|
|
|
{ |
|
|
|
|
if (reference.PublicKeyToken == null || reference.PublicKeyToken.Length == 0) |
|
|
|
|
return null; |
|
|
|
@ -640,7 +647,7 @@ namespace ICSharpCode.Decompiler.Metadata
@@ -640,7 +647,7 @@ namespace ICSharpCode.Decompiler.Metadata
|
|
|
|
|
return GetAssemblyInNetGac(reference); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static string GetAssemblyInMonoGac(IAssemblyReference reference) |
|
|
|
|
static string? GetAssemblyInMonoGac(IAssemblyReference reference) |
|
|
|
|
{ |
|
|
|
|
for (int i = 0; i < gac_paths.Count; i++) |
|
|
|
|
{ |
|
|
|
@ -653,7 +660,7 @@ namespace ICSharpCode.Decompiler.Metadata
@@ -653,7 +660,7 @@ namespace ICSharpCode.Decompiler.Metadata
|
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static string GetAssemblyInNetGac(IAssemblyReference reference) |
|
|
|
|
static string? GetAssemblyInNetGac(IAssemblyReference reference) |
|
|
|
|
{ |
|
|
|
|
var gacs = new[] { "GAC_MSIL", "GAC_32", "GAC_64", "GAC" }; |
|
|
|
|
var prefixes = new[] { string.Empty, "v4.0_" }; |
|
|
|
@ -672,7 +679,7 @@ namespace ICSharpCode.Decompiler.Metadata
@@ -672,7 +679,7 @@ namespace ICSharpCode.Decompiler.Metadata
|
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static string GetAssemblyFile(IAssemblyReference reference, string prefix, string gac) |
|
|
|
|
static string GetAssemblyFile(IAssemblyReference reference, string? prefix, string? gac) |
|
|
|
|
{ |
|
|
|
|
var gac_folder = new StringBuilder() |
|
|
|
|
.Append(prefix) |
|
|
|
|