1 // Copyright 2014 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 "chrome/browser/metrics/machine_id_provider.h"
10 #include "base/base_paths.h"
11 #include "base/files/file_path.h"
12 #include "base/path_service.h"
13 #include "base/win/scoped_handle.h"
14 #include "content/public/browser/browser_thread.h"
18 MachineIdProvider::MachineIdProvider() {}
19 MachineIdProvider::~MachineIdProvider() {}
21 // On windows, the machine id is based on the serial number of the drive Chrome
23 std::string
MachineIdProvider::GetMachineId() {
24 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
26 // Use the program's path to get the drive used for the machine id. This means
27 // that whenever the underlying drive changes, it's considered a new machine.
28 // This is fine as we do not support migrating Chrome installs to new drives.
29 base::FilePath executable_path
;
31 if (!PathService::Get(base::FILE_EXE
, &executable_path
)) {
36 std::vector
<base::FilePath::StringType
> path_components
;
37 executable_path
.GetComponents(&path_components
);
38 if (path_components
.empty()) {
42 base::FilePath::StringType drive_name
= L
"\\\\.\\" + path_components
[0];
44 base::win::ScopedHandle
drive_handle(CreateFile(
47 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
53 STORAGE_PROPERTY_QUERY query
= {};
54 query
.PropertyId
= StorageDeviceProperty
;
55 query
.QueryType
= PropertyStandardQuery
;
57 // Perform an initial query to get the number of bytes being returned.
59 STORAGE_DESCRIPTOR_HEADER header
= {};
60 BOOL status
= DeviceIoControl(drive_handle
, IOCTL_STORAGE_QUERY_PROPERTY
,
61 &query
, sizeof(STORAGE_PROPERTY_QUERY
),
62 &header
, sizeof(STORAGE_DESCRIPTOR_HEADER
),
63 &bytes_returned
, NULL
);
68 // Query for the actual serial number.
69 std::vector
<int8
> output_buf(header
.Size
);
70 status
= DeviceIoControl(drive_handle
, IOCTL_STORAGE_QUERY_PROPERTY
,
71 &query
, sizeof(STORAGE_PROPERTY_QUERY
),
72 &output_buf
[0], output_buf
.size(),
73 &bytes_returned
, NULL
);
78 const STORAGE_DEVICE_DESCRIPTOR
* device_descriptor
=
79 reinterpret_cast<STORAGE_DEVICE_DESCRIPTOR
*>(&output_buf
[0]);
81 // The serial number is stored in the |output_buf| as a null-terminated
82 // string starting at the specified offset.
83 const DWORD offset
= device_descriptor
->SerialNumberOffset
;
84 if (offset
>= output_buf
.size())
87 // Make sure that the null-terminator exists.
88 const std::vector
<int8
>::iterator serial_number_begin
=
89 output_buf
.begin() + offset
;
90 const std::vector
<int8
>::iterator null_location
=
91 std::find(serial_number_begin
, output_buf
.end(), '\0');
92 if (null_location
== output_buf
.end())
95 const char* serial_number
=
96 reinterpret_cast<const char*>(&output_buf
[offset
]);
98 return std::string(serial_number
);
102 MachineIdProvider
* MachineIdProvider::CreateInstance() {
103 return new MachineIdProvider();
106 } // namespace metrics