c++ - 带有 Unicode UTF-16 (1200) 代码页字符串表的 VerQueryValue 失败
问题描述
我正在尝试使用以下代码从 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 上没有它,这里是副本wLanguage
)具有编码为 0 和wCodePage
1200 的字符串表。在这种情况下VerQueryValue
失败并显示错误代码ERROR_RESOURCE_TYPE_NOT_FOUND
。但是当我在文件资源管理器中检查该文件时,我知道该文件具有“文件描述”属性:
那么我在上面的代码中做错了什么?
解决方案
使用 Resource Hacker 查看 MSTTSEngine.dll,资源数据存在不一致。VarFileInfo\Translation
由is定义的语言 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 属性 API获取版本资源信息。我在这个答案中给出了一个例子。在我的机器上,它正确地从 MSTTSEngine.dll 读取文件描述。
推荐阅读
- javascript - Vue.js - 动态删除特定组件
- nginx - 剂量 nginx server_name 如何工作
- sonarqube - sonarqube 中的卸载插件:只能作为 SonarSource 版本的一部分卸载
- css - 为什么我在背景图像上看不到我的线性渐变?
- javascript - 当我单击 p-autocomplete (prime-ng) 中的下拉按钮时,会有微调器出现
- c++ - 在 Visual Studio 中链接 Kim Walisch Primes 库
- visual-studio - 安装和配置 react-native-fbsdk 后构建失败
- html - 带有 colspan 的 HTML 表无法正常工作
- angular - 如何将来自多个 HTTP 请求的 HTTPErrorResponse 对象存储在一个数组中?
- java - 将数据从一个类存储到另一个类