第一步:打开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图形界面操作程序