blob: 7abcd2a792a1726f716bdc1b9fcca733156ed354 [file] [log] [blame]
pkasting@chromium.orgf481221192011-04-07 22:15:341// Copyright (c) 2011 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commitd7cae122008-07-26 21:49:384
tony@chromium.orgbcff05a2010-04-14 01:46:435#include "base/file_version_info_win.h"
initial.commitd7cae122008-07-26 21:49:386
phajdan.jr@chromium.orgf5393332009-06-03 15:01:297#include <windows.h>
avi9b6f42932015-12-26 22:15:148#include <stddef.h>
phajdan.jr@chromium.orgf5393332009-06-03 15:01:299
brettw@chromium.org57999812013-02-24 05:40:5210#include "base/files/file_path.h"
initial.commitd7cae122008-07-26 21:49:3811#include "base/logging.h"
David Benjamin04cc2b42019-01-29 05:30:3312#include "base/memory/ptr_util.h"
Avi Drissmane3b70bf2019-01-04 19:50:2213#include "base/stl_util.h"
Etienne Pierre-Doray3879b052018-09-17 14:17:2214#include "base/threading/scoped_blocking_call.h"
fdoray5b7de9e92016-06-29 23:13:1115#include "base/win/resource_util.h"
initial.commitd7cae122008-07-26 21:49:3816
brettw@chromium.org631a5472013-02-18 06:14:5917using base::FilePath;
18
fdoray5b7de9e92016-06-29 23:13:1119namespace {
initial.commitd7cae122008-07-26 21:49:3820
fdoray5b7de9e92016-06-29 23:13:1121struct LanguageAndCodePage {
initial.commitd7cae122008-07-26 21:49:3822 WORD language;
23 WORD code_page;
fdoray5b7de9e92016-06-29 23:13:1124};
25
26// Returns the \\VarFileInfo\\Translation value extracted from the
27// VS_VERSION_INFO resource in |data|.
28LanguageAndCodePage* GetTranslate(const void* data) {
29 LanguageAndCodePage* translate = nullptr;
30 UINT length;
31 if (::VerQueryValue(data, L"\\VarFileInfo\\Translation",
32 reinterpret_cast<void**>(&translate), &length)) {
33 return translate;
34 }
35 return nullptr;
36}
37
38VS_FIXEDFILEINFO* GetVsFixedFileInfo(const void* data) {
39 VS_FIXEDFILEINFO* fixed_file_info = nullptr;
40 UINT length;
41 if (::VerQueryValue(data, L"\\", reinterpret_cast<void**>(&fixed_file_info),
42 &length)) {
43 return fixed_file_info;
44 }
45 return nullptr;
46}
47
48} // namespace
49
50FileVersionInfoWin::~FileVersionInfoWin() = default;
initial.commitd7cae122008-07-26 21:49:3851
52// static
David Benjamin04cc2b42019-01-29 05:30:3353std::unique_ptr<FileVersionInfo>
54FileVersionInfo::CreateFileVersionInfoForModule(HMODULE module) {
fdoray5b7de9e92016-06-29 23:13:1155 void* data;
56 size_t version_info_length;
57 const bool has_version_resource = base::win::GetResourceFromModule(
58 module, VS_VERSION_INFO, RT_VERSION, &data, &version_info_length);
59 if (!has_version_resource)
60 return nullptr;
initial.commitd7cae122008-07-26 21:49:3861
fdoray5b7de9e92016-06-29 23:13:1162 const LanguageAndCodePage* translate = GetTranslate(data);
63 if (!translate)
64 return nullptr;
65
David Benjamin04cc2b42019-01-29 05:30:3366 return base::WrapUnique(
67 new FileVersionInfoWin(data, translate->language, translate->code_page));
initial.commitd7cae122008-07-26 21:49:3868}
69
70// static
David Benjamin04cc2b42019-01-29 05:30:3371std::unique_ptr<FileVersionInfo> FileVersionInfo::CreateFileVersionInfo(
avi@google.com0956223822008-12-23 16:57:3672 const FilePath& file_path) {
David Benjamin04cc2b42019-01-29 05:30:3373 return FileVersionInfoWin::CreateFileVersionInfoWin(file_path);
74}
75
76// static
77std::unique_ptr<FileVersionInfoWin>
78FileVersionInfoWin::CreateFileVersionInfoWin(const FilePath& file_path) {
Etienne Pierre-Doray3879b052018-09-17 14:17:2279 base::ScopedBlockingCall scoped_blocking_call(base::BlockingType::MAY_BLOCK);
jam@chromium.org45446a52010-11-04 17:41:0080
initial.commitd7cae122008-07-26 21:49:3881 DWORD dummy;
avi@google.com0956223822008-12-23 16:57:3682 const wchar_t* path = file_path.value().c_str();
fdoray5b7de9e92016-06-29 23:13:1183 const DWORD length = ::GetFileVersionInfoSize(path, &dummy);
initial.commitd7cae122008-07-26 21:49:3884 if (length == 0)
fdoray5b7de9e92016-06-29 23:13:1185 return nullptr;
initial.commitd7cae122008-07-26 21:49:3886
fdoray5b7de9e92016-06-29 23:13:1187 std::vector<uint8_t> data(length, 0);
initial.commitd7cae122008-07-26 21:49:3888
fdoray5b7de9e92016-06-29 23:13:1189 if (!::GetFileVersionInfo(path, dummy, length, data.data()))
90 return nullptr;
initial.commitd7cae122008-07-26 21:49:3891
fdoray5b7de9e92016-06-29 23:13:1192 const LanguageAndCodePage* translate = GetTranslate(data.data());
93 if (!translate)
94 return nullptr;
initial.commitd7cae122008-07-26 21:49:3895
David Benjamin04cc2b42019-01-29 05:30:3396 return base::WrapUnique(new FileVersionInfoWin(
97 std::move(data), translate->language, translate->code_page));
initial.commitd7cae122008-07-26 21:49:3898}
99
dbeam@chromium.orgf527d9c2013-12-30 21:43:00100base::string16 FileVersionInfoWin::company_name() {
initial.commitd7cae122008-07-26 21:49:38101 return GetStringValue(L"CompanyName");
102}
103
dbeam@chromium.orgf527d9c2013-12-30 21:43:00104base::string16 FileVersionInfoWin::company_short_name() {
initial.commitd7cae122008-07-26 21:49:38105 return GetStringValue(L"CompanyShortName");
106}
107
dbeam@chromium.orgf527d9c2013-12-30 21:43:00108base::string16 FileVersionInfoWin::internal_name() {
initial.commitd7cae122008-07-26 21:49:38109 return GetStringValue(L"InternalName");
110}
111
dbeam@chromium.orgf527d9c2013-12-30 21:43:00112base::string16 FileVersionInfoWin::product_name() {
initial.commitd7cae122008-07-26 21:49:38113 return GetStringValue(L"ProductName");
114}
115
dbeam@chromium.orgf527d9c2013-12-30 21:43:00116base::string16 FileVersionInfoWin::product_short_name() {
initial.commitd7cae122008-07-26 21:49:38117 return GetStringValue(L"ProductShortName");
118}
119
dbeam@chromium.orgf527d9c2013-12-30 21:43:00120base::string16 FileVersionInfoWin::comments() {
initial.commitd7cae122008-07-26 21:49:38121 return GetStringValue(L"Comments");
122}
123
dbeam@chromium.orgf527d9c2013-12-30 21:43:00124base::string16 FileVersionInfoWin::legal_copyright() {
initial.commitd7cae122008-07-26 21:49:38125 return GetStringValue(L"LegalCopyright");
126}
127
dbeam@chromium.orgf527d9c2013-12-30 21:43:00128base::string16 FileVersionInfoWin::product_version() {
initial.commitd7cae122008-07-26 21:49:38129 return GetStringValue(L"ProductVersion");
130}
131
dbeam@chromium.orgf527d9c2013-12-30 21:43:00132base::string16 FileVersionInfoWin::file_description() {
initial.commitd7cae122008-07-26 21:49:38133 return GetStringValue(L"FileDescription");
134}
135
dbeam@chromium.orgf527d9c2013-12-30 21:43:00136base::string16 FileVersionInfoWin::legal_trademarks() {
initial.commitd7cae122008-07-26 21:49:38137 return GetStringValue(L"LegalTrademarks");
138}
139
dbeam@chromium.orgf527d9c2013-12-30 21:43:00140base::string16 FileVersionInfoWin::private_build() {
initial.commitd7cae122008-07-26 21:49:38141 return GetStringValue(L"PrivateBuild");
142}
143
dbeam@chromium.orgf527d9c2013-12-30 21:43:00144base::string16 FileVersionInfoWin::file_version() {
initial.commitd7cae122008-07-26 21:49:38145 return GetStringValue(L"FileVersion");
146}
147
dbeam@chromium.orgf527d9c2013-12-30 21:43:00148base::string16 FileVersionInfoWin::original_filename() {
initial.commitd7cae122008-07-26 21:49:38149 return GetStringValue(L"OriginalFilename");
150}
151
dbeam@chromium.orgf527d9c2013-12-30 21:43:00152base::string16 FileVersionInfoWin::special_build() {
initial.commitd7cae122008-07-26 21:49:38153 return GetStringValue(L"SpecialBuild");
154}
155
dbeam@chromium.orgf527d9c2013-12-30 21:43:00156base::string16 FileVersionInfoWin::last_change() {
initial.commitd7cae122008-07-26 21:49:38157 return GetStringValue(L"LastChange");
158}
159
tony@chromium.orgbcff05a2010-04-14 01:46:43160bool FileVersionInfoWin::is_official_build() {
initial.commitd7cae122008-07-26 21:49:38161 return (GetStringValue(L"Official Build").compare(L"1") == 0);
162}
163
tony@chromium.orgbcff05a2010-04-14 01:46:43164bool FileVersionInfoWin::GetValue(const wchar_t* name,
165 std::wstring* value_str) {
initial.commitd7cae122008-07-26 21:49:38166 WORD lang_codepage[8];
thakis9230c1d2015-12-10 00:36:25167 size_t i = 0;
initial.commitd7cae122008-07-26 21:49:38168 // Use the language and codepage from the DLL.
169 lang_codepage[i++] = language_;
170 lang_codepage[i++] = code_page_;
171 // Use the default language and codepage from the DLL.
172 lang_codepage[i++] = ::GetUserDefaultLangID();
173 lang_codepage[i++] = code_page_;
174 // Use the language from the DLL and Latin codepage (most common).
175 lang_codepage[i++] = language_;
176 lang_codepage[i++] = 1252;
177 // Use the default language and Latin codepage (most common).
178 lang_codepage[i++] = ::GetUserDefaultLangID();
179 lang_codepage[i++] = 1252;
180
181 i = 0;
Avi Drissmane3b70bf2019-01-04 19:50:22182 while (i < base::size(lang_codepage)) {
initial.commitd7cae122008-07-26 21:49:38183 wchar_t sub_block[MAX_PATH];
184 WORD language = lang_codepage[i++];
185 WORD code_page = lang_codepage[i++];
186 _snwprintf_s(sub_block, MAX_PATH, MAX_PATH,
mmentovai@google.com51154742008-08-14 00:41:45187 L"\\StringFileInfo\\%04x%04x\\%ls", language, code_page, name);
initial.commitd7cae122008-07-26 21:49:38188 LPVOID value = NULL;
avi9b6f42932015-12-26 22:15:14189 uint32_t size;
fdoray5b7de9e92016-06-29 23:13:11190 BOOL r = ::VerQueryValue(data_, sub_block, &value, &size);
initial.commitd7cae122008-07-26 21:49:38191 if (r && value) {
192 value_str->assign(static_cast<wchar_t*>(value));
193 return true;
194 }
195 }
196 return false;
197}
198
tony@chromium.orgbcff05a2010-04-14 01:46:43199std::wstring FileVersionInfoWin::GetStringValue(const wchar_t* name) {
initial.commitd7cae122008-07-26 21:49:38200 std::wstring str;
201 if (GetValue(name, &str))
202 return str;
203 else
204 return L"";
205}
fdoray5b7de9e92016-06-29 23:13:11206
207FileVersionInfoWin::FileVersionInfoWin(std::vector<uint8_t>&& data,
208 WORD language,
209 WORD code_page)
210 : owned_data_(std::move(data)),
211 data_(owned_data_.data()),
212 language_(language),
213 code_page_(code_page),
214 fixed_file_info_(GetVsFixedFileInfo(data_)) {
215 DCHECK(!owned_data_.empty());
216}
217
218FileVersionInfoWin::FileVersionInfoWin(void* data,
219 WORD language,
220 WORD code_page)
221 : data_(data),
222 language_(language),
223 code_page_(code_page),
224 fixed_file_info_(GetVsFixedFileInfo(data)) {
225 DCHECK(data_);
226}