0%

用代码实现扫描WIFI并连接(1)

简介

微软提供了一系列WLAN相关的API函数,用来处理WIFI扫描和连接等的任务,
并且在对应API的MSDN文档中也给出了一些示例代码,如下做了一些整理

工作原理

1.扫描WIFI接入点
1
2
3
#include <windows.h>
#include <wlanapi.h>
#pragma comment(lib, "wlanapi.lib")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
VOID CALLBACK SubScanProc(PWLAN_NOTIFICATION_DATA pData, PVOID pContext)
{
if (pData->NotificationCode == wlan_notification_acm_scan_complete)
{
OutputDebugStringW(L"scan ok!\n\n");
SetEvent((HANDLE)pContext); // 扫描完成
return;
}
if (pData->NotificationCode == wlan_notification_acm_scan_fail)
{
OutputDebugStringW(L"scan fail!\n\n");
SetEvent((HANDLE)pContext); // 扫描失败
return;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
DWORD SubScan(HANDLE hClient, PWLAN_INTERFACE_INFO pIfInfo)
{
HANDLE hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
if (!hEvent) return GetLastError();

// 注册WLAN通知
DWORD dwResult = WlanRegisterNotification(
hClient, WLAN_NOTIFICATION_SOURCE_ACM, TRUE,
SubScanProc, (PVOID)hEvent, NULL, NULL);
if (dwResult != ERROR_SUCCESS)
{
CloseHandle(hEvent);
return dwResult;
}

// 扫描WIFI接入点
dwResult = WlanScan(hClient, &pIfInfo->InterfaceGuid, NULL, NULL, NULL);
if (dwResult == ERROR_SUCCESS)
WaitForSingleObject(hEvent, INFINITE); // 等待扫描结果

// 取消WIFI通知
WlanRegisterNotification(
hClient, WLAN_NOTIFICATION_SOURCE_ACM, TRUE,
NULL, NULL, NULL, NULL);

CloseHandle(hEvent);

return dwResult;
}
2.获取当前可连接列表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
DWORD SubGetAvailableList(HANDLE hClient, PWLAN_INTERFACE_INFO pIfInfo)
{
PWLAN_AVAILABLE_NETWORK_LIST pBssList = NULL;
DWORD dwResult = WlanGetAvailableNetworkList(
hClient, &pIfInfo->InterfaceGuid, 0, NULL, &pBssList);
if (dwResult != ERROR_SUCCESS)
return dwResult;

for (DWORD j = 0; j < pBssList->dwNumberOfItems; j++)
{
PWLAN_AVAILABLE_NETWORK pBssEntry = &pBssList->Network[j];
// 保存的连接设置名
pBssEntry->strProfileName;
// WIFI的接入点名称
pBssEntry->dot11Ssid.uSSIDLength;
pBssEntry->dot11Ssid.ucSSID;
// 是否可以连接
pBssEntry->bNetworkConnectable;
// 无法连接的原因
pBssEntry->wlanNotConnectableReason;
// 信号的质量
int iRSSI = -100 + (pBssEntry->wlanSignalQuality / 2);
// 是否支持安全连接
pBssEntry->bSecurityEnabled;
// 默认使用的验证算法
pBssEntry->dot11DefaultAuthAlgorithm;
// 默认使用的加密算法
pBssEntry->dot11DefaultCipherAlgorithm;
// 接入点的状态和标志
pBssEntry->dwFlags & WLAN_AVAILABLE_NETWORK_CONNECTED; // 是否已连接
pBssEntry->dwFlags & WLAN_AVAILABLE_NETWORK_HAS_PROFILE; // 是否有配置

// 使用配置进行连接
if (!wcscmp(pBssEntry->strProfileName, L"CMCC") &&
!(pBssEntry->dwFlags & WLAN_AVAILABLE_NETWORK_CONNECTED) &&
(pBssEntry->dwFlags & WLAN_AVAILABLE_NETWORK_HAS_PROFILE))
{
SubConnect(hClient, pIfInfo, pBssEntry);
break;
}
}

if (pBssList)
WlanFreeMemory(pBssList);

return ERROR_SUCCESS;
}
3.使用配置进行连接
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
DWORD SubConnect(
HANDLE hClient,
PWLAN_INTERFACE_INFO pIfInfo,
PWLAN_AVAILABLE_NETWORK pBssEntry)
{
WLAN_CONNECTION_PARAMETERS ConnPara = {};
ConnPara.wlanConnectionMode = wlan_connection_mode_profile; // 使用配置
ConnPara.strProfile = pBssEntry->strProfileName;
ConnPara.pDot11Ssid = &pBssEntry->dot11Ssid;
ConnPara.dot11BssType = pBssEntry->dot11BssType;

DWORD dwResult = WlanConnect(hClient, &pIfInfo->InterfaceGuid, &ConnPara, NULL);
if (dwResult == ERROR_SUCCESS)
OutputDebugStringW("Connect ok!\n\n");
else
OutputDebugStringW("Connect fail!\n\n");

return dwResult;
}
4.打开WLAN设备并进行遍历
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
DWORD WlanControlRequest()
{
HANDLE hClient = NULL;
DWORD dwCurVersion = 0;
DWORD dwResult = WlanOpenHandle(2, NULL, &dwCurVersion, &hClient);
if (dwResult != ERROR_SUCCESS)
return dwResult;

// 遍历所有WLAN设备接口
PWLAN_INTERFACE_INFO_LIST pIfList = NULL;
dwResult = WlanEnumInterfaces(hClient, NULL, &pIfList);
if (dwResult != ERROR_SUCCESS)
{
WlanCloseHandle(hClient, NULL);
return dwResult;
}

for (DWORD i = 0; i < pIfList->dwNumberOfItems; i++)
{
PWLAN_INTERFACE_INFO pIfInfo = &pIfList->InterfaceInfo[i];
// 设备接口的GUID
pIfInfo->InterfaceGuid;
// 设备接口的描述信息
pIfInfo->strInterfaceDescription;
// 设备接口的状态
pIfInfo->isState == wlan_interface_state_connected; // 已连接
pIfInfo->isState == wlan_interface_state_disconnected; // 未连接

// 扫描WIFI接入点
SubScan(hClient, pIfInfo);

// 获取当前可连接列表
SubGetAvailableList(hClient, pIfInfo);
}

if (pIfList)
WlanFreeMemory(pIfList);

if (hClient)
WlanCloseHandle(hClient, NULL);

return ERROR_SUCCESS;
}