diff options
author | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
---|---|---|
committer | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
commit | 5f8de423f190bbb79a62f804151bc24824fa32d8 (patch) | |
tree | 10027f336435511475e392454359edea8e25895d /netwerk/wifi/win_wifiScanner.cpp | |
parent | 49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff) | |
download | UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip |
Add m-esr52 at 52.6.0
Diffstat (limited to 'netwerk/wifi/win_wifiScanner.cpp')
-rw-r--r-- | netwerk/wifi/win_wifiScanner.cpp | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/netwerk/wifi/win_wifiScanner.cpp b/netwerk/wifi/win_wifiScanner.cpp new file mode 100644 index 000000000..a462b9696 --- /dev/null +++ b/netwerk/wifi/win_wifiScanner.cpp @@ -0,0 +1,195 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsWifiAccessPoint.h" +#include "win_wifiScanner.h" + +// Moz headers (alphabetical) +#include "win_wlanLibrary.h" + +#define DOT11_BSS_TYPE_UNUSED static_cast<DOT11_BSS_TYPE>(0) + +class InterfaceScanCallbackData { +public: + InterfaceScanCallbackData(uint32_t numInterfaces) + : mCurrentlyScanningInterfaces(numInterfaces) + { + mAllInterfacesDoneScanningEvent = + ::CreateEvent(nullptr, // null security + TRUE, // manual reset event + FALSE, // initially nonsignaled + nullptr); // not named + MOZ_ASSERT(NULL != mAllInterfacesDoneScanningEvent); + } + + ~InterfaceScanCallbackData() + { + ::CloseHandle(mAllInterfacesDoneScanningEvent); + } + + void + OnInterfaceScanComplete() + { + uint32_t val = ::InterlockedDecrement(&mCurrentlyScanningInterfaces); + if (!val) { + ::SetEvent(mAllInterfacesDoneScanningEvent); + } + } + + void + WaitForAllInterfacesToFinishScanning(uint32_t msToWait) + { + ::WaitForSingleObject(mAllInterfacesDoneScanningEvent, + msToWait); + } + +private: + volatile uint32_t mCurrentlyScanningInterfaces; + HANDLE mAllInterfacesDoneScanningEvent; +}; + +static void +OnScanComplete(PWLAN_NOTIFICATION_DATA data, PVOID context) +{ + if (WLAN_NOTIFICATION_SOURCE_ACM != data->NotificationSource) { + return; + } + + if (wlan_notification_acm_scan_complete != data->NotificationCode && + wlan_notification_acm_scan_fail != data->NotificationCode) { + return; + } + + InterfaceScanCallbackData* cbData = + reinterpret_cast<InterfaceScanCallbackData*>(context); + cbData->OnInterfaceScanComplete(); +} + +WinWifiScanner::WinWifiScanner() +{ + // NOTE: We assume that, if we were unable to load the WLAN library when + // we initially tried, we will not be able to load it in the future. + // Technically, on Windows XP SP2, a user could install the redistributable + // and make our assumption incorrect. We opt to avoid making a bunch of + // spurious LoadLibrary calls in the common case rather than load the + // WLAN API in the edge case. + mWlanLibrary = WinWLANLibrary::Load(); + if (!mWlanLibrary) { + NS_WARNING("Could not initialize Windows Wi-Fi scanner"); + } +} + +WinWifiScanner::~WinWifiScanner() +{ +} + +nsresult +WinWifiScanner::GetAccessPointsFromWLAN(nsCOMArray<nsWifiAccessPoint> &accessPoints) +{ + accessPoints.Clear(); + + // NOTE: We do not try to load the WLAN library if we previously failed + // to load it. See the note in WinWifiScanner constructor + if (!mWlanLibrary) { + return NS_ERROR_NOT_AVAILABLE; + } + + // Get the list of interfaces. WlanEnumInterfaces allocates interface_list. + WLAN_INTERFACE_INFO_LIST *interface_list = nullptr; + if (ERROR_SUCCESS != + (*mWlanLibrary->GetWlanEnumInterfacesPtr())(mWlanLibrary->GetWLANHandle(), + nullptr, + &interface_list)) { + return NS_ERROR_FAILURE; + } + + // This ensures we call WlanFreeMemory on interface_list + ScopedWLANObject scopedInterfaceList(mWlanLibrary, interface_list); + + if (!interface_list->dwNumberOfItems) { + return NS_OK; + } + + InterfaceScanCallbackData cbData(interface_list->dwNumberOfItems); + + DWORD wlanNotifySource; + if (ERROR_SUCCESS != + (*mWlanLibrary->GetWlanRegisterNotificationPtr())( + mWlanLibrary->GetWLANHandle(), + WLAN_NOTIFICATION_SOURCE_ACM, + TRUE, + (WLAN_NOTIFICATION_CALLBACK)OnScanComplete, + &cbData, + NULL, + &wlanNotifySource)) { + return NS_ERROR_FAILURE; + } + + // Go through the list of interfaces and call `WlanScan` on each + for (unsigned int i = 0; i < interface_list->dwNumberOfItems; ++i) { + if (ERROR_SUCCESS != + (*mWlanLibrary->GetWlanScanPtr())( + mWlanLibrary->GetWLANHandle(), + &interface_list->InterfaceInfo[i].InterfaceGuid, + NULL, + NULL, + NULL)) { + cbData.OnInterfaceScanComplete(); + } + } + + // From the MSDN documentation: + // "Wireless network drivers that meet Windows logo requirements are + // required to complete a WlanScan function request in 4 seconds" + cbData.WaitForAllInterfacesToFinishScanning(5000); + + // Unregister for the notifications. The documentation mentions that, + // if a callback is currently running, this will wait for the callback + // to complete. + (*mWlanLibrary->GetWlanRegisterNotificationPtr())( + mWlanLibrary->GetWLANHandle(), + WLAN_NOTIFICATION_SOURCE_NONE, + TRUE, + NULL, + NULL, + NULL, + &wlanNotifySource); + + // Go through the list of interfaces and get the data for each. + for (uint32_t i = 0; i < interface_list->dwNumberOfItems; ++i) { + WLAN_BSS_LIST *bss_list; + if (ERROR_SUCCESS != + (*mWlanLibrary->GetWlanGetNetworkBssListPtr())( + mWlanLibrary->GetWLANHandle(), + &interface_list->InterfaceInfo[i].InterfaceGuid, + nullptr, // Use all SSIDs. + DOT11_BSS_TYPE_UNUSED, + false, // bSecurityEnabled - unused + nullptr, // reserved + &bss_list)) { + continue; + } + + // This ensures we call WlanFreeMemory on bss_list + ScopedWLANObject scopedBssList(mWlanLibrary, bss_list); + + // Store each discovered access point in our outparam + for (int j = 0; j < static_cast<int>(bss_list->dwNumberOfItems); ++j) { + nsWifiAccessPoint* ap = new nsWifiAccessPoint(); + if (!ap) { + continue; + } + + const WLAN_BSS_ENTRY bss_entry = bss_list->wlanBssEntries[j]; + ap->setMac(bss_entry.dot11Bssid); + ap->setSignal(bss_entry.lRssi); + ap->setSSID(reinterpret_cast<char const*>(bss_entry.dot11Ssid.ucSSID), + bss_entry.dot11Ssid.uSSIDLength); + + accessPoints.AppendObject(ap); + } + } + + return NS_OK; +} |