ReactOS 0.4.15-dev-8119-g4fb2fdb
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/* Flag set in PARTENTRY::New when a partition is created automatically */
83#define PARTITION_NEW_AUTOCREATE 0x80
84
85/* List of supported file systems for the partition to be formatted */
87
88/* Machine state for the formatter */
91
92/*****************************************************/
93
96
97#ifdef __REACTOS__ /* HACK */
98
99/* FONT SUBSTITUTION WORKAROUND *************************************************/
100
101/* For font file check */
102FONTSUBSTSETTINGS s_SubstSettings = { FALSE };
103
104static void
105DoWatchDestFileName(LPCWSTR FileName)
106{
107 if (FileName[0] == 'm' || FileName[0] == 'M')
108 {
109 if (wcsicmp(FileName, L"mingliu.ttc") == 0)
110 {
111 DPRINT("mingliu.ttc found\n");
112 s_SubstSettings.bFoundFontMINGLIU = TRUE;
113 }
114 else if (wcsicmp(FileName, L"msgothic.ttc") == 0)
115 {
116 DPRINT("msgothic.ttc found\n");
117 s_SubstSettings.bFoundFontMSGOTHIC = TRUE;
118 }
119 else if (wcsicmp(FileName, L"msmincho.ttc") == 0)
120 {
121 DPRINT("msmincho.ttc found\n");
122 s_SubstSettings.bFoundFontMSMINCHO = TRUE;
123 }
124 else if (wcsicmp(FileName, L"mssong.ttf") == 0)
125 {
126 DPRINT("mssong.ttf found\n");
127 s_SubstSettings.bFoundFontMSSONG = TRUE;
128 }
129 }
130 else
131 {
132 if (wcsicmp(FileName, L"simsun.ttc") == 0)
133 {
134 DPRINT("simsun.ttc found\n");
135 s_SubstSettings.bFoundFontSIMSUN = TRUE;
136 }
137 else if (wcsicmp(FileName, L"gulim.ttc") == 0)
138 {
139 DPRINT("gulim.ttc found\n");
140 s_SubstSettings.bFoundFontGULIM = TRUE;
141 }
142 else if (wcsicmp(FileName, L"batang.ttc") == 0)
143 {
144 DPRINT("batang.ttc found\n");
145 s_SubstSettings.bFoundFontBATANG = TRUE;
146 }
147 }
148}
149#endif /* HACK */
150
151/* FUNCTIONS ****************************************************************/
152
153static VOID
155{
156 CHAR buffer[512];
157 va_list ap;
160
161 va_start(ap, fmt);
163 va_end(ap);
164
169}
170
171
172static VOID
174 IN SHORT yTop,
175 IN SHORT Width,
177{
178 COORD coPos;
179 DWORD Written;
180
181 /* Draw upper left corner */
182 coPos.X = xLeft;
183 coPos.Y = yTop;
185 CharUpperLeftCorner, // '+',
186 1,
187 coPos,
188 &Written);
189
190 /* Draw upper edge */
191 coPos.X = xLeft + 1;
192 coPos.Y = yTop;
194 CharHorizontalLine, // '-',
195 Width - 2,
196 coPos,
197 &Written);
198
199 /* Draw upper right corner */
200 coPos.X = xLeft + Width - 1;
201 coPos.Y = yTop;
203 CharUpperRightCorner, // '+',
204 1,
205 coPos,
206 &Written);
207
208 /* Draw right edge, inner space and left edge */
209 for (coPos.Y = yTop + 1; coPos.Y < yTop + Height - 1; coPos.Y++)
210 {
211 coPos.X = xLeft;
213 CharVerticalLine, // '|',
214 1,
215 coPos,
216 &Written);
217
218 coPos.X = xLeft + 1;
220 ' ',
221 Width - 2,
222 coPos,
223 &Written);
224
225 coPos.X = xLeft + Width - 1;
227 CharVerticalLine, // '|',
228 1,
229 coPos,
230 &Written);
231 }
232
233 /* Draw lower left corner */
234 coPos.X = xLeft;
235 coPos.Y = yTop + Height - 1;
237 CharLowerLeftCorner, // '+',
238 1,
239 coPos,
240 &Written);
241
242 /* Draw lower edge */
243 coPos.X = xLeft + 1;
244 coPos.Y = yTop + Height - 1;
246 CharHorizontalLine, // '-',
247 Width - 2,
248 coPos,
249 &Written);
250
251 /* Draw lower right corner */
252 coPos.X = xLeft + Width - 1;
253 coPos.Y = yTop + Height - 1;
255 CharLowerRightCorner, // '+',
256 1,
257 coPos,
258 &Written);
259}
260
261
262VOID
264 PCCH Status,
265 PINPUT_RECORD Ir,
266 ULONG WaitEvent)
267{
268 SHORT yTop;
269 SHORT xLeft;
270 COORD coPos;
271 DWORD Written;
273 ULONG MaxLength;
274 ULONG Lines;
275 PCHAR p;
276 PCCH pnext;
277 BOOLEAN LastLine;
278 SHORT Width;
280
281 /* Count text lines and longest line */
282 MaxLength = 0;
283 Lines = 0;
284 pnext = Text;
285
286 while (TRUE)
287 {
288 p = strchr(pnext, '\n');
289
290 if (p == NULL)
291 {
292 Length = strlen(pnext);
293 LastLine = TRUE;
294 }
295 else
296 {
297 Length = (ULONG)(p - pnext);
298 LastLine = FALSE;
299 }
300
301 Lines++;
302
303 if (Length > MaxLength)
304 MaxLength = Length;
305
306 if (LastLine)
307 break;
308
309 pnext = p + 1;
310 }
311
312 /* Check length of status line */
313 if (Status != NULL)
314 {
316
317 if (Length > MaxLength)
318 MaxLength = Length;
319 }
320
321 Width = MaxLength + 4;
322 Height = Lines + 2;
323
324 if (Status != NULL)
325 Height += 2;
326
327 yTop = (yScreen - Height) / 2;
328 xLeft = (xScreen - Width) / 2;
329
330
331 /* Set screen attributes */
332 coPos.X = xLeft;
333 for (coPos.Y = yTop; coPos.Y < yTop + Height; coPos.Y++)
334 {
337 Width,
338 coPos,
339 &Written);
340 }
341
342 DrawBox(xLeft, yTop, Width, Height);
343
344 /* Print message text */
345 coPos.Y = yTop + 1;
346 pnext = Text;
347 while (TRUE)
348 {
349 p = strchr(pnext, '\n');
350
351 if (p == NULL)
352 {
353 Length = strlen(pnext);
354 LastLine = TRUE;
355 }
356 else
357 {
358 Length = (ULONG)(p - pnext);
359 LastLine = FALSE;
360 }
361
362 if (Length != 0)
363 {
364 coPos.X = xLeft + 2;
366 pnext,
367 Length,
368 coPos,
369 &Written);
370 }
371
372 if (LastLine)
373 break;
374
375 coPos.Y++;
376 pnext = p + 1;
377 }
378
379 /* Print separator line and status text */
380 if (Status != NULL)
381 {
382 coPos.Y = yTop + Height - 3;
383 coPos.X = xLeft;
386 1,
387 coPos,
388 &Written);
389
390 coPos.X = xLeft + 1;
392 CharHorizontalLine, // '-',
393 Width - 2,
394 coPos,
395 &Written);
396
397 coPos.X = xLeft + Width - 1;
400 1,
401 coPos,
402 &Written);
403
404 coPos.Y++;
405 coPos.X = xLeft + 2;
407 Status,
408 min(strlen(Status), (SIZE_T)Width - 4),
409 coPos,
410 &Written);
411 }
412
413 if (WaitEvent == POPUP_WAIT_NONE)
414 return;
415
416 while (TRUE)
417 {
419
420 if (WaitEvent == POPUP_WAIT_ANY_KEY ||
421 Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)
422 {
423 return;
424 }
425 }
426}
427
428
429/*
430 * Confirm quit setup
431 * RETURNS
432 * TRUE: Quit setup.
433 * FALSE: Don't quit setup.
434 */
435static BOOL
437{
438 BOOL Result = FALSE;
440
441 while (TRUE)
442 {
444
445 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
446 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
447 {
448 Result = TRUE;
449 break;
450 }
451 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
452 {
453 Result = FALSE;
454 break;
455 }
456 }
457
458 return Result;
459}
460
461
462static VOID
464{
465 PGENERIC_LIST_ENTRY ListEntry;
466 KLID newLayout;
467
469
471 {
474 {
475 /* FIXME: Handle error! */
476 return;
477 }
478 }
479
480 /* Search for default layout (if provided) */
481 if (newLayout != 0)
482 {
483 for (ListEntry = GetFirstListEntry(USetupData.LayoutList); ListEntry;
484 ListEntry = GetNextListEntry(ListEntry))
485 {
486 PCWSTR pszLayoutId = ((PGENENTRY)GetListEntryData(ListEntry))->Id;
487 KLID LayoutId = (KLID)(pszLayoutId ? wcstoul(pszLayoutId, NULL, 16) : 0);
488 if (newLayout == LayoutId)
489 {
491 break;
492 }
493 }
494 }
495}
496
497
498static NTSTATUS
499NTAPI
503 IN SIZE_T cchBufferSize)
504{
505 return RtlStringCchPrintfA(Buffer, cchBufferSize, "%S",
507}
508
509static NTSTATUS
510NTAPI
514 IN SIZE_T cchBufferSize)
515{
517 PPARTENTRY PartEntry = NtOsInstall->PartEntry;
518
519 if (PartEntry && PartEntry->DriveLetter)
520 {
521 /* We have retrieved a partition that is mounted */
522 return RtlStringCchPrintfA(Buffer, cchBufferSize,
523 "%C:%S \"%S\"",
524 PartEntry->DriveLetter,
525 NtOsInstall->PathComponent,
526 NtOsInstall->InstallationName);
527 }
528 else
529 {
530 /* We failed somewhere, just show the NT path */
531 return RtlStringCchPrintfA(Buffer, cchBufferSize,
532 "%wZ \"%S\"",
533 &NtOsInstall->SystemNtPath,
534 NtOsInstall->InstallationName);
535 }
536}
537
538
539/*
540 * Start page
541 *
542 * Next pages:
543 * LanguagePage (at once, default)
544 * InstallIntroPage (at once, if unattended)
545 * QuitPage
546 *
547 * SIDEEFFECTS
548 * Init Sdi
549 * Init USetupData.SourcePath
550 * Init USetupData.SourceRootPath
551 * Init USetupData.SourceRootDir
552 * Init USetupData.SetupInf
553 * Init USetupData.RequiredPartitionDiskSpace
554 * Init IsUnattendedSetup
555 * If unattended, init *List and sets the Codepage
556 * If unattended, init SelectedLanguageId
557 * If unattended, init USetupData.LanguageId
558 *
559 * RETURNS
560 * Number of the next page.
561 */
562static PAGE_NUMBER
564{
565 ULONG Error;
566 PGENERIC_LIST_ENTRY ListEntry;
568
570
571 /* Initialize Setup, phase 1 */
573 if (Error != ERROR_SUCCESS)
574 {
576 return QUIT_PAGE;
577 }
578
579 /* Initialize the user-mode PnP manager */
581 DPRINT1("The user-mode PnP manager could not initialize, expect unavailable devices!\n");
582
583 /* Wait for any immediate pending installations to finish */
585 DPRINT1("WaitNoPendingInstallEvents() failed to wait!\n");
586
588
590 {
591 // TODO: Read options from inf
592 /* Load the hardware, language and keyboard layout lists */
593
597
599
600 /* new part */
604
606
607 /* first we hack LanguageList */
608 for (ListEntry = GetFirstListEntry(USetupData.LanguageList); ListEntry;
609 ListEntry = GetNextListEntry(ListEntry))
610 {
611 LocaleId = ((PGENENTRY)GetListEntryData(ListEntry))->Id;
613 {
614 DPRINT("found %S in LanguageList\n", LocaleId);
616 break;
617 }
618 }
619
620 /* now LayoutList */
621 for (ListEntry = GetFirstListEntry(USetupData.LayoutList); ListEntry;
622 ListEntry = GetNextListEntry(ListEntry))
623 {
624 LocaleId = ((PGENENTRY)GetListEntryData(ListEntry))->Id;
626 {
627 DPRINT("found %S in LayoutList\n", LocaleId);
629 break;
630 }
631 }
632
634
635 return INSTALL_INTRO_PAGE;
636 }
637
638 return LANGUAGE_PAGE;
639}
640
641
642/*
643 * Displays the LanguagePage.
644 *
645 * Next pages: WelcomePage, QuitPage
646 *
647 * SIDEEFFECTS
648 * Init SelectedLanguageId
649 * Init USetupData.LanguageId
650 *
651 * RETURNS
652 * Number of the next page.
653 */
654static PAGE_NUMBER
656{
657 GENERIC_LIST_UI ListUi;
658 PCWSTR NewLanguageId;
659 BOOL RefreshPage = FALSE;
660
661 /* Initialize the computer settings list */
663 {
666 {
667 PopupError("Setup failed to initialize available translations", NULL, NULL, POPUP_WAIT_NONE);
668 return WELCOME_PAGE;
669 }
670 }
671
674
675 /* Load the font */
678
679 /*
680 * If there is no language or just a single one in the list,
681 * skip the language selection process altogether.
682 */
684 {
686 return WELCOME_PAGE;
687 }
688
690 DrawGenericList(&ListUi,
691 2, 18,
692 xScreen - 3,
693 yScreen - 3);
694
696
698
699 while (TRUE)
700 {
702
703 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
704 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
705 {
706 ScrollDownGenericList(&ListUi);
707 RefreshPage = TRUE;
708 }
709 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
710 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
711 {
712 ScrollUpGenericList(&ListUi);
713 RefreshPage = TRUE;
714 }
715 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
716 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_NEXT)) /* PAGE DOWN */
717 {
719 RefreshPage = TRUE;
720 }
721 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
722 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_PRIOR)) /* PAGE UP */
723 {
725 RefreshPage = TRUE;
726 }
727 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
728 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
729 {
730 if (ConfirmQuit(Ir))
731 return QUIT_PAGE;
732 else
733 RedrawGenericList(&ListUi);
734 }
735 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
736 {
738
741
743
745 {
747 }
748
749 /* Load the font */
751
752 return WELCOME_PAGE;
753 }
754 else if ((Ir->Event.KeyEvent.uChar.AsciiChar > 0x60) && (Ir->Event.KeyEvent.uChar.AsciiChar < 0x7b))
755 {
756 /* a-z */
758 RefreshPage = TRUE;
759 }
760
761 if (RefreshPage)
762 {
764
765 NewLanguageId =
767
768 if (wcscmp(SelectedLanguageId, NewLanguageId))
769 {
770 /* Clear the language page */
772
773 SelectedLanguageId = NewLanguageId;
774
775 /* Load the font */
777
778 /* Redraw the list */
779 DrawGenericList(&ListUi,
780 2, 18,
781 xScreen - 3,
782 yScreen - 3);
783
784 /* Redraw language selection page in native language */
786 }
787
788 RefreshPage = FALSE;
789 }
790 }
791
792 return WELCOME_PAGE;
793}
794
795
796/*
797 * Displays the WelcomePage.
798 *
799 * Next pages:
800 * InstallIntroPage (default)
801 * RepairIntroPage
802 * RecoveryPage
803 * LicensePage
804 * QuitPage
805 *
806 * RETURNS
807 * Number of the next page.
808 */
809static PAGE_NUMBER
811{
813
814 while (TRUE)
815 {
817
818 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
819 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
820 {
821 if (ConfirmQuit(Ir))
822 return QUIT_PAGE;
823
824 break;
825 }
826 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
827 {
828 return INSTALL_INTRO_PAGE;
829 }
830 else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'R') /* R */
831 {
832 return RECOVERY_PAGE; // REPAIR_INTRO_PAGE;
833 }
834 else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'L') /* L */
835 {
836 return LICENSE_PAGE;
837 }
838 }
839
840 return WELCOME_PAGE;
841}
842
843
844/*
845 * Displays the License page.
846 *
847 * Next page:
848 * WelcomePage (default)
849 *
850 * RETURNS
851 * Number of the next page.
852 */
853static PAGE_NUMBER
855{
857
858 while (TRUE)
859 {
861
862 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
863 {
864 return WELCOME_PAGE;
865 }
866 }
867
868 return LICENSE_PAGE;
869}
870
871
872/*
873 * Displays the RepairIntroPage.
874 *
875 * Next pages:
876 * RebootPage (default)
877 * InstallIntroPage
878 * RecoveryPage
879 * IntroPage
880 *
881 * RETURNS
882 * Number of the next page.
883 */
884static PAGE_NUMBER
886{
888
889 while (TRUE)
890 {
892
893 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
894 {
895 return REBOOT_PAGE;
896 }
897 else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'U') /* U */
898 {
900 return INSTALL_INTRO_PAGE;
901 }
902 else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'R') /* R */
903 {
904 return RECOVERY_PAGE;
905 }
906 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESC */
907 {
908 return WELCOME_PAGE;
909 }
910 }
911
912 return REPAIR_INTRO_PAGE;
913}
914
915/*
916 * Displays the UpgradeRepairPage.
917 *
918 * Next pages:
919 * RebootPage (default)
920 * InstallIntroPage
921 * RecoveryPage
922 * WelcomePage
923 *
924 * RETURNS
925 * Number of the next page.
926 */
927static PAGE_NUMBER
929{
930 GENERIC_LIST_UI ListUi;
931
932/*** HACK!! ***/
933 if (PartitionList == NULL)
934 {
936 if (PartitionList == NULL)
937 {
938 /* FIXME: show an error dialog */
940 return QUIT_PAGE;
941 }
943 {
945 return QUIT_PAGE;
946 }
947
948 /* Reset the formatter machine state */
951 }
952/**************/
953
955 if (!NtOsInstallsList)
956 DPRINT1("Failed to get a list of NTOS installations; continue installation...\n");
957
958 /*
959 * If there is no available installation (or just a single one??) that can
960 * be updated in the list, just continue with the regular installation.
961 */
963 {
965
966 // return INSTALL_INTRO_PAGE;
968 // return SCSI_CONTROLLER_PAGE;
969 }
970
972
974 DrawGenericList(&ListUi,
975 2, 23,
976 xScreen - 3,
977 yScreen - 3);
978
979 // return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir);
980 while (TRUE)
981 {
983
984 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x00)
985 {
986 switch (Ir->Event.KeyEvent.wVirtualKeyCode)
987 {
988 case VK_DOWN: /* DOWN */
989 ScrollDownGenericList(&ListUi);
990 break;
991 case VK_UP: /* UP */
992 ScrollUpGenericList(&ListUi);
993 break;
994 case VK_NEXT: /* PAGE DOWN */
996 break;
997 case VK_PRIOR: /* PAGE UP */
999 break;
1000 case VK_F3: /* F3 */
1001 {
1002 if (ConfirmQuit(Ir))
1003 return QUIT_PAGE;
1004 else
1005 RedrawGenericList(&ListUi);
1006 break;
1007 }
1008#if 1
1009/* TODO: Temporarily kept until correct keyboard layout is in place.
1010 * (Actual AsciiChar of ESCAPE should be 0x1B instead of 0.)
1011 * Addendum to commit 8b94515b.
1012 */
1013 case VK_ESCAPE: /* ESC */
1014 {
1016 // return nextPage; // prevPage;
1017
1018 // return INSTALL_INTRO_PAGE;
1019 return DEVICE_SETTINGS_PAGE;
1020 // return SCSI_CONTROLLER_PAGE;
1021 }
1022
1023#endif
1024 }
1025 }
1026#if 0
1027/* TODO: Restore this once correct keyboard layout is in place. */
1028 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESC */
1029 {
1031 // return nextPage; // prevPage;
1032
1033 // return INSTALL_INTRO_PAGE;
1034 return DEVICE_SETTINGS_PAGE;
1035 // return SCSI_CONTROLLER_PAGE;
1036 }
1037#endif
1038 else
1039 {
1040 // switch (toupper(Ir->Event.KeyEvent.uChar.AsciiChar))
1041 // if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1042 if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'U') /* U */
1043 {
1044 /* Retrieve the current installation */
1046
1049
1050 DPRINT1("Selected installation for repair: \"%S\" ; DiskNumber = %d , PartitionNumber = %d\n",
1052
1054
1055 // return nextPage;
1056 /***/return INSTALL_INTRO_PAGE;/***/
1057 }
1058 else if ((Ir->Event.KeyEvent.uChar.AsciiChar > 0x60) &&
1059 (Ir->Event.KeyEvent.uChar.AsciiChar < 0x7b)) /* a-z */
1060 {
1062 }
1063 }
1064 }
1065
1066 return UPGRADE_REPAIR_PAGE;
1067}
1068
1069
1070/*
1071 * Displays the InstallIntroPage.
1072 *
1073 * Next pages:
1074 * DeviceSettingsPage (At once if repair or update is selected)
1075 * SelectPartitionPage (At once if unattended setup)
1076 * DeviceSettingsPage (default)
1077 * QuitPage
1078 *
1079 * RETURNS
1080 * Number of the next page.
1081 */
1082static PAGE_NUMBER
1084{
1085 if (RepairUpdateFlag)
1086 {
1087#if 1 /* Old code that looks good */
1088
1089 // return SELECT_PARTITION_PAGE;
1090 return DEVICE_SETTINGS_PAGE;
1091
1092#else /* Possible new code? */
1093
1094 return DEVICE_SETTINGS_PAGE;
1095 // return SCSI_CONTROLLER_PAGE;
1096
1097#endif
1098 }
1099
1101 return SELECT_PARTITION_PAGE;
1102
1104
1105 while (TRUE)
1106 {
1107 CONSOLE_ConInKey(Ir);
1108
1109 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1110 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1111 {
1112 if (ConfirmQuit(Ir))
1113 return QUIT_PAGE;
1114
1115 break;
1116 }
1117 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1118 {
1119 return UPGRADE_REPAIR_PAGE;
1120 }
1121 }
1122
1123 return INSTALL_INTRO_PAGE;
1124}
1125
1126
1127#if 0
1128static PAGE_NUMBER
1129ScsiControllerPage(PINPUT_RECORD Ir)
1130{
1131 // MUIDisplayPage(SCSI_CONTROLLER_PAGE);
1132
1133 CONSOLE_SetTextXY(6, 8, "Setup detected the following mass storage devices:");
1134
1135 /* FIXME: print loaded mass storage driver descriptions */
1136#if 0
1137 CONSOLE_SetTextXY(8, 10, "TEST device");
1138#endif
1139
1140 CONSOLE_SetStatusText(" ENTER = Continue F3 = Quit");
1141
1142 while (TRUE)
1143 {
1144 CONSOLE_ConInKey(Ir);
1145
1146 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1147 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1148 {
1149 if (ConfirmQuit(Ir))
1150 return QUIT_PAGE;
1151
1152 break;
1153 }
1154 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1155 {
1156 return DEVICE_SETTINGS_PAGE;
1157 }
1158 }
1159
1160 return SCSI_CONTROLLER_PAGE;
1161}
1162
1163static PAGE_NUMBER
1164OemDriverPage(PINPUT_RECORD Ir)
1165{
1166 // MUIDisplayPage(OEM_DRIVER_PAGE);
1167
1168 CONSOLE_SetTextXY(6, 8, "This is the OEM driver page!");
1169
1170 /* FIXME: Implement!! */
1171
1172 CONSOLE_SetStatusText(" ENTER = Continue F3 = Quit");
1173
1174 while (TRUE)
1175 {
1176 CONSOLE_ConInKey(Ir);
1177
1178 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1179 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1180 {
1181 if (ConfirmQuit(Ir))
1182 return QUIT_PAGE;
1183
1184 break;
1185 }
1186 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1187 {
1188 return DEVICE_SETTINGS_PAGE;
1189 }
1190 }
1191
1192 return OEM_DRIVER_PAGE;
1193}
1194#endif
1195
1196
1197/*
1198 * Displays the DeviceSettingsPage.
1199 *
1200 * Next pages:
1201 * SelectPartitionPage (At once if repair or update is selected)
1202 * ComputerSettingsPage
1203 * DisplaySettingsPage
1204 * KeyboardSettingsPage
1205 * LayoutsettingsPage
1206 * SelectPartitionPage
1207 * QuitPage
1208 *
1209 * SIDEEFFECTS
1210 * Init USetupData.ComputerList
1211 * Init USetupData.DisplayList
1212 * Init USetupData.KeyboardList
1213 * Init USetupData.LayoutList
1214 *
1215 * RETURNS
1216 * Number of the next page.
1217 */
1218static PAGE_NUMBER
1220{
1221 static ULONG Line = 16;
1222
1223 /* Initialize the computer settings list */
1225 {
1228 {
1230 return QUIT_PAGE;
1231 }
1232 }
1233
1234 /* Initialize the display settings list */
1236 {
1239 {
1241 return QUIT_PAGE;
1242 }
1243 }
1244
1245 /* Initialize the keyboard settings list */
1247 {
1250 {
1252 return QUIT_PAGE;
1253 }
1254 }
1255
1256 /* Initialize the keyboard layout list */
1258 {
1261 {
1262 /* FIXME: report error */
1264 return QUIT_PAGE;
1265 }
1266 }
1267
1268 if (RepairUpdateFlag)
1269 return SELECT_PARTITION_PAGE;
1270
1271 // if (IsUnattendedSetup)
1272 // return SELECT_PARTITION_PAGE;
1273
1275
1280
1281 CONSOLE_InvertTextXY(24, Line, 48, 1);
1282
1283 while (TRUE)
1284 {
1285 CONSOLE_ConInKey(Ir);
1286
1287 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1288 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1289 {
1290 CONSOLE_NormalTextXY(24, Line, 48, 1);
1291
1292 if (Line == 14)
1293 Line = 16;
1294 else if (Line == 16)
1295 Line = 11;
1296 else
1297 Line++;
1298
1299 CONSOLE_InvertTextXY(24, Line, 48, 1);
1300 }
1301 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1302 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1303 {
1304 CONSOLE_NormalTextXY(24, Line, 48, 1);
1305
1306 if (Line == 11)
1307 Line = 16;
1308 else if (Line == 16)
1309 Line = 14;
1310 else
1311 Line--;
1312
1313 CONSOLE_InvertTextXY(24, Line, 48, 1);
1314 }
1315 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1316 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1317 {
1318 if (ConfirmQuit(Ir))
1319 return QUIT_PAGE;
1320
1321 break;
1322 }
1323 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1324 {
1325 if (Line == 11)
1327 else if (Line == 12)
1328 return DISPLAY_SETTINGS_PAGE;
1329 else if (Line == 13)
1331 else if (Line == 14)
1332 return LAYOUT_SETTINGS_PAGE;
1333 else if (Line == 16)
1334 return SELECT_PARTITION_PAGE;
1335 }
1336 }
1337
1338 return DEVICE_SETTINGS_PAGE;
1339}
1340
1341
1342/*
1343 * Handles generic selection lists.
1344 *
1345 * PARAMS
1346 * GenericList: The list to handle.
1347 * nextPage: The page it needs to jump to after this page.
1348 * Ir: The PINPUT_RECORD
1349 */
1350static PAGE_NUMBER
1352 PAGE_NUMBER nextPage,
1353 PINPUT_RECORD Ir)
1354{
1355 while (TRUE)
1356 {
1357 CONSOLE_ConInKey(Ir);
1358
1359 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1360 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1361 {
1362 ScrollDownGenericList(ListUi);
1363 }
1364 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1365 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1366 {
1367 ScrollUpGenericList(ListUi);
1368 }
1369 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1370 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_NEXT)) /* PAGE DOWN */
1371 {
1373 }
1374 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1375 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_PRIOR)) /* PAGE UP */
1376 {
1378 }
1379 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1380 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1381 {
1382 if (ConfirmQuit(Ir))
1383 return QUIT_PAGE;
1384 else
1385 RedrawGenericList(ListUi);
1386 }
1387 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESC */
1388 {
1390 return nextPage; // Use some "prevPage;" instead?
1391 }
1392 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1393 {
1394 return nextPage;
1395 }
1396 else if ((Ir->Event.KeyEvent.uChar.AsciiChar > 0x60) && (Ir->Event.KeyEvent.uChar.AsciiChar < 0x7b))
1397 {
1398 /* a-z */
1400 }
1401 }
1402}
1403
1404
1405/*
1406 * Displays the ComputerSettingsPage.
1407 *
1408 * Next pages:
1409 * DeviceSettingsPage
1410 * QuitPage
1411 *
1412 * RETURNS
1413 * Number of the next page.
1414 */
1415static PAGE_NUMBER
1417{
1418 GENERIC_LIST_UI ListUi;
1420
1422 DrawGenericList(&ListUi,
1423 2, 18,
1424 xScreen - 3,
1425 yScreen - 3);
1426
1427 return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir);
1428}
1429
1430
1431/*
1432 * Displays the DisplaySettingsPage.
1433 *
1434 * Next pages:
1435 * DeviceSettingsPage
1436 * QuitPage
1437 *
1438 * RETURNS
1439 * Number of the next page.
1440 */
1441static PAGE_NUMBER
1443{
1444 GENERIC_LIST_UI ListUi;
1446
1448 DrawGenericList(&ListUi,
1449 2, 18,
1450 xScreen - 3,
1451 yScreen - 3);
1452
1453 return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir);
1454}
1455
1456
1457/*
1458 * Displays the KeyboardSettingsPage.
1459 *
1460 * Next pages:
1461 * DeviceSettingsPage
1462 * QuitPage
1463 *
1464 * RETURNS
1465 * Number of the next page.
1466 */
1467static PAGE_NUMBER
1469{
1470 GENERIC_LIST_UI ListUi;
1472
1474 DrawGenericList(&ListUi,
1475 2, 18,
1476 xScreen - 3,
1477 yScreen - 3);
1478
1479 return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir);
1480}
1481
1482
1483/*
1484 * Displays the LayoutSettingsPage.
1485 *
1486 * Next pages:
1487 * DeviceSettingsPage
1488 * QuitPage
1489 *
1490 * RETURNS
1491 * Number of the next page.
1492 */
1493static PAGE_NUMBER
1495{
1496 GENERIC_LIST_UI ListUi;
1498
1500 DrawGenericList(&ListUi,
1501 2, 18,
1502 xScreen - 3,
1503 yScreen - 3);
1504
1505 return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir);
1506}
1507
1508
1509static BOOLEAN
1511 _In_ PPARTENTRY PartEntry)
1512{
1513 /* Retrieve the maximum size in MB (rounded up) */
1514 ULONGLONG PartSize = RoundingDivide(GetPartEntrySizeInBytes(PartEntry), MB);
1515
1517 {
1518 /* Partition is too small so ask for another one */
1519 DPRINT1("Partition is too small (size: %I64u MB), required disk space is %lu MB\n",
1521 return FALSE;
1522 }
1523 else
1524 {
1525 return TRUE;
1526 }
1527}
1528
1529
1530/*
1531 * Displays the SelectPartitionPage.
1532 *
1533 * Next pages:
1534 * SelectFileSystemPage (At once if unattended)
1535 * SelectFileSystemPage (Default if free space is selected)
1536 * CreatePartitionPage
1537 * ConfirmDeleteSystemPartitionPage (if the selected partition is the system partition, aka with the boot flag set)
1538 * DeletePartitionPage
1539 * QuitPage
1540 *
1541 * SIDEEFFECTS
1542 * Set InstallShortcut (only if not unattended + free space is selected)
1543 *
1544 * RETURNS
1545 * Number of the next page.
1546 */
1547static PAGE_NUMBER
1549{
1550 PARTLIST_UI ListUi;
1551 ULONG Error;
1552
1553 if (PartitionList == NULL)
1554 {
1556 if (PartitionList == NULL)
1557 {
1559 return QUIT_PAGE;
1560 }
1562 {
1564 return QUIT_PAGE;
1565 }
1566
1567 /* Reset the formatter machine state */
1570 }
1571
1572 if (RepairUpdateFlag)
1573 {
1575
1576 /* Determine the selected installation disk & partition */
1580 if (!InstallPartition)
1581 {
1582 DPRINT1("RepairUpdateFlag == TRUE, SelectPartition() returned FALSE, assert!\n");
1583 ASSERT(FALSE);
1584 }
1586
1588 }
1589
1591
1594 2, 21,
1595 xScreen - 3,
1596 yScreen - 3);
1597 DrawPartitionList(&ListUi);
1598
1600 {
1601 /* Determine the selected installation disk & partition */
1605 if (!InstallPartition)
1606 {
1608
1610 {
1613
1614 /* Automatically create the partition on the whole empty space;
1615 * it will be formatted later with default parameters */
1618 0ULL);
1620
1621// FIXME?? Aren't we going to enter an infinite loop, if this test fails??
1623 {
1626 return SELECT_PARTITION_PAGE; /* let the user select another partition */
1627 }
1628
1631 }
1632 }
1633 else
1634 {
1636
1637 DrawPartitionList(&ListUi); // FIXME: Doesn't make much sense...
1638
1639// FIXME?? Aren't we going to enter an infinite loop, if this test fails??
1641 {
1644 return SELECT_PARTITION_PAGE; /* let the user select another partition */
1645 }
1646
1648 }
1649 }
1650
1651 while (TRUE)
1652 {
1653 ULONG uID;
1654
1656
1657 /* Update status text */
1658 if (CurrentPartition == NULL)
1659 {
1660 // FIXME: If we get a NULL current partition, this means that
1661 // the current disk is of unrecognized type. So we should display
1662 // instead a status string to initialize the disk with one of
1663 // the recognized partitioning schemes (MBR, later: GPT, etc.)
1664 // For the time being we don't have that, so use instead another
1665 // known string.
1667 }
1668 else
1669 {
1671 {
1675 {
1677 }
1678 }
1679 else
1680 {
1684 }
1685 }
1687
1688 CONSOLE_ConInKey(Ir);
1689
1690 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1691 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1692 {
1693 if (ConfirmQuit(Ir))
1694 {
1697 return QUIT_PAGE;
1698 }
1699
1700 break;
1701 }
1702 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1703 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1704 {
1705 ScrollDownPartitionList(&ListUi);
1706 }
1707 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1708 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1709 {
1710 ScrollUpPartitionList(&ListUi);
1711 }
1712 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
1713 {
1715
1717 continue; // return SELECT_PARTITION_PAGE;
1718
1719 /*
1720 * Check whether the user wants to install ReactOS on a disk that
1721 * is not recognized by the computer's firmware and if so, display
1722 * a warning since such disks may not be bootable.
1723 */
1724 if (CurrentPartition->DiskEntry->MediaType == FixedMedia &&
1725 !CurrentPartition->DiskEntry->BiosFound)
1726 {
1727 PopupError("The disk you have selected for installing ReactOS\n"
1728 "is not visible by the firmware of your computer,\n"
1729 "and so may not be bootable.\n"
1730 "Press ENTER to continue nonetheless.",
1732 Ir, POPUP_WAIT_ENTER);
1733 // return SELECT_PARTITION_PAGE;
1734 }
1735
1737 {
1739 if (Error != NOT_AN_ERROR)
1740 {
1742 return SELECT_PARTITION_PAGE;
1743 }
1744
1745 /* Automatically create the partition on the whole empty space;
1746 * it will be formatted later with default parameters */
1749 0ULL);
1751 }
1752
1754 {
1757 return SELECT_PARTITION_PAGE; /* let the user select another partition */
1758 }
1759
1762 }
1763 else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'C') /* C */
1764 {
1766
1768 if (Error != NOT_AN_ERROR)
1769 {
1771 return SELECT_PARTITION_PAGE;
1772 }
1773
1775 return CREATE_PARTITION_PAGE;
1776 }
1777 else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'E') /* E */
1778 {
1780
1782 {
1784 if (Error != NOT_AN_ERROR)
1785 {
1787 return SELECT_PARTITION_PAGE;
1788 }
1789
1791 return CREATE_PARTITION_PAGE;
1792 }
1793 }
1794 else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'D') /* D */
1795 {
1796 UNICODE_STRING CurrentPartitionU;
1797 WCHAR PathBuffer[MAX_PATH];
1798
1800
1801 /* Ignore deletion in case this is not a partitioned entry */
1803 {
1804 continue;
1805 }
1806
1807// TODO: Do something similar before trying to format the partition?
1808 if (!CurrentPartition->New &&
1811 {
1813
1814 RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
1815 L"\\Device\\Harddisk%lu\\Partition%lu\\",
1816 CurrentPartition->DiskEntry->DiskNumber,
1818 RtlInitUnicodeString(&CurrentPartitionU, PathBuffer);
1819
1820 /*
1821 * Check whether the user attempts to delete the partition on which
1822 * the installation source is present. If so, fail with an error.
1823 */
1824 // &USetupData.SourceRootPath
1825 if (RtlPrefixUnicodeString(&CurrentPartitionU, &USetupData.SourcePath, TRUE))
1826 {
1828 return SELECT_PARTITION_PAGE;
1829 }
1830 }
1831
1834 {
1836 }
1837
1838 return DELETE_PARTITION_PAGE;
1839 }
1840 }
1841
1842 return SELECT_PARTITION_PAGE;
1843}
1844
1845
1846#define PARTITION_SIZE_INPUT_FIELD_LENGTH 9
1847/* Restriction for MaxSize */
1848#define PARTITION_MAXSIZE (pow(10, (PARTITION_SIZE_INPUT_FIELD_LENGTH - 1)) - 1)
1849
1850static VOID
1852 SHORT Top,
1853 SHORT Right,
1854 SHORT Bottom,
1855 ULONG MaxSize,
1857 PBOOLEAN Quit,
1859{
1860 INPUT_RECORD Ir;
1861 COORD coPos;
1862 DWORD Written;
1863 CHAR Buffer[128];
1864 INT Length, Pos;
1865 WCHAR ch;
1866 SHORT iLeft;
1867 SHORT iTop;
1868
1869 if (Quit != NULL)
1870 *Quit = FALSE;
1871
1872 if (Cancel != NULL)
1873 *Cancel = FALSE;
1874
1875 DrawBox(Left, Top, Right - Left + 1, Bottom - Top + 1);
1876
1877 /* Print message */
1878 coPos.X = Left + 2;
1879 coPos.Y = Top + 2;
1881 iLeft = coPos.X + (USHORT)strlen(Buffer) + 1;
1882 iTop = coPos.Y;
1883
1885 Buffer,
1886 strlen(Buffer),
1887 coPos,
1888 &Written);
1889
1891 coPos.X = iLeft + PARTITION_SIZE_INPUT_FIELD_LENGTH + 1;
1892 coPos.Y = iTop;
1894 Buffer,
1895 strlen(Buffer),
1896 coPos,
1897 &Written);
1898
1899 swprintf(InputBuffer, L"%lu", MaxSize);
1901 Pos = Length;
1903 iTop,
1905 InputBuffer);
1906 CONSOLE_SetCursorXY(iLeft + Length, iTop);
1908
1909 while (TRUE)
1910 {
1911 CONSOLE_ConInKey(&Ir);
1912
1913 if ((Ir.Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1914 (Ir.Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1915 {
1916 if (Quit != NULL)
1917 *Quit = TRUE;
1918
1921 break;
1922 }
1923 else if (Ir.Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
1924 {
1926 break;
1927 }
1928 else if (Ir.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESC */
1929 {
1930 if (Cancel != NULL)
1931 *Cancel = TRUE;
1932
1935 break;
1936 }
1937 else if ((Ir.Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1938 (Ir.Event.KeyEvent.wVirtualKeyCode == VK_HOME)) /* HOME */
1939 {
1940 Pos = 0;
1941 CONSOLE_SetCursorXY(iLeft + Pos, iTop);
1942 }
1943 else if ((Ir.Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1944 (Ir.Event.KeyEvent.wVirtualKeyCode == VK_END)) /* END */
1945 {
1946 Pos = Length;
1947 CONSOLE_SetCursorXY(iLeft + Pos, iTop);
1948 }
1949 else if ((Ir.Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1950 (Ir.Event.KeyEvent.wVirtualKeyCode == VK_LEFT)) /* LEFT */
1951 {
1952 if (Pos > 0)
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_RIGHT)) /* RIGHT */
1960 {
1961 if (Pos < Length)
1962 {
1963 Pos++;
1964 CONSOLE_SetCursorXY(iLeft + Pos, iTop);
1965 }
1966 }
1967 else if ((Ir.Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1968 (Ir.Event.KeyEvent.wVirtualKeyCode == VK_DELETE)) /* DEL */
1969 {
1970 if (Pos < Length)
1971 {
1973 &InputBuffer[Pos + 1],
1974 (Length - Pos - 1) * sizeof(WCHAR));
1976
1977 Length--;
1979 iTop,
1981 InputBuffer);
1982 CONSOLE_SetCursorXY(iLeft + Pos, iTop);
1983 }
1984 }
1985 else if (Ir.Event.KeyEvent.wVirtualKeyCode == VK_BACK) /* BACKSPACE */
1986 {
1987 if (Pos > 0)
1988 {
1989 if (Pos < Length)
1990 memmove(&InputBuffer[Pos - 1],
1991 &InputBuffer[Pos],
1992 (Length - Pos) * sizeof(WCHAR));
1994
1995 Pos--;
1996 Length--;
1998 iTop,
2000 InputBuffer);
2001 CONSOLE_SetCursorXY(iLeft + Pos, iTop);
2002 }
2003 }
2004 else if (Ir.Event.KeyEvent.uChar.AsciiChar != 0x00)
2005 {
2007 {
2009
2010 if ((ch >= L'0') && (ch <= L'9'))
2011 {
2012 if (Pos < Length)
2013 memmove(&InputBuffer[Pos + 1],
2014 &InputBuffer[Pos],
2015 (Length - Pos) * sizeof(WCHAR));
2017 InputBuffer[Pos] = ch;
2018
2019 Pos++;
2020 Length++;
2022 iTop,
2024 InputBuffer);
2025 CONSOLE_SetCursorXY(iLeft + Pos, iTop);
2026 }
2027 }
2028 }
2029 }
2030}
2031
2032
2033/*
2034 * Displays the CreatePartitionPage.
2035 *
2036 * Next pages:
2037 * SelectPartitionPage
2038 * SelectFileSystemPage (default)
2039 * QuitPage
2040 *
2041 * RETURNS
2042 * Number of the next page.
2043 */
2044static PAGE_NUMBER
2046{
2047 PPARTENTRY PartEntry;
2048 PDISKENTRY DiskEntry;
2049 ULONG uID;
2050 ULONG MaxSize;
2051 ULONGLONG MaxPartSize, PartSize;
2052 BOOLEAN Quit, Cancel;
2053 WCHAR InputBuffer[50];
2054 CHAR LineBuffer[100];
2055
2057 {
2058 /* FIXME: show an error dialog */
2059 return QUIT_PAGE;
2060 }
2061
2063 {
2067 }
2068 else // if (PartCreateType == PartTypeExtended)
2069 {
2071 }
2072
2073 CONSOLE_SetTextXY(6, 8, MUIGetString(uID));
2074
2075 PartEntry = CurrentPartition;
2076 DiskEntry = CurrentPartition->DiskEntry;
2077
2078 DiskDescription(DiskEntry, LineBuffer, ARRAYSIZE(LineBuffer));
2080 LineBuffer);
2081
2083
2085
2086 MaxPartSize = GetPartEntrySizeInBytes(PartEntry);
2087
2088 while (TRUE)
2089 {
2090 /* Retrieve the maximum size in MB (rounded up)
2091 * and cap it with what the user can enter */
2092 MaxSize = (ULONG)RoundingDivide(MaxPartSize, MB);
2093 MaxSize = min(MaxSize, PARTITION_MAXSIZE);
2094
2095 ShowPartitionSizeInputBox(12, 14, xScreen - 12, 17,
2096 MaxSize, InputBuffer, &Quit, &Cancel);
2097 if (Quit)
2098 {
2099 if (ConfirmQuit(Ir))
2100 return QUIT_PAGE;
2101 break;
2102 }
2103 else if (Cancel)
2104 {
2105 return SELECT_PARTITION_PAGE;
2106 }
2107
2108 PartSize = _wcstoui64(InputBuffer, NULL, 10);
2109
2110 /* Retry if too small or too large */
2111 if ((PartSize < 1) || (PartSize > MaxSize))
2112 continue;
2113
2114 /*
2115 * If the input size, given in MB, specifies the maximum partition
2116 * size, it may slightly under- or over-estimate it due to rounding
2117 * error. In this case, use all of the unpartitioned disk space.
2118 * Otherwise, directly convert the size to bytes.
2119 */
2120 if (PartSize == MaxSize)
2121 PartSize = MaxPartSize;
2122 else // if (PartSize < MaxSize)
2123 PartSize *= MB;
2124 DPRINT("Partition size: %I64u bytes\n", PartSize);
2125
2126 ASSERT(PartSize <= MaxPartSize);
2127
2129 {
2132 PartSize);
2133 }
2134 else // if (PartCreateType == PartTypeExtended)
2135 {
2138 PartSize);
2139 }
2140
2141 return SELECT_PARTITION_PAGE;
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 {
2393 /* Automatically create the partition; it will be
2394 * formatted later with default parameters */
2395 // FIXME: Don't use the whole empty space, but a minimal size
2396 // specified from the TXTSETUP.SIF or unattended setup.
2399 0ULL);
2402 }
2403
2404 /* Set it as such */
2406 {
2407 DPRINT1("SetActivePartition(0x%p) failed?!\n", SystemPartition);
2408 ASSERT(FALSE);
2409 }
2410
2411 /* Commit all partition changes to all the disks */
2413 {
2414 DPRINT("WritePartitionsToDisk() failed\n");
2416 return QUIT_PAGE;
2417 }
2418
2419 /*
2420 * In all cases, whether or not we are going to perform a formatting,
2421 * we must perform a filesystem check of both the system and the
2422 * installation partitions.
2423 */
2427
2428 /*
2429 * In case we just repair an existing installation, or make
2430 * an unattended setup without formatting, just go to the
2431 * filesystem check step.
2432 */
2433 if (RepairUpdateFlag)
2435
2438 }
2439
2440 // ASSERT(SystemPartition->IsPartitioned);
2441
2442 /* Reset the filesystem list for each partition that is to be formatted */
2444
2445 PreviousFormatState = FormatState;
2446 switch (FormatState)
2447 {
2448 case Start:
2449 {
2450 /*
2451 * We start by formatting the system partition in case it is new
2452 * (it didn't exist before) and is not the same as the installation
2453 * partition. Otherwise we just require a filesystem check on it,
2454 * and start by formatting the installation partition instead.
2455 */
2456
2458
2461 {
2464
2465 // TODO: Should we let the user using a custom file-system,
2466 // or should we always use FAT(32) for it?
2467 // For "compatibility", FAT(32) would be best indeed.
2468
2470 DPRINT1("FormatState: Start --> FormatSystemPartition\n");
2471 }
2472 else
2473 {
2476
2478 {
2479 /* The system partition is separate, so it had better be formatted! */
2482
2483 /* Require a filesystem check on the system partition too */
2485 }
2486
2488 DPRINT1("FormatState: Start --> FormatInstallPartition\n");
2489 }
2490 break;
2491 }
2492
2494 {
2497
2499 DPRINT1("FormatState: FormatSystemPartition --> FormatInstallPartition\n");
2500 break;
2501 }
2502
2505 {
2507 NULL,
2508 &TempPartition))
2509 {
2512
2514 DPRINT1("FormatState: FormatInstallPartition --> FormatOtherPartition\n");
2515 else
2516 DPRINT1("FormatState: FormatOtherPartition --> FormatOtherPartition\n");
2517 }
2518 else
2519 {
2521
2523 DPRINT1("FormatState: FormatInstallPartition --> FormatDone\n");
2524 else
2525 DPRINT1("FormatState: FormatOtherPartition --> FormatDone\n");
2526
2528 }
2529 break;
2530 }
2531
2532 case FormatDone:
2533 {
2534 DPRINT1("FormatState: FormatDone\n");
2536 }
2537
2538 default:
2539 {
2540 DPRINT1("FormatState: Invalid value %ld\n", FormatState);
2541 ASSERT(FALSE);
2542 return QUIT_PAGE;
2543 }
2544 }
2545
2546 PartEntry = TempPartition;
2547 DiskEntry = TempPartition->DiskEntry;
2548
2549 ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0);
2550
2552
2553 if (PartEntry->New & PARTITION_NEW_AUTOCREATE)
2554 {
2555 PartEntry->New &= ~PARTITION_NEW_AUTOCREATE;
2556
2558 }
2559 else if (PartEntry->New)
2560 {
2561 switch (FormatState)
2562 {
2565 break;
2566
2569 break;
2570
2573 break;
2574
2575 default:
2576 ASSERT(FALSE);
2577 break;
2578 }
2579 }
2580 else
2581 {
2583 }
2584
2585 PartitionDescription(PartEntry, LineBuffer, ARRAYSIZE(LineBuffer));
2586 CONSOLE_SetTextXY(6, 10, LineBuffer);
2587
2588 DiskDescription(DiskEntry, LineBuffer, ARRAYSIZE(LineBuffer));
2590 LineBuffer);
2591
2592 /* Show "This Partition will be formatted next" only if it is unformatted */
2593 if (PartEntry->New || PartEntry->FormatState == Unformatted)
2595
2597
2599 {
2601
2602 switch (USetupData.FsType)
2603 {
2604 /* 1 is for BtrFS */
2605 case 1:
2606 DefaultFs = L"BTRFS";
2607 break;
2608
2609 /* If we don't understand input, default to FAT */
2610 default:
2611 DefaultFs = L"FAT";
2612 break;
2613 }
2614 }
2615 else
2616 {
2617 /* By default select the "FAT" file system */
2618 DefaultFs = L"FAT";
2619 }
2620
2621 /* Create the file system list */
2622 // TODO: Display only the FSes compatible with the selected partition!
2624 PartEntry->New ||
2625 PartEntry->FormatState == Unformatted,
2626 DefaultFs);
2627 if (FileSystemList == NULL)
2628 {
2629 /* FIXME: show an error dialog */
2630 return QUIT_PAGE;
2631 }
2632
2634 {
2636 return FORMAT_PARTITION_PAGE;
2637 }
2638
2640
2641 while (TRUE)
2642 {
2643 CONSOLE_ConInKey(Ir);
2644
2645 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2646 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
2647 {
2648 if (ConfirmQuit(Ir))
2649 {
2650 /* Reset the filesystem list */
2652 return QUIT_PAGE;
2653 }
2654
2655 break;
2656 }
2657 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESC */
2658 {
2659 /* Reset the formatter machine state */
2662
2663 /* Reset the filesystem list */
2665
2666 return SELECT_PARTITION_PAGE;
2667 }
2668 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2669 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
2670 {
2672 }
2673 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2674 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
2675 {
2677 }
2678 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
2679 {
2681 {
2683
2684 /*
2685 * Skip formatting this partition. We will also ignore
2686 * filesystem checks on it, unless it is either the system
2687 * or the installation partition.
2688 */
2691 {
2692 PartEntry->NeedsCheck = FALSE;
2693 }
2694
2696 }
2697 else
2698 {
2699 /* Format this partition */
2700 return FORMAT_PARTITION_PAGE;
2701 }
2702 }
2703 }
2704
2705 FormatState = PreviousFormatState;
2706
2708}
2709
2710
2711/*
2712 * Displays the FormatPartitionPage.
2713 *
2714 * Next pages:
2715 * InstallDirectoryPage (At once if IsUnattendedSetup or InstallShortcut)
2716 * SelectPartitionPage (At once)
2717 * QuitPage
2718 *
2719 * SIDEEFFECTS
2720 * Sets InstallPartition->FormatState
2721 * Sets USetupData.DestinationRootPath
2722 *
2723 * RETURNS
2724 * Number of the next page.
2725 */
2726static PAGE_NUMBER
2728{
2730 PPARTENTRY PartEntry;
2731 PDISKENTRY DiskEntry;
2732 PFILE_SYSTEM_ITEM SelectedFileSystem;
2733 WCHAR PathBuffer[MAX_PATH];
2735
2736 DPRINT("FormatPartitionPage()\n");
2737
2738 if (PartitionList == NULL || TempPartition == NULL)
2739 {
2740 /* FIXME: show an error dialog */
2741 return QUIT_PAGE;
2742 }
2743
2744 PartEntry = TempPartition;
2745 DiskEntry = TempPartition->DiskEntry;
2746
2747 ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0);
2748
2749 SelectedFileSystem = FileSystemList->Selected;
2750 ASSERT(SelectedFileSystem && SelectedFileSystem->FileSystem);
2751
2753
2755 CONSOLE_SetTextXY(6, 10, Buffer);
2756
2757 DiskDescription(DiskEntry, Buffer, ARRAYSIZE(Buffer));
2759 Buffer);
2760
2761 while (TRUE)
2762 {
2763 if (!IsUnattendedSetup)
2764 CONSOLE_ConInKey(Ir);
2765
2766 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2767 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
2768 {
2769 if (ConfirmQuit(Ir))
2770 {
2771 /* Reset the filesystem list */
2773 return QUIT_PAGE;
2774 }
2775
2776 break;
2777 }
2778 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN || IsUnattendedSetup) /* ENTER */
2779 {
2780 /*
2781 * Remove the "Press ENTER to continue" message prompt when the ENTER
2782 * key is pressed as the user wants to begin the partition formatting.
2783 */
2786
2787 /* Format the partition */
2788 Status = DoFormat(PartEntry,
2789 SelectedFileSystem->FileSystem,
2790 SelectedFileSystem->QuickFormat);
2792 {
2794
2795 /* Reset the filesystem list */
2797 return QUIT_PAGE;
2798 }
2800 {
2801 /* FIXME: show an error dialog */
2802 // MUIDisplayError(ERROR_FORMATTING_PARTITION, Ir, POPUP_WAIT_ANY_KEY, PathBuffer);
2803
2804 /* Reset the filesystem list */
2806 return QUIT_PAGE;
2807 }
2808 else if (Status == STATUS_NOT_SUPPORTED)
2809 {
2811 sizeof(Buffer),
2812 "Setup is currently unable to format a partition in %S.\n"
2813 "\n"
2814 " \x07 Press ENTER to continue Setup.\n"
2815 " \x07 Press F3 to quit Setup.",
2816 SelectedFileSystem->FileSystem);
2817
2821
2822 while (TRUE)
2823 {
2824 CONSOLE_ConInKey(Ir);
2825
2826 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x00 &&
2827 Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3) /* F3 */
2828 {
2829 if (ConfirmQuit(Ir))
2830 {
2831 /* Reset the filesystem list */
2833 return QUIT_PAGE;
2834 }
2835 else
2836 {
2838 }
2839 }
2840 else if (Ir->Event.KeyEvent.uChar.AsciiChar == VK_RETURN) /* ENTER */
2841 {
2843 }
2844 }
2845 }
2846 else if (!NT_SUCCESS(Status))
2847 {
2849 RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
2850 L"\\Device\\Harddisk%lu\\Partition%lu",
2851 DiskEntry->DiskNumber,
2852 PartEntry->PartitionNumber);
2853
2854 DPRINT1("DoFormat() failed: Status 0x%08lx\n", Status);
2856
2857 /* Reset the filesystem list */
2859 return QUIT_PAGE;
2860 }
2861
2863 }
2864 }
2865
2866 return FORMAT_PARTITION_PAGE;
2867}
2868
2869
2870/*
2871 * Displays the CheckFileSystemPage.
2872 *
2873 * Next pages:
2874 * InstallDirectoryPage (At once)
2875 * QuitPage
2876 *
2877 * SIDEEFFECTS
2878 * Inits or reloads FileSystemList
2879 *
2880 * RETURNS
2881 * Number of the next page.
2882 */
2883static PAGE_NUMBER
2885{
2887 PPARTENTRY PartEntry;
2889
2890 if (PartitionList == NULL)
2891 {
2892 /* FIXME: show an error dialog */
2893 return QUIT_PAGE;
2894 }
2895
2896 if (!GetNextUncheckedPartition(PartitionList, NULL, &PartEntry))
2897 {
2899 }
2900
2901 ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0);
2902
2903 DPRINT1("CheckFileSystemPage -- PartitionType: 0x%02X ; FileSystem: %S\n",
2904 PartEntry->PartitionType, (*PartEntry->FileSystem ? PartEntry->FileSystem : L"n/a"));
2905
2907
2909 CONSOLE_SetTextXY(6, 10, Buffer);
2910
2913 Buffer);
2914
2915 /* Check the partition */
2916 Status = DoChkdsk(PartEntry);
2918 {
2919 /*
2920 * Partition checking is not supported with the current filesystem,
2921 * so disable FS checks on it.
2922 */
2923 PartEntry->NeedsCheck = FALSE;
2924
2926 sizeof(Buffer),
2927 "Setup is currently unable to check a partition formatted in %S.\n"
2928 "\n"
2929 " \x07 Press ENTER to continue Setup.\n"
2930 " \x07 Press F3 to quit Setup.",
2931 PartEntry->FileSystem);
2932
2936
2937 while (TRUE)
2938 {
2939 CONSOLE_ConInKey(Ir);
2940
2941 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x00 &&
2942 Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3) /* F3 */
2943 {
2944 if (ConfirmQuit(Ir))
2945 return QUIT_PAGE;
2946 else
2948 }
2949 else if (Ir->Event.KeyEvent.uChar.AsciiChar == VK_RETURN) /* ENTER */
2950 {
2952 }
2953 }
2954 }
2955 else if (!NT_SUCCESS(Status))
2956 {
2957 DPRINT1("DoChkdsk() failed: Status 0x%08lx\n", Status);
2958
2960 sizeof(Buffer),
2961 "ChkDsk detected some disk errors.\n(Status 0x%08lx).\n",
2962 Status);
2963
2966 Ir, POPUP_WAIT_ENTER);
2967 }
2968
2969 PartEntry->NeedsCheck = FALSE;
2971}
2972
2973
2974static BOOLEAN
2976 IN PCWSTR InstallDir)
2977{
2978 UINT i, Length;
2979
2980 Length = wcslen(InstallDir);
2981
2982 // TODO: Add check for 8.3 too.
2983
2984 /* Path must be at least 2 characters long */
2985// if (Length < 2)
2986// return FALSE;
2987
2988 /* Path must start with a backslash */
2989// if (InstallDir[0] != L'\\')
2990// return FALSE;
2991
2992 /* Path must not end with a backslash */
2993 if (InstallDir[Length - 1] == L'\\')
2994 return FALSE;
2995
2996 /* Path must not contain whitespace characters */
2997 for (i = 0; i < Length; i++)
2998 {
2999 if (iswspace(InstallDir[i]))
3000 return FALSE;
3001 }
3002
3003 /* Path component must not end with a dot */
3004 for (i = 0; i < Length; i++)
3005 {
3006 if (InstallDir[i] == L'\\' && i > 0)
3007 {
3008 if (InstallDir[i - 1] == L'.')
3009 return FALSE;
3010 }
3011 }
3012
3013 if (InstallDir[Length - 1] == L'.')
3014 return FALSE;
3015
3016 return TRUE;
3017}
3018
3019
3020/*
3021 * Displays the InstallDirectoryPage.
3022 *
3023 * Next pages:
3024 * PrepareCopyPage
3025 * QuitPage
3026 *
3027 * RETURNS
3028 * Number of the next page.
3029 */
3030static PAGE_NUMBER
3032{
3034 ULONG Length, Pos;
3035 WCHAR c;
3036 WCHAR InstallDir[MAX_PATH];
3037
3038 /* We do not need the filesystem list anymore */
3040
3042 {
3043 /* FIXME: show an error dialog */
3044 return QUIT_PAGE;
3045 }
3046
3047 // if (IsUnattendedSetup)
3048 if (RepairUpdateFlag)
3049 wcscpy(InstallDir, CurrentInstallation->PathComponent); // SystemNtPath
3052 else
3053 wcscpy(InstallDir, L"\\ReactOS");
3054
3055 /*
3056 * Check the validity of the predefined 'InstallDir'. If we are either
3057 * in unattended setup or in update/repair mode, and the installation path
3058 * is valid, just perform the installation. Otherwise (either in the case
3059 * of an invalid path, or we are in regular setup), display the UI and allow
3060 * the user to specify a new installation path.
3061 */
3062 if ((RepairUpdateFlag || IsUnattendedSetup) && IsValidPath(InstallDir))
3063 {
3065 if (!NT_SUCCESS(Status))
3066 {
3067 DPRINT1("InitDestinationPaths() failed: Status 0x%lx\n", Status);
3069 return QUIT_PAGE;
3070 }
3071
3072 /*
3073 * Check whether the user attempts to install ReactOS within the
3074 * installation source directory, or in a subdirectory thereof.
3075 * If so, fail with an error.
3076 */
3078 {
3081 }
3082
3083 return PREPARE_COPY_PAGE;
3084 }
3085
3086 Length = wcslen(InstallDir);
3087 Pos = Length;
3088
3090 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
3091 CONSOLE_SetCursorXY(8 + Pos, 11);
3093
3094 while (TRUE)
3095 {
3096 CONSOLE_ConInKey(Ir);
3097
3098 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3099 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
3100 {
3102
3103 if (ConfirmQuit(Ir))
3104 return QUIT_PAGE;
3105
3107 break;
3108 }
3109 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3110 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DELETE)) /* DEL */
3111 {
3112 if (Pos < Length)
3113 {
3114 memmove(&InstallDir[Pos],
3115 &InstallDir[Pos + 1],
3116 (Length - Pos - 1) * sizeof(WCHAR));
3117 InstallDir[Length - 1] = UNICODE_NULL;
3118
3119 Length--;
3120 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
3121 CONSOLE_SetCursorXY(8 + Pos, 11);
3122 }
3123 }
3124 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3125 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_HOME)) /* HOME */
3126 {
3127 Pos = 0;
3128 CONSOLE_SetCursorXY(8 + Pos, 11);
3129 }
3130 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3131 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_END)) /* END */
3132 {
3133 Pos = Length;
3134 CONSOLE_SetCursorXY(8 + Pos, 11);
3135 }
3136 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3137 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_LEFT)) /* LEFT */
3138 {
3139 if (Pos > 0)
3140 {
3141 Pos--;
3142 CONSOLE_SetCursorXY(8 + Pos, 11);
3143 }
3144 }
3145 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3146 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RIGHT)) /* RIGHT */
3147 {
3148 if (Pos < Length)
3149 {
3150 Pos++;
3151 CONSOLE_SetCursorXY(8 + Pos, 11);
3152 }
3153 }
3154 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
3155 {
3157
3158 /*
3159 * Check for the validity of the installation directory and pop up
3160 * an error if it is not the case. Then the user can fix its input.
3161 */
3162 if (!IsValidPath(InstallDir))
3163 {
3166 }
3167
3169 if (!NT_SUCCESS(Status))
3170 {
3171 DPRINT1("InitDestinationPaths() failed: Status 0x%lx\n", Status);
3173 return QUIT_PAGE;
3174 }
3175
3176 /*
3177 * Check whether the user attempts to install ReactOS within the
3178 * installation source directory, or in a subdirectory thereof.
3179 * If so, fail with an error.
3180 */
3182 {
3185 }
3186
3187 return PREPARE_COPY_PAGE;
3188 }
3189 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x08) /* BACKSPACE */
3190 {
3191 if (Pos > 0)
3192 {
3193 if (Pos < Length)
3194 memmove(&InstallDir[Pos - 1],
3195 &InstallDir[Pos],
3196 (Length - Pos) * sizeof(WCHAR));
3197 InstallDir[Length - 1] = UNICODE_NULL;
3198
3199 Pos--;
3200 Length--;
3201 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
3202 CONSOLE_SetCursorXY(8 + Pos, 11);
3203 }
3204 }
3205 else if (isprint(Ir->Event.KeyEvent.uChar.AsciiChar))
3206 {
3207 if (Length < 50)
3208 {
3210 if (iswalpha(c) || iswdigit(c) || c == '.' || c == '\\' || c == '-' || c == '_')
3211 {
3212 if (Pos < Length)
3213 memmove(&InstallDir[Pos + 1],
3214 &InstallDir[Pos],
3215 (Length - Pos) * sizeof(WCHAR));
3216 InstallDir[Length + 1] = UNICODE_NULL;
3217 InstallDir[Pos] = c;
3218
3219 Pos++;
3220 Length++;
3221 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
3222 CONSOLE_SetCursorXY(8 + Pos, 11);
3223 }
3224 }
3225 }
3226 }
3227
3229}
3230
3231
3232// PSETUP_ERROR_ROUTINE
3233static VOID
3234__cdecl
3236 IN PUSETUP_DATA pSetupData,
3237 ...)
3238{
3239 INPUT_RECORD Ir;
3240 va_list arg_ptr;
3241
3242 va_start(arg_ptr, pSetupData);
3243
3244 if (pSetupData->LastErrorNumber >= ERROR_SUCCESS &&
3245 pSetupData->LastErrorNumber < ERROR_LAST_ERROR_CODE)
3246 {
3247 // Note: the "POPUP_WAIT_ENTER" actually depends on the LastErrorNumber...
3248 MUIDisplayErrorV(pSetupData->LastErrorNumber, &Ir, POPUP_WAIT_ENTER, arg_ptr);
3249 }
3250
3251 va_end(arg_ptr);
3252}
3253
3254/*
3255 * Displays the PrepareCopyPage.
3256 *
3257 * Next pages:
3258 * FileCopyPage(At once)
3259 * QuitPage
3260 *
3261 * SIDEEFFECTS
3262 * Calls PrepareFileCopy
3263 *
3264 * RETURNS
3265 * Number of the next page.
3266 */
3267static PAGE_NUMBER
3269{
3270 // ERROR_NUMBER ErrorNumber;
3272
3274
3275 /* ErrorNumber = */ Success = PrepareFileCopy(&USetupData, NULL);
3276 if (/*ErrorNumber != ERROR_SUCCESS*/ !Success)
3277 {
3278 // MUIDisplayError(ErrorNumber, Ir, POPUP_WAIT_ENTER);
3279 return QUIT_PAGE;
3280 }
3281
3282 return FILE_COPY_PAGE;
3283}
3284
3285typedef struct _COPYCONTEXT
3286{
3292
3293static VOID
3296{
3298
3299 /* Get the memory information from the system */
3301 &PerfInfo,
3302 sizeof(PerfInfo),
3303 NULL);
3304
3305 /* Check if this is initial setup */
3306 if (First)
3307 {
3308 /* Set maximum limits to be total RAM pages */
3309 ProgressSetStepCount(CopyContext->MemoryBars[0], PerfInfo.CommitLimit);
3310 ProgressSetStepCount(CopyContext->MemoryBars[1], PerfInfo.CommitLimit);
3311 ProgressSetStepCount(CopyContext->MemoryBars[2], PerfInfo.CommitLimit);
3312 }
3313
3314 /* Set current values */
3315 ProgressSetStep(CopyContext->MemoryBars[0], PerfInfo.PagedPoolPages + PerfInfo.NonPagedPoolPages);
3316 ProgressSetStep(CopyContext->MemoryBars[1], PerfInfo.ResidentSystemCachePage);
3317 ProgressSetStep(CopyContext->MemoryBars[2], PerfInfo.AvailablePages);
3318}
3319
3320static UINT
3324 UINT_PTR Param1,
3325 UINT_PTR Param2)
3326{
3327 PCOPYCONTEXT CopyContext = (PCOPYCONTEXT)Context;
3328 PFILEPATHS_W FilePathInfo;
3329 PCWSTR SrcFileName, DstFileName;
3330
3331 switch (Notification)
3332 {
3334 {
3335 CopyContext->TotalOperations = (ULONG)Param2;
3336 CopyContext->CompletedOperations = 0;
3337 ProgressSetStepCount(CopyContext->ProgressBar,
3338 CopyContext->TotalOperations);
3339 SetupUpdateMemoryInfo(CopyContext, TRUE);
3340 break;
3341 }
3342
3346 {
3347 FilePathInfo = (PFILEPATHS_W)Param1;
3348
3350 {
3351 /* Display delete message */
3352 ASSERT(Param2 == FILEOP_DELETE);
3353
3354 DstFileName = wcsrchr(FilePathInfo->Target, L'\\');
3355 if (DstFileName) ++DstFileName;
3356 else DstFileName = FilePathInfo->Target;
3357
3359 DstFileName);
3360 }
3362 {
3363 /* Display move/rename message */
3364 ASSERT(Param2 == FILEOP_RENAME);
3365
3366 SrcFileName = wcsrchr(FilePathInfo->Source, L'\\');
3367 if (SrcFileName) ++SrcFileName;
3368 else SrcFileName = FilePathInfo->Source;
3369
3370 DstFileName = wcsrchr(FilePathInfo->Target, L'\\');
3371 if (DstFileName) ++DstFileName;
3372 else DstFileName = FilePathInfo->Target;
3373
3374 if (!wcsicmp(SrcFileName, DstFileName))
3375 Param2 = STRING_MOVING;
3376 else
3377 Param2 = STRING_RENAMING;
3378
3380 SrcFileName, DstFileName);
3381 }
3383 {
3384 static PCSTR s_pszCopying = NULL; /* Cached for speed */
3385
3386 /* Display copy message */
3387 ASSERT(Param2 == FILEOP_COPY);
3388
3389 /* NOTE: When extracting from CABs the Source is the CAB name */
3390 DstFileName = wcsrchr(FilePathInfo->Target, L'\\');
3391 if (DstFileName) ++DstFileName;
3392 else DstFileName = FilePathInfo->Target;
3393
3394 if (!s_pszCopying)
3395 s_pszCopying = MUIGetString(STRING_COPYING);
3396 CONSOLE_SetStatusText(s_pszCopying, DstFileName);
3397#ifdef __REACTOS__ /* HACK */
3398 DoWatchDestFileName(DstFileName);
3399#endif
3400 }
3401
3402 SetupUpdateMemoryInfo(CopyContext, FALSE);
3403 break;
3404 }
3405
3407 {
3408 FilePathInfo = (PFILEPATHS_W)Param1;
3409
3410 DPRINT1("An error happened while trying to copy file '%S' (error 0x%08lx), skipping it...\n",
3411 FilePathInfo->Target, FilePathInfo->Win32Error);
3412 return FILEOP_SKIP;
3413 }
3414
3418 {
3419 CopyContext->CompletedOperations++;
3420
3421 /* SYSREG checkpoint */
3422 if (CopyContext->TotalOperations >> 1 == CopyContext->CompletedOperations)
3423 DPRINT1("CHECKPOINT:HALF_COPIED\n");
3424
3425 ProgressNextStep(CopyContext->ProgressBar);
3426 SetupUpdateMemoryInfo(CopyContext, FALSE);
3427 break;
3428 }
3429 }
3430
3431 return FILEOP_DOIT;
3432}
3433
3434
3435/*
3436 * Displays the FileCopyPage.
3437 *
3438 * Next pages:
3439 * RegistryPage(At once)
3440 *
3441 * SIDEEFFECTS
3442 * Calls DoFileCopy
3443 *
3444 * RETURNS
3445 * Number of the next page.
3446 */
3447static PAGE_NUMBER
3449{
3450 COPYCONTEXT CopyContext;
3451 UINT MemBarWidth;
3452
3454
3455 /* Create context for the copy process */
3456 CopyContext.TotalOperations = 0;
3457 CopyContext.CompletedOperations = 0;
3458
3459 /* Create the progress bar as well */
3460 CopyContext.ProgressBar = CreateProgressBar(13,
3461 26,
3462 xScreen - 13,
3463 yScreen - 20,
3464 10,
3465 24,
3466 TRUE,
3468
3469 // fit memory bars to screen width, distribute them uniform
3470 MemBarWidth = (xScreen - 26) / 5;
3471 MemBarWidth -= MemBarWidth % 2; // make even
3472 /* ATTENTION: The following progress bars are debug stuff, which should not be translated!! */
3473 /* Create the paged pool progress bar */
3474 CopyContext.MemoryBars[0] = CreateProgressBar(13,
3475 40,
3476 13 + MemBarWidth,
3477 43,
3478 13,
3479 44,
3480 FALSE,
3481 "Kernel Pool");
3482
3483 /* Create the non paged pool progress bar */
3484 CopyContext.MemoryBars[1] = CreateProgressBar((xScreen / 2)- (MemBarWidth / 2),
3485 40,
3486 (xScreen / 2) + (MemBarWidth / 2),
3487 43,
3488 (xScreen / 2)- (MemBarWidth / 2),
3489 44,
3490 FALSE,
3491 "Kernel Cache");
3492
3493 /* Create the global memory progress bar */
3494 CopyContext.MemoryBars[2] = CreateProgressBar(xScreen - 13 - MemBarWidth,
3495 40,
3496 xScreen - 13,
3497 43,
3498 xScreen - 13 - MemBarWidth,
3499 44,
3500 FALSE,
3501 "Free Memory");
3502
3503 /* Do the file copying */
3504 DoFileCopy(&USetupData, FileCopyCallback, &CopyContext);
3505
3506 /* If we get here, we're done, so cleanup the progress bar */
3507 DestroyProgressBar(CopyContext.ProgressBar);
3508 DestroyProgressBar(CopyContext.MemoryBars[0]);
3509 DestroyProgressBar(CopyContext.MemoryBars[1]);
3510 DestroyProgressBar(CopyContext.MemoryBars[2]);
3511
3512 /* Create the $winnt$.inf file */
3514
3515 /* Go display the next page */
3516 return REGISTRY_PAGE;
3517}
3518
3519
3520static VOID
3521__cdecl
3523{
3524 /* WARNING: Please keep this lookup table in sync with the resources! */
3525 static const UINT StringIDs[] =
3526 {
3527 STRING_DONE, /* Success */
3528 STRING_REGHIVEUPDATE, /* RegHiveUpdate */
3529 STRING_IMPORTFILE, /* ImportRegHive */
3530 STRING_DISPLAYSETTINGSUPDATE, /* DisplaySettingsUpdate */
3531 STRING_LOCALESETTINGSUPDATE, /* LocaleSettingsUpdate */
3532 STRING_ADDKBLAYOUTS, /* KeybLayouts */
3533 STRING_KEYBOARDSETTINGSUPDATE, /* KeybSettingsUpdate */
3534 STRING_CODEPAGEINFOUPDATE, /* CodePageInfoUpdate */
3535 };
3536
3537 va_list args;
3538
3539 if (RegStatus < ARRAYSIZE(StringIDs))
3540 {
3541 va_start(args, RegStatus);
3542 CONSOLE_SetStatusTextV(MUIGetString(StringIDs[RegStatus]), args);
3543 va_end(args);
3544 }
3545 else
3546 {
3547 CONSOLE_SetStatusText("Unknown status %d", RegStatus);
3548 }
3549}
3550
3551/*
3552 * Displays the RegistryPage.
3553 *
3554 * Next pages:
3555 * BootLoaderSelectPage
3556 * QuitPage
3557 *
3558 * SIDEEFFECTS
3559 * Calls UpdateRegistry
3560 *
3561 * RETURNS
3562 * Number of the next page.
3563 */
3564static PAGE_NUMBER
3566{
3567 ULONG Error;
3568
3570
3577 &s_SubstSettings);
3578 if (Error != ERROR_SUCCESS)
3579 {
3581 return QUIT_PAGE;
3582 }
3583 else
3584 {
3587 }
3588}
3589
3590
3591/*
3592 * Displays the BootLoaderSelectPage.
3593 *
3594 * Next pages:
3595 * SuccessPage
3596 * QuitPage
3597 *
3598 * RETURNS
3599 * Number of the next page.
3600 */
3601static PAGE_NUMBER
3603{
3604 USHORT Line = 12;
3605
3607
3608 /* We must have a supported system partition by now */
3610
3611 /*
3612 * If we repair an existing installation and we made it up to here,
3613 * this means a valid bootloader and boot entry have been found.
3614 * Thus, there is no need to re-install it: skip its installation.
3615 */
3616 if (RepairUpdateFlag)
3617 {
3619 goto Quit;
3620 }
3621
3622 /* For unattended setup, skip MBR installation or install on removable disk if needed */
3624 {
3625 if ((USetupData.MBRInstallType == 0) ||
3627 {
3628 goto Quit;
3629 }
3630 }
3631
3632 /*
3633 * We may install an MBR or VBR, but before that, check whether
3634 * we need to actually install the VBR on removable disk if the
3635 * system partition is not recognized.
3636 */
3637 if ((SystemPartition->DiskEntry->DiskStyle != PARTITION_STYLE_MBR) ||
3639 {
3641 goto Quit;
3642 }
3643
3644 /* Is it an unattended install on hdd? */
3646 {
3647 if ((USetupData.MBRInstallType == 2) ||
3649 {
3650 goto Quit;
3651 }
3652 }
3653
3655 CONSOLE_InvertTextXY(8, Line, 60, 1);
3656
3657 while (TRUE)
3658 {
3659 CONSOLE_ConInKey(Ir);
3660
3661 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3662 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
3663 {
3664 CONSOLE_NormalTextXY(8, Line, 60, 1);
3665
3666 Line++;
3667 if (Line < 12)
3668 Line = 15;
3669
3670 if (Line > 15)
3671 Line = 12;
3672
3673 CONSOLE_InvertTextXY(8, Line, 60, 1);
3674 }
3675 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3676 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
3677 {
3678 CONSOLE_NormalTextXY(8, Line, 60, 1);
3679
3680 Line--;
3681 if (Line < 12)
3682 Line = 15;
3683
3684 if (Line > 15)
3685 Line = 12;
3686
3687 CONSOLE_InvertTextXY(8, Line, 60, 1);
3688 }
3689 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3690 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_HOME)) /* HOME */
3691 {
3692 CONSOLE_NormalTextXY(8, Line, 60, 1);
3693
3694 Line = 12;
3695
3696 CONSOLE_InvertTextXY(8, Line, 60, 1);
3697 }
3698 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3699 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_END)) /* END */
3700 {
3701 CONSOLE_NormalTextXY(8, Line, 60, 1);
3702
3703 Line = 15;
3704
3705 CONSOLE_InvertTextXY(8, Line, 60, 1);
3706 }
3707 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3708 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
3709 {
3710 if (ConfirmQuit(Ir))
3711 return QUIT_PAGE;
3712
3713 break;
3714 }
3715 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
3716 {
3717 if (Line == 12)
3718 {
3719 /* Install on both MBR and VBR */
3721 break;
3722 }
3723 else if (Line == 13)
3724 {
3725 /* Install on VBR only */
3727 break;
3728 }
3729 else if (Line == 14)
3730 {
3731 /* Install on removable disk */
3733 break;
3734 }
3735 else if (Line == 15)
3736 {
3737 /* Skip installation */
3739 break;
3740 }
3741
3743 }
3744 }
3745
3746Quit:
3747 /* Continue the installation; the bootloader is installed at the end */
3749}
3750
3751
3752/*
3753 * Installs the bootloader on removable disk.
3754 */
3755static BOOLEAN
3757{
3759
3760Retry:
3762 CONSOLE_Flush();
3764// CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
3765
3766 while (TRUE)
3767 {
3768 CONSOLE_ConInKey(Ir);
3769
3770 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3771 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
3772 {
3773 if (ConfirmQuit(Ir))
3774 return FALSE;
3775
3776 break;
3777 }
3778 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
3779 {
3782 if (!NT_SUCCESS(Status))
3783 {
3786
3787 /* TODO: Print error message */
3788 goto Retry;
3789 }
3790
3791 return TRUE;
3792 }
3793 }
3794
3795 goto Retry;
3796}
3797
3798/*
3799 * Installs the bootloader on hard-disk.
3800 */
3801static BOOLEAN
3803{
3805 WCHAR DestinationDevicePathBuffer[MAX_PATH];
3806
3807 if (USetupData.MBRInstallType == 2)
3808 {
3809 /* Step 1: Write the VBR */
3814 if (!NT_SUCCESS(Status))
3815 {
3818 return FALSE;
3819 }
3820
3821 /* Step 2: Write the MBR if the disk containing the system partition is not a super-floppy */
3823 {
3824 RtlStringCchPrintfW(DestinationDevicePathBuffer, ARRAYSIZE(DestinationDevicePathBuffer),
3825 L"\\Device\\Harddisk%d\\Partition0",
3826 SystemPartition->DiskEntry->DiskNumber);
3829 DestinationDevicePathBuffer);
3830 if (!NT_SUCCESS(Status))
3831 {
3832 DPRINT1("InstallMbrBootCodeToDisk() failed: Status 0x%lx\n", Status);
3834 return FALSE;
3835 }
3836 }
3837 }
3838 else
3839 {
3844 if (!NT_SUCCESS(Status))
3845 {
3848 return FALSE;
3849 }
3850 }
3851
3852 return TRUE;
3853}
3854
3855/*
3856 * Actually installs the bootloader at the end of the installation.
3857 * The bootloader installation place has already been chosen before,
3858 * see BootLoaderSelectPage().
3859 *
3860 * Next pages:
3861 * SuccessPage (At once)
3862 * QuitPage
3863 *
3864 * RETURNS
3865 * Number of the next page.
3866 */
3867static PAGE_NUMBER
3869{
3870 WCHAR PathBuffer[MAX_PATH];
3871
3872 // /* We must have a supported system partition by now */
3873 // ASSERT(SystemPartition && SystemPartition->IsPartitioned && SystemPartition->PartitionNumber != 0);
3874
3876 RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
3877 L"\\Device\\Harddisk%lu\\Partition%lu\\",
3878 SystemPartition->DiskEntry->DiskNumber,
3881 DPRINT1("SystemRootPath: %wZ\n", &USetupData.SystemRootPath);
3882
3883 if (USetupData.MBRInstallType != 0)
3885
3886 switch (USetupData.MBRInstallType)
3887 {
3888 /* Skip installation */
3889 case 0:
3890 return SUCCESS_PAGE;
3891
3892 /* Install on removable disk */
3893 case 1:
3895
3896 /* Install on hard-disk (both MBR and VBR, or VBR only) */
3897 case 2:
3898 case 3:
3900
3901 default:
3902 return SUCCESS_PAGE;
3903 }
3904}
3905
3906
3929static
3933 IN BOOLEAN AlwaysUpdate,
3934 OUT PSTR Buffer,
3935 IN SIZE_T cchBufferSize)
3936{
3937 ULONG OldProgress = Bar->Progress;
3938
3939 if (Bar->StepCount == 0)
3940 {
3941 Bar->Progress = 0;
3942 }
3943 else
3944 {
3945 Bar->Progress = Bar->StepCount - Bar->CurrentStep;
3946 }
3947
3948 /* Build the progress string if it has changed */
3949 if (Bar->ProgressFormatText &&
3950 (AlwaysUpdate || (Bar->Progress != OldProgress)))
3951 {
3952 RtlStringCchPrintfA(Buffer, cchBufferSize,
3953 Bar->ProgressFormatText, Bar->Progress / max(1, Bar->Width) + 1);
3954
3955 return TRUE;
3956 }
3957
3958 return FALSE;
3959}
3960
3977static VOID
3979 IN PINPUT_RECORD Ir,
3980 IN LONG TimeOut)
3981{
3983 ULONG StartTime, BarWidth, TimerDiv;
3984 LONG TimeElapsed;
3985 LONG TimerValue, OldTimerValue;
3987 PPROGRESSBAR ProgressBar;
3988 BOOLEAN RefreshProgress = TRUE;
3989
3990 /* Bail out if the timeout is already zero */
3991 if (TimeOut <= 0)
3992 return;
3993
3994 /* Create the timeout progress bar and set it up */
3995 ProgressBar = CreateProgressBarEx(13,
3996 26,
3997 xScreen - 13,
3998 yScreen - 20,
3999 10,
4000 24,
4001 TRUE,
4003 0,
4004 NULL,
4007
4008 BarWidth = max(1, ProgressBar->Width);
4009 TimerValue = TimeOut * BarWidth;
4010 ProgressSetStepCount(ProgressBar, TimerValue);
4011
4013 CONSOLE_Flush();
4014
4015 TimerDiv = 1000 / BarWidth;
4016 TimerDiv = max(1, TimerDiv);
4017 OldTimerValue = TimerValue;
4018 while (TRUE)
4019 {
4020 /* Decrease the timer */
4021
4022 /*
4023 * Compute how much time the previous operations took.
4024 * This allows us in particular to take account for any time
4025 * elapsed if something slowed down.
4026 */
4027 TimeElapsed = NtGetTickCount() - StartTime;
4028 if (TimeElapsed >= TimerDiv)
4029 {
4030 /* Increase StartTime by steps of 1 / ProgressBar->Width seconds */
4031 TimeElapsed /= TimerDiv;
4032 StartTime += (TimerDiv * TimeElapsed);
4033
4034 if (TimeElapsed <= TimerValue)
4035 TimerValue -= TimeElapsed;
4036 else
4037 TimerValue = 0;
4038
4039 RefreshProgress = TRUE;
4040 }
4041
4042 if (RefreshProgress)
4043 {
4044 ProgressSetStep(ProgressBar, OldTimerValue - TimerValue);
4045 RefreshProgress = FALSE;
4046 }
4047
4048 /* Stop when the timer reaches zero */
4049 if (TimerValue <= 0)
4050 break;
4051
4052 /* Check for user key presses */
4053
4054 /*
4055 * If the timer is used, use a passive wait of maximum 1 second
4056 * while monitoring for incoming console input events, so that
4057 * we are still able to display the timing count.
4058 */
4059
4060 /* Wait a maximum of 1 second for input events */
4061 TimeElapsed = NtGetTickCount() - StartTime;
4062 if (TimeElapsed < TimerDiv)
4063 {
4064 /* Convert the time to NT format */
4065 Timeout.QuadPart = (TimerDiv - TimeElapsed) * -10000LL;
4067 }
4068 else
4069 {
4071 }
4072
4073 /* Check whether the input event has been signaled, or a timeout happened */
4074 if (Status == STATUS_TIMEOUT)
4075 {
4076 continue;
4077 }
4078 if (Status != STATUS_WAIT_0)
4079 {
4080 /* An error happened, bail out */
4081 DPRINT1("NtWaitForSingleObject() failed, Status 0x%08lx\n", Status);
4082 break;
4083 }
4084
4085 /* Check for an ENTER key press */
4086 while (CONSOLE_ConInKeyPeek(Ir))
4087 {
4088 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
4089 {
4090 /* Found it, stop waiting */
4091 goto Exit;
4092 }
4093 }
4094 }
4095
4096Exit:
4097 /* Destroy the progress bar and quit */
4098 DestroyProgressBar(ProgressBar);
4099}
4100
4101
4102/*
4103 * Displays the QuitPage.
4104 *
4105 * Next pages:
4106 * FlushPage (At once)
4107 *
4108 * SIDEEFFECTS
4109 * Destroy the Lists
4110 *
4111 * RETURNS
4112 * Number of the next page.
4113 */
4114static PAGE_NUMBER
4116{
4118
4119 /* Destroy the NTOS installations list */
4120 if (NtOsInstallsList != NULL)
4121 {
4124 }
4125
4126 /* Destroy the partition list */
4127 if (PartitionList != NULL)
4128 {
4131 }
4132
4133 /* Reset the formatter machine state */
4136
4137 /* Destroy the filesystem list */
4139
4141
4142 /* Wait for maximum 15 seconds or an ENTER key before quitting */
4143 ProgressCountdown(Ir, 15);
4144 return FLUSH_PAGE;
4145}
4146
4147
4148/*
4149 * Displays the SuccessPage.
4150 *
4151 * Next pages:
4152 * FlushPage (At once)
4153 *
4154 * SIDEEFFECTS
4155 * Destroy the Lists
4156 *
4157 * RETURNS
4158 * Number of the next page.
4159 */
4160static PAGE_NUMBER
4162{
4164
4166 return FLUSH_PAGE;
4167
4168 /* Wait for maximum 15 seconds or an ENTER key before quitting */
4169 ProgressCountdown(Ir, 15);
4170 return FLUSH_PAGE;
4171}
4172
4173
4174/*
4175 * Displays the FlushPage.
4176 *
4177 * Next pages:
4178 * RebootPage (At once)
4179 *
4180 * RETURNS
4181 * Number of the next page.
4182 */
4183static PAGE_NUMBER
4185{
4187 return REBOOT_PAGE;
4188}
4189
4190
4191/*
4192 * The start routine and page management
4193 */
4196{
4198 INPUT_RECORD Ir;
4200 BOOLEAN Old;
4201
4203
4204 /* Tell the Cm this is a setup boot, and it has to behave accordingly */
4206 if (!NT_SUCCESS(Status))
4207 DPRINT1("NtInitializeRegistry() failed (Status 0x%08lx)\n", Status);
4208
4209 /* Initialize the user-mode PnP manager */
4211 if (!NT_SUCCESS(Status))
4212 {
4213 // PrintString(??);
4214 DPRINT1("The user-mode PnP manager could not initialize (Status 0x%08lx), expect unavailable devices!\n", Status);
4215 }
4216
4217 if (!CONSOLE_Init())
4218 {
4222
4223 /* We failed to initialize the video, just quit the installer */
4225 }
4226
4227 /* Initialize Setup, phase 0 */
4230
4231 /* Hide the cursor and clear the screen and keyboard buffer */
4234 CONSOLE_Flush();
4235
4236 /* Global Initialization page */
4237 Page = SetupStartPage(&Ir);
4238
4239 while (Page != REBOOT_PAGE && Page != RECOVERY_PAGE)
4240 {
4242 CONSOLE_Flush();
4243
4244 // CONSOLE_SetUnderlinedTextXY(4, 3, " ReactOS " KERNEL_VERSION_STR " Setup ");
4245
4246 switch (Page)
4247 {
4248 /* Language page */
4249 case LANGUAGE_PAGE:
4250 Page = LanguagePage(&Ir);
4251 break;
4252
4253 /* Welcome page */
4254 case WELCOME_PAGE:
4255 Page = WelcomePage(&Ir);
4256 break;
4257
4258 /* License page */
4259 case LICENSE_PAGE:
4260 Page = LicensePage(&Ir);
4261 break;
4262
4263 /* Install pages */
4264 case INSTALL_INTRO_PAGE:
4265 Page = InstallIntroPage(&Ir);
4266 break;
4267
4268#if 0
4269 case SCSI_CONTROLLER_PAGE:
4270 Page = ScsiControllerPage(&Ir);
4271 break;
4272
4273 case OEM_DRIVER_PAGE:
4274 Page = OemDriverPage(&Ir);
4275 break;
4276#endif
4277
4279 Page = DeviceSettingsPage(&Ir);
4280 break;
4281
4284 break;
4285
4288 break;
4289
4292 break;
4293
4295 Page = LayoutSettingsPage(&Ir);
4296 break;
4297
4298 /* Partitioning pages */
4301 break;
4302
4305 break;
4306
4309 break;
4310
4313 break;
4314
4315 /* Filesystem partition operations pages */
4318 break;
4319
4322 break;
4323
4326 break;
4327
4328 /* Bootloader selection page */
4331 break;
4332
4333 /* Installation pages */
4336 break;
4337
4338 case PREPARE_COPY_PAGE:
4339 Page = PrepareCopyPage(&Ir);
4340 break;
4341
4342 case FILE_COPY_PAGE:
4343 Page = FileCopyPage(&Ir);
4344 break;
4345
4346 case REGISTRY_PAGE:
4347 Page = RegistryPage(&Ir);
4348 break;
4349
4350 /* Bootloader installation page */
4352 // case BOOTLOADER_REMOVABLE_DISK_PAGE:
4354 break;
4355
4356 /* Repair pages */
4357 case REPAIR_INTRO_PAGE:
4358 Page = RepairIntroPage(&Ir);
4359 break;
4360
4362 Page = UpgradeRepairPage(&Ir);
4363 break;
4364
4365 case SUCCESS_PAGE:
4366 Page = SuccessPage(&Ir);
4367 break;
4368
4369 case FLUSH_PAGE:
4370 Page = FlushPage(&Ir);
4371 break;
4372
4373 case QUIT_PAGE:
4374 Page = QuitPage(&Ir);
4375 break;
4376
4377 /* Virtual pages */
4378 case SETUP_INIT_PAGE:
4379 case REBOOT_PAGE:
4380 case RECOVERY_PAGE:
4381 break;
4382
4383 default:
4384 break;
4385 }
4386 }
4387
4388 /* Terminate the user-mode PnP manager */
4390
4391 /* Setup has finished */
4393
4394 if (Page == RECOVERY_PAGE)
4396
4397 FreeConsole();
4398
4399 /* Reboot */
4403
4404 return STATUS_SUCCESS;
4405}
4406
4407
4408VOID NTAPI
4410{
4413
4415
4417
4419
4420 Status = RunUSetup();
4421
4422 if (NT_SUCCESS(Status))
4423 {
4424 /*
4425 * Avoid a bugcheck if RunUSetup() finishes too quickly by implementing
4426 * a protective waiting.
4427 * This wait is needed because, since we are started as SMSS.EXE,
4428 * the NT kernel explicitly waits 5 seconds for the initial process
4429 * SMSS.EXE to initialize (as a protective measure), and otherwise
4430 * bugchecks with the code SESSION5_INITIALIZATION_FAILED.
4431 */
4432 Time.QuadPart += 50000000;
4434 }
4435 else
4436 {
4437 /* The installer failed to start: raise a hard error (crash the system/BSOD) */
4439 0, 0, NULL, 0, NULL);
4440 }
4441
4443}
4444
4445/* 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:826
BOOLEAN PrepareFileCopy(IN OUT PUSETUP_DATA pSetupData, IN PFILE_COPY_STATUS_ROUTINE StatusRoutine OPTIONAL)
Definition: install.c:684
PGENERIC_LIST CreateKeyboardDriverList(IN HINF InfFile)
Definition: settings.c:1072
PGENERIC_LIST CreateComputerTypeList(IN HINF InfFile)
Definition: settings.c:524
ULONG GetDefaultLanguageIndex(VOID)
Definition: settings.c:1098
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:1209
PGENERIC_LIST CreateLanguageList(IN HINF InfFile, OUT PWSTR DefaultLanguage)
Definition: settings.c:1159
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:1381
NTSTATUS InstallFatBootcodeToFloppy(IN PUNICODE_STRING SourceRootPath, IN PUNICODE_STRING DestinationArcPath)
Definition: bootsup.c:1426
NTSTATUS InstallMbrBootCodeToDisk(IN PUNICODE_STRING SystemRootPath, IN PUNICODE_STRING SourceRootPath, IN PCWSTR DestinationDevicePathBuffer)
Definition: bootsup.c:831
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
@ ERROR_SOURCE_PATH
Definition: errorcode.h:20
@ ERROR_NO_BUILD_PATH
Definition: errorcode.h:19