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.

1995 lines
53 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997.
  5. //
  6. // File: A C T R E E . C P P
  7. //
  8. // Contents: Functions related to the Advanced Configuration dialog
  9. // tree view control
  10. //
  11. // Notes:
  12. //
  13. // Author: danielwe 3 Dec 1997
  14. //
  15. //----------------------------------------------------------------------------
  16. #include "pch.h"
  17. #pragma hdrstop
  18. #include "netcon.h"
  19. #include "netconp.h"
  20. #include "acsheet.h"
  21. #include "acbind.h"
  22. #include "ncnetcfg.h"
  23. #include "lancmn.h"
  24. #include "ncui.h"
  25. #include "ncsetup.h"
  26. #include "ncperms.h"
  27. DWORD
  28. GetDepthSpecialCase (
  29. INetCfgBindingPath* pPath)
  30. {
  31. HRESULT hr;
  32. DWORD dwDepth;
  33. hr = pPath->GetDepth (&dwDepth);
  34. if (SUCCEEDED(hr))
  35. {
  36. INetCfgComponent* pLast;
  37. hr = HrGetLastComponentAndInterface (
  38. pPath, &pLast, NULL);
  39. if (SUCCEEDED(hr))
  40. {
  41. DWORD dwCharacteristics;
  42. // If the last component in the bindpath is one which
  43. // doesn't expose its lower bindings, then compsensate by
  44. // returning a depth that thinks it does. This special case
  45. // is only for this code which was written for the origianl
  46. // binding engine but needed to be quickly adapted to the new
  47. // binding engine which doesn't return 'fake' bindpaths.
  48. //
  49. hr = pLast->GetCharacteristics (&dwCharacteristics);
  50. if (SUCCEEDED(hr) && (dwCharacteristics & NCF_DONTEXPOSELOWER))
  51. {
  52. PWSTR pszInfId;
  53. hr = pLast->GetId (&pszInfId);
  54. if (S_OK == hr)
  55. {
  56. if (0 == lstrcmpW (pszInfId, L"ms_nwnb"))
  57. {
  58. dwDepth += 2;
  59. }
  60. else if (0 == lstrcmpW (pszInfId, L"ms_nwipx"))
  61. {
  62. dwDepth += 1;
  63. }
  64. CoTaskMemFree (pszInfId);
  65. }
  66. }
  67. ReleaseObj (pLast);
  68. }
  69. }
  70. return dwDepth;
  71. }
  72. //+---------------------------------------------------------------------------
  73. //
  74. // Function: FreeBindPathInfoList
  75. //
  76. // Purpose: Frees the given list of BIND_PATH_INFO structures
  77. //
  78. // Arguments:
  79. // listbpip [in, ref] Reference to list to be freed
  80. //
  81. // Returns: Nothing
  82. //
  83. // Author: danielwe 26 Nov 1997
  84. //
  85. // Notes:
  86. //
  87. VOID FreeBindPathInfoList(BPIP_LIST &listbpip)
  88. {
  89. BPIP_LIST::iterator iterBpip;
  90. for (iterBpip = listbpip.begin();
  91. iterBpip != listbpip.end();
  92. iterBpip++)
  93. {
  94. BIND_PATH_INFO * pbpi = *iterBpip;
  95. ReleaseObj(pbpi->pncbp);
  96. delete pbpi;
  97. }
  98. listbpip.erase(listbpip.begin(), listbpip.end());
  99. }
  100. //+---------------------------------------------------------------------------
  101. //
  102. // Member: CBindingsDlg::OnTreeItemChanged
  103. //
  104. // Purpose: Called in response to the TVN_SELCHANGED message
  105. //
  106. // Arguments:
  107. // idCtrl []
  108. // pnmh []
  109. // bHandled []
  110. //
  111. // Returns:
  112. //
  113. // Author: danielwe 26 Nov 1997
  114. //
  115. // Notes:
  116. //
  117. LRESULT CBindingsDlg::OnTreeItemChanged(int idCtrl, LPNMHDR pnmh,
  118. BOOL& bHandled)
  119. {
  120. NM_TREEVIEW * pnmtv = reinterpret_cast<NM_TREEVIEW *>(pnmh);
  121. Assert(pnmtv);
  122. #ifdef ENABLETRACE
  123. WCHAR szBuffer[265];
  124. pnmtv->itemNew.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_TEXT;
  125. pnmtv->itemNew.pszText = szBuffer;
  126. pnmtv->itemNew.cchTextMax = celems(szBuffer);
  127. TreeView_GetItem(m_hwndTV, &pnmtv->itemNew);
  128. TREE_ITEM_DATA * ptid;
  129. ptid = reinterpret_cast<TREE_ITEM_DATA *>(pnmtv->itemNew.lParam);
  130. Assert(ptid);
  131. TraceTag(ttidAdvCfg, "*-------------------------------------------------"
  132. "------------------------------*");
  133. TraceTag(ttidAdvCfg, "Tree item %S selected", szBuffer);
  134. TraceTag(ttidAdvCfg, "-----------------------------------------");
  135. TraceTag(ttidAdvCfg, "OnEnable list:");
  136. TraceTag(ttidAdvCfg, "--------------");
  137. BPIP_LIST::iterator iterBpip;
  138. for (iterBpip = ptid->listbpipOnEnable.begin();
  139. iterBpip != ptid->listbpipOnEnable.end();
  140. iterBpip++)
  141. {
  142. BIND_PATH_INFO * pbpi = *iterBpip;
  143. DbgDumpBindPath(pbpi->pncbp);
  144. }
  145. TraceTag(ttidAdvCfg, "-----------------------------------");
  146. TraceTag(ttidAdvCfg, "OnDisable list:");
  147. TraceTag(ttidAdvCfg, "--------------");
  148. for (iterBpip = ptid->listbpipOnDisable.begin();
  149. iterBpip != ptid->listbpipOnDisable.end();
  150. iterBpip++)
  151. {
  152. BIND_PATH_INFO * pbpi = *iterBpip;
  153. DbgDumpBindPath(pbpi->pncbp);
  154. }
  155. TraceTag(ttidAdvCfg, "*-------------------------------------------------"
  156. "------------------------------*");
  157. #endif
  158. // Assume both buttons are greyed initially
  159. ::EnableWindow(GetDlgItem(PSB_Binding_Up), FALSE);
  160. ::EnableWindow(GetDlgItem(PSB_Binding_Down), FALSE);
  161. if (TreeView_GetParent(m_hwndTV, pnmtv->itemNew.hItem))
  162. {
  163. if (TreeView_GetNextSibling(m_hwndTV, pnmtv->itemNew.hItem))
  164. {
  165. ::EnableWindow(GetDlgItem(PSB_Binding_Down), TRUE);
  166. }
  167. if (TreeView_GetPrevSibling(m_hwndTV, pnmtv->itemNew.hItem))
  168. {
  169. ::EnableWindow(GetDlgItem(PSB_Binding_Up), TRUE);
  170. }
  171. }
  172. return 0;
  173. }
  174. //+---------------------------------------------------------------------------
  175. //
  176. // Member: CBindingsDlg::OnTreeDeleteItem
  177. //
  178. // Purpose: Called in response to the TVN_DELETEITEM message
  179. //
  180. // Arguments:
  181. // idCtrl []
  182. // pnmh []
  183. // bHandled []
  184. //
  185. // Returns: Nothing useful
  186. //
  187. // Author: danielwe 26 Nov 1997
  188. //
  189. // Notes:
  190. //
  191. LRESULT CBindingsDlg::OnTreeDeleteItem(int idCtrl, LPNMHDR pnmh,
  192. BOOL& bHandled)
  193. {
  194. NM_TREEVIEW * pnmtv = reinterpret_cast<NM_TREEVIEW *>(pnmh);
  195. TREE_ITEM_DATA * ptid;
  196. Assert(pnmtv);
  197. ptid = reinterpret_cast<TREE_ITEM_DATA *>(pnmtv->itemOld.lParam);
  198. // May be NULL if moving items around
  199. if (ptid)
  200. {
  201. ReleaseObj(ptid->pncc);
  202. FreeBindPathInfoList(ptid->listbpipOnEnable);
  203. FreeBindPathInfoList(ptid->listbpipOnDisable);
  204. delete ptid;
  205. }
  206. return FALSE;
  207. }
  208. //+---------------------------------------------------------------------------
  209. //
  210. // Member: CBindingsDlg::OnTreeItemExpanding
  211. //
  212. // Purpose: Called when the TVN_ITEMEXPANDING message is received
  213. //
  214. // Arguments:
  215. // idCtrl []
  216. // pnmh []
  217. // bHandled []
  218. //
  219. // Returns:
  220. //
  221. // Author: danielwe 26 Nov 1997
  222. //
  223. // Notes:
  224. //
  225. LRESULT CBindingsDlg::OnTreeItemExpanding(int idCtrl, LPNMHDR pnmh,
  226. BOOL& bHandled)
  227. {
  228. // This prevents all tree items from collapsing
  229. return TRUE;
  230. }
  231. //+---------------------------------------------------------------------------
  232. //
  233. // Member: CBindingsDlg::OnTreeKeyDown
  234. //
  235. // Purpose: Called when the TVN_KEYDOWN message is received
  236. //
  237. // Arguments:
  238. // idCtrl []
  239. // pnmh []
  240. // fHandled []
  241. //
  242. // Returns:
  243. //
  244. // Author: danielwe 22 Dec 1997
  245. //
  246. // Notes:
  247. //
  248. LRESULT CBindingsDlg::OnTreeKeyDown(int idCtrl, LPNMHDR pnmh, BOOL& fHandled)
  249. {
  250. TV_KEYDOWN * ptvkd = (TV_KEYDOWN*)pnmh;
  251. HTREEITEM hti = NULL;
  252. if (VK_SPACE == ptvkd->wVKey)
  253. {
  254. hti = TreeView_GetSelection(m_hwndTV);
  255. // if there is a selection
  256. if (hti)
  257. {
  258. ToggleCheckbox(hti);
  259. }
  260. }
  261. return TRUE;
  262. }
  263. //+---------------------------------------------------------------------------
  264. //
  265. // Member: CBindingsDlg::ToggleCheckbox
  266. //
  267. // Purpose: Called when the user toggles a checbox in the treeview
  268. // control.
  269. //
  270. // Arguments:
  271. // hti [in] HTREEITEM of item that was toggled
  272. //
  273. // Returns: Nothing
  274. //
  275. // Author: danielwe 26 Nov 1997
  276. //
  277. // Notes:
  278. //
  279. VOID CBindingsDlg::ToggleCheckbox(HTREEITEM hti)
  280. {
  281. if (!FHasPermission(NCPERM_ChangeBindState))
  282. {
  283. // do nothing
  284. return;
  285. }
  286. TV_ITEM tvi = {0};
  287. TREE_ITEM_DATA * ptid;
  288. BOOL fEnable;
  289. tvi.mask = TVIF_PARAM | TVIF_HANDLE | TVIF_STATE;
  290. tvi.stateMask = TVIS_STATEIMAGEMASK;
  291. tvi.hItem = hti;
  292. TreeView_GetItem(m_hwndTV, &tvi);
  293. ptid = reinterpret_cast<TREE_ITEM_DATA *>(tvi.lParam);
  294. AssertSz(ptid, "No tree item data??");
  295. BPIP_LIST::iterator iterBpip;
  296. BPIP_LIST * plist;
  297. if (tvi.state & INDEXTOSTATEIMAGEMASK(SELS_CHECKED))
  298. {
  299. // unchecking the box
  300. plist = &ptid->listbpipOnDisable;
  301. fEnable = FALSE;
  302. }
  303. else
  304. {
  305. // checking the box
  306. plist = &ptid->listbpipOnEnable;
  307. fEnable = TRUE;
  308. }
  309. TraceTag(ttidAdvCfg, "ToggleChecbox: %s the following binding path(s)",
  310. fEnable ? "Enabling" : "Disabling");
  311. // Enable or disable each binding path in the appropriate list
  312. for (iterBpip = plist->begin();
  313. iterBpip != plist->end();
  314. iterBpip++)
  315. {
  316. BIND_PATH_INFO * pbpi = *iterBpip;
  317. (VOID)pbpi->pncbp->Enable(fEnable);
  318. DbgDumpBindPath(pbpi->pncbp);
  319. }
  320. SetCheckboxStates();
  321. TraceTag(ttidAdvCfg, "Done!");
  322. }
  323. //+---------------------------------------------------------------------------
  324. //
  325. // Member: CBindingsDlg::OnClick
  326. //
  327. // Purpose: Called in response to the NM_CLICK message.
  328. //
  329. // Arguments:
  330. // idCtrl []
  331. // pnmh []
  332. // fHandled []
  333. //
  334. // Returns:
  335. //
  336. // Author: danielwe 26 Nov 1997
  337. //
  338. // Notes:
  339. //
  340. LRESULT CBindingsDlg::OnClick(int idCtrl, LPNMHDR pnmh, BOOL& fHandled)
  341. {
  342. return OnClickOrDoubleClick(idCtrl, pnmh, FALSE);
  343. }
  344. //+---------------------------------------------------------------------------
  345. //
  346. // Member: CBindingsDlg::OnDoubleClick
  347. //
  348. // Purpose: Called in response to the NM_DBLCLK message.
  349. //
  350. // Arguments:
  351. // idCtrl []
  352. // pnmh []
  353. // fHandled []
  354. //
  355. // Returns:
  356. //
  357. // Author: danielwe 16 Dec 1997
  358. //
  359. // Notes:
  360. //
  361. LRESULT CBindingsDlg::OnDoubleClick(int idCtrl, LPNMHDR pnmh, BOOL& fHandled)
  362. {
  363. return OnClickOrDoubleClick(idCtrl, pnmh, TRUE);
  364. }
  365. //+---------------------------------------------------------------------------
  366. //
  367. // Member: CBindingsDlg::OnClickOrDoubleClick
  368. //
  369. // Purpose: Handles clicks or double clicks in the treeview control
  370. //
  371. // Arguments:
  372. // idCtrl [in] ID of control
  373. // pnmh [in] Notification header
  374. // fDoubleClick [in] TRUE if double click, FALSE if single click
  375. //
  376. // Returns:
  377. //
  378. // Author: danielwe 16 Dec 1997
  379. //
  380. // Notes:
  381. //
  382. LRESULT CBindingsDlg::OnClickOrDoubleClick(int idCtrl, LPNMHDR pnmh,
  383. BOOL fDoubleClick)
  384. {
  385. if (idCtrl == TVW_Bindings)
  386. {
  387. DWORD dwpts;
  388. RECT rc;
  389. TV_HITTESTINFO tvhti = {0};
  390. HTREEITEM hti;
  391. // we have the location
  392. dwpts = GetMessagePos();
  393. // translate it relative to the tree view
  394. ::GetWindowRect(m_hwndTV, &rc);
  395. tvhti.pt.x = LOWORD(dwpts) - rc.left;
  396. tvhti.pt.y = HIWORD(dwpts) - rc.top;
  397. // get currently selected item
  398. hti = TreeView_HitTest(m_hwndTV, &tvhti);
  399. if (hti)
  400. {
  401. if (tvhti.flags & TVHT_ONITEMSTATEICON)
  402. {
  403. ToggleCheckbox(hti);
  404. }
  405. else if ((tvhti.flags & TVHT_ONITEM) && fDoubleClick)
  406. {
  407. ToggleCheckbox(hti);
  408. }
  409. }
  410. }
  411. return FALSE;
  412. }
  413. //+---------------------------------------------------------------------------
  414. //
  415. // Member: CBindingsDlg::OnBindingUpDown
  416. //
  417. // Purpose: Handles the user moving a binding in the treeview up or down
  418. //
  419. // Arguments:
  420. // fUp [in] TRUE if moving up, FALSE if down
  421. //
  422. // Returns: Nothing
  423. //
  424. // Author: danielwe 3 Dec 1997
  425. //
  426. // Notes:
  427. //
  428. VOID CBindingsDlg::OnBindingUpDown(BOOL fUp)
  429. {
  430. HRESULT hr = S_OK;
  431. TV_ITEM tvi = {0};
  432. HTREEITEM htiSel;
  433. HTREEITEM htiDst;
  434. TREE_ITEM_DATA * ptidSel;
  435. TREE_ITEM_DATA * ptidDst;
  436. INetCfgComponentBindings * pnccb;
  437. htiSel = TreeView_GetSelection(m_hwndTV);
  438. AssertSz(htiSel, "No selection?");
  439. if (fUp)
  440. {
  441. htiDst = TreeView_GetPrevSibling(m_hwndTV, htiSel);
  442. }
  443. else
  444. {
  445. htiDst = TreeView_GetNextSibling(m_hwndTV, htiSel);
  446. }
  447. AssertSz(htiDst, "No next item?!");
  448. tvi.mask = TVIF_PARAM;
  449. tvi.hItem = htiSel;
  450. TreeView_GetItem(m_hwndTV, &tvi);
  451. ptidSel = reinterpret_cast<TREE_ITEM_DATA *>(tvi.lParam);
  452. tvi.hItem = htiDst;
  453. TreeView_GetItem(m_hwndTV, &tvi);
  454. ptidDst = reinterpret_cast<TREE_ITEM_DATA *>(tvi.lParam);
  455. BPIP_LIST::iterator iterlist;
  456. INetCfgBindingPath * pncbpDst;
  457. BIND_PATH_INFO * pbpiDst = NULL;
  458. BPIP_LIST::iterator posDst;
  459. BPIP_LIST::reverse_iterator posDstRev;
  460. INetCfgComponent * pnccDstOwner;
  461. if (fUp)
  462. {
  463. posDst = ptidDst->listbpipOnDisable.begin();
  464. pbpiDst = *posDst;
  465. }
  466. else
  467. {
  468. posDstRev = ptidDst->listbpipOnDisable.rbegin();
  469. pbpiDst = *posDstRev;
  470. }
  471. AssertSz(pbpiDst, "We never found a path to move before or after!");
  472. pncbpDst = pbpiDst->pncbp;
  473. Assert(pncbpDst);
  474. hr = pncbpDst->GetOwner(&pnccDstOwner);
  475. if (SUCCEEDED(hr))
  476. {
  477. hr = pnccDstOwner->QueryInterface(IID_INetCfgComponentBindings,
  478. reinterpret_cast<LPVOID *>(&pnccb));
  479. if (SUCCEEDED(hr))
  480. {
  481. for (iterlist = ptidSel->listbpipOnDisable.begin();
  482. iterlist != ptidSel->listbpipOnDisable.end() &&
  483. SUCCEEDED(hr);
  484. iterlist++)
  485. {
  486. // loop thru each item in the OnDisable list
  487. INetCfgBindingPath * pncbp;
  488. BIND_PATH_INFO * pbpi;
  489. pbpi = *iterlist;
  490. pncbp = pbpi->pncbp;
  491. #if DBG
  492. INetCfgComponent * pnccSrcOwner;
  493. if (SUCCEEDED(pncbp->GetOwner(&pnccSrcOwner)))
  494. {
  495. AssertSz(pnccSrcOwner == pnccDstOwner, "Source and "
  496. "dst path owners are not the same!?!");
  497. ReleaseObj(pnccSrcOwner);
  498. }
  499. #endif
  500. if (fUp)
  501. {
  502. TraceTag(ttidAdvCfg, "Treeview: Moving...");
  503. DbgDumpBindPath(pncbp);
  504. // Move this binding path before the tagret
  505. hr = pnccb->MoveBefore(pncbp, pncbpDst);
  506. TraceTag(ttidAdvCfg, "Treeview: before...");
  507. DbgDumpBindPath(pncbpDst);
  508. }
  509. else
  510. {
  511. TraceTag(ttidAdvCfg, "Treeview: Moving...");
  512. DbgDumpBindPath(pncbp);
  513. // Move this binding path after the tagret
  514. hr = pnccb->MoveAfter(pncbp, pncbpDst);
  515. TraceTag(ttidAdvCfg, "Treeview: after...");
  516. DbgDumpBindPath(pncbpDst);
  517. }
  518. }
  519. ReleaseObj(pnccb);
  520. }
  521. ReleaseObj(pnccDstOwner);
  522. }
  523. if (SUCCEEDED(hr))
  524. {
  525. HTREEITEM htiParent;
  526. htiParent = TreeView_GetParent(m_hwndTV, htiSel);
  527. // Now that the binding has been moved, move the tree view item to the
  528. // proper place. If moving
  529. if (fUp)
  530. {
  531. // If moving up, the "move after" item should be the previous
  532. // sibling's previous sibling. If that doesn't exist, use the
  533. // previous sibling's parent. That had better exist!
  534. htiDst = TreeView_GetPrevSibling(m_hwndTV, htiDst);
  535. if (!htiDst)
  536. {
  537. htiDst = htiParent;
  538. }
  539. }
  540. AssertSz(htiDst, "No destination to move after!");
  541. SendDlgItemMessage(TVW_Bindings, WM_SETREDRAW, FALSE, 0);
  542. htiSel = HtiMoveTreeItemAfter(htiParent, htiDst, htiSel);
  543. TreeView_SelectItem(m_hwndTV, htiSel);
  544. SendDlgItemMessage(TVW_Bindings, WM_SETREDRAW, TRUE, 0);
  545. ::SetFocus(m_hwndTV);
  546. }
  547. }
  548. //+---------------------------------------------------------------------------
  549. //
  550. // Member: CBindingsDlg::OnBindingUp
  551. //
  552. // Purpose: Called when the PSB_Binding_Up button is pressed
  553. //
  554. // Arguments:
  555. // wNotifyCode []
  556. // wID []
  557. // hWndCtl []
  558. // bHandled []
  559. //
  560. // Returns:
  561. //
  562. // Author: danielwe 3 Dec 1997
  563. //
  564. // Notes:
  565. //
  566. LRESULT CBindingsDlg::OnBindingUp(WORD wNotifyCode, WORD wID, HWND hWndCtl,
  567. BOOL& bHandled)
  568. {
  569. OnBindingUpDown(TRUE);
  570. return 0;
  571. }
  572. //+---------------------------------------------------------------------------
  573. //
  574. // Member: CBindingsDlg::OnBindingDown
  575. //
  576. // Purpose: Called when the PSB_Binding_Down button is pressed
  577. //
  578. // Arguments:
  579. // wNotifyCode []
  580. // wID []
  581. // hWndCtl []
  582. // bHandled []
  583. //
  584. // Returns:
  585. //
  586. // Author: danielwe 3 Dec 1997
  587. //
  588. // Notes:
  589. //
  590. LRESULT CBindingsDlg::OnBindingDown(WORD wNotifyCode, WORD wID, HWND hWndCtl,
  591. BOOL& bHandled)
  592. {
  593. OnBindingUpDown(FALSE);
  594. return 0;
  595. }
  596. //+---------------------------------------------------------------------------
  597. //
  598. // Member: CBindingsDlg::SetCheckboxStates
  599. //
  600. // Purpose: Sets the state of all checkboxes in the treeview.
  601. //
  602. // Arguments:
  603. // (none)
  604. //
  605. // Returns: Nothing
  606. //
  607. // Author: danielwe 26 Nov 1997
  608. //
  609. // Notes:
  610. //
  611. VOID CBindingsDlg::SetCheckboxStates()
  612. {
  613. HRESULT hr = S_OK;
  614. CIterTreeView iterTV(m_hwndTV);
  615. HTREEITEM hti;
  616. TV_ITEM tvi = {0};
  617. #ifdef ENABLETRACE
  618. WCHAR szBuffer[256];
  619. #endif
  620. BOOL fHasPermission = FHasPermission(NCPERM_ChangeBindState);
  621. while ((hti = iterTV.HtiNext()) && SUCCEEDED(hr))
  622. {
  623. TREE_ITEM_DATA * ptid;
  624. #ifdef ENABLETRACE
  625. tvi.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_TEXT;
  626. tvi.pszText = szBuffer;
  627. tvi.cchTextMax = celems(szBuffer);
  628. #else
  629. tvi.mask = TVIF_HANDLE | TVIF_PARAM;
  630. #endif
  631. tvi.hItem = hti;
  632. TreeView_GetItem(m_hwndTV, &tvi);
  633. ptid = reinterpret_cast<TREE_ITEM_DATA *>(tvi.lParam);
  634. AssertSz(ptid, "No tree item data??");
  635. #ifdef ENABLETRACE
  636. TraceTag(ttidAdvCfg, "Setting checkbox state for item %S.", szBuffer);
  637. #endif
  638. BPIP_LIST::iterator iterBpip;
  639. DWORD cEnabled = 0;
  640. for (iterBpip = ptid->listbpipOnDisable.begin();
  641. iterBpip != ptid->listbpipOnDisable.end();
  642. iterBpip++)
  643. {
  644. BIND_PATH_INFO * pbpi = *iterBpip;
  645. if (S_OK == pbpi->pncbp->IsEnabled())
  646. {
  647. cEnabled++;
  648. }
  649. }
  650. tvi.mask = TVIF_STATE;
  651. tvi.stateMask = TVIS_STATEIMAGEMASK;
  652. UINT iState;
  653. if (!fHasPermission)
  654. {
  655. iState = cEnabled ? SELS_FIXEDBINDING_ENABLED : SELS_FIXEDBINDING_DISABLED;
  656. }
  657. else
  658. {
  659. iState = cEnabled ? SELS_CHECKED : SELS_UNCHECKED;
  660. }
  661. tvi.state = INDEXTOSTATEIMAGEMASK(iState);
  662. TreeView_SetItem(m_hwndTV, &tvi);
  663. }
  664. }
  665. //+---------------------------------------------------------------------------
  666. //
  667. // Member: CBindingsDlg::BuildBindingsList
  668. //
  669. // Purpose: Builds the contents of the Bindings treeview control
  670. //
  671. // Arguments:
  672. // pncc [in] INetCfgComponent of adapter upon which this list is based
  673. //
  674. // Returns: Nothing
  675. //
  676. // Author: danielwe 26 Nov 1997
  677. //
  678. // Notes:
  679. //
  680. VOID CBindingsDlg::BuildBindingsList(INetCfgComponent *pncc)
  681. {
  682. HRESULT hr = S_OK;
  683. Assert(pncc);
  684. SBP_LIST listsbp;
  685. CIterNetCfgUpperBindingPath ncupbIter(pncc);
  686. INetCfgBindingPath * pncbp;
  687. CWaitCursor wc;
  688. SendDlgItemMessage(TVW_Bindings, WM_SETREDRAW, FALSE, 0);
  689. while (SUCCEEDED(hr) && S_OK == (hr = ncupbIter.HrNext(&pncbp)))
  690. {
  691. listsbp.push_back(CSortableBindPath(pncbp));
  692. }
  693. if (SUCCEEDED(hr))
  694. {
  695. SBP_LIST::iterator iterlist;
  696. // This sorts the list descending by depth
  697. listsbp.sort();
  698. for (iterlist = listsbp.begin();
  699. iterlist != listsbp.end() && SUCCEEDED(hr);
  700. iterlist++)
  701. {
  702. INetCfgBindingPath * pncbp;
  703. pncbp = (*iterlist).GetPath();
  704. Assert(pncbp);
  705. hr = HrHandleSubpath(listsbp, pncbp);
  706. if (S_FALSE == hr)
  707. {
  708. hr = HrHandleTopLevel(pncbp);
  709. }
  710. }
  711. }
  712. #ifdef ENABLETRACE
  713. if (FALSE)
  714. {
  715. SBP_LIST::iterator iterlist;
  716. for (iterlist = listsbp.begin(); iterlist != listsbp.end(); iterlist++)
  717. {
  718. INetCfgBindingPath * pncbp;
  719. pncbp = (*iterlist).GetPath();
  720. DWORD dwLen = GetDepthSpecialCase(pncbp);
  721. TraceTag(ttidAdvCfg, "Length is %ld.", dwLen);
  722. }
  723. }
  724. #endif
  725. if (SUCCEEDED(hr))
  726. {
  727. hr = HrOrderDisableLists();
  728. if (SUCCEEDED(hr))
  729. {
  730. hr = HrOrderSubItems();
  731. }
  732. }
  733. SendDlgItemMessage(TVW_Bindings, WM_SETREDRAW, TRUE, 0);
  734. // Select first item in the tree
  735. TreeView_SelectItem(m_hwndTV, TreeView_GetRoot(m_hwndTV));
  736. {
  737. SBP_LIST::iterator iterlist;
  738. for (iterlist = listsbp.begin();
  739. iterlist != listsbp.end() && SUCCEEDED(hr);
  740. iterlist++)
  741. {
  742. INetCfgBindingPath * pncbp;
  743. pncbp = (*iterlist).GetPath();
  744. ReleaseObj(pncbp);
  745. }
  746. }
  747. TraceError("CBindingsDlg::BuildBindingsList", hr);
  748. }
  749. //+---------------------------------------------------------------------------
  750. //
  751. // Function: BpiFindBindPathInList
  752. //
  753. // Purpose: Given a bind path and a list, finds the BIND_PATH_INFO item
  754. // that contains the given bind path.
  755. //
  756. // Arguments:
  757. // pncbp [in] Bind path to look for
  758. // listBpip [in, ref] List to search
  759. //
  760. // Returns: BIND_PATH_INFO of corresponding binding path, NULL if not
  761. // found
  762. //
  763. // Author: danielwe 4 Dec 1997
  764. //
  765. // Notes:
  766. //
  767. BIND_PATH_INFO *BpiFindBindPathInList(INetCfgBindingPath *pncbp,
  768. BPIP_LIST &listBpip)
  769. {
  770. BPIP_LIST::iterator iterlist;
  771. for (iterlist = listBpip.begin(); iterlist != listBpip.end(); iterlist++)
  772. {
  773. BIND_PATH_INFO * pbpi;
  774. pbpi = *iterlist;
  775. if (S_OK == pncbp->IsSamePathAs(pbpi->pncbp))
  776. {
  777. // Found the target path
  778. return pbpi;
  779. }
  780. }
  781. return NULL;
  782. }
  783. //+---------------------------------------------------------------------------
  784. //
  785. // Member: CBindingsDlg::HrOrderDisableList
  786. //
  787. // Purpose: Given a component's item data, orders the OnDisable list
  788. // based on the true binding order for the owning component
  789. //
  790. // Arguments:
  791. // ptid [in] Item data containing list
  792. //
  793. // Returns: S_OK if success, Win32 or OLE error code otherwise
  794. //
  795. // Author: danielwe 4 Dec 1997
  796. //
  797. // Notes:
  798. //
  799. HRESULT CBindingsDlg::HrOrderDisableList(TREE_ITEM_DATA *ptid)
  800. {
  801. HRESULT hr = S_OK;
  802. INetCfgComponent * pnccOwner;
  803. BIND_PATH_INFO * pbpi;
  804. #if DBG
  805. size_t cItems = ptid->listbpipOnDisable.size();
  806. #endif
  807. // Get the owning component of the first binding path in the list
  808. pbpi = *(ptid->listbpipOnDisable.begin());
  809. hr = pbpi->pncbp->GetOwner(&pnccOwner);
  810. if (SUCCEEDED(hr))
  811. {
  812. CIterNetCfgBindingPath ncbpIter(pnccOwner);
  813. INetCfgBindingPath * pncbp;
  814. BPIP_LIST::iterator posPncbp;
  815. BPIP_LIST::iterator posInsertAfter;
  816. // Start this at beginning
  817. posInsertAfter = ptid->listbpipOnDisable.begin();
  818. while (SUCCEEDED(hr) && S_OK == (hr = ncbpIter.HrNext(&pncbp)))
  819. {
  820. pbpi = BpiFindBindPathInList(pncbp, ptid->listbpipOnDisable);
  821. if (pbpi)
  822. {
  823. BPIP_LIST::iterator posErase;
  824. posErase = find(ptid->listbpipOnDisable.begin(),
  825. ptid->listbpipOnDisable.end(), pbpi);
  826. AssertSz(posErase != ptid->listbpipOnDisable.end(), "It HAS"
  827. " to be in the list!");
  828. // Found bind path in list
  829. // Remove it from present location and insert after next item
  830. ptid->listbpipOnDisable.splice(posInsertAfter,
  831. ptid->listbpipOnDisable,
  832. posErase);
  833. posInsertAfter++;
  834. }
  835. ReleaseObj(pncbp);
  836. }
  837. ReleaseObj(pnccOwner);
  838. }
  839. if (SUCCEEDED(hr))
  840. {
  841. AssertSz(ptid->listbpipOnDisable.size() == cItems, "How come we don't"
  842. " have the same number of items in the list anymore??");
  843. hr = S_OK;
  844. }
  845. TraceError("CBindingsDlg::HrOrderDisableList", hr);
  846. return hr;
  847. }
  848. //+---------------------------------------------------------------------------
  849. //
  850. // Member: CBindingsDlg::HrOrderDisableLists
  851. //
  852. // Purpose: Orders the OnDisable lists of all tree view items according
  853. // to the true binding order
  854. //
  855. // Arguments:
  856. // (none)
  857. //
  858. // Returns: S_OK if success, Win32 or OLE error code otherwise
  859. //
  860. // Author: danielwe 4 Dec 1997
  861. //
  862. // Notes:
  863. //
  864. HRESULT CBindingsDlg::HrOrderDisableLists()
  865. {
  866. HRESULT hr = S_OK;
  867. CIterTreeView iterHti(m_hwndTV);
  868. HTREEITEM hti;
  869. TV_ITEM tvi = {0};
  870. // Loop thru each tree item, ordering the OnDisable lists to match the
  871. // owning component's true binding order
  872. while ((hti = iterHti.HtiNext()) && SUCCEEDED(hr))
  873. {
  874. TREE_ITEM_DATA * ptid;
  875. tvi.mask = TVIF_PARAM;
  876. tvi.hItem = hti;
  877. TreeView_GetItem(m_hwndTV, &tvi);
  878. ptid = reinterpret_cast<TREE_ITEM_DATA *>(tvi.lParam);
  879. AssertSz(ptid, "No item data?!");
  880. hr = HrOrderDisableList(ptid);
  881. }
  882. if (SUCCEEDED(hr))
  883. {
  884. hr = S_OK;
  885. }
  886. TraceError("CBindingsDlg::HrOrderDisableLists", hr);
  887. return hr;
  888. }
  889. //+---------------------------------------------------------------------------
  890. //
  891. // Member: CBindingsDlg::HrOrderSubItems
  892. //
  893. // Purpose: Orders the sub items of the tree view to reflect the bind
  894. // order of the system
  895. //
  896. // Arguments:
  897. // (none)
  898. //
  899. // Returns: Nothing
  900. //
  901. // Author: danielwe 3 Dec 1997
  902. //
  903. // Notes:
  904. //
  905. HRESULT CBindingsDlg::HrOrderSubItems()
  906. {
  907. HRESULT hr = S_OK;
  908. HTREEITEM htiTopLevel;
  909. htiTopLevel = TreeView_GetRoot(m_hwndTV);
  910. while (htiTopLevel)
  911. {
  912. HTREEITEM htiChild;
  913. TREE_ITEM_DATA * ptid;
  914. TV_ITEM tvi = {0};
  915. tvi.mask = TVIF_PARAM;
  916. tvi.hItem = htiTopLevel;
  917. TreeView_GetItem(m_hwndTV, &tvi);
  918. ptid = reinterpret_cast<TREE_ITEM_DATA *>(tvi.lParam);
  919. AssertSz(ptid, "No tree item data??");
  920. CIterNetCfgBindingPath ncbpIter(ptid->pncc);
  921. INetCfgBindingPath * pncbp;
  922. HTREEITEM htiInsertAfter = NULL;
  923. while (SUCCEEDED(hr) && S_OK == (hr = ncbpIter.HrNext(&pncbp)))
  924. {
  925. BOOL fFound = FALSE;
  926. htiChild = TreeView_GetChild(m_hwndTV, htiTopLevel);
  927. while (htiChild && !fFound)
  928. {
  929. TREE_ITEM_DATA * ptidChild;
  930. tvi.mask = TVIF_PARAM;
  931. tvi.hItem = htiChild;
  932. TreeView_GetItem(m_hwndTV, &tvi);
  933. ptidChild = reinterpret_cast<TREE_ITEM_DATA *>(tvi.lParam);
  934. AssertSz(ptidChild, "No tree item data??");
  935. if (!ptidChild->fOrdered)
  936. {
  937. BIND_PATH_INFO * pbpi;
  938. pbpi = BpiFindBindPathInList(pncbp,
  939. ptidChild->listbpipOnDisable);
  940. if (pbpi)
  941. {
  942. htiInsertAfter = HtiMoveTreeItemAfter(htiTopLevel,
  943. htiInsertAfter,
  944. htiChild);
  945. ptidChild->fOrdered = TRUE;
  946. fFound = TRUE;
  947. // Go to next bind path
  948. break;
  949. }
  950. }
  951. htiChild = TreeView_GetNextSibling(m_hwndTV, htiChild);
  952. }
  953. ReleaseObj(pncbp);
  954. }
  955. htiTopLevel = TreeView_GetNextSibling(m_hwndTV, htiTopLevel);
  956. }
  957. if (SUCCEEDED(hr))
  958. {
  959. hr = S_OK;
  960. }
  961. TraceError("CBindingsDlg::HrOrderSubItems", hr);
  962. return hr;
  963. }
  964. //+---------------------------------------------------------------------------
  965. //
  966. // Member: CBindingsDlg::HtiAddTreeViewItem
  967. //
  968. // Purpose: Addes a new tree item according to provided information
  969. //
  970. // Arguments:
  971. // pnccOwner [in] INetCfgComponent owner of component being added
  972. // htiParent [in] HTREEITEM of parent (NULL if top-level item)
  973. //
  974. // Returns: HTREEITEM of newly added item
  975. //
  976. // Author: danielwe 26 Nov 1997
  977. //
  978. // Notes:
  979. //
  980. HTREEITEM CBindingsDlg::HtiAddTreeViewItem(INetCfgComponent * pnccOwner,
  981. HTREEITEM htiParent)
  982. {
  983. HRESULT hr = S_OK;
  984. HTREEITEM hti = NULL;
  985. SP_CLASSIMAGELIST_DATA cid;
  986. Assert(pnccOwner);
  987. // Get the class image list structure
  988. hr = HrSetupDiGetClassImageList(&cid);
  989. if (SUCCEEDED(hr))
  990. {
  991. BSTR pszwName;
  992. hr = pnccOwner->GetDisplayName(&pszwName);
  993. if (SUCCEEDED(hr))
  994. {
  995. GUID guidClass;
  996. hr = pnccOwner->GetClassGuid(&guidClass);
  997. if (SUCCEEDED(hr))
  998. {
  999. INT nIndex;
  1000. // Get the component's class image list index
  1001. hr = HrSetupDiGetClassImageIndex(&cid, &guidClass,
  1002. &nIndex);
  1003. if (SUCCEEDED(hr))
  1004. {
  1005. TV_INSERTSTRUCT tvis = {0};
  1006. TREE_ITEM_DATA * ptid;
  1007. ptid = new TREE_ITEM_DATA;
  1008. if (ptid)
  1009. {
  1010. AddRefObj(ptid->pncc = pnccOwner);
  1011. ptid->fOrdered = FALSE;
  1012. tvis.item.mask = TVIF_PARAM | TVIF_TEXT |
  1013. TVIF_STATE | TVIF_IMAGE |
  1014. TVIF_SELECTEDIMAGE;
  1015. tvis.item.iImage = nIndex;
  1016. tvis.item.iSelectedImage = nIndex;
  1017. tvis.item.stateMask = TVIS_STATEIMAGEMASK | TVIS_EXPANDED;
  1018. tvis.item.state = TVIS_EXPANDED |
  1019. INDEXTOSTATEIMAGEMASK(SELS_CHECKED);
  1020. tvis.item.pszText = pszwName;
  1021. tvis.item.lParam = reinterpret_cast<LPARAM>(ptid);
  1022. tvis.hParent = htiParent;
  1023. tvis.hInsertAfter = TVI_LAST;
  1024. hti = TreeView_InsertItem(m_hwndTV, &tvis);
  1025. TraceTag(ttidAdvCfg, "Adding%s treeview item: %S",
  1026. htiParent ? " child" : "", tvis.item.pszText);
  1027. CoTaskMemFree(pszwName);
  1028. }
  1029. else
  1030. {
  1031. hr = E_OUTOFMEMORY;
  1032. }
  1033. }
  1034. }
  1035. }
  1036. (void) HrSetupDiDestroyClassImageList(&cid);
  1037. }
  1038. return hti;
  1039. }
  1040. //+---------------------------------------------------------------------------
  1041. //
  1042. // Function: AddToListIfNotAlreadyAdded
  1043. //
  1044. // Purpose: Addes the given bind path info structure to the given list
  1045. //
  1046. // Arguments:
  1047. // bpipList [in, ref] List to be added to
  1048. // pbpi [in] BIND_PATH_INFO structure to add
  1049. //
  1050. // Returns: Nothing
  1051. //
  1052. // Author: danielwe 26 Nov 1997
  1053. //
  1054. // Notes: If the item is not added to the list, it is deleted
  1055. //
  1056. VOID AddToListIfNotAlreadyAdded(BPIP_LIST &bpipList, BIND_PATH_INFO *pbpi)
  1057. {
  1058. BPIP_LIST::iterator iterBpip;
  1059. BOOL fAlreadyInList = FALSE;
  1060. for (iterBpip = bpipList.begin();
  1061. iterBpip != bpipList.end();
  1062. iterBpip++)
  1063. {
  1064. BIND_PATH_INFO * pbpiList = *iterBpip;
  1065. if (S_OK == pbpiList->pncbp->IsSamePathAs(pbpi->pncbp))
  1066. {
  1067. fAlreadyInList = TRUE;
  1068. break;
  1069. }
  1070. }
  1071. if (!fAlreadyInList)
  1072. {
  1073. bpipList.push_back(pbpi);
  1074. }
  1075. else
  1076. {
  1077. ReleaseObj(pbpi->pncbp);
  1078. delete pbpi;
  1079. }
  1080. }
  1081. //+---------------------------------------------------------------------------
  1082. //
  1083. // Member: CBindingsDlg::AssociateBinding
  1084. //
  1085. // Purpose: Associates the given binding path with the given tree item
  1086. //
  1087. // Arguments:
  1088. // pncbpThis [in] Bind path to associate
  1089. // hti [in] HTREEITEM of item to associate the binding with
  1090. // dwFlags [in] One or combination of:
  1091. // ASSCF_ON_ENABLE - associate with OnEnable list
  1092. // ASSCF_ON_DISABLE - associate with OnDisable list
  1093. // ASSCF_ANCESTORS - associate this binding with all
  1094. // ancestors of the given item as
  1095. // well
  1096. //
  1097. // Returns: Nothing
  1098. //
  1099. // Author: danielwe 26 Nov 1997
  1100. //
  1101. // Notes: If binding is already present in the given list, it is not
  1102. // added again.
  1103. //
  1104. VOID CBindingsDlg::AssociateBinding(INetCfgBindingPath *pncbpThis,
  1105. HTREEITEM hti, DWORD dwFlags)
  1106. {
  1107. TV_ITEM tvi = {0};
  1108. TREE_ITEM_DATA * ptid;
  1109. #ifdef ENABLETRACE
  1110. WCHAR szBuffer[256];
  1111. #endif
  1112. //$ TODO (danielwe) 26 Nov 1997: Include ALL ancestors as well!
  1113. AssertSz(dwFlags, "NO flags!");
  1114. #ifdef ENABLETRACE
  1115. tvi.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_TEXT;
  1116. tvi.pszText = szBuffer;
  1117. tvi.cchTextMax = celems(szBuffer);
  1118. #else
  1119. tvi.mask = TVIF_HANDLE | TVIF_PARAM;
  1120. #endif
  1121. tvi.hItem = hti;
  1122. SideAssert(TreeView_GetItem(m_hwndTV, &tvi));
  1123. ptid = reinterpret_cast<TREE_ITEM_DATA *>(tvi.lParam);
  1124. AssertSz(ptid, "No tree item data??");
  1125. #ifdef ENABLETRACE
  1126. TraceTag(ttidAdvCfg, "Associating the following binding path with tree "
  1127. "item %S", szBuffer);
  1128. #endif
  1129. DbgDumpBindPath(pncbpThis);
  1130. if (dwFlags & ASSCF_ON_ENABLE)
  1131. {
  1132. BIND_PATH_INFO * pbpi;
  1133. pbpi = new BIND_PATH_INFO;
  1134. if (pbpi)
  1135. {
  1136. AddRefObj(pbpi->pncbp = pncbpThis);
  1137. // Note: (danielwe) 25 Nov 1997: Let's see if we need this. Until
  1138. // then, set to 0
  1139. pbpi->dwLength = 0;
  1140. AddToListIfNotAlreadyAdded(ptid->listbpipOnEnable, pbpi);
  1141. }
  1142. }
  1143. if (dwFlags & ASSCF_ON_DISABLE)
  1144. {
  1145. BIND_PATH_INFO * pbpi;
  1146. pbpi = new BIND_PATH_INFO;
  1147. if (pbpi)
  1148. {
  1149. AddRefObj(pbpi->pncbp = pncbpThis);
  1150. // Note: (danielwe) 25 Nov 1997: Let's see if we need this. Until
  1151. // then, set to 0
  1152. pbpi->dwLength = 0;
  1153. AddToListIfNotAlreadyAdded(ptid->listbpipOnDisable, pbpi);
  1154. }
  1155. }
  1156. if (dwFlags & ASSCF_ANCESTORS)
  1157. {
  1158. // Now associate the same binding with my parent (this will recurse to
  1159. // cover all ancestors)
  1160. HTREEITEM htiParent = TreeView_GetParent(m_hwndTV, hti);
  1161. if (htiParent)
  1162. {
  1163. AssociateBinding(pncbpThis, htiParent, dwFlags);
  1164. }
  1165. }
  1166. }
  1167. //+---------------------------------------------------------------------------
  1168. //
  1169. // Member: CBindingsDlg::HrHandleSubpath
  1170. //
  1171. // Purpose: Handles the case of the given binding path being a subpath
  1172. // of an already associated binding path
  1173. //
  1174. // Arguments:
  1175. // listsbp [in, ref] Sorted list of binding paths to use in checking
  1176. // pncbpSub [in] Binding path to compare
  1177. //
  1178. // Returns: S_OK if success, Win32 or OLE error code otherwise
  1179. //
  1180. // Author: danielwe 26 Nov 1997
  1181. //
  1182. // Notes:
  1183. //
  1184. HRESULT CBindingsDlg::HrHandleSubpath(SBP_LIST &listsbp,
  1185. INetCfgBindingPath *pncbpSub)
  1186. {
  1187. HRESULT hr = S_OK;
  1188. BOOL fProcessed = FALSE;
  1189. SBP_LIST::iterator iterlist;
  1190. TraceTag(ttidAdvCfg, "---------------------------------------------------"
  1191. "-------------------------");
  1192. DbgDumpBindPath(pncbpSub);
  1193. TraceTag(ttidAdvCfg, "...is being compared to the following...");
  1194. for (iterlist = listsbp.begin();
  1195. iterlist != listsbp.end() && SUCCEEDED(hr);
  1196. iterlist++)
  1197. {
  1198. INetCfgBindingPath * pncbp;
  1199. INetCfgComponent * pnccOwner;
  1200. pncbp = (*iterlist).GetPath();
  1201. Assert(pncbp);
  1202. if (S_OK == pncbp->IsSamePathAs(pncbpSub))
  1203. {
  1204. // Don't compare path to itself
  1205. continue;
  1206. }
  1207. hr = pncbp->GetOwner(&pnccOwner);
  1208. if (SUCCEEDED(hr))
  1209. {
  1210. if (FIsHidden(pnccOwner))
  1211. {
  1212. ReleaseObj(pnccOwner);
  1213. continue;
  1214. }
  1215. else
  1216. {
  1217. ReleaseObj(pnccOwner);
  1218. }
  1219. DbgDumpBindPath(pncbp);
  1220. hr = pncbpSub->IsSubPathOf(pncbp);
  1221. if (S_OK == hr)
  1222. {
  1223. CIterTreeView iterTV(m_hwndTV);
  1224. HTREEITEM hti;
  1225. TV_ITEM tvi = {0};
  1226. #ifdef ENABLETRACE
  1227. WCHAR szBuf[256] = {0};
  1228. #endif
  1229. while ((hti = iterTV.HtiNext()) && SUCCEEDED(hr))
  1230. {
  1231. TREE_ITEM_DATA * ptid;
  1232. #ifdef ENABLETRACE
  1233. tvi.mask = TVIF_TEXT | TVIF_PARAM | TVIF_HANDLE;
  1234. tvi.pszText = szBuf;
  1235. tvi.cchTextMax = celems(szBuf);
  1236. #else
  1237. tvi.mask = TVIF_PARAM | TVIF_HANDLE;
  1238. #endif
  1239. tvi.hItem = hti;
  1240. TreeView_GetItem(m_hwndTV, &tvi);
  1241. #ifdef ENABLETRACE
  1242. TraceTag(ttidAdvCfg, "TreeView item: %S.", szBuf);
  1243. #endif
  1244. ptid = reinterpret_cast<TREE_ITEM_DATA *>(tvi.lParam);
  1245. AssertSz(ptid, "No tree item data??");
  1246. // Look for pncbp in OnEnable of this item
  1247. BPIP_LIST::iterator iterBpip;
  1248. for (iterBpip = ptid->listbpipOnEnable.begin();
  1249. iterBpip != ptid->listbpipOnEnable.end();
  1250. iterBpip++)
  1251. {
  1252. INetCfgBindingPath * pncbpIter;
  1253. BIND_PATH_INFO * pbpi = *iterBpip;
  1254. pncbpIter = pbpi->pncbp;
  1255. AssertSz(pncbpIter, "No binding path?");
  1256. #ifdef ENABLETRACE
  1257. TraceTag(ttidAdvCfg, "OnEnable bindpath is");
  1258. DbgDumpBindPath (pncbpIter);
  1259. #endif
  1260. if (S_OK == pncbpIter->IsSamePathAs(pncbp))
  1261. {
  1262. hr = HrHandleSubItem(pncbpSub, pncbp, ptid, hti);
  1263. fProcessed = TRUE;
  1264. }
  1265. }
  1266. }
  1267. }
  1268. }
  1269. }
  1270. if (SUCCEEDED(hr))
  1271. {
  1272. hr = fProcessed ? S_OK : S_FALSE;
  1273. }
  1274. TraceError("CBindingsDlg::HrHandleSubpath", (hr == S_FALSE) ? S_OK : hr);
  1275. return hr;
  1276. }
  1277. //+---------------------------------------------------------------------------
  1278. //
  1279. // Member: CBindingsDlg::HtiIsSubItem
  1280. //
  1281. // Purpose: Determines if the given component is already a sub item of
  1282. // the given tree item
  1283. //
  1284. // Arguments:
  1285. // pncc [in] Component to check
  1286. // hti [in] HTREEITEM of item to check
  1287. //
  1288. // Returns: HTREEITEM of sub item, NULL if it is not a subitem
  1289. //
  1290. // Author: danielwe 26 Nov 1997
  1291. //
  1292. // Notes:
  1293. //
  1294. HTREEITEM CBindingsDlg::HtiIsSubItem(INetCfgComponent *pncc, HTREEITEM hti)
  1295. {
  1296. HTREEITEM htiCur;
  1297. htiCur = TreeView_GetChild(m_hwndTV, hti);
  1298. while (htiCur)
  1299. {
  1300. TREE_ITEM_DATA * ptid;
  1301. TV_ITEM tvi = {0};
  1302. tvi.hItem = htiCur;
  1303. tvi.mask = TVIF_HANDLE | TVIF_PARAM;
  1304. TreeView_GetItem(m_hwndTV, &tvi);
  1305. ptid = reinterpret_cast<TREE_ITEM_DATA *>(tvi.lParam);
  1306. AssertSz(ptid, "No item data??");
  1307. // Note: (danielwe) 26 Nov 1997: Make sure pointer comparison is
  1308. // ok.
  1309. if (pncc == ptid->pncc)
  1310. {
  1311. return htiCur;
  1312. }
  1313. htiCur = TreeView_GetNextSibling(m_hwndTV, htiCur);
  1314. }
  1315. return NULL;
  1316. }
  1317. //+---------------------------------------------------------------------------
  1318. //
  1319. // Member: CBindingsDlg::HrHandleSubItem
  1320. //
  1321. // Purpose: Handles the case of a single sub-item existing in the tree
  1322. // that matches the given binding path.
  1323. //
  1324. // Arguments:
  1325. // pncbpThis [in] Binding path being evaluated
  1326. // pncbpMatch [in] Binding path it is a subpath of
  1327. // ptid [in] Tree item data for tree view item that pncbpMatch
  1328. // is associated with
  1329. // htiMatchItem [in] HTREEITEM of above
  1330. //
  1331. // Returns: S_OK if success, Win32 or OLE error code otherwise
  1332. //
  1333. // Author: danielwe 26 Nov 1997
  1334. //
  1335. // Notes:
  1336. //
  1337. HRESULT CBindingsDlg::HrHandleSubItem(INetCfgBindingPath *pncbpThis,
  1338. INetCfgBindingPath *pncbpMatch,
  1339. TREE_ITEM_DATA *ptid,
  1340. HTREEITEM htiMatchItem)
  1341. {
  1342. HRESULT hr = S_OK;
  1343. DWORD dwThisLen;
  1344. DWORD dwMatchLen;
  1345. DWORD dLen;
  1346. INetCfgComponent * pnccMatchItem;
  1347. pnccMatchItem = ptid->pncc;
  1348. Assert(pnccMatchItem);
  1349. dwThisLen = GetDepthSpecialCase(pncbpThis);
  1350. dwMatchLen = GetDepthSpecialCase(pncbpMatch);
  1351. dLen = dwMatchLen - dwThisLen;
  1352. if ((dwMatchLen - dwThisLen) == 1 ||
  1353. (S_OK == (hr = HrComponentIsHidden(pncbpMatch, dLen))))
  1354. {
  1355. INetCfgComponent * pnccThisOwner;
  1356. INetCfgComponent * pnccMatchOwner;
  1357. hr = pncbpThis->GetOwner(&pnccThisOwner);
  1358. if (SUCCEEDED(hr))
  1359. {
  1360. hr = pncbpMatch->GetOwner(&pnccMatchOwner);
  1361. if (SUCCEEDED(hr))
  1362. {
  1363. if (!FIsHidden(pnccThisOwner) &&
  1364. !FDontExposeLower(pnccMatchOwner))
  1365. {
  1366. hr = HrHandleValidSubItem(pncbpThis, pncbpMatch,
  1367. pnccThisOwner,
  1368. htiMatchItem, ptid);
  1369. }
  1370. ReleaseObj(pnccMatchOwner);
  1371. }
  1372. ReleaseObj(pnccThisOwner);
  1373. }
  1374. }
  1375. AssociateBinding(pncbpThis, htiMatchItem,
  1376. ASSCF_ON_ENABLE | ASSCF_ANCESTORS);
  1377. TraceError("CBindingsDlg::HrHandleSubItem", (hr == S_FALSE) ? S_OK : hr);
  1378. return hr;
  1379. }
  1380. //+---------------------------------------------------------------------------
  1381. //
  1382. // Member: CBindingsDlg::HrHandleValidSubItem
  1383. //
  1384. // Purpose: Handles the case of the given binding path being a sub item
  1385. // of at least on item in the tree.
  1386. //
  1387. // Arguments:
  1388. // pncbpThis [in] THIS binding path
  1389. // pncbpMatch [in] MATCH binding path
  1390. // pnccThisOwner [in] Owner of THIS binding path
  1391. // htiMatchItem [in] HTREEITEM of match item
  1392. // ptid [in] TREE item data for match item
  1393. //
  1394. // Returns: S_OK if success, Win32 or OLE error code otherwise
  1395. //
  1396. // Author: danielwe 1 Dec 1997
  1397. //
  1398. // Notes:
  1399. //
  1400. HRESULT CBindingsDlg::HrHandleValidSubItem(INetCfgBindingPath *pncbpThis,
  1401. INetCfgBindingPath *pncbpMatch,
  1402. INetCfgComponent *pnccThisOwner,
  1403. HTREEITEM htiMatchItem,
  1404. TREE_ITEM_DATA *ptid)
  1405. {
  1406. HRESULT hr = S_OK;
  1407. HTREEITEM htiNew = NULL;
  1408. if (pnccThisOwner != ptid->pncc)
  1409. {
  1410. // Check if it is already present as a subitem
  1411. htiNew = HtiIsSubItem(pnccThisOwner, htiMatchItem);
  1412. if (!htiNew)
  1413. {
  1414. htiNew = HtiAddTreeViewItem(pnccThisOwner, htiMatchItem);
  1415. }
  1416. AssertSz(htiNew, "No new or existing tree item!?!");
  1417. AssociateBinding(pncbpMatch, htiNew,
  1418. ASSCF_ON_ENABLE | ASSCF_ON_DISABLE);
  1419. AssociateBinding(pncbpThis, htiNew, ASSCF_ON_ENABLE);
  1420. }
  1421. TraceError("CBindingsDlg::HrHandleComponent", hr);
  1422. return hr;
  1423. }
  1424. //+---------------------------------------------------------------------------
  1425. //
  1426. // Member: CBindingsDlg::HrComponentIsHidden
  1427. //
  1428. // Purpose: Determines if the Nth component of the given binding path is
  1429. // hidden.
  1430. //
  1431. // Arguments:
  1432. // pncbp [in] Binding path to check
  1433. // iComp [in] Index of component to check for hidden characterstic
  1434. //
  1435. // Returns: S_OK if success, Win32 or OLE error code otherwise
  1436. //
  1437. // Author: danielwe 26 Nov 1997
  1438. //
  1439. // Notes:
  1440. //
  1441. HRESULT CBindingsDlg::HrComponentIsHidden(INetCfgBindingPath *pncbp,
  1442. DWORD iComp)
  1443. {
  1444. Assert(pncbp);
  1445. HRESULT hr = S_OK;
  1446. CIterNetCfgBindingInterface ncbiIter(pncbp);
  1447. INetCfgBindingInterface * pncbi;
  1448. // Convert from component count to interface count
  1449. iComp--;
  1450. AssertSz(iComp > 0, "We should never be looking for the first component!");
  1451. while (SUCCEEDED(hr) && iComp && S_OK == (hr = ncbiIter.HrNext(&pncbi)))
  1452. {
  1453. iComp--;
  1454. if (!iComp)
  1455. {
  1456. INetCfgComponent * pnccLower;
  1457. hr = pncbi->GetLowerComponent(&pnccLower);
  1458. if (SUCCEEDED(hr))
  1459. {
  1460. if (!FIsHidden(pnccLower))
  1461. {
  1462. hr = S_FALSE;
  1463. }
  1464. ReleaseObj(pnccLower);
  1465. }
  1466. }
  1467. ReleaseObj(pncbi);
  1468. }
  1469. TraceError("CBindingsDlg::HrComponentIsHidden", (hr == S_FALSE) ? S_OK : hr);
  1470. return hr;
  1471. }
  1472. //+---------------------------------------------------------------------------
  1473. //
  1474. // Member: CBindingsDlg::HrHandleTopLevel
  1475. //
  1476. // Purpose: Handles the case of the given binding path not being associated
  1477. // with any existing tree view item
  1478. //
  1479. // Arguments:
  1480. // pncbpThis [in] Binding path being evaluated
  1481. //
  1482. // Returns: S_OK if success, Win32 or OLE error code otherwise
  1483. //
  1484. // Author: danielwe 26 Nov 1997
  1485. //
  1486. // Notes:
  1487. //
  1488. HRESULT CBindingsDlg::HrHandleTopLevel(INetCfgBindingPath *pncbpThis)
  1489. {
  1490. HRESULT hr = S_OK;
  1491. INetCfgComponent * pnccOwner;
  1492. BOOL fFound = FALSE;
  1493. // Check if the owner of this path is already present in the tree
  1494. hr = pncbpThis->GetOwner(&pnccOwner);
  1495. if (SUCCEEDED(hr))
  1496. {
  1497. CIterTreeView iterTV(m_hwndTV);
  1498. HTREEITEM hti;
  1499. TV_ITEM tvi = {0};
  1500. while ((hti = iterTV.HtiNext()) && SUCCEEDED(hr))
  1501. {
  1502. TREE_ITEM_DATA * ptid;
  1503. tvi.mask = TVIF_PARAM | TVIF_HANDLE;
  1504. tvi.hItem = hti;
  1505. TreeView_GetItem(m_hwndTV, &tvi);
  1506. ptid = reinterpret_cast<TREE_ITEM_DATA *>(tvi.lParam);
  1507. AssertSz(ptid, "No tree item data??");
  1508. // Note: (danielwe) 25 Nov 1997: Pointer comparison may not
  1509. // work. Use GUIDs if necessary.
  1510. if (ptid->pncc == pnccOwner)
  1511. {
  1512. // Found match with THIS binding owner and an existing tree
  1513. // item
  1514. AssociateBinding(pncbpThis, hti, ASSCF_ON_ENABLE |
  1515. ASSCF_ON_DISABLE);
  1516. fFound = TRUE;
  1517. break;
  1518. }
  1519. }
  1520. if (SUCCEEDED(hr) && !fFound)
  1521. {
  1522. // Not found in the tree
  1523. if (!FIsHidden(pnccOwner))
  1524. {
  1525. DWORD dwLen;
  1526. dwLen = GetDepthSpecialCase(pncbpThis);
  1527. if (dwLen > 2)
  1528. {
  1529. HTREEITEM hti;
  1530. hti = HtiAddTreeViewItem(pnccOwner, NULL);
  1531. if (hti)
  1532. {
  1533. AssociateBinding(pncbpThis, hti,
  1534. ASSCF_ON_ENABLE |
  1535. ASSCF_ON_DISABLE);
  1536. }
  1537. }
  1538. }
  1539. }
  1540. ReleaseObj(pnccOwner);
  1541. }
  1542. TraceError("CBindingsDlg::HrHandleTopLevel", (S_FALSE == hr) ? S_OK : hr);
  1543. return hr;
  1544. }
  1545. //+---------------------------------------------------------------------------
  1546. //
  1547. // Function: ChangeTreeItemParam
  1548. //
  1549. // Purpose: Helper function to change the lParam of a tree view item
  1550. //
  1551. // Arguments:
  1552. // hwndTV [in] Tree view window
  1553. // hitem [in] Handle to item to change
  1554. // lparam [in] New value of lParam
  1555. //
  1556. // Returns: Nothing
  1557. //
  1558. // Author: danielwe 3 Dec 1997
  1559. //
  1560. // Notes:
  1561. //
  1562. VOID ChangeTreeItemParam(HWND hwndTV, HTREEITEM hitem, LPARAM lparam)
  1563. {
  1564. TV_ITEM tvi;
  1565. tvi.hItem = hitem;
  1566. tvi.mask = TVIF_PARAM;
  1567. tvi.lParam = lparam;
  1568. TreeView_SetItem(hwndTV, &tvi);
  1569. }
  1570. //+---------------------------------------------------------------------------
  1571. //
  1572. // Member: CBindingsDlg::HtiMoveTreeItemAfter
  1573. //
  1574. // Purpose: Moves the given tree view item and all its children after the
  1575. // given treeview item
  1576. //
  1577. // Arguments:
  1578. // htiParent [in] Parent treeview item
  1579. // htiDest [in] Item to move after
  1580. // htiSrc [in] Item to move
  1581. //
  1582. // Returns: Newly added treeview item
  1583. //
  1584. // Author: danielwe 3 Dec 1997
  1585. //
  1586. // Notes:
  1587. //
  1588. HTREEITEM CBindingsDlg::HtiMoveTreeItemAfter(HTREEITEM htiParent,
  1589. HTREEITEM htiDest,
  1590. HTREEITEM htiSrc)
  1591. {
  1592. HTREEITEM htiNew;
  1593. HTREEITEM htiChild;
  1594. HTREEITEM htiNextChild;
  1595. TV_INSERTSTRUCT tvis;
  1596. WCHAR szText[256];
  1597. TraceTag(ttidAdvCfg, "Moving ...");
  1598. DbgDumpTreeViewItem(m_hwndTV, htiSrc);
  1599. TraceTag(ttidAdvCfg, "... after ...");
  1600. DbgDumpTreeViewItem(m_hwndTV, htiDest);
  1601. // retieve the items data
  1602. tvis.item.hItem = htiSrc;
  1603. tvis.item.mask = TVIF_IMAGE | TVIF_PARAM | TVIF_SELECTEDIMAGE |
  1604. TVIF_TEXT | TVIF_STATE;
  1605. tvis.item.stateMask = TVIS_STATEIMAGEMASK;
  1606. tvis.item.pszText = szText;
  1607. tvis.item.cchTextMax = celems(szText);
  1608. TreeView_GetItem(m_hwndTV, &tvis.item);
  1609. if (NULL == htiDest)
  1610. {
  1611. tvis.hInsertAfter = TVI_LAST;
  1612. }
  1613. else
  1614. {
  1615. if (htiParent == htiDest)
  1616. {
  1617. tvis.hInsertAfter = TVI_FIRST;
  1618. }
  1619. else
  1620. {
  1621. tvis.hInsertAfter = htiDest;
  1622. }
  1623. }
  1624. tvis.hParent = htiParent;
  1625. // add our new one
  1626. htiNew = TreeView_InsertItem(m_hwndTV, &tvis);
  1627. // copy all children
  1628. htiChild = TreeView_GetChild(m_hwndTV, htiSrc);
  1629. while (htiChild)
  1630. {
  1631. htiNextChild = TreeView_GetNextSibling(m_hwndTV, htiChild);
  1632. HtiMoveTreeItemAfter(htiNew, NULL, htiChild);
  1633. htiChild = htiNextChild;
  1634. }
  1635. // set old location param to null, so when it is removed,
  1636. // our lparam is not deleted by our remove routine
  1637. ChangeTreeItemParam(m_hwndTV, htiSrc, NULL);
  1638. // remove from old location
  1639. TreeView_DeleteItem(m_hwndTV, htiSrc);
  1640. return htiNew;
  1641. }
  1642. //
  1643. // Treeview flat iterator
  1644. //
  1645. //+---------------------------------------------------------------------------
  1646. //
  1647. // Member: CIterTreeView::HtiNext
  1648. //
  1649. // Purpose: Advances the iterator to the next treeview item
  1650. //
  1651. // Arguments:
  1652. // (none)
  1653. //
  1654. // Returns: Next HTREEITEM in tree view
  1655. //
  1656. // Author: danielwe 26 Nov 1997
  1657. //
  1658. // Notes: Uses a systematic iteration. First all children of first item
  1659. // are returned, then all siblings, then next sibling and so on
  1660. //
  1661. HTREEITEM CIterTreeView::HtiNext()
  1662. {
  1663. HTREEITEM htiRet;
  1664. HTREEITEM hti;
  1665. if (m_stackHti.empty())
  1666. {
  1667. return NULL;
  1668. }
  1669. htiRet = Front();
  1670. hti = TreeView_GetChild(m_hwndTV, htiRet);
  1671. if (!hti)
  1672. {
  1673. PopAndDelete();
  1674. hti = TreeView_GetNextSibling(m_hwndTV, htiRet);
  1675. if (hti)
  1676. {
  1677. PushAndAlloc(hti);
  1678. }
  1679. else
  1680. {
  1681. if (!m_stackHti.empty())
  1682. {
  1683. hti = TreeView_GetNextSibling(m_hwndTV, Front());
  1684. PopAndDelete();
  1685. if (hti)
  1686. {
  1687. PushAndAlloc(hti);
  1688. }
  1689. }
  1690. }
  1691. }
  1692. else
  1693. {
  1694. PushAndAlloc(hti);
  1695. }
  1696. return htiRet;
  1697. }