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); }
private void DoFindModuleInList_Executed(object sender, ExecutedRoutedEventArgs e) { ModuleTreeViewItem Source = e.Source as ModuleTreeViewItem; String SelectedModuleName = Source.GetTreeNodeHeaderName(Dependencies.Properties.Settings.Default.FullPath); foreach (DisplayModuleInfo item in this.ModulesList.Items) { if (item.ModuleName == SelectedModuleName) { this.ModulesList.SelectedItem = item; this.ModulesList.ScrollIntoView(item); return; } } }
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); }
/// <summary> /// Reentrant version of Collapse/Expand Node /// </summary> /// <param name="Item"></param> /// <param name="ExpandNode"></param> private ModuleTreeViewItem FindModuleInTree(ModuleTreeViewItem Item, DisplayModuleInfo Module, bool Highlight = false) { if (Item.GetTreeNodeHeaderName(Dependencies.Properties.Settings.Default.FullPath) == Module.ModuleName) { if (Highlight) { ExpandAllParentNode(Item.Parent as ModuleTreeViewItem); Item.IsSelected = true; Item.BringIntoView(); Item.Focus(); } return(Item); } // BFS style search -> return the first matching node with the lowest "depth" foreach (ModuleTreeViewItem ChildItem in Item.Items) { if (ChildItem.GetTreeNodeHeaderName(Dependencies.Properties.Settings.Default.FullPath) == Module.ModuleName) { if (Highlight) { ExpandAllParentNode(Item); ChildItem.IsSelected = true; ChildItem.BringIntoView(); ChildItem.Focus(); } return(Item); } } foreach (ModuleTreeViewItem ChildItem in Item.Items) { ModuleTreeViewItem matchingItem = FindModuleInTree(ChildItem, Module, Highlight); // early exit as soon as we find a matching node if (matchingItem != null) { return(matchingItem); } } return(null); }
private void ConstructDependencyTree(ModuleTreeViewItem RootNode, PE CurrentPE, int RecursionLevel = 0) { // "Closured" variables (it 's a scope hack really). Dictionary <string, ImportContext> NewTreeContexts = new Dictionary <string, ImportContext>(); BackgroundWorker bw = new BackgroundWorker(); bw.WorkerReportsProgress = true; // useless here for now bw.DoWork += (sender, e) => { ProcessPe(NewTreeContexts, CurrentPE); }; bw.RunWorkerCompleted += (sender, e) => { TreeBuildingBehaviour.DependencyTreeBehaviour SettingTreeBehaviour = Dependencies.TreeBuildingBehaviour.GetGlobalBehaviour(); List <ModuleTreeViewItem> PeWithDummyEntries = new List <ModuleTreeViewItem>(); List <BacklogImport> PEProcessingBacklog = new List <BacklogImport>(); // Important ! // // This handler is executed in the STA (Single Thread Application) // which is authorized to manipulate UI elements. The BackgroundWorker is not. // foreach (ImportContext NewTreeContext in NewTreeContexts.Values) { ModuleTreeViewItem childTreeNode = new ModuleTreeViewItem(); DependencyNodeContext childTreeNodeContext = new DependencyNodeContext(); childTreeNodeContext.IsDummy = false; string ModuleName = NewTreeContext.ModuleName; string ModuleFilePath = NewTreeContext.PeFilePath; ModuleCacheKey ModuleKey = new ModuleCacheKey(ModuleName, ModuleFilePath); // Newly seen modules if (!this.ProcessedModulesCache.ContainsKey(ModuleKey)) { // Missing module "found" if ((NewTreeContext.PeFilePath == null) || !NativeFile.Exists(NewTreeContext.PeFilePath)) { this.ProcessedModulesCache[ModuleKey] = new NotFoundModuleInfo(ModuleName); } else { if (NewTreeContext.IsApiSet) { var ApiSetContractModule = new DisplayModuleInfo(NewTreeContext.ApiSetModuleName, NewTreeContext.PeProperties, NewTreeContext.ModuleLocation, NewTreeContext.Flags); var NewModule = new ApiSetModuleInfo(NewTreeContext.ModuleName, ref ApiSetContractModule); this.ProcessedModulesCache[ModuleKey] = NewModule; if (SettingTreeBehaviour == TreeBuildingBehaviour.DependencyTreeBehaviour.Recursive) { PEProcessingBacklog.Add(new BacklogImport(childTreeNode, ApiSetContractModule.ModuleName)); } } else { var NewModule = new DisplayModuleInfo(NewTreeContext.ModuleName, NewTreeContext.PeProperties, NewTreeContext.ModuleLocation, NewTreeContext.Flags); this.ProcessedModulesCache[ModuleKey] = NewModule; switch (SettingTreeBehaviour) { case TreeBuildingBehaviour.DependencyTreeBehaviour.RecursiveOnlyOnDirectImports: if ((NewTreeContext.Flags & ModuleFlag.DelayLoad) == 0) { PEProcessingBacklog.Add(new BacklogImport(childTreeNode, NewModule.ModuleName)); } break; case TreeBuildingBehaviour.DependencyTreeBehaviour.Recursive: PEProcessingBacklog.Add(new BacklogImport(childTreeNode, NewModule.ModuleName)); break; } } } // add it to the module list this.ModulesList.AddModule(this.ProcessedModulesCache[ModuleKey]); } // Since we uniquely process PE, for thoses who have already been "seen", // we set a dummy entry in order to set the "[+]" icon next to the node. // The dll dependencies are actually resolved on user double-click action // We can't do the resolution in the same time as the tree construction since // it's asynchronous (we would have to wait for all the background to finish and // use another Async worker to resolve). if ((NewTreeContext.PeProperties != null) && (NewTreeContext.PeProperties.GetImports().Count > 0)) { ModuleTreeViewItem DummyEntry = new ModuleTreeViewItem(); DependencyNodeContext DummyContext = new DependencyNodeContext() { ModuleInfo = new WeakReference(new NotFoundModuleInfo("Dummy")), IsDummy = true }; DummyEntry.DataContext = DummyContext; DummyEntry.Header = "@Dummy : if you see this header, it's a bug."; DummyEntry.IsExpanded = false; childTreeNode.Items.Add(DummyEntry); childTreeNode.Expanded += ResolveDummyEntries; } // Add to tree view childTreeNodeContext.ModuleInfo = new WeakReference(this.ProcessedModulesCache[ModuleKey]); childTreeNode.DataContext = childTreeNodeContext; childTreeNode.Header = childTreeNode.GetTreeNodeHeaderName(Dependencies.Properties.Settings.Default.FullPath); RootNode.Items.Add(childTreeNode); } // Process next batch of dll imports if (SettingTreeBehaviour != TreeBuildingBehaviour.DependencyTreeBehaviour.ChildOnly) { foreach (var ImportNode in PEProcessingBacklog) { ConstructDependencyTree(ImportNode.Item1, ImportNode.Item2, RecursionLevel + 1); // warning : recursive call } } }; bw.RunWorkerAsync(); }