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

C++ 带有Unicode UTF-16(1200)代码页字符串表的VerQueryValue失败,c++,winapi,mfc,fileversioninfo,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, 4

我正在尝试使用以下代码从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上没有该文件,则为y)的字符串表编码为
wLanguage
为0,
wCodePage
为1200。在这种情况下,
VerQueryValue
失败,错误代码
error\u RESOURCE\u TYPE\u NOT\u FOUND
。但当我在文件资源管理器中检查该文件时,我知道该文件具有“文件描述”属性:


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

使用资源黑客查看MSTTSEngine.dll,资源数据中存在不一致。
VarFileInfo\Translation
定义的语言ID是
0x0000
,而
StringFileInfo
定义的是
0x0409
。只有代码页值匹配

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
无法很好地处理此类版本资源损坏的情况,因为无法独立于
VarFileInfo
枚举
StringFileInfo

解决方案
有另一种方法可以使用获取版本资源信息。我已经给出了一个答案。在我的机器上,它正确地从MSTTSEngine.dll读取文件描述。

A,只是为了将这些问题链接在一起。可能的话,你自己为解析版本资源编写一个小类到树结构,并使用-@RbMm:wow,这是一个非常酷的低级方法。谢谢分享!不过有一个问题,我正在检查您的解析器代码,您从哪里获取版本资源的格式?@c0000fd-这是文档化的代码,当然可以工作。我只概括了msdn中的信息。真的,如果看得更近-所有项目都有共同点format@c00000fd-此代码也可用于修改资源节点,并通过
RsrcNode::store
存储,然后在call
UpdateResource
@RemyLebeau中使用:谢谢你用这个无用的答案锁定了这个问题。提出的启发式猜测并不比仅仅这样做要好:
for(DWORD langID=0;langID