1971 lines
44 KiB
C
1971 lines
44 KiB
C
|
/*++
|
||
|
|
||
|
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 <string.h>
|
||
|
#include <ctype.h>
|
||
|
#include <errno.h>
|
||
|
#include <dos.h>
|
||
|
#include <stdio.h>
|
||
|
#include <io.h>
|
||
|
#include <fcntl.h>
|
||
|
#include <sys/types.h>
|
||
|
#include <sys/stat.h>
|
||
|
|
||
|
|
||
|
#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; v<ValueCount; v++) {
|
||
|
|
||
|
ValueHandle = AddValue ((PSWAP_INF)INFHandle, LineHandle, Values[v]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
PCHAR
|
||
|
DnGetSectionName (
|
||
|
IN PVOID INFHandle
|
||
|
)
|
||
|
{
|
||
|
PSWAP_INF pInf;
|
||
|
PSWAP_SECTION Section;
|
||
|
PCHAR result;
|
||
|
|
||
|
pInf = (PSWAP_INF)INFHandle;
|
||
|
if (!pInf->CurrentSection) {
|
||
|
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);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|