Added system hive support.
authorEric Kohl <eric.kohl@reactos.org>
Mon, 26 Nov 2001 22:33:20 +0000 (22:33 +0000)
committerEric Kohl <eric.kohl@reactos.org>
Mon, 26 Nov 2001 22:33:20 +0000 (22:33 +0000)
svn path=/trunk/; revision=2395

freeldr/freeldr/reactos/hwdetect.c [new file with mode: 0644]
freeldr/freeldr/reactos/reactos.c [new file with mode: 0644]
freeldr/freeldr/reactos/reactos.h [new file with mode: 0644]
freeldr/freeldr/reactos/reghive.c [new file with mode: 0644]
freeldr/freeldr/reactos/registry.c [new file with mode: 0644]
freeldr/freeldr/reactos/registry.h [new file with mode: 0644]

diff --git a/freeldr/freeldr/reactos/hwdetect.c b/freeldr/freeldr/reactos/hwdetect.c
new file mode 100644 (file)
index 0000000..10b1c12
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ *  FreeLoader
+ *
+ *  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"
+
+
+VOID
+DetectHardware(VOID)
+{
+}
\ No newline at end of file
diff --git a/freeldr/freeldr/reactos/reactos.c b/freeldr/freeldr/reactos/reactos.c
new file mode 100644 (file)
index 0000000..05ac2bf
--- /dev/null
@@ -0,0 +1,530 @@
+/*
+ *  FreeLoader
+ *
+ *  Copyright (C) 1999, 2000, 2001  Brian Palmer  <brianp@sginet.com>
+ *
+ *  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 "../asmcode.h"
+#include "reactos.h"
+#include "../stdlib.h"
+#include "../fs.h"
+#include "../tui.h"
+#include "../multiboot.h"
+#include "../arcname.h"
+#include "../memory.h"
+#include "../parseini.h"
+
+#include "registry.h"
+
+
+#define NDEBUG
+
+
+static BOOL
+LoadKernel(PCHAR szFileName, int nPos)
+{
+  PFILE FilePointer;
+  PCHAR szShortName;
+  char szBuffer[256];
+
+  szShortName = strrchr(szFileName, '\\');
+  if (szShortName == NULL)
+    szShortName = szFileName;
+  else
+    szShortName = szShortName + 1;
+
+  FilePointer = OpenFile(szFileName);
+  if (FilePointer == NULL)
+    {
+      strcat(szBuffer, szShortName);
+      strcat(szBuffer, " not found.");
+      MessageBox(szBuffer);
+      return(FALSE);
+    }
+
+  /*
+   * Update the status bar with the current file
+   */
+  strcpy(szBuffer, " Reading ");
+  strcat(szBuffer, szShortName);
+  DrawStatusText(szBuffer);
+
+  /*
+   * Load the kernel
+   */
+  MultiBootLoadKernel(FilePointer);
+
+  DrawProgressBar(nPos);
+
+  return(TRUE);
+}
+
+
+static BOOL
+LoadDriver(PCHAR szFileName, int nPos)
+{
+  PFILE FilePointer;
+  char value[256];
+  char *p;
+
+  FilePointer = OpenFile(szFileName);
+  if (FilePointer == NULL)
+    {
+      strcat(value, szFileName);
+      strcat(value, " not found.");
+      MessageBox(value);
+      return(FALSE);
+    }
+
+  /*
+   * Update the status bar with the current file
+   */
+  strcpy(value, " Reading ");
+  p = strrchr(szFileName, '\\');
+  if (p == NULL)
+    strcat(value, szFileName);
+  else
+    strcat(value, p + 1);
+  while (strlen(value) < 80)
+    strcat(value, " ");
+  DrawStatusText(value);
+
+  /*
+   * Load the driver
+   */
+  MultiBootLoadModule(FilePointer, szFileName, NULL);
+
+  DrawProgressBar(nPos);
+
+  return(TRUE);
+}
+
+
+static VOID
+LoadBootDrivers(PCHAR szSystemRoot, int nPos)
+{
+  LONG rc = 0;
+  HKEY hGroupKey, hServiceKey, hDriverKey;
+  char ValueBuffer[256];
+  char ServiceName[256];
+  ULONG BufferSize;
+  ULONG Index;
+  char *s, *p;
+  char GroupName[256];
+  ULONG len;
+  BOOL done;
+
+  ULONG ValueSize;
+  ULONG ValueType;
+  ULONG StartValue;
+  UCHAR DriverGroup[256];
+  ULONG DriverGroupSize;
+
+  UCHAR ImagePath[256];
+
+  /* get 'service group order' key */
+  rc = RegOpenKey(NULL,
+                 "\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\ServiceGroupOrder",
+                 &hGroupKey);
+//  printf("RegOpenKey(): rc %d\n", (int)rc);
+  if (rc != ERROR_SUCCESS)
+    return;
+
+  /* enumerate drivers */
+  rc = RegOpenKey(NULL,
+                 "\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services",
+                 &hServiceKey);
+//  printf("RegOpenKey(): rc %d\n", (int)rc);
+  if (rc != ERROR_SUCCESS)
+    return;
+
+//  printf("hKey: %x\n", (int)hKey);
+
+  BufferSize = 256;
+  rc = RegQueryValue(hGroupKey, "List", NULL, (PUCHAR)ValueBuffer, &BufferSize);
+//  printf("RegQueryValue(): rc %d\n", (int)rc);
+  if (rc != ERROR_SUCCESS)
+    return;
+
+
+//  printf("BufferSize: %d \n", (int)BufferSize);
+
+//  printf("ValueBuffer: '%s' \n", ValueBuffer);
+
+  done = FALSE;
+  s = ValueBuffer;
+  do
+    {
+      p = strchr(s, ';');
+      if (p != NULL)
+       {
+         len = p - s;
+         memcpy(GroupName, s, len);
+         GroupName[len] = 0;
+         s = p + 1;
+       }
+      else
+       {
+         strcpy(GroupName, s);
+         done = TRUE;
+       }
+//      printf("Driver group: '%s'\n", GroupName);
+
+      /* enumerate all drivers */
+      Index = 0;
+      while (TRUE)
+       {
+         ValueSize = 256;
+         rc = RegEnumKey(hServiceKey, Index, ServiceName, &ValueSize);
+//       printf("RegEnumKey(): rc %d\n", (int)rc);
+         if (rc == ERROR_NO_MORE_ITEMS)
+           break;
+         if (rc != ERROR_SUCCESS)
+           return;
+//       printf("Service %d: '%s'\n", (int)Index, ServiceName);
+
+         /* open driver Key */
+         rc = RegOpenKey(hServiceKey, ServiceName, &hDriverKey);
+
+         ValueSize = sizeof(ULONG);
+         rc = RegQueryValue(hDriverKey, "Start", &ValueType, (PUCHAR)&StartValue, &ValueSize);
+//       printf("  Start: %x  \n", (int)StartValue);
+
+         DriverGroupSize = 256;
+         rc = RegQueryValue(hDriverKey, "Group", NULL, (PUCHAR)DriverGroup, &DriverGroupSize);
+//       printf("  Group: %s  \n", DriverGroup);
+
+         if ((StartValue == 0) && (stricmp(DriverGroup, GroupName) == 0))
+           {
+             ValueSize = 256;
+             rc = RegQueryValue(hDriverKey,
+                                "ImagePathName",
+                                NULL,
+                                (PUCHAR)ImagePath,
+                                &ValueSize);
+             if (rc != ERROR_SUCCESS)
+               {
+//               printf("  ImagePath: not found\n");
+                 strcpy(ImagePath, szSystemRoot);
+                 strcat(ImagePath, "system32\\drivers\\");
+                 strcat(ImagePath, ServiceName);
+                 strcat(ImagePath, ".sys");
+               }
+             else
+               {
+//               printf("  ImagePath: '%s'\n", ImagePath);
+               }
+//           printf("  Loading driver: '%s'\n", ImagePath);
+
+             LoadDriver(ImagePath, nPos);
+
+             if (nPos < 100)
+               nPos += 5;
+           }
+         Index++;
+       }
+    }
+  while(done == FALSE);
+
+}
+
+void LoadAndBootReactOS(PUCHAR OperatingSystemName)
+{
+       PFILE           FilePointer;
+       char            name[1024];
+       char            value[1024];
+       char            szFileName[1024];
+       char            szBootPath[256];
+//     int             i;
+//     int             nNumDriverFiles=0;
+//     int             nNumFilesLoaded=0;
+       char            MsgBuffer[256];
+       ULONG           SectionId;
+
+       char* Base;
+       ULONG Size;
+
+       //
+       // Open the operating system section
+       // specified in the .ini file
+       //
+       if (!OpenSection(OperatingSystemName, &SectionId))
+       {
+               sprintf(MsgBuffer,"Operating System section '%s' not found in freeldr.ini", OperatingSystemName);
+               MessageBox(MsgBuffer);
+               return;
+       }
+
+       /*
+        * 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();
+       mb_info.mem_upper = GetExtendedMemorySize();
+       mb_info.boot_device = 0xffffffff;
+       mb_info.cmdline = (unsigned long)multiboot_kernel_cmdline;
+       mb_info.mods_count = 0;
+       mb_info.mods_addr = (unsigned long)multiboot_modules;
+       mb_info.mmap_length = GetBiosMemoryMap(&multiboot_memory_map);
+       if (mb_info.mmap_length)
+       {
+               mb_info.mmap_addr = (unsigned long)&multiboot_memory_map;
+               mb_info.flags |= MB_INFO_FLAG_MEMORY_MAP;
+               //printf("memory map length: %d\n", mb_info.mmap_length);
+               //printf("dumping memory map:\n");
+               //for (i=0; i<(mb_info.mmap_length / 4); i++)
+               //{
+               //      printf("0x%x\n", ((unsigned long *)&multiboot_memory_map)[i]);
+               //}
+               //getch();
+       }
+       //printf("low_mem = %d\n", mb_info.mem_lower);
+       //printf("high_mem = %d\n", mb_info.mem_upper);
+       //getch();
+
+       /*
+        * Make sure the system path is set in the .ini file
+        */
+       if (!ReadSectionSettingByName(SectionId, "SystemPath", value, 1024))
+       {
+               MessageBox("System path not specified for selected operating system.");
+               return;
+       }
+
+       /*
+        * Verify system path
+        */
+       if (!DissectArcPath(value, szBootPath, &BootDrive, &BootPartition))
+       {
+               sprintf(MsgBuffer,"Invalid system path: '%s'", value);
+               MessageBox(MsgBuffer);
+               return;
+       }
+
+       /* set boot drive and partition */
+       ((char *)(&mb_info.boot_device))[0] = (char)BootDrive;
+       ((char *)(&mb_info.boot_device))[1] = (char)BootPartition;
+
+       /* copy ARC path into kernel command line */
+       strcpy(multiboot_kernel_cmdline, value);
+
+       /*
+        * Read the optional kernel parameters (if any)
+        */
+       if (ReadSectionSettingByName(SectionId, "Options", value, 1024))
+       {
+               strcat(multiboot_kernel_cmdline, " ");
+               strcat(multiboot_kernel_cmdline, value);
+       }
+
+       /* append a backslash */
+       if ((strlen(szBootPath)==0) ||
+           szBootPath[strlen(szBootPath)] != '\\')
+               strcat(szBootPath, "\\");
+
+#ifndef NDEBUG
+       sprintf(MsgBuffer,"SystemRoot: '%s'", szBootPath);
+       MessageBox(MsgBuffer);
+#endif
+
+       DrawBackdrop();
+
+       DrawStatusText(" Loading...");
+       DrawProgressBar(0);
+
+       /*
+        * Try to open boot drive
+        */
+       if (!OpenDiskDrive(BootDrive, BootPartition))
+       {
+               MessageBox("Failed to open boot drive.");
+               return;
+       }
+
+       /*
+        * Find the kernel image name
+        * and try to load the kernel off the disk
+        */
+       if(ReadSectionSettingByName(SectionId, "Kernel", value, 1024))
+       {
+               /*
+                * Set the name and
+                */
+               if (value[0] == '\\')
+               {
+                       strcpy(szFileName, value);
+               }
+               else
+               {
+                       strcpy(szFileName, szBootPath);
+                       strcat(szFileName, "SYSTEM32\\");
+                       strcat(szFileName, value);
+               }
+       }
+       else
+       {
+               strcpy(value, "NTOSKRNL.EXE");
+               strcpy(szFileName, szBootPath);
+               strcat(szFileName, "SYSTEM32\\");
+               strcat(szFileName, value);
+       }
+
+       if (!LoadKernel(szFileName, 5))
+               return;
+
+       /*
+        * Find the HAL image name
+        * and try to load the kernel off the disk
+        */
+       if(ReadSectionSettingByName(SectionId, "Hal", value, 1024))
+       {
+               /*
+                * Set the name and
+                */
+               if (value[0] == '\\')
+               {
+                       strcpy(szFileName, value);
+               }
+               else
+               {
+                       strcpy(szFileName, szBootPath);
+                       strcat(szFileName, "SYSTEM32\\");
+                       strcat(szFileName, value);
+               }
+       }
+       else
+       {
+               strcpy(value, "HAL.DLL");
+               strcpy(szFileName, szBootPath);
+               strcat(szFileName, "SYSTEM32\\");
+               strcat(szFileName, value);
+       }
+
+       if (!LoadDriver(szFileName, 10))
+               return;
+
+       /*
+        * Find the System hive image name
+        * and try to load it off the disk
+        */
+       if(ReadSectionSettingByName(SectionId, "SystemHive", value, 1024))
+       {
+               /*
+                * Set the name and
+                */
+               if (value[0] == '\\')
+               {
+                       strcpy(szFileName, value);
+               }
+               else
+               {
+                       strcpy(szFileName, szBootPath);
+                       strcat(szFileName, "SYSTEM32\\CONFIG\\");
+                       strcat(szFileName, value);
+               }
+       }
+       else
+       {
+               strcpy(value, "SYSTEM.HIV");
+               strcpy(szFileName, szBootPath);
+               strcat(szFileName, "SYSTEM32\\CONFIG\\");
+               strcat(szFileName, value);
+       }
+
+#ifndef NDEBUG
+       sprintf(MsgBuffer,"SystemHive: '%s'", szFileName);
+       MessageBox(MsgBuffer);
+#endif
+
+       FilePointer = OpenFile(szFileName);
+       if (FilePointer == NULL)
+       {
+               strcat(value, " not found.");
+               MessageBox(value);
+               return;
+       }
+
+       /*
+        * Update the status bar with the current file
+        */
+       strcpy(name, " Reading ");
+       strcat(name, value);
+       while (strlen(name) < 80)
+               strcat(name, " ");
+       DrawStatusText(name);
+
+       /*
+        * Load the system hive
+        */
+       Base = MultiBootLoadModule(FilePointer, szFileName, &Size);
+       RegInitializeRegistry();
+       RegImportHive(Base, Size);
+
+       DrawProgressBar(15);
+
+#ifndef NDEBUG
+       sprintf(MsgBuffer,"SystemHive loaded at 0x%x size %u", (unsigned)Base, (unsigned)Size);
+       MessageBox(MsgBuffer);
+#endif
+
+       /*
+        * retrieve hardware information and create the hardware hive
+        */
+//     DetectHardware();
+//     Base = MultiBootCreateModule(HARDWARE.HIV);
+//     RegExportHardwareHive(Base, &Size);
+//     MultiBootCloseModule(Base, Size);
+
+       DrawProgressBar(20);
+
+       /*
+        * load NLS files
+        */
+//     LoadNlsFiles(szBootPath);
+
+       DrawProgressBar(25);
+
+       /*
+        * load boot drivers
+        */
+       LoadBootDrivers(szBootPath, 30);
+
+
+       /*
+        * Clear the screen and redraw the backdrop and status bar
+        */
+       DrawBackdrop();
+       DrawStatusText(" Press any key to boot");
+
+       /*
+        * Wait for user
+        */
+       strcpy(name, "Kernel and Drivers loaded.\nPress any key to boot ");
+       strcat(name, OperatingSystemName);
+       strcat(name, ".");
+       //MessageBox(name);
+
+       RestoreScreen(ScreenBuffer);
+
+       /*
+        * Now boot the kernel
+        */
+       stop_floppy();
+       boot_reactos();
+}
+
diff --git a/freeldr/freeldr/reactos/reactos.h b/freeldr/freeldr/reactos/reactos.h
new file mode 100644 (file)
index 0000000..fb907a3
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ *  FreeLoader
+ *
+ *  Copyright (C) 1999, 2000  Brian Palmer  <brianp@sginet.com>
+ *
+ *  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.
+ */
+
+#ifndef __REACTOS_H
+#define __REACTOS_H
+
+
+void LoadAndBootReactOS(PUCHAR OperatingSystemName);
+
+
+#endif // defined __REACTOS_H
\ No newline at end of file
diff --git a/freeldr/freeldr/reactos/reghive.c b/freeldr/freeldr/reactos/reghive.c
new file mode 100644 (file)
index 0000000..d93daff
--- /dev/null
@@ -0,0 +1,510 @@
+/*
+ *  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 "../stdlib.h"
+#include "../memory.h"
+
+#include "registry.h"
+
+#define NDEBUG
+
+
+#define  REGISTRY_FILE_MAGIC    "REGEDIT4"
+
+#define INVALID_HANDLE_VALUE    NULL
+
+
+static PCHAR 
+checkAndSkipMagic (PCHAR  regChunk)
+{
+  if (strncmp (regChunk, 
+               REGISTRY_FILE_MAGIC, 
+               strlen (REGISTRY_FILE_MAGIC)) != 0)
+  {
+#ifndef NDEBUG
+    printf("incorrect magic number in registry chunk. expected: %s got:%.*s\n",
+           REGISTRY_FILE_MAGIC,
+           strlen (REGISTRY_FILE_MAGIC),
+           regChunk);
+#endif
+    return  0;
+  }
+  regChunk += strlen (REGISTRY_FILE_MAGIC);
+#ifndef NDEBUG
+  printf("Found registry chunk magic value\n");
+#endif
+
+  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)
+    FreeMemory(*newKeyName);
+
+  *newKeyName = AllocateMemory(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;
+
+#ifndef NDEBUG
+  printf("Adding new key '%s'\n", newKeyName);
+#endif
+
+  RegCreateKey(NULL,
+              newKeyName,
+              &handleToReturn);
+
+#ifndef NDEBUG
+  printf("  returned handle: 0x%x\n", handleToReturn);
+#endif
+
+  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
+  {
+//    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(DWORD);
+    while (*regChunk != 0 && isxdigit(*regChunk))
+    {
+      regChunk++;
+    }
+  }
+  else
+  {
+//    UNIMPLEMENTED;
+  }
+
+  return  dataSize;
+}
+
+static BOOL
+allocateDataBuffer (PVOID * data, int * dataBufferSize, int dataSize)
+{
+  if (*dataBufferSize < dataSize)
+  {
+    if (*dataBufferSize > 0)
+      FreeMemory(*data);
+    *data = AllocateMemory(dataSize);
+    *dataBufferSize = dataSize;
+  }
+
+  return  TRUE;
+}
+
+static PCHAR
+getKeyValueDataFromChunk (PCHAR  regChunk, PCHAR  dataFormat, PCHAR data)
+{
+  char  dataValue;
+  ULONG 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(ULONG));
+  }
+  else
+  {
+//    UNIMPLEMENTED;
+  }
+
+  return  *regChunk ? regChunk : 0;
+}
+
+static BOOL
+setKeyValue (HKEY currentKey,
+             PCHAR newValueName,
+             ULONG keyValueType,
+             PVOID data,
+             ULONG dataSize)
+{
+  LONG status;
+
+#ifndef NDEBUG
+  printf("Adding value (%s) to current key, with data type %d size %d\n",
+         newValueName,
+         (int)keyValueType,
+         (int)dataSize);
+#endif
+  status = RegSetValue(currentKey,
+                      newValueName,
+                      keyValueType,
+                      data,
+                      dataSize);
+  if (status != ERROR_SUCCESS)
+  {
+#ifndef NDEBUG
+    printf("could not set key value, rc:%d\n", status);
+#endif
+    return  FALSE;
+  }
+
+  return  TRUE;
+}
+
+
+VOID
+RegImportHive(PCHAR ChunkBase,
+             ULONG ChunkSize)
+{
+  HKEY currentKey = NULL;
+  int  newKeySize = 0;
+  char *newKeyName = NULL;
+  char  dataFormat [10];
+  int  keyValueType;
+  int  dataSize = 0;
+  int  dataBufferSize = 0;
+  PVOID  data = 0;
+  PCHAR regChunk;
+
+#ifndef NDEBUG
+  printf("ChunkBase 0x%x  ChunkSize %x\n", ChunkBase, ChunkSize);
+#endif
+
+  regChunk = checkAndSkipMagic (ChunkBase);
+  if (regChunk == 0)
+    return;
+
+  while (regChunk != 0 && *regChunk != 0 && (((ULONG)regChunk-(ULONG)ChunkBase) < ChunkSize))
+  {
+    regChunk = skipWhitespaceInChunk (regChunk);
+    if (regChunk == 0)
+      continue;
+
+    if (*regChunk == '[')
+    {
+#ifndef NDEBUG
+    printf("Line: %s\n", regChunk);
+#endif
+      if (currentKey != NULL)
+      {
+#ifndef NDEBUG
+        printf("Closing current key: 0x%lx\n", currentKey);
+#endif
+        currentKey = NULL;
+      }
+
+      regChunk++;
+
+      newKeySize = computeKeyNameSize (regChunk);
+      if (!allocateKeyName (&newKeyName, newKeySize))
+      {
+        regChunk = 0;
+        continue;
+      }
+
+      regChunk = getKeyNameFromChunk (regChunk, newKeyName);
+      if (regChunk == 0)
+        continue;
+
+      currentKey = createNewKey (newKeyName);
+      if (currentKey == NULL)
+      {
+        regChunk = skipToNextKeyInChunk (regChunk);
+        continue;
+      }
+
+      regChunk++;
+    }
+    else
+    {
+      if (currentKey == NULL)
+      {
+        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 (newKeyName != NULL)
+  {
+    FreeMemory(newKeyName);
+  }
+  if (data != NULL)
+  {
+    FreeMemory(data);
+  }
+
+  return;
+}
+
+/* EOF */
diff --git a/freeldr/freeldr/reactos/registry.c b/freeldr/freeldr/reactos/registry.c
new file mode 100644 (file)
index 0000000..f027b95
--- /dev/null
@@ -0,0 +1,596 @@
+/*
+ *  FreeLoader
+ *
+ *  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.
+ */
+
+/*
+ * TODO:
+ *     - Implement RegDeleteKey().
+ *     - Implement RegQueryMultipleValue().
+ *     - Fix RegEnumValue().
+ */
+
+#include "../freeldr.h"
+#include "../memory.h"
+#include "../stdlib.h"
+#include "registry.h"
+
+#define NDEBUG
+
+
+static HKEY RootKey;
+
+
+VOID
+RegInitializeRegistry(VOID)
+{
+  RootKey = (HKEY)AllocateMemory(sizeof(KEY));
+
+  InitializeListHead(&RootKey->SubKeyList);
+  InitializeListHead(&RootKey->ValueList);
+  InitializeListHead(&RootKey->KeyList);
+
+  RootKey->NameSize = 2;
+  RootKey->Name = (PUCHAR)AllocateMemory(2);
+  strcpy(RootKey->Name, "\\");
+
+  RootKey->Type = 0;
+  RootKey->DataSize = 0;
+  RootKey->Data = NULL;
+}
+
+
+LONG
+RegCreateKey(HKEY ParentKey,
+            PCHAR KeyName,
+            PHKEY Key)
+{
+  PLIST_ENTRY Ptr;
+  HKEY SearchKey;
+  HKEY CurrentKey;
+  HKEY NewKey;
+  PCHAR p;
+  PCHAR name;
+  int subkeyLength;
+  int stringLength;
+
+#ifndef NDEBUG
+  printf("RegCreateKey(%s) called\n", KeyName);
+#endif
+
+  if (*KeyName == '\\')
+    {
+      KeyName++;
+      CurrentKey = RootKey;
+    }
+  else if (ParentKey == NULL)
+    {
+      CurrentKey = RootKey;
+    }
+  else
+    {
+      CurrentKey = ParentKey;
+    }
+
+
+  while (*KeyName != 0)
+    {
+#ifndef NDEBUG
+      printf("RegCreateKey(): KeyName '%s'\n", KeyName);
+#endif
+      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)
+       {
+#ifndef NDEBUG
+         printf("RegCreateKey(): Ptr 0x%x\n", Ptr);
+#endif
+         SearchKey = CONTAINING_RECORD(Ptr,
+                                       KEY,
+                                       KeyList);
+#ifndef NDEBUG
+         printf("RegCreateKey(): SearchKey 0x%x\n", SearchKey);
+         printf("RegCreateKey(): searching '%s'\n", SearchKey->Name);
+#endif
+         if (strncmp(SearchKey->Name, name, subkeyLength) == 0)
+           break;
+
+         Ptr = Ptr->Flink;
+       }
+
+      if (Ptr == &CurrentKey->SubKeyList)
+       {
+         /* no key found -> create new subkey */
+         NewKey = (HKEY)AllocateMemory(sizeof(KEY));
+         if (NewKey == NULL)
+          return(ERROR_OUTOFMEMORY);
+
+         InitializeListHead(&NewKey->SubKeyList);
+         InitializeListHead(&NewKey->ValueList);
+
+         NewKey->Type = 0;
+         NewKey->DataSize = 0;
+         NewKey->Data = NULL;
+
+         InsertTailList(&CurrentKey->SubKeyList, &NewKey->KeyList);
+         NewKey->NameSize = subkeyLength + 1;
+         NewKey->Name = (PCHAR)AllocateMemory(NewKey->NameSize);
+         if (NewKey->Name == NULL)
+          return(ERROR_OUTOFMEMORY);
+         memcpy(NewKey->Name, name, subkeyLength);
+         NewKey->Name[subkeyLength] = 0;
+
+#ifndef NDEBUG
+         printf("RegCreateKey(): new key 0x%x\n", NewKey);
+         printf("RegCreateKey(): new key '%s' length %d\n", NewKey->Name, NewKey->NameSize);
+#endif
+
+         CurrentKey = NewKey;
+       }
+      else
+       {
+         CurrentKey = SearchKey;
+       }
+
+      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);
+
+#ifndef NDEBUG
+  printf("RegEnumKey(): name '%s' length %d\n", SearchKey->Name, SearchKey->NameSize);
+#endif
+
+  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;
+  HKEY CurrentKey;
+  PCHAR p;
+  PCHAR name;
+  int subkeyLength;
+  int stringLength;
+
+#ifndef NDEBUG
+  printf("RegOpenKey(%s) called\n", KeyName);
+#endif
+
+  *Key = NULL;
+
+  if (*KeyName == '\\')
+    {
+      KeyName++;
+      CurrentKey = RootKey;
+    }
+  else if (ParentKey == NULL)
+    {
+      CurrentKey = RootKey;
+    }
+  else
+    {
+      CurrentKey = ParentKey;
+    }
+
+
+  while (*KeyName != 0)
+    {
+#ifndef NDEBUG
+      printf("RegOpenKey(): KeyName '%s'\n", KeyName);
+#endif
+      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)
+       {
+#ifndef NDEBUG
+         printf("RegCreateKey(): Ptr 0x%x\n", Ptr);
+#endif
+         SearchKey = CONTAINING_RECORD(Ptr,
+                                       KEY,
+                                       KeyList);
+#ifndef NDEBUG
+         printf("RegOpenKey(): SearchKey 0x%x\n", SearchKey);
+         printf("RegOpenKey(): searching '%s'\n", SearchKey->Name);
+#endif
+         if (strncmp(SearchKey->Name, name, subkeyLength) == 0)
+           break;
+
+         Ptr = Ptr->Flink;
+       }
+
+      if (Ptr == &CurrentKey->SubKeyList)
+       {
+         return(ERROR_PATH_NOT_FOUND);
+       }
+      else
+       {
+         CurrentKey = SearchKey;
+       }
+
+      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;
+
+#ifndef NDEBUG
+  printf("RegSetValue(%x, '%s', %d, %x, %d)\n", (int)Key, ValueName, (int)Type, (int)Data, (int)DataSize);
+#endif
+  if ((ValueName == NULL) || (*ValueName == 0))
+    {
+      /* set default value */
+      if (Key->Data != NULL)
+        FreeMemory(Key->Data);
+      Key->Data = (PUCHAR)AllocateMemory(DataSize);
+      Key->DataSize = DataSize;
+      Key->Type = 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);
+#ifndef NDEBUG
+         printf("Value->Name: '%s'\n", Value->Name);
+#endif
+         if (stricmp(Value->Name, ValueName) == 0)
+           break;
+
+         Ptr = Ptr->Flink;
+       }
+
+      if (Ptr == &Key->ValueList)
+       {
+         /* add new value */
+#ifndef NDEBUG
+         printf("No value found - adding new value\n");
+#endif
+         Value = (PVALUE)AllocateMemory(sizeof(VALUE));
+         if (Value == NULL)
+           return(ERROR_OUTOFMEMORY);
+         InsertTailList(&Key->ValueList, &Value->ValueList);
+         Value->NameSize = strlen(ValueName)+1;
+         Value->Name = (PCHAR)AllocateMemory(Value->NameSize);
+         if (Value->Name == NULL)
+           return(ERROR_OUTOFMEMORY);
+         strcpy(Value->Name, ValueName);
+         Value->Data = NULL;
+       }
+
+      /* set new value */
+      if (DataSize <= sizeof(PUCHAR))
+       {
+         Value->DataSize = DataSize;
+         Value->Type = Type;
+         memcpy(&Value->Data, Data, DataSize);
+       }
+      else
+       {
+         if(Value->Data != NULL)
+           FreeMemory(Value->Data);
+         Value->Data = (PUCHAR)AllocateMemory(DataSize);
+         if (Value->Data == NULL)
+           return(ERROR_OUTOFMEMORY);
+         Value->DataSize = DataSize;
+         Value->Type = Type;
+         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;
+
+  if ((ValueName == NULL) || (*ValueName == 0))
+    {
+      /* query default value */
+      if (Key->Data == NULL)
+       return(ERROR_INVALID_PARAMETER);
+
+      if (Type != NULL)
+       *Type = Key->Type;
+      if ((Data != NULL) && (DataSize != NULL))
+       {
+         Size = min(Key->DataSize, *DataSize);
+         memcpy(Data, Key->Data, Size);
+         *DataSize = Size;
+       }
+    }
+  else
+    {
+      /* query non-default value */
+      Ptr = Key->ValueList.Flink;
+      while (Ptr != &Key->ValueList)
+       {
+         Value = CONTAINING_RECORD(Ptr,
+                                   VALUE,
+                                   ValueList);
+#ifndef NDEBUG
+         printf("Name: %s\n", Value->Name);
+#endif
+         if (stricmp(Value->Name, ValueName) == 0)
+           break;
+
+         Ptr = Ptr->Flink;
+       }
+
+      if (Ptr == &Key->ValueList)
+       return(ERROR_INVALID_PARAMETER);
+
+      if (Type != NULL)
+       *Type = Value->Type;
+      if ((Data != NULL) && (DataSize != NULL))
+       {
+         if (*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;
+           }
+       }
+    }
+
+  return(ERROR_SUCCESS);
+}
+
+
+LONG
+RegDeleteValue(HKEY Key,
+              PCHAR ValueName)
+{
+  PLIST_ENTRY Ptr;
+  PVALUE Value;
+
+  if ((ValueName == NULL) || (*ValueName == 0))
+    {
+      /* delete default value */
+      if (Key->Data != NULL)
+       FreeMemory(Key->Data);
+      Key->Data = NULL;
+      Key->DataSize = 0;
+      Key->Type = 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)
+       FreeMemory(Value->Name);
+      Value->Name = NULL;
+      Value->NameSize = 0;
+
+      if (Value->DataSize > sizeof(PUCHAR))
+       {
+         if (Value->Data != NULL)
+           FreeMemory(Value->Data);
+       }
+      Value->Data = NULL;
+      Value->DataSize = 0;
+      Value->Type = 0;
+
+      RemoveEntryList(&Value->ValueList);
+      FreeMemory(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->Type;
+         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 */
diff --git a/freeldr/freeldr/reactos/registry.h b/freeldr/freeldr/reactos/registry.h
new file mode 100644 (file)
index 0000000..f10b144
--- /dev/null
@@ -0,0 +1,287 @@
+/*
+ *  FreeLoader - registry.h
+ *
+ *  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.
+ */
+
+#ifndef __REGISTRY_H
+#define __REGISTRY_H
+
+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 Type;
+  ULONG DataSize;
+  PUCHAR Data;
+} KEY, *HKEY, **PHKEY;
+
+
+typedef struct _REG_VALUE
+{
+  LIST_ENTRY ValueList;
+
+  /* value name */
+  ULONG NameSize;
+  PUCHAR Name;
+
+  /* value data */
+  ULONG Type;
+  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))
+
+
+//typedef struct _REG_KEY *HKEY, **PHKEY;
+
+
+#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);
+
+
+VOID
+RegImportHive(PCHAR ChunkBase,
+             ULONG ChunkSize);
+
+
+#endif /* __REGISTRY_H */
+
+/* EOF */
+