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 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();
78 MOZ_ASSERT(mWlanLibrary
);
81 WinWifiScanner::~WinWifiScanner()
86 WinWifiScanner::GetAccessPointsFromWLAN(nsCOMArray
<nsWifiAccessPoint
> &accessPoints
)
90 // NOTE: We do not try to load the WLAN library if we previously failed
91 // to load it. See the note in WinWifiScanner constructor
93 return NS_ERROR_NOT_AVAILABLE
;
96 // Get the list of interfaces. WlanEnumInterfaces allocates interface_list.
97 WLAN_INTERFACE_INFO_LIST
*interface_list
= nullptr;
99 (*mWlanLibrary
->GetWlanEnumInterfacesPtr())(mWlanLibrary
->GetWLANHandle(),
102 return NS_ERROR_FAILURE
;
105 // This ensures we call WlanFreeMemory on interface_list
106 ScopedWLANObject
scopedInterfaceList(mWlanLibrary
, interface_list
);
108 if (!interface_list
->dwNumberOfItems
) {
112 InterfaceScanCallbackData
cbData(interface_list
->dwNumberOfItems
);
114 DWORD wlanNotifySource
;
116 (*mWlanLibrary
->GetWlanRegisterNotificationPtr())(
117 mWlanLibrary
->GetWLANHandle(),
118 WLAN_NOTIFICATION_SOURCE_ACM
,
120 (WLAN_NOTIFICATION_CALLBACK
)OnScanComplete
,
123 &wlanNotifySource
)) {
124 return NS_ERROR_FAILURE
;
127 // Go through the list of interfaces and call `WlanScan` on each
128 for (unsigned int i
= 0; i
< interface_list
->dwNumberOfItems
; ++i
) {
130 (*mWlanLibrary
->GetWlanScanPtr())(
131 mWlanLibrary
->GetWLANHandle(),
132 &interface_list
->InterfaceInfo
[i
].InterfaceGuid
,
136 cbData
.OnInterfaceScanComplete();
140 // From the MSDN documentation:
141 // "Wireless network drivers that meet Windows logo requirements are
142 // required to complete a WlanScan function request in 4 seconds"
143 cbData
.WaitForAllInterfacesToFinishScanning(5000);
145 // Unregister for the notifications. The documentation mentions that,
146 // if a callback is currently running, this will wait for the callback
148 (*mWlanLibrary
->GetWlanRegisterNotificationPtr())(
149 mWlanLibrary
->GetWLANHandle(),
150 WLAN_NOTIFICATION_SOURCE_NONE
,
157 // Go through the list of interfaces and get the data for each.
158 for (uint32_t i
= 0; i
< interface_list
->dwNumberOfItems
; ++i
) {
159 WLAN_BSS_LIST
*bss_list
;
161 (*mWlanLibrary
->GetWlanGetNetworkBssListPtr())(
162 mWlanLibrary
->GetWLANHandle(),
163 &interface_list
->InterfaceInfo
[i
].InterfaceGuid
,
164 nullptr, // Use all SSIDs.
165 DOT11_BSS_TYPE_UNUSED
,
166 false, // bSecurityEnabled - unused
172 // This ensures we call WlanFreeMemory on bss_list
173 ScopedWLANObject
scopedBssList(mWlanLibrary
, bss_list
);
175 // Store each discovered access point in our outparam
176 for (int j
= 0; j
< static_cast<int>(bss_list
->dwNumberOfItems
); ++j
) {
177 nsWifiAccessPoint
* ap
= new nsWifiAccessPoint();
182 const WLAN_BSS_ENTRY bss_entry
= bss_list
->wlanBssEntries
[j
];
183 ap
->setMac(bss_entry
.dot11Bssid
);
184 ap
->setSignal(bss_entry
.lRssi
);
185 ap
->setSSID(reinterpret_cast<char const*>(bss_entry
.dot11Ssid
.ucSSID
),
186 bss_entry
.dot11Ssid
.uSSIDLength
);
188 accessPoints
.AppendObject(ap
);