Leaked source code of windows server 2003
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.
 
 
 
 
 
 

885 lines
25 KiB

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1997.
//
// File: A C L I S T . C P P
//
// Contents: Functions related to listview control in adavnced
// configuration dialog.
//
// Notes:
//
// Author: danielwe 3 Dec 1997
//
//----------------------------------------------------------------------------
#include "pch.h"
#pragma hdrstop
#include "acbind.h"
#include "acsheet.h"
#include "lancmn.h"
#include "ncnetcfg.h"
#include "ncnetcon.h"
#include "ncsetup.h"
#include "foldinc.h"
extern const WCHAR c_szInfId_MS_TCPIP[];
HRESULT CBindingsDlg::HrGetAdapters(INetCfgComponent *pncc,
NCC_LIST *plistNcc)
{
Assert(pncc);
HRESULT hr = S_OK;
CIterNetCfgBindingPath ncbpIter(pncc);
INetCfgBindingPath * pncbp;
NCC_LIST listncc;
INetCfgComponent * pnccLast;
while (SUCCEEDED(hr) && S_OK == (hr = ncbpIter.HrNext(&pncbp)))
{
hr = HrGetLastComponentAndInterface(pncbp, &pnccLast, NULL);
if (SUCCEEDED(hr))
{
hr = HrIsConnection(pnccLast);
if (S_OK == hr)
{
plistNcc->push_back(pnccLast);
}
else
{
// Don't need it anymore so release it
ReleaseObj(pnccLast);
}
}
ReleaseObj(pncbp);
}
if (SUCCEEDED(hr))
{
if (plistNcc->empty())
{
hr = S_FALSE;
}
else
{
plistNcc->unique();
hr = S_OK;
}
}
TraceError("CBindingsDlg::HrGetAdapters", hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Member: CBindingsDlg::HrBuildAdapterList
//
// Purpose: Builds the list of adapters displayed in the listview control
//
// Arguments:
// (none)
//
// Returns: S_OK if succeeded, OLE or Win32 error otherwise
//
// Author: danielwe 19 Nov 1997
//
// Notes:
//
HRESULT CBindingsDlg::HrBuildAdapterList()
{
HRESULT hr = S_OK;
INetCfgComponent * pncc = NULL;
SP_CLASSIMAGELIST_DATA cid;
INT nIndexWan;
INT ipos = 0;
NCC_LIST listncc;
Assert(m_pnc);
// Get the class image list structure
hr = HrSetupDiGetClassImageList(&cid);
if (SUCCEEDED(hr))
{
// Get the modem class image list index
hr = HrSetupDiGetClassImageIndex(&cid,
const_cast<LPGUID>(&GUID_DEVCLASS_MODEM),
&nIndexWan);
}
if (SUCCEEDED(hr))
{
hr = m_pnc->FindComponent(c_szInfId_MS_TCPIP, &pncc);
if (S_FALSE == hr)
{
// Hmm, TCP/IP is not installed. Better look for a protocol that
// has bindings to an adapter.
//
CIterNetCfgComponent nccIter(m_pnc, &GUID_DEVCLASS_NETTRANS);
while (SUCCEEDED(hr) && S_OK == (hr = nccIter.HrNext(&pncc)))
{
hr = HrGetAdapters(pncc, &listncc);
ReleaseObj(pncc);
if (S_OK == hr)
{
// We found one! Yay.
break;
}
}
}
else if (S_OK == hr)
{
hr = HrGetAdapters(pncc, &listncc);
ReleaseObj(pncc);
}
}
if (S_OK == hr)
{
// Iterate all LAN connections
//
INetConnectionManager * pconMan;
HRESULT hr = HrCreateInstance(
CLSID_LanConnectionManager,
CLSCTX_SERVER | CLSCTX_NO_CODE_DOWNLOAD,
&pconMan);
TraceHr(ttidError, FAL, hr, FALSE, "HrCreateInstance");
if (SUCCEEDED(hr))
{
NCC_LIST::iterator iterlist;
INetCfgComponent * pnccToAdd;
for (iterlist = listncc.begin();
iterlist != listncc.end();
iterlist++)
{
CIterNetCon ncIter(pconMan, NCME_DEFAULT);
INetConnection * pconn;
GUID guidAdd;
BOOL fAdded = FALSE;
pnccToAdd = *iterlist;
(VOID) pnccToAdd->GetInstanceGuid(&guidAdd);
while (SUCCEEDED(hr) && !fAdded &&
(S_OK == (ncIter.HrNext(&pconn))))
{
// Compare guid of connection's adapter to this
// one. If we have a match, add it to the listview
if (FPconnEqualGuid(pconn, guidAdd))
{
NETCON_PROPERTIES* pProps;
hr = pconn->GetProperties(&pProps);
if (SUCCEEDED(hr))
{
AddListViewItem(pnccToAdd, ipos, m_nIndexLan,
pProps->pszwName);
fAdded = TRUE;
ipos++;
FreeNetconProperties(pProps);
}
}
ReleaseObj(pconn);
}
#if DBG
if (!fAdded)
{
WCHAR szwGuid[64];
StringFromGUID2(guidAdd, szwGuid, sizeof(szwGuid));
TraceTag(ttidAdvCfg, "Never added item %S for this "
"connection!", szwGuid);
}
#endif
// Balance AddRef from HrGetLastComponentAndInterface()
ReleaseObj(pnccToAdd);
}
ReleaseObj(pconMan);
}
listncc.erase(listncc.begin(), listncc.end());
}
// Display WAN Adapter Bindings
if (SUCCEEDED(hr))
{
GetWanOrdering();
AddListViewItem(NULL, m_fWanBindingsFirst ? 0 : ipos, nIndexWan,
SzLoadIds(IDS_ADVCFG_WAN_ADAPTERS));
}
(void) HrSetupDiDestroyClassImageList(&cid);
if (SUCCEEDED(hr))
{
SetAdapterButtons();
ListView_SetColumnWidth(m_hwndLV, 0, LVSCW_AUTOSIZE);
hr = S_OK;
}
// Select first item
ListView_SetItemState(m_hwndLV, 0, LVIS_FOCUSED | LVIS_SELECTED,
LVIS_FOCUSED | LVIS_SELECTED);
TraceError("CBindingsDlg::HrBuildAdapterList", hr);
return hr;
}
VOID CBindingsDlg::GetWanOrdering()
{
INetCfgSpecialCase * pncsc = NULL;
if (SUCCEEDED(m_pnc->QueryInterface(IID_INetCfgSpecialCase,
reinterpret_cast<LPVOID*>(&pncsc))))
{
(VOID) pncsc->GetWanAdaptersFirst(&m_fWanBindingsFirst);
ReleaseObj(pncsc);
}
}
VOID CBindingsDlg::SetWanOrdering()
{
INetCfgSpecialCase * pncsc = NULL;
if (SUCCEEDED(m_pnc->QueryInterface(IID_INetCfgSpecialCase,
reinterpret_cast<LPVOID*>(&pncsc))))
{
(VOID) pncsc->SetWanAdaptersFirst(m_fWanBindingsFirst);
ReleaseObj(pncsc);
}
}
//+---------------------------------------------------------------------------
//
// Member: CBindingsDlg::AddListViewItem
//
// Purpose: Adds the given component to the listview
//
// Arguments:
// pncc [in] Component to be added. If NULL, then this is the
// special WAN adapter component.
// ipos [in] Position at which to add
// nIndex [in] Index of icon into system image list
// pszConnName [in] Connection name
//
// Returns: Nothing
//
// Author: danielwe 3 Dec 1997
//
// Notes:
//
VOID CBindingsDlg::AddListViewItem(INetCfgComponent *pncc, INT ipos,
INT nIndex, PCWSTR pszConnName)
{
LV_ITEM lvi = {0};
lvi.mask = LVIF_TEXT | LVIF_IMAGE |
LVIF_STATE | LVIF_PARAM;
lvi.iImage = nIndex;
lvi.iItem = ipos;
AddRefObj(pncc);
lvi.lParam = reinterpret_cast<LPARAM>(pncc);
lvi.pszText = const_cast<PWSTR>(pszConnName);
ListView_InsertItem(m_hwndLV, &lvi);
}
//+---------------------------------------------------------------------------
//
// Member: CBindingsDlg::OnListItemChanged
//
// Purpose: Called when the LVN_ITEMCHANGED message is received
//
// Arguments:
// idCtrl []
// pnmh []
// bHandled []
//
// Returns:
//
// Author: danielwe 19 Nov 1997
//
// Notes:
//
LRESULT CBindingsDlg::OnListItemChanged(int idCtrl, LPNMHDR pnmh,
BOOL& bHandled)
{
NM_LISTVIEW * pnmlv = reinterpret_cast<NM_LISTVIEW *>(pnmh);
Assert(pnmlv);
// Check if selection changed
if ((pnmlv->uNewState & LVIS_SELECTED) &&
(!(pnmlv->uOldState & LVIS_SELECTED)))
{
if (pnmlv->iItem != m_iItemSel)
{
// Selection changed to different item
OnAdapterChange(pnmlv->iItem);
m_iItemSel = pnmlv->iItem;
}
}
return 0;
}
//+---------------------------------------------------------------------------
//
// Member: CBindingsDlg::OnListDeleteItem
//
// Purpose: Called when the LVN_DELETEITEM message is received.
//
// Arguments:
// idCtrl []
// pnmh []
// bHandled []
//
// Returns:
//
// Author: danielwe 4 Dec 1997
//
// Notes:
//
LRESULT CBindingsDlg::OnListDeleteItem(int idCtrl, LPNMHDR pnmh,
BOOL& bHandled)
{
LV_ITEM lvi = {0};
INetCfgComponent * pncc;
NM_LISTVIEW * pnmlv = reinterpret_cast<NM_LISTVIEW *>(pnmh);
Assert(pnmlv);
lvi.mask = LVIF_PARAM;
lvi.iItem = pnmlv->iItem;
ListView_GetItem(m_hwndLV, &lvi);
pncc = reinterpret_cast<INetCfgComponent *>(lvi.lParam);
ReleaseObj(pncc);
return 0;
}
//+---------------------------------------------------------------------------
//
// Member: CBindingsDlg::OnAdapterChange
//
// Purpose: Handles the selection of a different adapter from the listview
//
// Arguments:
// iItem [in] Item in list that was selected
//
// Returns: S_OK if success, OLE or Win32 error otherwise
//
// Author: danielwe 19 Nov 1997
//
// Notes:
//
VOID CBindingsDlg::OnAdapterChange(INT iItem)
{
LV_ITEM lvi = {0};
INetCfgComponent * pncc;
PWSTR szwText;
WCHAR szBuffer[256];
lvi.mask = LVIF_TEXT | LVIF_PARAM;
lvi.pszText = szBuffer;
lvi.cchTextMax = celems(szBuffer);
lvi.iItem = iItem;
ListView_GetItem(m_hwndLV, &lvi);
TreeView_DeleteAllItems(m_hwndTV);
pncc = reinterpret_cast<INetCfgComponent *>(lvi.lParam);
if (pncc)
{
BuildBindingsList(pncc);
SetCheckboxStates();
}
SetAdapterButtons();
DwFormatStringWithLocalAlloc(SzLoadIds(IDS_BINDINGS_FOR), &szwText,
lvi.pszText);
BOOL bShouldEnable = TRUE;
if (!pncc)
{
// If the WAN bindings item is selected, hide and disable the treeview
bShouldEnable = FALSE;
}
else
{
// if a LAN item is selected, make sure the treeview is enabled
GUID guid;
HRESULT hr = pncc->GetInstanceGuid(&guid);
if (SUCCEEDED(hr))
{
ConnListEntry cle;
hr = g_ccl.HrFindConnectionByGuid(&guid, cle);
if (S_FALSE == hr)
{
hr = g_ccl.HrRefreshConManEntries();
if (SUCCEEDED(hr))
{
hr = g_ccl.HrFindConnectionByGuid(&guid, cle);
}
}
if (S_OK == hr)
{
if ( (NCM_LAN == cle.ccfe.GetNetConMediaType()) &&
(cle.ccfe.GetCharacteristics() & NCCF_BRIDGED) )
{
bShouldEnable = FALSE;
}
}
}
}
if (bShouldEnable)
{
::ShowWindow(GetDlgItem(IDH_TXT_ADVGFG_BINDINGS), SW_SHOW);
::EnableWindow(GetDlgItem(IDH_TXT_ADVGFG_BINDINGS), TRUE);
::EnableWindow(GetDlgItem(TVW_Bindings), TRUE);
}
else
{
::ShowWindow(GetDlgItem(IDH_TXT_ADVGFG_BINDINGS), SW_HIDE);
::EnableWindow(GetDlgItem(IDH_TXT_ADVGFG_BINDINGS), FALSE);
::EnableWindow(GetDlgItem(TVW_Bindings), FALSE);
}
SetDlgItemText(IDH_TXT_ADVGFG_BINDINGS, szwText);
LocalFree(szwText);
}
//+---------------------------------------------------------------------------
//
// Member: CBindingsDlg::OnAdapterUpDown
//
// Purpose: Helper function that performs most of the work to move
// adapter bindings
//
// Arguments:
// fUp [in] TRUE if moving up, FALSE if down
//
// Returns: Nothing
//
// Author: danielwe 2 Dec 1997
//
// Notes:
//
VOID CBindingsDlg::OnAdapterUpDown(BOOL fUp)
{
INetCfgComponent * pnccSrc;
INetCfgComponent * pnccDst;
INT iSel;
INT iDst;
LV_ITEM lvi = {0};
WCHAR szBuffer[256];
iSel = ListView_GetNextItem(m_hwndLV, -1, LVNI_SELECTED);
AssertSz(iSel != -1, "No Selection?!?!?");
lvi.mask = LVIF_PARAM | LVIF_TEXT | LVIF_IMAGE | LVIF_STATE;
lvi.pszText = szBuffer;
lvi.cchTextMax = celems(szBuffer);
lvi.iItem = iSel;
ListView_GetItem(m_hwndLV, &lvi);
pnccSrc = reinterpret_cast<INetCfgComponent *>(lvi.lParam);
if (pnccSrc)
{
// Normal LAN adapter
iDst = ListView_GetNextItem(m_hwndLV, iSel,
fUp ? LVNI_ABOVE : LVNI_BELOW);
AssertSz(iDst != -1, "No item above or below!");
}
else
{
m_fWanBindingsFirst = fUp;
// WAN binding item
iDst = fUp ? 0 : ListView_GetItemCount(m_hwndLV) - 1;
}
lvi.iItem = iDst;
ListView_GetItem(m_hwndLV, &lvi);
pnccDst = reinterpret_cast<INetCfgComponent *>(lvi.lParam);
AssertSz(pnccDst, "Dest Component is NULL!?!?");
if (pnccSrc)
{
MoveAdapterBindings(pnccSrc, pnccDst, fUp ? MAB_UP : MAB_DOWN);
}
else
{
SetWanOrdering();
}
// Delete source item and move to where dest item is
// Note: (danielwe) 2 Dec 1997: For LVN_DELETEITEM handler, make sure
// refcount remains the same
// Get item we are moving
lvi.iItem = iSel;
ListView_GetItem(m_hwndLV, &lvi);
// Make the lParam of the item NULL so we don't release it
ChangeListItemParam(m_hwndLV, iSel, NULL);
ListView_DeleteItem(m_hwndLV, iSel);
// Change its index
lvi.iItem = iDst;
lvi.state = lvi.stateMask = 0;
// And insert in new location
int iItem = ListView_InsertItem(m_hwndLV, &lvi);
if (-1 != iItem)
{
ListView_SetItemState(m_hwndLV, iItem, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
}
// Reset cached selection
m_iItemSel = iDst;
SetAdapterButtons();
::SetFocus(m_hwndLV);
}
//+---------------------------------------------------------------------------
//
// Member: CBindingsDlg::OnAdapterUp
//
// Purpose: Called when the adapter UP arrow button is pressed
//
// Arguments:
// wNotifyCode []
// wID []
// hWndCtl []
// bHandled []
//
// Returns:
//
// Author: danielwe 2 Dec 1997
//
// Notes:
//
LRESULT CBindingsDlg::OnAdapterUp(WORD wNotifyCode, WORD wID, HWND hWndCtl,
BOOL& bHandled)
{
OnAdapterUpDown(TRUE);
return 0;
}
//+---------------------------------------------------------------------------
//
// Member: CBindingsDlg::OnAdapterDown
//
// Purpose: Called when the adapter DOWN button is pressed
//
// Arguments:
// wNotifyCode []
// wID []
// hWndCtl []
// bHandled []
//
// Returns:
//
// Author: danielwe 2 Dec 1997
//
// Notes:
//
LRESULT CBindingsDlg::OnAdapterDown(WORD wNotifyCode, WORD wID, HWND hWndCtl,
BOOL& bHandled)
{
OnAdapterUpDown(FALSE);
return 0;
}
//+---------------------------------------------------------------------------
//
// Member: CBindingsDlg::FIsWanBinding
//
// Purpose: Determines if the given list view item is the special WAN
// adapter ordering item.
//
// Arguments:
// iItem [in] List view item to test
//
// Returns: TRUE if this is the WAN adapter ordering item or FALSE if not
//
// Author: danielwe 21 Jul 1998
//
// Notes:
//
BOOL CBindingsDlg::FIsWanBinding(INT iItem)
{
if (iItem != -1)
{
LV_ITEM lvi = {0};
lvi.mask = LVIF_PARAM;
lvi.iItem = iItem;
ListView_GetItem(m_hwndLV, &lvi);
return !lvi.lParam;
}
else
{
// Invalid item can't be the WAN binding
return FALSE;
}
}
//+---------------------------------------------------------------------------
//
// Member: CBindingsDlg::SetAdapterButtons
//
// Purpose: Sets the state of the up and down arrow buttons for the
// adapters listview
//
// Arguments:
// (none)
//
// Returns: Nothing
//
// Author: danielwe 19 Nov 1997
//
// Notes:
//
VOID CBindingsDlg::SetAdapterButtons()
{
INT iItemAbove = -1;
INT iItemBelow = -1;
INT iItem;
iItem = ListView_GetNextItem(m_hwndLV, -1, LVNI_SELECTED);
if (ListView_GetItemCount(m_hwndLV) > 1)
{
iItemAbove = ListView_GetNextItem(m_hwndLV, iItem, LVNI_ABOVE);
iItemBelow = ListView_GetNextItem(m_hwndLV, iItem, LVNI_BELOW);
if (FIsWanBinding(iItemAbove))
{
iItemAbove = -1;
AssertSz(ListView_GetNextItem(m_hwndLV, iItemAbove, LVNI_ABOVE) == -1,
"Item above the WAN binding??");
}
else if (FIsWanBinding(iItemBelow))
{
iItemBelow = -1;
AssertSz(ListView_GetNextItem(m_hwndLV, iItemBelow, LVNI_BELOW) == -1,
"Item below the WAN binding??");
}
}
::EnableWindow(GetDlgItem(PSB_Adapter_Up), (iItemAbove != -1));
::EnableWindow(GetDlgItem(PSB_Adapter_Down), (iItemBelow != -1));
}
static const GUID * c_aguidClass[] =
{
&GUID_DEVCLASS_NETTRANS,
&GUID_DEVCLASS_NETSERVICE,
&GUID_DEVCLASS_NETCLIENT,
};
static const DWORD c_cguidClass = celems(c_aguidClass);
//+---------------------------------------------------------------------------
//
// Member: CBindingsDlg::MoveAdapterBindings
//
// Purpose: Moves all bindings for the given source and destination
// adapters in the given direction
//
// Arguments:
// pnccSrc [in] Adapter for which bindings are being moved
// pnccDst [in] Adapter to which bindings are being moved before or
// after
// mabDir [in] Direction to move. Either MAB_UP or MAB_DOWN
//
// Returns: Nothing
//
// Author: danielwe 2 Dec 1997
//
// Notes:
//
VOID CBindingsDlg::MoveAdapterBindings(INetCfgComponent *pnccSrc,
INetCfgComponent *pnccDst,
MAB_DIRECTION mabDir)
{
HRESULT hr = S_OK;
DWORD iguid;
AssertSz(pnccDst, "Destination component cannot be NULL!");
for (iguid = 0; iguid < c_cguidClass; iguid++)
{
CIterNetCfgComponent nccIter(m_pnc, c_aguidClass[iguid]);
INetCfgComponent * pncc;
while (SUCCEEDED(hr) && S_OK == (hr = nccIter.HrNext(&pncc)))
{
CIterNetCfgBindingPath ncbpIter(pncc);
INetCfgBindingPath * pncbp;
INetCfgBindingPath * pncbpTarget = NULL;
BOOL fAssign = TRUE;
NCBP_LIST listbp;
INetCfgComponent * pnccLast;
while (SUCCEEDED(hr) && S_OK == (hr = ncbpIter.HrNext(&pncbp)))
{
hr = HrGetLastComponentAndInterface(pncbp, &pnccLast, NULL);
if (SUCCEEDED(hr))
{
if (pnccLast == pnccDst)
{
if ((mabDir == MAB_UP) && fAssign)
{
AddRefObj(pncbpTarget = pncbp);
fAssign = FALSE;
}
else if (mabDir == MAB_DOWN)
{
ReleaseObj(pncbpTarget);
AddRefObj(pncbpTarget = pncbp);
}
}
else if (pnccLast == pnccSrc)
{
AddRefObj(pncbp);
listbp.push_back(pncbp);
}
ReleaseObj(pnccLast);
}
ReleaseObj(pncbp);
}
if (SUCCEEDED(hr))
{
NCBP_LIST::iterator iterbp;
INetCfgComponentBindings * pnccb;
hr = pncc->QueryInterface(IID_INetCfgComponentBindings,
reinterpret_cast<LPVOID *>(&pnccb));
if (SUCCEEDED(hr))
{
for (iterbp = listbp.begin();
(iterbp != listbp.end()) && SUCCEEDED(hr);
iterbp++)
{
if (mabDir == MAB_UP)
{
TraceTag(ttidAdvCfg, "Moving...");
DbgDumpBindPath(*iterbp);
// Move this binding path before the tagret
hr = pnccb->MoveBefore(*iterbp, pncbpTarget);
TraceTag(ttidAdvCfg, "before...");
DbgDumpBindPath(pncbpTarget);
}
else
{
TraceTag(ttidAdvCfg, "Moving...");
DbgDumpBindPath(*iterbp);
// Move this binding path after the tagret
hr = pnccb->MoveAfter(*iterbp, pncbpTarget);
TraceTag(ttidAdvCfg, "after...");
DbgDumpBindPath(pncbpTarget);
}
if (mabDir == MAB_DOWN)
{
// In the down direction ONLY, from now on, the
// target becomes the last binding we moved. This
// keeps the binding order intact because moving
// several bindings after the same target
// effectively reverses their order.
//
// Release old target
ReleaseObj(pncbpTarget);
// AddRef new target
AddRefObj(pncbpTarget = *iterbp);
}
ReleaseObj(*iterbp);
}
ReleaseObj(pnccb);
}
listbp.erase(listbp.begin(), listbp.end());
}
ReleaseObj(pncbpTarget);
ReleaseObj(pncc);
}
}
if (SUCCEEDED(hr))
{
hr = S_OK;
}
TraceError("CBindingsDlg::MoveAdapterBindings", hr);
}
//+---------------------------------------------------------------------------
//
// Function: ChangeListItemParam
//
// Purpose: Changes the lParam member of the given item to the given
// value.
//
// Arguments:
// hwndLV [in] HWND of list view
// iItem [in] Item to modify
// lParam [in] New lParam for item
//
// Returns: Nothing
//
// Author: danielwe 4 Dec 1997
//
// Notes:
//
VOID ChangeListItemParam(HWND hwndLV, INT iItem, LPARAM lParam)
{
LV_ITEM lvi = {0};
lvi.mask = LVIF_PARAM;
lvi.iItem = iItem;
lvi.lParam = lParam;
ListView_SetItem(hwndLV, &lvi);
}