C++ Windows下連線WIFI
阿新 • • 發佈:2021-01-30
廢話不多說直接上程式碼.
//WifiMgr.h #pragma once #include <windows.h> #include <wlanapi.h> #include <stdio.h> #include <iostream> #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 char* getLastError(); protected: static void _stdcall wlanNotification(PWLAN_NOTIFICATION_DATA data, void* args); private: bool m_connected = false; bool m_reconnect = false; char m_lastError[256] = { 0 }; HANDLE m_handle = INVALID_HANDLE_VALUE; PWLAN_INTERFACE_INFO_LIST m_infoList = { 0 }; WIFIInfo m_wifiInfo = { 0 }; };
//WifiMgr.cpp #include "WifiMgr.h" 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, NULL, &version, &m_handle); if (value != ERROR_SUCCESS) { sprintf(m_lastError, "開啟WIFI控制代碼失敗,錯誤程式碼:%lu", value); break; } value = WlanEnumInterfaces(m_handle, NULL, &m_infoList); if (value != ERROR_SUCCESS) { sprintf(m_lastError, "列舉WIFI介面失敗,錯誤程式碼:%lu", value); 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, password); 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'; WlanDisconnect(m_handle, &m_infoList->InterfaceInfo[0].InterfaceGuid, NULL); WLAN_REASON_CODE reasonCode = { 0 }; value = WlanSetProfile(m_handle, &(m_infoList->InterfaceInfo[0].InterfaceGuid), 0, fileData, NULL, TRUE, NULL, &reasonCode); if (value != ERROR_SUCCESS) { sprintf(m_lastError, "設定WIFI配置檔案失敗,錯誤程式碼:%lu", value); break; } wchar_t wideSsid[256] = { 0 }; if (!MultiByteToWideChar(CP_ACP, 0, account, strlen(account) + 1, wideSsid, sizeof(wideSsid) / sizeof(wideSsid[0]))) { 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 可以填NULL */ connectionParameters.dot11BssType = dot11_BSS_type_any;//dot11_BSS_type_independent; /* msdn說可以dot11_BSS_type_any,實測不行 */ connectionParameters.pDesiredBssidList = NULL; connectionParameters.dwFlags = 0; /* WLAN_CONNECTION_ADHOC_JOIN_ONLY */ Sleep(300); value = WlanConnect(m_handle, &(m_infoList->InterfaceInfo[0].InterfaceGuid), &connectionParameters, NULL); if (value != ERROR_SUCCESS) { sprintf(m_lastError, "連線WIFI失敗,錯誤程式碼:%lu", value); break; } value = WlanRegisterNotification(m_handle, WLAN_NOTIFICATION_SOURCE_ALL, false, wlanNotification, this, NULL, NULL); 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 { wchar_t profile[256] = { 0 }; if (!MultiByteToWideChar(CP_ACP, 0, m_wifiInfo.account, strlen(m_wifiInfo.account) + 1, profile, sizeof(profile) / sizeof(profile[0]))) { sprintf(m_lastError, "多字元轉寬字元失敗,錯誤程式碼:%lu", GetLastError()); break; } unsigned long value = 0; if (removeProFile) { value = WlanDeleteProfile(m_handle, &(m_infoList->InterfaceInfo->InterfaceGuid), profile, NULL); if (value != ERROR_SUCCESS) { sprintf(m_lastError, "刪除WIFI配置檔案%s失敗,錯誤程式碼:%lu", m_wifiInfo.account, value); result = false; } } value = WlanDisconnect(m_handle, &(m_infoList->InterfaceInfo->InterfaceGuid), NULL); if (value != ERROR_SUCCESS) { if (strlen(m_lastError)) { strcat(m_lastError, ","); } char temp[256] = { 0 }; sprintf(temp, "斷開WIFI失敗,錯誤程式碼:%lu", value); strcat(m_lastError, temp); result = false; } if (m_handle != INVALID_HANDLE_VALUE) { WlanCloseHandle(m_handle, NULL); m_handle = INVALID_HANDLE_VALUE; } WlanFreeMemory(m_infoList); m_connected = false; } while (false); return result; } bool WifiMgr::connected() { return m_connected; } const char* WifiMgr::getLastError() { 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); std::cout << "ating reason:" << ptr->wlanReasonCode << std::endl; } action = "msm_associating"; break; case wlan_notification_msm_associated: { auto ptr = ((PWLAN_MSM_NOTIFICATION_DATA)data->pData); std::cout << "ated reason:" << ptr->wlanReasonCode << std::endl; } action = "msm_associated"; break; case wlan_notification_msm_authenticating: { auto ptr = ((PWLAN_MSM_NOTIFICATION_DATA)data->pData); std::cout << "auth reason:" << ptr->wlanReasonCode << std::endl; } 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); std::cout << "dis reason:" << ptr->wlanReasonCode << std::endl; } 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; } int main() { std::cout << "base:" << WLAN_REASON_CODE_MSMSEC_KEY_SUCCESS_TIMEOUT << std::endl; printf("sizeof %d,%d\n",sizeof(WLAN_CONNECTION_NOTIFICATION_DATA),sizeof(WLAN_MSM_NOTIFICATION_DATA)); WifiMgr mgr; if (!mgr.connect("HONOR 9X PRO", "66666666")) { printf("連線wifi失敗\n"); } //Sleep(10000); //printf("斷開連線\n"); //mgr.disconnect(); //Sleep(10000); getchar(); return 0; }