Fix: Decode host-management and clipboard text as GBK/UTF-8 on non-Chinese systems
The 主机管理 dialog wrote client data (process names, window titles, net connection state, software entries, IE history, favorites, services, scheduled tasks, hosts) through the ANSI InsertItem/SetItemText path, which re-converts through CP_ACP and garbles Chinese when the operator machine runs a non-Chinese ACP. Decode each client string with its real code page and write it via LVM_SETITEMTEXTW, mirroring SystemDlg::SetClientTextItem. Scheduled-task columns are split by encoding: name/path/exe come from the client as UTF-8 (BSTRToUTF8) while the status literal stays GBK. Also detect a UTF-8 BOM in the hosts file so a Notepad-saved hosts (EF BB BF) no longer shows "锘?" on its first line. In the keyboard dialog, the clipboard preview edit was an ANSI-class window filled via utf8_to_ansi (CP_ACP) + SetWindowTextA, so Chinese was replaced with '?' before it reached the control. Rebuild m_EditClipText as a Unicode-class window and write the UTF-8 clipboard text via SetWindowTextW, matching the m_edit record control. Co-Authored-By: deepseek-v4-pro
This commit is contained in:
1 parent
ca6f76565c
commit
d2149851b2
2 files changed
+88
-32
No files matched your search
@@ -123,6 +123,9 @@ BOOL CKeyBoardDlg::OnInitDialog()
|
||||
// 后,控件内部以 Unicode 存储,W 版消息直通,不再走 CP_ACP。
|
||||
// -----------------------------------------------------------------
|
||||
RebuildEdit(m_edit);
|
||||
// 剪切板显示框同样重建为 Unicode 控件,ShowClipboardText 全程走 W 版消息,
|
||||
// 否则 MBCS 下 SetWindowTextA 会在 A<->W 边界按 CP_ACP 转码,中文丢失。
|
||||
RebuildEdit(m_EditClipText);
|
||||
|
||||
m_edit.SetLimitText(MAXDWORD); // 设置最大长度
|
||||
auto rule = utf8_to_ansi((char*)m_TextRule.param);
|
||||
@@ -171,9 +174,19 @@ void CKeyBoardDlg::OnReceiveComplete()
|
||||
LRESULT CKeyBoardDlg::ShowClipboardText(WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
char* buf = (char*)wParam;
|
||||
std::string text = utf8_to_ansi(buf);
|
||||
// 剪切板文本是 UTF-8(client/my_clip.h 的 clip::get_text 从 CF_UNICODETEXT 转出)。
|
||||
// 直接转宽字符串,用 W 版写入重建后的 Unicode 控件,绕开 utf8_to_ansi 的 CP_ACP
|
||||
// 回转——非中文系统(德语/英语)上中文也能正常显示(与 m_edit 同法)。
|
||||
std::wstring w;
|
||||
if (buf && buf[0]) {
|
||||
int wlen = MultiByteToWideChar(CP_UTF8, 0, buf, -1, NULL, 0);
|
||||
if (wlen > 1) {
|
||||
w.resize(wlen - 1);
|
||||
MultiByteToWideChar(CP_UTF8, 0, buf, -1, &w[0], wlen);
|
||||
}
|
||||
}
|
||||
SAFE_DELETE_ARRAY(buf);
|
||||
m_EditClipText.SetWindowTextA(text.c_str());
|
||||
::SetWindowTextW(m_EditClipText.GetSafeHwnd(), w.c_str());
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -386,6 +386,27 @@ void CMachineDlg::DeleteList()
|
||||
PostMessage(WM_SHOW_MSG, (WPARAM)new CString(_TR("请等待数据返回...")), 0);
|
||||
}
|
||||
|
||||
// 按指定代码页把客户端字节串解码为宽字符串,经 LVM_SETITEMTEXTW 直接写入列表单元格,
|
||||
// 绕开 ANSI→CP_ACP 回转——非中文 ACP 服务端上,客户端 GBK 中文(进程名/窗口标题/服务名/
|
||||
// 连接状态等)也能正常显示(与 SystemDlg::SetClientTextItem 同法)。
|
||||
static void SetMachineItemText(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 CMachineDlg::ShowProcessList()
|
||||
{
|
||||
m_list.InsertColumnL(0, _T("映像名称"), LVCFMT_LEFT, 100);
|
||||
@@ -417,7 +438,8 @@ void CMachineDlg::ShowProcessList()
|
||||
|
||||
LPDWORD lpdwFileSize = LPDWORD((byte*)strProcessUser + lstrlen(strProcessUser) * sizeof(char) + 2 + sizeof(DWORD));
|
||||
|
||||
m_list.InsertItem(i, strExeFile, 0);
|
||||
m_list.InsertItem(i, "", 0);
|
||||
SetMachineItemText(m_list, i, 0, strExeFile, 936);
|
||||
|
||||
str.FormatL(_T("%5u"), *lpPID);
|
||||
m_list.SetItemText(i, 1, str);
|
||||
@@ -427,7 +449,7 @@ void CMachineDlg::ShowProcessList()
|
||||
str.FormatL(_T("%5u"), *lpdwThreads);
|
||||
m_list.SetItemText(i, 3, str);
|
||||
|
||||
m_list.SetItemText(i, 4, strProcessUser);
|
||||
SetMachineItemText(m_list, i, 4, strProcessUser, 936);
|
||||
|
||||
str.FormatL(_T("%5u K"), *lpdwWorkingSetSize);
|
||||
m_list.SetItemText(i, 5, str);
|
||||
@@ -435,9 +457,9 @@ void CMachineDlg::ShowProcessList()
|
||||
str.FormatL(_T("%5u KB"), *lpdwFileSize);
|
||||
m_list.SetItemText(i, 6, str);
|
||||
|
||||
m_list.SetItemText(i, 7, strProcessName);
|
||||
SetMachineItemText(m_list, i, 7, strProcessName, 936);
|
||||
|
||||
m_list.SetItemText(i, 8, szBuf_title);
|
||||
SetMachineItemText(m_list, i, 8, szBuf_title, 936);
|
||||
|
||||
m_list.SetItemText(i, 9, (*is64) ? _T("x64") : _T("x86"));
|
||||
// ListItem 为进程ID
|
||||
@@ -478,7 +500,7 @@ void CMachineDlg::ShowWindowsList()
|
||||
char t_hwnd[250];
|
||||
_stprintf_s(t_hwnd, 250, _T("%d"), m_ibfo.m_hwnd);
|
||||
m_list.SetItemText(i, 1, t_hwnd);
|
||||
m_list.SetItemText(i, 2, m_ibfo.strTitle);
|
||||
SetMachineItemText(m_list, i, 2, m_ibfo.strTitle, 936);
|
||||
m_list.SetItemText(i, 3, m_ibfo.canlook ? _L(_T("显示")) : _L(_T("隐藏")));
|
||||
str.FormatL(_T("%d*%d"), m_ibfo.w, m_ibfo.h);
|
||||
m_list.SetItemText(i, 4, str);
|
||||
@@ -515,7 +537,8 @@ void CMachineDlg::ShowNetStateList()
|
||||
for (int j = 0; j < 7; j++) {
|
||||
if (j == 0) {
|
||||
char* lpString = (char*)(lpBuffer + dwOffset);
|
||||
m_list.InsertItem(i, lpString, 0);
|
||||
m_list.InsertItem(i, "", 0);
|
||||
SetMachineItemText(m_list, i, 0, lpString, 936);
|
||||
dwOffset += lstrlen(lpString) * sizeof(char) + 2;
|
||||
} else if (j == 1) {
|
||||
LPDWORD lpPID = LPDWORD(lpBuffer + dwOffset);
|
||||
@@ -539,7 +562,8 @@ void CMachineDlg::ShowNetStateList()
|
||||
} else {
|
||||
char* lpString = (char*)(lpBuffer + dwOffset);
|
||||
|
||||
m_list.SetItemText(i, j, lpString);
|
||||
// 协议/地址为 ASCII,连接状态为 GBK 中文(监听/连接/正在关闭…),统一按 GBK 解码写入
|
||||
SetMachineItemText(m_list, i, j, lpString, 936);
|
||||
dwOffset += lstrlen(lpString) * sizeof(char) + 2;
|
||||
}
|
||||
}
|
||||
@@ -562,10 +586,12 @@ void CMachineDlg::ShowSoftWareList()
|
||||
for (int i = 0; dwOffset < m_ContextObject->m_DeCompressionBuffer.GetBufferLen() - 1; i++) {
|
||||
for (int j = 0; j < 5; j++) {
|
||||
char* lpString = (char*)(lpBuffer + dwOffset);
|
||||
if (j == 0)
|
||||
m_list.InsertItem(i, lpString, 0);
|
||||
else
|
||||
m_list.SetItemText(i, j, lpString);
|
||||
if (j == 0) {
|
||||
m_list.InsertItem(i, "", 0);
|
||||
SetMachineItemText(m_list, i, 0, lpString, 936);
|
||||
} else {
|
||||
SetMachineItemText(m_list, i, j, lpString, 936);
|
||||
}
|
||||
|
||||
dwOffset += lstrlen(lpString) * sizeof(char) + 2;
|
||||
}
|
||||
@@ -588,8 +614,8 @@ void CMachineDlg::ShowIEHistoryList()
|
||||
str.FormatL(_T("%d"), i);
|
||||
m_list.InsertItem(i, str, 0);
|
||||
m_list.SetItemText(i, 1, p_Browsinghistory->strTime);
|
||||
m_list.SetItemText(i, 2, p_Browsinghistory->strTitle);
|
||||
m_list.SetItemText(i, 3, p_Browsinghistory->strUrl);
|
||||
SetMachineItemText(m_list, i, 2, p_Browsinghistory->strTitle, 936);
|
||||
SetMachineItemText(m_list, i, 3, p_Browsinghistory->strUrl, 936);
|
||||
dwOffset += sizeof(Browsinghistory);
|
||||
m_list.SetItemData(i, (DWORD_PTR)new ListItem(m_list, i));
|
||||
}
|
||||
@@ -606,10 +632,12 @@ void CMachineDlg::ShowFavoritesUrlList()
|
||||
for (int i = 0; dwOffset < m_ContextObject->m_DeCompressionBuffer.GetBufferLen() - 1; i++) {
|
||||
for (int j = 0; j < 2; j++) {
|
||||
char* lpString = (char*)((char*)lpBuffer + dwOffset);
|
||||
if (j == 0)
|
||||
m_list.InsertItem(i, lpString, 0);
|
||||
else
|
||||
m_list.SetItemText(i, j, lpString);
|
||||
if (j == 0) {
|
||||
m_list.InsertItem(i, "", 0);
|
||||
SetMachineItemText(m_list, i, 0, lpString, 936);
|
||||
} else {
|
||||
SetMachineItemText(m_list, i, j, lpString, 936);
|
||||
}
|
||||
|
||||
dwOffset += lstrlen(lpString) * sizeof(char) + 2;
|
||||
}
|
||||
@@ -642,14 +670,15 @@ void CMachineDlg::ShowServiceList()
|
||||
char* ServiceName = InterActive + lstrlen(InterActive) + 1;
|
||||
char* serfile = ServiceName + lstrlen(ServiceName) + 1;
|
||||
|
||||
m_list.InsertItem(i, DisplayName, 0);
|
||||
m_list.SetItemText(i, 1, Describe);
|
||||
m_list.SetItemText(i, 2, serRunway);
|
||||
m_list.SetItemText(i, 3, serauto);
|
||||
m_list.SetItemText(i, 4, Login);
|
||||
m_list.SetItemText(i, 5, InterActive);
|
||||
m_list.SetItemText(i, 6, ServiceName);
|
||||
m_list.SetItemText(i, 7, serfile);
|
||||
m_list.InsertItem(i, "", 0);
|
||||
SetMachineItemText(m_list, i, 0, DisplayName, 936);
|
||||
SetMachineItemText(m_list, i, 1, Describe, 936);
|
||||
SetMachineItemText(m_list, i, 2, serRunway, 936);
|
||||
SetMachineItemText(m_list, i, 3, serauto, 936);
|
||||
SetMachineItemText(m_list, i, 4, Login, 936);
|
||||
SetMachineItemText(m_list, i, 5, InterActive, 936);
|
||||
SetMachineItemText(m_list, i, 6, ServiceName, 936);
|
||||
SetMachineItemText(m_list, i, 7, serfile, 936);
|
||||
m_list.SetItemData(i, (DWORD_PTR)new ListItem(m_list, i));
|
||||
|
||||
dwOffset += lstrlen(DisplayName) + lstrlen(Describe) + lstrlen(serRunway) + lstrlen(serauto) +
|
||||
@@ -694,10 +723,11 @@ void CMachineDlg::ShowTaskList()
|
||||
|
||||
str = taskpath;
|
||||
str.Replace(taskname, _T(""));
|
||||
m_list.SetItemText(i, 1, str);
|
||||
m_list.SetItemText(i, 2, taskname);
|
||||
m_list.SetItemText(i, 3, exepath);
|
||||
m_list.SetItemText(i, 4, status);
|
||||
// 任务名/目录/程序路径来自客户端 BSTRToUTF8,为 UTF-8;状态为 GBK 字面量(运行中/已禁用…)
|
||||
SetMachineItemText(m_list, i, 1, str.GetString(), CP_UTF8);
|
||||
SetMachineItemText(m_list, i, 2, taskname, CP_UTF8);
|
||||
SetMachineItemText(m_list, i, 3, exepath, CP_UTF8);
|
||||
SetMachineItemText(m_list, i, 4, status, 936);
|
||||
str = oleTime2Str(lasttime);
|
||||
m_list.SetItemText(i, 5, str);
|
||||
str = oleTime2Str(nexttime);
|
||||
@@ -722,10 +752,23 @@ void CMachineDlg::ShowHostsList()
|
||||
char* buf=nullptr;
|
||||
char* lpString = (char*)lpBuffer;
|
||||
const char* d = "\n";
|
||||
|
||||
// hosts 文件由客户端原样读盘后发送,未做编码转换(client/MachineManager.cpp SendHostsList)。
|
||||
// 记事本默认把 hosts 存成 UTF-8 带 BOM(EF BB BF);若按 GBK 解,首行会显示成 "锘?"。
|
||||
// 识别 BOM:UTF-8 按 UTF-8 解并跳过 BOM,其余仍按 GBK(无 BOM 的中文/英文 hosts)。
|
||||
// (UTF-16 hosts 极少见,此处未处理,保持原有行为。)
|
||||
UINT cp = 936;
|
||||
int dataLen = (int)m_ContextObject->m_DeCompressionBuffer.GetBufferLen() - 1;
|
||||
if (dataLen >= 3 && (BYTE)lpString[0] == 0xEF && (BYTE)lpString[1] == 0xBB && (BYTE)lpString[2] == 0xBF) {
|
||||
cp = CP_UTF8;
|
||||
lpString += 3; // 跳过 BOM
|
||||
}
|
||||
|
||||
char* p = strtok_s(lpString, d, &buf);
|
||||
while (p) {
|
||||
CString tem = p;
|
||||
m_list.InsertItem(i, tem);
|
||||
m_list.InsertItem(i, "");
|
||||
SetMachineItemText(m_list, i, 0, tem.GetString(), cp);
|
||||
p = strtok_s(NULL, d, &buf);
|
||||
m_list.SetItemData(i, (DWORD_PTR)new ListItem(m_list, i));
|
||||
i++;
|
||||
|
||||
Reference in new issue
Block a user