3 * Copyright (C) 2002, 2003 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
25 * Casper S. Hornstrup (chorns@users.sourceforge.net)
28 #include <ddk/ntddk.h>
29 #include <ntdll/rtl.h>
31 #include <ntos/minmax.h>
32 #include <reactos/resource.h>
39 #include "filequeue.h"
48 typedef enum _PAGE_NUMBER
54 SELECT_PARTITION_PAGE
,
55 CREATE_PARTITION_PAGE
,
56 SELECT_FILE_SYSTEM_PAGE
,
57 FORMAT_PARTITION_PAGE
,
58 CHECK_FILE_SYSTEM_PAGE
,
60 INSTALL_DIRECTORY_PAGE
,
71 REBOOT_PAGE
, /* virtual page */
72 } PAGE_NUMBER
, *PPAGE_NUMBER
;
74 typedef struct _COPYCONTEXT
76 ULONG TotalOperations
;
77 ULONG CompletedOperations
;
78 PPROGRESS ProgressBar
;
79 } COPYCONTEXT
, *PCOPYCONTEXT
;
82 /* GLOBALS ******************************************************************/
85 UNICODE_STRING SourceRootPath
;
87 /* LOCALS *******************************************************************/
89 static BOOLEAN PartDataValid
;
90 static PARTDATA PartData
;
92 static BOOLEAN ActivePartitionValid
;
93 static PARTDATA ActivePartition
;
95 static UNICODE_STRING SourcePath
;
97 static UNICODE_STRING InstallPath
;
98 static UNICODE_STRING DestinationPath
;
99 static UNICODE_STRING DestinationArcPath
;
100 static UNICODE_STRING DestinationRootPath
;
102 static UNICODE_STRING SystemRootPath
; /* Path to the active partition */
104 static HINF SetupInf
;
106 static HSPFILEQ SetupFileQueue
= NULL
;
108 static PPARTLIST CurrentPartitionList
= NULL
;
109 static PFILE_SYSTEM_LIST CurrentFileSystemList
;
112 /* FUNCTIONS ****************************************************************/
115 PrintString(char* fmt
,...)
119 UNICODE_STRING UnicodeString
;
120 ANSI_STRING AnsiString
;
123 vsprintf(buffer
, fmt
, ap
);
126 RtlInitAnsiString(&AnsiString
, buffer
);
127 RtlAnsiStringToUnicodeString(&UnicodeString
,
130 NtDisplayString(&UnicodeString
);
131 RtlFreeUnicodeString(&UnicodeString
);
136 PopupError(PCHAR Text
,
154 /* Count text lines and longest line */
160 p
= strchr(pnext
, '\n');
163 Length
= strlen(pnext
);
168 Length
= (ULONG
)(p
- pnext
);
173 if (Length
> MaxLength
)
176 if (LastLine
== TRUE
)
182 /* Check length of status line */
185 Length
= strlen(Status
);
186 if (Length
> MaxLength
)
190 GetScreenSize(&xScreen
, &yScreen
);
192 Width
= MaxLength
+ 4;
197 yTop
= (yScreen
- Height
) / 2;
198 xLeft
= (xScreen
- Width
) / 2;
201 /* Set screen attributes */
203 for (coPos
.Y
= yTop
; coPos
.Y
< yTop
+ Height
; coPos
.Y
++)
205 FillConsoleOutputAttribute(0x74,
211 /* draw upper left corner */
214 FillConsoleOutputCharacter(0xDA, // '+',
219 /* draw upper edge */
222 FillConsoleOutputCharacter(0xC4, // '-',
227 /* draw upper right corner */
228 coPos
.X
= xLeft
+ Width
- 1;
230 FillConsoleOutputCharacter(0xBF, // '+',
235 /* Draw right edge, inner space and left edge */
236 for (coPos
.Y
= yTop
+ 1; coPos
.Y
< yTop
+ Height
- 1; coPos
.Y
++)
239 FillConsoleOutputCharacter(0xB3, // '|',
245 FillConsoleOutputCharacter(' ',
250 coPos
.X
= xLeft
+ Width
- 1;
251 FillConsoleOutputCharacter(0xB3, // '|',
257 /* draw lower left corner */
259 coPos
.Y
= yTop
+ Height
- 1;
260 FillConsoleOutputCharacter(0xC0, // '+',
265 /* draw lower edge */
267 coPos
.Y
= yTop
+ Height
- 1;
268 FillConsoleOutputCharacter(0xC4, // '-',
273 /* draw lower right corner */
274 coPos
.X
= xLeft
+ Width
- 1;
275 coPos
.Y
= yTop
+ Height
- 1;
276 FillConsoleOutputCharacter(0xD9, // '+',
281 /* Print message text */
286 p
= strchr(pnext
, '\n');
289 Length
= strlen(pnext
);
294 Length
= (ULONG
)(p
- pnext
);
301 WriteConsoleOutputCharacters(pnext
,
306 if (LastLine
== TRUE
)
313 /* Print separator line and status text */
316 coPos
.Y
= yTop
+ Height
- 3;
318 FillConsoleOutputCharacter(0xC3, // '+',
324 FillConsoleOutputCharacter(0xC4, // '-',
329 coPos
.X
= xLeft
+ Width
- 1;
330 FillConsoleOutputCharacter(0xB4, // '+',
337 WriteConsoleOutputCharacters(Status
,
338 min(strlen(Status
), Width
- 4),
348 * FALSE: Don't quit setup.
351 ConfirmQuit(PINPUT_RECORD Ir
)
355 PopupError("ReactOS is not completely installed on your\n"
356 "computer. If you quit Setup now, you will need to\n"
357 "run Setup again to install ReactOS.\n"
359 " * Press ENTER to continue Setup.\n"
360 " * Press F3 to quit Setup.",
361 "F3= Quit ENTER = Continue");
367 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
368 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
373 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
388 * Number of the next page.
391 StartPage(PINPUT_RECORD Ir
)
394 WCHAR FileNameBuffer
[MAX_PATH
];
395 UNICODE_STRING FileName
;
400 SetStatusText(" Please wait...");
402 Status
= GetSourcePaths(&SourcePath
,
404 if (!NT_SUCCESS(Status
))
406 PrintTextXY(6, 15, "GetSourcePath() failed (Status 0x%08lx)", Status
);
407 PopupError("Setup could not find its source drive.\n",
408 "ENTER = Reboot computer");
413 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
422 PrintTextXY(6, 15, "SourcePath: '%wZ'", &SourcePath
);
423 PrintTextXY(6, 16, "SourceRootPath: '%wZ'", &SourceRootPath
);
427 /* Load txtsetup.sif from install media. */
428 wcscpy(FileNameBuffer
, SourceRootPath
.Buffer
);
429 wcscat(FileNameBuffer
, L
"\\reactos\\txtsetup.sif");
430 RtlInitUnicodeString(&FileName
,
433 Status
= InfOpenFile(&SetupInf
,
436 if (!NT_SUCCESS(Status
))
438 PopupError("Setup failed to load the file TXTSETUP.SIF.\n",
439 "ENTER = Reboot computer");
445 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
452 /* Open 'Version' section */
453 if (!InfFindFirstLine (SetupInf
, L
"Version", L
"Signature", &Context
))
455 PopupError("Setup found a corrupt TXTSETUP.SIF.\n",
456 "ENTER = Reboot computer");
462 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
470 /* Get pointer 'Signature' key */
471 if (!InfGetData (&Context
, NULL
, &Value
))
473 PopupError("Setup found a corrupt TXTSETUP.SIF.\n",
474 "ENTER = Reboot computer");
480 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
487 /* Check 'Signature' string */
488 if (_wcsicmp(Value
, L
"$ReactOS$") != 0)
490 PopupError("Setup found an invalid signature in TXTSETUP.SIF.\n",
491 "ENTER = Reboot computer");
497 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
514 IntroPage(PINPUT_RECORD Ir
)
516 SetHighlightedTextXY(6, 8, "Welcome to ReactOS Setup");
518 SetTextXY(6, 11, "This part of the setup copies the ReactOS Operating System to your");
519 SetTextXY(6, 12, "computer and prepares the second part of the setup.");
521 SetTextXY(8, 15, "\xfa Press ENTER to install ReactOS.");
523 SetTextXY(8, 17, "\xfa Press E to start the emergency console.");
525 SetTextXY(8, 19, "\xfa Press R to repair ReactOS.");
527 SetTextXY(8, 21, "\xfa Press F3 to quit without installing ReactOS.");
530 SetStatusText(" ENTER = Continue F3 = Quit");
536 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
537 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
539 if (ConfirmQuit(Ir
) == TRUE
)
543 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
545 return(INSTALL_INTRO_PAGE
);
547 else if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'E') /* E */
549 return(EMERGENCY_INTRO_PAGE
);
551 else if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'R') /* R */
553 return(REPAIR_INTRO_PAGE
);
562 EmergencyIntroPage(PINPUT_RECORD Ir
)
564 SetTextXY(6, 8, "ReactOS Setup is in an early development phase. It does not yet");
565 SetTextXY(6, 9, "support all the functions of a fully usable setup application.");
567 SetTextXY(6, 12, "The emergency console is not implemented yet.");
569 SetTextXY(8, 15, "\xfa Press ESC to return to the main page.");
571 SetTextXY(8, 17, "\xfa Press ENTER to reboot your computer.");
573 SetStatusText(" ESC = Main page ENTER = Reboot");
579 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
583 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
584 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
)) /* ESC */
590 return(REPAIR_INTRO_PAGE
);
595 RepairIntroPage(PINPUT_RECORD Ir
)
597 SetTextXY(6, 8, "ReactOS Setup is in an early development phase. It does not yet");
598 SetTextXY(6, 9, "support all the functions of a fully usable setup application.");
600 SetTextXY(6, 12, "The repair functions are not implemented yet.");
602 SetTextXY(8, 15, "\xfa Press ESC to return to the main page.");
604 SetTextXY(8, 17, "\xfa Press ENTER to reboot your computer.");
606 SetStatusText(" ESC = Main page ENTER = Reboot");
612 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
616 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
617 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
)) /* ESC */
623 return(REPAIR_INTRO_PAGE
);
628 InstallIntroPage(PINPUT_RECORD Ir
)
630 SetTextXY(6, 8, "ReactOS Setup is in an early development phase. It does not yet");
631 SetTextXY(6, 9, "support all the functions of a fully usable setup application.");
633 SetTextXY(6, 12, "The following functions are missing:");
634 SetTextXY(8, 13, "- Creating and deleting harddisk partitions.");
635 SetTextXY(8, 14, "- Formatting partitions.");
636 SetTextXY(8, 15, "- Support for non-FAT file systems.");
637 SetTextXY(8, 16, "- Checking file systems.");
641 SetTextXY(8, 21, "\xfa Press ENTER to install ReactOS.");
643 SetTextXY(8, 23, "\xfa Press F3 to quit without installing ReactOS.");
646 SetStatusText(" ENTER = Continue F3 = Quit");
652 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
653 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
655 if (ConfirmQuit(Ir
) == TRUE
)
659 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
661 return(SELECT_PARTITION_PAGE
);
665 return(INSTALL_INTRO_PAGE
);
670 * Confirm delete partition
672 * TRUE: Delete currently selected partition.
673 * FALSE: Don't delete currently selected partition.
676 ConfirmDeletePartition(PINPUT_RECORD Ir
)
680 PopupError("Are you sure you want to delete this partition?\n"
682 " * Press ENTER to delete the partition.\n"
683 " * Press ESC to NOT delete the partition.",
684 "ESC = Cancel ENTER = Delete partition");
690 if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
) /* ESC */
695 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
707 SelectPartitionPage(PINPUT_RECORD Ir
)
709 WCHAR PathBuffer
[MAX_PATH
];
714 SetTextXY(6, 8, "The list below shows existing partitions and unused disk");
715 SetTextXY(6, 9, "space for new partitions.");
717 SetTextXY(8, 11, "\xfa Press UP or DOWN to select a list entry.");
718 SetTextXY(8, 13, "\xfa Press ENTER to install ReactOS onto the selected partition.");
719 SetTextXY(8, 15, "\xfa Press C to create a new partition.");
720 SetTextXY(8, 17, "\xfa Press D to delete an existing partition.");
722 SetStatusText(" Please wait...");
724 RtlFreeUnicodeString(&DestinationPath
);
725 RtlFreeUnicodeString(&DestinationRootPath
);
727 GetScreenSize(&xScreen
, &yScreen
);
729 PartList
= CreatePartitionList(2, 19, xScreen
- 3, yScreen
- 3);
730 if (PartList
== NULL
)
732 /* FIXME: show an error dialog */
736 if (CurrentPartitionList
!= NULL
)
738 DestroyPartitionList(CurrentPartitionList
);
740 CurrentPartitionList
= PartList
;
742 SetStatusText(" ENTER = Continue F3 = Quit");
748 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
749 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
751 if (ConfirmQuit(Ir
) == TRUE
)
753 DestroyPartitionList(PartList
);
758 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
759 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
761 ScrollDownPartitionList(PartList
);
763 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
764 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
766 ScrollUpPartitionList(PartList
);
768 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
770 PartDataValid
= GetSelectedPartition(PartList
,
774 ActivePartitionValid
= GetActiveBootPartition(PartList
,
777 RtlFreeUnicodeString(&DestinationRootPath
);
779 L
"\\Device\\Harddisk%lu\\Partition%lu",
781 PartData
.PartNumber
);
782 RtlCreateUnicodeString(&DestinationRootPath
,
785 RtlFreeUnicodeString(&SystemRootPath
);
787 if (ActivePartitionValid
)
790 L
"\\Device\\Harddisk%lu\\Partition%lu",
791 ActivePartition
.DiskNumber
,
792 ActivePartition
.PartNumber
);
796 /* We mark the selected partition as bootable */
798 L
"\\Device\\Harddisk%lu\\Partition%lu",
800 PartData
.PartNumber
);
802 RtlCreateUnicodeString(&SystemRootPath
,
805 return(SELECT_FILE_SYSTEM_PAGE
);
809 /* FIXME: show an error dialog */
810 return(SELECT_PARTITION_PAGE
);
814 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_C
) /* C */
816 /* Don't destroy the parition list here */;
817 return(CREATE_PARTITION_PAGE
);
819 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_D
) /* D */
821 if (ConfirmDeletePartition(Ir
) == TRUE
)
823 (BOOLEAN
) DeleteSelectedPartition(CurrentPartitionList
);
825 return(SELECT_PARTITION_PAGE
);
829 /* FIXME: Update status text */
833 return(SELECT_PARTITION_PAGE
);
837 DrawInputField(ULONG FieldLength
,
847 memset(buf
, '_', sizeof(buf
));
848 buf
[FieldLength
- strlen(FieldContent
)] = 0;
849 strcat(buf
, FieldContent
);
850 WriteConsoleOutputCharacters(buf
,
855 #define PARTITION_SIZE_INPUT_FIELD_LENGTH 6
858 ShowPartitionSizeInputBox(ULONG MaxSize
,
884 GetScreenSize(&xScreen
, &yScreen
);
887 Right
= xScreen
- 12;
890 /* draw upper left corner */
893 FillConsoleOutputCharacter(0xDA, // '+',
898 /* draw upper edge */
901 FillConsoleOutputCharacter(0xC4, // '-',
906 /* draw upper right corner */
909 FillConsoleOutputCharacter(0xBF, // '+',
914 /* draw left and right edge */
915 for (i
= Top
+ 1; i
< Bottom
; i
++)
919 FillConsoleOutputCharacter(0xB3, // '|',
925 FillConsoleOutputCharacter(0xB3, //'|',
931 /* draw lower left corner */
934 FillConsoleOutputCharacter(0xC0, // '+',
939 /* draw lower edge */
942 FillConsoleOutputCharacter(0xC4, // '-',
947 /* draw lower right corner */
950 FillConsoleOutputCharacter(0xD9, // '+',
958 strcpy(buf
, "Size of new partition:");
959 iLeft
= coPos
.X
+ strlen(buf
) + 1;
961 WriteConsoleOutputCharacters(buf
,
965 sprintf(buf
, "MB (max. %d MB)", MaxSize
/ (1024 * 1024));
966 coPos
.X
= iLeft
+ PARTITION_SIZE_INPUT_FIELD_LENGTH
+ 1;
968 WriteConsoleOutputCharacters(buf
,
974 DrawInputField(PARTITION_SIZE_INPUT_FIELD_LENGTH
, iLeft
, iTop
, buf
);
979 if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
980 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
987 else if (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
991 else if (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
) /* ESCAPE */
998 else if ((Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_BACK
) && (index
> 0)) /* BACKSPACE */
1002 DrawInputField(PARTITION_SIZE_INPUT_FIELD_LENGTH
, iLeft
, iTop
, buf
);
1004 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
!= 0x00)
1005 && (index
< PARTITION_SIZE_INPUT_FIELD_LENGTH
))
1007 ch
= Ir
.Event
.KeyEvent
.uChar
.AsciiChar
;
1008 if ((ch
>= '0') && (ch
<= '9'))
1013 DrawInputField(PARTITION_SIZE_INPUT_FIELD_LENGTH
, iLeft
, iTop
, buf
);
1017 strcpy(InputBuffer
, buf
);
1023 CreatePartitionPage(PINPUT_RECORD Ir
)
1026 WCHAR PathBuffer
[MAX_PATH
];
1028 PPARTENTRY PartEntry
;
1033 CHAR InputBuffer
[50];
1037 SetTextXY(6, 8, "You have chosen to create a new partition in the unused disk space.");
1038 SetTextXY(6, 9, "Please enter the size of the new partition in megabytes.");
1040 SetStatusText(" Please wait...");
1042 GetScreenSize(&xScreen
, &yScreen
);
1044 PartList
= CurrentPartitionList
;
1046 SetStatusText(" ENTER = Continue ESC = Cancel F3 = Quit");
1048 PartEntry
= &PartList
->DiskArray
[PartList
->CurrentDisk
].PartArray
[PartList
->CurrentPartition
];
1051 MaxSize
= PartEntry
->PartSize
;
1052 ShowPartitionSizeInputBox(MaxSize
, InputBuffer
, &Quit
, &Cancel
);
1055 if (ConfirmQuit(Ir
) == TRUE
)
1057 DestroyPartitionList(PartList
);
1061 else if (Cancel
== TRUE
)
1067 PartSize
= atoi(InputBuffer
);
1073 /* Convert to bytes */
1074 PartSize
*= 1024 * 1024;
1076 if (PartSize
> PartEntry
->PartSize
)
1082 // assert(PartEntry->Unpartitioned == TRUE);
1083 PartEntry
->PartType
= PARTITION_ENTRY_UNUSED
;
1084 PartEntry
->Used
= TRUE
;
1086 PartDataValid
= GetSelectedPartition(PartList
,
1090 PartData
.CreatePartition
= TRUE
;
1091 PartData
.NewPartSize
= PartSize
;
1093 ActivePartitionValid
= GetActiveBootPartition(PartList
,
1096 RtlFreeUnicodeString(&DestinationRootPath
);
1097 swprintf(PathBuffer
,
1098 L
"\\Device\\Harddisk%lu\\Partition%lu",
1099 PartData
.DiskNumber
,
1100 PartData
.PartNumber
);
1101 RtlCreateUnicodeString(&DestinationRootPath
,
1104 RtlFreeUnicodeString(&SystemRootPath
);
1106 if (ActivePartitionValid
)
1108 swprintf(PathBuffer
,
1109 L
"\\Device\\Harddisk%lu\\Partition%lu",
1110 ActivePartition
.DiskNumber
,
1111 ActivePartition
.PartNumber
);
1115 /* We mark the selected partition as bootable */
1116 swprintf(PathBuffer
,
1117 L
"\\Device\\Harddisk%lu\\Partition%lu",
1118 PartData
.DiskNumber
,
1119 PartData
.PartNumber
);
1121 RtlCreateUnicodeString(&SystemRootPath
,
1124 return(SELECT_FILE_SYSTEM_PAGE
);
1128 /* FIXME: show an error dialog */
1129 return(SELECT_PARTITION_PAGE
);
1134 return(SELECT_PARTITION_PAGE
);
1139 static PFILE_SYSTEM_LIST
1140 CreateFileSystemList(SHORT Left
,
1142 BOOLEAN ForceFormat
,
1143 FILE_SYSTEM ForceFileSystem
)
1145 PFILE_SYSTEM_LIST List
;
1147 List
= (PFILE_SYSTEM_LIST
)RtlAllocateHeap(ProcessHeap
, 0, sizeof(FILE_SYSTEM_LIST
));
1154 List
->ForceFormat
= ForceFormat
;
1155 List
->FileSystemCount
= 1;
1158 List
->CurrentFileSystem
= ForceFileSystem
;
1162 List
->FileSystemCount
++;
1163 List
->CurrentFileSystem
= FsKeep
;
1170 DestroyFileSystemList(PFILE_SYSTEM_LIST List
)
1172 RtlFreeHeap(ProcessHeap
, 0, List
);
1177 DrawFileSystemList(PFILE_SYSTEM_LIST List
)
1185 coPos
.X
= List
->Left
;
1186 coPos
.Y
= List
->Top
+ index
;
1187 FillConsoleOutputAttribute(0x17,
1191 FillConsoleOutputCharacter(' ',
1196 if (List
->CurrentFileSystem
== FsFat
)
1198 SetInvertedTextXY(List
->Left
, List
->Top
+ index
, " Format partition as FAT file system ");
1202 SetTextXY(List
->Left
, List
->Top
+ index
, " Format partition as FAT file system ");
1206 if (!List
->ForceFormat
)
1208 coPos
.X
= List
->Left
;
1209 coPos
.Y
= List
->Top
+ index
;
1210 FillConsoleOutputAttribute(0x17,
1214 FillConsoleOutputCharacter(' ',
1219 if (List
->CurrentFileSystem
== FsKeep
)
1221 SetInvertedTextXY(List
->Left
, List
->Top
+ index
, " Keep current file system (no changes) ");
1225 SetTextXY(List
->Left
, List
->Top
+ index
, " Keep current file system (no changes) ");
1232 ScrollDownFileSystemList(PFILE_SYSTEM_LIST List
)
1234 if ((ULONG
) List
->CurrentFileSystem
< List
->FileSystemCount
- 1)
1236 (ULONG
) List
->CurrentFileSystem
++;
1237 DrawFileSystemList(List
);
1243 ScrollUpFileSystemList(PFILE_SYSTEM_LIST List
)
1245 if ((ULONG
) List
->CurrentFileSystem
> 0)
1247 (ULONG
) List
->CurrentFileSystem
--;
1248 DrawFileSystemList(List
);
1254 SelectFileSystemPage(PINPUT_RECORD Ir
)
1256 PFILE_SYSTEM_LIST FileSystemList
;
1257 BOOLEAN ForceFormat
;
1264 if (PartDataValid
== FALSE
)
1266 /* FIXME: show an error dialog */
1270 /* adjust disk size */
1271 if (PartData
.DiskSize
>= 0x280000000ULL
) /* 10 GB */
1273 DiskSize
= (PartData
.DiskSize
+ (1 << 29)) >> 30;
1278 DiskSize
= (PartData
.DiskSize
+ (1 << 19)) >> 20;
1282 /* adjust partition size */
1283 if (PartData
.PartSize
>= 0x280000000ULL
) /* 10 GB */
1285 PartSize
= (PartData
.PartSize
+ (1 << 29)) >> 30;
1290 PartSize
= (PartData
.PartSize
+ (1 << 19)) >> 20;
1294 /* adjust partition type */
1295 if ((PartData
.PartType
== PARTITION_FAT_12
) ||
1296 (PartData
.PartType
== PARTITION_FAT_16
) ||
1297 (PartData
.PartType
== PARTITION_HUGE
) ||
1298 (PartData
.PartType
== PARTITION_XINT13
))
1302 else if ((PartData
.PartType
== PARTITION_FAT32
) ||
1303 (PartData
.PartType
== PARTITION_FAT32_XINT13
))
1307 else if (PartData
.PartType
== PARTITION_IFS
)
1309 PartType
= "NTFS"; /* FIXME: Not quite correct! */
1311 else if (PartData
.PartType
== PARTITION_ENTRY_UNUSED
)
1313 PartType
= "Unused";
1317 PartType
= "Unknown";
1320 SetTextXY(6, 8, "Setup will install ReactOS on");
1322 PrintTextXY(8, 10, "Partition %lu (%I64u %s) %s of",
1323 PartData
.PartNumber
,
1328 PrintTextXY(8, 12, "Harddisk %lu (%I64u %s), Port=%hu, Bus=%hu, Id=%hu (%wZ).",
1329 PartData
.DiskNumber
,
1335 &PartData
.DriverName
);
1338 SetTextXY(6, 17, "Select a file system for the partition from the list below.");
1340 SetTextXY(8, 19, "\xfa Press UP or DOWN to select a file system.");
1341 SetTextXY(8, 21, "\xfa Press ENTER to format the partition.");
1342 SetTextXY(8, 23, "\xfa Press ESC to select another partition.");
1344 ForceFormat
= (PartData
.PartType
== PARTITION_ENTRY_UNUSED
);
1345 FileSystemList
= CreateFileSystemList(6, 26, ForceFormat
, FsFat
);
1346 if (FileSystemList
== NULL
)
1348 /* FIXME: show an error dialog */
1352 CurrentFileSystemList
= FileSystemList
;
1354 DrawFileSystemList(FileSystemList
);
1356 SetStatusText(" ENTER = Continue ESC = Cancel F3 = Quit");
1362 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1363 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1365 if (ConfirmQuit(Ir
) == TRUE
)
1369 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1370 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
)) /* ESC */
1372 DestroyFileSystemList(FileSystemList
);
1373 return(SELECT_PARTITION_PAGE
);
1375 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1376 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
1378 ScrollDownFileSystemList(FileSystemList
);
1380 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1381 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
1383 ScrollUpFileSystemList(FileSystemList
);
1385 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
1387 if (FileSystemList
->CurrentFileSystem
== FsKeep
)
1389 return(CHECK_FILE_SYSTEM_PAGE
);
1393 return(FORMAT_PARTITION_PAGE
);
1401 FormatPartitionPage(PINPUT_RECORD Ir
)
1407 SetTextXY(6, 8, "Format partition");
1409 SetTextXY(6, 10, "Setup will now format the partition. Press ENTER to continue.");
1411 SetStatusText(" ENTER = Continue F3 = Quit");
1417 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1418 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1420 if (ConfirmQuit(Ir
) == TRUE
)
1426 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
1428 SetStatusText(" Please wait ...");
1430 switch (CurrentFileSystemList
->CurrentFileSystem
)
1433 PartType
= PARTITION_FAT32_XINT13
;
1441 if (PartData
.CreatePartition
)
1443 Valid
= CreateSelectedPartition(CurrentPartitionList
, PartType
, PartData
.NewPartSize
);
1446 DPRINT("CreateSelectedPartition() failed\n");
1447 /* FIXME: show an error dialog */
1452 switch (CurrentFileSystemList
->CurrentFileSystem
)
1455 Status
= FormatPartition(&DestinationRootPath
);
1456 if (!NT_SUCCESS(Status
))
1458 DPRINT1("FormatPartition() failed with status 0x%.08x\n", Status
);
1459 /* FIXME: show an error dialog */
1468 return(INSTALL_DIRECTORY_PAGE
);
1472 return(INSTALL_DIRECTORY_PAGE
);
1476 CheckFileSystemPage(PINPUT_RECORD Ir
)
1478 SetTextXY(6, 8, "Check file system");
1480 SetTextXY(6, 10, "At present, ReactOS can not check file systems.");
1482 SetStatusText(" Please wait ...");
1485 SetStatusText(" ENTER = Continue F3 = Quit");
1491 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1492 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1494 if (ConfirmQuit(Ir
) == TRUE
)
1498 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1500 return(INSTALL_DIRECTORY_PAGE
);
1504 return(CHECK_FILE_SYSTEM_PAGE
);
1509 InstallDirectoryPage(PINPUT_RECORD Ir
)
1511 WCHAR PathBuffer
[MAX_PATH
];
1512 WCHAR InstallDir
[51];
1518 /* Search for 'DefaultPath' in the 'SetupData' section */
1519 if (!InfFindFirstLine (SetupInf
, L
"SetupData", L
"DefaultPath", &Context
))
1521 PopupError("Setup failed to find the 'SetupData' section\n"
1522 "in TXTSETUP.SIF.\n",
1523 "ENTER = Reboot computer");
1529 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1536 /* Read the 'DefaultPath' data */
1537 if (InfGetData (&Context
, NULL
, &DefaultPath
))
1539 wcscpy(InstallDir
, DefaultPath
);
1543 wcscpy(InstallDir
, L
"\\ReactOS");
1545 Length
= wcslen(InstallDir
);
1547 SetTextXY(6, 8, "Setup installs ReactOS files onto the selected partition. Choose a");
1548 SetTextXY(6, 9, "directory where you want ReactOS to be installed:");
1550 SetInputTextXY(8, 11, 51, InstallDir
);
1552 SetTextXY(6, 14, "To change the suggested directory, press BACKSPACE to delete");
1553 SetTextXY(6, 15, "characters and then type the directory where you want ReactOS to");
1554 SetTextXY(6, 16, "be installed.");
1556 SetStatusText(" ENTER = Continue F3 = Quit");
1562 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1563 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1565 if (ConfirmQuit(Ir
) == TRUE
)
1569 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1571 /* Create 'InstallPath' string */
1572 RtlFreeUnicodeString(&InstallPath
);
1573 RtlCreateUnicodeString(&InstallPath
,
1576 /* Create 'DestinationPath' string */
1577 RtlFreeUnicodeString(&DestinationPath
);
1579 DestinationRootPath
.Buffer
);
1580 if (InstallDir
[0] != L
'\\')
1583 wcscat(PathBuffer
, InstallDir
);
1584 RtlCreateUnicodeString(&DestinationPath
,
1587 /* Create 'DestinationArcPath' */
1588 RtlFreeUnicodeString(&DestinationArcPath
);
1589 swprintf(PathBuffer
,
1590 L
"multi(0)disk(0)rdisk(%lu)partition(%lu)",
1591 PartData
.DiskNumber
,
1592 PartData
.PartNumber
);
1593 if (InstallDir
[0] != L
'\\')
1596 wcscat(PathBuffer
, InstallDir
);
1597 RtlCreateUnicodeString(&DestinationArcPath
,
1600 return(PREPARE_COPY_PAGE
);
1602 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x08) /* BACKSPACE */
1607 InstallDir
[Length
] = 0;
1608 SetInputTextXY(8, 11, 51, InstallDir
);
1611 else if (isprint(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
))
1615 InstallDir
[Length
] = (WCHAR
)Ir
->Event
.KeyEvent
.uChar
.AsciiChar
;
1617 InstallDir
[Length
] = 0;
1618 SetInputTextXY(8, 11, 51, InstallDir
);
1623 return(INSTALL_DIRECTORY_PAGE
);
1628 PrepareCopyPage(PINPUT_RECORD Ir
)
1630 WCHAR PathBuffer
[MAX_PATH
];
1631 INFCONTEXT FilesContext
;
1632 INFCONTEXT DirContext
;
1639 PWCHAR FileKeyValue
;
1643 SetTextXY(6, 8, "Setup prepares your computer for copying the ReactOS files. ");
1647 * Build the file copy list
1649 SetStatusText(" Building the file copy list...");
1651 /* Search for the 'SourceFiles' section */
1652 if (!InfFindFirstLine (SetupInf
, L
"SourceFiles", NULL
, &FilesContext
))
1654 PopupError("Setup failed to find the 'SourceFiles' section\n"
1655 "in TXTSETUP.SIF.\n",
1656 "ENTER = Reboot computer");
1662 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1670 /* Create the file queue */
1671 SetupFileQueue
= SetupOpenFileQueue();
1672 if (SetupFileQueue
== NULL
)
1674 PopupError("Setup failed to open the copy file queue.\n",
1675 "ENTER = Reboot computer");
1681 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1689 * Enumerate the files in the 'SourceFiles' section
1690 * and add them to the file queue.
1694 if (!InfGetData (&FilesContext
, &FileKeyName
, &FileKeyValue
))
1697 DPRINT1("FileKeyName: '%S' FileKeyValue: '%S'\n", FileKeyName
, FileKeyValue
);
1699 /* Lookup target directory */
1700 if (!InfFindFirstLine (SetupInf
, L
"Directories", FileKeyValue
, &DirContext
))
1702 /* FIXME: Handle error! */
1703 DPRINT1("InfFindFirstLine() failed\n");
1707 if (!InfGetData (&DirContext
, NULL
, &DirKeyValue
))
1709 /* FIXME: Handle error! */
1710 DPRINT1("InfGetData() failed\n");
1714 if (!SetupQueueCopy(SetupFileQueue
,
1715 SourceRootPath
.Buffer
,
1721 /* FIXME: Handle error! */
1722 DPRINT1("SetupQueueCopy() failed\n");
1725 while (InfFindNextLine(&FilesContext
, &FilesContext
));
1728 /* Create directories */
1729 SetStatusText(" Creating directories...");
1733 * Install directories like '\reactos\test' are not handled yet.
1736 /* Get destination path */
1737 wcscpy(PathBuffer
, DestinationPath
.Buffer
);
1739 /* Remove trailing backslash */
1740 Length
= wcslen(PathBuffer
);
1741 if ((Length
> 0) && (PathBuffer
[Length
- 1] == '\\'))
1743 PathBuffer
[Length
- 1] = 0;
1746 /* Create the install directory */
1747 Status
= CreateDirectory(PathBuffer
);
1748 if (!NT_SUCCESS(Status
) && Status
!= STATUS_OBJECT_NAME_COLLISION
)
1750 DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer
, Status
);
1751 PopupError("Setup could not create the install directory.",
1752 "ENTER = Reboot computer");
1758 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1766 /* Search for the 'Directories' section */
1767 if (!InfFindFirstLine(SetupInf
, L
"Directories", NULL
, &DirContext
))
1769 PopupError("Setup failed to find the 'Directories' section\n"
1770 "in TXTSETUP.SIF.\n",
1771 "ENTER = Reboot computer");
1777 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1784 /* Enumerate the directory values and create the subdirectories */
1787 if (!InfGetData (&DirContext
, NULL
, &KeyValue
))
1790 if (KeyValue
[0] == L
'\\' && KeyValue
[1] != 0)
1792 DPRINT("Absolute Path: '%S'\n", KeyValue
);
1794 wcscpy(PathBuffer
, DestinationRootPath
.Buffer
);
1795 wcscat(PathBuffer
, KeyValue
);
1797 DPRINT("FullPath: '%S'\n", PathBuffer
);
1799 else if (KeyValue
[0] != L
'\\')
1801 DPRINT("RelativePath: '%S'\n", KeyValue
);
1802 wcscpy(PathBuffer
, DestinationPath
.Buffer
);
1803 wcscat(PathBuffer
, L
"\\");
1804 wcscat(PathBuffer
, KeyValue
);
1806 DPRINT("FullPath: '%S'\n", PathBuffer
);
1808 Status
= CreateDirectory(PathBuffer
);
1809 if (!NT_SUCCESS(Status
) && Status
!= STATUS_OBJECT_NAME_COLLISION
)
1811 DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer
, Status
);
1812 PopupError("Setup could not create install directories.",
1813 "ENTER = Reboot computer");
1819 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1827 while (InfFindNextLine (&DirContext
, &DirContext
));
1829 return(FILE_COPY_PAGE
);
1834 FileCopyCallback(PVOID Context
,
1839 PCOPYCONTEXT CopyContext
;
1841 CopyContext
= (PCOPYCONTEXT
)Context
;
1843 switch (Notification
)
1845 case SPFILENOTIFY_STARTSUBQUEUE
:
1846 CopyContext
->TotalOperations
= (ULONG
)Param2
;
1847 ProgressSetStepCount(CopyContext
->ProgressBar
,
1848 CopyContext
->TotalOperations
);
1851 case SPFILENOTIFY_STARTCOPY
:
1852 /* Display copy message */
1853 PrintTextXYN(6, 16, 60, "Copying file: %S", (PWSTR
)Param1
);
1855 PrintTextXYN(6, 18, 60, "File %lu of %lu",
1856 CopyContext
->CompletedOperations
+ 1,
1857 CopyContext
->TotalOperations
);
1860 case SPFILENOTIFY_ENDCOPY
:
1861 CopyContext
->CompletedOperations
++;
1862 ProgressNextStep(CopyContext
->ProgressBar
);
1871 FileCopyPage(PINPUT_RECORD Ir
)
1873 COPYCONTEXT CopyContext
;
1877 SetStatusText(" Please wait...");
1879 SetTextXY(6, 8, "Copying files");
1881 GetScreenSize(&xScreen
, &yScreen
);
1883 CopyContext
.TotalOperations
= 0;
1884 CopyContext
.CompletedOperations
= 0;
1885 CopyContext
.ProgressBar
= CreateProgressBar(6,
1890 SetupCommitFileQueue(SetupFileQueue
,
1891 DestinationRootPath
.Buffer
,
1893 (PSP_FILE_CALLBACK
)FileCopyCallback
,
1896 SetupCloseFileQueue(SetupFileQueue
);
1898 DestroyProgressBar(CopyContext
.ProgressBar
);
1900 return(REGISTRY_PAGE
);
1905 RegistryPage(PINPUT_RECORD Ir
)
1907 INFCONTEXT InfContext
;
1916 SetTextXY(6, 8, "Setup is updating the system configuration");
1918 SetStatusText(" Creating registry hives...");
1920 if (!SetInstallPathValue(&DestinationPath
))
1922 DPRINT("SetInstallPathValue() failed\n");
1923 PopupError("Setup failed to set the initialize the registry.",
1924 "ENTER = Reboot computer");
1930 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1937 /* Create the default hives */
1938 Status
= NtInitializeRegistry(TRUE
);
1939 if (!NT_SUCCESS(Status
))
1941 DPRINT("NtInitializeRegistry() failed (Status %lx)\n", Status
);
1942 PopupError("Setup failed to create the registry hives.",
1943 "ENTER = Reboot computer");
1949 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1956 /* Update registry */
1957 SetStatusText(" Updating registry hives...");
1959 if (!InfFindFirstLine(SetupInf
, L
"HiveInfs.Install", NULL
, &InfContext
))
1961 DPRINT1("InfFindFirstLine() failed\n");
1962 PopupError("Setup failed to find the registry data files.",
1963 "ENTER = Reboot computer");
1969 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1978 InfGetDataField (&InfContext
, 0, &Action
);
1979 InfGetDataField (&InfContext
, 1, &File
);
1980 InfGetDataField (&InfContext
, 2, &Section
);
1982 DPRINT1("Action: %S File: %S Section %S\n", Action
, File
, Section
);
1984 if (!_wcsicmp (Action
, L
"AddReg"))
1988 else if (!_wcsicmp (Action
, L
"DelReg"))
1997 SetStatusText(" Importing %S...", File
);
1999 if (!ImportRegistryFile(File
, Section
, Delete
))
2001 DPRINT1("Importing %S failed\n", File
);
2003 PopupError("Setup failed to import a hive file.",
2004 "ENTER = Reboot computer");
2010 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
2017 while (InfFindNextLine (&InfContext
, &InfContext
));
2019 SetStatusText(" Done...");
2021 return(BOOT_LOADER_PAGE
);
2026 BootLoaderPage(PINPUT_RECORD Ir
)
2028 WCHAR SrcPath
[MAX_PATH
];
2029 WCHAR DstPath
[MAX_PATH
];
2031 PINICACHESECTION IniSection
;
2033 BOOLEAN InstallMBR
= FALSE
;
2035 SetTextXY(6, 8, "Installing the boot loader");
2037 SetStatusText(" Please wait...");
2040 if (ActivePartitionValid
== FALSE
)
2042 /* Mark the chosen partition as active since there is no active
2045 if (!MarkPartitionActive(PartData
.DiskNumber
,
2046 PartData
.PartNumber
, &ActivePartition
))
2048 PopupError("Setup could not mark the system partiton active\n",
2049 "ENTER = Reboot computer");
2055 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
2066 WCHAR PathBuffer
[MAX_PATH
];
2067 UNICODE_STRING SystemRootMBRPath
;
2069 RtlFreeUnicodeString(&SystemRootMBRPath
);
2070 swprintf(PathBuffer
,
2071 L
"\\Device\\Harddisk%lu\\Partition0",
2072 PartData
.DiskNumber
);
2073 RtlCreateUnicodeString(&SystemRootMBRPath
,
2076 /* Install MBR bootcode */
2077 wcscpy(SrcPath
, SourceRootPath
.Buffer
);
2078 wcscat(SrcPath
, L
"\\loader\\dosmbr.bin");
2080 DPRINT1("Install MBR bootcode: %S ==> %S\n", SrcPath
, SystemRootMBRPath
.Buffer
);
2081 Status
= InstallMBRBootCodeToDisk(SrcPath
,
2082 SystemRootMBRPath
.Buffer
);
2083 if (!NT_SUCCESS(Status
))
2085 DPRINT1("InstallMBRBootCodeToDisk() failed (Status %lx)\n", Status
);
2086 PopupError("Setup failed to install the MBR bootcode.",
2087 "ENTER = Reboot computer");
2093 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
2102 if (ActivePartition
.PartType
== PARTITION_ENTRY_UNUSED
)
2104 DPRINT1("Error: active partition invalid (unused)\n");
2105 PopupError("The active partition is unused (invalid).\n",
2106 "ENTER = Reboot computer");
2112 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
2119 if (ActivePartition
.PartType
== 0x0A)
2121 /* OS/2 boot manager partition */
2122 DPRINT1("Found OS/2 boot manager partition\n");
2123 PopupError("Setup found an OS/2 boot manager partiton.\n"
2124 "The OS/2 boot manager is not supported yet!",
2125 "ENTER = Reboot computer");
2131 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
2137 else if (ActivePartition
.PartType
== 0x83)
2139 /* Linux ext2 partition */
2140 DPRINT1("Found Linux ext2 partition\n");
2141 PopupError("Setup found a Linux ext2 partiton.\n"
2142 "Linux ext2 partitions are not supported yet!",
2143 "ENTER = Reboot computer");
2149 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
2155 else if (ActivePartition
.PartType
== PARTITION_IFS
)
2157 /* NTFS partition */
2158 DPRINT1("Found NTFS partition\n");
2159 PopupError("Setup found an NTFS partiton.\n"
2160 "NTFS partitions are not supported yet!",
2161 "ENTER = Reboot computer");
2167 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
2173 else if ((ActivePartition
.PartType
== PARTITION_FAT_12
) ||
2174 (ActivePartition
.PartType
== PARTITION_FAT_16
) ||
2175 (ActivePartition
.PartType
== PARTITION_HUGE
) ||
2176 (ActivePartition
.PartType
== PARTITION_XINT13
) ||
2177 (ActivePartition
.PartType
== PARTITION_FAT32
) ||
2178 (ActivePartition
.PartType
== PARTITION_FAT32_XINT13
))
2180 /* FAT or FAT32 partition */
2181 DPRINT1("System path: '%wZ'\n", &SystemRootPath
);
2183 if (DoesFileExist(SystemRootPath
.Buffer
, L
"ntldr") == TRUE
||
2184 DoesFileExist(SystemRootPath
.Buffer
, L
"boot.ini") == TRUE
)
2186 /* Search root directory for 'ntldr' and 'boot.ini'. */
2187 DPRINT1("Found Microsoft Windows NT/2000/XP boot loader\n");
2189 /* Copy FreeLoader to the boot partition */
2190 wcscpy(SrcPath
, SourceRootPath
.Buffer
);
2191 wcscat(SrcPath
, L
"\\loader\\freeldr.sys");
2192 wcscpy(DstPath
, SystemRootPath
.Buffer
);
2193 wcscat(DstPath
, L
"\\freeldr.sys");
2195 DPRINT1("Copy: %S ==> %S\n", SrcPath
, DstPath
);
2196 Status
= SetupCopyFile(SrcPath
, DstPath
);
2197 if (!NT_SUCCESS(Status
))
2199 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status
);
2200 PopupError("Setup failed to copy 'freeldr.sys'.",
2201 "ENTER = Reboot computer");
2207 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
2214 /* Create or update freeldr.ini */
2215 if (DoesFileExist(SystemRootPath
.Buffer
, L
"freeldr.ini") == FALSE
)
2217 /* Create new 'freeldr.ini' */
2218 DPRINT1("Create new 'freeldr.ini'\n");
2219 wcscpy(DstPath
, SystemRootPath
.Buffer
);
2220 wcscat(DstPath
, L
"\\freeldr.ini");
2222 Status
= CreateFreeLoaderIniForReactos(DstPath
,
2223 DestinationArcPath
.Buffer
);
2224 if (!NT_SUCCESS(Status
))
2226 DPRINT1("CreateFreeLoaderIniForReactos() failed (Status %lx)\n", Status
);
2227 PopupError("Setup failed to create 'freeldr.ini'.",
2228 "ENTER = Reboot computer");
2234 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
2241 /* Install new bootcode */
2242 if ((ActivePartition
.PartType
== PARTITION_FAT32
) ||
2243 (ActivePartition
.PartType
== PARTITION_FAT32_XINT13
))
2245 /* Install FAT32 bootcode */
2246 wcscpy(SrcPath
, SourceRootPath
.Buffer
);
2247 wcscat(SrcPath
, L
"\\loader\\fat32.bin");
2248 wcscpy(DstPath
, SystemRootPath
.Buffer
);
2249 wcscat(DstPath
, L
"\\bootsect.ros");
2251 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath
, DstPath
);
2252 Status
= InstallFat32BootCodeToFile(SrcPath
,
2254 SystemRootPath
.Buffer
);
2255 if (!NT_SUCCESS(Status
))
2257 DPRINT1("InstallFat32BootCodeToFile() failed (Status %lx)\n", Status
);
2258 PopupError("Setup failed to install the FAT32 bootcode.",
2259 "ENTER = Reboot computer");
2265 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
2274 /* Install FAT16 bootcode */
2275 wcscpy(SrcPath
, SourceRootPath
.Buffer
);
2276 wcscat(SrcPath
, L
"\\loader\\fat.bin");
2277 wcscpy(DstPath
, SystemRootPath
.Buffer
);
2278 wcscat(DstPath
, L
"\\bootsect.ros");
2280 DPRINT1("Install FAT bootcode: %S ==> %S\n", SrcPath
, DstPath
);
2281 Status
= InstallFat16BootCodeToFile(SrcPath
,
2283 SystemRootPath
.Buffer
);
2284 if (!NT_SUCCESS(Status
))
2286 DPRINT1("InstallFat16BootCodeToFile() failed (Status %lx)\n", Status
);
2287 PopupError("Setup failed to install the FAT bootcode.",
2288 "ENTER = Reboot computer");
2294 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
2302 /* Update 'boot.ini' */
2303 wcscpy(DstPath
, SystemRootPath
.Buffer
);
2304 wcscat(DstPath
, L
"\\boot.ini");
2306 DPRINT1("Update 'boot.ini': %S\n", DstPath
);
2307 Status
= UpdateBootIni(DstPath
,
2308 L
"C:\\bootsect.ros",
2310 if (!NT_SUCCESS(Status
))
2312 DPRINT1("UpdateBootIni() failed (Status %lx)\n", Status
);
2313 PopupError("Setup failed to update \'boot.ini\'.",
2314 "ENTER = Reboot computer");
2320 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
2329 /* Update existing 'freeldr.ini' */
2330 DPRINT1("Update existing 'freeldr.ini'\n");
2331 wcscpy(DstPath
, SystemRootPath
.Buffer
);
2332 wcscat(DstPath
, L
"\\freeldr.ini");
2334 Status
= UpdateFreeLoaderIni(DstPath
,
2335 DestinationArcPath
.Buffer
);
2336 if (!NT_SUCCESS(Status
))
2338 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status
);
2339 PopupError("Setup failed to update 'freeldr.ini'.",
2340 "ENTER = Reboot computer");
2346 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
2354 else if (DoesFileExist(SystemRootPath
.Buffer
, L
"io.sys") == TRUE
||
2355 DoesFileExist(SystemRootPath
.Buffer
, L
"msdos.sys") == TRUE
)
2357 /* Search for root directory for 'io.sys' and 'msdos.sys'. */
2358 DPRINT1("Found Microsoft DOS or Windows 9x boot loader\n");
2360 /* Copy FreeLoader to the boot partition */
2361 wcscpy(SrcPath
, SourceRootPath
.Buffer
);
2362 wcscat(SrcPath
, L
"\\loader\\freeldr.sys");
2363 wcscpy(DstPath
, SystemRootPath
.Buffer
);
2364 wcscat(DstPath
, L
"\\freeldr.sys");
2366 DPRINT("Copy: %S ==> %S\n", SrcPath
, DstPath
);
2367 Status
= SetupCopyFile(SrcPath
, DstPath
);
2368 if (!NT_SUCCESS(Status
))
2370 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status
);
2371 PopupError("Setup failed to copy 'freeldr.sys'.",
2372 "ENTER = Reboot computer");
2378 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
2385 /* Create or update 'freeldr.ini' */
2386 if (DoesFileExist(SystemRootPath
.Buffer
, L
"freeldr.ini") == FALSE
)
2388 /* Create new 'freeldr.ini' */
2389 DPRINT1("Create new 'freeldr.ini'\n");
2390 wcscpy(DstPath
, SystemRootPath
.Buffer
);
2391 wcscat(DstPath
, L
"\\freeldr.ini");
2393 Status
= CreateFreeLoaderIniForDos(DstPath
,
2394 DestinationArcPath
.Buffer
);
2395 if (!NT_SUCCESS(Status
))
2397 DPRINT1("CreateFreeLoaderIniForDos() failed (Status %lx)\n", Status
);
2398 PopupError("Setup failed to create 'freeldr.ini'.",
2399 "ENTER = Reboot computer");
2405 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
2412 /* Save current bootsector as 'BOOTSECT.DOS' */
2413 wcscpy(SrcPath
, SystemRootPath
.Buffer
);
2414 wcscpy(DstPath
, SystemRootPath
.Buffer
);
2415 wcscat(DstPath
, L
"\\bootsect.dos");
2417 DPRINT1("Save bootsector: %S ==> %S\n", SrcPath
, DstPath
);
2418 Status
= SaveCurrentBootSector(SrcPath
,
2420 if (!NT_SUCCESS(Status
))
2422 DPRINT1("SaveCurrentBootSector() failed (Status %lx)\n", Status
);
2423 PopupError("Setup failed to save the current bootsector.",
2424 "ENTER = Reboot computer");
2430 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
2437 /* Install new bootsector */
2438 if ((ActivePartition
.PartType
== PARTITION_FAT32
) ||
2439 (ActivePartition
.PartType
== PARTITION_FAT32_XINT13
))
2441 wcscpy(SrcPath
, SourceRootPath
.Buffer
);
2442 wcscat(SrcPath
, L
"\\loader\\fat32.bin");
2444 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath
, SystemRootPath
.Buffer
);
2445 Status
= InstallFat32BootCodeToDisk(SrcPath
,
2446 SystemRootPath
.Buffer
);
2447 if (!NT_SUCCESS(Status
))
2449 DPRINT1("InstallFat32BootCodeToDisk() failed (Status %lx)\n", Status
);
2450 PopupError("Setup failed to install the FAT32 bootcode.",
2451 "ENTER = Reboot computer");
2457 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
2466 wcscpy(SrcPath
, SourceRootPath
.Buffer
);
2467 wcscat(SrcPath
, L
"\\loader\\fat.bin");
2469 DPRINT1("Install FAT bootcode: %S ==> %S\n", SrcPath
, SystemRootPath
.Buffer
);
2470 Status
= InstallFat16BootCodeToDisk(SrcPath
,
2471 SystemRootPath
.Buffer
);
2472 if (!NT_SUCCESS(Status
))
2474 DPRINT1("InstallFat16BootCodeToDisk() failed (Status %lx)\n", Status
);
2475 PopupError("Setup failed to install the FAT bootcode.",
2476 "ENTER = Reboot computer");
2482 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
2492 /* Update existing 'freeldr.ini' */
2493 wcscpy(DstPath
, SystemRootPath
.Buffer
);
2494 wcscat(DstPath
, L
"\\freeldr.ini");
2496 Status
= UpdateFreeLoaderIni(DstPath
,
2497 DestinationArcPath
.Buffer
);
2498 if (!NT_SUCCESS(Status
))
2500 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status
);
2501 PopupError("Setup failed to update 'freeldr.ini'.",
2502 "ENTER = Reboot computer");
2508 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
2518 /* No or unknown boot loader */
2519 DPRINT1("No or unknown boot loader found\n");
2521 /* Copy FreeLoader to the boot partition */
2522 wcscpy(SrcPath
, SourceRootPath
.Buffer
);
2523 wcscat(SrcPath
, L
"\\loader\\freeldr.sys");
2524 wcscpy(DstPath
, SystemRootPath
.Buffer
);
2525 wcscat(DstPath
, L
"\\freeldr.sys");
2527 DPRINT1("Copy: %S ==> %S\n", SrcPath
, DstPath
);
2528 Status
= SetupCopyFile(SrcPath
, DstPath
);
2529 if (!NT_SUCCESS(Status
))
2531 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status
);
2532 PopupError("Setup failed to copy 'freeldr.sys'.",
2533 "ENTER = Reboot computer");
2539 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
2546 /* Create or update 'freeldr.ini' */
2547 if (DoesFileExist(SystemRootPath
.Buffer
, L
"freeldr.ini") == FALSE
)
2549 /* Create new freeldr.ini */
2550 wcscpy(DstPath
, SystemRootPath
.Buffer
);
2551 wcscat(DstPath
, L
"\\freeldr.ini");
2553 DPRINT1("Copy: %S ==> %S\n", SrcPath
, DstPath
);
2554 Status
= CreateFreeLoaderIniForReactos(DstPath
,
2555 DestinationArcPath
.Buffer
);
2556 if (!NT_SUCCESS(Status
))
2558 DPRINT1("CreateFreeLoaderIniForReactos() failed (Status %lx)\n", Status
);
2559 PopupError("Setup failed to create \'freeldr.ini\'.",
2560 "ENTER = Reboot computer");
2566 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
2573 /* Save current bootsector as 'BOOTSECT.OLD' */
2574 wcscpy(SrcPath
, SystemRootPath
.Buffer
);
2575 wcscpy(DstPath
, SystemRootPath
.Buffer
);
2576 wcscat(DstPath
, L
"\\bootsect.old");
2578 DPRINT1("Save bootsector: %S ==> %S\n", SrcPath
, DstPath
);
2579 Status
= SaveCurrentBootSector(SrcPath
,
2581 if (!NT_SUCCESS(Status
))
2583 DPRINT1("SaveCurrentBootSector() failed (Status %lx)\n", Status
);
2584 PopupError("Setup failed save the current bootsector.",
2585 "ENTER = Reboot computer");
2591 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
2598 /* Install new bootsector */
2599 if ((ActivePartition
.PartType
== PARTITION_FAT32
) ||
2600 (ActivePartition
.PartType
== PARTITION_FAT32_XINT13
))
2602 wcscpy(SrcPath
, SourceRootPath
.Buffer
);
2603 wcscat(SrcPath
, L
"\\loader\\fat32.bin");
2605 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath
, SystemRootPath
.Buffer
);
2606 Status
= InstallFat32BootCodeToDisk(SrcPath
,
2607 SystemRootPath
.Buffer
);
2608 if (!NT_SUCCESS(Status
))
2610 DPRINT1("InstallFat32BootCodeToDisk() failed (Status %lx)\n", Status
);
2611 PopupError("Setup failed to install the FAT32 bootcode.",
2612 "ENTER = Reboot computer");
2618 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
2627 wcscpy(SrcPath
, SourceRootPath
.Buffer
);
2628 wcscat(SrcPath
, L
"\\loader\\fat.bin");
2630 DPRINT1("Install FAT bootcode: %S ==> %S\n", SrcPath
, SystemRootPath
.Buffer
);
2631 Status
= InstallFat16BootCodeToDisk(SrcPath
,
2632 SystemRootPath
.Buffer
);
2633 if (!NT_SUCCESS(Status
))
2635 DPRINT1("InstallFat16BootCodeToDisk() failed (Status %lx)\n", Status
);
2636 PopupError("Setup failed to install the FAT bootcode.",
2637 "ENTER = Reboot computer");
2643 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
2653 /* Update existing 'freeldr.ini' */
2654 wcscpy(DstPath
, SystemRootPath
.Buffer
);
2655 wcscat(DstPath
, L
"\\freeldr.ini");
2657 Status
= UpdateFreeLoaderIni(DstPath
,
2658 DestinationArcPath
.Buffer
);
2659 if (!NT_SUCCESS(Status
))
2661 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status
);
2662 PopupError("Setup failed to update 'freeldr.ini'.",
2663 "ENTER = Reboot computer");
2669 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
2680 /* Unknown partition */
2681 DPRINT1("Unknown partition found\n");
2682 PopupError("Setup found an unknown partiton type.\n"
2683 "This partition type is not supported!",
2684 "ENTER = Reboot computer");
2690 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
2697 return(SUCCESS_PAGE
);
2703 QuitPage(PINPUT_RECORD Ir
)
2705 SetTextXY(10, 6, "ReactOS is not completely installed");
2707 SetTextXY(10, 8, "Remove floppy disk from Drive A: and");
2708 SetTextXY(10, 9, "all CD-ROMs from CD-Drives.");
2710 SetTextXY(10, 11, "Press ENTER to reboot your computer.");
2712 SetStatusText(" ENTER = Reboot computer");
2718 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
2720 return(REBOOT_PAGE
);
2727 SuccessPage(PINPUT_RECORD Ir
)
2729 SetTextXY(10, 6, "The basic components of ReactOS have been installed successfully.");
2731 SetTextXY(10, 8, "Remove floppy disk from Drive A: and");
2732 SetTextXY(10, 9, "all CD-ROMs from CD-Drive.");
2734 SetTextXY(10, 11, "Press ENTER to reboot your computer.");
2736 SetStatusText(" ENTER = Reboot computer");
2742 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
2744 return(REBOOT_PAGE
);
2751 NtProcessStartup(PPEB Peb
)
2757 RtlNormalizeProcessParams(Peb
->ProcessParameters
);
2759 ProcessHeap
= Peb
->ProcessHeap
;
2761 Status
= AllocConsole();
2762 if (!NT_SUCCESS(Status
))
2764 PrintString("AllocConsole() failed (Status = 0x%08lx)\n", Status
);
2766 /* Raise a hard error (crash the system/BSOD) */
2767 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED
,
2771 PartDataValid
= FALSE
;
2773 /* Initialize global unicode strings */
2774 RtlInitUnicodeString(&SourcePath
, NULL
);
2775 RtlInitUnicodeString(&SourceRootPath
, NULL
);
2776 RtlInitUnicodeString(&InstallPath
, NULL
);
2777 RtlInitUnicodeString(&DestinationPath
, NULL
);
2778 RtlInitUnicodeString(&DestinationArcPath
, NULL
);
2779 RtlInitUnicodeString(&DestinationRootPath
, NULL
);
2780 RtlInitUnicodeString(&SystemRootPath
, NULL
);
2784 while (Page
!= REBOOT_PAGE
)
2788 SetUnderlinedTextXY(4, 3, " ReactOS " KERNEL_VERSION_STR
" Setup ");
2794 Page
= StartPage(&Ir
);
2799 Page
= IntroPage(&Ir
);
2803 case INSTALL_INTRO_PAGE
:
2804 Page
= InstallIntroPage(&Ir
);
2808 case OEM_DRIVER_PAGE
:
2809 Page
= OemDriverPage(&Ir
);
2814 case DEVICE_SETTINGS_PAGE
:
2817 case SELECT_PARTITION_PAGE
:
2818 Page
= SelectPartitionPage(&Ir
);
2822 case CREATE_PARTITION_PAGE
:
2823 Page
= CreatePartitionPage(&Ir
);
2827 case SELECT_FILE_SYSTEM_PAGE
:
2828 Page
= SelectFileSystemPage(&Ir
);
2831 case FORMAT_PARTITION_PAGE
:
2832 Page
= FormatPartitionPage(&Ir
);
2835 case CHECK_FILE_SYSTEM_PAGE
:
2836 Page
= CheckFileSystemPage(&Ir
);
2839 case INSTALL_DIRECTORY_PAGE
:
2840 Page
= InstallDirectoryPage(&Ir
);
2843 case PREPARE_COPY_PAGE
:
2844 Page
= PrepareCopyPage(&Ir
);
2847 case FILE_COPY_PAGE
:
2848 Page
= FileCopyPage(&Ir
);
2852 Page
= RegistryPage(&Ir
);
2855 case BOOT_LOADER_PAGE
:
2856 Page
= BootLoaderPage(&Ir
);
2861 case REPAIR_INTRO_PAGE
:
2862 Page
= RepairIntroPage(&Ir
);
2866 /* Emergency pages */
2867 case EMERGENCY_INTRO_PAGE
:
2868 Page
= EmergencyIntroPage(&Ir
);
2873 Page
= SuccessPage(&Ir
);
2877 Page
= QuitPage(&Ir
);
2884 NtShutdownSystem(ShutdownReboot
);