mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1801 lines
52 KiB
1801 lines
52 KiB
/**********************************************************************/
|
|
/** Microsoft Windows NT **/
|
|
/** Copyright(c) Microsoft Corp., 1991 **/
|
|
/**********************************************************************/
|
|
|
|
/*
|
|
Registry.cxx
|
|
|
|
ORIGINAL NAME: NCPAPPRG.CXX
|
|
|
|
Windows/NT Network Control Panel Applet Registry Access Module
|
|
|
|
|
|
FILE HISTORY:
|
|
DavidHov 10/9/91 Created
|
|
DavidHov 12/18/91 Extended to detect NetRules key
|
|
|
|
*/
|
|
#include "pch.hxx"
|
|
//#include "Registry.hxx"
|
|
#pragma hdrstop
|
|
|
|
static const int MAX_TEMP = 1024;
|
|
|
|
DEFINE_ARRAY_OF(COMP_ASSOC)
|
|
|
|
DEFINE_SLIST_OF(HUATOM)
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: SafeStrdup
|
|
|
|
SYNOPSIS: Make a duplicate of a string safely, using
|
|
operator new.
|
|
|
|
ENTRY:
|
|
|
|
EXIT:
|
|
|
|
RETURNS:
|
|
|
|
NOTES:
|
|
|
|
HISTORY:
|
|
|
|
********************************************************************/
|
|
TCHAR * SafeStrdup ( const TCHAR * pszOld )
|
|
{
|
|
TCHAR * pszResult = new TCHAR [ ::strlenf( (TCHAR *) pszOld ) + 1 ] ;
|
|
if ( pszResult )
|
|
::strcpyf( pszResult, pszOld ) ;
|
|
return pszResult ;
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: COMPONENT_DLIST::COMPONENT_DLIST
|
|
|
|
SYNOPSIS: Constructor for class COMPONENT_DLIST.
|
|
|
|
ENTRY: enum REG_NCPA_TYPE, describing type of contained objects
|
|
|
|
EXIT: standard for constructor
|
|
|
|
RETURNS:
|
|
|
|
NOTES:
|
|
|
|
HISTORY:
|
|
|
|
********************************************************************/
|
|
|
|
COMPONENT_DLIST :: COMPONENT_DLIST ( REG_NCPA_TYPE rntType )
|
|
: _rntType( rntType )
|
|
{
|
|
if ( QueryError() )
|
|
return ;
|
|
}
|
|
|
|
COMPONENT_DLIST :: ~ COMPONENT_DLIST ()
|
|
{
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: COMPONENT_DLIST::QueryNthItem
|
|
|
|
SYNOPSIS: Return pointer to the given item in the DLIST.
|
|
|
|
ENTRY: USHORT usItemNo item to be retrieved
|
|
|
|
EXIT: none
|
|
|
|
RETURNS: REG_KEY * or NULL if unsuccessful (out of range)
|
|
|
|
NOTES:
|
|
|
|
HISTORY:
|
|
|
|
********************************************************************/
|
|
REG_KEY * COMPONENT_DLIST :: QueryNthItem ( UINT usItemNo )
|
|
{
|
|
register DL_NODE * pdlNode = _pdlHead ;
|
|
register UINT usn ;
|
|
|
|
for ( usn = 0 ;
|
|
usn < usItemNo && pdlNode != NULL ;
|
|
usn++, pdlNode = pdlNode->_pdlnodeNext ) ;
|
|
return pdlNode ? (REG_KEY *) pdlNode->_pelem : NULL ;
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: COMPONENT_DLIST::QueryInfo
|
|
|
|
SYNOPSIS: Return standard information about an element in
|
|
a COMPONENT_DLIST.
|
|
|
|
ENTRY: USHORT usItemNo item of interest
|
|
|
|
EXIT: NLS_STR * pnlsName Internal name of item
|
|
NLS_STR * pnlsDesc Displayable name of item
|
|
|
|
RETURNS: APIERR if underlying Registry operation fails.
|
|
|
|
NOTES: If the item has no title, use its name instead.
|
|
|
|
HISTORY:
|
|
|
|
********************************************************************/
|
|
|
|
APIERR COMPONENT_DLIST :: QueryInfo (
|
|
UINT usItemNo, // Item number in list
|
|
NLS_STR * pnlsName, // Internal name
|
|
NLS_STR * pnlsDesc, // External (display) name
|
|
REG_NCPA_TYPE * prntType ) // Option type storage pointer
|
|
{
|
|
APIERR err = 0 ;
|
|
REG_KEY * prnItem = QueryNthItem( usItemNo ) ;
|
|
|
|
if ( prnItem )
|
|
{
|
|
prnItem->QueryKeyName( pnlsName ) ;
|
|
|
|
if ( REGISTRY_MANAGER::QueryComponentTitle( prnItem, pnlsDesc ) != 0 )
|
|
{
|
|
*pnlsDesc = SZ("") ;
|
|
}
|
|
if ( prntType )
|
|
*prntType = _rntType ;
|
|
}
|
|
else
|
|
{
|
|
err = ERROR_INVALID_PARAMETER ;
|
|
}
|
|
return err ;
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: COMPONENT_DLIST::Sort
|
|
|
|
SYNOPSIS: Sort the component list by the alphabetic
|
|
value of the titles
|
|
|
|
ENTRY: Nothing
|
|
|
|
EXIT: Nothing
|
|
|
|
RETURNS: APIERR if failure
|
|
|
|
NOTES: List is unaffected in most failure cases.
|
|
|
|
HISTORY:
|
|
|
|
********************************************************************/
|
|
|
|
// Helper structure for QuickSorting
|
|
|
|
struct CDL_REF
|
|
{
|
|
REG_KEY * _prKey ;
|
|
NLS_STR _nlsTitle ;
|
|
};
|
|
|
|
// QuickSort helper function
|
|
|
|
INT _CRTAPI1 COMPONENT_DLIST :: SortFunc ( const VOID * a, const VOID * b )
|
|
{
|
|
CDL_REF * pcdlr1 = (CDL_REF *) a ;
|
|
CDL_REF * pcdlr2 = (CDL_REF *) b ;
|
|
|
|
return pcdlr1->_nlsTitle._stricmp( pcdlr2->_nlsTitle ) ;
|
|
}
|
|
|
|
APIERR COMPONENT_DLIST :: Sort ()
|
|
{
|
|
APIERR err = 0 ;
|
|
INT cElem ;
|
|
|
|
CDL_REF * paCdlRefTable = new CDL_REF [ cElem = QueryNumElem() ] ;
|
|
|
|
if ( paCdlRefTable == NULL )
|
|
return ERROR_NOT_ENOUGH_MEMORY ;
|
|
|
|
// Walk the list, initializing the CDL_REFs
|
|
|
|
ITER_DL_OF( REG_KEY ) itrk( *this ) ;
|
|
REG_KEY * prkNext ;
|
|
INT i ;
|
|
|
|
// Transfer all pertinent info to the CDL_REF array. Don't
|
|
// remove anything until we know it's safe.
|
|
|
|
for ( i = 0 ; prkNext = itrk.Next() ; i++ )
|
|
{
|
|
if ( err = paCdlRefTable[i]._nlsTitle.QueryError() )
|
|
break ;
|
|
|
|
paCdlRefTable[i]._prKey = prkNext ;
|
|
|
|
err = REGISTRY_MANAGER::QueryComponentTitle( prkNext,
|
|
& paCdlRefTable[i]._nlsTitle ) ;
|
|
if ( err )
|
|
break ;
|
|
}
|
|
|
|
if ( err == 0 )
|
|
{
|
|
// Drain the DLIST
|
|
|
|
for ( itrk.Reset() ;
|
|
prkNext = Remove( itrk ) ; ) ;
|
|
|
|
// Sort the CDL_REF array
|
|
|
|
::qsort( (PVOID) paCdlRefTable,
|
|
cElem,
|
|
sizeof paCdlRefTable[0],
|
|
& COMPONENT_DLIST::SortFunc ) ;
|
|
|
|
// Rebuild the DLIST. Any error here is posible
|
|
// but very unlikely.
|
|
|
|
for ( i = 0 ; i < cElem ; i++ )
|
|
{
|
|
APIERR err2 = Append( paCdlRefTable[i]._prKey ) ;
|
|
|
|
if ( err2 != 0 && err == 0 )
|
|
{
|
|
// Save the first error which occurs
|
|
err = err2 ;
|
|
}
|
|
}
|
|
}
|
|
|
|
delete [cElem] paCdlRefTable ;
|
|
|
|
return err ;
|
|
}
|
|
|
|
|
|
#ifdef DEBUG
|
|
// Iterate over the COMPONENT_DLIST and force checking of
|
|
// the REG_KEY tree hierarchy.
|
|
void validateComponentDlist ( COMPONENT_DLIST * pcdl )
|
|
{
|
|
int i ;
|
|
REG_KEY * prnNext ;
|
|
NLS_STR nlsName ;
|
|
const TCHAR * pchTemp ;
|
|
|
|
for ( i = 0 ; prnNext = pcdl->QueryNthItem( i ) ; i++ )
|
|
{
|
|
prnNext->QueryName( & nlsName ) ;
|
|
pchTemp = nlsName.QueryPch() ;
|
|
}
|
|
}
|
|
#endif // DEBUG
|
|
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: COMP_BINDING::COMP_BINDING
|
|
|
|
SYNOPSIS: constructor of binding information holder
|
|
|
|
ENTRY: BYTE * generated binding string
|
|
|
|
EXIT:
|
|
|
|
RETURNS:
|
|
|
|
NOTES: Each COMP_BINDING structure represents a single
|
|
connection between two logical components. The
|
|
binding is represented in the Registry by a string
|
|
("pszBindString") generated by the SProlog algorithm.
|
|
The "export" string is the device name which this
|
|
component creates to allow access to the path
|
|
represented by the binding.
|
|
|
|
Along with this string, a list of atoms is given
|
|
which represent the path from the "binder" (upper)
|
|
component to the "bindee" (lower) component.
|
|
|
|
For simplicity of algorithm, the atom list is added
|
|
after construction; see AddBindToName().
|
|
|
|
HISTORY:
|
|
|
|
********************************************************************/
|
|
COMP_BINDING :: COMP_BINDING (
|
|
const TCHAR * pszBindString,
|
|
const TCHAR * pszExportString,
|
|
HUATOM huaInterface,
|
|
const TCHAR * pszInterfaceName )
|
|
: _cbFlags( 0 ),
|
|
_pszBindString( NULL ),
|
|
_pszExportString( NULL ),
|
|
_pszIf( NULL ),
|
|
_huaIf( huaInterface ),
|
|
_iSortOrder( -1 )
|
|
{
|
|
if ( pszBindString )
|
|
{
|
|
_pszBindString = SafeStrdup( pszBindString ) ;
|
|
}
|
|
if ( pszExportString )
|
|
{
|
|
_pszExportString = SafeStrdup( pszExportString ) ;
|
|
}
|
|
if ( pszInterfaceName )
|
|
{
|
|
_pszIf = SafeStrdup( pszInterfaceName ) ;
|
|
}
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: COMP_BINDING:: ~ COMP_BINDING
|
|
|
|
SYNOPSIS: destructor
|
|
|
|
ENTRY:
|
|
|
|
EXIT:
|
|
|
|
RETURNS:
|
|
|
|
NOTES:
|
|
|
|
HISTORY:
|
|
|
|
********************************************************************/
|
|
COMP_BINDING :: ~ COMP_BINDING ()
|
|
{
|
|
delete _pszBindString ;
|
|
delete _pszExportString ;
|
|
delete _pszIf ;
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: COMP_BINDING:: QueryBindToName
|
|
|
|
SYNOPSIS:
|
|
|
|
ENTRY: int index index of desired bind name.
|
|
|
|
EXIT: nothing
|
|
|
|
RETURNS: pointer to HUATOM or NULL if out of range.
|
|
|
|
NOTES:
|
|
|
|
HISTORY:
|
|
|
|
********************************************************************/
|
|
HUATOM * COMP_BINDING :: QueryBindToName ( int index )
|
|
{
|
|
ITER_SL_OF(HUATOM) iter( _slhaBinds ) ;
|
|
HUATOM * phuaResult ;
|
|
|
|
for ( int i = 0 ; (phuaResult = iter.Next()) && i++ < index ; ) ;
|
|
|
|
return phuaResult ;
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: COMP_BINDING::IsInteriorTo
|
|
|
|
SYNOPSIS: Return TRUE if the this binding is a proper subset
|
|
of the given binding (i.e., does not include at least
|
|
one leading HUATOM).
|
|
|
|
ENTRY: COMP_BINDING * binding to check
|
|
HUATOM huaThisDev device name atom of device
|
|
which owns this binding
|
|
HUATOM huaBindDev device name atom of device
|
|
which owns binding to check
|
|
|
|
EXIT:
|
|
|
|
RETURNS:
|
|
|
|
NOTES: The outermost device names are treated as though
|
|
they were members of the binding atom lists.
|
|
|
|
HISTORY:
|
|
|
|
********************************************************************/
|
|
BOOL COMP_BINDING :: IsInteriorTo (
|
|
COMP_BINDING * pBind,
|
|
HUATOM huaThisDev,
|
|
HUATOM huaBindDev )
|
|
{
|
|
ITER_SL_OF(HUATOM) itslHuaThis( _slhaBinds ) ;
|
|
ITER_SL_OF(HUATOM) itslHuaTest( pBind->_slhaBinds ) ;
|
|
|
|
HUATOM * phuaThis = & huaThisDev,
|
|
* phuaTest = & huaBindDev ;
|
|
|
|
INT iAtom, cMatched ;
|
|
|
|
for ( cMatched = iAtom = 0 ;
|
|
phuaTest != NULL && phuaThis != NULL ;
|
|
phuaTest = itslHuaTest.Next(), iAtom++ )
|
|
{
|
|
// If matching, bump to next atom; else, if
|
|
// there ever was a match, quit.
|
|
|
|
if ( *phuaTest == *phuaThis )
|
|
{
|
|
cMatched++ ;
|
|
phuaThis = itslHuaThis.Next() ;
|
|
}
|
|
else
|
|
if ( cMatched )
|
|
break ;
|
|
}
|
|
|
|
// If both terminated on a match and the number of matches
|
|
// is less than the total number of atoms, it's INTERIOR!
|
|
|
|
return phuaThis == NULL
|
|
&& phuaTest == NULL
|
|
&& cMatched < iAtom ;
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: COMP_BINDING::AddBindToName
|
|
|
|
SYNOPSIS: Append the next element onto the singly-linked
|
|
component binding path list.
|
|
|
|
ENTRY: HUATOM huaBindTo SProlog name of component
|
|
|
|
EXIT: nothing
|
|
|
|
RETURNS: TRUE if element was successfully allocated and added.
|
|
|
|
NOTES:
|
|
|
|
HISTORY:
|
|
|
|
********************************************************************/
|
|
BOOL COMP_BINDING :: AddBindToName ( HUATOM huaBindTo )
|
|
{
|
|
HUATOM * phua = new HUATOM ;
|
|
if ( phua )
|
|
{
|
|
*phua = huaBindTo ;
|
|
_slhaBinds.Append( phua );
|
|
}
|
|
return phua != NULL ;
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: COMP_ASSOC::COMP_ASSOC
|
|
|
|
SYNOPSIS: Constructor of helper class Component Association
|
|
|
|
ENTRY:
|
|
|
|
EXIT:
|
|
|
|
RETURNS:
|
|
|
|
NOTES:
|
|
|
|
HISTORY: DavidHov 9/12/92 Added flag "Soft Hard Owned" to
|
|
distinguish between the cases
|
|
of LoadCompAssoc(), where the REG_KEY
|
|
_prnSoftHard is created directly,
|
|
versus CreateFacts(), where it's
|
|
borrowed from the main COMPONENT_DLIST.
|
|
|
|
********************************************************************/
|
|
COMP_ASSOC :: COMP_ASSOC ()
|
|
: _prnSoftHard( NULL ),
|
|
_prnService( NULL ),
|
|
_rncType( RGNT_NONE ),
|
|
_dwFlags( 0 ),
|
|
_cuseType( CUSE_NONE ),
|
|
_cbfBindControl( CBNDF_ACTIVE ),
|
|
_errSvcUpdate( 0 ),
|
|
_pSlDepend( NULL )
|
|
{
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: COMP_ASSOC::~COMP_ASSOC
|
|
|
|
SYNOPSIS: Destructor of helper class Component Association
|
|
|
|
ENTRY:
|
|
|
|
EXIT:
|
|
|
|
RETURNS:
|
|
|
|
NOTES: The "service" key was created just for this structure,
|
|
but the "software/hardware" key may have been "borrowed"
|
|
from the COMPONENT_DLIST used in ConvertFacts().
|
|
|
|
HISTORY:
|
|
|
|
********************************************************************/
|
|
COMP_ASSOC :: ~ COMP_ASSOC ()
|
|
{
|
|
if ( QueryFlag( CMPASF_SOFT_HARD_OWNED ) )
|
|
{
|
|
delete _prnSoftHard ;
|
|
}
|
|
_prnSoftHard = NULL ;
|
|
|
|
delete _prnService ;
|
|
_prnService = NULL ;
|
|
|
|
delete _pSlDepend ;
|
|
_pSlDepend = NULL ;
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: REGISTRY_MANAGER::REGISTRY_MANAGER
|
|
|
|
SYNOPSIS: constructor
|
|
|
|
ENTRY: nothing
|
|
|
|
EXIT: standard
|
|
|
|
RETURNS: standard for BASE object
|
|
|
|
NOTES: Failure of EVENT_LOG_SOURCE is not cause
|
|
for failure to construct.
|
|
|
|
HISTORY:
|
|
|
|
********************************************************************/
|
|
REGISTRY_MANAGER :: REGISTRY_MANAGER () :
|
|
_lastErr( NERR_Success ),
|
|
_prnLocalMachine( REG_KEY::QueryLocalMachine() ),
|
|
_prnServices( NULL )
|
|
|
|
{
|
|
if ( QueryError() )
|
|
return ;
|
|
|
|
// Access the default keys for LocalMachine and CurrentUser
|
|
|
|
if ( _prnLocalMachine == NULL )
|
|
{
|
|
ReportError( _lastErr = ERROR_BADKEY ) ;
|
|
return ;
|
|
}
|
|
|
|
// Open a key to the Services tree
|
|
|
|
_prnServices = new REG_KEY( *_prnLocalMachine, HUATOM( RGAS_SERVICES_HOME ) ) ;
|
|
|
|
_lastErr = _prnServices
|
|
? _prnServices->QueryError()
|
|
: ERROR_NOT_ENOUGH_MEMORY ;
|
|
|
|
if ( _lastErr )
|
|
{
|
|
ReportError( _lastErr ) ;
|
|
return ;
|
|
}
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: REGISTRY_MANAGER:: ~ REGISTRY_MANAGER
|
|
|
|
SYNOPSIS:
|
|
|
|
ENTRY:
|
|
|
|
EXIT:
|
|
|
|
RETURNS:
|
|
|
|
NOTES:
|
|
|
|
HISTORY:
|
|
|
|
********************************************************************/
|
|
REGISTRY_MANAGER :: ~ REGISTRY_MANAGER ()
|
|
{
|
|
delete _prnLocalMachine ;
|
|
delete _prnServices ;
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: REGSITRY_MANAGER::ListOfServices
|
|
|
|
SYNOPSIS: Return a constructed COMPONENT_DLIST containing
|
|
all of the active Services objects by enumerating
|
|
the Registry
|
|
|
|
ENTRY:
|
|
|
|
EXIT:
|
|
|
|
RETURNS:
|
|
|
|
NOTES:
|
|
|
|
HISTORY:
|
|
|
|
********************************************************************/
|
|
COMPONENT_DLIST * REGISTRY_MANAGER :: ListOfServices ()
|
|
{
|
|
REG_ENUM rgEnum( *_prnServices ) ;
|
|
REG_KEY_INFO_STRUCT nodeInfo ;
|
|
REG_KEY * prnNext = NULL ;
|
|
|
|
COMPONENT_DLIST * pdlResult = new COMPONENT_DLIST( RGNT_SERVICE ) ;
|
|
|
|
if ( pdlResult == NULL )
|
|
{
|
|
_lastErr = ERROR_NOT_ENOUGH_MEMORY ;
|
|
return NULL ;
|
|
}
|
|
|
|
_lastErr = 0 ;
|
|
|
|
while ( (_lastErr = rgEnum.NextSubKey( & nodeInfo )) != ERROR_NO_MORE_ITEMS )
|
|
{
|
|
if (_lastErr == ERROR_SUCCESS)
|
|
{
|
|
prnNext = new REG_KEY( *_prnServices, nodeInfo.nlsName ) ;
|
|
|
|
if ( prnNext == NULL )
|
|
{
|
|
_lastErr = ERROR_NOT_ENOUGH_MEMORY ;
|
|
break ;
|
|
}
|
|
if (_lastErr = prnNext->QueryError())
|
|
{
|
|
delete prnNext;
|
|
if ( (ERROR_KEY_DELETED == _lastErr ) ||
|
|
(ERROR_ACCESS_DENIED == _lastErr ))
|
|
{
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
#if defined(DEBUG)
|
|
TRACEEOL( SZ("NCPA/REG: enumerate services ")
|
|
<< nodeInfo.nlsName.QueryPch() ) ;
|
|
#endif
|
|
|
|
if ( _lastErr = pdlResult->Add( prnNext ) )
|
|
break ;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Just return what we have
|
|
|
|
_lastErr = 0 ;
|
|
|
|
return pdlResult ;
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: REGISTRY_MANAGER::ListOfNetAdapters
|
|
|
|
SYNOPSIS: Return a constructed COMPONENT_DLIST containing
|
|
all of the active Adapter objects by enumerating
|
|
the Registry
|
|
|
|
ENTRY:
|
|
|
|
EXIT:
|
|
|
|
RETURNS:
|
|
|
|
NOTES:
|
|
|
|
HISTORY: DavidHov 10/22/92 Changed to allow "hidden"
|
|
adapters.
|
|
|
|
********************************************************************/
|
|
COMPONENT_DLIST * REGISTRY_MANAGER :: ListOfNetAdapters
|
|
( BOOL fIncludeHidden )
|
|
{
|
|
COMPONENT_DLIST * pdlResult = NULL ;
|
|
NLS_STR nlsNetCard( RGAS_ADAPTER_HOME );
|
|
REG_KEY * prnNetCard = NULL ;
|
|
DWORD dwHidden ;
|
|
|
|
_lastErr = NERR_Success ;
|
|
|
|
if ( nlsNetCard.QueryError() )
|
|
{
|
|
_lastErr = nlsNetCard.QueryError() ;
|
|
return NULL ;
|
|
}
|
|
|
|
pdlResult = new COMPONENT_DLIST( RGNT_ADAPTER ) ;
|
|
if ( pdlResult == NULL )
|
|
{
|
|
_lastErr = ERROR_NOT_ENOUGH_MEMORY ;
|
|
return NULL ;
|
|
}
|
|
|
|
do
|
|
{ // pseudo-loop for escaping when precondition fails.
|
|
|
|
// Get "<local machine>\Hardware\NetCard"
|
|
|
|
prnNetCard = new REG_KEY( *_prnLocalMachine, nlsNetCard, KEY_READ ) ;
|
|
|
|
if ( prnNetCard == NULL || prnNetCard->QueryError() )
|
|
{
|
|
pdlResult->ReportError( _lastErr = ERROR_GEN_FAILURE ) ;
|
|
break ;
|
|
}
|
|
|
|
//
|
|
// Network cards are subkeys of
|
|
// <local machine>\Hardware\NetworkCard.
|
|
// Enumerate and store the names as atoms.
|
|
//
|
|
|
|
{
|
|
REG_ENUM rgEnum( *prnNetCard ) ;
|
|
REG_KEY_INFO_STRUCT nodeInfo ;
|
|
REG_KEY * prnAdapter ;
|
|
|
|
while ( (_lastErr = rgEnum.NextSubKey( & nodeInfo )) != ERROR_NO_MORE_ITEMS )
|
|
{
|
|
if (_lastErr == ERROR_SUCCESS)
|
|
{
|
|
dwHidden = 0 ;
|
|
|
|
prnAdapter = new REG_KEY( *prnNetCard, nodeInfo.nlsName ) ;
|
|
|
|
if ( prnAdapter == NULL )
|
|
{
|
|
_lastErr = ERROR_NOT_ENOUGH_MEMORY ;
|
|
break ;
|
|
}
|
|
else if (_lastErr = prnAdapter->QueryError())
|
|
{
|
|
delete prnAdapter;
|
|
|
|
if ( (ERROR_KEY_DELETED == _lastErr ) ||
|
|
(ERROR_ACCESS_DENIED == _lastErr ))
|
|
{
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if ( ! fIncludeHidden )
|
|
{
|
|
DWORD dwOpFlags;
|
|
|
|
// new operations flag support, if not present use old method
|
|
//
|
|
if (ERROR_SUCCESS != prnAdapter->QueryValue( RGAS_SOFTWARE_OPSUPPORT,
|
|
&dwOpFlags ))
|
|
{
|
|
// If value isn't there, assume it's visible...
|
|
if ( prnAdapter->QueryValue( RGAS_HIDDEN_NAME, &dwHidden ) )
|
|
{
|
|
dwHidden = 0 ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dwHidden = !(dwOpFlags & NCOS_DISPLAY) ;
|
|
}
|
|
|
|
}
|
|
|
|
if ( dwHidden == 0 )
|
|
{
|
|
if ( (_lastErr = pdlResult->Add( prnAdapter )) == 0 )
|
|
prnAdapter = NULL ;
|
|
}
|
|
delete prnAdapter ;
|
|
|
|
if ( _lastErr )
|
|
break ;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
} while ( FALSE ) ;
|
|
|
|
delete prnNetCard ;
|
|
|
|
pdlResult->Sort() ;
|
|
|
|
return pdlResult ;
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: AppendToStrList
|
|
SYNOPSIS: Adds all the Manufacturer names from an inf file
|
|
to pslInclude (if they're not already there)
|
|
ARGUEMENTS: STRLIST *pslInclude, INFCONTEXT *pinfc
|
|
RETURN:
|
|
NOTES: The option name in this line has already been
|
|
read. Append comma separated names to the STRLIST
|
|
HISTORY: ChandanS 04/26/96 Created
|
|
|
|
********************************************************************/
|
|
void AppendToStrList(STRLIST *pslInclude, INFCONTEXT *pinfc)
|
|
{
|
|
int iTok = 1; // Because we've scanned the option already
|
|
WCHAR pszManf[MAX_TEMP];
|
|
DWORD cchRequired, cchBuffer = MAX_TEMP - 1;
|
|
|
|
ASSERT(pslInclude);
|
|
ASSERT(pinfc);
|
|
while (SetupGetStringField (pinfc, iTok++, pszManf, cchBuffer, &cchRequired))
|
|
{
|
|
ITER_STRLIST iter (*pslInclude);
|
|
NLS_STR *pnlsNext = NULL;
|
|
NLS_STR *pnlsManf = new NLS_STR (pszManf);
|
|
if (pnlsManf == NULL)
|
|
{ // try and add as many as possible.
|
|
// BUGBUG Should probably report some sort of err
|
|
continue;
|
|
}
|
|
while (pnlsNext = iter.Next())
|
|
{
|
|
if (pnlsNext->_stricmp(*pnlsManf) == 0)
|
|
break;
|
|
}
|
|
if (pnlsNext == NULL)
|
|
{
|
|
TRACE(_T("netcfg: Appending %s\n"), pnlsManf->QueryPch());
|
|
pslInclude->Append(pnlsManf);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: REGISTRY_MANAGER::ListOfNetProducts
|
|
|
|
SYNOPSIS: Return a COMPONENT_DLIST of all network-related
|
|
software products. If "fIncludeHidden", include
|
|
products marked as "hidden".
|
|
|
|
ENTRY: BOOL fIncludeHidden if TRUE, include all
|
|
network products
|
|
|
|
EXIT:
|
|
|
|
RETURNS:
|
|
|
|
NOTES: Only those products with a "NetRules" key are
|
|
considered to belong to the networking ensemble.
|
|
|
|
HISTORY: DavidHov 10/22/92 Changed to only use a products's
|
|
"CurrentVersion" key
|
|
|
|
********************************************************************/
|
|
COMPONENT_DLIST * REGISTRY_MANAGER :: ListOfNetProducts
|
|
( BOOL fIncludeHidden, DWORD fLntType )
|
|
{
|
|
COMPONENT_DLIST * pdlResult = NULL ;
|
|
NLS_STR nlsSoftware( RGAS_SOFTWARE_HOME );
|
|
NLS_STR nlsNetRules( RGAS_NETRULES_NAME );
|
|
NLS_STR nlsCurrentVersion( RGAS_CURRENT_VERSION ) ;
|
|
NLS_STR nlsStDriver( RGAS_ST_DRIVER );
|
|
NLS_STR nlsStTransport( RGAS_ST_TRANSPORT );
|
|
NLS_STR nlsStService( RGAS_ST_SERVICE );
|
|
NLS_STR nlsSoftwareType;
|
|
NLS_STR nlsKey;
|
|
REG_NCPA_TYPE rgnt;
|
|
REGSAM SamReq = KEY_READ; // MAXIMUM_ALLOWED for Upgrade
|
|
BOOL fIncludeAll = FALSE; // Enumerate all Manufacturers?
|
|
STRLIST *pslInclude = new STRLIST; // List of Manufacturers to enumerate
|
|
|
|
REG_KEY * prnSft = NULL,
|
|
* prnMfg = NULL,
|
|
* prnVers = NULL,
|
|
* prnProd = NULL,
|
|
* prnNetRules = NULL ;
|
|
DWORD dwHidden ;
|
|
|
|
LONG lErr = ERROR_SUCCESS;
|
|
|
|
_lastErr = nlsSoftware.QueryError()
|
|
? nlsSoftware.QueryError()
|
|
: nlsNetRules.QueryError() ;
|
|
|
|
if ( _lastErr == 0 )
|
|
{
|
|
_lastErr = nlsCurrentVersion.QueryError() ;
|
|
}
|
|
if ( _lastErr )
|
|
{
|
|
return NULL ;
|
|
}
|
|
|
|
// convert our search type to regtype?
|
|
{
|
|
switch (fLntType)
|
|
{
|
|
case LNT_SERVICE:
|
|
rgnt = RGNT_SERVICE;
|
|
break;
|
|
|
|
case LNT_TRANSPORT:
|
|
rgnt = RGNT_TRANSPORT;
|
|
break;
|
|
|
|
case LNT_DRIVER:
|
|
rgnt = RGNT_DRIVER;
|
|
break;
|
|
|
|
case LNT_PRODUCT:
|
|
rgnt = RGNT_PRODUCT;
|
|
SamReq = MAXIMUM_ALLOWED;
|
|
break;
|
|
|
|
default:
|
|
rgnt = RGNT_PRODUCT;
|
|
break;
|
|
}
|
|
pdlResult = new COMPONENT_DLIST( rgnt ) ;
|
|
}
|
|
|
|
if ( pdlResult == NULL )
|
|
{
|
|
_lastErr = ERROR_NOT_ENOUGH_MEMORY ;
|
|
return NULL ;
|
|
}
|
|
|
|
// Build a list of Manufacturers, if in upgrade mode
|
|
if (rgnt == RGNT_PRODUCT)
|
|
{
|
|
BOOL fInfErr = FALSE;
|
|
UINT iErrorLine;
|
|
HINF hinf = SetupOpenInfFile (L"NETDEFS.INF", NULL, INF_STYLE_OLDNT, &iErrorLine);
|
|
if (hinf != INVALID_HANDLE_VALUE)
|
|
{
|
|
TRACE(_T("netcfg: Opened netdefs.inf\n"));
|
|
INFCONTEXT infc;
|
|
if (SetupFindFirstLine(hinf, L"UpgradeNetComponents", NULL, &infc))
|
|
{
|
|
WCHAR pszOption[MAX_TEMP];
|
|
DWORD cchRequired, cchBuffer = MAX_TEMP - 1;
|
|
TRACE(_T("netcfg: First line in UpgradeNetComponents\n"));
|
|
|
|
do {
|
|
if (SetupGetStringField(&infc, 0, pszOption, cchBuffer, &cchRequired))
|
|
{
|
|
TRACE(_T("netcfg: Option = %s\n"), pszOption);
|
|
if (stricmpf(pszOption, L"IncludeAll") == 0)
|
|
{
|
|
fIncludeAll = TRUE;
|
|
delete pslInclude;
|
|
pslInclude = NULL;
|
|
break;
|
|
}
|
|
else if (stricmpf(pszOption, L"Include") == 0)
|
|
{
|
|
AppendToStrList(pslInclude, &infc);
|
|
}
|
|
else if (stricmpf(pszOption, L"Exclude") == 0)
|
|
{
|
|
}
|
|
}
|
|
else // error in SetupGetStringField
|
|
{
|
|
TRACE(_T("netcfg: error in SetupGetStringField\n"));
|
|
fInfErr = TRUE;
|
|
}
|
|
} while (SetupFindNextLine (&infc, &infc));
|
|
|
|
SetupCloseInfFile (hinf);
|
|
// BUGBUG Need to merge the Include & Exclude Lists
|
|
}
|
|
else // error in SetupFindFirstLine
|
|
{
|
|
TRACE(_T("netcfg: error in SetupFindFirstLine\n"));
|
|
fInfErr = TRUE;
|
|
}
|
|
}
|
|
else // hinf == INVALID_HANDLE_VALUE
|
|
{
|
|
TRACE(_T("netcfg: could not open netdefs.inf\n"));
|
|
fInfErr = TRUE;
|
|
}
|
|
if (fInfErr)
|
|
{ //Blow the list and append nlsMS & nlsDB to it.
|
|
// BUGBUG Need to warn that we are doing the default
|
|
TRACE(_T("netcfg: Default manufacturers\n"));
|
|
fIncludeAll = FALSE;
|
|
delete pslInclude;
|
|
pslInclude = new STRLIST;
|
|
|
|
if ( pslInclude == NULL)
|
|
{
|
|
TRACE(_T("netcfg: pslInclude NULL\n"));
|
|
_lastErr = ERROR_NOT_ENOUGH_MEMORY ;
|
|
return NULL ;
|
|
}
|
|
NLS_STR *pnlsMS = new NLS_STR (L"Microsoft");
|
|
if ( pnlsMS == NULL)
|
|
{
|
|
TRACE(_T("netcfg: pnlsMS NULL\n"));
|
|
_lastErr = ERROR_NOT_ENOUGH_MEMORY ;
|
|
return NULL ;
|
|
}
|
|
if ((_lastErr = pslInclude->Append (pnlsMS)) != NERR_Success)
|
|
{
|
|
TRACE(_T("netcfg: Appending pnlsMS\n"));
|
|
return NULL ;
|
|
}
|
|
NLS_STR *pnlsDB = new NLS_STR (L"DigiBoard");
|
|
if ( pnlsDB == NULL)
|
|
{
|
|
TRACE(_T("netcfg: pnlsDB NULL\n"));
|
|
_lastErr = ERROR_NOT_ENOUGH_MEMORY ;
|
|
return NULL ;
|
|
}
|
|
if ((_lastErr = pslInclude->Append (pnlsDB)) != NERR_Success)
|
|
{
|
|
TRACE(_T("netcfg: Appending pnlsDB\n"));
|
|
return NULL ;
|
|
}
|
|
}
|
|
}
|
|
|
|
do
|
|
{ // pseudo-loop for escaping when precondition fails.
|
|
|
|
// Get "HKLM\Software"
|
|
|
|
prnSft = new REG_KEY( *_prnLocalMachine, nlsSoftware, SamReq) ;
|
|
|
|
if ( prnSft == NULL || prnSft->QueryError() )
|
|
{
|
|
_lastErr = ERROR_NOT_ENOUGH_MEMORY ;
|
|
break ;
|
|
}
|
|
|
|
//
|
|
// Software products are stored two levels deep under
|
|
// their manufacturers and their product versions.
|
|
//
|
|
// E.g.: HKLM\Software\Microsoft\Browser\CurrentVersion
|
|
//
|
|
|
|
{
|
|
REG_ENUM rgMfgEnum( *prnSft ) ;
|
|
REG_KEY_INFO_STRUCT rniInfo ;
|
|
|
|
// Enumerate Manufacturers
|
|
|
|
while ( (lErr = rgMfgEnum.NextSubKey( & rniInfo )) != ERROR_NO_MORE_ITEMS )
|
|
{
|
|
if (ERROR_SUCCESS == lErr)
|
|
{
|
|
prnMfg = new REG_KEY( *prnSft, rniInfo.nlsName, SamReq) ;
|
|
|
|
if ( prnMfg == NULL )
|
|
{
|
|
_lastErr = ERROR_NOT_ENOUGH_MEMORY ;
|
|
break ;
|
|
}
|
|
else if (_lastErr = prnMfg->QueryError())
|
|
{
|
|
delete prnMfg;
|
|
if ( (ERROR_KEY_DELETED == _lastErr ) ||
|
|
(ERROR_ACCESS_DENIED == _lastErr ))
|
|
{
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
// If in Upgrade mode, then rgnt is RGNT_PRODUCT.
|
|
// We are interested in the Manufacturers that are listed
|
|
// in pslInclude (unless fIncludeAll is TRUE).
|
|
if (rgnt == RGNT_PRODUCT)
|
|
{
|
|
BOOL fFound = FALSE;
|
|
if (!fIncludeAll)
|
|
{
|
|
ITER_STRLIST iter (*pslInclude);
|
|
prnMfg->QueryKeyName(&nlsKey);
|
|
|
|
NLS_STR *pnlsTmp = NULL;
|
|
while ((pnlsTmp = iter.Next()) != NULL)
|
|
{
|
|
if (pnlsTmp->_stricmp(nlsKey) == 0)
|
|
{
|
|
TRACE(_T("netcfg: Upgrading Manufacturer %s\n"), nlsKey.QueryPch());
|
|
pnlsTmp = pslInclude->Remove (iter);
|
|
delete pnlsTmp;
|
|
fFound = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
if (!fFound)
|
|
{
|
|
TRACE(_T("netcfg: Skipping Manufacturer %s\n"), nlsKey.QueryPch());
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Enumerate Products
|
|
|
|
REG_ENUM rgProdEnum( *prnMfg ) ;
|
|
|
|
while ( (lErr = rgProdEnum.NextSubKey( & rniInfo )) != ERROR_NO_MORE_ITEMS )
|
|
{
|
|
if (ERROR_SUCCESS == lErr)
|
|
{
|
|
prnProd = new REG_KEY( *prnMfg, rniInfo.nlsName, SamReq) ;
|
|
|
|
if ( prnProd == NULL )
|
|
{
|
|
_lastErr = ERROR_NOT_ENOUGH_MEMORY ;
|
|
break ;
|
|
}
|
|
else if (_lastErr = prnProd->QueryError())
|
|
{
|
|
delete prnProd;
|
|
if ( (ERROR_KEY_DELETED == _lastErr ) ||
|
|
(ERROR_ACCESS_DENIED == _lastErr ))
|
|
{
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Enumerate Versions
|
|
|
|
REG_ENUM rgVersEnum( *prnProd ) ;
|
|
|
|
while ( (lErr = rgVersEnum.NextSubKey( & rniInfo )) != ERROR_NO_MORE_ITEMS )
|
|
{
|
|
if (ERROR_SUCCESS == lErr)
|
|
{
|
|
// Check if this is the current version; skip it if not.
|
|
|
|
if ( rniInfo.nlsName._stricmp( nlsCurrentVersion ) != 0 )
|
|
{
|
|
continue ;
|
|
}
|
|
prnVers = new REG_KEY( *prnProd, rniInfo.nlsName ) ;
|
|
|
|
if ( prnVers == NULL )
|
|
{
|
|
_lastErr = ERROR_NOT_ENOUGH_MEMORY ;
|
|
break ;
|
|
}
|
|
else if (_lastErr = prnVers->QueryError())
|
|
{
|
|
delete prnVers;
|
|
|
|
if ( (ERROR_KEY_DELETED == _lastErr ) ||
|
|
(ERROR_ACCESS_DENIED == _lastErr ))
|
|
{
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Determine if this component is relevant to
|
|
// networking by locating its "NetRules" key.
|
|
|
|
prnNetRules = new REG_KEY( *prnVers, nlsNetRules, SamReq) ;
|
|
if ( prnNetRules == NULL )
|
|
{
|
|
_lastErr = ERROR_NOT_ENOUGH_MEMORY ;
|
|
break ;
|
|
}
|
|
else if ( prnNetRules->QueryError() == 0 )
|
|
{
|
|
BOOL fInclude = FALSE;
|
|
|
|
// Network product!
|
|
//
|
|
// check the software type for the ones requested
|
|
//
|
|
if (ERROR_SUCCESS == prnVers->QueryValue( RGAS_SOFTWARETYPE_NAME, &nlsSoftwareType))
|
|
{
|
|
|
|
if (fLntType & LNT_SERVICE)
|
|
{
|
|
if ( nlsSoftwareType == nlsStService )
|
|
{
|
|
fInclude = TRUE;
|
|
}
|
|
// if not any of the normals, think of it as a service
|
|
if ( (nlsSoftwareType != nlsStService) &&
|
|
(nlsSoftwareType != nlsStDriver) &&
|
|
(nlsSoftwareType != nlsStTransport) )
|
|
{
|
|
// change it to a service
|
|
prnVers->SetValue( RGAS_SOFTWARETYPE_NAME, nlsStService );
|
|
fInclude = TRUE;
|
|
}
|
|
}
|
|
if (fLntType & LNT_TRANSPORT)
|
|
{
|
|
if (nlsSoftwareType == nlsStTransport)
|
|
{
|
|
fInclude = TRUE;
|
|
}
|
|
}
|
|
if (fLntType & LNT_DRIVER)
|
|
{
|
|
if (nlsSoftwareType == nlsStDriver)
|
|
{
|
|
fInclude = TRUE;
|
|
}
|
|
}
|
|
if (fLntType & LNT_PRODUCT)
|
|
{
|
|
fInclude = TRUE;
|
|
}
|
|
}
|
|
else if ((fLntType & LNT_SERVICE) || (fLntType & LNT_PRODUCT))
|
|
{
|
|
// No entry means default it to service
|
|
fInclude = TRUE;
|
|
}
|
|
|
|
if (fInclude)
|
|
{
|
|
// If hidden products are to be
|
|
// excluded, query the Registry to see if it's
|
|
// a hidden product.
|
|
|
|
dwHidden = 0 ;
|
|
|
|
if ( !fIncludeHidden )
|
|
{
|
|
DWORD dwOpFlags;
|
|
|
|
// new operations flag support, if not present use old method
|
|
//
|
|
if (ERROR_SUCCESS != prnVers->QueryValue( RGAS_SOFTWARE_OPSUPPORT,
|
|
&dwOpFlags ))
|
|
{
|
|
// If value isn't there, assume it's visible...
|
|
if ( prnVers->QueryValue( RGAS_HIDDEN_NAME, &dwHidden ) )
|
|
{
|
|
dwHidden = 0 ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dwHidden = !(dwOpFlags & NCOS_DISPLAY) ;
|
|
}
|
|
}
|
|
|
|
if ( dwHidden == 0 )
|
|
{
|
|
if (rgnt == RGNT_PRODUCT)
|
|
_lastErr = pdlResult->Append( prnVers );
|
|
else
|
|
_lastErr = pdlResult->Add( prnVers );
|
|
prnVers = NULL ;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
delete prnNetRules ;
|
|
|
|
// 'prnVers' will be NULL if it was added to the result list
|
|
delete prnVers ;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( _lastErr )
|
|
{
|
|
break ;
|
|
}
|
|
delete prnProd ;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
if ( _lastErr )
|
|
{
|
|
break ;
|
|
}
|
|
delete prnMfg ;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
} while ( FALSE ) ;
|
|
|
|
delete prnSft ;
|
|
|
|
DBG_ValidateComponentDlist( pdlResult ) ;
|
|
|
|
if (rgnt != RGNT_PRODUCT)
|
|
{
|
|
pdlResult->Sort() ;
|
|
}
|
|
|
|
if (pslInclude)
|
|
{
|
|
delete pslInclude;
|
|
pslInclude = NULL;
|
|
}
|
|
|
|
return pdlResult ;
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: REGISTRY_MANAGER::ValueAsString
|
|
|
|
SYNOPSIS: Given the result of a query, return a TCHAR pointer
|
|
to the REG_SZ string.
|
|
|
|
ENTRY: REG_VALUE_INFO_STRUCT * prviStruct
|
|
.ulDataLength must describe underlying buffer
|
|
.ulDataLengthOut contains byte count from Regsitry
|
|
|
|
EXIT: nothing
|
|
|
|
RETURNS: NULL if failure;
|
|
otherwise, TCHAR * into NUL-terminated buffer
|
|
|
|
NOTES: The underlying buffer must be larger than the resulting
|
|
information by at least the width of a TCHAR.
|
|
|
|
HISTORY:
|
|
|
|
********************************************************************/
|
|
TCHAR * REGISTRY_MANAGER :: ValueAsString
|
|
( REG_VALUE_INFO_STRUCT * prviStruct )
|
|
{
|
|
TCHAR * pszResult = (TCHAR *) prviStruct->pwcData ;
|
|
if ( pszResult )
|
|
{
|
|
int dcb = prviStruct->ulDataLength - prviStruct->ulDataLengthOut ;
|
|
if ( dcb >= sizeof (TCHAR) )
|
|
{
|
|
*(pszResult + (prviStruct->ulDataLengthOut / sizeof(TCHAR))) = 0 ;
|
|
}
|
|
else
|
|
pszResult = NULL ;
|
|
}
|
|
return pszResult ;
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: REGISTRY_MANAGER::QueryValueString
|
|
|
|
SYNOPSIS: Remembers the last failed valued retrival atttempt.
|
|
|
|
ENTRY: REG_KEY * prnKey the key containing the value
|
|
TCHAR * pszValueName the name of the value
|
|
TCHAR * * ppszResult the pointer into which to store
|
|
the resulting string
|
|
DWORD * pdwTitle title storage, if ! NULL
|
|
LONG lcbSize maximum size; if zero, key
|
|
is queried to find longest value
|
|
|
|
EXIT: ppszResult updated
|
|
|
|
RETURNS: APIERR if failure
|
|
|
|
NOTES: Value type must be "REG_SZ" or ERROR_INVALID_PARAMETER
|
|
is returned.
|
|
|
|
HISTORY:
|
|
|
|
********************************************************************/
|
|
APIERR REGISTRY_MANAGER :: QueryValueString
|
|
( REG_KEY * prnKey, // Registry key
|
|
const TCHAR * pszValueName, // Name of value
|
|
TCHAR * * ppszResult, // Location to store result
|
|
DWORD * pdwTitle, // location to receive title index
|
|
LONG lcbSize, // Maximum size
|
|
BOOL fExpandSz ) // Is REG_EXPAND_SZ allowed?
|
|
{
|
|
APIERR err = prnKey->QueryValue( pszValueName,
|
|
ppszResult,
|
|
lcbSize,
|
|
pdwTitle,
|
|
fExpandSz ) ;
|
|
|
|
if ( err )
|
|
{
|
|
prnKey->QueryName( & _nlsLastName, TRUE ) ;
|
|
}
|
|
return err ;
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: REGISTRY_MANAGER::SetValueString
|
|
|
|
SYNOPSIS: Remembers the last failed value set name attempted.
|
|
|
|
ENTRY: REG_KEY * prnKey the key containing the value
|
|
TCHAR * pszValueName the name of the value
|
|
TCHAR * psValue pointer the data to be stored
|
|
DWORD dwTitle if ! REG_VALUE_NOT_KNOWN, title
|
|
EXIT: nothing
|
|
|
|
RETURNS: APIERR if failure
|
|
|
|
NOTES:
|
|
|
|
HISTORY:
|
|
|
|
********************************************************************/
|
|
APIERR REGISTRY_MANAGER :: SetValueString
|
|
( REG_KEY * prnKey, // Registry key
|
|
const TCHAR * pszValueName, // Name of value
|
|
const TCHAR * pszValue, // Data to be applied
|
|
DWORD dwTitle, // Title index (optional)
|
|
LONG lcchSize, // Size (optional)
|
|
BOOL fExpandSz ) // Value is REG_EXPAND_SZ
|
|
{
|
|
APIERR err = prnKey->SetValue( pszValueName,
|
|
pszValue,
|
|
lcchSize,
|
|
dwTitle == REG_VALUE_NOT_KNOWN
|
|
? NULL
|
|
: & dwTitle,
|
|
fExpandSz ) ;
|
|
|
|
if ( err ) // If error, store the name of the problematical key
|
|
{
|
|
prnKey->QueryName( & _nlsLastName, TRUE ) ;
|
|
}
|
|
return err ;
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: REGISTRY_MANAGER::QueryValueLong
|
|
|
|
SYNOPSIS: Remembers the last failed valued retrival atttempt.
|
|
|
|
ENTRY: REG_KEY * prnKey the key containing the value
|
|
TCHAR * pszValueName the name of the value
|
|
LONG * pnResult the result of the query
|
|
|
|
EXIT: *pnResult updated
|
|
|
|
RETURNS: APIERR if failure
|
|
|
|
NOTES: Value type must be "REG_DWORD" or ERROR_INVALID_PARAMETER
|
|
is return.
|
|
|
|
HISTORY:
|
|
|
|
********************************************************************/
|
|
APIERR REGISTRY_MANAGER :: QueryValueLong
|
|
( REG_KEY * prnKey, // Registry key
|
|
const TCHAR * pszValueName, // Name of value
|
|
LONG * pnResult, // Location to store result
|
|
DWORD * pdwTitle ) // location to receive title index
|
|
{
|
|
APIERR err = prnKey->QueryValue( pszValueName,
|
|
(DWORD *) pnResult,
|
|
pdwTitle ) ;
|
|
if ( err )
|
|
{
|
|
prnKey->QueryName( & _nlsLastName, TRUE ) ;
|
|
}
|
|
return err ;
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: REGISTRY_MANAGER::SetValueLong
|
|
|
|
SYNOPSIS: Remembers the last failed value set name attempted.
|
|
|
|
ENTRY: REG_KEY * prnKey the key containing the value
|
|
TCHAR * pszValueName the name of the value
|
|
LONG nNewValue the value of the value
|
|
|
|
EXIT: nothing
|
|
|
|
RETURNS: APIERR if failure
|
|
|
|
NOTES:
|
|
|
|
HISTORY:
|
|
|
|
********************************************************************/
|
|
APIERR REGISTRY_MANAGER :: SetValueLong
|
|
( REG_KEY * prnKey, // Registry key
|
|
const TCHAR * pszValueName, // Name of value
|
|
LONG nNewValue, // Data to be applied
|
|
DWORD dwTitle ) // Title index (optional)
|
|
{
|
|
APIERR err = prnKey->SetValue( pszValueName,
|
|
(DWORD) nNewValue,
|
|
dwTitle == REG_VALUE_NOT_KNOWN
|
|
? NULL
|
|
: & dwTitle ) ;
|
|
if ( err )
|
|
{
|
|
prnKey->QueryName( & _nlsLastName, TRUE ) ;
|
|
}
|
|
return err ;
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: REGISTRY_MANAGER::QueryComponentTitle
|
|
|
|
SYNOPSIS: Return a displayable name for a component; the
|
|
title cannot be assumed to exist, so use the
|
|
key if it doesn't.
|
|
|
|
ENTRY: const REG_KEY * REG_KEY of component
|
|
|
|
EXIT: NLS_STR * string to store title into
|
|
|
|
RETURNS: APIERR if failure
|
|
|
|
NOTES:
|
|
|
|
HISTORY:
|
|
|
|
********************************************************************/
|
|
|
|
APIERR REGISTRY_MANAGER :: QueryComponentTitle
|
|
( REG_KEY * prnComp, NLS_STR * pnlsTitle )
|
|
{
|
|
APIERR err = prnComp->QueryValue( RGAS_COMPONENT_TITLE, pnlsTitle ) ;
|
|
|
|
if ( err ) // If no explicit title value, use the component name
|
|
{
|
|
err = prnComp->QueryKeyName( pnlsTitle ) ;
|
|
}
|
|
|
|
if ( err == 0 )
|
|
{
|
|
err = pnlsTitle ? pnlsTitle->QueryError() : 0 ;
|
|
}
|
|
return err ;
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: REGISTRY_MANAGER::QueryBindControl
|
|
|
|
SYNOPSIS: Return the binding control flag word for this component
|
|
REG_KEY.
|
|
|
|
ENTRY: const REG_KEY * REG_KEY of component
|
|
|
|
EXIT: Nothing
|
|
|
|
RETURNS: COMP_BIND_FLAGS bind control flags;
|
|
|
|
NOTES: A default value is supplied if the product
|
|
doesn't have the value.
|
|
|
|
HISTORY: DavidHov 11/18/92 Created
|
|
|
|
********************************************************************/
|
|
|
|
COMP_BIND_FLAGS REGISTRY_MANAGER :: QueryBindControl ( REG_KEY * prnComp )
|
|
{
|
|
DWORD dwResult ;
|
|
COMP_BIND_FLAGS cbfResult = CBNDF_ACTIVE ;
|
|
|
|
if ( prnComp->QueryValue( RGAS_BINDING_CTL_FLAGS, & dwResult ) == 0 )
|
|
{
|
|
// Allow only the flags we understand and support
|
|
// C8 note: anal restrictions on ENUMs render them almost useless.
|
|
|
|
cbfResult = (COMP_BIND_FLAGS) (dwResult & (CBNDF_ACTIVE | CBNDF_READ_ONLY | CBNDF_HIDDEN)) ;
|
|
}
|
|
|
|
return cbfResult ;
|
|
}
|
|
|
|
|
|
#define PROVIDER_ORDER SZ("System\\CurrentControlSet\\Control\\NetworkProvider\\Order")
|
|
#define PROVIDER_ORDER_NAME SZ("ProviderOrder")
|
|
#define SYSTEM_SERVICE0 SZ("System\\CurrentControlSet\\Services\\%1\\NetworkProvider")
|
|
#define NAME SZ("NAME")
|
|
#define SZ_CLASS SZ("Class")
|
|
|
|
#define PRINT_PROVIDER_ORDER SZ("System\\CurrentControlSet\\Control\\Print\\Providers")
|
|
#define PRINT_PROVIDER_ORDER_NAME SZ("Order")
|
|
#define PRINT_SERVICE0 SZ("System\\CurrentControlSet\\Control\\Print\\Providers\\%1")
|
|
|
|
// Return the number of existing UNC providers
|
|
INT REGISTRY_MANAGER :: QueryNumProviders ()
|
|
{
|
|
NLS_STR nlsProvidersOrder( PROVIDER_ORDER );
|
|
REG_KEY rkLocalMachine( HKEY_LOCAL_MACHINE ) ;
|
|
|
|
if ( rkLocalMachine.QueryError() )
|
|
{
|
|
_lastErr = IDS_WINREG_BADDB ;
|
|
return -1 ;
|
|
}
|
|
if ( _lastErr = nlsProvidersOrder.QueryError() )
|
|
{
|
|
return -1 ;
|
|
}
|
|
REG_KEY regkeyProvidersOrder( rkLocalMachine, nlsProvidersOrder );
|
|
if ( regkeyProvidersOrder.QueryError() != NERR_Success )
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
REG_VALUE_INFO_STRUCT regvalue;
|
|
BUFFER buf(512);
|
|
if (_lastErr = buf.QueryError())
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
regvalue.pwcData = buf.QueryPtr();
|
|
regvalue.ulDataLength = buf.QuerySize();
|
|
|
|
NLS_STR nlsProvidersOrderName= PROVIDER_ORDER_NAME ;
|
|
if (_lastErr = nlsProvidersOrderName.QueryError())
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
regvalue.nlsValueName = nlsProvidersOrderName;
|
|
if ( regkeyProvidersOrder.QueryValue( ®value ) != NERR_Success )
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
STRLIST strlst( REGISTRY_MANAGER::ValueAsString( & regvalue ), SZ(",") );
|
|
|
|
// count the real provider
|
|
ITER_STRLIST istr( strlst );
|
|
INT nNumProvider = 0;
|
|
NLS_STR * pTmp;
|
|
while (( pTmp = istr.Next())!= NULL )
|
|
{
|
|
NLS_STR nlsService = SYSTEM_SERVICE0;
|
|
nlsService.InsertParams( *pTmp );
|
|
|
|
REG_KEY regkeyService( rkLocalMachine, nlsService );
|
|
if ( regkeyService.QueryError() == NERR_Success )
|
|
{
|
|
DWORD dwClass;
|
|
if ( regkeyService.QueryValue( SZ_CLASS, &dwClass ) == NERR_Success )
|
|
{
|
|
if (!( dwClass & WN_NETWORK_CLASS ))
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
nNumProvider ++;
|
|
}
|
|
return nNumProvider;
|
|
}
|
|
|
|
// Return the number of printer providers.
|
|
INT REGISTRY_MANAGER :: QueryNumPrintProviders ()
|
|
{
|
|
NLS_STR nlsProvidersOrder( PRINT_PROVIDER_ORDER );
|
|
REG_KEY rkLocalMachine( HKEY_LOCAL_MACHINE ) ;
|
|
|
|
if ( rkLocalMachine.QueryError() )
|
|
{
|
|
_lastErr = IDS_WINREG_BADDB ;
|
|
return -1 ;
|
|
}
|
|
if ( _lastErr = nlsProvidersOrder.QueryError() )
|
|
{
|
|
return -1 ;
|
|
}
|
|
REG_KEY regkeyProvidersOrder( rkLocalMachine, nlsProvidersOrder );
|
|
if ( regkeyProvidersOrder.QueryError() != NERR_Success )
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
REG_VALUE_INFO_STRUCT regvalue;
|
|
BUFFER buf(512);
|
|
if (_lastErr = buf.QueryError())
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
regvalue.pwcData = buf.QueryPtr();
|
|
regvalue.ulDataLength = buf.QuerySize();
|
|
|
|
NLS_STR nlsProvidersOrderName= PRINT_PROVIDER_ORDER_NAME ;
|
|
if (_lastErr = nlsProvidersOrderName.QueryError())
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
regvalue.nlsValueName = nlsProvidersOrderName;
|
|
if ( regkeyProvidersOrder.QueryValue( ®value ) != NERR_Success )
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
//Convert the NULL seperator to "," separator.
|
|
LPTSTR lpPoint = (LPTSTR) regvalue.pwcData;
|
|
while ( ((*lpPoint) != 0) || ((*(lpPoint+1)) != 0))
|
|
{
|
|
if ( (*lpPoint) == 0 )
|
|
{
|
|
*(lpPoint) = TCH(',');
|
|
}
|
|
|
|
lpPoint++;
|
|
}
|
|
|
|
STRLIST strlst( REGISTRY_MANAGER::ValueAsString( & regvalue ), SZ(",") );
|
|
|
|
return strlst.QueryNumElem();
|
|
}
|
|
|
|
// End of NCPAPPRG.CXX
|