Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1432 lines
47 KiB

  1. #include <precomp.h>
  2. #include "wzcatl.h"
  3. #include "quickcfg.h"
  4. #include "eapolcfg.h"
  5. #include "wzccore.h"
  6. #include "wzchelp.h"
  7. #define RFSH_TIMEOUT 3500
  8. UINT g_TimerID = 373;
  9. // g_wszHiddWebK is a string of 26 bullets (0x25cf - the hidden password char) and a NULL
  10. WCHAR g_wszHiddWepK[] = {0x25cf, 0x25cf, 0x25cf, 0x25cf, 0x25cf, 0x25cf, 0x25cf, 0x25cf, 0x25cf, 0x25cf, 0x25cf, 0x25cf, 0x25cf,
  11. 0x25cf, 0x25cf, 0x25cf, 0x25cf, 0x25cf, 0x25cf, 0x25cf, 0x25cf, 0x25cf, 0x25cf, 0x25cf, 0x25cf, 0x25cf, 0x0000};
  12. #define ARRAYSIZE(x) (sizeof((x)) / sizeof((x)[0]))
  13. // Enhanced message box function
  14. int DisplayFormatMessage(HWND hwnd, UINT idCaption, UINT idFormatString, UINT uType, ...);
  15. //+---------------------------------------------------------------------------
  16. // checks the validity of the WEP Key material and selects the
  17. // material from the first invalid char (non hexa in hexa format or longer
  18. // than the specified length
  19. DWORD
  20. CWZCQuickCfg::GetWepKMaterial(UINT *pnKeyLen, LPBYTE *ppbKMat, DWORD *pdwCtlFlags)
  21. {
  22. DWORD dwErr = ERROR_SUCCESS;
  23. UINT nKeyLen = ::GetWindowTextLength(m_hEdtWepK);
  24. DWORD dwCtlFlags = 0;
  25. LPSTR pszKMat = NULL;
  26. // we only accept the follwing material for WEP keys:
  27. // - no text (length 0) => there is no WEP key provided
  28. // - 5 chars or 10 hexadecimal digits (5byte / 40bit key)
  29. // - 13 chars or 26 hexadecimal digits (13byte / 104bit key)
  30. // - 16 chars or 32 hexadecimal digits (16byte / 128bit key)
  31. if (nKeyLen != 0 &&
  32. nKeyLen != WZC_WEPKMAT_40_ASC && nKeyLen != WZC_WEPKMAT_40_HEX &&
  33. nKeyLen != WZC_WEPKMAT_104_ASC && nKeyLen != WZC_WEPKMAT_104_HEX &&
  34. nKeyLen != WZC_WEPKMAT_128_ASC && nKeyLen != WZC_WEPKMAT_128_HEX)
  35. {
  36. dwErr = ERROR_INVALID_DATA;
  37. }
  38. else if (nKeyLen != 0) // the key is either ascii or hexadecimal, 40 or 104bit
  39. {
  40. dwCtlFlags = WZCCTL_WEPK_PRESENT;
  41. pszKMat = new CHAR[nKeyLen + 1];
  42. if (pszKMat == NULL)
  43. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  44. // get the current key material from the edit control
  45. if (dwErr == ERROR_SUCCESS)
  46. {
  47. if (nKeyLen != ::GetWindowTextA(m_hEdtWepK, pszKMat, nKeyLen+1))
  48. dwErr = GetLastError();
  49. }
  50. // now we have the key material
  51. if (dwErr == ERROR_SUCCESS)
  52. {
  53. // if the key is provided in hexadecimal digits, mark it in
  54. // the ctl flags and do the conversion
  55. if (nKeyLen == WZC_WEPKMAT_40_HEX || nKeyLen == WZC_WEPKMAT_104_HEX || nKeyLen == WZC_WEPKMAT_128_HEX)
  56. {
  57. UINT i = 0, j = 0;
  58. dwCtlFlags |= WZCCTL_WEPK_XFORMAT;
  59. while (i < nKeyLen && pszKMat[i] != '\0')
  60. {
  61. BYTE chHexByte = 0;
  62. if (!isxdigit(pszKMat[i]) || !isxdigit(pszKMat[i+1]))
  63. {
  64. dwErr = ERROR_INVALID_DATA;
  65. break;
  66. }
  67. chHexByte = HEX(pszKMat[i]) << 4;
  68. i++;
  69. chHexByte |= HEX(pszKMat[i]);
  70. i++;
  71. pszKMat[j++] = chHexByte;
  72. }
  73. // if everything went fine, since we parsed hexadecimal digits
  74. // it means the real length is half of the text length (two hexadecimal
  75. // digits per byte)
  76. if (dwErr == ERROR_SUCCESS)
  77. nKeyLen /= 2;
  78. }
  79. }
  80. }
  81. if (dwErr == ERROR_SUCCESS)
  82. {
  83. if (pdwCtlFlags != NULL)
  84. *pdwCtlFlags = dwCtlFlags;
  85. if (pnKeyLen != NULL)
  86. *pnKeyLen = nKeyLen;
  87. if (ppbKMat != NULL)
  88. *ppbKMat = (LPBYTE)pszKMat;
  89. else if (pszKMat != NULL)
  90. delete pszKMat;
  91. }
  92. else
  93. {
  94. if (pszKMat != NULL)
  95. delete pszKMat;
  96. }
  97. return dwErr;
  98. }
  99. //+---------------------------------------------------------------------
  100. // IsConfigInList - checks whether the pwzcConfig (WZC_WLAN_CONFIG object) is
  101. // in the list provided as the first parameter.
  102. BOOL
  103. CWZCQuickCfg::IsConfigInList(CWZCConfig *pHdList, PWZC_WLAN_CONFIG pwzcConfig, CWZCConfig **ppMatchingConfig)
  104. {
  105. BOOL bYes = FALSE;
  106. if (pHdList != NULL)
  107. {
  108. CWZCConfig *pwzcCrt;
  109. pwzcCrt = pHdList;
  110. do
  111. {
  112. if (pwzcCrt->Match(pwzcConfig))
  113. {
  114. if (ppMatchingConfig != NULL)
  115. *ppMatchingConfig = pwzcCrt;
  116. bYes = TRUE;
  117. break;
  118. }
  119. pwzcCrt = pwzcCrt->m_pNext;
  120. } while(pwzcCrt != pHdList);
  121. }
  122. return bYes;
  123. }
  124. //+---------------------------------------------------------------------
  125. // InitListView - initializes the networks list view (doesn't fill it in)
  126. DWORD
  127. CWZCQuickCfg::InitListView()
  128. {
  129. RECT rc;
  130. LV_COLUMN lvc = {0};
  131. DWORD dwStyle;
  132. // initialize the image list styles
  133. dwStyle = ::GetWindowLong(m_hLstNetworks, GWL_STYLE);
  134. ::SetWindowLong(m_hLstNetworks, GWL_STYLE, (dwStyle | LVS_SHAREIMAGELISTS));
  135. // Create state image lists
  136. m_hImgs = ImageList_LoadImage(
  137. _Module.GetResourceInstance(),
  138. MAKEINTRESOURCE(IDB_WZC_LISTICONS),
  139. 16,
  140. 0,
  141. PALETTEINDEX(6),
  142. IMAGE_BITMAP,
  143. 0);
  144. ListView_SetImageList(m_hLstNetworks, m_hImgs, LVSIL_SMALL);
  145. lvc.mask = LVCF_FMT | LVCF_WIDTH;
  146. lvc.fmt = LVCFMT_LEFT;
  147. ::GetClientRect(m_hLstNetworks, &rc);
  148. lvc.cx = rc.right - GetSystemMetrics(SM_CXVSCROLL);
  149. //lvc.cx = rc.right;
  150. ListView_InsertColumn(m_hLstNetworks, 0, &lvc);
  151. ListView_SetExtendedListViewStyleEx(m_hLstNetworks, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);
  152. return ERROR_SUCCESS;
  153. }
  154. //+---------------------------------------------------------------------
  155. // GetOIDs - gets the OIDs for the m_IntfEntry member. It assumes the
  156. // GUID is set already
  157. DWORD
  158. CWZCQuickCfg::GetOIDs(DWORD dwInFlags, LPDWORD pdwOutFlags)
  159. {
  160. DWORD dwError = ERROR_SUCCESS;
  161. DWORD dwOutFlags;
  162. if (m_IntfEntry.wszGuid == NULL)
  163. {
  164. m_IntfEntry.wszGuid = (LPWSTR)RpcCAlloc(sizeof(WCHAR)*GUID_NCH);
  165. if (m_IntfEntry.wszGuid == NULL)
  166. {
  167. dwError = GetLastError();
  168. }
  169. else
  170. {
  171. // don't care of the return code. If getting the GUID fails (it shouldn't)
  172. // then we end up with a "0000..." GUID which will fail anyhow in the
  173. // RPC call later
  174. StringFromGUID2(
  175. m_Guid,
  176. m_IntfEntry.wszGuid,
  177. GUID_NCH);
  178. }
  179. }
  180. if (dwError == ERROR_SUCCESS)
  181. {
  182. if (dwInFlags & INTF_DESCR)
  183. {
  184. RpcFree(m_IntfEntry.wszDescr);
  185. m_IntfEntry.wszDescr = NULL;
  186. }
  187. if (dwInFlags & INTF_PREFLIST)
  188. {
  189. RpcFree(m_IntfEntry.rdStSSIDList.pData);
  190. m_IntfEntry.rdStSSIDList.dwDataLen = 0;
  191. m_IntfEntry.rdStSSIDList.pData = NULL;
  192. }
  193. if (dwInFlags & INTF_SSID)
  194. {
  195. RpcFree(m_IntfEntry.rdSSID.pData);
  196. m_IntfEntry.rdSSID.dwDataLen = 0;
  197. m_IntfEntry.rdSSID.pData = NULL;
  198. }
  199. if (dwInFlags & INTF_BSSID)
  200. {
  201. RpcFree(m_IntfEntry.rdBSSID.pData);
  202. m_IntfEntry.rdBSSID.dwDataLen = 0;
  203. m_IntfEntry.rdBSSID.pData = NULL;
  204. }
  205. if (dwInFlags & INTF_BSSIDLIST)
  206. {
  207. RpcFree(m_IntfEntry.rdBSSIDList.pData);
  208. m_IntfEntry.rdBSSIDList.dwDataLen = 0;
  209. m_IntfEntry.rdBSSIDList.pData = NULL;
  210. }
  211. dwError = WZCQueryInterface(
  212. NULL,
  213. dwInFlags,
  214. &m_IntfEntry,
  215. pdwOutFlags);
  216. }
  217. return dwError;
  218. }
  219. //+---------------------------------------------------------------------
  220. // SavePreferredConfigs - fills in the INTF_ENTRY parameter with all
  221. // the preferred networks from the m_pHdPList
  222. DWORD
  223. CWZCQuickCfg::SavePreferredConfigs(PINTF_ENTRY pIntf, CWZCConfig *pStartCfg)
  224. {
  225. DWORD dwErr = ERROR_SUCCESS;
  226. CWZCConfig *pCrt = NULL;
  227. UINT nPrefrd = 0;
  228. if (m_pHdPList != NULL)
  229. {
  230. // count first the number of preferred entries in the list
  231. pCrt = m_pHdPList;
  232. do
  233. {
  234. nPrefrd++;
  235. pCrt = pCrt->m_pNext;
  236. } while(pCrt != m_pHdPList);
  237. }
  238. if (nPrefrd > 0)
  239. {
  240. PWZC_802_11_CONFIG_LIST pwzcPrefrdList;
  241. UINT nwzcPrefrdSize;
  242. nwzcPrefrdSize = sizeof(WZC_802_11_CONFIG_LIST)+ (nPrefrd-1)*sizeof(WZC_WLAN_CONFIG);
  243. // allocate as much memory as needed for storing all the preferred SSIDs
  244. pwzcPrefrdList = (PWZC_802_11_CONFIG_LIST)RpcCAlloc(nwzcPrefrdSize);
  245. if (pwzcPrefrdList == NULL)
  246. {
  247. dwErr = GetLastError();
  248. }
  249. else
  250. {
  251. DWORD dwLErr;
  252. pwzcPrefrdList->NumberOfItems = 0;
  253. pwzcPrefrdList->Index = 0;
  254. // we have now all we need - start copying the preferred
  255. pCrt = m_pHdPList;
  256. do
  257. {
  258. PWZC_WLAN_CONFIG pPrefrdConfig;
  259. // if this is the configuration that needs to attempted first,
  260. // mark its index in the Index field.
  261. if (pCrt == pStartCfg)
  262. {
  263. pwzcPrefrdList->Index = pwzcPrefrdList->NumberOfItems;
  264. // save the 802.1x configuration just for the configuration we're connecting to!
  265. if (pCrt->m_pEapolConfig != NULL)
  266. {
  267. dwLErr = pCrt->m_pEapolConfig->SaveEapolConfig(m_IntfEntry.wszGuid, &(pCrt->m_wzcConfig.Ssid));
  268. if (dwErr == ERROR_SUCCESS)
  269. dwErr = dwLErr;
  270. }
  271. }
  272. pPrefrdConfig = &(pwzcPrefrdList->Config[pwzcPrefrdList->NumberOfItems++]);
  273. CopyMemory(pPrefrdConfig, &pCrt->m_wzcConfig, sizeof(WZC_WLAN_CONFIG));
  274. pCrt = pCrt->m_pNext;
  275. } while(pwzcPrefrdList->NumberOfItems < nPrefrd && pCrt != m_pHdPList);
  276. pIntf->rdStSSIDList.dwDataLen = nwzcPrefrdSize;
  277. pIntf->rdStSSIDList.pData = (LPBYTE)pwzcPrefrdList;
  278. }
  279. }
  280. else
  281. {
  282. pIntf->rdStSSIDList.dwDataLen = 0;
  283. pIntf->rdStSSIDList.pData = NULL;
  284. }
  285. return dwErr;
  286. }
  287. //+---------------------------------------------------------------------
  288. // FillVisibleList - fills in the configs from the WZC_802_11_CONFIG_LIST object
  289. // into the list of visible configs
  290. DWORD
  291. CWZCQuickCfg::FillVisibleList(PWZC_802_11_CONFIG_LIST pwzcVList)
  292. {
  293. DWORD dwErr = ERROR_SUCCESS;
  294. UINT i;
  295. // cleanup whatever we might already have in the visible list
  296. if (m_pHdVList != NULL)
  297. {
  298. while (m_pHdVList->m_pNext != m_pHdVList)
  299. {
  300. delete m_pHdVList->m_pNext;
  301. }
  302. delete m_pHdVList;
  303. m_pHdVList = NULL;
  304. }
  305. if (pwzcVList != NULL)
  306. {
  307. for (i = 0; i < pwzcVList->NumberOfItems; i++)
  308. {
  309. dwErr = AddUniqueConfig(
  310. 0, // no op flags
  311. WZC_DESCR_VISIBLE, // this is a visible entry
  312. &(pwzcVList->Config[i]));
  313. // reset the error if config was just duplicated
  314. if (dwErr == ERROR_DUPLICATE_TAG)
  315. dwErr = ERROR_SUCCESS;
  316. }
  317. }
  318. return dwErr;
  319. }
  320. //+---------------------------------------------------------------------
  321. // FillPreferredList - fills in the configs from the WZC_802_11_CONFIG_LIST object
  322. // into the list of preferred configs
  323. DWORD
  324. CWZCQuickCfg::FillPreferredList(PWZC_802_11_CONFIG_LIST pwzcPList)
  325. {
  326. DWORD dwErr = ERROR_SUCCESS;
  327. UINT i;
  328. // cleanup whatever we might already have in the preferred list
  329. if (m_pHdPList != NULL)
  330. {
  331. while (m_pHdPList ->m_pNext != m_pHdPList)
  332. {
  333. delete m_pHdPList ->m_pNext;
  334. }
  335. delete m_pHdPList;
  336. m_pHdPList = NULL;
  337. }
  338. if (pwzcPList != NULL)
  339. {
  340. for (i = 0; i < pwzcPList->NumberOfItems; i++)
  341. {
  342. PWZC_WLAN_CONFIG pwzcPConfig = &(pwzcPList->Config[i]);
  343. CWZCConfig *pVConfig = NULL;
  344. DWORD dwFlags = WZC_DESCR_PREFRD;
  345. // check whether this preferred is also visible and adjust dwFlags if so
  346. if (IsConfigInList(m_pHdVList, pwzcPConfig, &pVConfig))
  347. {
  348. // mark the visible entry as being also preferred!
  349. // NOTE: This is why the visible list needs to be filled in first!
  350. pVConfig->m_dwFlags |= WZC_DESCR_PREFRD;
  351. dwFlags |= WZC_DESCR_VISIBLE;
  352. }
  353. dwErr = AddUniqueConfig(
  354. WZCADD_OVERWRITE, // preferred entries cause info to be overwritten
  355. dwFlags,
  356. pwzcPConfig);
  357. // reset the error if config was just duplicated
  358. if (dwErr == ERROR_DUPLICATE_TAG)
  359. dwErr = ERROR_SUCCESS;
  360. }
  361. }
  362. return dwErr;
  363. }
  364. //+---------------------------------------------------------------------------
  365. // Adds the given configuration to the internal lists. The entries in the lists
  366. // are ordered on InfrastructureMode in descending order. This way the Infrastructure
  367. // entries will be on the top of the list while the adhoc entries will be on the
  368. // bottom. (we rely on the order as it is given in NDIS_802_11_NETWORK_INFRASTRUCTURE)
  369. DWORD
  370. CWZCQuickCfg::AddUniqueConfig(
  371. DWORD dwOpFlags,
  372. DWORD dwEntryFlags,
  373. PWZC_WLAN_CONFIG pwzcConfig,
  374. CWZCConfig **ppNewNode)
  375. {
  376. DWORD dwErr = ERROR_SUCCESS;
  377. CWZCConfig *pHdList = (dwEntryFlags & WZC_DESCR_PREFRD) ? m_pHdPList : m_pHdVList;
  378. // skip the null SSIDs from the visible list (coming from APs
  379. // not responding to broadcast SSID).
  380. if (pHdList == m_pHdVList)
  381. {
  382. UINT i = pwzcConfig->Ssid.SsidLength;
  383. for (; i > 0 && pwzcConfig->Ssid.Ssid[i-1] == 0; i--);
  384. if (i == 0)
  385. goto exit;
  386. }
  387. // if the list is currently empty, create the first entry as the head of the list
  388. if (pHdList == NULL)
  389. {
  390. pHdList = new CWZCConfig(dwEntryFlags, pwzcConfig);
  391. if (pHdList == NULL)
  392. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  393. else
  394. {
  395. pHdList->m_pEapolConfig = new CEapolConfig;
  396. if (pHdList->m_pEapolConfig == NULL)
  397. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  398. else
  399. dwErr = pHdList->m_pEapolConfig->LoadEapolConfig(m_IntfEntry.wszGuid, &(pHdList->m_wzcConfig.Ssid));
  400. if (dwErr != ERROR_SUCCESS)
  401. {
  402. delete pHdList;
  403. pHdList = NULL;
  404. }
  405. }
  406. // if the caller wants, return the pointer to the newly created object
  407. if (ppNewNode != NULL)
  408. *ppNewNode = pHdList;
  409. }
  410. else
  411. {
  412. // else the list already contains at least one element
  413. CWZCConfig *pCrt, *pHdGroup;
  414. // scan the list (keep in mind it is ordered descendingly on IM)
  415. pHdGroup = pCrt = pHdList;
  416. do
  417. {
  418. // check whether we entered a new group of configs (different InfrastructureMode)
  419. if (pHdGroup->m_wzcConfig.InfrastructureMode != pCrt->m_wzcConfig.InfrastructureMode)
  420. pHdGroup = pCrt;
  421. // if found an identical entry (same SSID and same InfraMode)
  422. // signal the DUPLICATE_TAG error
  423. if (pCrt->Match(pwzcConfig))
  424. {
  425. // merge the flags first
  426. pCrt->m_dwFlags |= dwEntryFlags;
  427. // If requested, copy over the new configuration.
  428. // If not explicitly requested, copy over only if the existent configuration
  429. // prooves to be weaker than the one being added.
  430. if (dwOpFlags & WZCADD_OVERWRITE || pCrt->Weaker(pwzcConfig))
  431. {
  432. memcpy(&(pCrt->m_wzcConfig), pwzcConfig, sizeof(WZC_WLAN_CONFIG));
  433. }
  434. // if the caller wants, return the pointer to the matching entry
  435. if (ppNewNode != NULL)
  436. *ppNewNode = pCrt;
  437. // signal there is already a matching config
  438. dwErr = ERROR_DUPLICATE_TAG;
  439. }
  440. pCrt = pCrt->m_pNext;
  441. } while (dwErr == ERROR_SUCCESS &&
  442. pCrt != pHdList &&
  443. pwzcConfig->InfrastructureMode <= pCrt->m_wzcConfig.InfrastructureMode);
  444. // if dwErr is unchanged, this means a new node has to be added ahead of pCrt node
  445. if (dwErr == ERROR_SUCCESS)
  446. {
  447. // create the new config and insert it ahead of this node.
  448. CWZCConfig *pNewConfig;
  449. pNewConfig = new CWZCConfig(dwEntryFlags, pwzcConfig);
  450. if (pNewConfig == NULL)
  451. {
  452. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  453. }
  454. else
  455. {
  456. pNewConfig->m_pEapolConfig = new CEapolConfig;
  457. if (pNewConfig->m_pEapolConfig == NULL)
  458. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  459. else
  460. dwErr = pNewConfig->m_pEapolConfig->LoadEapolConfig(m_IntfEntry.wszGuid, &(pNewConfig->m_wzcConfig.Ssid));
  461. if (dwErr != ERROR_SUCCESS)
  462. {
  463. delete pNewConfig;
  464. pNewConfig = NULL;
  465. }
  466. }
  467. if (dwErr == ERROR_SUCCESS)
  468. {
  469. INT nDiff;
  470. // if asked to insert in the head of the group, pCrt should point to this head
  471. if (dwOpFlags & WZCADD_HIGROUP)
  472. pCrt = pHdGroup;
  473. pNewConfig->m_pPrev = pCrt->m_pPrev;
  474. pNewConfig->m_pNext = pCrt;
  475. pCrt->m_pPrev->m_pNext = pNewConfig;
  476. pCrt->m_pPrev = pNewConfig;
  477. // get the difference between the Infrastructure modes for the new node and
  478. // for the current head
  479. nDiff = pNewConfig->m_wzcConfig.InfrastructureMode - pHdList->m_wzcConfig.InfrastructureMode;
  480. // if the newly entered entry has the largest "key" in
  481. // the existent sequence, or it has to be inserted in the head of its group and it is
  482. // in the first group, then the global list head moves to the new entry
  483. if (nDiff > 0 || ((dwOpFlags & WZCADD_HIGROUP) && (nDiff == 0)))
  484. pHdList = pNewConfig;
  485. }
  486. // if the caller wants, return the pointer to the newly created object
  487. if (ppNewNode != NULL)
  488. *ppNewNode = pNewConfig;
  489. }
  490. }
  491. if (dwEntryFlags & WZC_DESCR_PREFRD)
  492. {
  493. m_pHdPList = pHdList;
  494. }
  495. else
  496. {
  497. m_pHdVList = pHdList;
  498. }
  499. exit:
  500. return dwErr;
  501. }
  502. //+---------------------------------------------------------------------------
  503. // Display the Visible & Preferred lists into their controls
  504. DWORD
  505. CWZCQuickCfg::RefreshListView()
  506. {
  507. DWORD dwErr = ERROR_SUCCESS;
  508. CWZCConfig *pCrt;
  509. UINT i = 0;
  510. // clear first the list
  511. ListView_DeleteAllItems(m_hLstNetworks);
  512. // Add first VPI
  513. if (m_pHdPList != NULL)
  514. {
  515. pCrt = m_pHdPList;
  516. do
  517. {
  518. if (pCrt->m_dwFlags & WZC_DESCR_VISIBLE &&
  519. pCrt->m_wzcConfig.InfrastructureMode == Ndis802_11Infrastructure)
  520. {
  521. pCrt->m_nListIndex = i;
  522. pCrt->AddConfigToListView(m_hLstNetworks, i++);
  523. }
  524. pCrt = pCrt->m_pNext;
  525. } while (pCrt != m_pHdPList);
  526. }
  527. // Add next VI
  528. if (m_pHdVList != NULL)
  529. {
  530. pCrt = m_pHdVList;
  531. do
  532. {
  533. if (!(pCrt->m_dwFlags & WZC_DESCR_PREFRD) &&
  534. pCrt->m_wzcConfig.InfrastructureMode == Ndis802_11Infrastructure)
  535. {
  536. pCrt->m_nListIndex = i;
  537. pCrt->AddConfigToListView(m_hLstNetworks, i++);
  538. }
  539. pCrt = pCrt->m_pNext;
  540. } while (pCrt != m_pHdVList);
  541. }
  542. // Add now VPA
  543. if (m_pHdPList != NULL)
  544. {
  545. pCrt = m_pHdPList;
  546. do
  547. {
  548. if (pCrt->m_dwFlags & WZC_DESCR_VISIBLE &&
  549. pCrt->m_wzcConfig.InfrastructureMode == Ndis802_11IBSS)
  550. {
  551. pCrt->m_nListIndex = i;
  552. pCrt->AddConfigToListView(m_hLstNetworks, i++);
  553. }
  554. pCrt = pCrt->m_pNext;
  555. } while (pCrt != m_pHdPList);
  556. }
  557. // Add now VA
  558. if (m_pHdVList != NULL)
  559. {
  560. pCrt = m_pHdVList;
  561. do
  562. {
  563. if (!(pCrt->m_dwFlags & WZC_DESCR_PREFRD) &&
  564. pCrt->m_wzcConfig.InfrastructureMode == Ndis802_11IBSS)
  565. {
  566. pCrt->m_nListIndex = i;
  567. pCrt->AddConfigToListView(m_hLstNetworks, i++);
  568. }
  569. pCrt = pCrt->m_pNext;
  570. } while (pCrt != m_pHdVList);
  571. }
  572. ListView_SetItemState(m_hLstNetworks, 0, LVIS_SELECTED, LVIS_SELECTED);
  573. ListView_EnsureVisible(m_hLstNetworks, 0, FALSE);
  574. return dwErr;
  575. }
  576. DWORD
  577. CWZCQuickCfg::RefreshControls()
  578. {
  579. DWORD dwError = ERROR_SUCCESS;
  580. CWZCConfig *pConfig = NULL;
  581. LVITEM lvi = {0};
  582. INT iSelected;
  583. BOOL bEnableWepCtrls = FALSE;
  584. UINT nKLen = 0;
  585. UINT nCheckOneX = BST_UNCHECKED;
  586. BOOL bEnableOneX = FALSE;
  587. // get the selected item from the visible list
  588. iSelected = ListView_GetNextItem(m_hLstNetworks, -1, LVNI_SELECTED);
  589. if (iSelected >= 0)
  590. {
  591. lvi.mask = LVIF_PARAM;
  592. lvi.iItem = iSelected;
  593. if (ListView_GetItem(m_hLstNetworks, &lvi))
  594. {
  595. pConfig = (CWZCConfig*)lvi.lParam;
  596. }
  597. }
  598. else
  599. {
  600. ::EnableWindow(m_hBtnConnect, FALSE);
  601. return dwError;
  602. }
  603. // since we just switched the networks, yes, the wep key can be seen as touched.
  604. // If we find out there is already a key available, we'll reset this flag and go
  605. // with that one until the user is clicking it.
  606. m_bKMatTouched = TRUE;
  607. if (pConfig != NULL)
  608. {
  609. CWZCConfig *pVConfig;
  610. // pick up the "privacy" bit from the matching visible configuration
  611. // NOTE: The test below should always succeed actually
  612. if (IsConfigInList(m_pHdVList, &(pConfig->m_wzcConfig), &pVConfig))
  613. bEnableWepCtrls = (pVConfig->m_wzcConfig.Privacy != 0);
  614. else
  615. bEnableWepCtrls = (pConfig->m_wzcConfig.Privacy != 0);
  616. if (pConfig->m_dwFlags & WZC_DESCR_PREFRD &&
  617. pConfig->m_wzcConfig.dwCtlFlags & WZCCTL_WEPK_PRESENT &&
  618. pConfig->m_wzcConfig.KeyLength > 0)
  619. {
  620. //--- when a password is to be displayed as hidden chars, don't put in
  621. //--- its actual length, but just 8 bulled chars.
  622. nKLen = 8;
  623. m_bKMatTouched = FALSE;
  624. }
  625. if (bEnableWepCtrls)
  626. {
  627. // For networks requiring privacy, 802.1X is going to be by default disabled and
  628. // locked out on all IBSS networks.
  629. if (pConfig->m_wzcConfig.InfrastructureMode == Ndis802_11IBSS)
  630. {
  631. nCheckOneX = BST_UNCHECKED;
  632. bEnableOneX = FALSE;
  633. }
  634. else
  635. {
  636. // for all non-preferred Infrastructure networks, 802.1X is going to be by default
  637. // enabled since these networks start with "the key is provided for me automatically"
  638. // which suggests 802.1X.
  639. if (!(pConfig->m_dwFlags & WZC_DESCR_PREFRD))
  640. {
  641. nCheckOneX = BST_CHECKED;
  642. }
  643. else // this is a preferred Infrastructure network
  644. {
  645. // initial 802.1X state is the one from the profile
  646. nCheckOneX = pConfig->m_pEapolConfig->Is8021XEnabled() ?
  647. BST_CHECKED:
  648. BST_UNCHECKED;
  649. }
  650. // for Infrastructure networks requiring privacy, user is allowed to change 802.1X state
  651. bEnableOneX = TRUE;
  652. }
  653. }
  654. }
  655. g_wszHiddWepK[nKLen] = L'\0';
  656. ::SetWindowText(m_hEdtWepK, g_wszHiddWepK);
  657. ::SetWindowText(m_hEdtWepK2, g_wszHiddWepK);
  658. g_wszHiddWepK[nKLen] = 0x25cf;
  659. if (bEnableWepCtrls)
  660. {
  661. CheckDlgButton(IDC_WZCQCFG_CHK_ONEX, nCheckOneX);
  662. ::EnableWindow(m_hChkOneX, bEnableOneX);
  663. if (::IsWindowEnabled(m_hEdtWepK2))
  664. {
  665. ::EnableWindow(m_hLblWepK2, FALSE);
  666. ::EnableWindow(m_hEdtWepK2, FALSE);
  667. }
  668. if (::IsWindowVisible(m_hLblNoWepKInfo))
  669. {
  670. ::ShowWindow(m_hWarnIcon, SW_HIDE);
  671. ::ShowWindow(m_hLblNoWepKInfo, SW_HIDE);
  672. ::ShowWindow(m_hChkNoWepK, SW_HIDE);
  673. }
  674. if (!::IsWindowVisible(m_hLblWepKInfo))
  675. {
  676. ::ShowWindow(m_hLblWepKInfo, SW_SHOW);
  677. ::ShowWindow(m_hLblWepK, SW_SHOW);
  678. ::ShowWindow(m_hEdtWepK, SW_SHOW);
  679. ::ShowWindow(m_hLblWepK2, SW_SHOW);
  680. ::ShowWindow(m_hEdtWepK2, SW_SHOW);
  681. ::ShowWindow(m_hChkOneX, SW_SHOW);
  682. }
  683. }
  684. else
  685. {
  686. if (::IsWindowVisible(m_hLblWepKInfo))
  687. {
  688. ::ShowWindow(m_hLblWepKInfo, SW_HIDE);
  689. ::ShowWindow(m_hLblWepK, SW_HIDE);
  690. ::ShowWindow(m_hEdtWepK, SW_HIDE);
  691. ::ShowWindow(m_hLblWepK2, SW_HIDE);
  692. ::ShowWindow(m_hEdtWepK2, SW_HIDE);
  693. ::ShowWindow(m_hChkOneX, SW_HIDE);
  694. }
  695. if (!::IsWindowVisible(m_hLblNoWepKInfo))
  696. {
  697. ::ShowWindow(m_hWarnIcon, SW_SHOW);
  698. ::ShowWindow(m_hLblNoWepKInfo, SW_SHOW);
  699. ::ShowWindow(m_hChkNoWepK, SW_SHOW);
  700. CheckDlgButton(IDC_WZCQCFG_CHK_NOWK,BST_UNCHECKED);
  701. }
  702. pConfig = NULL; // reset the pointer to the configuration to force disable the "Connect" button
  703. }
  704. ::EnableWindow(m_hBtnConnect, pConfig != NULL);
  705. return dwError;
  706. }
  707. //+---------------------------------------------------------------------------
  708. // class constructor
  709. CWZCQuickCfg::CWZCQuickCfg(const GUID * pGuid)
  710. {
  711. // initialize the UI handles
  712. m_hLblInfo = NULL;
  713. m_hLblNetworks = NULL;
  714. m_hLstNetworks = NULL;
  715. m_hLblWepKInfo = NULL;
  716. m_hLblWepK = NULL;
  717. m_hEdtWepK = NULL;
  718. m_hLblWepK2 = NULL;
  719. m_hEdtWepK2 = NULL;
  720. m_hChkOneX = NULL;
  721. m_hWarnIcon = NULL;
  722. m_hLblNoWepKInfo = NULL;
  723. m_hChkNoWepK = NULL;
  724. m_hBtnAdvanced = NULL;
  725. m_hBtnConnect = NULL;
  726. // initialize the Images handle
  727. m_hImgs = NULL;
  728. // initialize the WZC data
  729. m_bHaveWZCData = FALSE;
  730. ZeroMemory(&m_IntfEntry, sizeof(INTF_ENTRY));
  731. m_dwOIDFlags = 0;
  732. m_nTimer = 0;
  733. m_hCursor = NULL;
  734. if (pGuid != NULL)
  735. m_Guid = *pGuid;
  736. else
  737. ZeroMemory(&m_Guid, sizeof(GUID));
  738. // init the internal list heads
  739. m_pHdVList = NULL;
  740. m_pHdPList = NULL;
  741. // init the connection
  742. m_wszTitle = NULL;
  743. }
  744. //+---------------------------------------------------------------------------
  745. // class destructor
  746. CWZCQuickCfg::~CWZCQuickCfg()
  747. {
  748. if (m_hImgs != NULL)
  749. ImageList_Destroy(m_hImgs);
  750. // delete the internal INTF_ENTRY object
  751. WZCDeleteIntfObj(&m_IntfEntry);
  752. // delete the internal list of visible configurations
  753. // (is like filling it with NULL)
  754. FillVisibleList(NULL);
  755. // delete the internal list of preferred configurations
  756. // (is like filling it with NULL)
  757. FillPreferredList(NULL);
  758. if (m_nTimer != 0)
  759. KillTimer(m_nTimer);
  760. }
  761. //+---------------------------------------------------------------------------
  762. // INIT_DIALOG handler
  763. LRESULT
  764. CWZCQuickCfg::OnInitDialog (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  765. {
  766. DWORD dwError;
  767. DWORD dwInFlags;
  768. BOOL bEnableAll;
  769. m_bKMatTouched = TRUE;
  770. // reference the UI controls
  771. m_hLblInfo = GetDlgItem(IDC_WZCQCFG_LBL_INFO);
  772. m_hLblNetworks = GetDlgItem(IDC_WZCQCFG_LBL_NETWORKS);
  773. m_hLstNetworks = GetDlgItem(IDC_WZCQCFG_NETWORKS);
  774. m_hLblWepKInfo = GetDlgItem(IDC_WZCQCFG_LBL_WKINFO);
  775. m_hLblWepK = GetDlgItem(IDC_WZCQCFG_LBL_WEPK);
  776. m_hEdtWepK = GetDlgItem(IDC_WZCQCFG_WEPK);
  777. m_hLblWepK2 = GetDlgItem(IDC_WZCQCFG_LBL_WEPK2);
  778. m_hEdtWepK2 = GetDlgItem(IDC_WZCQCFG_WEPK2);
  779. m_hChkOneX = GetDlgItem(IDC_WZCQCFG_CHK_ONEX);
  780. m_hWarnIcon = GetDlgItem(IDC_WZCQCFG_ICO_WARN);
  781. m_hLblNoWepKInfo = GetDlgItem(IDC_WZCQCFG_LBL_NOWKINFO);
  782. m_hChkNoWepK = GetDlgItem(IDC_WZCQCFG_CHK_NOWK);
  783. m_hBtnAdvanced = GetDlgItem(IDC_WZCQCFG_ADVANCED);
  784. m_hBtnConnect = GetDlgItem(IDC_WZCQCFG_CONNECT);
  785. if (m_wszTitle != NULL)
  786. SetWindowText(m_wszTitle);
  787. if (m_hWarnIcon != NULL)
  788. ::SendMessage(m_hWarnIcon, STM_SETICON, (WPARAM)LoadIcon(NULL, IDI_WARNING), (LPARAM)0);
  789. // sets the icon images for the list view
  790. InitListView();
  791. CenterWindow();
  792. m_dwOIDFlags = 0;
  793. dwInFlags = INTF_BSSIDLIST|INTF_PREFLIST|INTF_ALL_FLAGS;
  794. dwError = GetOIDs(dwInFlags,&m_dwOIDFlags);
  795. if (m_dwOIDFlags == dwInFlags)
  796. {
  797. // if the OIDs are supported, fill in everything.
  798. if (m_IntfEntry.dwCtlFlags & INTFCTL_OIDSSUPP)
  799. {
  800. // add the list of visible configs for this adapter
  801. FillVisibleList((PWZC_802_11_CONFIG_LIST)m_IntfEntry.rdBSSIDList.pData);
  802. // add the list of preferred configs for this adapter
  803. FillPreferredList((PWZC_802_11_CONFIG_LIST)m_IntfEntry.rdStSSIDList.pData);
  804. // fill in the list view
  805. RefreshListView();
  806. m_hCursor = SetCursor(LoadCursor(NULL, IDC_ARROW));
  807. // and enable all controls
  808. bEnableAll = TRUE;
  809. }
  810. }
  811. else
  812. {
  813. // switch the cursor to "App starting"
  814. m_hCursor = SetCursor(LoadCursor(NULL, IDC_APPSTARTING));
  815. // we should fill in the UI after Tr (see the WZC state machine)
  816. // Tr is 3secs (defined in ..zeroconf\server\state.h)
  817. m_nTimer = (UINT)SetTimer(g_TimerID, RFSH_TIMEOUT);
  818. bEnableAll = FALSE;
  819. }
  820. // now that the UI is filled up set the remaining controls to their
  821. // respective states.
  822. RefreshControls();
  823. ::EnableWindow(m_hLblInfo, bEnableAll);
  824. ::EnableWindow(m_hLblNetworks, bEnableAll);
  825. ::EnableWindow(m_hLstNetworks, bEnableAll);
  826. ::EnableWindow(m_hBtnAdvanced, bEnableAll);
  827. ::SetFocus(m_hLstNetworks);
  828. bHandled = TRUE;
  829. return 0;
  830. }
  831. //+---------------------------------------------------------------------------
  832. // Help handlers
  833. extern const WCHAR c_szNetCfgHelpFile[];
  834. LRESULT
  835. CWZCQuickCfg::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  836. {
  837. ::WinHelp(m_hWnd,
  838. c_wszWzcHelpFile,
  839. HELP_CONTEXTMENU,
  840. (ULONG_PTR)g_aHelpIDs_IDD_WZCQCFG);
  841. bHandled = TRUE;
  842. return 0;
  843. }
  844. LRESULT
  845. CWZCQuickCfg::OnHelp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  846. {
  847. LPHELPINFO lphi = reinterpret_cast<LPHELPINFO>(lParam);
  848. if (HELPINFO_WINDOW == lphi->iContextType)
  849. {
  850. ::WinHelp(static_cast<HWND>(lphi->hItemHandle),
  851. c_wszWzcHelpFile,
  852. HELP_WM_HELP,
  853. (ULONG_PTR)g_aHelpIDs_IDD_WZCQCFG);
  854. bHandled = TRUE;
  855. }
  856. return 0;
  857. }
  858. //+---------------------------------------------------------------------
  859. // Refresh timer handler
  860. LRESULT
  861. CWZCQuickCfg::OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  862. {
  863. if (m_nTimer != 0)
  864. {
  865. BOOL bEnableAll;
  866. DWORD dwInFlags;
  867. // switch the cursor back to whatever it was
  868. SetCursor(LoadCursor(NULL, IDC_ARROW));
  869. KillTimer(m_nTimer);
  870. m_nTimer = 0;
  871. m_dwOIDFlags = 0;
  872. dwInFlags = INTF_BSSIDLIST|INTF_PREFLIST|INTF_ALL_FLAGS;
  873. GetOIDs(dwInFlags,&m_dwOIDFlags);
  874. bEnableAll = (m_dwOIDFlags == dwInFlags) && (m_IntfEntry.dwCtlFlags & INTFCTL_OIDSSUPP);
  875. if (bEnableAll)
  876. {
  877. // add the list of visible configs for this adapter
  878. FillVisibleList((PWZC_802_11_CONFIG_LIST)m_IntfEntry.rdBSSIDList.pData);
  879. // add the list of preferred configs for this adapter
  880. FillPreferredList((PWZC_802_11_CONFIG_LIST)m_IntfEntry.rdStSSIDList.pData);
  881. // fill in the list view
  882. RefreshListView();
  883. }
  884. // now that the UI is filled up set the remaining controls to their
  885. // respective states.
  886. RefreshControls();
  887. // enable all the UI when done refreshing
  888. ::EnableWindow(m_hLblInfo, bEnableAll);
  889. ::EnableWindow(m_hLblNetworks, bEnableAll);
  890. ::EnableWindow(m_hLstNetworks, bEnableAll);
  891. ::EnableWindow(m_hBtnAdvanced, bEnableAll);
  892. }
  893. return 0;
  894. }
  895. //+---------------------------------------------------------------------
  896. // Selection changed in the list
  897. LRESULT CWZCQuickCfg::OnItemChanged(
  898. int idCtrl,
  899. LPNMHDR pnmh,
  900. BOOL& bHandled)
  901. {
  902. bHandled = TRUE;
  903. RefreshControls();
  904. ::SetFocus(m_hLstNetworks);
  905. return 0;
  906. }
  907. //+---------------------------------------------------------------------
  908. // User clicked an entry in the list
  909. LRESULT CWZCQuickCfg::OnDbClick(int idCtrl, LPNMHDR pnmh, BOOL& bHandled)
  910. {
  911. if (idCtrl == IDC_WZCQCFG_NETWORKS && ::IsWindowEnabled(m_hBtnConnect))
  912. {
  913. OnConnect(
  914. (WORD)pnmh->code,
  915. (WORD)pnmh->idFrom,
  916. pnmh->hwndFrom,
  917. bHandled);
  918. }
  919. return 0;
  920. }
  921. //+---------------------------------------------------------------------------
  922. // OnConnect button handler
  923. LRESULT
  924. CWZCQuickCfg::OnConnect(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
  925. {
  926. DWORD dwErr = ERROR_SUCCESS;
  927. INT iSelected;
  928. CWZCConfig *pConfig = NULL;
  929. UINT nKeyLen;
  930. LPBYTE pbKMat = NULL;
  931. DWORD dwCtlFlags;
  932. BOOL bOkToDismiss = TRUE;
  933. // get the selected item from the visible list
  934. iSelected = ListView_GetNextItem(m_hLstNetworks, -1, LVNI_SELECTED);
  935. if (iSelected < 0)
  936. dwErr = ERROR_GEN_FAILURE;
  937. // iSelected should be 0 otherwise "Connect" won't be enabled
  938. if (dwErr == ERROR_SUCCESS)
  939. {
  940. LVITEM lvi = {0};
  941. lvi.mask = LVIF_PARAM;
  942. lvi.iItem = iSelected;
  943. if (ListView_GetItem(m_hLstNetworks, &lvi))
  944. {
  945. pConfig = (CWZCConfig*)lvi.lParam;
  946. if (pConfig == NULL)
  947. dwErr = ERROR_GEN_FAILURE;
  948. }
  949. else
  950. dwErr = ERROR_GEN_FAILURE;
  951. }
  952. if (dwErr == ERROR_SUCCESS)
  953. {
  954. // here we should have a valid pConfig
  955. ASSERT(pConfig);
  956. if ((m_IntfEntry.dwCtlFlags & INTFCTL_CM_MASK) != Ndis802_11AutoUnknown &&
  957. (m_IntfEntry.dwCtlFlags & INTFCTL_CM_MASK) != pConfig->m_wzcConfig.InfrastructureMode)
  958. {
  959. // User is trying to access a network type (infra or adhoc) that they're not allowed to access.
  960. // Give them an error message
  961. UINT idMessage = (pConfig->m_wzcConfig.InfrastructureMode == Ndis802_11Infrastructure) ? IDS_CANTACCESSNET_INFRA : IDS_CANTACCESSNET_ADHOC;
  962. WCHAR szSSID[MAX_PATH];
  963. ListView_GetItemText(m_hLstNetworks, iSelected, 0, szSSID, ARRAYSIZE(szSSID));
  964. DisplayFormatMessage(m_hWnd, IDS_WZCERR_CAPTION, idMessage, MB_ICONERROR | MB_OK, szSSID);
  965. // Can't connect - error
  966. dwErr = ERROR_GEN_FAILURE;
  967. // Don't close the dialog
  968. bOkToDismiss = FALSE;
  969. }
  970. }
  971. // get the WEP key only if the user touched it. m_bKMatTouched is FALSE only when the configuration
  972. // selected is already in the preferred list and that preferred config already contained a key which was
  973. // not touched a bit by the user. Otherwise it is TRUE.
  974. if (dwErr == ERROR_SUCCESS && m_bKMatTouched)
  975. {
  976. UINT nIdsErr;
  977. // check whether the WEP key has the right format
  978. dwErr = GetWepKMaterial(&nKeyLen, &pbKMat, &dwCtlFlags);
  979. if (dwErr != ERROR_SUCCESS)
  980. {
  981. ::SendMessage(m_hEdtWepK, EM_SETSEL, 0, (LPARAM)-1);
  982. ::SetFocus(m_hEdtWepK);
  983. nIdsErr = IDS_WZCERR_INVALID_WEPK;
  984. }
  985. // check whether the WEP key is confirmed correctly
  986. if (dwErr == ERROR_SUCCESS && nKeyLen > 0)
  987. {
  988. WCHAR wszWepK1[32], wszWepK2[32];
  989. UINT nKeyLen1, nKeyLen2;
  990. nKeyLen1 = ::GetWindowText(m_hEdtWepK, wszWepK1, sizeof(wszWepK1)/sizeof(WCHAR));
  991. nKeyLen2 = ::GetWindowText(m_hEdtWepK2, wszWepK2, sizeof(wszWepK2)/sizeof(WCHAR));
  992. if (nKeyLen1 != nKeyLen2 || nKeyLen1 == 0 || wcscmp(wszWepK1, wszWepK2) != 0)
  993. {
  994. nIdsErr = IDS_WZCERR_MISMATCHED_WEPK;
  995. ::SetWindowText(m_hEdtWepK2, L"");
  996. ::SetFocus(m_hEdtWepK2);
  997. dwErr = ERROR_INVALID_DATA;
  998. }
  999. }
  1000. if (dwErr != ERROR_SUCCESS)
  1001. {
  1002. WCHAR wszBuffer[MAX_PATH];
  1003. WCHAR wszCaption[MAX_PATH];
  1004. LoadString(nIdsErr == IDS_WZCERR_INVALID_WEPK ? _Module.GetResourceInstance() : WZCGetSPResModule(),
  1005. nIdsErr,
  1006. wszBuffer,
  1007. MAX_PATH);
  1008. LoadString(_Module.GetResourceInstance(),
  1009. IDS_WZCERR_CAPTION,
  1010. wszCaption,
  1011. MAX_PATH);
  1012. MessageBox(wszBuffer, wszCaption, MB_ICONERROR|MB_OK);
  1013. bOkToDismiss = FALSE;
  1014. }
  1015. }
  1016. // we do have the right WEP key here, lets copy it to the corresponding config
  1017. if (dwErr == ERROR_SUCCESS)
  1018. {
  1019. // if this configuration is not a preferred one, copy it in the preferred
  1020. // list at the top of its group
  1021. if (!(pConfig->m_dwFlags & WZC_DESCR_PREFRD))
  1022. {
  1023. // move this configuration out of the visible list
  1024. pConfig->m_pNext->m_pPrev = pConfig->m_pPrev;
  1025. pConfig->m_pPrev->m_pNext = pConfig->m_pNext;
  1026. // if the list head pointed on this config, move it to
  1027. // the next in the list
  1028. if (m_pHdVList == pConfig)
  1029. m_pHdVList = pConfig->m_pNext;
  1030. // if the list head still points on the same config,
  1031. // it means this was the only one in the list. So, null out the head.
  1032. if (m_pHdVList == pConfig)
  1033. m_pHdVList = NULL;
  1034. //next insert this visible config in the preferred list
  1035. if (m_pHdPList == NULL)
  1036. {
  1037. m_pHdPList = pConfig;
  1038. pConfig->m_pNext = pConfig;
  1039. pConfig->m_pPrev = pConfig;
  1040. }
  1041. else
  1042. {
  1043. CWZCConfig *pCrt;
  1044. // the new preferred config comes on top of the list if:
  1045. // (it is infrastructure) or (there are no infrastructures in the preferred list)
  1046. if (pConfig->m_wzcConfig.InfrastructureMode == Ndis802_11Infrastructure ||
  1047. m_pHdPList->m_wzcConfig.InfrastructureMode == Ndis802_11IBSS)
  1048. {
  1049. pCrt = m_pHdPList;
  1050. m_pHdPList = pConfig;
  1051. }
  1052. else // it definitely doesn't come the first in the list
  1053. {
  1054. for (pCrt = m_pHdPList->m_pNext; pCrt != m_pHdPList; pCrt=pCrt->m_pNext)
  1055. {
  1056. // if this is the first configuration in the matching group break the loop
  1057. if (pCrt->m_wzcConfig.InfrastructureMode == Ndis802_11IBSS)
  1058. break;
  1059. }
  1060. }
  1061. // now we have to insert pConfig in the front of pCrt;
  1062. pConfig->m_pNext = pCrt;
  1063. pConfig->m_pPrev = pCrt->m_pPrev;
  1064. pConfig->m_pNext->m_pPrev = pConfig;
  1065. pConfig->m_pPrev->m_pNext = pConfig;
  1066. }
  1067. }
  1068. // if the configuration is a preferred one, just make sure we copy over the
  1069. // privacy bit from the visible list. That one is the "real" thing
  1070. else
  1071. {
  1072. CWZCConfig *pVConfig;
  1073. if (IsConfigInList(m_pHdVList, &pConfig->m_wzcConfig, &pVConfig))
  1074. {
  1075. pConfig->m_wzcConfig.Privacy = pVConfig->m_wzcConfig.Privacy;
  1076. }
  1077. }
  1078. // now the configuration is at its right position - put in the new WEP key, if any was typed in
  1079. if (pConfig->m_wzcConfig.Privacy && m_bKMatTouched)
  1080. {
  1081. // if no key is provided, it means there is no key material.
  1082. // All we do is to reset the corresponding bit - whatever material was there
  1083. // will be preserved along with its length & format
  1084. if (!(dwCtlFlags & WZCCTL_WEPK_PRESENT))
  1085. {
  1086. pConfig->m_wzcConfig.dwCtlFlags &= ~WZCCTL_WEPK_PRESENT;
  1087. }
  1088. else
  1089. {
  1090. // now if we have a WEP key, copy over its control flags and material
  1091. pConfig->m_wzcConfig.dwCtlFlags = dwCtlFlags;
  1092. ZeroMemory(pConfig->m_wzcConfig.KeyMaterial, WZCCTL_MAX_WEPK_MATERIAL);
  1093. pConfig->m_wzcConfig.KeyLength = nKeyLen;
  1094. memcpy(pConfig->m_wzcConfig.KeyMaterial, pbKMat, nKeyLen);
  1095. }
  1096. }
  1097. }
  1098. // if all 802.11 params have been taken care of, copy now the 802.1x params (if needed)
  1099. if (dwErr == ERROR_SUCCESS &&
  1100. pConfig->m_pEapolConfig != NULL)
  1101. {
  1102. // if the network is an infrastructure one fix the 802.1X state.
  1103. // For ad hoc networks don't touch the 802.1x since it might mess the setting for a
  1104. // corresponding Infrastructure network (802.1X doesn't differentiate between SSID Infra & SSID ad hoc)
  1105. // 802.1X engine is smart enough to not act on ad hoc networks regardless its registry state!
  1106. if (pConfig->m_wzcConfig.InfrastructureMode == Ndis802_11Infrastructure)
  1107. {
  1108. // if the network requires privacy, set its state according to the "Enable 802.1X" checkbox
  1109. if (pConfig->m_wzcConfig.Privacy)
  1110. {
  1111. pConfig->m_pEapolConfig->Set8021XState(IsDlgButtonChecked(IDC_WZCQCFG_CHK_ONEX) == BST_CHECKED);
  1112. }
  1113. else // if the network doesn't require privacy - disable 802.1X!
  1114. {
  1115. // if the network is either ad hoc or infrastructure with no wep
  1116. // explicitly disable 802.1x
  1117. pConfig->m_pEapolConfig->Set8021XState(0);
  1118. }
  1119. }
  1120. }
  1121. // ok, save the preferred list back to Wireless Zero Configuration Service
  1122. if (dwErr == ERROR_SUCCESS)
  1123. {
  1124. RpcFree(m_IntfEntry.rdStSSIDList.pData);
  1125. m_IntfEntry.rdStSSIDList.dwDataLen = 0;
  1126. m_IntfEntry.rdStSSIDList.pData = NULL;
  1127. dwErr = SavePreferredConfigs(&m_IntfEntry, pConfig);
  1128. }
  1129. if (dwErr == ERROR_SUCCESS)
  1130. {
  1131. // by saving the preferred list here we're forcing a hard reset to
  1132. // the WZC State machine. This is what we want since we're here
  1133. // as a consequence of a failure and a user intervention.
  1134. dwErr = WZCSetInterface(
  1135. NULL,
  1136. INTF_PREFLIST,
  1137. &m_IntfEntry,
  1138. NULL);
  1139. if (dwErr == ERROR_PARTIAL_COPY)
  1140. {
  1141. DisplayFormatMessage(
  1142. m_hWnd,
  1143. IDS_WZCERR_CAPTION,
  1144. IDS_WZC_PARTIAL_APPLY,
  1145. MB_ICONEXCLAMATION|MB_OK);
  1146. dwErr = ERROR_SUCCESS;
  1147. }
  1148. }
  1149. // in case of any failure we might want to warn the user (another popup?)
  1150. // the question is what is the user supposed to do in such a case?
  1151. if (dwErr != ERROR_SUCCESS)
  1152. {
  1153. dwErr = ERROR_SUCCESS;
  1154. }
  1155. if(pbKMat != NULL)
  1156. delete pbKMat;
  1157. if (bOkToDismiss)
  1158. {
  1159. bHandled = TRUE;
  1160. SpEndDialog(IDOK);
  1161. }
  1162. return 0;
  1163. }
  1164. //+---------------------------------------------------------------------------
  1165. // OK button handler
  1166. LRESULT
  1167. CWZCQuickCfg::OnCancel(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
  1168. {
  1169. bHandled = TRUE;
  1170. SpEndDialog(IDCANCEL);
  1171. return 0;
  1172. }
  1173. //+---------------------------------------------------------------------------
  1174. // Advanced button handler
  1175. LRESULT
  1176. CWZCQuickCfg::OnAdvanced(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
  1177. {
  1178. bHandled = TRUE;
  1179. SpEndDialog(IDC_WZCQCFG_ADVANCED);
  1180. return 0;
  1181. }
  1182. int DisplayFormatMessage(HWND hwnd, UINT idCaption, UINT idFormatString, UINT uType, ...)
  1183. {
  1184. int iResult = IDCANCEL;
  1185. TCHAR szError[1024 + 1]; *szError = 0;
  1186. TCHAR szCaption[256 + 1];
  1187. TCHAR szFormat[1024 + 1]; *szFormat = 0;
  1188. // Load and format the error body
  1189. if (LoadString(WZCGetSPResModule(), idFormatString, szFormat, ARRAYSIZE(szFormat)))
  1190. {
  1191. va_list arguments;
  1192. va_start(arguments, uType);
  1193. if (FormatMessage(FORMAT_MESSAGE_FROM_STRING, szFormat, 0, 0, szError, ARRAYSIZE(szError), &arguments))
  1194. {
  1195. // Load the caption
  1196. if (LoadString(_Module.GetResourceInstance(), idCaption, szCaption, ARRAYSIZE(szCaption)))
  1197. {
  1198. iResult = MessageBox(hwnd, szError, szCaption, uType);
  1199. }
  1200. }
  1201. va_end(arguments);
  1202. }
  1203. return iResult;
  1204. }
  1205. //+---------------------------------------------------------------------------
  1206. // Notification handler for the wep key edit text box
  1207. LRESULT
  1208. CWZCQuickCfg::OnWepKMatCmd(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
  1209. {
  1210. if (wNotifyCode == EN_SETFOCUS)
  1211. {
  1212. if (!m_bKMatTouched)
  1213. {
  1214. // the user has just clicked for the first time on an existent key.. clear out the fields,
  1215. // standing for "The key is provided automatically"
  1216. ::SetWindowText(m_hEdtWepK, L"");
  1217. ::SetWindowText(m_hEdtWepK2, L"");
  1218. ::EnableWindow(m_hLblWepK2, FALSE); // disable confirmation label for empty key
  1219. ::EnableWindow(m_hEdtWepK2, FALSE); // disable confirmation edit for empty key
  1220. m_bKMatTouched = TRUE;
  1221. // if the 802.1X checkbox is enabled then we do have to check it here!
  1222. if (::IsWindowEnabled(m_hChkOneX))
  1223. CheckDlgButton(IDC_WZCQCFG_CHK_ONEX, BST_CHECKED);
  1224. }
  1225. }
  1226. if (wNotifyCode == EN_CHANGE)
  1227. {
  1228. UINT nKMatLen = ::GetWindowTextLength(m_hEdtWepK);
  1229. if (!::IsWindowEnabled(m_hEdtWepK2) && nKMatLen > 0)
  1230. {
  1231. // user just typed in some key material - enable the confirmation text
  1232. ::EnableWindow(m_hLblWepK2, TRUE);
  1233. ::EnableWindow(m_hEdtWepK2, TRUE);
  1234. // also uncheck 802.1x checkbox
  1235. if (::IsWindowEnabled(m_hChkOneX))
  1236. CheckDlgButton(IDC_WZCQCFG_CHK_ONEX, BST_UNCHECKED);
  1237. }
  1238. if (::IsWindowEnabled(m_hEdtWepK2) && nKMatLen == 0)
  1239. {
  1240. // user just deleted all of the key material - switching to
  1241. // "The key is provided for me automatically"
  1242. ::SetWindowText(m_hEdtWepK2, L"");
  1243. ::EnableWindow(m_hLblWepK2, FALSE);
  1244. ::EnableWindow(m_hEdtWepK2, FALSE);
  1245. // auto key suggests 802.1X
  1246. if (::IsWindowEnabled(m_hChkOneX))
  1247. CheckDlgButton(IDC_WZCQCFG_CHK_ONEX, BST_CHECKED);
  1248. }
  1249. }
  1250. return 0;
  1251. }
  1252. LRESULT
  1253. CWZCQuickCfg::OnCheckConfirmNoWep(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
  1254. {
  1255. ::EnableWindow(m_hBtnConnect, IsDlgButtonChecked(IDC_WZCQCFG_CHK_NOWK) == BST_CHECKED);
  1256. return 0;
  1257. }