/// <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 OnTreeViewSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs <object> e) { if (this.DllTreeView.SelectedItem == null) { UpdateImportExportLists(null, null); return; } DependencyNodeContext childTreeContext = ((DependencyNodeContext)(this.DllTreeView.SelectedItem as ModuleTreeViewItem).DataContext); DisplayModuleInfo SelectedModule = childTreeContext.ModuleInfo.Target as DisplayModuleInfo; if (SelectedModule == null) { return; } // Selected Pe has not been found on disk : unvalidate current module SelectedModule.HasErrors = !NativeFile.Exists(SelectedModule.Filepath); if (SelectedModule.HasErrors) { // TODO : do a proper refresh instead of asking the user to do it System.Windows.MessageBox.Show(String.Format("We could not find {0:s} file on the disk anymore, please fix this problem and refresh the window via F5", SelectedModule.Filepath)); UpdateImportExportLists(null, null); return; } // Root Item : no parent ModuleTreeViewItem TreeRootItem = this.DllTreeView.Items[0] as ModuleTreeViewItem; ModuleTreeViewItem SelectedItem = this.DllTreeView.SelectedItem as ModuleTreeViewItem; if (SelectedItem == TreeRootItem) { SelectedModule.HasErrors = false; UpdateImportExportLists(SelectedModule, null); return; } // Tree Item DisplayModuleInfo parentModule = SelectedItem.ParentModule.ModuleInfo; UpdateImportExportLists(SelectedModule, parentModule); }
private void VerifyModuleImports() { // no parent : it's probably the root item ModuleTreeViewItem ParentModule = this.ParentModule; if (ParentModule == null) { ModuleInfo.HasErrors = false; return; } foreach (PeImportDll DllImport in ParentModule.ModuleInfo.Imports) { if (DllImport.Name != ModuleInfo._Name) { continue; } List <Tuple <PeImport, bool> > resolvedImports = BinaryCache.LookupImports(DllImport, ModuleInfo.Filepath); if (resolvedImports.Count == 0) { ModuleInfo.HasErrors = true; return; } foreach (var Import in resolvedImports) { if (!Import.Item2) { ModuleInfo.HasErrors = true; return; } } } ModuleInfo.HasErrors = false; }
private void OnTreeViewSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs <object> e) { if (this.DllTreeView.SelectedItem == null) { UpdateImportExportLists(null, null); return; } DependencyNodeContext childTreeContext = ((DependencyNodeContext)(this.DllTreeView.SelectedItem as ModuleTreeViewItem).DataContext); DisplayModuleInfo SelectedModule = childTreeContext.ModuleInfo.Target as DisplayModuleInfo; // Selected Pe has not been found on disk if (SelectedModule == null) { return; } // Root Item : no parent ModuleTreeViewItem TreeRootItem = this.DllTreeView.Items[0] as ModuleTreeViewItem; ModuleTreeViewItem SelectedItem = this.DllTreeView.SelectedItem as ModuleTreeViewItem; if (SelectedItem == TreeRootItem) { UpdateImportExportLists(SelectedModule, null); return; } // find parent. TODO : add parent ref to treeview context var parent = VisualTreeHelper.GetParent(SelectedItem as DependencyObject); while ((parent as TreeViewItem) == null) { parent = VisualTreeHelper.GetParent(parent); } DependencyNodeContext parentTreeContext = ((DependencyNodeContext)(parent as ModuleTreeViewItem).DataContext); DisplayModuleInfo parentModule = parentTreeContext.ModuleInfo.Target as DisplayModuleInfo; UpdateImportExportLists(SelectedModule, parentModule); }
/// <summary> /// Resolve imports when the user expand the node. /// </summary> private void ResolveDummyEntries(object sender, RoutedEventArgs e) { ModuleTreeViewItem NeedDummyPeNode = e.OriginalSource as ModuleTreeViewItem; if (NeedDummyPeNode.Items.Count == 0) { return; } ModuleTreeViewItem MaybeDummyNode = (ModuleTreeViewItem)NeedDummyPeNode.Items[0]; DependencyNodeContext Context = (DependencyNodeContext)MaybeDummyNode.DataContext; //TODO: Improve resolution predicate if (!Context.IsDummy) { return; } NeedDummyPeNode.Items.Clear(); string Filepath = NeedDummyPeNode.ModuleFilePath; ConstructDependencyTree(NeedDummyPeNode, Filepath); }
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(); }
public ModuleTreeViewItem(ModuleTreeViewItem Other) { Dependencies.Properties.Settings.Default.PropertyChanged += this.ModuleTreeViewItem_PropertyChanged; this.DataContext = new DependencyNodeContext((DependencyNodeContext)Other.DataContext); }
public ModuleTreeViewItem(ModuleTreeViewItem Parent) { _importsVerified = false; _Parent = Parent; Dependencies.Properties.Settings.Default.PropertyChanged += this.ModuleTreeViewItem_PropertyChanged; }
private void ConstructDependencyTree(ModuleTreeViewItem RootNode, string FilePath, int RecursionLevel = 0) { ConstructDependencyTree(RootNode, BinaryCache.LoadPe(FilePath), RecursionLevel); }
private void ConstructDependencyTree(ModuleTreeViewItem RootNode, string FilePath, int RecursionLevel = 0) { ConstructDependencyTree(RootNode, new PE(FilePath), RecursionLevel); }