1. 程式人生 > >【WindowsCE 】WinCE WIFI 無線網絡卡的配置和建立連線

【WindowsCE 】WinCE WIFI 無線網絡卡的配置和建立連線

    在 Windows CE 下自帶有無線網絡卡的配置和連線程式,這篇文章就來談一下如何用那麼可以利用微軟自帶的WZC函式來重新編寫一個獨立於系統的WIFI連線程式.

     下面是一整套通過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")  

二、列舉系統中可用的無線網路裝置

  1. BOOL GetFirstWirelessCard(PTCHAR pCard)
  2. {
  3.     if (!pCard)
  4.     {
  5.         return FALSE;
  6.     }
  7.     INTFS_KEY_TABLE IntfsTable;
  8.     IntfsTable.dwNumIntfs = 0;
  9.     IntfsTable.pIntfs = NULL;
  10.     _tcscpy(pCard, TEXT(""));
  11.     // 列舉系統中可用的無線網絡卡
  12.     DWORD dwStatus = WZCEnumInterfaces(NULL, &IntfsTable);
  13.     if (dwStatus != ERROR_SUCCESS)
  14.     {
  15.         RETAILMSG(DBG_MSG, (TEXT("WZCEnumInterfaces() error 0x%08X\n"),dwStatus));
  16.         return FALSE;
  17.     }
  18.     // 判斷無線網絡卡的數量,可以根據無線網絡卡數量來枚舉出所有可用的無線網絡卡
  19.     if (!IntfsTable.dwNumIntfs)
  20.     {
  21.         RETAILMSG(DBG_MSG, (TEXT("System has no wireless card.\n"
    )));
  22.         return FALSE;
  23.     }
  24.     _tcscpy(pCard, IntfsTable.pIntfs[0].wszGuid);
  25.     LocalFree(IntfsTable.pIntfs);
  26.     return TRUE;
  27. }

三、獲取無線網路資訊

        獲取到了系統可用的無線網絡卡後,我們就可以利用它的 GUID 號來進行進一步的操作了,首先要做的事情就是得到該無線網絡卡的資訊以及該無線網絡卡掃描到的 WIFI 閘道器資訊。

        以下函式可以獲取到該無線網絡卡及掃描的到的無線 AP 資訊

  1. //////////////////////////////////////////////////////////////////////////
  2. // pCard: 無線網絡卡 GUID
  3. // pIntf: 無線網絡卡配置資訊結果體
  4. // pOutFlags: 網絡卡配置資訊掩碼標誌
  5. //////////////////////////////////////////////////////////////////////////
  6. BOOL GetWirelessCardInfo(PTCHAR pCard, PINTF_ENTRY_EX pIntf, PDWORD pOutFlags)
  7. {
  8.     TCHAR *szWiFiCard = NULL;
  9.     // 引數校驗
  10.     if (!pCard || !pIntf || !pOutFlags)
  11.     {
  12.         RETAILMSG(DBG_MSG, (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(DBG_MSG, (TEXT("WZCQueryInterfaceEx() error 0x%08X\n"), dwStatus));
  26.         return FALSE;
  27.     }
  28.     return TRUE;
  29. }

        四、判斷連線狀態

        我們可以通過無線網絡卡的狀態來判斷當前無線網絡卡是否已經和無線AP建立了連線

  1. BOOL IsAssociated(const INTF_ENTRY_EX Intf, const DWORD dwOutFlags)
  2. {   
  3.     if (dwOutFlags & INTF_BSSID)
  4.     {
  5.         PRAW_DATA prdMAC = (PRAW_DATA)(&Intf.rdBSSID);
  6.         // 判斷 BSSID 的 MAC 地址是否有效來判斷是否和無線AP建立了連線
  7.         if (prdMAC == NULL || prdMAC->dwDataLen == 0 || 
  8.             (!prdMAC->pData[0] && !prdMAC->pData[1] && !prdMAC->pData[2] &
  9.             !prdMAC->pData[3] && !prdMAC->pData[4] && !prdMAC->pData[5]))
  10.         {
  11.             RETAILMSG(DBG_MSG, (TEXT("(This wifi card is not associated to any)\n")));
  12.             return FALSE;
  13.         }
  14.         else
  15.         {
  16.             RETAILMSG(DBG_MSG, (TEXT("(This wifi card is associated state)\n")));
  17.             return TRUE;
  18.         }
  19.     }
  20.     else
  21.     {
  22.         return FALSE;
  23.     }   
  24. }

        五、獲取無線AP資訊

        獲取了無線網絡卡的資訊後,可以通過無線網絡卡枚舉出當前所有可用的無線AP的SSID名稱以及加密模式等等所有可用資訊,一下函式可以實現該功能

  1. void GetWirelseeListSSID(const PRAW_DATA prdBSSIDList, HWND hListCtlWnd)
  2. {
  3.     if (prdBSSIDList == NULL || prdBSSIDList->dwDataLen  == 0)
  4.     {
  5.         RETAILMSG(DBG_MSG, (TEXT("<null> entry.\n")));
  6.     }
  7.     else
  8.     {
  9.         PWZC_802_11_CONFIG_LIST pConfigList = (PWZC_802_11_CONFIG_LIST)prdBSSIDList->pData;
  10.         //RETAILMSG(DBG_MSG, (TEXT("[%d] entries.\n"), pConfigList->NumberOfItems));
  11.         uint i;
  12.         // 列舉所有無線AP
  13.         for (i = 0; i < pConfigList->NumberOfItems; i++)
  14.         {
  15.             PWZC_WLAN_CONFIG pConfig = &(pConfigList->Config[i]);
  16.             RAW_DATA rdBuffer;
  17.             rdBuffer.dwDataLen = pConfig->Ssid.SsidLength;
  18.             rdBuffer.pData = pConfig->Ssid.Ssid;
  19.             TCHAR tSsid[MAX_PATH];
  20.             // 將 SSID 的 ASCII 碼轉化成字串
  21.             PrintSSID(&rdBuffer, tSsid);
  22.             if (hListCtlWnd)
  23.             {                   
  24.                 if (ListBox_FindString(hListCtlWnd, 0, tSsid) == LB_ERR)
  25.                 {
  26.                     ListBox_AddString(hListCtlWnd, tSsid);
  27.                 }               
  28.             }
  29.             //RETAILMSG(DBG_MSG, (TEXT("\n"))); 
  30.         }
  31.     }
  32. }

        六、連線到指定的無線AP

  1. //////////////////////////////////////////////////////////////////////////
  2. // pCard: 無線網絡卡 GUID
  3. // pSSID: 無線AP SSID號
  4. // bAdhoc: 是否點對點的 WIFI 連線
  5. // ulPrivacy: 加密模式(WEP/WPA....)
  6. // ndisMode: 認證模式(Open/Share)
  7. // iKeyIndex: 金鑰索引(1-4)
  8. // pKey: 密碼
  9. // iEapType: 802.11 認證模式
  10. //////////////////////////////////////////////////////////////////////////
  11. BOOL WirelessConnect(PTCHAR pCard, PTCHAR pSSID, BOOL bAdhoc, ULONG ulPrivacy, NDIS_802_11_AUTHENTICATION_MODE ndisMode, int iKeyIndex, PTCHAR pKey, int iEapType)
  12. {
  13.     BOOL bRet = FALSE;
  14.     if (!pSSID)
  15.     {
  16.         RETAILMSG(DBG_MSG, (TEXT("Param Error.\n")));
  17.         return FALSE;
  18.     }
  19.     else
  20.     {
  21.         WZC_WLAN_CONFIG wzcConfig;
  22.         ZeroMemory(&wzcConfig, sizeof(WZC_WLAN_CONFIG));
  23.         wzcConfig.Length = sizeof(WZC_WLAN_CONFIG);
  24.         wzcConfig.dwCtlFlags = 0;
  25.         wzcConfig.Ssid.SsidLength = _tcslen(pSSID);
  26.         for (UINT i = 0; i < wzcConfig.Ssid.SsidLength; i++)
  27.         {
  28.             wzcConfig.Ssid.Ssid[i] = (CHAR)pSSID[i];
  29.         }
  30.         if (bAdhoc)
  31.         {
  32.             wzcConfig.InfrastructureMode = Ndis802_11IBSS;
  33.         }
  34.         else
  35.         {
  36.             wzcConfig.InfrastructureMode = Ndis802_11Infrastructure;
  37.         }
  38.         wzcConfig.AuthenticationMode = ndisMode;
  39.         wzcConfig.Privacy = ulPrivacy;
  40.         if (pKey == NULL || _tcslen(pKey) == 0)
  41.         {
  42.             // 對金鑰進行轉換
  43.             bRet = InterpretEncryptionKeyValue(wzcConfig, 0, NULL, TRUE);
  44.             wzcConfig.EapolParams.dwEapType = iEapType;
  45.             wzcConfig.EapolParams.dwEapFlags = EAPOL_ENABLED;
  46.             wzcConfig.EapolParams.bEnable8021x  = TRUE;
  47.             wzcConfig.EapolParams.dwAuthDataLen = 0;
  48.             wzcConfig.EapolParams.pbAuthData = 0;
  49.         }
  50.         else
  51.         {
  52.             RETAILMSG(DBG_MSG, (TEXT("WirelessConnect iKeyIndex = %d.\n"), iKeyIndex));             
  53.             bRet = InterpretEncryptionKeyValue(wzcConfig, iKeyIndex, pKey, FALSE);
  54.         }
  55.         // 連線到指定的無線AP,並將該AP新增到首先無線AP中
  56.         AddToPreferredNetworkList(pCard, wzcConfig, pSSID);     
  57.     }
  58.     return bRet;
  59. }

        七、金鑰轉換

        輸入的金鑰需要通過加密方式進行一定的轉化,以下函式可以完成改功能

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

        通過以上操作,完全可以連線到可用的無線AP了。