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

@@ -83,6 +83,21 @@ public:
// 等 TOKEN_FILE_LIST调用方不关子链接
bool OnDriveList(uint64_t device_id, context* subCtx, const BYTE* buf, ULONG len);
// ===== P3list_registry注册表查询三阶段COMMAND_REGEDIT → TOKEN_REGEDIT →
// COMMAND_REG_FIND → TOKEN_REG_PATH + TOKEN_REG_KEY=====
// MessageHandle(TOKEN_REGEDIT) 调用:挂起命中且为 list_registry 则下发 COMMAND_REG_FIND
// 并返回 true接管子链接不打开 MFC 对话框);否则 false回落 MFC
bool OnRegeditReady(uint64_t device_id, context* subCtx);
// MessageHandle(TOKEN_REG_PATH / TOKEN_REG_KEY) 调用:两包都到齐后置 done 并唤醒等待者。
void TakeRegPath(uint64_t device_id, const BYTE* data, ULONG len);
void TakeRegKey(uint64_t device_id, const BYTE* data, ULONG len);
// 工具线程:等待注册表两包(子键 + 值);成功返回 true 并把两包分别写入 out超时返回 false。
bool WaitPendingRegistry(uint64_t device_id, std::vector<BYTE>& subkeys,
std::vector<BYTE>& values, int timeoutMs);
private:
CMcpServer();
~CMcpServer();
@@ -101,9 +116,13 @@ private:
// 挂起请求注册表(受 m_PendingMutex 保护,键 = device_id
struct PendingRequest {
std::string tool;
std::string path; // list_files目录路径空 = 只列盘
std::string path; // list_files目录路径list_registryrootToken(1B)+相对子键路径
uint16_t expectedReqId = 0; // get_screenshot期望的预览 reqId0 = 未设置)
std::vector<BYTE> data;
std::vector<BYTE> regPath; // list_registryTOKEN_REG_PATH 子键包(含 token 字节)
std::vector<BYTE> regKey; // list_registryTOKEN_REG_KEY 值包(含 token 字节)
bool pathDone = false; // list_registry已收到 TOKEN_REG_PATH
bool keyDone = false; // list_registry已收到 TOKEN_REG_KEY
bool done = false;
};
std::mutex m_PendingMutex;