483 lines
11 KiB
C
483 lines
11 KiB
C
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Copyright (c) 1997-1999 Microsoft Corporation
|
|
// All rights reserved.
|
|
//
|
|
// File Name:
|
|
// hsload.c
|
|
//
|
|
// Description:
|
|
//
|
|
// The functions in this file are a workaround. Ideally they should be
|
|
// merged in with non-Hal/SCSI equivalents of these functions. The
|
|
// decision was made to fix a HAL/SCSI bug and we are close to RTM so
|
|
// these extra functions were created to not jeopardize the standard
|
|
// answerfile write out. Sometime post-RTM these functions should be
|
|
// merged back into the core write out and queueing routines.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include "pch.h"
|
|
#include "settypes.h"
|
|
|
|
LINKED_LIST *SelectSettingQueue(QUEUENUM dwWhichQueue);
|
|
|
|
BOOL DoesSectionHaveKeys( SECTION_NODE *pSection );
|
|
|
|
BOOL SettingQueueHalScsi_Flush(LPTSTR lpFileName,
|
|
QUEUENUM dwWhichQueue);
|
|
|
|
BOOL SettingQueueHalScsi_AddSetting(LPTSTR lpSection,
|
|
LPTSTR lpKey,
|
|
LPTSTR lpValue,
|
|
QUEUENUM dwWhichQueue);
|
|
|
|
SECTION_NODE * SettingQueue_AddSection(LPTSTR lpSection, QUEUENUM dwWhichQueue);
|
|
|
|
KEY_NODE* FindKey(LINKED_LIST *ListHead,
|
|
LPTSTR lpKeyName);
|
|
|
|
VOID InsertNode(LINKED_LIST *pList, PVOID pNode);
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Function: IsBlankLine
|
|
//
|
|
// Purpose:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL
|
|
IsBlankLine( TCHAR * pszBuffer )
|
|
{
|
|
|
|
TCHAR * p = pszBuffer;
|
|
|
|
while( *p != _T('\0') )
|
|
{
|
|
if( ! _istspace( *p ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
return( TRUE );
|
|
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Function: LoadOriginalSettingsLowHalScsi
|
|
//
|
|
// Purpose:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
VOID
|
|
LoadOriginalSettingsLowHalScsi(HWND hwnd,
|
|
LPTSTR lpFileName,
|
|
QUEUENUM dwWhichQueue)
|
|
{
|
|
TCHAR Buffer[MAX_INILINE_LEN];
|
|
FILE *fp;
|
|
|
|
TCHAR SectionName[MAX_ININAME_LEN + 1] = _T("");
|
|
TCHAR KeyName[MAX_ININAME_LEN + 1] = _T("");
|
|
TCHAR *pValue;
|
|
|
|
//
|
|
// Open the answer file for reading
|
|
//
|
|
|
|
if ( (fp = My_fopen( lpFileName, _T("r") )) == NULL )
|
|
return;
|
|
|
|
//
|
|
// Read each line
|
|
//
|
|
|
|
while ( My_fgets(Buffer, MAX_INILINE_LEN - 1, fp) != NULL ) {
|
|
|
|
BOOL bSectionLine = FALSE;
|
|
BOOL bCreatedPriorSection = FALSE;
|
|
|
|
TCHAR *p;
|
|
TCHAR *pEqual;
|
|
|
|
//
|
|
// A semicolon(;) denotes that the rest of the line is a comment.
|
|
// Thus, if a semicolon(;) exists in the Buffer, place a null char
|
|
// there and send the Buffer on for further processing.
|
|
//
|
|
|
|
//
|
|
// Look for [SectionName]
|
|
//
|
|
|
|
if ( Buffer[0] == _T('[') ) {
|
|
|
|
for ( p=Buffer+1; *p && *p != _T(']'); p++ )
|
|
;
|
|
|
|
if ( p ) {
|
|
*p = _T('\0');
|
|
bSectionLine = TRUE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If this line has [SectionName], be sure we made a section node
|
|
// on the setting queue before overwriting SectionName buffer. This
|
|
// is the only way to get the SettingQueueFlush routine to write
|
|
// out an empty section. The user had an empty section originally,
|
|
// so we'll preserve it.
|
|
//
|
|
|
|
if( bSectionLine )
|
|
{
|
|
lstrcpyn(SectionName, Buffer+1, AS(SectionName));
|
|
}
|
|
else {
|
|
|
|
//
|
|
// if its not a Section line or a blank line then just add the full line to the
|
|
// queue under its appropriate section
|
|
//
|
|
|
|
if( ! IsBlankLine( Buffer ) )
|
|
{
|
|
|
|
//
|
|
// Don't add the key unless it has a section to go under. This has the side
|
|
// effect of striping comments from the top of txtsetup.oem.
|
|
//
|
|
|
|
if( SectionName[0] != _T('\0') )
|
|
{
|
|
|
|
SettingQueueHalScsi_AddSetting(SectionName,
|
|
L"",
|
|
Buffer,
|
|
dwWhichQueue);
|
|
|
|
bCreatedPriorSection = TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
My_fclose(fp);
|
|
return;
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Function: SettingQueueHalScsi_Flush
|
|
//
|
|
// Purpose: This function is called (by the wizard) once all the settings
|
|
// have been queued for Hal and SCSI.
|
|
//
|
|
// Arguments:
|
|
// LPTSTR lpFileName - name of file to create/edit
|
|
// DWORD dwWhichQueue - which queue, answers file, .udf, ...
|
|
//
|
|
// Returns:
|
|
// BOOL - success
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL
|
|
SettingQueueHalScsi_Flush(LPTSTR lpFileName,
|
|
QUEUENUM dwWhichQueue)
|
|
{
|
|
LINKED_LIST *pList;
|
|
SECTION_NODE *pSection;
|
|
KEY_NODE *pKey;
|
|
TCHAR Buffer[MAX_INILINE_LEN];
|
|
FILE *fp;
|
|
INT BufferSize = sizeof(Buffer) / sizeof(TCHAR);
|
|
HRESULT hrPrintf;
|
|
|
|
//
|
|
// Point to the proper queue to flush
|
|
//
|
|
|
|
pList = SelectSettingQueue(dwWhichQueue);
|
|
if (pList == NULL)
|
|
return FALSE;
|
|
pSection = (SECTION_NODE *) pList->Head;
|
|
|
|
//
|
|
// Start writing the file
|
|
//
|
|
|
|
if( ( fp = My_fopen( lpFileName, _T("w") ) ) == NULL ) {
|
|
|
|
return( FALSE );
|
|
|
|
}
|
|
|
|
if( My_fputs( _T(";SetupMgrTag\n"), fp ) == _TEOF ) {
|
|
|
|
My_fclose( fp );
|
|
|
|
return( FALSE );
|
|
}
|
|
|
|
//
|
|
// For each section ...
|
|
//
|
|
|
|
for ( pSection = (SECTION_NODE *) pList->Head;
|
|
pSection;
|
|
pSection = (SECTION_NODE *) pSection->Header.next ) {
|
|
|
|
Buffer[0] = _T('\0');
|
|
|
|
//
|
|
// We don't write out sections that are still marked volatile.
|
|
//
|
|
|
|
if ( pSection->bVolatile )
|
|
continue;
|
|
|
|
//
|
|
// Write the section name only if we will write keys below it
|
|
//
|
|
// ISSUE-2002/02/28-stelo- this causes problems because we want to write out
|
|
// some sections without keys, like:
|
|
//
|
|
//[NetServices]
|
|
// MS_SERVER=params.MS_SERVER
|
|
//
|
|
//[params.MS_SERVER]
|
|
//
|
|
// How can we get around this?
|
|
//
|
|
if( DoesSectionHaveKeys( pSection ) ) {
|
|
|
|
hrPrintf=StringCchPrintf(Buffer,
|
|
AS(Buffer),
|
|
_T("[%s]\n"),
|
|
pSection->lpSection);
|
|
|
|
}
|
|
else {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if( My_fputs( Buffer, fp ) == _TEOF ) {
|
|
|
|
My_fclose( fp );
|
|
|
|
return( FALSE );
|
|
|
|
}
|
|
|
|
//
|
|
// Write out the value
|
|
//
|
|
|
|
for ( pKey = (KEY_NODE *) pSection->key_list.Head;
|
|
pKey;
|
|
pKey = (KEY_NODE *) pKey->Header.next ) {
|
|
|
|
TCHAR *p;
|
|
|
|
Buffer[0] = _T('\0');
|
|
|
|
//
|
|
// An empty value means to not write it
|
|
//
|
|
|
|
if ( pKey->lpValue[0] == _T('\0') )
|
|
continue;
|
|
|
|
|
|
//
|
|
// Put the key we want into Buffer
|
|
//
|
|
|
|
lstrcatn( Buffer, pKey->lpValue, BufferSize );
|
|
|
|
if( My_fputs( Buffer, fp ) == _TEOF ) {
|
|
|
|
My_fclose( fp );
|
|
|
|
return( FALSE );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Write a blank line at the end of the section
|
|
//
|
|
|
|
hrPrintf=StringCchPrintf(Buffer, AS(Buffer), _T("\n"));
|
|
|
|
if( My_fputs( Buffer, fp ) == _TEOF ) {
|
|
|
|
My_fclose( fp );
|
|
|
|
return( FALSE );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
My_fclose( fp );
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Function: FindValue
|
|
//
|
|
// Purpose: Searches the given list of keynodes and finds one with the
|
|
// given name.
|
|
//
|
|
// Arguments:
|
|
// LPTSTR lpSection - name of section in .ini
|
|
//
|
|
// Returns:
|
|
// SECTION_NODE * or NULL if it does not exist
|
|
//
|
|
// Notes:
|
|
// - Searches are case insensitive
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
KEY_NODE* FindValue(LINKED_LIST *ListHead,
|
|
LPTSTR lpValue)
|
|
{
|
|
KEY_NODE *p = (KEY_NODE *) ListHead->Head;
|
|
|
|
if ( p == NULL )
|
|
return NULL;
|
|
|
|
do {
|
|
if ( _tcsicmp(p->lpValue, lpValue) == 0 )
|
|
break;
|
|
p = (KEY_NODE *) p->Header.next;
|
|
} while ( p );
|
|
|
|
return p;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Function: SettingQueueHalScsi_AddSetting
|
|
//
|
|
// Purpose: Same as SettingQueue_AddSetting except with HAL and SCSI all of
|
|
// the enties under a section are values, there are no keys. So don't add a
|
|
// setting if the value is already there.
|
|
//
|
|
// Arguments:
|
|
|
|
//
|
|
// Returns:
|
|
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL SettingQueueHalScsi_AddSetting(LPTSTR lpSection,
|
|
LPTSTR lpKey,
|
|
LPTSTR lpValue,
|
|
QUEUENUM dwWhichQueue)
|
|
{
|
|
SECTION_NODE *pSectionNode;
|
|
KEY_NODE *pKeyNode;
|
|
|
|
//
|
|
// You have to pass a section key and value. Section name cannot
|
|
// be empty.
|
|
//
|
|
|
|
Assert(lpSection != NULL);
|
|
Assert(lpKey != NULL);
|
|
Assert(lpValue != NULL);
|
|
Assert(lpSection[0]);
|
|
|
|
//
|
|
// See if a node for this section already exists. If not, create one.
|
|
//
|
|
|
|
pSectionNode = SettingQueue_AddSection(lpSection, dwWhichQueue);
|
|
if ( pSectionNode == NULL )
|
|
return FALSE;
|
|
|
|
//
|
|
// See if this key has already been set. If not, alloc a node and
|
|
// set all of its fields except for the lpValue.
|
|
//
|
|
// If the node already exist, free the lpValue to make room for
|
|
// the new value.
|
|
//
|
|
|
|
pKeyNode = FindValue( &pSectionNode->key_list, lpValue );
|
|
|
|
if( pKeyNode == NULL ) {
|
|
|
|
if ( (pKeyNode=malloc(sizeof(KEY_NODE))) == NULL )
|
|
return FALSE;
|
|
|
|
if ( (pKeyNode->lpKey = lstrdup(lpKey)) == NULL )
|
|
{
|
|
free(pKeyNode);
|
|
return FALSE;
|
|
}
|
|
InsertNode(&pSectionNode->key_list, pKeyNode);
|
|
|
|
} else {
|
|
|
|
#if DBG
|
|
//
|
|
// If the wizard has already set this key once, assert.
|
|
//
|
|
|
|
if ( pKeyNode->bSetOnce ) {
|
|
AssertMsg2(FALSE,
|
|
"Section \"%S\" Key \"%S\" has already been set",
|
|
lpSection, lpKey);
|
|
}
|
|
#endif
|
|
|
|
free(pKeyNode->lpValue);
|
|
}
|
|
|
|
#if DBG
|
|
//
|
|
// If this is going to an output queue, mark this setting as
|
|
// having already been set by the wizard.
|
|
//
|
|
// Note that when the input queue is copied to the output queue,
|
|
// the copy function preserves this setting.
|
|
//
|
|
|
|
pKeyNode->bSetOnce = ( (dwWhichQueue == SETTING_QUEUE_ANSWERS) |
|
|
(dwWhichQueue == SETTING_QUEUE_UDF) );
|
|
#endif
|
|
|
|
//
|
|
// Put the (possibly new) value in
|
|
//
|
|
|
|
if ( (pKeyNode->lpValue = lstrdup(lpValue)) == NULL )
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|