fix: WinDbg plugin dynamic dbgeng loading, editor two-tone bg, UI polish

WinDbg plugin: load dbgeng.dll dynamically from Debugging Tools directory
instead of static linking (system dbgeng.dll lacks remote DebugConnect).
Copy tools dbghelp.dll next to exe so it loads before System32 version.
Add COM init on DbgEng thread, browse for tools dir, styled dialog.

Editor: derive darker background via theme.background.darker(115) for
visual depth between chrome and editor surfaces.

UI: global scrollbar styling, workspace accent bar 1px, pane tab font
from editor settings, workspace dock default width 128px.
This commit is contained in:
IChooseYou
2026-03-07 08:31:51 -07:00
committed by IChooseYou
parent 188c27c6e2
commit 0dc390ed86
7 changed files with 252 additions and 36 deletions

View File

@@ -151,6 +151,26 @@ target_link_libraries(Reclass PRIVATE
)
if(WIN32)
target_link_libraries(Reclass PRIVATE dbghelp dwmapi psapi raw_pdb)
# Copy Debugging Tools dbghelp.dll next to Reclass.exe so the Windows
# loader picks it up (app dir > System32). The system dbghelp.dll
# lacks StackWalk2 which the tools dbgeng.dll needs for remote debug.
set(_DBG_TOOLS_DIRS
"C:/Program Files (x86)/Windows Kits/10/Debuggers/x64"
"C:/Program Files/Windows Kits/10/Debuggers/x64")
foreach(_dir ${_DBG_TOOLS_DIRS})
if(EXISTS "${_dir}/dbghelp.dll")
foreach(_dll dbghelp.dll dbgcore.dll symsrv.dll)
if(EXISTS "${_dir}/${_dll}")
add_custom_command(TARGET Reclass POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${_dir}/${_dll}" $<TARGET_FILE_DIR:Reclass>
COMMENT "Copying ${_dll} from Debugging Tools")
endif()
endforeach()
break()
endif()
endforeach()
endif()
add_executable(ReclassMcpBridge tools/rcx-mcp-stdio.cpp)

View File

@@ -20,7 +20,7 @@ set(PLUGIN_SOURCES
add_library(WinDbgMemoryPlugin SHARED ${PLUGIN_SOURCES})
# Link Qt + DbgEng
target_link_libraries(WinDbgMemoryPlugin PRIVATE ${QT}::Widgets dbgeng ole32)
target_link_libraries(WinDbgMemoryPlugin PRIVATE ${QT}::Widgets ole32)
# Include directories
target_include_directories(WinDbgMemoryPlugin PRIVATE

View File

@@ -12,12 +12,99 @@
#include <QDebug>
#include <QClipboard>
#include <QGuiApplication>
#include <QFileDialog>
#include <QFileInfo>
#include <QSettings>
#ifdef _WIN32
#include <windows.h>
#include <initguid.h>
#include <dbgeng.h>
#pragma comment(lib, "dbgeng.lib")
// dbgeng.dll is loaded dynamically — see loadDbgEngTools()
// The system dbgeng.dll (C:\Windows\System32) does not support remote
// connections (DebugConnect returns 0x8007053d). The full version lives
// in the Debugging Tools for Windows directory. We load it dynamically
// so the plugin works without requiring the debugger tools on PATH.
static const char* const kDbgToolsDirs[] = {
"C:\\Program Files (x86)\\Windows Kits\\10\\Debuggers\\x64",
"C:\\Program Files\\Windows Kits\\10\\Debuggers\\x64",
};
static const char* const kSettingsKey = "WinDbgPlugin/DbgToolsDir";
typedef HRESULT (STDAPICALLTYPE *PFN_DebugConnect)(PCSTR, REFIID, PVOID*);
typedef HRESULT (STDAPICALLTYPE *PFN_DebugCreate)(REFIID, PVOID*);
static QString s_loadedDir;
static HMODULE s_hDbgEng = nullptr;
static HMODULE tryLoadFrom(const char* dir) {
SetDllDirectoryA(dir);
// Pre-load dependencies so the tools versions are used instead of
// the older System32 copies (e.g. dbghelp.dll without StackWalk2).
char path[MAX_PATH];
for (auto dep : {"dbghelp.dll", "dbgcore.dll", "symsrv.dll"}) {
snprintf(path, sizeof(path), "%s\\%s", dir, dep);
LoadLibraryA(path); // OK if missing
}
snprintf(path, sizeof(path), "%s\\dbgeng.dll", dir);
HMODULE h = LoadLibraryA(path);
if (h) {
s_loadedDir = QString::fromLocal8Bit(dir);
qDebug() << "[WinDbg] Loaded dbgeng.dll from" << dir;
}
return h;
}
static HMODULE loadDbgEngTools() {
if (s_hDbgEng) return s_hDbgEng;
// 1. Try user-configured path from settings
QSettings settings;
QString userDir = settings.value(kSettingsKey).toString();
if (!userDir.isEmpty()) {
s_hDbgEng = tryLoadFrom(userDir.toLocal8Bit().constData());
if (s_hDbgEng) return s_hDbgEng;
}
// 2. Try well-known install paths
for (auto dir : kDbgToolsDirs) {
s_hDbgEng = tryLoadFrom(dir);
if (s_hDbgEng) return s_hDbgEng;
}
SetDllDirectoryA(nullptr);
return nullptr;
}
static bool dbgToolsFound() {
loadDbgEngTools();
return s_hDbgEng != nullptr;
}
static PFN_DebugConnect getDebugConnect() {
static PFN_DebugConnect pfn = nullptr;
static bool tried = false;
if (!tried) {
tried = true;
HMODULE h = loadDbgEngTools();
if (h) pfn = (PFN_DebugConnect)GetProcAddress(h, "DebugConnect");
if (!pfn) qWarning() << "[WinDbg] DebugConnect not available — Debugging Tools not found";
}
return pfn;
}
static PFN_DebugCreate getDebugCreate() {
static PFN_DebugCreate pfn = nullptr;
static bool tried = false;
if (!tried) {
tried = true;
HMODULE h = loadDbgEngTools();
if (h) pfn = (PFN_DebugCreate)GetProcAddress(h, "DebugCreate");
if (!pfn) qWarning() << "[WinDbg] DebugCreate not available — Debugging Tools not found";
}
return pfn;
}
#endif
// ──────────────────────────────────────────────────────────────────────────
@@ -65,6 +152,9 @@ WinDbgMemoryProvider::WinDbgMemoryProvider(const QString& target)
dispatchToOwner([this, &target]() {
HRESULT hr;
// COM must be initialized on this thread for DbgEng
CoInitializeEx(nullptr, COINIT_MULTITHREADED);
qDebug() << "[WinDbg] Opening target:" << target
<< "on DbgEng thread" << QThread::currentThread();
@@ -72,9 +162,11 @@ WinDbgMemoryProvider::WinDbgMemoryProvider(const QString& target)
|| target.startsWith("npipe:", Qt::CaseInsensitive))
{
// ── Remote: connect to existing WinDbg debug server ──
auto pfnConnect = getDebugConnect();
if (!pfnConnect) { qWarning() << "[WinDbg] Debugging Tools required for remote connections"; return; }
QByteArray connUtf8 = target.toUtf8();
qDebug() << "[WinDbg] DebugConnect:" << target;
hr = DebugConnect(connUtf8.constData(), IID_IDebugClient, (void**)&m_client);
hr = pfnConnect(connUtf8.constData(), IID_IDebugClient, (void**)&m_client);
qDebug() << "[WinDbg] DebugConnect hr=" << Qt::hex << (unsigned long)hr
<< "client=" << (void*)m_client;
if (FAILED(hr) || !m_client) {
@@ -86,7 +178,9 @@ WinDbgMemoryProvider::WinDbgMemoryProvider(const QString& target)
else
{
// ── Local: create debug client for pid/dump ──
hr = DebugCreate(IID_IDebugClient, (void**)&m_client);
auto pfnCreate = getDebugCreate();
if (!pfnCreate) { qWarning() << "[WinDbg] Debugging Tools required"; return; }
hr = pfnCreate(IID_IDebugClient, (void**)&m_client);
qDebug() << "[WinDbg] DebugCreate hr=" << Qt::hex << (unsigned long)hr
<< "client=" << (void*)m_client;
if (FAILED(hr) || !m_client) {
@@ -239,6 +333,7 @@ WinDbgMemoryProvider::~WinDbgMemoryProvider()
m_client->DetachProcesses();
}
cleanup();
CoUninitialize();
});
} else {
// Thread not running — clean up directly (best-effort)
@@ -503,7 +598,7 @@ std::unique_ptr<rcx::Provider> WinDbgMemoryPlugin::createProvider(const QString&
*errorMsg = QString("Failed to connect to debug server.\n\n"
"Target: %1\n\n"
"Make sure WinDbg is running with a matching .server command\n"
"(e.g. .server tcp:port=5055) and the port/pipe is reachable.")
"(e.g. .server tcp:port=5056) and the port/pipe is reachable.")
.arg(target);
else if (target.startsWith("pid:", Qt::CaseInsensitive))
*errorMsg = QString("Failed to attach to process.\n\n"
@@ -532,7 +627,7 @@ bool WinDbgMemoryPlugin::selectTarget(QWidget* parent, QString* target)
{
QDialog dlg(parent);
dlg.setWindowTitle("WinDbg Settings");
dlg.resize(460, 300);
dlg.resize(480, 360);
QPalette dlgPal = qApp->palette();
dlg.setPalette(dlgPal);
@@ -540,17 +635,27 @@ bool WinDbgMemoryPlugin::selectTarget(QWidget* parent, QString* target)
auto* layout = new QVBoxLayout(&dlg);
QColor editBg = dlgPal.window().color().darker(115);
QString editSS = QStringLiteral(
"QLineEdit { background: %1; color: %2; border: 1px solid %3;"
" border-radius: 3px; padding: 4px 6px; }")
.arg(editBg.name(),
dlgPal.color(QPalette::Text).name(),
dlgPal.color(QPalette::Mid).name());
layout->addWidget(new QLabel(
"Connect to a running WinDbg debug server.\n"
"In WinDbg, run: .server tcp:port=5055\n\n"
"In WinDbg, run: .server tcp:port=5056\n\n"
"Non-invasive debug and dump files only.\n"
"Execution control (bp, g, t, p) is not supported."));
"Execution control (bp, g, t, p) is not supported.\n"
"WinDbg Classic is recommended."));
layout->addSpacing(8);
layout->addWidget(new QLabel("Connection string:"));
auto* connEdit = new QLineEdit;
connEdit->setPlaceholderText("tcp:Port=5055,Server=localhost");
connEdit->setText("tcp:Port=5055,Server=localhost");
connEdit->setPlaceholderText("tcp:Port=5056,Server=127.0.0.1");
connEdit->setText("tcp:Port=5056,Server=127.0.0.1");
connEdit->setStyleSheet(editSS);
layout->addWidget(connEdit);
layout->addSpacing(4);
@@ -574,8 +679,72 @@ bool WinDbgMemoryPlugin::selectTarget(QWidget* parent, QString* target)
layout->addLayout(row);
};
addExample(".server tcp:port=5055");
addExample(".server tcp:port=5056");
addExample(".server npipe:pipe=reclass");
// ── Debugger Tools status ──
layout->addSpacing(8);
#ifdef _WIN32
bool found = dbgToolsFound();
auto* toolsRow = new QHBoxLayout;
auto* toolsLabel = new QLabel;
if (found) {
toolsLabel->setText(QStringLiteral("Debugging Tools: %1").arg(s_loadedDir));
QPalette tp = dlgPal;
tp.setColor(QPalette::WindowText, dlgPal.color(QPalette::Disabled, QPalette::WindowText));
toolsLabel->setPalette(tp);
} else {
toolsLabel->setText("Debugging Tools: not found");
QPalette tp = dlgPal;
tp.setColor(QPalette::WindowText, QColor(220, 120, 80));
toolsLabel->setPalette(tp);
}
toolsLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
toolsRow->addWidget(toolsLabel, 1);
auto* browseBtn = new QPushButton("Browse...");
browseBtn->setFixedWidth(70);
browseBtn->setToolTip("Locate Debugging Tools for Windows directory (contains dbgeng.dll)");
QObject::connect(browseBtn, &QPushButton::clicked, [&dlg, toolsLabel, &dlgPal]() {
QString dir = QFileDialog::getExistingDirectory(&dlg,
"Locate Debugging Tools for Windows",
"C:\\Program Files (x86)\\Windows Kits\\10\\Debuggers");
if (dir.isEmpty()) return;
QString dllPath = dir + "/dbgeng.dll";
if (!QFileInfo::exists(dllPath)) {
QMessageBox::warning(&dlg, "Not Found",
"dbgeng.dll was not found in that directory.\n"
"Select the folder containing dbgeng.dll\n"
"(e.g. Debuggers\\x64).");
return;
}
QSettings settings;
settings.setValue(kSettingsKey, dir);
// Force reload on next use
s_hDbgEng = nullptr;
s_loadedDir.clear();
if (dbgToolsFound()) {
toolsLabel->setText(QStringLiteral("Debugging Tools: %1").arg(s_loadedDir));
QPalette tp = dlgPal;
tp.setColor(QPalette::WindowText, dlgPal.color(QPalette::Disabled, QPalette::WindowText));
toolsLabel->setPalette(tp);
}
});
toolsRow->addWidget(browseBtn);
layout->addLayout(toolsRow);
if (!found) {
auto* note = new QLabel(
"The system dbgeng.dll does not support remote connections.\n"
"Install Debugging Tools for Windows or use Browse to locate them.");
QPalette np = dlgPal;
np.setColor(QPalette::WindowText, dlgPal.color(QPalette::Disabled, QPalette::WindowText));
note->setPalette(np);
note->setWordWrap(true);
layout->addWidget(note);
}
#endif
layout->addStretch();
auto* btnLayout = new QHBoxLayout;

View File

@@ -837,8 +837,11 @@ void RcxEditor::allocateMarginStyles() {
}
void RcxEditor::applyTheme(const Theme& theme) {
// Editor uses a slightly darker background than chrome for visual depth
const QColor editorBg = theme.background.darker(115);
// Paper and text
m_sci->setPaper(theme.background);
m_sci->setPaper(editorBg);
m_sci->setColor(theme.text);
m_sci->setCaretForegroundColor(theme.text);
@@ -882,25 +885,25 @@ void RcxEditor::applyTheme(const Theme& theme) {
m_lexer->setColor(theme.text, QsciLexerCPP::Operator);
m_lexer->setColor(theme.syntaxType, QsciLexerCPP::GlobalClass);
for (int i = 0; i <= 127; i++)
m_lexer->setPaper(theme.background, i);
m_lexer->setPaper(editorBg, i);
// Margins
m_sci->setMarginsBackgroundColor(theme.background);
m_sci->setMarginsBackgroundColor(editorBg);
m_sci->setMarginsForegroundColor(theme.textFaint);
m_sci->setFoldMarginColors(theme.background, theme.background);
m_sci->setFoldMarginColors(editorBg, editorBg);
// Markers
m_sci->setMarkerBackgroundColor(theme.markerPtr, M_PTR0);
m_sci->setMarkerForegroundColor(theme.markerPtr, M_PTR0);
m_sci->setMarkerBackgroundColor(theme.background, M_CYCLE);
m_sci->setMarkerForegroundColor(theme.background, M_CYCLE);
m_sci->setMarkerBackgroundColor(editorBg, M_CYCLE);
m_sci->setMarkerForegroundColor(editorBg, M_CYCLE);
m_sci->setMarkerBackgroundColor(theme.markerError, M_ERR);
m_sci->setMarkerForegroundColor(theme.text, M_ERR);
m_sci->setMarkerBackgroundColor(theme.background, M_STRUCT_BG);
m_sci->setMarkerBackgroundColor(editorBg, M_STRUCT_BG);
m_sci->setMarkerForegroundColor(theme.text, M_STRUCT_BG);
m_sci->setMarkerBackgroundColor(theme.hover, M_HOVER);
m_sci->setMarkerBackgroundColor(theme.selected, M_SELECTED);
m_sci->setMarkerBackgroundColor(theme.background, M_CMD_ROW);
m_sci->setMarkerBackgroundColor(editorBg, M_CMD_ROW);
m_sci->setMarkerBackgroundColor(theme.indHoverSpan, M_ACCENT);
// Margin extended styles
@@ -911,7 +914,7 @@ void RcxEditor::applyTheme(const Theme& theme) {
m_sci->SendScintilla(QsciScintillaBase::SCI_STYLESETFORE,
abs, theme.textFaint);
m_sci->SendScintilla(QsciScintillaBase::SCI_STYLESETBACK,
abs, theme.background);
abs, editorBg);
}
}

View File

@@ -509,7 +509,19 @@ static void applyGlobalTheme(const rcx::Theme& theme) {
qApp->setPalette(pal);
qApp->setStyleSheet(QString());
// Global scrollbar styling — track matches control bg, handle is solid
qApp->setStyleSheet(QStringLiteral(
"QScrollBar:vertical { background: palette(window); width: 12px; margin: 0; border: none; }"
"QScrollBar::handle:vertical { background: %1; min-height: 20px; border: none; }"
"QScrollBar::handle:vertical:hover { background: %2; }"
"QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical { height: 0; }"
"QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical { background: none; }"
"QScrollBar:horizontal { background: palette(window); height: 12px; margin: 0; border: none; }"
"QScrollBar::handle:horizontal { background: %1; min-width: 20px; border: none; }"
"QScrollBar::handle:horizontal:hover { background: %2; }"
"QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal { width: 0; }"
"QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal { background: none; }")
.arg(theme.textFaint.name(), theme.textDim.name()));
}
class BorderOverlay : public QWidget {
@@ -1218,16 +1230,20 @@ MainWindow::SplitPane MainWindow::createSplitPane(TabState& tab) {
// Style to match the top dock tab bar, with accent line on selected tab
{
const auto& t = ThemeManager::instance().current();
QSettings s("Reclass", "Reclass");
QString editorFont = s.value("font", "JetBrains Mono").toString();
pane.tabWidget->setStyleSheet(QStringLiteral(
"QTabBar { border: none; }"
"QTabBar::tab {"
" background: %1; color: %2; padding: 0px 16px; border: none; border-radius: 0px; height: 24px;"
" font-family: '%7'; font-size: 10pt;"
"}"
"QTabBar::tab:selected { color: %3; background: %4;"
" border-top: 3px solid %6; padding-top: -3px; }"
"QTabBar::tab:hover { color: %3; background: %5; }")
.arg(t.background.name(), t.textMuted.name(), t.text.name(),
t.backgroundAlt.name(), t.hover.name(), t.indHoverSpan.name()));
t.backgroundAlt.name(), t.hover.name(), t.indHoverSpan.name(),
editorFont));
}
// Create editor via controller (parent = tabWidget for ownership)
@@ -2352,16 +2368,19 @@ void MainWindow::applyTheme(const Theme& theme) {
// Restyle per-pane view tab bars (Reclass / C++)
{
QString editorFont = QSettings("Reclass", "Reclass").value("font", "JetBrains Mono").toString();
QString paneTabStyle = QStringLiteral(
"QTabBar { border: none; }"
"QTabBar::tab {"
" background: %1; color: %2; padding: 0px 16px; border: none; border-radius: 0px; height: 24px;"
" font-family: '%7'; font-size: 10pt;"
"}"
"QTabBar::tab:selected { color: %3; background: %4;"
" border-top: 3px solid %6; padding-top: -3px; }"
"QTabBar::tab:hover { color: %3; background: %5; }")
.arg(theme.background.name(), theme.textMuted.name(), theme.text.name(),
theme.backgroundAlt.name(), theme.hover.name(), theme.indHoverSpan.name());
theme.backgroundAlt.name(), theme.hover.name(), theme.indHoverSpan.name(),
editorFont);
for (auto it = m_tabs.begin(); it != m_tabs.end(); ++it) {
for (auto& pane : it->panes) {
if (pane.tabWidget)
@@ -2498,10 +2517,11 @@ void MainWindow::applyTheme(const Theme& theme) {
lexer->setColor(theme.text, QsciLexerCPP::Identifier);
lexer->setColor(theme.syntaxPreproc, QsciLexerCPP::PreProcessor);
lexer->setColor(theme.text, QsciLexerCPP::Operator);
const QColor editorBg = theme.background.darker(115);
for (int i = 0; i <= 127; i++)
lexer->setPaper(theme.background, i);
lexer->setPaper(editorBg, i);
}
sci->setPaper(theme.background);
sci->setPaper(theme.background.darker(115));
sci->setColor(theme.text);
sci->setCaretForegroundColor(theme.text);
sci->setCaretLineBackgroundColor(theme.hover);
@@ -2631,6 +2651,9 @@ void MainWindow::setEditorFont(const QString& fontName) {
tabBar->update();
}
}
// Pane tab bars (Reclass / C++) — re-apply stylesheet with new font
// (stylesheet overrides setFont, so font must be in the CSS)
applyTheme(ThemeManager::instance().current());
}
}
@@ -2716,15 +2739,16 @@ void MainWindow::setupRenderedSci(QsciScintilla* sci) {
lexer->setColor(theme.text, QsciLexerCPP::Identifier);
lexer->setColor(theme.syntaxPreproc, QsciLexerCPP::PreProcessor);
lexer->setColor(theme.text, QsciLexerCPP::Operator);
const QColor editorBg = theme.background.darker(115);
for (int i = 0; i <= 127; i++) {
lexer->setPaper(theme.background, i);
lexer->setPaper(editorBg, i);
lexer->setFont(f, i);
}
sci->setLexer(lexer);
sci->setBraceMatching(QsciScintilla::NoBraceMatch);
// Colors applied AFTER setLexer() — the lexer resets these on attach
sci->setPaper(theme.background);
sci->setPaper(editorBg);
sci->setColor(theme.text);
sci->setCaretForegroundColor(theme.text);
sci->setCaretLineVisible(true);
@@ -2980,7 +3004,7 @@ void MainWindow::importFromSource() {
rebuildWorkspaceModel();
if (!m_docDocks.isEmpty()) {
splitDockWidget(m_workspaceDock, m_docDocks.first(), Qt::Horizontal);
resizeDocks({m_workspaceDock}, {220}, Qt::Horizontal);
resizeDocks({m_workspaceDock}, {128}, Qt::Horizontal);
}
m_workspaceDock->show();
setAppStatus(QStringLiteral("Imported %1 classes from source").arg(classCount));
@@ -3034,7 +3058,7 @@ void MainWindow::importPdb() {
rebuildWorkspaceModel();
if (!m_docDocks.isEmpty()) {
splitDockWidget(m_workspaceDock, m_docDocks.first(), Qt::Horizontal);
resizeDocks({m_workspaceDock}, {220}, Qt::Horizontal);
resizeDocks({m_workspaceDock}, {128}, Qt::Horizontal);
}
m_workspaceDock->show();
setAppStatus(QStringLiteral("Imported %1 classes from %2")
@@ -3225,7 +3249,7 @@ QDockWidget* MainWindow::project_open(const QString& path) {
rebuildWorkspaceModel();
if (!m_docDocks.isEmpty()) {
splitDockWidget(m_workspaceDock, m_docDocks.first(), Qt::Horizontal);
resizeDocks({m_workspaceDock}, {220}, Qt::Horizontal);
resizeDocks({m_workspaceDock}, {128}, Qt::Horizontal);
}
m_workspaceDock->show();
int classCount = 0;
@@ -3251,7 +3275,7 @@ QDockWidget* MainWindow::project_open(const QString& path) {
rebuildWorkspaceModel();
if (!m_docDocks.isEmpty()) {
splitDockWidget(m_workspaceDock, m_docDocks.first(), Qt::Horizontal);
resizeDocks({m_workspaceDock}, {220}, Qt::Horizontal);
resizeDocks({m_workspaceDock}, {128}, Qt::Horizontal);
}
m_workspaceDock->show();
addRecentFile(filePath);

View File

@@ -219,7 +219,7 @@ public:
if (opt.state & QStyle::State_Selected) {
painter->fillRect(opt.rect, m_selected);
// Left accent bar
painter->fillRect(QRect(opt.rect.x(), opt.rect.y(), 2, opt.rect.height()), m_accent);
painter->fillRect(QRect(opt.rect.x(), opt.rect.y(), 1, opt.rect.height()), m_accent);
} else if (opt.state & QStyle::State_MouseOver) {
painter->fillRect(opt.rect, m_hover);
}

View File

@@ -24,7 +24,7 @@
using namespace rcx;
static const char* CDB_PATH = "C:\\Program Files (x86)\\Windows Kits\\10\\Debuggers\\x64\\cdb.exe";
static const int DBG_PORT = 5055;
static const int DBG_PORT = 5056;
class TestWinDbgProvider : public QObject {
Q_OBJECT
@@ -132,7 +132,7 @@ private slots:
void initTestCase()
{
m_connString = QString("tcp:Port=%1,Server=localhost").arg(DBG_PORT);
m_connString = QString("tcp:Port=%1,Server=127.0.0.1").arg(DBG_PORT);
// If a debug server is already listening (e.g. WinDbg with .server),
// skip launching our own cdb.exe.
@@ -207,7 +207,7 @@ private slots:
void plugin_canHandle_tcp()
{
WinDbgMemoryPlugin plugin;
QVERIFY(plugin.canHandle("tcp:Port=5055,Server=localhost"));
QVERIFY(plugin.canHandle("tcp:Port=5056,Server=localhost"));
QVERIFY(plugin.canHandle("TCP:Port=1234,Server=10.0.0.1"));
}
@@ -608,7 +608,7 @@ private slots:
// ── Kernel/dump session tests ──
// Set WINDBG_KERNEL_CONN to a target string:
// "dump:F:/path/to/file.dmp" — open dump directly
// "tcp:Port=5055,Server=localhost" — connect to debug server
// "tcp:Port=5056,Server=localhost" — connect to debug server
// Set WINDBG_KERNEL_ADDR to a readable hex address (e.g. kernel base).
static QString kernelTarget()