mirror of
https://github.com/yuanyuanxiang/SimpleRemoter.git
synced 2026-01-22 07:14:15 +08:00
Fix: Copy text between master and client need a delay
This commit is contained in:
@@ -457,7 +457,7 @@ VOID CScreenManager::OnReceive(PBYTE szBuffer, ULONG ulLength)
|
|||||||
SendData(szBuffer, sizeof(szBuffer));
|
SendData(szBuffer, sizeof(szBuffer));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
SendClientClipboard();
|
SendClientClipboard(ulLength > 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case COMMAND_SCREEN_SET_CLIPBOARD: {
|
case COMMAND_SCREEN_SET_CLIPBOARD: {
|
||||||
@@ -531,26 +531,48 @@ VOID CScreenManager::UpdateClientClipboard(char *szBuffer, ULONG ulLength)
|
|||||||
CloseClipboard();
|
CloseClipboard();
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID CScreenManager::SendClientClipboard()
|
VOID CScreenManager::SendClientClipboard(BOOL fast)
|
||||||
{
|
{
|
||||||
if (!::OpenClipboard(NULL)) //打开剪切板设备
|
if (!::OpenClipboard(NULL))
|
||||||
return;
|
return;
|
||||||
HGLOBAL hGlobal = GetClipboardData(CF_TEXT); //代表着一个内存
|
|
||||||
if (hGlobal == NULL) {
|
|
||||||
::CloseClipboard();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
size_t iPacketLength = GlobalSize(hGlobal) + 1;
|
|
||||||
char* szClipboardVirtualAddress = (LPSTR) GlobalLock(hGlobal); //锁定
|
|
||||||
LPBYTE szBuffer = new BYTE[iPacketLength];
|
|
||||||
|
|
||||||
|
// 改为获取 Unicode 格式
|
||||||
|
HGLOBAL hGlobal = GetClipboardData(CF_UNICODETEXT);
|
||||||
|
if (hGlobal == NULL) {
|
||||||
|
::CloseClipboard();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
szBuffer[0] = TOKEN_CLIPBOARD_TEXT;
|
wchar_t* pWideStr = (wchar_t*)GlobalLock(hGlobal);
|
||||||
memcpy(szBuffer + 1, szClipboardVirtualAddress, iPacketLength - 1);
|
if (pWideStr == NULL) {
|
||||||
::GlobalUnlock(hGlobal);
|
::CloseClipboard();
|
||||||
::CloseClipboard();
|
return;
|
||||||
m_ClientObject->Send2Server((char*)szBuffer, iPacketLength);
|
}
|
||||||
delete[] szBuffer;
|
|
||||||
|
// Unicode 转 UTF-8
|
||||||
|
int utf8Len = WideCharToMultiByte(CP_UTF8, 0, pWideStr, -1, NULL, 0, NULL, NULL);
|
||||||
|
if (utf8Len <= 0) {
|
||||||
|
GlobalUnlock(hGlobal);
|
||||||
|
::CloseClipboard();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fast && utf8Len > 200 * 1024) {
|
||||||
|
Mprintf("剪切板文本太长, 无法快速拷贝: %d\n", utf8Len);
|
||||||
|
GlobalUnlock(hGlobal);
|
||||||
|
::CloseClipboard();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LPBYTE szBuffer = new BYTE[utf8Len + 1];
|
||||||
|
szBuffer[0] = TOKEN_CLIPBOARD_TEXT;
|
||||||
|
WideCharToMultiByte(CP_UTF8, 0, pWideStr, -1, (char*)(szBuffer + 1), utf8Len, NULL, NULL);
|
||||||
|
|
||||||
|
GlobalUnlock(hGlobal);
|
||||||
|
::CloseClipboard();
|
||||||
|
|
||||||
|
m_ClientObject->Send2Server((char*)szBuffer, utf8Len + 1);
|
||||||
|
delete[] szBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ public:
|
|||||||
std::string m_DesktopID;
|
std::string m_DesktopID;
|
||||||
BOOL m_bIsWorking;
|
BOOL m_bIsWorking;
|
||||||
BOOL m_bIsBlockInput;
|
BOOL m_bIsBlockInput;
|
||||||
VOID SendClientClipboard();
|
VOID SendClientClipboard(BOOL fast);
|
||||||
VOID UpdateClientClipboard(char *szBuffer, ULONG ulLength);
|
VOID UpdateClientClipboard(char *szBuffer, ULONG ulLength);
|
||||||
|
|
||||||
std::string m_hash;
|
std::string m_hash;
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -134,21 +134,21 @@ static BOOL HandleServiceCommandLine()
|
|||||||
// -service: 作为服务运行
|
// -service: 作为服务运行
|
||||||
if (cmdLine.Find(_T("-service")) != -1) {
|
if (cmdLine.Find(_T("-service")) != -1) {
|
||||||
int r = ServerService_Run();
|
int r = ServerService_Run();
|
||||||
Mprintf("[HandleServiceCommandLine] ServerService_Run %s", r ? "failed" : "succeed");
|
Mprintf("[HandleServiceCommandLine] ServerService_Run %s\n", r ? "failed" : "succeed");
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// -install: 安装服务
|
// -install: 安装服务
|
||||||
if (cmdLine.Find(_T("-install")) != -1) {
|
if (cmdLine.Find(_T("-install")) != -1) {
|
||||||
BOOL r = ServerService_Install();
|
BOOL r = ServerService_Install();
|
||||||
Mprintf("[HandleServiceCommandLine] ServerService_Install %s", !r ? "failed" : "succeed");
|
Mprintf("[HandleServiceCommandLine] ServerService_Install %s\n", !r ? "failed" : "succeed");
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// -uninstall: 卸载服务
|
// -uninstall: 卸载服务
|
||||||
if (cmdLine.Find(_T("-uninstall")) != -1) {
|
if (cmdLine.Find(_T("-uninstall")) != -1) {
|
||||||
BOOL r = ServerService_Uninstall();
|
BOOL r = ServerService_Uninstall();
|
||||||
Mprintf("[HandleServiceCommandLine] ServerService_Uninstall %s", !r ? "failed" : "succeed");
|
Mprintf("[HandleServiceCommandLine] ServerService_Uninstall %s\n", !r ? "failed" : "succeed");
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,7 +156,7 @@ static BOOL HandleServiceCommandLine()
|
|||||||
// 此模式下正常运行GUI,但使用不同的互斥量名称避免冲突
|
// 此模式下正常运行GUI,但使用不同的互斥量名称避免冲突
|
||||||
if (cmdLine.Find(_T("-agent")) != -1) {
|
if (cmdLine.Find(_T("-agent")) != -1) {
|
||||||
// 继续正常启动GUI,但标记为代理模式
|
// 继续正常启动GUI,但标记为代理模式
|
||||||
Mprintf("[HandleServiceCommandLine] Run service agent: '%s'", cmdLine.GetString());
|
Mprintf("[HandleServiceCommandLine] Run service agent: '%s'\n", cmdLine.GetString());
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,7 +165,7 @@ static BOOL HandleServiceCommandLine()
|
|||||||
BOOL running = FALSE;
|
BOOL running = FALSE;
|
||||||
char servicePath[MAX_PATH] = { 0 };
|
char servicePath[MAX_PATH] = { 0 };
|
||||||
BOOL r = ServerService_CheckStatus(®istered, &running, servicePath, MAX_PATH);
|
BOOL r = ServerService_CheckStatus(®istered, &running, servicePath, MAX_PATH);
|
||||||
Mprintf("[HandleServiceCommandLine] ServerService_CheckStatus %s", !r ? "failed" : "succeed");
|
Mprintf("[HandleServiceCommandLine] ServerService_CheckStatus %s\n", !r ? "failed" : "succeed");
|
||||||
|
|
||||||
char curPath[MAX_PATH];
|
char curPath[MAX_PATH];
|
||||||
GetModuleFileNameA(NULL, curPath, MAX_PATH);
|
GetModuleFileNameA(NULL, curPath, MAX_PATH);
|
||||||
@@ -242,13 +242,13 @@ BOOL CMy2015RemoteApp::InitInstance()
|
|||||||
char curFile[MAX_PATH] = { 0 };
|
char curFile[MAX_PATH] = { 0 };
|
||||||
GetModuleFileNameA(NULL, curFile, MAX_PATH);
|
GetModuleFileNameA(NULL, curFile, MAX_PATH);
|
||||||
if (!IsRunningAsAdmin() && LaunchAsAdmin(curFile, "runas")) {
|
if (!IsRunningAsAdmin() && LaunchAsAdmin(curFile, "runas")) {
|
||||||
Mprintf("[InitInstance] 程序没有管理员权限,用户选择以管理员身份重新运行。");
|
Mprintf("[InitInstance] 程序没有管理员权限,用户选择以管理员身份重新运行。\n");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 首先处理服务命令行参数
|
// 首先处理服务命令行参数
|
||||||
if (HandleServiceCommandLine()) {
|
if (HandleServiceCommandLine()) {
|
||||||
Mprintf("[InitInstance] 服务命令已处理,退出。");
|
Mprintf("[InitInstance] 服务命令已处理,退出。\n");
|
||||||
return FALSE; // 服务命令已处理,退出
|
return FALSE; // 服务命令已处理,退出
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,7 +268,7 @@ BOOL CMy2015RemoteApp::InitInstance()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Mprintf("[InitInstance] 主控程序启动运行。");
|
Mprintf("[InitInstance] 主控程序启动运行。\n");
|
||||||
SetUnhandledExceptionFilter(&whenbuged);
|
SetUnhandledExceptionFilter(&whenbuged);
|
||||||
|
|
||||||
// 创建并显示启动画面
|
// 创建并显示启动画面
|
||||||
@@ -349,10 +349,11 @@ int CMy2015RemoteApp::ExitInstance()
|
|||||||
// 只有在代理模式退出时才停止服务
|
// 只有在代理模式退出时才停止服务
|
||||||
if (IsAgentMode()) {
|
if (IsAgentMode()) {
|
||||||
ServerService_Stop();
|
ServerService_Stop();
|
||||||
Mprintf("[InitInstance] 主控程序为代理模式,停止服务。");
|
Mprintf("[InitInstance] 主控程序为代理模式,停止服务。\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
Mprintf("[InitInstance] 主控程序退出运行。");
|
Mprintf("[InitInstance] 主控程序退出运行。\n");
|
||||||
|
Sleep(1000);
|
||||||
|
|
||||||
return CWinApp::ExitInstance();
|
return CWinApp::ExitInstance();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3809,53 +3809,56 @@ void CMy2015RemoteDlg::OnDestroy()
|
|||||||
|
|
||||||
CString GetClipboardText()
|
CString GetClipboardText()
|
||||||
{
|
{
|
||||||
if (!OpenClipboard(nullptr)) return _T("");
|
if (!OpenClipboard(nullptr)) return _T("");
|
||||||
|
|
||||||
|
CString strText;
|
||||||
|
|
||||||
|
// 优先获取 Unicode 格式
|
||||||
|
HANDLE hData = GetClipboardData(CF_UNICODETEXT);
|
||||||
|
if (hData) {
|
||||||
|
wchar_t* pszText = static_cast<wchar_t*>(GlobalLock(hData));
|
||||||
|
if (pszText) {
|
||||||
#ifdef UNICODE
|
#ifdef UNICODE
|
||||||
HANDLE hData = GetClipboardData(CF_UNICODETEXT);
|
strText = pszText;
|
||||||
#else
|
#else
|
||||||
HANDLE hData = GetClipboardData(CF_TEXT);
|
// 将 Unicode 转换为多字节(使用系统默认代码页)
|
||||||
|
int len = WideCharToMultiByte(CP_ACP, 0, pszText, -1, nullptr, 0, nullptr, nullptr);
|
||||||
|
if (len > 0) {
|
||||||
|
char* pBuf = strText.GetBuffer(len);
|
||||||
|
WideCharToMultiByte(CP_ACP, 0, pszText, -1, pBuf, len, nullptr, nullptr);
|
||||||
|
strText.ReleaseBuffer();
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
GlobalUnlock(hData);
|
||||||
|
}
|
||||||
|
|
||||||
if (!hData) {
|
CloseClipboard();
|
||||||
CloseClipboard();
|
return strText;
|
||||||
return _T("");
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef UNICODE
|
|
||||||
wchar_t* pszText = static_cast<wchar_t*>(GlobalLock(hData));
|
|
||||||
#else
|
|
||||||
char* pszText = static_cast<char*>(GlobalLock(hData));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
CString strText = pszText ? pszText : _T("");
|
|
||||||
GlobalUnlock(hData);
|
|
||||||
CloseClipboard();
|
|
||||||
return strText;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetClipboardText(const CString& text)
|
void SetClipboardText(const char* utf8Text)
|
||||||
{
|
{
|
||||||
if (!OpenClipboard(nullptr)) return;
|
if (!OpenClipboard(nullptr)) return;
|
||||||
EmptyClipboard();
|
EmptyClipboard();
|
||||||
|
|
||||||
#ifdef UNICODE
|
// UTF-8 转 Unicode
|
||||||
HGLOBAL hGlob = GlobalAlloc(GMEM_MOVEABLE, (text.GetLength() + 1) * sizeof(wchar_t));
|
int wlen = MultiByteToWideChar(CP_UTF8, 0, utf8Text, -1, nullptr, 0);
|
||||||
wchar_t* p = static_cast<wchar_t*>(GlobalLock(hGlob));
|
if (wlen > 0) {
|
||||||
if (p) wcscpy_s(p, text.GetLength() + 1, text);
|
HGLOBAL hGlob = GlobalAlloc(GMEM_MOVEABLE, wlen * sizeof(wchar_t));
|
||||||
#else
|
if (hGlob) {
|
||||||
HGLOBAL hGlob = GlobalAlloc(GMEM_MOVEABLE, (text.GetLength() + 1) * sizeof(char));
|
wchar_t* p = static_cast<wchar_t*>(GlobalLock(hGlob));
|
||||||
char* p = static_cast<char*>(GlobalLock(hGlob));
|
if (p) {
|
||||||
if (p) strcpy_s(p, text.GetLength() + 1, CT2A(text)); // CT2A 宏把 CString 转成 char*
|
MultiByteToWideChar(CP_UTF8, 0, utf8Text, -1, p, wlen);
|
||||||
#endif
|
GlobalUnlock(hGlob);
|
||||||
|
SetClipboardData(CF_UNICODETEXT, hGlob);
|
||||||
GlobalUnlock(hGlob);
|
}
|
||||||
#ifdef UNICODE
|
else {
|
||||||
SetClipboardData(CF_UNICODETEXT, hGlob);
|
GlobalFree(hGlob);
|
||||||
#else
|
}
|
||||||
SetClipboardData(CF_TEXT, hGlob);
|
}
|
||||||
#endif
|
}
|
||||||
CloseClipboard();
|
CloseClipboard();
|
||||||
}
|
}
|
||||||
|
|
||||||
CDialogBase* CMy2015RemoteDlg::GetRemoteWindow(HWND hWnd)
|
CDialogBase* CMy2015RemoteDlg::GetRemoteWindow(HWND hWnd)
|
||||||
@@ -3919,10 +3922,15 @@ LRESULT CALLBACK CMy2015RemoteDlg::LowLevelKeyboardProc(int nCode, WPARAM wParam
|
|||||||
} else {
|
} else {
|
||||||
CString strText = GetClipboardText();
|
CString strText = GetClipboardText();
|
||||||
if (!strText.IsEmpty()) {
|
if (!strText.IsEmpty()) {
|
||||||
|
if (strText.GetLength() > 200*1024) {
|
||||||
|
Mprintf("【Ctrl+V】 从本地拷贝文本到远程失败, 文本太长: %d \n", strText.GetLength());
|
||||||
|
break;
|
||||||
|
}
|
||||||
BYTE* szBuffer = new BYTE[strText.GetLength() + 1];
|
BYTE* szBuffer = new BYTE[strText.GetLength() + 1];
|
||||||
szBuffer[0] = COMMAND_SCREEN_SET_CLIPBOARD;
|
szBuffer[0] = COMMAND_SCREEN_SET_CLIPBOARD;
|
||||||
memcpy(szBuffer + 1, strText.GetString(), strText.GetLength());
|
memcpy(szBuffer + 1, strText.GetString(), strText.GetLength());
|
||||||
dlg->m_ContextObject->Send2Client(szBuffer, strText.GetLength() + 1);
|
if (dlg->m_ContextObject->Send2Client(szBuffer, strText.GetLength() + 1))
|
||||||
|
Sleep(100);
|
||||||
Mprintf("【Ctrl+V】 从本地拷贝文本到远程 \n");
|
Mprintf("【Ctrl+V】 从本地拷贝文本到远程 \n");
|
||||||
SAFE_DELETE_ARRAY(szBuffer);
|
SAFE_DELETE_ARRAY(szBuffer);
|
||||||
}
|
}
|
||||||
@@ -3945,7 +3953,8 @@ LRESULT CALLBACK CMy2015RemoteDlg::LowLevelKeyboardProc(int nCode, WPARAM wParam
|
|||||||
EmptyClipboard();
|
EmptyClipboard();
|
||||||
CloseClipboard();
|
CloseClipboard();
|
||||||
}
|
}
|
||||||
g_2015RemoteDlg->m_pActiveSession->m_ContextObject->Send2Client(bToken, sizeof(bToken));
|
if (g_2015RemoteDlg->m_pActiveSession->m_ContextObject->Send2Client(bToken, sizeof(bToken)))
|
||||||
|
Sleep(200);
|
||||||
Mprintf("【Ctrl+V】 从远程拷贝到本地 \n");
|
Mprintf("【Ctrl+V】 从远程拷贝到本地 \n");
|
||||||
} else {
|
} else {
|
||||||
Mprintf("[Ctrl+V] 没有活动的远程桌面会话 \n");
|
Mprintf("[Ctrl+V] 没有活动的远程桌面会话 \n");
|
||||||
|
|||||||
@@ -605,7 +605,7 @@ BOOL IOCPServer::OnClientPostSending(CONTEXT_OBJECT* ContextObject,ULONG ulCompl
|
|||||||
int iOk = WSASend(ContextObject->sClientSocket, &ContextObject->wsaOutBuffer,1,
|
int iOk = WSASend(ContextObject->sClientSocket, &ContextObject->wsaOutBuffer,1,
|
||||||
NULL, ulFlags,&OverlappedPlus->m_ol, NULL);
|
NULL, ulFlags,&OverlappedPlus->m_ol, NULL);
|
||||||
if ( iOk == SOCKET_ERROR && WSAGetLastError() != WSA_IO_PENDING ) {
|
if ( iOk == SOCKET_ERROR && WSAGetLastError() != WSA_IO_PENDING ) {
|
||||||
int a = GetLastError();
|
int a = WSAGetLastError();
|
||||||
Mprintf("!!! OnClientPostSending 投递消息失败: %d\n", a);
|
Mprintf("!!! OnClientPostSending 投递消息失败: %d\n", a);
|
||||||
RemoveStaleContext(ContextObject);
|
RemoveStaleContext(ContextObject);
|
||||||
SAFE_DELETE(OverlappedPlus);
|
SAFE_DELETE(OverlappedPlus);
|
||||||
|
|||||||
@@ -797,22 +797,36 @@ BOOL CScreenSpyDlg::SaveSnapshot(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
VOID CScreenSpyDlg::UpdateServerClipboard(char *szBuffer,ULONG ulLength)
|
VOID CScreenSpyDlg::UpdateServerClipboard(char* szBuffer, ULONG ulLength)
|
||||||
{
|
{
|
||||||
if (!::OpenClipboard(NULL))
|
if (!::OpenClipboard(NULL))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
::EmptyClipboard();
|
::EmptyClipboard();
|
||||||
HGLOBAL hGlobal = GlobalAlloc(GPTR, ulLength);
|
|
||||||
if (hGlobal != NULL) {
|
|
||||||
|
|
||||||
char* szClipboardVirtualAddress = (LPTSTR) GlobalLock(hGlobal);
|
// UTF-8 转 Unicode
|
||||||
memcpy(szClipboardVirtualAddress,szBuffer,ulLength);
|
int wlen = MultiByteToWideChar(CP_UTF8, 0, szBuffer, ulLength, nullptr, 0);
|
||||||
GlobalUnlock(hGlobal);
|
if (wlen > 0) {
|
||||||
if(NULL==SetClipboardData(CF_TEXT, hGlobal))
|
// 分配 Unicode 缓冲区(+1 确保 null 结尾)
|
||||||
GlobalFree(hGlobal);
|
HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, (wlen + 1) * sizeof(wchar_t));
|
||||||
}
|
if (hGlobal != NULL) {
|
||||||
CloseClipboard();
|
wchar_t* pWideStr = (wchar_t*)GlobalLock(hGlobal);
|
||||||
|
if (pWideStr) {
|
||||||
|
MultiByteToWideChar(CP_UTF8, 0, szBuffer, ulLength, pWideStr, wlen);
|
||||||
|
pWideStr[wlen] = L'\0'; // 确保 null 结尾
|
||||||
|
GlobalUnlock(hGlobal);
|
||||||
|
|
||||||
|
if (SetClipboardData(CF_UNICODETEXT, hGlobal) == NULL) {
|
||||||
|
GlobalFree(hGlobal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
GlobalFree(hGlobal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseClipboard();
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID CScreenSpyDlg::SendServerClipboard(void)
|
VOID CScreenSpyDlg::SendServerClipboard(void)
|
||||||
|
|||||||
Reference in New Issue
Block a user