C++ Win32开发如何修改GetLocaleInfoA返回的默认代码页为CP_UTF8
GetLocaleInfoA 查询 LOCALE_IDEFAULTANSICODEPAGE 时,默认读取当前进程绑定的ANSI代码页配置,不存在官方接口可直接修改系统层面的全局返回值,可根据实际场景选择以下三种可行方案:
方案1:进程级开启原生UTF-8支持(推荐,无侵入兼容系统逻辑)
Windows 10 1903(内部版本18362)及以上版本支持进程单独配置默认ANSI代码页为UTF-8,配置后所有A系列Win32 API默认使用CP_UTF8(代码页65001),此时GetLocaleInfoA查询LOCALE_IDEFAULTANSICODEPAGE会直接返回65001,无需修改现有业务代码。
配置方法是在程序manifest清单中添加如下片段:
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <application xmlns="urn:schemas-microsoft-com:asm.v3"> <windowsSettings> <activeCodePage xmlns="http://schemas.microsoft.com/SMI/2019/WindowsSettings">UTF-8</activeCodePage> </windowsSettings> </application> </assembly>
注意:该方案不支持Win10 1903以下的旧系统,旧系统会自动忽略该配置,回退到原系统默认ANSI代码页。
方案2:直接覆写业务逻辑中的代码页变量(最稳妥,无系统版本兼容问题)
你贴出的代码最终是将获取到的代码页值存入ms_uInputCodePage变量,完全不需要修改系统接口行为,直接在调用后强制赋值即可,无任何兼容风险:
char szCodePage[8]; int iRc = GetLocaleInfoA( MAKELCID( GETLANG(), SORT_DEFAULT ), LOCALE_IDEFAULTANSICODEPAGE, szCodePage, COUNTOF( szCodePage ) ); // 直接覆写为UTF-8代码页 ms_uInputCodePage = CP_UTF8; // CP_UTF8宏对应值即为65001
如果需要保留原有逻辑做兼容,也可以增加判断逻辑,仅在特定语言/场景下强制切换为UTF-8即可。
方案3:API Hook拦截接口返回(适用于无法修改调用方代码的场景)
如果调用GetLocaleInfoA的逻辑在第三方库中、无法直接修改对应代码,可以在进程内对GetLocaleInfoA做inline hook,拦截查询LOCALE_IDEFAULTANSICODEPAGE的请求,直接返回65001的字符串即可。以常用的MinHook库为例,hook逻辑示例:
// 原函数指针定义 typedef int (WINAPI* pfnGetLocaleInfoA)(LCID, LCTYPE, LPSTR, int); pfnGetLocaleInfoA oriGetLocaleInfoA = nullptr; // hook后的自定义函数 int WINAPI hookedGetLocaleInfoA(LCID lcid, LCTYPE lcType, LPSTR lpData, int cchData) { // 拦截默认ANSI代码页查询 if (lcType == LOCALE_IDEFAULTANSICODEPAGE && cchData >= 6) { strcpy_s(lpData, cchData, "65001"); return 5; // 返回字符串长度(不含终止空字符) } // 其余查询走原系统逻辑 return oriGetLocaleInfoA(lcid, lcType, lpData, cchData); } // 初始化hook的逻辑,程序启动时调用即可 void InitHook() { MH_Initialize(); MH_CreateHook(GetProcAddress(GetModuleHandleA("kernel32.dll"), "GetLocaleInfoA"), hookedGetLocaleInfoA, (void**)&oriGetLocaleInfoA); MH_EnableHook(MH_ALL_HOOKS); }
注意:该方案仅在当前进程内生效,不会影响其他程序运行。
不推荐操作
不要尝试修改系统全局的非Unicode程序默认代码页,该配置会影响系统内所有未做Unicode支持的程序,极易导致老旧软件出现乱码、运行异常问题。
内容的提问来源于stack exchange,提问作者Erik Schvarcz

