diff options
| author | sumuel <samuel@yakubos.org> | 2026-08-17 20:44:55 +0000 |
|---|---|---|
| committer | sumuel <samuel@yakubos.org> | 2026-08-17 20:44:55 +0000 |
| commit | 76424950e373d3b04ac3dd13019151bfba3e8423 (patch) | |
| tree | 4c3cfdbda039e592b9186be3e28f8d7cfd439e8a /src/common/windows/version.c | |
Add the files
Diffstat (limited to 'src/common/windows/version.c')
| -rw-r--r-- | src/common/windows/version.c | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/src/common/windows/version.c b/src/common/windows/version.c new file mode 100644 index 0000000..4d61c78 --- /dev/null +++ b/src/common/windows/version.c @@ -0,0 +1,77 @@ +#include "common/debug.h" +#include "common/mallocHelper.h" +#include "common/windows/version.h" +#include "common/windows/unicode.h" + +#include <windows.h> + +bool ffGetFileVersion(const wchar_t* filePath, const wchar_t* stringName, FFstrbuf* version) { + FF_DEBUG("ffGetFileVersion: enter filePath=%ls stringName=%ls", filePath, stringName); + + DWORD handle; + DWORD size = GetFileVersionInfoSizeW(filePath, &handle); + if (size == 0) { + FF_DEBUG("GetFileVersionInfoSizeW failed: %s", ffDebugWin32Error(GetLastError())); + return false; + } + + FF_DEBUG("GetFileVersionInfoSizeW ok: size=%lu handle=%lu", + (unsigned long) size, + (unsigned long) handle); + + FF_AUTO_FREE void* versionData = malloc(size); + if (!versionData) { + FF_DEBUG("malloc failed: size=%lu", (unsigned long) size); + return false; + } + + if (!GetFileVersionInfoW(filePath, handle, size, versionData)) { + FF_DEBUG("GetFileVersionInfoW failed: %s", ffDebugWin32Error(GetLastError())); + return false; + } + + FF_DEBUG("GetFileVersionInfoW ok"); + + if (!stringName) { + VS_FIXEDFILEINFO* verInfo; + UINT len; + if (VerQueryValueW(versionData, L"\\", (void**) &verInfo, &len) && + len && + verInfo->dwSignature == 0xFEEF04BD) { + ffStrbufSetF(version, "%u.%u.%u.%u", (unsigned) ((verInfo->dwProductVersionMS >> 16) & 0xffff), (unsigned) ((verInfo->dwProductVersionMS >> 0) & 0xffff), (unsigned) ((verInfo->dwProductVersionLS >> 16) & 0xffff), (unsigned) ((verInfo->dwProductVersionLS >> 0) & 0xffff)); + FF_DEBUG("fixed version resolved: %s", version->chars); + return true; + } + + FF_DEBUG("fixed version query failed or invalid signature"); + return false; + } + + struct { + WORD language; + WORD codePage; + }* translations; + UINT translationsLen; + + if (VerQueryValueW(versionData, L"\\VarFileInfo\\Translation", (void**) &translations, &translationsLen) && + translationsLen >= sizeof(*translations)) { + wchar_t subBlock[128]; + snwprintf(subBlock, ARRAY_SIZE(subBlock), L"\\StringFileInfo\\%04x%04x\\%ls", translations[0].language, translations[0].codePage, stringName); + FF_DEBUG("query version string with translation: %ls", subBlock); + + wchar_t* value; + UINT valueLen; // Number of characters, including null terminator + if (VerQueryValueW(versionData, subBlock, (void**) &value, &valueLen) && valueLen > 0) { + ffStrbufSetNWS(version, valueLen - 1, value); + FF_DEBUG("version string resolved (translation fallback): %s", version->chars); + return true; + } + + FF_DEBUG("translation fallback query failed"); + } else { + FF_DEBUG("no translation table found in version resource"); + } + + FF_DEBUG("ffGetFileVersion failed"); + return false; +} |