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.

2251 lines
63 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997-1999.
  5. //
  6. // File: U T I L. C P P
  7. //
  8. // Contents: Utility functions shared within lanui
  9. //
  10. //
  11. //----------------------------------------------------------------------------
  12. #include "pch.h"
  13. #pragma hdrstop
  14. #include "resource.h"
  15. #include "ncreg.h"
  16. #include "ncnetcon.h"
  17. #include "ncnetcfg.h"
  18. #include "ncsetup.h"
  19. #include "lanui.h"
  20. #include "util.h"
  21. #include "chklist.h"
  22. #include "lanuiobj.h"
  23. #include "ncui.h"
  24. #include "ndispnp.h"
  25. #include "ncperms.h"
  26. #include "ncmisc.h"
  27. #include "wzcsapi.h"
  28. #include <raseapif.h>
  29. #include <raserror.h>
  30. #include "connutil.h"
  31. #define INITGUID
  32. #include "ncxclsid.h"
  33. #undef INITGUID
  34. extern const WCHAR c_szBiNdisAtm[];
  35. extern const WCHAR c_szDevice[];
  36. extern const WCHAR c_szInfId_MS_TCPIP[];
  37. //+---------------------------------------------------------------------------
  38. //
  39. // Function Name: HrInitCheckboxListView
  40. //
  41. // Purpose: Initialize the list view for checkboxes.
  42. //
  43. // Arguments:
  44. // hwndList[in]: Handle of the list view
  45. // philStateIcons[out]: Image list for the list view
  46. // pcild [in,optional] Image list data, created if necessary
  47. //
  48. // Returns: HRESULT, Error code.
  49. //
  50. // Notes:
  51. //
  52. HRESULT HrInitCheckboxListView(HWND hwndList, HIMAGELIST* philStateIcons, SP_CLASSIMAGELIST_DATA* pcild)
  53. {
  54. HRESULT hr = S_OK;
  55. RECT rc;
  56. LVCOLUMN lvc = {0};
  57. HWND hwndHeader;
  58. // Create small image lists
  59. //
  60. if(NULL == pcild)
  61. {
  62. pcild = new SP_CLASSIMAGELIST_DATA;
  63. if(pcild)
  64. {
  65. hr = HrSetupDiGetClassImageList(pcild);
  66. if (SUCCEEDED(hr))
  67. {
  68. AssertSz(pcild->ImageList, "No class image list data!");
  69. // Save off image list data for use later
  70. ::SetWindowLongPtr(GetParent(hwndList), GWLP_USERDATA,
  71. reinterpret_cast<LONG_PTR>(pcild));
  72. }
  73. else
  74. {
  75. TraceError("HrSetupDiGetClassImageList returns failure", hr);
  76. hr = S_OK;
  77. // delete this if we couldn't get the structure
  78. delete pcild;
  79. ::SetWindowLongPtr(GetParent(hwndList), GWLP_USERDATA, 0);
  80. }
  81. }
  82. else
  83. {
  84. hr = E_OUTOFMEMORY;
  85. }
  86. }
  87. if(SUCCEEDED(hr))
  88. {
  89. ListView_SetImageList(hwndList, pcild->ImageList, LVSIL_SMALL);
  90. // Set the shared image lists bit so the caller can destroy the class
  91. // image lists itself
  92. //
  93. DWORD dwStyle = GetWindowLong(hwndList, GWL_STYLE);
  94. SetWindowLong(hwndList, GWL_STYLE, (dwStyle | LVS_SHAREIMAGELISTS));
  95. // Create state image lists
  96. *philStateIcons = ImageList_LoadBitmapAndMirror(
  97. _Module.GetResourceInstance(),
  98. MAKEINTRESOURCE(IDB_CHECKSTATE),
  99. 16,
  100. 0,
  101. PALETTEINDEX(6));
  102. ListView_SetImageList(hwndList, *philStateIcons, LVSIL_STATE);
  103. // First determine if we have already added a column before
  104. // adding one.
  105. //
  106. hwndHeader = ListView_GetHeader( hwndList );
  107. Assert( hwndHeader );
  108. if ( (!hwndHeader) ||
  109. (Header_GetItemCount(hwndHeader) == 0) )
  110. {
  111. GetClientRect(hwndList, &rc);
  112. lvc.mask = LVCF_FMT | LVCF_WIDTH;
  113. lvc.fmt = LVCFMT_LEFT;
  114. lvc.cx = rc.right;
  115. // $REVIEW(tongl 12\22\97): Fix for bug#127472
  116. // lvc.cx = rc.right - GetSystemMetrics(SM_CXVSCROLL);
  117. ListView_InsertColumn(hwndList, 0, &lvc);
  118. }
  119. }
  120. return hr;
  121. }
  122. //+---------------------------------------------------------------------------
  123. //
  124. // Function Name: HrInitListView
  125. //
  126. // Purpose: Initialize the list view.
  127. // Iterate through all installed clients, services and protocols,
  128. // insert into the list view with the correct binding state with
  129. // the adapter used in this connection.
  130. //
  131. // Arguments:
  132. // hwndList[in]: Handle of the list view
  133. // pnc[in]: The writable INetcfg pointer
  134. // pnccAdapter[in]: The INetcfgComponent pointer to the adapter used in this connection
  135. //
  136. // Returns: HRESULT, Error code.
  137. //
  138. // Notes:
  139. //
  140. HRESULT HrInitListView(HWND hwndList,
  141. INetCfg* pnc,
  142. INetCfgComponent * pnccAdapter,
  143. ListBPObj * plistBindingPaths,
  144. HIMAGELIST* philStateIcons)
  145. {
  146. HRESULT hr = S_OK;
  147. SP_CLASSIMAGELIST_DATA *pcild;
  148. Assert(hwndList);
  149. Assert(pnc);
  150. Assert(pnccAdapter);
  151. Assert(plistBindingPaths);
  152. Assert(philStateIcons);
  153. pcild = (SP_CLASSIMAGELIST_DATA *)::GetWindowLongPtr(::GetParent(hwndList),
  154. GWLP_USERDATA);
  155. HrInitCheckboxListView(hwndList, philStateIcons, pcild);
  156. hr = HrRefreshAll(hwndList, pnc, pnccAdapter, plistBindingPaths);
  157. if (SUCCEEDED(hr))
  158. {
  159. // Selete the first item
  160. ListView_SetItemState(hwndList, 0, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED);
  161. }
  162. TraceError("HrInitListView", hr);
  163. return hr;
  164. }
  165. //+---------------------------------------------------------------------------
  166. //
  167. // Function: UninitListView
  168. //
  169. // Purpose: Uninitializes the common component list view
  170. //
  171. // Arguments:
  172. // hwndList [in] HWND of listview
  173. //
  174. // Returns: Nothing
  175. //
  176. // Author: danielwe 2 Feb 1998
  177. //
  178. // Notes:
  179. //
  180. VOID UninitListView(HWND hwndList)
  181. {
  182. SP_CLASSIMAGELIST_DATA * pcild;
  183. Assert(hwndList);
  184. // delete existing items in the list view
  185. ListView_DeleteAllItems( hwndList );
  186. pcild = reinterpret_cast<SP_CLASSIMAGELIST_DATA *>(
  187. ::GetWindowLongPtr(GetParent(hwndList), GWLP_USERDATA));
  188. if (pcild)
  189. {
  190. // Destroy the class image list data
  191. (VOID) HrSetupDiDestroyClassImageList(pcild);
  192. delete pcild;
  193. }
  194. }
  195. //+---------------------------------------------------------------------------
  196. //
  197. // Function Name: HrInsertComponent
  198. //
  199. // Purpose: Insert all installed, non-hidden and bindable components
  200. // of a class to the list view
  201. //
  202. // Arguments:
  203. //
  204. // Returns: HRESULT, Error code.
  205. //
  206. // Notes:
  207. //
  208. HRESULT HrInsertComponent(
  209. IN HWND hwndList,
  210. IN const GUID* pGuidDevClass,
  211. IN INetCfgComponent *pncc,
  212. IN INetCfgComponent *pnccAdapter,
  213. IN DWORD dwFlags,
  214. IN ListBPObj * plistBindingPaths,
  215. IN OUT INT* pnPos)
  216. {
  217. HRESULT hr = S_OK;
  218. SP_CLASSIMAGELIST_DATA * pcild;
  219. Assert(hwndList);
  220. Assert(pGuidDevClass);
  221. pcild = reinterpret_cast<SP_CLASSIMAGELIST_DATA *>
  222. (::GetWindowLongPtr(GetParent(hwndList), GWLP_USERDATA));
  223. // We should only list components that are bindable to the adapter
  224. // Note: bindable means binding path exists, either enabled or disabled
  225. INetCfgComponentBindings * pnccb;
  226. hr = pncc->QueryInterface(IID_INetCfgComponentBindings, (LPVOID *)&pnccb);
  227. if (S_OK == hr)
  228. {
  229. // Do this only for protocols !!
  230. // $REVIEW(TongL 3/28/99), I included the 2 reasons on why we only filter
  231. // non-bindable protocols below, in case someone ask again ..
  232. // 1) (Originally per BillBe) The add component dialog filters out non-bindable
  233. // protocols by matching binding interface names from INF, it can not easily do
  234. // so for services/clients which could be several layers above the adapter.
  235. // The property UI needs to be consistent because it's confusing to users if
  236. // we allow them to add a component from a connection but don't let that
  237. // component show up in the same connection's property UI.
  238. // 2) (Per ShaunCo) After talking with Bill, we show protocols yet not clients
  239. // services not to be consistent with the add component dialog, but because
  240. // you cannot predict based on bindings alone whether a client or service will
  241. // end up being involved with an adapter. example: i can install a service
  242. // that doesn't bind and uses winsock to send data. It may be able to be configured
  243. // differently for each adapter (and hence would need to show up for each adapter's
  244. // connection) but you can't tell by any means whether its going to be invovled with
  245. // that adapter or not. -- So you have to show all services and clients.
  246. // A protocol, on the other hand, binds with adapters by definition. So, we know
  247. // for the protocol's which will use an adapter and which won't.
  248. // Special case: do now show filter components unless it is bindable,
  249. // Raid 358865
  250. DWORD dwFlags;
  251. hr = pncc->GetCharacteristics(&dwFlags);
  252. if ((SUCCEEDED(hr) && (dwFlags & NCF_FILTER)) ||
  253. (GUID_DEVCLASS_NETTRANS == *pGuidDevClass))
  254. {
  255. // $REVIEW(ShaunCo 3/26/99)
  256. // To see if the protocol is involved with the adapter, check the
  257. // owner of each bindpath and see if its equal to the component
  258. // we are considering inserting into the list view.
  259. // Note the special case for ms_nwnb. It won't be involved in a
  260. // direct binding to the adapter because it has NCF_DONTEXPOSELOWER,
  261. // so we can't use IsBindableTo.
  262. BOOL fProtocolIsInvolved = FALSE;
  263. ListBPObj_ITER iter;
  264. for (iter = plistBindingPaths->begin();
  265. (iter != plistBindingPaths->end() && !fProtocolIsInvolved);
  266. iter++)
  267. {
  268. INetCfgComponent* pScan;
  269. hr = (*iter)->m_pncbp->GetOwner(&pScan);
  270. if (S_OK == hr)
  271. {
  272. if (pScan == pncc)
  273. {
  274. fProtocolIsInvolved = TRUE;
  275. }
  276. ReleaseObj(pScan);
  277. }
  278. }
  279. if (!fProtocolIsInvolved)
  280. {
  281. // Don't insert this protocol because it is not involved
  282. // in the binding set for the adpater.
  283. //
  284. hr = S_FALSE;
  285. }
  286. }
  287. if (S_OK == hr) // bindable, add to list
  288. {
  289. PWSTR pszwName;
  290. hr = pncc->GetDisplayName(&pszwName);
  291. if (SUCCEEDED(hr))
  292. {
  293. PWSTR pszwDesc;
  294. // Special Case:
  295. // If this is a Domain Controller,
  296. // disable tcpip removal, Raid 263754
  297. //
  298. if (GUID_DEVCLASS_NETTRANS == *pGuidDevClass)
  299. {
  300. PWSTR pszwId;
  301. hr = pncc->GetId (&pszwId);
  302. if (SUCCEEDED(hr))
  303. {
  304. if (FEqualComponentId (c_szInfId_MS_TCPIP, pszwId))
  305. {
  306. NT_PRODUCT_TYPE pt;
  307. RtlGetNtProductType (&pt);
  308. if (NtProductLanManNt == pt)
  309. {
  310. dwFlags |= NCF_NOT_USER_REMOVABLE;
  311. }
  312. }
  313. CoTaskMemFree (pszwId);
  314. }
  315. }
  316. hr = pncc->GetHelpText(&pszwDesc);
  317. if (SUCCEEDED(hr))
  318. {
  319. LV_ITEM lvi = {0};
  320. lvi.mask = LVIF_TEXT | LVIF_IMAGE |
  321. LVIF_STATE | LVIF_PARAM;
  322. // Get the component's class image list index
  323. if (pcild)
  324. {
  325. INT nIndex = 0;
  326. (VOID) HrSetupDiGetClassImageIndex(pcild,
  327. pGuidDevClass, &nIndex);
  328. lvi.iImage = nIndex;
  329. }
  330. lvi.iItem = *pnPos;
  331. NET_ITEM_DATA * pnid = new NET_ITEM_DATA;
  332. if (pnid)
  333. {
  334. pnid->szwName = SzDupSz(pszwName);
  335. pnid->szwDesc = SzDupSz(pszwDesc);
  336. pnid->dwFlags = dwFlags;
  337. AddRefObj(pnid->pncc = pncc);
  338. pnid->pCompObj = new CComponentObj(pncc);
  339. if (pnid->pCompObj)
  340. {
  341. hr = pnid->pCompObj->HrInit(plistBindingPaths);
  342. if FAILED(hr)
  343. {
  344. TraceError("HrInsertComponent: failed to initialize a component object", hr);
  345. hr = S_OK;
  346. }
  347. }
  348. lvi.lParam = reinterpret_cast<LPARAM>(pnid);
  349. lvi.pszText = pnid->szwName;
  350. // We will refresh the state of the whole list in the end
  351. UINT iChkIndex = SELS_CHECKED;
  352. lvi.state = INDEXTOSTATEIMAGEMASK( iChkIndex );
  353. INT ret;
  354. ret = ListView_InsertItem(hwndList, &lvi);
  355. (*pnPos)++;
  356. CoTaskMemFree(pszwDesc);
  357. }
  358. }
  359. CoTaskMemFree(pszwName);
  360. }
  361. }
  362. ReleaseObj(pnccb);
  363. }
  364. TraceError("HrInsertComponent", S_FALSE == hr ? S_OK : hr);
  365. return hr;
  366. }
  367. //+---------------------------------------------------------------------------
  368. //
  369. // Function Name: HrInsertComponents
  370. //
  371. // Purpose: Insert installed and non-hidden components
  372. // of a class to the list view
  373. //
  374. // Arguments:
  375. //
  376. // Returns: HRESULT, Error code.
  377. //
  378. // Notes:
  379. //
  380. HRESULT HrInsertComponents(
  381. IN HWND hwndList,
  382. IN INetCfg* pnc,
  383. IN const GUID* pGuidDevClass,
  384. IN INetCfgComponent* pnccAdapter,
  385. IN ListBPObj* plistBindingPaths,
  386. IN OUT INT* pnPos)
  387. {
  388. Assert(hwndList);
  389. HRESULT hr = S_OK;
  390. CIterNetCfgComponent iterComp (pnc, pGuidDevClass);
  391. INetCfgComponent* pncc;
  392. while (SUCCEEDED(hr) && S_OK == (hr = iterComp.HrNext(&pncc)))
  393. {
  394. DWORD dwFlags;
  395. hr = pncc->GetCharacteristics(&dwFlags);
  396. // Make sure it's not hidden
  397. if (SUCCEEDED(hr) && !(dwFlags & NCF_HIDDEN))
  398. {
  399. // This will AddRef pncc so the release below can still be
  400. // there
  401. hr = HrInsertComponent(
  402. hwndList, pGuidDevClass, pncc, pnccAdapter,
  403. dwFlags, plistBindingPaths, pnPos);
  404. }
  405. ReleaseObj(pncc);
  406. }
  407. if (SUCCEEDED(hr))
  408. {
  409. // Get rid of FALSE returns
  410. hr = S_OK;
  411. }
  412. TraceError("HrInsertComponents", hr);
  413. return hr;
  414. }
  415. //+---------------------------------------------------------------------------
  416. //
  417. // Function Name: HrRefreshListView
  418. //
  419. // Purpose: Iterate through all installed clients, services and protocols,
  420. // insert into the list view with the correct binding state with
  421. // the adapter used in this connection.
  422. //
  423. // Arguments:
  424. // hwndList[in]: Handle of the list view
  425. // pnc[in]: The writable INetcfg pointer
  426. // pnccAdapter[in]: The INetcfgComponent pointer to the adapter used in this connection
  427. //
  428. // Returns: HRESULT, Error code.
  429. //
  430. // Notes:
  431. //
  432. HRESULT HrRefreshListView(HWND hwndList,
  433. INetCfg* pnc,
  434. INetCfgComponent * pnccAdapter,
  435. ListBPObj * plistBindingPaths)
  436. {
  437. HRESULT hr;
  438. INT nPos = 0;
  439. Assert(hwndList);
  440. // Clients
  441. hr = HrInsertComponents(hwndList, pnc,
  442. &GUID_DEVCLASS_NETCLIENT, pnccAdapter, plistBindingPaths,
  443. &nPos);
  444. if (SUCCEEDED(hr))
  445. {
  446. // Services
  447. hr = HrInsertComponents(hwndList, pnc,
  448. &GUID_DEVCLASS_NETSERVICE, pnccAdapter, plistBindingPaths,
  449. &nPos);
  450. }
  451. if (SUCCEEDED(hr))
  452. {
  453. // Protocols
  454. hr = HrInsertComponents(hwndList, pnc,
  455. &GUID_DEVCLASS_NETTRANS, pnccAdapter, plistBindingPaths,
  456. &nPos);
  457. }
  458. // Now refresh the state of all items
  459. if (SUCCEEDED(hr))
  460. {
  461. hr = HrRefreshCheckListState(hwndList);
  462. }
  463. TraceError("HrRefreshListView", hr);
  464. return hr;
  465. }
  466. //+---------------------------------------------------------------------------
  467. //
  468. // Function Name: HrLvGetSelectedComponent
  469. //
  470. // Purpose: Return pointer to the INetCfgComponent of the selected
  471. // client, service or protocol
  472. //
  473. // Returns: S_OK if successful,
  474. // S_FALSE if list view Macros returns failure
  475. // (specific error not available).
  476. //
  477. // Notes:
  478. //
  479. HRESULT HrLvGetSelectedComponent(HWND hwndList,
  480. INetCfgComponent ** ppncc)
  481. {
  482. HRESULT hr = S_FALSE;
  483. Assert(hwndList);
  484. *ppncc = NULL;
  485. INT iSelected = ListView_GetNextItem(hwndList, -1, LVNI_SELECTED);
  486. if (iSelected != -1)
  487. {
  488. LV_ITEM lvItem = {0};
  489. lvItem.mask = LVIF_PARAM;
  490. lvItem.iItem = iSelected;
  491. if (ListView_GetItem(hwndList, &lvItem))
  492. {
  493. NET_ITEM_DATA * pnid;
  494. pnid = reinterpret_cast<NET_ITEM_DATA *>(lvItem.lParam);
  495. if (pnid)
  496. {
  497. hr = S_OK;
  498. pnid->pncc->AddRef();
  499. *ppncc = pnid->pncc;
  500. }
  501. }
  502. }
  503. TraceError("HrLvGetSelectedComponent", S_FALSE == hr ? S_OK : hr);
  504. return hr;
  505. }
  506. //+---------------------------------------------------------------------------
  507. //
  508. // Function: LvDeleteItem
  509. //
  510. // Purpose: Handles deletion of the given item from the listview. Should
  511. // be called in response to the LVN_DELETEITEM notification.
  512. //
  513. // Arguments:
  514. // hwndList [in] Listview handle
  515. // iItem [in] item that was deleted
  516. //
  517. // Returns: Nothing
  518. //
  519. // Author: danielwe 3 Nov 1997
  520. //
  521. // Notes:
  522. //
  523. VOID LvDeleteItem(HWND hwndList, int iItem)
  524. {
  525. LV_ITEM lvi = {0};
  526. NET_ITEM_DATA * pnid;
  527. lvi.mask = LVIF_PARAM;
  528. lvi.iItem = iItem;
  529. ListView_GetItem(hwndList, &lvi);
  530. pnid = reinterpret_cast<NET_ITEM_DATA*>(lvi.lParam);
  531. AssertSz(pnid, "No item data!?!?");
  532. ReleaseObj(pnid->pncc);
  533. delete(pnid->pCompObj);
  534. delete pnid->szwName;
  535. delete pnid->szwDesc;
  536. delete pnid;
  537. }
  538. //+---------------------------------------------------------------------------
  539. //
  540. // Function Name: OnListClick
  541. //
  542. // Purpose:
  543. //
  544. // Returns:
  545. //
  546. INT OnListClick(HWND hwndList,
  547. HWND hwndParent,
  548. INetCfg *pnc,
  549. IUnknown *punk,
  550. INetCfgComponent *pnccAdapter,
  551. ListBPObj * plistBindingPaths,
  552. BOOL fDoubleClk,
  553. BOOL fReadOnly)
  554. {
  555. INT iItem;
  556. DWORD dwpts;
  557. LV_HITTESTINFO lvhti;
  558. // we have the location
  559. dwpts = GetMessagePos();
  560. lvhti.pt.x = LOWORD( dwpts );
  561. lvhti.pt.y = HIWORD( dwpts );
  562. MapWindowPoints(NULL , hwndList , (LPPOINT) &(lvhti.pt) , 1);
  563. // get currently selected item
  564. iItem = ListView_HitTest( hwndList, &lvhti );
  565. // if no selection, or click not on state return false
  566. if (-1 != iItem)
  567. {
  568. // set the current selection
  569. ListView_SetItemState(hwndList, iItem, LVIS_SELECTED, LVIS_SELECTED);
  570. if ( fDoubleClk )
  571. {
  572. if ((LVHT_ONITEMICON != (LVHT_ONITEMICON & lvhti.flags)) &&
  573. (LVHT_ONITEMLABEL != (LVHT_ONITEMLABEL & lvhti.flags)) &&
  574. (LVHT_ONITEMSTATEICON != (LVHT_ONITEMSTATEICON & lvhti.flags)) )
  575. {
  576. iItem = -1;
  577. }
  578. }
  579. else // single click
  580. {
  581. if (LVHT_ONITEMSTATEICON != (LVHT_ONITEMSTATEICON & lvhti.flags))
  582. {
  583. iItem = -1;
  584. }
  585. }
  586. if (-1 != iItem)
  587. {
  588. HRESULT hr = S_OK;
  589. if ((fDoubleClk) &&
  590. (LVHT_ONITEMSTATEICON != (LVHT_ONITEMSTATEICON & lvhti.flags)))
  591. {
  592. // only raise properties if the selected component has UI and
  593. // is not disabled, and the current user has the permission to
  594. // change properties.
  595. LV_ITEM lvItem;
  596. lvItem.mask = LVIF_PARAM;
  597. lvItem.iItem = iItem;
  598. lvItem.iSubItem = 0;
  599. if (ListView_GetItem(hwndList, &lvItem))
  600. {
  601. NET_ITEM_DATA * pnid = NULL;
  602. pnid = reinterpret_cast<NET_ITEM_DATA *>(lvItem.lParam);
  603. if (pnid)
  604. {
  605. // is this component checked ?
  606. if ((UNCHECKED != (pnid->pCompObj)->GetChkState()) &&
  607. (pnid->dwFlags & NCF_HAS_UI) &&
  608. FHasPermission(NCPERM_LanChangeProperties))
  609. {
  610. BOOL fShowProperties = TRUE;
  611. if (FIsUserNetworkConfigOps())
  612. {
  613. LPWSTR pszwId;
  614. hr = pnid->pncc->GetId(&pszwId);
  615. if (SUCCEEDED(hr))
  616. {
  617. if (pszwId)
  618. {
  619. if (!FEqualComponentId (c_szInfId_MS_TCPIP, pszwId))
  620. {
  621. fShowProperties = FALSE;
  622. }
  623. else if (FEqualComponentId (c_szInfId_MS_TCPIP, pszwId))
  624. {
  625. fShowProperties = TRUE;
  626. }
  627. CoTaskMemFree(pszwId);
  628. }
  629. else
  630. {
  631. fShowProperties = FALSE;
  632. }
  633. }
  634. else
  635. {
  636. fShowProperties = FALSE;
  637. }
  638. }
  639. if (fShowProperties)
  640. {
  641. hr = HrLvProperties(hwndList, hwndParent, pnc, punk,
  642. pnccAdapter, plistBindingPaths, NULL);
  643. }
  644. }
  645. }
  646. }
  647. }
  648. else
  649. {
  650. if (!fReadOnly)
  651. {
  652. hr = HrToggleLVItemState(hwndList, plistBindingPaths, iItem);
  653. }
  654. }
  655. if FAILED(hr)
  656. iItem = -1;
  657. }
  658. }
  659. return( iItem );
  660. }
  661. //+---------------------------------------------------------------------------
  662. //
  663. // Function Name: HrToggleLVItemState
  664. //
  665. // Purpose:
  666. //
  667. // Returns:
  668. //
  669. HRESULT HrToggleLVItemState(HWND hwndList,
  670. ListBPObj * plistBindingPaths,
  671. INT iItem)
  672. {
  673. HRESULT hr = S_OK;
  674. LV_ITEM lvItem;
  675. NET_ITEM_DATA * pnid;
  676. // we are interested in is the PARAM
  677. lvItem.iItem = iItem;
  678. lvItem.mask = LVIF_PARAM;
  679. lvItem.iSubItem = 0;
  680. ListView_GetItem( hwndList, &lvItem );
  681. // get the item
  682. pnid = (NET_ITEM_DATA *)lvItem.lParam;
  683. // If the binding checkbox is available, then allow the toggle.
  684. //
  685. if (!(pnid->dwFlags & NCF_FIXED_BINDING) &&
  686. FHasPermission(NCPERM_ChangeBindState))
  687. {
  688. if (pnid->pCompObj->GetChkState() == UNCHECKED) // toggle on
  689. {
  690. hr = pnid->pCompObj->HrCheck(plistBindingPaths);
  691. if SUCCEEDED(hr)
  692. {
  693. hr = HrRefreshCheckListState(hwndList);
  694. }
  695. // "Ding" if the state of this item is still unchecked
  696. if (pnid->pCompObj->GetChkState() == UNCHECKED)
  697. {
  698. #ifdef DBG
  699. TraceTag(ttidLanUi, "Why is this component still disabled ???");
  700. #endif
  701. }
  702. }
  703. else // toggle off
  704. {
  705. hr = pnid->pCompObj->HrUncheck(plistBindingPaths);
  706. if SUCCEEDED(hr)
  707. {
  708. hr = HrRefreshCheckListState(hwndList);
  709. }
  710. // "Ding" if the state of this item is not unchecked
  711. if (pnid->pCompObj->GetChkState() != UNCHECKED)
  712. {
  713. #ifdef DBG
  714. TraceTag(ttidLanUi, "Why is this component not disabled ???");
  715. #endif
  716. }
  717. }
  718. }
  719. TraceError("HrToggleLVItemState", hr);
  720. return hr;
  721. }
  722. //+---------------------------------------------------------------------------
  723. //
  724. // Function Name: OnListKeyDown
  725. //
  726. // Purpose:
  727. //
  728. // Returns:
  729. //
  730. INT OnListKeyDown(HWND hwndList, ListBPObj * plistBindingPaths, WORD wVKey)
  731. {
  732. INT iItem = -1;
  733. if ((VK_SPACE == wVKey) && (GetAsyncKeyState(VK_MENU)>=0))
  734. {
  735. iItem = ListView_GetNextItem(hwndList, -1, LVNI_FOCUSED | LVNI_SELECTED);
  736. // if no selection
  737. if (-1 != iItem)
  738. {
  739. HRESULT hr = S_OK;
  740. hr = HrToggleLVItemState(hwndList, plistBindingPaths, iItem);
  741. if FAILED(hr)
  742. iItem = -1;
  743. }
  744. }
  745. return( iItem );
  746. }
  747. //+---------------------------------------------------------------------------
  748. //
  749. // Function Name: LvSetButtons
  750. //
  751. // Purpose: Set the correct status of Add, Remove, Property buttons,
  752. // and the description text
  753. //
  754. // Returns:
  755. //
  756. VOID LvSetButtons(HWND hwndParent, HANDLES& h, BOOL fReadOnly, IUnknown * punk)
  757. {
  758. Assert(IsWindow(h.m_hList));
  759. Assert(IsWindow(h.m_hAdd));
  760. Assert(IsWindow(h.m_hRemove));
  761. Assert(IsWindow(h.m_hProperty));
  762. // enable Property button if valid and update description text
  763. INT iSelected = ListView_GetNextItem(h.m_hList, -1, LVNI_SELECTED);
  764. if (iSelected == -1) // Nothing selected or list empty
  765. {
  766. ::EnableWindow(h.m_hAdd, !fReadOnly && FHasPermission(NCPERM_AddRemoveComponents));
  767. if (!fReadOnly)
  768. {
  769. // if list is empty, set focus to the list view
  770. if (0 == ListView_GetItemCount(h.m_hList))
  771. {
  772. // remove the default on the remove button
  773. SendMessage(h.m_hRemove, BM_SETSTYLE, (WPARAM)BS_PUSHBUTTON, TRUE );
  774. // move focus to the Add button
  775. ::SetFocus(h.m_hAdd);
  776. }
  777. }
  778. ::EnableWindow(h.m_hRemove, FALSE);
  779. ::EnableWindow(h.m_hProperty, FALSE);
  780. if(h.m_hDescription)
  781. {
  782. ::SetWindowText(h.m_hDescription, c_szEmpty);
  783. }
  784. }
  785. else
  786. {
  787. // enable Add/Remove buttons
  788. ::EnableWindow(h.m_hAdd, !fReadOnly && FHasPermission(NCPERM_AddRemoveComponents));
  789. LV_ITEM lvItem;
  790. lvItem.mask = LVIF_PARAM;
  791. lvItem.iItem = iSelected;
  792. lvItem.iSubItem = 0;
  793. if (ListView_GetItem(h.m_hList, &lvItem))
  794. {
  795. NET_ITEM_DATA * pnid = NULL;
  796. pnid = reinterpret_cast<NET_ITEM_DATA *>(lvItem.lParam);
  797. if (pnid)
  798. {
  799. if (fReadOnly)
  800. {
  801. ::EnableWindow(h.m_hProperty, FALSE);
  802. ::EnableWindow(h.m_hRemove, FALSE);
  803. }
  804. else
  805. {
  806. // is this component checked ?
  807. if (UNCHECKED != (pnid->pCompObj)->GetChkState())
  808. {
  809. BOOL fHasPropertyUi = FALSE;
  810. HRESULT hr = S_OK;
  811. INetCfgComponent * pncc;
  812. LPWSTR pszwId;
  813. hr = HrLvGetSelectedComponent(h.m_hList, &pncc);
  814. if (S_OK == hr)
  815. {
  816. AssertSz(pncc, "No component selected?!?!");
  817. hr = pncc->RaisePropertyUi(hwndParent, NCRP_QUERY_PROPERTY_UI, punk);
  818. if (S_OK == hr)
  819. {
  820. fHasPropertyUi = TRUE;
  821. }
  822. ReleaseObj(pncc);
  823. }
  824. if (FIsUserNetworkConfigOps() && FHasPermission(NCPERM_LanChangeProperties))
  825. {
  826. hr = pncc->GetId(&pszwId);
  827. if (SUCCEEDED(hr))
  828. {
  829. if (pszwId && !FEqualComponentId (c_szInfId_MS_TCPIP, pszwId))
  830. {
  831. ::EnableWindow(h.m_hProperty, FALSE);
  832. }
  833. else if (pszwId && FEqualComponentId (c_szInfId_MS_TCPIP, pszwId) && fHasPropertyUi)
  834. {
  835. ::EnableWindow(h.m_hProperty, TRUE);
  836. }
  837. }
  838. }
  839. else
  840. {
  841. ::EnableWindow(h.m_hProperty,
  842. fHasPropertyUi &&
  843. FHasPermission(NCPERM_LanChangeProperties));
  844. }
  845. }
  846. else
  847. {
  848. ::EnableWindow(h.m_hProperty, FALSE);
  849. }
  850. // is this component user removable ?
  851. ::EnableWindow(h.m_hRemove,
  852. !(pnid->dwFlags & NCF_NOT_USER_REMOVABLE) &&
  853. FHasPermission(NCPERM_AddRemoveComponents));
  854. }
  855. // set description text
  856. if(h.m_hDescription)
  857. {
  858. ::SetWindowText(h.m_hDescription, (PCWSTR)pnid->szwDesc);
  859. }
  860. }
  861. // Set focus to the list (336050)
  862. SetFocus(h.m_hList);
  863. }
  864. }
  865. return;
  866. }
  867. //+---------------------------------------------------------------------------
  868. //
  869. // Function: HrLvRemove
  870. //
  871. // Purpose: Handles the pressing of the Remove button. Should be called
  872. // in responsed to the PSB_Remove message.
  873. //
  874. // Arguments:
  875. // hwndLV [in] Handle of listview
  876. // hwndParent [in] Handle of parent window
  877. // pnc [in] INetCfg being used
  878. // pnccAdapter [in] INetCfgComponent of adapter for the connection
  879. //
  880. // Returns: S_OK if success, Win32 or OLE error code otherwise
  881. //
  882. // Author: danielwe 3 Nov 1997
  883. //
  884. // Notes:
  885. //
  886. HRESULT HrLvRemove(HWND hwndLV, HWND hwndParent,
  887. INetCfg *pnc, INetCfgComponent *pnccAdapter,
  888. ListBPObj * plistBindingPaths)
  889. {
  890. HRESULT hr = S_OK;
  891. INetCfgComponent * pncc;
  892. hr = HrLvGetSelectedComponent(hwndLV, &pncc);
  893. if (S_OK == hr)
  894. {
  895. hr = HrQueryUserAndRemoveComponent(hwndParent, pnc, pncc);
  896. if (NETCFG_S_STILL_REFERENCED == hr)
  897. {
  898. hr = S_OK;
  899. }
  900. else
  901. {
  902. if (SUCCEEDED(hr))
  903. {
  904. HRESULT hrTmp = HrRefreshAll(hwndLV, pnc, pnccAdapter, plistBindingPaths);
  905. if (S_OK != hrTmp)
  906. hr = hrTmp;
  907. }
  908. }
  909. ReleaseObj(pncc);
  910. }
  911. else
  912. {
  913. TraceTag(ttidLanUi, "HrLvGetSelectedComponent did not get a valid selection.");
  914. }
  915. TraceError("HrLvRemove", hr);
  916. return hr;
  917. }
  918. //+---------------------------------------------------------------------------
  919. //
  920. // Function: HrLvAdd
  921. //
  922. // Purpose: Handles the pressing of the Add button. Should be called in
  923. // response to the PSB_Add message.
  924. //
  925. // Arguments:
  926. // hwndLV [in] Handle of listview
  927. // hwndParent [in] Handle of parent window
  928. // pnc [in] INetCfg being used
  929. // pnccAdapter [in] INetCfgComponent of adapter for the connection
  930. //
  931. // Returns: S_OK if success, Win32 or OLE error code otherwise
  932. //
  933. // Author: danielwe 3 Nov 1997
  934. //
  935. // Notes:
  936. //
  937. HRESULT HrLvAdd(HWND hwndLV, HWND hwndParent, INetCfg *pnc,
  938. INetCfgComponent *pnccAdapter,
  939. ListBPObj * plistBindingPaths)
  940. {
  941. HRESULT hr;
  942. CI_FILTER_INFO cfi;
  943. ZeroMemory(&cfi, sizeof(cfi));
  944. if (!pnccAdapter)
  945. {
  946. return E_INVALIDARG;
  947. }
  948. // We want to filter out any irrelvant protocols (i.e. protocols that
  949. // won't bind to this adapter) so we need to send in a filter info
  950. // struct with our information.
  951. cfi.eFilter = FC_LAN; // Apply lan specific filtering
  952. cfi.pIComp = pnccAdapter; // Filter against this adapter
  953. INetCfgComponentBindings* pnccb;
  954. hr = pnccAdapter->QueryInterface(IID_INetCfgComponentBindings,
  955. reinterpret_cast<LPVOID *>(&pnccb));
  956. if (SUCCEEDED(hr))
  957. {
  958. hr = pnccb->SupportsBindingInterface(NCF_UPPER, c_szBiNdisAtm);
  959. if (S_OK == hr)
  960. {
  961. cfi.eFilter = FC_ATM; // Apply lan specific filtering
  962. }
  963. ReleaseObj(pnccb);
  964. }
  965. hr = HrDisplayAddComponentDialog(hwndParent, pnc, &cfi);
  966. if ((S_OK == hr) || (NETCFG_S_REBOOT == hr))
  967. {
  968. HRESULT hrSave = hr;
  969. // Refresh the list to reflect changes
  970. hr = HrRefreshAll(hwndLV, pnc, pnccAdapter, plistBindingPaths);
  971. if (SUCCEEDED(hr))
  972. hr = hrSave;
  973. }
  974. else if (NETCFG_E_ACTIVE_RAS_CONNECTIONS == hr)
  975. {
  976. LvReportError(IDS_LANUI_REQUIRE_DISCONNECT_ADD, hwndParent, NULL, NULL);
  977. }
  978. else if (NETCFG_E_NEED_REBOOT == hr)
  979. {
  980. LvReportError(IDS_LANUI_REQUIRE_REBOOT_ADD, hwndParent, NULL, NULL);
  981. }
  982. else if (S_FALSE != hr)
  983. {
  984. PWSTR psz = NULL;
  985. if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  986. NULL,
  987. hr,
  988. LANG_NEUTRAL,
  989. (PWSTR)&psz,
  990. 0,
  991. NULL))
  992. {
  993. LvReportError(IDS_LANUI_GENERIC_ADD_ERROR, hwndParent, NULL, psz);
  994. GlobalFree(psz);
  995. }
  996. else
  997. {
  998. LvReportErrorHr(hr, IDS_LANUI_GENERIC_ADD_ERROR, hwndParent, NULL);
  999. }
  1000. }
  1001. TraceError("HrLvAdd", hr);
  1002. return hr;
  1003. }
  1004. //+---------------------------------------------------------------------------
  1005. //
  1006. // Function: LvReportError
  1007. //
  1008. // Purpose: Reports a generic error based on the information passed in
  1009. //
  1010. // Arguments:
  1011. // ids [in] IDS of the string to be used as the text of the
  1012. // message box
  1013. // hwnd [in] Parent HWND
  1014. // szDesc [in] Display name of component
  1015. // szText [in] [Optional] If supplied, provides additional string
  1016. // for replacement. Can be NULL.
  1017. //
  1018. // Returns: Nothing
  1019. //
  1020. // Author: danielwe 6 Jan 1998
  1021. //
  1022. // Notes:
  1023. //
  1024. VOID LvReportError(INT ids, HWND hwnd, PCWSTR szDesc, PCWSTR szText)
  1025. {
  1026. if (szDesc && szText)
  1027. {
  1028. NcMsgBox(_Module.GetResourceInstance(), hwnd,
  1029. IDS_LANUI_ERROR_CAPTION, ids,
  1030. MB_ICONSTOP | MB_OK, szDesc, szText);
  1031. }
  1032. else if (szDesc)
  1033. {
  1034. NcMsgBox(_Module.GetResourceInstance(), hwnd,
  1035. IDS_LANUI_ERROR_CAPTION, ids,
  1036. MB_ICONSTOP | MB_OK, szDesc);
  1037. }
  1038. else if (szText)
  1039. {
  1040. NcMsgBox(_Module.GetResourceInstance(), hwnd,
  1041. IDS_LANUI_ERROR_CAPTION, ids,
  1042. MB_ICONSTOP | MB_OK, szText);
  1043. }
  1044. else
  1045. {
  1046. NcMsgBox(_Module.GetResourceInstance(), hwnd,
  1047. IDS_LANUI_ERROR_CAPTION, ids,
  1048. MB_ICONSTOP | MB_OK);
  1049. }
  1050. }
  1051. //+---------------------------------------------------------------------------
  1052. //
  1053. // Function: LvReportErrorHr
  1054. //
  1055. // Purpose: Reports a generic error based on the information passed in
  1056. //
  1057. // Arguments:
  1058. // hr [in] HRESULT error value to use in reporting the error
  1059. // ids [in] IDS of the string to be used as the text of the
  1060. // message box
  1061. // hwnd [in] Parent HWND
  1062. // szDesc [in] Display name of component
  1063. //
  1064. // Returns: Nothing
  1065. //
  1066. // Author: danielwe 14 Nov 1997
  1067. //
  1068. // Notes:
  1069. //
  1070. VOID LvReportErrorHr(HRESULT hr, INT ids, HWND hwnd, PCWSTR szDesc)
  1071. {
  1072. WCHAR szText[32];
  1073. static const WCHAR c_szFmt[] = L"0x%08X";
  1074. wsprintfW(szText, c_szFmt, hr);
  1075. LvReportError(ids, hwnd, szDesc, szText);
  1076. }
  1077. //+---------------------------------------------------------------------------
  1078. //
  1079. // Function: HrLvProperties
  1080. //
  1081. // Purpose: Handles the pressing of the Add button. Should be called in
  1082. // response to the PSB_Properties message.
  1083. //
  1084. // Arguments:
  1085. // hwndLV [in] Handle of listview
  1086. // hwndParent [in] Handle of parent window
  1087. // pnc [in] INetCfg being used
  1088. // punk [in] IUnknown for interface to query context information
  1089. // bChanged [out] Boolean indicating if something changed.
  1090. //
  1091. // Returns: S_OK if success, Win32 or OLE error code otherwise
  1092. //
  1093. // Author: danielwe 3 Nov 1997
  1094. //
  1095. // Notes:
  1096. //
  1097. HRESULT HrLvProperties(HWND hwndLV, HWND hwndParent, INetCfg *pnc,
  1098. IUnknown *punk, INetCfgComponent *pnccAdapter,
  1099. ListBPObj * plistBindingPaths,
  1100. BOOL *bChanged)
  1101. {
  1102. HRESULT hr = S_OK;
  1103. INetCfgComponent * pncc;
  1104. if ( bChanged )
  1105. {
  1106. *bChanged = FALSE;
  1107. }
  1108. hr = HrLvGetSelectedComponent(hwndLV, &pncc);
  1109. if (S_OK == hr)
  1110. {
  1111. AssertSz(pncc, "No component selected?!?!");
  1112. hr = pncc->RaisePropertyUi(hwndParent, NCRP_SHOW_PROPERTY_UI, punk);
  1113. // if components have been added or removed, we may need
  1114. // to refresh the whole list
  1115. if (S_OK == hr)
  1116. {
  1117. TraceTag(ttidLanUi, "Refreshing component list needed because other components are added or removed.");
  1118. hr = HrRefreshAll(hwndLV, pnc, pnccAdapter, plistBindingPaths);
  1119. if ( bChanged )
  1120. {
  1121. *bChanged = TRUE;
  1122. }
  1123. }
  1124. ReleaseObj(pncc);
  1125. }
  1126. else
  1127. {
  1128. TraceTag(ttidLanUi, "HrLvGetSelectedComponent did not return a valid selection.");
  1129. }
  1130. if (SUCCEEDED(hr))
  1131. {
  1132. // Normalize error result
  1133. hr = S_OK;
  1134. }
  1135. TraceError("HrLvProperties", hr);
  1136. return hr;
  1137. }
  1138. //+---------------------------------------------------------------------------
  1139. //
  1140. // Function: HrRefreshAll
  1141. //
  1142. // Purpose: Rebuilds the collection of BindingPathObj and the list view
  1143. //
  1144. // Arguments:
  1145. // hwndList [in] Handle of listview
  1146. // pnc [in] INetCfg being used
  1147. // pnccAdapter [in] INetCfgComponent of the adapter in this connection
  1148. // plistBindingPaths [in/out] The collection of BindingPathObj
  1149. //
  1150. // Returns: S_OK if success, Win32 or OLE error code otherwise
  1151. //
  1152. // Author: tongl 23 Nov 1997
  1153. //
  1154. // Notes:
  1155. //
  1156. HRESULT HrRefreshAll(HWND hwndList,
  1157. INetCfg* pnc,
  1158. INetCfgComponent * pnccAdapter,
  1159. ListBPObj * plistBindingPaths)
  1160. {
  1161. HRESULT hr = S_OK;
  1162. ReleaseAll(hwndList, plistBindingPaths);
  1163. hr = HrRebuildBindingPathObjCollection( pnccAdapter,
  1164. plistBindingPaths);
  1165. if SUCCEEDED(hr)
  1166. {
  1167. // Set the correct state on the BindingPathObject list
  1168. hr = HrRefreshBindingPathObjCollectionState(plistBindingPaths);
  1169. if SUCCEEDED(hr)
  1170. {
  1171. // Now refresh the list to reflect changes
  1172. hr = HrRefreshListView(hwndList, pnc, pnccAdapter, plistBindingPaths);
  1173. }
  1174. }
  1175. // $REVIEW(tongl 12\16\97): added so we always have a selection.
  1176. // Caller of this function can reset selection if they need to.
  1177. if (SUCCEEDED(hr))
  1178. {
  1179. // Selete the first item
  1180. ListView_SetItemState(hwndList, 0, LVIS_SELECTED, LVIS_SELECTED);
  1181. }
  1182. TraceError("HrRefreshAll", hr);
  1183. return hr;
  1184. }
  1185. //+---------------------------------------------------------------------------
  1186. //
  1187. // Function: ReleaseAll
  1188. //
  1189. // Purpose: Releases the INetCfgComponent and INetCfgBindingPath objects
  1190. //
  1191. // Arguments:
  1192. // hwndList [in] Handle of listview
  1193. // plistBindingPaths [in/out] The collection of BindingPathObj
  1194. //
  1195. // Author: tongl 18 Mar, 1998
  1196. //
  1197. // Notes:
  1198. //
  1199. VOID ReleaseAll(HWND hwndList,
  1200. ListBPObj * plistBindingPaths)
  1201. {
  1202. // first, clean up any existing objects in the list
  1203. FreeCollectionAndItem(*plistBindingPaths);
  1204. // delete existing items in the list view
  1205. ListView_DeleteAllItems( hwndList );
  1206. }
  1207. //+---------------------------------------------------------------------------
  1208. //
  1209. // Function: FValidatePageContents
  1210. //
  1211. // Purpose: Check error conditions before LAN property or wizard page
  1212. // exits
  1213. //
  1214. // Arguments:
  1215. // hwndDlg [in] Handle of dialog
  1216. // hwndList [in] Handle of the list view
  1217. // pnc [in] INetCfg
  1218. // pnccAdapter [in] INetCfgComponent
  1219. // plistBindignPaths [in] List of binding paths to this adater
  1220. //
  1221. // Returns: TRUE if there is a possible error and user wants to fix
  1222. // it before leaving the page. FALSE if no error or user
  1223. // chooses to move on.
  1224. //
  1225. // Author: tongl 17 Sept 1998
  1226. //
  1227. // Notes:
  1228. //
  1229. BOOL FValidatePageContents( HWND hwndDlg,
  1230. HWND hwndList,
  1231. INetCfg * pnc,
  1232. INetCfgComponent * pnccAdapter,
  1233. ListBPObj * plistBindingPaths)
  1234. {
  1235. HRESULT hr = S_OK;
  1236. // 1) Check if any protocol is enabled on this adapter
  1237. BOOL fEnabledProtocolExists = FALSE;
  1238. CIterNetCfgComponent iterProt(pnc, &GUID_DEVCLASS_NETTRANS);
  1239. INetCfgComponent* pnccTrans;
  1240. while (SUCCEEDED(hr) && !fEnabledProtocolExists &&
  1241. S_OK == (hr = iterProt.HrNext(&pnccTrans)))
  1242. {
  1243. HRESULT hrTmp;
  1244. INetCfgComponentBindings * pnccb;
  1245. hrTmp = pnccTrans->QueryInterface (
  1246. IID_INetCfgComponentBindings, (LPVOID*)&pnccb);
  1247. if (S_OK == hrTmp)
  1248. {
  1249. hrTmp = pnccb->IsBindableTo(pnccAdapter);
  1250. if (S_OK == hrTmp)
  1251. {
  1252. fEnabledProtocolExists = TRUE;
  1253. }
  1254. ReleaseObj(pnccb);
  1255. }
  1256. ReleaseObj(pnccTrans);
  1257. }
  1258. if (!fEnabledProtocolExists)
  1259. {
  1260. // warn the user
  1261. int nRet = NcMsgBox(
  1262. _Module.GetResourceInstance(),
  1263. hwndDlg,
  1264. IDS_LANUI_NOPROTOCOL_CAPTION,
  1265. IDS_LANUI_NOPROTOCOL,
  1266. MB_APPLMODAL|MB_ICONINFORMATION|MB_YESNO
  1267. );
  1268. if (nRet == IDYES)
  1269. {
  1270. return TRUE;
  1271. }
  1272. }
  1273. // 2) Check if any component on the display list is in an intent check state
  1274. // If so, it means these components are actually disabled and will not be
  1275. // displayed as checked the next time the UI is refreshed.
  1276. tstring strCompList = c_szEmpty;
  1277. // for each item in the list view
  1278. int nlvCount = ListView_GetItemCount(hwndList);
  1279. LV_ITEM lvItem;
  1280. for (int i=0; i< nlvCount; i++)
  1281. {
  1282. lvItem.iItem = i;
  1283. lvItem.iSubItem = 0;
  1284. lvItem.mask = LVIF_PARAM;
  1285. if (ListView_GetItem(hwndList, &lvItem))
  1286. {
  1287. NET_ITEM_DATA * pnid;
  1288. pnid = reinterpret_cast<NET_ITEM_DATA *>(lvItem.lParam);
  1289. if (pnid)
  1290. {
  1291. // get the component object associated with this item
  1292. CComponentObj * pCompObj = pnid->pCompObj;
  1293. if (pCompObj)
  1294. {
  1295. if (INTENT_CHECKED == pCompObj->m_CheckState)
  1296. {
  1297. PWSTR pszwName;
  1298. hr = pCompObj->m_pncc->GetDisplayName(&pszwName);
  1299. if (SUCCEEDED(hr))
  1300. {
  1301. if (!strCompList.empty())
  1302. strCompList += SzLoadIds(IDS_NEWLINE);
  1303. strCompList += pszwName;
  1304. delete pszwName;
  1305. }
  1306. }
  1307. }
  1308. }
  1309. }
  1310. }
  1311. if (!strCompList.empty())
  1312. {
  1313. // warn the user
  1314. int nRet = NcMsgBox(
  1315. _Module.GetResourceInstance(),
  1316. hwndDlg,
  1317. IDS_LANUI_ERROR_CAPTION,
  1318. IDS_LANUI_INTENTCHECK,
  1319. MB_APPLMODAL|MB_ICONINFORMATION|MB_YESNO,
  1320. strCompList.c_str());
  1321. if (nRet == IDNO)
  1322. {
  1323. hr = HrRefreshAll(hwndList, pnc, pnccAdapter, plistBindingPaths);
  1324. return TRUE;
  1325. }
  1326. }
  1327. return FALSE;
  1328. }
  1329. //+---------------------------------------------------------------------------
  1330. //
  1331. // EAPOL related util functions
  1332. //
  1333. //+---------------------------------------------------------------------------
  1334. // Location of EAPOL Parameters Service
  1335. static WCHAR cszEapKeyEapolServiceParams[] = L"Software\\Microsoft\\EAPOL\\Parameters\\General" ;
  1336. static WCHAR cszInterfaceList[] = L"InterfaceList";
  1337. //+---------------------------------------------------------------------------
  1338. //
  1339. // Function called to retrieve the connection data for an interface for a
  1340. // specific EAP type and SSID (if any). Data is stored in the HKLM hive
  1341. //
  1342. // Input arguments:
  1343. // pwszGUID - GUID string for the interface
  1344. // dwEapTypeId - EAP type for which connection data is to be stored
  1345. // dwSizeOfSSID - Size of Special identifier if any for the EAP blob
  1346. // pwszSSID - Special identifier if any for the EAP blob
  1347. //
  1348. // Return values:
  1349. // pbConnInfo - pointer to binary EAP connection data blob
  1350. // dwInfoSize - pointer to size of EAP connection blob
  1351. //
  1352. //
  1353. HRESULT
  1354. HrElGetCustomAuthData (
  1355. IN WCHAR *pwszGUID,
  1356. IN DWORD dwEapTypeId,
  1357. IN DWORD dwSizeOfSSID,
  1358. IN BYTE *pbSSID,
  1359. IN OUT BYTE *pbConnInfo,
  1360. IN OUT DWORD *pdwInfoSize
  1361. )
  1362. {
  1363. DWORD dwRetCode = ERROR_SUCCESS;
  1364. HRESULT hr = S_OK;
  1365. do
  1366. {
  1367. dwRetCode = WZCEapolGetCustomAuthData (
  1368. NULL,
  1369. pwszGUID,
  1370. dwEapTypeId,
  1371. dwSizeOfSSID,
  1372. pbSSID,
  1373. pbConnInfo,
  1374. pdwInfoSize
  1375. );
  1376. if (dwRetCode == ERROR_BUFFER_TOO_SMALL)
  1377. {
  1378. hr = E_OUTOFMEMORY;
  1379. dwRetCode = ERROR_SUCCESS;
  1380. }
  1381. } while (FALSE);
  1382. if (dwRetCode != ERROR_SUCCESS)
  1383. {
  1384. hr = HRESULT_FROM_WIN32(dwRetCode);
  1385. }
  1386. return hr;
  1387. }
  1388. //+---------------------------------------------------------------------------
  1389. //
  1390. // Function called to set the connection data for an interface for a specific
  1391. // EAP type and SSID (if any). Data will be stored in the HKLM hive
  1392. //
  1393. // Input arguments:
  1394. // pwszGUID - pinter to GUID string for the interface
  1395. // dwEapTypeId - EAP type for which connection data is to be stored
  1396. // dwSizeOfSSID - Size of Special identifier if any for the EAP blob
  1397. // pwszSSID - Special identifier if any for the EAP blob
  1398. // pbConnInfo - pointer to binary EAP connection data blob
  1399. // dwInfoSize - Size of EAP connection blob
  1400. //
  1401. // Return values:
  1402. //
  1403. HRESULT
  1404. HrElSetCustomAuthData (
  1405. IN WCHAR *pwszGUID,
  1406. IN DWORD dwEapTypeId,
  1407. IN DWORD dwSizeOfSSID,
  1408. IN BYTE *pbSSID,
  1409. IN PBYTE pbConnInfo,
  1410. IN DWORD dwInfoSize
  1411. )
  1412. {
  1413. DWORD dwRetCode = ERROR_SUCCESS;
  1414. HRESULT hr = S_OK;
  1415. do
  1416. {
  1417. dwRetCode = WZCEapolSetCustomAuthData (
  1418. NULL,
  1419. pwszGUID,
  1420. dwEapTypeId,
  1421. dwSizeOfSSID,
  1422. pbSSID,
  1423. pbConnInfo,
  1424. dwInfoSize
  1425. );
  1426. } while (FALSE);
  1427. if (dwRetCode != ERROR_SUCCESS)
  1428. {
  1429. hr = HRESULT_FROM_WIN32(dwRetCode);
  1430. }
  1431. return hr;
  1432. }
  1433. //+---------------------------------------------------------------------------
  1434. //
  1435. // Function called to retrieve the EAPOL parameters for an interface
  1436. //
  1437. // Input arguments:
  1438. // pwszGUID - GUID string for the interface
  1439. //
  1440. // Return values:
  1441. // pdwDefaultEAPType - default EAP type for interface
  1442. // pIntfParams - Interface parameters
  1443. //
  1444. HRESULT
  1445. HrElGetInterfaceParams (
  1446. IN WCHAR *pwszGUID,
  1447. IN OUT EAPOL_INTF_PARAMS *pIntfParams
  1448. )
  1449. {
  1450. DWORD dwRetCode = ERROR_SUCCESS;
  1451. HRESULT hr = S_OK;
  1452. do
  1453. {
  1454. dwRetCode = WZCEapolGetInterfaceParams (
  1455. NULL,
  1456. pwszGUID,
  1457. pIntfParams
  1458. );
  1459. } while (FALSE);
  1460. if (dwRetCode != ERROR_SUCCESS)
  1461. {
  1462. hr = HRESULT_FROM_WIN32(dwRetCode);
  1463. }
  1464. return hr;
  1465. }
  1466. //+---------------------------------------------------------------------------
  1467. //
  1468. // Function called to set the EAPOL parameters for an interface
  1469. //
  1470. // Input arguments:
  1471. // pwszGUID - GUID string for the interface
  1472. // pIntfParams - Interface parameters
  1473. //
  1474. // Return values:
  1475. //
  1476. HRESULT
  1477. HrElSetInterfaceParams (
  1478. IN WCHAR *pwszGUID,
  1479. IN EAPOL_INTF_PARAMS *pIntfParams
  1480. )
  1481. {
  1482. DWORD dwRetCode = ERROR_SUCCESS;
  1483. HRESULT hr = S_OK;
  1484. do
  1485. {
  1486. dwRetCode = WZCEapolSetInterfaceParams (
  1487. NULL,
  1488. pwszGUID,
  1489. pIntfParams
  1490. );
  1491. } while (FALSE);
  1492. if (dwRetCode != ERROR_SUCCESS)
  1493. {
  1494. hr = HRESULT_FROM_WIN32(dwRetCode);
  1495. }
  1496. return hr;
  1497. }
  1498. //+---------------------------------------------------------------------------
  1499. //
  1500. // Set selection in listbox 'hwndLb' to 'nIndex' and notify parent as if
  1501. // user had clicked the item which Windows doesn't do for some reason.
  1502. //
  1503. VOID
  1504. ComboBox_SetCurSelNotify (
  1505. IN HWND hwndLb,
  1506. IN INT nIndex
  1507. )
  1508. {
  1509. ComboBox_SetCurSel( hwndLb, nIndex );
  1510. SendMessage(
  1511. GetParent( hwndLb ),
  1512. WM_COMMAND,
  1513. (WPARAM )MAKELONG(
  1514. (WORD )GetDlgCtrlID( hwndLb ), (WORD )CBN_SELCHANGE ),
  1515. (LPARAM )hwndLb );
  1516. }
  1517. //+---------------------------------------------------------------------------
  1518. //
  1519. // Set the width of the drop-down list 'hwndLb' to the width of the
  1520. // longest item (or the width of the list box if that's wider).
  1521. //
  1522. VOID
  1523. ComboBox_AutoSizeDroppedWidth (
  1524. IN HWND hwndLb
  1525. )
  1526. {
  1527. HDC hdc;
  1528. HFONT hfont;
  1529. TCHAR* psz;
  1530. SIZE size;
  1531. DWORD cch;
  1532. DWORD dxNew;
  1533. DWORD i;
  1534. hfont = (HFONT )SendMessage( hwndLb, WM_GETFONT, 0, 0 );
  1535. if (!hfont)
  1536. return;
  1537. hdc = GetDC( hwndLb );
  1538. if (!hdc)
  1539. return;
  1540. SelectObject( hdc, hfont );
  1541. dxNew = 0;
  1542. for (i = 0; psz = ComboBox_GetPsz( hwndLb, i ); ++i)
  1543. {
  1544. cch = lstrlen( psz );
  1545. if (GetTextExtentPoint32( hdc, psz, cch, &size ))
  1546. {
  1547. if (dxNew < (DWORD )size.cx)
  1548. dxNew = (DWORD )size.cx;
  1549. }
  1550. free ( psz );
  1551. }
  1552. ReleaseDC( hwndLb, hdc );
  1553. // Allow for the spacing on left and right added by the control.
  1554. dxNew += 6;
  1555. // Figure out if the vertical scrollbar will be displayed and, if so,
  1556. // allow for it's width.
  1557. {
  1558. RECT rectD;
  1559. RECT rectU;
  1560. DWORD dyItem;
  1561. DWORD cItemsInDrop;
  1562. DWORD cItemsInList;
  1563. GetWindowRect( hwndLb, &rectU );
  1564. SendMessage( hwndLb, CB_GETDROPPEDCONTROLRECT, 0, (LPARAM )&rectD );
  1565. dyItem = (DWORD)SendMessage( hwndLb, CB_GETITEMHEIGHT, 0, 0 );
  1566. cItemsInDrop = (rectD.bottom - rectU.bottom) / dyItem;
  1567. cItemsInList = ComboBox_GetCount( hwndLb );
  1568. if (cItemsInDrop < cItemsInList)
  1569. dxNew += GetSystemMetrics( SM_CXVSCROLL );
  1570. }
  1571. SendMessage( hwndLb, CB_SETDROPPEDWIDTH, dxNew, 0 );
  1572. }
  1573. //+---------------------------------------------------------------------------
  1574. //
  1575. // Adds data item 'pItem' with displayed text 'pszText' to listbox
  1576. // 'hwndLb'. The item is added sorted if the listbox has LBS_SORT style,
  1577. // or to the end of the list otherwise. If the listbox has LB_HASSTRINGS
  1578. // style, 'pItem' is a null terminated string, otherwise it is any user
  1579. // defined data.
  1580. //
  1581. // Returns the index of the item in the list or negative if error.
  1582. //
  1583. INT
  1584. ComboBox_AddItem(
  1585. IN HWND hwndLb,
  1586. IN LPCTSTR pszText,
  1587. IN VOID* pItem
  1588. )
  1589. {
  1590. INT nIndex;
  1591. nIndex = ComboBox_AddString( hwndLb, pszText );
  1592. if (nIndex >= 0)
  1593. ComboBox_SetItemData( hwndLb, nIndex, pItem );
  1594. return nIndex;
  1595. }
  1596. //+---------------------------------------------------------------------------
  1597. //
  1598. // Returns the address of the 'nIndex'th item context in 'hwndLb' or NULL
  1599. // if none.
  1600. //
  1601. VOID*
  1602. ComboBox_GetItemDataPtr (
  1603. IN HWND hwndLb,
  1604. IN INT nIndex
  1605. )
  1606. {
  1607. LRESULT lResult;
  1608. if (nIndex < 0)
  1609. return NULL;
  1610. lResult = ComboBox_GetItemData( hwndLb, nIndex );
  1611. if (lResult < 0)
  1612. return NULL;
  1613. return (VOID* )lResult;
  1614. }
  1615. //+---------------------------------------------------------------------------
  1616. //
  1617. // Returns heap block containing the text contents of the 'nIndex'th item
  1618. // of combo box 'hwnd' or NULL. It is caller's responsibility to Free the
  1619. // returned string.
  1620. //
  1621. TCHAR*
  1622. ComboBox_GetPsz (
  1623. IN HWND hwnd,
  1624. IN INT nIndex
  1625. )
  1626. {
  1627. INT cch;
  1628. TCHAR* psz;
  1629. cch = ComboBox_GetLBTextLen( hwnd, nIndex );
  1630. if (cch < 0)
  1631. return NULL;
  1632. psz = new TCHAR[( cch + 1)];
  1633. if (psz)
  1634. {
  1635. *psz = TEXT('\0');
  1636. ComboBox_GetLBText( hwnd, nIndex, psz );
  1637. }
  1638. return psz;
  1639. }
  1640. static WCHAR WZCSVC_SERVICE_NAME[] = L"WZCSVC";
  1641. //+---------------------------------------------------------------------------
  1642. //
  1643. // ElCanEapolRunOnInterface:
  1644. //
  1645. // Function to verify if EAPOL can ever be started on an interface
  1646. //
  1647. // Returns TRUE if:
  1648. // WZCSVC service is running and WZCSVC has bound to the interface
  1649. //
  1650. //
  1651. BOOL
  1652. ElCanEapolRunOnInterface (
  1653. IN INetConnection *pconn
  1654. )
  1655. {
  1656. SC_HANDLE hServiceCM = NULL;
  1657. SC_HANDLE hWZCSVCService = NULL;
  1658. SERVICE_STATUS WZCSVCServiceStatus;
  1659. WCHAR wszGuid[c_cchGuidWithTerm];
  1660. NETCON_PROPERTIES* pProps = NULL;
  1661. BOOL fIsOK = TRUE;
  1662. DWORD dwType = 0;
  1663. DWORD dwSizeOfList = 0;
  1664. WCHAR *pwszRegInterfaceList = NULL;
  1665. DWORD dwDisposition = 0;
  1666. HKEY hkey = NULL;
  1667. EAPOL_INTF_PARAMS EapolIntfParams;
  1668. LONG lError = ERROR_SUCCESS;
  1669. DWORD dwRetCode = NO_ERROR;
  1670. HRESULT hr = S_OK;
  1671. do
  1672. {
  1673. //
  1674. // Query status of WZCSVC service
  1675. // Do not display tab if WZCSVC service is not running
  1676. //
  1677. if ((hServiceCM = OpenSCManager ( NULL, NULL, GENERIC_READ ))
  1678. == NULL)
  1679. {
  1680. dwRetCode = GetLastError ();
  1681. TraceTag (ttidLanUi, "ElCanEapolRunOnInterface: OpenSCManager failed with error %ld",
  1682. dwRetCode);
  1683. fIsOK = FALSE;
  1684. break;
  1685. }
  1686. if ((hWZCSVCService =
  1687. OpenService ( hServiceCM, WZCSVC_SERVICE_NAME, GENERIC_READ ))
  1688. == NULL)
  1689. {
  1690. dwRetCode = GetLastError ();
  1691. TraceTag (ttidLanUi, "ElCanEapolRunOnInterface: OpenService failed with error %ld",
  1692. dwRetCode);
  1693. fIsOK = FALSE;
  1694. break;
  1695. }
  1696. if (!QueryServiceStatus ( hWZCSVCService, &WZCSVCServiceStatus ))
  1697. {
  1698. dwRetCode = GetLastError ();
  1699. TraceTag (ttidLanUi, "ElCanEapolRunOnInterface: StartService failed with error %ld",
  1700. dwRetCode);
  1701. fIsOK = FALSE;
  1702. break;
  1703. }
  1704. if ( WZCSVCServiceStatus.dwCurrentState != SERVICE_RUNNING )
  1705. {
  1706. TraceTag (ttidLanUi, "ElCanEapolRunOnInterface: WZCSVC service not running !!!");
  1707. fIsOK = FALSE;
  1708. break;
  1709. }
  1710. TraceTag (ttidLanUi, "ElCanEapolRunOnInterface: WZCSVC service is indeed running !!!");
  1711. if (!CloseServiceHandle ( hWZCSVCService ))
  1712. {
  1713. dwRetCode = GetLastError ();
  1714. TraceTag (ttidLanUi, "ElCanEapolRunOnInterface: CloseService failed with error %ld",
  1715. dwRetCode);
  1716. fIsOK = FALSE;
  1717. break;
  1718. }
  1719. hWZCSVCService = NULL;
  1720. if (!CloseServiceHandle ( hServiceCM ))
  1721. {
  1722. dwRetCode = GetLastError ();
  1723. TraceTag (ttidLanUi, "ElCanEapolRunOnInterface: CloseService failed with error %ld",
  1724. dwRetCode);
  1725. fIsOK = FALSE;
  1726. break;
  1727. }
  1728. hServiceCM = NULL;
  1729. //
  1730. // Check if NDISUIO is bound to interface
  1731. //
  1732. hr = pconn->GetProperties (&pProps);
  1733. if (SUCCEEDED(hr))
  1734. {
  1735. if (::StringFromGUID2 (pProps->guidId, wszGuid, c_cchGuidWithTerm)
  1736. == 0)
  1737. {
  1738. TraceTag (ttidLanUi, "ElCanEapolRunOnInterface: StringFromGUID2 failed");
  1739. fIsOK = FALSE;
  1740. FreeNetconProperties(pProps);
  1741. break;
  1742. }
  1743. FreeNetconProperties(pProps);
  1744. }
  1745. else
  1746. {
  1747. break;
  1748. }
  1749. // Fetch InterfaceList from registry
  1750. // Search for GUID string in registry
  1751. // Get handle to
  1752. // HKLM\Software\Microsoft\EAPOL\Parameters\Interfaces\General
  1753. hr = HrRegCreateKeyEx (
  1754. HKEY_LOCAL_MACHINE,
  1755. cszEapKeyEapolServiceParams,
  1756. REG_OPTION_NON_VOLATILE,
  1757. KEY_READ,
  1758. NULL,
  1759. &hkey,
  1760. &dwDisposition);
  1761. if (!SUCCEEDED (hr))
  1762. {
  1763. TraceTag (ttidLanUi, "ElCanEapolRunOnInterface: Error in HrRegCreateKeyEx for base key, %ld",
  1764. LresFromHr(hr));
  1765. fIsOK = FALSE;
  1766. break;
  1767. }
  1768. // Query the value of
  1769. // ...\EAPOL\Parameters\Interfaces\General\InterfaceList key
  1770. dwSizeOfList = 0;
  1771. hr = HrRegQueryValueEx (
  1772. hkey,
  1773. cszInterfaceList,
  1774. &dwType,
  1775. NULL,
  1776. &dwSizeOfList);
  1777. if (SUCCEEDED (hr))
  1778. {
  1779. pwszRegInterfaceList = (WCHAR *) new BYTE [dwSizeOfList];
  1780. if (pwszRegInterfaceList == NULL)
  1781. {
  1782. hr = E_OUTOFMEMORY;
  1783. fIsOK = FALSE;
  1784. break;
  1785. }
  1786. hr = HrRegQueryValueEx (
  1787. hkey,
  1788. cszInterfaceList,
  1789. &dwType,
  1790. (LPBYTE)pwszRegInterfaceList,
  1791. &dwSizeOfList);
  1792. if (!SUCCEEDED(hr))
  1793. {
  1794. TraceTag (ttidLanUi, "ElCanEapolRunOnInterface: Error in HrRegQueryValueEx acquiring value for InterfaceList, %ld",
  1795. LresFromHr(hr));
  1796. break;
  1797. }
  1798. TraceTag (ttidLanUi, "ElCanEapolRunOnInterface: Query value succeeded = %ws, size=%ld, search GUID = %ws",
  1799. pwszRegInterfaceList, dwSizeOfList, wszGuid);
  1800. }
  1801. else
  1802. {
  1803. TraceTag (ttidLanUi, "ElCanEapolRunOnInterface: Error in HrRegQueryValueEx size estimation for InterfaceList, %ld",
  1804. LresFromHr(hr));
  1805. fIsOK = FALSE;
  1806. break;
  1807. }
  1808. if (wcsstr (pwszRegInterfaceList, wszGuid))
  1809. {
  1810. TraceTag (ttidLanUi, "ElCanEapolRunOnInterface interface found in interface list !!!");
  1811. }
  1812. else
  1813. {
  1814. TraceTag (ttidLanUi, "ElCanEapolRunOnInterface interface *not* found in interface list !!!");
  1815. fIsOK = FALSE;
  1816. break;
  1817. }
  1818. } while (FALSE);
  1819. if (hkey != NULL)
  1820. {
  1821. RegSafeCloseKey (hkey);
  1822. }
  1823. if (pwszRegInterfaceList != NULL)
  1824. {
  1825. free (pwszRegInterfaceList);
  1826. }
  1827. if (hWZCSVCService != NULL)
  1828. {
  1829. if (!CloseServiceHandle ( hWZCSVCService ))
  1830. {
  1831. dwRetCode = GetLastError ();
  1832. TraceTag (ttidLanUi, "ElCanEapolRunOnInterface: CloseService failed with error %ld",
  1833. dwRetCode);
  1834. }
  1835. }
  1836. if (hServiceCM != NULL)
  1837. {
  1838. if (!CloseServiceHandle ( hServiceCM ))
  1839. {
  1840. dwRetCode = GetLastError ();
  1841. TraceTag (ttidLanUi, "ElCanEapolRunOnInterface: CloseService failed with error %ld",
  1842. dwRetCode);
  1843. }
  1844. }
  1845. return fIsOK;
  1846. }
  1847. #ifdef ENABLETRACE
  1848. //+---------------------------------------------------------------------------
  1849. //
  1850. // Function: PrintBindingPath
  1851. //
  1852. // Purpose: Prints the binding path ID and a list of component IDs on
  1853. // the path from top down
  1854. //
  1855. // Arguments:
  1856. //
  1857. // Returns:
  1858. //
  1859. // Author: tongl 26 Nov 1997
  1860. //
  1861. // Notes:
  1862. //
  1863. VOID PrintBindingPath (
  1864. TRACETAGID ttidToTrace,
  1865. INetCfgBindingPath* pncbp,
  1866. PCSTR pszaExtraText)
  1867. {
  1868. Assert (pncbp);
  1869. if (!pszaExtraText)
  1870. {
  1871. pszaExtraText = "";
  1872. }
  1873. const WCHAR c_szSept[] = L"->";
  1874. tstring strPath;
  1875. INetCfgComponent * pnccNetComponent;
  1876. PWSTR pszwCompId;
  1877. HRESULT hr;
  1878. // Get the top component
  1879. hr = pncbp->GetOwner(&pnccNetComponent);
  1880. if (SUCCEEDED(hr))
  1881. {
  1882. hr = pnccNetComponent->GetId(&pszwCompId);
  1883. if SUCCEEDED(hr)
  1884. {
  1885. strPath += pszwCompId;
  1886. CoTaskMemFree(pszwCompId);
  1887. }
  1888. }
  1889. ReleaseObj(pnccNetComponent);
  1890. // Get Comp ID for other component on the path
  1891. CIterNetCfgBindingInterface ncbiIter(pncbp);
  1892. INetCfgBindingInterface * pncbi;
  1893. //Go through interfaces of the binding path
  1894. while (SUCCEEDED(hr) && (hr = ncbiIter.HrNext(&pncbi)) == S_OK)
  1895. {
  1896. strPath += c_szSept;
  1897. // Get the lower component
  1898. hr = pncbi->GetLowerComponent(&pnccNetComponent);
  1899. if(SUCCEEDED(hr))
  1900. {
  1901. hr = pnccNetComponent->GetId(&pszwCompId);
  1902. if (SUCCEEDED(hr))
  1903. {
  1904. strPath += pszwCompId;
  1905. CoTaskMemFree(pszwCompId);
  1906. }
  1907. }
  1908. ReleaseObj(pnccNetComponent);
  1909. ReleaseObj(pncbi);
  1910. }
  1911. if (hr == S_FALSE) // We just got to the end of the loop
  1912. hr = S_OK;
  1913. BOOL fEnabled = (S_OK == pncbp->IsEnabled());
  1914. // Now print the path and ID
  1915. char szaBuf[1024];
  1916. wsprintfA (szaBuf, "[%s] %S: %s",
  1917. (fEnabled) ? "x" : " ",
  1918. strPath.c_str(),
  1919. pszaExtraText);
  1920. TraceTag (ttidToTrace, szaBuf);
  1921. TraceError ("PrintBindingPath", hr);
  1922. }
  1923. #endif //ENABLETRACE