1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "base/system/sys_info.h"
6 
7 #include <stddef.h>
8 #include <stdint.h>
9 #include <windows.h>
10 
11 #include <limits>
12 
13 #include "base/files/file_path.h"
14 #include "base/logging.h"
15 #include "base/process/process_metrics.h"
16 #include "base/strings/string_util.h"
17 #include "base/strings/stringprintf.h"
18 #include "base/strings/utf_string_conversions.h"
19 #include "base/threading/scoped_blocking_call.h"
20 #include "base/win/windows_version.h"
21 #include "base/win/wmi.h"
22 
23 namespace {
24 
AmountOfMemory(DWORDLONG MEMORYSTATUSEX::* memory_field)25 int64_t AmountOfMemory(DWORDLONG MEMORYSTATUSEX::*memory_field) {
26   MEMORYSTATUSEX memory_info;
27   memory_info.dwLength = sizeof(memory_info);
28   if (!GlobalMemoryStatusEx(&memory_info)) {
29     NOTREACHED();
30     return 0;
31   }
32 
33   int64_t rv = static_cast<int64_t>(memory_info.*memory_field);
34   return rv < 0 ? std::numeric_limits<int64_t>::max() : rv;
35 }
36 
GetDiskSpaceInfo(const base::FilePath & path,int64_t * available_bytes,int64_t * total_bytes)37 bool GetDiskSpaceInfo(const base::FilePath& path,
38                       int64_t* available_bytes,
39                       int64_t* total_bytes) {
40   ULARGE_INTEGER available;
41   ULARGE_INTEGER total;
42   ULARGE_INTEGER free;
43   if (!GetDiskFreeSpaceExW(path.value().c_str(), &available, &total, &free))
44     return false;
45 
46   if (available_bytes) {
47     *available_bytes = static_cast<int64_t>(available.QuadPart);
48     if (*available_bytes < 0)
49       *available_bytes = std::numeric_limits<int64_t>::max();
50   }
51   if (total_bytes) {
52     *total_bytes = static_cast<int64_t>(total.QuadPart);
53     if (*total_bytes < 0)
54       *total_bytes = std::numeric_limits<int64_t>::max();
55   }
56   return true;
57 }
58 
59 }  // namespace
60 
61 namespace base {
62 
63 // static
NumberOfProcessors()64 int SysInfo::NumberOfProcessors() {
65   return win::OSInfo::GetInstance()->processors();
66 }
67 
68 // static
AmountOfPhysicalMemoryImpl()69 int64_t SysInfo::AmountOfPhysicalMemoryImpl() {
70   return AmountOfMemory(&MEMORYSTATUSEX::ullTotalPhys);
71 }
72 
73 // static
AmountOfAvailablePhysicalMemoryImpl()74 int64_t SysInfo::AmountOfAvailablePhysicalMemoryImpl() {
75   SystemMemoryInfoKB info;
76   if (!GetSystemMemoryInfo(&info))
77     return 0;
78   return static_cast<int64_t>(info.avail_phys) * 1024;
79 }
80 
81 // static
AmountOfVirtualMemory()82 int64_t SysInfo::AmountOfVirtualMemory() {
83   return AmountOfMemory(&MEMORYSTATUSEX::ullTotalVirtual);
84 }
85 
86 // static
AmountOfFreeDiskSpace(const FilePath & path)87 int64_t SysInfo::AmountOfFreeDiskSpace(const FilePath& path) {
88   base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
89                                                 base::BlockingType::MAY_BLOCK);
90 
91   int64_t available;
92   if (!GetDiskSpaceInfo(path, &available, nullptr))
93     return -1;
94   return available;
95 }
96 
97 // static
AmountOfTotalDiskSpace(const FilePath & path)98 int64_t SysInfo::AmountOfTotalDiskSpace(const FilePath& path) {
99   base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
100                                                 base::BlockingType::MAY_BLOCK);
101 
102   int64_t total;
103   if (!GetDiskSpaceInfo(path, nullptr, &total))
104     return -1;
105   return total;
106 }
107 
OperatingSystemName()108 std::string SysInfo::OperatingSystemName() {
109   return "Windows NT";
110 }
111 
112 // static
OperatingSystemVersion()113 std::string SysInfo::OperatingSystemVersion() {
114   win::OSInfo* os_info = win::OSInfo::GetInstance();
115   win::OSInfo::VersionNumber version_number = os_info->version_number();
116   std::string version(StringPrintf("%d.%d.%d", version_number.major,
117                                    version_number.minor, version_number.build));
118   win::OSInfo::ServicePack service_pack = os_info->service_pack();
119   if (service_pack.major != 0) {
120     version += StringPrintf(" SP%d", service_pack.major);
121     if (service_pack.minor != 0)
122       version += StringPrintf(".%d", service_pack.minor);
123   }
124   return version;
125 }
126 
127 // TODO: Implement OperatingSystemVersionComplete, which would include
128 // patchlevel/service pack number.
129 // See chrome/browser/feedback/feedback_util.h, FeedbackUtil::SetOSVersion.
130 
131 // static
OperatingSystemArchitecture()132 std::string SysInfo::OperatingSystemArchitecture() {
133   win::OSInfo::WindowsArchitecture arch = win::OSInfo::GetArchitecture();
134   switch (arch) {
135     case win::OSInfo::X86_ARCHITECTURE:
136       return "x86";
137     case win::OSInfo::X64_ARCHITECTURE:
138       return "x86_64";
139     case win::OSInfo::IA64_ARCHITECTURE:
140       return "ia64";
141     case win::OSInfo::ARM64_ARCHITECTURE:
142       return "arm64";
143     default:
144       return "";
145   }
146 }
147 
148 // static
CPUModelName()149 std::string SysInfo::CPUModelName() {
150   return win::OSInfo::GetInstance()->processor_model_name();
151 }
152 
153 // static
VMAllocationGranularity()154 size_t SysInfo::VMAllocationGranularity() {
155   return win::OSInfo::GetInstance()->allocation_granularity();
156 }
157 
158 // static
OperatingSystemVersionNumbers(int32_t * major_version,int32_t * minor_version,int32_t * bugfix_version)159 void SysInfo::OperatingSystemVersionNumbers(int32_t* major_version,
160                                             int32_t* minor_version,
161                                             int32_t* bugfix_version) {
162   win::OSInfo* os_info = win::OSInfo::GetInstance();
163   *major_version = os_info->version_number().major;
164   *minor_version = os_info->version_number().minor;
165   *bugfix_version = 0;
166 }
167 
168 // static
GetHardwareInfoSync()169 SysInfo::HardwareInfo SysInfo::GetHardwareInfoSync() {
170   win::WmiComputerSystemInfo wmi_info = win::WmiComputerSystemInfo::Get();
171 
172   HardwareInfo info;
173   info.manufacturer = WideToUTF8(wmi_info.manufacturer());
174   info.model = WideToUTF8(wmi_info.model());
175   info.serial_number = WideToUTF8(wmi_info.serial_number());
176   DCHECK(IsStringUTF8(info.manufacturer));
177   DCHECK(IsStringUTF8(info.model));
178   DCHECK(IsStringUTF8(info.serial_number));
179   return info;
180 }
181 
182 }  // namespace base
183