CLEAN_FILES = $(TOOLS)
-all: $(TOOLS) wmc_directory_target cdmake_directory_target
+all: $(TOOLS) wmc_target cdmake_target mkhive_target
buildno$(EXE_POSTFIX): buildno.c ../include/reactos/version.h
$(HOST_CC) $(CFLAGS) -o buildno$(EXE_POSTFIX) buildno.c
endif
-wmc_directory_target:
+wmc_target:
$(MAKE) -C wmc wmc$(EXE_POSTFIX)
-cdmake_directory_target:
+cdmake_target:
$(MAKE) -C cdmake cdmake$(EXE_POSTFIX)
+mkhive_target:
+ $(MAKE) -C mkhive mkhive$(EXE_POSTFIX)
+
+
ifeq ($(HOST),mingw32-linux)
clean:
$(MAKE) -C cdmake clean
+ $(MAKE) -C mkhive clean
$(MAKE) -C wmc clean
rm mkconfig
rm $(TOOLS)
ifeq ($(HOST),mingw32-windows)
clean:
$(MAKE) -C cdmake clean
+ $(MAKE) -C mkhive clean
$(MAKE) -C wmc clean
del *$(EXE_POSTFIX)
endif
--- /dev/null
+#
+# Hive-Maker
+#
+PATH_TO_TOP = ../..
+
+TARGET = mkhive$(EXE_POSTFIX)
+
+all: $(TARGET)
+
+OBJECTS = mkhive.o binhive.o infcache.o reginf.o registry.o
+
+CLEAN_FILES = *.o mkhive$(EXE_POSTFIX)
+
+HOST_CFLAGS = -I.
+
+mkhive.o: mkhive.c
+ $(HOST_CC) $(HOST_CFLAGS) -c mkhive.c -o mkhive.o
+
+binhive.o: binhive.c
+ $(HOST_CC) $(HOST_CFLAGS) -c binhive.c -o binhive.o
+
+infcache.o: infcache.c
+ $(HOST_CC) $(HOST_CFLAGS) -c infcache.c -o infcache.o
+
+reginf.o: reginf.c
+ $(HOST_CC) $(HOST_CFLAGS) -c reginf.c -o reginf.o
+
+registry.o: registry.c
+ $(HOST_CC) $(HOST_CFLAGS) -c registry.c -o registry.o
+
+mkhive$(EXE_POSTFIX): $(OBJECTS)
+ $(HOST_CC) $(OBJECTS) -o mkhive$(EXE_POSTFIX)
+
+ifeq ($(HOST),mingw32-linux)
+clean:
+ rm -f *.o
+ rm -f mkhive$(EXE_POSTFIX)
+endif
+ifeq ($(HOST),mingw32-windows)
+clean:
+ del *.o
+ del mkhive$(EXE_POSTFIX)
+endif
+
+.phony: clean
+
+include $(PATH_TO_TOP)/rules.mak
+
+# EOF
--- /dev/null
+/*
+ * ReactOS kernel
+ * Copyright (C) 2003 ReactOS Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* $Id: binhive.c,v 1.1 2003/04/14 17:18:48 ekohl Exp $
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS hive maker
+ * FILE: tools/mkhive/binhive.c
+ * PURPOSE: Binary hive export code
+ * PROGRAMMER: Eric Kohl
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include "mkhive.h"
+
+BOOL
+ExportBinaryHive (PCHAR FileName,
+ PCHAR KeyName)
+{
+ return TRUE;
+}
+
+/* EOF */
--- /dev/null
+/*
+ * ReactOS kernel
+ * Copyright (C) 2003 ReactOS Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* $Id: binhive.h,v 1.1 2003/04/14 17:18:48 ekohl Exp $
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS hive maker
+ * FILE: tools/mkhive/binhive.h
+ * PURPOSE: Binary hive export code
+ * PROGRAMMER: Eric Kohl
+ */
+
+#ifndef __BINHIVE_H__
+#define __BINHIVE_H__
+
+BOOL
+ExportBinaryHive (PCHAR FileName,
+ PCHAR KeyName);
+
+#endif /* __BINHIVE_H__ */
+
+/* EOF */
--- /dev/null
+/*
+ * ReactOS kernel
+ * Copyright (C) 2003 ReactOS Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* $Id: infcache.c,v 1.1 2003/04/14 17:18:48 ekohl Exp $
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS hive maker
+ * FILE: tools/mkhive/infcache.c
+ * PURPOSE: INF file parser that caches contents of INF file in memory
+ * PROGRAMMER: Royce Mitchell III
+ * Eric Kohl
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "mkhive.h"
+#include "infcache.h"
+
+
+#define CONTROL_Z '\x1a'
+#define MAX_SECTION_NAME_LEN 255
+#define MAX_FIELD_LEN 511 /* larger fields get silently truncated */
+/* actual string limit is MAX_INF_STRING_LENGTH+1 (plus terminating null) under Windows */
+#define MAX_STRING_LEN (MAX_INF_STRING_LENGTH+1)
+
+
+typedef struct _INFCACHEFIELD
+{
+ struct _INFCACHEFIELD *Next;
+ struct _INFCACHEFIELD *Prev;
+
+ CHAR Data[1];
+} INFCACHEFIELD, *PINFCACHEFIELD;
+
+
+typedef struct _INFCACHELINE
+{
+ struct _INFCACHELINE *Next;
+ struct _INFCACHELINE *Prev;
+
+ LONG FieldCount;
+
+ PCHAR Key;
+
+ PINFCACHEFIELD FirstField;
+ PINFCACHEFIELD LastField;
+
+} INFCACHELINE, *PINFCACHELINE;
+
+
+typedef struct _INFCACHESECTION
+{
+ struct _INFCACHESECTION *Next;
+ struct _INFCACHESECTION *Prev;
+
+ PINFCACHELINE FirstLine;
+ PINFCACHELINE LastLine;
+
+ LONG LineCount;
+
+ CHAR Name[1];
+} INFCACHESECTION, *PINFCACHESECTION;
+
+
+typedef struct _INFCACHE
+{
+ PINFCACHESECTION FirstSection;
+ PINFCACHESECTION LastSection;
+
+ PINFCACHESECTION StringsSection;
+} INFCACHE, *PINFCACHE;
+
+
+/* parser definitions */
+
+enum parser_state
+{
+ LINE_START, /* at beginning of a line */
+ SECTION_NAME, /* parsing a section name */
+ KEY_NAME, /* parsing a key name */
+ VALUE_NAME, /* parsing a value name */
+ EOL_BACKSLASH, /* backslash at end of line */
+ QUOTES, /* inside quotes */
+ LEADING_SPACES, /* leading spaces */
+ TRAILING_SPACES, /* trailing spaces */
+ COMMENT, /* inside a comment */
+ NB_PARSER_STATES
+};
+
+struct parser
+{
+ const CHAR *start; /* start position of item being parsed */
+ const CHAR *end; /* end of buffer */
+ PINFCACHE file; /* file being built */
+ enum parser_state state; /* current parser state */
+ enum parser_state stack[4]; /* state stack */
+ int stack_pos; /* current pos in stack */
+
+ PINFCACHESECTION cur_section; /* pointer to the section being parsed*/
+ PINFCACHELINE line; /* current line */
+ unsigned int line_pos; /* current line position in file */
+ unsigned int error; /* error code */
+ unsigned int token_len; /* current token len */
+ CHAR token[MAX_FIELD_LEN+1]; /* current token */
+};
+
+typedef const CHAR * (*parser_state_func)( struct parser *parser, const CHAR *pos );
+
+/* parser state machine functions */
+static const CHAR *line_start_state( struct parser *parser, const CHAR *pos );
+static const CHAR *section_name_state( struct parser *parser, const CHAR *pos );
+static const CHAR *key_name_state( struct parser *parser, const CHAR *pos );
+static const CHAR *value_name_state( struct parser *parser, const CHAR *pos );
+static const CHAR *eol_backslash_state( struct parser *parser, const CHAR *pos );
+static const CHAR *quotes_state( struct parser *parser, const CHAR *pos );
+static const CHAR *leading_spaces_state( struct parser *parser, const CHAR *pos );
+static const CHAR *trailing_spaces_state( struct parser *parser, const CHAR *pos );
+static const CHAR *comment_state( struct parser *parser, const CHAR *pos );
+
+static const parser_state_func parser_funcs[NB_PARSER_STATES] =
+{
+ line_start_state, /* LINE_START */
+ section_name_state, /* SECTION_NAME */
+ key_name_state, /* KEY_NAME */
+ value_name_state, /* VALUE_NAME */
+ eol_backslash_state, /* EOL_BACKSLASH */
+ quotes_state, /* QUOTES */
+ leading_spaces_state, /* LEADING_SPACES */
+ trailing_spaces_state, /* TRAILING_SPACES */
+ comment_state /* COMMENT */
+};
+
+
+/* PRIVATE FUNCTIONS ********************************************************/
+
+static PINFCACHELINE
+InfpCacheFreeLine (PINFCACHELINE Line)
+{
+ PINFCACHELINE Next;
+ PINFCACHEFIELD Field;
+
+ if (Line == NULL)
+ {
+ return NULL;
+ }
+
+ Next = Line->Next;
+ if (Line->Key != NULL)
+ {
+ free (Line->Key);
+ Line->Key = NULL;
+ }
+
+ /* Remove data fields */
+ while (Line->FirstField != NULL)
+ {
+ Field = Line->FirstField->Next;
+ free (Line->FirstField);
+ Line->FirstField = Field;
+ }
+ Line->LastField = NULL;
+
+ free (Line);
+
+ return Next;
+}
+
+
+static PINFCACHESECTION
+InfpCacheFreeSection (PINFCACHESECTION Section)
+{
+ PINFCACHESECTION Next;
+
+ if (Section == NULL)
+ {
+ return NULL;
+ }
+
+ /* Release all keys */
+ Next = Section->Next;
+ while (Section->FirstLine != NULL)
+ {
+ Section->FirstLine = InfpCacheFreeLine (Section->FirstLine);
+ }
+ Section->LastLine = NULL;
+
+ free (Section);
+
+ return Next;
+}
+
+
+static PINFCACHESECTION
+InfpCacheFindSection (PINFCACHE Cache,
+ PCHAR Name)
+{
+ PINFCACHESECTION Section = NULL;
+
+ if (Cache == NULL || Name == NULL)
+ {
+ return NULL;
+ }
+
+ /* iterate through list of sections */
+ Section = Cache->FirstSection;
+ while (Section != NULL)
+ {
+ if (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;
+ ULONG Size;
+
+ if (Cache == NULL || Name == NULL)
+ {
+ DPRINT ("Invalid parameter\n");
+ return NULL;
+ }
+
+ /* Allocate and initialize the new section */
+ Size = sizeof(INFCACHESECTION) + strlen (Name);
+ Section = (PINFCACHESECTION)malloc (Size);
+ if (Section == NULL)
+ {
+ DPRINT ("RtlAllocateHeap() failed\n");
+ return NULL;
+ }
+ memset (Section, 0, Size);
+
+ /* Copy section name */
+ strcpy (Section->Name, Name);
+
+ /* Append section */
+ if (Cache->FirstSection == NULL)
+ {
+ Cache->FirstSection = Section;
+ Cache->LastSection = Section;
+ }
+ else
+ {
+ Cache->LastSection->Next = Section;
+ Section->Prev = Cache->LastSection;
+ Cache->LastSection = Section;
+ }
+
+ return Section;
+}
+
+
+static PINFCACHELINE
+InfpCacheAddLine (PINFCACHESECTION Section)
+{
+ PINFCACHELINE Line;
+
+ if (Section == NULL)
+ {
+ DPRINT("Invalid parameter\n");
+ return NULL;
+ }
+
+ Line = (PINFCACHELINE)malloc (sizeof(INFCACHELINE));
+ if (Line == NULL)
+ {
+ DPRINT("RtlAllocateHeap() failed\n");
+ return NULL;
+ }
+ memset (Line, 0, sizeof(INFCACHELINE));
+
+ /* Append line */
+ if (Section->FirstLine == NULL)
+ {
+ Section->FirstLine = Line;
+ Section->LastLine = Line;
+ }
+ else
+ {
+ Section->LastLine->Next = Line;
+ Line->Prev = Section->LastLine;
+ Section->LastLine = Line;
+ }
+ Section->LineCount++;
+
+ return Line;
+}
+
+
+static PVOID
+InfpAddKeyToLine (PINFCACHELINE Line,
+ PCHAR Key)
+{
+ if (Line == NULL)
+ return NULL;
+
+ if (Line->Key != NULL)
+ return NULL;
+
+ Line->Key = (PCHAR)malloc (strlen (Key) + 1);
+ if (Line->Key == NULL)
+ return NULL;
+
+ strcpy (Line->Key, Key);
+
+ return (PVOID)Line->Key;
+}
+
+
+static PVOID
+InfpAddFieldToLine (PINFCACHELINE Line,
+ PCHAR Data)
+{
+ PINFCACHEFIELD Field;
+ ULONG Size;
+
+ Size = sizeof(INFCACHEFIELD) + strlen(Data);
+ Field = (PINFCACHEFIELD)malloc (Size);
+ if (Field == NULL)
+ {
+ return NULL;
+ }
+ memset (Field, 0, Size);
+ strcpy (Field->Data, Data);
+
+ /* Append key */
+ if (Line->FirstField == NULL)
+ {
+ Line->FirstField = Field;
+ Line->LastField = Field;
+ }
+ else
+ {
+ Line->LastField->Next = Field;
+ Field->Prev = Line->LastField;
+ Line->LastField = Field;
+ }
+ Line->FieldCount++;
+
+ return (PVOID)Field;
+}
+
+
+static PINFCACHELINE
+InfpCacheFindKeyLine (PINFCACHESECTION Section,
+ PCHAR Key)
+{
+ PINFCACHELINE Line;
+
+ Line = Section->FirstLine;
+ while (Line != NULL)
+ {
+ if (Line->Key != NULL && 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 == '\r' /*'\n'*/);
+}
+
+
+/* push data from current token start up to pos into the current token */
+static int push_token( struct parser *parser, const CHAR *pos )
+{
+ int len = pos - parser->start;
+ const CHAR *src = parser->start;
+ CHAR *dst = parser->token + parser->token_len;
+
+ if (len > MAX_FIELD_LEN - parser->token_len)
+ len = MAX_FIELD_LEN - parser->token_len;
+
+ parser->token_len += len;
+ for ( ; len > 0; len--, dst++, src++)
+ *dst = *src ? *src : ' ';
+ *dst = 0;
+ parser->start = pos;
+
+ return 0;
+}
+
+
+
+/* add a section with the current token as name */
+static PVOID add_section_from_token( struct parser *parser )
+{
+ PINFCACHESECTION Section;
+
+ if (parser->token_len > MAX_SECTION_NAME_LEN)
+ {
+ parser->error = STATUS_SECTION_NAME_TOO_LONG;
+ return NULL;
+ }
+
+ Section = InfpCacheFindSection (parser->file,
+ parser->token);
+ if (Section == NULL)
+ {
+ /* need to create a new one */
+ Section= InfpCacheAddSection (parser->file,
+ parser->token);
+ if (Section == NULL)
+ {
+ parser->error = STATUS_NOT_ENOUGH_MEMORY;
+ return NULL;
+ }
+ }
+
+ parser->token_len = 0;
+ parser->cur_section = Section;
+
+ return (PVOID)Section;
+}
+
+
+/* add a field containing the current token to the current line */
+static struct field *add_field_from_token( struct parser *parser, int is_key )
+{
+ PVOID field;
+ CHAR *text;
+
+ if (!parser->line) /* need to start a new line */
+ {
+ if (parser->cur_section == NULL) /* got a line before the first section */
+ {
+ parser->error = STATUS_WRONG_INF_STYLE;
+ return NULL;
+ }
+
+ parser->line = InfpCacheAddLine (parser->cur_section);
+ if (parser->line == NULL)
+ goto error;
+ }
+ else
+ {
+// assert(!is_key);
+ }
+
+ if (is_key)
+ {
+ field = InfpAddKeyToLine(parser->line, parser->token);
+ }
+ else
+ {
+ field = InfpAddFieldToLine(parser->line, parser->token);
+ }
+
+ if (field != NULL)
+ {
+ parser->token_len = 0;
+ return field;
+ }
+
+error:
+ parser->error = STATUS_NOT_ENOUGH_MEMORY;
+ return NULL;
+}
+
+
+/* close the current line and prepare for parsing a new one */
+static void close_current_line( struct parser *parser )
+{
+ parser->line = NULL;
+}
+
+
+
+/* handler for parser LINE_START state */
+static const CHAR *line_start_state( struct parser *parser, const CHAR *pos )
+{
+ const CHAR *p;
+
+ for (p = pos; !is_eof( parser, p ); p++)
+ {
+ switch(*p)
+ {
+// case '\n':
+ case '\r':
+ p++;
+ 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 '\n':
+ case '\r':
+ parser->line_pos++;
+// parser->start = p + 1;
+ parser->start = p + 2;
+ set_state( parser, LEADING_SPACES );
+// return p + 1;
+ return p + 2;
+ case '\\':
+ continue;
+ case ';':
+ push_state( parser, EOL_BACKSLASH );
+ set_state( parser, COMMENT );
+ return p + 1;
+ default:
+ if (isspace(*p))
+ continue;
+ push_token( parser, p );
+ pop_state( parser );
+ return p;
+ }
+ }
+ parser->start = p;
+ pop_state( parser );
+
+ return p;
+}
+
+
+/* handler for parser QUOTES state */
+static const CHAR *quotes_state( struct parser *parser, const CHAR *pos )
+{
+ const CHAR *p, *token_end = parser->start;
+
+ for (p = pos; !is_eol( parser, p ); p++)
+ {
+ if (*p == '"')
+ {
+ if (p+1 < parser->end && p[1] == '"') /* double quotes */
+ {
+ push_token( parser, p + 1 );
+ parser->start = token_end = p + 2;
+ p++;
+ }
+ else /* end of quotes */
+ {
+ push_token( parser, p );
+ parser->start = p + 1;
+ pop_state( parser );
+ return p + 1;
+ }
+ }
+ }
+ push_token( parser, p );
+ pop_state( parser );
+ return p;
+}
+
+
+/* handler for parser LEADING_SPACES state */
+static const CHAR *leading_spaces_state( struct parser *parser, const CHAR *pos )
+{
+ const CHAR *p;
+
+ for (p = pos; !is_eol( parser, p ); p++)
+ {
+ if (*p == '\\')
+ {
+ parser->start = p;
+ set_state( parser, EOL_BACKSLASH );
+ return p;
+ }
+ if (!isspace(*p))
+ break;
+ }
+ parser->start = p;
+ pop_state( parser );
+ return p;
+}
+
+
+/* handler for parser TRAILING_SPACES state */
+static const CHAR *trailing_spaces_state( struct parser *parser, const CHAR *pos )
+{
+ const CHAR *p;
+
+ for (p = pos; !is_eol( parser, p ); p++)
+ {
+ if (*p == '\\')
+ {
+ set_state( parser, EOL_BACKSLASH );
+ return p;
+ }
+ if (!isspace(*p))
+ break;
+ }
+ pop_state( parser );
+ return p;
+}
+
+
+/* handler for parser COMMENT state */
+static const CHAR *comment_state( struct parser *parser, const CHAR *pos )
+{
+ const CHAR *p = pos;
+
+ while (!is_eol( parser, p ))
+ p++;
+ pop_state( parser );
+ return p;
+}
+
+
+/* parse a complete buffer */
+static BOOL
+InfpParseBuffer (PINFCACHE file,
+ const CHAR *buffer,
+ const CHAR *end,
+ PULONG error_line)
+{
+ struct parser parser;
+ const CHAR *pos = buffer;
+
+ parser.start = buffer;
+ parser.end = end;
+ parser.file = file;
+ parser.line = NULL;
+ parser.state = LINE_START;
+ parser.stack_pos = 0;
+ parser.cur_section = NULL;
+ parser.line_pos = 1;
+ parser.error = 0;
+ parser.token_len = 0;
+
+ /* parser main loop */
+ while (pos)
+ pos = (parser_funcs[parser.state])(&parser, pos);
+
+ if (parser.error)
+ {
+ if (error_line)
+ *error_line = parser.line_pos;
+ return parser.error;
+ }
+
+ /* find the [strings] section */
+ file->StringsSection = InfpCacheFindSection (file,
+ "Strings");
+
+ return TRUE;
+}
+
+
+
+/* PUBLIC FUNCTIONS *********************************************************/
+
+BOOL
+InfOpenFile(PHINF InfHandle,
+ PCHAR FileName,
+ PULONG ErrorLine)
+{
+ FILE *File;
+ PCHAR FileBuffer;
+ ULONG FileLength;
+ PINFCACHE Cache;
+
+ *InfHandle = NULL;
+ *ErrorLine = (ULONG)-1;
+
+ /* Open the inf file */
+ File = fopen (FileName, "rb");
+ if (File == NULL)
+ {
+ DPRINT("fopen() failed\n");
+ return FALSE;
+ }
+
+ DPRINT("fopen() successful\n");
+
+ /* Query file size */
+ fseek (File, 0, SEEK_END);
+ FileLength = ftell (File);
+ fseek (File, 0, SEEK_SET);
+
+ DPRINT("File size: %lu\n", FileLength);
+
+ /* Allocate file buffer */
+ FileBuffer = malloc (FileLength + 1);
+ if (FileBuffer == NULL)
+ {
+ DPRINT1("malloc() failed\n");
+ fclose (File);
+ return FALSE;
+ }
+
+ /* Read file */
+ if (fread (FileBuffer, FileLength, 1, File) < 0)
+ {
+ DPRINT ("fread() failed\n");
+ fclose (File);
+ free (FileBuffer);
+ return FALSE;
+ }
+
+ fclose (File);
+
+ /* Append string terminator */
+ FileBuffer[FileLength] = 0;
+
+ /* Allocate infcache header */
+ Cache = (PINFCACHE)malloc (sizeof(INFCACHE));
+ if (Cache == NULL)
+ {
+ DPRINT("malloc() failed\n");
+ free (FileBuffer);
+ return FALSE;
+ }
+
+ /* Initialize inicache header */
+ memset (Cache, 0, sizeof(INFCACHE));
+
+ /* Parse the inf buffer */
+ if (!InfpParseBuffer (Cache,
+ FileBuffer,
+ FileBuffer + FileLength,
+ ErrorLine))
+ {
+ free (Cache);
+ free (FileBuffer);
+ return FALSE;
+ }
+
+ /* Free file buffer */
+ free (FileBuffer);
+
+ *InfHandle = (HINF)Cache;
+
+ return TRUE;
+}
+
+
+VOID
+InfCloseFile(HINF InfHandle)
+{
+ PINFCACHE Cache;
+
+ Cache = (PINFCACHE)InfHandle;
+
+ if (Cache == NULL)
+ {
+ return;
+ }
+
+ while (Cache->FirstSection != NULL)
+ {
+ Cache->FirstSection = InfpCacheFreeSection(Cache->FirstSection);
+ }
+ Cache->LastSection = NULL;
+
+ free (Cache);
+}
+
+
+BOOL
+InfFindFirstLine (HINF InfHandle,
+ PCHAR Section,
+ PCHAR Key,
+ PINFCONTEXT Context)
+{
+ PINFCACHE Cache;
+ PINFCACHESECTION CacheSection;
+ PINFCACHELINE CacheLine;
+
+ if (InfHandle == NULL || Section == NULL || Context == NULL)
+ {
+ DPRINT("Invalid parameter\n");
+ return FALSE;
+ }
+
+ Cache = (PINFCACHE)InfHandle;
+
+ /* Iterate through list of sections */
+ CacheSection = Cache->FirstSection;
+ while (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, (PCHAR)Key);
+ }
+ else
+ {
+ CacheLine = CacheSection->FirstLine;
+ }
+
+ if (CacheLine == NULL)
+ return FALSE;
+
+ Context->Inf = (PVOID)Cache;
+ Context->Section = (PVOID)CacheSection;
+ Context->Line = (PVOID)CacheLine;
+
+ return TRUE;
+ }
+
+ /* Get the next section */
+ CacheSection = CacheSection->Next;
+ }
+
+ DPRINT("Section not found\n");
+
+ return FALSE;
+}
+
+
+BOOL
+InfFindNextLine (PINFCONTEXT ContextIn,
+ PINFCONTEXT ContextOut)
+{
+ PINFCACHELINE CacheLine;
+
+ if (ContextIn == NULL || ContextOut == NULL)
+ return FALSE;
+
+ if (ContextIn->Line == NULL)
+ return FALSE;
+
+ CacheLine = (PINFCACHELINE)ContextIn->Line;
+ if (CacheLine->Next == NULL)
+ return FALSE;
+
+ if (ContextIn != ContextOut)
+ {
+ ContextOut->Inf = ContextIn->Inf;
+ ContextOut->Section = ContextIn->Section;
+ }
+ ContextOut->Line = (PVOID)(CacheLine->Next);
+
+ return TRUE;
+}
+
+
+BOOL
+InfFindFirstMatchLine (PINFCONTEXT ContextIn,
+ PCHAR Key,
+ PINFCONTEXT ContextOut)
+{
+ PINFCACHELINE CacheLine;
+
+ if (ContextIn == NULL || ContextOut == NULL || Key == NULL || *Key == 0)
+ return FALSE;
+
+ if (ContextIn->Inf == NULL || ContextIn->Section == NULL)
+ return FALSE;
+
+ CacheLine = ((PINFCACHESECTION)(ContextIn->Section))->FirstLine;
+ while (CacheLine != NULL)
+ {
+ if (CacheLine->Key != NULL && 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;
+}
+
+
+BOOL
+InfFindNextMatchLine (PINFCONTEXT ContextIn,
+ PCHAR Key,
+ PINFCONTEXT ContextOut)
+{
+ PINFCACHELINE CacheLine;
+
+ if (ContextIn == NULL || ContextOut == NULL || Key == NULL || *Key == 0)
+ return FALSE;
+
+ if (ContextIn->Inf == NULL || ContextIn->Section == NULL || ContextIn->Line == NULL)
+ return FALSE;
+
+ CacheLine = (PINFCACHELINE)ContextIn->Line;
+ while (CacheLine != NULL)
+ {
+ if (CacheLine->Key != NULL && 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;
+}
+
+
+LONG
+InfGetLineCount(HINF InfHandle,
+ PCHAR Section)
+{
+ PINFCACHE Cache;
+ PINFCACHESECTION CacheSection;
+
+ if (InfHandle == NULL || Section == NULL)
+ {
+ DPRINT("Invalid parameter\n");
+ return -1;
+ }
+
+ Cache = (PINFCACHE)InfHandle;
+
+ /* Iterate through list of sections */
+ CacheSection = Cache->FirstSection;
+ while (Section != NULL)
+ {
+ DPRINT("Comparing '%s' and '%s'\n", CacheSection->Name, Section);
+
+ /* Are the section names the same? */
+ if (stricmp(CacheSection->Name, Section) == 0)
+ {
+ return CacheSection->LineCount;
+ }
+
+ /* Get the next section */
+ CacheSection = CacheSection->Next;
+ }
+
+ DPRINT("Section not found\n");
+
+ return -1;
+}
+
+
+/* InfGetLineText */
+
+
+LONG
+InfGetFieldCount(PINFCONTEXT Context)
+{
+ if (Context == NULL || Context->Line == NULL)
+ return 0;
+
+ return ((PINFCACHELINE)Context->Line)->FieldCount;
+}
+
+
+BOOL
+InfGetBinaryField (PINFCONTEXT Context,
+ ULONG FieldIndex,
+ PUCHAR ReturnBuffer,
+ ULONG ReturnBufferSize,
+ PULONG RequiredSize)
+{
+ PINFCACHELINE CacheLine;
+ PINFCACHEFIELD CacheField;
+ ULONG Index;
+ ULONG Size;
+ PUCHAR Ptr;
+
+ if (Context == NULL || Context->Line == NULL || FieldIndex == 0)
+ {
+ DPRINT("Invalid parameter\n");
+ return FALSE;
+ }
+
+ if (RequiredSize != NULL)
+ *RequiredSize = 0;
+
+ CacheLine = (PINFCACHELINE)Context->Line;
+
+ if (FieldIndex > CacheLine->FieldCount)
+ return FALSE;
+
+ CacheField = CacheLine->FirstField;
+ for (Index = 1; Index < FieldIndex; Index++)
+ CacheField = CacheField->Next;
+
+ Size = CacheLine->FieldCount - FieldIndex + 1;
+
+ if (RequiredSize != NULL)
+ *RequiredSize = Size;
+
+ if (ReturnBuffer != NULL)
+ {
+ if (ReturnBufferSize < Size)
+ return FALSE;
+
+ /* Copy binary data */
+ Ptr = ReturnBuffer;
+ while (CacheField != NULL)
+ {
+ *Ptr = (UCHAR)strtoul (CacheField->Data, NULL, 16);
+
+ Ptr++;
+ CacheField = CacheField->Next;
+ }
+ }
+
+ return TRUE;
+}
+
+
+BOOL
+InfGetIntField (PINFCONTEXT Context,
+ ULONG FieldIndex,
+ PLONG IntegerValue)
+{
+ PINFCACHELINE CacheLine;
+ PINFCACHEFIELD CacheField;
+ ULONG Index;
+ PCHAR Ptr;
+
+ if (Context == NULL || Context->Line == NULL || IntegerValue == NULL)
+ {
+ DPRINT("Invalid parameter\n");
+ return FALSE;
+ }
+
+ CacheLine = (PINFCACHELINE)Context->Line;
+
+ if (FieldIndex > CacheLine->FieldCount)
+ {
+ DPRINT("Invalid parameter\n");
+ return FALSE;
+ }
+
+ if (FieldIndex == 0)
+ {
+ Ptr = CacheLine->Key;
+ }
+ else
+ {
+ CacheField = CacheLine->FirstField;
+ for (Index = 1; Index < FieldIndex; Index++)
+ CacheField = CacheField->Next;
+
+ Ptr = CacheField->Data;
+ }
+
+ *IntegerValue = strtol (Ptr, NULL, 0);
+
+ return TRUE;
+}
+
+
+BOOL
+InfGetMultiSzField (PINFCONTEXT Context,
+ ULONG FieldIndex,
+ PCHAR ReturnBuffer,
+ ULONG ReturnBufferSize,
+ PULONG RequiredSize)
+{
+ PINFCACHELINE CacheLine;
+ PINFCACHEFIELD CacheField;
+ PINFCACHEFIELD FieldPtr;
+ ULONG Index;
+ ULONG Size;
+ PCHAR Ptr;
+
+ if (Context == NULL || Context->Line == NULL || FieldIndex == 0)
+ {
+ DPRINT("Invalid parameter\n");
+ return FALSE;
+ }
+
+ if (RequiredSize != NULL)
+ *RequiredSize = 0;
+
+ CacheLine = (PINFCACHELINE)Context->Line;
+
+ if (FieldIndex > CacheLine->FieldCount)
+ return FALSE;
+
+ CacheField = CacheLine->FirstField;
+ for (Index = 1; Index < FieldIndex; Index++)
+ CacheField = CacheField->Next;
+
+ /* Calculate the required buffer size */
+ FieldPtr = CacheField;
+ Size = 0;
+ while (FieldPtr != NULL)
+ {
+ Size += (strlen (FieldPtr->Data) + 1);
+ FieldPtr = FieldPtr->Next;
+ }
+ Size++;
+
+ if (RequiredSize != NULL)
+ *RequiredSize = Size;
+
+ if (ReturnBuffer != NULL)
+ {
+ if (ReturnBufferSize < Size)
+ return FALSE;
+
+ /* Copy multi-sz string */
+ Ptr = ReturnBuffer;
+ FieldPtr = CacheField;
+ while (FieldPtr != NULL)
+ {
+ Size = strlen (FieldPtr->Data) + 1;
+
+ strcpy (Ptr, FieldPtr->Data);
+
+ Ptr = Ptr + Size;
+ FieldPtr = FieldPtr->Next;
+ }
+ *Ptr = 0;
+ }
+
+ return TRUE;
+}
+
+
+BOOL
+InfGetStringField (PINFCONTEXT Context,
+ ULONG FieldIndex,
+ PCHAR ReturnBuffer,
+ ULONG ReturnBufferSize,
+ PULONG RequiredSize)
+{
+ PINFCACHELINE CacheLine;
+ PINFCACHEFIELD CacheField;
+ ULONG Index;
+ PCHAR Ptr;
+ ULONG Size;
+
+ if (Context == NULL || Context->Line == NULL || FieldIndex == 0)
+ {
+ DPRINT("Invalid parameter\n");
+ return FALSE;
+ }
+
+ if (RequiredSize != NULL)
+ *RequiredSize = 0;
+
+ CacheLine = (PINFCACHELINE)Context->Line;
+
+ if (FieldIndex > CacheLine->FieldCount)
+ return FALSE;
+
+ if (FieldIndex == 0)
+ {
+ Ptr = CacheLine->Key;
+ }
+ else
+ {
+ CacheField = CacheLine->FirstField;
+ for (Index = 1; Index < FieldIndex; Index++)
+ CacheField = CacheField->Next;
+
+ Ptr = CacheField->Data;
+ }
+
+ Size = wcslen (Ptr) + 1;
+
+ if (RequiredSize != NULL)
+ *RequiredSize = Size;
+
+ if (ReturnBuffer != NULL)
+ {
+ if (ReturnBufferSize < Size)
+ return FALSE;
+
+ strcpy (ReturnBuffer, Ptr);
+ }
+
+ return TRUE;
+}
+
+
+
+
+BOOL
+InfGetData (PINFCONTEXT Context,
+ PCHAR *Key,
+ PCHAR *Data)
+{
+ PINFCACHELINE CacheKey;
+
+ if (Context == NULL || Context->Line == NULL || Data == NULL)
+ {
+ DPRINT("Invalid parameter\n");
+ return FALSE;
+ }
+
+ CacheKey = (PINFCACHELINE)Context->Line;
+ if (Key != NULL)
+ *Key = CacheKey->Key;
+
+ if (Data != NULL)
+ {
+ if (CacheKey->FirstField == NULL)
+ {
+ *Data = NULL;
+ }
+ else
+ {
+ *Data = CacheKey->FirstField->Data;
+ }
+ }
+
+ return TRUE;
+}
+
+
+BOOL
+InfGetDataField (PINFCONTEXT Context,
+ ULONG FieldIndex,
+ PCHAR *Data)
+{
+ PINFCACHELINE CacheLine;
+ PINFCACHEFIELD CacheField;
+ ULONG Index;
+
+ if (Context == NULL || Context->Line == NULL || Data == NULL)
+ {
+ DPRINT("Invalid parameter\n");
+ return FALSE;
+ }
+
+ CacheLine = (PINFCACHELINE)Context->Line;
+
+ if (FieldIndex > CacheLine->FieldCount)
+ return FALSE;
+
+ if (FieldIndex == 0)
+ {
+ *Data = CacheLine->Key;
+ }
+ else
+ {
+ CacheField = CacheLine->FirstField;
+ for (Index = 1; Index < FieldIndex; Index++)
+ CacheField = CacheField->Next;
+
+ *Data = CacheField->Data;
+ }
+
+ return TRUE;
+}
+
+
+/* EOF */
--- /dev/null
+/*
+ * ReactOS kernel
+ * Copyright (C) 2003 ReactOS Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* $Id: infcache.h,v 1.1 2003/04/14 17:18:48 ekohl Exp $
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS hive maker
+ * FILE: tools/mkhive/infcache.h
+ * PURPOSE: INF file parser that caches contents of INF file in memory
+ * PROGRAMMER: Royce Mitchell III
+ * Eric Kohl
+ */
+
+/* INCLUDES *****************************************************************/
+
+#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 PVOID HINF, *PHINF;
+
+typedef struct _INFCONTEXT
+{
+ PVOID Inf;
+// PVOID CurrentInf;
+ PVOID Section;
+ PVOID Line;
+} INFCONTEXT, *PINFCONTEXT;
+
+
+/* FUNCTIONS ****************************************************************/
+
+BOOL
+InfOpenFile (PHINF InfHandle,
+ PCHAR FileName,
+ PULONG ErrorLine);
+
+VOID
+InfCloseFile (HINF InfHandle);
+
+
+BOOL
+InfFindFirstLine (HINF InfHandle,
+ PCHAR Section,
+ PCHAR Key,
+ PINFCONTEXT Context);
+
+BOOL
+InfFindNextLine (PINFCONTEXT ContextIn,
+ PINFCONTEXT ContextOut);
+
+BOOL
+InfFindFirstMatchLine (PINFCONTEXT ContextIn,
+ PCHAR Key,
+ PINFCONTEXT ContextOut);
+
+BOOL
+InfFindNextMatchLine (PINFCONTEXT ContextIn,
+ PCHAR Key,
+ PINFCONTEXT ContextOut);
+
+
+LONG
+InfGetLineCount (HINF InfHandle,
+ PCHAR Section);
+
+LONG
+InfGetFieldCount (PINFCONTEXT Context);
+
+
+BOOL
+InfGetBinaryField (PINFCONTEXT Context,
+ ULONG FieldIndex,
+ PUCHAR ReturnBuffer,
+ ULONG ReturnBufferSize,
+ PULONG RequiredSize);
+
+BOOL
+InfGetIntField (PINFCONTEXT Context,
+ ULONG FieldIndex,
+ PLONG IntegerValue);
+
+BOOL
+InfGetMultiSzField (PINFCONTEXT Context,
+ ULONG FieldIndex,
+ PCHAR ReturnBuffer,
+ ULONG ReturnBufferSize,
+ PULONG RequiredSize);
+
+BOOL
+InfGetStringField (PINFCONTEXT Context,
+ ULONG FieldIndex,
+ PCHAR ReturnBuffer,
+ ULONG ReturnBufferSize,
+ PULONG RequiredSize);
+
+
+
+BOOL
+InfGetData (PINFCONTEXT Context,
+ PCHAR *Key,
+ PCHAR *Data);
+
+BOOL
+InfGetDataField (PINFCONTEXT Context,
+ ULONG FieldIndex,
+ PCHAR *Data);
+
+#endif /* __INFCACHE_H__ */
+
+/* EOF */
--- /dev/null
+/*
+ * ReactOS kernel
+ * Copyright (C) 2003 ReactOS Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* $Id: mkhive.c,v 1.1 2003/04/14 17:18:48 ekohl Exp $
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS hive maker
+ * FILE: tools/mkhive/mkhive.c
+ * PURPOSE: Hive maker
+ * PROGRAMMER: Eric Kohl
+ */
+
+#include <limits.h>
+#include <string.h>
+
+#include "mkhive.h"
+#include "registry.h"
+#include "reginf.h"
+#include "binhive.h"
+
+#ifndef WIN32
+#ifndef PATH_MAX
+#define PATH_MAX 260
+#endif
+#define DIR_SEPARATOR_CHAR '/'
+#define DIR_SEPARATOR_STRING "/"
+#else
+#define DIR_SEPARATOR_CHAR '\\'
+#define DIR_SEPARATOR_STRING "\\"
+#endif
+
+
+void usage (void)
+{
+ printf ("Usage: mkhive <srcdir> <dstdir>\n\n");
+}
+
+
+int main (int argc, char *argv[])
+{
+ char FileName[PATH_MAX];
+
+ if (argc < 3)
+ {
+ usage ();
+ }
+
+ RegInitializeRegistry ();
+
+ strcpy (FileName, argv[1]);
+ strcat (FileName, DIR_SEPARATOR_STRING);
+ strcat (FileName, "hivesys.inf");
+ ImportRegistryFile (FileName, "AddReg", FALSE);
+
+#if 0
+ strcpy (FileName, argv[1]);
+ strcat (FileName, DIR_SEPARATOR_STRING);
+ strcat (FileName, "hivecls.inf");
+ ImportRegistryFile (FileName, "AddReg", FALSE);
+
+ strcpy (FileName, argv[1]);
+ strcat (FileName, DIR_SEPARATOR_STRING);
+ strcat (FileName, "hivesft.inf");
+ ImportRegistryFile (FileName, "AddReg", FALSE);
+
+ strcpy (FileName, argv[1]);
+ strcat (FileName, DIR_SEPARATOR_STRING);
+ strcat (FileName, "hivedef.inf");
+ ImportRegistryFile (FileName, "AddReg", FALSE);
+#endif
+
+ strcpy (FileName, argv[2]);
+ strcat (FileName, DIR_SEPARATOR_STRING);
+ strcat (FileName, "system");
+ ExportBinaryHive (FileName, "\\Registy\\Machine\\System");
+
+
+// RegShutdownRegistry ();
+
+ return 0;
+}
+
+/* EOF */
--- /dev/null
+/*
+ * ReactOS kernel
+ * Copyright (C) 2003 ReactOS Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* $Id: mkhive.h,v 1.1 2003/04/14 17:18:48 ekohl Exp $
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS hive maker
+ * FILE: tools/mkhive/mkhive.h
+ * PURPOSE: Hive maker
+ * PROGRAMMER: Eric Kohl
+ */
+
+#ifndef __MKHIVE_H__
+#define __MKHIVE_H__
+
+
+#define VOID void
+typedef void *PVOID;
+typedef char CHAR, *PCHAR;
+typedef unsigned char UCHAR, *PUCHAR;
+typedef short SHORT, *PSHORT;
+typedef unsigned short USHORT, *PUSHORT;
+typedef long LONG, *PLONG;
+typedef unsigned long ULONG, *PULONG;
+
+typedef int BOOL, *PBOOL;
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef NULL
+#define NULL ((void*)0)
+#endif
+
+
+#ifndef max
+#define max(a, b) (((a) > (b)) ? (a) : (b))
+#endif
+
+#ifndef min
+#define min(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+
+
+/* Debugging macros */
+
+#define DPRINT1(args...) do { printf("(%s:%d) ",__FILE__,__LINE__); printf(args); } while(0);
+#define CHECKPOINT1 do { printf("%s:%d\n",__FILE__,__LINE__); } while(0);
+
+#define DPRINT(args...)
+#define CHECKPOINT
+
+
+#endif /* __MKHIVE_H__ */
+
+/* EOF */
--- /dev/null
+/*
+ * ReactOS kernel
+ * Copyright (C) 2003 ReactOS Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* $Id: reginf.c,v 1.1 2003/04/14 17:18:48 ekohl Exp $
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS hive maker
+ * FILE: tools/mkhive/reginf.h
+ * PURPOSE: Inf file import code
+ * PROGRAMMER: Eric Kohl
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "mkhive.h"
+#include "registry.h"
+#include "infcache.h"
+
+
+
+#define FLG_ADDREG_BINVALUETYPE 0x00000001
+#define FLG_ADDREG_NOCLOBBER 0x00000002
+#define FLG_ADDREG_DELVAL 0x00000004
+#define FLG_ADDREG_APPEND 0x00000008
+#define FLG_ADDREG_KEYONLY 0x00000010
+#define FLG_ADDREG_OVERWRITEONLY 0x00000020
+#define FLG_ADDREG_TYPE_SZ 0x00000000
+#define FLG_ADDREG_TYPE_MULTI_SZ 0x00010000
+#define FLG_ADDREG_TYPE_EXPAND_SZ 0x00020000
+#define FLG_ADDREG_TYPE_BINARY (0x00000000 | FLG_ADDREG_BINVALUETYPE)
+#define FLG_ADDREG_TYPE_DWORD (0x00010000 | FLG_ADDREG_BINVALUETYPE)
+#define FLG_ADDREG_TYPE_NONE (0x00020000 | FLG_ADDREG_BINVALUETYPE)
+#define FLG_ADDREG_TYPE_MASK (0xFFFF0000 | FLG_ADDREG_BINVALUETYPE)
+
+
+/* FUNCTIONS ****************************************************************/
+
+static BOOL
+GetRootKey (PCHAR Name)
+{
+ if (!stricmp (Name, "HKCR"))
+ {
+ strcpy (Name, "\\Registry\\Machine\\SOFTWARE\\Classes\\");
+ return TRUE;
+ }
+
+ if (!stricmp (Name, "HKCU"))
+ {
+ strcpy (Name, "\\Registry\\User\\.DEFAULT\\");
+ return TRUE;
+ }
+
+ if (!stricmp (Name, "HKLM"))
+ {
+ strcpy (Name, "\\Registry\\Machine\\");
+ return TRUE;
+ }
+
+ if (!stricmp (Name, "HKU"))
+ {
+ strcpy (Name, "\\Registry\\User\\");
+ return TRUE;
+ }
+
+#if 0
+ if (!stricmp (Name, "HKR"))
+ return FALSE;
+#endif
+
+ return FALSE;
+}
+
+
+/***********************************************************************
+ * append_multi_sz_value
+ *
+ * Append a multisz string to a multisz registry value.
+ */
+#if 0
+static void
+append_multi_sz_value (HANDLE hkey,
+ const WCHAR *value,
+ const WCHAR *strings,
+ DWORD str_size )
+{
+ DWORD size, type, total;
+ WCHAR *buffer, *p;
+
+ if (RegQueryValueExW( hkey, value, NULL, &type, NULL, &size )) return;
+ if (type != REG_MULTI_SZ) return;
+
+ if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (size + str_size) * sizeof(WCHAR) ))) return;
+ if (RegQueryValueExW( hkey, value, NULL, NULL, (BYTE *)buffer, &size )) goto done;
+
+ /* compare each string against all the existing ones */
+ total = size;
+ while (*strings)
+ {
+ int len = strlenW(strings) + 1;
+
+ for (p = buffer; *p; p += strlenW(p) + 1)
+ if (!strcmpiW( p, strings )) break;
+
+ if (!*p) /* not found, need to append it */
+ {
+ memcpy( p, strings, len * sizeof(WCHAR) );
+ p[len] = 0;
+ total += len;
+ }
+ strings += len;
+ }
+ if (total != size)
+ {
+ TRACE( "setting value %s to %s\n", debugstr_w(value), debugstr_w(buffer) );
+ RegSetValueExW( hkey, value, 0, REG_MULTI_SZ, (BYTE *)buffer, total );
+ }
+ done:
+ HeapFree( GetProcessHeap(), 0, buffer );
+}
+#endif
+
+/***********************************************************************
+ * delete_multi_sz_value
+ *
+ * Remove a string from a multisz registry value.
+ */
+#if 0
+static void delete_multi_sz_value( HKEY hkey, const WCHAR *value, const WCHAR *string )
+{
+ DWORD size, type;
+ WCHAR *buffer, *src, *dst;
+
+ if (RegQueryValueExW( hkey, value, NULL, &type, NULL, &size )) return;
+ if (type != REG_MULTI_SZ) return;
+ /* allocate double the size, one for value before and one for after */
+ if (!(buffer = HeapAlloc( GetProcessHeap(), 0, size * 2 * sizeof(WCHAR) ))) return;
+ if (RegQueryValueExW( hkey, value, NULL, NULL, (BYTE *)buffer, &size )) goto done;
+ src = buffer;
+ dst = buffer + size;
+ while (*src)
+ {
+ int len = strlenW(src) + 1;
+ if (strcmpiW( src, string ))
+ {
+ memcpy( dst, src, len * sizeof(WCHAR) );
+ dst += len;
+ }
+ src += len;
+ }
+ *dst++ = 0;
+ if (dst != buffer + 2*size) /* did we remove something? */
+ {
+ TRACE( "setting value %s to %s\n", debugstr_w(value), debugstr_w(buffer + size) );
+ RegSetValueExW( hkey, value, 0, REG_MULTI_SZ,
+ (BYTE *)(buffer + size), dst - (buffer + size) );
+ }
+ done:
+ HeapFree( GetProcessHeap(), 0, buffer );
+}
+#endif
+
+/***********************************************************************
+ * do_reg_operation
+ *
+ * Perform an add/delete registry operation depending on the flags.
+ */
+static BOOL
+do_reg_operation(HKEY KeyHandle,
+ PCHAR ValueName,
+ PINFCONTEXT Context,
+ ULONG Flags)
+{
+ CHAR EmptyStr = (CHAR)0;
+ ULONG Type;
+ ULONG Size;
+// NTSTATUS Status;
+
+ if (Flags & FLG_ADDREG_DELVAL) /* deletion */
+ {
+#if 0
+ if (ValueName)
+ {
+ RegDeleteValueW( hkey, value );
+ }
+ else
+ {
+ RegDeleteKeyW( hkey, NULL );
+ }
+#endif
+ return TRUE;
+ }
+
+ if (Flags & FLG_ADDREG_KEYONLY)
+ return TRUE;
+
+#if 0
+ if (Flags & (FLG_ADDREG_NOCLOBBER | FLG_ADDREG_OVERWRITEONLY))
+ {
+ BOOL exists = !RegQueryValueExW( hkey, value, NULL, NULL, NULL, NULL );
+ if (exists && (flags & FLG_ADDREG_NOCLOBBER))
+ return TRUE;
+ if (!exists & (flags & FLG_ADDREG_OVERWRITEONLY))
+ return TRUE;
+ }
+#endif
+
+ switch (Flags & FLG_ADDREG_TYPE_MASK)
+ {
+ case FLG_ADDREG_TYPE_SZ:
+ Type = REG_SZ;
+ break;
+
+ case FLG_ADDREG_TYPE_MULTI_SZ:
+ Type = REG_MULTI_SZ;
+ break;
+
+ case FLG_ADDREG_TYPE_EXPAND_SZ:
+ Type = REG_EXPAND_SZ;
+ break;
+
+ case FLG_ADDREG_TYPE_BINARY:
+ Type = REG_BINARY;
+ break;
+
+ case FLG_ADDREG_TYPE_DWORD:
+ Type = REG_DWORD;
+ break;
+
+ case FLG_ADDREG_TYPE_NONE:
+ Type = REG_NONE;
+ break;
+
+ default:
+ Type = Flags >> 16;
+ break;
+ }
+
+ if (!(Flags & FLG_ADDREG_BINVALUETYPE) ||
+ (Type == REG_DWORD && InfGetFieldCount (Context) == 5))
+ {
+ PCHAR Str = NULL;
+
+ if (Type == REG_MULTI_SZ)
+ {
+ if (!InfGetMultiSzField (Context, 5, NULL, 0, &Size))
+ Size = 0;
+
+ if (Size)
+ {
+ Str = malloc (Size);
+ if (Str == NULL)
+ return FALSE;
+
+ InfGetMultiSzField (Context, 5, Str, Size, NULL);
+ }
+
+ if (Flags & FLG_ADDREG_APPEND)
+ {
+ if (Str == NULL)
+ return TRUE;
+
+// append_multi_sz_value( hkey, value, str, size );
+
+ free (Str);
+ return TRUE;
+ }
+ /* else fall through to normal string handling */
+ }
+ else
+ {
+ if (!InfGetStringField (Context, 5, NULL, 0, &Size))
+ Size = 0;
+
+ if (Size)
+ {
+ Str = malloc (Size);
+ if (Str == NULL)
+ return FALSE;
+
+ InfGetStringField (Context, 5, Str, Size, NULL);
+ }
+ }
+
+ if (Type == REG_DWORD)
+ {
+ ULONG dw = Str ? strtol (Str, NULL, 0) : 0;
+
+ DPRINT("setting dword %s to %lx\n", ValueName, dw);
+
+ RegSetValue (KeyHandle,
+ ValueName,
+ Type,
+ (PVOID)&dw,
+ sizeof(ULONG));
+ }
+ else
+ {
+ DPRINT ("setting value %wZ to %S\n", ValueName, Str);
+
+ if (Str)
+ {
+ RegSetValue (KeyHandle,
+ ValueName,
+ Type,
+ (PVOID)Str,
+ Size);
+ }
+ else
+ {
+ RegSetValue (KeyHandle,
+ ValueName,
+ Type,
+ (PVOID)&EmptyStr,
+ sizeof(CHAR));
+ }
+ }
+ free (Str);
+ }
+ else /* get the binary data */
+ {
+ PUCHAR Data = NULL;
+
+ if (!InfGetBinaryField (Context, 5, NULL, 0, &Size))
+ Size = 0;
+
+ if (Size)
+ {
+ Data = malloc (Size);
+ if (Data == NULL)
+ return FALSE;
+
+ DPRINT("setting binary data %s len %lu\n", ValueName, Size);
+ InfGetBinaryField (Context, 5, Data, Size, NULL);
+ }
+
+ RegSetValue (KeyHandle,
+ ValueName,
+ Type,
+ (PVOID)Data,
+ Size);
+
+ free (Data);
+ }
+
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * registry_callback
+ *
+ * Called once for each AddReg and DelReg entry in a given section.
+ */
+static BOOL
+registry_callback (HINF hInf, PCHAR Section, BOOL Delete)
+{
+ CHAR Buffer[MAX_INF_STRING_LENGTH];
+ PCHAR ValuePtr;
+ ULONG Flags;
+ ULONG Length;
+
+ INFCONTEXT Context;
+ HKEY KeyHandle;
+ BOOL Ok;
+
+
+ Ok = InfFindFirstLine (hInf, Section, NULL, &Context);
+
+ for (;Ok; Ok = InfFindNextLine (&Context, &Context))
+ {
+ /* get root */
+ if (!InfGetStringField (&Context, 1, Buffer, MAX_INF_STRING_LENGTH, NULL))
+ continue;
+ if (!GetRootKey (Buffer))
+ continue;
+
+ /* get key */
+ Length = strlen (Buffer);
+ if (!InfGetStringField (&Context, 2, Buffer + Length, MAX_INF_STRING_LENGTH - Length, NULL))
+ *Buffer = 0;
+
+ DPRINT("KeyName: <%s>\n", Buffer);
+
+ /* get flags */
+ if (!InfGetIntField (&Context, 4, (PLONG)&Flags))
+ Flags = 0;
+
+ DPRINT("Flags: %lx\n", Flags);
+
+ if (Delete || (Flags & FLG_ADDREG_OVERWRITEONLY))
+ {
+ if (RegOpenKey (NULL, Buffer, &KeyHandle) != ERROR_SUCCESS)
+ {
+ DPRINT("RegOpenKey(%s) failed\n", Buffer);
+ continue; /* ignore if it doesn't exist */
+ }
+ }
+ else
+ {
+ if (RegCreateKey (NULL, Buffer, &KeyHandle) != ERROR_SUCCESS)
+ {
+ DPRINT("RegCreateKey(%s) failed\n", Buffer);
+ continue;
+ }
+ }
+
+ /* get value name */
+ if (InfGetStringField (&Context, 3, Buffer, MAX_INF_STRING_LENGTH, NULL))
+ {
+ ValuePtr = Buffer;
+ }
+ else
+ {
+ ValuePtr = NULL;
+ }
+
+ /* and now do it */
+ if (!do_reg_operation (KeyHandle, ValuePtr, &Context, Flags))
+ {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+
+BOOL
+ImportRegistryFile(PCHAR FileName,
+ PCHAR Section,
+ BOOL Delete)
+{
+ HINF hInf;
+ ULONG ErrorLine;
+
+ /* Load inf file from install media. */
+ if (!InfOpenFile(&hInf, FileName, &ErrorLine))
+ {
+ DPRINT1 ("InfOpenFile() failed\n");
+ return FALSE;
+ }
+
+ if (!registry_callback (hInf, "AddReg", FALSE))
+ {
+ DPRINT1 ("registry_callback() failed\n");
+ }
+
+ InfCloseFile (hInf);
+
+ return TRUE;
+}
+
+/* EOF */
--- /dev/null
+/*
+ * ReactOS kernel
+ * Copyright (C) 2003 ReactOS Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* $Id: reginf.h,v 1.1 2003/04/14 17:18:48 ekohl Exp $
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS hive maker
+ * FILE: tools/mkhive/reginf.h
+ * PURPOSE: Inf file import code
+ * PROGRAMMER: Eric Kohl
+ */
+
+#ifndef __REGINF_H__
+#define __REGINF_H__
+
+BOOL
+ImportRegistryFile(PCHAR Filename,
+ PCHAR Section,
+ BOOL Delete);
+
+#endif /* __REGINF_H__ */
+
+/* EOF */
--- /dev/null
+/*
+ * ReactOS kernel
+ * Copyright (C) 2003 ReactOS Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* $Id: registry.c,v 1.1 2003/04/14 17:18:48 ekohl Exp $
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS hive maker
+ * FILE: tools/mkhive/registry.c
+ * PURPOSE: Registry code
+ * PROGRAMMER: Eric Kohl
+ */
+
+/*
+ * TODO:
+ * - Implement RegDeleteKey().
+ * - Implement RegQueryMultipleValue().
+ * - Fix RegEnumValue().
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "mkhive.h"
+#include "registry.h"
+
+
+static HKEY RootKey;
+
+
+VOID
+RegInitializeRegistry(VOID)
+{
+ /* Create root key */
+ RootKey = (HKEY)malloc(sizeof(KEY));
+
+ InitializeListHead(&RootKey->SubKeyList);
+ InitializeListHead(&RootKey->ValueList);
+ InitializeListHead(&RootKey->KeyList);
+
+ RootKey->NameSize = 2;
+ RootKey->Name = (PUCHAR)malloc(2);
+ strcpy(RootKey->Name, "\\");
+
+ RootKey->DataType = 0;
+ RootKey->DataSize = 0;
+ RootKey->Data = NULL;
+
+ /* Create SYSTEM key */
+ RegCreateKey(RootKey,
+ "Registry\\Machine\\SYSTEM",
+ NULL);
+
+ /* Create HARDWARE key */
+ RegCreateKey(RootKey,
+ "Registry\\Machine\\HARDWARE",
+ NULL);
+}
+
+
+LONG
+RegCreateKey(HKEY ParentKey,
+ PCHAR KeyName,
+ PHKEY Key)
+{
+ PLIST_ENTRY Ptr;
+ HKEY SearchKey = INVALID_HANDLE_VALUE;
+ HKEY CurrentKey;
+ HKEY NewKey;
+ PCHAR p;
+ PCHAR name;
+ int subkeyLength;
+ int stringLength;
+
+ DPRINT ("KeyName '%s'\n", KeyName);
+
+ if (*KeyName == '\\')
+ {
+ KeyName++;
+ CurrentKey = RootKey;
+ }
+ else if (ParentKey == NULL)
+ {
+ CurrentKey = RootKey;
+ }
+ else
+ {
+ CurrentKey = ParentKey;
+ }
+
+ /* Check whether current key is a link */
+ if (CurrentKey->DataType == REG_LINK)
+ {
+ CurrentKey = (HKEY)CurrentKey->Data;
+ }
+
+ while (*KeyName != 0)
+ {
+ DPRINT ("KeyName '%s'\n", KeyName);
+
+ if (*KeyName == '\\')
+ KeyName++;
+ p = strchr (KeyName, '\\');
+ if ((p != NULL) && (p != KeyName))
+ {
+ subkeyLength = p - KeyName;
+ stringLength = subkeyLength + 1;
+ name = KeyName;
+ }
+ else
+ {
+ subkeyLength = strlen (KeyName);
+ stringLength = subkeyLength;
+ name = KeyName;
+ }
+
+ Ptr = CurrentKey->SubKeyList.Flink;
+ while (Ptr != &CurrentKey->SubKeyList)
+ {
+ DPRINT ("Ptr 0x%x\n", Ptr);
+
+ SearchKey = CONTAINING_RECORD(Ptr,
+ KEY,
+ KeyList);
+ DPRINT ("SearchKey 0x%x\n", SearchKey);
+ DPRINT ("Searching '%s'\n", SearchKey->Name);
+ if (strncmp (SearchKey->Name, name, subkeyLength) == 0)
+ break;
+
+ Ptr = Ptr->Flink;
+ }
+
+ if (Ptr == &CurrentKey->SubKeyList)
+ {
+ /* no key found -> create new subkey */
+ NewKey = (HKEY)malloc (sizeof(KEY));
+ if (NewKey == NULL)
+ return ERROR_OUTOFMEMORY;
+
+ InitializeListHead (&NewKey->SubKeyList);
+ InitializeListHead (&NewKey->ValueList);
+
+ NewKey->DataType = 0;
+ NewKey->DataSize = 0;
+ NewKey->Data = NULL;
+
+ InsertTailList (&CurrentKey->SubKeyList, &NewKey->KeyList);
+ NewKey->NameSize = subkeyLength + 1;
+ NewKey->Name = (PCHAR)malloc (NewKey->NameSize);
+ if (NewKey->Name == NULL)
+ return(ERROR_OUTOFMEMORY);
+ memcpy(NewKey->Name, name, subkeyLength);
+ NewKey->Name[subkeyLength] = 0;
+
+ DPRINT ("NewKey 0x%x\n", NewKey);
+ DPRINT ("NewKey '%s' Length %d\n", NewKey->Name, NewKey->NameSize);
+
+ CurrentKey = NewKey;
+ }
+ else
+ {
+ CurrentKey = SearchKey;
+
+ /* Check whether current key is a link */
+ if (CurrentKey->DataType == REG_LINK)
+ {
+ CurrentKey = (HKEY)CurrentKey->Data;
+ }
+ }
+
+ KeyName = KeyName + stringLength;
+ }
+
+ if (Key != NULL)
+ *Key = CurrentKey;
+
+ return ERROR_SUCCESS;
+}
+
+
+LONG
+RegDeleteKey(HKEY Key,
+ PCHAR Name)
+{
+
+
+ if (strchr(Name, '\\') != NULL)
+ return(ERROR_INVALID_PARAMETER);
+
+
+
+ return(ERROR_SUCCESS);
+}
+
+
+LONG
+RegEnumKey(HKEY Key,
+ ULONG Index,
+ PCHAR Name,
+ PULONG NameSize)
+{
+ PLIST_ENTRY Ptr;
+ HKEY SearchKey;
+ ULONG Count = 0;
+ ULONG Size;
+
+ Ptr = Key->SubKeyList.Flink;
+ while (Ptr != &Key->SubKeyList)
+ {
+ if (Index == Count)
+ break;
+
+ Count++;
+ Ptr = Ptr->Flink;
+ }
+
+ if (Ptr == &Key->SubKeyList)
+ return(ERROR_NO_MORE_ITEMS);
+
+ SearchKey = CONTAINING_RECORD(Ptr,
+ KEY,
+ KeyList);
+
+ DPRINT ("Name '%s' Length %d\n", SearchKey->Name, SearchKey->NameSize);
+
+ Size = min(SearchKey->NameSize, *NameSize);
+ *NameSize = Size;
+ memcpy(Name, SearchKey->Name, Size);
+
+ return(ERROR_SUCCESS);
+}
+
+
+LONG
+RegOpenKey(HKEY ParentKey,
+ PCHAR KeyName,
+ PHKEY Key)
+{
+ PLIST_ENTRY Ptr;
+ HKEY SearchKey = INVALID_HANDLE_VALUE;
+ HKEY CurrentKey;
+ PCHAR p;
+ PCHAR name;
+ int subkeyLength;
+ int stringLength;
+
+ DPRINT("KeyName '%s'\n", KeyName);
+
+ *Key = NULL;
+
+ if (*KeyName == '\\')
+ {
+ KeyName++;
+ CurrentKey = RootKey;
+ }
+ else if (ParentKey == NULL)
+ {
+ CurrentKey = RootKey;
+ }
+ else
+ {
+ CurrentKey = ParentKey;
+ }
+
+ /* Check whether current key is a link */
+ if (CurrentKey->DataType == REG_LINK)
+ {
+ CurrentKey = (HKEY)CurrentKey->Data;
+ }
+
+ while (*KeyName != 0)
+ {
+ DPRINT ("KeyName '%s'\n", KeyName);
+
+ if (*KeyName == '\\')
+ KeyName++;
+ p = strchr(KeyName, '\\');
+ if ((p != NULL) && (p != KeyName))
+ {
+ subkeyLength = p - KeyName;
+ stringLength = subkeyLength + 1;
+ name = KeyName;
+ }
+ else
+ {
+ subkeyLength = strlen(KeyName);
+ stringLength = subkeyLength;
+ name = KeyName;
+ }
+
+ Ptr = CurrentKey->SubKeyList.Flink;
+ while (Ptr != &CurrentKey->SubKeyList)
+ {
+ DPRINT ("Ptr 0x%x\n", Ptr);
+
+ SearchKey = CONTAINING_RECORD(Ptr,
+ KEY,
+ KeyList);
+
+ DPRINT ("SearchKey 0x%x\n", SearchKey);
+ DPRINT ("Searching '%s'\n", SearchKey->Name);
+
+ if (strncmp(SearchKey->Name, name, subkeyLength) == 0)
+ break;
+
+ Ptr = Ptr->Flink;
+ }
+
+ if (Ptr == &CurrentKey->SubKeyList)
+ {
+ return(ERROR_PATH_NOT_FOUND);
+ }
+ else
+ {
+ CurrentKey = SearchKey;
+
+ /* Check whether current key is a link */
+ if (CurrentKey->DataType == REG_LINK)
+ {
+ CurrentKey = (HKEY)CurrentKey->Data;
+ }
+ }
+
+ KeyName = KeyName + stringLength;
+ }
+
+ if (Key != NULL)
+ *Key = CurrentKey;
+
+ return(ERROR_SUCCESS);
+}
+
+
+LONG
+RegSetValue(HKEY Key,
+ PCHAR ValueName,
+ ULONG Type,
+ PUCHAR Data,
+ ULONG DataSize)
+{
+ PLIST_ENTRY Ptr;
+ PVALUE Value = NULL;
+
+ DPRINT ("Key 0x%x, ValueName '%s', Type %d, Data 0x%x, DataSize %d\n",
+ (int)Key, ValueName, (int)Type, (int)Data, (int)DataSize);
+
+ if ((ValueName == NULL) || (*ValueName == 0))
+ {
+ /* set default value */
+ if ((Key->Data != NULL) && (Key->DataSize > sizeof(PUCHAR)))
+ {
+ free(Key->Data);
+ }
+
+ if (DataSize <= sizeof(PUCHAR))
+ {
+ Key->DataSize = DataSize;
+ Key->DataType = Type;
+ memcpy(&Key->Data, Data, DataSize);
+ }
+ else
+ {
+ Key->Data = (PUCHAR)malloc(DataSize);
+ Key->DataSize = DataSize;
+ Key->DataType = Type;
+ memcpy(Key->Data, Data, DataSize);
+ }
+ }
+ else
+ {
+ /* set non-default value */
+ Ptr = Key->ValueList.Flink;
+ while (Ptr != &Key->ValueList)
+ {
+ Value = CONTAINING_RECORD(Ptr,
+ VALUE,
+ ValueList);
+
+ DPRINT ("Value->Name '%s'\n", Value->Name);
+
+ if (stricmp(Value->Name, ValueName) == 0)
+ break;
+
+ Ptr = Ptr->Flink;
+ }
+
+ if (Ptr == &Key->ValueList)
+ {
+ /* add new value */
+ DPRINT("No value found - adding new value\n");
+
+ Value = (PVALUE)malloc(sizeof(VALUE));
+ if (Value == NULL)
+ return(ERROR_OUTOFMEMORY);
+ InsertTailList(&Key->ValueList, &Value->ValueList);
+ Value->NameSize = strlen(ValueName)+1;
+ Value->Name = (PCHAR)malloc(Value->NameSize);
+ if (Value->Name == NULL)
+ return(ERROR_OUTOFMEMORY);
+ strcpy(Value->Name, ValueName);
+ Value->DataType = REG_NONE;
+ Value->DataSize = 0;
+ Value->Data = NULL;
+ }
+
+ /* set new value */
+ if ((Value->Data != NULL) && (Value->DataSize > sizeof(PUCHAR)))
+ {
+ free(Value->Data);
+ }
+
+ if (DataSize <= sizeof(PUCHAR))
+ {
+ Value->DataSize = DataSize;
+ Value->DataType = Type;
+ memcpy(&Value->Data, Data, DataSize);
+ }
+ else
+ {
+ Value->Data = (PUCHAR)malloc(DataSize);
+ if (Value->Data == NULL)
+ return(ERROR_OUTOFMEMORY);
+ Value->DataType = Type;
+ Value->DataSize = DataSize;
+ memcpy(Value->Data, Data, DataSize);
+ }
+ }
+ return(ERROR_SUCCESS);
+}
+
+
+LONG
+RegQueryValue(HKEY Key,
+ PCHAR ValueName,
+ PULONG Type,
+ PUCHAR Data,
+ PULONG DataSize)
+{
+ ULONG Size;
+ PLIST_ENTRY Ptr;
+ PVALUE Value = NULL;
+
+ if ((ValueName == NULL) || (*ValueName == 0))
+ {
+ /* query default value */
+ if (Key->Data == NULL)
+ return(ERROR_INVALID_PARAMETER);
+
+ if (Type != NULL)
+ *Type = Key->DataType;
+ if ((Data != NULL) && (DataSize != NULL))
+ {
+ if (Key->DataSize <= sizeof(PUCHAR))
+ {
+ Size = min(Key->DataSize, *DataSize);
+ memcpy(Data, &Key->Data, Size);
+ *DataSize = Size;
+ }
+ else
+ {
+ Size = min(Key->DataSize, *DataSize);
+ memcpy(Data, Key->Data, Size);
+ *DataSize = Size;
+ }
+ }
+ else if ((Data == NULL) && (DataSize != NULL))
+ {
+ *DataSize = Key->DataSize;
+ }
+ }
+ else
+ {
+ /* query non-default value */
+ Ptr = Key->ValueList.Flink;
+ while (Ptr != &Key->ValueList)
+ {
+ Value = CONTAINING_RECORD(Ptr,
+ VALUE,
+ ValueList);
+
+ DPRINT("Searching for '%s'. Value name '%s'\n", ValueName, Value->Name);
+
+ if (stricmp(Value->Name, ValueName) == 0)
+ break;
+
+ Ptr = Ptr->Flink;
+ }
+
+ if (Ptr == &Key->ValueList)
+ return(ERROR_INVALID_PARAMETER);
+
+ if (Type != NULL)
+ *Type = Value->DataType;
+ if ((Data != NULL) && (DataSize != NULL))
+ {
+ if (Value->DataSize <= sizeof(PUCHAR))
+ {
+ Size = min(Value->DataSize, *DataSize);
+ memcpy(Data, &Value->Data, Size);
+ *DataSize = Size;
+ }
+ else
+ {
+ Size = min(Value->DataSize, *DataSize);
+ memcpy(Data, Value->Data, Size);
+ *DataSize = Size;
+ }
+ }
+ else if ((Data == NULL) && (DataSize != NULL))
+ {
+ *DataSize = Value->DataSize;
+ }
+ }
+
+ return(ERROR_SUCCESS);
+}
+
+
+LONG
+RegDeleteValue(HKEY Key,
+ PCHAR ValueName)
+{
+ PLIST_ENTRY Ptr;
+ PVALUE Value = NULL;
+
+ if ((ValueName == NULL) || (*ValueName == 0))
+ {
+ /* delete default value */
+ if (Key->Data != NULL)
+ free(Key->Data);
+ Key->Data = NULL;
+ Key->DataSize = 0;
+ Key->DataType = 0;
+ }
+ else
+ {
+ /* delete non-default value */
+ Ptr = Key->ValueList.Flink;
+ while (Ptr != &Key->ValueList)
+ {
+ Value = CONTAINING_RECORD(Ptr,
+ VALUE,
+ ValueList);
+ if (strcmp(Value->Name, ValueName) == 0)
+ break;
+
+ Ptr = Ptr->Flink;
+ }
+
+ if (Ptr == &Key->ValueList)
+ return(ERROR_INVALID_PARAMETER);
+
+ /* delete value */
+ if (Value->Name != NULL)
+ free(Value->Name);
+ Value->Name = NULL;
+ Value->NameSize = 0;
+
+ if (Value->DataSize > sizeof(PUCHAR))
+ {
+ if (Value->Data != NULL)
+ free(Value->Data);
+ }
+ Value->Data = NULL;
+ Value->DataSize = 0;
+ Value->DataType = 0;
+
+ RemoveEntryList(&Value->ValueList);
+ free(Value);
+ }
+ return(ERROR_SUCCESS);
+}
+
+
+LONG
+RegEnumValue(HKEY Key,
+ ULONG Index,
+ PCHAR ValueName,
+ PULONG NameSize,
+ PULONG Type,
+ PUCHAR Data,
+ PULONG DataSize)
+{
+ PLIST_ENTRY Ptr;
+ PVALUE Value;
+ ULONG Count = 0;
+
+ if (Key->Data != NULL)
+ {
+ if (Index > 0)
+ {
+ Index--;
+ }
+ else
+ {
+ /* enumerate default value */
+ if (ValueName != NULL)
+ *ValueName = 0;
+ if (Type != NULL)
+ *Type = Key->DataType;
+ if (DataSize != NULL)
+ *DataSize = Key->DataSize;
+
+ /* FIXME: return more values */
+ }
+ }
+
+ Ptr = Key->ValueList.Flink;
+ while (Ptr != &Key->ValueList)
+ {
+ if (Index == Count)
+ break;
+
+ Count++;
+ Ptr = Ptr->Flink;
+ }
+
+ if (Ptr == &Key->ValueList)
+ return(ERROR_NO_MORE_ITEMS);
+
+ Value = CONTAINING_RECORD(Ptr,
+ VALUE,
+ ValueList);
+
+ /* FIXME: return values */
+
+ return(ERROR_SUCCESS);
+}
+
+
+#if 0
+LONG
+RegQueryMultipleValue(HKEY Key,
+ ...)
+{
+ return(ERROR_SUCCESS);
+}
+#endif
+
+/* EOF */
--- /dev/null
+/*
+ * ReactOS kernel
+ * Copyright (C) 2003 ReactOS Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* $Id: registry.h,v 1.1 2003/04/14 17:18:48 ekohl Exp $
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS hive maker
+ * FILE: tools/mkhive/registry.h
+ * PURPOSE: Registry code
+ * PROGRAMMER: Eric Kohl
+ */
+
+#ifndef __REGISTRY_H__
+#define __REGISTRY_H__
+
+
+#define INVALID_HANDLE_VALUE NULL
+
+typedef struct _LIST_ENTRY
+{
+ struct _LIST_ENTRY *Flink;
+ struct _LIST_ENTRY *Blink;
+} LIST_ENTRY, *PLIST_ENTRY;
+
+
+typedef struct _REG_KEY
+{
+ LIST_ENTRY KeyList;
+ LIST_ENTRY SubKeyList;
+ LIST_ENTRY ValueList;
+
+ ULONG NameSize;
+ PUCHAR Name;
+
+ /* default data */
+ ULONG DataType;
+ ULONG DataSize;
+ PUCHAR Data;
+} KEY, *HKEY, **PHKEY;
+
+
+typedef struct _REG_VALUE
+{
+ LIST_ENTRY ValueList;
+
+ /* value name */
+ ULONG NameSize;
+ PUCHAR Name;
+
+ /* value data */
+ ULONG DataType;
+ ULONG DataSize;
+ PUCHAR Data;
+} VALUE, *PVALUE;
+
+
+#define ERROR_SUCCESS 0L
+#define ERROR_PATH_NOT_FOUND 2L
+#define ERROR_OUTOFMEMORY 14L
+#define ERROR_INVALID_PARAMETER 87L
+#define ERROR_MORE_DATA 234L
+#define ERROR_NO_MORE_ITEMS 259L
+
+
+#define assert(x)
+
+/*
+ * VOID
+ * InitializeListHead (
+ * PLIST_ENTRY ListHead
+ * );
+ *
+ * FUNCTION: Initializes a double linked list
+ * ARGUMENTS:
+ * ListHead = Caller supplied storage for the head of the list
+ */
+#define InitializeListHead(ListHead) \
+{ \
+ (ListHead)->Flink = (ListHead); \
+ (ListHead)->Blink = (ListHead); \
+}
+
+
+/*
+ * VOID
+ * InsertHeadList (
+ * PLIST_ENTRY ListHead,
+ * PLIST_ENTRY Entry
+ * );
+ *
+ * FUNCTION: Inserts an entry in a double linked list
+ * ARGUMENTS:
+ * ListHead = Head of the list
+ * Entry = Entry to insert
+ */
+#define InsertHeadList(ListHead, ListEntry) \
+{ \
+ PLIST_ENTRY OldFlink; \
+ OldFlink = (ListHead)->Flink; \
+ (ListEntry)->Flink = OldFlink; \
+ (ListEntry)->Blink = (ListHead); \
+ OldFlink->Blink = (ListEntry); \
+ (ListHead)->Flink = (ListEntry); \
+ assert((ListEntry) != NULL); \
+ assert((ListEntry)->Blink!=NULL); \
+ assert((ListEntry)->Blink->Flink == (ListEntry)); \
+ assert((ListEntry)->Flink != NULL); \
+ assert((ListEntry)->Flink->Blink == (ListEntry)); \
+}
+
+
+/*
+ * VOID
+ * InsertTailList (
+ * PLIST_ENTRY ListHead,
+ * PLIST_ENTRY Entry
+ * );
+ *
+ * FUNCTION:
+ * Inserts an entry in a double linked list
+ *
+ * ARGUMENTS:
+ * ListHead = Head of the list
+ * Entry = Entry to insert
+ */
+#define InsertTailList(ListHead, ListEntry) \
+{ \
+ PLIST_ENTRY OldBlink; \
+ OldBlink = (ListHead)->Blink; \
+ (ListEntry)->Flink = (ListHead); \
+ (ListEntry)->Blink = OldBlink; \
+ OldBlink->Flink = (ListEntry); \
+ (ListHead)->Blink = (ListEntry); \
+ assert((ListEntry) != NULL); \
+ assert((ListEntry)->Blink != NULL); \
+ assert((ListEntry)->Blink->Flink == (ListEntry)); \
+ assert((ListEntry)->Flink != NULL); \
+ assert((ListEntry)->Flink->Blink == (ListEntry)); \
+}
+
+/*
+ * BOOLEAN
+ * IsListEmpty (
+ * PLIST_ENTRY ListHead
+ * );
+ *
+ * FUNCTION:
+ * Checks if a double linked list is empty
+ *
+ * ARGUMENTS:
+ * ListHead = Head of the list
+*/
+#define IsListEmpty(ListHead) \
+ ((ListHead)->Flink == (ListHead))
+
+
+/*
+ *VOID
+ *RemoveEntryList (
+ * PLIST_ENTRY Entry
+ * );
+ *
+ * FUNCTION:
+ * Removes an entry from a double linked list
+ *
+ * ARGUMENTS:
+ * ListEntry = Entry to remove
+ */
+#define RemoveEntryList(ListEntry) \
+{ \
+ PLIST_ENTRY OldFlink; \
+ PLIST_ENTRY OldBlink; \
+ assert((ListEntry) != NULL); \
+ assert((ListEntry)->Blink!=NULL); \
+ assert((ListEntry)->Blink->Flink == (ListEntry)); \
+ assert((ListEntry)->Flink != NULL); \
+ assert((ListEntry)->Flink->Blink == (ListEntry)); \
+ OldFlink = (ListEntry)->Flink; \
+ OldBlink = (ListEntry)->Blink; \
+ OldFlink->Blink = OldBlink; \
+ OldBlink->Flink = OldFlink; \
+ (ListEntry)->Flink = NULL; \
+ (ListEntry)->Blink = NULL; \
+}
+
+/*
+ * PURPOSE: Returns the byte offset of a field within a structure
+ */
+#define FIELD_OFFSET(Type,Field) (LONG)(&(((Type *)(0))->Field))
+
+/*
+ * PURPOSE: Returns the base address structure if the caller knows the
+ * address of a field within the structure
+ * ARGUMENTS:
+ * Address = address of the field
+ * Type = Type of the whole structure
+ * Field = Name of the field whose address is none
+ */
+#define CONTAINING_RECORD(Address,Type,Field) \
+ (Type *)(((LONG)Address) - FIELD_OFFSET(Type,Field))
+
+
+#define REG_NONE 0
+#define REG_SZ 1
+#define REG_EXPAND_SZ 2
+#define REG_BINARY 3
+#define REG_DWORD 4
+#define REG_DWORD_BIG_ENDIAN 5
+#define REG_DWORD_LITTLE_ENDIAN 4
+#define REG_LINK 6
+#define REG_MULTI_SZ 7
+#define REG_RESOURCE_LIST 8
+#define REG_FULL_RESOURCE_DESCRIPTOR 9
+#define REG_RESOURCE_REQUIREMENTS_LIST 10
+
+
+
+VOID
+RegInitializeRegistry(VOID);
+
+LONG
+RegCreateKey(HKEY ParentKey,
+ PCHAR KeyName,
+ PHKEY Key);
+
+LONG
+RegDeleteKey(HKEY Key,
+ PCHAR Name);
+
+LONG
+RegEnumKey(HKEY Key,
+ ULONG Index,
+ PCHAR Name,
+ PULONG NameSize);
+
+LONG
+RegOpenKey(HKEY ParentKey,
+ PCHAR KeyName,
+ PHKEY Key);
+
+
+LONG
+RegSetValue(HKEY Key,
+ PCHAR ValueName,
+ ULONG Type,
+ PUCHAR Data,
+ ULONG DataSize);
+
+LONG
+RegQueryValue(HKEY Key,
+ PCHAR ValueName,
+ PULONG Type,
+ PUCHAR Data,
+ PULONG DataSize);
+
+LONG
+RegDeleteValue(HKEY Key,
+ PCHAR ValueName);
+
+LONG
+RegEnumValue(HKEY Key,
+ ULONG Index,
+ PCHAR ValueName,
+ PULONG NameSize,
+ PULONG Type,
+ PUCHAR Data,
+ PULONG DataSize);
+
+
+#if 0
+BOOL
+RegImportTextHive(PCHAR ChunkBase,
+ U32 ChunkSize);
+
+BOOL
+RegImportBinaryHive(PCHAR ChunkBase,
+ U32 ChunkSize);
+#endif
+
+#endif /* __REGISTRY_H__ */
+
+/* EOF */
+