Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

1619 lines
41 KiB

/**********************************************************************/
/** Microsoft Windows/NT **/
/** Copyright(c) Microsoft Corp., 1991 **/
/**********************************************************************/
/*
NCPDMAIN.CXX: Windows/NT Network Control Panel Applet;
Main dialog presentation module.
FILE HISTORY:
DavidHov 10/9/91 Created
DavidHov 07/24/92 Removed server service checkboxes;
added support for Update button.
*/
#include "pchncpa.hxx"
#if !defined(_CFRONT_PASS_)
#pragma hdrstop // This file creates the PCH
#endif
// Input parameter used to just run bindings algorithm.
static const TCHAR * pszParamBindOnly = SZ("BINDONLY") ;
REG_LISTBOX :: REG_LISTBOX ( OWNER_WINDOW * powin, CID cid )
: STRING_LISTBOX( powin, cid ),
_pcdlList( NULL )
{
}
REG_LISTBOX :: ~ REG_LISTBOX ()
{
delete _pcdlList ;
}
APIERR REG_LISTBOX :: Fill ( COMPONENT_DLIST * pcdlList )
{
Drain();
_pcdlList = pcdlList ;
APIERR err = NERR_Success ;
INT cItems = _pcdlList->QueryNumElem() ;
NLS_STR nlsName,
nlsDesc ;
for ( INT cItem = 0 ; cItem < cItems ; cItem++ )
{
err = _pcdlList->QueryInfo( cItem, & nlsName, & nlsDesc ) ;
if ( err )
break ;
AddItem( nlsDesc ) ;
}
return err ;
}
VOID REG_LISTBOX :: Drain ()
{
DeleteAllItems() ;
delete _pcdlList ;
_pcdlList = NULL ;
}
// Return a pointer to the selected element in the REG_LISTBOX
REG_KEY * REG_LISTBOX :: QuerySelComponent ()
{
INT iSel = QueryCurrentItem() ;
return iSel >= 0 ? _pcdlList->QueryNthItem( iSel ) : NULL ;
}
DLG_REG_LIST_GROUP :: DLG_REG_LIST_GROUP
( NCPA_DIALOG * pdlgNCPA,
REG_LISTBOX & rlb1,
REG_LISTBOX & rlb2,
SLE & sleDescription,
SLT & sltDescStatic,
PUSH_BUTTON & butnConfigure,
PUSH_BUTTON & butnRemove,
PUSH_BUTTON & butnUpdate,
REGISTRY_MANAGER & regMgr )
: _pdlgNCPA( pdlgNCPA ),
_rlb1( rlb1 ),
_rlb2( rlb2 ),
_sleDescription( sleDescription ),
_sltDescStatic( sltDescStatic ),
_butnConfigure( butnConfigure ),
_butnRemove( butnRemove ),
_butnUpdate( butnUpdate ),
_prnDescription( NULL ),
_regMgr( regMgr ),
_fFilled( FALSE )
{
_rlb1.SetGroup( this ) ;
_rlb2.SetGroup( this ) ;
ResetDescription( NULL );
}
DLG_REG_LIST_GROUP :: ~ DLG_REG_LIST_GROUP ()
{
ResetDescription( NULL ) ;
}
BOOL DLG_REG_LIST_GROUP :: QueryUserAdmin()
{
return _pdlgNCPA->QueryUserAdmin();
}
APIERR DLG_REG_LIST_GROUP :: OnUserAction
( CONTROL_WINDOW * pcw, const CONTROL_EVENT & cEvent )
{
if ( cEvent.QueryMessage() == WM_COMMAND
&& cEvent.QueryCode() == LBN_SELCHANGE )
{
REG_LISTBOX * prlbOther = pcw == & _rlb1 ? & _rlb2 : & _rlb1 ;
// Guarantee that only one listbox has a selection.
prlbOther->RemoveSelection() ;
// Change the description SLE; handle alteration.
ResetDescription( QuerySelComponent() ) ;
}
return NERR_Success ;
}
// Return a pointer to the selected element in either listbox.
REG_KEY * DLG_REG_LIST_GROUP :: QuerySelComponent ()
{
REG_KEY * prnNode = _rlb1.QuerySelComponent() ;
if ( prnNode == NULL )
prnNode = _rlb2.QuerySelComponent() ;
return prnNode ;
}
// Return TRUE if the Adapters list has the current selection
BOOL DLG_REG_LIST_GROUP :: QueryAdapterListSelected ()
{
return _rlb2.QuerySelComponent() != NULL ;
}
// Drain the listboxes, erase the description.
APIERR DLG_REG_LIST_GROUP :: Drain ()
{
ResetDescription( NULL ) ;
_rlb1.SetRedraw( FALSE ) ;
_rlb2.SetRedraw( FALSE ) ;
_rlb1.Drain();
_rlb2.Drain();
_rlb1.SetRedraw( TRUE ) ;
_rlb2.SetRedraw( TRUE ) ;
_rlb1.Invalidate( TRUE ) ;
_rlb2.Invalidate( TRUE ) ;
_fFilled = FALSE ;
return 0 ;
}
// Reconstruct the listboxes
APIERR DLG_REG_LIST_GROUP :: Refill ()
{
APIERR err, err2 ;
REG_KEY * prkSelection ;
REG_LISTBOX * prlbSelected ;
BOOL fIncludeHidden = FALSE ;
#if defined(DEBUG)
if ( NCPA_DBG_FLAG_ON( _pdlgNCPA->QueryDebugFlags(), NCPA_DBGCTL_NO_HIDDEN ) )
{
fIncludeHidden = TRUE ;
}
#endif
ResetDescription( NULL ) ;
_rlb1.SetRedraw( FALSE ) ;
_rlb2.SetRedraw( FALSE ) ;
_rlb1.Drain();
_rlb2.Drain();
err = _rlb1.Fill( _regMgr.ListOfProducts( fIncludeHidden ) ) ;
err2 = _rlb2.Fill( _regMgr.ListOfAdapters( fIncludeHidden ) ) ;
if ( err == 0 )
err = err2 ;
// Select the first adapter if there is one; if not,
// select the first software compoent.
prlbSelected = & _rlb2 ;
prkSelection = _rlb2.QueryComponentList()->QueryNthItem( 0 ) ;
if ( prkSelection == NULL )
{
prlbSelected = & _rlb1 ;
prkSelection = _rlb1.QueryComponentList()->QueryNthItem( 0 ) ;
}
if ( prkSelection )
{
ResetDescription( prkSelection ) ;
prlbSelected->SelectItem( 0 ) ;
}
_rlb1.SetRedraw( TRUE ) ;
_rlb2.SetRedraw( TRUE ) ;
_rlb1.Invalidate( TRUE ) ;
_rlb2.Invalidate( TRUE ) ;
_fFilled = TRUE ;
return err ;
}
// There's a new entry for the Description SLE. See if
// the old entry has changed, and alter it if so.
APIERR DLG_REG_LIST_GROUP :: ResetDescription ( REG_KEY * prnNewSel )
{
APIERR err = 0, // Error from setting prior string
err2 = 0 ; // Error from getting next string
if ( prnNewSel != _prnDescription )
{
TCHAR * pchDesc = NULL ;
NLS_STR nlsDesc ;
if ( err = nlsDesc.QueryError() )
return err ;
// If we had a desription, check to see if it has changed.
if ( _prnDescription )
{
err = _sleDescription.QueryText( & nlsDesc ) ;
if ( err == 0 && nlsDesc != _nlsDescription )
{
err = _regMgr.SetValueString( _prnDescription,
RGAS_COMPONENT_DESC,
nlsDesc.QueryPch() ) ;
}
}
_sleDescription.SetText( SZ("") ) ;
if ( (_prnDescription = prnNewSel) != NULL )
{
_sleDescription.Enable( QueryUserAdmin() ) ;
_sltDescStatic.Enable( QueryUserAdmin() ) ;
err2 = _regMgr.QueryValueString( prnNewSel,
RGAS_COMPONENT_DESC,
& pchDesc ) ;
if ( ! err2 )
{
_nlsDescription = pchDesc ;
if ( _nlsDescription.QueryError() == 0 )
{
_prnDescription = prnNewSel ;
_sleDescription.SetText( _nlsDescription ) ;
}
}
else
{
_nlsDescription = SZ("") ;
}
delete pchDesc ;
}
}
if ( _prnDescription == NULL )
{
_sleDescription.Enable( FALSE ) ;
_sltDescStatic.Enable( FALSE ) ;
}
_butnConfigure.Enable( QueryUserAdmin() && _prnDescription != NULL ) ;
_butnRemove.Enable( QueryUserAdmin() && _prnDescription != NULL ) ;
_butnUpdate.Enable( QueryUserAdmin() && _prnDescription != NULL ) ;
return err ? err : err2 ;
}
static void alterWindowStyle (
HWND hwnd,
LPARAM lStyle,
BOOL fSet = TRUE )
{
LPARAM lStyleSet = ::GetWindowLong( hwnd, GWL_STYLE ) ;
if ( fSet )
lStyleSet |= lStyle ;
else
lStyleSet &= ~ lStyle ;
::SetWindowLong( hwnd, GWL_STYLE, lStyleSet ) ;
}
static void alterWindowStyle (
CONTROL_WINDOW * pwCtl,
LPARAM lStyle,
BOOL fSet = TRUE )
{
alterWindowStyle( pwCtl->QueryHwnd(), lStyle, fSet ) ;
}
/*******************************************************************
NAME: NCPA_DIALOG :: NCPA_DIALOG
SYNOPSIS: Main dialog constructor
ENTRY: nothing
EXIT: normal for BASE object
RETURNS: nothing
NOTES:
HISTORY:
********************************************************************/
NCPA_DIALOG :: NCPA_DIALOG (
HWND hwndOwner,
BOOL fMainInstall,
const TCHAR * pszInstallParms )
: DIALOG_WINDOW( DLG_NM_NCPA, hwndOwner ),
_timer( this, NCPA_POLLING_INTERVAL, FALSE ),
_pszInstallParms( pszInstallParms ),
_sltDomain( this, IDC_MAIN_DOMAIN_NAME ),
_sltDomainLabel( this, IDC_MAIN_SLT_DOMAIN ),
_sltComputer( this, IDC_MAIN_COMPUTER_NAME ),
_sltOverlay( this, IDC_MAIN_OVERLAY ),
_rlbComponents( this, IDC_MAIN_LIST_PROTOCOLS ),
_rlbCards( this, IDC_MAIN_LIST_CARDS ),
_sltDescStatic( this, IDC_MAIN_STATIC_DESC ),
_sleDescription( this, IDC_MAIN_EDIT_DESCRIPTION, 256 ),
_butnCancel( this, IDCANCEL ),
_butnBindings( this, IDC_MAIN_BUTN_BINDINGS ),
_butnDomain( this, IDC_MAIN_BUTN_DOMAIN ),
_butnComputer( this, IDC_MAIN_BUTN_COMPUTERNAME ),
_butnProviders( this, IDC_MAIN_BUTN_PROVIDERS ),
_butnConfigure( this, IDC_MAIN_BUTN_CONFIGURE ),
_butnAdd( this, IDC_MAIN_BUTN_ADD ),
_butnAddCard( this, IDC_MAIN_BUTN_ADD_CARD ),
_butnRemove( this, IDC_MAIN_BUTN_REMOVE ),
_butnUpdate( this, IDC_MAIN_BUTN_UPDATE ),
_bindery( fMainInstall, pszInstallParms ),
_drlGrp( this, _rlbComponents, _rlbCards,
_sleDescription, _sltDescStatic,
_butnConfigure, _butnRemove, _butnUpdate,
_bindery )
{
// CODEWORK :: these items are init'ed here because C8 dies
// with "too many open parentheses" otherwise.
_hControlPanel = hwndOwner;
_pdmgrDomain = NULL ;
_psvcManager = NULL ;
_pnscControl = NULL ;
_pnscCtrlSave = NULL ;
_lastErr = 0 ;
_lastApiErr = 0 ;
_lastDeferredErr = 0 ;
_ptddacl = NULL ;
_pOffscreenDialog = NULL ;
_fMainInstall = fMainInstall ;
_fWinNt = TRUE ;
_fAdmin = FALSE ;
_fConfigLocked = FALSE ;
_fRebootRecommended = FALSE ;
_fRefill = FALSE ;
_fAuto = FALSE ;
_eiMode = NCPA_IMODE_NONE ;
_dwDebugFlags = 0 ;
if ( QueryError() )
return ; // Construction failure
if ( _bindery.QueryError() )
{ // BINDERY Construction failure
ReportError( _bindery.QueryError() ) ;
return ;
}
#if defined(TRACE)
// Drag in the debugging flags, if any.
if ( _bindery.GetNcpaValueNumber( NCPA_DEBUG_CONTROL, & _dwDebugFlags ) == 0 )
{
// Found the value; indicate that the flags are active.
_dwDebugFlags |= NCPA_DBGCTL_ACTIVE ;
}
#endif
// Enable the timer; tick...tick...tick...
_timer.Enable( TRUE ) ;
// Set the current directory to %SystemRoot%\SYSTEM.
SetDirectory() ;
// Determine whether the user can access the full scope or any
// information whatever
if ( ! EstablishUserAccess() )
{
ReportError( _lastErr ) ;
return ;
}
// Since EstablishUserAccess() was successful, we now have a
// DOMAIN_MANAGER at our disposal.
// If this is main installation, alter the dialog face to
// overlay the help text on top of the domain and machine name.
// Otherwise, if the user is admin, obtain the additional
// data.
BOOL fGetBasicFields = TRUE ;
if ( _fMainInstall )
{
// Get the installation mode.
_eiMode = QueryInstallMode() ;
RenameCancelToClose() ;
// Since we cannot rely on the size or position of the parent
// window, center this dialog in the physical screen.
INT cx = ::GetSystemMetrics( SM_CXSCREEN ) / 2 ;
INT cy = ::GetSystemMetrics( SM_CYSCREEN ) / 2 ;
INT cWidth, cHeight ;
QuerySize( & cWidth, & cHeight ) ;
XYPOINT xyNew( cx - (cWidth/2), cy - (cHeight/2) ) ;
// Don't repaint, since DIALOG_WINDOW will do that immediately
// upon return.
SetPos( xyNew, FALSE ) ;
//
// Now we have to play with the controls. There are two distinct
// "installation" states: normal and retry. In normal installation,
// we hide the "change computername" and "change domain/workgroup"
// controls and cover them with a text control. In retry mode,
// we allow access to the "change computername" control but
// not the "change domain/workgroup" controls.
//
if ( _eiMode == NCPA_IMODE_RETRY )
{
// Disable all domain/workgroup related controls.
_butnDomain.Enable( FALSE ) ;
_sltDomainLabel.Enable( FALSE ) ;
_sltDomain.Enable( FALSE ) ;
}
else
{
HWND hwnd ;
NLS_STR nlsMsg ;
// If not "retry", hide the upper controls
fGetBasicFields = FALSE ;
alterWindowStyle( & _sltComputer, WS_VISIBLE, FALSE ) ;
alterWindowStyle( & _butnDomain, WS_VISIBLE, FALSE ) ;
alterWindowStyle( & _butnComputer, WS_VISIBLE, FALSE ) ;
alterWindowStyle( & _sltDomainLabel, WS_VISIBLE, FALSE ) ;
alterWindowStyle( & _sltDomain, WS_VISIBLE, FALSE ) ;
if ( hwnd = ::GetDlgItem( QueryHwnd(), IDC_MAIN_SLT_COMPUTER ) )
alterWindowStyle( hwnd, WS_VISIBLE, FALSE ) ;
// Build and reveal the help text.
if ( ::ConcatMsgs( & nlsMsg, IDS_NCPA_OVERLAY1 ) == 0 )
_sltOverlay.SetText( nlsMsg ) ;
alterWindowStyle( & _sltOverlay, WS_VISIBLE ) ;
}
}
if ( fGetBasicFields )
{
// Read in the basic LANMan/NT information
HandleBasicFields() ;
_lastErr = 0 ;
}
// Drag in the bindings information
if ( _bindery.QueryBindState() == BND_NOT_LOADED )
{
if ( LoadBindings() )
{
_bindery.SetBindState( BND_CURRENT ) ;
}
else
{
#if defined(DEBUG)
DBGEOL( SZ("NCPA/MAIN: bind info load failure; error ")
<< _lastErr ) ;
#endif
_bindery.SetBindState( BND_OUT_OF_DATE ) ;
_lastErr = 0 ;
SetReboot() ;
}
}
if ( _bindery.QueryCfgDirty() )
{
SetReboot() ;
}
// Fill the two list boxes
_drlGrp.Refill() ;
// Disable the Providers button if the number of providers is < 2.
if ( _fMainInstall || ((QueryNumProviders() < 2) || (QueryNumPrintProviders() < 2)))
{
_butnProviders.Enable( FALSE ) ;
}
if ( !_fMainInstall && !QueryUserAdmin() )
{
// Disable any modifications, installations, etc.
_butnComputer.Enable( FALSE ) ;
_butnDomain.Enable( FALSE ) ;
_butnBindings.Enable( FALSE ) ;
_butnProviders.Enable( FALSE ) ;
_butnConfigure.Enable( FALSE ) ;
_butnAdd.Enable( FALSE ) ;
_butnAddCard.Enable( FALSE );
_butnRemove.Enable( FALSE );
_butnUpdate.Enable( FALSE );
_sleDescription.Enable( FALSE );
}
// End of code from OnExpand()
}
ULONG NCPA_DIALOG :: QueryHelpContext ()
{
return HC_NCPA_MAIN_DIALOG ;
}
/*******************************************************************
NAME: NCPA_DIALOG :: SetReboot
SYNOPSIS: Set the reboot flag on if parameter is TRUE; has
no effect if reboot is already on. Once on,
reboot flag cannot be reset.
ENTRY: BOOL fOn
EXIT:
RETURNS: BOOL new value of reboot flag.
NOTES:
HISTORY:
********************************************************************/
BOOL NCPA_DIALOG :: SetReboot ( BOOL fOn )
{
BOOL fWasOn = _fRebootRecommended ;
_fRebootRecommended = fOn ;
if ( fOn && ! fWasOn )
{
TRACEEOL(SZ("NCPA/MAIN: setting reboot"));
RenameCancelToClose() ;
}
return _fRebootRecommended ;
}
/*******************************************************************
NAME: NCPA_DIALOG :: SetDirectory
SYNOPSIS: Establish proper directory for NCPA to function
ENTRY: nothing
EXIT: nothing
RETURNS: BOOL if successful
NOTES: The Control Panel appears to consider %Systemroot%
to be its home location. For SETUP to execute,
we need %Systemroot\SYSTEM.
HISTORY:
********************************************************************/
BOOL NCPA_DIALOG :: SetDirectory ()
{
TCHAR achPath [MAX_PATH] ;
DWORD cchPath = ::GetCurrentDirectory( sizeof achPath, achPath ) ;
if ( cchPath > 0 && cchPath < sizeof achPath )
{
_nlsCurrentDirectory = achPath ;
}
cchPath = ::GetSystemDirectory( achPath, sizeof achPath ) ;
if ( cchPath > 0 && cchPath < sizeof achPath )
{
TRACEEOL( SZ("NCPA/NCPA: Current directory set to: ")
<< achPath );
return ::SetCurrentDirectory( achPath ) ;
}
return FALSE ;
}
/*******************************************************************
NAME: NCPA_DIALOG :: ResetDirectory
SYNOPSIS:
ENTRY: nothing
EXIT: nothing
RETURNS: TRUE if successful
NOTES: returns the current directory to where it was
when the dialog opened
HISTORY:
********************************************************************/
BOOL NCPA_DIALOG :: ResetDirectory ()
{
if ( _nlsCurrentDirectory.QueryTextLength() != 0 )
{
TRACEEOL( SZ("NCPA/NCPA: Reset current directory to: ")
<< _nlsCurrentDirectory.QueryPch() );
return ::SetCurrentDirectory( (TCHAR *) _nlsCurrentDirectory.QueryPch() ) ;
}
return FALSE ;
}
/*******************************************************************
NAME: NCPA_DIALOG::MayRun
SYNOPSIS: Override of standard MayRun() member.
If we're installing in "express" mode,
ENTRY: Nothing
EXIT: TRUE if NCPA dialog is to be presented in normal form.
RETURNS: APIERR
NOTES: If we're INSTALLING but we're not in CUSTOM mode,
or if we've been explicity called for "run bindings only"
then just flash the dialog, run the bindings algorithm,
store the bindings and leave. The user is not allowed
to fiddle with the product ensemble in this mode.
In addition, if we're not installing, find out if
the LanmanWorkstation service is installed and install
standard MS NT Networking if the user so desires.
HISTORY: DavidHov 4/20/92 Created
********************************************************************/
BOOL NCPA_DIALOG :: MayRun ()
{
BOOL fResult = TRUE ;
BOOL fBindOnly = CheckBoolSetupParameter( pszParamBindOnly ) ;
if ( _fMainInstall || fBindOnly )
{
// Set the "bindings out of date" flag to force reconfiguration
if ( fBindOnly || _eiMode != NCPA_IMODE_RETRY )
_bindery.SetBindState( BND_OUT_OF_DATE ) ;
// Set the "autopilot" flag if we're not supposed to interact
// with the user.
_fAuto = fBindOnly || _eiMode == NCPA_IMODE_EXPRESS ;
// If we're just being called for rebind, clear any left-over
// reboot flag (due to existence of ConfigChanged key).
if ( fBindOnly )
{
SetReboot( FALSE ) ;
}
// If this is a RETRY, stop the network.
if ( _eiMode == NCPA_IMODE_RETRY )
{
AUTO_CURSOR cursAuto ; // put up the eternal hourglass
TRACEEOL( SZ("NCPA/MAIN: stopping the network") );
_bindery.StopNetwork() ;
TRACEEOL( SZ("NCPA/MAIN: network stop complete.") );
}
}
if ( _fAuto )
{
// Express Mode:
// Complete all necessary operations;
// compute bindings; do INF callouts, etc.
#ifdef GLOBAL_LOCK
ConfigLock( TRUE ) ;
#endif // GLOBAL_LOCK
Close( FALSE ) ;
// Suppress real dialog execution
fResult = FALSE ;
_lastDeferredErr = 0 ;
}
else
if ( QueryUserAdmin() )
{
// Check to see if LanmanWorkstation service exists.
// Only display the main dialog if we DON'T launch
// NT LANManager installation.
if ( CheckForAndInstallLanManager() )
{
fResult = FALSE ;
_lastDeferredErr = 0 ;
SetReboot( FALSE ) ;
Dismiss( _lastErr = IDS_NCPA_PROCESS_LAUNCH ) ;
}
}
// Display any minor construction error
if ( _lastDeferredErr )
{
DoMsgPopup() ;
}
return fResult ;
}
/*******************************************************************
NAME: NCPA_DIALOG::Close
SYNOPSIS: Handle all exit paths out of this dialog.
ENTRY: BOOL TRUE if Cancel/Close button was used
EXIT:
RETURNS: BOOL to return to window handler
NOTES:
The state of the network bindings is checked. If
the ensemble of products has changed or the user has
reviewed the bindings, the Cancel button is now
titled Close.
If the bindings have been reviewed, they have already
been computed and can be stored straightaway; otherwise,
they must be computed.
Note that we don't check or obtain the configuration
lock. This should already have been done by the
function which instigated the change. The lock is
released by the dialog's destructor.
HOW BINDINGS REVIEW WORKS:
When the product ensemble has changed, we must store
the recomputed bindings into the Registry via
StoreBindings(). This member function will also
handle the process of automatic bindings review by calling
RunBindingsReview().
FinishBindings() is then called to snapshot the state of the
bindings for quick review, and the request to close the dialog
is finally honored.
HISTORY:
********************************************************************/
BOOL NCPA_DIALOG :: Close ( BOOL fCancel )
{
// If we started the separate process to install the network,
// don't put up the "reboot now" popup. Otherwise, if
// this is not main installation, prompt the user.
if ( _lastErr == IDS_NCPA_PROCESS_LAUNCH )
{
_fRebootRecommended = FALSE;
}
else
if ( ! (_fMainInstall || _fAuto) )
{
// Set the "reboot recommended" flag on if things have changed;
// leave it on if it's already on.
_fRebootRecommended |= _bindery.QueryBindState() > BND_OUT_OF_DATE_NO_REBOOT ;
}
switch ( _bindery.QueryBindState() )
{
case BND_NOT_LOADED:
case BND_LOADED:
case BND_CURRENT:
// The dialog execution has NOT changed the overall state of
// the product ensemble. Return "Cancelled" to the caller
// if this is the Cancel button.
break ;
case BND_OUT_OF_DATE_NO_REBOOT:
case BND_OUT_OF_DATE:
// Product ensemble has changed. Recompute the bindings
// and fall thru to apply them to the Registry
if ( !QueryUserAdmin())
{
break;
}
if ( ! ComputeBindings() )
{
// Since the binding operation has failed, suppress
// the reboot prompting.
DoMsgPopup() ;
break ;
}
RepaintNow() ;
case BND_RECOMPUTED:
case BND_REVIEWED:
case BND_UPDATED:
// Write the bindings to the Registry, call interested parties,
// write the bindings state value, etc.
if ( !QueryUserAdmin())
{
break;
}
if ( ! StoreBindings() )
{
DoMsgPopup() ;
}
RepaintNow() ;
case BND_AUTO_REVIEW_DONE:
// Generate and write our saved data structure into the Registry
if ( !QueryUserAdmin())
{
break;
}
FinishBindings();
break ;
default:
TRACEEOL( SZ("NCPA/DIALOG: Invalid bind state during close: ")
<< (long) _bindery.QueryBindState() ) ;
break ;
}
TRACEEOL( SZ("NCPA/DIALOG: Main NCPA dialog dismissed") ) ;
Dismiss( _lastErr ) ;
return TRUE ;
}
BOOL NCPA_DIALOG :: OnOK ()
{
return Close( FALSE ) ;
}
BOOL NCPA_DIALOG :: OnCancel ()
{
return Close( TRUE ) ;
}
/*******************************************************************
NAME: NCPA_DIALOG::RenameCancelToClose
SYNOPSIS: The effects of this dialog are now irreversible.
Change the name of the Cancel button to Close to
indicate this.
ENTRY: nothing
EXIT: nothing
RETURNS: APIERR (hopefully not)
NOTES:
HISTORY:
********************************************************************/
APIERR NCPA_DIALOG :: RenameCancelToClose()
{
NLS_STR nlsButton ;
APIERR err ;
if ( (err = nlsButton.QueryError()) == 0 )
{
if ( (err = nlsButton.Load( IDS_NCPA_NAME_CLOSE )) == 0 )
{
_butnCancel.SetText( nlsButton ) ;
_butnCancel.Invalidate() ;
}
}
return err ;
}
// BUGBUG: this should be a member function
static void setFocusOnOk ( DIALOG_WINDOW * pDlg )
{
::SetFocus( ::GetDlgItem( pDlg->QueryHwnd(), IDOK ) ) ;
}
/*******************************************************************
NAME: NCPA_DIALOG::OnCommand
SYNOPSIS: Handle dialog-based events.
ENTRY: const CONTROL_EVENT & event
the event which has occurred
EXIT: TRUE if the event was handled
RETURNS:
NOTES: The configuration lock is obtained only when
needed, and kept until the dialog is dismissed.
HISTORY:
********************************************************************/
BOOL NCPA_DIALOG::OnCommand ( const CONTROL_EVENT & event )
{
BOOL fDefault = TRUE ;
BOOL fResult = FALSE ;
BOOL fOk = TRUE ;
REG_KEY * prnComponent = NULL ;
static BOOL fDescHasFocus = FALSE ;
switch ( event.QueryCid() )
{
// Rename Cancel to Close whenever the description is updated.
// Note that we only check when the control has focus;
// otherwise, we'd be reacting to programmatic changes in
// its contents.
case IDC_MAIN_EDIT_DESCRIPTION:
switch ( event.QueryCode() )
{
case EN_CHANGE:
if ( fDescHasFocus )
{
RenameCancelToClose();
}
break ;
case EN_SETFOCUS:
fDescHasFocus = TRUE ;
break ;
case EN_KILLFOCUS:
fDescHasFocus = FALSE ;
break ;
}
break ;
case IDC_MAIN_BUTN_DOMAIN:
fResult = TRUE ;
fDefault = FALSE ;
#ifdef GLOBAL_LOCK
fOk = ConfigLock( TRUE ) && RunDomainDialog() ;
#endif // GLOBAL_LOCK
fOk = RunDomainDialog() ;
break ;
case IDC_MAIN_BUTN_COMPUTERNAME:
fResult = TRUE ;
fDefault = FALSE ;
#ifdef GLOBAL_LOCK
fOk = ConfigLock( TRUE ) && RunComputerNameDialog() ;
#endif // GLOBAL_LOCK
fOk = RunComputerNameDialog() ;
if ( _fRebootRecommended )
{
// Disable the Domain Change... button if the computername
// has been changed.
_butnDomain.Enable( FALSE );
}
break;
case IDC_MAIN_BUTN_PROVIDERS:
fResult = TRUE ;
fDefault = FALSE ;
#ifdef GLOBAL_LOCK
fOk = ConfigLock( TRUE ) && RunProvidersDialog() ;
#endif // GLOBAL_LOCK
fOk = RunProvidersDialog() ;
break ;
case IDC_MAIN_BUTN_BINDINGS:
fResult = TRUE ;
fDefault = FALSE ;
#ifdef GLOBAL_LOCK
if ( ! (fOk = ConfigLock( TRUE )) )
break ;
#endif // GLOBAL_LOCK
if ( _bindery.QueryCompAssoc() == NULL
|| _bindery.QueryBindState() == BND_OUT_OF_DATE
|| _bindery.QueryBindState() == BND_OUT_OF_DATE_NO_REBOOT )
{
// Rerun the binding algorithm and update the Registry.
if ( ! (fOk = ComputeBindings() && StoreBindings( FALSE )) )
{
break ;
}
}
// Bindings are marked as "changed" if either we have
// regenerated them or the user has altered them.
if ( RunBindingsDialog() )
{
_bindery.SetBindState( BND_REVIEWED );
}
break ;
case IDC_MAIN_BUTN_ADD_CARD:
#ifdef GLOBAL_LOCK
if ( ! (fOk = ConfigLock( TRUE )) )
break ;
#endif // GLOBAL_LOCK
//
// Make sure we can lock the service controller database before trying to install. This ensures
// that the srevice controller is not still autostarting.
//
if ( _lastErr = _psvcManager->Lock() )
{
fOk = FALSE;
break ;
}
_psvcManager->Unlock();
if ( _bindery.QueryBindState() == BND_REVIEWED )
{
DoWarning( IDS_NCPA_BINDINGS_REVIEW_LOST ) ;
}
setFocusOnOk( this ) ;
fOk = RunAddCard() || _lastErr == IDS_NCPA_SETUP_CANCELLED ;
fResult = TRUE ;
fDefault = FALSE ;
break ;
case IDC_MAIN_BUTN_ADD:
#ifdef GLOBAL_LOCK
if ( ! (fOk = ConfigLock( TRUE )) )
break ;
#endif // GLOBAL_LOCK
//
// Make sure we can lock the service controller database before trying to install. This ensures
// that the srevice controller is not still autostarting.
//
if ( _lastErr = _psvcManager->Lock() )
{
fOk = FALSE;
break ;
}
_psvcManager->Unlock();
if ( _bindery.QueryBindState() == BND_REVIEWED )
{
DoWarning( IDS_NCPA_BINDINGS_REVIEW_LOST ) ;
}
setFocusOnOk( this ) ;
fOk = RunAddComponent() || _lastErr == IDS_NCPA_SETUP_CANCELLED ;
fResult = TRUE ;
fDefault = FALSE ;
break ;
case IDC_MAIN_LIST_PROTOCOLS:
case IDC_MAIN_LIST_CARDS:
// A double-click in one of the component listboxes is
// a request to reconfigure the component.
if ( event.QueryCode() != LBN_DBLCLK || !QueryUserAdmin() )
break ;
// Fall thru to get selection and reconfigure...
case IDC_MAIN_BUTN_REMOVE:
// Re-check of CID required due to fall thru above
if ( event.QueryCid() == IDC_MAIN_BUTN_REMOVE )
{
if ( ::MsgPopup( this,
IDS_NCPA_REMOVE_WARNING,
MPSEV_WARNING,
MP_YESNO,
MP_NO ) != IDYES )
break ;
}
case IDC_MAIN_BUTN_UPDATE:
case IDC_MAIN_BUTN_CONFIGURE:
// Lock the configuration and run the configurator...
#ifdef GLOBAL_LOCK
if ( ! (fOk = ConfigLock( TRUE )) )
break ;
#endif // GLOBAL_LOCK
if ( _bindery.QueryBindState() == BND_REVIEWED )
{
DoWarning( IDS_NCPA_BINDINGS_REVIEW_LOST ) ;
}
if ( prnComponent = _drlGrp.QuerySelComponent() )
{
NCPA_CFG_FUNC ncfg = event.QueryCid() == IDC_MAIN_BUTN_UPDATE
? NCFG_UPDATE
: ( event.QueryCid() == IDC_MAIN_BUTN_REMOVE
? NCFG_REMOVE
: NCFG_CONFIGURE ) ;
setFocusOnOk( this ) ;
fOk = RunConfigurator( prnComponent, ncfg ) ;
}
fResult = TRUE ;
fDefault = FALSE ;
break ;
default:
break ;
}
if ( ! fOk )
{
DoMsgPopup() ;
}
if ( fDefault )
{
fResult = DIALOG_WINDOW::OnCommand( event ) ;
}
return fResult ;
}
/*******************************************************************
NAME: NCPA_DIALOG::Refill
and NCPA_DIALOG::Drain
SYNOPSIS: Refill the software and hardware components listboxes
ENTRY: Nothing
EXIT: Nothing
RETURNS: TRUE
NOTES: Note that although the methods associated with the
"expanded" controls exist before Expand() is called,
they are disabled and hidden.
HISTORY:
********************************************************************/
VOID NCPA_DIALOG :: Refill ()
{
TRACEEOL( SZ("NCPA/NCPA: Refill list box start...") );
// Things have changed; refill the component listboxes.
_drlGrp.Refill() ;
TRACEEOL( SZ("NCPA/NCPA: Refill list box end.") );
}
VOID NCPA_DIALOG :: Drain ()
{
TRACEEOL( SZ("NCPA/NCPA: Drain list boxes.") );
_drlGrp.Drain() ;
}
/*******************************************************************
NAME: NCPA_DIALOG::DoWarning
SYNOPSIS: Display a message box containing the last
error message generated. If no error, no
popup.
ENTRY: MSGID msgId IDS of message
BOOL fYesNo TRUE if user gets a choice
(Yes/No) or not (Ok only).
EXIT: Nothing
RETURNS: Result button value of ::MsgPopup
NOTES:
HISTORY:
********************************************************************/
INT NCPA_DIALOG :: DoWarning ( MSGID msgId, BOOL fYesNo )
{
UINT uButtons = fYesNo ? MP_YESNO : MP_OK,
uDefButton = fYesNo ? MP_YES : MP_OK ;
return ::MsgPopup( this,
msgId,
MPSEV_WARNING,
uButtons,
uDefButton ) ;
}
/*******************************************************************
NAME: NCPA_DIALOG::DoMsgPopup
SYNOPSIS: Display a message box containing the last
error message generated. If no error, no
popup.
ENTRY: BOOL fReset TRUE if _lastErr should be
reset to NERR_Success (0)
EXIT: Nothing
RETURNS: Result button value of ::MsgPopup
NOTES: This is a very special case routine. The caller
implicitly knows what behavior will occur based
upon the error code involved: warning, error,
number of buttons, default button, etc.
HISTORY: DavidHov 6/26/92 Changed to use parameterized "default
popup" in all cases.
********************************************************************/
INT NCPA_DIALOG :: DoMsgPopup ( BOOL fReset )
{
// Prepare default values for the "default popup".
INT iResult = 0 ;
BOOL fDefaultPopup = TRUE ;
BOOL fRegError = FALSE ;
const TCHAR * pszString = NULL ;
MSG_SEVERITY mpSev = MPSEV_ERROR ;
UINT uButtons = MP_OK,
uDefButton = MP_UNKNOWN ;
if ( _lastErr == 0 )
{
_lastErr = _lastDeferredErr ;
_lastDeferredErr = 0 ;
}
APIERR err = _lastErr ;
switch ( _lastErr )
{
case NO_ERROR:
case IDS_NCPA_SETUP_CANCELLED:
fDefaultPopup = FALSE ;
break ;
case ERROR_FILE_NOT_FOUND:
case ERROR_PATH_NOT_FOUND:
if ( _nlsMissingFile.QueryTextLength() > 0 )
{
err = IDS_NCPA_FILE_NOT_FOUND_STR ;
pszString = _nlsMissingFile.QueryPch() ;
}
else
{
err = IDS_NCPA_FILE_NOT_FOUND ;
}
break ;
// Registry errors
case ERROR_BADDB:
fRegError = TRUE ;
err = IDS_WINREG_BADDB ;
break ;
case ERROR_BADKEY:
fRegError = TRUE ;
err = IDS_WINREG_BADKEY ;
break ;
case ERROR_CANTOPEN:
fRegError = TRUE ;
err = IDS_WINREG_CANTOPEN ;
break ;
case ERROR_CANTREAD:
fRegError = TRUE ;
err = IDS_WINREG_CANTREAD ;
break ;
case ERROR_CANTWRITE:
fRegError = TRUE ;
err = IDS_WINREG_CANTWRITE ;
break ;
case IDS_NCPA_USER_SHOULD_REBOOT:
// User should reboot now. Ask her.
uButtons = MP_YESNO ;
mpSev = MPSEV_WARNING ;
uDefButton = MP_YES ;
break ;
default:
break ;
}
if ( fDefaultPopup )
{
if ( fRegError )
{
pszString = _bindery.QueryLastName().QueryPch() ;
}
if ( pszString )
{
iResult = ::MsgPopup( this,
err,
mpSev,
uButtons,
pszString,
uDefButton );
}
else
{
iResult = ::MsgPopup( this,
err,
mpSev,
uButtons,
uDefButton );
}
}
if ( fReset )
{
_nlsMissingFile = SZ("");
_lastErr = _lastApiErr = _lastDeferredErr = 0 ;
}
return iResult ;
}
/*******************************************************************
NAME: NCPA_DIALOG::LoadBindings
SYNOPSIS: Retrieve the last generation of binding information
from its Registry-pointed location. Handle
errors.
ENTRY: Nothing
EXIT: BOOL FALSE if failure (check _lastErr)
RETURNS: BOOL
NOTES: Any older results of bindings are discarded
HISTORY:
DavidHov 2/5/92 Created
********************************************************************/
BOOL NCPA_DIALOG :: LoadBindings ()
{
// Discard any old results
_bindery.Reset() ;
// Attempt to load bindings from the last cycle.
_lastErr = _bindery.LoadCompAssoc() ;
return _lastErr == 0 ;
}
/*******************************************************************
NAME: NCPA_DIALOG::StoreBindings
SYNOPSIS: Create a new version of the text file containing
bindings information.
ENTRY: There must be an active ARRAY_COMP_ASSOC.
EXIT: Nothing
RETURNS: BOOL FALSE if operation fails (see _lastErr).
NOTES: Write the binding and dependency information to
the Configuration Registry.
When complete, start the bindings review process.
See notes in NCPDINST.CXX and the NCPA_DIALOG::Close()
member for details.
HISTORY: DavidHov 2/5/92 Created
DavidHov 9/25/92 Added "fApplyBindings"
********************************************************************/
BOOL NCPA_DIALOG :: StoreBindings ( BOOL fApplyBindings )
{
AUTO_CURSOR cursAuto ; // put up the eternal hourglass
REQUIRE( _bindery.QueryCompAssoc() != NULL ) ;
_lastErr = 0 ;
// Write the bindings to the Registry if necessary
if ( _bindery.QueryBindState() < BND_UPDATED )
{
if ( (_lastErr = _bindery.ApplyBindings( _psvcManager )) == 0 )
{
_bindery.SetBindState( BND_UPDATED ) ;
}
}
// See if any error has occurred. If not, and we're asked
// to "apply bindings", release the configuration lock and
// run the bindings review cycle.
if ( _lastErr )
{
_lastApiErr = _lastErr ;
_lastErr = IDS_NCPA_SERVICE_DEPEND_FAILED ;
}
else
if ( fApplyBindings )
{
// In order to allow INFs to start services, we
// must unlock the Service Controller database now.
ConfigLock( FALSE ) ;
// Call out to the components which want to review their
// bindings, and to the final review INFs, if any.
// Note that RunBindingsRevuiew() sets the binding
// state to BND_AUTO_REVIEW_DONE.
cursAuto.TurnOff() ;
RunBindingsReview() ;
}
return _lastErr == 0 ;
}
/*******************************************************************
NAME: NCPA_DIALOG::FinishBindings
SYNOPSIS: Create a new version of the binding information
text structure attached to the NCPA's node.
ENTRY: There must be an active ARRAY_COMP_ASSOC!
EXIT: Nothing
RETURNS: BOOL FALSE if operation fails (see _lastErr).
NOTES:
HISTORY: DavidHov 2/5/92 Created
********************************************************************/
BOOL NCPA_DIALOG :: FinishBindings ()
{
AUTO_CURSOR cursAuto ; // put up the eternal hourglass
APIERR err = _bindery.RegenerateAllDependencies( _psvcManager ) ;
#if defined(TRACE)
if ( err )
{
TRACEEOL( SZ("NCPA/MAIN: RegenerateAllDependencies FAILED; error = ")
<< err ) ;
}
#endif
_lastErr = _bindery.StoreCompAssoc() ;
_bindery.SetBindState( BND_CURRENT ) ;
return _lastErr == 0 ;
}
/*******************************************************************
NAME: NCPA_DIALOG::ContinueEvenIfCfgDirty
SYNOPSIS: See if the configuration is "dirty" (in need of a
reboot). If so, warn the user and allow him to cancel
the operation.
ENTRY: Nothing
EXIT: Nothing
RETURNS: TRUE if operation should continue; i.e., configuration
is clean or user doesn't care.
NOTES:
HISTORY: DavidHov 3/5/93 Created
********************************************************************/
BOOL NCPA_DIALOG :: ContinueEvenIfCfgDirty ()
{
if ( ! _bindery.QueryCfgDirty() )
{
return TRUE ;
}
INT iResult = ::MsgPopup( this,
IDS_NCPA_WARN_CONFIG_DIRTY,
MPSEV_WARNING,
MP_YESNO,
MP_NO );
return iResult == IDYES ;
}
BOOL NCPA_DIALOG :: CheckBoolSetupParameter ( const TCHAR * pszParameter )
{
NLS_STR nlsTrue ;
BOOL fResult = FALSE ;
if ( FindSetupParameter( _pszInstallParms, pszParameter, & nlsTrue ) )
{
fResult = ::stricmpf( SZ("TRUE"), nlsTrue.QueryPch() ) == 0 ;
}
return fResult ;
}
// End of NCPDMAIN.CXX