ReactOS 0.4.15-dev-6067-g0b695a6
usetup.c
Go to the documentation of this file.
1/*
2 * ReactOS kernel
3 * Copyright (C) 2002, 2003, 2004 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 along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19/*
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS text-mode setup
22 * FILE: base/setup/usetup/usetup.c
23 * PURPOSE: Text-mode setup
24 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
25 * Hervé Poussineau (hpoussin@reactos.org)
26 */
27
28#include <usetup.h>
29#include <math.h>
30#include <ntstrsafe.h>
31
32#include "bootsup.h"
33#include "chkdsk.h"
34#include "cmdcons.h"
35#include "devinst.h"
36#include "format.h"
37
38#define NDEBUG
39#include <debug.h>
40
41
42/* GLOBALS & LOCALS *********************************************************/
43
46
48
49/* The partition where to perform the installation */
51/*
52 * The system partition we will actually use. It can be different from
53 * PartitionList->SystemPartition in case we don't support it, or we install
54 * on a removable disk.
55 * We may indeed not support the original system partition in case we do not
56 * have write support on it. Please note that this situation is partly a HACK
57 * and MUST NEVER happen on architectures where real system partitions are
58 * mandatory (because then they are formatted in FAT FS and we support write
59 * operation on them).
60 */
62
63
64/* OTHER Stuff *****/
65
67static WCHAR DefaultLanguage[20]; // Copy of string inside LanguageList
68static WCHAR DefaultKBLayout[20]; // Copy of string inside KeyboardList
69
71
72/* Global partition list on the system */
74
75/* Currently selected partition entry in the list */
77
78/* List of supported file systems for the partition to be formatted */
80
81/* Machine state for the formatter */
84
85/*****************************************************/
86
89
90#ifdef __REACTOS__ /* HACK */
91
92/* FONT SUBSTITUTION WORKAROUND *************************************************/
93
94/* For font file check */
95FONTSUBSTSETTINGS s_SubstSettings = { FALSE };
96
97static void
98DoWatchDestFileName(LPCWSTR FileName)
99{
100 if (FileName[0] == 'm' || FileName[0] == 'M')
101 {
102 if (wcsicmp(FileName, L"mingliu.ttc") == 0)
103 {
104 DPRINT("mingliu.ttc found\n");
105 s_SubstSettings.bFoundFontMINGLIU = TRUE;
106 }
107 else if (wcsicmp(FileName, L"msgothic.ttc") == 0)
108 {
109 DPRINT("msgothic.ttc found\n");
110 s_SubstSettings.bFoundFontMSGOTHIC = TRUE;
111 }
112 else if (wcsicmp(FileName, L"msmincho.ttc") == 0)
113 {
114 DPRINT("msmincho.ttc found\n");
115 s_SubstSettings.bFoundFontMSMINCHO = TRUE;
116 }
117 else if (wcsicmp(FileName, L"mssong.ttf") == 0)
118 {
119 DPRINT("mssong.ttf found\n");
120 s_SubstSettings.bFoundFontMSSONG = TRUE;
121 }
122 }
123 else
124 {
125 if (wcsicmp(FileName, L"simsun.ttc") == 0)
126 {
127 DPRINT("simsun.ttc found\n");
128 s_SubstSettings.bFoundFontSIMSUN = TRUE;
129 }
130 else if (wcsicmp(FileName, L"gulim.ttc") == 0)
131 {
132 DPRINT("gulim.ttc found\n");
133 s_SubstSettings.bFoundFontGULIM = TRUE;
134 }
135 else if (wcsicmp(FileName, L"batang.ttc") == 0)
136 {
137 DPRINT("batang.ttc found\n");
138 s_SubstSettings.bFoundFontBATANG = TRUE;
139 }
140 }
141}
142#endif /* HACK */
143
144/* FUNCTIONS ****************************************************************/
145
146static VOID
148{
149 CHAR buffer[512];
150 va_list ap;
153
154 va_start(ap, fmt);
156 va_end(ap);
157
162}
163
164
165static VOID
167 IN SHORT yTop,
168 IN SHORT Width,
170{
171 COORD coPos;
172 DWORD Written;
173
174 /* Draw upper left corner */
175 coPos.X = xLeft;
176 coPos.Y = yTop;
178 CharUpperLeftCorner, // '+',
179 1,
180 coPos,
181 &Written);
182
183 /* Draw upper edge */
184 coPos.X = xLeft + 1;
185 coPos.Y = yTop;
187 CharHorizontalLine, // '-',
188 Width - 2,
189 coPos,
190 &Written);
191
192 /* Draw upper right corner */
193 coPos.X = xLeft + Width - 1;
194 coPos.Y = yTop;
196 CharUpperRightCorner, // '+',
197 1,
198 coPos,
199 &Written);
200
201 /* Draw right edge, inner space and left edge */
202 for (coPos.Y = yTop + 1; coPos.Y < yTop + Height - 1; coPos.Y++)
203 {
204 coPos.X = xLeft;
206 CharVerticalLine, // '|',
207 1,
208 coPos,
209 &Written);
210
211 coPos.X = xLeft + 1;
213 ' ',
214 Width - 2,
215 coPos,
216 &Written);
217
218 coPos.X = xLeft + Width - 1;
220 CharVerticalLine, // '|',
221 1,
222 coPos,
223 &Written);
224 }
225
226 /* Draw lower left corner */
227 coPos.X = xLeft;
228 coPos.Y = yTop + Height - 1;
230 CharLowerLeftCorner, // '+',
231 1,
232 coPos,
233 &Written);
234
235 /* Draw lower edge */
236 coPos.X = xLeft + 1;
237 coPos.Y = yTop + Height - 1;
239 CharHorizontalLine, // '-',
240 Width - 2,
241 coPos,
242 &Written);
243
244 /* Draw lower right corner */
245 coPos.X = xLeft + Width - 1;
246 coPos.Y = yTop + Height - 1;
248 CharLowerRightCorner, // '+',
249 1,
250 coPos,
251 &Written);
252}
253
254
255VOID
257 PCCH Status,
258 PINPUT_RECORD Ir,
259 ULONG WaitEvent)
260{
261 SHORT yTop;
262 SHORT xLeft;
263 COORD coPos;
264 DWORD Written;
266 ULONG MaxLength;
267 ULONG Lines;
268 PCHAR p;
269 PCCH pnext;
270 BOOLEAN LastLine;
271 SHORT Width;
273
274 /* Count text lines and longest line */
275 MaxLength = 0;
276 Lines = 0;
277 pnext = Text;
278
279 while (TRUE)
280 {
281 p = strchr(pnext, '\n');
282
283 if (p == NULL)
284 {
285 Length = strlen(pnext);
286 LastLine = TRUE;
287 }
288 else
289 {
290 Length = (ULONG)(p - pnext);
291 LastLine = FALSE;
292 }
293
294 Lines++;
295
296 if (Length > MaxLength)
297 MaxLength = Length;
298
299 if (LastLine)
300 break;
301
302 pnext = p + 1;
303 }
304
305 /* Check length of status line */
306 if (Status != NULL)
307 {
309
310 if (Length > MaxLength)
311 MaxLength = Length;
312 }
313
314 Width = MaxLength + 4;
315 Height = Lines + 2;
316
317 if (Status != NULL)
318 Height += 2;
319
320 yTop = (yScreen - Height) / 2;
321 xLeft = (xScreen - Width) / 2;
322
323
324 /* Set screen attributes */
325 coPos.X = xLeft;
326 for (coPos.Y = yTop; coPos.Y < yTop + Height; coPos.Y++)
327 {
330 Width,
331 coPos,
332 &Written);
333 }
334
335 DrawBox(xLeft, yTop, Width, Height);
336
337 /* Print message text */
338 coPos.Y = yTop + 1;
339 pnext = Text;
340 while (TRUE)
341 {
342 p = strchr(pnext, '\n');
343
344 if (p == NULL)
345 {
346 Length = strlen(pnext);
347 LastLine = TRUE;
348 }
349 else
350 {
351 Length = (ULONG)(p - pnext);
352 LastLine = FALSE;
353 }
354
355 if (Length != 0)
356 {
357 coPos.X = xLeft + 2;
359 pnext,
360 Length,
361 coPos,
362 &Written);
363 }
364
365 if (LastLine)
366 break;
367
368 coPos.Y++;
369 pnext = p + 1;
370 }
371
372 /* Print separator line and status text */
373 if (Status != NULL)
374 {
375 coPos.Y = yTop + Height - 3;
376 coPos.X = xLeft;
379 1,
380 coPos,
381 &Written);
382
383 coPos.X = xLeft + 1;
385 CharHorizontalLine, // '-',
386 Width - 2,
387 coPos,
388 &Written);
389
390 coPos.X = xLeft + Width - 1;
393 1,
394 coPos,
395 &Written);
396
397 coPos.Y++;
398 coPos.X = xLeft + 2;
400 Status,
401 min(strlen(Status), (SIZE_T)Width - 4),
402 coPos,
403 &Written);
404 }
405
406 if (WaitEvent == POPUP_WAIT_NONE)
407 return;
408
409 while (TRUE)
410 {
412
413 if (WaitEvent == POPUP_WAIT_ANY_KEY ||
414 Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)
415 {
416 return;
417 }
418 }
419}
420
421
422/*
423 * Confirm quit setup
424 * RETURNS
425 * TRUE: Quit setup.
426 * FALSE: Don't quit setup.
427 */
428static BOOL
430{
431 BOOL Result = FALSE;
433
434 while (TRUE)
435 {
437
438 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
439 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
440 {
441 Result = TRUE;
442 break;
443 }
444 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
445 {
446 Result = FALSE;
447 break;
448 }
449 }
450
451 return Result;
452}
453
454
455static VOID
457{
458 PGENERIC_LIST_ENTRY ListEntry;
459 PCWSTR pszNewLayout;
460
462
464 {
467 {
468 /* FIXME: Handle error! */
469 return;
470 }
471 }
472
473 /* Search for default layout (if provided) */
474 if (pszNewLayout != NULL)
475 {
476 for (ListEntry = GetFirstListEntry(USetupData.LayoutList); ListEntry;
477 ListEntry = GetNextListEntry(ListEntry))
478 {
479 if (!wcscmp(pszNewLayout, ((PGENENTRY)GetListEntryData(ListEntry))->Id))
480 {
482 break;
483 }
484 }
485 }
486}
487
488
489static NTSTATUS
490NTAPI
494 IN SIZE_T cchBufferSize)
495{
496 return RtlStringCchPrintfA(Buffer, cchBufferSize, "%S",
498}
499
500static NTSTATUS
501NTAPI
505 IN SIZE_T cchBufferSize)
506{
508 PPARTENTRY PartEntry = NtOsInstall->PartEntry;
509
510 if (PartEntry && PartEntry->DriveLetter)
511 {
512 /* We have retrieved a partition that is mounted */
513 return RtlStringCchPrintfA(Buffer, cchBufferSize,
514 "%C:%S \"%S\"",
515 PartEntry->DriveLetter,
516 NtOsInstall->PathComponent,
517 NtOsInstall->InstallationName);
518 }
519 else
520 {
521 /* We failed somewhere, just show the NT path */
522 return RtlStringCchPrintfA(Buffer, cchBufferSize,
523 "%wZ \"%S\"",
524 &NtOsInstall->SystemNtPath,
525 NtOsInstall->InstallationName);
526 }
527}
528
529
530/*
531 * Displays the LanguagePage.
532 *
533 * Next pages: WelcomePage, QuitPage
534 *
535 * SIDEEFFECTS
536 * Init SelectedLanguageId
537 * Init USetupData.LanguageId
538 *
539 * RETURNS
540 * Number of the next page.
541 */
542static PAGE_NUMBER
544{
545 GENERIC_LIST_UI ListUi;
546 PCWSTR NewLanguageId;
547 BOOL RefreshPage = FALSE;
548
549 /* Initialize the computer settings list */
551 {
554 {
555 PopupError("Setup failed to initialize available translations", NULL, NULL, POPUP_WAIT_NONE);
556 return WELCOME_PAGE;
557 }
558 }
559
562
563 /* Load the font */
566
567 /*
568 * If there is no language or just a single one in the list,
569 * skip the language selection process altogether.
570 */
572 {
574 return WELCOME_PAGE;
575 }
576
578 DrawGenericList(&ListUi,
579 2, 18,
580 xScreen - 3,
581 yScreen - 3);
582
584
586
587 while (TRUE)
588 {
590
591 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
592 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
593 {
594 ScrollDownGenericList(&ListUi);
595 RefreshPage = TRUE;
596 }
597 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
598 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
599 {
600 ScrollUpGenericList(&ListUi);
601 RefreshPage = TRUE;
602 }
603 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
604 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_NEXT)) /* PAGE DOWN */
605 {
607 RefreshPage = TRUE;
608 }
609 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
610 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_PRIOR)) /* PAGE UP */
611 {
613 RefreshPage = TRUE;
614 }
615 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
616 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
617 {
618 if (ConfirmQuit(Ir))
619 return QUIT_PAGE;
620 else
621 RedrawGenericList(&ListUi);
622 }
623 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
624 {
626
629
631
633 {
635 }
636
637 /* Load the font */
639
640 return WELCOME_PAGE;
641 }
642 else if ((Ir->Event.KeyEvent.uChar.AsciiChar > 0x60) && (Ir->Event.KeyEvent.uChar.AsciiChar < 0x7b))
643 {
644 /* a-z */
646 RefreshPage = TRUE;
647 }
648
649 if (RefreshPage)
650 {
652
653 NewLanguageId =
655
656 if (wcscmp(SelectedLanguageId, NewLanguageId))
657 {
658 /* Clear the language page */
660
661 SelectedLanguageId = NewLanguageId;
662
663 /* Load the font */
665
666 /* Redraw the list */
667 DrawGenericList(&ListUi,
668 2, 18,
669 xScreen - 3,
670 yScreen - 3);
671
672 /* Redraw language selection page in native language */
674 }
675
676 RefreshPage = FALSE;
677 }
678 }
679
680 return WELCOME_PAGE;
681}
682
683
684/*
685 * Start page
686 *
687 * Next pages:
688 * LanguagePage (at once, default)
689 * InstallIntroPage (at once, if unattended)
690 * QuitPage
691 *
692 * SIDEEFFECTS
693 * Init Sdi
694 * Init USetupData.SourcePath
695 * Init USetupData.SourceRootPath
696 * Init USetupData.SourceRootDir
697 * Init USetupData.SetupInf
698 * Init USetupData.RequiredPartitionDiskSpace
699 * Init IsUnattendedSetup
700 * If unattended, init *List and sets the Codepage
701 * If unattended, init SelectedLanguageId
702 * If unattended, init USetupData.LanguageId
703 *
704 * RETURNS
705 * Number of the next page.
706 */
707static PAGE_NUMBER
709{
710 ULONG Error;
711 PGENERIC_LIST_ENTRY ListEntry;
713
715
716 /* Initialize Setup, phase 1 */
718 if (Error != ERROR_SUCCESS)
719 {
721 return QUIT_PAGE;
722 }
723
724 /* Initialize the user-mode PnP manager */
726 DPRINT1("The user-mode PnP manager could not initialize, expect unavailable devices!\n");
727
728 /* Wait for any immediate pending installations to finish */
730 DPRINT1("WaitNoPendingInstallEvents() failed to wait!\n");
731
733
735 {
736 // TODO: Read options from inf
737 /* Load the hardware, language and keyboard layout lists */
738
742
744
745 /* new part */
749
751
752 /* first we hack LanguageList */
753 for (ListEntry = GetFirstListEntry(USetupData.LanguageList); ListEntry;
754 ListEntry = GetNextListEntry(ListEntry))
755 {
756 LocaleId = ((PGENENTRY)GetListEntryData(ListEntry))->Id;
758 {
759 DPRINT("found %S in LanguageList\n", LocaleId);
761 break;
762 }
763 }
764
765 /* now LayoutList */
766 for (ListEntry = GetFirstListEntry(USetupData.LayoutList); ListEntry;
767 ListEntry = GetNextListEntry(ListEntry))
768 {
769 LocaleId = ((PGENENTRY)GetListEntryData(ListEntry))->Id;
771 {
772 DPRINT("found %S in LayoutList\n", LocaleId);
774 break;
775 }
776 }
777
779
780 return INSTALL_INTRO_PAGE;
781 }
782
783 return LANGUAGE_PAGE;
784}
785
786
787/*
788 * Displays the WelcomePage.
789 *
790 * Next pages:
791 * InstallIntroPage (default)
792 * RepairIntroPage
793 * RecoveryPage
794 * LicensePage
795 * QuitPage
796 *
797 * RETURNS
798 * Number of the next page.
799 */
800static PAGE_NUMBER
802{
804
805 while (TRUE)
806 {
808
809 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
810 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
811 {
812 if (ConfirmQuit(Ir))
813 return QUIT_PAGE;
814
815 break;
816 }
817 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
818 {
819 return INSTALL_INTRO_PAGE;
820 }
821 else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'R') /* R */
822 {
823 return RECOVERY_PAGE; // REPAIR_INTRO_PAGE;
824 }
825 else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'L') /* L */
826 {
827 return LICENSE_PAGE;
828 }
829 }
830
831 return WELCOME_PAGE;
832}
833
834
835/*
836 * Displays the License page.
837 *
838 * Next page:
839 * WelcomePage (default)
840 *
841 * RETURNS
842 * Number of the next page.
843 */
844static PAGE_NUMBER
846{
848
849 while (TRUE)
850 {
852
853 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
854 {
855 return WELCOME_PAGE;
856 }
857 }
858
859 return LICENSE_PAGE;
860}
861
862
863/*
864 * Displays the RepairIntroPage.
865 *
866 * Next pages:
867 * RebootPage (default)
868 * InstallIntroPage
869 * RecoveryPage
870 * IntroPage
871 *
872 * RETURNS
873 * Number of the next page.
874 */
875static PAGE_NUMBER
877{
879
880 while (TRUE)
881 {
883
884 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
885 {
886 return REBOOT_PAGE;
887 }
888 else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'U') /* U */
889 {
891 return INSTALL_INTRO_PAGE;
892 }
893 else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'R') /* R */
894 {
895 return RECOVERY_PAGE;
896 }
897 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESC */
898 {
899 return WELCOME_PAGE;
900 }
901 }
902
903 return REPAIR_INTRO_PAGE;
904}
905
906/*
907 * Displays the UpgradeRepairPage.
908 *
909 * Next pages:
910 * RebootPage (default)
911 * InstallIntroPage
912 * RecoveryPage
913 * WelcomePage
914 *
915 * RETURNS
916 * Number of the next page.
917 */
918static PAGE_NUMBER
920{
921 GENERIC_LIST_UI ListUi;
922
923/*** HACK!! ***/
924 if (PartitionList == NULL)
925 {
927 if (PartitionList == NULL)
928 {
929 /* FIXME: show an error dialog */
931 return QUIT_PAGE;
932 }
934 {
936 return QUIT_PAGE;
937 }
938
939 /* Reset the formatter machine state */
942 }
943/**************/
944
946 if (!NtOsInstallsList)
947 DPRINT1("Failed to get a list of NTOS installations; continue installation...\n");
948
949 /*
950 * If there is no available installation (or just a single one??) that can
951 * be updated in the list, just continue with the regular installation.
952 */
954 {
956
957 // return INSTALL_INTRO_PAGE;
959 // return SCSI_CONTROLLER_PAGE;
960 }
961
963
965 DrawGenericList(&ListUi,
966 2, 23,
967 xScreen - 3,
968 yScreen - 3);
969
970 // return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir);
971 while (TRUE)
972 {
974
975 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x00)
976 {
977 switch (Ir->Event.KeyEvent.wVirtualKeyCode)
978 {
979 case VK_DOWN: /* DOWN */
980 ScrollDownGenericList(&ListUi);
981 break;
982 case VK_UP: /* UP */
983 ScrollUpGenericList(&ListUi);
984 break;
985 case VK_NEXT: /* PAGE DOWN */
987 break;
988 case VK_PRIOR: /* PAGE UP */
990 break;
991 case VK_F3: /* F3 */
992 {
993 if (ConfirmQuit(Ir))
994 return QUIT_PAGE;
995 else
996 RedrawGenericList(&ListUi);
997 break;
998 }
999#if 1
1000/* TODO: Temporarily kept until correct keyboard layout is in place.
1001 * (Actual AsciiChar of ESCAPE should be 0x1B instead of 0.)
1002 * Addendum to commit 8b94515b.
1003 */
1004 case VK_ESCAPE: /* ESC */
1005 {
1007 // return nextPage; // prevPage;
1008
1009 // return INSTALL_INTRO_PAGE;
1010 return DEVICE_SETTINGS_PAGE;
1011 // return SCSI_CONTROLLER_PAGE;
1012 }
1013
1014#endif
1015 }
1016 }
1017#if 0
1018/* TODO: Restore this once correct keyboard layout is in place. */
1019 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESC */
1020 {
1022 // return nextPage; // prevPage;
1023
1024 // return INSTALL_INTRO_PAGE;
1025 return DEVICE_SETTINGS_PAGE;
1026 // return SCSI_CONTROLLER_PAGE;
1027 }
1028#endif
1029 else
1030 {
1031 // switch (toupper(Ir->Event.KeyEvent.uChar.AsciiChar))
1032 // if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1033 if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'U') /* U */
1034 {
1035 /* Retrieve the current installation */
1037
1040
1041 DPRINT1("Selected installation for repair: \"%S\" ; DiskNumber = %d , PartitionNumber = %d\n",
1043
1045
1046 // return nextPage;
1047 /***/return INSTALL_INTRO_PAGE;/***/
1048 }
1049 else if ((Ir->Event.KeyEvent.uChar.AsciiChar > 0x60) &&
1050 (Ir->Event.KeyEvent.uChar.AsciiChar < 0x7b)) /* a-z */
1051 {
1053 }
1054 }
1055 }
1056
1057 return UPGRADE_REPAIR_PAGE;
1058}
1059
1060
1061/*
1062 * Displays the InstallIntroPage.
1063 *
1064 * Next pages:
1065 * DeviceSettingsPage (At once if repair or update is selected)
1066 * SelectPartitionPage (At once if unattended setup)
1067 * DeviceSettingsPage (default)
1068 * QuitPage
1069 *
1070 * RETURNS
1071 * Number of the next page.
1072 */
1073static PAGE_NUMBER
1075{
1076 if (RepairUpdateFlag)
1077 {
1078#if 1 /* Old code that looks good */
1079
1080 // return SELECT_PARTITION_PAGE;
1081 return DEVICE_SETTINGS_PAGE;
1082
1083#else /* Possible new code? */
1084
1085 return DEVICE_SETTINGS_PAGE;
1086 // return SCSI_CONTROLLER_PAGE;
1087
1088#endif
1089 }
1090
1092 return SELECT_PARTITION_PAGE;
1093
1095
1096 while (TRUE)
1097 {
1098 CONSOLE_ConInKey(Ir);
1099
1100 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1101 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1102 {
1103 if (ConfirmQuit(Ir))
1104 return QUIT_PAGE;
1105
1106 break;
1107 }
1108 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1109 {
1110 return UPGRADE_REPAIR_PAGE;
1111 }
1112 }
1113
1114 return INSTALL_INTRO_PAGE;
1115}
1116
1117
1118#if 0
1119static PAGE_NUMBER
1120ScsiControllerPage(PINPUT_RECORD Ir)
1121{
1122 // MUIDisplayPage(SCSI_CONTROLLER_PAGE);
1123
1124 CONSOLE_SetTextXY(6, 8, "Setup detected the following mass storage devices:");
1125
1126 /* FIXME: print loaded mass storage driver descriptions */
1127#if 0
1128 CONSOLE_SetTextXY(8, 10, "TEST device");
1129#endif
1130
1131 CONSOLE_SetStatusText(" ENTER = Continue F3 = Quit");
1132
1133 while (TRUE)
1134 {
1135 CONSOLE_ConInKey(Ir);
1136
1137 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1138 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1139 {
1140 if (ConfirmQuit(Ir))
1141 return QUIT_PAGE;
1142
1143 break;
1144 }
1145 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1146 {
1147 return DEVICE_SETTINGS_PAGE;
1148 }
1149 }
1150
1151 return SCSI_CONTROLLER_PAGE;
1152}
1153
1154static PAGE_NUMBER
1155OemDriverPage(PINPUT_RECORD Ir)
1156{
1157 // MUIDisplayPage(OEM_DRIVER_PAGE);
1158
1159 CONSOLE_SetTextXY(6, 8, "This is the OEM driver page!");
1160
1161 /* FIXME: Implement!! */
1162
1163 CONSOLE_SetStatusText(" ENTER = Continue F3 = Quit");
1164
1165 while (TRUE)
1166 {
1167 CONSOLE_ConInKey(Ir);
1168
1169 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1170 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1171 {
1172 if (ConfirmQuit(Ir))
1173 return QUIT_PAGE;
1174
1175 break;
1176 }
1177 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1178 {
1179 return DEVICE_SETTINGS_PAGE;
1180 }
1181 }
1182
1183 return OEM_DRIVER_PAGE;
1184}
1185#endif
1186
1187
1188/*
1189 * Displays the DeviceSettingsPage.
1190 *
1191 * Next pages:
1192 * SelectPartitionPage (At once if repair or update is selected)
1193 * ComputerSettingsPage
1194 * DisplaySettingsPage
1195 * KeyboardSettingsPage
1196 * LayoutsettingsPage
1197 * SelectPartitionPage
1198 * QuitPage
1199 *
1200 * SIDEEFFECTS
1201 * Init USetupData.ComputerList
1202 * Init USetupData.DisplayList
1203 * Init USetupData.KeyboardList
1204 * Init USetupData.LayoutList
1205 *
1206 * RETURNS
1207 * Number of the next page.
1208 */
1209static PAGE_NUMBER
1211{
1212 static ULONG Line = 16;
1213
1214 /* Initialize the computer settings list */
1216 {
1219 {
1221 return QUIT_PAGE;
1222 }
1223 }
1224
1225 /* Initialize the display settings list */
1227 {
1230 {
1232 return QUIT_PAGE;
1233 }
1234 }
1235
1236 /* Initialize the keyboard settings list */
1238 {
1241 {
1243 return QUIT_PAGE;
1244 }
1245 }
1246
1247 /* Initialize the keyboard layout list */
1248 if (USetupData.LayoutList == NULL)
1249 {
1251 if (USetupData.LayoutList == NULL)
1252 {
1253 /* FIXME: report error */
1255 return QUIT_PAGE;
1256 }
1257 }
1258
1259 if (RepairUpdateFlag)
1260 return SELECT_PARTITION_PAGE;
1261
1262 // if (IsUnattendedSetup)
1263 // return SELECT_PARTITION_PAGE;
1264
1266
1271
1272 CONSOLE_InvertTextXY(24, Line, 48, 1);
1273
1274 while (TRUE)
1275 {
1276 CONSOLE_ConInKey(Ir);
1277
1278 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1279 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1280 {
1281 CONSOLE_NormalTextXY(24, Line, 48, 1);
1282
1283 if (Line == 14)
1284 Line = 16;
1285 else if (Line == 16)
1286 Line = 11;
1287 else
1288 Line++;
1289
1290 CONSOLE_InvertTextXY(24, Line, 48, 1);
1291 }
1292 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1293 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1294 {
1295 CONSOLE_NormalTextXY(24, Line, 48, 1);
1296
1297 if (Line == 11)
1298 Line = 16;
1299 else if (Line == 16)
1300 Line = 14;
1301 else
1302 Line--;
1303
1304 CONSOLE_InvertTextXY(24, Line, 48, 1);
1305 }
1306 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1307 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1308 {
1309 if (ConfirmQuit(Ir))
1310 return QUIT_PAGE;
1311
1312 break;
1313 }
1314 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1315 {
1316 if (Line == 11)
1318 else if (Line == 12)
1319 return DISPLAY_SETTINGS_PAGE;
1320 else if (Line == 13)
1322 else if (Line == 14)
1323 return LAYOUT_SETTINGS_PAGE;
1324 else if (Line == 16)
1325 return SELECT_PARTITION_PAGE;
1326 }
1327 }
1328
1329 return DEVICE_SETTINGS_PAGE;
1330}
1331
1332
1333/*
1334 * Handles generic selection lists.
1335 *
1336 * PARAMS
1337 * GenericList: The list to handle.
1338 * nextPage: The page it needs to jump to after this page.
1339 * Ir: The PINPUT_RECORD
1340 */
1341static PAGE_NUMBER
1343 PAGE_NUMBER nextPage,
1344 PINPUT_RECORD Ir)
1345{
1346 while (TRUE)
1347 {
1348 CONSOLE_ConInKey(Ir);
1349
1350 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1351 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1352 {
1353 ScrollDownGenericList(ListUi);
1354 }
1355 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1356 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1357 {
1358 ScrollUpGenericList(ListUi);
1359 }
1360 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1361 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_NEXT)) /* PAGE DOWN */
1362 {
1364 }
1365 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1366 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_PRIOR)) /* PAGE UP */
1367 {
1369 }
1370 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1371 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1372 {
1373 if (ConfirmQuit(Ir))
1374 return QUIT_PAGE;
1375 else
1376 RedrawGenericList(ListUi);
1377 }
1378 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESC */
1379 {
1381 return nextPage; // Use some "prevPage;" instead?
1382 }
1383 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1384 {
1385 return nextPage;
1386 }
1387 else if ((Ir->Event.KeyEvent.uChar.AsciiChar > 0x60) && (Ir->Event.KeyEvent.uChar.AsciiChar < 0x7b))
1388 {
1389 /* a-z */
1391 }
1392 }
1393}
1394
1395
1396/*
1397 * Displays the ComputerSettingsPage.
1398 *
1399 * Next pages:
1400 * DeviceSettingsPage
1401 * QuitPage
1402 *
1403 * RETURNS
1404 * Number of the next page.
1405 */
1406static PAGE_NUMBER
1408{
1409 GENERIC_LIST_UI ListUi;
1411
1413 DrawGenericList(&ListUi,
1414 2, 18,
1415 xScreen - 3,
1416 yScreen - 3);
1417
1418 return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir);
1419}
1420
1421
1422/*
1423 * Displays the DisplaySettingsPage.
1424 *
1425 * Next pages:
1426 * DeviceSettingsPage
1427 * QuitPage
1428 *
1429 * RETURNS
1430 * Number of the next page.
1431 */
1432static PAGE_NUMBER
1434{
1435 GENERIC_LIST_UI ListUi;
1437
1439 DrawGenericList(&ListUi,
1440 2, 18,
1441 xScreen - 3,
1442 yScreen - 3);
1443
1444 return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir);
1445}
1446
1447
1448/*
1449 * Displays the KeyboardSettingsPage.
1450 *
1451 * Next pages:
1452 * DeviceSettingsPage
1453 * QuitPage
1454 *
1455 * RETURNS
1456 * Number of the next page.
1457 */
1458static PAGE_NUMBER
1460{
1461 GENERIC_LIST_UI ListUi;
1463
1465 DrawGenericList(&ListUi,
1466 2, 18,
1467 xScreen - 3,
1468 yScreen - 3);
1469
1470 return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir);
1471}
1472
1473
1474/*
1475 * Displays the LayoutSettingsPage.
1476 *
1477 * Next pages:
1478 * DeviceSettingsPage
1479 * QuitPage
1480 *
1481 * RETURNS
1482 * Number of the next page.
1483 */
1484static PAGE_NUMBER
1486{
1487 GENERIC_LIST_UI ListUi;
1489
1491 DrawGenericList(&ListUi,
1492 2, 18,
1493 xScreen - 3,
1494 yScreen - 3);
1495
1496 return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir);
1497}
1498
1499
1500static BOOL
1502{
1504
1505 size = PartEntry->SectorCount.QuadPart * PartEntry->DiskEntry->BytesPerSector;
1506 size = (size + (512 * KB)) / MB; /* in MBytes */
1507
1509 {
1510 /* Partition is too small so ask for another one */
1511 DPRINT1("Partition is too small (size: %I64u MB), required disk space is %lu MB\n", size, USetupData.RequiredPartitionDiskSpace);
1512 return FALSE;
1513 }
1514 else
1515 {
1516 return TRUE;
1517 }
1518}
1519
1520
1521/*
1522 * Displays the SelectPartitionPage.
1523 *
1524 * Next pages:
1525 * SelectFileSystemPage (At once if unattended)
1526 * SelectFileSystemPage (Default if free space is selected)
1527 * CreatePrimaryPartitionPage
1528 * CreateExtendedPartitionPage
1529 * CreateLogicalPartitionPage
1530 * ConfirmDeleteSystemPartitionPage (if the selected partition is the system partition, aka with the boot flag set)
1531 * DeletePartitionPage
1532 * QuitPage
1533 *
1534 * SIDEEFFECTS
1535 * Set InstallShortcut (only if not unattended + free space is selected)
1536 *
1537 * RETURNS
1538 * Number of the next page.
1539 */
1540static PAGE_NUMBER
1542{
1543 PARTLIST_UI ListUi;
1544 ULONG Error;
1545
1546 if (PartitionList == NULL)
1547 {
1549 if (PartitionList == NULL)
1550 {
1552 return QUIT_PAGE;
1553 }
1555 {
1557 return QUIT_PAGE;
1558 }
1559
1560 /* Reset the formatter machine state */
1563 }
1564
1565 if (RepairUpdateFlag)
1566 {
1568
1569 /* Determine the selected installation disk & partition */
1573 if (!InstallPartition)
1574 {
1575 DPRINT1("RepairUpdateFlag == TRUE, SelectPartition() returned FALSE, assert!\n");
1576 ASSERT(FALSE);
1577 }
1579
1581 }
1582
1584
1587 2, 23,
1588 xScreen - 3,
1589 yScreen - 3);
1590 DrawPartitionList(&ListUi);
1591
1593 {
1594 /* Determine the selected installation disk & partition */
1598 if (!InstallPartition)
1599 {
1601
1603 {
1606
1608 {
1612 TRUE);
1613 }
1614 else
1615 {
1619 TRUE);
1620 }
1621
1622// FIXME?? Aren't we going to enter an infinite loop, if this test fails??
1624 {
1627 return SELECT_PARTITION_PAGE; /* let the user select another partition */
1628 }
1629
1632 }
1633 }
1634 else
1635 {
1637
1638 DrawPartitionList(&ListUi); // FIXME: Doesn't make much sense...
1639
1640// FIXME?? Aren't we going to enter an infinite loop, if this test fails??
1642 {
1645 return SELECT_PARTITION_PAGE; /* let the user select another partition */
1646 }
1647
1649 }
1650 }
1651
1652 while (TRUE)
1653 {
1655
1656 /* Update status text */
1657 if (CurrentPartition == NULL)
1658 {
1660 }
1662 {
1664 {
1666 }
1667 else
1668 {
1670 }
1671 }
1672 else
1673 {
1675 {
1677 {
1679 }
1680 else
1681 {
1683 }
1684 }
1685 else
1686 {
1688 }
1689 }
1690
1691 CONSOLE_ConInKey(Ir);
1692
1693 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1694 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1695 {
1696 if (ConfirmQuit(Ir))
1697 {
1700 return QUIT_PAGE;
1701 }
1702
1703 break;
1704 }
1705 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1706 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1707 {
1708 ScrollDownPartitionList(&ListUi);
1709 }
1710 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1711 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1712 {
1713 ScrollUpPartitionList(&ListUi);
1714 }
1715 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
1716 {
1718
1720 continue; // return SELECT_PARTITION_PAGE;
1721
1722 /*
1723 * Check whether the user wants to install ReactOS on a disk that
1724 * is not recognized by the computer's firmware and if so, display
1725 * a warning since such disks may not be bootable.
1726 */
1727 if (CurrentPartition->DiskEntry->MediaType == FixedMedia &&
1728 !CurrentPartition->DiskEntry->BiosFound)
1729 {
1730 PopupError("The disk you have selected for installing ReactOS\n"
1731 "is not visible by the firmware of your computer,\n"
1732 "and so may not be bootable.\n"
1733 "Press ENTER to continue nonetheless.",
1735 Ir, POPUP_WAIT_ENTER);
1736 // return SELECT_PARTITION_PAGE;
1737 }
1738
1740 {
1742 {
1744 if (Error != NOT_AN_ERROR)
1745 {
1747 return SELECT_PARTITION_PAGE;
1748 }
1749
1752 0ULL,
1753 TRUE);
1754 }
1755 else
1756 {
1758 if (Error != NOT_AN_ERROR)
1759 {
1761 return SELECT_PARTITION_PAGE;
1762 }
1763
1766 0ULL,
1767 TRUE);
1768 }
1769 }
1770
1772 {
1775 return SELECT_PARTITION_PAGE; /* let the user select another partition */
1776 }
1777
1780 }
1781 else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'P') /* P */
1782 {
1784
1786 {
1788 if (Error != NOT_AN_ERROR)
1789 {
1791 return SELECT_PARTITION_PAGE;
1792 }
1793
1795 }
1796 }
1797 else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'E') /* E */
1798 {
1800
1802 {
1804 if (Error != NOT_AN_ERROR)
1805 {
1807 return SELECT_PARTITION_PAGE;
1808 }
1809
1811 }
1812 }
1813 else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'L') /* L */
1814 {
1816
1818 {
1820 if (Error != NOT_AN_ERROR)
1821 {
1823 return SELECT_PARTITION_PAGE;
1824 }
1825
1827 }
1828 }
1829 else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'D') /* D */
1830 {
1831 UNICODE_STRING CurrentPartitionU;
1832 WCHAR PathBuffer[MAX_PATH];
1833
1835
1837 {
1839 return SELECT_PARTITION_PAGE;
1840 }
1841
1842// TODO: Do something similar before trying to format the partition?
1843 if (!CurrentPartition->New &&
1846 {
1848
1849 RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
1850 L"\\Device\\Harddisk%lu\\Partition%lu\\",
1851 CurrentPartition->DiskEntry->DiskNumber,
1853 RtlInitUnicodeString(&CurrentPartitionU, PathBuffer);
1854
1855 /*
1856 * Check whether the user attempts to delete the partition on which
1857 * the installation source is present. If so, fail with an error.
1858 */
1859 // &USetupData.SourceRootPath
1860 if (RtlPrefixUnicodeString(&CurrentPartitionU, &USetupData.SourcePath, TRUE))
1861 {
1863 return SELECT_PARTITION_PAGE;
1864 }
1865 }
1866
1869 {
1871 }
1872
1873 return DELETE_PARTITION_PAGE;
1874 }
1875 }
1876
1877 return SELECT_PARTITION_PAGE;
1878}
1879
1880
1881#define PARTITION_SIZE_INPUT_FIELD_LENGTH 9
1882/* Restriction for MaxSize */
1883#define PARTITION_MAXSIZE (pow(10, (PARTITION_SIZE_INPUT_FIELD_LENGTH - 1)) - 1)
1884
1885static VOID
1887 SHORT Top,
1888 SHORT Right,
1889 SHORT Bottom,
1890 ULONG MaxSize,
1892 PBOOLEAN Quit,
1894{
1895 INPUT_RECORD Ir;
1896 COORD coPos;
1897 DWORD Written;
1898 CHAR Buffer[128];
1899 INT Length, Pos;
1900 WCHAR ch;
1901 SHORT iLeft;
1902 SHORT iTop;
1903
1904 if (Quit != NULL)
1905 *Quit = FALSE;
1906
1907 if (Cancel != NULL)
1908 *Cancel = FALSE;
1909
1910 DrawBox(Left, Top, Right - Left + 1, Bottom - Top + 1);
1911
1912 /* Print message */
1913 coPos.X = Left + 2;
1914 coPos.Y = Top + 2;
1916 iLeft = coPos.X + (USHORT)strlen(Buffer) + 1;
1917 iTop = coPos.Y;
1918
1920 Buffer,
1921 strlen(Buffer),
1922 coPos,
1923 &Written);
1924
1926 coPos.X = iLeft + PARTITION_SIZE_INPUT_FIELD_LENGTH + 1;
1927 coPos.Y = iTop;
1929 Buffer,
1930 strlen(Buffer),
1931 coPos,
1932 &Written);
1933
1934 swprintf(InputBuffer, L"%lu", MaxSize);
1936 Pos = Length;
1938 iTop,
1940 InputBuffer);
1941 CONSOLE_SetCursorXY(iLeft + Length, iTop);
1943
1944 while (TRUE)
1945 {
1946 CONSOLE_ConInKey(&Ir);
1947
1948 if ((Ir.Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1949 (Ir.Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1950 {
1951 if (Quit != NULL)
1952 *Quit = TRUE;
1953
1956 break;
1957 }
1958 else if (Ir.Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
1959 {
1961 break;
1962 }
1963 else if (Ir.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESC */
1964 {
1965 if (Cancel != NULL)
1966 *Cancel = TRUE;
1967
1970 break;
1971 }
1972 else if ((Ir.Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1973 (Ir.Event.KeyEvent.wVirtualKeyCode == VK_HOME)) /* HOME */
1974 {
1975 Pos = 0;
1976 CONSOLE_SetCursorXY(iLeft + Pos, iTop);
1977 }
1978 else if ((Ir.Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1979 (Ir.Event.KeyEvent.wVirtualKeyCode == VK_END)) /* END */
1980 {
1981 Pos = Length;
1982 CONSOLE_SetCursorXY(iLeft + Pos, iTop);
1983 }
1984 else if ((Ir.Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1985 (Ir.Event.KeyEvent.wVirtualKeyCode == VK_LEFT)) /* LEFT */
1986 {
1987 if (Pos > 0)
1988 {
1989 Pos--;
1990 CONSOLE_SetCursorXY(iLeft + Pos, iTop);
1991 }
1992 }
1993 else if ((Ir.Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1994 (Ir.Event.KeyEvent.wVirtualKeyCode == VK_RIGHT)) /* RIGHT */
1995 {
1996 if (Pos < Length)
1997 {
1998 Pos++;
1999 CONSOLE_SetCursorXY(iLeft + Pos, iTop);
2000 }
2001 }
2002 else if ((Ir.Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2003 (Ir.Event.KeyEvent.wVirtualKeyCode == VK_DELETE)) /* DEL */
2004 {
2005 if (Pos < Length)
2006 {
2008 &InputBuffer[Pos + 1],
2009 (Length - Pos - 1) * sizeof(WCHAR));
2011
2012 Length--;
2014 iTop,
2016 InputBuffer);
2017 CONSOLE_SetCursorXY(iLeft + Pos, iTop);
2018 }
2019 }
2020 else if (Ir.Event.KeyEvent.wVirtualKeyCode == VK_BACK) /* BACKSPACE */
2021 {
2022 if (Pos > 0)
2023 {
2024 if (Pos < Length)
2025 memmove(&InputBuffer[Pos - 1],
2026 &InputBuffer[Pos],
2027 (Length - Pos) * sizeof(WCHAR));
2029
2030 Pos--;
2031 Length--;
2033 iTop,
2035 InputBuffer);
2036 CONSOLE_SetCursorXY(iLeft + Pos, iTop);
2037 }
2038 }
2039 else if (Ir.Event.KeyEvent.uChar.AsciiChar != 0x00)
2040 {
2042 {
2044
2045 if ((ch >= L'0') && (ch <= L'9'))
2046 {
2047 if (Pos < Length)
2048 memmove(&InputBuffer[Pos + 1],
2049 &InputBuffer[Pos],
2050 (Length - Pos) * sizeof(WCHAR));
2052 InputBuffer[Pos] = ch;
2053
2054 Pos++;
2055 Length++;
2057 iTop,
2059 InputBuffer);
2060 CONSOLE_SetCursorXY(iLeft + Pos, iTop);
2061 }
2062 }
2063 }
2064 }
2065}
2066
2067
2068/*
2069 * Displays the CreatePrimaryPartitionPage.
2070 *
2071 * Next pages:
2072 * SelectPartitionPage
2073 * SelectFileSystemPage (default)
2074 * QuitPage
2075 *
2076 * RETURNS
2077 * Number of the next page.
2078 */
2079static PAGE_NUMBER
2081{
2082 PPARTENTRY PartEntry;
2083 PDISKENTRY DiskEntry;
2084 BOOLEAN Quit;
2086 ULONG MaxSize;
2087 ULONGLONG PartSize;
2089 WCHAR InputBuffer[50];
2090 CHAR LineBuffer[100];
2091
2093 {
2094 /* FIXME: show an error dialog */
2095 return QUIT_PAGE;
2096 }
2097
2098 PartEntry = CurrentPartition;
2099 DiskEntry = CurrentPartition->DiskEntry;
2100
2102
2104
2105 DiskDescription(DiskEntry, LineBuffer, ARRAYSIZE(LineBuffer));
2107 LineBuffer);
2108
2110
2111#if 0
2112 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2114#endif
2115
2117
2118 PartEntry = CurrentPartition;
2119 while (TRUE)
2120 {
2121 MaxSize = (PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector) / MB; /* in MBytes (rounded) */
2122
2123 if (MaxSize > PARTITION_MAXSIZE)
2124 MaxSize = PARTITION_MAXSIZE;
2125
2126 ShowPartitionSizeInputBox(12, 14, xScreen - 12, 17, /* left, top, right, bottom */
2127 MaxSize, InputBuffer, &Quit, &Cancel);
2128
2129 if (Quit)
2130 {
2131 if (ConfirmQuit(Ir))
2132 return QUIT_PAGE;
2133
2134 break;
2135 }
2136 else if (Cancel)
2137 {
2138 return SELECT_PARTITION_PAGE;
2139 }
2140 else
2141 {
2142 PartSize = _wcstoui64(InputBuffer, NULL, 10);
2143
2144 if (PartSize < 1)
2145 {
2146 /* Too small */
2147 continue;
2148 }
2149
2150 if (PartSize > MaxSize)
2151 {
2152 /* Too large */
2153 continue;
2154 }
2155
2156 /* Convert to bytes */
2157 if (PartSize == MaxSize)
2158 {
2159 /* Use all of the unpartitioned disk space */
2160 SectorCount = PartEntry->SectorCount.QuadPart;
2161 }
2162 else
2163 {
2164 /* Calculate the sector count from the size in MB */
2165 SectorCount = PartSize * MB / DiskEntry->BytesPerSector;
2166
2167 /* But never get larger than the unpartitioned disk space */
2168 if (SectorCount > PartEntry->SectorCount.QuadPart)
2169 SectorCount = PartEntry->SectorCount.QuadPart;
2170 }
2171
2172 DPRINT ("Partition size: %I64u bytes\n", PartSize);
2173
2177 FALSE);
2178
2179 return SELECT_PARTITION_PAGE;
2180 }
2181 }
2182
2184}
2185
2186
2187/*
2188 * Displays the CreateExtendedPartitionPage.
2189 *
2190 * Next pages:
2191 * SelectPartitionPage (default)
2192 * QuitPage
2193 *
2194 * RETURNS
2195 * Number of the next page.
2196 */
2197static PAGE_NUMBER
2199{
2200 PPARTENTRY PartEntry;
2201 PDISKENTRY DiskEntry;
2202 BOOLEAN Quit;
2204 ULONG MaxSize;
2205 ULONGLONG PartSize;
2207 WCHAR InputBuffer[50];
2208 CHAR LineBuffer[100];
2209
2211 {
2212 /* FIXME: show an error dialog */
2213 return QUIT_PAGE;
2214 }
2215
2216 PartEntry = CurrentPartition;
2217 DiskEntry = CurrentPartition->DiskEntry;
2218
2220
2222
2223 DiskDescription(DiskEntry, LineBuffer, ARRAYSIZE(LineBuffer));
2225 LineBuffer);
2226
2228
2229#if 0
2230 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2232#endif
2233
2235
2236 PartEntry = CurrentPartition;
2237 while (TRUE)
2238 {
2239 MaxSize = (PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector) / MB; /* in MBytes (rounded) */
2240
2241 if (MaxSize > PARTITION_MAXSIZE)
2242 MaxSize = PARTITION_MAXSIZE;
2243
2244 ShowPartitionSizeInputBox(12, 14, xScreen - 12, 17, /* left, top, right, bottom */
2245 MaxSize, InputBuffer, &Quit, &Cancel);
2246
2247 if (Quit)
2248 {
2249 if (ConfirmQuit(Ir))
2250 return QUIT_PAGE;
2251
2252 break;
2253 }
2254 else if (Cancel)
2255 {
2256 return SELECT_PARTITION_PAGE;
2257 }
2258 else
2259 {
2260 PartSize = _wcstoui64(InputBuffer, NULL, 10);
2261
2262 if (PartSize < 1)
2263 {
2264 /* Too small */
2265 continue;
2266 }
2267
2268 if (PartSize > MaxSize)
2269 {
2270 /* Too large */
2271 continue;
2272 }
2273
2274 /* Convert to bytes */
2275 if (PartSize == MaxSize)
2276 {
2277 /* Use all of the unpartitioned disk space */
2278 SectorCount = PartEntry->SectorCount.QuadPart;
2279 }
2280 else
2281 {
2282 /* Calculate the sector count from the size in MB */
2283 SectorCount = PartSize * MB / DiskEntry->BytesPerSector;
2284
2285 /* But never get larger than the unpartitioned disk space */
2286 if (SectorCount > PartEntry->SectorCount.QuadPart)
2287 SectorCount = PartEntry->SectorCount.QuadPart;
2288 }
2289
2290 DPRINT ("Partition size: %I64u bytes\n", PartSize);
2291
2294 SectorCount);
2295
2296 return SELECT_PARTITION_PAGE;
2297 }
2298 }
2299
2301}
2302
2303
2304/*
2305 * Displays the CreateLogicalPartitionPage.
2306 *
2307 * Next pages:
2308 * SelectFileSystemPage (default)
2309 * QuitPage
2310 *
2311 * RETURNS
2312 * Number of the next page.
2313 */
2314static PAGE_NUMBER
2316{
2317 PPARTENTRY PartEntry;
2318 PDISKENTRY DiskEntry;
2319 BOOLEAN Quit;
2321 ULONG MaxSize;
2322 ULONGLONG PartSize;
2324 WCHAR InputBuffer[50];
2325 CHAR LineBuffer[100];
2326
2328 {
2329 /* FIXME: show an error dialog */
2330 return QUIT_PAGE;
2331 }
2332
2333 PartEntry = CurrentPartition;
2334 DiskEntry = CurrentPartition->DiskEntry;
2335
2337
2339
2340 DiskDescription(DiskEntry, LineBuffer, ARRAYSIZE(LineBuffer));
2342 LineBuffer);
2343
2345
2346#if 0
2347 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2349#endif
2350
2352
2353 PartEntry = CurrentPartition;
2354 while (TRUE)
2355 {
2356 MaxSize = (PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector) / MB; /* in MBytes (rounded) */
2357
2358 if (MaxSize > PARTITION_MAXSIZE)
2359 MaxSize = PARTITION_MAXSIZE;
2360
2361 ShowPartitionSizeInputBox(12, 14, xScreen - 12, 17, /* left, top, right, bottom */
2362 MaxSize, InputBuffer, &Quit, &Cancel);
2363
2364 if (Quit)
2365 {
2366 if (ConfirmQuit(Ir))
2367 return QUIT_PAGE;
2368
2369 break;
2370 }
2371 else if (Cancel)
2372 {
2373 return SELECT_PARTITION_PAGE;
2374 }
2375 else
2376 {
2377 PartSize = _wcstoui64(InputBuffer, NULL, 10);
2378
2379 if (PartSize < 1)
2380 {
2381 /* Too small */
2382 continue;
2383 }
2384
2385 if (PartSize > MaxSize)
2386 {
2387 /* Too large */
2388 continue;
2389 }
2390
2391 /* Convert to bytes */
2392 if (PartSize == MaxSize)
2393 {
2394 /* Use all of the unpartitioned disk space */
2395 SectorCount = PartEntry->SectorCount.QuadPart;
2396 }
2397 else
2398 {
2399 /* Calculate the sector count from the size in MB */
2400 SectorCount = PartSize * MB / DiskEntry->BytesPerSector;
2401
2402 /* But never get larger than the unpartitioned disk space */
2403 if (SectorCount > PartEntry->SectorCount.QuadPart)
2404 SectorCount = PartEntry->SectorCount.QuadPart;
2405 }
2406
2407 DPRINT("Partition size: %I64u bytes\n", PartSize);
2408
2412 FALSE);
2413
2414 return SELECT_PARTITION_PAGE;
2415 }
2416 }
2417
2419}
2420
2421
2422/*
2423 * Displays the ConfirmDeleteSystemPartitionPage.
2424 *
2425 * Next pages:
2426 * DeletePartitionPage (default)
2427 * SelectPartitionPage
2428 *
2429 * RETURNS
2430 * Number of the next page.
2431 */
2432static PAGE_NUMBER
2434{
2436
2437 while (TRUE)
2438 {
2439 CONSOLE_ConInKey(Ir);
2440
2441 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2442 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
2443 {
2444 if (ConfirmQuit(Ir))
2445 return QUIT_PAGE;
2446
2447 break;
2448 }
2449 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
2450 {
2451 return DELETE_PARTITION_PAGE;
2452 }
2453 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESC */
2454 {
2455 return SELECT_PARTITION_PAGE;
2456 }
2457 }
2458
2460}
2461
2462
2463/*
2464 * Displays the DeletePartitionPage.
2465 *
2466 * Next pages:
2467 * SelectPartitionPage (default)
2468 * QuitPage
2469 *
2470 * RETURNS
2471 * Number of the next page.
2472 */
2473static PAGE_NUMBER
2475{
2476 PPARTENTRY PartEntry;
2477 PDISKENTRY DiskEntry;
2478 CHAR LineBuffer[100];
2479
2481 {
2482 /* FIXME: show an error dialog */
2483 return QUIT_PAGE;
2484 }
2485
2486 PartEntry = CurrentPartition;
2487 DiskEntry = CurrentPartition->DiskEntry;
2488
2490
2491 PartitionDescription(PartEntry, LineBuffer, ARRAYSIZE(LineBuffer));
2492 CONSOLE_PrintTextXY(6, 10, " %s", LineBuffer);
2493
2494 DiskDescription(DiskEntry, LineBuffer, ARRAYSIZE(LineBuffer));
2496 LineBuffer);
2497
2498 while (TRUE)
2499 {
2500 CONSOLE_ConInKey(Ir);
2501
2502 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2503 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
2504 {
2505 if (ConfirmQuit(Ir))
2506 return QUIT_PAGE;
2507
2508 break;
2509 }
2510 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESC */
2511 {
2512 return SELECT_PARTITION_PAGE;
2513 }
2514 else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'L') /* L */
2515 {
2519 return SELECT_PARTITION_PAGE;
2520 }
2521 }
2522
2523 return DELETE_PARTITION_PAGE;
2524}
2525
2526
2527static VOID
2529{
2530 if (!FileSystemList)
2531 return;
2532
2535}
2536
2537/*
2538 * Displays the SelectFileSystemPage.
2539 *
2540 * Next pages:
2541 * CheckFileSystemPage (At once if RepairUpdate is selected)
2542 * CheckFileSystemPage (At once if Unattended and not USetupData.FormatPartition)
2543 * FormatPartitionPage (At once if Unattended and USetupData.FormatPartition)
2544 * SelectPartitionPage (If the user aborts)
2545 * FormatPartitionPage (Default)
2546 * QuitPage
2547 *
2548 * SIDEEFFECTS
2549 * Calls UpdatePartitionType()
2550 * Calls FindSupportedSystemPartition()
2551 *
2552 * RETURNS
2553 * Number of the next page.
2554 */
2555static PAGE_NUMBER
2557{
2558 PPARTENTRY PartEntry;
2559 PDISKENTRY DiskEntry;
2560 FORMATMACHINESTATE PreviousFormatState;
2561 PCWSTR DefaultFs;
2562 CHAR LineBuffer[100];
2563
2564 DPRINT("SelectFileSystemPage()\n");
2565
2567 {
2568 /* FIXME: show an error dialog */
2569 return QUIT_PAGE;
2570 }
2571
2572 /* Find or set the active system partition when starting formatting */
2573 if (FormatState == Start)
2574 {
2575 /*
2576 * If we install on a fixed disk, try to find a supported system
2577 * partition on the system. Otherwise if we install on a removable disk
2578 * use the install partition as the system partition.
2579 */
2580 if (InstallPartition->DiskEntry->MediaType == FixedMedia)
2581 {
2583 FALSE,
2586 /* Use the original system partition as the old active partition hint */
2587 PartEntry = PartitionList->SystemPartition;
2588
2591 {
2592 DPRINT1("We are using a different system partition!!!!\n");
2593
2595
2596 {
2597 PPARTENTRY PartEntry; // Shadow variable
2598
2599 PartEntry = PartitionList->SystemPartition;
2600 DiskEntry = PartEntry->DiskEntry;
2601
2602 PartitionDescription(PartEntry, LineBuffer, ARRAYSIZE(LineBuffer));
2603 CONSOLE_SetTextXY(8, 10, LineBuffer);
2604
2605 DiskDescription(DiskEntry, LineBuffer, ARRAYSIZE(LineBuffer));
2607 LineBuffer);
2608
2609
2610 PartEntry = SystemPartition;
2611 DiskEntry = PartEntry->DiskEntry;
2612
2613 PartitionDescription(PartEntry, LineBuffer, ARRAYSIZE(LineBuffer));
2614 CONSOLE_SetTextXY(8, 23, LineBuffer);
2615 }
2616
2617 while (TRUE)
2618 {
2619 CONSOLE_ConInKey(Ir);
2620
2621 if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
2622 {
2623 break;
2624 }
2625 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESC */
2626 {
2627 return SELECT_PARTITION_PAGE;
2628 }
2629 }
2630
2632 CONSOLE_Flush();
2633 }
2634 }
2635 else // if (InstallPartition->DiskEntry->MediaType == RemovableMedia)
2636 {
2638 /* Don't specify any old active partition hint */
2639 PartEntry = NULL;
2640 }
2641
2642 if (!SystemPartition)
2643 {
2644 /* FIXME: improve the error dialog */
2645 //
2646 // Error dialog should say that we cannot find a suitable
2647 // system partition and create one on the system. At this point,
2648 // it may be nice to ask the user whether he wants to continue,
2649 // or use an external drive as the system drive/partition
2650 // (e.g. floppy, USB drive, etc...)
2651 //
2652 PopupError("The ReactOS Setup could not find a supported system partition\n"
2653 "on your system or could not create a new one. Without such partition\n"
2654 "the Setup program cannot install ReactOS.\n"
2655 "Press ENTER to return to the partition selection list.",
2657 Ir, POPUP_WAIT_ENTER);
2658 return SELECT_PARTITION_PAGE;
2659 }
2660
2661 /*
2662 * If the system partition can be created in some
2663 * non-partitioned space, create it now.
2664 */
2666 {
2669 0LL, // SystemPartition->SectorCount.QuadPart,
2670 TRUE);
2672 }
2673
2674 /* Set it as such */
2676 {
2677 DPRINT1("SetActivePartition(0x%p) failed?!\n", SystemPartition);
2678 ASSERT(FALSE);
2679 }
2680
2681 /* Commit all partition changes to all the disks */
2683 {
2684 DPRINT("WritePartitionsToDisk() failed\n");
2686 return QUIT_PAGE;
2687 }
2688
2689 /*
2690 * In all cases, whether or not we are going to perform a formatting,
2691 * we must perform a filesystem check of both the system and the
2692 * installation partitions.
2693 */
2697
2698 /*
2699 * In case we just repair an existing installation, or make
2700 * an unattended setup without formatting, just go to the
2701 * filesystem check step.
2702 */
2703 if (RepairUpdateFlag)
2705
2708 }
2709
2710 // ASSERT(SystemPartition->IsPartitioned);
2711
2712 /* Reset the filesystem list for each partition that is to be formatted */
2714
2715 PreviousFormatState = FormatState;
2716 switch (FormatState)
2717 {
2718 case Start:
2719 {
2720 /*
2721 * We start by formatting the system partition in case it is new
2722 * (it didn't exist before) and is not the same as the installation
2723 * partition. Otherwise we just require a filesystem check on it,
2724 * and start by formatting the installation partition instead.
2725 */
2726
2728
2731 {
2734
2735 // TODO: Should we let the user using a custom file-system,
2736 // or should we always use FAT(32) for it?
2737 // For "compatibility", FAT(32) would be best indeed.
2738
2740 DPRINT1("FormatState: Start --> FormatSystemPartition\n");
2741 }
2742 else
2743 {
2746
2748 {
2749 /* The system partition is separate, so it had better be formatted! */
2752
2753 /* Require a filesystem check on the system partition too */
2755 }
2756
2758 DPRINT1("FormatState: Start --> FormatInstallPartition\n");
2759 }
2760 break;
2761 }
2762
2764 {
2767
2769 DPRINT1("FormatState: FormatSystemPartition --> FormatInstallPartition\n");
2770 break;
2771 }
2772
2775 {
2777 NULL,
2778 &TempPartition))
2779 {
2782
2784 DPRINT1("FormatState: FormatInstallPartition --> FormatOtherPartition\n");
2785 else
2786 DPRINT1("FormatState: FormatOtherPartition --> FormatOtherPartition\n");
2787 }
2788 else
2789 {
2791
2793 DPRINT1("FormatState: FormatInstallPartition --> FormatDone\n");
2794 else
2795 DPRINT1("FormatState: FormatOtherPartition --> FormatDone\n");
2796
2798 }
2799 break;
2800 }
2801
2802 case FormatDone:
2803 {
2804 DPRINT1("FormatState: FormatDone\n");
2806 }
2807
2808 default:
2809 {
2810 DPRINT1("FormatState: Invalid value %ld\n", FormatState);
2811 ASSERT(FALSE);
2812 return QUIT_PAGE;
2813 }
2814 }
2815
2816 PartEntry = TempPartition;
2817 DiskEntry = TempPartition->DiskEntry;
2818
2819 ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0);
2820
2822
2823 if (PartEntry->AutoCreate)
2824 {
2826
2827#if 0
2828 PartitionDescription(PartEntry, LineBuffer, ARRAYSIZE(LineBuffer));
2829 CONSOLE_SetTextXY(8, 10, LineBuffer);
2830#endif
2831
2832 DiskDescription(DiskEntry, LineBuffer, ARRAYSIZE(LineBuffer));
2834 LineBuffer);
2835
2837
2838 PartEntry->AutoCreate = FALSE;
2839 }
2840 else if (PartEntry->New)
2841 {
2842 switch (FormatState)
2843 {
2846 break;
2847
2850 break;
2851
2854 break;
2855
2856 default:
2857 ASSERT(FALSE);
2858 break;
2859 }
2860
2861 DiskDescription(DiskEntry, LineBuffer, ARRAYSIZE(LineBuffer));
2863 LineBuffer);
2864
2866 }
2867 else
2868 {
2870
2871 PartitionDescription(PartEntry, LineBuffer, ARRAYSIZE(LineBuffer));
2872 CONSOLE_SetTextXY(8, 10, LineBuffer);
2873
2874 DiskDescription(DiskEntry, LineBuffer, ARRAYSIZE(LineBuffer));
2876 LineBuffer);
2877 }
2878
2880
2882 {
2884
2885 switch (USetupData.FsType)
2886 {
2887 /* 1 is for BtrFS */
2888 case 1:
2889 DefaultFs = L"BTRFS";
2890 break;
2891
2892 /* If we don't understand input, default to FAT */
2893 default:
2894 DefaultFs = L"FAT";
2895 break;
2896 }
2897 }
2898 else
2899 {
2900 /* By default select the "FAT" file system */
2901 DefaultFs = L"FAT";
2902 }
2903
2904 /* Create the file system list */
2905 // TODO: Display only the FSes compatible with the selected partition!
2907 PartEntry->New ||
2908 PartEntry->FormatState == Unformatted,
2909 DefaultFs);
2910 if (FileSystemList == NULL)
2911 {
2912 /* FIXME: show an error dialog */
2913 return QUIT_PAGE;
2914 }
2915
2917 {
2919 return FORMAT_PARTITION_PAGE;
2920 }
2921
2923
2924 while (TRUE)
2925 {
2926 CONSOLE_ConInKey(Ir);
2927
2928 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2929 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
2930 {
2931 if (ConfirmQuit(Ir))
2932 {
2933 /* Reset the filesystem list */
2935 return QUIT_PAGE;
2936 }
2937
2938 break;
2939 }
2940 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESC */
2941 {
2942 /* Reset the formatter machine state */
2945
2946 /* Reset the filesystem list */
2948
2949 return SELECT_PARTITION_PAGE;
2950 }
2951 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2952 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
2953 {
2955 }
2956 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2957 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
2958 {
2960 }
2961 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
2962 {
2964 {
2966
2967 /*
2968 * Skip formatting this partition. We will also ignore
2969 * filesystem checks on it, unless it is either the system
2970 * or the installation partition.
2971 */
2974 {
2975 PartEntry->NeedsCheck = FALSE;
2976 }
2977
2979 }
2980 else
2981 {
2982 /* Format this partition */
2983 return FORMAT_PARTITION_PAGE;
2984 }
2985 }
2986 }
2987
2988 FormatState = PreviousFormatState;
2989
2991}
2992
2993
2994/*
2995 * Displays the FormatPartitionPage.
2996 *
2997 * Next pages:
2998 * InstallDirectoryPage (At once if IsUnattendedSetup or InstallShortcut)
2999 * SelectPartitionPage (At once)
3000 * QuitPage
3001 *
3002 * SIDEEFFECTS
3003 * Sets InstallPartition->FormatState
3004 * Sets USetupData.DestinationRootPath
3005 *
3006 * RETURNS
3007 * Number of the next page.
3008 */
3009static PAGE_NUMBER
3011{
3013 PPARTENTRY PartEntry;
3014 PDISKENTRY DiskEntry;
3015 PFILE_SYSTEM_ITEM SelectedFileSystem;
3016 WCHAR PathBuffer[MAX_PATH];
3018
3019 DPRINT("FormatPartitionPage()\n");
3020
3022
3023 if (PartitionList == NULL || TempPartition == NULL)
3024 {
3025 /* FIXME: show an error dialog */
3026 return QUIT_PAGE;
3027 }
3028
3029 PartEntry = TempPartition;
3030 DiskEntry = TempPartition->DiskEntry;
3031
3032 ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0);
3033
3034 SelectedFileSystem = FileSystemList->Selected;
3035 ASSERT(SelectedFileSystem && SelectedFileSystem->FileSystem);
3036
3037 while (TRUE)
3038 {
3039 if (!IsUnattendedSetup)
3040 CONSOLE_ConInKey(Ir);
3041
3042 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3043 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
3044 {
3045 if (ConfirmQuit(Ir))
3046 {
3047 /* Reset the filesystem list */
3049 return QUIT_PAGE;
3050 }
3051
3052 break;
3053 }
3054 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN || IsUnattendedSetup) /* ENTER */
3055 {
3056 /*
3057 * Remove the "Press ENTER to continue" message prompt when the ENTER
3058 * key is pressed as the user wants to begin the partition formatting.
3059 */
3062
3063 /* Format the partition */
3064 Status = DoFormat(PartEntry,
3065 SelectedFileSystem->FileSystem,
3066 SelectedFileSystem->QuickFormat);
3068 {
3070
3071 /* Reset the filesystem list */
3073 return QUIT_PAGE;
3074 }
3076 {
3077 /* FIXME: show an error dialog */
3078 // MUIDisplayError(ERROR_FORMATTING_PARTITION, Ir, POPUP_WAIT_ANY_KEY, PathBuffer);
3079
3080 /* Reset the filesystem list */
3082 return QUIT_PAGE;
3083 }
3084 else if (Status == STATUS_NOT_SUPPORTED)
3085 {
3087 sizeof(Buffer),
3088 "Setup is currently unable to format a partition in %S.\n"
3089 "\n"
3090 " \x07 Press ENTER to continue Setup.\n"
3091 " \x07 Press F3 to quit Setup.",
3092 SelectedFileSystem->FileSystem);
3093
3097
3098 while (TRUE)
3099 {
3100 CONSOLE_ConInKey(Ir);
3101
3102 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x00 &&
3103 Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3) /* F3 */
3104 {
3105 if (ConfirmQuit(Ir))
3106 {
3107 /* Reset the filesystem list */
3109 return QUIT_PAGE;
3110 }
3111 else
3112 {
3114 }
3115 }
3116 else if (Ir->Event.KeyEvent.uChar.AsciiChar == VK_RETURN) /* ENTER */
3117 {
3119 }
3120 }
3121 }
3122 else if (!NT_SUCCESS(Status))
3123 {
3125 RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
3126 L"\\Device\\Harddisk%lu\\Partition%lu",
3127 DiskEntry->DiskNumber,
3128 PartEntry->PartitionNumber);
3129
3130 DPRINT1("FormatPartition() failed with status 0x%08lx\n", Status);
3132
3133 /* Reset the filesystem list */
3135 return QUIT_PAGE;
3136 }
3137
3139 }
3140 }
3141
3142 return FORMAT_PARTITION_PAGE;
3143}
3144
3145
3146/*
3147 * Displays the CheckFileSystemPage.
3148 *
3149 * Next pages:
3150 * InstallDirectoryPage (At once)
3151 * QuitPage
3152 *
3153 * SIDEEFFECTS
3154 * Inits or reloads FileSystemList
3155 *
3156 * RETURNS
3157 * Number of the next page.
3158 */
3159static PAGE_NUMBER
3161{
3163 PPARTENTRY PartEntry;
3165
3167
3168 if (PartitionList == NULL)
3169 {
3170 /* FIXME: show an error dialog */
3171 return QUIT_PAGE;
3172 }
3173
3174 if (!GetNextUncheckedPartition(PartitionList, NULL, &PartEntry))
3175 {
3177 }
3178
3179 ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0);
3180
3181 DPRINT1("CheckFileSystemPage -- PartitionType: 0x%02X ; FileSystem: %S\n",
3182 PartEntry->PartitionType, (*PartEntry->FileSystem ? PartEntry->FileSystem : L"n/a"));
3183
3184 /* Check the partition */
3185 Status = DoChkdsk(PartEntry);
3187 {
3188 /*
3189 * Partition checking is not supported with the current filesystem,
3190 * so disable FS checks on it.
3191 */
3192 PartEntry->NeedsCheck = FALSE;
3193
3195 sizeof(Buffer),
3196 "Setup is currently unable to check a partition formatted in %S.\n"
3197 "\n"
3198 " \x07 Press ENTER to continue Setup.\n"
3199 " \x07 Press F3 to quit Setup.",
3200 PartEntry->FileSystem);
3201
3205
3206 while (TRUE)
3207 {
3208 CONSOLE_ConInKey(Ir);
3209
3210 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x00 &&
3211 Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3) /* F3 */
3212 {
3213 if (ConfirmQuit(Ir))
3214 return QUIT_PAGE;
3215 else
3217 }
3218 else if (Ir->Event.KeyEvent.uChar.AsciiChar == VK_RETURN) /* ENTER */
3219 {
3221 }
3222 }
3223 }
3224 else if (!NT_SUCCESS(Status))
3225 {
3226 DPRINT1("ChkdskPartition() failed with status 0x%08lx\n", Status);
3227
3229 sizeof(Buffer),
3230 "ChkDsk detected some disk errors.\n(Status 0x%08lx).\n",
3231 Status);
3232
3235 Ir, POPUP_WAIT_ENTER);
3236 }
3237
3238 PartEntry->NeedsCheck = FALSE;
3240}
3241
3242
3243static BOOLEAN
3245 IN PCWSTR InstallDir)
3246{
3247 UINT i, Length;
3248
3249 Length = wcslen(InstallDir);
3250
3251 // TODO: Add check for 8.3 too.
3252
3253 /* Path must be at least 2 characters long */
3254// if (Length < 2)
3255// return FALSE;
3256
3257 /* Path must start with a backslash */
3258// if (InstallDir[0] != L'\\')
3259// return FALSE;
3260
3261 /* Path must not end with a backslash */
3262 if (InstallDir[Length - 1] == L'\\')
3263 return FALSE;
3264
3265 /* Path must not contain whitespace characters */
3266 for (i = 0; i < Length; i++)
3267 {
3268 if (iswspace(InstallDir[i]))
3269 return FALSE;
3270 }
3271
3272 /* Path component must not end with a dot */
3273 for (i = 0; i < Length; i++)
3274 {
3275 if (InstallDir[i] == L'\\' && i > 0)
3276 {
3277 if (InstallDir[i - 1] == L'.')
3278 return FALSE;
3279 }
3280 }
3281
3282 if (InstallDir[Length - 1] == L'.')
3283 return FALSE;
3284
3285 return TRUE;
3286}
3287
3288
3289/*
3290 * Displays the InstallDirectoryPage.
3291 *
3292 * Next pages:
3293 * PrepareCopyPage
3294 * QuitPage
3295 *
3296 * RETURNS
3297 * Number of the next page.
3298 */
3299static PAGE_NUMBER
3301{
3303 ULONG Length, Pos;
3304 WCHAR c;
3305 WCHAR InstallDir[MAX_PATH];
3306
3307 /* We do not need the filesystem list anymore */
3309
3311 {
3312 /* FIXME: show an error dialog */
3313 return QUIT_PAGE;
3314 }
3315
3316 // if (IsUnattendedSetup)
3317 if (RepairUpdateFlag)
3318 wcscpy(InstallDir, CurrentInstallation->PathComponent); // SystemNtPath
3321 else
3322 wcscpy(InstallDir, L"\\ReactOS");
3323
3324 /*
3325 * Check the validity of the predefined 'InstallDir'. If we are either
3326 * in unattended setup or in update/repair mode, and the installation path
3327 * is valid, just perform the installation. Otherwise (either in the case
3328 * of an invalid path, or we are in regular setup), display the UI and allow
3329 * the user to specify a new installation path.
3330 */
3331 if ((RepairUpdateFlag || IsUnattendedSetup) && IsValidPath(InstallDir))
3332 {
3334 if (!NT_SUCCESS(Status))
3335 {
3336 DPRINT1("InitDestinationPaths() failed. Status code: 0x%lx", Status);
3338 return QUIT_PAGE;
3339 }
3340
3341 /*
3342 * Check whether the user attempts to install ReactOS within the
3343 * installation source directory, or in a subdirectory thereof.
3344 * If so, fail with an error.
3345 */
3347 {
3350 }
3351
3352 return PREPARE_COPY_PAGE;
3353 }
3354
3355 Length = wcslen(InstallDir);
3356 Pos = Length;
3357
3359 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
3360 CONSOLE_SetCursorXY(8 + Pos, 11);
3362
3363 while (TRUE)
3364 {
3365 CONSOLE_ConInKey(Ir);
3366
3367 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3368 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
3369 {
3371
3372 if (ConfirmQuit(Ir))
3373 return QUIT_PAGE;
3374
3376 break;
3377 }
3378 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3379 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DELETE)) /* DEL */
3380 {
3381 if (Pos < Length)
3382 {
3383 memmove(&InstallDir[Pos],
3384 &InstallDir[Pos + 1],
3385 (Length - Pos - 1) * sizeof(WCHAR));
3386 InstallDir[Length - 1] = UNICODE_NULL;
3387
3388 Length--;
3389 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
3390 CONSOLE_SetCursorXY(8 + Pos, 11);
3391 }
3392 }
3393 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3394 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_HOME)) /* HOME */
3395 {
3396 Pos = 0;
3397 CONSOLE_SetCursorXY(8 + Pos, 11);
3398 }
3399 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3400 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_END)) /* END */
3401 {
3402 Pos = Length;
3403 CONSOLE_SetCursorXY(8 + Pos, 11);
3404 }
3405 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3406 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_LEFT)) /* LEFT */
3407 {
3408 if (Pos > 0)
3409 {
3410 Pos--;
3411 CONSOLE_SetCursorXY(8 + Pos, 11);
3412 }
3413 }
3414 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3415 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RIGHT)) /* RIGHT */
3416 {
3417 if (Pos < Length)
3418 {
3419 Pos++;
3420 CONSOLE_SetCursorXY(8 + Pos, 11);
3421 }
3422 }
3423 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
3424 {
3426
3427 /*
3428 * Check for the validity of the installation directory and pop up
3429 * an error if it is not the case. Then the user can fix its input.
3430 */
3431 if (!IsValidPath(InstallDir))
3432 {
3435 }
3436
3438 if (!NT_SUCCESS(Status))
3439 {
3440 DPRINT1("InitDestinationPaths() failed. Status code: 0x%lx", Status);
3442 return QUIT_PAGE;
3443 }
3444
3445 /*
3446 * Check whether the user attempts to install ReactOS within the
3447 * installation source directory, or in a subdirectory thereof.
3448 * If so, fail with an error.
3449 */
3451 {
3454 }
3455
3456 return PREPARE_COPY_PAGE;
3457 }
3458 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x08) /* BACKSPACE */
3459 {
3460 if (Pos > 0)
3461 {
3462 if (Pos < Length)
3463 memmove(&InstallDir[Pos - 1],
3464 &InstallDir[Pos],
3465 (Length - Pos) * sizeof(WCHAR));
3466 InstallDir[Length - 1] = UNICODE_NULL;
3467
3468 Pos--;
3469 Length--;
3470 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
3471 CONSOLE_SetCursorXY(8 + Pos, 11);
3472 }
3473 }
3474 else if (isprint(Ir->Event.KeyEvent.uChar.AsciiChar))
3475 {
3476 if (Length < 50)
3477 {
3479 if (iswalpha(c) || iswdigit(c) || c == '.' || c == '\\' || c == '-' || c == '_')
3480 {
3481 if (Pos < Length)
3482 memmove(&InstallDir[Pos + 1],
3483 &InstallDir[Pos],
3484 (Length - Pos) * sizeof(WCHAR));
3485 InstallDir[Length + 1] = UNICODE_NULL;
3486 InstallDir[Pos] = c;
3487
3488 Pos++;
3489 Length++;
3490 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
3491 CONSOLE_SetCursorXY(8 + Pos, 11);
3492 }
3493 }
3494 }
3495 }
3496
3498}
3499
3500
3501// PSETUP_ERROR_ROUTINE
3502static VOID
3503__cdecl
3505 IN PUSETUP_DATA pSetupData,
3506 ...)
3507{
3508 INPUT_RECORD Ir;
3509 va_list arg_ptr;
3510
3511 va_start(arg_ptr, pSetupData);
3512
3513 if (pSetupData->LastErrorNumber >= ERROR_SUCCESS &&
3514 pSetupData->LastErrorNumber < ERROR_LAST_ERROR_CODE)
3515 {
3516 // Note: the "POPUP_WAIT_ENTER" actually depends on the LastErrorNumber...
3517 MUIDisplayErrorV(pSetupData->LastErrorNumber, &Ir, POPUP_WAIT_ENTER, arg_ptr);
3518 }
3519
3520 va_end(arg_ptr);
3521}
3522
3523/*
3524 * Displays the PrepareCopyPage.
3525 *
3526 * Next pages:
3527 * FileCopyPage(At once)
3528 * QuitPage
3529 *
3530 * SIDEEFFECTS
3531 * Calls PrepareFileCopy
3532 *
3533 * RETURNS
3534 * Number of the next page.
3535 */
3536static PAGE_NUMBER
3538{
3539 // ERROR_NUMBER ErrorNumber;
3541
3543
3544 /* ErrorNumber = */ Success = PrepareFileCopy(&USetupData, NULL);
3545 if (/*ErrorNumber != ERROR_SUCCESS*/ !Success)
3546 {
3547 // MUIDisplayError(ErrorNumber, Ir, POPUP_WAIT_ENTER);
3548 return QUIT_PAGE;
3549 }
3550
3551 return FILE_COPY_PAGE;
3552}
3553
3554typedef struct _COPYCONTEXT
3555{
3561
3562static VOID
3565{
3567
3568 /* Get the memory information from the system */
3570 &PerfInfo,
3571 sizeof(PerfInfo),
3572 NULL);
3573
3574 /* Check if this is initial setup */
3575 if (First)
3576 {
3577 /* Set maximum limits to be total RAM pages */
3578 ProgressSetStepCount(CopyContext->MemoryBars[0], PerfInfo.CommitLimit);
3579 ProgressSetStepCount(CopyContext->MemoryBars[1], PerfInfo.CommitLimit);
3580 ProgressSetStepCount(CopyContext->MemoryBars[2], PerfInfo.CommitLimit);
3581 }
3582
3583 /* Set current values */
3584 ProgressSetStep(CopyContext->MemoryBars[0], PerfInfo.PagedPoolPages + PerfInfo.NonPagedPoolPages);
3585 ProgressSetStep(CopyContext->MemoryBars[1], PerfInfo.ResidentSystemCachePage);
3586 ProgressSetStep(CopyContext->MemoryBars[2], PerfInfo.AvailablePages);
3587}
3588
3589static UINT
3593 UINT_PTR Param1,
3594 UINT_PTR Param2)
3595{
3596 PCOPYCONTEXT CopyContext = (PCOPYCONTEXT)Context;
3597 PFILEPATHS_W FilePathInfo;
3598 PCWSTR SrcFileName, DstFileName;
3599
3600 switch (Notification)
3601 {
3603 {
3604 CopyContext->TotalOperations = (ULONG)Param2;
3605 CopyContext->CompletedOperations = 0;
3606 ProgressSetStepCount(CopyContext->ProgressBar,
3607 CopyContext->TotalOperations);
3608 SetupUpdateMemoryInfo(CopyContext, TRUE);
3609 break;
3610 }
3611
3615 {
3616 FilePathInfo = (PFILEPATHS_W)Param1;
3617
3619 {
3620 /* Display delete message */
3621 ASSERT(Param2 == FILEOP_DELETE);
3622
3623 DstFileName = wcsrchr(FilePathInfo->Target, L'\\');
3624 if (DstFileName) ++DstFileName;
3625 else DstFileName = FilePathInfo->Target;
3626
3628 DstFileName);
3629 }
3631 {
3632 /* Display move/rename message */
3633 ASSERT(Param2 == FILEOP_RENAME);
3634
3635 SrcFileName = wcsrchr(FilePathInfo->Source, L'\\');
3636 if (SrcFileName) ++SrcFileName;
3637 else SrcFileName = FilePathInfo->Source;
3638
3639 DstFileName = wcsrchr(FilePathInfo->Target, L'\\');
3640 if (DstFileName) ++DstFileName;
3641 else DstFileName = FilePathInfo->Target;
3642
3643 if (!wcsicmp(SrcFileName, DstFileName))
3644 Param2 = STRING_MOVING;
3645 else
3646 Param2 = STRING_RENAMING;
3647
3649 SrcFileName, DstFileName);
3650 }
3652 {
3653 static PCSTR s_pszCopying = NULL; /* Cached for speed */
3654
3655 /* Display copy message */
3656 ASSERT(Param2 == FILEOP_COPY);
3657
3658 /* NOTE: When extracting from CABs the Source is the CAB name */
3659 DstFileName = wcsrchr(FilePathInfo->Target, L'\\');
3660 if (DstFileName) ++DstFileName;
3661 else DstFileName = FilePathInfo->Target;
3662
3663 if (!s_pszCopying)
3664 s_pszCopying = MUIGetString(STRING_COPYING);
3665 CONSOLE_SetStatusText(s_pszCopying, DstFileName);
3666#ifdef __REACTOS__ /* HACK */
3667 DoWatchDestFileName(DstFileName);
3668#endif
3669 }
3670
3671 SetupUpdateMemoryInfo(CopyContext, FALSE);
3672 break;
3673 }
3674
3676 {
3677 FilePathInfo = (PFILEPATHS_W)Param1;
3678
3679 DPRINT1("An error happened while trying to copy file '%S' (error 0x%08lx), skipping it...\n",
3680 FilePathInfo->Target, FilePathInfo->Win32Error);
3681 return FILEOP_SKIP;
3682 }
3683
3687 {
3688 CopyContext->CompletedOperations++;
3689
3690 /* SYSREG checkpoint */
3691 if (CopyContext->TotalOperations >> 1 == CopyContext->CompletedOperations)
3692 DPRINT1("CHECKPOINT:HALF_COPIED\n");
3693
3694 ProgressNextStep(CopyContext->ProgressBar);
3695 SetupUpdateMemoryInfo(CopyContext, FALSE);
3696 break;
3697 }
3698 }
3699
3700 return FILEOP_DOIT;
3701}
3702
3703
3704/*
3705 * Displays the FileCopyPage.
3706 *
3707 * Next pages:
3708 * RegistryPage(At once)
3709 *
3710 * SIDEEFFECTS
3711 * Calls DoFileCopy
3712 *
3713 * RETURNS
3714 * Number of the next page.
3715 */
3716static PAGE_NUMBER
3718{
3719 COPYCONTEXT CopyContext;
3720 UINT MemBarWidth;
3721
3723
3724 /* Create context for the copy process */
3725 CopyContext.TotalOperations = 0;
3726 CopyContext.CompletedOperations = 0;
3727
3728 /* Create the progress bar as well */
3729 CopyContext.ProgressBar = CreateProgressBar(13,
3730 26,
3731 xScreen - 13,
3732 yScreen - 20,
3733 10,
3734 24,
3735 TRUE,
3737
3738 // fit memory bars to screen width, distribute them uniform
3739 MemBarWidth = (xScreen - 26) / 5;
3740 MemBarWidth -= MemBarWidth % 2; // make even
3741 /* ATTENTION: The following progress bars are debug stuff, which should not be translated!! */
3742 /* Create the paged pool progress bar */
3743 CopyContext.MemoryBars[0] = CreateProgressBar(13,
3744 40,
3745 13 + MemBarWidth,
3746 43,
3747 13,
3748 44,
3749 FALSE,
3750 "Kernel Pool");
3751
3752 /* Create the non paged pool progress bar */
3753 CopyContext.MemoryBars[1] = CreateProgressBar((xScreen / 2)- (MemBarWidth / 2),
3754 40,
3755 (xScreen / 2) + (MemBarWidth / 2),
3756 43,
3757 (xScreen / 2)- (MemBarWidth / 2),
3758 44,
3759 FALSE,
3760 "Kernel Cache");
3761
3762 /* Create the global memory progress bar */
3763 CopyContext.MemoryBars[2] = CreateProgressBar(xScreen - 13 - MemBarWidth,
3764 40,
3765 xScreen - 13,
3766 43,
3767 xScreen - 13 - MemBarWidth,
3768 44,
3769 FALSE,
3770 "Free Memory");
3771
3772 /* Do the file copying */
3773 DoFileCopy(&USetupData, FileCopyCallback, &CopyContext);
3774
3775 /* If we get here, we're done, so cleanup the progress bar */
3776 DestroyProgressBar(CopyContext.ProgressBar);
3777 DestroyProgressBar(CopyContext.MemoryBars[0]);
3778 DestroyProgressBar(CopyContext.MemoryBars[1]);
3779 DestroyProgressBar(CopyContext.MemoryBars[2]);
3780
3781 /* Create the $winnt$.inf file */
3783
3784 /* Go display the next page */
3785 return REGISTRY_PAGE;
3786}
3787
3788
3789static VOID
3790__cdecl
3792{
3793 /* WARNING: Please keep this lookup table in sync with the resources! */
3794 static const UINT StringIDs[] =
3795 {
3796 STRING_DONE, /* Success */
3797 STRING_REGHIVEUPDATE, /* RegHiveUpdate */
3798 STRING_IMPORTFILE, /* ImportRegHive */
3799 STRING_DISPLAYSETTINGSUPDATE, /* DisplaySettingsUpdate */
3800 STRING_LOCALESETTINGSUPDATE, /* LocaleSettingsUpdate */
3801 STRING_ADDKBLAYOUTS, /* KeybLayouts */
3802 STRING_KEYBOARDSETTINGSUPDATE, /* KeybSettingsUpdate */
3803 STRING_CODEPAGEINFOUPDATE, /* CodePageInfoUpdate */
3804 };
3805
3806 va_list args;
3807
3808 if (RegStatus < ARRAYSIZE(StringIDs))
3809 {
3810 va_start(args, RegStatus);
3811 CONSOLE_SetStatusTextV(MUIGetString(StringIDs[RegStatus]), args);
3812 va_end(args);
3813 }
3814 else
3815 {
3816 CONSOLE_SetStatusText("Unknown status %d", RegStatus);
3817 }
3818}
3819
3820/*
3821 * Displays the RegistryPage.
3822 *
3823 * Next pages:
3824 * SuccessPage (if RepairUpdate)
3825 * BootLoaderPage (default)
3826 * QuitPage
3827 *
3828 * SIDEEFFECTS
3829 * Calls UpdateRegistry
3830 *
3831 * RETURNS
3832 * Number of the next page.
3833 */
3834static PAGE_NUMBER
3836{
3837 ULONG Error;
3838
3840
3847 &s_SubstSettings);
3848 if (Error != ERROR_SUCCESS)
3849 {
3851 return QUIT_PAGE;
3852 }
3853 else
3854 {
3856 return BOOT_LOADER_PAGE;
3857 }
3858}
3859
3860
3861/*
3862 * Displays the BootLoaderPage.
3863 *
3864 * Next pages:
3865 * SuccessPage (if RepairUpdate)
3866 * BootLoaderHarddiskMbrPage
3867 * BootLoaderHarddiskVbrPage
3868 * BootLoaderFloppyPage
3869 * SuccessPage
3870 * QuitPage
3871 *
3872 * SIDEEFFECTS
3873 * Calls RegInitializeRegistry
3874 * Calls ImportRegistryFile
3875 * Calls SetDefaultPagefile
3876 * Calls SetMountedDeviceValues
3877 *
3878 * RETURNS
3879 * Number of the next page.
3880 */
3881static PAGE_NUMBER
3883{
3884 USHORT Line = 12;
3885 WCHAR PathBuffer[MAX_PATH];
3886
3888
3889 /* We must have a supported system partition by now */
3891
3893 RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
3894 L"\\Device\\Harddisk%lu\\Partition%lu\\",
3895 SystemPartition->DiskEntry->DiskNumber,
3898 DPRINT1("SystemRootPath: %wZ\n", &USetupData.SystemRootPath);
3899
3900 /* For unattended setup, skip MBR installation or install on floppy if needed */
3902 {
3903 if ((USetupData.MBRInstallType == 0) ||
3905 {
3906 goto Quit;
3907 }
3908 }
3909
3910 /*
3911 * We may install an MBR or VBR, but before that, check whether
3912 * we need to actually install the VBR on floppy/removable media
3913 * if the system partition is not recognized.
3914 */
3915 if ((SystemPartition->DiskEntry->DiskStyle != PARTITION_STYLE_MBR) ||
3917 {
3919 goto Quit;
3920 }
3921
3922 /* Is it an unattended install on hdd? */
3924 {
3925 if ((USetupData.MBRInstallType == 2) ||
3927 {
3928 goto Quit;
3929 }
3930 }
3931
3933 CONSOLE_InvertTextXY(8, Line, 60, 1);
3934
3935 while (TRUE)
3936 {
3937 CONSOLE_ConInKey(Ir);
3938
3939 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3940 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
3941 {
3942 CONSOLE_NormalTextXY(8, Line, 60, 1);
3943
3944 Line++;
3945 if (Line < 12)
3946 Line = 15;
3947
3948 if (Line > 15)
3949 Line = 12;
3950
3951 CONSOLE_InvertTextXY(8, Line, 60, 1);
3952 }
3953 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3954 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
3955 {
3956 CONSOLE_NormalTextXY(8, Line, 60, 1);
3957
3958 Line--;
3959 if (Line < 12)
3960 Line = 15;
3961
3962 if (Line > 15)
3963 Line = 12;
3964
3965 CONSOLE_InvertTextXY(8, Line, 60, 1);
3966 }
3967 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3968 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_HOME)) /* HOME */
3969 {
3970 CONSOLE_NormalTextXY(8, Line, 60, 1);
3971
3972 Line = 12;
3973
3974 CONSOLE_InvertTextXY(8, Line, 60, 1);
3975 }
3976 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3977 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_END)) /* END */
3978 {
3979 CONSOLE_NormalTextXY(8, Line, 60, 1);
3980
3981 Line = 15;
3982
3983 CONSOLE_InvertTextXY(8, Line, 60, 1);
3984 }
3985 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3986 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
3987 {
3988 if (ConfirmQuit(Ir))
3989 return QUIT_PAGE;
3990
3991 break;
3992 }
3993 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
3994 {
3995 if (Line == 12)
3996 {
3997 /* Install on both MBR and VBR */
3999 break;
4000 }
4001 else if (Line == 13)
4002 {
4003 /* Install on VBR only */
4005 break;
4006 }
4007 else if (Line == 14)
4008 {
4009 /* Install on floppy */
4011 break;
4012 }
4013 else if (Line == 15)
4014 {
4015 /* Skip MBR installation */
4017 break;
4018 }
4019
4020 return BOOT_LOADER_PAGE;
4021 }
4022 }
4023
4024Quit:
4025 switch (USetupData.MBRInstallType)
4026 {
4027 /* Skip MBR installation */
4028 case 0:
4029 return SUCCESS_PAGE;
4030
4031 /* Install on floppy */
4032 case 1:
4034
4035 /* Install on both MBR and VBR or VBR only */
4036 case 2:
4037 case 3:
4039 }
4040
4041 return BOOT_LOADER_PAGE;
4042}
4043
4044
4045/*
4046 * Displays the BootLoaderFloppyPage.
4047 *
4048 * Next pages:
4049 * SuccessPage (At once)
4050 * QuitPage
4051 *
4052 * SIDEEFFECTS
4053 * Calls InstallFatBootcodeToFloppy()
4054 *
4055 * RETURNS
4056 * Number of the next page.
4057 */
4058static PAGE_NUMBER
4060{
4062
4064
4065// CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
4066
4067 while (TRUE)
4068 {
4069 CONSOLE_ConInKey(Ir);
4070
4071 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
4072 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
4073 {
4074 if (ConfirmQuit(Ir))
4075 return QUIT_PAGE;
4076
4077 break;
4078 }
4079 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
4080 {
4083 if (!NT_SUCCESS(Status))
4084 {
4087
4088 /* TODO: Print error message */
4090 }
4091
4092 return SUCCESS_PAGE;
4093 }
4094 }
4095
4097}
4098
4099
4100/*
4101 * Displays the BootLoaderInstallationPage.
4102 *
4103 * Next pages:
4104 * SuccessPage (At once)
4105 * QuitPage
4106 *
4107 * SIDEEFFECTS
4108 * Calls InstallVBRToPartition() if VBR installation is chosen.
4109 * Otherwise both InstallVBRToPartition() and InstallMbrBootCodeToDisk()
4110 * are called if both MBR and VBR installation is chosen.
4111 *
4112 * RETURNS
4113 * Number of the next page.
4114 */
4115static PAGE_NUMBER
4117{
4119 WCHAR DestinationDevicePathBuffer[MAX_PATH];
4120
4122
4123 if (USetupData.MBRInstallType == 2)
4124 {
4125 /* Step 1: Write the VBR */
4130 if (!NT_SUCCESS(Status))
4131 {
4134 return QUIT_PAGE;
4135 }
4136
4137 /* Step 2: Write the MBR if the disk containing the system partition is not a super-floppy */
4139 {
4140 RtlStringCchPrintfW(DestinationDevicePathBuffer, ARRAYSIZE(DestinationDevicePathBuffer),
4141 L"\\Device\\Harddisk%d\\Partition0",
4142 SystemPartition->DiskEntry->DiskNumber);
4145 DestinationDevicePathBuffer);
4146 if (!NT_SUCCESS(Status))
4147 {
4148 DPRINT1("InstallMbrBootCodeToDisk() failed (Status %lx)\n", Status);
4150 return QUIT_PAGE;
4151 }
4152 }
4153 }
4154 else
4155 {
4160 if (!NT_SUCCESS(Status))
4161 {
4164 return QUIT_PAGE;
4165 }
4166 }
4167
4168 return SUCCESS_PAGE;
4169}
4170
4171
4194static
4198 IN BOOLEAN AlwaysUpdate,
4199 OUT PSTR Buffer,
4200 IN SIZE_T cchBufferSize)
4201{
4202 ULONG OldProgress = Bar->Progress;
4203
4204 if (Bar->StepCount == 0)
4205 {
4206 Bar->Progress = 0;
4207 }
4208 else
4209 {
4210 Bar->Progress = Bar->StepCount - Bar->CurrentStep;
4211 }
4212
4213 /* Build the progress string if it has changed */
4214 if (Bar->ProgressFormatText &&
4215 (AlwaysUpdate || (Bar->Progress != OldProgress)))
4216 {
4217 RtlStringCchPrintfA(Buffer, cchBufferSize,
4218 Bar->ProgressFormatText, Bar->Progress / max(1, Bar->Width) + 1);
4219
4220 return TRUE;
4221 }
4222
4223 return FALSE;
4224}
4225
4242static VOID
4244 IN PINPUT_RECORD Ir,
4245 IN LONG TimeOut)
4246{
4248 ULONG StartTime, BarWidth, TimerDiv;
4249 LONG TimeElapsed;
4250 LONG TimerValue, OldTimerValue;
4252 PPROGRESSBAR ProgressBar;
4253 BOOLEAN RefreshProgress = TRUE;
4254
4255 /* Bail out if the timeout is already zero */
4256 if (TimeOut <= 0)
4257 return;
4258
4259 /* Create the timeout progress bar and set it up */
4260 ProgressBar = CreateProgressBarEx(13,
4261 26,
4262 xScreen - 13,
4263 yScreen - 20,
4264 10,
4265 24,
4266 TRUE,
4268 0,
4269 NULL,
4272
4273 BarWidth = max(1, ProgressBar->Width);
4274 TimerValue = TimeOut * BarWidth;
4275 ProgressSetStepCount(ProgressBar, TimerValue);
4276
4278 CONSOLE_Flush();
4279
4280 TimerDiv = 1000 / BarWidth;
4281 TimerDiv = max(1, TimerDiv);
4282 OldTimerValue = TimerValue;
4283 while (TRUE)
4284 {
4285 /* Decrease the timer */
4286
4287 /*
4288 * Compute how much time the previous operations took.
4289 * This allows us in particular to take account for any time
4290 * elapsed if something slowed down.
4291 */
4292 TimeElapsed = NtGetTickCount() - StartTime;
4293 if (TimeElapsed >= TimerDiv)
4294 {
4295 /* Increase StartTime by steps of 1 / ProgressBar->Width seconds */
4296 TimeElapsed /= TimerDiv;
4297 StartTime += (TimerDiv * TimeElapsed);
4298
4299 if (TimeElapsed <= TimerValue)
4300 TimerValue -= TimeElapsed;
4301 else
4302 TimerValue = 0;
4303
4304 RefreshProgress = TRUE;
4305 }
4306
4307 if (RefreshProgress)
4308 {
4309 ProgressSetStep(ProgressBar, OldTimerValue - TimerValue);
4310 RefreshProgress = FALSE;
4311 }
4312
4313 /* Stop when the timer reaches zero */
4314 if (TimerValue <= 0)
4315 break;
4316
4317 /* Check for user key presses */
4318
4319 /*
4320 * If the timer is used, use a passive wait of maximum 1 second
4321 * while monitoring for incoming console input events, so that
4322 * we are still able to display the timing count.
4323 */
4324
4325 /* Wait a maximum of 1 second for input events */
4326 TimeElapsed = NtGetTickCount() - StartTime;
4327 if (TimeElapsed < TimerDiv)
4328 {
4329 /* Convert the time to NT format */
4330 Timeout.QuadPart = (TimerDiv - TimeElapsed) * -10000LL;
4332 }
4333 else
4334 {
4336 }
4337
4338 /* Check whether the input event has been signaled, or a timeout happened */
4339 if (Status == STATUS_TIMEOUT)
4340 {
4341 continue;
4342 }
4343 if (Status != STATUS_WAIT_0)
4344 {
4345 /* An error happened, bail out */
4346 DPRINT1("NtWaitForSingleObject() failed, Status 0x%08lx\n", Status);
4347 break;
4348 }
4349
4350 /* Check for an ENTER key press */
4351 while (CONSOLE_ConInKeyPeek(Ir))
4352 {
4353 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
4354 {
4355 /* Found it, stop waiting */
4356 goto Exit;
4357 }
4358 }
4359 }
4360
4361Exit:
4362 /* Destroy the progress bar and quit */
4363 DestroyProgressBar(ProgressBar);
4364}
4365
4366
4367/*
4368 * Displays the QuitPage.
4369 *
4370 * Next pages:
4371 * FlushPage (At once)
4372 *
4373 * SIDEEFFECTS
4374 * Destroy the Lists
4375 *
4376 * RETURNS
4377 * Number of the next page.
4378 */
4379static PAGE_NUMBER
4381{
4383
4384 /* Destroy the NTOS installations list */
4385 if (NtOsInstallsList != NULL)
4386 {
4389 }
4390
4391 /* Destroy the partition list */
4392 if (PartitionList != NULL)
4393 {
4396 }
4397
4398 /* Reset the formatter machine state */
4401
4402 /* Destroy the filesystem list */
4404
4406
4407 /* Wait for maximum 15 seconds or an ENTER key before quitting */
4408 ProgressCountdown(Ir, 15);
4409 return FLUSH_PAGE;
4410}
4411
4412
4413/*
4414 * Displays the SuccessPage.
4415 *
4416 * Next pages:
4417 * FlushPage (At once)
4418 *
4419 * SIDEEFFECTS
4420 * Destroy the Lists
4421 *
4422 * RETURNS
4423 * Number of the next page.
4424 */
4425static PAGE_NUMBER
4427{
4429
4431 return FLUSH_PAGE;
4432
4433 /* Wait for maximum 15 seconds or an ENTER key before quitting */
4434 ProgressCountdown(Ir, 15);
4435 return FLUSH_PAGE;
4436}
4437
4438
4439/*
4440 * Displays the FlushPage.
4441 *
4442 * Next pages:
4443 * RebootPage (At once)
4444 *
4445 * RETURNS
4446 * Number of the next page.
4447 */
4448static PAGE_NUMBER
4450{
4452 return REBOOT_PAGE;
4453}
4454
4455
4456/*
4457 * The start routine and page management
4458 */
4461{
4463 INPUT_RECORD Ir;
4465 BOOLEAN Old;
4466
4468
4469 /* Tell the Cm this is a setup boot, and it has to behave accordingly */
4471 if (!NT_SUCCESS(Status))
4472 DPRINT1("NtInitializeRegistry() failed (Status 0x%08lx)\n", Status);
4473
4474 /* Initialize the user-mode PnP manager */
4476 if (!NT_SUCCESS(Status))
4477 {
4478 // PrintString(??);
4479 DPRINT1("The user-mode PnP manager could not initialize (Status 0x%08lx), expect unavailable devices!\n", Status);
4480 }
4481
4482 if (!CONSOLE_Init())
4483 {
4487
4488 /* We failed to initialize the video, just quit the installer */
4490 }
4491
4492 /* Initialize Setup, phase 0 */
4495
4496 /* Hide the cursor and clear the screen and keyboard buffer */
4499 CONSOLE_Flush();
4500
4501 /* Global Initialization page */
4502 Page = SetupStartPage(&Ir);
4503
4504 while (Page != REBOOT_PAGE && Page != RECOVERY_PAGE)
4505 {
4507 CONSOLE_Flush();
4508
4509 // CONSOLE_SetUnderlinedTextXY(4, 3, " ReactOS " KERNEL_VERSION_STR " Setup ");
4510
4511 switch (Page)
4512 {
4513 /* Language page */
4514 case LANGUAGE_PAGE:
4515 Page = LanguagePage(&Ir);
4516 break;
4517
4518 /* Welcome page */
4519 case WELCOME_PAGE:
4520 Page = WelcomePage(&Ir);
4521 break;
4522
4523 /* License page */
4524 case LICENSE_PAGE:
4525 Page = LicensePage(&Ir);
4526 break;
4527
4528 /* Install pages */
4529 case INSTALL_INTRO_PAGE:
4530 Page = InstallIntroPage(&Ir);
4531 break;
4532
4533#if 0
4534 case SCSI_CONTROLLER_PAGE:
4535 Page = ScsiControllerPage(&Ir);
4536 break;
4537
4538 case OEM_DRIVER_PAGE:
4539 Page = OemDriverPage(&Ir);
4540 break;
4541#endif
4542
4544 Page = DeviceSettingsPage(&Ir);
4545 break;
4546
4549 break;
4550
4553 break;
4554
4557 break;
4558
4560 Page = LayoutSettingsPage(&Ir);
4561 break;
4562
4563 /* Partitioning pages */
4566 break;
4567
4570 break;
4571
4574 break;
4575
4578 break;
4579
4582 break;
4583
4586 break;
4587
4588 /* Filesystem partition operations pages */
4591 break;
4592
4595 break;
4596
4599 break;
4600
4601 /* Installation pages */
4604 break;
4605
4606 case PREPARE_COPY_PAGE:
4607 Page = PrepareCopyPage(&Ir);
4608 break;
4609
4610 case FILE_COPY_PAGE:
4611 Page = FileCopyPage(&Ir);
4612 break;
4613
4614 case REGISTRY_PAGE:
4615 Page = RegistryPage(&Ir);
4616 break;
4617
4618 /* Bootloader installation pages */
4619 case BOOT_LOADER_PAGE:
4620 Page = BootLoaderPage(&Ir);
4621 break;
4622
4625 break;
4626
4629 break;
4630
4631 /* Repair pages */
4632 case REPAIR_INTRO_PAGE:
4633 Page = RepairIntroPage(&Ir);
4634 break;
4635
4637 Page = UpgradeRepairPage(&Ir);
4638 break;
4639
4640 case SUCCESS_PAGE:
4641 Page = SuccessPage(&Ir);
4642 break;
4643
4644 case FLUSH_PAGE:
4645