在 Windows CE 下自带有无线网卡的配置和连接程序,但是如果系统剪裁掉了资源管理器和任务栏,或者再CE的很多应用中,是不允许用户回到桌面去调用系统的连接程序的,这篇文章就来谈一下如何用那么可以利用微软自带的WZC函数来重新编写一个独立于系统的WIFI连接程序。
连接WIFI网络有这么几个步骤,第一步,要获取你自己的网卡,调用GetFirstWirelessNetworkCard()来实现。第二步,要获得当前环境中的无线网信息,调用GetWirelessCardInfo来取得这些信息,调用GetWirelseeListSSID来解析这些信息,接下来把取得的无线网SSID和自己输入的密码用AddToPreferredNetworkList()传到WINDOWS的首选无线网列表中,windows就会自动连接这个无线网络。
下面是一整套通过WZC函数连接无线网的程序,我自己测试后保证可以运行,如有需要全部源码或者动态库文件的,请留言或者留下邮箱
调用WZC函数需要包含的文件和库如下:
#include <eaputil.h>
#include <pm.h>
#include <wzcsapi.h>
#include <iphlpapi.h>
#pragma comment(lib,"Iphlpapi.lib")
#pragma comment(lib,"Wzcsapi.lib")
#pragma comment(lib,"cclib.lib")
存放SSID的基本信息的数据结构:
/*SSID基本信息*/
typedef struct tag_SsidInfo
{
wstring sSsid;
int nRssi;
NDIS_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode;
ULONG ulPrivacy;
NDIS_802_11_AUTHENTICATION_MODE AuthenticationMode;
int iKeyIndex;
wstring pKey;
int iEapType;
}SsidInfo;
接下来看关键函数的具体实现:
1.取得无线网卡
BOOL GetFirstWirelessCard(PTCHAR pCard)
{
WifiCallBack=NULL;
if (!pCard)
{
return FALSE;
}
INTFS_KEY_TABLE IntfsTable;
IntfsTable.dwNumIntfs = 0;
IntfsTable.pIntfs = NULL;
_tcscpy(pCard, TEXT(""));
// 枚举系统中可用的无线网卡
DWORD dwStatus = WZCEnumInterfaces(NULL, &IntfsTable);
if (dwStatus != ERROR_SUCCESS)
{
RETAILMSG(1, (TEXT("WZCEnumInterfaces() error 0x%08X\n"),dwStatus));
return FALSE;
}
// 判断无线网卡的数量,可以根据无线网卡数量来枚举出所有可用的无线网卡
if (!IntfsTable.dwNumIntfs)
{
RETAILMSG(1, (TEXT("System has no wireless card.\n")));
return FALSE;
}
_tcscpy(pCard, IntfsTable.pIntfs[0].wszGuid);
LocalFree(IntfsTable.pIntfs);
return TRUE;
}
2.从无线网卡取得无线网络信息
//////////////////////////////////////////////////////////////////////////
// pCard: 无线网卡 GUID
// pIntf: 无线网卡配置信息结果体
// pOutFlags: 网卡配置信息掩码标志
//////////////////////////////////////////////////////////////////////////
BOOL GetWirelessCardInfo(PTCHAR pCard, PINTF_ENTRY_EX pIntf, PDWORD pOutFlags)
{
TCHAR *szWiFiCard = NULL;
// 参数校验
if (!pCard || !pIntf || !pOutFlags)
{
//RETAILMSG(1, (TEXT("Param Error.\n")));
return FALSE;
}
szWiFiCard = pCard;
*pOutFlags = 0;
// 初始化无线网卡信息
ZeroMemory(pIntf, sizeof(INTF_ENTRY_EX));
// 设置 GUID 号
pIntf->wszGuid = szWiFiCard;
// 查询无线网卡信息
DWORD dwStatus = WZCQueryInterfaceEx(NULL, INTF_ALL, pIntf, pOutFlags);
if (dwStatus != ERROR_SUCCESS)
{
//RETAILMSG(1, (TEXT("WZCQueryInterfaceEx() error 0x%08X\n"), dwStatus));
return FALSE;
}
return TRUE;
}
3.解析这些信息,得到需要的无线网参数,ssid,信号强度,加密方式等等
void GetWirelseeListSSID(const PRAW_DATA prdBSSIDList,vector<SsidInfo> &SsidList)
{
SsidInfo tempInfo;
WCHAR tSsid[MAX_PATH];
if (prdBSSIDList == NULL || prdBSSIDList->dwDataLen == 0)
{
// RETAILMSG(DBG_MSG, (TEXT("<null> entry.\n")));
return;
}
else
{
PWZC_802_11_CONFIG_LIST pConfigList = (PWZC_802_11_CONFIG_LIST)prdBSSIDList->pData;
//RETAILMSG(DBG_MSG, (TEXT("[%d] entries.\n"), pConfigList->NumberOfItems));
int i;
// 枚举所有无线AP
for (i = 0; i < pConfigList->NumberOfItems; i++)
{
PWZC_WLAN_CONFIG pConfig = &(pConfigList->Config[i]);
RAW_DATA rdBuffer;
rdBuffer.dwDataLen = pConfig->Ssid.SsidLength;
rdBuffer.pData = pConfig->Ssid.Ssid;
// 将 SSID 的 ASCII 码转化成字符串
memset(tSsid,0,sizeof(tSsid));
PrintSSID(&rdBuffer, tSsid);
tempInfo.sSsid=wstring(tSsid);
tempInfo.nRssi=(int)pConfig->Rssi;
tempInfo.InfrastructureMode=pConfig->InfrastructureMode;
tempInfo.AuthenticationMode=pConfig->AuthenticationMode;
tempInfo.ulPrivacy=pConfig->Privacy;
if (WifiCallBack)
{
WifiCallBack(tempInfo);
}
SsidList.push_back(tempInfo);
}
}
}
取得无线网的SSID名称
void PrintSSID
// some RAW_DATA is a SSID, this function is for printing SSID
(
PRAW_DATA prdSSID, // RAW SSID data
WCHAR* tSsid
)
{
if (prdSSID == NULL || prdSSID->dwDataLen == 0)
wprintf(L"<NULL>");
else
{
WCHAR szSsid[33];
MultiByteToWideChar(CP_ACP,0,(LPCSTR)prdSSID->pData,-1,tSsid,MAX_PATH*2);
}
} // PrintSSID()
4.根据上面得到的信息,加上用户输入的密码,生成的信息交给WINDOWS 的首选网络列表
BOOL WirelessConnect(PTCHAR pCard, PTCHAR pSSID,NDIS_802_11_NETWORK_INFRASTRUCTURE infr, ULONG ulPrivacy, NDIS_802_11_AUTHENTICATION_MODE ndisMode, PTCHAR pKey,int iKeyIndex, int iEapType)
//pCard: 无线网卡 GUID;pSSID: 无线AP SSID;bAdhoc: 是否点对点的 WIFI 连接;ulPrivacy: 加密模式(WEP/WPA....) ;
//ndisMode: 认证模式(Open/Share);iKeyIndex: 密钥索引(1-4);pKey: 密码;iEapType: 802.11 认证模式
{
ResetPreferredList(pCard);
BOOL bRet = FALSE;
if (!pSSID)
{
return FALSE;
}
else
{
WZC_WLAN_CONFIG wzcConfig;
ZeroMemory(&wzcConfig, sizeof(WZC_WLAN_CONFIG));
wzcConfig.Length = sizeof(WZC_WLAN_CONFIG);
wzcConfig.dwCtlFlags = 0;
wzcConfig.Ssid.SsidLength = _tcslen(pSSID);
for (UINT i = 0; i < wzcConfig.Ssid.SsidLength; i++)
{
wzcConfig.Ssid.Ssid[i] = (CHAR)pSSID[i];
}
wzcConfig.InfrastructureMode = infr;
wzcConfig.AuthenticationMode = ndisMode;
wzcConfig.Privacy = ulPrivacy;
if (pKey == NULL || _tcslen(pKey) == 0)
{
// 对密钥进行转换
bRet = InterpretEncryptionKeyValue(wzcConfig, 0, NULL, TRUE);
wzcConfig.EapolParams.dwEapType = iEapType;
wzcConfig.EapolParams.dwEapType =EAP_TYPE_TLS;
wzcConfig.EapolParams.dwEapFlags = EAPOL_ENABLED;
wzcConfig.EapolParams.bEnable8021x = TRUE;
wzcConfig.EapolParams.dwAuthDataLen = 0;
wzcConfig.EapolParams.pbAuthData = 0;
}
else
{
// RETAILMSG(DBG_MSG, (TEXT("WirelessConnect iKeyIndex = %d.\n"), iKeyIndex));
bRet = InterpretEncryptionKeyValue(wzcConfig, iKeyIndex, pKey, FALSE);
}
// 连接到指定的无线AP,并将该AP添加到首先无线AP中
AddToPreferredNetworkList(pCard, wzcConfig, pSSID);
}
return bRet;
}
5.加入WINDOWS的首选网络列表
void AddToPreferredNetworkList
// adding to the [Preferred Networks]
// [Preferred Networks] is a list of SSIDs in preference order.
// WZC continuously scans available SSIDs and attempt to connect to the most preferable SSID.
(
IN WCHAR *szWiFiCard,
IN WZC_WLAN_CONFIG& wzcConfig1,
IN WCHAR *szSsidToConnect
)
{
DWORD dwOutFlags = 0;
INTF_ENTRY_EX Intf;
memset(&Intf, 0x00, sizeof(INTF_ENTRY_EX));
Intf.wszGuid = szWiFiCard;
DWORD dwStatus = WZCQueryInterfaceEx(
NULL,
INTF_ALL,
&Intf,
&dwOutFlags);
if(dwStatus)
{
wprintf(L"WZCQueryInterfaceEx() error dwStatus=0x%0X, dwOutFlags=0x%0X", dwStatus, dwOutFlags);
WZCDeleteIntfObjEx(&Intf);
return;
}
WZC_802_11_CONFIG_LIST *pConfigList = (PWZC_802_11_CONFIG_LIST)Intf.rdStSSIDList.pData;
if(!pConfigList) // empty [Preferred Networks] list case
{
DWORD dwDataLen = sizeof(WZC_802_11_CONFIG_LIST);
WZC_802_11_CONFIG_LIST *pNewConfigList = (WZC_802_11_CONFIG_LIST *)LocalAlloc(LPTR, dwDataLen);
pNewConfigList->NumberOfItems = 1;
pNewConfigList->Index = 0;
memcpy(pNewConfigList->Config, &wzcConfig1, sizeof(wzcConfig1));
Intf.rdStSSIDList.pData = (BYTE*)pNewConfigList;
Intf.rdStSSIDList.dwDataLen = dwDataLen;
}
else
{
ULONG uiNumberOfItems = pConfigList->NumberOfItems;
for(UINT i=0; i<uiNumberOfItems; i++)
{
if(memcmp(&wzcConfig1.Ssid, &pConfigList->Config[i].Ssid, sizeof(NDIS_802_11_SSID)) == 0)
{
wprintf(L"%s is already in the [Preferred Networks] list", szSsidToConnect);
WZCDeleteIntfObjEx(&Intf);
return;
}
}
wprintf(L"SSID List has [%d] entries.\n", uiNumberOfItems);
wprintf(L"adding %s to the top of [Preferred Networks]\n", szSsidToConnect); // this will be the most preferable SSID
DWORD dwDataLen = sizeof(WZC_802_11_CONFIG_LIST) + (uiNumberOfItems+1)*sizeof(WZC_WLAN_CONFIG);
WZC_802_11_CONFIG_LIST *pNewConfigList = (WZC_802_11_CONFIG_LIST *)LocalAlloc(LPTR, dwDataLen);
pNewConfigList->NumberOfItems = uiNumberOfItems + 1;
pNewConfigList->Index = 0;
memcpy(pNewConfigList->Config, &wzcConfig1, sizeof(wzcConfig1));
if(pConfigList->NumberOfItems)
{
pNewConfigList->Index = pConfigList->Index;
memcpy(pNewConfigList->Config+1, pConfigList->Config, (uiNumberOfItems)*sizeof(WZC_WLAN_CONFIG));
LocalFree(pConfigList);
pConfigList = NULL;
}
Intf.rdStSSIDList.pData = (BYTE*)pNewConfigList;
Intf.rdStSSIDList.dwDataLen = dwDataLen;
}
dwStatus = WZCSetInterfaceEx(NULL, INTF_PREFLIST, &Intf, &dwOutFlags);
if(dwStatus)
wprintf(L"WZCSetInterfaceEx() error dwStatus=0x%0X, dwOutFlags=0x%0X", dwStatus, dwOutFlags);
WZCDeleteIntfObjEx(&Intf);
} // AddToPreferredNetworkList()
6.重置WINDOWS的首选网络列表
void ResetPreferredList
// reset the [Preferred Networks], so wireless will be disconnected
// wzctool -reset cisco1
// reset CISCO1 adapter.
// wzctool -reset
// reset the first wireless adapter found in the system
(
PTCHAR pCard
)
{
WCHAR *szWiFiCard = NULL;
szWiFiCard = pCard;
DWORD dwInFlags = 0;
INTF_ENTRY_EX Intf;
memset(&Intf, 0x00, sizeof(INTF_ENTRY_EX));
Intf.wszGuid = szWiFiCard;
DWORD dwStatus = WZCSetInterfaceEx(NULL, INTF_PREFLIST, &Intf, &dwInFlags);
if(dwStatus)
wprintf(L"WZCSetInterfaceEx() error dwStatus=0x%0X, dwOutFlags=0x%0X", dwStatus, dwInFlags);
else
wprintf(L"now, WZC resets [Preferred Networks]\n");
} // ResetPreferredList()
7.判断网卡是否连接到了无线网络
BOOL IsWifiConnected(PTCHAR pCard,DWORD * pAdd)
{
BOOL bHasDefaultRoute = FALSE;
ULONG wifiindex =0;
if(NO_ERROR == GetAdapterIndex(pCard,&wifiindex))
{
DWORD dwTableSize = 0;
GetIpAddrTable(NULL, &dwTableSize, FALSE);
if (dwTableSize)
{
MIB_IPADDRTABLE* pft;
pft = (MIB_IPADDRTABLE*)malloc(dwTableSize);
if (pft)
{
if (GetIpAddrTable(pft, &dwTableSize, TRUE) == NO_ERROR)
{
for (ulong nIndex = 0; nIndex < pft->dwNumEntries; nIndex++)
{
if (pft->table[nIndex].dwIndex == wifiindex)
{
printf("get wifi index\n");
printf("wifi add=%x\n",pft->table[nIndex].dwAddr);
if (0!=pft->table[nIndex].dwAddr)
{
bHasDefaultRoute = TRUE;
if (pAdd)
{
*pAdd = pft->table[nIndex].dwAddr;
}
}
break;
}
}
}
free(pft);
}
}
}
return bHasDefaultRoute;
}
8.密码加密算法
static void EncryptWepKMaterial(IN OUT WZC_WLAN_CONFIG* pwzcConfig)
{
BYTE chFakeKeyMaterial[] = { 0x56, 0x09, 0x08, 0x98, 0x4D, 0x08, 0x11, 0x66, 0x42, 0x03, 0x01, 0x67, 0x66 };
for (int i = 0; i < WZCCTL_MAX_WEPK_MATERIAL; i++)
pwzcConfig->KeyMaterial[i] ^= chFakeKeyMaterial[(7*i)%13];
}
BOOL InterpretEncryptionKeyValue(IN OUT WZC_WLAN_CONFIG& wzcConfig, IN int iKeyIndex, IN PTCHAR pKey, IN BOOL bNeed8021X)
{
if(wzcConfig.Privacy == Ndis802_11WEPEnabled)
{
if(!bNeed8021X && pKey)
{
wzcConfig.KeyIndex = iKeyIndex;
wzcConfig.KeyLength = _tcslen(pKey);
if((wzcConfig.KeyLength == 5) || (wzcConfig.KeyLength == 13))
{
for(UINT i=0; i<wzcConfig.KeyLength; i++)
wzcConfig.KeyMaterial[i] = (UCHAR)pKey[i];
}
else
{
if((pKey[0] != TEXT('0')) || (pKey[1] != TEXT('x')))
{
// RETAILMSG(DBG_MSG, (TEXT("Invalid key value.\n")));
return FALSE;
}
pKey += 2;
wzcConfig.KeyLength = wcslen(pKey);
if((wzcConfig.KeyLength != 10) && (wzcConfig.KeyLength != 26))
{
// RETAILMSG(DBG_MSG, (TEXT("Invalid key value.\n")));
return FALSE;
}
wzcConfig.KeyLength >>= 1;
for(UINT i=0; i<wzcConfig.KeyLength; i++)
{
wzcConfig.KeyMaterial[i] = (HEX(pKey[2 * i]) << 4) | HEX(pKey[2 * i + 1]);
}
}
EncryptWepKMaterial(&wzcConfig);
wzcConfig.dwCtlFlags |= WZCCTL_WEPK_PRESENT;
}
}
else if(wzcConfig.Privacy == Ndis802_11Encryption2Enabled
|| wzcConfig.Privacy == Ndis802_11Encryption3Enabled)
{
if(!bNeed8021X)
{
wzcConfig.KeyLength = wcslen(pKey);
if((wzcConfig.KeyLength < 8) || (wzcConfig.KeyLength > 63))
{
// RETAILMSG(DBG_MSG, (TEXT("WPA-PSK/TKIP key should be 8-63 char long string.\n")));
return FALSE;
}
char szEncryptionKeyValue8[64]; // longest key is 63
memset(szEncryptionKeyValue8, 0, sizeof(szEncryptionKeyValue8));
WideCharToMultiByte(CP_ACP,
0,
pKey,
wzcConfig.KeyLength + 1,
szEncryptionKeyValue8,
wzcConfig.KeyLength + 1,
NULL,
NULL);
WZCPassword2Key(&wzcConfig, szEncryptionKeyValue8);
EncryptWepKMaterial(&wzcConfig);
wzcConfig.dwCtlFlags |= WZCCTL_WEPK_XFORMAT
| WZCCTL_WEPK_PRESENT
| WZCCTL_ONEX_ENABLED;
}
wzcConfig.EapolParams.dwEapFlags = EAPOL_ENABLED;
wzcConfig.EapolParams.dwEapType = DEFAULT_EAP_TYPE;
wzcConfig.EapolParams.bEnable8021x = TRUE;
wzcConfig.WPAMCastCipher = Ndis802_11Encryption2Enabled;
}
return TRUE;
}
分享到:
相关推荐
WinCE5下WIFI无线网卡 配置、连接程序
wince系统下调用wifi连接,在wince5和wince6下均测试过,wince6下通过SID连接有点小问题,通过mac连接可以通过。
wince下wifi无线连接源码以及整套需要的库,WINCE平台需要的库文件等等。
在Wince下如何实现Wifi无线功能。。。
包含了在wince6.0下对wifi的启用和禁用,无线网络列表,连接无线网络等功能。
Wince BSP 下的Wifi 驱动 基于PXA270 CPU
wince 下通过vs2005 和WIFI 实现rfid功能
用于 Windows CE 平台的无线网卡配置及WIFI连接程序。
wince5.0 wifi连接示例 包含用到的类库
WINCE\WinCE下USB无线网卡驱动程序,主要是用于WINCE5.0和WINCE6.0.zip
Motorola Symbol MC3190(WinCE6) 无线网络设置,不错的参考,非常有用
WINCE无线网络连接、断开、查询程序源码,window mobile phone6.0编译环境,基于WINCE wzctool程序
wince系统工业平板电脑结合GPRS无线串口模块轻松实现无线上网功能
Wince 自定义WiFi设置
wince中系统自带的WZC函数,可实现wifi操作,另配有获取wince各个网卡的ip信息函数
WINCE WIFI无线网络信号测试,能测出所有能搜索到的无线网络信号和IP读取或更改。解压后直接打开,不用安装
检测wince的wifi是否连接,方法比较简单。找了好久才找到的。放上来给兄弟们共享下,写的比较差见笑了。
Wifi测试程序,主要用于wifi的收发测试和传输速度的性能的
实现了WINCE车机的WIFI连接问题,链接WIFI联网版凯立德导航可实现实时路况功能!