public IDnSpyFile Resolve(IAssembly assembly, ModuleDef sourceModule = null) { FrameworkRedirect.ApplyFrameworkRedirect(ref assembly, sourceModule); if (assembly.IsContentTypeWindowsRuntime) { return(ResolveWinMD(assembly, sourceModule)); } // WinMD files have a reference to mscorlib but its version is always 255.255.255.255 // since mscorlib isn't really loaded. The resolver only loads exact versions, so // we must change the version or the resolve will fail. if (assembly.Name == "mscorlib" && assembly.Version == invalidMscorlibVersion) { assembly = new AssemblyNameInfo(assembly) { Version = newMscorlibVersion } } ; return(ResolveNormal(assembly, sourceModule)); } IDnSpyFile ResolveNormal(IAssembly assembly, ModuleDef sourceModule) { var existingFile = fileManager.FindAssembly(assembly); if (existingFile != null) { return(existingFile); } var file = LookupFromSearchPaths(assembly, sourceModule, true); if (file != null) { return(fileManager.GetOrAddCanDispose(file)); } if (fileManager.Settings.UseGAC) { var gacFile = GacInfo.FindInGac(assembly); if (gacFile != null) { return(fileManager.TryGetOrCreate(DnSpyFileInfo.CreateFile(gacFile), true)); } foreach (var path in GacInfo.OtherGacPaths) { file = TryLoadFromDir(assembly, true, path); if (file != null) { return(fileManager.GetOrAddCanDispose(file)); } } } file = LookupFromSearchPaths(assembly, sourceModule, false); if (file != null) { return(fileManager.GetOrAddCanDispose(file)); } return(null); } IDnSpyFile LookupFromSearchPaths(IAssembly asmName, ModuleDef sourceModule, bool exactCheck) { IDnSpyFile file; string sourceModuleDir = null; if (sourceModule != null && File.Exists(sourceModule.Location)) { sourceModuleDir = Path.GetDirectoryName(sourceModule.Location); file = TryLoadFromDir(asmName, exactCheck, sourceModuleDir); if (file != null) { return(file); } } var ary = asmSearchPathsArray; foreach (var path in ary) { file = TryLoadFromDir(asmName, exactCheck, path); if (file != null) { return(file); } } return(null); } IDnSpyFile TryLoadFromDir(IAssembly asmName, bool exactCheck, string dirPath) { string baseName; try { baseName = Path.Combine(dirPath, asmName.Name); } catch (ArgumentException) { // eg. invalid chars in asmName.Name return(null); } return(TryLoadFromDir2(asmName, exactCheck, baseName + ".dll") ?? TryLoadFromDir2(asmName, exactCheck, baseName + ".exe")); } IDnSpyFile TryLoadFromDir2(IAssembly asmName, bool exactCheck, string filename) { if (!File.Exists(filename)) { return(null); } IDnSpyFile file = null; bool error = true; try { file = fileManager.TryCreateDnSpyFile(DnSpyFileInfo.CreateFile(filename)); if (file == null) { return(null); } file.IsAutoLoaded = true; var asm = file.AssemblyDef; if (asm == null) { return(null); } bool b = exactCheck ? AssemblyNameComparer.CompareAll.Equals(asmName, asm) : AssemblyNameComparer.NameAndPublicKeyTokenOnly.Equals(asmName, asm); if (!b) { return(null); } error = false; return(file); } finally { if (error) { if (file is IDisposable) { ((IDisposable)file).Dispose(); } } } } IDnSpyFile ResolveWinMD(IAssembly assembly, ModuleDef sourceModule) { var existingFile = fileManager.FindAssembly(assembly); if (existingFile != null) { return(existingFile); } foreach (var winmdPath in GacInfo.WinmdPaths) { string file; try { file = Path.Combine(winmdPath, assembly.Name + ".winmd"); } catch (ArgumentException) { continue; } if (File.Exists(file)) { return(fileManager.TryGetOrCreate(DnSpyFileInfo.CreateFile(file), true)); } } return(null); } }
IDsDocument ResolveNormal(IAssembly assembly, ModuleDef sourceModule) { var fwkKind = GetFrameworkKind(sourceModule, out var netCoreVersion, out var sourceModuleDirectoryHint); if (fwkKind == FrameworkKind.DotNetCore && !dotNetCorePathProvider.HasDotNetCore) { fwkKind = FrameworkKind.DotNetFramework4; } IDsDocument document; switch (fwkKind) { case FrameworkKind.Unknown: case FrameworkKind.DotNetFramework2: case FrameworkKind.DotNetFramework4: int gacVersion; if (!GacInfo.HasGAC2) { fwkKind = FrameworkKind.DotNetFramework4; } if (fwkKind == FrameworkKind.DotNetFramework4) { FrameworkRedirect.ApplyFrameworkRedirectV4(ref assembly); gacVersion = 4; } else if (fwkKind == FrameworkKind.DotNetFramework2) { FrameworkRedirect.ApplyFrameworkRedirectV2(ref assembly); gacVersion = 2; } else { Debug.Assert(fwkKind == FrameworkKind.Unknown); var tempAsm = assembly; FrameworkRedirect.ApplyFrameworkRedirect(ref tempAsm, sourceModule); // OK : System.Runtime 4.0.20.0 => 4.0.0.0 // KO : System 4.0.0.0 => 2.0.0.0 if (tempAsm.Version.Major >= assembly.Version.Major) { assembly = tempAsm; } gacVersion = -1; } var existingDocument = documentService.FindAssembly(assembly); if (existingDocument != null) { return(existingDocument); } document = LookupFromSearchPaths(assembly, sourceModule, sourceModuleDirectoryHint, netCoreVersion); if (document != null) { return(documentService.GetOrAddCanDispose(document, assembly)); } var gacFile = GacInfo.FindInGac(assembly, gacVersion); if (gacFile != null) { return(documentService.TryGetOrCreateInternal(DsDocumentInfo.CreateDocument(gacFile), true, true)); } foreach (var gacPath in GacInfo.OtherGacPaths) { if (gacVersion == 4) { if (gacPath.Version != GacVersion.V4) { continue; } } else if (gacVersion == 2) { if (gacPath.Version != GacVersion.V2) { continue; } } else { Debug.Assert(gacVersion == -1); } document = TryLoadFromDir(assembly, checkVersion: true, checkPublicKeyToken: true, gacPath.Path); if (document != null) { return(documentService.GetOrAddCanDispose(document, assembly)); } } break; case FrameworkKind.DotNetCore: case FrameworkKind.Unity: case FrameworkKind.SelfContainedDotNetCore: // If it's a self-contained .NET Core app, we don't need the version since we must only search // the current directory. Debug.Assert(fwkKind == FrameworkKind.DotNetCore || netCoreVersion == null); document = LookupFromSearchPaths(assembly, sourceModule, sourceModuleDirectoryHint, netCoreVersion); if (document != null) { return(documentService.GetOrAddCanDispose(document, assembly)); } break; default: throw new InvalidOperationException(); } return(null); }