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.
 
 
 
 
 
 

5317 lines
148 KiB

//----------------------------------------------------------------------------
//
// File: Setup.cpp
//
// Contents: This file contains the Setup entry points and support functions
//
// Entry Points:
// CplSetup - The main setup entry point
//
//
// Notes:
//
// History:
// April 21, 1995 MikeMi - Created
//
//
//----------------------------------------------------------------------------
#include "pch.hxx" // Precompiled header
#pragma hdrstop
static const int MAX_TEMP = 1024;
// 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)
#define ARGMAX 8000 // note that getparams has returned over 3800
static CHAR g_achBuff [ ARGMAX ] ; // N.B. Must be static for use as
// return value to SETUP.
#define DLG_NM_LANANUM MAKEINTRESOURCE(IDD_DLG_NM_LANANUM)
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 ;
BOOL fStillSupported ;
} setupFuncIndex [] =
{ // who uses this
{ ESFUNC_NCPA, SZ("NCPA") , TRUE , TRUE }, // setup only
{ ESFUNC_DOMAIN, SZ("DOMAIN") , TRUE , FALSE }, // setup only
{ ESFUNC_CONNECT, SZ("CONNECT") , FALSE , FALSE }, // not used
{ ESFUNC_CREATE_SERVICE, SZ("CREATESVC") , FALSE , TRUE }, // utility
{ ESFUNC_DELETE_SERVICE, SZ("DELETESVC") , FALSE , TRUE }, // oem, utility
{ ESFUNC_START_SERVICE, SZ("STARTSVC") , FALSE , TRUE }, // oem
{ ESFUNC_SECURE_REG_KEY, SZ("SECUREKEY") , FALSE , TRUE }, // oem
{ ESFUNC_WINSOCK_MAPPING, SZ("WINSOCKMAP"), FALSE , TRUE }, // utility
{ ESFUNC_ERROR_MESSAGE, SZ("ERRORMSG") , FALSE , TRUE }, // oem
{ ESFUNC_DETECT_START, SZ("DTSTART") , FALSE , TRUE }, // oem (ncparam)
{ ESFUNC_DETECT_END, SZ("DTEND") , FALSE , TRUE }, // oem (ncparam)
{ ESFUNC_DETECT_RESET, SZ("DTRESET") , FALSE , TRUE }, // oem (ncparam)
{ ESFUNC_DETECT_CARD, SZ("DTCARD") , FALSE , TRUE }, // oem (ncparam)
{ ESFUNC_DETECT_PARAMS, SZ("DTPARAMS") , FALSE , TRUE }, // oem (ncparam)
{ ESFUNC_DETECT_QUERY, SZ("DTQUERY") , FALSE , TRUE }, // oem (ncparam)
{ ESFUNC_DETECT_VERIFY, SZ("DTVERIFY") , FALSE , TRUE }, // oem (ncparam)
{ ESFUNC_DETECT_STRING, SZ("DTSTRING") , FALSE , TRUE }, // not used (doc'ed)
{ ESFUNC_DETECT_PNAME, SZ("DTPNAME") , FALSE , TRUE }, // not used (doc'ed)
{ ESFUNC_DETECT_CLAIM, SZ("DTCLAIM") , FALSE , TRUE }, // ncparam
{ ESFUNC_DETECT_OPEN, SZ("DTOPEN") , FALSE , FALSE }, // not used
{ ESFUNC_SECURE_SERVICE, SZ("SECURESVC") , FALSE , TRUE }, // oem
{ ESFUNC_TCPIP_CFG_CHECK, SZ("TCPCFGCHK") , FALSE , FALSE }, // not used
{ ESFUNC_MCS_CFG_CHECK, SZ("MCSCFGCHK") , FALSE , TRUE }, // oem
{ ESFUNC_ROUTE_TO_INF_LIST, SZ("ROUTETOLIST"), FALSE, TRUE }, // oem (nbinfo)
{ ESFUNC_BINDINGS_ONLY, SZ("BINDONLY") , TRUE , FALSE }, // not used
{ ESFUNC_ACTIVATE_BINDINGS, SZ("ACTIVBIND") , FALSE , TRUE }, // oem
{ ESFUNC_BDC_REPLICATE, SZ("DOBDCREPL") , TRUE , FALSE }, // setup
{ ESFUNC_NONE, NULL , FALSE , FALSE }
};
/*
* 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: 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: 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 ;
}
// Check to see if starting an individual service or a group
if ( *pszParms[0] == L'+' )
{
const TCHAR * pszTmp = pszParms[0];
// Skip the '+'
pszTmp++;
// Starting a group.
err = NcpaStartGroup( pszTmp, NULL, TRUE );
}
else
{
// Starting a service
// 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 = 0; // nlsTemp.Load( CvtDec( pszError ) ) ;
{
WCHAR pszTemp[MAX_TEMP+1];
LoadString( g_hinst, CvtDec( pszError ), pszTemp, MAX_TEMP );
nlsTemp = pszTemp;
}
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 );
// pDtCtl->FreeParameterSet( Isa, 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->FreeParameterSet( Isa, 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)
// ||
// pCardRef->QueryIfType() == Isa )
{
// 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 ;
}
APIERR RunDetectCardEx( CARD_REFERENCE*& pCardRef, INT& iCard, BOOL fFirst )
{
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, fFirst ) )
break ;
// Get the corresponding card reference.
pCardRef = pDtCtl->NthCard( iCard ) ;
ASSERT( pCardRef != NULL ) ;
if ( pCardRef->QueryIfType() == PCMCIABus )
// ||
// pCardRef->QueryIfType() == Isa )
{
// 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 ;
// this can be used to debug the verify code
// MessageBox( NULL, L"Set your breakpoints now!", L"Helper Message", MB_APPLMODAL | MB_OK );
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 ;
// this can be used to debug the verify code
// MessageBox( NULL, L"Place your breakpoints now...", L"Helpful Hint", MB_ICONINFORMATION | MB_OK );
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: 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 NetSetupActivateBindingsW (
const TCHAR * pszServiceName,
const TCHAR * * apszBinds )
{
return ActivateBindings( pszServiceName, apszBinds ) ;
}
LONG FAR PASCAL NetSetupActivateBindingsA (
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: 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 ;
}
//-------------------------------------------------------------------
//
// Function:
//
// Synopsis:
//
// Arguments:
//
// Returns:
//
// Notes:
//
// History:
// April 21, 1995 MikeMi -
//
//
//-------------------------------------------------------------------
APIERR RunNcpa( HWND hwndParent )
{
NCP ncp;
APIERR err = 0;
if ( ncp.Initialize( hwndParent ) )
{
ncp.SetUseInprocInterp( FALSE );
ncp.SetFrameHwnd( hwndParent );
do
{
err = ncp.QueryError();
if (err) break;
ncp.SetBindState( BND_OUT_OF_DATE_NO_REBOOT );
err = ncp.QueryError();
if (err) break;
ncp.SaveBindingChanges();
err = ncp.QueryError();
} while (FALSE);
ncp.DeInitialize();
}
else
{
err = ncp.QueryError();
}
return( err );
}
//-------------------------------------------------------------------
//
//
//
//-------------------------------------------------------------------
APIERR NetSetupReviewBindings( HWND hwndParent, DWORD dwBindFlags )
{
NCP ncp;
APIERR err = 0;
do
{
if ( !::IsWindow( hwndParent ) )
{
err = ERROR_INVALID_WINDOW_HANDLE;
break;
}
// dwBindFlags is a reserved value for future expansion
// of this call. A thought is that it might be used to
// set the bind state before calling SaveBindingChanges
//
if (0 != dwBindFlags)
{
err = ERROR_INVALID_PARAMETER;
break;
}
if (!ncp.Initialize( hwndParent ) )
{
err = ncp.QueryError();
break;
}
ncp.SetFrameHwnd( hwndParent );
err = ncp.QueryError();
if (err) break;
ncp.SetBindState( BND_OUT_OF_DATE_NO_REBOOT );
err = ncp.QueryError();
if (err) break;
ncp.SaveBindingChanges();
err = ncp.QueryError();
ncp.DeInitialize();
} while (FALSE);
return( err );
}
//-------------------------------------------------------------------
//
//
//
//-------------------------------------------------------------------
APIERR NetSetupFindSoftwareComponent( PCWSTR pszInfOption,
PWSTR pszInfName, PDWORD pcchInfName,
PWSTR pszRegBase, PDWORD pcchRegBase )
{
BOOL fLoop = TRUE;
APIERR dwError = ERROR_SUCCESS;
do
{
if ( (NULL == pszInfOption) ||
(NULL == pszInfName) ||
(NULL == pcchInfName) ||
((NULL == pszRegBase) && (NULL != pcchRegBase)) ||
((NULL != pszRegBase) && (NULL == pcchRegBase)) )
{
dwError = ERROR_INVALID_PARAMETER ;
break;
}
HKEY hkeySoftware;
WCHAR pszTemp[MAX_PATH];
DWORD cchTemp;
DWORD cbTemp;
FILETIME ftLastWriteTime;
//
// search the registry for a component with the option name given
//
// start at software key
//
dwError = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
RGAS_SOFTWARE_HOME,
0,
KEY_READ,
&hkeySoftware );
if (dwError)
{
break;
}
// enumerate all manufacturers
//
WCHAR pszManufacturer[MAX_PATH];
DWORD iManufacturers = 0;
HKEY hkeyManufacturer;
do
{
cchTemp = MAX_PATH;
dwError = RegEnumKeyEx( hkeySoftware,
iManufacturers++,
pszManufacturer,
&cchTemp,
NULL,
NULL,
NULL,
&ftLastWriteTime );
if (ERROR_NO_MORE_ITEMS == dwError)
{
break;
}
if (ERROR_SUCCESS != dwError)
{
continue;
}
// open the manufacturer key
//
dwError = RegOpenKeyEx( hkeySoftware,
pszManufacturer,
0,
KEY_READ,
&hkeyManufacturer );
if (dwError)
{
continue;
}
// enumerate all possible components
//
WCHAR pszComponent[MAX_PATH];
DWORD iComponents = 0;
HKEY hkeyComponent;
HKEY hkeyCurrentVersion;
HKEY hkeyNetRules;
DWORD dwRegType;
do
{
cchTemp = MAX_PATH;
dwError = RegEnumKeyEx( hkeyManufacturer,
iComponents++,
pszComponent,
&cchTemp,
NULL,
NULL,
NULL,
&ftLastWriteTime );
if (ERROR_NO_MORE_ITEMS == dwError)
{
break;
}
if (ERROR_SUCCESS != dwError)
{
continue;
}
// open the component key
//
dwError = RegOpenKeyEx( hkeyManufacturer,
pszComponent,
0,
KEY_READ,
&hkeyComponent );
if (dwError)
{
continue;
}
// check if the current version key is present
//
dwError = RegOpenKeyEx( hkeyComponent,
RGAS_CURRENT_VERSION,
0,
KEY_READ,
&hkeyCurrentVersion );
if (dwError)
{
continue;
}
// check if the netrules key is present, thus making this a
// network component
//
dwError = RegOpenKeyEx( hkeyCurrentVersion,
RGAS_NETRULES_NAME,
0,
KEY_READ,
&hkeyNetRules );
RegCloseKey( hkeyCurrentVersion );
if (dwError)
{
continue;
}
// Get the option value
//
cbTemp = MAX_PATH * sizeof( WCHAR );
dwError = RegQueryValueEx( hkeyNetRules,
RGAS_INF_OPTION,
NULL,
&dwRegType,
(PBYTE)pszTemp,
&cbTemp );
if (REG_SZ != dwRegType)
{
dwError = ERROR_BADKEY;
}
if (dwError)
{
RegCloseKey( hkeyNetRules );
continue;
}
// does the option name match the given search option name
//
if (0 == lstrcmpi( pszInfOption, pszTemp ))
{
fLoop = FALSE;
// get the inf name
cbTemp = *pcchInfName * sizeof( WCHAR );
dwError = RegQueryValueEx( hkeyNetRules,
RGAS_INF_FILE_NAME,
NULL,
&dwRegType,
(PBYTE)pszInfName,
&cbTemp );
if (REG_SZ != dwRegType)
{
dwError = ERROR_BADKEY;
}
if (dwError)
{
*pcchInfName = cbTemp / sizeof( WCHAR );
RegCloseKey( hkeyNetRules );
break;
}
// get the complete reg path to the item, if the user wanted it
//
if (NULL != pcchRegBase)
{
// confirm buffer size, complete path plus slashes
// between and null termination
cchTemp = lstrlen( RGAS_SOFTWARE_HOME ) + 1 +
lstrlen( pszManufacturer ) + 1 +
lstrlen( pszComponent ) + 1 +
lstrlen( RGAS_CURRENT_VERSION ) + 1;
if (*pcchRegBase < cchTemp)
{
*pcchRegBase = cchTemp;
RegCloseKey( hkeyNetRules );
dwError = ERROR_MORE_DATA;
break;
}
lstrcpy( pszRegBase, RGAS_SOFTWARE_HOME );
lstrcat( pszRegBase, L"\\" );
lstrcat( pszRegBase, pszManufacturer );
lstrcat( pszRegBase, L"\\" );
lstrcat( pszRegBase, pszComponent );
lstrcat( pszRegBase, L"\\" );
lstrcat( pszRegBase, RGAS_CURRENT_VERSION );
}
}
RegCloseKey( hkeyNetRules );
} while (fLoop);
RegCloseKey( hkeyManufacturer );
} while (fLoop);
RegCloseKey( hkeySoftware );
} while (FALSE);
return( dwError );
}
//-------------------------------------------------------------------
//
//
//
//-------------------------------------------------------------------
APIERR NetSetupFindHardwareComponent( PCWSTR pszInfOption,
PWSTR pszInfName, PDWORD pcchInfName,
PWSTR pszRegBase, PDWORD pcchRegBase )
{
BOOL fLoop = TRUE;
APIERR dwError = ERROR_SUCCESS;
do
{
if ( (NULL == pszInfOption) ||
(NULL == pszInfName) ||
(NULL == pcchInfName) ||
((NULL == pszRegBase) && (NULL != pcchRegBase)) ||
((NULL != pszRegBase) && (NULL == pcchRegBase)) )
{
dwError = ERROR_INVALID_PARAMETER ;
break;
}
HKEY hkeyNetCards;
WCHAR pszTemp[MAX_PATH];
DWORD cchTemp;
DWORD cbTemp;
FILETIME ftLastWriteTime;
//
// search the registry for a component with the option name given
//
// start at netcards home key
//
dwError = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
RGAS_ADAPTER_HOME,
0,
KEY_READ,
&hkeyNetCards );
if (dwError)
{
break;
}
// enumerate all netcards
//
WCHAR pszNetCard[MAX_PATH];
DWORD iNetCard = 0;
HKEY hkeyNetCard;
HKEY hkeyNetRules;
DWORD dwRegType;
do
{
cchTemp = MAX_PATH;
dwError = RegEnumKeyEx( hkeyNetCards,
iNetCard++,
pszNetCard,
&cchTemp,
NULL,
NULL,
NULL,
&ftLastWriteTime );
if (ERROR_NO_MORE_ITEMS == dwError)
{
break;
}
if (ERROR_SUCCESS != dwError)
{
continue;
}
// open the netcard key
//
dwError = RegOpenKeyEx( hkeyNetCards,
pszNetCard,
0,
KEY_READ,
&hkeyNetCard );
if (dwError)
{
continue;
}
// check if the netrules key is present, thus making this a
// valid network adapter
//
dwError = RegOpenKeyEx( hkeyNetCard,
RGAS_NETRULES_NAME,
0,
KEY_READ,
&hkeyNetRules );
RegCloseKey( hkeyNetCard );
if (dwError)
{
continue;
}
// Get the option value
//
cbTemp = MAX_PATH * sizeof( WCHAR );
dwError = RegQueryValueEx( hkeyNetRules,
RGAS_INF_OPTION,
NULL,
&dwRegType,
(PBYTE)pszTemp,
&cbTemp );
if (REG_SZ != dwRegType)
{
dwError = ERROR_BADKEY;
}
if (dwError)
{
RegCloseKey( hkeyNetRules );
continue;
}
// does the option name match the given search option name
//
if (0 == lstrcmpi( pszInfOption, pszTemp ))
{
fLoop = FALSE;
// get the inf name
cbTemp = *pcchInfName * sizeof( WCHAR );
dwError = RegQueryValueEx( hkeyNetRules,
RGAS_INF_FILE_NAME,
NULL,
&dwRegType,
(PBYTE)pszInfName,
&cbTemp );
if (REG_SZ != dwRegType)
{
dwError = ERROR_BADKEY;
}
if (dwError)
{
*pcchInfName = cbTemp / sizeof( WCHAR );
RegCloseKey( hkeyNetRules );
break;
}
// get the complete reg path to the item, if the user wanted it
//
if (NULL != pcchRegBase)
{
// confirm buffer size, complete path plus slashes
// between and null termination
cchTemp = lstrlen( RGAS_ADAPTER_HOME ) + 1 +
lstrlen( pszNetCard ) + 1;
if (*pcchRegBase < cchTemp)
{
*pcchRegBase = cchTemp;
RegCloseKey( hkeyNetRules );
dwError = ERROR_MORE_DATA;
break;
}
lstrcpy( pszRegBase, RGAS_ADAPTER_HOME );
lstrcat( pszRegBase, L"\\" );
lstrcat( pszRegBase, pszNetCard );
}
}
RegCloseKey( hkeyNetRules );
} while (fLoop);
RegCloseKey( hkeyNetCards );
} while (FALSE);
return( dwError );
}
//-------------------------------------------------------------------
//
//
//
//-------------------------------------------------------------------
const DWORD INFINSTALL_PRIMARYINSTALL = 0x00000001;
const DWORD INFINSTALL_INPROCINTERP = 0x00000002;
const DWORD INFINSTALL_SUPPORTED = 0x00000003;
APIERR NetSetupComponentInstall( HWND hwndParent,
PCWSTR pszInfOption,
PCWSTR pszInfName,
PCWSTR pszInstallPath,
PCWSTR plszInfSymbols,
DWORD dwInstallFlags,
PDWORD pdwReturn )
{
APIERR dwError = ERROR_SUCCESS;
do
{
if ( !::IsWindow( hwndParent ) )
{
dwError = ERROR_INVALID_WINDOW_HANDLE;
break;
}
if (NULL == pszInfOption)
{
dwError = ERROR_INVALID_PARAMETER ;
break;
}
if (NULL == pszInfName)
{
dwError = ERROR_INVALID_NAME ;
break;
}
if (INFINSTALL_SUPPORTED != (dwInstallFlags | INFINSTALL_SUPPORTED))
{
dwError = ERROR_INVALID_FLAG_NUMBER ;
break;
}
dwError = ERROR_NOT_ENOUGH_MEMORY ;
SetupInterpreter siConfig( (dwInstallFlags & INFINSTALL_INPROCINTERP) );
if (!siConfig.Initialize( hwndParent ))
{
break;
}
if (!siConfig.SetNetShellModes( SIM_INSTALL ))
{
break;
}
if (dwError = siConfig.SetNetComponent( pszInfOption, pszInfName ))
{
break;
}
dwError = ERROR_NOT_ENOUGH_MEMORY ;
// if the path is filled in, use it
if (NULL != pszInstallPath)
{
if (!siConfig.IncludeSymbol( PSZ_NETSRCPATH, pszInstallPath, TRUE ))
{
break;
}
}
if (dwInstallFlags & INFINSTALL_PRIMARYINSTALL)
{
if (!siConfig.IncludeSymbol( PSZ_NETOVERIDEPHASE, L"primary" ))
{
break;
}
}
// if passed a list of symbol value pairs, then add them to
// the available list
//
if (NULL != plszInfSymbols)
{
// include private symbols
PWSTR pszSymbol = (PWSTR)plszInfSymbols;
PWSTR pszValue;
while (L'\0' != *pszSymbol)
{
pszValue = pszSymbol + lstrlen( pszSymbol ) + 1;
if (!siConfig.IncludeSymbol( pszSymbol, pszValue ))
{
break;
}
pszSymbol = pszValue + lstrlen( pszValue ) + 1;
}
}
if (dwError = siConfig.Run())
{
break;
}
dwError = ERROR_SUCCESS;
*pdwReturn = siConfig.QueryReturnValue();
} while(FALSE);
return( dwError );
}
//-------------------------------------------------------------------
//
//
//
//-------------------------------------------------------------------
APIERR NetSetupComponentRemove( HWND hwndParent,
PCWSTR pszInfOption,
DWORD dwInstallFlags,
PDWORD pdwReturn )
{
APIERR dwError = ERROR_SUCCESS;
WCHAR pszInfName[MAX_PATH+1];
WCHAR pszRegBase[MAX_PATH+1];
do
{
if ( !::IsWindow( hwndParent ) )
{
dwError = ERROR_INVALID_WINDOW_HANDLE;
break;
}
if (NULL == pszInfOption)
{
dwError = ERROR_INVALID_PARAMETER ;
break;
}
if (INFINSTALL_SUPPORTED != (dwInstallFlags | INFINSTALL_SUPPORTED))
{
dwError = ERROR_INVALID_FLAG_NUMBER ;
break;
}
dwError = ERROR_NOT_ENOUGH_MEMORY ;
SetupInterpreter siConfig( (dwInstallFlags & INFINSTALL_INPROCINTERP) );
if (!siConfig.Initialize( hwndParent ))
{
break;
}
if (!siConfig.SetNetShellModes( SIM_DEINSTALL ))
{
break;
}
DWORD cchInfName = MAX_PATH;
DWORD cchRegBase = MAX_PATH;
dwError = NetSetupFindHardwareComponent( pszInfOption, pszInfName, &cchInfName, pszRegBase, &cchRegBase );
if (dwError)
{
dwError = NetSetupFindSoftwareComponent( pszInfOption, pszInfName, &cchInfName, pszRegBase, &cchRegBase );
if (dwError)
{
break;
}
}
if (dwError = siConfig.SetNetComponent( pszInfOption, pszInfName, pszRegBase ))
{
break;
}
if (dwInstallFlags & INFINSTALL_PRIMARYINSTALL)
{
if (!siConfig.IncludeSymbol( PSZ_NETOVERIDEPHASE, L"primary" ))
{
break;
}
}
if (dwError = siConfig.Run())
{
break;
}
dwError = ERROR_SUCCESS;
*pdwReturn = siConfig.QueryReturnValue();
} while(FALSE);
return( dwError );
}
//-------------------------------------------------------------------
//
//
//
//-------------------------------------------------------------------
APIERR NetSetupComponentProperties( HWND hwndParent,
PCWSTR pszInfOption,
DWORD dwInstallFlags,
PDWORD pdwReturn )
{
APIERR dwError = ERROR_SUCCESS;
WCHAR pszInfName[MAX_PATH+1];
WCHAR pszRegBase[MAX_PATH+1];
do
{
if ( !::IsWindow( hwndParent ) )
{
dwError = ERROR_INVALID_WINDOW_HANDLE;
break;
}
if (NULL == pszInfOption)
{
dwError = ERROR_INVALID_PARAMETER ;
break;
}
if (INFINSTALL_SUPPORTED != (dwInstallFlags | INFINSTALL_SUPPORTED))
{
dwError = ERROR_INVALID_FLAG_NUMBER ;
break;
}
dwError = ERROR_NOT_ENOUGH_MEMORY ;
SetupInterpreter siConfig( (dwInstallFlags & INFINSTALL_INPROCINTERP) );
if (!siConfig.Initialize( hwndParent ))
{
break;
}
if (!siConfig.SetNetShellModes( SIM_CONFIGURE ))
{
break;
}
DWORD cchInfName = MAX_PATH;
DWORD cchRegBase = MAX_PATH;
dwError = NetSetupFindHardwareComponent( pszInfOption, pszInfName, &cchInfName, pszRegBase, &cchRegBase );
if (dwError)
{
dwError = NetSetupFindSoftwareComponent( pszInfOption, pszInfName, &cchInfName, pszRegBase, &cchRegBase );
if (dwError)
{
break;
}
}
if (dwError = siConfig.SetNetComponent( pszInfOption, pszInfName, pszRegBase ))
{
break;
}
if (dwInstallFlags & INFINSTALL_PRIMARYINSTALL)
{
if (!siConfig.IncludeSymbol( PSZ_NETOVERIDEPHASE, L"primary" ))
{
break;
}
}
if (dwError = siConfig.Run())
{
break;
}
dwError = ERROR_SUCCESS;
*pdwReturn = siConfig.QueryReturnValue();
} while (FALSE);
return( dwError );
}
//-------------------------------------------------------------------
//
// Function:
//
// Synopsis:
//
// Arguments:
//
// Returns:
//
// Notes:
//
// History:
// April 21, 1995 MikeMi -
//
//
//-------------------------------------------------------------------
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: 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
********************************************************************/
BOOL FAR PASCAL NetSetupFunctions(
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 ;
BOOL fSupported;
// 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 ;
}
// 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 ;
fSupported = setupFuncIndex[iFunc].fStillSupported;
if (fSupported)
{
// 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 entries commented out below are not supported anymore
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;
}
}
else
{
err = ERROR_INVALID_FUNCTION ;
}
#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( g_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( g_achBuff ) ;
if ( nlsResult.MapCopyTo( g_achBuff + cchBuff,
sizeof g_achBuff - 1 - cchBuff ) )
{
g_achBuff[cchBuff] = 0 ;
}
}
::strcat( g_achBuff, "}" );
// This (sometimes huge) output seems to kill NTSD
// TRACEEOL( SZ("NCPA/SETP: return string is: ") << g_achBuff ) ;
//
TRACEEOL( SZ("NCPA/SETP: return result is: ") << err ) ;
*ppszResult = g_achBuff ;
FreeArgs( patchArgs, nArgs ) ;
return err == 0 ;
}
/*******************************************************************
NAME: CplSetupCleanup
SYNOPSIS: Clean up possible memory remnants at
DLL detatch time.
ENTRY:
EXIT:
RETURNS:
NOTES:
HISTORY:
********************************************************************/
LONG FAR PASCAL NetSetupRunDetectEnd()
{
RunDetectEnd() ;
return( 0 );
}
/*******************************************************************
NAME: CPlNETBIOS
SYNOPSIS: Wrapper routine for calling RunNETBIOS. It should be called
from inf file.
ENTRY: The first parameter must be the parent window handle.
RETURN: BOOL - TRUE for okay.
HISTORY:
terryk 11-Nov-1992 Created
********************************************************************/
BOOL FAR PASCAL NetSetupNETBIOS( DWORD nArgs, LPSTR apszArgs[], LPSTR * ppszResult )
{
APIERR err = ERROR_SUCCESS ;
HWND hWnd = NULL;
TCHAR **patchArgs;
if (( patchArgs = CvtArgs( apszArgs, nArgs )) == NULL )
{
wsprintfA( g_achBuff, "{\"%d\"}", ERROR_INVALID_PARAMETER );
*ppszResult = g_achBuff;
return FALSE;
}
// get window handle
if ( nArgs > 0 && patchArgs[0][0] != TCH('\0') )
{
hWnd = (HWND) CvtHex( patchArgs[0] ) ;
}
else
{
hWnd = ::GetActiveWindow() ;
}
if (!RaiseNetBiosDialog( hWnd ))
{
err = ERROR_CANCELLED;
}
wsprintfA( g_achBuff, "{\"%d\"}", err );
*ppszResult = g_achBuff;
FreeArgs( patchArgs, nArgs );
return err == NERR_Success;
}
/*******************************************************************
NAME: CPlSetupLanaMap
SYNOPSIS: This is a wrapper routine for called SetupLanaMap. It should be
called from inf file. SetupLanaMap will setup the LanaMax
variable and LanaMap variable in NETBIOS section of the
registry.
ENTRY: NONE from inf file.
RETURN: BOOL - TRUE for success.
HISTORY:
terryk 11-Nov-1992 Created
********************************************************************/
BOOL FAR PASCAL NetSetupLanaMap( DWORD nArgs, LPSTR apszArgs[], LPSTR * ppszResult )
{
wsprintfA( g_achBuff, "{\"0\"}" );
*ppszResult = g_achBuff;
return SetupLanaMap() == NERR_Success;
}
/*******************************************************************
NAME: EqualToXnsRoute
SYNOPSIS: Compare whether the first arg is started with ["Xns].
It should be called from an inf file.
ENTRY: The first argument should contain the Route string.
RETURN: ppszResult will contian either ASCII 0 or ASCII 1. 0 for
FALSE and 1 for TRUE.
TRUE means the given string is started with "Xns
HISTORY:
terryk 11-Nov-1992 Created
********************************************************************/
#define RGAS_MCSXNS_PATH SZ("SYSTEM\\CurrentControlSet\\Services\\Mcsxns\\NetConfig\\Driver01")
#define RGAS_ADAPTERNAME SZ("AdapterName")
BOOL FAR PASCAL NetSetupEqualToXnsRoute( DWORD nArgs, LPSTR apszArgs[], LPSTR * ppszResult )
{
BOOL fReturn = FALSE;
wsprintfA( g_achBuff, "0" );
if ( nArgs > 0 && apszArgs[0][0] != TCH('\0') )
{
fReturn = ((_strnicmp( apszArgs[0], "\"Xns", 4 ) == 0)||
(_strnicmp( apszArgs[0], "\"Ubnb", 5 ) == 0));
wsprintfA( g_achBuff, "%d", fReturn?1:0 );
}
*ppszResult = g_achBuff;
return fReturn;
}
/*******************************************************************
NAME: SetEnum
SYNOPSIS: Worker function for SetEnumExport. This function will
look at the given Route string and search the adapter
section of the route string. For example, if the route
string is:
"NBF" "Elnkii" "Elnkii01"
The routine will look at:
System\CurrentControlSet\Services\Elnkii01\Parameters
If this section contain a variable called "EnumExportPref",
the subroutine will set the:
System\CurrentControlSet\Services\NETBIOSInformation\
Parameters\EnumExport[POS]
to the same value. ( POS is the first parameter of this
subroutine.) Otherwise, it will just return to the caller.
ENTRY: TCHAR * pszPos - position number in string format.
TCHAR * pszRoute - route string. i.e., NBF Elnkii Elnkii01
HISTORY:
terryk 11-Nov-1992 Created
********************************************************************/
#define RGAS_PARAMETERS SZ("\\Parameters")
#define RGAS_ROUTE SZ("Route")
#define RGAS_LANANUM SZ("LanaNum")
#define RGAS_ENUMEXPORT SZ("EnumExport")
#define RGAS_ENUMEXPORTPREF SZ("EnumExportPref")
#define RG_NETBIOSINFO_PATH SZ("\\NetBIOSInformation\\Parameters")
void SetEnum( TCHAR *pszPos, TCHAR * pszRoute )
{
APIERR err = NERR_Success;
NLS_STR nlsRoute = pszRoute;
DWORD dwPref = 1;
// get the service name from the route
ISTR istrLastQuote( nlsRoute );
ISTR istrStart( nlsRoute );
nlsRoute.strrchr( & istrLastQuote, '"' );
NLS_STR *pnlsTmp = nlsRoute.QuerySubStr( istrStart, istrLastQuote );
ISTR istrSecLastQuote( *pnlsTmp );
pnlsTmp->strrchr( & istrSecLastQuote, '"' );
++istrSecLastQuote;
NLS_STR *pnlsServiceName = pnlsTmp->QuerySubStr( istrSecLastQuote );
delete pnlsTmp;
// get the EnumExportPref value
REG_KEY rkLocalMachine( HKEY_LOCAL_MACHINE );
NLS_STR nlsService = RGAS_SERVICES_HOME;
nlsService.AppendChar( TCHAR('\\' ));
nlsService.strcat( *pnlsServiceName );
nlsService.strcat( RGAS_PARAMETERS );
REG_KEY regService( rkLocalMachine, nlsService );
if (((( err = regService.QueryError())) != NERR_Success ) ||
((err = regService.QueryValue( RGAS_ENUMEXPORTPREF, & dwPref )) != NERR_Success ))
{
delete pnlsServiceName;
return;
}
delete pnlsServiceName;
// set the NETBIOSInformation\Parameters\EnumExportXX
NLS_STR nlsNetbiosInfo = RGAS_SERVICES_HOME;
nlsNetbiosInfo.strcat( RG_NETBIOSINFO_PATH );
NLS_STR nlsExport( RGAS_ENUMEXPORT );
nlsExport.strcat( pszPos );
REG_KEY regExport( rkLocalMachine, nlsNetbiosInfo );
if (((( err = regExport.QueryError())) != NERR_Success ) ||
((err = regExport.SetValue( nlsExport, dwPref )) != NERR_Success ))
{
return;
}
}
/*******************************************************************
NAME: SetEnumExport
SYNOPSIS: Wrapper function for SetEnum. The nbinfo.inf file will call
this function to reset all the EnumExport values under
NETBIOSInformation.
ENTRY: The first parameter is the position string for the EnumExport
value.i.e., "1", "12", ...
The second parameter is the route string.i.e.,
"NBF" "ELNKII" ELNK01"
RETURN: BOOL - TRUE for success. FALSE for failure.
HISTORY:
terryk 11-Nov-1992 Created
********************************************************************/
BOOL FAR PASCAL NetSetupSetEnumExport( DWORD nArgs, LPSTR apszArgs[], LPSTR * ppszResult )
{
TCHAR **patchArgs;
if (( nArgs != 2 ) || (( patchArgs = CvtArgs( apszArgs, nArgs )) == NULL ))
{
wsprintfA( g_achBuff, "{\"%d\"}", ERROR_INVALID_PARAMETER );
*ppszResult = g_achBuff;
return FALSE;
}
SetEnum( patchArgs[0], patchArgs[1] );
wsprintfA( g_achBuff, "{\"0\"}" );
*ppszResult = g_achBuff;
FreeArgs( patchArgs, nArgs );
return TRUE;
}
/*******************************************************************
NAME: RemoveRoute
SYNOPSIS: Worker function for RemoveRouteFromNETBIOS. This function will
receive a device name. It will look through all the route
string under NETBIOSInformation\Parameters\Route, if it
finds the route string which contains the device name, it
will remove it from the route list. It will also remove
the related LanaNum and EnumExport variables. After it
removes the LanaNum and EnumExport variables, it will move
all the LanaNum and EnumExport value names down 1 position.
ENTRY: TCHAR * pszDeviceName - device name string, i.e., "Elnkii01"
HISTORY:
terryk 11-Nov-1992 Created
********************************************************************/
void RemoveRoute ( TCHAR * pszDeviceName )
{
APIERR err = NERR_Success;
NLS_STR nlsDeviceName ( pszDeviceName );
STRLIST * pstrlstRoute = NULL;
NLS_STR nlsNetbiosInfo = RGAS_SERVICES_HOME;
nlsNetbiosInfo.strcat( RG_NETBIOSINFO_PATH );
REG_KEY rkLocalMachine( HKEY_LOCAL_MACHINE );
REG_KEY regNetbios( rkLocalMachine, nlsNetbiosInfo );
// get the original route strings list
if (((( err = regNetbios.QueryError())) != NERR_Success ) ||
((err = regNetbios.QueryValue( RGAS_ROUTE, &pstrlstRoute )) != NERR_Success ))
{
delete pstrlstRoute;
return;
}
INT nNumRoute = pstrlstRoute->QueryNumElem();
INT nNewNumRoute = nNumRoute;
ITER_STRLIST iterRoute( *pstrlstRoute );
NLS_STR *pnlsRoute = iterRoute.Next();
STRLIST strlstNewRoute;
INT nNextAvail = 1;
NLS_STR * pnlsTmp ;
for ( INT i = 1; i <= nNumRoute; i++, pnlsRoute = iterRoute.Next() )
{
ISTR istrRoute( *pnlsRoute );
if ( pnlsRoute->strstr( &istrRoute, nlsDeviceName ))
{
// found it
nNewNumRoute --;
} else if (( pnlsTmp = new NLS_STR( *pnlsRoute ) ) != NULL )
{
// cannot find it; must have been deleted
strlstNewRoute.Append( pnlsTmp );
if ( nNewNumRoute != nNumRoute )
{
// if we have already removed the route string from the route list,
// we will move the LanaNum and EnumExport variables up
DWORD nLanaNum;
DWORD nEnumExport;
DEC_STR nlsOldPos( i );
DEC_STR nlsNewPos( nNextAvail );
NLS_STR nlsOldLanaNum( RGAS_LANANUM );
NLS_STR nlsOldEnumExport( RGAS_ENUMEXPORT );
NLS_STR nlsNewLanaNum( RGAS_LANANUM );
NLS_STR nlsNewEnumExport( RGAS_ENUMEXPORT );
nlsOldLanaNum.strcat( nlsOldPos );
nlsOldEnumExport.strcat( nlsOldPos );
nlsNewLanaNum.strcat( nlsNewPos );
nlsNewEnumExport.strcat( nlsNewPos );
regNetbios.QueryValue( nlsOldLanaNum, &nLanaNum );
regNetbios.QueryValue( nlsOldEnumExport, &nEnumExport );
regNetbios.SetValue( nlsNewLanaNum, nLanaNum );
regNetbios.SetValue( nlsNewEnumExport, nEnumExport );
}
nNextAvail ++;
}
}
if ( nNewNumRoute != nNumRoute )
{
// remove extra LanaNum and EnumExport
for ( i = nNewNumRoute ; i < nNumRoute; i++ )
{
DEC_STR nlsPos( i + 1 );
NLS_STR nlsLanaNum( RGAS_LANANUM );
NLS_STR nlsEnumExport( RGAS_ENUMEXPORT );
nlsLanaNum.strcat( nlsPos );
nlsEnumExport.strcat( nlsPos );
regNetbios.DeleteValue( nlsLanaNum );
regNetbios.DeleteValue( nlsEnumExport );
}
// save the new route list
regNetbios.SetValue( RGAS_ROUTE, &strlstNewRoute );
}
delete pstrlstRoute;
}
/*******************************************************************
NAME: RemoveRouteFromNETBIOS
SYNOPSIS: Wrapper function for RemoveRoute. This subroutine is called
from utility.inf. When the user removes an adapter card from
NCPA, utility.inf will call this routine to remove the related
information from the NETBIOSInformation section of the registry.
ENTRY: The first parameter is the device name.
RETURN: BOOL - TRUE for success.
HISTORY:
terryk 11-Nov-1992 Created
********************************************************************/
BOOL FAR PASCAL NetSetupRemoveRouteFromNETBIOS( DWORD nArgs, LPSTR apszArgs[], LPSTR * ppszResult )
{
TCHAR **patchArgs;
if (( nArgs != 1 ) || (( patchArgs = CvtArgs( apszArgs, nArgs )) == NULL ))
{
wsprintfA( g_achBuff, "{\"%d\"}", ERROR_INVALID_PARAMETER );
*ppszResult = g_achBuff;
return FALSE;
}
RemoveRoute( patchArgs[0] );
wsprintfA( g_achBuff, "{\"0\"}" );
*ppszResult = g_achBuff;
FreeArgs( patchArgs, nArgs );
return TRUE;
}
/*******************************************************************
NAME: CPlBROWSER
SYNOPSIS: It should be called
from inf file.
ENTRY: The first parameter must be the parent window handle.
RETURN: BOOL - TRUE for okay.
HISTORY:
terryk 11-Nov-1992 Created
********************************************************************/
BOOL FAR PASCAL NetSetupBROWSER( DWORD nArgs, LPSTR apszArgs[], LPSTR * ppszResult )
{
APIERR err = NERR_Success ;
HWND hWnd = NULL;
TCHAR **patchArgs;
if (( patchArgs = CvtArgs( apszArgs, nArgs )) == NULL )
{
wsprintfA( g_achBuff, "{\"%d\"}", ERROR_INVALID_PARAMETER );
*ppszResult = g_achBuff;
return FALSE;
}
// get window handle
if ( nArgs > 0 && patchArgs[0][0] != TCH('\0') )
{
hWnd = (HWND) CvtHex( patchArgs[0] ) ;
}
else
{
hWnd = ::GetActiveWindow() ;
}
if (!RaiseBrowserDialog( hWnd ))
{
err = 1;
}
wsprintfA( g_achBuff, "{\"%d\"}", err );
*ppszResult = g_achBuff;
FreeArgs( patchArgs, nArgs );
return err == NERR_Success;
}
BOOL FAR PASCAL NetSetupConvertEndPointString( DWORD nArgs, LPSTR apszArgs[], LPSTR * ppszResult )
{
if ( nArgs != 2 )
{
wsprintfA( g_achBuff, "{\"%d\"}", ERROR_INVALID_PARAMETER );
*ppszResult = g_achBuff;
return FALSE;
}
CHAR achComponent[200] ;
CHAR * pcTmp = achComponent,
* pcTmpMax = & achComponent [ sizeof achComponent - 1 ],
* pcPos ;
for ( pcPos = apszArgs[1] ;
pcTmp < pcTmpMax && *pcPos != 0 && *pcPos != ' ' ;
pcPos++ )
{
*pcTmp++ = *pcPos;
}
*pcTmp = '\0';
wsprintfA( g_achBuff, "\"%s\" %s", apszArgs[0], achComponent );
*ppszResult = g_achBuff;
return TRUE;
}
/*******************************************************************
NAME: CPlAddMonitor
SYNOPSIS: This is a wrapper routine for called AddMonitor. It should be
called from inf file if the user installs DLC or Token Ring.
ENTRY: NONE from inf file.
RETURN: BOOL - TRUE for success.
HISTORY:
terryk 11-Nov-1992 Created
********************************************************************/
typedef BOOL (WINAPI *T_AddMonitor)(LPWSTR pName,DWORD Level,LPBYTE pMonitors);
typedef BOOL (WINAPI *T_DeleteMonitor)(LPWSTR pName,LPWSTR pEnv, LPWSTR pMon);
BOOL FAR PASCAL NetSetupAddMonitor( DWORD nArgs, LPSTR apszArgs[], LPSTR * ppszResult )
{
NLS_STR nlsMonitorName;
MONITOR_INFO_2 MonitorInfo2;
APIERR err = NERR_Success;
do
{
{
WCHAR pszTemp[MAX_TEMP+1];
LoadString( g_hinst, IDS_HP_MONITOR_NAME, pszTemp, MAX_TEMP );
nlsMonitorName = pszTemp;
}
/*
if (( err = nlsMonitorName.Load( IDS_HP_MONITOR_NAME )) != NERR_Success )
{
break;
}
*/
MonitorInfo2.pName = (LPWSTR)nlsMonitorName.QueryPch();
MonitorInfo2.pEnvironment = NULL;
MonitorInfo2.pDLLName = SZ("hpmon.dll");
HINSTANCE hDll = ::LoadLibraryA( "winspool.drv" );
if ( hDll == NULL )
{
err = ::GetLastError();
break;
}
FARPROC pAddMonitor = ::GetProcAddress( hDll, "AddMonitorW" );
if ( pAddMonitor == NULL )
{
err = ::GetLastError();
}
else if ( !(*(T_AddMonitor)pAddMonitor)(NULL,2,(LPBYTE)&MonitorInfo2))
{
err = ::GetLastError();
}
if ( hDll )
::FreeLibrary( hDll );
} while (FALSE);
wsprintfA( g_achBuff, "{\"%d\"}", err );
*ppszResult = g_achBuff;
return TRUE;
}
BOOL FAR PASCAL NetSetupDeleteMonitor( DWORD nArgs, LPSTR apszArgs[], LPSTR * ppszResult )
{
NLS_STR nlsMonitorName;
APIERR err = NERR_Success;
do {
{
WCHAR pszTemp[MAX_TEMP+1];
LoadString( g_hinst, IDS_HP_MONITOR_NAME, pszTemp, MAX_TEMP );
nlsMonitorName = pszTemp;
}
/*
if (( err = nlsMonitorName.Load( IDS_HP_MONITOR_NAME )) != NERR_Success )
{
break;
}
*/
HINSTANCE hDll = ::LoadLibraryA( "winspool.drv" );
if ( hDll == NULL )
{
err = ::GetLastError();
break;
}
FARPROC pDeleteMonitor = ::GetProcAddress( hDll, "DeleteMonitorW" );
if ( pDeleteMonitor == NULL )
{
err = ::GetLastError();
} else if ( !(*(T_DeleteMonitor)pDeleteMonitor)(NULL,NULL,(LPWSTR)nlsMonitorName.QueryPch()))
{
err = ::GetLastError();
}
if ( hDll )
::FreeLibrary ( hDll );
} while (FALSE);
wsprintfA( g_achBuff, "{\"%d\"}", err );
*ppszResult = g_achBuff;
return TRUE;
}
/*******************************************************************
NAME: GetBusTypeDialog
SYNOPSIS: Wrapper routine for calling RunGetBusDlg. The inf file
should call this function into to display the Bus Location
dialog.
ENTRY: The first parameter must be the parent window handle.
The second parameter must be the network card description name.
The third parameter is the bus type
The fourth parameter is the bus number
RETURN: BOOL - TRUE for okay.
HISTORY:
terryk 03-Aug-1993 Created
********************************************************************/
CHAR PSZ_RTCANCEL[] = "CANCEL";
CHAR PSZ_RTOK[] = "OK";
BOOL FAR PASCAL NetSetupGetBusTypeDialog( DWORD nArgs, LPSTR apszArgs[], LPSTR * ppszResult )
{
APIERR err = NERR_Success ;
HWND hWnd = NULL;
BOOL fReturn = TRUE;
TCHAR **patchArgs;
INT nBusType = 0;
INT nBusNum = 0;
wsprintfA( g_achBuff, "{\"%d\",\"%d\",\"%d\"}", ERROR_INVALID_PARAMETER, nBusType, nBusNum );
*ppszResult = g_achBuff;
do
{
if (( patchArgs = CvtArgs( apszArgs, nArgs )) == NULL )
{
fReturn = FALSE;
break;
}
// get window handle
if ( nArgs > 0 && patchArgs[0][0] != TCH('\0') )
{
hWnd = (HWND) CvtHex( patchArgs[0] ) ;
}
else
{
hWnd = ::GetActiveWindow() ;
}
if (( nArgs > 2 ) && ( patchArgs[2][0] != TCH('\0') ))
{
NLS_STR nlsTmp = patchArgs[2];
if ( nlsTmp.QueryError() != NERR_Success )
{
fReturn = FALSE;
break;
}
nBusType = nlsTmp.atoi();
}
else
{
nBusType = 1; // assume it is ISA
}
if (( nArgs > 3 ) && ( patchArgs[3][0] != TCH('\0') ))
{
NLS_STR nlsTmp = patchArgs[3];
if ( nlsTmp.QueryError() != NERR_Success )
{
fReturn = FALSE;
break;
}
nBusNum = nlsTmp.atoi();
}
else
{
nBusNum = 0; // assume it is bus 0
}
// Call the worker function by passing the window handle and the
// network card description name
BOOL fUserCancel;
LPCSTR pszRt = NULL;
err = RunGetBusTypeDlg( hWnd , patchArgs[1], &nBusType, &nBusNum, fUserCancel ) ;
if (!fUserCancel)
{
pszRt = PSZ_RTOK;
}
else
{
pszRt = PSZ_RTCANCEL;
}
wsprintfA( g_achBuff, "{\"%d\",\"%d\",\"%d\",\"%s\"}", err, nBusType, nBusNum, pszRt );
*ppszResult = g_achBuff;
fReturn = err == NERR_Success;
} while ( FALSE );
FreeArgs( patchArgs, nArgs );
return fReturn;
}
/*
Upgrdsna.cxx
Upgrade SNA.
1. See whether SNA is installed or not
2. If yes, look for all the snadlcX keys
3. changed the snadlcX\Parameters\ExtraParameters\AdapterName by
removing the extra 0 (if necessary).
FILE HISTORY:
terryk 5/20/94 Created
*/
// Registry keys
#define RGAS_SNADLC SZ("SnaDLC")
#define RGAS_SNASERVER SZ("Software\\Microsoft\\SNA Server")
#define RGAS_SNA_PARAMETERS SZ("\\Parameters\\ExtraParameters")
#define RGAS_SNA_ADAPTERNAME SZ("AdapterName")
//
// UpgradeSNA()
//
BOOL FAR PASCAL NetSetupUpgradeSNA (
DWORD nArgs, // Number of string arguments
LPSTR apszArgs[], // The arguments, NULL-terminated
LPSTR * ppszResult ) // Result variable storage
{
APIERR err = NERR_Success;
do {
NLS_STR nlsServices = RGAS_SERVICES_HOME;
// Open Local Machine and Service Key
REG_KEY rkLocalMachine( HKEY_LOCAL_MACHINE ) ;
REG_KEY regServices( rkLocalMachine, nlsServices );
if ((( err = rkLocalMachine.QueryError()) != NERR_Success ) ||
(( err = regServices.QueryError()) != NERR_Success ))
{
#ifdef DEBUG
OutputDebugString(SZ("Cannot open service key.\n\r"));
#endif
break;
}
//
// Make sure Sna Server Exist
//
NLS_STR nlsSnaServer = RGAS_SNASERVER;
REG_KEY regSnaServer( rkLocalMachine, nlsSnaServer );
if ( regSnaServer.QueryError() != NERR_Success )
{
// SNA Server does not exist
#ifdef DEBUG
OutputDebugString(SZ("Cannot open SNA Server key.\n\r"));
#endif
break;
}
// Enumerate all the Services and look for SNADLCX where X
// is a number or a letter from A to U
REG_ENUM regEnumServices( regServices );
if (( err = regEnumServices.QueryError()) != NERR_Success )
{
#ifdef DEBUG
OutputDebugString(SZ("Cannot open Enum Services key.\n\r"));
#endif
break;
}
REG_KEY_INFO_STRUCT regKeyInfo;
NLS_STR nlsSNADLC = RGAS_SNADLC;
ISTR istrEndSNADLC( nlsSNADLC );
UINT nLenSNADLC = nlsSNADLC.QueryNumChar();
istrEndSNADLC += nLenSNADLC;
while ( regEnumServices.NextSubKey( & regKeyInfo ) == NERR_Success )
{
// Looking for SNADLCX
if ( nlsSNADLC._strnicmp( regKeyInfo.nlsName, istrEndSNADLC ) == 0 )
{
if ( regKeyInfo.nlsName.QueryNumChar() == ( nLenSNADLC + 1 ))
{
// SnaDLCX services
// 1. Open SnaDLCX\Parameters
NLS_STR nlsSnaParameters = regKeyInfo.nlsName;
nlsSnaParameters += RGAS_SNA_PARAMETERS;
REG_KEY regSnaServices( regServices, nlsSnaParameters );
if ( regSnaServices.QueryError() != NERR_Success )
{
#ifdef DEBUG
OutputDebugString(SZ("Cannot open Parameter key.\n"));
#endif
// if no ExtraParameters Key exist, look for next one
continue;
}
// 2. change the adapterName
NLS_STR nlsAdapterName;
NLS_STR nlsNewAdapterName;
regSnaServices.QueryValue( RGAS_SNA_ADAPTERNAME, &nlsAdapterName );
nlsNewAdapterName = nlsAdapterName;
ISTR istrStartAdapterName( nlsNewAdapterName );
ISTR istrEndAdapterName( nlsNewAdapterName );
istrStartAdapterName += nlsNewAdapterName.QueryNumChar() - 2;
istrEndAdapterName += nlsNewAdapterName.QueryNumChar() - 1;
if ( *(nlsNewAdapterName.QueryPch( istrStartAdapterName )) == TCH('0'))
{
nlsNewAdapterName.DelSubStr( istrStartAdapterName, istrEndAdapterName );
// check whether device exists or not
ISTR istrBackSlash( nlsNewAdapterName );
if ( nlsNewAdapterName.strrchr( &istrBackSlash, TCHAR('\\')))
{
++istrBackSlash;
NLS_STR *pnlsServices = nlsNewAdapterName.QuerySubStr( istrBackSlash );
#ifdef DEBUG
OutputDebugString(SZ("\n\rNew Adapter Name:"));
OutputDebugString( pnlsServices->QueryPch());
#endif
REG_KEY regNewService( regServices, *pnlsServices );
if ( regNewService.QueryError() == NERR_Success )
{
// set the new adapter name if and only if the service exists
#ifdef DEBUG
OutputDebugString(SZ("\n\rWrite New Adapter Name for:"));
OutputDebugString( pnlsServices->QueryPch());
#endif
regSnaServices.SetValue( RGAS_SNA_ADAPTERNAME, nlsNewAdapterName );
}
delete pnlsServices;
}
}
}
}
}
if ( err != NERR_Success )
break;
} while (FALSE);
wsprintfA( g_achBuff, "{\"0\"}" );
*ppszResult = g_achBuff;
return err == NERR_Success;
}
/*
Upgrade.cxx
Upgrade the network component call out.
FILE HISTORY:
terryk 11/30/92 Created
*/
#define VALUEEXTRASIZE 100
APIERR CopyReg( REG_KEY &src, REG_KEY &dest )
{
REG_KEY_INFO_STRUCT rni ;
REG_KEY_CREATE_STRUCT regCreate;
REG_VALUE_INFO_STRUCT rvi ;
REG_ENUM regEnum( src ) ;
BYTE * pbValueData = NULL ;
APIERR errIter,
err = NERR_Success;
REG_KEY * pRnNew = NULL,
* pRnSub = NULL ;
LONG cbMaxValue ;
err = src.QueryInfo( & rni ) ;
if ( err )
return err ;
regCreate.dwTitleIndex = 0;
regCreate.ulOptions = REG_OPTION_NON_VOLATILE;
regCreate.nlsClass = RGAS_GENERIC_CLASS;
regCreate.regSam = MAXIMUM_ALLOWED;
regCreate.pSecAttr = NULL;
regCreate.ulDisposition = 0;
cbMaxValue = rni.ulMaxValueLen + VALUEEXTRASIZE ;
pbValueData = new BYTE [ cbMaxValue ] ;
if ( pbValueData == NULL )
return ERROR_NOT_ENOUGH_MEMORY ;
// Next, copy all value items to the new node.
rvi.pwcData = pbValueData ;
rvi.ulDataLength = cbMaxValue ;
err = errIter = 0 ;
while ( (errIter = regEnum.NextValue( & rvi )) == NERR_Success )
{
rvi.ulDataLength = rvi.ulDataLengthOut ;
if ( err = dest.SetValue( & rvi ) )
break ;
rvi.ulDataLength = cbMaxValue ;
}
// BUGBUG: Check for iteration errors other than 'finished'.
if ( err == 0 )
{
// Finally, recursively copy the subkeys.
regEnum.Reset() ;
err = errIter = 0 ;
while ( (errIter = regEnum.NextSubKey( & rni )) == NERR_Success )
{
// Open the subkey.
REG_KEY RegSubKey( dest, rni.nlsName, &regCreate );
pRnSub = new REG_KEY( src, rni.nlsName );
if ( pRnSub == NULL )
{
err = ERROR_NOT_ENOUGH_MEMORY ;
}
else
if ( (err = pRnSub->QueryError()) == 0 )
{
// Recurse
err = CopyReg( *pRnSub, RegSubKey ) ;
}
// Delete the subkey object and continue
delete pRnSub ;
if ( err )
break ;
}
}
delete pRnNew ;
delete pbValueData ;
return err ;
}
#define RGAS_SZ_NETWORK_CARD SZ("Software\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards")
#define RGAS_SZ_TITLE SZ("Title")
#define RGAS_SZ_SERVICE SZ("ServiceName")
#define RGAS_SZ_BINDFORM SZ("bindform")
#define RGAS_SZ_NETRULES SZ("NetRules")
#define RGAS_DLC_PARAMETERS SZ("DLC\\Parameters\\")
BOOL FAR PASCAL NetSetupUpgradeCardNum (
DWORD nArgs, // Number of string arguments
LPSTR apszArgs[], // The arguments, NULL-terminated
LPSTR * ppszResult ) // Result variable storage
{
APIERR err = NERR_Success;
// static CHAR g_achBuff[200];
REG_KEY_CREATE_STRUCT regCreate;
regCreate.dwTitleIndex = 0;
regCreate.ulOptions = REG_OPTION_NON_VOLATILE;
regCreate.nlsClass = RGAS_GENERIC_CLASS;
regCreate.regSam = MAXIMUM_ALLOWED;
regCreate.pSecAttr = NULL;
regCreate.ulDisposition = 0;
do {
NLS_STR nlsNetworkCards = RGAS_SZ_NETWORK_CARD;
REG_KEY rkLocalMachine( HKEY_LOCAL_MACHINE ) ;
REG_KEY regNetworkCards( rkLocalMachine, nlsNetworkCards );
if ((( err = rkLocalMachine.QueryError()) != NERR_Success ) ||
(( err = regNetworkCards.QueryError()) != NERR_Success ))
{
break;
}
REG_ENUM regEnumCards( regNetworkCards );
if (( err = regEnumCards.QueryError()) != NERR_Success )
{
break;
}
REG_KEY_INFO_STRUCT regKeyInfo;
STRLIST strCardList;
NLS_STR *pnlsCard = NULL;
while ( regEnumCards.NextSubKey( & regKeyInfo ) == NERR_Success )
{
pnlsCard = new NLS_STR( regKeyInfo.nlsName );
if ( pnlsCard != NULL )
{
strCardList.Append( pnlsCard );
} else
{
err = ERROR_NOT_ENOUGH_MEMORY;
break;
}
}
if ( err != NERR_Success )
break;
ITER_STRLIST istrNetCard( strCardList );
while ( ( pnlsCard = istrNetCard.Next()) != NULL )
{
// check to see if the name is start with a 0
if ( *(pnlsCard->QueryPch()) == TCH('0') )
{
// do something about it
TCHAR szNewNum[3];
wsprintf( szNewNum, SZ("%s"), (pnlsCard->QueryPch() + 1) );
NLS_STR nlsNewNum = szNewNum;
REG_KEY regCard( regNetworkCards, *pnlsCard );
REG_KEY regNewCard( regNetworkCards, nlsNewNum, &regCreate );
if ((( err = regNewCard.QueryError()) != NERR_Success ) ||
(( err = regCard.QueryError()) != NERR_Success ) ||
(( err = CopyReg( regCard, regNewCard )) != NERR_Success ) ||
// delete NetworkCards\0X
(( err = regCard.DeleteTree()) != NERR_Success ))
{
continue;
}
// change 0X\ServiceName
NLS_STR nlsServiceName;
NLS_STR nlsNewServiceName;
regNewCard.QueryValue( RGAS_SZ_SERVICE, &nlsServiceName );
nlsNewServiceName = nlsServiceName;
ISTR istrStartServiceName( nlsNewServiceName );
ISTR istrEndServiceName( nlsNewServiceName );
istrStartServiceName += nlsNewServiceName.QueryNumChar() - 2;
istrEndServiceName += nlsNewServiceName.QueryNumChar() - 1;
nlsNewServiceName.DelSubStr( istrStartServiceName, istrEndServiceName );
regNewCard.SetValue( RGAS_SZ_SERVICE, nlsNewServiceName );
// change 0X\Title
NLS_STR nlsTitle;
regNewCard.QueryValue( RGAS_SZ_TITLE, &nlsTitle );
ISTR istrStartTitle( nlsTitle );
ISTR istrEndTitle( nlsTitle );
istrStartTitle += 1;
istrEndTitle += 2;
nlsTitle.DelSubStr( istrStartTitle, istrEndTitle );
regNewCard.SetValue( RGAS_SZ_TITLE, nlsTitle );
// change 0x\NetRules\bindform
NLS_STR nlsNetRules = RGAS_SZ_NETRULES;
REG_KEY regNetRules( regNewCard, nlsNetRules );
if (( err = regNetRules.QueryError()) != NERR_Success )
{
continue;
}
NLS_STR nlsBindForm;
regNetRules.QueryValue( RGAS_SZ_BINDFORM, &nlsBindForm );
ISTR istrStartBindForm( nlsBindForm );
ISTR istrEndBindForm( nlsBindForm );
ISTR istrTmp( nlsBindForm ); // temporary storage
ISTR istrHead( nlsBindForm ); // starting position for search
while (nlsBindForm.strstr( & istrTmp, *pnlsCard, istrHead ))
{
// advance to the next starting position
istrHead += pnlsCard->QueryNumChar();
// remember the last found
istrStartBindForm = istrTmp;
}
istrEndBindForm = istrStartBindForm;
istrEndBindForm += 1;
nlsBindForm.DelSubStr( istrStartBindForm, istrEndBindForm );
regNetRules.SetValue( RGAS_SZ_BINDFORM, nlsBindForm );
// change System\CurrentControlSet\Services\<ServiceName>
NLS_STR nlsServices = RGAS_SERVICES_HOME;
REG_KEY regServices( rkLocalMachine, nlsServices );
if (( err = regServices.QueryError()) != NERR_Success )
{
continue;
}
REG_KEY regServiceName( regServices, nlsServiceName );
REG_KEY regNewServiceName( regServices, nlsNewServiceName, &regCreate );
if ((( err = regServiceName.QueryError()) != NERR_Success ) ||
(( err = regNewServiceName.QueryError()) != NERR_Success ) ||
(( err = CopyReg( regServiceName, regNewServiceName )) != NERR_Success ) ||
// delete nlsServiceName
(( err = regServiceName.DeleteTree()) != NERR_Success ))
{
continue;
}
// check whether DLC is installed or not
// if yes, update it
NLS_STR nlsOldDLCName = RGAS_DLC_PARAMETERS;
nlsOldDLCName += nlsServiceName;
NLS_STR nlsNewDLCName = RGAS_DLC_PARAMETERS;
nlsNewDLCName += nlsNewServiceName;
REG_KEY regOldDLCName( regServices, nlsOldDLCName );
REG_KEY regNewDLCName( regServices, nlsNewDLCName, &regCreate );
if ((( err = regOldDLCName.QueryError()) != NERR_Success ) ||
(( err = regNewDLCName.QueryError()) != NERR_Success ) ||
(( err = CopyReg( regOldDLCName, regNewDLCName )) != NERR_Success ) ||
// delete nlsOldDLCName
(( err = regOldDLCName.DeleteTree()) != NERR_Success ))
{
continue;
}
}
}
} while (FALSE);
wsprintfA( g_achBuff, "{\"0\"}" );
*ppszResult = g_achBuff;
return TRUE;
}
//-------------------------------------------------------------------
PWSTR StrPathCleanW( PWSTR pszDest )
{
WCHAR pszSrc[MAX_PATH+1];
int iSrc = 0;
int iDest = 0;
// copy the buffer
lstrcpyW( pszSrc, pszDest );
// start writing over old buffer, could be null
// no need to do this since it was just a copy
// pszDest[iDest] = pszSrc[iSrc];
while (L'\0' != pszSrc[iSrc])
{
// remove double slashes only after the first two
while ( (iSrc > 0) &&
(L'\\' == pszSrc[iSrc]) &&
(L'\\' == pszSrc[iSrc+1]) )
{
iSrc++;
}
iSrc++;
iDest++;
pszDest[iDest] = pszSrc[iSrc];
}
return( pszDest );
}
//-------------------------------------------------------------------
PWSTR StrExstractNameW( PWSTR pszName, PWSTR pszSrc )
{
INT iSrc = lstrlenW( pszSrc ) - 1;
PWSTR pszTemp;
// from the end, find the first slash
pszTemp = wcsrchr( pszSrc, L'\\' );
if (NULL == pszTemp)
{
// no path
pszTemp = pszSrc;
}
else
{
// some path
// terminate the path
*pszTemp = L'\0';
pszTemp++;
}
// copy the name
lstrcpyW( pszName, pszTemp );
return( pszName );
}
//-------------------------------------------------------------------
BOOL FAR PASCAL NetSetupCopySingleFile(
DWORD nArgs, // Number of string arguments
LPSTR apszArgs[], // The arguments, NULL-terminated
LPSTR * ppszResult ) // Result variable storage
{
BOOL frt = FALSE;
DWORD err = ERROR_BAD_ARGUMENTS;
// this can be used to debug the verify code
// MessageBox( NULL, L"Set your breakpoints now!", L"Helper Message", MB_APPLMODAL | MB_OK );
*ppszResult = g_achBuff;
if (nArgs == 3)
{
HWND hwnd = (HWND)strtoul( apszArgs[0], '\0', 16 ) ;
if (!IsWindow( hwnd ))
{
err = ERROR_INVALID_WINDOW_HANDLE;
}
else
{
UINT errCopy = DPROMPT_CANCEL;
WCHAR pszSrc[MAX_PATH+1];
WCHAR pszDest[MAX_PATH+1];
WCHAR pszName[MAX_PATH+1];
// retrieve and convert the src and destination names, paths
MultiByteToWideChar( CP_ACP ,MB_PRECOMPOSED, apszArgs[1], -1, pszSrc, MAX_PATH );
MultiByteToWideChar( CP_ACP ,MB_PRECOMPOSED, apszArgs[2], -1, pszDest, MAX_PATH );
// lstrcpyA( pszSrc, apszArgs[1] );
// lstrcpyA( pszDest, apszArgs[2] );
// remove double slashes if present, but not if the first chars
StrPathCleanW( pszDest );
// all errors are user handled from here on
frt = TRUE;
do
{
// remove double slashes if present, but not if the first chars
StrPathCleanW( pszSrc );
err = SetupDecompressOrCopyFileW( pszSrc, pszDest, NULL );
if (ERROR_SUCCESS != err)
{
DWORD dwRequired;
// exstract just the filename from the src and modify
// src to be just the path
StrExstractNameW( pszName, pszSrc );
errCopy = SetupCopyErrorW( hwnd,
NULL,
NULL,
pszSrc,
pszName,
pszDest,
err,
0,
pszSrc,
MAX_PATH,
&dwRequired );
if (DPROMPT_SUCCESS == errCopy)
{
// replace filename on src
//
lstrcatW( pszSrc, L"\\" );
lstrcatW( pszSrc, pszName );
}
}
} while (DPROMPT_SUCCESS == errCopy);
}
}
::wsprintfA( g_achBuff, "{\"%ld\"}", err ) ;
return(frt);
}
//-------------------------------------------------------------------
//
//
//-------------------------------------------------------------------
LONG RegCopyKeyTree( HKEY hkeyDest, HKEY hkeySrc )
{
LONG lrt;
FILETIME ftLastWrite;
DWORD cchMaxSubKeyLen;
DWORD cchMaxClassLen;
DWORD cchMaxValueNameLen;
DWORD cbMaxValueLen;
DWORD iItem;
PWSTR pszName;
PWSTR pszClass;
PBYTE pbData;
DWORD cchName;
DWORD cchClass;
DWORD cbData;
HKEY hkeyChildDest;
HKEY hkeyChildSrc;
DWORD dwDisposition;
// find out the longest name and data field and create the buffers
// to store enumerations in
//
lrt = RegQueryInfoKey( hkeySrc,
NULL,
NULL,
NULL,
NULL,
&cchMaxSubKeyLen,
&cchMaxClassLen,
NULL,
&cchMaxValueNameLen,
&cbMaxValueLen,
NULL,
&ftLastWrite );
do
{
if (ERROR_SUCCESS != lrt)
{
break;
}
// use only one buffer for all names, values or keys
cchMaxValueNameLen = max( cchMaxSubKeyLen, cchMaxValueNameLen );
// allocate buffers
lrt = ERROR_NOT_ENOUGH_MEMORY;
pszName = new WCHAR[ cchMaxValueNameLen + 1 ];
if (NULL == pszName)
{
break;
}
pszClass = new WCHAR[ cchMaxClassLen + 1 ];
if (NULL == pszClass)
{
delete [] pszName;
break;
}
pbData = new BYTE[ cbMaxValueLen ];
if (NULL == pbData)
{
delete [] pszName;
delete [] pszClass;
break;
}
lrt = ERROR_SUCCESS;
// enum all sub keys and copy them
//
iItem = 0;
do
{
cchName = cchMaxValueNameLen + 1;
cchClass = cchMaxClassLen + 1;
lrt = RegEnumKeyEx( hkeySrc, iItem, pszName, &cchName, NULL, pszClass, &cchClass, &ftLastWrite );
iItem++;
if (ERROR_SUCCESS == lrt)
{
// create key at destination
lrt = RegCreateKeyEx( hkeyDest,
pszName,
0,
pszClass,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hkeyChildDest,
&dwDisposition );
if (ERROR_SUCCESS != lrt)
{
break;
}
// open the key at source
lrt = RegOpenKeyEx( hkeySrc, pszName, 0, KEY_ALL_ACCESS, &hkeyChildSrc );
if (ERROR_SUCCESS != lrt)
{
RegCloseKey( hkeyChildDest );
break;
}
// copy this sub-tree
lrt = RegCopyKeyTree( hkeyChildDest, hkeyChildSrc );
RegCloseKey( hkeyChildDest );
RegCloseKey( hkeyChildSrc );
}
} while (ERROR_SUCCESS == lrt);
if (ERROR_NO_MORE_ITEMS == lrt)
{
// enum completed, no errors
//
DWORD dwType;
// enum all values and copy them
//
iItem = 0;
do
{
cchName = cchMaxValueNameLen + 1;
cbData = cbMaxValueLen;
lrt = RegEnumValue( hkeySrc, iItem, pszName, &cchName, NULL, &dwType, pbData, &cbData );
iItem++;
if (ERROR_SUCCESS == lrt)
{
// write the value to the destination
lrt = RegSetValueEx( hkeyDest, pszName, 0, dwType, pbData, cbData );
}
} while (ERROR_SUCCESS == lrt);
if (ERROR_NO_MORE_ITEMS == lrt)
{
// if we hit the end of the enum without error
// reset error code to success
//
lrt = ERROR_SUCCESS;
}
}
// free our buffers
delete [] pszName;
delete [] pszClass;
delete [] pbData;
} while ( FALSE );
return( lrt );
}
//-------------------------------------------------------------------
//
// [0] - handle to source key
// [1] - handle to destination key
//
//-------------------------------------------------------------------
const int MAXLEN_HANDLE = 32;
BOOL FAR PASCAL NetSetupRegCopyTree(
DWORD nArgs, // Number of string arguments
LPSTR apszArgs[], // The arguments, NULL-terminated
LPSTR * ppszResult ) // Result variable storage
{
DWORD err = ERROR_BAD_ARGUMENTS;
WCHAR pszHandle[MAXLEN_HANDLE+1];
// this can be used to debug the verify code
// MessageBox( NULL, L"Set your breakpoints now!", L"Helper Message", MB_APPLMODAL | MB_OK );
*ppszResult = g_achBuff;
if (nArgs == 2)
{
mbstowcs( pszHandle, apszArgs[0], MAXLEN_HANDLE );
HKEY hkeySrc = CvtRegHandle( pszHandle ) ;
mbstowcs( pszHandle, apszArgs[1], MAXLEN_HANDLE );
HKEY hkeyDest = CvtRegHandle( pszHandle ) ;
if ( (NULL != hkeySrc) && (NULL != hkeyDest) )
{
err = RegCopyKeyTree( hkeyDest, hkeySrc );
}
}
::wsprintfA( g_achBuff, "{\"%ld\"}", err ) ;
return( 0 == err );
}
//-------------------------------------------------------------------
//
//
//
// apszArgs[0] - hwndNotify (hex)
// apszArgs[1] - message (decimal)
// apszArgs[2] - wParam Type 'A' - atom string, 'S' - string, 'D' - decimal, 'H' - hex
// apszArgs[3] - wParam, string containing wParam to convert as defined in type and pass in wParam
// apszArgs[4] - lParam Type 'A' - atom string, 'S' - string, 'D' - decimal, 'H' - hex
// apszArgs[5] - lParam, string containing lParam to convert as defined in type and pass in wParam
//
//-------------------------------------------------------------------
BOOL CreateParam( DWORD& dwParam, PSTR pszType, PSTR pszParam )
{
WCHAR pszText[MAX_PATH+1];
BOOL frt = TRUE;
switch (toupper( *pszType ))
{
case 'A':
MultiByteToWideChar( CP_ACP ,MB_PRECOMPOSED, pszParam, -1, pszText, MAX_PATH );
dwParam = (DWORD)AddAtom( pszText );
break;
case 'S':
{
PWSTR pszTemp;
INT cchTemp;
cchTemp = lstrlenA( pszParam );
pszTemp = new WCHAR[ cchTemp + 1 ];
MultiByteToWideChar( CP_ACP ,MB_PRECOMPOSED, pszParam, -1, pszTemp, cchTemp );
dwParam = (DWORD)pszTemp;
}
break;
case 'D':
dwParam = (DWORD)strtoul( pszParam, '\0', 10 ) ;
break;
case 'H':
dwParam = (DWORD)strtoul( pszParam, '\0', 16 ) ;
break;
default:
frt = FALSE;
break;
}
return( frt );
}
BOOL FAR PASCAL NetSetupSendProgressMessage(
DWORD nArgs, // Number of string arguments
LPSTR apszArgs[], // The arguments, NULL-terminated
LPSTR * ppszResult ) // Result variable storage
{
BOOL frt = FALSE;
DWORD err = ERROR_BAD_ARGUMENTS;
// this can be used to debug the verify code
// MessageBox( NULL, L"Set your breakpoints now!", L"Helper Message", MB_APPLMODAL | MB_OK );
*ppszResult = g_achBuff;
if (nArgs == 6)
{
HWND hwnd = (HWND)strtoul( apszArgs[1], '\0', 16 ) ;
if (!IsWindow( hwnd ))
{
err = ERROR_INVALID_WINDOW_HANDLE;
}
else
{
UINT msg = (UINT)strtoul( apszArgs[0], '\0', 10 ) ;
WCHAR pszwParam[MAX_PATH+1];
WCHAR pszlParam[MAX_PATH+1];
DWORD wParam;
DWORD lParam;
err = ERROR_BAD_ARGUMENTS;
do
{
if (!CreateParam( wParam, apszArgs[2], apszArgs[3] ))
{
break;
}
if (!CreateParam( lParam, apszArgs[4], apszArgs[5] ))
{
break;
}
PostMessage( hwnd, msg, wParam, lParam );
frt = TRUE;
err = 0;
} while (FALSE);
}
}
::wsprintfA( g_achBuff, "{\"%ld\"}", err ) ;
return(frt);
}
//-------------------------------------------------------------------
//
//
//
//
//-------------------------------------------------------------------
BOOL FAR PASCAL NetSetupAddNameSpaceProvider(
DWORD nArgs, // Number of string arguments
LPSTR apszArgs[], // The arguments, NULL-terminated
LPSTR * ppszResult ) // Result variable storage
{
BOOL frt = FALSE;
DWORD err = ERROR_BAD_ARGUMENTS;
// this can be used to debug the verify code
// MessageBox( NULL, L"Set your bz;reakpoints now!", L"Helper Message", MB_APPLMODAL | MB_OK );
*ppszResult = g_achBuff;
if (nArgs == 5)
{
do
{
GUID guidProvider;
WCHAR pszGuid[MAX_TEMP+1];
WCHAR pszDisplayName[MAX_TEMP+1];
WCHAR pszPathDLLName[MAX_TEMP+1];
DWORD dwNameSpace;
BOOL fSchemaSupport;
if (0 == MultiByteToWideChar( CP_ACP ,MB_PRECOMPOSED, apszArgs[4], -1, pszGuid, MAX_TEMP ))
{
break;
}
if (S_OK != IIDFromString( pszGuid, &guidProvider ))
{
break;
}
if (0 == MultiByteToWideChar( CP_ACP ,MB_PRECOMPOSED, apszArgs[0], -1, pszDisplayName, MAX_TEMP ))
{
break;
}
if (0 == MultiByteToWideChar( CP_ACP ,MB_PRECOMPOSED, apszArgs[1], -1, pszPathDLLName, MAX_TEMP ))
{
break;
}
dwNameSpace = (DWORD)strtoul( apszArgs[2], '\0', 10 ) ;
fSchemaSupport = (0 == lstrcmpiA( apszArgs[3], "TRUE" ));
err = WSCInstallNameSpace(pszDisplayName,
pszPathDLLName,
dwNameSpace,
fSchemaSupport,
&guidProvider);
} while (FALSE);
}
::wsprintfA( g_achBuff, "{\"%ld\"}", err ) ;
return(frt);
}
//-------------------------------------------------------------------
//
//
//
//
//-------------------------------------------------------------------
BOOL FAR PASCAL NetSetupRemoveNameSpaceProvider(
DWORD nArgs, // Number of string arguments
LPSTR apszArgs[], // The arguments, NULL-terminated
LPSTR * ppszResult ) // Result variable storage
{
BOOL frt = FALSE;
DWORD err = ERROR_BAD_ARGUMENTS;
// this can be used to debug the verify code
// MessageBox( NULL, L"Set your breakpoints now!", L"Helper Message", MB_APPLMODAL | MB_OK );
*ppszResult = g_achBuff;
if (nArgs == 1)
{
GUID guidProvider;
WCHAR pszGuid[MAX_TEMP+1];
if (0 != MultiByteToWideChar( CP_ACP ,MB_PRECOMPOSED, apszArgs[0], -1, pszGuid, MAX_TEMP ))
{
if (S_OK == IIDFromString( pszGuid, &guidProvider ))
{
if (ERROR_SUCCESS == WSCUnInstallNameSpace(&guidProvider))
{
err = 0;
}
}
}
}
::wsprintfA( g_achBuff, "{\"%ld\"}", err ) ;
return(frt);
}