CP_THREAD_ACP与CP_ACP
在使用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的更多相关文章
- Windows上的字符转换之CP_ACP和CP_OEMCP
原文地址:http://blog.sina.com.cn/s/blog_53c1950a010158mw.html Windows API函数MultiByteToWideChar用于多字节编码字符串 ...
- CP_ACP : CP_OEMCP
// filesystem windows_file_codecvt.cpp -----------------------------------------// // Copyright Bema ...
- 关于多字节、宽字节、WideCharToMultiByte和MultiByteToWideChar函数的详解
所谓的短字符,就是用8bit来表示的字符,典型的应用是ASCII码. 而宽字符,顾名思义,就是用16bit表示的字符,典型的有UNICODE. **************************** ...
- MULTIBYTETOWIDECHAR的与WIDECHARTOMULTIBYTE的参数详解及相互转换
第一个就是宽字符到多字节字符转换函数,函数原型如下: int WideCharToMultiByte( UINT CodePage, DWORD dwFlags, LPCWSTR lpWideChar ...
- 函数 MultiByteToWideChar() 详解
函数原型: int MultiByteToWideChar( UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int cchMultiByte ...
- 函数WideCharToMultiByte() 详解
函数原型: int WideCharToMultiByte( UINT CodePage, DWORD dwFlags, LPWSTR lpWideCharStr, int cchWideChar, ...
- MultiByteToWideChar和WideCharToMultiByte用法详解
今天写ini文件的时候发现的问题: TCHAR temp[]; //strcpy_s(temp, request.newVersion); MultiByteToWideChar(CP_ACP, , ...
- php连接Access数据库的三种方法
http://www.php100.com/html/webkaifa/PHP/PHPyingyong/2009/1115/3524.html 虽然不是一个类但先放这儿吧 最近想把一个asp的网站改成 ...
- 使用Win32 API 查找文件
头文件:#include <windows.h> //FindFirstFile() 获得指定目录的第一个文件 HANDLE FindFirstFile( LPCTSTR lpFileNa ...
随机推荐
- effective c++(07)之为多态基类声明virtual析构函数
class TimeKeeper { public: TimeKeeper() ; ~TimeKepper() ; ... } ; class AtomicClock:public TimeKeepe ...
- 浅析foreach原理
在日常开发工作中,我们发现很多对象都能通过foreach来遍历,比如HashTable.Dictionary.数组等数据类型.那为何这些对象能通过foreach来遍历呢?如果写一个普通的Person类 ...
- 【html】【16】高级篇--毛玻璃效果[模糊]
参考: http://www.zhangxinxu.com/wordpress/2013/11/%E5%B0%8Ftip-%E4%BD%BF%E7%94%A8css%E5%B0%86%E5%9B%BE ...
- Java实战之02Hibernate-05检索策略、检索方式
十一.Hibernate的检索策略 1.概述: 查询的时机:什么时候去查? /** * 一张表的检索策略我们称之为: * 类级别的检索策略. * 注意:只要是说类级别的检索策略,就一定不涉及关联对象. ...
- Eclipse恢复初始界面&打开视图
恢复初始界面: 单击菜单栏的windows主菜单,在子菜单里选择 Reset Perspective 会弹出各对话框 ,点 ok就可以了 打开视图:Windows->Show View 其中Ot ...
- Vijos P1325桐桐的糖果计划
> P1325桐桐的糖果计划 标签:**图结构 强连通分量** 描述 桐桐很喜欢吃棒棒糖.他家处在一大堆糖果店的附近. 但是,他们家的区域经常出现塞车.塞人等情况,这导致他不得不等到塞的车或人走 ...
- c&c++函数的参数和返回值的传递终结版
c++函数的参数和返回值的传递方式有三种:值传递.指针传递和引用传递. 在这之前先看几个例子: 一, int a=10; int b=a; b+=10; 此时b是a的一个拷贝,改变b的值,a并不会受到 ...
- Android SDK下载技巧
转载说明 本篇文章可能已经更新,最新文章请转:http://www.sollyu.com/android-sdk-download-tips/ 说明 想必在国内的你,是不是经常在下载Android S ...
- mysql---整体备份和增量备份
整体备份: 对整张表或者整个数据库甚至所有数据库进行备份. 增量备份: 对某一范围内的数据进行备份. 1.整体备份: 对表进行备份: 针对存储引擎为myisam的表,可以直接复制frm.myd.myi ...
- 银行卡号Luhm校验Java实现代码
import java.util.regex.Matcher; import java.util.regex.Pattern; public class CheckBankNumber { //Des ...