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

来源:互联网 发布:mac怎么复制文件到u盘 编辑:程序博客网 时间:2024/06/03 11:30

博主已改行多年,不再提供文件,见谅。

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

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

    下面是一整套通过WZC函数连接无线网的程序,我自己测试后保证可以运行.

最近测试下面的代码时,发现连接没有密码的AP是会连接不上。已经修改。

    调用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 Wifioption::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 Wifioption::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 Wifioption::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 Wifioption::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 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)  //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;  */            //CRICH_MOON 修改于2012年12月14日            bRet = InterpretEncryptionKeyValue(wzcConfig, iKeyIndex, pKey, FALSE);                      }                   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 Wifioption::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的首选网络列表

voidWifioption::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 Wifioption::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 Wifioption::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;   }