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