// Copyright 2013 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 "components/wifi/wifi_service.h"

#include <windows.h>  // Must be in front of other Windows header files.

#include <iphlpapi.h>
#include <objbase.h>
#include <stddef.h>
#include <stdint.h>
#include <wlanapi.h>

#include <memory>
#include <set>
#include <utility>

#include "base/base_paths_win.h"
#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/path_service.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string16.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "base/win/registry.h"
#include "components/onc/onc_constants.h"
#include "components/wifi/network_properties.h"
#include "third_party/libxml/chromium/libxml_utils.h"

namespace {
const wchar_t kNwCategoryWizardRegKey[] =
    L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Network\\"
    L"NwCategoryWizard";
const wchar_t kNwCategoryWizardRegValue[] = L"Show";
const wchar_t kNwCategoryWizardSavedRegValue[] = L"ShowSaved";
const wchar_t kNwCategoryWizardDeleteRegValue[] = L"ShowDelete";
const wchar_t kWlanApiDll[] = L"wlanapi.dll";

// Created Profile Dictionary keys
const char kProfileXmlKey[] = "xml";
const char kProfileSharedKey[] = "shared";

// WlanApi function names
const char kWlanConnect[] = "WlanConnect";
const char kWlanCloseHandle[] = "WlanCloseHandle";
const char kWlanDeleteProfile[] = "WlanDeleteProfile";
const char kWlanDisconnect[] = "WlanDisconnect";
const char kWlanEnumInterfaces[] = "WlanEnumInterfaces";
const char kWlanFreeMemory[] = "WlanFreeMemory";
const char kWlanGetAvailableNetworkList[] = "WlanGetAvailableNetworkList";
const char kWlanGetNetworkBssList[] = "WlanGetNetworkBssList";
const char kWlanGetProfile[] = "WlanGetProfile";
const char kWlanOpenHandle[] = "WlanOpenHandle";
const char kWlanQueryInterface[] = "WlanQueryInterface";
const char kWlanRegisterNotification[] = "WlanRegisterNotification";
const char kWlanSaveTemporaryProfile[] = "WlanSaveTemporaryProfile";
const char kWlanScan[] = "WlanScan";
const char kWlanSetProfile[] = "WlanSetProfile";

// WlanApi function definitions
typedef DWORD(WINAPI* WlanConnectFunction)(
    HANDLE hClientHandle,
    CONST GUID* pInterfaceGuid,
    CONST PWLAN_CONNECTION_PARAMETERS pConnectionParameters,
    PVOID pReserved);

typedef DWORD (WINAPI* WlanCloseHandleFunction)(
    HANDLE hClientHandle,
    PVOID pReserved);

typedef DWORD(WINAPI* WlanDeleteProfileFunction)(HANDLE hClientHandle,
                                                 const GUID* pInterfaceGuid,
                                                 LPCWSTR strProfileName,
                                                 PVOID pReserved);

typedef DWORD(WINAPI* WlanDisconnectFunction)(HANDLE hClientHandle,
                                              CONST GUID* pInterfaceGuid,
                                              PVOID pReserved);

typedef DWORD(WINAPI* WlanEnumInterfacesFunction)(
    HANDLE hClientHandle,
    PVOID pReserved,
    PWLAN_INTERFACE_INFO_LIST* ppInterfaceList);

typedef VOID (WINAPI* WlanFreeMemoryFunction)(
    _In_ PVOID pMemory);

typedef DWORD(WINAPI* WlanGetAvailableNetworkListFunction)(
    HANDLE hClientHandle,
    CONST GUID* pInterfaceGuid,
    DWORD dwFlags,
    PVOID pReserved,
    PWLAN_AVAILABLE_NETWORK_LIST* ppAvailableNetworkList);

typedef DWORD (WINAPI* WlanGetNetworkBssListFunction)(
    HANDLE hClientHandle,
    const GUID* pInterfaceGuid,
    const  PDOT11_SSID pDot11Ssid,
    DOT11_BSS_TYPE dot11BssType,
    BOOL bSecurityEnabled,
    PVOID pReserved,
    PWLAN_BSS_LIST* ppWlanBssList);

typedef DWORD(WINAPI* WlanGetProfileFunction)(HANDLE hClientHandle,
                                              CONST GUID* pInterfaceGuid,
                                              LPCWSTR strProfileName,
                                              PVOID pReserved,
                                              LPWSTR* pstrProfileXml,
                                              DWORD* pdwFlags,
                                              DWORD* pdwGrantedAccess);

typedef DWORD (WINAPI* WlanOpenHandleFunction)(
    DWORD dwClientVersion,
    PVOID pReserved,
    PDWORD pdwNegotiatedVersion,
    PHANDLE phClientHandle);

typedef DWORD(WINAPI* WlanQueryInterfaceFunction)(
    HANDLE hClientHandle,
    const GUID* pInterfaceGuid,
    WLAN_INTF_OPCODE OpCode,
    PVOID pReserved,
    PDWORD pdwDataSize,
    PVOID* ppData,
    PWLAN_OPCODE_VALUE_TYPE pWlanOpcodeValueType);

typedef DWORD (WINAPI* WlanRegisterNotificationFunction)(
    HANDLE hClientHandle,
    DWORD dwNotifSource,
    BOOL bIgnoreDuplicate,
    WLAN_NOTIFICATION_CALLBACK funcCallback,
    PVOID pCallbackContext,
    PVOID pReserved,
    PDWORD pdwPrevNotifSource);

typedef DWORD (WINAPI* WlanSaveTemporaryProfileFunction)(
    HANDLE hClientHandle,
    CONST GUID* pInterfaceGuid,
    LPCWSTR strProfileName,
    LPCWSTR strAllUserProfileSecurity,
    DWORD dwFlags,
    BOOL bOverWrite,
    PVOID pReserved);

typedef DWORD(WINAPI* WlanScanFunction)(HANDLE hClientHandle,
                                        CONST GUID* pInterfaceGuid,
                                        CONST PDOT11_SSID pDot11Ssid,
                                        CONST PWLAN_RAW_DATA pIeData,
                                        PVOID pReserved);

typedef DWORD(WINAPI* WlanSetProfileFunction)(HANDLE hClientHandle,
                                              const GUID* pInterfaceGuid,
                                              DWORD dwFlags,
                                              LPCWSTR strProfileXml,
                                              LPCWSTR strAllUserProfileSecurity,
                                              BOOL bOverwrite,
                                              PVOID pReserved,
                                              DWORD* pdwReasonCode);

// Values for WLANProfile XML.
const char kAuthenticationOpen[] = "open";
const char kAuthenticationWepPsk[] = "WEP";
const char kAuthenticationWpaPsk[] = "WPAPSK";
const char kAuthenticationWpa2Psk[] = "WPA2PSK";
const char kEncryptionAES[] = "AES";
const char kEncryptionNone[] = "none";
const char kEncryptionTKIP[] = "TKIP";
const char kEncryptionWEP[] = "WEP";
const char kKeyTypeNetwork[] = "networkKey";
const char kKeyTypePassphrase[] = "passPhrase";

}  // namespace

namespace wifi {

// Implementation of WiFiService for Windows.
class WiFiServiceImpl : public WiFiService {
 public:
  WiFiServiceImpl();
  ~WiFiServiceImpl() override;

  // WiFiService interface implementation.
  void Initialize(
      scoped_refptr<base::SequencedTaskRunner> task_runner) override;

  void UnInitialize() override;

  void GetProperties(const std::string& network_guid,
                     base::DictionaryValue* properties,
                     std::string* error) override;

  void GetManagedProperties(const std::string& network_guid,
                            base::DictionaryValue* managed_properties,
                            std::string* error) override;

  void GetState(const std::string& network_guid,
                base::DictionaryValue* properties,
                std::string* error) override;

  void SetProperties(const std::string& network_guid,
                     std::unique_ptr<base::DictionaryValue> properties,
                     std::string* error) override;

  void CreateNetwork(bool shared,
                     std::unique_ptr<base::DictionaryValue> properties,
                     std::string* network_guid,
                     std::string* error) override;

  void GetVisibleNetworks(const std::string& network_type,
                          base::ListValue* network_list,
                          bool include_details) override;

  void RequestNetworkScan() override;

  void StartConnect(const std::string& network_guid,
                    std::string* error) override;

  void StartDisconnect(const std::string& network_guid,
                       std::string* error) override;

  void GetKeyFromSystem(const std::string& network_guid,
                        std::string* key_data,
                        std::string* error) override;

  void SetEventObservers(
      scoped_refptr<base::SingleThreadTaskRunner> task_runner,
      const NetworkGuidListCallback& networks_changed_observer,
      const NetworkGuidListCallback& network_list_changed_observer) override;

  void RequestConnectedNetworkUpdate() override {}

  void GetConnectedNetworkSSID(std::string* ssid, std::string* error) override;

 private:
  typedef int32_t EncryptionType;
  enum EncryptionTypeEnum {
    kEncryptionTypeAny = 0,
    kEncryptionTypeAES = 1,
    kEncryptionTypeTKIP = 2
  };

  // Static callback for Windows WLAN_NOTIFICATION. Calls OnWlanNotification
  // on WiFiServiceImpl passed back as |context|.
  static void __stdcall OnWlanNotificationCallback(
      PWLAN_NOTIFICATION_DATA wlan_notification_data,
      PVOID context);

  // Callback for Windows WLAN_NOTIFICATION. Called on random thread from
  // OnWlanNotificationCallback. Handles network connectivity and scan complete
  // notification and posts tasks to main thread.
  void OnWlanNotification(PWLAN_NOTIFICATION_DATA wlan_notification_data);

  // Handles NetworkScanComplete notification on main thread. Sends
  // |NetworkListChanged| event with new list of visible networks.
  void OnNetworkScanCompleteOnMainThread();

  // Wait up to |kMaxAttempts| with |kAttemptDelayMs| delay for connection
  // to network with |network_guid|. Reset DHCP and Notify that |NetworkChanged|
  // upon success.
  void WaitForNetworkConnect(const std::string& network_guid, int attempt);

  // Check |error_code| and if is not |ERROR_SUCCESS|, then store |error_name|
  // into |error|.
  bool CheckError(DWORD error_code,
                  const std::string& error_name,
                  std::string* error) const;

  // Return |iterator| to network identified by |network_guid| in |networks|
  // list.
  NetworkList::iterator FindNetwork(NetworkList& networks,
                                    const std::string& network_guid);

  // Save currently connected network profile so it can be re-connected later.
  DWORD SaveCurrentConnectedNetwork(const NetworkProperties& properties);

  // Sort networks, so connected/connecting is up front, then by type:
  // Ethernet, WiFi, Cellular, VPN
  static void SortNetworks(NetworkList* networks);

  // Open a WLAN client handle, register for WLAN notifications.
  DWORD OpenClientHandle();

  // Reset DHCP on wireless network to work around an issue when Windows
  // takes forever to connect to the network, e.g. after Chromecast
  // device reset.
  DWORD ResetDHCP();

  // Find |adapter_index_map| by |interface_guid| for DHCP reset.
  DWORD FindAdapterIndexMapByGUID(const GUID& interface_guid,
                                  IP_ADAPTER_INDEX_MAP* adapter_index_map);

  // Avoid the network location wizard to pop up when network is connected.
  // Preserve current value in |saved_nw_category_wizard_|.
  DWORD DisableNwCategoryWizard();

  // Restore network location wizard to value saved by DisableNwCategoryWizard.
  DWORD RestoreNwCategoryWizard();

  // Ensure that |client_| handle is initialized.
  DWORD EnsureInitialized();

  // Close |client_| handle if it is open.
  DWORD CloseClientHandle();

  // Get |profile_name| from unique |network_guid|.
  base::string16 ProfileNameFromGUID(const std::string& network_guid) const {
    return base::UTF8ToUTF16(network_guid);
  }

  // Get |dot11_ssid| from unique |network_guid|.
  DOT11_SSID SSIDFromGUID(const std::string& network_guid) const;

  // Get unique |network_guid| string based on |dot11_ssid|.
  std::string GUIDFromSSID(const DOT11_SSID& dot11_ssid) const {
    return std::string(reinterpret_cast<const char*>(dot11_ssid.ucSSID),
                       dot11_ssid.uSSIDLength);
  }

  // Get network |ssid| string based on |wlan|.
  std::string SSIDFromWLAN(const WLAN_AVAILABLE_NETWORK& wlan) const {
    return GUIDFromSSID(wlan.dot11Ssid);
  }

  // Get unique |network_guid| string based on |wlan|.
  std::string GUIDFromWLAN(const WLAN_AVAILABLE_NETWORK& wlan) const {
    return SSIDFromWLAN(wlan);
  }

  // Deduce |onc::wifi| security from |alg|.
  std::string SecurityFromDot11AuthAlg(DOT11_AUTH_ALGORITHM alg) const;

  // Deduce |onc::connection_state| from |wlan_state|.
  std::string ConnectionStateFromInterfaceState(
      WLAN_INTERFACE_STATE wlan_state) const;

  // Convert |EncryptionType| into WPA(2) encryption type string.
  std::string WpaEncryptionFromEncryptionType(
      EncryptionType encryption_type) const;

  // Deduce WLANProfile |authEncryption| values from |onc::wifi| security.
  bool AuthEncryptionFromSecurity(const std::string& security,
                                  EncryptionType encryption_type,
                                  std::string* authentication,
                                  std::string* encryption,
                                  std::string* key_type) const;

  // Populate |properties| based on |wlan|.
  void NetworkPropertiesFromAvailableNetwork(const WLAN_AVAILABLE_NETWORK& wlan,
                                             NetworkProperties* properties);

  // Update |properties| based on bss info from |wlan_bss_list|. If |bssid| in
  // |properties| is not empty, then it is not changed and |frequency| is set
  // based on that bssid.
  void UpdateNetworkPropertiesFromBssList(const std::string& network_guid,
                                          const WLAN_BSS_LIST& wlan_bss_list,
                                          NetworkProperties* properties);

  // Get the list of visible wireless networks.
  DWORD GetVisibleNetworkList(NetworkList* network_list);

  // Get properties of the network currently used (connected or in transition)
  // by interface. Populate |current_properties| on success.
  DWORD GetCurrentProperties(NetworkProperties* current_properties);

  // Get the SSID of the network currently used (connected or in transition)
  // by interface. Populate |ssid| on success. This is a stripped down version
  // of GetCurrentProperties that doesn't use the BSS list;
  DWORD GetCurrentSSID(std::string* ssid);

  // Connect to network |network_guid| using previosly stored profile if exists,
  // or just network sid. If |frequency| is not |kFrequencyUnknown| then
  // connects only to BSS which uses that frequency and returns
  // |ERROR_NOT_FOUND| if such BSS cannot be found.
  DWORD Connect(const std::string& network_guid, Frequency frequency);

  // Disconnect from currently connected network if any.
  DWORD Disconnect();

  // Get desired connection freqency if it was set using |SetProperties|.
  // Default to |kFrequencyAny|.
  Frequency GetFrequencyToConnect(const std::string& network_guid) const;

  // Get DOT11_BSSID_LIST of desired BSSIDs to connect to |ssid| network on
  // given |frequency|.
  DWORD GetDesiredBssList(DOT11_SSID& ssid,
                          Frequency frequency,
                          std::unique_ptr<DOT11_BSSID_LIST>* desired_list);

  // Normalizes |frequency_in_mhz| into one of |Frequency| values.
  Frequency GetNormalizedFrequency(int frequency_in_mhz) const;

  // Create |profile_xml| based on |network_properties|. If |encryption_type|
  // is |kEncryptionTypeAny| applies the type most suitable for parameters in
  // |network_properties|.
  bool CreateProfile(const NetworkProperties& network_properties,
                     EncryptionType encryption_type,
                     std::string* profile_xml);

  // Save temporary wireless profile for |network_guid|.
  DWORD SaveTempProfile(const std::string& network_guid);

  // Get previously stored |profile_xml| for |network_guid|.
  // If |get_plaintext_key| is true, and process has sufficient privileges, then
  // <sharedKey> data in |profile_xml| will be unprotected.
  DWORD GetProfile(const std::string& network_guid,
                   bool get_plaintext_key,
                   std::string* profile_xml);

  // Set |profile_xml| to current user or all users depending on |shared| flag.
  // If |overwrite| is false, then returns an error if profile exists.
  DWORD SetProfile(bool shared, const std::string& profile_xml, bool overwrite);

  // Return true if there is previously stored profile xml for |network_guid|.
  bool HaveProfile(const std::string& network_guid);

  // Delete profile that was created, but failed to connect.
  DWORD DeleteCreatedProfile(const std::string& network_guid);

  // Notify |network_list_changed_observer_| that list of visible networks has
  // changed to |networks|.
  void NotifyNetworkListChanged(const NetworkList& networks);

  // Notify |networks_changed_observer_| that network |network_guid| status has
  // changed.
  void NotifyNetworkChanged(const std::string& network_guid);

  // Load WlanApi.dll from SystemDirectory and get Api function pointers.
  DWORD LoadWlanLibrary();
  // Instance of WlanApi.dll.
  HINSTANCE wlan_api_library_;
  // WlanApi function pointers
  WlanConnectFunction WlanConnect_function_;
  WlanCloseHandleFunction WlanCloseHandle_function_;
  WlanDeleteProfileFunction WlanDeleteProfile_function_;
  WlanDisconnectFunction WlanDisconnect_function_;
  WlanEnumInterfacesFunction WlanEnumInterfaces_function_;
  WlanFreeMemoryFunction WlanFreeMemory_function_;
  WlanGetAvailableNetworkListFunction WlanGetAvailableNetworkList_function_;
  // WlanGetNetworkBssList function may not be avaiable on Windows XP.
  WlanGetNetworkBssListFunction WlanGetNetworkBssList_function_;
  WlanGetProfileFunction WlanGetProfile_function_;
  WlanOpenHandleFunction WlanOpenHandle_function_;
  WlanQueryInterfaceFunction WlanQueryInterface_function_;
  WlanRegisterNotificationFunction WlanRegisterNotification_function_;
  WlanScanFunction WlanScan_function_;
  WlanSetProfileFunction WlanSetProfile_function_;
  // WlanSaveTemporaryProfile function may not be avaiable on Windows XP.
  WlanSaveTemporaryProfileFunction WlanSaveTemporaryProfile_function_;

  // WLAN service handle.
  HANDLE client_;
  // GUID of the currently connected interface, if any, otherwise the GUID of
  // one of the WLAN interfaces.
  GUID interface_guid_;
  // Temporary storage of network properties indexed by |network_guid|. Persist
  // only in memory.
  base::DictionaryValue connect_properties_;
  // Preserved WLAN profile xml.
  std::map<std::string, std::string> saved_profiles_xml_;
  // Created WLAN Profiles, indexed by |network_guid|. Contains xml with TKIP
  // encryption type saved by |CreateNetwork| if applicable. Profile has to be
  // deleted if connection fails. Implicitly created profiles have to be deleted
  // if connection succeeds. Persist only in memory.
  base::DictionaryValue created_profiles_;
  // Observer to get notified when network(s) have changed (e.g. connect).
  NetworkGuidListCallback networks_changed_observer_;
  // Observer to get notified when network list has changed (scan complete).
  NetworkGuidListCallback network_list_changed_observer_;
  // Saved value of network location wizard show value.
  std::unique_ptr<DWORD> saved_nw_category_wizard_;
  // Task runner to post events on UI thread.
  scoped_refptr<base::SingleThreadTaskRunner> event_task_runner_;
  // Task runner for worker tasks.
  scoped_refptr<base::SequencedTaskRunner> task_runner_;
  // If |false|, then |networks_changed_observer_| is not notified.
  bool enable_notify_network_changed_;
  // Number of attempts to check that network has connected successfully.
  static const int kMaxAttempts = 100;
  // Delay between attempts to check that network has connected successfully.
  static const int kAttemptDelayMs = 100;
  DISALLOW_COPY_AND_ASSIGN(WiFiServiceImpl);
};

WiFiServiceImpl::WiFiServiceImpl()
    : wlan_api_library_(nullptr),
      WlanConnect_function_(nullptr),
      WlanCloseHandle_function_(nullptr),
      WlanDeleteProfile_function_(nullptr),
      WlanDisconnect_function_(nullptr),
      WlanEnumInterfaces_function_(nullptr),
      WlanFreeMemory_function_(nullptr),
      WlanGetAvailableNetworkList_function_(nullptr),
      WlanGetNetworkBssList_function_(nullptr),
      WlanGetProfile_function_(nullptr),
      WlanOpenHandle_function_(nullptr),
      WlanRegisterNotification_function_(nullptr),
      WlanScan_function_(nullptr),
      WlanSetProfile_function_(nullptr),
      WlanSaveTemporaryProfile_function_(nullptr),
      client_(nullptr),
      enable_notify_network_changed_(true) {}

WiFiServiceImpl::~WiFiServiceImpl() { UnInitialize(); }

void WiFiServiceImpl::Initialize(
    scoped_refptr<base::SequencedTaskRunner> task_runner) {
  DCHECK(!client_);
  task_runner_.swap(task_runner);
  // Restore NwCategoryWizard in case if we crashed during connect.
  RestoreNwCategoryWizard();
  OpenClientHandle();
}

void WiFiServiceImpl::UnInitialize() {
  CloseClientHandle();
}

void WiFiServiceImpl::GetProperties(const std::string& network_guid,
                                    base::DictionaryValue* properties,
                                    std::string* error) {
  DWORD error_code = EnsureInitialized();
  if (CheckError(error_code, kErrorWiFiService, error))
    return;

  NetworkProperties connected_properties;
  error_code = GetCurrentProperties(&connected_properties);
  if (error_code == ERROR_SUCCESS &&
      connected_properties.guid == network_guid) {
    properties->Swap(connected_properties.ToValue(false).get());
    return;
  }

  NetworkList network_list;
  error_code = GetVisibleNetworkList(&network_list);
  if (error_code == ERROR_SUCCESS) {
    NetworkList::const_iterator it = FindNetwork(network_list, network_guid);
    if (it != network_list.end()) {
      DVLOG(1) << "Get Properties: " << network_guid << ":"
                  << it->connection_state;
      properties->Swap(it->ToValue(false).get());
      return;
    }
    error_code = ERROR_NOT_FOUND;
  }

  CheckError(error_code, kErrorWiFiService, error);
}

void WiFiServiceImpl::GetManagedProperties(
    const std::string& network_guid,
    base::DictionaryValue* managed_properties,
    std::string* error) {
  CheckError(ERROR_CALL_NOT_IMPLEMENTED, kErrorWiFiService, error);
}

void WiFiServiceImpl::GetState(const std::string& network_guid,
                               base::DictionaryValue* properties,
                               std::string* error) {
  CheckError(ERROR_CALL_NOT_IMPLEMENTED, kErrorWiFiService, error);
}

void WiFiServiceImpl::SetProperties(
    const std::string& network_guid,
    std::unique_ptr<base::DictionaryValue> properties,
    std::string* error) {
  // Temporary preserve WiFi properties (desired frequency, wifi password) to
  // use in StartConnect.
  DCHECK(properties);
  if (!properties->HasKey(onc::network_type::kWiFi)) {
    DVLOG(0) << "Missing WiFi properties:" << *properties;
    *error = kErrorWiFiService;
    return;
  }

  base::DictionaryValue* existing_properties;
  // If the network properties already exist, don't override previously set
  // properties, unless they are set in |properties|.
  if (connect_properties_.GetDictionaryWithoutPathExpansion(
          network_guid, &existing_properties)) {
    existing_properties->MergeDictionary(properties.get());
  } else {
    connect_properties_.SetWithoutPathExpansion(network_guid,
                                                std::move(properties));
  }
}

void WiFiServiceImpl::CreateNetwork(
    bool shared,
    std::unique_ptr<base::DictionaryValue> properties,
    std::string* network_guid,
    std::string* error) {
  DWORD error_code = EnsureInitialized();
  if (CheckError(error_code, kErrorWiFiService, error))
    return;

  NetworkProperties network_properties;
  if (!network_properties.UpdateFromValue(*properties)) {
    CheckError(ERROR_INVALID_DATA, kErrorWiFiService, error);
    return;
  }

  network_properties.guid = network_properties.ssid;
  std::string profile_xml;
  if (!CreateProfile(network_properties, kEncryptionTypeAny, &profile_xml)) {
    CheckError(ERROR_INVALID_DATA, kErrorWiFiService, error);
    return;
  }

  error_code = SetProfile(shared, profile_xml, false);
  if (CheckError(error_code, kErrorWiFiService, error)) {
    DVLOG(0) << profile_xml;
    return;
  }

  // WAP and WAP2 networks could use either AES or TKIP encryption type.
  // Preserve alternative profile to use in case if connection with default
  // encryption type fails.
  std::string tkip_profile_xml;
  if (!CreateProfile(network_properties,
                     kEncryptionTypeTKIP,
                     &tkip_profile_xml)) {
    CheckError(ERROR_INVALID_DATA, kErrorWiFiService, error);
    return;
  }

  if (tkip_profile_xml != profile_xml) {
    std::unique_ptr<base::DictionaryValue> tkip_profile(
        new base::DictionaryValue());
    tkip_profile->SetString(kProfileXmlKey, tkip_profile_xml);
    tkip_profile->SetBoolean(kProfileSharedKey, shared);
    created_profiles_.SetWithoutPathExpansion(network_properties.guid,
                                              std::move(tkip_profile));
  }

  *network_guid = network_properties.guid;
}

void WiFiServiceImpl::GetVisibleNetworks(const std::string& network_type,
                                         base::ListValue* network_list,
                                         bool include_details) {
  if (!network_type.empty() &&
      network_type != onc::network_type::kAllTypes &&
      network_type != onc::network_type::kWiFi) {
    return;
  }

  DWORD error = EnsureInitialized();
  if (error == ERROR_SUCCESS) {
    NetworkList networks;
    error = GetVisibleNetworkList(&networks);
    if (error == ERROR_SUCCESS && !networks.empty()) {
      SortNetworks(&networks);
      for (NetworkList::const_iterator it = networks.begin();
           it != networks.end();
           ++it) {
        std::unique_ptr<base::DictionaryValue> network(
            it->ToValue(!include_details));
        network_list->Append(std::move(network));
      }
    }
  }
}

void WiFiServiceImpl::RequestNetworkScan() {
  DWORD error = EnsureInitialized();
  if (error == ERROR_SUCCESS) {
    WlanScan_function_(client_, &interface_guid_, nullptr, nullptr, nullptr);
  }
}

void WiFiServiceImpl::StartConnect(const std::string& network_guid,
                                   std::string* error) {
  DVLOG(1) << "Start Connect: " << network_guid;
  DWORD error_code = EnsureInitialized();
  if (CheckError(error_code, kErrorWiFiService, error))
    return;

  // Check, if the network is already connected on desired frequency.
  Frequency frequency = GetFrequencyToConnect(network_guid);
  NetworkProperties properties;
  GetCurrentProperties(&properties);
  bool already_connected =
      network_guid == properties.guid &&
      properties.connection_state == onc::connection_state::kConnected &&
      (frequency == kFrequencyAny || frequency == properties.frequency);

  // Connect only if network |network_guid| is not connected already.
  if (!already_connected) {
    SaveCurrentConnectedNetwork(properties);
    error_code = Connect(network_guid, frequency);
  }
  if (error_code == ERROR_SUCCESS) {
    // Notify that previously connected network has changed.
    NotifyNetworkChanged(properties.guid);
    // Start waiting for network connection state change.
    if (!networks_changed_observer_.is_null()) {
      DisableNwCategoryWizard();
      // Disable automatic network change notifications as they get fired
      // when network is just connected, but not yet accessible (doesn't
      // have valid IP address).
      enable_notify_network_changed_ = false;
      WaitForNetworkConnect(network_guid, 0);
      return;
    }
  } else if (error_code == ERROR_ACCESS_DENIED) {
    CheckError(error_code, kErrorNotConfigured, error);
  } else {
    CheckError(error_code, kErrorWiFiService, error);
  }
}

void WiFiServiceImpl::StartDisconnect(const std::string& network_guid,
                                      std::string* error) {
  DVLOG(1) << "Start Disconnect: " << network_guid;
  DWORD error_code = EnsureInitialized();
  if (CheckError(error_code, kErrorWiFiService, error))
    return;

  // Check, if the network is currently connected.
  NetworkProperties properties;
  GetCurrentProperties(&properties);
  if (network_guid == properties.guid) {
    if (properties.connection_state == onc::connection_state::kConnected)
      SaveCurrentConnectedNetwork(properties);
    error_code = Disconnect();
    if (error_code == ERROR_SUCCESS) {
      NotifyNetworkChanged(network_guid);
      return;
    }
  }
  CheckError(error_code, kErrorWiFiService, error);
}

void WiFiServiceImpl::GetKeyFromSystem(const std::string& network_guid,
                                       std::string* key_data,
                                       std::string* error) {
  DWORD error_code = EnsureInitialized();
  if (CheckError(error_code, kErrorWiFiService, error))
    return;

  std::string profile_xml;
  error_code = GetProfile(network_guid, true, &profile_xml);
  if (CheckError(error_code, kErrorWiFiService, error))
    return;

  const char kSharedKeyElement[] = "sharedKey";
  const char kProtectedElement[] = "protected";
  const char kKeyMaterialElement[] = "keyMaterial";

  // Quick check to verify presence of <sharedKey> element.
  if (profile_xml.find(kSharedKeyElement) == std::string::npos) {
    *error = kErrorWiFiService;
    return;
  }

  XmlReader reader;
  if (reader.Load(profile_xml)) {
    while (reader.Read()) {
      reader.SkipToElement();
      if (reader.NodeName() == kSharedKeyElement) {
        while (reader.Read()) {
          reader.SkipToElement();
          if (reader.NodeName() == kKeyMaterialElement) {
            reader.ReadElementContent(key_data);
          } else if (reader.NodeName() == kProtectedElement) {
            std::string protected_data;
            reader.ReadElementContent(&protected_data);
            // Without UAC privilege escalation call to |GetProfile| with
            // |WLAN_PROFILE_GET_PLAINTEXT_KEY| flag returns success, but has
            // protected keyMaterial. Report an error in this case.
            if (protected_data != "false") {
              *error = kErrorWiFiService;
              break;
            }
          }
        }
        return;
      }
    }
  }

  // Did not find passphrase in the profile.
  *error = kErrorWiFiService;
}

void WiFiServiceImpl::SetEventObservers(
    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
    const NetworkGuidListCallback& networks_changed_observer,
    const NetworkGuidListCallback& network_list_changed_observer) {
  DWORD error_code = EnsureInitialized();
  if (error_code != ERROR_SUCCESS)
    return;
  event_task_runner_.swap(task_runner);
  if (!networks_changed_observer_.is_null() ||
      !network_list_changed_observer_.is_null()) {
    // Stop listening to WLAN notifications.
    WlanRegisterNotification_function_(client_, WLAN_NOTIFICATION_SOURCE_NONE,
                                       FALSE, OnWlanNotificationCallback, this,
                                       nullptr, nullptr);
  }
  networks_changed_observer_ = networks_changed_observer;
  network_list_changed_observer_ = network_list_changed_observer;
  if (!networks_changed_observer_.is_null() ||
      !network_list_changed_observer_.is_null()) {
    // Start listening to WLAN notifications.
    WlanRegisterNotification_function_(client_, WLAN_NOTIFICATION_SOURCE_ALL,
                                       FALSE, OnWlanNotificationCallback, this,
                                       nullptr, nullptr);
  }
}

void WiFiServiceImpl::GetConnectedNetworkSSID(std::string* ssid,
                                              std::string* error) {
  DWORD error_code = EnsureInitialized();
  if (CheckError(error_code, kErrorWiFiService, error))
    return;
  std::string current_ssid;
  error_code = GetCurrentSSID(&current_ssid);
  if (CheckError(error_code, kErrorWiFiService, error))
    return;
  *ssid = current_ssid;
}

void WiFiServiceImpl::OnWlanNotificationCallback(
    PWLAN_NOTIFICATION_DATA wlan_notification_data,
    PVOID context) {
  WiFiServiceImpl* service = reinterpret_cast<WiFiServiceImpl*>(context);
  service->OnWlanNotification(wlan_notification_data);
}

void WiFiServiceImpl::OnWlanNotification(
    PWLAN_NOTIFICATION_DATA wlan_notification_data) {
  if (!event_task_runner_)
    return;
  switch (wlan_notification_data->NotificationCode) {
    case wlan_notification_acm_disconnected:
    case wlan_notification_acm_connection_complete:
    case wlan_notification_acm_connection_attempt_fail: {
      PWLAN_CONNECTION_NOTIFICATION_DATA wlan_connection_data =
          reinterpret_cast<PWLAN_CONNECTION_NOTIFICATION_DATA>(
              wlan_notification_data->pData);
      event_task_runner_->PostTask(
          FROM_HERE,
          base::BindOnce(&WiFiServiceImpl::NotifyNetworkChanged,
                         base::Unretained(this),
                         GUIDFromSSID(wlan_connection_data->dot11Ssid)));
      break;
    }
    case wlan_notification_acm_scan_complete:
    case wlan_notification_acm_interface_removal:
      event_task_runner_->PostTask(
          FROM_HERE,
          base::BindOnce(&WiFiServiceImpl::OnNetworkScanCompleteOnMainThread,
                         base::Unretained(this)));
      break;
  }
}

void WiFiServiceImpl::OnNetworkScanCompleteOnMainThread() {
  NetworkList networks;
  // Get current list of visible networks and notify that network list has
  // changed.
  DWORD error = GetVisibleNetworkList(&networks);
  if (error != ERROR_SUCCESS)
    networks.clear();
  NotifyNetworkListChanged(networks);
}

void WiFiServiceImpl::WaitForNetworkConnect(const std::string& network_guid,
                                            int attempt) {
  // If network didn't get connected in |kMaxAttempts|, then try to connect
  // using different profile if it was created recently.
  if (attempt > kMaxAttempts) {
    LOG(ERROR) << kMaxAttempts << " attempts exceeded waiting for connect to "
               << network_guid;

    base::DictionaryValue* created_profile = nullptr;
    // Check, whether this connection is using newly created profile.
    if (created_profiles_.GetDictionaryWithoutPathExpansion(
        network_guid, &created_profile)) {
      std::string tkip_profile_xml;
      bool shared = false;
      // Check, if this connection there is alternative TKIP profile xml that
      // should be tried. If there is, then set it up and try to connect again.
      if (created_profile->GetString(kProfileXmlKey, &tkip_profile_xml) &&
          created_profile->GetBoolean(kProfileSharedKey, &shared)) {
        // Remove TKIP profile xml, so it will not be tried again.
        created_profile->Remove(kProfileXmlKey, nullptr);
        created_profile->Remove(kProfileSharedKey, nullptr);
        DWORD error_code = SetProfile(shared, tkip_profile_xml, true);
        if (error_code == ERROR_SUCCESS) {
          // Try to connect with new profile.
          error_code = Connect(network_guid,
                               GetFrequencyToConnect(network_guid));
          if (error_code == ERROR_SUCCESS) {
            // Start waiting again.
            WaitForNetworkConnect(network_guid, 0);
            return;
          } else {
            LOG(ERROR) << "Failed to set created profile for " << network_guid
                       << " error=" << error_code;
          }
        }
      } else {
        // Connection has failed, so delete bad created profile.
        DWORD error_code = DeleteCreatedProfile(network_guid);
        if (error_code != ERROR_SUCCESS) {
          LOG(ERROR) << "Failed to delete created profile for " << network_guid
                     << " error=" << error_code;
        }
      }
    }
    // Restore automatic network change notifications and stop waiting.
    enable_notify_network_changed_ = true;
    RestoreNwCategoryWizard();
    return;
  }
  NetworkProperties current_properties;
  DWORD error = GetCurrentProperties(&current_properties);
  if (network_guid == current_properties.guid &&
      current_properties.connection_state ==
          onc::connection_state::kConnected) {
    DVLOG(1) << "WiFi Connected, Reset DHCP: " << network_guid;
    // Even though wireless network is now connected, it may still be unusable,
    // e.g. after Chromecast device reset. Reset DHCP on wireless network to
    // work around this issue.
    error = ResetDHCP();
    if (error != ERROR_SUCCESS)
      LOG(ERROR) << error;
    // There is no need to keep created profile as network is connected.
    created_profiles_.RemoveWithoutPathExpansion(network_guid, nullptr);
    // Restore previously suppressed notifications.
    enable_notify_network_changed_ = true;
    RestoreNwCategoryWizard();
    NotifyNetworkChanged(network_guid);
  } else {
    // Continue waiting for network connection state change.
    task_runner_->PostDelayedTask(
        FROM_HERE,
        base::BindOnce(&WiFiServiceImpl::WaitForNetworkConnect,
                       base::Unretained(this), network_guid, ++attempt),
        base::TimeDelta::FromMilliseconds(kAttemptDelayMs));
  }
}

bool WiFiServiceImpl::CheckError(DWORD error_code,
                                 const std::string& error_name,
                                 std::string* error) const {
  if (error_code != ERROR_SUCCESS) {
    DLOG(ERROR) << "WiFiService Error " << error_code << ": " << error_name;
    *error = error_name;
    return true;
  }
  return false;
}

NetworkList::iterator WiFiServiceImpl::FindNetwork(
    NetworkList& networks,
    const std::string& network_guid) {
  for (NetworkList::iterator it = networks.begin(); it != networks.end();
       ++it) {
    if (it->guid == network_guid)
      return it;
  }
  return networks.end();
}

DWORD WiFiServiceImpl::SaveCurrentConnectedNetwork(
    const NetworkProperties& current_properties) {
  DWORD error = ERROR_SUCCESS;
  // Save currently connected network.
  if (!current_properties.guid.empty() &&
      current_properties.connection_state ==
          onc::connection_state::kConnected) {
    error = SaveTempProfile(current_properties.guid);
  }
  return error;
}

void WiFiServiceImpl::SortNetworks(NetworkList* networks) {
  networks->sort(NetworkProperties::OrderByType);
}

DWORD WiFiServiceImpl::LoadWlanLibrary() {
  // Use an absolute path to load the DLL to avoid DLL preloading attacks.
  base::FilePath path;
  if (!base::PathService::Get(base::DIR_SYSTEM, &path)) {
    LOG(ERROR) << "Unable to get system path.";
    return ERROR_NOT_FOUND;
  }
  wlan_api_library_ = ::LoadLibraryEx(path.Append(kWlanApiDll).value().c_str(),
                                      nullptr, LOAD_WITH_ALTERED_SEARCH_PATH);
  if (!wlan_api_library_) {
    LOG(ERROR) << "Unable to load WlanApi.dll.";
    return ERROR_NOT_FOUND;
  }

  // Initialize WlanApi function pointers
  WlanConnect_function_ =
      reinterpret_cast<WlanConnectFunction>(
          ::GetProcAddress(wlan_api_library_, kWlanConnect));
  WlanCloseHandle_function_ =
      reinterpret_cast<WlanCloseHandleFunction>(
          ::GetProcAddress(wlan_api_library_, kWlanCloseHandle));
  WlanDeleteProfile_function_ =
      reinterpret_cast<WlanDeleteProfileFunction>(
          ::GetProcAddress(wlan_api_library_, kWlanDeleteProfile));
  WlanDisconnect_function_ =
      reinterpret_cast<WlanDisconnectFunction>(
          ::GetProcAddress(wlan_api_library_, kWlanDisconnect));
  WlanEnumInterfaces_function_ =
      reinterpret_cast<WlanEnumInterfacesFunction>(
          ::GetProcAddress(wlan_api_library_, kWlanEnumInterfaces));
  WlanFreeMemory_function_ =
      reinterpret_cast<WlanFreeMemoryFunction>(
          ::GetProcAddress(wlan_api_library_, kWlanFreeMemory));
  WlanGetAvailableNetworkList_function_ =
      reinterpret_cast<WlanGetAvailableNetworkListFunction>(
          ::GetProcAddress(wlan_api_library_, kWlanGetAvailableNetworkList));
  WlanGetNetworkBssList_function_ =
      reinterpret_cast<WlanGetNetworkBssListFunction>(
          ::GetProcAddress(wlan_api_library_, kWlanGetNetworkBssList));
  WlanGetProfile_function_ =
      reinterpret_cast<WlanGetProfileFunction>(
          ::GetProcAddress(wlan_api_library_, kWlanGetProfile));
  WlanOpenHandle_function_ =
      reinterpret_cast<WlanOpenHandleFunction>(
          ::GetProcAddress(wlan_api_library_, kWlanOpenHandle));
  WlanQueryInterface_function_ =
      reinterpret_cast<WlanQueryInterfaceFunction>(
          ::GetProcAddress(wlan_api_library_, kWlanQueryInterface));
  WlanRegisterNotification_function_ =
      reinterpret_cast<WlanRegisterNotificationFunction>(
          ::GetProcAddress(wlan_api_library_, kWlanRegisterNotification));
  WlanSaveTemporaryProfile_function_ =
      reinterpret_cast<WlanSaveTemporaryProfileFunction>(
          ::GetProcAddress(wlan_api_library_, kWlanSaveTemporaryProfile));
  WlanScan_function_ =
      reinterpret_cast<WlanScanFunction>(
          ::GetProcAddress(wlan_api_library_, kWlanScan));
  WlanSetProfile_function_ =
      reinterpret_cast<WlanSetProfileFunction>(
          ::GetProcAddress(wlan_api_library_, kWlanSetProfile));

  if (!WlanConnect_function_ ||
      !WlanCloseHandle_function_ ||
      !WlanDeleteProfile_function_ ||
      !WlanDisconnect_function_ ||
      !WlanEnumInterfaces_function_ ||
      !WlanFreeMemory_function_ ||
      !WlanGetAvailableNetworkList_function_ ||
      !WlanGetProfile_function_ ||
      !WlanOpenHandle_function_ ||
      !WlanQueryInterface_function_ ||
      !WlanRegisterNotification_function_ ||
      !WlanScan_function_ ||
      !WlanSetProfile_function_) {
    LOG(ERROR) << "Unable to find required WlanApi function.";
    FreeLibrary(wlan_api_library_);
    wlan_api_library_ = nullptr;
    return ERROR_NOT_FOUND;
  }

  // Some WlanApi functions may not be available on XP.
  if (!WlanGetNetworkBssList_function_ ||
      !WlanSaveTemporaryProfile_function_) {
    DVLOG(1) << "WlanApi function is not be available on XP.";
  }

  return ERROR_SUCCESS;
}

DWORD WiFiServiceImpl::OpenClientHandle() {
  DWORD error = LoadWlanLibrary();
  DWORD service_version = 0;

  if (error != ERROR_SUCCESS)
    return error;

  // Open a handle to the service.
  error = WlanOpenHandle_function_(1, nullptr, &service_version, &client_);

  PWLAN_INTERFACE_INFO_LIST interface_list = nullptr;
  if (error == ERROR_SUCCESS) {
    // Enumerate wireless interfaces.
    error = WlanEnumInterfaces_function_(client_, nullptr, &interface_list);
    if (error == ERROR_SUCCESS) {
      if (interface_list && interface_list->dwNumberOfItems != 0) {
        // Remember first interface just in case if none are connected.
        interface_guid_ = interface_list->InterfaceInfo[0].InterfaceGuid;
        // Try to find a connected interface.
        for (DWORD itf = 0; itf < interface_list->dwNumberOfItems; ++itf) {
          if (interface_list->InterfaceInfo[itf].isState ==
              wlan_interface_state_connected) {
            // Found connected interface, remember it!
            interface_guid_ = interface_list->InterfaceInfo[itf].InterfaceGuid;
            break;
          }
        }
      } else {
        error = ERROR_NOINTERFACE;
      }
    }
    // Clean up..
    if (interface_list)
      WlanFreeMemory_function_(interface_list);
  }
  return error;
}

DWORD WiFiServiceImpl::ResetDHCP() {
  IP_ADAPTER_INDEX_MAP adapter_index_map = {0};
  DWORD error = FindAdapterIndexMapByGUID(interface_guid_, &adapter_index_map);
  if (error != ERROR_SUCCESS) {
    LOG(ERROR) << error;
    return error;
  }
  error = ::IpReleaseAddress(&adapter_index_map);
  if (error != ERROR_SUCCESS) {
    if (error != ERROR_ADDRESS_NOT_ASSOCIATED) {
      LOG(ERROR) << error;
      return error;
    }
    DVLOG(1) << "Ignoring IpReleaseAddress Error: " << error;
  }
  error = ::IpRenewAddress(&adapter_index_map);
  if (error != ERROR_SUCCESS)
    LOG(ERROR) << error;
  return error;
}

DWORD WiFiServiceImpl::FindAdapterIndexMapByGUID(
    const GUID& interface_guid,
    IP_ADAPTER_INDEX_MAP* adapter_index_map) {
  base::string16 guid_string;
  const int kGUIDSize = 39;
  ::StringFromGUID2(
      interface_guid, base::WriteInto(&guid_string, kGUIDSize), kGUIDSize);

  ULONG buffer_length = 0;
  DWORD error = ::GetInterfaceInfo(nullptr, &buffer_length);
  if (error == ERROR_INSUFFICIENT_BUFFER) {
    std::unique_ptr<unsigned char[]> buffer(new unsigned char[buffer_length]);
    IP_INTERFACE_INFO* interface_info =
        reinterpret_cast<IP_INTERFACE_INFO*>(buffer.get());
    error = GetInterfaceInfo(interface_info, &buffer_length);
    if (error == ERROR_SUCCESS) {
      for (int adapter = 0; adapter < interface_info->NumAdapters; ++adapter) {
        if (base::EndsWith(
                interface_info->Adapter[adapter].Name, guid_string,
                base::CompareCase::INSENSITIVE_ASCII)) {
          *adapter_index_map = interface_info->Adapter[adapter];
          break;
        }
      }
    }
  }
  return error;
}

DWORD WiFiServiceImpl::DisableNwCategoryWizard() {
  base::win::RegKey nw_category_wizard;
  DWORD error = nw_category_wizard.Open(HKEY_CURRENT_USER,
                                        kNwCategoryWizardRegKey,
                                        KEY_READ | KEY_SET_VALUE);
  if (error == ERROR_SUCCESS) {
    // Save current value if present.
    if (nw_category_wizard.HasValue(kNwCategoryWizardRegValue)) {
      DWORD saved = 0u;
      error = nw_category_wizard.ReadValueDW(kNwCategoryWizardRegValue,
                                             &saved);
      if (error == ERROR_SUCCESS) {
        error = nw_category_wizard.WriteValue(kNwCategoryWizardSavedRegValue,
                                              saved);
      }
    } else {
      // Mark that temporary value has to be deleted.
      error = nw_category_wizard.WriteValue(kNwCategoryWizardDeleteRegValue,
                                            1u);
    }

    // Disable network location wizard.
    error = nw_category_wizard.WriteValue(kNwCategoryWizardRegValue,
                                          static_cast<DWORD>(0));
  }

  return error;
}

DWORD WiFiServiceImpl::RestoreNwCategoryWizard() {
  base::win::RegKey nw_category_wizard;
  DWORD error = nw_category_wizard.Open(HKEY_CURRENT_USER,
                                        kNwCategoryWizardRegKey,
                                        KEY_SET_VALUE);
  if (error == ERROR_SUCCESS) {
    // Restore saved value if present.
    if (nw_category_wizard.HasValue(kNwCategoryWizardSavedRegValue)) {
      DWORD saved = 0u;
      error = nw_category_wizard.ReadValueDW(kNwCategoryWizardSavedRegValue,
                                             &saved);
      if (error == ERROR_SUCCESS) {
        error = nw_category_wizard.WriteValue(kNwCategoryWizardRegValue,
                                              saved);
        error = nw_category_wizard.DeleteValue(kNwCategoryWizardSavedRegValue);
      }
    } else if (nw_category_wizard.HasValue(kNwCategoryWizardDeleteRegValue)) {
      error = nw_category_wizard.DeleteValue(kNwCategoryWizardRegValue);
      error = nw_category_wizard.DeleteValue(kNwCategoryWizardDeleteRegValue);
    }
  }

  return error;
}

DWORD WiFiServiceImpl::EnsureInitialized() {
  if (client_)
    return ERROR_SUCCESS;
  return ERROR_NOINTERFACE;
}

DWORD WiFiServiceImpl::CloseClientHandle() {
  DWORD error = ERROR_SUCCESS;
  if (client_) {
    error = WlanCloseHandle_function_(client_, nullptr);
    client_ = nullptr;
  }
  if (wlan_api_library_) {
    WlanConnect_function_ = nullptr;
    WlanCloseHandle_function_ = nullptr;
    WlanDeleteProfile_function_ = nullptr;
    WlanDisconnect_function_ = nullptr;
    WlanEnumInterfaces_function_ = nullptr;
    WlanFreeMemory_function_ = nullptr;
    WlanGetAvailableNetworkList_function_ = nullptr;
    WlanGetNetworkBssList_function_ = nullptr;
    WlanGetProfile_function_ = nullptr;
    WlanOpenHandle_function_ = nullptr;
    WlanRegisterNotification_function_ = nullptr;
    WlanSaveTemporaryProfile_function_ = nullptr;
    WlanScan_function_ = nullptr;
    WlanSetProfile_function_ = nullptr;
    ::FreeLibrary(wlan_api_library_);
    wlan_api_library_ = nullptr;
  }
  return error;
}

DOT11_SSID WiFiServiceImpl::SSIDFromGUID(
    const std::string& network_guid) const {
  DOT11_SSID ssid = {0};
  if (network_guid.length() <= DOT11_SSID_MAX_LENGTH) {
    ssid.uSSIDLength = static_cast<ULONG>(network_guid.length());
    strncpy(reinterpret_cast<char*>(ssid.ucSSID),
            network_guid.c_str(),
            ssid.uSSIDLength);
  } else {
    NOTREACHED();
  }
  return ssid;
}

std::string WiFiServiceImpl::SecurityFromDot11AuthAlg(
    DOT11_AUTH_ALGORITHM alg) const {
  switch (alg) {
    case DOT11_AUTH_ALGO_RSNA:
      return onc::wifi::kWPA_EAP;
    case DOT11_AUTH_ALGO_RSNA_PSK:
      return onc::wifi::kWPA_PSK;
    case DOT11_AUTH_ALGO_80211_SHARED_KEY:
      return onc::wifi::kWEP_PSK;
    case DOT11_AUTH_ALGO_80211_OPEN:
      return onc::wifi::kSecurityNone;
    default:
      return onc::wifi::kWPA_EAP;
  }
}

std::string WiFiServiceImpl::ConnectionStateFromInterfaceState(
    WLAN_INTERFACE_STATE wlan_state) const {
  switch (wlan_state) {
    case wlan_interface_state_connected:
      // TODO(mef): Even if |wlan_state| is connected, the network may still
      // not be reachable, and should be resported as |kConnecting|.
      return onc::connection_state::kConnected;
    case wlan_interface_state_associating:
    case wlan_interface_state_discovering:
    case wlan_interface_state_authenticating:
      return onc::connection_state::kConnecting;
    default:
      return onc::connection_state::kNotConnected;
  }
}

void WiFiServiceImpl::NetworkPropertiesFromAvailableNetwork(
    const WLAN_AVAILABLE_NETWORK& wlan,
    NetworkProperties* properties) {
  // TODO(mef): It would be nice for the connection states in
  // getVisibleNetworks and getProperties results to be consistent.
  if (wlan.dwFlags & WLAN_AVAILABLE_NETWORK_CONNECTED) {
    properties->connection_state = onc::connection_state::kConnected;
  } else {
    properties->connection_state = onc::connection_state::kNotConnected;
  }

  properties->ssid = SSIDFromWLAN(wlan);
  properties->name = properties->ssid;
  properties->guid = GUIDFromWLAN(wlan);
  properties->type = onc::network_type::kWiFi;
  properties->security =
      SecurityFromDot11AuthAlg(wlan.dot11DefaultAuthAlgorithm);
  properties->signal_strength = wlan.wlanSignalQuality;
}

void WiFiServiceImpl::UpdateNetworkPropertiesFromBssList(
    const std::string& network_guid,
    const WLAN_BSS_LIST& wlan_bss_list,
    NetworkProperties* properties) {
  if (network_guid.empty())
    return;

  DOT11_SSID ssid = SSIDFromGUID(network_guid);
  for (size_t bss = 0; bss < wlan_bss_list.dwNumberOfItems; ++bss) {
    const WLAN_BSS_ENTRY& bss_entry(wlan_bss_list.wlanBssEntries[bss]);
    if (bss_entry.dot11Ssid.uSSIDLength == ssid.uSSIDLength &&
        0 == memcmp(bss_entry.dot11Ssid.ucSSID,
                    ssid.ucSSID,
                    bss_entry.dot11Ssid.uSSIDLength)) {
      std::string bssid = NetworkProperties::MacAddressAsString(
          bss_entry.dot11Bssid);
      Frequency frequency = GetNormalizedFrequency(
          bss_entry.ulChCenterFrequency / 1000);
      properties->frequency_set.insert(frequency);
      if (properties->bssid.empty() || properties->bssid == bssid) {
        properties->frequency = frequency;
        properties->bssid = bssid;
      }
    }
  }
}

// Get the list of visible wireless networks
DWORD WiFiServiceImpl::GetVisibleNetworkList(NetworkList* network_list) {
  DCHECK(client_);

  DWORD error = ERROR_SUCCESS;
  PWLAN_AVAILABLE_NETWORK_LIST available_network_list = nullptr;
  PWLAN_BSS_LIST bss_list = nullptr;

  error = WlanGetAvailableNetworkList_function_(
      client_, &interface_guid_,
      WLAN_AVAILABLE_NETWORK_INCLUDE_ALL_MANUAL_HIDDEN_PROFILES, nullptr,
      &available_network_list);

  std::set<std::string> network_guids;

  if (error == ERROR_SUCCESS &&
      available_network_list &&
      WlanGetNetworkBssList_function_) {
    // TODO(mef): WlanGetNetworkBssList is not available on XP. If XP support is
    // needed, then different method of getting BSS (e.g. OID query) will have
    // to be used.
    error = WlanGetNetworkBssList_function_(client_, &interface_guid_, nullptr,
                                            dot11_BSS_type_any, FALSE, nullptr,
                                            &bss_list);
    if (error == ERROR_SUCCESS && bss_list) {
      for (DWORD i = 0; i < available_network_list->dwNumberOfItems; ++i) {
        NetworkProperties network_properties;
        NetworkPropertiesFromAvailableNetwork(
            available_network_list->Network[i], &network_properties);
        UpdateNetworkPropertiesFromBssList(network_properties.guid, *bss_list,
                                           &network_properties);
        // Check for duplicate network guids.
        if (network_guids.count(network_properties.guid)) {
          // There should be no difference between properties except for
          // |connection_state|, so mark it as |kConnected| if either one is.
          if (network_properties.connection_state ==
              onc::connection_state::kConnected) {
            NetworkList::iterator previous_network_properties =
                FindNetwork(*network_list, network_properties.guid);
            DCHECK(previous_network_properties != network_list->end());
            previous_network_properties->connection_state =
                network_properties.connection_state;
          }
        } else {
          network_list->push_back(network_properties);
        }
        network_guids.insert(network_properties.guid);
      }
    }
  }

  // Clean up.
  if (available_network_list) {
    WlanFreeMemory_function_(available_network_list);
  }
  if (bss_list) {
    WlanFreeMemory_function_(bss_list);
  }
  return error;
}

DWORD WiFiServiceImpl::GetCurrentProperties(NetworkProperties* properties) {
  DCHECK(client_);

  // TODO(mef): WlanGetNetworkBssList is not available on XP. If XP support is
  // needed, then different method of getting BSS (e.g. OID query) will have
  // to be used.
  if (!WlanGetNetworkBssList_function_)
    return ERROR_NOINTERFACE;

  DWORD error = ERROR_SUCCESS;
  DWORD data_size = 0;
  PWLAN_CONNECTION_ATTRIBUTES wlan_connection_attributes = nullptr;
  PWLAN_BSS_LIST bss_list = nullptr;
  error = WlanQueryInterface_function_(
      client_, &interface_guid_, wlan_intf_opcode_current_connection, nullptr,
      &data_size, reinterpret_cast<PVOID*>(&wlan_connection_attributes),
      nullptr);
  if (error == ERROR_SUCCESS && wlan_connection_attributes != nullptr) {
    WLAN_ASSOCIATION_ATTRIBUTES& connected_wlan =
        wlan_connection_attributes->wlanAssociationAttributes;

    properties->connection_state = ConnectionStateFromInterfaceState(
        wlan_connection_attributes->isState);
    properties->ssid = GUIDFromSSID(connected_wlan.dot11Ssid);
    properties->name = properties->ssid;
    properties->guid = GUIDFromSSID(connected_wlan.dot11Ssid);
    properties->type = onc::network_type::kWiFi;
    properties->bssid = NetworkProperties::MacAddressAsString(
        connected_wlan.dot11Bssid);
    properties->security = SecurityFromDot11AuthAlg(
        wlan_connection_attributes->wlanSecurityAttributes.dot11AuthAlgorithm);
    properties->signal_strength = connected_wlan.wlanSignalQuality;

    error = WlanGetNetworkBssList_function_(
        client_, &interface_guid_, &connected_wlan.dot11Ssid,
        connected_wlan.dot11BssType, FALSE, nullptr, &bss_list);
    if (error == ERROR_SUCCESS && bss_list) {
      UpdateNetworkPropertiesFromBssList(properties->guid, *bss_list,
                                         properties);
    }
  }

  // Clean up.
  if (wlan_connection_attributes)
    WlanFreeMemory_function_(wlan_connection_attributes);

  if (bss_list)
    WlanFreeMemory_function_(bss_list);

  return error;
}

DWORD WiFiServiceImpl::GetCurrentSSID(std::string* ssid) {
  DCHECK(client_);
  DWORD error = ERROR_SUCCESS;
  DWORD data_size = 0;
  PWLAN_CONNECTION_ATTRIBUTES wlan_connection_attributes = nullptr;
  error = WlanQueryInterface_function_(
      client_, &interface_guid_, wlan_intf_opcode_current_connection, nullptr,
      &data_size, reinterpret_cast<PVOID*>(&wlan_connection_attributes),
      nullptr);
  if (error == ERROR_SUCCESS && wlan_connection_attributes) {
    WLAN_ASSOCIATION_ATTRIBUTES& connected_wlan =
        wlan_connection_attributes->wlanAssociationAttributes;
    *ssid = GUIDFromSSID(connected_wlan.dot11Ssid);
  }

  // Clean up.
  if (wlan_connection_attributes)
    WlanFreeMemory_function_(wlan_connection_attributes);

  return error;
}

Frequency WiFiServiceImpl::GetFrequencyToConnect(
    const std::string& network_guid) const {
  // Check whether desired frequency is set in |connect_properties_|.
  const base::DictionaryValue* properties;
  if (connect_properties_.GetDictionaryWithoutPathExpansion(network_guid,
                                                            &properties)) {
    const base::DictionaryValue* wifi;
    if (properties->GetDictionary(onc::network_type::kWiFi, &wifi)) {
      int frequency;
      if (wifi->GetInteger(onc::wifi::kFrequency, &frequency))
        return GetNormalizedFrequency(frequency);
    }
  }
  return kFrequencyAny;
}

DWORD WiFiServiceImpl::GetDesiredBssList(
    DOT11_SSID& ssid,
    Frequency frequency,
    std::unique_ptr<DOT11_BSSID_LIST>* desired_list) {
  DCHECK(client_);

  desired_list->reset();

  if (frequency == kFrequencyAny)
    return ERROR_SUCCESS;

  // TODO(mef): WlanGetNetworkBssList is not available on XP. If XP support is
  // needed, then different method of getting BSS (e.g. OID query) will have
  // to be used.
  if (!WlanGetNetworkBssList_function_)
    return ERROR_NOT_SUPPORTED;

  DWORD error = ERROR_SUCCESS;
  PWLAN_BSS_LIST bss_list = nullptr;

  error = WlanGetNetworkBssList_function_(client_, &interface_guid_, &ssid,
                                          dot11_BSS_type_infrastructure, FALSE,
                                          nullptr, &bss_list);
  if (error == ERROR_SUCCESS && bss_list) {
    unsigned int best_quality = 0u;
    size_t best_index = 0;
    Frequency bss_frequency;

    // Go through bss_list and find best quality BSSID with matching frequency.
    for (size_t bss = 0; bss < bss_list->dwNumberOfItems; ++bss) {
      const WLAN_BSS_ENTRY& bss_entry(bss_list->wlanBssEntries[bss]);
      if (bss_entry.dot11Ssid.uSSIDLength != ssid.uSSIDLength ||
          0 != memcmp(bss_entry.dot11Ssid.ucSSID,
                      ssid.ucSSID,
                      bss_entry.dot11Ssid.uSSIDLength))
        continue;

      bss_frequency = GetNormalizedFrequency(
          bss_entry.ulChCenterFrequency / 1000);
      if (bss_frequency == frequency &&
          bss_entry.uLinkQuality > best_quality) {
        best_quality = bss_entry.uLinkQuality;
        best_index = bss;
      }
    }

    // If any matching BSS were found, prepare the header.
    if (best_quality > 0) {
      const WLAN_BSS_ENTRY& bss_entry(bss_list->wlanBssEntries[best_index]);
      std::unique_ptr<DOT11_BSSID_LIST> selected_list(new DOT11_BSSID_LIST);

      selected_list->Header.Revision = DOT11_BSSID_LIST_REVISION_1;
      selected_list->Header.Size = sizeof(DOT11_BSSID_LIST);
      selected_list->Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
      selected_list->uNumOfEntries = 1;
      selected_list->uTotalNumOfEntries = 1;
      std::copy(bss_entry.dot11Bssid,
                bss_entry.dot11Bssid + sizeof(bss_entry.dot11Bssid),
                selected_list->BSSIDs[0]);
      desired_list->swap(selected_list);
      DVLOG(1) << "Quality: " << best_quality << " BSS: "
               << NetworkProperties::MacAddressAsString(bss_entry.dot11Bssid);
    } else {
      error = ERROR_NOT_FOUND;
    }
  }

  // Clean up.
  if (bss_list) {
    WlanFreeMemory_function_(bss_list);
  }
  return error;
}

Frequency WiFiServiceImpl::GetNormalizedFrequency(int frequency_in_mhz) const {
  if (frequency_in_mhz == 0)
    return kFrequencyAny;
  if (frequency_in_mhz < 3000)
    return kFrequency2400;
  return kFrequency5000;
}

DWORD WiFiServiceImpl::Connect(const std::string& network_guid,
                               Frequency frequency) {
  DCHECK(client_);
  DWORD error = ERROR_SUCCESS;
  DOT11_SSID ssid = SSIDFromGUID(network_guid);
  std::unique_ptr<DOT11_BSSID_LIST> desired_bss_list;
  error = GetDesiredBssList(ssid, frequency, &desired_bss_list);
  if (error == ERROR_SUCCESS) {
    if (HaveProfile(network_guid)) {
      base::string16 profile_name = ProfileNameFromGUID(network_guid);
      WLAN_CONNECTION_PARAMETERS wlan_params = {
          wlan_connection_mode_profile, profile_name.c_str(), nullptr,
          desired_bss_list.get(),       dot11_BSS_type_any,   0};
      error = WlanConnect_function_(client_, &interface_guid_, &wlan_params,
                                    nullptr);
    } else {
      // If network is available, but is not open security, then it cannot be
      // connected without profile, so return 'access denied' error.
      std::unique_ptr<base::DictionaryValue> properties(
          new base::DictionaryValue);
      const base::DictionaryValue* wifi;
      std::string wifi_security;
      std::string error_string;
      GetProperties(network_guid, properties.get(), &error_string);
      if (error_string.empty() &&
          properties->GetDictionary(onc::network_type::kWiFi, &wifi) &&
          wifi->GetString(onc::wifi::kSecurity, &wifi_security) &&
          wifi_security != onc::wifi::kSecurityNone) {
        error = ERROR_ACCESS_DENIED;
        LOG(ERROR) << error;
        return error;
      }
      WLAN_CONNECTION_PARAMETERS wlan_params = {
          wlan_connection_mode_discovery_unsecure,
          nullptr,
          &ssid,
          desired_bss_list.get(),
          dot11_BSS_type_infrastructure,
          0};
      error = WlanConnect_function_(client_, &interface_guid_, &wlan_params,
                                    nullptr);
    }
  }

  return error;
}

DWORD WiFiServiceImpl::Disconnect() {
  DCHECK(client_);
  DWORD error = ERROR_SUCCESS;
  error = WlanDisconnect_function_(client_, &interface_guid_, nullptr);
  return error;
}

DWORD WiFiServiceImpl::SaveTempProfile(const std::string& network_guid) {
  DCHECK(client_);
  DWORD error = ERROR_SUCCESS;
  base::string16 profile_name = ProfileNameFromGUID(network_guid);
  // TODO(mef): WlanSaveTemporaryProfile is not available on XP. If XP support
  // is needed, then different method of saving network profile will have to be
  // used.
  if (WlanSaveTemporaryProfile_function_) {
    error = WlanSaveTemporaryProfile_function_(
        client_, &interface_guid_, profile_name.c_str(), nullptr,
        WLAN_PROFILE_USER, true, nullptr);
  } else {
    error = ERROR_NOT_SUPPORTED;
  }
  return error;
}

DWORD WiFiServiceImpl::GetProfile(const std::string& network_guid,
                                  bool get_plaintext_key,
                                  std::string* profile_xml) {
  DCHECK(client_);
  DWORD error = ERROR_SUCCESS;
  base::string16 profile_name = ProfileNameFromGUID(network_guid);
  DWORD flags = get_plaintext_key ? WLAN_PROFILE_GET_PLAINTEXT_KEY : 0;
  LPWSTR str_profile_xml = nullptr;
  error =
      WlanGetProfile_function_(client_, &interface_guid_, profile_name.c_str(),
                               nullptr, &str_profile_xml, &flags, nullptr);

  if (error == ERROR_SUCCESS && str_profile_xml) {
    *profile_xml = base::UTF16ToUTF8(str_profile_xml);
  }
  // Clean up.
  if (str_profile_xml) {
    WlanFreeMemory_function_(str_profile_xml);
  }

  return error;
}

DWORD WiFiServiceImpl::SetProfile(bool shared,
                                  const std::string& profile_xml,
                                  bool overwrite) {
  DWORD error_code = ERROR_SUCCESS;

  base::string16 profile_xml16(base::UTF8ToUTF16(profile_xml));
  DWORD reason_code = 0u;

  error_code = WlanSetProfile_function_(
      client_, &interface_guid_, shared ? 0 : WLAN_PROFILE_USER,
      profile_xml16.c_str(), nullptr, overwrite, nullptr, &reason_code);
  return error_code;
}

bool WiFiServiceImpl::HaveProfile(const std::string& network_guid) {
  std::string profile_xml;
  return GetProfile(network_guid, false, &profile_xml) == ERROR_SUCCESS;
}


DWORD WiFiServiceImpl::DeleteCreatedProfile(const std::string& network_guid) {
  base::DictionaryValue* created_profile = nullptr;
  DWORD error_code = ERROR_SUCCESS;
  // Check, whether this connection is using new created profile, and remove it.
  if (created_profiles_.GetDictionaryWithoutPathExpansion(
      network_guid, &created_profile)) {
    // Connection has failed, so delete it.
    base::string16 profile_name = ProfileNameFromGUID(network_guid);
    error_code = WlanDeleteProfile_function_(client_, &interface_guid_,
                                             profile_name.c_str(), nullptr);
    created_profiles_.RemoveWithoutPathExpansion(network_guid, nullptr);
  }
  return error_code;
}

std::string WiFiServiceImpl::WpaEncryptionFromEncryptionType(
    EncryptionType encryption_type) const {
  if (encryption_type == kEncryptionTypeTKIP)
    return kEncryptionTKIP;
  return kEncryptionAES;
}

bool WiFiServiceImpl::AuthEncryptionFromSecurity(
    const std::string& security,
    EncryptionType encryption_type,
    std::string* authentication,
    std::string* encryption,
    std::string* key_type) const {
  if (security == onc::wifi::kSecurityNone) {
    *authentication = kAuthenticationOpen;
    *encryption = kEncryptionNone;
  } else if (security == onc::wifi::kWEP_PSK) {
    *authentication = kAuthenticationWepPsk;
    *encryption = kEncryptionWEP;
    *key_type = kKeyTypeNetwork;
  } else if (security == onc::wifi::kWPA_PSK) {
    *authentication = kAuthenticationWpaPsk;
    *encryption = WpaEncryptionFromEncryptionType(encryption_type);
    *key_type = kKeyTypePassphrase;
  } else if (security == onc::wifi::kWPA2_PSK) {
    *authentication = kAuthenticationWpa2Psk;
    *encryption = WpaEncryptionFromEncryptionType(encryption_type);
    *key_type = kKeyTypePassphrase;
  } else {
    return false;
  }
  return true;
}

bool WiFiServiceImpl::CreateProfile(
    const NetworkProperties& network_properties,
    EncryptionType encryption_type,
    std::string* profile_xml) {
  // Get authentication and encryption values from security.
  std::string authentication;
  std::string encryption;
  std::string key_type;
  bool valid = AuthEncryptionFromSecurity(network_properties.security,
                                          encryption_type,
                                          &authentication,
                                          &encryption,
                                          &key_type);
  if (!valid)
    return valid;

  // Generate profile XML.
  XmlWriter xml_writer;
  xml_writer.StartWriting();
  xml_writer.StartElement("WLANProfile");
  xml_writer.AddAttribute(
      "xmlns",
      "http://www.microsoft.com/networking/WLAN/profile/v1");
  xml_writer.WriteElement("name", network_properties.guid);
  xml_writer.StartElement("SSIDConfig");
  xml_writer.StartElement("SSID");
  xml_writer.WriteElement("name", network_properties.ssid);
  xml_writer.EndElement();  // Ends "SSID" element.
  xml_writer.EndElement();  // Ends "SSIDConfig" element.
  xml_writer.WriteElement("connectionType", "ESS");
  xml_writer.WriteElement("connectionMode", "manual");
  xml_writer.StartElement("MSM");
  xml_writer.StartElement("security");
  xml_writer.StartElement("authEncryption");
  xml_writer.WriteElement("authentication", authentication);
  xml_writer.WriteElement("encryption", encryption);
  xml_writer.WriteElement("useOneX", "false");
  xml_writer.EndElement();  // Ends "authEncryption" element.
  if (!key_type.empty()) {
    xml_writer.StartElement("sharedKey");
    xml_writer.WriteElement("keyType", key_type);
    xml_writer.WriteElement("protected", "false");
    xml_writer.WriteElement("keyMaterial", network_properties.password);
    xml_writer.EndElement();  // Ends "sharedKey" element.
  }
  xml_writer.EndElement();  // Ends "security" element.
  xml_writer.EndElement();  // Ends "MSM" element.
  xml_writer.EndElement();  // Ends "WLANProfile" element.
  xml_writer.StopWriting();
  *profile_xml = xml_writer.GetWrittenString();

  return true;
}

void WiFiServiceImpl::NotifyNetworkListChanged(const NetworkList& networks) {
  if (network_list_changed_observer_.is_null())
    return;

  NetworkGuidList current_networks;
  for (NetworkList::const_iterator it = networks.begin();
       it != networks.end();
       ++it) {
    current_networks.push_back(it->guid);
  }

  event_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(network_list_changed_observer_, current_networks));
}

void WiFiServiceImpl::NotifyNetworkChanged(const std::string& network_guid) {
  if (enable_notify_network_changed_ && !networks_changed_observer_.is_null()) {
    DVLOG(1) << "NotifyNetworkChanged: " << network_guid;
    NetworkGuidList changed_networks(1, network_guid);
    event_task_runner_->PostTask(
        FROM_HERE,
        base::BindOnce(networks_changed_observer_, changed_networks));
  }
}

WiFiService* WiFiService::Create() { return new WiFiServiceImpl(); }

}  // namespace wifi
