wince下实现wifi无线网络的连接和配置(WLAN)
在 Windows CE 下自带有无线网卡的配置和连接程序,但是如果系统剪裁掉了资源管理器和任务栏,或者再CE的很多应用中,是不允许用户回到桌面去调用系统的连接程序的,这篇文章就来谈一下如何用那么可以利用微软自带的WZC函数来重新编写一个独立于系统的WIFI连接程序。
存放SSID的基本信息的数据结构:
2.从无线网卡取得无线网络信息
3.解析这些信息,得到需要的无线网参数,ssid,信号强度,加密方式等等
取得无线网的SSID名称
4.根据上面得到的信息,加上用户输入的密码,生成的信息交给WINDOWS 的首选网络列表
5.加入WINDOWS的首选网络列表
6.重置WINDOWS的首选网络列表
7.判断网卡是否连接到了无线网络
8.密码加密算法
连接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);
- }
- }
- }
- 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;
- }