windows-nt/Source/XPSP1/NT/net/mmc/dhcp/servbrow.cpp
2020-09-26 16:20:57 +08:00

742 lines
16 KiB
C++

/**********************************************************************/
/** Microsoft Windows/NT **/
/** Copyright(c) Microsoft Corporation, 1997 - 1999 **/
/**********************************************************************/
/*
ServBrow.cpp
The server browser dialog
FILE HISTORY:
*/
#include "stdafx.h"
#include "ServBrow.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
BOOL g_bDhcpDsInitialized = FALSE;
CAuthServerList::CAuthServerList()
: m_pos(NULL), m_bInitialized(FALSE)
{
}
CAuthServerList::~CAuthServerList()
{
Destroy();
}
HRESULT
CAuthServerList::Destroy()
{
// we only call cleanup once for this process
// ::DhcpDsCleanup();
m_bInitialized = FALSE;
return S_OK;
}
HRESULT
CAuthServerList::Init()
{
DWORD dwErr = ERROR_SUCCESS;
CSingleLock sl(&m_cs); // only one thread at a time in here
// DhcpDsInit only needs to be called once per process and is time consuming.
// if we've alredy called it then don't call again.
if (!g_bDhcpDsInitialized)
{
dwErr = ::DhcpDsInit();
if (dwErr == ERROR_SUCCESS)
g_bDhcpDsInitialized = TRUE;
}
if (g_bDhcpDsInitialized)
m_bInitialized = TRUE;
return HRESULT_FROM_WIN32(dwErr);
}
HRESULT
CAuthServerList::EnumServers()
{
LPDHCP_SERVER_INFO_ARRAY pServerInfoArray = NULL;
DWORD dwErr = ERROR_SUCCESS;
dwErr = ::DhcpEnumServers(0, NULL, &pServerInfoArray, NULL, NULL);
if (dwErr != ERROR_SUCCESS)
return HRESULT_FROM_WIN32(dwErr);
Assert(pServerInfoArray);
for (UINT i = 0; i < pServerInfoArray->NumElements; i++)
{
CServerInfo ServerInfo(pServerInfoArray->Servers[i].ServerAddress,
pServerInfoArray->Servers[i].ServerName);
AddTail(ServerInfo);
}
return S_OK;
}
BOOL
CAuthServerList::IsAuthorized
(
DWORD dwIpAddress
)
{
BOOL bValid = FALSE;
POSITION pos = GetHeadPosition();
while (pos)
{
if (GetNext(pos).m_dwIp == dwIpAddress)
{
bValid = TRUE;
break;
}
}
return bValid;
}
HRESULT
CAuthServerList::AddServer
(
DWORD dwIpAddress,
LPCTSTR pFQDN
)
{
DWORD dwErr = ERROR_SUCCESS;
DHCP_SERVER_INFO dhcpServerInfo = {0};
dhcpServerInfo.ServerAddress = dwIpAddress;
dhcpServerInfo.ServerName = (LPTSTR) pFQDN;
dwErr = ::DhcpAddServer(0, NULL, &dhcpServerInfo, NULL, NULL);
if (dwErr != ERROR_SUCCESS)
return HRESULT_FROM_WIN32(dwErr);
CServerInfo ServerInfo(dwIpAddress, pFQDN);
AddTail(ServerInfo);
return S_OK;
}
HRESULT
CAuthServerList::RemoveServer
(
DWORD dwIpAddress
)
{
DWORD dwErr = ERROR_SUCCESS;
DHCP_SERVER_INFO dhcpServerInfo = {0};
POSITION posCurrent;
POSITION pos = GetHeadPosition();
while (pos)
{
posCurrent = pos;
CServerInfo & ServerInfo = GetNext(pos);
if (ServerInfo.m_dwIp == dwIpAddress)
{
dhcpServerInfo.ServerAddress = ServerInfo.m_dwIp;
dhcpServerInfo.ServerName = (LPTSTR) ((LPCTSTR)ServerInfo.m_strName);
dwErr = ::DhcpDeleteServer(0, NULL, &dhcpServerInfo, NULL, NULL);
if (dwErr == ERROR_SUCCESS)
{
// success, remove from list
RemoveAt(posCurrent);
}
return HRESULT_FROM_WIN32(dwErr);
}
}
return E_INVALIDARG;
}
void
CAuthServerList::Clear()
{
RemoveAll();
Reset();
}
void
CAuthServerList::Reset()
{
m_pos = GetHeadPosition();
}
HRESULT
CAuthServerList::Next
(
CServerInfo &ServerInfo
)
{
if (m_pos)
ServerInfo = GetNext(m_pos);
else
return E_FAIL;
return S_OK;
}
/*---------------------------------------------------------------------------
CAuthServerWorker
---------------------------------------------------------------------------*/
CAuthServerWorker::CAuthServerWorker(CAuthServerList ** ppList)
{
m_ppList = ppList;
}
CAuthServerWorker::~CAuthServerWorker()
{
}
void
CAuthServerWorker::OnDoAction()
{
HRESULT hr = hrOK;
m_pAuthList = &g_AuthServerList;
hr = m_pAuthList->Init();
Trace1("CAuthServerWorker::OnDoAction - Init returned %d\n", hr);
hr = m_pAuthList->EnumServers();
Trace1("CAuthServerWorker::OnDoAction - EnumServers returned %d\n", hr);
if (!IsAbandoned())
{
if (m_ppList)
*m_ppList = m_pAuthList;
}
}
/*---------------------------------------------------------------------------
CStandaloneAuthServerWorker
---------------------------------------------------------------------------*/
CStandaloneAuthServerWorker::CStandaloneAuthServerWorker()
: CAuthServerWorker(NULL)
{
m_bAutoDelete = TRUE;
}
CStandaloneAuthServerWorker::~CStandaloneAuthServerWorker()
{
}
int
CStandaloneAuthServerWorker::Run()
{
OnDoAction();
return 0;
}
int CALLBACK ServerBrowseCompareFunc
(
LPARAM lParam1,
LPARAM lParam2,
LPARAM lParamSort
)
{
return ((CServerBrowse *) lParamSort)->HandleSort(lParam1, lParam2);
}
/////////////////////////////////////////////////////////////////////////////
// CServerBrowse dialog
CServerBrowse::CServerBrowse(BOOL bMultiselect, CWnd* pParent /*=NULL*/)
: CBaseDialog(CServerBrowse::IDD, pParent)
{
//{{AFX_DATA_INIT(CServerBrowse)
//}}AFX_DATA_INIT
m_bMultiselect = bMultiselect;
ResetSort();
}
void CServerBrowse::DoDataExchange(CDataExchange* pDX)
{
CBaseDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CServerBrowse)
DDX_Control(pDX, IDOK, m_buttonOk);
DDX_Control(pDX, IDC_BUTTON_REMOVE, m_buttonRemove);
DDX_Control(pDX, IDC_LIST_VALID_SERVERS, m_listctrlServers);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CServerBrowse, CBaseDialog)
//{{AFX_MSG_MAP(CServerBrowse)
ON_BN_CLICKED(IDC_BUTTON_REFRESH, OnButtonRefresh)
ON_BN_CLICKED(IDC_BUTTON_REMOVE, OnButtonRemove)
ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST_VALID_SERVERS, OnItemchangedListValidServers)
ON_BN_CLICKED(IDC_BUTTON_AUTHORIZE, OnButtonAuthorize)
ON_NOTIFY(LVN_COLUMNCLICK, IDC_LIST_VALID_SERVERS, OnColumnclickListValidServers)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CServerBrowse message handlers
BOOL CServerBrowse::OnInitDialog()
{
CBaseDialog::OnInitDialog();
LV_COLUMN lvColumn;
CString strText;
strText.LoadString(IDS_NAME);
ListView_SetExtendedListViewStyle(m_listctrlServers.GetSafeHwnd(), LVS_EX_FULLROWSELECT);
lvColumn.mask = LVCF_TEXT | LVCF_FMT | LVCF_WIDTH;
lvColumn.fmt = LVCFMT_LEFT;
lvColumn.cx = 175;
lvColumn.pszText = (LPTSTR) (LPCTSTR) strText;
m_listctrlServers.InsertColumn(0, &lvColumn);
strText.LoadString(IDS_IP_ADDRESS);
lvColumn.pszText = (LPTSTR) (LPCTSTR) strText;
lvColumn.cx = 100;
m_listctrlServers.InsertColumn(1, &lvColumn);
FillListCtrl();
UpdateButtons();
if (m_bMultiselect)
{
DWORD dwStyle = ::GetWindowLong(m_listctrlServers.GetSafeHwnd(), GWL_STYLE);
dwStyle &= ~LVS_SINGLESEL;
::SetWindowLong(m_listctrlServers.GetSafeHwnd(), GWL_EXSTYLE, dwStyle);
}
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void CServerBrowse::OnOK()
{
int nSelectedItem = m_listctrlServers.GetNextItem(-1, LVNI_SELECTED);
while (nSelectedItem != -1)
{
m_astrName.Add(m_listctrlServers.GetItemText(nSelectedItem, 0));
m_astrIp.Add(m_listctrlServers.GetItemText(nSelectedItem, 1));
nSelectedItem = m_listctrlServers.GetNextItem(nSelectedItem, LVNI_SELECTED);
}
CBaseDialog::OnOK();
}
void CServerBrowse::RefreshData()
{
if (m_pServerList)
{
m_pServerList->Clear();
m_pServerList->EnumServers();
ResetSort();
FillListCtrl();
}
}
void CServerBrowse::UpdateButtons()
{
// Find the selected item
int nSelectedItem = m_listctrlServers.GetNextItem(-1, LVNI_SELECTED);
BOOL bEnable = (nSelectedItem != -1) ? TRUE : FALSE;
m_buttonOk.EnableWindow(bEnable);
m_buttonRemove.EnableWindow(bEnable);
}
void CServerBrowse::FillListCtrl()
{
CServerInfo ServerInfo;
CString strIp;
int nItem = 0;
m_listctrlServers.DeleteAllItems();
POSITION pos = m_pServerList->GetHeadPosition();
// walk the list and add items to the list control
while (pos != NULL)
{
POSITION lastpos = pos;
// get the next item
ServerInfo = m_pServerList->GetNext(pos);
UtilCvtIpAddrToWstr(ServerInfo.m_dwIp, &strIp);
nItem = m_listctrlServers.InsertItem(nItem, ServerInfo.m_strName);
m_listctrlServers.SetItemText(nItem, 1, strIp);
// save off the position value for sorting later
m_listctrlServers.SetItemData(nItem, (DWORD_PTR) lastpos);
}
Sort(COLUMN_NAME);
}
void CServerBrowse::OnButtonAuthorize()
{
// put up the dialog to get the name and IP address of the server
DWORD err;
CGetServer dlgGetServer;
if (dlgGetServer.DoModal() == IDOK)
{
BEGIN_WAIT_CURSOR;
err = m_pServerList->AddServer(dlgGetServer.m_dwIpAddress, dlgGetServer.m_strName);
if (err != ERROR_SUCCESS)
{
::DhcpMessageBox(WIN32_FROM_HRESULT(err));
}
else
{
RefreshData();
UpdateButtons();
}
END_WAIT_CURSOR;
}
}
void CServerBrowse::OnButtonRefresh()
{
BEGIN_WAIT_CURSOR;
RefreshData();
UpdateButtons();
END_WAIT_CURSOR;
}
void CServerBrowse::OnButtonRemove()
{
HRESULT hr;
int nSelectedItem = m_listctrlServers.GetNextItem(-1, LVNI_SELECTED);
if (nSelectedItem != -1)
{
CString strIp = m_listctrlServers.GetItemText(nSelectedItem, 1);
DWORD dwIp = UtilCvtWstrToIpAddr(strIp);
BEGIN_WAIT_CURSOR;
hr = m_pServerList->RemoveServer(dwIp);
END_WAIT_CURSOR;
if (FAILED(hr))
{
::DhcpMessageBox(WIN32_FROM_HRESULT(hr));
}
else
{
BEGIN_WAIT_CURSOR;
RefreshData();
UpdateButtons();
END_WAIT_CURSOR;
}
}
}
void CServerBrowse::OnItemchangedListValidServers(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
UpdateButtons();
*pResult = 0;
}
void CServerBrowse::OnColumnclickListValidServers(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
// sort depending on what column was clicked;
Sort(pNMListView->iSubItem);
*pResult = 0;
}
void CServerBrowse::Sort(int nCol)
{
if (m_nSortColumn == nCol)
{
// if the user is clicking the same column again, reverse the sort order
m_aSortOrder[nCol] = m_aSortOrder[nCol] ? FALSE : TRUE;
}
else
{
m_nSortColumn = nCol;
}
m_listctrlServers.SortItems(ServerBrowseCompareFunc, (LPARAM) this);
}
int CServerBrowse::HandleSort(LPARAM lParam1, LPARAM lParam2)
{
int nCompare = 0;
CServerInfo ServerInfo1, ServerInfo2;
ServerInfo1 = m_pServerList->GetAt((POSITION) lParam1);
ServerInfo2 = m_pServerList->GetAt((POSITION) lParam2);
switch (m_nSortColumn)
{
case COLUMN_NAME:
{
nCompare = ServerInfo1.m_strName.CompareNoCase(ServerInfo2.m_strName);
}
// if the names are the same, fall back to the IP address
if (nCompare != 0)
{
break;
}
case COLUMN_IP:
{
if (ServerInfo1.m_dwIp > ServerInfo2.m_dwIp)
nCompare = 1;
else
if (ServerInfo1.m_dwIp < ServerInfo2.m_dwIp)
nCompare = -1;
}
break;
}
if (m_aSortOrder[m_nSortColumn] == FALSE)
{
// descending
return -nCompare;
}
else
{
// ascending
return nCompare;
}
}
void CServerBrowse::ResetSort()
{
m_nSortColumn = -1;
for (int i = 0; i < COLUMN_MAX; i++)
{
m_aSortOrder[i] = TRUE; // ascending
}
}
/////////////////////////////////////////////////////////////////////////////
// CGetServer dialog
CGetServer::CGetServer(CWnd* pParent /*=NULL*/)
: CBaseDialog(CGetServer::IDD, pParent)
{
//{{AFX_DATA_INIT(CGetServer)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
m_dwIpAddress = 0;
}
void CGetServer::DoDataExchange(CDataExchange* pDX)
{
CBaseDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CGetServer)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CGetServer, CBaseDialog)
//{{AFX_MSG_MAP(CGetServer)
ON_EN_CHANGE(IDC_EDIT_SERVER_NAME_IP, OnChangeEditServerNameIp)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CGetServer message handlers
BOOL CGetServer::OnInitDialog()
{
CBaseDialog::OnInitDialog();
GetDlgItem(IDOK)->EnableWindow(FALSE);
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void CGetServer::OnOK()
{
CString strNameOrIp;
DWORD err = 0;
DHC_HOST_INFO_STRUCT dhcHostInfo;
BEGIN_WAIT_CURSOR;
GetDlgItem(IDC_EDIT_SERVER_NAME_IP)->GetWindowText(strNameOrIp);
switch (UtilCategorizeName(strNameOrIp))
{
case HNM_TYPE_IP:
m_dwIpAddress = ::UtilCvtWstrToIpAddr( strNameOrIp ) ;
break ;
case HNM_TYPE_NB:
case HNM_TYPE_DNS:
err = ::UtilGetHostAddress( strNameOrIp, &m_dwIpAddress ) ;
m_strName = strNameOrIp; // default
break ;
default:
err = IDS_ERR_BAD_HOST_NAME ;
break;
}
// now that we have the address, try to get the full host info
// an empty host name is valid here, so if we can't find a host
// name then we'll just leave it blank.
if (err == ERROR_SUCCESS)
{
err = UtilGetHostInfo(m_dwIpAddress, &dhcHostInfo);
if (err == ERROR_SUCCESS)
{
m_strName = dhcHostInfo._chHostName;
}
}
END_WAIT_CURSOR;
// confirm choice with user, give them a chance to modify our findings
CConfirmAuthorization dlgConfirm;
dlgConfirm.m_strName = m_strName;
dlgConfirm.m_dwAuthAddress = m_dwIpAddress;
if (dlgConfirm.DoModal() != IDOK)
{
return;
}
// use whatever they selected
m_strName = dlgConfirm.m_strName;
m_dwIpAddress = dlgConfirm.m_dwAuthAddress;
CBaseDialog::OnOK();
}
void CGetServer::OnChangeEditServerNameIp()
{
CString strText;
BOOL fEnable = FALSE;
GetDlgItem(IDC_EDIT_SERVER_NAME_IP)->GetWindowText(strText);
if (!strText.IsEmpty())
fEnable = TRUE;
GetDlgItem(IDOK)->EnableWindow(fEnable);
}
/////////////////////////////////////////////////////////////////////////////
// CConfirmAuthorization dialog
CConfirmAuthorization::CConfirmAuthorization(CWnd* pParent /*=NULL*/)
: CBaseDialog(CConfirmAuthorization::IDD, pParent)
{
//{{AFX_DATA_INIT(CConfirmAuthorization)
m_strName = _T("");
//}}AFX_DATA_INIT
m_dwAuthAddress = 0;
}
void CConfirmAuthorization::DoDataExchange(CDataExchange* pDX)
{
CBaseDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CConfirmAuthorization)
DDX_Text(pDX, IDC_EDIT_AUTH_NAME, m_strName);
//}}AFX_DATA_MAP
DDX_Control(pDX, IDC_IPADDR_AUTH, m_ipaAuth);
}
BEGIN_MESSAGE_MAP(CConfirmAuthorization, CBaseDialog)
//{{AFX_MSG_MAP(CConfirmAuthorization)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CConfirmAuthorization message handlers
BOOL CConfirmAuthorization::OnInitDialog()
{
CBaseDialog::OnInitDialog();
if (m_dwAuthAddress != 0)
{
m_ipaAuth.SetAddress(m_dwAuthAddress);
}
else
{
m_ipaAuth.ClearAddress();
}
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void CConfirmAuthorization::OnOK()
{
m_ipaAuth.GetAddress(&m_dwAuthAddress);
if (m_dwAuthAddress == 0)
{
DhcpMessageBox(IDS_ERR_DLL_INVALID_ADDRESS);
m_ipaAuth.SetFocus();
return;
}
CBaseDialog::OnOK();
}