mirror of https://github.com/lianthony/NT4.0
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.
1052 lines
25 KiB
1052 lines
25 KiB
/**********************************************************************/
|
|
/** Microsoft Windows NT **/
|
|
/** Copyright(c) Microsoft Corp., 1992 **/
|
|
/**********************************************************************/
|
|
/*
|
|
BindInit.cxx
|
|
|
|
OLDNAME: NCPAPBNDI.CXX:
|
|
|
|
Windows/NT Network Control Panel Applet
|
|
|
|
BINDERY Initialization.
|
|
|
|
|
|
FILE HISTORY:
|
|
DavidHov 3/22/92 Created
|
|
|
|
*/
|
|
|
|
#include "pch.hxx" // Precompiled header
|
|
#pragma hdrstop
|
|
|
|
#define BNDI_RULE_MAX_SIZE 100000
|
|
#define CR '\r'
|
|
#define LF '\n'
|
|
#define EF '\0x1a'
|
|
|
|
|
|
const TCHAR * pszDefaultSrcPath = SZ("A:\\") ;
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: BINDERY::GetTextResource
|
|
|
|
SYNOPSIS: Read the a TEXT resource from the resource fork
|
|
|
|
ENTRY:
|
|
|
|
EXIT:
|
|
|
|
RETURNS:
|
|
|
|
NOTES:
|
|
|
|
HISTORY:
|
|
|
|
********************************************************************/
|
|
CHAR * BINDERY :: GetTextResource ( const TCHAR * pchResName )
|
|
{
|
|
HRSRC hResource ;
|
|
HGLOBAL hRuleResource ;
|
|
CHAR * pszResult ;
|
|
INT cbSize ;
|
|
|
|
hResource = ::FindResource( g_hinst,
|
|
pchResName,
|
|
RGAS_RES_RULES_TYPE ) ;
|
|
if ( hResource == NULL )
|
|
return NULL ;
|
|
|
|
cbSize = ::SizeofResource( g_hinst, hResource ) ;
|
|
|
|
hRuleResource = ::LoadResource( g_hinst, hResource ) ;
|
|
|
|
if ( hRuleResource == NULL )
|
|
return NULL ;
|
|
|
|
// Note that text files are stored as CHAR by the Resource Compiler
|
|
// Do a C++-compatible "strdup". Allow for addition of
|
|
// another NUL character at the end of the buffer.
|
|
|
|
pszResult = new CHAR [ cbSize + (sizeof (CHAR) * 2) ] ;
|
|
|
|
if ( pszResult )
|
|
{
|
|
// Move the resource data to the new block
|
|
|
|
::memcpy( pszResult,
|
|
::LockResource( hRuleResource ),
|
|
cbSize ) ;
|
|
|
|
// Guarantee that there's no old-style EOF in the buffer
|
|
|
|
CHAR * pch = pszResult ;
|
|
INT cb ;
|
|
|
|
for ( cb = 0, pch = pszResult ; cb < cbSize ; cb++, pch++ )
|
|
{
|
|
if ( *pch == 0 || *pch == EF )
|
|
break ;
|
|
}
|
|
*pch = 0 ;
|
|
}
|
|
|
|
UnlockResource( hRuleResource ) ;
|
|
|
|
::FreeResource( hRuleResource ) ;
|
|
|
|
return pszResult ;
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: BINDERY::AddNcpaDefaultRulesValue
|
|
|
|
SYNOPSIS: Read the default rules TEXT resource from the resource
|
|
fork, convert it Unicode, demarcate its lines and
|
|
write the result to a REG_MULTI_SZ value called RawRules.
|
|
|
|
ENTRY:
|
|
|
|
EXIT:
|
|
|
|
RETURNS:
|
|
|
|
NOTES:
|
|
|
|
HISTORY:
|
|
|
|
********************************************************************/
|
|
APIERR BINDERY :: AddNcpaDefaultRulesValue ()
|
|
{
|
|
APIERR err = 0 ;
|
|
STRLIST slRules ;
|
|
NLS_STR * pnlsNext ;
|
|
INT cStrs, cOk ;
|
|
CHAR * psz1,
|
|
* psz2 ;
|
|
CHAR * pszDefaultRules = GetTextResource( RGAS_RES_DEFAULT_RULES_NAME ) ;
|
|
|
|
if ( pszDefaultRules == NULL )
|
|
{
|
|
return ERROR_RESOURCE_NAME_NOT_FOUND ;
|
|
}
|
|
|
|
for ( cStrs = 0, psz1 = psz2 = pszDefaultRules ;
|
|
*psz1 ;
|
|
psz2 = psz1 )
|
|
{
|
|
for ( cOk = 0 ; *psz1 != 0 ; psz1++ )
|
|
{
|
|
if ( *psz1 == CR )
|
|
break ;
|
|
|
|
if ( *psz1 >= ' ' )
|
|
{
|
|
if ( cOk++ == 0 )
|
|
psz2 = psz1 ;
|
|
}
|
|
}
|
|
|
|
if ( cOk > 0 )
|
|
{
|
|
pnlsNext = new NLS_STR ;
|
|
if ( pnlsNext == NULL )
|
|
{
|
|
err = ERROR_NOT_ENOUGH_MEMORY ;
|
|
break ;
|
|
}
|
|
|
|
CHAR ch = *psz1 ;
|
|
|
|
*psz1 = 0 ;
|
|
err = pnlsNext->MapCopyFrom( psz2 ) ;
|
|
*psz1 = ch ;
|
|
|
|
if ( err )
|
|
break ;
|
|
if ( err = slRules.Append( pnlsNext ) )
|
|
break ;
|
|
cStrs++ ;
|
|
}
|
|
|
|
while ( *psz1 == CR || *psz1 == LF )
|
|
{
|
|
psz1++ ;
|
|
}
|
|
}
|
|
|
|
if ( err == 0 && cStrs > 0 )
|
|
{
|
|
err = _prnNcpa->SetValue( RGAS_RAW_RULES_NAME, & slRules ) ;
|
|
}
|
|
|
|
delete pszDefaultRules ;
|
|
return err ;
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: BINDERY::BINDERY
|
|
|
|
SYNOPSIS: Constructor of BINDERY. SProlog engine and parent
|
|
Registry Manager construct without arguments.
|
|
Contains pointer placeholders for results of Registry scans.
|
|
|
|
ENTRY: Nothing
|
|
|
|
EXIT: Nothing
|
|
|
|
RETURNS: Nothing; QueryError() for construction failure.
|
|
|
|
NOTES:
|
|
|
|
HISTORY:
|
|
|
|
********************************************************************/
|
|
BINDERY :: BINDERY ( BOOL fMainInstall,
|
|
const TCHAR * pszInstallParms )
|
|
: _paCompAssoc( NULL ),
|
|
_pcdlAdapters( NULL ),
|
|
_pcdlTransports( NULL ),
|
|
_pcdlServices( NULL ),
|
|
_pcdlDrivers( NULL ),
|
|
_prnNcpa( NULL ),
|
|
_fAdmin( FALSE ),
|
|
_pszRuleFileName( NULL ),
|
|
_pszRuleData( NULL ),
|
|
_bindState( BND_NOT_LOADED )
|
|
{
|
|
APIERR err = 0,
|
|
err2 = 0 ;
|
|
NLS_STR nlsNcpa( RGAS_NCPA_HOME ) ;
|
|
|
|
if ( QueryError() )
|
|
{
|
|
return ;
|
|
}
|
|
if ( err = nlsNcpa.QueryError() )
|
|
{
|
|
ReportError( err ) ;
|
|
return ;
|
|
}
|
|
|
|
// Obtain access to the NCPA's home location in the Registry.
|
|
// First, try to get WRITE access.
|
|
|
|
_prnNcpa = new REG_KEY( *_prnLocalMachine,
|
|
nlsNcpa,
|
|
GENERIC_READ | GENERIC_WRITE ) ;
|
|
if ( _prnNcpa == NULL )
|
|
{
|
|
ReportError( ERROR_NOT_ENOUGH_MEMORY ) ;
|
|
return ;
|
|
}
|
|
|
|
// If error, attempt to create the key and its value data.
|
|
|
|
if ( _prnNcpa->QueryError()
|
|
&& _prnNcpa->QueryError() != ERROR_ACCESS_DENIED)
|
|
{
|
|
delete _prnNcpa ;
|
|
_prnNcpa = NULL ;
|
|
|
|
if ( (err = CreateNcpaRegKey( pszInstallParms )) == 0 )
|
|
{
|
|
_fAdmin = TRUE ;
|
|
}
|
|
}
|
|
else if ( _prnNcpa->QueryError() == ERROR_ACCESS_DENIED )
|
|
{
|
|
// Try with read only access
|
|
|
|
delete _prnNcpa ;
|
|
_prnNcpa = NULL ;
|
|
_prnNcpa = new REG_KEY( *_prnLocalMachine,
|
|
nlsNcpa,
|
|
GENERIC_READ ) ;
|
|
if ( _prnNcpa == NULL )
|
|
{
|
|
ReportError( ERROR_NOT_ENOUGH_MEMORY ) ;
|
|
return ;
|
|
}
|
|
}
|
|
|
|
if ( err )
|
|
{
|
|
ReportError( IDS_NCPA_REG_FMT_NO_HOME ) ;
|
|
return ;
|
|
}
|
|
|
|
// Get the name of the rule file or the rule data value string
|
|
|
|
err = QueryValueString( _prnNcpa,
|
|
RGAS_NCPA_RULE_FILE,
|
|
& _pszRuleFileName,
|
|
NULL,
|
|
MAX_PATH ) ;
|
|
|
|
if ( (_pszRuleData = GetRulesResource()) == NULL )
|
|
err2 = IDS_NCPA_REG_FMT_NO_RULEFILE ;
|
|
|
|
if ( err != 0 && err2 != 0 )
|
|
{
|
|
// One or the other MUST be present, or we can't compute bindings
|
|
|
|
ReportError( IDS_NCPA_REG_FMT_NO_RULEFILE );
|
|
return ;
|
|
}
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: BINDERY:: ~ BINDERY
|
|
|
|
SYNOPSIS: Destructor of BINDERY.
|
|
|
|
ENTRY:
|
|
|
|
EXIT:
|
|
|
|
RETURNS:
|
|
|
|
NOTES:
|
|
|
|
HISTORY:
|
|
|
|
********************************************************************/
|
|
BINDERY :: ~ BINDERY ()
|
|
{
|
|
Reset() ;
|
|
delete _pszRuleFileName ;
|
|
delete _pszRuleData ;
|
|
delete _prnNcpa ;
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: BINDERY::CreateNcpaRegKey
|
|
|
|
SYNOPSIS: Create the NCPA's home product location in the
|
|
Registry if necessary. Establish all pertinent
|
|
values. Extract the SProlog rule set from the
|
|
resource fork and write it to the Regsitry.
|
|
|
|
ENTRY:
|
|
|
|
EXIT:
|
|
|
|
RETURNS:
|
|
|
|
NOTES:
|
|
|
|
HISTORY:
|
|
|
|
********************************************************************/
|
|
|
|
APIERR BINDERY :: CreateNcpaRegKey ( const TCHAR * pszInstallParms )
|
|
{
|
|
APIERR err ;
|
|
REG_KEY * prkProd = NULL ;
|
|
REG_KEY_CREATE_STRUCT rkcStruct ;
|
|
NLS_STR nlsNcpa( RGAS_NCPA_HOME ) ;
|
|
NLS_STR nlsTemp,
|
|
nlsSrcPath( pszDefaultSrcPath ),
|
|
nlsMt ;
|
|
TCHAR * pchTempData = NULL ;
|
|
LSPL_PROD_TYPE lspt ;
|
|
|
|
delete _prnNcpa ;
|
|
_prnNcpa = NULL ;
|
|
|
|
// Get the package product type
|
|
|
|
if ( LSA_POLICY::QueryProductType( & lspt ) != 0 )
|
|
{
|
|
// If unanticipated error, assume "Windows NT"
|
|
|
|
lspt = LSPL_PROD_WIN_NT ;
|
|
}
|
|
|
|
do
|
|
{ // pseudo-loop to avoid excessive internal returns.
|
|
|
|
if ( err = nlsNcpa.QueryError() )
|
|
break ;
|
|
|
|
_prnNcpa = new REG_KEY( *_prnLocalMachine, nlsNcpa ) ;
|
|
|
|
if ( _prnNcpa == NULL )
|
|
{
|
|
err = ERROR_NOT_ENOUGH_MEMORY ;
|
|
break ;
|
|
}
|
|
|
|
if ( _prnNcpa->QueryError() )
|
|
{
|
|
// At this point, we know the key does not exist
|
|
// or is broken in some way. Attempt to recreate it.
|
|
|
|
delete _prnNcpa ;
|
|
_prnNcpa = NULL ;
|
|
|
|
rkcStruct.dwTitleIndex = 0 ;
|
|
rkcStruct.ulOptions = 0 ;
|
|
rkcStruct.ulDisposition = 0 ;
|
|
rkcStruct.regSam = 0 ;
|
|
rkcStruct.pSecAttr = NULL ;
|
|
rkcStruct.nlsClass = RGAS_GENERAL_CLASS ;
|
|
|
|
#if defined(DEBUG)
|
|
if ( lspt == LSPL_PROD_WIN_NT )
|
|
{
|
|
TRACEEOL( "NCPA/BNDI: Create NCPA Product key for Windows NT" ) ;
|
|
}
|
|
else
|
|
{
|
|
TRACEEOL( "NCPA/BNDI: Create NCPA Product key for Lanman NT" ) ;
|
|
}
|
|
#endif
|
|
if ( err = rkcStruct.nlsClass.QueryError() )
|
|
break ;
|
|
|
|
_prnNcpa = new REG_KEY( *_prnLocalMachine, nlsNcpa, & rkcStruct ) ;
|
|
|
|
if ( _prnNcpa == NULL )
|
|
{
|
|
err = ERROR_NOT_ENOUGH_MEMORY ;
|
|
break ;
|
|
}
|
|
|
|
if ( err = _prnNcpa->QueryError() )
|
|
break ;
|
|
}
|
|
|
|
// The key exists.
|
|
// Add the INF file path name values as REG_EXPAND_SZ
|
|
|
|
// NtlanmanInfName = NTLANMAN.INF
|
|
|
|
err = nlsTemp.CopyFrom( RGAS_VALUE_NTLANMAN_NAME ) ;
|
|
if ( err )
|
|
break ;
|
|
|
|
err = _prnNcpa->SetValue( RGAS_VALUE_NTLANMAN_INF,
|
|
nlsTemp,
|
|
0, NULL, TRUE ) ;
|
|
if ( err )
|
|
break ;
|
|
|
|
// NcpaShelInfName = NCPASHEL.INF
|
|
|
|
err = nlsTemp.CopyFrom( RGAS_VALUE_NCPASHEL_NAME ) ;
|
|
if ( err )
|
|
break ;
|
|
|
|
err = _prnNcpa->SetValue( RGAS_VALUE_NCPASHEL_INF,
|
|
nlsTemp,
|
|
0, NULL, TRUE ) ;
|
|
if ( err )
|
|
break ;
|
|
|
|
// Write the default SProlog rules to the RawRules value
|
|
|
|
if ( err = AddNcpaDefaultRulesValue() )
|
|
break ;
|
|
|
|
// Create an empty prior configuration history. Ignore any error.
|
|
|
|
_prnNcpa->SetValue( RGAS_NCPA_BIND_FILE_EX, nlsMt ) ;
|
|
|
|
// If this is main setup, record the setup source path into
|
|
// the Registry.
|
|
|
|
/* BUGBUG - the following routines will need to be added to Setup.cxx
|
|
if ( pszInstallParms )
|
|
{
|
|
// Alter default setup medium source path if present
|
|
|
|
NCPA_DIALOG::FindSetupParameter( pszInstallParms,
|
|
STF_SRCDIR,
|
|
& nlsSrcPath );
|
|
|
|
// If this is an IDW installation, record that fact.
|
|
|
|
if ( NCPA_DIALOG::FindSetupParameter( pszInstallParms,
|
|
STF_IDW,
|
|
& nlsTemp )
|
|
&& ::stricmpf( STF_TRUE, nlsTemp.QueryPch() ) == 0 )
|
|
{
|
|
TRACEEOL( SZ("NCPA/BNDI: IDW installation ") );
|
|
|
|
_prnNcpa->SetValue( RGAS_NCPA_IDW, (DWORD) 1 );
|
|
}
|
|
}
|
|
|
|
// See if a review INF was specified. Record it
|
|
// or the default value as a REG_MULTI_SZ.
|
|
|
|
if ( pszInstallParms == NULL
|
|
|| ! NCPA_DIALOG::FindSetupParameter( pszInstallParms,
|
|
STF_REVIEW,
|
|
& nlsTemp ) )
|
|
{
|
|
nlsTemp = RGAS_VALUE_REVIEW_NAME ;
|
|
}
|
|
*/
|
|
{
|
|
STRLIST strLst ;
|
|
NLS_STR * pnlsTemp = new NLS_STR( RGAS_VALUE_REVIEW_NAME ) ;
|
|
|
|
TRACEEOL( SZ("NCPA/BNDI: ReviewPrograms INF is ")
|
|
<< nlsTemp.QueryPch() );
|
|
|
|
if ( pnlsTemp != NULL
|
|
&& pnlsTemp->QueryError() == 0
|
|
&& strLst.Append( pnlsTemp ) == 0 )
|
|
{
|
|
_prnNcpa->SetValue( RGAS_REVIEW_INFS,
|
|
& strLst );
|
|
}
|
|
}
|
|
|
|
}
|
|
while ( FALSE ) ;
|
|
|
|
if ( err )
|
|
{
|
|
delete _prnNcpa ;
|
|
_prnNcpa = NULL ;
|
|
}
|
|
|
|
return err ;
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: BINDERY::GetRulesResource
|
|
|
|
SYNOPSIS: Read the SProlog rule file in from the resource fork
|
|
and promote it to UNICODE.
|
|
|
|
ENTRY:
|
|
|
|
EXIT:
|
|
|
|
RETURNS:
|
|
|
|
NOTES: If resource name pointer is NULL, defaults to
|
|
standard NCPARULE.SPR rules resource.
|
|
|
|
HISTORY:
|
|
|
|
********************************************************************/
|
|
TCHAR * BINDERY :: GetRulesResource ( const TCHAR * pszResourceName )
|
|
{
|
|
CHAR * pchRuleData ;
|
|
TCHAR * pszResult ;
|
|
UINT cbSize ;
|
|
|
|
if ( pszResourceName == NULL )
|
|
{
|
|
pszResourceName = RGAS_RES_RULES_NAME ;
|
|
}
|
|
|
|
if ( (pchRuleData = GetTextResource( pszResourceName )) == NULL )
|
|
{
|
|
return NULL ;
|
|
}
|
|
|
|
cbSize = strlen( pchRuleData ) ;
|
|
pszResult = new TCHAR [ cbSize + (sizeof (TCHAR) * 2) ] ;
|
|
|
|
if ( pszResult )
|
|
{
|
|
TCHAR * pcha ;
|
|
CHAR * pchb ;
|
|
UINT i ;
|
|
|
|
// Make a copy of the data, guaranteeing that it's zero-terminated.
|
|
// NOTE: This also performs a trivial promotion to UNICODE.
|
|
|
|
for ( i = cbSize,
|
|
pcha = pszResult,
|
|
pchb = pchRuleData ;
|
|
i-- ; *pcha++ = (TCHAR) (*pchb++) ) ;
|
|
*pcha++ = 0 ;
|
|
}
|
|
|
|
delete pchRuleData ;
|
|
return pszResult ;
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: BINDERY::ResetInterpreter
|
|
|
|
SYNOPSIS: Reset the SPROLOG interpreter.
|
|
|
|
ENTRY:
|
|
|
|
EXIT:
|
|
|
|
RETURNS:
|
|
|
|
NOTES:
|
|
|
|
HISTORY:
|
|
|
|
********************************************************************/
|
|
|
|
APIERR BINDERY :: ResetInterpreter ()
|
|
{
|
|
_queryEngine.Reset() ;
|
|
|
|
return 0 ;
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: BINDERY::IsInteriorBinding
|
|
|
|
SYNOPSIS: Given a component index and a binding index,
|
|
return TRUE if the binding is entirely contained
|
|
(is a pure subset of and lacks a head atom) of
|
|
at least one other binding.
|
|
|
|
ENTRY:
|
|
|
|
EXIT:
|
|
|
|
RETURNS:
|
|
|
|
NOTES:
|
|
|
|
HISTORY:
|
|
|
|
********************************************************************/
|
|
BOOL BINDERY :: IsInteriorBinding ( INT iComp, INT iBind )
|
|
{
|
|
ASSERT( _paCompAssoc != NULL ) ;
|
|
ASSERT( _paCompAssoc->QueryCount() > iComp ) ;
|
|
|
|
COMP_ASSOC * pComp = & (*_paCompAssoc)[iComp],
|
|
* pCompNext ;
|
|
|
|
INT iCompNext,
|
|
iBindNext ;
|
|
|
|
COMP_BINDING * pBind = NULL,
|
|
* pBindNext,
|
|
* pBindExterior = NULL ;
|
|
|
|
{
|
|
// Locate the binding in question
|
|
|
|
ITER_DL_OF( COMP_BINDING ) itBind( pComp->_dlcbBinds ) ;
|
|
INT i ;
|
|
for ( i = 0 ; (pBind = itBind.Next()) && i < iBind; i++ ) ;
|
|
|
|
if ( pBind == NULL )
|
|
{
|
|
TRACEEOL( SZ("NCPA/BIND: Binding ")
|
|
<< iComp
|
|
<< SZ(", ")
|
|
<< iBind
|
|
<< SZ(" does not exist") ) ;
|
|
|
|
return FALSE ; // Bind index is invalid!
|
|
}
|
|
}
|
|
|
|
// For each component...
|
|
|
|
for ( iCompNext = 0 ;
|
|
pBindExterior == NULL && iCompNext < _paCompAssoc->QueryCount() ;
|
|
iCompNext++ )
|
|
{
|
|
pCompNext = & (*_paCompAssoc)[iCompNext] ;
|
|
ITER_DL_OF( COMP_BINDING ) itBind( pCompNext->_dlcbBinds ) ;
|
|
|
|
// For each binding...
|
|
|
|
for ( iBindNext = 0 ;
|
|
pBindExterior == NULL && (pBindNext = itBind.Next()) ;
|
|
iBindNext++ )
|
|
{
|
|
// No need to check for the trivial (self <==> self) case;
|
|
// it MUST fail, since it's not a proper subset of itself.
|
|
|
|
if ( pBind->IsInteriorTo( pBindNext,
|
|
pComp->_huaDevName,
|
|
pCompNext->_huaDevName ) )
|
|
pBindExterior = pBindNext ;
|
|
}
|
|
}
|
|
|
|
#if defined(DEBUG)
|
|
if ( pBindExterior )
|
|
{
|
|
TRACEEOL( SZ("NCPA/BIND: Binding ")
|
|
<< pBind->QueryBindString()
|
|
<< SZ(" is interior to ")
|
|
<< pBindExterior->QueryBindString() );
|
|
}
|
|
#endif
|
|
|
|
return pBindExterior != NULL ;
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: BINDERY::DetermineInteriorBindings
|
|
|
|
SYNOPSIS: Iterate over all components and bindings, setting
|
|
the "interior" flag on any binding which is
|
|
a subset of another binding.
|
|
|
|
ENTRY:
|
|
|
|
EXIT:
|
|
|
|
RETURNS:
|
|
|
|
NOTES:
|
|
|
|
HISTORY:
|
|
|
|
********************************************************************/
|
|
VOID BINDERY :: DetermineInteriorBindings ()
|
|
{
|
|
ASSERT( _paCompAssoc != NULL ) ;
|
|
|
|
INT cComp = _paCompAssoc->QueryCount(),
|
|
iComp,
|
|
iBind ;
|
|
|
|
TRACEEOL( SZ("NCPA/BIND: Determine interior bindings start") ) ;
|
|
|
|
for ( iComp = 0 ; iComp < cComp ; iComp++ )
|
|
{
|
|
COMP_ASSOC * pComp = & (*_paCompAssoc)[iComp] ;
|
|
ITER_DL_OF( COMP_BINDING ) itBind( pComp->_dlcbBinds ) ;
|
|
COMP_BINDING * pBind ;
|
|
for ( iBind = 0 ; pBind = itBind.Next() ; iBind++ )
|
|
{
|
|
pBind->SetInterior( IsInteriorBinding( iComp, iBind ) ) ;
|
|
}
|
|
}
|
|
|
|
TRACEEOL( SZ("NCPA/BIND: Determine interior bindings end") ) ;
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: BINDERY::HandleInteriorBindings
|
|
|
|
SYNOPSIS: After the user has fiddled with the bindings, determine
|
|
if any interior bindings have been implicitly
|
|
deactivated.
|
|
|
|
An interior binding is left "active" iff there exists
|
|
at least one active binding to which it is interior.
|
|
|
|
ENTRY:
|
|
|
|
EXIT:
|
|
|
|
RETURNS:
|
|
|
|
NOTES: This routine depends upon DetermineInteriorBindings()
|
|
having been called to set the "interior" flag.
|
|
|
|
HISTORY:
|
|
|
|
********************************************************************/
|
|
VOID BINDERY :: HandleInteriorBindings ()
|
|
{
|
|
ASSERT( _paCompAssoc != NULL ) ;
|
|
|
|
INT cComp = _paCompAssoc->QueryCount(),
|
|
iComp,
|
|
iBind ;
|
|
|
|
TRACEEOL( SZ("NCPA/BIND: Handle interior bindings start") ) ;
|
|
|
|
for ( iComp = 0 ; iComp < cComp ; iComp++ )
|
|
{
|
|
COMP_ASSOC * pComp = & (*_paCompAssoc)[iComp] ;
|
|
ITER_DL_OF( COMP_BINDING ) itBind( pComp->_dlcbBinds ) ;
|
|
COMP_BINDING * pBind ;
|
|
for ( iBind = 0 ; pBind = itBind.Next() ; iBind++ )
|
|
{
|
|
// If this binding is interior, do the N**2 search.
|
|
if ( pBind->QueryInterior() )
|
|
{
|
|
pBind->SetState( RequiredInteriorBinding( pComp, pBind ) ) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
TRACEEOL( SZ("NCPA/BIND: Handle interior bindings end") ) ;
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: BINDERY::RequiredInteriorBinding
|
|
|
|
SYNOPSIS: Helper routine to HandleInteriorBindings(). Determine
|
|
if a single interior binding is still required; i.e.,
|
|
do any of its exterior bindings remain active?
|
|
|
|
ENTRY:
|
|
|
|
EXIT:
|
|
|
|
RETURNS:
|
|
|
|
NOTES: This routine depends upon DetermineInteriorBindings()
|
|
having been called to set the "interior" flag.
|
|
|
|
HISTORY:
|
|
|
|
********************************************************************/
|
|
BOOL BINDERY :: RequiredInteriorBinding (
|
|
COMP_ASSOC * pCompCheck,
|
|
COMP_BINDING * pBindCheck )
|
|
{
|
|
ASSERT( _paCompAssoc != NULL && pBindCheck->QueryInterior() ) ;
|
|
|
|
INT cComp = _paCompAssoc->QueryCount(),
|
|
iComp ;
|
|
BOOL fResult = FALSE ;
|
|
COMP_ASSOC * pComp ;
|
|
|
|
for ( iComp = 0 ; (! fResult) && iComp < cComp ; iComp++ )
|
|
{
|
|
pComp = & (*_paCompAssoc)[iComp] ;
|
|
|
|
if ( pComp == pCompCheck )
|
|
continue ;
|
|
|
|
ITER_DL_OF( COMP_BINDING ) itBind( pComp->_dlcbBinds ) ;
|
|
COMP_BINDING * pBind ;
|
|
|
|
while ( (! fResult) && (pBind = itBind.Next()) )
|
|
{
|
|
if ( pBind->QueryState()
|
|
&& pBindCheck->IsInteriorTo( pBind,
|
|
pCompCheck->_huaDevName,
|
|
pComp->_huaDevName ) )
|
|
fResult = TRUE ;
|
|
}
|
|
}
|
|
return fResult ;
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: BINDERY::GetNcpaValueString
|
|
|
|
SYNOPSIS:
|
|
|
|
ENTRY:
|
|
|
|
EXIT:
|
|
|
|
RETURNS:
|
|
|
|
NOTES: Get one of the NCPA's configured
|
|
REG_EXPAND_SZ strings.
|
|
|
|
HISTORY:
|
|
|
|
********************************************************************/
|
|
APIERR BINDERY :: GetNcpaValueString (
|
|
const TCHAR * pszValue,
|
|
NLS_STR * pnlsResult )
|
|
{
|
|
APIERR err = _prnNcpa->QueryValue( pszValue,
|
|
pnlsResult,
|
|
0, NULL, TRUE ) ;
|
|
#if defined(DEBUG)
|
|
if ( err )
|
|
{
|
|
TRACEEOL( SZ("NCPA/BINDERY: failed to read NCPA key value ")
|
|
<< pszValue );
|
|
|
|
SetLastErrorName( pszValue ) ;
|
|
}
|
|
else
|
|
{
|
|
TRACEEOL( SZ("NCPA/BINDERY: NCPA key value ")
|
|
<< pszValue
|
|
<< SZ(" retrieved was ")
|
|
<< pnlsResult->QueryPch() ) ;
|
|
}
|
|
#endif
|
|
|
|
return err ;
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: BINDERY::GetNcpaValueNumber
|
|
|
|
SYNOPSIS:
|
|
|
|
ENTRY:
|
|
|
|
EXIT:
|
|
|
|
RETURNS:
|
|
|
|
NOTES:
|
|
|
|
HISTORY:
|
|
|
|
********************************************************************/
|
|
APIERR BINDERY :: GetNcpaValueNumber (
|
|
const TCHAR * pszValue,
|
|
DWORD * pdwValue )
|
|
{
|
|
APIERR err = _prnNcpa->QueryValue( pszValue,
|
|
pdwValue ) ;
|
|
#if defined(DEBUG)
|
|
if ( err )
|
|
{
|
|
TRACEEOL( SZ("NCPA/BINDERY: failed to read NCPA key value ")
|
|
<< pszValue );
|
|
|
|
SetLastErrorName( pszValue ) ;
|
|
}
|
|
else
|
|
{
|
|
TRACEEOL( SZ("NCPA/BINDERY: NCPA key value ")
|
|
<< pszValue
|
|
<< SZ(" retrieved was ")
|
|
<< *pdwValue ) ;
|
|
}
|
|
#endif
|
|
|
|
return err ;
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: BINDERY::QueryCfgDirty
|
|
|
|
SYNOPSIS: See SetCfgDirty().
|
|
|
|
ENTRY: Nothing
|
|
|
|
EXIT: Nothing
|
|
|
|
RETURNS: TRUE if configuration is in need of a reboot.
|
|
|
|
NOTES:
|
|
|
|
HISTORY:
|
|
|
|
********************************************************************/
|
|
BOOL BINDERY :: QueryCfgDirty ()
|
|
{
|
|
NLS_STR nlsDirtyKeyName( RGAS_NCPA_CFG_DIRTY_KEY_NAME );
|
|
|
|
ASSERT( _prnNcpa != NULL ) ;
|
|
|
|
REG_KEY rkDirty( *_prnNcpa, nlsDirtyKeyName ) ;
|
|
|
|
return rkDirty.QueryError() == 0 ;
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: BINDERY::SetCfgDirty
|
|
|
|
SYNOPSIS: A volatile Registry key is created to indicate
|
|
that the current configuration needs to be rebooted.
|
|
This routine either creates or destroys that key.
|
|
|
|
ENTRY: BOOL fDirty state configuration should be in
|
|
|
|
EXIT: Nothing
|
|
|
|
RETURNS: TRUE if configuration was dirty.
|
|
|
|
NOTES:
|
|
|
|
HISTORY:
|
|
|
|
********************************************************************/
|
|
BOOL BINDERY :: SetCfgDirty ( BOOL fDirty )
|
|
{
|
|
APIERR err = 0 ;
|
|
|
|
NLS_STR nlsDirtyKeyName( RGAS_NCPA_CFG_DIRTY_KEY_NAME );
|
|
|
|
ASSERT( _prnNcpa != NULL ) ;
|
|
|
|
REG_KEY rkDirty( *_prnNcpa, nlsDirtyKeyName ) ;
|
|
|
|
BOOL fWasDirty = rkDirty.QueryError() == 0 ;
|
|
|
|
if ( fWasDirty ^ fDirty )
|
|
{
|
|
// State doesn't match user's desire.
|
|
// Do we create or destroy?
|
|
|
|
if ( fDirty )
|
|
{
|
|
// Create
|
|
|
|
REG_KEY_CREATE_STRUCT rkcStruct ;
|
|
|
|
rkcStruct.dwTitleIndex = 0 ;
|
|
rkcStruct.ulOptions = REG_OPTION_VOLATILE ;
|
|
rkcStruct.ulDisposition = 0 ;
|
|
rkcStruct.regSam = 0 ;
|
|
rkcStruct.pSecAttr = NULL ;
|
|
rkcStruct.nlsClass = RGAS_GENERAL_CLASS ;
|
|
|
|
REG_KEY rkNewDirty( *_prnNcpa,
|
|
nlsDirtyKeyName,
|
|
& rkcStruct ) ;
|
|
|
|
err = rkNewDirty.QueryError() ;
|
|
|
|
#if defined(TRACE)
|
|
if ( err )
|
|
{
|
|
TRACEEOL( "NCPA/BNDI: Creation of cfg dirty key returned "
|
|
<< err ) ;
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
// Destroy
|
|
|
|
err = rkDirty.Delete() ;
|
|
|
|
#if defined(TRACE)
|
|
if ( err )
|
|
{
|
|
TRACEEOL( "NCPA/BNDI: Deletion of cfg dirty key returned "
|
|
<< err ) ;
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
return fWasDirty ;
|
|
}
|
|
|
|
// End of NCPABNDI.CXX
|