/*++ Copyright (c) 1991 Microsoft Corporation Module Name: alinf.c Abstract: This module implements functions to access the parsed INF. Author: Sunil Pai (sunilp) 13-Nov-1991 Revision History: Calin Negreanu (calinn) 03-Sep-1998 - Major parser rewrite to work with a swap file --*/ #include "winnt.h" #include #include #include #include #include #include #include #include #include #define MAX_BUFFER_SIZE 0x1680 //7D00 #define SWAP_SIGNATURE 0xAABBCCDD #define SWAP_SIGN_SIZE 4 #define NULL_HANDLE 0 #define MAX_PATH 256 // // typedefs exported // typedef unsigned *PUNSIGNED; typedef PVOID SECTION_HANDLE; typedef unsigned long LINE_HANDLE; typedef unsigned long VALUE_HANDLE; typedef struct _SWAP_VALUE { unsigned ValueSize; VALUE_HANDLE NextValue; char ValueName[]; } SWAP_VALUE, *PSWAP_VALUE; typedef struct _SWAP_LINE { unsigned LineSize; LINE_HANDLE NextLine; VALUE_HANDLE FirstValue; VALUE_HANDLE LastValue; char LineName[]; } SWAP_LINE, *PSWAP_LINE; typedef struct _SWAP_SECTION { unsigned SectionSize; SECTION_HANDLE NextSection; LINE_HANDLE FirstLine; LINE_HANDLE LastLine; char SectionName[]; } SWAP_SECTION, *PSWAP_SECTION; typedef struct _SWAP_INF { SECTION_HANDLE CurrentSection; SECTION_HANDLE FirstSection; SECTION_HANDLE LastSection; int SwapFileHandle; unsigned long BufferSize; BOOLEAN BufferDirty; PCHAR Buffer; unsigned long BufferStart; unsigned long BufferEnd; SECTION_HANDLE LastSectionHandle; unsigned LastLineIndex; LINE_HANDLE LastLineHandle; unsigned LastValueIndex; VALUE_HANDLE LastValueHandle; char SwapFile[]; } SWAP_INF, *PSWAP_INF; char *CommonStrings[] = { (char *)("d1") }; // // DEFINES USED FOR THE PARSER INTERNALLY // // // typedefs used // typedef enum _tokentype { TOK_EOF, TOK_EOL, TOK_LBRACE, TOK_RBRACE, TOK_STRING, TOK_EQUAL, TOK_COMMA, TOK_ERRPARSE, TOK_ERRNOMEM } TOKENTYPE, *PTOKENTTYPE; typedef struct _token { TOKENTYPE Type; PCHAR pValue; } TOKEN, *PTOKEN; // // Routine defines // PSWAP_SECTION GetSectionPtr ( IN PSWAP_INF InfHandle, IN SECTION_HANDLE SectionHandle ); PSWAP_LINE GetLinePtr ( IN PSWAP_INF InfHandle, IN LINE_HANDLE LineHandle ); PSWAP_VALUE GetValuePtr ( IN PSWAP_INF InfHandle, IN VALUE_HANDLE ValueHandle ); SECTION_HANDLE GetNextSection ( IN PSWAP_INF InfHandle, IN SECTION_HANDLE SectionHandle ); LINE_HANDLE GetNextLine ( IN PSWAP_INF InfHandle, IN LINE_HANDLE LineHandle ); VALUE_HANDLE GetNextValue ( IN PSWAP_INF InfHandle, IN VALUE_HANDLE ValueHandle ); SECTION_HANDLE AddSection ( IN PSWAP_INF InfHandle, IN PCHAR SectionName ); LINE_HANDLE AddLine ( IN PSWAP_INF InfHandle, IN SECTION_HANDLE Section, IN PCHAR LineName ); VALUE_HANDLE AddValue ( IN PSWAP_INF InfHandle, IN LINE_HANDLE Line, IN PCHAR ValueName ); SECTION_HANDLE StoreNewSection ( IN PSWAP_INF InfHandle, IN PSWAP_SECTION Section ); LINE_HANDLE StoreNewLine ( IN PSWAP_INF InfHandle, IN SECTION_HANDLE Section, IN PSWAP_LINE Line ); VALUE_HANDLE StoreNewValue ( IN PSWAP_INF InfHandle, IN LINE_HANDLE Line, IN PSWAP_VALUE Value ); BOOLEAN LoadBuffer ( IN PSWAP_INF InfHandle, IN unsigned long Offset ); TOKEN GetToken ( IN FILE *File ); BOOLEAN ParseInfBuffer ( IN PSWAP_INF InfHandle, IN FILE *File, IN OUT unsigned *LineNumber ); // // Internal Routine declarations for searching in the INF structures // VALUE_HANDLE SearchValueInLineByIndex ( IN PSWAP_INF InfHandle, IN LINE_HANDLE Line, IN unsigned ValueIndex ); LINE_HANDLE SearchLineInSectionByName ( IN PSWAP_INF InfHandle, IN SECTION_HANDLE Section, IN PCHAR LineName ); LINE_HANDLE SearchLineInSectionByIndex ( IN PSWAP_INF InfHandle, IN SECTION_HANDLE Section, IN unsigned LineIndex ); SECTION_HANDLE SearchSectionByName ( IN PSWAP_INF InfHandle, IN PCHAR SectionName ); // // ROUTINE DEFINITIONS // static unsigned g_Sequencer = 0; // // returns a handle to use for further inf parsing // int DnInitINFBuffer ( IN FILE *InfFileHandle, OUT PVOID *pINFHandle, OUT unsigned *LineNumber ) /*++ Routine Description: Arguments: Return Value: --*/ { char SwapFilePath[MAX_PATH]; PSWAP_INF InfHandle = NULL; int Status; unsigned long SwapSign; *LineNumber = 0; // // Prepare the swap file path // sprintf (SwapFilePath, "%c:\\INF%03u.SWP", DngSwapDriveLetter, g_Sequencer++); // // Allocate and populate the SWAP_INF structure // InfHandle = MALLOC(sizeof(SWAP_INF) + strlen (SwapFilePath) + 1, TRUE); InfHandle->CurrentSection = NULL; InfHandle->FirstSection = NULL; InfHandle->LastSection = NULL; InfHandle->SwapFileHandle = -1; InfHandle->BufferSize = 0; InfHandle->BufferDirty = FALSE; InfHandle->Buffer = NULL; InfHandle->BufferStart = 0; InfHandle->BufferEnd = 0; InfHandle->LastSectionHandle = NULL_HANDLE; InfHandle->LastLineIndex = 0xffff; InfHandle->LastLineHandle = NULL_HANDLE; InfHandle->LastValueIndex = 0xffff; InfHandle->LastValueHandle = NULL_HANDLE; strcpy (InfHandle->SwapFile, SwapFilePath); // // Prepare the swap file // InfHandle->SwapFileHandle = open (InfHandle->SwapFile, O_BINARY|O_CREAT|O_TRUNC|O_RDWR, S_IREAD|S_IWRITE); if (InfHandle->SwapFileHandle == -1) { FREE (InfHandle); Status = errno; } else { // // write down signature // SwapSign = SWAP_SIGNATURE; write (InfHandle->SwapFileHandle, &SwapSign, SWAP_SIGN_SIZE); // // Prepare the buffer // InfHandle->BufferSize = MAX_BUFFER_SIZE; InfHandle->Buffer = MALLOC (MAX_BUFFER_SIZE, TRUE); InfHandle->BufferStart = SWAP_SIGN_SIZE; InfHandle->BufferEnd = SWAP_SIGN_SIZE; // // Parse the file // if (!ParseInfBuffer (InfHandle, InfFileHandle, LineNumber)) { // // Free SWAP_INF structure // DnFreeINFBuffer (InfHandle); *pINFHandle = NULL; Status = EBADF; } else { *pINFHandle = InfHandle; Status = EZERO; } } // // Clean up and return // return(Status); } // // frees an INF Buffer // int DnFreeINFBuffer ( IN PVOID INFHandle ) /*++ Routine Description: Arguments: Return Value: --*/ { PSWAP_INF pINF; PSWAP_SECTION Section; SECTION_HANDLE SectionHandle; // // Valid INF Handle? // if (INFHandle == (PVOID)NULL) { return EZERO; } // // cast the buffer into an INF structure // pINF = (PSWAP_INF)INFHandle; // // Close and delete the swap file // close (pINF->SwapFileHandle); remove (pINF->SwapFile); // // free temporary buffer // FREE (pINF->Buffer); // // Free section list // SectionHandle = pINF->FirstSection; while (SectionHandle) { Section = GetSectionPtr (pINF, SectionHandle); SectionHandle = Section->NextSection; FREE (Section); } // // free the inf structure too // FREE(pINF); return( EZERO ); } SECTION_HANDLE AddSection ( IN PSWAP_INF InfHandle, IN PCHAR SectionName ) { SECTION_HANDLE SectionHandle; PSWAP_SECTION Section; unsigned SectionSize; // // Let's walk through the section structures to make sure that this section does // not exist. // SectionHandle = InfHandle->FirstSection; while (SectionHandle) { Section = GetSectionPtr (InfHandle, SectionHandle); if (stricmp (Section->SectionName, SectionName) == 0) { break; } SectionHandle = GetNextSection (InfHandle, SectionHandle); } if (!SectionHandle) { // // Allocate the section structure // SectionSize = sizeof(SWAP_SECTION) + (SectionName?strlen (SectionName):0) + 1; Section = MALLOC (SectionSize, TRUE); Section->SectionSize = SectionSize; Section->NextSection = NULL; Section->FirstLine = NULL_HANDLE; Section->LastLine = NULL_HANDLE; if (SectionName) { strcpy (Section->SectionName, SectionName); } else { Section->SectionName[0] = 0; } // // Store the newly created section // SectionHandle = StoreNewSection (InfHandle, Section); } return SectionHandle; } LINE_HANDLE AddLine ( IN PSWAP_INF InfHandle, IN SECTION_HANDLE Section, IN PCHAR LineName ) { LINE_HANDLE LineHandle; PSWAP_LINE Line; unsigned LineSize; // // Allocate the line structure // LineSize = sizeof(SWAP_LINE) + (LineName?strlen (LineName):0) + 1; Line = MALLOC (LineSize, TRUE); Line->LineSize = LineSize; Line->NextLine = NULL_HANDLE; Line->FirstValue = NULL_HANDLE; Line->LastValue = NULL_HANDLE; if (LineName) { strcpy (Line->LineName, LineName); } else { Line->LineName[0] = 0; } // // Store the newly created line // LineHandle = StoreNewLine (InfHandle, Section, Line); FREE (Line); return LineHandle; } VALUE_HANDLE AddValue ( IN PSWAP_INF InfHandle, IN LINE_HANDLE Line, IN PCHAR ValueName ) { VALUE_HANDLE ValueHandle; PSWAP_VALUE Value; unsigned ValueSize; // // Allocate the value structure // ValueSize = sizeof(SWAP_VALUE) + (ValueName?strlen (ValueName):0) + 1; Value = MALLOC (ValueSize, TRUE); Value->ValueSize = ValueSize; Value->NextValue = NULL_HANDLE; if (ValueName) { strcpy (Value->ValueName, ValueName); } else { Value->ValueName[0] = 0; } // // Store the newly created line // ValueHandle = StoreNewValue (InfHandle, Line, Value); FREE (Value); return ValueHandle; } PSWAP_SECTION GetSectionPtr ( IN PSWAP_INF InfHandle, IN SECTION_HANDLE SectionHandle ) { return (PSWAP_SECTION) SectionHandle; } PSWAP_LINE GetLinePtr ( IN PSWAP_INF InfHandle, IN LINE_HANDLE LineHandle ) { // // Verify if the buffer contains the requested line (at least the size of LineSize) // if ((InfHandle->BufferStart > LineHandle) || (InfHandle->BufferEnd < (LineHandle + sizeof (unsigned))) || (InfHandle->BufferEnd < (LineHandle + *((PUNSIGNED)(InfHandle->Buffer+LineHandle-InfHandle->BufferStart)))) ) { LoadBuffer (InfHandle, LineHandle); } return (PSWAP_LINE) (InfHandle->Buffer+LineHandle-InfHandle->BufferStart); } PSWAP_VALUE GetValuePtr ( IN PSWAP_INF InfHandle, IN VALUE_HANDLE ValueHandle ) { // // Verify if the buffer contains the requested value (at least the size of ValueSize) // if ((InfHandle->BufferStart > ValueHandle) || (InfHandle->BufferEnd < (ValueHandle + sizeof (unsigned))) || (InfHandle->BufferEnd < (ValueHandle + *((PUNSIGNED)(InfHandle->Buffer+ValueHandle-InfHandle->BufferStart)))) ) { LoadBuffer (InfHandle, ValueHandle); } return (PSWAP_VALUE) (InfHandle->Buffer+ValueHandle-InfHandle->BufferStart); } SECTION_HANDLE GetNextSection ( IN PSWAP_INF InfHandle, IN SECTION_HANDLE SectionHandle ) { PSWAP_SECTION Section; Section = GetSectionPtr (InfHandle, SectionHandle); return Section->NextSection; } LINE_HANDLE GetNextLine ( IN PSWAP_INF InfHandle, IN LINE_HANDLE LineHandle ) { PSWAP_LINE Line; Line = GetLinePtr (InfHandle, LineHandle); return Line->NextLine; } VALUE_HANDLE GetNextValue ( IN PSWAP_INF InfHandle, IN VALUE_HANDLE ValueHandle ) { PSWAP_VALUE Value; Value = GetValuePtr (InfHandle, ValueHandle); return Value->NextValue; } SECTION_HANDLE StoreNewSection ( IN PSWAP_INF InfHandle, IN PSWAP_SECTION Section ) { PSWAP_SECTION LastSectionPtr; if (!InfHandle->FirstSection) { InfHandle->FirstSection = (SECTION_HANDLE) Section; InfHandle->LastSection = (SECTION_HANDLE) Section; } else { LastSectionPtr = GetSectionPtr (InfHandle, InfHandle->LastSection); LastSectionPtr->NextSection = (SECTION_HANDLE) Section; InfHandle->LastSection = (SECTION_HANDLE) Section; } return (SECTION_HANDLE) Section; } LINE_HANDLE StoreNewLine ( IN PSWAP_INF InfHandle, IN SECTION_HANDLE Section, IN PSWAP_LINE Line ) { PSWAP_SECTION SectionPtr; LINE_HANDLE LineHandle; PSWAP_LINE LastLinePtr; // // Let's store data in the swap file // if ((InfHandle->BufferSize-InfHandle->BufferEnd+InfHandle->BufferStart) < Line->LineSize) { LoadBuffer (InfHandle, 0); } memcpy (InfHandle->Buffer+InfHandle->BufferEnd-InfHandle->BufferStart, Line, Line->LineSize); InfHandle->BufferDirty = TRUE; LineHandle = InfHandle->BufferEnd; InfHandle->BufferEnd += Line->LineSize; SectionPtr = GetSectionPtr (InfHandle, Section); if (!SectionPtr->LastLine) { SectionPtr->FirstLine = LineHandle; SectionPtr->LastLine = LineHandle; } else { LastLinePtr = GetLinePtr (InfHandle, SectionPtr->LastLine); LastLinePtr->NextLine = LineHandle; InfHandle->BufferDirty = TRUE; SectionPtr = GetSectionPtr (InfHandle, Section); SectionPtr->LastLine = LineHandle; } return LineHandle; } VALUE_HANDLE StoreNewValue ( IN PSWAP_INF InfHandle, IN LINE_HANDLE Line, IN PSWAP_VALUE Value ) { PSWAP_LINE LinePtr; VALUE_HANDLE ValueHandle; PSWAP_VALUE LastValuePtr; // // Let's store data in the swap file // if ((InfHandle->BufferSize-InfHandle->BufferEnd+InfHandle->BufferStart) < Value->ValueSize) { LoadBuffer (InfHandle, 0); } memcpy (InfHandle->Buffer+InfHandle->BufferEnd-InfHandle->BufferStart, Value, Value->ValueSize); InfHandle->BufferDirty = TRUE; ValueHandle = InfHandle->BufferEnd; InfHandle->BufferEnd += Value->ValueSize; LinePtr = GetLinePtr (InfHandle, Line); if (!LinePtr->LastValue) { LinePtr->FirstValue = ValueHandle; LinePtr->LastValue = ValueHandle; InfHandle->BufferDirty = TRUE; } else { LastValuePtr = GetValuePtr (InfHandle, LinePtr->LastValue); LastValuePtr->NextValue = ValueHandle; InfHandle->BufferDirty = TRUE; LinePtr = GetLinePtr (InfHandle, Line); LinePtr->LastValue = ValueHandle; InfHandle->BufferDirty = TRUE; } return ValueHandle; } BOOLEAN LoadBuffer ( IN PSWAP_INF InfHandle, IN unsigned long Offset ) { // // See if we need to write the buffer to disk (e.g. is dirty) // if (InfHandle->BufferDirty) { lseek (InfHandle->SwapFileHandle, InfHandle->BufferStart, SEEK_SET); write (InfHandle->SwapFileHandle, InfHandle->Buffer, (unsigned int) (InfHandle->BufferEnd-InfHandle->BufferStart)); } if (!Offset) { Offset = lseek (InfHandle->SwapFileHandle, 0, SEEK_END); } InfHandle->BufferStart = lseek (InfHandle->SwapFileHandle, Offset, SEEK_SET); InfHandle->BufferEnd = InfHandle->BufferStart + read (InfHandle->SwapFileHandle, InfHandle->Buffer, MAX_BUFFER_SIZE); return TRUE; } SECTION_HANDLE SearchSectionByName ( IN PSWAP_INF InfHandle, IN PCHAR SectionName ) { SECTION_HANDLE SectionHandle; PSWAP_SECTION Section; SectionHandle = InfHandle->FirstSection; while (SectionHandle) { Section = GetSectionPtr (InfHandle, SectionHandle); if (stricmp (Section->SectionName, SectionName?SectionName:"") == 0) { break; } SectionHandle = GetNextSection (InfHandle, SectionHandle); } if (SectionHandle != InfHandle->LastSectionHandle) { InfHandle->LastSectionHandle = SectionHandle; InfHandle->LastLineIndex = 0xffff; InfHandle->LastLineHandle = NULL_HANDLE; InfHandle->LastValueIndex = 0xffff; InfHandle->LastValueHandle = NULL_HANDLE; } return SectionHandle; } LINE_HANDLE SearchLineInSectionByName ( IN PSWAP_INF InfHandle, IN SECTION_HANDLE Section, IN PCHAR LineName ) { PSWAP_SECTION SectionPtr; LINE_HANDLE LineHandle; PSWAP_LINE Line; unsigned index; if (!Section) { return NULL_HANDLE; } SectionPtr = GetSectionPtr (InfHandle, Section); LineHandle = SectionPtr->FirstLine; index = 0; while (LineHandle) { Line = GetLinePtr (InfHandle, LineHandle); if (stricmp (Line->LineName, LineName?LineName:"") == 0) { break; } index ++; LineHandle = GetNextLine (InfHandle, LineHandle); } if (LineHandle != InfHandle->LastLineHandle) { InfHandle->LastLineIndex = index; InfHandle->LastLineHandle = LineHandle; InfHandle->LastValueIndex = 0xffff; InfHandle->LastValueHandle = NULL_HANDLE; } return LineHandle; } LINE_HANDLE SearchLineInSectionByIndex ( IN PSWAP_INF InfHandle, IN SECTION_HANDLE Section, IN unsigned LineIndex ) { PSWAP_SECTION SectionPtr; LINE_HANDLE LineHandle; unsigned index; if (!Section) { return NULL_HANDLE; } // // Optimize access // if ((InfHandle->LastSectionHandle == Section) && (InfHandle->LastLineIndex <= LineIndex) ) { LineHandle = InfHandle->LastLineHandle; index = InfHandle->LastLineIndex; } else { SectionPtr = GetSectionPtr (InfHandle, Section); LineHandle = SectionPtr->FirstLine; index = 0; } while (LineHandle) { if (index == LineIndex) { break; } index ++; LineHandle = GetNextLine (InfHandle, LineHandle); } if (LineHandle != InfHandle->LastLineHandle) { InfHandle->LastLineIndex = LineIndex; InfHandle->LastLineHandle = LineHandle; InfHandle->LastValueIndex = 0xffff; InfHandle->LastValueHandle = NULL_HANDLE; } return LineHandle; } VALUE_HANDLE SearchValueInLineByIndex ( IN PSWAP_INF InfHandle, IN LINE_HANDLE Line, IN unsigned ValueIndex ) { PSWAP_LINE LinePtr; VALUE_HANDLE ValueHandle; unsigned index; if (!Line) { return NULL_HANDLE; } // // Optimize access // if ((InfHandle->LastLineHandle == Line) && (InfHandle->LastValueIndex <= ValueIndex) ) { ValueHandle = InfHandle->LastValueHandle; index = InfHandle->LastValueIndex; } else { LinePtr = GetLinePtr (InfHandle, Line); ValueHandle = LinePtr->FirstValue; index = 0; } while (ValueHandle) { if (index == ValueIndex) { break; } index ++; ValueHandle = GetNextValue (InfHandle, ValueHandle); } InfHandle->LastValueIndex = ValueIndex; InfHandle->LastValueHandle = ValueHandle; return ValueHandle; } // // Globals used by the token parser // // string terminators are the whitespace characters (isspace: space, tab, // linefeed, formfeed, vertical tab, carriage return) or the chars given below CHAR StringTerminators[] = {'[', ']', '=', ',', '\"', ' ', '\t', '\n','\f','\v','\r','\032', 0}; // // quoted string terminators allow some of the regular terminators to // appear as characters CHAR QStringTerminators[] = {'\"', '\n','\f','\v', '\r','\032', 0}; // // Main parser routine // BOOLEAN ParseInfBuffer ( IN PSWAP_INF InfHandle, IN FILE *File, IN OUT unsigned *LineNumber ) /*++ Routine Description: Given a character buffer containing the INF file, this routine parses the INF into an internal form with Section records, Line records and Value records. Arguments: InfHandle - PSWAP_INF structure used to create INF structures File - supplies open, rewound CRT handle to file. LineNumber - In case of error, this variable will contain the line in the file that contains a syntax error. Return Value: TRUE - the INF file was parsed successfully FALSE - otherwise --*/ { PCHAR pchSectionName, pchValue; unsigned State, InfLine; TOKEN Token; BOOLEAN Done; BOOLEAN Error; int ErrorCode; SECTION_HANDLE LastSection = NULL; LINE_HANDLE LastLine = NULL_HANDLE; *LineNumber = 0; // // Set initial state // State = 1; InfLine = 1; Done = FALSE; Error = FALSE; // // Enter token processing loop // while (!Done) { Token = GetToken(File); switch (State) { // // STATE1: Start of file, this state remains till first // section is found // Valid Tokens: TOK_EOL, TOK_EOF, TOK_LBRACE case 1: switch (Token.Type) { case TOK_EOL: break; case TOK_EOF: Done = TRUE; break; case TOK_LBRACE: State = 2; break; default: Error = Done = TRUE; ErrorCode = EINVAL; break; } break; // // STATE 2: Section LBRACE has been received, expecting STRING // // Valid Tokens: TOK_STRING // case 2: switch (Token.Type) { case TOK_STRING: State = 3; pchSectionName = Token.pValue; break; default: Error = Done = TRUE; ErrorCode = EINVAL; break; } break; // // STATE 3: Section Name received, expecting RBRACE // // Valid Tokens: TOK_RBRACE // case 3: switch (Token.Type) { case TOK_RBRACE: State = 4; break; default: Error = Done = TRUE; ErrorCode = EINVAL; break; } break; // // STATE 4: Section Definition Complete, expecting EOL // // Valid Tokens: TOK_EOL, TOK_EOF // case 4: switch (Token.Type) { case TOK_EOL: LastSection = AddSection (InfHandle, pchSectionName); FREE (pchSectionName); pchSectionName = NULL; State = 5; break; case TOK_EOF: LastSection = AddSection (InfHandle, pchSectionName); FREE (pchSectionName); pchSectionName = NULL; Done = TRUE; break; default: Error = Done = TRUE; ErrorCode = EINVAL; break; } break; // // STATE 5: Expecting Section Lines // // Valid Tokens: TOK_EOL, TOK_EOF, TOK_STRING, TOK_LBRACE // case 5: switch (Token.Type) { case TOK_EOL: break; case TOK_EOF: Done = TRUE; break; case TOK_STRING: pchValue = Token.pValue; State = 6; break; case TOK_LBRACE: State = 2; break; default: Error = Done = TRUE; ErrorCode = EINVAL; break; } break; // // STATE 6: String returned, not sure whether it is key or value // // Valid Tokens: TOK_EOL, TOK_EOF, TOK_COMMA, TOK_EQUAL // case 6: switch (Token.Type) { case TOK_EOL: LastLine = AddLine (InfHandle, LastSection, NULL); AddValue (InfHandle, LastLine, pchValue); FREE (pchValue); pchValue = NULL; State = 5; break; case TOK_EOF: LastLine = AddLine (InfHandle, LastSection, NULL); AddValue (InfHandle, LastLine, pchValue); FREE (pchValue); pchValue = NULL; Done = TRUE; break; case TOK_COMMA: LastLine = AddLine (InfHandle, LastSection, NULL); AddValue (InfHandle, LastLine, pchValue); FREE (pchValue); pchValue = NULL; State = 7; break; case TOK_EQUAL: LastLine = AddLine (InfHandle, LastSection, pchValue); FREE (pchValue); pchValue = NULL; State = 8; break; default: Error = Done = TRUE; ErrorCode = EINVAL; break; } break; // // STATE 7: Comma received, Expecting another string // // Valid Tokens: TOK_STRING // case 7: switch (Token.Type) { case TOK_STRING: AddValue (InfHandle, LastLine, Token.pValue); State = 9; break; case TOK_COMMA: AddValue (InfHandle, LastLine, NULL); State = 7; break; default: Error = Done = TRUE; ErrorCode = EINVAL; break; } break; // // STATE 8: Equal received, Expecting another string // // Valid Tokens: TOK_STRING // case 8: switch (Token.Type) { case TOK_STRING: AddValue (InfHandle, LastLine, Token.pValue); State = 9; break; default: Error = Done = TRUE; ErrorCode = EINVAL; break; } break; // // STATE 9: String received after equal, value string // // Valid Tokens: TOK_EOL, TOK_EOF, TOK_COMMA // case 9: switch (Token.Type) { case TOK_EOL: State = 5; break; case TOK_EOF: Done = TRUE; break; case TOK_COMMA: State = 7; break; default: Error = Done = TRUE; ErrorCode = EINVAL; break; } break; // // STATE 10: Value string definitely received // // Valid Tokens: TOK_EOL, TOK_EOF, TOK_COMMA // case 10: switch (Token.Type) { case TOK_EOL: State =5; break; case TOK_EOF: Done = TRUE; break; case TOK_COMMA: State = 7; break; default: Error = Done = TRUE; ErrorCode = EINVAL; break; } break; default: Error = Done = TRUE; ErrorCode = EINVAL; break; } // end switch(State) if (Error) { switch (ErrorCode) { case ENOMEM: DnFatalError(&DnsOutOfMemory); default: break; } } else { // // Keep track of line numbers so that we can display Errors // if (Token.Type == TOK_EOL) InfLine++; } } // End while if (Error) { *LineNumber = InfLine; } return (BOOLEAN) (!Error); } BOOLEAN TokenMatch ( IN OUT char **p, IN char *line ) /*++ Routine Description: This function tries to match to string pointed to be line against a set of commonly used stirngs. If we hit, we'll assign p to point to the matched string. Arguments: p - Supplies a char pointer that we'll assign if we find a match. line - Supplies the address of the string we're trying to match. Return Value: TRUE - we found a match and have assigned p FALSE - we found no match and made no assignment to p --*/ { int i; if( (p == NULL) || (line == NULL) ) { return( FALSE ); } for( i = 0; i < sizeof(CommonStrings)/sizeof(char *); i++ ) { if( !strcmp( line, CommonStrings[i] ) ) { // // Hit... // *p = (char *)CommonStrings[i]; return( TRUE ); } } return( FALSE ); } TOKEN GetToken( IN FILE *File ) /*++ Routine Description: This function returns the Next token from the configuration stream. Arguments: Stream - Supplies the address of the configuration stream. Returns the address of where to start looking for tokens within the stream. MaxStream - Supplies the address of the last character in the stream. Return Value: TOKEN - Returns the next token --*/ { int i; unsigned Length; TOKEN Token; #define _MAXLINE 1024 static char line[_MAXLINE+1]; char *p; // // Skip whitespace (except for eol) // while(((i = fgetc(File)) != EOF) && (i != '\n') && (isspace(i) || (i == 26))) { ; } // // Check for comments and remove them // if((i != EOF) && ((i == '#') || (i == ';'))) { while(((i = fgetc(File)) != EOF) && (i != '\n')) { ; } } // // Check to see if EOF has been reached, set the token to the right // value // if(i == EOF) { Token.Type = TOK_EOF; Token.pValue = NULL; return(Token); } switch(i) { case '[' : Token.Type = TOK_LBRACE; Token.pValue = NULL; break; case ']' : Token.Type = TOK_RBRACE; Token.pValue = NULL; break; case '=' : Token.Type = TOK_EQUAL; Token.pValue = NULL; break; case ',' : Token.Type = TOK_COMMA; Token.pValue = NULL; break; case '\n' : Token.Type = TOK_EOL; Token.pValue = NULL; break; case '\"': // // determine quoted string // Length = 0; while(((i = fgetc(File)) != EOF) && !strchr(QStringTerminators,i)) { if(Length < _MAXLINE) { line[Length++] = (char)i; } } if((i == EOF) || (i != '\"')) { Token.Type = TOK_ERRPARSE; Token.pValue = NULL; } else { line[Length] = 0; p = MALLOC(Length+1,TRUE); strcpy(p,line); Token.Type = TOK_STRING; Token.pValue = p; } break; default: // // determine regular string // line[0] = (char)i; Length = 1; while(((i = fgetc(File)) != EOF) && !strchr(StringTerminators,i)) { if(Length < _MAXLINE) { line[Length++] = (char)i; } } // // Put back the char that terminated the string. // if(i != EOF) { ungetc(i,File); } line[Length] = 0; // // See if we can use one of the common strings. // if( !TokenMatch ( &p, line ) ) { // // Nope. // p = MALLOC(Length+1,TRUE); strcpy(p,line); } else { char *p1; p1 = MALLOC (strlen(p)+1, TRUE); strcpy (p1, p); p = p1; } Token.Type = TOK_STRING; Token.pValue = p; break; } return(Token); } BOOLEAN DnSearchINFSection ( IN PVOID INFHandle, IN PCHAR SectionName ) { return (BOOLEAN) (SearchSectionByName ((PSWAP_INF)INFHandle, SectionName) != NULL_HANDLE); } PCHAR DnGetSectionLineIndex ( IN PVOID INFHandle, IN PCHAR SectionName, IN unsigned LineIndex, IN unsigned ValueIndex ) { SECTION_HANDLE SectionHandle; LINE_HANDLE LineHandle; VALUE_HANDLE ValueHandle; PSWAP_VALUE Value; PCHAR result; SectionHandle = SearchSectionByName ((PSWAP_INF)INFHandle, SectionName); if (!SectionHandle) { return NULL; } LineHandle = SearchLineInSectionByIndex ((PSWAP_INF)INFHandle, SectionHandle, LineIndex); if (!LineHandle) { return NULL; } ValueHandle = SearchValueInLineByIndex ((PSWAP_INF)INFHandle, LineHandle, ValueIndex); if (!ValueHandle) { return NULL; } Value = GetValuePtr ((PSWAP_INF)INFHandle, ValueHandle); result = MALLOC (Value->ValueSize - sizeof(SWAP_VALUE), TRUE); strcpy (result, Value->ValueName); return result; } BOOLEAN DnGetSectionKeyExists ( IN PVOID INFHandle, IN PCHAR SectionName, IN PCHAR Key ) { SECTION_HANDLE SectionHandle; SectionHandle = SearchSectionByName ((PSWAP_INF)INFHandle, SectionName); if (!SectionHandle) { return FALSE; } return (BOOLEAN) (SearchLineInSectionByName ((PSWAP_INF)INFHandle, SectionHandle, Key) != NULL_HANDLE); } BOOLEAN DnGetSectionEntryExists ( IN PVOID INFHandle, IN PCHAR SectionName, IN PCHAR Entry ) { SECTION_HANDLE SectionHandle; LINE_HANDLE LineHandle; PSWAP_SECTION SectionPtr=NULL; PSWAP_LINE LinePtr=NULL; PSWAP_VALUE ValuePtr=NULL; PCHAR pEntryName; SectionHandle = SearchSectionByName ((PSWAP_INF)INFHandle, SectionName); if (!SectionHandle) { return FALSE; } //_LOG(("Found [%s]\n", SectionName)); SectionPtr = GetSectionPtr((PSWAP_INF)INFHandle, SectionHandle); LineHandle = SectionPtr->FirstLine; while( LineHandle ){ LinePtr = GetLinePtr((PSWAP_INF)INFHandle, LineHandle); pEntryName = NULL; if( LinePtr->LineName[0] != 0){ pEntryName = LinePtr->LineName; // _LOG(("Found Line %s\n", pEntryName)); }else{ ValuePtr = GetValuePtr((PSWAP_INF)INFHandle, LinePtr->FirstValue); if (ValuePtr && (ValuePtr->ValueName[0] != 0)) { pEntryName = ValuePtr->ValueName; }else pEntryName = NULL; } //_LOG(("Found Entry %s\n", pEntryName)); if( pEntryName && !stricmp( pEntryName, Entry )){ return TRUE; } LineHandle = GetNextLine((PSWAP_INF)INFHandle, LineHandle); }// while return FALSE; } PCHAR DnGetSectionKeyIndex ( IN PVOID INFHandle, IN PCHAR SectionName, IN PCHAR Key, IN unsigned ValueIndex ) { SECTION_HANDLE SectionHandle; LINE_HANDLE LineHandle; VALUE_HANDLE ValueHandle; PSWAP_VALUE Value; PCHAR result; SectionHandle = SearchSectionByName ((PSWAP_INF)INFHandle, SectionName); if (!SectionHandle) { return NULL; } LineHandle = SearchLineInSectionByName ((PSWAP_INF)INFHandle, SectionHandle, Key); if (!LineHandle) { return NULL; } ValueHandle = SearchValueInLineByIndex ((PSWAP_INF)INFHandle, LineHandle, ValueIndex); if (!ValueHandle) { return NULL; } Value = GetValuePtr ((PSWAP_INF)INFHandle, ValueHandle); result = MALLOC (Value->ValueSize - sizeof(SWAP_VALUE), TRUE); strcpy (result, Value->ValueName); return result; } PCHAR DnGetKeyName ( IN PVOID INFHandle, IN PCHAR SectionName, IN unsigned LineIndex ) { SECTION_HANDLE SectionHandle; LINE_HANDLE LineHandle; PSWAP_LINE Line; PCHAR result; SectionHandle = SearchSectionByName ((PSWAP_INF)INFHandle, SectionName); if (!SectionHandle) { return NULL; } LineHandle = SearchLineInSectionByIndex ((PSWAP_INF)INFHandle, SectionHandle, LineIndex); if (!LineHandle) { return NULL; } Line = GetLinePtr ((PSWAP_INF)INFHandle, LineHandle); result = MALLOC (Line->LineSize - sizeof(SWAP_LINE), TRUE); strcpy (result, Line->LineName); return result; } PVOID DnNewSetupTextFile ( VOID ) { char SwapFilePath[MAX_PATH]; PSWAP_INF InfHandle = NULL; unsigned long SwapSign; // // Prepare the swap file path // sprintf (SwapFilePath, "%c:\\INF%03u.SWP", DngSwapDriveLetter, g_Sequencer++); // // Allocate and populate the SWAP_INF structure // InfHandle = MALLOC(sizeof(SWAP_INF) + strlen (SwapFilePath) + 1, TRUE); InfHandle->CurrentSection = NULL; InfHandle->FirstSection = NULL; InfHandle->LastSection = NULL; InfHandle->SwapFileHandle = -1; InfHandle->BufferSize = 0; InfHandle->BufferDirty = FALSE; InfHandle->Buffer = NULL; InfHandle->BufferStart = 0; InfHandle->BufferEnd = 0; InfHandle->LastSectionHandle = NULL_HANDLE; InfHandle->LastLineIndex = 0xffff; InfHandle->LastLineHandle = NULL_HANDLE; InfHandle->LastValueIndex = 0xffff; InfHandle->LastValueHandle = NULL_HANDLE; strcpy (InfHandle->SwapFile, SwapFilePath); // // Prepare the swap file // InfHandle->SwapFileHandle = open (InfHandle->SwapFile, O_BINARY|O_CREAT|O_TRUNC|O_RDWR, S_IREAD|S_IWRITE); if (InfHandle->SwapFileHandle == -1) { FREE (InfHandle); return NULL; } else { // // write down signature // SwapSign = SWAP_SIGNATURE; write (InfHandle->SwapFileHandle, &SwapSign, SWAP_SIGN_SIZE); // // Prepare the buffer // InfHandle->BufferSize = MAX_BUFFER_SIZE; InfHandle->Buffer = MALLOC (MAX_BUFFER_SIZE, TRUE); InfHandle->BufferStart = SWAP_SIGN_SIZE; InfHandle->BufferEnd = SWAP_SIGN_SIZE; return InfHandle; } } BOOLEAN DnWriteSetupTextFile ( IN PVOID INFHandle, IN PCHAR FileName ) { struct find_t FindData; FILE *Handle; PSWAP_INF pInf; SECTION_HANDLE Section; PSWAP_SECTION SectionPtr; LINE_HANDLE Line; PSWAP_LINE LinePtr; VALUE_HANDLE Value; PSWAP_VALUE ValuePtr; // // See if the file exists and see if it is in read-only mode // if(!_dos_findfirst(FileName,_A_HIDDEN|_A_SUBDIR|_A_SYSTEM|_A_RDONLY,&FindData)) { // // The File Exists -- Perform some simple checks // if (FindData.attrib & _A_RDONLY) { // // Make it writeable // _dos_setfileattr(FileName,_A_NORMAL); } if (FindData.attrib & _A_SUBDIR) { // // This isn't a valid file that we can work with.. // return FALSE; } } // // Obtain a handle to the file in write-only mode // Handle = fopen(FileName, "w+"); if (Handle == NULL) { // // We could not open the file // return FALSE; } pInf = (PSWAP_INF) INFHandle; if (pInf == NULL) { // // There isn't anything in the file. // That isn't an error since we can empty // the file if we so desire, but this is a // strange way todo that. However... // fclose(Handle); return TRUE; } // // NOTE - This can't handle > 64k buffers. Which may or may not be // important // Section = pInf->FirstSection; while (Section) { SectionPtr = GetSectionPtr (pInf, Section); fprintf (Handle, "[%s]\n", SectionPtr->SectionName); Line = SectionPtr->FirstLine; while (Line) { LinePtr = GetLinePtr (pInf, Line); if ((LinePtr->LineName) && (LinePtr->LineName[0])) { if (strchr (LinePtr->LineName, ' ') == NULL) { fprintf (Handle, "%s = ", LinePtr->LineName); } else { fprintf (Handle, "\"%s\" = ", LinePtr->LineName); } } Value = LinePtr->FirstValue; while (Value) { ValuePtr = GetValuePtr (pInf, Value); fprintf (Handle,"\"%s\"", ValuePtr->ValueName); Value = GetNextValue (pInf, Value); if (Value) { fprintf (Handle, ","); } } Line = GetNextLine (pInf, Line); fprintf (Handle,"\n"); } Section = GetNextSection (pInf, Section); } // // Flush and Close the file // fflush(Handle); fclose(Handle); return TRUE; } VOID DnAddLineToSection ( IN PVOID INFHandle, IN PCHAR SectionName, IN PCHAR KeyName, IN PCHAR Values[], IN ULONG ValueCount ) { SECTION_HANDLE SectionHandle; LINE_HANDLE LineHandle; VALUE_HANDLE ValueHandle; ULONG v; SectionHandle = AddSection ((PSWAP_INF)INFHandle, SectionName); LineHandle = AddLine ((PSWAP_INF)INFHandle, SectionHandle, KeyName); for (v = 0; vCurrentSection) { pInf->CurrentSection = pInf->FirstSection; } else { pInf->CurrentSection = GetNextSection (pInf, pInf->CurrentSection); } if (!pInf->CurrentSection) { return NULL; } Section = GetSectionPtr (pInf, pInf->CurrentSection); result = MALLOC (Section->SectionSize - sizeof(SWAP_SECTION), TRUE); strcpy (result, Section->SectionName); return result; } VOID DnCopySetupTextSection ( IN PVOID FromInf, IN PVOID ToInf, IN PCHAR SectionName ) { PSWAP_INF SourceInf; PSWAP_INF DestInf; SECTION_HANDLE SourceSection; SECTION_HANDLE DestSection; PSWAP_SECTION SectionPtr; LINE_HANDLE SourceLine; LINE_HANDLE DestLine; PSWAP_LINE LinePtr; VALUE_HANDLE SourceValue; VALUE_HANDLE DestValue; PSWAP_VALUE ValuePtr; SourceInf = (PSWAP_INF)FromInf; DestInf = (PSWAP_INF)ToInf; SourceSection = SearchSectionByName (FromInf, SectionName); if (SourceSection) { SectionPtr = GetSectionPtr (SourceInf, SourceSection); DestSection = AddSection (DestInf, SectionPtr->SectionName); if (DestSection) { SourceLine = SectionPtr->FirstLine; while (SourceLine) { LinePtr = GetLinePtr (SourceInf, SourceLine); DestLine = AddLine (DestInf, DestSection, LinePtr->LineName); SourceValue = LinePtr->FirstValue; while (SourceValue) { ValuePtr = GetValuePtr (SourceInf, SourceValue); DestValue = AddValue (DestInf, DestLine, ValuePtr->ValueName); SourceValue = GetNextValue (SourceInf, SourceValue); } SourceLine = GetNextLine (SourceInf, SourceLine); } } } }