summaryrefslogtreecommitdiffstats
path: root/toolkit/xre/ModuleVersionInfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/xre/ModuleVersionInfo.cpp')
-rw-r--r--toolkit/xre/ModuleVersionInfo.cpp111
1 files changed, 111 insertions, 0 deletions
diff --git a/toolkit/xre/ModuleVersionInfo.cpp b/toolkit/xre/ModuleVersionInfo.cpp
new file mode 100644
index 0000000000..b6f7b0925d
--- /dev/null
+++ b/toolkit/xre/ModuleVersionInfo.cpp
@@ -0,0 +1,111 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+#include "ModuleVersionInfo.h"
+
+#include "mozilla/UniquePtr.h"
+
+namespace mozilla {
+
+/**
+ * Gets a string value from a version info block with the specified translation
+ * and field name.
+ *
+ * @param aBlock [in] The binary version resource block
+ * @param aTranslation [in] The translation ID as obtained in the version
+ * translation list.
+ * @param aFieldName [in] Null-terminated name of the desired field
+ * @param aResult [out] Receives the string value, if successful.
+ * @return true if successful. aResult is unchanged upon failure.
+ */
+static bool QueryStringValue(const void* aBlock, DWORD aTranslation,
+ const wchar_t* aFieldName, nsAString& aResult) {
+ nsAutoString path;
+ path.AppendPrintf("\\StringFileInfo\\%02X%02X%02X%02X\\%S",
+ (aTranslation & 0x0000ff00) >> 8,
+ (aTranslation & 0x000000ff),
+ (aTranslation & 0xff000000) >> 24,
+ (aTranslation & 0x00ff0000) >> 16, aFieldName);
+
+ wchar_t* lpBuffer = nullptr;
+ UINT len = 0;
+ if (!::VerQueryValueW(aBlock, path.get(), (PVOID*)&lpBuffer, &len)) {
+ return false;
+ }
+ aResult.Assign(lpBuffer, (size_t)len - 1);
+ return true;
+}
+
+/**
+ * Searches through translations in the version resource for the requested
+ * field. English(US) is preferred, otherwise we take the first translation
+ * that succeeds.
+ *
+ * @param aBlock [in] The binary version resource block
+ * @param aTranslations [in] The list of translation IDs available
+ * @param aNumTrans [in] Number of items in aTranslations
+ * @param aFieldName [in] Null-terminated name of the desired field
+ * @param aResult [in] Receives the string value, if successful.
+ * @return true if successful. aResult is unchanged upon failure.
+ */
+static bool QueryStringValue(const void* aBlock, const DWORD* aTranslations,
+ size_t aNumTrans, const wchar_t* aFieldName,
+ nsAString& aResult) {
+ static const DWORD kPreferredTranslation =
+ 0x04b00409; // English (US), Unicode
+ if (QueryStringValue(aBlock, kPreferredTranslation, aFieldName, aResult)) {
+ return true;
+ }
+ for (size_t i = 0; i < aNumTrans; ++i) {
+ if (QueryStringValue(aBlock, aTranslations[i], aFieldName, aResult)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool ModuleVersionInfo::GetFromImage(const nsAString& aPath) {
+ nsString path(aPath);
+ DWORD infoSize = GetFileVersionInfoSizeW(path.get(), nullptr);
+ if (!infoSize) {
+ return false;
+ }
+
+ auto verInfo = MakeUnique<BYTE[]>(infoSize);
+ if (!::GetFileVersionInfoW(path.get(), 0, infoSize, verInfo.get())) {
+ return false;
+ }
+
+ VS_FIXEDFILEINFO* vInfo = nullptr;
+ UINT vInfoLen = 0;
+ if (::VerQueryValueW(verInfo.get(), L"\\", (LPVOID*)&vInfo, &vInfoLen)) {
+ mFileVersion =
+ VersionNumber(vInfo->dwFileVersionMS, vInfo->dwFileVersionLS);
+ mProductVersion =
+ VersionNumber(vInfo->dwProductVersionMS, vInfo->dwProductVersionLS);
+ }
+
+ // Note that regardless the character set indicated, strings are always
+ // returned as Unicode by the Windows APIs.
+ DWORD* pTrans = nullptr;
+ UINT cbTrans = 0;
+ if (::VerQueryValueW(verInfo.get(), L"\\VarFileInfo\\Translation",
+ (PVOID*)&pTrans, &cbTrans)) {
+ size_t numTrans = cbTrans / sizeof(DWORD);
+ QueryStringValue(verInfo.get(), pTrans, numTrans, L"CompanyName",
+ mCompanyName);
+ QueryStringValue(verInfo.get(), pTrans, numTrans, L"ProductName",
+ mProductName);
+ QueryStringValue(verInfo.get(), pTrans, numTrans, L"LegalCopyright",
+ mLegalCopyright);
+ QueryStringValue(verInfo.get(), pTrans, numTrans, L"FileDescription",
+ mFileDescription);
+ }
+
+ return true;
+}
+
+} // namespace mozilla