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.
1469 lines
42 KiB
1469 lines
42 KiB
//***************************************************************************
|
|
//
|
|
// CONNECT.CPP
|
|
//
|
|
// Module: NLB Manager
|
|
//
|
|
// Purpose: Implements ConnectDialog, which is a dialog for connecting
|
|
// to a host, extracting and displaying its list of adapters.
|
|
//
|
|
// Copyright (c)2001 Microsoft Corporation, All Rights Reserved
|
|
//
|
|
// History:
|
|
//
|
|
// 07/30/01 JosephJ Created
|
|
//
|
|
//***************************************************************************
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
#include "private.h"
|
|
#include "connect.h"
|
|
#include "connect.tmh"
|
|
|
|
|
|
// BEGIN_MESSAGE_MAP( ConnectDialog, CDialog )
|
|
|
|
BEGIN_MESSAGE_MAP( ConnectDialog, CPropertyPage )
|
|
|
|
ON_BN_CLICKED(IDC_BUTTON_CONNECT, OnButtonConnect)
|
|
ON_WM_HELPINFO()
|
|
ON_WM_CONTEXTMENU()
|
|
ON_NOTIFY( LVN_ITEMCHANGED, IDC_LIST_INTERFACES, OnSelchanged )
|
|
ON_EN_UPDATE(IDC_EDIT_HOSTADDRESS,OnUpdateEditHostAddress)
|
|
|
|
//
|
|
// Other options...
|
|
//
|
|
// ON_EN_SETFOCUS(IDC_EDIT_HOSTADDRESS,OnSetFocusEditHostAddress)
|
|
// ON_WM_ACTIVATE()
|
|
// ON_NOTIFY( NM_DBLCLK, IDC_LIST_INTERFACES, OnDoubleClick )
|
|
// ON_NOTIFY( LVN_COLUMNCLICK, IDC_LIST_INTERFACES, OnColumnClick )
|
|
//
|
|
|
|
END_MESSAGE_MAP()
|
|
|
|
|
|
//
|
|
// Static help-id maps
|
|
//
|
|
|
|
DWORD
|
|
ConnectDialog::s_HelpIDs[] =
|
|
{
|
|
IDC_TEXT_HOSTADDRESS, IDC_EDIT_HOSTADDRESS,
|
|
IDC_EDIT_HOSTADDRESS, IDC_EDIT_HOSTADDRESS,
|
|
IDC_BUTTON_CONNECT, IDC_BUTTON_CONNECT,
|
|
IDC_GROUP_CONNECTION_STATUS, IDC_GROUP_CONNECTION_STATUS,
|
|
IDC_TEXT_CONNECTION_STATUS, IDC_TEXT_CONNECTION_STATUS,
|
|
IDC_TEXT_INTERFACES, IDC_LIST_INTERFACES,
|
|
IDC_LIST_INTERFACES, IDC_LIST_INTERFACES,
|
|
0, 0
|
|
};
|
|
|
|
DWORD
|
|
ConnectDialog::s_ExistingClusterHelpIDs[] =
|
|
{
|
|
IDC_TEXT_HOSTADDRESS, IDC_EDIT_HOSTADDRESSEX,
|
|
IDC_EDIT_HOSTADDRESS, IDC_EDIT_HOSTADDRESSEX,
|
|
IDC_BUTTON_CONNECT, IDC_BUTTON_CONNECTEX,
|
|
IDC_GROUP_CONNECTION_STATUS, IDC_GROUP_CONNECTION_STATUS,
|
|
IDC_TEXT_CONNECTION_STATUS, IDC_TEXT_CONNECTION_STATUS,
|
|
IDC_TEXT_INTERFACES, IDC_LIST_INTERFACESEX,
|
|
IDC_LIST_INTERFACES, IDC_LIST_INTERFACESEX,
|
|
0, 0
|
|
};
|
|
|
|
|
|
VOID zap_slash(LPWSTR sz) // Look for a the first '/' and set it to zero.
|
|
{
|
|
sz = wcschr(sz, '/');
|
|
if (sz!=NULL) *sz=0;
|
|
}
|
|
|
|
ConnectDialog::ConnectDialog(
|
|
CPropertySheet *psh,
|
|
Document *pDocument,
|
|
NLB_EXTENDED_CLUSTER_CONFIGURATION *pNlbCfg,
|
|
ENGINEHANDLE *pehInterface, // IN OUT
|
|
DlgType type,
|
|
CWnd* parent
|
|
)
|
|
:
|
|
// CDialog( IDD, parent )
|
|
CPropertyPage(IDD),
|
|
m_type(type),
|
|
m_fOK(FALSE),
|
|
m_pshOwner(psh),
|
|
m_pDocument(pDocument),
|
|
m_fInterfaceSelected(FALSE),
|
|
m_iInterfaceListItem(0),
|
|
m_pehSelectedInterfaceId(pehInterface),
|
|
m_fSelectedInterfaceIsInCluster(FALSE),
|
|
m_pNlbCfg(pNlbCfg),
|
|
m_ehHostId(NULL)
|
|
{
|
|
*m_pehSelectedInterfaceId = NULL;
|
|
}
|
|
|
|
void
|
|
ConnectDialog::DoDataExchange( CDataExchange* pDX )
|
|
{
|
|
// CDialog::DoDataExchange(pDX);
|
|
CPropertyPage::DoDataExchange(pDX);
|
|
|
|
DDX_Control(pDX, IDC_LIST_INTERFACES, interfaceList);
|
|
DDX_Control(pDX, IDC_TEXT_CONNECTION_STATUS, connectionStatus);
|
|
DDX_Control(pDX, IDC_TEXT_INTERFACES, listHeading);
|
|
DDX_Control(pDX, IDC_EDIT_HOSTADDRESS, hostAddress);
|
|
|
|
//
|
|
// 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
|
|
ConnectDialog::OnInitDialog()
|
|
{
|
|
// BOOL fRet = CDialog::OnInitDialog();
|
|
BOOL fRet = CPropertyPage::OnInitDialog();
|
|
_bstr_t bstrDescription;
|
|
_bstr_t bstrListText;
|
|
|
|
m_fOK = FALSE;
|
|
|
|
switch(m_type)
|
|
{
|
|
case DLGTYPE_NEW_CLUSTER:
|
|
bstrDescription = GETRESOURCEIDSTRING(IDS_CONNECT_NEW_HINT);
|
|
bstrListText = GETRESOURCEIDSTRING(IDS_CONNECT_NEW_LIST_TXT);
|
|
break;
|
|
|
|
case DLGTYPE_EXISTING_CLUSTER:
|
|
bstrDescription = GETRESOURCEIDSTRING(IDS_CONNECT_EXISTING_HINT);
|
|
bstrListText = GETRESOURCEIDSTRING(IDS_CONNECT_EXISTING_LIST_TXT);
|
|
break;
|
|
|
|
case DLGTYPE_ADD_HOST:
|
|
bstrDescription = GETRESOURCEIDSTRING(IDS_CONNECT_ADD_HOST_HINT);
|
|
bstrListText = GETRESOURCEIDSTRING(IDS_CONNECT_ADD_HOST_LIST_TXT);
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Initialize the caption and discription based on the type of
|
|
// dialog.
|
|
//
|
|
{
|
|
CWnd *pItem = GetDlgItem(IDC_TEXT_CONNECT_DESCRIPTION);
|
|
pItem->SetWindowText(bstrDescription);
|
|
pItem = GetDlgItem(IDC_TEXT_INTERFACES);
|
|
pItem->SetWindowText(bstrListText);
|
|
}
|
|
|
|
// Initialize the list control
|
|
mfn_InitializeListView();
|
|
|
|
// interfaceList.SetCurSel( 0 );
|
|
// ::EnableWindow(::GetDlgItem(m_hWnd, IDC_EDIT_HOSTADDRESS), TRUE );
|
|
// ::EnableWindow(::GetDlgItem(m_hWnd, IDC_LIST_INTERFACES), TRUE );
|
|
|
|
//
|
|
// The "Connect" button starts out disabled. It is only enabled
|
|
// when the uers types non-whitespace text in the host address
|
|
// edit control.
|
|
//
|
|
::EnableWindow (GetDlgItem(IDC_BUTTON_CONNECT)->m_hWnd, FALSE);
|
|
return fRet;
|
|
}
|
|
|
|
|
|
BOOL
|
|
ConnectDialog::OnHelpInfo (HELPINFO* helpInfo )
|
|
{
|
|
if( helpInfo->iContextType == HELPINFO_WINDOW )
|
|
{
|
|
//
|
|
// We choose the context-senstive map appropriate to the
|
|
// type of dialog (m_type).
|
|
//
|
|
|
|
ULONG_PTR pHelpIds = (ULONG_PTR) s_HelpIDs;
|
|
BOOL fExisting = (m_type == DLGTYPE_EXISTING_CLUSTER);
|
|
|
|
if (fExisting)
|
|
{
|
|
pHelpIds = (ULONG_PTR) s_ExistingClusterHelpIDs;
|
|
}
|
|
|
|
|
|
::WinHelp( static_cast<HWND> ( helpInfo->hItemHandle ),
|
|
CVY_CTXT_HELP_FILE,
|
|
HELP_WM_HELP,
|
|
(ULONG_PTR ) pHelpIds);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
void
|
|
ConnectDialog::OnContextMenu( CWnd* pWnd, CPoint point )
|
|
{
|
|
::WinHelp( m_hWnd,
|
|
CVY_CTXT_HELP_FILE,
|
|
HELP_CONTEXTMENU,
|
|
(ULONG_PTR ) s_HelpIDs);
|
|
}
|
|
|
|
void
|
|
ConnectDialog::mfn_InitializeListView(void)
|
|
//
|
|
// Set the columns on the list box based on the type of dialog
|
|
//
|
|
{
|
|
BOOL fExisting = (m_type == DLGTYPE_EXISTING_CLUSTER);
|
|
|
|
RECT rect;
|
|
INT colWidth;
|
|
|
|
interfaceList.GetClientRect(&rect);
|
|
|
|
colWidth = (rect.right - rect.left)/4;
|
|
|
|
if (fExisting)
|
|
{
|
|
//
|
|
// The interface list is that of interfaces already bound to NLB.
|
|
// we display the cluster dnsname and ip first, then adapter name.
|
|
//
|
|
interfaceList.InsertColumn(
|
|
0,
|
|
GETRESOURCEIDSTRING( IDS_HEADER_IFLIST_CLUSTERNAME),
|
|
LVCFMT_LEFT,
|
|
colWidth);
|
|
interfaceList.InsertColumn(
|
|
1,
|
|
GETRESOURCEIDSTRING( IDS_HEADER_IFLIST_CLUSTERIP),
|
|
LVCFMT_LEFT,
|
|
colWidth);
|
|
interfaceList.InsertColumn(
|
|
2,
|
|
GETRESOURCEIDSTRING( IDS_HEADER_IFLIST_IFNAME),
|
|
LVCFMT_LEFT,
|
|
colWidth * 2);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// The interface list is that of interfaces NOT bound to NLB.
|
|
// We display the current IP address first, then adapter name.
|
|
//
|
|
interfaceList.InsertColumn(
|
|
0,
|
|
GETRESOURCEIDSTRING( IDS_HEADER_IFLIST_IFNAME),
|
|
LVCFMT_LEFT,
|
|
colWidth * 2);
|
|
interfaceList.InsertColumn(
|
|
1,
|
|
GETRESOURCEIDSTRING( IDS_HEADER_IFLIST_IFIP),
|
|
LVCFMT_LEFT,
|
|
colWidth);
|
|
interfaceList.InsertColumn(
|
|
2,
|
|
GETRESOURCEIDSTRING( IDS_HEADER_IFLIST_CLUSTERIP),
|
|
LVCFMT_LEFT,
|
|
colWidth);
|
|
}
|
|
|
|
//
|
|
// Allow entire row to be selected.
|
|
//
|
|
interfaceList.SetExtendedStyle(
|
|
interfaceList.GetExtendedStyle() | LVS_EX_FULLROWSELECT );
|
|
}
|
|
|
|
|
|
void
|
|
ConnectDialog::mfn_InsertBoundInterface(
|
|
ENGINEHANDLE ehInterfaceId,
|
|
LPCWSTR szClusterName,
|
|
LPCWSTR szClusterIp,
|
|
LPCWSTR szInterfaceName
|
|
)
|
|
{
|
|
if (szClusterName == NULL)
|
|
{
|
|
szClusterName = L"";
|
|
}
|
|
if (szClusterIp == NULL)
|
|
{
|
|
szClusterIp = L"";
|
|
}
|
|
if (szInterfaceName == NULL)
|
|
{
|
|
szInterfaceName = L""; // TODO: localize
|
|
}
|
|
int iRet = interfaceList.InsertItem(
|
|
LVIF_TEXT | LVIF_PARAM, // nMask
|
|
0, // nItem,
|
|
szClusterName, // lpszItem
|
|
0, // nState (unused)
|
|
0, // nStateMask (unused)
|
|
0, // nImage (unused)
|
|
(LPARAM) ehInterfaceId // lParam
|
|
);
|
|
// interfaceList.InsertItem(0, szClusterName);
|
|
interfaceList.SetItem(
|
|
0, // nItem
|
|
1,// nSubItem
|
|
LVIF_TEXT, // nMask
|
|
szClusterIp, // lpszItem
|
|
0, // nImage
|
|
0, // nState
|
|
0, // nStateMask
|
|
0 // lParam
|
|
);
|
|
interfaceList.SetItem(
|
|
0, // nItem
|
|
2,// nSubItem
|
|
LVIF_TEXT, // nMask
|
|
szInterfaceName, // lpszItem
|
|
0, // nImage
|
|
0, // nState
|
|
0, // nStateMask
|
|
0 // lParam
|
|
);
|
|
|
|
}
|
|
|
|
void
|
|
ConnectDialog::mfn_InsertInterface(
|
|
ENGINEHANDLE ehInterfaceId,
|
|
LPCWSTR szInterfaceIp,
|
|
LPCWSTR szInterfaceName,
|
|
LPCWSTR szClusterIp
|
|
)
|
|
{
|
|
if (szInterfaceIp == NULL)
|
|
{
|
|
szInterfaceIp = L"";
|
|
}
|
|
if (szInterfaceName == NULL)
|
|
{
|
|
szInterfaceName = L""; // TODO: localize
|
|
}
|
|
if (szClusterIp == NULL)
|
|
{
|
|
szClusterIp = L"";
|
|
}
|
|
|
|
int iRet = interfaceList.InsertItem(
|
|
LVIF_TEXT | LVIF_PARAM, // nMask
|
|
0, // nItem,
|
|
szInterfaceName, // lpszItem
|
|
0, // nState (unused)
|
|
0, // nStateMask (unused)
|
|
0, // nImage (unused)
|
|
(LPARAM) ehInterfaceId // lParam
|
|
);
|
|
// interfaceList.InsertItem(0, szInterfaceIp);
|
|
interfaceList.SetItem(
|
|
0, // nItem
|
|
1,// nSubItem
|
|
LVIF_TEXT, // nMask
|
|
szInterfaceIp, // lpszItem
|
|
0, // nImage
|
|
0, // nState
|
|
0, // nStateMask
|
|
0 // lParam
|
|
);
|
|
// interfaceList.InsertItem(0, szInterfaceIp);
|
|
interfaceList.SetItem(
|
|
0, // nItem
|
|
2,// nSubItem
|
|
LVIF_TEXT, // nMask
|
|
szClusterIp, // lpszItem
|
|
0, // nImage
|
|
0, // nState
|
|
0, // nStateMask
|
|
0 // lParam
|
|
);
|
|
// interfaceList.SetCurSel( 0 );
|
|
|
|
}
|
|
|
|
void ConnectDialog::OnOK()
|
|
{
|
|
// CDialog::OnOK();
|
|
CPropertyPage::OnOK();
|
|
}
|
|
|
|
_bstr_t g_hostName;
|
|
|
|
void ConnectDialog::OnButtonConnect()
|
|
/*
|
|
User has clicked the "Connect" button.
|
|
|
|
1. (For now) If empty string, do nothing. Later we'll disable/enable.
|
|
2. Switch cursor to hourglass, connect, switch back from hourglass.
|
|
*/
|
|
{
|
|
BOOL fExisting = (m_type == DLGTYPE_EXISTING_CLUSTER);
|
|
BOOL fRet;
|
|
#define MAX_HOST_ADDRESS_LENGTH 256
|
|
WCHAR szHostAddress[MAX_HOST_ADDRESS_LENGTH+1];
|
|
ENGINEHANDLE ehHostId;
|
|
CHostSpec hSpec;
|
|
BOOL fNicsAvailable = FALSE;
|
|
NLBERROR err;
|
|
_bstr_t bstrUserName;
|
|
_bstr_t bstrPassword;
|
|
_bstr_t bstrConnectionStatus;
|
|
|
|
//
|
|
// Get the connection string. If empty, we simply return.
|
|
//
|
|
{
|
|
fRet = GetDlgItemText(
|
|
IDC_EDIT_HOSTADDRESS,
|
|
szHostAddress,
|
|
MAX_HOST_ADDRESS_LENGTH
|
|
);
|
|
if (!fRet)
|
|
{
|
|
goto end;
|
|
}
|
|
|
|
//
|
|
// Clean out trailing whitespace..
|
|
//
|
|
{
|
|
LPWSTR sz = (szHostAddress+wcslen(szHostAddress))-1;
|
|
|
|
while (sz >= szHostAddress)
|
|
{
|
|
WCHAR c = *sz;
|
|
if (c == ' ' || c == '\t')
|
|
{
|
|
*sz = 0;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
sz--;
|
|
}
|
|
}
|
|
|
|
if (szHostAddress[0] == 0)
|
|
{
|
|
goto end;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Let's see if we have any record of this connection string -- if so
|
|
// we use that record's username and password as the first guest.
|
|
//
|
|
err = gEngine.LookupConnectionInfo(
|
|
szHostAddress,
|
|
REF bstrUserName,
|
|
REF bstrPassword
|
|
);
|
|
if (NLBFAILED(err))
|
|
{
|
|
//
|
|
// Nope -- let's use default credentials...
|
|
//
|
|
m_pDocument->getDefaultCredentials(REF bstrUserName, REF bstrPassword);
|
|
}
|
|
//
|
|
// Set status
|
|
//
|
|
{
|
|
bstrConnectionStatus = GETRESOURCEIDSTRING(IDS_CONNECT_STATUS_CONNECTING);
|
|
SetDlgItemText(IDC_TEXT_CONNECTION_STATUS, (LPCWSTR) bstrConnectionStatus);
|
|
}
|
|
|
|
//
|
|
// Clear the list of interfaces.
|
|
//
|
|
interfaceList.DeleteAllItems();
|
|
|
|
|
|
//
|
|
// These two buffers must be defined outside the loop below because
|
|
// ConnInfo points to them across multiple iterations.
|
|
// We initialize them to the user-name and password we obtained above...
|
|
//
|
|
WCHAR rgUserName[CREDUI_MAX_USERNAME_LENGTH+1];
|
|
WCHAR rgPassword[MAX_ENCRYPTED_PASSWORD_LENGTH];
|
|
LPCWSTR szName = (LPCWSTR) bstrUserName;
|
|
LPCWSTR szPassword = (LPCWSTR) bstrPassword;
|
|
if (szName == NULL)
|
|
{
|
|
szName = L"";
|
|
}
|
|
if (szPassword == NULL)
|
|
{
|
|
szPassword = L"";
|
|
}
|
|
ARRAYSTRCPY(rgUserName, szName);
|
|
ARRAYSTRCPY(rgPassword, szPassword);
|
|
|
|
while (1)
|
|
{
|
|
WMI_CONNECTION_INFO ConnInfo;
|
|
CLocalLogger logger;
|
|
|
|
ZeroMemory(&ConnInfo, sizeof(ConnInfo));
|
|
ConnInfo.szMachine = szHostAddress;
|
|
|
|
if (*rgUserName == 0)
|
|
{
|
|
// Use default creds ...
|
|
ConnInfo.szUserName = NULL;
|
|
ConnInfo.szPassword = NULL;
|
|
}
|
|
else
|
|
{
|
|
ConnInfo.szUserName = rgUserName;
|
|
ConnInfo.szPassword = rgPassword;
|
|
}
|
|
|
|
//
|
|
// ACTUALLY CONNECT TO THE HOST
|
|
//
|
|
BeginWaitCursor();
|
|
|
|
// TRUE 2nd param says overwrite the connection info for this host
|
|
// if the connect succeeds.
|
|
err = gEngine.ConnectToHost(&ConnInfo, TRUE, REF ehHostId, REF bstrConnectionStatus);
|
|
EndWaitCursor();
|
|
|
|
if (err != NLBERR_ACCESS_DENIED)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// We got an access-denied --
|
|
// Bring ui UI prompting for new username and password.
|
|
//
|
|
_bstr_t bstrCaption = GETRESOURCEIDSTRING(IDS_CONNECT_UNABLE_TO_CONNECT);
|
|
logger.Log(IDS_SPECIFY_MACHINE_CREDS, ConnInfo.szMachine);
|
|
|
|
fRet = PromptForEncryptedCreds(
|
|
m_hWnd,
|
|
(LPCWSTR) bstrCaption,
|
|
logger.GetStringSafe(),
|
|
rgUserName,
|
|
ASIZE(rgUserName),
|
|
rgPassword,
|
|
ASIZE(rgPassword)
|
|
);
|
|
if (!fRet)
|
|
{
|
|
err = NLBERR_CANCELLED;
|
|
break;
|
|
}
|
|
|
|
} // while (1)
|
|
|
|
if (err == NLBERR_OK)
|
|
{
|
|
//
|
|
// Set status
|
|
//
|
|
bstrConnectionStatus = GETRESOURCEIDSTRING(IDS_CONNECT_STATUS_CONNECTED);
|
|
SetDlgItemText(IDC_TEXT_CONNECTION_STATUS, (LPCWSTR) bstrConnectionStatus);
|
|
|
|
//
|
|
// Clear list of all items
|
|
//
|
|
interfaceList.DeleteAllItems();
|
|
|
|
err = gEngine.GetHostSpec(ehHostId, REF hSpec);
|
|
if (NLBFAILED(err))
|
|
{
|
|
goto end;
|
|
}
|
|
|
|
//
|
|
// Extract list of interfaces
|
|
//
|
|
for( int i = 0; i < hSpec.m_ehInterfaceIdList.size(); ++i )
|
|
{
|
|
ENGINEHANDLE ehIID = hSpec.m_ehInterfaceIdList[i];
|
|
CInterfaceSpec iSpec;
|
|
|
|
err = gEngine.GetInterfaceSpec(ehIID, REF iSpec);
|
|
if (err == NLBERR_OK)
|
|
{
|
|
//
|
|
// Get interfaces.
|
|
//
|
|
// szFriendlyName
|
|
// szClusterIp (NULL if nlb not bound)
|
|
// szClusterName (NULL if nlb not bound)
|
|
// szFirstIp (first ip bound to NLB)
|
|
//
|
|
WBEMSTATUS wStat;
|
|
LPWSTR szFriendlyName = NULL;
|
|
LPWSTR szClusterIp = NULL;
|
|
LPWSTR szClusterName = NULL;
|
|
LPWSTR *pszNetworkAddresses = NULL;
|
|
BOOL fNlbBound = FALSE;
|
|
UINT NumAddresses=0;
|
|
LPWSTR szFirstNetworkAddress = NULL;
|
|
|
|
wStat = iSpec.m_NlbCfg.GetFriendlyName(&szFriendlyName);
|
|
if (FAILED(wStat)) szFriendlyName = NULL;
|
|
|
|
wStat = iSpec.m_NlbCfg.GetNetworkAddresses(
|
|
&pszNetworkAddresses,
|
|
&NumAddresses
|
|
);
|
|
|
|
if (FAILED(wStat))
|
|
{
|
|
pszNetworkAddresses = NULL;
|
|
NumAddresses = 0;
|
|
}
|
|
else if (NumAddresses != 0)
|
|
{
|
|
szFirstNetworkAddress = pszNetworkAddresses[0];
|
|
zap_slash(szFirstNetworkAddress); // zap the /
|
|
}
|
|
|
|
if (iSpec.m_NlbCfg.IsNlbBound())
|
|
{
|
|
fNlbBound = TRUE;
|
|
if (iSpec.m_NlbCfg.IsValidNlbConfig())
|
|
{
|
|
wStat = iSpec.m_NlbCfg.GetClusterNetworkAddress(
|
|
&szClusterIp
|
|
);
|
|
if (FAILED(wStat))
|
|
{
|
|
szClusterIp = NULL;
|
|
}
|
|
else if (szClusterIp!=NULL)
|
|
{
|
|
zap_slash(szClusterIp);
|
|
}
|
|
wStat = iSpec.m_NlbCfg.GetClusterName(
|
|
&szClusterName
|
|
);
|
|
if (FAILED(wStat))
|
|
{
|
|
szClusterName = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (fExisting && fNlbBound)
|
|
{
|
|
fNicsAvailable = TRUE;
|
|
mfn_InsertBoundInterface(
|
|
ehIID,
|
|
szClusterName,
|
|
szClusterIp,
|
|
szFriendlyName
|
|
);
|
|
}
|
|
else if (!fExisting)
|
|
{
|
|
fNicsAvailable = TRUE;
|
|
mfn_InsertInterface(
|
|
ehIID,
|
|
szFirstNetworkAddress,
|
|
szFriendlyName,
|
|
szClusterIp
|
|
);
|
|
}
|
|
delete szFriendlyName;
|
|
delete szClusterIp;
|
|
delete szClusterName;
|
|
delete pszNetworkAddresses;
|
|
}
|
|
}
|
|
|
|
if (!fNicsAvailable)
|
|
{
|
|
//
|
|
// There are no NICs on this host on which NLB may be installed.
|
|
//
|
|
if (fExisting)
|
|
{
|
|
MessageBox(
|
|
GETRESOURCEIDSTRING( IDS_CONNECT_NO_NICS_EXISTING_CLUSTER),
|
|
GETRESOURCEIDSTRING( IDS_CONNECT_SELECT_NICS_ERROR ),
|
|
MB_ICONSTOP | MB_OK
|
|
);
|
|
}
|
|
else
|
|
{
|
|
MessageBox(
|
|
GETRESOURCEIDSTRING( IDS_CONNECT_NO_NICS_NEW_CLUSTER ),
|
|
GETRESOURCEIDSTRING( IDS_CONNECT_SELECT_NICS_ERROR ),
|
|
MB_ICONSTOP | MB_OK
|
|
);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
m_ehHostId = ehHostId;
|
|
m_MachineName = hSpec.m_MachineName; // machine name.
|
|
m_fInterfaceSelected = FALSE;
|
|
m_iInterfaceListItem = 0;
|
|
*m_pehSelectedInterfaceId = NULL;
|
|
m_fSelectedInterfaceIsInCluster = FALSE;
|
|
|
|
|
|
if (fExisting)
|
|
{
|
|
//
|
|
// We're asked to pick an existing cluster.
|
|
// Let's select the first interface bound to NLB
|
|
//
|
|
mfn_SelectInterfaceIfAlreadyInCluster(
|
|
NULL
|
|
);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// We're asked to add a host to a cluster.
|
|
//
|
|
// Now we check if an interfaces is already part of
|
|
// the cluster. If so we select it and prevent the user from
|
|
// subsequently changing this selection. Furthermore, we use
|
|
// the host-specific settings that already exist on that
|
|
// interface.
|
|
//
|
|
mfn_SelectInterfaceIfAlreadyInCluster(
|
|
m_pNlbCfg->NlbParams.cl_ip_addr
|
|
);
|
|
|
|
//
|
|
// Let's apply the selected interface's information.
|
|
//
|
|
mfn_ApplySelectedInterfaceConfiguration();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Error connecting.
|
|
//
|
|
LPCWSTR szErr = (LPCWSTR)bstrConnectionStatus;
|
|
if (szErr == NULL)
|
|
{
|
|
szErr = L"";
|
|
}
|
|
|
|
SetDlgItemText(IDC_TEXT_CONNECTION_STATUS, szErr);
|
|
}
|
|
|
|
end:
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void ConnectDialog::OnSelchanged(NMHDR * pNotifyStruct, LRESULT * result )
|
|
/*
|
|
A listbox item has been selected.
|
|
*/
|
|
{
|
|
POSITION pos = interfaceList.GetFirstSelectedItemPosition();
|
|
UINT WizardFlags = 0;
|
|
int index = -1;
|
|
if( pos != NULL )
|
|
{
|
|
index = interfaceList.GetNextSelectedItem( pos );
|
|
}
|
|
|
|
if (m_type == DLGTYPE_NEW_CLUSTER)
|
|
{
|
|
//
|
|
// We're not the first, so we enable the back button.
|
|
//
|
|
WizardFlags = PSWIZB_BACK;
|
|
}
|
|
|
|
|
|
if (m_fInterfaceSelected && index == m_iInterfaceListItem)
|
|
{
|
|
//
|
|
// No change in selection; Nothing to do..
|
|
// In fact we do NOT want to change the settings because the user
|
|
// may have made some host-specific changes like change the
|
|
// dedicated IP.
|
|
//
|
|
goto end;
|
|
}
|
|
|
|
if (m_fSelectedInterfaceIsInCluster)
|
|
{
|
|
BOOL fRet = FALSE;
|
|
//
|
|
// we don't allow a change in selection -- move back to
|
|
// selecting the cluster ip.
|
|
fRet = interfaceList.SetItemState(
|
|
m_iInterfaceListItem,
|
|
LVIS_FOCUSED | LVIS_SELECTED, // nState
|
|
LVIS_FOCUSED | LVIS_SELECTED // nMask
|
|
);
|
|
|
|
if (fRet)
|
|
{
|
|
goto end;
|
|
}
|
|
}
|
|
|
|
//
|
|
// We are getting here ONLY if (a) there has been a change in the selection
|
|
// and (b) the selected interface is NOT already in the cluster.
|
|
// We'll set the dedicated ip and subnet mask to be the first
|
|
// address/subnet bound to the adapter.
|
|
//
|
|
// If adapter is configured for DHCP, we leave the dedicated IP field
|
|
// blank.
|
|
//
|
|
|
|
if (index != -1)
|
|
{
|
|
|
|
//
|
|
// Update m_pNlbCfg appropriately...
|
|
//
|
|
ENGINEHANDLE ehIID = NULL;
|
|
|
|
ehIID = (ENGINEHANDLE) interfaceList.GetItemData(index);
|
|
|
|
if (ehIID == NULL)
|
|
{
|
|
TRACE_CRIT("%!FUNC! could not get ehIID for index %lu", index);
|
|
goto end;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Update the saved-away "selected interface" ID.
|
|
//
|
|
ENGINEHANDLE ehOldId = *m_pehSelectedInterfaceId;
|
|
*m_pehSelectedInterfaceId = ehIID;
|
|
m_fInterfaceSelected = TRUE;
|
|
m_iInterfaceListItem = index;
|
|
|
|
|
|
//
|
|
// TODO: duplicate code
|
|
//
|
|
CInterfaceSpec iSpec;
|
|
WBEMSTATUS wStat;
|
|
LPWSTR szFriendlyName = NULL;
|
|
LPWSTR szClusterIp = NULL;
|
|
LPWSTR szClusterName = NULL;
|
|
LPWSTR *pszNetworkAddresses = NULL;
|
|
UINT NumAddresses=0;
|
|
LPWSTR szFirstNetworkAddress = NULL;
|
|
NLBERROR err;
|
|
|
|
err = gEngine.GetInterfaceSpec(ehIID, REF iSpec);
|
|
if (!NLBOK(err))
|
|
{
|
|
TRACE_CRIT("%!FUNC! could not get iSpec for ehSpec 0x%lx", ehIID);
|
|
goto end;
|
|
}
|
|
|
|
wStat = iSpec.m_NlbCfg.GetFriendlyName(&szFriendlyName);
|
|
if (FAILED(wStat)) szFriendlyName = NULL;
|
|
|
|
wStat = iSpec.m_NlbCfg.GetNetworkAddresses(
|
|
&pszNetworkAddresses,
|
|
&NumAddresses
|
|
);
|
|
|
|
if (FAILED(wStat))
|
|
{
|
|
pszNetworkAddresses = NULL;
|
|
NumAddresses = 0;
|
|
}
|
|
else if (NumAddresses != 0)
|
|
{
|
|
szFirstNetworkAddress = pszNetworkAddresses[0];
|
|
}
|
|
|
|
m_pNlbCfg->SetFriendlyName(szFriendlyName);
|
|
|
|
if (iSpec.m_NlbCfg.IsNlbBound())
|
|
{
|
|
if (m_type != DLGTYPE_EXISTING_CLUSTER)
|
|
{
|
|
//
|
|
// The user has selected an interface that is bound with
|
|
// some other IP address -- we should put up a message box
|
|
// here or maybe later, on kill-active.
|
|
//
|
|
}
|
|
}
|
|
|
|
//
|
|
// Set defaults for dedicatedip -- the first network address on
|
|
// the NIC, but ONLY if this address is not a cluster IP address.
|
|
//
|
|
if (szFirstNetworkAddress != NULL)
|
|
{
|
|
LPCWSTR szAddress = szFirstNetworkAddress;
|
|
|
|
WCHAR rgIp[WLBS_MAX_CL_IP_ADDR+1];
|
|
LPCWSTR pSlash = wcsrchr(szAddress, (int) '/');
|
|
|
|
if (pSlash != NULL)
|
|
{
|
|
UINT len = (UINT) (pSlash - szAddress);
|
|
if (len < WLBS_MAX_CL_IP_ADDR)
|
|
{
|
|
CopyMemory(rgIp, szAddress, len*sizeof(WCHAR));
|
|
rgIp[len] = 0;
|
|
szAddress = rgIp;
|
|
}
|
|
}
|
|
|
|
if (!_wcsicmp(m_pNlbCfg->NlbParams.cl_ip_addr, szAddress))
|
|
{
|
|
szFirstNetworkAddress = NULL;
|
|
}
|
|
|
|
if (iSpec.m_NlbCfg.fDHCP)
|
|
{
|
|
//
|
|
// The adapter is currently under DHCP control. We don't
|
|
// want to suggest that we use the current IP address
|
|
// as the static DIP!
|
|
//
|
|
szFirstNetworkAddress = NULL;
|
|
}
|
|
|
|
//
|
|
// TODO -- check also if this address conflicts with the
|
|
// additional VIPS.
|
|
//
|
|
}
|
|
m_pNlbCfg->SetDedicatedNetworkAddress(szFirstNetworkAddress); // NULL ok
|
|
|
|
delete szFriendlyName;
|
|
delete szClusterIp;
|
|
delete szClusterName;
|
|
delete pszNetworkAddresses;
|
|
}
|
|
|
|
if (m_type == DLGTYPE_EXISTING_CLUSTER)
|
|
{
|
|
// we're last page, so enable finish.
|
|
WizardFlags |= PSWIZB_FINISH;
|
|
}
|
|
else
|
|
{
|
|
// we're not the last page, so enable next.
|
|
WizardFlags |= PSWIZB_NEXT;
|
|
}
|
|
}
|
|
|
|
m_pshOwner->SetWizardButtons(WizardFlags);
|
|
|
|
end:
|
|
|
|
return;
|
|
}
|
|
|
|
BOOL
|
|
ConnectDialog::OnSetActive()
|
|
{
|
|
BOOL fRet = CPropertyPage::OnSetActive();
|
|
|
|
if (fRet)
|
|
{
|
|
UINT WizardFlags = 0;
|
|
|
|
if (m_type == DLGTYPE_NEW_CLUSTER)
|
|
{
|
|
WizardFlags |= PSWIZB_BACK; // we're not the first page.
|
|
}
|
|
|
|
if (m_fInterfaceSelected)
|
|
{
|
|
WizardFlags |= PSWIZB_NEXT; // Ok to continue.
|
|
}
|
|
|
|
m_pshOwner->SetWizardButtons(WizardFlags);
|
|
}
|
|
return fRet;
|
|
}
|
|
|
|
|
|
LRESULT ConnectDialog::OnWizardNext()
|
|
{
|
|
LRESULT lRet = 0;
|
|
|
|
TRACE_INFO("%!FUNC! ->");
|
|
|
|
lRet = CPropertyPage::OnWizardNext();
|
|
|
|
if (lRet != 0)
|
|
{
|
|
goto end;
|
|
}
|
|
|
|
if (mfn_ValidateData())
|
|
{
|
|
lRet = 0;
|
|
}
|
|
else
|
|
{
|
|
lRet = -1; // validation failed -- stay in current page.
|
|
}
|
|
|
|
end:
|
|
|
|
TRACE_INFO("%!FUNC! <- returns %lu", lRet);
|
|
return lRet;
|
|
}
|
|
|
|
|
|
void ConnectDialog::OnUpdateEditHostAddress()
|
|
{
|
|
//
|
|
// This gets called when the user has made changes to the connect-to-host
|
|
// edit control.
|
|
//
|
|
|
|
//
|
|
// We get the latest text -- if null or just blanks, we
|
|
// disable the connect window.
|
|
// Else we enable the connect window.
|
|
//
|
|
#define BUF_SIZ 32
|
|
WCHAR rgBuf[BUF_SIZ+1];
|
|
int l = hostAddress.GetWindowText(rgBuf, BUF_SIZ);
|
|
|
|
if (l == 0 || _wcsspnp(rgBuf, L" \t")==NULL)
|
|
{
|
|
//
|
|
// Empty string or entirely whitespace.
|
|
//
|
|
::EnableWindow (GetDlgItem(IDC_BUTTON_CONNECT)->m_hWnd, FALSE);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Non-empty string -- enable button and make it the default.
|
|
//
|
|
::EnableWindow (GetDlgItem(IDC_BUTTON_CONNECT)->m_hWnd, TRUE);
|
|
this->SetDefID(IDC_BUTTON_CONNECT);
|
|
}
|
|
|
|
|
|
}
|
|
|
|
void
|
|
ConnectDialog::mfn_SelectInterfaceIfAlreadyInCluster(LPCWSTR szClusterIp)
|
|
/*
|
|
Check the list of interfaces to see if there exists an interface
|
|
which is is already part of the cluster -- i.e., it is bound and it's
|
|
cluster ip matches the one in m_pNlbCfg.
|
|
|
|
If so, we select it, and furthermore, prevent the user from selecting
|
|
any other interface.
|
|
|
|
*/
|
|
{
|
|
ENGINEHANDLE ehInterfaceId = NULL;
|
|
NLBERROR nerr;
|
|
UINT NumFound = 0;
|
|
nerr = gEngine.FindInterfaceOnHostByClusterIp(
|
|
m_ehHostId,
|
|
//m_pNlbCfg->NlbParams.cl_ip_addr,
|
|
szClusterIp,
|
|
REF ehInterfaceId,
|
|
REF NumFound
|
|
);
|
|
if (!NLBOK(nerr))
|
|
{
|
|
// not found or bad host id or some other err -- we don't care which.
|
|
goto end;
|
|
}
|
|
|
|
//
|
|
// Find the list item with this ehInterfaceId.
|
|
//
|
|
{
|
|
LVFINDINFO Info;
|
|
int nItem;
|
|
ZeroMemory(&Info, sizeof(Info));
|
|
Info.flags = LVFI_PARAM;
|
|
Info.lParam = ehInterfaceId;
|
|
|
|
nItem = interfaceList.FindItem(&Info);
|
|
|
|
if (nItem != -1)
|
|
{
|
|
BOOL fRet;
|
|
UINT WizardFlags = 0;
|
|
|
|
//
|
|
// Found it! -- select it and use it's host-specific information
|
|
//
|
|
m_fInterfaceSelected = TRUE;
|
|
m_iInterfaceListItem = nItem;
|
|
*m_pehSelectedInterfaceId = ehInterfaceId;
|
|
if (NumFound == 1)
|
|
{
|
|
m_fSelectedInterfaceIsInCluster = TRUE;
|
|
}
|
|
fRet = interfaceList.SetItemState(
|
|
nItem,
|
|
LVIS_FOCUSED | LVIS_SELECTED, // nState
|
|
LVIS_FOCUSED | LVIS_SELECTED // nMask
|
|
);
|
|
|
|
if (m_type == DLGTYPE_NEW_CLUSTER)
|
|
{
|
|
WizardFlags |= PSWIZB_BACK; // we're not the first page.
|
|
}
|
|
|
|
if (m_type == DLGTYPE_EXISTING_CLUSTER)
|
|
{
|
|
WizardFlags |= PSWIZB_FINISH;
|
|
}
|
|
else
|
|
{
|
|
WizardFlags |= PSWIZB_NEXT;
|
|
}
|
|
// TODO: consider adding finish in add-host case here.
|
|
|
|
m_pshOwner->SetWizardButtons(WizardFlags);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Go through and set all other list items to have a gray background.
|
|
//
|
|
|
|
end:
|
|
|
|
return;
|
|
}
|
|
|
|
void
|
|
ConnectDialog::mfn_ApplySelectedInterfaceConfiguration(void)
|
|
{
|
|
ENGINEHANDLE ehIID = *m_pehSelectedInterfaceId;
|
|
CInterfaceSpec iSpec;
|
|
WBEMSTATUS wStat;
|
|
BOOL fNlbBound = FALSE;
|
|
NLBERROR err;
|
|
NLB_EXTENDED_CLUSTER_CONFIGURATION TmpConfig;
|
|
|
|
if (!m_fSelectedInterfaceIsInCluster) goto end;
|
|
|
|
err = gEngine.GetInterfaceSpec(ehIID, REF iSpec);
|
|
if (!NLBOK(err))
|
|
{
|
|
TRACE_CRIT("%!FUNC! could not get iSpec for ehSpec 0x%lx", ehIID);
|
|
goto end;
|
|
}
|
|
|
|
if (!iSpec.m_NlbCfg.IsValidNlbConfig())
|
|
{
|
|
// can't trust NLB config info on this interface.
|
|
goto end;
|
|
}
|
|
|
|
//
|
|
// We'll make a copy of the interface's config and apply the cluster
|
|
// properties to it and then copy this copy over to the cluster properties.
|
|
//
|
|
wStat = TmpConfig.Update(&iSpec.m_NlbCfg);
|
|
if (FAILED(wStat))
|
|
{
|
|
TRACE_CRIT("%!FUNC! could not perform an internal copy!");
|
|
goto end;
|
|
}
|
|
|
|
err = gEngine.ApplyClusterWideConfiguration(REF *m_pNlbCfg, TmpConfig);
|
|
if (!NLBOK(err))
|
|
{
|
|
goto end;
|
|
}
|
|
|
|
wStat = m_pNlbCfg->Update(&TmpConfig);
|
|
|
|
if (FAILED(wStat))
|
|
{
|
|
goto end;
|
|
}
|
|
|
|
// Fall through.
|
|
|
|
end:
|
|
return;
|
|
}
|
|
|
|
BOOL
|
|
ConnectDialog::mfn_ValidateData()
|
|
/*
|
|
Make sure the interface is not already part of a different cluster,
|
|
or other problem (eg we're connnecting to this interface and it's DHCP)
|
|
|
|
NewCluster:
|
|
ExistingCluster:
|
|
AddHost:
|
|
|
|
In all cases, we fail if pISpec already has an ehCluster associated with
|
|
it. Put up a message box with the associated ehCluster.
|
|
*/
|
|
{
|
|
|
|
BOOL fRet = FALSE;
|
|
NLBERROR nerr;
|
|
ENGINEHANDLE ehHost = NULL;
|
|
ENGINEHANDLE ehCluster = NULL;
|
|
_bstr_t bstrFriendlyName;
|
|
_bstr_t bstrDisplayName;
|
|
_bstr_t bstrHostName;
|
|
LPCWSTR szFriendlyName = NULL;
|
|
BOOL fOkCancel=FALSE;
|
|
CLocalLogger msgLog;
|
|
_bstr_t bstrCaption;
|
|
|
|
if (*m_pehSelectedInterfaceId == NULL)
|
|
{
|
|
|
|
//
|
|
// We shouldn't get here because the "Next" button is only enabled
|
|
// if there IS a selection; however we deal with this case anyway.
|
|
//
|
|
// bstrCaption = L"No interface selected";
|
|
bstrCaption = GETRESOURCEIDSTRING (IDS_CONNECT_NO_INTERFACE_SELECTED);
|
|
msgLog.Log(IDS_CONNECT_SELECT_AN_INTERFACE);
|
|
goto end;
|
|
}
|
|
|
|
nerr = gEngine.GetInterfaceIdentification(
|
|
*m_pehSelectedInterfaceId,
|
|
REF ehHost,
|
|
REF ehCluster,
|
|
REF bstrFriendlyName,
|
|
REF bstrDisplayName,
|
|
REF bstrHostName
|
|
);
|
|
|
|
if (NLBFAILED(nerr))
|
|
{
|
|
//
|
|
// This indicates an internal error like a bad handle.
|
|
//
|
|
bstrCaption = GETRESOURCEIDSTRING(IDS_CONNECT_UNABLE_TO_PROCEED);
|
|
// szCaption = L"Unable to proceed";
|
|
|
|
msgLog.Log(IDS_CONNECT_UNABLE_TO_PROCEEED_INTERNAL);
|
|
// szMessage = L"Unable to proceed due to an internal error.";
|
|
goto end;
|
|
}
|
|
|
|
szFriendlyName = (LPCWSTR) bstrFriendlyName;
|
|
if (szFriendlyName == NULL)
|
|
{
|
|
szFriendlyName = L"";
|
|
}
|
|
|
|
if (ehCluster == NULL)
|
|
{
|
|
//
|
|
// Should be good to go.
|
|
// TODO -- if interface already bound AND m_type is NOT
|
|
// DLGTYPE_EXISTING_CLUSTER, we should ask if user wants to
|
|
// clobber the existing interface.
|
|
//
|
|
if (m_type != DLGTYPE_EXISTING_CLUSTER)
|
|
{
|
|
CInterfaceSpec iSpec;
|
|
|
|
nerr = gEngine.GetInterfaceSpec(*m_pehSelectedInterfaceId, REF iSpec);
|
|
if (nerr == NLBERR_OK)
|
|
{
|
|
|
|
//
|
|
// Check if we're connected to this NIC, and
|
|
// the NIC is DHCP, so we're not going to be able to
|
|
// keep the connected IP address.
|
|
//
|
|
// If so, we cannot proceed.
|
|
//
|
|
{
|
|
ENGINEHANDLE ehConnectionIF = NULL;
|
|
_bstr_t bstrConnectionString;
|
|
UINT uConnectionIp = 0;
|
|
|
|
nerr = gEngine.GetHostConnectionInformation(
|
|
ehHost,
|
|
REF ehConnectionIF,
|
|
REF bstrConnectionString,
|
|
REF uConnectionIp
|
|
);
|
|
if (NLBFAILED(nerr))
|
|
{
|
|
TRACE_CRIT(L"%!FUNC! gEngine.GetHostConnectionInformation fails!");
|
|
//
|
|
// We'll plow on...
|
|
//
|
|
ehConnectionIF = NULL;
|
|
uConnectionIp = 0;
|
|
}
|
|
|
|
if (ehConnectionIF == *m_pehSelectedInterfaceId)
|
|
{
|
|
//
|
|
// The selected interface is also the interface that we
|
|
// are connecting over...
|
|
//
|
|
|
|
if (iSpec.m_NlbCfg.fDHCP)
|
|
{
|
|
//
|
|
// Ouch -- it's also DHCP. We can't allow this...
|
|
//
|
|
msgLog.Log(IDS_CANT_USE_DHCP_NIC_MSG);
|
|
bstrCaption = GETRESOURCEIDSTRING(IDS_CONNECT_UNABLE_TO_PROCEED);
|
|
fRet = FALSE;
|
|
goto end;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Check if nlb is bound and if so, if it's cluster ip address
|
|
// is different.
|
|
//
|
|
if (iSpec.m_NlbCfg.IsValidNlbConfig())
|
|
{
|
|
//
|
|
// Hmm... interface is already bound to NLB.
|
|
// Let's see if the cluster IP address is different...
|
|
//
|
|
LPCWSTR szClusterIp = m_pNlbCfg->NlbParams.cl_ip_addr;
|
|
LPCWSTR szIfClusterIp = iSpec.m_NlbCfg.NlbParams.cl_ip_addr;
|
|
if ( szIfClusterIp[0]!=0
|
|
&& (_wcsspnp(szIfClusterIp, L".0")!=NULL))
|
|
{
|
|
// non-blank cluster Ip address
|
|
if (wcscmp(szClusterIp, szIfClusterIp))
|
|
{
|
|
//
|
|
// IPs don't match! Put up message box..
|
|
//
|
|
msgLog.Log(
|
|
IDS_CONNECT_MSG_IF_ALREADY_BOUND,
|
|
szFriendlyName,
|
|
iSpec.m_NlbCfg.NlbParams.domain_name,
|
|
szIfClusterIp
|
|
);
|
|
bstrCaption = GETRESOURCEIDSTRING(IDS_CONNECT_CAP_IF_ALREADY_BOUND);
|
|
// szCaption = L"Interface already configured for NLB";
|
|
|
|
fOkCancel=TRUE;
|
|
fRet = FALSE;
|
|
goto end;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fRet = TRUE;
|
|
}
|
|
else
|
|
{
|
|
_bstr_t bstrClusterDescription;
|
|
_bstr_t bstrIpAddress;
|
|
_bstr_t bstrDomainName;
|
|
LPCWSTR szClusterDescription = NULL;
|
|
|
|
nerr = gEngine.GetClusterIdentification(
|
|
ehCluster,
|
|
REF bstrIpAddress,
|
|
REF bstrDomainName,
|
|
REF bstrDisplayName
|
|
);
|
|
|
|
if (FAILED(nerr))
|
|
{
|
|
TRACE_CRIT(L"%!FUNC!: Error 0x%lx getting ehCluster 0x%lx identification\n",
|
|
nerr, ehCluster);
|
|
bstrCaption = GETRESOURCEIDSTRING(IDS_CONNECT_UNABLE_TO_PROCEED);
|
|
// szCaption = L"Unable to proceed";
|
|
|
|
msgLog.Log(IDS_CONNECT_UNABLE_TO_PROCEEED_INTERNAL);
|
|
// szMessage = L"Unable to proceed due to an internal error.";
|
|
goto end;
|
|
}
|
|
szClusterDescription = bstrDisplayName;
|
|
if (szClusterDescription==NULL)
|
|
{
|
|
szClusterDescription = L"";
|
|
}
|
|
|
|
|
|
//
|
|
// We won't allow proceeding in this case, because this indicates that
|
|
// this interface is already part of a cluster managed by NLB Manger.
|
|
//
|
|
msgLog.Log(
|
|
IDS_CONNECT_MSG_INTERFACE_ALREADY_MANAGED,
|
|
szFriendlyName,
|
|
szClusterDescription
|
|
);
|
|
bstrCaption = GETRESOURCEIDSTRING(IDS_CONNECT_UNABLE_TO_PROCEED);
|
|
|
|
}
|
|
|
|
end:
|
|
|
|
if (!fRet)
|
|
{
|
|
LPCWSTR szCaption = (LPCWSTR) bstrCaption;
|
|
LPCWSTR szMessage = msgLog.GetStringSafe();
|
|
|
|
if (fOkCancel)
|
|
{
|
|
|
|
int i = MessageBox( szMessage, szCaption, MB_OKCANCEL);
|
|
if (i == IDOK)
|
|
{
|
|
fRet = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MessageBox( szMessage, szCaption, MB_ICONSTOP | MB_OK);
|
|
}
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
|
|
BOOL g_Silent = FALSE;
|