ReactOS  0.4.14-dev-843-g15bc263
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 
67 static WCHAR DefaultLanguage[20]; // Copy of string inside LanguageList
68 static WCHAR DefaultKBLayout[20]; // Copy of string inside KeyboardList
69 
71 
72 /* Global partition list on the system */
74 
75 /* Currently selected partition entry in the list */
77 
78 /* List of supported file systems for the partition to be formatted */
80 
81 /* Machine state for the formatter */
84 
85 /*****************************************************/
86 
89 
90 
91 /* FUNCTIONS ****************************************************************/
92 
93 static VOID
94 PrintString(char* fmt,...)
95 {
96  char buffer[512];
97  va_list ap;
100 
101  va_start(ap, fmt);
102  vsprintf(buffer, fmt, ap);
103  va_end(ap);
104 
109 }
110 
111 
112 static VOID
114  IN SHORT yTop,
115  IN SHORT Width,
116  IN SHORT Height)
117 {
118  COORD coPos;
119  DWORD Written;
120 
121  /* Draw upper left corner */
122  coPos.X = xLeft;
123  coPos.Y = yTop;
125  0xDA, // '+',
126  1,
127  coPos,
128  &Written);
129 
130  /* Draw upper edge */
131  coPos.X = xLeft + 1;
132  coPos.Y = yTop;
134  0xC4, // '-',
135  Width - 2,
136  coPos,
137  &Written);
138 
139  /* Draw upper right corner */
140  coPos.X = xLeft + Width - 1;
141  coPos.Y = yTop;
143  0xBF, // '+',
144  1,
145  coPos,
146  &Written);
147 
148  /* Draw right edge, inner space and left edge */
149  for (coPos.Y = yTop + 1; coPos.Y < yTop + Height - 1; coPos.Y++)
150  {
151  coPos.X = xLeft;
153  0xB3, // '|',
154  1,
155  coPos,
156  &Written);
157 
158  coPos.X = xLeft + 1;
160  ' ',
161  Width - 2,
162  coPos,
163  &Written);
164 
165  coPos.X = xLeft + Width - 1;
167  0xB3, // '|',
168  1,
169  coPos,
170  &Written);
171  }
172 
173  /* Draw lower left corner */
174  coPos.X = xLeft;
175  coPos.Y = yTop + Height - 1;
177  0xC0, // '+',
178  1,
179  coPos,
180  &Written);
181 
182  /* Draw lower edge */
183  coPos.X = xLeft + 1;
184  coPos.Y = yTop + Height - 1;
186  0xC4, // '-',
187  Width - 2,
188  coPos,
189  &Written);
190 
191  /* Draw lower right corner */
192  coPos.X = xLeft + Width - 1;
193  coPos.Y = yTop + Height - 1;
195  0xD9, // '+',
196  1,
197  coPos,
198  &Written);
199 }
200 
201 
202 VOID
204  PCCH Status,
205  PINPUT_RECORD Ir,
206  ULONG WaitEvent)
207 {
208  SHORT yTop;
209  SHORT xLeft;
210  COORD coPos;
211  DWORD Written;
212  ULONG Length;
213  ULONG MaxLength;
214  ULONG Lines;
215  PCHAR p;
216  PCCH pnext;
217  BOOLEAN LastLine;
218  SHORT Width;
219  SHORT Height;
220 
221  /* Count text lines and longest line */
222  MaxLength = 0;
223  Lines = 0;
224  pnext = Text;
225 
226  while (TRUE)
227  {
228  p = strchr(pnext, '\n');
229 
230  if (p == NULL)
231  {
232  Length = strlen(pnext);
233  LastLine = TRUE;
234  }
235  else
236  {
237  Length = (ULONG)(p - pnext);
238  LastLine = FALSE;
239  }
240 
241  Lines++;
242 
243  if (Length > MaxLength)
244  MaxLength = Length;
245 
246  if (LastLine)
247  break;
248 
249  pnext = p + 1;
250  }
251 
252  /* Check length of status line */
253  if (Status != NULL)
254  {
255  Length = strlen(Status);
256 
257  if (Length > MaxLength)
258  MaxLength = Length;
259  }
260 
261  Width = MaxLength + 4;
262  Height = Lines + 2;
263 
264  if (Status != NULL)
265  Height += 2;
266 
267  yTop = (yScreen - Height) / 2;
268  xLeft = (xScreen - Width) / 2;
269 
270 
271  /* Set screen attributes */
272  coPos.X = xLeft;
273  for (coPos.Y = yTop; coPos.Y < yTop + Height; coPos.Y++)
274  {
277  Width,
278  coPos,
279  &Written);
280  }
281 
282  DrawBox(xLeft, yTop, Width, Height);
283 
284  /* Print message text */
285  coPos.Y = yTop + 1;
286  pnext = Text;
287  while (TRUE)
288  {
289  p = strchr(pnext, '\n');
290 
291  if (p == NULL)
292  {
293  Length = strlen(pnext);
294  LastLine = TRUE;
295  }
296  else
297  {
298  Length = (ULONG)(p - pnext);
299  LastLine = FALSE;
300  }
301 
302  if (Length != 0)
303  {
304  coPos.X = xLeft + 2;
306  pnext,
307  Length,
308  coPos,
309  &Written);
310  }
311 
312  if (LastLine)
313  break;
314 
315  coPos.Y++;
316  pnext = p + 1;
317  }
318 
319  /* Print separator line and status text */
320  if (Status != NULL)
321  {
322  coPos.Y = yTop + Height - 3;
323  coPos.X = xLeft;
325  0xC3, // '+',
326  1,
327  coPos,
328  &Written);
329 
330  coPos.X = xLeft + 1;
332  0xC4, // '-',
333  Width - 2,
334  coPos,
335  &Written);
336 
337  coPos.X = xLeft + Width - 1;
339  0xB4, // '+',
340  1,
341  coPos,
342  &Written);
343 
344  coPos.Y++;
345  coPos.X = xLeft + 2;
347  Status,
348  min(strlen(Status), (SIZE_T)Width - 4),
349  coPos,
350  &Written);
351  }
352 
353  if (WaitEvent == POPUP_WAIT_NONE)
354  return;
355 
356  while (TRUE)
357  {
358  CONSOLE_ConInKey(Ir);
359 
360  if (WaitEvent == POPUP_WAIT_ANY_KEY ||
361  Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)
362  {
363  return;
364  }
365  }
366 }
367 
368 
369 /*
370  * Confirm quit setup
371  * RETURNS
372  * TRUE: Quit setup.
373  * FALSE: Don't quit setup.
374  */
375 static BOOL
377 {
378  BOOL Result = FALSE;
380 
381  while (TRUE)
382  {
383  CONSOLE_ConInKey(Ir);
384 
385  if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
386  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
387  {
388  Result = TRUE;
389  break;
390  }
391  else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
392  {
393  Result = FALSE;
394  break;
395  }
396  }
397 
398  return Result;
399 }
400 
401 
402 static VOID
404 {
405  PGENERIC_LIST_ENTRY ListEntry;
406  PCWSTR pszNewLayout;
407 
409 
410  if (USetupData.LayoutList == NULL)
411  {
413  if (USetupData.LayoutList == NULL)
414  {
415  /* FIXME: Handle error! */
416  return;
417  }
418  }
419 
420  /* Search for default layout (if provided) */
421  if (pszNewLayout != NULL)
422  {
423  for (ListEntry = GetFirstListEntry(USetupData.LayoutList); ListEntry;
424  ListEntry = GetNextListEntry(ListEntry))
425  {
426  if (!wcscmp(pszNewLayout, ((PGENENTRY)GetListEntryData(ListEntry))->Id))
427  {
428  SetCurrentListEntry(USetupData.LayoutList, ListEntry);
429  break;
430  }
431  }
432  }
433 }
434 
435 
436 static NTSTATUS
437 NTAPI
440  OUT PSTR Buffer,
442 {
445 }
446 
447 static NTSTATUS
448 NTAPI
451  OUT PSTR Buffer,
453 {
455  PPARTENTRY PartEntry = NtOsInstall->PartEntry;
456 
457  if (PartEntry && PartEntry->DriveLetter)
458  {
459  /* We have retrieved a partition that is mounted */
461  "%C:%S \"%S\"",
462  PartEntry->DriveLetter,
463  NtOsInstall->PathComponent,
464  NtOsInstall->InstallationName);
465  }
466  else
467  {
468  /* We failed somewhere, just show the NT path */
470  "%wZ \"%S\"",
471  &NtOsInstall->SystemNtPath,
472  NtOsInstall->InstallationName);
473  }
474 }
475 
476 
477 /*
478  * Displays the LanguagePage.
479  *
480  * Next pages: WelcomePage, QuitPage
481  *
482  * SIDEEFFECTS
483  * Init SelectedLanguageId
484  * Init USetupData.LanguageId
485  *
486  * RETURNS
487  * Number of the next page.
488  */
489 static PAGE_NUMBER
491 {
492  GENERIC_LIST_UI ListUi;
493  PCWSTR NewLanguageId;
494  BOOL RefreshPage = FALSE;
495 
496  /* Initialize the computer settings list */
497  if (USetupData.LanguageList == NULL)
498  {
499  USetupData.LanguageList = CreateLanguageList(USetupData.SetupInf, DefaultLanguage);
500  if (USetupData.LanguageList == NULL)
501  {
502  PopupError("Setup failed to initialize available translations", NULL, NULL, POPUP_WAIT_NONE);
503  return WELCOME_PAGE;
504  }
505  }
506 
508  USetupData.LanguageId = 0;
509 
510  /* Load the font */
512  UpdateKBLayout();
513 
514  /*
515  * If there is no language or just a single one in the list,
516  * skip the language selection process altogether.
517  */
518  if (GetNumberOfListEntries(USetupData.LanguageList) <= 1)
519  {
520  USetupData.LanguageId = (LANGID)(wcstol(SelectedLanguageId, NULL, 16) & 0xFFFF);
521  return WELCOME_PAGE;
522  }
523 
524  InitGenericListUi(&ListUi, USetupData.LanguageList, GetSettingDescription);
525  DrawGenericList(&ListUi,
526  2, 18,
527  xScreen - 3,
528  yScreen - 3);
529 
531 
533 
534  while (TRUE)
535  {
536  CONSOLE_ConInKey(Ir);
537 
538  if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
539  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
540  {
541  ScrollDownGenericList(&ListUi);
542  RefreshPage = TRUE;
543  }
544  else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
545  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
546  {
547  ScrollUpGenericList(&ListUi);
548  RefreshPage = TRUE;
549  }
550  if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
551  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_NEXT)) /* PAGE DOWN */
552  {
553  ScrollPageDownGenericList(&ListUi);
554  RefreshPage = TRUE;
555  }
556  else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
557  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_PRIOR)) /* PAGE UP */
558  {
559  ScrollPageUpGenericList(&ListUi);
560  RefreshPage = TRUE;
561  }
562  else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
563  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
564  {
565  if (ConfirmQuit(Ir))
566  return QUIT_PAGE;
567  else
568  RedrawGenericList(&ListUi);
569  }
570  else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
571  {
572  ASSERT(GetNumberOfListEntries(USetupData.LanguageList) >= 1);
573 
576 
577  USetupData.LanguageId = (LANGID)(wcstol(SelectedLanguageId, NULL, 16) & 0xFFFF);
578 
580  {
581  UpdateKBLayout();
582  }
583 
584  /* Load the font */
586 
587  return WELCOME_PAGE;
588  }
589  else if ((Ir->Event.KeyEvent.uChar.AsciiChar > 0x60) && (Ir->Event.KeyEvent.uChar.AsciiChar < 0x7b))
590  {
591  /* a-z */
593  RefreshPage = TRUE;
594  }
595 
596  if (RefreshPage)
597  {
598  ASSERT(GetNumberOfListEntries(USetupData.LanguageList) >= 1);
599 
600  NewLanguageId =
602 
603  if (wcscmp(SelectedLanguageId, NewLanguageId))
604  {
605  /* Clear the language page */
607 
608  SelectedLanguageId = NewLanguageId;
609 
610  /* Load the font */
612 
613  /* Redraw language selection page in native language */
615  }
616 
617  RefreshPage = FALSE;
618  }
619  }
620 
621  return WELCOME_PAGE;
622 }
623 
624 
625 /*
626  * Start page
627  *
628  * Next pages:
629  * LanguagePage (at once, default)
630  * InstallIntroPage (at once, if unattended)
631  * QuitPage
632  *
633  * SIDEEFFECTS
634  * Init Sdi
635  * Init USetupData.SourcePath
636  * Init USetupData.SourceRootPath
637  * Init USetupData.SourceRootDir
638  * Init USetupData.SetupInf
639  * Init USetupData.RequiredPartitionDiskSpace
640  * Init IsUnattendedSetup
641  * If unattended, init *List and sets the Codepage
642  * If unattended, init SelectedLanguageId
643  * If unattended, init USetupData.LanguageId
644  *
645  * RETURNS
646  * Number of the next page.
647  */
648 static PAGE_NUMBER
650 {
651  ULONG Error;
652  PGENERIC_LIST_ENTRY ListEntry;
653  PCWSTR LocaleId;
654 
656 
657  /* Initialize Setup, phase 1 */
659  if (Error != ERROR_SUCCESS)
660  {
662  return QUIT_PAGE;
663  }
664 
665  /* Initialize the user-mode PnP manager */
667  DPRINT1("The user-mode PnP manager could not initialize, expect unavailable devices!\n");
668 
669  /* Wait for any immediate pending installations to finish */
671  DPRINT1("WaitNoPendingInstallEvents() failed to wait!\n");
672 
674 
675  if (IsUnattendedSetup)
676  {
677  // TODO: Read options from inf
678  /* Load the hardware, language and keyboard layout lists */
679 
680  USetupData.ComputerList = CreateComputerTypeList(USetupData.SetupInf);
681  USetupData.DisplayList = CreateDisplayDriverList(USetupData.SetupInf);
682  USetupData.KeyboardList = CreateKeyboardDriverList(USetupData.SetupInf);
683 
684  USetupData.LanguageList = CreateLanguageList(USetupData.SetupInf, DefaultLanguage);
685 
686  /* new part */
688  wcscpy(DefaultLanguage, USetupData.LocaleID);
689  USetupData.LanguageId = (LANGID)(wcstol(SelectedLanguageId, NULL, 16) & 0xFFFF);
690 
692 
693  /* first we hack LanguageList */
694  for (ListEntry = GetFirstListEntry(USetupData.LanguageList); ListEntry;
695  ListEntry = GetNextListEntry(ListEntry))
696  {
697  LocaleId = ((PGENENTRY)GetListEntryData(ListEntry))->Id;
698  if (!wcsicmp(USetupData.LocaleID, LocaleId))
699  {
700  DPRINT("found %S in LanguageList\n", LocaleId);
701  SetCurrentListEntry(USetupData.LanguageList, ListEntry);
702  break;
703  }
704  }
705 
706  /* now LayoutList */
707  for (ListEntry = GetFirstListEntry(USetupData.LayoutList); ListEntry;
708  ListEntry = GetNextListEntry(ListEntry))
709  {
710  LocaleId = ((PGENENTRY)GetListEntryData(ListEntry))->Id;
711  if (!wcsicmp(USetupData.LocaleID, LocaleId))
712  {
713  DPRINT("found %S in LayoutList\n", LocaleId);
714  SetCurrentListEntry(USetupData.LayoutList, ListEntry);
715  break;
716  }
717  }
718 
720 
721  return INSTALL_INTRO_PAGE;
722  }
723 
724  return LANGUAGE_PAGE;
725 }
726 
727 
728 /*
729  * Displays the WelcomePage.
730  *
731  * Next pages:
732  * InstallIntroPage (default)
733  * RepairIntroPage
734  * RecoveryPage
735  * LicensePage
736  * QuitPage
737  *
738  * RETURNS
739  * Number of the next page.
740  */
741 static PAGE_NUMBER
743 {
745 
746  while (TRUE)
747  {
748  CONSOLE_ConInKey(Ir);
749 
750  if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
751  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
752  {
753  if (ConfirmQuit(Ir))
754  return QUIT_PAGE;
755 
756  break;
757  }
758  else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
759  {
760  return INSTALL_INTRO_PAGE;
761  }
762  else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'R') /* R */
763  {
764  return RECOVERY_PAGE; // REPAIR_INTRO_PAGE;
765  }
766  else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'L') /* L */
767  {
768  return LICENSE_PAGE;
769  }
770  }
771 
772  return WELCOME_PAGE;
773 }
774 
775 
776 /*
777  * Displays the License page.
778  *
779  * Next page:
780  * WelcomePage (default)
781  *
782  * RETURNS
783  * Number of the next page.
784  */
785 static PAGE_NUMBER
787 {
789 
790  while (TRUE)
791  {
792  CONSOLE_ConInKey(Ir);
793 
794  if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
795  {
796  return WELCOME_PAGE;
797  }
798  }
799 
800  return LICENSE_PAGE;
801 }
802 
803 
804 /*
805  * Displays the RepairIntroPage.
806  *
807  * Next pages:
808  * RebootPage (default)
809  * InstallIntroPage
810  * RecoveryPage
811  * IntroPage
812  *
813  * RETURNS
814  * Number of the next page.
815  */
816 static PAGE_NUMBER
818 {
820 
821  while (TRUE)
822  {
823  CONSOLE_ConInKey(Ir);
824 
825  if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
826  {
827  return REBOOT_PAGE;
828  }
829  else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'U') /* U */
830  {
832  return INSTALL_INTRO_PAGE;
833  }
834  else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'R') /* R */
835  {
836  return RECOVERY_PAGE;
837  }
838  else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
839  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
840  {
841  return WELCOME_PAGE;
842  }
843  }
844 
845  return REPAIR_INTRO_PAGE;
846 }
847 
848 /*
849  * Displays the UpgradeRepairPage.
850  *
851  * Next pages:
852  * RebootPage (default)
853  * InstallIntroPage
854  * RecoveryPage
855  * WelcomePage
856  *
857  * RETURNS
858  * Number of the next page.
859  */
860 static PAGE_NUMBER
862 {
863  GENERIC_LIST_UI ListUi;
864 
865 /*** HACK!! ***/
866  if (PartitionList == NULL)
867  {
869  if (PartitionList == NULL)
870  {
871  /* FIXME: show an error dialog */
873  return QUIT_PAGE;
874  }
876  {
878  return QUIT_PAGE;
879  }
880 
881  /* Reset the formatter machine state */
883  FormatState = Start;
884  }
885 /**************/
886 
888  if (!NtOsInstallsList)
889  DPRINT1("Failed to get a list of NTOS installations; continue installation...\n");
890 
891  /*
892  * If there is no available installation (or just a single one??) that can
893  * be updated in the list, just continue with the regular installation.
894  */
896  {
898 
899  // return INSTALL_INTRO_PAGE;
900  return DEVICE_SETTINGS_PAGE;
901  // return SCSI_CONTROLLER_PAGE;
902  }
903 
905 
907  DrawGenericList(&ListUi,
908  2, 23,
909  xScreen - 3,
910  yScreen - 3);
911 
912  // return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir);
913  while (TRUE)
914  {
915  CONSOLE_ConInKey(Ir);
916 
917  if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x00)
918  {
919  switch (Ir->Event.KeyEvent.wVirtualKeyCode)
920  {
921  case VK_DOWN: /* DOWN */
922  ScrollDownGenericList(&ListUi);
923  break;
924  case VK_UP: /* UP */
925  ScrollUpGenericList(&ListUi);
926  break;
927  case VK_NEXT: /* PAGE DOWN */
928  ScrollPageDownGenericList(&ListUi);
929  break;
930  case VK_PRIOR: /* PAGE UP */
931  ScrollPageUpGenericList(&ListUi);
932  break;
933  case VK_F3: /* F3 */
934  {
935  if (ConfirmQuit(Ir))
936  return QUIT_PAGE;
937  else
938  RedrawGenericList(&ListUi);
939  break;
940  }
941  case VK_ESCAPE: /* ESC */
942  {
943  RestoreGenericListUiState(&ListUi);
944  // return nextPage; // prevPage;
945 
946  // return INSTALL_INTRO_PAGE;
947  return DEVICE_SETTINGS_PAGE;
948  // return SCSI_CONTROLLER_PAGE;
949  }
950  }
951  }
952  else
953  {
954  // switch (toupper(Ir->Event.KeyEvent.uChar.AsciiChar))
955  // if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
956  if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'U') /* U */
957  {
958  /* Retrieve the current installation */
960 
963 
964  DPRINT1("Selected installation for repair: \"%S\" ; DiskNumber = %d , PartitionNumber = %d\n",
966 
968 
969  // return nextPage;
970  /***/return INSTALL_INTRO_PAGE;/***/
971  }
972  else if ((Ir->Event.KeyEvent.uChar.AsciiChar > 0x60) &&
973  (Ir->Event.KeyEvent.uChar.AsciiChar < 0x7b)) /* a-z */
974  {
976  }
977  }
978  }
979 
980  return UPGRADE_REPAIR_PAGE;
981 }
982 
983 
984 /*
985  * Displays the InstallIntroPage.
986  *
987  * Next pages:
988  * DeviceSettingsPage (At once if repair or update is selected)
989  * SelectPartitionPage (At once if unattended setup)
990  * DeviceSettingsPage (default)
991  * QuitPage
992  *
993  * RETURNS
994  * Number of the next page.
995  */
996 static PAGE_NUMBER
998 {
999  if (RepairUpdateFlag)
1000  {
1001 #if 1 /* Old code that looks good */
1002 
1003  // return SELECT_PARTITION_PAGE;
1004  return DEVICE_SETTINGS_PAGE;
1005 
1006 #else /* Possible new code? */
1007 
1008  return DEVICE_SETTINGS_PAGE;
1009  // return SCSI_CONTROLLER_PAGE;
1010 
1011 #endif
1012  }
1013 
1014  if (IsUnattendedSetup)
1015  return SELECT_PARTITION_PAGE;
1016 
1018 
1019  while (TRUE)
1020  {
1021  CONSOLE_ConInKey(Ir);
1022 
1023  if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1024  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1025  {
1026  if (ConfirmQuit(Ir))
1027  return QUIT_PAGE;
1028 
1029  break;
1030  }
1031  else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1032  {
1033  return UPGRADE_REPAIR_PAGE;
1034  }
1035  }
1036 
1037  return INSTALL_INTRO_PAGE;
1038 }
1039 
1040 
1041 #if 0
1042 static PAGE_NUMBER
1043 ScsiControllerPage(PINPUT_RECORD Ir)
1044 {
1045  // MUIDisplayPage(SCSI_CONTROLLER_PAGE);
1046 
1047  CONSOLE_SetTextXY(6, 8, "Setup detected the following mass storage devices:");
1048 
1049  /* FIXME: print loaded mass storage driver descriptions */
1050 #if 0
1051  CONSOLE_SetTextXY(8, 10, "TEST device");
1052 #endif
1053 
1054  CONSOLE_SetStatusText(" ENTER = Continue F3 = Quit");
1055 
1056  while (TRUE)
1057  {
1058  CONSOLE_ConInKey(Ir);
1059 
1060  if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1061  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1062  {
1063  if (ConfirmQuit(Ir))
1064  return QUIT_PAGE;
1065 
1066  break;
1067  }
1068  else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1069  {
1070  return DEVICE_SETTINGS_PAGE;
1071  }
1072  }
1073 
1074  return SCSI_CONTROLLER_PAGE;
1075 }
1076 
1077 static PAGE_NUMBER
1078 OemDriverPage(PINPUT_RECORD Ir)
1079 {
1080  // MUIDisplayPage(OEM_DRIVER_PAGE);
1081 
1082  CONSOLE_SetTextXY(6, 8, "This is the OEM driver page!");
1083 
1084  /* FIXME: Implement!! */
1085 
1086  CONSOLE_SetStatusText(" ENTER = Continue F3 = Quit");
1087 
1088  while (TRUE)
1089  {
1090  CONSOLE_ConInKey(Ir);
1091 
1092  if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1093  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1094  {
1095  if (ConfirmQuit(Ir))
1096  return QUIT_PAGE;
1097 
1098  break;
1099  }
1100  else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1101  {
1102  return DEVICE_SETTINGS_PAGE;
1103  }
1104  }
1105 
1106  return OEM_DRIVER_PAGE;
1107 }
1108 #endif
1109 
1110 
1111 /*
1112  * Displays the DeviceSettingsPage.
1113  *
1114  * Next pages:
1115  * SelectPartitionPage (At once if repair or update is selected)
1116  * ComputerSettingsPage
1117  * DisplaySettingsPage
1118  * KeyboardSettingsPage
1119  * LayoutsettingsPage
1120  * SelectPartitionPage
1121  * QuitPage
1122  *
1123  * SIDEEFFECTS
1124  * Init USetupData.ComputerList
1125  * Init USetupData.DisplayList
1126  * Init USetupData.KeyboardList
1127  * Init USetupData.LayoutList
1128  *
1129  * RETURNS
1130  * Number of the next page.
1131  */
1132 static PAGE_NUMBER
1134 {
1135  static ULONG Line = 16;
1136 
1137  /* Initialize the computer settings list */
1138  if (USetupData.ComputerList == NULL)
1139  {
1140  USetupData.ComputerList = CreateComputerTypeList(USetupData.SetupInf);
1141  if (USetupData.ComputerList == NULL)
1142  {
1144  return QUIT_PAGE;
1145  }
1146  }
1147 
1148  /* Initialize the display settings list */
1149  if (USetupData.DisplayList == NULL)
1150  {
1151  USetupData.DisplayList = CreateDisplayDriverList(USetupData.SetupInf);
1152  if (USetupData.DisplayList == NULL)
1153  {
1155  return QUIT_PAGE;
1156  }
1157  }
1158 
1159  /* Initialize the keyboard settings list */
1160  if (USetupData.KeyboardList == NULL)
1161  {
1162  USetupData.KeyboardList = CreateKeyboardDriverList(USetupData.SetupInf);
1163  if (USetupData.KeyboardList == NULL)
1164  {
1166  return QUIT_PAGE;
1167  }
1168  }
1169 
1170  /* Initialize the keyboard layout list */
1171  if (USetupData.LayoutList == NULL)
1172  {
1174  if (USetupData.LayoutList == NULL)
1175  {
1176  /* FIXME: report error */
1178  return QUIT_PAGE;
1179  }
1180  }
1181 
1182  if (RepairUpdateFlag)
1183  return SELECT_PARTITION_PAGE;
1184 
1185  // if (IsUnattendedSetup)
1186  // return SELECT_PARTITION_PAGE;
1187 
1189 
1194 
1195  CONSOLE_InvertTextXY(24, Line, 48, 1);
1196 
1197  while (TRUE)
1198  {
1199  CONSOLE_ConInKey(Ir);
1200 
1201  if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1202  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1203  {
1204  CONSOLE_NormalTextXY(24, Line, 48, 1);
1205 
1206  if (Line == 14)
1207  Line = 16;
1208  else if (Line == 16)
1209  Line = 11;
1210  else
1211  Line++;
1212 
1213  CONSOLE_InvertTextXY(24, Line, 48, 1);
1214  }
1215  else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1216  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1217  {
1218  CONSOLE_NormalTextXY(24, Line, 48, 1);
1219 
1220  if (Line == 11)
1221  Line = 16;
1222  else if (Line == 16)
1223  Line = 14;
1224  else
1225  Line--;
1226 
1227  CONSOLE_InvertTextXY(24, Line, 48, 1);
1228  }
1229  else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1230  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1231  {
1232  if (ConfirmQuit(Ir))
1233  return QUIT_PAGE;
1234 
1235  break;
1236  }
1237  else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1238  {
1239  if (Line == 11)
1240  return COMPUTER_SETTINGS_PAGE;
1241  else if (Line == 12)
1242  return DISPLAY_SETTINGS_PAGE;
1243  else if (Line == 13)
1244  return KEYBOARD_SETTINGS_PAGE;
1245  else if (Line == 14)
1246  return LAYOUT_SETTINGS_PAGE;
1247  else if (Line == 16)
1248  return SELECT_PARTITION_PAGE;
1249  }
1250  }
1251 
1252  return DEVICE_SETTINGS_PAGE;
1253 }
1254 
1255 
1256 /*
1257  * Handles generic selection lists.
1258  *
1259  * PARAMS
1260  * GenericList: The list to handle.
1261  * nextPage: The page it needs to jump to after this page.
1262  * Ir: The PINPUT_RECORD
1263  */
1264 static PAGE_NUMBER
1266  PAGE_NUMBER nextPage,
1267  PINPUT_RECORD Ir)
1268 {
1269  while (TRUE)
1270  {
1271  CONSOLE_ConInKey(Ir);
1272 
1273  if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1274  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1275  {
1276  ScrollDownGenericList(ListUi);
1277  }
1278  else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1279  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1280  {
1281  ScrollUpGenericList(ListUi);
1282  }
1283  else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1284  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_NEXT)) /* PAGE DOWN */
1285  {
1286  ScrollPageDownGenericList(ListUi);
1287  }
1288  else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1289  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_PRIOR)) /* PAGE UP */
1290  {
1291  ScrollPageUpGenericList(ListUi);
1292  }
1293  else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1294  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1295  {
1296  if (ConfirmQuit(Ir))
1297  return QUIT_PAGE;
1298  else
1299  RedrawGenericList(ListUi);
1300  }
1301  else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1302  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
1303  {
1304  RestoreGenericListUiState(ListUi);
1305  return nextPage; // Use some "prevPage;" instead?
1306  }
1307  else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1308  {
1309  return nextPage;
1310  }
1311  else if ((Ir->Event.KeyEvent.uChar.AsciiChar > 0x60) && (Ir->Event.KeyEvent.uChar.AsciiChar < 0x7b))
1312  {
1313  /* a-z */
1315  }
1316  }
1317 }
1318 
1319 
1320 /*
1321  * Displays the ComputerSettingsPage.
1322  *
1323  * Next pages:
1324  * DeviceSettingsPage
1325  * QuitPage
1326  *
1327  * RETURNS
1328  * Number of the next page.
1329  */
1330 static PAGE_NUMBER
1332 {
1333  GENERIC_LIST_UI ListUi;
1335 
1336  InitGenericListUi(&ListUi, USetupData.ComputerList, GetSettingDescription);
1337  DrawGenericList(&ListUi,
1338  2, 18,
1339  xScreen - 3,
1340  yScreen - 3);
1341 
1342  return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir);
1343 }
1344 
1345 
1346 /*
1347  * Displays the DisplaySettingsPage.
1348  *
1349  * Next pages:
1350  * DeviceSettingsPage
1351  * QuitPage
1352  *
1353  * RETURNS
1354  * Number of the next page.
1355  */
1356 static PAGE_NUMBER
1358 {
1359  GENERIC_LIST_UI ListUi;
1361 
1362  InitGenericListUi(&ListUi, USetupData.DisplayList, GetSettingDescription);
1363  DrawGenericList(&ListUi,
1364  2, 18,
1365  xScreen - 3,
1366  yScreen - 3);
1367 
1368  return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir);
1369 }
1370 
1371 
1372 /*
1373  * Displays the KeyboardSettingsPage.
1374  *
1375  * Next pages:
1376  * DeviceSettingsPage
1377  * QuitPage
1378  *
1379  * RETURNS
1380  * Number of the next page.
1381  */
1382 static PAGE_NUMBER
1384 {
1385  GENERIC_LIST_UI ListUi;
1387 
1388  InitGenericListUi(&ListUi, USetupData.KeyboardList, GetSettingDescription);
1389  DrawGenericList(&ListUi,
1390  2, 18,
1391  xScreen - 3,
1392  yScreen - 3);
1393 
1394  return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir);
1395 }
1396 
1397 
1398 /*
1399  * Displays the LayoutSettingsPage.
1400  *
1401  * Next pages:
1402  * DeviceSettingsPage
1403  * QuitPage
1404  *
1405  * RETURNS
1406  * Number of the next page.
1407  */
1408 static PAGE_NUMBER
1410 {
1411  GENERIC_LIST_UI ListUi;
1413 
1414  InitGenericListUi(&ListUi, USetupData.LayoutList, GetSettingDescription);
1415  DrawGenericList(&ListUi,
1416  2, 18,
1417  xScreen - 3,
1418  yScreen - 3);
1419 
1420  return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir);
1421 }
1422 
1423 
1424 static BOOL
1426 {
1427  ULONGLONG size;
1428 
1429  size = PartEntry->SectorCount.QuadPart * PartEntry->DiskEntry->BytesPerSector;
1430  size = (size + (512 * KB)) / MB; /* in MBytes */
1431 
1432  if (size < USetupData.RequiredPartitionDiskSpace)
1433  {
1434  /* Partition is too small so ask for another one */
1435  DPRINT1("Partition is too small (size: %I64u MB), required disk space is %lu MB\n", size, USetupData.RequiredPartitionDiskSpace);
1436  return FALSE;
1437  }
1438  else
1439  {
1440  return TRUE;
1441  }
1442 }
1443 
1444 
1445 /*
1446  * Displays the SelectPartitionPage.
1447  *
1448  * Next pages:
1449  * SelectFileSystemPage (At once if unattended)
1450  * SelectFileSystemPage (Default if free space is selected)
1451  * CreatePrimaryPartitionPage
1452  * CreateExtendedPartitionPage
1453  * CreateLogicalPartitionPage
1454  * ConfirmDeleteSystemPartitionPage (if the selected partition is the system partition, aka with the boot flag set)
1455  * DeletePartitionPage
1456  * QuitPage
1457  *
1458  * SIDEEFFECTS
1459  * Set InstallShortcut (only if not unattended + free space is selected)
1460  *
1461  * RETURNS
1462  * Number of the next page.
1463  */
1464 static PAGE_NUMBER
1466 {
1467  PARTLIST_UI ListUi;
1468  ULONG Error;
1469 
1470  if (PartitionList == NULL)
1471  {
1473  if (PartitionList == NULL)
1474  {
1476  return QUIT_PAGE;
1477  }
1479  {
1481  return QUIT_PAGE;
1482  }
1483 
1484  /* Reset the formatter machine state */
1485  TempPartition = NULL;
1486  FormatState = Start;
1487  }
1488 
1489  if (RepairUpdateFlag)
1490  {
1492 
1493  /* Determine the selected installation disk & partition */
1497  if (!InstallPartition)
1498  {
1499  DPRINT1("RepairUpdateFlag == TRUE, SelectPartition() returned FALSE, assert!\n");
1500  ASSERT(FALSE);
1501  }
1503 
1504  return SELECT_FILE_SYSTEM_PAGE;
1505  }
1506 
1508 
1511  2, 23,
1512  xScreen - 3,
1513  yScreen - 3);
1514  DrawPartitionList(&ListUi);
1515 
1516  if (IsUnattendedSetup)
1517  {
1518  /* Determine the selected installation disk & partition */
1520  USetupData.DestinationDiskNumber,
1521  USetupData.DestinationPartitionNumber);
1522  if (!InstallPartition)
1523  {
1525 
1526  if (USetupData.AutoPartition)
1527  {
1530 
1532  {
1536  TRUE);
1537  }
1538  else
1539  {
1543  TRUE);
1544  }
1545 
1546 // FIXME?? Aren't we going to enter an infinite loop, if this test fails??
1548  {
1550  USetupData.RequiredPartitionDiskSpace);
1551  return SELECT_PARTITION_PAGE; /* let the user select another partition */
1552  }
1553 
1555  return SELECT_FILE_SYSTEM_PAGE;
1556  }
1557  }
1558  else
1559  {
1561 
1562  DrawPartitionList(&ListUi); // FIXME: Doesn't make much sense...
1563 
1564 // FIXME?? Aren't we going to enter an infinite loop, if this test fails??
1566  {
1568  USetupData.RequiredPartitionDiskSpace);
1569  return SELECT_PARTITION_PAGE; /* let the user select another partition */
1570  }
1571 
1572  return SELECT_FILE_SYSTEM_PAGE;
1573  }
1574  }
1575 
1576  while (TRUE)
1577  {
1579 
1580  /* Update status text */
1581  if (CurrentPartition == NULL)
1582  {
1584  }
1586  {
1588  {
1590  }
1591  else
1592  {
1594  }
1595  }
1596  else
1597  {
1599  {
1601  {
1603  }
1604  else
1605  {
1607  }
1608  }
1609  else
1610  {
1612  }
1613  }
1614 
1615  CONSOLE_ConInKey(Ir);
1616 
1617  if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1618  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1619  {
1620  if (ConfirmQuit(Ir))
1621  {
1623  PartitionList = NULL;
1624  return QUIT_PAGE;
1625  }
1626 
1627  break;
1628  }
1629  else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1630  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1631  {
1632  ScrollDownPartitionList(&ListUi);
1633  }
1634  else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1635  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1636  {
1637  ScrollUpPartitionList(&ListUi);
1638  }
1639  else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
1640  {
1642 
1644  continue; // return SELECT_PARTITION_PAGE;
1645 
1646  /*
1647  * Check whether the user wants to install ReactOS on a disk that
1648  * is not recognized by the computer's firmware and if so, display
1649  * a warning since such disks may not be bootable.
1650  */
1651  if (CurrentPartition->DiskEntry->MediaType == FixedMedia &&
1652  !CurrentPartition->DiskEntry->BiosFound)
1653  {
1654  PopupError("The disk you have selected for installing ReactOS\n"
1655  "is not visible by the firmware of your computer,\n"
1656  "and so may not be bootable.\n"
1657  "Press ENTER to continue nonetheless.",
1659  Ir, POPUP_WAIT_ENTER);
1660  // return SELECT_PARTITION_PAGE;
1661  }
1662 
1664  {
1666  {
1668  if (Error != NOT_AN_ERROR)
1669  {
1671  return SELECT_PARTITION_PAGE;
1672  }
1673 
1676  0ULL,
1677  TRUE);
1678  }
1679  else
1680  {
1682  if (Error != NOT_AN_ERROR)
1683  {
1685  return SELECT_PARTITION_PAGE;
1686  }
1687 
1690  0ULL,
1691  TRUE);
1692  }
1693  }
1694 
1696  {
1698  USetupData.RequiredPartitionDiskSpace);
1699  return SELECT_PARTITION_PAGE; /* let the user select another partition */
1700  }
1701 
1703  return SELECT_FILE_SYSTEM_PAGE;
1704  }
1705  else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'P') /* P */
1706  {
1708 
1710  {
1712  if (Error != NOT_AN_ERROR)
1713  {
1715  return SELECT_PARTITION_PAGE;
1716  }
1717 
1719  }
1720  }
1721  else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'E') /* E */
1722  {
1724 
1726  {
1728  if (Error != NOT_AN_ERROR)
1729  {
1731  return SELECT_PARTITION_PAGE;
1732  }
1733 
1735  }
1736  }
1737  else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'L') /* L */
1738  {
1740 
1742  {
1744  if (Error != NOT_AN_ERROR)
1745  {
1747  return SELECT_PARTITION_PAGE;
1748  }
1749 
1751  }
1752  }
1753  else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'D') /* D */
1754  {
1755  UNICODE_STRING CurrentPartitionU;
1756  WCHAR PathBuffer[MAX_PATH];
1757 
1759 
1761  {
1763  return SELECT_PARTITION_PAGE;
1764  }
1765 
1766 // TODO: Do something similar before trying to format the partition?
1767  if (!CurrentPartition->New &&
1770  {
1772 
1773  RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
1774  L"\\Device\\Harddisk%lu\\Partition%lu\\",
1775  CurrentPartition->DiskEntry->DiskNumber,
1777  RtlInitUnicodeString(&CurrentPartitionU, PathBuffer);
1778 
1779  /*
1780  * Check whether the user attempts to delete the partition on which
1781  * the installation source is present. If so, fail with an error.
1782  */
1783  // &USetupData.SourceRootPath
1784  if (RtlPrefixUnicodeString(&CurrentPartitionU, &USetupData.SourcePath, TRUE))
1785  {
1787  return SELECT_PARTITION_PAGE;
1788  }
1789  }
1790 
1793  {
1795  }
1796 
1797  return DELETE_PARTITION_PAGE;
1798  }
1799  }
1800 
1801  return SELECT_PARTITION_PAGE;
1802 }
1803 
1804 
1805 #define PARTITION_SIZE_INPUT_FIELD_LENGTH 9
1806 /* Restriction for MaxSize */
1807 #define PARTITION_MAXSIZE (pow(10, (PARTITION_SIZE_INPUT_FIELD_LENGTH - 1)) - 1)
1808 
1809 static VOID
1811  SHORT Top,
1812  SHORT Right,
1813  SHORT Bottom,
1814  ULONG MaxSize,
1816  PBOOLEAN Quit,
1817  PBOOLEAN Cancel)
1818 {
1819  INPUT_RECORD Ir;
1820  COORD coPos;
1821  DWORD Written;
1822  CHAR Buffer[128];
1823  INT Length, Pos;
1824  WCHAR ch;
1825  SHORT iLeft;
1826  SHORT iTop;
1827 
1828  if (Quit != NULL)
1829  *Quit = FALSE;
1830 
1831  if (Cancel != NULL)
1832  *Cancel = FALSE;
1833 
1834  DrawBox(Left, Top, Right - Left + 1, Bottom - Top + 1);
1835 
1836  /* Print message */
1837  coPos.X = Left + 2;
1838  coPos.Y = Top + 2;
1840  iLeft = coPos.X + strlen(Buffer) + 1;
1841  iTop = coPos.Y;
1842 
1844  Buffer,
1845  strlen(Buffer),
1846  coPos,
1847  &Written);
1848 
1850  coPos.X = iLeft + PARTITION_SIZE_INPUT_FIELD_LENGTH + 1;
1851  coPos.Y = iTop;
1853  Buffer,
1854  strlen(Buffer),
1855  coPos,
1856  &Written);
1857 
1858  swprintf(InputBuffer, L"%lu", MaxSize);
1860  Pos = Length;
1861  CONSOLE_SetInputTextXY(iLeft,
1862  iTop,
1864  InputBuffer);
1865  CONSOLE_SetCursorXY(iLeft + Length, iTop);
1867 
1868  while (TRUE)
1869  {
1870  CONSOLE_ConInKey(&Ir);
1871 
1872  if ((Ir.Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1873  (Ir.Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1874  {
1875  if (Quit != NULL)
1876  *Quit = TRUE;
1877 
1880  break;
1881  }
1882  else if (Ir.Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
1883  {
1885  break;
1886  }
1887  else if (Ir.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESC */
1888  {
1889  if (Cancel != NULL)
1890  *Cancel = TRUE;
1891 
1894  break;
1895  }
1896  else if ((Ir.Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1897  (Ir.Event.KeyEvent.wVirtualKeyCode == VK_HOME)) /* HOME */
1898  {
1899  Pos = 0;
1900  CONSOLE_SetCursorXY(iLeft + Pos, iTop);
1901  }
1902  else if ((Ir.Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1903  (Ir.Event.KeyEvent.wVirtualKeyCode == VK_END)) /* END */
1904  {
1905  Pos = Length;
1906  CONSOLE_SetCursorXY(iLeft + Pos, iTop);
1907  }
1908  else if ((Ir.Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1909  (Ir.Event.KeyEvent.wVirtualKeyCode == VK_LEFT)) /* LEFT */
1910  {
1911  if (Pos > 0)
1912  {
1913  Pos--;
1914  CONSOLE_SetCursorXY(iLeft + Pos, iTop);
1915  }
1916  }
1917  else if ((Ir.Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1918  (Ir.Event.KeyEvent.wVirtualKeyCode == VK_RIGHT)) /* RIGHT */
1919  {
1920  if (Pos < Length)
1921  {
1922  Pos++;
1923  CONSOLE_SetCursorXY(iLeft + Pos, iTop);
1924  }
1925  }
1926  else if ((Ir.Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1927  (Ir.Event.KeyEvent.wVirtualKeyCode == VK_DELETE)) /* DEL */
1928  {
1929  if (Pos < Length)
1930  {
1932  &InputBuffer[Pos + 1],
1933  (Length - Pos - 1) * sizeof(WCHAR));
1935 
1936  Length--;
1937  CONSOLE_SetInputTextXY(iLeft,
1938  iTop,
1940  InputBuffer);
1941  CONSOLE_SetCursorXY(iLeft + Pos, iTop);
1942  }
1943  }
1944  else if (Ir.Event.KeyEvent.wVirtualKeyCode == VK_BACK) /* BACKSPACE */
1945  {
1946  if (Pos > 0)
1947  {
1948  if (Pos < Length)
1949  memmove(&InputBuffer[Pos - 1],
1950  &InputBuffer[Pos],
1951  (Length - Pos) * sizeof(WCHAR));
1953 
1954  Pos--;
1955  Length--;
1956  CONSOLE_SetInputTextXY(iLeft,
1957  iTop,
1959  InputBuffer);
1960  CONSOLE_SetCursorXY(iLeft + Pos, iTop);
1961  }
1962  }
1963  else if (Ir.Event.KeyEvent.uChar.AsciiChar != 0x00)
1964  {
1966  {
1967  ch = (WCHAR)Ir.Event.KeyEvent.uChar.AsciiChar;
1968 
1969  if ((ch >= L'0') && (ch <= L'9'))
1970  {
1971  if (Pos < Length)
1972  memmove(&InputBuffer[Pos + 1],
1973  &InputBuffer[Pos],
1974  (Length - Pos) * sizeof(WCHAR));
1976  InputBuffer[Pos] = ch;
1977 
1978  Pos++;
1979  Length++;
1980  CONSOLE_SetInputTextXY(iLeft,
1981  iTop,
1983  InputBuffer);
1984  CONSOLE_SetCursorXY(iLeft + Pos, iTop);
1985  }
1986  }
1987  }
1988  }
1989 }
1990 
1991 
1992 /*
1993  * Displays the CreatePrimaryPartitionPage.
1994  *
1995  * Next pages:
1996  * SelectPartitionPage
1997  * SelectFileSystemPage (default)
1998  * QuitPage
1999  *
2000  * RETURNS
2001  * Number of the next page.
2002  */
2003 static PAGE_NUMBER
2005 {
2006  PPARTENTRY PartEntry;
2007  PDISKENTRY DiskEntry;
2008  BOOLEAN Quit;
2009  BOOLEAN Cancel;
2010  WCHAR InputBuffer[50];
2011  ULONG MaxSize;
2012  ULONGLONG PartSize;
2013  ULONGLONG DiskSize;
2015  PCHAR Unit;
2016 
2017  if (PartitionList == NULL || CurrentPartition == NULL)
2018  {
2019  /* FIXME: show an error dialog */
2020  return QUIT_PAGE;
2021  }
2022 
2023  PartEntry = CurrentPartition;
2024  DiskEntry = CurrentPartition->DiskEntry;
2025 
2027 
2029 
2030  DiskSize = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
2031 #if 0
2032  if (DiskSize >= 10 * GB) /* 10 GB */
2033  {
2034  DiskSize = DiskSize / GB;
2036  }
2037  else
2038 #endif
2039  {
2040  DiskSize = DiskSize / MB;
2041  if (DiskSize == 0)
2042  DiskSize = 1;
2043 
2045  }
2046 
2047  if (DiskEntry->DriverName.Length > 0)
2048  {
2049  CONSOLE_PrintTextXY(6, 10,
2051  DiskSize,
2052  Unit,
2053  DiskEntry->DiskNumber,
2054  DiskEntry->Port,
2055  DiskEntry->Bus,
2056  DiskEntry->Id,
2057  &DiskEntry->DriverName,
2058  DiskEntry->DiskStyle == PARTITION_STYLE_MBR ? "MBR" :
2059  DiskEntry->DiskStyle == PARTITION_STYLE_GPT ? "GPT" :
2060  "RAW");
2061  }
2062  else
2063  {
2064  CONSOLE_PrintTextXY(6, 10,
2066  DiskSize,
2067  Unit,
2068  DiskEntry->DiskNumber,
2069  DiskEntry->Port,
2070  DiskEntry->Bus,
2071  DiskEntry->Id,
2072  DiskEntry->DiskStyle == PARTITION_STYLE_MBR ? "MBR" :
2073  DiskEntry->DiskStyle == PARTITION_STYLE_GPT ? "GPT" :
2074  "RAW");
2075  }
2076 
2078 
2079 #if 0
2080  CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2081  CurrentPartition->SectorCount * DiskEntry->BytesPerSector / MB);
2082 #endif
2083 
2085 
2086  PartEntry = CurrentPartition;
2087  while (TRUE)
2088  {
2089  MaxSize = (PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector) / MB; /* in MBytes (rounded) */
2090 
2091  if (MaxSize > PARTITION_MAXSIZE)
2092  MaxSize = PARTITION_MAXSIZE;
2093 
2094  ShowPartitionSizeInputBox(12, 14, xScreen - 12, 17, /* left, top, right, bottom */
2095  MaxSize, InputBuffer, &Quit, &Cancel);
2096 
2097  if (Quit)
2098  {
2099  if (ConfirmQuit(Ir))
2100  return QUIT_PAGE;
2101 
2102  break;
2103  }
2104  else if (Cancel)
2105  {
2106  return SELECT_PARTITION_PAGE;
2107  }
2108  else
2109  {
2110  PartSize = _wcstoui64(InputBuffer, NULL, 10);
2111 
2112  if (PartSize < 1)
2113  {
2114  /* Too small */
2115  continue;
2116  }
2117 
2118  if (PartSize > MaxSize)
2119  {
2120  /* Too large */
2121  continue;
2122  }
2123 
2124  /* Convert to bytes */
2125  if (PartSize == MaxSize)
2126  {
2127  /* Use all of the unpartitioned disk space */
2128  SectorCount = PartEntry->SectorCount.QuadPart;
2129  }
2130  else
2131  {
2132  /* Calculate the sector count from the size in MB */
2133  SectorCount = PartSize * MB / DiskEntry->BytesPerSector;
2134 
2135  /* But never get larger than the unpartitioned disk space */
2136  if (SectorCount > PartEntry->SectorCount.QuadPart)
2137  SectorCount = PartEntry->SectorCount.QuadPart;
2138  }
2139 
2140  DPRINT ("Partition size: %I64u bytes\n", PartSize);
2141 
2144  SectorCount,
2145  FALSE);
2146 
2147  return SELECT_PARTITION_PAGE;
2148  }
2149  }
2150 
2152 }
2153 
2154 
2155 /*
2156  * Displays the CreateExtendedPartitionPage.
2157  *
2158  * Next pages:
2159  * SelectPartitionPage (default)
2160  * QuitPage
2161  *
2162  * RETURNS
2163  * Number of the next page.
2164  */
2165 static PAGE_NUMBER
2167 {
2168  PPARTENTRY PartEntry;
2169  PDISKENTRY DiskEntry;
2170  BOOLEAN Quit;
2171  BOOLEAN Cancel;
2172  WCHAR InputBuffer[50];
2173  ULONG MaxSize;
2174  ULONGLONG PartSize;
2175  ULONGLONG DiskSize;
2177  PCHAR Unit;
2178 
2179  if (PartitionList == NULL || CurrentPartition == NULL)
2180  {
2181  /* FIXME: show an error dialog */
2182  return QUIT_PAGE;
2183  }
2184 
2185  PartEntry = CurrentPartition;
2186  DiskEntry = CurrentPartition->DiskEntry;
2187 
2189 
2191 
2192  DiskSize = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
2193 #if 0
2194  if (DiskSize >= 10 * GB) /* 10 GB */
2195  {
2196  DiskSize = DiskSize / GB;
2198  }
2199  else
2200 #endif
2201  {
2202  DiskSize = DiskSize / MB;
2203  if (DiskSize == 0)
2204  DiskSize = 1;
2205 
2207  }
2208 
2209  if (DiskEntry->DriverName.Length > 0)
2210  {
2211  CONSOLE_PrintTextXY(6, 10,
2213  DiskSize,
2214  Unit,
2215  DiskEntry->DiskNumber,
2216  DiskEntry->Port,
2217  DiskEntry->Bus,
2218  DiskEntry->Id,
2219  &DiskEntry->DriverName,
2220  DiskEntry->DiskStyle == PARTITION_STYLE_MBR ? "MBR" :
2221  DiskEntry->DiskStyle == PARTITION_STYLE_GPT ? "GPT" :
2222  "RAW");
2223  }
2224  else
2225  {
2226  CONSOLE_PrintTextXY(6, 10,
2228  DiskSize,
2229  Unit,
2230  DiskEntry->DiskNumber,
2231  DiskEntry->Port,
2232  DiskEntry->Bus,
2233  DiskEntry->Id,
2234  DiskEntry->DiskStyle == PARTITION_STYLE_MBR ? "MBR" :
2235  DiskEntry->DiskStyle == PARTITION_STYLE_GPT ? "GPT" :
2236  "RAW");
2237  }
2238 
2240 
2241 #if 0
2242  CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2243  CurrentPartition->SectorCount * DiskEntry->BytesPerSector / MB);
2244 #endif
2245 
2247 
2248  PartEntry = CurrentPartition;
2249  while (TRUE)
2250  {
2251  MaxSize = (PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector) / MB; /* in MBytes (rounded) */
2252 
2253  if (MaxSize > PARTITION_MAXSIZE)
2254  MaxSize = PARTITION_MAXSIZE;
2255 
2256  ShowPartitionSizeInputBox(12, 14, xScreen - 12, 17, /* left, top, right, bottom */
2257  MaxSize, InputBuffer, &Quit, &Cancel);
2258 
2259  if (Quit)
2260  {
2261  if (ConfirmQuit(Ir))
2262  return QUIT_PAGE;
2263 
2264  break;
2265  }
2266  else if (Cancel)
2267  {
2268  return SELECT_PARTITION_PAGE;
2269  }
2270  else
2271  {
2272  PartSize = _wcstoui64(InputBuffer, NULL, 10);
2273 
2274  if (PartSize < 1)
2275  {
2276  /* Too small */
2277  continue;
2278  }
2279 
2280  if (PartSize > MaxSize)
2281  {
2282  /* Too large */
2283  continue;
2284  }
2285 
2286  /* Convert to bytes */
2287  if (PartSize == MaxSize)
2288  {
2289  /* Use all of the unpartitioned disk space */
2290  SectorCount = PartEntry->SectorCount.QuadPart;
2291  }
2292  else
2293  {
2294  /* Calculate the sector count from the size in MB */
2295  SectorCount = PartSize * MB / DiskEntry->BytesPerSector;
2296 
2297  /* But never get larger than the unpartitioned disk space */
2298  if (SectorCount > PartEntry->SectorCount.QuadPart)
2299  SectorCount = PartEntry->SectorCount.QuadPart;
2300  }
2301 
2302  DPRINT ("Partition size: %I64u bytes\n", PartSize);
2303 
2306  SectorCount);
2307 
2308  return SELECT_PARTITION_PAGE;
2309  }
2310  }
2311 
2313 }
2314 
2315 
2316 /*
2317  * Displays the CreateLogicalPartitionPage.
2318  *
2319  * Next pages:
2320  * SelectFileSystemPage (default)
2321  * QuitPage
2322  *
2323  * RETURNS
2324  * Number of the next page.
2325  */
2326 static PAGE_NUMBER
2328 {
2329  PPARTENTRY PartEntry;
2330  PDISKENTRY DiskEntry;
2331  BOOLEAN Quit;
2332  BOOLEAN Cancel;
2333  WCHAR InputBuffer[50];
2334  ULONG MaxSize;
2335  ULONGLONG PartSize;
2336  ULONGLONG DiskSize;
2338  PCHAR Unit;
2339 
2340  if (PartitionList == NULL || CurrentPartition == NULL)
2341  {
2342  /* FIXME: show an error dialog */
2343  return QUIT_PAGE;
2344  }
2345 
2346  PartEntry = CurrentPartition;
2347  DiskEntry = CurrentPartition->DiskEntry;
2348 
2350 
2352 
2353  DiskSize = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
2354 #if 0
2355  if (DiskSize >= 10 * GB) /* 10 GB */
2356  {
2357  DiskSize = DiskSize / GB;
2359  }
2360  else
2361 #endif
2362  {
2363  DiskSize = DiskSize / MB;
2364  if (DiskSize == 0)
2365  DiskSize = 1;
2366 
2368  }
2369 
2370  if (DiskEntry->DriverName.Length > 0)
2371  {
2372  CONSOLE_PrintTextXY(6, 10,
2374  DiskSize,
2375  Unit,
2376  DiskEntry->DiskNumber,
2377  DiskEntry->Port,
2378  DiskEntry->Bus,
2379  DiskEntry->Id,
2380  &DiskEntry->DriverName,
2381  DiskEntry->DiskStyle == PARTITION_STYLE_MBR ? "MBR" :
2382  DiskEntry->DiskStyle == PARTITION_STYLE_GPT ? "GPT" :
2383  "RAW");
2384  }
2385  else
2386  {
2387  CONSOLE_PrintTextXY(6, 10,
2389  DiskSize,
2390  Unit,
2391  DiskEntry->DiskNumber,
2392  DiskEntry->Port,
2393  DiskEntry->Bus,
2394  DiskEntry->Id,
2395  DiskEntry->DiskStyle == PARTITION_STYLE_MBR ? "MBR" :
2396  DiskEntry->DiskStyle == PARTITION_STYLE_GPT ? "GPT" :
2397  "RAW");
2398  }
2399 
2401 
2402 #if 0
2403  CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2404  CurrentPartition->SectorCount * DiskEntry->BytesPerSector / MB);
2405 #endif
2406 
2408 
2409  PartEntry = CurrentPartition;
2410  while (TRUE)
2411  {
2412  MaxSize = (PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector) / MB; /* in MBytes (rounded) */
2413 
2414  if (MaxSize > PARTITION_MAXSIZE)
2415  MaxSize = PARTITION_MAXSIZE;
2416 
2417  ShowPartitionSizeInputBox(12, 14, xScreen - 12, 17, /* left, top, right, bottom */
2418  MaxSize, InputBuffer, &Quit, &Cancel);
2419 
2420  if (Quit)
2421  {
2422  if (ConfirmQuit(Ir))
2423  return QUIT_PAGE;
2424 
2425  break;
2426  }
2427  else if (Cancel)
2428  {
2429  return SELECT_PARTITION_PAGE;
2430  }
2431  else
2432  {
2433  PartSize = _wcstoui64(InputBuffer, NULL, 10);
2434 
2435  if (PartSize < 1)
2436  {
2437  /* Too small */
2438  continue;
2439  }
2440 
2441  if (PartSize > MaxSize)
2442  {
2443  /* Too large */
2444  continue;
2445  }
2446 
2447  /* Convert to bytes */
2448  if (PartSize == MaxSize)
2449  {
2450  /* Use all of the unpartitioned disk space */
2451  SectorCount = PartEntry->SectorCount.QuadPart;
2452  }
2453  else
2454  {
2455  /* Calculate the sector count from the size in MB */
2456  SectorCount = PartSize * MB / DiskEntry->BytesPerSector;
2457 
2458  /* But never get larger than the unpartitioned disk space */
2459  if (SectorCount > PartEntry->SectorCount.QuadPart)
2460  SectorCount = PartEntry->SectorCount.QuadPart;
2461  }
2462 
2463  DPRINT("Partition size: %I64u bytes\n", PartSize);
2464 
2467  SectorCount,
2468  FALSE);
2469 
2470  return SELECT_PARTITION_PAGE;
2471  }
2472  }
2473 
2475 }
2476 
2477 
2478 /*
2479  * Displays the ConfirmDeleteSystemPartitionPage.
2480  *
2481  * Next pages:
2482  * DeletePartitionPage (default)
2483  * SelectPartitionPage
2484  *
2485  * RETURNS
2486  * Number of the next page.
2487  */
2488 static PAGE_NUMBER
2490 {
2492 
2493  while (TRUE)
2494  {
2495  CONSOLE_ConInKey(Ir);
2496 
2497  if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2498  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
2499  {
2500  if (ConfirmQuit(Ir))
2501  return QUIT_PAGE;
2502 
2503  break;
2504  }
2505  else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
2506  {
2507  return DELETE_PARTITION_PAGE;
2508  }
2509  else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESC */
2510  {
2511  return SELECT_PARTITION_PAGE;
2512  }
2513  }
2514 
2516 }
2517 
2518 
2519 /*
2520  * Displays the DeletePartitionPage.
2521  *
2522  * Next pages:
2523  * SelectPartitionPage (default)
2524  * QuitPage
2525  *
2526  * RETURNS
2527  * Number of the next page.
2528  */
2529 static PAGE_NUMBER
2531 {
2532  PPARTENTRY PartEntry;
2533  PDISKENTRY DiskEntry;
2534  ULONGLONG DiskSize;
2535  ULONGLONG PartSize;
2536  PCHAR Unit;
2537  CHAR PartTypeString[32];
2538 
2539  if (PartitionList == NULL || CurrentPartition == NULL)
2540  {
2541  /* FIXME: show an error dialog */
2542  return QUIT_PAGE;
2543  }
2544 
2545  PartEntry = CurrentPartition;
2546  DiskEntry = CurrentPartition->DiskEntry;
2547 
2549 
2550  /* Adjust partition type */
2552  PartTypeString,
2553  ARRAYSIZE(PartTypeString));
2554 
2555  PartSize = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
2556 #if 0
2557  if (PartSize >= 10 * GB) /* 10 GB */
2558  {
2559  PartSize = PartSize / GB;
2561  }
2562  else
2563 #endif
2564  if (PartSize >= 10 * MB) /* 10 MB */
2565  {
2566  PartSize = PartSize / MB;
2568  }
2569  else
2570  {
2571  PartSize = PartSize / KB;
2573  }
2574 
2575  if (*PartTypeString == '\0') // STRING_FORMATUNKNOWN ??
2576  {
2577  CONSOLE_PrintTextXY(6, 10,
2579  (PartEntry->DriveLetter == 0) ? '-' : (CHAR)PartEntry->DriveLetter,
2580  (PartEntry->DriveLetter == 0) ? '-' : ':',
2581  PartEntry->PartitionType,
2582  PartSize,
2583  Unit);
2584  }
2585  else
2586  {
2587  CONSOLE_PrintTextXY(6, 10,
2588  " %c%c %s %I64u %s",
2589  (PartEntry->DriveLetter == 0) ? '-' : (CHAR)PartEntry->DriveLetter,
2590  (PartEntry->DriveLetter == 0) ? '-' : ':',
2591  PartTypeString,
2592  PartSize,
2593  Unit);
2594  }
2595 
2596  DiskSize = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
2597 #if 0
2598  if (DiskSize >= 10 * GB) /* 10 GB */
2599  {
2600  DiskSize = DiskSize / GB;
2602  }
2603  else
2604 #endif
2605  {
2606  DiskSize = DiskSize / MB;
2607  if (DiskSize == 0)
2608  DiskSize = 1;
2609 
2611  }
2612 
2613  if (DiskEntry->DriverName.Length > 0)
2614  {
2615  CONSOLE_PrintTextXY(6, 12,
2617  DiskSize,
2618  Unit,
2619  DiskEntry->DiskNumber,
2620  DiskEntry->Port,
2621  DiskEntry->Bus,
2622  DiskEntry->Id,
2623  &DiskEntry->DriverName,
2624  DiskEntry->DiskStyle == PARTITION_STYLE_MBR ? "MBR" :
2625  DiskEntry->DiskStyle == PARTITION_STYLE_GPT ? "GPT" :
2626  "RAW");
2627  }
2628  else
2629  {
2630  CONSOLE_PrintTextXY(6, 12,
2632  DiskSize,
2633  Unit,
2634  DiskEntry->DiskNumber,
2635  DiskEntry->Port,
2636  DiskEntry->Bus,
2637  DiskEntry->Id,
2638  DiskEntry->DiskStyle == PARTITION_STYLE_MBR ? "MBR" :
2639  DiskEntry->DiskStyle == PARTITION_STYLE_GPT ? "GPT" :
2640  "RAW");
2641  }
2642 
2643  while (TRUE)
2644  {
2645  CONSOLE_ConInKey(Ir);
2646 
2647  if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2648  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
2649  {
2650  if (ConfirmQuit(Ir))
2651  return QUIT_PAGE;
2652 
2653  break;
2654  }
2655  else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESC */
2656  {
2657  return SELECT_PARTITION_PAGE;
2658  }
2659  else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'L') /* L */
2660  {
2663  &CurrentPartition);
2664  return SELECT_PARTITION_PAGE;
2665  }
2666  }
2667 
2668  return DELETE_PARTITION_PAGE;
2669 }
2670 
2671 
2672 static VOID
2674 {
2675  if (!FileSystemList)
2676  return;
2677 
2679  FileSystemList = NULL;
2680 }
2681 
2682 /*
2683  * Displays the SelectFileSystemPage.
2684  *
2685  * Next pages:
2686  * CheckFileSystemPage (At once if RepairUpdate is selected)
2687  * CheckFileSystemPage (At once if Unattended and not USetupData.FormatPartition)
2688  * FormatPartitionPage (At once if Unattended and USetupData.FormatPartition)
2689  * SelectPartitionPage (If the user aborts)
2690  * FormatPartitionPage (Default)
2691  * QuitPage
2692  *
2693  * SIDEEFFECTS
2694  * Calls UpdatePartitionType()
2695  * Calls FindSupportedSystemPartition()
2696  *
2697  * RETURNS
2698  * Number of the next page.
2699  */
2700 static PAGE_NUMBER
2702 {
2703  PPARTENTRY PartEntry;
2704  PDISKENTRY DiskEntry;
2705  ULONGLONG DiskSize;
2706  ULONGLONG PartSize;
2707  PCHAR DiskUnit;
2708  PCHAR PartUnit;
2709  CHAR PartTypeString[32];
2710  FORMATMACHINESTATE PreviousFormatState;
2711  PCWSTR DefaultFs;
2712 
2713  DPRINT("SelectFileSystemPage()\n");
2714 
2715  if (PartitionList == NULL || InstallPartition == NULL)
2716  {
2717  /* FIXME: show an error dialog */
2718  return QUIT_PAGE;
2719  }
2720 
2721  /* Find or set the active system partition when starting formatting */
2722  if (FormatState == Start)
2723  {
2724  /*
2725  * If we install on a fixed disk, try to find a supported system
2726  * partition on the system. Otherwise if we install on a removable disk
2727  * use the install partition as the system partition.
2728  */
2729  // TODO: Include that logic inside the FindSupportedSystemPartition() function?
2730  if (InstallPartition->DiskEntry->MediaType == FixedMedia)
2731  {
2733  FALSE,
2736  /* Use the original system partition as the old active partition hint */
2737  PartEntry = PartitionList->SystemPartition;
2738 
2741  {
2742  DPRINT1("We are using a different system partition!!!!\n");
2743 
2745 
2746  {
2747  PPARTENTRY PartEntry; // Shadow variable
2748 
2749  PartEntry = PartitionList->SystemPartition;
2750  DiskEntry = PartEntry->DiskEntry;
2751 
2752  /* Adjust partition size */
2753  PartSize = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
2754  if (PartSize >= 10 * GB) /* 10 GB */
2755  {
2756  PartSize = PartSize / GB;
2757  PartUnit = MUIGetString(STRING_GB);
2758  }
2759  else
2760  {
2761  PartSize = PartSize / MB;
2762  PartUnit = MUIGetString(STRING_MB);
2763  }
2764 
2765  /* Adjust partition type */
2767  PartTypeString,
2768  ARRAYSIZE(PartTypeString));
2769 
2770  if (*PartTypeString == '\0') // STRING_FORMATUNKNOWN ??
2771  {
2772  CONSOLE_PrintTextXY(8, 10,
2774  (PartEntry->DriveLetter == 0) ? '-' : (CHAR)PartEntry->DriveLetter,
2775  (PartEntry->DriveLetter == 0) ? '-' : ':',
2776  PartEntry->PartitionType,
2777  PartSize,
2778  PartUnit);
2779  }
2780  else
2781  {
2782  CONSOLE_PrintTextXY(8, 10,
2783  "%c%c %s %I64u %s",
2784  (PartEntry->DriveLetter == 0) ? '-' : (CHAR)PartEntry->DriveLetter,
2785  (PartEntry->DriveLetter == 0) ? '-' : ':',
2786  PartTypeString,
2787  PartSize,
2788  PartUnit);
2789  }
2790 
2791 
2792  /* Adjust disk size */
2793  DiskSize = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
2794  if (DiskSize >= 10 * GB) /* 10 GB */
2795  {
2796  DiskSize = DiskSize / GB;
2797  DiskUnit = MUIGetString(STRING_GB);
2798  }
2799  else
2800  {
2801  DiskSize = DiskSize / MB;
2802  DiskUnit = MUIGetString(STRING_MB);
2803  }
2804 
2806  DiskEntry->DiskNumber,
2807  DiskSize,
2808  DiskUnit,
2809  DiskEntry->Port,
2810  DiskEntry->Bus,
2811  DiskEntry->Id,
2812  &DiskEntry->DriverName,
2813  DiskEntry->DiskStyle == PARTITION_STYLE_MBR ? "MBR" :
2814  DiskEntry->DiskStyle == PARTITION_STYLE_GPT ? "GPT" :
2815  "RAW");
2816 
2817 
2818  PartEntry = SystemPartition;
2819  DiskEntry = PartEntry->DiskEntry;
2820 
2821  /* Adjust partition size */
2822  PartSize = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
2823  if (PartSize >= 10 * GB) /* 10 GB */
2824  {
2825  PartSize = PartSize / GB;
2826  PartUnit = MUIGetString(STRING_GB);
2827  }
2828  else
2829  {
2830  PartSize = PartSize / MB;
2831  PartUnit = MUIGetString(STRING_MB);
2832  }
2833 
2834  /* Adjust partition type */
2836  PartTypeString,
2837  ARRAYSIZE(PartTypeString));
2838 
2839  if (*PartTypeString == '\0') // STRING_FORMATUNKNOWN ??
2840  {
2841  CONSOLE_PrintTextXY(8, 23,
2843  (PartEntry->DriveLetter == 0) ? '-' : (CHAR)PartEntry->DriveLetter,
2844  (PartEntry->DriveLetter == 0) ? '-' : ':',
2845  PartEntry->PartitionType,
2846  PartSize,
2847  PartUnit);
2848  }
2849  else
2850  {
2851  CONSOLE_PrintTextXY(8, 23,
2852  "%c%c %s %I64u %s",
2853  (PartEntry->DriveLetter == 0) ? '-' : (CHAR)PartEntry->DriveLetter,
2854  (PartEntry->DriveLetter == 0) ? '-' : ':',
2855  PartTypeString,
2856  PartSize,
2857  PartUnit);
2858  }
2859 
2860  }
2861 
2862  while (TRUE)
2863  {
2864  CONSOLE_ConInKey(Ir);
2865 
2866  if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
2867  {
2868  break;
2869  }
2870  else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESC */
2871  {
2872  return SELECT_PARTITION_PAGE;
2873  }
2874  }
2875 
2877  CONSOLE_Flush();
2878  }
2879  }
2880  else // if (InstallPartition->DiskEntry->MediaType == RemovableMedia)
2881  {
2883  /* Don't specify any old active partition hint */
2884  PartEntry = NULL;
2885  }
2886 
2887  if (!SystemPartition)
2888  {
2889  /* FIXME: improve the error dialog */
2890  //
2891  // Error dialog should say that we cannot find a suitable
2892  // system partition and create one on the system. At this point,
2893  // it may be nice to ask the user whether he wants to continue,
2894  // or use an external drive as the system drive/partition
2895  // (e.g. floppy, USB drive, etc...)
2896  //
2897  PopupError("The ReactOS Setup could not find a supported system partition\n"
2898  "on your system or could not create a new one. Without such partition\n"
2899  "the Setup program cannot install ReactOS.\n"
2900  "Press ENTER to return to the partition selection list.",
2902  Ir, POPUP_WAIT_ENTER);
2903  return SELECT_PARTITION_PAGE;
2904  }
2905 
2906  /*
2907  * If the system partition can be created in some
2908  * non-partitioned space, create it now.
2909  */
2911  {
2912  // if (IsUnattendedSetup)
2913  {
2916  0LL, // SystemPartition->SectorCount.QuadPart,
2917  TRUE);
2919  }
2920  // else
2921  {
2922  }
2923  }
2924 
2925  /* Set it as such */
2927  {
2928  DPRINT1("SetActivePartition(0x%p) failed?!\n", SystemPartition);
2929  ASSERT(FALSE);
2930  }
2931 
2932  /* Commit all partition changes to all the disks */
2934  {
2935  DPRINT("WritePartitionsToDisk() failed\n");
2937  return QUIT_PAGE;
2938  }
2939 
2940  /*
2941  * In all cases, whether or not we are going to perform a formatting,
2942  * we must perform a filesystem check of both the system and the
2943  * installation partitions.
2944  */
2948 
2949  /*
2950  * In case we just repair an existing installation, or make
2951  * an unattended setup without formatting, just go to the
2952  * filesystem check step.
2953  */
2954  if (RepairUpdateFlag)
2955  return CHECK_FILE_SYSTEM_PAGE;
2956 
2957  if (IsUnattendedSetup && !USetupData.FormatPartition)
2958  return CHECK_FILE_SYSTEM_PAGE;
2959  }
2960 
2961  // ASSERT(SystemPartition->IsPartitioned);
2962 
2963  /* Reset the filesystem list for each partition that is to be formatted */
2965 
2966  PreviousFormatState = FormatState;
2967  switch (FormatState)
2968  {
2969  case Start:
2970  {
2971  /*
2972  * We start by formatting the system partition in case it is new
2973  * (it didn't exist before) and is not the same as the installation
2974  * partition. Otherwise we just require a filesystem check on it,
2975  * and start by formatting the installation partition instead.
2976  */
2977 
2979 
2980  if ((SystemPartition != InstallPartition) &&
2982  {
2985 
2986  // TODO: Should we let the user using a custom file-system,
2987  // or should we always use FAT(32) for it?
2988  // For "compatibility", FAT(32) would be best indeed.
2989 
2991  DPRINT1("FormatState: Start --> FormatSystemPartition\n");
2992  }
2993  else
2994  {
2997 
2999  {
3000  /* The system partition is separate, so it had better be formatted! */
3003 
3004  /* Require a filesystem check on the system partition too */
3006  }
3007 
3009  DPRINT1("FormatState: Start --> FormatInstallPartition\n");
3010  }
3011  break;
3012  }
3013 
3014  case FormatSystemPartition:
3015  {
3018 
3020  DPRINT1("FormatState: FormatSystemPartition --> FormatInstallPartition\n");
3021  break;
3022  }
3023 
3025  case FormatOtherPartition:
3026  {
3028  NULL,
3029  &TempPartition))
3030  {
3033 
3035  DPRINT1("FormatState: FormatInstallPartition --> FormatOtherPartition\n");
3036  else
3037  DPRINT1("FormatState: FormatOtherPartition --> FormatOtherPartition\n");
3038  }
3039  else
3040  {
3042 
3044  DPRINT1("FormatState: FormatInstallPartition --> FormatDone\n");
3045  else
3046  DPRINT1("FormatState: FormatOtherPartition --> FormatDone\n");
3047 
3048  return CHECK_FILE_SYSTEM_PAGE;
3049  }
3050  break;
3051  }
3052 
3053  case FormatDone:
3054  {
3055  DPRINT1("FormatState: FormatDone\n");
3056  return CHECK_FILE_SYSTEM_PAGE;
3057  }
3058 
3059  default:
3060  {
3061  DPRINT1("FormatState: Invalid value %ld\n", FormatState);
3062  ASSERT(FALSE);
3063  return QUIT_PAGE;
3064  }
3065  }
3066 
3067  PartEntry = TempPartition;
3068  DiskEntry = TempPartition->DiskEntry;
3069 
3070  ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0);
3071 
3072  /* Adjust disk size */
3073  DiskSize = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
3074  if (DiskSize >= 10 * GB) /* 10 GB */
3075  {
3076  DiskSize = DiskSize / GB;
3077  DiskUnit = MUIGetString(STRING_GB);
3078  }
3079  else
3080  {
3081  DiskSize = DiskSize / MB;
3082  DiskUnit = MUIGetString(STRING_MB);
3083  }
3084 
3085  /* Adjust partition size */
3086  PartSize = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
3087  if (PartSize >= 10 * GB) /* 10 GB */
3088  {
3089  PartSize = PartSize / GB;
3090  PartUnit = MUIGetString(STRING_GB);
3091  }
3092  else
3093  {
3094  PartSize = PartSize / MB;
3095  PartUnit = MUIGetString(STRING_MB);
3096  }
3097 
3098  /* Adjust partition type */
3100  PartTypeString,
3101  ARRAYSIZE(PartTypeString));
3102 
3104 
3105  if (PartEntry->AutoCreate)
3106  {
3108 
3109 #if 0
3110  CONSOLE_PrintTextXY(8, 10, "Partition %lu (%I64u %s) %s of",
3111  PartEntry->PartitionNumber,
3112  PartSize,
3113  PartUnit,
3114  PartTypeString);
3115 #endif
3116 
3118  DiskEntry->DiskNumber,
3119  DiskSize,
3120  DiskUnit,
3121  DiskEntry->Port,
3122  DiskEntry->Bus,
3123  DiskEntry->Id,
3124  &DiskEntry->DriverName,
3125  DiskEntry->DiskStyle == PARTITION_STYLE_MBR ? "MBR" :
3126  DiskEntry->DiskStyle == PARTITION_STYLE_GPT ? "GPT" :
3127  "RAW");
3128 
3130 
3131  PartEntry->AutoCreate = FALSE;
3132  }
3133  else if (PartEntry->New)
3134  {
3135  switch (FormatState)
3136  {
3137  case FormatSystemPartition:
3139  break;
3140 
3143  break;
3144 
3145  case FormatOtherPartition:
3147  break;
3148 
3149  default:
3150  ASSERT(FALSE);
3151  break;
3152  }
3153 
3155  DiskEntry->DiskNumber,
3156  DiskSize,
3157  DiskUnit,
3158  DiskEntry->Port,
3159  DiskEntry->Bus,
3160  DiskEntry->Id,
3161  &DiskEntry->DriverName,
3162  DiskEntry->DiskStyle == PARTITION_STYLE_MBR ? "MBR" :
3163  DiskEntry->DiskStyle == PARTITION_STYLE_GPT ? "GPT" :
3164  "RAW");
3165 
3167  }
3168  else
3169  {
3171 
3172  if (*PartTypeString == '\0') // STRING_FORMATUNKNOWN ??
3173  {
3174  CONSOLE_PrintTextXY(8, 10,
3176  (PartEntry->DriveLetter == 0) ? '-' : (CHAR)PartEntry->DriveLetter,
3177  (PartEntry->DriveLetter == 0) ? '-' : ':',
3178  PartEntry->PartitionType,
3179  PartSize,
3180  PartUnit);
3181  }
3182  else
3183  {
3184  CONSOLE_PrintTextXY(8, 10,
3185  "%c%c %s %I64u %s",
3186  (PartEntry->DriveLetter == 0) ? '-' : (CHAR)PartEntry->DriveLetter,
3187  (PartEntry->DriveLetter == 0) ? '-' : ':',
3188  PartTypeString,
3189  PartSize,
3190  PartUnit);
3191  }
3192 
3194  DiskEntry->DiskNumber,
3195  DiskSize,
3196  DiskUnit,
3197  DiskEntry->Port,
3198  DiskEntry->Bus,
3199  DiskEntry->Id,
3200  &DiskEntry->DriverName,
3201  DiskEntry->DiskStyle == PARTITION_STYLE_MBR ? "MBR" :
3202  DiskEntry->DiskStyle == PARTITION_STYLE_GPT ? "GPT" :
3203  "RAW");
3204  }
3205 
3207 
3208  if (IsUnattendedSetup)
3209  {
3210  ASSERT(USetupData.FormatPartition);
3211 
3212  switch (USetupData.FsType)
3213  {
3214  /* 1 is for BtrFS */
3215  case 1:
3216  DefaultFs = L"BTRFS";
3217  break;
3218 
3219  /* If we don't understand input, default to FAT */
3220  default:
3221  DefaultFs = L"FAT";
3222  break;
3223  }
3224  }
3225  else
3226  {
3227  /* By default select the "FAT" file system */
3228  DefaultFs = L"FAT";
3229  }
3230 
3231  /* Create the file system list */
3232  // TODO: Display only the FSes compatible with the selected partition!
3234  PartEntry->New ||
3235  PartEntry->FormatState == Unformatted,
3236  DefaultFs);
3237  if (FileSystemList == NULL)
3238  {
3239  /* FIXME: show an error dialog */
3240  return QUIT_PAGE;
3241  }
3242 
3243  if (IsUnattendedSetup)
3244  {
3245  ASSERT(USetupData.FormatPartition);
3246  return FORMAT_PARTITION_PAGE;
3247  }
3248 
3250 
3251  while (TRUE)
3252  {
3253  CONSOLE_ConInKey(Ir);
3254 
3255  if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3256  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
3257  {
3258  if (ConfirmQuit(Ir))
3259  {
3260  /* Reset the filesystem list */
3262  return QUIT_PAGE;
3263  }
3264 
3265  break;
3266  }
3267  else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3268  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
3269  {
3270  /* Reset the formatter machine state */
3271  TempPartition = NULL;
3272  FormatState = Start;
3273 
3274  /* Reset the filesystem list */
3276 
3277  return SELECT_PARTITION_PAGE;
3278  }
3279  else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3280  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
3281  {
3283  }
3284  else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3285  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
3286  {
3288  }
3289  else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
3290  {
3292  {
3294 
3295  /*
3296  * Skip formatting this partition. We will also ignore
3297  * filesystem checks on it, unless it is either the system
3298  * or the installation partition.
3299  */
3300  if (TempPartition != SystemPartition &&
3302  {
3303  PartEntry->NeedsCheck = FALSE;
3304  }
3305 
3306  return SELECT_FILE_SYSTEM_PAGE;
3307  }
3308  else
3309  {
3310  /* Format this partition */
3311  return FORMAT_PARTITION_PAGE;
3312  }
3313  }
3314  }
3315 
3316  FormatState = PreviousFormatState;
3317 
3318  return SELECT_FILE_SYSTEM_PAGE;
3319 }
3320 
3321 
3322 /*
3323  * Displays the FormatPartitionPage.
3324  *
3325  * Next pages:
3326  * InstallDirectoryPage (At once if IsUnattendedSetup or InstallShortcut)
3327  * SelectPartitionPage (At once)
3328  * QuitPage
3329  *
3330  * SIDEEFFECTS
3331  * Sets InstallPartition->FormatState
3332  * Sets USetupData.DestinationRootPath
3333  *
3334  * RETURNS
3335  * Number of the next page.
3336  */
3337 static PAGE_NUMBER
3339 {
3340  NTSTATUS Status;
3341  PPARTENTRY PartEntry;
3342  PDISKENTRY DiskEntry;
3343  PFILE_SYSTEM_ITEM SelectedFileSystem;
3344  UNICODE_STRING PartitionRootPath;
3345  WCHAR PathBuffer[MAX_PATH];
3346  CHAR Buffer[MAX_PATH];
3347 
3348 #ifndef NDEBUG
3349  ULONG Line;
3350  ULONG i;
3352 #endif
3353 
3354  DPRINT("FormatPartitionPage()\n");
3355 
3357 
3358  if (PartitionList == NULL || TempPartition == NULL)
3359  {
3360  /* FIXME: show an error dialog */
3361  return QUIT_PAGE;
3362  }
3363 
3364  PartEntry = TempPartition;
3365  DiskEntry = TempPartition->DiskEntry;
3366 
3367  ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0);
3368 
3369  SelectedFileSystem = FileSystemList->Selected;
3370  ASSERT(SelectedFileSystem && SelectedFileSystem->FileSystem);
3371 
3372  while (TRUE)
3373  {
3374  if (!IsUnattendedSetup)
3375  CONSOLE_ConInKey(Ir);
3376 
3377  if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3378  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
3379  {
3380  if (ConfirmQuit(Ir))
3381  {
3382  /* Reset the filesystem list */
3384  return QUIT_PAGE;
3385  }
3386 
3387  break;
3388  }
3389  else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN || IsUnattendedSetup) /* ENTER */
3390  {
3391  /*
3392  * Remove the "Press ENTER to continue" message prompt when the ENTER
3393  * key is pressed as the user wants to begin the partition formatting.
3394  */
3397 
3398  if (!PreparePartitionForFormatting(PartEntry, SelectedFileSystem->FileSystem))
3399  {
3400  /* FIXME: show an error dialog */
3401 
3402  /* Reset the filesystem list */
3404 
3405  return QUIT_PAGE;
3406  }
3407 
3408 #ifndef NDEBUG
3409  CONSOLE_PrintTextXY(6, 12,
3410  "Cylinders: %I64u Tracks/Cyl: %lu Sectors/Trk: %lu Bytes/Sec: %lu %c",
3411  DiskEntry->Cylinders,
3412  DiskEntry->TracksPerCylinder,
3413  DiskEntry->SectorsPerTrack,
3414  DiskEntry->BytesPerSector,
3415  DiskEntry->Dirty ? '*' : ' ');
3416 
3417  Line = 13;
3418 
3419  for (i = 0; i < DiskEntry->LayoutBuffer->PartitionCount; i++)
3420  {
3421  PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[i];
3422 
3424  "%2u: %2lu %c %12I64u %12I64u %02x",
3425  i,
3426  PartitionInfo->PartitionNumber,
3427  PartitionInfo->BootIndicator ? 'A' : '-',
3428  PartitionInfo->StartingOffset.QuadPart / DiskEntry->BytesPerSector,
3429  PartitionInfo->PartitionLength.QuadPart / DiskEntry->BytesPerSector,
3430  PartitionInfo->PartitionType);
3431  Line++;
3432  }
3433 #endif
3434 
3435  /* Commit the partition changes to the disk */
3436  Status = WritePartitions(DiskEntry);
3437  if (!NT_SUCCESS(Status))
3438  {
3439  DPRINT1("WritePartitions(disk %lu) failed, Status 0x%08lx\n",
3440  DiskEntry->DiskNumber, Status);
3441 
3443 
3444  /* Reset the filesystem list */
3446 
3447  return QUIT_PAGE;
3448  }
3449 
3450  /* Set PartitionRootPath */
3451  RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
3452  L"\\Device\\Harddisk%lu\\Partition%lu",
3453  DiskEntry->DiskNumber,
3454  PartEntry->PartitionNumber);
3455  RtlInitUnicodeString(&PartitionRootPath, PathBuffer);
3456  DPRINT("PartitionRootPath: %wZ\n", &PartitionRootPath);
3457 
3458  /* Format the partition */
3459  Status = FormatPartition(&PartitionRootPath,
3460  SelectedFileSystem->FileSystem,
3461  SelectedFileSystem->QuickFormat);
3463  {
3464  sprintf(Buffer,
3465  "Setup is currently unable to format a partition in %S.\n"
3466  "\n"
3467  " \x07 Press ENTER to continue Setup.\n"
3468  " \x07 Press F3 to quit Setup.",
3469  SelectedFileSystem->FileSystem);
3470 
3474 
3475  while (TRUE)
3476  {
3477  CONSOLE_ConInKey(Ir);
3478 
3479  if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x00 &&
3480  Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3) /* F3 */
3481  {
3482  if (ConfirmQuit(Ir))
3483  {
3484  /* Reset the filesystem list */
3486  return QUIT_PAGE;
3487  }
3488  else
3489  {
3490  return SELECT_FILE_SYSTEM_PAGE;
3491  }
3492  }
3493  else if (Ir->Event.KeyEvent.uChar.AsciiChar == VK_RETURN) /* ENTER */
3494  {
3495  return SELECT_FILE_SYSTEM_PAGE;
3496  }
3497  }
3498  }
3499  else if (!NT_SUCCESS(Status))
3500  {
3501  DPRINT1("FormatPartition() failed with status 0x%08lx\n", Status);
3503 
3504  /* Reset the filesystem list */
3506 
3507  return QUIT_PAGE;
3508  }
3509 
3510 //
3511 // TODO: Here, call a partlist.c function that update the actual FS name
3512 // and the label fields of the volume.
3513 //
3514  PartEntry->FormatState = Formatted;
3515  // PartEntry->FileSystem = FileSystem;
3516  PartEntry->New = FALSE;
3517 
3518 #ifndef NDEBUG
3519  CONSOLE_SetStatusText(" Done. Press any key ...");
3520  CONSOLE_ConInKey(Ir);
3521 #endif
3522 
3523  return SELECT_FILE_SYSTEM_PAGE;
3524  }
3525  }
3526 
3527  return FORMAT_PARTITION_PAGE;
3528 }
3529 
3530 
3531 /*
3532  * Displays the CheckFileSystemPage.
3533  *
3534  * Next pages:
3535  * InstallDirectoryPage (At once)
3536  * QuitPage
3537  *
3538  * SIDEEFFECTS
3539  * Inits or reloads FileSystemList
3540  *
3541  * RETURNS
3542  * Number of the next page.
3543  */
3544 static PAGE_NUMBER
3546 {
3547  NTSTATUS Status;
3548  PDISKENTRY DiskEntry;
3549  PPARTENTRY PartEntry;
3550  UNICODE_STRING PartitionRootPath;
3551  WCHAR PathBuffer[MAX_PATH];
3552  CHAR Buffer[MAX_PATH];
3553 
3554  if (PartitionList == NULL)
3555  {
3556  /* FIXME: show an error dialog */
3557  return QUIT_PAGE;
3558  }
3559 
3560  if (!GetNextUncheckedPartition(PartitionList, &DiskEntry, &PartEntry))
3561  {
3562  return INSTALL_DIRECTORY_PAGE;
3563  }
3564 
3565  ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0);
3566 
3568 
3570 
3571  DPRINT1("CheckFileSystemPage -- PartitionType: 0x%02X ; FileSystem: %S\n",
3572  PartEntry->PartitionType, (*PartEntry->FileSystem ? PartEntry->FileSystem : L"n/a"));
3573 
3574  /* HACK: Do not try to check a partition with an unknown filesystem */
3575  if (!*PartEntry->FileSystem)
3576  {
3577  PartEntry->NeedsCheck = FALSE;
3578  return CHECK_FILE_SYSTEM_PAGE;
3579  }
3580 
3581  /* Set PartitionRootPath */
3582  RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
3583  L"\\Device\\Harddisk%lu\\Partition%lu",
3584  DiskEntry->DiskNumber,
3585  PartEntry->PartitionNumber);
3586  RtlInitUnicodeString(&PartitionRootPath, PathBuffer);
3587  DPRINT("PartitionRootPath: %wZ\n", &PartitionRootPath);
3588 
3589  /* Check the partition */
3590  Status = ChkdskPartition(&PartitionRootPath, PartEntry->FileSystem);
3592  {
3593  /*
3594  * Partition checking is not supported with the current filesystem,
3595  * so disable FS checks on it.
3596  */
3597  PartEntry->NeedsCheck = FALSE;
3598 
3600  sizeof(Buffer),
3601  "Setup is currently unable to check a partition formatted in %S.\n"
3602  "\n"
3603  " \x07 Press ENTER to continue Setup.\n"
3604  " \x07 Press F3 to quit Setup.",
3605  PartEntry->FileSystem);
3606 
3610 
3611  while (TRUE)
3612  {
3613  CONSOLE_ConInKey(Ir);
3614 
3615  if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x00 &&
3616  Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3) /* F3 */
3617  {
3618  if (ConfirmQuit(Ir))
3619  return QUIT_PAGE;
3620  else
3621  return CHECK_FILE_SYSTEM_PAGE;
3622  }
3623  else if (Ir->Event.KeyEvent.uChar.AsciiChar == VK_RETURN) /* ENTER */
3624  {
3625  return CHECK_FILE_SYSTEM_PAGE;
3626  }
3627  }
3628  }
3629  else if (!NT_SUCCESS(Status))
3630  {
3631  DPRINT("ChkdskPartition() failed with status 0x%08lx\n", Status);
3632  sprintf(Buffer, "ChkDsk detected some disk errors.\n(Status 0x%08lx).\n", Status);
3635  Ir, POPUP_WAIT_ENTER);
3636  }
3637 
3638  PartEntry->NeedsCheck = FALSE;
3639  return CHECK_FILE_SYSTEM_PAGE;
3640 }
3641 
3642 
3643 static BOOLEAN
3645  IN PCWSTR InstallDir)
3646 {
3647  UINT i, Length;
3648 
3649  Length = wcslen(InstallDir);
3650 
3651  // TODO: Add check for 8.3 too.
3652 
3653  /* Path must be at least 2 characters long */
3654 // if (Length < 2)
3655 // return FALSE;
3656 
3657  /* Path must start with a backslash */
3658 // if (InstallDir[0] != L'\\')
3659 // return FALSE;
3660 
3661  /* Path must not end with a backslash */
3662  if (InstallDir[Length - 1] == L'\\')
3663  return FALSE;
3664 
3665  /* Path must not contain whitespace characters */
3666  for (i = 0; i < Length; i++)
3667  {
3668  if (iswspace(InstallDir[i]))
3669  return FALSE;
3670  }
3671 
3672  /* Path component must not end with a dot */
3673  for (i = 0; i < Length; i++)
3674  {
3675  if (InstallDir[i] == L'\\' && i > 0)
3676  {
3677  if (InstallDir[i - 1] == L'.')
3678  return FALSE;
3679  }
3680  }
3681 
3682  if (InstallDir[Length - 1] == L'.')
3683  return FALSE;
3684 
3685  return TRUE;
3686 }
3687 
3688 
3689 /*
3690  * Displays the InstallDirectoryPage.
3691  *
3692  * Next pages:
3693  * PrepareCopyPage
3694  * QuitPage
3695  *
3696  * RETURNS
3697  * Number of the next page.
3698  */
3699 static PAGE_NUMBER
3701 {
3702  NTSTATUS Status;
3703  ULONG Length, Pos;
3704  WCHAR c;
3705  WCHAR InstallDir[MAX_PATH];
3706 
3707  /* We do not need the filesystem list anymore */
3709 
3710  if (PartitionList == NULL || InstallPartition == NULL)
3711  {
3712  /* FIXME: show an error dialog */
3713  return QUIT_PAGE;
3714  }
3715 
3716  // if (IsUnattendedSetup)
3717  if (RepairUpdateFlag)
3718  wcscpy(InstallDir, CurrentInstallation->PathComponent); // SystemNtPath
3719  else if (USetupData.InstallationDirectory[0])
3720  wcscpy(InstallDir, USetupData.InstallationDirectory);
3721  else
3722  wcscpy(InstallDir, L"\\ReactOS");
3723 
3724  /*
3725  * Check the validity of the predefined 'InstallDir'. If we are either
3726  * in unattended setup or in update/repair mode, and the installation path
3727  * is valid, just perform the installation. Otherwise (either in the case
3728  * of an invalid path, or we are in regular setup), display the UI and allow
3729  * the user to specify a new installation path.
3730  */
3731  if ((RepairUpdateFlag || IsUnattendedSetup) && IsValidPath(InstallDir))
3732  {
3734  if (!NT_SUCCESS(Status))
3735  {
3736  DPRINT1("InitDestinationPaths() failed. Status code: 0x%lx", Status);
3738  return QUIT_PAGE;
3739  }
3740 
3741  /*
3742  * Check whether the user attempts to install ReactOS within the
3743  * installation source directory, or in a subdirectory thereof.
3744  * If so, fail with an error.
3745  */
3746  if (RtlPrefixUnicodeString(&USetupData.SourcePath, &USetupData.DestinationPath, TRUE))
3747  {
3749  return INSTALL_DIRECTORY_PAGE;
3750  }
3751 
3752  return PREPARE_COPY_PAGE;
3753  }
3754 
3755  Length = wcslen(InstallDir);
3756  Pos = Length;
3757 
3759  CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
3760  CONSOLE_SetCursorXY(8 + Pos, 11);
3762 
3763  while (TRUE)
3764  {
3765  CONSOLE_ConInKey(Ir);
3766 
3767  if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3768  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
3769  {
3771 
3772  if (ConfirmQuit(Ir))
3773  return QUIT_PAGE;
3774 
3776  break;
3777  }
3778  else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3779  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DELETE)) /* DEL */
3780  {
3781  if (Pos < Length)
3782  {
3783  memmove(&InstallDir[Pos],
3784  &InstallDir[Pos + 1],
3785  (Length - Pos - 1) * sizeof(WCHAR));
3786  InstallDir[Length - 1] = UNICODE_NULL;
3787 
3788  Length--;
3789  CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
3790  CONSOLE_SetCursorXY(8 + Pos, 11);
3791  }
3792  }
3793  else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3794  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_HOME)) /* HOME */
3795  {
3796  Pos = 0;
3797  CONSOLE_SetCursorXY(8 + Pos, 11);
3798  }
3799  else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3800  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_END)) /* END */
3801  {
3802  Pos = Length;
3803  CONSOLE_SetCursorXY(8 + Pos, 11);
3804  }
3805  else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3806  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_LEFT)) /* LEFT */
3807  {
3808  if (Pos > 0)
3809  {
3810  Pos--;
3811  CONSOLE_SetCursorXY(8 + Pos, 11);
3812  }
3813  }
3814  else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3815  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RIGHT)) /* RIGHT */
3816  {
3817  if (Pos < Length)
3818  {
3819  Pos++;
3820  CONSOLE_SetCursorXY(8 + Pos, 11);
3821  }
3822  }
3823  else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
3824  {
3826 
3827  /*
3828  * Check for the validity of the installation directory and pop up
3829  * an error if it is not the case. Then the user can fix its input.
3830  */
3831  if (!IsValidPath(InstallDir))
3832  {
3834  return INSTALL_DIRECTORY_PAGE;
3835  }
3836 
3838  if (!NT_SUCCESS(Status))
3839  {
3840  DPRINT1("InitDestinationPaths() failed. Status code: 0x%lx", Status);
3842  return QUIT_PAGE;
3843  }
3844 
3845  /*
3846  * Check whether the user attempts to install ReactOS within the
3847  * installation source directory, or in a subdirectory thereof.
3848  * If so, fail with an error.
3849  */
3850  if (RtlPrefixUnicodeString(&USetupData.SourcePath, &USetupData.DestinationPath, TRUE))
3851  {
3853  return INSTALL_DIRECTORY_PAGE;
3854  }
3855 
3856  return PREPARE_COPY_PAGE;
3857  }
3858  else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x08) /* BACKSPACE */
3859  {
3860  if (Pos > 0)
3861  {
3862  if (Pos < Length)
3863  memmove(&InstallDir[Pos - 1],
3864  &InstallDir[Pos],
3865  (Length - Pos) * sizeof(WCHAR));
3866  InstallDir[Length - 1] = UNICODE_NULL;
3867 
3868  Pos--;
3869  Length--;
3870  CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
3871  CONSOLE_SetCursorXY(8 + Pos, 11);
3872  }
3873  }
3874  else if (isprint(Ir->Event.KeyEvent.uChar.AsciiChar))
3875  {
3876  if (Length < 50)
3877  {
3879  if (iswalpha(c) || iswdigit(c) || c == '.' || c == '\\' || c == '-' || c == '_')
3880  {
3881  if (Pos < Length)
3882  memmove(&InstallDir[Pos + 1],
3883  &InstallDir[Pos],
3884  (Length - Pos) * sizeof(WCHAR));
3885  InstallDir[Length + 1] = UNICODE_NULL;
3886  InstallDir[Pos] = c;
3887 
3888  Pos++;
3889  Length++;
3890  CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
3891  CONSOLE_SetCursorXY(8 + Pos, 11);
3892  }
3893  }
3894  }
3895  }
3896 
3897  return INSTALL_DIRECTORY_PAGE;
3898 }
3899 
3900 
3901 // PSETUP_ERROR_ROUTINE
3902 static VOID
3903 __cdecl
3905  IN PUSETUP_DATA pSetupData,
3906  ...)
3907 {
3908  INPUT_RECORD Ir;
3909  va_list arg_ptr;
3910 
3911  va_start(arg_ptr, pSetupData);
3912 
3913  if (pSetupData->LastErrorNumber >= ERROR_SUCCESS &&
3914  pSetupData->LastErrorNumber < ERROR_LAST_ERROR_CODE)
3915  {
3916  // Note: the "POPUP_WAIT_ENTER" actually depends on the LastErrorNumber...
3917  MUIDisplayErrorV(pSetupData->LastErrorNumber, &Ir, POPUP_WAIT_ENTER, arg_ptr);
3918  }
3919 
3920  va_end(arg_ptr);
3921 }
3922 
3923 /*
3924  * Displays the PrepareCopyPage.
3925  *
3926  * Next pages:
3927  * FileCopyPage(At once)
3928  * QuitPage
3929  *
3930  * SIDEEFFECTS
3931  * Calls PrepareFileCopy
3932  *
3933  * RETURNS
3934  * Number of the next page.
3935  */
3936 static PAGE_NUMBER
3938 {
3939  // ERROR_NUMBER ErrorNumber;
3940  BOOLEAN Success;
3941 
3943 
3944  /* ErrorNumber = */ Success = PrepareFileCopy(&USetupData, NULL);
3945  if (/*ErrorNumber != ERROR_SUCCESS*/ !Success)
3946  {
3947  // MUIDisplayError(ErrorNumber, Ir, POPUP_WAIT_ENTER);
3948  return QUIT_PAGE;
3949  }
3950 
3951  return FILE_COPY_PAGE;
3952 }
3953 
3954 typedef struct _COPYCONTEXT
3955 {
3961 
3962 static VOID
3964  IN BOOLEAN First)
3965 {
3967 
3968  /* Get the memory information from the system */
3970  &PerfInfo,
3971  sizeof(PerfInfo),
3972  NULL);
3973 
3974  /* Check if this is initial setup */
3975  if (First)
3976  {
3977  /* Set maximum limits to be total RAM pages */
3978  ProgressSetStepCount(CopyContext->MemoryBars[0], PerfInfo.CommitLimit);
3979  ProgressSetStepCount(CopyContext->MemoryBars[1], PerfInfo.CommitLimit);
3980  ProgressSetStepCount(CopyContext->MemoryBars[2], PerfInfo.CommitLimit);
3981  }
3982 
3983  /* Set current values */
3984  ProgressSetStep(CopyContext->MemoryBars[0], PerfInfo.PagedPoolPages + PerfInfo.NonPagedPoolPages);
3985  ProgressSetStep(CopyContext->MemoryBars[1], PerfInfo.ResidentSystemCachePage);
3986  ProgressSetStep(CopyContext->MemoryBars[2], PerfInfo.AvailablePages);
3987 }
3988 
3989 static UINT
3990 CALLBACK
3992  UINT Notification,
3993  UINT_PTR Param1,
3994  UINT_PTR Param2)
3995 {
3996  PCOPYCONTEXT CopyContext = (PCOPYCONTEXT)Context;
3997  PFILEPATHS_W FilePathInfo;
3998  PCWSTR SrcFileName, DstFileName;
3999 
4000  switch (Notification)
4001  {
4003  {
4004  CopyContext->TotalOperations = (ULONG)Param2;
4005  CopyContext->CompletedOperations = 0;
4006  ProgressSetStepCount(CopyContext->ProgressBar,
4007  CopyContext->TotalOperations);
4008  SetupUpdateMemoryInfo(CopyContext, TRUE);
4009  break;
4010  }
4011 
4015  {
4016  FilePathInfo = (PFILEPATHS_W)Param1;
4017 
4018  if (Notification == SPFILENOTIFY_STARTDELETE)
4019  {
4020  /* Display delete message */
4021  ASSERT(Param2 == FILEOP_DELETE);
4022 
4023  DstFileName = wcsrchr(FilePathInfo->Target, L'\\');
4024  if (DstFileName) ++DstFileName;
4025  else DstFileName = FilePathInfo->Target;
4026 
4028  DstFileName);
4029  }
4030  else if (Notification == SPFILENOTIFY_STARTRENAME)
4031  {
4032  /* Display move/rename message */
4033  ASSERT(Param2 == FILEOP_RENAME);
4034 
4035  SrcFileName = wcsrchr(FilePathInfo->Source, L'\\');
4036  if (SrcFileName) ++SrcFileName;
4037  else SrcFileName = FilePathInfo->Source;
4038 
4039  DstFileName = wcsrchr(FilePathInfo->Target, L'\\');
4040  if (DstFileName) ++DstFileName;
4041  else DstFileName = FilePathInfo->Target;
4042 
4043  if (!wcsicmp(SrcFileName, DstFileName))
4044  Param2 = STRING_MOVING;
4045  else
4046  Param2 = STRING_RENAMING;
4047 
4049  SrcFileName, DstFileName);
4050  }
4051  else if (Notification == SPFILENOTIFY_STARTCOPY)
4052  {
4053  /* Display copy message */
4054  ASSERT(Param2 == FILEOP_COPY);
4055 
4056  /* NOTE: When extracting from CABs the Source is the CAB name */
4057  DstFileName = wcsrchr(FilePathInfo->Target, L'\\');
4058  if (DstFileName) ++DstFileName;
4059  else DstFileName = FilePathInfo->Target;
4060 
4062  DstFileName);
4063  }
4064 
4065  SetupUpdateMemoryInfo(CopyContext, FALSE);
4066  break;
4067  }
4068 
4070  {
4071  FilePathInfo = (PFILEPATHS_W)Param1;
4072 
4073  DPRINT1("An error happened while trying to copy file '%S' (error 0x%08lx), skipping it...\n",
4074  FilePathInfo->Target, FilePathInfo->Win32Error);
4075  return FILEOP_SKIP;
4076  }
4077 
4080  case SPFILENOTIFY_ENDCOPY:
4081  {
4082  CopyContext->CompletedOperations++;
4083 
4084  /* SYSREG checkpoint */
4085  if (CopyContext->TotalOperations >> 1 == CopyContext->CompletedOperations)
4086  DPRINT1("CHECKPOINT:HALF_COPIED\n");
4087 
4088  ProgressNextStep(CopyContext->ProgressBar);
4089  SetupUpdateMemoryInfo(CopyContext, FALSE);
4090  break;
4091  }
4092  }
4093 
4094  return FILEOP_DOIT;
4095 }
4096 
4097 
4098 /*
4099  * Displays the FileCopyPage.
4100  *
4101  * Next pages:
4102  * RegistryPage(At once)
4103  *
4104  * SIDEEFFECTS
4105  * Calls DoFileCopy
4106  *
4107  * RETURNS
4108  * Number of the next page.
4109  */
4110 static PAGE_NUMBER
4112 {
4113  COPYCONTEXT CopyContext;
4114  UINT MemBarWidth;
4115 
4117 
4118  /* Create context for the copy process */
4119  CopyContext.TotalOperations = 0;
4120  CopyContext.CompletedOperations = 0;
4121 
4122  /* Create the progress bar as well */
4123  CopyContext.ProgressBar = CreateProgressBar(13,
4124  26,
4125  xScreen - 13,
4126  yScreen - 20,
4127  10,
4128  24,
4129  TRUE,
4131 
4132  // fit memory bars to screen width, distribute them uniform
4133  MemBarWidth = (xScreen - 26) / 5;
4134  MemBarWidth -= MemBarWidth % 2; // make even
4135  /* ATTENTION: The following progress bars are debug stuff, which should not be translated!! */
4136  /* Create the paged pool progress bar */
4137  CopyContext.MemoryBars[0] = CreateProgressBar(13,
4138  40,
4139  13 + MemBarWidth,
4140  43,
4141  13,
4142  44,
4143  FALSE,
4144  "Kernel Pool");
4145 
4146  /* Create the non paged pool progress bar */
4147  CopyContext.MemoryBars[1] = CreateProgressBar((xScreen / 2)- (MemBarWidth / 2),
4148  40,
4149  (xScreen / 2) + (MemBarWidth / 2),
4150  43,
4151  (xScreen / 2)- (MemBarWidth / 2),
4152  44,
4153  FALSE,
4154  "Kernel Cache");
4155 
4156  /* Create the global memory progress bar */
4157  CopyContext.MemoryBars[2] = CreateProgressBar(xScreen - 13 - MemBarWidth,
4158  40,
4159  xScreen - 13,
4160  43,
4161  xScreen - 13 - MemBarWidth,
4162  44,
4163  FALSE,
4164  "Free Memory");
4165 
4166  /* Do the file copying */
4167  DoFileCopy(&USetupData, FileCopyCallback, &CopyContext);
4168 
4169  /* If we get here, we're done, so cleanup the progress bar */
4170  DestroyProgressBar(CopyContext.ProgressBar);
4171  DestroyProgressBar(CopyContext.MemoryBars[0]);
4172  DestroyProgressBar(CopyContext.MemoryBars[1]);
4173  DestroyProgressBar(CopyContext.MemoryBars[2]);
4174 
4175  /* Create the $winnt$.inf file */
4177 
4178  /* Go display the next page */
4179  return REGISTRY_PAGE;
4180 }
4181 
4182 
4183 static VOID
4184 __cdecl
4186 {
4187  /* WARNING: Please keep this lookup table in sync with the resources! */
4188  static const UINT StringIDs[] =
4189  {
4190  STRING_DONE, /* Success */
4191  STRING_REGHIVEUPDATE, /* RegHiveUpdate */
4192  STRING_IMPORTFILE, /* ImportRegHive */
4193  STRING_DISPLAYSETTINGSUPDATE, /* DisplaySettingsUpdate */
4194  STRING_LOCALESETTINGSUPDATE, /* LocaleSettingsUpdate */
4195  STRING_ADDKBLAYOUTS, /* KeybLayouts */
4196  STRING_KEYBOARDSETTINGSUPDATE, /* KeybSettingsUpdate */
4197  STRING_CODEPAGEINFOUPDATE, /* CodePageInfoUpdate */
4198  };
4199 
4200  va_list args;
4201 
4202  if (RegStatus < ARRAYSIZE(StringIDs))
4203  {
4204  va_start(args, RegStatus);
4205  CONSOLE_SetStatusTextV(MUIGetString(StringIDs[RegStatus]), args);
4206  va_end(args);
4207  }
4208  else
4209  {
4210  CONSOLE_SetStatusText("Unknown status %d", RegStatus);
4211  }
4212 }
4213 
4214 /*
4215  * Displays the RegistryPage.
4216  *
4217  * Next pages:
4218  * SuccessPage (if RepairUpdate)
4219  * BootLoaderPage (default)
4220  * QuitPage
4221  *
4222  * SIDEEFFECTS
4223  * Calls UpdateRegistry
4224  *
4225  * RETURNS
4226  * Number of the next page.
4227  */
4228 static PAGE_NUMBER
4230 {
4231  ULONG Error;
4232 
4234 
4237  PartitionList,
4240  RegistryStatus);
4241  if (Error != ERROR_SUCCESS)
4242  {
4244  return QUIT_PAGE;
4245  }
4246  else
4247  {
4249  return BOOT_LOADER_PAGE;
4250  }
4251 }
4252 
4253 
4254 /*
4255  * Displays the BootLoaderPage.
4256  *
4257  * Next pages:
4258  * SuccessPage (if RepairUpdate)
4259  * BootLoaderHarddiskMbrPage
4260  * BootLoaderHarddiskVbrPage
4261  * BootLoaderFloppyPage
4262  * SuccessPage
4263  * QuitPage
4264  *
4265  * SIDEEFFECTS
4266  * Calls RegInitializeRegistry
4267  * Calls ImportRegistryFile
4268  * Calls SetDefaultPagefile
4269  * Calls SetMountedDeviceValues
4270  *
4271  * RETURNS
4272  * Number of the next page.
4273  */
4274 static PAGE_NUMBER
4276 {
4278  BOOLEAN InstallOnFloppy;
4279  USHORT Line = 12;
4280  WCHAR PathBuffer[MAX_PATH];
4281 
4283 
4285 
4286  RtlFreeUnicodeString(&USetupData.SystemRootPath);
4287  RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
4288  L"\\Device\\Harddisk%lu\\Partition%lu\\",
4289  SystemPartition->DiskEntry->DiskNumber,
4291  RtlCreateUnicodeString(&USetupData.SystemRootPath, PathBuffer);
4292  DPRINT1("SystemRootPath: %wZ\n", &USetupData.SystemRootPath);
4293 
4295 
4296  /* For unattended setup, skip MBR installation or install on floppy if needed */
4297  if (IsUnattendedSetup)
4298  {
4299  if ((USetupData.MBRInstallType == 0) ||
4300  (USetupData.MBRInstallType == 1))
4301  {
4302  goto Quit;
4303  }
4304  }
4305 
4306  /*
4307  * We may install an MBR or VBR, but before that, check whether
4308  * we need to actually install the VBR on floppy.
4309  */
4311  {
4312  DPRINT("Error: system partition invalid (unused)\n");
4313  InstallOnFloppy = TRUE;
4314  }
4315  else if (PartitionType == PARTITION_OS2BOOTMGR)
4316  {
4317  /* OS/2 boot manager partition */
4318  DPRINT("Found OS/2 boot manager partition\n");
4319  InstallOnFloppy = TRUE;
4320  }
4321  else if (PartitionType == PARTITION_LINUX)
4322  {
4323  /* Linux partition */
4324  DPRINT("Found Linux native partition (ext2/ext3/ReiserFS/BTRFS/etc)\n");
4325  InstallOnFloppy = FALSE;
4326  }
4327  else if (PartitionType == PARTITION_IFS)
4328  {
4329  /* NTFS partition */
4330  DPRINT("Found NTFS partition\n");
4331 
4332  // FIXME: Make it FALSE when we'll support NTFS installation!
4333  InstallOnFloppy = TRUE;
4334  }
4335  else if ((PartitionType == PARTITION_FAT_12) ||
4341  {
4342  DPRINT("Found FAT partition\n");
4343  InstallOnFloppy = FALSE;
4344  }
4345  else
4346  {
4347  /* Unknown partition */
4348  DPRINT("Unknown partition found\n");
4349  InstallOnFloppy = TRUE;
4350  }
4351 
4352  /* We should install on floppy */
4353  if (InstallOnFloppy)
4354  {
4355  USetupData.MBRInstallType = 1;
4356  goto Quit;
4357  }
4358 
4359  /* Is it an unattended install on hdd? */
4360  if (IsUnattendedSetup)
4361  {
4362  if ((USetupData.MBRInstallType == 2) ||
4363  (USetupData.MBRInstallType == 3))
4364  {
4365  goto Quit;
4366  }
4367  }
4368 
4370  CONSOLE_InvertTextXY(8, Line, 60, 1);
4371 
4372  while (TRUE)
4373  {
4374  CONSOLE_ConInKey(Ir);
4375 
4376  if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
4377  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
4378  {
4379  CONSOLE_NormalTextXY(8, Line, 60, 1);
4380 
4381  Line++;
4382  if (Line < 12)
4383  Line = 15;
4384 
4385  if (Line > 15)
4386  Line = 12;
4387 
4388  CONSOLE_InvertTextXY(8, Line, 60, 1);
4389  }
4390  else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
4391  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
4392  {
4393  CONSOLE_NormalTextXY(8, Line, 60, 1);
4394 
4395  Line--;
4396  if (Line < 12)
4397  Line = 15;
4398 
4399  if (Line > 15)
4400  Line = 12;
4401 
4402  CONSOLE_InvertTextXY(8, Line, 60, 1);
4403  }
4404  else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
4405  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_HOME)) /* HOME */
4406  {
4407  CONSOLE_NormalTextXY(8, Line, 60, 1);
4408 
4409  Line = 12;
4410 
4411  CONSOLE_InvertTextXY(8, Line, 60, 1);
4412  }
4413  else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
4414  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_END)) /* END */
4415  {
4416  CONSOLE_NormalTextXY(8, Line, 60, 1);
4417 
4418  Line = 15;
4419 
4420  CONSOLE_InvertTextXY(8, Line, 60, 1);
4421  }
4422  else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
4423  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
4424  {
4425  if (ConfirmQuit(Ir))
4426  return QUIT_PAGE;
4427 
4428  break;
4429  }
4430  else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
4431  {
4432  if (Line == 12)
4433  {
4434  /* Install on both MBR and VBR */
4435  USetupData.MBRInstallType = 2;
4436  break;
4437  }
4438  else if (Line == 13)
4439  {
4440  /* Install on VBR only */
4441  USetupData.MBRInstallType = 3;
4442  break;
4443  }
4444  else if (Line == 14)
4445  {
4446  /* Install on floppy */
4447  USetupData.MBRInstallType = 1;
4448  break;
4449  }
4450  else if (Line == 15)
4451  {
4452  /* Skip MBR installation */
4453  USetupData.MBRInstallType = 0;
4454  break;
4455  }
4456 
4457  return BOOT_LOADER_PAGE;
4458  }
4459  }
4460 
4461 Quit:
4462  switch (USetupData.MBRInstallType)
4463  {
4464  /* Skip MBR installation */
4465  case 0:
4466  return SUCCESS_PAGE;
4467 
4468  /* Install on floppy */
4469  case 1:
4470  return BOOT_LOADER_FLOPPY_PAGE;
4471 
4472  /* Install on both MBR and VBR */
4473  case 2:
4475 
4476  /* Install on VBR only */
4477  case 3:
4479  }
4480 
4481  return BOOT_LOADER_PAGE;
4482 }
4483 
4484 
4485 /*
4486  * Displays the BootLoaderFloppyPage.
4487  *
4488  * Next pages:
4489  * SuccessPage (At once)
4490  * QuitPage
4491  *
4492  * SIDEEFFECTS
4493  * Calls InstallFatBootcodeToFloppy()
4494  *
4495  * RETURNS
4496  * Number of the next page.
4497  */
4498 static PAGE_NUMBER
4500 {
4501  NTSTATUS Status;
4502 
4504 
4505 // CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
4506 
4507  while (TRUE)
4508  {
4509  CONSOLE_ConInKey(Ir);
4510 
4511  if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
4512  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
4513  {
4514  if (ConfirmQuit(Ir))
4515  return QUIT_PAGE;
4516 
4517  break;
4518  }
4519  else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
4520  {
4521  Status = InstallFatBootcodeToFloppy(&USetupData.SourceRootPath,
4522  &USetupData.DestinationArcPath);
4523  if (!NT_SUCCESS(Status))
4524  {
4527 
4528  /* TODO: Print error message */
4529  return BOOT_LOADER_FLOPPY_PAGE;
4530  }
4531 
4532  return SUCCESS_PAGE;
4533  }
4534  }
4535 
4536  return BOOT_LOADER_FLOPPY_PAGE;
4537 }
4538 
4539 
4540 /*
4541  * Displays the BootLoaderHarddiskVbrPage.
4542  *
4543  * Next pages:
4544  * SuccessPage (At once)
4545  * QuitPage
4546  *
4547  * SIDEEFFECTS
4548  * Calls InstallVBRToPartition()
4549  *
4550  * RETURNS
4551  * Number of the next page.
4552  */
4553 static PAGE_NUMBER
4555 {
4556  NTSTATUS Status;
4557 
4558  // FIXME! We must not use the partition type, but instead use the partition FileSystem!!
4559  Status = InstallVBRToPartition(&USetupData.SystemRootPath,
4560  &USetupData.SourceRootPath,
4561  &USetupData.DestinationArcPath,
4563  if (!NT_SUCCESS(Status))
4564  {
4567  return QUIT_PAGE;
4568  }
4569 
4570  return SUCCESS_PAGE;
4571 }
4572 
4573 
4574 /*
4575  * Displays the BootLoaderHarddiskMbrPage.
4576  *
4577  * Next pages:
4578  * SuccessPage (At once)
4579  * QuitPage
4580  *
4581  * SIDEEFFECTS
4582  * Calls InstallVBRToPartition()
4583  * Calls InstallMbrBootCodeToDisk()
4584  *
4585  * RETURNS
4586  * Number of the next page.
4587  */
4588 static PAGE_NUMBER
4590 {
4591  NTSTATUS Status;
4592  WCHAR DestinationDevicePathBuffer[MAX_PATH];
4593 
4594  /* Step 1: Write the VBR */
4595  // FIXME! We must not use the partition type, but instead use the partition FileSystem!!
4596  Status = InstallVBRToPartition(&USetupData.SystemRootPath,
4597  &USetupData.SourceRootPath,
4598  &USetupData.DestinationArcPath,
4600  if (!NT_SUCCESS(Status))
4601  {
4604  return QUIT_PAGE;
4605  }
4606 
4607  /* Step 2: Write the MBR if the disk containing the system partition is not a super-floppy */
4609  {
4610  RtlStringCchPrintfW(DestinationDevicePathBuffer, ARRAYSIZE(DestinationDevicePathBuffer),
4611  L"\\Device\\Harddisk%d\\Partition0",
4612  SystemPartition->DiskEntry->DiskNumber);
4613  Status = InstallMbrBootCodeToDisk(&USetupData.SystemRootPath,
4614  &USetupData.SourceRootPath,
4615  DestinationDevicePathBuffer);
4616  if (!NT_SUCCESS(Status))
4617  {
4618  DPRINT1("InstallMbrBootCodeToDisk() failed (Status %lx)\n", Status);
4620  return QUIT_PAGE;
4621  }
4622  }
4623 
4624  return SUCCESS_PAGE;
4625 }
4626 
4627 
4650 static
4651 BOOLEAN NTAPI
4653  IN PPROGRESSBAR Bar,
4655  OUT PSTR Buffer,
4657 {
4658  ULONG OldProgress = Bar->Progress;
4659 
4660  if (Bar->StepCount == 0)
4661  {
4662  Bar->Progress = 0;
4663  }
4664  else
4665  {
4666  Bar->Progress = Bar->StepCount - Bar->CurrentStep;
4667  }
4668 
4669  /* Build the progress string if it has changed */
4670  if (Bar->ProgressFormatText &&
4671  (AlwaysUpdate || (Bar->Progress != OldProgress)))
4672  {
4674  Bar->ProgressFormatText, Bar->Progress / max(1, Bar->Width) + 1);
4675 
4676  return TRUE;
4677  }
4678 
4679  return FALSE;
4680 }
4681 
4698 static VOID
4700  IN PINPUT_RECORD Ir,
4701  IN LONG TimeOut)
4702 {
4703  NTSTATUS Status;
4704  ULONG StartTime, BarWidth, TimerDiv;
4705  LONG TimeElapsed;
4706  LONG TimerValue, OldTimerValue;
4708  PPROGRESSBAR ProgressBar;
4709  BOOLEAN RefreshProgress = TRUE;
4710 
4711  /* Bail out if the timeout is already zero */
4712  if (TimeOut <= 0)
4713  return;
4714 
4715  /* Create the timeout progress bar and set it up */
4716  ProgressBar = CreateProgressBarEx(13,
4717  26,
4718  xScreen - 13,
4719  yScreen - 20,
4720  10,
4721  24,
4722  TRUE,
4724  0,
4725  NULL,
4728 
4729  BarWidth = max(1, ProgressBar->Width);
4730  TimerValue = TimeOut * BarWidth;
4731  ProgressSetStepCount(ProgressBar, TimerValue);
4732 
4734  CONSOLE_Flush();
4735 
4736  TimerDiv = 1000 / BarWidth;
4737  TimerDiv = max(1, TimerDiv);
4738  OldTimerValue = TimerValue;
4739  while (TRUE)
4740  {
4741  /* Decrease the timer */
4742 
4743  /*
4744  * Compute how much time the previous operations took.
4745  * This allows us in particular to take account for any time
4746  * elapsed if something slowed down.
4747  */
4748  TimeElapsed = NtGetTickCount() - StartTime;
4749  if (TimeElapsed >= TimerDiv)
4750  {
4751  /* Increase StartTime by steps of 1 / ProgressBar->Width seconds */
4752  TimeElapsed /= TimerDiv;
4753  StartTime += (TimerDiv * TimeElapsed);
4754 
4755  if (TimeElapsed <= TimerValue)
4756  TimerValue -= TimeElapsed;
4757  else
4758  TimerValue = 0;
4759 
4760  RefreshProgress = TRUE;
4761  }
4762 
4763  if (RefreshProgress)
4764  {
4765  ProgressSetStep(ProgressBar, OldTimerValue - TimerValue);
4766  RefreshProgress = FALSE;
4767  }
4768 
4769  /* Stop when the timer reaches zero */
4770  if (TimerValue <= 0)
4771  break;
4772 
4773  /* Check for user key presses */
4774 
4775  /*
4776  * If the timer is used, use a passive wait of maximum 1 second
4777  * while monitoring for incoming console input events, so that
4778  * we are still able to display the timing count.
4779  */
4780 
4781  /* Wait a maximum of 1 second for input events */
4782  TimeElapsed = NtGetTickCount() - StartTime;
4783  if (TimeElapsed < TimerDiv)
4784  {
4785  /* Convert the time to NT Format */
4786  Timeout.QuadPart = (TimerDiv - TimeElapsed) * -10000LL;
4788  }
4789  else
4790  {
4792  }
4793 
4794  /* Check whether the input event has been signaled, or a timeout happened */
4795  if (Status == STATUS_TIMEOUT)
4796  {
4797  continue;
4798  }
4799  if (Status != STATUS_WAIT_0)
4800  {
4801  /* An error happened, bail out */
4802  DPRINT1("NtWaitForSingleObject() failed, Status 0x%08lx\n", Status);
4803  break;
4804  }
4805 
4806  /* Check for an ENTER key press */
4807  while (CONSOLE_ConInKeyPeek(Ir))
4808  {
4809  if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
4810  {
4811  /* Found it, stop waiting */
4812  goto Exit;
4813  }
4814  }
4815  }
4816 
4817 Exit:
4818  /* Destroy the progress bar and quit */
4819  DestroyProgressBar(ProgressBar);
4820 }
4821 
4822 
4823 /*
4824  * Displays the QuitPage.
4825  *
4826  * Next pages:
4827  * FlushPage (At once)
4828  *
4829  * SIDEEFFECTS
4830  * Destroy the Lists
4831  *
4832  * RETURNS
4833  * Number of the next page.
4834  */
4835 static PAGE_NUMBER
4837 {
4839 
4840  /* Destroy the NTOS installations list */
4841  if (NtOsInstallsList != NULL)
4842  {
4845  }
4846 
4847  /* Destroy the partition list */
4848  if (PartitionList != NULL)
4849  {
4851  PartitionList = NULL;
4852  }
4853 
4854  /* Reset the formatter machine state */
4855  TempPartition = NULL;
4856  FormatState = Start;
4857 
4858  /* Destroy the filesystem list */
4860 
4862 
4863  /* Wait for maximum 15 seconds or an ENTER key before quitting */
4864  ProgressCountdown(Ir, 15);
4865  return FLUSH_PAGE;
4866 }
4867 
4868 
4869 /*
4870  * Displays the SuccessPage.
4871  *
4872  * Next pages:
4873  * FlushPage (At once)
4874  *
4875  * SIDEEFFECTS
4876  * Destroy the Lists
4877  *
4878  * RETURNS
4879  * Number of the next page.
4880  */
4881 static PAGE_NUMBER
4883 {
4885 
4886  if (IsUnattendedSetup)
4887  return FLUSH_PAGE;
4888 
4889  /* Wait for maximum 15 seconds or an ENTER key before quitting */
4890  ProgressCountdown(Ir, 15);
4891  return FLUSH_PAGE;
4892 }
4893 
4894 
4895 /*
4896  * Displays the FlushPage.
4897  *
4898  * Next pages:
4899  * RebootPage (At once)
4900  *
4901  * RETURNS
4902  * Number of the next page.
4903  */
4904 static PAGE_NUMBER
4906 {
4908  return REBOOT_PAGE;
4909 }
4910 
4911 
4912 /*
4913  * The start routine and page management
4914  */
4915 NTSTATUS
4917 {
4918  NTSTATUS Status;
4919  INPUT_RECORD Ir;
4920  PAGE_NUMBER Page;
4921  BOOLEAN Old;
4922 
4924 
4925  /* Tell the Cm this is a setup boot, and it has to behave accordingly */
4927  if (!NT_SUCCESS(Status))
4928  DPRINT1("NtInitializeRegistry() failed (Status 0x%08lx)\n", Status);
4929 
4930  /* Initialize the user-mode PnP manager */
4932  if (!NT_SUCCESS(Status))
4933  {
4934  // PrintString(??);
4935  DPRINT1("The user-mode PnP manager could not initialize (Status 0x%08lx), expect unavailable devices!\n", Status);
4936  }
4937 
4938  if (!CONSOLE_Init())
4939  {
4943 
4944  /* We failed to initialize the video, just quit the installer */
4945  return STATUS_APP_INIT_FAILURE;
4946  }
4947 
4948  /* Initialize Setup, phase 0 */
4950  USetupData.ErrorRoutine = USetupErrorRoutine;
4951 
4952  /* Hide the cursor and clear the screen and keyboard buffer */
4955  CONSOLE_Flush();
4956 
4957  /* Global Initialization page */
4958  Page = SetupStartPage(&Ir);
4959 
4960  while (Page != REBOOT_PAGE && Page != RECOVERY_PAGE)
4961  {
4963  CONSOLE_Flush();
4964 
4965  // CONSOLE_SetUnderlinedTextXY(4, 3, " ReactOS " KERNEL_VERSION_STR " Setup ");
4966  // CONSOLE_Flush();
4967 
4968  switch (Page)
4969  {
4970  /* Language page */
4971  case LANGUAGE_PAGE:
4972  Page = LanguagePage(&Ir);
4973  break;
4974 
4975  /* Welcome page */
4976  case WELCOME_PAGE:
4977  Page = WelcomePage(&Ir);
4978  break;
4979 
4980  /* License page */
4981  case LICENSE_PAGE:
4982  Page = LicensePage(&Ir);
4983  break;
4984 
4985  /* Install pages */
4986  case INSTALL_INTRO_PAGE:
4987  Page = InstallIntroPage(&Ir);
4988  break;
4989 
4990 #if 0
4991  case SCSI_CONTROLLER_PAGE:
4992  Page = ScsiControllerPage(&Ir);
4993  break;
4994 
4995  case OEM_DRIVER_PAGE:
4996  Page = OemDriverPage(&Ir);
4997  break;
4998 #endif
4999 
5000  case DEVICE_SETTINGS_PAGE:
5001  Page = DeviceSettingsPage(&Ir);
5002  break;
5003 
5005  Page = ComputerSettingsPage(&Ir);
5006  break;
5007 
5008  case DISPLAY_SETTINGS_PAGE:
5009  Page = DisplaySettingsPage(&Ir);
5010  break;
5011 
5013  Page = KeyboardSettingsPage(&Ir);
5014  break;
5015 
5016  case LAYOUT_SETTINGS_PAGE:
5017  Page = LayoutSettingsPage(&Ir);
5018  break;
5019 
5020  case SELECT_PARTITION_PAGE:
5021  Page = SelectPartitionPage(&Ir);
5022  break;
5023 
5025  Page = CreatePrimaryPartitionPage(&Ir);
5026  break;
5027 
5029  Page = CreateExtendedPartitionPage(&Ir);
5030  break;
5031 
5033  Page = CreateLogicalPartitionPage(&Ir);
5034  break;
5035 
5038  break;
5039 
5040  case DELETE_PARTITION_PAGE:
5041  Page = DeletePartitionPage(&Ir);
5042  break;
5043 
5045  Page = SelectFileSystemPage(&Ir);
5046  break;
5047 
5048  case FORMAT_PARTITION_PAGE:
5049  Page = FormatPartitionPage(&Ir);
5050  break;
5051 
5053  Page = CheckFileSystemPage(&Ir);
5054  break;
5055 
5057  Page = InstallDirectoryPage(&Ir);
5058  break;
5059 
5060  case PREPARE_COPY_PAGE:
5061  Page = PrepareCopyPage(&Ir);
5062  break;
5063 
5064  case FILE_COPY_PAGE:
5065  Page = FileCopyPage(&Ir);
5066  break;
5067 
5068  case REGISTRY_PAGE:
5069  Page = RegistryPage(&Ir);
5070  break;
5071 
5072  case BOOT_LOADER_PAGE:
5073  Page = BootLoaderPage(&Ir);
5074  break;
5075 
5077  Page = BootLoaderFloppyPage(&Ir);
5078  break;
5079 
5081  Page = BootLoaderHarddiskMbrPage(&Ir);
5082  break;
5083 
5085  Page = BootLoaderHarddiskVbrPage(&Ir);
5086  break;
5087 
5088  /* Repair pages */
5089  case REPAIR_INTRO_PAGE:
5090  Page = RepairIntroPage(&Ir);
5091  break;
5092 
5093  case UPGRADE_REPAIR_PAGE:
5094  Page = UpgradeRepairPage(&Ir);
5095  break;
5096 
5097  case SUCCESS_PAGE:
5098  Page = SuccessPage(&Ir);
5099  break;
5100 
5101  case FLUSH_PAGE:
5102  Page = FlushPage(&Ir);
5103  break;
5104 
5105  case QUIT_PAGE:
5106  Page = QuitPage(&Ir);
5107  break;
5108 
5109  /* Virtual pages */
5110  case SETUP_INIT_PAGE:
5111  case REBOOT_PAGE:
5112  case RECOVERY_PAGE:
5113  break;
5114 
5115  default:
5116  break;
5117  }
5118  }
5119 
5120  /* Terminate the user-mode PnP manager */
5122 
5123  /* Setup has finished */