我已经用我的Win8项目从Win10搬到了VS2012 C++。我在Win8中使用Win8函数时没有问题,但现在在调试过程中出现了错误:
Unhandled exception at 0x77C88F11 (ntdll.dll) in MyApp.exe: 0xC0000005: Access violation writing location 0x00AAC2DC.我使用来自MSDN的示例代码
CString GetVersionInfo(HMODULE hLib, CString csEntry)
{
CString csRet;
if (hLib == NULL)
hLib = AfxGetResourceHandle();
HRSRC hVersion = FindResource( hLib,
MAKEINTRESOURCE(VS_VERSION_INFO), RT_VERSION );
if (hVersion != NULL)
{
HGLOBAL hGlobal = LoadResource( hLib, hVersion );
if ( hGlobal != NULL)
{
LPVOID versionInfo = LockResource(hGlobal);
if (versionInfo != NULL)
{
DWORD vLen,langD;
BOOL retVal;
LPVOID retbuf=NULL;
static char fileEntry[256];
sprintf(fileEntry,"\\VarFileInfo\\Translation");
retVal = VerQueryValue(versionInfo,fileEntry,&retbuf,(UINT *)&vLen);
if (retVal && vLen==4)
{
memcpy(&langD,retbuf,4);
sprintf(fileEntry, "\\StringFileInfo\\%02X%02X%02X%02X\\%s",
(langD & 0xff00)>>8,langD & 0xff,(langD & 0xff000000)>>24,
(langD & 0xff0000)>>16, csEntry);
}
else
sprintf(fileEntry, "\\StringFileInfo\\%04X04B0\\%s",
GetUserDefaultLangID(), csEntry);
if (VerQueryValue(versionInfo,fileEntry,&retbuf,(UINT *)&vLen))
csRet = (char*)retbuf;
}
}
UnlockResource( hGlobal );
FreeResource( hGlobal );
}
return csRet;
}有什么问题吗?
发布于 2016-11-28 20:36:09
您正在直接访问版本资源数据,而不是使用GetFileVersionInfo()。因此,不能使用VerQueryValue()查询本地化的值,您可以只查询的VS_FIXEDFILEINFO结构,而不需要查询其他任何东西。即使如此,您也不能将LockResource()的返回值用于该访问。在访问结构之前,必须将资源数据复制到您自己的读/写内存缓冲区中。
这是因为GetFileVersionInfo()执行VerQueryValue()内部使用的数据查找和内存块分配。雷蒙德·陈在他的博客上解释道:
VerQueryValue的第一个参数实际上必须是从GetFileVersionInfo获得的缓冲区。
文档指出,VerQueryValue的第一个参数必须是GetFileVersionInfo函数出于某种原因返回的缓冲区。 GetFileVersionInfo返回的缓冲区是一个特殊格式化的不透明数据块,以便VerQueryValue能够工作。您不应该查看该缓冲区,当然也不能尝试“以其他方式获取数据”。因为(如果是这样的话),VerQueryValue将在缓冲区中查找不按函数所期望的方式格式化的内容。
这就是为什么您要崩溃的原因-- VerQueryValue()正在尝试访问未正确设置的内存。
如果要直接访问版本资源,则需要手动解析其数据,根本不使用VerQueryValue()。你很幸运你的代码从来没有崩溃过。您是在未定义的行为区域操作的!你的运气已经用完了。你需要重写代码来做正确的事情。
https://stackoverflow.com/questions/40840337
复制相似问题