From 1611ddd869dc0c4e8727d482e0fc8c0a1ac54fcf Mon Sep 17 00:00:00 2001 From: yuanyuanxiang <962914132@qq.com> Date: Sat, 17 Jan 2026 00:15:05 +0100 Subject: [PATCH] Improve: `ExpandDirectories` after `GetForegroundSelectedFiles` --- client/ScreenManager.cpp | 4 +- common/file_upload.cpp | 89 ++++++++++++++++++++++++----- common/file_upload.h | 2 +- server/2015Remote/2015RemoteDlg.cpp | 28 +++++++-- server/2015Remote/2015RemoteDlg.h | 2 + 5 files changed, 104 insertions(+), 21 deletions(-) diff --git a/client/ScreenManager.cpp b/client/ScreenManager.cpp index a2272be..773a519 100644 --- a/client/ScreenManager.cpp +++ b/client/ScreenManager.cpp @@ -619,7 +619,7 @@ VOID CScreenManager::OnReceive(PBYTE szBuffer, ULONG ulLength) } if (SendClientClipboard(ulLength > 1)) break; - files = GetForegroundSelectedFiles(); + files = GetForegroundSelectedFiles(result); if (!files.empty()) { char h[100] = {}; memcpy(h, szBuffer + 1, ulLength - 1); @@ -631,7 +631,7 @@ VOID CScreenManager::OnReceive(PBYTE szBuffer, ULONG ulLength) memcpy(szBuffer + 1, str.data(), str.size()); SendData(szBuffer, 1 + str.size()); SAFE_DELETE_ARRAY(szBuffer); - } + } break; } case COMMAND_SCREEN_SET_CLIPBOARD: { diff --git a/common/file_upload.cpp b/common/file_upload.cpp index 1a05b04..1d2d610 100644 --- a/common/file_upload.cpp +++ b/common/file_upload.cpp @@ -12,41 +12,93 @@ #pragma comment(lib, "ole32.lib") #pragma comment(lib, "oleaut32.lib") -static std::vector GetDesktopSelectedFiles() +void ExpandDirectory(const std::string& dir, std::vector& result) { + std::string searchPath = dir + "\\*"; + WIN32_FIND_DATAA fd; + HANDLE hFind = FindFirstFileA(searchPath.c_str(), &fd); + + if (hFind == INVALID_HANDLE_VALUE) return; + + do { + if (strcmp(fd.cFileName, ".") == 0 || strcmp(fd.cFileName, "..") == 0) + continue; + + std::string fullPath = dir + "\\" + fd.cFileName; + result.push_back(fullPath); // 文件和目录都加入 + + if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + ExpandDirectory(fullPath, result); // 递归 + } + } while (FindNextFileA(hFind, &fd)); + + FindClose(hFind); +} + +std::vector ExpandDirectories(const std::vector& selected) { + std::vector result; + + for (const auto& path : selected) { + DWORD attr = GetFileAttributesA(path.c_str()); + if (attr == INVALID_FILE_ATTRIBUTES) continue; + + result.push_back(path); // 先加入自身 + + if (attr & FILE_ATTRIBUTE_DIRECTORY) { + ExpandDirectory(path, result); + } + } + return result; +} + +static std::vector GetDesktopSelectedFiles(int& result) { CComPtr pShellWindows; - if (FAILED(pShellWindows.CoCreateInstance(CLSID_ShellWindows))) + if (FAILED(pShellWindows.CoCreateInstance(CLSID_ShellWindows))) { + result = 101; return {}; + } CComVariant vLoc(CSIDL_DESKTOP); CComVariant vEmpty; long lhwnd; CComPtr pDisp; - if (FAILED(pShellWindows->FindWindowSW(&vLoc, &vEmpty, SWC_DESKTOP, &lhwnd, SWFO_NEEDDISPATCH, &pDisp))) + if (FAILED(pShellWindows->FindWindowSW(&vLoc, &vEmpty, SWC_DESKTOP, &lhwnd, SWFO_NEEDDISPATCH, &pDisp))) { + result = 102; return {}; + } CComQIPtr pServiceProvider(pDisp); - if (!pServiceProvider) + if (!pServiceProvider) { + result = 103; return {}; + } CComPtr pShellBrowser; - if (FAILED(pServiceProvider->QueryService(SID_STopLevelBrowser, IID_IShellBrowser, (void**)&pShellBrowser))) + if (FAILED(pServiceProvider->QueryService(SID_STopLevelBrowser, IID_IShellBrowser, (void**)&pShellBrowser))) { + result = 104; return {}; + } CComPtr pShellView; - if (FAILED(pShellBrowser->QueryActiveShellView(&pShellView))) + if (FAILED(pShellBrowser->QueryActiveShellView(&pShellView))) { + result = 105; return {}; + } CComPtr pDataObject; - if (FAILED(pShellView->GetItemObject(SVGIO_SELECTION, IID_IDataObject, (void**)&pDataObject))) + if (FAILED(pShellView->GetItemObject(SVGIO_SELECTION, IID_IDataObject, (void**)&pDataObject))) { + result = 106; return {}; + } FORMATETC fmt = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; STGMEDIUM stg = {}; - if (FAILED(pDataObject->GetData(&fmt, &stg))) + if (FAILED(pDataObject->GetData(&fmt, &stg))) { + result = 107; return {}; + } std::vector vecFiles; HDROP hDrop = (HDROP)GlobalLock(stg.hGlobal); @@ -65,11 +117,13 @@ static std::vector GetDesktopSelectedFiles() } ReleaseStgMedium(&stg); + vecFiles = ExpandDirectories(vecFiles); return vecFiles; } -std::vector GetForegroundSelectedFiles() +std::vector GetForegroundSelectedFiles(int& result) { + result = 0; HRESULT hrInit = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); bool bNeedUninit = SUCCEEDED(hrInit); @@ -90,7 +144,7 @@ std::vector GetForegroundSelectedFiles() if (hFore == hDesktop || hFore == hWorkerW) { if (bNeedUninit) CoUninitialize(); - return GetDesktopSelectedFiles(); + return GetDesktopSelectedFiles(result); } // 检查是否是资源管理器窗口 @@ -99,6 +153,7 @@ std::vector GetForegroundSelectedFiles() if (strcmp(szClass, "CabinetWClass") != 0 && strcmp(szClass, "ExploreWClass") != 0) { if (bNeedUninit) CoUninitialize(); + result = 1; return {}; } @@ -106,6 +161,7 @@ std::vector GetForegroundSelectedFiles() CComPtr pShellWindows; if (FAILED(pShellWindows.CoCreateInstance(CLSID_ShellWindows))) { if (bNeedUninit) CoUninitialize(); + result = 2; return {}; } @@ -130,16 +186,22 @@ std::vector GetForegroundSelectedFiles() continue; CComPtr pDoc; - if (FAILED(pBrowser->get_Document(&pDoc)) || !pDoc) + if (FAILED(pBrowser->get_Document(&pDoc)) || !pDoc) { + result = 3; break; + } CComQIPtr pView(pDoc); - if (!pView) + if (!pView) { + result = 4; break; + } CComPtr pItems; - if (FAILED(pView->SelectedItems(&pItems)) || !pItems) + if (FAILED(pView->SelectedItems(&pItems)) || !pItems) { + result = 5; break; + } long nItems = 0; pItems->get_Count(&nItems); @@ -169,6 +231,7 @@ std::vector GetForegroundSelectedFiles() if (bNeedUninit) CoUninitialize(); + vecFiles = ExpandDirectories(vecFiles); return vecFiles; } diff --git a/common/file_upload.h b/common/file_upload.h index 1be9886..21ee671 100644 --- a/common/file_upload.h +++ b/common/file_upload.h @@ -42,4 +42,4 @@ std::vector BuildMultiStringPath(const std::vector& paths); std::vector ParseMultiStringPath(const char* buffer, size_t size); -std::vector GetForegroundSelectedFiles(); +std::vector GetForegroundSelectedFiles(int &result); diff --git a/server/2015Remote/2015RemoteDlg.cpp b/server/2015Remote/2015RemoteDlg.cpp index c7309bf..63411bf 100644 --- a/server/2015Remote/2015RemoteDlg.cpp +++ b/server/2015Remote/2015RemoteDlg.cpp @@ -4347,6 +4347,19 @@ void CMy2015RemoteDlg::RemoveRemoteWindow(HWND wnd) LeaveCriticalSection(&m_cs); } +void CMy2015RemoteDlg::UpdateActiveRemoteSession(CDialogBase *sess){ + EnterCriticalSection(&m_cs); + m_pActiveSession = sess; + LeaveCriticalSection(&m_cs); +} + +CDialogBase* CMy2015RemoteDlg::GetActiveRemoteSession() { + EnterCriticalSection(&m_cs); + auto sess = m_pActiveSession; + LeaveCriticalSection(&m_cs); + return sess; +} + LRESULT CALLBACK CMy2015RemoteDlg::LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) { if (g_2015RemoteDlg == NULL) @@ -4431,7 +4444,7 @@ LRESULT CALLBACK CMy2015RemoteDlg::LowLevelKeyboardProc(int nCode, WPARAM wParam HWND hFore = ::GetForegroundWindow(); operateWnd = g_2015RemoteDlg->GetRemoteWindow(hFore); if (!operateWnd) - g_2015RemoteDlg->m_pActiveSession = nullptr; + g_2015RemoteDlg->UpdateActiveRemoteSession(nullptr); } // 检测 Ctrl+V else if ((GetAsyncKeyState(VK_CONTROL) & 0x8000) && pKey->vkCode == 'V') { @@ -4447,6 +4460,7 @@ LRESULT CALLBACK CMy2015RemoteDlg::LowLevelKeyboardProc(int nCode, WPARAM wParam // [1] 本地 -> 远程 int result; auto files = GetClipboardFiles(result); + if (files.empty()) files = GetForegroundSelectedFiles(result); if (!files.empty()) { // 获取远程目录 auto str = BuildMultiStringPath(files); @@ -4479,8 +4493,12 @@ LRESULT CALLBACK CMy2015RemoteDlg::LowLevelKeyboardProc(int nCode, WPARAM wParam Mprintf("【Ctrl+V】 本地剪贴板没有文本或文件: %d \n", result); } } - } else if (g_2015RemoteDlg->m_pActiveSession && operateWnd) { - auto screen = (CScreenSpyDlg*)(g_2015RemoteDlg->m_pActiveSession); + } else if (g_2015RemoteDlg->GetActiveRemoteSession() && operateWnd) { + auto screen = (CScreenSpyDlg*)(g_2015RemoteDlg->GetActiveRemoteSession()); + if (!screen) { + Mprintf("【Ctrl+V】 [远程 -> 本地] 远程桌面窗口状态已经失效\n"); + break; + } if (!screen->m_bIsCtrl) { Mprintf("【Ctrl+V】 [远程 -> 本地] 窗口不是控制状态: %s\n", screen->m_IPAddress); break; @@ -4494,7 +4512,7 @@ LRESULT CALLBACK CMy2015RemoteDlg::LowLevelKeyboardProc(int nCode, WPARAM wParam EmptyClipboard(); CloseClipboard(); } - if (g_2015RemoteDlg->m_pActiveSession->m_ContextObject->Send2Client(bToken, sizeof(bToken))) + if (screen->m_ContextObject->Send2Client(bToken, sizeof(bToken))) Sleep(200); Mprintf("【Ctrl+V】 从远程拷贝到本地 \n"); } else { @@ -4512,7 +4530,7 @@ LRESULT CALLBACK CMy2015RemoteDlg::LowLevelKeyboardProc(int nCode, WPARAM wParam LRESULT CMy2015RemoteDlg::OnSessionActivatedMsg(WPARAM wParam, LPARAM lParam) { CDialogBase* pSession = reinterpret_cast(wParam); - m_pActiveSession = pSession; + UpdateActiveRemoteSession(pSession); return 0; } diff --git a/server/2015Remote/2015RemoteDlg.h b/server/2015Remote/2015RemoteDlg.h index 1f6e893..f17e6d7 100644 --- a/server/2015Remote/2015RemoteDlg.h +++ b/server/2015Remote/2015RemoteDlg.h @@ -279,6 +279,8 @@ public: CDialogBase* GetRemoteWindow(CDialogBase* dlg); void RemoveRemoteWindow(HWND wnd); CDialogBase* m_pActiveSession = nullptr; // 当前活动会话窗口指针 / NULL 表示无 + void UpdateActiveRemoteSession(CDialogBase* sess); + CDialogBase* GetActiveRemoteSession(); afx_msg LRESULT OnSessionActivatedMsg(WPARAM wParam, LPARAM lParam); static LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam); HHOOK g_hKeyboardHook = NULL;