-
Notifications
You must be signed in to change notification settings - Fork 162
Open
Labels
Description
Thanks for the great project! I'm trying to use it for reading versions from executables.
I've built it with Qt Creator, gcc, qbs (see my .qbs and .cpp files in the archive): pe-parse.zip
Most EXE and DLL files I've tried were parsed fine but two of them failed:
- System.Text.Json.dll - getDebugDir fails. Since this file has an Authenticode signature of .NET project, it's unlikely that the file is currupt.
- ConfKarat.exe - incorrect version resource is passed to IterRsrc callback. Windows explorer file properties box shows the version. I can also see the version in a hex editor. But res.buf->buf in my code doesn't point to anything containing VS_VERSION_INFO and 0xfeef04bd signature.
Here is my code:
struct MY_VS_FIXEDFILEINFO
{
quint32 dwSignature;
quint32 dwStrucVersion;
quint32 dwFileVersionMS;
quint32 dwFileVersionLS;
quint32 dwProductVersionMS;
quint32 dwProductVersionLS;
quint32 dwFileFlagsMask;
quint32 dwFileFlags;
quint32 dwFileOS;
quint32 dwFileType;
quint32 dwFileSubtype;
quint32 dwFileDateMS;
quint32 dwFileDateLS;
};
int extractVersionFromResourceCallback(void* ptr, const peparse::resource& res)
{
// Skip all resource types execpt RT_VERSION
if(res.type != 16) return 0;
// Find VS_FIXEDFILEINFO in the buffer
auto structSize = sizeof(MY_VS_FIXEDFILEINFO);
for(size_t offset = 0; offset + structSize <= res.size; offset += 4)
{
auto verInfo = (const MY_VS_FIXEDFILEINFO*)(res.buf->buf + offset);
if (verInfo->dwSignature == 0xfeef04bd)
{
QString& result = *(QString*)ptr;
result = QStringLiteral("%1.%2.%3.%4")
.arg(( verInfo->dwFileVersionMS >> 16 ) & 0xffff)
.arg(( verInfo->dwFileVersionMS >> 0 ) & 0xffff)
.arg(( verInfo->dwFileVersionLS >> 16 ) & 0xffff)
.arg(( verInfo->dwFileVersionLS >> 0 ) & 0xffff);
return 1;
}
}
// Maybe there's another version resource we'll understand
return 0;
}
...
// Have to use mutex because pe-parse library uses globals
static QMutex peparseMutex;
QMutexLocker locker(&peparseMutex);
// Try to parse PE
auto peptr = peparse::ParsePEFromPointer((std::uint8_t*)m_data.data(), m_data.size());
if (peptr == nullptr)
{
qWarning() << "Failed to parse PE. Code:" << peparse::GetPEErr() << endl
<< "Error:" << QString::fromStdString(peparse::GetPEErrString()) << endl
<< "Location:" << QString::fromStdString(peparse::GetPEErrLoc());
return QString();
}
// Make sure we cleanup properly
try
{
// Iterate resources
QString result;
peparse::IterRsrc(peptr, extractVersionFromResourceCallback, &result);
DestructParsedPE(peptr);
return result;
}
catch (...)
{
DestructParsedPE(peptr);
throw;
}