wince下实现wifi无线网络的连接和配置(WLAN)

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

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

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

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

    #include   
    #include   
    #include   
    #include   
    #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 &SsidList)
{
    SsidInfo tempInfo;
    WCHAR tSsid[MAX_PATH];
    if (prdBSSIDList == NULL || prdBSSIDList->dwDataLen  == 0)
    {
        //         RETAILMSG(DBG_MSG, (TEXT(" 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);
        }
    }
}
取得无线网的SSID名称
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"");
    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; iConfig[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>= 1;   
                for(UINT i=0; i 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;   
}    



你可能感兴趣的:(wince下实现wifi无线网络的连接和配置(WLAN))