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.
 
 
 
 
 
 

3183 lines
86 KiB

/**********************************************************************/
/** Microsoft Windows NT **/
/** Copyright(c) Microsoft Corp., 1991 **/
/**********************************************************************/
/*
NCPASETP.CXX: Windows/NT Network Control Panel Applet
Installation and Setup handling.
FILE HISTORY:
DavidHov 4/20/92 Created
DavidHov 11/02/92 Moved string-mangling stuff into
..\NCPA\NCPASTRS.CXX
*/
#include "pchncpa.hxx" // Precompiled header
#include "ncpacpl.hxx"
// Access rights required for using Service Controller, et al.
#define SVC_CTRL_ACCESS (GENERIC_ALL)
#define SVC_CTRL_START_ACCESS (GENERIC_READ | GENERIC_EXECUTE)
#define LSA_ACCESS (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE)
enum ESETUP_ARGS { ESARG_HWND, ESARG_FUNC, ESARG_1ST };
enum ESETUP_FUNC
{ // (N.B.: asterisk means it uses a window handle)
ESFUNC_NONE, // None
ESFUNC_NCPA, // *Run NCPA, OEM Setup, etc.
ESFUNC_DOMAIN, // *Perform domain setup
ESFUNC_CONNECT, // Connect to network sharepoint
ESFUNC_CREATE_SERVICE, // Create a Service Controller Service
ESFUNC_DELETE_SERVICE, // Delete " " " "
ESFUNC_START_SERVICE, // Start " " " "
ESFUNC_SECURE_REG_KEY, // Change security on a registry key
ESFUNC_WINSOCK_MAPPING, // Retrieve and store WinSock mapping info
ESFUNC_ERROR_MESSAGE, // Translate an APIERR to an error message
ESFUNC_DETECT_START, // Start netcard detection
ESFUNC_DETECT_END, // Terminate netcard detection
ESFUNC_DETECT_RESET, // Reset detection iteration
ESFUNC_DETECT_CARD, // Detect a netcard
ESFUNC_DETECT_VERIFY, // Verify the setting of a netcard
ESFUNC_DETECT_PARAMS, // Return netcard type parameter info
ESFUNC_DETECT_QUERY, // Return netcard instance paramter info
ESFUNC_DETECT_STRING, // Return option data string
ESFUNC_DETECT_PNAME, // Return parameter name string
ESFUNC_DETECT_CLAIM, // Claim new resources
ESFUNC_DETECT_OPEN, // Open a handle to an existing card
ESFUNC_SECURE_SERVICE, // Set service security info
ESFUNC_TCPIP_CFG_CHECK, // See if TCP/IP needs reconfiguration
ESFUNC_MCS_CFG_CHECK, // See if MCS needs reconfiguration
ESFUNC_ROUTE_TO_INF_LIST, // Convert imbedded quoted string to list
ESFUNC_BINDINGS_ONLY, // *Run NCPA for bindings only
ESFUNC_ACTIVATE_BINDINGS, // Given a list of bindings, activate them
ESFUNC_BDC_REPLICATE, // Wait for the BDC replication to complete
ESFUNC_MAX
};
static struct SETUP_FUNC_INDEX
{
ESETUP_FUNC esFunc ;
TCHAR * pszToken ;
BOOL fUsesHwnd ;
} setupFuncIndex [] =
{
{ ESFUNC_NCPA, SZ("NCPA") , TRUE },
{ ESFUNC_DOMAIN, SZ("DOMAIN") , TRUE },
{ ESFUNC_CONNECT, SZ("CONNECT") , FALSE },
{ ESFUNC_CREATE_SERVICE, SZ("CREATESVC") , FALSE },
{ ESFUNC_DELETE_SERVICE, SZ("DELETESVC") , FALSE },
{ ESFUNC_START_SERVICE, SZ("STARTSVC") , FALSE },
{ ESFUNC_SECURE_REG_KEY, SZ("SECUREKEY") , FALSE },
{ ESFUNC_WINSOCK_MAPPING, SZ("WINSOCKMAP"), FALSE },
{ ESFUNC_ERROR_MESSAGE, SZ("ERRORMSG") , FALSE },
{ ESFUNC_DETECT_START, SZ("DTSTART") , FALSE },
{ ESFUNC_DETECT_END, SZ("DTEND") , FALSE },
{ ESFUNC_DETECT_RESET, SZ("DTRESET") , FALSE },
{ ESFUNC_DETECT_CARD, SZ("DTCARD") , FALSE },
{ ESFUNC_DETECT_PARAMS, SZ("DTPARAMS") , FALSE },
{ ESFUNC_DETECT_QUERY, SZ("DTQUERY") , FALSE },
{ ESFUNC_DETECT_VERIFY, SZ("DTVERIFY") , FALSE },
{ ESFUNC_DETECT_STRING, SZ("DTSTRING") , FALSE },
{ ESFUNC_DETECT_PNAME, SZ("DTPNAME") , FALSE },
{ ESFUNC_DETECT_CLAIM, SZ("DTCLAIM") , FALSE },
{ ESFUNC_DETECT_OPEN, SZ("DTOPEN") , FALSE },
{ ESFUNC_SECURE_SERVICE, SZ("SECURESVC") , FALSE },
{ ESFUNC_TCPIP_CFG_CHECK, SZ("TCPCFGCHK") , FALSE },
{ ESFUNC_MCS_CFG_CHECK, SZ("MCSCFGCHK") , FALSE },
{ ESFUNC_ROUTE_TO_INF_LIST, SZ("ROUTETOLIST"), FALSE },
{ ESFUNC_BINDINGS_ONLY, SZ("BINDONLY") , TRUE },
{ ESFUNC_ACTIVATE_BINDINGS, SZ("ACTIVBIND") , FALSE },
{ ESFUNC_BDC_REPLICATE, SZ("DOBDCREPL") , TRUE },
{ ESFUNC_NONE, NULL , FALSE }
};
extern APIERR RunBDCReplWait ( HWND hWnd );
/*
* Merge the contents of *pslOther onto *pslMain.
* Each string is fully duplicated.
*/
static APIERR mergeStrLists ( STRLIST * pslMain, STRLIST * pslOther )
{
APIERR err = 0 ;
ITER_STRLIST islOther( *pslOther ) ;
NLS_STR * pnlsNext,
* pnlsDup = NULL ;
// This unfortunate code is based on the fact that STRLIST
// iteration/removal is not reliable.
while ( pnlsNext = islOther.Next() )
{
pnlsDup = new NLS_STR( *pnlsNext ) ;
err = pnlsDup == NULL
? ERROR_NOT_ENOUGH_MEMORY
: pnlsDup->QueryError() ;
if ( err )
break ;
err = pslMain->Append( pnlsDup ) ;
pnlsDup = NULL ;
if ( err )
break ;
}
delete pnlsDup ; // Precaution if failure.
return err ;
}
/*******************************************************************
NAME: ActivateBindings
SYNOPSIS: Given a list of bindings to preserve,
activate them and disable all other bindings.
ENTRY: REG_KEY * prkNbtLinkage pointer to NBT linkage
registry key
-- or --
const TCHAR * pszServiceName name of service to
fiddle with
const TCHAR * apszBinds NULL-terminated list
of binding names
EXIT: Nothing
RETURNS: APIERR if failure or zero if successful
NOTES: Enabled (active) bindings are listed under the "Linkage"
key; disabled (inactive) bindings are listed under
the "Linkage\Disabled" key.
Due to the fact that iterating a STRLIST while removing
items is not reliable, this code does more string
duplication than would seem necessary at first glance.
The algorithm is:
Query the active and inactive binding data from
the Registry.
Merge active and inactive bindings into a new set
of STRLISTs; clear the disabled STRLISTs.
Iterate over the merged lists, duplicating each
set of strings. If the Bind value matches the
function argument, make it active; all others
become inactive.
Set all Registry values.
HISTORY:
********************************************************************/
APIERR ActivateBindings (
REG_KEY * prkNbtLinkage,
const TCHAR * * apszBinds )
{
APIERR err = 0 ;
NLS_STR nlsDisabled( RGAS_DISABLED_KEY_NAME ) ;
STRLIST * pslActBind = NULL,
* pslActExport = NULL,
* pslActRoute = NULL,
* pslDisBind = NULL,
* pslDisExport = NULL,
* pslDisRoute = NULL,
* pslMergeBind = NULL,
* pslMergeExport = NULL,
* pslMergeRoute = NULL ;
if ( err = nlsDisabled.QueryError() )
{
return err ;
}
REG_KEY rkDisabled ( *prkNbtLinkage, nlsDisabled, MAXIMUM_ALLOWED ) ;
if ( err = rkDisabled.QueryError() )
{
return err ;
}
do // Pseudo-loop
{
// Suck in all the values.
// Allocate an empty list for anything not found.
if ( prkNbtLinkage->QueryValue( RGAS_BIND_VALUE_NAME, & pslMergeBind ) )
pslMergeBind = new STRLIST ;
if ( prkNbtLinkage->QueryValue( RGAS_EXPORT_VALUE_NAME, & pslMergeExport ) )
pslMergeExport = new STRLIST ;
if ( prkNbtLinkage->QueryValue( RGAS_ROUTE_VALUE_NAME, & pslMergeRoute ) )
pslMergeRoute = new STRLIST ;
if ( rkDisabled.QueryValue( RGAS_BIND_VALUE_NAME, & pslDisBind ) )
pslDisBind = new STRLIST ;
if ( rkDisabled.QueryValue( RGAS_EXPORT_VALUE_NAME, & pslDisExport ) )
pslDisExport = new STRLIST ;
if ( rkDisabled.QueryValue( RGAS_ROUTE_VALUE_NAME, & pslDisRoute ) )
pslDisRoute = new STRLIST ;
// Allocate new "active" STRLISTs
pslActBind = new STRLIST ;
pslActExport = new STRLIST ;
pslActRoute = new STRLIST ;
if ( pslActBind == NULL
|| pslActExport == NULL
|| pslActRoute == NULL
|| pslDisBind == NULL
|| pslDisExport == NULL
|| pslDisRoute == NULL
|| pslMergeBind == NULL
|| pslMergeExport == NULL
|| pslMergeRoute == NULL
)
{
err = ERROR_NOT_ENOUGH_MEMORY ;
break ;
}
// Merge the active and inactive lists; clear the inactive lists.
if ( err = mergeStrLists( pslMergeBind, pslDisBind ) )
break ;
if ( err = mergeStrLists( pslMergeExport, pslDisExport ) )
break ;
if ( err = mergeStrLists( pslMergeRoute, pslDisRoute ) )
break ;
pslDisBind->Clear() ;
pslDisExport->Clear() ;
pslDisRoute->Clear() ;
// Loop through the merged lists. When we find the target, make it
// active; make all others inactive.
NLS_STR * pnlsBind,
* pnlsExport,
* pnlsRoute,
* pnlsDupBind = NULL,
* pnlsDupExport = NULL,
* pnlsDupRoute = NULL ;
ITER_STRLIST islBind( *pslMergeBind ) ;
ITER_STRLIST islExport( *pslMergeExport ) ;
ITER_STRLIST islRoute( *pslMergeRoute ) ;
for ( ; pnlsBind = islBind.Next() ; )
{
pnlsExport = islExport.Next() ;
pnlsRoute = islRoute.Next() ;
if ( pnlsExport == NULL || pnlsRoute == NULL )
{
// BOGUS: the lists are internally out of sync!
err = ERROR_GEN_FAILURE ;
}
// Duplicate this set of strings. This method of
// operation is due to problems in removing SLIST
// items while iterating.
pnlsDupBind = new NLS_STR( *pnlsBind ) ;
pnlsDupExport = new NLS_STR( *pnlsExport ) ;
pnlsDupRoute = new NLS_STR( *pnlsRoute ) ;
if ( pnlsDupBind == NULL
|| pnlsDupExport == NULL
|| pnlsDupRoute == NULL )
{
err = ERROR_NOT_ENOUGH_MEMORY ;
delete pnlsDupBind ;
delete pnlsDupExport ;
delete pnlsDupRoute ;
break ;
}
// If this is an active binding, make it so;
// otherwise, add it to the inactive set
for ( INT iBind = 0 ; apszBinds[iBind] ; iBind++ )
{
if ( ::stricmpf( pnlsBind->QueryPch(), apszBinds[iBind] ) == 0 )
break ;
}
if ( apszBinds[iBind] )
{
pslActBind->Append( pnlsDupBind ) ;
pslActExport->Append( pnlsDupExport ) ;
pslActRoute->Append( pnlsDupRoute ) ;
TRACEEOL( SZ("NCPA/TCPIP: ActivateBindings; binding found: ")
<< apszBinds[iBind] ) ;
}
else
{
pslDisBind->Append( pnlsDupBind ) ;
pslDisExport->Append( pnlsDupExport ) ;
pslDisRoute->Append( pnlsDupRoute ) ;
}
}
// Write out the modified REG_MULTI_SZs
prkNbtLinkage->SetValue( RGAS_BIND_VALUE_NAME, pslActBind ) ;
prkNbtLinkage->SetValue( RGAS_EXPORT_VALUE_NAME, pslActExport ) ;
prkNbtLinkage->SetValue( RGAS_ROUTE_VALUE_NAME, pslActRoute ) ;
rkDisabled.SetValue( RGAS_BIND_VALUE_NAME, pslDisBind ) ;
rkDisabled.SetValue( RGAS_EXPORT_VALUE_NAME, pslDisExport ) ;
rkDisabled.SetValue( RGAS_ROUTE_VALUE_NAME, pslDisRoute ) ;
} while ( FALSE ) ;
delete pslActBind ;
delete pslActRoute ;
delete pslActExport ;
delete pslDisBind ;
delete pslDisExport ;
delete pslDisRoute ;
delete pslMergeBind ;
delete pslMergeRoute ;
delete pslMergeExport ;
return err ;
}
// Variant which opens the Linkage key given the
// name of the service.
APIERR ActivateBindings (
const TCHAR * pszServiceName,
const TCHAR * * apszBinds )
{
APIERR err ;
TCHAR achLinkage [MAX_PATH] ;
::wsprintf( achLinkage, SZ("%s\\%s\\%s"),
RGAS_SERVICES_HOME,
pszServiceName,
RGAS_LINKAGE_NAME ) ;
ALIAS_STR nlsLinkageKeyName( achLinkage ) ;
REG_KEY rkLocalMachine( HKEY_LOCAL_MACHINE ) ;
if ( err = rkLocalMachine.QueryError() )
{
return err ;
}
REG_KEY rkLinkage( rkLocalMachine,
nlsLinkageKeyName ) ;
if ( err = rkLinkage.QueryError() )
{
return err ;
}
return ActivateBindings( & rkLinkage, apszBinds ) ;
}
// Activate a single binding.
APIERR ActivateBinding (
REG_KEY * prkLinkage,
const TCHAR * pszBind )
{
const TCHAR * apszBinds [2] ;
apszBinds[0] = pszBind ;
apszBinds[1] = NULL ;
return ActivateBindings( prkLinkage, apszBinds ) ;
}
// Exported versions: UNICODE and ANSI.
LONG FAR PASCAL CPlActivateBindingsW (
const TCHAR * pszServiceName,
const TCHAR * * apszBinds )
{
return ActivateBindings( pszServiceName, apszBinds ) ;
}
LONG FAR PASCAL CPlActivateBindingsA (
const CHAR * pszServiceName,
const CHAR * * apszBinds )
{
NLS_STR nlsServiceName ;
const TCHAR * * apwchBinds = NULL ;
INT cBind ;
APIERR err ;
do
{
if ( err = nlsServiceName.QueryError() )
break ;
if ( err = nlsServiceName.MapCopyFrom( pszServiceName ) )
break ;
// Count the number of bindings given; use the
// ANSI string vector to create a UNICODE vector.
for ( cBind = 0 ; apszBinds[cBind++] ; ) ;
if ( (apwchBinds = (const TCHAR **) CvtArgs( (const LPSTR *) apszBinds, cBind )) == NULL )
{
err = ERROR_NOT_ENOUGH_MEMORY ;
break ;
}
// Call the worker function
err = ActivateBindings( nlsServiceName.QueryPch(), apwchBinds ) ;
FreeArgs( (TCHAR **) apwchBinds, cBind ) ;
}
while ( FALSE ) ;
return err ;
}
/*******************************************************************
NAME: appendToInfList
SYNOPSIS: Add a string (or number) to an INF-style list.
Prefix or suffix with comma separator as requested.
ENTRY: NLS_STR * pnlsList result
TCHAR * pszData data to append
INFSEPCTL separator control flags
EXIT: APIERR err != 0 if failure
RETURNS:
NOTES: Has overloaded variant for numbers.
HISTORY:
********************************************************************/
enum INFSEPCTL { ISC_None, ISC_Before, ISC_After, ISC_Both } ;
static APIERR appendToInfList (
NLS_STR * pnlsList, // List a-building
const TCHAR * pszData, // Data to append
INFSEPCTL iSepCtl = ISC_None ) // Add separators?
{
#define CHQUOTE ((TCHAR)TCH('\"'))
#define CHSEP ((TCHAR)TCH(','))
#define CHSPACE ((TCHAR)TCH(' '))
APIERR err = 0 ;
do
{
if ( iSepCtl & ISC_Before )
{
if ( err = pnlsList->AppendChar( CHSEP ) )
break ;
}
if ( err = pnlsList->AppendChar( CHQUOTE ) )
break ;
if ( err = pnlsList->Append( pszData ) )
break ;
if ( err = pnlsList->AppendChar( CHQUOTE ) )
break ;
if ( ! (iSepCtl & ISC_After) )
break ;
if ( err = pnlsList->AppendChar( CHSEP ) )
break ;
} while ( FALSE ) ;
return err ;
}
static APIERR appendToInfList (
NLS_STR * pnlsList, // List a-building
INT iArg, // Integer to add
INFSEPCTL iSepCtl = ISC_None ) // Add separators?
{
TCHAR chBuffer [ 20 ] ;
IntToStr( iArg, chBuffer, 10 ) ;
return appendToInfList( pnlsList, chBuffer, iSepCtl ) ;
}
/*******************************************************************
NAME: RunNcpa
SYNOPSIS: Invoke the main dialog of the Network Control Panel
Applet
ENTRY: HWND hWnd window handle of parent window.
BOOL fMainInstall TRUE if this is is "main installation";
false for normal Control Panel-driven
invocation.
TCHAR * pszParms command line parameters from SETUP;
only applicable if "fMainInstall" is
TRUE.
EXIT:
RETURNS: APIERR
NOTES: If the NCPA returns the error code indicating
that a separate process has been launched, we
ExitProcess() here.
HISTORY:
********************************************************************/
APIERR RunNcpa ( HWND hWnd, BOOL fMainInstall, const TCHAR * pszParms )
{
APIERR err ;
UINT ulDlgResult = 0 ;
POPUP::SetCaption( IDS_NCPA_NAME_STRING_SETTINGS ) ;
NCPA_DIALOG * pdlgNcpa = new NCPA_DIALOG( hWnd, fMainInstall, pszParms ) ;
if ( pdlgNcpa == NULL )
{
err = ERROR_NOT_ENOUGH_MEMORY ;
}
else
if ( (err = pdlgNcpa->QueryError()) == 0 )
{
err = pdlgNcpa->Process( & ulDlgResult );
}
if ( err )
{
::MsgPopup( hWnd, (MSGID) err ) ;
}
else
{
err = ulDlgResult ;
}
delete pdlgNcpa ;
// See if the dialog failure was due to launching
// a separate process to install the network
// If so, this is the end of time.
if ( err == IDS_NCPA_PROCESS_LAUNCH )
{
::ExitProcess( 0 ) ;
}
POPUP::ResetCaption() ;
return err ;
}
/*******************************************************************
NAME: RunNcpaBindingsOnly
SYNOPSIS: Invoke the main dialog of the Network Control Panel
Applet to automatically regenerate bindings.
ENTRY: HWND hWnd window handle of parent window.
EXIT:
RETURNS: APIERR
NOTES:
HISTORY:
********************************************************************/
APIERR RunNcpaBindingsOnly ( HWND hWnd )
{
static const TCHAR * pszBindOnly = SZ("/t BINDONLY = TRUE") ;
return RunNcpa( hWnd, FALSE, pszBindOnly ) ;
}
APIERR RouteToInfList (
const TCHAR * pszRoute,
NLS_STR * pnlsResult )
{
NLS_STR nls ;
INT cQuote ;
for ( cQuote = 0 ; *pszRoute ; pszRoute++ )
{
if ( *pszRoute == CHQUOTE )
{
if ( cQuote++ & 1 ) // If it's a closing quote...
{
if ( nls.QueryTextLength() )
appendToInfList( pnlsResult, nls.QueryPch(), ISC_Before ) ;
}
nls = SZ("") ;
}
else
{
nls.AppendChar( *pszRoute ) ;
}
}
return 0 ;
}
/*******************************************************************
NAME: RunDomain
SYNOPSIS: Perform domain joining and creation during installation.
ENTRY: HWND hWnd window handle of parent window.
TCHAR * pszParms command line parameters from SETUP;
only applicable if "fMainInstall" is
TRUE.
EXIT: NLS_STR * pnlsResult result string to be passed back
to NTLANMAN.INF
RETURNS: APIERR
NOTES: This function is only called through the CPlSetup()
export function.
Instantiate a DOMAIN_MANAGER, which is a subclass of
LSA_POLICY. This requires admin-level access, since we're
going to update LSA, etc. See NCPADOMN.CXX for details.
The command line parameters are parsed in DomainInstall();
they contain the type of product, machine/user name,
installation mode, etc.
The result data is returned in the format expected by
SETUP. See NTLANMAN.INF and SETUP.INF for details.
Output format (error supplied by caller):
{ <numeric error code>
COMPUTERNAME
DOMAINNAME
LOGONPASSWORD
COMPUTERROLE
}
HISTORY: DavidHov 4/19/92 Created
********************************************************************/
APIERR RunDomain (
HWND hWnd,
const TCHAR * pszParms,
NLS_STR * pnlsResult )
{
APIERR err ;
POPUP::SetCaption( IDS_NCPA_NAME_STRING_SETTINGS ) ;
DOMAIN_MANAGER domnMgr ( hWnd,
LSA_ACCESS,
NULL,
NULL,
TRUE ) ;
if ( (err = domnMgr.QueryError()) == 0 )
{
err = domnMgr.DomainInstall( pszParms ) ;
}
if ( err == 0 )
{
// Append information onto the return variable list
const NLS_STR * pnlsPeek ;
const TCHAR * pchRole ;
ISTACK_NLS_STR( nlsEmpty, 4, SZ("\"\"") ) ;
if ( (pnlsPeek = domnMgr.PeekName( EDRNM_COMPUTER )) == NULL
|| pnlsPeek->QueryTextSize() == 0 )
pnlsPeek = & nlsEmpty ;
appendToInfList( pnlsResult, *pnlsPeek, ISC_Before ) ;
if ( (pnlsPeek = domnMgr.PeekName( EDRNM_DOMAIN )) == NULL
|| pnlsPeek->QueryTextSize() == 0 )
pnlsPeek = & nlsEmpty ;
appendToInfList( pnlsResult, *pnlsPeek, ISC_Before ) ;
if ( (pnlsPeek = domnMgr.PeekName( EDRNM_LOGON_PWD )) == NULL
|| pnlsPeek->QueryTextSize() == 0 )
pnlsPeek = & nlsEmpty ;
appendToInfList( pnlsResult, *pnlsPeek, ISC_Before ) ;
switch ( domnMgr.QueryRole() )
{
case EROLE_DC:
pchRole = SZ("DC") ;
break ;
case EROLE_MEMBER:
pchRole = SZ("MEMBER") ;
break ;
case EROLE_TRUSTED:
pchRole = SZ("TRUSTED") ;
break ;
case EROLE_STANDALONE:
pchRole = SZ("STANDALONE") ;
break ;
case EROLE_UNKNOWN:
default:
pchRole = SZ("UNKNOWN") ;
break ;
}
appendToInfList( pnlsResult, pchRole, ISC_Before ) ;
}
POPUP::ResetCaption() ;
return err ;
}
/*******************************************************************
NAME: RunConnect
SYNOPSIS: Connect to SETUP's network sharepoint
ENTRY: TCHAR * pszParms [] command line parameters from SETUP
pszParms [0] Drive letter to use; "D:"
pszParms [1] UNC resource name
(optional) pszParms [2] password
(optional) pszParms [3] user name
(optional) pszParms [4] domain
EXIT:
RETURNS: APIERR
NOTES: This function is only called through the CPlSetup()
export function.
THIS FUNCTION IS CURRENTLY NEVER CALLED, but is left
here in case we ever need it.
HISTORY: DavidHov 4/19/92 Created
********************************************************************/
APIERR RunConnect ( const TCHAR * pszParms [], INT cArgs )
{
enum ECONNPARM
{
ECNP_DRIVE, ECNP_UNC, ECNP_PASS, ECNP_USER, ECNP_DOMAIN
};
// Guarantee that we have at least a drive letter and a UNC name.
if ( cArgs < ECNP_PASS
|| pszParms[ECNP_DRIVE] == NULL
|| ::strlenf( pszParms[ECNP_DRIVE] ) < 2
|| pszParms[ECNP_DRIVE][1] != TCH(':')
|| pszParms[ECNP_UNC] == NULL
|| ::strlenf( pszParms[ECNP_UNC] ) == 0
|| pszParms[ECNP_UNC][0] != TCH('\\')
|| pszParms[ECNP_UNC][1] != TCH('\\') )
{
TRACEEOL( SZ("NCPA/SETP: Invalid drive or UNC parameters to connect to") ) ;
return ERROR_INVALID_PARAMETER ;
}
TCHAR achDev [4] ;
// Just use the drive letter from the caller's string. SETUP has
// a hard time with substringing.
achDev[0] = pszParms[ECNP_DRIVE][0] ;
achDev[1] = TCH(':') ;
achDev[2] = 0 ;
TRACEEOL( SZ("NCPA/SETP: Connect ")
<< pszParms[ECNP_UNC]
<< SZ(" as ")
<< achDev ) ;
// Construct the DEVICE2 object representing the connection
DEVICE2 devShare( achDev ) ;
// Push the DEVICE2 into a valid state.
APIERR err = devShare.GetInfo() ;
if ( err == 0 )
{
// Default the arguments as necessary. If not passed
// or zero length, replace with NULL.
const TCHAR * pszPass = cArgs > ECNP_PASS
? pszParms[ECNP_PASS]
: NULL ;
const TCHAR * pszUser = cArgs > ECNP_USER
? pszParms[ECNP_USER]
: NULL ;
const TCHAR * pszDomain = cArgs > ECNP_DOMAIN
? pszParms[ECNP_DOMAIN]
: NULL ;
if ( pszPass && ::strlenf( pszPass ) == 0 )
pszPass = NULL ;
if ( pszUser && ::strlenf( pszUser ) == 0 )
pszUser = NULL ;
if ( pszDomain && ::strlenf( pszDomain ) == 0 )
pszDomain = NULL ;
// Attempt to connect to the sharepoint
err = devShare.Connect( pszParms[ECNP_UNC],
pszPass, pszUser, pszDomain) ;
}
return err ;
}
/*******************************************************************
NAME: RunCreateService
SYNOPSIS: Create a new Win32 service in the Service Controller
ENTRY: TCHAR * pszParms [] command line parameters from SETUP
pszParms [0] String: Name of Service
pszParms [1] String: Display Name of Service
pszParms [2] Decimal: Start code
pszParms [3] Decimal: Type code
pszParms [4] Decimal: Error control value
pszParms [5] String: Path\exename
pszParms [6] String: Load order group name
pszParms [7] String: Dependency names
optional pszParms [8] String: account start name
optional pszParms [9] String: Password
EXIT:
RETURNS: APIERR
NOTES: This function is only called through the CPlSetup()
export function.
If the account name is not passed, "LocalSystem" is used
as the default.
The dependency names should be constructed as a SETUP
list with {}; for example:
{ "dependency 1","dependency 2" }
HISTORY: DavidHov 5/24/92 Created
********************************************************************/
APIERR RunCreateService ( const TCHAR * pszParms [], INT cArgs )
{
// Definition stolen from SVCCTRL\SERVER\ACCOUNT.H
#define LOCAL_SYSTEM_USER_NAME SZ("LocalSystem")
APIERR err = 0 ;
TCHAR szDependencies [ 500 ] ;
enum ECSVCPARM
{
ECSP_NAME,
ECSP_DISPLAY_NAME,
ECSP_START,
ECSP_TYPE,
ECSP_ERROR_CONTROL,
ECSP_BINARY_PATH,
ECSP_GROUP_NAME,
ECSP_DEPENDENCIES,
ECSP_START_NAME, // optional
ECSP_PASSWORD // optional
};
if ( cArgs < ECSP_START_NAME )
{
return ERROR_INVALID_PARAMETER ;
}
const TCHAR * pszName = pszParms[ ECSP_NAME ] ;
const TCHAR * pszDisplayName = pszParms[ ECSP_DISPLAY_NAME ] ;
const TCHAR * pszPath = pszParms[ ECSP_BINARY_PATH ] ;
const TCHAR * pszDependencies = CvtList( pszParms[ ECSP_DEPENDENCIES ],
szDependencies,
sizeof szDependencies ) ;
const TCHAR * pszAccount = cArgs > ECSP_START_NAME
? pszParms[ ECSP_START_NAME ]
: NULL ;
const TCHAR * pszPassword = cArgs > ECSP_PASSWORD
? pszParms[ ECSP_PASSWORD ]
: NULL ;
const TCHAR * pszGroup = pszParms[ ECSP_GROUP_NAME ] ;
// NULL the account and password parameters if necessary,
// then default them.
if ( pszAccount != NULL )
{
if ( ::strlenf( pszAccount ) == 0 )
pszAccount = NULL ;
}
if ( pszPassword != NULL )
{
if ( ::strlenf( pszPassword ) == 0 )
pszPassword = NULL ;
}
UINT uiStart = CvtDec( pszParms[ ECSP_START ] ) ;
UINT uiType = CvtDec( pszParms[ ECSP_TYPE ] ) ;
UINT uiError = CvtDec( pszParms[ ECSP_ERROR_CONTROL ] ) ;
//
// See if the "ObjectName" must be defaulted. It's interpreted
// as "account context in which to run process" for services,
// and as "NT object name" for drivers.
//
if ( pszAccount == NULL && ! (uiType & SERVICE_DRIVER) )
{
pszAccount = LOCAL_SYSTEM_USER_NAME ;
}
SC_MANAGER * pScManager = NULL ;
SC_SERVICE * pScService = NULL ;
do // Pseudo-loop for error breakuot
{
TRACEEOL( SZ("NCPA/SETP: Create service named: ") << pszName ) ;
// Construct an SC_MANAGER to handle the request
pScManager = new SC_MANAGER( NULL, SVC_CTRL_ACCESS ) ;
if ( pScManager == NULL )
{
err = ERROR_NOT_ENOUGH_MEMORY ;
break ;
}
if ( err = pScManager->QueryError() )
break ;
// Create the new service object
#if defined(DEBUG)
TRACEEOL( SZ("NCPA/SETP: service type: ") << uiType
<< SZ(" start: ") << uiStart
<< SZ(" error: ") << uiError
<< SZ(" path: [") << pszPath << SZ("]") ) ;
if ( pszGroup && ::strlenf( pszGroup ) )
{
TRACEEOL( SZ("NCPA/SETP: service group: ") << pszGroup ) ;
}
TRACEEOL( SZ("NCPA/SETP: service dependencies: [")
<< pszDependencies << SZ("]") ) ;
#endif
if ( err = pScManager->Lock())
break;
pScService = new SC_SERVICE ( *pScManager,
pszName,
pszDisplayName,
uiType,
uiStart,
uiError,
pszPath,
pszGroup,
pszDependencies,
pszAccount,
pszPassword,
SVC_CTRL_ACCESS );
if ( err = pScManager->Unlock())
break;
if ( pScService == NULL )
{
err = ERROR_NOT_ENOUGH_MEMORY ;
break ;
}
if ( err = pScService->QueryError() )
break ;
}
while ( FALSE ) ;
delete pScService ;
delete pScManager ;
return err ;
}
/*******************************************************************
NAME: RunDeleteService
SYNOPSIS: Delete a Win32 service from the Service Controller
ENTRY: TCHAR * pszService Name of Service
EXIT:
RETURNS: APIERR
NOTES: This function is only called through the CPlSetup()
export function.
HISTORY: DavidHov 5/26/92 Created
********************************************************************/
APIERR RunDeleteService ( const TCHAR * pszService )
{
APIERR err ;
// Create the Service Controller access object
TRACEEOL( SZ("NCPA/SETP: Delete service named: ") << pszService ) ;
SC_MANAGER scMgr( NULL, SVC_CTRL_ACCESS );
if ( err = scMgr.QueryError() )
{
return err ;
}
if ( err = scMgr.Lock())
return err;
SC_SERVICE scSvc( scMgr, pszService, SVC_CTRL_ACCESS );
if ( err = scSvc.QueryError() )
{
scMgr.Unlock();
return err ;
}
err = scSvc.Delete() ;
if ( err = scMgr.Unlock())
return err;
return err ;
}
/*******************************************************************
NAME: RunStartService
SYNOPSIS: Start a service
ENTRY: TCHAR * pszParms [] command line parameters from SETUP
pszParms [0] String: Name of Service
pszParms [1] Decimal: MS to sleep after starting
pszParms [2] String: passed to service; all
subsequent parms are also
passed to the service
INT cArgs Number of arguments passed
BOOL fStartOk If TRUE, service is checked to
see if it's already running.
If so, it's not an error.
EXIT: nothing
RETURNS: APIERR
NOTES: This function is only called through the CPlSetup()
export function.
HISTORY:
********************************************************************/
APIERR RunStartService (
const TCHAR * pszParms [],
INT cArgs,
BOOL fStartOk = FALSE )
{
APIERR err = 0 ;
DWORD dwPostStartSleep = 0 ;
INT cSvcArgs = cArgs - 2 ;
// Maximum time to wait for service to attain "running" state
const DWORD dwSvcMaxSleep = 60000 ;
if ( cSvcArgs < 0 )
cSvcArgs = 0 ;
// Must have at least the name of the service
if ( cArgs < 1 )
{
return ERROR_INVALID_PARAMETER ;
}
// If extra sleep desired, convert and constrain it.
if ( cArgs >= 2 )
{
dwPostStartSleep = CvtDec( pszParms[1] ) ;
if ( dwPostStartSleep > dwSvcMaxSleep )
dwPostStartSleep = dwSvcMaxSleep ;
}
if ( (err = NcpaStartService( pszParms[0], NULL, TRUE, cSvcArgs, & pszParms[2] )) == 0 )
{
// If an extra delay is desired after starting the service,
// do it.
if ( dwPostStartSleep )
{
::Sleep( dwPostStartSleep ) ;
}
}
TRACEEOL( SZ("NCPA/SETP: Start service returned: ") << err ) ;
return err ;
}
/*******************************************************************
NAME: RunSecureKey
SYNOPSIS: Change the security on a Registry key. This
function is very limited; it uses the SETUP form
of a Registry handle (a string prefixed with a '|'
character) and allows the security descriptor to be
changed to one of the limited range defined in
..\NCPA\NCPAACL.CXX.
This routine was written to support changed ACLs
on the keys associated with the Replicator service,
which require "replicator alias all" in addition
to the standard SETUP/NCPA process DACL settings.
ENTRY: TCHAR * pszHandle SETUP-formatted string handle
to open registry key
TCHAR * pszIndex string decimal number of
security to apply
EXIT:
RETURNS: APIERR
NOTES: This function is only called through the CPlSetup()
export function.
HISTORY:
********************************************************************/
APIERR RunSecureKey ( const TCHAR * pszHandle, const TCHAR * pszIndex )
{
HKEY hKey = CvtRegHandle( pszHandle ) ;
INT iSec = CvtDec( pszIndex ) ;
PSECURITY_ATTRIBUTES pSecAttr = NULL ;
APIERR err ;
if ( ! hKey )
return ERROR_INVALID_HANDLE ;
if ( iSec >= NCSA_MAX )
return ERROR_INVALID_PARAMETER ;
err = ::NcpaCreateSecurityAttributes( & pSecAttr, iSec ) ;
if ( err == 0 )
{
err = ::RegSetKeySecurity( hKey,
DACL_SECURITY_INFORMATION,
pSecAttr->lpSecurityDescriptor ) ;
}
::NcpaDestroySecurityAttributes( pSecAttr ) ;
return err ;
}
/*******************************************************************
NAME: RunSecureService
SYNOPSIS: Change the security on a Win32 Service. See the
limitations described for RunSecureKey() above.
ENTRY: TCHAR * pszService name of service to be modified
TCHAR * pszIndex string decimal number of
security to apply
EXIT: Nothing
RETURNS: APIERR
NOTES: This function is only called through the CPlSetup()
export function.
HISTORY:
********************************************************************/
APIERR RunSecureService (
const TCHAR * pszService,
const TCHAR * pszIndex )
{
APIERR err ;
PSECURITY_ATTRIBUTES pSecAttr = NULL ;
// Convert the ACL index to decimal
INT iSec = CvtDec( pszIndex ) ;
if ( iSec >= NCSA_MAX )
return ERROR_INVALID_PARAMETER ;
// Create the Service Controller access object
TRACEEOL( SZ("NCPA/SETP: Change security on service named: ")
<< pszService ) ;
SC_MANAGER scMgr( NULL, SVC_CTRL_ACCESS );
if ( err = scMgr.QueryError() )
{
return err ;
}
// Create the Service object
if ( err = scMgr.Lock())
return err;
SC_SERVICE scSvc( scMgr, pszService, SVC_CTRL_ACCESS );
if ( err = scSvc.QueryError() )
{
scMgr.Unlock();
return err ;
}
err = ::NcpaCreateSecurityAttributes( & pSecAttr, iSec ) ;
if ( err == 0 )
{
err = scSvc.SetSecurity( DACL_SECURITY_INFORMATION,
pSecAttr->lpSecurityDescriptor ) ;
}
::NcpaDestroySecurityAttributes( pSecAttr ) ;
if ( err = scMgr.Unlock())
return err;
return err ;
}
/*******************************************************************
NAME: RunWinsockMapping
SYNOPSIS: Extract Winsock mapping information from a transport's
companion DLL and store it into the Registry.
ENTRY: TCHAR * pszParms [] command line parameters from SETUP
pszParms [0] String: name of DLL
pszParms [1] String: SETUP-format Registry key
handle.
EXIT: nothing
RETURNS: APIERR
NOTES: This function is only called through the CPlSetup()
export function.
HISTORY:
********************************************************************/
#define WSHWINSOCKMAPPING "WSHGetWinsockMapping"
#define WSH_MappingValueName SZ("Mapping")
#define WSH_MAX_MAPPING_DATA 8192
APIERR RunWinsockMapping ( const TCHAR * pszDllName, const TCHAR * pszHandle )
{
HKEY hKey = NULL ;
HMODULE hDll = NULL ;
APIERR err = 0 ;
PWINSOCK_MAPPING pMapTriples = NULL ;
PWSH_GET_WINSOCK_MAPPING pMapFunc = NULL ;
DWORD cbMapping ;
TCHAR tchExpandedName [MAX_PATH+1] ;
INT cb ;
do // Pseudo-loop
{
pMapTriples = (PWINSOCK_MAPPING) (new CHAR [WSH_MAX_MAPPING_DATA]);
if ( ! pMapTriples )
{
err = ERROR_NOT_ENOUGH_MEMORY ;
break ;
}
// Convert the SETUP-fprmatted Registry key handle
if ( (hKey = CvtRegHandle( pszHandle )) == NULL )
{
err = ERROR_INVALID_HANDLE ;
break ;
}
// Expand any environment strings in the DLL path string.
cb = ::ExpandEnvironmentStrings( pszDllName,
tchExpandedName,
sizeof tchExpandedName ) ;
if ( cb == 0 || cb > sizeof tchExpandedName )
{
err = ERROR_INVALID_NAME ;
break ;
}
// Bind to the DLL
if ( (hDll = ::LoadLibrary( tchExpandedName )) == NULL )
{
err = ::GetLastError() ;
break ;
}
// Get the address of the export
pMapFunc = (PWSH_GET_WINSOCK_MAPPING) ::GetProcAddress( hDll,
WSHWINSOCKMAPPING ) ;
if ( ! pMapFunc )
{
err = ERROR_INVALID_FUNCTION ;
break ;
}
// Call the export to return the mapping table
cbMapping = (*pMapFunc)( pMapTriples, WSH_MAX_MAPPING_DATA ) ;
if ( cbMapping > WSH_MAX_MAPPING_DATA )
{
err = ERROR_NOT_ENOUGH_MEMORY ;
break ;
}
// Store the mapping info into the Registry
err = ::RegSetValueEx( hKey,
WSH_MappingValueName,
0,
REG_BINARY,
(LPBYTE) pMapTriples,
cbMapping ) ;
}
while ( FALSE );
if ( pMapTriples )
{
delete (CHAR *) pMapTriples ;
}
if ( hDll )
{
::FreeLibrary( hDll ) ;
}
return err ;
}
/*******************************************************************
NAME: RunErrorMessage
SYNOPSIS: Convert an error message to text.
ENTRY: TCHAR * pszParms [] error message number in ASCII decimal
NLS_STR * pnlsResult string in which to store text.
EXIT:
RETURNS: APIERR
NOTES: This function is only called through the CPlSetup()
export function.
HISTORY:
********************************************************************/
APIERR RunErrorMessage ( const TCHAR * pszError, NLS_STR * pnlsResult )
{
NLS_STR nlsTemp ;
APIERR err = nlsTemp.Load( CvtDec( pszError ) ) ;
if ( err == 0 )
{
err = appendToInfList( pnlsResult, nlsTemp, ISC_Before ) ;
}
return err ;
}
/*************************************************************************
NAME: DETECTION_CONTROL
SYNOPSIS: Interger-based wrapper for DETECTION_MANAGER
INTERFACE: Normal construction
PARENT: DETECTION_MANAGER
USES: SLIST_OF_CARD_REFERENCE
CAVEATS:
NOTES: This is a simple wrapper for DETECTION_MANAGER which
maintains an SLIST of the CARD_REFERENCEs returned
by the detection algorithm. This allows the caller
to deal with simple (and easily verifiable) integers
as indexes into the card list.
HISTORY: DavidHov 11/4/92 Created
**************************************************************************/
class DETECTION_CONTROL : public DETECTION_MANAGER
{
public:
DETECTION_CONTROL() ;
~ DETECTION_CONTROL () ;
// Return (externally opaque) detected card reference.
APIERR DetectCard ( INT * piCard,
BOOL fFirst = TRUE,
BOOL fSingleStep = FALSE ) ;
// Release a CARD_REFERENCE index created by DetectCard
VOID ReleaseCard ( INT iCard ) ;
// Return the object pointer corresponding to the list index
CARD_REFERENCE * NthCard ( INT iIndex ) ;
VOID ReleaseAllCards () ;
INT OpenCard ( const TCHAR * pszOptionName,
INT iBus,
INTERFACE_TYPE ifType ) ;
private:
SLIST_OF_CARD_REFERENCE _slCardRef ;
};
// Try to start the netcard detection service; ignore any errors.
DETECTION_CONTROL :: DETECTION_CONTROL ()
{
const TCHAR * apszParams [2] = { SZ("NETDETECT"), NULL } ;
RunStartService( (const TCHAR **)apszParams, 1, TRUE ) ;
}
DETECTION_CONTROL :: ~ DETECTION_CONTROL ()
{
}
CARD_REFERENCE * DETECTION_CONTROL :: NthCard ( INT iIndex )
{
ITER_SL_OF(CARD_REFERENCE) islCard( _slCardRef ) ;
CARD_REFERENCE * pResult = NULL ;
for ( INT i = 0 ;
(pResult = islCard.Next()) && i < iIndex ;
i++ ) ;
return pResult ;
}
// This is the global instance pointer for DETECTION_CONTROL
DETECTION_CONTROL * pDtCtl = NULL ;
/*******************************************************************
NAME: DETECTION_CONTROL::DetectCard
SYNOPSIS: Perform DETECTION_MANAGER::DetectCard(), but
convert the resulting CARD_REFERENCE to an
index into the list.
ENTRY:
EXIT:
RETURNS:
NOTES:
HISTORY:
********************************************************************/
APIERR DETECTION_CONTROL :: DetectCard (
INT * piCard,
BOOL fFirst,
BOOL fSingleStep )
{
CARD_REFERENCE * pCardRef = NULL ;
APIERR err = DETECTION_MANAGER::DetectCard( & pCardRef,
fFirst,
fSingleStep ) ;
// If successful, append the card to the list.
if ( err == 0 )
{
if ( (err = _slCardRef.Append( pCardRef )) == 0 )
*piCard = _slCardRef.QueryNumElem() - 1 ;
}
return err ;
}
/*******************************************************************
NAME: DETECTION_CONTROL::ReleaseCard
SYNOPSIS: Perform DETECTION_CONTROL::ReleaseCard() using
a list index.
ENTRY:
EXIT:
RETURNS:
NOTES:
HISTORY:
********************************************************************/
VOID DETECTION_CONTROL :: ReleaseCard ( INT iCard )
{
ITER_SL_OF(CARD_REFERENCE) islCardRef( _slCardRef ) ;
CARD_REFERENCE * pCardRef ;
for ( ; islCardRef.Next() && iCard ; --iCard ) ;
if ( pCardRef = _slCardRef.Remove( islCardRef ) )
{
DETECTION_MANAGER::ReleaseCard( pCardRef ) ;
}
}
/*******************************************************************
NAME: DETECTION_CONTROL::ReleaseAllCards
SYNOPSIS: Release all detected card instances.
ENTRY:
EXIT:
RETURNS:
NOTES:
HISTORY:
********************************************************************/
VOID DETECTION_CONTROL :: ReleaseAllCards ()
{
while ( _slCardRef.QueryNumElem() )
{
ReleaseCard( 0 ) ;
}
}
/*******************************************************************
NAME: DETECTION_CONTROL::OpenCard
SYNOPSIS: Open a card handle given the option name
and bus parameters.
ENTRY: const TCHAR * name of option
INT iBus bus index
INTERFACE_TYPE ifType bus type
EXIT: -1 if failure; else, the card index
for this card.
RETURNS:
NOTES:
HISTORY:
********************************************************************/
INT DETECTION_CONTROL :: OpenCard (
const TCHAR * pszOptionName,
INT iBus,
INTERFACE_TYPE ifType )
{
INT iCard = -1 ;
CARD_REFERENCE * pCardRef =
DETECTION_MANAGER::OpenCard( pszOptionName, iBus, ifType ) ;
if ( pCardRef != NULL
&& _slCardRef.Append( pCardRef ) == 0 )
{
iCard = _slCardRef.QueryNumElem() - 1 ;
}
return iCard ;
}
/*******************************************************************
NAME: RunDetectEnd
SYNOPSIS: Destroy the single instance of a DETECTION_CONTROL
object.
ENTRY:
EXIT:
RETURNS:
NOTES:
HISTORY:
********************************************************************/
APIERR RunDetectEnd ()
{
// call temporary free resource
if ( pDtCtl )
pDtCtl->FreeParameterSet( PCMCIABus, 0, NULL, TRUE );
delete pDtCtl ;
pDtCtl = NULL ;
return 0 ;
}
/*******************************************************************
NAME: RunDetectReset
SYNOPSIS: Reset iteration against the DETECTION_MANAGER object.
ENTRY:
EXIT:
RETURNS:
NOTES: Discards all current CARD_REFERENCE instances
HISTORY:
********************************************************************/
APIERR RunDetectReset ()
{
APIERR err = 0 ;
if ( pDtCtl )
{
// call temporary free resource
pDtCtl->FreeParameterSet( PCMCIABus, 0, NULL, TRUE );
pDtCtl->ReleaseAllCards() ;
pDtCtl->ResetIteration() ;
}
else
{
err = ERROR_INVALID_PARAMETER ;
}
return err ;
}
/*******************************************************************
NAME: RunDetectStart
SYNOPSIS: Allocate the DETECTION_CONTROL object.
ENTRY:
EXIT:
RETURNS:
NOTES:
HISTORY:
********************************************************************/
APIERR RunDetectStart ()
{
if ( pDtCtl != NULL )
{
return NO_ERROR ;
}
pDtCtl = new DETECTION_CONTROL() ;
if ( pDtCtl == NULL )
{
return ERROR_NOT_ENOUGH_MEMORY ;
}
APIERR err = pDtCtl->QueryError() ;
// If an error occurred, delete the bogus object
if ( err )
{
RunDetectEnd() ;
}
return err ;
}
/*******************************************************************
NAME: RunDetectCard
SYNOPSIS: Attempt to detect a netcard.
ENTRY:
EXIT:
RETURNS: APIERR if failure
NOTES: After help from CPlSetup(), output appears as:
{ <error code>,
OPTIONNAME,
<card index>,
<numeric card type code>,
<detection confidence level>,
<bus interface type>,
<bus number>
}
The outer braces and error code are inserted by
the caller, CPlSetup().
HISTORY:
********************************************************************/
APIERR RunDetectCard ( NLS_STR * pnlsResult )
{
INT iCard ;
CARD_REFERENCE * pCardRef ;
APIERR err = 0 ;
WCHAR chBuffer[ 4000 ];
do
{
// Check to see if there's a DETECTION_CONTROL object
if ( pDtCtl == NULL )
{
err = ERROR_INVALID_PARAMETER ;
break ;
}
// Detect the next card
if ( err = pDtCtl->DetectCard( & iCard ) )
break ;
// Get the corresponding card reference.
pCardRef = pDtCtl->NthCard( iCard ) ;
ASSERT( pCardRef != NULL ) ;
// Output appears as:
// {"<error code>","CARDOPTIONNAME","<card handle>"}
if ( err = appendToInfList( pnlsResult,
pCardRef->QueryCardType()->QueryOptionName(),
ISC_Both ) )
break ;
// Append card index to result
if ( err = appendToInfList( pnlsResult, iCard, ISC_After ) )
break ;
// Append numeric card type to result
if ( err = appendToInfList( pnlsResult,
pCardRef->QueryCardType()->QueryType(),
ISC_After ) )
break ;
// Append overall detection confidence level to list
if ( err = appendToInfList( pnlsResult,
pCardRef->QueryConfidence(),
ISC_After ) )
break ;
// Append interface type to result
if ( err = appendToInfList( pnlsResult,
(INT) pCardRef->QueryIfType(),
ISC_After ) )
break ;
// Append bus number to result
if ( err = appendToInfList( pnlsResult,
pCardRef->QueryBus() ))
break ;
if ( pCardRef->QueryIfType() == PCMCIABus )
{
// call temporary claim the resource for PCMCIA
pCardRef->QueryCardType()->Dll()->QueryCfg( pCardRef->QueryHandle(), chBuffer, sizeof chBuffer );
pDtCtl->ClaimParameterSet( pCardRef->QueryIfType(), pCardRef->QueryBus(), chBuffer, TRUE, TRUE );
}
} while ( FALSE ) ;
return err ;
}
/*******************************************************************
NAME: RunDetectGetParams
SYNOPSIS: Given the name of a netcard option, return the
SETUP INF list describing its parameters, their
constraints and possible legal values.
ENTRY: const TCHAR * name of netcard option;
e.g., "DEC201".
EXIT: APIERR if failure
RETURNS: pnlsResult contains list of lists
of paramters, etc.
NOTES:
HISTORY:
********************************************************************/
APIERR RunDetectGetParams (
const TCHAR * pszOptionName,
NLS_STR * pnlsResult )
{
TCHAR * pszParams = NULL ;
CARDTYPE_REFERENCE * pCardType = NULL ;
APIERR err = 0 ;
CFG_RULE_SET crsParams ;
TEXT_BUFFER txBuff ;
do
{
if ( pDtCtl == NULL )
{
err = ERROR_INVALID_PARAMETER ;
break ;
}
pCardType = pDtCtl->FindOptionName( pszOptionName ) ;
if ( pCardType == NULL )
{
err = ERROR_FILE_NOT_FOUND ;
break ;
}
pszParams = pCardType->QueryConfigurationOptions() ;
if ( pszParams == NULL )
{
err = ERROR_FILE_NOT_FOUND ;
break ;
}
if ( err = crsParams.Parse( pszParams, PARSE_CTL_FULL_SYNTAX ) )
break ;
// Convert the parameter list to an INF-style list at a
// nesting level of 1.
if ( err = crsParams.TextifyInf( & txBuff, 1 ) )
break ;
if ( err = appendToInfList( pnlsResult, txBuff, ISC_Before ) )
break ;
} while ( FALSE ) ;
delete pszParams ;
return err ;
}
/*******************************************************************
NAME: RunDetectQueryCard
SYNOPSIS: Given the index of a previously detected card,
return its detectable configuration parameters.
ENTRY:
EXIT:
RETURNS:
NOTES:
HISTORY:
********************************************************************/
APIERR RunDetectQueryCard (
const TCHAR * pszCardIndex,
NLS_STR * pnlsResult )
{
INT iCard = (INT) CvtDec( pszCardIndex ) ;
CARD_REFERENCE * pCard = NULL ;
APIERR err = 0 ;
TCHAR * pszConfig = NULL ;
CFG_RULE_SET crsParams ;
TEXT_BUFFER txBuff ;
do
{
if ( pDtCtl == NULL )
{
err = ERROR_INVALID_PARAMETER ;
break ;
}
pCard = pDtCtl->NthCard( iCard ) ;
if ( pCard == NULL )
{
err = ERROR_INVALID_PARAMETER ;
break ;
}
pszConfig = pCard->QueryConfiguration() ;
if ( pszConfig == NULL )
{
err = ERROR_INVALID_PARAMETER ;
break ;
}
// Parse the resulting SProlog-style list.
if ( err = crsParams.Parse( pszConfig, PARSE_CTL_FULL_SYNTAX ) )
break ;
// Convert the parameter list to an INF-style list at a
// nesting level of 1.
if ( err = crsParams.TextifyInf( & txBuff, 1 ) )
break ;
if ( err = appendToInfList( pnlsResult, txBuff, ISC_Before ) )
break ;
} while ( FALSE ) ;
delete pszConfig ;
return err ;
}
/*******************************************************************
NAME: RunDetectVerifyCard
SYNOPSIS: Given the index of a previously detected card,
return the SETUP INF list describing its
detected parameters.
ENTRY: const TCHAR * pszCardIndex ASCII decimal numeric card index
const TCHAR * pszConfigData INF nested lists of confiuration
parameters.
EXIT:
RETURNS: APIERR
NOTES: If the card index is 1000, this is a special value
indicating that NULL should be passed to
DETECTION_MANAGER::VerifyConfiguration(). This allows
resource claiming to occur for non-detected cards.
HISTORY:
********************************************************************/
APIERR RunDetectVerifyCard (
const TCHAR * pszCardIndex,
const TCHAR * pszConfigData )
{
const INT iCardNotDetected = 1000 ;
INT iCard = (INT) CvtDec( pszCardIndex ) ;
CARD_REFERENCE * pCard = NULL ;
APIERR err = 0 ;
CFG_RULE_SET crsParams ;
do
{
if ( pDtCtl == NULL )
{
err = ERROR_INVALID_PARAMETER ;
break ;
}
if ( iCard != iCardNotDetected
&& (pCard = pDtCtl->NthCard( iCard )) == NULL )
{
err = ERROR_INVALID_PARAMETER ;
break ;
}
if ( err = crsParams.ParseInfList( pszConfigData ) )
{
TRACEEOL( SZ("NCPA/SETP: DTVERIFY: cfg param INF list parse failed") ) ;
break ;
}
err = pDtCtl->VerifyConfiguration( pCard, & crsParams, TRUE ) ;
} while ( FALSE ) ;
return err ;
}
/*******************************************************************
NAME: RunDetectOpen
SYNOPSIS: Open a card handle given the necessary data.
ENTRY: const TCHAR * * Data arguments
arg[0] netcard option name
arg[1] bus type
arg[2] bus number
EXIT: NLS_STR * pnlsResult contains numeric card index
RETURNS: APIERR
NOTES:
HISTORY:
********************************************************************/
APIERR RunDetectOpen (
const TCHAR * pszNetcardOption,
const TCHAR * pszBusType,
const TCHAR * pszBusNumber,
NLS_STR * pnlsResult )
{
INT iCard = 0 ;
INT iBusType = CvtDec( pszBusType ) ;
INT iBusNum = CvtDec( pszBusNumber ) ;
CARD_REFERENCE * pCard = NULL ;
APIERR err = 0 ;
do
{
if ( pDtCtl == NULL )
{
err = ERROR_INVALID_PARAMETER ;
break ;
}
iCard = pDtCtl->OpenCard( pszNetcardOption,
iBusType,
(INTERFACE_TYPE) iBusNum ) ;
if ( iCard < 0 )
{
err = ERROR_FILE_NOT_FOUND ;
break ;
}
// Append numeric card type to result
err = appendToInfList( pnlsResult, iCard ) ;
} while ( FALSE ) ;
return err ;
}
/*******************************************************************
NAME: RunDetectClaim
SYNOPSIS: Claim the list of resources given.
ENTRY: const TCHAR * pszConfigData INF nested lists of confiuration
parameters.
EXIT:
RETURNS: APIERR
NOTES:
HISTORY:
********************************************************************/
APIERR RunDetectClaim ( const TCHAR * pszConfigData )
{
APIERR err = 0 ;
CFG_RULE_SET crsParams ;
do
{
if ( pDtCtl == NULL )
{
err = ERROR_INVALID_PARAMETER ;
break ;
}
if ( err = crsParams.ParseInfList( pszConfigData ) )
{
TRACEEOL( SZ("NCPA/SETP: DTVERIFY: cfg param INF list parse failed") ) ;
break ;
}
err = pDtCtl->VerifyConfiguration( NULL, & crsParams, TRUE ) ;
} while ( FALSE ) ;
return err ;
}
/*******************************************************************
NAME: RunDetectGetString
SYNOPSIS: Given the name of a netcard option and a
numeric string index, return the corresponding
string data.
ENTRY: const TCHAR * name of netcard option;
e.g., "DE201".
const TCHAR * string index in character form
EXIT: APIERR if failure
RETURNS: pnlsResult contains list of lists
of paramters, etc.
NOTES: This function returns information strings
relative to a particular netcard type and
the DLL which supports it.
Such strings include the displayable name of the
card, its manufacturer, etc.
HISTORY:
********************************************************************/
APIERR RunDetectGetString (
const TCHAR * pszOptionName,
const TCHAR * pszStringIndex,
NLS_STR * pnlsResult )
{
INT iString = (INT) CvtDec( pszStringIndex ) ;
APIERR err = 0 ;
CARDTYPE_REFERENCE * pCardType ;
TCHAR chBuffer [ 200 ] ;
do
{
if ( pDtCtl == NULL )
{
err = ERROR_INVALID_PARAMETER ;
break ;
}
pCardType = pDtCtl->FindOptionName( pszOptionName ) ;
if ( pCardType == NULL )
{
err = ERROR_FILE_NOT_FOUND ;
break ;
}
err = pCardType->Dll()->Identify( pCardType->QueryType() + iString,
chBuffer,
sizeof chBuffer ) ;
if ( err )
break ;
err = appendToInfList( pnlsResult, chBuffer, ISC_Before ) ;
} while ( FALSE ) ;
return err ;
}
/*******************************************************************
NAME: RunDetectGetParamName
SYNOPSIS: Given the name of a netcard option and a
numeric string index, return the corresponding
string data.
ENTRY: const TCHAR * name of netcard option;
e.g., "DE201".
const TCHAR * name of parameter to retrieve
EXIT: APIERR if failure
RETURNS: pnlsResult contains list of lists
of paramters, etc.
NOTES: This function returns the displayable name
of the parameter whose symbolic name is given
in the pszParamName parameter.
HISTORY:
********************************************************************/
APIERR RunDetectGetParamName (
const TCHAR * pszOptionName,
const TCHAR * pszParamName,
NLS_STR * pnlsResult )
{
APIERR err = 0 ;
CARDTYPE_REFERENCE * pCardType ;
TCHAR chBuffer [ 200 ] ;
do
{
if ( pDtCtl == NULL )
{
err = ERROR_INVALID_PARAMETER ;
break ;
}
pCardType = pDtCtl->FindOptionName( pszOptionName ) ;
if ( pCardType == NULL )
{
err = ERROR_FILE_NOT_FOUND ;
break ;
}
err = pCardType->Dll()->QueryParamName(
pszParamName,
chBuffer,
sizeof chBuffer ) ;
if ( err )
break ;
err = appendToInfList( pnlsResult, chBuffer, ISC_Before ) ;
} while ( FALSE ) ;
return err ;
}
/*******************************************************************
NAME: getAdapterList
SYNOPSIS: Given the name of a service, return a STRLIST
consisting of the names of the adapters to which
the service is currently bound.
ENTRY: REG_KEY * prkMachine REG_KEY for
HKEY_LOCAL_MACHINE
const TCHAR * name of service
STRLIST * * location to store ptr
to created STRLIST
EXIT: STRLIST * * updated
RETURNS: APIERR if failure
NOTES:
HISTORY:
********************************************************************/
static APIERR getAdapterList (
REG_KEY * prkMachine,
const TCHAR * pszServiceName,
STRLIST * * ppslResult )
{
APIERR err ;
TCHAR tchKeyName [ MAX_PATH ] ;
NLS_STR nlsKeyName ;
*ppslResult = NULL ;
wsprintf( tchKeyName,
SZ("%s%c%s%c%s"),
RGAS_SERVICES_HOME,
TCH('\\'),
pszServiceName,
TCH('\\'),
RGAS_LINKAGE_NAME ) ;
if ( err = nlsKeyName.CopyFrom( tchKeyName ) )
return err ;
REG_KEY rkLinkage( *prkMachine, nlsKeyName ) ;
if ( err = rkLinkage.QueryError() )
return err ;
err = rkLinkage.QueryValue( RGAS_ROUTE_VALUE_NAME, ppslResult ) ;
if ( err == 0 )
{
ITER_STRLIST isl( **ppslResult ) ;
NLS_STR * pnlsNext ;
// Iterate over the strings. Locate the last double-quoted
// substring; remove all but the enclosed substring from each
// string.
for ( ; (err == 0) && (pnlsNext = isl.Next()) ; )
{
INT cQuote = 0,
i = 0 ;
const TCHAR * pch = pnlsNext->QueryPch(),
* pch2 = NULL ;
TCHAR tchAdapterName [MAX_PATH] ;
// Iterate over the string, remembering the start of the
// last sub-string enclosed in double quotes.
for ( ; *pch ; pch++ )
{
if ( *pch == TCH('\"') )
{
if ( ++cQuote & 1 )
pch2 = pch ;
}
}
// Extact just the adapter name from the string; if not
// found, leave the string empty.
if ( pch2 )
{
for ( pch2++ ; *pch2 && *pch2 != TCH('\"') ; )
{
tchAdapterName[i++] = *pch2++ ;
if ( i >= sizeof tchAdapterName - 1 )
break ;
}
}
tchAdapterName[i] = 0 ;
TRACEEOL("NCPA/SETP: adapter name ["
<< tchAdapterName
<< SZ("] extracted from ")
<< pnlsNext->QueryPch() );
err = pnlsNext->CopyFrom( tchAdapterName ) ;
}
}
if ( err )
{
delete *ppslResult ;
*ppslResult = NULL ;
}
return err ;
}
/*******************************************************************
NAME: RunMCSAlteredCheck
SYNOPSIS: See if MCS products need to recall during binding phase.
ENTRY: const TCHAR * name of service
EXIT: Nothing.
RETURNS: APIERR: 0 (NO_ERROR) implies no reconfiguration
required; any other value causes IP Address
configuration dialog to appear.
NOTES: THIS FUNCTION IS HIGHLY SPECIFIC TO THE REGISTRY FORMATS
USED BY MCS for XNS and IPX.
The criteria are as follows (XXX is the product name):
1) system\currentcontrolset\services\XXX\Netconfig\Driver01
must exist.
2) The adaptername string must exist.
3) system\currentcontrolset\services\$(adaptername)
must exist.
4) make sure that the card is bound to the service.
5) make sure that the service is bound to only one adapter.
HISTORY: terryk 4-7-93 Created
********************************************************************/
APIERR RunMCSAlteredCheck( const TCHAR * pszArg1 )
{
APIERR err = NERR_Success;
REG_KEY rkMachine( HKEY_LOCAL_MACHINE ) ;
do
{
if ( err = rkMachine.QueryError() )
break;
NLS_STR nlsMCSLocation = RGAS_SERVICES_HOME;
nlsMCSLocation.strcat( SZ("\\"));
nlsMCSLocation.strcat( pszArg1 );
nlsMCSLocation.strcat( SZ("\\NetConfig\\Driver01") );
REG_KEY regMCS( rkMachine, nlsMCSLocation );
if ( err = regMCS.QueryError() )
break;
NLS_STR nlsAdapter;
// get adapter name from Driver01
if ( err = regMCS.QueryValue( SZ("AdapterName"), &nlsAdapter ))
break;
if ( nlsAdapter.QueryNumChar() == 0 )
{
// no adapter name currently assigned...
err = 3;
break;
}
NLS_STR nlsCard = RGAS_SERVICES_HOME;
nlsCard.strcat( SZ("\\") );
nlsCard.strcat( nlsAdapter );
// make sure the card exists in the registry
REG_KEY regAdapter( rkMachine, nlsCard );
if ( err = regAdapter.QueryError())
break;
STRLIST * pslAdapters = NULL;
NLS_STR * pnlsNext = NULL;
// Get a STRLIST of adapter names.
if ( err = getAdapterList( & rkMachine, pszArg1, & pslAdapters ) )
break ;
ITER_STRLIST isl( *pslAdapters ) ;
// Attempt to match the primary adapter to (one of)
// the current binding(s).
for ( ; pnlsNext = isl.Next() ; )
{
if ( pnlsNext->_stricmp( nlsAdapter ) == 0 )
break;
}
// If > 1 active binding or no match on current adapter,
// reconfiguration is necessary.
if ( pslAdapters->QueryNumElem() > 1 || pnlsNext == NULL )
err = 3 ;
delete pslAdapters;
}
while ( FALSE );
return err;
}
/*******************************************************************
NAME: RunTcpipAlteredCheck
SYNOPSIS: See if TCP/IP's "bindings review" phase should
bring up the configuration dialog. In other
words, has anything substantive changed?
ENTRY: Nothing.
EXIT: Nothing.
RETURNS: APIERR: 0 (NO_ERROR) implies no reconfiguration
required; any other value causes IP Address
configuration dialog to appear.
NOTES: The criteria are as follows:
1) All adapters bound to TCP/IP must have
IP addresses.
2) NBT must be bound to one and only one
adapter.
3) The adapter over which NBT is running
is still in use by TCP/IP.
4) NBT/parameters/permanentname must exist
HISTORY:
********************************************************************/
APIERR RunTcpipAlteredCheck ()
{
APIERR err = 0 ;
STRLIST * pslAdapters = NULL,
* pslNbtAdapters = NULL ;
TCHAR * pszTcpip = SZ("Tcpip") ;
NLS_STR * pnlsNext ;
NLS_STR nlsIpAddr ;
NLS_STR nlsKeyName ;
TCHAR tchBuffer [ MAX_PATH ] ;
REG_KEY rkMachine( HKEY_LOCAL_MACHINE ) ;
do
{
if ( err = rkMachine.QueryError() )
return err ;
// Get a STRLIST of adapter names.
if ( err = getAdapterList( & rkMachine, pszTcpip, & pslAdapters ) )
break ;
// Iterate over the adapter list checking that each has an IP address.
ITER_STRLIST isl( *pslAdapters ) ;
for ( ; (err == 0) && (pnlsNext = isl.Next()) ; )
{
TRACEEOL("NCPA/SETP: checking for IP address for adapter named "
<< pnlsNext->QueryPch() );
wsprintf( tchBuffer,
SZ("%s%c%s%s%s"),
RGAS_SERVICES_HOME,
TCH('\\'),
pnlsNext->QueryPch(),
SZ("\\Parameters\\"),
pszTcpip ) ;
// Criterion 1: if any bound adapter lacks an IP address,
// configuration dialog is mandatory.
if ( err = nlsKeyName.CopyFrom( tchBuffer ) )
break ;
REG_KEY rkAdapter( rkMachine, nlsKeyName, KEY_READ ) ;
if ( (err = rkAdapter.QueryError()) == 0 )
{
err = rkAdapter.QueryValue( SZ("IPAddress"), & nlsIpAddr ) ;
}
}
if ( err )
break ;
// Ok, we made it so far. Next, check that NBT's bound adapter is
// still connected to TCP/IP.
// Get a STRLIST of NBT's adapter names.
if ( err = getAdapterList( & rkMachine, SZ("Nbt"), & pslNbtAdapters ) )
break ;
// Criterion 2: if NBT is not connected to exactly one adapter,
// we must run reconfiguration dialog.
if ( pslNbtAdapters->QueryNumElem() != 1 )
{
err = ERROR_TOO_MANY_NAMES ;
break ;
}
// Get a pointer to the one and only NBT adapter name.
ITER_STRLIST islNbt( *pslNbtAdapters ) ;
NLS_STR * pnlsNbt = islNbt.Next() ;
// Criterion 3: see if the NBT adapter is in TCP's list
for ( isl.Reset() ; pnlsNext = isl.Next() ; )
{
if ( pnlsNext->_stricmp( *pnlsNbt ) == 0 )
break ;
}
if ( pnlsNext == NULL )
{
err = ERROR_FILE_NOT_FOUND ;
break;
}
// check to make sure that NBT/parameters/permanentname exists
wsprintf( tchBuffer, SZ("%s\\NBT\\Parameters"), RGAS_SERVICES_HOME );
NLS_STR nlsNBTParameter = tchBuffer;
REG_KEY rkAdapter( rkMachine, nlsNBTParameter, KEY_READ );
if (( err = rkAdapter.QueryError()) == 0 )
{
NLS_STR nlsPermanentName;
err = rkAdapter.QueryValue( SZ("Permanentname"), & nlsPermanentName );
}
}
while ( FALSE );
delete pslAdapters ;
delete pslNbtAdapters ;
return err ;
}
/*******************************************************************
NAME: RunActivateBindings
SYNOPSIS: Given a service name and a list of bindings,
activate the bindings listed.
ENTRY: const TCHAR * pszServiceName name of service
const TCHAR * pszInfList INF list of bindings
EXIT:
RETURNS: APIERR
NOTES:
HISTORY:
********************************************************************/
APIERR RunActivateBindings (
const TCHAR * pszServiceName,
const TCHAR * pszInfList )
{
APIERR err = 0 ;
CFG_RULE_SET crsParams ;
CFG_RULE_NODE * pcrnTop,
* pcrnTemp ;
INT cBinds = 0 ;
const TCHAR * * apszBinds = NULL ;
do
{
if ( err = crsParams.ParseInfList( pszInfList ) )
{
TRACEEOL( SZ("NCPA/SETP: ACTIVBIND: INF list parse failed") ) ;
break ;
}
// Walk the parse tree, extracting the information
// necessary. Parse tree looks like this:
//
// ( ) enclosing list (CFG_RULE_SET)
// |
// ( ) enclosing list from braces {}
// |
// "string" "string" "string"...
if ( (pcrnTop = crsParams.QueryList()) == NULL
|| pcrnTop->QueryType() != CRN_NIL
|| (pcrnTop = pcrnTop->QueryNext()) == NULL
|| pcrnTop->QueryType() != CRN_LIST
|| (pcrnTop = pcrnTop->QueryList()) == NULL )
{
err = ERROR_GEN_FAILURE ;
break ;
}
// First, walk the parsed list to determine the number
// of elements.
for ( pcrnTemp = pcrnTop ; pcrnTemp = pcrnTemp->QueryNext() ; )
{
// Ignore anything that's not a string
cBinds += pcrnTemp->QueryType() == CRN_STR ;
}
// Allocate the array of pointers to active binding strings
apszBinds = new const TCHAR * [cBinds + 1] ;
if ( apszBinds == NULL )
{
err = ERROR_NOT_ENOUGH_MEMORY ;
break ;
}
// Then, walk the list to extract pointers to the strings,
// building the TCHAR * array.
for ( cBinds = 0, pcrnTemp = pcrnTop ;
pcrnTemp = pcrnTemp->QueryNext() ; )
{
if ( pcrnTemp->QueryType() == CRN_STR )
{
apszBinds[cBinds++] = pcrnTemp->QueryAtom().QueryText() ;
}
}
apszBinds[cBinds] = NULL ;
// Finally, call the activation routine.
err = ActivateBindings( pszServiceName, apszBinds ) ;
} while ( FALSE ) ;
delete (TCHAR **) apszBinds ;
return err ;
}
/*******************************************************************
NAME: CPlSetup
SYNOPSIS: Exported function to cause NCPA to run in "main
installation" mode.
ENTRY: DWORD nArgs
LPSTR apszArgs []
LPSTR * ppszResult
apszArgs[0] window handle
apszArgs[1] symbolic name of function
to be executed
See enumeration info for
list of currently supported values.
apszArgs[2] command line to be passed to
function (see RunNcpa()).
apszArgs[n] other arguments to other functions
EXIT: nothing
RETURNS: SETUP INF list form, starting with error code
E.g.:
"{ 0 }"
NOTES: The called function can return more variables into
the list by appending them onto the passed NLS_STR.
HISTORY:
beng 05-May-1992 wsprintf -> wsprintfA
********************************************************************/
#define ARGMAX 10000
BOOL FAR PASCAL CPlSetup (
DWORD nArgs, // Number of string arguments
LPSTR apszArgs[], // The arguments, NULL-terminated
LPSTR * ppszResult ) // Result variable storage
{
APIERR err = 0 ;
HWND hWnd = 0 ;
UINT iFunc ;
TCHAR * * patchArgs ;
ESETUP_FUNC esFunc ;
NLS_STR nlsResult ;
BOOL fWasDisabled ;
static CHAR achBuff [ ARGMAX ] ; // N.B. Must be static for use as
// return value to SETUP.
// Sanity Check
if ( nArgs < 2 )
{
TRACEEOL( SZ("NCPA/SETP: Invalid number of arguments to CPlSetup().") ) ;
return FALSE ;
}
// Check that we can convert the arguments to a usable form
if ( (patchArgs = CvtArgs( apszArgs, nArgs )) == NULL )
{
return FALSE ;
}
// Start the master timer (and don't return without stopping it)
// We must do this here since we aren't necessarily in the CPL
// when CPlSetup is called. It doesn't hurt to do it twice.
TRACEEOL( "NCPA/SETP: Starting master timer" );
if ( (err = BLT_MASTER_TIMER::Init()) != NERR_Success )
{
TRACEEOL( "NCPA/SETP: master timer returned " << err ) ;
return FALSE ;
}
// Convert the second argument from a string to an enum
TRACEEOL( SZ("NCPA/SETP: requested function is: ")
<< patchArgs[ESARG_FUNC] );
for ( iFunc = 0 ; setupFuncIndex[iFunc].pszToken ; iFunc++ )
{
if ( ::stricmpf( patchArgs[ESARG_FUNC],
setupFuncIndex[iFunc].pszToken ) == 0 )
break ;
}
esFunc = setupFuncIndex[iFunc].esFunc ;
// If the function references the window handle,
// convert it and control window dis/enabling.
if ( setupFuncIndex[iFunc].fUsesHwnd )
{
// Convert the first argment to a window handle.
if ( patchArgs[ESARG_HWND][0] != TCH('\0') )
{
hWnd = (HWND) CvtHex( patchArgs[ESARG_HWND] ) ;
}
// If desperate, grab any old window handle at all
if ( hWnd == 0 || ! ::IsWindow( hWnd ) )
{
TRACEEOL( SZ("NCPA/SETP: window handle passed was invalid") ) ;
hWnd = ::GetActiveWindow() ;
}
// Perform window disable/enable like the dialog manager...
fWasDisabled = ::EnableWindow( hWnd, FALSE ) ;
TRACEEOL( SZ("NCPA/SETP: EnableWindow() returned: " << fWasDisabled ) ) ;
}
switch ( esFunc )
{
case ESFUNC_NCPA:
err = RunNcpa( hWnd,
TRUE,
nArgs >= ESARG_1ST
? patchArgs[ESARG_1ST]
: NULL ) ;
break ;
case ESFUNC_DOMAIN:
err = RunDomain( hWnd,
patchArgs[ESARG_1ST],
& nlsResult );
break ;
case ESFUNC_CONNECT:
err = RunConnect( (const TCHAR * *) & patchArgs[ESARG_1ST],
nArgs - ESARG_1ST ) ;
break;
case ESFUNC_CREATE_SERVICE:
err = RunCreateService( (const TCHAR * *) & patchArgs[ESARG_1ST],
nArgs - ESARG_1ST ) ;
break ;
case ESFUNC_DELETE_SERVICE:
err = RunDeleteService( patchArgs[ESARG_1ST] ) ;
break ;
case ESFUNC_START_SERVICE:
err = RunStartService( (const TCHAR * *) & patchArgs[ESARG_1ST],
nArgs - ESARG_1ST ) ;
break;
case ESFUNC_SECURE_SERVICE:
err = RunSecureService( patchArgs[ ESARG_1ST ],
patchArgs[ ESARG_1ST + 1 ] );
break;
case ESFUNC_SECURE_REG_KEY:
err = RunSecureKey( patchArgs[ ESARG_1ST ],
patchArgs[ ESARG_1ST + 1 ] );
break ;
case ESFUNC_WINSOCK_MAPPING:
err = RunWinsockMapping( patchArgs[ ESARG_1ST ],
patchArgs[ ESARG_1ST + 1 ] );
break ;
case ESFUNC_ERROR_MESSAGE:
err = RunErrorMessage( patchArgs[ ESARG_1ST ],
& nlsResult );
break ;
case ESFUNC_DETECT_START:
err = RunDetectStart() ;
break ;
case ESFUNC_DETECT_END:
err = RunDetectEnd() ;
break ;
case ESFUNC_DETECT_RESET:
err = RunDetectReset() ;
break ;
case ESFUNC_DETECT_CARD:
err = RunDetectCard( & nlsResult ) ;
break ;
case ESFUNC_DETECT_VERIFY:
err = RunDetectVerifyCard( patchArgs[ ESARG_1ST ],
patchArgs[ ESARG_1ST + 1 ] ) ;
break ;
case ESFUNC_DETECT_QUERY:
err = RunDetectQueryCard( patchArgs[ ESARG_1ST ],
& nlsResult ) ;
break ;
case ESFUNC_DETECT_PARAMS:
err = RunDetectGetParams( patchArgs[ ESARG_1ST ],
& nlsResult ) ;
break ;
case ESFUNC_DETECT_STRING:
err = RunDetectGetString( patchArgs[ ESARG_1ST],
patchArgs[ ESARG_1ST + 1 ],
& nlsResult ) ;
break ;
case ESFUNC_DETECT_PNAME:
err = RunDetectGetParamName( patchArgs[ ESARG_1ST],
patchArgs[ ESARG_1ST + 1 ],
& nlsResult ) ;
break ;
case ESFUNC_DETECT_CLAIM:
err = RunDetectClaim( patchArgs[ ESARG_1ST] ) ;
break ;
case ESFUNC_DETECT_OPEN:
if ( nArgs < ESARG_1ST + 2 )
{
err = ERROR_INVALID_PARAMETER ;
}
else
{
err = RunDetectOpen( patchArgs[ESARG_1ST],
patchArgs[ESARG_1ST+1],
patchArgs[ESARG_1ST+2],
& nlsResult ) ;
}
break;
case ESFUNC_MCS_CFG_CHECK:
err = RunMCSAlteredCheck( (const TCHAR * ) patchArgs[ESARG_1ST] );
break;
case ESFUNC_TCPIP_CFG_CHECK:
err = RunTcpipAlteredCheck() ;
break ;
case ESFUNC_ROUTE_TO_INF_LIST:
err = RouteToInfList( patchArgs[ ESARG_1ST ],
& nlsResult ) ;
break ;
case ESFUNC_BINDINGS_ONLY:
err = RunNcpaBindingsOnly( hWnd ) ;
break ;
case ESFUNC_ACTIVATE_BINDINGS:
err = RunActivateBindings( patchArgs[ ESARG_1ST ],
patchArgs[ ESARG_1ST+1 ] ) ;
break ;
case ESFUNC_BDC_REPLICATE:
err = RunBDCReplWait( hWnd );
break ;
case ESFUNC_NONE:
case ESFUNC_MAX:
default:
err = ERROR_INVALID_FUNCTION ;
break;
}
#if defined(DEBUG)
if ( err == ERROR_INVALID_FUNCTION )
{
TRACEEOL( SZ("NCPA/SETP: requested function was invalid") ) ;
}
else
if ( err )
{
TRACEEOL( SZ("NCPA/SETP: requested function [")
<< patchArgs[ESARG_FUNC]
<< SZ("] returned error: ")
<< err ) ;
}
#endif
// If the routine used the window handle, control en/disabling.
if ( hWnd )
{
::EnableWindow( hWnd, ! fWasDisabled ) ;
}
// Generate the non-UNICODE result. Since SETUP is always
// ANSI, return an 8-bit character result. It's formatted as
// as a SETUP list variable whose first element is a numeric
// error code. The remainder of the variables are function-
// specific.
::wsprintfA( achBuff, "{\"%ld\"", err ) ;
// See if the subfunction appended any data; if so, add it
// as-is to the string, just converting from UNICODE to ANSI.
if ( nlsResult.QueryError() == 0
&& nlsResult.QueryTextLength() > 0 )
{
// This code assumes that MapCopyTo() moves the
// string terminator as well as the data. Note that
// MapCopyTo() will fail if buffer is insufficient.
INT cchBuff = ::strlen( achBuff ) ;
if ( nlsResult.MapCopyTo( achBuff + cchBuff,
sizeof achBuff - 1 - cchBuff ) )
{
achBuff[cchBuff] = 0 ;
}
}
::strcat( achBuff, "}" );
// This (sometimes huge) output seems to kill NTSD
// TRACEEOL( SZ("NCPA/SETP: return string is: ") << achBuff ) ;
//
TRACEEOL( SZ("NCPA/SETP: return result is: ") << err ) ;
*ppszResult = achBuff ;
FreeArgs( patchArgs, nArgs ) ;
// Stop the master timer
TRACEEOL( "NCPA/SETP: Stopping master timer" );
BLT_MASTER_TIMER::Term();
return err == 0 ;
}
/*******************************************************************
NAME: CplSetupCleanup
SYNOPSIS: Clean up possible memory remnants at
DLL detatch time.
ENTRY:
EXIT:
RETURNS:
NOTES:
HISTORY:
********************************************************************/
VOID CplSetupCleanup ()
{
RunDetectEnd() ;
}
// End of NCPASETP.CXX