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.
1392 lines
39 KiB
1392 lines
39 KiB
//***************************************************************************
|
|
//
|
|
// VIPSPAGE.CPP
|
|
//
|
|
// Module: NLB Manager
|
|
//
|
|
// Purpose: Implements VipsPage, which is a dialog for managing the list
|
|
// of cluster ip addresses.
|
|
//
|
|
// Copyright (c)2001 Microsoft Corporation, All Rights Reserved
|
|
//
|
|
// History:
|
|
//
|
|
// 09/24/01 JosephJ Created
|
|
// 01/22/2002 SHouse cleaned up this dialog
|
|
//
|
|
//***************************************************************************
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
#include "private.h"
|
|
#include "vipspage.h"
|
|
#include "vipspage.tmh"
|
|
|
|
|
|
// BEGIN_MESSAGE_MAP( VipsPage, CDialog )
|
|
|
|
BEGIN_MESSAGE_MAP( VipsPage, CPropertyPage )
|
|
|
|
ON_BN_CLICKED(IDC_BUTTON_ADD_VIP, OnButtonAdd)
|
|
ON_BN_CLICKED(IDC_BUTTON_MODIFY_VIP, OnButtonEdit)
|
|
ON_BN_CLICKED(IDC_BUTTON_REMOVE_VIP, OnButtonRemove)
|
|
ON_NOTIFY(NM_DBLCLK, IDC_LIST_ADDITIONAL_VIPS, OnDoubleClick)
|
|
|
|
ON_WM_HELPINFO()
|
|
ON_WM_CONTEXTMENU()
|
|
ON_NOTIFY( LVN_ITEMCHANGED, IDC_LIST_ADDITIONAL_VIPS, OnSelchanged )
|
|
|
|
//
|
|
// Other options...
|
|
//
|
|
// ON_EN_SETFOCUS(IDC_EDIT_HOSTADDRESS,OnSetFocusEditHostAddress)
|
|
// ON_WM_ACTIVATE()
|
|
// ON_NOTIFY( NM_DBLCLK, IDC_LIST_ADDITONAL_VIPS, OnDoubleClick )
|
|
// ON_NOTIFY( LVN_COLUMNCLICK, IDC_LIST_ADDITONAL_VIPS, OnColumnClick )
|
|
//
|
|
|
|
END_MESSAGE_MAP()
|
|
|
|
|
|
//
|
|
// Static help-id maps
|
|
//
|
|
|
|
DWORD
|
|
VipsPage::s_HelpIDs[] =
|
|
{
|
|
IDC_GROUP_PRIMARY_IP, IDC_EDIT_PRIMARY_IP,
|
|
IDC_TEXT_PRIMARY_IP, IDC_EDIT_PRIMARY_IP,
|
|
IDC_EDIT_PRIMARY_IP, IDC_EDIT_PRIMARY_IP,
|
|
IDC_TEXT_PRIMARY_MASK, IDC_EDIT_PRIMARY_IP,
|
|
IDC_EDIT_PRIMARY_MASK, IDC_EDIT_PRIMARY_IP,
|
|
IDC_GROUP_ADDITIONAL_VIPS, IDC_LIST_ADDITIONAL_VIPS,
|
|
IDC_LIST_ADDITIONAL_VIPS, IDC_LIST_ADDITIONAL_VIPS,
|
|
IDC_BUTTON_ADD_VIP, IDC_BUTTON_ADD_VIP,
|
|
IDC_BUTTON_MODIFY_VIP, IDC_BUTTON_MODIFY_VIP,
|
|
IDC_BUTTON_REMOVE_VIP, IDC_BUTTON_REMOVE_VIP,
|
|
0, 0
|
|
};
|
|
|
|
|
|
VipsPage::VipsPage(
|
|
CPropertySheet *psh,
|
|
NLB_EXTENDED_CLUSTER_CONFIGURATION *pNlbCfg,
|
|
BOOL fClusterView,
|
|
CWnd* parent
|
|
)
|
|
:
|
|
CPropertyPage(IDD),
|
|
m_pshOwner(psh),
|
|
m_pNlbCfg(pNlbCfg),
|
|
m_fClusterView(fClusterView),
|
|
m_fModified(FALSE),
|
|
m_uPrimaryClusterIp(0)
|
|
{
|
|
|
|
}
|
|
|
|
void
|
|
VipsPage::DoDataExchange( CDataExchange* pDX )
|
|
{
|
|
// CDialog::DoDataExchange(pDX);
|
|
CPropertyPage::DoDataExchange(pDX);
|
|
|
|
DDX_Control(pDX, IDC_LIST_ADDITIONAL_VIPS, listAdditionalVips);
|
|
|
|
//
|
|
// Note: the buttons are handled by the ON_BN_CLICKED macro
|
|
// above.
|
|
//
|
|
// DDX_Control(pDX, IDC_BUTTON_CONNECT, buttonConnect);
|
|
// DDX_Control(pDX, IDC_BUTTON_CREDENTIALS, credentialsButton);
|
|
}
|
|
|
|
|
|
BOOL
|
|
VipsPage::OnInitDialog()
|
|
{
|
|
BOOL fRet = CPropertyPage::OnInitDialog();
|
|
|
|
if (fRet)
|
|
{
|
|
CWnd *pItem = NULL;
|
|
|
|
// Initialize the list control
|
|
mfn_InitializeListView();
|
|
|
|
mfn_LoadFromNlbCfg();
|
|
|
|
/* Disable the Delete button. */
|
|
pItem = GetDlgItem(IDC_BUTTON_REMOVE_VIP);
|
|
if (pItem)
|
|
{
|
|
::EnableWindow (pItem->m_hWnd, FALSE);
|
|
}
|
|
|
|
/* Disable the Edit button. */
|
|
pItem = GetDlgItem(IDC_BUTTON_MODIFY_VIP);
|
|
if (pItem)
|
|
{
|
|
::EnableWindow (pItem->m_hWnd, FALSE);
|
|
}
|
|
|
|
/* Enable the Add button only if we're showing cluster
|
|
properties; otherwise its read-only, disable it. */
|
|
pItem = GetDlgItem(IDC_BUTTON_ADD_VIP);
|
|
if (pItem)
|
|
{
|
|
::EnableWindow (pItem->m_hWnd, m_fClusterView);
|
|
}
|
|
|
|
/* Disable the primary IP address dialog. */
|
|
pItem = GetDlgItem(IDC_EDIT_PRIMARY_IP);
|
|
if (pItem)
|
|
{
|
|
::EnableWindow (pItem->m_hWnd, FALSE);
|
|
}
|
|
|
|
/* Disable the primary IP subnet mask dialog */
|
|
pItem = GetDlgItem(IDC_EDIT_PRIMARY_MASK);
|
|
if (pItem)
|
|
{
|
|
::EnableWindow (pItem->m_hWnd, FALSE);
|
|
}
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
|
|
|
|
BOOL
|
|
VipsPage::OnHelpInfo (HELPINFO* helpInfo )
|
|
{
|
|
if( helpInfo->iContextType == HELPINFO_WINDOW )
|
|
{
|
|
::WinHelp( static_cast<HWND> ( helpInfo->hItemHandle ),
|
|
CVY_CTXT_HELP_FILE,
|
|
HELP_WM_HELP,
|
|
(ULONG_PTR ) s_HelpIDs);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
void
|
|
VipsPage::OnContextMenu( CWnd* pWnd, CPoint point )
|
|
{
|
|
::WinHelp( m_hWnd,
|
|
CVY_CTXT_HELP_FILE,
|
|
HELP_CONTEXTMENU,
|
|
(ULONG_PTR ) s_HelpIDs);
|
|
}
|
|
|
|
BOOL
|
|
VipsPage::OnKillActive()
|
|
{
|
|
// validate data
|
|
|
|
mfn_SaveToNlbCfg();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void
|
|
VipsPage::mfn_InitializeListView(void)
|
|
//
|
|
// Set the columns on the list box based on the type of dialog
|
|
//
|
|
{
|
|
RECT rect;
|
|
INT colWidth;
|
|
CWnd * List = GetDlgItem(IDC_LIST_ADDITIONAL_VIPS);
|
|
|
|
List->GetClientRect(&rect);
|
|
|
|
colWidth = (rect.right - rect.left)/2;
|
|
|
|
//
|
|
// The interface list is that of interfaces already bound to NLB.
|
|
// we display the cluster dnsname and ip first, then adapter name.
|
|
//
|
|
listAdditionalVips.InsertColumn(
|
|
0,
|
|
GETRESOURCEIDSTRING( IDS_HEADER_VIPLIST_IP_ADDRESS),
|
|
LVCFMT_LEFT,
|
|
colWidth);
|
|
|
|
listAdditionalVips.InsertColumn(
|
|
1,
|
|
GETRESOURCEIDSTRING( IDS_HEADER_VIPLIST_SUBNET_MASK),
|
|
LVCFMT_LEFT,
|
|
colWidth);
|
|
|
|
//
|
|
// Allow entire row to be selected.
|
|
//
|
|
listAdditionalVips.SetExtendedStyle(listAdditionalVips.GetExtendedStyle() | LVS_EX_FULLROWSELECT );
|
|
}
|
|
|
|
void
|
|
VipsPage::mfn_InsertNetworkAddress(
|
|
LPCWSTR szIP,
|
|
LPCWSTR szSubnetMask,
|
|
UINT lParam,
|
|
int nItem
|
|
)
|
|
{
|
|
LVFINDINFO Info;
|
|
int eItem;
|
|
|
|
ZeroMemory(&Info, sizeof(Info));
|
|
|
|
Info.flags = LVFI_PARAM;
|
|
Info.lParam = lParam;
|
|
|
|
eItem = listAdditionalVips.FindItem(&Info);
|
|
|
|
/* If we found an entry that already has this IP address, we
|
|
need to do some extra work to resolve the duplicate entry. */
|
|
if (eItem != -1) {
|
|
/* If this is an Add operation, then we should simple usurp
|
|
this entry in the list and re-use it for this IP. If a
|
|
user tries to add an IP address that already exists, we'll
|
|
in effect change it to a modify operation in the case that
|
|
the subnet mask has changed; otherwise its a no-op. */
|
|
if (nItem == -1) {
|
|
/* Change nItem to eItem to usurp the existing list entry
|
|
for this new IP address entry. */
|
|
nItem = eItem;
|
|
|
|
/* Otherwise, if this is already an edit operation, then what
|
|
what actually need to do is both turn this operation into
|
|
an edit on the existing entry we found for this IP address,
|
|
but further, we need to delete the item we were actually in
|
|
the process of editing, as it was the user's intention to
|
|
get rid of that IP address. */
|
|
} else if (eItem != nItem) {
|
|
/* Delete the list entry we're "editing". */
|
|
listAdditionalVips.DeleteItem(nItem);
|
|
|
|
/* Change nItem to eItem to usurp the existing list entry
|
|
for this new IP address entry. */
|
|
nItem = eItem;
|
|
}
|
|
}
|
|
|
|
/* An index of -1 indicates a new item to list. If the index is NOT
|
|
-1, then we're dealing with changes to an existing list item. */
|
|
if (nItem != -1) {
|
|
|
|
listAdditionalVips.SetItemText(nItem, 0, szIP);
|
|
listAdditionalVips.SetItemText(nItem, 1, szSubnetMask);
|
|
|
|
/* Otherwise, insert a new item. */
|
|
} else {
|
|
|
|
nItem = listAdditionalVips.GetItemCount();
|
|
|
|
/* Add the IP address. */
|
|
listAdditionalVips.InsertItem(
|
|
LVIF_TEXT | LVIF_PARAM, // nMask
|
|
nItem, // nItem
|
|
szIP,
|
|
0, // nState
|
|
0, // nStateMask
|
|
0, // nImage
|
|
lParam // lParam
|
|
);
|
|
|
|
/* Add the subnet mask. */
|
|
listAdditionalVips.SetItemText(nItem, 1, szSubnetMask);
|
|
}
|
|
|
|
/* Select the new or modified rule. */
|
|
listAdditionalVips.SetItemState(nItem, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
|
|
|
|
return;
|
|
}
|
|
|
|
void VipsPage::OnOK()
|
|
{
|
|
mfn_SaveToNlbCfg();
|
|
CPropertyPage::OnOK();
|
|
}
|
|
|
|
void VipsPage::OnButtonAdd()
|
|
/*
|
|
User has clicked the "Add" button.
|
|
2. Switch cursor to hourglass, connect, switch back from hourglass.
|
|
*/
|
|
{
|
|
LPWSTR szIPAddress = NULL;
|
|
LPWSTR szSubnetMask = NULL;
|
|
|
|
/* Create a dialog to add a new VIP. Initialize with empty strings
|
|
(or NULL) since this is an Add operation. */
|
|
CIPAddressDialog pIPDlg(L"", L"");
|
|
|
|
/* Show the dialog box. If the user presses "OK", update the VIP list, otherwise ignore it. */
|
|
if (pIPDlg.DoModal() == IDOK) {
|
|
WCHAR szMungedIpAddress[WLBS_MAX_CL_IP_ADDR+1];
|
|
WCHAR szDefaultSubnetMask[WLBS_MAX_CL_NET_MASK+1];
|
|
WCHAR szConcatenatedIPandMask[WLBS_MAX_CL_IP_ADDR + WLBS_MAX_CL_NET_MASK + 2];
|
|
LPWSTR szNewIPAddress = NULL;
|
|
LPWSTR szNewSubnetMask = NULL;
|
|
UINT uClusterIp = 0;
|
|
UINT uSubnetMask = 0;
|
|
UINT uDefaultSubnetMask = 0;
|
|
|
|
/* Get the IP address and subnet mask the user typed into the dialog.
|
|
Note that the dialog allocates the memory for us and we're required
|
|
to free it when we're done. */
|
|
szIPAddress = pIPDlg.GetIPAddress();
|
|
szSubnetMask = pIPDlg.GetSubnetMask();
|
|
|
|
/* Cat the IP address and subnetmask for verification by CfgUtilsValidateNetworkAddress. */
|
|
StringCbPrintf(
|
|
szConcatenatedIPandMask,
|
|
sizeof(szConcatenatedIPandMask),
|
|
L"%ls/%ls", szIPAddress, szSubnetMask
|
|
);
|
|
|
|
//
|
|
// Validate the network address -- if failure, put up msg box.
|
|
// TODO: call extended validation function.
|
|
//
|
|
{
|
|
WBEMSTATUS wStat;
|
|
|
|
wStat = CfgUtilsValidateNetworkAddress(
|
|
szConcatenatedIPandMask,
|
|
&uClusterIp,
|
|
&uSubnetMask,
|
|
&uDefaultSubnetMask
|
|
);
|
|
|
|
if (!FAILED(wStat))
|
|
{
|
|
//
|
|
// Add some more checks...
|
|
//
|
|
UINT u = uClusterIp&0xff;
|
|
if (u<1 || u>=224)
|
|
{
|
|
wStat = WBEM_E_CRITICAL_ERROR;
|
|
}
|
|
}
|
|
|
|
if (FAILED(wStat))
|
|
{
|
|
::MessageBox(
|
|
NULL,
|
|
GETRESOURCEIDSTRING(IDS_INVALID_IP_OR_SUBNET),
|
|
GETRESOURCEIDSTRING(IDS_INVALID_INFORMATION),
|
|
MB_ICONINFORMATION | MB_OK
|
|
);
|
|
goto end;
|
|
}
|
|
|
|
//
|
|
// Can't add the primary cluster vip.
|
|
//
|
|
if (uClusterIp == m_uPrimaryClusterIp)
|
|
{
|
|
goto end;
|
|
}
|
|
}
|
|
|
|
if (*szSubnetMask == 0)
|
|
{
|
|
// subnet mask was not specified -- substitute default.
|
|
uSubnetMask = uDefaultSubnetMask;
|
|
}
|
|
|
|
//
|
|
// Change subnet to canonical form...
|
|
//
|
|
{
|
|
LPBYTE pb = (LPBYTE) &uSubnetMask;
|
|
StringCbPrintf(
|
|
szDefaultSubnetMask,
|
|
sizeof(szDefaultSubnetMask),
|
|
L"%lu.%lu.%lu.%lu",
|
|
pb[0], pb[1], pb[2], pb[3]
|
|
);
|
|
szNewSubnetMask = szDefaultSubnetMask;
|
|
}
|
|
|
|
//
|
|
// Change IP to canonical form
|
|
//
|
|
{
|
|
LPBYTE pb = (LPBYTE) &uClusterIp;
|
|
StringCbPrintf(
|
|
szMungedIpAddress,
|
|
sizeof(szMungedIpAddress),
|
|
L"%lu.%lu.%lu.%lu",
|
|
pb[0], pb[1], pb[2], pb[3]
|
|
);
|
|
szNewIPAddress = szMungedIpAddress;
|
|
}
|
|
|
|
//
|
|
// mfn_InsertNetworkAddress will make sure it's inserted in the
|
|
// proper location and will not insert it if it's a duplicate.
|
|
//
|
|
mfn_InsertNetworkAddress(szNewIPAddress, szNewSubnetMask, uClusterIp, -1);
|
|
|
|
m_fModified = TRUE; // we'll need to update m_pNlbCfg later.
|
|
}
|
|
|
|
end:
|
|
|
|
/* Move the focus from the add button back to the list view. */
|
|
listAdditionalVips.SetFocus();
|
|
|
|
/* Free the IP address and subnet mask memory that were allocated by CIPAddressDialog. */
|
|
if (szIPAddress) free(szIPAddress);
|
|
if (szSubnetMask) free(szSubnetMask);
|
|
|
|
return;
|
|
}
|
|
|
|
void VipsPage::OnButtonRemove()
|
|
/*
|
|
User has clicked the "Remove" button.
|
|
*/
|
|
{
|
|
int nItem;
|
|
UINT uCount;
|
|
|
|
/* Get the selected item - if nothing is selected, bail out. */
|
|
nItem = listAdditionalVips.GetNextItem(-1, LVNI_ALL|LVNI_SELECTED);
|
|
if (nItem == -1)
|
|
{
|
|
goto end;
|
|
}
|
|
|
|
/* Delete the selected entry. */
|
|
listAdditionalVips.DeleteItem(nItem);
|
|
|
|
uCount = listAdditionalVips.GetItemCount();
|
|
|
|
if (uCount > nItem) {
|
|
/* This was NOT the last (in order) VIP in the list, so highlight
|
|
the VIP in the same position in the list box. */
|
|
listAdditionalVips.SetItemState(nItem, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
|
|
} else if (uCount > 0) {
|
|
/* This was the last (in order) VIP in the list, so we highlight
|
|
the VIP "behind" us in the list - our position minus one. */
|
|
listAdditionalVips.SetItemState(nItem - 1, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
|
|
} else {
|
|
/* The list is empty - no need to select anything. */
|
|
}
|
|
|
|
m_fModified = TRUE; // we'll need to update m_pNlbCfg later.
|
|
|
|
end:
|
|
|
|
/* Move the focus from the delete button back to the list view. */
|
|
listAdditionalVips.SetFocus();
|
|
|
|
return;
|
|
}
|
|
|
|
void VipsPage::OnDoubleClick (NMHDR * pNotifyStruct, LRESULT * result )
|
|
{
|
|
OnButtonEdit();
|
|
|
|
*result = 0;
|
|
return;
|
|
}
|
|
|
|
void VipsPage::OnButtonEdit()
|
|
/*
|
|
User has clicked the "Edit" button.
|
|
*/
|
|
{
|
|
WCHAR wszSubnetMask[64];
|
|
WCHAR wszIPAddress[64];
|
|
LPWSTR szIPAddress = NULL;
|
|
LPWSTR szSubnetMask = NULL;
|
|
|
|
int nItem;
|
|
int iLen;
|
|
|
|
nItem = listAdditionalVips.GetNextItem(-1, LVNI_ALL|LVNI_SELECTED);
|
|
|
|
if (nItem == -1)
|
|
{
|
|
return;
|
|
}
|
|
|
|
/* Get the IP address from the listview. */
|
|
iLen = listAdditionalVips.GetItemText(
|
|
nItem,
|
|
0,
|
|
wszIPAddress,
|
|
sizeof(wszIPAddress)/sizeof(*wszIPAddress));
|
|
|
|
wszIPAddress[(sizeof(wszIPAddress)/sizeof(*wszIPAddress))-1]=0;
|
|
|
|
/* Get the subnet mask from the listview. */
|
|
iLen = listAdditionalVips.GetItemText(
|
|
nItem,
|
|
1,
|
|
wszSubnetMask,
|
|
sizeof(wszSubnetMask)/sizeof(*wszSubnetMask));
|
|
|
|
wszSubnetMask[(sizeof(wszSubnetMask)/sizeof(*wszSubnetMask))-1]=0;
|
|
|
|
/* Create a dialog to add a new VIP. Initialize with the IP address and
|
|
subnet masks retrieved from the listview since this is an Edit operation. */
|
|
CIPAddressDialog pIPDlg(wszIPAddress, wszSubnetMask);
|
|
|
|
/* Show the dialog box. If the user presses "OK", update the VIP list, otherwise ignore it. */
|
|
if (pIPDlg.DoModal() == IDOK) {
|
|
WCHAR szMungedIpAddress[WLBS_MAX_CL_IP_ADDR+1];
|
|
WCHAR szDefaultSubnetMask[WLBS_MAX_CL_NET_MASK+1];
|
|
WCHAR szConcatenatedIPandMask[WLBS_MAX_CL_IP_ADDR + WLBS_MAX_CL_NET_MASK + 2];
|
|
LPWSTR szNewIPAddress = NULL;
|
|
LPWSTR szNewSubnetMask = NULL;
|
|
UINT uClusterIp = 0;
|
|
UINT uSubnetMask = 0;
|
|
UINT uDefaultSubnetMask = 0;
|
|
|
|
/* Get the IP address and subnet mask the user typed into the dialog.
|
|
Note that the dialog allocates the memory for us and we're required
|
|
to free it when we're done. */
|
|
szIPAddress = pIPDlg.GetIPAddress();
|
|
szSubnetMask = pIPDlg.GetSubnetMask();
|
|
|
|
/* Cat the IP address and subnetmask for verification by CfgUtilsValidateNetworkAddress. */
|
|
StringCbPrintf(
|
|
szConcatenatedIPandMask,
|
|
sizeof(szConcatenatedIPandMask),
|
|
L"%ls/%ls", szIPAddress, szSubnetMask
|
|
);
|
|
|
|
//
|
|
// Validate the network address -- if failure, put up msg box.
|
|
// TODO: call extended validation function.
|
|
//
|
|
{
|
|
WBEMSTATUS wStat;
|
|
|
|
wStat = CfgUtilsValidateNetworkAddress(
|
|
szConcatenatedIPandMask,
|
|
&uClusterIp,
|
|
&uSubnetMask,
|
|
&uDefaultSubnetMask
|
|
);
|
|
|
|
if (!FAILED(wStat))
|
|
{
|
|
//
|
|
// Add some more checks...
|
|
//
|
|
UINT u = uClusterIp&0xff;
|
|
if (u<1 || u>=224)
|
|
{
|
|
wStat = WBEM_E_CRITICAL_ERROR;
|
|
}
|
|
}
|
|
|
|
if (FAILED(wStat))
|
|
{
|
|
::MessageBox(
|
|
NULL,
|
|
GETRESOURCEIDSTRING(IDS_INVALID_IP_OR_SUBNET),
|
|
GETRESOURCEIDSTRING(IDS_INVALID_INFORMATION),
|
|
MB_ICONINFORMATION | MB_OK
|
|
);
|
|
goto end;
|
|
}
|
|
|
|
//
|
|
// Can't add the primary cluster vip.
|
|
//
|
|
if (uClusterIp == m_uPrimaryClusterIp)
|
|
{
|
|
goto end;
|
|
}
|
|
}
|
|
|
|
if (*szSubnetMask == 0)
|
|
{
|
|
// subnet mask was not specified -- substitute default.
|
|
uSubnetMask = uDefaultSubnetMask;
|
|
}
|
|
|
|
//
|
|
// Change subnet to canonical form...
|
|
//
|
|
{
|
|
LPBYTE pb = (LPBYTE) &uSubnetMask;
|
|
StringCbPrintf(
|
|
szDefaultSubnetMask,
|
|
sizeof(szDefaultSubnetMask),
|
|
L"%lu.%lu.%lu.%lu",
|
|
pb[0], pb[1], pb[2], pb[3]
|
|
);
|
|
szNewSubnetMask = szDefaultSubnetMask;
|
|
}
|
|
|
|
//
|
|
// Change IP to canonical form
|
|
//
|
|
{
|
|
LPBYTE pb = (LPBYTE) &uClusterIp;
|
|
StringCbPrintf(
|
|
szMungedIpAddress,
|
|
sizeof(szMungedIpAddress),
|
|
L"%lu.%lu.%lu.%lu",
|
|
pb[0], pb[1], pb[2], pb[3]
|
|
);
|
|
szNewIPAddress = szMungedIpAddress;
|
|
}
|
|
|
|
//
|
|
// mfn_InsertNetworkAddress will make sure it's inserted in the
|
|
// proper location and will not insert it if it's a duplicate.
|
|
//
|
|
mfn_InsertNetworkAddress(szNewIPAddress, szNewSubnetMask, uClusterIp, nItem);
|
|
|
|
m_fModified = TRUE; // we'll need to update m_pNlbCfg later.
|
|
}
|
|
|
|
end:
|
|
|
|
/* Move the focus from the edit button back to the list view. */
|
|
listAdditionalVips.SetFocus();
|
|
|
|
/* Free the IP address and subnet mask memory that were allocated by CIPAddressDialog. */
|
|
if (szIPAddress) free(szIPAddress);
|
|
if (szSubnetMask) free(szSubnetMask);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void VipsPage::OnSelchanged(NMHDR * pNotifyStruct, LRESULT * result )
|
|
/*
|
|
A listbox item has been selected.
|
|
*/
|
|
{
|
|
POSITION pos;
|
|
BOOL fSelected = FALSE;
|
|
|
|
if (!m_fClusterView)
|
|
{
|
|
goto end; // we don't allow modifications unless its the cluster
|
|
// view.
|
|
}
|
|
|
|
pos = listAdditionalVips.GetFirstSelectedItemPosition();
|
|
fSelected = FALSE;
|
|
if( pos != NULL )
|
|
{
|
|
int index = listAdditionalVips.GetNextSelectedItem( pos );
|
|
fSelected = TRUE;
|
|
}
|
|
else
|
|
{
|
|
}
|
|
|
|
if (fSelected)
|
|
{
|
|
// enable remove
|
|
::EnableWindow (GetDlgItem(IDC_BUTTON_REMOVE_VIP)->m_hWnd, TRUE);
|
|
// enable edit
|
|
::EnableWindow (GetDlgItem(IDC_BUTTON_MODIFY_VIP)->m_hWnd, TRUE);
|
|
}
|
|
else
|
|
{
|
|
// disable remove
|
|
::EnableWindow (GetDlgItem(IDC_BUTTON_REMOVE_VIP)->m_hWnd, FALSE);
|
|
// disable edit
|
|
::EnableWindow (GetDlgItem(IDC_BUTTON_MODIFY_VIP)->m_hWnd, FALSE);
|
|
}
|
|
|
|
end:
|
|
|
|
*result = 0;
|
|
return;
|
|
}
|
|
|
|
BOOL
|
|
VipsPage::OnSetActive()
|
|
{
|
|
BOOL fRet = CPropertyPage::OnSetActive();
|
|
m_pshOwner->SetWizardButtons(
|
|
PSWIZB_BACK|
|
|
PSWIZB_NEXT|
|
|
// PSWIZB_FINISH|
|
|
// PSWIZB_DISABLEDFINISH|
|
|
0
|
|
);
|
|
|
|
mfn_LoadFromNlbCfg();
|
|
|
|
return fRet;
|
|
}
|
|
|
|
void
|
|
VipsPage::mfn_LoadFromNlbCfg(void)
|
|
{
|
|
WBEMSTATUS wStatus;
|
|
UINT uClusterIp = 0;
|
|
UINT uDedicatedIp = 0;
|
|
WBEMSTATUS wStat;
|
|
|
|
//
|
|
// Initialize the cluster network address.
|
|
//
|
|
{
|
|
CWnd *pItem = GetDlgItem(IDC_EDIT_PRIMARY_IP);
|
|
|
|
m_uPrimaryClusterIp = 0;
|
|
|
|
if (pItem)
|
|
{
|
|
wStat = CfgUtilsValidateNetworkAddress(
|
|
m_pNlbCfg->NlbParams.cl_ip_addr,
|
|
&uClusterIp,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
if (wStat != WBEM_NO_ERROR)
|
|
{
|
|
uClusterIp = 0;
|
|
pItem->SetWindowText(L"");
|
|
}
|
|
else
|
|
{
|
|
m_uPrimaryClusterIp = uClusterIp;
|
|
pItem->SetWindowText(m_pNlbCfg->NlbParams.cl_ip_addr);
|
|
}
|
|
}
|
|
|
|
pItem = GetDlgItem(IDC_EDIT_PRIMARY_MASK);
|
|
|
|
if (pItem)
|
|
{
|
|
pItem->SetWindowText(m_pNlbCfg->NlbParams.cl_net_mask);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Get the DWORD form of the dedicated IP address
|
|
//
|
|
{
|
|
wStat = CfgUtilsValidateNetworkAddress(
|
|
m_pNlbCfg->NlbParams.ded_ip_addr,
|
|
&uDedicatedIp,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
if (wStat != WBEM_NO_ERROR)
|
|
{
|
|
uDedicatedIp = 0;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Fill in the list box, EXCLUDING the cluster network address
|
|
// and dedicated ip address (if each are present)
|
|
//
|
|
{
|
|
//
|
|
// Clear the list box
|
|
//
|
|
listAdditionalVips.DeleteAllItems();
|
|
|
|
|
|
//
|
|
// For each ip address list, if it's not the vip or dip,
|
|
// insert it into the list view.
|
|
//
|
|
// Find location of old network address
|
|
for (UINT u=0; u<m_pNlbCfg->NumIpAddresses; u++)
|
|
{
|
|
UINT uTmpIp = 0;
|
|
NLB_IP_ADDRESS_INFO *pInfo = & m_pNlbCfg->pIpAddressInfo[u];
|
|
wStat = CfgUtilsValidateNetworkAddress(
|
|
pInfo->IpAddress,
|
|
&uTmpIp,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
if (wStat == WBEM_NO_ERROR)
|
|
{
|
|
if (uTmpIp == uDedicatedIp || uTmpIp == uClusterIp)
|
|
{
|
|
//
|
|
// It's the cluster ip or the dedicated ip -- skip.
|
|
//
|
|
continue;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TRACE_CRIT(L"%!FUNC! Invalid IP address %ws",
|
|
m_pNlbCfg->pIpAddressInfo[u].IpAddress);
|
|
|
|
//
|
|
// Invalid IP -- don't display it -- should we?
|
|
//
|
|
continue;
|
|
}
|
|
|
|
mfn_InsertNetworkAddress(
|
|
pInfo->IpAddress,
|
|
pInfo->SubnetMask,
|
|
uTmpIp,
|
|
-1
|
|
);
|
|
}
|
|
}
|
|
|
|
m_fModified = FALSE; // not been modified since we've last synched
|
|
// with m_pNlbCfg.
|
|
}
|
|
|
|
void
|
|
VipsPage::mfn_SaveToNlbCfg(void)
|
|
/*
|
|
Save settings to m_pNlbCfg
|
|
*/
|
|
{
|
|
WBEMSTATUS wStatus;
|
|
|
|
if (!m_fModified)
|
|
{
|
|
// Nothing to do.
|
|
goto end;
|
|
}
|
|
|
|
m_fModified = FALSE;
|
|
|
|
//
|
|
// We expect that the list ctrl never contains the
|
|
// primary cluster IP, so we'll always add it first,
|
|
// followed by all the ip in the list ctrl.
|
|
//
|
|
{
|
|
// Pre-allocate the array
|
|
UINT uCount = listAdditionalVips.GetItemCount();
|
|
|
|
NLB_IP_ADDRESS_INFO *rgInfo = new NLB_IP_ADDRESS_INFO[uCount+1];
|
|
|
|
if (rgInfo == NULL)
|
|
{
|
|
TRACE_CRIT("%!FUNC! allocation failure!");
|
|
goto end;
|
|
}
|
|
|
|
ZeroMemory(rgInfo, sizeof(NLB_IP_ADDRESS_INFO)*(uCount+1));
|
|
|
|
//
|
|
// Insert the primary vip first.
|
|
//
|
|
ARRAYSTRCPY(
|
|
rgInfo[0].IpAddress,
|
|
m_pNlbCfg->NlbParams.cl_ip_addr
|
|
);
|
|
ARRAYSTRCPY(
|
|
rgInfo[0].SubnetMask,
|
|
m_pNlbCfg->NlbParams.cl_net_mask
|
|
);
|
|
|
|
//
|
|
// Insert the remaining ones.
|
|
//
|
|
for (int nItem = 0; nItem < uCount; nItem++)
|
|
{
|
|
NLB_IP_ADDRESS_INFO *pInfo = &rgInfo[nItem+1];
|
|
WCHAR rgTmp[64];
|
|
int iLen;
|
|
|
|
/* Get the IP address. */
|
|
iLen = listAdditionalVips.GetItemText(
|
|
nItem,
|
|
0, // nSubItem,
|
|
rgTmp,
|
|
sizeof(rgTmp)/sizeof(*rgTmp));
|
|
|
|
rgTmp[(sizeof(rgTmp)/sizeof(*rgTmp))-1]=0;
|
|
|
|
if (iLen > 0)
|
|
{
|
|
ARRAYSTRCPY(pInfo->IpAddress, rgTmp);
|
|
}
|
|
|
|
/* Get the subnet mask. */
|
|
iLen = listAdditionalVips.GetItemText(
|
|
nItem,
|
|
1, // nSubItem,
|
|
rgTmp,
|
|
sizeof(rgTmp)/sizeof(*rgTmp));
|
|
|
|
rgTmp[(sizeof(rgTmp)/sizeof(*rgTmp))-1]=0;
|
|
|
|
if (iLen > 0)
|
|
{
|
|
ARRAYSTRCPY(pInfo->SubnetMask, rgTmp);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Now replace the old address list with the new.
|
|
//
|
|
m_pNlbCfg->SetNetworkAddressesRaw(rgInfo, uCount+1);
|
|
}
|
|
|
|
end:
|
|
|
|
return;
|
|
}
|
|
|
|
/*** CIPAddressDialog ***/
|
|
|
|
DWORD
|
|
CIPAddressDialog::s_HelpIDs[] =
|
|
{
|
|
IDC_TEXT_IP_ADDRESS, IDC_EDIT_IP_ADDRESS,
|
|
IDC_EDIT_IP_ADDRESS, IDC_EDIT_IP_ADDRESS,
|
|
IDC_TEXT_SUBNET_MASK, IDC_EDIT_IP_ADDRESS,
|
|
IDC_EDIT_SUBNET_MASK, IDC_EDIT_IP_ADDRESS,
|
|
0, 0
|
|
};
|
|
|
|
BEGIN_MESSAGE_MAP(CIPAddressDialog, CDialog)
|
|
|
|
ON_EN_SETFOCUS (IDC_EDIT_SUBNET_MASK, OnEditSubnetMask)
|
|
|
|
ON_WM_HELPINFO()
|
|
ON_WM_CONTEXTMENU()
|
|
|
|
END_MESSAGE_MAP()
|
|
|
|
CIPAddressDialog::CIPAddressDialog (LPWSTR szIPAddress, LPWSTR szSubnetMask)
|
|
: CDialog(CIPAddressDialog::IDD)
|
|
{
|
|
ZeroMemory(&address, sizeof(address));
|
|
|
|
/* If an initial IP address was specified, copy it into local storage. */
|
|
if (szIPAddress)
|
|
wcsncpy(address.IpAddress, szIPAddress, WLBS_MAX_CL_IP_ADDR);
|
|
|
|
/* If an initial subnet mask was specified, copy it into local storage. */
|
|
if (szSubnetMask)
|
|
wcsncpy(address.SubnetMask, szSubnetMask, WLBS_MAX_CL_NET_MASK);
|
|
}
|
|
|
|
CIPAddressDialog::~CIPAddressDialog ()
|
|
{
|
|
|
|
}
|
|
|
|
void CIPAddressDialog::DoDataExchange( CDataExchange* pDX )
|
|
{
|
|
CDialog::DoDataExchange(pDX);
|
|
|
|
DDX_Control(pDX, IDC_EDIT_IP_ADDRESS, IPAddress);
|
|
DDX_Control(pDX, IDC_EDIT_SUBNET_MASK, SubnetMask);
|
|
}
|
|
|
|
BOOL CIPAddressDialog::OnHelpInfo (HELPINFO* helpInfo )
|
|
{
|
|
if( helpInfo->iContextType == HELPINFO_WINDOW )
|
|
{
|
|
::WinHelp( static_cast<HWND> ( helpInfo->hItemHandle ),
|
|
CVY_CTXT_HELP_FILE,
|
|
HELP_WM_HELP,
|
|
(ULONG_PTR ) s_HelpIDs);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void CIPAddressDialog::OnContextMenu( CWnd* pWnd, CPoint point )
|
|
{
|
|
::WinHelp( m_hWnd,
|
|
CVY_CTXT_HELP_FILE,
|
|
HELP_CONTEXTMENU,
|
|
(ULONG_PTR ) s_HelpIDs);
|
|
}
|
|
|
|
BOOL CIPAddressDialog::OnInitDialog ()
|
|
{
|
|
/* Call the base class initialize method. */
|
|
BOOL fRet = CDialog::OnInitDialog();
|
|
|
|
if (fRet)
|
|
{
|
|
/* Set the valid ranges on each field of the IP address. */
|
|
IPAddress.SetFieldRange(0, 1, 223);
|
|
IPAddress.SetFieldRange(1, 0, 255);
|
|
IPAddress.SetFieldRange(2, 0, 255);
|
|
IPAddress.SetFieldRange(3, 0, 255);
|
|
|
|
/* Set the valid ranges on each field of the subnet mask. */
|
|
SubnetMask.SetFieldRange(0, 0, 255);
|
|
SubnetMask.SetFieldRange(1, 0, 255);
|
|
SubnetMask.SetFieldRange(2, 0, 255);
|
|
SubnetMask.SetFieldRange(3, 0, 255);
|
|
|
|
/* If the IP address is blank, clear the dialog; otherwise, convert
|
|
the string to an IP address DWORD and fill in the dialog. */
|
|
if (!lstrlen(address.IpAddress))
|
|
IPAddress.ClearAddress();
|
|
else
|
|
IPAddress.SetAddress(WideStringToIPAddress(address.IpAddress));
|
|
|
|
/* If the subnet mask is blank, clear the dialog; otherwise, convert
|
|
the string to an IP address DWORD and fill in the dialog. */
|
|
if (!lstrlen(address.SubnetMask))
|
|
SubnetMask.ClearAddress();
|
|
else
|
|
SubnetMask.SetAddress(WideStringToIPAddress(address.SubnetMask));
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
|
|
/*
|
|
* Method: OnEditSubnetMask
|
|
* Description: This method is invoked when the focus changes to the
|
|
* subnet mask control. If the IP address has been already
|
|
* specified and the subnet mask is blank, auto-generate one.
|
|
*/
|
|
void CIPAddressDialog::OnEditSubnetMask ()
|
|
{
|
|
/* Only if the IP address is NOT blank and the subnet mask IS
|
|
blank do we want to auto-generate a subnet mask. */
|
|
if (!IPAddress.IsBlank() && SubnetMask.IsBlank()) {
|
|
WCHAR wszIPAddress[WLBS_MAX_CL_IP_ADDR + 1];
|
|
WCHAR wszSubnetMask[WLBS_MAX_CL_NET_MASK + 1];
|
|
DWORD dwIPAddress;
|
|
|
|
/* Get the IP address from the IP address dialog. */
|
|
IPAddress.GetAddress(dwIPAddress);
|
|
|
|
/* Convert the IP address to a unicode string. */
|
|
IPAddressToWideString(dwIPAddress, wszIPAddress);
|
|
|
|
/* Generate a subnet mask from the class of the given IP address. */
|
|
GenerateSubnetMask(wszIPAddress, ASIZE(wszSubnetMask), wszSubnetMask);
|
|
|
|
/* Fill in the subnet mask dialog with the generated subnet mask. */
|
|
SubnetMask.SetAddress(WideStringToIPAddress(wszSubnetMask));
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Method: On OK
|
|
* Description: Called when the user presses OK. If the user presses
|
|
* Cancel, no method is called and changes are lost.
|
|
*/
|
|
void CIPAddressDialog::OnOK ()
|
|
{
|
|
DWORD dwIPAddress;
|
|
DWORD dwSubnetMask;
|
|
|
|
if (IPAddress.IsBlank()) {
|
|
/* If the IP address dialog is blank, store an empty
|
|
string; if we actually perform a GetAddress call,
|
|
it will tell us its 0.0.0.0 and we want to be able
|
|
to tell the difference between blank and 0.0.0.0. */
|
|
wcsncpy(address.IpAddress, L"", WLBS_MAX_CL_IP_ADDR);
|
|
|
|
} else {
|
|
/* Otherwise, get the IP address DWORD from the control
|
|
and convert it to a unicode string. */
|
|
IPAddress.GetAddress(dwIPAddress);
|
|
|
|
IPAddressToWideString(dwIPAddress, address.IpAddress);
|
|
|
|
}
|
|
|
|
if (SubnetMask.IsBlank()) {
|
|
/* If the subnet mask dialog is blank, store an empty
|
|
string; if we actually perform a GetAddress call,
|
|
it will tell us its 0.0.0.0 and we want to be able
|
|
to tell the difference between blank and 0.0.0.0. */
|
|
wcsncpy(address.SubnetMask, L"", WLBS_MAX_CL_NET_MASK);
|
|
|
|
} else {
|
|
/* Otherwise, get the IP address DWORD from the control
|
|
and convert it to a unicode string. */
|
|
SubnetMask.GetAddress(dwSubnetMask);
|
|
|
|
IPAddressToWideString(dwSubnetMask, address.SubnetMask);
|
|
|
|
}
|
|
|
|
/* Check the validity of the IP address and subnet mask. If
|
|
one or both is invalid, throw up an error and don't close
|
|
the dialog. */
|
|
if (!IsValid(address.IpAddress, address.SubnetMask)) {
|
|
::MessageBox(
|
|
NULL,
|
|
GETRESOURCEIDSTRING(IDS_INVALID_IP_OR_SUBNET),
|
|
GETRESOURCEIDSTRING(IDS_INVALID_INFORMATION),
|
|
MB_ICONINFORMATION | MB_OK
|
|
);
|
|
|
|
/* If the IP address is blank, clear the dialog; otherwise, convert
|
|
the string to an IP address DWORD and fill in the dialog. */
|
|
if (!lstrlen(address.IpAddress))
|
|
IPAddress.ClearAddress();
|
|
else
|
|
IPAddress.SetAddress(WideStringToIPAddress(address.IpAddress));
|
|
|
|
/* If the subnet mask is blank, clear the dialog; otherwise, convert
|
|
the string to an IP address DWORD and fill in the dialog. */
|
|
if (!lstrlen(address.SubnetMask))
|
|
SubnetMask.ClearAddress();
|
|
else
|
|
SubnetMask.SetAddress(WideStringToIPAddress(address.SubnetMask));
|
|
|
|
return;
|
|
}
|
|
|
|
EndDialog(IDOK);
|
|
}
|
|
|
|
/*
|
|
* Method:
|
|
* Description:
|
|
*/
|
|
DWORD CIPAddressDialog::WideStringToIPAddress (const WCHAR* wszIPAddress)
|
|
{
|
|
CHAR szIPAddress[MAXIPSTRLEN + 1];
|
|
DWORD dwIPAddress;
|
|
DWORD dwTemp;
|
|
BYTE * pTemp = (BYTE *)&dwTemp;
|
|
BYTE * pIPAddress = (BYTE *)&dwIPAddress;
|
|
|
|
if (!wszIPAddress) return 0;
|
|
|
|
WideCharToMultiByte(CP_ACP, 0, wszIPAddress, -1, szIPAddress, sizeof(szIPAddress), NULL, NULL);
|
|
|
|
dwTemp = inet_addr(szIPAddress);
|
|
|
|
pIPAddress[0] = pTemp[3];
|
|
pIPAddress[1] = pTemp[2];
|
|
pIPAddress[2] = pTemp[1];
|
|
pIPAddress[3] = pTemp[0];
|
|
|
|
return dwIPAddress;
|
|
}
|
|
|
|
/*
|
|
* Method:
|
|
* Description:
|
|
*/
|
|
void CIPAddressDialog::IPAddressToWideString (DWORD dwIPAddress, LPWSTR wszIPAddress)
|
|
{
|
|
CHAR * szIPAddress;
|
|
DWORD dwTemp;
|
|
BYTE * pTemp = (BYTE *)&dwTemp;
|
|
const BYTE * pIPAddress = (const BYTE *)&dwIPAddress;
|
|
|
|
if (!wszIPAddress) return;
|
|
|
|
pTemp[0] = pIPAddress[3];
|
|
pTemp[1] = pIPAddress[2];
|
|
pTemp[2] = pIPAddress[1];
|
|
pTemp[3] = pIPAddress[0];
|
|
|
|
szIPAddress = inet_ntoa(*(struct in_addr *)&dwTemp);
|
|
|
|
if (!szIPAddress)
|
|
{
|
|
wcsncpy(wszIPAddress, L"", MAXIPSTRLEN);
|
|
return;
|
|
}
|
|
|
|
MultiByteToWideChar(CP_ACP, 0, szIPAddress, -1, wszIPAddress, MAXIPSTRLEN + 1);
|
|
}
|
|
|
|
/*
|
|
* Method:
|
|
* Description:
|
|
*/
|
|
void CIPAddressDialog::GetIPAddressOctets (LPWSTR wszIPAddress, DWORD dwIPAddress[4])
|
|
{
|
|
DWORD dwIP = WideStringToIPAddress(wszIPAddress);
|
|
const BYTE * bp = (const BYTE *)&dwIP;
|
|
|
|
dwIPAddress[3] = (DWORD)bp[0];
|
|
dwIPAddress[2] = (DWORD)bp[1];
|
|
dwIPAddress[1] = (DWORD)bp[2];
|
|
dwIPAddress[0] = (DWORD)bp[3];
|
|
}
|
|
|
|
/*
|
|
* Method:
|
|
* Description:
|
|
*/
|
|
BOOL CIPAddressDialog::IsValid (LPWSTR wszIPAddress, LPWSTR wszSubnetMask)
|
|
{
|
|
BOOL fNoError = TRUE;
|
|
|
|
DWORD dwAddr = WideStringToIPAddress(wszIPAddress);
|
|
DWORD dwMask = WideStringToIPAddress(wszSubnetMask);
|
|
|
|
if (!IsContiguousSubnetMask(wszSubnetMask))
|
|
return FALSE;
|
|
|
|
if (( (dwMask | dwAddr) == 0xFFFFFFFF) // Is the host ID all 1's ?
|
|
|| (((~dwMask) & dwAddr) == 0) // Is the host ID all 0's ?
|
|
|| ( (dwMask & dwAddr) == 0)) // Is the network ID all 0's ?
|
|
return FALSE;
|
|
|
|
DWORD ardwNetID[4];
|
|
DWORD ardwHostID[4];
|
|
DWORD ardwIp[4];
|
|
DWORD ardwMask[4];
|
|
|
|
GetIPAddressOctets(wszIPAddress, ardwIp);
|
|
GetIPAddressOctets(wszSubnetMask, ardwMask);
|
|
|
|
INT nFirstByte = ardwIp[0] & 0xFF;
|
|
|
|
// setup Net ID
|
|
ardwNetID[0] = ardwIp[0] & ardwMask[0] & 0xFF;
|
|
ardwNetID[1] = ardwIp[1] & ardwMask[1] & 0xFF;
|
|
ardwNetID[2] = ardwIp[2] & ardwMask[2] & 0xFF;
|
|
ardwNetID[3] = ardwIp[3] & ardwMask[3] & 0xFF;
|
|
|
|
// setup Host ID
|
|
ardwHostID[0] = ardwIp[0] & (~(ardwMask[0]) & 0xFF);
|
|
ardwHostID[1] = ardwIp[1] & (~(ardwMask[1]) & 0xFF);
|
|
ardwHostID[2] = ardwIp[2] & (~(ardwMask[2]) & 0xFF);
|
|
ardwHostID[3] = ardwIp[3] & (~(ardwMask[3]) & 0xFF);
|
|
|
|
// check each case
|
|
if( ((nFirstByte & 0xF0) == 0xE0) || // Class D
|
|
((nFirstByte & 0xF0) == 0xF0) || // Class E
|
|
(ardwNetID[0] == 127) || // NetID cannot be 127...
|
|
((ardwNetID[0] == 0) && // netid cannot be 0.0.0.0
|
|
(ardwNetID[1] == 0) &&
|
|
(ardwNetID[2] == 0) &&
|
|
(ardwNetID[3] == 0)) ||
|
|
// netid cannot be equal to sub-net mask
|
|
((ardwNetID[0] == ardwMask[0]) &&
|
|
(ardwNetID[1] == ardwMask[1]) &&
|
|
(ardwNetID[2] == ardwMask[2]) &&
|
|
(ardwNetID[3] == ardwMask[3])) ||
|
|
// hostid cannot be 0.0.0.0
|
|
((ardwHostID[0] == 0) &&
|
|
(ardwHostID[1] == 0) &&
|
|
(ardwHostID[2] == 0) &&
|
|
(ardwHostID[3] == 0)) ||
|
|
// hostid cannot be 255.255.255.255
|
|
((ardwHostID[0] == 0xFF) &&
|
|
(ardwHostID[1] == 0xFF) &&
|
|
(ardwHostID[2] == 0xFF) &&
|
|
(ardwHostID[3] == 0xFF)) ||
|
|
// test for all 255
|
|
((ardwIp[0] == 0xFF) &&
|
|
(ardwIp[1] == 0xFF) &&
|
|
(ardwIp[2] == 0xFF) &&
|
|
(ardwIp[3] == 0xFF)))
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
* Method:
|
|
* Description:
|
|
*/
|
|
BOOL CIPAddressDialog::IsContiguousSubnetMask (LPWSTR wszSubnetMask)
|
|
{
|
|
DWORD dwSubnetMask[4];
|
|
|
|
GetIPAddressOctets(wszSubnetMask, dwSubnetMask);
|
|
|
|
DWORD dwMask = (dwSubnetMask[0] << 24) + (dwSubnetMask[1] << 16)
|
|
+ (dwSubnetMask[2] << 8) + dwSubnetMask[3];
|
|
|
|
DWORD i, dwContiguousMask;
|
|
|
|
// Find out where the first '1' is in binary going right to left
|
|
dwContiguousMask = 0;
|
|
|
|
for (i = 0; i < sizeof(dwMask)*8; i++) {
|
|
dwContiguousMask |= 1 << i;
|
|
|
|
if (dwContiguousMask & dwMask)
|
|
break;
|
|
}
|
|
|
|
// At this point, dwContiguousMask is 000...0111... If we inverse it,
|
|
// we get a mask that can be or'd with dwMask to fill in all of
|
|
// the holes.
|
|
dwContiguousMask = dwMask | ~dwContiguousMask;
|
|
|
|
// If the new mask is different, correct it here
|
|
if (dwMask != dwContiguousMask)
|
|
return FALSE;
|
|
else
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
* Method:
|
|
* Description:
|
|
*/
|
|
BOOL CIPAddressDialog::GenerateSubnetMask (LPWSTR wszIPAddress,
|
|
UINT cchSubnetMask,
|
|
LPWSTR wszSubnetMask
|
|
)
|
|
{
|
|
DWORD b[4];
|
|
|
|
if (swscanf(wszIPAddress, L"%d.%d.%d.%d", b, b+1, b+2, b+3) != EOF)
|
|
{
|
|
if ((b[0] >= 1) && (b[0] <= 126)) {
|
|
b[0] = 255;
|
|
b[1] = 0;
|
|
b[2] = 0;
|
|
b[3] = 0;
|
|
} else if ((b[0] >= 128) && (b[0] <= 191)) {
|
|
b[0] = 255;
|
|
b[1] = 255;
|
|
b[2] = 0;
|
|
b[3] = 0;
|
|
} else if ((b[0] >= 192) && (b[0] <= 223)) {
|
|
b[0] = 255;
|
|
b[1] = 255;
|
|
b[2] = 255;
|
|
b[3] = 0;
|
|
} else {
|
|
b[0] = 0;
|
|
b[1] = 0;
|
|
b[2] = 0;
|
|
b[3] = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
b[0] = 0;
|
|
b[1] = 0;
|
|
b[2] = 0;
|
|
b[3] = 0;
|
|
}
|
|
|
|
StringCchPrintf(
|
|
wszSubnetMask,
|
|
cchSubnetMask,
|
|
L"%d.%d.%d.%d", b[0], b[1], b[2], b[3]);
|
|
|
|
return((b[0] + b[1] + b[2] + b[3]) > 0);
|
|
}
|