reactos/reactos/tools/mkhive/infcache.c
Robert Dickenson 2e841b972e Trivial mod to remove obsolete comment about bugfix. Thanks Eric for comfirming.
Removed line:
//  while (Section != NULL)  // RobD - this looks like an error, Section variable never changes inside the while loop...

svn path=/trunk/; revision=6334
2003-10-16 08:39:28 +00:00

1489 lines
31 KiB
C

/*
* ReactOS kernel
* Copyright (C) 2003 ReactOS Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: infcache.c,v 1.7 2003/10/16 08:39:28 robd Exp $
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS hive maker
* FILE: tools/mkhive/infcache.c
* PURPOSE: INF file parser that caches contents of INF file in memory
* PROGRAMMER: Royce Mitchell III
* Eric Kohl
*/
/* INCLUDES *****************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "mkhive.h"
#include "infcache.h"
#define CONTROL_Z '\x1a'
#define MAX_SECTION_NAME_LEN 255
#define MAX_FIELD_LEN 511 /* larger fields get silently truncated */
/* actual string limit is MAX_INF_STRING_LENGTH+1 (plus terminating null) under Windows */
#define MAX_STRING_LEN (MAX_INF_STRING_LENGTH+1)
typedef struct _INFCACHEFIELD
{
struct _INFCACHEFIELD *Next;
struct _INFCACHEFIELD *Prev;
CHAR Data[1];
} INFCACHEFIELD, *PINFCACHEFIELD;
typedef struct _INFCACHELINE
{
struct _INFCACHELINE *Next;
struct _INFCACHELINE *Prev;
LONG FieldCount;
PCHAR Key;
PINFCACHEFIELD FirstField;
PINFCACHEFIELD LastField;
} INFCACHELINE, *PINFCACHELINE;
typedef struct _INFCACHESECTION
{
struct _INFCACHESECTION *Next;
struct _INFCACHESECTION *Prev;
PINFCACHELINE FirstLine;
PINFCACHELINE LastLine;
LONG LineCount;
CHAR Name[1];
} INFCACHESECTION, *PINFCACHESECTION;
typedef struct _INFCACHE
{
PINFCACHESECTION FirstSection;
PINFCACHESECTION LastSection;
PINFCACHESECTION StringsSection;
} INFCACHE, *PINFCACHE;
/* parser definitions */
enum parser_state
{
LINE_START, /* at beginning of a line */
SECTION_NAME, /* parsing a section name */
KEY_NAME, /* parsing a key name */
VALUE_NAME, /* parsing a value name */
EOL_BACKSLASH, /* backslash at end of line */
QUOTES, /* inside quotes */
LEADING_SPACES, /* leading spaces */
TRAILING_SPACES, /* trailing spaces */
COMMENT, /* inside a comment */
NB_PARSER_STATES
};
struct parser
{
const CHAR *start; /* start position of item being parsed */
const CHAR *end; /* end of buffer */
PINFCACHE file; /* file being built */
enum parser_state state; /* current parser state */
enum parser_state stack[4]; /* state stack */
int stack_pos; /* current pos in stack */
PINFCACHESECTION cur_section; /* pointer to the section being parsed*/
PINFCACHELINE line; /* current line */
unsigned int line_pos; /* current line position in file */
unsigned int error; /* error code */
unsigned int token_len; /* current token len */
CHAR token[MAX_FIELD_LEN+1]; /* current token */
};
typedef const CHAR * (*parser_state_func)( struct parser *parser, const CHAR *pos );
/* parser state machine functions */
static const CHAR *line_start_state( struct parser *parser, const CHAR *pos );
static const CHAR *section_name_state( struct parser *parser, const CHAR *pos );
static const CHAR *key_name_state( struct parser *parser, const CHAR *pos );
static const CHAR *value_name_state( struct parser *parser, const CHAR *pos );
static const CHAR *eol_backslash_state( struct parser *parser, const CHAR *pos );
static const CHAR *quotes_state( struct parser *parser, const CHAR *pos );
static const CHAR *leading_spaces_state( struct parser *parser, const CHAR *pos );
static const CHAR *trailing_spaces_state( struct parser *parser, const CHAR *pos );
static const CHAR *comment_state( struct parser *parser, const CHAR *pos );
static const parser_state_func parser_funcs[NB_PARSER_STATES] =
{
line_start_state, /* LINE_START */
section_name_state, /* SECTION_NAME */
key_name_state, /* KEY_NAME */
value_name_state, /* VALUE_NAME */
eol_backslash_state, /* EOL_BACKSLASH */
quotes_state, /* QUOTES */
leading_spaces_state, /* LEADING_SPACES */
trailing_spaces_state, /* TRAILING_SPACES */
comment_state /* COMMENT */
};
/* PRIVATE FUNCTIONS ********************************************************/
static PINFCACHELINE
InfpCacheFreeLine (PINFCACHELINE Line)
{
PINFCACHELINE Next;
PINFCACHEFIELD Field;
if (Line == NULL)
{
return NULL;
}
Next = Line->Next;
if (Line->Key != NULL)
{
free (Line->Key);
Line->Key = NULL;
}
/* Remove data fields */
while (Line->FirstField != NULL)
{
Field = Line->FirstField->Next;
free (Line->FirstField);
Line->FirstField = Field;
}
Line->LastField = NULL;
free (Line);
return Next;
}
static PINFCACHESECTION
InfpCacheFreeSection (PINFCACHESECTION Section)
{
PINFCACHESECTION Next;
if (Section == NULL)
{
return NULL;
}
/* Release all keys */
Next = Section->Next;
while (Section->FirstLine != NULL)
{
Section->FirstLine = InfpCacheFreeLine (Section->FirstLine);
}
Section->LastLine = NULL;
free (Section);
return Next;
}
static PINFCACHESECTION
InfpCacheFindSection (PINFCACHE Cache,
PCHAR Name)
{
PINFCACHESECTION Section = NULL;
if (Cache == NULL || Name == NULL)
{
return NULL;
}
/* iterate through list of sections */
Section = Cache->FirstSection;
while (Section != NULL)
{
if (strcasecmp (Section->Name, Name) == 0)
{
return Section;
}
/* get the next section*/
Section = Section->Next;
}
return NULL;
}
static PINFCACHESECTION
InfpCacheAddSection (PINFCACHE Cache,
PCHAR Name)
{
PINFCACHESECTION Section = NULL;
ULONG Size;
if (Cache == NULL || Name == NULL)
{
DPRINT ("Invalid parameter\n");
return NULL;
}
/* Allocate and initialize the new section */
Size = sizeof(INFCACHESECTION) + strlen (Name);
Section = (PINFCACHESECTION)malloc (Size);
if (Section == NULL)
{
DPRINT ("RtlAllocateHeap() failed\n");
return NULL;
}
memset (Section, 0, Size);
/* Copy section name */
strcpy (Section->Name, Name);
/* Append section */
if (Cache->FirstSection == NULL)
{
Cache->FirstSection = Section;
Cache->LastSection = Section;
}
else
{
Cache->LastSection->Next = Section;
Section->Prev = Cache->LastSection;
Cache->LastSection = Section;
}
return Section;
}
static PINFCACHELINE
InfpCacheAddLine (PINFCACHESECTION Section)
{
PINFCACHELINE Line;
if (Section == NULL)
{
DPRINT("Invalid parameter\n");
return NULL;
}
Line = (PINFCACHELINE)malloc (sizeof(INFCACHELINE));
if (Line == NULL)
{
DPRINT("RtlAllocateHeap() failed\n");
return NULL;
}
memset (Line, 0, sizeof(INFCACHELINE));
/* Append line */
if (Section->FirstLine == NULL)
{
Section->FirstLine = Line;
Section->LastLine = Line;
}
else
{
Section->LastLine->Next = Line;
Line->Prev = Section->LastLine;
Section->LastLine = Line;
}
Section->LineCount++;
return Line;
}
static PVOID
InfpAddKeyToLine (PINFCACHELINE Line,
PCHAR Key)
{
if (Line == NULL)
return NULL;
if (Line->Key != NULL)
return NULL;
Line->Key = (PCHAR)malloc (strlen (Key) + 1);
if (Line->Key == NULL)
return NULL;
strcpy (Line->Key, Key);
return (PVOID)Line->Key;
}
static PVOID
InfpAddFieldToLine (PINFCACHELINE Line,
PCHAR Data)
{
PINFCACHEFIELD Field;
ULONG Size;
Size = sizeof(INFCACHEFIELD) + strlen(Data);
Field = (PINFCACHEFIELD)malloc (Size);
if (Field == NULL)
{
return NULL;
}
memset (Field, 0, Size);
strcpy (Field->Data, Data);
/* Append key */
if (Line->FirstField == NULL)
{
Line->FirstField = Field;
Line->LastField = Field;
}
else
{
Line->LastField->Next = Field;
Field->Prev = Line->LastField;
Line->LastField = Field;
}
Line->FieldCount++;
return (PVOID)Field;
}
static PINFCACHELINE
InfpCacheFindKeyLine (PINFCACHESECTION Section,
PCHAR Key)
{
PINFCACHELINE Line;
Line = Section->FirstLine;
while (Line != NULL)
{
if (Line->Key != NULL && strcasecmp (Line->Key, Key) == 0)
{
return Line;
}
Line = Line->Next;
}
return NULL;
}
/* push the current state on the parser stack */
inline static void push_state( struct parser *parser, enum parser_state state )
{
// assert( parser->stack_pos < sizeof(parser->stack)/sizeof(parser->stack[0]) );
parser->stack[parser->stack_pos++] = state;
}
/* pop the current state */
inline static void pop_state( struct parser *parser )
{
// assert( parser->stack_pos );
parser->state = parser->stack[--parser->stack_pos];
}
/* set the parser state and return the previous one */
inline static enum parser_state set_state( struct parser *parser, enum parser_state state )
{
enum parser_state ret = parser->state;
parser->state = state;
return ret;
}
/* check if the pointer points to an end of file */
inline static int is_eof( struct parser *parser, const CHAR *ptr )
{
return (ptr >= parser->end || *ptr == CONTROL_Z);
}
/* check if the pointer points to an end of line */
inline static int is_eol( struct parser *parser, const CHAR *ptr )
{
return (ptr >= parser->end ||
*ptr == CONTROL_Z ||
*ptr == '\n' ||
(*ptr == '\r' && *(ptr + 1) == '\n'));
}
/* push data from current token start up to pos into the current token */
static int push_token( struct parser *parser, const CHAR *pos )
{
int len = pos - parser->start;
const CHAR *src = parser->start;
CHAR *dst = parser->token + parser->token_len;
if (len > MAX_FIELD_LEN - parser->token_len)
len = MAX_FIELD_LEN - parser->token_len;
parser->token_len += len;
for ( ; len > 0; len--, dst++, src++)
*dst = *src ? *src : ' ';
*dst = 0;
parser->start = pos;
return 0;
}
/* add a section with the current token as name */
static PVOID add_section_from_token( struct parser *parser )
{
PINFCACHESECTION Section;
if (parser->token_len > MAX_SECTION_NAME_LEN)
{
parser->error = STATUS_SECTION_NAME_TOO_LONG;
return NULL;
}
Section = InfpCacheFindSection (parser->file,
parser->token);
if (Section == NULL)
{
/* need to create a new one */
Section= InfpCacheAddSection (parser->file,
parser->token);
if (Section == NULL)
{
parser->error = STATUS_NOT_ENOUGH_MEMORY;
return NULL;
}
}
parser->token_len = 0;
parser->cur_section = Section;
return (PVOID)Section;
}
/* add a field containing the current token to the current line */
static struct field *add_field_from_token( struct parser *parser, int is_key )
{
PVOID field;
CHAR *text;
if (!parser->line) /* need to start a new line */
{
if (parser->cur_section == NULL) /* got a line before the first section */
{
parser->error = STATUS_WRONG_INF_STYLE;
return NULL;
}
parser->line = InfpCacheAddLine (parser->cur_section);
if (parser->line == NULL)
goto error;
}
else
{
// assert(!is_key);
}
if (is_key)
{
field = InfpAddKeyToLine(parser->line, parser->token);
}
else
{
field = InfpAddFieldToLine(parser->line, parser->token);
}
if (field != NULL)
{
parser->token_len = 0;
return field;
}
error:
parser->error = STATUS_NOT_ENOUGH_MEMORY;
return NULL;
}
/* close the current line and prepare for parsing a new one */
static void close_current_line( struct parser *parser )
{
parser->line = NULL;
}
/* handler for parser LINE_START state */
static const CHAR *line_start_state( struct parser *parser, const CHAR *pos )
{
const CHAR *p;
for (p = pos; !is_eof( parser, p ); p++)
{
switch(*p)
{
case '\r':
continue;
case '\n':
parser->line_pos++;
close_current_line( parser );
break;
case ';':
push_state( parser, LINE_START );
set_state( parser, COMMENT );
return p + 1;
case '[':
parser->start = p + 1;
set_state( parser, SECTION_NAME );
return p + 1;
default:
if (!isspace(*p))
{
parser->start = p;
set_state( parser, KEY_NAME );
return p;
}
break;
}
}
close_current_line( parser );
return NULL;
}
/* handler for parser SECTION_NAME state */
static const CHAR *section_name_state( struct parser *parser, const CHAR *pos )
{
const CHAR *p;
for (p = pos; !is_eol( parser, p ); p++)
{
if (*p == ']')
{
push_token( parser, p );
if (add_section_from_token( parser ) == NULL)
return NULL;
push_state( parser, LINE_START );
set_state( parser, COMMENT ); /* ignore everything else on the line */
return p + 1;
}
}
parser->error = STATUS_BAD_SECTION_NAME_LINE; /* unfinished section name */
return NULL;
}
/* handler for parser KEY_NAME state */
static const CHAR *key_name_state( struct parser *parser, const CHAR *pos )
{
const CHAR *p, *token_end = parser->start;
for (p = pos; !is_eol( parser, p ); p++)
{
if (*p == ',') break;
switch(*p)
{
case '=':
push_token( parser, token_end );
if (!add_field_from_token( parser, 1 )) return NULL;
parser->start = p + 1;
push_state( parser, VALUE_NAME );
set_state( parser, LEADING_SPACES );
return p + 1;
case ';':
push_token( parser, token_end );
if (!add_field_from_token( parser, 0 )) return NULL;
push_state( parser, LINE_START );
set_state( parser, COMMENT );
return p + 1;
case '"':
push_token( parser, token_end );
parser->start = p + 1;
push_state( parser, KEY_NAME );
set_state( parser, QUOTES );
return p + 1;
case '\\':
push_token( parser, token_end );
parser->start = p;
push_state( parser, KEY_NAME );
set_state( parser, EOL_BACKSLASH );
return p;
default:
if (!isspace(*p)) token_end = p + 1;
else
{
push_token( parser, p );
push_state( parser, KEY_NAME );
set_state( parser, TRAILING_SPACES );
return p;
}
break;
}
}
push_token( parser, token_end );
set_state( parser, VALUE_NAME );
return p;
}
/* handler for parser VALUE_NAME state */
static const CHAR *value_name_state( struct parser *parser, const CHAR *pos )
{
const CHAR *p, *token_end = parser->start;
for (p = pos; !is_eol( parser, p ); p++)
{
switch(*p)
{
case ';':
push_token( parser, token_end );
if (!add_field_from_token( parser, 0 )) return NULL;
push_state( parser, LINE_START );
set_state( parser, COMMENT );
return p + 1;
case ',':
push_token( parser, token_end );
if (!add_field_from_token( parser, 0 )) return NULL;
parser->start = p + 1;
push_state( parser, VALUE_NAME );
set_state( parser, LEADING_SPACES );
return p + 1;
case '"':
push_token( parser, token_end );
parser->start = p + 1;
push_state( parser, VALUE_NAME );
set_state( parser, QUOTES );
return p + 1;
case '\\':
push_token( parser, token_end );
parser->start = p;
push_state( parser, VALUE_NAME );
set_state( parser, EOL_BACKSLASH );
return p;
default:
if (!isspace(*p)) token_end = p + 1;
else
{
push_token( parser, p );
push_state( parser, VALUE_NAME );
set_state( parser, TRAILING_SPACES );
return p;
}
break;
}
}
push_token( parser, token_end );
if (!add_field_from_token( parser, 0 )) return NULL;
set_state( parser, LINE_START );
return p;
}
/* handler for parser EOL_BACKSLASH state */
static const CHAR *eol_backslash_state( struct parser *parser, const CHAR *pos )
{
const CHAR *p;
for (p = pos; !is_eof( parser, p ); p++)
{
switch(*p)
{
case '\r':
continue;
case '\n':
parser->line_pos++;
parser->start = p + 1;
set_state( parser, LEADING_SPACES );
return p + 1;
case '\\':
continue;
case ';':
push_state( parser, EOL_BACKSLASH );
set_state( parser, COMMENT );
return p + 1;
default:
if (isspace(*p))
continue;
push_token( parser, p );
pop_state( parser );
return p;
}
}
parser->start = p;
pop_state( parser );
return p;
}
/* handler for parser QUOTES state */
static const CHAR *quotes_state( struct parser *parser, const CHAR *pos )
{
const CHAR *p, *token_end = parser->start;
for (p = pos; !is_eol( parser, p ); p++)
{
if (*p == '"')
{
if (p+1 < parser->end && p[1] == '"') /* double quotes */
{
push_token( parser, p + 1 );
parser->start = token_end = p + 2;
p++;
}
else /* end of quotes */
{
push_token( parser, p );
parser->start = p + 1;
pop_state( parser );
return p + 1;
}
}
}
push_token( parser, p );
pop_state( parser );
return p;
}
/* handler for parser LEADING_SPACES state */
static const CHAR *leading_spaces_state( struct parser *parser, const CHAR *pos )
{
const CHAR *p;
for (p = pos; !is_eol( parser, p ); p++)
{
if (*p == '\\')
{
parser->start = p;
set_state( parser, EOL_BACKSLASH );
return p;
}
if (!isspace(*p))
break;
}
parser->start = p;
pop_state( parser );
return p;
}
/* handler for parser TRAILING_SPACES state */
static const CHAR *trailing_spaces_state( struct parser *parser, const CHAR *pos )
{
const CHAR *p;
for (p = pos; !is_eol( parser, p ); p++)
{
if (*p == '\\')
{
set_state( parser, EOL_BACKSLASH );
return p;
}
if (!isspace(*p))
break;
}
pop_state( parser );
return p;
}
/* handler for parser COMMENT state */
static const CHAR *comment_state( struct parser *parser, const CHAR *pos )
{
const CHAR *p = pos;
while (!is_eol( parser, p ))
p++;
pop_state( parser );
return p;
}
/* parse a complete buffer */
static BOOL
InfpParseBuffer (PINFCACHE file,
const CHAR *buffer,
const CHAR *end,
PULONG error_line)
{
struct parser parser;
const CHAR *pos = buffer;
parser.start = buffer;
parser.end = end;
parser.file = file;
parser.line = NULL;
parser.state = LINE_START;
parser.stack_pos = 0;
parser.cur_section = NULL;
parser.line_pos = 1;
parser.error = 0;
parser.token_len = 0;
/* parser main loop */
while (pos)
pos = (parser_funcs[parser.state])(&parser, pos);
if (parser.error)
{
if (error_line)
*error_line = parser.line_pos;
return parser.error;
}
/* find the [strings] section */
file->StringsSection = InfpCacheFindSection (file,
"Strings");
return TRUE;
}
/* PUBLIC FUNCTIONS *********************************************************/
BOOL
InfOpenFile(PHINF InfHandle,
PCHAR FileName,
PULONG ErrorLine)
{
FILE *File;
PCHAR FileBuffer;
ULONG FileLength;
PINFCACHE Cache;
*InfHandle = NULL;
*ErrorLine = (ULONG)-1;
/* Open the inf file */
File = fopen (FileName, "rb");
if (File == NULL)
{
DPRINT("fopen() failed\n");
return FALSE;
}
DPRINT("fopen() successful\n");
/* Query file size */
fseek (File, 0, SEEK_END);
FileLength = ftell (File);
fseek (File, 0, SEEK_SET);
DPRINT("File size: %lu\n", FileLength);
/* Allocate file buffer */
FileBuffer = malloc (FileLength + 1);
if (FileBuffer == NULL)
{
DPRINT1("malloc() failed\n");
fclose (File);
return FALSE;
}
/* Read file */
if (fread (FileBuffer, FileLength, 1, File) < 0)
{
DPRINT ("fread() failed\n");
fclose (File);
free (FileBuffer);
return FALSE;
}
fclose (File);
/* Append string terminator */
FileBuffer[FileLength] = 0;
/* Allocate infcache header */
Cache = (PINFCACHE)malloc (sizeof(INFCACHE));
if (Cache == NULL)
{
DPRINT("malloc() failed\n");
free (FileBuffer);
return FALSE;
}
/* Initialize inicache header */
memset (Cache, 0, sizeof(INFCACHE));
/* Parse the inf buffer */
if (!InfpParseBuffer (Cache,
FileBuffer,
FileBuffer + FileLength,
ErrorLine))
{
free (Cache);
free (FileBuffer);
return FALSE;
}
/* Free file buffer */
free (FileBuffer);
*InfHandle = (HINF)Cache;
return TRUE;
}
VOID
InfCloseFile(HINF InfHandle)
{
PINFCACHE Cache;
Cache = (PINFCACHE)InfHandle;
if (Cache == NULL)
{
return;
}
while (Cache->FirstSection != NULL)
{
Cache->FirstSection = InfpCacheFreeSection(Cache->FirstSection);
}
Cache->LastSection = NULL;
free (Cache);
}
BOOL
InfFindFirstLine (HINF InfHandle,
PCHAR Section,
PCHAR Key,
PINFCONTEXT Context)
{
PINFCACHE Cache;
PINFCACHESECTION CacheSection;
PINFCACHELINE CacheLine;
if (InfHandle == NULL || Section == NULL || Context == NULL)
{
DPRINT("Invalid parameter\n");
return FALSE;
}
Cache = (PINFCACHE)InfHandle;
/* Iterate through list of sections */
CacheSection = Cache->FirstSection;
while (CacheSection != NULL)
{
DPRINT("Comparing '%s' and '%s'\n", CacheSection->Name, Section);
/* Are the section names the same? */
if (strcasecmp(CacheSection->Name, Section) == 0)
{
if (Key != NULL)
{
CacheLine = InfpCacheFindKeyLine (CacheSection, (PCHAR)Key);
}
else
{
CacheLine = CacheSection->FirstLine;
}
if (CacheLine == NULL)
return FALSE;
Context->Inf = (PVOID)Cache;
Context->Section = (PVOID)CacheSection;
Context->Line = (PVOID)CacheLine;
return TRUE;
}
/* Get the next section */
CacheSection = CacheSection->Next;
}
DPRINT("Section not found\n");
return FALSE;
}
BOOL
InfFindNextLine (PINFCONTEXT ContextIn,
PINFCONTEXT ContextOut)
{
PINFCACHELINE CacheLine;
if (ContextIn == NULL || ContextOut == NULL)
return FALSE;
if (ContextIn->Line == NULL)
return FALSE;
CacheLine = (PINFCACHELINE)ContextIn->Line;
if (CacheLine->Next == NULL)
return FALSE;
if (ContextIn != ContextOut)
{
ContextOut->Inf = ContextIn->Inf;
ContextOut->Section = ContextIn->Section;
}
ContextOut->Line = (PVOID)(CacheLine->Next);
return TRUE;
}
BOOL
InfFindFirstMatchLine (PINFCONTEXT ContextIn,
PCHAR Key,
PINFCONTEXT ContextOut)
{
PINFCACHELINE CacheLine;
if (ContextIn == NULL || ContextOut == NULL || Key == NULL || *Key == 0)
return FALSE;
if (ContextIn->Inf == NULL || ContextIn->Section == NULL)
return FALSE;
CacheLine = ((PINFCACHESECTION)(ContextIn->Section))->FirstLine;
while (CacheLine != NULL)
{
if (CacheLine->Key != NULL && strcasecmp (CacheLine->Key, Key) == 0)
{
if (ContextIn != ContextOut)
{
ContextOut->Inf = ContextIn->Inf;
ContextOut->Section = ContextIn->Section;
}
ContextOut->Line = (PVOID)CacheLine;
return TRUE;
}
CacheLine = CacheLine->Next;
}
return FALSE;
}
BOOL
InfFindNextMatchLine (PINFCONTEXT ContextIn,
PCHAR Key,
PINFCONTEXT ContextOut)
{
PINFCACHELINE CacheLine;
if (ContextIn == NULL || ContextOut == NULL || Key == NULL || *Key == 0)
return FALSE;
if (ContextIn->Inf == NULL || ContextIn->Section == NULL || ContextIn->Line == NULL)
return FALSE;
CacheLine = (PINFCACHELINE)ContextIn->Line;
while (CacheLine != NULL)
{
if (CacheLine->Key != NULL && strcasecmp (CacheLine->Key, Key) == 0)
{
if (ContextIn != ContextOut)
{
ContextOut->Inf = ContextIn->Inf;
ContextOut->Section = ContextIn->Section;
}
ContextOut->Line = (PVOID)CacheLine;
return TRUE;
}
CacheLine = CacheLine->Next;
}
return FALSE;
}
LONG
InfGetLineCount(HINF InfHandle,
PCHAR Section)
{
PINFCACHE Cache;
PINFCACHESECTION CacheSection;
if (InfHandle == NULL || Section == NULL)
{
DPRINT("Invalid parameter\n");
return -1;
}
Cache = (PINFCACHE)InfHandle;
/* Iterate through list of sections */
CacheSection = Cache->FirstSection;
while (Section != NULL)
{
DPRINT("Comparing '%s' and '%s'\n", CacheSection->Name, Section);
/* Are the section names the same? */
if (strcasecmp(CacheSection->Name, Section) == 0)
{
return CacheSection->LineCount;
}
/* Get the next section */
CacheSection = CacheSection->Next;
}
DPRINT("Section not found\n");
return -1;
}
/* InfGetLineText */
LONG
InfGetFieldCount(PINFCONTEXT Context)
{
if (Context == NULL || Context->Line == NULL)
return 0;
return ((PINFCACHELINE)Context->Line)->FieldCount;
}
BOOL
InfGetBinaryField (PINFCONTEXT Context,
ULONG FieldIndex,
PUCHAR ReturnBuffer,
ULONG ReturnBufferSize,
PULONG RequiredSize)
{
PINFCACHELINE CacheLine;
PINFCACHEFIELD CacheField;
ULONG Index;
ULONG Size;
PUCHAR Ptr;
if (Context == NULL || Context->Line == NULL || FieldIndex == 0)
{
DPRINT("Invalid parameter\n");
return FALSE;
}
if (RequiredSize != NULL)
*RequiredSize = 0;
CacheLine = (PINFCACHELINE)Context->Line;
if (FieldIndex > CacheLine->FieldCount)
return FALSE;
CacheField = CacheLine->FirstField;
for (Index = 1; Index < FieldIndex; Index++)
CacheField = CacheField->Next;
Size = CacheLine->FieldCount - FieldIndex + 1;
if (RequiredSize != NULL)
*RequiredSize = Size;
if (ReturnBuffer != NULL)
{
if (ReturnBufferSize < Size)
return FALSE;
/* Copy binary data */
Ptr = ReturnBuffer;
while (CacheField != NULL)
{
*Ptr = (UCHAR)strtoul (CacheField->Data, NULL, 16);
Ptr++;
CacheField = CacheField->Next;
}
}
return TRUE;
}
BOOL
InfGetIntField (PINFCONTEXT Context,
ULONG FieldIndex,
PLONG IntegerValue)
{
PINFCACHELINE CacheLine;
PINFCACHEFIELD CacheField;
ULONG Index;
PCHAR Ptr;
if (Context == NULL || Context->Line == NULL || IntegerValue == NULL)
{
DPRINT("Invalid parameter\n");
return FALSE;
}
CacheLine = (PINFCACHELINE)Context->Line;
if (FieldIndex > CacheLine->FieldCount)
{
DPRINT("Invalid parameter\n");
return FALSE;
}
if (FieldIndex == 0)
{
Ptr = CacheLine->Key;
}
else
{
CacheField = CacheLine->FirstField;
for (Index = 1; Index < FieldIndex; Index++)
CacheField = CacheField->Next;
Ptr = CacheField->Data;
}
*IntegerValue = strtol (Ptr, NULL, 0);
return TRUE;
}
BOOL
InfGetMultiSzField (PINFCONTEXT Context,
ULONG FieldIndex,
PCHAR ReturnBuffer,
ULONG ReturnBufferSize,
PULONG RequiredSize)
{
PINFCACHELINE CacheLine;
PINFCACHEFIELD CacheField;
PINFCACHEFIELD FieldPtr;
ULONG Index;
ULONG Size;
PCHAR Ptr;
if (Context == NULL || Context->Line == NULL || FieldIndex == 0)
{
DPRINT("Invalid parameter\n");
return FALSE;
}
if (RequiredSize != NULL)
*RequiredSize = 0;
CacheLine = (PINFCACHELINE)Context->Line;
if (FieldIndex > CacheLine->FieldCount)
return FALSE;
CacheField = CacheLine->FirstField;
for (Index = 1; Index < FieldIndex; Index++)
CacheField = CacheField->Next;
/* Calculate the required buffer size */
FieldPtr = CacheField;
Size = 0;
while (FieldPtr != NULL)
{
Size += (strlen (FieldPtr->Data) + 1);
FieldPtr = FieldPtr->Next;
}
Size++;
if (RequiredSize != NULL)
*RequiredSize = Size;
if (ReturnBuffer != NULL)
{
if (ReturnBufferSize < Size)
return FALSE;
/* Copy multi-sz string */
Ptr = ReturnBuffer;
FieldPtr = CacheField;
while (FieldPtr != NULL)
{
Size = strlen (FieldPtr->Data) + 1;
strcpy (Ptr, FieldPtr->Data);
Ptr = Ptr + Size;
FieldPtr = FieldPtr->Next;
}
*Ptr = 0;
}
return TRUE;
}
BOOL
InfGetStringField (PINFCONTEXT Context,
ULONG FieldIndex,
PCHAR ReturnBuffer,
ULONG ReturnBufferSize,
PULONG RequiredSize)
{
PINFCACHELINE CacheLine;
PINFCACHEFIELD CacheField;
ULONG Index;
PCHAR Ptr;
ULONG Size;
if (Context == NULL || Context->Line == NULL || FieldIndex == 0)
{
DPRINT("Invalid parameter\n");
return FALSE;
}
if (RequiredSize != NULL)
*RequiredSize = 0;
CacheLine = (PINFCACHELINE)Context->Line;
if (FieldIndex > CacheLine->FieldCount)
return FALSE;
if (FieldIndex == 0)
{
Ptr = CacheLine->Key;
}
else
{
CacheField = CacheLine->FirstField;
for (Index = 1; Index < FieldIndex; Index++)
CacheField = CacheField->Next;
Ptr = CacheField->Data;
}
Size = strlen (Ptr) + 1;
if (RequiredSize != NULL)
*RequiredSize = Size;
if (ReturnBuffer != NULL)
{
if (ReturnBufferSize < Size)
return FALSE;
strcpy (ReturnBuffer, Ptr);
}
return TRUE;
}
BOOL
InfGetData (PINFCONTEXT Context,
PCHAR *Key,
PCHAR *Data)
{
PINFCACHELINE CacheKey;
if (Context == NULL || Context->Line == NULL || Data == NULL)
{
DPRINT("Invalid parameter\n");
return FALSE;
}
CacheKey = (PINFCACHELINE)Context->Line;
if (Key != NULL)
*Key = CacheKey->Key;
if (Data != NULL)
{
if (CacheKey->FirstField == NULL)
{
*Data = NULL;
}
else
{
*Data = CacheKey->FirstField->Data;
}
}
return TRUE;
}
BOOL
InfGetDataField (PINFCONTEXT Context,
ULONG FieldIndex,
PCHAR *Data)
{
PINFCACHELINE CacheLine;
PINFCACHEFIELD CacheField;
ULONG Index;
if (Context == NULL || Context->Line == NULL || Data == NULL)
{
DPRINT("Invalid parameter\n");
return FALSE;
}
CacheLine = (PINFCACHELINE)Context->Line;
if (FieldIndex > CacheLine->FieldCount)
return FALSE;
if (FieldIndex == 0)
{
*Data = CacheLine->Key;
}
else
{
CacheField = CacheLine->FirstField;
for (Index = 1; Index < FieldIndex; Index++)
CacheField = CacheField->Next;
*Data = CacheField->Data;
}
return TRUE;
}
/* EOF */