port remaining windows backend from qtmobility.
[qt:qtsystems.git] / src / systeminfo / qnetworkinfo_win.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtSystems module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.  For licensing terms and
14 ** conditions see http://qt.digia.com/licensing.  For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights.  These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file.  Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qnetworkinfo_win_p.h"
43
44 #include <QMutex>
45 #include <QLibraryInfo>
46 #include <QtCore/qlibrary.h>
47 #include <QtCore/QTimer>
48 #include <QtCore/QTimerEvent>
49 #include <QtCore/QSettings>
50
51 #include <QtCore/qmetaobject.h>
52
53 #if !defined( Q_CC_MINGW)
54 #ifndef Q_OS_WINCE
55 #include "windows/qwmihelper_win_p.h"
56
57 enum NDIS_MEDIUM {
58     NdisMedium802_3 = 0,
59     NdisMediumWirelessWan = 9,
60 };
61
62 enum NDIS_PHYSICAL_MEDIUM {
63     NdisPhysicalMediumUnspecified = 0,
64     NdisPhysicalMediumWirelessLan = 1,
65     NdisPhysicalMediumBluetooth = 10,
66     NdisPhysicalMediumWiMax = 12,
67 };
68
69 #define OID_GEN_MEDIA_SUPPORTED 0x00010103
70 #define OID_GEN_PHYSICAL_MEDIUM 0x00010202
71
72 #define IOCTL_NDIS_QUERY_GLOBAL_STATS \
73     CTL_CODE(FILE_DEVICE_PHYSICAL_NETCARD, 0, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
74
75 #endif
76 #endif
77
78
79 #define WLAN_MAX_NAME_LENGTH 256
80 #define DOT11_SSID_MAX_LENGTH 32
81 #define WLAN_NOTIFICATION_SOURCE_ALL 0x0000ffff
82
83 enum WLAN_INTF_OPCODE {
84     wlan_intf_opcode_autoconf_start = 0x000000000,
85     wlan_intf_opcode_autoconf_enabled,
86     wlan_intf_opcode_background_scan_enabled,
87     wlan_intf_opcode_media_streaming_mode,
88     wlan_intf_opcode_radio_state,
89     wlan_intf_opcode_batteryStatuss_type,
90     wlan_intf_opcode_interface_state,
91     wlan_intf_opcode_current_connection,
92     wlan_intf_opcode_channel_number,
93     wlan_intf_opcode_supported_infrastructure_auth_cipher_pairs,
94     wlan_intf_opcode_supported_adhoc_auth_cipher_pairs,
95     wlan_intf_opcode_supported_country_or_region_string_list,
96     wlan_intf_opcode_current_operation_mode,
97     wlan_intf_opcode_supported_safe_mode,
98     wlan_intf_opcode_certified_safe_mode,
99     wlan_intf_opcode_autoconf_end = 0x0fffffff,
100     wlan_intf_opcode_msm_start = 0x10000100,
101     wlan_intf_opcode_statistics,
102     wlan_intf_opcode_rssi,
103     wlan_intf_opcode_msm_end = 0x1fffffff,
104     wlan_intf_opcode_security_start = 0x20010000,
105     wlan_intf_opcode_security_end = 0x2fffffff,
106     wlan_intf_opcode_ihv_start = 0x30000000,
107     wlan_intf_opcode_ihv_end = 0x3fffffff
108 };
109
110 enum WLAN_OPCODE_VALUE_TYPE {
111     wlan_opcode_value_type_query_only = 0,
112     wlan_opcode_value_type_set_by_group_policy,
113     wlan_opcode_value_type_set_by_user,
114     wlan_opcode_value_type_invalid
115 };
116
117 enum WLAN_INTERFACE_STATE {
118     wlan_interface_state_not_ready = 0,
119     wlan_interface_state_connected,
120     wlan_interface_state_ad_hoc_network_formed,
121     wlan_interface_state_disconnecting,
122     wlan_interface_state_disconnected,
123     wlan_interface_state_associating,
124     wlan_interface_state_discovering,
125     wlan_interface_state_authenticating
126 };
127
128 struct WLAN_INTERFACE_INFO {
129     GUID InterfaceGuid;
130     WCHAR strInterfaceDescription[WLAN_MAX_NAME_LENGTH];
131     WLAN_INTERFACE_STATE isState;
132 };
133
134 struct WLAN_INTERFACE_INFO_LIST {
135     DWORD dwNumberOfItems;
136     DWORD dwIndex;
137     WLAN_INTERFACE_INFO InterfaceInfo[1];
138 };
139
140 struct WLAN_NOTIFICATION_DATA {
141     DWORD NotificationSource;
142     DWORD NotificationCode;
143     GUID InterfaceGuid;
144     DWORD dwDataSize;
145     PVOID pData;
146 };
147
148 enum WLAN_CONNECTION_MODE {
149     wlan_connection_mode_profile = 0,
150     wlan_connection_mode_temporary_profile,
151     wlan_connection_mode_discovery_secure,
152     wlan_connection_mode_discovery_unsecure,
153     wlan_connection_mode_auto,
154     wlan_connection_mode_invalid
155 };
156
157 enum DOT11_PHY_TYPE {
158         dot11_phy_type_unknown = 0,
159         dot11_phy_type_any = dot11_phy_type_unknown,
160         dot11_phy_type_fhss = 1,
161         dot11_phy_type_dsss = 2,
162         dot11_phy_type_irbaseband = 3,
163         dot11_phy_type_ofdm = 4,
164         dot11_phy_type_hrdsss = 5,
165         dot11_phy_type_erp = 6,
166         dot11_phy_type_ht = 7,
167         dot11_phy_type_IHV_start = 0x80000000,
168         dot11_phy_type_IHV_end = 0xffffffff
169     };
170
171
172 enum DOT11_AUTH_ALGORITHM {
173     DOT11_AUTH_ALGO_80211_OPEN = 1,
174     DOT11_AUTH_ALGO_80211_SHARED_KEY = 2,
175     DOT11_AUTH_ALGO_WPA = 3,
176     DOT11_AUTH_ALGO_WPA_PSK = 4,
177     DOT11_AUTH_ALGO_WPA_NONE = 5,
178     DOT11_AUTH_ALGO_RSNA = 6,
179     DOT11_AUTH_ALGO_RSNA_PSK = 7,
180     DOT11_AUTH_ALGO_IHV_START = 0x80000000,
181     DOT11_AUTH_ALGO_IHV_END = 0xffffffff
182 };
183
184
185 enum DOT11_CIPHER_ALGORITHM {
186     DOT11_CIPHER_ALGO_NONE = 0x00,
187     DOT11_CIPHER_ALGO_WEP40 = 0x01,
188     DOT11_CIPHER_ALGO_TKIP = 0x02,
189     DOT11_CIPHER_ALGO_CCMP = 0x04,
190     DOT11_CIPHER_ALGO_WEP104 = 0x05,
191     DOT11_CIPHER_ALGO_WPA_USE_GROUP = 0x100,
192     DOT11_CIPHER_ALGO_RSN_USE_GROUP = 0x100,
193     DOT11_CIPHER_ALGO_WEP = 0x101,
194     DOT11_CIPHER_ALGO_IHV_START = 0x80000000,
195     DOT11_CIPHER_ALGO_IHV_END = 0xffffffff
196 };
197
198
199 enum DOT11_batteryStatusS_TYPE {
200     dot11_batteryStatusS_type_infrastructure = 1,
201     dot11_batteryStatusS_type_independent = 2,
202     dot11_batteryStatusS_type_any = 3
203 };
204
205
206 struct DOT11_SSID {
207     ULONG uSSIDLength;
208     UCHAR ucSSID[DOT11_SSID_MAX_LENGTH];
209 };
210
211 typedef UCHAR DOT11_MAC_ADDRESS[6];
212
213 struct WLAN_ASSOCIATION_ATTRIBUTES {
214     DOT11_SSID dot11Ssid;
215     DOT11_batteryStatusS_TYPE dot11batteryStatussType;
216     DOT11_MAC_ADDRESS dot11batteryStatussid;
217     DOT11_PHY_TYPE dot11PhyType;
218     ULONG uDot11PhyIndex;
219     ULONG wlanSignalQuality;
220     ULONG ulRxRate;
221     ULONG ulTxRate;
222 };
223
224 struct WLAN_SECURITY_ATTRIBUTES {
225     BOOL batteryStatusecurityEnabled;
226     BOOL bOneXEnabled;
227     DOT11_AUTH_ALGORITHM dot11AuthAlgorithm;
228     DOT11_CIPHER_ALGORITHM dot11CipherAlgorithm;
229 };
230
231 struct WLAN_CONNECTION_ATTRIBUTES {
232     WLAN_INTERFACE_STATE isState;
233     WLAN_CONNECTION_MODE wlanConnectionMode;
234     WCHAR strProfileName[WLAN_MAX_NAME_LENGTH];
235     WLAN_ASSOCIATION_ATTRIBUTES wlanAssociationAttributes;
236     WLAN_SECURITY_ATTRIBUTES wlanSecurityAttributes;
237 };
238
239 enum WLAN_NOTIFICATION_ACM {
240     wlan_notification_acm_start = 0,
241     wlan_notification_acm_autoconf_enabled,
242     wlan_notification_acm_autoconf_disabled,
243     wlan_notification_acm_background_scan_enabled,
244     wlan_notification_acm_background_scan_disabled,
245     wlan_notification_acm_batteryStatuss_type_change,
246     wlan_notification_acm_power_setting_change,
247     wlan_notification_acm_scan_complete,
248     wlan_notification_acm_scan_fail,
249     wlan_notification_acm_connection_start,
250     wlan_notification_acm_connection_complete,
251     wlan_notification_acm_connection_attempt_fail,
252     wlan_notification_acm_filter_list_change,
253     wlan_notification_acm_interface_arrival,
254     wlan_notification_acm_interface_removal,
255     wlan_notification_acm_profile_change,
256     wlan_notification_acm_profile_name_change,
257     wlan_notification_acm_profiles_exhausted,
258     wlan_notification_acm_network_not_available,
259     wlan_notification_acm_network_available,
260     wlan_notification_acm_disconnecting,
261     wlan_notification_acm_disconnected,
262     wlan_notification_acm_adhoc_network_state_change,
263     wlan_notification_acm_end
264 };
265
266 enum _WLAN_NOTIFICATION_MSM {
267     wlan_notification_msm_start = 0,
268     wlan_notification_msm_associating,
269     wlan_notification_msm_associated,
270     wlan_notification_msm_authenticating,
271     wlan_notification_msm_connected,
272     wlan_notification_msm_roaming_start,
273     wlan_notification_msm_roaming_end,
274     wlan_notification_msm_radio_state_change,
275     wlan_notification_msm_signal_quality_change,
276     wlan_notification_msm_disassociating,
277     wlan_notification_msm_disconnected,
278     wlan_notification_msm_peer_join,
279     wlan_notification_msm_peer_leave,
280     wlan_notification_msm_adapter_removal,
281     wlan_notification_msm_adapter_operation_mode_change,
282     wlan_notification_msm_end
283 };
284
285 typedef void (WINAPI *WLAN_NOTIFICATION_CALLBACK) (WLAN_NOTIFICATION_DATA *, PVOID);
286
287 //#define _WCHAR_T_DEFINED
288 //#define _TIME64_T_DEFINED
289
290 typedef struct _BLUETOOTH_FIND_RADIO_PARAMS {
291     DWORD   dwSize;             //  IN  sizeof this structure
292 } BLUETOOTH_FIND_RADIO_PARAMS;
293
294
295 typedef DWORD (WINAPI *WlanOpenHandleProto)
296     (DWORD dwClientVersion, PVOID pReserved, PDWORD pdwNegotiatedVersion, PHANDLE phClientHandle);
297 static WlanOpenHandleProto local_WlanOpenHandle = 0;
298
299 typedef DWORD (WINAPI *WlanCloseHandleProto)(HANDLE hClientHandle, PVOID pReserved);
300 static WlanCloseHandleProto local_WlanCloseHandle = 0;
301
302 #if !defined(Q_OS_WINCE)
303 typedef DWORD (WINAPI *WlanEnumInterfacesProto)
304     (HANDLE hClientHandle, PVOID pReserved, WLAN_INTERFACE_INFO_LIST **ppInterfaceList);
305 static WlanEnumInterfacesProto local_WlanEnumInterfaces = 0;
306
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 static WlanQueryInterfaceProto local_WlanQueryInterface = 0;
311
312 typedef DWORD (WINAPI *WlanRegisterNotificationProto)
313     (HANDLE hClientHandle, DWORD dwNotifSource, BOOL bIgnoreDuplicate,
314      WLAN_NOTIFICATION_CALLBACK funcCallback, PVOID pCallbackContext,
315      PVOID pReserved, PDWORD pdwPrevNotifSource);
316 static WlanRegisterNotificationProto local_WlanRegisterNotification = 0;
317 #endif
318
319 typedef VOID (WINAPI *WlanFreeMemoryProto)(PVOID pMemory);
320 static WlanFreeMemoryProto local_WlanFreeMemory = 0;
321
322 typedef BOOL (WINAPI *BluetoothFindRadioClose)(HANDLE hFind);
323 static BluetoothFindRadioClose local_BluetoothFindRadioClose=0;
324
325 typedef HANDLE (WINAPI *BluetoothFindFirstRadio)(const BLUETOOTH_FIND_RADIO_PARAMS * pbtfrp,HANDLE * phRadio);
326 static BluetoothFindFirstRadio local_BluetoothFindFirstRadio=0;
327
328
329 #if !defined( Q_CC_MINGW) && !defined( Q_OS_WINCE)
330 static WLAN_CONNECTION_ATTRIBUTES *getWifiConnectionAttributes()
331 {
332     if (!local_WlanOpenHandle)
333         return NULL;
334     DWORD version =  0;
335     HANDLE clientHandle = NULL;
336     DWORD result;
337     WLAN_CONNECTION_ATTRIBUTES  *connAtts = NULL;
338
339     WLAN_INTERFACE_INFO_LIST *interfacesInfoList = NULL;
340     result = local_WlanOpenHandle( 2, NULL, &version, &clientHandle );
341     if ( result != ERROR_SUCCESS) {
342         local_WlanFreeMemory(connAtts);
343         local_WlanCloseHandle(clientHandle,  0);
344         return NULL;
345     }
346     result = local_WlanEnumInterfaces(clientHandle, NULL, &interfacesInfoList);
347
348     if ( result != ERROR_SUCCESS) {
349         local_WlanCloseHandle(clientHandle, NULL);
350         local_WlanFreeMemory(connAtts);
351         return NULL;
352     }
353
354     for ( uint i = 0; i < interfacesInfoList->dwNumberOfItems; i++ ) {
355         WLAN_INTERFACE_INFO *interfaceInfo = &interfacesInfoList->InterfaceInfo[i];
356         GUID& guid = interfaceInfo->InterfaceGuid;
357         WLAN_INTERFACE_STATE wlanInterfaceState = interfaceInfo->isState;
358
359         if ( wlanInterfaceState == wlan_interface_state_not_ready ) {
360             continue;
361         }
362
363         ULONG size = 0;
364         result = local_WlanQueryInterface( clientHandle, &guid,  wlan_intf_opcode_current_connection, NULL, &size, (PVOID*) &connAtts, NULL );
365         if ( result != ERROR_SUCCESS ) {
366             continue;
367         }
368     }
369     local_WlanCloseHandle(clientHandle, NULL);
370     return connAtts;
371 }
372 #endif
373
374 #if !defined( Q_CC_MINGW) && !defined( Q_OS_WINCE)
375
376 void wlanNotificationCallback(WLAN_NOTIFICATION_DATA *pNotifyData, QNetworkInfoPrivate *netInfo)
377 {
378     // xp only supports disconnected and complete
379     switch (pNotifyData->NotificationCode) {
380     case wlan_notification_acm_scan_complete:
381         break;
382     case wlan_notification_acm_disconnecting:
383         break;
384     case wlan_notification_acm_disconnected:
385     case wlan_notification_acm_connection_attempt_fail:
386     case wlan_notification_acm_network_not_available:
387         netInfo->emitNetworkStatusChanged(QNetworkInfo::WlanMode,
388                                           QNetworkInfo::NoNetworkAvailable);
389         break;
390     case wlan_notification_acm_profile_name_change:
391         break;
392     case  wlan_notification_msm_connected:
393         netInfo->emitNetworkStatusChanged(QNetworkInfo::WlanMode,
394                                           QNetworkInfo::HomeNetwork);
395         break;
396     case wlan_notification_acm_connection_start:
397         netInfo->emitNetworkStatusChanged(QNetworkInfo::WlanMode,
398                                           QNetworkInfo::Searching);
399         break;
400     case wlan_notification_msm_signal_quality_change:
401         netInfo->emitNetworkSignalStrengthChanged(QNetworkInfo::WlanMode,
402                                                   reinterpret_cast<qint32>(pNotifyData->pData));
403         break;
404     default:
405         break;
406     };
407 }
408 #endif
409
410 QT_BEGIN_NAMESPACE
411
412 Q_GLOBAL_STATIC_WITH_ARGS(QMutex, dynamicLoadMutex, (QMutex::Recursive));
413
414 static void resolveLibrary()
415 {
416 #if !defined( Q_OS_WINCE)
417             static volatile bool triedResolve = false;
418
419     if (!triedResolve) {
420 #ifndef QT_NO_THREAD
421         QMutexLocker locker(dynamicLoadMutex());
422 #endif
423
424         if (!triedResolve) {
425             local_WlanOpenHandle = (WlanOpenHandleProto)
426                                    QLibrary::resolve(QLatin1String("wlanapi.dll"), "WlanOpenHandle");
427             local_WlanRegisterNotification = (WlanRegisterNotificationProto)
428                                              QLibrary::resolve(QLatin1String("wlanapi.dll"), "WlanRegisterNotification");
429             local_WlanEnumInterfaces = (WlanEnumInterfacesProto)
430                                        QLibrary::resolve(QLatin1String("wlanapi.dll"), "WlanEnumInterfaces");
431             local_WlanQueryInterface = (WlanQueryInterfaceProto)
432                                        QLibrary::resolve(QLatin1String("wlanapi.dll"), "WlanQueryInterface");
433             local_WlanFreeMemory = (WlanFreeMemoryProto)
434                                    QLibrary::resolve(QLatin1String("wlanapi.dll"), "WlanFreeMemory");
435             local_WlanCloseHandle = (WlanCloseHandleProto)
436                                     QLibrary::resolve(QLatin1String("wlanapi.dll"), "WlanCloseHandle");
437
438
439             local_BluetoothFindFirstRadio = (BluetoothFindFirstRadio)
440                                             QLibrary::resolve(QLatin1String("Bthprops.cpl"), "BluetoothFindFirstRadio");
441             local_BluetoothFindRadioClose = (BluetoothFindRadioClose)
442                                             QLibrary::resolve(QLatin1String("Bthprops.cpl"), "BluetoothFindRadioClose");
443
444             triedResolve = true;
445         }
446     }
447 #endif
448 }
449
450 QNetworkInfoPrivate::QNetworkInfoPrivate(QNetworkInfo *parent)
451     : QObject(parent)
452     , q_ptr(parent)
453 {
454     wlanCallbackInitialized = false;
455
456     resolveLibrary();
457
458     startWifiCallback();
459
460      timerMs = 5000;
461      switch (QSysInfo::WindowsVersion) {
462      case  QSysInfo::WV_VISTA:
463      case QSysInfo::WV_WINDOWS7:
464          break;
465      default:
466          {
467              if (local_WlanOpenHandle)
468                  QTimer::singleShot(timerMs, this, SLOT(networkStrengthTimeout()));
469          }
470          break;
471      };
472 }
473 QNetworkInfoPrivate::~QNetworkInfoPrivate()
474 {
475 #if !defined( Q_OS_WINCE)
476     if (hWlan != 0)
477          local_WlanCloseHandle(hWlan, 0);
478 #endif
479 }
480
481 QNetworkInfoPrivate *QNetworkInfoPrivate::instance()
482 {
483     resolveLibrary();
484     static QNetworkInfoPrivate *self = 0;
485     if (!self) {
486         self = new QNetworkInfoPrivate;
487     }
488     return self;
489 }
490
491 void QNetworkInfoPrivate::startWifiCallback()
492 {
493 #if !defined( Q_CC_MINGW) && !defined( Q_OS_WINCE)
494     if (networkStatus(QNetworkInfo::WlanMode, 1) != QNetworkInfo::HomeNetwork
495     && wlanCallbackInitialized){
496         return;
497     }
498     DWORD version =  0;
499     hWlan = NULL;
500     DWORD result;
501     if (local_WlanOpenHandle)
502         result = local_WlanOpenHandle(2, NULL, &version, &hWlan );
503     if ( result != ERROR_SUCCESS ) {
504         qDebug() << "Error opening Wlanapi 2" << result ;
505         return ;
506     }
507     if ( result != ERROR_SUCCESS) {
508         qDebug() << "Error in enumerating wireless interfaces" << result;
509         return ;
510     }
511     if (ERROR_SUCCESS != local_WlanRegisterNotification(hWlan,
512                                                   WLAN_NOTIFICATION_SOURCE_ALL,
513                                                   true,
514                                                   WLAN_NOTIFICATION_CALLBACK(wlanNotificationCallback),
515                                                   this, 0, 0)) {
516         qDebug() << "failed";
517     } else {
518         wlanCallbackInitialized = true;
519     }
520 #endif
521 }
522
523
524 void QNetworkInfoPrivate::emitNetworkStatusChanged(QNetworkInfo::NetworkMode mode,
525                                                          QNetworkInfo::NetworkStatus status)
526 {
527     emit networkStatusChanged(mode, 1, status);
528     if (status == QNetworkInfo::NoNetworkAvailable
529         || status == QNetworkInfo::HomeNetwork) {
530         startWifiCallback();
531         emit networkNameChanged(mode, 1, networkName(mode, 1));
532         if (isDefaultMode(mode)) {
533             emit currentNetworkModeChanged(mode);
534         }
535     } else {
536         networkSignalStrengthChanged(mode, 1, 0);
537     }
538 }
539
540 void QNetworkInfoPrivate::emitNetworkSignalStrengthChanged(QNetworkInfo::NetworkMode mode,int /*strength*/)
541 {
542     switch (QSysInfo::WindowsVersion) {
543     case QSysInfo::WV_VISTA:
544     case QSysInfo::WV_WINDOWS7:
545         break;
546     default:
547         QTimer::singleShot(timerMs, this, SLOT(networkStrengthTimeout()));
548         break;
549     };
550     networkSignalStrength(mode, 1);
551 }
552
553 void QNetworkInfoPrivate::timerEvent(QTimerEvent *event)
554 {
555    if (event->timerId() == netStrengthTimer.timerId()) {
556       networkStrengthTimeout();
557    } else {
558       QObject::timerEvent(event);
559    }
560 }
561
562
563 void QNetworkInfoPrivate::networkStrengthTimeout()
564 {
565     QList<QNetworkInfo::NetworkMode> modeList;
566     modeList << QNetworkInfo::GsmMode;
567     modeList << QNetworkInfo::CdmaMode;
568     modeList << QNetworkInfo::WcdmaMode;
569     modeList << QNetworkInfo::WlanMode;
570     modeList << QNetworkInfo::EthernetMode;
571     modeList << QNetworkInfo::BluetoothMode;
572     modeList << QNetworkInfo::WimaxMode;
573
574     foreach (const QNetworkInfo::NetworkMode mode, modeList) {
575         networkSignalStrength(mode, 1);
576     }
577     switch (QSysInfo::WindowsVersion) {
578     case QSysInfo::WV_VISTA:
579     case QSysInfo::WV_WINDOWS7:
580         break;
581     default:
582         if (local_WlanOpenHandle)
583             QTimer::singleShot(timerMs, this, SLOT(networkStrengthTimeout()));
584         break;
585     };
586  }
587
588 void QNetworkInfoPrivate::networkStatusTimeout()
589 {
590     QList<QNetworkInfo::NetworkMode> modeList;
591     modeList << QNetworkInfo::GsmMode;
592     modeList << QNetworkInfo::CdmaMode;
593     modeList << QNetworkInfo::WcdmaMode;
594     modeList << QNetworkInfo::WlanMode;
595     modeList << QNetworkInfo::EthernetMode;
596     modeList << QNetworkInfo::BluetoothMode;
597     modeList << QNetworkInfo::WimaxMode;
598
599     foreach (const QNetworkInfo::NetworkMode mode, modeList) {
600         networkStatus(mode,1);
601     }
602
603  }
604
605 int QNetworkInfoPrivate::networkInterfaceCount(QNetworkInfo::NetworkMode mode)
606 {
607     switch (mode) {
608     case QNetworkInfo::WlanMode:
609     case QNetworkInfo::EthernetMode:
610     case QNetworkInfo::BluetoothMode:
611
612 //    case QNetworkInfo::GsmMode:
613 //    case QNetworkInfo::CdmaMode:
614 //    case QNetworkInfo::WcdmaMode:
615 //    case QNetworkInfo::WimaxMode:
616 //    case QNetworkInfo::LteMode:
617 //    case QNetworkInfo::TdscdmaMode:
618     default:
619         break;
620     };
621
622     return -1;
623 }
624
625 int QNetworkInfoPrivate::networkSignalStrength(QNetworkInfo::NetworkMode mode, int netInterface)
626 {
627     Q_UNUSED(netInterface)
628
629     switch (mode) {
630     case QNetworkInfo::WlanMode:
631     {
632
633 #if !defined( Q_CC_MINGW) && !defined( Q_OS_WINCE)
634         if (local_WlanOpenHandle) {
635
636             DWORD version =  0;
637             DWORD result;
638
639             WLAN_INTERFACE_INFO_LIST *interfacesInfoList = NULL;
640             if (hWlan ==0) {
641                 result = local_WlanOpenHandle( 2, NULL, &version, &hWlan );
642                 if ( result != ERROR_SUCCESS ) {
643                     qDebug() << "Error opening Wlanapi 3" << result ;
644                     local_WlanCloseHandle(hWlan,  0);
645                     return 0;
646                 }
647             }
648             result = local_WlanEnumInterfaces(hWlan, NULL, &interfacesInfoList);
649
650             if ( result != ERROR_SUCCESS) {
651                 qDebug() << "Error in enumerating wireless interfaces" << result;
652                 local_WlanCloseHandle(hWlan,  0);
653                 return 0;
654             }
655
656             for ( uint i = 0; i < interfacesInfoList->dwNumberOfItems; i++ ) {
657                 WLAN_INTERFACE_INFO *interfaceInfo = &interfacesInfoList->InterfaceInfo[i];
658                 GUID& guid = interfaceInfo->InterfaceGuid;
659                 WLAN_INTERFACE_STATE wlanInterfaceState = interfaceInfo->isState;
660
661                 if ( wlanInterfaceState == wlan_interface_state_not_ready ) {
662                     qDebug() << "Interface not ready";
663                     continue;
664                 }
665
666                 ULONG size = 0;
667                 WLAN_CONNECTION_ATTRIBUTES  *connAtts = NULL;
668                 result = local_WlanQueryInterface( hWlan, &guid,
669                                                    wlan_intf_opcode_current_connection, NULL, &size, (PVOID*) &connAtts, NULL );
670
671                 if ( result != ERROR_SUCCESS ) {
672                     continue;
673                 }
674                 ulong sig =  connAtts->wlanAssociationAttributes.wlanSignalQuality;
675                 local_WlanFreeMemory(connAtts);
676                 local_WlanFreeMemory(interfacesInfoList);
677
678                 if (sig != wifiStrength) {
679                     emit networkSignalStrengthChanged(mode,1, sig);
680                     wifiStrength = sig;
681                 }
682                 return sig;
683             }
684         }
685 #endif
686     }
687     break;
688     case QNetworkInfo::EthernetMode:
689     {
690 #if !defined( Q_CC_MINGW) && !defined( Q_OS_WINCE)
691         WMIHelper *wHelper;
692         wHelper = new WMIHelper(this);
693         wHelper->setWmiNamespace(QLatin1String("root/cimv2"));
694         wHelper->setClassName(QLatin1String("Win32_NetworkAdapter"));
695         wHelper->setClassProperty(QStringList() << QLatin1String("NetConnectionStatus"));
696         QString cond = QLatin1String("WHERE MACAddress = '%1'");
697         cond = cond.arg( interfaceForMode(mode, 1).hardwareAddress());
698         wHelper->setConditional(cond);
699         QVariant v = wHelper->getWMIData();
700         quint32 strength = v.toUInt();
701         quint32 tmpStrength;
702
703         if ( strength == 2
704            || strength == 9) {
705             tmpStrength = 100;
706         } else {
707            tmpStrength = 0;
708         }
709
710         if (tmpStrength != ethStrength) {
711             ethStrength = tmpStrength;
712             emit networkSignalStrengthChanged(mode, 1, ethStrength);
713         }
714
715         return ethStrength;
716 #endif
717     }
718     break;
719     case QNetworkInfo::BluetoothMode:
720
721 //    case QNetworkInfo::GsmMode:
722 //    case QNetworkInfo::CdmaMode:
723 //    case QNetworkInfo::WcdmaMode:
724 //    case QNetworkInfo::WimaxMode:
725 //    case QNetworkInfo::LteMode:
726 //    case QNetworkInfo::TdscdmaMode:
727     default:
728         break;
729     };
730
731     return -1;
732 }
733
734 QNetworkInfo::CellDataTechnology QNetworkInfoPrivate::currentCellDataTechnology(int netInterface)
735 {
736     Q_UNUSED(netInterface)
737     return QNetworkInfo::UnknownDataTechnology;
738 }
739
740 bool QNetworkInfoPrivate::isDefaultMode(QNetworkInfo::NetworkMode mode)
741 {
742     bool isDefaultGateway = false;
743     QNetworkInterface netInterface = interfaceForMode(mode,1);
744     QString deviceNameReg;
745
746     switch (QSysInfo::WindowsVersion) {
747     case  QSysInfo::WV_VISTA:
748     case QSysInfo::WV_WINDOWS7:
749         deviceNameReg =  QLatin1String("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\%1\\");
750         deviceNameReg = deviceNameReg.arg(netInterface.name());
751         break;
752     default:
753         deviceNameReg = QLatin1String("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\%1\\Parameters\\Tcpip");
754         deviceNameReg = deviceNameReg.arg(netInterface.name());
755         break;
756     };
757
758     QSettings deviceSettings(deviceNameReg, QSettings::NativeFormat);
759     QString dhcpGw = QLatin1String("DhcpDefaultGateway");
760     QString gw = QLatin1String("DefaultGateway");
761     if (!deviceSettings.value(dhcpGw).toStringList().isEmpty()
762             || !deviceSettings.value(gw).toStringList().isEmpty()) {
763         isDefaultGateway = true;
764     }
765         return isDefaultGateway;
766 }
767 QNetworkInfo::NetworkMode QNetworkInfoPrivate::currentNetworkMode()
768 {
769     QList <QNetworkInfo::NetworkMode> modeList;
770     modeList << QNetworkInfo::EthernetMode
771             << QNetworkInfo::WlanMode
772             << QNetworkInfo::BluetoothMode
773             << QNetworkInfo::WcdmaMode
774             << QNetworkInfo::CdmaMode
775             << QNetworkInfo::GsmMode
776             << QNetworkInfo::WimaxMode;
777
778     for (int i = 0; i < modeList.size(); ++i) {
779         if ( isDefaultMode(modeList.at(i)))
780             return modeList.at(i);
781     }
782         return QNetworkInfo::UnknownMode;
783 }
784
785 QNetworkInfo::NetworkStatus QNetworkInfoPrivate::networkStatus(QNetworkInfo::NetworkMode mode, int netInterface)
786 {
787     Q_UNUSED(netInterface)
788
789     switch (mode) {
790     case QNetworkInfo::WlanMode:
791     {
792 #if !defined( Q_CC_MINGW) && !defined( Q_OS_WINCE)
793         if (local_WlanOpenHandle) {
794             WLAN_CONNECTION_ATTRIBUTES *connAtts = getWifiConnectionAttributes();
795             if (connAtts != NULL) {
796                 if (connAtts->isState  == wlan_interface_state_authenticating) {
797                     local_WlanFreeMemory(connAtts);
798                     return QNetworkInfo::Searching;
799                 }
800                 if (connAtts->isState  == wlan_interface_state_connected) {
801                     local_WlanFreeMemory(connAtts);
802                     return QNetworkInfo::HomeNetwork;
803                 }
804             }
805             local_WlanFreeMemory(connAtts);
806         }
807 #endif
808     }
809         break;
810     case QNetworkInfo::EthernetMode:
811     {
812 #if !defined( Q_CC_MINGW) && !defined( Q_OS_WINCE)
813         WMIHelper *wHelper;
814         wHelper = new WMIHelper(this);
815         wHelper->setWmiNamespace(QLatin1String("root/cimv2"));
816         wHelper->setClassName(QLatin1String("Win32_NetworkAdapter"));
817         wHelper->setClassProperty(QStringList() << QLatin1String("NetConnectionStatus"));
818         QString cond = QLatin1String("WHERE MACAddress = '%1'");
819         cond = cond.arg(interfaceForMode(mode,1).hardwareAddress());
820         wHelper->setConditional(cond);
821         QVariant v = wHelper->getWMIData();
822         if (v.toUInt() == 2) {
823             return QNetworkInfo::HomeNetwork;
824         }
825 #endif
826     }
827         break;
828     case QNetworkInfo::BluetoothMode:
829     {
830 #if !defined( Q_CC_MINGW) && !defined( Q_OS_WINCE)
831         WMIHelper *wHelper;
832         wHelper = new WMIHelper(this);
833         wHelper->setWmiNamespace(QLatin1String("root/cimv2"));
834         wHelper->setClassName(QLatin1String("Win32_NetworkAdapter"));
835         wHelper->setClassProperty(QStringList() << QLatin1String("NetConnectionStatus"));
836         QString cond = QLatin1String("WHERE MACAddress = '%1'");
837         cond = cond.arg(interfaceForMode(mode, 1).hardwareAddress());
838         wHelper->setConditional(cond);
839         QVariant v = wHelper->getWMIData();
840         if (v.toUInt() == 2) {
841             return QNetworkInfo::HomeNetwork;
842         }
843 #endif
844     }
845         break;
846 //    case QNetworkInfo::GsmMode:
847 //    case QNetworkInfo::CdmaMode:
848 //    case QNetworkInfo::WcdmaMode:
849 //    case QNetworkInfo::WimaxMode:
850 //    case QNetworkInfo::LteMode:
851 //    case QNetworkInfo::TdscdmaMode:
852         break;
853
854     default:
855         break;
856     };
857
858     return QNetworkInfo::UnknownStatus;
859 }
860
861 #ifndef QT_NO_NETWORKINTERFACE
862 QNetworkInterface QNetworkInfoPrivate::interfaceForMode(QNetworkInfo::NetworkMode mode, int netInterface)
863 {
864     Q_UNUSED(netInterface)
865     QList<QNetworkInterface> interfaceList;
866     interfaceList = QNetworkInterface::allInterfaces();
867     QListIterator<QNetworkInterface> i(interfaceList);
868     while (i.hasNext()) {
869        QNetworkInterface netInterface = i.next();
870         if (!netInterface.isValid()
871             || (netInterface.flags() & QNetworkInterface::IsLoopBack)
872             || !(netInterface.flags() & QNetworkInterface::IsUp)
873             || !(netInterface.flags() & QNetworkInterface::IsRunning)
874             || netInterface.addressEntries().isEmpty()) {
875             continue;
876         }
877
878 #if !defined( Q_CC_MINGW) && !defined( Q_OS_WINCE)
879
880         if (local_WlanOpenHandle) {
881             unsigned long oid;
882             DWORD bytesWritten;
883
884             NDIS_MEDIUM medium ;
885             NDIS_PHYSICAL_MEDIUM physicalMedium = NdisPhysicalMediumUnspecified;
886             QString filestr = QLatin1String("\\\\.\\%1");
887             HANDLE handle = CreateFile((TCHAR *)filestr.arg(netInterface.name()).utf16(), 0,
888                                        FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
889
890             if (handle == INVALID_HANDLE_VALUE) {
891                 continue;
892             }
893
894             oid = OID_GEN_MEDIA_SUPPORTED;
895             bytesWritten;
896             bool result = DeviceIoControl(handle, IOCTL_NDIS_QUERY_GLOBAL_STATS, &oid, sizeof(oid),
897                                           &medium, sizeof(medium), &bytesWritten, 0);
898             if (!result) {
899                 CloseHandle(handle);
900                 qDebug() << "DeviceIo result is false";
901                 return QNetworkInterface();
902                 continue;
903             }
904
905             oid = OID_GEN_PHYSICAL_MEDIUM;
906             bytesWritten = 0;
907             result = DeviceIoControl(handle, IOCTL_NDIS_QUERY_GLOBAL_STATS, &oid, sizeof(oid),
908                                      &physicalMedium, sizeof(physicalMedium), &bytesWritten, 0);
909
910             if (!result) {
911                 CloseHandle(handle);
912                 if (medium == NdisMedium802_3 && mode == QNetworkInfo::EthernetMode) {
913                     return netInterface;
914                 } else {
915                     continue;
916                 }
917             }
918
919             CloseHandle(handle);
920             if (physicalMedium == NdisMediumWirelessWan && mode == QNetworkInfo::WlanMode) {
921                 //some wifi devices show up here
922                 return netInterface;
923             }
924
925             if (medium == NdisMedium802_3) {
926                 switch (physicalMedium) {
927                 case NdisPhysicalMediumUnspecified:
928                     {
929                         if (mode == QNetworkInfo::EthernetMode) {
930                             return netInterface;
931                         }
932                     }
933                     break;
934                 case NdisPhysicalMediumWirelessLan:
935                     {
936                         if (mode == QNetworkInfo::WlanMode) {
937                             return netInterface;
938                         }
939                     }
940                     break;
941                 case NdisPhysicalMediumBluetooth:
942                     {
943                         if (mode == QNetworkInfo::BluetoothMode) {
944                             return netInterface;
945                         }
946                     }
947                     break;
948 #ifdef NDIS_SUPPORT_NDIS6
949                 case NdisPhysicalMediumWiMax:
950                     {
951                         if (mode == QNetworkInfo::WimaxMode) {
952                             return netInterface;
953                         }
954                     }
955                     break;
956 #endif
957                 };
958             }
959         }
960 #endif
961     }
962 //    Q_UNUSED(interface)
963
964 //    switch (mode) {
965 //    case QNetworkInfo::WlanMode:
966 //    case QNetworkInfo::EthernetMode:
967
968 ////    case QNetworkInfo::BluetoothMode:
969 ////    case QNetworkInfo::GsmMode:
970 ////    case QNetworkInfo::CdmaMode:
971 ////    case QNetworkInfo::WcdmaMode:
972 ////    case QNetworkInfo::WimaxMode:
973 ////    case QNetworkInfo::LteMode:
974 ////    case QNetworkInfo::TdscdmaMode:
975 //    default:
976 //        break;
977 //    };
978
979     return QNetworkInterface();
980 }
981 #endif // QT_NO_NETWORKINTERFACE
982
983 QString QNetworkInfoPrivate::cellId(int netInterface)
984 {
985     Q_UNUSED(netInterface)
986     return QString();
987 }
988
989 QString QNetworkInfoPrivate::currentMobileCountryCode(int netInterface)
990 {
991     Q_UNUSED(netInterface)
992     return QString();
993 }
994
995 QString QNetworkInfoPrivate::currentMobileNetworkCode(int netInterface)
996 {
997     Q_UNUSED(netInterface)
998     return QString();
999 }
1000
1001 QString QNetworkInfoPrivate::homeMobileCountryCode(int netInterface)
1002 {
1003     Q_UNUSED(netInterface)
1004     return QString();
1005 }
1006
1007 QString QNetworkInfoPrivate::homeMobileNetworkCode(int netInterface)
1008 {
1009     Q_UNUSED(netInterface)
1010     return QString();
1011 }
1012
1013 QString QNetworkInfoPrivate::imsi(int netInterface)
1014 {
1015     Q_UNUSED(netInterface)
1016     return QString();
1017 }
1018
1019 QString QNetworkInfoPrivate::locationAreaCode(int netInterface)
1020 {
1021     Q_UNUSED(netInterface)
1022     return QString();
1023 }
1024
1025 QString QNetworkInfoPrivate::macAddress(QNetworkInfo::NetworkMode mode, int netInterface)
1026 {
1027     Q_UNUSED(netInterface)
1028     QString mac = interfaceForMode(mode,1).hardwareAddress();
1029     return mac;
1030
1031 //    switch (mode) {
1032 //    case QNetworkInfo::WlanMode:
1033 //    case QNetworkInfo::EthernetMode:
1034 //    case QNetworkInfo::BluetoothMode:
1035
1036 ////    case QNetworkInfo::GsmMode:
1037 ////    case QNetworkInfo::CdmaMode:
1038 ////    case QNetworkInfo::WcdmaMode:
1039 ////    case QNetworkInfo::WimaxMode:
1040 ////    case QNetworkInfo::LteMode:
1041 ////    case QNetworkInfo::TdscdmaMode:
1042 //    default:
1043 //        break;
1044 //    };
1045
1046     return QString();
1047 }
1048
1049 QString QNetworkInfoPrivate::networkName(QNetworkInfo::NetworkMode mode, int netInterface)
1050 {
1051     Q_UNUSED(netInterface)
1052     QString  netname;
1053
1054     switch (mode) {
1055     case QNetworkInfo::WlanMode:
1056     {
1057 #if !defined( Q_CC_MINGW) && !defined( Q_OS_WINCE)
1058         if (local_WlanOpenHandle) {
1059             WLAN_CONNECTION_ATTRIBUTES *connAtts = getWifiConnectionAttributes();
1060             if (connAtts != NULL) {
1061                 DOT11_SSID ssid;
1062                 ssid = connAtts->wlanAssociationAttributes.dot11Ssid;
1063                 for (uint i = 0; i < ssid.uSSIDLength;i++) {
1064                     QString temp = ssid.ucSSID[i];
1065                     netname += temp;
1066                 }
1067             }
1068             local_WlanFreeMemory(connAtts);
1069         }
1070 #endif
1071     }
1072     break;
1073     case QNetworkInfo::EthernetMode:
1074     {
1075 #if !defined( Q_CC_MINGW) && !defined( Q_OS_WINCE)
1076         WMIHelper *wHelper;
1077         wHelper = new WMIHelper(this);
1078         wHelper->setWmiNamespace(QLatin1String("root/cimv2"));
1079         wHelper->setClassName(QLatin1String("Win32_ComputerSystem"));
1080         wHelper->setClassProperty(QStringList() << QLatin1String("Domain"));
1081
1082         QVariant v = wHelper->getWMIData();
1083         netname = v.toString();
1084 #endif
1085     }
1086     break;
1087     case QNetworkInfo::BluetoothMode:
1088
1089 //    case QNetworkInfo::GsmMode:
1090 //    case QNetworkInfo::CdmaMode:
1091 //    case QNetworkInfo::WcdmaMode:
1092 //    case QNetworkInfo::WimaxMode:
1093 //    case QNetworkInfo::LteMode:
1094 //    case QNetworkInfo::TdscdmaMode:
1095     default:
1096         break;
1097     };
1098
1099     return netname;
1100 }
1101
1102 void QNetworkInfoPrivate::connectNotify(const QMetaMethod &signal)
1103 {
1104     Q_UNUSED(signal)
1105 }
1106
1107 void QNetworkInfoPrivate::disconnectNotify(const QMetaMethod &signal)
1108 {
1109     Q_UNUSED(signal)
1110 }
1111
1112 QT_END_NAMESPACE