| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/metrics/drive_metrics_provider.h" | 5 #include "components/metrics/drive_metrics_provider.h" |
| 6 | 6 |
| 7 #include <windows.h> | 7 #include <windows.h> |
| 8 #include <ntddscsi.h> | 8 #include <ntddscsi.h> |
| 9 #include <winioctl.h> | 9 #include <winioctl.h> |
| 10 #include <vector> | 10 #include <vector> |
| 11 | 11 |
| 12 #include "base/files/file.h" | 12 #include "base/files/file.h" |
| 13 #include "base/files/file_path.h" | 13 #include "base/files/file_path.h" |
| 14 #include "base/macros.h" | 14 #include "base/macros.h" |
| 15 #include "base/strings/stringprintf.h" | 15 #include "base/strings/stringprintf.h" |
| 16 #include "base/win/windows_version.h" | 16 #include "base/win/windows_version.h" |
| 17 | 17 |
| 18 namespace metrics { |
| 19 |
| 18 namespace { | 20 namespace { |
| 19 | 21 |
| 20 // Semi-copy of similarly named struct from ata.h in WinDDK. | 22 // Semi-copy of similarly named struct from ata.h in WinDDK. |
| 21 struct IDENTIFY_DEVICE_DATA { | 23 struct IDENTIFY_DEVICE_DATA { |
| 22 USHORT UnusedWords[217]; | 24 USHORT UnusedWords[217]; |
| 23 USHORT NominalMediaRotationRate; | 25 USHORT NominalMediaRotationRate; |
| 24 USHORT MoreUnusedWords[38]; | 26 USHORT MoreUnusedWords[38]; |
| 25 }; | 27 }; |
| 26 COMPILE_ASSERT(sizeof(IDENTIFY_DEVICE_DATA) == 512, IdentifyDeviceDataSize); | 28 COMPILE_ASSERT(sizeof(IDENTIFY_DEVICE_DATA) == 512, IdentifyDeviceDataSize); |
| 27 | 29 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 47 if (!volume.IsValid()) | 49 if (!volume.IsValid()) |
| 48 return false; | 50 return false; |
| 49 | 51 |
| 50 if (win7_or_higher) { | 52 if (win7_or_higher) { |
| 51 STORAGE_PROPERTY_QUERY query = {}; | 53 STORAGE_PROPERTY_QUERY query = {}; |
| 52 query.QueryType = PropertyStandardQuery; | 54 query.QueryType = PropertyStandardQuery; |
| 53 query.PropertyId = StorageDeviceSeekPenaltyProperty; | 55 query.PropertyId = StorageDeviceSeekPenaltyProperty; |
| 54 | 56 |
| 55 DEVICE_SEEK_PENALTY_DESCRIPTOR result; | 57 DEVICE_SEEK_PENALTY_DESCRIPTOR result; |
| 56 DWORD bytes_returned; | 58 DWORD bytes_returned; |
| 57 BOOL success = DeviceIoControl(volume.GetPlatformFile(), | 59 BOOL success = DeviceIoControl( |
| 58 IOCTL_STORAGE_QUERY_PROPERTY, | 60 volume.GetPlatformFile(), IOCTL_STORAGE_QUERY_PROPERTY, &query, |
| 59 &query, sizeof(query), | 61 sizeof(query), &result, sizeof(result), &bytes_returned, NULL); |
| 60 &result, sizeof(result), | |
| 61 &bytes_returned, NULL); | |
| 62 if (success == FALSE || bytes_returned < sizeof(result)) | 62 if (success == FALSE || bytes_returned < sizeof(result)) |
| 63 return false; | 63 return false; |
| 64 | 64 |
| 65 *has_seek_penalty = result.IncursSeekPenalty != FALSE; | 65 *has_seek_penalty = result.IncursSeekPenalty != FALSE; |
| 66 } else { | 66 } else { |
| 67 AtaRequest request = {}; | 67 AtaRequest request = {}; |
| 68 request.query.AtaFlags = ATA_FLAGS_DATA_IN; | 68 request.query.AtaFlags = ATA_FLAGS_DATA_IN; |
| 69 request.query.CurrentTaskFile[6] = ID_CMD; | 69 request.query.CurrentTaskFile[6] = ID_CMD; |
| 70 request.query.DataBufferOffset = sizeof(request.query); | 70 request.query.DataBufferOffset = sizeof(request.query); |
| 71 request.query.DataTransferLength = sizeof(request.result); | 71 request.query.DataTransferLength = sizeof(request.result); |
| 72 request.query.Length = sizeof(request.query); | 72 request.query.Length = sizeof(request.query); |
| 73 request.query.TimeOutValue = 10; | 73 request.query.TimeOutValue = 10; |
| 74 | 74 |
| 75 DWORD bytes_returned; | 75 DWORD bytes_returned; |
| 76 BOOL success = DeviceIoControl(volume.GetPlatformFile(), | 76 BOOL success = DeviceIoControl( |
| 77 IOCTL_ATA_PASS_THROUGH, | 77 volume.GetPlatformFile(), IOCTL_ATA_PASS_THROUGH, &request, |
| 78 &request, sizeof(request), | 78 sizeof(request), &request, sizeof(request), &bytes_returned, NULL); |
| 79 &request, sizeof(request), | |
| 80 &bytes_returned, NULL); | |
| 81 if (success == FALSE || bytes_returned < sizeof(request) || | 79 if (success == FALSE || bytes_returned < sizeof(request) || |
| 82 request.query.CurrentTaskFile[0]) { | 80 request.query.CurrentTaskFile[0]) { |
| 83 return false; | 81 return false; |
| 84 } | 82 } |
| 85 | 83 |
| 86 *has_seek_penalty = request.result.NominalMediaRotationRate != 1; | 84 *has_seek_penalty = request.result.NominalMediaRotationRate != 1; |
| 87 } | 85 } |
| 88 | 86 |
| 89 return true; | 87 return true; |
| 90 } | 88 } |
| 89 |
| 90 } // namespace metrics |
| OLD | NEW |