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