Enable Enterprise enrollment on desktop builds.
[chromium-blink-merge.git] / chrome / browser / metrics / machine_id_provider_win.cc
blobc3320bccb4b3cbdd5f5b1bf6f85047847ba4586d
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"
7 #include <windows.h>
8 #include <winioctl.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"
16 namespace metrics {
18 MachineIdProvider::MachineIdProvider() {}
19 MachineIdProvider::~MachineIdProvider() {}
21 // On windows, the machine id is based on the serial number of the drive Chrome
22 // is running from.
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)) {
32 NOTREACHED();
33 return std::string();
36 std::vector<base::FilePath::StringType> path_components;
37 executable_path.GetComponents(&path_components);
38 if (path_components.empty()) {
39 NOTREACHED();
40 return std::string();
42 base::FilePath::StringType drive_name = L"\\\\.\\" + path_components[0];
44 base::win::ScopedHandle drive_handle(CreateFile(
45 drive_name.c_str(),
47 FILE_SHARE_READ | FILE_SHARE_WRITE,
48 NULL,
49 OPEN_EXISTING,
51 NULL));
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.
58 DWORD bytes_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);
65 if (!status)
66 return std::string();
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);
75 if (!status)
76 return std::string();
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())
85 return std::string();
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())
93 return std::string();
95 const char* serial_number =
96 reinterpret_cast<const char*>(&output_buf[offset]);
98 return std::string(serial_number);
101 // static
102 MachineIdProvider* MachineIdProvider::CreateInstance() {
103 return new MachineIdProvider();
106 } // namespace metrics