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

150 lines
6.2 KiB
C++

#include "AttachDialog.h"
#include "ui_AttachDialog.h"
#include "StdIconSearchListView.h"
#include "StdTable.h"
#include <QMenu>
#include <QMessageBox>
#include <QFileInfo>
AttachDialog::AttachDialog(QWidget* parent) : QDialog(parent), ui(new Ui::AttachDialog)
{
ui->setupUi(this);
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
// Setup actions/shortcuts
//
// Enter key as shortcut for "Attach"
mAttachAction = new QAction(DIcon("attach"), tr("Attach"), this);
mAttachAction->setShortcut(QKeySequence("enter"));
connect(mAttachAction, SIGNAL(triggered()), this, SLOT(on_btnAttach_clicked()));
// F5 as shortcut to refresh view
mRefreshAction = new QAction(DIcon("arrow-restart"), tr("Refresh"), this);
mRefreshAction->setShortcut(ConfigShortcut("ActionRefresh"));
ui->btnRefresh->setText(tr("Refresh") + QString(" (%1)").arg(mRefreshAction->shortcut().toString()));
connect(mRefreshAction, SIGNAL(triggered()), this, SLOT(refresh()));
this->addAction(mRefreshAction);
connect(ui->btnRefresh, SIGNAL(clicked()), this, SLOT(refresh()));
// Create search view (regex disabled)
mSearchListView = new StdIconSearchListView(this, false, false);
mSearchListView->mSearchStartCol = 0;
ui->verticalLayout->insertWidget(0, mSearchListView);
//setup process list
int charwidth = mSearchListView->getCharWidth();
mSearchListView->addColumnAt(charwidth * sizeof(int) * 2 + 8, tr("PID"), true, QString(), ConfigBool("Gui", "PidTidInHex") ? StdTable::SortBy::AsHex : StdTable::SortBy::AsInt);
mSearchListView->addColumnAt(150, tr("Name"), true);
mSearchListView->addColumnAt(300, tr("Title"), true);
mSearchListView->addColumnAt(500, tr("Path"), true);
mSearchListView->addColumnAt(800, tr("Command Line Arguments"), true);
mSearchListView->setIconColumn(1); // Name
mSearchListView->setDrawDebugOnly(false);
connect(mSearchListView, SIGNAL(enterPressedSignal()), this, SLOT(on_btnAttach_clicked()));
connect(mSearchListView, SIGNAL(listContextMenuSignal(QMenu*)), this, SLOT(processListContextMenu(QMenu*)));
// Highlight the search box
mSearchListView->mCurList->setFocus();
Config()->setupWindowPos(this);
// Populate the process list atleast once
refresh();
}
AttachDialog::~AttachDialog()
{
Config()->saveWindowPos(this);
delete ui;
}
void AttachDialog::refresh()
{
mSearchListView->setRowCount(0);
DBGPROCESSINFO* entries;
int count;
if(!DbgFunctions()->GetProcessList(&entries, &count))
return;
mSearchListView->setRowCount(count);
for(int i = 0; i < count; i++)
{
QFileInfo fi(entries[i].szExeFile);
mSearchListView->setCellContent(i, ColPid, QString().sprintf(ConfigBool("Gui", "PidTidInHex") ? "%.8X" : "%u", entries[i].dwProcessId));
mSearchListView->setCellContent(i, ColName, fi.baseName());
mSearchListView->setCellContent(i, ColTitle, QString(entries[i].szExeMainWindowTitle));
mSearchListView->setCellContent(i, ColPath, QString(entries[i].szExeFile));
mSearchListView->setCellContent(i, ColCommandLine, QString(entries[i].szExeArgs));
mSearchListView->setRowIcon(i, getFileIcon(QString(entries[i].szExeFile)));
}
mSearchListView->reloadData();
mSearchListView->refreshSearchList();
}
void AttachDialog::on_btnAttach_clicked()
{
QString pid = mSearchListView->mCurList->getCellContent(mSearchListView->mCurList->getInitialSelection(), ColPid);
DbgCmdExec(QString("attach %1%2").arg(ConfigBool("Gui", "PidTidInHex") ? "" : ".").arg(pid));
accept();
}
void AttachDialog::on_btnFindWindow_clicked()
{
QString windowText;
retryFindWindow:
if(!SimpleInputBox(this, tr("Find Window"), windowText, windowText, tr("Enter window title or class name here.")))
return;
HWND hWndFound = FindWindowW(NULL, reinterpret_cast<LPCWSTR>(windowText.utf16())); //Window Title first
if(hWndFound == NULL)
hWndFound = FindWindowW(reinterpret_cast<LPCWSTR>(windowText.utf16()), NULL); //Then try window class name
if(hWndFound == NULL)
{
QMessageBox retryDialog(QMessageBox::Critical, tr("Find Window"), tr("Cannot find window \"%1\". Retry?").arg(windowText), QMessageBox::Cancel | QMessageBox::Retry, this);
retryDialog.setWindowIcon(DIcon("compile-error"));
if(retryDialog.exec() == QMessageBox::Retry)
goto retryFindWindow;
}
else
{
DWORD pid, tid;
if(tid = GetWindowThreadProcessId(hWndFound, &pid))
{
refresh();
QString pidText = QString().sprintf(ConfigBool("Gui", "PidTidInHex") ? "%.8X" : "%u", pid);
bool found = false;
for(int i = 0; i < mSearchListView->mCurList->getRowCount(); i++)
{
if(mSearchListView->mCurList->getCellContent(i, ColPid) == pidText)
{
mSearchListView->mCurList->setSingleSelection(i);
found = true;
break;
}
}
if(!found)
{
QMessageBox hiddenProcessDialog(QMessageBox::Question, tr("Find Window"),
tr("The PID of the window \"%1\" is %2, but it's hidden in the process list. Do you want to attach to it immediately?").arg(windowText).arg(pidText),
QMessageBox::Yes | QMessageBox::No, this);
if(hiddenProcessDialog.exec() == QMessageBox::Yes)
{
DbgCmdExec(QString("attach %1").arg(pid, 0, 16));
accept();
}
}
}
else
SimpleErrorBox(this, tr("Find Window"), tr("GetWindowThreadProcessId() failed. Cannot get the PID of the window."));
}
}
void AttachDialog::processListContextMenu(QMenu* wMenu)
{
// Don't show menu options if nothing is listed
if(!mSearchListView->mCurList->getRowCount())
return;
wMenu->addAction(mAttachAction);
wMenu->addAction(mRefreshAction);
}