具有Unicode UTF-16(1200)代码页字符串表的VerQueryValue失败

时间:2019-01-28 06:04:11

标签: c++ winapi mfc fileversioninfo

我正在尝试使用以下代码从PE文件中检索文件描述:

//This code was simplified &
//most error checks were removed for brevity

BYTE* pData = new BYTE[4096];
LPCTSTR path = L"C:\\Windows\\system32\\Speech\\Engines\\TTS\\MSTTSEngine.dll";
if(::GetFileVersionInfo(path, NULL, 4096, pData))
{
    struct LANGANDCODEPAGE
    {
        WORD wLanguage;
        WORD wCodePage;
    } *lpTranslate = NULL;

    UINT cbTranslate;
    if(VerQueryValue(pData,  L"\\VarFileInfo\\Translation", (LPVOID*)&lpTranslate, &cbTranslate))
    {
        CString strBlock;
        strBlock.Format(L"\\StringFileInfo\\%04x%04x\\FileDescription", 
            lpTranslate[0].wLanguage,
            lpTranslate[0].wCodePage
            );

        UINT dwProdLn = 0;
        VOID* lpBufferName = NULL;
        if(VerQueryValue(pData, strBlock, &lpBufferName, &dwProdLn))
        {
            TRACE(L"Description: %s", lpBufferName);
        }
        else
        {
            TRACE(L"Error=%d", ::GetLastError());
        }
    }

    delete[] pData;
}

该特定文件(如果在Windows 10上没有,则为here's the cop y),其字符串表编码为wLanguage为0,wCodePage为1200。 VerQueryValue失败,错误代码为ERROR_RESOURCE_TYPE_NOT_FOUND。但是我知道在文件浏览器中检查该文件时,该文件具有“文件描述”属性:

enter image description here

那么我上面的代码在做什么错了?

1 个答案:

答案 0 :(得分:3)

使用Resource Hacker查看MSTTSEngine.dll,资源数据不一致。 VarFileInfo\Translation定义的语言ID为0x0000,而StringFileInfo定义0x0409。只有CodePage值匹配。

BLOCK "StringFileInfo"
{
    BLOCK "040904b0"
    //     ^^^^ -> Problem
    {
        VALUE "CompanyName", "Microsoft Corporation"
        VALUE "FileDescription", "Microsoft TTS Engine (Desktop)"
        // [...]
    }
}

BLOCK "VarFileInfo"
{
    VALUE "Translation", 0x0000 0x04B0
    //                     ^^^^ -> Problem
}

因此,您的代码尝试读取StringFileInfo\000004B0,它不存在。 不幸的是,VerQueryValue无法很好地处理这种情况,因为没有办法独立于StringFileInfo来枚举VarFileInfo块。

解决方案

还有一种使用shell property API获取版本资源信息的方法。我给了example in this answer。在我的计算机上,它可以从MSTTSEngine.dll正确读取文件描述。