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
90 lines
3.4 KiB
C++
90 lines
3.4 KiB
C++
#pragma once
|
|
|
|
#include "common/header.h"
|
|
#include "common/commands.h"
|
|
#include <atlstr.h>
|
|
|
|
enum {
|
|
ONLINELIST_IP = 0, // IP的列顺序
|
|
ONLINELIST_ADDR, // 地址
|
|
ONLINELIST_LOCATION, // 地理位置
|
|
ONLINELIST_COMPUTER_NAME, // 计算机名/备注
|
|
ONLINELIST_OS, // 操作系统
|
|
ONLINELIST_CPU, // CPU
|
|
ONLINELIST_VIDEO, // 摄像头(有无)
|
|
ONLINELIST_PING, // PING(对方的网速)
|
|
ONLINELIST_VERSION, // 版本信息
|
|
ONLINELIST_INSTALLTIME, // 安装时间
|
|
ONLINELIST_LOGINTIME, // 活动窗口
|
|
ONLINELIST_CLIENTTYPE, // 客户端类型
|
|
ONLINELIST_PATH, // 文件路径
|
|
ONLINELIST_PUBIP,
|
|
ONLINELIST_STARTTIME,
|
|
ONLINELIST_CAPABILITIES, // 客户端能力位
|
|
ONLINELIST_PRIVILEGE, // 权限级别 (SYSTEM/Admin/User)
|
|
ONLINELIST_MAX,
|
|
};
|
|
|
|
class context
|
|
{
|
|
public:
|
|
// 纯虚函数
|
|
virtual VOID InitMember(SOCKET s, VOID* svr) = 0;
|
|
virtual BOOL Send2Client(PBYTE szBuffer, ULONG ulOriginalLength) = 0;
|
|
virtual CString GetClientData(int index)const = 0;
|
|
virtual void GetAdditionalData(CString(&s)[RES_MAX]) const = 0;
|
|
virtual CString GetAdditionalData(int index) const = 0;
|
|
virtual uint64_t GetClientID() const = 0;
|
|
virtual std::string GetPeerName() const = 0;
|
|
virtual int GetPort() const = 0;
|
|
virtual std::string GetProtocol() const = 0;
|
|
virtual int GetServerPort() const = 0;
|
|
virtual FlagType GetFlagType() const = 0;
|
|
virtual std::string GetGroupName() const = 0;
|
|
virtual uint64_t GetAliveTime()const = 0;
|
|
virtual void SetLastHeartbeat(uint64_t time) = 0;
|
|
virtual uint64_t GetLastHeartbeat() = 0;
|
|
virtual void CancelIO() = 0;
|
|
virtual std::string GetMasterID() const = 0;
|
|
public:
|
|
virtual ~context() {}
|
|
virtual void Destroy() {}
|
|
virtual BOOL IsLogin() const
|
|
{
|
|
return TRUE;
|
|
}
|
|
virtual void SetGroupName(const std::string& group) {}
|
|
|
|
// 等待本连接待发送缓冲排空(用于「发写命令 → 补发刷新命令」的背靠背发送:
|
|
// 两次 Send2Client 会对同一发送缓冲并发 WSASend,造成竞态/丢包)。非 IOCP
|
|
// 服务端无异步发送缓冲,默认立即返回 true;CONTEXT_OBJECT 覆写为轮询发送缓冲
|
|
// 归零直到排空或超时。
|
|
virtual bool WaitSendIdle(int timeoutMs)
|
|
{
|
|
(void)timeoutMs;
|
|
return true;
|
|
}
|
|
|
|
// 检查客户端是否支持 V2 文件传输
|
|
bool SupportsFileV2() const {
|
|
CString caps = GetClientData(ONLINELIST_CAPABILITIES);
|
|
if (caps.IsEmpty()) return false;
|
|
return (strtoul(caps.GetString(), nullptr, 16) & CLIENT_CAP_V2) != 0;
|
|
}
|
|
|
|
// 检查客户端是否使用 UTF-8 协议字符串编码。
|
|
// 无此能力位的老客户端:服务端按 CP_ACP(CP936,覆盖 95% 的简中/英语 ASCII 老客户端)解读。
|
|
bool SupportsUtf8() const {
|
|
CString caps = GetClientData(ONLINELIST_CAPABILITIES);
|
|
if (caps.IsEmpty()) return false;
|
|
return (strtoul(caps.GetString(), nullptr, 16) & CLIENT_CAP_UTF8) != 0;
|
|
}
|
|
|
|
// 检查客户端是否支持屏幕预览(双击主机时拉缩略图)。
|
|
bool SupportsScreenPreview() const {
|
|
CString caps = GetClientData(ONLINELIST_CAPABILITIES);
|
|
if (caps.IsEmpty()) return false;
|
|
return (strtoul(caps.GetString(), nullptr, 16) & CLIENT_CAP_SCREEN_PREVIEW) != 0;
|
|
}
|
|
};
|