I would like to know how a windows C++ app can get notified when windows system changes its wifi network. I'm interested in the following cases:
Note: Switching on/off the wifi is not of interest. Device needs to be connected to a network. Network may or may not have an internet connection.
I'm trying to achieve this using the wlanapi.h and have checked out a few examples, but have not been able to achieve this.
Let me know if someone was able to achieve this using wlanapi.h. Or is there an another way? Pls demonstrate with an example.
Any help would be appreciated.
EDIT: Adding code
#include <windows.h>
#include <Wlanapi.h>
#include <iostream>
// Link wlanapi.lib
#pragma comment(lib, "wlanapi.lib")
void DetectWifiNetworkChanges ();
void EventLoop ();
// Callback func to receive network notifications
void WlanNotificationCallback (PWLAN_NOTIFICATION_DATA pData, PVOID pContext);
int main ()
{
DetectWifiNetworkChanges ();
printf ("\n");
getchar ();
return 0;
}
void DetectWifiNetworkChanges ()
{
printf ("DetectWifiNetworkChanges\n");
HANDLE client;
DWORD client_version = 2;
DWORD current_version = 0;
DWORD result;
result = WlanOpenHandle (client_version, NULL, ¤t_version, &client);
if (result != ERROR_SUCCESS) {
printf ("WlanOpenHandle failed !!\n");
return;
}
result = WlanRegisterNotification (client, WLAN_NOTIFICATION_SOURCE_ALL, FALSE, WlanNotificationCallback, NULL, NULL, NULL);
if (result != ERROR_SUCCESS) {
printf ("WlanRegisterNotification failed !!\n");
return;
}
printf ("WlanRegistration successful\n");
// An infinite loop (Ctrl + C to quit the app for now)
EventLoop ();
result = WlanCloseHandle (client, NULL);
if (result != ERROR_SUCCESS) {
printf ("WlanCloseHandle !!\n");
return;
}
}
Output
DetectWifiNetworkChanges
WlanRegistration successful
EventLoop
I tried to connect and disconnect from my network, but the callback is not called.
But sometimes, without me disconnecting from the network, the callback is called lots of times.
The solution was simple. I just had to change the type of notifications while registering and capture the states in the callback (The callback was empty previously).
When registering, the notification source should be WLAN_NOTIFICATION_SOURCE_ACM.
I captured all the states in the callback. Here is the modified working code
#include <windows.h>
#include <Wlanapi.h>
#include <iostream>
// Link wlanapi.lib
#pragma comment(lib, "wlanapi.lib")
void DetectWifiNetworkChanges ();
void HandleACMNotifications (PWLAN_NOTIFICATION_DATA pNotification);
// Callback func to receive wifi notifications
void WlanNotificationCallback (PWLAN_NOTIFICATION_DATA pData, PVOID pContext);
int
main ()
{
DetectWifiNetworkChanges ();
printf ("\n");
getchar ();
return 0;
}
// Entry point.
// Will be called from int main
void
DetectWifiNetworkChanges ()
{
printf ("DetectWifiNetworkChanges\n");
HANDLE client;
DWORD client_version = 2;
DWORD current_version = 0;
DWORD result;
result = WlanOpenHandle (client_version, NULL, ¤t_version, &client);
if (result != ERROR_SUCCESS) {
printf ("WlanOpenHandle failed !!\n");
return;
}
result = WlanRegisterNotification (client, WLAN_NOTIFICATION_SOURCE_ACM, FALSE, WlanNotificationCallback, NULL, NULL, NULL);
if (result != ERROR_SUCCESS) {
printf ("WlanRegisterNotification failed !!\n");
return;
}
printf ("WlanRegistration successful\n");
// Wait for input from user
// The program pauses here. Toggle the wifi, change wifi network etc.
// to see the wifi notifications
getchar ();
result = WlanCloseHandle (client, NULL);
if (result != ERROR_SUCCESS) {
printf ("WlanCloseHandle !!\n");
return;
}
}
void
WlanNotificationCallback (PWLAN_NOTIFICATION_DATA pNotification, PVOID pContext)
{
printf ("WlanNotificationCallback\n");
if (pNotification->NotificationSource == WLAN_NOTIFICATION_SOURCE_ACM)
HandleACMNotifications (pNotification);
}
void
HandleACMNotifications (PWLAN_NOTIFICATION_DATA pNotification)
{
printf ("HandleACMNotifications\n");
switch (pNotification->NotificationCode) {
case wlan_notification_acm_start:
printf ("wlan_notification_acm_start\n");
break;
case wlan_notification_acm_autoconf_enabled:
printf ("wlan_notification_acm_autoconf_enabled\n");
break;
case wlan_notification_acm_autoconf_disabled:
printf ("wlan_notification_acm_autoconf_disabled\n");
break;
case wlan_notification_acm_background_scan_enabled:
printf ("wlan_notification_acm_background_scan_enabled\n");
break;
case wlan_notification_acm_background_scan_disabled:
printf ("wlan_notification_acm_background_scan_disabled\n");
break;
case wlan_notification_acm_bss_type_change:
printf ("wlan_notification_acm_bss_type_change\n");
break;
case wlan_notification_acm_power_setting_change:
printf ("wlan_notification_acm_power_setting_change\n");
break;
case wlan_notification_acm_scan_complete:
printf ("wlan_notification_acm_scan_complete\n");
break;
case wlan_notification_acm_scan_fail:
printf ("wlan_notification_acm_scan_fail\n");
break;
case wlan_notification_acm_connection_start:
printf ("wlan_notification_acm_connection_start\n");
break;
case wlan_notification_acm_connection_complete:
printf ("wlan_notification_acm_connection_complete\n");
break;
case wlan_notification_acm_connection_attempt_fail:
printf ("wlan_notification_acm_connection_attempt_fail\n");
break;
case wlan_notification_acm_filter_list_change:
printf ("wlan_notification_acm_filter_list_change\n");
break;
case wlan_notification_acm_interface_arrival:
printf ("wlan_notification_acm_interface_arrival\n");
break;
case wlan_notification_acm_interface_removal:
printf ("wlan_notification_acm_interface_removal\n");
break;
case wlan_notification_acm_profile_change:
printf ("wlan_notification_acm_profile_change\n");
break;
case wlan_notification_acm_profile_name_change:
printf ("wlan_notification_acm_profile_name_change\n");
break;
case wlan_notification_acm_profiles_exhausted:
printf ("wlan_notification_acm_profiles_exhausted\n");
break;
case wlan_notification_acm_network_not_available:
printf ("wlan_notification_acm_network_not_available\n");
break;
case wlan_notification_acm_network_available:
printf ("wlan_notification_acm_network_available\n");
break;
case wlan_notification_acm_disconnecting:
printf ("wlan_notification_acm_disconnecting\n");
break;
case wlan_notification_acm_disconnected:
printf ("wlan_notification_acm_disconnected\n");
break;
case wlan_notification_acm_adhoc_network_state_change:
printf ("wlan_notification_acm_adhoc_network_state_change\n");
break;
case wlan_notification_acm_profile_unblocked:
printf ("wlan_notification_acm_profile_unblocked\n");
break;
case wlan_notification_acm_screen_power_change:
printf ("wlan_notification_acm_screen_power_change\n");
break;
case wlan_notification_acm_profile_blocked:
printf ("wlan_notification_acm_profile_blocked\n");
break;
case wlan_notification_acm_scan_list_refresh:
printf ("wlan_notification_acm_scan_list_refresh\n");
break;
case wlan_notification_acm_operational_state_change:
printf ("wlan_notification_acm_operational_state_change\n");
break;
case wlan_notification_acm_end:
printf ("wlan_notification_acm_end\n");
break;
}
}
Observation:
When I click on the wifi icon to see the list of available networks, the callback is invoked with the following notifications
WlanNotificationCallback
HandleACMNotifications
wlan_notification_acm_scan_complete
WlanNotificationCallback
HandleACMNotifications
wlan_notification_acm_scan_list_refresh
WlanNotificationCallback
HandleACMNotifications
wlan_notification_acm_network_available
WlanNotificationCallback
HandleACMNotifications
wlan_notification_acm_profiles_exhausted
WlanNotificationCallback
HandleACMNotifications
wlan_notification_acm_network_available
Note: WlanNotificationCallback, HandleACMNotifications are my printfs, as shown in the code. These two are pasted in the output along with the notification code as per the flow.
These notifications will be repeated since the system scans and displays the list of available networks in the following scenarios
Notifications received when disconnecting from the network:
WlanNotificationCallback
HandleACMNotifications
wlan_notification_acm_scan_complete
WlanNotificationCallback
HandleACMNotifications
wlan_notification_acm_scan_list_refresh
WlanNotificationCallback
HandleACMNotifications
wlan_notification_acm_profile_change
WlanNotificationCallback
HandleACMNotifications
wlan_notification_acm_disconnecting
WlanNotificationCallback
HandleACMNotifications
wlan_notification_acm_disconnected
Notifications received when connecting to a network:
wlan_notification_acm_profile_change
WlanNotificationCallback
HandleACMNotifications
wlan_notification_acm_connection_start
WlanNotificationCallback
HandleACMNotifications
wlan_notification_acm_scan_fail
WlanNotificationCallback
HandleACMNotifications
wlan_notification_acm_connection_complete
Ignoring the intermediate notification codes, handling wlan_notification_acm_connection_complete and wlan_notification_acm_disconnected will work.