public void InitializeView() { if (!NativeFile.Exists(this.Filename)) { MessageBox.Show( String.Format("{0:s} is not present on the disk", this.Filename), "Invalid PE", MessageBoxButton.OK ); return; } this.Pe = (Application.Current as App).LoadBinary(this.Filename); if (this.Pe == null || !this.Pe.LoadSuccessful) { MessageBox.Show( String.Format("{0:s} is not a valid PE-COFF file", this.Filename), "Invalid PE", MessageBoxButton.OK ); return; } this.SymPrv = new PhSymbolProvider(); this.RootFolder = Path.GetDirectoryName(this.Filename); this.SxsEntriesCache = SxsManifest.GetSxsEntries(this.Pe); this.ProcessedModulesCache = new ModulesCache(); this.ApiSetmapCache = Phlib.GetApiSetSchema(); this._SelectedModule = null; this._DisplayWarning = false; // TODO : Find a way to properly bind commands instead of using this hack this.ModulesList.Items.Clear(); this.ModulesList.DoFindModuleInTreeCommand = DoFindModuleInTree; this.ModulesList.ConfigureSearchOrderCommand = ConfigureSearchOrderCommand; var RootFilename = Path.GetFileName(this.Filename); var RootModule = new DisplayModuleInfo(RootFilename, this.Pe, ModuleSearchStrategy.ROOT); this.ProcessedModulesCache.Add(new ModuleCacheKey(RootFilename, this.Filename), RootModule); ModuleTreeViewItem treeNode = new ModuleTreeViewItem(); DependencyNodeContext childTreeInfoContext = new DependencyNodeContext() { ModuleInfo = new WeakReference(RootModule), IsDummy = false }; treeNode.DataContext = childTreeInfoContext; treeNode.Header = treeNode.GetTreeNodeHeaderName(Dependencies.Properties.Settings.Default.FullPath); treeNode.IsExpanded = true; this.DllTreeView.Items.Clear(); this.DllTreeView.Items.Add(treeNode); // Recursively construct tree of dll imports ConstructDependencyTree(treeNode, this.Pe); }
// find dll with same name as sxs assembly in target directory public static SxsEntries SxsFindTargetDll(string AssemblyName, string Folder) { SxsEntries EntriesFromElement = new SxsEntries(); string TargetFilePath = Path.Combine(Folder, AssemblyName); if (File.Exists(TargetFilePath)) { var Name = System.IO.Path.GetFileName(TargetFilePath); var Path = TargetFilePath; EntriesFromElement.Add(new SxsEntry(Name, Path)); return(EntriesFromElement); } string TargetDllPath = Path.Combine(Folder, String.Format("{0:s}.dll", AssemblyName)); if (File.Exists(TargetDllPath)) { var Name = System.IO.Path.GetFileName(TargetDllPath); var Path = TargetDllPath; EntriesFromElement.Add(new SxsEntry(Name, Path)); return(EntriesFromElement); } return(EntriesFromElement); }
public static Tuple <ModuleSearchStrategy, PE> ResolveModule(PE RootPe, string ModuleName) { string WorkingDirectory = Path.GetDirectoryName(RootPe.Filepath); List <string> CustomSearchFolders = new List <string>(); SxsEntries SxsCache = SxsManifest.GetSxsEntries(RootPe); return(ResolveModule(RootPe, ModuleName, SxsCache, CustomSearchFolders, WorkingDirectory)); }
public static Tuple <ModuleSearchStrategy, PE> ResolveModule(string ModuleName) { PE RootPe = LoadPe(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), "ntdll.dll")); string WorkingDirectory = Path.GetDirectoryName(RootPe.Filepath); List <string> CustomSearchFolders = new List <string>(); SxsEntries SxsCache = SxsManifest.GetSxsEntries(RootPe); return(ResolveModule(RootPe, ModuleName, SxsCache, CustomSearchFolders, WorkingDirectory)); }
public static SxsEntries FromSxsAssembly(XElement SxsAssembly, XNamespace Namespace, string Folder) { SxsEntries Entries = new SxsEntries(); XElement SxsAssemblyIdentity = SxsAssembly.Element(Namespace + "assemblyIdentity"); foreach (XElement SxsFile in SxsAssembly.Elements(Namespace + "file")) { Entries.Add(new SxsEntry(SxsAssemblyIdentity, SxsFile, Folder)); } return(Entries); }
public DependencyWindow(String FileName) { InitializeComponent(); this.Filename = FileName; this.Pe = new PE(FileName); if (!this.Pe.LoadSuccessful) { MessageBox.Show( String.Format("{0:s} is not a valid PE-COFF file", this.Filename), "Invalid PE", MessageBoxButton.OK ); return; } this.SymPrv = new PhSymbolProvider(); this.RootFolder = Path.GetDirectoryName(FileName); this.SxsEntriesCache = SxsManifest.GetSxsEntries(this.Pe); this.ProcessedModulesCache = new ModulesCache(); this.ApiSetmapCache = Phlib.GetApiSetSchema(); // TODO : Find a way to properly bind commands instead of using this hack this.ModulesList.DoFindModuleInTreeCommand = DoFindModuleInTree; var RootFilename = Path.GetFileName(FileName); var RootModule = new DisplayModuleInfo(RootFilename, this.Pe); this.ProcessedModulesCache.Add(new ModuleCacheKey(RootFilename, FileName), RootModule); ModuleTreeViewItem treeNode = new ModuleTreeViewItem(); DependencyNodeContext childTreeInfoContext = new DependencyNodeContext() { ModuleInfo = new WeakReference(RootModule), IsDummy = false }; treeNode.DataContext = childTreeInfoContext; treeNode.Header = treeNode.GetTreeNodeHeaderName(Dependencies.Properties.Settings.Default.FullPath); treeNode.IsExpanded = true; this.DllTreeView.Items.Add(treeNode); // Recursively construct tree of dll imports ConstructDependencyTree(treeNode, this.Pe); }
public void SetImports(List <PeImportDll> Imports, PE rootPe, SxsEntries SxsCache, PhSymbolProvider SymPrv) { this.ImportList.Items.Clear(); foreach (PeImportDll DllImport in Imports) { Tuple <ModuleSearchStrategy, String> PeFilePath = FindPe.FindPeFromDefault(rootPe, DllImport.Name, SxsCache); foreach (PeImport Import in DllImport.ImportList) { this.ImportList.Items.Add(new DisplayPeImport(Import, SymPrv, PeFilePath.Item2)); } } // Refresh search view ImportSearchFilter_OnTextChanged(null, null); }
public static SxsEntries ExtractDependenciesFromSxsManifest(System.IO.Stream ManifestStream, string Folder, string ExecutableName = "", bool Wow64Pe = false) { SxsEntries AdditionnalDependencies = new SxsEntries(); XDocument XmlManifest = ParseSxsManifest(ManifestStream); XNamespace Namespace = XmlManifest.Root.GetDefaultNamespace(); // Find any declared dll //< assembly xmlns = 'urn:schemas-microsoft-com:asm.v1' manifestVersion = '1.0' > // < assemblyIdentity name = 'additional_dll' version = 'XXX.YY.ZZ' type = 'win32' /> // < file name = 'additional_dll.dll' /> //</ assembly > foreach (XElement SxsAssembly in XmlManifest.Descendants(Namespace + "assembly")) { AdditionnalDependencies.AddRange(SxsEntries.FromSxsAssembly(SxsAssembly, Namespace, Folder)); } // Find any dependencies : // <dependency> // <dependentAssembly> // <assemblyIdentity // type="win32" // name="Microsoft.Windows.Common-Controls" // version="6.0.0.0" // processorArchitecture="amd64" // publicKeyToken="6595b64144ccf1df" // language="*" // /> // </dependentAssembly> // </dependency> foreach (XElement SxsAssembly in XmlManifest.Descendants(Namespace + "dependency") .Elements(Namespace + "dependentAssembly") .Elements(Namespace + "assemblyIdentity") ) { // find target PE AdditionnalDependencies.AddRange(ExtractDependenciesFromSxsElement(SxsAssembly, Folder, ExecutableName, Wow64Pe)); } return(AdditionnalDependencies); }
public static SxsEntries GetSxsEntries(PE Pe) { SxsEntries Entries = new SxsEntries(); string RootPeFolder = Path.GetDirectoryName(Pe.Filepath); string RootPeFilename = Path.GetFileName(Pe.Filepath); // Look for overriding manifest file (named "{$name}.manifest) string OverridingManifest = String.Format("{0:s}.manifest", Pe.Filepath); if (File.Exists(OverridingManifest)) { return(ExtractDependenciesFromSxsManifestFile( OverridingManifest, RootPeFolder, RootPeFilename, Pe.IsWow64Dll() )); } // Retrieve embedded manifest string PeManifest = Pe.GetManifest(); if (PeManifest.Length == 0) { return(Entries); } byte[] RawManifest = System.Text.Encoding.UTF8.GetBytes(PeManifest); System.IO.Stream ManifestStream = new System.IO.MemoryStream(RawManifest); Entries = ExtractDependenciesFromSxsManifest( ManifestStream, RootPeFolder, RootPeFilename, Pe.IsWow64Dll() ); return(Entries); }
// default search order : // https://msdn.microsoft.com/en-us/library/windows/desktop/ms682586(v=vs.85).aspx // // if (SafeDllSearchMode) { // -1. Sxs manifests // 0. KnownDlls list // 1. Loaded PE folder // 2. C:\Windows\(System32 | SysWow64 ) // 3. 16-bit system directory <-- ignored // 4. C:\Windows // 5. %pwd% // 6. AppDatas // } public static Tuple <ModuleSearchStrategy, string> FindPeFromDefault(PE RootPe, string ModuleName, SxsEntries SxsCache) { bool Wow64Dll = RootPe.IsWow64Dll(); string RootPeFolder = Path.GetDirectoryName(RootPe.Filepath); string FoundPePath = null; Environment.SpecialFolder WindowsSystemFolder = (Wow64Dll) ? Environment.SpecialFolder.SystemX86 : Environment.SpecialFolder.System; String WindowsSystemFolderPath = Environment.GetFolderPath(WindowsSystemFolder); // -1. Look in Sxs manifest (copious reversing needed) // TODO : find dll search order if (SxsCache.Count != 0) { SxsEntry Entry = SxsCache.Find(SxsItem => string.Equals(SxsItem.Name, ModuleName, StringComparison.OrdinalIgnoreCase) ); if (Entry != null) { return(new Tuple <ModuleSearchStrategy, string>(ModuleSearchStrategy.SxS, Entry.Path)); } } // 0. Look in well-known dlls list // HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\KnownDLLs // https://blogs.msdn.microsoft.com/larryosterman/2004/07/19/what-are-known-dlls-anyway/ String KnownDll = Phlib.GetKnownDlls(Wow64Dll).Find(x => string.Equals(x, ModuleName, StringComparison.OrdinalIgnoreCase)); if (KnownDll != null) { return(new Tuple <ModuleSearchStrategy, string>( ModuleSearchStrategy.WellKnownDlls, Path.Combine(WindowsSystemFolderPath, KnownDll) )); } // 1. Look in application folder FoundPePath = FindPeFromPath(ModuleName, new List <string>(new string[] { RootPeFolder }), Wow64Dll); if (FoundPePath != null) { return(new Tuple <ModuleSearchStrategy, string>( ModuleSearchStrategy.ApplicationDirectory, FoundPePath )); } // {2-3-4}. Look in system folders List <String> SystemFolders = new List <string>(new string[] { WindowsSystemFolderPath, Environment.GetFolderPath(Environment.SpecialFolder.Windows) } ); FoundPePath = FindPeFromPath(ModuleName, SystemFolders, Wow64Dll); if (FoundPePath != null) { return(new Tuple <ModuleSearchStrategy, string>( ModuleSearchStrategy.WindowsFolder, FoundPePath )); } // 5. Look in current directory // Ignored for the time being since we can't know from // where the exe is run // TODO : Add a user supplied path emulating %cwd% // 6. Look in local app data (check for python for exemple) // 7. Find in PATH string PATH = Environment.GetEnvironmentVariable("PATH"); List <String> PATHFolders = new List <string>(PATH.Split(';')); FoundPePath = FindPeFromPath(ModuleName, PATHFolders, Wow64Dll); if (FoundPePath != null) { return(new Tuple <ModuleSearchStrategy, string>( ModuleSearchStrategy.Environment, FoundPePath )); } return(new Tuple <ModuleSearchStrategy, string>( ModuleSearchStrategy.NOT_FOUND, null )); }
public static SxsEntries ExtractDependenciesFromSxsElement(XElement SxsAssembly, string Folder, string ExecutableName = "", bool Wow64Pe = false) { // Private assembly search sequence : https://msdn.microsoft.com/en-us/library/windows/desktop/aa374224(v=vs.85).aspx // // * In the application's folder. Typically, this is the folder containing the application's executable file. // * In a subfolder in the application's folder. The subfolder must have the same name as the assembly. // * In a language-specific subfolder in the application's folder. // -> The name of the subfolder is a string of DHTML language codes indicating a language-culture or language. // * In a subfolder of a language-specific subfolder in the application's folder. // -> The name of the higher subfolder is a string of DHTML language codes indicating a language-culture or language. The deeper subfolder has the same name as the assembly. // // // 0. Side-by-side searches the WinSxS folder. // 1. \\<appdir>\<assemblyname>.DLL // 2. \\<appdir>\<assemblyname>.manifest // 3. \\<appdir>\<assemblyname>\<assemblyname>.DLL // 4. \\<appdir>\<assemblyname>\<assemblyname>.manifest string TargetSxsManifestPath; string SxsManifestName = SxsAssembly.Attribute("name").Value.ToString(); string SxsManifestDir = Path.Combine(Folder, SxsManifestName); // 0. find publisher manifest in %WINDIR%/WinSxs/Manifest if (SxsAssembly.Attribute("publicKeyToken") != null) { string WinSxsDir = Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.Windows), "WinSxs" ); string WinSxsManifestDir = Path.Combine(WinSxsDir, "Manifests"); var RegisteredManifests = Directory.EnumerateFiles( WinSxsManifestDir, "*.manifest" ); string PublicKeyToken = SxsAssembly.Attribute("publicKeyToken").Value; string Name = SxsAssembly.Attribute("name").Value.ToLower(); string ProcessArch = SxsAssembly.Attribute("processorArchitecture") != null?SxsAssembly.Attribute("processorArchitecture").Value : "*"; string Version = SxsAssembly.Attribute("version").Value; string Langage = SxsAssembly.Attribute("langage") != null?SxsAssembly.Attribute("langage").Value : "none"; // TODO : support localized sxs redirection switch (ProcessArch.ToLower()) { case "$(build.arch)": case "*": ProcessArch = (Wow64Pe) ? "x86" : "amd64"; break; case "amd64": case "x86": case "wow64": case "msil": break; // nothing to do default: ProcessArch = ".*"; break; } Regex MajorVersionRegex = new Regex(@"([0-9]+)\.(.*)", RegexOptions.IgnoreCase); Match MajorVersionMatch = MajorVersionRegex.Match(Version); string MajorVersion = (MajorVersionMatch.Success) ? MajorVersionMatch.Groups[1].Value.ToString() : ".*"; // Manifest filename : {ProcArch}_{Name}_{PublicKeyToken}_{FuzzyVersion}_{Langage}_{some_hash}.manifest Regex ManifestFileNameRegex = new Regex( String.Format(@"({0:s}_{1:s}_{2:s}_({3:s}\.[\.0-9]*)_none_([a-fA-F0-9]+))\.manifest", ProcessArch, Name, PublicKeyToken, MajorVersion //Langage, // some hash ), RegexOptions.IgnoreCase ); foreach (var FileName in RegisteredManifests) { Match MatchingSxsFile = ManifestFileNameRegex.Match(FileName); if (MatchingSxsFile.Success) { TargetSxsManifestPath = Path.Combine(WinSxsManifestDir, FileName); SxsManifestDir = Path.Combine(WinSxsDir, MatchingSxsFile.Groups[1].Value); // "{name}.local" local sxs directory hijack ( really used for UAC bypasses ) if (ExecutableName != "") { string LocalSxsDir = Path.Combine(Folder, String.Format("{0:s}.local", ExecutableName)); string MatchingLocalSxsDir = Path.Combine(LocalSxsDir, MatchingSxsFile.Groups[1].Value); if (Directory.Exists(LocalSxsDir) && Directory.Exists(MatchingLocalSxsDir)) { SxsManifestDir = MatchingLocalSxsDir; } } return(ExtractDependenciesFromSxsManifestFile(TargetSxsManifestPath, SxsManifestDir, ExecutableName, Wow64Pe)); } } } // 1. \\<appdir>\<assemblyname>.DLL // find dll with same assembly name in same directory SxsEntries EntriesFromMatchingDll = SxsFindTargetDll(SxsManifestName, Folder); if (EntriesFromMatchingDll.Count > 0) { return(EntriesFromMatchingDll); } // 2. \\<appdir>\<assemblyname>.manifest // find manifest with same assembly name in same directory TargetSxsManifestPath = Path.Combine(Folder, String.Format("{0:s}.manifest", SxsManifestName)); if (File.Exists(TargetSxsManifestPath)) { return(ExtractDependenciesFromSxsManifestFile(TargetSxsManifestPath, Folder, ExecutableName, Wow64Pe)); } // 3. \\<appdir>\<assemblyname>\<assemblyname>.DLL // find matching dll in sub directory SxsEntries EntriesFromMatchingDllSub = SxsFindTargetDll(SxsManifestName, SxsManifestDir); if (EntriesFromMatchingDllSub.Count > 0) { return(EntriesFromMatchingDllSub); } // 4. \<appdir>\<assemblyname>\<assemblyname>.manifest // find manifest in sub directory TargetSxsManifestPath = Path.Combine(SxsManifestDir, String.Format("{0:s}.manifest", SxsManifestName)); if (Directory.Exists(SxsManifestDir) && File.Exists(TargetSxsManifestPath)) { return(ExtractDependenciesFromSxsManifestFile(TargetSxsManifestPath, SxsManifestDir, ExecutableName, Wow64Pe)); } // TODO : do the same thing for localization // // 0. Side-by-side searches the WinSxS folder. // 1. \\<appdir>\<language-culture>\<assemblyname>.DLL // 2. \\<appdir>\<language-culture>\<assemblyname>.manifest // 3. \\<appdir>\<language-culture>\<assemblyname>\<assemblyname>.DLL // 4. \\<appdir>\<language-culture>\<assemblyname>\<assemblyname>.manifest // TODO : also take into account Multilanguage User Interface (MUI) when // scanning manifests and WinSxs dll. God this is horrendously complicated. // Could not find the dependency { SxsEntries EntriesFromElement = new SxsEntries(); EntriesFromElement.Add(new SxsEntry(SxsManifestName, "file ???")); return(EntriesFromElement); } }
public static Tuple <ModuleSearchStrategy, PE> ResolveModule(PE RootPe, string ModuleName, SxsEntries SxsCache) { Tuple <ModuleSearchStrategy, string> ResolvedFilepath; // if no extension is used, assume a .dll if (Path.GetExtension(ModuleName) == String.Empty) { ModuleName = String.Format("{0:s}.dll", ModuleName); } string ApiSetName = LookupApiSetLibrary(ModuleName); if (ApiSetName != null) { ModuleName = ApiSetName; } ResolvedFilepath = FindPe.FindPeFromDefault(RootPe, ModuleName, SxsCache); // ApiSet override the underneath search location if found ModuleSearchStrategy ModuleLocation = ResolvedFilepath.Item1; if ((ApiSetName != null) && (ResolvedFilepath.Item2 != null)) { ModuleLocation = ModuleSearchStrategy.ApiSetSchema; } // PE ResolvedModule = null; if (ResolvedFilepath.Item2 != null) { ResolvedModule = LoadPe(ResolvedFilepath.Item2); } return(new Tuple <ModuleSearchStrategy, PE>(ModuleLocation, ResolvedModule)); }
// default search order : // https://msdn.microsoft.com/en-us/library/windows/desktop/ms682586(v=vs.85).aspx // // if (SafeDllSearchMode) { // -1. Sxs manifests // 0. KnownDlls list // 1. Loaded PE folder // 2. C:\Windows\(System32 | SysWow64 ) // 3. 16-bit system directory <-- ignored // 4. C:\Windows // 5. %pwd% // 6. AppDatas // } public static Tuple <ModuleSearchStrategy, string> FindPeFromDefault(PE RootPe, string ModuleName, SxsEntries SxsCache, List <string> CustomSearchFolders, string WorkingDirectory) { bool Wow64Dll = RootPe.IsWow64Dll(); string RootPeFolder = Path.GetDirectoryName(RootPe.Filepath); string FoundPePath = null; Environment.SpecialFolder WindowsSystemFolder = (Wow64Dll) ? Environment.SpecialFolder.SystemX86 : Environment.SpecialFolder.System; String WindowsSystemFolderPath = Environment.GetFolderPath(WindowsSystemFolder); // -1. Look in Sxs manifest (copious reversing needed) // TODO : find dll search order if (SxsCache.Count != 0) { SxsEntry Entry = SxsCache.Find(SxsItem => string.Equals(SxsItem.Name, ModuleName, StringComparison.OrdinalIgnoreCase) ); if (Entry != null) { return(new Tuple <ModuleSearchStrategy, string>(ModuleSearchStrategy.SxS, Entry.Path)); } } // 0. Look in well-known dlls list // HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\KnownDLLs // https://blogs.msdn.microsoft.com/larryosterman/2004/07/19/what-are-known-dlls-anyway/ String KnownDll = Phlib.GetKnownDlls(Wow64Dll).Find(x => string.Equals(x, ModuleName, StringComparison.OrdinalIgnoreCase)); if (KnownDll != null) { return(new Tuple <ModuleSearchStrategy, string>( ModuleSearchStrategy.WellKnownDlls, Path.Combine(WindowsSystemFolderPath, KnownDll) )); } // 1. Look in application folder FoundPePath = FindPeFromPath(ModuleName, new List <string>(new string[] { RootPeFolder }), Wow64Dll); if (FoundPePath != null) { return(new Tuple <ModuleSearchStrategy, string>( ModuleSearchStrategy.ApplicationDirectory, FoundPePath )); } // {2-3-4}. Look in system folders List <String> SystemFolders = new List <string>(new string[] { WindowsSystemFolderPath, Environment.GetFolderPath(Environment.SpecialFolder.Windows) } ); FoundPePath = FindPeFromPath(ModuleName, SystemFolders, Wow64Dll); if (FoundPePath != null) { return(new Tuple <ModuleSearchStrategy, string>( ModuleSearchStrategy.WindowsFolder, FoundPePath )); } // 5. Look in current directory // Ignored for the time being since we can't know from // where the exe is run // TODO : Add a user supplied path emulating %cwd% FoundPePath = FindPeFromPath(ModuleName, new List <string>(new string[] { WorkingDirectory }), Wow64Dll); if (FoundPePath != null) { return(new Tuple <ModuleSearchStrategy, string>( ModuleSearchStrategy.WorkingDirectory, FoundPePath )); } // 6. Look in local app data (check for python for exemple) // 7. Find in PATH string PATH = Environment.GetEnvironmentVariable("PATH"); List <String> PATHFolders = new List <string>(PATH.Split(';')); // Filter out empty paths, since it resolve to the current working directory // fix https://github.com/lucasg/Dependencies/issues/51 PATHFolders = PATHFolders.Where(path => path.Length != 0).ToList(); FoundPePath = FindPeFromPath(ModuleName, PATHFolders, Wow64Dll); if (FoundPePath != null) { return(new Tuple <ModuleSearchStrategy, string>( ModuleSearchStrategy.Environment, FoundPePath )); } // 8. Check if it's an absolute import if ((Path.GetFullPath(ModuleName) == ModuleName) && File.Exists(ModuleName)) { return(new Tuple <ModuleSearchStrategy, string>( ModuleSearchStrategy.Fullpath, ModuleName )); } // 0xff. Allow the user to supply custom search folders, to take into account // specific cases. FoundPePath = FindPeFromPath(ModuleName, CustomSearchFolders, Wow64Dll); if (FoundPePath != null) { return(new Tuple <ModuleSearchStrategy, string>( ModuleSearchStrategy.UserDefined, FoundPePath )); } return(new Tuple <ModuleSearchStrategy, string>( ModuleSearchStrategy.NOT_FOUND, null )); }
public static Tuple <ModuleSearchStrategy, PE> ResolveModule(PE RootPe, string ModuleName, SxsEntries SxsCache) { Tuple <ModuleSearchStrategy, string> ResolvedFilepath; string ApiSetName = LookupApiSetLibrary(ModuleName); if (ApiSetName != null) { ModuleName = ApiSetName; } ResolvedFilepath = FindPe.FindPeFromDefault(RootPe, ModuleName, SxsCache); // ApiSet override the underneath search location if found ModuleSearchStrategy ModuleLocation = ResolvedFilepath.Item1; if ((ApiSetName != null) && (ResolvedFilepath.Item2 != null)) { ModuleLocation = ModuleSearchStrategy.ApiSetSchema; } // PE ResolvedModule = null; if (ResolvedFilepath.Item2 != null) { ResolvedModule = LoadPe(ResolvedFilepath.Item2); } return(new Tuple <ModuleSearchStrategy, PE>(ModuleLocation, ResolvedModule)); }