1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #include "nsWifiAccessPoint.h"
6 #include "win_wifiScanner.h"
8 // Moz headers (alphabetical)
9 #include "win_wlanLibrary.h"
11 #define DOT11_BSS_TYPE_UNUSED static_cast<DOT11_BSS_TYPE>(0)
13 class InterfaceScanCallbackData
{
15 explicit InterfaceScanCallbackData(uint32_t numInterfaces
)
16 : mCurrentlyScanningInterfaces(numInterfaces
)
18 mAllInterfacesDoneScanningEvent
=
19 ::CreateEvent(nullptr, // null security
20 TRUE
, // manual reset event
21 FALSE
, // initially nonsignaled
22 nullptr); // not named
23 MOZ_ASSERT(NULL
!= mAllInterfacesDoneScanningEvent
);
26 ~InterfaceScanCallbackData()
28 ::CloseHandle(mAllInterfacesDoneScanningEvent
);
32 OnInterfaceScanComplete()
34 uint32_t val
= ::InterlockedDecrement(&mCurrentlyScanningInterfaces
);
36 ::SetEvent(mAllInterfacesDoneScanningEvent
);
41 WaitForAllInterfacesToFinishScanning(uint32_t msToWait
)
43 ::WaitForSingleObject(mAllInterfacesDoneScanningEvent
,
48 volatile uint32_t mCurrentlyScanningInterfaces
;
49 HANDLE mAllInterfacesDoneScanningEvent
;
53 OnScanComplete(PWLAN_NOTIFICATION_DATA data
, PVOID context
)
55 if (WLAN_NOTIFICATION_SOURCE_ACM
!= data
->NotificationSource
) {
59 if (wlan_notification_acm_scan_complete
!= data
->NotificationCode
&&
60 wlan_notification_acm_scan_fail
!= data
->NotificationCode
) {
64 InterfaceScanCallbackData
* cbData
=
65 reinterpret_cast<InterfaceScanCallbackData
*>(context
);
66 cbData
->OnInterfaceScanComplete();
69 WinWifiScanner::WinWifiScanner()
71 // NOTE: We assume that, if we were unable to load the WLAN library when
72 // we initially tried, we will not be able to load it in the future.
73 // Technically, on Windows XP SP2, a user could install the redistributable
74 // and make our assumption incorrect. We opt to avoid making a bunch of
75 // spurious LoadLibrary calls in the common case rather than load the
76 // WLAN API in the edge case.
77 mWlanLibrary
= WinWLANLibrary::Load();
79 NS_WARNING("Could not initialize Windows Wi-Fi scanner");
83 WinWifiScanner::~WinWifiScanner()
88 WinWifiScanner::GetAccessPointsFromWLAN(nsCOMArray
<nsWifiAccessPoint
> &accessPoints
)
92 // NOTE: We do not try to load the WLAN library if we previously failed
93 // to load it. See the note in WinWifiScanner constructor
95 return NS_ERROR_NOT_AVAILABLE
;
98 // Get the list of interfaces. WlanEnumInterfaces allocates interface_list.
99 WLAN_INTERFACE_INFO_LIST
*interface_list
= nullptr;
101 (*mWlanLibrary
->GetWlanEnumInterfacesPtr())(mWlanLibrary
->GetWLANHandle(),
104 return NS_ERROR_FAILURE
;
107 // This ensures we call WlanFreeMemory on interface_list
108 ScopedWLANObject
scopedInterfaceList(mWlanLibrary
, interface_list
);
110 if (!interface_list
->dwNumberOfItems
) {
114 InterfaceScanCallbackData
cbData(interface_list
->dwNumberOfItems
);
116 DWORD wlanNotifySource
;
118 (*mWlanLibrary
->GetWlanRegisterNotificationPtr())(
119 mWlanLibrary
->GetWLANHandle(),
120 WLAN_NOTIFICATION_SOURCE_ACM
,
122 (WLAN_NOTIFICATION_CALLBACK
)OnScanComplete
,
125 &wlanNotifySource
)) {
126 return NS_ERROR_FAILURE
;
129 // Go through the list of interfaces and call `WlanScan` on each
130 for (unsigned int i
= 0; i
< interface_list
->dwNumberOfItems
; ++i
) {
132 (*mWlanLibrary
->GetWlanScanPtr())(
133 mWlanLibrary
->GetWLANHandle(),
134 &interface_list
->InterfaceInfo
[i
].InterfaceGuid
,
138 cbData
.OnInterfaceScanComplete();
142 // From the MSDN documentation:
143 // "Wireless network drivers that meet Windows logo requirements are
144 // required to complete a WlanScan function request in 4 seconds"
145 cbData
.WaitForAllInterfacesToFinishScanning(5000);
147 // Unregister for the notifications. The documentation mentions that,
148 // if a callback is currently running, this will wait for the callback
150 (*mWlanLibrary
->GetWlanRegisterNotificationPtr())(
151 mWlanLibrary
->GetWLANHandle(),
152 WLAN_NOTIFICATION_SOURCE_NONE
,
159 // Go through the list of interfaces and get the data for each.
160 for (uint32_t i
= 0; i
< interface_list
->dwNumberOfItems
; ++i
) {
161 WLAN_BSS_LIST
*bss_list
;
163 (*mWlanLibrary
->GetWlanGetNetworkBssListPtr())(
164 mWlanLibrary
->GetWLANHandle(),
165 &interface_list
->InterfaceInfo
[i
].InterfaceGuid
,
166 nullptr, // Use all SSIDs.
167 DOT11_BSS_TYPE_UNUSED
,
168 false, // bSecurityEnabled - unused
174 // This ensures we call WlanFreeMemory on bss_list
175 ScopedWLANObject
scopedBssList(mWlanLibrary
, bss_list
);
177 // Store each discovered access point in our outparam
178 for (int j
= 0; j
< static_cast<int>(bss_list
->dwNumberOfItems
); ++j
) {
179 nsWifiAccessPoint
* ap
= new nsWifiAccessPoint();
184 const WLAN_BSS_ENTRY bss_entry
= bss_list
->wlanBssEntries
[j
];
185 ap
->setMac(bss_entry
.dot11Bssid
);
186 ap
->setSignal(bss_entry
.lRssi
);
187 ap
->setSSID(reinterpret_cast<char const*>(bss_entry
.dot11Ssid
.ucSSID
),
188 bss_entry
.dot11Ssid
.uSSIDLength
);
190 accessPoints
.AppendObject(ap
);