1
0
Fork 0
x64dbg/x64_dbg_gui/Project/Src/Gui/MainWindow.cpp

1136 lines
38 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"
MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
//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*)));
//setup menu api
initMenuApi();
addMenuToList(this, ui->menuPlugins, GUI_PLUGIN_MENU);
this->showMaximized();
#ifdef _WIN64
mWindowMainTitle = "x64dbg";
#else
mWindowMainTitle = "x32dbg";
#endif
//Set window title
setWindowTitle(QString(mWindowMainTitle));
//Load application icon
HICON hIcon = LoadIcon(GetModuleHandleA(0), MAKEINTRESOURCE(100));
SendMessageA((HWND)MainWindow::winId(), WM_SETICON, ICON_BIG, (LPARAM)hIcon);
DestroyIcon(hIcon);
//Load recent files
loadMRUList(16);
//Accept drops
setAcceptDrops(true);
// Log View
mLogView = new LogView();
mLogView->setWindowTitle("Log");
mLogView->setWindowIcon(QIcon(":/icons/images/log.png"));
mLogView->hide();
// Symbol view
mSymbolView = new SymbolView();
mSymbolView->setWindowTitle("Symbols");
mSymbolView->setWindowIcon(QIcon(":/icons/images/pdb.png"));
mSymbolView->hide();
// Source View
mSourceViewManager = new SourceViewerManager();
mSourceViewManager->setWindowTitle("Source");
mSourceViewManager->setWindowIcon(QIcon(":/icons/images/source.png"));
mSourceViewManager->hide();
connect(mSourceViewManager, SIGNAL(showCpu()), this, SLOT(displayCpuWidget()));
// Breakpoints
mBreakpointsView = new BreakpointsView();
mBreakpointsView->setWindowTitle("Breakpoints");
mBreakpointsView->setWindowIcon(QIcon(":/icons/images/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("Memory Map");
mMemMapView->setWindowIcon(QIcon(":/icons/images/memory-map.png"));
mMemMapView->hide();
// Callstack View
mCallStackView = new CallStackView();
mCallStackView->setWindowTitle("Call Stack");
mCallStackView->setWindowIcon(QIcon(":/icons/images/callstack.png"));
connect(mCallStackView, SIGNAL(showCpu()), this, SLOT(displayCpuWidget()));
// Script view
mScriptView = new ScriptView();
mScriptView->setWindowTitle("Script");
mScriptView->setWindowIcon(QIcon(":/icons/images/script-code.png"));
mScriptView->hide();
// CPU View
mCpuWidget = new CPUWidget();
mCpuWidget->setWindowTitle("CPU");
mCpuWidget->setWindowIcon(QIcon(":/icons/images/processor-cpu.png"));
// Reference Manager
mReferenceManager = new ReferenceManager(this);
Bridge::getBridge()->referenceManager = mReferenceManager;
mReferenceManager->setWindowTitle("References");
mReferenceManager->setWindowIcon(QIcon(":/icons/images/search.png"));
// Thread View
mThreadView = new ThreadView();
connect(mThreadView, SIGNAL(showCpu()), this, SLOT(displayCpuWidget()));
mThreadView->setWindowTitle("Threads");
mThreadView->setWindowIcon(QIcon(":/icons/images/arrow-threads.png"));
// Snowman View (decompiler)
mSnowmanView = CreateSnowman(this);
mSnowmanView->setWindowTitle("Snowman");
mSnowmanView->setWindowIcon(QIcon(":/icons/images/snowman.png"));
//Create the tab widget
mTabWidget = new MHTabWidget(NULL);
//Setup tabs
addQWidgetTab(mCpuWidget);
addQWidgetTab(mLogView);
addQWidgetTab(mBreakpointsView);
addQWidgetTab(mMemMapView);
addQWidgetTab(mCallStackView);
addQWidgetTab(mScriptView);
addQWidgetTab(mSymbolView);
addQWidgetTab(mSourceViewManager);
addQWidgetTab(mReferenceManager);
addQWidgetTab(mThreadView);
addQWidgetTab(mSnowmanView);
setCentralWidget(mTabWidget);
// Setup the command bar
mCmdLineEdit = new CommandLineEdit(ui->cmdBar);
ui->cmdBar->addWidget(new QLabel("Command: "));
ui->cmdBar->addWidget(mCmdLineEdit);
// Status bar
mStatusLabel = new StatusLabel(ui->statusBar);
mStatusLabel->setText("Ready");
ui->statusBar->addWidget(mStatusLabel);
mLastLogLabel = new StatusLabel();
ui->statusBar->addPermanentWidget(mLastLogLabel, 1);
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->actionSkipNextInstruction, SIGNAL(triggered()), this, SLOT(execSkip()));
connect(ui->actionScript, SIGNAL(triggered()), this, SLOT(displayScriptWidget()));
connect(ui->actionRunSelection, SIGNAL(triggered()), this, SLOT(runSelection()));
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(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->actionDonate, SIGNAL(triggered()), this, SLOT(donate()));
connect(ui->actionReportBug, SIGNAL(triggered()), this, SLOT(reportBug()));
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(mCpuWidget->mDisas, SIGNAL(displayReferencesWidget()), this, SLOT(displayReferencesWidget()));
connect(mCpuWidget->mDisas, SIGNAL(displaySourceManagerWidget()), this, SLOT(displaySourceViewWidget()));
connect(mCpuWidget->mDisas, SIGNAL(displaySnowmanWidget()), this, SLOT(displaySnowmanWidget()));
connect(mCpuWidget->mDisas, SIGNAL(showPatches()), this, SLOT(patchWindow()));
connect(mCpuWidget->mDisas, SIGNAL(decompileAt(int_t, int_t)), this, SLOT(decompileAt(int_t, int_t)));
connect(mCpuWidget->mDump, SIGNAL(displayReferencesWidget()), this, SLOT(displayReferencesWidget()));
connect(mCpuWidget->mStack, SIGNAL(displayReferencesWidget()), this, SLOT(displayReferencesWidget()));
connect(Config(), SIGNAL(shortcutsUpdated()), this, SLOT(refreshShortcuts()));
//Set default setttings (when not set)
SettingsDialog defaultSettings;
lastException = 0;
defaultSettings.SaveSettings();
//Create updatechecker
mUpdateChecker = new UpdateChecker(this);
refreshShortcuts();
//setup close thread and dialog
bCanClose = false;
mCloseThread = new MainWindowCloseThread();
connect(mCloseThread, SIGNAL(canClose()), this, SLOT(canClose()));
mCloseDialog = new CloseDialog(this);
mCpuWidget->mDisas->setFocus();
GuiAddLogMessage(QString().sprintf("thread id (GUI thread) %X\n", GetCurrentThreadId()).toUtf8().constData());
}
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();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::setTab(QWidget* widget)
{
for(int i = 0; i < mTabWidget->count(); i++)
if(mTabWidget->widget(i) == widget)
{
mTabWidget->setCurrentIndex(i);
break;
}
}
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->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->actionRun, ConfigShortcut("DebugRun"));
setGlobalShortcut(ui->actioneRun, ConfigShortcut("DebugeRun"));
setGlobalShortcut(ui->actionRunSelection, ConfigShortcut("DebugRunSelection"));
setGlobalShortcut(ui->actionPause, ConfigShortcut("DebugPause"));
setGlobalShortcut(ui->actionRestart, ConfigShortcut("DebugRestart"));
setGlobalShortcut(ui->actionClose, ConfigShortcut("DebugClose"));
setGlobalShortcut(ui->actionStepInto, ConfigShortcut("DebugStepInto"));
setGlobalShortcut(ui->actioneStepInto, ConfigShortcut("DebugeStepInfo"));
setGlobalShortcut(ui->actionStepOver, ConfigShortcut("DebugStepOver"));
setGlobalShortcut(ui->actioneStepOver, ConfigShortcut("DebugeStepOver"));
setGlobalShortcut(ui->actionRtr, ConfigShortcut("DebugRtr"));
setGlobalShortcut(ui->actioneRtr, ConfigShortcut("DebugeRtr"));
setGlobalShortcut(ui->actionCommand, ConfigShortcut("DebugCommand"));
setGlobalShortcut(ui->actionSkipNextInstruction, ConfigShortcut("DebugSkipNextInstruction"));
setGlobalShortcut(ui->actionScylla, ConfigShortcut("PluginsScylla"));
setGlobalShortcut(ui->actionSettings, ConfigShortcut("OptionsPreferences"));
setGlobalShortcut(ui->actionAppearance, ConfigShortcut("OptionsAppearance"));
setGlobalShortcut(ui->actionShortcuts, ConfigShortcut("OptionsShortcuts"));
setGlobalShortcut(ui->actionTopmost, ConfigShortcut("OptionsTopmost"));
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->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 = this->menuBar()->findChild<QMenu*>(QString::fromWCharArray(L"menuFile"));
if(fileMenu == NULL)
{
QMessageBox msg(QMessageBox::Critical, "Error!", "Failed to find menu!");
msg.setWindowIcon(QIcon(":/icons/images/compile-error.png"));
msg.setParent(this, Qt::Dialog);
msg.setWindowFlags(msg.windowFlags() & (~Qt::WindowContextHelpButtonHint));
msg.exec();
return;
}
fileMenu = fileMenu->findChild<QMenu*>(QString::fromWCharArray(L"menuRecent_Files"));
if(fileMenu == NULL)
{
QMessageBox msg(QMessageBox::Critical, "Error!", "Failed to find submenu!");
msg.setWindowIcon(QIcon(":/icons/images/compile-error.png"));
msg.setParent(this, Qt::Dialog);
msg.setWindowFlags(msg.windowFlags() & (~Qt::WindowContextHelpButtonHint));
msg.exec();
return;
}
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)
{
QString path;
if(index < mMRUList.size())
path = mMRUList.at(index);
return path;
}
void MainWindow::executeCommand()
{
QString wCmd = mCmdLineEdit->text();
DbgCmdExec(wCmd.toUtf8().constData());
mCmdLineEdit->addLineToHistory(wCmd);
mCmdLineEdit->setText("");
}
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::displayMemMapWidget()
{
showQWidgetTab(mMemMapView);
}
void MainWindow::displayLogWidget()
{
showQWidgetTab(mLogView);
}
void MainWindow::displayScriptWidget()
{
showQWidgetTab(mScriptView);
}
void MainWindow::displayAboutWidget()
{
#ifdef _WIN64
QString title = "About x64dbg";
#else
QString title = "About x32dbg";
#endif
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>"__DATE__", "__TIME__);
msg.setWindowIcon(QIcon(":/icons/images/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("init \"" + filename + "\"").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->mDisas->setFocus();
}
void MainWindow::execPause()
{
DbgCmdExec("pause");
}
void MainWindow::startScylla() //this is executed
{
DbgCmdExec("StartScylla");
}
void MainWindow::restartDebugging()
{
char filename[MAX_SETTING_SIZE] = "";
if(!mMRUList.size())
return;
strcpy_s(filename, mMRUList.at(0).toUtf8().constData());
if(DbgIsDebugging())
{
DbgCmdExec("stop"); //close current file (when present)
Sleep(400);
}
DbgCmdExec(QString().sprintf("init \"%s\"", filename).toUtf8().constData());
mCpuWidget->mDisas->setFocus();
}
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());
if(DbgIsDebugging())
DbgCmdExecDirect("stop");
QString cmd;
DbgCmdExec(cmd.sprintf("init \"%s\"", filename.toUtf8().constData()).toUtf8().constData());
pEvent->acceptProposedAction();
}
}
void MainWindow::updateWindowTitleSlot(QString filename)
{
if(filename.length())
setWindowTitle(QString(mWindowMainTitle) + QString(" - ") + filename);
else
setWindowTitle(QString(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::openSettings()
{
SettingsDialog settings(this);
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->mDisas->rvaToVa(mCpuWidget->mDisas->getInitialSelection()), sizeof(int_t) * 2, 16, QChar('0')).toUpper()).toUtf8().constData());
displayReferencesWidget();
}
void MainWindow::findModularCalls()
{
DbgCmdExec(QString("modcallfind " + QString("%1").arg(mCpuWidget->mDisas->rvaToVa(mCpuWidget->mDisas->getInitialSelection()), sizeof(int_t) * 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->mDisas->rvaToVa(mCpuWidget->mDisas->getInitialSelection()), sizeof(int_t) * 2, 16, QChar('0')).toUpper() + ", ss";
if(DbgCmdExecDirect(command.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())
{
QMessageBox msg(QMessageBox::Critical, "Error!", QString("Patches cannot be shown when not debugging..."));
msg.setWindowIcon(QIcon(":/icons/images/compile-error.png"));
msg.setWindowFlags(msg.windowFlags() & (~Qt::WindowContextHelpButtonHint));
msg.exec();
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::donate()
{
QMessageBox msg(QMessageBox::Information, "Donate", "All the money will go to x64dbg development.");
msg.setWindowIcon(QIcon(":/icons/images/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, "Report Bug", "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(QIcon(":/icons/images/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::displayAttach()
{
AttachDialog attach(this);
attach.exec();
mCpuWidget->mDisas->setFocus();
}
void MainWindow::detach()
{
DbgCmdExec("detach");
}
void MainWindow::changeCommandLine()
{
if(!DbgIsDebugging())
return;
LineEditDialog mLineEdit(this);
mLineEdit.setText("");
mLineEdit.setWindowTitle("Change Command Line");
mLineEdit.setWindowIcon(QIcon(":/icons/images/changeargs.png"));
size_t cbsize = 0;
char* cmdline = 0;
if(!DbgFunctions()->GetCmdline(0, &cbsize))
mLineEdit.setText("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()))
{
QMessageBox msg(QMessageBox::Warning, "Error", "Could not set command line!");
msg.setWindowIcon(QIcon(":/icons/images/compile-warning.png"));
msg.setParent(this, Qt::Dialog);
msg.setWindowFlags(msg.windowFlags() & (~Qt::WindowContextHelpButtonHint));
msg.exec();
}
else
{
DbgFunctions()->MemUpdateMap();
GuiUpdateMemoryView();
GuiAddStatusBarMessage(QString("New command line: " + mLineEdit.editText + "\n").toUtf8().constData());
}
}
void MainWindow::decompileAt(int_t start, int_t end)
{
DecompileAt(mSnowmanView, start, end);
}
void MainWindow::canClose()
{
bCanClose = true;
close();
}
void MainWindow::addQWidgetTab(QWidget* qWidget)
{
mTabWidget->addTab(qWidget, qWidget->windowIcon(), 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)();
}