C++ 带有Unicode UTF-16(1200)代码页字符串表的VerQueryValue失败
我正在尝试使用以下代码从PE文件检索文件描述: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
//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
存储,然后在callUpdateResource
@RemyLebeau中使用:谢谢你用这个无用的答案锁定了这个问题。提出的启发式猜测并不比仅仅这样做要好:for(DWORD langID=0;langID