1
0
Fork 0
x64dbg/src/gui/Src/Gui/MainWindow.cpp

1577 lines
54 KiB
C++

#include "MainWindow.h"
#include "ui_MainWindow.h"
#include <QMessageBox>
#include <QIcon>
#include <QUrl>
#include <QFileDialog>
#include <QMimeData>
#include <QDesktopServices>
#include "Configuration.h"
#include "SettingsDialog.h"
#include "AppearanceDialog.h"
#include "ShortcutsDialog.h"
#include "AttachDialog.h"
#include "LineEditDialog.h"
#include "StringUtil.h"
#include "MiscUtil.h"
#include "FavouriteTools.h"
QString MainWindow::windowTitle = "";
MainWindow::MainWindow(QWidget* parent)
: QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
// Build information
QAction* buildInfo = new QAction(ToDateString(GetCompileDate()), this);
buildInfo->setEnabled(false);
ui->menuBar->addAction(buildInfo);
// Setup bridge signals
connect(Bridge::getBridge(), SIGNAL(updateWindowTitle(QString)), this, SLOT(updateWindowTitleSlot(QString)));
connect(Bridge::getBridge(), SIGNAL(addRecentFile(QString)), this, SLOT(addRecentFile(QString)));
connect(Bridge::getBridge(), SIGNAL(setLastException(uint)), this, SLOT(setLastException(uint)));
connect(Bridge::getBridge(), SIGNAL(menuAddMenuToList(QWidget*, QMenu*, int, int)), this, SLOT(addMenuToList(QWidget*, QMenu*, int, int)));
connect(Bridge::getBridge(), SIGNAL(menuAddMenu(int, QString)), this, SLOT(addMenu(int, QString)));
connect(Bridge::getBridge(), SIGNAL(menuAddMenuEntry(int, QString)), this, SLOT(addMenuEntry(int, QString)));
connect(Bridge::getBridge(), SIGNAL(menuAddSeparator(int)), this, SLOT(addSeparator(int)));
connect(Bridge::getBridge(), SIGNAL(menuClearMenu(int)), this, SLOT(clearMenu(int)));
connect(Bridge::getBridge(), SIGNAL(menuRemoveMenuEntry(int)), this, SLOT(removeMenuEntry(int)));
connect(Bridge::getBridge(), SIGNAL(getStrWindow(QString, QString*)), this, SLOT(getStrWindow(QString, QString*)));
connect(Bridge::getBridge(), SIGNAL(setIconMenu(int, QIcon)), this, SLOT(setIconMenu(int, QIcon)));
connect(Bridge::getBridge(), SIGNAL(setIconMenuEntry(int, QIcon)), this, SLOT(setIconMenuEntry(int, QIcon)));
connect(Bridge::getBridge(), SIGNAL(showCpu()), this, SLOT(displayCpuWidget()));
connect(Bridge::getBridge(), SIGNAL(addQWidgetTab(QWidget*)), this, SLOT(addQWidgetTab(QWidget*)));
connect(Bridge::getBridge(), SIGNAL(showQWidgetTab(QWidget*)), this, SLOT(showQWidgetTab(QWidget*)));
connect(Bridge::getBridge(), SIGNAL(closeQWidgetTab(QWidget*)), this, SLOT(closeQWidgetTab(QWidget*)));
connect(Bridge::getBridge(), SIGNAL(executeOnGuiThread(void*)), this, SLOT(executeOnGuiThread(void*)));
connect(Bridge::getBridge(), SIGNAL(dbgStateChanged(DBGSTATE)), this, SLOT(dbgStateChangedSlot(DBGSTATE)));
// Setup menu API
initMenuApi();
addMenuToList(this, ui->menuPlugins, GUI_PLUGIN_MENU);
this->showMaximized();
mWindowMainTitle = QCoreApplication::applicationName();
// Set window title
setWindowTitle(QString(mWindowMainTitle));
// Load application icon
SetApplicationIcon(MainWindow::winId());
// Load recent files
loadMRUList(16);
// Accept drops
setAcceptDrops(true);
// Log view
mLogView = new LogView();
mLogView->setWindowTitle(tr("Log"));
mLogView->setWindowIcon(DIcon("log.png"));
mLogView->hide();
// Symbol view
mSymbolView = new SymbolView();
mSymbolView->setWindowTitle(tr("Symbols"));
mSymbolView->setWindowIcon(DIcon("pdb.png"));
mSymbolView->hide();
// Source view
mSourceViewManager = new SourceViewerManager();
mSourceViewManager->setWindowTitle(tr("Source"));
mSourceViewManager->setWindowIcon(DIcon("source.png"));
mSourceViewManager->hide();
connect(mSourceViewManager, SIGNAL(showCpu()), this, SLOT(displayCpuWidget()));
// Breakpoints
mBreakpointsView = new BreakpointsView();
mBreakpointsView->setWindowTitle(tr("Breakpoints"));
mBreakpointsView->setWindowIcon(DIcon("breakpoint.png"));
mBreakpointsView->hide();
connect(mBreakpointsView, SIGNAL(showCpu()), this, SLOT(displayCpuWidget()));
// Memory map view
mMemMapView = new MemoryMapView();
connect(mMemMapView, SIGNAL(showCpu()), this, SLOT(displayCpuWidget()));
connect(mMemMapView, SIGNAL(showReferences()), this, SLOT(displayReferencesWidget()));
mMemMapView->setWindowTitle(tr("Memory Map"));
mMemMapView->setWindowIcon(DIcon("memory-map.png"));
mMemMapView->hide();
// Callstack view
mCallStackView = new CallStackView();
mCallStackView->setWindowTitle(tr("Call Stack"));
mCallStackView->setWindowIcon(DIcon("callstack.png"));
connect(mCallStackView, SIGNAL(showCpu()), this, SLOT(displayCpuWidget()));
// SEH Chain view
mSEHChainView = new SEHChainView();
mSEHChainView->setWindowTitle(tr("SEH"));
mSEHChainView->setWindowIcon(DIcon("seh-chain.png"));
connect(mSEHChainView, SIGNAL(showCpu()), this, SLOT(displayCpuWidget()));
// Script view
mScriptView = new ScriptView();
mScriptView->setWindowTitle(tr("Script"));
mScriptView->setWindowIcon(DIcon("script-code.png"));
mScriptView->hide();
// CPU view
mCpuWidget = new CPUWidget();
mCpuWidget->setWindowTitle(tr("CPU"));
#ifdef _WIN64
mCpuWidget->setWindowIcon(DIcon("processor64.png"));
#else
mCpuWidget->setWindowIcon(DIcon("processor32.png"));
ui->actionCpu->setIcon(DIcon("processor32.png"));
#endif //_WIN64
// Reference manager
mReferenceManager = new ReferenceManager(this);
Bridge::getBridge()->referenceManager = mReferenceManager;
mReferenceManager->setWindowTitle(tr("References"));
mReferenceManager->setWindowIcon(DIcon("search.png"));
// Thread view
mThreadView = new ThreadView();
connect(mThreadView, SIGNAL(showCpu()), this, SLOT(displayCpuWidget()));
mThreadView->setWindowTitle(tr("Threads"));
mThreadView->setWindowIcon(DIcon("arrow-threads.png"));
// Snowman view (decompiler)
mSnowmanView = CreateSnowman(this);
if(!mSnowmanView)
mSnowmanView = (SnowmanView*)new QLabel("<center>Snowman is disabled...</center>", this);
mSnowmanView->setWindowTitle(tr("Snowman"));
mSnowmanView->setWindowIcon(DIcon("snowman.png"));
// Notes manager
mNotesManager = new NotesManager(this);
mNotesManager->setWindowTitle(tr("Notes"));
mNotesManager->setWindowIcon(DIcon("notes.png"));
// Handles view
mHandlesView = new HandlesView(this);
mHandlesView->setWindowTitle(tr("Handles"));
mHandlesView->setWindowIcon(DIcon("handles.png"));
// Graph view
mGraphView = new DisassemblerGraphView(this);
mGraphView->setWindowTitle(tr("Graph"));
mGraphView->setWindowIcon(DIcon("graph.png"));
// Create the tab widget
mTabWidget = new MHTabWidget();
// Add all widgets to the list
mWidgetList.push_back(mCpuWidget);
mWidgetNativeNameList.push_back("CPUTab");
mWidgetList.push_back(mGraphView);
mWidgetNativeNameList.push_back("GraphTab");
mWidgetList.push_back(mLogView);
mWidgetNativeNameList.push_back("LogTab");
mWidgetList.push_back(mNotesManager);
mWidgetNativeNameList.push_back("NotesTab");
mWidgetList.push_back(mBreakpointsView);
mWidgetNativeNameList.push_back("BreakpointsTab");
mWidgetList.push_back(mMemMapView);
mWidgetNativeNameList.push_back("MemoryMapTab");
mWidgetList.push_back(mCallStackView);
mWidgetNativeNameList.push_back("CallStackTab");
mWidgetList.push_back(mSEHChainView);
mWidgetNativeNameList.push_back("SEHTab");
mWidgetList.push_back(mScriptView);
mWidgetNativeNameList.push_back("ScriptTab");
mWidgetList.push_back(mSymbolView);
mWidgetNativeNameList.push_back("SymbolsTab");
mWidgetList.push_back(mSourceViewManager);
mWidgetNativeNameList.push_back("SourceTab");
mWidgetList.push_back(mReferenceManager);
mWidgetNativeNameList.push_back("ReferencesTab");
mWidgetList.push_back(mThreadView);
mWidgetNativeNameList.push_back("ThreadsTab");
mWidgetList.push_back(mSnowmanView);
mWidgetNativeNameList.push_back("SnowmanTab");
mWidgetList.push_back(mHandlesView);
mWidgetNativeNameList.push_back("HandlesTab");
// If LoadSaveTabOrder disabled, load tabs in default order
if(!ConfigBool("Miscellaneous", "LoadSaveTabOrder"))
loadTabDefaultOrder();
else
loadTabSavedOrder();
setCentralWidget(mTabWidget);
// Setup the command and status bars
setupCommandBar();
setupStatusBar();
// Patch dialog
mPatchDialog = new PatchDialog(this);
mCalculatorDialog = new CalculatorDialog(this);
connect(mCalculatorDialog, SIGNAL(showCpu()), this, SLOT(displayCpuWidget()));
// Setup signals/slots
connect(mCmdLineEdit, SIGNAL(returnPressed()), this, SLOT(executeCommand()));
connect(ui->actionStepOver, SIGNAL(triggered()), this, SLOT(execStepOver()));
connect(ui->actionStepInto, SIGNAL(triggered()), this, SLOT(execStepInto()));
connect(ui->actionCommand, SIGNAL(triggered()), this, SLOT(setFocusToCommandBar()));
connect(ui->actionClose, SIGNAL(triggered()), this, SLOT(execClose()));
connect(ui->actionMemoryMap, SIGNAL(triggered()), this, SLOT(displayMemMapWidget()));
connect(ui->actionRun, SIGNAL(triggered()), this, SLOT(execRun()));
connect(ui->actionRtr, SIGNAL(triggered()), this, SLOT(execRtr()));
connect(ui->actionLog, SIGNAL(triggered()), this, SLOT(displayLogWidget()));
connect(ui->actionAbout, SIGNAL(triggered()), this, SLOT(displayAboutWidget()));
connect(ui->actionOpen, SIGNAL(triggered()), this, SLOT(openFile()));
connect(ui->actionPause, SIGNAL(triggered()), this, SLOT(execPause()));
connect(ui->actionScylla, SIGNAL(triggered()), this, SLOT(startScylla()));
connect(ui->actionRestart, SIGNAL(triggered()), this, SLOT(restartDebugging()));
connect(ui->actionBreakpoints, SIGNAL(triggered()), this, SLOT(displayBreakpointWidget()));
connect(ui->actioneStepOver, SIGNAL(triggered()), this, SLOT(execeStepOver()));
connect(ui->actioneStepInto, SIGNAL(triggered()), this, SLOT(execeStepInto()));
connect(ui->actioneRun, SIGNAL(triggered()), this, SLOT(execeRun()));
connect(ui->actioneRtr, SIGNAL(triggered()), this, SLOT(execeRtr()));
connect(ui->actionRtu, SIGNAL(triggered()), this, SLOT(execRtu()));
connect(ui->actionTicnd, SIGNAL(triggered()), this, SLOT(execTicnd()));
connect(ui->actionTocnd, SIGNAL(triggered()), this, SLOT(execTocnd()));
connect(ui->actionTRBit, SIGNAL(triggered()), this, SLOT(execTRBit()));
connect(ui->actionTRByte, SIGNAL(triggered()), this, SLOT(execTRByte()));
connect(ui->actionTRWord, SIGNAL(triggered()), this, SLOT(execTRWord()));
connect(ui->actionTRNone, SIGNAL(triggered()), this, SLOT(execTRNone()));
connect(ui->actionTRTIBT, SIGNAL(triggered()), this, SLOT(execTRTIBT()));
connect(ui->actionTRTOBT, SIGNAL(triggered()), this, SLOT(execTRTOBT()));
connect(ui->actionTRTIIT, SIGNAL(triggered()), this, SLOT(execTRTIIT()));
connect(ui->actionTRTOIT, SIGNAL(triggered()), this, SLOT(execTRTOIT()));
connect(ui->actionInstrUndo, SIGNAL(triggered()), this, SLOT(execInstrUndo()));
connect(ui->actionSkipNextInstruction, SIGNAL(triggered()), this, SLOT(execSkip()));
connect(ui->actionScript, SIGNAL(triggered()), this, SLOT(displayScriptWidget()));
connect(ui->actionRunSelection, SIGNAL(triggered()), this, SLOT(runSelection()));
connect(ui->actionRunExpression, SIGNAL(triggered(bool)), this, SLOT(runExpression()));
connect(ui->actionHideDebugger, SIGNAL(triggered()), this, SLOT(hideDebugger()));
connect(ui->actionCpu, SIGNAL(triggered()), this, SLOT(displayCpuWidget()));
connect(ui->actionSymbolInfo, SIGNAL(triggered()), this, SLOT(displaySymbolWidget()));
connect(ui->actionSource, SIGNAL(triggered()), this, SLOT(displaySourceViewWidget()));
connect(mSymbolView, SIGNAL(showCpu()), this, SLOT(displayCpuWidget()));
connect(mSymbolView, SIGNAL(showReferences()), this, SLOT(displayReferencesWidget()));
connect(mReferenceManager, SIGNAL(showCpu()), this, SLOT(displayCpuWidget()));
connect(mGraphView, SIGNAL(showCpu()), this, SLOT(displayCpuWidget()));
connect(ui->actionReferences, SIGNAL(triggered()), this, SLOT(displayReferencesWidget()));
connect(ui->actionThreads, SIGNAL(triggered()), this, SLOT(displayThreadsWidget()));
connect(ui->actionSettings, SIGNAL(triggered()), this, SLOT(openSettings()));
connect(ui->actionStrings, SIGNAL(triggered()), this, SLOT(findStrings()));
connect(ui->actionCalls, SIGNAL(triggered()), this, SLOT(findModularCalls()));
connect(ui->actionAppearance, SIGNAL(triggered()), this, SLOT(openAppearance()));
connect(ui->actionShortcuts, SIGNAL(triggered()), this, SLOT(openShortcuts()));
connect(ui->actionTopmost, SIGNAL(toggled(bool)), this, SLOT(changeTopmost(bool)));
connect(ui->actionCalculator, SIGNAL(triggered()), this, SLOT(openCalculator()));
connect(ui->actionPatches, SIGNAL(triggered()), this, SLOT(patchWindow()));
connect(ui->actionComments, SIGNAL(triggered()), this, SLOT(displayComments()));
connect(ui->actionLabels, SIGNAL(triggered()), this, SLOT(displayLabels()));
connect(ui->actionBookmarks, SIGNAL(triggered()), this, SLOT(displayBookmarks()));
connect(ui->actionFunctions, SIGNAL(triggered()), this, SLOT(displayFunctions()));
connect(ui->actionCheckUpdates, SIGNAL(triggered()), this, SLOT(checkUpdates()));
connect(ui->actionCallStack, SIGNAL(triggered()), this, SLOT(displayCallstack()));
connect(ui->actionSEHChain, SIGNAL(triggered()), this, SLOT(displaySEHChain()));
connect(ui->actionDonate, SIGNAL(triggered()), this, SLOT(donate()));
connect(ui->actionReportBug, SIGNAL(triggered()), this, SLOT(reportBug()));
connect(ui->actionCrashDump, SIGNAL(triggered()), this, SLOT(crashDump()));
connect(ui->actionAttach, SIGNAL(triggered()), this, SLOT(displayAttach()));
connect(ui->actionDetach, SIGNAL(triggered()), this, SLOT(detach()));
connect(ui->actionChangeCommandLine, SIGNAL(triggered()), this, SLOT(changeCommandLine()));
connect(ui->actionManual, SIGNAL(triggered()), this, SLOT(displayManual()));
connect(ui->actionNotes, SIGNAL(triggered()), this, SLOT(displayNotesWidget()));
connect(ui->actionSnowman, SIGNAL(triggered()), this, SLOT(displaySnowmanWidget()));
connect(ui->actionHandles, SIGNAL(triggered()), this, SLOT(displayHandlesWidget()));
connect(ui->actionGraph, SIGNAL(triggered()), this, SLOT(displayGraphWidget()));
connect(mCpuWidget->getDisasmWidget(), SIGNAL(updateWindowTitle(QString)), this, SLOT(updateWindowTitleSlot(QString)));
connect(mCpuWidget->getDisasmWidget(), SIGNAL(displayReferencesWidget()), this, SLOT(displayReferencesWidget()));
connect(mCpuWidget->getDisasmWidget(), SIGNAL(displaySourceManagerWidget()), this, SLOT(displaySourceViewWidget()));
connect(mCpuWidget->getDisasmWidget(), SIGNAL(displaySnowmanWidget()), this, SLOT(displaySnowmanWidget()));
connect(mCpuWidget->getDisasmWidget(), SIGNAL(displayLogWidget()), this, SLOT(displayLogWidget()));
connect(mCpuWidget->getDisasmWidget(), SIGNAL(displayGraphWidget()), this, SLOT(displayGraphWidget()));
connect(mCpuWidget->getDisasmWidget(), SIGNAL(showPatches()), this, SLOT(patchWindow()));
connect(mCpuWidget->getDisasmWidget(), SIGNAL(decompileAt(dsint, dsint)), this, SLOT(decompileAt(dsint, dsint)));
connect(mCpuWidget->getDumpWidget(), SIGNAL(displayReferencesWidget()), this, SLOT(displayReferencesWidget()));
connect(mCpuWidget->getStackWidget(), SIGNAL(displayReferencesWidget()), this, SLOT(displayReferencesWidget()));
connect(mTabWidget, SIGNAL(tabMovedTabWidget(int, int)), this, SLOT(tabMovedSlot(int, int)));
connect(Config(), SIGNAL(shortcutsUpdated()), this, SLOT(refreshShortcuts()));
// Setup favourite tools menu
updateFavouriteTools();
// Set default setttings (when not set)
SettingsDialog defaultSettings;
lastException = 0;
defaultSettings.SaveSettings();
// Don't need to set shortcuts because the code above will signal refreshShortcuts()
// Create updatechecker
mUpdateChecker = new UpdateChecker(this);
// Setup close thread and dialog
bCanClose = false;
mCloseThread = new MainWindowCloseThread(this);
connect(mCloseThread, SIGNAL(canClose()), this, SLOT(canClose()));
mCloseDialog = new CloseDialog(this);
mCpuWidget->setDisasmFocus();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::setupCommandBar()
{
mCmdLineEdit = new CommandLineEdit(ui->cmdBar);
ui->cmdBar->addWidget(new QLabel(tr("Command: ")));
ui->cmdBar->addWidget(mCmdLineEdit);
ui->cmdBar->addWidget(mCmdLineEdit->selectorWidget());
}
void MainWindow::setupStatusBar()
{
// Status label (Ready, Paused, ...)
mStatusLabel = new StatusLabel(ui->statusBar);
mStatusLabel->setText(tr("Ready"));
ui->statusBar->addWidget(mStatusLabel);
// Log line
mLastLogLabel = new StatusLabel();
ui->statusBar->addPermanentWidget(mLastLogLabel, 1);
// Time wasted counter
QLabel* timeWastedLabel = new QLabel(this);
ui->statusBar->addPermanentWidget(timeWastedLabel);
mTimeWastedCounter = new TimeWastedCounter(this, timeWastedLabel);
}
void MainWindow::closeEvent(QCloseEvent* event)
{
mCloseDialog->show();
mCloseDialog->setFocus();
static volatile bool bExecuteThread = true;
if(bExecuteThread)
{
bExecuteThread = false;
CloseSnowman(mSnowmanView);
Sleep(100);
mCloseThread->start();
}
if(bCanClose)
{
mCloseDialog->allowClose();
mCloseDialog->close();
event->accept();
}
else
event->ignore();
}
void MainWindow::setTab(QWidget* widget)
{
for(int i = 0; i < mTabWidget->count(); i++)
{
if(mTabWidget->widget(i) == widget)
{
mTabWidget->setCurrentIndex(i);
break;
}
}
}
void MainWindow::loadTabDefaultOrder()
{
clearTabWidget();
// Setup tabs
//TODO
for(int i = 0; i < mWidgetList.size(); i++)
addQWidgetTab(mWidgetList[i], mWidgetNativeNameList[i]);
}
void MainWindow::loadTabSavedOrder()
{
clearTabWidget();
QMap<duint, std::pair<QWidget*, QString>> tabIndexToWidget;
// Get tabIndex for each widget and add them to tabIndexToWidget
for(int i = 0; i < mWidgetList.size(); i++)
{
QString tabName = mWidgetNativeNameList[i];
duint tabIndex = Config()->getUint("TabOrder", tabName);
if(!tabIndexToWidget.contains(tabIndex))
tabIndexToWidget.insert(tabIndex, std::make_pair(mWidgetList[i], tabName));
else
{
// Conflicts. Try to find an unused tab index.
for(duint j = 0; j < mWidgetList.size(); j++)
{
auto item = tabIndexToWidget.find(j);
if(item == tabIndexToWidget.end())
{
tabIndexToWidget.insert(j, std::make_pair(mWidgetList[i], tabName));
break;
}
}
}
}
// Setup tabs
for(auto & widget : tabIndexToWidget)
addQWidgetTab(widget.first, widget.second);
}
void MainWindow::clearTabWidget()
{
if(mTabWidget->count() <= 0)
return;
// Remove all tabs starting from the end
for(int i = mTabWidget->count() - 1; i >= 0; i--)
mTabWidget->removeTab(i);
}
void MainWindow::setGlobalShortcut(QAction* action, const QKeySequence & key)
{
action->setShortcut(key);
action->setShortcutContext(Qt::ApplicationShortcut);
}
void MainWindow::refreshShortcuts()
{
setGlobalShortcut(ui->actionOpen, ConfigShortcut("FileOpen"));
setGlobalShortcut(ui->actionAttach, ConfigShortcut("FileAttach"));
setGlobalShortcut(ui->actionDetach, ConfigShortcut("FileDetach"));
setGlobalShortcut(ui->actionExit, ConfigShortcut("FileExit"));
setGlobalShortcut(ui->actionCpu, ConfigShortcut("ViewCpu"));
setGlobalShortcut(ui->actionLog, ConfigShortcut("ViewLog"));
setGlobalShortcut(ui->actionBreakpoints, ConfigShortcut("ViewBreakpoints"));
setGlobalShortcut(ui->actionMemoryMap, ConfigShortcut("ViewMemoryMap"));
setGlobalShortcut(ui->actionCallStack, ConfigShortcut("ViewCallStack"));
setGlobalShortcut(ui->actionSEHChain, ConfigShortcut("ViewSEHChain"));
setGlobalShortcut(ui->actionScript, ConfigShortcut("ViewScript"));
setGlobalShortcut(ui->actionSymbolInfo, ConfigShortcut("ViewSymbolInfo"));
setGlobalShortcut(ui->actionSource, ConfigShortcut("ViewSource"));
setGlobalShortcut(ui->actionReferences, ConfigShortcut("ViewReferences"));
setGlobalShortcut(ui->actionThreads, ConfigShortcut("ViewThreads"));
setGlobalShortcut(ui->actionPatches, ConfigShortcut("ViewPatches"));
setGlobalShortcut(ui->actionComments, ConfigShortcut("ViewComments"));
setGlobalShortcut(ui->actionLabels, ConfigShortcut("ViewLabels"));
setGlobalShortcut(ui->actionBookmarks, ConfigShortcut("ViewBookmarks"));
setGlobalShortcut(ui->actionFunctions, ConfigShortcut("ViewFunctions"));
setGlobalShortcut(ui->actionSnowman, ConfigShortcut("ViewSnowman"));
setGlobalShortcut(ui->actionHandles, ConfigShortcut("ViewHandles"));
setGlobalShortcut(ui->actionGraph, ConfigShortcut("ViewGraph"));
setGlobalShortcut(ui->actionRun, ConfigShortcut("DebugRun"));
setGlobalShortcut(ui->actioneRun, ConfigShortcut("DebugeRun"));
setGlobalShortcut(ui->actionRunSelection, ConfigShortcut("DebugRunSelection"));
setGlobalShortcut(ui->actionRunExpression, ConfigShortcut("DebugRunExpression"));
setGlobalShortcut(ui->actionPause, ConfigShortcut("DebugPause"));
setGlobalShortcut(ui->actionRestart, ConfigShortcut("DebugRestart"));
setGlobalShortcut(ui->actionClose, ConfigShortcut("DebugClose"));
setGlobalShortcut(ui->actionStepInto, ConfigShortcut("DebugStepInto"));
setGlobalShortcut(ui->actioneStepInto, ConfigShortcut("DebugeStepInto"));
setGlobalShortcut(ui->actionStepIntoSource, ConfigShortcut("DebugStepIntoSource"));
setGlobalShortcut(ui->actionStepOver, ConfigShortcut("DebugStepOver"));
setGlobalShortcut(ui->actioneStepOver, ConfigShortcut("DebugeStepOver"));
setGlobalShortcut(ui->actionStepOverSource, ConfigShortcut("DebugStepOverSource"));
setGlobalShortcut(ui->actionRtr, ConfigShortcut("DebugRtr"));
setGlobalShortcut(ui->actioneRtr, ConfigShortcut("DebugeRtr"));
setGlobalShortcut(ui->actionRtu, ConfigShortcut("DebugRtu"));
setGlobalShortcut(ui->actionCommand, ConfigShortcut("DebugCommand"));
setGlobalShortcut(ui->actionSkipNextInstruction, ConfigShortcut("DebugSkipNextInstruction"));
setGlobalShortcut(ui->actionTicnd, ConfigShortcut("DebugTraceIntoConditional"));
setGlobalShortcut(ui->actionTocnd, ConfigShortcut("DebugTraceOverConditional"));
setGlobalShortcut(ui->actionTRBit, ConfigShortcut("DebugEnableTraceRecordBit"));
setGlobalShortcut(ui->actionTRNone, ConfigShortcut("DebugTraceRecordNone"));
setGlobalShortcut(ui->actionInstrUndo, ConfigShortcut("DebugInstrUndo"));
setGlobalShortcut(ui->actionScylla, ConfigShortcut("PluginsScylla"));
setGlobalShortcut(actionManageFavourites, ConfigShortcut("FavouritesManage"));
setGlobalShortcut(ui->actionSettings, ConfigShortcut("OptionsPreferences"));
setGlobalShortcut(ui->actionAppearance, ConfigShortcut("OptionsAppearance"));
setGlobalShortcut(ui->actionShortcuts, ConfigShortcut("OptionsShortcuts"));
setGlobalShortcut(ui->actionTopmost, ConfigShortcut("OptionsTopmost"));
setGlobalShortcut(ui->actionReloadStylesheet, ConfigShortcut("OptionsReloadStylesheet"));
setGlobalShortcut(ui->actionAbout, ConfigShortcut("HelpAbout"));
setGlobalShortcut(ui->actionDonate, ConfigShortcut("HelpDonate"));
setGlobalShortcut(ui->actionCheckUpdates, ConfigShortcut("HelpCheckForUpdates"));
setGlobalShortcut(ui->actionCalculator, ConfigShortcut("HelpCalculator"));
setGlobalShortcut(ui->actionReportBug, ConfigShortcut("HelpReportBug"));
setGlobalShortcut(ui->actionManual, ConfigShortcut("HelpManual"));
setGlobalShortcut(ui->actionCrashDump, ConfigShortcut("HelpCrashDump"));
setGlobalShortcut(ui->actionStrings, ConfigShortcut("ActionFindStrings"));
setGlobalShortcut(ui->actionCalls, ConfigShortcut("ActionFindIntermodularCalls"));
}
//Reads recent files list from settings
void MainWindow::loadMRUList(int maxItems)
{
mMaxMRU = maxItems;
for(int i = 0; i < mMaxMRU; i++)
{
char currentFile[MAX_SETTING_SIZE] = "";
if(!BridgeSettingGet("Recent Files", QString().sprintf("%.2d", i + 1).toUtf8().constData(), currentFile))
break;
if(QString(currentFile).size() && QFile(currentFile).exists())
mMRUList.push_back(currentFile);
}
mMRUList.removeDuplicates();
updateMRUMenu();
}
//save recent files to settings
void MainWindow::saveMRUList()
{
BridgeSettingSet("Recent Files", 0, 0); //clear
mMRUList.removeDuplicates();
int mruSize = mMRUList.size();
for(int i = 0; i < mruSize; i++)
{
if(QFile(mMRUList.at(i)).exists())
BridgeSettingSet("Recent Files", QString().sprintf("%.2d", i + 1).toUtf8().constData(), mMRUList.at(i).toUtf8().constData());
}
}
void MainWindow::addMRUEntry(QString entry)
{
if(!entry.size())
return;
//remove duplicate entry if it exists
removeMRUEntry(entry);
mMRUList.insert(mMRUList.begin(), entry);
if(mMRUList.size() > mMaxMRU)
mMRUList.erase(mMRUList.begin() + mMaxMRU, mMRUList.end());
}
void MainWindow::removeMRUEntry(QString entry)
{
if(!entry.size())
return;
QList<QString>::iterator it;
for(it = mMRUList.begin(); it != mMRUList.end(); ++it)
{
if((*it) == entry)
{
mMRUList.erase(it);
break;
}
}
}
void MainWindow::updateMRUMenu()
{
if(mMaxMRU < 1)
return;
QMenu* fileMenu = ui->menuRecentFiles;
QList<QAction*> list = fileMenu->actions();
for(int i = 1; i < list.length(); ++i)
fileMenu->removeAction(list.at(i));
//add items to list
if(mMRUList.size() > 0)
{
list = fileMenu->actions();
for(int index = 0; index < mMRUList.size(); ++index)
{
fileMenu->addAction(new QAction(mMRUList.at(index), this));
fileMenu->actions().last()->setObjectName(QString("MRU").append(QString::number(index)));
connect(fileMenu->actions().last(), SIGNAL(triggered()), this, SLOT(openFile()));
}
}
}
QString MainWindow::getMRUEntry(int index)
{
if(index < mMRUList.size())
return mMRUList.at(index);
return "";
}
void MainWindow::executeCommand()
{
mCmdLineEdit->execute();
}
void MainWindow::execStepOver()
{
DbgCmdExec("StepOver");
}
void MainWindow::execStepInto()
{
DbgCmdExec("StepInto");
}
void MainWindow::setFocusToCommandBar()
{
mCmdLineEdit->setFocus();
}
void MainWindow::execClose()
{
DbgCmdExec("stop");
}
void MainWindow::execRun()
{
DbgCmdExec("run");
}
void MainWindow::execRtr()
{
DbgCmdExec("rtr");
}
void MainWindow::execRtu()
{
DbgCmdExec("rtu");
}
void MainWindow::execTRBit()
{
mCpuWidget->getDisasmWidget()->ActionTraceRecordBitSlot();
}
void MainWindow::execTRByte()
{
mCpuWidget->getDisasmWidget()->ActionTraceRecordByteSlot();
}
void MainWindow::execTRWord()
{
mCpuWidget->getDisasmWidget()->ActionTraceRecordWordSlot();
}
void MainWindow::execTRNone()
{
mCpuWidget->getDisasmWidget()->ActionTraceRecordDisableSlot();
}
void MainWindow::execTRTIBT()
{
DbgCmdExec("tibt");
}
void MainWindow::execTRTOBT()
{
DbgCmdExec("tobt");
}
void MainWindow::execTRTIIT()
{
DbgCmdExec("tiit");
}
void MainWindow::execTRTOIT()
{
DbgCmdExec("toit");
}
void MainWindow::execInstrUndo()
{
DbgCmdExec("InstrUndo");
}
void MainWindow::execTicnd()
{
if(!DbgIsDebugging())
return;
LineEditDialog mLineEdit(this);
mLineEdit.setWindowTitle(tr("Enter trace into finishing condition."));
if(mLineEdit.exec() == QDialog::Accepted)
DbgCmdExec(QString("ticnd \"%1\"").arg(mLineEdit.editText).toUtf8().constData());
}
void MainWindow::execTocnd()
{
if(!DbgIsDebugging())
return;
LineEditDialog mLineEdit(this);
mLineEdit.setWindowTitle(tr("Enter trace over finishing condition."));
if(mLineEdit.exec() == QDialog::Accepted)
DbgCmdExec(QString("tocnd \"%1\"").arg(mLineEdit.editText).toUtf8().constData());
}
void MainWindow::displayMemMapWidget()
{
showQWidgetTab(mMemMapView);
}
void MainWindow::displayLogWidget()
{
showQWidgetTab(mLogView);
}
void MainWindow::displayScriptWidget()
{
showQWidgetTab(mScriptView);
}
void MainWindow::displayAboutWidget()
{
#ifdef _WIN64
QString title = tr("About x64dbg");
#else
QString title = tr("About x32dbg");
#endif //_WIN64
title += QString().sprintf(" v%d", BridgeGetDbgVersion());
QMessageBox msg(QMessageBox::Information, title, "Website:<br><a href=\"http://x64dbg.com\">http://x64dbg.com</a><br><br>Attribution:<br><a href=\"http://icons8.com\">Icons8</a><br><a href=\"http://p.yusukekamiyamane.com\">Yusuke Kamiyamane</a><br><br>Compiled on:<br>" + ToDateString(GetCompileDate()) + ", " __TIME__);
msg.setWindowIcon(DIcon("information.png"));
msg.setTextFormat(Qt::RichText);
msg.setParent(this, Qt::Dialog);
msg.setWindowFlags(msg.windowFlags() & (~Qt::WindowContextHelpButtonHint));
msg.exec();
}
void MainWindow::openFile()
{
QString lastPath, filename;
QAction* fileToOpen = qobject_cast<QAction*>(sender());
//if sender is from recent list directly open file, otherwise show dialog
if(fileToOpen == NULL || !fileToOpen->objectName().startsWith("MRU") || !(fileToOpen->text().length()))
{
lastPath = (mMRUList.size() > 0) ? mMRUList.at(0) : 0;
filename = QFileDialog::getOpenFileName(this, tr("Open file"), lastPath, tr("Executables (*.exe *.dll);;All files (*.*)"));
if(!filename.length())
return;
filename = QDir::toNativeSeparators(filename); //convert to native path format (with backlashes)
}
else
{
filename = fileToOpen->text();
}
DbgCmdExec(QString().sprintf("init \"%s\"", filename.toUtf8().constData()).toUtf8().constData());
//file is from recent menu
if(fileToOpen != NULL && fileToOpen->objectName().startsWith("MRU"))
{
fileToOpen->setObjectName(fileToOpen->objectName().split("U").at(1));
int index = fileToOpen->objectName().toInt();
QString exists = getMRUEntry(index);
if(exists.length() == 0)
{
addMRUEntry(filename);
updateMRUMenu();
saveMRUList();
}
fileToOpen->setObjectName(fileToOpen->objectName().prepend("MRU"));
}
//file is from open button
bool update = true;
if(fileToOpen == NULL || fileToOpen->objectName().compare("actionOpen") == 0)
for(int i = 0; i < mMRUList.size(); i++)
if(mMRUList.at(i) == filename)
{
update = false;
break;
}
if(update)
{
addMRUEntry(filename);
updateMRUMenu();
saveMRUList();
}
mCpuWidget->setDisasmFocus();
}
void MainWindow::execPause()
{
DbgCmdExec("pause");
}
void MainWindow::startScylla() //this is executed
{
DbgCmdExec("StartScylla");
}
void MainWindow::restartDebugging()
{
if(!mMRUList.size())
return;
DbgCmdExec(QString().sprintf("init \"%s\"", mMRUList.at(0).toUtf8().constData()).toUtf8().constData());
mCpuWidget->setDisasmFocus();
}
void MainWindow::displayBreakpointWidget()
{
showQWidgetTab(mBreakpointsView);
}
void MainWindow::dragEnterEvent(QDragEnterEvent* pEvent)
{
if(pEvent->mimeData()->hasUrls())
{
pEvent->acceptProposedAction();
}
}
void MainWindow::dropEvent(QDropEvent* pEvent)
{
if(pEvent->mimeData()->hasUrls())
{
QString filename = QDir::toNativeSeparators(pEvent->mimeData()->urls()[0].toLocalFile());
DbgCmdExec(QString().sprintf("init \"%s\"", filename.toUtf8().constData()).toUtf8().constData());
pEvent->acceptProposedAction();
}
}
void MainWindow::updateWindowTitleSlot(QString filename)
{
if(filename.length())
{
setWindowTitle(mWindowMainTitle + QString(" - ") + filename);
windowTitle = filename;
}
else
{
setWindowTitle(mWindowMainTitle);
windowTitle = mWindowMainTitle;
}
}
void MainWindow::execeStepOver()
{
DbgCmdExec("eStepOver");
}
void MainWindow::execeStepInto()
{
DbgCmdExec("eStepInto");
}
void MainWindow::execeRun()
{
DbgCmdExec("erun");
}
void MainWindow::execeRtr()
{
DbgCmdExec("ertr");
}
void MainWindow::execSkip()
{
DbgCmdExec("skip");
}
void MainWindow::displayCpuWidget()
{
showQWidgetTab(mCpuWidget);
}
void MainWindow::displaySymbolWidget()
{
showQWidgetTab(mSymbolView);
}
void MainWindow::displaySourceViewWidget()
{
showQWidgetTab(mSourceViewManager);
}
void MainWindow::displayReferencesWidget()
{
showQWidgetTab(mReferenceManager);
}
void MainWindow::displayThreadsWidget()
{
showQWidgetTab(mThreadView);
}
void MainWindow::displaySnowmanWidget()
{
showQWidgetTab(mSnowmanView);
}
void MainWindow::displayGraphWidget()
{
showQWidgetTab(mGraphView);
}
void MainWindow::hideDebugger()
{
DbgCmdExec("hide");
}
void MainWindow::openSettings()
{
SettingsDialog* settings = new SettingsDialog(this);
connect(settings, SIGNAL(chkSaveLoadTabOrderStateChanged(bool)), this, SLOT(chkSaveloadTabSavedOrderStateChangedSlot(bool)));
settings->lastException = lastException;
settings->exec();
}
void MainWindow::openAppearance()
{
AppearanceDialog appearance(this);
appearance.exec();
}
void MainWindow::openCalculator()
{
mCalculatorDialog->showNormal();
mCalculatorDialog->setFocus();
mCalculatorDialog->setExpressionFocus();
}
void MainWindow::openShortcuts()
{
ShortcutsDialog shortcuts(this);
shortcuts.exec();
}
void MainWindow::changeTopmost(bool checked)
{
if(checked)
SetWindowPos((HWND)this->winId(), HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
else
SetWindowPos((HWND)this->winId(), HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
}
void MainWindow::addRecentFile(QString file)
{
addMRUEntry(file);
updateMRUMenu();
saveMRUList();
}
void MainWindow::setLastException(unsigned int exceptionCode)
{
lastException = exceptionCode;
}
void MainWindow::findStrings()
{
DbgCmdExec(QString("strref " + QString("%1").arg(mCpuWidget->getDisasmWidget()->getSelectedVa(), sizeof(dsint) * 2, 16, QChar('0')).toUpper()).toUtf8().constData());
displayReferencesWidget();
}
void MainWindow::findModularCalls()
{
DbgCmdExec(QString("modcallfind " + QString("%1").arg(mCpuWidget->getDisasmWidget()->getSelectedVa(), sizeof(dsint) * 2, 16, QChar('0')).toUpper()).toUtf8().constData());
displayReferencesWidget();
}
const MainWindow::MenuInfo* MainWindow::findMenu(int hMenu)
{
if(hMenu == -1)
return 0;
int nFound = -1;
for(int i = 0; i < mMenuList.size(); i++)
{
if(hMenu == mMenuList.at(i).hMenu)
{
nFound = i;
break;
}
}
return nFound == -1 ? 0 : &mMenuList.at(nFound);
}
void MainWindow::addMenuToList(QWidget* parent, QMenu* menu, int hMenu, int hParentMenu)
{
if(!findMenu(hMenu))
mMenuList.push_back(MenuInfo(parent, menu, hMenu, hParentMenu));
Bridge::getBridge()->setResult();
}
void MainWindow::addMenu(int hMenu, QString title)
{
const MenuInfo* menu = findMenu(hMenu);
if(!menu && hMenu != -1)
{
Bridge::getBridge()->setResult(-1);
return;
}
int hMenuNew = hMenuNext++;
QWidget* parent = hMenu == -1 ? this : menu->parent;
QMenu* wMenu = new QMenu(title, parent);
wMenu->menuAction()->setVisible(false);
mMenuList.push_back(MenuInfo(parent, wMenu, hMenuNew, hMenu));
if(hMenu == -1) //top-level
ui->menuBar->addMenu(wMenu);
else //deeper level
menu->mMenu->addMenu(wMenu);
Bridge::getBridge()->setResult(hMenuNew);
}
void MainWindow::addMenuEntry(int hMenu, QString title)
{
const MenuInfo* menu = findMenu(hMenu);
if(!menu && hMenu != -1)
{
Bridge::getBridge()->setResult(-1);
return;
}
MenuEntryInfo newInfo;
int hEntryNew = hEntryNext++;
newInfo.hEntry = hEntryNew;
newInfo.hParentMenu = hMenu;
QWidget* parent = hMenu == -1 ? this : menu->parent;
QAction* wAction = new QAction(title, parent);
wAction->setObjectName(QString().sprintf("ENTRY|%d", hEntryNew));
parent->addAction(wAction);
connect(wAction, SIGNAL(triggered()), this, SLOT(menuEntrySlot()));
newInfo.mAction = wAction;
mEntryList.push_back(newInfo);
if(hMenu == -1) //top level
ui->menuBar->addAction(wAction);
else //deeper level
{
menu->mMenu->addAction(wAction);
menu->mMenu->menuAction()->setVisible(true);
}
Bridge::getBridge()->setResult(hEntryNew);
}
void MainWindow::addSeparator(int hMenu)
{
const MenuInfo* menu = findMenu(hMenu);
if(menu)
{
MenuEntryInfo newInfo;
newInfo.hEntry = -1;
newInfo.hParentMenu = hMenu;
newInfo.mAction = menu->mMenu->addSeparator();
mEntryList.push_back(newInfo);
}
Bridge::getBridge()->setResult();
}
void MainWindow::clearMenu(int hMenu)
{
if(!mMenuList.size() || hMenu == -1)
{
Bridge::getBridge()->setResult();
return;
}
const MenuInfo* menu = findMenu(hMenu);
//delete menu entries
for(int i = mEntryList.size() - 1; i > -1; i--)
{
if(hMenu == mEntryList.at(i).hParentMenu) //we found an entry that has the menu as parent
{
QWidget* parent = menu == 0 ? this : menu->parent;
parent->removeAction(mEntryList.at(i).mAction);
delete mEntryList.at(i).mAction; //delete the entry object
mEntryList.erase(mEntryList.begin() + i);
}
}
//recursively delete the menus
for(int i = mMenuList.size() - 1; i > -1; i--)
{
if(hMenu == mMenuList.at(i).hParentMenu) //we found a menu that has the menu as parent
{
clearMenu(mMenuList.at(i).hMenu); //delete children menus
delete mMenuList.at(i).mMenu; //delete the child menu object
mMenuList.erase(mMenuList.begin() + i); //delete the child entry
}
}
//hide the empty menu
if(menu)
menu->mMenu->menuAction()->setVisible(false);
Bridge::getBridge()->setResult();
}
void MainWindow::initMenuApi()
{
//256 entries are reserved
mEntryList.clear();
hEntryNext = 256;
mMenuList.clear();
hMenuNext = 256;
}
void MainWindow::menuEntrySlot()
{
QAction* action = qobject_cast<QAction*>(sender());
if(action && action->objectName().startsWith("ENTRY|"))
{
int hEntry = -1;
if(sscanf_s(action->objectName().mid(6).toUtf8().constData(), "%d", &hEntry) == 1)
DbgMenuEntryClicked(hEntry);
}
}
void MainWindow::removeMenuEntry(int hEntry)
{
for(int i = 0; i < mEntryList.size(); i++)
{
if(mEntryList.at(i).hEntry == hEntry)
{
const MenuEntryInfo & entry = mEntryList.at(i);
const MenuInfo* menu = findMenu(entry.hParentMenu);
QWidget* parent = menu == 0 ? this : menu->parent;
parent->removeAction(entry.mAction);
delete entry.mAction;
mEntryList.erase(mEntryList.begin() + i);
break;
}
}
Bridge::getBridge()->setResult();
}
void MainWindow::setIconMenuEntry(int hEntry, QIcon icon)
{
for(int i = 0; i < mEntryList.size(); i++)
{
if(mEntryList.at(i).hEntry == hEntry)
{
const MenuEntryInfo & entry = mEntryList.at(i);
entry.mAction->setIcon(icon);
break;
}
}
Bridge::getBridge()->setResult();
}
void MainWindow::setIconMenu(int hMenu, QIcon icon)
{
for(int i = 0; i < mMenuList.size(); i++)
{
if(mMenuList.at(i).hMenu == hMenu)
{
const MenuInfo & menu = mMenuList.at(i);
menu.mMenu->setIcon(icon);
}
}
Bridge::getBridge()->setResult();
}
void MainWindow::runSelection()
{
if(!DbgIsDebugging())
return;
QString command = "bp " + QString("%1").arg(mCpuWidget->getDisasmWidget()->getSelectedVa(), sizeof(dsint) * 2, 16, QChar('0')).toUpper() + ", ss";
if(DbgCmdExecDirect(command.toUtf8().constData()))
DbgCmdExecDirect("run");
}
void MainWindow::runExpression()
{
if(!DbgIsDebugging())
return;
GotoDialog gotoDialog(this);
gotoDialog.setWindowTitle(tr("Enter expression to run to..."));
if(gotoDialog.exec() != QDialog::Accepted)
return;
if(DbgCmdExecDirect(QString("bp \"%1\", ss").arg(gotoDialog.expressionText).toUtf8().constData()))
DbgCmdExecDirect("run");
}
void MainWindow::getStrWindow(const QString title, QString* text)
{
LineEditDialog mLineEdit(this);
mLineEdit.setWindowTitle(title);
bool bResult = true;
if(mLineEdit.exec() != QDialog::Accepted)
bResult = false;
*text = mLineEdit.editText;
Bridge::getBridge()->setResult(bResult);
}
void MainWindow::patchWindow()
{
if(!DbgIsDebugging())
{
SimpleErrorBox(this, tr("Error!"), tr("Patches cannot be shown when not debugging..."));
return;
}
GuiUpdatePatches();
mPatchDialog->showNormal();
mPatchDialog->setFocus();
}
void MainWindow::displayComments()
{
if(!DbgIsDebugging())
return;
DbgCmdExec("commentlist");
displayReferencesWidget();
}
void MainWindow::displayLabels()
{
if(!DbgIsDebugging())
return;
DbgCmdExec("labellist");
displayReferencesWidget();
}
void MainWindow::displayBookmarks()
{
if(!DbgIsDebugging())
return;
DbgCmdExec("bookmarklist");
displayReferencesWidget();
}
void MainWindow::displayFunctions()
{
if(!DbgIsDebugging())
return;
DbgCmdExec("functionlist");
displayReferencesWidget();
}
void MainWindow::checkUpdates()
{
mUpdateChecker->checkForUpdates();
}
void MainWindow::displayCallstack()
{
showQWidgetTab(mCallStackView);
}
void MainWindow::displaySEHChain()
{
showQWidgetTab(mSEHChainView);
}
void MainWindow::donate()
{
QMessageBox msg(QMessageBox::Information, tr("Donate"), tr("All the money will go to x64dbg development."));
msg.setWindowIcon(DIcon("donate.png"));
msg.setParent(this, Qt::Dialog);
msg.setWindowFlags(msg.windowFlags() & (~Qt::WindowContextHelpButtonHint));
msg.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
msg.setDefaultButton(QMessageBox::Ok);
if(msg.exec() != QMessageBox::Ok)
return;
QDesktopServices::openUrl(QUrl("http://donate.x64dbg.com"));
}
void MainWindow::reportBug()
{
QMessageBox msg(QMessageBox::Information, tr("Report Bug"), tr("You will be taken to a website where you can report a bug.\nMake sure to fill in as much information as possible."));
msg.setWindowIcon(DIcon("bug-report.png"));
msg.setParent(this, Qt::Dialog);
msg.setWindowFlags(msg.windowFlags() & (~Qt::WindowContextHelpButtonHint));
msg.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
msg.setDefaultButton(QMessageBox::Ok);
if(msg.exec() != QMessageBox::Ok)
return;
QDesktopServices::openUrl(QUrl("http://report.x64dbg.com"));
}
void MainWindow::crashDump()
{
QMessageBox msg(QMessageBox::Critical, tr("Generate crash dump"), tr("This action will crash the debugger and generate a crash dump. You will LOSE ALL YOUR DATA. Do you really want to continue?"));
msg.setWindowIcon(DIcon("fatal-error.png"));
msg.setParent(this, Qt::Dialog);
msg.setWindowFlags(msg.windowFlags() & (~Qt::WindowContextHelpButtonHint));
msg.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
msg.setDefaultButton(QMessageBox::Cancel);
if(msg.exec() != QMessageBox::Ok)
return;
// Fatal error
__debugbreak();
// Congratulations! We survived a fatal error!
SimpleWarningBox(this, tr("Have fun debugging the debugger!"), tr("Debugger detected!"));
}
void MainWindow::displayAttach()
{
AttachDialog attach(this);
attach.exec();
mCpuWidget->setDisasmFocus();
}
void MainWindow::detach()
{
DbgCmdExec("detach");
}
void MainWindow::changeCommandLine()
{
if(!DbgIsDebugging())
return;
LineEditDialog mLineEdit(this);
mLineEdit.setText("");
mLineEdit.setWindowTitle(tr("Change Command Line"));
mLineEdit.setWindowIcon(DIcon("changeargs.png"));
size_t cbsize = 0;
char* cmdline = 0;
if(!DbgFunctions()->GetCmdline(0, &cbsize))
mLineEdit.setText(tr("Cannot get remote command line, use the 'getcmdline' command for more information."));
else
{
cmdline = new char[cbsize];
DbgFunctions()->GetCmdline(cmdline, 0);
mLineEdit.setText(QString(cmdline));
delete[] cmdline;
}
mLineEdit.setCursorPosition(0);
if(mLineEdit.exec() != QDialog::Accepted)
return; //pressed cancel
if(!DbgFunctions()->SetCmdline((char*)mLineEdit.editText.toUtf8().constData()))
SimpleErrorBox(this, tr("Error!"), tr("Could not set command line!"));
else
{
DbgFunctions()->MemUpdateMap();
GuiUpdateMemoryView();
GuiAddStatusBarMessage((tr("New command line: ") + mLineEdit.editText + "\n").toUtf8().constData());
}
}
void MainWindow::displayManual()
{
// Open the Windows CHM in the upper directory
QDesktopServices::openUrl(QUrl(QUrl::fromLocalFile(QString("%1/../x64dbg.chm").arg(QCoreApplication::applicationDirPath()))));
}
void MainWindow::decompileAt(dsint start, dsint end)
{
DecompileAt(mSnowmanView, start, end);
}
void MainWindow::canClose()
{
bCanClose = true;
close();
}
void MainWindow::addQWidgetTab(QWidget* qWidget, QString nativeName)
{
mTabWidget->addTabEx(qWidget, qWidget->windowIcon(), qWidget->windowTitle(), nativeName);
}
void MainWindow::addQWidgetTab(QWidget* qWidget)
{
addQWidgetTab(qWidget, qWidget->windowTitle());
}
void MainWindow::showQWidgetTab(QWidget* qWidget)
{
qWidget->show();
qWidget->setFocus();
setTab(qWidget);
}
void MainWindow::closeQWidgetTab(QWidget* qWidget)
{
for(int i = 0; i < mTabWidget->count(); i++)
{
if(mTabWidget->widget(i) == qWidget)
{
mTabWidget->DeleteTab(i);
break;
}
}
}
void MainWindow::executeOnGuiThread(void* cbGuiThread)
{
((GUICALLBACK)cbGuiThread)();
}
void MainWindow::tabMovedSlot(int from, int to)
{
for(int i = 0; i < mTabWidget->count(); i++)
{
// Remove space in widget name and append Tab to get config settings (CPUTab, MemoryMapTab, etc...)
//QString tabName = mTabWidget->tabText(i).replace(" ", "") + "Tab";
QString tabName = mTabWidget->getNativeName(i);
Config()->setUint("TabOrder", tabName, i);
}
}
void MainWindow::chkSaveloadTabSavedOrderStateChangedSlot(bool state)
{
if(state)
loadTabSavedOrder();
else
loadTabDefaultOrder();
}
void MainWindow::dbgStateChangedSlot(DBGSTATE state)
{
if(state == initialized) //fixes a crash when restarting with certain settings in another tab
displayCpuWidget();
}
void MainWindow::on_actionFaq_triggered()
{
QDesktopServices::openUrl(QUrl("http://faq.x64dbg.com"));
}
void MainWindow::on_actionReloadStylesheet_triggered()
{
QFile f(QString("%1/style.css").arg(QCoreApplication::applicationDirPath()));
if(f.open(QFile::ReadOnly | QFile::Text))
{
QTextStream in(&f);
auto style = in.readAll();
f.close();
qApp->setStyleSheet(style);
}
else
qApp->setStyleSheet("");
ensurePolished();
update();
}
void MainWindow::displayNotesWidget()
{
showQWidgetTab(mNotesManager);
}
void MainWindow::displayHandlesWidget()
{
showQWidgetTab(mHandlesView);
}
void MainWindow::manageFavourites()
{
FavouriteTools favToolsDialog(this);
favToolsDialog.exec();
updateFavouriteTools();
}
void MainWindow::updateFavouriteTools()
{
char buffer[MAX_SETTING_SIZE];
bool isanythingexists = false;
ui->menuFavourites->clear();
for(unsigned int i = 1; BridgeSettingGet("Favourite", QString("Tool%1").arg(i).toUtf8().constData(), buffer); i++)
{
QString exePath = QString::fromUtf8(buffer);
QAction* newAction = new QAction(this);
newAction->setData(QVariant(QString("Tool,%1").arg(exePath)));
if(BridgeSettingGet("Favourite", QString("ToolShortcut%1").arg(i).toUtf8().constData(), buffer))
if(*buffer && strcmp(buffer, "NOT_SET") != 0)
setGlobalShortcut(newAction, QKeySequence(QString::fromUtf8(buffer)));
if(BridgeSettingGet("Favourite", QString("ToolDescription%1").arg(i).toUtf8().constData(), buffer))
newAction->setText(QString::fromUtf8(buffer));
else
newAction->setText(exePath);
connect(newAction, SIGNAL(triggered()), this, SLOT(clickFavouriteTool()));
ui->menuFavourites->addAction(newAction);
isanythingexists = true;
}
if(isanythingexists)
{
isanythingexists = false;
ui->menuFavourites->addSeparator();
}
for(unsigned int i = 1; BridgeSettingGet("Favourite", QString("Script%1").arg(i).toUtf8().constData(), buffer); i++)
{
QString scriptPath = QString::fromUtf8(buffer);
QAction* newAction = new QAction(this);
newAction->setData(QVariant(QString("Script,%1").arg(scriptPath)));
if(BridgeSettingGet("Favourite", QString("ScriptShortcut%1").arg(i).toUtf8().constData(), buffer))
if(*buffer && strcmp(buffer, "NOT_SET") != 0)
setGlobalShortcut(newAction, QKeySequence(QString::fromUtf8(buffer)));
if(BridgeSettingGet("Favourite", QString("ScriptDescription%1").arg(i).toUtf8().constData(), buffer))
newAction->setText(QString::fromUtf8(buffer));
else
newAction->setText(scriptPath);
connect(newAction, SIGNAL(triggered()), this, SLOT(clickFavouriteTool()));
ui->menuFavourites->addAction(newAction);
isanythingexists = true;
}
if(isanythingexists)
{
isanythingexists = false;
ui->menuFavourites->addSeparator();
}
for(unsigned int i = 1; BridgeSettingGet("Favourite", QString("Command%1").arg(i).toUtf8().constData(), buffer); i++)
{
QAction* newAction = new QAction(QString::fromUtf8(buffer), this);
newAction->setData(QVariant(QString("Command")));
if(BridgeSettingGet("Favourite", QString("CommandShortcut%1").arg(i).toUtf8().constData(), buffer))
if(*buffer && strcmp(buffer, "NOT_SET") != 0)
setGlobalShortcut(newAction, QKeySequence(QString::fromUtf8(buffer)));
connect(newAction, SIGNAL(triggered()), this, SLOT(clickFavouriteTool()));
ui->menuFavourites->addAction(newAction);
isanythingexists = true;
}
if(isanythingexists)
ui->menuFavourites->addSeparator();
actionManageFavourites = new QAction(DIcon("star.png"), tr("&Manage Favourite Tools..."), this);
ui->menuFavourites->addAction(actionManageFavourites);
setGlobalShortcut(actionManageFavourites, ConfigShortcut("FavouritesManage"));
connect(ui->menuFavourites->actions().last(), SIGNAL(triggered()), this, SLOT(manageFavourites()));
}
void MainWindow::clickFavouriteTool()
{
QAction* action = qobject_cast<QAction*>(sender());
if(action == nullptr)
return;
QString data = action->data().toString();
if(data.startsWith("Tool,"))
{
QString toolPath = data.mid(5);
duint PID = DbgValFromString("$pid");
toolPath.replace(QString("%PID%"), QString::number(PID), Qt::CaseInsensitive);
PROCESS_INFORMATION procinfo;
STARTUPINFO startupinfo;
memset(&procinfo, 0, sizeof(PROCESS_INFORMATION));
memset(&startupinfo, 0, sizeof(startupinfo));
startupinfo.cb = sizeof(startupinfo);
CreateProcessW(nullptr, (LPWSTR)toolPath.toStdWString().c_str(), nullptr, nullptr, FALSE, 0, nullptr, nullptr, &startupinfo, &procinfo);
CloseHandle(procinfo.hThread);
CloseHandle(procinfo.hProcess);
}
else if(data.startsWith("Script,"))
{
QString scriptPath = data.mid(7);
DbgScriptUnload();
DbgScriptLoad(scriptPath.toUtf8().constData());
}
else if(data.compare("Command") == 0)
{
DbgCmdExec(action->text().toUtf8().constData());
}
}
void MainWindow::on_actionStepIntoSource_triggered()
{
DbgCmdExec("TraceIntoConditional src.line(cip) && !src.disp(cip)");
}
void MainWindow::on_actionStepOverSource_triggered()
{
DbgCmdExec("TraceOverConditional src.line(cip) && !src.disp(cip)");
}