Feature: Add list_registry MCP tool

Add a read-only list_registry MCP tool for querying a remote Windows
host's registry. An empty path returns the five root keys; a path such as
HKEY_LOCAL_MACHINE plus subkeys returns that key's immediate subkeys and
values (name, type, and formatted data).

Client side: enumerate with KEY_READ instead of KEY_ALL_ACCESS and map the
full value-type set (REG_SZ, REG_DWORD, REG_BINARY, REG_EXPAND_SZ,
REG_MULTI_SZ, REG_QWORD, REG_NONE) so unknown types are no longer
mis-reported as REG_SZ. The registry manager now always sends both the
TOKEN_REG_PATH and TOKEN_REG_KEY packets (an empty packet when a part is
empty), making the two-packet reply deterministic for the server.

Server side: add the three-phase flow (COMMAND_REGEDIT, COMMAND_REG_FIND,
then PATH plus KEY) with per-host pending state, parse the fixed-width
wire format with bounds checks, format value data for JSON, and guard
registry paths against exceeding MAX_PATH to protect the client stack.

Co-Authored-By: deepseek-v4-pro
This commit is contained in:
yuanyuanxiang
2026-08-23 10:37:55 +02:00
parent 8815c4f896
commit 8bd6f3b60a
5 changed files with 508 additions and 19 deletions

View File

@@ -6458,9 +6458,33 @@ VOID CMy2015RemoteDlg::MessageHandle(CONTEXT_OBJECT* ContextObject)
break;
}
case TOKEN_REGEDIT: { // 注册表管理【x】
// P3MCP 挂起时接管。TOKEN_REGEDIT 是客户端子链接构造即发CRegisterManager 构造),
// 命中则下发 COMMAND_REG_FIND 并保持子链接(等 TOKEN_REG_PATH/KEY不打开 MFC 对话框。
uint64_t devId = ContextObject->GetClientID();
if (McpServer().IsPending(devId) && McpServer().OnRegeditReady(devId, ContextObject))
break;
g_2015RemoteDlg->SendMessage(WM_OPENREGISTERDIALOG, 0, (LPARAM)ContextObject);
break;
}
case TOKEN_REG_PATH: { // 注册表子键【P3仅 MCP 无头路径会到达】
// 正常注册表管理由 RegisterDlg 的 hDlg 接管TOKEN_REG_PATH 不进此分派;
// 到达此处只有 MCP 无头查询一种情形。命中则存子键包并保持子链接(等 TOKEN_REG_KEY
uint64_t devId = ContextObject->GetClientID();
if (McpServer().IsPending(devId)) {
McpServer().TakeRegPath(devId, szBuffer, len);
} else {
ContextObject->CancelIO(); // 迟到/游离包,关闭子链接避免泄漏
}
break;
}
case TOKEN_REG_KEY: { // 注册表值【P3仅 MCP 无头路径会到达】
uint64_t devId = ContextObject->GetClientID();
if (McpServer().IsPending(devId)) {
McpServer().TakeRegKey(devId, szBuffer, len);
}
ContextObject->CancelIO(); // 值包为最后包,无论命中与否用完即关
break;
}
case TOKEN_SERVERLIST: { // 服务管理【x】
// P3MCP 挂起时接管。服务列表为一次性子链接回传CServicesManager 构造即发),
// 取走即 CancelIO 关子链接(无 MFC 对话框续用该子链接)。