[NEWINFLIB]

Add a UNICODE-aware version of the inflib library.
It is not used by other components yet but usetup and mkhive will use it in the future.
ATTENTION: This commit might break the build bot because I could not test a build on a Linux system.

svn path=/trunk/; revision=47016
This commit is contained in:
Eric Kohl 2010-04-25 15:58:34 +00:00
parent 49496ddec6
commit 0225b59c2d
20 changed files with 3803 additions and 0 deletions

View file

@ -37,6 +37,9 @@
<directory name="lsalib">
<xi:include href="lsalib/lsalib.rbuild" />
</directory>
<directory name="newinflib">
<xi:include href="newinflib/inflib.rbuild" />
</directory>
<directory name="nls">
<xi:include href="nls/nls.rbuild" />
</directory>

View file

@ -0,0 +1,16 @@
Routines to handle .inf files.
This is the UNICODE-enabled version of inflib. It will be used by usetup and mkhive.
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,98 @@
/*
* PROJECT: .inf file parser
* LICENSE: GPL - See COPYING in the top level directory
* COPYRIGHT: Copyright 2005 Ge van Geldorp <gvg@reactos.org>
*/
#ifdef INFLIB_HOST
/* Definitions native to the host on which we're building */
#include <host/typedefs.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#define FREE(Area) free(Area)
#define MALLOC(Size) malloc((size_t)(Size))
#define ZEROMEMORY(Area, Size) memset((Area), '\0', (size_t)(Size))
#define MEMCPY(Dest, Src, Size) memcpy((Dest), (Src), (size_t)(Size))
#define STATUS_SUCCESS 0
#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 TCHAR, *PTCHAR, *PTSTR;
typedef const TCHAR *PCTSTR;
typedef WORD LCID;
#define _T(x) x
#define _tcsicmp strcasecmp
#define _tcslen strlen
#define _tcscpy strcpy
#define _tcstoul strtoul
#define _tcstol strtol
#define STRFMT "%s"
#ifdef _MSC_VER
#define strcasecmp _stricmp
#endif
#define IS_TEXT_UNICODE_ASCII16 1
#define IS_TEXT_UNICODE_REVERSE_ASCII16 16
#define IS_TEXT_UNICODE_STATISTICS 2
#define IS_TEXT_UNICODE_REVERSE_STATISTICS 32
#define IS_TEXT_UNICODE_CONTROLS 4
#define IS_TEXT_UNICODE_REVERSE_CONTROLS 64
#define IS_TEXT_UNICODE_SIGNATURE 8
#define IS_TEXT_UNICODE_REVERSE_SIGNATURE 128
#define IS_TEXT_UNICODE_ILLEGAL_CHARS 256
#define IS_TEXT_UNICODE_ODD_LENGTH 512
#define IS_TEXT_UNICODE_NULL_BYTES 4096
#define IS_TEXT_UNICODE_UNICODE_MASK 15
#define IS_TEXT_UNICODE_REVERSE_MASK 240
#define IS_TEXT_UNICODE_NOT_UNICODE_MASK 3840
#define IS_TEXT_UNICODE_NOT_ASCII_MASK 61440
#define SUBLANG_NEUTRAL 0
#define PRIMARYLANGID(lgid) ((WORD)(lgid) & 0x3ff)
#define MAKELANGID(p, s) ((((WORD)(s)) << 10) | (WORD)(p))
#else /* ! defined(INFLIB_HOST) */
/* ReactOS definitions */
#define UNICODE
#define _UNICODE
#define WIN32_NO_STATUS
#include <windows.h>
#define NTOS_MODE_USER
#include <ndk/ntndk.h>
#include <tchar.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))
#define STRFMT "%S"
#endif /* INFLIB_HOST */
/* EOF */

View file

@ -0,0 +1,16 @@
/*
* PROJECT: .inf file parser
* LICENSE: GPL - See COPYING in the top level directory
* PROGRAMMER: Royce Mitchell III
* Eric Kohl
* Ge van Geldorp <gvg@reactos.org>
*/
#pragma once
#define MAX_INF_STRING_LENGTH 512
typedef void *HINF, **PHINF;
typedef struct _INFCONTEXT *PINFCONTEXT;
/* EOF */

View file

@ -0,0 +1,831 @@
/*
* PROJECT: .inf file parser
* LICENSE: GPL - See COPYING in the top level directory
* PROGRAMMER: Royce Mitchell III
* Eric Kohl
* Ge van Geldorp <gvg@reactos.org>
*/
/* 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 WCHAR *start; /* start position of item being parsed */
const WCHAR *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 */
INFSTATUS error; /* error code */
unsigned int token_len; /* current token len */
WCHAR token[MAX_FIELD_LEN+1]; /* current token */
};
typedef const WCHAR * (*parser_state_func)( struct parser *parser, const WCHAR *pos );
/* parser state machine functions */
static const WCHAR *line_start_state( struct parser *parser, const WCHAR *pos );
static const WCHAR *section_name_state( struct parser *parser, const WCHAR *pos );
static const WCHAR *key_name_state( struct parser *parser, const WCHAR *pos );
static const WCHAR *value_name_state( struct parser *parser, const WCHAR *pos );
static const WCHAR *eol_backslash_state( struct parser *parser, const WCHAR *pos );
static const WCHAR *quotes_state( struct parser *parser, const WCHAR *pos );
static const WCHAR *leading_spaces_state( struct parser *parser, const WCHAR *pos );
static const WCHAR *trailing_spaces_state( struct parser *parser, const WCHAR *pos );
static const WCHAR *comment_state( struct parser *parser, const WCHAR *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
InfpFreeLine (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
InfpFreeSection (PINFCACHESECTION Section)
{
PINFCACHESECTION Next;
if (Section == NULL)
{
return NULL;
}
/* Release all keys */
Next = Section->Next;
while (Section->FirstLine != NULL)
{
Section->FirstLine = InfpFreeLine (Section->FirstLine);
}
Section->LastLine = NULL;
FREE (Section);
return Next;
}
PINFCACHESECTION
InfpFindSection(PINFCACHE Cache,
PCWSTR Name)
{
PINFCACHESECTION Section = NULL;
if (Cache == NULL || Name == NULL)
{
return NULL;
}
/* iterate through list of sections */
Section = Cache->FirstSection;
while (Section != NULL)
{
if (_wcsicmp (Section->Name, Name) == 0)
{
return Section;
}
/* get the next section*/
Section = Section->Next;
}
return NULL;
}
PINFCACHESECTION
InfpAddSection(PINFCACHE Cache,
PCWSTR Name)
{
PINFCACHESECTION Section = NULL;
ULONG Size;
if (Cache == NULL || Name == NULL)
{
DPRINT("Invalid parameter\n");
return NULL;
}
/* Allocate and initialize the new section */
Size = (ULONG)FIELD_OFFSET(INFCACHESECTION,
Name[wcslen (Name) + 1]);
Section = (PINFCACHESECTION)MALLOC(Size);
if (Section == NULL)
{
DPRINT("MALLOC() failed\n");
return NULL;
}
ZEROMEMORY (Section,
Size);
/* Copy section name */
wcscpy (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;
}
PINFCACHELINE
InfpAddLine(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;
}
PVOID
InfpAddKeyToLine(PINFCACHELINE Line,
PCWSTR Key)
{
if (Line == NULL)
{
DPRINT1("Invalid Line\n");
return NULL;
}
if (Line->Key != NULL)
{
DPRINT1("Line already has a key\n");
return NULL;
}
Line->Key = (PWCHAR)MALLOC((wcslen(Key) + 1) * sizeof(WCHAR));
if (Line->Key == NULL)
{
DPRINT1("MALLOC() failed\n");
return NULL;
}
wcscpy(Line->Key, Key);
return (PVOID)Line->Key;
}
PVOID
InfpAddFieldToLine(PINFCACHELINE Line,
PCWSTR Data)
{
PINFCACHEFIELD Field;
ULONG Size;
Size = (ULONG)FIELD_OFFSET(INFCACHEFIELD,
Data[wcslen(Data) + 1]);
Field = (PINFCACHEFIELD)MALLOC(Size);
if (Field == NULL)
{
DPRINT1("MALLOC() failed\n");
return NULL;
}
ZEROMEMORY (Field,
Size);
wcscpy (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
InfpFindKeyLine(PINFCACHESECTION Section,
PCWSTR Key)
{
PINFCACHELINE Line;
Line = Section->FirstLine;
while (Line != NULL)
{
if (Line->Key != NULL && _wcsicmp (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 WCHAR *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 WCHAR *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 WCHAR *pos )
{
UINT len = (UINT)(pos - parser->start);
const WCHAR *src = parser->start;
WCHAR *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++)
{
if (*src)
{
*dst = *src;
}
else
{
*dst = ' ';
}
}
*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 = InfpFindSection(parser->file,
parser->token);
if (Section == NULL)
{
/* need to create a new one */
Section= InfpAddSection(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 = InfpAddLine(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 WCHAR *line_start_state( struct parser *parser, const WCHAR *pos )
{
const WCHAR *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 (!iswspace(*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 WCHAR *section_name_state( struct parser *parser, const WCHAR *pos )
{
const WCHAR *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 WCHAR *key_name_state( struct parser *parser, const WCHAR *pos )
{
const WCHAR *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 (!iswspace(*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 WCHAR *value_name_state( struct parser *parser, const WCHAR *pos )
{
const WCHAR *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 WCHAR *eol_backslash_state( struct parser *parser, const WCHAR *pos )
{
const WCHAR *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 (iswspace(*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 WCHAR *quotes_state( struct parser *parser, const WCHAR *pos )
{
const WCHAR *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 WCHAR *leading_spaces_state( struct parser *parser, const WCHAR *pos )
{
const WCHAR *p;
for (p = pos; !is_eol( parser, p ); p++)
{
if (*p == '\\')
{
parser->start = p;
set_state( parser, EOL_BACKSLASH );
return p;
}
if (!iswspace(*p))
break;
}
parser->start = p;
pop_state( parser );
return p;
}
/* handler for parser TRAILING_SPACES state */
static const WCHAR *trailing_spaces_state( struct parser *parser, const WCHAR *pos )
{
const WCHAR *p;
for (p = pos; !is_eol( parser, p ); p++)
{
if (*p == '\\')
{
set_state( parser, EOL_BACKSLASH );
return p;
}
if (!iswspace(*p))
break;
}
pop_state( parser );
return p;
}
/* handler for parser COMMENT state */
static const WCHAR *comment_state( struct parser *parser, const WCHAR *pos )
{
const WCHAR *p = pos;
while (!is_eol( parser, p ))
p++;
pop_state( parser );
return p;
}
/* parse a complete buffer */
INFSTATUS
InfpParseBuffer (PINFCACHE file,
const WCHAR *buffer,
const WCHAR *end,
PULONG error_line)
{
struct parser parser;
const WCHAR *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 = InfpFindSection(file,
L"Strings");
return INF_STATUS_SUCCESS;
}
/* EOF */

View file

@ -0,0 +1,668 @@
/*
* PROJECT: .inf file parser
* LICENSE: GPL - See COPYING in the top level directory
* PROGRAMMER: Royce Mitchell III
* Eric Kohl
* Ge van Geldorp <gvg@reactos.org>
*/
/* INCLUDES *****************************************************************/
#include "inflib.h"
#define NDEBUG
#include <debug.h>
static unsigned int
InfpSubstituteString(PINFCACHE Inf,
const WCHAR *text,
WCHAR *buffer,
unsigned int size);
/* retrieve the string substitution for a given string, or NULL if not found */
/* if found, len is set to the substitution length */
static PCWSTR
InfpGetSubstitutionString(PINFCACHE Inf,
PCWSTR str,
unsigned int *len,
BOOL no_trailing_slash)
{
static const WCHAR percent = '%';
INFSTATUS Status = INF_STATUS_NOT_FOUND;
PINFCONTEXT Context = NULL;
PWCHAR Data = NULL;
WCHAR ValueName[MAX_INF_STRING_LENGTH +1];
WCHAR StringLangId[13];
if (!*len) /* empty string (%%) is replaced by single percent */
{
*len = 1;
return &percent;
}
wcsncpy(ValueName, str, *len);
ValueName[*len] = 0;
DPRINT("Value name: %S\n", ValueName);
if (Inf->LocaleId != 0)
{
swprintf(StringLangId,
L"Strings.%04hx",
Inf->LocaleId);
Status = InfpFindFirstLine(Inf,
StringLangId,
ValueName,
&Context);
if (Status != INF_STATUS_SUCCESS)
{
swprintf(StringLangId,
L"Strings.%04hx",
MAKELANGID(PRIMARYLANGID(Inf->LocaleId), SUBLANG_NEUTRAL));
Status = InfpFindFirstLine(Inf,
StringLangId,
ValueName,
&Context);
if (Status != INF_STATUS_SUCCESS)
{
Status = InfpFindFirstLine(Inf,
L"Strings",
ValueName,
&Context);
}
}
}
else
{
Status = InfpFindFirstLine(Inf,
L"Strings",
ValueName,
&Context);
}
if (Status != INF_STATUS_SUCCESS || Context == NULL)
return NULL;
Status = InfpGetData(Context,
NULL,
&Data);
InfpFreeContext(Context);
if (Status == STATUS_SUCCESS)
{
*len = wcslen(Data);
DPRINT("Substitute: %S Length: %ul\n", Data, *len);
return Data;
}
return NULL;
}
/* do string substitutions on the specified text */
/* the buffer is assumed to be large enough */
/* returns necessary length not including terminating null */
static unsigned int
InfpSubstituteString(PINFCACHE Inf,
PCWSTR text,
PWSTR buffer,
unsigned int size)
{
const WCHAR *start, *subst, *p;
unsigned int len, total = 0;
int inside = 0;
if (!buffer) size = MAX_INF_STRING_LENGTH + 1;
for (p = start = text; *p; p++)
{
if (*p != '%') continue;
inside = !inside;
if (inside) /* start of a %xx% string */
{
len = (unsigned int)(p - start);
if (len > size - 1) len = size - 1;
if (buffer) memcpy( buffer + total, start, len * sizeof(WCHAR) );
total += len;
size -= len;
start = p;
}
else /* end of the %xx% string, find substitution */
{
len = (unsigned int)(p - start - 1);
subst = InfpGetSubstitutionString( Inf, start + 1, &len, p[1] == '\\' );
if (!subst)
{
subst = start;
len = (unsigned int)(p - start + 1);
}
if (len > size - 1) len = size - 1;
if (buffer) memcpy( buffer + total, subst, len * sizeof(WCHAR) );
total += len;
size -= len;
start = p + 1;
}
}
if (start != p) /* unfinished string, copy it */
{
len = (unsigned int)(p - start);
if (len > size - 1) len = size - 1;
if (buffer) memcpy( buffer + total, start, len * sizeof(WCHAR) );
total += len;
}
if (buffer && size) buffer[total] = 0;
return total;
}
INFSTATUS
InfpFindFirstLine(PINFCACHE Cache,
PCWSTR Section,
PCWSTR Key,
PINFCONTEXT *Context)
{
PINFCACHESECTION CacheSection;
PINFCACHELINE CacheLine;
if (Cache == NULL || Section == NULL || Context == NULL)
{
DPRINT1("Invalid parameter\n");
return INF_STATUS_INVALID_PARAMETER;
}
CacheSection = InfpFindSection(Cache, Section);
if (NULL == CacheSection)
{
DPRINT("Section not found\n");
return INF_STATUS_NOT_FOUND;
}
if (Key != NULL)
{
CacheLine = InfpFindKeyLine(CacheSection, Key);
}
else
{
CacheLine = CacheSection->FirstLine;
}
if (NULL == CacheLine)
{
DPRINT("Key not found\n");
return INF_STATUS_NOT_FOUND;
}
*Context = MALLOC(sizeof(INFCONTEXT));
if (NULL == *Context)
{
DPRINT1("MALLOC() failed\n");
return INF_STATUS_NO_MEMORY;
}
(*Context)->Inf = (PVOID)Cache;
(*Context)->Section = (PVOID)CacheSection;
(*Context)->Line = (PVOID)CacheLine;
return INF_STATUS_SUCCESS;
}
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,
PCWSTR 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 && _wcsicmp (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,
PCWSTR 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 && _wcsicmp (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,
PCWSTR 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 (_wcsicmp(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 = (ULONG)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)wcstoul(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;
PWCHAR 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 = (LONG)wcstol(Ptr, NULL, 0);
return INF_STATUS_SUCCESS;
}
INFSTATUS
InfpGetMultiSzField(PINFCONTEXT Context,
ULONG FieldIndex,
PWSTR ReturnBuffer,
ULONG ReturnBufferSize,
PULONG RequiredSize)
{
PINFCACHELINE CacheLine;
PINFCACHEFIELD CacheField;
PINFCACHEFIELD FieldPtr;
ULONG Index;
ULONG Size;
PWCHAR 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 += ((ULONG)wcslen (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 = (ULONG)wcslen (FieldPtr->Data) + 1;
wcscpy (Ptr, FieldPtr->Data);
Ptr = Ptr + Size;
FieldPtr = FieldPtr->Next;
}
*Ptr = 0;
}
return INF_STATUS_SUCCESS;
}
INFSTATUS
InfpGetStringField(PINFCONTEXT Context,
ULONG FieldIndex,
PWSTR ReturnBuffer,
ULONG ReturnBufferSize,
PULONG RequiredSize)
{
PINFCACHELINE CacheLine;
PINFCACHEFIELD CacheField;
ULONG Index;
PWCHAR 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 = (ULONG)wcslen (Ptr) + 1;
Size = InfpSubstituteString(Context->Inf,
Ptr,
NULL,
0);
if (RequiredSize != NULL)
*RequiredSize = Size + 1;
if (ReturnBuffer != NULL)
{
if (ReturnBufferSize <= Size)
return INF_STATUS_BUFFER_OVERFLOW;
// wcscpy (ReturnBuffer, Ptr);
InfpSubstituteString(Context->Inf,
Ptr,
ReturnBuffer,
ReturnBufferSize);
}
return INF_STATUS_SUCCESS;
}
INFSTATUS
InfpGetData(PINFCONTEXT Context,
PWCHAR *Key,
PWCHAR *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,
PWCHAR *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,86 @@
/*
* PROJECT: .inf file parser
* LICENSE: GPL - See COPYING in the top level directory
* PROGRAMMER: Royce Mitchell III
* Eric Kohl
* Ge van Geldorp <gvg@reactos.org>
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include "infcommon.h"
extern NTSTATUS NTAPI RtlMultiByteToUnicodeN(IN PWCHAR UnicodeString,
IN ULONG UnicodeSize, IN PULONG ResultSize, IN PCSTR MbString, IN ULONG MbSize);
extern BOOLEAN NTAPI RtlIsTextUnicode( PVOID buf, INT len, INT *pf );
extern int InfHostOpenBufferedFile(PHINF InfHandle,
void *Buffer,
ULONG BufferSize,
LCID LocaleId,
ULONG *ErrorLine);
extern int InfHostOpenFile(PHINF InfHandle,
const CHAR *FileName,
LCID LocaleId,
ULONG *ErrorLine);
extern int InfHostWriteFile(HINF InfHandle,
const CHAR *FileName,
const CHAR *HeaderComment);
extern void InfHostCloseFile(HINF InfHandle);
extern int InfHostFindFirstLine(HINF InfHandle,
const WCHAR *Section,
const WCHAR *Key,
PINFCONTEXT *Context);
extern int InfHostFindNextLine(PINFCONTEXT ContextIn,
PINFCONTEXT ContextOut);
extern int InfHostFindFirstMatchLine(PINFCONTEXT ContextIn,
const WCHAR *Key,
PINFCONTEXT ContextOut);
extern int InfHostFindNextMatchLine(PINFCONTEXT ContextIn,
const WCHAR *Key,
PINFCONTEXT ContextOut);
extern LONG InfHostGetLineCount(HINF InfHandle,
const WCHAR *Section);
extern LONG InfHostGetFieldCount(PINFCONTEXT Context);
extern int InfHostGetBinaryField(PINFCONTEXT Context,
ULONG FieldIndex,
UCHAR *ReturnBuffer,
ULONG ReturnBufferSize,
ULONG *RequiredSize);
extern int InfHostGetIntField(PINFCONTEXT Context,
ULONG FieldIndex,
ULONG *IntegerValue);
extern int InfHostGetMultiSzField(PINFCONTEXT Context,
ULONG FieldIndex,
WCHAR *ReturnBuffer,
ULONG ReturnBufferSize,
ULONG *RequiredSize);
extern int InfHostGetStringField(PINFCONTEXT Context,
ULONG FieldIndex,
WCHAR *ReturnBuffer,
ULONG ReturnBufferSize,
ULONG *RequiredSize);
extern int InfHostGetData(PINFCONTEXT Context,
WCHAR **Key,
WCHAR **Data);
extern int InfHostGetDataField(PINFCONTEXT Context,
ULONG FieldIndex,
WCHAR **Data);
extern int InfHostFindOrAddSection(HINF InfHandle,
const WCHAR *Section,
PINFCONTEXT *Context);
extern int InfHostAddLine(PINFCONTEXT Context, const WCHAR *Key);
extern int InfHostAddField(PINFCONTEXT Context, const WCHAR *Data);
extern void InfHostFreeContext(PINFCONTEXT Context);
#ifdef __cplusplus
}
#endif /* __cplusplus */
/* EOF */

View file

@ -0,0 +1,316 @@
/*
* PROJECT: .inf file parser
* LICENSE: GPL - See COPYING in the top level directory
* PROGRAMMER: Royce Mitchell III
* Eric Kohl
* Ge van Geldorp <gvg@reactos.org>
*/
/* INCLUDES *****************************************************************/
#include "inflib.h"
#include "infhost.h"
#define NDEBUG
#include <debug.h>
/* PUBLIC FUNCTIONS *********************************************************/
int
InfHostOpenBufferedFile(PHINF InfHandle,
void *Buffer,
ULONG BufferSize,
LCID LocaleId,
ULONG *ErrorLine)
{
INFSTATUS Status;
PINFCACHE Cache;
WCHAR *FileBuffer;
ULONG FileBufferSize;
*InfHandle = NULL;
*ErrorLine = (ULONG)-1;
/* Allocate file buffer */
FileBufferSize = BufferSize + 2;
FileBuffer = MALLOC(FileBufferSize);
if (FileBuffer == NULL)
{
DPRINT1("MALLOC() failed\n");
return(INF_STATUS_INSUFFICIENT_RESOURCES);
}
MEMCPY(FileBuffer, Buffer, BufferSize);
/* Append string terminator */
FileBuffer[BufferSize] = 0;
FileBuffer[BufferSize + 1] = 0;
/* Allocate infcache header */
Cache = (PINFCACHE)MALLOC(sizeof(INFCACHE));
if (Cache == NULL)
{
DPRINT1("MALLOC() failed\n");
FREE(FileBuffer);
return(INF_STATUS_INSUFFICIENT_RESOURCES);
}
/* Initialize inicache header */
ZEROMEMORY(Cache,
sizeof(INFCACHE));
Cache->LocaleId = LocaleId;
if (!RtlIsTextUnicode(FileBuffer, (INT)FileBufferSize, NULL))
{
// static const BYTE utf8_bom[3] = { 0xef, 0xbb, 0xbf };
WCHAR *new_buff;
// UINT codepage = CP_ACP;
UINT offset = 0;
// if (BufferSize > sizeof(utf8_bom) && !memcmp(FileBuffer, utf8_bom, sizeof(utf8_bom) ))
// {
// codepage = CP_UTF8;
// offset = sizeof(utf8_bom);
// }
new_buff = MALLOC(FileBufferSize * sizeof(WCHAR));
if (new_buff != NULL)
{
// DWORD len = MultiByteToWideChar( codepage, 0, (char *)FileBuffer + offset,
// FileBufferSize - offset, new_buff, FileBufferSize);
ULONG len;
Status = RtlMultiByteToUnicodeN(new_buff,
FileBufferSize * sizeof(WCHAR),
&len,
(char *)FileBuffer + offset,
FileBufferSize - offset);
Status = InfpParseBuffer(Cache,
new_buff,
new_buff + len / sizeof(WCHAR),
ErrorLine);
FREE(new_buff);
}
else
Status = INF_STATUS_INSUFFICIENT_RESOURCES;
}
else
{
WCHAR *new_buff = (WCHAR *)FileBuffer;
/* UCS-16 files should start with the Unicode BOM; we should skip it */
if (*new_buff == 0xfeff)
{
new_buff++;
FileBufferSize -= sizeof(WCHAR);
}
Status = InfpParseBuffer(Cache,
new_buff,
(WCHAR*)((char*)new_buff + FileBufferSize),
ErrorLine);
}
/* 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,
const CHAR *FileName,
LCID LocaleId,
ULONG *ErrorLine)
{
FILE *File;
CHAR *FileBuffer;
ULONG FileLength;
ULONG FileBufferLength;
PINFCACHE Cache;
INFSTATUS Status = INF_STATUS_SUCCESS;
*InfHandle = NULL;
*ErrorLine = (ULONG)-1;
/* Open the inf file */
File = fopen(FileName, "rb");
if (NULL == File)
{
DPRINT1("fopen() failed (errno %d)\n", errno);
return -1;
}
DPRINT("fopen() successful\n");
/* Query file size */
if (fseek(File, (size_t)0, SEEK_END))
{
DPRINT1("fseek() to EOF failed (errno %d)\n", errno);
fclose(File);
return -1;
}
FileLength = (ULONG)ftell(File);
if ((ULONG) -1 == FileLength)
{
DPRINT1("ftell() failed (errno %d)\n", errno);
fclose(File);
return -1;
}
DPRINT("File size: %u\n", (UINT)FileLength);
/* Rewind */
if (fseek(File, (size_t)0, SEEK_SET))
{
DPRINT1("fseek() to BOF failed (errno %d)\n", errno);
fclose(File);
return -1;
}
/* Allocate file buffer */
FileBufferLength = FileLength + 2;
FileBuffer = MALLOC(FileBufferLength);
if (FileBuffer == NULL)
{
DPRINT1("MALLOC() failed\n");
fclose(File);
return -1;
}
/* Read file */
if (FileLength != fread(FileBuffer, (size_t)1, (size_t)FileLength, File))
{
DPRINT1("fread() failed (errno %d)\n", errno);
fclose(File);
return -1;
}
fclose(File);
/* Append string terminator */
FileBuffer[FileLength] = 0;
FileBuffer[FileLength + 1] = 0;
/* Allocate infcache header */
Cache = (PINFCACHE)MALLOC(sizeof(INFCACHE));
if (Cache == NULL)
{
DPRINT1("MALLOC() failed\n");
FREE(FileBuffer);
return -1;
}
/* Initialize inicache header */
ZEROMEMORY(Cache,
sizeof(INFCACHE));
Cache->LocaleId = LocaleId;
/* Parse the inf buffer */
if (!RtlIsTextUnicode(FileBuffer, (INT)FileBufferLength, NULL))
{
// static const BYTE utf8_bom[3] = { 0xef, 0xbb, 0xbf };
WCHAR *new_buff;
// UINT codepage = CP_ACP;
UINT offset = 0;
// if (FileLength > sizeof(utf8_bom) && !memcmp(FileBuffer, utf8_bom, sizeof(utf8_bom) ))
// {
// codepage = CP_UTF8;
// offset = sizeof(utf8_bom);
// }
new_buff = MALLOC(FileBufferLength * sizeof(WCHAR));
if (new_buff != NULL)
{
// DWORD len = MultiByteToWideChar( codepage, 0, (char *)FileBuffer + offset,
// FileLength - offset, new_buff, FileLength);
ULONG len;
Status = RtlMultiByteToUnicodeN(new_buff,
FileBufferLength * sizeof(WCHAR),
&len,
(char *)FileBuffer + offset,
FileBufferLength - offset);
Status = InfpParseBuffer(Cache,
new_buff,
new_buff + len / sizeof(WCHAR),
ErrorLine);
FREE(new_buff);
}
else
Status = INF_STATUS_INSUFFICIENT_RESOURCES;
}
else
{
WCHAR *new_buff = (WCHAR *)FileBuffer;
/* UCS-16 files should start with the Unicode BOM; we should skip it */
if (*new_buff == 0xfeff)
{
new_buff++;
FileBufferLength -= sizeof(WCHAR);
}
Status = InfpParseBuffer(Cache,
new_buff,
(WCHAR*)((char*)new_buff + FileBufferLength),
ErrorLine);
}
// 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 = InfpFreeSection(Cache->FirstSection);
}
Cache->LastSection = NULL;
FREE(Cache);
}
/* EOF */

View file

@ -0,0 +1,249 @@
/*
* PROJECT: .inf file parser
* LICENSE: GPL - See COPYING in the top level directory
* PROGRAMMER: Royce Mitchell III
* Eric Kohl
* Ge van Geldorp <gvg@reactos.org>
*/
/* INCLUDES *****************************************************************/
#include "inflib.h"
#include "infhost.h"
#define NDEBUG
#include <debug.h>
int
InfHostFindFirstLine(HINF InfHandle,
const WCHAR *Section,
const WCHAR *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 WCHAR *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 WCHAR *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,
PCWSTR Section)
{
return InfpGetLineCount(InfHandle, Section);
}
/* InfGetLineText */
LONG
InfHostGetFieldCount(PINFCONTEXT Context)
{
return InfpGetFieldCount(Context);
}
int
InfHostGetBinaryField(PINFCONTEXT Context,
ULONG FieldIndex,
UCHAR *ReturnBuffer,
ULONG ReturnBufferSize,
ULONG *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,
ULONG FieldIndex,
ULONG *IntegerValue)
{
INFSTATUS Status;
Status = InfpGetIntField(Context, FieldIndex, (PLONG)IntegerValue);
if (INF_SUCCESS(Status))
{
return 0;
}
else
{
errno = Status;
return -1;
}
}
int
InfHostGetMultiSzField(PINFCONTEXT Context,
ULONG FieldIndex,
WCHAR *ReturnBuffer,
ULONG ReturnBufferSize,
ULONG *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,
ULONG FieldIndex,
WCHAR *ReturnBuffer,
ULONG ReturnBufferSize,
ULONG *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,
WCHAR **Key,
WCHAR **Data)
{
INFSTATUS Status;
Status = InfpGetData(Context, Key, Data);
if (INF_SUCCESS(Status))
{
return 0;
}
else
{
errno = Status;
return -1;
}
}
int
InfHostGetDataField(PINFCONTEXT Context,
ULONG FieldIndex,
WCHAR **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,115 @@
/*
* PROJECT: .inf file parser
* LICENSE: GPL - See COPYING in the top level directory
* COPYRIGHT: Copyright 2005 Ge van Geldorp <gvg@reactos.org>
*/
/* INCLUDES *****************************************************************/
#include "inflib.h"
#include "infhost.h"
#define NDEBUG
#include <debug.h>
int
InfHostWriteFile(HINF InfHandle,
const CHAR *FileName,
const CHAR *HeaderComment)
{
WCHAR *Buffer;
ULONG BufferSize;
INFSTATUS Status;
FILE *File;
Status = InfpBuildFileBuffer((PINFCACHE) InfHandle, &Buffer, &BufferSize);
if (! INF_SUCCESS(Status))
{
errno = Status;
return -1;
}
File = fopen(FileName, "wb");
if (NULL == File)
{
FREE(Buffer);
DPRINT1("fopen() failed (errno %d)\n", errno);
return -1;
}
DPRINT("fopen() successful\n");
if (NULL != HeaderComment && '\0' != *HeaderComment)
{
// fprintf(File, "; %s\r\n\r\n", HeaderComment);
}
if (BufferSize != fwrite(Buffer, (size_t)1, (size_t)BufferSize, File))
{
DPRINT1("fwrite() failed (errno %d)\n", errno);
fclose(File);
FREE(Buffer);
return -1;
}
fclose(File);
FREE(Buffer);
return 0;
}
int
InfHostFindOrAddSection(HINF InfHandle,
const WCHAR *Section,
PINFCONTEXT *Context)
{
INFSTATUS Status;
Status = InfpFindOrAddSection((PINFCACHE) InfHandle, Section, Context);
if (INF_SUCCESS(Status))
{
return 0;
}
else
{
errno = Status;
return -1;
}
}
int
InfHostAddLine(PINFCONTEXT Context, const WCHAR *Key)
{
INFSTATUS Status;
Status = InfpAddLineWithKey(Context, Key);
if (INF_SUCCESS(Status))
{
return 0;
}
else
{
errno = Status;
return -1;
}
}
int
InfHostAddField(PINFCONTEXT Context, const WCHAR *Data)
{
INFSTATUS Status;
Status = InfpAddField(Context, Data);
if (INF_SUCCESS(Status))
{
return 0;
}
else
{
errno = Status;
return -1;
}
}
/* EOF */

View file

@ -0,0 +1,151 @@
/*
* PROJECT: .inf file parser
* LICENSE: GPL - See COPYING in the top level directory
* PROGRAMMER: Royce Mitchell III
* Eric Kohl
* Ge van Geldorp <gvg@reactos.org>
*/
/* INCLUDES *****************************************************************/
#include "inflib.h"
#include "infhost.h"
#define NDEBUG
#include <debug.h>
NTSTATUS NTAPI
RtlMultiByteToUnicodeN(
IN PWCHAR UnicodeString,
IN ULONG UnicodeSize,
IN PULONG ResultSize,
IN PCSTR MbString,
IN ULONG MbSize)
{
ULONG Size = 0;
ULONG i;
PUCHAR WideString;
/* single-byte code page */
if (MbSize > (UnicodeSize / sizeof(WCHAR)))
Size = UnicodeSize / sizeof(WCHAR);
else
Size = MbSize;
if (ResultSize != NULL)
*ResultSize = Size * sizeof(WCHAR);
WideString = (PUCHAR)UnicodeString;
for (i = 0; i <= Size; i++)
{
WideString[2 * i + 0] = (UCHAR)MbString[i];
WideString[2 * i + 1] = 0;
}
return STATUS_SUCCESS;
}
BOOLEAN
NTAPI
RtlIsTextUnicode( PVOID buf, INT len, INT *pf )
{
static const WCHAR std_control_chars[] = {'\r','\n','\t',' ',0x3000,0};
static const WCHAR byterev_control_chars[] = {0x0d00,0x0a00,0x0900,0x2000,0};
const WCHAR *s = buf;
int i;
unsigned int flags = MAXULONG, out_flags = 0;
if (len < sizeof(WCHAR))
{
/* FIXME: MSDN documents IS_TEXT_UNICODE_BUFFER_TOO_SMALL but there is no such thing... */
if (pf) *pf = 0;
return FALSE;
}
if (pf)
flags = (unsigned int)*pf;
/*
* Apply various tests to the text string. According to the
* docs, each test "passed" sets the corresponding flag in
* the output flags. But some of the tests are mutually
* exclusive, so I don't see how you could pass all tests ...
*/
/* Check for an odd length ... pass if even. */
if (len & 1) out_flags |= IS_TEXT_UNICODE_ODD_LENGTH;
if (((char *)buf)[len - 1] == 0)
len--; /* Windows seems to do something like that to avoid e.g. false IS_TEXT_UNICODE_NULL_BYTES */
len /= (INT)sizeof(WCHAR);
/* Windows only checks the first 256 characters */
if (len > 256) len = 256;
/* Check for the special byte order unicode marks. */
if (*s == 0xFEFF) out_flags |= IS_TEXT_UNICODE_SIGNATURE;
if (*s == 0xFFFE) out_flags |= IS_TEXT_UNICODE_REVERSE_SIGNATURE;
/* apply some statistical analysis */
if (flags & IS_TEXT_UNICODE_STATISTICS)
{
int stats = 0;
/* FIXME: checks only for ASCII characters in the unicode stream */
for (i = 0; i < len; i++)
{
if (s[i] <= 255) stats++;
}
if (stats > len / 2)
out_flags |= IS_TEXT_UNICODE_STATISTICS;
}
/* Check for unicode NULL chars */
if (flags & IS_TEXT_UNICODE_NULL_BYTES)
{
for (i = 0; i < len; i++)
{
if (!(s[i] & 0xff) || !(s[i] >> 8))
{
out_flags |= IS_TEXT_UNICODE_NULL_BYTES;
break;
}
}
}
if (flags & IS_TEXT_UNICODE_CONTROLS)
{
for (i = 0; i < len; i++)
{
if (wcschr(std_control_chars, s[i]))
{
out_flags |= IS_TEXT_UNICODE_CONTROLS;
break;
}
}
}
if (flags & IS_TEXT_UNICODE_REVERSE_CONTROLS)
{
for (i = 0; i < len; i++)
{
if (wcschr(byterev_control_chars, s[i]))
{
out_flags |= IS_TEXT_UNICODE_REVERSE_CONTROLS;
break;
}
}
}
if (pf)
{
out_flags &= (unsigned int)*pf;
*pf = (INT)out_flags;
}
/* check for flags that indicate it's definitely not valid Unicode */
if (out_flags & (IS_TEXT_UNICODE_REVERSE_MASK | IS_TEXT_UNICODE_NOT_UNICODE_MASK)) return FALSE;
/* now check for invalid ASCII, and assume Unicode if so */
if (out_flags & IS_TEXT_UNICODE_NOT_ASCII_MASK) return TRUE;
/* now check for Unicode flags */
if (out_flags & IS_TEXT_UNICODE_UNICODE_MASK) return TRUE;
/* no flags set */
return FALSE;
}

View file

@ -0,0 +1,15 @@
/*
* PROJECT: .inf file parser
* LICENSE: GPL - See COPYING in the top level directory
* COPYRIGHT: Copyright 2005 Ge van Geldorp <gvg@reactos.org>
*/
#include <ctype.h>
#include <stddef.h>
#include <stdlib.h>
#include "builddep.h"
#include "infcommon.h"
#include "infpriv.h"
/* EOF */

View file

@ -0,0 +1,76 @@
INFLIB_BASE = $(LIB_BASE_)newinflib
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)newinflib.a
INFLIB_HOST_SOURCES = $(addprefix $(INFLIB_BASE_), \
infcore.c \
infget.c \
infput.c \
infhostgen.c \
infhostget.c \
infhostput.c \
infhostrtl.c \
)
INFLIB_HOST_OBJECTS = \
$(subst $(INFLIB_BASE), $(INFLIB_INT), $(INFLIB_HOST_SOURCES:.c=.o))
INFLIB_HOST_CFLAGS = -O3 -Wall -Wpointer-arith -Wconversion \
-Wstrict-prototypes -Wmissing-prototypes -DINFLIB_HOST \
-Iinclude/reactos -Iinclude $(HOST_CFLAGS)
$(INFLIB_HOST_TARGET): $(INFLIB_HOST_OBJECTS) | $(INFLIB_OUT)
$(ECHO_HOSTAR)
$(host_ar) -r $@ $(INFLIB_HOST_OBJECTS)
$(INFLIB_INT_)infcore.o: $(INFLIB_BASE_)infcore.c | $(INFLIB_INT)
$(ECHO_HOSTCC)
${host_gcc} $(INFLIB_HOST_CFLAGS) -c $< -o $@
$(INFLIB_INT_)infget.o: $(INFLIB_BASE_)infget.c | $(INFLIB_INT)
$(ECHO_HOSTCC)
${host_gcc} $(INFLIB_HOST_CFLAGS) -c $< -o $@
$(INFLIB_INT_)infput.o: $(INFLIB_BASE_)infput.c | $(INFLIB_INT)
$(ECHO_HOSTCC)
${host_gcc} $(INFLIB_HOST_CFLAGS) -c $< -o $@
$(INFLIB_INT_)infhostgen.o: $(INFLIB_BASE_)infhostgen.c | $(INFLIB_INT)
$(ECHO_HOSTCC)
${host_gcc} $(INFLIB_HOST_CFLAGS) -c $< -o $@
$(INFLIB_INT_)infhostget.o: $(INFLIB_BASE_)infhostget.c | $(INFLIB_INT)
$(ECHO_HOSTCC)
${host_gcc} $(INFLIB_HOST_CFLAGS) -c $< -o $@
$(INFLIB_INT_)infhostput.o: $(INFLIB_BASE_)infhostput.c | $(INFLIB_INT)
$(ECHO_HOSTCC)
${host_gcc} $(INFLIB_HOST_CFLAGS) -c $< -o $@
$(INFLIB_INT_)infhostrtl.o: $(INFLIB_BASE_)infhostrtl.c | $(INFLIB_INT)
$(ECHO_HOSTCC)
${host_gcc} $(INFLIB_HOST_CFLAGS) -c $< -o $@
.PHONY: newinflib_host
newinflib_host: $(INFLIB_HOST_TARGET)
.PHONY: newinflib_host_clean
newinflib_host_clean:
-@$(rm) $(INFLIB_HOST_TARGET) $(INFLIB_HOST_OBJECTS) 2>$(NUL)
clean: newinflib_host_clean

View file

@ -0,0 +1,31 @@
<?xml version="1.0"?>
<!DOCTYPE module SYSTEM "../../tools/rbuild/project.dtd">
<group>
<module name="newinflib" type="staticlibrary">
<include base="newinflib">.</include>
<file>infcore.c</file>
<file>infget.c</file>
<file>infput.c</file>
<file>infrosgen.c</file>
<file>infrosget.c</file>
<file>infrosput.c</file>
</module>
<module name="newinflibhost" type="hoststaticlibrary" allowwarnings="true">
<include base="newinflibhost">.</include>
<define name="__NO_CTYPE_INLINES" />
<group compilerset="gcc">
<compilerflag>-Wpointer-arith</compilerflag>
<compilerflag>-Wconversion</compilerflag>
<compilerflag>-Wstrict-prototypes</compilerflag>
<compilerflag>-Wmissing-prototypes</compilerflag>
</group>
<define name="INFLIB_HOST" />
<file>infcore.c</file>
<file>infget.c</file>
<file>infput.c</file>
<file>infhostgen.c</file>
<file>infhostget.c</file>
<file>infhostput.c</file>
<file>infhostrtl.c</file>
</module>
</group>

View file

@ -0,0 +1,145 @@
/*
* PROJECT: .inf file parser
* LICENSE: GPL - See COPYING in the top level directory
* PROGRAMMER: Royce Mitchell III
* Eric Kohl
* Ge van Geldorp <gvg@reactos.org>
*/
#pragma once
#ifndef FIELD_OFFSET
#define FIELD_OFFSET(t,f) ((ptrdiff_t)&(((t*)0)->f))
#endif
#define INF_STATUS_INSUFFICIENT_RESOURCES ((INFSTATUS)0xC000009A)
#define INF_STATUS_BAD_SECTION_NAME_LINE ((INFSTATUS)0xC0700001)
#define INF_STATUS_SECTION_NAME_TOO_LONG ((INFSTATUS)0xC0700002)
#define INF_STATUS_WRONG_INF_STYLE ((INFSTATUS)0xC0700003)
#define INF_STATUS_NOT_ENOUGH_MEMORY ((INFSTATUS)0xC0700004)
typedef struct _INFCACHEFIELD
{
struct _INFCACHEFIELD *Next;
struct _INFCACHEFIELD *Prev;
WCHAR Data[1];
} INFCACHEFIELD, *PINFCACHEFIELD;
typedef struct _INFCACHELINE
{
struct _INFCACHELINE *Next;
struct _INFCACHELINE *Prev;
LONG FieldCount;
PWCHAR Key;
PINFCACHEFIELD FirstField;
PINFCACHEFIELD LastField;
} INFCACHELINE, *PINFCACHELINE;
typedef struct _INFCACHESECTION
{
struct _INFCACHESECTION *Next;
struct _INFCACHESECTION *Prev;
PINFCACHELINE FirstLine;
PINFCACHELINE LastLine;
LONG LineCount;
WCHAR Name[1];
} INFCACHESECTION, *PINFCACHESECTION;
typedef struct _INFCACHE
{
LCID LocaleId;
PINFCACHESECTION FirstSection;
PINFCACHESECTION LastSection;
PINFCACHESECTION StringsSection;
} INFCACHE, *PINFCACHE;
typedef struct _INFCONTEXT
{
PINFCACHE Inf;
PINFCACHESECTION Section;
PINFCACHELINE Line;
} INFCONTEXT;
typedef int INFSTATUS;
/* FUNCTIONS ****************************************************************/
extern INFSTATUS InfpParseBuffer(PINFCACHE file,
const WCHAR *buffer,
const WCHAR *end,
PULONG error_line);
extern PINFCACHESECTION InfpFreeSection(PINFCACHESECTION Section);
extern PINFCACHESECTION InfpAddSection(PINFCACHE Cache,
PCWSTR Name);
extern PINFCACHELINE InfpAddLine(PINFCACHESECTION Section);
extern PVOID InfpAddKeyToLine(PINFCACHELINE Line,
PCWSTR Key);
extern PVOID InfpAddFieldToLine(PINFCACHELINE Line,
PCWSTR Data);
extern PINFCACHELINE InfpFindKeyLine(PINFCACHESECTION Section,
PCWSTR Key);
extern PINFCACHESECTION InfpFindSection(PINFCACHE Cache,
PCWSTR Section);
extern INFSTATUS InfpBuildFileBuffer(PINFCACHE InfHandle,
PWCHAR *Buffer,
PULONG BufferSize);
extern INFSTATUS InfpFindFirstLine(PINFCACHE InfHandle,
PCWSTR Section,
PCWSTR Key,
PINFCONTEXT *Context);
extern INFSTATUS InfpFindNextLine(PINFCONTEXT ContextIn,
PINFCONTEXT ContextOut);
extern INFSTATUS InfpFindFirstMatchLine(PINFCONTEXT ContextIn,
PCWSTR Key,
PINFCONTEXT ContextOut);
extern INFSTATUS InfpFindNextMatchLine(PINFCONTEXT ContextIn,
PCWSTR Key,
PINFCONTEXT ContextOut);
extern LONG InfpGetLineCount(HINF InfHandle,
PCWSTR 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,
PWSTR ReturnBuffer,
ULONG ReturnBufferSize,
PULONG RequiredSize);
extern INFSTATUS InfpGetStringField(PINFCONTEXT Context,
ULONG FieldIndex,
PWSTR ReturnBuffer,
ULONG ReturnBufferSize,
PULONG RequiredSize);
extern INFSTATUS InfpGetData(PINFCONTEXT Context,
PWCHAR *Key,
PWCHAR *Data);
extern INFSTATUS InfpGetDataField(PINFCONTEXT Context,
ULONG FieldIndex,
PWCHAR *Data);
extern INFSTATUS InfpFindOrAddSection(PINFCACHE Cache,
PCWSTR Section,
PINFCONTEXT *Context);
extern INFSTATUS InfpAddLineWithKey(PINFCONTEXT Context, PCWSTR Key);
extern INFSTATUS InfpAddField(PINFCONTEXT Context, PCWSTR Data);
extern VOID InfpFreeContext(PINFCONTEXT Context);
/* EOF */

View file

@ -0,0 +1,264 @@
/*
* PROJECT: .inf file parser
* LICENSE: GPL - See COPYING in the top level directory
* COPYRIGHT: Copyright 2005 Ge van Geldorp <gvg@reactos.org>
*/
/* INCLUDES *****************************************************************/
#include "inflib.h"
#define NDEBUG
#include <debug.h>
#define EOL L"\r\n"
#define SIZE_INC 1024
typedef struct _OUTPUTBUFFER
{
PWCHAR Buffer;
PWCHAR Current;
ULONG TotalSize;
ULONG FreeSize;
INFSTATUS Status;
} OUTPUTBUFFER, *POUTPUTBUFFER;
static void
Output(POUTPUTBUFFER OutBuf, PCWSTR Text)
{
ULONG Length;
PWCHAR NewBuf;
ULONG NewSize;
/* Skip mode? */
if (! INF_SUCCESS(OutBuf->Status))
{
return;
}
/* Doesn't fit? */
Length = (ULONG)wcslen(Text) * sizeof(WCHAR);
if (OutBuf->FreeSize < Length + 1 && INF_SUCCESS(OutBuf->Status))
{
DPRINT("Out of free space. TotalSize %u FreeSize %u Length %u\n",
(UINT)OutBuf->TotalSize, (UINT)OutBuf->FreeSize, (UINT)Length);
/* Round up to next SIZE_INC */
NewSize = OutBuf->TotalSize +
(((Length + 1) - OutBuf->FreeSize + (SIZE_INC - 1)) /
SIZE_INC) * SIZE_INC;
DPRINT("NewSize %u\n", (UINT)NewSize);
NewBuf = MALLOC(NewSize);
/* Abort if failed */
if (NULL == NewBuf)
{
DPRINT1("MALLOC() failed\n");
OutBuf->Status = INF_STATUS_NO_MEMORY;
return;
}
/* Need to copy old contents? */
if (NULL != OutBuf->Buffer)
{
DPRINT("Copying %u bytes from old content\n",
(UINT)(OutBuf->TotalSize - OutBuf->FreeSize));
MEMCPY(NewBuf, OutBuf->Buffer, OutBuf->TotalSize - OutBuf->FreeSize);
OutBuf->Current = NewBuf + (OutBuf->Current - OutBuf->Buffer);
FREE(OutBuf->Buffer);
}
else
{
OutBuf->Current = NewBuf;
}
OutBuf->Buffer = NewBuf;
OutBuf->FreeSize += NewSize - OutBuf->TotalSize;
OutBuf->TotalSize = NewSize;
DPRINT("After reallocation TotalSize %u FreeSize %u\n",
(UINT)OutBuf->TotalSize, (UINT)OutBuf->FreeSize);
}
/* We're guaranteed to have enough room now. Copy char by char because of
possible "conversion" from Unicode to Ansi */
while (Length--)
{
*OutBuf->Current++ = *Text++;
OutBuf->FreeSize--;
}
*OutBuf->Current = '\0';
}
INFSTATUS
InfpBuildFileBuffer(PINFCACHE Cache,
PWCHAR *Buffer,
PULONG BufferSize)
{
OUTPUTBUFFER OutBuf;
PINFCACHESECTION CacheSection;
PINFCACHELINE CacheLine;
PINFCACHEFIELD CacheField;
PWCHAR p;
BOOLEAN NeedQuotes;
OutBuf.Buffer = NULL;
OutBuf.Current = NULL;
OutBuf.FreeSize = 0;
OutBuf.TotalSize = 0;
OutBuf.Status = INF_STATUS_SUCCESS;
/* Iterate through list of sections */
CacheSection = Cache->FirstSection;
while (CacheSection != NULL)
{
DPRINT("Processing section %S\n", CacheSection->Name);
if (CacheSection != Cache->FirstSection)
{
Output(&OutBuf, EOL);
}
Output(&OutBuf, L"[");
Output(&OutBuf, CacheSection->Name);
Output(&OutBuf, L"]");
Output(&OutBuf, EOL);
/* Iterate through list of lines */
CacheLine = CacheSection->FirstLine;
while (CacheLine != NULL)
{
if (NULL != CacheLine->Key)
{
DPRINT("Line with key %S\n", CacheLine->Key);
Output(&OutBuf, CacheLine->Key);
Output(&OutBuf, L" = ");
}
else
{
DPRINT("Line without key\n");
}
/* Iterate through list of lines */
CacheField = CacheLine->FirstField;
while (CacheField != NULL)
{
if (CacheField != CacheLine->FirstField)
{
Output(&OutBuf, L",");
}
p = CacheField->Data;
NeedQuotes = FALSE;
while (L'\0' != *p && ! NeedQuotes)
{
NeedQuotes = (BOOLEAN)(L',' == *p || L';' == *p ||
L'\\' == *p);
p++;
}
if (NeedQuotes)
{
Output(&OutBuf, L"\"");
Output(&OutBuf, CacheField->Data);
Output(&OutBuf, L"\"");
}
else
{
Output(&OutBuf, CacheField->Data);
}
/* Get the next field */
CacheField = CacheField->Next;
}
Output(&OutBuf, EOL);
/* Get the next line */
CacheLine = CacheLine->Next;
}
/* Get the next section */
CacheSection = CacheSection->Next;
}
if (INF_SUCCESS(OutBuf.Status))
{
*Buffer = OutBuf.Buffer;
*BufferSize = OutBuf.TotalSize - OutBuf.FreeSize;
}
else if (NULL != OutBuf.Buffer)
{
FREE(OutBuf.Buffer);
}
return INF_STATUS_SUCCESS;
}
INFSTATUS
InfpFindOrAddSection(PINFCACHE Cache,
PCWSTR Section,
PINFCONTEXT *Context)
{
DPRINT("InfpFindOrAddSection section %S\n", Section);
*Context = MALLOC(sizeof(INFCONTEXT));
if (NULL == *Context)
{
DPRINT1("MALLOC() failed\n");
return INF_STATUS_NO_MEMORY;
}
(*Context)->Inf = Cache;
(*Context)->Section = InfpFindSection(Cache, Section);
(*Context)->Line = NULL;
if (NULL == (*Context)->Section)
{
DPRINT("Section not found, creating it\n");
(*Context)->Section = InfpAddSection(Cache, Section);
if (NULL == (*Context)->Section)
{
DPRINT("Failed to create section\n");
FREE(*Context);
return INF_STATUS_NO_MEMORY;
}
}
return INF_STATUS_SUCCESS;
}
INFSTATUS
InfpAddLineWithKey(PINFCONTEXT Context, PCWSTR Key)
{
if (NULL == Context)
{
DPRINT1("Invalid parameter\n");
return INF_STATUS_INVALID_PARAMETER;
}
Context->Line = InfpAddLine(Context->Section);
if (NULL == Context->Line)
{
DPRINT("Failed to create line\n");
return INF_STATUS_NO_MEMORY;
}
if (NULL != Key && NULL == InfpAddKeyToLine(Context->Line, Key))
{
DPRINT("Failed to add key\n");
return INF_STATUS_NO_MEMORY;
}
return INF_STATUS_SUCCESS;
}
INFSTATUS
InfpAddField(PINFCONTEXT Context, PCWSTR Data)
{
if (NULL == Context || NULL == Context->Line)
{
DPRINT1("Invalid parameter\n");
return INF_STATUS_INVALID_PARAMETER;
}
if (NULL == InfpAddFieldToLine(Context->Line, Data))
{
DPRINT("Failed to add field\n");
return INF_STATUS_NO_MEMORY;
}
return INF_STATUS_SUCCESS;
}
/* EOF */

View file

@ -0,0 +1,81 @@
/*
* PROJECT: .inf file parser
* LICENSE: GPL - See COPYING in the top level directory
* PROGRAMMER: Royce Mitchell III
* Eric Kohl
* Ge van Geldorp <gvg@reactos.org>
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include <infcommon.h>
extern VOID InfSetHeap(PVOID Heap);
extern NTSTATUS InfOpenBufferedFile(PHINF InfHandle,
PVOID Buffer,
ULONG BufferSize,
LCID LocaleId,
PULONG ErrorLine);
extern NTSTATUS InfOpenFile(PHINF InfHandle,
PUNICODE_STRING FileName,
LCID LocaleId,
PULONG ErrorLine);
extern NTSTATUS InfWriteFile(HINF InfHandle,
PUNICODE_STRING FileName,
PUNICODE_STRING HeaderComment);
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 BOOLEAN InfFindOrAddSection(HINF InfHandle,
PCWSTR Section,
PINFCONTEXT *Context);
extern BOOLEAN InfAddLine(PINFCONTEXT Context, PCWSTR Key);
extern BOOLEAN InfAddField(PINFCONTEXT Context, PCWSTR Data);
extern VOID InfFreeContext(PINFCONTEXT Context);
#ifdef __cplusplus
}
#endif /* __cplusplus */
/* EOF */

View file

@ -0,0 +1,370 @@
/*
* PROJECT: .inf file parser
* LICENSE: GPL - See COPYING in the top level directory
* PROGRAMMER: Royce Mitchell III
* Eric Kohl
* Ge van Geldorp <gvg@reactos.org>
*/
/* 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,
LCID LocaleId,
PULONG ErrorLine)
{
INFSTATUS Status;
PINFCACHE Cache;
PCHAR FileBuffer;
ULONG FileBufferSize;
CheckHeap();
*InfHandle = NULL;
*ErrorLine = (ULONG)-1;
/* Allocate file buffer */
FileBufferSize = BufferSize + 2;
FileBuffer = MALLOC(FileBufferSize);
if (FileBuffer == NULL)
{
DPRINT1("MALLOC() failed\n");
return(INF_STATUS_INSUFFICIENT_RESOURCES);
}
MEMCPY(FileBuffer, Buffer, BufferSize);
/* Append string terminator */
FileBuffer[BufferSize] = 0;
FileBuffer[BufferSize + 1] = 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));
Cache->LocaleId = LocaleId;
if (!RtlIsTextUnicode(FileBuffer, FileBufferSize, NULL))
{
// static const BYTE utf8_bom[3] = { 0xef, 0xbb, 0xbf };
WCHAR *new_buff;
// UINT codepage = CP_ACP;
UINT offset = 0;
// if (BufferSize > sizeof(utf8_bom) && !memcmp(FileBuffer, utf8_bom, sizeof(utf8_bom) ))
// {
// codepage = CP_UTF8;
// offset = sizeof(utf8_bom);
// }
new_buff = MALLOC(FileBufferSize * sizeof(WCHAR));
if (new_buff != NULL)
{
// DWORD len = MultiByteToWideChar( codepage, 0, (char *)FileBuffer + offset,
// FileBufferSize - offset, new_buff, FileBufferSize);
ULONG len;
Status = RtlMultiByteToUnicodeN(new_buff,
FileBufferSize * sizeof(WCHAR),
&len,
(char *)FileBuffer + offset,
FileBufferSize - offset);
Status = InfpParseBuffer(Cache,
new_buff,
new_buff + len,
ErrorLine);
FREE(new_buff);
}
else
Status = INF_STATUS_INSUFFICIENT_RESOURCES;
}
else
{
WCHAR *new_buff = (WCHAR *)FileBuffer;
/* UCS-16 files should start with the Unicode BOM; we should skip it */
if (*new_buff == 0xfeff)
{
new_buff++;
FileBufferSize -= sizeof(WCHAR);
}
Status = InfpParseBuffer(Cache,
new_buff,
(WCHAR*)((char*)new_buff + FileBufferSize),
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,
LCID LocaleId,
PULONG ErrorLine)
{
OBJECT_ATTRIBUTES ObjectAttributes;
FILE_STANDARD_INFORMATION FileInfo;
IO_STATUS_BLOCK IoStatusBlock;
HANDLE FileHandle;
NTSTATUS Status;
PCHAR FileBuffer;
ULONG FileLength;
ULONG FileBufferLength;
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 */
FileBufferLength = FileLength + 2;
FileBuffer = MALLOC(FileBufferLength);
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;
FileBuffer[FileLength + 1] = 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));
Cache->LocaleId = LocaleId;
/* Parse the inf buffer */
if (!RtlIsTextUnicode(FileBuffer, FileBufferLength, NULL))
{
// static const BYTE utf8_bom[3] = { 0xef, 0xbb, 0xbf };
WCHAR *new_buff;
// UINT codepage = CP_ACP;
UINT offset = 0;
// if (FileLength > sizeof(utf8_bom) && !memcmp(FileBuffer, utf8_bom, sizeof(utf8_bom) ))
// {
// codepage = CP_UTF8;
// offset = sizeof(utf8_bom);
// }
new_buff = MALLOC(FileBufferLength * sizeof(WCHAR));
if (new_buff != NULL)
{
// DWORD len = MultiByteToWideChar( codepage, 0, (char *)FileBuffer + offset,
// FileLength - offset, new_buff, FileLength);
ULONG len;
Status = RtlMultiByteToUnicodeN(new_buff,
FileBufferLength * sizeof(WCHAR),
&len,
(char *)FileBuffer + offset,
FileBufferLength - offset);
Status = InfpParseBuffer(Cache,
new_buff,
new_buff + len,
ErrorLine);
FREE(new_buff);
}
else
Status = INF_STATUS_INSUFFICIENT_RESOURCES;
}
else
{
WCHAR *new_buff = (WCHAR *)FileBuffer;
/* UCS-16 files should start with the Unicode BOM; we should skip it */
if (*new_buff == 0xfeff)
{
new_buff++;
FileBufferLength -= sizeof(WCHAR);
}
Status = InfpParseBuffer(Cache,
new_buff,
(WCHAR*)((char*)new_buff + FileBufferLength),
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 = InfpFreeSection(Cache->FirstSection);
}
Cache->LastSection = NULL;
FREE(Cache);
if (0 < InfpHeapRefCount)
{
InfpHeapRefCount--;
if (0 == InfpHeapRefCount)
{
RtlDestroyHeap(InfpHeap);
InfpHeap = NULL;
}
}
}
/* EOF */

View file

@ -0,0 +1,140 @@
/*
* PROJECT: .inf file parser
* LICENSE: GPL - See COPYING in the top level directory
* PROGRAMMER: Royce Mitchell III
* Eric Kohl
* Ge van Geldorp <gvg@reactos.org>
*/
/* 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

@ -0,0 +1,132 @@
/*
* PROJECT: .inf file parser
* LICENSE: GPL - See COPYING in the top level directory
* COPYRIGHT: Copyright 2005 Ge van Geldorp <gvg@reactos.org>
*/
/* INCLUDES *****************************************************************/
#include "inflib.h"
#include "infros.h"
#define NDEBUG
#include <debug.h>
NTSTATUS
InfWriteFile(HINF InfHandle,
PUNICODE_STRING FileName,
PUNICODE_STRING HeaderComment)
{
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
HANDLE FileHandle;
NTSTATUS Status;
INFSTATUS InfStatus;
PWCHAR Buffer;
ULONG BufferSize;
PWCHAR HeaderBuffer;
ULONG HeaderBufferSize;
UINT Index;
InfStatus = InfpBuildFileBuffer((PINFCACHE) InfHandle, &Buffer, &BufferSize);
if (! INF_SUCCESS(InfStatus))
{
DPRINT("Failed to create buffer (Status 0x%lx)\n", InfStatus);
return InfStatus;
}
/* Open the inf file */
InitializeObjectAttributes(&ObjectAttributes,
FileName,
0,
NULL,
NULL);
Status = NtOpenFile(&FileHandle,
GENERIC_WRITE | SYNCHRONIZE,
&ObjectAttributes,
&IoStatusBlock,
0,
FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE);
if (!INF_SUCCESS(Status))
{
DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
FREE(Buffer);
return Status;
}
DPRINT("NtOpenFile() successful\n");
if (NULL != HeaderComment && 0 != HeaderComment->Length)
{
/* This is just a comment header, don't abort on errors here */
HeaderBufferSize = HeaderComment->Length + 7 * sizeof(WCHAR);
HeaderBuffer = MALLOC(HeaderBufferSize);
if (NULL != HeaderBuffer)
{
wcscpy(HeaderBuffer, L"; ");
for (Index = 0; Index < HeaderComment->Length / sizeof(WCHAR); Index++)
{
HeaderBuffer[2 + Index] = HeaderComment->Buffer[Index];
}
wcscpy(HeaderBuffer + (2 + HeaderComment->Length / sizeof(WCHAR)),
L"\r\n\r\n");
NtWriteFile(FileHandle,
NULL,
NULL,
NULL,
&IoStatusBlock,
HeaderBuffer,
HeaderBufferSize,
NULL,
NULL);
FREE(HeaderBuffer);
}
}
/* Write main contents */
Status = NtWriteFile(FileHandle,
NULL,
NULL,
NULL,
&IoStatusBlock,
Buffer,
BufferSize,
NULL,
NULL);
NtClose(FileHandle);
FREE(Buffer);
if (!INF_SUCCESS(Status))
{
DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
FREE(Buffer);
return(Status);
}
return STATUS_SUCCESS;
}
BOOLEAN
InfFindOrAddSection(HINF InfHandle,
PCWSTR Section,
PINFCONTEXT *Context)
{
return INF_SUCCESS(InfpFindOrAddSection((PINFCACHE) InfHandle,
Section, Context));
}
BOOLEAN
InfHostAddLine(PINFCONTEXT Context, PCWSTR Key)
{
return INF_SUCCESS(InfpAddLineWithKey(Context, Key));
}
BOOLEAN
InfHostAddField(PINFCONTEXT Context, PCWSTR Data)
{
return INF_SUCCESS(InfpAddField(Context, Data));
}
/* EOF */