Enable ReactOS installation.
[reactos.git] / reactos / subsys / system / usetup / usetup.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 2002, 2003 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 * Casper S. Hornstrup (chorns@users.sourceforge.net)
26 */
27
28 #include <ddk/ntddk.h>
29 #include <ntdll/rtl.h>
30
31 #include <ntos/minmax.h>
32 #include <reactos/resource.h>
33
34 #include "usetup.h"
35 #include "console.h"
36 #include "partlist.h"
37 #include "inicache.h"
38 #include "infcache.h"
39 #include "filequeue.h"
40 #include "progress.h"
41 #include "bootsup.h"
42 #include "registry.h"
43 #include "format.h"
44 #include "fslist.h"
45
46 #define NDEBUG
47 #include <debug.h>
48
49
50 typedef enum _PAGE_NUMBER
51 {
52 START_PAGE,
53 INTRO_PAGE,
54 INSTALL_INTRO_PAGE,
55
56 SELECT_PARTITION_PAGE,
57 CREATE_PARTITION_PAGE,
58 DELETE_PARTITION_PAGE,
59
60 SELECT_FILE_SYSTEM_PAGE,
61 FORMAT_PARTITION_PAGE,
62 CHECK_FILE_SYSTEM_PAGE,
63
64 PREPARE_COPY_PAGE,
65 INSTALL_DIRECTORY_PAGE,
66 FILE_COPY_PAGE,
67 REGISTRY_PAGE,
68 BOOT_LOADER_PAGE,
69
70 REPAIR_INTRO_PAGE,
71
72 EMERGENCY_INTRO_PAGE,
73
74 SUCCESS_PAGE,
75 QUIT_PAGE,
76 REBOOT_PAGE, /* virtual page */
77 } PAGE_NUMBER, *PPAGE_NUMBER;
78
79 typedef struct _COPYCONTEXT
80 {
81 ULONG TotalOperations;
82 ULONG CompletedOperations;
83 PPROGRESS ProgressBar;
84 } COPYCONTEXT, *PCOPYCONTEXT;
85
86
87 /* GLOBALS ******************************************************************/
88
89 HANDLE ProcessHeap;
90 UNICODE_STRING SourceRootPath;
91
92
93 /* LOCALS *******************************************************************/
94
95 static PPARTLIST PartitionList = NULL;
96
97 static PFILE_SYSTEM_LIST FileSystemList = NULL;
98
99
100 static UNICODE_STRING SourcePath;
101
102 static UNICODE_STRING InstallPath;
103
104 /* Path to the install directory */
105 static UNICODE_STRING DestinationPath;
106 static UNICODE_STRING DestinationArcPath;
107 static UNICODE_STRING DestinationRootPath;
108
109 /* Path to the active partition (boot manager) */
110 static UNICODE_STRING SystemRootPath;
111
112 static HINF SetupInf;
113
114 static HSPFILEQ SetupFileQueue = NULL;
115
116
117 /* FUNCTIONS ****************************************************************/
118
119 static VOID
120 PrintString(char* fmt,...)
121 {
122 char buffer[512];
123 va_list ap;
124 UNICODE_STRING UnicodeString;
125 ANSI_STRING AnsiString;
126
127 va_start(ap, fmt);
128 vsprintf(buffer, fmt, ap);
129 va_end(ap);
130
131 RtlInitAnsiString(&AnsiString, buffer);
132 RtlAnsiStringToUnicodeString(&UnicodeString,
133 &AnsiString,
134 TRUE);
135 NtDisplayString(&UnicodeString);
136 RtlFreeUnicodeString(&UnicodeString);
137 }
138
139
140 static VOID
141 PopupError(PCHAR Text,
142 PCHAR Status)
143 {
144 SHORT xScreen;
145 SHORT yScreen;
146 SHORT yTop;
147 SHORT xLeft;
148 COORD coPos;
149 ULONG Written;
150 ULONG Length;
151 ULONG MaxLength;
152 ULONG Lines;
153 PCHAR p;
154 PCHAR pnext;
155 BOOLEAN LastLine;
156 SHORT Width;
157 SHORT Height;
158
159 /* Count text lines and longest line */
160 MaxLength = 0;
161 Lines = 0;
162 pnext = Text;
163 while (TRUE)
164 {
165 p = strchr(pnext, '\n');
166 if (p == NULL)
167 {
168 Length = strlen(pnext);
169 LastLine = TRUE;
170 }
171 else
172 {
173 Length = (ULONG)(p - pnext);
174 LastLine = FALSE;
175 }
176
177 Lines++;
178 if (Length > MaxLength)
179 MaxLength = Length;
180
181 if (LastLine == TRUE)
182 break;
183
184 pnext = p + 1;
185 }
186
187 /* Check length of status line */
188 if (Status != NULL)
189 {
190 Length = strlen(Status);
191 if (Length > MaxLength)
192 MaxLength = Length;
193 }
194
195 GetScreenSize(&xScreen, &yScreen);
196
197 Width = MaxLength + 4;
198 Height = Lines + 2;
199 if (Status != NULL)
200 Height += 2;
201
202 yTop = (yScreen - Height) / 2;
203 xLeft = (xScreen - Width) / 2;
204
205
206 /* Set screen attributes */
207 coPos.X = xLeft;
208 for (coPos.Y = yTop; coPos.Y < yTop + Height; coPos.Y++)
209 {
210 FillConsoleOutputAttribute(0x74,
211 Width,
212 coPos,
213 &Written);
214 }
215
216 /* draw upper left corner */
217 coPos.X = xLeft;
218 coPos.Y = yTop;
219 FillConsoleOutputCharacter(0xDA, // '+',
220 1,
221 coPos,
222 &Written);
223
224 /* draw upper edge */
225 coPos.X = xLeft + 1;
226 coPos.Y = yTop;
227 FillConsoleOutputCharacter(0xC4, // '-',
228 Width - 2,
229 coPos,
230 &Written);
231
232 /* draw upper right corner */
233 coPos.X = xLeft + Width - 1;
234 coPos.Y = yTop;
235 FillConsoleOutputCharacter(0xBF, // '+',
236 1,
237 coPos,
238 &Written);
239
240 /* Draw right edge, inner space and left edge */
241 for (coPos.Y = yTop + 1; coPos.Y < yTop + Height - 1; coPos.Y++)
242 {
243 coPos.X = xLeft;
244 FillConsoleOutputCharacter(0xB3, // '|',
245 1,
246 coPos,
247 &Written);
248
249 coPos.X = xLeft + 1;
250 FillConsoleOutputCharacter(' ',
251 Width - 2,
252 coPos,
253 &Written);
254
255 coPos.X = xLeft + Width - 1;
256 FillConsoleOutputCharacter(0xB3, // '|',
257 1,
258 coPos,
259 &Written);
260 }
261
262 /* draw lower left corner */
263 coPos.X = xLeft;
264 coPos.Y = yTop + Height - 1;
265 FillConsoleOutputCharacter(0xC0, // '+',
266 1,
267 coPos,
268 &Written);
269
270 /* draw lower edge */
271 coPos.X = xLeft + 1;
272 coPos.Y = yTop + Height - 1;
273 FillConsoleOutputCharacter(0xC4, // '-',
274 Width - 2,
275 coPos,
276 &Written);
277
278 /* draw lower right corner */
279 coPos.X = xLeft + Width - 1;
280 coPos.Y = yTop + Height - 1;
281 FillConsoleOutputCharacter(0xD9, // '+',
282 1,
283 coPos,
284 &Written);
285
286 /* Print message text */
287 coPos.Y = yTop + 1;
288 pnext = Text;
289 while (TRUE)
290 {
291 p = strchr(pnext, '\n');
292 if (p == NULL)
293 {
294 Length = strlen(pnext);
295 LastLine = TRUE;
296 }
297 else
298 {
299 Length = (ULONG)(p - pnext);
300 LastLine = FALSE;
301 }
302
303 if (Length != 0)
304 {
305 coPos.X = xLeft + 2;
306 WriteConsoleOutputCharacters(pnext,
307 Length,
308 coPos);
309 }
310
311 if (LastLine == TRUE)
312 break;
313
314 coPos.Y++;
315 pnext = p + 1;
316 }
317
318 /* Print separator line and status text */
319 if (Status != NULL)
320 {
321 coPos.Y = yTop + Height - 3;
322 coPos.X = xLeft;
323 FillConsoleOutputCharacter(0xC3, // '+',
324 1,
325 coPos,
326 &Written);
327
328 coPos.X = xLeft + 1;
329 FillConsoleOutputCharacter(0xC4, // '-',
330 Width - 2,
331 coPos,
332 &Written);
333
334 coPos.X = xLeft + Width - 1;
335 FillConsoleOutputCharacter(0xB4, // '+',
336 1,
337 coPos,
338 &Written);
339
340 coPos.Y++;
341 coPos.X = xLeft + 2;
342 WriteConsoleOutputCharacters(Status,
343 min(strlen(Status), Width - 4),
344 coPos);
345 }
346 }
347
348
349 /*
350 * Confirm quit setup
351 * RETURNS
352 * TRUE: Quit setup.
353 * FALSE: Don't quit setup.
354 */
355 static BOOL
356 ConfirmQuit(PINPUT_RECORD Ir)
357 {
358 BOOL Result = FALSE;
359
360 PopupError("ReactOS is not completely installed on your\n"
361 "computer. If you quit Setup now, you will need to\n"
362 "run Setup again to install ReactOS.\n"
363 "\n"
364 " \x07 Press ENTER to continue Setup.\n"
365 " \x07 Press F3 to quit Setup.",
366 "F3= Quit ENTER = Continue");
367
368 while(TRUE)
369 {
370 ConInKey(Ir);
371
372 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
373 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
374 {
375 Result = TRUE;
376 break;
377 }
378 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
379 {
380 Result = FALSE;
381 break;
382 }
383 }
384
385 return(Result);
386 }
387
388
389
390 /*
391 * Start page
392 * RETURNS
393 * Number of the next page.
394 */
395 static PAGE_NUMBER
396 StartPage(PINPUT_RECORD Ir)
397 {
398 NTSTATUS Status;
399 WCHAR FileNameBuffer[MAX_PATH];
400 UNICODE_STRING FileName;
401 INFCONTEXT Context;
402 PWCHAR Value;
403 ULONG ErrorLine;
404
405 SetStatusText(" Please wait...");
406
407 Status = GetSourcePaths(&SourcePath,
408 &SourceRootPath);
409 if (!NT_SUCCESS(Status))
410 {
411 PrintTextXY(6, 15, "GetSourcePath() failed (Status 0x%08lx)", Status);
412 PopupError("Setup could not find its source drive.\n",
413 "ENTER = Reboot computer");
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 #if 0
425 else
426 {
427 PrintTextXY(6, 15, "SourcePath: '%wZ'", &SourcePath);
428 PrintTextXY(6, 16, "SourceRootPath: '%wZ'", &SourceRootPath);
429 }
430 #endif
431
432 /* Load txtsetup.sif from install media. */
433 wcscpy(FileNameBuffer, SourceRootPath.Buffer);
434 wcscat(FileNameBuffer, L"\\reactos\\txtsetup.sif");
435 RtlInitUnicodeString(&FileName,
436 FileNameBuffer);
437
438 Status = InfOpenFile(&SetupInf,
439 &FileName,
440 &ErrorLine);
441 if (!NT_SUCCESS(Status))
442 {
443 PopupError("Setup failed to load the file TXTSETUP.SIF.\n",
444 "ENTER = Reboot computer");
445
446 while(TRUE)
447 {
448 ConInKey(Ir);
449
450 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
451 {
452 return(QUIT_PAGE);
453 }
454 }
455 }
456
457 /* Open 'Version' section */
458 if (!InfFindFirstLine (SetupInf, L"Version", L"Signature", &Context))
459 {
460 PopupError("Setup found a corrupt TXTSETUP.SIF.\n",
461 "ENTER = Reboot computer");
462
463 while(TRUE)
464 {
465 ConInKey(Ir);
466
467 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
468 {
469 return(QUIT_PAGE);
470 }
471 }
472 }
473
474
475 /* Get pointer 'Signature' key */
476 if (!InfGetData (&Context, NULL, &Value))
477 {
478 PopupError("Setup found a corrupt TXTSETUP.SIF.\n",
479 "ENTER = Reboot computer");
480
481 while(TRUE)
482 {
483 ConInKey(Ir);
484
485 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
486 {
487 return(QUIT_PAGE);
488 }
489 }
490 }
491
492 /* Check 'Signature' string */
493 if (_wcsicmp(Value, L"$ReactOS$") != 0)
494 {
495 PopupError("Setup found an invalid signature in TXTSETUP.SIF.\n",
496 "ENTER = Reboot computer");
497
498 while(TRUE)
499 {
500 ConInKey(Ir);
501
502 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
503 {
504 return(QUIT_PAGE);
505 }
506 }
507 }
508
509 return(INTRO_PAGE);
510 }
511
512
513 /*
514 * First setup page
515 * RETURNS
516 * Next page number.
517 */
518 static PAGE_NUMBER
519 IntroPage(PINPUT_RECORD Ir)
520 {
521 SetHighlightedTextXY(6, 8, "Welcome to ReactOS Setup");
522
523 SetTextXY(6, 11, "This part of the setup copies the ReactOS Operating System to your");
524 SetTextXY(6, 12, "computer and prepares the second part of the setup.");
525
526 SetTextXY(8, 15, "\x07 Press ENTER to install ReactOS.");
527
528 SetTextXY(8, 17, "\x07 Press E to start the emergency console.");
529
530 SetTextXY(8, 19, "\x07 Press R to repair ReactOS.");
531
532 SetTextXY(8, 21, "\x07 Press F3 to quit without installing ReactOS.");
533
534
535 SetStatusText(" ENTER = Continue F3 = Quit");
536
537 while(TRUE)
538 {
539 ConInKey(Ir);
540
541 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
542 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
543 {
544 if (ConfirmQuit(Ir) == TRUE)
545 return(QUIT_PAGE);
546 break;
547 }
548 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
549 {
550 return(INSTALL_INTRO_PAGE);
551 }
552 else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'E') /* E */
553 {
554 return(EMERGENCY_INTRO_PAGE);
555 }
556 else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'R') /* R */
557 {
558 return(REPAIR_INTRO_PAGE);
559 }
560 }
561
562 return(INTRO_PAGE);
563 }
564
565
566 static PAGE_NUMBER
567 EmergencyIntroPage(PINPUT_RECORD Ir)
568 {
569 SetTextXY(6, 8, "ReactOS Setup is in an early development phase. It does not yet");
570 SetTextXY(6, 9, "support all the functions of a fully usable setup application.");
571
572 SetTextXY(6, 12, "The emergency console is not implemented yet.");
573
574 SetTextXY(8, 15, "\x07 Press ESC to return to the main page.");
575
576 SetTextXY(8, 17, "\x07 Press ENTER to reboot your computer.");
577
578 SetStatusText(" ESC = Main page ENTER = Reboot");
579
580 while(TRUE)
581 {
582 ConInKey(Ir);
583
584 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
585 {
586 return(REBOOT_PAGE);
587 }
588 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
589 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
590 {
591 return(INTRO_PAGE);
592 }
593 }
594
595 return(REPAIR_INTRO_PAGE);
596 }
597
598
599 static PAGE_NUMBER
600 RepairIntroPage(PINPUT_RECORD Ir)
601 {
602 SetTextXY(6, 8, "ReactOS Setup is in an early development phase. It does not yet");
603 SetTextXY(6, 9, "support all the functions of a fully usable setup application.");
604
605 SetTextXY(6, 12, "The repair functions are not implemented yet.");
606
607 SetTextXY(8, 15, "\x07 Press ESC to return to the main page.");
608
609 SetTextXY(8, 17, "\x07 Press ENTER to reboot your computer.");
610
611 SetStatusText(" ESC = Main page ENTER = Reboot");
612
613 while(TRUE)
614 {
615 ConInKey(Ir);
616
617 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
618 {
619 return(REBOOT_PAGE);
620 }
621 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
622 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
623 {
624 return(INTRO_PAGE);
625 }
626 }
627
628 return(REPAIR_INTRO_PAGE);
629 }
630
631
632 static PAGE_NUMBER
633 InstallIntroPage(PINPUT_RECORD Ir)
634 {
635 SetTextXY(6, 8, "ReactOS Setup is in an early development phase. It does not yet");
636 SetTextXY(6, 9, "support all the functions of a fully usable setup application.");
637
638 SetTextXY(6, 12, "The following functions are missing:");
639 SetTextXY(8, 13, "- Creating and deleting harddisk partitions.");
640 SetTextXY(8, 14, "- Formatting partitions.");
641 SetTextXY(8, 15, "- Support for non-FAT file systems.");
642 SetTextXY(8, 16, "- Checking file systems.");
643
644
645
646 SetTextXY(8, 21, "\x07 Press ENTER to install ReactOS.");
647
648 SetTextXY(8, 23, "\x07 Press F3 to quit without installing ReactOS.");
649
650
651 SetStatusText(" ENTER = Continue F3 = Quit");
652
653 while(TRUE)
654 {
655 ConInKey(Ir);
656
657 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
658 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
659 {
660 if (ConfirmQuit(Ir) == TRUE)
661 return(QUIT_PAGE);
662 break;
663 }
664 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
665 {
666 return(SELECT_PARTITION_PAGE);
667 }
668 }
669
670 return(INSTALL_INTRO_PAGE);
671 }
672
673
674 static PAGE_NUMBER
675 SelectPartitionPage(PINPUT_RECORD Ir)
676 {
677 SHORT xScreen;
678 SHORT yScreen;
679
680 SetTextXY(6, 8, "The list below shows existing partitions and unused disk");
681 SetTextXY(6, 9, "space for new partitions.");
682
683 SetTextXY(8, 11, "\x07 Press UP or DOWN to select a list entry.");
684 SetTextXY(8, 13, "\x07 Press ENTER to install ReactOS onto the selected partition.");
685 SetTextXY(8, 15, "\x07 Press C to create a new partition.");
686 SetTextXY(8, 17, "\x07 Press D to delete an existing partition.");
687
688 SetStatusText(" Please wait...");
689
690 GetScreenSize(&xScreen, &yScreen);
691
692 if (PartitionList == NULL)
693 {
694 PartitionList = CreatePartitionList (2,
695 19,
696 xScreen - 3,
697 yScreen - 3);
698 if (PartitionList == NULL)
699 {
700 /* FIXME: show an error dialog */
701 return(QUIT_PAGE);
702 }
703 }
704
705 DrawPartitionList (PartitionList);
706
707 while(TRUE)
708 {
709 /* Update status text */
710 if (PartitionList->CurrentPartition == NULL ||
711 PartitionList->CurrentPartition->Unpartitioned == TRUE)
712 {
713 SetStatusText (" ENTER = Install C = Create Partition F3 = Quit");
714 }
715 else
716 {
717 SetStatusText (" ENTER = Install D = Delete Partition F3 = Quit");
718 }
719
720 ConInKey(Ir);
721
722 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
723 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
724 {
725 if (ConfirmQuit(Ir) == TRUE)
726 {
727 DestroyPartitionList (PartitionList);
728 PartitionList = NULL;
729 return QUIT_PAGE;
730 }
731 break;
732 }
733 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
734 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
735 {
736 ScrollDownPartitionList (PartitionList);
737 }
738 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
739 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
740 {
741 ScrollUpPartitionList (PartitionList);
742 }
743 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
744 {
745 if (PartitionList->CurrentPartition == NULL ||
746 PartitionList->CurrentPartition->Unpartitioned == TRUE)
747 {
748 CreateNewPartition (PartitionList,
749 0ULL,
750 TRUE);
751 }
752
753 return SELECT_FILE_SYSTEM_PAGE;
754 }
755 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_C) /* C */
756 {
757 if (PartitionList->CurrentPartition->Unpartitioned == FALSE)
758 {
759 PopupError ("You can not create a new Partition inside\n"
760 "of an already existing Partition!\n"
761 "\n"
762 " * Press any key to continue.",
763 NULL);
764 ConInKey (Ir);
765
766 return SELECT_PARTITION_PAGE;
767 }
768
769 return CREATE_PARTITION_PAGE;
770 }
771 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_D) /* D */
772 {
773 if (PartitionList->CurrentPartition->Unpartitioned == TRUE)
774 {
775 PopupError ("You can not delete unpartitioned disk space!\n"
776 "\n"
777 " * Press any key to continue.",
778 NULL);
779 ConInKey (Ir);
780
781 return SELECT_PARTITION_PAGE;
782 }
783
784 return DELETE_PARTITION_PAGE;
785 }
786 }
787
788 return SELECT_PARTITION_PAGE;
789 }
790
791
792 static VOID
793 DrawInputField(ULONG FieldLength,
794 SHORT Left,
795 SHORT Top,
796 PCHAR FieldContent)
797 {
798 CHAR buf[100];
799 COORD coPos;
800
801 coPos.X = Left;
802 coPos.Y = Top;
803 memset(buf, '_', sizeof(buf));
804 buf[FieldLength - strlen(FieldContent)] = 0;
805 strcat(buf, FieldContent);
806
807 WriteConsoleOutputCharacters (buf,
808 strlen (buf),
809 coPos);
810 }
811
812
813 #define PARTITION_SIZE_INPUT_FIELD_LENGTH 6
814
815 static VOID
816 ShowPartitionSizeInputBox(SHORT Left,
817 SHORT Top,
818 SHORT Right,
819 SHORT Bottom,
820 ULONG MaxSize,
821 PCHAR InputBuffer,
822 PBOOLEAN Quit,
823 PBOOLEAN Cancel)
824 {
825 INPUT_RECORD Ir;
826 COORD coPos;
827 ULONG Written;
828 SHORT i;
829 CHAR Buffer[100];
830 ULONG Index;
831 CHAR ch;
832 SHORT iLeft;
833 SHORT iTop;
834
835 if (Quit != NULL)
836 *Quit = FALSE;
837
838 if (Cancel != NULL)
839 *Cancel = FALSE;
840
841 /* draw upper left corner */
842 coPos.X = Left;
843 coPos.Y = Top;
844 FillConsoleOutputCharacter(0xDA, // '+',
845 1,
846 coPos,
847 &Written);
848
849 /* draw upper edge */
850 coPos.X = Left + 1;
851 coPos.Y = Top;
852 FillConsoleOutputCharacter(0xC4, // '-',
853 Right - Left - 1,
854 coPos,
855 &Written);
856
857 /* draw upper right corner */
858 coPos.X = Right;
859 coPos.Y = Top;
860 FillConsoleOutputCharacter(0xBF, // '+',
861 1,
862 coPos,
863 &Written);
864
865 /* draw left and right edge */
866 for (i = Top + 1; i < Bottom; i++)
867 {
868 coPos.X = Left;
869 coPos.Y = i;
870 FillConsoleOutputCharacter(0xB3, // '|',
871 1,
872 coPos,
873 &Written);
874
875 coPos.X = Right;
876 FillConsoleOutputCharacter(0xB3, //'|',
877 1,
878 coPos,
879 &Written);
880 }
881
882 /* draw lower left corner */
883 coPos.X = Left;
884 coPos.Y = Bottom;
885 FillConsoleOutputCharacter(0xC0, // '+',
886 1,
887 coPos,
888 &Written);
889
890 /* draw lower edge */
891 coPos.X = Left + 1;
892 coPos.Y = Bottom;
893 FillConsoleOutputCharacter(0xC4, // '-',
894 Right - Left - 1,
895 coPos,
896 &Written);
897
898 /* draw lower right corner */
899 coPos.X = Right;
900 coPos.Y = Bottom;
901 FillConsoleOutputCharacter(0xD9, // '+',
902 1,
903 coPos,
904 &Written);
905
906 /* Print message */
907 coPos.X = Left + 2;
908 coPos.Y = Top + 2;
909 strcpy (Buffer, "Size of new partition:");
910 iLeft = coPos.X + strlen (Buffer) + 1;
911 iTop = coPos.Y;
912 WriteConsoleOutputCharacters (Buffer,
913 strlen (Buffer),
914 coPos);
915
916 sprintf (Buffer, "MB (max. %d MB)", MaxSize);
917 coPos.X = iLeft + PARTITION_SIZE_INPUT_FIELD_LENGTH + 1;
918 coPos.Y = iTop;
919 WriteConsoleOutputCharacters (Buffer,
920 strlen (Buffer),
921 coPos);
922
923 Buffer[0] = 0;
924 Index = 0;
925 DrawInputField (PARTITION_SIZE_INPUT_FIELD_LENGTH,
926 iLeft,
927 iTop,
928 Buffer);
929
930 while (TRUE)
931 {
932 ConInKey (&Ir);
933
934 if ((Ir.Event.KeyEvent.uChar.AsciiChar == 0x00) &&
935 (Ir.Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
936 {
937 if (Quit != NULL)
938 *Quit = TRUE;
939 Buffer[0] = 0;
940 break;
941 }
942 else if (Ir.Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
943 {
944 break;
945 }
946 else if (Ir.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESCAPE */
947 {
948 if (Cancel != NULL)
949 *Cancel = TRUE;
950 Buffer[0] = 0;
951 break;
952 }
953 else if ((Ir.Event.KeyEvent.wVirtualKeyCode == VK_BACK) && /* BACKSPACE */
954 (Index > 0))
955 {
956 Index--;
957 Buffer[Index] = 0;
958 DrawInputField (PARTITION_SIZE_INPUT_FIELD_LENGTH,
959 iLeft,
960 iTop,
961 Buffer);
962 }
963 else if ((Ir.Event.KeyEvent.uChar.AsciiChar != 0x00) &&
964 (Index < PARTITION_SIZE_INPUT_FIELD_LENGTH))
965 {
966 ch = Ir.Event.KeyEvent.uChar.AsciiChar;
967 if ((ch >= '0') && (ch <= '9'))
968 {
969 Buffer[Index] = ch;
970 Index++;
971 Buffer[Index] = 0;
972 DrawInputField (PARTITION_SIZE_INPUT_FIELD_LENGTH,
973 iLeft,
974 iTop,
975 Buffer);
976 }
977 }
978 }
979
980 strcpy (InputBuffer,
981 Buffer);
982 }
983
984
985 static PAGE_NUMBER
986 CreatePartitionPage (PINPUT_RECORD Ir)
987 {
988 PDISKENTRY DiskEntry;
989 PPARTENTRY PartEntry;
990 SHORT xScreen;
991 SHORT yScreen;
992 BOOLEAN Quit;
993 BOOLEAN Cancel;
994 CHAR InputBuffer[50];
995 ULONG MaxSize;
996 ULONGLONG PartSize;
997 ULONGLONG DiskSize;
998 PCHAR Unit;
999
1000 if (PartitionList == NULL ||
1001 PartitionList->CurrentDisk == NULL ||
1002 PartitionList->CurrentPartition == NULL)
1003 {
1004 /* FIXME: show an error dialog */
1005 return QUIT_PAGE;
1006 }
1007
1008 DiskEntry = PartitionList->CurrentDisk;
1009 PartEntry = PartitionList->CurrentPartition;
1010
1011 SetStatusText (" Please wait...");
1012
1013 GetScreenSize (&xScreen, &yScreen);
1014
1015 SetTextXY (6, 8, "You have chosen to create a new partition on");
1016
1017 #if 0
1018 if (DiskEntry->DiskSize >= 0x280000000ULL) /* 10 GB */
1019 {
1020 DiskSize = (DiskEntry->DiskSize + (1 << 29)) >> 30;
1021 Unit = "GB";
1022 }
1023 else
1024 #endif
1025 {
1026 DiskSize = (DiskEntry->DiskSize + (1 << 19)) >> 20;
1027 if (DiskSize == 0)
1028 DiskSize = 1;
1029 Unit = "MB";
1030 }
1031
1032 if (DiskEntry->DriverName.Length > 0)
1033 {
1034 PrintTextXY (6, 10,
1035 "%I64u %s Harddisk %lu (Port=%hu, Bus=%hu, Id=%hu) on %wZ.",
1036 DiskSize,
1037 Unit,
1038 DiskEntry->DiskNumber,
1039 DiskEntry->Port,
1040 DiskEntry->Bus,
1041 DiskEntry->Id,
1042 &DiskEntry->DriverName);
1043 }
1044 else
1045 {
1046 PrintTextXY (6, 10,
1047 "%I64u %s Harddisk %lu (Port=%hu, Bus=%hu, Id=%hu).",
1048 DiskSize,
1049 Unit,
1050 DiskEntry->DiskNumber,
1051 DiskEntry->Port,
1052 DiskEntry->Bus,
1053 DiskEntry->Id);
1054 }
1055
1056
1057 SetTextXY (6, 12, "Please enter the size of the new partition in megabytes.");
1058
1059 #if 0
1060 PrintTextXY (8, 10, "Maximum size of the new partition is %I64u MB",
1061 PartitionList->CurrentPartition->UnpartitionedLength / (1024*1024));
1062 #endif
1063
1064 SetStatusText (" ENTER = Create Partition ESC = Cancel F3 = Quit");
1065
1066 PartEntry = PartitionList->CurrentPartition;
1067 while (TRUE)
1068 {
1069 MaxSize = (PartEntry->UnpartitionedLength + (1 << 19)) >> 20; /* in MBytes (rounded) */
1070 ShowPartitionSizeInputBox (12, 14, xScreen - 12, 17, /* left, top, right, bottom */
1071 MaxSize, InputBuffer, &Quit, &Cancel);
1072 if (Quit == TRUE)
1073 {
1074 if (ConfirmQuit (Ir) == TRUE)
1075 {
1076 return QUIT_PAGE;
1077 }
1078 }
1079 else if (Cancel == TRUE)
1080 {
1081 return SELECT_PARTITION_PAGE;
1082 }
1083 else
1084 {
1085 PartSize = atoi (InputBuffer);
1086 if (PartSize < 1)
1087 {
1088 /* Too small */
1089 continue;
1090 }
1091
1092 if (PartSize > MaxSize)
1093 {
1094 /* Too large */
1095 continue;
1096 }
1097
1098 /* Convert to bytes */
1099 if (PartSize == MaxSize)
1100 {
1101 /* Use all of the unpartitioned disk space */
1102 PartSize = PartEntry->UnpartitionedLength;
1103 }
1104 else
1105 {
1106 /* Round-up by cylinder size */
1107 PartSize = ROUND_UP (PartSize * 1024 * 1024,
1108 DiskEntry->CylinderSize);
1109
1110 /* But never get larger than the unpartitioned disk space */
1111 if (PartSize > PartEntry->UnpartitionedLength)
1112 PartSize = PartEntry->UnpartitionedLength;
1113 }
1114
1115 DPRINT ("Partition size: %I64u bytes\n", PartSize);
1116
1117 CreateNewPartition (PartitionList,
1118 PartSize,
1119 FALSE);
1120
1121 return SELECT_PARTITION_PAGE;
1122 }
1123 }
1124
1125 return CREATE_PARTITION_PAGE;
1126 }
1127
1128
1129 static PAGE_NUMBER
1130 DeletePartitionPage (PINPUT_RECORD Ir)
1131 {
1132 PDISKENTRY DiskEntry;
1133 PPARTENTRY PartEntry;
1134 ULONGLONG DiskSize;
1135 ULONGLONG PartSize;
1136 PCHAR Unit;
1137 PCHAR PartType;
1138
1139 if (PartitionList == NULL ||
1140 PartitionList->CurrentDisk == NULL ||
1141 PartitionList->CurrentPartition == NULL)
1142 {
1143 /* FIXME: show an error dialog */
1144 return QUIT_PAGE;
1145 }
1146
1147 DiskEntry = PartitionList->CurrentDisk;
1148 PartEntry = PartitionList->CurrentPartition;
1149
1150 SetTextXY (6, 8, "You have chosen to delete the partition");
1151
1152 /* Determine partition type */
1153 PartType = NULL;
1154 if (PartEntry->New == TRUE)
1155 {
1156 PartType = "New (Unformatted)";
1157 }
1158 else if (PartEntry->Unpartitioned == FALSE)
1159 {
1160 if ((PartEntry->PartInfo[0].PartitionType == PARTITION_FAT_12) ||
1161 (PartEntry->PartInfo[0].PartitionType == PARTITION_FAT_16) ||
1162 (PartEntry->PartInfo[0].PartitionType == PARTITION_HUGE) ||
1163 (PartEntry->PartInfo[0].PartitionType == PARTITION_XINT13))
1164 {
1165 PartType = "FAT";
1166 }
1167 else if ((PartEntry->PartInfo[0].PartitionType == PARTITION_FAT32) ||
1168 (PartEntry->PartInfo[0].PartitionType == PARTITION_FAT32_XINT13))
1169 {
1170 PartType = "FAT32";
1171 }
1172 else if (PartEntry->PartInfo[0].PartitionType == PARTITION_IFS)
1173 {
1174 PartType = "NTFS"; /* FIXME: Not quite correct! */
1175 }
1176 }
1177
1178 #if 0
1179 if (PartEntry->PartInfo[0].PartitionLength.QuadPart >= 0x280000000ULL) /* 10 GB */
1180 {
1181 PartSize = (PartEntry->PartInfo[0].PartitionLength.QuadPart + (1 << 29)) >> 30;
1182 Unit = "GB";
1183 }
1184 else
1185 #endif
1186 if (PartEntry->PartInfo[0].PartitionLength.QuadPart >= 0xA00000ULL) /* 10 MB */
1187 {
1188 PartSize = (PartEntry->PartInfo[0].PartitionLength.QuadPart + (1 << 19)) >> 20;
1189 Unit = "MB";
1190 }
1191 else
1192 {
1193 PartSize = (PartEntry->PartInfo[0].PartitionLength.QuadPart + (1 << 9)) >> 10;
1194 Unit = "KB";
1195 }
1196
1197 if (PartType == NULL)
1198 {
1199 PrintTextXY (6, 10,
1200 " %c%c Type %lu %I64u %s",
1201 (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
1202 (PartEntry->DriveLetter == 0) ? '-' : ':',
1203 PartEntry->PartInfo[0].PartitionType,
1204 PartSize,
1205 Unit);
1206 }
1207 else
1208 {
1209 PrintTextXY (6, 10,
1210 " %c%c %s %I64u %s",
1211 (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
1212 (PartEntry->DriveLetter == 0) ? '-' : ':',
1213 PartType,
1214 PartSize,
1215 Unit);
1216 }
1217
1218 #if 0
1219 if (DiskEntry->DiskSize >= 0x280000000ULL) /* 10 GB */
1220 {
1221 DiskSize = (DiskEntry->DiskSize + (1 << 29)) >> 30;
1222 Unit = "GB";
1223 }
1224 else
1225 #endif
1226 {
1227 DiskSize = (DiskEntry->DiskSize + (1 << 19)) >> 20;
1228 if (DiskSize == 0)
1229 DiskSize = 1;
1230 Unit = "MB";
1231 }
1232
1233 if (DiskEntry->DriverName.Length > 0)
1234 {
1235 PrintTextXY (6, 12,
1236 "on %I64u %s Harddisk %lu (Port=%hu, Bus=%hu, Id=%hu) on %wZ.",
1237 DiskSize,
1238 Unit,
1239 DiskEntry->DiskNumber,
1240 DiskEntry->Port,
1241 DiskEntry->Bus,
1242 DiskEntry->Id,
1243 &DiskEntry->DriverName);
1244 }
1245 else
1246 {
1247 PrintTextXY (6, 12,
1248 "on %I64u %s Harddisk %lu (Port=%hu, Bus=%hu, Id=%hu).",
1249 DiskSize,
1250 Unit,
1251 DiskEntry->DiskNumber,
1252 DiskEntry->Port,
1253 DiskEntry->Bus,
1254 DiskEntry->Id);
1255 }
1256
1257 SetTextXY (8, 18, "\x07 Press D to delete the partition.");
1258 SetTextXY (11, 19, "WARNING: All data on this partition will be lost!");
1259
1260 SetTextXY (8, 21, "\x07 Press ESC to cancel.");
1261
1262 SetStatusText (" D = Delete Partition ESC = Cancel F3 = Quit");
1263
1264 while (TRUE)
1265 {
1266 ConInKey (Ir);
1267
1268 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1269 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1270 {
1271 if (ConfirmQuit (Ir) == TRUE)
1272 {
1273 return QUIT_PAGE;
1274 }
1275 break;
1276 }
1277 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESC */
1278 {
1279 return SELECT_PARTITION_PAGE;
1280 }
1281 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_D) /* D */
1282 {
1283 DeleteCurrentPartition (PartitionList);
1284
1285 return SELECT_PARTITION_PAGE;
1286 }
1287 }
1288
1289 return DELETE_PARTITION_PAGE;
1290 }
1291
1292
1293 static PAGE_NUMBER
1294 SelectFileSystemPage (PINPUT_RECORD Ir)
1295 {
1296 PDISKENTRY DiskEntry;
1297 PPARTENTRY PartEntry;
1298 ULONGLONG DiskSize;
1299 ULONGLONG PartSize;
1300 PCHAR DiskUnit;
1301 PCHAR PartUnit;
1302 PCHAR PartType;
1303
1304 if (PartitionList == NULL ||
1305 PartitionList->CurrentDisk == NULL ||
1306 PartitionList->CurrentPartition == NULL)
1307 {
1308 /* FIXME: show an error dialog */
1309 return QUIT_PAGE;
1310 }
1311
1312 DiskEntry = PartitionList->CurrentDisk;
1313 PartEntry = PartitionList->CurrentPartition;
1314
1315 /* adjust disk size */
1316 if (DiskEntry->DiskSize >= 0x280000000ULL) /* 10 GB */
1317 {
1318 DiskSize = (DiskEntry->DiskSize + (1 << 29)) >> 30;
1319 DiskUnit = "GB";
1320 }
1321 else
1322 {
1323 DiskSize = (DiskEntry->DiskSize + (1 << 19)) >> 20;
1324 DiskUnit = "MB";
1325 }
1326
1327 /* adjust partition size */
1328 if (PartEntry->PartInfo[0].PartitionLength.QuadPart >= 0x280000000ULL) /* 10 GB */
1329 {
1330 PartSize = (PartEntry->PartInfo[0].PartitionLength.QuadPart + (1 << 29)) >> 30;
1331 PartUnit = "GB";
1332 }
1333 else
1334 {
1335 PartSize = (PartEntry->PartInfo[0].PartitionLength.QuadPart + (1 << 19)) >> 20;
1336 PartUnit = "MB";
1337 }
1338
1339 /* adjust partition type */
1340 if ((PartEntry->PartInfo[0].PartitionType == PARTITION_FAT_12) ||
1341 (PartEntry->PartInfo[0].PartitionType == PARTITION_FAT_16) ||
1342 (PartEntry->PartInfo[0].PartitionType == PARTITION_HUGE) ||
1343 (PartEntry->PartInfo[0].PartitionType == PARTITION_XINT13))
1344 {
1345 PartType = "FAT";
1346 }
1347 else if ((PartEntry->PartInfo[0].PartitionType == PARTITION_FAT32) ||
1348 (PartEntry->PartInfo[0].PartitionType == PARTITION_FAT32_XINT13))
1349 {
1350 PartType = "FAT32";
1351 }
1352 else if (PartEntry->PartInfo[0].PartitionType == PARTITION_IFS)
1353 {
1354 PartType = "NTFS"; /* FIXME: Not quite correct! */
1355 }
1356 else if (PartEntry->PartInfo[0].PartitionType == PARTITION_ENTRY_UNUSED)
1357 {
1358 PartType = "Unused";
1359 }
1360 else
1361 {
1362 PartType = "Unknown";
1363 }
1364
1365 if (PartEntry->AutoCreate == TRUE)
1366 {
1367 SetTextXY(6, 8, "Setup created a new partition on");
1368
1369 #if 0
1370 PrintTextXY(8, 10, "Partition %lu (%I64u %s) %s of",
1371 PartEntry->PartInfo[0].PartitionNumber,
1372 PartSize,
1373 PartUnit,
1374 PartType);
1375 #endif
1376
1377 PrintTextXY(8, 10, "Harddisk %lu (%I64u %s), Port=%hu, Bus=%hu, Id=%hu (%wZ).",
1378 DiskEntry->DiskNumber,
1379 DiskSize,
1380 DiskUnit,
1381 DiskEntry->Port,
1382 DiskEntry->Bus,
1383 DiskEntry->Id,
1384 &DiskEntry->DriverName);
1385
1386 SetTextXY(6, 12, "This Partition will be formatted next.");
1387
1388
1389 PartEntry->AutoCreate = FALSE;
1390 }
1391 else if (PartEntry->New == TRUE)
1392 {
1393 SetTextXY(6, 8, "You chose to install ReactOS on a new or unformatted Partition.");
1394 SetTextXY(6, 10, "This Partition will be formatted next.");
1395 }
1396 else
1397 {
1398 SetTextXY(6, 8, "Setup install ReactOS onto Partition");
1399
1400 if (PartType == NULL)
1401 {
1402 PrintTextXY (8, 10,
1403 "%c%c Type %lu %I64u %s",
1404 (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
1405 (PartEntry->DriveLetter == 0) ? '-' : ':',
1406 PartEntry->PartInfo[0].PartitionType,
1407 PartSize,
1408 PartUnit);
1409 }
1410 else
1411 {
1412 PrintTextXY (8, 10,
1413 "%c%c %s %I64u %s",
1414 (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
1415 (PartEntry->DriveLetter == 0) ? '-' : ':',
1416 PartType,
1417 PartSize,
1418 PartUnit);
1419 }
1420
1421 PrintTextXY(6, 12, "on Harddisk %lu (%I64u %s), Port=%hu, Bus=%hu, Id=%hu (%wZ).",
1422 DiskEntry->DiskNumber,
1423 DiskSize,
1424 DiskUnit,
1425 DiskEntry->Port,
1426 DiskEntry->Bus,
1427 DiskEntry->Id,
1428 &DiskEntry->DriverName);
1429 }
1430
1431
1432 SetTextXY(6, 17, "Select a file system from the list below.");
1433
1434 SetTextXY(8, 19, "\x07 Press UP or DOWN to select a file system.");
1435 SetTextXY(8, 21, "\x07 Press ENTER to format the partition.");
1436 SetTextXY(8, 23, "\x07 Press ESC to select another partition.");
1437
1438 if (FileSystemList == NULL)
1439 {
1440 FileSystemList = CreateFileSystemList (6, 26, PartEntry->New, FsFat);
1441 if (FileSystemList == NULL)
1442 {
1443 /* FIXME: show an error dialog */
1444 return QUIT_PAGE;
1445 }
1446
1447 /* FIXME: Add file systems to list */
1448 }
1449 DrawFileSystemList (FileSystemList);
1450
1451 SetStatusText (" ENTER = Continue ESC = Cancel F3 = Quit");
1452
1453 while (TRUE)
1454 {
1455 ConInKey (Ir);
1456
1457 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1458 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1459 {
1460 if (ConfirmQuit (Ir) == TRUE)
1461 {
1462 return QUIT_PAGE;
1463 }
1464 break;
1465 }
1466 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1467 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
1468 {
1469 return SELECT_PARTITION_PAGE;
1470 }
1471 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1472 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1473 {
1474 ScrollDownFileSystemList (FileSystemList);
1475 }
1476 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1477 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1478 {
1479 ScrollUpFileSystemList (FileSystemList);
1480 }
1481 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
1482 {
1483 if (FileSystemList->CurrentFileSystem == FsKeep)
1484 {
1485 return CHECK_FILE_SYSTEM_PAGE;
1486 }
1487 else
1488 {
1489 return FORMAT_PARTITION_PAGE;
1490 }
1491 }
1492 }
1493
1494 return SELECT_FILE_SYSTEM_PAGE;
1495 }
1496
1497
1498 static ULONG
1499 FormatPartitionPage (PINPUT_RECORD Ir)
1500 {
1501 WCHAR PathBuffer[MAX_PATH];
1502 PDISKENTRY DiskEntry;
1503 PPARTENTRY PartEntry;
1504 PLIST_ENTRY Entry;
1505 NTSTATUS Status;
1506
1507 //#ifndef NDEBUG
1508 ULONG Line;
1509 ULONG i;
1510 //#endif
1511
1512
1513 SetTextXY(6, 8, "Format partition");
1514
1515 SetTextXY(6, 10, "Setup will now format the partition. Press ENTER to continue.");
1516
1517 SetStatusText(" ENTER = Continue F3 = Quit");
1518
1519
1520 if (PartitionList == NULL ||
1521 PartitionList->CurrentDisk == NULL ||
1522 PartitionList->CurrentPartition == NULL)
1523 {
1524 /* FIXME: show an error dialog */
1525 return QUIT_PAGE;
1526 }
1527
1528 DiskEntry = PartitionList->CurrentDisk;
1529 PartEntry = PartitionList->CurrentPartition;
1530
1531 while(TRUE)
1532 {
1533 ConInKey(Ir);
1534
1535 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1536 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1537 {
1538 if (ConfirmQuit (Ir) == TRUE)
1539 {
1540 return QUIT_PAGE;
1541 }
1542 break;
1543 }
1544 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
1545 {
1546 SetStatusText (" Please wait ...");
1547
1548 switch (FileSystemList->CurrentFileSystem)
1549 {
1550 case FsFat:
1551 if (DiskEntry->UseLba == FALSE)
1552 {
1553 if (PartEntry->PartInfo[0].PartitionLength.QuadPart < (32ULL * 1024ULL * 1024ULL))
1554 {
1555 /* FAT16 CHS partition (disk is smaller than 32MB) */
1556 PartEntry->PartInfo[0].PartitionType = PARTITION_FAT_16;
1557 }
1558 else
1559 {
1560 /* FAT16 CHS partition (disk is smaller than 8.4GB) */
1561 PartEntry->PartInfo[0].PartitionType = PARTITION_HUGE;
1562 }
1563 }
1564 else if (PartEntry->PartInfo[0].PartitionLength.QuadPart < (2ULL * 1024ULL * 1024ULL * 1024ULL))
1565 {
1566 /* FAT16 LBA partition (partition is smaller than 2GB) */
1567 PartEntry->PartInfo[0].PartitionType = PARTITION_XINT13;
1568 }
1569 else
1570 {
1571 /* FAT32 LBA partition (partition is at least 2GB) */
1572 PartEntry->PartInfo[0].PartitionType = PARTITION_FAT32_XINT13;
1573 }
1574 break;
1575
1576 case FsKeep:
1577 break;
1578
1579 default:
1580 return QUIT_PAGE;
1581 }
1582
1583 CheckActiveBootPartition (PartitionList);
1584
1585 //#ifndef NDEBUG
1586 PrintTextXY (6, 12,
1587 "Disk: %I64u Cylinder: %I64u Track: %I64u",
1588 DiskEntry->DiskSize,
1589 DiskEntry->CylinderSize,
1590 DiskEntry->TrackSize);
1591
1592 Line = 13;
1593 DiskEntry = PartitionList->CurrentDisk;
1594 Entry = DiskEntry->PartListHead.Flink;
1595 while (Entry != &DiskEntry->PartListHead)
1596 {
1597 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
1598
1599 if (PartEntry->Unpartitioned == FALSE)
1600 {
1601
1602 for (i = 0; i < 4; i++)
1603 {
1604 PrintTextXY (6, Line,
1605 "%2u: %2u %c %12I64u %12I64u %2u %c",
1606 i,
1607 PartEntry->PartInfo[i].PartitionNumber,
1608 PartEntry->PartInfo[i].BootIndicator ? 'A' : '-',
1609 PartEntry->PartInfo[i].StartingOffset.QuadPart,
1610 PartEntry->PartInfo[i].PartitionLength.QuadPart,
1611 PartEntry->PartInfo[i].PartitionType,
1612 PartEntry->PartInfo[i].RewritePartition ? '*' : ' ');
1613
1614 Line++;
1615 }
1616
1617 Line++;
1618 }
1619
1620 Entry = Entry->Flink;
1621 }
1622 //#endif
1623
1624 if (WritePartitionsToDisk (PartitionList) == FALSE)
1625 {
1626 DPRINT ("WritePartitionsToDisk() failed\n");
1627
1628 PopupError ("Setup failed to write partition tables.\n",
1629 "ENTER = Reboot computer");
1630
1631 while (TRUE)
1632 {
1633 ConInKey (Ir);
1634
1635 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1636 {
1637 return QUIT_PAGE;
1638 }
1639 }
1640 }
1641
1642
1643 /* Set DestinationRootPath */
1644 RtlFreeUnicodeString (&DestinationRootPath);
1645 swprintf (PathBuffer,
1646 L"\\Device\\Harddisk%lu\\Partition%lu",
1647 PartitionList->CurrentDisk->DiskNumber,
1648 PartitionList->CurrentPartition->PartInfo[0].PartitionNumber);
1649 RtlCreateUnicodeString (&DestinationRootPath,
1650 PathBuffer);
1651 DPRINT1 ("DestinationRootPath: %wZ\n", &DestinationRootPath);
1652
1653
1654 /* Set SystemRootPath */
1655 RtlFreeUnicodeString (&SystemRootPath);
1656 swprintf (PathBuffer,
1657 L"\\Device\\Harddisk%lu\\Partition%lu",
1658 PartitionList->ActiveBootDisk->DiskNumber,
1659 PartitionList->ActiveBootPartition->PartInfo[0].PartitionNumber);
1660 RtlCreateUnicodeString (&SystemRootPath,
1661 PathBuffer);
1662 DPRINT1 ("SystemRootPath: %wZ\n", &SystemRootPath);
1663
1664
1665 switch (FileSystemList->CurrentFileSystem)
1666 {
1667 case FsFat:
1668 Status = FormatPartition (&DestinationRootPath);
1669 if (!NT_SUCCESS (Status))
1670 {
1671 DPRINT1 ("FormatPartition() failed with status 0x%.08x\n", Status);
1672 /* FIXME: show an error dialog */
1673 return QUIT_PAGE;
1674 }
1675
1676 /* FIXME: Install boot code. This is a hack! */
1677 wcscpy (PathBuffer, SourceRootPath.Buffer);
1678 wcscat (PathBuffer, L"\\loader\\fat32.bin");
1679
1680 DPRINT1 ("Install FAT32 bootcode: %S ==> %S\n", PathBuffer,
1681 DestinationRootPath.Buffer);
1682 Status = InstallFat32BootCodeToDisk (PathBuffer,
1683 DestinationRootPath.Buffer);
1684 if (!NT_SUCCESS (Status))
1685 {
1686 DPRINT1 ("InstallFat32BootCodeToDisk() failed with status 0x%.08x\n", Status);
1687 /* FIXME: show an error dialog */
1688 return QUIT_PAGE;
1689 }
1690 break;
1691
1692 case FsKeep:
1693 break;
1694
1695 default:
1696 return QUIT_PAGE;
1697 }
1698
1699 SetStatusText (" Done. Press any key ...");
1700 ConInKey(Ir);
1701
1702 return INSTALL_DIRECTORY_PAGE;
1703 }
1704 }
1705
1706 return FORMAT_PARTITION_PAGE;
1707 }
1708
1709
1710 static ULONG
1711 CheckFileSystemPage(PINPUT_RECORD Ir)
1712 {
1713 WCHAR PathBuffer[MAX_PATH];
1714
1715 SetTextXY(6, 8, "Check file system");
1716
1717 SetTextXY(6, 10, "At present, ReactOS can not check file systems.");
1718
1719 SetStatusText(" Please wait ...");
1720
1721
1722 SetStatusText(" ENTER = Continue F3 = Quit");
1723
1724
1725 /* Set DestinationRootPath */
1726 RtlFreeUnicodeString (&DestinationRootPath);
1727 swprintf (PathBuffer,
1728 L"\\Device\\Harddisk%lu\\Partition%lu",
1729 PartitionList->CurrentDisk->DiskNumber,
1730 PartitionList->CurrentPartition->PartInfo[0].PartitionNumber);
1731 RtlCreateUnicodeString (&DestinationRootPath,
1732 PathBuffer);
1733 DPRINT1 ("DestinationRootPath: %wZ\n", &DestinationRootPath);
1734
1735 /* Set SystemRootPath */
1736 RtlFreeUnicodeString (&SystemRootPath);
1737 swprintf (PathBuffer,
1738 L"\\Device\\Harddisk%lu\\Partition%lu",
1739 PartitionList->ActiveBootDisk->DiskNumber,
1740 PartitionList->ActiveBootPartition->PartInfo[0].PartitionNumber);
1741 RtlCreateUnicodeString (&SystemRootPath,
1742 PathBuffer);
1743 DPRINT1 ("SystemRootPath: %wZ\n", &SystemRootPath);
1744
1745
1746 while(TRUE)
1747 {
1748 ConInKey(Ir);
1749
1750 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1751 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1752 {
1753 if (ConfirmQuit(Ir) == TRUE)
1754 return(QUIT_PAGE);
1755 break;
1756 }
1757 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1758 {
1759 return(INSTALL_DIRECTORY_PAGE);
1760 }
1761 }
1762
1763 return(CHECK_FILE_SYSTEM_PAGE);
1764 }
1765
1766
1767 static PAGE_NUMBER
1768 InstallDirectoryPage(PINPUT_RECORD Ir)
1769 {
1770 PDISKENTRY DiskEntry;
1771 PPARTENTRY PartEntry;
1772 WCHAR PathBuffer[MAX_PATH];
1773 WCHAR InstallDir[51];
1774 PWCHAR DefaultPath;
1775 INFCONTEXT Context;
1776 ULONG Length;
1777 NTSTATUS Status;
1778
1779 if (PartitionList == NULL ||
1780 PartitionList->CurrentDisk == NULL ||
1781 PartitionList->CurrentPartition == NULL)
1782 {
1783 /* FIXME: show an error dialog */
1784 return QUIT_PAGE;
1785 }
1786
1787 DiskEntry = PartitionList->CurrentDisk;
1788 PartEntry = PartitionList->CurrentPartition;
1789
1790 /* Search for 'DefaultPath' in the 'SetupData' section */
1791 if (!InfFindFirstLine (SetupInf, L"SetupData", L"DefaultPath", &Context))
1792 {
1793 PopupError("Setup failed to find the 'SetupData' section\n"
1794 "in TXTSETUP.SIF.\n",
1795 "ENTER = Reboot computer");
1796
1797 while (TRUE)
1798 {
1799 ConInKey (Ir);
1800
1801 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1802 {
1803 return QUIT_PAGE;
1804 }
1805 }
1806 }
1807
1808 /* Read the 'DefaultPath' data */
1809 if (InfGetData (&Context, NULL, &DefaultPath))
1810 {
1811 wcscpy(InstallDir, DefaultPath);
1812 }
1813 else
1814 {
1815 wcscpy(InstallDir, L"\\ReactOS");
1816 }
1817 Length = wcslen(InstallDir);
1818
1819 SetTextXY(6, 8, "Setup installs ReactOS files onto the selected partition. Choose a");
1820 SetTextXY(6, 9, "directory where you want ReactOS to be installed:");
1821
1822 SetInputTextXY(8, 11, 51, InstallDir);
1823
1824 SetTextXY(6, 14, "To change the suggested directory, press BACKSPACE to delete");
1825 SetTextXY(6, 15, "characters and then type the directory where you want ReactOS to");
1826 SetTextXY(6, 16, "be installed.");
1827
1828 SetStatusText(" ENTER = Continue F3 = Quit");
1829
1830 while(TRUE)
1831 {
1832 ConInKey(Ir);
1833
1834 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1835 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1836 {
1837 if (ConfirmQuit(Ir) == TRUE)
1838 return(QUIT_PAGE);
1839 break;
1840 }
1841 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1842 {
1843 /* Create 'InstallPath' string */
1844 RtlFreeUnicodeString(&InstallPath);
1845 RtlCreateUnicodeString(&InstallPath,
1846 InstallDir);
1847
1848 /* Create 'DestinationPath' string */
1849 RtlFreeUnicodeString(&DestinationPath);
1850 wcscpy(PathBuffer,
1851 DestinationRootPath.Buffer);
1852 if (InstallDir[0] != L'\\')
1853 wcscat(PathBuffer,
1854 L"\\");
1855 wcscat(PathBuffer, InstallDir);
1856 RtlCreateUnicodeString(&DestinationPath,
1857 PathBuffer);
1858
1859 /* Create 'DestinationArcPath' */
1860 RtlFreeUnicodeString(&DestinationArcPath);
1861 swprintf(PathBuffer,
1862 L"multi(0)disk(0)rdisk(%lu)partition(%lu)",
1863 DiskEntry->DiskNumber,
1864 PartEntry->PartInfo[0].PartitionNumber);
1865 if (InstallDir[0] != L'\\')
1866 wcscat(PathBuffer,
1867 L"\\");
1868 wcscat(PathBuffer, InstallDir);
1869 RtlCreateUnicodeString(&DestinationArcPath,
1870 PathBuffer);
1871
1872 return(PREPARE_COPY_PAGE);
1873 }
1874 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x08) /* BACKSPACE */
1875 {
1876 if (Length > 0)
1877 {
1878 Length--;
1879 InstallDir[Length] = 0;
1880 SetInputTextXY(8, 11, 51, InstallDir);
1881 }
1882 }
1883 else if (isprint(Ir->Event.KeyEvent.uChar.AsciiChar))
1884 {
1885 if (Length < 50)
1886 {
1887 InstallDir[Length] = (WCHAR)Ir->Event.KeyEvent.uChar.AsciiChar;
1888 Length++;
1889 InstallDir[Length] = 0;
1890 SetInputTextXY(8, 11, 51, InstallDir);
1891 }
1892 }
1893 }
1894
1895 return(INSTALL_DIRECTORY_PAGE);
1896 }
1897
1898
1899 static PAGE_NUMBER
1900 PrepareCopyPage(PINPUT_RECORD Ir)
1901 {
1902 WCHAR PathBuffer[MAX_PATH];
1903 INFCONTEXT FilesContext;
1904 INFCONTEXT DirContext;
1905 PWCHAR KeyName;
1906 PWCHAR KeyValue;
1907 ULONG Length;
1908 NTSTATUS Status;
1909
1910 PWCHAR FileKeyName;
1911 PWCHAR FileKeyValue;
1912 PWCHAR DirKeyName;
1913 PWCHAR DirKeyValue;
1914
1915 SetTextXY(6, 8, "Setup prepares your computer for copying the ReactOS files. ");
1916
1917
1918 /*
1919 * Build the file copy list
1920 */
1921 SetStatusText(" Building the file copy list...");
1922
1923 /* Search for the 'SourceFiles' section */
1924 if (!InfFindFirstLine (SetupInf, L"SourceFiles", NULL, &FilesContext))
1925 {
1926 PopupError("Setup failed to find the 'SourceFiles' section\n"
1927 "in TXTSETUP.SIF.\n",
1928 "ENTER = Reboot computer");
1929
1930 while(TRUE)
1931 {
1932 ConInKey(Ir);
1933
1934 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1935 {
1936 return(QUIT_PAGE);
1937 }
1938 }
1939 }
1940
1941
1942 /* Create the file queue */
1943 SetupFileQueue = SetupOpenFileQueue();
1944 if (SetupFileQueue == NULL)
1945 {
1946 PopupError("Setup failed to open the copy file queue.\n",
1947 "ENTER = Reboot computer");
1948
1949 while(TRUE)
1950 {
1951 ConInKey(Ir);
1952
1953 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1954 {
1955 return(QUIT_PAGE);
1956 }
1957 }
1958 }
1959
1960 /*
1961 * Enumerate the files in the 'SourceFiles' section
1962 * and add them to the file queue.
1963 */
1964 do
1965 {
1966 if (!InfGetData (&FilesContext, &FileKeyName, &FileKeyValue))
1967 break;
1968
1969 DPRINT1("FileKeyName: '%S' FileKeyValue: '%S'\n", FileKeyName, FileKeyValue);
1970
1971 /* Lookup target directory */
1972 if (!InfFindFirstLine (SetupInf, L"Directories", FileKeyValue, &DirContext))
1973 {
1974 /* FIXME: Handle error! */
1975 DPRINT1("InfFindFirstLine() failed\n");
1976 break;
1977 }
1978
1979 if (!InfGetData (&DirContext, NULL, &DirKeyValue))
1980 {
1981 /* FIXME: Handle error! */
1982 DPRINT1("InfGetData() failed\n");
1983 break;
1984 }
1985
1986 if (!SetupQueueCopy(SetupFileQueue,
1987 SourceRootPath.Buffer,
1988 L"\\reactos",
1989 FileKeyName,
1990 DirKeyValue,
1991 NULL))
1992 {
1993 /* FIXME: Handle error! */
1994 DPRINT1("SetupQueueCopy() failed\n");
1995 }
1996 }
1997 while (InfFindNextLine(&FilesContext, &FilesContext));
1998
1999
2000 /* Create directories */
2001 SetStatusText(" Creating directories...");
2002
2003 /*
2004 * FIXME:
2005 * Install directories like '\reactos\test' are not handled yet.
2006 */
2007
2008 /* Get destination path */
2009 wcscpy(PathBuffer, DestinationPath.Buffer);
2010
2011 /* Remove trailing backslash */
2012 Length = wcslen(PathBuffer);
2013 if ((Length > 0) && (PathBuffer[Length - 1] == '\\'))
2014 {
2015 PathBuffer[Length - 1] = 0;
2016 }
2017
2018 /* Create the install directory */
2019 Status = CreateDirectory(PathBuffer);
2020 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION)
2021 {
2022 DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer, Status);
2023 PopupError("Setup could not create the install directory.",
2024 "ENTER = Reboot computer");
2025
2026 while(TRUE)
2027 {
2028 ConInKey(Ir);
2029
2030 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2031 {
2032 return(QUIT_PAGE);
2033 }
2034 }
2035 }
2036
2037
2038 /* Search for the 'Directories' section */
2039 if (!InfFindFirstLine(SetupInf, L"Directories", NULL, &DirContext))
2040 {
2041 PopupError("Setup failed to find the 'Directories' section\n"
2042 "in TXTSETUP.SIF.\n",
2043 "ENTER = Reboot computer");
2044
2045 while(TRUE)
2046 {
2047 ConInKey(Ir);
2048
2049 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2050 {
2051 return(QUIT_PAGE);
2052 }
2053 }
2054 }
2055
2056 /* Enumerate the directory values and create the subdirectories */
2057 do
2058 {
2059 if (!InfGetData (&DirContext, NULL, &KeyValue))
2060 break;
2061
2062 if (KeyValue[0] == L'\\' && KeyValue[1] != 0)
2063 {
2064 DPRINT("Absolute Path: '%S'\n", KeyValue);
2065
2066 wcscpy(PathBuffer, DestinationRootPath.Buffer);
2067 wcscat(PathBuffer, KeyValue);
2068
2069 DPRINT("FullPath: '%S'\n", PathBuffer);
2070 }
2071 else if (KeyValue[0] != L'\\')
2072 {
2073 DPRINT("RelativePath: '%S'\n", KeyValue);
2074 wcscpy(PathBuffer, DestinationPath.Buffer);
2075 wcscat(PathBuffer, L"\\");
2076 wcscat(PathBuffer, KeyValue);
2077
2078 DPRINT("FullPath: '%S'\n", PathBuffer);
2079
2080 Status = CreateDirectory(PathBuffer);
2081 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION)
2082 {
2083 DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer, Status);
2084 PopupError("Setup could not create install directories.",
2085 "ENTER = Reboot computer");
2086
2087 while (TRUE)
2088 {
2089 ConInKey(Ir);
2090
2091 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2092 {
2093 return(QUIT_PAGE);
2094 }
2095 }
2096 }
2097 }
2098 }
2099 while (InfFindNextLine (&DirContext, &DirContext));
2100
2101 return(FILE_COPY_PAGE);
2102 }
2103
2104
2105 static ULONG
2106 FileCopyCallback(PVOID Context,
2107 ULONG Notification,
2108 PVOID Param1,
2109 PVOID Param2)
2110 {
2111 PCOPYCONTEXT CopyContext;
2112
2113 CopyContext = (PCOPYCONTEXT)Context;
2114
2115 switch (Notification)
2116 {
2117 case SPFILENOTIFY_STARTSUBQUEUE:
2118 CopyContext->TotalOperations = (ULONG)Param2;
2119 ProgressSetStepCount(CopyContext->ProgressBar,
2120 CopyContext->TotalOperations);
2121 break;
2122
2123 case SPFILENOTIFY_STARTCOPY:
2124 /* Display copy message */
2125 PrintTextXYN(6, 16, 60, "Copying file: %S", (PWSTR)Param1);
2126
2127 PrintTextXYN(6, 18, 60, "File %lu of %lu",
2128 CopyContext->CompletedOperations + 1,
2129 CopyContext->TotalOperations);
2130 break;
2131
2132 case SPFILENOTIFY_ENDCOPY:
2133 CopyContext->CompletedOperations++;
2134 ProgressNextStep(CopyContext->ProgressBar);
2135 break;
2136 }
2137
2138 return(0);
2139 }
2140
2141
2142 static PAGE_NUMBER
2143 FileCopyPage(PINPUT_RECORD Ir)
2144 {
2145 COPYCONTEXT CopyContext;
2146 SHORT xScreen;
2147 SHORT yScreen;
2148
2149 SetStatusText(" Please wait...");
2150
2151 SetTextXY(6, 8, "Copying files");
2152
2153 GetScreenSize(&xScreen, &yScreen);
2154
2155 CopyContext.TotalOperations = 0;
2156 CopyContext.CompletedOperations = 0;
2157 CopyContext.ProgressBar = CreateProgressBar(6,
2158 yScreen - 14,
2159 xScreen - 7,
2160 yScreen - 10);
2161
2162 SetupCommitFileQueue(SetupFileQueue,
2163 DestinationRootPath.Buffer,
2164 InstallPath.Buffer,
2165 (PSP_FILE_CALLBACK)FileCopyCallback,
2166 &CopyContext);
2167
2168 SetupCloseFileQueue(SetupFileQueue);
2169
2170 DestroyProgressBar(CopyContext.ProgressBar);
2171
2172 return(REGISTRY_PAGE);
2173 }
2174
2175
2176 static PAGE_NUMBER
2177 RegistryPage(PINPUT_RECORD Ir)
2178 {
2179 INFCONTEXT InfContext;
2180 NTSTATUS Status;
2181
2182 PWSTR Action;
2183 PWSTR File;
2184 PWSTR Section;
2185 BOOLEAN Delete;
2186
2187
2188 SetTextXY(6, 8, "Setup is updating the system configuration");
2189
2190 SetStatusText(" Creating registry hives...");
2191
2192 if (!SetInstallPathValue(&DestinationPath))
2193 {
2194 DPRINT("SetInstallPathValue() failed\n");
2195 PopupError("Setup failed to set the initialize the registry.",
2196 "ENTER = Reboot computer");
2197
2198 while(TRUE)
2199 {
2200 ConInKey(Ir);
2201
2202 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2203 {
2204 return(QUIT_PAGE);
2205 }
2206 }
2207 }
2208
2209 /* Create the default hives */
2210 Status = NtInitializeRegistry(TRUE);
2211 if (!NT_SUCCESS(Status))
2212 {
2213 DPRINT("NtInitializeRegistry() failed (Status %lx)\n", Status);
2214 PopupError("Setup failed to create the registry hives.",
2215 "ENTER = Reboot computer");
2216
2217 while(TRUE)
2218 {
2219 ConInKey(Ir);
2220
2221 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2222 {
2223 return(QUIT_PAGE);
2224 }
2225 }
2226 }
2227
2228 /* Update registry */
2229 SetStatusText(" Updating registry hives...");
2230
2231 if (!InfFindFirstLine(SetupInf, L"HiveInfs.Install", NULL, &InfContext))
2232 {
2233 DPRINT1("InfFindFirstLine() failed\n");
2234 PopupError("Setup failed to find the registry data files.",
2235 "ENTER = Reboot computer");
2236
2237 while(TRUE)
2238 {
2239 ConInKey(Ir);
2240
2241 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2242 {
2243 return(QUIT_PAGE);
2244 }
2245 }
2246 }
2247
2248 do
2249 {
2250 InfGetDataField (&InfContext, 0, &Action);
2251 InfGetDataField (&InfContext, 1, &File);
2252 InfGetDataField (&InfContext, 2, &Section);
2253
2254 DPRINT1("Action: %S File: %S Section %S\n", Action, File, Section);
2255
2256 if (!_wcsicmp (Action, L"AddReg"))
2257 {
2258 Delete = FALSE;
2259 }
2260 else if (!_wcsicmp (Action, L"DelReg"))
2261 {
2262 Delete = TRUE;
2263 }
2264 else
2265 {
2266 continue;
2267 }
2268
2269 SetStatusText(" Importing %S...", File);
2270
2271 if (!ImportRegistryFile(File, Section, Delete))
2272 {
2273 DPRINT1("Importing %S failed\n", File);
2274
2275 PopupError("Setup failed to import a hive file.",
2276 "ENTER = Reboot computer");
2277
2278 while(TRUE)
2279 {
2280 ConInKey(Ir);
2281
2282 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2283 {
2284 return(QUIT_PAGE);
2285 }
2286 }
2287 }
2288 }
2289 while (InfFindNextLine (&InfContext, &InfContext));
2290
2291 SetStatusText(" Done...");
2292
2293 return(BOOT_LOADER_PAGE);
2294 }
2295
2296
2297 static PAGE_NUMBER
2298 BootLoaderPage(PINPUT_RECORD Ir)
2299 {
2300 WCHAR SrcPath[MAX_PATH];
2301 WCHAR DstPath[MAX_PATH];
2302 PINICACHE IniCache;
2303 PINICACHESECTION IniSection;
2304 NTSTATUS Status;
2305
2306 SetTextXY(6, 8, "Installing the boot loader");
2307
2308 SetStatusText(" Please wait...");
2309
2310
2311 if (PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_ENTRY_UNUSED)
2312 {
2313 DPRINT1("Error: active partition invalid (unused)\n");
2314 PopupError("The active partition is unused (invalid).\n",
2315 "ENTER = Reboot computer");
2316
2317 while(TRUE)
2318 {
2319 ConInKey(Ir);
2320
2321 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2322 {
2323 return(QUIT_PAGE);
2324 }
2325 }
2326 }
2327
2328 if (PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == 0x0A)
2329 {
2330 /* OS/2 boot manager partition */
2331 DPRINT1("Found OS/2 boot manager partition\n");
2332 PopupError("Setup found an OS/2 boot manager partiton.\n"
2333 "The OS/2 boot manager is not supported yet!",
2334 "ENTER = Reboot computer");
2335
2336 while(TRUE)
2337 {
2338 ConInKey(Ir);
2339
2340 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2341 {
2342 return(QUIT_PAGE);
2343 }
2344 }
2345 }
2346 else if (PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == 0x83)
2347 {
2348 /* Linux ext2 partition */
2349 DPRINT1("Found Linux ext2 partition\n");
2350 PopupError("Setup found a Linux ext2 partiton.\n"
2351 "Linux ext2 partitions are not supported yet!",
2352 "ENTER = Reboot computer");
2353
2354 while(TRUE)
2355 {
2356 ConInKey(Ir);
2357
2358 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2359 {
2360 return(QUIT_PAGE);
2361 }
2362 }
2363 }
2364 else if (PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_IFS)
2365 {
2366 /* NTFS partition */
2367 DPRINT1("Found NTFS partition\n");
2368 PopupError("Setup found an NTFS partiton.\n"
2369 "NTFS partitions are not supported yet!",
2370 "ENTER = Reboot computer");
2371
2372 while(TRUE)
2373 {
2374 ConInKey(Ir);
2375
2376 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2377 {
2378 return(QUIT_PAGE);
2379 }
2380 }
2381 }
2382 else if ((PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_FAT_12) ||
2383 (PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_FAT_16) ||
2384 (PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_HUGE) ||
2385 (PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_XINT13) ||
2386 (PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_FAT32) ||
2387 (PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_FAT32_XINT13))
2388 {
2389 /* FAT or FAT32 partition */
2390 DPRINT1("System path: '%wZ'\n", &SystemRootPath);
2391
2392 if (DoesFileExist(SystemRootPath.Buffer, L"ntldr") == TRUE ||
2393 DoesFileExist(SystemRootPath.Buffer, L"boot.ini") == TRUE)
2394 {
2395 /* Search root directory for 'ntldr' and 'boot.ini'. */
2396 DPRINT1("Found Microsoft Windows NT/2000/XP boot loader\n");
2397
2398 /* Copy FreeLoader to the boot partition */
2399 wcscpy(SrcPath, SourceRootPath.Buffer);
2400 wcscat(SrcPath, L"\\loader\\freeldr.sys");
2401 wcscpy(DstPath, SystemRootPath.Buffer);
2402 wcscat(DstPath, L"\\freeldr.sys");
2403
2404 DPRINT1("Copy: %S ==> %S\n", SrcPath, DstPath);
2405 Status = SetupCopyFile(SrcPath, DstPath);
2406 if (!NT_SUCCESS(Status))
2407 {
2408 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
2409 PopupError("Setup failed to copy 'freeldr.sys'.",
2410 "ENTER = Reboot computer");
2411
2412 while(TRUE)
2413 {
2414 ConInKey(Ir);
2415
2416 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2417 {
2418 return(QUIT_PAGE);
2419 }
2420 }
2421 }
2422
2423 /* Create or update freeldr.ini */
2424 if (DoesFileExist(SystemRootPath.Buffer, L"freeldr.ini") == FALSE)
2425 {
2426 /* Create new 'freeldr.ini' */
2427 DPRINT1("Create new 'freeldr.ini'\n");
2428 wcscpy(DstPath, SystemRootPath.Buffer);
2429 wcscat(DstPath, L"\\freeldr.ini");
2430
2431 Status = CreateFreeLoaderIniForReactos(DstPath,
2432 DestinationArcPath.Buffer);
2433 if (!NT_SUCCESS(Status))
2434 {
2435 DPRINT1("CreateFreeLoaderIniForReactos() failed (Status %lx)\n", Status);
2436 PopupError("Setup failed to create 'freeldr.ini'.",
2437 "ENTER = Reboot computer");
2438
2439 while(TRUE)
2440 {
2441 ConInKey(Ir);
2442
2443 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2444 {
2445 return(QUIT_PAGE);
2446 }
2447 }
2448 }
2449
2450 /* Install new bootcode */
2451 if ((PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_FAT32) ||
2452 (PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_FAT32_XINT13))
2453 {
2454 /* Install FAT32 bootcode */
2455 wcscpy(SrcPath, SourceRootPath.Buffer);
2456 wcscat(SrcPath, L"\\loader\\fat32.bin");
2457 wcscpy(DstPath, SystemRootPath.Buffer);
2458 wcscat(DstPath, L"\\bootsect.ros");
2459
2460 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, DstPath);
2461 Status = InstallFat32BootCodeToFile(SrcPath,
2462 DstPath,
2463 SystemRootPath.Buffer);
2464 if (!NT_SUCCESS(Status))
2465 {
2466 DPRINT1("InstallFat32BootCodeToFile() failed (Status %lx)\n", Status);
2467 PopupError("Setup failed to install the FAT32 bootcode.",
2468 "ENTER = Reboot computer");
2469
2470 while(TRUE)
2471 {
2472 ConInKey(Ir);
2473
2474 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2475 {
2476 return(QUIT_PAGE);
2477 }
2478 }
2479 }
2480 }
2481 else
2482 {
2483 /* Install FAT16 bootcode */
2484 wcscpy(SrcPath, SourceRootPath.Buffer);
2485 wcscat(SrcPath, L"\\loader\\fat.bin");
2486 wcscpy(DstPath, SystemRootPath.Buffer);
2487 wcscat(DstPath, L"\\bootsect.ros");
2488
2489 DPRINT1("Install FAT bootcode: %S ==> %S\n", SrcPath, DstPath);
2490 Status = InstallFat16BootCodeToFile(SrcPath,
2491 DstPath,
2492 SystemRootPath.Buffer);
2493 if (!NT_SUCCESS(Status))
2494 {
2495 DPRINT1("InstallFat16BootCodeToFile() failed (Status %lx)\n", Status);
2496 PopupError("Setup failed to install the FAT bootcode.",
2497 "ENTER = Reboot computer");
2498
2499 while(TRUE)
2500 {
2501 ConInKey(Ir);
2502
2503 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2504 {
2505 return(QUIT_PAGE);
2506 }
2507 }
2508 }
2509 }
2510
2511 /* Update 'boot.ini' */
2512 wcscpy(DstPath, SystemRootPath.Buffer);
2513 wcscat(DstPath, L"\\boot.ini");
2514
2515 DPRINT1("Update 'boot.ini': %S\n", DstPath);
2516 Status = UpdateBootIni(DstPath,
2517 L"C:\\bootsect.ros",
2518 L"\"ReactOS\"");
2519 if (!NT_SUCCESS(Status))
2520 {
2521 DPRINT1("UpdateBootIni() failed (Status %lx)\n", Status);
2522 PopupError("Setup failed to update \'boot.ini\'.",
2523 "ENTER = Reboot computer");
2524
2525 while(TRUE)
2526 {
2527 ConInKey(Ir);
2528
2529 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2530 {
2531 return(QUIT_PAGE);
2532 }
2533 }
2534 }
2535 }
2536 else
2537 {
2538 /* Update existing 'freeldr.ini' */
2539 DPRINT1("Update existing 'freeldr.ini'\n");
2540 wcscpy(DstPath, SystemRootPath.Buffer);
2541 wcscat(DstPath, L"\\freeldr.ini");
2542
2543 Status = UpdateFreeLoaderIni(DstPath,
2544 DestinationArcPath.Buffer);
2545 if (!NT_SUCCESS(Status))
2546 {
2547 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
2548 PopupError("Setup failed to update 'freeldr.ini'.",
2549 "ENTER = Reboot computer");
2550
2551 while(TRUE)
2552 {
2553 ConInKey(Ir);
2554
2555 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2556 {
2557 return(QUIT_PAGE);
2558 }
2559 }
2560 }
2561 }
2562 }
2563 else if (DoesFileExist(SystemRootPath.Buffer, L"io.sys") == TRUE ||
2564 DoesFileExist(SystemRootPath.Buffer, L"msdos.sys") == TRUE)
2565 {
2566 /* Search for root directory for 'io.sys' and 'msdos.sys'. */
2567 DPRINT1("Found Microsoft DOS or Windows 9x boot loader\n");
2568
2569 /* Copy FreeLoader to the boot partition */
2570 wcscpy(SrcPath, SourceRootPath.Buffer);
2571 wcscat(SrcPath, L"\\loader\\freeldr.sys");
2572 wcscpy(DstPath, SystemRootPath.Buffer);
2573 wcscat(DstPath, L"\\freeldr.sys");
2574
2575 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
2576 Status = SetupCopyFile(SrcPath, DstPath);
2577 if (!NT_SUCCESS(Status))
2578 {
2579 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
2580 PopupError("Setup failed to copy 'freeldr.sys'.",
2581 "ENTER = Reboot computer");
2582
2583 while(TRUE)
2584 {
2585 ConInKey(Ir);
2586
2587 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2588 {
2589 return(QUIT_PAGE);
2590 }
2591 }
2592 }
2593
2594 /* Create or update 'freeldr.ini' */
2595 if (DoesFileExist(SystemRootPath.Buffer, L"freeldr.ini") == FALSE)
2596 {
2597 /* Create new 'freeldr.ini' */
2598 DPRINT1("Create new 'freeldr.ini'\n");
2599 wcscpy(DstPath, SystemRootPath.Buffer);
2600 wcscat(DstPath, L"\\freeldr.ini");
2601
2602 Status = CreateFreeLoaderIniForDos(DstPath,
2603 DestinationArcPath.Buffer);
2604 if (!NT_SUCCESS(Status))
2605 {
2606 DPRINT1("CreateFreeLoaderIniForDos() failed (Status %lx)\n", Status);
2607 PopupError("Setup failed to create 'freeldr.ini'.",
2608 "ENTER = Reboot computer");
2609
2610 while(TRUE)
2611 {
2612 ConInKey(Ir);
2613
2614 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2615 {
2616 return(QUIT_PAGE);
2617 }
2618 }
2619 }
2620
2621 /* Save current bootsector as 'BOOTSECT.DOS' */
2622 wcscpy(SrcPath, SystemRootPath.Buffer);
2623 wcscpy(DstPath, SystemRootPath.Buffer);
2624 wcscat(DstPath, L"\\bootsect.dos");
2625
2626 DPRINT1("Save bootsector: %S ==> %S\n", SrcPath, DstPath);
2627 Status = SaveCurrentBootSector(SrcPath,
2628 DstPath);
2629 if (!NT_SUCCESS(Status))
2630 {
2631 DPRINT1("SaveCurrentBootSector() failed (Status %lx)\n", Status);
2632 PopupError("Setup failed to save the current bootsector.",
2633 "ENTER = Reboot computer");
2634
2635 while(TRUE)
2636 {
2637 ConInKey(Ir);
2638
2639 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2640 {
2641 return(QUIT_PAGE);
2642 }
2643 }
2644 }
2645
2646 /* Install new bootsector */
2647 if ((PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_FAT32) ||
2648 (PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_FAT32_XINT13))
2649 {
2650 wcscpy(SrcPath, SourceRootPath.Buffer);
2651 wcscat(SrcPath, L"\\loader\\fat32.bin");
2652
2653 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, SystemRootPath.Buffer);
2654 Status = InstallFat32BootCodeToDisk(SrcPath,
2655 SystemRootPath.Buffer);
2656 if (!NT_SUCCESS(Status))
2657 {
2658 DPRINT1("InstallFat32BootCodeToDisk() failed (Status %lx)\n", Status);
2659 PopupError("Setup failed to install the FAT32 bootcode.",
2660 "ENTER = Reboot computer");
2661
2662 while(TRUE)
2663 {
2664 ConInKey(Ir);
2665
2666 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2667 {
2668 return(QUIT_PAGE);
2669 }
2670 }
2671 }
2672 }
2673 else
2674 {
2675 wcscpy(SrcPath, SourceRootPath.Buffer);
2676 wcscat(SrcPath, L"\\loader\\fat.bin");
2677
2678 DPRINT1("Install FAT bootcode: %S ==> %S\n", SrcPath, SystemRootPath.Buffer);
2679 Status = InstallFat16BootCodeToDisk(SrcPath,
2680 SystemRootPath.Buffer);
2681 if (!NT_SUCCESS(Status))
2682 {
2683 DPRINT1("InstallFat16BootCodeToDisk() failed (Status %lx)\n", Status);
2684 PopupError("Setup failed to install the FAT bootcode.",
2685 "ENTER = Reboot computer");
2686
2687 while(TRUE)
2688 {
2689 ConInKey(Ir);
2690
2691 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2692 {
2693 return(QUIT_PAGE);
2694 }
2695 }
2696 }
2697 }
2698 }
2699 else
2700 {
2701 /* Update existing 'freeldr.ini' */
2702 wcscpy(DstPath, SystemRootPath.Buffer);
2703 wcscat(DstPath, L"\\freeldr.ini");
2704
2705 Status = UpdateFreeLoaderIni(DstPath,
2706 DestinationArcPath.Buffer);
2707 if (!NT_SUCCESS(Status))
2708 {
2709 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
2710 PopupError("Setup failed to update 'freeldr.ini'.",
2711 "ENTER = Reboot computer");
2712
2713 while(TRUE)
2714 {
2715 ConInKey(Ir);
2716
2717 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2718 {
2719 return(QUIT_PAGE);
2720 }
2721 }
2722 }
2723 }
2724 }
2725 else
2726 {
2727 /* No or unknown boot loader */
2728 DPRINT1("No or unknown boot loader found\n");
2729
2730 /* Copy FreeLoader to the boot partition */
2731 wcscpy(SrcPath, SourceRootPath.Buffer);
2732 wcscat(SrcPath, L"\\loader\\freeldr.sys");
2733 wcscpy(DstPath, SystemRootPath.Buffer);
2734 wcscat(DstPath, L"\\freeldr.sys");
2735
2736 DPRINT1("Copy: %S ==> %S\n", SrcPath, DstPath);
2737 Status = SetupCopyFile(SrcPath, DstPath);
2738 if (!NT_SUCCESS(Status))
2739 {
2740 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
2741 PopupError("Setup failed to copy 'freeldr.sys'.",
2742 "ENTER = Reboot computer");
2743
2744 while(TRUE)
2745 {
2746 ConInKey(Ir);
2747
2748 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2749 {
2750 return(QUIT_PAGE);
2751 }
2752 }
2753 }
2754
2755 /* Create or update 'freeldr.ini' */
2756 if (DoesFileExist(SystemRootPath.Buffer, L"freeldr.ini") == FALSE)
2757 {
2758 /* Create new freeldr.ini */
2759 wcscpy(DstPath, SystemRootPath.Buffer);
2760 wcscat(DstPath, L"\\freeldr.ini");
2761
2762 DPRINT1("Copy: %S ==> %S\n", SrcPath, DstPath);
2763 Status = CreateFreeLoaderIniForReactos(DstPath,
2764 DestinationArcPath.Buffer);
2765 if (!NT_SUCCESS(Status))
2766 {
2767 DPRINT1("CreateFreeLoaderIniForReactos() failed (Status %lx)\n", Status);
2768 PopupError("Setup failed to create \'freeldr.ini\'.",
2769 "ENTER = Reboot computer");
2770
2771 while(TRUE)
2772 {
2773 ConInKey(Ir);
2774
2775 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2776 {
2777 return(QUIT_PAGE);
2778 }
2779 }
2780 }
2781
2782 /* Save current bootsector as 'BOOTSECT.OLD' */
2783 wcscpy(SrcPath, SystemRootPath.Buffer);
2784 wcscpy(DstPath, SystemRootPath.Buffer);
2785 wcscat(DstPath, L"\\bootsect.old");
2786
2787 DPRINT1("Save bootsector: %S ==> %S\n", SrcPath, DstPath);
2788 Status = SaveCurrentBootSector(SrcPath,
2789 DstPath);
2790 if (!NT_SUCCESS(Status))
2791 {
2792 DPRINT1("SaveCurrentBootSector() failed (Status %lx)\n", Status);
2793 PopupError("Setup failed save the current bootsector.",
2794 "ENTER = Reboot computer");
2795
2796 while(TRUE)
2797 {
2798 ConInKey(Ir);
2799
2800 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2801 {
2802 return(QUIT_PAGE);
2803 }
2804 }
2805 }
2806
2807 /* Install new bootsector */
2808 if ((PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_FAT32) ||
2809 (PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_FAT32_XINT13))
2810 {
2811 wcscpy(SrcPath, SourceRootPath.Buffer);
2812 wcscat(SrcPath, L"\\loader\\fat32.bin");
2813
2814 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, SystemRootPath.Buffer);
2815 Status = InstallFat32BootCodeToDisk(SrcPath,
2816 SystemRootPath.Buffer);
2817 if (!NT_SUCCESS(Status))
2818 {
2819 DPRINT1("InstallFat32BootCodeToDisk() failed (Status %lx)\n", Status);
2820 PopupError("Setup failed to install the FAT32 bootcode.",
2821 "ENTER = Reboot computer");
2822
2823 while(TRUE)
2824 {
2825 ConInKey(Ir);
2826
2827 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2828 {
2829 return(QUIT_PAGE);
2830 }
2831 }
2832 }
2833 }
2834 else
2835 {
2836 wcscpy(SrcPath, SourceRootPath.Buffer);
2837 wcscat(SrcPath, L"\\loader\\fat.bin");
2838
2839 DPRINT1("Install FAT bootcode: %S ==> %S\n", SrcPath, SystemRootPath.Buffer);
2840 Status = InstallFat16BootCodeToDisk(SrcPath,
2841 SystemRootPath.Buffer);
2842 if (!NT_SUCCESS(Status))
2843 {
2844 DPRINT1("InstallFat16BootCodeToDisk() failed (Status %lx)\n", Status);
2845 PopupError("Setup failed to install the FAT bootcode.",
2846 "ENTER = Reboot computer");
2847
2848 while(TRUE)
2849 {
2850 ConInKey(Ir);
2851
2852 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2853 {
2854 return(QUIT_PAGE);
2855 }
2856 }
2857 }
2858 }
2859 }
2860 else
2861 {
2862 /* Update existing 'freeldr.ini' */
2863 wcscpy(DstPath, SystemRootPath.Buffer);
2864 wcscat(DstPath, L"\\freeldr.ini");
2865
2866 Status = UpdateFreeLoaderIni(DstPath,
2867 DestinationArcPath.Buffer);
2868 if (!NT_SUCCESS(Status))
2869 {
2870 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
2871 PopupError("Setup failed to update 'freeldr.ini'.",
2872 "ENTER = Reboot computer");
2873
2874 while(TRUE)
2875 {
2876 ConInKey(Ir);
2877
2878 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2879 {
2880 return(QUIT_PAGE);
2881 }
2882 }
2883 }
2884 }
2885 }
2886 }
2887 else
2888 {
2889 /* Unknown partition */
2890 DPRINT1("Unknown partition found\n");
2891 PopupError("Setup found an unknown partiton type.\n"
2892 "This partition type is not supported!",
2893 "ENTER = Reboot computer");
2894
2895 while(TRUE)
2896 {
2897 ConInKey(Ir);
2898
2899 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2900 {
2901 return(QUIT_PAGE);
2902 }
2903 }
2904 }
2905
2906 return(SUCCESS_PAGE);
2907 }
2908
2909
2910
2911 static PAGE_NUMBER
2912 QuitPage(PINPUT_RECORD Ir)
2913 {
2914 SetTextXY(10, 6, "ReactOS is not completely installed");
2915
2916 SetTextXY(10, 8, "Remove floppy disk from Drive A: and");
2917 SetTextXY(10, 9, "all CD-ROMs from CD-Drives.");
2918
2919 SetTextXY(10, 11, "Press ENTER to reboot your computer.");
2920
2921 SetStatusText(" Please wait ...");
2922
2923 /* Destroy partition list */
2924 if (PartitionList != NULL)
2925 {
2926 DestroyPartitionList (PartitionList);
2927 PartitionList = NULL;
2928 }
2929
2930 /* Destroy filesystem list */
2931 if (FileSystemList != NULL)
2932 {
2933 DestroyFileSystemList (FileSystemList);
2934 FileSystemList = NULL;
2935 }
2936
2937 SetStatusText(" ENTER = Reboot computer");
2938
2939 while(TRUE)
2940 {
2941 ConInKey(Ir);
2942
2943 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2944 {
2945 return(REBOOT_PAGE);
2946 }
2947 }
2948 }
2949
2950
2951 static PAGE_NUMBER
2952 SuccessPage(PINPUT_RECORD Ir)
2953 {
2954 SetTextXY(10, 6, "The basic components of ReactOS have been installed successfully.");
2955
2956 SetTextXY(10, 8, "Remove floppy disk from Drive A: and");
2957 SetTextXY(10, 9, "all CD-ROMs from CD-Drive.");
2958
2959 SetTextXY(10, 11, "Press ENTER to reboot your computer.");
2960
2961 SetStatusText(" ENTER = Reboot computer");
2962
2963 while(TRUE)
2964 {
2965 ConInKey(Ir);
2966
2967 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2968 {
2969 return(REBOOT_PAGE);
2970 }
2971 }
2972 }
2973
2974
2975 VOID STDCALL
2976 NtProcessStartup(PPEB Peb)
2977 {
2978 NTSTATUS Status;
2979 INPUT_RECORD Ir;
2980 PAGE_NUMBER Page;
2981
2982 RtlNormalizeProcessParams(Peb->ProcessParameters);
2983
2984 ProcessHeap = Peb->ProcessHeap;
2985
2986 Status = AllocConsole();
2987 if (!NT_SUCCESS(Status))
2988 {
2989 PrintString("AllocConsole() failed (Status = 0x%08lx)\n", Status);
2990
2991 /* Raise a hard error (crash the system/BSOD) */
2992 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED,
2993 0,0,0,0,0);
2994 }
2995
2996
2997 /* Initialize global unicode strings */
2998 RtlInitUnicodeString(&SourcePath, NULL);
2999 RtlInitUnicodeString(&SourceRootPath, NULL);
3000 RtlInitUnicodeString(&InstallPath, NULL);
3001 RtlInitUnicodeString(&DestinationPath, NULL);
3002 RtlInitUnicodeString(&DestinationArcPath, NULL);
3003 RtlInitUnicodeString(&DestinationRootPath, NULL);
3004 RtlInitUnicodeString(&SystemRootPath, NULL);
3005
3006
3007 Page = START_PAGE;
3008 while (Page != REBOOT_PAGE)
3009 {
3010 ClearScreen();
3011
3012 SetUnderlinedTextXY(4, 3, " ReactOS " KERNEL_VERSION_STR " Setup ");
3013
3014 switch (Page)
3015 {
3016 /* Start page */
3017 case START_PAGE:
3018 Page = StartPage(&Ir);
3019 break;
3020
3021 /* Intro page */
3022 case INTRO_PAGE:
3023 Page = IntroPage(&Ir);
3024 break;
3025
3026 /* Install pages */
3027 case INSTALL_INTRO_PAGE:
3028 Page = InstallIntroPage(&Ir);
3029 break;
3030
3031 #if 0
3032 case OEM_DRIVER_PAGE:
3033 Page = OemDriverPage(&Ir);
3034 break;
3035 #endif
3036
3037 #if 0
3038 case DEVICE_SETTINGS_PAGE:
3039 #endif
3040
3041 case SELECT_PARTITION_PAGE:
3042 Page = SelectPartitionPage(&Ir);
3043 break;
3044
3045 case CREATE_PARTITION_PAGE:
3046 Page = CreatePartitionPage(&Ir);
3047 break;
3048
3049 case DELETE_PARTITION_PAGE:
3050 Page = DeletePartitionPage(&Ir);
3051 break;
3052
3053 case SELECT_FILE_SYSTEM_PAGE:
3054 Page = SelectFileSystemPage(&Ir);
3055 break;
3056
3057 case FORMAT_PARTITION_PAGE:
3058 Page = FormatPartitionPage(&Ir);
3059 break;
3060
3061 case CHECK_FILE_SYSTEM_PAGE:
3062 Page = CheckFileSystemPage(&Ir);
3063 break;
3064
3065 case INSTALL_DIRECTORY_PAGE:
3066 Page = InstallDirectoryPage(&Ir);
3067 break;
3068
3069 case PREPARE_COPY_PAGE:
3070 Page = PrepareCopyPage(&Ir);
3071 break;
3072
3073 case FILE_COPY_PAGE:
3074 Page = FileCopyPage(&Ir);
3075 break;
3076
3077 case REGISTRY_PAGE:
3078 Page = RegistryPage(&Ir);
3079 break;
3080
3081 case BOOT_LOADER_PAGE:
3082 Page = BootLoaderPage(&Ir);
3083 break;
3084
3085
3086 /* Repair pages */
3087 case REPAIR_INTRO_PAGE:
3088 Page = RepairIntroPage(&Ir);
3089 break;
3090
3091
3092 /* Emergency pages */
3093 case EMERGENCY_INTRO_PAGE:
3094 Page = EmergencyIntroPage(&Ir);
3095 break;
3096
3097
3098 case SUCCESS_PAGE:
3099 Page = SuccessPage(&Ir);
3100 break;
3101
3102 case QUIT_PAGE:
3103 Page = QuitPage(&Ir);
3104 break;
3105 }
3106 }
3107
3108 /* Reboot */
3109 FreeConsole();
3110 NtShutdownSystem(ShutdownReboot);
3111 }
3112
3113 /* EOF */