mirror of https://github.com/tongzx/nt5src
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
1995 lines
53 KiB
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1997.
|
|
//
|
|
// File: A C T R E E . C P P
|
|
//
|
|
// Contents: Functions related to the Advanced Configuration dialog
|
|
// tree view control
|
|
//
|
|
// Notes:
|
|
//
|
|
// Author: danielwe 3 Dec 1997
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include "pch.h"
|
|
#pragma hdrstop
|
|
|
|
#include "netcon.h"
|
|
#include "netconp.h"
|
|
#include "acsheet.h"
|
|
#include "acbind.h"
|
|
#include "ncnetcfg.h"
|
|
#include "lancmn.h"
|
|
#include "ncui.h"
|
|
#include "ncsetup.h"
|
|
#include "ncperms.h"
|
|
|
|
DWORD
|
|
GetDepthSpecialCase (
|
|
INetCfgBindingPath* pPath)
|
|
{
|
|
HRESULT hr;
|
|
DWORD dwDepth;
|
|
|
|
hr = pPath->GetDepth (&dwDepth);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
INetCfgComponent* pLast;
|
|
|
|
hr = HrGetLastComponentAndInterface (
|
|
pPath, &pLast, NULL);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
DWORD dwCharacteristics;
|
|
|
|
// If the last component in the bindpath is one which
|
|
// doesn't expose its lower bindings, then compsensate by
|
|
// returning a depth that thinks it does. This special case
|
|
// is only for this code which was written for the origianl
|
|
// binding engine but needed to be quickly adapted to the new
|
|
// binding engine which doesn't return 'fake' bindpaths.
|
|
//
|
|
|
|
hr = pLast->GetCharacteristics (&dwCharacteristics);
|
|
if (SUCCEEDED(hr) && (dwCharacteristics & NCF_DONTEXPOSELOWER))
|
|
{
|
|
PWSTR pszInfId;
|
|
|
|
hr = pLast->GetId (&pszInfId);
|
|
if (S_OK == hr)
|
|
{
|
|
if (0 == lstrcmpW (pszInfId, L"ms_nwnb"))
|
|
{
|
|
dwDepth += 2;
|
|
}
|
|
else if (0 == lstrcmpW (pszInfId, L"ms_nwipx"))
|
|
{
|
|
dwDepth += 1;
|
|
}
|
|
|
|
CoTaskMemFree (pszInfId);
|
|
}
|
|
}
|
|
|
|
ReleaseObj (pLast);
|
|
}
|
|
}
|
|
|
|
return dwDepth;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: FreeBindPathInfoList
|
|
//
|
|
// Purpose: Frees the given list of BIND_PATH_INFO structures
|
|
//
|
|
// Arguments:
|
|
// listbpip [in, ref] Reference to list to be freed
|
|
//
|
|
// Returns: Nothing
|
|
//
|
|
// Author: danielwe 26 Nov 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
VOID FreeBindPathInfoList(BPIP_LIST &listbpip)
|
|
{
|
|
BPIP_LIST::iterator iterBpip;
|
|
|
|
for (iterBpip = listbpip.begin();
|
|
iterBpip != listbpip.end();
|
|
iterBpip++)
|
|
{
|
|
BIND_PATH_INFO * pbpi = *iterBpip;
|
|
|
|
ReleaseObj(pbpi->pncbp);
|
|
delete pbpi;
|
|
}
|
|
|
|
listbpip.erase(listbpip.begin(), listbpip.end());
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CBindingsDlg::OnTreeItemChanged
|
|
//
|
|
// Purpose: Called in response to the TVN_SELCHANGED message
|
|
//
|
|
// Arguments:
|
|
// idCtrl []
|
|
// pnmh []
|
|
// bHandled []
|
|
//
|
|
// Returns:
|
|
//
|
|
// Author: danielwe 26 Nov 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
LRESULT CBindingsDlg::OnTreeItemChanged(int idCtrl, LPNMHDR pnmh,
|
|
BOOL& bHandled)
|
|
{
|
|
NM_TREEVIEW * pnmtv = reinterpret_cast<NM_TREEVIEW *>(pnmh);
|
|
|
|
Assert(pnmtv);
|
|
|
|
#ifdef ENABLETRACE
|
|
WCHAR szBuffer[265];
|
|
|
|
pnmtv->itemNew.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_TEXT;
|
|
pnmtv->itemNew.pszText = szBuffer;
|
|
pnmtv->itemNew.cchTextMax = celems(szBuffer);
|
|
|
|
TreeView_GetItem(m_hwndTV, &pnmtv->itemNew);
|
|
|
|
TREE_ITEM_DATA * ptid;
|
|
|
|
ptid = reinterpret_cast<TREE_ITEM_DATA *>(pnmtv->itemNew.lParam);
|
|
|
|
Assert(ptid);
|
|
|
|
TraceTag(ttidAdvCfg, "*-------------------------------------------------"
|
|
"------------------------------*");
|
|
TraceTag(ttidAdvCfg, "Tree item %S selected", szBuffer);
|
|
TraceTag(ttidAdvCfg, "-----------------------------------------");
|
|
TraceTag(ttidAdvCfg, "OnEnable list:");
|
|
TraceTag(ttidAdvCfg, "--------------");
|
|
|
|
BPIP_LIST::iterator iterBpip;
|
|
|
|
for (iterBpip = ptid->listbpipOnEnable.begin();
|
|
iterBpip != ptid->listbpipOnEnable.end();
|
|
iterBpip++)
|
|
{
|
|
BIND_PATH_INFO * pbpi = *iterBpip;
|
|
|
|
DbgDumpBindPath(pbpi->pncbp);
|
|
}
|
|
|
|
TraceTag(ttidAdvCfg, "-----------------------------------");
|
|
TraceTag(ttidAdvCfg, "OnDisable list:");
|
|
TraceTag(ttidAdvCfg, "--------------");
|
|
|
|
for (iterBpip = ptid->listbpipOnDisable.begin();
|
|
iterBpip != ptid->listbpipOnDisable.end();
|
|
iterBpip++)
|
|
{
|
|
BIND_PATH_INFO * pbpi = *iterBpip;
|
|
|
|
DbgDumpBindPath(pbpi->pncbp);
|
|
}
|
|
|
|
TraceTag(ttidAdvCfg, "*-------------------------------------------------"
|
|
"------------------------------*");
|
|
|
|
#endif
|
|
|
|
// Assume both buttons are greyed initially
|
|
::EnableWindow(GetDlgItem(PSB_Binding_Up), FALSE);
|
|
::EnableWindow(GetDlgItem(PSB_Binding_Down), FALSE);
|
|
|
|
if (TreeView_GetParent(m_hwndTV, pnmtv->itemNew.hItem))
|
|
{
|
|
if (TreeView_GetNextSibling(m_hwndTV, pnmtv->itemNew.hItem))
|
|
{
|
|
::EnableWindow(GetDlgItem(PSB_Binding_Down), TRUE);
|
|
}
|
|
|
|
if (TreeView_GetPrevSibling(m_hwndTV, pnmtv->itemNew.hItem))
|
|
{
|
|
::EnableWindow(GetDlgItem(PSB_Binding_Up), TRUE);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CBindingsDlg::OnTreeDeleteItem
|
|
//
|
|
// Purpose: Called in response to the TVN_DELETEITEM message
|
|
//
|
|
// Arguments:
|
|
// idCtrl []
|
|
// pnmh []
|
|
// bHandled []
|
|
//
|
|
// Returns: Nothing useful
|
|
//
|
|
// Author: danielwe 26 Nov 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
LRESULT CBindingsDlg::OnTreeDeleteItem(int idCtrl, LPNMHDR pnmh,
|
|
BOOL& bHandled)
|
|
{
|
|
NM_TREEVIEW * pnmtv = reinterpret_cast<NM_TREEVIEW *>(pnmh);
|
|
TREE_ITEM_DATA * ptid;
|
|
|
|
Assert(pnmtv);
|
|
|
|
ptid = reinterpret_cast<TREE_ITEM_DATA *>(pnmtv->itemOld.lParam);
|
|
|
|
// May be NULL if moving items around
|
|
if (ptid)
|
|
{
|
|
ReleaseObj(ptid->pncc);
|
|
FreeBindPathInfoList(ptid->listbpipOnEnable);
|
|
FreeBindPathInfoList(ptid->listbpipOnDisable);
|
|
|
|
delete ptid;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CBindingsDlg::OnTreeItemExpanding
|
|
//
|
|
// Purpose: Called when the TVN_ITEMEXPANDING message is received
|
|
//
|
|
// Arguments:
|
|
// idCtrl []
|
|
// pnmh []
|
|
// bHandled []
|
|
//
|
|
// Returns:
|
|
//
|
|
// Author: danielwe 26 Nov 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
LRESULT CBindingsDlg::OnTreeItemExpanding(int idCtrl, LPNMHDR pnmh,
|
|
BOOL& bHandled)
|
|
{
|
|
// This prevents all tree items from collapsing
|
|
return TRUE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CBindingsDlg::OnTreeKeyDown
|
|
//
|
|
// Purpose: Called when the TVN_KEYDOWN message is received
|
|
//
|
|
// Arguments:
|
|
// idCtrl []
|
|
// pnmh []
|
|
// fHandled []
|
|
//
|
|
// Returns:
|
|
//
|
|
// Author: danielwe 22 Dec 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
LRESULT CBindingsDlg::OnTreeKeyDown(int idCtrl, LPNMHDR pnmh, BOOL& fHandled)
|
|
{
|
|
TV_KEYDOWN * ptvkd = (TV_KEYDOWN*)pnmh;
|
|
HTREEITEM hti = NULL;
|
|
|
|
if (VK_SPACE == ptvkd->wVKey)
|
|
{
|
|
hti = TreeView_GetSelection(m_hwndTV);
|
|
// if there is a selection
|
|
if (hti)
|
|
{
|
|
ToggleCheckbox(hti);
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CBindingsDlg::ToggleCheckbox
|
|
//
|
|
// Purpose: Called when the user toggles a checbox in the treeview
|
|
// control.
|
|
//
|
|
// Arguments:
|
|
// hti [in] HTREEITEM of item that was toggled
|
|
//
|
|
// Returns: Nothing
|
|
//
|
|
// Author: danielwe 26 Nov 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
VOID CBindingsDlg::ToggleCheckbox(HTREEITEM hti)
|
|
{
|
|
if (!FHasPermission(NCPERM_ChangeBindState))
|
|
{
|
|
// do nothing
|
|
return;
|
|
}
|
|
|
|
TV_ITEM tvi = {0};
|
|
TREE_ITEM_DATA * ptid;
|
|
BOOL fEnable;
|
|
|
|
tvi.mask = TVIF_PARAM | TVIF_HANDLE | TVIF_STATE;
|
|
tvi.stateMask = TVIS_STATEIMAGEMASK;
|
|
tvi.hItem = hti;
|
|
TreeView_GetItem(m_hwndTV, &tvi);
|
|
|
|
ptid = reinterpret_cast<TREE_ITEM_DATA *>(tvi.lParam);
|
|
AssertSz(ptid, "No tree item data??");
|
|
|
|
BPIP_LIST::iterator iterBpip;
|
|
BPIP_LIST * plist;
|
|
|
|
if (tvi.state & INDEXTOSTATEIMAGEMASK(SELS_CHECKED))
|
|
{
|
|
// unchecking the box
|
|
plist = &ptid->listbpipOnDisable;
|
|
fEnable = FALSE;
|
|
}
|
|
else
|
|
{
|
|
// checking the box
|
|
plist = &ptid->listbpipOnEnable;
|
|
fEnable = TRUE;
|
|
}
|
|
|
|
TraceTag(ttidAdvCfg, "ToggleChecbox: %s the following binding path(s)",
|
|
fEnable ? "Enabling" : "Disabling");
|
|
|
|
// Enable or disable each binding path in the appropriate list
|
|
for (iterBpip = plist->begin();
|
|
iterBpip != plist->end();
|
|
iterBpip++)
|
|
{
|
|
BIND_PATH_INFO * pbpi = *iterBpip;
|
|
|
|
(VOID)pbpi->pncbp->Enable(fEnable);
|
|
DbgDumpBindPath(pbpi->pncbp);
|
|
}
|
|
|
|
SetCheckboxStates();
|
|
|
|
TraceTag(ttidAdvCfg, "Done!");
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CBindingsDlg::OnClick
|
|
//
|
|
// Purpose: Called in response to the NM_CLICK message.
|
|
//
|
|
// Arguments:
|
|
// idCtrl []
|
|
// pnmh []
|
|
// fHandled []
|
|
//
|
|
// Returns:
|
|
//
|
|
// Author: danielwe 26 Nov 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
LRESULT CBindingsDlg::OnClick(int idCtrl, LPNMHDR pnmh, BOOL& fHandled)
|
|
{
|
|
return OnClickOrDoubleClick(idCtrl, pnmh, FALSE);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CBindingsDlg::OnDoubleClick
|
|
//
|
|
// Purpose: Called in response to the NM_DBLCLK message.
|
|
//
|
|
// Arguments:
|
|
// idCtrl []
|
|
// pnmh []
|
|
// fHandled []
|
|
//
|
|
// Returns:
|
|
//
|
|
// Author: danielwe 16 Dec 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
LRESULT CBindingsDlg::OnDoubleClick(int idCtrl, LPNMHDR pnmh, BOOL& fHandled)
|
|
{
|
|
return OnClickOrDoubleClick(idCtrl, pnmh, TRUE);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CBindingsDlg::OnClickOrDoubleClick
|
|
//
|
|
// Purpose: Handles clicks or double clicks in the treeview control
|
|
//
|
|
// Arguments:
|
|
// idCtrl [in] ID of control
|
|
// pnmh [in] Notification header
|
|
// fDoubleClick [in] TRUE if double click, FALSE if single click
|
|
//
|
|
// Returns:
|
|
//
|
|
// Author: danielwe 16 Dec 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
LRESULT CBindingsDlg::OnClickOrDoubleClick(int idCtrl, LPNMHDR pnmh,
|
|
BOOL fDoubleClick)
|
|
{
|
|
if (idCtrl == TVW_Bindings)
|
|
{
|
|
DWORD dwpts;
|
|
RECT rc;
|
|
TV_HITTESTINFO tvhti = {0};
|
|
HTREEITEM hti;
|
|
|
|
// we have the location
|
|
dwpts = GetMessagePos();
|
|
|
|
// translate it relative to the tree view
|
|
::GetWindowRect(m_hwndTV, &rc);
|
|
|
|
tvhti.pt.x = LOWORD(dwpts) - rc.left;
|
|
tvhti.pt.y = HIWORD(dwpts) - rc.top;
|
|
|
|
// get currently selected item
|
|
hti = TreeView_HitTest(m_hwndTV, &tvhti);
|
|
if (hti)
|
|
{
|
|
if (tvhti.flags & TVHT_ONITEMSTATEICON)
|
|
{
|
|
ToggleCheckbox(hti);
|
|
}
|
|
else if ((tvhti.flags & TVHT_ONITEM) && fDoubleClick)
|
|
{
|
|
ToggleCheckbox(hti);
|
|
}
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CBindingsDlg::OnBindingUpDown
|
|
//
|
|
// Purpose: Handles the user moving a binding in the treeview up or down
|
|
//
|
|
// Arguments:
|
|
// fUp [in] TRUE if moving up, FALSE if down
|
|
//
|
|
// Returns: Nothing
|
|
//
|
|
// Author: danielwe 3 Dec 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
VOID CBindingsDlg::OnBindingUpDown(BOOL fUp)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
TV_ITEM tvi = {0};
|
|
HTREEITEM htiSel;
|
|
HTREEITEM htiDst;
|
|
TREE_ITEM_DATA * ptidSel;
|
|
TREE_ITEM_DATA * ptidDst;
|
|
INetCfgComponentBindings * pnccb;
|
|
|
|
htiSel = TreeView_GetSelection(m_hwndTV);
|
|
|
|
AssertSz(htiSel, "No selection?");
|
|
|
|
if (fUp)
|
|
{
|
|
htiDst = TreeView_GetPrevSibling(m_hwndTV, htiSel);
|
|
}
|
|
else
|
|
{
|
|
htiDst = TreeView_GetNextSibling(m_hwndTV, htiSel);
|
|
}
|
|
|
|
AssertSz(htiDst, "No next item?!");
|
|
|
|
tvi.mask = TVIF_PARAM;
|
|
tvi.hItem = htiSel;
|
|
|
|
TreeView_GetItem(m_hwndTV, &tvi);
|
|
|
|
ptidSel = reinterpret_cast<TREE_ITEM_DATA *>(tvi.lParam);
|
|
|
|
tvi.hItem = htiDst;
|
|
|
|
TreeView_GetItem(m_hwndTV, &tvi);
|
|
|
|
ptidDst = reinterpret_cast<TREE_ITEM_DATA *>(tvi.lParam);
|
|
|
|
BPIP_LIST::iterator iterlist;
|
|
INetCfgBindingPath * pncbpDst;
|
|
BIND_PATH_INFO * pbpiDst = NULL;
|
|
BPIP_LIST::iterator posDst;
|
|
BPIP_LIST::reverse_iterator posDstRev;
|
|
INetCfgComponent * pnccDstOwner;
|
|
|
|
if (fUp)
|
|
{
|
|
posDst = ptidDst->listbpipOnDisable.begin();
|
|
pbpiDst = *posDst;
|
|
}
|
|
else
|
|
{
|
|
posDstRev = ptidDst->listbpipOnDisable.rbegin();
|
|
pbpiDst = *posDstRev;
|
|
}
|
|
|
|
AssertSz(pbpiDst, "We never found a path to move before or after!");
|
|
|
|
pncbpDst = pbpiDst->pncbp;
|
|
|
|
Assert(pncbpDst);
|
|
|
|
hr = pncbpDst->GetOwner(&pnccDstOwner);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pnccDstOwner->QueryInterface(IID_INetCfgComponentBindings,
|
|
reinterpret_cast<LPVOID *>(&pnccb));
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
for (iterlist = ptidSel->listbpipOnDisable.begin();
|
|
iterlist != ptidSel->listbpipOnDisable.end() &&
|
|
SUCCEEDED(hr);
|
|
iterlist++)
|
|
{
|
|
// loop thru each item in the OnDisable list
|
|
INetCfgBindingPath * pncbp;
|
|
BIND_PATH_INFO * pbpi;
|
|
|
|
pbpi = *iterlist;
|
|
pncbp = pbpi->pncbp;
|
|
|
|
#if DBG
|
|
INetCfgComponent * pnccSrcOwner;
|
|
|
|
if (SUCCEEDED(pncbp->GetOwner(&pnccSrcOwner)))
|
|
{
|
|
AssertSz(pnccSrcOwner == pnccDstOwner, "Source and "
|
|
"dst path owners are not the same!?!");
|
|
ReleaseObj(pnccSrcOwner);
|
|
}
|
|
#endif
|
|
if (fUp)
|
|
{
|
|
TraceTag(ttidAdvCfg, "Treeview: Moving...");
|
|
DbgDumpBindPath(pncbp);
|
|
// Move this binding path before the tagret
|
|
hr = pnccb->MoveBefore(pncbp, pncbpDst);
|
|
TraceTag(ttidAdvCfg, "Treeview: before...");
|
|
DbgDumpBindPath(pncbpDst);
|
|
}
|
|
else
|
|
{
|
|
TraceTag(ttidAdvCfg, "Treeview: Moving...");
|
|
DbgDumpBindPath(pncbp);
|
|
// Move this binding path after the tagret
|
|
hr = pnccb->MoveAfter(pncbp, pncbpDst);
|
|
TraceTag(ttidAdvCfg, "Treeview: after...");
|
|
DbgDumpBindPath(pncbpDst);
|
|
}
|
|
}
|
|
|
|
ReleaseObj(pnccb);
|
|
}
|
|
|
|
ReleaseObj(pnccDstOwner);
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
HTREEITEM htiParent;
|
|
|
|
htiParent = TreeView_GetParent(m_hwndTV, htiSel);
|
|
|
|
// Now that the binding has been moved, move the tree view item to the
|
|
// proper place. If moving
|
|
|
|
if (fUp)
|
|
{
|
|
// If moving up, the "move after" item should be the previous
|
|
// sibling's previous sibling. If that doesn't exist, use the
|
|
// previous sibling's parent. That had better exist!
|
|
htiDst = TreeView_GetPrevSibling(m_hwndTV, htiDst);
|
|
if (!htiDst)
|
|
{
|
|
htiDst = htiParent;
|
|
}
|
|
}
|
|
|
|
AssertSz(htiDst, "No destination to move after!");
|
|
|
|
SendDlgItemMessage(TVW_Bindings, WM_SETREDRAW, FALSE, 0);
|
|
htiSel = HtiMoveTreeItemAfter(htiParent, htiDst, htiSel);
|
|
TreeView_SelectItem(m_hwndTV, htiSel);
|
|
SendDlgItemMessage(TVW_Bindings, WM_SETREDRAW, TRUE, 0);
|
|
|
|
::SetFocus(m_hwndTV);
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CBindingsDlg::OnBindingUp
|
|
//
|
|
// Purpose: Called when the PSB_Binding_Up button is pressed
|
|
//
|
|
// Arguments:
|
|
// wNotifyCode []
|
|
// wID []
|
|
// hWndCtl []
|
|
// bHandled []
|
|
//
|
|
// Returns:
|
|
//
|
|
// Author: danielwe 3 Dec 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
LRESULT CBindingsDlg::OnBindingUp(WORD wNotifyCode, WORD wID, HWND hWndCtl,
|
|
BOOL& bHandled)
|
|
{
|
|
OnBindingUpDown(TRUE);
|
|
|
|
return 0;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CBindingsDlg::OnBindingDown
|
|
//
|
|
// Purpose: Called when the PSB_Binding_Down button is pressed
|
|
//
|
|
// Arguments:
|
|
// wNotifyCode []
|
|
// wID []
|
|
// hWndCtl []
|
|
// bHandled []
|
|
//
|
|
// Returns:
|
|
//
|
|
// Author: danielwe 3 Dec 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
LRESULT CBindingsDlg::OnBindingDown(WORD wNotifyCode, WORD wID, HWND hWndCtl,
|
|
BOOL& bHandled)
|
|
{
|
|
OnBindingUpDown(FALSE);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CBindingsDlg::SetCheckboxStates
|
|
//
|
|
// Purpose: Sets the state of all checkboxes in the treeview.
|
|
//
|
|
// Arguments:
|
|
// (none)
|
|
//
|
|
// Returns: Nothing
|
|
//
|
|
// Author: danielwe 26 Nov 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
VOID CBindingsDlg::SetCheckboxStates()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CIterTreeView iterTV(m_hwndTV);
|
|
HTREEITEM hti;
|
|
TV_ITEM tvi = {0};
|
|
#ifdef ENABLETRACE
|
|
WCHAR szBuffer[256];
|
|
#endif
|
|
|
|
BOOL fHasPermission = FHasPermission(NCPERM_ChangeBindState);
|
|
|
|
while ((hti = iterTV.HtiNext()) && SUCCEEDED(hr))
|
|
{
|
|
TREE_ITEM_DATA * ptid;
|
|
|
|
#ifdef ENABLETRACE
|
|
tvi.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_TEXT;
|
|
tvi.pszText = szBuffer;
|
|
tvi.cchTextMax = celems(szBuffer);
|
|
#else
|
|
tvi.mask = TVIF_HANDLE | TVIF_PARAM;
|
|
#endif
|
|
tvi.hItem = hti;
|
|
TreeView_GetItem(m_hwndTV, &tvi);
|
|
|
|
ptid = reinterpret_cast<TREE_ITEM_DATA *>(tvi.lParam);
|
|
AssertSz(ptid, "No tree item data??");
|
|
|
|
#ifdef ENABLETRACE
|
|
TraceTag(ttidAdvCfg, "Setting checkbox state for item %S.", szBuffer);
|
|
#endif
|
|
|
|
BPIP_LIST::iterator iterBpip;
|
|
DWORD cEnabled = 0;
|
|
|
|
for (iterBpip = ptid->listbpipOnDisable.begin();
|
|
iterBpip != ptid->listbpipOnDisable.end();
|
|
iterBpip++)
|
|
{
|
|
BIND_PATH_INFO * pbpi = *iterBpip;
|
|
|
|
if (S_OK == pbpi->pncbp->IsEnabled())
|
|
{
|
|
cEnabled++;
|
|
}
|
|
}
|
|
|
|
tvi.mask = TVIF_STATE;
|
|
tvi.stateMask = TVIS_STATEIMAGEMASK;
|
|
|
|
UINT iState;
|
|
|
|
if (!fHasPermission)
|
|
{
|
|
iState = cEnabled ? SELS_FIXEDBINDING_ENABLED : SELS_FIXEDBINDING_DISABLED;
|
|
}
|
|
else
|
|
{
|
|
iState = cEnabled ? SELS_CHECKED : SELS_UNCHECKED;
|
|
}
|
|
tvi.state = INDEXTOSTATEIMAGEMASK(iState);
|
|
|
|
TreeView_SetItem(m_hwndTV, &tvi);
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CBindingsDlg::BuildBindingsList
|
|
//
|
|
// Purpose: Builds the contents of the Bindings treeview control
|
|
//
|
|
// Arguments:
|
|
// pncc [in] INetCfgComponent of adapter upon which this list is based
|
|
//
|
|
// Returns: Nothing
|
|
//
|
|
// Author: danielwe 26 Nov 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
VOID CBindingsDlg::BuildBindingsList(INetCfgComponent *pncc)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
Assert(pncc);
|
|
|
|
SBP_LIST listsbp;
|
|
CIterNetCfgUpperBindingPath ncupbIter(pncc);
|
|
INetCfgBindingPath * pncbp;
|
|
|
|
CWaitCursor wc;
|
|
|
|
SendDlgItemMessage(TVW_Bindings, WM_SETREDRAW, FALSE, 0);
|
|
|
|
while (SUCCEEDED(hr) && S_OK == (hr = ncupbIter.HrNext(&pncbp)))
|
|
{
|
|
listsbp.push_back(CSortableBindPath(pncbp));
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
SBP_LIST::iterator iterlist;
|
|
|
|
// This sorts the list descending by depth
|
|
listsbp.sort();
|
|
|
|
for (iterlist = listsbp.begin();
|
|
iterlist != listsbp.end() && SUCCEEDED(hr);
|
|
iterlist++)
|
|
{
|
|
INetCfgBindingPath * pncbp;
|
|
|
|
pncbp = (*iterlist).GetPath();
|
|
Assert(pncbp);
|
|
|
|
hr = HrHandleSubpath(listsbp, pncbp);
|
|
if (S_FALSE == hr)
|
|
{
|
|
hr = HrHandleTopLevel(pncbp);
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef ENABLETRACE
|
|
if (FALSE)
|
|
{
|
|
SBP_LIST::iterator iterlist;
|
|
for (iterlist = listsbp.begin(); iterlist != listsbp.end(); iterlist++)
|
|
{
|
|
INetCfgBindingPath * pncbp;
|
|
|
|
pncbp = (*iterlist).GetPath();
|
|
|
|
DWORD dwLen = GetDepthSpecialCase(pncbp);
|
|
|
|
TraceTag(ttidAdvCfg, "Length is %ld.", dwLen);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = HrOrderDisableLists();
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = HrOrderSubItems();
|
|
}
|
|
}
|
|
|
|
SendDlgItemMessage(TVW_Bindings, WM_SETREDRAW, TRUE, 0);
|
|
|
|
// Select first item in the tree
|
|
TreeView_SelectItem(m_hwndTV, TreeView_GetRoot(m_hwndTV));
|
|
|
|
{
|
|
SBP_LIST::iterator iterlist;
|
|
|
|
for (iterlist = listsbp.begin();
|
|
iterlist != listsbp.end() && SUCCEEDED(hr);
|
|
iterlist++)
|
|
{
|
|
INetCfgBindingPath * pncbp;
|
|
|
|
pncbp = (*iterlist).GetPath();
|
|
ReleaseObj(pncbp);
|
|
}
|
|
}
|
|
|
|
TraceError("CBindingsDlg::BuildBindingsList", hr);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: BpiFindBindPathInList
|
|
//
|
|
// Purpose: Given a bind path and a list, finds the BIND_PATH_INFO item
|
|
// that contains the given bind path.
|
|
//
|
|
// Arguments:
|
|
// pncbp [in] Bind path to look for
|
|
// listBpip [in, ref] List to search
|
|
//
|
|
// Returns: BIND_PATH_INFO of corresponding binding path, NULL if not
|
|
// found
|
|
//
|
|
// Author: danielwe 4 Dec 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
BIND_PATH_INFO *BpiFindBindPathInList(INetCfgBindingPath *pncbp,
|
|
BPIP_LIST &listBpip)
|
|
{
|
|
BPIP_LIST::iterator iterlist;
|
|
|
|
for (iterlist = listBpip.begin(); iterlist != listBpip.end(); iterlist++)
|
|
{
|
|
BIND_PATH_INFO * pbpi;
|
|
|
|
pbpi = *iterlist;
|
|
|
|
if (S_OK == pncbp->IsSamePathAs(pbpi->pncbp))
|
|
{
|
|
// Found the target path
|
|
return pbpi;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CBindingsDlg::HrOrderDisableList
|
|
//
|
|
// Purpose: Given a component's item data, orders the OnDisable list
|
|
// based on the true binding order for the owning component
|
|
//
|
|
// Arguments:
|
|
// ptid [in] Item data containing list
|
|
//
|
|
// Returns: S_OK if success, Win32 or OLE error code otherwise
|
|
//
|
|
// Author: danielwe 4 Dec 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
HRESULT CBindingsDlg::HrOrderDisableList(TREE_ITEM_DATA *ptid)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
INetCfgComponent * pnccOwner;
|
|
BIND_PATH_INFO * pbpi;
|
|
|
|
#if DBG
|
|
size_t cItems = ptid->listbpipOnDisable.size();
|
|
#endif
|
|
|
|
// Get the owning component of the first binding path in the list
|
|
pbpi = *(ptid->listbpipOnDisable.begin());
|
|
hr = pbpi->pncbp->GetOwner(&pnccOwner);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
CIterNetCfgBindingPath ncbpIter(pnccOwner);
|
|
INetCfgBindingPath * pncbp;
|
|
BPIP_LIST::iterator posPncbp;
|
|
BPIP_LIST::iterator posInsertAfter;
|
|
|
|
// Start this at beginning
|
|
posInsertAfter = ptid->listbpipOnDisable.begin();
|
|
|
|
while (SUCCEEDED(hr) && S_OK == (hr = ncbpIter.HrNext(&pncbp)))
|
|
{
|
|
pbpi = BpiFindBindPathInList(pncbp, ptid->listbpipOnDisable);
|
|
if (pbpi)
|
|
{
|
|
BPIP_LIST::iterator posErase;
|
|
|
|
posErase = find(ptid->listbpipOnDisable.begin(),
|
|
ptid->listbpipOnDisable.end(), pbpi);
|
|
|
|
AssertSz(posErase != ptid->listbpipOnDisable.end(), "It HAS"
|
|
" to be in the list!");
|
|
|
|
// Found bind path in list
|
|
// Remove it from present location and insert after next item
|
|
ptid->listbpipOnDisable.splice(posInsertAfter,
|
|
ptid->listbpipOnDisable,
|
|
posErase);
|
|
posInsertAfter++;
|
|
}
|
|
|
|
ReleaseObj(pncbp);
|
|
}
|
|
|
|
ReleaseObj(pnccOwner);
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
AssertSz(ptid->listbpipOnDisable.size() == cItems, "How come we don't"
|
|
" have the same number of items in the list anymore??");
|
|
hr = S_OK;
|
|
}
|
|
|
|
TraceError("CBindingsDlg::HrOrderDisableList", hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CBindingsDlg::HrOrderDisableLists
|
|
//
|
|
// Purpose: Orders the OnDisable lists of all tree view items according
|
|
// to the true binding order
|
|
//
|
|
// Arguments:
|
|
// (none)
|
|
//
|
|
// Returns: S_OK if success, Win32 or OLE error code otherwise
|
|
//
|
|
// Author: danielwe 4 Dec 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
HRESULT CBindingsDlg::HrOrderDisableLists()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CIterTreeView iterHti(m_hwndTV);
|
|
HTREEITEM hti;
|
|
TV_ITEM tvi = {0};
|
|
|
|
// Loop thru each tree item, ordering the OnDisable lists to match the
|
|
// owning component's true binding order
|
|
|
|
while ((hti = iterHti.HtiNext()) && SUCCEEDED(hr))
|
|
{
|
|
TREE_ITEM_DATA * ptid;
|
|
|
|
tvi.mask = TVIF_PARAM;
|
|
tvi.hItem = hti;
|
|
TreeView_GetItem(m_hwndTV, &tvi);
|
|
|
|
ptid = reinterpret_cast<TREE_ITEM_DATA *>(tvi.lParam);
|
|
AssertSz(ptid, "No item data?!");
|
|
|
|
hr = HrOrderDisableList(ptid);
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
|
|
TraceError("CBindingsDlg::HrOrderDisableLists", hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CBindingsDlg::HrOrderSubItems
|
|
//
|
|
// Purpose: Orders the sub items of the tree view to reflect the bind
|
|
// order of the system
|
|
//
|
|
// Arguments:
|
|
// (none)
|
|
//
|
|
// Returns: Nothing
|
|
//
|
|
// Author: danielwe 3 Dec 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
HRESULT CBindingsDlg::HrOrderSubItems()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
HTREEITEM htiTopLevel;
|
|
|
|
htiTopLevel = TreeView_GetRoot(m_hwndTV);
|
|
while (htiTopLevel)
|
|
{
|
|
HTREEITEM htiChild;
|
|
TREE_ITEM_DATA * ptid;
|
|
TV_ITEM tvi = {0};
|
|
|
|
tvi.mask = TVIF_PARAM;
|
|
tvi.hItem = htiTopLevel;
|
|
TreeView_GetItem(m_hwndTV, &tvi);
|
|
|
|
ptid = reinterpret_cast<TREE_ITEM_DATA *>(tvi.lParam);
|
|
AssertSz(ptid, "No tree item data??");
|
|
|
|
CIterNetCfgBindingPath ncbpIter(ptid->pncc);
|
|
INetCfgBindingPath * pncbp;
|
|
HTREEITEM htiInsertAfter = NULL;
|
|
|
|
while (SUCCEEDED(hr) && S_OK == (hr = ncbpIter.HrNext(&pncbp)))
|
|
{
|
|
BOOL fFound = FALSE;
|
|
|
|
htiChild = TreeView_GetChild(m_hwndTV, htiTopLevel);
|
|
|
|
while (htiChild && !fFound)
|
|
{
|
|
TREE_ITEM_DATA * ptidChild;
|
|
|
|
tvi.mask = TVIF_PARAM;
|
|
tvi.hItem = htiChild;
|
|
TreeView_GetItem(m_hwndTV, &tvi);
|
|
|
|
ptidChild = reinterpret_cast<TREE_ITEM_DATA *>(tvi.lParam);
|
|
AssertSz(ptidChild, "No tree item data??");
|
|
|
|
if (!ptidChild->fOrdered)
|
|
{
|
|
BIND_PATH_INFO * pbpi;
|
|
|
|
pbpi = BpiFindBindPathInList(pncbp,
|
|
ptidChild->listbpipOnDisable);
|
|
if (pbpi)
|
|
{
|
|
htiInsertAfter = HtiMoveTreeItemAfter(htiTopLevel,
|
|
htiInsertAfter,
|
|
htiChild);
|
|
ptidChild->fOrdered = TRUE;
|
|
|
|
fFound = TRUE;
|
|
// Go to next bind path
|
|
break;
|
|
}
|
|
}
|
|
|
|
htiChild = TreeView_GetNextSibling(m_hwndTV, htiChild);
|
|
}
|
|
|
|
ReleaseObj(pncbp);
|
|
}
|
|
|
|
htiTopLevel = TreeView_GetNextSibling(m_hwndTV, htiTopLevel);
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
|
|
TraceError("CBindingsDlg::HrOrderSubItems", hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CBindingsDlg::HtiAddTreeViewItem
|
|
//
|
|
// Purpose: Addes a new tree item according to provided information
|
|
//
|
|
// Arguments:
|
|
// pnccOwner [in] INetCfgComponent owner of component being added
|
|
// htiParent [in] HTREEITEM of parent (NULL if top-level item)
|
|
//
|
|
// Returns: HTREEITEM of newly added item
|
|
//
|
|
// Author: danielwe 26 Nov 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
HTREEITEM CBindingsDlg::HtiAddTreeViewItem(INetCfgComponent * pnccOwner,
|
|
HTREEITEM htiParent)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
HTREEITEM hti = NULL;
|
|
SP_CLASSIMAGELIST_DATA cid;
|
|
|
|
Assert(pnccOwner);
|
|
|
|
// Get the class image list structure
|
|
hr = HrSetupDiGetClassImageList(&cid);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
BSTR pszwName;
|
|
|
|
hr = pnccOwner->GetDisplayName(&pszwName);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
GUID guidClass;
|
|
|
|
hr = pnccOwner->GetClassGuid(&guidClass);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
INT nIndex;
|
|
|
|
// Get the component's class image list index
|
|
hr = HrSetupDiGetClassImageIndex(&cid, &guidClass,
|
|
&nIndex);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
TV_INSERTSTRUCT tvis = {0};
|
|
TREE_ITEM_DATA * ptid;
|
|
|
|
ptid = new TREE_ITEM_DATA;
|
|
if (ptid)
|
|
{
|
|
AddRefObj(ptid->pncc = pnccOwner);
|
|
ptid->fOrdered = FALSE;
|
|
|
|
tvis.item.mask = TVIF_PARAM | TVIF_TEXT |
|
|
TVIF_STATE | TVIF_IMAGE |
|
|
TVIF_SELECTEDIMAGE;
|
|
tvis.item.iImage = nIndex;
|
|
tvis.item.iSelectedImage = nIndex;
|
|
tvis.item.stateMask = TVIS_STATEIMAGEMASK | TVIS_EXPANDED;
|
|
tvis.item.state = TVIS_EXPANDED |
|
|
INDEXTOSTATEIMAGEMASK(SELS_CHECKED);
|
|
tvis.item.pszText = pszwName;
|
|
tvis.item.lParam = reinterpret_cast<LPARAM>(ptid);
|
|
tvis.hParent = htiParent;
|
|
tvis.hInsertAfter = TVI_LAST;
|
|
|
|
hti = TreeView_InsertItem(m_hwndTV, &tvis);
|
|
|
|
TraceTag(ttidAdvCfg, "Adding%s treeview item: %S",
|
|
htiParent ? " child" : "", tvis.item.pszText);
|
|
|
|
CoTaskMemFree(pszwName);
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
(void) HrSetupDiDestroyClassImageList(&cid);
|
|
}
|
|
|
|
return hti;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: AddToListIfNotAlreadyAdded
|
|
//
|
|
// Purpose: Addes the given bind path info structure to the given list
|
|
//
|
|
// Arguments:
|
|
// bpipList [in, ref] List to be added to
|
|
// pbpi [in] BIND_PATH_INFO structure to add
|
|
//
|
|
// Returns: Nothing
|
|
//
|
|
// Author: danielwe 26 Nov 1997
|
|
//
|
|
// Notes: If the item is not added to the list, it is deleted
|
|
//
|
|
VOID AddToListIfNotAlreadyAdded(BPIP_LIST &bpipList, BIND_PATH_INFO *pbpi)
|
|
{
|
|
BPIP_LIST::iterator iterBpip;
|
|
BOOL fAlreadyInList = FALSE;
|
|
|
|
for (iterBpip = bpipList.begin();
|
|
iterBpip != bpipList.end();
|
|
iterBpip++)
|
|
{
|
|
BIND_PATH_INFO * pbpiList = *iterBpip;
|
|
|
|
if (S_OK == pbpiList->pncbp->IsSamePathAs(pbpi->pncbp))
|
|
{
|
|
fAlreadyInList = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!fAlreadyInList)
|
|
{
|
|
bpipList.push_back(pbpi);
|
|
}
|
|
else
|
|
{
|
|
ReleaseObj(pbpi->pncbp);
|
|
delete pbpi;
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CBindingsDlg::AssociateBinding
|
|
//
|
|
// Purpose: Associates the given binding path with the given tree item
|
|
//
|
|
// Arguments:
|
|
// pncbpThis [in] Bind path to associate
|
|
// hti [in] HTREEITEM of item to associate the binding with
|
|
// dwFlags [in] One or combination of:
|
|
// ASSCF_ON_ENABLE - associate with OnEnable list
|
|
// ASSCF_ON_DISABLE - associate with OnDisable list
|
|
// ASSCF_ANCESTORS - associate this binding with all
|
|
// ancestors of the given item as
|
|
// well
|
|
//
|
|
// Returns: Nothing
|
|
//
|
|
// Author: danielwe 26 Nov 1997
|
|
//
|
|
// Notes: If binding is already present in the given list, it is not
|
|
// added again.
|
|
//
|
|
VOID CBindingsDlg::AssociateBinding(INetCfgBindingPath *pncbpThis,
|
|
HTREEITEM hti, DWORD dwFlags)
|
|
{
|
|
TV_ITEM tvi = {0};
|
|
TREE_ITEM_DATA * ptid;
|
|
|
|
#ifdef ENABLETRACE
|
|
WCHAR szBuffer[256];
|
|
#endif
|
|
|
|
//$ TODO (danielwe) 26 Nov 1997: Include ALL ancestors as well!
|
|
|
|
AssertSz(dwFlags, "NO flags!");
|
|
|
|
#ifdef ENABLETRACE
|
|
tvi.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_TEXT;
|
|
tvi.pszText = szBuffer;
|
|
tvi.cchTextMax = celems(szBuffer);
|
|
#else
|
|
tvi.mask = TVIF_HANDLE | TVIF_PARAM;
|
|
#endif
|
|
|
|
tvi.hItem = hti;
|
|
|
|
SideAssert(TreeView_GetItem(m_hwndTV, &tvi));
|
|
|
|
ptid = reinterpret_cast<TREE_ITEM_DATA *>(tvi.lParam);
|
|
AssertSz(ptid, "No tree item data??");
|
|
|
|
#ifdef ENABLETRACE
|
|
TraceTag(ttidAdvCfg, "Associating the following binding path with tree "
|
|
"item %S", szBuffer);
|
|
#endif
|
|
DbgDumpBindPath(pncbpThis);
|
|
|
|
if (dwFlags & ASSCF_ON_ENABLE)
|
|
{
|
|
BIND_PATH_INFO * pbpi;
|
|
|
|
pbpi = new BIND_PATH_INFO;
|
|
if (pbpi)
|
|
{
|
|
AddRefObj(pbpi->pncbp = pncbpThis);
|
|
|
|
// Note: (danielwe) 25 Nov 1997: Let's see if we need this. Until
|
|
// then, set to 0
|
|
|
|
pbpi->dwLength = 0;
|
|
|
|
AddToListIfNotAlreadyAdded(ptid->listbpipOnEnable, pbpi);
|
|
}
|
|
}
|
|
|
|
if (dwFlags & ASSCF_ON_DISABLE)
|
|
{
|
|
BIND_PATH_INFO * pbpi;
|
|
|
|
pbpi = new BIND_PATH_INFO;
|
|
if (pbpi)
|
|
{
|
|
AddRefObj(pbpi->pncbp = pncbpThis);
|
|
|
|
// Note: (danielwe) 25 Nov 1997: Let's see if we need this. Until
|
|
// then, set to 0
|
|
|
|
pbpi->dwLength = 0;
|
|
|
|
AddToListIfNotAlreadyAdded(ptid->listbpipOnDisable, pbpi);
|
|
}
|
|
}
|
|
|
|
if (dwFlags & ASSCF_ANCESTORS)
|
|
{
|
|
// Now associate the same binding with my parent (this will recurse to
|
|
// cover all ancestors)
|
|
HTREEITEM htiParent = TreeView_GetParent(m_hwndTV, hti);
|
|
if (htiParent)
|
|
{
|
|
AssociateBinding(pncbpThis, htiParent, dwFlags);
|
|
}
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CBindingsDlg::HrHandleSubpath
|
|
//
|
|
// Purpose: Handles the case of the given binding path being a subpath
|
|
// of an already associated binding path
|
|
//
|
|
// Arguments:
|
|
// listsbp [in, ref] Sorted list of binding paths to use in checking
|
|
// pncbpSub [in] Binding path to compare
|
|
//
|
|
// Returns: S_OK if success, Win32 or OLE error code otherwise
|
|
//
|
|
// Author: danielwe 26 Nov 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
HRESULT CBindingsDlg::HrHandleSubpath(SBP_LIST &listsbp,
|
|
INetCfgBindingPath *pncbpSub)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BOOL fProcessed = FALSE;
|
|
|
|
SBP_LIST::iterator iterlist;
|
|
|
|
TraceTag(ttidAdvCfg, "---------------------------------------------------"
|
|
"-------------------------");
|
|
DbgDumpBindPath(pncbpSub);
|
|
TraceTag(ttidAdvCfg, "...is being compared to the following...");
|
|
|
|
for (iterlist = listsbp.begin();
|
|
iterlist != listsbp.end() && SUCCEEDED(hr);
|
|
iterlist++)
|
|
{
|
|
INetCfgBindingPath * pncbp;
|
|
INetCfgComponent * pnccOwner;
|
|
|
|
pncbp = (*iterlist).GetPath();
|
|
Assert(pncbp);
|
|
|
|
if (S_OK == pncbp->IsSamePathAs(pncbpSub))
|
|
{
|
|
// Don't compare path to itself
|
|
continue;
|
|
}
|
|
|
|
hr = pncbp->GetOwner(&pnccOwner);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (FIsHidden(pnccOwner))
|
|
{
|
|
ReleaseObj(pnccOwner);
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
ReleaseObj(pnccOwner);
|
|
}
|
|
|
|
DbgDumpBindPath(pncbp);
|
|
hr = pncbpSub->IsSubPathOf(pncbp);
|
|
if (S_OK == hr)
|
|
{
|
|
CIterTreeView iterTV(m_hwndTV);
|
|
HTREEITEM hti;
|
|
TV_ITEM tvi = {0};
|
|
#ifdef ENABLETRACE
|
|
WCHAR szBuf[256] = {0};
|
|
#endif
|
|
|
|
while ((hti = iterTV.HtiNext()) && SUCCEEDED(hr))
|
|
{
|
|
TREE_ITEM_DATA * ptid;
|
|
|
|
#ifdef ENABLETRACE
|
|
tvi.mask = TVIF_TEXT | TVIF_PARAM | TVIF_HANDLE;
|
|
tvi.pszText = szBuf;
|
|
tvi.cchTextMax = celems(szBuf);
|
|
#else
|
|
tvi.mask = TVIF_PARAM | TVIF_HANDLE;
|
|
#endif
|
|
tvi.hItem = hti;
|
|
TreeView_GetItem(m_hwndTV, &tvi);
|
|
|
|
#ifdef ENABLETRACE
|
|
TraceTag(ttidAdvCfg, "TreeView item: %S.", szBuf);
|
|
#endif
|
|
ptid = reinterpret_cast<TREE_ITEM_DATA *>(tvi.lParam);
|
|
AssertSz(ptid, "No tree item data??");
|
|
|
|
// Look for pncbp in OnEnable of this item
|
|
BPIP_LIST::iterator iterBpip;
|
|
|
|
for (iterBpip = ptid->listbpipOnEnable.begin();
|
|
iterBpip != ptid->listbpipOnEnable.end();
|
|
iterBpip++)
|
|
{
|
|
INetCfgBindingPath * pncbpIter;
|
|
BIND_PATH_INFO * pbpi = *iterBpip;
|
|
|
|
pncbpIter = pbpi->pncbp;
|
|
AssertSz(pncbpIter, "No binding path?");
|
|
|
|
#ifdef ENABLETRACE
|
|
TraceTag(ttidAdvCfg, "OnEnable bindpath is");
|
|
DbgDumpBindPath (pncbpIter);
|
|
#endif
|
|
|
|
if (S_OK == pncbpIter->IsSamePathAs(pncbp))
|
|
{
|
|
hr = HrHandleSubItem(pncbpSub, pncbp, ptid, hti);
|
|
fProcessed = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = fProcessed ? S_OK : S_FALSE;
|
|
}
|
|
|
|
TraceError("CBindingsDlg::HrHandleSubpath", (hr == S_FALSE) ? S_OK : hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CBindingsDlg::HtiIsSubItem
|
|
//
|
|
// Purpose: Determines if the given component is already a sub item of
|
|
// the given tree item
|
|
//
|
|
// Arguments:
|
|
// pncc [in] Component to check
|
|
// hti [in] HTREEITEM of item to check
|
|
//
|
|
// Returns: HTREEITEM of sub item, NULL if it is not a subitem
|
|
//
|
|
// Author: danielwe 26 Nov 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
HTREEITEM CBindingsDlg::HtiIsSubItem(INetCfgComponent *pncc, HTREEITEM hti)
|
|
{
|
|
HTREEITEM htiCur;
|
|
|
|
htiCur = TreeView_GetChild(m_hwndTV, hti);
|
|
while (htiCur)
|
|
{
|
|
TREE_ITEM_DATA * ptid;
|
|
TV_ITEM tvi = {0};
|
|
|
|
tvi.hItem = htiCur;
|
|
tvi.mask = TVIF_HANDLE | TVIF_PARAM;
|
|
TreeView_GetItem(m_hwndTV, &tvi);
|
|
ptid = reinterpret_cast<TREE_ITEM_DATA *>(tvi.lParam);
|
|
|
|
AssertSz(ptid, "No item data??");
|
|
|
|
// Note: (danielwe) 26 Nov 1997: Make sure pointer comparison is
|
|
// ok.
|
|
if (pncc == ptid->pncc)
|
|
{
|
|
return htiCur;
|
|
}
|
|
|
|
htiCur = TreeView_GetNextSibling(m_hwndTV, htiCur);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CBindingsDlg::HrHandleSubItem
|
|
//
|
|
// Purpose: Handles the case of a single sub-item existing in the tree
|
|
// that matches the given binding path.
|
|
//
|
|
// Arguments:
|
|
// pncbpThis [in] Binding path being evaluated
|
|
// pncbpMatch [in] Binding path it is a subpath of
|
|
// ptid [in] Tree item data for tree view item that pncbpMatch
|
|
// is associated with
|
|
// htiMatchItem [in] HTREEITEM of above
|
|
//
|
|
// Returns: S_OK if success, Win32 or OLE error code otherwise
|
|
//
|
|
// Author: danielwe 26 Nov 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
HRESULT CBindingsDlg::HrHandleSubItem(INetCfgBindingPath *pncbpThis,
|
|
INetCfgBindingPath *pncbpMatch,
|
|
TREE_ITEM_DATA *ptid,
|
|
HTREEITEM htiMatchItem)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DWORD dwThisLen;
|
|
DWORD dwMatchLen;
|
|
DWORD dLen;
|
|
INetCfgComponent * pnccMatchItem;
|
|
|
|
pnccMatchItem = ptid->pncc;
|
|
|
|
Assert(pnccMatchItem);
|
|
|
|
dwThisLen = GetDepthSpecialCase(pncbpThis);
|
|
dwMatchLen = GetDepthSpecialCase(pncbpMatch);
|
|
|
|
dLen = dwMatchLen - dwThisLen;
|
|
|
|
if ((dwMatchLen - dwThisLen) == 1 ||
|
|
(S_OK == (hr = HrComponentIsHidden(pncbpMatch, dLen))))
|
|
{
|
|
INetCfgComponent * pnccThisOwner;
|
|
INetCfgComponent * pnccMatchOwner;
|
|
|
|
hr = pncbpThis->GetOwner(&pnccThisOwner);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pncbpMatch->GetOwner(&pnccMatchOwner);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (!FIsHidden(pnccThisOwner) &&
|
|
!FDontExposeLower(pnccMatchOwner))
|
|
{
|
|
hr = HrHandleValidSubItem(pncbpThis, pncbpMatch,
|
|
pnccThisOwner,
|
|
htiMatchItem, ptid);
|
|
}
|
|
|
|
ReleaseObj(pnccMatchOwner);
|
|
}
|
|
|
|
ReleaseObj(pnccThisOwner);
|
|
}
|
|
}
|
|
|
|
AssociateBinding(pncbpThis, htiMatchItem,
|
|
ASSCF_ON_ENABLE | ASSCF_ANCESTORS);
|
|
|
|
TraceError("CBindingsDlg::HrHandleSubItem", (hr == S_FALSE) ? S_OK : hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CBindingsDlg::HrHandleValidSubItem
|
|
//
|
|
// Purpose: Handles the case of the given binding path being a sub item
|
|
// of at least on item in the tree.
|
|
//
|
|
// Arguments:
|
|
// pncbpThis [in] THIS binding path
|
|
// pncbpMatch [in] MATCH binding path
|
|
// pnccThisOwner [in] Owner of THIS binding path
|
|
// htiMatchItem [in] HTREEITEM of match item
|
|
// ptid [in] TREE item data for match item
|
|
//
|
|
// Returns: S_OK if success, Win32 or OLE error code otherwise
|
|
//
|
|
// Author: danielwe 1 Dec 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
HRESULT CBindingsDlg::HrHandleValidSubItem(INetCfgBindingPath *pncbpThis,
|
|
INetCfgBindingPath *pncbpMatch,
|
|
INetCfgComponent *pnccThisOwner,
|
|
HTREEITEM htiMatchItem,
|
|
TREE_ITEM_DATA *ptid)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
HTREEITEM htiNew = NULL;
|
|
|
|
if (pnccThisOwner != ptid->pncc)
|
|
{
|
|
// Check if it is already present as a subitem
|
|
htiNew = HtiIsSubItem(pnccThisOwner, htiMatchItem);
|
|
if (!htiNew)
|
|
{
|
|
htiNew = HtiAddTreeViewItem(pnccThisOwner, htiMatchItem);
|
|
}
|
|
|
|
AssertSz(htiNew, "No new or existing tree item!?!");
|
|
|
|
AssociateBinding(pncbpMatch, htiNew,
|
|
ASSCF_ON_ENABLE | ASSCF_ON_DISABLE);
|
|
AssociateBinding(pncbpThis, htiNew, ASSCF_ON_ENABLE);
|
|
}
|
|
|
|
TraceError("CBindingsDlg::HrHandleComponent", hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CBindingsDlg::HrComponentIsHidden
|
|
//
|
|
// Purpose: Determines if the Nth component of the given binding path is
|
|
// hidden.
|
|
//
|
|
// Arguments:
|
|
// pncbp [in] Binding path to check
|
|
// iComp [in] Index of component to check for hidden characterstic
|
|
//
|
|
// Returns: S_OK if success, Win32 or OLE error code otherwise
|
|
//
|
|
// Author: danielwe 26 Nov 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
HRESULT CBindingsDlg::HrComponentIsHidden(INetCfgBindingPath *pncbp,
|
|
DWORD iComp)
|
|
{
|
|
Assert(pncbp);
|
|
|
|
HRESULT hr = S_OK;
|
|
CIterNetCfgBindingInterface ncbiIter(pncbp);
|
|
INetCfgBindingInterface * pncbi;
|
|
|
|
// Convert from component count to interface count
|
|
iComp--;
|
|
|
|
AssertSz(iComp > 0, "We should never be looking for the first component!");
|
|
|
|
while (SUCCEEDED(hr) && iComp && S_OK == (hr = ncbiIter.HrNext(&pncbi)))
|
|
{
|
|
iComp--;
|
|
if (!iComp)
|
|
{
|
|
INetCfgComponent * pnccLower;
|
|
|
|
hr = pncbi->GetLowerComponent(&pnccLower);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (!FIsHidden(pnccLower))
|
|
{
|
|
hr = S_FALSE;
|
|
}
|
|
|
|
ReleaseObj(pnccLower);
|
|
}
|
|
}
|
|
ReleaseObj(pncbi);
|
|
}
|
|
|
|
TraceError("CBindingsDlg::HrComponentIsHidden", (hr == S_FALSE) ? S_OK : hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CBindingsDlg::HrHandleTopLevel
|
|
//
|
|
// Purpose: Handles the case of the given binding path not being associated
|
|
// with any existing tree view item
|
|
//
|
|
// Arguments:
|
|
// pncbpThis [in] Binding path being evaluated
|
|
//
|
|
// Returns: S_OK if success, Win32 or OLE error code otherwise
|
|
//
|
|
// Author: danielwe 26 Nov 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
HRESULT CBindingsDlg::HrHandleTopLevel(INetCfgBindingPath *pncbpThis)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
INetCfgComponent * pnccOwner;
|
|
BOOL fFound = FALSE;
|
|
|
|
// Check if the owner of this path is already present in the tree
|
|
hr = pncbpThis->GetOwner(&pnccOwner);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
CIterTreeView iterTV(m_hwndTV);
|
|
HTREEITEM hti;
|
|
TV_ITEM tvi = {0};
|
|
|
|
while ((hti = iterTV.HtiNext()) && SUCCEEDED(hr))
|
|
{
|
|
TREE_ITEM_DATA * ptid;
|
|
|
|
tvi.mask = TVIF_PARAM | TVIF_HANDLE;
|
|
tvi.hItem = hti;
|
|
TreeView_GetItem(m_hwndTV, &tvi);
|
|
|
|
ptid = reinterpret_cast<TREE_ITEM_DATA *>(tvi.lParam);
|
|
AssertSz(ptid, "No tree item data??");
|
|
|
|
// Note: (danielwe) 25 Nov 1997: Pointer comparison may not
|
|
// work. Use GUIDs if necessary.
|
|
if (ptid->pncc == pnccOwner)
|
|
{
|
|
// Found match with THIS binding owner and an existing tree
|
|
// item
|
|
AssociateBinding(pncbpThis, hti, ASSCF_ON_ENABLE |
|
|
ASSCF_ON_DISABLE);
|
|
|
|
fFound = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED(hr) && !fFound)
|
|
{
|
|
// Not found in the tree
|
|
if (!FIsHidden(pnccOwner))
|
|
{
|
|
DWORD dwLen;
|
|
|
|
dwLen = GetDepthSpecialCase(pncbpThis);
|
|
|
|
if (dwLen > 2)
|
|
{
|
|
HTREEITEM hti;
|
|
|
|
hti = HtiAddTreeViewItem(pnccOwner, NULL);
|
|
if (hti)
|
|
{
|
|
AssociateBinding(pncbpThis, hti,
|
|
ASSCF_ON_ENABLE |
|
|
ASSCF_ON_DISABLE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
ReleaseObj(pnccOwner);
|
|
}
|
|
|
|
TraceError("CBindingsDlg::HrHandleTopLevel", (S_FALSE == hr) ? S_OK : hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ChangeTreeItemParam
|
|
//
|
|
// Purpose: Helper function to change the lParam of a tree view item
|
|
//
|
|
// Arguments:
|
|
// hwndTV [in] Tree view window
|
|
// hitem [in] Handle to item to change
|
|
// lparam [in] New value of lParam
|
|
//
|
|
// Returns: Nothing
|
|
//
|
|
// Author: danielwe 3 Dec 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
VOID ChangeTreeItemParam(HWND hwndTV, HTREEITEM hitem, LPARAM lparam)
|
|
{
|
|
TV_ITEM tvi;
|
|
|
|
tvi.hItem = hitem;
|
|
tvi.mask = TVIF_PARAM;
|
|
tvi.lParam = lparam;
|
|
|
|
TreeView_SetItem(hwndTV, &tvi);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CBindingsDlg::HtiMoveTreeItemAfter
|
|
//
|
|
// Purpose: Moves the given tree view item and all its children after the
|
|
// given treeview item
|
|
//
|
|
// Arguments:
|
|
// htiParent [in] Parent treeview item
|
|
// htiDest [in] Item to move after
|
|
// htiSrc [in] Item to move
|
|
//
|
|
// Returns: Newly added treeview item
|
|
//
|
|
// Author: danielwe 3 Dec 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
HTREEITEM CBindingsDlg::HtiMoveTreeItemAfter(HTREEITEM htiParent,
|
|
HTREEITEM htiDest,
|
|
HTREEITEM htiSrc)
|
|
{
|
|
HTREEITEM htiNew;
|
|
HTREEITEM htiChild;
|
|
HTREEITEM htiNextChild;
|
|
TV_INSERTSTRUCT tvis;
|
|
WCHAR szText[256];
|
|
|
|
TraceTag(ttidAdvCfg, "Moving ...");
|
|
DbgDumpTreeViewItem(m_hwndTV, htiSrc);
|
|
TraceTag(ttidAdvCfg, "... after ...");
|
|
DbgDumpTreeViewItem(m_hwndTV, htiDest);
|
|
|
|
// retieve the items data
|
|
tvis.item.hItem = htiSrc;
|
|
tvis.item.mask = TVIF_IMAGE | TVIF_PARAM | TVIF_SELECTEDIMAGE |
|
|
TVIF_TEXT | TVIF_STATE;
|
|
tvis.item.stateMask = TVIS_STATEIMAGEMASK;
|
|
tvis.item.pszText = szText;
|
|
tvis.item.cchTextMax = celems(szText);
|
|
TreeView_GetItem(m_hwndTV, &tvis.item);
|
|
|
|
if (NULL == htiDest)
|
|
{
|
|
tvis.hInsertAfter = TVI_LAST;
|
|
}
|
|
else
|
|
{
|
|
if (htiParent == htiDest)
|
|
{
|
|
tvis.hInsertAfter = TVI_FIRST;
|
|
}
|
|
else
|
|
{
|
|
tvis.hInsertAfter = htiDest;
|
|
}
|
|
}
|
|
|
|
tvis.hParent = htiParent;
|
|
|
|
// add our new one
|
|
htiNew = TreeView_InsertItem(m_hwndTV, &tvis);
|
|
|
|
// copy all children
|
|
htiChild = TreeView_GetChild(m_hwndTV, htiSrc);
|
|
while (htiChild)
|
|
{
|
|
htiNextChild = TreeView_GetNextSibling(m_hwndTV, htiChild);
|
|
|
|
HtiMoveTreeItemAfter(htiNew, NULL, htiChild);
|
|
htiChild = htiNextChild;
|
|
}
|
|
|
|
// set old location param to null, so when it is removed,
|
|
// our lparam is not deleted by our remove routine
|
|
ChangeTreeItemParam(m_hwndTV, htiSrc, NULL);
|
|
|
|
// remove from old location
|
|
TreeView_DeleteItem(m_hwndTV, htiSrc);
|
|
|
|
return htiNew;
|
|
}
|
|
|
|
//
|
|
// Treeview flat iterator
|
|
//
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CIterTreeView::HtiNext
|
|
//
|
|
// Purpose: Advances the iterator to the next treeview item
|
|
//
|
|
// Arguments:
|
|
// (none)
|
|
//
|
|
// Returns: Next HTREEITEM in tree view
|
|
//
|
|
// Author: danielwe 26 Nov 1997
|
|
//
|
|
// Notes: Uses a systematic iteration. First all children of first item
|
|
// are returned, then all siblings, then next sibling and so on
|
|
//
|
|
HTREEITEM CIterTreeView::HtiNext()
|
|
{
|
|
HTREEITEM htiRet;
|
|
HTREEITEM hti;
|
|
|
|
if (m_stackHti.empty())
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
htiRet = Front();
|
|
hti = TreeView_GetChild(m_hwndTV, htiRet);
|
|
if (!hti)
|
|
{
|
|
PopAndDelete();
|
|
hti = TreeView_GetNextSibling(m_hwndTV, htiRet);
|
|
if (hti)
|
|
{
|
|
PushAndAlloc(hti);
|
|
}
|
|
else
|
|
{
|
|
if (!m_stackHti.empty())
|
|
{
|
|
hti = TreeView_GetNextSibling(m_hwndTV, Front());
|
|
PopAndDelete();
|
|
if (hti)
|
|
{
|
|
PushAndAlloc(hti);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
PushAndAlloc(hti);
|
|
}
|
|
|
|
return htiRet;
|
|
}
|
|
|