// Copyright (c) 2010 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.

// Windows Vista uses the Native Wifi (WLAN) API for accessing WiFi cards. See
// http://msdn.microsoft.com/en-us/library/ms705945(VS.85).aspx. Windows XP
// Service Pack 3 (and Windows XP Service Pack 2, if upgraded with a hot fix)
// also support a limited version of the WLAN API. See
// http://msdn.microsoft.com/en-us/library/bb204766.aspx. The WLAN API uses
// wlanapi.h, which is not part of the SDK used by Gears, so is replicated
// locally using data from the MSDN.
//
// Windows XP from Service Pack 2 onwards supports the Wireless Zero
// Configuration (WZC) programming interface. See
// http://msdn.microsoft.com/en-us/library/ms706587(VS.85).aspx.
//
// The MSDN recommends that one use the WLAN API where available, and WZC
// otherwise.
//
// However, it seems that WZC fails for some wireless cards. Also, WLAN seems
// not to work on XP SP3. So we use WLAN on Vista, and use NDIS directly
// otherwise.

#include "device/geolocation/wifi_data_provider_win.h"

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

#include "base/memory/free_deleter.h"
#include "base/metrics/histogram.h"
#include "base/strings/utf_string_conversions.h"
#include "base/win/windows_version.h"
#include "device/geolocation/wifi_data_provider_common.h"
#include "device/geolocation/wifi_data_provider_common_win.h"
#include "device/geolocation/wifi_data_provider_manager.h"

// Taken from ndis.h for WinCE.
#define NDIS_STATUS_INVALID_LENGTH ((NDIS_STATUS)0xC0010014L)
#define NDIS_STATUS_BUFFER_TOO_SHORT ((NDIS_STATUS)0xC0010016L)

namespace device {
namespace {
// The limits on the size of the buffer used for the OID query.
const int kInitialBufferSize = 2 << 12;  // Good for about 50 APs.
const int kMaximumBufferSize = 2 << 20;  // 2MB

// Length for generic string buffers passed to Windows APIs.
const int kStringLength = 512;

// The time periods, in milliseconds, between successive polls of the wifi data.
const int kDefaultPollingInterval = 10000;                 // 10s
const int kNoChangePollingInterval = 120000;               // 2 mins
const int kTwoNoChangePollingInterval = 600000;            // 10 mins
const int kNoWifiPollingIntervalMilliseconds = 20 * 1000;  // 20s

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

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

// WlanGetNetworkBssList
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);

// WlanFreeMemory
typedef VOID(WINAPI* WlanFreeMemoryFunction)(PVOID pMemory);

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

// Local classes and functions
class WindowsWlanApi : public WifiDataProviderCommon::WlanApiInterface {
 public:
  ~WindowsWlanApi() override;
  // Factory function. Will return NULL if this API is unavailable.
  static WindowsWlanApi* Create();

  // WlanApiInterface
  bool GetAccessPointData(WifiData::AccessPointDataSet* data) override;

 private:
  // Takes ownership of the library handle.
  explicit WindowsWlanApi(HINSTANCE library);

  // Loads the required functions from the DLL.
  void GetWLANFunctions(HINSTANCE wlan_library);
  int GetInterfaceDataWLAN(HANDLE wlan_handle,
                           const GUID& interface_id,
                           WifiData::AccessPointDataSet* data);

  // Logs number of detected wlan interfaces.
  static void LogWlanInterfaceCount(int count);

  // Handle to the wlanapi.dll library.
  HINSTANCE library_;

  // Function pointers for WLAN
  WlanOpenHandleFunction WlanOpenHandle_function_;
  WlanEnumInterfacesFunction WlanEnumInterfaces_function_;
  WlanGetNetworkBssListFunction WlanGetNetworkBssList_function_;
  WlanFreeMemoryFunction WlanFreeMemory_function_;
  WlanCloseHandleFunction WlanCloseHandle_function_;
};

class WindowsNdisApi : public WifiDataProviderCommon::WlanApiInterface {
 public:
  ~WindowsNdisApi() override;
  static WindowsNdisApi* Create();

  // WlanApiInterface
  bool GetAccessPointData(WifiData::AccessPointDataSet* data) override;

 private:
  static bool GetInterfacesNDIS(
      std::vector<base::string16>* interface_service_names_out);

  // Swaps in content of the vector passed
  explicit WindowsNdisApi(std::vector<base::string16>* interface_service_names);

  bool GetInterfaceDataNDIS(HANDLE adapter_handle,
                            WifiData::AccessPointDataSet* data);
  // NDIS variables.
  std::vector<base::string16> interface_service_names_;

  // Remembers scan result buffer size across calls.
  int oid_buffer_size_;
};

// Extracts data for an access point and converts to Gears format.
bool GetNetworkData(const WLAN_BSS_ENTRY& bss_entry,
                    AccessPointData* access_point_data);
bool UndefineDosDevice(const base::string16& device_name);
bool DefineDosDeviceIfNotExists(const base::string16& device_name);
HANDLE GetFileHandle(const base::string16& device_name);
// Makes the OID query and returns a Windows API error code.
int PerformQuery(HANDLE adapter_handle,
                 BYTE* buffer,
                 DWORD buffer_size,
                 DWORD* bytes_out);
bool ResizeBuffer(int requested_size,
                  std::unique_ptr<BYTE, base::FreeDeleter>* buffer);
// Gets the system directory and appends a trailing slash if not already
// present.
bool GetSystemDirectory(base::string16* path);
}  // namespace

WifiDataProvider* WifiDataProviderManager::DefaultFactoryFunction() {
  return new WifiDataProviderWin();
}

WifiDataProviderWin::WifiDataProviderWin() {}

WifiDataProviderWin::~WifiDataProviderWin() {}

WifiDataProviderCommon::WlanApiInterface* WifiDataProviderWin::NewWlanApi() {
  // Use the WLAN interface if we're on Vista and if it's available. Otherwise,
  // use NDIS.
  WlanApiInterface* api = WindowsWlanApi::Create();
  if (api) {
    return api;
  }
  return WindowsNdisApi::Create();
}

WifiPollingPolicy* WifiDataProviderWin::NewPollingPolicy() {
  return new GenericWifiPollingPolicy<
      kDefaultPollingInterval, kNoChangePollingInterval,
      kTwoNoChangePollingInterval, kNoWifiPollingIntervalMilliseconds>;
}

// Local classes and functions
namespace {

// WindowsWlanApi
WindowsWlanApi::WindowsWlanApi(HINSTANCE library) : library_(library) {
  GetWLANFunctions(library_);
}

WindowsWlanApi::~WindowsWlanApi() {
  FreeLibrary(library_);
}

WindowsWlanApi* WindowsWlanApi::Create() {
  if (base::win::GetVersion() < base::win::VERSION_VISTA)
    return NULL;
  // We use an absolute path to load the DLL to avoid DLL preloading attacks.
  base::string16 system_directory;
  if (!GetSystemDirectory(&system_directory)) {
    return NULL;
  }
  DCHECK(!system_directory.empty());
  base::string16 dll_path = system_directory + L"wlanapi.dll";
  HINSTANCE library =
      LoadLibraryEx(dll_path.c_str(), NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
  if (!library) {
    return NULL;
  }
  return new WindowsWlanApi(library);
}

void WindowsWlanApi::GetWLANFunctions(HINSTANCE wlan_library) {
  DCHECK(wlan_library);
  WlanOpenHandle_function_ = reinterpret_cast<WlanOpenHandleFunction>(
      GetProcAddress(wlan_library, "WlanOpenHandle"));
  WlanEnumInterfaces_function_ = reinterpret_cast<WlanEnumInterfacesFunction>(
      GetProcAddress(wlan_library, "WlanEnumInterfaces"));
  WlanGetNetworkBssList_function_ =
      reinterpret_cast<WlanGetNetworkBssListFunction>(
          GetProcAddress(wlan_library, "WlanGetNetworkBssList"));
  WlanFreeMemory_function_ = reinterpret_cast<WlanFreeMemoryFunction>(
      GetProcAddress(wlan_library, "WlanFreeMemory"));
  WlanCloseHandle_function_ = reinterpret_cast<WlanCloseHandleFunction>(
      GetProcAddress(wlan_library, "WlanCloseHandle"));
  DCHECK(WlanOpenHandle_function_ && WlanEnumInterfaces_function_ &&
         WlanGetNetworkBssList_function_ && WlanFreeMemory_function_ &&
         WlanCloseHandle_function_);
}

void WindowsWlanApi::LogWlanInterfaceCount(int count) {
  UMA_HISTOGRAM_CUSTOM_COUNTS("Net.Wifi.InterfaceCount", count, 1, 5, 6);
}

bool WindowsWlanApi::GetAccessPointData(WifiData::AccessPointDataSet* data) {
  DCHECK(data);

  // Get the handle to the WLAN API.
  DWORD negotiated_version;
  HANDLE wlan_handle = NULL;
  // We could be executing on either Windows XP or Windows Vista, so use the
  // lower version of the client WLAN API. It seems that the negotiated version
  // is the Vista version irrespective of what we pass!
  static const int kXpWlanClientVersion = 1;
  if ((*WlanOpenHandle_function_)(kXpWlanClientVersion, NULL,
                                  &negotiated_version,
                                  &wlan_handle) != ERROR_SUCCESS) {
    LogWlanInterfaceCount(0);
    return false;
  }
  DCHECK(wlan_handle);

  // Get the list of interfaces. WlanEnumInterfaces allocates interface_list.
  WLAN_INTERFACE_INFO_LIST* interface_list = NULL;
  if ((*WlanEnumInterfaces_function_)(wlan_handle, NULL, &interface_list) !=
      ERROR_SUCCESS) {
    LogWlanInterfaceCount(0);
    return false;
  }
  DCHECK(interface_list);

  LogWlanInterfaceCount(interface_list->dwNumberOfItems);

  // Go through the list of interfaces and get the data for each.
  for (int i = 0; i < static_cast<int>(interface_list->dwNumberOfItems); ++i) {
    // Skip any interface that is midway through association; the
    // WlanGetNetworkBssList function call is known to hang indefinitely
    // when it's in this state. http://crbug.com/39300
    if (interface_list->InterfaceInfo[i].isState ==
        wlan_interface_state_associating) {
      LOG(WARNING) << "Skipping wifi scan on adapter " << i << " ("
                   << interface_list->InterfaceInfo[i].strInterfaceDescription
                   << ") in 'associating' state. Repeated occurrences "
                      "indicates a non-responding adapter.";
      continue;
    }
    GetInterfaceDataWLAN(wlan_handle,
                         interface_list->InterfaceInfo[i].InterfaceGuid, data);
  }

  // Free interface_list.
  (*WlanFreeMemory_function_)(interface_list);

  // Close the handle.
  if ((*WlanCloseHandle_function_)(wlan_handle, NULL) != ERROR_SUCCESS) {
    return false;
  }

  return true;
}

// Appends the data for a single interface to the data vector. Returns the
// number of access points found, or -1 on error.
int WindowsWlanApi::GetInterfaceDataWLAN(const HANDLE wlan_handle,
                                         const GUID& interface_id,
                                         WifiData::AccessPointDataSet* data) {
  DCHECK(data);

  const base::TimeTicks start_time = base::TimeTicks::Now();

  // WlanGetNetworkBssList allocates bss_list.
  WLAN_BSS_LIST* bss_list = NULL;
  if ((*WlanGetNetworkBssList_function_)(wlan_handle, &interface_id,
                                         NULL,  // Use all SSIDs.
                                         dot11_BSS_type_any,
                                         false,  // bSecurityEnabled - unused
                                         NULL,   // reserved
                                         &bss_list) != ERROR_SUCCESS) {
    return -1;
  }
  // According to http://www.attnetclient.com/kb/questions.php?questionid=75
  // WlanGetNetworkBssList can sometimes return success, but leave the bss
  // list as NULL.
  if (!bss_list)
    return -1;

  const base::TimeDelta duration = base::TimeTicks::Now() - start_time;

  UMA_HISTOGRAM_CUSTOM_TIMES("Net.Wifi.ScanLatency", duration,
                             base::TimeDelta::FromMilliseconds(1),
                             base::TimeDelta::FromMinutes(1), 100);

  int found = 0;
  for (int i = 0; i < static_cast<int>(bss_list->dwNumberOfItems); ++i) {
    AccessPointData access_point_data;
    if (GetNetworkData(bss_list->wlanBssEntries[i], &access_point_data)) {
      ++found;
      data->insert(access_point_data);
    }
  }

  (*WlanFreeMemory_function_)(bss_list);

  return found;
}

// WindowsNdisApi
WindowsNdisApi::WindowsNdisApi(
    std::vector<base::string16>* interface_service_names)
    : oid_buffer_size_(kInitialBufferSize) {
  DCHECK(!interface_service_names->empty());
  interface_service_names_.swap(*interface_service_names);
}

WindowsNdisApi::~WindowsNdisApi() {}

WindowsNdisApi* WindowsNdisApi::Create() {
  std::vector<base::string16> interface_service_names;
  if (GetInterfacesNDIS(&interface_service_names)) {
    return new WindowsNdisApi(&interface_service_names);
  }
  return NULL;
}

bool WindowsNdisApi::GetAccessPointData(WifiData::AccessPointDataSet* data) {
  DCHECK(data);
  int interfaces_failed = 0;
  int interfaces_succeeded = 0;

  for (int i = 0; i < static_cast<int>(interface_service_names_.size()); ++i) {
    // First, check that we have a DOS device for this adapter.
    if (!DefineDosDeviceIfNotExists(interface_service_names_[i])) {
      continue;
    }

    // Get the handle to the device. This will fail if the named device is not
    // valid.
    HANDLE adapter_handle = GetFileHandle(interface_service_names_[i]);
    if (adapter_handle == INVALID_HANDLE_VALUE) {
      continue;
    }

    // Get the data.
    if (GetInterfaceDataNDIS(adapter_handle, data)) {
      ++interfaces_succeeded;
    } else {
      ++interfaces_failed;
    }

    // Clean up.
    CloseHandle(adapter_handle);
    UndefineDosDevice(interface_service_names_[i]);
  }

  // Return true if at least one interface succeeded, or at the very least none
  // failed.
  return interfaces_succeeded > 0 || interfaces_failed == 0;
}

bool WindowsNdisApi::GetInterfacesNDIS(
    std::vector<base::string16>* interface_service_names_out) {
  HKEY network_cards_key = NULL;
  if (RegOpenKeyEx(
          HKEY_LOCAL_MACHINE,
          L"Software\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards", 0,
          KEY_READ, &network_cards_key) != ERROR_SUCCESS) {
    return false;
  }
  DCHECK(network_cards_key);

  for (int i = 0;; ++i) {
    TCHAR name[kStringLength];
    DWORD name_size = kStringLength;
    FILETIME time;
    if (RegEnumKeyEx(network_cards_key, i, name, &name_size, NULL, NULL, NULL,
                     &time) != ERROR_SUCCESS) {
      break;
    }
    HKEY hardware_key = NULL;
    if (RegOpenKeyEx(network_cards_key, name, 0, KEY_READ, &hardware_key) !=
        ERROR_SUCCESS) {
      break;
    }
    DCHECK(hardware_key);

    TCHAR service_name[kStringLength];
    DWORD service_name_size = kStringLength;
    DWORD type = 0;
    if (RegQueryValueEx(hardware_key, L"ServiceName", NULL, &type,
                        reinterpret_cast<LPBYTE>(service_name),
                        &service_name_size) == ERROR_SUCCESS) {
      interface_service_names_out->push_back(service_name);
    }
    RegCloseKey(hardware_key);
  }

  RegCloseKey(network_cards_key);
  return true;
}

bool WindowsNdisApi::GetInterfaceDataNDIS(HANDLE adapter_handle,
                                          WifiData::AccessPointDataSet* data) {
  DCHECK(data);

  std::unique_ptr<BYTE, base::FreeDeleter> buffer(
      static_cast<BYTE*>(malloc(oid_buffer_size_)));
  if (buffer == NULL) {
    return false;
  }

  DWORD bytes_out;
  int result;

  while (true) {
    bytes_out = 0;
    result = PerformQuery(adapter_handle, buffer.get(), oid_buffer_size_,
                          &bytes_out);
    if (result == ERROR_GEN_FAILURE ||  // Returned by some Intel cards.
        result == ERROR_INSUFFICIENT_BUFFER || result == ERROR_MORE_DATA ||
        result == NDIS_STATUS_INVALID_LENGTH ||
        result == NDIS_STATUS_BUFFER_TOO_SHORT) {
      // The buffer we supplied is too small, so increase it. bytes_out should
      // provide the required buffer size, but this is not always the case.
      if (bytes_out > static_cast<DWORD>(oid_buffer_size_)) {
        oid_buffer_size_ = bytes_out;
      } else {
        oid_buffer_size_ *= 2;
      }
      if (!ResizeBuffer(oid_buffer_size_, &buffer)) {
        oid_buffer_size_ = kInitialBufferSize;  // Reset for next time.
        return false;
      }
    } else {
      // The buffer is not too small.
      break;
    }
  }
  DCHECK(buffer.get());

  if (result == ERROR_SUCCESS) {
    NDIS_802_11_BSSID_LIST* bssid_list =
        reinterpret_cast<NDIS_802_11_BSSID_LIST*>(buffer.get());
    GetDataFromBssIdList(*bssid_list, oid_buffer_size_, data);
  }

  return true;
}

bool GetNetworkData(const WLAN_BSS_ENTRY& bss_entry,
                    AccessPointData* access_point_data) {
  // Currently we get only MAC address, signal strength and SSID.
  DCHECK(access_point_data);
  access_point_data->mac_address = MacAddressAsString16(bss_entry.dot11Bssid);
  access_point_data->radio_signal_strength = bss_entry.lRssi;
  // bss_entry.dot11Ssid.ucSSID is not null-terminated.
  base::UTF8ToUTF16(reinterpret_cast<const char*>(bss_entry.dot11Ssid.ucSSID),
                    static_cast<ULONG>(bss_entry.dot11Ssid.uSSIDLength),
                    &access_point_data->ssid);
  // TODO(steveblock): Is it possible to get the following?
  // access_point_data->signal_to_noise
  // access_point_data->age
  // access_point_data->channel
  return true;
}

bool UndefineDosDevice(const base::string16& device_name) {
  // We remove only the mapping we use, that is \Device\<device_name>.
  base::string16 target_path = L"\\Device\\" + device_name;
  return DefineDosDevice(DDD_RAW_TARGET_PATH | DDD_REMOVE_DEFINITION |
                             DDD_EXACT_MATCH_ON_REMOVE,
                         device_name.c_str(), target_path.c_str()) == TRUE;
}

bool DefineDosDeviceIfNotExists(const base::string16& device_name) {
  // We create a DOS device name for the device at \Device\<device_name>.
  base::string16 target_path = L"\\Device\\" + device_name;

  TCHAR target[kStringLength];
  if (QueryDosDevice(device_name.c_str(), target, kStringLength) > 0 &&
      target_path.compare(target) == 0) {
    // Device already exists.
    return true;
  }

  if (GetLastError() != ERROR_FILE_NOT_FOUND) {
    return false;
  }

  if (!DefineDosDevice(DDD_RAW_TARGET_PATH, device_name.c_str(),
                       target_path.c_str())) {
    return false;
  }

  // Check that the device is really there.
  return QueryDosDevice(device_name.c_str(), target, kStringLength) > 0 &&
         target_path.compare(target) == 0;
}

HANDLE GetFileHandle(const base::string16& device_name) {
  // We access a device with DOS path \Device\<device_name> at
  // \\.\<device_name>.
  base::string16 formatted_device_name = L"\\\\.\\" + device_name;

  return CreateFile(formatted_device_name.c_str(), GENERIC_READ,
                    FILE_SHARE_READ | FILE_SHARE_WRITE,  // share mode
                    0,                                   // security attributes
                    OPEN_EXISTING,
                    0,  // flags and attributes
                    INVALID_HANDLE_VALUE);
}

int PerformQuery(HANDLE adapter_handle,
                 BYTE* buffer,
                 DWORD buffer_size,
                 DWORD* bytes_out) {
  DWORD oid = OID_802_11_BSSID_LIST;
  if (!DeviceIoControl(adapter_handle, IOCTL_NDIS_QUERY_GLOBAL_STATS, &oid,
                       sizeof(oid), buffer, buffer_size, bytes_out, NULL)) {
    return GetLastError();
  }
  return ERROR_SUCCESS;
}

bool ResizeBuffer(int requested_size,
                  std::unique_ptr<BYTE, base::FreeDeleter>* buffer) {
  DCHECK_GT(requested_size, 0);
  DCHECK(buffer);
  if (requested_size > kMaximumBufferSize) {
    buffer->reset();
    return false;
  }

  buffer->reset(
      reinterpret_cast<BYTE*>(realloc(buffer->release(), requested_size)));
  return buffer != NULL;
}

bool GetSystemDirectory(base::string16* path) {
  DCHECK(path);
  // Return value includes terminating NULL.
  int buffer_size = ::GetSystemDirectory(NULL, 0);
  if (buffer_size == 0) {
    return false;
  }
  std::unique_ptr<base::char16[]> buffer(new base::char16[buffer_size]);

  // Return value excludes terminating NULL.
  int characters_written = ::GetSystemDirectory(buffer.get(), buffer_size);
  if (characters_written == 0) {
    return false;
  }
  DCHECK_EQ(buffer_size - 1, characters_written);

  path->assign(buffer.get(), characters_written);

  if (*path->rbegin() != L'\\') {
    path->append(L"\\");
  }
  DCHECK_EQ(L'\\', *path->rbegin());
  return true;
}
}  // namespace

}  // namespace device
