Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

726 lines
17 KiB

/**********************************************************************/
/** Microsoft Windows/NT **/
/** Copyright(c) Microsoft Corp., 1995 **/
/**********************************************************************/
/*
dhcpleas.cpp
Lease Dialog
The behaviour of this dialog is based upon the nature of the DHCP API. The
key points are:
1) "Reserved IP" information is not directly related to the
"Client" information maintained by a DHCP server.
2) When a reservation is created, the server creates a client
record for it. Likewise, when the reservation is deleted,
the client record is deleted.
The results of this dichotomy are several, both in this module and in the
DHCPCLID.CPP module. First, both client information and reservation information
must be enumerated to display the list of clients in an appropriate fashion.
Second, deletion of a client requires that we call different APIs based upon
whether the client record is related to a reservation or not.
Finally, the "add client" information has to be done in two phases. First,
the "Reserved IP" address has to be added as a subnet element. Then, the
newly created client record has to be retrieved and updated with the name
and comment information.
FILE HISTORY:
`
*/
#include "stdafx.h"
#include "dhcpleas.h"
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
#define RADIO_SORTBY_IP 0
#define RADIO_SORTBY_NAME 1
/////////////////////////////////////////////////////////////////////////////
// CDhcpLeaseDlg dialog
CDhcpLeaseDlg::CDhcpLeaseDlg(
CDhcpScope * pdhcScope,
CObListParamTypes * poblTypes,
BOOL fAllowReconcile,
CWnd* pParent /*=NULL*/
)
: CDialog(CDhcpLeaseDlg::IDD, pParent),
m_ListBoxResLeases(
IDB_LEASES,
m_listbox_Leases.nBitmaps
),
m_p_scope( pdhcScope ),
m_p_types( poblTypes ),
m_pobl_clients( NULL ),
m_b_resv_only( FALSE ),
m_bReservation( FALSE ),
m_fReconcileAvailable( fAllowReconcile )
{
//{{AFX_DATA_INIT(CDhcpLeaseDlg)
m_nSortBy = RADIO_SORTBY_IP;
//}}AFX_DATA_INIT
TRACEEOLID("Reconciliation option is " << m_fReconcileAvailable );
m_listbox_Leases.AttachResources( &m_ListBoxResLeases );
}
CDhcpLeaseDlg :: ~ CDhcpLeaseDlg ()
{
theApp.UpdateStatusBar() ;
delete m_pobl_clients ;
}
void
CDhcpLeaseDlg::DoDataExchange(
CDataExchange* pDX
)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CDhcpLeaseDlg)
DDX_Control(pDX, IDC_BUTTON_RECONCILE, m_button_Reconcile);
DDX_Control(pDX, IDC_STATIC_ACTIVE_LEASES, m_static_Active);
DDX_Control(pDX, IDC_STATIC_AVAILABLE, m_static_Available);
DDX_Control(pDX, IDC_STATIC_TOTAL_LEASES, m_static_TotalLeases);
DDX_Control(pDX, IDC_CHECK_RESV_ONLY, m_butn_resv_only);
DDX_Control(pDX, IDC_BUTN_LEASE_PROP, m_butn_properties);
DDX_Control(pDX, IDC_BUTN_LEASE_DELETE, m_butn_delete);
DDX_Radio(pDX, IDC_RADIO_SORTBY_IP, m_nSortBy);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CDhcpLeaseDlg, CDialog)
//{{AFX_MSG_MAP(CDhcpLeaseDlg)
ON_WM_CREATE()
ON_WM_CLOSE()
ON_BN_CLICKED(IDC_HELP, OnClickedHelp)
ON_BN_CLICKED(IDC_BUTN_LEASE_DELETE, OnClickedButnLeaseDelete)
ON_BN_CLICKED(IDC_BUTN_LEASE_PROP, OnClickedButnLeaseProp)
ON_BN_CLICKED(IDC_CHECK_RESV_ONLY, OnClickedCheckResvOnly)
ON_BN_CLICKED(IDC_RADIO_SORTBY_IP, OnClickedRadioSortbyIp)
ON_BN_CLICKED(IDC_RADIO_SORTBY_NAME, OnClickedRadioSortbyName)
ON_LBN_DBLCLK(IDC_LIST_LEASES, OnDblclkListLeases)
ON_LBN_ERRSPACE(IDC_LIST_LEASES, OnErrspaceListLeases)
ON_LBN_SELCHANGE(IDC_LIST_LEASES, OnSelchangeListLeases)
ON_BN_CLICKED(IDC_BUTTON_RECONCILE, OnClickedButtonReconcile)
ON_BN_CLICKED(IDC_BUTTON_REFRESH, OnButtonRefresh)
//}}AFX_MSG_MAP
ON_WM_VKEYTOITEM()
ON_WM_SYSCOLORCHANGE()
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CDhcpLeaseDlg message handlers
void
CDhcpLeaseDlg::SetTitleBar()
{
CString str1;
GetWindowText(str1);
CHAR szIp[256];
::UtilCvtIpAddrToString( m_p_scope->QueryId(), szIp, sizeof szIp ) ;
CHAR sz[1000];
::wsprintf (sz, "%s - [%s]", (LPCSTR)str1, szIp);
SetWindowText(sz);
}
BOOL
CDhcpLeaseDlg::OnInitDialog()
{
CDialog::OnInitDialog();
LONG err = 0 ;
m_listbox_Leases.SubclassDlgItem(IDC_LIST_LEASES, this);
//
// Reconciliation is a new option for 3.51, and is not
// available prior to that.
//
m_button_Reconcile.EnableWindow(m_fReconcileAvailable);
CATCH_MEM_EXCEPTION
{
//
// Load up the static strings we need for data presentation
//
m_str_hex.LoadString( IDS_INFO_HEX_TABLE ) ;
m_str_AvailableLeases.LoadString ( IDS_INFO_LEASE_PERCENTAGE );
//m_str_date_time.LoadString( IDS_INFO_DATE_MASK );
m_butn_properties.EnableWindow( FALSE ) ;
m_butn_delete.EnableWindow( FALSE ) ;
//m_edit_name.SetReadOnly() ;
//m_edit_comment.SetReadOnly() ;
//m_static_scope_name.SetWindowText( m_p_scope->QueryName() ) ;
m_butn_resv_only.SetCheck( m_b_resv_only ) ;
SetTitleBar();
//
// Create the client list
//
theApp.UpdateStatusBar( IDS_STATUS_GETTING_CLIENT_INFO ) ;
err = CreateClientList() ;
theApp.UpdateStatusBar( IDS_STATUS_CLIENT_REVIEW ) ;
}
END_MEM_EXCEPTION(err)
if ( err )
{
theApp.MessageBox( err ) ;
EndDialog( -1 ) ;
}
else
{
m_listbox_Leases.SetFocus();
}
return FALSE ;
}
LONG
CDhcpLeaseDlg :: CreateClientList ()
{
LONG err = 0 ;
//
// Delete the current client list.
//
delete m_pobl_clients ;
CATCH_MEM_EXCEPTION
{
do
{
//
// Create the new list.
//
m_pobl_clients = new CObListClients( m_p_scope->QueryScopeId() ) ;
if ( err = m_pobl_clients->QueryError() )
{
break;
}
//
// Mark the list entries which are reservations. Prune the
// list if necessary.
//
err = m_pobl_clients->MarkReservations( m_b_resv_only ) ;
//
// The incoming list was sorted by IP. Adjust if sorting
// by name.
//
if (m_nSortBy == RADIO_SORTBY_NAME)
{
m_pobl_clients->SortByName();
}
} while ( FALSE ) ;
}
END_MEM_EXCEPTION(err)
if ( err == 0 )
{
//
// Fill the list and the other controls.
//
FillList() ;
Fill() ;
}
return err ;
}
//
// Fill the list box from the client list.
//
void
CDhcpLeaseDlg :: FillList ()
{
CObListIter obli( *m_pobl_clients ) ;
const CDhcpClient * pClient ;
m_listbox_Leases.ResetContent();
int cItems = 0 ;
for ( ; pClient = (CDhcpClient *) obli.Next() ; cItems++ )
{
m_listbox_Leases.AddString( (LPCSTR)pClient ) ;
}
m_listbox_Leases.SetCurSel( cItems ? 0 : -1 ) ;
//
// Display the number of available leases, etc
//
LPDHCP_MIB_INFO pmibInfo;
LONG err = m_p_scope->GetMibInfo(&pmibInfo);
if (err != ERROR_SUCCESS)
{
theApp.MessageBox(err);
}
else
{
//
// Find our scope in the list of scopes defined on this
// host
//
DWORD n;
LPSCOPE_MIB_INFO lpScopeInfo = NULL;
for (n = 0; n < pmibInfo->Scopes; ++n)
{
LPSCOPE_MIB_INFO lpInfo = &(pmibInfo->ScopeInfo[n]);
int j = pmibInfo->ScopeInfo[n].Subnet;
if (pmibInfo->ScopeInfo[n].Subnet == (DWORD)m_p_scope->QueryScopeId().QueryId())
{
lpScopeInfo = &(pmibInfo->ScopeInfo[n]);
break;
}
}
if (lpScopeInfo == NULL)
{
theApp.MessageBox(IDS_ERR_NO_LEASE_STATISTICS);
}
else
{
CIntlNumber nTotal(lpScopeInfo->NumAddressesFree + lpScopeInfo->NumAddressesInuse);
CIntlNumber nActive(lpScopeInfo->NumAddressesInuse);
CIntlNumber nFree(lpScopeInfo->NumAddressesFree);
CHAR szLeases[256];
m_static_TotalLeases.SetWindowText((CString)nTotal);
::wsprintf ( szLeases, m_str_AvailableLeases,
(LPCSTR)(CString)nActive, 100L * (LONG)nActive / (LONG)nTotal );
m_static_Active.SetWindowText(szLeases);
::wsprintf ( szLeases, m_str_AvailableLeases,
(LPCSTR)(CString)nFree, 100L * (LONG)nFree / (LONG)nTotal);
m_static_Available.SetWindowText(szLeases);
}
::DhcpRpcFreeMemory(pmibInfo);
}
}
//
// Fill the other controls based upon the current listbox selection
//
void
CDhcpLeaseDlg :: Fill ()
{
const char * pszEmpty = "" ;
int cSel = m_listbox_Leases.GetCurSel() ;
const CDhcpClient * pClient = NULL ;
CString strId ;
m_bReservation = FALSE ;
if ( cSel >= 0 )
{
pClient = (CDhcpClient *) m_listbox_Leases.GetItemData(cSel);
ASSERT( pClient != NULL ) ;
}
if ( pClient )
{
m_bReservation = pClient->IsReservation() ;
}
//
// Disable the modification buttons if this is not a reservation
//
m_butn_properties.EnableWindow( cSel >= 0 ) ;
m_butn_delete.EnableWindow( cSel >= 0 ) ;
}
int
CDhcpLeaseDlg::OnCreate(
LPCREATESTRUCT lpCreateStruct
)
{
if (CDialog::OnCreate(lpCreateStruct) == -1)
{
return -1;
}
return 0;
}
void
CDhcpLeaseDlg::OnClose()
{
CDialog::OnClose();
}
void
CDhcpLeaseDlg::OnOK()
{
CDialog::OnCancel();
}
void
CDhcpLeaseDlg::OnCancel()
{
CDialog::OnCancel();
}
void
CDhcpLeaseDlg::OnClickedHelp()
{
}
void
CDhcpLeaseDlg::OnClickedButnLeaseDelete()
{
int cSel = m_listbox_Leases.GetCurSel() ;
if ( cSel < 0 ||
theApp.MessageBox(IDS_MSG_DELETE_LEASE, MB_YESNO | MB_DEFBUTTON2 | MB_ICONQUESTION) == IDNO
)
{
return ;
}
CDhcpClient * pClient = (CDhcpClient *) m_pobl_clients->Index( cSel ) ;
ASSERT( pClient != NULL ) ;
theApp.BeginWaitCursor();
LONG err = m_p_scope->DeleteClient( pClient ) ;
if ( err == 0 )
{
err = CreateClientList() ;
}
theApp.EndWaitCursor();
if ( err )
{
theApp.MessageBox( err ) ;
}
else
{
RenameCancelToClose() ;
}
}
void
CDhcpLeaseDlg :: RenameCancelToClose ()
{
CWnd * pButnCancel = GetDlgItem( IDCANCEL ) ;
if ( pButnCancel )
{
LONG err ;
CATCH_MEM_EXCEPTION
{
CString cStr ;
cStr.LoadString( IDS_INFO_BUTTON_CLOSE ) ;
pButnCancel->SetWindowText( cStr ) ;
}
END_MEM_EXCEPTION(err)
}
}
void
CDhcpLeaseDlg::OnClickedButnLeaseProp()
{
int cSel = m_listbox_Leases.GetCurSel() ;
if ( cSel < 0 )
{
return ;
}
CDhcpClient * pClient = (CDhcpClient *) m_pobl_clients->Index( cSel ) ;
ASSERT( pClient != NULL ) ;
CDhcpClientInfoDlg dlgClientInfo(
m_p_scope,
pClient,
m_p_types,
!m_bReservation, // Allow editing of reservations only.
this
) ;
if ( dlgClientInfo.DoModal() == IDOK )
{
RenameCancelToClose() ;
//
// Refresh the data in the controls
//
Fill() ;
//
// Clean up the listbox
//
if (m_nSortBy == RADIO_SORTBY_NAME)
{
theApp.BeginWaitCursor();
m_listbox_Leases.SetRedraw(FALSE);
m_pobl_clients->SortByName();
FillList();
m_listbox_Leases.SetCurSel(cSel);
m_listbox_Leases.SetRedraw(TRUE);
theApp.EndWaitCursor();
}
else
{
//
// Can't edit ip address, so no need
// to resort if sorted by ip. Refresh
// the current entry
//
RECT rc;
m_listbox_Leases.GetItemRect(cSel, &rc);
m_listbox_Leases.InvalidateRect(&rc, FALSE);
}
}
}
void
CDhcpLeaseDlg::OnClickedCheckResvOnly()
{
BOOL bResvOnly = m_b_resv_only ;
m_b_resv_only = (m_butn_resv_only.GetCheck() & 3) > 0 ;
if ( bResvOnly != m_b_resv_only )
{
theApp.BeginWaitCursor() ;
LONG err = CreateClientList() ;
theApp.EndWaitCursor() ;
if ( err )
{
theApp.MessageBox( err ) ;
EndDialog( -1 ) ;
}
}
}
void
CDhcpLeaseDlg::OnClickedRadioSortbyIp()
{
if (m_nSortBy != RADIO_SORTBY_IP)
{
theApp.BeginWaitCursor();
m_listbox_Leases.SetRedraw(FALSE);
m_pobl_clients->SortByIp();
FillList();
m_listbox_Leases.SetRedraw(TRUE);
theApp.EndWaitCursor();
m_nSortBy = RADIO_SORTBY_IP;
}
}
void
CDhcpLeaseDlg::OnClickedRadioSortbyName()
{
if (m_nSortBy != RADIO_SORTBY_NAME)
{
theApp.BeginWaitCursor();
m_listbox_Leases.SetRedraw(FALSE);
m_pobl_clients->SortByName();
FillList();
m_listbox_Leases.SetRedraw(TRUE);
theApp.EndWaitCursor();
m_nSortBy = RADIO_SORTBY_NAME;
}
}
void
CDhcpLeaseDlg::OnDblclkListLeases()
{
OnClickedButnLeaseProp();
}
void
CDhcpLeaseDlg::OnErrspaceListLeases()
{
}
void
CDhcpLeaseDlg::OnSelchangeListLeases()
{
Fill() ;
}
void
CDhcpLeaseDlg::OnSysColorChange()
{
m_ListBoxResLeases.SysColorChanged();
CDialog::OnSysColorChange();
}
int
CDhcpLeaseDlg::OnVKeyToItem(
UINT nKey,
CListBox* pListBox,
UINT nIndex
)
{
switch(nKey)
{
case VK_DELETE:
OnClickedButnLeaseDelete();
break;
default:
return(-1);
}
return -2;
}
//
// Perform a complete reconciliation between
// the database and the bit mask.
//
void
CDhcpLeaseDlg::OnClickedButtonReconcile()
{
LPDHCP_SCAN_LIST lpScanList = NULL;
LONG err = 0;
theApp.UpdateStatusBar( IDS_STATUS_RECONCILE1 ) ;
theApp.BeginWaitCursor();
do
{
//
// First we scan the whole database to see if
// there are IP addresses that need to be resolved.
//
err = m_p_scope->ScanDatabase(FALSE, &lpScanList);
theApp.UpdateStatusBar() ;
theApp.EndWaitCursor();
if (err != ERROR_SUCCESS)
{
break;
}
ASSERT(lpScanList != NULL);
if (lpScanList->NumScanItems > 0)
{
//
// There are items to be reconciled.
// Present the list of ip addresses
// that didn't match, and let
// the user decide to add them
// or not.
//
CReconcileDlg dlgReconcile(lpScanList);
if (dlgReconcile.DoModal() == IDOK)
{
theApp.UpdateStatusBar ( IDS_STATUS_RECONCILE2 );
theApp.BeginWaitCursor();
err = m_p_scope->ScanDatabase(TRUE, &lpScanList);
if (err != ERROR_SUCCESS)
{
break;
}
//
// Now refill the listbox, as several leases
// have now been added.
//
CreateClientList();
}
}
else
{
theApp.MessageBox(IDS_MSG_NO_RECONCILE, MB_ICONINFORMATION);
}
}
while(FALSE);
if (lpScanList != NULL)
{
::DhcpRpcFreeMemory(lpScanList);
}
if (err != ERROR_SUCCESS)
{
theApp.MessageBox(err);
}
}
void CDhcpLeaseDlg::OnButtonRefresh()
{
// Create the client list
theApp.BeginWaitCursor();
theApp.UpdateStatusBar(IDS_STATUS_GETTING_CLIENT_INFO);
m_listbox_Leases.SetRedraw(FALSE);
CreateClientList();
theApp.UpdateStatusBar();
m_listbox_Leases.SetRedraw(TRUE);
theApp.EndWaitCursor();
}
/////////////////////////////////////////////////////////////////////////////
// CReconcileDlg dialog
CReconcileDlg::CReconcileDlg(
LPDHCP_SCAN_LIST lpScanList,
CWnd* pParent /*=NULL*/
)
: CDialog(CReconcileDlg::IDD, pParent),
m_lpScanList(lpScanList)
{
//{{AFX_DATA_INIT(CReconcileDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
}
void
CReconcileDlg::DoDataExchange(
CDataExchange* pDX
)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CReconcileDlg)
DDX_Control(pDX, IDC_LIST_RECONCILE_IP_ADDRESSES, m_list_IpAddresses);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CReconcileDlg, CDialog)
//{{AFX_MSG_MAP(CReconcileDlg)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CReconcileDlg message handlers
BOOL
CReconcileDlg::OnInitDialog()
{
CDialog::OnInitDialog();
for (DWORD i = 0; i < m_lpScanList->NumScanItems; ++i)
{
CIpAddress ia(m_lpScanList->ScanItems[i].IpAddress);
m_list_IpAddresses.AddString((CString)ia);
}
return TRUE; // return TRUE unless you set the focus to a control
}