root/chrome/browser/metrics/machine_id_provider_win.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. GetMachineId
  2. CreateInstance

// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/metrics/machine_id_provider.h"

#include <windows.h>
#include <winioctl.h>

#include "base/base_paths.h"
#include "base/files/file_path.h"
#include "base/path_service.h"
#include "base/win/scoped_handle.h"
#include "content/public/browser/browser_thread.h"

namespace metrics {

MachineIdProvider::MachineIdProvider() {}
MachineIdProvider::~MachineIdProvider() {}

// On windows, the machine id is based on the serial number of the drive Chrome
// is running from.
std::string MachineIdProvider::GetMachineId() {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));

  // Use the program's path to get the drive used for the machine id. This means
  // that whenever the underlying drive changes, it's considered a new machine.
  // This is fine as we do not support migrating Chrome installs to new drives.
  base::FilePath executable_path;

  if (!PathService::Get(base::FILE_EXE, &executable_path)) {
    NOTREACHED();
    return std::string();
  }

  std::vector<base::FilePath::StringType> path_components;
  executable_path.GetComponents(&path_components);
  if (path_components.empty()) {
    NOTREACHED();
    return std::string();
  }
  base::FilePath::StringType drive_name = L"\\\\.\\" + path_components[0];

  base::win::ScopedHandle drive_handle(CreateFile(
      drive_name.c_str(),
      0,
      FILE_SHARE_READ | FILE_SHARE_WRITE,
      NULL,
      OPEN_EXISTING,
      0,
      NULL));

  STORAGE_PROPERTY_QUERY query = {};
  query.PropertyId = StorageDeviceProperty;
  query.QueryType = PropertyStandardQuery;

  // Perform an initial query to get the number of bytes being returned.
  DWORD bytes_returned;
  STORAGE_DESCRIPTOR_HEADER header = {};
  BOOL status = DeviceIoControl(drive_handle, IOCTL_STORAGE_QUERY_PROPERTY,
                                &query, sizeof(STORAGE_PROPERTY_QUERY),
                                &header, sizeof(STORAGE_DESCRIPTOR_HEADER),
                                &bytes_returned, NULL);

  if (!status)
    return std::string();

  // Query for the actual serial number.
  std::vector<int8> output_buf(header.Size);
  status = DeviceIoControl(drive_handle, IOCTL_STORAGE_QUERY_PROPERTY,
                           &query, sizeof(STORAGE_PROPERTY_QUERY),
                           &output_buf[0], output_buf.size(),
                           &bytes_returned, NULL);

  if (!status)
    return std::string();

  const STORAGE_DEVICE_DESCRIPTOR* device_descriptor =
      reinterpret_cast<STORAGE_DEVICE_DESCRIPTOR*>(&output_buf[0]);

  // The serial number is stored in the |output_buf| as a null-terminated
  // string starting at the specified offset.
  const DWORD offset = device_descriptor->SerialNumberOffset;
  if (offset >= output_buf.size())
    return std::string();

  // Make sure that the null-terminator exists.
  const std::vector<int8>::iterator serial_number_begin =
      output_buf.begin() + offset;
  const std::vector<int8>::iterator null_location =
      std::find(serial_number_begin, output_buf.end(), '\0');
  if (null_location == output_buf.end())
    return std::string();

  const char* serial_number =
      reinterpret_cast<const char*>(&output_buf[offset]);

  return std::string(serial_number);
}

// static
MachineIdProvider* MachineIdProvider::CreateInstance() {
  return new MachineIdProvider();
}

} //  namespace metrics

/* [<][>][^][v][top][bottom][index][help] */