Feature: Add MCP device management-control tools (kill/window/service/power)

Add P7 management-control tools behind a single McpManage flag (plus
McpReadonly=0): kill_process, operate_window, control_service and
power_action. The write tools run a ready->confirm lifecycle on their
sub-connection, using a new followUp/followUpSent field to tell the two
arrivals of the same TOKEN_*LIST apart; the write command and the follow-up
refresh command go out as two separate Send2Client calls, with a new
WaitSendIdle() (context.h / Server.h) draining the outbound buffer in between
so the same buffer is never WSASend'd concurrently.

McpSettingsDlg gains a "management operations" checkbox (IDC_MCP_MANAGE), the
main toolbar gains an MCP entry button, and en/de/zh-TW strings are synced.
power_action is fire-and-forget over the main connection (no confirmation).

Verified end-to-end against a real Windows 10/VMware client: kill_process
returns remaining:[] and operate_window/control_service return ok:true with
their confirm packet arriving after an HTTP split. Verification surfaced a
prerequisite parser bug, fixed separately in a72e6eb, where HeaderParser
latched m_bShouldUnmask FALSE on HTTP continuation chunks and dropped the
confirm packet.

Co-Authored-By: deepseek-v4-pro
This commit is contained in:
yuanyuanxianganddeepseek-v4-pro committed 2026-10-01 16:56:30 +02:00
1 parent a72e6eb391
commit 9eed43bc8d
13 files changed
+932 -10

No files matched your search

+33
View File
@@ -242,6 +242,34 @@ public:
// 收尾:擦会话 + 锁外 CancelIO 文件管理器/流式两条子链接(幂等)。
void ClearFileTransfer(uint64_t device_id);
// ===== P7:设备管理控制(kill_process / operate_window / control_service / power_action)=====
// 写工具复用 m_Pending 单飞行;followUp/followUpSent/subCtx 标记接管进度。
// 「就绪 token」与「确认 token」是同一 token(客户端子连接构造即回一包,写后再回一包),
// 故必须用 followUpSent 区分两次到达,不能靠 token 区分(与 list_registry 的 PATH/KEY 双 token 不同)。
void SetManageEnabled(bool enabled) { m_manageEnabled = enabled; }
bool IsManageEnabled() const { return m_manageEnabled; }
// 登记写挂起:与 BeginPending 同单飞行,另预填 followUp(写命令 payload)。
bool BeginPendingFollowUp(uint64_t device_id, const std::string& tool,
const std::vector<BYTE>& followUp);
// MessageHandle(TOKEN_PSLIST/TOKEN_WSLIST) 调用:命中且为写工具(kill_process/operate_window)
// 则接管子连接、下发 followUp(返回 true=已接管,调用方不 CancelIO);否则 false(回落 MFC
// 或按确认包走 TakeMainResponse)。
bool OnSystemReady(uint64_t device_id, context* subCtx);
// MessageHandle(TOKEN_SERVERLIST) 调用:命中且为 control_service 则接管、下发
// COMMAND_SERVICECONFIG(返回 true=已接管);否则 false。
bool OnServiceReady(uint64_t device_id, context* subCtx);
// 工具线程:等待写确认包(第二个同 token 包);超时/空数据清挂起并 CancelIO 子连接。
bool WaitPendingWrite(uint64_t device_id, std::vector<BYTE>& out, int timeoutMs);
// OfflineProc 调用:接管的子连接断开时清挂起(置 done 并清 subCtx,唤醒等待线程)。
// 不擦表(由 WaitPendingWrite 持有迭代器时自行擦除,防迭代器失效);清 subCtx 使
// 超时路径不会对已回收(连接池复用)的 context 误 CancelIO。
void OnManageSubClosed(context* subCtx);
// 安全配置(启动时由 CMy2015RemoteDlg 读 THIS_CFG 后设置)。
void SetReadonly(bool readonly) { m_readonly = readonly; }
void SetCmdWhitelist(const std::string& whitelist) { m_cmdWhitelist = whitelist; }
@@ -274,6 +302,10 @@ private:
bool pathDone = false; // list_registry:已收到 TOKEN_REG_PATH
bool keyDone = false; // list_registry:已收到 TOKEN_REG_KEY
bool done = false;
// ===== P7:写工具(kill_process / operate_window / control_service)接管进度 =====
std::vector<BYTE> followUp; // 接管后下发的写命令 payload(首字节 = 写命令)
bool followUpSent = false; // false=等子连接就绪(首包);true=已发写命令、等确认包
context* subCtx = nullptr; // 接管的子连接(超时/失败 CancelIO 用,防孤儿子连接)
};
std::mutex m_PendingMutex;
std::condition_variable m_PendingCv;
@@ -348,6 +380,7 @@ private:
bool m_terminalEnabled = false; // 持久终端开关(默认关;要求 m_readonly=false)
bool m_remoteControlEnabled = false; // 远程控制开关(默认关;要求 m_readonly=false)
bool m_fileTransferEnabled = false; // 文件传输开关(默认关;download_file)
bool m_manageEnabled = false; // P7 管理控制开关(默认关;要求 m_readonly=false)
};
// 全局访问器(仿 WebService(),见 WebService.h 末尾)