#pragma once
#include <windows.h>
#include <wlanapi.h>
#pragma comment(lib, "wlanapi.lib")
//连接方式
#define MODE_AUTO "auto"
#define MODE_MANUAL "manual"
//认证方式
#define AUTH_WPAPSK "WPAPSK"
#define AUTH_WPA2PSK "WPA2PSK"
//加密方式
#define ENCR_AES "AES"
#define ENCR_TKIP "TKIP"
/*WIFI信息*/
struct WifiInfo
{
char account[64];
char password[64];
char mode[32];
char auth[32];
char encrypt[32];
};
class WifiMgr
{
public:
WifiMgr();
~WifiMgr();
bool connect(const char* account, const char* password, const char* mode = MODE_MANUAL,
const char* auth = AUTH_WPAPSK, const char* encrypt = ENCR_AES);
bool connect(const WifiInfo& info);
bool reconnect();
bool disconnect(bool removeProFile = true);
bool connected() const;
const char* getLastError() const;
protected:
static void _stdcall wlanNotification(PWLAN_NOTIFICATION_DATA data, void* args);
private:
bool m_connected = false;
bool m_reconnect = false;
char m_lastError[256] = { "未知错误" };
HANDLE m_handle = INVALID_HANDLE_VALUE;
PWLAN_INTERFACE_INFO_LIST m_infoList = nullptr;
WifiInfo m_wifiInfo = { 0 };
};
#include "WifiMgr.h"
#include <stdio.h>
#include <string>
WifiMgr::WifiMgr()
{
}
WifiMgr::~WifiMgr()
{
if (m_connected)
{
disconnect();
}
}
bool WifiMgr::connect(const char* account, const char* password, const char* mode,
const char* auth, const char* encrypt)
{
bool result = false;
do
{
if (!m_reconnect)
{
strcpy(m_wifiInfo.account, account);
strcpy(m_wifiInfo.password, password);
strcpy(m_wifiInfo.mode, mode);
strcpy(m_wifiInfo.auth, auth);
strcpy(m_wifiInfo.encrypt, encrypt);
}
unsigned long version = 0, value = 0;
value = WlanOpenHandle(WLAN_API_VERSION, nullptr, &version, &m_handle);
if (value != ERROR_SUCCESS)
{
sprintf(m_lastError, "打开WIFI句柄失败,错误代码:%lu", value);
break;
}
value = WlanEnumInterfaces(m_handle, nullptr, &m_infoList);
if (value != ERROR_SUCCESS)
{
disconnect();
sprintf(m_lastError, "枚举WIFI接口失败,错误代码:%lu", value);
break;
}
std::string character = std::string(password);
for (std::string::size_type pos = 0; pos != std::string::npos; pos += strlen("&"))
{
pos = character.find("&", pos);
if (pos != std::string::npos)
character.replace(pos, strlen("&"), "&");
else
break;
}
char xmlBuffer[4096] = { 0 };
sprintf(xmlBuffer, "<?xml version =\"1.0\"?>\
<WLANProfile xmlns =\"http://www.microsoft.com/networking/WLAN/profile/v1\">\
<name>%s</name>\
<SSIDConfig>\
<SSID>\
<name>%s</name>\
</SSID>\
</SSIDConfig>\
<connectionType>ESS</connectionType>\
<connectionMode>%s</connectionMode>\
<autoSwitch>false</autoSwitch>\
<MSM>\
<security>\
<authEncryption>\
<authentication>%s</authentication>\
<encryption>%s</encryption>\
<useOneX>false</useOneX>\
</authEncryption>\
<sharedKey>\
<keyType>passPhrase</keyType>\
<protected>false</protected>\
<keyMaterial>%s</keyMaterial>\
</sharedKey>\
</security>\
</MSM>\
</WLANProfile>",
account, account, mode, auth, encrypt, character.c_str());
wchar_t fileData[4096] = { 0 };
int length = strlen(xmlBuffer);
for (int j = 0; j < length; j++)
{
mbtowc(&fileData[j], &xmlBuffer[j], 1);
}
fileData[length] = '\0';
WLAN_REASON_CODE reasonCode = 0;
value = WlanSetProfile(m_handle, &m_infoList->InterfaceInfo[0].InterfaceGuid,
0, fileData, nullptr, TRUE, nullptr, &reasonCode);
if (value != ERROR_SUCCESS)
{
disconnect();
sprintf(m_lastError, "设置WIFI配置文件失败,错误代码:%lu", value);
break;
}
wchar_t wideSsid[512] = { 0 };
if (!MultiByteToWideChar(CP_ACP, 0, account, strlen(account) + 1,
wideSsid, sizeof(wideSsid) / sizeof(wideSsid[0])))
{
disconnect();
sprintf(m_lastError, "多字符转宽字符失败,错误代码:%lu", GetLastError());
break;
}
DOT11_SSID dot11Ssid = { 0 };
memcpy(dot11Ssid.ucSSID, account, strlen(account) + 1);
dot11Ssid.uSSIDLength = strlen(account);
WLAN_CONNECTION_PARAMETERS connectionParameters;
memset(&connectionParameters, 0, sizeof(connectionParameters));
connectionParameters.pDot11Ssid = &dot11Ssid;
connectionParameters.wlanConnectionMode = wlan_connection_mode_profile;
connectionParameters.strProfile = wideSsid; /* clear 可以填nullptr */
connectionParameters.dot11BssType = dot11_BSS_type_any;//dot11_BSS_type_independent; /* msdn说可以dot11_BSS_type_any,实测不行 */
connectionParameters.pDesiredBssidList = nullptr;
connectionParameters.dwFlags = 0; /* WLAN_CONNECTION_ADHOC_JOIN_ONLY */
Sleep(300);
value = WlanConnect(m_handle, &m_infoList->InterfaceInfo[0].InterfaceGuid,
&connectionParameters, nullptr);
if (value != ERROR_SUCCESS)
{
disconnect();
sprintf(m_lastError, "连接WIFI失败,错误代码:%lu", value);
break;
}
//value = WlanRegisterNotification(m_handle, WLAN_NOTIFICATION_SOURCE_ALL, false,
// wlanNotification, this, nullptr, nullptr);
//if (value != ERROR_SUCCESS)
//{
// sprintf(m_lastError, "注册通知失败,错误代码:%lu", value);
// break;
//}
m_connected = true;
result = true;
} while (false);
return result;
}
bool WifiMgr::connect(const WifiInfo& info)
{
return connect(info.account, info.password, info.mode, info.auth, info.encrypt);
}
bool WifiMgr::reconnect()
{
bool result = false;
m_reconnect = true;
result = disconnect() && connect(m_wifiInfo);
m_reconnect = false;
return result;
}
bool WifiMgr::disconnect(bool removeProFile)
{
bool result = true;
do
{
unsigned long value = 0;
if (removeProFile)
{
wchar_t profile[256] = { 0 };
if (MultiByteToWideChar(CP_ACP, 0, m_wifiInfo.account, strlen(m_wifiInfo.account) + 1,
profile, sizeof(profile) / sizeof(profile[0])))
{
if (m_handle != INVALID_HANDLE_VALUE && m_infoList)
{
WlanDeleteProfile(m_handle, &(m_infoList->InterfaceInfo->InterfaceGuid), profile, nullptr);
}
}
}
if (m_handle != INVALID_HANDLE_VALUE && m_infoList)
{
WlanDisconnect(m_handle, &(m_infoList->InterfaceInfo->InterfaceGuid), nullptr);
}
if (m_handle != INVALID_HANDLE_VALUE)
{
WlanCloseHandle(m_handle, nullptr);
m_handle = INVALID_HANDLE_VALUE;
}
if (m_infoList)
{
WlanFreeMemory(m_infoList);
m_infoList = nullptr;
}
m_connected = false;
} while (false);
return result;
}
bool WifiMgr::connected() const
{
return m_connected;
}
const char* WifiMgr::getLastError() const
{
return m_lastError;
}
void WifiMgr::wlanNotification(PWLAN_NOTIFICATION_DATA data, void* args)
{
WifiMgr* wifi = static_cast<WifiMgr*>(args);
if (!wifi)
return;
unsigned long source = data->NotificationSource;
unsigned long code = data->NotificationCode;
unsigned long size = data->dwDataSize;
const char* action = "unknown";
if (source == WLAN_NOTIFICATION_SOURCE_ACM)
{
switch (source)
{
case wlan_notification_acm_start:
action = "acm_start";
break;
case wlan_notification_acm_autoconf_enabled:
action = "acm_autoconf_enabled";
break;
case wlan_notification_acm_autoconf_disabled:
action = "acm_autoconf_disabled";
break;
case wlan_notification_acm_background_scan_enabled:
action = "acm_background_scan_enabled";
break;
case wlan_notification_acm_background_scan_disabled:
action = "acm_background_scan_disabled";
break;
case wlan_notification_acm_bss_type_change:
action = "acm_bss_type_change";
break;
case wlan_notification_acm_power_setting_change:
action = "acm_power_setting_change";
break;
case wlan_notification_acm_scan_complete:
action = "acm_scan_complete";
break;
case wlan_notification_acm_scan_fail:
action = "acm_scan_fail";
break;
case wlan_notification_acm_connection_start:
action = "acm_connection_start";
break;
case wlan_notification_acm_connection_complete:
action = "acm_connection_complete";
break;
case wlan_notification_acm_connection_attempt_fail:
action = "acm_connection_attempt_fail";
break;
case wlan_notification_acm_filter_list_change:
action = "acm_filter_list_change";
break;
case wlan_notification_acm_interface_arrival:
action = "acm_interface_removal";
break;
case wlan_notification_acm_interface_removal:
action = "acm_interface_removal";
break;
case wlan_notification_acm_profile_change:
action = "acm_profile_change";
break;
case wlan_notification_acm_profile_name_change:
action = "acm_profile_name_change";
break;
case wlan_notification_acm_profiles_exhausted:
action = "acm_profiles_exhausted";
break;
case wlan_notification_acm_network_not_available:
action = "acm_network_not_available";
break;
case wlan_notification_acm_network_available:
action = "acm_network_available";
break;
case wlan_notification_acm_disconnecting:
action = "acm_disconnecting";
break;
case wlan_notification_acm_disconnected:
action = "acm_disconnected";
break;
case wlan_notification_acm_adhoc_network_state_change:
action = "acm_adhoc_network_state_change";
break;
case wlan_notification_acm_end:
action = "acm_end";
break;
default:break;
}
}
else if (source == WLAN_NOTIFICATION_SOURCE_MSM)
{
switch (code)
{
case wlan_notification_msm_start:
action = "msm_start";
break;
case wlan_notification_msm_associating:
{
auto ptr = ((PWLAN_MSM_NOTIFICATION_DATA)data->pData);
}
action = "msm_associating";
break;
case wlan_notification_msm_associated:
{
auto ptr = ((PWLAN_MSM_NOTIFICATION_DATA)data->pData);
}
action = "msm_associated";
break;
case wlan_notification_msm_authenticating:
{
auto ptr = ((PWLAN_MSM_NOTIFICATION_DATA)data->pData);
}
action = "msm_authenticating";
break;
case wlan_notification_msm_connected:
action = "msm_connected";
break;
case wlan_notification_msm_roaming_start:
action = "msm_roaming_start";
break;
case wlan_notification_msm_roaming_end:
action = "msm_roaming_end";
break;
case wlan_notification_msm_radio_state_change:
action = "msm_radio_state_change";
break;
case wlan_notification_msm_signal_quality_change:
action = "msm_signal_quality_change";
printf("信号质量:%lu\n", *(unsigned long*)data->pData);
break;
case wlan_notification_msm_disassociating:
action = "msm_disassociating";
break;
case wlan_notification_msm_disconnected:
{
auto ptr = ((PWLAN_MSM_NOTIFICATION_DATA)data->pData);
}
action = "msm_disconnected";
break;
case wlan_notification_msm_peer_join:
action = "msm_peer_join";
break;
case wlan_notification_msm_peer_leave:
action = "msm_peer_leave";
break;
case wlan_notification_msm_adapter_removal:
action = "msm_adapter_removal";
break;
case wlan_notification_msm_adapter_operation_mode_change:
action = "msm_adapter_operation_mode_change";
break;
case wlan_notification_msm_end:
action = "msm_end";
break;
default:break;
}
}
printf("source %d,code %d,size %d,action %s\n", source, code, size, action);
return;
}