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

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

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

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

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

[cpp] view plaincopyprint?
  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的基本信息的数据结构:
[cpp] view plaincopyprint?
  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.取得无线网卡

[cpp] view plaincopyprint?
  1. BOOL 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.从无线网卡取得无线网络信息
[cpp] view plaincopyprint?
  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(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,信号强度,加密方式等等


[cpp] view plaincopyprint?
  1. void 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. }
取得无线网的SSID名称
[cpp] view plaincopyprint?
  1. void PrintSSID
  2. // some RAW_DATA is a SSID, this function is for printing SSID
  3. (
  4. PRAW_DATA prdSSID, // RAW SSID data
  5. WCHAR* tSsid
  6. )
  7. {
  8. if (prdSSID == NULL || prdSSID->dwDataLen == 0)
  9. wprintf(L"<NULL>");
  10. else
  11. {
  12. WCHAR szSsid[33];
  13. MultiByteToWideChar(CP_ACP,0,(LPCSTR)prdSSID->pData,-1,tSsid,MAX_PATH*2);
  14. }
  15. } // PrintSSID()

4.根据上面得到的信息,加上用户输入的密码,生成的信息交给WINDOWS 的首选网络列表
[cpp] view plaincopyprint?
  1. 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)
  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. if (pKey == NULL || _tcslen(pKey) == 0)
  26. {
  27. // 对密钥进行转换
  28. bRet = InterpretEncryptionKeyValue(wzcConfig, 0, NULL, TRUE);
  29. wzcConfig.EapolParams.dwEapType = iEapType;
  30. wzcConfig.EapolParams.dwEapType =EAP_TYPE_TLS;
  31. wzcConfig.EapolParams.dwEapFlags = EAPOL_ENABLED;
  32. wzcConfig.EapolParams.bEnable8021x = TRUE;
  33. wzcConfig.EapolParams.dwAuthDataLen = 0;
  34. wzcConfig.EapolParams.pbAuthData = 0;
  35. }
  36. else
  37. {
  38. // RETAILMSG(DBG_MSG, (TEXT("WirelessConnect iKeyIndex = %d.\n"), iKeyIndex));
  39. bRet = InterpretEncryptionKeyValue(wzcConfig, iKeyIndex, pKey, FALSE);
  40. }
  41. // 连接到指定的无线AP,并将该AP添加到首先无线AP中
  42. AddToPreferredNetworkList(pCard, wzcConfig, pSSID);
  43. }
  44. return bRet;
  45. }

5.加入WINDOWS的首选网络列表
[cpp] view plaincopyprint?
  1. void 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. DWORD dwStatus = WZCQueryInterfaceEx(
  16. NULL,
  17. INTF_ALL,
  18. &Intf,
  19. &dwOutFlags);
  20. if(dwStatus)
  21. {
  22. wprintf(L"WZCQueryInterfaceEx() error dwStatus=0x%0X, dwOutFlags=0x%0X", dwStatus, dwOutFlags);
  23. WZCDeleteIntfObjEx(&Intf);
  24. return;
  25. }
  26. WZC_802_11_CONFIG_LIST *pConfigList = (PWZC_802_11_CONFIG_LIST)Intf.rdStSSIDList.pData;
  27. if(!pConfigList) // empty [Preferred Networks] list case
  28. {
  29. DWORD dwDataLen = sizeof(WZC_802_11_CONFIG_LIST);
  30. WZC_802_11_CONFIG_LIST *pNewConfigList = (WZC_802_11_CONFIG_LIST *)LocalAlloc(LPTR, dwDataLen);
  31. pNewConfigList->NumberOfItems = 1;
  32. pNewConfigList->Index = 0;
  33. memcpy(pNewConfigList->Config, &wzcConfig1, sizeof(wzcConfig1));
  34. Intf.rdStSSIDList.pData = (BYTE*)pNewConfigList;
  35. Intf.rdStSSIDList.dwDataLen = dwDataLen;
  36. }
  37. else
  38. {
  39. ULONG uiNumberOfItems = pConfigList->NumberOfItems;
  40. for(UINT i=0; i<uiNumberOfItems; i++)
  41. {
  42. if(memcmp(&wzcConfig1.Ssid, &pConfigList->Config[i].Ssid,sizeof(NDIS_802_11_SSID)) == 0)
  43. {
  44. wprintf(L"%s is already in the [Preferred Networks] list", szSsidToConnect);
  45. WZCDeleteIntfObjEx(&Intf);
  46. return;
  47. }
  48. }
  49. wprintf(L"SSID List has [%d] entries.\n", uiNumberOfItems);
  50. wprintf(L"adding %s to the top of [Preferred Networks]\n", szSsidToConnect);// this will be the most preferable SSID
  51. DWORD dwDataLen = sizeof(WZC_802_11_CONFIG_LIST) + (uiNumberOfItems+1)*sizeof(WZC_WLAN_CONFIG);
  52. WZC_802_11_CONFIG_LIST *pNewConfigList = (WZC_802_11_CONFIG_LIST *)LocalAlloc(LPTR, dwDataLen);
  53. pNewConfigList->NumberOfItems = uiNumberOfItems + 1;
  54. pNewConfigList->Index = 0;
  55. memcpy(pNewConfigList->Config, &wzcConfig1, sizeof(wzcConfig1));
  56. if(pConfigList->NumberOfItems)
  57. {
  58. pNewConfigList->Index = pConfigList->Index;
  59. memcpy(pNewConfigList->Config+1, pConfigList->Config, (uiNumberOfItems)*sizeof(WZC_WLAN_CONFIG));
  60. LocalFree(pConfigList);
  61. pConfigList = NULL;
  62. }
  63. Intf.rdStSSIDList.pData = (BYTE*)pNewConfigList;
  64. Intf.rdStSSIDList.dwDataLen = dwDataLen;
  65. }
  66. dwStatus = WZCSetInterfaceEx(NULL, INTF_PREFLIST, &Intf, &dwOutFlags);
  67. if(dwStatus)
  68. wprintf(L"WZCSetInterfaceEx() error dwStatus=0x%0X, dwOutFlags=0x%0X", dwStatus, dwOutFlags);
  69. WZCDeleteIntfObjEx(&Intf);
  70. } // AddToPreferredNetworkList()

6.重置WINDOWS的首选网络列表
[cpp] view plaincopyprint?
  1. void ResetPreferredList
  2. // reset the [Preferred Networks], so wireless will be disconnected
  3. // wzctool -reset cisco1
  4. // reset CISCO1 adapter.
  5. // wzctool -reset
  6. // reset the first wireless adapter found in the system
  7. (
  8. PTCHAR pCard
  9. )
  10. {
  11. WCHAR *szWiFiCard = NULL;
  12. szWiFiCard = pCard;
  13. DWORD dwInFlags = 0;
  14. INTF_ENTRY_EX Intf;
  15. memset(&Intf, 0x00, sizeof(INTF_ENTRY_EX));
  16. Intf.wszGuid = szWiFiCard;
  17. DWORD dwStatus = WZCSetInterfaceEx(NULL, INTF_PREFLIST, &Intf, &dwInFlags);
  18. if(dwStatus)
  19. wprintf(L"WZCSetInterfaceEx() error dwStatus=0x%0X, dwOutFlags=0x%0X", dwStatus, dwInFlags);
  20. else
  21. wprintf(L"now, WZC resets [Preferred Networks]\n");
  22. } // ResetPreferredList()

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



原创粉丝点击