diff --git a/engine/src/flutter/shell/common/shorebird/shorebird.cc b/engine/src/flutter/shell/common/shorebird/shorebird.cc index 2d9f73ed33320..8e9e644e84156 100644 --- a/engine/src/flutter/shell/common/shorebird/shorebird.cc +++ b/engine/src/flutter/shell/common/shorebird/shorebird.cc @@ -132,8 +132,11 @@ bool ConfigureShorebird(const ShorebirdConfigArgs& args, AppParameters app_parameters; // Combine version and version_code into a single string. // We could also pass these separately through to the updater if needed. - auto release_version = - args.release_version.version + "+" + args.release_version.build_number; + auto release_version = args.release_version.version; + if (!args.release_version.build_number.empty()) { + release_version += "+" + args.release_version.build_number; + } + app_parameters.release_version = release_version.c_str(); app_parameters.code_cache_dir = code_cache_dir.c_str(); app_parameters.app_storage_dir = app_storage_dir.c_str(); diff --git a/engine/src/flutter/shell/platform/windows/flutter_windows_engine.cc b/engine/src/flutter/shell/platform/windows/flutter_windows_engine.cc index ff82112a84898..0e683f837f8dc 100644 --- a/engine/src/flutter/shell/platform/windows/flutter_windows_engine.cc +++ b/engine/src/flutter/shell/platform/windows/flutter_windows_engine.cc @@ -269,36 +269,57 @@ int GetReleaseVersionAndBuildNumber(ReleaseVersion* release_version) { } // Allocate memory for version info - // std::vector version_data(version_info_size); std::unique_ptr version_data(new char[version_info_size]); if (!GetFileVersionInfoA(module_path, handle, version_info_size, version_data.get())) { return -1; } - // Get the version info structure - VS_FIXEDFILEINFO* file_info = nullptr; - UINT file_info_size = -1; - if (!VerQueryValueA(version_data.get(), "\\", - reinterpret_cast(&file_info), &file_info_size)) { + // Adopted from + // https://learn.microsoft.com/en-us/windows/win32/api/winver/nf-winver-verqueryvaluea + // Get the translation table + struct LANGANDCODEPAGE { + WORD wLanguage; + WORD wCodePage; + }* lpTranslate; + + UINT cbTranslate = 0; + if (!VerQueryValueA(version_data.get(), "\\VarFileInfo\\Translation", + (LPVOID*)&lpTranslate, &cbTranslate)) { + FML_LOG(ERROR) << "Error: Unable to get translation info."; return -1; } - if (file_info) { - // Extract version numbers - DWORD major = HIWORD(file_info->dwProductVersionMS); - DWORD minor = LOWORD(file_info->dwProductVersionMS); - DWORD build = HIWORD(file_info->dwProductVersionLS); - - char version[49]; - snprintf(version, sizeof(version), "%lu.%lu.%lu", major, minor, build); - release_version->version = std::string(version); - release_version->build_number = - std::to_string(LOWORD(file_info->dwProductVersionLS)); - return kSuccess; + // Construct the query string using the first translation found + char subBlock[64]; + sprintf_s(subBlock, "\\StringFileInfo\\%04x%04x\\ProductVersion", + lpTranslate[0].wLanguage, lpTranslate[0].wCodePage); + + LPSTR versionString = nullptr; + UINT size = 0; + if (!VerQueryValueA(version_data.get(), subBlock, (LPVOID*)&versionString, + &size)) { + return -1; + } + + if (!versionString) { + return -1; + } + + // The version string is in the format of "1.0.0+1", with the label ("+1") + // being optional. + auto version = std::string(versionString); + auto plusPos = version.find("+"); + if (plusPos != std::string::npos) { + auto semVer = version.substr(0, plusPos); + auto patch = version.substr(plusPos + 1, version.length()); + release_version->version = semVer; + release_version->build_number = patch; + } else { + release_version->version = version; } - return -1; + return kSuccess; } bool GetLocalAppDataPath(std::string& outPath) {