// 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 "device/bluetooth/bluetooth_low_energy_win.h"

#include <memory>
#include <utility>

#include "base/files/file.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/strings/sys_string_conversions.h"
#include "base/win/scoped_handle.h"
#include "base/win/windows_version.h"
#include "third_party/re2/src/re2/re2.h"

namespace {

using device::win::DeviceRegistryPropertyValue;
using device::win::DevicePropertyValue;
using device::win::BluetoothLowEnergyDeviceInfo;
using device::win::BluetoothLowEnergyServiceInfo;

const char kPlatformNotSupported[] =
    "Bluetooth Low energy is only supported on Windows 8 and later.";
const char kDeviceEnumError[] = "Error enumerating Bluetooth LE devices.";
const char kDeviceInfoError[] =
    "Error retrieving Bluetooth LE device information.";
const char kDeviceAddressError[] =
    "Device instance ID value does not seem to contain a Bluetooth Adapter "
    "address.";
const char kDeviceFriendlyNameError[] = "Device name is not valid.";
const char kInvalidBluetoothAddress[] = "Bluetooth address format is invalid.";
struct Patterns {
  Patterns();
  // Patterns is only instantiated as a leaky LazyInstance, so the destructor
  // is never called.
  ~Patterns() = delete;
  const RE2 address_regex;
};

Patterns::Patterns()
    // Match an embedded MAC address in a device path.
    // e.g.
    // BTHLEDEVICE\{0000180F-0000-1000-8000-00805F9B34FB}_DEV_VID&01000A_PID&
    //   014C_REV&0100_818B4B0BACE6\8&4C387F7&0&0020
    // matches _818B4B0BACE6\
    // and the 12 hex digits are selected in a capture group.
    : address_regex(R"(_([0-9A-F]{12})\\)") {}

base::LazyInstance<Patterns>::Leaky g_patterns = LAZY_INSTANCE_INITIALIZER;

// Like ScopedHandle but for HDEVINFO.  Only use this on HDEVINFO returned from
// SetupDiGetClassDevs.
class DeviceInfoSetTraits {
 public:
  typedef HDEVINFO Handle;

  static bool CloseHandle(HDEVINFO handle) {
    return ::SetupDiDestroyDeviceInfoList(handle) != FALSE;
  }

  static bool IsHandleValid(HDEVINFO handle) {
    return handle != INVALID_HANDLE_VALUE;
  }

  static HDEVINFO NullHandle() { return INVALID_HANDLE_VALUE; }

 private:
  DISALLOW_IMPLICIT_CONSTRUCTORS(DeviceInfoSetTraits);
};

typedef base::win::GenericScopedHandle<DeviceInfoSetTraits,
                                       base::win::DummyVerifierTraits>
    ScopedDeviceInfoSetHandle;

std::string FormatBluetoothError(const char* message, HRESULT hr) {
  std::ostringstream string_stream;
  string_stream << message;
  if (FAILED(hr))
    string_stream << logging::SystemErrorCodeToString(hr);
  return string_stream.str();
}

bool CheckInsufficientBuffer(bool success,
                             const char* message,
                             std::string* error) {
  if (success) {
    *error = FormatBluetoothError(message, S_OK);
    return false;
  }

  HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
  if (hr != HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) {
    *error = FormatBluetoothError(message, hr);
    return false;
  }

  return true;
}

bool CheckHResult(HRESULT hr, const char* message, std::string* error) {
  if (FAILED(hr)) {
    *error = FormatBluetoothError(message, hr);
    return false;
  }

  return true;
}

bool CheckSuccess(bool success, const char* message, std::string* error) {
  if (!success) {
    CheckHResult(HRESULT_FROM_WIN32(GetLastError()), message, error);
    return false;
  }

  return true;
}

bool CheckNoData(HRESULT hr, size_t length) {
  if (hr == HRESULT_FROM_WIN32(ERROR_NOT_FOUND))
    return true;

  if (SUCCEEDED(hr) && length == 0)
    return true;

  return false;
}

bool CheckMoreData(HRESULT hr, const char* message, std::string* error) {
  if (SUCCEEDED(hr)) {
    *error = FormatBluetoothError(message, hr);
    return false;
  }

  if (hr != HRESULT_FROM_WIN32(ERROR_MORE_DATA)) {
    *error = FormatBluetoothError(message, hr);
    return false;
  }

  return true;
}

bool CheckExpectedLength(size_t actual_length,
                         size_t expected_length,
                         const char* message,
                         std::string* error) {
  if (actual_length != expected_length) {
    *error = FormatBluetoothError(message, E_FAIL);
    return false;
  }

  return true;
}

bool CollectBluetoothLowEnergyDeviceProperty(
    const ScopedDeviceInfoSetHandle& device_info_handle,
    PSP_DEVINFO_DATA device_info_data,
    const DEVPROPKEY& key,
    std::unique_ptr<DevicePropertyValue>* value,
    std::string* error) {
  DWORD required_length;
  DEVPROPTYPE prop_type;
  BOOL success = SetupDiGetDeviceProperty(device_info_handle.Get(),
                                          device_info_data,
                                          &key,
                                          &prop_type,
                                          NULL,
                                          0,
                                          &required_length,
                                          0);
  if (!CheckInsufficientBuffer(!!success, kDeviceInfoError, error))
    return false;

  std::unique_ptr<uint8_t[]> prop_value(new uint8_t[required_length]);
  DWORD actual_length = required_length;
  success = SetupDiGetDeviceProperty(device_info_handle.Get(),
                                     device_info_data,
                                     &key,
                                     &prop_type,
                                     prop_value.get(),
                                     actual_length,
                                     &required_length,
                                     0);
  if (!CheckSuccess(!!success, kDeviceInfoError, error))
    return false;
  if (!CheckExpectedLength(
          actual_length, required_length, kDeviceInfoError, error)) {
    return false;
  }

  (*value) = std::unique_ptr<DevicePropertyValue>(
      new DevicePropertyValue(prop_type, std::move(prop_value), actual_length));
  return true;
}

bool CollectBluetoothLowEnergyDeviceRegistryProperty(
    const ScopedDeviceInfoSetHandle& device_info_handle,
    PSP_DEVINFO_DATA device_info_data,
    DWORD property_id,
    std::unique_ptr<DeviceRegistryPropertyValue>* value,
    std::string* error) {
  ULONG required_length = 0;
  BOOL success = SetupDiGetDeviceRegistryProperty(device_info_handle.Get(),
                                                  device_info_data,
                                                  property_id,
                                                  NULL,
                                                  NULL,
                                                  0,
                                                  &required_length);
  if (!CheckInsufficientBuffer(!!success, kDeviceInfoError, error))
    return false;

  std::unique_ptr<uint8_t[]> property_value(new uint8_t[required_length]);
  ULONG actual_length = required_length;
  DWORD property_type;
  success = SetupDiGetDeviceRegistryProperty(device_info_handle.Get(),
                                             device_info_data,
                                             property_id,
                                             &property_type,
                                             property_value.get(),
                                             actual_length,
                                             &required_length);
  if (!CheckSuccess(!!success, kDeviceInfoError, error))
    return false;
  if (!CheckExpectedLength(
          actual_length, required_length, kDeviceInfoError, error)) {
    return false;
  }

  (*value) = DeviceRegistryPropertyValue::Create(
      property_type, std::move(property_value), actual_length);
  return true;
}

bool CollectBluetoothLowEnergyDeviceInstanceId(
    const ScopedDeviceInfoSetHandle& device_info_handle,
    PSP_DEVINFO_DATA device_info_data,
    std::unique_ptr<device::win::BluetoothLowEnergyDeviceInfo>& device_info,
    std::string* error) {
  ULONG required_length = 0;
  BOOL success = SetupDiGetDeviceInstanceId(
      device_info_handle.Get(), device_info_data, NULL, 0, &required_length);
  if (!CheckInsufficientBuffer(!!success, kDeviceInfoError, error))
    return false;

  std::unique_ptr<WCHAR[]> instance_id(new WCHAR[required_length]);
  ULONG actual_length = required_length;
  success = SetupDiGetDeviceInstanceId(device_info_handle.Get(),
                                       device_info_data,
                                       instance_id.get(),
                                       actual_length,
                                       &required_length);
  if (!CheckSuccess(!!success, kDeviceInfoError, error))
    return false;
  if (!CheckExpectedLength(
          actual_length, required_length, kDeviceInfoError, error)) {
    return false;
  }

  if (actual_length >= 1) {
    // Ensure string is zero terminated.
    instance_id.get()[actual_length - 1] = 0;
    device_info->id = base::SysWideToUTF8(instance_id.get());
  }
  return true;
}

bool CollectBluetoothLowEnergyDeviceFriendlyName(
    const ScopedDeviceInfoSetHandle& device_info_handle,
    PSP_DEVINFO_DATA device_info_data,
    std::unique_ptr<device::win::BluetoothLowEnergyDeviceInfo>& device_info,
    std::string* error) {
  std::unique_ptr<DeviceRegistryPropertyValue> property_value;
  if (!CollectBluetoothLowEnergyDeviceRegistryProperty(device_info_handle,
                                                       device_info_data,
                                                       SPDRP_FRIENDLYNAME,
                                                       &property_value,
                                                       error)) {
    return false;
  }

  if (property_value->property_type() != REG_SZ) {
    *error = kDeviceFriendlyNameError;
    return false;
  }

  device_info->friendly_name = property_value->AsString();
  return true;
}

bool ExtractBluetoothAddressFromDeviceInstanceId(const std::string& instance_id,
                                                 BLUETOOTH_ADDRESS* btha,
                                                 std::string* error) {
  std::string address;
  if (!RE2::PartialMatch(instance_id, g_patterns.Get().address_regex,
                         &address)) {
    *error = kDeviceAddressError;
    return false;
  }

  int buffer[6];
  int result =
      sscanf_s(address.c_str(), "%02X%02X%02X%02X%02X%02X", &buffer[5],
               &buffer[4], &buffer[3], &buffer[2], &buffer[1], &buffer[0]);
  if (result != 6) {
    *error = kInvalidBluetoothAddress;
    return false;
  }

  ZeroMemory(btha, sizeof(*btha));
  btha->rgBytes[0] = buffer[0];
  btha->rgBytes[1] = buffer[1];
  btha->rgBytes[2] = buffer[2];
  btha->rgBytes[3] = buffer[3];
  btha->rgBytes[4] = buffer[4];
  btha->rgBytes[5] = buffer[5];
  return true;
}

bool CollectBluetoothLowEnergyDeviceAddress(
    const ScopedDeviceInfoSetHandle& device_info_handle,
    PSP_DEVINFO_DATA device_info_data,
    std::unique_ptr<device::win::BluetoothLowEnergyDeviceInfo>& device_info,
    std::string* error) {
  // TODO(rpaquay): We exctract the bluetooth device address from the device
  // instance ID string, as we did not find a more formal API for retrieving the
  // bluetooth address of a Bluetooth Low Energy device.
  // A Bluetooth device instance ID often has the following format (under
  // Win8+):
  // BTHLE\DEV_BC6A29AB5FB0\8&31038925&0&BC6A29AB5FB0
  // However, they have also been seen with the following, more expanded,
  // format:
  // BTHLEDEVICE\{0000180F-0000-1000-8000-00805F9B34FB}_DEV_VID&01000A_PID&
  // 014C_REV&0100_818B4B0BACE6\8&4C387F7&0&0020
  return ExtractBluetoothAddressFromDeviceInstanceId(
      device_info->id, &device_info->address, error);
}

bool CollectBluetoothLowEnergyDeviceStatus(
    const ScopedDeviceInfoSetHandle& device_info_handle,
    PSP_DEVINFO_DATA device_info_data,
    std::unique_ptr<device::win::BluetoothLowEnergyDeviceInfo>& device_info,
    std::string* error) {
  std::unique_ptr<DevicePropertyValue> value;
  if (!CollectBluetoothLowEnergyDeviceProperty(device_info_handle,
                                               device_info_data,
                                               DEVPKEY_Device_DevNodeStatus,
                                               &value,
                                               error)) {
    return false;
  }

  if (value->property_type() != DEVPROP_TYPE_UINT32) {
    *error = kDeviceInfoError;
    return false;
  }

  device_info->connected = !(value->AsUint32() & DN_DEVICE_DISCONNECTED);
  // Windows 8 exposes BLE devices only if they are visible and paired. This
  // might change in the future if Windows offers a public API for discovering
  // and pairing BLE devices.
  device_info->visible = true;
  device_info->authenticated = true;
  return true;
}

bool CollectBluetoothLowEnergyDeviceServices(
    const base::FilePath& device_path,
    std::vector<std::unique_ptr<BluetoothLowEnergyServiceInfo>>* services,
    std::string* error) {
  base::File file(device_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
  if (!file.IsValid()) {
    *error = file.ErrorToString(file.error_details());
    return false;
  }

  USHORT required_length;
  HRESULT hr = BluetoothGATTGetServices(file.GetPlatformFile(),
                                        0,
                                        NULL,
                                        &required_length,
                                        BLUETOOTH_GATT_FLAG_NONE);
  if (CheckNoData(hr, required_length))
    return true;
  if (!CheckMoreData(hr, kDeviceInfoError, error))
    return false;

  std::unique_ptr<BTH_LE_GATT_SERVICE[]> gatt_services(
      new BTH_LE_GATT_SERVICE[required_length]);
  USHORT actual_length = required_length;
  hr = BluetoothGATTGetServices(file.GetPlatformFile(),
                                actual_length,
                                gatt_services.get(),
                                &required_length,
                                BLUETOOTH_GATT_FLAG_NONE);
  if (!CheckHResult(hr, kDeviceInfoError, error))
    return false;
  if (!CheckExpectedLength(
          actual_length, required_length, kDeviceInfoError, error)) {
    return false;
  }

  for (USHORT i = 0; i < actual_length; ++i) {
    BTH_LE_GATT_SERVICE& gatt_service(gatt_services.get()[i]);
    auto service_info = std::make_unique<BluetoothLowEnergyServiceInfo>();
    service_info->uuid = gatt_service.ServiceUuid;
    service_info->attribute_handle = gatt_service.AttributeHandle;
    services->push_back(std::move(service_info));
  }

  return true;
}

bool CollectBluetoothLowEnergyDeviceInfo(
    const ScopedDeviceInfoSetHandle& device_info_handle,
    PSP_DEVICE_INTERFACE_DATA device_interface_data,
    std::unique_ptr<device::win::BluetoothLowEnergyDeviceInfo>* device_info,
    std::string* error) {
  // Retrieve required # of bytes for interface details
  ULONG required_length = 0;
  BOOL success = SetupDiGetDeviceInterfaceDetail(device_info_handle.Get(),
                                                 device_interface_data,
                                                 NULL,
                                                 0,
                                                 &required_length,
                                                 NULL);
  if (!CheckInsufficientBuffer(!!success, kDeviceInfoError, error))
    return false;

  std::unique_ptr<uint8_t[]> interface_data(new uint8_t[required_length]);
  ZeroMemory(interface_data.get(), required_length);

  PSP_DEVICE_INTERFACE_DETAIL_DATA device_interface_detail_data =
      reinterpret_cast<PSP_DEVICE_INTERFACE_DETAIL_DATA>(interface_data.get());
  device_interface_detail_data->cbSize =
      sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

  SP_DEVINFO_DATA device_info_data = {0};
  device_info_data.cbSize = sizeof(SP_DEVINFO_DATA);

  ULONG actual_length = required_length;
  success = SetupDiGetDeviceInterfaceDetail(device_info_handle.Get(),
                                            device_interface_data,
                                            device_interface_detail_data,
                                            actual_length,
                                            &required_length,
                                            &device_info_data);
  if (!CheckSuccess(!!success, kDeviceInfoError, error))
    return false;
  if (!CheckExpectedLength(
          actual_length, required_length, kDeviceInfoError, error)) {
    return false;
  }

  std::unique_ptr<device::win::BluetoothLowEnergyDeviceInfo> result(
      new device::win::BluetoothLowEnergyDeviceInfo());
  result->path =
      base::FilePath(std::wstring(device_interface_detail_data->DevicePath));
  if (!CollectBluetoothLowEnergyDeviceInstanceId(
          device_info_handle, &device_info_data, result, error)) {
    return false;
  }
  // Get the friendly name. If it fails it is OK to leave the
  // device_info_data.friendly_name as nullopt indicating the name not read.
  CollectBluetoothLowEnergyDeviceFriendlyName(device_info_handle,
                                              &device_info_data, result, error);
  if (!CollectBluetoothLowEnergyDeviceAddress(
          device_info_handle, &device_info_data, result, error)) {
    return false;
  }
  if (!CollectBluetoothLowEnergyDeviceStatus(
          device_info_handle, &device_info_data, result, error)) {
    return false;
  }
  (*device_info) = std::move(result);
  return true;
}

enum DeviceInfoResult { kOk, kError, kNoMoreDevices };

// For |device_interface_guid| see the Note of below
// EnumerateKnownBLEOrBLEGattServiceDevices interface.
DeviceInfoResult EnumerateSingleBluetoothLowEnergyDevice(
    GUID device_interface_guid,
    const ScopedDeviceInfoSetHandle& device_info_handle,
    DWORD device_index,
    std::unique_ptr<device::win::BluetoothLowEnergyDeviceInfo>* device_info,
    std::string* error) {
  GUID BluetoothInterfaceGUID = device_interface_guid;
  SP_DEVICE_INTERFACE_DATA device_interface_data = {0};
  device_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
  BOOL success = ::SetupDiEnumDeviceInterfaces(device_info_handle.Get(),
                                               NULL,
                                               &BluetoothInterfaceGUID,
                                               device_index,
                                               &device_interface_data);
  if (!success) {
    HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
    if (hr == HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS)) {
      return kNoMoreDevices;
    }
    *error = FormatBluetoothError(kDeviceInfoError, hr);
    return kError;
  }

  if (!CollectBluetoothLowEnergyDeviceInfo(
          device_info_handle, &device_interface_data, device_info, error)) {
    return kError;
  }

  return kOk;
}

// Opens a Device Info Set that can be used to enumerate Bluetooth LE devices
// present on the machine. For |device_interface_guid| see the Note of below
// EnumerateKnownBLEOrBLEGattServiceDevices interface.
HRESULT OpenBluetoothLowEnergyDevices(GUID device_interface_guid,
                                      ScopedDeviceInfoSetHandle* handle) {
  GUID BluetoothClassGUID = device_interface_guid;
  ScopedDeviceInfoSetHandle result(SetupDiGetClassDevs(
      &BluetoothClassGUID, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE));
  if (!result.IsValid()) {
    return HRESULT_FROM_WIN32(::GetLastError());
  }

  (*handle) = std::move(result);
  return S_OK;
}

// Enumerate known Bluetooth low energy devices or Bluetooth low energy GATT
// service devices according to |device_interface_guid|.
// Note: |device_interface_guid| = GUID_BLUETOOTHLE_DEVICE_INTERFACE corresponds
// Bluetooth low energy devices. |device_interface_guid| =
// GUID_BLUETOOTH_GATT_SERVICE_DEVICE_INTERFACE corresponds Bluetooth low energy
// Gatt service devices.
bool EnumerateKnownBLEOrBLEGattServiceDevices(
    GUID guid,
    std::vector<std::unique_ptr<BluetoothLowEnergyDeviceInfo>>* devices,
    std::string* error) {
  ScopedDeviceInfoSetHandle info_set_handle;
  HRESULT hr = OpenBluetoothLowEnergyDevices(guid, &info_set_handle);
  if (FAILED(hr)) {
    *error = FormatBluetoothError(kDeviceEnumError, hr);
    return false;
  }

  for (DWORD i = 0;; ++i) {
    std::unique_ptr<BluetoothLowEnergyDeviceInfo> device_info;
    DeviceInfoResult result = EnumerateSingleBluetoothLowEnergyDevice(
        guid, info_set_handle, i, &device_info, error);
    switch (result) {
      case kNoMoreDevices:
        return true;
      case kError:
        return false;
      case kOk:
        devices->push_back(std::move(device_info));
    }
  }
}

}  // namespace

namespace device {
namespace win {

// static
std::unique_ptr<DeviceRegistryPropertyValue>
DeviceRegistryPropertyValue::Create(DWORD property_type,
                                    std::unique_ptr<uint8_t[]> value,
                                    size_t value_size) {
  switch (property_type) {
    case REG_SZ: {
      // Ensure string is zero terminated.
      size_t character_size = value_size / sizeof(WCHAR);
      CHECK_EQ(character_size * sizeof(WCHAR), value_size);
      CHECK_GE(character_size, 1u);
      WCHAR* value_string = reinterpret_cast<WCHAR*>(value.get());
      value_string[character_size - 1] = 0;
      break;
    }
    case REG_DWORD: {
      CHECK_EQ(value_size, sizeof(DWORD));
      break;
    }
  }
  return base::WrapUnique(
      new DeviceRegistryPropertyValue(property_type, std::move(value)));
}

DeviceRegistryPropertyValue::DeviceRegistryPropertyValue(
    DWORD property_type,
    std::unique_ptr<uint8_t[]> value)
    : property_type_(property_type), value_(std::move(value)) {}

DeviceRegistryPropertyValue::~DeviceRegistryPropertyValue() {
}

std::string DeviceRegistryPropertyValue::AsString() const {
  CHECK_EQ(property_type_, static_cast<DWORD>(REG_SZ));
  WCHAR* value_string = reinterpret_cast<WCHAR*>(value_.get());
  return base::SysWideToUTF8(value_string);
}

DWORD DeviceRegistryPropertyValue::AsDWORD() const {
  CHECK_EQ(property_type_, static_cast<DWORD>(REG_DWORD));
  DWORD* value = reinterpret_cast<DWORD*>(value_.get());
  return *value;
}

DevicePropertyValue::DevicePropertyValue(DEVPROPTYPE property_type,
                                         std::unique_ptr<uint8_t[]> value,
                                         size_t value_size)
    : property_type_(property_type),
      value_(std::move(value)),
      value_size_(value_size) {}

DevicePropertyValue::~DevicePropertyValue() {
}

uint32_t DevicePropertyValue::AsUint32() const {
  CHECK_EQ(property_type_, static_cast<DEVPROPTYPE>(DEVPROP_TYPE_UINT32));
  CHECK_EQ(value_size_, sizeof(uint32_t));
  return *reinterpret_cast<uint32_t*>(value_.get());
}

BluetoothLowEnergyServiceInfo::BluetoothLowEnergyServiceInfo() {
}

BluetoothLowEnergyServiceInfo::~BluetoothLowEnergyServiceInfo() {
}

BluetoothLowEnergyDeviceInfo::BluetoothLowEnergyDeviceInfo()
    : visible(false), authenticated(false), connected(false) {
  address.ullLong = BLUETOOTH_NULL_ADDRESS;
}

BluetoothLowEnergyDeviceInfo::~BluetoothLowEnergyDeviceInfo() {
}

bool ExtractBluetoothAddressFromDeviceInstanceIdForTesting(
    const std::string& instance_id,
    BLUETOOTH_ADDRESS* btha,
    std::string* error) {
  return ExtractBluetoothAddressFromDeviceInstanceId(instance_id, btha, error);
}

BluetoothLowEnergyWrapper::BluetoothLowEnergyWrapper() {}
BluetoothLowEnergyWrapper::~BluetoothLowEnergyWrapper() {}

bool BluetoothLowEnergyWrapper::IsBluetoothLowEnergySupported() {
  return base::win::GetVersion() >= base::win::VERSION_WIN8;
}

bool BluetoothLowEnergyWrapper::EnumerateKnownBluetoothLowEnergyDevices(
    std::vector<std::unique_ptr<BluetoothLowEnergyDeviceInfo>>* devices,
    std::string* error) {
  if (!IsBluetoothLowEnergySupported()) {
    *error = kPlatformNotSupported;
    return false;
  }

  return EnumerateKnownBLEOrBLEGattServiceDevices(
      GUID_BLUETOOTHLE_DEVICE_INTERFACE, devices, error);
}

bool BluetoothLowEnergyWrapper::
    EnumerateKnownBluetoothLowEnergyGattServiceDevices(
        std::vector<std::unique_ptr<BluetoothLowEnergyDeviceInfo>>* devices,
        std::string* error) {
  if (!IsBluetoothLowEnergySupported()) {
    *error = kPlatformNotSupported;
    return false;
  }

  return EnumerateKnownBLEOrBLEGattServiceDevices(
      GUID_BLUETOOTH_GATT_SERVICE_DEVICE_INTERFACE, devices, error);
}

bool BluetoothLowEnergyWrapper::EnumerateKnownBluetoothLowEnergyServices(
    const base::FilePath& device_path,
    std::vector<std::unique_ptr<BluetoothLowEnergyServiceInfo>>* services,
    std::string* error) {
  if (!IsBluetoothLowEnergySupported()) {
    *error = kPlatformNotSupported;
    return false;
  }

  return CollectBluetoothLowEnergyDeviceServices(device_path, services, error);
}

HRESULT BluetoothLowEnergyWrapper::ReadCharacteristicsOfAService(
    base::FilePath& service_path,
    const PBTH_LE_GATT_SERVICE service,
    std::unique_ptr<BTH_LE_GATT_CHARACTERISTIC>* out_included_characteristics,
    USHORT* out_counts) {
  base::File file(service_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
  if (!file.IsValid())
    return HRESULT_FROM_WIN32(ERROR_OPEN_FAILED);

  USHORT allocated_length = 0;
  HRESULT hr = BluetoothGATTGetCharacteristics(file.GetPlatformFile(), service,
                                               0, NULL, &allocated_length,
                                               BLUETOOTH_GATT_FLAG_NONE);
  if (hr != HRESULT_FROM_WIN32(ERROR_MORE_DATA))
    return hr;

  out_included_characteristics->reset(
      new BTH_LE_GATT_CHARACTERISTIC[allocated_length]);
  hr = BluetoothGATTGetCharacteristics(file.GetPlatformFile(), service,
                                       allocated_length,
                                       out_included_characteristics->get(),
                                       out_counts, BLUETOOTH_GATT_FLAG_NONE);
  if (SUCCEEDED(hr) && allocated_length != *out_counts) {
    LOG(ERROR) << "Retrieved charactersitics is not equal to expected"
               << " allocated_length " << allocated_length << " got "
               << *out_counts;
    hr = HRESULT_FROM_WIN32(ERROR_INVALID_USER_BUFFER);
  }

  if (FAILED(hr)) {
    out_included_characteristics->reset(nullptr);
    *out_counts = 0;
  }
  return hr;
}

HRESULT BluetoothLowEnergyWrapper::ReadDescriptorsOfACharacteristic(
    base::FilePath& service_path,
    const PBTH_LE_GATT_CHARACTERISTIC characteristic,
    std::unique_ptr<BTH_LE_GATT_DESCRIPTOR>* out_included_descriptors,
    USHORT* out_counts) {
  base::File file(service_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
  if (!file.IsValid())
    return HRESULT_FROM_WIN32(ERROR_OPEN_FAILED);

  USHORT allocated_length = 0;
  HRESULT hr = BluetoothGATTGetDescriptors(
      file.GetPlatformFile(), characteristic, 0, NULL, &allocated_length,
      BLUETOOTH_GATT_FLAG_NONE);
  if (hr != HRESULT_FROM_WIN32(ERROR_MORE_DATA))
    return hr;

  out_included_descriptors->reset(new BTH_LE_GATT_DESCRIPTOR[allocated_length]);
  hr = BluetoothGATTGetDescriptors(
      file.GetPlatformFile(), characteristic, allocated_length,
      out_included_descriptors->get(), out_counts, BLUETOOTH_GATT_FLAG_NONE);
  if (SUCCEEDED(hr) && allocated_length != *out_counts) {
    LOG(ERROR) << "Retrieved descriptors is not equal to expected"
               << " allocated_length " << allocated_length << " got "
               << *out_counts;
    hr = HRESULT_FROM_WIN32(ERROR_INVALID_USER_BUFFER);
  }

  if (FAILED(hr)) {
    out_included_descriptors->reset(nullptr);
    *out_counts = 0;
  }
  return hr;
}

HRESULT BluetoothLowEnergyWrapper::ReadCharacteristicValue(
    base::FilePath& service_path,
    const PBTH_LE_GATT_CHARACTERISTIC characteristic,
    std::unique_ptr<BTH_LE_GATT_CHARACTERISTIC_VALUE>* out_value) {
  base::File file(service_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
  if (!file.IsValid())
    return HRESULT_FROM_WIN32(ERROR_OPEN_FAILED);

  USHORT allocated_length = 0;
  HRESULT hr = BluetoothGATTGetCharacteristicValue(
      file.GetPlatformFile(), characteristic, 0, NULL, &allocated_length,
      BLUETOOTH_GATT_FLAG_NONE);
  if (hr != HRESULT_FROM_WIN32(ERROR_MORE_DATA))
    return hr;

  out_value->reset(
      (PBTH_LE_GATT_CHARACTERISTIC_VALUE)(new UCHAR[allocated_length]));
  USHORT out_length = 0;
  hr = BluetoothGATTGetCharacteristicValue(
      file.GetPlatformFile(), characteristic, (ULONG)allocated_length,
      out_value->get(), &out_length, BLUETOOTH_GATT_FLAG_NONE);
  if (SUCCEEDED(hr) && allocated_length != out_length) {
    LOG(ERROR) << "Retrieved characteristic value size is not equal to expected"
               << " allocated_length " << allocated_length << " got "
               << out_length;
    hr = HRESULT_FROM_WIN32(ERROR_INVALID_USER_BUFFER);
  }

  if (FAILED(hr)) {
    out_value->reset(nullptr);
  }
  return hr;
}

HRESULT BluetoothLowEnergyWrapper::WriteCharacteristicValue(
    base::FilePath& service_path,
    const PBTH_LE_GATT_CHARACTERISTIC characteristic,
    PBTH_LE_GATT_CHARACTERISTIC_VALUE new_value) {
  base::File file(service_path, base::File::FLAG_OPEN | base::File::FLAG_READ |
                                    base::File::FLAG_WRITE);
  if (!file.IsValid())
    return HRESULT_FROM_WIN32(ERROR_OPEN_FAILED);

  ULONG flag = BLUETOOTH_GATT_FLAG_NONE;
  if (!characteristic->IsWritable) {
    DCHECK(characteristic->IsWritableWithoutResponse);
    flag |= BLUETOOTH_GATT_FLAG_WRITE_WITHOUT_RESPONSE;
  }

  return BluetoothGATTSetCharacteristicValue(
      file.GetPlatformFile(), characteristic, new_value, NULL, flag);
}

HRESULT BluetoothLowEnergyWrapper::RegisterGattEvents(
    base::FilePath& service_path,
    BTH_LE_GATT_EVENT_TYPE event_type,
    PVOID event_parameter,
    PFNBLUETOOTH_GATT_EVENT_CALLBACK_CORRECTED callback,
    PVOID context,
    BLUETOOTH_GATT_EVENT_HANDLE* out_handle) {
  base::File file(service_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
  if (!file.IsValid())
    return HRESULT_FROM_WIN32(ERROR_OPEN_FAILED);
  // Cast to the official callback type for compatibility with the Windows
  // 10.0.10586 definition, even though it is incorrect. This cast can be
  // removed when we mandate building Chromium with the 10.0.14393 SDK or
  // higher.
  return BluetoothGATTRegisterEvent(
      file.GetPlatformFile(), event_type, event_parameter,
      reinterpret_cast<PFNBLUETOOTH_GATT_EVENT_CALLBACK>(callback), context,
      out_handle, BLUETOOTH_GATT_FLAG_NONE);
}

HRESULT BluetoothLowEnergyWrapper::UnregisterGattEvent(
    BLUETOOTH_GATT_EVENT_HANDLE event_handle) {
  return BluetoothGATTUnregisterEvent(event_handle, BLUETOOTH_GATT_FLAG_NONE);
}

HRESULT BluetoothLowEnergyWrapper::WriteDescriptorValue(
    base::FilePath& service_path,
    const PBTH_LE_GATT_DESCRIPTOR descriptor,
    PBTH_LE_GATT_DESCRIPTOR_VALUE new_value) {
  base::File file(service_path, base::File::FLAG_OPEN | base::File::FLAG_READ |
                                    base::File::FLAG_WRITE);
  if (!file.IsValid())
    return HRESULT_FROM_WIN32(ERROR_OPEN_FAILED);
  return BluetoothGATTSetDescriptorValue(file.GetPlatformFile(), descriptor,
                                         new_value, BLUETOOTH_GATT_FLAG_NONE);
}

}  // namespace win
}  // namespace device
