COMMON: Fix loading version information from 16-bit executables

This commit is contained in:
Cameron Cawley 2021-07-13 17:03:51 +01:00 committed by Eugene Sandulenko
parent be5452fccc
commit 4736b0ed99
6 changed files with 112 additions and 65 deletions

View file

@ -218,69 +218,6 @@ WinResources::VersionInfo *WinResources::getVersionResource(const WinResourceID
return info;
}
WinResources::VersionInfo *WinResources::parseVersionInfo(SeekableReadStream *res) {
VersionInfo *info = new VersionInfo;
while (res->pos() < res->size() && !res->eos()) {
while (res->pos() % 4 && !res->eos()) // Pad to 4
res->readByte();
/* uint16 len = */ res->readUint16LE();
uint16 valLen = res->readUint16LE();
uint16 type = res->readUint16LE();
uint16 c;
Common::U32String key;
while ((c = res->readUint16LE()) != 0 && !res->eos())
key += c;
while (res->pos() % 4 && !res->eos()) // Pad to 4
res->readByte();
if (res->eos())
break;
if (type != 0) { // text
Common::U32String value;
for (int j = 0; j < valLen; j++)
value += res->readUint16LE();
info->hash.setVal(key.encode(), value);
} else {
if (key == "VS_VERSION_INFO") {
// Signature check
if (res->readUint32LE() != 0xFEEF04BD)
return info;
res->readUint32LE(); // struct version
// The versions are stored a bit weird
info->fileVersion[1] = res->readUint16LE();
info->fileVersion[0] = res->readUint16LE();
info->fileVersion[3] = res->readUint16LE();
info->fileVersion[2] = res->readUint16LE();
info->productVersion[1] = res->readUint16LE();
info->productVersion[0] = res->readUint16LE();
info->productVersion[3] = res->readUint16LE();
info->productVersion[2] = res->readUint16LE();
info->fileFlagsMask = res->readUint32LE();
info->fileFlags = res->readUint32LE();
info->fileOS = res->readUint32LE();
info->fileType = res->readUint32LE();
info->fileSubtype = res->readUint32LE();
info->fileDate[0] = res->readUint32LE();
info->fileDate[1] = res->readUint32LE();
info->hash.setVal("File:", Common::String::format("%d.%d.%d.%d", info->fileVersion[0], info->fileVersion[1], info->fileVersion[2], info->fileVersion[3]));
info->hash.setVal("Prod:", Common::String::format("%d.%d.%d.%d", info->productVersion[0], info->productVersion[1], info->productVersion[2], info->productVersion[3]));
}
}
}
return info;
}
WinResources::VersionInfo::VersionInfo() {
fileVersion[0] = fileVersion[1] = fileVersion[2] = fileVersion[3] = 0;
productVersion[0] = productVersion[1] = productVersion[2] = productVersion[3] = 0;
@ -292,4 +229,36 @@ WinResources::VersionInfo::VersionInfo() {
fileDate[0] = fileDate[1] = 0;
}
bool WinResources::VersionInfo::readVSVersionInfo(SeekableReadStream *res) {
// Signature check
if (res->readUint32LE() != 0xFEEF04BD)
return false;
res->readUint32LE(); // struct version
// The versions are stored a bit weird
fileVersion[1] = res->readUint16LE();
fileVersion[0] = res->readUint16LE();
fileVersion[3] = res->readUint16LE();
fileVersion[2] = res->readUint16LE();
productVersion[1] = res->readUint16LE();
productVersion[0] = res->readUint16LE();
productVersion[3] = res->readUint16LE();
productVersion[2] = res->readUint16LE();
fileFlagsMask = res->readUint32LE();
fileFlags = res->readUint32LE();
fileOS = res->readUint32LE();
fileType = res->readUint32LE();
fileSubtype = res->readUint32LE();
fileDate[0] = res->readUint32LE();
fileDate[1] = res->readUint32LE();
hash.setVal("File:", Common::U32String::format("%d.%d.%d.%d", fileVersion[0], fileVersion[1], fileVersion[2], fileVersion[3]));
hash.setVal("Prod:", Common::U32String::format("%d.%d.%d.%d", productVersion[0], productVersion[1], productVersion[2], productVersion[3]));
return true;
}
} // End of namespace Common

View file

@ -158,14 +158,17 @@ public:
uint32 fileDate[2];
VersionHash hash;
};
static VersionInfo *parseVersionInfo(SeekableReadStream *stream);
bool readVSVersionInfo(SeekableReadStream *res);
};
VersionInfo *getVersionResource(const WinResourceID &id);
/** Get a string from a string resource. */
virtual String loadString(uint32 stringID) = 0;
protected:
virtual VersionInfo *parseVersionInfo(SeekableReadStream *stream) = 0;
};
/** @} */

View file

@ -234,4 +234,34 @@ String NEResources::loadString(uint32 stringID) {
return string;
}
WinResources::VersionInfo *NEResources::parseVersionInfo(SeekableReadStream *res) {
VersionInfo *info = new VersionInfo;
while (res->pos() < res->size() && !res->eos()) {
while (res->pos() % 4 && !res->eos()) // Pad to 4
res->readByte();
/* uint16 len = */ res->readUint16LE();
/* uint16 valLen = */ res->readUint16LE();
uint16 c;
Common::String key;
while ((c = res->readByte()) != 0 && !res->eos())
key += c;
while (res->pos() % 4 && !res->eos()) // Pad to 4
res->readByte();
if (res->eos())
break;
if (key == "VS_VERSION_INFO") {
if (!info->readVSVersionInfo(res))
return info;
}
}
return info;
}
} // End of namespace Common

View file

@ -70,6 +70,9 @@ public:
/** Get a string from a string resource. */
String loadString(uint32 stringID);
protected:
VersionInfo *parseVersionInfo(SeekableReadStream *stream);
private:
/** A resource. */
struct Resource {

View file

@ -259,4 +259,43 @@ String PEResources::loadString(uint32 stringID) {
return string;
}
WinResources::VersionInfo *PEResources::parseVersionInfo(SeekableReadStream *res) {
VersionInfo *info = new VersionInfo;
while (res->pos() < res->size() && !res->eos()) {
while (res->pos() % 4 && !res->eos()) // Pad to 4
res->readByte();
/* uint16 len = */ res->readUint16LE();
uint16 valLen = res->readUint16LE();
uint16 type = res->readUint16LE();
uint16 c;
Common::U32String key;
while ((c = res->readUint16LE()) != 0 && !res->eos())
key += c;
while (res->pos() % 4 && !res->eos()) // Pad to 4
res->readByte();
if (res->eos())
break;
if (type != 0) { // text
Common::U32String value;
for (int j = 0; j < valLen; j++)
value += res->readUint16LE();
info->hash.setVal(key.encode(), value);
} else {
if (key == "VS_VERSION_INFO") {
if (!info->readVSVersionInfo(res))
return info;
}
}
}
return info;
}
} // End of namespace Common

View file

@ -78,6 +78,9 @@ public:
/** Get a string from a string resource. */
String loadString(uint32 stringID);
protected:
VersionInfo *parseVersionInfo(SeekableReadStream *stream);
private:
struct Section {
uint32 virtualAddress;