如何解决Unicode /多字节兼容性问题

时间:2020-03-20 00:15:47

标签: c++

我想将项目保留在多字节上,而不是将其切换为Unicode。我在尝试使我的类型按如下方式协同工作时遇到一些错误(VS2019设置为bybye):

原始错误是:“ char *”类型的参数与以下行的“ const wchar_t *”类型不兼容

if (!wcscmp(ModuleEntry.szModule, ModuleName)

ModuleEntry的类型为MODULEENTRY32

如果我将ModuleEntry的类型更改为MODULEENTRY32W,则会出现以下错误:

参数类型“ MODULEENTRY32W”与类型“ LPMODULEENTRY32”不兼容。

完整功能供您参考:

DWORD GetModuleBaseAddress(const wchar_t* ModuleName, DWORD ProcessId) {
    MODULEENTRY32 ModuleEntry = { 0 };
    HANDLE SnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, ProcessId);

    if (!SnapShot)
        return NULL;

    ModuleEntry.dwSize = sizeof(ModuleEntry);

    if (!Module32First(SnapShot, &ModuleEntry))
        return NULL;
    do {    
        if (!wcscmp(ModuleEntry.szModule, ModuleName)) {        
            CloseHandle(SnapShot);
            return (DWORD)ModuleEntry.modBaseAddr;
        }   
    } while (Module32Next(SnapShot, &ModuleEntry));

    CloseHandle(SnapShot);
    return NULL;
}

谢谢。

1 个答案:

答案 0 :(得分:2)

首先,如果SnapShot失败,则会泄漏Module32First()句柄。

第二,您使用的是基于TCHAR的Module32 API版本,但是您正在传入wchar_t Unicode数据以将枚举的模块数据进行比较。您已将项目设置为MultiByte,这意味着TCHAR映射到char,而基于TCHAR的API映射到ANSI API。

因此,您实际上是在调用Module32 API的 ANSI 版本,即MODULEENTRY32映射到MODULEENTRY32AModule32First() / Module32Next()映射到Module32FirstA() / Module32NextA()

您不能将char数据传递到wcscmp(),也不能将wchar_t数据传递给strcmp()。因此,如果继续使用ANSI API,则必须在运行时在一个方向或另一个方向上执行数据转换,转换为:

  • char模块数据通过wchar_t转换为MultiByteToWieChar()

  • wchar_t比较数据通过char

  • 转换为WideCharToMultiByte()

然后您才能使用适当的函数来比较两个数据。

由于要传递wchar_t数据以进行比较,因此应明确地调用Module32 API的 Unicode 版本,而不是TCHAR版。您不必将整个项目都设置为Unicode即可使用Unicode API,例如:

void* GetModuleBaseAddress(const wchar_t* ModuleName, DWORD ProcessId)
{
    HANDLE SnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, ProcessId);
    if (SnapShot)
    {
        MODULEENTRY32W ModuleEntry = { 0 };
        ModuleEntry.dwSize = sizeof(ModuleEntry);

        if (Module32FirstW(SnapShot, &ModuleEntry))
        {
            do
            {
                if (wcscmp(ModuleEntry.szModule, ModuleName) == 0)
                {
                    CloseHandle(SnapShot);
                    return ModuleEntry.modBaseAddr;
                }   
            }
            while (Module32NextW(SnapShot, &ModuleEntry));
        }

        CloseHandle(SnapShot);
    }

    return NULL;
}