1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
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\\%02lX%02lX%02lX%02lX\\%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
|