windows-nt/Source/XPSP1/NT/base/cluster/setup/common/answerfile.cpp
2020-09-26 16:20:57 +08:00

1018 lines
26 KiB
C++

/////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 1996-1998 Microsoft Corporation
//
// Module Name:
// AnswerFile.cpp
//
// Abstract:
// This is the implementation file for the CAnswerFileSection class and
// its' contained classes.
//
// Author:
// C. Brent Thomas a-brentt
//
// Revision History:
//
// 24-Sep-1998 original
//
// Notes:
//
// The classes implemented in this file include:
//
// CAnswerFileSection
// CAnswerFileEntry
// CParameterListEntry
//
// I consciously chose not to use MFC because I expect cluster setup to
// move away from MFC (probably to ATL) when it gets rewritten.
//
/////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <setupapi.h>
#include <tchar.h>
#include "AnswerFile.h"
// The following set of functions implements the CParameterList class.
/////////////////////////////////////////////////////////////////////////////
//++
//
// CParameterListEntry
//
// Routine Description:
// This is the constructor for the CParameterListEntry class.
//
// Arguments:
// None
//
// Return Value:
// None
//
//--
/////////////////////////////////////////////////////////////////////////////
CParameterListEntry::CParameterListEntry()
{
// Initialize the pointer to the next CParameterListEntry object to NULL.
m_pNextParameter = NULL; // The CParameterList object that this data
// member points to will be allocated with the
// new operator.
// Initialize the pointer to the parameter string to NULL.
m_ptszParameter = NULL; // The string that this data member points to
// will be allocated with the new operator.
}
/////////////////////////////////////////////////////////////////////////////
//++
//
// ~CParameterListEntry
//
// Routine Description:
// This is the destructor for the CParameterListEntry class.
//
// Arguments:
// None
//
// Return Value:
// None
//
//--
/////////////////////////////////////////////////////////////////////////////
CParameterListEntry::~CParameterListEntry()
{
// Delete the parameter string.
if ( m_ptszParameter != NULL )
{
delete [] m_ptszParameter;
}
// Delete any other CParameterListEntry objects that may be in this list.
if ( m_pNextParameter != NULL )
{
delete m_pNextParameter;
}
}
/////////////////////////////////////////////////////////////////////////////
//++
//
// SetParameterString
//
// Routine Description:
// This function allocates memory for a parameter string, initializes the
// string, ans sets the m_ptszParameter data member of a CParameterListEntry
// object.
//
// Arguments:
// ptszParameter - the input string
//
// Return Value:
// TRUE - indicates success
// FALSE - indicates and error occured
//
//--
/////////////////////////////////////////////////////////////////////////////
BOOL CParameterListEntry::SetParameterString( LPTSTR ptszParameter )
{
BOOL fReturnValue;
// Has the parameter string already been set?
if ( m_ptszParameter != NULL )
{
// Free the existing parameter string. It will be replaced below.
delete m_ptszParameter;
}
// Is the parameter meaningfull?
if ( (ptszParameter != NULL) && (*ptszParameter != TEXT( '\0' )) )
{
// Allocate memory for the parameter string ans save its' address.
m_ptszParameter = new TCHAR[_tcslen( ptszParameter ) + 1];
_tcscpy( m_ptszParameter, ptszParameter );
}
else
{
m_ptszParameter = NULL;
}
fReturnValue = TRUE;
return ( fReturnValue );
}
/////////////////////////////////////////////////////////////////////////////
//++
//
// GetparameterStringPointer
//
// Routine Description:
// This function returns the contents of the m_ptszParameter member of
// a CParameterListEntry object.
//
// Arguments:
// None
//
// Return Value:
// A pointer to a parameter string.
//
//--
/////////////////////////////////////////////////////////////////////////////
LPTSTR CParameterListEntry::GetParameterStringPointer( void )
{
return ( m_ptszParameter );
}
/////////////////////////////////////////////////////////////////////////////
//++
//
// SetNextParameterPointer
//
// Routine Description:
// This function sets the m_pNextParameter data member of a CParameterListEntry object.
//
// Arguments:
// pParameterListPointer - Points to a CParameterListEntry object.
//
// Return Value:
// TRUE - indicates success
// FALSE - indicates error
//
//--
/////////////////////////////////////////////////////////////////////////////
BOOL CParameterListEntry::SetNextParameterPointer( CParameterListEntry * pParameterListPointer )
{
BOOL fReturnValue;
// If the parameter list pointer has already been set, free it. It will get replaced below.
if ( m_pNextParameter != NULL )
{
delete m_pNextParameter;
}
// Set the parameter list pointer member.
m_pNextParameter = pParameterListPointer;
fReturnValue = TRUE;
return ( fReturnValue );
}
/////////////////////////////////////////////////////////////////////////////
//++
//
// GetParameterListPointer
//
// Routine Description:
// This function returns the m_pNextParameter data member of a CParameterListEntry object.
//
// Arguments:
// None
//
// Return Value:
// The value of the m_pNextParameter data member of a CParameterListEntry object.
//
//--
/////////////////////////////////////////////////////////////////////////////
CParameterListEntry * CParameterListEntry::GetParameterListPointer( void )
{
return ( m_pNextParameter );
}
// The following set of functions implements the CAnswerFileEntry class.
/////////////////////////////////////////////////////////////////////////////
//++
//
// CAnswerFileEntry
//
// Routine Description:
// This is the constructor for the CAnswerFileEntry class.
//
// Arguments:
// None
//
// Return Value:
// None
//
//--
/////////////////////////////////////////////////////////////////////////////
CAnswerFileEntry::CAnswerFileEntry()
{
// Initialize the pointer to the next CAnswerFileEntry object to NULL.
m_pNextEntry = NULL; // The CAnswerFileEntry object that this
// data member points to will be allocated
// with the new operator.
// Initialize the pointer to the key string to NULL.
m_ptszKey = NULL; // The string that this data member points to
// will be allocated with the new operator.
// Initialize the pointer to the list of parameters to NULL;
m_pParameterList = NULL; // The CParameterList object that this data
// member points to will be allocated with the
// new operator.
// Initialize the number of parameters to zero;
m_xParameterCount = 0;
}
/////////////////////////////////////////////////////////////////////////////
//++
//
// ~CAnswerFileEntry
//
// Routine Description:
// This is the destructor for the CAnswerFileEntry class.
//
// Arguments:
// None
//
// Return Value:
// None
//
//--
/////////////////////////////////////////////////////////////////////////////
CAnswerFileEntry::~CAnswerFileEntry()
{
// Delete the key string.
if ( m_ptszKey != NULL )
{
delete [] m_ptszKey;
}
// Delete the parameter list.
if ( m_pParameterList != NULL )
{
delete m_pParameterList;
}
// Delete any other CAnswerFileEntry objects that may be in this list.
if ( m_pNextEntry != NULL )
{
delete m_pNextEntry;
}
}
/////////////////////////////////////////////////////////////////////////////
//++
//
// SetKey
//
// Routine Description:
// This function sets the m_ptszKey data member of a CAnswerFileEntry object.
// It allocates memory for the string, initializes the string, and sets the
// m_ptszKey member to point to the string.
//
// Arguments:
// ptszKey - the string to which the m_ptszKey member should be set.
//
// Return Value:
// TRUE - indicates success
// FALSE - indicates that an error occured
//
//--
/////////////////////////////////////////////////////////////////////////////
BOOL CAnswerFileEntry::SetKey( LPTSTR ptszKey )
{
BOOL fReturnValue;
// If the key string has previously been set delete it.
if ( m_ptszKey != NULL )
{
delete m_ptszKey;
}
// Set the key string.
// Is the parameter meaningfull?
if ( (ptszKey != NULL) && (*ptszKey != TEXT( '\0' )) )
{
// Allocate memory for the string and save its' address.
m_ptszKey = new TCHAR[_tcslen(ptszKey) + 1];
// Store the key string.
_tcscpy( m_ptszKey, ptszKey );
}
else
{
m_ptszKey = NULL;
}
fReturnValue = TRUE;
return ( fReturnValue );
}
/////////////////////////////////////////////////////////////////////////////
//++
//
// GetKeyPointer
//
// Routine Description:
// This function returns the contents of the m_ptszKey member of a
// CAnswerFileEntry object.
//
// Arguments:
// None
//
// Return Value:
// A pointer to the key for a CAnswerFileEntry object.
//
//--
/////////////////////////////////////////////////////////////////////////////
LPTSTR CAnswerFileEntry::GetKeyPointer( void )
{
return ( m_ptszKey );
}
/////////////////////////////////////////////////////////////////////////////
//++
//
// SetParameterCount
//
// Routine Description:
// This function sets the m_xParameterCount member of a CAnswerFileEntry object.
//
// Arguments:
// xParameterCount - the number of parameters in the answer file entry
//
// Return Value:
// TRUE - indicates success
// FALSE - indicates an error occured
//
//--
/////////////////////////////////////////////////////////////////////////////
BOOL CAnswerFileEntry::SetParameterCount( int xParameterCount )
{
BOOL fReturnValue;
m_xParameterCount = xParameterCount;
fReturnValue = TRUE;
return ( fReturnValue );
}
/////////////////////////////////////////////////////////////////////////////
//++
//
// GetParameterCount
//
// Routine Description:
// This function returns the m_xParameterCount member of a CAnswerFileEntry object.
//
// Arguments:
// None
//
// Return Value:
// the number of parameters read from the answer file for this entry
//
//--
/////////////////////////////////////////////////////////////////////////////
int CAnswerFileEntry::GetParameterCount( void )
{
return ( m_xParameterCount );
}
/////////////////////////////////////////////////////////////////////////////
//++
//
// SetNextEntryPointer
//
// Routine Description:
// This function sets the m_pNextEntry member of a CAnswerFileEntry object.
//
// Arguments:
// pAnswerFileEntry - points to a CAnswerFileEntry object.
//
// Return Value:
// TRUE - indicates success
// FALSE - indicates that an error occured
//
//--
/////////////////////////////////////////////////////////////////////////////
BOOL CAnswerFileEntry::SetNextEntryPointer( CAnswerFileEntry * pEntry )
{
BOOL fReturnValue;
// If the next entry pointer has already been set free it. It will be set below.
if ( m_pNextEntry != NULL )
{
delete m_pNextEntry;
}
// Set the next entry pointer.
m_pNextEntry = pEntry;
fReturnValue = TRUE;
return ( fReturnValue );
}
/////////////////////////////////////////////////////////////////////////////
//++
//
// GetNextEntryPointer
//
// Routine Description:
// This function returns the m_pNextEntry member of a CAnswerFileEntry object.
//
// Arguments:
// None
//
// Return Value:
// The m_pNextEntry member of a CAnswerFileEntry object.
//
//--
/////////////////////////////////////////////////////////////////////////////
CAnswerFileEntry * CAnswerFileEntry::GetNextEntryPointer( void )
{
return ( m_pNextEntry );
}
/////////////////////////////////////////////////////////////////////////////
//++
//
// ReadParameters
//
// Routine Description:
// This function reads the parameters for an entry in the answer file.
// It may create and initialize a CParameterListEntry object.
//
// Arguments:
// pAnswerFileEntry - points to the CAnswerFileEntry object
// pAnswerFileContext - points to the INFCONTEXT structure for the answer file
//
// Return Value:
// TRUE - indicates that the parameters were read successfully
// FALSE - indicates that an error occured
//
//--
/////////////////////////////////////////////////////////////////////////////
BOOL CAnswerFileEntry::ReadParameters( PINFCONTEXT pAnswerFileContext )
{
BOOL fReturnValue;
// Are the parameters meaningfull?
if ( pAnswerFileContext != NULL )
{
DWORD dwFieldCount;
// How many fields are in the entry? There must be at least one to be meaningfull.
dwFieldCount = SetupGetFieldCount( pAnswerFileContext );
if ( dwFieldCount >= 1 )
{
// Read the parameters. Apparently SetupGetStringField does not handle
// empty fields gracefully. So, any empty parameter shall be treated
// as an error. Parsing will terminate at that point.
TCHAR tszBuffer[MAX_INF_STRING_LENGTH]; // buffer to receive strings
// Attempt to read the first parameter.
fReturnValue = SetupGetStringField( pAnswerFileContext,
1,
tszBuffer,
MAX_INF_STRING_LENGTH,
NULL );
// Was the first parameter read?
if ( fReturnValue == TRUE )
{
// Is the parameter string non-empty?
if ( _tcslen( tszBuffer ) > 0 )
{
// Create a CParameterListEntry object and save its' address.
CParameterListEntry * pParameterListEntry; // working pointer
pParameterListEntry = new CParameterListEntry;
if ( pParameterListEntry != NULL )
{
SetParameterListPointer( pParameterListEntry );
// Initialize the first parameter string.
pParameterListEntry->SetParameterString( tszBuffer );
int xParameterCount = 1; // one parameter has already been read.
// Are there additional parameters?
if ( dwFieldCount >= 2 )
{
// Read the second and subsequent parameters.
int xIndex;
// On entry to this loop pParameterListEntry points to the first
// CParameterListEntry object.
for ( xIndex = 2; xIndex <= (int) dwFieldCount; xIndex++ )
{
// Attempt to read a parameter.
fReturnValue = SetupGetStringField( pAnswerFileContext,
xIndex,
tszBuffer,
MAX_INF_STRING_LENGTH,
NULL );
// Was a parameter read?
if ( fReturnValue == TRUE )
{
// Is the parameter string non-empty?
if ( _tcslen( tszBuffer ) > 0 )
{
// Create a CParameterListEntry object and save its' address.
pParameterListEntry->SetNextParameterPointer( new CParameterListEntry );
// Point to the newly created CParameterListEntry object.
pParameterListEntry = pParameterListEntry->GetParameterListPointer();
// Initialize the parameter string.
pParameterListEntry->SetParameterString( tszBuffer );
// Increment the count of parameters.
xParameterCount += 1;
} // if - parameter non-empty?
else
{
// Since the parameter is an empty string, terminate
// the loop.
break;
} // if - parameter non-empty?
} // if - SetupGetStringField succeeded?
else
{
// Since SetupGetStringField failed, terminate the loop.
// fReturnValue will indicate error.
break;
} // if - SetupGetStringField succeeded?
} // for loop reading 2nd and subsequent parameters
} // Additional parameters?
else
{
fReturnValue = TRUE;
} // Additional parameters?
// Set the parameter count.
SetParameterCount( xParameterCount );
} // if - memory allocation succeeded
else
{
fReturnValue = FALSE;
} // else - memory allocation failed.
} // if - first parameter non-empty?
else
{
// There is no use attempting to read additional parameters.
SetParameterCount( 0 );
} // if - first parameter non-empty?
} // Was a parameter read?
else
{
// There is no use attempting to read additional parameters.
SetParameterCount( 0 );
} // Was a parameter read?
} // two or more fields?
else
{
// It is legal for an entry to have no parameters, but not useful.
SetParameterCount( 0 );
fReturnValue = TRUE;
} // two or more fields?
}
else
{
fReturnValue = FALSE;
}
return ( fReturnValue );
}
/////////////////////////////////////////////////////////////////////////////
//++
//
// SetParameterListPointer
//
// Routine Description:
// This function sets the m_pParameterList member of a CAnswerFileEntry object.
//
// Arguments:
// pParameterList - points to a CParameterListEntry object.
//
// Return Value:
// TRUE - indicates success
// FALSE - indicates that an error occured.
//
//--
/////////////////////////////////////////////////////////////////////////////
BOOL CAnswerFileEntry::SetParameterListPointer( CParameterListEntry * pParameterList )
{
BOOL fReturnValue;
// If the parameter list pointer has already been set free it. It will be set below.
if ( m_pParameterList != NULL )
{
delete m_pParameterList;
}
// Set the next entry pointer.
m_pParameterList = pParameterList;
fReturnValue = TRUE;
return ( fReturnValue );
}
/////////////////////////////////////////////////////////////////////////////
//++
//
// GetParameterListPointer
//
// Routine Description:
// This function returns the m_pParameterList data member of a CAnswerFileEntry object.
//
// Arguments:
// None
//
// Return Value:
// The value of the m_pParameterList data member of a CAnswerFileEntry object.
//
//--
/////////////////////////////////////////////////////////////////////////////
CParameterListEntry * CAnswerFileEntry::GetParameterListPointer( void )
{
return ( m_pParameterList );
}
// The following set of functions implements the CAnswerFileSection class.
/////////////////////////////////////////////////////////////////////////////
//++
//
// CAnswerFileSection
//
// Routine Description:
// This is the constructor for the CAnswerFileSection class.
//
// Arguments:
// None
//
// Return Value:
// None
//
//--
/////////////////////////////////////////////////////////////////////////////
CAnswerFileSection::CAnswerFileSection()
{
// Initialize the pointer to the CAnswerFileEntry objects to NULL.
m_pEntries = NULL; // The CAnswerFileEntry object that this data member
// points to will be allocated with the new operator.
}
/////////////////////////////////////////////////////////////////////////////
//++
//
// GetEntryPointer
//
// Routine Description:
// This function returns the contents of the m_pEntries member of a
// CAnswerFileSection object.
//
// Arguments:
// None
//
// Return Value:
// A pointer to a CAnswerFileEntry object.
//
//--
/////////////////////////////////////////////////////////////////////////////
CAnswerFileEntry * CAnswerFileSection::GetEntryPointer( void )
{
return ( m_pEntries );
}
/////////////////////////////////////////////////////////////////////////////
//++
//
// ~CAnswerFileSection
//
// Routine Description:
// This is the destructor for the CAnswerFileSection class.
//
// Arguments:
// None
//
// Return Value:
// None
//
//--
/////////////////////////////////////////////////////////////////////////////
CAnswerFileSection::~CAnswerFileSection()
{
// Delete the CAnswerFileEntry objects.
if ( m_pEntries != NULL )
{
delete m_pEntries;
}
}
/////////////////////////////////////////////////////////////////////////////
//++
//
// ReadAnswerFileSection
//
// Routine Description:
// This function reads the entries in an answer file.
//
// Arguments:
// hAnswerFile - the handle to the answer file
// ptszSection - points to the answer file section name
//
//
// Return Value:
// TRUE - indicates that the section whose name is in ptszSection was read
// from the answer file whose handle is hAnswerFile successfully.
// FALSE - indicates that an error occured.
//
//--
/////////////////////////////////////////////////////////////////////////////
BOOL CAnswerFileSection::ReadAnswerFileSection( HINF hAnswerFile,
LPTSTR ptszSection )
{
BOOL fReturnValue;
// Is the desired section present and non-empty in the answer file?
LONG lSectionLineCount;
lSectionLineCount = SetupGetLineCount( hAnswerFile, ptszSection );
if ( lSectionLineCount > 0L )
{
// The section is present and non empty. Find the first entry.
INFCONTEXT AnswerFileContext;
fReturnValue = SetupFindFirstLine( hAnswerFile,
ptszSection,
NULL, // find first line of the section
&AnswerFileContext );
// Was the first entry found?
if ( fReturnValue == TRUE )
{
// Get the key for the first entry.
TCHAR tszBuffer[MAX_INF_STRING_LENGTH]; // buffer to receive strings
fReturnValue = SetupGetStringField( &AnswerFileContext,
0, // get the key
tszBuffer,
MAX_INF_STRING_LENGTH,
NULL );
// Was the first key read?
if ( fReturnValue == TRUE )
{
// The key for the first entry in the section was read.
// Create the first CAnswerFileEntry object and save its' address.
m_pEntries = new CAnswerFileEntry; // m_pEntries points to the head of
// the list of CAnswerFileEntry objects.
if ( m_pEntries == NULL )
{
fReturnValue = FALSE;
}
else
{
// Set the key for the first CAnswerFileEntry object.
fReturnValue = m_pEntries->SetKey( tszBuffer );
}
// Was the key for the first entry set?
if ( fReturnValue == TRUE )
{
// Read the parameters for the first entry.
fReturnValue = m_pEntries->ReadParameters( &AnswerFileContext );
// Were the parameters for the first entry read successfully?
if ( fReturnValue == TRUE )
{
CAnswerFileEntry * pEntry; // working pointer to entries
// Initialize the working pointer to the head of the list.
pEntry = m_pEntries;
// Read the rest of the entries/
while ( (SetupFindNextLine( &AnswerFileContext, &AnswerFileContext ) == TRUE) &&
(fReturnValue == TRUE) )
{
// Create a CAnswerFileEntry object for the next entry.
pEntry->SetNextEntryPointer( new CAnswerFileEntry );
// Operate on the next entry object.
pEntry = pEntry->GetNextEntryPointer();
if ( pEntry == FALSE )
{
fReturnValue = FALSE;
break;
}
// Read the key for this entry.
fReturnValue = SetupGetStringField( &AnswerFileContext,
0, // get the key
tszBuffer,
MAX_INF_STRING_LENGTH,
NULL );
// Was the key for this entry read?
if ( fReturnValue == TRUE )
{
pEntry->SetKey( tszBuffer );
// Read the parameters for the next entry.
fReturnValue = pEntry->ReadParameters( &AnswerFileContext );
}
} // while reading lines in the section
} // params for first entry read successfully?
} // Was the first key set?
} // Was the first key read?
} // Was the first entry found?
}
else
{
// Either the section does not exist or it is empty.
fReturnValue = FALSE;
} // Does a non-empty section exist?
return ( fReturnValue );
}