Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / components / metrics / machine_id_provider_win.cc
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.
4
5 #include "components/metrics/machine_id_provider.h"
6
7 #include <windows.h>
8 #include <winioctl.h>
9
10 #include "base/base_paths.h"
11 #include "base/files/file_path.h"
12 #include "base/path_service.h"
13 #include "base/threading/thread_restrictions.h"
14 #include "base/win/scoped_handle.h"
15
16 namespace metrics {
17
18 MachineIdProvider::MachineIdProvider() {
19 }
20
21 MachineIdProvider::~MachineIdProvider() {
22 }
23
24 // On windows, the machine id is based on the serial number of the drive Chrome
25 // is running from.
26 std::string MachineIdProvider::GetMachineId() {
27   base::ThreadRestrictions::AssertIOAllowed();
28
29   // Use the program's path to get the drive used for the machine id. This means
30   // that whenever the underlying drive changes, it's considered a new machine.
31   // This is fine as we do not support migrating Chrome installs to new drives.
32   base::FilePath executable_path;
33
34   if (!PathService::Get(base::FILE_EXE, &executable_path)) {
35     NOTREACHED();
36     return std::string();
37   }
38
39   std::vector<base::FilePath::StringType> path_components;
40   executable_path.GetComponents(&path_components);
41   if (path_components.empty()) {
42     NOTREACHED();
43     return std::string();
44   }
45   base::FilePath::StringType drive_name = L"\\\\.\\" + path_components[0];
46
47   base::win::ScopedHandle drive_handle(
48       CreateFile(drive_name.c_str(),
49                  0,
50                  FILE_SHARE_READ | FILE_SHARE_WRITE,
51                  NULL,
52                  OPEN_EXISTING,
53                  0,
54                  NULL));
55
56   STORAGE_PROPERTY_QUERY query = {};
57   query.PropertyId = StorageDeviceProperty;
58   query.QueryType = PropertyStandardQuery;
59
60   // Perform an initial query to get the number of bytes being returned.
61   DWORD bytes_returned;
62   STORAGE_DESCRIPTOR_HEADER header = {};
63   BOOL status = DeviceIoControl(drive_handle.Get(),
64                                 IOCTL_STORAGE_QUERY_PROPERTY,
65                                 &query,
66                                 sizeof(STORAGE_PROPERTY_QUERY),
67                                 &header,
68                                 sizeof(STORAGE_DESCRIPTOR_HEADER),
69                                 &bytes_returned,
70                                 NULL);
71
72   if (!status)
73     return std::string();
74
75   // Query for the actual serial number.
76   std::vector<int8> output_buf(header.Size);
77   status = DeviceIoControl(drive_handle.Get(),
78                            IOCTL_STORAGE_QUERY_PROPERTY,
79                            &query,
80                            sizeof(STORAGE_PROPERTY_QUERY),
81                            &output_buf[0],
82                            output_buf.size(),
83                            &bytes_returned,
84                            NULL);
85
86   if (!status)
87     return std::string();
88
89   const STORAGE_DEVICE_DESCRIPTOR* device_descriptor =
90       reinterpret_cast<STORAGE_DEVICE_DESCRIPTOR*>(&output_buf[0]);
91
92   // The serial number is stored in the |output_buf| as a null-terminated
93   // string starting at the specified offset.
94   const DWORD offset = device_descriptor->SerialNumberOffset;
95   if (offset >= output_buf.size())
96     return std::string();
97
98   // Make sure that the null-terminator exists.
99   const std::vector<int8>::iterator serial_number_begin =
100       output_buf.begin() + offset;
101   const std::vector<int8>::iterator null_location =
102       std::find(serial_number_begin, output_buf.end(), '\0');
103   if (null_location == output_buf.end())
104     return std::string();
105
106   const char* serial_number =
107       reinterpret_cast<const char*>(&output_buf[offset]);
108
109   return std::string(serial_number);
110 }
111
112 // static
113 MachineIdProvider* MachineIdProvider::CreateInstance() {
114   return new MachineIdProvider();
115 }
116
117 }  //  namespace metrics