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 OnTreeViewSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs <object> e) { 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; } UpdateImportExportLists(SelectedModule); }
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)); } // Root Item : no parent ModuleTreeViewItem TreeRootItem = this.DllTreeView.Items[0] as ModuleTreeViewItem; ModuleTreeViewItem SelectedItem = this.DllTreeView.SelectedItem as ModuleTreeViewItem; if (SelectedItem == TreeRootItem) { // Selected Pe has not been found on disk : unvalidate current module if (SelectedModule.HasErrors) { UpdateImportExportLists(null, null); } else { SelectedModule.HasErrors = false; UpdateImportExportLists(SelectedModule, null); } return; } // Tree Item DisplayModuleInfo parentModule = SelectedItem.ParentModule.ModuleInfo; UpdateImportExportLists(SelectedModule, parentModule); }
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); }
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 DependencyNodeContext(DependencyNodeContext other) { ModuleInfo = other.ModuleInfo; IsDummy = other.IsDummy; }