- Factor out .inf handling code from usetup

- Provide a dual interface, for use in build tools and for use in ReactOS code

svn path=/trunk/; revision=19516
This commit is contained in:
Gé van Geldorp 2005-11-24 08:07:12 +00:00
parent 59a50a6f88
commit 1c781d1933
17 changed files with 2670 additions and 0 deletions

View file

@ -119,6 +119,9 @@
<directory name="imm32">
<xi:include href="imm32/imm32.xml" />
</directory>
<directory name="inflib">
<xi:include href="inflib/inflib.xml" />
</directory>
<directory name="intrlck">
<xi:include href="intrlck/intrlck.xml" />
</directory>

View file

@ -0,0 +1,14 @@
Routines to handle .inf files.
This library is used to share .inf handling code between build tools and
ReactOS code. Two versions are built, "inflib_host" (for use by build tools)
and "inflib" (for use by ReactOS code). Both depend on the same core source,
with a wrapper for the appropriate interface.
Most of the differences between the host and the ReactOS environment are
abstracted away in builddep.h. Of particular note is that the host version
uses Ansi characters while the ReactOS version uses Unicode. So, the core
source uses TCHARs. builddep.h depends on a preprocessor variable INFLIB_HOST
which is defined when building the host version (inflib.mak) but not defined
when building the ReactOS version (inflib.xml).
The wrappers have "host" or "ros" in their filename. The library interface is
"infhost.h" for the host version, "infros.h" for the ReactOS version.

View file

@ -0,0 +1,75 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: .inf file parser
* FILE: lib/inflib/builddep.h
* PURPOSE: Build dependent definitions
* PROGRAMMER: Ge van Geldorp <gvg@reactos.org>
*/
#ifdef INFLIB_HOST
/* Definitions native to the host on which we're building */
#include <string.h>
#include <errno.h>
#define FREE(Area) free(Area)
#define MALLOC(Size) malloc(Size)
#define ZEROMEMORY(Area, Size) memset((Area), '\0', (Size))
#define MEMCPY(Dest, Src, Size) memcpy((Dest), (Src), (Size))
#define INF_STATUS_SUCCESS 0
#define INF_STATUS_NO_MEMORY ENOMEM
#define INF_STATUS_INVALID_PARAMETER EINVAL
#define INF_STATUS_NOT_FOUND ENOENT
#define INF_STATUS_BUFFER_OVERFLOW E2BIG
#define INF_SUCCESS(x) (0 == (x))
typedef char CHAR, *PCHAR;
typedef unsigned char UCHAR, *PUCHAR;
typedef long LONG, *PLONG;
typedef unsigned long ULONG, *PULONG;
typedef void VOID, *PVOID;
typedef UCHAR BOOLEAN, *PBOOLEAN;
typedef char TCHAR, *PTCHAR, *PTSTR;
#define _T(x) x
#define _tcsicmp strcasecmp
#define _tcslen strlen
#define _tcscpy strcpy
#define _tcstoul strtoul
#define _tcstol strtol
extern void DbgPrint(const char *Fmt, ...);
#else /* ! defined(INFLIB_HOST) */
/* ReactOS definitions */
#define UNICODE
#define _UNICODE
#include <tchar.h>
#define WIN32_NO_STATUS
#include <windows.h>
#define NTOS_MODE_USER
#include <ndk/ntndk.h>
extern PVOID InfpHeap;
#define FREE(Area) RtlFreeHeap(InfpHeap, 0, (Area))
#define MALLOC(Size) RtlAllocateHeap(InfpHeap, 0, (Size))
#define ZEROMEMORY(Area, Size) RtlZeroMemory((Area), (Size))
#define MEMCPY(Dest, Src, Size) RtlCopyMemory((Dest), (Src), (Size))
#define INF_STATUS_SUCCESS STATUS_SUCCESS
#define INF_STATUS_NO_MEMORY STATUS_NO_MEMORY
#define INF_STATUS_INVALID_PARAMETER STATUS_INVALID_PARAMETER
#define INF_STATUS_NOT_FOUND STATUS_NOT_FOUND
#define INF_STATUS_BUFFER_OVERFLOW STATUS_BUFFER_OVERFLOW
#define INF_SUCCESS(x) (0 <= (x))
#endif /* INFLIB_HOST */
typedef const TCHAR *PCTSTR;
/* EOF */

View file

@ -0,0 +1,21 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: .inf file parser
* FILE: lib/inflib/infcommon.h
* PURPOSE: Public .inf routines
* PROGRAMMER: Royce Mitchell III
* Eric Kohl
* Ge van Geldorp
*/
#ifndef INFCOMMON_H_INCLUDED
#define INFCOMMON_H_INCLUDED
#define MAX_INF_STRING_LENGTH 512
typedef void *HINF, **PHINF;
typedef struct _INFCONTEXT *PINFCONTEXT;
#endif /* INFCOMMON_H_INCLUDED */
/* EOF */

View file

@ -0,0 +1,811 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: .inf file parser
* FILE: lib/inflib/infcore.c
* PURPOSE: INF file parser that caches contents of INF file in memory
* PROGRAMMER: Royce Mitchell III
* Eric Kohl
* Ge van Geldorp
*/
/* INCLUDES *****************************************************************/
#include "inflib.h"
#define NDEBUG
#include <debug.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)
/* 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 */
TCHAR 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;
}
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,
PCTSTR Name)
{
PINFCACHESECTION Section = NULL;
if (Cache == NULL || Name == NULL)
{
return NULL;
}
/* iterate through list of sections */
Section = Cache->FirstSection;
while (Section != NULL)
{
if (_tcsicmp (Section->Name, Name) == 0)
{
return Section;
}
/* get the next section*/
Section = Section->Next;
}
return NULL;
}
static PINFCACHESECTION
InfpCacheAddSection (PINFCACHE Cache,
PTCHAR 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) + (_tcslen (Name) * sizeof(TCHAR));
Section = (PINFCACHESECTION)MALLOC (Size);
if (Section == NULL)
{
DPRINT("MALLOC() failed\n");
return NULL;
}
ZEROMEMORY (Section,
Size);
/* Copy section name */
_tcscpy (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("MALLOC() failed\n");
return NULL;
}
ZEROMEMORY(Line,
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,
PTCHAR Key)
{
if (Line == NULL)
return NULL;
if (Line->Key != NULL)
return NULL;
Line->Key = (PTCHAR)MALLOC ((_tcslen (Key) + 1) * sizeof(TCHAR));
if (Line->Key == NULL)
return NULL;
_tcscpy (Line->Key, Key);
return (PVOID)Line->Key;
}
static PVOID
InfpAddFieldToLine (PINFCACHELINE Line,
PTCHAR Data)
{
PINFCACHEFIELD Field;
ULONG Size;
Size = sizeof(INFCACHEFIELD) + (_tcslen(Data) * sizeof(TCHAR));
Field = (PINFCACHEFIELD)MALLOC (Size);
if (Field == NULL)
{
return NULL;
}
ZEROMEMORY (Field,
Size);
_tcscpy (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;
}
PINFCACHELINE
InfpCacheFindKeyLine (PINFCACHESECTION Section,
PTCHAR Key)
{
PINFCACHELINE Line;
Line = Section->FirstLine;
while (Line != NULL)
{
if (Line->Key != NULL && _tcsicmp (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 )
{
unsigned int len = pos - parser->start;
const CHAR *src = parser->start;
TCHAR *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 ? (TCHAR)*src : L' ';
*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 = INF_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 = INF_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;
if (!parser->line) /* need to start a new line */
{
if (parser->cur_section == NULL) /* got a line before the first section */
{
parser->error = INF_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 = INF_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 = INF_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 */
INFSTATUS
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,
_T("Strings"));
return INF_STATUS_SUCCESS;
}
/* EOF */

529
reactos/lib/inflib/infget.c Normal file
View file

@ -0,0 +1,529 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: .inf file parser
* FILE: lib/inflib/infrosget.c
* PURPOSE: Read .inf routines for use in ReactOS
* PROGRAMMER: Royce Mitchell III
* Eric Kohl
* Ge van Geldorp
*/
/* INCLUDES *****************************************************************/
#include "inflib.h"
#define NDEBUG
#include <debug.h>
INFSTATUS
InfpFindFirstLine(HINF InfHandle,
PCTSTR Section,
PCTSTR Key,
PINFCONTEXT *Context)
{
PINFCACHE Cache;
PINFCACHESECTION CacheSection;
PINFCACHELINE CacheLine;
if (InfHandle == NULL || Section == NULL || Context == NULL)
{
DPRINT("Invalid parameter\n");
return INF_STATUS_INVALID_PARAMETER;
}
*Context = MALLOC(sizeof(INFCONTEXT));
if (NULL == *Context)
{
DPRINT1("MALLOC() failed\n");
return INF_STATUS_NO_MEMORY;
}
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 (_tcsicmp(CacheSection->Name, Section) == 0)
{
if (Key != NULL)
{
CacheLine = InfpCacheFindKeyLine (CacheSection, (PTCHAR)Key);
}
else
{
CacheLine = CacheSection->FirstLine;
}
if (CacheLine == NULL)
return INF_STATUS_NOT_FOUND;
(*Context)->Inf = (PVOID)Cache;
(*Context)->Section = (PVOID)CacheSection;
(*Context)->Line = (PVOID)CacheLine;
return INF_STATUS_SUCCESS;
}
/* Get the next section */
CacheSection = CacheSection->Next;
}
DPRINT("Section not found\n");
return INF_STATUS_NOT_FOUND;
}
INFSTATUS
InfpFindNextLine(PINFCONTEXT ContextIn,
PINFCONTEXT ContextOut)
{
PINFCACHELINE CacheLine;
if (ContextIn == NULL || ContextOut == NULL)
return INF_STATUS_INVALID_PARAMETER;
if (ContextIn->Line == NULL)
return INF_STATUS_INVALID_PARAMETER;
CacheLine = (PINFCACHELINE)ContextIn->Line;
if (CacheLine->Next == NULL)
return INF_STATUS_NOT_FOUND;
if (ContextIn != ContextOut)
{
ContextOut->Inf = ContextIn->Inf;
ContextOut->Section = ContextIn->Section;
}
ContextOut->Line = (PVOID)(CacheLine->Next);
return INF_STATUS_SUCCESS;
}
INFSTATUS
InfpFindFirstMatchLine(PINFCONTEXT ContextIn,
PCTSTR Key,
PINFCONTEXT ContextOut)
{
PINFCACHELINE CacheLine;
if (ContextIn == NULL || ContextOut == NULL || Key == NULL || *Key == 0)
return INF_STATUS_INVALID_PARAMETER;
if (ContextIn->Inf == NULL || ContextIn->Section == NULL)
return INF_STATUS_INVALID_PARAMETER;
CacheLine = ((PINFCACHESECTION)(ContextIn->Section))->FirstLine;
while (CacheLine != NULL)
{
if (CacheLine->Key != NULL && _tcsicmp (CacheLine->Key, Key) == 0)
{
if (ContextIn != ContextOut)
{
ContextOut->Inf = ContextIn->Inf;
ContextOut->Section = ContextIn->Section;
}
ContextOut->Line = (PVOID)CacheLine;
return INF_STATUS_SUCCESS;
}
CacheLine = CacheLine->Next;
}
return INF_STATUS_NOT_FOUND;
}
INFSTATUS
InfpFindNextMatchLine(PINFCONTEXT ContextIn,
PCTSTR Key,
PINFCONTEXT ContextOut)
{
PINFCACHELINE CacheLine;
if (ContextIn == NULL || ContextOut == NULL || Key == NULL || *Key == 0)
return INF_STATUS_INVALID_PARAMETER;
if (ContextIn->Inf == NULL || ContextIn->Section == NULL || ContextIn->Line == NULL)
return INF_STATUS_INVALID_PARAMETER;
CacheLine = (PINFCACHELINE)ContextIn->Line;
while (CacheLine != NULL)
{
if (CacheLine->Key != NULL && _tcsicmp (CacheLine->Key, Key) == 0)
{
if (ContextIn != ContextOut)
{
ContextOut->Inf = ContextIn->Inf;
ContextOut->Section = ContextIn->Section;
}
ContextOut->Line = (PVOID)CacheLine;
return INF_STATUS_SUCCESS;
}
CacheLine = CacheLine->Next;
}
return INF_STATUS_NOT_FOUND;
}
LONG
InfpGetLineCount(HINF InfHandle,
PCTSTR 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 (CacheSection != NULL)
{
/* Are the section names the same? */
if (_tcsicmp(CacheSection->Name, Section) == 0)
{
return CacheSection->LineCount;
}
/* Get the next section */
CacheSection = CacheSection->Next;
}
DPRINT("Section not found\n");
return -1;
}
/* InfpGetLineText */
LONG
InfpGetFieldCount(PINFCONTEXT Context)
{
if (Context == NULL || Context->Line == NULL)
return 0;
return ((PINFCACHELINE)Context->Line)->FieldCount;
}
INFSTATUS
InfpGetBinaryField(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 INF_STATUS_INVALID_PARAMETER;
}
if (RequiredSize != NULL)
*RequiredSize = 0;
CacheLine = (PINFCACHELINE)Context->Line;
if (FieldIndex > (ULONG)CacheLine->FieldCount)
return INF_STATUS_NOT_FOUND;
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 INF_STATUS_BUFFER_OVERFLOW;
/* Copy binary data */
Ptr = ReturnBuffer;
while (CacheField != NULL)
{
*Ptr = (UCHAR)_tcstoul (CacheField->Data, NULL, 16);
Ptr++;
CacheField = CacheField->Next;
}
}
return INF_STATUS_SUCCESS;
}
INFSTATUS
InfpGetIntField(PINFCONTEXT Context,
ULONG FieldIndex,
PLONG IntegerValue)
{
PINFCACHELINE CacheLine;
PINFCACHEFIELD CacheField;
ULONG Index;
PTCHAR Ptr;
if (Context == NULL || Context->Line == NULL || IntegerValue == NULL)
{
DPRINT("Invalid parameter\n");
return INF_STATUS_INVALID_PARAMETER;
}
CacheLine = (PINFCACHELINE)Context->Line;
if (FieldIndex > (ULONG)CacheLine->FieldCount)
{
DPRINT("Invalid parameter\n");
return INF_STATUS_INVALID_PARAMETER;
}
if (FieldIndex == 0)
{
Ptr = CacheLine->Key;
}
else
{
CacheField = CacheLine->FirstField;
for (Index = 1; Index < FieldIndex; Index++)
CacheField = CacheField->Next;
Ptr = CacheField->Data;
}
*IntegerValue = _tcstol(Ptr, NULL, 0);
return INF_STATUS_SUCCESS;
}
INFSTATUS
InfpGetMultiSzField(PINFCONTEXT Context,
ULONG FieldIndex,
PTSTR ReturnBuffer,
ULONG ReturnBufferSize,
PULONG RequiredSize)
{
PINFCACHELINE CacheLine;
PINFCACHEFIELD CacheField;
PINFCACHEFIELD FieldPtr;
ULONG Index;
ULONG Size;
PTCHAR Ptr;
if (Context == NULL || Context->Line == NULL || FieldIndex == 0)
{
DPRINT("Invalid parameter\n");
return INF_STATUS_INVALID_PARAMETER;
}
if (RequiredSize != NULL)
*RequiredSize = 0;
CacheLine = (PINFCACHELINE)Context->Line;
if (FieldIndex > (ULONG)CacheLine->FieldCount)
return INF_STATUS_INVALID_PARAMETER;
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 += (_tcslen (FieldPtr->Data) + 1);
FieldPtr = FieldPtr->Next;
}
Size++;
if (RequiredSize != NULL)
*RequiredSize = Size;
if (ReturnBuffer != NULL)
{
if (ReturnBufferSize < Size)
return INF_STATUS_BUFFER_OVERFLOW;
/* Copy multi-sz string */
Ptr = ReturnBuffer;
FieldPtr = CacheField;
while (FieldPtr != NULL)
{
Size = _tcslen (FieldPtr->Data) + 1;
_tcscpy (Ptr, FieldPtr->Data);
Ptr = Ptr + Size;
FieldPtr = FieldPtr->Next;
}
*Ptr = 0;
}
return INF_STATUS_SUCCESS;
}
INFSTATUS
InfpGetStringField(PINFCONTEXT Context,
ULONG FieldIndex,
PTSTR ReturnBuffer,
ULONG ReturnBufferSize,
PULONG RequiredSize)
{
PINFCACHELINE CacheLine;
PINFCACHEFIELD CacheField;
ULONG Index;
PTCHAR Ptr;
ULONG Size;
if (Context == NULL || Context->Line == NULL || FieldIndex == 0)
{
DPRINT("Invalid parameter\n");
return INF_STATUS_INVALID_PARAMETER;
}
if (RequiredSize != NULL)
*RequiredSize = 0;
CacheLine = (PINFCACHELINE)Context->Line;
if (FieldIndex > (ULONG)CacheLine->FieldCount)
return INF_STATUS_INVALID_PARAMETER;
if (FieldIndex == 0)
{
Ptr = CacheLine->Key;
}
else
{
CacheField = CacheLine->FirstField;
for (Index = 1; Index < FieldIndex; Index++)
CacheField = CacheField->Next;
Ptr = CacheField->Data;
}
Size = _tcslen (Ptr) + 1;
if (RequiredSize != NULL)
*RequiredSize = Size;
if (ReturnBuffer != NULL)
{
if (ReturnBufferSize < Size)
return INF_STATUS_BUFFER_OVERFLOW;
_tcscpy (ReturnBuffer, Ptr);
}
return INF_STATUS_SUCCESS;
}
INFSTATUS
InfpGetData(PINFCONTEXT Context,
PTCHAR *Key,
PTCHAR *Data)
{
PINFCACHELINE CacheKey;
if (Context == NULL || Context->Line == NULL || Data == NULL)
{
DPRINT("Invalid parameter\n");
return INF_STATUS_INVALID_PARAMETER;
}
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 INF_STATUS_SUCCESS;
}
INFSTATUS
InfpGetDataField(PINFCONTEXT Context,
ULONG FieldIndex,
PTCHAR *Data)
{
PINFCACHELINE CacheLine;
PINFCACHEFIELD CacheField;
ULONG Index;
if (Context == NULL || Context->Line == NULL || Data == NULL)
{
DPRINT("Invalid parameter\n");
return INF_STATUS_INVALID_PARAMETER;
}
CacheLine = (PINFCACHELINE)Context->Line;
if (FieldIndex > (ULONG)CacheLine->FieldCount)
return INF_STATUS_INVALID_PARAMETER;
if (FieldIndex == 0)
{
*Data = CacheLine->Key;
}
else
{
CacheField = CacheLine->FirstField;
for (Index = 1; Index < FieldIndex; Index++)
CacheField = CacheField->Next;
*Data = CacheField->Data;
}
return INF_STATUS_SUCCESS;
}
VOID
InfpFreeContext(PINFCONTEXT Context)
{
FREE(Context);
}
/* EOF */

View file

@ -0,0 +1,67 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: .inf file parser
* FILE: lib/inflib/infros.h
* PURPOSE: Public .inf routines for use on the host build system
* PROGRAMMER: Royce Mitchell III
* Eric Kohl
* Ge van Geldorp
*/
#ifndef INFHOST_H_INCLUDED
#define INFHOST_H_INCLUDED
#include <infcommon.h>
extern int InfHostOpenBufferedFile(PHINF InfHandle,
void *Buffer,
unsigned long BufferSize,
unsigned long *ErrorLine);
extern int InfHostOpenFile(PHINF InfHandle,
char *FileName,
unsigned long *ErrorLine);
extern void InfHostCloseFile(HINF InfHandle);
extern int InfHostFindFirstLine(HINF InfHandle,
const char *Section,
const char *Key,
PINFCONTEXT *Context);
extern int InfHostFindNextLine(PINFCONTEXT ContextIn,
PINFCONTEXT ContextOut);
extern int InfHostFindFirstMatchLine(PINFCONTEXT ContextIn,
const char *Key,
PINFCONTEXT ContextOut);
extern int InfHostFindNextMatchLine(PINFCONTEXT ContextIn,
const char *Key,
PINFCONTEXT ContextOut);
extern long InfHostGetLineCount(HINF InfHandle,
const char *Section);
extern long InfHostGetFieldCount(PINFCONTEXT Context);
extern int InfHostGetBinaryField(PINFCONTEXT Context,
unsigned long FieldIndex,
unsigned char *ReturnBuffer,
unsigned long ReturnBufferSize,
unsigned long *RequiredSize);
extern int InfHostGetIntField(PINFCONTEXT Context,
unsigned long FieldIndex,
unsigned long *IntegerValue);
extern int InfHostGetMultiSzField(PINFCONTEXT Context,
unsigned long FieldIndex,
char *ReturnBuffer,
unsigned long ReturnBufferSize,
unsigned long *RequiredSize);
extern int InfHostGetStringField(PINFCONTEXT Context,
unsigned long FieldIndex,
char *ReturnBuffer,
unsigned long ReturnBufferSize,
unsigned long *RequiredSize);
extern int InfHostGetData(PINFCONTEXT Context,
char **Key,
char **Data);
extern int InfHostGetDataField(PINFCONTEXT Context,
unsigned long FieldIndex,
char **Data);
extern VOID InfHostFreeContext(PINFCONTEXT Context);
#endif /* INFROS_H_INCLUDED */
/* EOF */

View file

@ -0,0 +1,207 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: .inf file parser
* FILE: lib/inflib/infhostgen.c
* PURPOSE: General .inf routines for use on the host build system
* PROGRAMMER: Royce Mitchell III
* Eric Kohl
* Ge van Geldorp
*/
/* INCLUDES *****************************************************************/
#include <stdio.h>
#include <errno.h>
#include "inflib.h"
#include "infhost.h"
#define NDEBUG
#include <debug.h>
/* PUBLIC FUNCTIONS *********************************************************/
int
InfHostOpenBufferedFile(PHINF InfHandle,
void *Buffer,
unsigned long BufferSize,
unsigned long *ErrorLine)
{
INFSTATUS Status;
PINFCACHE Cache;
char *FileBuffer;
*InfHandle = NULL;
*ErrorLine = (unsigned long)-1;
/* Allocate file buffer */
FileBuffer = MALLOC(BufferSize + 1);
if (FileBuffer == NULL)
{
DPRINT1("MALLOC() failed\n");
return(INF_STATUS_INSUFFICIENT_RESOURCES);
}
MEMCPY(FileBuffer, Buffer, BufferSize);
/* Append string terminator */
FileBuffer[BufferSize] = 0;
/* Allocate infcache header */
Cache = (PINFCACHE)MALLOC(sizeof(INFCACHE));
if (Cache == NULL)
{
DPRINT("MALLOC() failed\n");
FREE(FileBuffer);
return(INF_STATUS_INSUFFICIENT_RESOURCES);
}
/* Initialize inicache header */
ZEROMEMORY(Cache,
sizeof(INFCACHE));
/* Parse the inf buffer */
Status = InfpParseBuffer (Cache,
FileBuffer,
FileBuffer + BufferSize,
ErrorLine);
if (!INF_SUCCESS(Status))
{
FREE(Cache);
Cache = NULL;
}
/* Free file buffer */
FREE(FileBuffer);
*InfHandle = (HINF)Cache;
return INF_SUCCESS(Status) ? 0 : -1;
}
int
InfHostOpenFile(PHINF InfHandle,
char *FileName,
unsigned long *ErrorLine)
{
FILE *File;
char *FileBuffer;
unsigned long FileLength;
PINFCACHE Cache;
INFSTATUS Status;
*InfHandle = NULL;
*ErrorLine = (unsigned long)-1;
/* Open the inf file */
File = fopen(FileName, "rb");
if (NULL == File)
{
DPRINT("fopen() failed (errno %d)\n", errno);
return -1;
}
DPRINT("fopen() successful\n");
/* Query file size */
if (fseek(File, 0, SEEK_END))
{
DPRINT("fseek() to EOF failed (errno %d)\n", errno);
fclose(File);
return -1;
}
FileLength = ftell(File);
if ((unsigned long) -1 == FileLength)
{
DPRINT("ftell() failed (errno %d)\n", errno);
fclose(File);
return -1;
}
DPRINT("File size: %lu\n", FileLength);
/* Rewind */
if (fseek(File, 0, SEEK_SET))
{
DPRINT("fseek() to BOF failed (errno %d)\n", errno);
fclose(File);
return -1;
}
/* Allocate file buffer */
FileBuffer = MALLOC(FileLength + 1);
if (FileBuffer == NULL)
{
DPRINT1("MALLOC() failed\n");
fclose(File);
return -1;
}
/* Read file */
if (FileLength != fread(FileBuffer, 1, FileLength, File))
{
DPRINT("fread() failed (errno %d)\n", errno);
fclose(File);
return -1;
}
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 -1;
}
/* Initialize inicache header */
ZEROMEMORY(Cache,
sizeof(INFCACHE));
/* Parse the inf buffer */
Status = InfpParseBuffer (Cache,
FileBuffer,
FileBuffer + FileLength,
ErrorLine);
if (!INF_SUCCESS(Status))
{
FREE(Cache);
Cache = NULL;
}
/* Free file buffer */
FREE(FileBuffer);
*InfHandle = (HINF)Cache;
return INF_SUCCESS(Status) ? 0 : -1;
}
void
InfHostCloseFile(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);
}
/* EOF */

View file

@ -0,0 +1,252 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: .inf file parser
* FILE: lib/inflib/infrosget.c
* PURPOSE: Read .inf routines for use on the host build system
* PROGRAMMER: Royce Mitchell III
* Eric Kohl
* Ge van Geldorp
*/
/* INCLUDES *****************************************************************/
#include <errno.h>
#include "inflib.h"
#include "infhost.h"
#define NDEBUG
#include <debug.h>
int
InfHostFindFirstLine(HINF InfHandle,
const char *Section,
const char *Key,
PINFCONTEXT *Context)
{
INFSTATUS Status;
Status = InfpFindFirstLine(InfHandle, Section, Key, Context);
if (INF_SUCCESS(Status))
{
return 0;
}
else
{
errno = Status;
return -1;
}
}
int
InfHostFindNextLine(PINFCONTEXT ContextIn,
PINFCONTEXT ContextOut)
{
INFSTATUS Status;
Status = InfpFindNextLine(ContextIn, ContextOut);
if (INF_SUCCESS(Status))
{
return 0;
}
else
{
errno = Status;
return -1;
}
}
int
InfHostFindFirstMatchLine(PINFCONTEXT ContextIn,
const char *Key,
PINFCONTEXT ContextOut)
{
INFSTATUS Status;
Status = InfpFindFirstMatchLine(ContextIn, Key, ContextOut);
if (INF_SUCCESS(Status))
{
return 0;
}
else
{
errno = Status;
return -1;
}
}
int
InfHostFindNextMatchLine(PINFCONTEXT ContextIn,
const char *Key,
PINFCONTEXT ContextOut)
{
INFSTATUS Status;
Status = InfpFindNextMatchLine(ContextIn, Key, ContextOut);
if (INF_SUCCESS(Status))
{
return 0;
}
else
{
errno = Status;
return -1;
}
}
long
InfHostGetLineCount(HINF InfHandle,
PCTSTR Section)
{
return InfpGetLineCount(InfHandle, Section);
}
/* InfGetLineText */
long
InfHostGetFieldCount(PINFCONTEXT Context)
{
return InfpGetFieldCount(Context);
}
int
InfHostGetBinaryField(PINFCONTEXT Context,
unsigned long FieldIndex,
unsigned char *ReturnBuffer,
unsigned long ReturnBufferSize,
unsigned long *RequiredSize)
{
INFSTATUS Status;
Status = InfpGetBinaryField(Context, FieldIndex, ReturnBuffer,
ReturnBufferSize, RequiredSize);
if (INF_SUCCESS(Status))
{
return 0;
}
else
{
errno = Status;
return -1;
}
}
int
InfHostGetIntField(PINFCONTEXT Context,
unsigned long FieldIndex,
unsigned long *IntegerValue)
{
INFSTATUS Status;
Status = InfpGetIntField(Context, FieldIndex, IntegerValue);
if (INF_SUCCESS(Status))
{
return 0;
}
else
{
errno = Status;
return -1;
}
}
int
InfHostGetMultiSzField(PINFCONTEXT Context,
unsigned long FieldIndex,
char * ReturnBuffer,
unsigned long ReturnBufferSize,
unsigned long *RequiredSize)
{
INFSTATUS Status;
Status = InfpGetMultiSzField(Context, FieldIndex, ReturnBuffer,
ReturnBufferSize, RequiredSize);
if (INF_SUCCESS(Status))
{
return 0;
}
else
{
errno = Status;
return -1;
}
}
int
InfHostGetStringField(PINFCONTEXT Context,
unsigned long FieldIndex,
char *ReturnBuffer,
unsigned long ReturnBufferSize,
unsigned long *RequiredSize)
{
INFSTATUS Status;
Status = InfpGetStringField(Context, FieldIndex, ReturnBuffer,
ReturnBufferSize, RequiredSize);
if (INF_SUCCESS(Status))
{
return 0;
}
else
{
errno = Status;
return -1;
}
}
int
InfHostGetData(PINFCONTEXT Context,
char **Key,
char **Data)
{
INFSTATUS Status;
Status = InfpGetData(Context, Key, Data);
if (INF_SUCCESS(Status))
{
return 0;
}
else
{
errno = Status;
return -1;
}
}
int
InfHostGetDataField(PINFCONTEXT Context,
unsigned long FieldIndex,
char **Data)
{
INFSTATUS Status;
Status = InfpGetDataField(Context, FieldIndex, Data);
if (INF_SUCCESS(Status))
{
return 0;
}
else
{
errno = Status;
return -1;
}
}
VOID
InfHostFreeContext(PINFCONTEXT Context)
{
InfpFreeContext(Context);
}
/* EOF */

View file

@ -0,0 +1,16 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: .inf file parser
* FILE: lib/inflib/inflib.h
* PURPOSE: Pre-compiled header
* PROGRAMMER: Ge van Geldorp <gvg@reactos.org>
*/
#include <ctype.h>
#include <stdlib.h>
#include "builddep.h"
#include "infcommon.h"
#include "infpriv.h"
/* EOF */

61
reactos/lib/inflib/inflib.mak Executable file
View file

@ -0,0 +1,61 @@
INFLIB_BASE = $(LIB_BASE_)inflib
INFLIB_BASE_ = $(INFLIB_BASE)$(SEP)
INFLIB_INT = $(INTERMEDIATE_)$(INFLIB_BASE)_host
INFLIB_INT_ = $(INTERMEDIATE_)$(INFLIB_BASE)_host$(SEP)
INFLIB_OUT = $(OUTPUT_)$(INFLIB_BASE)_host
INFLIB_OUT_ = $(OUTPUT_)$(INFLIB_BASE)_host$(SEP)
$(INFLIB_INT): | $(LIB_INT)
$(ECHO_MKDIR)
${mkdir} $@
ifneq ($(INTERMEDIATE),$(OUTPUT))
$(INFLIB_OUT): | $(OUTPUT_)$(LIB_BASE)
$(ECHO_MKDIR)
${mkdir} $@
endif
INFLIB_HOST_TARGET = \
$(INFLIB_OUT)$(SEP)inflib.a
INFLIB_HOST_SOURCES = $(addprefix $(INFLIB_BASE_), \
infcore.c \
infget.c \
infhostgen.c \
infhostget.c \
)
INFLIB_HOST_OBJECTS = \
$(subst $(INFLIB_BASE), $(INFLIB_INT), $(INFLIB_HOST_SOURCES:.c=.o))
INFLIB_HOST_CFLAGS = -O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \
-Wstrict-prototypes -Wmissing-prototypes -DINFLIB_HOST -D_M_IX86 \
-I$(INFLIB_BASE) -Iinclude/reactos
$(INFLIB_HOST_TARGET): $(INFLIB_HOST_OBJECTS) | $(INFLIB_OUT)
$(ECHO_AR)
$(host_ar) -r $@ $(INFLIB_HOST_OBJECTS)
$(INFLIB_INT_)infcore.o: $(INFLIB_BASE_)infcore.c | $(INFLIB_INT)
$(ECHO_CC)
${host_gcc} $(INFLIB_HOST_CFLAGS) -c $< -o $@
$(INFLIB_INT_)infget.o: $(INFLIB_BASE_)infget.c | $(INFLIB_INT)
$(ECHO_CC)
${host_gcc} $(INFLIB_HOST_CFLAGS) -c $< -o $@
$(INFLIB_INT_)infhostgen.o: $(INFLIB_BASE_)infhostgen.c | $(INFLIB_INT)
$(ECHO_CC)
${host_gcc} $(INFLIB_HOST_CFLAGS) -c $< -o $@
$(INFLIB_INT_)infhostget.o: $(INFLIB_BASE_)infhostget.c | $(INFLIB_INT)
$(ECHO_CC)
${host_gcc} $(INFLIB_HOST_CFLAGS) -c $< -o $@
.PHONY: inflib_host
inflib_host: $(INFLIB_HOST_TARGET)
.PHONY: inflib_host_clean
inflib_host_clean:
-@$(rm) $(INFLIB_HOST_TARGET) $(INFLIB_HOST_OBJECTS) 2>$(NUL)
clean: inflib_host_clean

View file

@ -0,0 +1,8 @@
<module name="inflib" type="staticlibrary">
<include base="inflib">.</include>
<pch>inflib.h</pch>
<file>infcore.c</file>
<file>infget.c</file>
<file>infrosgen.c</file>
<file>infrosget.c</file>
</module>

View file

@ -0,0 +1,126 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: .inf file parser
* FILE: lib/inflib/infcache.h
* PURPOSE: INF file parser that caches contents of INF file in memory
* PROGRAMMER: Royce Mitchell III
* Eric Kohl
* Ge van Geldorp <gvg@reactos.org>
*/
#ifndef INFPRIV_H_INCLUDED
#define INFPRIV_H_INCLUDED
#define INF_STATUS_INSUFFICIENT_RESOURCES (0xC000009A)
#define INF_STATUS_BAD_SECTION_NAME_LINE (0xC0700001)
#define INF_STATUS_SECTION_NAME_TOO_LONG (0xC0700002)
#define INF_STATUS_WRONG_INF_STYLE (0xC0700003)
#define INF_STATUS_NOT_ENOUGH_MEMORY (0xC0700004)
typedef struct _INFCONTEXT
{
PVOID Inf;
PVOID Section;
PVOID Line;
} INFCONTEXT;
typedef struct _INFCACHEFIELD
{
struct _INFCACHEFIELD *Next;
struct _INFCACHEFIELD *Prev;
TCHAR Data[1];
} INFCACHEFIELD, *PINFCACHEFIELD;
typedef struct _INFCACHELINE
{
struct _INFCACHELINE *Next;
struct _INFCACHELINE *Prev;
LONG FieldCount;
PTCHAR Key;
PINFCACHEFIELD FirstField;
PINFCACHEFIELD LastField;
} INFCACHELINE, *PINFCACHELINE;
typedef struct _INFCACHESECTION
{
struct _INFCACHESECTION *Next;
struct _INFCACHESECTION *Prev;
PINFCACHELINE FirstLine;
PINFCACHELINE LastLine;
LONG LineCount;
TCHAR Name[1];
} INFCACHESECTION, *PINFCACHESECTION;
typedef struct _INFCACHE
{
PINFCACHESECTION FirstSection;
PINFCACHESECTION LastSection;
PINFCACHESECTION StringsSection;
} INFCACHE, *PINFCACHE;
typedef long INFSTATUS;
/* FUNCTIONS ****************************************************************/
extern INFSTATUS InfpParseBuffer(PINFCACHE file,
const CHAR *buffer,
const CHAR *end,
PULONG error_line);
extern PINFCACHESECTION InfpCacheFreeSection(PINFCACHESECTION Section);
extern PINFCACHELINE InfpCacheFindKeyLine(PINFCACHESECTION Section,
PTCHAR Key);
extern INFSTATUS InfpFindFirstLine(HINF InfHandle,
PCTSTR Section,
PCTSTR Key,
PINFCONTEXT *Context);
extern INFSTATUS InfpFindNextLine(PINFCONTEXT ContextIn,
PINFCONTEXT ContextOut);
extern INFSTATUS InfpFindFirstMatchLine(PINFCONTEXT ContextIn,
PCTSTR Key,
PINFCONTEXT ContextOut);
extern INFSTATUS InfpFindNextMatchLine(PINFCONTEXT ContextIn,
PCTSTR Key,
PINFCONTEXT ContextOut);
extern LONG InfpGetLineCount(HINF InfHandle,
PCTSTR Section);
extern LONG InfpGetFieldCount(PINFCONTEXT Context);
extern INFSTATUS InfpGetBinaryField(PINFCONTEXT Context,
ULONG FieldIndex,
PUCHAR ReturnBuffer,
ULONG ReturnBufferSize,
PULONG RequiredSize);
extern INFSTATUS InfpGetIntField(PINFCONTEXT Context,
ULONG FieldIndex,
PLONG IntegerValue);
extern INFSTATUS InfpGetMultiSzField(PINFCONTEXT Context,
ULONG FieldIndex,
PTSTR ReturnBuffer,
ULONG ReturnBufferSize,
PULONG RequiredSize);
extern INFSTATUS InfpGetStringField(PINFCONTEXT Context,
ULONG FieldIndex,
PTSTR ReturnBuffer,
ULONG ReturnBufferSize,
PULONG RequiredSize);
extern INFSTATUS InfpGetData(PINFCONTEXT Context,
PTCHAR *Key,
PTCHAR *Data);
extern INFSTATUS InfpGetDataField(PINFCONTEXT Context,
ULONG FieldIndex,
PTCHAR *Data);
extern VOID InfpFreeContext(PINFCONTEXT Context);
#endif /* INFPRIV_H_INCLUDED */
/* EOF */

View file

@ -0,0 +1,68 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: .inf file parser
* FILE: lib/inflib/infros.h
* PURPOSE: Public .inf routines for use in ReactOS
* PROGRAMMER: Royce Mitchell III
* Eric Kohl
* Ge van Geldorp
*/
#ifndef INFROS_H_INCLUDED
#define INFROS_H_INCLUDED
#include <infcommon.h>
extern VOID InfSetHeap(PVOID Heap);
extern NTSTATUS InfOpenBufferedFile(PHINF InfHandle,
PVOID Buffer,
ULONG BufferSize,
PULONG ErrorLine);
extern NTSTATUS InfOpenFile(PHINF InfHandle,
PUNICODE_STRING FileName,
PULONG ErrorLine);
extern VOID InfCloseFile(HINF InfHandle);
extern BOOLEAN InfFindFirstLine(HINF InfHandle,
PCWSTR Section,
PCWSTR Key,
PINFCONTEXT *Context);
extern BOOLEAN InfFindNextLine(PINFCONTEXT ContextIn,
PINFCONTEXT ContextOut);
extern BOOLEAN InfFindFirstMatchLine(PINFCONTEXT ContextIn,
PCWSTR Key,
PINFCONTEXT ContextOut);
extern BOOLEAN InfFindNextMatchLine(PINFCONTEXT ContextIn,
PCWSTR Key,
PINFCONTEXT ContextOut);
extern LONG InfGetLineCount(HINF InfHandle,
PCWSTR Section);
extern LONG InfGetFieldCount(PINFCONTEXT Context);
extern BOOLEAN InfGetBinaryField(PINFCONTEXT Context,
ULONG FieldIndex,
PUCHAR ReturnBuffer,
ULONG ReturnBufferSize,
PULONG RequiredSize);
extern BOOLEAN InfGetIntField(PINFCONTEXT Context,
ULONG FieldIndex,
PLONG IntegerValue);
extern BOOLEAN InfGetMultiSzField(PINFCONTEXT Context,
ULONG FieldIndex,
PWSTR ReturnBuffer,
ULONG ReturnBufferSize,
PULONG RequiredSize);
extern BOOLEAN InfGetStringField(PINFCONTEXT Context,
ULONG FieldIndex,
PWSTR ReturnBuffer,
ULONG ReturnBufferSize,
PULONG RequiredSize);
extern BOOLEAN InfGetData(PINFCONTEXT Context,
PWCHAR *Key,
PWCHAR *Data);
extern BOOLEAN InfGetDataField(PINFCONTEXT Context,
ULONG FieldIndex,
PWCHAR *Data);
extern VOID InfFreeContext(PINFCONTEXT Context);
#endif /* INFROS_H_INCLUDED */
/* EOF */

View file

@ -0,0 +1,269 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: .inf file parser
* FILE: lib/inflib/infrosgen.c
* PURPOSE: General .inf routines for use in ReactOS
* PROGRAMMER: Royce Mitchell III
* Eric Kohl
* Ge van Geldorp
*/
/* INCLUDES *****************************************************************/
#include "inflib.h"
#include "infros.h"
#define NDEBUG
#include <debug.h>
/* PRIVATE FUNCTIONS ********************************************************/
static int InfpHeapRefCount;
static VOID
CheckHeap()
{
if (NULL == InfpHeap)
{
InfpHeap = RtlCreateHeap(HEAP_GROWABLE, NULL, 0, 0, NULL, NULL);
}
if (0 <= InfpHeapRefCount)
{
InfpHeapRefCount++;
}
}
/* PUBLIC FUNCTIONS *********************************************************/
PVOID InfpHeap;
VOID
InfSetHeap(PVOID Heap)
{
if (NULL == InfpHeap)
{
InfpHeap = Heap;
InfpHeapRefCount = -1;
}
}
NTSTATUS
InfOpenBufferedFile(PHINF InfHandle,
PVOID Buffer,
ULONG BufferSize,
PULONG ErrorLine)
{
INFSTATUS Status;
PINFCACHE Cache;
PCHAR FileBuffer;
CheckHeap();
*InfHandle = NULL;
*ErrorLine = (ULONG)-1;
/* Allocate file buffer */
FileBuffer = MALLOC(BufferSize + 1);
if (FileBuffer == NULL)
{
DPRINT1("MALLOC() failed\n");
return(INF_STATUS_INSUFFICIENT_RESOURCES);
}
MEMCPY(FileBuffer, Buffer, BufferSize);
/* Append string terminator */
FileBuffer[BufferSize] = 0;
/* Allocate infcache header */
Cache = (PINFCACHE)MALLOC(sizeof(INFCACHE));
if (Cache == NULL)
{
DPRINT("MALLOC() failed\n");
FREE(FileBuffer);
return(INF_STATUS_INSUFFICIENT_RESOURCES);
}
/* Initialize inicache header */
ZEROMEMORY(Cache,
sizeof(INFCACHE));
/* Parse the inf buffer */
Status = InfpParseBuffer (Cache,
FileBuffer,
FileBuffer + BufferSize,
ErrorLine);
if (!INF_SUCCESS(Status))
{
FREE(Cache);
Cache = NULL;
}
/* Free file buffer */
FREE(FileBuffer);
*InfHandle = (HINF)Cache;
return(Status);
}
NTSTATUS
InfOpenFile(PHINF InfHandle,
PUNICODE_STRING FileName,
PULONG ErrorLine)
{
OBJECT_ATTRIBUTES ObjectAttributes;
FILE_STANDARD_INFORMATION FileInfo;
IO_STATUS_BLOCK IoStatusBlock;
HANDLE FileHandle;
NTSTATUS Status;
PCHAR FileBuffer;
ULONG FileLength;
LARGE_INTEGER FileOffset;
PINFCACHE Cache;
CheckHeap();
*InfHandle = NULL;
*ErrorLine = (ULONG)-1;
/* Open the inf file */
InitializeObjectAttributes(&ObjectAttributes,
FileName,
0,
NULL,
NULL);
Status = NtOpenFile(&FileHandle,
GENERIC_READ | SYNCHRONIZE,
&ObjectAttributes,
&IoStatusBlock,
FILE_SHARE_READ,
FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE);
if (!INF_SUCCESS(Status))
{
DPRINT("NtOpenFile() failed (Status %lx)\n", Status);
return(Status);
}
DPRINT("NtOpenFile() successful\n");
/* Query file size */
Status = NtQueryInformationFile(FileHandle,
&IoStatusBlock,
&FileInfo,
sizeof(FILE_STANDARD_INFORMATION),
FileStandardInformation);
if (!INF_SUCCESS(Status))
{
DPRINT("NtQueryInformationFile() failed (Status %lx)\n", Status);
NtClose(FileHandle);
return(Status);
}
FileLength = FileInfo.EndOfFile.u.LowPart;
DPRINT("File size: %lu\n", FileLength);
/* Allocate file buffer */
FileBuffer = MALLOC(FileLength + 1);
if (FileBuffer == NULL)
{
DPRINT1("MALLOC() failed\n");
NtClose(FileHandle);
return(INF_STATUS_INSUFFICIENT_RESOURCES);
}
/* Read file */
FileOffset.QuadPart = 0ULL;
Status = NtReadFile(FileHandle,
NULL,
NULL,
NULL,
&IoStatusBlock,
FileBuffer,
FileLength,
&FileOffset,
NULL);
/* Append string terminator */
FileBuffer[FileLength] = 0;
NtClose(FileHandle);
if (!INF_SUCCESS(Status))
{
DPRINT("NtReadFile() failed (Status %lx)\n", Status);
FREE(FileBuffer);
return(Status);
}
/* Allocate infcache header */
Cache = (PINFCACHE)MALLOC(sizeof(INFCACHE));
if (Cache == NULL)
{
DPRINT("MALLOC() failed\n");
FREE(FileBuffer);
return(INF_STATUS_INSUFFICIENT_RESOURCES);
}
/* Initialize inicache header */
ZEROMEMORY(Cache,
sizeof(INFCACHE));
/* Parse the inf buffer */
Status = InfpParseBuffer (Cache,
FileBuffer,
FileBuffer + FileLength,
ErrorLine);
if (!INF_SUCCESS(Status))
{
FREE(Cache);
Cache = NULL;
}
/* Free file buffer */
FREE(FileBuffer);
*InfHandle = (HINF)Cache;
return(Status);
}
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);
if (0 < InfpHeapRefCount)
{
InfpHeapRefCount--;
if (0 == InfpHeapRefCount)
{
RtlDestroyHeap(InfpHeap);
InfpHeap = NULL;
}
}
}
/* EOF */

View file

@ -0,0 +1,142 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: .inf file parser
* FILE: lib/inflib/infrosget.c
* PURPOSE: Read .inf routines for use in ReactOS
* PROGRAMMER: Royce Mitchell III
* Eric Kohl
* Ge van Geldorp
*/
/* INCLUDES *****************************************************************/
#include "inflib.h"
#include "infros.h"
#define NDEBUG
#include <debug.h>
BOOLEAN
InfFindFirstLine(HINF InfHandle,
PCWSTR Section,
PCWSTR Key,
PINFCONTEXT *Context)
{
return INF_SUCCESS(InfpFindFirstLine(InfHandle, Section, Key, Context));
}
BOOLEAN
InfFindNextLine(PINFCONTEXT ContextIn,
PINFCONTEXT ContextOut)
{
return INF_SUCCESS(InfpFindNextLine(ContextIn, ContextOut));
}
BOOLEAN
InfFindFirstMatchLine(PINFCONTEXT ContextIn,
PCWSTR Key,
PINFCONTEXT ContextOut)
{
return INF_SUCCESS(InfpFindFirstMatchLine(ContextIn, Key, ContextOut));
}
BOOLEAN
InfFindNextMatchLine(PINFCONTEXT ContextIn,
PCWSTR Key,
PINFCONTEXT ContextOut)
{
return INF_SUCCESS(InfpFindNextMatchLine(ContextIn, Key, ContextOut));
}
LONG
InfGetLineCount(HINF InfHandle,
PCWSTR Section)
{
return InfpGetLineCount(InfHandle, Section);
}
/* InfGetLineText */
LONG
InfGetFieldCount(PINFCONTEXT Context)
{
return InfpGetFieldCount(Context);
}
BOOLEAN
InfGetBinaryField(PINFCONTEXT Context,
ULONG FieldIndex,
PUCHAR ReturnBuffer,
ULONG ReturnBufferSize,
PULONG RequiredSize)
{
return INF_SUCCESS(InfpGetBinaryField(Context, FieldIndex, ReturnBuffer,
ReturnBufferSize, RequiredSize));
}
BOOLEAN
InfGetIntField(PINFCONTEXT Context,
ULONG FieldIndex,
PLONG IntegerValue)
{
return INF_SUCCESS(InfpGetIntField(Context, FieldIndex, IntegerValue));
}
BOOLEAN
InfGetMultiSzField(PINFCONTEXT Context,
ULONG FieldIndex,
PWSTR ReturnBuffer,
ULONG ReturnBufferSize,
PULONG RequiredSize)
{
return INF_SUCCESS(InfpGetMultiSzField(Context, FieldIndex, ReturnBuffer,
ReturnBufferSize, RequiredSize));
}
BOOLEAN
InfGetStringField(PINFCONTEXT Context,
ULONG FieldIndex,
PWSTR ReturnBuffer,
ULONG ReturnBufferSize,
PULONG RequiredSize)
{
return INF_SUCCESS(InfpGetStringField(Context, FieldIndex, ReturnBuffer,
ReturnBufferSize, RequiredSize));
}
BOOLEAN
InfGetData(PINFCONTEXT Context,
PWCHAR *Key,
PWCHAR *Data)
{
return INF_SUCCESS(InfpGetData(Context, Key, Data));
}
BOOLEAN
InfGetDataField (PINFCONTEXT Context,
ULONG FieldIndex,
PWCHAR *Data)
{
return INF_SUCCESS(InfpGetDataField(Context, FieldIndex, Data));
}
VOID
InfFreeContext(PINFCONTEXT Context)
{
InfpFreeContext(Context);
}
/* EOF */

View file

@ -2,3 +2,4 @@ LIB_BASE = lib
LIB_BASE_ = $(LIB_BASE)$(SEP)
include $(LIB_BASE_)zlib/zlib.mak
include $(LIB_BASE_)inflib/inflib.mak