* Install MBR boot code if necessary.
[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 #if 0
1703 return INSTALL_DIRECTORY_PAGE;
1704 #endif
1705
1706 return SELECT_PARTITION_PAGE;
1707 }
1708 }
1709
1710 return FORMAT_PARTITION_PAGE;
1711 }
1712
1713
1714 static ULONG
1715 CheckFileSystemPage(PINPUT_RECORD Ir)
1716 {
1717 WCHAR PathBuffer[MAX_PATH];
1718
1719 SetTextXY(6, 8, "Check file system");
1720
1721 SetTextXY(6, 10, "At present, ReactOS can not check file systems.");
1722
1723 SetStatusText(" Please wait ...");
1724
1725
1726 SetStatusText(" ENTER = Continue F3 = Quit");
1727
1728
1729 /* Set DestinationRootPath */
1730 RtlFreeUnicodeString (&DestinationRootPath);
1731 swprintf (PathBuffer,
1732 L"\\Device\\Harddisk%lu\\Partition%lu",
1733 PartitionList->CurrentDisk->DiskNumber,
1734 PartitionList->CurrentPartition->PartInfo[0].PartitionNumber);
1735 RtlCreateUnicodeString (&DestinationRootPath,
1736 PathBuffer);
1737 DPRINT1 ("DestinationRootPath: %wZ\n", &DestinationRootPath);
1738
1739 /* Set SystemRootPath */
1740 RtlFreeUnicodeString (&SystemRootPath);
1741 swprintf (PathBuffer,
1742 L"\\Device\\Harddisk%lu\\Partition%lu",
1743 PartitionList->ActiveBootDisk->DiskNumber,
1744 PartitionList->ActiveBootPartition->PartInfo[0].PartitionNumber);
1745 RtlCreateUnicodeString (&SystemRootPath,
1746 PathBuffer);
1747 DPRINT1 ("SystemRootPath: %wZ\n", &SystemRootPath);
1748
1749
1750 while(TRUE)
1751 {
1752 ConInKey(Ir);
1753
1754 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1755 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1756 {
1757 if (ConfirmQuit(Ir) == TRUE)
1758 return(QUIT_PAGE);
1759 break;
1760 }
1761 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1762 {
1763 return(INSTALL_DIRECTORY_PAGE);
1764 }
1765 }
1766
1767 return(CHECK_FILE_SYSTEM_PAGE);
1768 }
1769
1770
1771 static PAGE_NUMBER
1772 InstallDirectoryPage(PINPUT_RECORD Ir)
1773 {
1774 PDISKENTRY DiskEntry;
1775 PPARTENTRY PartEntry;
1776 WCHAR PathBuffer[MAX_PATH];
1777 WCHAR InstallDir[51];
1778 PWCHAR DefaultPath;
1779 INFCONTEXT Context;
1780 ULONG Length;
1781 NTSTATUS Status;
1782
1783 if (PartitionList == NULL ||
1784 PartitionList->CurrentDisk == NULL ||
1785 PartitionList->CurrentPartition == NULL)
1786 {
1787 /* FIXME: show an error dialog */
1788 return QUIT_PAGE;
1789 }
1790
1791 DiskEntry = PartitionList->CurrentDisk;
1792 PartEntry = PartitionList->CurrentPartition;
1793
1794 /* Search for 'DefaultPath' in the 'SetupData' section */
1795 if (!InfFindFirstLine (SetupInf, L"SetupData", L"DefaultPath", &Context))
1796 {
1797 PopupError("Setup failed to find the 'SetupData' section\n"
1798 "in TXTSETUP.SIF.\n",
1799 "ENTER = Reboot computer");
1800
1801 while (TRUE)
1802 {
1803 ConInKey (Ir);
1804
1805 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1806 {
1807 return QUIT_PAGE;
1808 }
1809 }
1810 }
1811
1812 /* Read the 'DefaultPath' data */
1813 if (InfGetData (&Context, NULL, &DefaultPath))
1814 {
1815 wcscpy(InstallDir, DefaultPath);
1816 }
1817 else
1818 {
1819 wcscpy(InstallDir, L"\\ReactOS");
1820 }
1821 Length = wcslen(InstallDir);
1822
1823 SetTextXY(6, 8, "Setup installs ReactOS files onto the selected partition. Choose a");
1824 SetTextXY(6, 9, "directory where you want ReactOS to be installed:");
1825
1826 SetInputTextXY(8, 11, 51, InstallDir);
1827
1828 SetTextXY(6, 14, "To change the suggested directory, press BACKSPACE to delete");
1829 SetTextXY(6, 15, "characters and then type the directory where you want ReactOS to");
1830 SetTextXY(6, 16, "be installed.");
1831
1832 SetStatusText(" ENTER = Continue F3 = Quit");
1833
1834 while(TRUE)
1835 {
1836 ConInKey(Ir);
1837
1838 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1839 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1840 {
1841 if (ConfirmQuit(Ir) == TRUE)
1842 return(QUIT_PAGE);
1843 break;
1844 }
1845 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1846 {
1847 /* Create 'InstallPath' string */
1848 RtlFreeUnicodeString(&InstallPath);
1849 RtlCreateUnicodeString(&InstallPath,
1850 InstallDir);
1851
1852 /* Create 'DestinationPath' string */
1853 RtlFreeUnicodeString(&DestinationPath);
1854 wcscpy(PathBuffer,
1855 DestinationRootPath.Buffer);
1856 if (InstallDir[0] != L'\\')
1857 wcscat(PathBuffer,
1858 L"\\");
1859 wcscat(PathBuffer, InstallDir);
1860 RtlCreateUnicodeString(&DestinationPath,
1861 PathBuffer);
1862
1863 /* Create 'DestinationArcPath' */
1864 RtlFreeUnicodeString(&DestinationArcPath);
1865 swprintf(PathBuffer,
1866 L"multi(0)disk(0)rdisk(%lu)partition(%lu)",
1867 DiskEntry->DiskNumber,
1868 PartEntry->PartInfo[0].PartitionNumber);
1869 if (InstallDir[0] != L'\\')
1870 wcscat(PathBuffer,
1871 L"\\");
1872 wcscat(PathBuffer, InstallDir);
1873 RtlCreateUnicodeString(&DestinationArcPath,
1874 PathBuffer);
1875
1876 return(PREPARE_COPY_PAGE);
1877 }
1878 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x08) /* BACKSPACE */
1879 {
1880 if (Length > 0)
1881 {
1882 Length--;
1883 InstallDir[Length] = 0;
1884 SetInputTextXY(8, 11, 51, InstallDir);
1885 }
1886 }
1887 else if (isprint(Ir->Event.KeyEvent.uChar.AsciiChar))
1888 {
1889 if (Length < 50)
1890 {
1891 InstallDir[Length] = (WCHAR)Ir->Event.KeyEvent.uChar.AsciiChar;
1892 Length++;
1893 InstallDir[Length] = 0;
1894 SetInputTextXY(8, 11, 51, InstallDir);
1895 }
1896 }
1897 }
1898
1899 return(INSTALL_DIRECTORY_PAGE);
1900 }
1901
1902
1903 static PAGE_NUMBER
1904 PrepareCopyPage(PINPUT_RECORD Ir)
1905 {
1906 WCHAR PathBuffer[MAX_PATH];
1907 INFCONTEXT FilesContext;
1908 INFCONTEXT DirContext;
1909 PWCHAR KeyName;
1910 PWCHAR KeyValue;
1911 ULONG Length;
1912 NTSTATUS Status;
1913
1914 PWCHAR FileKeyName;
1915 PWCHAR FileKeyValue;
1916 PWCHAR DirKeyName;
1917 PWCHAR DirKeyValue;
1918
1919 SetTextXY(6, 8, "Setup prepares your computer for copying the ReactOS files. ");
1920
1921
1922 /*
1923 * Build the file copy list
1924 */
1925 SetStatusText(" Building the file copy list...");
1926
1927 /* Search for the 'SourceFiles' section */
1928 if (!InfFindFirstLine (SetupInf, L"SourceFiles", NULL, &FilesContext))
1929 {
1930 PopupError("Setup failed to find the 'SourceFiles' section\n"
1931 "in TXTSETUP.SIF.\n",
1932 "ENTER = Reboot computer");
1933
1934 while(TRUE)
1935 {
1936 ConInKey(Ir);
1937
1938 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1939 {
1940 return(QUIT_PAGE);
1941 }
1942 }
1943 }
1944
1945
1946 /* Create the file queue */
1947 SetupFileQueue = SetupOpenFileQueue();
1948 if (SetupFileQueue == NULL)
1949 {
1950 PopupError("Setup failed to open the copy file queue.\n",
1951 "ENTER = Reboot computer");
1952
1953 while(TRUE)
1954 {
1955 ConInKey(Ir);
1956
1957 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1958 {
1959 return(QUIT_PAGE);
1960 }
1961 }
1962 }
1963
1964 /*
1965 * Enumerate the files in the 'SourceFiles' section
1966 * and add them to the file queue.
1967 */
1968 do
1969 {
1970 if (!InfGetData (&FilesContext, &FileKeyName, &FileKeyValue))
1971 break;
1972
1973 DPRINT1("FileKeyName: '%S' FileKeyValue: '%S'\n", FileKeyName, FileKeyValue);
1974
1975 /* Lookup target directory */
1976 if (!InfFindFirstLine (SetupInf, L"Directories", FileKeyValue, &DirContext))
1977 {
1978 /* FIXME: Handle error! */
1979 DPRINT1("InfFindFirstLine() failed\n");
1980 break;
1981 }
1982
1983 if (!InfGetData (&DirContext, NULL, &DirKeyValue))
1984 {
1985 /* FIXME: Handle error! */
1986 DPRINT1("InfGetData() failed\n");
1987 break;
1988 }
1989
1990 if (!SetupQueueCopy(SetupFileQueue,
1991 SourceRootPath.Buffer,
1992 L"\\reactos",
1993 FileKeyName,
1994 DirKeyValue,
1995 NULL))
1996 {
1997 /* FIXME: Handle error! */
1998 DPRINT1("SetupQueueCopy() failed\n");
1999 }
2000 }
2001 while (InfFindNextLine(&FilesContext, &FilesContext));
2002
2003
2004 /* Create directories */
2005 SetStatusText(" Creating directories...");
2006
2007 /*
2008 * FIXME:
2009 * Install directories like '\reactos\test' are not handled yet.
2010 */
2011
2012 /* Get destination path */
2013 wcscpy(PathBuffer, DestinationPath.Buffer);
2014
2015 /* Remove trailing backslash */
2016 Length = wcslen(PathBuffer);
2017 if ((Length > 0) && (PathBuffer[Length - 1] == '\\'))
2018 {
2019 PathBuffer[Length - 1] = 0;
2020 }
2021
2022 /* Create the install directory */
2023 Status = CreateDirectory(PathBuffer);
2024 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION)
2025 {
2026 DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer, Status);
2027 PopupError("Setup could not create the install directory.",
2028 "ENTER = Reboot computer");
2029
2030 while(TRUE)
2031 {
2032 ConInKey(Ir);
2033
2034 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2035 {
2036 return(QUIT_PAGE);
2037 }
2038 }
2039 }
2040
2041
2042 /* Search for the 'Directories' section */
2043 if (!InfFindFirstLine(SetupInf, L"Directories", NULL, &DirContext))
2044 {
2045 PopupError("Setup failed to find the 'Directories' section\n"
2046 "in TXTSETUP.SIF.\n",
2047 "ENTER = Reboot computer");
2048
2049 while(TRUE)
2050 {
2051 ConInKey(Ir);
2052
2053 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2054 {
2055 return(QUIT_PAGE);
2056 }
2057 }
2058 }
2059
2060 /* Enumerate the directory values and create the subdirectories */
2061 do
2062 {
2063 if (!InfGetData (&DirContext, NULL, &KeyValue))
2064 break;
2065
2066 if (KeyValue[0] == L'\\' && KeyValue[1] != 0)
2067 {
2068 DPRINT("Absolute Path: '%S'\n", KeyValue);
2069
2070 wcscpy(PathBuffer, DestinationRootPath.Buffer);
2071 wcscat(PathBuffer, KeyValue);
2072
2073 DPRINT("FullPath: '%S'\n", PathBuffer);
2074 }
2075 else if (KeyValue[0] != L'\\')
2076 {
2077 DPRINT("RelativePath: '%S'\n", KeyValue);
2078 wcscpy(PathBuffer, DestinationPath.Buffer);
2079 wcscat(PathBuffer, L"\\");
2080 wcscat(PathBuffer, KeyValue);
2081
2082 DPRINT("FullPath: '%S'\n", PathBuffer);
2083
2084 Status = CreateDirectory(PathBuffer);
2085 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION)
2086 {
2087 DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer, Status);
2088 PopupError("Setup could not create install directories.",
2089 "ENTER = Reboot computer");
2090
2091 while (TRUE)
2092 {
2093 ConInKey(Ir);
2094
2095 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2096 {
2097 return(QUIT_PAGE);
2098 }
2099 }
2100 }
2101 }
2102 }
2103 while (InfFindNextLine (&DirContext, &DirContext));
2104
2105 return(FILE_COPY_PAGE);
2106 }
2107
2108
2109 static ULONG
2110 FileCopyCallback(PVOID Context,
2111 ULONG Notification,
2112 PVOID Param1,
2113 PVOID Param2)
2114 {
2115 PCOPYCONTEXT CopyContext;
2116
2117 CopyContext = (PCOPYCONTEXT)Context;
2118
2119 switch (Notification)
2120 {
2121 case SPFILENOTIFY_STARTSUBQUEUE:
2122 CopyContext->TotalOperations = (ULONG)Param2;
2123 ProgressSetStepCount(CopyContext->ProgressBar,
2124 CopyContext->TotalOperations);
2125 break;
2126
2127 case SPFILENOTIFY_STARTCOPY:
2128 /* Display copy message */
2129 PrintTextXYN(6, 16, 60, "Copying file: %S", (PWSTR)Param1);
2130
2131 PrintTextXYN(6, 18, 60, "File %lu of %lu",
2132 CopyContext->CompletedOperations + 1,
2133 CopyContext->TotalOperations);
2134 break;
2135
2136 case SPFILENOTIFY_ENDCOPY:
2137 CopyContext->CompletedOperations++;
2138 ProgressNextStep(CopyContext->ProgressBar);
2139 break;
2140 }
2141
2142 return(0);
2143 }
2144
2145
2146 static PAGE_NUMBER
2147 FileCopyPage(PINPUT_RECORD Ir)
2148 {
2149 COPYCONTEXT CopyContext;
2150 SHORT xScreen;
2151 SHORT yScreen;
2152
2153 SetStatusText(" Please wait...");
2154
2155 SetTextXY(6, 8, "Copying files");
2156
2157 GetScreenSize(&xScreen, &yScreen);
2158
2159 CopyContext.TotalOperations = 0;
2160 CopyContext.CompletedOperations = 0;
2161 CopyContext.ProgressBar = CreateProgressBar(6,
2162 yScreen - 14,
2163 xScreen - 7,
2164 yScreen - 10);
2165
2166 SetupCommitFileQueue(SetupFileQueue,
2167 DestinationRootPath.Buffer,
2168 InstallPath.Buffer,
2169 (PSP_FILE_CALLBACK)FileCopyCallback,
2170 &CopyContext);
2171
2172 SetupCloseFileQueue(SetupFileQueue);
2173
2174 DestroyProgressBar(CopyContext.ProgressBar);
2175
2176 return(REGISTRY_PAGE);
2177 }
2178
2179
2180 static PAGE_NUMBER
2181 RegistryPage(PINPUT_RECORD Ir)
2182 {
2183 INFCONTEXT InfContext;
2184 NTSTATUS Status;
2185
2186 PWSTR Action;
2187 PWSTR File;
2188 PWSTR Section;
2189 BOOLEAN Delete;
2190
2191
2192 SetTextXY(6, 8, "Setup is updating the system configuration");
2193
2194 SetStatusText(" Creating registry hives...");
2195
2196 if (!SetInstallPathValue(&DestinationPath))
2197 {
2198 DPRINT("SetInstallPathValue() failed\n");
2199 PopupError("Setup failed to set the initialize the registry.",
2200 "ENTER = Reboot computer");
2201
2202 while(TRUE)
2203 {
2204 ConInKey(Ir);
2205
2206 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2207 {
2208 return(QUIT_PAGE);
2209 }
2210 }
2211 }
2212
2213 /* Create the default hives */
2214 Status = NtInitializeRegistry(TRUE);
2215 if (!NT_SUCCESS(Status))
2216 {
2217 DPRINT("NtInitializeRegistry() failed (Status %lx)\n", Status);
2218 PopupError("Setup failed to create the registry hives.",
2219 "ENTER = Reboot computer");
2220
2221 while(TRUE)
2222 {
2223 ConInKey(Ir);
2224
2225 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2226 {
2227 return(QUIT_PAGE);
2228 }
2229 }
2230 }
2231
2232 /* Update registry */
2233 SetStatusText(" Updating registry hives...");
2234
2235 if (!InfFindFirstLine(SetupInf, L"HiveInfs.Install", NULL, &InfContext))
2236 {
2237 DPRINT1("InfFindFirstLine() failed\n");
2238 PopupError("Setup failed to find the registry data files.",
2239 "ENTER = Reboot computer");
2240
2241 while(TRUE)
2242 {
2243 ConInKey(Ir);
2244
2245 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2246 {
2247 return(QUIT_PAGE);
2248 }
2249 }
2250 }
2251
2252 do
2253 {
2254 InfGetDataField (&InfContext, 0, &Action);
2255 InfGetDataField (&InfContext, 1, &File);
2256 InfGetDataField (&InfContext, 2, &Section);
2257
2258 DPRINT1("Action: %S File: %S Section %S\n", Action, File, Section);
2259
2260 if (!_wcsicmp (Action, L"AddReg"))
2261 {
2262 Delete = FALSE;
2263 }
2264 else if (!_wcsicmp (Action, L"DelReg"))
2265 {
2266 Delete = TRUE;
2267 }
2268 else
2269 {
2270 continue;
2271 }
2272
2273 SetStatusText(" Importing %S...", File);
2274
2275 if (!ImportRegistryFile(File, Section, Delete))
2276 {
2277 DPRINT1("Importing %S failed\n", File);
2278
2279 PopupError("Setup failed to import a hive file.",
2280 "ENTER = Reboot computer");
2281
2282 while(TRUE)
2283 {
2284 ConInKey(Ir);
2285
2286 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2287 {
2288 return(QUIT_PAGE);
2289 }
2290 }
2291 }
2292 }
2293 while (InfFindNextLine (&InfContext, &InfContext));
2294
2295 SetStatusText(" Done...");
2296
2297 return(BOOT_LOADER_PAGE);
2298 }
2299
2300
2301 static PAGE_NUMBER
2302 BootLoaderPage(PINPUT_RECORD Ir)
2303 {
2304 WCHAR SrcPath[MAX_PATH];
2305 WCHAR DstPath[MAX_PATH];
2306 PINICACHE IniCache;
2307 PINICACHESECTION IniSection;
2308 NTSTATUS Status;
2309
2310 SetTextXY(6, 8, "Installing the boot loader");
2311
2312 SetStatusText(" Please wait...");
2313
2314
2315 if (PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_ENTRY_UNUSED)
2316 {
2317 DPRINT1("Error: active partition invalid (unused)\n");
2318 PopupError("The active partition is unused (invalid).\n",
2319 "ENTER = Reboot computer");
2320
2321 while(TRUE)
2322 {
2323 ConInKey(Ir);
2324
2325 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2326 {
2327 return(QUIT_PAGE);
2328 }
2329 }
2330 }
2331
2332 if (PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == 0x0A)
2333 {
2334 /* OS/2 boot manager partition */
2335 DPRINT1("Found OS/2 boot manager partition\n");
2336 PopupError("Setup found an OS/2 boot manager partiton.\n"
2337 "The OS/2 boot manager is not supported yet!",
2338 "ENTER = Reboot computer");
2339
2340 while(TRUE)
2341 {
2342 ConInKey(Ir);
2343
2344 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2345 {
2346 return(QUIT_PAGE);
2347 }
2348 }
2349 }
2350 else if (PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == 0x83)
2351 {
2352 /* Linux ext2 partition */
2353 DPRINT1("Found Linux ext2 partition\n");
2354 PopupError("Setup found a Linux ext2 partiton.\n"
2355 "Linux ext2 partitions are not supported yet!",
2356 "ENTER = Reboot computer");
2357
2358 while(TRUE)
2359 {
2360 ConInKey(Ir);
2361
2362 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2363 {
2364 return(QUIT_PAGE);
2365 }
2366 }
2367 }
2368 else if (PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_IFS)
2369 {
2370 /* NTFS partition */
2371 DPRINT1("Found NTFS partition\n");
2372 PopupError("Setup found an NTFS partiton.\n"
2373 "NTFS partitions are not supported yet!",
2374 "ENTER = Reboot computer");
2375
2376 while(TRUE)
2377 {
2378 ConInKey(Ir);
2379
2380 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2381 {
2382 return(QUIT_PAGE);
2383 }
2384 }
2385 }
2386 else if ((PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_FAT_12) ||
2387 (PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_FAT_16) ||
2388 (PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_HUGE) ||
2389 (PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_XINT13) ||
2390 (PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_FAT32) ||
2391 (PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_FAT32_XINT13))
2392 {
2393 /* FAT or FAT32 partition */
2394 DPRINT1("System path: '%wZ'\n", &SystemRootPath);
2395
2396 if (DoesFileExist(SystemRootPath.Buffer, L"ntldr") == TRUE ||
2397 DoesFileExist(SystemRootPath.Buffer, L"boot.ini") == TRUE)
2398 {
2399 /* Search root directory for 'ntldr' and 'boot.ini'. */
2400 DPRINT1("Found Microsoft Windows NT/2000/XP boot loader\n");
2401
2402 /* Copy FreeLoader to the boot partition */
2403 wcscpy(SrcPath, SourceRootPath.Buffer);
2404 wcscat(SrcPath, L"\\loader\\freeldr.sys");
2405 wcscpy(DstPath, SystemRootPath.Buffer);
2406 wcscat(DstPath, L"\\freeldr.sys");
2407
2408 DPRINT1("Copy: %S ==> %S\n", SrcPath, DstPath);
2409 Status = SetupCopyFile(SrcPath, DstPath);
2410 if (!NT_SUCCESS(Status))
2411 {
2412 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
2413 PopupError("Setup failed to copy 'freeldr.sys'.",
2414 "ENTER = Reboot computer");
2415
2416 while(TRUE)
2417 {
2418 ConInKey(Ir);
2419
2420 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2421 {
2422 return(QUIT_PAGE);
2423 }
2424 }
2425 }
2426
2427 /* Create or update freeldr.ini */
2428 if (DoesFileExist(SystemRootPath.Buffer, L"freeldr.ini") == FALSE)
2429 {
2430 /* Create new 'freeldr.ini' */
2431 DPRINT1("Create new 'freeldr.ini'\n");
2432 wcscpy(DstPath, SystemRootPath.Buffer);
2433 wcscat(DstPath, L"\\freeldr.ini");
2434
2435 Status = CreateFreeLoaderIniForReactos(DstPath,
2436 DestinationArcPath.Buffer);
2437 if (!NT_SUCCESS(Status))
2438 {
2439 DPRINT1("CreateFreeLoaderIniForReactos() failed (Status %lx)\n", Status);
2440 PopupError("Setup failed to create 'freeldr.ini'.",
2441 "ENTER = Reboot computer");
2442
2443 while(TRUE)
2444 {
2445 ConInKey(Ir);
2446
2447 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2448 {
2449 return(QUIT_PAGE);
2450 }
2451 }
2452 }
2453
2454 /* Install new bootcode */
2455 if ((PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_FAT32) ||
2456 (PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_FAT32_XINT13))
2457 {
2458 /* Install FAT32 bootcode */
2459 wcscpy(SrcPath, SourceRootPath.Buffer);
2460 wcscat(SrcPath, L"\\loader\\fat32.bin");
2461 wcscpy(DstPath, SystemRootPath.Buffer);
2462 wcscat(DstPath, L"\\bootsect.ros");
2463
2464 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, DstPath);
2465 Status = InstallFat32BootCodeToFile(SrcPath,
2466 DstPath,
2467 SystemRootPath.Buffer);
2468 if (!NT_SUCCESS(Status))
2469 {
2470 DPRINT1("InstallFat32BootCodeToFile() failed (Status %lx)\n", Status);
2471 PopupError("Setup failed to install the FAT32 bootcode.",
2472 "ENTER = Reboot computer");
2473
2474 while(TRUE)
2475 {
2476 ConInKey(Ir);
2477
2478 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2479 {
2480 return(QUIT_PAGE);
2481 }
2482 }
2483 }
2484 }
2485 else
2486 {
2487 /* Install FAT16 bootcode */
2488 wcscpy(SrcPath, SourceRootPath.Buffer);
2489 wcscat(SrcPath, L"\\loader\\fat.bin");
2490 wcscpy(DstPath, SystemRootPath.Buffer);
2491 wcscat(DstPath, L"\\bootsect.ros");
2492
2493 DPRINT1("Install FAT bootcode: %S ==> %S\n", SrcPath, DstPath);
2494 Status = InstallFat16BootCodeToFile(SrcPath,
2495 DstPath,
2496 SystemRootPath.Buffer);
2497 if (!NT_SUCCESS(Status))
2498 {
2499 DPRINT1("InstallFat16BootCodeToFile() failed (Status %lx)\n", Status);
2500 PopupError("Setup failed to install the FAT bootcode.",
2501 "ENTER = Reboot computer");
2502
2503 while(TRUE)
2504 {
2505 ConInKey(Ir);
2506
2507 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2508 {
2509 return(QUIT_PAGE);
2510 }
2511 }
2512 }
2513 }
2514
2515 /* Update 'boot.ini' */
2516 wcscpy(DstPath, SystemRootPath.Buffer);
2517 wcscat(DstPath, L"\\boot.ini");
2518
2519 DPRINT1("Update 'boot.ini': %S\n", DstPath);
2520 Status = UpdateBootIni(DstPath,
2521 L"C:\\bootsect.ros",
2522 L"\"ReactOS\"");
2523 if (!NT_SUCCESS(Status))
2524 {
2525 DPRINT1("UpdateBootIni() failed (Status %lx)\n", Status);
2526 PopupError("Setup failed to update \'boot.ini\'.",
2527 "ENTER = Reboot computer");
2528
2529 while(TRUE)
2530 {
2531 ConInKey(Ir);
2532
2533 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2534 {
2535 return(QUIT_PAGE);
2536 }
2537 }
2538 }
2539 }
2540 else
2541 {
2542 /* Update existing 'freeldr.ini' */
2543 DPRINT1("Update existing 'freeldr.ini'\n");
2544 wcscpy(DstPath, SystemRootPath.Buffer);
2545 wcscat(DstPath, L"\\freeldr.ini");
2546
2547 Status = UpdateFreeLoaderIni(DstPath,
2548 DestinationArcPath.Buffer);
2549 if (!NT_SUCCESS(Status))
2550 {
2551 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
2552 PopupError("Setup failed to update 'freeldr.ini'.",
2553 "ENTER = Reboot computer");
2554
2555 while(TRUE)
2556 {
2557 ConInKey(Ir);
2558
2559 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2560 {
2561 return(QUIT_PAGE);
2562 }
2563 }
2564 }
2565 }
2566 }
2567 else if (DoesFileExist(SystemRootPath.Buffer, L"io.sys") == TRUE ||
2568 DoesFileExist(SystemRootPath.Buffer, L"msdos.sys") == TRUE)
2569 {
2570 /* Search for root directory for 'io.sys' and 'msdos.sys'. */
2571 DPRINT1("Found Microsoft DOS or Windows 9x boot loader\n");
2572
2573 /* Copy FreeLoader to the boot partition */
2574 wcscpy(SrcPath, SourceRootPath.Buffer);
2575 wcscat(SrcPath, L"\\loader\\freeldr.sys");
2576 wcscpy(DstPath, SystemRootPath.Buffer);
2577 wcscat(DstPath, L"\\freeldr.sys");
2578
2579 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
2580 Status = SetupCopyFile(SrcPath, DstPath);
2581 if (!NT_SUCCESS(Status))
2582 {
2583 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
2584 PopupError("Setup failed to copy 'freeldr.sys'.",
2585 "ENTER = Reboot computer");
2586
2587 while(TRUE)
2588 {
2589 ConInKey(Ir);
2590
2591 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2592 {
2593 return(QUIT_PAGE);
2594 }
2595 }
2596 }
2597
2598 /* Create or update 'freeldr.ini' */
2599 if (DoesFileExist(SystemRootPath.Buffer, L"freeldr.ini") == FALSE)
2600 {
2601 /* Create new 'freeldr.ini' */
2602 DPRINT1("Create new 'freeldr.ini'\n");
2603 wcscpy(DstPath, SystemRootPath.Buffer);
2604 wcscat(DstPath, L"\\freeldr.ini");
2605
2606 Status = CreateFreeLoaderIniForDos(DstPath,
2607 DestinationArcPath.Buffer);
2608 if (!NT_SUCCESS(Status))
2609 {
2610 DPRINT1("CreateFreeLoaderIniForDos() failed (Status %lx)\n", Status);
2611 PopupError("Setup failed to create 'freeldr.ini'.",
2612 "ENTER = Reboot computer");
2613
2614 while(TRUE)
2615 {
2616 ConInKey(Ir);
2617
2618 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2619 {
2620 return(QUIT_PAGE);
2621 }
2622 }
2623 }
2624
2625 /* Save current bootsector as 'BOOTSECT.DOS' */
2626 wcscpy(SrcPath, SystemRootPath.Buffer);
2627 wcscpy(DstPath, SystemRootPath.Buffer);
2628 wcscat(DstPath, L"\\bootsect.dos");
2629
2630 DPRINT1("Save bootsector: %S ==> %S\n", SrcPath, DstPath);
2631 Status = SaveCurrentBootSector(SrcPath,
2632 DstPath);
2633 if (!NT_SUCCESS(Status))
2634 {
2635 DPRINT1("SaveCurrentBootSector() failed (Status %lx)\n", Status);
2636 PopupError("Setup failed to save the current bootsector.",
2637 "ENTER = Reboot computer");
2638
2639 while(TRUE)
2640 {
2641 ConInKey(Ir);
2642
2643 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2644 {
2645 return(QUIT_PAGE);
2646 }
2647 }
2648 }
2649
2650 /* Install new bootsector */
2651 if ((PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_FAT32) ||
2652 (PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_FAT32_XINT13))
2653 {
2654 wcscpy(SrcPath, SourceRootPath.Buffer);
2655 wcscat(SrcPath, L"\\loader\\fat32.bin");
2656
2657 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, SystemRootPath.Buffer);
2658 Status = InstallFat32BootCodeToDisk(SrcPath,
2659 SystemRootPath.Buffer);
2660 if (!NT_SUCCESS(Status))
2661 {
2662 DPRINT1("InstallFat32BootCodeToDisk() failed (Status %lx)\n", Status);
2663 PopupError("Setup failed to install the FAT32 bootcode.",
2664 "ENTER = Reboot computer");
2665
2666 while(TRUE)
2667 {
2668 ConInKey(Ir);
2669
2670 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2671 {
2672 return(QUIT_PAGE);
2673 }
2674 }
2675 }
2676 }
2677 else
2678 {
2679 wcscpy(SrcPath, SourceRootPath.Buffer);
2680 wcscat(SrcPath, L"\\loader\\fat.bin");
2681
2682 DPRINT1("Install FAT bootcode: %S ==> %S\n", SrcPath, SystemRootPath.Buffer);
2683 Status = InstallFat16BootCodeToDisk(SrcPath,
2684 SystemRootPath.Buffer);
2685 if (!NT_SUCCESS(Status))
2686 {
2687 DPRINT1("InstallFat16BootCodeToDisk() failed (Status %lx)\n", Status);
2688 PopupError("Setup failed to install the FAT bootcode.",
2689 "ENTER = Reboot computer");
2690
2691 while(TRUE)
2692 {
2693 ConInKey(Ir);
2694
2695 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2696 {
2697 return(QUIT_PAGE);
2698 }
2699 }
2700 }
2701 }
2702 }
2703 else
2704 {
2705 /* Update existing 'freeldr.ini' */
2706 wcscpy(DstPath, SystemRootPath.Buffer);
2707 wcscat(DstPath, L"\\freeldr.ini");
2708
2709 Status = UpdateFreeLoaderIni(DstPath,
2710 DestinationArcPath.Buffer);
2711 if (!NT_SUCCESS(Status))
2712 {
2713 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
2714 PopupError("Setup failed to update 'freeldr.ini'.",
2715 "ENTER = Reboot computer");
2716
2717 while(TRUE)
2718 {
2719 ConInKey(Ir);
2720
2721 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2722 {
2723 return(QUIT_PAGE);
2724 }
2725 }
2726 }
2727 }
2728 }
2729 else
2730 {
2731 /* No or unknown boot loader */
2732 DPRINT1("No or unknown boot loader found\n");
2733
2734 /* Copy FreeLoader to the boot partition */
2735 wcscpy(SrcPath, SourceRootPath.Buffer);
2736 wcscat(SrcPath, L"\\loader\\freeldr.sys");
2737 wcscpy(DstPath, SystemRootPath.Buffer);
2738 wcscat(DstPath, L"\\freeldr.sys");
2739
2740 DPRINT1("Copy: %S ==> %S\n", SrcPath, DstPath);
2741 Status = SetupCopyFile(SrcPath, DstPath);
2742 if (!NT_SUCCESS(Status))
2743 {
2744 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
2745 PopupError("Setup failed to copy 'freeldr.sys'.",
2746 "ENTER = Reboot computer");
2747
2748 while(TRUE)
2749 {
2750 ConInKey(Ir);
2751
2752 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2753 {
2754 return(QUIT_PAGE);
2755 }
2756 }
2757 }
2758
2759 /* Create or update 'freeldr.ini' */
2760 if (DoesFileExist(SystemRootPath.Buffer, L"freeldr.ini") == FALSE)
2761 {
2762 /* Create new freeldr.ini */
2763 wcscpy(DstPath, SystemRootPath.Buffer);
2764 wcscat(DstPath, L"\\freeldr.ini");
2765
2766 DPRINT1("Copy: %S ==> %S\n", SrcPath, DstPath);
2767 Status = CreateFreeLoaderIniForReactos(DstPath,
2768 DestinationArcPath.Buffer);
2769 if (!NT_SUCCESS(Status))
2770 {
2771 DPRINT1("CreateFreeLoaderIniForReactos() failed (Status %lx)\n", Status);
2772 PopupError("Setup failed to create \'freeldr.ini\'.",
2773 "ENTER = Reboot computer");
2774
2775 while(TRUE)
2776 {
2777 ConInKey(Ir);
2778
2779 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2780 {
2781 return(QUIT_PAGE);
2782 }
2783 }
2784 }
2785
2786 /* Save current bootsector as 'BOOTSECT.OLD' */
2787 wcscpy(SrcPath, SystemRootPath.Buffer);
2788 wcscpy(DstPath, SystemRootPath.Buffer);
2789 wcscat(DstPath, L"\\bootsect.old");
2790
2791 DPRINT1("Save bootsector: %S ==> %S\n", SrcPath, DstPath);
2792 Status = SaveCurrentBootSector(SrcPath,
2793 DstPath);
2794 if (!NT_SUCCESS(Status))
2795 {
2796 DPRINT1("SaveCurrentBootSector() failed (Status %lx)\n", Status);
2797 PopupError("Setup failed save the current bootsector.",
2798 "ENTER = Reboot computer");
2799
2800 while(TRUE)
2801 {
2802 ConInKey(Ir);
2803
2804 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2805 {
2806 return(QUIT_PAGE);
2807 }
2808 }
2809 }
2810
2811 /* Install new bootsector */
2812 if ((PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_FAT32) ||
2813 (PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_FAT32_XINT13))
2814 {
2815 wcscpy(SrcPath, SourceRootPath.Buffer);
2816 wcscat(SrcPath, L"\\loader\\fat32.bin");
2817
2818 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, SystemRootPath.Buffer);
2819 Status = InstallFat32BootCodeToDisk(SrcPath,
2820 SystemRootPath.Buffer);
2821 if (!NT_SUCCESS(Status))
2822 {
2823 DPRINT1("InstallFat32BootCodeToDisk() failed (Status %lx)\n", Status);
2824 PopupError("Setup failed to install the FAT32 bootcode.",
2825 "ENTER = Reboot computer");
2826
2827 while(TRUE)
2828 {
2829 ConInKey(Ir);
2830
2831 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2832 {
2833 return(QUIT_PAGE);
2834 }
2835 }
2836 }
2837 }
2838 else
2839 {
2840 wcscpy(SrcPath, SourceRootPath.Buffer);
2841 wcscat(SrcPath, L"\\loader\\fat.bin");
2842
2843 DPRINT1("Install FAT bootcode: %S ==> %S\n", SrcPath, SystemRootPath.Buffer);
2844 Status = InstallFat16BootCodeToDisk(SrcPath,
2845 SystemRootPath.Buffer);
2846 if (!NT_SUCCESS(Status))
2847 {
2848 DPRINT1("InstallFat16BootCodeToDisk() failed (Status %lx)\n", Status);
2849 PopupError("Setup failed to install the FAT bootcode.",
2850 "ENTER = Reboot computer");
2851
2852 while(TRUE)
2853 {
2854 ConInKey(Ir);
2855
2856 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2857 {
2858 return(QUIT_PAGE);
2859 }
2860 }
2861 }
2862 }
2863 }
2864 else
2865 {
2866 /* Update existing 'freeldr.ini' */
2867 wcscpy(DstPath, SystemRootPath.Buffer);
2868 wcscat(DstPath, L"\\freeldr.ini");
2869
2870 Status = UpdateFreeLoaderIni(DstPath,
2871 DestinationArcPath.Buffer);
2872 if (!NT_SUCCESS(Status))
2873 {
2874 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
2875 PopupError("Setup failed to update 'freeldr.ini'.",
2876 "ENTER = Reboot computer");
2877
2878 while(TRUE)
2879 {
2880 ConInKey(Ir);
2881
2882 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2883 {
2884 return(QUIT_PAGE);
2885 }
2886 }
2887 }
2888 }
2889 }
2890 }
2891 else
2892 {
2893 /* Unknown partition */
2894 DPRINT1("Unknown partition found\n");
2895 PopupError("Setup found an unknown partiton type.\n"
2896 "This partition type is not supported!",
2897 "ENTER = Reboot computer");
2898
2899 while(TRUE)
2900 {
2901 ConInKey(Ir);
2902
2903 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2904 {
2905 return(QUIT_PAGE);
2906 }
2907 }
2908 }
2909
2910 return(SUCCESS_PAGE);
2911 }
2912
2913
2914
2915 static PAGE_NUMBER
2916 QuitPage(PINPUT_RECORD Ir)
2917 {
2918 SetTextXY(10, 6, "ReactOS is not completely installed");
2919
2920 SetTextXY(10, 8, "Remove floppy disk from Drive A: and");
2921 SetTextXY(10, 9, "all CD-ROMs from CD-Drives.");
2922
2923 SetTextXY(10, 11, "Press ENTER to reboot your computer.");
2924
2925 SetStatusText(" Please wait ...");
2926
2927 /* Destroy partition list */
2928 if (PartitionList != NULL)
2929 {
2930 DestroyPartitionList (PartitionList);
2931 PartitionList = NULL;
2932 }
2933
2934 /* Destroy filesystem list */
2935 if (FileSystemList != NULL)
2936 {
2937 DestroyFileSystemList (FileSystemList);
2938 FileSystemList = NULL;
2939 }
2940
2941 SetStatusText(" ENTER = Reboot computer");
2942
2943 while(TRUE)
2944 {
2945 ConInKey(Ir);
2946
2947 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2948 {
2949 return(REBOOT_PAGE);
2950 }
2951 }
2952 }
2953
2954
2955 static PAGE_NUMBER
2956 SuccessPage(PINPUT_RECORD Ir)
2957 {
2958 SetTextXY(10, 6, "The basic components of ReactOS have been installed successfully.");
2959
2960 SetTextXY(10, 8, "Remove floppy disk from Drive A: and");
2961 SetTextXY(10, 9, "all CD-ROMs from CD-Drive.");
2962
2963 SetTextXY(10, 11, "Press ENTER to reboot your computer.");
2964
2965 SetStatusText(" ENTER = Reboot computer");
2966
2967 while(TRUE)
2968 {
2969 ConInKey(Ir);
2970
2971 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2972 {
2973 return(REBOOT_PAGE);
2974 }
2975 }
2976 }
2977
2978
2979 VOID STDCALL
2980 NtProcessStartup(PPEB Peb)
2981 {
2982 NTSTATUS Status;
2983 INPUT_RECORD Ir;
2984 PAGE_NUMBER Page;
2985
2986 RtlNormalizeProcessParams(Peb->ProcessParameters);
2987
2988 ProcessHeap = Peb->ProcessHeap;
2989
2990 Status = AllocConsole();
2991 if (!NT_SUCCESS(Status))
2992 {
2993 PrintString("AllocConsole() failed (Status = 0x%08lx)\n", Status);
2994
2995 /* Raise a hard error (crash the system/BSOD) */
2996 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED,
2997 0,0,0,0,0);
2998 }
2999
3000
3001 /* Initialize global unicode strings */
3002 RtlInitUnicodeString(&SourcePath, NULL);
3003 RtlInitUnicodeString(&SourceRootPath, NULL);
3004 RtlInitUnicodeString(&InstallPath, NULL);
3005 RtlInitUnicodeString(&DestinationPath, NULL);
3006 RtlInitUnicodeString(&DestinationArcPath, NULL);
3007 RtlInitUnicodeString(&DestinationRootPath, NULL);
3008 RtlInitUnicodeString(&SystemRootPath, NULL);
3009
3010
3011 Page = START_PAGE;
3012 while (Page != REBOOT_PAGE)
3013 {
3014 ClearScreen();
3015
3016 SetUnderlinedTextXY(4, 3, " ReactOS " KERNEL_VERSION_STR " Setup ");
3017
3018 switch (Page)
3019 {
3020 /* Start page */
3021 case START_PAGE:
3022 Page = StartPage(&Ir);
3023 break;
3024
3025 /* Intro page */
3026 case INTRO_PAGE:
3027 Page = IntroPage(&Ir);
3028 break;
3029
3030 /* Install pages */
3031 case INSTALL_INTRO_PAGE:
3032 Page = InstallIntroPage(&Ir);
3033 break;
3034
3035 #if 0
3036 case OEM_DRIVER_PAGE:
3037 Page = OemDriverPage(&Ir);
3038 break;
3039 #endif
3040
3041 #if 0
3042 case DEVICE_SETTINGS_PAGE:
3043 #endif
3044
3045 case SELECT_PARTITION_PAGE:
3046 Page = SelectPartitionPage(&Ir);
3047 break;
3048
3049 case CREATE_PARTITION_PAGE:
3050 Page = CreatePartitionPage(&Ir);
3051 break;
3052
3053 case DELETE_PARTITION_PAGE:
3054 Page = DeletePartitionPage(&Ir);
3055 break;
3056
3057 case SELECT_FILE_SYSTEM_PAGE:
3058 Page = SelectFileSystemPage(&Ir);
3059 break;
3060
3061 case FORMAT_PARTITION_PAGE:
3062 Page = FormatPartitionPage(&Ir);
3063 break;
3064
3065 case CHECK_FILE_SYSTEM_PAGE:
3066 Page = CheckFileSystemPage(&Ir);
3067 break;
3068
3069 case INSTALL_DIRECTORY_PAGE:
3070 Page = InstallDirectoryPage(&Ir);
3071 break;
3072
3073 case PREPARE_COPY_PAGE:
3074 Page = PrepareCopyPage(&Ir);
3075 break;
3076
3077 case FILE_COPY_PAGE:
3078 Page = FileCopyPage(&Ir);
3079 break;
3080
3081 case REGISTRY_PAGE:
3082 Page = RegistryPage(&Ir);
3083 break;
3084
3085 case BOOT_LOADER_PAGE:
3086 Page = BootLoaderPage(&Ir);
3087 break;
3088
3089
3090 /* Repair pages */
3091 case REPAIR_INTRO_PAGE:
3092 Page = RepairIntroPage(&Ir);
3093 break;
3094
3095
3096 /* Emergency pages */
3097 case EMERGENCY_INTRO_PAGE:
3098 Page = EmergencyIntroPage(&Ir);
3099 break;
3100
3101
3102 case SUCCESS_PAGE:
3103 Page = SuccessPage(&Ir);
3104 break;
3105
3106 case QUIT_PAGE:
3107 Page = QuitPage(&Ir);
3108 break;
3109 }
3110 }
3111
3112 /* Reboot */
3113 FreeConsole();
3114 NtShutdownSystem(ShutdownReboot);
3115 }
3116
3117 /* EOF */