1*6777b538SAndroid Build Coastguard Worker // Copyright 2015 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "base/system/sys_info.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <windows.h>
8*6777b538SAndroid Build Coastguard Worker
9*6777b538SAndroid Build Coastguard Worker #include <stddef.h>
10*6777b538SAndroid Build Coastguard Worker #include <stdint.h>
11*6777b538SAndroid Build Coastguard Worker
12*6777b538SAndroid Build Coastguard Worker #include <algorithm>
13*6777b538SAndroid Build Coastguard Worker #include <bit>
14*6777b538SAndroid Build Coastguard Worker #include <limits>
15*6777b538SAndroid Build Coastguard Worker #include <type_traits>
16*6777b538SAndroid Build Coastguard Worker #include <vector>
17*6777b538SAndroid Build Coastguard Worker
18*6777b538SAndroid Build Coastguard Worker #include "base/check.h"
19*6777b538SAndroid Build Coastguard Worker #include "base/files/file_path.h"
20*6777b538SAndroid Build Coastguard Worker #include "base/notreached.h"
21*6777b538SAndroid Build Coastguard Worker #include "base/numerics/safe_conversions.h"
22*6777b538SAndroid Build Coastguard Worker #include "base/process/process_metrics.h"
23*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_util.h"
24*6777b538SAndroid Build Coastguard Worker #include "base/strings/stringprintf.h"
25*6777b538SAndroid Build Coastguard Worker #include "base/strings/sys_string_conversions.h"
26*6777b538SAndroid Build Coastguard Worker #include "base/strings/utf_string_conversions.h"
27*6777b538SAndroid Build Coastguard Worker #include "base/threading/scoped_blocking_call.h"
28*6777b538SAndroid Build Coastguard Worker #include "base/win/registry.h"
29*6777b538SAndroid Build Coastguard Worker #include "base/win/windows_version.h"
30*6777b538SAndroid Build Coastguard Worker #include "third_party/abseil-cpp/absl/container/inlined_vector.h"
31*6777b538SAndroid Build Coastguard Worker
32*6777b538SAndroid Build Coastguard Worker namespace {
33*6777b538SAndroid Build Coastguard Worker
34*6777b538SAndroid Build Coastguard Worker // Returns the power efficiency levels of physical cores or empty vector on
35*6777b538SAndroid Build Coastguard Worker // failure. The BYTE value of the element is the relative efficiency rank among
36*6777b538SAndroid Build Coastguard Worker // all physical cores, where 0 is the most efficient, 1 is the second most
37*6777b538SAndroid Build Coastguard Worker // efficient, and so on.
GetCoreEfficiencyClasses()38*6777b538SAndroid Build Coastguard Worker std::vector<BYTE> GetCoreEfficiencyClasses() {
39*6777b538SAndroid Build Coastguard Worker const DWORD kReservedSize =
40*6777b538SAndroid Build Coastguard Worker sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX) * 64;
41*6777b538SAndroid Build Coastguard Worker absl::InlinedVector<BYTE, kReservedSize> buffer;
42*6777b538SAndroid Build Coastguard Worker buffer.resize(kReservedSize);
43*6777b538SAndroid Build Coastguard Worker DWORD byte_length = kReservedSize;
44*6777b538SAndroid Build Coastguard Worker if (!GetLogicalProcessorInformationEx(
45*6777b538SAndroid Build Coastguard Worker RelationProcessorCore,
46*6777b538SAndroid Build Coastguard Worker reinterpret_cast<SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*>(
47*6777b538SAndroid Build Coastguard Worker buffer.data()),
48*6777b538SAndroid Build Coastguard Worker &byte_length)) {
49*6777b538SAndroid Build Coastguard Worker DPCHECK(GetLastError() == ERROR_INSUFFICIENT_BUFFER);
50*6777b538SAndroid Build Coastguard Worker buffer.resize(byte_length);
51*6777b538SAndroid Build Coastguard Worker if (!GetLogicalProcessorInformationEx(
52*6777b538SAndroid Build Coastguard Worker RelationProcessorCore,
53*6777b538SAndroid Build Coastguard Worker reinterpret_cast<SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*>(
54*6777b538SAndroid Build Coastguard Worker buffer.data()),
55*6777b538SAndroid Build Coastguard Worker &byte_length)) {
56*6777b538SAndroid Build Coastguard Worker return {};
57*6777b538SAndroid Build Coastguard Worker }
58*6777b538SAndroid Build Coastguard Worker }
59*6777b538SAndroid Build Coastguard Worker
60*6777b538SAndroid Build Coastguard Worker std::vector<BYTE> efficiency_classes;
61*6777b538SAndroid Build Coastguard Worker BYTE* byte_ptr = buffer.data();
62*6777b538SAndroid Build Coastguard Worker while (byte_ptr < buffer.data() + byte_length) {
63*6777b538SAndroid Build Coastguard Worker const auto* structure_ptr =
64*6777b538SAndroid Build Coastguard Worker reinterpret_cast<SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*>(byte_ptr);
65*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(structure_ptr->Relationship, RelationProcessorCore);
66*6777b538SAndroid Build Coastguard Worker DCHECK_LE(&structure_ptr->Processor.EfficiencyClass +
67*6777b538SAndroid Build Coastguard Worker sizeof(structure_ptr->Processor.EfficiencyClass),
68*6777b538SAndroid Build Coastguard Worker buffer.data() + byte_length);
69*6777b538SAndroid Build Coastguard Worker efficiency_classes.push_back(structure_ptr->Processor.EfficiencyClass);
70*6777b538SAndroid Build Coastguard Worker DCHECK_GE(
71*6777b538SAndroid Build Coastguard Worker structure_ptr->Size,
72*6777b538SAndroid Build Coastguard Worker offsetof(std::remove_pointer_t<decltype(structure_ptr)>, Processor) +
73*6777b538SAndroid Build Coastguard Worker sizeof(structure_ptr->Processor));
74*6777b538SAndroid Build Coastguard Worker byte_ptr = byte_ptr + structure_ptr->Size;
75*6777b538SAndroid Build Coastguard Worker }
76*6777b538SAndroid Build Coastguard Worker
77*6777b538SAndroid Build Coastguard Worker return efficiency_classes;
78*6777b538SAndroid Build Coastguard Worker }
79*6777b538SAndroid Build Coastguard Worker
80*6777b538SAndroid Build Coastguard Worker // Returns the physical cores to logical processor mapping masks by using the
81*6777b538SAndroid Build Coastguard Worker // Windows API GetLogicalProcessorInformation(), or an empty vector on failure.
82*6777b538SAndroid Build Coastguard Worker // When succeeded, the vector would be of same size to the number of physical
83*6777b538SAndroid Build Coastguard Worker // cores, while each element is the bitmask of the logical processors that the
84*6777b538SAndroid Build Coastguard Worker // physical core has.
GetCoreProcessorMasks()85*6777b538SAndroid Build Coastguard Worker std::vector<uint64_t> GetCoreProcessorMasks() {
86*6777b538SAndroid Build Coastguard Worker const DWORD kReservedSize = 64;
87*6777b538SAndroid Build Coastguard Worker absl::InlinedVector<SYSTEM_LOGICAL_PROCESSOR_INFORMATION, kReservedSize>
88*6777b538SAndroid Build Coastguard Worker buffer;
89*6777b538SAndroid Build Coastguard Worker buffer.resize(kReservedSize);
90*6777b538SAndroid Build Coastguard Worker DWORD byte_length = sizeof(buffer[0]) * kReservedSize;
91*6777b538SAndroid Build Coastguard Worker const BOOL result =
92*6777b538SAndroid Build Coastguard Worker GetLogicalProcessorInformation(buffer.data(), &byte_length);
93*6777b538SAndroid Build Coastguard Worker DWORD element_count = byte_length / sizeof(buffer[0]);
94*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(byte_length % sizeof(buffer[0]), 0u);
95*6777b538SAndroid Build Coastguard Worker if (!result) {
96*6777b538SAndroid Build Coastguard Worker DPCHECK(GetLastError() == ERROR_INSUFFICIENT_BUFFER);
97*6777b538SAndroid Build Coastguard Worker buffer.resize(element_count);
98*6777b538SAndroid Build Coastguard Worker if (!GetLogicalProcessorInformation(buffer.data(), &byte_length)) {
99*6777b538SAndroid Build Coastguard Worker return {};
100*6777b538SAndroid Build Coastguard Worker }
101*6777b538SAndroid Build Coastguard Worker }
102*6777b538SAndroid Build Coastguard Worker
103*6777b538SAndroid Build Coastguard Worker std::vector<uint64_t> processor_masks;
104*6777b538SAndroid Build Coastguard Worker for (DWORD i = 0; i < element_count; i++) {
105*6777b538SAndroid Build Coastguard Worker if (buffer[i].Relationship == RelationProcessorCore) {
106*6777b538SAndroid Build Coastguard Worker processor_masks.push_back(buffer[i].ProcessorMask);
107*6777b538SAndroid Build Coastguard Worker }
108*6777b538SAndroid Build Coastguard Worker }
109*6777b538SAndroid Build Coastguard Worker
110*6777b538SAndroid Build Coastguard Worker return processor_masks;
111*6777b538SAndroid Build Coastguard Worker }
112*6777b538SAndroid Build Coastguard Worker
AmountOfMemory(DWORDLONG MEMORYSTATUSEX::* memory_field)113*6777b538SAndroid Build Coastguard Worker uint64_t AmountOfMemory(DWORDLONG MEMORYSTATUSEX::*memory_field) {
114*6777b538SAndroid Build Coastguard Worker MEMORYSTATUSEX memory_info;
115*6777b538SAndroid Build Coastguard Worker memory_info.dwLength = sizeof(memory_info);
116*6777b538SAndroid Build Coastguard Worker if (!GlobalMemoryStatusEx(&memory_info)) {
117*6777b538SAndroid Build Coastguard Worker NOTREACHED();
118*6777b538SAndroid Build Coastguard Worker return 0;
119*6777b538SAndroid Build Coastguard Worker }
120*6777b538SAndroid Build Coastguard Worker
121*6777b538SAndroid Build Coastguard Worker return memory_info.*memory_field;
122*6777b538SAndroid Build Coastguard Worker }
123*6777b538SAndroid Build Coastguard Worker
GetDiskSpaceInfo(const base::FilePath & path,int64_t * available_bytes,int64_t * total_bytes)124*6777b538SAndroid Build Coastguard Worker bool GetDiskSpaceInfo(const base::FilePath& path,
125*6777b538SAndroid Build Coastguard Worker int64_t* available_bytes,
126*6777b538SAndroid Build Coastguard Worker int64_t* total_bytes) {
127*6777b538SAndroid Build Coastguard Worker ULARGE_INTEGER available;
128*6777b538SAndroid Build Coastguard Worker ULARGE_INTEGER total;
129*6777b538SAndroid Build Coastguard Worker ULARGE_INTEGER free;
130*6777b538SAndroid Build Coastguard Worker if (!GetDiskFreeSpaceExW(path.value().c_str(), &available, &total, &free))
131*6777b538SAndroid Build Coastguard Worker return false;
132*6777b538SAndroid Build Coastguard Worker
133*6777b538SAndroid Build Coastguard Worker if (available_bytes) {
134*6777b538SAndroid Build Coastguard Worker *available_bytes = static_cast<int64_t>(available.QuadPart);
135*6777b538SAndroid Build Coastguard Worker if (*available_bytes < 0)
136*6777b538SAndroid Build Coastguard Worker *available_bytes = std::numeric_limits<int64_t>::max();
137*6777b538SAndroid Build Coastguard Worker }
138*6777b538SAndroid Build Coastguard Worker if (total_bytes) {
139*6777b538SAndroid Build Coastguard Worker *total_bytes = static_cast<int64_t>(total.QuadPart);
140*6777b538SAndroid Build Coastguard Worker if (*total_bytes < 0)
141*6777b538SAndroid Build Coastguard Worker *total_bytes = std::numeric_limits<int64_t>::max();
142*6777b538SAndroid Build Coastguard Worker }
143*6777b538SAndroid Build Coastguard Worker return true;
144*6777b538SAndroid Build Coastguard Worker }
145*6777b538SAndroid Build Coastguard Worker
146*6777b538SAndroid Build Coastguard Worker } // namespace
147*6777b538SAndroid Build Coastguard Worker
148*6777b538SAndroid Build Coastguard Worker namespace base {
149*6777b538SAndroid Build Coastguard Worker
150*6777b538SAndroid Build Coastguard Worker // static
NumberOfProcessors()151*6777b538SAndroid Build Coastguard Worker int SysInfo::NumberOfProcessors() {
152*6777b538SAndroid Build Coastguard Worker return win::OSInfo::GetInstance()->processors();
153*6777b538SAndroid Build Coastguard Worker }
154*6777b538SAndroid Build Coastguard Worker
155*6777b538SAndroid Build Coastguard Worker // static
NumberOfEfficientProcessorsImpl()156*6777b538SAndroid Build Coastguard Worker int SysInfo::NumberOfEfficientProcessorsImpl() {
157*6777b538SAndroid Build Coastguard Worker std::vector<BYTE> efficiency_classes = GetCoreEfficiencyClasses();
158*6777b538SAndroid Build Coastguard Worker if (efficiency_classes.empty())
159*6777b538SAndroid Build Coastguard Worker return 0;
160*6777b538SAndroid Build Coastguard Worker
161*6777b538SAndroid Build Coastguard Worker auto [min_efficiency_class_it, max_efficiency_class_it] =
162*6777b538SAndroid Build Coastguard Worker std::minmax_element(efficiency_classes.begin(), efficiency_classes.end());
163*6777b538SAndroid Build Coastguard Worker if (*min_efficiency_class_it == *max_efficiency_class_it)
164*6777b538SAndroid Build Coastguard Worker return 0;
165*6777b538SAndroid Build Coastguard Worker
166*6777b538SAndroid Build Coastguard Worker std::vector<uint64_t> processor_masks = GetCoreProcessorMasks();
167*6777b538SAndroid Build Coastguard Worker if (processor_masks.empty())
168*6777b538SAndroid Build Coastguard Worker return 0;
169*6777b538SAndroid Build Coastguard Worker
170*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(efficiency_classes.size(), processor_masks.size());
171*6777b538SAndroid Build Coastguard Worker int num_of_efficient_processors = 0;
172*6777b538SAndroid Build Coastguard Worker for (size_t i = 0; i < efficiency_classes.size(); i++) {
173*6777b538SAndroid Build Coastguard Worker if (efficiency_classes[i] == *min_efficiency_class_it) {
174*6777b538SAndroid Build Coastguard Worker num_of_efficient_processors += std::popcount(processor_masks[i]);
175*6777b538SAndroid Build Coastguard Worker }
176*6777b538SAndroid Build Coastguard Worker }
177*6777b538SAndroid Build Coastguard Worker
178*6777b538SAndroid Build Coastguard Worker return num_of_efficient_processors;
179*6777b538SAndroid Build Coastguard Worker }
180*6777b538SAndroid Build Coastguard Worker
181*6777b538SAndroid Build Coastguard Worker // static
AmountOfPhysicalMemoryImpl()182*6777b538SAndroid Build Coastguard Worker uint64_t SysInfo::AmountOfPhysicalMemoryImpl() {
183*6777b538SAndroid Build Coastguard Worker return AmountOfMemory(&MEMORYSTATUSEX::ullTotalPhys);
184*6777b538SAndroid Build Coastguard Worker }
185*6777b538SAndroid Build Coastguard Worker
186*6777b538SAndroid Build Coastguard Worker // static
AmountOfAvailablePhysicalMemoryImpl()187*6777b538SAndroid Build Coastguard Worker uint64_t SysInfo::AmountOfAvailablePhysicalMemoryImpl() {
188*6777b538SAndroid Build Coastguard Worker SystemMemoryInfoKB info;
189*6777b538SAndroid Build Coastguard Worker if (!GetSystemMemoryInfo(&info))
190*6777b538SAndroid Build Coastguard Worker return 0;
191*6777b538SAndroid Build Coastguard Worker return checked_cast<uint64_t>(info.avail_phys) * 1024;
192*6777b538SAndroid Build Coastguard Worker }
193*6777b538SAndroid Build Coastguard Worker
194*6777b538SAndroid Build Coastguard Worker // static
AmountOfVirtualMemory()195*6777b538SAndroid Build Coastguard Worker uint64_t SysInfo::AmountOfVirtualMemory() {
196*6777b538SAndroid Build Coastguard Worker return AmountOfMemory(&MEMORYSTATUSEX::ullTotalVirtual);
197*6777b538SAndroid Build Coastguard Worker }
198*6777b538SAndroid Build Coastguard Worker
199*6777b538SAndroid Build Coastguard Worker // static
AmountOfFreeDiskSpace(const FilePath & path)200*6777b538SAndroid Build Coastguard Worker int64_t SysInfo::AmountOfFreeDiskSpace(const FilePath& path) {
201*6777b538SAndroid Build Coastguard Worker base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
202*6777b538SAndroid Build Coastguard Worker base::BlockingType::MAY_BLOCK);
203*6777b538SAndroid Build Coastguard Worker
204*6777b538SAndroid Build Coastguard Worker int64_t available;
205*6777b538SAndroid Build Coastguard Worker if (!GetDiskSpaceInfo(path, &available, nullptr))
206*6777b538SAndroid Build Coastguard Worker return -1;
207*6777b538SAndroid Build Coastguard Worker return available;
208*6777b538SAndroid Build Coastguard Worker }
209*6777b538SAndroid Build Coastguard Worker
210*6777b538SAndroid Build Coastguard Worker // static
AmountOfTotalDiskSpace(const FilePath & path)211*6777b538SAndroid Build Coastguard Worker int64_t SysInfo::AmountOfTotalDiskSpace(const FilePath& path) {
212*6777b538SAndroid Build Coastguard Worker base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
213*6777b538SAndroid Build Coastguard Worker base::BlockingType::MAY_BLOCK);
214*6777b538SAndroid Build Coastguard Worker
215*6777b538SAndroid Build Coastguard Worker int64_t total;
216*6777b538SAndroid Build Coastguard Worker if (!GetDiskSpaceInfo(path, nullptr, &total))
217*6777b538SAndroid Build Coastguard Worker return -1;
218*6777b538SAndroid Build Coastguard Worker return total;
219*6777b538SAndroid Build Coastguard Worker }
220*6777b538SAndroid Build Coastguard Worker
OperatingSystemName()221*6777b538SAndroid Build Coastguard Worker std::string SysInfo::OperatingSystemName() {
222*6777b538SAndroid Build Coastguard Worker return "Windows NT";
223*6777b538SAndroid Build Coastguard Worker }
224*6777b538SAndroid Build Coastguard Worker
225*6777b538SAndroid Build Coastguard Worker // static
OperatingSystemVersion()226*6777b538SAndroid Build Coastguard Worker std::string SysInfo::OperatingSystemVersion() {
227*6777b538SAndroid Build Coastguard Worker win::OSInfo* os_info = win::OSInfo::GetInstance();
228*6777b538SAndroid Build Coastguard Worker win::OSInfo::VersionNumber version_number = os_info->version_number();
229*6777b538SAndroid Build Coastguard Worker std::string version(StringPrintf("%d.%d.%d", version_number.major,
230*6777b538SAndroid Build Coastguard Worker version_number.minor, version_number.build));
231*6777b538SAndroid Build Coastguard Worker win::OSInfo::ServicePack service_pack = os_info->service_pack();
232*6777b538SAndroid Build Coastguard Worker if (service_pack.major != 0) {
233*6777b538SAndroid Build Coastguard Worker version += StringPrintf(" SP%d", service_pack.major);
234*6777b538SAndroid Build Coastguard Worker if (service_pack.minor != 0)
235*6777b538SAndroid Build Coastguard Worker version += StringPrintf(".%d", service_pack.minor);
236*6777b538SAndroid Build Coastguard Worker }
237*6777b538SAndroid Build Coastguard Worker return version;
238*6777b538SAndroid Build Coastguard Worker }
239*6777b538SAndroid Build Coastguard Worker
240*6777b538SAndroid Build Coastguard Worker // TODO: Implement OperatingSystemVersionComplete, which would include
241*6777b538SAndroid Build Coastguard Worker // patchlevel/service pack number.
242*6777b538SAndroid Build Coastguard Worker // See chrome/browser/feedback/feedback_util.h, FeedbackUtil::SetOSVersion.
243*6777b538SAndroid Build Coastguard Worker
244*6777b538SAndroid Build Coastguard Worker // static
OperatingSystemArchitecture()245*6777b538SAndroid Build Coastguard Worker std::string SysInfo::OperatingSystemArchitecture() {
246*6777b538SAndroid Build Coastguard Worker win::OSInfo::WindowsArchitecture arch = win::OSInfo::GetArchitecture();
247*6777b538SAndroid Build Coastguard Worker switch (arch) {
248*6777b538SAndroid Build Coastguard Worker case win::OSInfo::X86_ARCHITECTURE:
249*6777b538SAndroid Build Coastguard Worker return "x86";
250*6777b538SAndroid Build Coastguard Worker case win::OSInfo::X64_ARCHITECTURE:
251*6777b538SAndroid Build Coastguard Worker return "x86_64";
252*6777b538SAndroid Build Coastguard Worker case win::OSInfo::IA64_ARCHITECTURE:
253*6777b538SAndroid Build Coastguard Worker return "ia64";
254*6777b538SAndroid Build Coastguard Worker case win::OSInfo::ARM64_ARCHITECTURE:
255*6777b538SAndroid Build Coastguard Worker return "arm64";
256*6777b538SAndroid Build Coastguard Worker default:
257*6777b538SAndroid Build Coastguard Worker return "";
258*6777b538SAndroid Build Coastguard Worker }
259*6777b538SAndroid Build Coastguard Worker }
260*6777b538SAndroid Build Coastguard Worker
261*6777b538SAndroid Build Coastguard Worker // static
CPUModelName()262*6777b538SAndroid Build Coastguard Worker std::string SysInfo::CPUModelName() {
263*6777b538SAndroid Build Coastguard Worker return win::OSInfo::GetInstance()->processor_model_name();
264*6777b538SAndroid Build Coastguard Worker }
265*6777b538SAndroid Build Coastguard Worker
266*6777b538SAndroid Build Coastguard Worker // static
VMAllocationGranularity()267*6777b538SAndroid Build Coastguard Worker size_t SysInfo::VMAllocationGranularity() {
268*6777b538SAndroid Build Coastguard Worker return win::OSInfo::GetInstance()->allocation_granularity();
269*6777b538SAndroid Build Coastguard Worker }
270*6777b538SAndroid Build Coastguard Worker
271*6777b538SAndroid Build Coastguard Worker // static
OperatingSystemVersionNumbers(int32_t * major_version,int32_t * minor_version,int32_t * bugfix_version)272*6777b538SAndroid Build Coastguard Worker void SysInfo::OperatingSystemVersionNumbers(int32_t* major_version,
273*6777b538SAndroid Build Coastguard Worker int32_t* minor_version,
274*6777b538SAndroid Build Coastguard Worker int32_t* bugfix_version) {
275*6777b538SAndroid Build Coastguard Worker win::OSInfo* os_info = win::OSInfo::GetInstance();
276*6777b538SAndroid Build Coastguard Worker *major_version = static_cast<int32_t>(os_info->version_number().major);
277*6777b538SAndroid Build Coastguard Worker *minor_version = static_cast<int32_t>(os_info->version_number().minor);
278*6777b538SAndroid Build Coastguard Worker *bugfix_version = 0;
279*6777b538SAndroid Build Coastguard Worker }
280*6777b538SAndroid Build Coastguard Worker
281*6777b538SAndroid Build Coastguard Worker // static
ReadHardwareInfoFromRegistry(const wchar_t * reg_value_name)282*6777b538SAndroid Build Coastguard Worker std::string ReadHardwareInfoFromRegistry(const wchar_t* reg_value_name) {
283*6777b538SAndroid Build Coastguard Worker // On some systems or VMs, the system information and some of the below
284*6777b538SAndroid Build Coastguard Worker // locations may be missing info. Attempt to find the info from the below
285*6777b538SAndroid Build Coastguard Worker // registry keys in the order provided.
286*6777b538SAndroid Build Coastguard Worker static const wchar_t* const kSystemInfoRegKeyPaths[] = {
287*6777b538SAndroid Build Coastguard Worker L"HARDWARE\\DESCRIPTION\\System\\BIOS",
288*6777b538SAndroid Build Coastguard Worker L"SYSTEM\\CurrentControlSet\\Control\\SystemInformation",
289*6777b538SAndroid Build Coastguard Worker L"SYSTEM\\HardwareConfig\\Current",
290*6777b538SAndroid Build Coastguard Worker };
291*6777b538SAndroid Build Coastguard Worker
292*6777b538SAndroid Build Coastguard Worker std::wstring value;
293*6777b538SAndroid Build Coastguard Worker for (const wchar_t* system_info_reg_key_path : kSystemInfoRegKeyPaths) {
294*6777b538SAndroid Build Coastguard Worker base::win::RegKey system_information_key;
295*6777b538SAndroid Build Coastguard Worker if (system_information_key.Open(HKEY_LOCAL_MACHINE,
296*6777b538SAndroid Build Coastguard Worker system_info_reg_key_path,
297*6777b538SAndroid Build Coastguard Worker KEY_READ) == ERROR_SUCCESS) {
298*6777b538SAndroid Build Coastguard Worker if ((system_information_key.ReadValue(reg_value_name, &value) ==
299*6777b538SAndroid Build Coastguard Worker ERROR_SUCCESS) &&
300*6777b538SAndroid Build Coastguard Worker !value.empty()) {
301*6777b538SAndroid Build Coastguard Worker break;
302*6777b538SAndroid Build Coastguard Worker }
303*6777b538SAndroid Build Coastguard Worker }
304*6777b538SAndroid Build Coastguard Worker }
305*6777b538SAndroid Build Coastguard Worker
306*6777b538SAndroid Build Coastguard Worker return base::SysWideToUTF8(value);
307*6777b538SAndroid Build Coastguard Worker }
308*6777b538SAndroid Build Coastguard Worker
309*6777b538SAndroid Build Coastguard Worker // static
GetHardwareInfoSync()310*6777b538SAndroid Build Coastguard Worker SysInfo::HardwareInfo SysInfo::GetHardwareInfoSync() {
311*6777b538SAndroid Build Coastguard Worker HardwareInfo info = {ReadHardwareInfoFromRegistry(L"SystemManufacturer"),
312*6777b538SAndroid Build Coastguard Worker SysInfo::HardwareModelName()};
313*6777b538SAndroid Build Coastguard Worker return info;
314*6777b538SAndroid Build Coastguard Worker }
315*6777b538SAndroid Build Coastguard Worker
316*6777b538SAndroid Build Coastguard Worker // static
HardwareModelName()317*6777b538SAndroid Build Coastguard Worker std::string SysInfo::HardwareModelName() {
318*6777b538SAndroid Build Coastguard Worker return ReadHardwareInfoFromRegistry(L"SystemProductName");
319*6777b538SAndroid Build Coastguard Worker }
320*6777b538SAndroid Build Coastguard Worker
321*6777b538SAndroid Build Coastguard Worker } // namespace base
322