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
This commit is contained in:
yuanyuanxianganddeepseek-v4-pro committed 2026-10-09 16:23:23 +02:00
1 parent f3a8406050
commit 1a9312d2d1
2 files changed
+71 -9

No files matched your search

+32 -3
View File
@@ -223,6 +223,27 @@ int GetIconIndex(LPCTSTR lpFileName, DWORD dwFileAttributes)
return index; 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<LPWSTR>(L"") : &w[0];
::SendMessageW(list.GetSafeHwnd(), LVM_SETITEMTEXTW, (WPARAM)iItem, (LPARAM)&lv);
}
BOOL CFileManagerDlg::OnInitDialog() BOOL CFileManagerDlg::OnInitDialog()
{ {
__super::OnInitDialog(); __super::OnInitDialog();
@@ -1104,6 +1125,9 @@ void CFileManagerDlg::OnDblclkListRemote(NMHDR* pNMHDR, LRESULT* pResult)
void CFileManagerDlg::FixedRemoteFileList(BYTE *pbBuffer, DWORD dwBufferLen) 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 // 重新设置ImageList
SHFILEINFO sfi = {}; SHFILEINFO sfi = {};
HIMAGELIST hImageListLarge = (HIMAGELIST)SHGetFileInfo(NULL, 0, &sfi,sizeof(SHFILEINFO), SHGFI_SYSICONINDEX | SHGFI_LARGEICON); 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; pszFileName = ++pList;
if (bIsInsert) { 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); m_list_remote.SetItemData(nItem, nType == FILE_ATTRIBUTE_DIRECTORY);
SHFILEINFO sfi = {}; SHFILEINFO sfi = {};
SHGetFileInfo(pszFileName, FILE_ATTRIBUTE_NORMAL | nType, &sfi,sizeof(SHFILEINFO), SHGFI_TYPENAME | SHGFI_USEFILEATTRIBUTES); 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) 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) { if (!m_bSearching) {
m_bSearching = true; 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); m_list_remote.SetItemData(nItem, nType == FILE_ATTRIBUTE_DIRECTORY);
pList += lstrlen(pszFullPath) + 1; 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, 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; pList += 16;
m_nSearchResultCount++; m_nSearchResultCount++;
+39 -6
View File
@@ -7,6 +7,7 @@
#include "InputDlg.h" #include "InputDlg.h"
#include <windows.h> #include <windows.h>
#include <Shlwapi.h> #include <Shlwapi.h>
#include <string>
#ifdef _DEBUG #ifdef _DEBUG
#define new DEBUG_NEW #define new DEBUG_NEW
@@ -818,8 +819,32 @@ void CFileManagerDlg::OnclickListSearch(NMHDR* pNMHDR, LRESULT* pResult)
int GetIconIndex(LPCTSTR lpFileName, DWORD dwFileAttributes); 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<LPWSTR>(L"") : &w[0];
::SendMessageW(list.GetSafeHwnd(), LVM_SETITEMTEXTW, (WPARAM)iItem, (LPARAM)&lv);
}
void CFileManagerDlg::FixedRemoteFileList(BYTE* pbBuffer, DWORD dwBufferLen) 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(); m_list_remote.DeleteAllItems();
int nItemIndex = 0; int nItemIndex = 0;
@@ -855,7 +880,8 @@ void CFileManagerDlg::FixedRemoteFileList(BYTE* pbBuffer, DWORD dwBufferLen)
if (bIsInsert) { if (bIsInsert) {
int iicon = GetIconIndex(pszFileName, nType); 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); m_list_remote.SetItemData(nItem, nType == FILE_ATTRIBUTE_DIRECTORY);
SHFILEINFO sfi = {}; SHFILEINFO sfi = {};
SHGetFileInfo(pszFileName, FILE_ATTRIBUTE_NORMAL | nType, &sfi, sizeof(SHFILEINFO), SHGFI_TYPENAME | SHGFI_USEFILEATTRIBUTES); 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) 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; byte* pList = pbBuffer + 1;
int nItemIndex = 0; int nItemIndex = 0;
for (byte* pBase = pList; (int)(pList - pBase) < (int)(dwBufferLen - 1);) { 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('\\')); int nPos = csFilePath.ReverseFind(_T('\\'));
csFileFullName = csFilePath.Right(csFilePath.GetLength() - nPos - 1);// 获取文件全名,包括文件名和扩展名 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); m_list_remote_search.SetItemData(nItem, nType == FILE_ATTRIBUTE_DIRECTORY);
pList += (lstrlen(pszFileName) + 1) * sizeof(TCHAR); 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"))); m_list_remote_search.SetItemText(nItem, 2, time.FormatL(_T("%Y-%m-%d %H:%M")));
PathRemoveFileSpec(pszFileName); //去除文件名获取文件路径 PathRemoveFileSpec(pszFileName); //去除文件名获取文件路径
m_list_remote_search.SetItemText(nItem, 3, pszFileName); SetFileTextItem(m_list_remote_search, nItem, 3, pszFileName, cp);
pList += 16; pList += 16;
} }
@@ -2491,6 +2521,9 @@ void CFileManagerDlg::ShowSearchPlugList()
char* Filename; char* Filename;
char* Pathname; char* Pathname;
CString clientType = m_ContextObject->GetAdditionalData(RES_CLIENT_TYPE);
UINT cp = (clientType == _T("LNX") || clientType == _T("MAC")) ? CP_UTF8 : 936;
DWORD dwOffset = 0; DWORD dwOffset = 0;
m_list_remote_search.DeleteAllItems(); m_list_remote_search.DeleteAllItems();
int i = 0; int i = 0;
@@ -2498,13 +2531,13 @@ void CFileManagerDlg::ShowSearchPlugList()
Filename = lpBuffer + dwOffset; Filename = lpBuffer + dwOffset;
Pathname = Filename + strlen(Filename) + 1; Pathname = Filename + strlen(Filename) + 1;
CString CS_tem; CString CS_tem;
CS_tem = Filename; m_list_remote_search.InsertItem(i, _T(""), 0);
m_list_remote_search.InsertItem(i, CS_tem, 0); SetFileTextItem(m_list_remote_search, i, 0, Filename, cp);
CS_tem = Pathname; CS_tem = Pathname;
int index = CS_tem.ReverseFind('\\'); int index = CS_tem.ReverseFind('\\');
if (index >= 0) if (index >= 0)
CS_tem = CS_tem.Left(index); 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; dwOffset += strlen(Filename) + strlen(Pathname) + 2;
} }
m_list_remote_search.EnableWindow(TRUE); m_list_remote_search.EnableWindow(TRUE);