/**********************************************************************/ /** Microsoft Windows/NT **/ /** Copyright(c) Microsoft Corp., 1995 **/ /**********************************************************************/ /* dhcpsrvd.cpp Dhcp server dialogs - Add server dialog - Server propeties (General, BOOTP Table) FILE HISTORY: 31-Jan-94 RONALDM2 Creation of CDhcpSrvDlg dialog. 14-Nov-96 t-danmo Added server properties dialogs */ #include "stdafx.h" #include "dhcpsrvd.h" #ifdef _DEBUG #undef THIS_FILE static char BASED_CODE THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // CDhcpSrvDlg dialog // CDhcpSrvDlg::CDhcpSrvDlg( CWnd* pParent /*=NULL*/ ) : CDialog(CDhcpSrvDlg::IDD, pParent) { //{{AFX_DATA_INIT(CDhcpSrvDlg) // NOTE: the ClassWizard will add member initialization here //}}AFX_DATA_INIT m_pobHost = NULL; } void CDhcpSrvDlg::DoDataExchange( CDataExchange* pDX ) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CDhcpSrvDlg) DDX_Control(pDX, IDOK, m_button_Ok); DDX_Control(pDX, IDC_EDIT_SERVER_NAME, m_edit_server); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CDhcpSrvDlg, CDialog) //{{AFX_MSG_MAP(CDhcpSrvDlg) ON_EN_CHANGE(IDC_EDIT_SERVER_NAME, OnChangeEditServerName) //}}AFX_MSG_MAP END_MESSAGE_MAP() void CDhcpSrvDlg::SetControlState() { m_button_Ok.EnableWindow(m_edit_server.GetWindowTextLength() > 0); } void CDhcpSrvDlg::OnOK() { LONG err; m_edit_server.GetWindowText( m_chServer, sizeof(m_chServer) ) ; err = theApp.CreateHostObject( m_chServer, &m_pobHost ) ; if ( err == ERROR_SUCCESS) { // // Try to add the host to the // application's master list. // if ( err = theApp.AddHost( m_pobHost ) ) { // // Failure; delete the // unnecessary object. // delete m_pobHost ; m_pobHost = NULL; } } if (err != ERROR_SUCCESS) { theApp.MessageBox(err); // // We don't quit out the d-box // m_edit_server.SetSel(0,-1); return; } CDialog::OnOK(); } BOOL CDhcpSrvDlg::OnInitDialog() { CDialog::OnInitDialog(); m_edit_server.LimitText( sizeof m_chServer - 2 ) ; m_edit_server.SetModify( FALSE ) ; m_edit_server.SetFocus() ; SetControlState(); return FALSE; } void CDhcpSrvDlg::OnChangeEditServerName() { SetControlState(); } ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // CDhcpServerProperties // IMPLEMENT_DYNAMIC(CDhcpServerProperties, CPropertySheet) CDhcpServerProperties::CDhcpServerProperties(LPCTSTR pszCaption, CWnd* pParentWnd, UINT iSelectPage) :CPropertySheet(pszCaption, pParentWnd, iSelectPage) { m_dwDirtyFlags = 0; m_paDhcpConfigInfo = NULL; m_pPageGeneral = NULL; m_pPageBootp = NULL; } CDhcpServerProperties::~CDhcpServerProperties() { delete m_pPageGeneral; delete m_pPageBootp; if (m_paDhcpConfigInfo != NULL) ::DhcpRpcFreeMemory(m_paDhcpConfigInfo); } BOOL CDhcpServerProperties::FInit(CHostName * pHostName) { Assert(pHostName != NULL); m_pHostName = pHostName; CString strCaption; LoadStringPrintf(IDS_s_SERVER_PROPERTIES, OUT &strCaption, m_pHostName->FIsLocalHost() ? (LPCSTR)theApp.m_str_Local : (LPCSTR)m_pHostName->PszGetHostName()); SetTitle(strCaption); m_pPageGeneral = new CDhcpServerPropGeneral; m_pPageGeneral->m_pData = this; AddPage(m_pPageGeneral); m_pPageBootp = new CDhcpServerPropBootpTable; m_pPageBootp->m_pData = this; AddPage(m_pPageBootp); Assert(m_paDhcpConfigInfo == NULL); theApp.UpdateStatusBar(IDS_STATUS_GETTING_SERVER_INFO); theApp.BeginWaitCursor(); APIERR err = ::DhcpServerGetConfigV4( pHostName->QueryWcName(), OUT &m_paDhcpConfigInfo); theApp.EndWaitCursor(); theApp.UpdateStatusBar(); if (err != ERROR_SUCCESS) { Assert(m_paDhcpConfigInfo == NULL); ReportDhcpError(err); return FALSE; } if (m_paDhcpConfigInfo == NULL) { Assert(FALSE); return FALSE; } return TRUE; } // CDhcpServerProperties::FInit() // Return FALSE if an error occured. BOOL CDhcpServerProperties::FOnApply() { Assert(m_pHostName != NULL); Assert(m_paDhcpConfigInfo != NULL); if (m_dwDirtyFlags == 0) { // Nothing has been modified, so nothing to do return TRUE; } theApp.BeginWaitCursor(); theApp.UpdateStatusBar(IDS_STATUS_UPDATING_SERVER_INFO); APIERR err = ::DhcpServerSetConfigV4( m_pHostName->QueryWcName(), m_dwDirtyFlags, IN m_paDhcpConfigInfo); theApp.EndWaitCursor(); if (err != ERROR_SUCCESS) { ReportDhcpError(err); } else { m_dwDirtyFlags = 0; } theApp.UpdateStatusBar(); return (err == ERROR_SUCCESS); } BEGIN_MESSAGE_MAP(CDhcpServerProperties, CPropertySheet) //{{AFX_MSG_MAP(CDhcpServerProperties) // NOTE - the ClassWizard will add and remove mapping macros here. //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // CDhcpServerPropGeneral property page IMPLEMENT_DYNCREATE(CDhcpServerPropGeneral, CPropertyPage) CDhcpServerPropGeneral::CDhcpServerPropGeneral() : CPropertyPage(CDhcpServerPropGeneral::IDD) { //{{AFX_DATA_INIT(CDhcpServerPropGeneral) //}}AFX_DATA_INIT } CDhcpServerPropGeneral::~CDhcpServerPropGeneral() { } void CDhcpServerPropGeneral::DoDataExchange(CDataExchange* pDX) { Assert(m_pData != NULL); Assert(m_pData->m_paDhcpConfigInfo != NULL); DHCP_SERVER_CONFIG_INFO_V4 * pDhcpConfigInfo = m_pData->m_paDhcpConfigInfo; if (!pDX->m_bSaveAndValidate) { m_fAuditLog = pDhcpConfigInfo->fAuditLog; m_cConflictDetection = pDhcpConfigInfo->dwPingRetries; } CPropertyPage::DoDataExchange(pDX); //{{AFX_DATA_MAP(CDhcpServerPropGeneral) DDX_Check(pDX, IDC_CHECK_AUDIT_LOGGING, m_fAuditLog); DDX_CBIndex(pDX, IDC_COMBO_CONFLICT_DETECTION, m_cConflictDetection); //}}AFX_DATA_MAP if (pDX->m_bSaveAndValidate) { pDhcpConfigInfo->fAuditLog = m_fAuditLog; pDhcpConfigInfo->dwPingRetries = m_cConflictDetection; } } BEGIN_MESSAGE_MAP(CDhcpServerPropGeneral, CPropertyPage) //{{AFX_MSG_MAP(CDhcpServerPropGeneral) ON_BN_CLICKED(IDC_CHECK_AUDIT_LOGGING, OnCheckAuditLogging) ON_CBN_SELCHANGE(IDC_COMBO_CONFLICT_DETECTION, OnSelchangeComboConflictDetection) //}}AFX_MSG_MAP END_MESSAGE_MAP() void CDhcpServerPropGeneral::OnCheckAuditLogging() { SetModified(); m_pData->m_dwDirtyFlags |= Set_AuditLogState; } void CDhcpServerPropGeneral::OnSelchangeComboConflictDetection() { SetModified(); m_pData->m_dwDirtyFlags |= Set_PingRetries; } BOOL CDhcpServerPropGeneral::OnApply() { // Write the data into the service control database if (!m_pData->FOnApply()) { // Unable to write the information return FALSE; } return CPropertyPage::OnApply(); } ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////// // PchInitData() // // Initialize the BOOTP entry from a formatted string. // // "%s,%s,%s" = "szBootImage,szFileServer,szFileServer" // // Return a pointer to the beginning of the next string to parse. // If the next string to parse is empty, or an error occured, return // a pointer to empty string. // WCHAR * CDhcpBootpEntry::PchInitData( CONST WCHAR grszwBootTable[]) // IN: Group of strings for the boot table { Assert(grszwBootTable != NULL); CONST WCHAR * pszw; pszw = PchParseUnicodeString(IN grszwBootTable, OUT m_strBootImage); Assert(*pszw == BOOT_FILE_STRING_DELIMITER_W); pszw = PchParseUnicodeString(IN pszw + 1, OUT m_strFileName); Assert(*pszw == BOOT_FILE_STRING_DELIMITER_W); pszw = PchParseUnicodeString(IN pszw + 1, OUT m_strFileServer); Assert(*pszw == '\0'); return const_cast(pszw + 1); } ///////////////////////////////////////////////////////////////////// // Compute the length (number of characters) necessary // to store the BOOTP entry. Additional characters // are added for extra security. int CDhcpBootpEntry::CchGetDataLength() { return 16 + m_strBootImage.GetLength() + m_strFileName.GetLength() + m_strFileServer.GetLength(); } ///////////////////////////////////////////////////////////////////// // Recursively compute the length of the linked-list of BOOTP entries. int CDhcpBootpEntry::CchGetDataLengthR() { return CchGetDataLength() + ((m_pNext == NULL) ? 0 : m_pNext->CchGetDataLengthR()); } ///////////////////////////////////////////////////////////////////// // Write the data into a formatted string. WCHAR * CDhcpBootpEntry::PchStoreData(OUT WCHAR szwBuffer[]) { int cch; cch = wsprintfW(OUT szwBuffer, L"%hs,%hs,%hs", (LPCTSTR)m_strBootImage, (LPCTSTR)m_strFileName, (LPCTSTR)m_strFileServer); Assert(cch > 0); Assert(cch + 4 < CchGetDataLength()); return const_cast(szwBuffer + cch + 1); } ///////////////////////////////////////////////////////////////////// WCHAR * CDhcpBootpEntry::PchStoreDataR(OUT WCHAR szwBuffer[]) { WCHAR * pszwBuffer; pszwBuffer = PchStoreData(OUT szwBuffer); if (m_pNext != NULL) { pszwBuffer = m_pNext->PchStoreDataR(OUT pszwBuffer); } else { *pszwBuffer++ = '\0'; // Double null-terminator at end } return pszwBuffer; } ///////////////////////////////////////////////////////////////////// void CDhcpBootpEntry::AddToListview(CListCtrl& rListview) { LV_ITEM lvItem; INT iItem; lvItem.mask = LVIF_TEXT | LVIF_PARAM; lvItem.iItem = 0; lvItem.iSubItem = 0; lvItem.lParam = (LPARAM)this; lvItem.pszText = const_cast((LPCTSTR)m_strBootImage); iItem = rListview.InsertItem(IN &lvItem); Report(iItem >= 0); lvItem.iItem = iItem; lvItem.mask = LVIF_TEXT; lvItem.iSubItem = 1; lvItem.pszText = const_cast((LPCTSTR)m_strFileName); VERIFY(rListview.SetItem(IN &lvItem)); lvItem.iSubItem = 2; lvItem.pszText = const_cast((LPCTSTR)m_strFileServer); VERIFY(rListview.SetItem(IN &lvItem)); } // CDhcpBootpEntry::AddToListview() ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // CDhcpServerPropBootpTable property page // IMPLEMENT_DYNCREATE(CDhcpServerPropBootpTable, CPropertyPage) CDhcpServerPropBootpTable::CDhcpServerPropBootpTable() : CPropertyPage(CDhcpServerPropBootpTable::IDD) { //{{AFX_DATA_INIT(CDhcpServerPropBootpTable) // NOTE: the ClassWizard will add member initialization here //}}AFX_DATA_INIT m_paBootpList = NULL; m_pBootpSelectedEntry = NULL; m_pagrszwBootpList = NULL; } CDhcpServerPropBootpTable::~CDhcpServerPropBootpTable() { delete m_paBootpList; // Delete linked-list of BOOTP entries delete m_pagrszwBootpList; // Delete group of string of BOOTP entries } void CDhcpServerPropBootpTable::DoDataExchange(CDataExchange* pDX) { Assert(m_pData != NULL); Assert(m_pData->m_paDhcpConfigInfo != NULL); DHCP_SERVER_CONFIG_INFO_V4 * pDhcpConfigInfo = m_pData->m_paDhcpConfigInfo; CPropertyPage::DoDataExchange(pDX); //{{AFX_DATA_MAP(CDhcpServerPropBootpTable) DDX_Control(pDX, IDC_LIST_BOOTP_TABLE, m_listviewBootpTable); //}}AFX_DATA_MAP if (!pDX->m_bSaveAndValidate) { CONST WCHAR * pszwBootpList = pDhcpConfigInfo->wszBootTableString; delete m_paBootpList; m_paBootpList = NULL; m_listviewBootpTable.DeleteAllItems(); if (pszwBootpList == NULL || pDhcpConfigInfo->cbBootTableString == 0) { // Empty list -> nothing to do return; } // Parse the BOOTP list of format "%s,%s,%s","%s,%s,%s",... while (*pszwBootpList != '\0') { CDhcpBootpEntry * pBootpEntryNew = new CDhcpBootpEntry; pBootpEntryNew->m_pNext = m_paBootpList; m_paBootpList = pBootpEntryNew; pszwBootpList = pBootpEntryNew->PchInitData(IN pszwBootpList); pBootpEntryNew->AddToListview(m_listviewBootpTable); } // while } else { delete m_pagrszwBootpList; m_pagrszwBootpList = NULL; if (m_paBootpList != NULL) { // Compute how much memory is needed int cchData = m_paBootpList->CchGetDataLengthR(); // Allocate the memory buffer m_pagrszwBootpList = new WCHAR[cchData]; // Store the data into the buffer WCHAR * pszwEnd = m_paBootpList->PchStoreDataR(m_pagrszwBootpList); Assert(pszwEnd > m_pagrszwBootpList); pDhcpConfigInfo->cbBootTableString = (pszwEnd - m_pagrszwBootpList) * sizeof(WCHAR); } else { pDhcpConfigInfo->cbBootTableString = 0; } pDhcpConfigInfo->wszBootTableString = m_pagrszwBootpList; } // if...else } // CDhcpServerPropBootpTable::DoDataExchange() BEGIN_MESSAGE_MAP(CDhcpServerPropBootpTable, CPropertyPage) //{{AFX_MSG_MAP(CDhcpServerPropBootpTable) ON_BN_CLICKED(IDC_BUTTON_NEW, OnButtonNew) ON_NOTIFY(NM_DBLCLK, IDC_LIST_BOOTP_TABLE, OnDblclkListBootpTable) ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST_BOOTP_TABLE, OnItemchangedListBootpTable) ON_BN_CLICKED(IDC_BUTTON_DELETE, OnButtonDelete) ON_BN_CLICKED(IDC_BUTTON_PROPERTIES, OnButtonPropertiesBootp) //}}AFX_MSG_MAP END_MESSAGE_MAP() const static TColumnHeaderItem rgzBootpTableHeader[] = { { IDS_BOOT_IMAGE, 25 }, { IDS_FILE_NAME, 25 }, { IDS_FILE_SERVER, 40 }, { 0, 0 } }; BOOL CDhcpServerPropBootpTable::OnInitDialog() { Assert(m_pData != NULL); Assert(m_pBootpSelectedEntry == NULL); ListView_AddColumnHeaders(::GetDlgItem(m_hWnd, IDC_LIST_BOOTP_TABLE), rgzBootpTableHeader); CPropertyPage::OnInitDialog(); UpdateUI(); return TRUE; } void CDhcpServerPropBootpTable::OnItemchangedListBootpTable(NMHDR* pNMHDR, LRESULT* pResult) { NM_LISTVIEW * pNnListview = (NM_LISTVIEW*)pNMHDR; Assert(pNnListview != NULL); Assert(pNnListview->lParam != -1); m_pBootpSelectedEntry = (CDhcpBootpEntry *)pNnListview->lParam; UpdateUI(); *pResult = 0; } void CDhcpServerPropBootpTable::OnDblclkListBootpTable(NMHDR* pNMHDR, LRESULT* pResult) { OnButtonPropertiesBootp(); } void CDhcpServerPropBootpTable::OnButtonNew() { // Create a new BOOTP entry CCreateBootpEntryDlg dlg; if (dlg.DoModal() != IDOK) return; SetModified(); m_pData->m_dwDirtyFlags |= Set_BootFileTable; CDhcpBootpEntry * pBootpEntryNew = new CDhcpBootpEntry; pBootpEntryNew->m_pNext = m_paBootpList; m_paBootpList = pBootpEntryNew; pBootpEntryNew->m_strBootImage = dlg.m_strBootImage; pBootpEntryNew->m_strFileName = dlg.m_strFileName; pBootpEntryNew->m_strFileServer = dlg.m_strFileServer; pBootpEntryNew->AddToListview(m_listviewBootpTable); } void CDhcpServerPropBootpTable::OnButtonDelete() { // Delete selected BOOTP entry Assert(m_pBootpSelectedEntry != NULL); LV_FINDINFO lvFindInfo; lvFindInfo.flags = LVFI_PARAM; lvFindInfo.lParam = (LPARAM)m_pBootpSelectedEntry; int iItem = m_listviewBootpTable.FindItem(&lvFindInfo); Assert(iItem >= 0); CDhcpBootpEntry * pBootpEntry; CDhcpBootpEntry * pBootpEntryPrev = NULL; for (pBootpEntry = m_paBootpList; pBootpEntry != NULL; pBootpEntry = pBootpEntry->m_pNext) { if (pBootpEntry == m_pBootpSelectedEntry) { // Detach the node from the linked list if (pBootpEntryPrev == NULL) m_paBootpList = pBootpEntry->m_pNext; else pBootpEntryPrev->m_pNext = pBootpEntry->m_pNext; pBootpEntry->m_pNext = NULL; delete pBootpEntry; VERIFY(m_listviewBootpTable.DeleteItem(iItem)); SetModified(); m_pData->m_dwDirtyFlags |= Set_BootFileTable; m_pBootpSelectedEntry = NULL; UpdateUI(); return; } pBootpEntryPrev = pBootpEntry; } // for // Should never reach this line Assert(FALSE && "Node not found"); } void CDhcpServerPropBootpTable::OnButtonPropertiesBootp() { // Edit the properties of the selected BOOTP entry if (m_pBootpSelectedEntry == NULL) return; CCreateBootpEntryDlg dlg; dlg.m_strBootImage = m_pBootpSelectedEntry->m_strBootImage; dlg.m_strFileName = m_pBootpSelectedEntry->m_strFileName; dlg.m_strFileServer = m_pBootpSelectedEntry->m_strFileServer; if (dlg.DoModal() != IDOK) return; m_pBootpSelectedEntry->m_strBootImage = dlg.m_strBootImage; m_pBootpSelectedEntry->m_strFileName = dlg.m_strFileName; m_pBootpSelectedEntry->m_strFileServer = dlg.m_strFileServer; LV_FINDINFO lvFindInfo; lvFindInfo.flags = LVFI_PARAM; lvFindInfo.lParam = (LPARAM)m_pBootpSelectedEntry; int iItem = m_listviewBootpTable.FindItem(&lvFindInfo); Assert(iItem >= 0); m_listviewBootpTable.SetItemText(iItem, 0, dlg.m_strBootImage); m_listviewBootpTable.SetItemText(iItem, 1, dlg.m_strFileName); m_listviewBootpTable.SetItemText(iItem, 2, dlg.m_strFileServer); SetModified(); m_pData->m_dwDirtyFlags |= Set_BootFileTable; } void CDhcpServerPropBootpTable::UpdateUI() { BOOL fEnable = m_pBootpSelectedEntry != NULL; ::EnableWindow(::GetDlgItem(m_hWnd, IDC_BUTTON_DELETE), fEnable); ::EnableWindow(::GetDlgItem(m_hWnd, IDC_BUTTON_PROPERTIES), fEnable); } ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // CCreateBootpEntryDlg dialog CCreateBootpEntryDlg::CCreateBootpEntryDlg(CWnd* pParent /*=NULL*/) : CDialog(CCreateBootpEntryDlg::IDD, pParent) { //{{AFX_DATA_INIT(CCreateBootpEntryDlg) //}}AFX_DATA_INIT } BOOL CCreateBootpEntryDlg::OnInitDialog() { CDialog::OnInitDialog(); if (!m_strBootImage.IsEmpty()) { // We already got something, so change the caption // from "add" to "properties" SetWindowTextPrintf(m_hWnd, IDS_BOOTP_PROPERTIES); } UpdateUI(); return TRUE; } void CCreateBootpEntryDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CCreateBootpEntryDlg) DDX_Text(pDX, IDC_EDIT_BOOT_IMAGE, m_strBootImage); DDV_MaxChars(pDX, m_strBootImage, 250); DDX_Text(pDX, IDC_EDIT_FILE_NAME, m_strFileName); DDV_MaxChars(pDX, m_strFileName, 250); DDX_Text(pDX, IDC_EDIT_SERVER_NAME, m_strFileServer); DDV_MaxChars(pDX, m_strFileServer, 250); //}}AFX_DATA_MAP TrimString(INOUT m_strBootImage); TrimString(INOUT m_strFileName); TrimString(INOUT m_strFileServer); } BEGIN_MESSAGE_MAP(CCreateBootpEntryDlg, CDialog) //{{AFX_MSG_MAP(CCreateBootpEntryDlg) ON_EN_CHANGE(IDC_EDIT_BOOT_IMAGE, OnChangeEditBootImage) ON_EN_CHANGE(IDC_EDIT_FILE_NAME, OnChangeEditFileName) ON_EN_CHANGE(IDC_EDIT_SERVER_NAME, OnChangeEditServerName) //}}AFX_MSG_MAP END_MESSAGE_MAP() void CCreateBootpEntryDlg::OnChangeEditBootImage() { UpdateUI(); } void CCreateBootpEntryDlg::OnChangeEditFileName() { UpdateUI(); } void CCreateBootpEntryDlg::OnChangeEditServerName() { UpdateUI(); } void CCreateBootpEntryDlg::UpdateUI() { UpdateData(); // Enable the OK button only if all the // fiends are filled. ::EnableWindow(::GetDlgItem(m_hWnd, IDOK), !m_strBootImage.IsEmpty() && !m_strFileName.IsEmpty() && !m_strFileServer.IsEmpty()); }