zoukankan      html  css  js  c++  java
  • 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之间可能会存在不一致性。这篇文章可以做个参考。

  • 相关阅读:
    BSGS模板(互质与不互质) 洛谷P4195、P3846
    整除分块(数论分块)
    洛谷P3327 [SDOI2015]约数个数和——莫比乌斯反演
    模块二
    模块
    二分法 匿名函数
    3.26作业
    函数的递归调用
    yield表达式 三元表达式
    3.25作业
  • 原文地址:https://www.cnblogs.com/navono007/p/3422110.html
Copyright © 2011-2022 走看看