//---------------------------------------------------------------------------- // // 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; }