1120 lines
27 KiB
C++
1120 lines
27 KiB
C++
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (c) 2000-2001 Microsoft Corporation
|
|
//
|
|
// Module Name:
|
|
// SelNodesPage.cpp
|
|
//
|
|
// Maintained By:
|
|
// David Potter (DavidP) 31-JAN-2001
|
|
// Geoffrey Pease (GPease) 12-MAY-2000
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "pch.h"
|
|
#include "SelNodesPage.h"
|
|
#include "WizardUtils.h"
|
|
|
|
DEFINE_THISCLASS("CSelNodesPage");
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CSelNodesPage::CSelNodesPage
|
|
//
|
|
// Description:
|
|
// Constructor.
|
|
//
|
|
// Arguments:
|
|
// pspIn -- IServiceProvider
|
|
// ecamCreateAddModeIn -- Creating cluster or adding nodes to cluster
|
|
// pcCountInout -- Count of computers in prgbstrComputersInout
|
|
// prgbstrComputersInout -- Array of computers
|
|
// pbstrClusterNameIn -- Name of the cluster
|
|
//
|
|
// Return Values:
|
|
// None.
|
|
//
|
|
// Remarks:
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
CSelNodesPage::CSelNodesPage(
|
|
IServiceProvider * pspIn,
|
|
ECreateAddMode ecamCreateAddModeIn,
|
|
ULONG * pcCountInout,
|
|
BSTR ** prgbstrComputersInout,
|
|
BSTR * pbstrClusterNameIn
|
|
)
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
Assert( pspIn != NULL );
|
|
Assert( pcCountInout != NULL );
|
|
Assert( prgbstrComputersInout != NULL );
|
|
Assert( pbstrClusterNameIn != NULL );
|
|
|
|
// m_hwnd
|
|
THR( pspIn->TypeSafeQI( IServiceProvider, &m_psp ) );
|
|
m_pcComputers = pcCountInout;
|
|
m_prgbstrComputers = prgbstrComputersInout;
|
|
m_pbstrClusterName = pbstrClusterNameIn;
|
|
m_cfDsObjectPicker = 0;
|
|
|
|
TraceFuncExit();
|
|
|
|
} //*** CSelNodesPage::CSelNodesPage()
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CSelNodesPage::~CSelNodesPage
|
|
//
|
|
// Description:
|
|
// Destructor.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Values:
|
|
// None.
|
|
//
|
|
// Remarks:
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
CSelNodesPage::~CSelNodesPage( void )
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
if ( m_psp != NULL )
|
|
{
|
|
m_psp->Release();
|
|
}
|
|
|
|
TraceFuncExit();
|
|
|
|
} //*** CSelNodesPage::~CSelNodesPage()
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CSelNodesPage::OnInitDialog
|
|
//
|
|
// Description:
|
|
// Handle the WM_INITDIALOG window message.
|
|
//
|
|
// Arguments:
|
|
// hDlgIn
|
|
//
|
|
// Return Values:
|
|
// FALSE - Didn't set the focus.
|
|
//
|
|
// Remarks:
|
|
//
|
|
//-
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
LRESULT
|
|
CSelNodesPage::OnInitDialog(
|
|
HWND hDlgIn
|
|
)
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
HRESULT hr;
|
|
|
|
BSTR bstrComputerName = NULL;
|
|
|
|
LRESULT lr = FALSE; // Didn't set the focus.
|
|
|
|
//
|
|
// If a list of computers was already specified, validate them.
|
|
//
|
|
|
|
if ( ( *m_prgbstrComputers != NULL )
|
|
&& ( *m_pcComputers >= 1 )
|
|
&& ( (*m_prgbstrComputers)[ 0 ] != NULL )
|
|
)
|
|
{
|
|
ULONG idxComputers;
|
|
|
|
//
|
|
// If a script pre-entered the machine names, make sure they end up in the UI.
|
|
//
|
|
|
|
for ( idxComputers = 0 ; idxComputers < *m_pcComputers ; idxComputers ++ )
|
|
{
|
|
hr = THR( HrValidateDnsHostname(
|
|
hDlgIn
|
|
, (*m_prgbstrComputers)[ idxComputers ]
|
|
, mvdhoALLOW_FULL_NAME
|
|
) );
|
|
if ( ! FAILED( hr ) )
|
|
{
|
|
//
|
|
// Make sure the node is in the same domain as the cluster.
|
|
//
|
|
|
|
LPWSTR pszClusterDomain;
|
|
LPWSTR pszComputerDomain;
|
|
|
|
pszClusterDomain = wcschr( (*m_pbstrClusterName), L'.' );
|
|
Assert( pszClusterDomain != NULL );
|
|
pszComputerDomain = wcschr( (*m_prgbstrComputers)[ idxComputers ], L'.' );
|
|
if ( pszComputerDomain != NULL )
|
|
{
|
|
if ( _wcsicmp( &pszClusterDomain[ 1 ], &pszComputerDomain[ 1 ] ) != 0 )
|
|
{
|
|
hr = THR( HRESULT_FROM_WIN32( ERROR_INVALID_COMPUTERNAME ) );
|
|
THR( HrMessageBoxWithStatusString(
|
|
m_hwnd
|
|
, IDS_ERR_VALIDATING_NAME_TITLE
|
|
, IDS_ERR_VALIDATING_NAME_TEXT
|
|
, IDS_ERR_HOST_DOMAIN_DOESNT_MATCH_CLUSTER
|
|
, 0
|
|
, MB_OK | MB_ICONSTOP
|
|
, NULL
|
|
, *m_pbstrClusterName
|
|
) );
|
|
} // if: computer not in same domain
|
|
else
|
|
{
|
|
// Don't add the computer to the list with its domain name.
|
|
*pszComputerDomain = L'\0';
|
|
}
|
|
} // if: computer domain specified
|
|
} // if: DNS validation was successful
|
|
|
|
if ( FAILED( hr ) )
|
|
{
|
|
//
|
|
// Construct a comma-separated list of invalid computer names.
|
|
// This list will be written to the edit control so the user
|
|
// can correct mistakes.
|
|
//
|
|
|
|
if ( bstrComputerName == NULL )
|
|
{
|
|
//
|
|
// First invalid computer name.
|
|
//
|
|
|
|
bstrComputerName = TraceSysAllocString( (*m_prgbstrComputers)[ idxComputers ] );
|
|
if ( bstrComputerName == NULL )
|
|
{
|
|
THR( E_OUTOFMEMORY );
|
|
}
|
|
} // if: first invalid computer name
|
|
else
|
|
{
|
|
BSTR bstr = NULL;
|
|
|
|
//
|
|
// Subsequent invalid computer name.
|
|
//
|
|
|
|
hr = THR( HrFormatStringIntoBSTR(
|
|
L"%1!ws!,%2!ws!"
|
|
, &bstr
|
|
, bstrComputerName
|
|
, (*m_prgbstrComputers)[ idxComputers ]
|
|
) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
// Ignore error. What can we do?
|
|
}
|
|
else
|
|
{
|
|
TraceSysFreeString( bstrComputerName );
|
|
bstrComputerName = bstr;
|
|
}
|
|
} // else: more than one invalid computer name
|
|
} // if: error validating computer name
|
|
else
|
|
{
|
|
ListBox_AddString( GetDlgItem( m_hwnd, IDC_SELNODE_LB_NODES ), (*m_prgbstrComputers)[ idxComputers ] );
|
|
}
|
|
} // for: each computer
|
|
|
|
//
|
|
// Set the edit control to the list of invalid computer names.
|
|
//
|
|
if ( bstrComputerName != NULL )
|
|
{
|
|
SetDlgItemText( m_hwnd, IDC_SELNODE_E_COMPUTERNAME, bstrComputerName );
|
|
} // if: invalid computer names found
|
|
} // if: computers were specified by the caller of the wizard
|
|
else
|
|
{
|
|
DWORD dwStatus;
|
|
DWORD dwClusterState;
|
|
|
|
//
|
|
// If the node is already in a cluster, don't have it default in the edit box.
|
|
// If there is an error getting the "NodeClusterState", then default the node
|
|
// name (it could be in the middle of cleaning up the node).
|
|
//
|
|
|
|
dwStatus = TW32( GetNodeClusterState( NULL, &dwClusterState ) );
|
|
if ( ( dwStatus != ERROR_SUCCESS )
|
|
|| ( dwClusterState == ClusterStateNotConfigured ) )
|
|
{
|
|
hr = THR( HrGetComputerName( ComputerNameDnsHostname, &bstrComputerName ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
SetDlgItemText( m_hwnd, IDC_SELNODE_E_COMPUTERNAME, bstrComputerName );
|
|
} // else: no list of computers was specified
|
|
|
|
m_cfDsObjectPicker = RegisterClipboardFormat( CFSTR_DSOP_DS_SELECTION_LIST );
|
|
if ( m_cfDsObjectPicker == 0 )
|
|
{
|
|
TW32( GetLastError() );
|
|
//
|
|
// If registering the clipboard format fails, then disable the Browse
|
|
// button.
|
|
//
|
|
EnableWindow( GetDlgItem( hDlgIn, IDC_SELNODE_PB_BROWSE ), FALSE );
|
|
|
|
} // if:
|
|
|
|
Cleanup:
|
|
TraceSysFreeString( bstrComputerName );
|
|
|
|
RETURN( lr );
|
|
|
|
} //*** CSelNodesPage::OnInitDialog()
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CSelNodesPage::OnCommand
|
|
//
|
|
// Description:
|
|
//
|
|
// Arguments:
|
|
// idNotificationIn
|
|
// idControlIn
|
|
// hwndSenderIn
|
|
//
|
|
// Return Values:
|
|
// TRUE
|
|
// FALSE
|
|
//
|
|
// Remarks:
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
LRESULT
|
|
CSelNodesPage::OnCommand(
|
|
UINT idNotificationIn,
|
|
UINT idControlIn,
|
|
HWND hwndSenderIn
|
|
)
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
LRESULT lr = FALSE;
|
|
|
|
switch ( idControlIn )
|
|
{
|
|
case IDC_SELNODE_E_COMPUTERNAME:
|
|
if ( idNotificationIn == EN_CHANGE )
|
|
{
|
|
THR( HrUpdateWizardButtons() );
|
|
lr = TRUE;
|
|
}
|
|
break;
|
|
|
|
case IDC_SELNODE_LB_NODES:
|
|
if ( idNotificationIn == LBN_SELCHANGE )
|
|
{
|
|
THR( HrUpdateWizardButtons() );
|
|
lr = TRUE;
|
|
}
|
|
break;
|
|
|
|
case IDC_SELNODE_PB_BROWSE:
|
|
if ( idNotificationIn == BN_CLICKED )
|
|
{
|
|
THR( HrBrowse() );
|
|
lr = TRUE;
|
|
}
|
|
break;
|
|
|
|
case IDC_SELNODE_PB_ADD:
|
|
if ( idNotificationIn == BN_CLICKED )
|
|
{
|
|
THR( HrAddNodeToList() );
|
|
lr = TRUE;
|
|
}
|
|
break;
|
|
|
|
case IDC_SELNODE_PB_REMOVE:
|
|
if ( idNotificationIn == BN_CLICKED )
|
|
{
|
|
THR( HrRemoveNodeFromList() );
|
|
lr = TRUE;
|
|
}
|
|
break;
|
|
|
|
} // switch: idControlIn
|
|
|
|
RETURN( lr );
|
|
|
|
} //*** CSelNodesPage::OnCommand()
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CSelNodesPage::HrUpdateWizardButtons
|
|
//
|
|
// Description:
|
|
//
|
|
// Arguments:
|
|
// fSetActiveIn - TRUE = called while handling PSN_SETACTIVE.
|
|
//
|
|
// Return Values:
|
|
// S_OK
|
|
//
|
|
// Remarks:
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CSelNodesPage::HrUpdateWizardButtons(
|
|
bool fSetActiveIn // = false
|
|
)
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
HWND hwndList = GetDlgItem( m_hwnd, IDC_SELNODE_LB_NODES );
|
|
|
|
DWORD dwFlags = PSWIZB_BACK | PSWIZB_NEXT;
|
|
DWORD dwLen;
|
|
LRESULT lr;
|
|
|
|
// Disable the Next button if there are no entries in the list box
|
|
// or if the edit control is not empty.
|
|
lr = ListBox_GetCount( hwndList );
|
|
dwLen = GetWindowTextLength( GetDlgItem( m_hwnd, IDC_SELNODE_E_COMPUTERNAME ) );
|
|
if ( ( lr == 0 )
|
|
|| ( dwLen != 0 ) )
|
|
{
|
|
dwFlags &= ~PSWIZB_NEXT;
|
|
}
|
|
|
|
// This cannot be done synchronously if called while handling
|
|
// PSN_SETACTIVE. Otherwise, do it synchronously.
|
|
if ( fSetActiveIn )
|
|
{
|
|
PropSheet_SetWizButtons( GetParent( m_hwnd ), dwFlags );
|
|
}
|
|
else
|
|
{
|
|
SendMessage( GetParent( m_hwnd ), PSM_SETWIZBUTTONS, 0, (LPARAM) dwFlags );
|
|
}
|
|
|
|
// Enable or disable the Add button based on whether there is text
|
|
// in the edit control or not.
|
|
if ( dwLen == 0 )
|
|
{
|
|
EnableWindow( GetDlgItem( m_hwnd, IDC_SELNODE_PB_ADD ), FALSE );
|
|
}
|
|
else
|
|
{
|
|
EnableWindow( GetDlgItem( m_hwnd, IDC_SELNODE_PB_ADD ), TRUE );
|
|
SendMessage( m_hwnd, DM_SETDEFID, IDC_SELNODE_PB_ADD, 0 );
|
|
}
|
|
|
|
// Enable or disable the Remove button based whether an item is
|
|
// selected in the list box or not.
|
|
lr = ListBox_GetCurSel( hwndList );
|
|
if ( lr == LB_ERR )
|
|
{
|
|
EnableWindow( GetDlgItem( m_hwnd, IDC_SELNODE_PB_REMOVE ), FALSE );
|
|
}
|
|
else
|
|
{
|
|
EnableWindow( GetDlgItem( m_hwnd, IDC_SELNODE_PB_REMOVE ), TRUE );
|
|
}
|
|
|
|
HRETURN( hr );
|
|
|
|
} //*** CSelNodesPage::HrUpdateWizardButtons()
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CSelNodesPage::HrAddNodeToList
|
|
//
|
|
// Description:
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Values:
|
|
// S_OK
|
|
// E_OUTOFMEMORY
|
|
//
|
|
// Remarks:
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CSelNodesPage::HrAddNodeToList( void )
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
HRESULT hr;
|
|
DNS_STATUS dnsStatus;
|
|
|
|
DWORD dwLen;
|
|
int idcFocus = 0;
|
|
|
|
LPWSTR psz;
|
|
LPWSTR pszComputerName;
|
|
LPWSTR pszFreeBuffer = NULL;
|
|
|
|
HWND hwndList = GetDlgItem( m_hwnd, IDC_SELNODE_LB_NODES );
|
|
HWND hwndEdit = GetDlgItem( m_hwnd, IDC_SELNODE_E_COMPUTERNAME );
|
|
|
|
dwLen = GetWindowTextLength( hwndEdit );
|
|
if ( dwLen == 0 )
|
|
{
|
|
hr = HRESULT_FROM_WIN32( TW32( GetLastError() ) );
|
|
if ( hr == HRESULT_FROM_WIN32( ERROR_SUCCESS ) )
|
|
{
|
|
AssertMsg( dwLen != 0, "How did we get here?!" );
|
|
}
|
|
goto Error;
|
|
}
|
|
|
|
pszComputerName = (LPWSTR) TraceAlloc( 0, ( dwLen + 1 ) * sizeof(WCHAR) );
|
|
if ( pszComputerName == NULL )
|
|
{
|
|
goto OutOfMemory;
|
|
}
|
|
|
|
pszFreeBuffer = pszComputerName;
|
|
|
|
dwLen = GetDlgItemText( m_hwnd, IDC_SELNODE_E_COMPUTERNAME, pszComputerName, dwLen + 1 );
|
|
AssertMsg( dwLen != 0, "How did we get here?!" );
|
|
|
|
for ( ; pszComputerName != NULL ; pszComputerName = psz )
|
|
{
|
|
// Allow comma, semi-colon, and space delimiters.
|
|
psz = wcspbrk( pszComputerName, L",; " );
|
|
if ( psz != NULL )
|
|
{
|
|
*psz = L'\0';
|
|
psz++;
|
|
}
|
|
|
|
hr = THR( HrValidateDnsHostname(
|
|
m_hwnd
|
|
, pszComputerName
|
|
, mvdhoALLOW_ONLY_HOSTNAME_LABEL
|
|
) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
idcFocus = IDC_SELNODE_E_COMPUTERNAME;
|
|
goto Error;
|
|
}
|
|
|
|
ListBox_AddString( GetDlgItem( m_hwnd, IDC_SELNODE_LB_NODES ), pszComputerName );
|
|
|
|
} // for: pszComputerName;
|
|
|
|
SetDlgItemText( m_hwnd, IDC_SELNODE_E_COMPUTERNAME, L"" );
|
|
|
|
hr = THR( HrUpdateWizardButtons() );
|
|
|
|
Error:
|
|
TraceFree( pszFreeBuffer );
|
|
|
|
if ( idcFocus != 0 )
|
|
{
|
|
SetFocus( GetDlgItem( m_hwnd, idcFocus ) );
|
|
}
|
|
|
|
HRETURN( hr );
|
|
|
|
OutOfMemory:
|
|
hr = E_OUTOFMEMORY;
|
|
goto Error;
|
|
|
|
} //*** CSelNodesPage::HrAddNodeToList()
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CSelNodesPage::HrRemoveNodeFromList
|
|
//
|
|
// Description:
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Values:
|
|
// S_OK
|
|
//
|
|
// Remarks:
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CSelNodesPage::HrRemoveNodeFromList( void )
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
HRESULT hr;
|
|
LRESULT lr;
|
|
|
|
HWND hwndList = GetDlgItem( m_hwnd, IDC_SELNODE_LB_NODES );
|
|
|
|
lr = ListBox_GetCurSel( hwndList );
|
|
if ( lr != LB_ERR )
|
|
{
|
|
ListBox_DeleteString( hwndList, lr );
|
|
}
|
|
|
|
hr = THR( HrUpdateWizardButtons() );
|
|
|
|
HRETURN( hr );
|
|
|
|
} //*** CSelNodesPage::HrRemoveNodeFromList()
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CSelNodesPage::OnNotifySetActive
|
|
//
|
|
// Description:
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Values:
|
|
// TRUE
|
|
//
|
|
// Remarks:
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
LRESULT
|
|
CSelNodesPage::OnNotifySetActive( void )
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
LRESULT lr = TRUE;
|
|
|
|
THR( HrUpdateWizardButtons( true /* fSetActiveIn */ ) );
|
|
|
|
RETURN( lr );
|
|
|
|
} //*** CSelNodesPage::OnNotifySetActive()
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CSelNodesPage::OnNotifyQueryCancel
|
|
//
|
|
// Description:
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Values:
|
|
// TRUE
|
|
//
|
|
// Remarks:
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
LRESULT
|
|
CSelNodesPage::OnNotifyQueryCancel( void )
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
LRESULT lr = TRUE;
|
|
|
|
int iRet;
|
|
|
|
iRet = MessageBoxFromStrings( m_hwnd,
|
|
IDS_QUERY_CANCEL_TITLE,
|
|
IDS_QUERY_CANCEL_TEXT,
|
|
MB_YESNO
|
|
);
|
|
|
|
if ( iRet == IDNO )
|
|
{
|
|
SetWindowLongPtr( m_hwnd, DWLP_MSGRESULT, -1 );
|
|
}
|
|
|
|
RETURN( lr );
|
|
|
|
} //*** CSelNodesPage::OnNotifyQueryCancel()
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CSelNodesPage::OnNotifyWizNext
|
|
//
|
|
// Description:
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Values:
|
|
// TRUE
|
|
// LB_ERR
|
|
// Other LRESULT values.
|
|
//
|
|
// Remarks:
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
LRESULT
|
|
CSelNodesPage::OnNotifyWizNext( void )
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
LPWSTR pszDomain;
|
|
DWORD dwLen;
|
|
|
|
WCHAR szComputerName[ DNS_MAX_NAME_BUFFER_LENGTH ];
|
|
|
|
LRESULT lr = TRUE;
|
|
|
|
HWND hwndList = GetDlgItem( m_hwnd, IDC_SELNODE_LB_NODES );
|
|
|
|
//
|
|
// Free old list (if any)
|
|
//
|
|
|
|
while ( *m_pcComputers != 0 )
|
|
{
|
|
(*m_pcComputers) --;
|
|
TraceSysFreeString( (*m_prgbstrComputers)[ *m_pcComputers ] );
|
|
}
|
|
|
|
//
|
|
// Find out how many are in the new list.
|
|
//
|
|
|
|
lr = ListBox_GetCount( hwndList );
|
|
if ( lr == LB_ERR )
|
|
{
|
|
goto Error;
|
|
}
|
|
|
|
// Check to see if we have a FQDN cluster name
|
|
pszDomain = wcschr( *m_pbstrClusterName, L'.' );
|
|
|
|
//
|
|
// Loop thru adding the FQDN node names to the list of nodes.
|
|
//
|
|
|
|
Assert( lr >= 0 );
|
|
|
|
TraceFree( *m_prgbstrComputers );
|
|
|
|
//
|
|
// Need to make a new list.
|
|
//
|
|
|
|
*m_prgbstrComputers = (BSTR *) TraceAlloc( HEAP_ZERO_MEMORY, (size_t) lr * sizeof(BSTR) );
|
|
if ( *m_prgbstrComputers == NULL )
|
|
{
|
|
goto OutOfMemory;
|
|
}
|
|
|
|
for ( *m_pcComputers = 0; *m_pcComputers < (ULONG) lr; (*m_pcComputers) ++ )
|
|
{
|
|
dwLen = ListBox_GetText( hwndList, *m_pcComputers, szComputerName );
|
|
Assert( dwLen < ARRAYSIZE( szComputerName ) );
|
|
|
|
// Append domain name to node if present.
|
|
if ( pszDomain != NULL )
|
|
{
|
|
wcsncpy( &szComputerName[ dwLen ], pszDomain, ARRAYSIZE( szComputerName ) - dwLen - 1 /* NULL */ );
|
|
}
|
|
|
|
// Add a new entry
|
|
(*m_prgbstrComputers)[ *m_pcComputers ] = TraceSysAllocString( szComputerName );
|
|
if ( (*m_prgbstrComputers)[ *m_pcComputers ] == NULL )
|
|
{
|
|
goto OutOfMemory;
|
|
}
|
|
|
|
} // for: *m_pcComputers
|
|
|
|
Cleanup:
|
|
RETURN( lr );
|
|
|
|
OutOfMemory:
|
|
LogMsg( "Out of memory." );
|
|
// fall thru
|
|
|
|
Error:
|
|
SetWindowLongPtr( m_hwnd, DWLP_MSGRESULT, -1 );
|
|
goto Cleanup;
|
|
|
|
} //*** CSelNodesPage::OnNotifyWizNext()
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CSelNodesPage::OnNotify
|
|
//
|
|
// Description:
|
|
//
|
|
// Arguments:
|
|
// idCtrlIn
|
|
// pnmhdrIn
|
|
//
|
|
// Return Values:
|
|
// TRUE
|
|
// Other LRESULT values.
|
|
//
|
|
// Remarks:
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
LRESULT
|
|
CSelNodesPage::OnNotify(
|
|
WPARAM idCtrlIn,
|
|
LPNMHDR pnmhdrIn
|
|
)
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
LRESULT lr = TRUE;
|
|
|
|
SetWindowLongPtr( m_hwnd, DWLP_MSGRESULT, 0 );
|
|
|
|
switch( pnmhdrIn->code )
|
|
{
|
|
case PSN_SETACTIVE:
|
|
lr = OnNotifySetActive();
|
|
break;
|
|
|
|
case PSN_WIZNEXT:
|
|
lr = OnNotifyWizNext();
|
|
break;
|
|
|
|
case PSN_QUERYCANCEL:
|
|
lr = OnNotifyQueryCancel();
|
|
break;
|
|
} // switch: notification code
|
|
|
|
RETURN( lr );
|
|
|
|
} //*** CSelNodesPage::OnNotify()
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CSelNodePage::HrBrowse
|
|
//
|
|
// Description:
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Values:
|
|
// S_OK
|
|
// Other HRESULT values.
|
|
//
|
|
// Remarks:
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CSelNodesPage::HrBrowse( void )
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
HRESULT hr = S_OK;
|
|
IDsObjectPicker * piop = NULL;
|
|
IDataObject * pido = NULL;
|
|
HCURSOR hOldCursor = NULL;
|
|
|
|
hOldCursor = SetCursor( LoadCursor( g_hInstance, IDC_WAIT ) );
|
|
|
|
// Create an instance of the object picker.
|
|
hr = THR( CoCreateInstance( CLSID_DsObjectPicker, NULL, CLSCTX_INPROC_SERVER, IID_IDsObjectPicker, (void **) &piop ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
} // if:
|
|
|
|
// Initialize the object picker instance.
|
|
hr = THR( HrInitObjectPicker( piop ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
} // if:
|
|
|
|
SetCursor( hOldCursor );
|
|
|
|
// Invoke the modal dialog.
|
|
hr = THR( piop->InvokeDialog( m_hwnd, &pido ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
} // if:
|
|
|
|
if ( hr == S_OK )
|
|
{
|
|
hr = THR( HrGetSelections( pido ) );
|
|
} // if:
|
|
else if ( hr == S_FALSE )
|
|
{
|
|
hr = S_OK; // don't want to squawk in the caller...
|
|
} // else if:
|
|
|
|
Cleanup:
|
|
|
|
if ( pido != NULL )
|
|
{
|
|
pido->Release();
|
|
} // if:
|
|
|
|
if ( piop != NULL )
|
|
{
|
|
piop->Release();
|
|
} // if:
|
|
|
|
HRETURN( hr );
|
|
|
|
} //*** CSelNodesPage::HrBrowse()
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CSelNodesPage::HrInitObjectPicker
|
|
//
|
|
// Description:
|
|
// Initialize the Object Picker dialog.
|
|
//
|
|
// Arguments:
|
|
// piopIn -- IDsObjectPicker
|
|
//
|
|
// Return Values:
|
|
// HRESULT values.
|
|
//
|
|
// Remarks:
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CSelNodesPage::HrInitObjectPicker( IDsObjectPicker * piopIn )
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
DSOP_SCOPE_INIT_INFO rgScopeInit[ 1 ];
|
|
DSOP_INIT_INFO iiInfo;
|
|
|
|
ZeroMemory( rgScopeInit, sizeof( DSOP_SCOPE_INIT_INFO ) * (sizeof( rgScopeInit ) / sizeof( rgScopeInit[ 0 ] ) ) );
|
|
|
|
rgScopeInit[0].cbSize = sizeof( DSOP_SCOPE_INIT_INFO );
|
|
rgScopeInit[0].flType = DSOP_SCOPE_TYPE_UPLEVEL_JOINED_DOMAIN | DSOP_SCOPE_TYPE_DOWNLEVEL_JOINED_DOMAIN;
|
|
rgScopeInit[0].flScope = DSOP_SCOPE_FLAG_STARTING_SCOPE;
|
|
|
|
rgScopeInit[0].FilterFlags.Uplevel.flBothModes = DSOP_FILTER_COMPUTERS;
|
|
rgScopeInit[0].FilterFlags.flDownlevel = DSOP_DOWNLEVEL_FILTER_COMPUTERS;
|
|
|
|
ZeroMemory( &iiInfo, sizeof( iiInfo ) );
|
|
|
|
iiInfo.cbSize = sizeof( iiInfo );
|
|
iiInfo.pwzTargetComputer = NULL;
|
|
iiInfo.cDsScopeInfos = 1;
|
|
iiInfo.aDsScopeInfos = rgScopeInit;
|
|
iiInfo.flOptions = DSOP_FLAG_MULTISELECT;
|
|
|
|
HRETURN( piopIn->Initialize( &iiInfo) );
|
|
|
|
} //*** CSelNodesPage::HrInitObjectPicker
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CSelNodePage::HrGetSelections
|
|
//
|
|
// Description:
|
|
// Get selections from the Object Picker dialog.
|
|
//
|
|
// Arguments:
|
|
// pidoIn -- IDataObject
|
|
//
|
|
// Return Values:
|
|
// S_OK
|
|
// E_OUTOFMEMORY
|
|
// Other HRESULT values.
|
|
//
|
|
// Remarks:
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CSelNodesPage::HrGetSelections(
|
|
IDataObject * pidoIn
|
|
)
|
|
{
|
|
TraceFunc( "" );
|
|
Assert( pidoIn != NULL );
|
|
|
|
HRESULT hr;
|
|
STGMEDIUM stgmedium = { TYMED_HGLOBAL, NULL, NULL };
|
|
FORMATETC formatetc = { (CLIPFORMAT) m_cfDsObjectPicker, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
|
|
PDS_SELECTION_LIST pds = NULL;
|
|
DWORD sc;
|
|
ULONG idx;
|
|
HWND hwndEdit = GetDlgItem( m_hwnd, IDC_SELNODE_E_COMPUTERNAME );
|
|
WCHAR * psz = NULL;
|
|
ULONG cch = 0;
|
|
|
|
hr = THR( pidoIn->GetData( &formatetc, &stgmedium ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
pds = (PDS_SELECTION_LIST) GlobalLock( stgmedium.hGlobal );
|
|
if ( pds == NULL )
|
|
{
|
|
sc = TW32( GetLastError() );
|
|
hr = HRESULT_FROM_WIN32( sc );
|
|
goto Cleanup;
|
|
} // if:
|
|
|
|
for ( idx = 0 ; idx < pds->cItems; idx++ )
|
|
{
|
|
cch += wcslen( pds->aDsSelection[ idx ].pwzName ) + 2; // EOS plus the ';'
|
|
psz = (WCHAR *) TraceReAlloc( psz, cch * sizeof( WCHAR ), HEAP_ZERO_MEMORY );
|
|
if ( psz == NULL )
|
|
{
|
|
goto OutOfMemory;
|
|
} // if:
|
|
|
|
wcscat( psz, pds->aDsSelection[ idx ].pwzName );
|
|
wcscat( psz, L"," );
|
|
} // for:
|
|
|
|
//
|
|
// Remove the last trailing comma ','
|
|
//
|
|
cch = wcslen( psz );
|
|
psz[ cch - 1 ] = L'\0';
|
|
Edit_SetText( hwndEdit, psz );
|
|
|
|
goto Cleanup;
|
|
|
|
OutOfMemory:
|
|
|
|
hr = THR( E_OUTOFMEMORY );
|
|
|
|
Cleanup:
|
|
|
|
if ( pds != NULL )
|
|
{
|
|
GlobalUnlock( stgmedium.hGlobal );
|
|
} // if:
|
|
|
|
if ( stgmedium.hGlobal != NULL )
|
|
{
|
|
ReleaseStgMedium( &stgmedium );
|
|
} // if:
|
|
|
|
TraceFree( psz );
|
|
|
|
HRETURN( hr );
|
|
|
|
} //*** CSelNodesPage::HrGetSelections()
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// static
|
|
// CALLBACK
|
|
// CSelNodesPage::S_DlgProc
|
|
//
|
|
// Description:
|
|
// Dialog proc for this page.
|
|
//
|
|
// Arguments:
|
|
// hDlgIn
|
|
// MsgIn
|
|
// wParam
|
|
// lParam
|
|
//
|
|
// Return Values:
|
|
// FALSE
|
|
// Other LRESULT values.
|
|
//
|
|
// Remarks:
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
INT_PTR
|
|
CALLBACK
|
|
CSelNodesPage::S_DlgProc(
|
|
HWND hDlgIn,
|
|
UINT MsgIn,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
)
|
|
{
|
|
// Don't do TraceFunc because every mouse movement
|
|
// will cause this function to be called.
|
|
|
|
WndMsg( hDlgIn, MsgIn, wParam, lParam );
|
|
|
|
LRESULT lr = FALSE;
|
|
|
|
CSelNodesPage * pPage = reinterpret_cast< CSelNodesPage *> ( GetWindowLongPtr( hDlgIn, GWLP_USERDATA ) );
|
|
|
|
if ( MsgIn == WM_INITDIALOG )
|
|
{
|
|
Assert( lParam != NULL );
|
|
|
|
PROPSHEETPAGE * ppage = reinterpret_cast< PROPSHEETPAGE * >( lParam );
|
|
SetWindowLongPtr( hDlgIn, GWLP_USERDATA, (LPARAM) ppage->lParam );
|
|
pPage = reinterpret_cast< CSelNodesPage * >( ppage->lParam );
|
|
pPage->m_hwnd = hDlgIn;
|
|
}
|
|
|
|
if ( pPage != NULL )
|
|
{
|
|
Assert( hDlgIn == pPage->m_hwnd );
|
|
|
|
switch( MsgIn )
|
|
{
|
|
case WM_INITDIALOG:
|
|
lr = pPage->OnInitDialog( hDlgIn );
|
|
break;
|
|
|
|
case WM_NOTIFY:
|
|
lr = pPage->OnNotify( wParam, reinterpret_cast< LPNMHDR >( lParam ) );
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
lr= pPage->OnCommand( HIWORD( wParam ), LOWORD( wParam ), (HWND) lParam );
|
|
break;
|
|
|
|
// no default clause needed
|
|
} // switch: message
|
|
} // if: there is a page associated with the window
|
|
|
|
return lr;
|
|
|
|
} //*** CSelNodesPage::S_DlgProc()
|