在使用MultiByteToWideChar的时候,大部分都知道上述两个参数,MSDN上的解释也是简单到极致。通常我们会选择使用CP_ACP,但是总有人会在没有真正明白它们之间的区别前使用CP_THREAD_ACP。

上周收到一个日方的Bug报告。Bug的上下文基本是这样的:有一个功能是记录设备信息一览的,并可以将这些信息输出到一个文件(格式有很多)。这个文件可以手动实时获取,也可以设置日期和时间定时获取。

Bug的现象是:在英语和日语的环境下,一切都OK。但是在俄语下定时获取文件的功能失效,手动获取确实OK的。

我们模拟俄语的环境是在非俄语的OS下,改变控制面板中的“地域”中的信息为俄语,包括User Locale和System Locale还有位置。

int usize = ::MultiByteToWideChar(CP_THREAD_ACP, 0, name, (int)strlen(name) + 1, NULL, 0);

wchar_t    *unicode = new wchar_t[usize];
if(NULL != unicode)
{
ZeroMemory(unicode, usize * sizeof(wchar_t)); // Convert
::MultiByteToWideChar(CP_THREAD_ACP, 0, name, (int)strlen(name), unicode, usize); // Make Key-source
unsigned char key_message[DM_MAX_SIZE_OF_PARAMS]; memcpy( key_message, SNMPV3_HASH_KEY, strlen(SNMPV3_HASH_KEY) );
memcpy( key_message + strlen(SNMPV3_HASH_KEY),
unicode, usize * sizeof(wchar_t) );
memcpy( key_message + strlen(SNMPV3_HASH_KEY) + usize * sizeof(wchar_t),
hash, SIZE_OF_MESSAGE_DIGEST ); // Make hash
md5.MakeMD5(key_message,
strlen(SNMPV3_HASH_KEY) + usize * sizeof(wchar_t) + SIZE_OF_MESSAGE_DIGEST,
key_data);
if( NULL != key ) memcpy( key, key_data, SIZE_OF_MESSAGE_DIGEST ); delete[] unicode;
}

上面的代码片段是我摘自过程中的出现问题的一段。

后来经过分析,执行写文件的功能是在一个单独的F.exe中做的,而F.exe调用了S.dll中的函数,上述代码就是处于S.dll中。定时写文件的功能是因为主程序有个服务,当时间到达后由服务创建F.exe来执行功能。

在主程序中,手动执行保存文件动作是,进入S.dll中的Thread Locale是和System Locale相同的,为0x0419,即俄语。所以执行MultiByteToWideChar没问题,也就能产生正确的Key用于解密。但是在定时的情况下,由服务创建F.exe进程进入S.dll时,Thread Locale是0x0411,即日语(OS为日语),System Locale还是0x0419。这种情况下,使用MultiByteToWideChar转换的字符串会是乱码,最终也就导致了程序的异常。

在此有个不明白的地方是,为什么由服务启动F.exe进程,执行进程的主线程的Thread Local会是0x0411。正常情况下启动F.exe(通过主程序Create或手动启动),Thread Locale和System Locale都是相同的。CreateProcess中也没有办法来设置Thread Locale让主线程运行在指定的Locale下。

这个也说明了另外一个问题,通过过更改地域信息区模拟其他语言环境还是会存在一些缺陷。上面代码如果是运行在俄语的OS下我想是不会出现这样的问题。

Conclusion

在我们不确定线程的code page时,使用CP_THREAD_ACP并不是一个好主意。因为我们没有办法确定Thread Locale和System Locale是一致的,也就是System Locale和User Locale之间可能会存在不一致性。这篇文章可以做个参考。

CP_THREAD_ACP与CP_ACP的更多相关文章

  1. Windows上的字符转换之CP_ACP和CP_OEMCP

    原文地址:http://blog.sina.com.cn/s/blog_53c1950a010158mw.html Windows API函数MultiByteToWideChar用于多字节编码字符串 ...

  2. CP_ACP : CP_OEMCP

    // filesystem windows_file_codecvt.cpp -----------------------------------------// // Copyright Bema ...

  3. 关于多字节、宽字节、WideCharToMultiByte和MultiByteToWideChar函数的详解

    所谓的短字符,就是用8bit来表示的字符,典型的应用是ASCII码. 而宽字符,顾名思义,就是用16bit表示的字符,典型的有UNICODE. **************************** ...

  4. MULTIBYTETOWIDECHAR的与WIDECHARTOMULTIBYTE的参数详解及相互转换

    第一个就是宽字符到多字节字符转换函数,函数原型如下: int WideCharToMultiByte( UINT CodePage, DWORD dwFlags, LPCWSTR lpWideChar ...

  5. 函数 MultiByteToWideChar() 详解

    函数原型: int MultiByteToWideChar( UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int cchMultiByte ...

  6. 函数WideCharToMultiByte() 详解

    函数原型: int WideCharToMultiByte( UINT CodePage, DWORD dwFlags, LPWSTR lpWideCharStr, int cchWideChar, ...

  7. MultiByteToWideChar和WideCharToMultiByte用法详解

    今天写ini文件的时候发现的问题: TCHAR temp[]; //strcpy_s(temp, request.newVersion); MultiByteToWideChar(CP_ACP, , ...

  8. php连接Access数据库的三种方法

    http://www.php100.com/html/webkaifa/PHP/PHPyingyong/2009/1115/3524.html 虽然不是一个类但先放这儿吧 最近想把一个asp的网站改成 ...

  9. 使用Win32 API 查找文件

    头文件:#include <windows.h> //FindFirstFile() 获得指定目录的第一个文件 HANDLE FindFirstFile( LPCTSTR lpFileNa ...

随机推荐

  1. 知乎 zhihu

    知乎上关于美食的精彩问答有哪些? http://www.zhihu.com/question/22744751/answer/22473212 知乎上关于乐队的精彩问答有哪些? http://www. ...

  2. UITabBar - 深度解剖

    for (UIView *tabbarbutton in self.subviews) { //        NSLog(@"%@",tabbarbutton);         ...

  3. asp:第三平台登陆

    第三平台登陆接口申请网址: http://open.51094.com/ 文档: 第三方合作登录平台使用说明 为方便更多的开发朋友,本人特将当前市面上所有支持第三方联合登录的接口集为一体,以前需要多次 ...

  4. 重置mysql管理员密码

    重置管理员密码 1.关闭mysql 2.开启mysql,跳过授权表mysql服务 提示:如果此步骤操作成功,那么任何用户登陆MySQL都不需要用户名与密码 保持此窗口不能关闭 3.重新cmd,登陆 m ...

  5. C++ 代码性能优化 -- 循环分割提高并行性

    对于一个可结合和可交换的合并操作来说,比如整数的加法或乘法, 我们可以通过将一组合并操作分割成 2 个或更多的部分,并在最后合并结果来提高性能. 原理: 普通代码只能利用 CPU 的一个寄存器,分割后 ...

  6. Linux之在CentOS上一次艰难的木马查杀过程

    今天朋友说他一台要准备上线的生产服务器被挂马,特征ps命令找不到进程,top能看到负载最高的一个程序是一个随机的10位字母的东西,kill掉之后自动再次出现一个随机10位字母的进程. 我让他关闭这个机 ...

  7. install xdebug on fedora

    Compiling There is a wizard available that provides you with the correct file to download, and which ...

  8. Java添加事件的四种方式

    Java添加事件的几种方式(转载了codebrother的文章,做了稍微的改动) /** * Java事件监听处理——自身类实现ActionListener接口,作为事件监听器 * * @author ...

  9. web api 如何接收post过来的json字符串

    前言 好久没有写博客了,有一天同学问我咋不写了,我说没啥写的,都是一些基础的东西.然后他说,难道写东西不是为了总结吗?我说是的.....额,我是不知道怎么说了.确实是写博客也是给自己的一种总结,一种理 ...

  10. css3的3D翻牌效果

    利用hover控制动画,一个从翻面向正面翻,一个从正面向反面翻. 利用:backface-visibility: hidden;控制反面的元素不显示. 不支持的浏览器直接切换层级换图. <!DO ...