使用WZC函数在WINDOWS CE下搜索连接WIFI的具体实现与源码

来源:互联网 发布:bt是什么软件 编辑:程序博客网 时间:2024/05/29 23:44
    在 Windows CE 下自带有无线网卡的配置和连接程序,但是如果系统剪裁掉了资源管理器和任务栏,或者再CE的很多应用中,是不允许用户回到桌面去调用系统的连接程序的,这篇文章就来谈一下如何用那么可以利用微软自带的WZC函数来重新编写一个独立于系统的WIFI连接程序。   

    连接WIFI网络有这么几个步骤,第一步,要获取你自己的网卡,调用GetFirstWirelessNetworkCard()来实现。第二步,要获得当前环境中的无线网信息,调用GetWirelessCardInfo来取得这些信息,调用GetWirelseeListSSID来解析这些信息,接下来把取得的无线网SSID和自己输入的密码用AddToPreferredNetworkList()传到WINDOWS的首选无线网列表中,windows就会自动连接这个无线网络。

    下面是一整套通过WZC函数连接无线网的程序,我自己测试后保证可以运行,如有需要全部源码或者动态库文件的,请留言或者留下邮箱

    调用WZC函数需要包含的文件和库如下

view plaincopy to clipboardprint?
  1. #include <eaputil.h>     
  2. #include <pm.h>     
  3. #include <wzcsapi.h>     
  4. #include <iphlpapi.h>     
  5. #pragma comment(lib,"Iphlpapi.lib")    
  6. #pragma comment(lib,"Wzcsapi.lib")     
  7. #pragma comment(lib,"cclib.lib")    

存放SSID的基本信息的数据结构

view plaincopy to clipboardprint?
  1. /*SSID基本信息*/    
  2. typedef struct tag_SsidInfo    
  3. {    
  4.     wstring sSsid;    
  5.     int nRssi;    
  6.     NDIS_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode;    
  7.     ULONG ulPrivacy;    
  8.     NDIS_802_11_AUTHENTICATION_MODE AuthenticationMode;    
  9.     int iKeyIndex;     
  10.     wstring pKey;    
  11.     int iEapType;    
  12. }SsidInfo;   

接下来看关键函数的具体实现:

1.取得无线网卡

view plaincopy to clipboardprint?
  1. BOOL Wifioption::GetFirstWirelessCard(PTCHAR pCard)   
  2. {   
  3.     WifiCallBack=NULL;  
  4.     if (!pCard)   
  5.     {   
  6.         return FALSE;   
  7.     }   
  8.     INTFS_KEY_TABLE IntfsTable;   
  9.     IntfsTable.dwNumIntfs = 0;   
  10.     IntfsTable.pIntfs = NULL;   
  11.     _tcscpy(pCard, TEXT(""));   
  12.     // 枚举系统中可用的无线网卡    
  13.     DWORD dwStatus = WZCEnumInterfaces(NULL, &IntfsTable);   
  14.     if (dwStatus != ERROR_SUCCESS)   
  15.     {   
  16.         RETAILMSG(1, (TEXT("WZCEnumInterfaces() error 0x%08X\n"),dwStatus));   
  17.         return FALSE;   
  18.     }   
  19.     // 判断无线网卡的数量,可以根据无线网卡数量来枚举出所有可用的无线网卡   
  20.     if (!IntfsTable.dwNumIntfs)   
  21.     {   
  22.         RETAILMSG(1, (TEXT("System has no wireless card.\n")));   
  23.         return FALSE;   
  24.     }   
  25.     _tcscpy(pCard, IntfsTable.pIntfs[0].wszGuid);   
  26.     LocalFree(IntfsTable.pIntfs);   
  27.     return TRUE;   
  28. }   

2.从无线网卡取得无线网络信息

view plaincopy to clipboardprint?
  1. //////////////////////////////////////////////////////////////////////////   
  2. // pCard: 无线网卡 GUID    
  3. // pIntf: 无线网卡配置信息结果体    
  4. // pOutFlags: 网卡配置信息掩码标志    
  5. //////////////////////////////////////////////////////////////////////////   
  6. BOOL Wifioption::GetWirelessCardInfo(PTCHAR pCard, PINTF_ENTRY_EX pIntf, PDWORD pOutFlags)   
  7. {   
  8.     TCHAR *szWiFiCard = NULL;   
  9.     // 参数校验    
  10.     if (!pCard || !pIntf || !pOutFlags)   
  11.     {   
  12.         //RETAILMSG(1, (TEXT("Param Error.\n")));   
  13.         return FALSE;   
  14.     }  
  15.     szWiFiCard = pCard;   
  16.     *pOutFlags = 0;   
  17.     // 初始化无线网卡信息    
  18.     ZeroMemory(pIntf, sizeof(INTF_ENTRY_EX));   
  19.     // 设置 GUID 号    
  20.     pIntf->wszGuid = szWiFiCard;   
  21.     // 查询无线网卡信息    
  22.     DWORD dwStatus = WZCQueryInterfaceEx(NULL, INTF_ALL, pIntf, pOutFlags);   
  23.     if (dwStatus != ERROR_SUCCESS)   
  24.     {   
  25.         //RETAILMSG(1, (TEXT("WZCQueryInterfaceEx() error 0x%08X\n"), dwStatus));   
  26.         return FALSE;   
  27.     }   
  28.     return TRUE;   
  29. }   

3.解析这些信息,得到需要的无线网参数,ssid,信号强度,加密方式等等

view plaincopy to clipboardprint?
  1. void Wifioption::GetWirelseeListSSID(const PRAW_DATA prdBSSIDList,vector<SsidInfo> &SsidList)  
  2. {  
  3.     SsidInfo tempInfo;  
  4.     WCHAR tSsid[MAX_PATH];  
  5.     if (prdBSSIDList == NULL || prdBSSIDList->dwDataLen  == 0)  
  6.     {  
  7.         //         RETAILMSG(DBG_MSG, (TEXT("<null> entry.\n")));  
  8.         return;  
  9.     }  
  10.     else  
  11.     {  
  12.         PWZC_802_11_CONFIG_LIST pConfigList = (PWZC_802_11_CONFIG_LIST)prdBSSIDList->pData;  
  13.         //RETAILMSG(DBG_MSG, (TEXT("[%d] entries.\n"), pConfigList->NumberOfItems));  
  14.         int i;  
  15.         // 枚举所有无线AP   
  16.         for (i = 0; i < pConfigList->NumberOfItems; i++)  
  17.         {  
  18.             PWZC_WLAN_CONFIG pConfig = &(pConfigList->Config[i]);  
  19.             RAW_DATA rdBuffer;  
  20.             rdBuffer.dwDataLen = pConfig->Ssid.SsidLength;  
  21.             rdBuffer.pData = pConfig->Ssid.Ssid;  
  22.             // 将 SSID 的 ASCII 码转化成字符串   
  23.             memset(tSsid,0,sizeof(tSsid));  
  24.             PrintSSID(&rdBuffer, tSsid);  
  25.             tempInfo.sSsid=wstring(tSsid);  
  26.             tempInfo.nRssi=(int)pConfig->Rssi;  
  27.             tempInfo.InfrastructureMode=pConfig->InfrastructureMode;  
  28.             tempInfo.AuthenticationMode=pConfig->AuthenticationMode;  
  29.             tempInfo.ulPrivacy=pConfig->Privacy;  
  30.             if (WifiCallBack)  
  31.             {  
  32.                 WifiCallBack(tempInfo);  
  33.             }  
  34.             SsidList.push_back(tempInfo);  
  35.         }  
  36.     }  
  37. }  
view plaincopy to clipboardprint?
  1. void   
  2. Wifioption::PrintSSID  
  3. // some RAW_DATA is a SSID, this function is for printing SSID  
  4. (  
  5.  PRAW_DATA prdSSID,   // RAW SSID data  
  6.  WCHAR* tSsid    
  7.  )  
  8. {  
  9.     if (prdSSID == NULL || prdSSID->dwDataLen == 0)  
  10.         wprintf(L"<NULL>");  
  11.     else  
  12.     {  
  13.         WCHAR szSsid[33];  
  14.         MultiByteToWideChar(CP_ACP,0,(LPCSTR)prdSSID->pData,-1,tSsid,MAX_PATH*2);  
  15.     }  
  16.   
  17. }   //  PrintSSID()  

4.根据上面得到的信息,加上用户输入的密码,生成的信息交给WINDOWS 的首选网络列表

view plaincopy to clipboardprint?
  1. BOOL Wifioption::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)    
  2. //pCard: 无线网卡 GUID;pSSID: 无线AP SSID;bAdhoc: 是否点对点的 WIFI 连接;ulPrivacy: 加密模式(WEP/WPA....) ;    
  3. //ndisMode: 认证模式(Open/Share);iKeyIndex: 密钥索引(1-4);pKey: 密码;iEapType: 802.11 认证模式    
  4. {  
  5.     ResetPreferredList(pCard);  
  6.     BOOL bRet = FALSE;     
  7.     if (!pSSID)    
  8.     {    
  9.         return FALSE;    
  10.     }    
  11.     else    
  12.     {    
  13.         WZC_WLAN_CONFIG wzcConfig;    
  14.         ZeroMemory(&wzcConfig, sizeof(WZC_WLAN_CONFIG));     
  15.         wzcConfig.Length = sizeof(WZC_WLAN_CONFIG);    
  16.         wzcConfig.dwCtlFlags = 0;    
  17.         wzcConfig.Ssid.SsidLength = _tcslen(pSSID);    
  18.         for (UINT i = 0; i < wzcConfig.Ssid.SsidLength; i++)    
  19.         {    
  20.             wzcConfig.Ssid.Ssid[i] = (CHAR)pSSID[i];    
  21.         }    
  22.         wzcConfig.InfrastructureMode = infr;  
  23.         wzcConfig.AuthenticationMode = ndisMode;    
  24.         wzcConfig.Privacy = ulPrivacy;    
  25.   
  26.         if (pKey == NULL || _tcslen(pKey) == 0)    
  27.         {    
  28.             // 对密钥进行转换     
  29.             bRet = InterpretEncryptionKeyValue(wzcConfig, 0, NULL, TRUE);    
  30.             wzcConfig.EapolParams.dwEapType = iEapType;  
  31.             wzcConfig.EapolParams.dwEapType =EAP_TYPE_TLS;  
  32.             wzcConfig.EapolParams.dwEapFlags = EAPOL_ENABLED;    
  33.             wzcConfig.EapolParams.bEnable8021x  = TRUE;    
  34.             wzcConfig.EapolParams.dwAuthDataLen = 0;    
  35.             wzcConfig.EapolParams.pbAuthData = 0;    
  36.         }    
  37.         else    
  38.         {    
  39. //            RETAILMSG(DBG_MSG, (TEXT("WirelessConnect iKeyIndex = %d.\n"), iKeyIndex));                 
  40.             bRet = InterpretEncryptionKeyValue(wzcConfig, iKeyIndex, pKey, FALSE);    
  41.         }    
  42.         // 连接到指定的无线AP,并将该AP添加到首先无线AP中     
  43.         AddToPreferredNetworkList(pCard, wzcConfig, pSSID);         
  44.     }    
  45.     return bRet;    
  46. }     
取得无线网的SSID名称
view plaincopy to clipboardprint?
  1. void   
  2. Wifioption::PrintSSID  
  3. // some RAW_DATA is a SSID, this function is for printing SSID  
  4. (  
  5.  PRAW_DATA prdSSID,   // RAW SSID data  
  6.  WCHAR* tSsid    
  7.  )  
  8. {  
  9.     if (prdSSID == NULL || prdSSID->dwDataLen == 0)  
  10.         wprintf(L"<NULL>");  
  11.     else  
  12.     {  
  13.         WCHAR szSsid[33];  
  14.         MultiByteToWideChar(CP_ACP,0,(LPCSTR)prdSSID->pData,-1,tSsid,MAX_PATH*2);  
  15.     }  
  16.   
  17. }   //  PrintSSID()  

5.加入WINDOWS的首选网络列表

view plaincopy to clipboardprint?
  1. void Wifioption::AddToPreferredNetworkList  
  2. // adding to the [Preferred Networks]   
  3. // [Preferred Networks] is a list of SSIDs in preference order.  
  4. // WZC continuously scans available SSIDs and attempt to connect to the most preferable SSID.  
  5. (  
  6.  IN WCHAR *szWiFiCard,  
  7.  IN WZC_WLAN_CONFIG& wzcConfig1,  
  8.  IN WCHAR *szSsidToConnect  
  9.  )  
  10. {  
  11.     DWORD dwOutFlags = 0;  
  12.     INTF_ENTRY_EX Intf;  
  13.     memset(&Intf, 0x00, sizeof(INTF_ENTRY_EX));  
  14.     Intf.wszGuid = szWiFiCard;  
  15.   
  16.     DWORD dwStatus = WZCQueryInterfaceEx(  
  17.         NULL,   
  18.         INTF_ALL,  
  19.         &Intf,   
  20.         &dwOutFlags);  
  21.     if(dwStatus)  
  22.     {  
  23.         wprintf(L"WZCQueryInterfaceEx() error dwStatus=0x%0X, dwOutFlags=0x%0X", dwStatus, dwOutFlags);  
  24.         WZCDeleteIntfObjEx(&Intf);  
  25.         return;  
  26.     }  
  27.   
  28.     WZC_802_11_CONFIG_LIST *pConfigList = (PWZC_802_11_CONFIG_LIST)Intf.rdStSSIDList.pData;  
  29.     if(!pConfigList)   // empty [Preferred Networks] list case  
  30.     {  
  31.         DWORD dwDataLen = sizeof(WZC_802_11_CONFIG_LIST);  
  32.         WZC_802_11_CONFIG_LIST *pNewConfigList = (WZC_802_11_CONFIG_LIST *)LocalAlloc(LPTR, dwDataLen);  
  33.         pNewConfigList->NumberOfItems = 1;  
  34.         pNewConfigList->Index = 0;  
  35.         memcpy(pNewConfigList->Config, &wzcConfig1, sizeof(wzcConfig1));  
  36.         Intf.rdStSSIDList.pData = (BYTE*)pNewConfigList;  
  37.         Intf.rdStSSIDList.dwDataLen = dwDataLen;  
  38.     }  
  39.     else  
  40.     {  
  41.         ULONG uiNumberOfItems = pConfigList->NumberOfItems;  
  42.         for(UINT i=0; i<uiNumberOfItems; i++)  
  43.         {  
  44.             if(memcmp(&wzcConfig1.Ssid, &pConfigList->Config[i].Ssid, sizeof(NDIS_802_11_SSID)) == 0)  
  45.             {  
  46.                 wprintf(L"%s is already in the [Preferred Networks] list", szSsidToConnect);  
  47.                 WZCDeleteIntfObjEx(&Intf);  
  48.                 return;  
  49.             }  
  50.         }  
  51.         wprintf(L"SSID List has [%d] entries.\n", uiNumberOfItems);  
  52.         wprintf(L"adding %s to the top of [Preferred Networks]\n", szSsidToConnect); // this will be the most preferable SSID  
  53.   
  54.         DWORD dwDataLen = sizeof(WZC_802_11_CONFIG_LIST) + (uiNumberOfItems+1)*sizeof(WZC_WLAN_CONFIG);  
  55.         WZC_802_11_CONFIG_LIST *pNewConfigList = (WZC_802_11_CONFIG_LIST *)LocalAlloc(LPTR, dwDataLen);  
  56.         pNewConfigList->NumberOfItems = uiNumberOfItems + 1;  
  57.         pNewConfigList->Index = 0;  
  58.   
  59.         memcpy(pNewConfigList->Config, &wzcConfig1, sizeof(wzcConfig1));  
  60.         if(pConfigList->NumberOfItems)  
  61.         {  
  62.             pNewConfigList->Index = pConfigList->Index;  
  63.             memcpy(pNewConfigList->Config+1, pConfigList->Config, (uiNumberOfItems)*sizeof(WZC_WLAN_CONFIG));  
  64.             LocalFree(pConfigList);  
  65.             pConfigList = NULL;  
  66.         }  
  67.   
  68.         Intf.rdStSSIDList.pData = (BYTE*)pNewConfigList;  
  69.         Intf.rdStSSIDList.dwDataLen = dwDataLen;  
  70.     }  
  71.   
  72.     dwStatus = WZCSetInterfaceEx(NULL, INTF_PREFLIST, &Intf, &dwOutFlags);  
  73.     if(dwStatus)  
  74.         wprintf(L"WZCSetInterfaceEx() error dwStatus=0x%0X, dwOutFlags=0x%0X", dwStatus, dwOutFlags);  
  75.   
  76.     WZCDeleteIntfObjEx(&Intf);  
  77. }   // AddToPreferredNetworkList()  
6.重置WINDOWS的首选网络列表

view plaincopy to clipboardprint?
  1. void  
  2. Wifioption::ResetPreferredList  
  3. // reset the [Preferred Networks], so wireless will be disconnected  
  4. // wzctool -reset cisco1   
  5. //      reset CISCO1 adapter.   
  6. // wzctool -reset   
  7. //      reset the first wireless adapter found in the system  
  8. (  
  9. PTCHAR pCard  
  10. )  
  11. {  
  12.     WCHAR *szWiFiCard = NULL;  
  13.         szWiFiCard = pCard;  
  14.     DWORD dwInFlags = 0;  
  15.     INTF_ENTRY_EX Intf;  
  16.     memset(&Intf, 0x00, sizeof(INTF_ENTRY_EX));  
  17.     Intf.wszGuid = szWiFiCard;  
  18.     DWORD dwStatus = WZCSetInterfaceEx(NULL, INTF_PREFLIST, &Intf, &dwInFlags);  
  19.     if(dwStatus)  
  20.         wprintf(L"WZCSetInterfaceEx() error dwStatus=0x%0X, dwOutFlags=0x%0X", dwStatus, dwInFlags);  
  21.     else  
  22.         wprintf(L"now, WZC resets [Preferred Networks]\n");  
  23. }   // ResetPreferredList()  
7.判断网卡是否连接到了无线网络
view plaincopy to clipboardprint?
  1. BOOL Wifioption::IsWifiConnected(PTCHAR pCard,DWORD * pAdd)  
  2. {  
  3.     BOOL bHasDefaultRoute = FALSE;  
  4.     ULONG wifiindex =0;  
  5.     if(NO_ERROR == GetAdapterIndex(pCard,&wifiindex))  
  6.     {  
  7.         DWORD dwTableSize = 0;  
  8.         GetIpAddrTable(NULL, &dwTableSize, FALSE);  
  9.         if (dwTableSize)  
  10.         {  
  11.             MIB_IPADDRTABLE* pft;  
  12.             pft = (MIB_IPADDRTABLE*)malloc(dwTableSize);  
  13.             if (pft)  
  14.             {  
  15.                 if (GetIpAddrTable(pft, &dwTableSize, TRUE) == NO_ERROR)  
  16.                 {  
  17.                     for (ulong nIndex = 0; nIndex < pft->dwNumEntries; nIndex++)  
  18.                     {  
  19.                         if (pft->table[nIndex].dwIndex == wifiindex)  
  20.                         {  
  21.                             printf("get wifi index\n");  
  22.                             printf("wifi add=%x\n",pft->table[nIndex].dwAddr);  
  23.                             if (0!=pft->table[nIndex].dwAddr)  
  24.                             {  
  25.                                 bHasDefaultRoute = TRUE;  
  26.                                 if (pAdd)  
  27.                                 {  
  28.                                     *pAdd = pft->table[nIndex].dwAddr;  
  29.                                 }  
  30.                             }  
  31.                             break;  
  32.                         }  
  33.                     }  
  34.                 }  
  35.                 free(pft);  
  36.             }  
  37.         }  
  38.     }  
  39.     return bHasDefaultRoute;  
  40. }  

8.密码加密算法

view plaincopy to clipboardprint?
  1. static void EncryptWepKMaterial(IN OUT WZC_WLAN_CONFIG* pwzcConfig)     
  2. {     
  3.     BYTE chFakeKeyMaterial[] = { 0x56, 0x09, 0x08, 0x98, 0x4D, 0x08, 0x11, 0x66, 0x42, 0x03, 0x01, 0x67, 0x66 };     
  4.     for (int i = 0; i < WZCCTL_MAX_WEPK_MATERIAL; i++)     
  5.         pwzcConfig->KeyMaterial[i] ^= chFakeKeyMaterial[(7*i)%13];     
  6. }     

view plaincopy to clipboardprint?
  1. BOOL Wifioption::InterpretEncryptionKeyValue(IN OUT WZC_WLAN_CONFIG& wzcConfig, IN int iKeyIndex, IN PTCHAR pKey, IN BOOL bNeed8021X)     
  2. {      
  3.     if(wzcConfig.Privacy == Ndis802_11WEPEnabled)     
  4.     {      
  5.         if(!bNeed8021X && pKey)      
  6.         {      
  7.             wzcConfig.KeyIndex = iKeyIndex;     
  8.             wzcConfig.KeyLength = _tcslen(pKey);     
  9.   
  10.             if((wzcConfig.KeyLength == 5) || (wzcConfig.KeyLength == 13))     
  11.             {     
  12.                 for(UINT i=0; i<wzcConfig.KeyLength; i++)     
  13.                     wzcConfig.KeyMaterial[i] = (UCHAR)pKey[i];     
  14.             }     
  15.             else     
  16.             {     
  17.                 if((pKey[0] != TEXT('0')) || (pKey[1] != TEXT('x')))     
  18.                 {      
  19. //                    RETAILMSG(DBG_MSG, (TEXT("Invalid key value.\n")));      
  20.                     return FALSE;     
  21.                 }     
  22.                 pKey += 2;     
  23.                 wzcConfig.KeyLength = wcslen(pKey);     
  24.                 if((wzcConfig.KeyLength != 10) && (wzcConfig.KeyLength != 26))     
  25.                 {     
  26. //                    RETAILMSG(DBG_MSG, (TEXT("Invalid key value.\n")));      
  27.                     return FALSE;     
  28.                 }     
  29.                 wzcConfig.KeyLength >>= 1;     
  30.                 for(UINT i=0; i<wzcConfig.KeyLength; i++)     
  31.                 {     
  32.                     wzcConfig.KeyMaterial[i] = (HEX(pKey[2 * i]) << 4) | HEX(pKey[2 * i + 1]);     
  33.                 }      
  34.             }     
  35.             EncryptWepKMaterial(&wzcConfig);     
  36.             wzcConfig.dwCtlFlags |= WZCCTL_WEPK_PRESENT;     
  37.         }     
  38.     }     
  39.     else if(wzcConfig.Privacy == Ndis802_11Encryption2Enabled     
  40.         || wzcConfig.Privacy == Ndis802_11Encryption3Enabled)     
  41.     {      
  42.         if(!bNeed8021X)      
  43.         {     
  44.             wzcConfig.KeyLength = wcslen(pKey);     
  45.             if((wzcConfig.KeyLength < 8) || (wzcConfig.KeyLength > 63))     
  46.             {     
  47. //                RETAILMSG(DBG_MSG, (TEXT("WPA-PSK/TKIP key should be 8-63 char long string.\n")));      
  48.                 return FALSE;     
  49.             }   
  50.             char szEncryptionKeyValue8[64]; // longest key is 63     
  51.             memset(szEncryptionKeyValue8, 0, sizeof(szEncryptionKeyValue8));     
  52.             WideCharToMultiByte(CP_ACP,     
  53.                 0,     
  54.                 pKey,     
  55.                 wzcConfig.KeyLength + 1,     
  56.                 szEncryptionKeyValue8,     
  57.                 wzcConfig.KeyLength + 1,     
  58.                 NULL,     
  59.                 NULL);     
  60.             WZCPassword2Key(&wzcConfig, szEncryptionKeyValue8);     
  61.             EncryptWepKMaterial(&wzcConfig);     
  62.             wzcConfig.dwCtlFlags |= WZCCTL_WEPK_XFORMAT     
  63.                 | WZCCTL_WEPK_PRESENT     
  64.                 | WZCCTL_ONEX_ENABLED;     
  65.         }     
  66.         wzcConfig.EapolParams.dwEapFlags = EAPOL_ENABLED;     
  67.         wzcConfig.EapolParams.dwEapType = DEFAULT_EAP_TYPE;     
  68.         wzcConfig.EapolParams.bEnable8021x = TRUE;     
  69.         wzcConfig.WPAMCastCipher = Ndis802_11Encryption2Enabled;     
  70.     }     
  71.     return TRUE;     
  72. }      
原创粉丝点击