branch update for HEAD-2003021201
[reactos.git] / subsys / system / usetup / usetup.c
1 /*
2  *  ReactOS kernel
3  *  Copyright (C) 2002 ReactOS Team
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19 /*
20  * COPYRIGHT:       See COPYING in the top level directory
21  * PROJECT:         ReactOS text-mode setup
22  * FILE:            subsys/system/usetup/usetup.c
23  * PURPOSE:         Text-mode setup
24  * PROGRAMMER:      Eric Kohl
25  */
26
27 #include <ddk/ntddk.h>
28 #include <ntdll/rtl.h>
29
30 #include <ntos/minmax.h>
31 #include <reactos/resource.h>
32
33 #include "usetup.h"
34 #include "console.h"
35 #include "partlist.h"
36 #include "inicache.h"
37 #include "filequeue.h"
38 #include "progress.h"
39 #include "bootsup.h"
40
41
42 #define START_PAGE                      0
43 #define INTRO_PAGE                      1
44 #define INSTALL_INTRO_PAGE              2
45
46 #define SELECT_PARTITION_PAGE           4
47 #define SELECT_FILE_SYSTEM_PAGE         5
48 #define CHECK_FILE_SYSTEM_PAGE          6
49 #define PREPARE_COPY_PAGE               7
50 #define INSTALL_DIRECTORY_PAGE          8
51 #define FILE_COPY_PAGE                  9
52 #define REGISTRY_PAGE                   10
53 #define BOOT_LOADER_PAGE                11
54
55 #define REPAIR_INTRO_PAGE               20
56
57 #define SUCCESS_PAGE                    100
58 #define QUIT_PAGE                       101
59 #define REBOOT_PAGE                     102
60
61
62 typedef struct _COPYCONTEXT
63 {
64   ULONG TotalOperations;
65   ULONG CompletedOperations;
66   PPROGRESS ProgressBar;
67 } COPYCONTEXT, *PCOPYCONTEXT;
68
69
70 /* GLOBALS ******************************************************************/
71
72 HANDLE ProcessHeap;
73
74 BOOLEAN PartDataValid;
75 PARTDATA PartData;
76
77 BOOLEAN ActivePartitionValid;
78 PARTDATA ActivePartition;
79
80 UNICODE_STRING SourcePath;
81 UNICODE_STRING SourceRootPath;
82
83 UNICODE_STRING InstallPath;
84 UNICODE_STRING DestinationPath;
85 UNICODE_STRING DestinationArcPath;
86 UNICODE_STRING DestinationRootPath;
87
88 UNICODE_STRING SystemRootPath; /* Path to the active partition */
89
90 PINICACHE IniCache;
91
92 HSPFILEQ SetupFileQueue = NULL;
93
94
95 /* FUNCTIONS ****************************************************************/
96
97 static VOID
98 PrintString(char* fmt,...)
99 {
100   char buffer[512];
101   va_list ap;
102   UNICODE_STRING UnicodeString;
103   ANSI_STRING AnsiString;
104
105   va_start(ap, fmt);
106   vsprintf(buffer, fmt, ap);
107   va_end(ap);
108
109   RtlInitAnsiString(&AnsiString, buffer);
110   RtlAnsiStringToUnicodeString(&UnicodeString,
111                                &AnsiString,
112                                TRUE);
113   NtDisplayString(&UnicodeString);
114   RtlFreeUnicodeString(&UnicodeString);
115 }
116
117
118 static VOID
119 PopupError(PCHAR Text,
120            PCHAR Status)
121 {
122   SHORT xScreen;
123   SHORT yScreen;
124   SHORT yTop;
125   SHORT xLeft;
126   COORD coPos;
127   ULONG Written;
128   ULONG Length;
129   ULONG MaxLength;
130   ULONG Lines;
131   PCHAR p;
132   PCHAR pnext;
133   BOOLEAN LastLine;
134   SHORT Width;
135   SHORT Height;
136
137   /* Count text lines and longest line */
138   MaxLength = 0;
139   Lines = 0;
140   pnext = Text;
141   while (TRUE)
142   {
143     p = strchr(pnext, '\n');
144     if (p == NULL)
145     {
146       Length = strlen(pnext);
147       LastLine = TRUE;
148     }
149     else
150     {
151       Length = (ULONG)(p - pnext);
152       LastLine = FALSE;
153     }
154
155     Lines++;
156     if (Length > MaxLength)
157       MaxLength = Length;
158
159     if (LastLine == TRUE)
160       break;
161
162     pnext = p + 1;
163   }
164
165   /* Check length of status line */
166   if (Status != NULL)
167   {
168     Length = strlen(Status);
169     if (Length > MaxLength)
170       MaxLength = Length;
171   }
172
173   GetScreenSize(&xScreen, &yScreen);
174
175   Width = MaxLength + 4;
176   Height = Lines + 2;
177   if (Status != NULL)
178     Height += 2;
179
180   yTop = (yScreen - Height) / 2;
181   xLeft = (xScreen - Width) / 2;
182
183
184   /* Set screen attributes */
185   coPos.X = xLeft;
186   for (coPos.Y = yTop; coPos.Y < yTop + Height; coPos.Y++)
187   {
188     FillConsoleOutputAttribute(0x74,
189                                Width,
190                                coPos,
191                                &Written);
192   }
193
194   /* draw upper left corner */
195   coPos.X = xLeft;
196   coPos.Y = yTop;
197   FillConsoleOutputCharacter(0xDA, // '+',
198                              1,
199                              coPos,
200                              &Written);
201
202   /* draw upper edge */
203   coPos.X = xLeft + 1;
204   coPos.Y = yTop;
205   FillConsoleOutputCharacter(0xC4, // '-',
206                              Width - 2,
207                              coPos,
208                              &Written);
209
210   /* draw upper right corner */
211   coPos.X = xLeft + Width - 1;
212   coPos.Y = yTop;
213   FillConsoleOutputCharacter(0xBF, // '+',
214                              1,
215                              coPos,
216                              &Written);
217
218   /* Draw right edge, inner space and left edge */
219   for (coPos.Y = yTop + 1; coPos.Y < yTop + Height - 1; coPos.Y++)
220   {
221     coPos.X = xLeft;
222     FillConsoleOutputCharacter(0xB3, // '|',
223                                1,
224                                coPos,
225                                &Written);
226
227     coPos.X = xLeft + 1;
228     FillConsoleOutputCharacter(' ',
229                                Width - 2,
230                                coPos,
231                                &Written);
232
233     coPos.X = xLeft + Width - 1;
234     FillConsoleOutputCharacter(0xB3, // '|',
235                                1,
236                                coPos,
237                                &Written);
238   }
239
240   /* draw lower left corner */
241   coPos.X = xLeft;
242   coPos.Y = yTop + Height - 1;
243   FillConsoleOutputCharacter(0xC0, // '+',
244                              1,
245                              coPos,
246                              &Written);
247
248   /* draw lower edge */
249   coPos.X = xLeft + 1;
250   coPos.Y = yTop + Height - 1;
251   FillConsoleOutputCharacter(0xC4, // '-',
252                              Width - 2,
253                              coPos,
254                              &Written);
255
256   /* draw lower right corner */
257   coPos.X = xLeft + Width - 1;
258   coPos.Y = yTop + Height - 1;
259   FillConsoleOutputCharacter(0xD9, // '+',
260                              1,
261                              coPos,
262                              &Written);
263
264   /* Print message text */
265   coPos.Y = yTop + 1;
266   pnext = Text;
267   while (TRUE)
268   {
269     p = strchr(pnext, '\n');
270     if (p == NULL)
271     {
272       Length = strlen(pnext);
273       LastLine = TRUE;
274     }
275     else
276     {
277       Length = (ULONG)(p - pnext);
278       LastLine = FALSE;
279     }
280
281     if (Length != 0)
282     {
283       coPos.X = xLeft + 2;
284       WriteConsoleOutputCharacters(pnext,
285                                    Length,
286                                    coPos);
287     }
288
289     if (LastLine == TRUE)
290       break;
291
292     coPos.Y++;
293     pnext = p + 1;
294   }
295
296   /* Print separator line and status text */
297   if (Status != NULL)
298   {
299     coPos.Y = yTop + Height - 3;
300     coPos.X = xLeft;
301     FillConsoleOutputCharacter(0xC3, // '+',
302                                1,
303                                coPos,
304                                &Written);
305
306     coPos.X = xLeft + 1;
307     FillConsoleOutputCharacter(0xC4, // '-',
308                                Width - 2,
309                                coPos,
310                                &Written);
311
312     coPos.X = xLeft + Width - 1;
313     FillConsoleOutputCharacter(0xB4, // '+',
314                                1,
315                                coPos,
316                                &Written);
317
318     coPos.Y++;
319     coPos.X = xLeft + 2;
320     WriteConsoleOutputCharacters(Status,
321                                  min(strlen(Status), Width - 4),
322                                  coPos);
323   }
324 }
325
326
327 /*
328  * Confirm quit setup
329  * RETURNS
330  *      TRUE: Quit setup.
331  *      FALSE: Don't quit setup.
332  */
333 static BOOL
334 ConfirmQuit(PINPUT_RECORD Ir)
335 {
336   BOOL Result = FALSE;
337
338   PopupError("ReactOS is not completely installed on your\n"
339              "computer. If you quit Setup now, you will need to\n"
340              "run Setup again to install ReactOS.\n"
341              "\n"
342              "  * Press ENTER to continue Setup.\n"
343              "  * Press F3 to quit Setup.",
344              "F3= Quit  ENTER = Continue");
345
346   while(TRUE)
347     {
348       ConInKey(Ir);
349
350       if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
351           (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3))        /* F3 */
352         {
353           Result = TRUE;
354           break;
355         }
356       else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)      /* ENTER */
357         {
358           Result = FALSE;
359           break;
360         }
361     }
362
363   return(Result);
364 }
365
366
367
368 /*
369  * Start page
370  * RETURNS
371  *      Number of the next page.
372  */
373 static ULONG
374 StartPage(PINPUT_RECORD Ir)
375 {
376   NTSTATUS Status;
377   WCHAR FileNameBuffer[MAX_PATH];
378   UNICODE_STRING FileName;
379
380   PINICACHESECTION Section;
381   PWCHAR Value;
382
383
384   SetStatusText("   Please wait...");
385
386   Status = GetSourcePaths(&SourcePath,
387                           &SourceRootPath);
388   if (!NT_SUCCESS(Status))
389     {
390       PrintTextXY(6, 15, "GetSourcePath() failed (Status 0x%08lx)", Status);
391     }
392   else
393     {
394       PrintTextXY(6, 15, "SourcePath: '%wZ'", &SourcePath);
395       PrintTextXY(6, 16, "SourceRootPath: '%wZ'", &SourceRootPath);
396     }
397
398
399   /* Load txtsetup.sif from install media. */
400   wcscpy(FileNameBuffer, SourceRootPath.Buffer);
401   wcscat(FileNameBuffer, L"\\install\\txtsetup.sif");
402   RtlInitUnicodeString(&FileName,
403                        FileNameBuffer);
404
405   IniCache = NULL;
406   Status = IniCacheLoad(&IniCache,
407                         &FileName,
408                         TRUE);
409   if (!NT_SUCCESS(Status))
410     {
411       PopupError("Setup failed to load the file TXTSETUP.SIF.\n",
412                  "ENTER = Reboot computer");
413
414       while(TRUE)
415         {
416           ConInKey(Ir);
417
418           if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)       /* ENTER */
419             {
420               return(QUIT_PAGE);
421             }
422         }
423     }
424
425   /* Open 'Version' section */
426   Section = IniCacheGetSection(IniCache,
427                                L"Version");
428   if (Section == NULL)
429     {
430       PopupError("Setup found a corrupt TXTSETUP.SIF.\n",
431                  "ENTER = Reboot computer");
432
433       while(TRUE)
434         {
435           ConInKey(Ir);
436
437           if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)       /* ENTER */
438             {
439               return(QUIT_PAGE);
440             }
441         }
442     }
443
444
445   /* Get pointer 'Signature' key */
446   Status = IniCacheGetKey(Section,
447                           L"Signature",
448                           &Value);
449   if (!NT_SUCCESS(Status))
450     {
451       PopupError("Setup found a corrupt TXTSETUP.SIF.\n",
452                  "ENTER = Reboot computer");
453
454       while(TRUE)
455         {
456           ConInKey(Ir);
457
458           if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)       /* ENTER */
459             {
460               return(QUIT_PAGE);
461             }
462         }
463     }
464
465   /* Check 'Signature' string */
466   if (_wcsicmp(Value, L"$ReactOS$") != 0)
467     {
468       PopupError("Setup found an invalid signature in TXTSETUP.SIF.\n",
469                  "ENTER = Reboot computer");
470
471       while(TRUE)
472         {
473           ConInKey(Ir);
474
475           if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)       /* ENTER */
476             {
477               return(QUIT_PAGE);
478             }
479         }
480     }
481
482   return(INTRO_PAGE);
483 }
484
485
486
487 static ULONG
488 RepairIntroPage(PINPUT_RECORD Ir)
489 {
490   SetTextXY(6, 8, "ReactOS Setup is in an early development phase. It does not yet");
491   SetTextXY(6, 9, "support all the functions of a fully usable setup application.");
492
493   SetTextXY(6, 12, "The repair functions are not implemented yet.");
494
495   SetTextXY(8, 15, "\xfa  Press ESC to return to the main page.");
496
497   SetTextXY(8, 17, "\xfa  Press ENTER to reboot your computer.");
498
499   SetStatusText("   ESC = Main page  ENTER = Reboot");
500
501   while(TRUE)
502     {
503       ConInKey(Ir);
504
505       if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
506         {
507           return(REBOOT_PAGE);
508         }
509       else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
510                (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
511         {
512           return(INTRO_PAGE);
513         }
514     }
515
516   return(REPAIR_INTRO_PAGE);
517 }
518
519
520 /*
521  * First setup page
522  * RETURNS
523  *      TRUE: setup/repair completed successfully
524  *      FALSE: setup/repair terminated by user
525  */
526 static ULONG
527 IntroPage(PINPUT_RECORD Ir)
528 {
529   SetHighlightedTextXY(6, 8, "Welcome to ReactOS Setup");
530
531   SetTextXY(6, 11, "This part of the setup copies the ReactOS Operating System to your");
532   SetTextXY(6, 12, "computer and prepares the second part of the setup.");
533
534   SetTextXY(8, 15, "\xfa  Press ENTER to install ReactOS.");
535
536   SetTextXY(8, 17, "\xfa  Press E to start the emergency repair console.");
537
538   SetTextXY(8, 19, "\xfa  Press R to repair ReactOS.");
539
540   SetTextXY(8, 21, "\xfa  Press F3 to quit without installing ReactOS.");
541
542
543   SetStatusText("   ENTER = Continue   F3 = Quit");
544
545   while(TRUE)
546     {
547       ConInKey(Ir);
548
549       if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
550           (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
551         {
552           if (ConfirmQuit(Ir) == TRUE)
553             return(QUIT_PAGE);
554           break;
555         }
556       else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
557         {
558           return(INSTALL_INTRO_PAGE);
559         }
560 #if 0
561       else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'E') /* E */
562         {
563           return(RepairConsole());
564         }
565 #endif
566       else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'R') /* R */
567         {
568           return(REPAIR_INTRO_PAGE);
569         }
570     }
571
572   return(INTRO_PAGE);
573 }
574
575
576 static ULONG
577 InstallIntroPage(PINPUT_RECORD Ir)
578 {
579   SetTextXY(6, 8, "ReactOS Setup is in an early development phase. It does not yet");
580   SetTextXY(6, 9, "support all the functions of a fully usable setup application.");
581
582   SetTextXY(6, 12, "The following functions are missing:");
583   SetTextXY(8, 13, "- Creating and deleting harddisk partitions.");
584   SetTextXY(8, 14, "- Formatting partitions.");
585   SetTextXY(8, 15, "- Support for non-FAT file systems.");
586   SetTextXY(8, 16, "- Checking file systems.");
587
588
589
590   SetTextXY(8, 21, "\xfa  Press ENTER to install ReactOS.");
591
592   SetTextXY(8, 23, "\xfa  Press F3 to quit without installing ReactOS.");
593
594
595   SetStatusText("   ENTER = Continue   F3 = Quit");
596
597   while(TRUE)
598     {
599       ConInKey(Ir);
600
601       if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
602           (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
603         {
604           if (ConfirmQuit(Ir) == TRUE)
605             return(QUIT_PAGE);
606           break;
607         }
608       else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
609         {
610           return(SELECT_PARTITION_PAGE);
611         }
612     }
613
614   return(INSTALL_INTRO_PAGE);
615 }
616
617
618 static ULONG
619 SelectPartitionPage(PINPUT_RECORD Ir)
620 {
621   WCHAR PathBuffer[MAX_PATH];
622   PPARTLIST PartList;
623   SHORT xScreen;
624   SHORT yScreen;
625
626   SetTextXY(6, 8, "The list below shows existing partitions and unused disk");
627   SetTextXY(6, 9, "space for new partitions.");
628
629   SetTextXY(8, 11, "\xfa  Press UP or DOWN to select a list entry.");
630   SetTextXY(8, 13, "\xfa  Press ENTER to install ReactOS onto the selected partition.");
631   SetTextXY(8, 15, "\xfa  Press C to create a new partition.");
632   SetTextXY(8, 17, "\xfa  Press D to delete an existing partition.");
633
634   SetStatusText("   Please wait...");
635
636   RtlFreeUnicodeString(&DestinationPath);
637   RtlFreeUnicodeString(&DestinationRootPath);
638
639   GetScreenSize(&xScreen, &yScreen);
640
641   PartList = CreatePartitionList(2, 19, xScreen - 3, yScreen - 3);
642   if (PartList == NULL)
643     {
644       /* FIXME: show an error dialog */
645       return(QUIT_PAGE);
646     }
647
648   SetStatusText("   ENTER = Continue   F3 = Quit");
649
650   while(TRUE)
651     {
652       ConInKey(Ir);
653
654       if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
655           (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
656         {
657           if (ConfirmQuit(Ir) == TRUE)
658             {
659               DestroyPartitionList(PartList);
660               return(QUIT_PAGE);
661             }
662           break;
663         }
664       else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
665                (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
666         {
667           ScrollDownPartitionList(PartList);
668         }
669       else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
670                (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
671         {
672           ScrollUpPartitionList(PartList);
673         }
674       else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
675         {
676           PartDataValid = GetSelectedPartition(PartList,
677                                                &PartData);
678           ActivePartitionValid = GetActiveBootPartition(PartList,
679                                                         &ActivePartition);
680           DestroyPartitionList(PartList);
681
682           RtlFreeUnicodeString(&DestinationRootPath);
683           swprintf(PathBuffer,
684                    L"\\Device\\Harddisk%lu\\Partition%lu",
685                    PartData.DiskNumber,
686                    PartData.PartNumber);
687           RtlCreateUnicodeString(&DestinationRootPath,
688                                  PathBuffer);
689
690           RtlFreeUnicodeString(&SystemRootPath);
691           swprintf(PathBuffer,
692                    L"\\Device\\Harddisk%lu\\Partition%lu",
693                    ActivePartition.DiskNumber,
694                    ActivePartition.PartNumber);
695           RtlCreateUnicodeString(&SystemRootPath,
696                                  PathBuffer);
697
698           return(SELECT_FILE_SYSTEM_PAGE);
699         }
700
701       /* FIXME: Update status text */
702
703     }
704
705   DestroyPartitionList(PartList);
706
707   return(SELECT_PARTITION_PAGE);
708 }
709
710
711 static ULONG
712 SelectFileSystemPage(PINPUT_RECORD Ir)
713 {
714   ULONGLONG DiskSize;
715   ULONGLONG PartSize;
716   PCHAR DiskUnit;
717   PCHAR PartUnit;
718   PCHAR PartType;
719
720   if (PartDataValid == FALSE)
721     {
722       /* FIXME: show an error dialog */
723       return(QUIT_PAGE);
724     }
725
726   /* adjust disk size */
727   if (PartData.DiskSize >= 0x280000000ULL) /* 10 GB */
728     {
729       DiskSize = (PartData.DiskSize + (1 << 29)) >> 30;
730       DiskUnit = "GB";
731     }
732   else
733     {
734       DiskSize = (PartData.DiskSize + (1 << 19)) >> 20;
735       DiskUnit = "MB";
736     }
737
738   /* adjust partition size */
739   if (PartData.PartSize >= 0x280000000ULL) /* 10 GB */
740     {
741       PartSize = (PartData.PartSize + (1 << 29)) >> 30;
742       PartUnit = "GB";
743     }
744   else
745     {
746       PartSize = (PartData.PartSize + (1 << 19)) >> 20;
747       PartUnit = "MB";
748     }
749
750   /* adjust partition type */
751   if ((PartData.PartType == PARTITION_FAT_12) ||
752       (PartData.PartType == PARTITION_FAT_16) ||
753       (PartData.PartType == PARTITION_HUGE) ||
754       (PartData.PartType == PARTITION_XINT13))
755     {
756       PartType = "FAT";
757     }
758   else if ((PartData.PartType == PARTITION_FAT32) ||
759            (PartData.PartType == PARTITION_FAT32_XINT13))
760     {
761       PartType = "FAT32";
762     }
763   else if (PartData.PartType == PARTITION_IFS)
764     {
765       PartType = "NTFS"; /* FIXME: Not quite correct! */
766     }
767   else
768     {
769       PartType = "Unknown";
770     }
771
772   SetTextXY(6, 8, "Setup will install ReactOS on");
773
774   PrintTextXY(8, 10, "Partition %lu (%I64u %s) %s on",
775               PartData.PartNumber,
776               PartSize,
777               PartUnit,
778               PartType);
779
780   PrintTextXY(8, 12, "Harddisk %lu (%I64u %s), Port=%hu, Bus=%hu, Id=%hu (%wZ).",
781               PartData.DiskNumber,
782               DiskSize,
783               DiskUnit,
784               PartData.Port,
785               PartData.Bus,
786               PartData.Id,
787               &PartData.DriverName);
788
789
790   SetTextXY(6, 17, "Select a file system for the partition from the list below.");
791
792   SetTextXY(8, 19, "\xfa  Press UP or DOWN to select a file system.");
793   SetTextXY(8, 21, "\xfa  Press ENTER to format the partition.");
794   SetTextXY(8, 23, "\xfa  Press ESC to select another partition.");
795
796   /* FIXME: use a real list later */
797   SetInvertedTextXY(6, 26, " Keep current file system (no changes) ");
798
799
800   SetStatusText("   ENTER = Continue   ESC = Cancel   F3 = Quit");
801
802   while(TRUE)
803     {
804       ConInKey(Ir);
805
806       if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
807           (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
808         {
809           if (ConfirmQuit(Ir) == TRUE)
810             return(QUIT_PAGE);
811           break;
812         }
813       else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
814                (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
815         {
816           return(SELECT_PARTITION_PAGE);
817         }
818       else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
819         {
820           return(CHECK_FILE_SYSTEM_PAGE);
821         }
822     }
823
824   return(SELECT_FILE_SYSTEM_PAGE);
825 }
826
827
828 static ULONG
829 CheckFileSystemPage(PINPUT_RECORD Ir)
830 {
831   SetTextXY(6, 8, "Check file system");
832
833   SetTextXY(6, 10, "At present, ReactOS can not check file systems.");
834
835   SetStatusText("   Please wait ...");
836
837
838   SetStatusText("   ENTER = Continue   F3 = Quit");
839
840   while(TRUE)
841     {
842       ConInKey(Ir);
843
844       if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
845           (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
846         {
847           if (ConfirmQuit(Ir) == TRUE)
848             return(QUIT_PAGE);
849           break;
850         }
851       else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
852         {
853           return(INSTALL_DIRECTORY_PAGE);
854         }
855     }
856
857   return(CHECK_FILE_SYSTEM_PAGE);
858 }
859
860
861 static ULONG
862 InstallDirectoryPage(PINPUT_RECORD Ir)
863 {
864   PINICACHESECTION Section;
865   WCHAR PathBuffer[MAX_PATH];
866   WCHAR InstallDir[51];
867   PWCHAR DefaultPath;
868   ULONG Length;
869   NTSTATUS Status;
870
871   /* Open 'SetupData' section */
872   Section = IniCacheGetSection(IniCache,
873                                L"SetupData");
874   if (Section == NULL)
875     {
876       PopupError("Setup failed to find the 'SetupData' section\n"
877                  "in TXTSETUP.SIF.\n",
878                  "ENTER = Reboot computer");
879
880       while(TRUE)
881         {
882           ConInKey(Ir);
883
884           if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)       /* ENTER */
885             {
886               return(QUIT_PAGE);
887             }
888         }
889     }
890
891   /* Read the 'DefaultPath' key */
892   Status = IniCacheGetKey(Section,
893                           L"DefaultPath",
894                           &DefaultPath);
895   if (!NT_SUCCESS(Status))
896     {
897       wcscpy(InstallDir, L"\\reactos");
898     }
899   else
900     {
901       wcscpy(InstallDir, DefaultPath);
902     }
903   Length = wcslen(InstallDir);
904
905   SetTextXY(6, 8, "Setup installs ReactOS files onto the selected partition. Choose a");
906   SetTextXY(6, 9, "directory where you want ReactOS to be installed:");
907
908   SetInputTextXY(8, 11, 51, InstallDir);
909
910   SetTextXY(6, 14, "To change the suggested directory, press BACKSPACE to delete");
911   SetTextXY(6, 15, "characters and then type the directory where you want ReactOS to");
912   SetTextXY(6, 16, "be installed.");
913
914   SetStatusText("   ENTER = Continue   F3 = Quit");
915
916   while(TRUE)
917     {
918       ConInKey(Ir);
919
920       if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
921           (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
922         {
923           if (ConfirmQuit(Ir) == TRUE)
924             return(QUIT_PAGE);
925           break;
926         }
927       else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
928         {
929           /* Create 'InstallPath' string */
930           RtlFreeUnicodeString(&InstallPath);
931           RtlCreateUnicodeString(&InstallPath,
932                                  InstallDir);
933
934           /* Create 'DestinationPath' string */
935           RtlFreeUnicodeString(&DestinationPath);
936           wcscpy(PathBuffer,
937                  DestinationRootPath.Buffer);
938           if (InstallDir[0] != L'\\')
939             wcscat(PathBuffer,
940                    L"\\");
941           wcscat(PathBuffer, InstallDir);
942           RtlCreateUnicodeString(&DestinationPath,
943                                  PathBuffer);
944
945           /* Create 'DestinationArcPath' */
946           RtlFreeUnicodeString(&DestinationArcPath);
947           swprintf(PathBuffer,
948                    L"multi(0)disk(0)rdisk(%lu)partition(%lu)",
949                    PartData.DiskNumber,
950                    PartData.PartNumber);
951           if (InstallDir[0] != L'\\')
952             wcscat(PathBuffer,
953                    L"\\");
954           wcscat(PathBuffer, InstallDir);
955           RtlCreateUnicodeString(&DestinationArcPath,
956                                  PathBuffer);
957
958           return(PREPARE_COPY_PAGE);
959         }
960       else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x08) /* BACKSPACE */
961         {
962           if (Length > 0)
963             {
964               Length--;
965               InstallDir[Length] = 0;
966               SetInputTextXY(8, 11, 51, InstallDir);
967             }
968         }
969       else if (isprint(Ir->Event.KeyEvent.uChar.AsciiChar))
970         {
971           if (Length < 50)
972             {
973               InstallDir[Length] = (WCHAR)Ir->Event.KeyEvent.uChar.AsciiChar;
974               Length++;
975               InstallDir[Length] = 0;
976               SetInputTextXY(8, 11, 51, InstallDir);
977             }
978         }
979     }
980
981   return(INSTALL_DIRECTORY_PAGE);
982 }
983
984
985 static ULONG
986 PrepareCopyPage(PINPUT_RECORD Ir)
987 {
988   WCHAR PathBuffer[MAX_PATH];
989   PINICACHESECTION DirSection;
990   PINICACHESECTION FilesSection;
991   PINICACHEITERATOR Iterator;
992   PWCHAR KeyName;
993   PWCHAR KeyValue;
994   ULONG Length;
995   NTSTATUS Status;
996
997   PWCHAR FileKeyName;
998   PWCHAR FileKeyValue;
999   PWCHAR DirKeyName;
1000   PWCHAR DirKeyValue;
1001
1002   SetTextXY(6, 8, "Setup prepares your computer for copying the ReactOS files. ");
1003
1004
1005 //  SetTextXY(8, 12, "Build file copy list");
1006
1007 //  SetTextXY(8, 14, "Create directories");
1008
1009 //  SetStatusText("   Please wait...");
1010
1011
1012   /*
1013    * Build the file copy list
1014    */
1015   SetStatusText("   Building the file copy list...");
1016 //  SetInvertedTextXY(8, 12, "Build file copy list");
1017
1018
1019   /* Open 'Directories' section */
1020   DirSection = IniCacheGetSection(IniCache,
1021                                   L"Directories");
1022   if (DirSection == NULL)
1023   {
1024     PopupError("Setup failed to find the 'Directories' section\n"
1025                "in TXTSETUP.SIF.\n",
1026                "ENTER = Reboot computer");
1027
1028       while(TRUE)
1029       {
1030         ConInKey(Ir);
1031
1032         if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1033         {
1034           return(QUIT_PAGE);
1035         }
1036       }
1037   }
1038
1039   /* Open 'SourceFiles' section */
1040   FilesSection = IniCacheGetSection(IniCache,
1041                                     L"SourceFiles");
1042   if (FilesSection == NULL)
1043   {
1044     PopupError("Setup failed to find the 'SourceFiles' section\n"
1045                "in TXTSETUP.SIF.\n",
1046                "ENTER = Reboot computer");
1047
1048       while(TRUE)
1049       {
1050         ConInKey(Ir);
1051
1052         if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1053         {
1054           return(QUIT_PAGE);
1055         }
1056       }
1057   }
1058
1059
1060   /* Create the file queue */
1061   SetupFileQueue = SetupOpenFileQueue();
1062   if (SetupFileQueue == NULL)
1063   {
1064     PopupError("Setup failed to open the copy file queue.\n",
1065                "ENTER = Reboot computer");
1066
1067       while(TRUE)
1068       {
1069         ConInKey(Ir);
1070
1071         if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1072         {
1073           return(QUIT_PAGE);
1074         }
1075       }
1076   }
1077
1078   /*
1079    * Enumerate the files in the 'SourceFiles' section
1080    * and add them to the file queue.
1081    */
1082   Iterator = IniCacheFindFirstValue(FilesSection,
1083                                     &FileKeyName,
1084                                     &FileKeyValue);
1085   if (Iterator != NULL)
1086   {
1087     do
1088     {
1089       DPRINT1("FileKeyName: '%S'  FileKeyValue: '%S'\n", FileKeyName, FileKeyValue);
1090
1091       /* Lookup target directory */
1092       Status = IniCacheGetKey(DirSection,
1093                               FileKeyValue,
1094                               &DirKeyValue);
1095       if (!NT_SUCCESS(Status))
1096       {
1097         /* FIXME: Handle error! */
1098         DPRINT1("IniCacheGetKey() failed (Status 0x%lX)\n", Status);
1099       }
1100
1101       if (SetupQueueCopy(SetupFileQueue,
1102                          SourceRootPath.Buffer,
1103                          L"\\install",
1104                          FileKeyName,
1105                          DirKeyValue,
1106                          NULL) == FALSE)
1107       {
1108         /* FIXME: Handle error! */
1109         DPRINT1("SetupQueueCopy() failed\n");
1110       }
1111     }
1112     while (IniCacheFindNextValue(Iterator, &FileKeyName, &FileKeyValue));
1113
1114     IniCacheFindClose(Iterator);
1115   }
1116
1117   /* Report that the file queue has been built */
1118 //  SetTextXY(8, 12, "Build file copy list");
1119 //  SetHighlightedTextXY(50, 12, "Done");
1120
1121   /* create directories */
1122   SetStatusText("   Creating directories...");
1123 //  SetInvertedTextXY(8, 14, "Create directories");
1124
1125
1126   /*
1127    * FIXME:
1128    * Install directories like '\reactos\test' are not handled yet.
1129    */
1130
1131   /* Get destination path */
1132   wcscpy(PathBuffer, DestinationPath.Buffer);
1133
1134   /* Remove trailing backslash */
1135   Length = wcslen(PathBuffer);
1136   if ((Length > 0) && (PathBuffer[Length - 1] == '\\'))
1137     PathBuffer[Length - 1] = 0;
1138
1139   /* Create the install directory */
1140   Status = CreateDirectory(PathBuffer);
1141   if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION)
1142   {
1143     DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer, Status);
1144
1145     PopupError("Setup could not create the install directory.",
1146                "ENTER = Reboot computer");
1147
1148     while(TRUE)
1149     {
1150       ConInKey(Ir);
1151
1152       if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)   /* ENTER */
1153       {
1154         return(QUIT_PAGE);
1155       }
1156     }
1157   }
1158
1159
1160   /* Enumerate the directory values and create the subdirectories */
1161   Iterator = IniCacheFindFirstValue(DirSection,
1162                                     &KeyName,
1163                                     &KeyValue);
1164   if (Iterator != NULL)
1165   {
1166     do
1167     {
1168       if (KeyValue[0] == L'\\' && KeyValue[1] != 0)
1169       {
1170         DPRINT("Absolute Path: '%S'\n", KeyValue);
1171
1172         wcscpy(PathBuffer, DestinationRootPath.Buffer);
1173         wcscat(PathBuffer, KeyValue);
1174
1175         DPRINT("FullPath: '%S'\n", PathBuffer);
1176       }
1177       else if (KeyValue[0] != L'\\')
1178       {
1179         DPRINT("RelativePath: '%S'\n", KeyValue);
1180         wcscpy(PathBuffer, DestinationPath.Buffer);
1181         wcscat(PathBuffer, L"\\");
1182         wcscat(PathBuffer, KeyValue);
1183
1184         DPRINT("FullPath: '%S'\n", PathBuffer);
1185
1186         Status = CreateDirectory(PathBuffer);
1187         if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION)
1188           {
1189             DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer, Status);
1190
1191             PopupError("Setup could not create install directories.",
1192                        "ENTER = Reboot computer");
1193
1194             while(TRUE)
1195             {
1196               ConInKey(Ir);
1197
1198               if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)   /* ENTER */
1199               {
1200                 IniCacheFindClose(Iterator);
1201                 return(QUIT_PAGE);
1202               }
1203             }
1204           }
1205       }
1206     }
1207     while (IniCacheFindNextValue(Iterator, &KeyName, &KeyValue));
1208
1209     IniCacheFindClose(Iterator);
1210   }
1211
1212
1213   return(FILE_COPY_PAGE);
1214
1215 #if 0
1216   SetTextXY(8, 14, "Create directories");
1217   SetHighlightedTextXY(50, 14, "Done");
1218
1219
1220   SetStatusText("   ENTER = Continue   F3 = Quit");
1221
1222   while(TRUE)
1223     {
1224       ConInKey(Ir);
1225
1226       if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1227           (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1228         {
1229           if (ConfirmQuit(Ir) == TRUE)
1230             return(QUIT_PAGE);
1231           break;
1232         }
1233       else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1234         {
1235           return(FILE_COPY_PAGE);
1236         }
1237     }
1238
1239   return(PREPARE_COPY_PAGE);
1240 #endif
1241 }
1242
1243
1244 static ULONG
1245 FileCopyCallback(PVOID Context,
1246                  ULONG Notification,
1247                  PVOID Param1,
1248                  PVOID Param2)
1249 {
1250   PCOPYCONTEXT CopyContext;
1251
1252   CopyContext = (PCOPYCONTEXT)Context;
1253
1254   switch (Notification)
1255   {
1256     case SPFILENOTIFY_STARTSUBQUEUE:
1257       CopyContext->TotalOperations = (ULONG)Param2;
1258       ProgressSetStepCount(CopyContext->ProgressBar,
1259                            CopyContext->TotalOperations);
1260       break;
1261
1262     case SPFILENOTIFY_STARTCOPY:
1263       /* Display copy message */
1264       PrintTextXYN(6, 16, 60, "Copying file: %S", (PWSTR)Param1);
1265
1266       PrintTextXYN(6, 18, 60, "File %lu of %lu",
1267                    CopyContext->CompletedOperations + 1,
1268                    CopyContext->TotalOperations);
1269       break;
1270
1271
1272     case SPFILENOTIFY_ENDCOPY:
1273       CopyContext->CompletedOperations++;
1274       ProgressNextStep(CopyContext->ProgressBar);
1275       break;
1276   }
1277
1278   return(0);
1279 }
1280
1281
1282 static ULONG
1283 FileCopyPage(PINPUT_RECORD Ir)
1284 {
1285   COPYCONTEXT CopyContext;
1286   SHORT xScreen;
1287   SHORT yScreen;
1288
1289   SetStatusText("   Please wait...");
1290
1291   SetTextXY(6, 8, "Copying files");
1292
1293   GetScreenSize(&xScreen, &yScreen);
1294
1295   CopyContext.TotalOperations = 0;
1296   CopyContext.CompletedOperations = 0;
1297   CopyContext.ProgressBar = CreateProgressBar(6,
1298                                               yScreen - 14,
1299                                               xScreen - 7,
1300                                               yScreen - 10);
1301
1302   SetupCommitFileQueue(SetupFileQueue,
1303                        DestinationRootPath.Buffer,
1304                        InstallPath.Buffer,
1305                        (PSP_FILE_CALLBACK)FileCopyCallback,
1306                        &CopyContext);
1307
1308   SetupCloseFileQueue(SetupFileQueue);
1309
1310   DestroyProgressBar(CopyContext.ProgressBar);
1311
1312   return(REGISTRY_PAGE);
1313
1314 #if 0
1315   SetStatusText("   ENTER = Continue   F3 = Quit");
1316
1317   while(TRUE)
1318     {
1319       ConInKey(Ir);
1320
1321       if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1322           (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1323         {
1324           if (ConfirmQuit(Ir) == TRUE)
1325             return(QUIT_PAGE);
1326           break;
1327         }
1328       else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1329         {
1330           return(REGISTRY_PAGE);
1331         }
1332     }
1333
1334   return(FILE_COPY_PAGE);
1335 #endif
1336 }
1337
1338
1339
1340 static ULONG
1341 RegistryPage(PINPUT_RECORD Ir)
1342 {
1343   OBJECT_ATTRIBUTES ObjectAttributes;
1344   UNICODE_STRING KeyName;
1345   UNICODE_STRING ValueName;
1346   HANDLE KeyHandle;
1347   NTSTATUS Status;
1348
1349   SetTextXY(6, 8, "Setup initializes system settings");
1350
1351
1352 //  SetTextXY(6, 12, "Create registry hives");
1353
1354 //  SetTextXY(6, 14, "Update registry hives");
1355
1356
1357 //  SetStatusText("   Please wait...");
1358
1359   SetStatusText("   Creating registry hives...");
1360
1361   /* Create the 'secret' InstallPath key */
1362   RtlInitUnicodeStringFromLiteral(&KeyName,
1363                                   L"\\Registry\\Machine\\HARDWARE");
1364   InitializeObjectAttributes(&ObjectAttributes,
1365                              &KeyName,
1366                              OBJ_CASE_INSENSITIVE,
1367                              NULL,
1368                              NULL);
1369   Status =  NtOpenKey(&KeyHandle,
1370                       KEY_ALL_ACCESS,
1371                       &ObjectAttributes);
1372   if (!NT_SUCCESS(Status))
1373   {
1374     DPRINT1("NtOpenKey() failed (Status %lx)\n", Status);
1375     PopupError("Setup failed to open the HARDWARE registry key.",
1376                "ENTER = Reboot computer");
1377
1378       while(TRUE)
1379       {
1380         ConInKey(Ir);
1381
1382         if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1383         {
1384           return(QUIT_PAGE);
1385         }
1386       }
1387   }
1388
1389   RtlInitUnicodeStringFromLiteral(&ValueName,
1390                                   L"InstallPath");
1391
1392   Status = NtSetValueKey(KeyHandle,
1393                          &ValueName,
1394                          0,
1395                          REG_SZ,
1396                          (PVOID)DestinationPath.Buffer,
1397                          DestinationPath.Length);
1398   NtClose(KeyHandle);
1399   if (!NT_SUCCESS(Status))
1400   {
1401     DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status);
1402     PopupError("Setup failed to set the \'InstallPath\' registry value.",
1403                "ENTER = Reboot computer");
1404
1405       while(TRUE)
1406       {
1407         ConInKey(Ir);
1408
1409         if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1410         {
1411           return(QUIT_PAGE);
1412         }
1413       }
1414   }
1415
1416   /* Create the standard hives */
1417   Status = NtInitializeRegistry(TRUE);
1418   if (!NT_SUCCESS(Status))
1419   {
1420     DPRINT1("NtInitializeRegistry() failed (Status %lx)\n", Status);
1421     PopupError("Setup failed to initialize the registry.",
1422                "ENTER = Reboot computer");
1423
1424       while(TRUE)
1425       {
1426         ConInKey(Ir);
1427
1428         if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1429         {
1430           return(QUIT_PAGE);
1431         }
1432       }
1433   }
1434
1435
1436   /* Update registry */
1437   SetStatusText("   Updating registry hives...");
1438
1439   /* FIXME: Create key '\Registry\Machine\System\Setup' */
1440
1441   /* FIXME: Create value 'SystemSetupInProgress' */
1442
1443
1444   return(BOOT_LOADER_PAGE);
1445
1446 #if 0
1447   SetStatusText("   ENTER = Continue   F3 = Quit");
1448
1449   while(TRUE)
1450   {
1451     ConInKey(Ir);
1452
1453     if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1454         (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1455     {
1456       if (ConfirmQuit(Ir) == TRUE)
1457         return(QUIT_PAGE);
1458       break;
1459     }
1460     else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1461     {
1462       return(BOOT_LOADER_PAGE);
1463     }
1464   }
1465
1466   return(REGISTRY_PAGE);
1467 #endif
1468 }
1469
1470
1471 static ULONG
1472 BootLoaderPage(PINPUT_RECORD Ir)
1473 {
1474   WCHAR SrcPath[MAX_PATH];
1475   WCHAR DstPath[MAX_PATH];
1476   PINICACHE IniCache;
1477   PINICACHESECTION IniSection;
1478   NTSTATUS Status;
1479
1480   SetTextXY(6, 8, "Installing the boot loader");
1481
1482   SetStatusText("   Please wait...");
1483
1484   if (ActivePartitionValid == FALSE)
1485   {
1486     DPRINT1("Error: no active partition found\n");
1487     PopupError("Setup could not find an active partiton\n",
1488                "ENTER = Reboot computer");
1489
1490     while(TRUE)
1491     {
1492       ConInKey(Ir);
1493
1494       if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)   /* ENTER */
1495       {
1496         return(QUIT_PAGE);
1497       }
1498     }
1499   }
1500
1501   if (ActivePartition.PartType == PARTITION_ENTRY_UNUSED)
1502   {
1503     DPRINT1("Error: active partition invalid (unused)\n");
1504     PopupError("The active partition is unused (invalid).\n",
1505                "ENTER = Reboot computer");
1506
1507     while(TRUE)
1508     {
1509       ConInKey(Ir);
1510
1511       if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)   /* ENTER */
1512       {
1513         return(QUIT_PAGE);
1514       }
1515     }
1516   }
1517
1518   if (ActivePartition.PartType == 0x0A)
1519   {
1520     /* OS/2 boot manager partition */
1521     DPRINT1("Found OS/2 boot manager partition\n");
1522     PopupError("Setup found an OS/2 boot manager partiton.\n"
1523                "The OS/2 boot manager is not supported yet!",
1524                "ENTER = Reboot computer");
1525
1526     while(TRUE)
1527     {
1528       ConInKey(Ir);
1529
1530       if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)   /* ENTER */
1531       {
1532         return(QUIT_PAGE);
1533       }
1534     }
1535   }
1536   else if (ActivePartition.PartType == 0x83)
1537   {
1538     /* Linux ext2 partition */
1539     DPRINT1("Found Linux ext2 partition\n");
1540     PopupError("Setup found a Linux ext2 partiton.\n"
1541                "Linux ext2 partitions are not supported yet!",
1542                "ENTER = Reboot computer");
1543
1544     while(TRUE)
1545     {
1546       ConInKey(Ir);
1547
1548       if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)   /* ENTER */
1549       {
1550         return(QUIT_PAGE);
1551       }
1552     }
1553   }
1554   else if (ActivePartition.PartType == PARTITION_IFS)
1555   {
1556       /* NTFS partition */
1557     DPRINT1("Found NTFS partition\n");
1558     PopupError("Setup found an NTFS partiton.\n"
1559                "NTFS partitions are not supported yet!",
1560                "ENTER = Reboot computer");
1561
1562     while(TRUE)
1563     {
1564       ConInKey(Ir);
1565
1566       if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)   /* ENTER */
1567       {
1568         return(QUIT_PAGE);
1569       }
1570     }
1571   }
1572   else if ((ActivePartition.PartType == PARTITION_FAT_12) ||
1573            (ActivePartition.PartType == PARTITION_FAT_16) ||
1574            (ActivePartition.PartType == PARTITION_HUGE) ||
1575            (ActivePartition.PartType == PARTITION_XINT13) ||
1576            (ActivePartition.PartType == PARTITION_FAT32) ||
1577            (ActivePartition.PartType == PARTITION_FAT32_XINT13))
1578   {
1579     /* FAT or FAT32 partition */
1580     DPRINT1("System path: '%wZ'\n", &SystemRootPath);
1581
1582     if (DoesFileExist(SystemRootPath.Buffer, L"ntldr") == TRUE ||
1583         DoesFileExist(SystemRootPath.Buffer, L"boot.ini") == TRUE)
1584     {
1585       /* Search root directory for 'ntldr' and 'boot.ini'. */
1586       DPRINT1("Found Microsoft Windows NT/2000/XP boot loader\n");
1587
1588       /* Copy FreeLoader to the boot partition */
1589       wcscpy(SrcPath, SourceRootPath.Buffer);
1590       wcscat(SrcPath, L"\\loader\\freeldr.sys");
1591       wcscpy(DstPath, SystemRootPath.Buffer);
1592       wcscat(DstPath, L"\\freeldr.sys");
1593
1594       DPRINT1("Copy: %S ==> %S\n", SrcPath, DstPath);
1595       Status = SetupCopyFile(SrcPath, DstPath);
1596       if (!NT_SUCCESS(Status))
1597       {
1598         DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
1599         PopupError("Setup failed to copy 'freeldr.sys'.",
1600                    "ENTER = Reboot computer");
1601
1602         while(TRUE)
1603         {
1604           ConInKey(Ir);
1605
1606           if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)       /* ENTER */
1607           {
1608             return(QUIT_PAGE);
1609           }
1610         }
1611       }
1612
1613       /* Create or update freeldr.ini */
1614       if (DoesFileExist(SystemRootPath.Buffer, L"freeldr.ini") == FALSE)
1615       {
1616         /* Create new 'freeldr.ini' */
1617         DPRINT1("Create new 'freeldr.ini'\n");
1618         wcscpy(DstPath, SystemRootPath.Buffer);
1619         wcscat(DstPath, L"\\freeldr.ini");
1620
1621         Status = CreateFreeLoaderIniForReactos(DstPath,
1622                                                DestinationArcPath.Buffer);
1623         if (!NT_SUCCESS(Status))
1624         {
1625           DPRINT1("CreateFreeLoaderIniForReactos() failed (Status %lx)\n", Status);
1626           PopupError("Setup failed to create 'freeldr.ini'.",
1627                      "ENTER = Reboot computer");
1628
1629           while(TRUE)
1630           {
1631             ConInKey(Ir);
1632
1633             if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)     /* ENTER */
1634             {
1635               return(QUIT_PAGE);
1636             }
1637           }
1638         }
1639
1640         /* Install new bootcode */
1641         if ((ActivePartition.PartType == PARTITION_FAT32) ||
1642             (ActivePartition.PartType == PARTITION_FAT32_XINT13))
1643         {
1644           /* Install FAT32 bootcode */
1645           wcscpy(SrcPath, SourceRootPath.Buffer);
1646           wcscat(SrcPath, L"\\loader\\fat32.bin");
1647           wcscpy(DstPath, SystemRootPath.Buffer);
1648           wcscat(DstPath, L"\\bootsect.ros");
1649
1650           DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, DstPath);
1651           Status = InstallFat32BootCodeToFile(SrcPath,
1652                                               DstPath,
1653                                               SystemRootPath.Buffer);
1654           if (!NT_SUCCESS(Status))
1655           {
1656             DPRINT1("InstallFat32BootCodeToFile() failed (Status %lx)\n", Status);
1657             PopupError("Setup failed to install the FAT32 bootcode.",
1658                        "ENTER = Reboot computer");
1659
1660             while(TRUE)
1661             {
1662               ConInKey(Ir);
1663
1664               if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)   /* ENTER */
1665               {
1666                 return(QUIT_PAGE);
1667               }
1668             }
1669           }
1670         }
1671         else
1672         {
1673           /* Install FAT16 bootcode */
1674           wcscpy(SrcPath, SourceRootPath.Buffer);
1675           wcscat(SrcPath, L"\\loader\\fat.bin");
1676           wcscpy(DstPath, SystemRootPath.Buffer);
1677           wcscat(DstPath, L"\\bootsect.ros");
1678
1679           DPRINT1("Install FAT bootcode: %S ==> %S\n", SrcPath, DstPath);
1680           Status = InstallFat16BootCodeToFile(SrcPath,
1681                                               DstPath,
1682                                               SystemRootPath.Buffer);
1683           if (!NT_SUCCESS(Status))
1684           {
1685             DPRINT1("InstallFat16BootCodeToFile() failed (Status %lx)\n", Status);
1686             PopupError("Setup failed to install the FAT bootcode.",
1687                        "ENTER = Reboot computer");
1688
1689             while(TRUE)
1690             {
1691               ConInKey(Ir);
1692
1693               if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)   /* ENTER */
1694               {
1695                 return(QUIT_PAGE);
1696               }
1697             }
1698           }
1699         }
1700
1701         /* Update 'boot.ini' */
1702         wcscpy(DstPath, SystemRootPath.Buffer);
1703         wcscat(DstPath, L"\\boot.ini");
1704
1705         DPRINT1("Update 'boot.ini': %S\n", DstPath);
1706         Status = UpdateBootIni(DstPath,
1707                                L"C:\\bootsect.ros",
1708                                L"\"ReactOS\"");
1709         if (!NT_SUCCESS(Status))
1710         {
1711           DPRINT1("UpdateBootIni() failed (Status %lx)\n", Status);
1712           PopupError("Setup failed to update \'boot.ini\'.",
1713                      "ENTER = Reboot computer");
1714
1715           while(TRUE)
1716           {
1717             ConInKey(Ir);
1718
1719             if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)     /* ENTER */
1720             {
1721               return(QUIT_PAGE);
1722             }
1723           }
1724         }
1725       }
1726       else
1727       {
1728         /* Update existing 'freeldr.ini' */
1729         DPRINT1("Update existing 'freeldr.ini'\n");
1730         wcscpy(DstPath, SystemRootPath.Buffer);
1731         wcscat(DstPath, L"\\freeldr.ini");
1732
1733         Status = UpdateFreeLoaderIni(DstPath,
1734                                      DestinationArcPath.Buffer);
1735         if (!NT_SUCCESS(Status))
1736         {
1737           DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
1738           PopupError("Setup failed to update 'freeldr.ini'.",
1739                      "ENTER = Reboot computer");
1740
1741           while(TRUE)
1742           {
1743             ConInKey(Ir);
1744
1745             if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)     /* ENTER */
1746             {
1747               return(QUIT_PAGE);
1748             }
1749           }
1750         }
1751       }
1752     }
1753     else if (DoesFileExist(SystemRootPath.Buffer, L"io.sys") == TRUE ||
1754              DoesFileExist(SystemRootPath.Buffer, L"msdos.sys") == TRUE)
1755     {
1756       /* Search for root directory for 'io.sys' and 'msdos.sys'. */
1757       DPRINT1("Found Microsoft DOS or Windows 9x boot loader\n");
1758
1759       /* Copy FreeLoader to the boot partition */
1760       wcscpy(SrcPath, SourceRootPath.Buffer);
1761       wcscat(SrcPath, L"\\loader\\freeldr.sys");
1762       wcscpy(DstPath, SystemRootPath.Buffer);
1763       wcscat(DstPath, L"\\freeldr.sys");
1764
1765       DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
1766       Status = SetupCopyFile(SrcPath, DstPath);
1767       if (!NT_SUCCESS(Status))
1768       {
1769         DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
1770         PopupError("Setup failed to copy 'freeldr.sys'.",
1771                    "ENTER = Reboot computer");
1772
1773         while(TRUE)
1774         {
1775           ConInKey(Ir);
1776
1777           if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)       /* ENTER */
1778           {
1779             return(QUIT_PAGE);
1780           }
1781         }
1782       }
1783
1784       /* Create or update 'freeldr.ini' */
1785       if (DoesFileExist(SystemRootPath.Buffer, L"freeldr.ini") == FALSE)
1786       {
1787         /* Create new 'freeldr.ini' */
1788         DPRINT1("Create new 'freeldr.ini'\n");
1789         wcscpy(DstPath, SystemRootPath.Buffer);
1790         wcscat(DstPath, L"\\freeldr.ini");
1791
1792         Status = CreateFreeLoaderIniForDos(DstPath,
1793                                            DestinationArcPath.Buffer);
1794         if (!NT_SUCCESS(Status))
1795         {
1796           DPRINT1("CreateFreeLoaderIniForDos() failed (Status %lx)\n", Status);
1797           PopupError("Setup failed to create 'freeldr.ini'.",
1798                      "ENTER = Reboot computer");
1799
1800           while(TRUE)
1801           {
1802             ConInKey(Ir);
1803
1804             if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)     /* ENTER */
1805             {
1806               return(QUIT_PAGE);
1807             }
1808           }
1809         }
1810
1811         /* Save current bootsector as 'BOOTSECT.DOS' */
1812         wcscpy(SrcPath, SystemRootPath.Buffer);
1813         wcscpy(DstPath, SystemRootPath.Buffer);
1814         wcscat(DstPath, L"\\bootsect.dos");
1815
1816         DPRINT1("Save bootsector: %S ==> %S\n", SrcPath, DstPath);
1817         Status = SaveCurrentBootSector(SrcPath,
1818                                        DstPath);
1819         if (!NT_SUCCESS(Status))
1820         {
1821           DPRINT1("SaveCurrentBootSector() failed (Status %lx)\n", Status);
1822           PopupError("Setup failed to save the current bootsector.",
1823                      "ENTER = Reboot computer");
1824
1825           while(TRUE)
1826           {
1827             ConInKey(Ir);
1828
1829             if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)     /* ENTER */
1830             {
1831               return(QUIT_PAGE);
1832             }
1833           }
1834         }
1835
1836         /* Install new bootsector */
1837         if ((ActivePartition.PartType == PARTITION_FAT32) ||
1838             (ActivePartition.PartType == PARTITION_FAT32_XINT13))
1839         {
1840           wcscpy(SrcPath, SourceRootPath.Buffer);
1841           wcscat(SrcPath, L"\\loader\\fat32.bin");
1842
1843           DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, SystemRootPath.Buffer);
1844           Status = InstallFat32BootCodeToDisk(SrcPath,
1845                                               SystemRootPath.Buffer);
1846           if (!NT_SUCCESS(Status))
1847           {
1848             DPRINT1("InstallFat32BootCodeToDisk() failed (Status %lx)\n", Status);
1849             PopupError("Setup failed to install the FAT32 bootcode.",
1850                        "ENTER = Reboot computer");
1851
1852             while(TRUE)
1853             {
1854               ConInKey(Ir);
1855
1856               if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)   /* ENTER */
1857               {
1858                 return(QUIT_PAGE);
1859               }
1860             }
1861           }
1862         }
1863         else
1864         {
1865           wcscpy(SrcPath, SourceRootPath.Buffer);
1866           wcscat(SrcPath, L"\\loader\\fat.bin");
1867
1868           DPRINT1("Install FAT bootcode: %S ==> %S\n", SrcPath, SystemRootPath.Buffer);
1869           Status = InstallFat16BootCodeToDisk(SrcPath,
1870                                               SystemRootPath.Buffer);
1871           if (!NT_SUCCESS(Status))
1872           {
1873             DPRINT1("InstallFat16BootCodeToDisk() failed (Status %lx)\n", Status);
1874             PopupError("Setup failed to install the FAT bootcode.",
1875                        "ENTER = Reboot computer");
1876
1877             while(TRUE)
1878             {
1879               ConInKey(Ir);
1880
1881               if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)   /* ENTER */
1882               {
1883                 return(QUIT_PAGE);
1884               }
1885             }
1886           }
1887         }
1888       }
1889       else
1890       {
1891         /* Update existing 'freeldr.ini' */
1892         wcscpy(DstPath, SystemRootPath.Buffer);
1893         wcscat(DstPath, L"\\freeldr.ini");
1894
1895         Status = UpdateFreeLoaderIni(DstPath,
1896                                      DestinationArcPath.Buffer);
1897         if (!NT_SUCCESS(Status))
1898         {
1899           DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
1900           PopupError("Setup failed to update 'freeldr.ini'.",
1901                      "ENTER = Reboot computer");
1902
1903           while(TRUE)
1904           {
1905             ConInKey(Ir);
1906
1907             if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)     /* ENTER */
1908             {
1909               return(QUIT_PAGE);
1910             }
1911           }
1912         }
1913       }
1914     }
1915     else
1916     {
1917       /* No or unknown boot loader */
1918       DPRINT1("No or unknown boot loader found\n");
1919
1920       /* Copy FreeLoader to the boot partition */
1921       wcscpy(SrcPath, SourceRootPath.Buffer);
1922       wcscat(SrcPath, L"\\loader\\freeldr.sys");
1923       wcscpy(DstPath, SystemRootPath.Buffer);
1924       wcscat(DstPath, L"\\freeldr.sys");
1925
1926       DPRINT1("Copy: %S ==> %S\n", SrcPath, DstPath);
1927       Status = SetupCopyFile(SrcPath, DstPath);
1928       if (!NT_SUCCESS(Status))
1929       {
1930         DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
1931         PopupError("Setup failed to copy 'freeldr.sys'.",
1932                    "ENTER = Reboot computer");
1933
1934         while(TRUE)
1935         {
1936           ConInKey(Ir);
1937
1938           if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)       /* ENTER */
1939           {
1940             return(QUIT_PAGE);
1941           }
1942         }
1943       }
1944
1945       /* Create or update 'freeldr.ini' */
1946       if (DoesFileExist(SystemRootPath.Buffer, L"freeldr.ini") == FALSE)
1947       {
1948         /* Create new freeldr.ini */
1949         wcscpy(DstPath, SystemRootPath.Buffer);
1950         wcscat(DstPath, L"\\freeldr.ini");
1951
1952         DPRINT1("Copy: %S ==> %S\n", SrcPath, DstPath);
1953         Status = CreateFreeLoaderIniForReactos(DstPath,
1954                                                DestinationArcPath.Buffer);
1955         if (!NT_SUCCESS(Status))
1956         {
1957           DPRINT1("CreateFreeLoaderIniForReactos() failed (Status %lx)\n", Status);
1958           PopupError("Setup failed to create \'freeldr.ini\'.",
1959                      "ENTER = Reboot computer");
1960
1961           while(TRUE)
1962           {
1963             ConInKey(Ir);
1964
1965             if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)     /* ENTER */
1966             {
1967               return(QUIT_PAGE);
1968             }
1969           }
1970         }
1971
1972         /* Save current bootsector as 'BOOTSECT.OLD' */
1973         wcscpy(SrcPath, SystemRootPath.Buffer);
1974         wcscpy(DstPath, SystemRootPath.Buffer);
1975         wcscat(DstPath, L"\\bootsect.old");
1976
1977         DPRINT1("Save bootsector: %S ==> %S\n", SrcPath, DstPath);
1978         Status = SaveCurrentBootSector(SrcPath,
1979                                        DstPath);
1980         if (!NT_SUCCESS(Status))
1981         {
1982           DPRINT1("SaveCurrentBootSector() failed (Status %lx)\n", Status);
1983           PopupError("Setup failed save the current bootsector.",
1984                      "ENTER = Reboot computer");
1985
1986           while(TRUE)
1987           {
1988             ConInKey(Ir);
1989
1990             if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)     /* ENTER */
1991             {
1992               return(QUIT_PAGE);
1993             }
1994           }
1995         }
1996
1997         /* Install new bootsector */
1998         if ((ActivePartition.PartType == PARTITION_FAT32) ||
1999             (ActivePartition.PartType == PARTITION_FAT32_XINT13))
2000         {
2001           wcscpy(SrcPath, SourceRootPath.Buffer);
2002           wcscat(SrcPath, L"\\loader\\fat32.bin");
2003
2004           DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, SystemRootPath.Buffer);
2005           Status = InstallFat32BootCodeToDisk(SrcPath,
2006                                               SystemRootPath.Buffer);
2007           if (!NT_SUCCESS(Status))
2008           {
2009             DPRINT1("InstallFat32BootCodeToDisk() failed (Status %lx)\n", Status);
2010             PopupError("Setup failed to install the FAT32 bootcode.",
2011                        "ENTER = Reboot computer");
2012
2013             while(TRUE)
2014             {
2015               ConInKey(Ir);
2016
2017               if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)   /* ENTER */
2018               {
2019                 return(QUIT_PAGE);
2020               }
2021             }
2022           }
2023         }
2024         else
2025         {
2026           wcscpy(SrcPath, SourceRootPath.Buffer);
2027           wcscat(SrcPath, L"\\loader\\fat.bin");
2028
2029           DPRINT1("Install FAT bootcode: %S ==> %S\n", SrcPath, SystemRootPath.Buffer);
2030           Status = InstallFat16BootCodeToDisk(SrcPath,
2031                                               SystemRootPath.Buffer);
2032           if (!NT_SUCCESS(Status))
2033           {
2034             DPRINT1("InstallFat16BootCodeToDisk() failed (Status %lx)\n", Status);
2035             PopupError("Setup failed to install the FAT bootcode.",
2036                        "ENTER = Reboot computer");
2037
2038             while(TRUE)
2039             {
2040               ConInKey(Ir);
2041
2042               if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)   /* ENTER */
2043               {
2044                 return(QUIT_PAGE);
2045               }
2046             }
2047           }
2048         }
2049       }
2050       else
2051       {
2052         /* Update existing 'freeldr.ini' */
2053         wcscpy(DstPath, SystemRootPath.Buffer);
2054         wcscat(DstPath, L"\\freeldr.ini");
2055
2056         Status = UpdateFreeLoaderIni(DstPath,
2057                                      DestinationArcPath.Buffer);
2058         if (!NT_SUCCESS(Status))
2059         {
2060           DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
2061           PopupError("Setup failed to update 'freeldr.ini'.",
2062                      "ENTER = Reboot computer");
2063
2064           while(TRUE)
2065           {
2066             ConInKey(Ir);
2067
2068             if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)     /* ENTER */
2069             {
2070               return(QUIT_PAGE);
2071             }
2072           }
2073         }
2074       }
2075     }
2076   }
2077   else
2078   {
2079     /* Unknown partition */
2080     DPRINT1("Unknown partition found\n");
2081     PopupError("Setup found an unknown partiton type.\n"
2082                "This partition type is not supported!",
2083                "ENTER = Reboot computer");
2084
2085     while(TRUE)
2086     {
2087       ConInKey(Ir);
2088
2089       if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)   /* ENTER */
2090       {
2091         return(QUIT_PAGE);
2092       }
2093     }
2094   }
2095
2096   return(SUCCESS_PAGE);
2097
2098 #if 0
2099   SetStatusText("   ENTER = Continue   F3 = Quit");
2100
2101   while(TRUE)
2102     {
2103       ConInKey(Ir);
2104
2105       if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2106           (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
2107         {
2108           if (ConfirmQuit(Ir) == TRUE)
2109             return(QUIT_PAGE);
2110           break;
2111         }
2112       else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2113         {
2114           return(SUCCESS_PAGE);
2115         }
2116     }
2117
2118   return(BOOT_LOADER_PAGE);
2119 #endif
2120 }
2121
2122
2123
2124 static ULONG
2125 QuitPage(PINPUT_RECORD Ir)
2126 {
2127   SetTextXY(10, 6, "ReactOS is not completely installed");
2128
2129   SetTextXY(10, 8, "Remove floppy disk from Drive A: and");
2130   SetTextXY(10, 9, "all CD-ROMs from CD-Drives.");
2131
2132   SetTextXY(10, 11, "Press ENTER to reboot your computer.");
2133
2134   SetStatusText("   ENTER = Reboot computer");
2135
2136   while(TRUE)
2137     {
2138       ConInKey(Ir);
2139
2140       if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2141         {
2142           return(REBOOT_PAGE);
2143         }
2144     }
2145 }
2146
2147
2148 static ULONG
2149 SuccessPage(PINPUT_RECORD Ir)
2150 {
2151   SetTextXY(10, 6, "The basic components of ReactOS have been installed successfully.");
2152
2153   SetTextXY(10, 8, "Remove floppy disk from Drive A: and");
2154   SetTextXY(10, 9, "all CD-ROMs from CD-Drive.");
2155
2156   SetTextXY(10, 11, "Press ENTER to reboot your computer.");
2157
2158   SetStatusText("   ENTER = Reboot computer");
2159
2160   while(TRUE)
2161     {
2162       ConInKey(Ir);
2163
2164       if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2165         {
2166           return(REBOOT_PAGE);
2167         }
2168     }
2169 }
2170
2171
2172 VOID STDCALL
2173 NtProcessStartup(PPEB Peb)
2174 {
2175   NTSTATUS Status;
2176   INPUT_RECORD Ir;
2177   ULONG Page;
2178
2179   RtlNormalizeProcessParams(Peb->ProcessParameters);
2180
2181   ProcessHeap = Peb->ProcessHeap;
2182
2183   Status = AllocConsole();
2184   if (!NT_SUCCESS(Status))
2185     {
2186       PrintString("AllocConsole() failed (Status = 0x%08lx)\n", Status);
2187
2188       /* Raise a hard error (crash the system/BSOD) */
2189       NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED,
2190                        0,0,0,0,0);
2191     }
2192
2193   PartDataValid = FALSE;
2194
2195   /* Initialize global unicode strings */
2196   RtlInitUnicodeString(&SourcePath, NULL);
2197   RtlInitUnicodeString(&SourceRootPath, NULL);
2198   RtlInitUnicodeString(&InstallPath, NULL);
2199   RtlInitUnicodeString(&DestinationPath, NULL);
2200   RtlInitUnicodeString(&DestinationArcPath, NULL);
2201   RtlInitUnicodeString(&DestinationRootPath, NULL);
2202   RtlInitUnicodeString(&SystemRootPath, NULL);
2203
2204
2205   Page = START_PAGE;
2206   while (Page != REBOOT_PAGE)
2207     {
2208       ClearScreen();
2209
2210       SetUnderlinedTextXY(4, 3, " ReactOS " KERNEL_VERSION_STR " Setup ");
2211
2212       switch (Page)
2213         {
2214           /* Start page */
2215           case START_PAGE:
2216             Page = StartPage(&Ir);
2217             break;
2218
2219           /* Intro page */
2220           case INTRO_PAGE:
2221             Page = IntroPage(&Ir);
2222             break;
2223
2224           /* Install pages */
2225           case INSTALL_INTRO_PAGE:
2226             Page = InstallIntroPage(&Ir);
2227             break;
2228
2229 #if 0
2230           case OEM_DRIVER_PAGE:
2231             Page = OemDriverPage(&Ir);
2232             break;
2233 #endif
2234
2235 #if 0
2236           case DEVICE_SETTINGS_PAGE:
2237 #endif
2238
2239           case SELECT_PARTITION_PAGE:
2240             Page = SelectPartitionPage(&Ir);
2241             break;
2242
2243           case SELECT_FILE_SYSTEM_PAGE:
2244             Page = SelectFileSystemPage(&Ir);
2245             break;
2246
2247           case CHECK_FILE_SYSTEM_PAGE:
2248             Page = CheckFileSystemPage(&Ir);
2249             break;
2250
2251           case INSTALL_DIRECTORY_PAGE:
2252             Page = InstallDirectoryPage(&Ir);
2253             break;
2254
2255           case PREPARE_COPY_PAGE:
2256             Page = PrepareCopyPage(&Ir);
2257             break;
2258
2259           case FILE_COPY_PAGE:
2260             Page = FileCopyPage(&Ir);
2261             break;
2262
2263           case REGISTRY_PAGE:
2264             Page = RegistryPage(&Ir);
2265             break;
2266
2267           case BOOT_LOADER_PAGE:
2268             Page = BootLoaderPage(&Ir);
2269             break;
2270
2271
2272           /* Repair pages */
2273           case REPAIR_INTRO_PAGE:
2274             Page = RepairIntroPage(&Ir);
2275             break;
2276
2277
2278           case SUCCESS_PAGE:
2279             Page = SuccessPage(&Ir);
2280             break;
2281
2282           case QUIT_PAGE:
2283             Page = QuitPage(&Ir);
2284             break;
2285         }
2286     }
2287
2288   /* Reboot */
2289   FreeConsole();
2290   NtShutdownSystem(ShutdownReboot);
2291 }
2292
2293 /* EOF */