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.
5 #include "base/sys_info.h"
11 #include "base/files/file.h"
12 #include "base/files/file_path.h"
13 #include "base/logging.h"
14 #include "base/macros.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "base/strings/stringprintf.h"
17 #include "base/threading/thread_restrictions.h"
18 #include "base/win/windows_version.h"
22 // Semi-copy of similarly named struct from ata.h in WinDDK.
23 struct IDENTIFY_DEVICE_DATA
{
24 USHORT UnusedWords
[217];
25 USHORT NominalMediaRotationRate
;
26 USHORT MoreUnusedWords
[38];
28 COMPILE_ASSERT(sizeof(IDENTIFY_DEVICE_DATA
) == 512, IdentifyDeviceDataSize
);
31 ATA_PASS_THROUGH_EX query
;
32 IDENTIFY_DEVICE_DATA result
;
35 int64
AmountOfMemory(DWORDLONG
MEMORYSTATUSEX::* memory_field
) {
36 MEMORYSTATUSEX memory_info
;
37 memory_info
.dwLength
= sizeof(memory_info
);
38 if (!GlobalMemoryStatusEx(&memory_info
)) {
43 int64 rv
= static_cast<int64
>(memory_info
.*memory_field
);
44 return rv
< 0 ? kint64max
: rv
;
52 int SysInfo::NumberOfProcessors() {
53 return win::OSInfo::GetInstance()->processors();
57 int64
SysInfo::AmountOfPhysicalMemory() {
58 return AmountOfMemory(&MEMORYSTATUSEX::ullTotalPhys
);
62 int64
SysInfo::AmountOfAvailablePhysicalMemory() {
63 return AmountOfMemory(&MEMORYSTATUSEX::ullAvailPhys
);
67 int64
SysInfo::AmountOfVirtualMemory() {
72 int64
SysInfo::AmountOfFreeDiskSpace(const FilePath
& path
) {
73 ThreadRestrictions::AssertIOAllowed();
75 ULARGE_INTEGER available
, total
, free
;
76 if (!GetDiskFreeSpaceExW(path
.value().c_str(), &available
, &total
, &free
))
79 int64 rv
= static_cast<int64
>(available
.QuadPart
);
80 return rv
< 0 ? kint64max
: rv
;
83 bool SysInfo::HasSeekPenalty(const FilePath
& path
, bool* has_seek_penalty
) {
84 ThreadRestrictions::AssertIOAllowed();
86 DCHECK(path
.IsAbsolute());
87 DCHECK(has_seek_penalty
);
89 std::vector
<FilePath::StringType
> components
;
90 path
.GetComponents(&components
);
92 int flags
= File::FLAG_OPEN
;
93 const bool win7_or_higher
= win::GetVersion() >= win::VERSION_WIN7
;
95 flags
|= File::FLAG_READ
| File::FLAG_WRITE
;
97 File
volume(FilePath(L
"\\\\.\\" + components
[0]), flags
);
98 if (!volume
.IsValid())
101 if (win7_or_higher
) {
102 STORAGE_PROPERTY_QUERY query
= {};
103 query
.QueryType
= PropertyStandardQuery
;
104 query
.PropertyId
= StorageDeviceSeekPenaltyProperty
;
106 DEVICE_SEEK_PENALTY_DESCRIPTOR result
;
107 DWORD bytes_returned
;
108 BOOL success
= DeviceIoControl(volume
.GetPlatformFile(),
109 IOCTL_STORAGE_QUERY_PROPERTY
,
110 &query
, sizeof(query
),
111 &result
, sizeof(result
),
112 &bytes_returned
, NULL
);
113 if (success
== FALSE
|| bytes_returned
< sizeof(result
))
116 *has_seek_penalty
= result
.IncursSeekPenalty
!= FALSE
;
118 AtaRequest request
= {};
119 request
.query
.AtaFlags
= ATA_FLAGS_DATA_IN
;
120 request
.query
.CurrentTaskFile
[6] = ID_CMD
;
121 request
.query
.DataBufferOffset
= sizeof(request
.query
);
122 request
.query
.DataTransferLength
= sizeof(request
.result
);
123 request
.query
.Length
= sizeof(request
.query
);
124 request
.query
.TimeOutValue
= 10;
126 DWORD bytes_returned
;
127 BOOL success
= DeviceIoControl(volume
.GetPlatformFile(),
128 IOCTL_ATA_PASS_THROUGH
,
129 &request
, sizeof(request
),
130 &request
, sizeof(request
),
131 &bytes_returned
, NULL
);
132 if (success
== FALSE
|| bytes_returned
< sizeof(request
) ||
133 request
.query
.CurrentTaskFile
[0]) {
137 *has_seek_penalty
= request
.result
.NominalMediaRotationRate
!= 1;
144 std::string
SysInfo::OperatingSystemName() {
149 std::string
SysInfo::OperatingSystemVersion() {
150 win::OSInfo
* os_info
= win::OSInfo::GetInstance();
151 win::OSInfo::VersionNumber version_number
= os_info
->version_number();
152 std::string
version(StringPrintf("%d.%d", version_number
.major
,
153 version_number
.minor
));
154 win::OSInfo::ServicePack service_pack
= os_info
->service_pack();
155 if (service_pack
.major
!= 0) {
156 version
+= StringPrintf(" SP%d", service_pack
.major
);
157 if (service_pack
.minor
!= 0)
158 version
+= StringPrintf(".%d", service_pack
.minor
);
163 // TODO: Implement OperatingSystemVersionComplete, which would include
164 // patchlevel/service pack number.
165 // See chrome/browser/feedback/feedback_util.h, FeedbackUtil::SetOSVersion.
168 std::string
SysInfo::OperatingSystemArchitecture() {
169 win::OSInfo::WindowsArchitecture arch
=
170 win::OSInfo::GetInstance()->architecture();
172 case win::OSInfo::X86_ARCHITECTURE
:
174 case win::OSInfo::X64_ARCHITECTURE
:
176 case win::OSInfo::IA64_ARCHITECTURE
:
184 std::string
SysInfo::CPUModelName() {
185 return win::OSInfo::GetInstance()->processor_model_name();
189 size_t SysInfo::VMAllocationGranularity() {
190 return win::OSInfo::GetInstance()->allocation_granularity();
194 void SysInfo::OperatingSystemVersionNumbers(int32
* major_version
,
195 int32
* minor_version
,
196 int32
* bugfix_version
) {
197 win::OSInfo
* os_info
= win::OSInfo::GetInstance();
198 *major_version
= os_info
->version_number().major
;
199 *minor_version
= os_info
->version_number().minor
;