WLAN API应用介绍(含实例程序)

时间:2023-02-21 20:48:24

第一步:打开WLAN服务 

bool CWLANConnectDlg::OpenWLANService()
{
dwResult = WlanOpenHandle(WLAN_API_VERSION    //客户端支持的WLAN API的最高版本
, NULL, &dwCurVersion    //指定这次会话中将会使用的版本
, &hClient    //指定客户端在这次会话中使用的句柄,这个句柄会贯穿整个会话被其他函数使用 。
);
     if(ERROR_SUCCESS != dwResult)
    {
        switch (dwResult)
        {
            case ERROR_INVALID_PARAMETER:    //参数一、四为空或参数二不为空
                wprintf(L"Para is NULL\n"); 
                break;
            case ERROR_NOT_ENOUGH_MEMORY:    //没有足够的内存空间
                wprintf(L"Failed to allocate memory \n");
                break; 
            case ERROR_REMOTE_SESSION_LIMIT_EXCEEDED:    //超过服务器限定的句柄数量
                wprintf(L"Server is Busy\n");
                break;
            default:
                dwResult = GetLastError();
                wprintf(L"WlanOpenHandle Fail:%wd\n", dwResult);
                break;
        }
return false;
    }
return true;
}
 

第二步:枚举处当前系统安装的所有无线网卡的接口信息。

WLAN_INTERFACE_INFO_LIST

   这个结构体是包含着网卡接口信息的阵列。

 typedef struct _WLAN_INTERFACE_INFO_LIST {
                 DWORD dwNumberOfItems;
                 DWORD dwIndex;
                 WLAN_INTERFACE_INFO InterfaceInfo[]; 
 } WLAN_INTERFACE_INFO_LIST, 
  *PWLAN_INTERFACE_INFO_LIST; 

       dwNumberOfItems InterfaceInfo[ ] 中包含的单元的个数。

       dwIndex :当前单元的索引,从0开始到 dwNumberOfItems-1。

                这个参数一般用于在 WLAN_INTERFACE_INFO_LIST 被用作参数传递时的一个传递偏移量。这个参数在用之前必须要进行初始化。

       InterfaceInfo[ ] :包含WLAN_INTERFACE_INFO 结构体的阵列,用于记录接口信息。

bool WLANNetwork()
{
dwResult = WlanEnumInterfaces(hClient    //客户端会话句柄。由 WlanOpenHandle 得到。
, NULL, &pInterfaceList    //指向包含无线网卡接口信息list的结构体 PWLAN_INTERFACE_INFO_LIST 的指针。
);
    if(ERROR_SUCCESS != dwResult)
    {
        switch (dwResult)
        {
        case ERROR_INVALID_PARAMETER:    //参数一、三为空,或参数二不为空
            wprintf(L"Para is NULL\n");
            break;
        case ERROR_INVALID_HANDLE:    //无效的句柄
            wprintf(L"Failed to INVALID HANDLE \n");
            break; 
        case ERROR_NOT_ENOUGH_MEMORY:    //没有足够的内存空间
            wprintf(L"Failed to allocate memory \n");
            break; 
        default:
            dwResult = GetLastError();
            wprintf(L"WlanEnumInterfaces Fail: %wd\n", dwResult);
            break;
        }
return false;
    }
wprintf(L"WlanEnumInterfaces Number %wd\n", pInterfaceList->dwNumberOfItems);    //输出网卡数量
return true;
}
 

第三步:搜索接口上可用的网络。

WLAN_AVAILABLE_NETWORK_LIST

结构体,包含可用网络(network)的信息的列表。

typedef struct _WLAN_AVAILABLE_NETWORK_LIST {
           DWORD dwNumberOfItems;
           DWORD dwIndex;
          WLAN_AVAILABLE_NETWORK Network[1]; 
 }  WLAN_AVAILABLE_NETWORK_LIST, 
  *PWLAN_AVAILABLE_NETWORK_LIST; 

  dwNumberOfItems :Network中包含的单元的个数

  dwIndex :当前单元的索引,从0开始到dwNumberOfItems-1;

当这个结构体作为参数时用到。用之前必须赋初值。

  Network :一个WLAN_AVAILABLE_NETWORK 的列表,包含接口信息。

WLAN_AVAILABLE_NETWORK

结构体,包含可用无线网络(network)单元的信息。

typedef struct _WLAN_AVAILABLE_NETWORK {
           WCHAR strProfileName[256];
           DOT11_SSID dot11Ssid;  //SSID
          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;

DOT11_BSS_TYPE

枚举类型,用于定义BSS网络的类型

typedef enum _DOT11_BSS_TYPE {
                   dot11_BSS_type_infrastructure,
                   dot11_BSS_type_independent,
                   dot11_BSS_type_any,
          } DOT11_BSS_TYPE, *PDOT11_BSS_TYPE;

dot11_BSS_type_infrastructure : 为 infrastructure BSS 网络。

dot11_BSS_type_independent :为independent BSS网络

dot11_BSS_type_any :是 infrastructure 或者 independent BSS网络

 

infrastructure BSS

中控型基本服务集 (BSS)是一个包含了一个接入点和一些站点的 802.11 网络。这个接入点将信息送入目标站点或者一个固定网络。

independent BSS

IBSS(Independent Basic Service Set) 独立基本服务集 。是一种无线拓扑结构,IEEE802.11标准的模式

bool SearchNet()
{   
    if (!OpenWLANService())
    {
        return false;
    }
    if (!WLANNetwork())
    {
        return false;
    } 
    for(nInterfaceNumber = 0; nInterfaceNumber < (int)pInterfaceList->dwNumberOfItems; nInterfaceNumber++)
    {
        /*获取网卡信息*/
        pInterface = (PWLAN_INTERFACE_INFO)&pInterfaceList->InterfaceInfo[nInterfaceNumber];


        /*获得网络信息列表*/
        dwResult = WlanGetAvailableNetworkList(hClient    //客户端的会话句柄
		, &pInterface->InterfaceGuid    //要搜索的接口的GUID
		, 0x00    //控制list中返回的网络的类型,XP SP2和SP3为零
		, NULL, &pNetList    //指向返回的可用网络的 WLAN_AVAILABLE_NETWORK_LIST 的指针
		);
        if(ERROR_SUCCESS != dwResult)
        {
            switch (dwResult)
            {
            case ERROR_INVALID_PARAMETER:    //参数四不为空,或其他参数为空
                wprintf(L"Para is NULL\n");
                break;
            case ERROR_INVALID_HANDLE:
                wprintf(L"Failed to INVALID HANDLE \n");
                break; 
            case ERROR_NOT_ENOUGH_MEMORY:
                wprintf(L"Failed to allocate memory \n");
                break;
            case ERROR_NDIS_DOT11_POWER_STATE_INVALID:    //广播关闭无法搜索
                wprintf(L"The radio for the interface is turned off \n");
                break;
            default:
                dwResult = GetLastError();
                wprintf(L"WlanGetAvailableNetworkList Fail: %wd\n", dwResult);
                break;
            }
		return false;
        }
        wprintf(L"WlanGetAvailableNetworkList Number %wd\n", pNetList->dwNumberOfItems);    //输出网络数量


        /*连接网络*/
	bool resultSearch = true;
        for(nNetNumber = 0; nNetNumber < pNetList->dwNumberOfItems; nNetNumber++)
        {
            /*获取网络信息,去重复*/
            pNet = (PWLAN_AVAILABLE_NETWORK)&pNetList->Network[nNetNumber];           
	if (strcmp(target.c_str(),(char*)pNet->dot11Ssid.ucSSID) || !resultSearch)
	{
		continue;
	}
	resultSearch = false;
	if (!SetProfile())
	{
		return false;
	}
	if (!WLANConnect())
	{
		return false;
	} 
    }
        /*释放网络信息列表*/
        if (NULL != pNetList)
        {
            WlanFreeMemory(pNetList);
            pNetList = NULL;
        }
    }
    /*释放网卡信息列表*/
    if(NULL != pInterfaceList)
    {
        WlanFreeMemory(pInterfaceList);
        pInterfaceList = NULL;
    }   
    printf("SUCESS\n");
    return true;
}


 

第四步:设置用户文件Profile

bool SetProfile()
{ 
	string szProfileXML("");  //Profile XML流
	wscProfileXML = NULL;
	/*组合参数XML码流*/ 
    	string szTemp("");
	// char p[1024];
    	/*头*/
    	szProfileXML += string("<?xml version=\"1.0\"?><WLANProfile xmlns=\"http://www.microsoft.com/networking/WLAN/profile/v1\"><name>");
    	/*name,一般与SSID相同*/
	szTemp = string((char*)pNet->dot11Ssid.ucSSID);    //配置文件名
    	szProfileXML += szTemp;
    	/*SSIDConfig*/
    	szProfileXML += string("</name><SSIDConfig><SSID><name>");
	szProfileXML += szTemp;    //已搜索到的网络对应的SSID
	szProfileXML += string("</name></SSID></SSIDConfig>");
	/*connectionType*/
	szProfileXML += string("<connectionType>");
	switch(pNet->dot11BssType)    //网络类型
    	{
        case dot11_BSS_type_infrastructure:
            szProfileXML += "ESS";
            break;
        case dot11_BSS_type_independent:
            szProfileXML += "IBSS";
            break;
        case dot11_BSS_type_any:
            szProfileXML += "Any";
            break;
        default:
            wprintf(L"Unknown BSS type");
            return false;
    	}
	/*MSM*/
	szProfileXML += string("</connectionType><MSM><security><authEncryption><authentication>");
	switch( pNet->dot11DefaultAuthAlgorithm)    //网络加密方式
    {
        case DOT11_AUTH_ALGO_80211_OPEN:
            szProfileXML += "open";
		wprintf(L"Open 802.11 authentication\n");
            break;
        case DOT11_AUTH_ALGO_80211_SHARED_KEY:
		szProfileXML += "shared";
            wprintf(L"Shared 802.11 authentication");
            break;
        case DOT11_AUTH_ALGO_WPA:
		szProfileXML += "WPA";
            wprintf(L"WPA-Enterprise 802.11 authentication\n");
            break;
        case DOT11_AUTH_ALGO_WPA_PSK:
		szProfileXML += "WPAPSK";
            wprintf(L"WPA-Personal 802.11 authentication\n");
            break;
        case DOT11_AUTH_ALGO_WPA_NONE:
		szProfileXML += "none";
            wprintf(L"WPA-NONE,not exist in MSDN\n");
            break;
        case DOT11_AUTH_ALGO_RSNA:
		szProfileXML += "WPA2";
            wprintf(L"WPA2-Enterprise 802.11 authentication\n");
            break;
        case DOT11_AUTH_ALGO_RSNA_PSK:
		szProfileXML += "WPA2PSK";
            wprintf(L"WPA2-Personal 802.11 authentication\n");
            break;
        default:
           wprintf(L"Unknown authentication");
   		return false;
    }
	szProfileXML += string("</authentication><encryption>");
	/*sprintf(p, "%d", pNet->dot11DefaultCipherAlgorithm);
	szProfileXML += string(p);*/
	switch(pNet->dot11DefaultCipherAlgorithm)
    {
        case DOT11_CIPHER_ALGO_NONE:
            szProfileXML += "none";
            break;
        case DOT11_CIPHER_ALGO_WEP40:
            szProfileXML += "WEP";
            break;
        case DOT11_CIPHER_ALGO_TKIP:
            szProfileXML += "TKIP";
            break;
        case DOT11_CIPHER_ALGO_CCMP:
            szProfileXML += "AES";
            break;
        case DOT11_CIPHER_ALGO_WEP104:
            szProfileXML += "WEP";
            break;        
        case DOT11_CIPHER_ALGO_WEP:
            szProfileXML += "WEP";
            break;
	  case DOT11_CIPHER_ALGO_WPA_USE_GROUP:
		wprintf(L"USE-GROUP not exist in MSDN");
        default:
            wprintf(L"Unknown encryption");
		return false;
    }
	//szProfileXML += string	("</encryption><useOneX>false</useOneX></authEncryption></security></MSM>");
        //如果加密方式为WEP,keyType必须改为networkKey
	szProfileXML += string	("</encryption></authEncryption><sharedKey><keyType>passPhrase</keyType><protected>false</protected><keyMaterial>");
	szProfileXML += targetKey;
	/*尾*/
	szProfileXML += string("</keyMaterial></sharedKey></security></MSM></WLANProfile>");
	/*XML码流转换成双字节*/
	wscProfileXML = StringToLPCWSTR(szProfileXML);
	if(NULL == wscProfileXML)
	{
		wprintf(L"Change wscProfileXML fail\n");
		return false;
	}
 	/*设置网络参数*/
    dwResult = WlanSetProfile(hClient, &pInterface->InterfaceGuid, 
        0x00    //设置用户文件类型
	, wscProfileXML    //用户文件内容
	, NULL    //在XP SP1和SP2下必须为NULL
	, FALSE    //是否覆盖已存在的用户文件
	, NULL    //在XP SP1和SP2下必须为NULL
	, &dwReasonCode);
    if(ERROR_SUCCESS != dwResult)
    {
        switch (dwResult)
        {
        case ERROR_INVALID_PARAMETER:    //参数一、二、四、八为空或在XP SP1和SP2下参数三不为0
            wprintf(L"Para is NULL\n");
            break;
        case ERROR_NO_MATCH:    //网络接口不支持的加密类型
            wprintf(L"NIC NOT SUPPORT\n");
            break; 
        case ERROR_NOT_ENOUGH_MEMORY:    //没有足够的内存空间
            wprintf(L"Failed to allocate memory \n");
            break;
        case ERROR_BAD_PROFILE:    //用户文件格式错误
            wprintf(L"The profile specified by strProfileXml is not valid \n");
            break;
        case ERROR_ALREADY_EXISTS:    //设置的用户文件已存在
            wprintf(L"strProfileXml specifies a network that already exists \n");
            break;
        case ERROR_ACCESS_DENIED:    //用户没有权限设置用户文件
            wprintf(L"The caller does not set the profile. \n");
            break;
        default:
            dwResult = GetLastError();
            wprintf(L"WlanSetProfile Fail: %wd\n", dwResult); 
            break;
        }
	if (dwResult != 183)
	{
		return false;
	}
    }
	return true;
}

第五步:连接一个指定的网络

WLAN_CONNECTION_PARAMETERS

  在使用WlanConnect 这个函数的时候,这个结构体需要作为参数来设定连接属性。

    typedef struct _WLAN_CONNECTION_PARAMETERS {
            WLAN_CONNECTION_MODE wlanConnectionMode;
           LPCWSTR strProfile;
            PDOT11_SSID pDot11Ssid;
            PDOT11_BSSID_LIST pDesiredBssidList;
            DOT11_BSS_TYPE dot11BssType;
            DWORD dwFlags; 
 } WLAN_CONNECTION_PARAMETERS, 
  *PWLAN_CONNECTION_PARAMETERS;
bool WLANConnect()
{
	pConnPara = (PWLAN_CONNECTION_PARAMETERS)calloc(1, sizeof(WLAN_CONNECTION_PARAMETERS));
    /*设置网络连接参数*/
    if(NULL == pConnPara)
    {
        wprintf(L"pConnPara fail\n");
    }
	pConnPara->wlanConnectionMode = (WLAN_CONNECTION_MODE)0; //XP SP2,SP3 must be 0
	pConnPara->strProfile = StringToLPCWSTR(target);    //指定的用户文件
	pConnPara->pDot11Ssid = &pNet->dot11Ssid;    //指定的SSID
	pConnPara->pDesiredBssidList = NULL; //XP SP2,SP3 must be NULL
	pConnPara->dot11BssType = pNet->dot11BssType;    //网络类型
	pConnPara->dwFlags = 0x00000000; //XP SP2,SP3 must be 0
   
    dwResult = WlanConnect(hClient    //客户端句柄
	, &pInterface->InterfaceGuid    //连接使用的接口的GUID
	, pConnPara    //指向结构体 WLAN_CONNECTION_PARAMETERS ,其中指定了连接类型,模式,网络概况,SSID 等其他参数。
	, NULL);
    if(ERROR_SUCCESS != dwResult)
    {
        switch (dwResult)
        {
        case ERROR_INVALID_PARAMETER:
            wprintf(L"Para is NULL\n");
            break;
        case ERROR_INVALID_HANDLE:
            wprintf(L"Failed to INVALID HANDLE \n");
            break; 
        case ERROR_ACCESS_DENIED:
            wprintf(L"The caller does not have sufficient permissions. \n");
            break;
        default:
            dwResult = GetLastError();
            wprintf(L"WlanConnect Fail: %wd\n", dwResult);
            break;
        }
		return false;
    }
	return true;
}


第六步:断开网络连接

bool WLANDisconnect()
{ 
    dwResult = WlanDisconnect(hClient, &pInterface->InterfaceGuid, NULL);
    if(ERROR_SUCCESS != dwResult)
    {
        switch (dwResult)
        {
        case ERROR_INVALID_PARAMETER:    //参数一、二为空
            wprintf(L"Para is NULL\n");
            break;
        case ERROR_INVALID_HANDLE:
            wprintf(L"Failed to INVALID HANDLE \n");
            break; 
        case ERROR_NOT_ENOUGH_MEMORY:
            wprintf(L"Failed to allocate memory \n");
            break;
        case ERROR_ACCESS_DENIED:
            wprintf(L"The caller does not have sufficient permissions. \n");
            break;
        default:
            dwResult = GetLastError();
            wprintf(L"WlanConnect Fail: %wd\n", dwResult);
            break;
        }
	if (pProfileXml != NULL) 
	{
		WlanFreeMemory(pProfileXml);	//所有API用到的参数,都要使用API提供的函数去释放
		pProfileXml = NULL;
	}
        free(pConnPara);
		return false;
    	}
	return true;
}

第七步:关闭与服务器间的连接

bool CloseWLANService()
{
	 if(NULL != hClient)
     	{
        dwResult = WlanCloseHandle(hClient    //要关闭的连接的客户端句柄
		, NULL);
        if(ERROR_SUCCESS != dwResult)
        {
            switch (dwResult)
            {
            case ERROR_INVALID_PARAMETER:    //参数一为空或参数二不为空
                wprintf(L"Para is NULL\n");
                break;
            case ERROR_INVALID_HANDLE:
                wprintf(L"Failed to INVALID HANDLE \n");
                break; 
            default:
                dwResult = GetLastError();
                wprintf(L"WlanCloseHandle Fail: %wd\n", dwResult);
                break;
            }
		return false;
        }
        hClient = NULL;
      }
 	return true;
}


附加:

查询网卡连接状态,每次查询都必须使用WlanEnumInterfaces获得新的网卡列表。

    PWLAN_INTERFACE_INFO_LIST pIfList = NULL;
    PWLAN_INTERFACE_INFO pIfInfo = NULL;
    dwResult = WlanEnumInterfaces(hClient, NULL, &pIfList); 
    if (dwResult != ERROR_SUCCESS)  {
        wprintf(L"WlanEnumInterfaces failed with error: %u\n", dwResult);
        // FormatMessage can be used to find out why the function failed
        return 1;
    }
    pIfInfo = (WLAN_INTERFACE_INFO *) &pIfList->InterfaceInfo[0];
    switch (pIfInfo->isState) {
            case wlan_interface_state_not_ready:
                wprintf(L"Not ready\n");
                break;
            case wlan_interface_state_connected:
                wprintf(L"Connected\n");
                break;
            case wlan_interface_state_ad_hoc_network_formed:
                wprintf(L"First node in a ad hoc network\n");
                break;
            case wlan_interface_state_disconnecting:
                wprintf(L"Disconnecting\n");
                break;
            case wlan_interface_state_disconnected:
                wprintf(L"Not connected\n");
                break;
            case wlan_interface_state_associating:
                wprintf(L"Attempting to associate with a network\n");
                break;
            case wlan_interface_state_discovering:
                wprintf(L"Auto configuration is discovering settings for the network\n");
                break;
            case wlan_interface_state_authenticating:
                wprintf(L"In process of authenticating\n");
                break;
            default:
                wprintf(L"Unknown state %ld\n", pIfInfo->isState);
                break;
    }

CSDN源码:

WLAN控制台程序

WLAN图形界面操作程序

PUDN源码:

WLAN控制台程序

WLAN图形界面操作程序