From 80de07851c1159e2eba58b61bbeac9d8e9b54292 Mon Sep 17 00:00:00 2001 From: baiqing Date: Wed, 6 May 2026 18:08:21 +0800 Subject: [PATCH 1/2] =?UTF-8?q?fix(windows-ime):=20=E9=9D=99=E6=80=81?= =?UTF-8?q?=E9=93=BE=E6=8E=A5=20CRT=20=E9=98=B2=20host=20=E8=BF=9B?= =?UTF-8?q?=E7=A8=8B=20MSVCP140=20=E5=8A=AB=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 用户反馈:在 Windows 11 切到微软拼音时 QQ (QQEX.exe v9.9.26.44725) 崩 0xc0000005,故障模块 D:\program\QQ\versions\\resources\app\ MSVCP140.dll @ 偏移 0x13080。 根因(DLL Hell 经典场景): 1. QQ 把私有版本的 MSVCP140.dll 放在 app/ 目录,DLL 搜索顺序优先于系统 2. ctfmon 切微软拼音 → 把所有已注册 TSF DLL 加载进 QQ 进程 3. 我们 OpenLessIme.dll 此前用 MSBuild 默认 RuntimeLibrary(= MultiThreadedDLL,动态链接 MSVCP140.dll/VCRUNTIME140.dll/UCRT) 4. 在 QQ 进程内被绑给 QQ 自带的旧版 MSVCP140 → 调 std::wstring / std::thread / std::mutex 等跑的是 QQ 那份 → ABI 行为漂移 → AV 修复: - vcxproj 4 处 ItemDefinitionGroup(Debug/Release × Win32/x64)显式声明 MultiThreaded(Release)/ MultiThreadedDebug(Debug)。 - DLL 自带 CRT 副本,QQ 私有 MSVCP140 劫持不到。 - DLL 体积 +~300 KB;DLL 内部 STL 不能跨边界共享,但我们 IPC 走 named pipe + JSON(C ABI 友好),不受影响。 不动的部分: - TSF 接口本身已是 COM C ABI(vtable + COM-typed 参数),无需改 - 重量级 ASR/LLM/polish 早已在 OpenLess.exe 主进程,DLL 只做 TSF text service hooks + IPC(已合规"组件极简,IPC 通信"原则) QQ 客观脆弱性已整理详细报告(桌面 PDF/DOCX + GitHub issue),用于上报 TSRC:app/ 目录下 MSVCP140 劫持系统 CRT、版本号目录嵌套混乱、无 IME 崩溃隔离机制、CRT 漂移。 --- openless-all/app/windows-ime/OpenLessIme.vcxproj | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/openless-all/app/windows-ime/OpenLessIme.vcxproj b/openless-all/app/windows-ime/OpenLessIme.vcxproj index 2bbe9feb..956cd1fa 100644 --- a/openless-all/app/windows-ime/OpenLessIme.vcxproj +++ b/openless-all/app/windows-ime/OpenLessIme.vcxproj @@ -75,6 +75,12 @@ WIN32;_WINDOWS;_USRDLL;OPENLESSIME_EXPORTS;%(PreprocessorDefinitions) true stdcpp17 + + MultiThreadedDebug Windows @@ -89,6 +95,7 @@ WIN32;_WINDOWS;_USRDLL;OPENLESSIME_EXPORTS;%(PreprocessorDefinitions) true stdcpp17 + MultiThreadedDebug Windows @@ -105,6 +112,7 @@ WIN32;NDEBUG;_WINDOWS;_USRDLL;OPENLESSIME_EXPORTS;%(PreprocessorDefinitions) true stdcpp17 + MultiThreaded Windows @@ -123,6 +131,7 @@ WIN32;NDEBUG;_WINDOWS;_USRDLL;OPENLESSIME_EXPORTS;%(PreprocessorDefinitions) true stdcpp17 + MultiThreaded Windows From 901e9dfe3f2595ecf02d92c7f33de79205e07ff6 Mon Sep 17 00:00:00 2001 From: baiqing Date: Wed, 6 May 2026 19:07:54 +0800 Subject: [PATCH 2/2] =?UTF-8?q?fix(windows-ime):=20=E7=A7=BB=E9=99=A4=20Di?= =?UTF-8?q?sableThreadLibraryCalls=20=E2=80=94=20/MT=20=E4=B8=8B=E9=9C=80?= =?UTF-8?q?=20thread=20=E9=80=9A=E7=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Codex P1 (PR #287):DLL 改用 /MT 静态链接 CRT 后,仍调 DisableThreadLibraryCalls(instance) 会让静态 CRT 拿不到 DLL_THREAD_DETACH 通知,per-thread TLS 初始化/清理断裂 — 在 host 进程(QQ / Office / 微软拼音切换)创建新 input thread 时反而把这次想修的崩溃问题重新引回。 Microsoft 文档 DisableThreadLibraryCalls 备注明确:使用 static CRT 的 DLL 不应禁用 thread library calls。 修复:删除该调用;保留 g_module 缓存。 --- openless-all/app/windows-ime/src/dllmain.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/openless-all/app/windows-ime/src/dllmain.cpp b/openless-all/app/windows-ime/src/dllmain.cpp index 84476ba2..624c79f7 100644 --- a/openless-all/app/windows-ime/src/dllmain.cpp +++ b/openless-all/app/windows-ime/src/dllmain.cpp @@ -13,9 +13,13 @@ LONG g_object_count = 0; BOOL APIENTRY DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) { UNREFERENCED_PARAMETER(reserved); + // 不调用 DisableThreadLibraryCalls:DLL 现在用 /MT 静态链接 CRT,CRT 需要 + // DLL_THREAD_ATTACH / DLL_THREAD_DETACH 通知做 per-thread TLS 初始化与清理。 + // 在 host 进程(如 QQ / Office)切输入法新建 input thread 时禁用通知,会让 + // 静态 CRT 的 thread-local 资源泄漏 / 行为不稳定,反而把这次想修的崩溃问题 + // 重新引回来。详见 Microsoft 文档 DisableThreadLibraryCalls 备注。 if (reason == DLL_PROCESS_ATTACH) { g_module = instance; - DisableThreadLibraryCalls(instance); } return TRUE;