| Index: device/geolocation/wifi_data_provider_win.cc
|
| diff --git a/device/geolocation/wifi_data_provider_win.cc b/device/geolocation/wifi_data_provider_win.cc
|
| index 8b296ae1f4e84d546b2063be834608a05dc25a6e..908d06c4f54e783f4d23de3e4e74446debdb9695 100644
|
| --- a/device/geolocation/wifi_data_provider_win.cc
|
| +++ b/device/geolocation/wifi_data_provider_win.cc
|
| @@ -2,25 +2,6 @@
|
| // 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>
|
| @@ -31,29 +12,20 @@
|
| #include "base/memory/ptr_util.h"
|
| #include "base/metrics/histogram_macros.h"
|
| #include "base/strings/utf_string_conversions.h"
|
| +#include "base/timer/elapsed_timer.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;
|
| +namespace {
|
|
|
| -// 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
|
| +static const int kDefaultPollingIntervalMs = 10 * 1000; // 10s
|
| +static const int kNoChangePollingIntervalMs = 2 * 60 * 1000; // 2 mins
|
| +static const int kTwoNoChangePollingIntervalMs = 10 * 60 * 1000; // 10 mins
|
| +static const int kNoWifiPollingIntervalMs = 20 * 1000; // 20s
|
|
|
| // WlanOpenHandle
|
| typedef DWORD(WINAPI* WlanOpenHandleFunction)(DWORD dwClientVersion,
|
| @@ -84,29 +56,47 @@ typedef VOID(WINAPI* WlanFreeMemoryFunction)(PVOID pMemory);
|
| typedef DWORD(WINAPI* WlanCloseHandleFunction)(HANDLE hClientHandle,
|
| PVOID pReserved);
|
|
|
| -// Local classes and functions
|
| +// Extracts data for an access point and converts to AccessPointData.
|
| +AccessPointData GetNetworkData(const WLAN_BSS_ENTRY& bss_entry) {
|
| + AccessPointData access_point_data;
|
| + // Currently we get only MAC address, signal strength and SSID.
|
| + 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 access_point_data;
|
| +}
|
| +
|
| +// This class encapsulates loading and interacting with wlan_api.dll, which can
|
| +// not be loaded statically because it's not available in Server 2008 R2, where
|
| +// it must be installed explicitly by the user if and when they wants to use the
|
| +// Wireless interface.
|
| +// https://www.bonusbits.com/wiki/KB:Wlanapi.dll_missing_on_Windows_Server_2008_R2
|
| class WindowsWlanApi : public WifiDataProviderCommon::WlanApiInterface {
|
| public:
|
| - // Factory function. Will return NULL if this API is unavailable.
|
| static std::unique_ptr<WindowsWlanApi> Create();
|
|
|
| // Takes ownership of the library handle.
|
| explicit WindowsWlanApi(HINSTANCE library);
|
| ~WindowsWlanApi() override;
|
|
|
| - // WlanApiInterface
|
| + // WlanApiInterface implementation
|
| bool GetAccessPointData(WifiData::AccessPointDataSet* data) override;
|
|
|
| private:
|
| - // 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);
|
|
|
| + bool GetInterfaceDataWLAN(HANDLE wlan_handle,
|
| + const GUID& interface_id,
|
| + WifiData::AccessPointDataSet* data);
|
| // Handle to the wlanapi.dll library.
|
| HINSTANCE library_;
|
|
|
| @@ -118,130 +108,56 @@ class WindowsWlanApi : public WifiDataProviderCommon::WlanApiInterface {
|
| WlanCloseHandleFunction WlanCloseHandle_function_;
|
| };
|
|
|
| -class WindowsNdisApi : public WifiDataProviderCommon::WlanApiInterface {
|
| - public:
|
| - static std::unique_ptr<WindowsNdisApi> Create();
|
| -
|
| - // Swaps in content of the vector passed
|
| - explicit WindowsNdisApi(std::vector<base::string16>* interface_service_names);
|
| - ~WindowsNdisApi() override;
|
| -
|
| - // WlanApiInterface
|
| - bool GetAccessPointData(WifiData::AccessPointDataSet* data) override;
|
| -
|
| - private:
|
| - static bool GetInterfacesNDIS(
|
| - std::vector<base::string16>* interface_service_names_out);
|
| - 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);
|
| -} // anonymous namespace
|
| -
|
| -WifiDataProvider* WifiDataProviderManager::DefaultFactoryFunction() {
|
| - return new WifiDataProviderWin();
|
| -}
|
| -
|
| -WifiDataProviderWin::WifiDataProviderWin() {}
|
| -
|
| -WifiDataProviderWin::~WifiDataProviderWin() {}
|
| -
|
| -std::unique_ptr<WifiDataProviderCommon::WlanApiInterface>
|
| -WifiDataProviderWin::CreateWlanApi() {
|
| - // Use the WLAN interface if we're on Vista and if it's available. Otherwise,
|
| - // use NDIS.
|
| - std::unique_ptr<WlanApiInterface> api = WindowsWlanApi::Create();
|
| - if (api)
|
| - return api;
|
| - return WindowsNdisApi::Create();
|
| -}
|
| -
|
| -std::unique_ptr<WifiPollingPolicy> WifiDataProviderWin::CreatePollingPolicy() {
|
| - return base::MakeUnique<GenericWifiPollingPolicy<
|
| - kDefaultPollingInterval, kNoChangePollingInterval,
|
| - kTwoNoChangePollingInterval, kNoWifiPollingIntervalMilliseconds>>();
|
| -}
|
| -
|
| -// Local classes and functions
|
| -namespace {
|
| -
|
| -// WindowsWlanApi
|
| -WindowsWlanApi::WindowsWlanApi(HINSTANCE library) : library_(library) {
|
| - GetWLANFunctions(library_);
|
| -}
|
| -
|
| -WindowsWlanApi::~WindowsWlanApi() {
|
| - FreeLibrary(library_);
|
| -}
|
| -
|
| +// static
|
| std::unique_ptr<WindowsWlanApi> WindowsWlanApi::Create() {
|
| - if (base::win::GetVersion() < base::win::VERSION_VISTA)
|
| - return nullptr;
|
| - // We use an absolute path to load the DLL to avoid DLL preloading attacks.
|
| - base::string16 system_directory;
|
| - if (!GetSystemDirectory(&system_directory))
|
| - return nullptr;
|
| - 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);
|
| + // Use an absolute path to load the DLL to avoid DLL preloading attacks.
|
| + static const wchar_t* const kDLL = L"%WINDIR%\\system32\\wlanapi.dll";
|
| + wchar_t path[MAX_PATH] = {0};
|
| + ExpandEnvironmentStrings(kDLL, path, arraysize(path));
|
| + HINSTANCE library = LoadLibraryEx(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
|
| if (!library)
|
| return nullptr;
|
| return base::MakeUnique<WindowsWlanApi>(library);
|
| }
|
|
|
| -void WindowsWlanApi::GetWLANFunctions(HINSTANCE wlan_library) {
|
| - DCHECK(wlan_library);
|
| +WindowsWlanApi::WindowsWlanApi(HINSTANCE library) : library_(library) {
|
| + DCHECK(library_);
|
| + // Extract all methods from |library_|.
|
| WlanOpenHandle_function_ = reinterpret_cast<WlanOpenHandleFunction>(
|
| - GetProcAddress(wlan_library, "WlanOpenHandle"));
|
| + GetProcAddress(library_, "WlanOpenHandle"));
|
| WlanEnumInterfaces_function_ = reinterpret_cast<WlanEnumInterfacesFunction>(
|
| - GetProcAddress(wlan_library, "WlanEnumInterfaces"));
|
| + GetProcAddress(library_, "WlanEnumInterfaces"));
|
| WlanGetNetworkBssList_function_ =
|
| reinterpret_cast<WlanGetNetworkBssListFunction>(
|
| - GetProcAddress(wlan_library, "WlanGetNetworkBssList"));
|
| + GetProcAddress(library_, "WlanGetNetworkBssList"));
|
| WlanFreeMemory_function_ = reinterpret_cast<WlanFreeMemoryFunction>(
|
| - GetProcAddress(wlan_library, "WlanFreeMemory"));
|
| + GetProcAddress(library_, "WlanFreeMemory"));
|
| WlanCloseHandle_function_ = reinterpret_cast<WlanCloseHandleFunction>(
|
| - GetProcAddress(wlan_library, "WlanCloseHandle"));
|
| + GetProcAddress(library_, "WlanCloseHandle"));
|
| +
|
| DCHECK(WlanOpenHandle_function_ && WlanEnumInterfaces_function_ &&
|
| WlanGetNetworkBssList_function_ && WlanFreeMemory_function_ &&
|
| WlanCloseHandle_function_);
|
| }
|
|
|
| +WindowsWlanApi::~WindowsWlanApi() {
|
| + FreeLibrary(library_);
|
| +}
|
| +
|
| +// static
|
| void WindowsWlanApi::LogWlanInterfaceCount(int count) {
|
| - UMA_HISTOGRAM_CUSTOM_COUNTS("Net.Wifi.InterfaceCount", count, 1, 5, 6);
|
| + UMA_HISTOGRAM_CUSTOM_COUNTS("Net.Wifi.InterfaceCount", count, 1 /* min */,
|
| + 5 /* max */, 6 /* bucket_count */);
|
| }
|
|
|
| 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!
|
| + HANDLE wlan_handle = nullptr;
|
| + // Highest WLAN API version supported by the client; pass the lowest. It seems
|
| + // that the negotiated version is the Vista version (the highest) irrespective
|
| + // of what we pass!
|
| static const int kXpWlanClientVersion = 1;
|
| if ((*WlanOpenHandle_function_)(kXpWlanClientVersion, NULL,
|
| &negotiated_version,
|
| @@ -251,8 +167,8 @@ bool WindowsWlanApi::GetAccessPointData(WifiData::AccessPointDataSet* data) {
|
| }
|
| DCHECK(wlan_handle);
|
|
|
| - // Get the list of interfaces. WlanEnumInterfaces allocates interface_list.
|
| - WLAN_INTERFACE_INFO_LIST* interface_list = NULL;
|
| + // Get the list of interfaces. WlanEnumInterfaces allocates |interface_list|.
|
| + WLAN_INTERFACE_INFO_LIST* interface_list = nullptr;
|
| if ((*WlanEnumInterfaces_function_)(wlan_handle, NULL, &interface_list) !=
|
| ERROR_SUCCESS) {
|
| LogWlanInterfaceCount(0);
|
| @@ -263,324 +179,78 @@ bool WindowsWlanApi::GetAccessPointData(WifiData::AccessPointDataSet* data) {
|
| 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) {
|
| + for (size_t i = 0; i < interface_list->dwNumberOfItems; ++i) {
|
| + const WLAN_INTERFACE_INFO interface_info = interface_list->InterfaceInfo[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.";
|
| + // when it's in this state. https://crbug.com/39300
|
| + if (interface_info.isState == wlan_interface_state_associating) {
|
| + DLOG(WARNING) << "Skipping wifi scan on adapter " << i << " ("
|
| + << interface_info.strInterfaceDescription
|
| + << ") in 'associating' state. Repeated occurrences "
|
| + "indicates a non-responding adapter.";
|
| continue;
|
| }
|
| - GetInterfaceDataWLAN(wlan_handle,
|
| - interface_list->InterfaceInfo[i].InterfaceGuid, data);
|
| + GetInterfaceDataWLAN(wlan_handle, interface_info.InterfaceGuid, data);
|
| }
|
|
|
| - // Free interface_list.
|
| (*WlanFreeMemory_function_)(interface_list);
|
|
|
| - // Close the handle.
|
| - if ((*WlanCloseHandle_function_)(wlan_handle, NULL) != ERROR_SUCCESS) {
|
| - return false;
|
| - }
|
| -
|
| - return true;
|
| + return (*WlanCloseHandle_function_)(wlan_handle, NULL) == ERROR_SUCCESS;
|
| }
|
|
|
| -// 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;
|
| +// Appends the data for a single interface to |data|. Returns false for error.
|
| +bool WindowsWlanApi::GetInterfaceDataWLAN(const HANDLE wlan_handle,
|
| + const GUID& interface_id,
|
| + WifiData::AccessPointDataSet* data) {
|
| + base::ElapsedTimer wlan_get_network_list_timer;
|
| + // WlanGetNetworkBssList allocates |bss_list|.
|
| + WLAN_BSS_LIST* bss_list = nullptr;
|
| 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;
|
| + return false;
|
| }
|
| - // According to http://www.attnetclient.com/kb/questions.php?questionid=75
|
| - // WlanGetNetworkBssList can sometimes return success, but leave the bss
|
| - // list as NULL.
|
| + // WlanGetNetworkBssList() can return success without filling |bss_list|.
|
| if (!bss_list)
|
| - return -1;
|
| -
|
| - const base::TimeDelta duration = base::TimeTicks::Now() - start_time;
|
| + return false;
|
|
|
| - UMA_HISTOGRAM_CUSTOM_TIMES("Net.Wifi.ScanLatency", duration,
|
| + UMA_HISTOGRAM_CUSTOM_TIMES("Net.Wifi.ScanLatency",
|
| + wlan_get_network_list_timer.Elapsed(),
|
| 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);
|
| - }
|
| - }
|
| + for (size_t i = 0; i < bss_list->dwNumberOfItems; ++i)
|
| + data->insert(GetNetworkData(bss_list->wlanBssEntries[i]));
|
|
|
| (*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() {}
|
| -
|
| -std::unique_ptr<WindowsNdisApi> WindowsNdisApi::Create() {
|
| - std::vector<base::string16> interface_service_names;
|
| - if (GetInterfacesNDIS(&interface_service_names))
|
| - return base::MakeUnique<WindowsNdisApi>(&interface_service_names);
|
| - return nullptr;
|
| -}
|
| -
|
| -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)
|
| - 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;
|
| -}
|
| +} // anonymous namespace
|
|
|
| -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);
|
| +WifiDataProvider* WifiDataProviderManager::DefaultFactoryFunction() {
|
| + return new WifiDataProviderWin();
|
| }
|
|
|
| -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;
|
| -}
|
| +WifiDataProviderWin::WifiDataProviderWin() = default;
|
|
|
| -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;
|
| - }
|
| +WifiDataProviderWin::~WifiDataProviderWin() = default;
|
|
|
| - buffer->reset(
|
| - reinterpret_cast<BYTE*>(realloc(buffer->release(), requested_size)));
|
| - return buffer != NULL;
|
| +std::unique_ptr<WifiDataProviderCommon::WlanApiInterface>
|
| +WifiDataProviderWin::CreateWlanApi() {
|
| + return WindowsWlanApi::Create();
|
| }
|
|
|
| -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;
|
| +std::unique_ptr<WifiPollingPolicy> WifiDataProviderWin::CreatePollingPolicy() {
|
| + return base::MakeUnique<GenericWifiPollingPolicy<
|
| + kDefaultPollingIntervalMs, kNoChangePollingIntervalMs,
|
| + kTwoNoChangePollingIntervalMs, kNoWifiPollingIntervalMs>>();
|
| }
|
| -} // namespace
|
|
|
| } // namespace device
|
|
|