3 * Copyright (C) 2002 ReactOS Team
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.
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.
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.
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
27 #include <ddk/ntddk.h>
28 #include <ntdll/rtl.h>
30 #include <ntos/minmax.h>
31 #include <reactos/resource.h>
37 #include "filequeue.h"
44 #define INSTALL_INTRO_PAGE 2
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
55 #define REPAIR_INTRO_PAGE 20
57 #define SUCCESS_PAGE 100
59 #define REBOOT_PAGE 102
62 typedef struct _COPYCONTEXT
64 ULONG TotalOperations
;
65 ULONG CompletedOperations
;
66 PPROGRESS ProgressBar
;
67 } COPYCONTEXT
, *PCOPYCONTEXT
;
70 /* GLOBALS ******************************************************************/
74 BOOLEAN PartDataValid
;
77 BOOLEAN ActivePartitionValid
;
78 PARTDATA ActivePartition
;
80 UNICODE_STRING SourcePath
;
81 UNICODE_STRING SourceRootPath
;
83 UNICODE_STRING InstallPath
;
84 UNICODE_STRING DestinationPath
;
85 UNICODE_STRING DestinationRootPath
;
87 UNICODE_STRING SystemRootPath
; /* Path to the active partition */
91 HSPFILEQ SetupFileQueue
= NULL
;
94 /* FUNCTIONS ****************************************************************/
97 PrintString(char* fmt
,...)
101 UNICODE_STRING UnicodeString
;
102 ANSI_STRING AnsiString
;
105 vsprintf(buffer
, fmt
, ap
);
108 RtlInitAnsiString(&AnsiString
, buffer
);
109 RtlAnsiStringToUnicodeString(&UnicodeString
,
112 NtDisplayString(&UnicodeString
);
113 RtlFreeUnicodeString(&UnicodeString
);
118 PopupError(PCHAR Text
,
137 /* Count text lines and longest line */
143 p
= strchr(pnext
, '\n');
146 Length
= strlen(pnext
);
151 Length
= (ULONG
)(p
- pnext
);
156 if (Length
> MaxLength
)
159 if (LastLine
== TRUE
)
165 /* Check length of status line */
168 Length
= strlen(Status
);
169 if (Length
> MaxLength
)
173 GetScreenSize(&xScreen
, &yScreen
);
175 Width
= MaxLength
+ 4;
180 yTop
= (yScreen
- Height
) / 2;
181 xLeft
= (xScreen
- Width
) / 2;
184 /* Set screen attributes */
186 for (coPos
.Y
= yTop
; coPos
.Y
< yTop
+ Height
; coPos
.Y
++)
188 FillConsoleOutputAttribute(0x74,
194 /* draw upper left corner */
197 FillConsoleOutputCharacter(0xDA, // '+',
202 /* draw upper edge */
205 FillConsoleOutputCharacter(0xC4, // '-',
210 /* draw upper right corner */
211 coPos
.X
= xLeft
+ Width
- 1;
213 FillConsoleOutputCharacter(0xBF, // '+',
218 /* Draw right edge, inner space and left edge */
219 for (coPos
.Y
= yTop
+ 1; coPos
.Y
< yTop
+ Height
- 1; coPos
.Y
++)
222 FillConsoleOutputCharacter(0xB3, // '|',
228 FillConsoleOutputCharacter(' ',
233 coPos
.X
= xLeft
+ Width
- 1;
234 FillConsoleOutputCharacter(0xB3, // '|',
240 /* draw lower left corner */
242 coPos
.Y
= yTop
+ Height
- 1;
243 FillConsoleOutputCharacter(0xC0, // '+',
248 /* draw lower edge */
250 coPos
.Y
= yTop
+ Height
- 1;
251 FillConsoleOutputCharacter(0xC4, // '-',
256 /* draw lower right corner */
257 coPos
.X
= xLeft
+ Width
- 1;
258 coPos
.Y
= yTop
+ Height
- 1;
259 FillConsoleOutputCharacter(0xD9, // '+',
264 /* Print message text */
269 p
= strchr(pnext
, '\n');
272 Length
= strlen(pnext
);
277 Length
= (ULONG
)(p
- pnext
);
284 WriteConsoleOutputCharacters(pnext
,
289 if (LastLine
== TRUE
)
296 /* Print separator line and status text */
299 coPos
.Y
= yTop
+ Height
- 3;
301 FillConsoleOutputCharacter(0xC3, // '+',
307 FillConsoleOutputCharacter(0xC4, // '-',
312 coPos
.X
= xLeft
+ Width
- 1;
313 FillConsoleOutputCharacter(0xB4, // '+',
320 WriteConsoleOutputCharacters(Status
,
321 min(strlen(Status
), Width
- 4),
331 * FALSE: Don't quit setup.
334 ConfirmQuit(PINPUT_RECORD Ir
)
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"
342 " * Press ENTER to continue Setup.\n"
343 " * Press F3 to quit Setup.",
344 "F3= Quit ENTER = Continue");
350 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
351 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
356 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
371 * Number of the next page.
374 StartPage(PINPUT_RECORD Ir
)
377 WCHAR FileNameBuffer
[MAX_PATH
];
378 UNICODE_STRING FileName
;
380 PINICACHESECTION Section
;
384 SetStatusText(" Please wait...");
386 Status
= GetSourcePaths(&SourcePath
,
388 if (!NT_SUCCESS(Status
))
390 PrintTextXY(6, 15, "GetSourcePath() failed (Status 0x%08lx)", Status
);
394 PrintTextXY(6, 15, "SourcePath: '%wZ'", &SourcePath
);
395 PrintTextXY(6, 16, "SourceRootPath: '%wZ'", &SourceRootPath
);
399 /* Load txtsetup.sif from install media. */
400 wcscpy(FileNameBuffer
, SourceRootPath
.Buffer
);
401 wcscat(FileNameBuffer
, L
"\\install\\txtsetup.sif");
402 RtlInitUnicodeString(&FileName
,
406 Status
= IniCacheLoad(&IniCache
,
408 if (!NT_SUCCESS(Status
))
410 PopupError("Setup failed to load the file TXTSETUP.SIF.\n",
411 "ENTER = Reboot computer");
417 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
424 /* Open 'Version' section */
425 Section
= IniCacheGetSection(IniCache
,
429 PopupError("Setup found a corrupt TXTSETUP.SIF.\n",
430 "ENTER = Reboot computer");
436 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
444 /* Get pointer 'Signature' key */
445 Status
= IniCacheGetKey(Section
,
448 if (!NT_SUCCESS(Status
))
450 PopupError("Setup found a corrupt TXTSETUP.SIF.\n",
451 "ENTER = Reboot computer");
457 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
464 /* Check 'Signature' string */
465 if (_wcsicmp(Value
, L
"$ReactOS$") != 0)
467 PopupError("Setup found an invalid signature in TXTSETUP.SIF.\n",
468 "ENTER = Reboot computer");
474 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
482 PopupError("This is a test error.", "ENTER = Reboot computer");
484 SetStatusText(" ENTER = Continue");
490 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
505 RepairIntroPage(PINPUT_RECORD Ir
)
507 SetTextXY(6, 8, "ReactOS Setup is in an early development phase. It does not yet");
508 SetTextXY(6, 9, "support all the functions of a fully usable setup application.");
510 SetTextXY(6, 12, "The repair functions are not implemented yet.");
512 SetTextXY(8, 15, "\xf9 Press ESC to return to the main page.");
514 SetTextXY(8, 17, "\xf9 Press ENTER to reboot your computer.");
516 SetStatusText(" ESC = Main page ENTER = Reboot");
522 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
526 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
527 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
)) /* ESC */
533 return(REPAIR_INTRO_PAGE
);
540 * TRUE: setup/repair completed successfully
541 * FALSE: setup/repair terminated by user
544 IntroPage(PINPUT_RECORD Ir
)
546 SetHighlightedTextXY(6, 8, "Welcome to ReactOS Setup");
548 SetTextXY(6, 11, "This part of the setup copies the ReactOS Operating System to your");
549 SetTextXY(6, 12, "computer and prepares the second part of the setup.");
551 SetTextXY(8, 15, "\xf9 Press ENTER to install ReactOS.");
553 SetTextXY(8, 17, "\xf9 Press E to start the emergency repair console.");
555 SetTextXY(8, 19, "\xf9 Press R to repair ReactOS.");
557 SetTextXY(8, 21, "\xf9 Press F3 to quit without installing ReactOS.");
560 SetStatusText(" ENTER = Continue F3 = Quit");
566 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
567 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
569 if (ConfirmQuit(Ir
) == TRUE
)
573 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
575 return(INSTALL_INTRO_PAGE
);
578 else if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'E') /* E */
580 return(RepairConsole());
583 else if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'R') /* R */
585 return(REPAIR_INTRO_PAGE
);
594 InstallIntroPage(PINPUT_RECORD Ir
)
596 SetTextXY(6, 8, "ReactOS Setup is in an early development phase. It does not yet");
597 SetTextXY(6, 9, "support all the functions of a fully usable setup application.");
599 SetTextXY(6, 12, "The following functions are missing:");
600 SetTextXY(8, 13, "- Creating and deleting harddisk partitions.");
601 SetTextXY(8, 14, "- Formatting partitions.");
602 SetTextXY(8, 15, "- Support for non-FAT file systems.");
603 SetTextXY(8, 16, "- Checking file systems.");
604 SetTextXY(8, 17, "- Installing the bootloader.");
608 SetTextXY(8, 21, "\xf9 Press ENTER to install ReactOS.");
610 SetTextXY(8, 23, "\xf9 Press F3 to quit without installing ReactOS.");
613 SetStatusText(" ENTER = Continue F3 = Quit");
619 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
620 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
622 if (ConfirmQuit(Ir
) == TRUE
)
626 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
628 return(SELECT_PARTITION_PAGE
);
632 return(INSTALL_INTRO_PAGE
);
637 SelectPartitionPage(PINPUT_RECORD Ir
)
639 WCHAR PathBuffer
[MAX_PATH
];
644 SetTextXY(6, 8, "The list below shows existing partitions and unused disk");
645 SetTextXY(6, 9, "space for new partitions.");
647 SetTextXY(8, 11, "\xf9 Press UP or DOWN to select a list entry.");
648 SetTextXY(8, 13, "\xf9 Press ENTER to install ReactOS onto the selected partition.");
649 SetTextXY(8, 15, "\xf9 Press C to create a new partition.");
650 SetTextXY(8, 17, "\xf9 Press D to delete an existing partition.");
652 SetStatusText(" Please wait...");
654 RtlFreeUnicodeString(&DestinationPath
);
655 RtlFreeUnicodeString(&DestinationRootPath
);
657 GetScreenSize(&xScreen
, &yScreen
);
659 PartList
= CreatePartitionList(2, 19, xScreen
- 3, yScreen
- 3);
660 if (PartList
== NULL
)
662 /* FIXME: show an error dialog */
666 SetStatusText(" ENTER = Continue F3 = Quit");
672 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
673 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
675 if (ConfirmQuit(Ir
) == TRUE
)
677 DestroyPartitionList(PartList
);
682 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
683 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
685 ScrollDownPartitionList(PartList
);
687 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
688 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
690 ScrollUpPartitionList(PartList
);
692 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
694 PartDataValid
= GetSelectedPartition(PartList
,
696 ActivePartitionValid
= GetActiveBootPartition(PartList
,
698 DestroyPartitionList(PartList
);
700 RtlFreeUnicodeString(&DestinationRootPath
);
702 L
"\\Device\\Harddisk%lu\\Partition%lu",
704 PartData
.PartNumber
);
705 RtlCreateUnicodeString(&DestinationRootPath
,
708 RtlFreeUnicodeString(&SystemRootPath
);
710 L
"\\Device\\Harddisk%lu\\Partition%lu",
711 ActivePartition
.DiskNumber
,
712 ActivePartition
.PartNumber
);
713 RtlCreateUnicodeString(&SystemRootPath
,
716 return(SELECT_FILE_SYSTEM_PAGE
);
719 /* FIXME: Update status text */
723 DestroyPartitionList(PartList
);
725 return(SELECT_PARTITION_PAGE
);
730 SelectFileSystemPage(PINPUT_RECORD Ir
)
738 if (PartDataValid
== FALSE
)
740 /* FIXME: show an error dialog */
744 /* adjust disk size */
745 if (PartData
.DiskSize
>= 0x280000000ULL
) /* 10 GB */
747 DiskSize
= (PartData
.DiskSize
+ (1 << 29)) >> 30;
752 DiskSize
= (PartData
.DiskSize
+ (1 << 19)) >> 20;
756 /* adjust partition size */
757 if (PartData
.PartSize
>= 0x280000000ULL
) /* 10 GB */
759 PartSize
= (PartData
.PartSize
+ (1 << 29)) >> 30;
764 PartSize
= (PartData
.PartSize
+ (1 << 19)) >> 20;
768 /* adjust partition type */
769 if ((PartData
.PartType
== PARTITION_FAT_12
) ||
770 (PartData
.PartType
== PARTITION_FAT_16
) ||
771 (PartData
.PartType
== PARTITION_HUGE
) ||
772 (PartData
.PartType
== PARTITION_XINT13
))
776 else if ((PartData
.PartType
== PARTITION_FAT32
) ||
777 (PartData
.PartType
== PARTITION_FAT32_XINT13
))
781 else if (PartData
.PartType
== PARTITION_IFS
)
783 PartType
= "NTFS"; /* FIXME: Not quite correct! */
787 PartType
= "Unknown";
790 SetTextXY(6, 8, "Setup will install ReactOS on");
792 PrintTextXY(8, 10, "Partition %lu (%I64u %s) %s on",
798 PrintTextXY(8, 12, "Harddisk %lu (%I64u %s), Port=%hu, Bus=%hu, Id=%hu (%wZ).",
805 &PartData
.DriverName
);
808 SetTextXY(6, 17, "Select a file system for the partition from the list below.");
810 SetTextXY(8, 19, "\xf9 Press UP or DOWN to select a file system.");
811 SetTextXY(8, 21, "\xf9 Press ENTER to format the partition.");
812 SetTextXY(8, 23, "\xf9 Press ESC to select another partition.");
814 /* FIXME: use a real list later */
815 SetInvertedTextXY(6, 26, " Keep current file system (no changes) ");
818 SetStatusText(" ENTER = Continue ESC = Cancel F3 = Quit");
824 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
825 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
827 if (ConfirmQuit(Ir
) == TRUE
)
831 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
832 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
)) /* ESC */
834 return(SELECT_PARTITION_PAGE
);
836 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
838 return(CHECK_FILE_SYSTEM_PAGE
);
842 return(SELECT_FILE_SYSTEM_PAGE
);
847 CheckFileSystemPage(PINPUT_RECORD Ir
)
849 SetTextXY(6, 8, "Check file system");
851 SetTextXY(6, 10, "At present, ReactOS can not check file systems.");
853 SetStatusText(" Please wait ...");
856 SetStatusText(" ENTER = Continue F3 = Quit");
862 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
863 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
865 if (ConfirmQuit(Ir
) == TRUE
)
869 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
871 return(INSTALL_DIRECTORY_PAGE
);
875 return(CHECK_FILE_SYSTEM_PAGE
);
880 InstallDirectoryPage(PINPUT_RECORD Ir
)
882 WCHAR PathBuffer
[MAX_PATH
];
883 WCHAR InstallDir
[51];
886 SetTextXY(6, 8, "Setup installs ReactOS files onto the selected partition. Choose a");
887 SetTextXY(6, 9, "directory where you want ReactOS to be installed:");
889 wcscpy(InstallDir
, L
"\\reactos");
890 Length
= wcslen(InstallDir
);
892 SetInputTextXY(8, 11, 51, InstallDir
);
894 SetTextXY(6, 14, "To change the suggested directory, press BACKSPACE to delete");
895 SetTextXY(6, 15, "characters and then type the directory where you want ReactOS to");
896 SetTextXY(6, 16, "be installed.");
899 SetStatusText(" ENTER = Continue F3 = Quit");
905 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
906 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
908 if (ConfirmQuit(Ir
) == TRUE
)
912 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
914 /* Create 'DestinationPath' string */
915 RtlFreeUnicodeString(&InstallPath
);
916 RtlCreateUnicodeString(&InstallPath
,
919 /* Create 'DestinationPath' string */
920 RtlFreeUnicodeString(&DestinationPath
);
922 DestinationRootPath
.Buffer
);
923 if (InstallDir
[0] != L
'\\')
926 wcscat(PathBuffer
, InstallDir
);
927 RtlCreateUnicodeString(&DestinationPath
,
930 return(PREPARE_COPY_PAGE
);
932 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x08) /* BACKSPACE */
937 InstallDir
[Length
] = 0;
938 SetInputTextXY(8, 11, 51, InstallDir
);
941 else if (isprint(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
))
945 InstallDir
[Length
] = (WCHAR
)Ir
->Event
.KeyEvent
.uChar
.AsciiChar
;
947 InstallDir
[Length
] = 0;
948 SetInputTextXY(8, 11, 51, InstallDir
);
953 return(INSTALL_DIRECTORY_PAGE
);
958 PrepareCopyPage(PINPUT_RECORD Ir
)
960 WCHAR PathBuffer
[MAX_PATH
];
961 PINICACHESECTION DirSection
;
962 PINICACHESECTION FilesSection
;
963 PINICACHEITERATOR Iterator
;
974 SetTextXY(6, 8, "Setup prepares your computer for copying the ReactOS files. ");
977 SetTextXY(8, 12, "Build file copy list");
979 SetTextXY(8, 14, "Create directories");
981 SetStatusText(" Please wait...");
985 * Build the file copy list
987 SetInvertedTextXY(8, 12, "Build file copy list");
990 /* Open 'Directories' section */
991 DirSection
= IniCacheGetSection(IniCache
,
993 if (DirSection
== NULL
)
995 PopupError("Setup failed to find the 'Directories' section\n"
996 "in TXTSETUP.SIF.\n",
997 "ENTER = Reboot computer");
1003 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1010 /* Open 'SourceFiles' section */
1011 FilesSection
= IniCacheGetSection(IniCache
,
1013 if (FilesSection
== NULL
)
1015 PopupError("Setup failed to find the 'SourceFiles' section\n"
1016 "in TXTSETUP.SIF.\n",
1017 "ENTER = Reboot computer");
1023 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1031 /* Create the file queue */
1032 SetupFileQueue
= SetupOpenFileQueue();
1033 if (SetupFileQueue
== NULL
)
1035 PopupError("Setup failed to open the copy file queue.\n",
1036 "ENTER = Reboot computer");
1042 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1050 * Enumerate the files in the 'SourceFiles' section
1051 * and add them to the file queue.
1053 Iterator
= IniCacheFindFirstValue(FilesSection
,
1056 if (Iterator
!= NULL
)
1060 DPRINT("FileKeyName: '%S' FileKeyValue: '%S'\n", FileKeyName
, FileKeyValue
);
1062 /* Lookup target directory */
1063 Status
= IniCacheGetKey(DirSection
,
1066 if (!NT_SUCCESS(Status
))
1068 /* FIXME: Handle error! */
1069 DPRINT1("IniCacheGetKey() failed (Status 0x%lX)\n", Status
);
1072 if (SetupQueueCopy(SetupFileQueue
,
1073 SourceRootPath
.Buffer
,
1079 /* FIXME: Handle error! */
1080 DPRINT1("SetupQueueCopy() failed\n");
1083 while (IniCacheFindNextValue(Iterator
, &FileKeyName
, &FileKeyValue
));
1085 IniCacheFindClose(Iterator
);
1088 /* Report that the file queue has been built */
1089 SetTextXY(8, 12, "Build file copy list");
1090 SetHighlightedTextXY(50, 12, "Done");
1092 /* create directories */
1093 SetInvertedTextXY(8, 14, "Create directories");
1098 * Install directories like '\reactos\test' are not handled yet.
1101 /* Get destination path */
1102 wcscpy(PathBuffer
, DestinationPath
.Buffer
);
1104 /* Remove trailing backslash */
1105 Length
= wcslen(PathBuffer
);
1106 if ((Length
> 0) && (PathBuffer
[Length
- 1] == '\\'))
1107 PathBuffer
[Length
- 1] = 0;
1109 /* Create the install directory */
1110 Status
= CreateDirectory(PathBuffer
);
1111 if (!NT_SUCCESS(Status
) && Status
!= STATUS_OBJECT_NAME_COLLISION
)
1113 DPRINT1("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer
, Status
);
1115 PopupError("Setup could not create the install directory.",
1116 "ENTER = Reboot computer");
1122 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1130 /* Enumerate the directory values and create the subdirectories */
1131 Iterator
= IniCacheFindFirstValue(DirSection
,
1134 if (Iterator
!= NULL
)
1138 if (KeyValue
[0] == L
'\\' && KeyValue
[1] != 0)
1140 DPRINT("Absolute Path: '%S'\n", KeyValue
);
1142 wcscpy(PathBuffer
, DestinationRootPath
.Buffer
);
1143 wcscat(PathBuffer
, KeyValue
);
1145 DPRINT("FullPath: '%S'\n", PathBuffer
);
1147 else if (KeyValue
[0] != L
'\\')
1149 DPRINT("RelativePath: '%S'\n", KeyValue
);
1150 wcscpy(PathBuffer
, DestinationPath
.Buffer
);
1151 wcscat(PathBuffer
, L
"\\");
1152 wcscat(PathBuffer
, KeyValue
);
1154 DPRINT("FullPath: '%S'\n", PathBuffer
);
1156 Status
= CreateDirectory(PathBuffer
);
1157 if (!NT_SUCCESS(Status
) && Status
!= STATUS_OBJECT_NAME_COLLISION
)
1159 DPRINT1("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer
, Status
);
1161 PopupError("Setup could not create install directories.",
1162 "ENTER = Reboot computer");
1168 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1170 IniCacheFindClose(Iterator
);
1177 while (IniCacheFindNextValue(Iterator
, &KeyName
, &KeyValue
));
1179 IniCacheFindClose(Iterator
);
1183 SetTextXY(8, 14, "Create directories");
1184 SetHighlightedTextXY(50, 14, "Done");
1187 SetStatusText(" ENTER = Continue F3 = Quit");
1193 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1194 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1196 if (ConfirmQuit(Ir
) == TRUE
)
1200 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1202 return(FILE_COPY_PAGE
);
1206 return(PREPARE_COPY_PAGE
);
1211 FileCopyCallback(PVOID Context
,
1216 PCOPYCONTEXT CopyContext
;
1218 CopyContext
= (PCOPYCONTEXT
)Context
;
1220 switch (Notification
)
1222 case SPFILENOTIFY_STARTSUBQUEUE
:
1223 CopyContext
->TotalOperations
= (ULONG
)Param2
;
1224 ProgressSetStepCount(CopyContext
->ProgressBar
,
1225 CopyContext
->TotalOperations
);
1228 case SPFILENOTIFY_STARTCOPY
:
1229 /* Display copy message */
1230 PrintTextXYN(6, 16, 60, "Copying file: %S", (PWSTR
)Param1
);
1232 PrintTextXYN(6, 18, 60, "File %lu of %lu",
1233 CopyContext
->CompletedOperations
+ 1,
1234 CopyContext
->TotalOperations
);
1238 case SPFILENOTIFY_ENDCOPY
:
1239 CopyContext
->CompletedOperations
++;
1240 ProgressNextStep(CopyContext
->ProgressBar
);
1249 FileCopyPage(PINPUT_RECORD Ir
)
1251 COPYCONTEXT CopyContext
;
1255 SetStatusText(" Please wait...");
1257 SetTextXY(6, 8, "Copying files");
1259 GetScreenSize(&xScreen
, &yScreen
);
1261 CopyContext
.TotalOperations
= 0;
1262 CopyContext
.CompletedOperations
= 0;
1263 CopyContext
.ProgressBar
= CreateProgressBar(6,
1268 SetupCommitFileQueue(SetupFileQueue
,
1269 DestinationRootPath
.Buffer
,
1271 (PSP_FILE_CALLBACK
)FileCopyCallback
,
1274 SetupCloseFileQueue(SetupFileQueue
);
1276 DestroyProgressBar(CopyContext
.ProgressBar
);
1278 SetStatusText(" ENTER = Continue F3 = Quit");
1284 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1285 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1287 if (ConfirmQuit(Ir
) == TRUE
)
1291 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1293 return(REGISTRY_PAGE
);
1297 return(FILE_COPY_PAGE
);
1303 RegistryPage(PINPUT_RECORD Ir
)
1305 OBJECT_ATTRIBUTES ObjectAttributes
;
1306 UNICODE_STRING KeyName
;
1307 UNICODE_STRING ValueName
;
1311 SetTextXY(6, 8, "Initializing system settings");
1314 SetTextXY(6, 12, "Create registry hives");
1316 SetTextXY(6, 14, "Update registry hives");
1319 SetStatusText(" Please wait...");
1322 /* Create the 'secret' InstallPath key */
1323 RtlInitUnicodeStringFromLiteral(&KeyName
,
1324 L
"\\Registry\\Machine\\HARDWARE");
1325 InitializeObjectAttributes(&ObjectAttributes
,
1327 OBJ_CASE_INSENSITIVE
,
1330 Status
= NtOpenKey(&KeyHandle
,
1333 if (!NT_SUCCESS(Status
))
1335 DPRINT1("NtOpenKey() failed (Status %lx)\n", Status
);
1338 RtlInitUnicodeStringFromLiteral(&ValueName
,
1341 Status
= NtSetValueKey(KeyHandle
,
1345 (PVOID
)DestinationPath
.Buffer
,
1346 DestinationPath
.Length
);
1348 if (!NT_SUCCESS(Status
))
1350 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status
);
1353 /* Create the standard hives */
1354 Status
= NtInitializeRegistry(TRUE
);
1355 if (!NT_SUCCESS(Status
))
1357 DPRINT1("NtInitializeRegistry() failed (Status %lx)\n", Status
);
1362 /* Update registry */
1364 /* FIXME: Create key '\Registry\Machine\System\Setup' */
1366 /* FIXME: Create value 'SystemSetupInProgress' */
1370 SetStatusText(" ENTER = Continue F3 = Quit");
1376 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1377 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1379 if (ConfirmQuit(Ir
) == TRUE
)
1383 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1385 return(BOOT_LOADER_PAGE
);
1389 return(REGISTRY_PAGE
);
1394 BootLoaderPage(PINPUT_RECORD Ir
)
1396 WCHAR SrcPath
[MAX_PATH
];
1397 WCHAR DstPath
[MAX_PATH
];
1399 PINICACHESECTION IniSection
;
1401 SetTextXY(6, 8, "Installing the boot loader");
1403 SetStatusText(" Please wait...");
1405 if (ActivePartitionValid
== FALSE
)
1407 SetTextXY(6, 10, "Error: no active partition found");
1411 if (ActivePartition
.PartType
== PARTITION_ENTRY_UNUSED
)
1413 SetTextXY(6, 10, "Error: active partition invalid (unused)");
1417 if (ActivePartition
.PartType
== 0x0A)
1419 /* OS/2 boot manager partition */
1420 SetTextXY(6, 12, "Found OS/2 boot manager");
1423 else if (ActivePartition
.PartType
== 0x83)
1425 /* Linux ext2 partition */
1426 SetTextXY(6, 12, "Found Linux ext2 partition");
1429 else if (ActivePartition
.PartType
== PARTITION_IFS
)
1431 /* NTFS partition */
1432 SetTextXY(6, 12, "Found NTFS partition");
1435 else if ((ActivePartition
.PartType
== PARTITION_FAT_12
) ||
1436 (ActivePartition
.PartType
== PARTITION_FAT_16
) ||
1437 (ActivePartition
.PartType
== PARTITION_HUGE
) ||
1438 (ActivePartition
.PartType
== PARTITION_XINT13
) ||
1439 (ActivePartition
.PartType
== PARTITION_FAT32
) ||
1440 (ActivePartition
.PartType
== PARTITION_FAT32_XINT13
))
1442 /* FAT or FAT 32 partition */
1443 PrintTextXY(6, 10, "System path: '%wZ'", &SystemRootPath
);
1445 if (DoesFileExist(SystemRootPath
.Buffer
, L
"ntldr") == TRUE
||
1446 DoesFileExist(SystemRootPath
.Buffer
, L
"boot.ini") == TRUE
)
1448 /* Search root directory for 'ntldr' and 'boot.ini'. */
1449 SetTextXY(6, 12, "Found Microsoft Windows NT/2000/XP boot loader");
1453 else if (DoesFileExist(SystemRootPath
.Buffer
, L
"io.sys") == TRUE
||
1454 DoesFileExist(SystemRootPath
.Buffer
, L
"msdos.sys") == TRUE
)
1456 /* Search for root directory for 'io.sys' and 'msdos.sys'. */
1457 SetTextXY(6, 12, "Found Microsoft DOS or Windows 9x boot loader");
1459 /* Copy FreeLoader to the boot partition */
1460 wcscpy(SrcPath
, SourceRootPath
.Buffer
);
1461 wcscat(SrcPath
, L
"\\loader\\freeldr.sys");
1462 wcscpy(DstPath
, SystemRootPath
.Buffer
);
1463 wcscat(DstPath
, L
"\\freeldr.sys");
1465 PrintTextXY(6, 14, "Copy: %S ==> %S", SrcPath
, DstPath
);
1467 SetupCopyFile(SrcPath
, DstPath
);
1469 /* Create freeldr.ini */
1470 wcscpy(DstPath
, SystemRootPath
.Buffer
);
1471 wcscat(DstPath
, L
"\\freeldr.ini");
1473 CreateFreeLoaderIniForDos(DstPath
,
1474 DestinationPath
.Buffer
);
1476 /* Copy current bootsector to 'BOOTSECT.DOS' */
1477 if ((ActivePartition
.PartType
== PARTITION_FAT32
) ||
1478 (ActivePartition
.PartType
== PARTITION_FAT32_XINT13
))
1490 SetTextXY(6, 12, "No or unknown boot loader found");
1496 /* unknown partition */
1497 SetTextXY(6, 12, "Unknown partition found");
1500 SetStatusText(" ENTER = Continue F3 = Quit");
1506 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1507 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1509 if (ConfirmQuit(Ir
) == TRUE
)
1513 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1515 return(SUCCESS_PAGE
);
1519 return(BOOT_LOADER_PAGE
);
1525 QuitPage(PINPUT_RECORD Ir
)
1527 SetTextXY(10, 6, "ReactOS is not completely installed");
1529 SetTextXY(10, 8, "Remove floppy disk from Drive A: and");
1530 SetTextXY(10, 9, "all CD-ROMs from CD-Drive.");
1532 SetTextXY(10, 11, "Press ENTER to reboot your computer.");
1534 SetStatusText(" ENTER = Reboot computer");
1540 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1542 return(REBOOT_PAGE
);
1549 SuccessPage(PINPUT_RECORD Ir
)
1551 SetTextXY(10, 6, "The basic components of ReactOS have been installed successfully.");
1553 SetTextXY(10, 8, "Remove floppy disk from Drive A: and");
1554 SetTextXY(10, 9, "all CD-ROMs from CD-Drive.");
1556 SetTextXY(10, 11, "Press ENTER to reboot your computer.");
1558 SetStatusText(" ENTER = Reboot computer");
1564 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1566 return(REBOOT_PAGE
);
1573 NtProcessStartup(PPEB Peb
)
1579 RtlNormalizeProcessParams(Peb
->ProcessParameters
);
1581 ProcessHeap
= Peb
->ProcessHeap
;
1583 Status
= AllocConsole();
1584 if (!NT_SUCCESS(Status
))
1586 PrintString("AllocConsole() failed (Status = 0x%08lx)\n", Status
);
1588 /* Raise a hard error (crash the system/BSOD) */
1589 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED
,
1593 PartDataValid
= FALSE
;
1595 /* Initialize global unicode strings */
1596 RtlInitUnicodeString(&SourcePath
, NULL
);
1597 RtlInitUnicodeString(&SourceRootPath
, NULL
);
1598 RtlInitUnicodeString(&InstallPath
, NULL
);
1599 RtlInitUnicodeString(&DestinationPath
, NULL
);
1600 RtlInitUnicodeString(&DestinationRootPath
, NULL
);
1601 RtlInitUnicodeString(&SystemRootPath
, NULL
);
1605 while (Page
!= REBOOT_PAGE
)
1609 SetUnderlinedTextXY(4, 3, " ReactOS " KERNEL_VERSION_STR
" Setup ");
1615 Page
= StartPage(&Ir
);
1620 Page
= IntroPage(&Ir
);
1624 case INSTALL_INTRO_PAGE
:
1625 Page
= InstallIntroPage(&Ir
);
1629 case OEM_DRIVER_PAGE
:
1630 Page
= OemDriverPage(&Ir
);
1635 case DEVICE_SETTINGS_PAGE
:
1638 case SELECT_PARTITION_PAGE
:
1639 Page
= SelectPartitionPage(&Ir
);
1642 case SELECT_FILE_SYSTEM_PAGE
:
1643 Page
= SelectFileSystemPage(&Ir
);
1646 case CHECK_FILE_SYSTEM_PAGE
:
1647 Page
= CheckFileSystemPage(&Ir
);
1650 case INSTALL_DIRECTORY_PAGE
:
1651 Page
= InstallDirectoryPage(&Ir
);
1654 case PREPARE_COPY_PAGE
:
1655 Page
= PrepareCopyPage(&Ir
);
1658 case FILE_COPY_PAGE
:
1659 Page
= FileCopyPage(&Ir
);
1663 Page
= RegistryPage(&Ir
);
1666 case BOOT_LOADER_PAGE
:
1667 Page
= BootLoaderPage(&Ir
);
1672 case REPAIR_INTRO_PAGE
:
1673 Page
= RepairIntroPage(&Ir
);
1678 Page
= SuccessPage(&Ir
);
1682 Page
= QuitPage(&Ir
);
1689 NtShutdownSystem(ShutdownReboot
);