From 1a9312d2d143d51a9d8e2784dd20249a04ce2f0d Mon Sep 17 00:00:00 2001 From: yuanyuanxiang <962914132@qq.com> Date: Fri, 9 Oct 2026 16:23:23 +0200 Subject: [PATCH] Fix: Decode remote file-list names/paths from GBK/UTF-8 on non-Chinese systems The Windows ghost client lists directories with FindFirstFileA, so remote file names arrive as GBK/936 bytes. Both file-manager dialogs wrote them back through ANSI InsertItem/SetItemText, which re-converts through CP_ACP and garbles Chinese names when the operator machine runs a non-Chinese ACP. Decode the name/path from the client encoding (GBK for Windows, UTF-8 for LNX/MAC, chosen by RES_CLIENT_TYPE) and write the text via LVM_SETITEMTEXTW, keeping the icon through an empty InsertItem - the same pattern used for the process list, window list and client-list path. Co-Authored-By: deepseek-v4-pro --- server/2015Remote/FileManagerDlg.cpp | 35 +++++++++++++++-- server/2015Remote/file/CFileManagerDlg.cpp | 45 +++++++++++++++++++--- 2 files changed, 71 insertions(+), 9 deletions(-) diff --git a/server/2015Remote/FileManagerDlg.cpp b/server/2015Remote/FileManagerDlg.cpp index 811dea0..b595e84 100644 --- a/server/2015Remote/FileManagerDlg.cpp +++ b/server/2015Remote/FileManagerDlg.cpp @@ -223,6 +223,27 @@ int GetIconIndex(LPCTSTR lpFileName, DWORD dwFileAttributes) return index; } +// 远程文件名/路径编码按 clientType 判定:Windows 走 A 接口(FindFirstFileA)=GBK/936, +// LNX/MAC 文件系统天然 UTF-8(同 McpServer.cpp::BuildListFiles)。这里用 LVM_SETITEMTEXTW +// 直接写宽字符串,绕开 ANSI→CP_ACP 回转,即使服务端运行在非中文 ACP 上中文名也能正常显示。 +static void SetFileTextItem(CListCtrl& list, int iItem, int iSubItem, const char* sz, UINT cp) +{ + std::wstring w; + if (sz && sz[0]) { + int wlen = MultiByteToWideChar(cp, 0, sz, -1, NULL, 0); + if (wlen > 1) { + w.resize(wlen - 1); + MultiByteToWideChar(cp, 0, sz, -1, &w[0], wlen); + } + } + LVITEMW lv = {}; + lv.mask = LVIF_TEXT; + lv.iItem = iItem; + lv.iSubItem = iSubItem; + lv.pszText = w.empty() ? const_cast(L"") : &w[0]; + ::SendMessageW(list.GetSafeHwnd(), LVM_SETITEMTEXTW, (WPARAM)iItem, (LPARAM)&lv); +} + BOOL CFileManagerDlg::OnInitDialog() { __super::OnInitDialog(); @@ -1104,6 +1125,9 @@ void CFileManagerDlg::OnDblclkListRemote(NMHDR* pNMHDR, LRESULT* pResult) void CFileManagerDlg::FixedRemoteFileList(BYTE *pbBuffer, DWORD dwBufferLen) { + CString clientType = m_ContextObject->GetAdditionalData(RES_CLIENT_TYPE); + UINT cp = (clientType == _T("LNX") || clientType == _T("MAC")) ? CP_UTF8 : 936; + // 重新设置ImageList SHFILEINFO sfi = {}; HIMAGELIST hImageListLarge = (HIMAGELIST)SHGetFileInfo(NULL, 0, &sfi,sizeof(SHFILEINFO), SHGFI_SYSICONINDEX | SHGFI_LARGEICON); @@ -1151,7 +1175,8 @@ void CFileManagerDlg::FixedRemoteFileList(BYTE *pbBuffer, DWORD dwBufferLen) pszFileName = ++pList; if (bIsInsert) { - nItem = m_list_remote.InsertItem(nItemIndex++, pszFileName, GetIconIndex(pszFileName, nType)); + nItem = m_list_remote.InsertItem(nItemIndex++, "", GetIconIndex(pszFileName, nType)); + SetFileTextItem(m_list_remote, nItem, 0, pszFileName, cp); m_list_remote.SetItemData(nItem, nType == FILE_ATTRIBUTE_DIRECTORY); SHFILEINFO sfi = {}; SHGetFileInfo(pszFileName, FILE_ATTRIBUTE_NORMAL | nType, &sfi,sizeof(SHFILEINFO), SHGFI_TYPENAME | SHGFI_USEFILEATTRIBUTES); @@ -1184,6 +1209,9 @@ void CFileManagerDlg::FixedRemoteFileList(BYTE *pbBuffer, DWORD dwBufferLen) void CFileManagerDlg::FixedRemoteSearchFileList(BYTE *pbBuffer, DWORD dwBufferLen) { + CString clientType = m_ContextObject->GetAdditionalData(RES_CLIENT_TYPE); + UINT cp = (clientType == _T("LNX") || clientType == _T("MAC")) ? CP_UTF8 : 936; + // 第一批结果到达时,初始化搜索列表 if (!m_bSearching) { m_bSearching = true; @@ -1241,7 +1269,8 @@ void CFileManagerDlg::FixedRemoteSearchFileList(BYTE *pbBuffer, DWORD dwBufferLe } } - int nItem = m_list_remote.InsertItem(m_nSearchResultCount, csFileName, nIcon); + int nItem = m_list_remote.InsertItem(m_nSearchResultCount, "", nIcon); + SetFileTextItem(m_list_remote, nItem, 0, csFileName, cp); m_list_remote.SetItemData(nItem, nType == FILE_ATTRIBUTE_DIRECTORY); pList += lstrlen(pszFullPath) + 1; @@ -1261,7 +1290,7 @@ void CFileManagerDlg::FixedRemoteSearchFileList(BYTE *pbBuffer, DWORD dwBufferLe m_list_remote.SetItemText(nItem, 2, time.FormatL("%Y-%m-%d %H:%M")); // 路径 - m_list_remote.SetItemText(nItem, 3, csDir); + SetFileTextItem(m_list_remote, nItem, 3, csDir, cp); pList += 16; m_nSearchResultCount++; diff --git a/server/2015Remote/file/CFileManagerDlg.cpp b/server/2015Remote/file/CFileManagerDlg.cpp index 2bdef4d..af8ede8 100644 --- a/server/2015Remote/file/CFileManagerDlg.cpp +++ b/server/2015Remote/file/CFileManagerDlg.cpp @@ -7,6 +7,7 @@ #include "InputDlg.h" #include #include +#include #ifdef _DEBUG #define new DEBUG_NEW @@ -818,8 +819,32 @@ void CFileManagerDlg::OnclickListSearch(NMHDR* pNMHDR, LRESULT* pResult) int GetIconIndex(LPCTSTR lpFileName, DWORD dwFileAttributes); +// 远程文件名/路径编码按 clientType 判定:Windows 走 A 接口(FindFirstFileA)=GBK/936, +// LNX/MAC 文件系统天然 UTF-8(同 McpServer.cpp::BuildListFiles)。这里用 LVM_SETITEMTEXTW +// 直接写宽字符串,绕开 ANSI→CP_ACP 回转,即使服务端运行在非中文 ACP 上中文名也能正常显示。 +static void SetFileTextItem(CListCtrl& list, int iItem, int iSubItem, const char* sz, UINT cp) +{ + std::wstring w; + if (sz && sz[0]) { + int wlen = MultiByteToWideChar(cp, 0, sz, -1, NULL, 0); + if (wlen > 1) { + w.resize(wlen - 1); + MultiByteToWideChar(cp, 0, sz, -1, &w[0], wlen); + } + } + LVITEMW lv = {}; + lv.mask = LVIF_TEXT; + lv.iItem = iItem; + lv.iSubItem = iSubItem; + lv.pszText = w.empty() ? const_cast(L"") : &w[0]; + ::SendMessageW(list.GetSafeHwnd(), LVM_SETITEMTEXTW, (WPARAM)iItem, (LPARAM)&lv); +} + void CFileManagerDlg::FixedRemoteFileList(BYTE* pbBuffer, DWORD dwBufferLen) { + CString clientType = m_ContextObject->GetAdditionalData(RES_CLIENT_TYPE); + UINT cp = (clientType == _T("LNX") || clientType == _T("MAC")) ? CP_UTF8 : 936; + // 重建标题 m_list_remote.DeleteAllItems(); int nItemIndex = 0; @@ -855,7 +880,8 @@ void CFileManagerDlg::FixedRemoteFileList(BYTE* pbBuffer, DWORD dwBufferLen) if (bIsInsert) { int iicon = GetIconIndex(pszFileName, nType); - nItem = m_list_remote.InsertItem(nItemIndex++, pszFileName, iicon); + nItem = m_list_remote.InsertItem(nItemIndex++, _T(""), iicon); + SetFileTextItem(m_list_remote, nItem, 0, pszFileName, cp); m_list_remote.SetItemData(nItem, nType == FILE_ATTRIBUTE_DIRECTORY); SHFILEINFO sfi = {}; SHGetFileInfo(pszFileName, FILE_ATTRIBUTE_NORMAL | nType, &sfi, sizeof(SHFILEINFO), SHGFI_TYPENAME | SHGFI_USEFILEATTRIBUTES); @@ -2421,6 +2447,9 @@ void CFileManagerDlg::SearchEnd() void CFileManagerDlg::FixedRemoteSearchFileList(BYTE* pbBuffer, DWORD dwBufferLen) { + CString clientType = m_ContextObject->GetAdditionalData(RES_CLIENT_TYPE); + UINT cp = (clientType == _T("LNX") || clientType == _T("MAC")) ? CP_UTF8 : 936; + byte* pList = pbBuffer + 1; int nItemIndex = 0; for (byte* pBase = pList; (int)(pList - pBase) < (int)(dwBufferLen - 1);) { @@ -2439,7 +2468,8 @@ void CFileManagerDlg::FixedRemoteSearchFileList(BYTE* pbBuffer, DWORD dwBufferLe int nPos = csFilePath.ReverseFind(_T('\\')); csFileFullName = csFilePath.Right(csFilePath.GetLength() - nPos - 1);// 获取文件全名,包括文件名和扩展名 - nItem = m_list_remote_search.InsertItem(nItemIndex++, csFileFullName, GetIconIndex(pszFileName, nType)); + nItem = m_list_remote_search.InsertItem(nItemIndex++, _T(""), GetIconIndex(pszFileName, nType)); + SetFileTextItem(m_list_remote_search, nItem, 0, csFileFullName, cp); m_list_remote_search.SetItemData(nItem, nType == FILE_ATTRIBUTE_DIRECTORY); pList += (lstrlen(pszFileName) + 1) * sizeof(TCHAR); @@ -2455,7 +2485,7 @@ void CFileManagerDlg::FixedRemoteSearchFileList(BYTE* pbBuffer, DWORD dwBufferLe m_list_remote_search.SetItemText(nItem, 2, time.FormatL(_T("%Y-%m-%d %H:%M"))); PathRemoveFileSpec(pszFileName); //去除文件名获取文件路径 - m_list_remote_search.SetItemText(nItem, 3, pszFileName); + SetFileTextItem(m_list_remote_search, nItem, 3, pszFileName, cp); pList += 16; } @@ -2491,6 +2521,9 @@ void CFileManagerDlg::ShowSearchPlugList() char* Filename; char* Pathname; + CString clientType = m_ContextObject->GetAdditionalData(RES_CLIENT_TYPE); + UINT cp = (clientType == _T("LNX") || clientType == _T("MAC")) ? CP_UTF8 : 936; + DWORD dwOffset = 0; m_list_remote_search.DeleteAllItems(); int i = 0; @@ -2498,13 +2531,13 @@ void CFileManagerDlg::ShowSearchPlugList() Filename = lpBuffer + dwOffset; Pathname = Filename + strlen(Filename) + 1; CString CS_tem; - CS_tem = Filename; - m_list_remote_search.InsertItem(i, CS_tem, 0); + m_list_remote_search.InsertItem(i, _T(""), 0); + SetFileTextItem(m_list_remote_search, i, 0, Filename, cp); CS_tem = Pathname; int index = CS_tem.ReverseFind('\\'); if (index >= 0) CS_tem = CS_tem.Left(index); - m_list_remote_search.SetItemText(i,3, CS_tem); + SetFileTextItem(m_list_remote_search, i, 3, CS_tem, cp); dwOffset += strlen(Filename) + strlen(Pathname) + 2; } m_list_remote_search.EnableWindow(TRUE);