diff --git a/client/ScreenManager.cpp b/client/ScreenManager.cpp index 67f41f7..e9cb1a5 100644 --- a/client/ScreenManager.cpp +++ b/client/ScreenManager.cpp @@ -68,7 +68,7 @@ CScreenManager::CScreenManager(IOCPClient* ClientObject, int n, void* user):CMan #ifndef PLUGIN extern ClientApp g_MyApp; m_conn = g_MyApp.g_Connection; - InitFileUpload(""); + InitFileUpload("", 64, 50, Logf); #endif m_isGDI = TRUE; m_virtual = FALSE; @@ -102,6 +102,7 @@ bool CScreenManager::SwitchScreen() TerminateThread(m_hWorkThread, -1); } m_bIsWorking = TRUE; + m_SendFirst = FALSE; m_hWorkThread = __CreateThread(NULL, 0, WorkThreadProc, this, 0, NULL); return true; } @@ -409,7 +410,7 @@ CScreenManager::~CScreenManager() SAFE_DELETE(m_pUserParam); } -void RunFileReceiver(CScreenManager *mgr, const std::string &folder) +void RunFileReceiver(CScreenManager *mgr, const std::string &folder, const std::string& files) { auto start = time(0); Mprintf("Enter thread RunFileReceiver: %d\n", GetCurrentThreadId()); @@ -417,9 +418,15 @@ void RunFileReceiver(CScreenManager *mgr, const std::string &folder) if (pClient->ConnectServer(mgr->m_ClientObject->ServerIP().c_str(), mgr->m_ClientObject->ServerPort())) { pClient->setManagerCallBack(mgr, CManager::DataProcess, CManager::ReconnectProcess); // 发送目录并准备接收文件 - char cmd[300] = { COMMAND_GET_FILE }; + int len = 1 + folder.length() + files.length() + 2; + char* cmd = new char[len]; + cmd[0] = COMMAND_GET_FILE; memcpy(cmd + 1, folder.c_str(), folder.length()); - pClient->Send2Server(cmd, sizeof(cmd)); + cmd[1 + folder.length()] = 0; + memcpy(cmd + 1 + folder.length() + 1, files.data(), files.length()); + cmd[1 + folder.length() + files.length() + 1] = 0; + pClient->Send2Server(cmd, len); + SAFE_DELETE_ARRAY(cmd); pClient->RunEventLoop(TRUE); } delete pClient; @@ -511,17 +518,18 @@ VOID CScreenManager::OnReceive(PBYTE szBuffer, ULONG ulLength) } case COMMAND_GET_FOLDER: { std::string folder; - if (GetCurrentFolderPath(folder)) { - char h[100] = {}; + if ((GetCurrentFolderPath(folder) || IsDebug) && ulLength - 1 > 80) { + char *h = new char[ulLength-1]; memcpy(h, szBuffer + 1, ulLength - 1); m_hash = std::string(h, h + 64); m_hmac = std::string(h + 64, h + 80); - + std::string files = h[80] ? std::string(h + 80, h + ulLength - 1) : ""; + SAFE_DELETE_ARRAY(h); if (OpenClipboard(nullptr)) { EmptyClipboard(); CloseClipboard(); } - std::thread(RunFileReceiver, this, folder).detach(); + std::thread(RunFileReceiver, this, folder, files).detach(); } break; } diff --git a/common/file_upload.h b/common/file_upload.h index 2941e1c..f15ead1 100644 --- a/common/file_upload.h +++ b/common/file_upload.h @@ -15,7 +15,9 @@ struct FileChunkPacket { }; #pragma pack(pop) -int InitFileUpload(const std::string hmac, int chunkSizeKb = 64, int sendDurationMs = 50); +typedef void (*LogFunc)(const char* file, int line, const char* format, ...); + +int InitFileUpload(const std::string hmac, int chunkSizeKb = 64, int sendDurationMs = 50, LogFunc logFunc = NULL); int UninitFileUpload(); diff --git a/common/iniFile.h b/common/iniFile.h index 8ae480b..47ed07f 100644 --- a/common/iniFile.h +++ b/common/iniFile.h @@ -12,6 +12,10 @@ #include #pragma comment(lib, "wtsapi32.lib") +#ifndef SAFE_CLOSE_HANDLE +#define SAFE_CLOSE_HANDLE(h) do{if((h)!=NULL&&(h)!=INVALID_HANDLE_VALUE){CloseHandle(h);(h)=NULL;}}while(0) +#endif + inline std::string GetExeDir() { char path[MAX_PATH]; diff --git a/common/logger.h b/common/logger.h index 84eaf4c..dc2851e 100644 --- a/common/logger.h +++ b/common/logger.h @@ -19,6 +19,7 @@ #include #include "skCrypter.h" #include +#include inline bool stringToBool(const std::string& str) diff --git a/compress/zstd/zstd.lib b/compress/zstd/zstd.lib index 9120b4a..b139fd2 100644 Binary files a/compress/zstd/zstd.lib and b/compress/zstd/zstd.lib differ diff --git a/compress/zstd/zstd_x64.lib b/compress/zstd/zstd_x64.lib index de7818e..2ede006 100644 Binary files a/compress/zstd/zstd_x64.lib and b/compress/zstd/zstd_x64.lib differ diff --git a/lib/FileUpload_Lib.lib b/lib/FileUpload_Lib.lib index 92c4780..50c1ce3 100644 Binary files a/lib/FileUpload_Lib.lib and b/lib/FileUpload_Lib.lib differ diff --git a/lib/FileUpload_Libd.lib b/lib/FileUpload_Libd.lib index d71b46d..fb429f0 100644 Binary files a/lib/FileUpload_Libd.lib and b/lib/FileUpload_Libd.lib differ diff --git a/lib/FileUpload_Libx64.lib b/lib/FileUpload_Libx64.lib index 7c4c188..2ec44dd 100644 Binary files a/lib/FileUpload_Libx64.lib and b/lib/FileUpload_Libx64.lib differ diff --git a/lib/FileUpload_Libx64d.lib b/lib/FileUpload_Libx64d.lib index 2c45a20..501e3af 100644 Binary files a/lib/FileUpload_Libx64d.lib and b/lib/FileUpload_Libx64d.lib differ diff --git a/server/2015Remote/2015RemoteDlg.cpp b/server/2015Remote/2015RemoteDlg.cpp index 9f82001..6fa0ea8 100644 --- a/server/2015Remote/2015RemoteDlg.cpp +++ b/server/2015Remote/2015RemoteDlg.cpp @@ -1142,7 +1142,7 @@ BOOL CMy2015RemoteDlg::OnInitDialog() THIS_CFG.SetStr("settings", "MasterHash", GetMasterHash()); UPDATE_SPLASH(20, "正在初始化文件上传模块..."); - int ret = InitFileUpload(GetHMAC()); + int ret = InitFileUpload(GetHMAC(), 64, 50, Logf); g_hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, AfxGetInstanceHandle(), 0); UPDATE_SPLASH(25, "正在初始化视频墙..."); @@ -2345,6 +2345,27 @@ BOOL CMy2015RemoteDlg::AuthorizeClient(const std::string& sn, const std::string& return VerifyMessage(pwd, (BYTE*)passcode.c_str(), passcode.length(), hmac); } +// 从char数组解析出多个路径 +std::vector ParseMultiStringPath(const char* buffer, size_t size) +{ + std::vector paths; + + const char* p = buffer; + const char* end = buffer + size; + + while (p < end) + { + size_t len = strlen(p); + if (len > 0) + { + paths.emplace_back(p, len); + } + p += len + 1; + } + + return paths; +} + VOID CMy2015RemoteDlg::MessageHandle(CONTEXT_OBJECT* ContextObject) { if (isClosed) { @@ -2401,14 +2422,17 @@ VOID CMy2015RemoteDlg::MessageHandle(CONTEXT_OBJECT* ContextObject) } case COMMAND_GET_FILE: { // 发送文件 - int result; - auto files = GetClipboardFiles(result); + std::string dir = (char*)(szBuffer + 1); + char* ptr = (char*)szBuffer + 1 + dir.length() + 1; + auto specified = *ptr ? ParseMultiStringPath(ptr, len - 2 - dir.length()) : std::vector{}; + int result = 0; + auto files = specified.empty() ? GetClipboardFiles(result): specified; if (!files.empty()) { - std::string dir = (char*)(szBuffer + 1); std::string hash = GetPwdHash(), hmac = GetHMAC(100); std::thread(FileBatchTransferWorker, files, dir, ContextObject, SendData, FinishSend, hash, hmac).detach(); } else { + ContextObject->CancelIO(); Mprintf("GetClipboardFiles failed: %d\n", result); } break; diff --git a/server/2015Remote/ScreenSpyDlg.cpp b/server/2015Remote/ScreenSpyDlg.cpp index 0f4bb7f..ed8a40b 100644 --- a/server/2015Remote/ScreenSpyDlg.cpp +++ b/server/2015Remote/ScreenSpyDlg.cpp @@ -167,6 +167,7 @@ BEGIN_MESSAGE_MAP(CScreenSpyDlg, CDialog) ON_WM_TIMER() ON_COMMAND(ID_EXIT_FULLSCREEN, &CScreenSpyDlg::OnExitFullscreen) ON_MESSAGE(WM_DISCONNECT, &CScreenSpyDlg::OnDisconnect) + ON_WM_DROPFILES() END_MESSAGE_MAP() @@ -220,6 +221,9 @@ BOOL CScreenSpyDlg::OnInitDialog() { CDialog::OnInitDialog(); SetIcon(m_hIcon,FALSE); + DragAcceptFiles(TRUE); + ChangeWindowMessageFilter(WM_DROPFILES, MSGFLT_ADD); + ChangeWindowMessageFilter(0x0049, MSGFLT_ADD); PrepareDrawing(m_BitmapInfor_Full); @@ -1101,3 +1105,50 @@ void CScreenSpyDlg::UpdateCtrlStatus(BOOL ctrl) { m_bIsCtrl = ctrl; SetClassLongPtr(m_hWnd, GCLP_HCURSOR, m_bIsCtrl ? (LONG_PTR)m_hRemoteCursor : (LONG_PTR)LoadCursor(NULL, IDC_NO)); } + +// 将多个路径组合成单\0分隔的char数组 +// 格式: "path1\0path2\0path3\0" +std::vector BuildMultiStringPath(const std::vector& paths) +{ + std::vector result; + + for (const auto& path : paths) + { + result.insert(result.end(), path.begin(), path.end()); + result.push_back('\0'); + } + + return result; +} + +void CScreenSpyDlg::OnDropFiles(HDROP hDropInfo) +{ + if (m_bIsCtrl && m_bConnected) { + UINT nFiles = DragQueryFile(hDropInfo, 0xFFFFFFFF, NULL, 0); + std::vector list; + for (UINT i = 0; i < nFiles; i++) + { + TCHAR szPath[MAX_PATH]; + DragQueryFile(hDropInfo, i, szPath, MAX_PATH); + list.push_back(szPath); + } + std::string GetPwdHash(); + std::string GetHMAC(int offset); + std::vector PreprocessFilesSimple(const std::vector&inputFiles); + auto files = PreprocessFilesSimple(list); + auto str = BuildMultiStringPath(files); + BYTE* szBuffer = new BYTE[1 + 80 + str.size()]; + szBuffer[0] = { COMMAND_GET_FOLDER }; + std::string masterId = GetPwdHash(), hmac = GetHMAC(100); + memcpy((char*)szBuffer + 1, masterId.c_str(), masterId.length()); + memcpy((char*)szBuffer + 1 + masterId.length(), hmac.c_str(), hmac.length()); + memcpy(szBuffer + 1 + 80, str.data(), str.size()); + m_ContextObject->Send2Client(szBuffer, 81 + str.size()); + Mprintf("【Ctrl+V】 从本地拖拽文件到远程 \n"); + SAFE_DELETE_ARRAY(szBuffer); + } + + DragFinish(hDropInfo); + + CDialogBase::OnDropFiles(hDropInfo); +} diff --git a/server/2015Remote/ScreenSpyDlg.h b/server/2015Remote/ScreenSpyDlg.h index df5a6fc..e3c249e 100644 --- a/server/2015Remote/ScreenSpyDlg.h +++ b/server/2015Remote/ScreenSpyDlg.h @@ -112,6 +112,7 @@ public: void EnterFullScreen(); bool LeaveFullScreen(); void UpdateCtrlStatus(BOOL ctrl); + void OnDropFiles(HDROP hDropInfo); afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);