在windows下C++使用Native wifi API获取SSID和连接信息

在linux下获取当前连接的信息很是轻松的,但是在windows下相对比较复杂,虽然可以考虑使用cmd命令获取网卡的信息并分析出当前连接的SSID,但是对于网络环境比较复杂的情况下其实我们同样可以使用Native wifi API获取目前的连接信息。

原理是通过打开网卡设备获取其连接信息,并提供给我们的程序使用。在此对网上的一些资料做了一些整理和总结。

一、首先是我们所需要的结构体:

typedef struct _WLAN_AVAILABLE_NETWORK {
  WCHAR                  strProfileName[WLAN_MAX_NAME_LENGTH];
  DOT11_SSID             dot11Ssid;
  DOT11_BSS_TYPE         dot11BssType;
  ULONG                  uNumberOfBssids;
  BOOL                   bNetworkConnectable;
  WLAN_REASON_CODE       wlanNotConnectableReason;
  ULONG                  uNumberOfPhyTypes;
  DOT11_PHY_TYPE         dot11PhyTypes[WLAN_MAX_PHY_TYPE_NUMBER];
  BOOL                   bMorePhyTypes;
  WLAN_SIGNAL_QUALITY    wlanSignalQuality;
  BOOL                   bSecurityEnabled;
  DOT11_AUTH_ALGORITHM   dot11DefaultAuthAlgorithm;
  DOT11_CIPHER_ALGORITHM dot11DefaultCipherAlgorithm;
  DWORD                  dwFlags;
  DWORD                  dwReserved;
} WLAN_AVAILABLE_NETWORK, *PWLAN_AVAILABLE_NETWORK;

具体参考微软的API描述清晰明了: 

Members:

strProfileName

Contains the profile name associated with the network. If the network does not have a profile, this member will be empty. If multiple profiles are associated with the network, there will be multiple entries with the same SSID in the visible network list. Profile names are case-sensitive. This string must be NULL-terminated.

dot11Ssid

DOT11_SSID structure that contains the SSID of the visible wireless network.

dot11BssType

DOT11_BSS_TYPE value that specifies whether the network is infrastructure or ad hoc.

uNumberOfBssids

Indicates the number of BSSIDs in the network.

Windows XP with SP3 and Wireless LAN API for Windows XP with SP2:  uNumberofBssids is at most 1, regardless of the number of access points broadcasting the SSID.

bNetworkConnectable

Indicates whether the network is connectable or not. If set to TRUE, the network is connectable, otherwise the network cannot be connected to.

wlanNotConnectableReason

A WLAN_REASON_CODE value that indicates why a network cannot be connected to. This member is only valid whenbNetworkConnectable is FALSE.

uNumberOfPhyTypes

The number of PHY types supported on available networks. The maximum value of uNumberOfPhyTypes is WLAN_MAX_PHY_TYPE_NUMBER, which has a value of 8. If more than WLAN_MAX_PHY_TYPE_NUMBER PHY types are supported, bMorePhyTypes must be set to TRUE.

dot11PhyTypes

Contains an array of DOT11_PHY_TYPE values that represent the PHY types supported by the available networks. When uNumberOfPhyTypes is greater than WLAN_MAX_PHY_TYPE_NUMBER, this array contains only the first WLAN_MAX_PHY_TYPE_NUMBER PHY types.

ValueMeaning

dot11_phy_type_unknown

Specifies an unknown or uninitialized PHY type.

dot11_phy_type_any

Specifies any PHY type.

dot11_phy_type_fhss

Specifies a frequency-hopping spread-spectrum (FHSS) PHY. Bluetooth devices can use FHSS or an adaptation of FHSS.

dot11_phy_type_dsss

Specifies a direct sequence spread spectrum (DSSS) PHY.

dot11_phy_type_irbaseband

Specifies an infrared (IR) baseband PHY.

dot11_phy_type_ofdm

Specifies an orthogonal frequency division multiplexing (OFDM) PHY. 802.11a devices can use OFDM.

dot11_phy_type_hrdsss

Specifies a high-rate DSSS (HRDSSS) PHY.

dot11_phy_type_erp

Specifies an extended rate PHY (ERP). 802.11g devices can use ERP.

dot11_phy_type_ht

Specifies an 802.11n PHY type.

dot11_phy_type_vht

Specifies the 802.11ac PHY type. This is the very high throughput PHY type specified in IEEE 802.11ac.

This value is supported on Windows 8.1, Windows Server 2012 R2, and later.

dot11_phy_type_IHV_start

Specifies the start of the range that is used to define PHY types that are developed by an independent hardware vendor (IHV).

dot11_phy_type_IHV_end

Specifies the end of the range that is used to define PHY types that are developed by an independent hardware vendor (IHV).

bMorePhyTypes

Specifies if there are more than WLAN_MAX_PHY_TYPE_NUMBER PHY types supported.

When this member is set to TRUE, an application must call WlanGetNetworkBssList to get the complete list of PHY types. The returned WLAN_BSS_LIST structure has an array of WLAN_BSS_ENTRY structures. The uPhyId member of the WLAN_BSS_ENTRYstructure contains the PHY type for an entry.

wlanSignalQuality

A percentage value that represents the signal quality of the network. WLAN_SIGNAL_QUALITY is of type ULONG. This member contains a value between 0 and 100. A value of 0 implies an actual RSSI signal strength of -100 dbm. A value of 100 implies an actual RSSI signal strength of -50 dbm. You can calculate the RSSI signal strength value for wlanSignalQuality values between 1 and 99 using linear interpolation.

bSecurityEnabled

Indicates whether security is enabled on the network. A value of TRUE indicates that security is enabled, otherwise it is not.

dot11DefaultAuthAlgorithm

DOT11_AUTH_ALGORITHM value that indicates the default authentication algorithm used to join this network for the first time.

dot11DefaultCipherAlgorithm

DOT11_CIPHER_ALGORITHM value that indicates the default cipher algorithm to be used when joining this network.

dwFlags

Contains various flags for the network.

ValueMeaning

WLAN_AVAILABLE_NETWORK_CONNECTED

This network is currently connected.

WLAN_AVAILABLE_NETWORK_HAS_PROFILE

There is a profile for this network.

dwReserved

Reserved for future use. Must be set to NULL.

二、打开Wlan设备,获取设备资源句柄:

DWORD WINAPI 
WlanOpenHandle( 
__in        DWORD dwClientVersion,
__reserved  PVOID pReserved, 
__out       PDWORD pdwNegotiatedVersion, 
__out       PHANDLE phClientHandle
);

其中:

dwClientVersion:对于windows XP 的SP2或者SP3版本,取值为 1

                              对于Windows Vista 和WindowsServer 2008 取值为 2

pReserved:取值为NULL

pdwNegotiatedVersion :返回参数,返回当前使用的version,比如你在xpsp2下它就返回1。

phClientHandle :Specifies a handle for the client to use in this session. This handle is used by other functions throughout the session(即wifi设备的句柄,在整个扫描或者连接wifi过程中都会被用到)。

Return value:成功返回ERROR_SUCCESS,错误会返回错误代码。

且在MSDN上:

WlanOpenHandle will return an error message if the Wireless Zero Configuration (WZC) service has not been started or if the WZC service is not responsive.(必须启动WZC服务,不然WlanOpenHandle 返回失败)。

三、通过WlanEnumInterfaces列出无线网卡设备

DWORD WINAPI
WlanEnumInterfaces(
    __in HANDLE hClientHandle,
    __reserved PVOID pReserved,
    __deref_out PWLAN_INTERFACE_INFO_LIST *ppInterfaceList
);

hClientHandle :通过WlanOpenHandle获取的wifi设备资源的句柄(The client's session handle, obtained by a previous call to the WlanOpenHandle function.)。

pReserved :NULL

ppInterfaceList :指针结构体,它是存储wireless LANinterfaces 的一个结构体。Pointer to a WLAN_INTERFACE_INFO_LIST structure that contains the list of NIC interfaces.(网卡接口信息列表结构的指针,NIC:Network Interface Card,也就是网络适配器/网卡),This function will allocate memory for the list of returned interfaces. The caller is responsible for freeing this memory using the WlanFreeMemory function(意思就是你传一个空指针的地址进去就行了,系统自动分配,你记得用完后用WlanFreeMemory释放)。
Return value:成功返回ERROR_SUCCESS,错误会返回错误代码。


对于WLAN_INTERFACE_INFO_LIST

typedef struct _WLAN_INTERFACE_INFO_LIST {
  DWORD               dwNumberOfItems;
  DWORD               dwIndex;
#if ...
  WLAN_INTERFACE_INFO *InterfaceInfo[];
#else
  WLAN_INTERFACE_INFO InterfaceInfo[1];
#endif
} WLAN_INTERFACE_INFO_LIST, *PWLAN_INTERFACE_INFO_LIST;

dwNumberOfItems:

Contains the number of items in the InterfaceInfo member(InterfaceInfo[ ] 中包含的单元的个数)

dwIndex:

The index of the current item. The index of the first item is 0. dwIndex must be less than dwNumberOfItems.

This member is not used by the wireless service. Applications can use this member when processing individual interfaces in theWLAN_INTERFACE_INFO_LIST structure. When an application passes this structure from one function to another, it can set the value of dwIndex to the index of the item currently being processed. This can help an application maintain state.

dwIndex should always be initialized before use.

0到dwNumberOfItems-1, 一般用于在 WLAN_INTERFACE_INFO_LIST 作为参数传递时的一个传递偏移量。这个参数在用之前必须要进行初始化

InterfaceInfo[ ]:

An array of WLAN_INTERFACE_INFO structures containing interface information.(包含LAN_INTERFACE_INFO 结构体的阵列,用于记录接口信息)。其描述如下:

typedef struct _WLAN_INTERFACE_INFO {
  GUID                 InterfaceGuid;
  WCHAR                strInterfaceDescription[WLAN_MAX_NAME_LENGTH];
  WLAN_INTERFACE_STATE isState;
} WLAN_INTERFACE_INFO, *PWLAN_INTERFACE_INFO;

InterfaceGuid:

Contains the GUID of the interface.(接口的GUID,GUID:Globally Unique Identifier(全球唯一标识符),据称是根椐时间,网卡,机器名等结合算法生成的,所以唯一,所以调用者在某些函数中可以通过GUID来指定特定网卡)。

strInterfaceDescription:

Contains the description of the interface.(接口的描绘信息,打开设备管理器-无线网卡属性可以看到描述)

isState:

Contains a WLAN_INTERFACE_STATE value that indicates the current state of the interface.

Windows XP with SP3 and Wireless LAN API for Windows XP with SP2:  Only the wlan_interface_state_connected,  wlan_interface_state_disconnected,  and wlan_interface_state_authenticating values are supported.(包含一个 WLAN_INTERFACE_STATE值,标示这个NIC接口的当前状态)。其详细如下:

typedef enum _WLAN_INTERFACE_STATE {
  wlan_interface_state_not_ready,
  wlan_interface_state_connected,
  wlan_interface_state_ad_hoc_network_formed,
  wlan_interface_state_disconnecting,
  wlan_interface_state_disconnected,
  wlan_interface_state_associating,
  wlan_interface_state_discovering,
  wlan_interface_state_authenticating
} WLAN_INTERFACE_STATE, *PWLAN_INTERFACE_STATE;

WirelessLAN API for Windows XP SP2:

Only the wlan_interface_state_connected, wlan_interface_state_disconnected, and wlan_interface_state_authenticating values are supported.(xpsp2下仅支持已连接,已断开,生效中这三种状态)。

四、通过WlanGetAvailableNetworkList获得有效的无线网络信息 

DWORD WlanGetAvailableNetworkList(
  HANDLE                       hClientHandle,
  const GUID                   *pInterfaceGuid,
  DWORD                        dwFlags,
  PVOID                        pReserved,
  PWLAN_AVAILABLE_NETWORK_LIST *ppAvailableNetworkList
);

hClientHandle:

The client's session handle, obtained by a previous call to the WlanOpenHandle function.(WlanOpenHandle返回的那个客户端句柄)

pInterfaceGuid:

The GUID of the interface to be queried.(上面 WLAN_INTERFACE_INFO 的GUID,也就是网卡的GUID)

dwFlags:

Controls the type of networks returned in the list(控制ppAvailableNetworkList中获得的网络类型),其值为0,1,2,3(1和2组合)四种选择

1:Include all ad-hoc network profiles in the available network list, including profiles that are not visible.(ad-hoc network :即点对点方式的无线网络,包括profiles name(配置文件名称)不可见(获得profiles name字符为空)的所有点对对无线网络)

2:Include all hidden network profiles in the available network list, including profiles that are not visible.(包括profiles name(配置文件名称)不可见(获得profiles name字符为空)的所有隐藏网络配置)

3:前二者的组合

ppAvailableNetworkList:Pointer to a WLAN_AVAILABLE_NETWORK_LIST to receive the returned list of visible networks.(无线网络列表)This function will allocate memory for the list of returned interfaces. The caller is responsible for freeing this memory using the WlanFreeMemory function(传一个空指针的地址进去就行了,系统自动分配,调用者负责用WlanFreeMemory释放)

这个结构和WLAN_INTERFACE_INFO_LIST 相仿.

简单demo

int GetInfo()
{ 
    int id = 0;
	HANDLE ClientHandle;
	DWORD nv, i, j;
	PWLAN_INTERFACE_INFO_LIST ilist;
	PWLAN_AVAILABLE_NETWORK_LIST nlist;
	static char ssid[36];
	setlocale(LC_ALL, "chs");
	if (WlanOpenHandle(1, 0, &nv, &ClientHandle) == 0)
	{
		if (WlanEnumInterfaces(ClientHandle, 0, &ilist) == 0)
		{
			for (i = 0; i < ilist->dwNumberOfItems; i++)
			{
				wprintf(L"网卡: %s\n\n", ilist->InterfaceInfo[i].strInterfaceDescription);
				if (WlanGetAvailableNetworkList(ClientHandle, &ilist->InterfaceInfo[i].InterfaceGuid, 0, 0, &nlist) == 0)
				{
					for (j = 0; j < nlist->dwNumberOfItems; j++)
					{
						memcpy(ssid, nlist->Network[j].dot11Ssid.ucSSID, nlist->Network[j].dot11Ssid.uSSIDLength);
						ssid[nlist->Network[j].dot11Ssid.uSSIDLength] = 0;
						printf("%d. SSID:  %-25s  信号强度:  %5d\n", id++, ssid, nlist->Network[j].wlanSignalQuality);
						//可继续获取BSSID
						if (1)
						{
							PWLAN_BSS_LIST ppWlanBssList; //BSS网络列表
							auto dwResult = WlanGetNetworkBssList(
								ClientHandle,
								&ilist->InterfaceInfo[i].InterfaceGuid,
								&nlist->Network[j].dot11Ssid, nlist->Network[j].dot11BssType,
								nlist->Network[j].bSecurityEnabled,
								NULL, &ppWlanBssList);

							if (ERROR_SUCCESS == dwResult)
							{
								for (int k = 0; k < ppWlanBssList->dwNumberOfItems; k++)
								{
									printf("    %3 MAC:");
									printf("%02X:%02X:%02X:%02X:%02X:%02X",
										ppWlanBssList->wlanBssEntries[k].dot11Bssid[0],
										ppWlanBssList->wlanBssEntries[k].dot11Bssid[1],
										ppWlanBssList->wlanBssEntries[k].dot11Bssid[2],
										ppWlanBssList->wlanBssEntries[k].dot11Bssid[3],
										ppWlanBssList->wlanBssEntries[k].dot11Bssid[4],
										ppWlanBssList->wlanBssEntries[k].dot11Bssid[5]
										);
									printf("\n");
								}
							}
						}
					}
					WlanFreeMemory(nlist);
				}
			}
			WlanFreeMemory(ilist);
		}
		system("pause>nul");
		WlanCloseHandle(ClientHandle, 0);
	}
	system("pause");
	return true;
}

至此通过wlanapi获取无线网络信息基本完成,可以获取当前无线连接SSID,或进行下一步操作。

参考文章:Native wifi API使用_hgy413的专栏-CSDN博客_native wifi

Windows下无线局域网设备SSID和BSSID获取方法(C语言)_匿名用户_的博客-CSDN博客_无线网bssid和ssid

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值