Skip to content

Commit fb46bd1

Browse files
committed
[WLANWIZ] Rewrite network scan procedure, again
Making our loops a bit less frequent thing. We are operating indexes at this point and cue ones that might be our point of interest, like index of currently connected network.
1 parent 7807185 commit fb46bd1

File tree

1 file changed

+54
-36
lines changed

1 file changed

+54
-36
lines changed

dll/shellext/wlanwiz/scan.cpp

Lines changed: 54 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,16 @@
22
* PROJECT: ReactOS Shell
33
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
44
* PURPOSE: ReactOS Wizard for Wireless Network Connections (WLAN Scanning Routines)
5-
* COPYRIGHT: Copyright 2024 Vitaly Orekhov <[email protected]>
5+
* COPYRIGHT: Copyright 2024-2025 Vitaly Orekhov <[email protected]>
66
*/
77

88
#include "main.h"
99

10+
#include <algorithm>
11+
#include <numeric>
12+
#include <set>
1013
#include <string>
11-
#include <unordered_set>
14+
#include <vector>
1215

1316
LRESULT CWlanWizard::OnScanNetworks(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
1417
{
@@ -88,23 +91,57 @@ LRESULT CWlanWizard::OnScanNetworks(WORD wNotifyCode, WORD wID, HWND hWndCtl, BO
8891
m_SidebarButtonAS.EnableWindow();
8992
m_SidebarButtonSN.EnableWindow();
9093

91-
/*
92-
* WIP: Single pass sorting of discovered networks.
93-
* TODO: Restore ad-hoc network positioning in the end of the list.
94-
*/
94+
DPRINT("Discovered %lu access points\n", this->lstWlanNetworks->dwNumberOfItems);
95+
9596
if (this->lstWlanNetworks->dwNumberOfItems > 0)
9697
{
97-
/* Add discovered networks to listbox and sort networks by signal level */
98-
std::unordered_set<std::wstring_view> ucAPsWithProfiles;
99-
WLAN_SIGNAL_QUALITY ulPrevSignalQuality = 0, ulWorstSignalQuality = 100;
100-
101-
for (;
102-
this->lstWlanNetworks->dwIndex <= this->lstWlanNetworks->dwNumberOfItems - 1;
103-
++this->lstWlanNetworks->dwIndex)
98+
auto vecIndexesBySignalQuality = std::vector<DWORD>(this->lstWlanNetworks->dwNumberOfItems);
99+
DWORD dwConnectedTo = MAXDWORD;
100+
std::set<DWORD> setDiscoveredAdHocIndexes;
101+
std::iota(vecIndexesBySignalQuality.begin(), vecIndexesBySignalQuality.end(), 0);
102+
103+
/* Sort networks by signal level */
104+
std::sort(vecIndexesBySignalQuality.begin(), vecIndexesBySignalQuality.end(), [&](DWORD left, DWORD right)
105+
{
106+
WLAN_AVAILABLE_NETWORK wlanLeft = this->lstWlanNetworks->Network[left];
107+
WLAN_AVAILABLE_NETWORK wlanRight = this->lstWlanNetworks->Network[right];
108+
109+
if (wlanLeft.dot11BssType == dot11_BSS_type_independent)
110+
setDiscoveredAdHocIndexes.insert(left);
111+
112+
if (wlanLeft.dwFlags & WLAN_AVAILABLE_NETWORK_CONNECTED)
113+
dwConnectedTo = left;
114+
115+
return wlanLeft.wlanSignalQuality > wlanRight.wlanSignalQuality;
116+
});
117+
118+
/* Shift all ad hoc networks to end */
119+
if (setDiscoveredAdHocIndexes.size() > 0)
104120
{
105-
WLAN_AVAILABLE_NETWORK wlanNetwork = this->lstWlanNetworks->Network[this->lstWlanNetworks->dwIndex];
121+
for (const auto& dwAdHocIdx : setDiscoveredAdHocIndexes)
122+
{
123+
auto iter = std::find(vecIndexesBySignalQuality.begin(), vecIndexesBySignalQuality.end(), dwAdHocIdx);
124+
125+
if (iter != vecIndexesBySignalQuality.end())
126+
{
127+
auto idx = iter - vecIndexesBySignalQuality.begin();
128+
std::rotate(vecIndexesBySignalQuality.begin() + idx, vecIndexesBySignalQuality.begin() + idx + 1, vecIndexesBySignalQuality.end());
129+
}
130+
}
131+
}
132+
133+
/* Finally, move currently connected network to beginning */
134+
if (dwConnectedTo != MAXDWORD)
135+
{
136+
auto connectedIdx = std::find(vecIndexesBySignalQuality.begin(), vecIndexesBySignalQuality.end(), dwConnectedTo) - vecIndexesBySignalQuality.begin();
137+
std::rotate(vecIndexesBySignalQuality.begin() + connectedIdx, vecIndexesBySignalQuality.begin() + connectedIdx + 1, vecIndexesBySignalQuality.end());
138+
}
139+
140+
/* TODO: remove networks that do not have a saved profile matching the SSID */
141+
for (const auto& dwNetwork : vecIndexesBySignalQuality)
142+
{
143+
WLAN_AVAILABLE_NETWORK wlanNetwork = this->lstWlanNetworks->Network[dwNetwork];
106144
std::wstring_view wsvSSID;
107-
int iInsertAt = -1;
108145

109146
// Convert SSID from UTF-8 to UTF-16
110147
int iSSIDLengthWide = MultiByteToWideChar(CP_UTF8, 0, reinterpret_cast<LPCSTR>(wlanNetwork.dot11Ssid.ucSSID), wlanNetwork.dot11Ssid.uSSIDLength, NULL, 0);
@@ -113,35 +150,16 @@ LRESULT CWlanWizard::OnScanNetworks(WORD wNotifyCode, WORD wID, HWND hWndCtl, BO
113150
MultiByteToWideChar(CP_UTF8, 0, reinterpret_cast<LPCSTR>(wlanNetwork.dot11Ssid.ucSSID), wlanNetwork.dot11Ssid.uSSIDLength, cswSSID.GetBuffer(), iSSIDLengthWide);
114151
wsvSSID = std::wstring_view(cswSSID.GetBuffer());
115152

116-
// TODO: filter access points by profile
117-
if (ucAPsWithProfiles.find(wsvSSID) != ucAPsWithProfiles.end())
118-
continue;
119-
120-
/* This allows discarding duplicated entries that with APs we had already connected earlier */
121-
if (wlanNetwork.dwFlags & WLAN_AVAILABLE_NETWORK_HAS_PROFILE)
122-
ucAPsWithProfiles.emplace(wsvSSID);
123-
124-
/* Sort by descending signal order */
125-
if (this->lstWlanNetworks->dwIndex == 0 || wlanNetwork.wlanSignalQuality > ulPrevSignalQuality)
126-
iInsertAt = 0;
127-
else if (wlanNetwork.wlanSignalQuality < ulPrevSignalQuality)
128-
iInsertAt = 1;
129-
130153
if (cswSSID.IsEmpty())
131154
cswSSID.LoadStringW(IDS_WLANWIZ_HIDDEN_NETWORK);
132155

133156
LRESULT iItemIdx = m_ListboxWLAN.SendMessageW(LB_INSERTSTRING,
134-
iInsertAt,
157+
-1,
135158
reinterpret_cast<LPARAM>(cswSSID.GetBuffer()));
136159

137160
m_ListboxWLAN.SendMessageW(LB_SETITEMDATA,
138161
iItemIdx,
139-
static_cast<LPARAM>(this->lstWlanNetworks->dwIndex));
140-
141-
ulPrevSignalQuality = wlanNetwork.wlanSignalQuality;
142-
143-
if (ulPrevSignalQuality < ulWorstSignalQuality)
144-
ulWorstSignalQuality = ulPrevSignalQuality;
162+
static_cast<LPARAM>(dwNetwork));
145163
}
146164
}
147165

0 commit comments

Comments
 (0)