|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the Qt Mobility Components. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 #include "qnativewifiengine_win_p.h" |
|
43 #include "qnetworkconfiguration_p.h" |
|
44 |
|
45 #include <QtCore/qmutex.h> |
|
46 #include <QtCore/private/qmutexpool_p.h> |
|
47 #include <QtCore/qlibrary.h> |
|
48 #include <QtCore/qstringlist.h> |
|
49 |
|
50 #include <QtCore/qdebug.h> |
|
51 |
|
52 #include <wtypes.h> |
|
53 #undef interface |
|
54 |
|
55 QTM_BEGIN_NAMESPACE |
|
56 |
|
57 Q_GLOBAL_STATIC(QNativeWifiEngine, nativeWifiEngine) |
|
58 |
|
59 #define WLAN_MAX_NAME_LENGTH 256 |
|
60 #define WLAN_MAX_PHY_TYPE_NUMBER 8 |
|
61 #define WLAN_NOTIFICATION_SOURCE_ALL 0x0000ffff |
|
62 #define WLAN_AVAILABLE_NETWORK_CONNECTED 1 |
|
63 #define WLAN_AVAILABLE_NETWORK_HAS_PROFILE 2 |
|
64 #define DOT11_SSID_MAX_LENGTH 32 |
|
65 |
|
66 struct WLAN_NOTIFICATION_DATA { |
|
67 DWORD NotificationSource; |
|
68 DWORD NotificationCode; |
|
69 GUID InterfaceGuid; |
|
70 DWORD dwDataSize; |
|
71 PVOID pData; |
|
72 }; |
|
73 |
|
74 enum WLAN_INTERFACE_STATE { |
|
75 wlan_interface_state_not_ready = 0, |
|
76 wlan_interface_state_connected, |
|
77 wlan_interface_state_ad_hoc_network_formed, |
|
78 wlan_interface_state_disconnecting, |
|
79 wlan_interface_state_disconnected, |
|
80 wlan_interface_state_associating, |
|
81 wlan_interface_state_discovering, |
|
82 wlan_interface_state_authenticating |
|
83 }; |
|
84 |
|
85 struct WLAN_INTERFACE_INFO { |
|
86 GUID InterfaceGuid; |
|
87 WCHAR strInterfaceDescription[WLAN_MAX_NAME_LENGTH]; |
|
88 WLAN_INTERFACE_STATE isState; |
|
89 }; |
|
90 |
|
91 struct WLAN_INTERFACE_INFO_LIST { |
|
92 DWORD dwNumberOfItems; |
|
93 DWORD dwIndex; |
|
94 WLAN_INTERFACE_INFO InterfaceInfo[1]; |
|
95 }; |
|
96 |
|
97 struct DOT11_SSID { |
|
98 ULONG uSSIDLength; |
|
99 UCHAR ucSSID[DOT11_SSID_MAX_LENGTH]; |
|
100 }; |
|
101 |
|
102 struct NDIS_OBJECT_HEADER { |
|
103 UCHAR Type; |
|
104 UCHAR Revision; |
|
105 USHORT Size; |
|
106 }; |
|
107 |
|
108 typedef UCHAR DOT11_MAC_ADDRESS[6]; |
|
109 struct DOT11_BSSID_LIST { |
|
110 NDIS_OBJECT_HEADER Header; |
|
111 ULONG uNumberOfEntries; |
|
112 ULONG uTotalNumOfEntries; |
|
113 DOT11_MAC_ADDRESS BSSIDs[1]; |
|
114 }; |
|
115 |
|
116 enum DOT11_BSS_TYPE { |
|
117 dot11_BSS_type_infrastructure = 1, |
|
118 dot11_BSS_type_independent = 2, |
|
119 dot11_BSS_type_any = 3 |
|
120 }; |
|
121 |
|
122 enum DOT11_PHY_TYPE { |
|
123 dot11_phy_type_unknown = 0, |
|
124 dot11_phy_type_any = dot11_phy_type_unknown, |
|
125 dot11_phy_type_fhss = 1, |
|
126 dot11_phy_type_dsss = 2, |
|
127 dot11_phy_type_irbaseband = 3, |
|
128 dot11_phy_type_ofdm = 4, |
|
129 dot11_phy_type_hrdsss = 5, |
|
130 dot11_phy_type_erp = 6, |
|
131 dot11_phy_type_ht = 7, |
|
132 dot11_phy_type_IHV_start = 0x80000000, |
|
133 dot11_phy_type_IHV_end = 0xffffffff |
|
134 }; |
|
135 |
|
136 enum DOT11_AUTH_ALGORITHM { |
|
137 DOT11_AUTH_ALGO_80211_OPEN = 1, |
|
138 DOT11_AUTH_ALGO_80211_SHARED_KEY = 2, |
|
139 DOT11_AUTH_ALGO_WPA = 3, |
|
140 DOT11_AUTH_ALGO_WPA_PSK = 4, |
|
141 DOT11_AUTH_ALGO_WPA_NONE = 5, |
|
142 DOT11_AUTH_ALGO_RSNA = 6, |
|
143 DOT11_AUTH_ALGO_RSNA_PSK = 7, |
|
144 DOT11_AUTH_ALGO_IHV_START = 0x80000000, |
|
145 DOT11_AUTH_ALGO_IHV_END = 0xffffffff |
|
146 }; |
|
147 |
|
148 enum DOT11_CIPHER_ALGORITHM { |
|
149 DOT11_CIPHER_ALGO_NONE = 0x00, |
|
150 DOT11_CIPHER_ALGO_WEP40 = 0x01, |
|
151 DOT11_CIPHER_ALGO_TKIP = 0x02, |
|
152 DOT11_CIPHER_ALGO_CCMP = 0x04, |
|
153 DOT11_CIPHER_ALGO_WEP104 = 0x05, |
|
154 DOT11_CIPHER_ALGO_WPA_USE_GROUP = 0x100, |
|
155 DOT11_CIPHER_ALGO_RSN_USE_GROUP = 0x100, |
|
156 DOT11_CIPHER_ALGO_WEP = 0x101, |
|
157 DOT11_CIPHER_ALGO_IHV_START = 0x80000000, |
|
158 DOT11_CIPHER_ALGO_IHV_END = 0xffffffff |
|
159 }; |
|
160 |
|
161 struct WLAN_AVAILABLE_NETWORK { |
|
162 WCHAR strProfileName[WLAN_MAX_NAME_LENGTH]; |
|
163 DOT11_SSID dot11Ssid; |
|
164 DOT11_BSS_TYPE dot11BssType; |
|
165 ULONG uNumberOfBssids; |
|
166 BOOL bNetworkConnectable; |
|
167 DWORD wlanNotConnectableReason; |
|
168 ULONG uNumberOfPhyTypes; |
|
169 DOT11_PHY_TYPE dot11PhyTypes[WLAN_MAX_PHY_TYPE_NUMBER]; |
|
170 BOOL bMorePhyTypes; |
|
171 ULONG wlanSignalQuality; |
|
172 BOOL bSecurityEnabled; |
|
173 DOT11_AUTH_ALGORITHM dot11DefaultAuthAlgorithm; |
|
174 DOT11_CIPHER_ALGORITHM dot11DefaultCipherAlgorithm; |
|
175 DWORD dwFlags; |
|
176 DWORD dwReserved; |
|
177 }; |
|
178 |
|
179 struct WLAN_AVAILABLE_NETWORK_LIST { |
|
180 DWORD dwNumberOfItems; |
|
181 DWORD dwIndex; |
|
182 WLAN_AVAILABLE_NETWORK Network[1]; |
|
183 }; |
|
184 |
|
185 enum WLAN_INTF_OPCODE { |
|
186 wlan_intf_opcode_autoconf_start = 0x000000000, |
|
187 wlan_intf_opcode_autoconf_enabled, |
|
188 wlan_intf_opcode_background_scan_enabled, |
|
189 wlan_intf_opcode_media_streaming_mode, |
|
190 wlan_intf_opcode_radio_state, |
|
191 wlan_intf_opcode_bss_type, |
|
192 wlan_intf_opcode_interface_state, |
|
193 wlan_intf_opcode_current_connection, |
|
194 wlan_intf_opcode_channel_number, |
|
195 wlan_intf_opcode_supported_infrastructure_auth_cipher_pairs, |
|
196 wlan_intf_opcode_supported_adhoc_auth_cipher_pairs, |
|
197 wlan_intf_opcode_supported_country_or_region_string_list, |
|
198 wlan_intf_opcode_current_operation_mode, |
|
199 wlan_intf_opcode_supported_safe_mode, |
|
200 wlan_intf_opcode_certified_safe_mode, |
|
201 wlan_intf_opcode_autoconf_end = 0x0fffffff, |
|
202 wlan_intf_opcode_msm_start = 0x10000100, |
|
203 wlan_intf_opcode_statistics, |
|
204 wlan_intf_opcode_rssi, |
|
205 wlan_intf_opcode_msm_end = 0x1fffffff, |
|
206 wlan_intf_opcode_security_start = 0x20010000, |
|
207 wlan_intf_opcode_security_end = 0x2fffffff, |
|
208 wlan_intf_opcode_ihv_start = 0x30000000, |
|
209 wlan_intf_opcode_ihv_end = 0x3fffffff |
|
210 }; |
|
211 |
|
212 enum WLAN_OPCODE_VALUE_TYPE { |
|
213 wlan_opcode_value_type_query_only = 0, |
|
214 wlan_opcode_value_type_set_by_group_policy, |
|
215 wlan_opcode_value_type_set_by_user, |
|
216 wlan_opcode_value_type_invalid |
|
217 }; |
|
218 |
|
219 enum WLAN_CONNECTION_MODE { |
|
220 wlan_connection_mode_profile = 0, |
|
221 wlan_connection_mode_temporary_profile, |
|
222 wlan_connection_mode_discovery_secure, |
|
223 wlan_connection_mode_discovery_unsecure, |
|
224 wlan_connection_mode_auto, |
|
225 wlan_connection_mode_invalid |
|
226 }; |
|
227 |
|
228 struct WLAN_CONNECTION_PARAMETERS { |
|
229 WLAN_CONNECTION_MODE wlanConnectionMode; |
|
230 LPCWSTR strProfile; |
|
231 DOT11_SSID *pDot11Ssid; |
|
232 DOT11_BSSID_LIST *pDesiredBssidList; |
|
233 DOT11_BSS_TYPE dot11BssType; |
|
234 DWORD dwFlags; |
|
235 }; |
|
236 |
|
237 struct WLAN_RAW_DATA { |
|
238 DWORD dwDataSize; |
|
239 BYTE DataBlob[1]; |
|
240 }; |
|
241 |
|
242 enum WLAN_NOTIFICATION_ACM { |
|
243 wlan_notification_acm_start = 0, |
|
244 wlan_notification_acm_autoconf_enabled, |
|
245 wlan_notification_acm_autoconf_disabled, |
|
246 wlan_notification_acm_background_scan_enabled, |
|
247 wlan_notification_acm_background_scan_disabled, |
|
248 wlan_notification_acm_bss_type_change, |
|
249 wlan_notification_acm_power_setting_change, |
|
250 wlan_notification_acm_scan_complete, |
|
251 wlan_notification_acm_scan_fail, |
|
252 wlan_notification_acm_connection_start, |
|
253 wlan_notification_acm_connection_complete, |
|
254 wlan_notification_acm_connection_attempt_fail, |
|
255 wlan_notification_acm_filter_list_change, |
|
256 wlan_notification_acm_interface_arrival, |
|
257 wlan_notification_acm_interface_removal, |
|
258 wlan_notification_acm_profile_change, |
|
259 wlan_notification_acm_profile_name_change, |
|
260 wlan_notification_acm_profiles_exhausted, |
|
261 wlan_notification_acm_network_not_available, |
|
262 wlan_notification_acm_network_available, |
|
263 wlan_notification_acm_disconnecting, |
|
264 wlan_notification_acm_disconnected, |
|
265 wlan_notification_acm_adhoc_network_state_change, |
|
266 wlan_notification_acm_end |
|
267 }; |
|
268 |
|
269 struct WLAN_ASSOCIATION_ATTRIBUTES { |
|
270 DOT11_SSID dot11Ssid; |
|
271 DOT11_BSS_TYPE dot11BssType; |
|
272 DOT11_MAC_ADDRESS dot11Bssid; |
|
273 DOT11_PHY_TYPE dot11PhyType; |
|
274 ULONG uDot11PhyIndex; |
|
275 ULONG wlanSignalQuality; |
|
276 ULONG ulRxRate; |
|
277 ULONG ulTxRate; |
|
278 }; |
|
279 |
|
280 struct WLAN_SECURITY_ATTRIBUTES { |
|
281 BOOL bSecurityEnabled; |
|
282 BOOL bOneXEnabled; |
|
283 DOT11_AUTH_ALGORITHM dot11AuthAlgorithm; |
|
284 DOT11_CIPHER_ALGORITHM dot11CipherAlgorithm; |
|
285 }; |
|
286 |
|
287 struct WLAN_CONNECTION_ATTRIBUTES { |
|
288 WLAN_INTERFACE_STATE isState; |
|
289 WLAN_CONNECTION_MODE wlanConnectionMode; |
|
290 WCHAR strProfileName[WLAN_MAX_NAME_LENGTH]; |
|
291 WLAN_ASSOCIATION_ATTRIBUTES wlanAssociationAttributes; |
|
292 WLAN_SECURITY_ATTRIBUTES wlanSecurityAttributes; |
|
293 }; |
|
294 |
|
295 typedef void (WINAPI *WLAN_NOTIFICATION_CALLBACK)(WLAN_NOTIFICATION_DATA *, PVOID); |
|
296 |
|
297 typedef DWORD (WINAPI *WlanOpenHandleProto) |
|
298 (DWORD dwClientVersion, PVOID pReserved, PDWORD pdwNegotiatedVersion, PHANDLE phClientHandle); |
|
299 typedef DWORD (WINAPI *WlanRegisterNotificationProto) |
|
300 (HANDLE hClientHandle, DWORD dwNotifSource, BOOL bIgnoreDuplicate, |
|
301 WLAN_NOTIFICATION_CALLBACK funcCallback, PVOID pCallbackContext, |
|
302 PVOID pReserved, PDWORD pdwPrevNotifSource); |
|
303 typedef DWORD (WINAPI *WlanEnumInterfacesProto) |
|
304 (HANDLE hClientHandle, PVOID pReserved, WLAN_INTERFACE_INFO_LIST **ppInterfaceList); |
|
305 typedef DWORD (WINAPI *WlanGetAvailableNetworkListProto) |
|
306 (HANDLE hClientHandle, const GUID* pInterfaceGuid, DWORD dwFlags, PVOID pReserved, |
|
307 WLAN_AVAILABLE_NETWORK_LIST **ppAvailableNetworkList); |
|
308 typedef DWORD (WINAPI *WlanQueryInterfaceProto) |
|
309 (HANDLE hClientHandle, const GUID *pInterfaceGuid, WLAN_INTF_OPCODE OpCode, PVOID pReserved, |
|
310 PDWORD pdwDataSize, PVOID *ppData, WLAN_OPCODE_VALUE_TYPE *pWlanOpcodeValueType); |
|
311 typedef DWORD (WINAPI *WlanConnectProto) |
|
312 (HANDLE hClientHandle, const GUID *pInterfaceGuid, |
|
313 const WLAN_CONNECTION_PARAMETERS *pConnectionParameters, PVOID pReserved); |
|
314 typedef DWORD (WINAPI *WlanDisconnectProto) |
|
315 (HANDLE hClientHandle, const GUID *pInterfaceGuid, PVOID pReserved); |
|
316 typedef DWORD (WINAPI *WlanScanProto) |
|
317 (HANDLE hClientHandle, const GUID *pInterfaceGuid, const DOT11_SSID *pDot11Ssid, |
|
318 const WLAN_RAW_DATA *pIeData, PVOID pReserved); |
|
319 typedef VOID (WINAPI *WlanFreeMemoryProto)(PVOID pMemory); |
|
320 typedef DWORD (WINAPI *WlanCloseHandleProto)(HANDLE hClientHandle, PVOID pReserved); |
|
321 |
|
322 static WlanOpenHandleProto local_WlanOpenHandle = 0; |
|
323 static WlanRegisterNotificationProto local_WlanRegisterNotification = 0; |
|
324 static WlanEnumInterfacesProto local_WlanEnumInterfaces = 0; |
|
325 static WlanGetAvailableNetworkListProto local_WlanGetAvailableNetworkList = 0; |
|
326 static WlanQueryInterfaceProto local_WlanQueryInterface = 0; |
|
327 static WlanConnectProto local_WlanConnect = 0; |
|
328 static WlanDisconnectProto local_WlanDisconnect = 0; |
|
329 static WlanScanProto local_WlanScan = 0; |
|
330 static WlanFreeMemoryProto local_WlanFreeMemory = 0; |
|
331 static WlanCloseHandleProto local_WlanCloseHandle = 0; |
|
332 |
|
333 static void resolveLibrary() |
|
334 { |
|
335 static volatile bool triedResolve = false; |
|
336 |
|
337 if (!triedResolve) { |
|
338 #ifndef QT_NO_THREAD |
|
339 QMutexLocker locker(QMutexPool::globalInstanceGet(&local_WlanOpenHandle)); |
|
340 #endif |
|
341 |
|
342 if (!triedResolve) { |
|
343 local_WlanOpenHandle = (WlanOpenHandleProto) |
|
344 QLibrary::resolve(QLatin1String("wlanapi.dll"), "WlanOpenHandle"); |
|
345 local_WlanRegisterNotification = (WlanRegisterNotificationProto) |
|
346 QLibrary::resolve(QLatin1String("wlanapi.dll"), "WlanRegisterNotification"); |
|
347 local_WlanEnumInterfaces = (WlanEnumInterfacesProto) |
|
348 QLibrary::resolve(QLatin1String("wlanapi.dll"), "WlanEnumInterfaces"); |
|
349 local_WlanGetAvailableNetworkList = (WlanGetAvailableNetworkListProto) |
|
350 QLibrary::resolve(QLatin1String("wlanapi.dll"), "WlanGetAvailableNetworkList"); |
|
351 local_WlanQueryInterface = (WlanQueryInterfaceProto) |
|
352 QLibrary::resolve(QLatin1String("wlanapi.dll"), "WlanQueryInterface"); |
|
353 local_WlanConnect = (WlanConnectProto) |
|
354 QLibrary::resolve(QLatin1String("wlanapi.dll"), "WlanConnect"); |
|
355 local_WlanDisconnect = (WlanDisconnectProto) |
|
356 QLibrary::resolve(QLatin1String("wlanapi.dll"), "WlanDisconnect"); |
|
357 local_WlanScan = (WlanScanProto) |
|
358 QLibrary::resolve(QLatin1String("wlanapi.dll"), "WlanScan"); |
|
359 local_WlanFreeMemory = (WlanFreeMemoryProto) |
|
360 QLibrary::resolve(QLatin1String("wlanapi.dll"), "WlanFreeMemory"); |
|
361 local_WlanCloseHandle = (WlanCloseHandleProto) |
|
362 QLibrary::resolve(QLatin1String("wlanapi.dll"), "WlanCloseHandle"); |
|
363 |
|
364 triedResolve = true; |
|
365 } |
|
366 } |
|
367 } |
|
368 |
|
369 void qNotificationCallback(WLAN_NOTIFICATION_DATA *data, QNativeWifiEngine *d) |
|
370 { |
|
371 Q_UNUSED(d); |
|
372 |
|
373 switch (data->NotificationCode) { |
|
374 case wlan_notification_acm_connection_complete: |
|
375 case wlan_notification_acm_disconnected: |
|
376 d->emitConfigurationsChanged(); |
|
377 break; |
|
378 default: |
|
379 qDebug() << "wlan unknown notification"; |
|
380 } |
|
381 } |
|
382 |
|
383 QNativeWifiEngine::QNativeWifiEngine(QObject *parent) |
|
384 : QNetworkSessionEngine(parent), handle(0) |
|
385 { |
|
386 DWORD clientVersion; |
|
387 |
|
388 DWORD result = local_WlanOpenHandle(1, 0, &clientVersion, &handle); |
|
389 if (result != ERROR_SUCCESS) { |
|
390 if (result != ERROR_SERVICE_NOT_ACTIVE) |
|
391 qWarning("%s: WlanOpenHandle failed with error %ld\n", __FUNCTION__, result); |
|
392 |
|
393 return; |
|
394 } |
|
395 |
|
396 result = local_WlanRegisterNotification(handle, WLAN_NOTIFICATION_SOURCE_ALL, true, |
|
397 WLAN_NOTIFICATION_CALLBACK(qNotificationCallback), |
|
398 this, 0, 0); |
|
399 if (result != ERROR_SUCCESS) |
|
400 qWarning("%s: WlanRegisterNotification failed with error %ld\n", __FUNCTION__, result); |
|
401 |
|
402 // On Windows XP SP2 and SP3 only connection and disconnection notifications are available. |
|
403 // We need to poll for changes in available wireless networks. |
|
404 connect(&pollTimer, SIGNAL(timeout()), this, SIGNAL(configurationsChanged())); |
|
405 pollTimer.setInterval(10000); |
|
406 } |
|
407 |
|
408 QNativeWifiEngine::~QNativeWifiEngine() |
|
409 { |
|
410 local_WlanCloseHandle(handle, 0); |
|
411 } |
|
412 |
|
413 QList<QNetworkConfigurationPrivate *> QNativeWifiEngine::getConfigurations(bool *ok) |
|
414 { |
|
415 if (ok) |
|
416 *ok = false; |
|
417 |
|
418 QList<QNetworkConfigurationPrivate *> foundConfigurations; |
|
419 |
|
420 // enumerate interfaces |
|
421 WLAN_INTERFACE_INFO_LIST *interfaceList; |
|
422 DWORD result = local_WlanEnumInterfaces(handle, 0, &interfaceList); |
|
423 if (result != ERROR_SUCCESS) { |
|
424 qWarning("%s: WlanEnumInterfaces failed with error %ld\n", __FUNCTION__, result); |
|
425 return foundConfigurations; |
|
426 } |
|
427 |
|
428 for (unsigned int i = 0; i < interfaceList->dwNumberOfItems; ++i) { |
|
429 const WLAN_INTERFACE_INFO &interface = interfaceList->InterfaceInfo[i]; |
|
430 |
|
431 WLAN_AVAILABLE_NETWORK_LIST *networkList; |
|
432 result = local_WlanGetAvailableNetworkList(handle, &interface.InterfaceGuid, |
|
433 3, 0, &networkList); |
|
434 if (result != ERROR_SUCCESS) { |
|
435 qWarning("%s: WlanGetAvailableNetworkList failed with error %ld\n", |
|
436 __FUNCTION__, result); |
|
437 continue; |
|
438 } |
|
439 |
|
440 QStringList seenNetworks; |
|
441 |
|
442 for (unsigned int j = 0; j < networkList->dwNumberOfItems; ++j) { |
|
443 WLAN_AVAILABLE_NETWORK &network = networkList->Network[j]; |
|
444 |
|
445 QString networkName; |
|
446 |
|
447 if (network.strProfileName[0] != 0) { |
|
448 networkName = QString::fromWCharArray(network.strProfileName); |
|
449 } else { |
|
450 networkName = QByteArray(reinterpret_cast<char *>(network.dot11Ssid.ucSSID), |
|
451 network.dot11Ssid.uSSIDLength); |
|
452 } |
|
453 |
|
454 // don't add duplicate networks |
|
455 if (seenNetworks.contains(networkName)) |
|
456 continue; |
|
457 else |
|
458 seenNetworks.append(networkName); |
|
459 |
|
460 QNetworkConfigurationPrivate *cpPriv = new QNetworkConfigurationPrivate; |
|
461 |
|
462 cpPriv->isValid = true; |
|
463 |
|
464 cpPriv->name = networkName; |
|
465 cpPriv->id = QString::number(qHash(QLatin1String("WLAN:") + cpPriv->name)); |
|
466 |
|
467 if (!(network.dwFlags & WLAN_AVAILABLE_NETWORK_HAS_PROFILE)) |
|
468 cpPriv->state = QNetworkConfiguration::Undefined; |
|
469 |
|
470 if (network.strProfileName[0] != 0) { |
|
471 if (network.bNetworkConnectable) { |
|
472 if (network.dwFlags & WLAN_AVAILABLE_NETWORK_CONNECTED) |
|
473 cpPriv->state = QNetworkConfiguration::Active; |
|
474 else |
|
475 cpPriv->state = QNetworkConfiguration::Discovered; |
|
476 } else { |
|
477 cpPriv->state = QNetworkConfiguration::Defined; |
|
478 } |
|
479 } |
|
480 |
|
481 cpPriv->type = QNetworkConfiguration::InternetAccessPoint; |
|
482 cpPriv->bearer = QLatin1String("WLAN"); |
|
483 |
|
484 |
|
485 foundConfigurations.append(cpPriv); |
|
486 } |
|
487 |
|
488 local_WlanFreeMemory(networkList); |
|
489 } |
|
490 |
|
491 local_WlanFreeMemory(interfaceList); |
|
492 |
|
493 if (ok) |
|
494 *ok = true; |
|
495 |
|
496 pollTimer.start(); |
|
497 |
|
498 return foundConfigurations; |
|
499 } |
|
500 |
|
501 QString QNativeWifiEngine::getInterfaceFromId(const QString &id) |
|
502 { |
|
503 // enumerate interfaces |
|
504 WLAN_INTERFACE_INFO_LIST *interfaceList; |
|
505 DWORD result = local_WlanEnumInterfaces(handle, 0, &interfaceList); |
|
506 if (result != ERROR_SUCCESS) { |
|
507 qWarning("%s: WlanEnumInterfaces failed with error %ld\n", __FUNCTION__, result); |
|
508 return QString(); |
|
509 } |
|
510 |
|
511 for (unsigned int i = 0; i < interfaceList->dwNumberOfItems; ++i) { |
|
512 const WLAN_INTERFACE_INFO &interface = interfaceList->InterfaceInfo[i]; |
|
513 |
|
514 DWORD dataSize; |
|
515 WLAN_CONNECTION_ATTRIBUTES *connectionAttributes; |
|
516 result = local_WlanQueryInterface(handle, &interface.InterfaceGuid, |
|
517 wlan_intf_opcode_current_connection, 0, &dataSize, |
|
518 reinterpret_cast<PVOID *>(&connectionAttributes), 0); |
|
519 if (result != ERROR_SUCCESS) { |
|
520 if (result != ERROR_INVALID_STATE) |
|
521 qWarning("%s: WlanQueryInterface failed with error %ld\n", __FUNCTION__, result); |
|
522 |
|
523 continue; |
|
524 } |
|
525 |
|
526 if (qHash(QLatin1String("WLAN:") + |
|
527 QString::fromWCharArray(connectionAttributes->strProfileName)) == id.toUInt()) { |
|
528 QString guid("{%1-%2-%3-%4%5-%6%7%8%9%10%11}"); |
|
529 |
|
530 guid = guid.arg(interface.InterfaceGuid.Data1, 8, 16, QChar('0')); |
|
531 guid = guid.arg(interface.InterfaceGuid.Data2, 4, 16, QChar('0')); |
|
532 guid = guid.arg(interface.InterfaceGuid.Data3, 4, 16, QChar('0')); |
|
533 for (int i = 0; i < 8; ++i) |
|
534 guid = guid.arg(interface.InterfaceGuid.Data4[i], 2, 16, QChar('0')); |
|
535 |
|
536 local_WlanFreeMemory(connectionAttributes); |
|
537 |
|
538 return guid.toUpper(); |
|
539 } |
|
540 |
|
541 local_WlanFreeMemory(connectionAttributes); |
|
542 local_WlanFreeMemory(interfaceList); |
|
543 } |
|
544 |
|
545 return QString(); |
|
546 } |
|
547 |
|
548 bool QNativeWifiEngine::hasIdentifier(const QString &id) |
|
549 { |
|
550 // enumerate interfaces |
|
551 WLAN_INTERFACE_INFO_LIST *interfaceList; |
|
552 DWORD result = local_WlanEnumInterfaces(handle, 0, &interfaceList); |
|
553 if (result != ERROR_SUCCESS) { |
|
554 qWarning("%s: WlanEnumInterfaces failed with error %ld\n", __FUNCTION__, result); |
|
555 return false; |
|
556 } |
|
557 |
|
558 for (unsigned int i = 0; i < interfaceList->dwNumberOfItems; ++i) { |
|
559 const WLAN_INTERFACE_INFO &interface = interfaceList->InterfaceInfo[i]; |
|
560 |
|
561 WLAN_AVAILABLE_NETWORK_LIST *networkList; |
|
562 result = local_WlanGetAvailableNetworkList(handle, &interface.InterfaceGuid, |
|
563 3, 0, &networkList); |
|
564 if (result != ERROR_SUCCESS) { |
|
565 qWarning("%s: WlanGetAvailableNetworkList failed with error %ld\n", |
|
566 __FUNCTION__, result); |
|
567 continue; |
|
568 } |
|
569 |
|
570 for (unsigned int j = 0; j < networkList->dwNumberOfItems; ++j) { |
|
571 WLAN_AVAILABLE_NETWORK &network = networkList->Network[j]; |
|
572 |
|
573 QString networkName; |
|
574 |
|
575 if (network.strProfileName[0] != 0) { |
|
576 networkName = QString::fromWCharArray(network.strProfileName); |
|
577 } else { |
|
578 networkName = QByteArray(reinterpret_cast<char *>(network.dot11Ssid.ucSSID), |
|
579 network.dot11Ssid.uSSIDLength); |
|
580 } |
|
581 |
|
582 if (qHash(QLatin1String("WLAN:") + networkName) == id.toUInt()) { |
|
583 local_WlanFreeMemory(networkList); |
|
584 local_WlanFreeMemory(interfaceList); |
|
585 return true; |
|
586 } |
|
587 } |
|
588 |
|
589 local_WlanFreeMemory(networkList); |
|
590 } |
|
591 |
|
592 local_WlanFreeMemory(interfaceList); |
|
593 |
|
594 return false; |
|
595 } |
|
596 |
|
597 /*QString QNativeWifiEngine::bearerName(const QString &) |
|
598 { |
|
599 return QLatin1String("WLAN"); |
|
600 }*/ |
|
601 |
|
602 void QNativeWifiEngine::connectToId(const QString &id) |
|
603 { |
|
604 WLAN_INTERFACE_INFO_LIST *interfaceList; |
|
605 DWORD result = local_WlanEnumInterfaces(handle, 0, &interfaceList); |
|
606 if (result != ERROR_SUCCESS) { |
|
607 qWarning("%s: WlanEnumInterfaces failed with error %ld\n", __FUNCTION__, result); |
|
608 emit connectionError(id, InterfaceLookupError); |
|
609 return; |
|
610 } |
|
611 |
|
612 QString profile; |
|
613 |
|
614 for (unsigned int i = 0; i < interfaceList->dwNumberOfItems; ++i) { |
|
615 const WLAN_INTERFACE_INFO &interface = interfaceList->InterfaceInfo[i]; |
|
616 |
|
617 WLAN_AVAILABLE_NETWORK_LIST *networkList; |
|
618 result = local_WlanGetAvailableNetworkList(handle, &interface.InterfaceGuid, |
|
619 3, 0, &networkList); |
|
620 if (result != ERROR_SUCCESS) { |
|
621 qWarning("%s: WlanGetAvailableNetworkList failed with error %ld\n", |
|
622 __FUNCTION__, result); |
|
623 continue; |
|
624 } |
|
625 |
|
626 for (unsigned int j = 0; j < networkList->dwNumberOfItems; ++j) { |
|
627 WLAN_AVAILABLE_NETWORK &network = networkList->Network[j]; |
|
628 |
|
629 profile = QString::fromWCharArray(network.strProfileName); |
|
630 |
|
631 if (qHash(QLatin1String("WLAN:") + profile) == id.toUInt()) |
|
632 break; |
|
633 else |
|
634 profile.clear(); |
|
635 } |
|
636 |
|
637 local_WlanFreeMemory(networkList); |
|
638 |
|
639 if (!profile.isEmpty()) { |
|
640 WLAN_CONNECTION_PARAMETERS parameters; |
|
641 parameters.wlanConnectionMode = wlan_connection_mode_profile; |
|
642 parameters.strProfile = reinterpret_cast<LPCWSTR>(profile.utf16()); |
|
643 parameters.pDot11Ssid = 0; |
|
644 parameters.pDesiredBssidList = 0; |
|
645 parameters.dot11BssType = dot11_BSS_type_any; |
|
646 parameters.dwFlags = 0; |
|
647 |
|
648 DWORD result = local_WlanConnect(handle, &interface.InterfaceGuid, ¶meters, 0); |
|
649 if (result != ERROR_SUCCESS) { |
|
650 qWarning("%s: WlanConnect failed with error %ld\n", __FUNCTION__, result); |
|
651 emit connectionError(id, ConnectError); |
|
652 break; |
|
653 } |
|
654 |
|
655 break; |
|
656 } |
|
657 } |
|
658 |
|
659 local_WlanFreeMemory(interfaceList); |
|
660 |
|
661 if (profile.isEmpty()) |
|
662 emit connectionError(id, InterfaceLookupError); |
|
663 } |
|
664 |
|
665 void QNativeWifiEngine::disconnectFromId(const QString &id) |
|
666 { |
|
667 QString interface = getInterfaceFromId(id); |
|
668 |
|
669 if (interface.isEmpty()) { |
|
670 emit connectionError(id, InterfaceLookupError); |
|
671 return; |
|
672 } |
|
673 |
|
674 QStringList split = interface.mid(1, interface.length() - 2).split('-'); |
|
675 |
|
676 GUID guid; |
|
677 guid.Data1 = split.at(0).toUInt(0, 16); |
|
678 guid.Data2 = split.at(1).toUShort(0, 16); |
|
679 guid.Data3 = split.at(2).toUShort(0, 16); |
|
680 guid.Data4[0] = split.at(3).left(2).toUShort(0, 16); |
|
681 guid.Data4[1] = split.at(3).right(2).toUShort(0, 16); |
|
682 for (int i = 0; i < 6; ++i) |
|
683 guid.Data4[i + 2] = split.at(4).mid(i*2, 2).toUShort(0, 16); |
|
684 |
|
685 DWORD result = local_WlanDisconnect(handle, &guid, 0); |
|
686 if (result != ERROR_SUCCESS) { |
|
687 qWarning("%s: WlanDisconnect failed with error %ld\n", __FUNCTION__, result); |
|
688 emit connectionError(id, DisconnectionError); |
|
689 return; |
|
690 } |
|
691 } |
|
692 |
|
693 void QNativeWifiEngine::requestUpdate() |
|
694 { |
|
695 // enumerate interfaces |
|
696 WLAN_INTERFACE_INFO_LIST *interfaceList; |
|
697 DWORD result = local_WlanEnumInterfaces(handle, 0, &interfaceList); |
|
698 if (result != ERROR_SUCCESS) { |
|
699 qWarning("%s: WlanEnumInterfaces failed with error %ld\n", __FUNCTION__, result); |
|
700 return; |
|
701 } |
|
702 |
|
703 for (unsigned int i = 0; i < interfaceList->dwNumberOfItems; ++i) { |
|
704 result = local_WlanScan(handle, &interfaceList->InterfaceInfo[i].InterfaceGuid, 0, 0, 0); |
|
705 if (result != ERROR_SUCCESS) |
|
706 qWarning("%s: WlanScan failed with error %ld\n", __FUNCTION__, result); |
|
707 } |
|
708 } |
|
709 |
|
710 QNativeWifiEngine *QNativeWifiEngine::instance() |
|
711 { |
|
712 resolveLibrary(); |
|
713 |
|
714 // native wifi dll not available |
|
715 if (!local_WlanOpenHandle) |
|
716 return 0; |
|
717 |
|
718 QNativeWifiEngine *engine = nativeWifiEngine(); |
|
719 |
|
720 // could not initialise subsystem |
|
721 if (engine && engine->handle == 0) |
|
722 return 0; |
|
723 |
|
724 return engine; |
|
725 } |
|
726 |
|
727 #include "moc_qnativewifiengine_win_p.cpp" |
|
728 |
|
729 QTM_END_NAMESPACE |