branch update for HEAD-2003091401
[reactos.git] / subsys / system / usetup / usetup.c
index 96620cf..6f47017 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ReactOS kernel
- *  Copyright (C) 2002 ReactOS Team
+ *  Copyright (C) 2002, 2003 ReactOS Team
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
 #include "bootsup.h"
 #include "registry.h"
 #include "format.h"
+#include "fslist.h"
+#include "cabinet.h"
 
 #define NDEBUG
 #include <debug.h>
 
+
 typedef enum _PAGE_NUMBER
 {
   START_PAGE,
@@ -53,9 +56,12 @@ typedef enum _PAGE_NUMBER
 
   SELECT_PARTITION_PAGE,
   CREATE_PARTITION_PAGE,
+  DELETE_PARTITION_PAGE,
+
   SELECT_FILE_SYSTEM_PAGE,
   FORMAT_PARTITION_PAGE,
   CHECK_FILE_SYSTEM_PAGE,
+
   PREPARE_COPY_PAGE,
   INSTALL_DIRECTORY_PAGE,
   FILE_COPY_PAGE,
@@ -64,6 +70,8 @@ typedef enum _PAGE_NUMBER
 
   REPAIR_INTRO_PAGE,
 
+  EMERGENCY_INTRO_PAGE,
+
   SUCCESS_PAGE,
   QUIT_PAGE,
   REBOOT_PAGE,                 /* virtual page */
@@ -82,29 +90,31 @@ typedef struct _COPYCONTEXT
 HANDLE ProcessHeap;
 UNICODE_STRING SourceRootPath;
 
+
 /* LOCALS *******************************************************************/
 
-static BOOLEAN PartDataValid;
-static PARTDATA PartData;
+static PPARTLIST PartitionList = NULL;
+
+static PFILE_SYSTEM_LIST FileSystemList = NULL;
 
-static BOOLEAN ActivePartitionValid;
-static PARTDATA ActivePartition;
 
 static UNICODE_STRING SourcePath;
 
 static UNICODE_STRING InstallPath;
+
+/* Path to the install directory */
 static UNICODE_STRING DestinationPath;
 static UNICODE_STRING DestinationArcPath;
 static UNICODE_STRING DestinationRootPath;
 
-static UNICODE_STRING SystemRootPath; /* Path to the active partition */
+/* Path to the active partition (boot manager) */
+static UNICODE_STRING SystemRootPath;
 
 static HINF SetupInf;
 
 static HSPFILEQ SetupFileQueue = NULL;
 
-static PPARTLIST CurrentPartitionList = NULL;
-static PFILE_SYSTEM_LIST CurrentFileSystemList;
+static BOOLEAN WarnLinuxPartitions = TRUE;
 
 
 /* FUNCTIONS ****************************************************************/
@@ -354,8 +364,8 @@ ConfirmQuit(PINPUT_RECORD Ir)
             "computer. If you quit Setup now, you will need to\n"
             "run Setup again to install ReactOS.\n"
             "\n"
-            "  * Press ENTER to continue Setup.\n"
-            "  * Press F3 to quit Setup.",
+            "  \x07  Press ENTER to continue Setup.\n"
+            "  \x07  Press F3 to quit Setup.",
             "F3= Quit  ENTER = Continue");
 
   while(TRUE)
@@ -391,12 +401,10 @@ StartPage(PINPUT_RECORD Ir)
   NTSTATUS Status;
   WCHAR FileNameBuffer[MAX_PATH];
   UNICODE_STRING FileName;
-
   INFCONTEXT Context;
   PWCHAR Value;
   ULONG ErrorLine;
 
-
   SetStatusText("   Please wait...");
 
   Status = GetSourcePaths(&SourcePath,
@@ -404,17 +412,29 @@ StartPage(PINPUT_RECORD Ir)
   if (!NT_SUCCESS(Status))
     {
       PrintTextXY(6, 15, "GetSourcePath() failed (Status 0x%08lx)", Status);
+      PopupError("Setup could not find its source drive.\n",
+                "ENTER = Reboot computer");
+      while(TRUE)
+       {
+         ConInKey(Ir);
+
+         if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)       /* ENTER */
+           {
+             return(QUIT_PAGE);
+           }
+       }
     }
+#if 0
   else
     {
       PrintTextXY(6, 15, "SourcePath: '%wZ'", &SourcePath);
       PrintTextXY(6, 16, "SourceRootPath: '%wZ'", &SourceRootPath);
     }
-
+#endif
 
   /* Load txtsetup.sif from install media. */
   wcscpy(FileNameBuffer, SourceRootPath.Buffer);
-  wcscat(FileNameBuffer, L"\\install\\txtsetup.sif");
+  wcscat(FileNameBuffer, L"\\reactos\\txtsetup.sif");
   RtlInitUnicodeString(&FileName,
                       FileNameBuffer);
 
@@ -493,18 +513,70 @@ StartPage(PINPUT_RECORD Ir)
 }
 
 
+/*
+ * First setup page
+ * RETURNS
+ *     Next page number.
+ */
+static PAGE_NUMBER
+IntroPage(PINPUT_RECORD Ir)
+{
+  SetHighlightedTextXY(6, 8, "Welcome to ReactOS Setup");
+
+  SetTextXY(6, 11, "This part of the setup copies the ReactOS Operating System to your");
+  SetTextXY(6, 12, "computer and prepares the second part of the setup.");
+
+  SetTextXY(8, 15, "\x07  Press ENTER to install ReactOS.");
+
+  SetTextXY(8, 17, "\x07  Press E to start the emergency console.");
+
+  SetTextXY(8, 19, "\x07  Press R to repair ReactOS.");
+
+  SetTextXY(8, 21, "\x07  Press F3 to quit without installing ReactOS.");
+
+
+  SetStatusText("   ENTER = Continue   F3 = Quit");
+
+  while(TRUE)
+    {
+      ConInKey(Ir);
+
+      if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
+         (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
+       {
+         if (ConfirmQuit(Ir) == TRUE)
+           return(QUIT_PAGE);
+         break;
+       }
+      else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
+       {
+         return(INSTALL_INTRO_PAGE);
+       }
+      else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'E') /* E */
+       {
+         return(EMERGENCY_INTRO_PAGE);
+       }
+      else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'R') /* R */
+       {
+         return(REPAIR_INTRO_PAGE);
+       }
+    }
+
+  return(INTRO_PAGE);
+}
+
 
 static PAGE_NUMBER
-RepairIntroPage(PINPUT_RECORD Ir)
+EmergencyIntroPage(PINPUT_RECORD Ir)
 {
   SetTextXY(6, 8, "ReactOS Setup is in an early development phase. It does not yet");
   SetTextXY(6, 9, "support all the functions of a fully usable setup application.");
 
-  SetTextXY(6, 12, "The repair functions are not implemented yet.");
+  SetTextXY(6, 12, "The emergency console is not implemented yet.");
 
-  SetTextXY(8, 15, "\xfa  Press ESC to return to the main page.");
+  SetTextXY(8, 15, "\x07  Press ESC to return to the main page.");
 
-  SetTextXY(8, 17, "\xfa  Press ENTER to reboot your computer.");
+  SetTextXY(8, 17, "\x07  Press ENTER to reboot your computer.");
 
   SetStatusText("   ESC = Main page  ENTER = Reboot");
 
@@ -527,59 +599,36 @@ RepairIntroPage(PINPUT_RECORD Ir)
 }
 
 
-/*
- * First setup page
- * RETURNS
- *     TRUE: setup/repair completed successfully
- *     FALSE: setup/repair terminated by user
- */
 static PAGE_NUMBER
-IntroPage(PINPUT_RECORD Ir)
+RepairIntroPage(PINPUT_RECORD Ir)
 {
-  SetHighlightedTextXY(6, 8, "Welcome to ReactOS Setup");
-
-  SetTextXY(6, 11, "This part of the setup copies the ReactOS Operating System to your");
-  SetTextXY(6, 12, "computer and prepares the second part of the setup.");
-
-  SetTextXY(8, 15, "\xfa  Press ENTER to install ReactOS.");
-
-  SetTextXY(8, 17, "\xfa  Press E to start the emergency repair console.");
+  SetTextXY(6, 8, "ReactOS Setup is in an early development phase. It does not yet");
+  SetTextXY(6, 9, "support all the functions of a fully usable setup application.");
 
-  SetTextXY(8, 19, "\xfa  Press R to repair ReactOS.");
+  SetTextXY(6, 12, "The repair functions are not implemented yet.");
 
-  SetTextXY(8, 21, "\xfa  Press F3 to quit without installing ReactOS.");
+  SetTextXY(8, 15, "\x07  Press ESC to return to the main page.");
 
+  SetTextXY(8, 17, "\x07  Press ENTER to reboot your computer.");
 
-  SetStatusText("   ENTER = Continue   F3 = Quit");
+  SetStatusText("   ESC = Main page  ENTER = Reboot");
 
   while(TRUE)
     {
       ConInKey(Ir);
 
-      if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
-         (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
-       {
-         if (ConfirmQuit(Ir) == TRUE)
-           return(QUIT_PAGE);
-         break;
-       }
-      else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
-       {
-         return(INSTALL_INTRO_PAGE);
-       }
-#if 0
-      else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'E') /* E */
+      if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
        {
-         return(RepairConsole());
+         return(REBOOT_PAGE);
        }
-#endif
-      else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'R') /* R */
+      else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
+              (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
        {
-         return(REPAIR_INTRO_PAGE);
+         return(INTRO_PAGE);
        }
     }
 
-  return(INTRO_PAGE);
+  return(REPAIR_INTRO_PAGE);
 }
 
 
@@ -597,9 +646,9 @@ InstallIntroPage(PINPUT_RECORD Ir)
 
 
 
-  SetTextXY(8, 21, "\xfa  Press ENTER to install ReactOS.");
+  SetTextXY(8, 21, "\x07  Press ENTER to install ReactOS.");
 
-  SetTextXY(8, 23, "\xfa  Press F3 to quit without installing ReactOS.");
+  SetTextXY(8, 23, "\x07  Press F3 to quit without installing ReactOS.");
 
 
   SetStatusText("   ENTER = Continue   F3 = Quit");
@@ -625,83 +674,83 @@ InstallIntroPage(PINPUT_RECORD Ir)
 }
 
 
-/*
- * Confirm delete partition
- * RETURNS
- *   TRUE: Delete currently selected partition.
- *   FALSE: Don't delete currently selected partition.
- */
-static BOOL
-ConfirmDeletePartition(PINPUT_RECORD Ir)
-{
-  BOOL Result = FALSE;
-
-  PopupError("Are you sure you want to delete this partition?\n"
-            "\n"
-            "  * Press ENTER to delete the partition.\n"
-            "  * Press ESC to NOT delete the partition.",
-            "ESC = Cancel  ENTER = Delete partition");
-
-  while(TRUE)
-    {
-      ConInKey(Ir);
-
-      if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)  /* ESC */
-       {
-         Result = FALSE;
-         break;
-       }
-      else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN)        /* ENTER */
-       {
-         Result = TRUE;
-         break;
-       }
-    }
-
-  return(Result);
-}
-
-
 static PAGE_NUMBER
 SelectPartitionPage(PINPUT_RECORD Ir)
 {
-  WCHAR PathBuffer[MAX_PATH];
-  PPARTLIST PartList;
   SHORT xScreen;
   SHORT yScreen;
 
   SetTextXY(6, 8, "The list below shows existing partitions and unused disk");
   SetTextXY(6, 9, "space for new partitions.");
 
-  SetTextXY(8, 11, "\xfa  Press UP or DOWN to select a list entry.");
-  SetTextXY(8, 13, "\xfa  Press ENTER to install ReactOS onto the selected partition.");
-  SetTextXY(8, 15, "\xfa  Press C to create a new partition.");
-  SetTextXY(8, 17, "\xfa  Press D to delete an existing partition.");
+  SetTextXY(8, 11, "\x07  Press UP or DOWN to select a list entry.");
+  SetTextXY(8, 13, "\x07  Press ENTER to install ReactOS onto the selected partition.");
+  SetTextXY(8, 15, "\x07  Press C to create a new partition.");
+  SetTextXY(8, 17, "\x07  Press D to delete an existing partition.");
 
   SetStatusText("   Please wait...");
 
-  RtlFreeUnicodeString(&DestinationPath);
-  RtlFreeUnicodeString(&DestinationRootPath);
-
   GetScreenSize(&xScreen, &yScreen);
 
-  PartList = CreatePartitionList(2, 19, xScreen - 3, yScreen - 3);
-  if (PartList == NULL)
+  if (PartitionList == NULL)
     {
-      /* FIXME: show an error dialog */
-      return(QUIT_PAGE);
+      PartitionList = CreatePartitionList (2,
+                                          19,
+                                          xScreen - 3,
+                                          yScreen - 3);
+      if (PartitionList == NULL)
+       {
+         /* FIXME: show an error dialog */
+         return(QUIT_PAGE);
+       }
     }
 
-  if (CurrentPartitionList != NULL)
+  CheckActiveBootPartition (PartitionList);
+
+  DrawPartitionList (PartitionList);
+
+  /* Warn about partitions created by Linux Fdisk */
+  if (WarnLinuxPartitions == TRUE &&
+      CheckForLinuxFdiskPartitions (PartitionList) == TRUE)
     {
-      DestroyPartitionList(CurrentPartitionList);
-    }
-  CurrentPartitionList = PartList;
+      PopupError ("Setup found that at least one harddisk contains an incompatible\n"
+                 "partition table that can not be handled properly!\n"
+                 "\n"
+                 "Creating or deleting partitions can destroy the partiton table.\n"
+                 "\n"
+                 "  \x07  Press F3 to quit Setup."
+                 "  \x07  Press ENTER to continue.",
+                 "F3= Quit  ENTER = Continue");
+      while (TRUE)
+       {
+         ConInKey (Ir);
 
-  SetStatusText("   ENTER = Continue   F3 = Quit");
+         if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
+             (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
+           {
+             return QUIT_PAGE;
+           }
+         else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
+           {
+             WarnLinuxPartitions = FALSE;
+             return SELECT_PARTITION_PAGE;
+           }
+       }
+    }
 
   while(TRUE)
     {
+      /* Update status text */
+      if (PartitionList->CurrentPartition == NULL ||
+         PartitionList->CurrentPartition->Unpartitioned == TRUE)
+       {
+         SetStatusText ("   ENTER = Install   C = Create Partition   F3 = Quit");
+       }
+      else
+       {
+         SetStatusText ("   ENTER = Install   D = Delete Partition   F3 = Quit");
+       }
+
       ConInKey(Ir);
 
       if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
@@ -709,91 +758,71 @@ SelectPartitionPage(PINPUT_RECORD Ir)
        {
          if (ConfirmQuit(Ir) == TRUE)
            {
-             DestroyPartitionList(PartList);
-             return(QUIT_PAGE);
+             DestroyPartitionList (PartitionList);
+             PartitionList = NULL;
+             return QUIT_PAGE;
            }
          break;
        }
       else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
               (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
        {
-         ScrollDownPartitionList(PartList);
+         ScrollDownPartitionList (PartitionList);
        }
       else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
               (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
        {
-         ScrollUpPartitionList(PartList);
+         ScrollUpPartitionList (PartitionList);
        }
       else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
        {
-         PartDataValid = GetSelectedPartition(PartList,
-                                              &PartData);
-    if (PartDataValid)
-      {
-         ActivePartitionValid = GetActiveBootPartition(PartList,
-                                                       &ActivePartition);
-    
-         RtlFreeUnicodeString(&DestinationRootPath);
-         swprintf(PathBuffer,
-                  L"\\Device\\Harddisk%lu\\Partition%lu",
-                  PartData.DiskNumber,
-                  PartData.PartNumber);
-         RtlCreateUnicodeString(&DestinationRootPath,
-                                PathBuffer);
-    
-         RtlFreeUnicodeString(&SystemRootPath);
-    
-          if (ActivePartitionValid)
-            {
-             swprintf(PathBuffer,
-                   L"\\Device\\Harddisk%lu\\Partition%lu",
-                   ActivePartition.DiskNumber,
-                   ActivePartition.PartNumber);
-            }
-          else
-            {
-              /* We mark the selected partition as bootable */
-             swprintf(PathBuffer,
-                   L"\\Device\\Harddisk%lu\\Partition%lu",
-                   PartData.DiskNumber,
-                   PartData.PartNumber);
-            }
-         RtlCreateUnicodeString(&SystemRootPath,
-                                PathBuffer);
-    
-         return(SELECT_FILE_SYSTEM_PAGE);
-      }
-    else
-      {
-        /* FIXME: show an error dialog */
-        return(SELECT_PARTITION_PAGE);
-      }
+         if (PartitionList->CurrentPartition == NULL ||
+             PartitionList->CurrentPartition->Unpartitioned == TRUE)
+           {
+             CreateNewPartition (PartitionList,
+                                 0ULL,
+                                 TRUE);
+           }
+
+         return SELECT_FILE_SYSTEM_PAGE;
        }
       else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_C) /* C */
        {
-#ifdef ENABLE_FORMAT
-    /* Don't destroy the parition list here */;
-    return(CREATE_PARTITION_PAGE);
-#endif
+         if (PartitionList->CurrentPartition->Unpartitioned == FALSE)
+           {
+             PopupError ("You can not create a new Partition inside\n"
+                         "of an already existing Partition!\n"
+                         "\n"
+                         "  * Press any key to continue.",
+                         NULL);
+             ConInKey (Ir);
+
+             return SELECT_PARTITION_PAGE;
+           }
+
+         return CREATE_PARTITION_PAGE;
        }
       else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_D) /* D */
        {
-#ifdef ENABLE_FORMAT
-         if (ConfirmDeletePartition(Ir) == TRUE)
-      {
-        (BOOLEAN) DeleteSelectedPartition(CurrentPartitionList);
-      }
-    return(SELECT_PARTITION_PAGE);
-#endif
-       }
+         if (PartitionList->CurrentPartition->Unpartitioned == TRUE)
+           {
+             PopupError ("You can not delete unpartitioned disk space!\n"
+                         "\n"
+                         "  * Press any key to continue.",
+                         NULL);
+             ConInKey (Ir);
 
-      /* FIXME: Update status text */
+             return SELECT_PARTITION_PAGE;
+           }
 
+         return DELETE_PARTITION_PAGE;
+       }
     }
 
-  return(SELECT_PARTITION_PAGE);
+  return SELECT_PARTITION_PAGE;
 }
 
+
 static VOID
 DrawInputField(ULONG FieldLength,
   SHORT Left,
@@ -808,46 +837,41 @@ DrawInputField(ULONG FieldLength,
   memset(buf, '_', sizeof(buf));
   buf[FieldLength - strlen(FieldContent)] = 0;
   strcat(buf, FieldContent);
-  WriteConsoleOutputCharacters(buf,
-              strlen(buf),
-              coPos);
+
+  WriteConsoleOutputCharacters (buf,
+                               strlen (buf),
+                               coPos);
 }
 
+
 #define PARTITION_SIZE_INPUT_FIELD_LENGTH 6
 
 static VOID
-ShowPartitionSizeInputBox(ULONG MaxSize,
-  PCHAR InputBuffer,
-  PBOOLEAN Quit,
-  PBOOLEAN Cancel)
+ShowPartitionSizeInputBox(SHORT Left,
+                         SHORT Top,
+                         SHORT Right,
+                         SHORT Bottom,
+                         ULONG MaxSize,
+                         PCHAR InputBuffer,
+                         PBOOLEAN Quit,
+                         PBOOLEAN Cancel)
 {
-  SHORT Left;
-  SHORT Top;
-  SHORT Right;
-  SHORT Bottom;
   INPUT_RECORD Ir;
   COORD coPos;
   ULONG Written;
   SHORT i;
-  CHAR buf[100];
-  ULONG index;
+  CHAR Buffer[100];
+  ULONG Index;
   CHAR ch;
   SHORT iLeft;
   SHORT iTop;
-  SHORT xScreen;
-  SHORT yScreen;
 
   if (Quit != NULL)
     *Quit = FALSE;
+
   if (Cancel != NULL)
     *Cancel = FALSE;
 
-  GetScreenSize(&xScreen, &yScreen);
-  Left = 12;
-  Top = 11;
-  Right = xScreen - 12;
-  Bottom = 15;
-
   /* draw upper left corner */
   coPos.X = Left;
   coPos.Y = Top;
@@ -916,75 +940,86 @@ ShowPartitionSizeInputBox(ULONG MaxSize,
   /* Print message */
   coPos.X = Left + 2;
   coPos.Y = Top + 2;
-  strcpy(buf, "Size of new partition:");
-  iLeft = coPos.X + strlen(buf) + 1;
+  strcpy (Buffer, "Size of new partition:");
+  iLeft = coPos.X + strlen (Buffer) + 1;
   iTop = coPos.Y;
-  WriteConsoleOutputCharacters(buf,
-                      strlen(buf),
-                      coPos);
+  WriteConsoleOutputCharacters (Buffer,
+                                strlen (Buffer),
+                                coPos);
 
-  sprintf(buf, "MB (max. %d MB)", MaxSize / (1024 * 1024));
+  sprintf (Buffer, "MB (max. %d MB)", MaxSize);
   coPos.X = iLeft + PARTITION_SIZE_INPUT_FIELD_LENGTH + 1;
   coPos.Y = iTop;
-  WriteConsoleOutputCharacters(buf,
-                      strlen(buf),
-                      coPos);
+  WriteConsoleOutputCharacters (Buffer,
+                               strlen (Buffer),
+                               coPos);
 
-  buf[0] = 0;
-  index = 0;
-  DrawInputField(PARTITION_SIZE_INPUT_FIELD_LENGTH, iLeft, iTop, buf);
+  Buffer[0] = 0;
+  Index = 0;
+  DrawInputField (PARTITION_SIZE_INPUT_FIELD_LENGTH,
+                 iLeft,
+                 iTop,
+                 Buffer);
 
-  while(TRUE)
+  while (TRUE)
     {
-      ConInKey(&Ir);
+      ConInKey (&Ir);
+
       if ((Ir.Event.KeyEvent.uChar.AsciiChar == 0x00) &&
-           (Ir.Event.KeyEvent.wVirtualKeyCode == VK_F3))       /* F3 */
-       {
-          if (Quit != NULL)
-            *Quit = TRUE;
-          buf[0] = 0;
-         break;
-       }
+         (Ir.Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
+       {
+         if (Quit != NULL)
+           *Quit = TRUE;
+         Buffer[0] = 0;
+         break;
+       }
       else if (Ir.Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
-       {
-                 break;
-       }
+       {
+         break;
+       }
       else if (Ir.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESCAPE */
-       {
-          if (Cancel != NULL)
-            *Cancel = FALSE;
-          buf[0] = 0;
-                 break;
-       }
-      else if ((Ir.Event.KeyEvent.wVirtualKeyCode == VK_BACK) && (index > 0)) /* BACKSPACE */
-       {
-          index--;
-          buf[index] = 0;
-          DrawInputField(PARTITION_SIZE_INPUT_FIELD_LENGTH, iLeft, iTop, buf);
-       }
-      else if ((Ir.Event.KeyEvent.uChar.AsciiChar != 0x00)
-        && (index < PARTITION_SIZE_INPUT_FIELD_LENGTH))
-        {
-          ch = Ir.Event.KeyEvent.uChar.AsciiChar;
-          if ((ch >= '0') && (ch <= '9'))
-            {
-              buf[index] = ch;
-              index++;
-              buf[index] = 0;
-              DrawInputField(PARTITION_SIZE_INPUT_FIELD_LENGTH, iLeft, iTop, buf);
-            }
-        }
+       {
+         if (Cancel != NULL)
+           *Cancel = TRUE;
+         Buffer[0] = 0;
+         break;
+       }
+      else if ((Ir.Event.KeyEvent.wVirtualKeyCode == VK_BACK) &&  /* BACKSPACE */
+              (Index > 0))
+       {
+         Index--;
+         Buffer[Index] = 0;
+         DrawInputField (PARTITION_SIZE_INPUT_FIELD_LENGTH,
+                         iLeft,
+                         iTop,
+                         Buffer);
+       }
+      else if ((Ir.Event.KeyEvent.uChar.AsciiChar != 0x00) &&
+              (Index < PARTITION_SIZE_INPUT_FIELD_LENGTH))
+       {
+         ch = Ir.Event.KeyEvent.uChar.AsciiChar;
+         if ((ch >= '0') && (ch <= '9'))
+           {
+             Buffer[Index] = ch;
+             Index++;
+             Buffer[Index] = 0;
+             DrawInputField (PARTITION_SIZE_INPUT_FIELD_LENGTH,
+                             iLeft,
+                             iTop,
+                             Buffer);
+           }
+       }
     }
-  strcpy(InputBuffer, buf);
+
+  strcpy (InputBuffer,
+         Buffer);
 }
 
 
 static PAGE_NUMBER
-CreatePartitionPage(PINPUT_RECORD Ir)
+CreatePartitionPage (PINPUT_RECORD Ir)
 {
-  BOOLEAN Valid;
-  WCHAR PathBuffer[MAX_PATH];
-  PPARTLIST PartList;
+  PDISKENTRY DiskEntry;
   PPARTENTRY PartEntry;
   SHORT xScreen;
   SHORT yScreen;
@@ -993,282 +1028,366 @@ CreatePartitionPage(PINPUT_RECORD Ir)
   CHAR InputBuffer[50];
   ULONG MaxSize;
   ULONGLONG PartSize;
+  ULONGLONG DiskSize;
+  PCHAR Unit;
 
-  SetTextXY(6, 8, "You have chosen to create a new partition in the unused disk space.");
-  SetTextXY(6, 9, "Please enter the size of the new partition in megabytes.");
+  if (PartitionList == NULL ||
+      PartitionList->CurrentDisk == NULL ||
+      PartitionList->CurrentPartition == NULL)
+    {
+      /* FIXME: show an error dialog */
+      return QUIT_PAGE;
+    }
 
-  SetStatusText("   Please wait...");
+  DiskEntry = PartitionList->CurrentDisk;
+  PartEntry = PartitionList->CurrentPartition;
 
-  GetScreenSize(&xScreen, &yScreen);
+  SetStatusText ("   Please wait...");
 
-  PartList = CurrentPartitionList;
+  GetScreenSize (&xScreen, &yScreen);
 
-  SetStatusText("   ENTER = Continue   ESC = Cancel   F3 = Quit");
+  SetTextXY (6, 8, "You have chosen to create a new partition on");
 
-  PartEntry = &PartList->DiskArray[PartList->CurrentDisk].PartArray[PartList->CurrentPartition];
+#if 0
+  if (DiskEntry->DiskSize >= 0x280000000ULL) /* 10 GB */
+    {
+      DiskSize = (DiskEntry->DiskSize + (1 << 29)) >> 30;
+      Unit = "GB";
+    }
+  else
+#endif
+    {
+      DiskSize = (DiskEntry->DiskSize + (1 << 19)) >> 20;
+      if (DiskSize == 0)
+       DiskSize = 1;
+      Unit = "MB";
+    }
+
+  if (DiskEntry->DriverName.Length > 0)
+    {
+      PrintTextXY (6, 10,
+                  "%I64u %s  Harddisk %lu  (Port=%hu, Bus=%hu, Id=%hu) on %wZ.",
+                  DiskSize,
+                  Unit,
+                  DiskEntry->DiskNumber,
+                  DiskEntry->Port,
+                  DiskEntry->Bus,
+                  DiskEntry->Id,
+                  &DiskEntry->DriverName);
+    }
+  else
+    {
+      PrintTextXY (6, 10,
+                  "%I64u %s  Harddisk %lu  (Port=%hu, Bus=%hu, Id=%hu).",
+                  DiskSize,
+                  Unit,
+                  DiskEntry->DiskNumber,
+                  DiskEntry->Port,
+                  DiskEntry->Bus,
+                  DiskEntry->Id);
+    }
+
+
+  SetTextXY (6, 12, "Please enter the size of the new partition in megabytes.");
+
+#if 0
+  PrintTextXY (8, 10, "Maximum size of the new partition is %I64u MB",
+              PartitionList->CurrentPartition->UnpartitionedLength / (1024*1024));
+#endif
+
+  SetStatusText ("   ENTER = Create Partition   ESC = Cancel   F3 = Quit");
+
+  PartEntry = PartitionList->CurrentPartition;
   while (TRUE)
     {
-      MaxSize = PartEntry->PartSize;
-      ShowPartitionSizeInputBox(MaxSize, InputBuffer, &Quit, &Cancel);
+      MaxSize = (PartEntry->UnpartitionedLength + (1 << 19)) >> 20;  /* in MBytes (rounded) */
+      ShowPartitionSizeInputBox (12, 14, xScreen - 12, 17, /* left, top, right, bottom */
+                                MaxSize, InputBuffer, &Quit, &Cancel);
       if (Quit == TRUE)
-        {
-         if (ConfirmQuit(Ir) == TRUE)
-           {
-             DestroyPartitionList(PartList);
-             return(QUIT_PAGE);
-           }
-        }
+       {
+         if (ConfirmQuit (Ir) == TRUE)
+           {
+             return QUIT_PAGE;
+           }
+       }
       else if (Cancel == TRUE)
-        {
-          break;
-        }
+       {
+         return SELECT_PARTITION_PAGE;
+       }
       else
-        {
-          PartSize = atoi(InputBuffer);
-          if (PartSize < 1)
-            {
-              // Too small
-              continue;
-            }
-          /* Convert to bytes */
-          PartSize *= 1024 * 1024;
-
-          if (PartSize > PartEntry->PartSize)
-            {
-              // Too large
-              continue;
-            }
-
-          assert(PartEntry->Unpartitioned == TRUE);
-          PartEntry->PartType = PARTITION_ENTRY_UNUSED;
-          PartEntry->Used = TRUE;
-
-         PartDataValid = GetSelectedPartition(PartList,
-                                              &PartData);
-          if (PartDataValid)
-            {
-              PartData.CreatePartition = TRUE;
-              PartData.NewPartSize = PartSize;
-
-                 ActivePartitionValid = GetActiveBootPartition(PartList,
-                                                               &ActivePartition);
-
-                 RtlFreeUnicodeString(&DestinationRootPath);
-                 swprintf(PathBuffer,
-                          L"\\Device\\Harddisk%lu\\Partition%lu",
-                          PartData.DiskNumber,
-                          PartData.PartNumber);
-                 RtlCreateUnicodeString(&DestinationRootPath,
-                                        PathBuffer);
-
-                 RtlFreeUnicodeString(&SystemRootPath);
-
-              if (ActivePartitionValid)
-                {
-                     swprintf(PathBuffer,
-                           L"\\Device\\Harddisk%lu\\Partition%lu",
-                           ActivePartition.DiskNumber,
-                           ActivePartition.PartNumber);
-                }
-              else
-                {
-                  /* We mark the selected partition as bootable */
-                     swprintf(PathBuffer,
-                           L"\\Device\\Harddisk%lu\\Partition%lu",
-                           PartData.DiskNumber,
-                           PartData.PartNumber);
-                }
-                 RtlCreateUnicodeString(&SystemRootPath,
-                                        PathBuffer);
-
-                 return(SELECT_FILE_SYSTEM_PAGE);
-            }
-          else
-            {
-              /* FIXME: show an error dialog */
-              return(SELECT_PARTITION_PAGE);
-            }
-        }
-    }
+       {
+         PartSize = atoi (InputBuffer);
+         if (PartSize < 1)
+           {
+             /* Too small */
+             continue;
+           }
 
-  return(SELECT_PARTITION_PAGE);
-}
+         if (PartSize > MaxSize)
+           {
+             /* Too large */
+             continue;
+           }
 
+         /* Convert to bytes */
+         if (PartSize == MaxSize)
+           {
+             /* Use all of the unpartitioned disk space */
+             PartSize = PartEntry->UnpartitionedLength;
+           }
+         else
+           {
+             /* Round-up by cylinder size */
+             PartSize = ROUND_UP (PartSize * 1024 * 1024,
+                                  DiskEntry->CylinderSize);
 
-static PFILE_SYSTEM_LIST
-CreateFileSystemList(SHORT Left,
-  SHORT Top,
-  BOOLEAN ForceFormat,
-  FILE_SYSTEM ForceFileSystem)
-{
-  PFILE_SYSTEM_LIST List;
+             /* But never get larger than the unpartitioned disk space */
+             if (PartSize > PartEntry->UnpartitionedLength)
+               PartSize = PartEntry->UnpartitionedLength;
+           }
 
-  List = (PFILE_SYSTEM_LIST)RtlAllocateHeap(ProcessHeap, 0, sizeof(FILE_SYSTEM_LIST));
-  if (List == NULL)
-    return(NULL);
+         DPRINT ("Partition size: %I64u bytes\n", PartSize);
 
-  List->Left = Left;
-  List->Top = Top;
+         CreateNewPartition (PartitionList,
+                             PartSize,
+                             FALSE);
 
-#ifdef ENABLE_FORMAT
-  List->FileSystemCount = 1;
-#else
-  List->FileSystemCount = 0;
-#endif
-  if (ForceFormat)
-    {
-      List->CurrentFileSystem = ForceFileSystem;
-    }
-  else
-    {
-      List->FileSystemCount++;
-      List->CurrentFileSystem = FsKeep;
+         return SELECT_PARTITION_PAGE;
+       }
     }
-  return(List);
+
+  return CREATE_PARTITION_PAGE;
 }
 
 
-static VOID
-DestroyFileSystemList(PFILE_SYSTEM_LIST List)
+static PAGE_NUMBER
+DeletePartitionPage (PINPUT_RECORD Ir)
 {
-  RtlFreeHeap(ProcessHeap, 0, List);
-}
+  PDISKENTRY DiskEntry;
+  PPARTENTRY PartEntry;
+  ULONGLONG DiskSize;
+  ULONGLONG PartSize;
+  PCHAR Unit;
+  PCHAR PartType;
 
+  if (PartitionList == NULL ||
+      PartitionList->CurrentDisk == NULL ||
+      PartitionList->CurrentPartition == NULL)
+    {
+      /* FIXME: show an error dialog */
+      return QUIT_PAGE;
+    }
 
-static VOID
-DrawFileSystemList(PFILE_SYSTEM_LIST List)
-{
-  COORD coPos;
-  ULONG Written;
-  ULONG index;
+  DiskEntry = PartitionList->CurrentDisk;
+  PartEntry = PartitionList->CurrentPartition;
 
-  index = 0;
+  SetTextXY (6, 8, "You have chosen to delete the partition");
 
-#ifdef ENABLE_FORMAT
-  coPos.X = List->Left;
-  coPos.Y = List->Top + index;
-  FillConsoleOutputAttribute(0x17,
-                            50,
-                            coPos,
-                            &Written);
-  FillConsoleOutputCharacter(' ',
-                            50,
-                            coPos,
-                            &Written);
+  /* Determine partition type */
+  PartType = NULL;
+  if (PartEntry->New == TRUE)
+    {
+      PartType = "New (Unformatted)";
+    }
+  else if (PartEntry->Unpartitioned == FALSE)
+    {
+      if ((PartEntry->PartInfo[0].PartitionType == PARTITION_FAT_12) ||
+         (PartEntry->PartInfo[0].PartitionType == PARTITION_FAT_16) ||
+         (PartEntry->PartInfo[0].PartitionType == PARTITION_HUGE) ||
+         (PartEntry->PartInfo[0].PartitionType == PARTITION_XINT13))
+       {
+         PartType = "FAT";
+       }
+      else if ((PartEntry->PartInfo[0].PartitionType == PARTITION_FAT32) ||
+              (PartEntry->PartInfo[0].PartitionType == PARTITION_FAT32_XINT13))
+       {
+         PartType = "FAT32";
+       }
+      else if (PartEntry->PartInfo[0].PartitionType == PARTITION_IFS)
+       {
+         PartType = "NTFS"; /* FIXME: Not quite correct! */
+       }
+    }
 
-  if (List->CurrentFileSystem == FsFat)
+#if 0
+  if (PartEntry->PartInfo[0].PartitionLength.QuadPart >= 0x280000000ULL) /* 10 GB */
     {
-      SetInvertedTextXY(List->Left, List->Top + index, " Format partition as FAT file system ");
+      PartSize = (PartEntry->PartInfo[0].PartitionLength.QuadPart + (1 << 29)) >> 30;
+      Unit = "GB";
     }
   else
+#endif
+  if (PartEntry->PartInfo[0].PartitionLength.QuadPart >= 0xA00000ULL) /* 10 MB */
     {
-      SetTextXY(List->Left, List->Top + index, " Format partition as FAT file system ");
+      PartSize = (PartEntry->PartInfo[0].PartitionLength.QuadPart + (1 << 19)) >> 20;
+      Unit = "MB";
+    }
+  else
+    {
+      PartSize = (PartEntry->PartInfo[0].PartitionLength.QuadPart + (1 << 9)) >> 10;
+      Unit = "KB";
     }
-  index++;
-#endif
-
-  coPos.X = List->Left;
-  coPos.Y = List->Top + index;
-  FillConsoleOutputAttribute(0x17,
-                            50,
-                            coPos,
-                            &Written);
-  FillConsoleOutputCharacter(' ',
-                            50,
-                            coPos,
-                            &Written);
 
-  if (List->CurrentFileSystem == FsKeep)
+  if (PartType == NULL)
     {
-      SetInvertedTextXY(List->Left, List->Top + index, " Keep current file system (no changes) ");
+      PrintTextXY (6, 10,
+                  "   %c%c  Type %lu    %I64u %s",
+                  (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
+                  (PartEntry->DriveLetter == 0) ? '-' : ':',
+                  PartEntry->PartInfo[0].PartitionType,
+                  PartSize,
+                  Unit);
     }
   else
     {
-      SetTextXY(List->Left, List->Top + index, " Keep current file system (no changes) ");
+      PrintTextXY (6, 10,
+                  "   %c%c  %s    %I64u %s",
+                  (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
+                  (PartEntry->DriveLetter == 0) ? '-' : ':',
+                  PartType,
+                  PartSize,
+                  Unit);
     }
-}
 
+#if 0
+  if (DiskEntry->DiskSize >= 0x280000000ULL) /* 10 GB */
+    {
+      DiskSize = (DiskEntry->DiskSize + (1 << 29)) >> 30;
+      Unit = "GB";
+    }
+  else
+#endif
+    {
+      DiskSize = (DiskEntry->DiskSize + (1 << 19)) >> 20;
+      if (DiskSize == 0)
+       DiskSize = 1;
+      Unit = "MB";
+    }
 
-static VOID
-ScrollDownFileSystemList(PFILE_SYSTEM_LIST List)
-{
-  if ((ULONG) List->CurrentFileSystem < List->FileSystemCount - 1)
+  if (DiskEntry->DriverName.Length > 0)
     {
-      (ULONG) List->CurrentFileSystem++;
-      DrawFileSystemList(List);
+      PrintTextXY (6, 12,
+                  "on %I64u %s  Harddisk %lu  (Port=%hu, Bus=%hu, Id=%hu) on %wZ.",
+                  DiskSize,
+                  Unit,
+                  DiskEntry->DiskNumber,
+                  DiskEntry->Port,
+                  DiskEntry->Bus,
+                  DiskEntry->Id,
+                  &DiskEntry->DriverName);
+    }
+  else
+    {
+      PrintTextXY (6, 12,
+                  "on %I64u %s  Harddisk %lu  (Port=%hu, Bus=%hu, Id=%hu).",
+                  DiskSize,
+                  Unit,
+                  DiskEntry->DiskNumber,
+                  DiskEntry->Port,
+                  DiskEntry->Bus,
+                  DiskEntry->Id);
     }
-}
 
+  SetTextXY (8, 18, "\x07  Press D to delete the partition.");
+  SetTextXY (11, 19, "WARNING: All data on this partition will be lost!");
 
-static VOID
-ScrollUpFileSystemList(PFILE_SYSTEM_LIST List)
-{
-  if ((ULONG) List->CurrentFileSystem > 0)
+  SetTextXY (8, 21, "\x07  Press ESC to cancel.");
+
+  SetStatusText ("   D = Delete Partition   ESC = Cancel   F3 = Quit");
+
+  while (TRUE)
     {
-      (ULONG) List->CurrentFileSystem--;
-      DrawFileSystemList(List);
+      ConInKey (Ir);
+
+      if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
+         (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
+       {
+         if (ConfirmQuit (Ir) == TRUE)
+           {
+             return QUIT_PAGE;
+           }
+         break;
+       }
+      else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)  /* ESC */
+       {
+         return SELECT_PARTITION_PAGE;
+       }
+      else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_D) /* D */
+       {
+         DeleteCurrentPartition (PartitionList);
+
+         return SELECT_PARTITION_PAGE;
+       }
     }
+
+  return DELETE_PARTITION_PAGE;
 }
 
 
 static PAGE_NUMBER
-SelectFileSystemPage(PINPUT_RECORD Ir)
+SelectFileSystemPage (PINPUT_RECORD Ir)
 {
-  PFILE_SYSTEM_LIST FileSystemList;
+  PDISKENTRY DiskEntry;
+  PPARTENTRY PartEntry;
   ULONGLONG DiskSize;
   ULONGLONG PartSize;
   PCHAR DiskUnit;
   PCHAR PartUnit;
   PCHAR PartType;
 
-  if (PartDataValid == FALSE)
+  if (PartitionList == NULL ||
+      PartitionList->CurrentDisk == NULL ||
+      PartitionList->CurrentPartition == NULL)
     {
       /* FIXME: show an error dialog */
-      return(QUIT_PAGE);
+      return QUIT_PAGE;
     }
 
+  DiskEntry = PartitionList->CurrentDisk;
+  PartEntry = PartitionList->CurrentPartition;
+
   /* adjust disk size */
-  if (PartData.DiskSize >= 0x280000000ULL) /* 10 GB */
+  if (DiskEntry->DiskSize >= 0x280000000ULL) /* 10 GB */
     {
-      DiskSize = (PartData.DiskSize + (1 << 29)) >> 30;
+      DiskSize = (DiskEntry->DiskSize + (1 << 29)) >> 30;
       DiskUnit = "GB";
     }
   else
     {
-      DiskSize = (PartData.DiskSize + (1 << 19)) >> 20;
+      DiskSize = (DiskEntry->DiskSize + (1 << 19)) >> 20;
       DiskUnit = "MB";
     }
 
   /* adjust partition size */
-  if (PartData.PartSize >= 0x280000000ULL) /* 10 GB */
+  if (PartEntry->PartInfo[0].PartitionLength.QuadPart >= 0x280000000ULL) /* 10 GB */
     {
-      PartSize = (PartData.PartSize + (1 << 29)) >> 30;
+      PartSize = (PartEntry->PartInfo[0].PartitionLength.QuadPart + (1 << 29)) >> 30;
       PartUnit = "GB";
     }
   else
     {
-      PartSize = (PartData.PartSize + (1 << 19)) >> 20;
+      PartSize = (PartEntry->PartInfo[0].PartitionLength.QuadPart + (1 << 19)) >> 20;
       PartUnit = "MB";
     }
 
   /* adjust partition type */
-  if ((PartData.PartType == PARTITION_FAT_12) ||
-      (PartData.PartType == PARTITION_FAT_16) ||
-      (PartData.PartType == PARTITION_HUGE) ||
-      (PartData.PartType == PARTITION_XINT13))
+  if ((PartEntry->PartInfo[0].PartitionType == PARTITION_FAT_12) ||
+      (PartEntry->PartInfo[0].PartitionType == PARTITION_FAT_16) ||
+      (PartEntry->PartInfo[0].PartitionType == PARTITION_HUGE) ||
+      (PartEntry->PartInfo[0].PartitionType == PARTITION_XINT13))
     {
       PartType = "FAT";
     }
-  else if ((PartData.PartType == PARTITION_FAT32) ||
-          (PartData.PartType == PARTITION_FAT32_XINT13))
+  else if ((PartEntry->PartInfo[0].PartitionType == PARTITION_FAT32) ||
+          (PartEntry->PartInfo[0].PartitionType == PARTITION_FAT32_XINT13))
     {
       PartType = "FAT32";
     }
-  else if (PartData.PartType == PARTITION_IFS)
+  else if (PartEntry->PartInfo[0].PartitionType == PARTITION_IFS)
     {
       PartType = "NTFS"; /* FIXME: Not quite correct! */
     }
-  else if (PartData.PartType == PARTITION_ENTRY_UNUSED)
+  else if (PartEntry->PartInfo[0].PartitionType == PARTITION_ENTRY_UNUSED)
     {
       PartType = "Unused";
     }
@@ -1277,166 +1396,408 @@ SelectFileSystemPage(PINPUT_RECORD Ir)
       PartType = "Unknown";
     }
 
-  SetTextXY(6, 8, "Setup will install ReactOS on");
+  if (PartEntry->AutoCreate == TRUE)
+    {
+      SetTextXY(6, 8, "Setup created a new partition on");
 
+#if 0
   PrintTextXY(8, 10, "Partition %lu (%I64u %s) %s of",
-             PartData.PartNumber,
+             PartEntry->PartInfo[0].PartitionNumber,
              PartSize,
              PartUnit,
              PartType);
+#endif
 
-  PrintTextXY(8, 12, "Harddisk %lu (%I64u %s), Port=%hu, Bus=%hu, Id=%hu (%wZ).",
-             PartData.DiskNumber,
+  PrintTextXY(8, 10, "Harddisk %lu (%I64u %s), Port=%hu, Bus=%hu, Id=%hu (%wZ).",
+             DiskEntry->DiskNumber,
              DiskSize,
              DiskUnit,
-             PartData.Port,
-             PartData.Bus,
-             PartData.Id,
-             &PartData.DriverName);
+             DiskEntry->Port,
+             DiskEntry->Bus,
+             DiskEntry->Id,
+             &DiskEntry->DriverName);
+
+      SetTextXY(6, 12, "This Partition will be formatted next.");
+
+
+      PartEntry->AutoCreate = FALSE;
+    }
+  else if (PartEntry->New == TRUE)
+    {
+      SetTextXY(6, 8, "You chose to install ReactOS on a new or unformatted Partition.");
+      SetTextXY(6, 10, "This Partition will be formatted next.");
+    }
+  else
+    {
+      SetTextXY(6, 8, "Setup install ReactOS onto Partition");
+
+      if (PartType == NULL)
+       {
+         PrintTextXY (8, 10,
+                      "%c%c  Type %lu    %I64u %s",
+                      (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
+                      (PartEntry->DriveLetter == 0) ? '-' : ':',
+                      PartEntry->PartInfo[0].PartitionType,
+                      PartSize,
+                      PartUnit);
+       }
+      else
+       {
+         PrintTextXY (8, 10,
+                      "%c%c  %s    %I64u %s",
+                      (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
+                      (PartEntry->DriveLetter == 0) ? '-' : ':',
+                      PartType,
+                      PartSize,
+                      PartUnit);
+       }
+
+      PrintTextXY(6, 12, "on Harddisk %lu (%I64u %s), Port=%hu, Bus=%hu, Id=%hu (%wZ).",
+                 DiskEntry->DiskNumber,
+                 DiskSize,
+                 DiskUnit,
+                 DiskEntry->Port,
+                 DiskEntry->Bus,
+                 DiskEntry->Id,
+                 &DiskEntry->DriverName);
+    }
 
 
-  SetTextXY(6, 17, "Select a file system for the partition from the list below.");
+  SetTextXY(6, 17, "Select a file system from the list below.");
 
-  SetTextXY(8, 19, "\xfa  Press UP or DOWN to select a file system.");
-  SetTextXY(8, 21, "\xfa  Press ENTER to format the partition.");
-  SetTextXY(8, 23, "\xfa  Press ESC to select another partition.");
+  SetTextXY(8, 19, "\x07  Press UP or DOWN to select a file system.");
+  SetTextXY(8, 21, "\x07  Press ENTER to format the partition.");
+  SetTextXY(8, 23, "\x07  Press ESC to select another partition.");
 
-  FileSystemList = CreateFileSystemList(6, 26, FALSE, FsKeep);
   if (FileSystemList == NULL)
     {
-      /* FIXME: show an error dialog */
-      return(QUIT_PAGE);
+      FileSystemList = CreateFileSystemList (6, 26, PartEntry->New, FsFat);
+      if (FileSystemList == NULL)
+       {
+         /* FIXME: show an error dialog */
+         return QUIT_PAGE;
+       }
+
+      /* FIXME: Add file systems to list */
     }
+  DrawFileSystemList (FileSystemList);
 
-  CurrentFileSystemList = FileSystemList;
+  SetStatusText ("   ENTER = Continue   ESC = Cancel   F3 = Quit");
 
-  DrawFileSystemList(FileSystemList);
+  while (TRUE)
+    {
+      ConInKey (Ir);
 
-  SetStatusText("   ENTER = Continue   ESC = Cancel   F3 = Quit");
+      if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
+         (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
+       {
+         if (ConfirmQuit (Ir) == TRUE)
+           {
+             return QUIT_PAGE;
+           }
+         break;
+       }
+      else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
+              (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
+       {
+         return SELECT_PARTITION_PAGE;
+       }
+      else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
+              (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
+       {
+         ScrollDownFileSystemList (FileSystemList);
+       }
+      else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
+              (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
+       {
+         ScrollUpFileSystemList (FileSystemList);
+       }
+      else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
+       {
+         if (FileSystemList->CurrentFileSystem == FsKeep)
+           {
+             return CHECK_FILE_SYSTEM_PAGE;
+           }
+         else
+           {
+             return FORMAT_PARTITION_PAGE;
+           }
+       }
+    }
+
+  return SELECT_FILE_SYSTEM_PAGE;
+}
+
+
+static ULONG
+FormatPartitionPage (PINPUT_RECORD Ir)
+{
+  WCHAR PathBuffer[MAX_PATH];
+  PDISKENTRY DiskEntry;
+  PPARTENTRY PartEntry;
+  PLIST_ENTRY Entry;
+  NTSTATUS Status;
+
+//#ifndef NDEBUG
+  ULONG Line;
+  ULONG i;
+//#endif
+
+
+  SetTextXY(6, 8, "Format partition");
+
+  SetTextXY(6, 10, "Setup will now format the partition. Press ENTER to continue.");
+
+  SetStatusText("   ENTER = Continue   F3 = Quit");
+
+
+  if (PartitionList == NULL ||
+      PartitionList->CurrentDisk == NULL ||
+      PartitionList->CurrentPartition == NULL)
+    {
+      /* FIXME: show an error dialog */
+      return QUIT_PAGE;
+    }
+
+  DiskEntry = PartitionList->CurrentDisk;
+  PartEntry = PartitionList->CurrentPartition;
 
   while(TRUE)
     {
       ConInKey(Ir);
 
-      if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
-         (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
-       {
-         if (ConfirmQuit(Ir) == TRUE)
-           return(QUIT_PAGE);
-         break;
-       }
-      else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
-              (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
-       {
-    DestroyFileSystemList(FileSystemList);
-         return(SELECT_PARTITION_PAGE);
-       }
-      else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
-              (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
-       {
-         ScrollDownFileSystemList(FileSystemList);
-       }
-      else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
-              (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
-       {
-         ScrollUpFileSystemList(FileSystemList);
-       }
-      else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
-       {
-    if (FileSystemList->CurrentFileSystem == FsKeep)
-      {
-        return(CHECK_FILE_SYSTEM_PAGE);
-      }
-    else
-      {
-        return(FORMAT_PARTITION_PAGE);
-      }
-       }
-    }
-}
+      if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
+         (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
+       {
+         if (ConfirmQuit (Ir) == TRUE)
+           {
+             return QUIT_PAGE;
+           }
+         break;
+       }
+      else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
+       {
+         SetStatusText ("   Please wait ...");
+
+         if (PartEntry->PartInfo[0].PartitionType == PARTITION_ENTRY_UNUSED)
+           {
+             switch (FileSystemList->CurrentFileSystem)
+               {
+                 case FsFat:
+                   if (PartEntry->PartInfo[0].PartitionLength.QuadPart < (4200ULL * 1024ULL))
+                     {
+                       /* FAT12 CHS partition (disk is smaller than 4.1MB) */
+                       PartEntry->PartInfo[0].PartitionType = PARTITION_FAT_12;
+                     }
+                   else if (PartEntry->PartInfo[0].StartingOffset.QuadPart < (1024ULL * 255ULL * 63ULL * 512ULL))
+                     {
+                       /* Partition starts below the 8.4GB boundary ==> CHS partition */
+
+                       if (PartEntry->PartInfo[0].PartitionLength.QuadPart < (32ULL * 1024ULL * 1024ULL))
+                         {
+                           /* FAT16 CHS partition (partiton size < 32MB) */
+                           PartEntry->PartInfo[0].PartitionType = PARTITION_FAT_16;
+                         }
+                       else if (PartEntry->PartInfo[0].PartitionLength.QuadPart < (512ULL * 1024ULL * 1024ULL))
+                         {
+                           /* FAT16 CHS partition (partition size < 512MB) */
+                           PartEntry->PartInfo[0].PartitionType = PARTITION_HUGE;
+                         }
+                       else
+                         {
+                           /* FAT32 CHS partition (partition size >= 512MB) */
+                           PartEntry->PartInfo[0].PartitionType = PARTITION_FAT32;
+                         }
+                     }
+                   else
+                     {
+                       /* Partition starts above the 8.4GB boundary ==> LBA partition */
+
+                       if (PartEntry->PartInfo[0].PartitionLength.QuadPart < (512ULL * 1024ULL * 1024ULL))
+                         {
+                           /* FAT16 LBA partition (partition size < 512MB) */
+                           PartEntry->PartInfo[0].PartitionType = PARTITION_XINT13;
+                         }
+                       else
+                         {
+                           /* FAT32 LBA partition (partition size >= 512MB) */
+                           PartEntry->PartInfo[0].PartitionType = PARTITION_FAT32_XINT13;
+                         }
+                     }
+                   break;
+
+                 case FsKeep:
+                   break;
+
+                 default:
+                   return QUIT_PAGE;
+               }
+           }
+
+         CheckActiveBootPartition (PartitionList);
+
+//#ifndef NDEBUG
+         PrintTextXY (6, 12,
+                      "Disk: %I64u  Cylinder: %I64u  Track: %I64u",
+                      DiskEntry->DiskSize,
+                      DiskEntry->CylinderSize,
+                      DiskEntry->TrackSize);
+
+         Line = 13;
+         DiskEntry = PartitionList->CurrentDisk;
+         Entry = DiskEntry->PartListHead.Flink;
+         while (Entry != &DiskEntry->PartListHead)
+           {
+             PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
+
+             if (PartEntry->Unpartitioned == FALSE)
+               {
+
+                 for (i = 0; i < 4; i++)
+                   {
+                     PrintTextXY (6, Line,
+                                  "%2u:  %2u  %c  %12I64u  %12I64u  %2u  %c",
+                                  i,
+                                  PartEntry->PartInfo[i].PartitionNumber,
+                                  PartEntry->PartInfo[i].BootIndicator ? 'A' : '-',
+                                  PartEntry->PartInfo[i].StartingOffset.QuadPart,
+                                  PartEntry->PartInfo[i].PartitionLength.QuadPart,
+                                  PartEntry->PartInfo[i].PartitionType,
+                                  PartEntry->PartInfo[i].RewritePartition ? '*' : ' ');
+
+                     Line++;
+                   }
+
+                 Line++;
+               }
+
+             Entry = Entry->Flink;
+           }
+
+         /* Restore the old entry */
+         PartEntry = PartitionList->CurrentPartition;
+//#endif
+
+         if (WritePartitionsToDisk (PartitionList) == FALSE)
+           {
+             DPRINT ("WritePartitionsToDisk() failed\n");
+
+             PopupError ("Setup failed to write partition tables.\n",
+                         "ENTER = Reboot computer");
+
+             while (TRUE)
+               {
+                 ConInKey (Ir);
+
+                 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
+                   {
+                     return QUIT_PAGE;
+                   }
+               }
+           }
+
+
+         /* Set DestinationRootPath */
+         RtlFreeUnicodeString (&DestinationRootPath);
+         swprintf (PathBuffer,
+                   L"\\Device\\Harddisk%lu\\Partition%lu",
+                   PartitionList->CurrentDisk->DiskNumber,
+                   PartitionList->CurrentPartition->PartInfo[0].PartitionNumber);
+         RtlCreateUnicodeString (&DestinationRootPath,
+                                 PathBuffer);
+         DPRINT ("DestinationRootPath: %wZ\n", &DestinationRootPath);
 
-static ULONG
-FormatPartitionPage(PINPUT_RECORD Ir)
-{
-  NTSTATUS Status;
-  ULONG PartType;
-  BOOLEAN Valid;
 
-  SetTextXY(6, 8, "Format partition");
+         /* Set SystemRootPath */
+         RtlFreeUnicodeString (&SystemRootPath);
+         swprintf (PathBuffer,
+                   L"\\Device\\Harddisk%lu\\Partition%lu",
+                   PartitionList->ActiveBootDisk->DiskNumber,
+                   PartitionList->ActiveBootPartition->PartInfo[0].PartitionNumber);
+         RtlCreateUnicodeString (&SystemRootPath,
+                                 PathBuffer);
+         DPRINT ("SystemRootPath: %wZ\n", &SystemRootPath);
 
-  SetTextXY(6, 10, "Setup will now format the partition. Press ENTER to continue.");
 
-  SetStatusText("   ENTER = Continue   F3 = Quit");
+         switch (FileSystemList->CurrentFileSystem)
+           {
+             case FsFat:
+               Status = FormatPartition (&DestinationRootPath);
+               if (!NT_SUCCESS (Status))
+                 {
+                   DPRINT1 ("FormatPartition() failed with status 0x%.08x\n", Status);
+                   /* FIXME: show an error dialog */
+                   return QUIT_PAGE;
+                 }
 
-  while(TRUE)
-    {
-      ConInKey(Ir);
+               PartEntry->New = FALSE;
+               if (FileSystemList != NULL)
+                 {
+                   DestroyFileSystemList (FileSystemList);
+                   FileSystemList = NULL;
+                 }
 
-      if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
-         (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
-       {
-         if (ConfirmQuit(Ir) == TRUE)
-      {
-             return(QUIT_PAGE);
-      }
-         break;
-       }
-      else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
-       {
-    SetStatusText("   Please wait ...");
+               CheckActiveBootPartition (PartitionList);
 
-    switch (CurrentFileSystemList->CurrentFileSystem)
-      {
-#ifdef ENABLE_FORMAT
-        case FsFat:
-          PartType = PARTITION_FAT32_XINT13;
-          break;
-#endif
-        case FsKeep:
-          break;
-        default:
-          return QUIT_PAGE;
-      }
+               /* FIXME: Install boot code. This is a hack! */
+               if ((PartEntry->PartInfo[0].PartitionType == PARTITION_FAT32_XINT13) ||
+                   (PartEntry->PartInfo[0].PartitionType == PARTITION_FAT32))
+                 {
+                   wcscpy (PathBuffer, SourceRootPath.Buffer);
+                   wcscat (PathBuffer, L"\\loader\\fat32.bin");
+
+                   DPRINT1 ("Install FAT32 bootcode: %S ==> %S\n", PathBuffer,
+                            DestinationRootPath.Buffer);
+                   Status = InstallFat32BootCodeToDisk (PathBuffer,
+                                                        DestinationRootPath.Buffer);
+                   if (!NT_SUCCESS (Status))
+                     {
+                       DPRINT1 ("InstallFat32BootCodeToDisk() failed with status 0x%.08x\n", Status);
+                       /* FIXME: show an error dialog */
+                       return QUIT_PAGE;
+                     }
+                 }
+               else
+                 {
+                   wcscpy (PathBuffer, SourceRootPath.Buffer);
+                   wcscat (PathBuffer, L"\\loader\\fat.bin");
+
+                   DPRINT1 ("Install FAT bootcode: %S ==> %S\n", PathBuffer,
+                            DestinationRootPath.Buffer);
+                   Status = InstallFat16BootCodeToDisk (PathBuffer,
+                                                        DestinationRootPath.Buffer);
+                   if (!NT_SUCCESS (Status))
+                     {
+                       DPRINT1 ("InstallFat16BootCodeToDisk() failed with status 0x%.08x\n", Status);
+                       /* FIXME: show an error dialog */
+                       return QUIT_PAGE;
+                     }
+                 }
+               break;
 
-    if (PartData.CreatePartition)
-      {
-         Valid = CreateSelectedPartition(CurrentPartitionList, PartType, PartData.NewPartSize);
-        if (!Valid)
-          {
-            DPRINT("CreateSelectedPartition() failed\n");
-            /* FIXME: show an error dialog */
-            return(QUIT_PAGE);
-          }
-      }
+             case FsKeep:
+               break;
 
-    switch (CurrentFileSystemList->CurrentFileSystem)
-      {
-#ifdef ENABLE_FORMAT
-        case FsFat:
-          Status = FormatPartition(&DestinationRootPath);
-          if (!NT_SUCCESS(Status))
-            {
-              DPRINT1("FormatPartition() failed with status 0x%.08x\n", Status);
-              /* FIXME: show an error dialog */
-              return(QUIT_PAGE);
-            }
-          break;
-#endif
-        case FsKeep:
-          break;
-        default:
-          return QUIT_PAGE;
-      }
-    return(INSTALL_DIRECTORY_PAGE);
+             default:
+               return QUIT_PAGE;
+           }
+
+         SetStatusText ("   Done.  Press any key ...");
+         ConInKey(Ir);
+
+         return INSTALL_DIRECTORY_PAGE;
        }
     }
 
-  return(INSTALL_DIRECTORY_PAGE);
+  return FORMAT_PARTITION_PAGE;
 }
 
+
 static ULONG
 CheckFileSystemPage(PINPUT_RECORD Ir)
 {
+  WCHAR PathBuffer[MAX_PATH];
+
   SetTextXY(6, 8, "Check file system");
 
   SetTextXY(6, 10, "At present, ReactOS can not check file systems.");
@@ -1446,6 +1807,28 @@ CheckFileSystemPage(PINPUT_RECORD Ir)
 
   SetStatusText("   ENTER = Continue   F3 = Quit");
 
+
+  /* Set DestinationRootPath */
+  RtlFreeUnicodeString (&DestinationRootPath);
+  swprintf (PathBuffer,
+           L"\\Device\\Harddisk%lu\\Partition%lu",
+           PartitionList->CurrentDisk->DiskNumber,
+           PartitionList->CurrentPartition->PartInfo[0].PartitionNumber);
+  RtlCreateUnicodeString (&DestinationRootPath,
+                         PathBuffer);
+  DPRINT ("DestinationRootPath: %wZ\n", &DestinationRootPath);
+
+  /* Set SystemRootPath */
+  RtlFreeUnicodeString (&SystemRootPath);
+  swprintf (PathBuffer,
+           L"\\Device\\Harddisk%lu\\Partition%lu",
+           PartitionList->ActiveBootDisk->DiskNumber,
+           PartitionList->ActiveBootPartition->PartInfo[0].PartitionNumber);
+  RtlCreateUnicodeString (&SystemRootPath,
+                         PathBuffer);
+  DPRINT ("SystemRootPath: %wZ\n", &SystemRootPath);
+
+
   while(TRUE)
     {
       ConInKey(Ir);
@@ -1470,6 +1853,8 @@ CheckFileSystemPage(PINPUT_RECORD Ir)
 static PAGE_NUMBER
 InstallDirectoryPage(PINPUT_RECORD Ir)
 {
+  PDISKENTRY DiskEntry;
+  PPARTENTRY PartEntry;
   WCHAR PathBuffer[MAX_PATH];
   WCHAR InstallDir[51];
   PWCHAR DefaultPath;
@@ -1477,6 +1862,17 @@ InstallDirectoryPage(PINPUT_RECORD Ir)
   ULONG Length;
   NTSTATUS Status;
 
+  if (PartitionList == NULL ||
+      PartitionList->CurrentDisk == NULL ||
+      PartitionList->CurrentPartition == NULL)
+    {
+      /* FIXME: show an error dialog */
+      return QUIT_PAGE;
+    }
+
+  DiskEntry = PartitionList->CurrentDisk;
+  PartEntry = PartitionList->CurrentPartition;
+
   /* Search for 'DefaultPath' in the 'SetupData' section */
   if (!InfFindFirstLine (SetupInf, L"SetupData", L"DefaultPath", &Context))
     {
@@ -1484,13 +1880,13 @@ InstallDirectoryPage(PINPUT_RECORD Ir)
                 "in TXTSETUP.SIF.\n",
                 "ENTER = Reboot computer");
 
-      while(TRUE)
+      while (TRUE)
        {
-         ConInKey(Ir);
+         ConInKey (Ir);
 
          if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)       /* ENTER */
            {
-             return(QUIT_PAGE);
+             return QUIT_PAGE;
            }
        }
     }
@@ -1550,8 +1946,8 @@ InstallDirectoryPage(PINPUT_RECORD Ir)
          RtlFreeUnicodeString(&DestinationArcPath);
          swprintf(PathBuffer,
                   L"multi(0)disk(0)rdisk(%lu)partition(%lu)",
-                  PartData.DiskNumber,
-                  PartData.PartNumber);
+                  DiskEntry->DiskNumber,
+                  PartEntry->PartInfo[0].PartitionNumber);
          if (InstallDir[0] != L'\\')
            wcscat(PathBuffer,
                   L"\\");
@@ -1586,8 +1982,8 @@ InstallDirectoryPage(PINPUT_RECORD Ir)
 }
 
 
-static PAGE_NUMBER
-PrepareCopyPage(PINPUT_RECORD Ir)
+static BOOLEAN
+PrepareCopyPageInfFile(HINF InfFile, PWCHAR SourceCabinet, PINPUT_RECORD Ir)
 {
   WCHAR PathBuffer[MAX_PATH];
   INFCONTEXT FilesContext;
@@ -1596,53 +1992,16 @@ PrepareCopyPage(PINPUT_RECORD Ir)
   PWCHAR KeyValue;
   ULONG Length;
   NTSTATUS Status;
-
   PWCHAR FileKeyName;
   PWCHAR FileKeyValue;
   PWCHAR DirKeyName;
   PWCHAR DirKeyValue;
 
-  SetTextXY(6, 8, "Setup prepares your computer for copying the ReactOS files. ");
-
-
-//  SetTextXY(8, 12, "Build file copy list");
-
-//  SetTextXY(8, 14, "Create directories");
-
-//  SetStatusText("   Please wait...");
-
-  /*
-   * Build the file copy list
-   */
-  SetStatusText("   Building the file copy list...");
-//  SetInvertedTextXY(8, 12, "Build file copy list");
-
-
-
   /* Search for the 'SourceFiles' section */
-  if (!InfFindFirstLine (SetupInf, L"SourceFiles", NULL, &FilesContext))
+  if (!InfFindFirstLine (InfFile, L"SourceFiles", NULL, &FilesContext))
     {
       PopupError("Setup failed to find the 'SourceFiles' section\n"
-                "in TXTSETUP.SIF.\n",
-                "ENTER = Reboot computer");
-
-      while(TRUE)
-       {
-         ConInKey(Ir);
-
-         if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)       /* ENTER */
-           {
-             return(QUIT_PAGE);
-           }
-       }
-    }
-
-
-  /* Create the file queue */
-  SetupFileQueue = SetupOpenFileQueue();
-  if (SetupFileQueue == NULL)
-    {
-      PopupError("Setup failed to open the copy file queue.\n",
+                "in TXTSETUP.SIF.\n",  // FIXME
                 "ENTER = Reboot computer");
 
       while(TRUE)
@@ -1651,7 +2010,7 @@ PrepareCopyPage(PINPUT_RECORD Ir)
 
          if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)       /* ENTER */
            {
-             return(QUIT_PAGE);
+             return(FALSE);
            }
        }
     }
@@ -1663,12 +2022,15 @@ PrepareCopyPage(PINPUT_RECORD Ir)
   do
     {
       if (!InfGetData (&FilesContext, &FileKeyName, &FileKeyValue))
-       break;
+        {
+          DPRINT("break\n");
+               break;
+        }
 
-      DPRINT1("FileKeyName: '%S'  FileKeyValue: '%S'\n", FileKeyName, FileKeyValue);
+      DPRINT ("FileKeyName: '%S'  FileKeyValue: '%S'\n", FileKeyName, FileKeyValue);
 
       /* Lookup target directory */
-      if (!InfFindFirstLine (SetupInf, L"Directories", FileKeyValue, &DirContext))
+      if (!InfFindFirstLine (InfFile, L"Directories", FileKeyValue, &DirContext))
        {
          /* FIXME: Handle error! */
          DPRINT1("InfFindFirstLine() failed\n");
@@ -1683,8 +2045,9 @@ PrepareCopyPage(PINPUT_RECORD Ir)
        }
 
       if (!SetupQueueCopy(SetupFileQueue,
+        SourceCabinet,
                          SourceRootPath.Buffer,
-                         L"\\install",
+                         L"\\reactos",
                          FileKeyName,
                          DirKeyValue,
                          NULL))
@@ -1697,7 +2060,6 @@ PrepareCopyPage(PINPUT_RECORD Ir)
 
 
   /* Create directories */
-  SetStatusText("   Creating directories...");
 
   /*
    * FIXME:
@@ -1728,18 +2090,25 @@ PrepareCopyPage(PINPUT_RECORD Ir)
 
          if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)       /* ENTER */
            {
-             return(QUIT_PAGE);
+             return(FALSE);
            }
        }
     }
 
 
   /* Search for the 'Directories' section */
-  if (!InfFindFirstLine(SetupInf, L"Directories", NULL, &DirContext))
+  if (!InfFindFirstLine(InfFile, L"Directories", NULL, &DirContext))
     {
-      PopupError("Setup failed to find the 'Directories' section\n"
-                "in TXTSETUP.SIF.\n",
-                "ENTER = Reboot computer");
+      if (SourceCabinet)
+        {
+          PopupError("Setup failed to find the 'Directories' section\n"
+                   "in the cabinet.\n", "ENTER = Reboot computer");
+        }
+      else
+        {
+          PopupError("Setup failed to find the 'Directories' section\n"
+                   "in TXTSETUP.SIF.\n", "ENTER = Reboot computer");
+        }
 
       while(TRUE)
        {
@@ -1747,7 +2116,7 @@ PrepareCopyPage(PINPUT_RECORD Ir)
 
          if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)       /* ENTER */
            {
-             return(QUIT_PAGE);
+             return(FALSE);
            }
        }
     }
@@ -1756,7 +2125,10 @@ PrepareCopyPage(PINPUT_RECORD Ir)
   do
     {
       if (!InfGetData (&DirContext, NULL, &KeyValue))
-       break;
+        {
+          DPRINT1("break\n");
+               break;
+        }
 
       if (KeyValue[0] == L'\\' && KeyValue[1] != 0)
        {
@@ -1789,7 +2161,7 @@ PrepareCopyPage(PINPUT_RECORD Ir)
 
                  if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)       /* ENTER */
                    {
-                     return(QUIT_PAGE);
+                     return(FALSE);
                    }
                }
            }
@@ -1797,6 +2169,159 @@ PrepareCopyPage(PINPUT_RECORD Ir)
     }
   while (InfFindNextLine (&DirContext, &DirContext));
 
+  return(TRUE);
+}
+
+
+static PAGE_NUMBER
+PrepareCopyPage(PINPUT_RECORD Ir)
+{
+  INT CabStatus;
+  HINF InfHandle;
+  WCHAR PathBuffer[MAX_PATH];
+  INFCONTEXT CabinetsContext;
+  ULONG InfFileSize;
+  PWCHAR KeyValue;
+  NTSTATUS Status;
+  ULONG ErrorLine;
+  PVOID InfFileData;
+
+  SetTextXY(6, 8, "Setup prepares your computer for copying the ReactOS files. ");
+
+
+  /*
+   * Build the file copy list
+   */
+  SetStatusText("   Building the file copy list...");
+
+  /* Create the file queue */
+  SetupFileQueue = SetupOpenFileQueue();
+  if (SetupFileQueue == NULL)
+    {
+      PopupError("Setup failed to open the copy file queue.\n",
+                "ENTER = Reboot computer");
+
+      while(TRUE)
+       {
+         ConInKey(Ir);
+
+         if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)       /* ENTER */
+           {
+             return(QUIT_PAGE);
+           }
+       }
+    }
+
+
+  if (!PrepareCopyPageInfFile(SetupInf, NULL, Ir))
+    {
+      return(QUIT_PAGE);
+    }
+
+
+  /* Search for the 'Cabinets' section */
+  if (!InfFindFirstLine (SetupInf, L"Cabinets", NULL, &CabinetsContext))
+    {
+      PopupError("Setup failed to find the 'Cabinets' section\n"
+                "in TXTSETUP.SIF.\n",
+                "ENTER = Reboot computer");
+
+      while(TRUE)
+       {
+         ConInKey(Ir);
+
+         if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)       /* ENTER */
+           {
+             return(QUIT_PAGE);
+           }
+       }
+    }
+
+
+  /*
+   * Enumerate the directory values in the 'Cabinets'
+   * section and parse their inf files.
+   */
+  do
+    {
+      if (!InfGetData (&CabinetsContext, NULL, &KeyValue))
+    break;
+
+         wcscpy(PathBuffer, SourcePath.Buffer);
+         wcscat(PathBuffer, L"\\");
+         wcscat(PathBuffer, KeyValue);
+
+    CabinetInitialize();
+    CabinetSetEventHandlers(NULL, NULL, NULL);
+    CabinetSetCabinetName(PathBuffer);
+
+    if (CabinetOpen() == CAB_STATUS_SUCCESS)
+      {
+        DPRINT("Cabinet %S\n", CabinetGetCabinetName());
+
+        InfFileData = CabinetGetCabinetReservedArea(&InfFileSize);
+        if (InfFileData == NULL)
+          {
+            PopupError("Cabinet has no setup script.\n",
+                   "ENTER = Reboot computer");
+
+            while(TRUE)
+               {
+                 ConInKey(Ir);
+            
+                 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)       /* ENTER */
+                   {
+                     return(QUIT_PAGE);
+                   }
+               }
+          }
+      }
+    else
+      {
+        DPRINT("Cannot open cabinet: %S.\n", CabinetGetCabinetName());
+
+        PopupError("Cabinet not found.\n", "ENTER = Reboot computer");
+  
+        while(TRUE)
+               {
+                 ConInKey(Ir);
+        
+                 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)       /* ENTER */
+                   {
+                     return(QUIT_PAGE);
+                   }
+               }
+      }
+
+    Status = InfOpenBufferedFile(&InfHandle,
+           InfFileData,
+      InfFileSize,
+           &ErrorLine);
+    if (!NT_SUCCESS(Status))
+      {
+        PopupError("Cabinet has no valid inf file.\n",
+                "ENTER = Reboot computer");
+  
+        while(TRUE)
+       {
+         ConInKey(Ir);
+  
+         if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)       /* ENTER */
+           {
+             return(QUIT_PAGE);
+           }
+       }
+      }
+
+      CabinetCleanup();
+
+      if (!PrepareCopyPageInfFile(InfHandle, KeyValue, Ir))
+        {
+          return(QUIT_PAGE);
+        }
+    }
+  while (InfFindNextLine (&CabinetsContext, &CabinetsContext));
+
   return(FILE_COPY_PAGE);
 }
 
@@ -2001,74 +2526,12 @@ BootLoaderPage(PINPUT_RECORD Ir)
   PINICACHE IniCache;
   PINICACHESECTION IniSection;
   NTSTATUS Status;
-  BOOLEAN InstallMBR = FALSE;
 
   SetTextXY(6, 8, "Installing the boot loader");
 
   SetStatusText("   Please wait...");
 
-  if (ActivePartitionValid == FALSE)
-    {
-      /* Mark the chosen partition as active since there is no active
-         partition now */
-     
-               if (!MarkPartitionActive(PartData.DiskNumber,
-                       PartData.PartNumber, &ActivePartition))
-               {
-                     PopupError("Setup could not mark the system partiton active\n",
-                                "ENTER = Reboot computer");
-               
-                     while(TRUE)
-                       {
-                         ConInKey(Ir);
-               
-                         if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)       /* ENTER */
-                           {
-                             return(QUIT_PAGE);
-                           }
-                       }
-               }
-        InstallMBR = TRUE;
-    }
-
-  if (InstallMBR)
-    {
-          WCHAR PathBuffer[MAX_PATH];
-             UNICODE_STRING SystemRootMBRPath;
-       
-                 RtlFreeUnicodeString(&SystemRootMBRPath);
-                 swprintf(PathBuffer,
-                          L"\\Device\\Harddisk%lu\\Partition0",
-                          PartData.DiskNumber);
-                 RtlCreateUnicodeString(&SystemRootMBRPath,
-                                        PathBuffer);
-
-                 /* Install MBR bootcode */
-                 wcscpy(SrcPath, SourceRootPath.Buffer);
-                 wcscat(SrcPath, L"\\loader\\dosmbr.bin");
-       
-                 DPRINT1("Install MBR bootcode: %S ==> %S\n", SrcPath, SystemRootMBRPath.Buffer);
-                 Status = InstallMBRBootCodeToDisk(SrcPath,
-                                                     SystemRootMBRPath.Buffer);
-                 if (!NT_SUCCESS(Status))
-                 {
-                   DPRINT1("InstallMBRBootCodeToDisk() failed (Status %lx)\n", Status);
-                   PopupError("Setup failed to install the MBR bootcode.",
-                              "ENTER = Reboot computer");
-       
-                   while(TRUE)
-                   {
-                     ConInKey(Ir);
-       
-                     if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)   /* ENTER */
-                     {
-                       return(QUIT_PAGE);
-                     }
-                   }
-                 }
-    }
-
-  if (ActivePartition.PartType == PARTITION_ENTRY_UNUSED)
+  if (PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_ENTRY_UNUSED)
     {
       DPRINT1("Error: active partition invalid (unused)\n");
       PopupError("The active partition is unused (invalid).\n",
@@ -2084,8 +2547,7 @@ BootLoaderPage(PINPUT_RECORD Ir)
            }
        }
     }
-
-  if (ActivePartition.PartType == 0x0A)
+  if (PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == 0x0A)
     {
       /* OS/2 boot manager partition */
       DPRINT1("Found OS/2 boot manager partition\n");
@@ -2103,7 +2565,7 @@ BootLoaderPage(PINPUT_RECORD Ir)
            }
        }
     }
-  else if (ActivePartition.PartType == 0x83)
+  else if (PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == 0x83)
     {
       /* Linux ext2 partition */
       DPRINT1("Found Linux ext2 partition\n");
@@ -2121,7 +2583,7 @@ BootLoaderPage(PINPUT_RECORD Ir)
            }
        }
     }
-  else if (ActivePartition.PartType == PARTITION_IFS)
+  else if (PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_IFS)
     {
       /* NTFS partition */
       DPRINT1("Found NTFS partition\n");
@@ -2139,12 +2601,12 @@ BootLoaderPage(PINPUT_RECORD Ir)
            }
        }
     }
-  else if ((ActivePartition.PartType == PARTITION_FAT_12) ||
-          (ActivePartition.PartType == PARTITION_FAT_16) ||
-          (ActivePartition.PartType == PARTITION_HUGE) ||
-          (ActivePartition.PartType == PARTITION_XINT13) ||
-          (ActivePartition.PartType == PARTITION_FAT32) ||
-          (ActivePartition.PartType == PARTITION_FAT32_XINT13))
+  else if ((PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_FAT_12) ||
+          (PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_FAT_16) ||
+          (PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_HUGE) ||
+          (PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_XINT13) ||
+          (PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_FAT32) ||
+          (PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_FAT32_XINT13))
   {
     /* FAT or FAT32 partition */
     DPRINT1("System path: '%wZ'\n", &SystemRootPath);
@@ -2208,8 +2670,8 @@ BootLoaderPage(PINPUT_RECORD Ir)
        }
 
        /* Install new bootcode */
-       if ((ActivePartition.PartType == PARTITION_FAT32) ||
-           (ActivePartition.PartType == PARTITION_FAT32_XINT13))
+       if ((PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_FAT32) ||
+           (PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_FAT32_XINT13))
        {
          /* Install FAT32 bootcode */
          wcscpy(SrcPath, SourceRootPath.Buffer);
@@ -2404,8 +2866,8 @@ BootLoaderPage(PINPUT_RECORD Ir)
        }
 
        /* Install new bootsector */
-       if ((ActivePartition.PartType == PARTITION_FAT32) ||
-           (ActivePartition.PartType == PARTITION_FAT32_XINT13))
+       if ((PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_FAT32) ||
+           (PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_FAT32_XINT13))
        {
          wcscpy(SrcPath, SourceRootPath.Buffer);
          wcscat(SrcPath, L"\\loader\\fat32.bin");
@@ -2565,8 +3027,8 @@ BootLoaderPage(PINPUT_RECORD Ir)
        }
 
        /* Install new bootsector */
-       if ((ActivePartition.PartType == PARTITION_FAT32) ||
-           (ActivePartition.PartType == PARTITION_FAT32_XINT13))
+       if ((PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_FAT32) ||
+           (PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_FAT32_XINT13))
        {
          wcscpy(SrcPath, SourceRootPath.Buffer);
          wcscat(SrcPath, L"\\loader\\fat32.bin");
@@ -2678,6 +3140,22 @@ QuitPage(PINPUT_RECORD Ir)
 
   SetTextXY(10, 11, "Press ENTER to reboot your computer.");
 
+  SetStatusText("   Please wait ...");
+
+  /* Destroy partition list */
+  if (PartitionList != NULL)
+    {
+      DestroyPartitionList (PartitionList);
+      PartitionList = NULL;
+    }
+
+  /* Destroy filesystem list */
+  if (FileSystemList != NULL)
+    {
+      DestroyFileSystemList (FileSystemList);
+      FileSystemList = NULL;
+    }
+
   SetStatusText("   ENTER = Reboot computer");
 
   while(TRUE)
@@ -2737,7 +3215,6 @@ NtProcessStartup(PPEB Peb)
                       0,0,0,0,0);
     }
 
-  PartDataValid = FALSE;
 
   /* Initialize global unicode strings */
   RtlInitUnicodeString(&SourcePath, NULL);
@@ -2791,6 +3268,10 @@ NtProcessStartup(PPEB Peb)
            Page = CreatePartitionPage(&Ir);
            break;
 
+         case DELETE_PARTITION_PAGE:
+           Page = DeletePartitionPage(&Ir);
+           break;
+
          case SELECT_FILE_SYSTEM_PAGE:
            Page = SelectFileSystemPage(&Ir);
            break;
@@ -2830,6 +3311,12 @@ NtProcessStartup(PPEB Peb)
            break;
 
 
+         /* Emergency pages */
+         case EMERGENCY_INTRO_PAGE:
+           Page = EmergencyIntroPage(&Ir);
+           break;
+
+
          case SUCCESS_PAGE:
            Page = SuccessPage(&Ir);
            break;