- Added .inf-file parser
authorEric Kohl <eric.kohl@reactos.org>
Sun, 25 May 2003 21:20:43 +0000 (21:20 +0000)
committerEric Kohl <eric.kohl@reactos.org>
Sun, 25 May 2003 21:20:43 +0000 (21:20 +0000)
- SetupLdr loads and uses txtsetup.sif
- Removed .hiv (text-hive) parser

svn path=/trunk/; revision=4758

12 files changed:
freeldr/freeldr/CHANGELOG
freeldr/freeldr/Makefile
freeldr/freeldr/include/inffile.h [new file with mode: 0644]
freeldr/freeldr/include/version.h
freeldr/freeldr/inffile/inffile.c [new file with mode: 0644]
freeldr/freeldr/inifile/inifile.c
freeldr/freeldr/miscboot.c
freeldr/freeldr/multiboot.c
freeldr/freeldr/reactos/reactos.c
freeldr/freeldr/reactos/reghive.c [deleted file]
freeldr/freeldr/reactos/registry.h
freeldr/freeldr/reactos/setupldr.c

index b1ec4b2..701cde5 100644 (file)
@@ -1,3 +1,9 @@
+Changes in v1.8.12 (5/25/2003) (ekohl)
+
+- Added .inf-file parser
+- SetupLdr loads and uses txtsetup.sif
+- Removed .hiv (text-hive) parser
+
 Changes in v1.8.11 (4/30/2003) (ekohl)
 
 - Added DiskGetExtendedDriveParameters()
index 2ca3864..18dd306 100644 (file)
@@ -233,9 +233,7 @@ UI_OBJS             =       tui.o           \
                                ui.o            \
                                gui.o
 
-REACTOS_OBJS=  reactos.o       \
-                               arcname.o       \
-                               reghive.o       \
+REACTOS_OBJS=  arcname.o       \
                                binhive.o       \
                                registry.o
 
@@ -255,6 +253,8 @@ INIFILE_OBJS=       inifile.o       \
                                ini_init.o      \
                                parse.o
 
+INFFILE_OBJS=  inffile.o
+
 VIDEO_OBJS     =       video.o         \
                                vidmode.o       \
                                fade.o          \
@@ -269,17 +269,19 @@ MATH_OBJS =       libgcc2.o
 
 BASE_OBJS      =       freeldr.o \
                                debug.o \
-                               drivemap.o \
                                multiboot.o     \
                                version.o
 
 FREELDR_OBJS=  bootmgr.o \
+                               drivemap.o \
                                miscboot.o \
                                options.o \
                                linuxboot.o     \
                                oslist.o \
                                custom.o
 
+ROSLDR_OBJS =  reactos.o
+
 SETUPLDR_OBJS= setupldr.o
 
 COMMON_OBJS    =       $(ARCH_OBJS)            \
@@ -291,23 +293,33 @@ COMMON_OBJS       =       $(ARCH_OBJS)            \
                                $(DISK_OBJS)            \
                                $(MM_OBJS)                      \
                                $(CACHE_OBJS)           \
-                               $(INIFILE_OBJS)         \
                                $(VIDEO_OBJS)           \
                                $(MATH_OBJS)            \
                                $(BASE_OBJS)
 
+SPECIAL_OBJS = $(INIFILE_OBJS)         \
+                               $(INFFILE_OBJS)         \
+                               $(FREELDR_OBJS)         \
+                               $(ROSLDR_OBJS)          \
+                               $(SETUPLDR_OBJS)
+                               
+
 F_OBJS         =       $(COMMON_OBJS)          \
+                               $(INIFILE_OBJS)         \
+                               $(ROSLDR_OBJS)          \
                                $(FREELDR_OBJS)
 
 S_OBJS         =       $(COMMON_OBJS)          \
+                               $(INIFILE_OBJS)         \
+                               $(INFFILE_OBJS)         \
                                $(SETUPLDR_OBJS)
 
+
 #############################################
 # ALL THE OBJECTS
 #
 ALL_OBJS       =       $(COMMON_OBJS)          \
-                               $(FREELDR_OBJS)         \
-                               $(SETUPLDR_OBJS)
+                               $(SPECIAL_OBJS)
 
 
 #############################################
@@ -324,6 +336,7 @@ VPATH               =       $(SRCDIR)/                                      \
                                $(SRCDIR)/mm                            \
                                $(SRCDIR)/cache                         \
                                $(SRCDIR)/inifile                       \
+                               $(SRCDIR)/inffile                       \
                                $(SRCDIR)/video                         \
                                $(SRCDIR)/math                          \
                                $(SRCDIR)/include
@@ -347,7 +360,6 @@ freeldr.sys : $(ALL_OBJS)
 
 setupldr.sys : $(ALL_OBJS)
        @echo ===================================================== LINKING $@
-#      @$(LD) -N -Ttext=0x8000 --oformat=binary -s -o setupldr.sys $(S_OBJS)
        @$(LD) $(LFLAGS) -Map setupldr.map -o setupldr.exe $(S_OBJS)
        @$(NM) --numeric-sort setupldr.exe > setupldr.sym
        @$(OBJCOPY) -O binary setupldr.exe setupldr.sys
diff --git a/freeldr/freeldr/include/inffile.h b/freeldr/freeldr/include/inffile.h
new file mode 100644 (file)
index 0000000..aa33414
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ *  ReactOS kernel
+ *  Copyright (C) 2002, 2003 ReactOS Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* $Id: inffile.h,v 1.1 2003/05/25 21:17:30 ekohl Exp $
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS text-mode setup
+ * FILE:            subsys/system/usetup/infcache.h
+ * PURPOSE:         INF file parser that caches contents of INF file in memory
+ * PROGRAMMER:      Royce Mitchell III
+ *                  Eric Kohl
+ */
+
+#ifndef __INFCACHE_H__
+#define __INFCACHE_H__
+
+
+#define STATUS_BAD_SECTION_NAME_LINE   (0xC0700001)
+#define STATUS_SECTION_NAME_TOO_LONG   (0xC0700002)
+#define STATUS_WRONG_INF_STYLE         (0xC0700003)
+#define STATUS_NOT_ENOUGH_MEMORY       (0xC0700004)
+
+#define MAX_INF_STRING_LENGTH  512
+
+typedef PU32 HINF, *PHINF;
+
+typedef struct _INFCONTEXT
+{
+  PVOID Inf;
+//  PVOID CurrentInf;
+  PVOID Section;
+  PVOID Line;
+} INFCONTEXT, *PINFCONTEXT;
+
+
+/* FUNCTIONS ****************************************************************/
+
+BOOLEAN
+InfOpenFile (PHINF InfHandle,
+            PCHAR FileName,
+            PU32 ErrorLine);
+
+VOID
+InfCloseFile (HINF InfHandle);
+
+
+BOOLEAN
+InfFindFirstLine (HINF InfHandle,
+                 PCHAR Section,
+                 PCHAR Key,
+                 PINFCONTEXT Context);
+
+BOOLEAN
+InfFindNextLine (PINFCONTEXT ContextIn,
+                PINFCONTEXT ContextOut);
+
+BOOLEAN
+InfFindFirstMatchLine (PINFCONTEXT ContextIn,
+                      PCHAR Key,
+                      PINFCONTEXT ContextOut);
+
+BOOLEAN
+InfFindNextMatchLine (PINFCONTEXT ContextIn,
+                     PCHAR Key,
+                     PINFCONTEXT ContextOut);
+
+
+S32
+InfGetLineCount (HINF InfHandle,
+                PCHAR Section);
+
+S32
+InfGetFieldCount (PINFCONTEXT Context);
+
+
+BOOLEAN
+InfGetBinaryField (PINFCONTEXT Context,
+                  U32 FieldIndex,
+                  PU8 ReturnBuffer,
+                  U32 ReturnBufferSize,
+                  PU32 RequiredSize);
+
+BOOLEAN
+InfGetIntField (PINFCONTEXT Context,
+               U32 FieldIndex,
+               S32 *IntegerValue);
+
+BOOLEAN
+InfGetMultiSzField (PINFCONTEXT Context,
+                   U32 FieldIndex,
+                   PCHAR ReturnBuffer,
+                   U32 ReturnBufferSize,
+                   PU32 RequiredSize);
+
+BOOLEAN
+InfGetStringField (PINFCONTEXT Context,
+                  U32 FieldIndex,
+                  PCHAR ReturnBuffer,
+                  U32 ReturnBufferSize,
+                  PU32 RequiredSize);
+
+
+
+BOOLEAN
+InfGetData (PINFCONTEXT Context,
+           PCHAR *Key,
+           PCHAR *Data);
+
+BOOLEAN
+InfGetDataField (PINFCONTEXT Context,
+                U32 FieldIndex,
+                PCHAR *Data);
+
+#endif /* __INFCACHE_H__ */
+
+/* EOF */
index 0b942e9..964948e 100644 (file)
@@ -22,7 +22,7 @@
 
 
 /* just some stuff */
-#define VERSION                        "FreeLoader v1.8.11"
+#define VERSION                        "FreeLoader v1.8.12"
 #define COPYRIGHT              "Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>"
 #define AUTHOR_EMAIL   "<brianp@sginet.com>"
 #define BY_AUTHOR              "by Brian Palmer"
@@ -36,7 +36,7 @@
 //
 #define FREELOADER_MAJOR_VERSION       1
 #define FREELOADER_MINOR_VERSION       8
-#define FREELOADER_PATCH_VERSION       11
+#define FREELOADER_PATCH_VERSION       12
 
 
 PUCHAR GetFreeLoaderVersionString(VOID);
diff --git a/freeldr/freeldr/inffile/inffile.c b/freeldr/freeldr/inffile/inffile.c
new file mode 100644 (file)
index 0000000..4e54b06
--- /dev/null
@@ -0,0 +1,1494 @@
+/*
+ *  ReactOS kernel
+ *  Copyright (C) 2002,2003 ReactOS Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* $Id: inffile.c,v 1.1 2003/05/25 21:18:16 ekohl Exp $
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS text-mode setup
+ * FILE:            subsys/system/usetup/infcache.c
+ * PURPOSE:         INF file parser that caches contents of INF file in memory
+ * PROGRAMMER:      Royce Mitchell III
+ *                  Eric Kohl
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include <freeldr.h>
+#include <mm.h>
+#include <rtl.h>
+#include <fs.h>
+
+#include <inffile.h>
+
+
+#define CONTROL_Z  '\x1a'
+#define MAX_SECTION_NAME_LEN  255
+#define MAX_FIELD_LEN         511  /* larger fields get silently truncated */
+/* actual string limit is MAX_INF_STRING_LENGTH+1 (plus terminating null) under Windows */
+#define MAX_STRING_LEN        (MAX_INF_STRING_LENGTH+1)
+
+
+typedef struct _INFCACHEFIELD
+{
+  struct _INFCACHEFIELD *Next;
+  struct _INFCACHEFIELD *Prev;
+
+  CHAR Data[1];
+} INFCACHEFIELD, *PINFCACHEFIELD;
+
+
+typedef struct _INFCACHELINE
+{
+  struct _INFCACHELINE *Next;
+  struct _INFCACHELINE *Prev;
+
+  S32 FieldCount;
+
+  PCHAR Key;
+
+  PINFCACHEFIELD FirstField;
+  PINFCACHEFIELD LastField;
+
+} INFCACHELINE, *PINFCACHELINE;
+
+
+typedef struct _INFCACHESECTION
+{
+  struct _INFCACHESECTION *Next;
+  struct _INFCACHESECTION *Prev;
+
+  PINFCACHELINE FirstLine;
+  PINFCACHELINE LastLine;
+
+  S32 LineCount;
+
+  CHAR Name[1];
+} INFCACHESECTION, *PINFCACHESECTION;
+
+
+typedef struct _INFCACHE
+{
+  PINFCACHESECTION FirstSection;
+  PINFCACHESECTION LastSection;
+
+  PINFCACHESECTION StringsSection;
+} INFCACHE, *PINFCACHE;
+
+
+/* parser definitions */
+
+enum parser_state
+{
+  LINE_START,      /* at beginning of a line */
+  SECTION_NAME,    /* parsing a section name */
+  KEY_NAME,        /* parsing a key name */
+  VALUE_NAME,      /* parsing a value name */
+  EOL_BACKSLASH,   /* backslash at end of line */
+  QUOTES,          /* inside quotes */
+  LEADING_SPACES,  /* leading spaces */
+  TRAILING_SPACES, /* trailing spaces */
+  COMMENT,         /* inside a comment */
+  NB_PARSER_STATES
+};
+
+struct parser
+{
+  const CHAR        *start;       /* start position of item being parsed */
+  const CHAR        *end;         /* end of buffer */
+  PINFCACHE         file;         /* file being built */
+  enum parser_state state;        /* current parser state */
+  enum parser_state stack[4];     /* state stack */
+  int               stack_pos;    /* current pos in stack */
+
+  PINFCACHESECTION cur_section;   /* pointer to the section being parsed*/
+  PINFCACHELINE    line;          /* current line */
+  unsigned int     line_pos;      /* current line position in file */
+  unsigned int     error;         /* error code */
+  unsigned int     token_len;     /* current token len */
+  CHAR token[MAX_FIELD_LEN+1];   /* current token */
+};
+
+typedef const CHAR * (*parser_state_func)( struct parser *parser, const CHAR *pos );
+
+/* parser state machine functions */
+static const CHAR *line_start_state( struct parser *parser, const CHAR *pos );
+static const CHAR *section_name_state( struct parser *parser, const CHAR *pos );
+static const CHAR *key_name_state( struct parser *parser, const CHAR *pos );
+static const CHAR *value_name_state( struct parser *parser, const CHAR *pos );
+static const CHAR *eol_backslash_state( struct parser *parser, const CHAR *pos );
+static const CHAR *quotes_state( struct parser *parser, const CHAR *pos );
+static const CHAR *leading_spaces_state( struct parser *parser, const CHAR *pos );
+static const CHAR *trailing_spaces_state( struct parser *parser, const CHAR *pos );
+static const CHAR *comment_state( struct parser *parser, const CHAR *pos );
+
+static const parser_state_func parser_funcs[NB_PARSER_STATES] =
+{
+  line_start_state,      /* LINE_START */
+  section_name_state,    /* SECTION_NAME */
+  key_name_state,        /* KEY_NAME */
+  value_name_state,      /* VALUE_NAME */
+  eol_backslash_state,   /* EOL_BACKSLASH */
+  quotes_state,          /* QUOTES */
+  leading_spaces_state,  /* LEADING_SPACES */
+  trailing_spaces_state, /* TRAILING_SPACES */
+  comment_state          /* COMMENT */
+};
+
+
+/* PRIVATE FUNCTIONS ********************************************************/
+
+static PINFCACHELINE
+InfpCacheFreeLine (PINFCACHELINE Line)
+{
+  PINFCACHELINE Next;
+  PINFCACHEFIELD Field;
+
+  if (Line == NULL)
+    {
+      return NULL;
+    }
+
+  Next = Line->Next;
+  if (Line->Key != NULL)
+    {
+      MmFreeMemory (Line->Key);
+      Line->Key = NULL;
+    }
+
+  /* Remove data fields */
+  while (Line->FirstField != NULL)
+    {
+      Field = Line->FirstField->Next;
+      MmFreeMemory (Line->FirstField);
+      Line->FirstField = Field;
+    }
+  Line->LastField = NULL;
+
+  MmFreeMemory (Line);
+
+  return Next;
+}
+
+
+static PINFCACHESECTION
+InfpCacheFreeSection (PINFCACHESECTION Section)
+{
+  PINFCACHESECTION Next;
+
+  if (Section == NULL)
+    {
+      return NULL;
+    }
+
+  /* Release all keys */
+  Next = Section->Next;
+  while (Section->FirstLine != NULL)
+    {
+      Section->FirstLine = InfpCacheFreeLine (Section->FirstLine);
+    }
+  Section->LastLine = NULL;
+
+  MmFreeMemory (Section);
+
+  return Next;
+}
+
+
+static PINFCACHESECTION
+InfpCacheFindSection (PINFCACHE Cache,
+                     PCHAR Name)
+{
+  PINFCACHESECTION Section = NULL;
+
+  if (Cache == NULL || Name == NULL)
+    {
+      return NULL;
+    }
+
+  /* iterate through list of sections */
+  Section = Cache->FirstSection;
+  while (Section != NULL)
+    {
+      if (stricmp (Section->Name, Name) == 0)
+       {
+         return Section;
+       }
+
+      /* get the next section*/
+      Section = Section->Next;
+    }
+
+  return NULL;
+}
+
+
+static PINFCACHESECTION
+InfpCacheAddSection (PINFCACHE Cache,
+                    PCHAR Name)
+{
+  PINFCACHESECTION Section = NULL;
+  U32 Size;
+
+  if (Cache == NULL || Name == NULL)
+    {
+//      DPRINT("Invalid parameter\n");
+      return NULL;
+    }
+
+  /* Allocate and initialize the new section */
+  Size = sizeof(INFCACHESECTION) + strlen (Name);
+  Section = (PINFCACHESECTION)MmAllocateMemory (Size);
+  if (Section == NULL)
+    {
+//      DPRINT("RtlAllocateHeap() failed\n");
+      return NULL;
+    }
+  memset (Section, 0, Size);
+
+  /* Copy section name */
+  strcpy (Section->Name, Name);
+
+  /* Append section */
+  if (Cache->FirstSection == NULL)
+    {
+      Cache->FirstSection = Section;
+      Cache->LastSection = Section;
+    }
+  else
+    {
+      Cache->LastSection->Next = Section;
+      Section->Prev = Cache->LastSection;
+      Cache->LastSection = Section;
+    }
+
+  return Section;
+}
+
+
+static PINFCACHELINE
+InfpCacheAddLine (PINFCACHESECTION Section)
+{
+  PINFCACHELINE Line;
+
+  if (Section == NULL)
+    {
+//      DPRINT("Invalid parameter\n");
+      return NULL;
+    }
+
+  Line = (PINFCACHELINE)MmAllocateMemory (sizeof(INFCACHELINE));
+  if (Line == NULL)
+    {
+//      DPRINT("RtlAllocateHeap() failed\n");
+      return NULL;
+    }
+  memset (Line, 0, sizeof(INFCACHELINE));
+
+  /* Append line */
+  if (Section->FirstLine == NULL)
+    {
+      Section->FirstLine = Line;
+      Section->LastLine = Line;
+    }
+  else
+    {
+      Section->LastLine->Next = Line;
+      Line->Prev = Section->LastLine;
+      Section->LastLine = Line;
+    }
+  Section->LineCount++;
+
+  return Line;
+}
+
+
+static PVOID
+InfpAddKeyToLine (PINFCACHELINE Line,
+                 PCHAR Key)
+{
+  if (Line == NULL)
+    return NULL;
+
+  if (Line->Key != NULL)
+    return NULL;
+
+  Line->Key = (PCHAR)MmAllocateMemory (strlen (Key) + 1);
+  if (Line->Key == NULL)
+    return NULL;
+
+  strcpy (Line->Key, Key);
+
+  return (PVOID)Line->Key;
+}
+
+
+static PVOID
+InfpAddFieldToLine (PINFCACHELINE Line,
+                   PCHAR Data)
+{
+  PINFCACHEFIELD Field;
+  U32 Size;
+
+  Size = sizeof(INFCACHEFIELD) + strlen(Data);
+  Field = (PINFCACHEFIELD)MmAllocateMemory (Size);
+  if (Field == NULL)
+    {
+      return NULL;
+    }
+  memset (Field, 0, Size);
+
+  strcpy (Field->Data, Data);
+
+  /* Append key */
+  if (Line->FirstField == NULL)
+    {
+      Line->FirstField = Field;
+      Line->LastField = Field;
+    }
+  else
+    {
+      Line->LastField->Next = Field;
+      Field->Prev = Line->LastField;
+      Line->LastField = Field;
+    }
+  Line->FieldCount++;
+
+  return (PVOID)Field;
+}
+
+
+static PINFCACHELINE
+InfpCacheFindKeyLine (PINFCACHESECTION Section,
+                     PCHAR Key)
+{
+  PINFCACHELINE Line;
+
+  Line = Section->FirstLine;
+  while (Line != NULL)
+    {
+      if (Line->Key != NULL && stricmp (Line->Key, Key) == 0)
+       {
+         return Line;
+       }
+
+      Line = Line->Next;
+    }
+
+  return NULL;
+}
+
+
+/* push the current state on the parser stack */
+inline static void push_state( struct parser *parser, enum parser_state state )
+{
+//  assert( parser->stack_pos < sizeof(parser->stack)/sizeof(parser->stack[0]) );
+  parser->stack[parser->stack_pos++] = state;
+}
+
+
+/* pop the current state */
+inline static void pop_state( struct parser *parser )
+{
+//  assert( parser->stack_pos );
+  parser->state = parser->stack[--parser->stack_pos];
+}
+
+
+/* set the parser state and return the previous one */
+inline static enum parser_state set_state( struct parser *parser, enum parser_state state )
+{
+  enum parser_state ret = parser->state;
+  parser->state = state;
+  return ret;
+}
+
+
+/* check if the pointer points to an end of file */
+inline static int is_eof( struct parser *parser, const CHAR *ptr )
+{
+  return (ptr >= parser->end || *ptr == CONTROL_Z);
+}
+
+
+/* check if the pointer points to an end of line */
+inline static int is_eol( struct parser *parser, const CHAR *ptr )
+{
+  return (ptr >= parser->end ||
+         *ptr == CONTROL_Z ||
+         *ptr == '\n' ||
+         (*ptr == '\r' && *(ptr + 1) == '\n'));
+}
+
+
+/* push data from current token start up to pos into the current token */
+static int push_token( struct parser *parser, const CHAR *pos )
+{
+  int len = pos - parser->start;
+  const CHAR *src = parser->start;
+  CHAR *dst = parser->token + parser->token_len;
+
+  if (len > MAX_FIELD_LEN - parser->token_len)
+    len = MAX_FIELD_LEN - parser->token_len;
+
+  parser->token_len += len;
+  for ( ; len > 0; len--, dst++, src++)
+    *dst = *src ? (CHAR)*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 = FALSE;
+      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 = FALSE;
+         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 = 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 = FALSE;
+  return NULL;
+}
+
+
+/* close the current line and prepare for parsing a new one */
+static void close_current_line( struct parser *parser )
+{
+  parser->line = NULL;
+}
+
+
+
+/* handler for parser LINE_START state */
+static const CHAR *line_start_state( struct parser *parser, const CHAR *pos )
+{
+  const CHAR *p;
+
+  for (p = pos; !is_eof( parser, p ); p++)
+    {
+      switch(*p)
+       {
+         case '\r':
+           continue;
+
+         case '\n':
+           parser->line_pos++;
+           close_current_line( parser );
+           break;
+
+         case ';':
+           push_state( parser, LINE_START );
+           set_state( parser, COMMENT );
+           return p + 1;
+
+         case '[':
+           parser->start = p + 1;
+           set_state( parser, SECTION_NAME );
+           return p + 1;
+
+         default:
+           if (!isspace(*p))
+             {
+               parser->start = p;
+               set_state( parser, KEY_NAME );
+               return p;
+             }
+           break;
+       }
+    }
+  close_current_line( parser );
+  return NULL;
+}
+
+
+/* handler for parser SECTION_NAME state */
+static const CHAR *section_name_state( struct parser *parser, const CHAR *pos )
+{
+  const CHAR *p;
+
+  for (p = pos; !is_eol( parser, p ); p++)
+    {
+      if (*p == ']')
+       {
+         push_token( parser, p );
+         if (add_section_from_token( parser ) == NULL)
+           return NULL;
+         push_state( parser, LINE_START );
+         set_state( parser, COMMENT );  /* ignore everything else on the line */
+         return p + 1;
+       }
+    }
+  parser->error = STATUS_BAD_SECTION_NAME_LINE; /* unfinished section name */
+  return NULL;
+}
+
+
+/* handler for parser KEY_NAME state */
+static const CHAR *key_name_state( struct parser *parser, const CHAR *pos )
+{
+    const CHAR *p, *token_end = parser->start;
+
+    for (p = pos; !is_eol( parser, p ); p++)
+    {
+        if (*p == ',') break;
+        switch(*p)
+        {
+
+         case '=':
+            push_token( parser, token_end );
+            if (!add_field_from_token( parser, 1 )) return NULL;
+            parser->start = p + 1;
+            push_state( parser, VALUE_NAME );
+            set_state( parser, LEADING_SPACES );
+            return p + 1;
+        case ';':
+            push_token( parser, token_end );
+            if (!add_field_from_token( parser, 0 )) return NULL;
+            push_state( parser, LINE_START );
+            set_state( parser, COMMENT );
+            return p + 1;
+        case '"':
+            push_token( parser, token_end );
+            parser->start = p + 1;
+            push_state( parser, KEY_NAME );
+            set_state( parser, QUOTES );
+            return p + 1;
+        case '\\':
+            push_token( parser, token_end );
+            parser->start = p;
+            push_state( parser, KEY_NAME );
+            set_state( parser, EOL_BACKSLASH );
+            return p;
+        default:
+            if (!isspace(*p)) token_end = p + 1;
+            else
+            {
+                push_token( parser, p );
+                push_state( parser, KEY_NAME );
+                set_state( parser, TRAILING_SPACES );
+                return p;
+            }
+            break;
+        }
+    }
+    push_token( parser, token_end );
+    set_state( parser, VALUE_NAME );
+    return p;
+}
+
+
+/* handler for parser VALUE_NAME state */
+static const CHAR *value_name_state( struct parser *parser, const CHAR *pos )
+{
+    const CHAR *p, *token_end = parser->start;
+
+    for (p = pos; !is_eol( parser, p ); p++)
+    {
+        switch(*p)
+        {
+        case ';':
+            push_token( parser, token_end );
+            if (!add_field_from_token( parser, 0 )) return NULL;
+            push_state( parser, LINE_START );
+            set_state( parser, COMMENT );
+            return p + 1;
+        case ',':
+            push_token( parser, token_end );
+            if (!add_field_from_token( parser, 0 )) return NULL;
+            parser->start = p + 1;
+            push_state( parser, VALUE_NAME );
+            set_state( parser, LEADING_SPACES );
+            return p + 1;
+        case '"':
+            push_token( parser, token_end );
+            parser->start = p + 1;
+            push_state( parser, VALUE_NAME );
+            set_state( parser, QUOTES );
+            return p + 1;
+        case '\\':
+            push_token( parser, token_end );
+            parser->start = p;
+            push_state( parser, VALUE_NAME );
+            set_state( parser, EOL_BACKSLASH );
+            return p;
+        default:
+            if (!isspace(*p)) token_end = p + 1;
+            else
+            {
+                push_token( parser, p );
+                push_state( parser, VALUE_NAME );
+                set_state( parser, TRAILING_SPACES );
+                return p;
+            }
+            break;
+        }
+    }
+    push_token( parser, token_end );
+    if (!add_field_from_token( parser, 0 )) return NULL;
+    set_state( parser, LINE_START );
+    return p;
+}
+
+
+/* handler for parser EOL_BACKSLASH state */
+static const CHAR *eol_backslash_state( struct parser *parser, const CHAR *pos )
+{
+  const CHAR *p;
+
+  for (p = pos; !is_eof( parser, p ); p++)
+    {
+      switch(*p)
+       {
+         case '\r':
+           continue;
+
+         case '\n':
+           parser->line_pos++;
+           parser->start = p + 1;
+           set_state( parser, LEADING_SPACES );
+           return p + 1;
+
+         case '\\':
+           continue;
+
+         case ';':
+           push_state( parser, EOL_BACKSLASH );
+           set_state( parser, COMMENT );
+           return p + 1;
+
+         default:
+           if (isspace(*p))
+             continue;
+           push_token( parser, p );
+           pop_state( parser );
+           return p;
+       }
+    }
+  parser->start = p;
+  pop_state( parser );
+
+  return p;
+}
+
+
+/* handler for parser QUOTES state */
+static const CHAR *quotes_state( struct parser *parser, const CHAR *pos )
+{
+  const CHAR *p, *token_end = parser->start;
+
+  for (p = pos; !is_eol( parser, p ); p++)
+    {
+      if (*p == '"')
+       {
+         if (p+1 < parser->end && p[1] == '"')  /* double quotes */
+           {
+             push_token( parser, p + 1 );
+             parser->start = token_end = p + 2;
+             p++;
+           }
+         else  /* end of quotes */
+           {
+             push_token( parser, p );
+             parser->start = p + 1;
+             pop_state( parser );
+             return p + 1;
+           }
+       }
+    }
+  push_token( parser, p );
+  pop_state( parser );
+  return p;
+}
+
+
+/* handler for parser LEADING_SPACES state */
+static const CHAR *leading_spaces_state( struct parser *parser, const CHAR *pos )
+{
+  const CHAR *p;
+
+  for (p = pos; !is_eol( parser, p ); p++)
+    {
+      if (*p == '\\')
+       {
+         parser->start = p;
+         set_state( parser, EOL_BACKSLASH );
+         return p;
+       }
+      if (!isspace(*p))
+       break;
+    }
+  parser->start = p;
+  pop_state( parser );
+  return p;
+}
+
+
+/* handler for parser TRAILING_SPACES state */
+static const CHAR *trailing_spaces_state( struct parser *parser, const CHAR *pos )
+{
+  const CHAR *p;
+
+  for (p = pos; !is_eol( parser, p ); p++)
+    {
+      if (*p == '\\')
+       {
+         set_state( parser, EOL_BACKSLASH );
+         return p;
+       }
+      if (!isspace(*p))
+       break;
+    }
+  pop_state( parser );
+  return p;
+}
+
+
+/* handler for parser COMMENT state */
+static const CHAR *comment_state( struct parser *parser, const CHAR *pos )
+{
+  const CHAR *p = pos;
+
+  while (!is_eol( parser, p ))
+     p++;
+  pop_state( parser );
+  return p;
+}
+
+
+/* parse a complete buffer */
+static BOOLEAN
+InfpParseBuffer (PINFCACHE file,
+                const CHAR *buffer,
+                const CHAR *end,
+                PU32 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       = TRUE;
+  parser.token_len   = 0;
+
+  /* parser main loop */
+  while (pos)
+    pos = (parser_funcs[parser.state])(&parser, pos);
+
+  if (parser.error)
+    {
+      if (error_line)
+       *error_line = parser.line_pos;
+      return parser.error;
+    }
+
+  /* find the [strings] section */
+  file->StringsSection = InfpCacheFindSection (file, "Strings");
+
+  return TRUE;
+}
+
+/* PUBLIC FUNCTIONS *********************************************************/
+
+BOOLEAN
+InfOpenFile(PHINF InfHandle,
+           PCHAR FileName,
+           PU32 ErrorLine)
+{
+  PFILE FileHandle;
+  PCHAR FileBuffer;
+  U32 FileSize;
+  PINFCACHE Cache;
+  BOOLEAN Success;
+
+
+  *InfHandle = NULL;
+  *ErrorLine = (U32)-1;
+
+
+  /* Open the inf file */
+  FileHandle = FsOpenFile (FileName);
+  if (FileHandle == NULL)
+    {
+//      DPRINT("NtOpenFile() failed (Status %lx)\n", Status);
+      return FALSE;
+    }
+
+//  DPRINT("NtOpenFile() successful\n");
+
+  /* Query file size */
+  FileSize = FsGetFileSize (FileHandle);
+  if (FileSize == 0)
+    {
+//      DPRINT("NtQueryInformationFile() failed (Status %lx)\n", Status);
+      FsCloseFile (FileHandle);
+      return FALSE;
+    }
+
+//  DPRINT("File size: %lu\n", FileLength);
+
+  /* Allocate file buffer */
+  FileBuffer = MmAllocateMemory (FileSize + 1);
+  if (FileBuffer == NULL)
+    {
+//      DPRINT1("RtlAllocateHeap() failed\n");
+      FsCloseFile (FileHandle);
+      return FALSE;
+    }
+
+  /* Read file */
+  Success = FsReadFile(FileHandle, FileSize, NULL, FileBuffer);
+
+  FsCloseFile (FileHandle);
+  if (!Success)
+    {
+//      DPRINT("FsReadFile() failed\n");
+      MmFreeMemory (FileBuffer);
+      return FALSE;
+    }
+
+  /* Append string terminator */
+  FileBuffer[FileSize] = 0;
+
+  /* Allocate infcache header */
+  Cache = (PINFCACHE)MmAllocateMemory (sizeof(INFCACHE));
+  if (Cache == NULL)
+    {
+//      DPRINT("RtlAllocateHeap() failed\n");
+      MmFreeMemory (FileBuffer);
+      return FALSE;
+    }
+
+  /* Initialize inicache header */
+  RtlZeroMemory(Cache,
+               sizeof(INFCACHE));
+
+  /* Parse the inf buffer */
+  Success = InfpParseBuffer (Cache,
+                            FileBuffer,
+                            FileBuffer + FileSize,
+                            ErrorLine);
+  if (!Success)
+    {
+      MmFreeMemory (Cache);
+      Cache = NULL;
+    }
+
+  /* Free file buffer */
+  MmFreeMemory (FileBuffer);
+
+  *InfHandle = (HINF)Cache;
+
+  return Success;
+}
+
+
+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;
+
+  MmFreeMemory(Cache);
+}
+
+
+BOOLEAN
+InfFindFirstLine (HINF InfHandle,
+                 PCHAR Section,
+                 PCHAR Key,
+                 PINFCONTEXT Context)
+{
+  PINFCACHE Cache;
+  PINFCACHESECTION CacheSection;
+  PINFCACHELINE CacheLine;
+
+  if (InfHandle == NULL || Section == NULL || Context == NULL)
+    {
+//      DPRINT("Invalid parameter\n");
+      return FALSE;
+    }
+
+  Cache = (PINFCACHE)InfHandle;
+
+  /* Iterate through list of sections */
+  CacheSection = Cache->FirstSection;
+  while (Section != NULL)
+    {
+//      DPRINT("Comparing '%S' and '%S'\n", CacheSection->Name, Section);
+
+      /* Are the section names the same? */
+      if (stricmp(CacheSection->Name, Section) == 0)
+       {
+         if (Key != NULL)
+           {
+             CacheLine = InfpCacheFindKeyLine (CacheSection, Key);
+           }
+         else
+           {
+             CacheLine = CacheSection->FirstLine;
+           }
+
+         if (CacheLine == NULL)
+           return FALSE;
+
+         Context->Inf = (PVOID)Cache;
+         Context->Section = (PVOID)CacheSection;
+         Context->Line = (PVOID)CacheLine;
+
+         return TRUE;
+       }
+
+      /* Get the next section */
+      CacheSection = CacheSection->Next;
+    }
+
+//  DPRINT("Section not found\n");
+
+  return FALSE;
+}
+
+
+BOOLEAN
+InfFindNextLine (PINFCONTEXT ContextIn,
+                PINFCONTEXT ContextOut)
+{
+  PINFCACHELINE CacheLine;
+
+  if (ContextIn == NULL || ContextOut == NULL)
+    return FALSE;
+
+  if (ContextIn->Line == NULL)
+    return FALSE;
+
+  CacheLine = (PINFCACHELINE)ContextIn->Line;
+  if (CacheLine->Next == NULL)
+    return FALSE;
+
+  if (ContextIn != ContextOut)
+    {
+      ContextOut->Inf = ContextIn->Inf;
+      ContextOut->Section = ContextIn->Section;
+    }
+  ContextOut->Line = (PVOID)(CacheLine->Next);
+
+  return TRUE;
+}
+
+
+BOOLEAN
+InfFindFirstMatchLine (PINFCONTEXT ContextIn,
+                      PCHAR Key,
+                      PINFCONTEXT ContextOut)
+{
+  PINFCACHELINE CacheLine;
+
+  if (ContextIn == NULL || ContextOut == NULL || Key == NULL || *Key == 0)
+    return FALSE;
+
+  if (ContextIn->Inf == NULL || ContextIn->Section == NULL)
+    return FALSE;
+
+  CacheLine = ((PINFCACHESECTION)(ContextIn->Section))->FirstLine;
+  while (CacheLine != NULL)
+    {
+      if (CacheLine->Key != NULL && stricmp (CacheLine->Key, Key) == 0)
+       {
+
+         if (ContextIn != ContextOut)
+           {
+             ContextOut->Inf = ContextIn->Inf;
+             ContextOut->Section = ContextIn->Section;
+           }
+         ContextOut->Line = (PVOID)CacheLine;
+
+         return TRUE;
+       }
+
+      CacheLine = CacheLine->Next;
+    }
+
+  return FALSE;
+}
+
+
+BOOLEAN
+InfFindNextMatchLine (PINFCONTEXT ContextIn,
+                     PCHAR Key,
+                     PINFCONTEXT ContextOut)
+{
+  PINFCACHELINE CacheLine;
+
+  if (ContextIn == NULL || ContextOut == NULL || Key == NULL || *Key == 0)
+    return FALSE;
+
+  if (ContextIn->Inf == NULL || ContextIn->Section == NULL || ContextIn->Line == NULL)
+    return FALSE;
+
+  CacheLine = (PINFCACHELINE)ContextIn->Line;
+  while (CacheLine != NULL)
+    {
+      if (CacheLine->Key != NULL && stricmp (CacheLine->Key, Key) == 0)
+       {
+
+         if (ContextIn != ContextOut)
+           {
+             ContextOut->Inf = ContextIn->Inf;
+             ContextOut->Section = ContextIn->Section;
+           }
+         ContextOut->Line = (PVOID)CacheLine;
+
+         return TRUE;
+       }
+
+      CacheLine = CacheLine->Next;
+    }
+
+  return FALSE;
+}
+
+
+S32
+InfGetLineCount(HINF InfHandle,
+               PCHAR Section)
+{
+  PINFCACHE Cache;
+  PINFCACHESECTION CacheSection;
+
+  if (InfHandle == NULL || Section == NULL)
+    {
+//      DPRINT("Invalid parameter\n");
+      return -1;
+    }
+
+  Cache = (PINFCACHE)InfHandle;
+
+  /* Iterate through list of sections */
+  CacheSection = Cache->FirstSection;
+  while (Section != NULL)
+    {
+//      DPRINT("Comparing '%S' and '%S'\n", CacheSection->Name, Section);
+
+      /* Are the section names the same? */
+      if (stricmp(CacheSection->Name, Section) == 0)
+       {
+         return CacheSection->LineCount;
+       }
+
+      /* Get the next section */
+      CacheSection = CacheSection->Next;
+    }
+
+//  DPRINT("Section not found\n");
+
+  return -1;
+}
+
+
+/* InfGetLineText */
+
+
+S32
+InfGetFieldCount(PINFCONTEXT Context)
+{
+  if (Context == NULL || Context->Line == NULL)
+    return 0;
+
+  return ((PINFCACHELINE)Context->Line)->FieldCount;
+}
+
+
+BOOLEAN
+InfGetBinaryField (PINFCONTEXT Context,
+                  U32 FieldIndex,
+                  PU8 ReturnBuffer,
+                  U32 ReturnBufferSize,
+                  PU32 RequiredSize)
+{
+  PINFCACHELINE CacheLine;
+  PINFCACHEFIELD CacheField;
+  U32 Index;
+  U32 Size;
+  PU8 Ptr;
+
+  if (Context == NULL || Context->Line == NULL || FieldIndex == 0)
+    {
+//      DPRINT("Invalid parameter\n");
+      return FALSE;
+    }
+
+  if (RequiredSize != NULL)
+    *RequiredSize = 0;
+
+  CacheLine = (PINFCACHELINE)Context->Line;
+
+  if (FieldIndex > CacheLine->FieldCount)
+    return FALSE;
+
+  CacheField = CacheLine->FirstField;
+  for (Index = 1; Index < FieldIndex; Index++)
+    CacheField = CacheField->Next;
+
+  Size = CacheLine->FieldCount - FieldIndex + 1;
+
+  if (RequiredSize != NULL)
+    *RequiredSize = Size;
+
+  if (ReturnBuffer != NULL)
+    {
+      if (ReturnBufferSize < Size)
+       return FALSE;
+
+      /* Copy binary data */
+      Ptr = ReturnBuffer;
+      while (CacheField != NULL)
+       {
+         *Ptr = (UCHAR)atoi(CacheField->Data); //strtoul (CacheField->Data, NULL, 16);
+
+         Ptr++;
+         CacheField = CacheField->Next;
+       }
+    }
+
+  return TRUE;
+}
+
+
+BOOLEAN
+InfGetIntField (PINFCONTEXT Context,
+               U32 FieldIndex,
+               S32 *IntegerValue)
+{
+  PINFCACHELINE CacheLine;
+  PINFCACHEFIELD CacheField;
+  U32 Index;
+  PCHAR Ptr;
+
+  if (Context == NULL || Context->Line == NULL || IntegerValue == NULL)
+    {
+//      DPRINT("Invalid parameter\n");
+      return FALSE;
+    }
+
+  CacheLine = (PINFCACHELINE)Context->Line;
+
+  if (FieldIndex > CacheLine->FieldCount)
+    {
+//      DPRINT("Invalid parameter\n");
+      return FALSE;
+    }
+
+  if (FieldIndex == 0)
+    {
+      Ptr = CacheLine->Key;
+    }
+  else
+    {
+      CacheField = CacheLine->FirstField;
+      for (Index = 1; Index < FieldIndex; Index++)
+       CacheField = CacheField->Next;
+
+      Ptr = CacheField->Data;
+    }
+
+  *IntegerValue = atoi (Ptr); //strtol (Ptr, NULL, 0);
+
+  return TRUE;
+}
+
+
+BOOLEAN
+InfGetMultiSzField (PINFCONTEXT Context,
+                   U32 FieldIndex,
+                   PCHAR ReturnBuffer,
+                   U32 ReturnBufferSize,
+                   PU32 RequiredSize)
+{
+  PINFCACHELINE CacheLine;
+  PINFCACHEFIELD CacheField;
+  PINFCACHEFIELD FieldPtr;
+  U32 Index;
+  U32 Size;
+  PCHAR Ptr;
+
+  if (Context == NULL || Context->Line == NULL || FieldIndex == 0)
+    {
+//      DPRINT("Invalid parameter\n");
+      return FALSE;
+    }
+
+  if (RequiredSize != NULL)
+    *RequiredSize = 0;
+
+  CacheLine = (PINFCACHELINE)Context->Line;
+
+  if (FieldIndex > CacheLine->FieldCount)
+    return FALSE;
+
+  CacheField = CacheLine->FirstField;
+  for (Index = 1; Index < FieldIndex; Index++)
+    CacheField = CacheField->Next;
+
+  /* Calculate the required buffer size */
+  FieldPtr = CacheField;
+  Size = 0;
+  while (FieldPtr != NULL)
+    {
+      Size += (strlen (FieldPtr->Data) + 1);
+      FieldPtr = FieldPtr->Next;
+    }
+  Size++;
+
+  if (RequiredSize != NULL)
+    *RequiredSize = Size;
+
+  if (ReturnBuffer != NULL)
+    {
+      if (ReturnBufferSize < Size)
+       return FALSE;
+
+      /* Copy multi-sz string */
+      Ptr = ReturnBuffer;
+      FieldPtr = CacheField;
+      while (FieldPtr != NULL)
+       {
+         Size = strlen (FieldPtr->Data) + 1;
+
+         strcpy (Ptr, FieldPtr->Data);
+
+         Ptr = Ptr + Size;
+         FieldPtr = FieldPtr->Next;
+       }
+      *Ptr = 0;
+    }
+
+  return TRUE;
+}
+
+
+BOOLEAN
+InfGetStringField (PINFCONTEXT Context,
+                  U32 FieldIndex,
+                  PCHAR ReturnBuffer,
+                  U32 ReturnBufferSize,
+                  PU32 RequiredSize)
+{
+  PINFCACHELINE CacheLine;
+  PINFCACHEFIELD CacheField;
+  U32 Index;
+  PCHAR Ptr;
+  U32 Size;
+
+  if (Context == NULL || Context->Line == NULL || FieldIndex == 0)
+    {
+//      DPRINT("Invalid parameter\n");
+      return FALSE;
+    }
+
+  if (RequiredSize != NULL)
+    *RequiredSize = 0;
+
+  CacheLine = (PINFCACHELINE)Context->Line;
+
+  if (FieldIndex > CacheLine->FieldCount)
+    return FALSE;
+
+  if (FieldIndex == 0)
+    {
+      Ptr = CacheLine->Key;
+    }
+  else
+    {
+      CacheField = CacheLine->FirstField;
+      for (Index = 1; Index < FieldIndex; Index++)
+       CacheField = CacheField->Next;
+
+      Ptr = CacheField->Data;
+    }
+
+  Size = strlen (Ptr) + 1;
+
+  if (RequiredSize != NULL)
+    *RequiredSize = Size;
+
+  if (ReturnBuffer != NULL)
+    {
+      if (ReturnBufferSize < Size)
+       return FALSE;
+
+      strcpy (ReturnBuffer, Ptr);
+    }
+
+  return TRUE;
+}
+
+
+
+
+BOOLEAN
+InfGetData (PINFCONTEXT Context,
+           PCHAR *Key,
+           PCHAR *Data)
+{
+  PINFCACHELINE CacheKey;
+
+  if (Context == NULL || Context->Line == NULL || Data == NULL)
+    {
+//      DPRINT("Invalid parameter\n");
+      return FALSE;
+    }
+
+  CacheKey = (PINFCACHELINE)Context->Line;
+  if (Key != NULL)
+    *Key = CacheKey->Key;
+
+  if (Data != NULL)
+    {
+      if (CacheKey->FirstField == NULL)
+       {
+         *Data = NULL;
+       }
+      else
+       {
+         *Data = CacheKey->FirstField->Data;
+       }
+    }
+
+  return TRUE;
+}
+
+
+BOOLEAN
+InfGetDataField (PINFCONTEXT Context,
+                U32 FieldIndex,
+                PCHAR *Data)
+{
+  PINFCACHELINE CacheLine;
+  PINFCACHEFIELD CacheField;
+  U32 Index;
+
+  if (Context == NULL || Context->Line == NULL || Data == NULL)
+    {
+//      DPRINT("Invalid parameter\n");
+      return FALSE;
+    }
+
+  CacheLine = (PINFCACHELINE)Context->Line;
+
+  if (FieldIndex > CacheLine->FieldCount)
+    return FALSE;
+
+  if (FieldIndex == 0)
+    {
+      *Data = CacheLine->Key;
+    }
+  else
+    {
+      CacheField = CacheLine->FirstField;
+      for (Index = 1; Index < FieldIndex; Index++)
+       CacheField = CacheField->Next;
+
+      *Data = CacheField->Data;
+    }
+
+  return TRUE;
+}
+
+
+/* EOF */
index 4b8d327..4456df9 100644 (file)
@@ -30,6 +30,9 @@ BOOL IniOpenSection(PUCHAR SectionName, U32* SectionId)
 
        DbgPrint((DPRINT_INIFILE, "IniOpenSection() SectionName = %s\n", SectionName));
 
+       if (!IniFileSectionListHead)
+               return FALSE;
+
        // Loop through each section and find the one they want
        Section = (PINI_SECTION)RtlListGetHead((PLIST_ITEM)IniFileSectionListHead);
        while (Section != NULL)
index 154b69f..6feee05 100644 (file)
@@ -17,7 +17,7 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-       
+
 #include <freeldr.h>
 #include <arch.h>
 #include <miscboot.h>
index 4f6f619..5db7252 100644 (file)
@@ -207,6 +207,7 @@ PVOID MultiBootLoadModule(FILE *ModuleImage, char *ModuleName, U32* ModuleSize)
        return((PVOID)pModule->mod_start);
 }
 
+#if 0
 int GetBootPartition(char *OperatingSystemName)
 {
        int             BootPartitionNumber = -1;
@@ -223,7 +224,7 @@ int GetBootPartition(char *OperatingSystemName)
 
        return BootPartitionNumber;
 }
-
+#endif
 
 PVOID MultiBootCreateModule(char *ModuleName)
 {
index 0d50df4..ded0ef8 100644 (file)
@@ -662,21 +662,8 @@ LoadAndBootReactOS(PUCHAR OperatingSystemName)
        FilePointer = FsOpenFile(szFileName);
        if (FilePointer == NULL)
        {
-               strcpy(szFileName, szBootPath);
-               strcat(szFileName, "SYSTEM32\\CONFIG\\SYSTEM.HIV");
-
-               DbgPrint((DPRINT_REACTOS, "SystemHive: '%s'", szFileName));
-
-               FilePointer = FsOpenFile(szFileName);
-               if (FilePointer == NULL)
-               {
-                       UiMessageBox("Could not find the System hive!");
-                       return;
-               }
-               else
-               {
-                       TextHive = TRUE;
-               }
+               UiMessageBox("Could not find the System hive!");
+               return;
        }
 
        /*
@@ -702,14 +689,7 @@ LoadAndBootReactOS(PUCHAR OperatingSystemName)
        /*
         * Import the loaded system hive
         */
-       if (TextHive)
-       {
-               RegImportTextHive(Base, Size);
-       }
-       else
-       {
-               RegImportBinaryHive(Base, Size);
-       }
+       RegImportBinaryHive(Base, Size);
 
        /*
         * Initialize the 'CurrentControlSet' link
diff --git a/freeldr/freeldr/reactos/reghive.c b/freeldr/freeldr/reactos/reghive.c
deleted file mode 100644 (file)
index 93000a3..0000000
+++ /dev/null
@@ -1,591 +0,0 @@
-/*
- *  FreeLoader
- *
- *  Copyright (C) 2001  Rex Jolliff
- *  Copyright (C) 2001  Eric Kohl
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <freeldr.h>
-#include <rtl.h>
-#include <mm.h>
-#include <debug.h>
-
-#include "registry.h"
-
-
-#define  REGISTRY_FILE_MAGIC    "REGEDIT4"
-
-static PCHAR 
-checkAndSkipMagic (PCHAR  regChunk)
-{
-  if (strncmp (regChunk, 
-               REGISTRY_FILE_MAGIC, 
-               strlen (REGISTRY_FILE_MAGIC)) != 0)
-  {
-    DbgPrint((DPRINT_REGISTRY, "Incorrect magic number in registry chunk. Expected: '%s' Got: '%.*s'\n",
-      REGISTRY_FILE_MAGIC, strlen(REGISTRY_FILE_MAGIC), regChunk));
-
-    return  0;
-  }
-  regChunk += strlen (REGISTRY_FILE_MAGIC);
-
-  DbgPrint((DPRINT_REGISTRY, "Found registry chunk magic value\n"));
-
-  return regChunk;
-}
-
-static PCHAR
-skipWhitespaceInChunk (PCHAR regChunk)
-{
-  while (*regChunk && isspace (*regChunk))
-    regChunk++;
-
-  return *regChunk ? regChunk : 0;
-}
-
-static int
-computeKeyNameSize (PCHAR  regChunk)
-{
-  int  copyCount = 0;
-
-  while (*regChunk != 0 && *regChunk != ']')
-  {
-    copyCount++;
-    regChunk++;
-  }
-
-  return  copyCount;
-}
-
-static BOOL
-allocateKeyName(PCHAR *newKeyName, int newKeySize)
-{
-  if (*newKeyName != NULL)
-    MmFreeMemory(*newKeyName);
-
-  *newKeyName = MmAllocateMemory(newKeySize + 1);
-  if (*newKeyName == NULL)
-    return(FALSE);
-
-  memset(*newKeyName, 0, newKeySize + 1);
-
-  return(TRUE);
-}
-
-static PCHAR
-skipToNextKeyInChunk (PCHAR  regChunk)
-{
-  while (*regChunk != 0 && *regChunk != '[')
-  {
-    while (*regChunk != 0 && *regChunk != '\n')
-    {
-      regChunk++;
-    }
-    regChunk++;
-  }
-
-  return  *regChunk ? regChunk : 0;
-}
-
-static PCHAR
-getKeyNameFromChunk (PCHAR  regChunk, PCHAR  newKeyName)
-{
-  int index = 0;
-
-  while (*regChunk != 0 && *regChunk != ']')
-  {
-    newKeyName[index++] = *regChunk++;
-  }
-  newKeyName[index] = '\0';
-
-  return  *regChunk ? regChunk : 0;
-}
-
-static HKEY
-createNewKey (PCHAR newKeyName)
-{
-  HKEY handleToReturn = NULL;
-
-  DbgPrint((DPRINT_REGISTRY, "Adding new key '%s'\n", newKeyName));
-
-  RegCreateKey(NULL,
-              newKeyName,
-              &handleToReturn);
-
-  DbgPrint((DPRINT_REGISTRY, "Returned handle: 0x%x\n", handleToReturn));
-
-  return handleToReturn;
-}
-
-static PCHAR
-skipToNextKeyValueInChunk (PCHAR  regChunk)
-{
-  while (*regChunk != 0 && *regChunk != '\n')
-    regChunk++;
-  regChunk = skipWhitespaceInChunk (regChunk);
-  
-  return  regChunk;
-}
-
-static int
-computeKeyValueNameSize (PCHAR  regChunk)
-{
-  int size = 0;
-
-  if (*regChunk != '\"')
-    return  0;
-  regChunk++;
-  while (*regChunk != 0 && *regChunk != '\"')
-  {
-    size++;
-    regChunk++;
-  }
-
-  return  regChunk ? size : 0;
-}
-
-static PCHAR
-getKeyValueNameFromChunk (PCHAR regChunk, PCHAR newKeyName)
-{
-  int  index = 0;
-
-  regChunk++;
-  while (*regChunk != 0 && *regChunk != '\"')
-  {
-    newKeyName[index++] = *regChunk++;
-  }
-  newKeyName[index] = '\0';
-  regChunk++;
-
-  return  *regChunk ? regChunk : 0;
-}
-
-static PCHAR 
-getKeyValueTypeFromChunk (PCHAR  regChunk, PCHAR  dataFormat, int *keyValueType)
-{
-  if (*regChunk == '\"')
-  {
-    strcpy (dataFormat, "string");
-    *keyValueType = REG_SZ;
-  }
-  else if (strncmp (regChunk, "hex", 3) == 0)
-  {
-    strcpy (dataFormat, "hex");
-    regChunk += 3;
-    if (*regChunk == '(')
-    {
-      regChunk++;
-      *keyValueType = atoi (regChunk);
-      while (*regChunk != 0 && *regChunk != ')')
-        regChunk++;
-      regChunk++;
-    }
-    else
-      *keyValueType = REG_BINARY;
-    if (*regChunk == ':')
-      regChunk++;
-  }
-  else if (strncmp (regChunk, "dword", 5) == 0)
-  {
-    strcpy (dataFormat, "dword");
-    *keyValueType = REG_DWORD;
-    regChunk += 5;
-    if (*regChunk == ':')
-      regChunk++;
-  }
-  else if (strncmp (regChunk, "multi", 5) == 0)
-  {
-    strcpy (dataFormat, "multi");
-    *keyValueType = REG_MULTI_SZ;
-    regChunk += 5;
-    if (*regChunk == ':')
-      regChunk++;
-  }
-  else if (strncmp (regChunk, "expand", 6) == 0)
-  {
-    strcpy (dataFormat, "expand");
-    *keyValueType = REG_EXPAND_SZ;
-    regChunk += 6;
-    if (*regChunk == ':')
-      regChunk++;
-  }
-  else
-  {
-    UNIMPLEMENTED();
-  }
-
-  return  *regChunk ? regChunk : 0;
-}
-
-static int 
-computeKeyValueDataSize (PCHAR  regChunk, PCHAR  dataFormat)
-{
-  int  dataSize = 0;
-
-  if (strcmp (dataFormat, "string") == 0)
-  {
-    regChunk++;
-    while (*regChunk != 0 && *regChunk != '\"')
-    {
-      dataSize++;
-      regChunk++;
-    }
-    dataSize++;
-  }
-  else if (strcmp (dataFormat, "hex") == 0)
-  {
-    while (*regChunk != 0 && isxdigit(*regChunk))
-    {
-      regChunk++;
-      regChunk++;
-      dataSize++;
-      if (*regChunk == ',')
-      {
-        regChunk++;
-        if (*regChunk == '\\')
-        {
-          regChunk++;
-          regChunk = skipWhitespaceInChunk (regChunk);
-        }
-      }
-    }
-  }
-  else if (strcmp (dataFormat, "dword") == 0)
-  {
-    dataSize = sizeof(U32);
-    while (*regChunk != 0 && isxdigit(*regChunk))
-    {
-      regChunk++;
-    }
-  }
-  else if (strcmp (dataFormat, "multi") == 0)
-  {
-    while (*regChunk == '\"')
-    {
-      regChunk++;
-      while (*regChunk != 0 && *regChunk != '\"')
-      {
-        dataSize++;
-        regChunk++;
-      }
-      regChunk++;
-      dataSize++;
-      if (*regChunk == ',')
-      {
-        regChunk++;
-        regChunk = skipWhitespaceInChunk (regChunk);
-        if (*regChunk == '\\')
-        {
-          regChunk++;
-          regChunk = skipWhitespaceInChunk (regChunk);
-        }
-      }
-      else
-        break;
-    }
-    dataSize++;
-  }
-  else if (strcmp (dataFormat, "expand") == 0)
-  {
-    regChunk++;
-    while (*regChunk != 0 && *regChunk != '\"')
-    {
-      dataSize++;
-      regChunk++;
-    }
-    dataSize++;
-  }
-  else
-  {
-    UNIMPLEMENTED();
-  }
-
-  return  dataSize;
-}
-
-static BOOL
-allocateDataBuffer (PVOID * data, int * dataBufferSize, int dataSize)
-{
-  if (*dataBufferSize < dataSize)
-  {
-    if (*dataBufferSize > 0)
-      MmFreeMemory(*data);
-    *data = MmAllocateMemory(dataSize);
-    *dataBufferSize = dataSize;
-  }
-
-  return  TRUE;
-}
-
-static PCHAR
-getKeyValueDataFromChunk (PCHAR  regChunk, PCHAR  dataFormat, PCHAR data)
-{
-  char  dataValue;
-  U32 ulValue;
-  PCHAR ptr;
-  
-  if (strcmp (dataFormat, "string") == 0)
-  {
-    /* convert quoted string to zero-terminated Unicode string */
-    ptr = (PCHAR)data;
-    regChunk++;
-    while (*regChunk != 0 && *regChunk != '\"')
-    {
-      *ptr++ = (CHAR)*regChunk++;
-    }
-    *ptr = 0;
-    regChunk++;
-  }
-  else if (strcmp (dataFormat, "hex") == 0)
-  {
-    while (*regChunk != 0 && isxdigit (*regChunk))
-    {
-      dataValue = (isdigit (*regChunk) ? *regChunk - '0' : 
-        tolower(*regChunk) - 'a') << 4;
-      regChunk++;
-      dataValue += (isdigit (*regChunk) ? *regChunk - '0' : 
-        tolower(*regChunk) - 'a');
-      regChunk++;
-      *data++ = dataValue;
-      if (*regChunk == ',')
-      {
-        regChunk++;
-        if (*regChunk == '\\')
-        {
-          regChunk++;
-          regChunk = skipWhitespaceInChunk (regChunk);
-        }
-      }
-    }
-  }
-  else if (strcmp (dataFormat, "dword") == 0)
-  {
-    ulValue = 0;
-    while (*regChunk != 0 && isxdigit(*regChunk))
-    {
-      dataValue = (isdigit (*regChunk) ? *regChunk - '0' : 
-        tolower(*regChunk) - 'a');
-      ulValue = (ulValue << 4) + dataValue;
-      regChunk++;
-    }
-    memcpy(data, &ulValue, sizeof(U32));
-  }
-  else if (strcmp (dataFormat, "multi") == 0)
-  {
-    ptr = (PCHAR)data;
-    while (*regChunk == '\"')
-    {
-      regChunk++;
-      while (*regChunk != 0 && *regChunk != '\"')
-      {
-        *ptr++ = (CHAR)*regChunk++;
-      }
-      regChunk++;
-      *ptr++ = 0;
-      if (*regChunk == ',')
-      {
-        regChunk++;
-        regChunk = skipWhitespaceInChunk (regChunk);
-        if (*regChunk == '\\')
-        {
-          regChunk++;
-          regChunk = skipWhitespaceInChunk (regChunk);
-        }
-      }
-      else
-        break;
-    }
-    *ptr = 0;
-  }
-  else if (strcmp (dataFormat, "expand") == 0)
-  {
-    /* convert quoted string to zero-terminated Unicode string */
-    ptr = (PCHAR)data;
-    regChunk++;
-    while (*regChunk != 0 && *regChunk != '\"')
-    {
-      *ptr++ = (CHAR)*regChunk++;
-    }
-    *ptr = 0;
-    regChunk++;
-  }
-  else
-  {
-    UNIMPLEMENTED();
-  }
-
-  return  *regChunk ? regChunk : 0;
-}
-
-static BOOL
-setKeyValue (HKEY currentKey,
-             PCHAR newValueName,
-             U32 keyValueType,
-             PVOID data,
-             U32 dataSize)
-{
-  S32 status;
-
-  DbgPrint((DPRINT_REGISTRY, "Adding value (%s) to current key, with data type %d and size %d\n",
-    newValueName, (int)keyValueType, (int)dataSize));
-
-  status = RegSetValue(currentKey,
-                      newValueName,
-                      keyValueType,
-                      data,
-                      dataSize);
-  if (status != ERROR_SUCCESS)
-  {
-    DbgPrint((DPRINT_REGISTRY, "Could not set key value. status: %d\n", status));
-    return  FALSE;
-  }
-
-  return  TRUE;
-}
-
-BOOL
-RegImportTextHive(PCHAR ChunkBase,
-                 U32 ChunkSize)
-{
-  HKEY  currentKey = INVALID_HANDLE_VALUE;
-  char *newKeyName = NULL;
-  int  newKeySize;
-  char  dataFormat [10];
-  int  keyValueType;
-  int  dataSize = 0;
-  int  dataBufferSize = 0;
-  PVOID  data = 0;
-  PCHAR regChunk;
-
-  DbgPrint((DPRINT_REGISTRY, "ChunkBase %p  ChunkSize %lx\n", ChunkBase, ChunkSize));
-
-  regChunk = checkAndSkipMagic (ChunkBase);
-  if (regChunk == 0)
-    return FALSE;
-
-  while (regChunk != 0 && *regChunk != 0 && (((U32)regChunk-(U32)ChunkBase) < ChunkSize))
-  {
-    regChunk = skipWhitespaceInChunk (regChunk);
-    if (regChunk == 0)
-      continue;
-
-    if (*regChunk == '[')
-    {
-      if (currentKey != INVALID_HANDLE_VALUE)
-      {
-        DbgPrint((DPRINT_REGISTRY, "Closing current key: 0x%lx\n", currentKey));
-        currentKey = INVALID_HANDLE_VALUE;
-      }
-
-      regChunk++;
-
-      newKeySize = computeKeyNameSize (regChunk);
-      if (!allocateKeyName (&newKeyName, newKeySize))
-      {
-        regChunk = 0;
-        continue;
-      }
-
-      regChunk = getKeyNameFromChunk (regChunk, newKeyName);
-      if (regChunk == 0)
-        continue;
-
-      currentKey = createNewKey (newKeyName);
-      if (currentKey == INVALID_HANDLE_VALUE)
-      {
-        regChunk = skipToNextKeyInChunk (regChunk);
-        continue;
-      }
-
-      regChunk++;
-    }
-    else
-    {
-      if (currentKey == INVALID_HANDLE_VALUE)
-      {
-        regChunk = skipToNextKeyInChunk (regChunk);
-        continue;
-      }
-
-      newKeySize = computeKeyValueNameSize (regChunk);
-      if (!allocateKeyName (&newKeyName, newKeySize))
-      {
-        regChunk = 0;
-        continue;
-      }
-
-      regChunk = getKeyValueNameFromChunk (regChunk, newKeyName);
-      if (regChunk == 0)
-        continue;
-
-      if (*regChunk != '=')
-      {
-        regChunk = skipToNextKeyValueInChunk (regChunk);
-        continue;
-      }
-      regChunk++;
-
-      regChunk = getKeyValueTypeFromChunk (regChunk, dataFormat, &keyValueType);
-      if (regChunk == 0)
-        continue;
-
-      dataSize = computeKeyValueDataSize (regChunk, dataFormat);
-      if (!allocateDataBuffer (&data, &dataBufferSize, dataSize))
-      {
-        regChunk = 0;
-        continue;
-      }
-      
-      regChunk = getKeyValueDataFromChunk (regChunk, dataFormat, data);
-      if (regChunk == 0)
-        continue;
-
-      if (!setKeyValue (currentKey, newKeyName, keyValueType, data, dataSize))
-      {
-        regChunk = 0;
-        continue;
-      }
-    }
-  }
-
-  if (currentKey != INVALID_HANDLE_VALUE)
-  {
-    DbgPrint((DPRINT_REGISTRY, "Closing current key: 0x%lx\n", currentKey));
-  }
-
-  if (newKeyName != NULL)
-  {
-    MmFreeMemory(newKeyName);
-  }
-
-  if (data != NULL)
-  {
-    MmFreeMemory(data);
-  }
-
-  return TRUE;
-}
-
-#if 0
-BOOL
-RegExportHive(PCHAR ChunkBase, U32* ChunkSize)
-{
-  return(TRUE);
-}
-#endif
-
-/* EOF */
index 3b2ebad..4cfdb0f 100644 (file)
@@ -288,10 +288,6 @@ U32
 RegGetValueCount (HKEY Key);
 
 
-BOOL
-RegImportTextHive (PCHAR ChunkBase,
-                  U32 ChunkSize);
-
 BOOL
 RegImportBinaryHive (PCHAR ChunkBase,
                     U32 ChunkSize);
index ac63fe3..df8b15b 100644 (file)
@@ -28,6 +28,7 @@
 #include <multiboot.h>
 #include <mm.h>
 #include <ui.h>
+#include <inffile.h>
 
 #include "registry.h"
 
@@ -238,6 +239,10 @@ VOID RunLoader(VOID)
   char *SourcePath;
   char *LoadOptions;
 
+  HINF InfHandle;
+  U32 ErrorLine;
+  INFCONTEXT InfContext;
+
   /* Setup multiboot information structure */
   mb_info.flags = MB_INFO_FLAG_MEM_SIZE | MB_INFO_FLAG_BOOT_DEVICE | MB_INFO_FLAG_COMMAND_LINE | MB_INFO_FLAG_MODULES;
   mb_info.mem_lower = GetConventionalMemorySize();
@@ -298,9 +303,46 @@ VOID RunLoader(VOID)
   ((char *)(&mb_info.boot_device))[1] = (char)BootPartition;
 
 
-  /* Set load options */
-//  LoadOptions = "/DEBUGPORT=COM1";
-  LoadOptions = "/DEBUGPORT=SCREEN";
+  /* Open boot drive */
+  if (!FsOpenVolume(BootDrive, BootPartition))
+    {
+#ifdef USE_UI
+      UiMessageBox("Failed to open boot drive.");
+#else
+      printf("Failed to open boot drive.");
+#endif
+      return;
+    }
+
+  /* Open 'txtsetup.sif' */
+  if (!InfOpenFile (&InfHandle,
+                   (BootDrive < 0x80) ? "\\txtsetup.sif" : "\\reactos\\txtsetup.sif",
+                   &ErrorLine))
+    {
+      printf("Failed to open 'txtsetup.sif'\n");
+      return;
+    }
+
+  /* Get load options */
+  if (!InfFindFirstLine (InfHandle,
+                        "SetupData",
+                        "OsLoadOptions",
+                        &InfContext))
+    {
+      printf("Failed to find 'SetupData/OsLoadOptions'\n");
+      return;
+    }
+
+  if (!InfGetDataField (&InfContext,
+                       1,
+                       &LoadOptions))
+    {
+      printf("Failed to get load options\n");
+      return;
+    }
+#if 0
+  printf("LoadOptions: '%s'\n", LoadOptions);
+#endif
 
   if (BootDrive < 0x80)
     {
@@ -321,18 +363,6 @@ VOID RunLoader(VOID)
          SourcePath,
          LoadOptions);
 
-
-  /* Open boot drive */
-  if (!FsOpenVolume(BootDrive, BootPartition))
-    {
-#ifdef USE_UI
-      UiMessageBox("Failed to open boot drive.");
-#else
-      printf("Failed to open boot drive.");
-#endif
-      return;
-    }
-
   /* Load ntoskrnl.exe */
   if (!LoadKernel(SourcePath, "ntoskrnl.exe"))
     return;