1. 程式人生 > 其它 >C++ Windows下連線WIFI

C++ Windows下連線WIFI

技術標籤:C++連線WIFIWindows連線WIFI

廢話不多說直接上程式碼.

//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;
}