// DhcpRouteArrayEditor.cpp : implementation file // #include "stdafx.h" #include "RouteArrayEditor.h" #include "optcfg.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CDhcpRouteArrayEditor dialog CDhcpRouteArrayEditor::CDhcpRouteArrayEditor( CDhcpOption * pdhcType, DHCP_OPTION_SCOPE_TYPE dhcScopeType, CWnd *pParent ) : CBaseDialog(CDhcpRouteArrayEditor::IDD, pParent), m_p_type( pdhcType ), m_option_type( dhcScopeType ) { //{{AFX_DATA_INIT(CDhcpRouteArrayEditor) //}}AFX_DATA_INIT } void CDhcpRouteArrayEditor::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CDhcpRouteArrayEditor) DDX_Control(pDX, IDC_STATIC_OPTION_NAME, m_st_option); DDX_Control(pDX, IDC_STATIC_APPLICATION, m_st_application); DDX_Control(pDX, IDC_LIST_OF_ROUTES, m_lc_routes); DDX_Control(pDX, IDC_BUTN_ROUTE_DELETE, m_butn_route_delete); DDX_Control(pDX, IDC_BUTN_ROUTE_ADD, m_butn_route_add); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CDhcpRouteArrayEditor, CBaseDialog) //{{AFX_MSG_MAP(CDhcpRouteArrayEditor) ON_BN_CLICKED(IDC_BUTN_ROUTE_ADD, OnButnRouteAdd) ON_BN_CLICKED(IDC_BUTN_ROUTE_DELETE, OnButnRouteDelete) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CDhcpRouteArrayEditor message handlers void CDhcpRouteArrayEditor::OnButnRouteAdd() { CAddRoute NewRoute( NULL ); NewRoute.DoModal(); if ( NewRoute.m_bChange ) { const int IP_ADDR_LEN = 20; WCHAR strDest[ IP_ADDR_LEN ]; WCHAR strMask[ IP_ADDR_LEN ]; WCHAR strRouter[ IP_ADDR_LEN ]; // obtain the three strings.. ::UtilCvtIpAddrToWstr( NewRoute.Dest, strDest, IP_ADDR_LEN ); ::UtilCvtIpAddrToWstr( NewRoute.Mask, strMask, IP_ADDR_LEN ); ::UtilCvtIpAddrToWstr( NewRoute.Router, strRouter, IP_ADDR_LEN ); LV_ITEM lvi; lvi.mask = LVIF_TEXT; lvi.iItem = m_lc_routes.GetItemCount(); lvi.iSubItem = 0; lvi.pszText = ( LPTSTR )( LPCTSTR ) strDest; lvi.iImage = 0; lvi.stateMask = 0; int nItem = m_lc_routes.InsertItem( &lvi ); m_lc_routes.SetItemText( nItem, 1, strMask ); m_lc_routes.SetItemText( nItem, 2, strRouter ); // unselect others for ( int i = 0; i < m_lc_routes.GetItemCount(); i++ ) { m_lc_routes.SetItemState( i, 0, LVIS_SELECTED ); } // for // Make this route as selected item m_lc_routes.SetItemState( nItem, LVIS_SELECTED, LVIS_SELECTED ); HandleActivation(); } // if route added } // CDhcpRouteArrayEditor::OnButnRouteAdd() void CDhcpRouteArrayEditor::OnButnRouteDelete() { int nItem = m_lc_routes.GetNextItem( -1, LVNI_SELECTED ); int nDelItem = 0; while ( nItem != -1 ) { m_lc_routes.DeleteItem( nItem ); nDelItem = nItem; // Make the next one or the last one as selected nItem = m_lc_routes.GetNextItem( -1, LVNI_SELECTED ); } // while // Select an item int items = m_lc_routes.GetItemCount(); if ( items > 0 ) { if ( nDelItem >= items ) { nDelItem = items - 1; } m_lc_routes.SetItemState( nDelItem, LVIS_SELECTED, LVIS_SELECTED ); } // if HandleActivation(); } // CDhcpRouteArrayEditor::OnButnRouteDelete() void CDhcpRouteArrayEditor::OnCancel() { CBaseDialog::OnCancel(); } void CDhcpRouteArrayEditor::OnOK() { DWORD err = 0; int nItems, BufSize; CListCtrl *pList; LPBYTE Buffer; // The following code is borrowed from // CDhcpOptCfgPropPage::HandleActivationRouteArray() nItems = m_lc_routes.GetItemCount(); Buffer = new BYTE[ sizeof( DWORD ) * 4 * nItems ]; if ( NULL == Buffer ) { return; } BufSize = 0; for ( int i = 0; i < nItems; i++ ) { DHCP_IP_ADDRESS Dest, Mask, Router; Dest = UtilCvtWstrToIpAddr( m_lc_routes.GetItemText( i, 0 )); Mask = UtilCvtWstrToIpAddr( m_lc_routes.GetItemText( i, 1 )); Router = UtilCvtWstrToIpAddr( m_lc_routes.GetItemText( i, 2 )); Dest = htonl( Dest ); Router = htonl( Router ); int nBitsInMask = 0; while ( Mask != 0 ) { nBitsInMask++; Mask <<= 1; } // first add destination descriptor // first byte contains # of bits in mask // next few bytes contain the dest address for only // the significant octets Buffer[ BufSize++ ] = ( BYTE ) nBitsInMask; memcpy( &Buffer[ BufSize ], &Dest, ( nBitsInMask + 7 ) / 8 ); BufSize += ( nBitsInMask + 7 ) / 8; // now just copy the router address memcpy(& Buffer[ BufSize ], &Router, sizeof( Router )); BufSize += sizeof( Router ); } // for // Now write back the option value DHCP_OPTION_DATA_ELEMENT DataElement = { DhcpBinaryDataOption }; DHCP_OPTION_DATA Data = { 1, &DataElement }; DataElement.Element.BinaryDataOption.DataLength = BufSize; DataElement.Element.BinaryDataOption.Data = Buffer; err = m_p_type->QueryValue().SetData( &Data ); delete[] Buffer; m_p_type->SetDirty(); if ( err ) { ::DhcpMessageBox( err ); OnCancel(); } else { CBaseDialog::OnOK(); } } // CDhcpRouteArrayEditor::OnOK() // // strings and widths used for the list control // const int ROUTE_LIST_COL_HEADERS[3] = { IDS_ROUTE_LIST_COL_DEST, IDS_ROUTE_LIST_COL_MASK, IDS_ROUTE_LIST_COL_ROUTER }; const int ROUTE_COLS = sizeof( ROUTE_LIST_COL_HEADERS ) / sizeof( ROUTE_LIST_COL_HEADERS[ 0 ]); BOOL CDhcpRouteArrayEditor::OnInitDialog() { CString strColHeader; RECT rect; LONG width; CDhcpOptionValue &optValue = m_p_type->QueryValue(); // make sure the option type is set as Binary data type ASSERT( DhcpBinaryDataOption == optValue.QueryDataType()); CBaseDialog::OnInitDialog(); DWORD err = 0; int cStrId = ( m_option_type == DhcpDefaultOptions) ? IDS_INFO_TITLE_DEFAULT_OPTIONS : (( m_option_type == DhcpGlobalOptions ) ? IDS_INFO_TITLE_GLOBAL_OPTIONS : IDS_INFO_TITLE_SCOPE_OPTIONS ); // // setup the columns in the list control // m_lc_routes.GetClientRect( &rect ); width = ( rect.right - rect.left ) / 3; for ( int i = 0; i < ROUTE_COLS; i++ ) { strColHeader.LoadString( ROUTE_LIST_COL_HEADERS[ i ] ); m_lc_routes.InsertColumn( i, strColHeader, LVCFMT_LEFT, width, -1 ); } // for // Select a full row m_lc_routes.SetExtendedStyle( m_lc_routes.GetExtendedStyle() | LVS_EX_FULLROWSELECT ); const CByteArray *pbaData = optValue.QueryBinaryArray(); ASSERT( pbaData != NULL ); int nDataSize = ( int ) pbaData->GetSize(); LPBYTE pData = ( LPBYTE ) pbaData->GetData(); // // The following loop is copied from optcfg.cpp, // COptionsCfgPropPage::FillDataEntry() // while ( nDataSize > sizeof( DWORD )) { // first 1 byte contains the # of bits in subnetmask nDataSize --; BYTE nBitsMask = *pData ++; DWORD Mask = (~0); if( nBitsMask < 32 ) Mask <<= (32-nBitsMask); // based on the # of bits, the next few bytes contain // the subnet address for the 1-bits of subnet mask int nBytesDest = (nBitsMask+7)/8; if( nBytesDest > 4 ) nBytesDest = 4; DWORD Dest = 0; memcpy( &Dest, pData, nBytesDest ); pData += nBytesDest; nDataSize -= nBytesDest; // subnet address is obviously in network order. Dest = ntohl(Dest); // now the four bytes would be the router address DWORD Router = 0; if( nDataSize < sizeof(DWORD) ) { Assert( FALSE ); break; } memcpy(&Router, pData, sizeof(DWORD)); Router = ntohl( Router ); pData += sizeof(DWORD); nDataSize -= sizeof(DWORD); // now fill the list box.. const int IP_ADDR_LEN = 20; WCHAR strDest[ IP_ADDR_LEN ]; WCHAR strMask[ IP_ADDR_LEN ]; WCHAR strRouter[ IP_ADDR_LEN ]; ::UtilCvtIpAddrToWstr( Dest, strDest, IP_ADDR_LEN ); ::UtilCvtIpAddrToWstr( Mask, strMask, IP_ADDR_LEN ); ::UtilCvtIpAddrToWstr( Router, strRouter, IP_ADDR_LEN ); LV_ITEM lvi; lvi.mask = LVIF_TEXT; lvi.iItem = m_lc_routes.GetItemCount(); lvi.iSubItem = 0; lvi.pszText = ( LPTSTR )( LPCTSTR ) strDest; lvi.iImage = 0; lvi.stateMask = 0; int nItem = m_lc_routes.InsertItem( &lvi ); m_lc_routes.SetItemText( nItem, 1, strMask ); m_lc_routes.SetItemText( nItem, 2, strRouter ); } // while // set the first item as selected if any is added. if ( m_lc_routes.GetItemCount() > 0 ) { m_lc_routes.SetItemState( 0, LVIS_SELECTED, LVIS_SELECTED ); } CATCH_MEM_EXCEPTION { CString str; m_st_option.SetWindowText( m_p_type->QueryName()); str.LoadString( cStrId ); m_st_application.SetWindowText( str ); // Set proper button states. HandleActivation(); } END_MEM_EXCEPTION( err ); if ( err ) { ::DhcpMessageBox( err ); EndDialog( -1 ); } return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE } // CDhcpRouteArrayEditor::OnInitDialog() void CDhcpRouteArrayEditor::HandleActivation() { int cItems = m_lc_routes.GetItemCount(); // set the focus to Add button m_butn_route_add.SetFocus(); m_butn_route_delete.EnableWindow( 0 != cItems ); UpdateData( FALSE ); } // CDhcpRouteArrayEditor::HandleActivation()