ReactOS 0.4.15-dev-7157-gb7dcc10
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 */
77static enum {
78 PartTypeData, // On MBR-disks, primary or logical partition
79 PartTypeExtended // MBR-disk container
81
82/* List of supported file systems for the partition to be formatted */
84
85/* Machine state for the formatter */
88
89/*****************************************************/
90
93
94#ifdef __REACTOS__ /* HACK */
95
96/* FONT SUBSTITUTION WORKAROUND *************************************************/
97
98/* For font file check */
99FONTSUBSTSETTINGS s_SubstSettings = { FALSE };
100
101static void
102DoWatchDestFileName(LPCWSTR FileName)
103{
104 if (FileName[0] == 'm' || FileName[0] == 'M')
105 {
106 if (wcsicmp(FileName, L"mingliu.ttc") == 0)
107 {
108 DPRINT("mingliu.ttc found\n");
109 s_SubstSettings.bFoundFontMINGLIU = TRUE;
110 }
111 else if (wcsicmp(FileName, L"msgothic.ttc") == 0)
112 {
113 DPRINT("msgothic.ttc found\n");
114 s_SubstSettings.bFoundFontMSGOTHIC = TRUE;
115 }
116 else if (wcsicmp(FileName, L"msmincho.ttc") == 0)
117 {
118 DPRINT("msmincho.ttc found\n");
119 s_SubstSettings.bFoundFontMSMINCHO = TRUE;
120 }
121 else if (wcsicmp(FileName, L"mssong.ttf") == 0)
122 {
123 DPRINT("mssong.ttf found\n");
124 s_SubstSettings.bFoundFontMSSONG = TRUE;
125 }
126 }
127 else
128 {
129 if (wcsicmp(FileName, L"simsun.ttc") == 0)
130 {
131 DPRINT("simsun.ttc found\n");
132 s_SubstSettings.bFoundFontSIMSUN = TRUE;
133 }
134 else if (wcsicmp(FileName, L"gulim.ttc") == 0)
135 {
136 DPRINT("gulim.ttc found\n");
137 s_SubstSettings.bFoundFontGULIM = TRUE;
138 }
139 else if (wcsicmp(FileName, L"batang.ttc") == 0)
140 {
141 DPRINT("batang.ttc found\n");
142 s_SubstSettings.bFoundFontBATANG = TRUE;
143 }
144 }
145}
146#endif /* HACK */
147
148/* FUNCTIONS ****************************************************************/
149
150static VOID
152{
153 CHAR buffer[512];
154 va_list ap;
157
158 va_start(ap, fmt);
160 va_end(ap);
161
166}
167
168
169static VOID
171 IN SHORT yTop,
172 IN SHORT Width,
174{
175 COORD coPos;
176 DWORD Written;
177
178 /* Draw upper left corner */
179 coPos.X = xLeft;
180 coPos.Y = yTop;
182 CharUpperLeftCorner, // '+',
183 1,
184 coPos,
185 &Written);
186
187 /* Draw upper edge */
188 coPos.X = xLeft + 1;
189 coPos.Y = yTop;
191 CharHorizontalLine, // '-',
192 Width - 2,
193 coPos,
194 &Written);
195
196 /* Draw upper right corner */
197 coPos.X = xLeft + Width - 1;
198 coPos.Y = yTop;
200 CharUpperRightCorner, // '+',
201 1,
202 coPos,
203 &Written);
204
205 /* Draw right edge, inner space and left edge */
206 for (coPos.Y = yTop + 1; coPos.Y < yTop + Height - 1; coPos.Y++)
207 {
208 coPos.X = xLeft;
210 CharVerticalLine, // '|',
211 1,
212 coPos,
213 &Written);
214
215 coPos.X = xLeft + 1;
217 ' ',
218 Width - 2,
219 coPos,
220 &Written);
221
222 coPos.X = xLeft + Width - 1;
224 CharVerticalLine, // '|',
225 1,
226 coPos,
227 &Written);
228 }
229
230 /* Draw lower left corner */
231 coPos.X = xLeft;
232 coPos.Y = yTop + Height - 1;
234 CharLowerLeftCorner, // '+',
235 1,
236 coPos,
237 &Written);
238
239 /* Draw lower edge */
240 coPos.X = xLeft + 1;
241 coPos.Y = yTop + Height - 1;
243 CharHorizontalLine, // '-',
244 Width - 2,
245 coPos,
246 &Written);
247
248 /* Draw lower right corner */
249 coPos.X = xLeft + Width - 1;
250 coPos.Y = yTop + Height - 1;
252 CharLowerRightCorner, // '+',
253 1,
254 coPos,
255 &Written);
256}
257
258
259VOID
261 PCCH Status,
262 PINPUT_RECORD Ir,
263 ULONG WaitEvent)
264{
265 SHORT yTop;
266 SHORT xLeft;
267 COORD coPos;
268 DWORD Written;
270 ULONG MaxLength;
271 ULONG Lines;
272 PCHAR p;
273 PCCH pnext;
274 BOOLEAN LastLine;
275 SHORT Width;
277
278 /* Count text lines and longest line */
279 MaxLength = 0;
280 Lines = 0;
281 pnext = Text;
282
283 while (TRUE)
284 {
285 p = strchr(pnext, '\n');
286
287 if (p == NULL)
288 {
289 Length = strlen(pnext);
290 LastLine = TRUE;
291 }
292 else
293 {
294 Length = (ULONG)(p - pnext);
295 LastLine = FALSE;
296 }
297
298 Lines++;
299
300 if (Length > MaxLength)
301 MaxLength = Length;
302
303 if (LastLine)
304 break;
305
306 pnext = p + 1;
307 }
308
309 /* Check length of status line */
310 if (Status != NULL)
311 {
313
314 if (Length > MaxLength)
315 MaxLength = Length;
316 }
317
318 Width = MaxLength + 4;
319 Height = Lines + 2;
320
321 if (Status != NULL)
322 Height += 2;
323
324 yTop = (yScreen - Height) / 2;
325 xLeft = (xScreen - Width) / 2;
326
327
328 /* Set screen attributes */
329 coPos.X = xLeft;
330 for (coPos.Y = yTop; coPos.Y < yTop + Height; coPos.Y++)
331 {
334 Width,
335 coPos,
336 &Written);
337 }
338
339 DrawBox(xLeft, yTop, Width, Height);
340
341 /* Print message text */
342 coPos.Y = yTop + 1;
343 pnext = Text;
344 while (TRUE)
345 {
346 p = strchr(pnext, '\n');
347
348 if (p == NULL)
349 {
350 Length = strlen(pnext);
351 LastLine = TRUE;
352 }
353 else
354 {
355 Length = (ULONG)(p - pnext);
356 LastLine = FALSE;
357 }
358
359 if (Length != 0)
360 {
361 coPos.X = xLeft + 2;
363 pnext,
364 Length,
365 coPos,
366 &Written);
367 }
368
369 if (LastLine)
370 break;
371
372 coPos.Y++;
373 pnext = p + 1;
374 }
375
376 /* Print separator line and status text */
377 if (Status != NULL)
378 {
379 coPos.Y = yTop + Height - 3;
380 coPos.X = xLeft;
383 1,
384 coPos,
385 &Written);
386
387 coPos.X = xLeft + 1;
389 CharHorizontalLine, // '-',
390 Width - 2,
391 coPos,
392 &Written);
393
394 coPos.X = xLeft + Width - 1;
397 1,
398 coPos,
399 &Written);
400
401 coPos.Y++;
402 coPos.X = xLeft + 2;
404 Status,
405 min(strlen(Status), (SIZE_T)Width - 4),
406 coPos,
407 &Written);
408 }
409
410 if (WaitEvent == POPUP_WAIT_NONE)
411 return;
412
413 while (TRUE)
414 {
416
417 if (WaitEvent == POPUP_WAIT_ANY_KEY ||
418 Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)
419 {
420 return;
421 }
422 }
423}
424
425
426/*
427 * Confirm quit setup
428 * RETURNS
429 * TRUE: Quit setup.
430 * FALSE: Don't quit setup.
431 */
432static BOOL
434{
435 BOOL Result = FALSE;
437
438 while (TRUE)
439 {
441
442 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
443 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
444 {
445 Result = TRUE;
446 break;
447 }
448 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
449 {
450 Result = FALSE;
451 break;
452 }
453 }
454
455 return Result;
456}
457
458
459static VOID
461{
462 PGENERIC_LIST_ENTRY ListEntry;
463 PCWSTR pszNewLayout;
464
466
468 {
471 {
472 /* FIXME: Handle error! */
473 return;
474 }
475 }
476
477 /* Search for default layout (if provided) */
478 if (pszNewLayout != NULL)
479 {
480 for (ListEntry = GetFirstListEntry(USetupData.LayoutList); ListEntry;
481 ListEntry = GetNextListEntry(ListEntry))
482 {
483 if (!wcscmp(pszNewLayout, ((PGENENTRY)GetListEntryData(ListEntry))->Id))
484 {
486 break;
487 }
488 }
489 }
490}
491
492
493static NTSTATUS
494NTAPI
498 IN SIZE_T cchBufferSize)
499{
500 return RtlStringCchPrintfA(Buffer, cchBufferSize, "%S",
502}
503
504static NTSTATUS
505NTAPI
509 IN SIZE_T cchBufferSize)
510{
512 PPARTENTRY PartEntry = NtOsInstall->PartEntry;
513
514 if (PartEntry && PartEntry->DriveLetter)
515 {
516 /* We have retrieved a partition that is mounted */
517 return RtlStringCchPrintfA(Buffer, cchBufferSize,
518 "%C:%S \"%S\"",
519 PartEntry->DriveLetter,
520 NtOsInstall->PathComponent,
521 NtOsInstall->InstallationName);
522 }
523 else
524 {
525 /* We failed somewhere, just show the NT path */
526 return RtlStringCchPrintfA(Buffer, cchBufferSize,
527 "%wZ \"%S\"",
528 &NtOsInstall->SystemNtPath,
529 NtOsInstall->InstallationName);
530 }
531}
532
533
534/*
535 * Displays the LanguagePage.
536 *
537 * Next pages: WelcomePage, QuitPage
538 *
539 * SIDEEFFECTS
540 * Init SelectedLanguageId
541 * Init USetupData.LanguageId
542 *
543 * RETURNS
544 * Number of the next page.
545 */
546static PAGE_NUMBER
548{
549 GENERIC_LIST_UI ListUi;
550 PCWSTR NewLanguageId;
551 BOOL RefreshPage = FALSE;
552
553 /* Initialize the computer settings list */
555 {
558 {
559 PopupError("Setup failed to initialize available translations", NULL, NULL, POPUP_WAIT_NONE);
560 return WELCOME_PAGE;
561 }
562 }
563
566
567 /* Load the font */
570
571 /*
572 * If there is no language or just a single one in the list,
573 * skip the language selection process altogether.
574 */
576 {
578 return WELCOME_PAGE;
579 }
580
582 DrawGenericList(&ListUi,
583 2, 18,
584 xScreen - 3,
585 yScreen - 3);
586
588
590
591 while (TRUE)
592 {
594
595 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
596 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
597 {
598 ScrollDownGenericList(&ListUi);
599 RefreshPage = TRUE;
600 }
601 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
602 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
603 {
604 ScrollUpGenericList(&ListUi);
605 RefreshPage = TRUE;
606 }
607 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
608 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_NEXT)) /* PAGE DOWN */
609 {
611 RefreshPage = TRUE;
612 }
613 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
614 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_PRIOR)) /* PAGE UP */
615 {
617 RefreshPage = TRUE;
618 }
619 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
620 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
621 {
622 if (ConfirmQuit(Ir))
623 return QUIT_PAGE;
624 else
625 RedrawGenericList(&ListUi);
626 }
627 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
628 {
630
633
635
637 {
639 }
640
641 /* Load the font */
643
644 return WELCOME_PAGE;
645 }
646 else if ((Ir->Event.KeyEvent.uChar.AsciiChar > 0x60) && (Ir->Event.KeyEvent.uChar.AsciiChar < 0x7b))
647 {
648 /* a-z */
650 RefreshPage = TRUE;
651 }
652
653 if (RefreshPage)
654 {
656
657 NewLanguageId =
659
660 if (wcscmp(SelectedLanguageId, NewLanguageId))
661 {
662 /* Clear the language page */
664
665 SelectedLanguageId = NewLanguageId;
666
667 /* Load the font */
669
670 /* Redraw the list */
671 DrawGenericList(&ListUi,
672 2, 18,
673 xScreen - 3,
674 yScreen - 3);
675
676 /* Redraw language selection page in native language */
678 }
679
680 RefreshPage = FALSE;
681 }
682 }
683
684 return WELCOME_PAGE;
685}
686
687
688/*
689 * Start page
690 *
691 * Next pages:
692 * LanguagePage (at once, default)
693 * InstallIntroPage (at once, if unattended)
694 * QuitPage
695 *
696 * SIDEEFFECTS
697 * Init Sdi
698 * Init USetupData.SourcePath
699 * Init USetupData.SourceRootPath
700 * Init USetupData.SourceRootDir
701 * Init USetupData.SetupInf
702 * Init USetupData.RequiredPartitionDiskSpace
703 * Init IsUnattendedSetup
704 * If unattended, init *List and sets the Codepage
705 * If unattended, init SelectedLanguageId
706 * If unattended, init USetupData.LanguageId
707 *
708 * RETURNS
709 * Number of the next page.
710 */
711static PAGE_NUMBER
713{
714 ULONG Error;
715 PGENERIC_LIST_ENTRY ListEntry;
717
719
720 /* Initialize Setup, phase 1 */
722 if (Error != ERROR_SUCCESS)
723 {
725 return QUIT_PAGE;
726 }
727
728 /* Initialize the user-mode PnP manager */
730 DPRINT1("The user-mode PnP manager could not initialize, expect unavailable devices!\n");
731
732 /* Wait for any immediate pending installations to finish */
734 DPRINT1("WaitNoPendingInstallEvents() failed to wait!\n");
735
737
739 {
740 // TODO: Read options from inf
741 /* Load the hardware, language and keyboard layout lists */
742
746
748
749 /* new part */
753
755
756 /* first we hack LanguageList */
757 for (ListEntry = GetFirstListEntry(USetupData.LanguageList); ListEntry;
758 ListEntry = GetNextListEntry(ListEntry))
759 {
760 LocaleId = ((PGENENTRY)GetListEntryData(ListEntry))->Id;
762 {
763 DPRINT("found %S in LanguageList\n", LocaleId);
765 break;
766 }
767 }
768
769 /* now LayoutList */
770 for (ListEntry = GetFirstListEntry(USetupData.LayoutList); ListEntry;
771 ListEntry = GetNextListEntry(ListEntry))
772 {
773 LocaleId = ((PGENENTRY)GetListEntryData(ListEntry))->Id;
775 {
776 DPRINT("found %S in LayoutList\n", LocaleId);
778 break;
779 }
780 }
781
783
784 return INSTALL_INTRO_PAGE;
785 }
786
787 return LANGUAGE_PAGE;
788}
789
790
791/*
792 * Displays the WelcomePage.
793 *
794 * Next pages:
795 * InstallIntroPage (default)
796 * RepairIntroPage
797 * RecoveryPage
798 * LicensePage
799 * QuitPage
800 *
801 * RETURNS
802 * Number of the next page.
803 */
804static PAGE_NUMBER
806{
808
809 while (TRUE)
810 {
812
813 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
814 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
815 {
816 if (ConfirmQuit(Ir))
817 return QUIT_PAGE;
818
819 break;
820 }
821 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
822 {
823 return INSTALL_INTRO_PAGE;
824 }
825 else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'R') /* R */
826 {
827 return RECOVERY_PAGE; // REPAIR_INTRO_PAGE;
828 }
829 else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'L') /* L */
830 {
831 return LICENSE_PAGE;
832 }
833 }
834
835 return WELCOME_PAGE;
836}
837
838
839/*
840 * Displays the License page.
841 *
842 * Next page:
843 * WelcomePage (default)
844 *
845 * RETURNS
846 * Number of the next page.
847 */
848static PAGE_NUMBER
850{
852
853 while (TRUE)
854 {
856
857 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
858 {
859 return WELCOME_PAGE;
860 }
861 }
862
863 return LICENSE_PAGE;
864}
865
866
867/*
868 * Displays the RepairIntroPage.
869 *
870 * Next pages:
871 * RebootPage (default)
872 * InstallIntroPage
873 * RecoveryPage
874 * IntroPage
875 *
876 * RETURNS
877 * Number of the next page.
878 */
879static PAGE_NUMBER
881{
883
884 while (TRUE)
885 {
887
888 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
889 {
890 return REBOOT_PAGE;
891 }
892 else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'U') /* U */
893 {
895 return INSTALL_INTRO_PAGE;
896 }
897 else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'R') /* R */
898 {
899 return RECOVERY_PAGE;
900 }
901 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESC */
902 {
903 return WELCOME_PAGE;
904 }
905 }
906
907 return REPAIR_INTRO_PAGE;
908}
909
910/*
911 * Displays the UpgradeRepairPage.
912 *
913 * Next pages:
914 * RebootPage (default)
915 * InstallIntroPage
916 * RecoveryPage
917 * WelcomePage
918 *
919 * RETURNS
920 * Number of the next page.
921 */
922static PAGE_NUMBER
924{
925 GENERIC_LIST_UI ListUi;
926
927/*** HACK!! ***/
928 if (PartitionList == NULL)
929 {
931 if (PartitionList == NULL)
932 {
933 /* FIXME: show an error dialog */
935 return QUIT_PAGE;
936 }
938 {
940 return QUIT_PAGE;
941 }
942
943 /* Reset the formatter machine state */
946 }
947/**************/
948
950 if (!NtOsInstallsList)
951 DPRINT1("Failed to get a list of NTOS installations; continue installation...\n");
952
953 /*
954 * If there is no available installation (or just a single one??) that can
955 * be updated in the list, just continue with the regular installation.
956 */
958 {
960
961 // return INSTALL_INTRO_PAGE;
963 // return SCSI_CONTROLLER_PAGE;
964 }
965
967
969 DrawGenericList(&ListUi,
970 2, 23,
971 xScreen - 3,
972 yScreen - 3);
973
974 // return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir);
975 while (TRUE)
976 {
978
979 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x00)
980 {
981 switch (Ir->Event.KeyEvent.wVirtualKeyCode)
982 {
983 case VK_DOWN: /* DOWN */
984 ScrollDownGenericList(&ListUi);
985 break;
986 case VK_UP: /* UP */
987 ScrollUpGenericList(&ListUi);
988 break;
989 case VK_NEXT: /* PAGE DOWN */
991 break;
992 case VK_PRIOR: /* PAGE UP */
994 break;
995 case VK_F3: /* F3 */
996 {
997 if (ConfirmQuit(Ir))
998 return QUIT_PAGE;
999 else
1000 RedrawGenericList(&ListUi);
1001 break;
1002 }
1003#if 1
1004/* TODO: Temporarily kept until correct keyboard layout is in place.
1005 * (Actual AsciiChar of ESCAPE should be 0x1B instead of 0.)
1006 * Addendum to commit 8b94515b.
1007 */
1008 case VK_ESCAPE: /* ESC */
1009 {
1011 // return nextPage; // prevPage;
1012
1013 // return INSTALL_INTRO_PAGE;
1014 return DEVICE_SETTINGS_PAGE;
1015 // return SCSI_CONTROLLER_PAGE;
1016 }
1017
1018#endif
1019 }
1020 }
1021#if 0
1022/* TODO: Restore this once correct keyboard layout is in place. */
1023 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESC */
1024 {
1026 // return nextPage; // prevPage;
1027
1028 // return INSTALL_INTRO_PAGE;
1029 return DEVICE_SETTINGS_PAGE;
1030 // return SCSI_CONTROLLER_PAGE;
1031 }
1032#endif
1033 else
1034 {
1035 // switch (toupper(Ir->Event.KeyEvent.uChar.AsciiChar))
1036 // if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1037 if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'U') /* U */
1038 {
1039 /* Retrieve the current installation */
1041
1044
1045 DPRINT1("Selected installation for repair: \"%S\" ; DiskNumber = %d , PartitionNumber = %d\n",
1047
1049
1050 // return nextPage;
1051 /***/return INSTALL_INTRO_PAGE;/***/
1052 }
1053 else if ((Ir->Event.KeyEvent.uChar.AsciiChar > 0x60) &&
1054 (Ir->Event.KeyEvent.uChar.AsciiChar < 0x7b)) /* a-z */
1055 {
1057 }
1058 }
1059 }
1060
1061 return UPGRADE_REPAIR_PAGE;
1062}
1063
1064
1065/*
1066 * Displays the InstallIntroPage.
1067 *
1068 * Next pages:
1069 * DeviceSettingsPage (At once if repair or update is selected)
1070 * SelectPartitionPage (At once if unattended setup)
1071 * DeviceSettingsPage (default)
1072 * QuitPage
1073 *
1074 * RETURNS
1075 * Number of the next page.
1076 */
1077static PAGE_NUMBER
1079{
1080 if (RepairUpdateFlag)
1081 {
1082#if 1 /* Old code that looks good */
1083
1084 // return SELECT_PARTITION_PAGE;
1085 return DEVICE_SETTINGS_PAGE;
1086
1087#else /* Possible new code? */
1088
1089 return DEVICE_SETTINGS_PAGE;
1090 // return SCSI_CONTROLLER_PAGE;
1091
1092#endif
1093 }
1094
1096 return SELECT_PARTITION_PAGE;
1097
1099
1100 while (TRUE)
1101 {
1102 CONSOLE_ConInKey(Ir);
1103
1104 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1105 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1106 {
1107 if (ConfirmQuit(Ir))
1108 return QUIT_PAGE;
1109
1110 break;
1111 }
1112 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1113 {
1114 return UPGRADE_REPAIR_PAGE;
1115 }
1116 }
1117
1118 return INSTALL_INTRO_PAGE;
1119}
1120
1121
1122#if 0
1123static PAGE_NUMBER
1124ScsiControllerPage(PINPUT_RECORD Ir)
1125{
1126 // MUIDisplayPage(SCSI_CONTROLLER_PAGE);
1127
1128 CONSOLE_SetTextXY(6, 8, "Setup detected the following mass storage devices:");
1129
1130 /* FIXME: print loaded mass storage driver descriptions */
1131#if 0
1132 CONSOLE_SetTextXY(8, 10, "TEST device");
1133#endif
1134
1135 CONSOLE_SetStatusText(" ENTER = Continue F3 = Quit");
1136
1137 while (TRUE)
1138 {
1139 CONSOLE_ConInKey(Ir);
1140
1141 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1142 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1143 {
1144 if (ConfirmQuit(Ir))
1145 return QUIT_PAGE;
1146
1147 break;
1148 }
1149 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1150 {
1151 return DEVICE_SETTINGS_PAGE;
1152 }
1153 }
1154
1155 return SCSI_CONTROLLER_PAGE;
1156}
1157
1158static PAGE_NUMBER
1159OemDriverPage(PINPUT_RECORD Ir)
1160{
1161 // MUIDisplayPage(OEM_DRIVER_PAGE);
1162
1163 CONSOLE_SetTextXY(6, 8, "This is the OEM driver page!");
1164
1165 /* FIXME: Implement!! */
1166
1167 CONSOLE_SetStatusText(" ENTER = Continue F3 = Quit");
1168
1169 while (TRUE)
1170 {
1171 CONSOLE_ConInKey(Ir);
1172
1173 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1174 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1175 {
1176 if (ConfirmQuit(Ir))
1177 return QUIT_PAGE;
1178
1179 break;
1180 }
1181 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1182 {
1183 return DEVICE_SETTINGS_PAGE;
1184 }
1185 }
1186
1187 return OEM_DRIVER_PAGE;
1188}
1189#endif
1190
1191
1192/*
1193 * Displays the DeviceSettingsPage.
1194 *
1195 * Next pages:
1196 * SelectPartitionPage (At once if repair or update is selected)
1197 * ComputerSettingsPage
1198 * DisplaySettingsPage
1199 * KeyboardSettingsPage
1200 * LayoutsettingsPage
1201 * SelectPartitionPage
1202 * QuitPage
1203 *
1204 * SIDEEFFECTS
1205 * Init USetupData.ComputerList
1206 * Init USetupData.DisplayList
1207 * Init USetupData.KeyboardList
1208 * Init USetupData.LayoutList
1209 *
1210 * RETURNS
1211 * Number of the next page.
1212 */
1213static PAGE_NUMBER
1215{
1216 static ULONG Line = 16;
1217
1218 /* Initialize the computer settings list */
1220 {
1223 {
1225 return QUIT_PAGE;
1226 }
1227 }
1228
1229 /* Initialize the display settings list */
1231 {
1234 {
1236 return QUIT_PAGE;
1237 }
1238 }
1239
1240 /* Initialize the keyboard settings list */
1242 {
1245 {
1247 return QUIT_PAGE;
1248 }
1249 }
1250
1251 /* Initialize the keyboard layout list */
1252 if (USetupData.LayoutList == NULL)
1253 {
1255 if (USetupData.LayoutList == NULL)
1256 {
1257 /* FIXME: report error */
1259 return QUIT_PAGE;
1260 }
1261 }
1262
1263 if (RepairUpdateFlag)
1264 return SELECT_PARTITION_PAGE;
1265
1266 // if (IsUnattendedSetup)
1267 // return SELECT_PARTITION_PAGE;
1268
1270
1275
1276 CONSOLE_InvertTextXY(24, Line, 48, 1);
1277
1278 while (TRUE)
1279 {
1280 CONSOLE_ConInKey(Ir);
1281
1282 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1283 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1284 {
1285 CONSOLE_NormalTextXY(24, Line, 48, 1);
1286
1287 if (Line == 14)
1288 Line = 16;
1289 else if (Line == 16)
1290 Line = 11;
1291 else
1292 Line++;
1293
1294 CONSOLE_InvertTextXY(24, Line, 48, 1);
1295 }
1296 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1297 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1298 {
1299 CONSOLE_NormalTextXY(24, Line, 48, 1);
1300
1301 if (Line == 11)
1302 Line = 16;
1303 else if (Line == 16)
1304 Line = 14;
1305 else
1306 Line--;
1307
1308 CONSOLE_InvertTextXY(24, Line, 48, 1);
1309 }
1310 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1311 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1312 {
1313 if (ConfirmQuit(Ir))
1314 return QUIT_PAGE;
1315
1316 break;
1317 }
1318 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1319 {
1320 if (Line == 11)
1322 else if (Line == 12)
1323 return DISPLAY_SETTINGS_PAGE;
1324 else if (Line == 13)
1326 else if (Line == 14)
1327 return LAYOUT_SETTINGS_PAGE;
1328 else if (Line == 16)
1329 return SELECT_PARTITION_PAGE;
1330 }
1331 }
1332
1333 return DEVICE_SETTINGS_PAGE;
1334}
1335
1336
1337/*
1338 * Handles generic selection lists.
1339 *
1340 * PARAMS
1341 * GenericList: The list to handle.
1342 * nextPage: The page it needs to jump to after this page.
1343 * Ir: The PINPUT_RECORD
1344 */
1345static PAGE_NUMBER
1347 PAGE_NUMBER nextPage,
1348 PINPUT_RECORD Ir)
1349{
1350 while (TRUE)
1351 {
1352 CONSOLE_ConInKey(Ir);
1353
1354 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1355 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1356 {
1357 ScrollDownGenericList(ListUi);
1358 }
1359 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1360 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1361 {
1362 ScrollUpGenericList(ListUi);
1363 }
1364 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1365 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_NEXT)) /* PAGE DOWN */
1366 {
1368 }
1369 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1370 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_PRIOR)) /* PAGE UP */
1371 {
1373 }
1374 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1375 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1376 {
1377 if (ConfirmQuit(Ir))
1378 return QUIT_PAGE;
1379 else
1380 RedrawGenericList(ListUi);
1381 }
1382 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESC */
1383 {
1385 return nextPage; // Use some "prevPage;" instead?
1386 }
1387 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1388 {
1389 return nextPage;
1390 }
1391 else if ((Ir->Event.KeyEvent.uChar.AsciiChar > 0x60) && (Ir->Event.KeyEvent.uChar.AsciiChar < 0x7b))
1392 {
1393 /* a-z */
1395 }
1396 }
1397}
1398
1399
1400/*
1401 * Displays the ComputerSettingsPage.
1402 *
1403 * Next pages:
1404 * DeviceSettingsPage
1405 * QuitPage
1406 *
1407 * RETURNS
1408 * Number of the next page.
1409 */
1410static PAGE_NUMBER
1412{
1413 GENERIC_LIST_UI ListUi;
1415
1417 DrawGenericList(&ListUi,
1418 2, 18,
1419 xScreen - 3,
1420 yScreen - 3);
1421
1422 return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir);
1423}
1424
1425
1426/*
1427 * Displays the DisplaySettingsPage.
1428 *
1429 * Next pages:
1430 * DeviceSettingsPage
1431 * QuitPage
1432 *
1433 * RETURNS
1434 * Number of the next page.
1435 */
1436static PAGE_NUMBER
1438{
1439 GENERIC_LIST_UI ListUi;
1441
1443 DrawGenericList(&ListUi,
1444 2, 18,
1445 xScreen - 3,
1446 yScreen - 3);
1447
1448 return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir);
1449}
1450
1451
1452/*
1453 * Displays the KeyboardSettingsPage.
1454 *
1455 * Next pages:
1456 * DeviceSettingsPage
1457 * QuitPage
1458 *
1459 * RETURNS
1460 * Number of the next page.
1461 */
1462static PAGE_NUMBER
1464{
1465 GENERIC_LIST_UI ListUi;
1467
1469 DrawGenericList(&ListUi,
1470 2, 18,
1471 xScreen - 3,
1472 yScreen - 3);
1473
1474 return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir);
1475}
1476
1477
1478/*
1479 * Displays the LayoutSettingsPage.
1480 *
1481 * Next pages:
1482 * DeviceSettingsPage
1483 * QuitPage
1484 *
1485 * RETURNS
1486 * Number of the next page.
1487 */
1488static PAGE_NUMBER
1490{
1491 GENERIC_LIST_UI ListUi;
1493
1495 DrawGenericList(&ListUi,
1496 2, 18,
1497 xScreen - 3,
1498 yScreen - 3);
1499
1500 return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir);
1501}
1502
1503
1504static BOOL
1506{
1508
1509 size = PartEntry->SectorCount.QuadPart * PartEntry->DiskEntry->BytesPerSector;
1510 size = (size + (512 * KB)) / MB; /* in MBytes */
1511
1513 {
1514 /* Partition is too small so ask for another one */
1515 DPRINT1("Partition is too small (size: %I64u MB), required disk space is %lu MB\n", size, USetupData.RequiredPartitionDiskSpace);
1516 return FALSE;
1517 }
1518 else
1519 {
1520 return TRUE;
1521 }
1522}
1523
1524
1525/*
1526 * Displays the SelectPartitionPage.
1527 *
1528 * Next pages:
1529 * SelectFileSystemPage (At once if unattended)
1530 * SelectFileSystemPage (Default if free space is selected)
1531 * CreatePartitionPage
1532 * ConfirmDeleteSystemPartitionPage (if the selected partition is the system partition, aka with the boot flag set)
1533 * DeletePartitionPage
1534 * QuitPage
1535 *
1536 * SIDEEFFECTS
1537 * Set InstallShortcut (only if not unattended + free space is selected)
1538 *
1539 * RETURNS
1540 * Number of the next page.
1541 */
1542static PAGE_NUMBER
1544{
1545 PARTLIST_UI ListUi;
1546 ULONG Error;
1547
1548 if (PartitionList == NULL)
1549 {
1551 if (PartitionList == NULL)
1552 {
1554 return QUIT_PAGE;
1555 }
1557 {
1559 return QUIT_PAGE;
1560 }
1561
1562 /* Reset the formatter machine state */
1565 }
1566
1567 if (RepairUpdateFlag)
1568 {
1570
1571 /* Determine the selected installation disk & partition */
1575 if (!InstallPartition)
1576 {
1577 DPRINT1("RepairUpdateFlag == TRUE, SelectPartition() returned FALSE, assert!\n");
1578 ASSERT(FALSE);
1579 }
1581
1583 }
1584
1586
1589 2, 21,
1590 xScreen - 3,
1591 yScreen - 3);
1592 DrawPartitionList(&ListUi);
1593
1595 {
1596 /* Determine the selected installation disk & partition */
1600 if (!InstallPartition)
1601 {
1603
1605 {
1608
1612 TRUE);
1613
1614// FIXME?? Aren't we going to enter an infinite loop, if this test fails??
1616 {
1619 return SELECT_PARTITION_PAGE; /* let the user select another partition */
1620 }
1621
1624 }
1625 }
1626 else
1627 {
1629
1630 DrawPartitionList(&ListUi); // FIXME: Doesn't make much sense...
1631
1632// FIXME?? Aren't we going to enter an infinite loop, if this test fails??
1634 {
1637 return SELECT_PARTITION_PAGE; /* let the user select another partition */
1638 }
1639
1641 }
1642 }
1643
1644 while (TRUE)
1645 {
1646 ULONG uID;
1647
1649
1650 /* Update status text */
1651 if (CurrentPartition == NULL)
1652 {
1653 // FIXME: If we get a NULL current partition, this means that
1654 // the current disk is of unrecognized type. So we should display
1655 // instead a status string to initialize the disk with one of
1656 // the recognized partitioning schemes (MBR, later: GPT, etc.)
1657 // For the time being we don't have that, so use instead another
1658 // known string.
1660 }
1661 else
1662 {
1664 {
1668 {
1670 }
1671 }
1672 else
1673 {
1677 }
1678 }
1680
1681 CONSOLE_ConInKey(Ir);
1682
1683 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1684 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1685 {
1686 if (ConfirmQuit(Ir))
1687 {
1690 return QUIT_PAGE;
1691 }
1692
1693 break;
1694 }
1695 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1696 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1697 {
1698 ScrollDownPartitionList(&ListUi);
1699 }
1700 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1701 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1702 {
1703 ScrollUpPartitionList(&ListUi);
1704 }
1705 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
1706 {
1708
1710 continue; // return SELECT_PARTITION_PAGE;
1711
1712 /*
1713 * Check whether the user wants to install ReactOS on a disk that
1714 * is not recognized by the computer's firmware and if so, display
1715 * a warning since such disks may not be bootable.
1716 */
1717 if (CurrentPartition->DiskEntry->MediaType == FixedMedia &&
1718 !CurrentPartition->DiskEntry->BiosFound)
1719 {
1720 PopupError("The disk you have selected for installing ReactOS\n"
1721 "is not visible by the firmware of your computer,\n"
1722 "and so may not be bootable.\n"
1723 "Press ENTER to continue nonetheless.",
1725 Ir, POPUP_WAIT_ENTER);
1726 // return SELECT_PARTITION_PAGE;
1727 }
1728
1730 {
1732 if (Error != NOT_AN_ERROR)
1733 {
1735 return SELECT_PARTITION_PAGE;
1736 }
1737
1740 0ULL,
1741 TRUE);
1742 }
1743
1745 {
1748 return SELECT_PARTITION_PAGE; /* let the user select another partition */
1749 }
1750
1753 }
1754 else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'C') /* C */
1755 {
1757
1759 if (Error != NOT_AN_ERROR)
1760 {
1762 return SELECT_PARTITION_PAGE;
1763 }
1764
1766 return CREATE_PARTITION_PAGE;
1767 }
1768 else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'E') /* E */
1769 {
1771
1773 {
1775 if (Error != NOT_AN_ERROR)
1776 {
1778 return SELECT_PARTITION_PAGE;
1779 }
1780
1782 return CREATE_PARTITION_PAGE;
1783 }
1784 }
1785 else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'D') /* D */
1786 {
1787 UNICODE_STRING CurrentPartitionU;
1788 WCHAR PathBuffer[MAX_PATH];
1789
1791
1792 /* Ignore deletion in case this is not a partitioned entry */
1794 {
1795 continue;
1796 }
1797
1798// TODO: Do something similar before trying to format the partition?
1799 if (!CurrentPartition->New &&
1802 {
1804
1805 RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
1806 L"\\Device\\Harddisk%lu\\Partition%lu\\",
1807 CurrentPartition->DiskEntry->DiskNumber,
1809 RtlInitUnicodeString(&CurrentPartitionU, PathBuffer);
1810
1811 /*
1812 * Check whether the user attempts to delete the partition on which
1813 * the installation source is present. If so, fail with an error.
1814 */
1815 // &USetupData.SourceRootPath
1816 if (RtlPrefixUnicodeString(&CurrentPartitionU, &USetupData.SourcePath, TRUE))
1817 {
1819 return SELECT_PARTITION_PAGE;
1820 }
1821 }
1822
1825 {
1827 }
1828
1829 return DELETE_PARTITION_PAGE;
1830 }
1831 }
1832
1833 return SELECT_PARTITION_PAGE;
1834}
1835
1836
1837#define PARTITION_SIZE_INPUT_FIELD_LENGTH 9
1838/* Restriction for MaxSize */
1839#define PARTITION_MAXSIZE (pow(10, (PARTITION_SIZE_INPUT_FIELD_LENGTH - 1)) - 1)
1840
1841static VOID
1843 SHORT Top,
1844 SHORT Right,
1845 SHORT Bottom,
1846 ULONG MaxSize,
1848 PBOOLEAN Quit,
1850{
1851 INPUT_RECORD Ir;
1852 COORD coPos;
1853 DWORD Written;
1854 CHAR Buffer[128];
1855 INT Length, Pos;
1856 WCHAR ch;
1857 SHORT iLeft;
1858 SHORT iTop;
1859
1860 if (Quit != NULL)
1861 *Quit = FALSE;
1862
1863 if (Cancel != NULL)
1864 *Cancel = FALSE;
1865
1866 DrawBox(Left, Top, Right - Left + 1, Bottom - Top + 1);
1867
1868 /* Print message */
1869 coPos.X = Left + 2;
1870 coPos.Y = Top + 2;
1872 iLeft = coPos.X + (USHORT)strlen(Buffer) + 1;
1873 iTop = coPos.Y;
1874
1876 Buffer,
1877 strlen(Buffer),
1878 coPos,
1879 &Written);
1880
1882 coPos.X = iLeft + PARTITION_SIZE_INPUT_FIELD_LENGTH + 1;
1883 coPos.Y = iTop;
1885 Buffer,
1886 strlen(Buffer),
1887 coPos,
1888 &Written);
1889
1890 swprintf(InputBuffer, L"%lu", MaxSize);
1892 Pos = Length;
1894 iTop,
1896 InputBuffer);
1897 CONSOLE_SetCursorXY(iLeft + Length, iTop);
1899
1900 while (TRUE)
1901 {
1902 CONSOLE_ConInKey(&Ir);
1903
1904 if ((Ir.Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1905 (Ir.Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1906 {
1907 if (Quit != NULL)
1908 *Quit = TRUE;
1909
1912 break;
1913 }
1914 else if (Ir.Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
1915 {
1917 break;
1918 }
1919 else if (Ir.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESC */
1920 {
1921 if (Cancel != NULL)
1922 *Cancel = TRUE;
1923
1926 break;
1927 }
1928 else if ((Ir.Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1929 (Ir.Event.KeyEvent.wVirtualKeyCode == VK_HOME)) /* HOME */
1930 {
1931 Pos = 0;
1932 CONSOLE_SetCursorXY(iLeft + Pos, iTop);
1933 }
1934 else if ((Ir.Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1935 (Ir.Event.KeyEvent.wVirtualKeyCode == VK_END)) /* END */
1936 {
1937 Pos = Length;
1938 CONSOLE_SetCursorXY(iLeft + Pos, iTop);
1939 }
1940 else if ((Ir.Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1941 (Ir.Event.KeyEvent.wVirtualKeyCode == VK_LEFT)) /* LEFT */
1942 {
1943 if (Pos > 0)
1944 {
1945 Pos--;
1946 CONSOLE_SetCursorXY(iLeft + Pos, iTop);
1947 }
1948 }
1949 else if ((Ir.Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1950 (Ir.Event.KeyEvent.wVirtualKeyCode == VK_RIGHT)) /* RIGHT */
1951 {
1952 if (Pos < Length)
1953 {
1954 Pos++;
1955 CONSOLE_SetCursorXY(iLeft + Pos, iTop);
1956 }
1957 }
1958 else if ((Ir.Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1959 (Ir.Event.KeyEvent.wVirtualKeyCode == VK_DELETE)) /* DEL */
1960 {
1961 if (Pos < Length)
1962 {
1964 &InputBuffer[Pos + 1],
1965 (Length - Pos - 1) * sizeof(WCHAR));
1967
1968 Length--;
1970 iTop,
1972 InputBuffer);
1973 CONSOLE_SetCursorXY(iLeft + Pos, iTop);
1974 }
1975 }
1976 else if (Ir.Event.KeyEvent.wVirtualKeyCode == VK_BACK) /* BACKSPACE */
1977 {
1978 if (Pos > 0)
1979 {
1980 if (Pos < Length)
1981 memmove(&InputBuffer[Pos - 1],
1982 &InputBuffer[Pos],
1983 (Length - Pos) * sizeof(WCHAR));
1985
1986 Pos--;
1987 Length--;
1989 iTop,
1991 InputBuffer);
1992 CONSOLE_SetCursorXY(iLeft + Pos, iTop);
1993 }
1994 }
1995 else if (Ir.Event.KeyEvent.uChar.AsciiChar != 0x00)
1996 {
1998 {
2000
2001 if ((ch >= L'0') && (ch <= L'9'))
2002 {
2003 if (Pos < Length)
2004 memmove(&InputBuffer[Pos + 1],
2005 &InputBuffer[Pos],
2006 (Length - Pos) * sizeof(WCHAR));
2008 InputBuffer[Pos] = ch;
2009
2010 Pos++;
2011 Length++;
2013 iTop,
2015 InputBuffer);
2016 CONSOLE_SetCursorXY(iLeft + Pos, iTop);
2017 }
2018 }
2019 }
2020 }
2021}
2022
2023
2024/*
2025 * Displays the CreatePartitionPage.
2026 *
2027 * Next pages:
2028 * SelectPartitionPage
2029 * SelectFileSystemPage (default)
2030 * QuitPage
2031 *
2032 * RETURNS
2033 * Number of the next page.
2034 */
2035static PAGE_NUMBER
2037{
2038 PPARTENTRY PartEntry;
2039 PDISKENTRY DiskEntry;
2040 ULONG uID;
2041 BOOLEAN Quit;
2043 ULONG MaxSize;
2044 ULONGLONG PartSize;
2046 WCHAR InputBuffer[50];
2047 CHAR LineBuffer[100];
2048
2050 {
2051 /* FIXME: show an error dialog */
2052 return QUIT_PAGE;
2053 }
2054
2056 {
2060 }
2061 else // if (PartCreateType == PartTypeExtended)
2062 {
2064 }
2065
2066 CONSOLE_SetTextXY(6, 8, MUIGetString(uID));
2067
2068 PartEntry = CurrentPartition;
2069 DiskEntry = CurrentPartition->DiskEntry;
2070
2071 DiskDescription(DiskEntry, LineBuffer, ARRAYSIZE(LineBuffer));
2073 LineBuffer);
2074
2076
2078
2079 while (TRUE)
2080 {
2081 MaxSize = (PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector) / MB; /* in MBytes (rounded) */
2082 if (MaxSize > PARTITION_MAXSIZE)
2083 MaxSize = PARTITION_MAXSIZE;
2084
2085 ShowPartitionSizeInputBox(12, 14, xScreen - 12, 17, /* left, top, right, bottom */
2086 MaxSize, InputBuffer, &Quit, &Cancel);
2087
2088 if (Quit)
2089 {
2090 if (ConfirmQuit(Ir))
2091 return QUIT_PAGE;
2092 break;
2093 }
2094 else if (Cancel)
2095 {
2096 return SELECT_PARTITION_PAGE;
2097 }
2098 else
2099 {
2100 PartSize = _wcstoui64(InputBuffer, NULL, 10);
2101
2102 /* Retry if too small or too large */
2103 if (PartSize < 1)
2104 continue;
2105 if (PartSize > MaxSize)
2106 continue;
2107
2108 /* Convert to bytes */
2109 if (PartSize == MaxSize)
2110 {
2111 /* Use all of the unpartitioned disk space */
2112 SectorCount = PartEntry->SectorCount.QuadPart;
2113 }
2114 else
2115 {
2116 /* Calculate the sector count from the size in MB */
2117 SectorCount = PartSize * MB / DiskEntry->BytesPerSector;
2118
2119 /* But never get larger than the unpartitioned disk space */
2120 if (SectorCount > PartEntry->SectorCount.QuadPart)
2121 SectorCount = PartEntry->SectorCount.QuadPart;
2122 }
2123
2124 DPRINT("Partition size: %I64u bytes\n", PartSize);
2125
2127 {
2131 FALSE);
2132 }
2133 else // if (PartCreateType == PartTypeExtended)
2134 {
2137 SectorCount);
2138 }
2139
2140 return SELECT_PARTITION_PAGE;
2141 }
2142 }
2143
2144 return CREATE_PARTITION_PAGE;
2145}
2146
2147
2148/*
2149 * Displays the ConfirmDeleteSystemPartitionPage.
2150 *
2151 * Next pages:
2152 * DeletePartitionPage (default)
2153 * SelectPartitionPage
2154 *
2155 * RETURNS
2156 * Number of the next page.
2157 */
2158static PAGE_NUMBER
2160{
2162
2163 while (TRUE)
2164 {
2165 CONSOLE_ConInKey(Ir);
2166
2167 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2168 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
2169 {
2170 if (ConfirmQuit(Ir))
2171 return QUIT_PAGE;
2172
2173 break;
2174 }
2175 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
2176 {
2177 return DELETE_PARTITION_PAGE;
2178 }
2179 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESC */
2180 {
2181 return SELECT_PARTITION_PAGE;
2182 }
2183 }
2184
2186}
2187
2188
2189/*
2190 * Displays the DeletePartitionPage.
2191 *
2192 * Next pages:
2193 * SelectPartitionPage (default)
2194 * QuitPage
2195 *
2196 * RETURNS
2197 * Number of the next page.
2198 */
2199static PAGE_NUMBER
2201{
2202 PPARTENTRY PartEntry;
2203 PDISKENTRY DiskEntry;
2204 CHAR LineBuffer[100];
2205
2207 {
2208 /* FIXME: show an error dialog */
2209 return QUIT_PAGE;
2210 }
2211
2212 PartEntry = CurrentPartition;
2213 DiskEntry = CurrentPartition->DiskEntry;
2214
2216
2217 PartitionDescription(PartEntry, LineBuffer, ARRAYSIZE(LineBuffer));
2218 CONSOLE_SetTextXY(6, 10, LineBuffer);
2219
2220 DiskDescription(DiskEntry, LineBuffer, ARRAYSIZE(LineBuffer));
2222 LineBuffer);
2223
2224 while (TRUE)
2225 {
2226 CONSOLE_ConInKey(Ir);
2227
2228 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2229 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
2230 {
2231 if (ConfirmQuit(Ir))
2232 return QUIT_PAGE;
2233
2234 break;
2235 }
2236 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESC */
2237 {
2238 return SELECT_PARTITION_PAGE;
2239 }
2240 else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'L') /* L */
2241 {
2245 return SELECT_PARTITION_PAGE;
2246 }
2247 }
2248
2249 return DELETE_PARTITION_PAGE;
2250}
2251
2252
2253static VOID
2255{
2256 if (!FileSystemList)
2257 return;
2258
2261}
2262
2263/*
2264 * Displays the SelectFileSystemPage.
2265 *
2266 * Next pages:
2267 * CheckFileSystemPage (At once if RepairUpdate is selected)
2268 * CheckFileSystemPage (At once if Unattended and not USetupData.FormatPartition)
2269 * FormatPartitionPage (At once if Unattended and USetupData.FormatPartition)
2270 * SelectPartitionPage (If the user aborts)
2271 * FormatPartitionPage (Default)
2272 * QuitPage
2273 *
2274 * SIDEEFFECTS
2275 * Calls UpdatePartitionType()
2276 * Calls FindSupportedSystemPartition()
2277 *
2278 * RETURNS
2279 * Number of the next page.
2280 */
2281static PAGE_NUMBER
2283{
2284 PPARTENTRY PartEntry;
2285 PDISKENTRY DiskEntry;
2286 FORMATMACHINESTATE PreviousFormatState;
2287 PCWSTR DefaultFs;
2288 CHAR LineBuffer[100];
2289
2290 DPRINT("SelectFileSystemPage()\n");
2291
2293 {
2294 /* FIXME: show an error dialog */
2295 return QUIT_PAGE;
2296 }
2297
2298 /* Find or set the active system partition when starting formatting */
2299 if (FormatState == Start)
2300 {
2301 /*
2302 * If we install on a fixed disk, try to find a supported system
2303 * partition on the system. Otherwise if we install on a removable disk
2304 * use the install partition as the system partition.
2305 */
2306 if (InstallPartition->DiskEntry->MediaType == FixedMedia)
2307 {
2309 FALSE,
2312 /* Use the original system partition as the old active partition hint */
2313 PartEntry = PartitionList->SystemPartition;
2314
2317 {
2318 DPRINT1("We are using a different system partition!!!!\n");
2319
2321
2322 {
2323 PPARTENTRY PartEntry; // Shadow variable
2324
2325 PartEntry = PartitionList->SystemPartition;
2326 DiskEntry = PartEntry->DiskEntry;
2327
2328 PartitionDescription(PartEntry, LineBuffer, ARRAYSIZE(LineBuffer));
2329 CONSOLE_SetTextXY(8, 10, LineBuffer);
2330
2331 DiskDescription(DiskEntry, LineBuffer, ARRAYSIZE(LineBuffer));
2333 LineBuffer);
2334
2335
2336 PartEntry = SystemPartition;
2337 DiskEntry = PartEntry->DiskEntry;
2338
2339 PartitionDescription(PartEntry, LineBuffer, ARRAYSIZE(LineBuffer));
2340 CONSOLE_SetTextXY(8, 23, LineBuffer);
2341 }
2342
2343 while (TRUE)
2344 {
2345 CONSOLE_ConInKey(Ir);
2346
2347 if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
2348 {
2349 break;
2350 }
2351 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESC */
2352 {
2353 return SELECT_PARTITION_PAGE;
2354 }
2355 }
2356
2358 CONSOLE_Flush();
2359 }
2360 }
2361 else // if (InstallPartition->DiskEntry->MediaType == RemovableMedia)
2362 {
2364 /* Don't specify any old active partition hint */
2365 PartEntry = NULL;
2366 }
2367
2368 if (!SystemPartition)
2369 {
2370 /* FIXME: improve the error dialog */
2371 //
2372 // Error dialog should say that we cannot find a suitable
2373 // system partition and create one on the system. At this point,
2374 // it may be nice to ask the user whether he wants to continue,
2375 // or use an external drive as the system drive/partition
2376 // (e.g. floppy, USB drive, etc...)
2377 //
2378 PopupError("The ReactOS Setup could not find a supported system partition\n"
2379 "on your system or could not create a new one. Without such partition\n"
2380 "the Setup program cannot install ReactOS.\n"
2381 "Press ENTER to return to the partition selection list.",
2383 Ir, POPUP_WAIT_ENTER);
2384 return SELECT_PARTITION_PAGE;
2385 }
2386
2387 /*
2388 * If the system partition can be created in some
2389 * non-partitioned space, create it now.
2390 */
2392 {
2395 0LL, // SystemPartition->SectorCount.QuadPart,
2396 TRUE);
2398 }
2399
2400 /* Set it as such */
2402 {
2403 DPRINT1("SetActivePartition(0x%p) failed?!\n", SystemPartition);
2404 ASSERT(FALSE);
2405 }
2406
2407 /* Commit all partition changes to all the disks */
2409 {
2410 DPRINT("WritePartitionsToDisk() failed\n");
2412 return QUIT_PAGE;
2413 }
2414
2415 /*
2416 * In all cases, whether or not we are going to perform a formatting,
2417 * we must perform a filesystem check of both the system and the
2418 * installation partitions.
2419 */
2423
2424 /*
2425 * In case we just repair an existing installation, or make
2426 * an unattended setup without formatting, just go to the
2427 * filesystem check step.
2428 */
2429 if (RepairUpdateFlag)
2431
2434 }
2435
2436 // ASSERT(SystemPartition->IsPartitioned);
2437
2438 /* Reset the filesystem list for each partition that is to be formatted */
2440
2441 PreviousFormatState = FormatState;
2442 switch (FormatState)
2443 {
2444 case Start:
2445 {
2446 /*
2447 * We start by formatting the system partition in case it is new
2448 * (it didn't exist before) and is not the same as the installation
2449 * partition. Otherwise we just require a filesystem check on it,
2450 * and start by formatting the installation partition instead.
2451 */
2452
2454
2457 {
2460
2461 // TODO: Should we let the user using a custom file-system,
2462 // or should we always use FAT(32) for it?
2463 // For "compatibility", FAT(32) would be best indeed.
2464
2466 DPRINT1("FormatState: Start --> FormatSystemPartition\n");
2467 }
2468 else
2469 {
2472
2474 {
2475 /* The system partition is separate, so it had better be formatted! */
2478
2479 /* Require a filesystem check on the system partition too */
2481 }
2482
2484 DPRINT1("FormatState: Start --> FormatInstallPartition\n");
2485 }
2486 break;
2487 }
2488
2490 {
2493
2495 DPRINT1("FormatState: FormatSystemPartition --> FormatInstallPartition\n");
2496 break;
2497 }
2498
2501 {
2503 NULL,
2504 &TempPartition))
2505 {
2508
2510 DPRINT1("FormatState: FormatInstallPartition --> FormatOtherPartition\n");
2511 else
2512 DPRINT1("FormatState: FormatOtherPartition --> FormatOtherPartition\n");
2513 }
2514 else
2515 {
2517
2519 DPRINT1("FormatState: FormatInstallPartition --> FormatDone\n");
2520 else
2521 DPRINT1("FormatState: FormatOtherPartition --> FormatDone\n");
2522
2524 }
2525 break;
2526 }
2527
2528 case FormatDone:
2529 {
2530 DPRINT1("FormatState: FormatDone\n");
2532 }
2533
2534 default:
2535 {
2536 DPRINT1("FormatState: Invalid value %ld\n", FormatState);
2537 ASSERT(FALSE);
2538 return QUIT_PAGE;
2539 }
2540 }
2541
2542 PartEntry = TempPartition;
2543 DiskEntry = TempPartition->DiskEntry;
2544
2545 ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0);
2546
2548
2549 if (PartEntry->AutoCreate)
2550 {
2551 PartEntry->AutoCreate = FALSE;
2552
2554 }
2555 else if (PartEntry->New)
2556 {
2557 switch (FormatState)
2558 {
2561 break;
2562
2565 break;
2566
2569 break;
2570
2571 default:
2572 ASSERT(FALSE);
2573 break;
2574 }
2575 }
2576 else
2577 {
2579 }
2580
2581 PartitionDescription(PartEntry, LineBuffer, ARRAYSIZE(LineBuffer));
2582 CONSOLE_SetTextXY(6, 10, LineBuffer);
2583
2584 DiskDescription(DiskEntry, LineBuffer, ARRAYSIZE(LineBuffer));
2586 LineBuffer);
2587
2588 /* Show "This Partition will be formatted next" only if it is unformatted */
2589 if (PartEntry->New || PartEntry->FormatState == Unformatted)
2591
2593
2595 {
2597
2598 switch (USetupData.FsType)
2599 {
2600 /* 1 is for BtrFS */
2601 case 1:
2602 DefaultFs = L"BTRFS";
2603 break;
2604
2605 /* If we don't understand input, default to FAT */
2606 default:
2607 DefaultFs = L"FAT";
2608 break;
2609 }
2610 }
2611 else
2612 {
2613 /* By default select the "FAT" file system */
2614 DefaultFs = L"FAT";
2615 }
2616
2617 /* Create the file system list */
2618 // TODO: Display only the FSes compatible with the selected partition!
2620 PartEntry->New ||
2621 PartEntry->FormatState == Unformatted,
2622 DefaultFs);
2623 if (FileSystemList == NULL)
2624 {
2625 /* FIXME: show an error dialog */
2626 return QUIT_PAGE;
2627 }
2628
2630 {
2632 return FORMAT_PARTITION_PAGE;
2633 }
2634
2636
2637 while (TRUE)
2638 {
2639 CONSOLE_ConInKey(Ir);
2640
2641 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2642 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
2643 {
2644 if (ConfirmQuit(Ir))
2645 {
2646 /* Reset the filesystem list */
2648 return QUIT_PAGE;
2649 }
2650
2651 break;
2652 }
2653 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESC */
2654 {
2655 /* Reset the formatter machine state */
2658
2659 /* Reset the filesystem list */
2661
2662 return SELECT_PARTITION_PAGE;
2663 }
2664 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2665 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
2666 {
2668 }
2669 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2670 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
2671 {
2673 }
2674 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
2675 {
2677 {
2679
2680 /*
2681 * Skip formatting this partition. We will also ignore
2682 * filesystem checks on it, unless it is either the system
2683 * or the installation partition.
2684 */
2687 {
2688 PartEntry->NeedsCheck = FALSE;
2689 }
2690
2692 }
2693 else
2694 {
2695 /* Format this partition */
2696 return FORMAT_PARTITION_PAGE;
2697 }
2698 }
2699 }
2700
2701 FormatState = PreviousFormatState;
2702
2704}
2705
2706
2707/*
2708 * Displays the FormatPartitionPage.
2709 *
2710 * Next pages:
2711 * InstallDirectoryPage (At once if IsUnattendedSetup or InstallShortcut)
2712 * SelectPartitionPage (At once)
2713 * QuitPage
2714 *
2715 * SIDEEFFECTS
2716 * Sets InstallPartition->FormatState
2717 * Sets USetupData.DestinationRootPath
2718 *
2719 * RETURNS
2720 * Number of the next page.
2721 */
2722static PAGE_NUMBER
2724{
2726 PPARTENTRY PartEntry;
2727 PDISKENTRY DiskEntry;
2728 PFILE_SYSTEM_ITEM SelectedFileSystem;
2729 WCHAR PathBuffer[MAX_PATH];
2731
2732 DPRINT("FormatPartitionPage()\n");
2733
2734 if (PartitionList == NULL || TempPartition == NULL)
2735 {
2736 /* FIXME: show an error dialog */
2737 return QUIT_PAGE;
2738 }
2739
2740 PartEntry = TempPartition;
2741 DiskEntry = TempPartition->DiskEntry;
2742
2743 ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0);
2744
2745 SelectedFileSystem = FileSystemList->Selected;
2746 ASSERT(SelectedFileSystem && SelectedFileSystem->FileSystem);
2747
2749
2751 CONSOLE_SetTextXY(6, 10, Buffer);
2752
2753 DiskDescription(DiskEntry, Buffer, ARRAYSIZE(Buffer));
2755 Buffer);
2756
2757 while (TRUE)
2758 {
2759 if (!IsUnattendedSetup)
2760 CONSOLE_ConInKey(Ir);
2761
2762 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2763 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
2764 {
2765 if (ConfirmQuit(Ir))
2766 {
2767 /* Reset the filesystem list */
2769 return QUIT_PAGE;
2770 }
2771
2772 break;
2773 }
2774 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN || IsUnattendedSetup) /* ENTER */
2775 {
2776 /*
2777 * Remove the "Press ENTER to continue" message prompt when the ENTER
2778 * key is pressed as the user wants to begin the partition formatting.
2779 */
2782
2783 /* Format the partition */
2784 Status = DoFormat(PartEntry,
2785 SelectedFileSystem->FileSystem,
2786 SelectedFileSystem->QuickFormat);
2788 {
2790
2791 /* Reset the filesystem list */
2793 return QUIT_PAGE;
2794 }
2796 {
2797 /* FIXME: show an error dialog */
2798 // MUIDisplayError(ERROR_FORMATTING_PARTITION, Ir, POPUP_WAIT_ANY_KEY, PathBuffer);
2799
2800 /* Reset the filesystem list */
2802 return QUIT_PAGE;
2803 }
2804 else if (Status == STATUS_NOT_SUPPORTED)
2805 {
2807 sizeof(Buffer),
2808 "Setup is currently unable to format a partition in %S.\n"
2809 "\n"
2810 " \x07 Press ENTER to continue Setup.\n"
2811 " \x07 Press F3 to quit Setup.",
2812 SelectedFileSystem->FileSystem);
2813
2817
2818 while (TRUE)
2819 {
2820 CONSOLE_ConInKey(Ir);
2821
2822 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x00 &&
2823 Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3) /* F3 */
2824 {
2825 if (ConfirmQuit(Ir))
2826 {
2827 /* Reset the filesystem list */
2829 return QUIT_PAGE;
2830 }
2831 else
2832 {
2834 }
2835 }
2836 else if (Ir->Event.KeyEvent.uChar.AsciiChar == VK_RETURN) /* ENTER */
2837 {
2839 }
2840 }
2841 }
2842 else if (!NT_SUCCESS(Status))
2843 {
2845 RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
2846 L"\\Device\\Harddisk%lu\\Partition%lu",
2847 DiskEntry->DiskNumber,
2848 PartEntry->PartitionNumber);
2849
2850 DPRINT1("DoFormat() failed: Status 0x%08lx\n", Status);
2852
2853 /* Reset the filesystem list */
2855 return QUIT_PAGE;
2856 }
2857
2859 }
2860 }
2861
2862 return FORMAT_PARTITION_PAGE;
2863}
2864
2865
2866/*
2867 * Displays the CheckFileSystemPage.
2868 *
2869 * Next pages:
2870 * InstallDirectoryPage (At once)
2871 * QuitPage
2872 *
2873 * SIDEEFFECTS
2874 * Inits or reloads FileSystemList
2875 *
2876 * RETURNS
2877 * Number of the next page.
2878 */
2879static PAGE_NUMBER
2881{
2883 PPARTENTRY PartEntry;
2885
2886 if (PartitionList == NULL)
2887 {
2888 /* FIXME: show an error dialog */
2889 return QUIT_PAGE;
2890 }
2891
2892 if (!GetNextUncheckedPartition(PartitionList, NULL, &PartEntry))
2893 {
2895 }
2896
2897 ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0);
2898
2899 DPRINT1("CheckFileSystemPage -- PartitionType: 0x%02X ; FileSystem: %S\n",
2900 PartEntry->PartitionType, (*PartEntry->FileSystem ? PartEntry->FileSystem : L"n/a"));
2901
2903
2905 CONSOLE_SetTextXY(6, 10, Buffer);
2906
2909 Buffer);
2910
2911 /* Check the partition */
2912 Status = DoChkdsk(PartEntry);
2914 {
2915 /*
2916 * Partition checking is not supported with the current filesystem,
2917 * so disable FS checks on it.
2918 */
2919 PartEntry->NeedsCheck = FALSE;
2920
2922 sizeof(Buffer),
2923 "Setup is currently unable to check a partition formatted in %S.\n"
2924 "\n"
2925 " \x07 Press ENTER to continue Setup.\n"
2926 " \x07 Press F3 to quit Setup.",
2927 PartEntry->FileSystem);
2928
2932
2933 while (TRUE)
2934 {
2935 CONSOLE_ConInKey(Ir);
2936
2937 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x00 &&
2938 Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3) /* F3 */
2939 {
2940 if (ConfirmQuit(Ir))
2941 return QUIT_PAGE;
2942 else
2944 }
2945 else if (Ir->Event.KeyEvent.uChar.AsciiChar == VK_RETURN) /* ENTER */
2946 {
2948 }
2949 }
2950 }
2951 else if (!NT_SUCCESS(Status))
2952 {
2953 DPRINT1("DoChkdsk() failed: Status 0x%08lx\n", Status);
2954
2956 sizeof(Buffer),
2957 "ChkDsk detected some disk errors.\n(Status 0x%08lx).\n",
2958 Status);
2959
2962 Ir, POPUP_WAIT_ENTER);
2963 }
2964
2965 PartEntry->NeedsCheck = FALSE;
2967}
2968
2969
2970static BOOLEAN
2972 IN PCWSTR InstallDir)
2973{
2974 UINT i, Length;
2975
2976 Length = wcslen(InstallDir);
2977
2978 // TODO: Add check for 8.3 too.
2979
2980 /* Path must be at least 2 characters long */
2981// if (Length < 2)
2982// return FALSE;
2983
2984 /* Path must start with a backslash */
2985// if (InstallDir[0] != L'\\')
2986// return FALSE;
2987
2988 /* Path must not end with a backslash */
2989 if (InstallDir[Length - 1] == L'\\')
2990 return FALSE;
2991
2992 /* Path must not contain whitespace characters */
2993 for (i = 0; i < Length; i++)
2994 {
2995 if (iswspace(InstallDir[i]))
2996 return FALSE;
2997 }
2998
2999 /* Path component must not end with a dot */
3000 for (i = 0; i < Length; i++)
3001 {
3002 if (InstallDir[i] == L'\\' && i > 0)
3003 {
3004 if (InstallDir[i - 1] == L'.')
3005 return FALSE;
3006 }
3007 }
3008
3009 if (InstallDir[Length - 1] == L'.')
3010 return FALSE;
3011
3012 return TRUE;
3013}
3014
3015
3016/*
3017 * Displays the InstallDirectoryPage.
3018 *
3019 * Next pages:
3020 * PrepareCopyPage
3021 * QuitPage
3022 *
3023 * RETURNS
3024 * Number of the next page.
3025 */
3026static PAGE_NUMBER
3028{
3030 ULONG Length, Pos;
3031 WCHAR c;
3032 WCHAR InstallDir[MAX_PATH];
3033
3034 /* We do not need the filesystem list anymore */
3036
3038 {
3039 /* FIXME: show an error dialog */
3040 return QUIT_PAGE;
3041 }
3042
3043 // if (IsUnattendedSetup)
3044 if (RepairUpdateFlag)
3045 wcscpy(InstallDir, CurrentInstallation->PathComponent); // SystemNtPath
3048 else
3049 wcscpy(InstallDir, L"\\ReactOS");
3050
3051 /*
3052 * Check the validity of the predefined 'InstallDir'. If we are either
3053 * in unattended setup or in update/repair mode, and the installation path
3054 * is valid, just perform the installation. Otherwise (either in the case
3055 * of an invalid path, or we are in regular setup), display the UI and allow
3056 * the user to specify a new installation path.
3057 */
3058 if ((RepairUpdateFlag || IsUnattendedSetup) && IsValidPath(InstallDir))
3059 {
3061 if (!NT_SUCCESS(Status))
3062 {
3063 DPRINT1("InitDestinationPaths() failed: Status 0x%lx\n", Status);
3065 return QUIT_PAGE;
3066 }
3067
3068 /*
3069 * Check whether the user attempts to install ReactOS within the
3070 * installation source directory, or in a subdirectory thereof.
3071 * If so, fail with an error.
3072 */
3074 {
3077 }
3078
3079 return PREPARE_COPY_PAGE;
3080 }
3081
3082 Length = wcslen(InstallDir);
3083 Pos = Length;
3084
3086 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
3087 CONSOLE_SetCursorXY(8 + Pos, 11);
3089
3090 while (TRUE)
3091 {
3092 CONSOLE_ConInKey(Ir);
3093
3094 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3095 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
3096 {
3098
3099 if (ConfirmQuit(Ir))
3100 return QUIT_PAGE;
3101
3103 break;
3104 }
3105 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3106 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DELETE)) /* DEL */
3107 {
3108 if (Pos < Length)
3109 {
3110 memmove(&InstallDir[Pos],
3111 &InstallDir[Pos + 1],
3112 (Length - Pos - 1) * sizeof(WCHAR));
3113 InstallDir[Length - 1] = UNICODE_NULL;
3114
3115 Length--;
3116 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
3117 CONSOLE_SetCursorXY(8 + Pos, 11);
3118 }
3119 }
3120 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3121 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_HOME)) /* HOME */
3122 {
3123 Pos = 0;
3124 CONSOLE_SetCursorXY(8 + Pos, 11);
3125 }
3126 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3127 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_END)) /* END */
3128 {
3129 Pos = Length;
3130 CONSOLE_SetCursorXY(8 + Pos, 11);
3131 }
3132 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3133 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_LEFT)) /* LEFT */
3134 {
3135 if (Pos > 0)
3136 {
3137 Pos--;
3138 CONSOLE_SetCursorXY(8 + Pos, 11);
3139 }
3140 }
3141 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3142 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RIGHT)) /* RIGHT */
3143 {
3144 if (Pos < Length)
3145 {
3146 Pos++;
3147 CONSOLE_SetCursorXY(8 + Pos, 11);
3148 }
3149 }
3150 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
3151 {
3153
3154 /*
3155 * Check for the validity of the installation directory and pop up
3156 * an error if it is not the case. Then the user can fix its input.
3157 */
3158 if (!IsValidPath(InstallDir))
3159 {
3162 }
3163
3165 if (!NT_SUCCESS(Status))
3166 {
3167 DPRINT1("InitDestinationPaths() failed: Status 0x%lx\n", Status);
3169 return QUIT_PAGE;
3170 }
3171
3172 /*
3173 * Check whether the user attempts to install ReactOS within the
3174 * installation source directory, or in a subdirectory thereof.
3175 * If so, fail with an error.
3176 */
3178 {
3181 }
3182
3183 return PREPARE_COPY_PAGE;
3184 }
3185 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x08) /* BACKSPACE */
3186 {
3187 if (Pos > 0)
3188 {
3189 if (Pos < Length)
3190 memmove(&InstallDir[Pos - 1],
3191 &InstallDir[Pos],
3192 (Length - Pos) * sizeof(WCHAR));
3193 InstallDir[Length - 1] = UNICODE_NULL;
3194
3195 Pos--;
3196 Length--;
3197 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
3198 CONSOLE_SetCursorXY(8 + Pos, 11);
3199 }
3200 }
3201 else if (isprint(Ir->Event.KeyEvent.uChar.AsciiChar))
3202 {
3203 if (Length < 50)
3204 {
3206 if (iswalpha(c) || iswdigit(c) || c == '.' || c == '\\' || c == '-' || c == '_')
3207 {
3208 if (Pos < Length)
3209 memmove(&InstallDir[Pos + 1],
3210 &InstallDir[Pos],
3211 (Length - Pos) * sizeof(WCHAR));
3212 InstallDir[Length + 1] = UNICODE_NULL;
3213 InstallDir[Pos] = c;
3214
3215 Pos++;
3216 Length++;
3217 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
3218 CONSOLE_SetCursorXY(8 + Pos, 11);
3219 }
3220 }
3221 }
3222 }
3223
3225}
3226
3227
3228// PSETUP_ERROR_ROUTINE
3229static VOID
3230__cdecl
3232 IN PUSETUP_DATA pSetupData,
3233 ...)
3234{
3235 INPUT_RECORD Ir;
3236 va_list arg_ptr;
3237
3238 va_start(arg_ptr, pSetupData);
3239
3240 if (pSetupData->LastErrorNumber >= ERROR_SUCCESS &&
3241 pSetupData->LastErrorNumber < ERROR_LAST_ERROR_CODE)
3242 {
3243 // Note: the "POPUP_WAIT_ENTER" actually depends on the LastErrorNumber...
3244 MUIDisplayErrorV(pSetupData->LastErrorNumber, &Ir, POPUP_WAIT_ENTER, arg_ptr);
3245 }
3246
3247 va_end(arg_ptr);
3248}
3249
3250/*
3251 * Displays the PrepareCopyPage.
3252 *
3253 * Next pages:
3254 * FileCopyPage(At once)
3255 * QuitPage
3256 *
3257 * SIDEEFFECTS
3258 * Calls PrepareFileCopy
3259 *
3260 * RETURNS
3261 * Number of the next page.
3262 */
3263static PAGE_NUMBER
3265{
3266 // ERROR_NUMBER ErrorNumber;
3268
3270
3271 /* ErrorNumber = */ Success = PrepareFileCopy(&USetupData, NULL);
3272 if (/*ErrorNumber != ERROR_SUCCESS*/ !Success)
3273 {
3274 // MUIDisplayError(ErrorNumber, Ir, POPUP_WAIT_ENTER);
3275 return QUIT_PAGE;
3276 }
3277
3278 return FILE_COPY_PAGE;
3279}
3280
3281typedef struct _COPYCONTEXT
3282{
3288
3289static VOID
3292{
3294
3295 /* Get the memory information from the system */
3297 &PerfInfo,
3298 sizeof(PerfInfo),
3299 NULL);
3300
3301 /* Check if this is initial setup */
3302 if (First)
3303 {
3304 /* Set maximum limits to be total RAM pages */
3305 ProgressSetStepCount(CopyContext->MemoryBars[0], PerfInfo.CommitLimit);
3306 ProgressSetStepCount(CopyContext->MemoryBars[1], PerfInfo.CommitLimit);
3307 ProgressSetStepCount(CopyContext->MemoryBars[2], PerfInfo.CommitLimit);
3308 }
3309
3310 /* Set current values */
3311 ProgressSetStep(CopyContext->MemoryBars[0], PerfInfo.PagedPoolPages + PerfInfo.NonPagedPoolPages);
3312 ProgressSetStep(CopyContext->MemoryBars[1], PerfInfo.ResidentSystemCachePage);
3313 ProgressSetStep(CopyContext->MemoryBars[2], PerfInfo.AvailablePages);
3314}
3315
3316static UINT
3320 UINT_PTR Param1,
3321 UINT_PTR Param2)
3322{
3323 PCOPYCONTEXT CopyContext = (PCOPYCONTEXT)Context;
3324 PFILEPATHS_W FilePathInfo;
3325 PCWSTR SrcFileName, DstFileName;
3326
3327 switch (Notification)
3328 {
3330 {
3331 CopyContext->TotalOperations = (ULONG)Param2;
3332 CopyContext->CompletedOperations = 0;
3333 ProgressSetStepCount(CopyContext->ProgressBar,
3334 CopyContext->TotalOperations);
3335 SetupUpdateMemoryInfo(CopyContext, TRUE);
3336 break;
3337 }
3338
3342 {
3343 FilePathInfo = (PFILEPATHS_W)Param1;
3344
3346 {
3347 /* Display delete message */
3348 ASSERT(Param2 == FILEOP_DELETE);
3349
3350 DstFileName = wcsrchr(FilePathInfo->Target, L'\\');
3351 if (DstFileName) ++DstFileName;
3352 else DstFileName = FilePathInfo->Target;
3353
3355 DstFileName);
3356 }
3358 {
3359 /* Display move/rename message */
3360 ASSERT(Param2 == FILEOP_RENAME);
3361
3362 SrcFileName = wcsrchr(FilePathInfo->Source, L'\\');
3363 if (SrcFileName) ++SrcFileName;
3364 else SrcFileName = FilePathInfo->Source;
3365
3366 DstFileName = wcsrchr(FilePathInfo->Target, L'\\');
3367 if (DstFileName) ++DstFileName;
3368 else DstFileName = FilePathInfo->Target;
3369
3370 if (!wcsicmp(SrcFileName, DstFileName))
3371 Param2 = STRING_MOVING;
3372 else
3373 Param2 = STRING_RENAMING;
3374
3376 SrcFileName, DstFileName);
3377 }
3379 {
3380 static PCSTR s_pszCopying = NULL; /* Cached for speed */
3381
3382 /* Display copy message */
3383 ASSERT(Param2 == FILEOP_COPY);
3384
3385 /* NOTE: When extracting from CABs the Source is the CAB name */
3386 DstFileName = wcsrchr(FilePathInfo->Target, L'\\');
3387 if (DstFileName) ++DstFileName;
3388 else DstFileName = FilePathInfo->Target;
3389
3390 if (!s_pszCopying)
3391 s_pszCopying = MUIGetString(STRING_COPYING);
3392 CONSOLE_SetStatusText(s_pszCopying, DstFileName);
3393#ifdef __REACTOS__ /* HACK */
3394 DoWatchDestFileName(DstFileName);
3395#endif
3396 }
3397
3398 SetupUpdateMemoryInfo(CopyContext, FALSE);
3399 break;
3400 }
3401
3403 {
3404 FilePathInfo = (PFILEPATHS_W)Param1;
3405
3406 DPRINT1("An error happened while trying to copy file '%S' (error 0x%08lx), skipping it...\n",
3407 FilePathInfo->Target, FilePathInfo->Win32Error);
3408 return FILEOP_SKIP;
3409 }
3410
3414 {
3415 CopyContext->CompletedOperations++;
3416
3417 /* SYSREG checkpoint */
3418 if (CopyContext->TotalOperations >> 1 == CopyContext->CompletedOperations)
3419 DPRINT1("CHECKPOINT:HALF_COPIED\n");
3420
3421 ProgressNextStep(CopyContext->ProgressBar);
3422 SetupUpdateMemoryInfo(CopyContext, FALSE);
3423 break;
3424 }
3425 }
3426
3427 return FILEOP_DOIT;
3428}
3429
3430
3431/*
3432 * Displays the FileCopyPage.
3433 *
3434 * Next pages:
3435 * RegistryPage(At once)
3436 *
3437 * SIDEEFFECTS
3438 * Calls DoFileCopy
3439 *
3440 * RETURNS
3441 * Number of the next page.
3442 */
3443static PAGE_NUMBER
3445{
3446 COPYCONTEXT CopyContext;
3447 UINT MemBarWidth;
3448
3450
3451 /* Create context for the copy process */
3452 CopyContext.TotalOperations = 0;
3453 CopyContext.CompletedOperations = 0;
3454
3455 /* Create the progress bar as well */
3456 CopyContext.ProgressBar = CreateProgressBar(13,
3457 26,
3458 xScreen - 13,
3459 yScreen - 20,
3460 10,
3461 24,
3462 TRUE,
3464
3465 // fit memory bars to screen width, distribute them uniform
3466 MemBarWidth = (xScreen - 26) / 5;
3467 MemBarWidth -= MemBarWidth % 2; // make even
3468 /* ATTENTION: The following progress bars are debug stuff, which should not be translated!! */
3469 /* Create the paged pool progress bar */
3470 CopyContext.MemoryBars[0] = CreateProgressBar(13,
3471 40,
3472 13 + MemBarWidth,
3473 43,
3474 13,
3475 44,
3476 FALSE,
3477 "Kernel Pool");
3478
3479 /* Create the non paged pool progress bar */
3480 CopyContext.MemoryBars[1] = CreateProgressBar((xScreen / 2)- (MemBarWidth / 2),
3481 40,
3482 (xScreen / 2) + (MemBarWidth / 2),
3483 43,
3484 (xScreen / 2)- (MemBarWidth / 2),
3485 44,
3486 FALSE,
3487 "Kernel Cache");
3488
3489 /* Create the global memory progress bar */
3490 CopyContext.MemoryBars[2] = CreateProgressBar(xScreen - 13 - MemBarWidth,
3491 40,
3492 xScreen - 13,
3493 43,
3494 xScreen - 13 - MemBarWidth,
3495 44,
3496 FALSE,
3497 "Free Memory");
3498
3499 /* Do the file copying */
3500 DoFileCopy(&USetupData, FileCopyCallback, &CopyContext);
3501
3502 /* If we get here, we're done, so cleanup the progress bar */
3503 DestroyProgressBar(CopyContext.ProgressBar);
3504 DestroyProgressBar(CopyContext.MemoryBars[0]);
3505 DestroyProgressBar(CopyContext.MemoryBars[1]);
3506 DestroyProgressBar(CopyContext.MemoryBars[2]);
3507
3508 /* Create the $winnt$.inf file */
3510
3511 /* Go display the next page */
3512 return REGISTRY_PAGE;
3513}
3514
3515
3516static VOID
3517__cdecl
3519{
3520 /* WARNING: Please keep this lookup table in sync with the resources! */
3521 static const UINT StringIDs[] =
3522 {
3523 STRING_DONE, /* Success */
3524 STRING_REGHIVEUPDATE, /* RegHiveUpdate */
3525 STRING_IMPORTFILE, /* ImportRegHive */
3526 STRING_DISPLAYSETTINGSUPDATE, /* DisplaySettingsUpdate */
3527 STRING_LOCALESETTINGSUPDATE, /* LocaleSettingsUpdate */
3528 STRING_ADDKBLAYOUTS, /* KeybLayouts */
3529 STRING_KEYBOARDSETTINGSUPDATE, /* KeybSettingsUpdate */
3530 STRING_CODEPAGEINFOUPDATE, /* CodePageInfoUpdate */
3531 };
3532
3533 va_list args;
3534
3535 if (RegStatus < ARRAYSIZE(StringIDs))
3536 {
3537 va_start(args, RegStatus);
3538 CONSOLE_SetStatusTextV(MUIGetString(StringIDs[RegStatus]), args);
3539 va_end(args);
3540 }
3541 else
3542 {
3543 CONSOLE_SetStatusText("Unknown status %d", RegStatus);
3544 }
3545}
3546
3547/*
3548 * Displays the RegistryPage.
3549 *
3550 * Next pages:
3551 * BootLoaderSelectPage
3552 * QuitPage
3553 *
3554 * SIDEEFFECTS
3555 * Calls UpdateRegistry
3556 *
3557 * RETURNS
3558 * Number of the next page.
3559 */
3560static PAGE_NUMBER
3562{
3563 ULONG Error;
3564
3566
3573 &s_SubstSettings);
3574 if (Error != ERROR_SUCCESS)
3575 {
3577 return QUIT_PAGE;
3578 }
3579 else
3580 {
3583 }
3584}
3585
3586
3587/*
3588 * Displays the BootLoaderSelectPage.
3589 *
3590 * Next pages:
3591 * SuccessPage
3592 * QuitPage
3593 *
3594 * RETURNS
3595 * Number of the next page.
3596 */
3597static PAGE_NUMBER
3599{
3600 USHORT Line = 12;
3601
3603
3604 /* We must have a supported system partition by now */
3606
3607 /*
3608 * If we repair an existing installation and we made it up to here,
3609 * this means a valid bootloader and boot entry have been found.
3610 * Thus, there is no need to re-install it: skip its installation.
3611 */
3612 if (RepairUpdateFlag)
3613 {
3615 goto Quit;
3616 }
3617
3618 /* For unattended setup, skip MBR installation or install on removable disk if needed */
3620 {
3621 if ((USetupData.MBRInstallType == 0) ||
3623 {
3624 goto Quit;
3625 }
3626 }
3627
3628 /*
3629 * We may install an MBR or VBR, but before that, check whether
3630 * we need to actually install the VBR on removable disk if the
3631 * system partition is not recognized.
3632 */
3633 if ((SystemPartition->DiskEntry->DiskStyle != PARTITION_STYLE_MBR) ||
3635 {
3637 goto Quit;
3638 }
3639
3640 /* Is it an unattended install on hdd? */
3642 {
3643 if ((USetupData.MBRInstallType == 2) ||
3645 {
3646 goto Quit;
3647 }
3648 }
3649
3651 CONSOLE_InvertTextXY(8, Line, 60, 1);
3652
3653 while (TRUE)
3654 {
3655 CONSOLE_ConInKey(Ir);
3656
3657 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3658 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
3659 {
3660 CONSOLE_NormalTextXY(8, Line, 60, 1);
3661
3662 Line++;
3663 if (Line < 12)
3664 Line = 15;
3665
3666 if (Line > 15)
3667 Line = 12;
3668
3669 CONSOLE_InvertTextXY(8, Line, 60, 1);
3670 }
3671 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3672 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
3673 {
3674 CONSOLE_NormalTextXY(8, Line, 60, 1);
3675
3676 Line--;
3677 if (Line < 12)
3678 Line = 15;
3679
3680 if (Line > 15)
3681 Line = 12;
3682
3683 CONSOLE_InvertTextXY(8, Line, 60, 1);
3684 }
3685 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3686 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_HOME)) /* HOME */
3687 {
3688 CONSOLE_NormalTextXY(8, Line, 60, 1);
3689
3690 Line = 12;
3691
3692 CONSOLE_InvertTextXY(8, Line, 60, 1);
3693 }
3694 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3695 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_END)) /* END */
3696 {
3697 CONSOLE_NormalTextXY(8, Line, 60, 1);
3698
3699 Line = 15;
3700
3701 CONSOLE_InvertTextXY(8, Line, 60, 1);
3702 }
3703 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3704 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
3705 {
3706 if (ConfirmQuit(Ir))
3707 return QUIT_PAGE;
3708
3709 break;
3710 }
3711 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
3712 {
3713 if (Line == 12)
3714 {
3715 /* Install on both MBR and VBR */
3717 break;
3718 }
3719 else if (Line == 13)
3720 {
3721 /* Install on VBR only */
3723 break;
3724 }
3725 else if (Line == 14)
3726 {
3727 /* Install on removable disk */
3729 break;
3730 }
3731 else if (Line == 15)
3732 {
3733 /* Skip installation */
3735 break;
3736 }
3737
3739 }
3740 }
3741
3742Quit:
3743 /* Continue the installation; the bootloader is installed at the end */
3745}
3746
3747
3748/*
3749 * Installs the bootloader on removable disk.
3750 */
3751static BOOLEAN
3753{
3755
3756Retry:
3758 CONSOLE_Flush();
3760// CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
3761
3762 while (TRUE)
3763 {
3764 CONSOLE_ConInKey(Ir);
3765
3766 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3767 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
3768 {
3769 if (ConfirmQuit(Ir))
3770 return FALSE;
3771
3772 break;
3773 }
3774 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
3775 {
3778 if (!NT_SUCCESS(Status))
3779 {
3782
3783 /* TODO: Print error message */
3784 goto Retry;
3785 }
3786
3787 return TRUE;
3788 }
3789 }
3790
3791 goto Retry;
3792}
3793
3794/*
3795 * Installs the bootloader on hard-disk.
3796 */
3797static BOOLEAN
3799{
3801 WCHAR DestinationDevicePathBuffer[MAX_PATH];
3802
3803 if (USetupData.MBRInstallType == 2)
3804 {
3805 /* Step 1: Write the VBR */
3810 if (!NT_SUCCESS(Status))
3811 {
3814 return FALSE;
3815 }
3816
3817 /* Step 2: Write the MBR if the disk containing the system partition is not a super-floppy */
3819 {
3820 RtlStringCchPrintfW(DestinationDevicePathBuffer, ARRAYSIZE(DestinationDevicePathBuffer),
3821 L"\\Device\\Harddisk%d\\Partition0",
3822 SystemPartition->DiskEntry->DiskNumber);
3825 DestinationDevicePathBuffer);
3826 if (!NT_SUCCESS(Status))
3827 {
3828 DPRINT1("InstallMbrBootCodeToDisk() failed: Status 0x%lx\n", Status);
3830 return FALSE;
3831 }
3832 }
3833 }
3834 else
3835 {
3840 if (!NT_SUCCESS(Status))
3841 {
3844 return FALSE;
3845 }
3846 }
3847
3848 return TRUE;
3849}
3850
3851/*
3852 * Actually installs the bootloader at the end of the installation.
3853 * The bootloader installation place has already been chosen before,
3854 * see BootLoaderSelectPage().
3855 *
3856 * Next pages:
3857 * SuccessPage (At once)
3858 * QuitPage
3859 *
3860 * RETURNS
3861 * Number of the next page.
3862 */
3863static PAGE_NUMBER
3865{
3866 WCHAR PathBuffer[MAX_PATH];
3867
3868 // /* We must have a supported system partition by now */
3869 // ASSERT(SystemPartition && SystemPartition->IsPartitioned && SystemPartition->PartitionNumber != 0);
3870
3872 RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
3873 L"\\Device\\Harddisk%lu\\Partition%lu\\",
3874 SystemPartition->DiskEntry->DiskNumber,
3877 DPRINT1("SystemRootPath: %wZ\n", &USetupData.SystemRootPath);
3878
3879 if (USetupData.MBRInstallType != 0)
3881
3882 switch (USetupData.MBRInstallType)
3883 {
3884 /* Skip installation */
3885 case 0:
3886 return SUCCESS_PAGE;
3887
3888 /* Install on removable disk */
3889 case 1:
3891
3892 /* Install on hard-disk (both MBR and VBR, or VBR only) */
3893 case 2:
3894 case 3:
3896
3897 default:
3898 return SUCCESS_PAGE;
3899 }
3900}
3901
3902
3925static
3929 IN BOOLEAN AlwaysUpdate,
3930 OUT PSTR Buffer,
3931 IN SIZE_T cchBufferSize)
3932{
3933 ULONG OldProgress = Bar->Progress;
3934
3935 if (Bar->StepCount == 0)
3936 {
3937 Bar->Progress = 0;
3938 }
3939 else
3940 {
3941 Bar->Progress = Bar->StepCount - Bar->CurrentStep;
3942 }
3943
3944 /* Build the progress string if it has changed */
3945 if (Bar->ProgressFormatText &&
3946 (AlwaysUpdate || (Bar->Progress != OldProgress)))
3947 {
3948 RtlStringCchPrintfA(Buffer, cchBufferSize,
3949 Bar->ProgressFormatText, Bar->Progress / max(1, Bar->Width) + 1);
3950
3951 return TRUE;
3952 }
3953
3954 return FALSE;
3955}
3956
3973static VOID
3975 IN PINPUT_RECORD Ir,
3976 IN LONG TimeOut)
3977{
3979 ULONG StartTime, BarWidth, TimerDiv;
3980 LONG TimeElapsed;
3981 LONG TimerValue, OldTimerValue;
3983 PPROGRESSBAR ProgressBar;
3984 BOOLEAN RefreshProgress = TRUE;
3985
3986 /* Bail out if the timeout is already zero */
3987 if (TimeOut <= 0)
3988 return;
3989
3990 /* Create the timeout progress bar and set it up */
3991 ProgressBar = CreateProgressBarEx(13,
3992 26,
3993 xScreen - 13,
3994 yScreen - 20,
3995 10,
3996 24,
3997 TRUE,
3999 0,
4000 NULL,
4003
4004 BarWidth = max(1, ProgressBar->Width);
4005 TimerValue = TimeOut * BarWidth;
4006 ProgressSetStepCount(ProgressBar, TimerValue);
4007
4009 CONSOLE_Flush();
4010
4011 TimerDiv = 1000 / BarWidth;
4012 TimerDiv = max(1, TimerDiv);
4013 OldTimerValue = TimerValue;
4014 while (TRUE)
4015 {
4016 /* Decrease the timer */
4017
4018 /*
4019 * Compute how much time the previous operations took.
4020 * This allows us in particular to take account for any time
4021 * elapsed if something slowed down.
4022 */
4023 TimeElapsed = NtGetTickCount() - StartTime;
4024 if (TimeElapsed >= TimerDiv)
4025 {
4026 /* Increase StartTime by steps of 1 / ProgressBar->Width seconds */
4027 TimeElapsed /= TimerDiv;
4028 StartTime += (TimerDiv * TimeElapsed);
4029
4030 if (TimeElapsed <= TimerValue)
4031 TimerValue -= TimeElapsed;
4032 else
4033 TimerValue = 0;
4034
4035 RefreshProgress = TRUE;
4036 }
4037
4038 if (RefreshProgress)
4039 {
4040 ProgressSetStep(ProgressBar, OldTimerValue - TimerValue);
4041 RefreshProgress = FALSE;
4042 }
4043
4044 /* Stop when the timer reaches zero */
4045 if (TimerValue <= 0)
4046 break;
4047
4048 /* Check for user key presses */
4049
4050 /*
4051 * If the timer is used, use a passive wait of maximum 1 second
4052 * while monitoring for incoming console input events, so that
4053 * we are still able to display the timing count.
4054 */
4055
4056 /* Wait a maximum of 1 second for input events */
4057 TimeElapsed = NtGetTickCount() - StartTime;
4058 if (TimeElapsed < TimerDiv)
4059 {
4060 /* Convert the time to NT format */
4061 Timeout.QuadPart = (TimerDiv - TimeElapsed) * -10000LL;
4063 }
4064 else
4065 {
4067 }
4068
4069 /* Check whether the input event has been signaled, or a timeout happened */
4070 if (Status == STATUS_TIMEOUT)
4071 {
4072 continue;
4073 }
4074 if (Status != STATUS_WAIT_0)
4075 {
4076 /* An error happened, bail out */
4077 DPRINT1("NtWaitForSingleObject() failed, Status 0x%08lx\n", Status);
4078 break;
4079 }
4080
4081 /* Check for an ENTER key press */
4082 while (CONSOLE_ConInKeyPeek(Ir))
4083 {
4084 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
4085 {
4086 /* Found it, stop waiting */
4087 goto Exit;
4088 }
4089 }
4090 }
4091
4092Exit:
4093 /* Destroy the progress bar and quit */
4094 DestroyProgressBar(ProgressBar);
4095}
4096
4097
4098/*
4099 * Displays the QuitPage.
4100 *
4101 * Next pages:
4102 * FlushPage (At once)
4103 *
4104 * SIDEEFFECTS
4105 * Destroy the Lists
4106 *
4107 * RETURNS
4108 * Number of the next page.
4109 */
4110static PAGE_NUMBER
4112{
4114
4115 /* Destroy the NTOS installations list */
4116 if (NtOsInstallsList != NULL)
4117 {
4120 }
4121
4122 /* Destroy the partition list */
4123 if (PartitionList != NULL)
4124 {
4127 }
4128
4129 /* Reset the formatter machine state */
4132
4133 /* Destroy the filesystem list */
4135
4137
4138 /* Wait for maximum 15 seconds or an ENTER key before quitting */
4139 ProgressCountdown(Ir, 15);
4140 return FLUSH_PAGE;
4141}
4142
4143
4144/*
4145 * Displays the SuccessPage.
4146 *
4147 * Next pages:
4148 * FlushPage (At once)
4149 *
4150 * SIDEEFFECTS
4151 * Destroy the Lists
4152 *
4153 * RETURNS
4154 * Number of the next page.
4155 */
4156static PAGE_NUMBER
4158{
4160
4162 return FLUSH_PAGE;
4163
4164 /* Wait for maximum 15 seconds or an ENTER key before quitting */
4165 ProgressCountdown(Ir, 15);
4166 return FLUSH_PAGE;
4167}
4168
4169
4170/*
4171 * Displays the FlushPage.
4172 *
4173 * Next pages:
4174 * RebootPage (At once)
4175 *
4176 * RETURNS
4177 * Number of the next page.
4178 */
4179static PAGE_NUMBER
4181{
4183 return REBOOT_PAGE;
4184}
4185
4186
4187/*
4188 * The start routine and page management
4189 */
4192{
4194 INPUT_RECORD Ir;
4196 BOOLEAN Old;
4197
4199
4200 /* Tell the Cm this is a setup boot, and it has to behave accordingly */
4202 if (!NT_SUCCESS(Status))
4203 DPRINT1("NtInitializeRegistry() failed (Status 0x%08lx)\n", Status);
4204
4205 /* Initialize the user-mode PnP manager */
4207 if (!NT_SUCCESS(Status))
4208 {
4209 // PrintString(??);
4210 DPRINT1("The user-mode PnP manager could not initialize (Status 0x%08lx), expect unavailable devices!\n", Status);
4211 }
4212
4213 if (!CONSOLE_Init())
4214 {
4218
4219 /* We failed to initialize the video, just quit the installer */
4221 }
4222
4223 /* Initialize Setup, phase 0 */
4226
4227 /* Hide the cursor and clear the screen and keyboard buffer */
4230 CONSOLE_Flush();
4231
4232 /* Global Initialization page */
4233 Page = SetupStartPage(&Ir);
4234
4235 while (Page != REBOOT_PAGE && Page != RECOVERY_PAGE)
4236 {
4238 CONSOLE_Flush();
4239
4240 // CONSOLE_SetUnderlinedTextXY(4, 3, " ReactOS " KERNEL_VERSION_STR " Setup ");
4241
4242 switch (Page)
4243 {
4244 /* Language page */
4245 case LANGUAGE_PAGE:
4246 Page = LanguagePage(&Ir);
4247 break;
4248
4249 /* Welcome page */
4250 case WELCOME_PAGE:
4251 Page = WelcomePage(&Ir);
4252 break;
4253
4254 /* License page */
4255 case LICENSE_PAGE:
4256 Page = LicensePage(&Ir);
4257 break;
4258
4259 /* Install pages */
4260 case INSTALL_INTRO_PAGE:
4261 Page = InstallIntroPage(&Ir);
4262 break;
4263
4264#if 0
4265 case SCSI_CONTROLLER_PAGE:
4266 Page = ScsiControllerPage(&Ir);
4267 break;
4268
4269 case OEM_DRIVER_PAGE:
4270 Page = OemDriverPage(&Ir);
4271 break;
4272#endif
4273
4275 Page = DeviceSettingsPage(&Ir);
4276 break;
4277
4280 break;
4281
4284 break;
4285
4288 break;
4289
4291 Page = LayoutSettingsPage(&Ir);
4292 break;
4293
4294 /* Partitioning pages */
4297 break;
4298
4301 break;
4302
4305 break;
4306
4309 break;
4310
4311 /* Filesystem partition operations pages */
4314 break;
4315
4318 break;
4319
4322 break;
4323
4324 /* Bootloader selection page */
4327 break;
4328
4329 /* Installation pages */
4332 break;
4333
4334 case PREPARE_COPY_PAGE:
4335 Page = PrepareCopyPage(&Ir);
4336 break;
4337
4338 case FILE_COPY_PAGE:
4339 Page = FileCopyPage(&Ir);
4340 break;
4341
4342 case REGISTRY_PAGE:
4343 Page = RegistryPage(&Ir);
4344 break;
4345
4346 /* Bootloader installation page */
4348 // case BOOTLOADER_REMOVABLE_DISK_PAGE:
4350 break;
4351
4352 /* Repair pages */
4353 case REPAIR_INTRO_PAGE:
4354 Page = RepairIntroPage(&Ir);
4355 break;
4356
4358 Page = UpgradeRepairPage(&Ir);
4359 break;
4360
4361 case SUCCESS_PAGE:
4362 Page = SuccessPage(&Ir);
4363 break;
4364
4365 case FLUSH_PAGE:
4366 Page = FlushPage(&Ir);
4367 break;
4368
4369 case QUIT_PAGE:
4370 Page = QuitPage(&Ir);
4371 break;
4372
4373 /* Virtual pages */
4374 case SETUP_INIT_PAGE:
4375 case REBOOT_PAGE:
4376 case RECOVERY_PAGE:
4377 break;
4378
4379 default:
4380 break;
4381 }
4382 }
4383
4384 /* Terminate the user-mode PnP manager */
4386
4387 /* Setup has finished */
4389
4390 if (Page == RECOVERY_PAGE)
4392
4393 FreeConsole();
4394
4395 /* Reboot */
4399
4400 return STATUS_SUCCESS;
4401}
4402
4403
4404VOID NTAPI
4406{
4409
4411
4413
4415
4416 Status = RunUSetup();
4417
4418 if (NT_SUCCESS(Status))
4419 {
4420 /*
4421 * Avoid a bugcheck if RunUSetup() finishes too quickly by implementing
4422 * a protective waiting.
4423 * This wait is needed because, since we are started as SMSS.EXE,
4424 * the NT kernel explicitly waits 5 seconds for the initial process
4425 * SMSS.EXE to initialize (as a protective measure), and otherwise
4426 * bugchecks with the code SESSION5_INITIALIZATION_FAILED.
4427 */
4428 Time.QuadPart += 50000000;
4430 }
4431 else
4432 {
4433 /* The installer failed to start: raise a hard error (crash the system/BSOD) */
4435 0, 0, NULL, 0, NULL);
4436 }
4437
4439}
4440
4441/* EOF */
DWORD Id
WCHAR First[]
Definition: FormatMessage.c:11
unsigned char BOOLEAN
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define isprint(c)
Definition: acclib.h:73
int toupper(int c)
Definition: utclib.c:881
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
char * strchr(const char *String, int ch)
Definition: utclib.c:501
#define __cdecl
Definition: accygwin.h:79
char * va_list
Definition: acmsvcex.h:78
#define va_end(ap)
Definition: acmsvcex.h:90
#define va_start(ap, A)
Definition: acmsvcex.h:91
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
BOOLEAN DoFileCopy(IN OUT PUSETUP_DATA pSetupData, IN PSP_FILE_CALLBACK_W MsgHandler, IN PVOID Context OPTIONAL)
Definition: install.c:818
BOOLEAN PrepareFileCopy(IN OUT PUSETUP_DATA pSetupData, IN PFILE_COPY_STATUS_ROUTINE StatusRoutine OPTIONAL)
Definition: install.c:676
PGENERIC_LIST CreateKeyboardDriverList(IN HINF InfFile)
Definition: settings.c:1093
PGENERIC_LIST CreateComputerTypeList(IN HINF InfFile)
Definition: settings.c:524
ULONG GetDefaultLanguageIndex(VOID)
Definition: settings.c:1119
PGENERIC_LIST CreateDisplayDriverList(IN HINF InfFile)
Definition: settings.c:708
PGENERIC_LIST CreateKeyboardLayoutList(IN HINF InfFile, IN PCWSTR LanguageId, OUT PWSTR DefaultKBLayout)
Definition: settings.c:1230
PGENERIC_LIST CreateLanguageList(IN HINF InfFile, OUT PWSTR DefaultLanguage)
Definition: settings.c:1180
struct _GENENTRY * PGENENTRY
NTSTATUS DoChkdsk(IN PPARTENTRY PartEntry)
Definition: chkdsk.c:57
BOOL WINAPI WriteConsoleOutputCharacterA(HANDLE hConsoleOutput, IN LPCSTR lpCharacter, IN DWORD nLength, IN COORD dwWriteCoord, OUT LPDWORD lpNumberOfCharsWritten)
Definition: console.c:407
BOOL WINAPI FillConsoleOutputCharacterA(IN HANDLE hConsoleOutput, IN CHAR cCharacter, IN DWORD nLength, IN COORD dwWriteCoord, OUT LPDWORD lpNumberOfCharsWritten)
Definition: console.c:560
BOOL WINAPI FreeConsole(VOID)
Definition: console.c:156
BOOL WINAPI FillConsoleOutputAttribute(IN HANDLE hConsoleOutput, IN WORD wAttribute, IN DWORD nLength, IN COORD dwWriteCoord, OUT LPDWORD lpNumberOfAttrsWritten)
Definition: console.c:525
NTSTATUS InitializeUserModePnpManager(IN HINF *phSetupInf)
Definition: devinst.c:559
VOID TerminateUserModePnpManager(VOID)
Definition: devinst.c:690
NTSTATUS WaitNoPendingInstallEvents(IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: devinst.c:514
BOOLEAN EnableUserModePnpManager(VOID)
Definition: devinst.c:521
NTSTATUS DoFormat(IN PPARTENTRY PartEntry, IN PCWSTR FileSystemName, IN BOOLEAN QuickFormat)
Definition: format.c:92
VOID ProgressSetStep(IN PPROGRESSBAR Bar, IN ULONG Step)
Definition: progress.c:368
VOID ProgressNextStep(IN PPROGRESSBAR Bar)
Definition: progress.c:361
PPROGRESSBAR CreateProgressBarEx(IN SHORT Left, IN SHORT Top, IN SHORT Right, IN SHORT Bottom, IN SHORT TextTop, IN SHORT TextRight, IN BOOLEAN DoubleEdge, IN SHORT ProgressColour, IN ULONG StepCount, IN PCSTR DescriptionText OPTIONAL, IN PCSTR ProgressFormatText OPTIONAL, IN PUPDATE_PROGRESS UpdateProgressProc OPTIONAL)
Definition: progress.c:272
VOID ProgressSetStepCount(IN PPROGRESSBAR Bar, IN ULONG StepCount)
Definition: progress.c:347
PPROGRESSBAR CreateProgressBar(IN SHORT Left, IN SHORT Top, IN SHORT Right, IN SHORT Bottom, IN SHORT TextTop, IN SHORT TextRight, IN BOOLEAN DoubleEdge, IN PCSTR DescriptionText OPTIONAL)
Definition: progress.c:317
VOID DestroyProgressBar(IN OUT PPROGRESSBAR Bar)
Definition: progress.c:339
static LPHIST_ENTRY Bottom
Definition: history.c:54
static LPHIST_ENTRY Top
Definition: history.c:53
BOOL Error
Definition: chkdsk.c:66
#define BACKGROUND_BLUE
Definition: blue.h:65
#define FOREGROUND_RED
Definition: blue.h:63
NTSTATUS InstallVBRToPartition(IN PUNICODE_STRING SystemRootPath, IN PUNICODE_STRING SourceRootPath, IN PUNICODE_STRING DestinationArcPath, IN PCWSTR FileSystemName)
Definition: bootsup.c:1333
NTSTATUS InstallFatBootcodeToFloppy(IN PUNICODE_STRING SourceRootPath, IN PUNICODE_STRING DestinationArcPath)
Definition: bootsup.c:1378
NTSTATUS InstallMbrBootCodeToDisk(IN PUNICODE_STRING SystemRootPath, IN PUNICODE_STRING SourceRootPath, IN PCWSTR DestinationDevicePathBuffer)
Definition: bootsup.c:763
Definition: bufpool.h:45
_In_ PSCSI_REQUEST_BLOCK _Out_ NTSTATUS _Inout_ BOOLEAN * Retry
Definition: classpnp.h:312
VOID RecoveryConsole(VOID)
Definition: cmdcons.c:1160
char * Text
Definition: combotst.c:136
NTSYSAPI BOOLEAN NTAPI RtlCreateUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
BOOL CONSOLE_Flush(VOID)
Definition: consup.c:175
VOID CONSOLE_SetInputTextXY(IN SHORT x, IN SHORT y, IN SHORT len, IN LPCWSTR Text)
Definition: consup.c:357
VOID CONSOLE_InvertTextXY(IN SHORT x, IN SHORT y, IN SHORT col, IN SHORT row)
Definition: consup.c:276
VOID CONSOLE_SetCursorXY(IN SHORT x, IN SHORT y)
Definition: consup.c:227
VOID CONSOLE_NormalTextXY(IN SHORT x, IN SHORT y, IN SHORT col, IN SHORT row)
Definition: consup.c:298
SHORT yScreen
Definition: consup.c:40
VOID __cdecl CONSOLE_SetStatusText(IN LPCSTR fmt,...)
Definition: consup.c:480
VOID CONSOLE_SetTextXY(IN SHORT x, IN SHORT y, IN LPCSTR Text)
Definition: consup.c:320
SHORT xScreen
Definition: consup.c:39
VOID CONSOLE_ConInKey(OUT PINPUT_RECORD Buffer)
Definition: consup.c:70
VOID __cdecl CONSOLE_PrintTextXY(IN SHORT x, IN SHORT y, IN LPCSTR fmt,...)
Definition: consup.c:595
VOID CONSOLE_ClearScreen(VOID)
Definition: consup.c:239
BOOLEAN CONSOLE_Init(VOID)
Definition: consup.c:45
VOID CONSOLE_SetStatusTextV(IN LPCSTR fmt, IN va_list args)
Definition: consup.c:471
BOOLEAN CONSOLE_ConInKeyPeek(OUT PINPUT_RECORD Buffer)
Definition: consup.c:89
VOID CONSOLE_SetCursorType(IN BOOL bInsert, IN BOOL bVisible)
Definition: consup.c:214
HANDLE StdOutput
Definition: consup.c:37
HANDLE StdInput
Definition: consup.c:36
#define TEXT_TYPE_REGULAR
Definition: consup.h:39
#define BACKGROUND_WHITE
Definition: consup.h:31
ush Pos
Definition: deflate.h:92
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#define wcsrchr
Definition: compat.h:16
#define MAX_PATH
Definition: compat.h:34
#define CALLBACK
Definition: compat.h:35
#define wcsicmp
Definition: compat.h:15
PPEB Peb
Definition: dllmain.c:27
#define swprintf
Definition: precomp.h:40
@ AnsiString
Definition: dnslib.h:19
VOID DrawPartitionList(IN HWND hWndList, IN PPARTLIST List)
Definition: drivepage.c:591
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
@ ERROR_SOURCE_DIR
Definition: errorcode.h:21
@ ERROR_LOAD_KBLAYOUT
Definition: errorcode.h:32
@ ERROR_LOAD_KEYBOARD
Definition: errorcode.h:31
@ ERROR_WRITE_BOOT
Definition: errorcode.h:28
@ NOT_AN_ERROR
Definition: errorcode.h:17
@ ERROR_DIRECTORY_NAME
Definition: errorcode.h:56
@ ERROR_LAST_ERROR_CODE
Definition: errorcode.h:62
@ ERROR_LOAD_DISPLAY
Definition: errorcode.h:30
@ ERROR_DRIVE_INFORMATION
Definition: errorcode.h:27
@ ERROR_INSUFFICIENT_PARTITION_SIZE
Definition: errorcode.h:57
@ ERROR_LOAD_COMPUTER
Definition: errorcode.h:29
<