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.

2077 lines
68 KiB

  1. #include "pch.h"
  2. #pragma hdrstop
  3. #include "connutil.h"
  4. #include "ncnetcon.h"
  5. #include "ncperms.h"
  6. #include "ncui.h"
  7. #include "lanui.h"
  8. #include "xpsp1res.h"
  9. #include "eapolui.h"
  10. #include "util.h"
  11. #include "lanhelp.h"
  12. #include "wzcprops.h"
  13. #include "eapolpage.h"
  14. #include "wzcpage.h"
  15. #include "wzcui.h"
  16. ////////////////////////////////////////////////////////////////////////
  17. // CWZCConfig related stuff
  18. //
  19. //+---------------------------------------------------------------------------
  20. // constructor
  21. CWZCConfig::CWZCConfig(DWORD dwFlags, PWZC_WLAN_CONFIG pwzcConfig)
  22. {
  23. m_dwFlags = dwFlags;
  24. CopyMemory(&m_wzcConfig, pwzcConfig, sizeof(WZC_WLAN_CONFIG));
  25. m_pPrev = m_pNext = this;
  26. m_nListIndex = -1;
  27. m_pEapolConfig = NULL;
  28. }
  29. //+---------------------------------------------------------------------------
  30. // destructor
  31. CWZCConfig::~CWZCConfig()
  32. {
  33. // remove the object from the list
  34. m_pPrev->m_pNext = m_pNext;
  35. m_pNext->m_pPrev = m_pPrev;
  36. if (m_pEapolConfig != NULL)
  37. {
  38. delete m_pEapolConfig;
  39. m_pEapolConfig = NULL;
  40. }
  41. }
  42. //+---------------------------------------------------------------------------
  43. // checks whether this configuration matches with the one from pwzcConfig
  44. BOOL
  45. CWZCConfig::Match(PWZC_WLAN_CONFIG pwzcConfig)
  46. {
  47. BOOL bMatch;
  48. // check whether the InfrastructureMode matches
  49. bMatch = (m_wzcConfig.InfrastructureMode == pwzcConfig->InfrastructureMode);
  50. // check whether the SSIDs are of the same length
  51. bMatch = bMatch && (m_wzcConfig.Ssid.SsidLength == pwzcConfig->Ssid.SsidLength);
  52. if (bMatch && m_wzcConfig.Ssid.SsidLength != 0)
  53. {
  54. // in case of Non empty SSIDs, check if they're the same
  55. bMatch = (memcmp(m_wzcConfig.Ssid.Ssid,
  56. pwzcConfig->Ssid.Ssid,
  57. m_wzcConfig.Ssid.SsidLength)) == 0;
  58. }
  59. return bMatch;
  60. }
  61. //+---------------------------------------------------------------------------
  62. // checks whether this configuration is weaker than the one given as parameter
  63. BOOL
  64. CWZCConfig::Weaker(PWZC_WLAN_CONFIG pwzcConfig)
  65. {
  66. BOOL bWeaker = FALSE;
  67. // a configuration is stronger if its privacy bit is set while the matching one is not set
  68. if (m_wzcConfig.Privacy != pwzcConfig->Privacy)
  69. bWeaker = pwzcConfig->Privacy;
  70. // if privacy bits are identical, a configuration is stronger if it has Open Auth mode
  71. else if (m_wzcConfig.AuthenticationMode != pwzcConfig->AuthenticationMode)
  72. bWeaker = (pwzcConfig->AuthenticationMode == Ndis802_11AuthModeOpen);
  73. return bWeaker;
  74. }
  75. DWORD
  76. CWZCConfig::AddConfigToListView(HWND hwndLV, INT nPos)
  77. {
  78. DWORD dwErr = ERROR_SUCCESS;
  79. // ugly but this is life. In order to convert the SSID to LPWSTR we need a buffer.
  80. // We know an SSID can't exceed 32 chars (see NDIS_802_11_SSID from ntddndis.h) so
  81. // make room for the null terminator and that's it. We could do mem alloc but I'm
  82. // not sure it worth the effort (at runtime).
  83. WCHAR wszSSID[33];
  84. UINT nLenSSID = 0;
  85. // convert the LPSTR (original SSID format) to LPWSTR (needed in List Ctrl)
  86. if (m_wzcConfig.Ssid.SsidLength != 0)
  87. {
  88. nLenSSID = MultiByteToWideChar(
  89. CP_ACP,
  90. 0,
  91. (LPCSTR)m_wzcConfig.Ssid.Ssid,
  92. m_wzcConfig.Ssid.SsidLength,
  93. wszSSID,
  94. celems(wszSSID));
  95. if (nLenSSID == 0)
  96. dwErr = GetLastError();
  97. }
  98. if (dwErr == ERROR_SUCCESS)
  99. {
  100. LVITEM lvi={0};
  101. UINT nImgIdx;
  102. // put the null terminator
  103. wszSSID[nLenSSID]=L'\0';
  104. // get the item's image index
  105. if (m_wzcConfig.InfrastructureMode == Ndis802_11Infrastructure)
  106. {
  107. nImgIdx = (m_dwFlags & WZC_DESCR_ACTIVE) ? WZCIMG_INFRA_ACTIVE :
  108. ((m_dwFlags & WZC_DESCR_VISIBLE) ? WZCIMG_INFRA_AIRING : WZCIMG_INFRA_SILENT);
  109. }
  110. else
  111. {
  112. nImgIdx = (m_dwFlags & WZC_DESCR_ACTIVE) ? WZCIMG_ADHOC_ACTIVE :
  113. ((m_dwFlags & WZC_DESCR_VISIBLE) ? WZCIMG_ADHOC_AIRING : WZCIMG_ADHOC_SILENT);
  114. }
  115. lvi.iItem = nPos;
  116. lvi.iSubItem = 0;
  117. lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
  118. lvi.pszText = wszSSID;
  119. lvi.iImage = nImgIdx;
  120. lvi.lParam = (LPARAM)this;
  121. // store the list position in the object
  122. m_nListIndex = ListView_InsertItem(hwndLV, &lvi);
  123. }
  124. return dwErr;
  125. }
  126. ////////////////////////////////////////////////////////////////////////
  127. // CWZeroConfPage related stuff
  128. //
  129. #define RFSH_TIMEOUT 3500
  130. UINT g_TimerID = 371;
  131. //+=================== PRIVATE MEMBERS =================================
  132. DWORD
  133. CWZeroConfPage::InitListViews()
  134. {
  135. RECT rc;
  136. LV_COLUMN lvc = {0};
  137. DWORD dwStyle;
  138. // initialize the image list styles
  139. dwStyle = ::GetWindowLong(m_hwndVLV, GWL_STYLE);
  140. ::SetWindowLong(m_hwndVLV, GWL_STYLE, (dwStyle | LVS_SHAREIMAGELISTS));
  141. dwStyle = ::GetWindowLong(m_hwndPLV, GWL_STYLE);
  142. ::SetWindowLong(m_hwndPLV, GWL_STYLE, (dwStyle | LVS_SHAREIMAGELISTS));
  143. // Create state image lists
  144. m_hImgs = ImageList_LoadBitmapAndMirror(
  145. _Module.GetResourceInstance(),
  146. MAKEINTRESOURCE(IDB_WZCSTATE),
  147. 16,
  148. 0,
  149. PALETTEINDEX(6));
  150. ListView_SetImageList(m_hwndVLV, m_hImgs, LVSIL_SMALL);
  151. ListView_SetImageList(m_hwndPLV, m_hImgs, LVSIL_SMALL);
  152. lvc.mask = LVCF_FMT | LVCF_WIDTH;
  153. lvc.fmt = LVCFMT_LEFT;
  154. ::GetClientRect(m_hwndVLV, &rc);
  155. lvc.cx = rc.right - GetSystemMetrics(SM_CXVSCROLL);
  156. //lvc.cx = rc.right;
  157. ListView_InsertColumn(m_hwndVLV, 0, &lvc);
  158. ::GetClientRect(m_hwndPLV, &rc);
  159. lvc.cx = rc.right - GetSystemMetrics(SM_CXVSCROLL);
  160. //lvc.cx = rc.right;
  161. ListView_InsertColumn(m_hwndPLV, 0, &lvc);
  162. ListView_SetExtendedListViewStyleEx(m_hwndPLV, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);
  163. ListView_SetExtendedListViewStyleEx(m_hwndVLV, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);
  164. return ERROR_SUCCESS;
  165. }
  166. //+=================== PUBLIC MEMBERS =================================
  167. //+---------------------------------------------------------------------
  168. // CWZeroConfPage constructor
  169. CWZeroConfPage::CWZeroConfPage(
  170. IUnknown* punk,
  171. INetCfg* pnc,
  172. INetConnection* pconn,
  173. const DWORD * adwHelpIDs)
  174. {
  175. m_pconn = pconn;
  176. m_pnc = pnc;
  177. m_adwHelpIDs = adwHelpIDs;
  178. // initialize the WZC data
  179. m_bHaveWZCData = FALSE;
  180. ZeroMemory(&m_IntfEntry, sizeof(INTF_ENTRY));
  181. m_dwOIDFlags = 0;
  182. m_nTimer = 0;
  183. m_hCursor = NULL;
  184. // initialize all the control's handles
  185. m_hckbEnable = NULL;
  186. m_hwndVLV = NULL;
  187. m_hwndPLV = NULL;
  188. m_hbtnCopy = NULL;
  189. m_hbtnRfsh = NULL;
  190. m_hbtnAdd = NULL;
  191. m_hbtnRem = NULL;
  192. m_hbtnUp = NULL;
  193. m_hbtnDown = NULL;
  194. m_hbtnAdvanced = NULL;
  195. m_hbtnProps = NULL;
  196. m_hlblVisNet = NULL;
  197. m_hlblPrefNet = NULL;
  198. m_hlblAvail = NULL;
  199. m_hlblPrefDesc = NULL;
  200. m_hlblAdvDesc = NULL;
  201. m_hbtnProps = NULL;
  202. m_hImgs = NULL;
  203. m_hIcoUp = NULL;
  204. m_hIcoDown = NULL;
  205. // default the infrastructure mode to Auto
  206. m_dwCtlFlags = (INTFCTL_ENABLED | INTFCTL_FALLBACK | Ndis802_11AutoUnknown);
  207. // init the internal list heads
  208. m_pHdVList = NULL;
  209. m_pHdPList = NULL;
  210. }
  211. //+---------------------------------------------------------------------
  212. CWZeroConfPage::~CWZeroConfPage()
  213. {
  214. if (m_hImgs != NULL)
  215. ImageList_Destroy(m_hImgs);
  216. if (m_hIcoUp != NULL)
  217. DeleteObject(m_hIcoUp);
  218. if (m_hIcoDown != NULL)
  219. DeleteObject(m_hIcoDown);
  220. // delete the internal INTF_ENTRY object
  221. WZCDeleteIntfObj(&m_IntfEntry);
  222. // delete the internal list of visible configurations
  223. // (is like filling it with NULL)
  224. FillVisibleList(NULL);
  225. // delete the internal list of preferred configurations
  226. // (is like filling it with NULL)
  227. FillPreferredList(NULL);
  228. if (m_nTimer != 0)
  229. KillTimer(m_nTimer);
  230. }
  231. //+---------------------------------------------------------------------
  232. // IsWireless - loads data from WZC if needed and checks whether the
  233. // interface is wireless or not.
  234. BOOL
  235. CWZeroConfPage::IsWireless()
  236. {
  237. if (!m_bHaveWZCData)
  238. {
  239. BOOL bOk;
  240. WCHAR wszGuid[c_cchGuidWithTerm];
  241. NETCON_PROPERTIES *pProps = NULL;
  242. bOk = SUCCEEDED(m_pconn->GetProperties(&pProps));
  243. if (bOk)
  244. {
  245. UINT cch;
  246. cch = ::StringFromGUID2(
  247. pProps->guidId,
  248. wszGuid,
  249. c_cchGuidWithTerm);
  250. FreeNetconProperties(pProps);
  251. bOk = (cch != 0);
  252. }
  253. if (bOk)
  254. {
  255. WZCDeleteIntfObj(&m_IntfEntry);
  256. ZeroMemory(&m_IntfEntry, sizeof(INTF_ENTRY));
  257. m_IntfEntry.wszGuid = (LPWSTR)RpcCAlloc(sizeof(WCHAR)*c_cchGuidWithTerm);
  258. bOk = (m_IntfEntry.wszGuid != NULL);
  259. }
  260. if (bOk)
  261. {
  262. DWORD dwErr;
  263. CopyMemory(m_IntfEntry.wszGuid, wszGuid, c_cchGuidWithTerm*sizeof(WCHAR));
  264. m_IntfEntry.wszDescr = NULL;
  265. m_dwOIDFlags = 0;
  266. dwErr = GetOIDs(INTF_ALL, &m_dwOIDFlags);
  267. // if getting the oids failed or we could get the OIDs but the driver/firmware
  268. // is not capable of doing the BSSID_LIST_SCAN it means we don't have enough
  269. // driver/firmware support for having Zero Configuration running. This will
  270. // result in not showing the Zero Configuration tab at all.
  271. bOk = (dwErr == ERROR_SUCCESS) && (m_IntfEntry.dwCtlFlags & INTFCTL_OIDSSUPP);
  272. if (m_IntfEntry.nAuthMode < 0)
  273. m_IntfEntry.nAuthMode = 0;
  274. if (m_IntfEntry.nInfraMode < 0)
  275. m_IntfEntry.nInfraMode = 0;
  276. if (!bOk)
  277. {
  278. WZCDeleteIntfObj(&m_IntfEntry);
  279. ZeroMemory(&m_IntfEntry, sizeof(INTF_ENTRY));
  280. }
  281. }
  282. m_bHaveWZCData = bOk;
  283. }
  284. return m_bHaveWZCData && (m_IntfEntry.ulPhysicalMediaType == NdisPhysicalMediumWirelessLan);
  285. }
  286. //+---------------------------------------------------------------------
  287. // GetOIDs - gets the OIDs for the m_IntfEntry member. It assumes the
  288. // GUID is set already
  289. DWORD
  290. CWZeroConfPage::GetOIDs(DWORD dwInFlags, LPDWORD pdwOutFlags)
  291. {
  292. DWORD rpcStatus, dwOutFlags;
  293. if (dwInFlags & INTF_DESCR)
  294. {
  295. RpcFree(m_IntfEntry.wszDescr);
  296. m_IntfEntry.wszDescr = NULL;
  297. }
  298. if (dwInFlags & INTF_PREFLIST)
  299. {
  300. RpcFree(m_IntfEntry.rdStSSIDList.pData);
  301. m_IntfEntry.rdStSSIDList.dwDataLen = 0;
  302. m_IntfEntry.rdStSSIDList.pData = NULL;
  303. }
  304. if (dwInFlags & INTF_SSID)
  305. {
  306. RpcFree(m_IntfEntry.rdSSID.pData);
  307. m_IntfEntry.rdSSID.dwDataLen = 0;
  308. m_IntfEntry.rdSSID.pData = NULL;
  309. }
  310. if (dwInFlags & INTF_BSSID)
  311. {
  312. RpcFree(m_IntfEntry.rdBSSID.pData);
  313. m_IntfEntry.rdBSSID.dwDataLen = 0;
  314. m_IntfEntry.rdBSSID.pData = NULL;
  315. }
  316. if (dwInFlags & INTF_BSSIDLIST)
  317. {
  318. RpcFree(m_IntfEntry.rdBSSIDList.pData);
  319. m_IntfEntry.rdBSSIDList.dwDataLen = 0;
  320. m_IntfEntry.rdBSSIDList.pData = NULL;
  321. }
  322. rpcStatus = WZCQueryInterface(
  323. NULL,
  324. dwInFlags,
  325. &m_IntfEntry,
  326. pdwOutFlags);
  327. return rpcStatus;
  328. }
  329. //+---------------------------------------------------------------------
  330. // HelpCenter - brings up the help topic given as parameter
  331. DWORD
  332. CWZeroConfPage::HelpCenter(LPCTSTR wszTopic)
  333. {
  334. DWORD dwErr = ERROR_SUCCESS;
  335. SHELLEXECUTEINFO shexinfo = {0};
  336. shexinfo.cbSize = sizeof (shexinfo);
  337. shexinfo.fMask = SEE_MASK_FLAG_NO_UI;
  338. shexinfo.nShow = SW_SHOWNORMAL;
  339. shexinfo.lpFile = wszTopic;
  340. shexinfo.lpVerb = _T("open");
  341. // since help center doesn't properly call AllowSetForegroundWindow when it defers
  342. // to an existing process we just give it to the next taker.
  343. AllowSetForegroundWindow(-1);
  344. ShellExecuteEx(&shexinfo);
  345. return dwErr;
  346. }
  347. //+---------------------------------------------------------------------
  348. // IsConfigInList - checks whether the pwzcConfig (WZC_WLAN_CONFIG object) is present
  349. // in the list given as the first param
  350. BOOL
  351. CWZeroConfPage::IsConfigInList(CWZCConfig *pHdList, PWZC_WLAN_CONFIG pwzcConfig, CWZCConfig **ppMatchingConfig)
  352. {
  353. BOOL bYes = FALSE;
  354. if (pHdList != NULL)
  355. {
  356. CWZCConfig *pConfig;
  357. pConfig = pHdList;
  358. do
  359. {
  360. if (pConfig->Match(pwzcConfig))
  361. {
  362. if (ppMatchingConfig != NULL)
  363. *ppMatchingConfig = pConfig;
  364. bYes = TRUE;
  365. break;
  366. }
  367. pConfig = pConfig->m_pNext;
  368. } while(pConfig != pHdList);
  369. }
  370. return bYes;
  371. }
  372. //+---------------------------------------------------------------------------
  373. // Adds the given configuration to the internal lists. The entries in the lists
  374. // are ordered on InfrastructureMode in descending order. This way the Infrastructure
  375. // entries will be on the top of the list while the adhoc entries will be on the
  376. // bottom. (we rely on the order as it is given in NDIS_802_11_NETWORK_INFRASTRUCTURE)
  377. DWORD
  378. CWZeroConfPage::AddUniqueConfig(
  379. DWORD dwOpFlags,
  380. DWORD dwEntryFlags,
  381. PWZC_WLAN_CONFIG pwzcConfig,
  382. CEapolConfig *pEapolConfig,
  383. CWZCConfig **ppNewNode)
  384. {
  385. LRESULT dwErr = ERROR_SUCCESS;
  386. CWZCConfig *pHdList;
  387. if (dwEntryFlags & WZC_DESCR_PREFRD)
  388. {
  389. pHdList = m_pHdPList;
  390. }
  391. else
  392. {
  393. UINT i;
  394. pHdList = m_pHdVList;
  395. // skip the null SSIDs from the visible list (coming from APs
  396. // not responding to broadcast SSID).
  397. for (i = pwzcConfig->Ssid.SsidLength; i > 0 && pwzcConfig->Ssid.Ssid[i-1] == 0; i--);
  398. if (i == 0)
  399. goto exit;
  400. }
  401. // if the list is currently empty, create the first entry as the head of the list
  402. if (pHdList == NULL)
  403. {
  404. pHdList = new CWZCConfig(dwEntryFlags, pwzcConfig);
  405. if (pHdList == NULL)
  406. {
  407. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  408. }
  409. else if (pEapolConfig == NULL)
  410. {
  411. pHdList->m_pEapolConfig = new CEapolConfig;
  412. if (pHdList->m_pEapolConfig == NULL)
  413. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  414. else
  415. dwErr = pHdList->m_pEapolConfig->LoadEapolConfig(m_IntfEntry.wszGuid, &(pHdList->m_wzcConfig.Ssid));
  416. if (dwErr != ERROR_SUCCESS)
  417. {
  418. delete pHdList;
  419. pHdList = NULL;
  420. }
  421. }
  422. else
  423. {
  424. pHdList->m_pEapolConfig = pEapolConfig;
  425. }
  426. // if the caller wants, return the pointer to the newly created object
  427. if (ppNewNode != NULL)
  428. *ppNewNode = pHdList;
  429. }
  430. else
  431. {
  432. // else the list already contains at least one element
  433. CWZCConfig *pCrt, *pHdGroup;
  434. // scan the list (keep in mind it is ordered descendingly on IM)
  435. pHdGroup = pCrt = pHdList;
  436. do
  437. {
  438. // check whether we entered a new group of configs (different InfrastructureMode)
  439. if (pHdGroup->m_wzcConfig.InfrastructureMode != pCrt->m_wzcConfig.InfrastructureMode)
  440. pHdGroup = pCrt;
  441. // if found an identical entry (same SSID and same InfraMode)
  442. // signal the DUPLICATE_TAG error
  443. if (pCrt->Match(pwzcConfig))
  444. {
  445. // merge the flags first
  446. pCrt->m_dwFlags |= dwEntryFlags;
  447. // If requested, copy over the new configuration.
  448. // If not explicitly requested, copy over only if the existent configuration
  449. // prooves to be weaker than the one being added.
  450. //
  451. // NOTE: the pCrt->m_pEapolConfig remains untouched since it depends exclusively
  452. // on the SSID & Infrastructure mode. These are not changing hence there is no
  453. // reason to reload the 802.1x settings.
  454. if (dwOpFlags & WZCADD_OVERWRITE ||
  455. (pHdList == m_pHdVList && pCrt->Weaker(pwzcConfig)))
  456. {
  457. memcpy(&(pCrt->m_wzcConfig), pwzcConfig, sizeof(WZC_WLAN_CONFIG));
  458. // just in case a different pEapolConfig has been provided, destroy
  459. // the original one (if any) and point to the new object
  460. if (pEapolConfig != NULL)
  461. {
  462. if (pCrt->m_pEapolConfig != NULL)
  463. delete pCrt->m_pEapolConfig;
  464. pCrt->m_pEapolConfig = pEapolConfig;
  465. }
  466. }
  467. // if the caller wants, return the pointer to the matching entry
  468. if (ppNewNode != NULL)
  469. *ppNewNode = pCrt;
  470. // signal there is already a matching config
  471. dwErr = ERROR_DUPLICATE_TAG;
  472. }
  473. pCrt = pCrt->m_pNext;
  474. } while (dwErr == ERROR_SUCCESS &&
  475. pCrt != pHdList &&
  476. pwzcConfig->InfrastructureMode <= pCrt->m_wzcConfig.InfrastructureMode);
  477. // if dwErr is unchanged, this means a new node has to be added ahead of pCrt node
  478. if (dwErr == ERROR_SUCCESS)
  479. {
  480. // create the new config and insert it ahead of this node.
  481. CWZCConfig *pNewConfig;
  482. pNewConfig = new CWZCConfig(dwEntryFlags, pwzcConfig);
  483. if (pNewConfig == NULL)
  484. {
  485. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  486. }
  487. else if (pEapolConfig == NULL)
  488. {
  489. pNewConfig->m_pEapolConfig = new CEapolConfig;
  490. if (pNewConfig->m_pEapolConfig == NULL)
  491. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  492. else
  493. dwErr = pNewConfig->m_pEapolConfig->LoadEapolConfig(m_IntfEntry.wszGuid, &(pNewConfig->m_wzcConfig.Ssid));
  494. if (dwErr != ERROR_SUCCESS)
  495. {
  496. delete pNewConfig;
  497. pNewConfig = NULL;
  498. }
  499. }
  500. else
  501. {
  502. pNewConfig->m_pEapolConfig = pEapolConfig;
  503. }
  504. if (dwErr == ERROR_SUCCESS)
  505. {
  506. INT nDiff;
  507. // if asked to insert in the head of the group, pCrt should point to this head
  508. if (dwOpFlags & WZCADD_HIGROUP)
  509. pCrt = pHdGroup;
  510. pNewConfig->m_pPrev = pCrt->m_pPrev;
  511. pNewConfig->m_pNext = pCrt;
  512. pCrt->m_pPrev->m_pNext = pNewConfig;
  513. pCrt->m_pPrev = pNewConfig;
  514. // get the difference between the Infrastructure modes for the new node and
  515. // for the current head
  516. nDiff = pNewConfig->m_wzcConfig.InfrastructureMode - pHdList->m_wzcConfig.InfrastructureMode;
  517. // if the newly entered entry has the largest "key" in
  518. // the existent sequence, or it has to be inserted in the head of its group and it is
  519. // in the first group, then the global list head moves to the new entry
  520. if (nDiff > 0 || ((dwOpFlags & WZCADD_HIGROUP) && (nDiff == 0)))
  521. pHdList = pNewConfig;
  522. }
  523. // if the caller wants, return the pointer to the newly created object
  524. if (ppNewNode != NULL)
  525. *ppNewNode = pNewConfig;
  526. }
  527. }
  528. if (dwEntryFlags & WZC_DESCR_PREFRD)
  529. {
  530. m_pHdPList = pHdList;
  531. }
  532. else
  533. {
  534. m_pHdVList = pHdList;
  535. }
  536. exit:
  537. return dwErr;
  538. }
  539. //+---------------------------------------------------------------------
  540. // FillVisibleList - fills in the configs from the WZC_802_11_CONFIG_LIST object
  541. // into the list of visible configs
  542. DWORD
  543. CWZeroConfPage::FillVisibleList(PWZC_802_11_CONFIG_LIST pwzcVList)
  544. {
  545. DWORD dwErr = ERROR_SUCCESS;
  546. UINT i;
  547. // cleanup whatever we might already have in the visible list
  548. if (m_pHdVList != NULL)
  549. {
  550. while (m_pHdVList->m_pNext != m_pHdVList)
  551. {
  552. delete m_pHdVList->m_pNext;
  553. }
  554. delete m_pHdVList;
  555. m_pHdVList = NULL;
  556. }
  557. if (pwzcVList != NULL)
  558. {
  559. for (i = 0; i < pwzcVList->NumberOfItems; i++)
  560. {
  561. dwErr = AddUniqueConfig(
  562. 0, // no op flags
  563. WZC_DESCR_VISIBLE, // this is a visible entry
  564. &(pwzcVList->Config[i]));
  565. // reset the error if config was just duplicated
  566. if (dwErr == ERROR_DUPLICATE_TAG)
  567. dwErr = ERROR_SUCCESS;
  568. }
  569. }
  570. return dwErr;
  571. }
  572. //+---------------------------------------------------------------------
  573. // FillPreferredList - fills in the configs from the WZC_802_11_CONFIG_LIST object
  574. // into the list of preferred configs
  575. DWORD
  576. CWZeroConfPage::FillPreferredList(PWZC_802_11_CONFIG_LIST pwzcPList)
  577. {
  578. DWORD dwErr = ERROR_SUCCESS;
  579. UINT i;
  580. // cleanup whatever we might already have in the preferred list
  581. if (m_pHdPList != NULL)
  582. {
  583. while (m_pHdPList ->m_pNext != m_pHdPList)
  584. {
  585. delete m_pHdPList ->m_pNext;
  586. }
  587. delete m_pHdPList;
  588. m_pHdPList = NULL;
  589. }
  590. if (pwzcPList != NULL)
  591. {
  592. for (i = 0; i < pwzcPList->NumberOfItems; i++)
  593. {
  594. PWZC_WLAN_CONFIG pwzcPConfig = &(pwzcPList->Config[i]);
  595. DWORD dwFlags = WZC_DESCR_PREFRD;
  596. // check whether this preferred is also visible and adjust dwFlags if so
  597. if (IsConfigInList(m_pHdVList, pwzcPConfig))
  598. dwFlags |= WZC_DESCR_VISIBLE;
  599. dwErr = AddUniqueConfig(
  600. WZCADD_OVERWRITE, // preferred entries cause info to be overwritten
  601. dwFlags,
  602. pwzcPConfig);
  603. // reset the error if config was just duplicated
  604. if (dwErr == ERROR_DUPLICATE_TAG)
  605. dwErr = ERROR_SUCCESS;
  606. }
  607. }
  608. return dwErr;
  609. }
  610. //+---------------------------------------------------------------------------
  611. // Fill in the current configuration settings for this adapter
  612. DWORD
  613. CWZeroConfPage::FillCurrentConfig(PINTF_ENTRY pIntf)
  614. {
  615. DWORD dwErr = ERROR_SUCCESS;
  616. WZC_WLAN_CONFIG wzcCurrent = {0};
  617. CWZCConfig *pConfig = NULL;
  618. wzcCurrent.InfrastructureMode = (NDIS_802_11_NETWORK_INFRASTRUCTURE)pIntf->nInfraMode;
  619. wzcCurrent.Ssid.SsidLength = pIntf->rdSSID.dwDataLen;
  620. CopyMemory(wzcCurrent.Ssid.Ssid, pIntf->rdSSID.pData, pIntf->rdSSID.dwDataLen);
  621. // another bit of a hack. Code in the authentication mode for this adapter in the highest
  622. // of the two reserved bits from WZC_WLAN_CONFIG
  623. //NWB_SET_AUTHMODE(&wzcCurrent, pIntf->nAuthMode);
  624. wzcCurrent.AuthenticationMode = (NDIS_802_11_AUTHENTICATION_MODE)pIntf->nAuthMode;
  625. // set the privacy field based on the adapter's WEP status.
  626. wzcCurrent.Privacy = (pIntf->nWepStatus == Ndis802_11WEPEnabled);
  627. if (IsConfigInList(m_pHdVList, &wzcCurrent, &pConfig))
  628. pConfig->m_dwFlags |= WZC_DESCR_ACTIVE;
  629. if (IsConfigInList(m_pHdPList, &wzcCurrent, &pConfig))
  630. pConfig->m_dwFlags |= WZC_DESCR_ACTIVE;
  631. return dwErr;
  632. }
  633. //+---------------------------------------------------------------------------
  634. // Display the Visible & Preferred lists into their controls
  635. DWORD
  636. CWZeroConfPage::RefreshListView(DWORD dwFlags)
  637. {
  638. DWORD dwErr = ERROR_SUCCESS;
  639. CWZCConfig *pActive = NULL;
  640. while (dwFlags != 0)
  641. {
  642. HWND hwndLV;
  643. CWZCConfig *pHdList;
  644. // the logic below allows iteration through all the lists
  645. // requested by the caller
  646. if (dwFlags & WZCOP_VLIST)
  647. {
  648. dwFlags ^= WZCOP_VLIST;
  649. hwndLV = m_hwndVLV;
  650. pHdList = m_pHdVList;
  651. }
  652. else if (dwFlags & WZCOP_PLIST)
  653. {
  654. dwFlags ^= WZCOP_PLIST;
  655. hwndLV = m_hwndPLV;
  656. pHdList = m_pHdPList;
  657. }
  658. else
  659. break;
  660. // clear first the list
  661. ListView_DeleteAllItems(hwndLV);
  662. if (pHdList != NULL)
  663. {
  664. CWZCConfig *pCrt;
  665. UINT i;
  666. pCrt = pHdList;
  667. i = 0;
  668. do
  669. {
  670. // add in the list all the entries if AutoMode or we're filling the
  671. // visible list.
  672. // Otherwise (!AutoMode & Preferred list) put in just the entries for
  673. // the corresponding infrastructure mode
  674. if ((m_dwCtlFlags & INTFCTL_CM_MASK) == Ndis802_11AutoUnknown ||
  675. hwndLV == m_hwndVLV ||
  676. (m_dwCtlFlags & INTFCTL_CM_MASK) == pCrt->m_wzcConfig.InfrastructureMode)
  677. {
  678. pCrt->m_nListIndex = i;
  679. pCrt->AddConfigToListView(hwndLV, i++);
  680. if (pCrt->m_dwFlags & WZC_DESCR_ACTIVE)
  681. pActive = pCrt;
  682. }
  683. else
  684. {
  685. pCrt->m_nListIndex = -1;
  686. }
  687. pCrt = pCrt->m_pNext;
  688. } while (pCrt != pHdList);
  689. if (pActive != NULL)
  690. {
  691. ListView_SetItemState(hwndLV, pActive->m_nListIndex, LVIS_SELECTED, LVIS_SELECTED);
  692. ListView_EnsureVisible(hwndLV, pActive->m_nListIndex, FALSE);
  693. }
  694. else if (i > 0)
  695. {
  696. ListView_SetItemState(hwndLV, 0, LVIS_SELECTED, LVIS_SELECTED);
  697. ListView_EnsureVisible(hwndLV, 0, FALSE);
  698. }
  699. }
  700. }
  701. return dwErr;
  702. }
  703. DWORD
  704. CWZeroConfPage::RefreshButtons()
  705. {
  706. CWZCConfig *pVConfig = NULL;
  707. CWZCConfig *pPConfig = NULL;
  708. LVITEM lvi = {0};
  709. INT iSelected;
  710. BOOL bEnabled;
  711. // get the selected item from the visible list
  712. iSelected = ListView_GetNextItem(m_hwndVLV, -1, LVNI_SELECTED);
  713. if (iSelected >= 0)
  714. {
  715. lvi.mask = LVIF_PARAM;
  716. lvi.iItem = iSelected;
  717. if (ListView_GetItem(m_hwndVLV, &lvi))
  718. {
  719. pVConfig = (CWZCConfig*)lvi.lParam;
  720. }
  721. }
  722. // get the selected item from the preferred list
  723. iSelected = ListView_GetNextItem(m_hwndPLV, -1, LVNI_SELECTED);
  724. if (iSelected >= 0)
  725. {
  726. lvi.mask = LVIF_PARAM;
  727. lvi.iItem = iSelected;
  728. if (ListView_GetItem(m_hwndPLV, &lvi))
  729. {
  730. pPConfig = (CWZCConfig*)lvi.lParam;
  731. }
  732. }
  733. // enable buttons only if not during refresh - otherwise disable all
  734. bEnabled = (m_dwOIDFlags & INTF_BSSIDLIST);
  735. // "Refresh" button is enabled if we do have the visible list
  736. // "Refresh" button might be enabled even if the service is disabled. User can see what is visible
  737. ::EnableWindow(m_hbtnRfsh, bEnabled);
  738. bEnabled = bEnabled && (m_dwCtlFlags & INTFCTL_ENABLED);
  739. // "Copy" button is enabled if there is any selection in the Visible list
  740. ::EnableWindow(m_hbtnCopy, bEnabled && (pVConfig != NULL) &&
  741. ((m_dwCtlFlags & INTFCTL_CM_MASK) == Ndis802_11AutoUnknown ||
  742. (m_dwCtlFlags & INTFCTL_CM_MASK) == pVConfig->m_wzcConfig.InfrastructureMode));
  743. // "Add" Button is always enabled, regardless the selections
  744. ::EnableWindow(m_hbtnAdd, bEnabled);
  745. // "Remove" button is active only if there is any selection in the Preferred list
  746. ::EnableWindow(m_hbtnRem, bEnabled && (pPConfig != NULL));
  747. // Same test for "properties" button as for "remove"
  748. ::EnableWindow(m_hbtnProps, bEnabled && (pPConfig != NULL));
  749. // "Up" button is active only for preferred entries.
  750. // It also is active only if the entry is not the first in the
  751. // list and the entry preceding it has the same InfrastructureMode
  752. bEnabled = bEnabled && (pPConfig != NULL);
  753. bEnabled = bEnabled && (pPConfig != m_pHdPList);
  754. bEnabled = bEnabled &&
  755. (pPConfig->m_wzcConfig.InfrastructureMode == pPConfig->m_pPrev->m_wzcConfig.InfrastructureMode);
  756. ::EnableWindow(m_hbtnUp, bEnabled);
  757. // "Down" button is active only for preferred or preferred entries.
  758. // It also is active only if the entry is not the last in the list
  759. // and it precedes another entry of exactly the same InfrastructureMode
  760. bEnabled = (m_dwCtlFlags & INTFCTL_ENABLED) && (m_dwOIDFlags & INTF_BSSIDLIST);
  761. bEnabled = bEnabled && (pPConfig != NULL);
  762. bEnabled = bEnabled && (pPConfig->m_pNext != m_pHdPList);
  763. bEnabled = bEnabled &&
  764. (pPConfig->m_wzcConfig.InfrastructureMode == pPConfig->m_pNext->m_wzcConfig.InfrastructureMode);
  765. ::EnableWindow(m_hbtnDown, bEnabled);
  766. return ERROR_SUCCESS;
  767. }
  768. //+---------------------------------------------------------------------
  769. DWORD
  770. CWZeroConfPage::SwapConfigsInListView(INT nIdx1, INT nIdx2, CWZCConfig * & pConfig1, CWZCConfig * & pConfig2)
  771. {
  772. DWORD dwErr = ERROR_SUCCESS;
  773. LVITEM lvi1 = {0};
  774. LVITEM lvi2 = {0};
  775. WCHAR wszSSID1[33];
  776. WCHAR wszSSID2[33];
  777. // since we take all what is known about an item this includes
  778. // images indices and selection state
  779. // get the first item
  780. lvi1.iItem = nIdx1;
  781. lvi1.mask = LVIF_TEXT | LVIF_STATE | LVIF_IMAGE | LVIF_PARAM;
  782. lvi1.stateMask = (UINT)-1;
  783. lvi1.pszText = wszSSID1;
  784. lvi1.cchTextMax = sizeof(wszSSID1)/sizeof(WCHAR);
  785. if (!ListView_GetItem(m_hwndPLV, &lvi1))
  786. {
  787. dwErr = ERROR_GEN_FAILURE;
  788. goto exit;
  789. }
  790. pConfig1 = (CWZCConfig*)lvi1.lParam;
  791. // get the second item
  792. lvi2.iItem = nIdx2;
  793. lvi2.mask = LVIF_TEXT | LVIF_STATE | LVIF_IMAGE | LVIF_PARAM;
  794. lvi2.stateMask = (UINT)-1;
  795. lvi2.pszText = wszSSID2;
  796. lvi2.cchTextMax = sizeof(wszSSID2)/sizeof(WCHAR);
  797. if (!ListView_GetItem(m_hwndPLV, &lvi2))
  798. {
  799. dwErr = ERROR_GEN_FAILURE;
  800. goto exit;
  801. }
  802. pConfig2 = (CWZCConfig*)lvi2.lParam;
  803. // swap the indices and reset the items at their new positions
  804. lvi1.iItem = nIdx2;
  805. lvi2.iItem = nIdx1;
  806. if (!ListView_SetItem(m_hwndPLV, &lvi1) ||
  807. !ListView_SetItem(m_hwndPLV, &lvi2))
  808. {
  809. dwErr = ERROR_GEN_FAILURE;
  810. goto exit;
  811. }
  812. // if everything went fine, swap the indices in the objects
  813. pConfig1->m_nListIndex = nIdx2;
  814. pConfig2->m_nListIndex = nIdx1;
  815. // make visible the selected entry
  816. ListView_EnsureVisible(m_hwndPLV, nIdx1, FALSE);
  817. exit:
  818. return dwErr;
  819. }
  820. //+---------------------------------------------------------------------
  821. DWORD
  822. CWZeroConfPage::SavePreferredConfigs(PINTF_ENTRY pIntf)
  823. {
  824. DWORD dwErr = ERROR_SUCCESS;
  825. CWZCConfig *pCrt = NULL;
  826. UINT nPrefrd = 0;
  827. if (m_pHdPList != NULL)
  828. {
  829. // count first the number of preferred entries in the list
  830. pCrt = m_pHdPList;
  831. do
  832. {
  833. nPrefrd++;
  834. pCrt = pCrt->m_pNext;
  835. } while(pCrt != m_pHdPList);
  836. }
  837. if (nPrefrd > 0)
  838. {
  839. PWZC_802_11_CONFIG_LIST pwzcPrefrdList;
  840. UINT nwzcPrefrdSize;
  841. nwzcPrefrdSize = sizeof(WZC_802_11_CONFIG_LIST)+ (nPrefrd-1)*sizeof(WZC_WLAN_CONFIG);
  842. // allocate as much memory as needed for storing all the preferred SSIDs
  843. pwzcPrefrdList = (PWZC_802_11_CONFIG_LIST)RpcCAlloc(nwzcPrefrdSize);
  844. if (pwzcPrefrdList == NULL)
  845. {
  846. dwErr = GetLastError();
  847. }
  848. else
  849. {
  850. DWORD dwLErr;
  851. pwzcPrefrdList->NumberOfItems = 0;
  852. // we have now all we need - start copying the preferred
  853. pCrt = m_pHdPList;
  854. do
  855. {
  856. PWZC_WLAN_CONFIG pPrefrdConfig;
  857. pPrefrdConfig = &(pwzcPrefrdList->Config[pwzcPrefrdList->NumberOfItems++]);
  858. CopyMemory(pPrefrdConfig, &pCrt->m_wzcConfig, sizeof(WZC_WLAN_CONFIG));
  859. // fix 802.1X state for infrastructure networks only.
  860. // don't touch the 802.1X state for ad hoc networks since this might mess the setting for a
  861. // corresponding Infrastructure network (802.1X engine doesn't make the difference between SSID infra
  862. // and SSID ad hoc) and besides, the 802.1X engine is smart enough to not act on ad hoc networks
  863. if (pCrt->m_pEapolConfig != NULL &&
  864. pPrefrdConfig->InfrastructureMode == Ndis802_11Infrastructure)
  865. {
  866. dwLErr = pCrt->m_pEapolConfig->SaveEapolConfig(m_IntfEntry.wszGuid, &(pCrt->m_wzcConfig.Ssid));
  867. if (dwErr == ERROR_SUCCESS)
  868. dwErr = dwLErr;
  869. }
  870. pCrt = pCrt->m_pNext;
  871. } while(pwzcPrefrdList->NumberOfItems < nPrefrd && pCrt != m_pHdPList);
  872. // since we don't want any "one time configuration" logic to apply here,
  873. // we need to put in the whole number of items in the "Index" field
  874. pwzcPrefrdList->Index = pwzcPrefrdList->NumberOfItems;
  875. pIntf->rdStSSIDList.dwDataLen = nwzcPrefrdSize;
  876. pIntf->rdStSSIDList.pData = (LPBYTE)pwzcPrefrdList;
  877. }
  878. }
  879. else
  880. {
  881. pIntf->rdStSSIDList.dwDataLen = 0;
  882. pIntf->rdStSSIDList.pData = NULL;
  883. }
  884. return dwErr;
  885. }
  886. //+---------------------------------------------------------------------
  887. LRESULT CWZeroConfPage::OnInitDialog(
  888. UINT uMsg,
  889. WPARAM wParam,
  890. LPARAM lParam,
  891. BOOL& bHandled)
  892. {
  893. HRESULT hr = S_OK;
  894. BOOL bEnableAll;
  895. BOOL bEnableVisible;
  896. // get the controls as the first thing to do
  897. m_hckbEnable = GetDlgItem(IDC_WZC_CHK_EnableWZC);
  898. m_hlblVisNet = GetDlgItem(IDC_WZC_LBL_VisNet);
  899. m_hlblPrefNet = GetDlgItem(IDC_WZC_LBL_PrefNet);
  900. m_hlblAvail = GetDlgItem(IDC_AVAILLABEL);
  901. m_hlblPrefDesc = GetDlgItem(IDC_PREFERLABEL);
  902. m_hlblAdvDesc = GetDlgItem(IDC_ADVANCEDLABEL);
  903. m_hwndVLV = GetDlgItem(IDC_WZC_LVW_BSSIDList);
  904. m_hwndPLV = GetDlgItem(IDC_WZC_LVW_StSSIDList);
  905. m_hbtnUp = GetDlgItem(IDC_WZC_BTN_UP);
  906. m_hbtnDown = GetDlgItem(IDC_WZC_BTN_DOWN);
  907. m_hbtnCopy = GetDlgItem(IDC_WZC_BTN_COPY);
  908. m_hbtnRfsh = GetDlgItem(IDC_WZC_BTN_RFSH);
  909. m_hbtnAdd = GetDlgItem(IDC_WZC_BTN_ADD);
  910. m_hbtnRem = GetDlgItem(IDC_WZC_BTN_REM);
  911. m_hbtnAdvanced = GetDlgItem(IDC_ADVANCED);
  912. m_hbtnProps = GetDlgItem(IDC_PROPERTIES);
  913. // Initialize the list view controls
  914. InitListViews();
  915. // enable UI only for Admins and if the interface is wireless
  916. // As a side effect, IsWireless() loads the data from the WZC
  917. bEnableAll = /*FIsUserAdmin() &&*/ IsWireless();
  918. bEnableVisible = bEnableAll;
  919. if (bEnableAll)
  920. {
  921. // set the configuration mode to the one for this interface
  922. m_dwCtlFlags = m_IntfEntry.dwCtlFlags;
  923. // if service disabled, gray out everything
  924. bEnableAll = (m_dwCtlFlags & INTFCTL_ENABLED);
  925. // set the control check boxes
  926. CheckDlgButton(IDC_WZC_CHK_EnableWZC,
  927. (m_dwCtlFlags & INTFCTL_ENABLED) ? BST_CHECKED : BST_UNCHECKED);
  928. // the UI can be filled in only when we were able to retrieve the list of
  929. // visible configs (even if it is NULL/empty). Otherwise, the UI is locked.
  930. if (m_dwOIDFlags & INTF_BSSIDLIST)
  931. {
  932. // add the list of visible configs for this adapter
  933. FillVisibleList((PWZC_802_11_CONFIG_LIST)m_IntfEntry.rdBSSIDList.pData);
  934. // add the list of preferred configs for this adapter
  935. FillPreferredList((PWZC_802_11_CONFIG_LIST)m_IntfEntry.rdStSSIDList.pData);
  936. // add to the visible list the current settings
  937. FillCurrentConfig(&m_IntfEntry);
  938. // dump the resulting lists in their List Views
  939. RefreshListView(WZCOP_VLIST|WZCOP_PLIST);
  940. // if we got a visible list, have to enable it here
  941. bEnableVisible = TRUE;
  942. }
  943. else
  944. {
  945. // mark that we don't have WZC data yet
  946. m_bHaveWZCData = FALSE;
  947. // the list of preferred configs still needs to be filled up here
  948. FillPreferredList((PWZC_802_11_CONFIG_LIST)m_IntfEntry.rdStSSIDList.pData);
  949. // switch the cursor to "App starting"
  950. m_hCursor = SetCursor(LoadCursor(NULL, IDC_APPSTARTING));
  951. // we should fill in the UI after Tr (see the WZC state machine)
  952. // Tr is 3secs (defined in ..zeroconf\server\state.h)
  953. m_nTimer = SetTimer(g_TimerID, RFSH_TIMEOUT, 0);
  954. // don't enable any control if refreshing
  955. bEnableAll = FALSE;
  956. // actually disable even the "Enable" button
  957. ::EnableWindow(m_hckbEnable, FALSE);
  958. // and also disable the visible list
  959. bEnableVisible = FALSE;
  960. }
  961. // refresh the buttons
  962. RefreshButtons();
  963. }
  964. // the controls related to the visible list should be enabled if:
  965. // - WZC can operate on this adapter
  966. // - we got a BSSIDLIST from the very first shot.
  967. // otherwise these controls should remain disabled
  968. ::EnableWindow(m_hlblVisNet, bEnableVisible);
  969. ::EnableWindow(m_hwndVLV, bEnableVisible);
  970. ::EnableWindow(m_hlblAvail, bEnableVisible);
  971. // all the remaining controls should be enabled only if:
  972. // - WZC can operate on the adapter
  973. // - WZC is enabled as a service
  974. // - we got the BSSIDLIST from the very first shot
  975. // otherwise these controls should remain disabled
  976. ::EnableWindow(m_hlblPrefNet, bEnableAll);
  977. ::EnableWindow(m_hwndPLV, bEnableAll);
  978. ::EnableWindow(m_hlblPrefDesc, bEnableAll);
  979. ::EnableWindow(m_hlblAdvDesc, bEnableAll);
  980. ::EnableWindow(m_hbtnAdvanced, bEnableAll);
  981. return LresFromHr(hr);
  982. }
  983. //+---------------------------------------------------------------------
  984. LRESULT CWZeroConfPage::OnApply(
  985. int idCtrl,
  986. LPNMHDR pnmh,
  987. BOOL& bHandled)
  988. {
  989. HRESULT hr = S_OK;
  990. WCHAR wszGuid[c_cchGuidWithTerm];
  991. NETCON_PROPERTIES *pProps = NULL;
  992. DWORD rpcStatus = ERROR_SUCCESS;
  993. BOOL bOk;
  994. hr = m_pconn->GetProperties(&pProps);
  995. bOk = SUCCEEDED(hr);
  996. if (bOk)
  997. {
  998. UINT cch;
  999. cch = ::StringFromGUID2(
  1000. pProps->guidId,
  1001. wszGuid,
  1002. c_cchGuidWithTerm);
  1003. FreeNetconProperties(pProps);
  1004. bOk = (cch != 0);
  1005. }
  1006. if (bOk)
  1007. {
  1008. UINT nText;
  1009. INTF_ENTRY Intf;
  1010. BOOL bDirty;
  1011. DWORD dwOneXErr;
  1012. ZeroMemory(&Intf, sizeof(INTF_ENTRY));
  1013. Intf.wszGuid = wszGuid;
  1014. // copy the configuration mode
  1015. Intf.dwCtlFlags = m_dwCtlFlags;
  1016. // save the preferred config list
  1017. dwOneXErr = SavePreferredConfigs(&Intf);
  1018. bDirty = (Intf.dwCtlFlags != m_IntfEntry.dwCtlFlags);
  1019. bDirty = bDirty || (Intf.rdStSSIDList.dwDataLen != m_IntfEntry.rdStSSIDList.dwDataLen);
  1020. bDirty = bDirty || ((Intf.rdStSSIDList.dwDataLen != 0) &&
  1021. memcmp(Intf.rdStSSIDList.pData, m_IntfEntry.rdStSSIDList.pData, Intf.rdStSSIDList.dwDataLen));
  1022. if (bDirty)
  1023. {
  1024. rpcStatus = WZCSetInterface(
  1025. NULL,
  1026. INTF_ALL_FLAGS | INTF_PREFLIST,
  1027. &Intf,
  1028. NULL);
  1029. }
  1030. if (dwOneXErr != ERROR_SUCCESS || rpcStatus == ERROR_PARTIAL_COPY)
  1031. {
  1032. NcMsgBox(
  1033. WZCGetSPResModule(),
  1034. m_hWnd,
  1035. IDS_LANUI_ERROR_CAPTION,
  1036. IDS_WZC_PARTIAL_APPLY,
  1037. MB_ICONEXCLAMATION|MB_OK);
  1038. rpcStatus = RPC_S_OK;
  1039. }
  1040. bOk = (rpcStatus == RPC_S_OK);
  1041. // wszGuid field is not pointing to heap memory hence it should not
  1042. // be deleted -> set the pointer to NULL to avoid this to happen
  1043. Intf.wszGuid = NULL;
  1044. WZCDeleteIntfObj(&Intf);
  1045. }
  1046. return LresFromHr(hr);
  1047. }
  1048. //+---------------------------------------------------------------------
  1049. extern const WCHAR c_szNetCfgHelpFile[];
  1050. LRESULT
  1051. CWZeroConfPage::OnContextMenu(
  1052. UINT uMsg,
  1053. WPARAM wParam,
  1054. LPARAM lParam,
  1055. BOOL& fHandled)
  1056. {
  1057. if (m_adwHelpIDs != NULL)
  1058. {
  1059. ::WinHelp(m_hWnd,
  1060. c_szNetCfgHelpFile,
  1061. HELP_CONTEXTMENU,
  1062. (ULONG_PTR)m_adwHelpIDs);
  1063. }
  1064. return 0;
  1065. }
  1066. LRESULT
  1067. CWZeroConfPage::OnHelp(
  1068. UINT uMsg,
  1069. WPARAM wParam,
  1070. LPARAM lParam,
  1071. BOOL& fHandled)
  1072. {
  1073. LPHELPINFO lphi = reinterpret_cast<LPHELPINFO>(lParam);
  1074. if ((m_adwHelpIDs != NULL) && (HELPINFO_WINDOW == lphi->iContextType))
  1075. {
  1076. ::WinHelp(static_cast<HWND>(lphi->hItemHandle),
  1077. c_szNetCfgHelpFile,
  1078. HELP_WM_HELP,
  1079. (ULONG_PTR)m_adwHelpIDs);
  1080. }
  1081. return 0;
  1082. }
  1083. //+---------------------------------------------------------------------
  1084. LRESULT
  1085. CWZeroConfPage::OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  1086. {
  1087. if (m_nTimer != 0)
  1088. {
  1089. BOOL bEnableAll;
  1090. // switch the cursor back to whatever it was
  1091. SetCursor(LoadCursor(NULL, IDC_ARROW));
  1092. KillTimer(m_nTimer);
  1093. m_nTimer = 0;
  1094. // attempt to requery the service for all the OIDs. Regardless we could or not
  1095. // obtain the OIDs, fill the UI with what we have.
  1096. if (GetOIDs(INTF_ALL_OIDS, &m_dwOIDFlags) == ERROR_SUCCESS)
  1097. {
  1098. CWZCConfig *pPConfig = NULL;
  1099. // add the list of visible configs for this adapter
  1100. FillVisibleList((PWZC_802_11_CONFIG_LIST)m_IntfEntry.rdBSSIDList.pData);
  1101. // Update the visibility flag for each of the preferred configs
  1102. pPConfig = m_pHdPList;
  1103. if (pPConfig != NULL)
  1104. {
  1105. do
  1106. {
  1107. // by default, none of the preferred entries is marked as "active".
  1108. // This will be taken care of later, when calling FillCurrentConfig().
  1109. pPConfig->m_dwFlags &= ~WZC_DESCR_ACTIVE;
  1110. if (IsConfigInList(m_pHdVList, &pPConfig->m_wzcConfig))
  1111. pPConfig->m_dwFlags |= WZC_DESCR_VISIBLE;
  1112. else
  1113. pPConfig->m_dwFlags &= ~WZC_DESCR_VISIBLE;
  1114. pPConfig = pPConfig->m_pNext;
  1115. } while(pPConfig != m_pHdPList);
  1116. }
  1117. // add the current settings to the visible list
  1118. FillCurrentConfig(&m_IntfEntry);
  1119. }
  1120. // even in case of failure, at this point we should live with whatever
  1121. // visible list (if any) we have. Hence, flag BSSIDLIST as "visible"
  1122. m_dwOIDFlags |= INTF_BSSIDLIST;
  1123. // dump the resulting lists in their List Views
  1124. RefreshListView(WZCOP_VLIST|WZCOP_PLIST);
  1125. // refresh the buttons
  1126. RefreshButtons();
  1127. // if service disabled, gray out all the other controls
  1128. bEnableAll = (m_dwCtlFlags & INTFCTL_ENABLED);
  1129. // enable all the UI when done refreshing
  1130. ::EnableWindow(m_hckbEnable, TRUE);
  1131. // enable everything related to the visible list
  1132. ::EnableWindow(m_hlblVisNet, TRUE);
  1133. ::EnableWindow(m_hwndVLV, TRUE);
  1134. ::EnableWindow(m_hlblAvail, TRUE);
  1135. ::EnableWindow(m_hlblPrefNet, bEnableAll);
  1136. ::EnableWindow(m_hwndPLV, bEnableAll);
  1137. ::EnableWindow(m_hlblPrefDesc, bEnableAll);
  1138. ::EnableWindow(m_hlblAdvDesc, bEnableAll);
  1139. ::EnableWindow(m_hbtnAdvanced, bEnableAll);
  1140. }
  1141. return 0;
  1142. }
  1143. //+---------------------------------------------------------------------
  1144. LRESULT CWZeroConfPage::OnDblClick(
  1145. int idCtrl,
  1146. LPNMHDR pnmh,
  1147. BOOL& bHandled)
  1148. {
  1149. HWND hwndLV;
  1150. HRESULT hr = S_OK;
  1151. LPNMLISTVIEW pnmhLv = (LPNMLISTVIEW) pnmh;
  1152. if (idCtrl == IDC_WZC_LVW_BSSIDList)
  1153. {
  1154. hwndLV = m_hwndVLV;
  1155. }
  1156. else
  1157. {
  1158. hwndLV = m_hwndPLV;
  1159. }
  1160. bHandled = FALSE;
  1161. if (pnmhLv->iItem != -1)
  1162. {
  1163. ListView_SetItemState(hwndLV, pnmhLv->iItem, LVIS_SELECTED, LVIS_SELECTED);
  1164. hr = _DoProperties(hwndLV, pnmhLv->iItem);
  1165. bHandled = TRUE;
  1166. }
  1167. return LresFromHr(hr);
  1168. }
  1169. //+---------------------------------------------------------------------
  1170. LRESULT CWZeroConfPage::OnClick(
  1171. int idCtrl,
  1172. LPNMHDR pnmh,
  1173. BOOL& bHandled)
  1174. {
  1175. HRESULT hr = S_OK;
  1176. LPNMLISTVIEW pnmhLv = (LPNMLISTVIEW) pnmh;
  1177. if (idCtrl == IDC_LEARNABOUT)
  1178. {
  1179. HelpCenter(SzLoadString(_Module.GetResourceInstance(), IDS_WZC_LEARNCMD));
  1180. }
  1181. return LresFromHr(hr);
  1182. }
  1183. //+---------------------------------------------------------------------
  1184. LRESULT CWZeroConfPage::OnReturn(
  1185. int idCtrl,
  1186. LPNMHDR pnmh,
  1187. BOOL& bHandled)
  1188. {
  1189. HRESULT hr = S_OK;
  1190. LPNMLISTVIEW pnmhLv = (LPNMLISTVIEW) pnmh;
  1191. if (idCtrl == IDC_LEARNABOUT)
  1192. {
  1193. HelpCenter(SzLoadString(_Module.GetResourceInstance(), IDS_WZC_LEARNCMD));
  1194. }
  1195. return LresFromHr(hr);
  1196. }
  1197. //+---------------------------------------------------------------------
  1198. LRESULT CWZeroConfPage::OnItemChanged(
  1199. int idCtrl,
  1200. LPNMHDR pnmh,
  1201. BOOL& bHandled)
  1202. {
  1203. HRESULT hr = S_OK;
  1204. RefreshButtons();
  1205. bHandled = TRUE;
  1206. return LresFromHr(hr);
  1207. }
  1208. //+---------------------------------------------------------------------
  1209. LRESULT CWZeroConfPage::OnChkWZCEnable(
  1210. WORD wNotifyCode,
  1211. WORD wID,
  1212. HWND hWndCtl,
  1213. BOOL& bHandled)
  1214. {
  1215. HRESULT hr = S_OK;
  1216. BOOL bEnable;
  1217. bEnable = (IsDlgButtonChecked(IDC_WZC_CHK_EnableWZC) == BST_CHECKED);
  1218. m_dwCtlFlags &= ~INTFCTL_ENABLED;
  1219. if (bEnable)
  1220. m_dwCtlFlags |= INTFCTL_ENABLED;
  1221. // enable everything related to the visible list
  1222. ::EnableWindow(m_hlblVisNet, TRUE);
  1223. ::EnableWindow(m_hwndVLV, TRUE);
  1224. ::EnableWindow(m_hlblAvail, TRUE);
  1225. ::EnableWindow(m_hlblPrefNet, bEnable);
  1226. ::EnableWindow(m_hwndPLV, bEnable);
  1227. ::EnableWindow(m_hlblPrefDesc, bEnable);
  1228. ::EnableWindow(m_hlblAdvDesc, bEnable);
  1229. ::EnableWindow(m_hbtnAdvanced, bEnable);
  1230. RefreshButtons();
  1231. return LresFromHr(hr);
  1232. }
  1233. //+---------------------------------------------------------------------
  1234. LRESULT
  1235. CWZeroConfPage::OnPushAddOrCopy(
  1236. WORD wNotifyCode,
  1237. WORD wID,
  1238. HWND hWndCtl,
  1239. BOOL& bHandled)
  1240. {
  1241. HRESULT hr = S_OK;
  1242. LVITEM lvi = {0};
  1243. BOOL bOk;
  1244. INT iSelected;
  1245. CWZCConfig *pConfig = NULL;
  1246. CWZCConfigPage PpWzcProps(WZCDLG_PROPS_RWALL|WZCDLG_PROPS_DEFOK|WZCDLG_PROPS_ONEX_CHECK);
  1247. CEapolConfig *pEapolConfig = NULL;
  1248. // in case of success, the object allocated here is linked to the
  1249. // newly created or updated CWZCConfig and will be deleted when
  1250. // this latter one gets destroyed.
  1251. pEapolConfig = new CEapolConfig;
  1252. bOk = (pEapolConfig != NULL);
  1253. if (bOk)
  1254. {
  1255. if (hWndCtl == m_hbtnCopy)
  1256. {
  1257. // get the selected item from the Visible list
  1258. iSelected = ListView_GetNextItem(m_hwndVLV, -1, LVNI_SELECTED);
  1259. bOk = (iSelected != -1);
  1260. // there is a valid selection to copy (it couldn't be otherwise since
  1261. // "Copy" shouldn't be enabled if there is no such selection)
  1262. // Find the CWZCConfig for the selection
  1263. if (bOk)
  1264. {
  1265. LVITEM lvi = {0};
  1266. lvi.mask = LVIF_PARAM;
  1267. lvi.iItem = iSelected;
  1268. if (ListView_GetItem(m_hwndVLV, &lvi))
  1269. {
  1270. pConfig = (CWZCConfig*)lvi.lParam;
  1271. if (pConfig != NULL)
  1272. {
  1273. UINT nVisPrivacy = pConfig->m_wzcConfig.Privacy;
  1274. // check whether this config is in the preferred list. If IsConfigInList
  1275. // succeeds, it returns in pConfig the pointer to the preferred config - this is
  1276. // what we need to show the properties for.
  1277. // If this network is not in the preferred list, pConfig will not be modified hence
  1278. // the properties coming from the AP will be loaded. Again what we want.
  1279. IsConfigInList(m_pHdPList, &pConfig->m_wzcConfig, &pConfig);
  1280. // copy in the newly created 802.1x object what we have for this configuration
  1281. pEapolConfig->CopyEapolConfig(pConfig->m_pEapolConfig);
  1282. // upload the 802.11 settings into the property page
  1283. PpWzcProps.UploadWzcConfig(pConfig);
  1284. // However, even if we're showing up preferred, settings, the Privacy bit from the AP
  1285. // (the visible configuration) takes precedence.
  1286. if (nVisPrivacy)
  1287. {
  1288. PpWzcProps.m_wzcConfig.Privacy = nVisPrivacy;
  1289. }
  1290. }
  1291. }
  1292. bOk = (pConfig != NULL);
  1293. }
  1294. }
  1295. else
  1296. {
  1297. // this is a brand new network, we don't know even the SSID,
  1298. // let 802.1x start with its defaults then.
  1299. pEapolConfig->LoadEapolConfig(m_IntfEntry.wszGuid, NULL);
  1300. bOk = TRUE;
  1301. }
  1302. }
  1303. // we have the CWZCConfig object, prompt the user with it allowing
  1304. // him to change whatever params he want
  1305. if (bOk)
  1306. {
  1307. CWLANAuthenticationPage PpAuthProps(NULL, m_pnc, m_pconn, g_aHelpIDs_IDD_SECURITY);
  1308. // if the mode is not "auto", freeze it in the dialog
  1309. if ((m_dwCtlFlags & INTFCTL_CM_MASK) != Ndis802_11AutoUnknown)
  1310. {
  1311. PpWzcProps.m_wzcConfig.InfrastructureMode = (NDIS_802_11_NETWORK_INFRASTRUCTURE)(m_dwCtlFlags & INTFCTL_CM_MASK);
  1312. PpWzcProps.SetFlags(WZCDLG_PROPS_RWINFR, 0);
  1313. }
  1314. PpAuthProps.UploadEapolConfig(pEapolConfig, &PpWzcProps);
  1315. PpWzcProps.UploadEapolConfig(pEapolConfig);
  1316. bOk = (_DoModalPropSheet(&PpWzcProps, &PpAuthProps) > 0);
  1317. }
  1318. // the dialog was ack-ed, the dialog contains the WZC_WLAN_CONFIG to be added
  1319. // go ahead and create the list entry for it.
  1320. if (bOk)
  1321. {
  1322. DWORD dwFlags = WZC_DESCR_PREFRD;
  1323. DWORD dwErr;
  1324. // it could happen that the newly added config is visible
  1325. if (IsConfigInList(m_pHdVList, &PpWzcProps.m_wzcConfig))
  1326. dwFlags |= WZC_DESCR_VISIBLE;
  1327. // we have now a WZC_WLAN_CONFIG structure in the dialog
  1328. // we have to add it to the list view and to the internal list as
  1329. // a preferred one. This call doesn't fix the list index
  1330. // and doesn't insert the new config in the ListView.
  1331. dwErr = AddUniqueConfig(
  1332. WZCADD_OVERWRITE | WZCADD_HIGROUP,
  1333. dwFlags,
  1334. &PpWzcProps.m_wzcConfig,
  1335. pEapolConfig, // 802.1x settings need to be updated no matter what
  1336. &pConfig);
  1337. // if the addition returns success, it means this is a brand new
  1338. // entry! Then fix the indices and add the entry to the list view
  1339. if (dwErr == ERROR_SUCCESS)
  1340. {
  1341. CWZCConfig *pCrt = pConfig;
  1342. INT nCrtIdx = 0;
  1343. // if everything went up fine, we need to fix the indices and
  1344. // create/add the list view item
  1345. // find the first index above the newly entry item.
  1346. // pConfig already has the m_nListIndex set to -1;
  1347. if (pConfig == m_pHdPList)
  1348. {
  1349. nCrtIdx = 0;
  1350. }
  1351. else
  1352. {
  1353. do
  1354. {
  1355. pCrt = pCrt->m_pPrev;
  1356. if (pCrt->m_nListIndex != -1)
  1357. {
  1358. nCrtIdx = pCrt->m_nListIndex+1;
  1359. break;
  1360. }
  1361. } while(pCrt != m_pHdPList);
  1362. }
  1363. pConfig->m_nListIndex = nCrtIdx++;
  1364. pCrt = pConfig->m_pNext;
  1365. while(pCrt != m_pHdPList)
  1366. {
  1367. if (pCrt->m_nListIndex != -1)
  1368. pCrt->m_nListIndex = nCrtIdx++;
  1369. pCrt = pCrt->m_pNext;
  1370. }
  1371. pConfig->AddConfigToListView(m_hwndPLV, pConfig->m_nListIndex);
  1372. }
  1373. bOk = (dwErr == ERROR_SUCCESS) || (dwErr == ERROR_DUPLICATE_TAG);
  1374. }
  1375. if (bOk)
  1376. {
  1377. ListView_SetItemState(m_hwndPLV, pConfig->m_nListIndex, LVIS_SELECTED, LVIS_SELECTED);
  1378. ListView_EnsureVisible(m_hwndPLV, pConfig->m_nListIndex, FALSE);
  1379. RefreshButtons();
  1380. }
  1381. if (!bOk && pEapolConfig != NULL)
  1382. delete pEapolConfig;
  1383. bHandled = bOk;
  1384. return LresFromHr(hr);
  1385. }
  1386. //+---------------------------------------------------------------------
  1387. LRESULT
  1388. CWZeroConfPage::OnPushRefresh(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
  1389. {
  1390. HRESULT hr = S_OK;
  1391. DWORD rpcStatus;
  1392. DWORD dwOutFlags;
  1393. // since we are here, it means we have already got the info for this adapter, hence
  1394. // we already have its GUID in the m_IntfEntry member.
  1395. // All we have to do is to ask WZCSVC for a visible list rescan
  1396. rpcStatus = WZCRefreshInterface(
  1397. NULL,
  1398. INTF_LIST_SCAN,
  1399. &m_IntfEntry,
  1400. &dwOutFlags);
  1401. // if everything went fine, just disable the "Refresh" button and set
  1402. // the timer for the future query
  1403. if (rpcStatus == RPC_S_OK &&
  1404. dwOutFlags & INTF_LIST_SCAN)
  1405. {
  1406. ::EnableWindow(m_hbtnRfsh, FALSE);
  1407. // mark that we don't have WZC data yet
  1408. m_bHaveWZCData = FALSE;
  1409. // switch the cursor to the "app starting"
  1410. m_hCursor = SetCursor(LoadCursor(NULL, IDC_APPSTARTING));
  1411. m_nTimer = SetTimer(g_TimerID, RFSH_TIMEOUT, 0);
  1412. // indicate we don't have the visible list in order
  1413. // to disable all the buttons
  1414. m_dwOIDFlags &= ~INTF_BSSIDLIST;
  1415. RefreshButtons();
  1416. // disable all the UI while refreshing
  1417. ::EnableWindow(m_hckbEnable, FALSE);
  1418. ::EnableWindow(m_hwndVLV, FALSE);
  1419. ::EnableWindow(m_hwndPLV, FALSE);
  1420. ::EnableWindow(m_hlblVisNet, FALSE);
  1421. ::EnableWindow(m_hlblPrefNet, FALSE);
  1422. ::EnableWindow(m_hlblAvail, FALSE);
  1423. ::EnableWindow(m_hlblPrefDesc, FALSE);
  1424. ::EnableWindow(m_hlblAdvDesc, FALSE);
  1425. ::EnableWindow(m_hbtnAdvanced, FALSE);
  1426. }
  1427. return LresFromHr(hr);
  1428. }
  1429. //+---------------------------------------------------------------------
  1430. LRESULT
  1431. CWZeroConfPage::OnPushUpOrDown(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
  1432. {
  1433. HRESULT hr = S_OK;
  1434. INT iSelected;
  1435. INT iOther;
  1436. CWZCConfig *pConfig, *pOther;
  1437. // no matter what, get the selected item from the list
  1438. iSelected = ListView_GetNextItem(m_hwndPLV, -1, LVNI_SELECTED);
  1439. // since we are here it means there is another entry up/down side
  1440. // with which the selected one needs to change place
  1441. // first delete the entry from its current position in the list
  1442. iOther = (hWndCtl == m_hbtnDown)? iSelected+1 : iSelected-1;
  1443. // swap first the visual elements (entries in the List View)
  1444. // This returns the CWZCConfig pointers with their indices already
  1445. // adjusted
  1446. if (SwapConfigsInListView(iSelected, iOther, pConfig, pOther) == ERROR_SUCCESS)
  1447. {
  1448. // if need to go down one hop..
  1449. if (hWndCtl == m_hbtnDown)
  1450. {
  1451. // swap positions in the list
  1452. // remove the entry from its current position
  1453. pOther->m_pPrev = pConfig->m_pPrev;
  1454. pConfig->m_pPrev->m_pNext = pOther;
  1455. // and put it back down to its successor
  1456. pConfig->m_pPrev = pOther;
  1457. pConfig->m_pNext = pOther->m_pNext;
  1458. pOther->m_pNext->m_pPrev = pConfig;
  1459. pOther->m_pNext = pConfig;
  1460. // fix the m_pHdPList if needed;
  1461. if (m_pHdPList == pConfig)
  1462. m_pHdPList = pOther;
  1463. }
  1464. // if need to go up one hop..
  1465. else
  1466. {
  1467. // swap positions in the list
  1468. // remove the entry from its current position
  1469. pOther->m_pNext = pConfig->m_pNext;
  1470. pConfig->m_pNext->m_pPrev = pOther;
  1471. // and put it back in front of its predecessor
  1472. pConfig->m_pNext = pOther;
  1473. pConfig->m_pPrev = pOther->m_pPrev;
  1474. pOther->m_pPrev->m_pNext = pConfig;
  1475. pOther->m_pPrev = pConfig;
  1476. // fix the m_pHdPList if needed
  1477. if (m_pHdPList == pOther)
  1478. m_pHdPList = pConfig;
  1479. }
  1480. }
  1481. // need to refresh the buttons such that the "Up"/"Down" buttons
  1482. // get updated for the new position of the selection
  1483. RefreshButtons();
  1484. bHandled = TRUE;
  1485. return LresFromHr(hr);
  1486. }
  1487. //+---------------------------------------------------------------------
  1488. LRESULT CWZeroConfPage::OnPushRemove(
  1489. WORD wNotifyCode,
  1490. WORD wID,
  1491. HWND hWndCtl,
  1492. BOOL& bHandled)
  1493. {
  1494. HRESULT hr = S_OK;
  1495. LVITEM lvi = {0};
  1496. CWZCConfig *pConfig, *pCrt;
  1497. INT iSelected;
  1498. iSelected = ListView_GetNextItem(m_hwndPLV, -1, LVNI_SELECTED);
  1499. lvi.mask = LVIF_PARAM;
  1500. lvi.iItem = iSelected;
  1501. if (!ListView_GetItem(m_hwndPLV, &lvi))
  1502. goto exit;
  1503. // get the CWZCConfig from it
  1504. pConfig = (CWZCConfig*)lvi.lParam;
  1505. // adjust the list indices for all the entries that follow
  1506. // the selected one
  1507. for (pCrt = pConfig->m_pNext; pCrt != m_pHdPList; pCrt = pCrt->m_pNext)
  1508. {
  1509. if (pCrt->m_nListIndex != -1)
  1510. pCrt->m_nListIndex--;
  1511. }
  1512. // determine first which entry gets the selection
  1513. // the selection moves down if there is any other entry down, or up otherwise
  1514. pCrt = (pConfig->m_pNext == m_pHdPList) ? pConfig->m_pPrev : pConfig->m_pNext;
  1515. // if after that the selection still points to the same object, it means
  1516. // it is the only one in the list so the head and selection are set to NULL
  1517. if (pCrt == pConfig)
  1518. {
  1519. m_pHdPList = pCrt = NULL;
  1520. }
  1521. // otherwise, if it is the head of the list which gets removed, the head
  1522. // moves down to the next entry
  1523. else if (m_pHdPList == pConfig)
  1524. {
  1525. m_pHdPList = pConfig->m_pNext;
  1526. }
  1527. // delete now the selected entry from the list
  1528. ListView_DeleteItem(m_hwndPLV, iSelected);
  1529. // and destroy its object (desctructor takes care of list removal)
  1530. delete pConfig;
  1531. // set the new selection if any
  1532. if (pCrt != NULL)
  1533. {
  1534. ListView_SetItemState(m_hwndPLV, pCrt->m_nListIndex, LVIS_SELECTED, LVIS_SELECTED);
  1535. ListView_EnsureVisible(m_hwndPLV, pCrt->m_nListIndex, FALSE);
  1536. }
  1537. // refresh the buttons' state
  1538. RefreshButtons();
  1539. bHandled = TRUE;
  1540. exit:
  1541. return LresFromHr(hr);
  1542. }
  1543. LRESULT CWZeroConfPage::OnPushAdvanced(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
  1544. {
  1545. bHandled = TRUE;
  1546. DialogBoxParam(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDD_LAN_WZC_ADVANCED), m_hWnd, AdvancedDialogProc, (LPARAM) this);
  1547. RefreshListView(WZCOP_VLIST|WZCOP_PLIST);
  1548. RefreshButtons();
  1549. return 0;
  1550. }
  1551. LRESULT CWZeroConfPage::OnPushProperties(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
  1552. {
  1553. bHandled = TRUE;
  1554. int iItem = ListView_GetNextItem(m_hwndPLV, -1, LVNI_SELECTED);
  1555. if (-1 != iItem)
  1556. {
  1557. _DoProperties(m_hwndPLV, iItem);
  1558. }
  1559. return 0;
  1560. }
  1561. HRESULT CWZeroConfPage::_DoProperties(HWND hwndLV, int iItem)
  1562. {
  1563. LV_ITEM lvi = {0};
  1564. // we need to get to the corresponding config object
  1565. lvi.mask = LVIF_PARAM;
  1566. lvi.iItem = iItem;
  1567. if (ListView_GetItem(hwndLV, &lvi) && lvi.lParam != NULL)
  1568. {
  1569. CWZCConfig *pConfig = (CWZCConfig*)lvi.lParam;
  1570. if (hwndLV == m_hwndVLV)
  1571. {
  1572. CWZCConfigProps dlgProps;
  1573. dlgProps.UploadWzcConfig(pConfig);
  1574. // bring up the info dialog (it only has "Close" so the user can't
  1575. // change anything there, hence there is no reason to do anything
  1576. // more here.
  1577. dlgProps.DoModal(m_hWnd);
  1578. }
  1579. else
  1580. {
  1581. BOOL bOk = FALSE;
  1582. CWZCConfigPage PpWzcProps(WZCDLG_PROPS_RWAUTH|WZCDLG_PROPS_RWWEP);
  1583. CEapolConfig *pEapolConfig;
  1584. PpWzcProps.UploadWzcConfig(pConfig);
  1585. pEapolConfig = new CEapolConfig;
  1586. bOk = (pEapolConfig != NULL);
  1587. if (bOk)
  1588. {
  1589. CWLANAuthenticationPage PpAuthProps(NULL, m_pnc, m_pconn, g_aHelpIDs_IDD_SECURITY);
  1590. pEapolConfig->CopyEapolConfig(pConfig->m_pEapolConfig);
  1591. PpAuthProps.UploadEapolConfig(pEapolConfig, &PpWzcProps);
  1592. PpWzcProps.UploadEapolConfig(pEapolConfig);
  1593. bOk = (_DoModalPropSheet(&PpWzcProps, &PpAuthProps, TRUE) > 0);
  1594. }
  1595. // bring up the modal property sheet
  1596. if (bOk)
  1597. {
  1598. // copy over the info from the dialog. SSID & Infra Mode should have been locked
  1599. // so the position of this entry in the internal and UI list has not changed
  1600. memcpy(&pConfig->m_wzcConfig, &PpWzcProps.m_wzcConfig, sizeof(WZC_WLAN_CONFIG));
  1601. delete pConfig->m_pEapolConfig;
  1602. pConfig->m_pEapolConfig = pEapolConfig;
  1603. }
  1604. if (!bOk && pEapolConfig != NULL)
  1605. delete pEapolConfig;
  1606. }
  1607. }
  1608. return S_OK;
  1609. }
  1610. INT CWZeroConfPage::_DoModalPropSheet(CWZCConfigPage *pPpWzcPage, CWLANAuthenticationPage *pPpAuthPage, BOOL bCustomizeTitle)
  1611. {
  1612. INT retCode = 0;
  1613. PROPSHEETHEADER psh;
  1614. HPROPSHEETPAGE hpsp[2];
  1615. INT npsp = 0;
  1616. LPWSTR pwszCaption = NULL;
  1617. WCHAR wszBuffer[64];
  1618. hpsp[0] = pPpWzcPage->CreatePage(
  1619. IDC_WZC_DLG_PROPS,
  1620. 0,
  1621. NULL,
  1622. NULL,
  1623. NULL,
  1624. WZCGetSPResModule());
  1625. npsp++;
  1626. if (hpsp[0] == NULL)
  1627. return -1;
  1628. if(pPpAuthPage != NULL)
  1629. {
  1630. hpsp[1] = pPpAuthPage->CreatePage(
  1631. IDD_LAN_SECURITY,
  1632. 0,
  1633. NULL,
  1634. NULL,
  1635. NULL,
  1636. WZCGetSPResModule());
  1637. npsp++;
  1638. if (hpsp[1] == NULL)
  1639. return -1;
  1640. }
  1641. ZeroMemory (&psh, sizeof(psh));
  1642. psh.dwSize = sizeof( PROPSHEETHEADER );
  1643. psh.dwFlags = PSH_NOAPPLYNOW ;
  1644. psh.hwndParent = m_hWnd;
  1645. psh.hInstance = WZCGetSPResModule();
  1646. psh.nPages = npsp;
  1647. psh.phpage = hpsp;
  1648. psh.nStartPage = 0;
  1649. // just double check the SsidLength is no larger than the allowed size!
  1650. if (bCustomizeTitle && pPpWzcPage->m_wzcConfig.Ssid.SsidLength <= 32)
  1651. {
  1652. // SzLoadString returns either the right string or " " (space)
  1653. //LPCWSTR pwszSuffix = SzLoadString(WZCGetSPResModule(), IDS_WZC_DLG_CAP_SUFFIX);
  1654. LPCWSTR pwszSuffix = wszBuffer;
  1655. UINT nLen = 0;
  1656. LoadString(WZCGetSPResModule(), IDS_WZC_DLG_CAP_SUFFIX, wszBuffer, sizeof(wszBuffer));
  1657. // alocate space enough for the SSID (32 ACP chars can't result in more than 32 WCHARs)
  1658. // the space between the SSID and the suffix, the suffix itself and the null-terminator
  1659. pwszCaption = new WCHAR [wcslen(pwszSuffix) + pPpWzcPage->m_wzcConfig.Ssid.SsidLength + 2];
  1660. // in case of failure put in just the suffix!
  1661. if (pwszCaption == NULL)
  1662. {
  1663. psh.pszCaption = pwszSuffix;
  1664. }
  1665. else
  1666. {
  1667. if (pPpWzcPage->m_wzcConfig.Ssid.SsidLength)
  1668. {
  1669. nLen = MultiByteToWideChar(
  1670. CP_ACP,
  1671. 0,
  1672. (LPCSTR)pPpWzcPage->m_wzcConfig.Ssid.Ssid,
  1673. pPpWzcPage->m_wzcConfig.Ssid.SsidLength,
  1674. pwszCaption,
  1675. 32); // no more than 32 WCHARs reserved for the SSID
  1676. }
  1677. pwszCaption[nLen] = L' ';
  1678. // this copies the null terminator as well
  1679. wcscpy(&(pwszCaption[nLen + 1]), pwszSuffix);
  1680. psh.pszCaption = pwszCaption;
  1681. }
  1682. }
  1683. else
  1684. {
  1685. LoadString(WZCGetSPResModule(), IDS_WZC_DLG_CAPTION, wszBuffer, sizeof(wszBuffer));
  1686. //psh.pszCaption = SzLoadString(WZCGetSPResModule(), IDS_WZC_DLG_CAPTION);
  1687. psh.pszCaption = wszBuffer;
  1688. }
  1689. retCode = PropertySheet(&psh);
  1690. if (pwszCaption != NULL)
  1691. delete pwszCaption;
  1692. return retCode;
  1693. }
  1694. // Advanced dialog
  1695. INT_PTR CALLBACK CWZeroConfPage::AdvancedDialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1696. {
  1697. // Get the pointer to our instance from where we stashed it.
  1698. CWZeroConfPage* pThis = (CWZeroConfPage*) ::GetWindowLongPtr(hwnd, GWLP_USERDATA);
  1699. if (!pThis)
  1700. {
  1701. if (WM_INITDIALOG == uMsg)
  1702. {
  1703. // Stash our instance pointer
  1704. pThis = (CWZeroConfPage*) lParam;
  1705. ::SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) pThis);
  1706. }
  1707. }
  1708. if (pThis)
  1709. {
  1710. switch (uMsg)
  1711. {
  1712. case WM_INITDIALOG:
  1713. {
  1714. // select the correct item by default
  1715. NDIS_802_11_NETWORK_INFRASTRUCTURE mode = (NDIS_802_11_NETWORK_INFRASTRUCTURE)(pThis->m_dwCtlFlags & INTFCTL_CM_MASK);
  1716. UINT idSelect;
  1717. switch (mode)
  1718. {
  1719. case Ndis802_11IBSS:
  1720. // Computer-to-computer
  1721. idSelect = IDC_ADHOC;
  1722. break;
  1723. case Ndis802_11Infrastructure:
  1724. // infrastructure (access point) network
  1725. idSelect = IDC_INFRA;
  1726. break;
  1727. case Ndis802_11AutoUnknown:
  1728. default:
  1729. // Any network (access point preferred)
  1730. idSelect = IDC_ANYNET;
  1731. };
  1732. // Select the right radio button
  1733. ::SendDlgItemMessage(hwnd, idSelect, BM_SETCHECK, BST_CHECKED, 0);
  1734. // Check the "fallback to visible networks" checkbox if necessary
  1735. ::SendDlgItemMessage(hwnd, IDC_WZC_CHK_Fallback, BM_SETCHECK, (pThis->m_dwCtlFlags & INTFCTL_FALLBACK) ? BST_CHECKED : BST_UNCHECKED, 0);
  1736. }
  1737. return TRUE;
  1738. case WM_COMMAND:
  1739. switch(LOWORD(wParam))
  1740. {
  1741. case IDOK:
  1742. {
  1743. // ...Set the connectivity mode...
  1744. NDIS_802_11_NETWORK_INFRASTRUCTURE mode = Ndis802_11AutoUnknown;
  1745. // See what type of network connectivity the user selected
  1746. if (BST_CHECKED == ::SendDlgItemMessage(hwnd, IDC_ADHOC, BM_GETCHECK, 0, 0))
  1747. {
  1748. // Computer-to-computer
  1749. mode = Ndis802_11IBSS;
  1750. }
  1751. else if (BST_CHECKED == ::SendDlgItemMessage(hwnd, IDC_INFRA, BM_GETCHECK, 0, 0))
  1752. {
  1753. // infrastructure (access point) network
  1754. mode = Ndis802_11Infrastructure;
  1755. }
  1756. else if (BST_CHECKED == ::SendDlgItemMessage(hwnd, IDC_ANYNET, BM_GETCHECK, 0, 0))
  1757. {
  1758. // Any network (access point preferred)
  1759. mode = Ndis802_11AutoUnknown;
  1760. }
  1761. pThis->m_dwCtlFlags &= ~INTFCTL_CM_MASK;
  1762. pThis->m_dwCtlFlags |= (((DWORD) mode) & INTFCTL_CM_MASK);
  1763. // Set the "fallback to visible networks" flag
  1764. pThis->m_dwCtlFlags &= ~INTFCTL_FALLBACK;
  1765. if (BST_CHECKED == ::SendDlgItemMessage(hwnd, IDC_WZC_CHK_Fallback, BM_GETCHECK, 0, 0))
  1766. {
  1767. pThis->m_dwCtlFlags |= INTFCTL_FALLBACK;
  1768. }
  1769. ::EndDialog(hwnd, IDOK);
  1770. }
  1771. return TRUE;
  1772. }
  1773. break;
  1774. case WM_CLOSE:
  1775. ::EndDialog(hwnd, IDCANCEL);
  1776. return TRUE;
  1777. case WM_CONTEXTMENU:
  1778. {
  1779. ::WinHelp(hwnd,
  1780. c_szNetCfgHelpFile,
  1781. HELP_CONTEXTMENU,
  1782. (ULONG_PTR)g_aHelpIDs_IDC_WZC_ADVANCED);
  1783. return TRUE;
  1784. }
  1785. case WM_HELP:
  1786. {
  1787. LPHELPINFO lphi = reinterpret_cast<LPHELPINFO>(lParam);
  1788. ::WinHelp(static_cast<HWND>(lphi->hItemHandle),
  1789. c_szNetCfgHelpFile,
  1790. HELP_WM_HELP,
  1791. (ULONG_PTR)g_aHelpIDs_IDC_WZC_ADVANCED);
  1792. return TRUE;
  1793. }
  1794. }
  1795. }
  1796. return FALSE;
  1797. }