WinCE 5.0 WIFI 无线网卡的配置和建立连接
在 Windows CE 下自带有无线网卡的配置和连接程序,可是我的系统剪裁掉了资源管理器和任务栏,导致自带的无线网卡配置程序不能再使用了,只好自力更生。
我的环境是 S3C2440 + WinCE 5.0 + VNUWCL5(威盛无线网卡)及驱动程序。使用 Automatic Configuration Functions API
一、枚举系统中可用的无线网络设备
下面的函数可以枚举出系统中所有可用的无线网卡设备的GUID,为了简化,我选择第一块可用的无线网卡来操作
- BOOL
GetFirstWirelessCard(
PTCHAR
pCard) - {
-
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(DBG_MSG, (TEXT(
"WZCEnumInterfaces() error 0x%08X/n"
),dwStatus)); -
return
FALSE; - }
-
// 判断无线网卡的数量,可以根据无线网卡数量来枚举出所有可用的无线网卡 -
if
(!IntfsTable.dwNumIntfs) - {
- RETAILMSG(DBG_MSG, (TEXT(
"System has no wireless card./n"
))); -
return
FALSE; - }
- _tcscpy(pCard, IntfsTable.pIntfs[0].wszGuid);
- LocalFree(IntfsTable.pIntfs);
-
return
TRUE; - }
二、获取无线网络信息
获取到了系统可用的无线网卡后,我们就可以利用它的 GUID 号来进行进一步的操作了,首先要做的事情就是得到该无线网卡的信息以及该无线网卡扫描到的 WIFI 网关信息。
以下函数可以获取到该无线网卡及扫描的到的无线 AP 信息
- //////////////////////////////////////////////////////////////////////////
- // pCard: 无线网卡 GUID
- // pIntf: 无线网卡配置信息结果体
- // pOutFlags: 网卡配置信息掩码标志
- //////////////////////////////////////////////////////////////////////////
- BOOL
GetWirelessCardInfo(
PTCHAR
pCard, PINTF_ENTRY_EX pIntf, PDWORD pOutFlags) - {
-
TCHAR
*szWiFiCard = NULL; -
// 参数校验 -
if
(!pCard || !pIntf || !pOutFlags) - {
- RETAILMSG(DBG_MSG, (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(DBG_MSG, (TEXT(
"WZCQueryInterfaceEx() error 0x%08X/n"
), dwStatus)); -
return
FALSE; - }
-
return
TRUE; - }
三、判断连接状态
我们可以通过无线网卡的状态来判断当前无线网卡是否已经和无线AP建立了连接
- BOOL
IsAssociated(
const
INTF_ENTRY_EX Intf,
const
DWORD
dwOutFlags) - {
-
if
(dwOutFlags & INTF_BSSID) - {
- PRAW_DATA prdMAC = (PRAW_DATA)(&Intf.rdBSSID);
-
// 判断 BSSID 的 MAC 地址是否有效来判断是否和无线AP建立了连接 -
if
(prdMAC == NULL || prdMAC->dwDataLen == 0 || - (!prdMAC->pData[0] && !prdMAC->pData[1] && !prdMAC->pData[2] &
- !prdMAC->pData[3] && !prdMAC->pData[4] && !prdMAC->pData[5]))
- {
- RETAILMSG(DBG_MSG, (TEXT(
"(This wifi card is not associated to any)/n"
))); -
return
FALSE; - }
-
else - {
- RETAILMSG(DBG_MSG, (TEXT(
"(This wifi card is associated state)/n"
))); -
return
TRUE; - }
- }
-
else - {
-
return
FALSE; - }
- }
四、获取无线AP信息
获取了无线网卡的信息后,可以通过无线网卡枚举出当前所有可用的无线AP的SSID名称以及加密模式等等所有可用信息,一下函数可以实现该功能
- void
GetWirelseeListSSID(
const
PRAW_DATA prdBSSIDList,
HWND
hListCtlWnd) - {
-
if
(prdBSSIDList == NULL || prdBSSIDList->dwDataLen == 0) - {
- RETAILMSG(DBG_MSG, (TEXT(
"<null> entry./n"
))); - }
-
else - {
- PWZC_802_11_CONFIG_LIST pConfigList = (PWZC_802_11_CONFIG_LIST)prdBSSIDList->pData;
-
//RETAILMSG(DBG_MSG, (TEXT("[%d] entries./n"), pConfigList->NumberOfItems)); - uint 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;
-
TCHAR
tSsid[MAX_PATH]; -
// 将 SSID 的 ASCII 码转化成字符串 - PrintSSID(&rdBuffer, tSsid);
-
if
(hListCtlWnd) - {
-
if
(ListBox_FindString(hListCtlWnd, 0, tSsid) == LB_ERR) - {
- ListBox_AddString(hListCtlWnd, tSsid);
- }
- }
-
//RETAILMSG(DBG_MSG, (TEXT("/n"))); - }
- }
- }
五、连接到指定的无线AP
- //////////////////////////////////////////////////////////////////////////
- // pCard: 无线网卡 GUID
- // pSSID: 无线AP SSID号
- // bAdhoc: 是否点对点的 WIFI 连接
- // ulPrivacy: 加密模式(WEP/WPA....)
- // ndisMode: 认证模式(Open/Share)
- // iKeyIndex: 密钥索引(1-4)
- // pKey: 密码
- // iEapType: 802.11 认证模式
- //////////////////////////////////////////////////////////////////////////
- BOOL
WirelessConnect(
PTCHAR
pCard,
PTCHAR
pSSID,
BOOL
bAdhoc,
ULONG
ulPrivacy, NDIS_802_11_AUTHENTICATION_MODE ndisMode,
int
iKeyIndex,
PTCHAR
pKey,
int
iEapType) - {
-
BOOL
bRet = FALSE; -
if
(!pSSID) - {
- RETAILMSG(DBG_MSG, (TEXT(
"Param Error./n"
))); -
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]; - }
-
if
(bAdhoc) - {
- wzcConfig.InfrastructureMode = Ndis802_11IBSS;
- }
-
else - {
- wzcConfig.InfrastructureMode = Ndis802_11Infrastructure;
- }
- wzcConfig.AuthenticationMode = ndisMode;
- wzcConfig.Privacy = ulPrivacy;
-
if
(pKey == NULL || _tcslen(pKey) == 0) - {
-
// 对密钥进行转换 - bRet = InterpretEncryptionKeyValue(wzcConfig, 0, NULL, TRUE);
- wzcConfig.EapolParams.dwEapType = iEapType;
- 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; - }
六、密钥转换
输入的密钥需要通过加密方式进行一定的转化,以下函数可以完成改功能
- 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; - }
通过以上操作,完全可以连接到可用的无线AP了,再加上些适当的UI程序,完全可以用来替代 Windows CE 自带的无线配置程序了,我再连接中放置了一个简单的而完整的测试程序,相信大家看了以后都知道怎么操作无线网卡了。
http://download.csdn.net/source/927575