ReactOS  0.4.15-dev-2979-gfd8baca
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  0xDA, // '+',
179  1,
180  coPos,
181  &Written);
182 
183  /* Draw upper edge */
184  coPos.X = xLeft + 1;
185  coPos.Y = yTop;
187  0xC4, // '-',
188  Width - 2,
189  coPos,
190  &Written);
191 
192  /* Draw upper right corner */
193  coPos.X = xLeft + Width - 1;
194  coPos.Y = yTop;
196  0xBF, // '+',
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  0xB3, // '|',
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  0xB3, // '|',
221  1,
222  coPos,
223  &Written);
224  }
225 
226  /* Draw lower left corner */
227  coPos.X = xLeft;
228  coPos.Y = yTop + Height - 1;
230  0xC0, // '+',
231  1,
232  coPos,
233  &Written);
234 
235  /* Draw lower edge */
236  coPos.X = xLeft + 1;
237  coPos.Y = yTop + Height - 1;
239  0xC4, // '-',
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  0xD9, // '+',
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;
378  0xC3, // '+',
379  1,
380  coPos,
381  &Written);
382 
383  coPos.X = xLeft + 1;
385  0xC4, // '-',
386  Width - 2,
387  coPos,
388  &Written);
389 
390  coPos.X = xLeft + Width - 1;
392  0xB4, // '+',
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 language selection page in native language */
668  }
669 
670  RefreshPage = FALSE;
671  }
672  }
673 
674  return WELCOME_PAGE;
675 }
676 
677 
678 /*
679  * Start page
680  *
681  * Next pages:
682  * LanguagePage (at once, default)
683  * InstallIntroPage (at once, if unattended)
684  * QuitPage
685  *
686  * SIDEEFFECTS
687  * Init Sdi
688  * Init USetupData.SourcePath
689  * Init USetupData.SourceRootPath
690  * Init USetupData.SourceRootDir
691  * Init USetupData.SetupInf
692  * Init USetupData.RequiredPartitionDiskSpace
693  * Init IsUnattendedSetup
694  * If unattended, init *List and sets the Codepage
695  * If unattended, init SelectedLanguageId
696  * If unattended, init USetupData.LanguageId
697  *
698  * RETURNS
699  * Number of the next page.
700  */
701 static PAGE_NUMBER
703 {
704  ULONG Error;
705  PGENERIC_LIST_ENTRY ListEntry;
707 
709 
710  /* Initialize Setup, phase 1 */
712  if (Error != ERROR_SUCCESS)
713  {
715  return QUIT_PAGE;
716  }
717 
718  /* Initialize the user-mode PnP manager */
720  DPRINT1("The user-mode PnP manager could not initialize, expect unavailable devices!\n");
721 
722  /* Wait for any immediate pending installations to finish */
724  DPRINT1("WaitNoPendingInstallEvents() failed to wait!\n");
725 
727 
728  if (IsUnattendedSetup)
729  {
730  // TODO: Read options from inf
731  /* Load the hardware, language and keyboard layout lists */
732 
733  USetupData.ComputerList = CreateComputerTypeList(USetupData.SetupInf);
734  USetupData.DisplayList = CreateDisplayDriverList(USetupData.SetupInf);
735  USetupData.KeyboardList = CreateKeyboardDriverList(USetupData.SetupInf);
736 
737  USetupData.LanguageList = CreateLanguageList(USetupData.SetupInf, DefaultLanguage);
738 
739  /* new part */
741  wcscpy(DefaultLanguage, USetupData.LocaleID);
742  USetupData.LanguageId = (LANGID)(wcstol(SelectedLanguageId, NULL, 16) & 0xFFFF);
743 
745 
746  /* first we hack LanguageList */
747  for (ListEntry = GetFirstListEntry(USetupData.LanguageList); ListEntry;
748  ListEntry = GetNextListEntry(ListEntry))
749  {
750  LocaleId = ((PGENENTRY)GetListEntryData(ListEntry))->Id;
751  if (!wcsicmp(USetupData.LocaleID, LocaleId))
752  {
753  DPRINT("found %S in LanguageList\n", LocaleId);
754  SetCurrentListEntry(USetupData.LanguageList, ListEntry);
755  break;
756  }
757  }
758 
759  /* now LayoutList */
760  for (ListEntry = GetFirstListEntry(USetupData.LayoutList); ListEntry;
761  ListEntry = GetNextListEntry(ListEntry))
762  {
763  LocaleId = ((PGENENTRY)GetListEntryData(ListEntry))->Id;
764  if (!wcsicmp(USetupData.LocaleID, LocaleId))
765  {
766  DPRINT("found %S in LayoutList\n", LocaleId);
767  SetCurrentListEntry(USetupData.LayoutList, ListEntry);
768  break;
769  }
770  }
771 
773 
774  return INSTALL_INTRO_PAGE;
775  }
776 
777  return LANGUAGE_PAGE;
778 }
779 
780 
781 /*
782  * Displays the WelcomePage.
783  *
784  * Next pages:
785  * InstallIntroPage (default)
786  * RepairIntroPage
787  * RecoveryPage
788  * LicensePage
789  * QuitPage
790  *
791  * RETURNS
792  * Number of the next page.
793  */
794 static PAGE_NUMBER
796 {
798 
799  while (TRUE)
800  {
801  CONSOLE_ConInKey(Ir);
802 
803  if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
804  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
805  {
806  if (ConfirmQuit(Ir))
807  return QUIT_PAGE;
808 
809  break;
810  }
811  else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
812  {
813  return INSTALL_INTRO_PAGE;
814  }
815  else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'R') /* R */
816  {
817  return RECOVERY_PAGE; // REPAIR_INTRO_PAGE;
818  }
819  else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'L') /* L */
820  {
821  return LICENSE_PAGE;
822  }
823  }
824 
825  return WELCOME_PAGE;
826 }
827 
828 
829 /*
830  * Displays the License page.
831  *
832  * Next page:
833  * WelcomePage (default)
834  *
835  * RETURNS
836  * Number of the next page.
837  */
838 static PAGE_NUMBER
840 {
842 
843  while (TRUE)
844  {
845  CONSOLE_ConInKey(Ir);
846 
847  if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
848  {
849  return WELCOME_PAGE;
850  }
851  }
852 
853  return LICENSE_PAGE;
854 }
855 
856 
857 /*
858  * Displays the RepairIntroPage.
859  *
860  * Next pages:
861  * RebootPage (default)
862  * InstallIntroPage
863  * RecoveryPage
864  * IntroPage
865  *
866  * RETURNS
867  * Number of the next page.
868  */
869 static PAGE_NUMBER
871 {
873 
874  while (TRUE)
875  {
876  CONSOLE_ConInKey(Ir);
877 
878  if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
879  {
880  return REBOOT_PAGE;
881  }
882  else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'U') /* U */
883  {
885  return INSTALL_INTRO_PAGE;
886  }
887  else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'R') /* R */
888  {
889  return RECOVERY_PAGE;
890  }
891  else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESC */
892  {
893  return WELCOME_PAGE;
894  }
895  }
896 
897  return REPAIR_INTRO_PAGE;
898 }
899 
900 /*
901  * Displays the UpgradeRepairPage.
902  *
903  * Next pages:
904  * RebootPage (default)
905  * InstallIntroPage
906  * RecoveryPage
907  * WelcomePage
908  *
909  * RETURNS
910  * Number of the next page.
911  */
912 static PAGE_NUMBER
914 {
915  GENERIC_LIST_UI ListUi;
916 
917 /*** HACK!! ***/
918  if (PartitionList == NULL)
919  {
921  if (PartitionList == NULL)
922  {
923  /* FIXME: show an error dialog */
925  return QUIT_PAGE;
926  }
928  {
930  return QUIT_PAGE;
931  }
932 
933  /* Reset the formatter machine state */
935  FormatState = Start;
936  }
937 /**************/
938 
940  if (!NtOsInstallsList)
941  DPRINT1("Failed to get a list of NTOS installations; continue installation...\n");
942 
943  /*
944  * If there is no available installation (or just a single one??) that can
945  * be updated in the list, just continue with the regular installation.
946  */
948  {
950 
951  // return INSTALL_INTRO_PAGE;
952  return DEVICE_SETTINGS_PAGE;
953  // return SCSI_CONTROLLER_PAGE;
954  }
955 
957 
959  DrawGenericList(&ListUi,
960  2, 23,
961  xScreen - 3,
962  yScreen - 3);
963 
964  // return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir);
965  while (TRUE)
966  {
967  CONSOLE_ConInKey(Ir);
968 
969  if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x00)
970  {
971  switch (Ir->Event.KeyEvent.wVirtualKeyCode)
972  {
973  case VK_DOWN: /* DOWN */
974  ScrollDownGenericList(&ListUi);
975  break;
976  case VK_UP: /* UP */
977  ScrollUpGenericList(&ListUi);
978  break;
979  case VK_NEXT: /* PAGE DOWN */
980  ScrollPageDownGenericList(&ListUi);
981  break;
982  case VK_PRIOR: /* PAGE UP */
983  ScrollPageUpGenericList(&ListUi);
984  break;
985  case VK_F3: /* F3 */
986  {
987  if (ConfirmQuit(Ir))
988  return QUIT_PAGE;
989  else
990  RedrawGenericList(&ListUi);
991  break;
992  }
993 #if 1
994 /* TODO: Temporarily kept until correct keyboard layout is in place.
995  * (Actual AsciiChar of ESCAPE should be 0x1B instead of 0.)
996  * Addendum to commit 8b94515b.
997  */
998  case VK_ESCAPE: /* ESC */
999  {
1000  RestoreGenericListUiState(&ListUi);
1001  // return nextPage; // prevPage;
1002 
1003  // return INSTALL_INTRO_PAGE;
1004  return DEVICE_SETTINGS_PAGE;
1005  // return SCSI_CONTROLLER_PAGE;
1006  }
1007 
1008 #endif
1009  }
1010  }
1011 #if 0
1012 /* TODO: Restore this once correct keyboard layout is in place. */
1013  else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESC */
1014  {
1015  RestoreGenericListUiState(&ListUi);
1016  // return nextPage; // prevPage;
1017 
1018  // return INSTALL_INTRO_PAGE;
1019  return DEVICE_SETTINGS_PAGE;
1020  // return SCSI_CONTROLLER_PAGE;
1021  }
1022 #endif
1023  else
1024  {
1025  // switch (toupper(Ir->Event.KeyEvent.uChar.AsciiChar))
1026  // if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1027  if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'U') /* U */
1028  {
1029  /* Retrieve the current installation */
1031 
1034 
1035  DPRINT1("Selected installation for repair: \"%S\" ; DiskNumber = %d , PartitionNumber = %d\n",
1037 
1039 
1040  // return nextPage;
1041  /***/return INSTALL_INTRO_PAGE;/***/
1042  }
1043  else if ((Ir->Event.KeyEvent.uChar.AsciiChar > 0x60) &&
1044  (Ir->Event.KeyEvent.uChar.AsciiChar < 0x7b)) /* a-z */
1045  {
1047  }
1048  }
1049  }
1050 
1051  return UPGRADE_REPAIR_PAGE;
1052 }
1053 
1054 
1055 /*
1056  * Displays the InstallIntroPage.
1057  *
1058  * Next pages:
1059  * DeviceSettingsPage (At once if repair or update is selected)
1060  * SelectPartitionPage (At once if unattended setup)
1061  * DeviceSettingsPage (default)
1062  * QuitPage
1063  *
1064  * RETURNS
1065  * Number of the next page.
1066  */
1067 static PAGE_NUMBER
1069 {
1070  if (RepairUpdateFlag)
1071  {
1072 #if 1 /* Old code that looks good */
1073 
1074  // return SELECT_PARTITION_PAGE;
1075  return DEVICE_SETTINGS_PAGE;
1076 
1077 #else /* Possible new code? */
1078 
1079  return DEVICE_SETTINGS_PAGE;
1080  // return SCSI_CONTROLLER_PAGE;
1081 
1082 #endif
1083  }
1084 
1085  if (IsUnattendedSetup)
1086  return SELECT_PARTITION_PAGE;
1087 
1089 
1090  while (TRUE)
1091  {
1092  CONSOLE_ConInKey(Ir);
1093 
1094  if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1095  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1096  {
1097  if (ConfirmQuit(Ir))
1098  return QUIT_PAGE;
1099 
1100  break;
1101  }
1102  else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1103  {
1104  return UPGRADE_REPAIR_PAGE;
1105  }
1106  }
1107 
1108  return INSTALL_INTRO_PAGE;
1109 }
1110 
1111 
1112 #if 0
1113 static PAGE_NUMBER
1114 ScsiControllerPage(PINPUT_RECORD Ir)
1115 {
1116  // MUIDisplayPage(SCSI_CONTROLLER_PAGE);
1117 
1118  CONSOLE_SetTextXY(6, 8, "Setup detected the following mass storage devices:");
1119 
1120  /* FIXME: print loaded mass storage driver descriptions */
1121 #if 0
1122  CONSOLE_SetTextXY(8, 10, "TEST device");
1123 #endif
1124 
1125  CONSOLE_SetStatusText(" ENTER = Continue F3 = Quit");
1126 
1127  while (TRUE)
1128  {
1129  CONSOLE_ConInKey(Ir);
1130 
1131  if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1132  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1133  {
1134  if (ConfirmQuit(Ir))
1135  return QUIT_PAGE;
1136 
1137  break;
1138  }
1139  else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1140  {
1141  return DEVICE_SETTINGS_PAGE;
1142  }
1143  }
1144 
1145  return SCSI_CONTROLLER_PAGE;
1146 }
1147 
1148 static PAGE_NUMBER
1149 OemDriverPage(PINPUT_RECORD Ir)
1150 {
1151  // MUIDisplayPage(OEM_DRIVER_PAGE);
1152 
1153  CONSOLE_SetTextXY(6, 8, "This is the OEM driver page!");
1154 
1155  /* FIXME: Implement!! */
1156 
1157  CONSOLE_SetStatusText(" ENTER = Continue F3 = Quit");
1158 
1159  while (TRUE)
1160  {
1161  CONSOLE_ConInKey(Ir);
1162 
1163  if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1164  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1165  {
1166  if (ConfirmQuit(Ir))
1167  return QUIT_PAGE;
1168 
1169  break;
1170  }
1171  else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1172  {
1173  return DEVICE_SETTINGS_PAGE;
1174  }
1175  }
1176 
1177  return OEM_DRIVER_PAGE;
1178 }
1179 #endif
1180 
1181 
1182 /*
1183  * Displays the DeviceSettingsPage.
1184  *
1185  * Next pages:
1186  * SelectPartitionPage (At once if repair or update is selected)
1187  * ComputerSettingsPage
1188  * DisplaySettingsPage
1189  * KeyboardSettingsPage
1190  * LayoutsettingsPage
1191  * SelectPartitionPage
1192  * QuitPage
1193  *
1194  * SIDEEFFECTS
1195  * Init USetupData.ComputerList
1196  * Init USetupData.DisplayList
1197  * Init USetupData.KeyboardList
1198  * Init USetupData.LayoutList
1199  *
1200  * RETURNS
1201  * Number of the next page.
1202  */
1203 static PAGE_NUMBER
1205 {
1206  static ULONG Line = 16;
1207 
1208  /* Initialize the computer settings list */
1209  if (USetupData.ComputerList == NULL)
1210  {
1211  USetupData.ComputerList = CreateComputerTypeList(USetupData.SetupInf);
1212  if (USetupData.ComputerList == NULL)
1213  {
1215  return QUIT_PAGE;
1216  }
1217  }
1218 
1219  /* Initialize the display settings list */
1220  if (USetupData.DisplayList == NULL)
1221  {
1222  USetupData.DisplayList = CreateDisplayDriverList(USetupData.SetupInf);
1223  if (USetupData.DisplayList == NULL)
1224  {
1226  return QUIT_PAGE;
1227  }
1228  }
1229 
1230  /* Initialize the keyboard settings list */
1231  if (USetupData.KeyboardList == NULL)
1232  {
1233  USetupData.KeyboardList = CreateKeyboardDriverList(USetupData.SetupInf);
1234  if (USetupData.KeyboardList == NULL)
1235  {
1237  return QUIT_PAGE;
1238  }
1239  }
1240 
1241  /* Initialize the keyboard layout list */
1242  if (USetupData.LayoutList == NULL)
1243  {
1245  if (USetupData.LayoutList == NULL)
1246  {
1247  /* FIXME: report error */
1249  return QUIT_PAGE;
1250  }
1251  }
1252 
1253  if (RepairUpdateFlag)
1254  return SELECT_PARTITION_PAGE;
1255 
1256  // if (IsUnattendedSetup)
1257  // return SELECT_PARTITION_PAGE;
1258 
1260 
1265 
1266  CONSOLE_InvertTextXY(24, Line, 48, 1);
1267 
1268  while (TRUE)
1269  {
1270  CONSOLE_ConInKey(Ir);
1271 
1272  if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1273  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1274  {
1275  CONSOLE_NormalTextXY(24, Line, 48, 1);
1276 
1277  if (Line == 14)
1278  Line = 16;
1279  else if (Line == 16)
1280  Line = 11;
1281  else
1282  Line++;
1283 
1284  CONSOLE_InvertTextXY(24, Line, 48, 1);
1285  }
1286  else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1287  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1288  {
1289  CONSOLE_NormalTextXY(24, Line, 48, 1);
1290 
1291  if (Line == 11)
1292  Line = 16;
1293  else if (Line == 16)
1294  Line = 14;
1295  else
1296  Line--;
1297 
1298  CONSOLE_InvertTextXY(24, Line, 48, 1);
1299  }
1300  else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1301  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1302  {
1303  if (ConfirmQuit(Ir))
1304  return QUIT_PAGE;
1305 
1306  break;
1307  }
1308  else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1309  {
1310  if (Line == 11)
1311  return COMPUTER_SETTINGS_PAGE;
1312  else if (Line == 12)
1313  return DISPLAY_SETTINGS_PAGE;
1314  else if (Line == 13)
1315  return KEYBOARD_SETTINGS_PAGE;
1316  else if (Line == 14)
1317  return LAYOUT_SETTINGS_PAGE;
1318  else if (Line == 16)
1319  return SELECT_PARTITION_PAGE;
1320  }
1321  }
1322 
1323  return DEVICE_SETTINGS_PAGE;
1324 }
1325 
1326 
1327 /*
1328  * Handles generic selection lists.
1329  *
1330  * PARAMS
1331  * GenericList: The list to handle.
1332  * nextPage: The page it needs to jump to after this page.
1333  * Ir: The PINPUT_RECORD
1334  */
1335 static PAGE_NUMBER
1337  PAGE_NUMBER nextPage,
1338  PINPUT_RECORD Ir)
1339 {
1340  while (TRUE)
1341  {
1342  CONSOLE_ConInKey(Ir);
1343 
1344  if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1345  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1346  {
1347  ScrollDownGenericList(ListUi);
1348  }
1349  else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1350  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1351  {
1352  ScrollUpGenericList(ListUi);
1353  }
1354  else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1355  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_NEXT)) /* PAGE DOWN */
1356  {
1357  ScrollPageDownGenericList(ListUi);
1358  }
1359  else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1360  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_PRIOR)) /* PAGE UP */
1361  {
1362  ScrollPageUpGenericList(ListUi);
1363  }
1364  else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1365  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1366  {
1367  if (ConfirmQuit(Ir))
1368  return QUIT_PAGE;
1369  else
1370  RedrawGenericList(ListUi);
1371  }
1372  else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESC */
1373  {
1374  RestoreGenericListUiState(ListUi);
1375  return nextPage; // Use some "prevPage;" instead?
1376  }
1377  else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1378  {
1379  return nextPage;
1380  }
1381  else if ((Ir->Event.KeyEvent.uChar.AsciiChar > 0x60) && (Ir->Event.KeyEvent.uChar.AsciiChar < 0x7b))
1382  {
1383  /* a-z */
1385  }
1386  }
1387 }
1388 
1389 
1390 /*
1391  * Displays the ComputerSettingsPage.
1392  *
1393  * Next pages:
1394  * DeviceSettingsPage
1395  * QuitPage
1396  *
1397  * RETURNS
1398  * Number of the next page.
1399  */
1400 static PAGE_NUMBER
1402 {
1403  GENERIC_LIST_UI ListUi;
1405 
1406  InitGenericListUi(&ListUi, USetupData.ComputerList, GetSettingDescription);
1407  DrawGenericList(&ListUi,
1408  2, 18,
1409  xScreen - 3,
1410  yScreen - 3);
1411 
1412  return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir);
1413 }
1414 
1415 
1416 /*
1417  * Displays the DisplaySettingsPage.
1418  *
1419  * Next pages:
1420  * DeviceSettingsPage
1421  * QuitPage
1422  *
1423  * RETURNS
1424  * Number of the next page.
1425  */
1426 static PAGE_NUMBER
1428 {
1429  GENERIC_LIST_UI ListUi;
1431 
1432  InitGenericListUi(&ListUi, USetupData.DisplayList, GetSettingDescription);
1433  DrawGenericList(&ListUi,
1434  2, 18,
1435  xScreen - 3,
1436  yScreen - 3);
1437 
1438  return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir);
1439 }
1440 
1441 
1442 /*
1443  * Displays the KeyboardSettingsPage.
1444  *
1445  * Next pages:
1446  * DeviceSettingsPage
1447  * QuitPage
1448  *
1449  * RETURNS
1450  * Number of the next page.
1451  */
1452 static PAGE_NUMBER
1454 {
1455  GENERIC_LIST_UI ListUi;
1457 
1458  InitGenericListUi(&ListUi, USetupData.KeyboardList, GetSettingDescription);
1459  DrawGenericList(&ListUi,
1460  2, 18,
1461  xScreen - 3,
1462  yScreen - 3);
1463 
1464  return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir);
1465 }
1466 
1467 
1468 /*
1469  * Displays the LayoutSettingsPage.
1470  *
1471  * Next pages:
1472  * DeviceSettingsPage
1473  * QuitPage
1474  *
1475  * RETURNS
1476  * Number of the next page.
1477  */
1478 static PAGE_NUMBER
1480 {
1481  GENERIC_LIST_UI ListUi;
1483 
1484  InitGenericListUi(&ListUi, USetupData.LayoutList, GetSettingDescription);
1485  DrawGenericList(&ListUi,
1486  2, 18,
1487  xScreen - 3,
1488  yScreen - 3);
1489 
1490  return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir);
1491 }
1492 
1493 
1494 static BOOL
1496 {
1497  ULONGLONG size;
1498 
1499  size = PartEntry->SectorCount.QuadPart * PartEntry->DiskEntry->BytesPerSector;
1500  size = (size + (512 * KB)) / MB; /* in MBytes */
1501 
1502  if (size < USetupData.RequiredPartitionDiskSpace)
1503  {
1504  /* Partition is too small so ask for another one */
1505  DPRINT1("Partition is too small (size: %I64u MB), required disk space is %lu MB\n", size, USetupData.RequiredPartitionDiskSpace);
1506  return FALSE;
1507  }
1508  else
1509  {
1510  return TRUE;
1511  }
1512 }
1513 
1514 
1515 /*
1516  * Displays the SelectPartitionPage.
1517  *
1518  * Next pages:
1519  * SelectFileSystemPage (At once if unattended)
1520  * SelectFileSystemPage (Default if free space is selected)
1521  * CreatePrimaryPartitionPage
1522  * CreateExtendedPartitionPage
1523  * CreateLogicalPartitionPage
1524  * ConfirmDeleteSystemPartitionPage (if the selected partition is the system partition, aka with the boot flag set)
1525  * DeletePartitionPage
1526  * QuitPage
1527  *
1528  * SIDEEFFECTS
1529  * Set InstallShortcut (only if not unattended + free space is selected)
1530  *
1531  * RETURNS
1532  * Number of the next page.
1533  */
1534 static PAGE_NUMBER
1536 {
1537  PARTLIST_UI ListUi;
1538  ULONG Error;
1539 
1540  if (PartitionList == NULL)
1541  {
1543  if (PartitionList == NULL)
1544  {
1546  return QUIT_PAGE;
1547  }
1549  {
1551  return QUIT_PAGE;
1552  }
1553 
1554  /* Reset the formatter machine state */
1555  TempPartition = NULL;
1556  FormatState = Start;
1557  }
1558 
1559  if (RepairUpdateFlag)
1560  {
1562 
1563  /* Determine the selected installation disk & partition */
1567  if (!InstallPartition)
1568  {
1569  DPRINT1("RepairUpdateFlag == TRUE, SelectPartition() returned FALSE, assert!\n");
1570  ASSERT(FALSE);
1571  }
1573 
1574  return SELECT_FILE_SYSTEM_PAGE;
1575  }
1576 
1578 
1581  2, 23,
1582  xScreen - 3,
1583  yScreen - 3);
1584  DrawPartitionList(&ListUi);
1585 
1586  if (IsUnattendedSetup)
1587  {
1588  /* Determine the selected installation disk & partition */
1590  USetupData.DestinationDiskNumber,
1591  USetupData.DestinationPartitionNumber);
1592  if (!InstallPartition)
1593  {
1595 
1596  if (USetupData.AutoPartition)
1597  {
1600 
1602  {
1606  TRUE);
1607  }
1608  else
1609  {
1613  TRUE);
1614  }
1615 
1616 // FIXME?? Aren't we going to enter an infinite loop, if this test fails??
1618  {
1620  USetupData.RequiredPartitionDiskSpace);
1621  return SELECT_PARTITION_PAGE; /* let the user select another partition */
1622  }
1623 
1625  return SELECT_FILE_SYSTEM_PAGE;
1626  }
1627  }
1628  else
1629  {
1631 
1632  DrawPartitionList(&ListUi); // FIXME: Doesn't make much sense...
1633 
1634 // FIXME?? Aren't we going to enter an infinite loop, if this test fails??
1636  {
1638  USetupData.RequiredPartitionDiskSpace);
1639  return SELECT_PARTITION_PAGE; /* let the user select another partition */
1640  }
1641 
1642  return SELECT_FILE_SYSTEM_PAGE;
1643  }
1644  }
1645 
1646  while (TRUE)
1647  {
1649 
1650  /* Update status text */
1651  if (CurrentPartition == NULL)
1652  {
1654  }
1656  {
1658  {
1660  }
1661  else
1662  {
1664  }
1665  }
1666  else
1667  {
1669  {
1671  {
1673  }
1674  else
1675  {
1677  }
1678  }
1679  else
1680  {
1682  }
1683  }
1684 
1685  CONSOLE_ConInKey(Ir);
1686 
1687  if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1688  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1689  {
1690  if (ConfirmQuit(Ir))
1691  {
1693  PartitionList = NULL;
1694  return QUIT_PAGE;
1695  }
1696 
1697  break;
1698  }
1699  else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1700  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1701  {
1702  ScrollDownPartitionList(&ListUi);
1703  }
1704  else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1705  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1706  {
1707  ScrollUpPartitionList(&ListUi);
1708  }
1709  else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
1710  {
1712 
1714  continue; // return SELECT_PARTITION_PAGE;
1715 
1716  /*
1717  * Check whether the user wants to install ReactOS on a disk that
1718  * is not recognized by the computer's firmware and if so, display
1719  * a warning since such disks may not be bootable.
1720  */
1721  if (CurrentPartition->DiskEntry->MediaType == FixedMedia &&
1722  !CurrentPartition->DiskEntry->BiosFound)
1723  {
1724  PopupError("The disk you have selected for installing ReactOS\n"
1725  "is not visible by the firmware of your computer,\n"
1726  "and so may not be bootable.\n"
1727  "Press ENTER to continue nonetheless.",
1729  Ir, POPUP_WAIT_ENTER);
1730  // return SELECT_PARTITION_PAGE;
1731  }
1732 
1734  {
1736  {
1738  if (Error != NOT_AN_ERROR)
1739  {
1741  return SELECT_PARTITION_PAGE;
1742  }
1743 
1746  0ULL,
1747  TRUE);
1748  }
1749  else
1750  {
1752  if (Error != NOT_AN_ERROR)
1753  {
1755  return SELECT_PARTITION_PAGE;
1756  }
1757 
1760  0ULL,
1761  TRUE);
1762  }
1763  }
1764 
1766  {
1768  USetupData.RequiredPartitionDiskSpace);
1769  return SELECT_PARTITION_PAGE; /* let the user select another partition */
1770  }
1771 
1773  return SELECT_FILE_SYSTEM_PAGE;
1774  }
1775  else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'P') /* P */
1776  {
1778 
1780  {
1782  if (Error != NOT_AN_ERROR)
1783  {
1785  return SELECT_PARTITION_PAGE;
1786  }
1787 
1789  }
1790  }
1791  else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'E') /* E */
1792  {
1794 
1796  {
1798  if (Error != NOT_AN_ERROR)
1799  {
1801  return SELECT_PARTITION_PAGE;
1802  }
1803 
1805  }
1806  }
1807  else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'L') /* L */
1808  {
1810 
1812  {
1814  if (Error != NOT_AN_ERROR)
1815  {
1817  return SELECT_PARTITION_PAGE;
1818  }
1819 
1821  }
1822  }
1823  else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'D') /* D */
1824  {
1825  UNICODE_STRING CurrentPartitionU;
1826  WCHAR PathBuffer[MAX_PATH];
1827 
1829 
1831  {
1833  return SELECT_PARTITION_PAGE;
1834  }
1835 
1836 // TODO: Do something similar before trying to format the partition?
1837  if (!CurrentPartition->New &&
1840  {
1842 
1843  RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
1844  L"\\Device\\Harddisk%lu\\Partition%lu\\",
1845  CurrentPartition->DiskEntry->DiskNumber,
1847  RtlInitUnicodeString(&CurrentPartitionU, PathBuffer);
1848 
1849  /*
1850  * Check whether the user attempts to delete the partition on which
1851  * the installation source is present. If so, fail with an error.
1852  */
1853  // &USetupData.SourceRootPath
1854  if (RtlPrefixUnicodeString(&CurrentPartitionU, &USetupData.SourcePath, TRUE))
1855  {
1857  return SELECT_PARTITION_PAGE;
1858  }
1859  }
1860 
1863  {
1865  }
1866 
1867  return DELETE_PARTITION_PAGE;
1868  }
1869  }
1870 
1871  return SELECT_PARTITION_PAGE;
1872 }
1873 
1874 
1875 #define PARTITION_SIZE_INPUT_FIELD_LENGTH 9
1876 /* Restriction for MaxSize */
1877 #define PARTITION_MAXSIZE (pow(10, (PARTITION_SIZE_INPUT_FIELD_LENGTH - 1)) - 1)
1878 
1879 static VOID
1881  SHORT Top,
1882  SHORT Right,
1883  SHORT Bottom,
1884  ULONG MaxSize,
1886  PBOOLEAN Quit,
1887  PBOOLEAN Cancel)
1888 {
1889  INPUT_RECORD Ir;
1890  COORD coPos;
1891  DWORD Written;
1892  CHAR Buffer[128];
1893  INT Length, Pos;
1894  WCHAR ch;
1895  SHORT iLeft;
1896  SHORT iTop;
1897 
1898  if (Quit != NULL)
1899  *Quit = FALSE;
1900 
1901  if (Cancel != NULL)
1902  *Cancel = FALSE;
1903 
1904  DrawBox(Left, Top, Right - Left + 1, Bottom - Top + 1);
1905 
1906  /* Print message */
1907  coPos.X = Left + 2;
1908  coPos.Y = Top + 2;
1910  iLeft = coPos.X + (USHORT)strlen(Buffer) + 1;
1911  iTop = coPos.Y;
1912 
1914  Buffer,
1915  strlen(Buffer),
1916  coPos,
1917  &Written);
1918 
1920  coPos.X = iLeft + PARTITION_SIZE_INPUT_FIELD_LENGTH + 1;
1921  coPos.Y = iTop;
1923  Buffer,
1924  strlen(Buffer),
1925  coPos,
1926  &Written);
1927 
1928  swprintf(InputBuffer, L"%lu", MaxSize);
1930  Pos = Length;
1931  CONSOLE_SetInputTextXY(iLeft,
1932  iTop,
1934  InputBuffer);
1935  CONSOLE_SetCursorXY(iLeft + Length, iTop);
1937 
1938  while (TRUE)
1939  {
1940  CONSOLE_ConInKey(&Ir);
1941 
1942  if ((Ir.Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1943  (Ir.Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1944  {
1945  if (Quit != NULL)
1946  *Quit = TRUE;
1947 
1950  break;
1951  }
1952  else if (Ir.Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
1953  {
1955  break;
1956  }
1957  else if (Ir.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESC */
1958  {
1959  if (Cancel != NULL)
1960  *Cancel = TRUE;
1961 
1964  break;
1965  }
1966  else if ((Ir.Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1967  (Ir.Event.KeyEvent.wVirtualKeyCode == VK_HOME)) /* HOME */
1968  {
1969  Pos = 0;
1970  CONSOLE_SetCursorXY(iLeft + Pos, iTop);
1971  }
1972  else if ((Ir.Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1973  (Ir.Event.KeyEvent.wVirtualKeyCode == VK_END)) /* END */
1974  {
1975  Pos = Length;
1976  CONSOLE_SetCursorXY(iLeft + Pos, iTop);
1977  }
1978  else if ((Ir.Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1979  (Ir.Event.KeyEvent.wVirtualKeyCode == VK_LEFT)) /* LEFT */
1980  {
1981  if (Pos > 0)
1982  {
1983  Pos--;
1984  CONSOLE_SetCursorXY(iLeft + Pos, iTop);
1985  }
1986  }
1987  else if ((Ir.Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1988  (Ir.Event.KeyEvent.wVirtualKeyCode == VK_RIGHT)) /* RIGHT */
1989  {
1990  if (Pos < Length)
1991  {
1992  Pos++;
1993  CONSOLE_SetCursorXY(iLeft + Pos, iTop);
1994  }
1995  }
1996  else if ((Ir.Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1997  (Ir.Event.KeyEvent.wVirtualKeyCode == VK_DELETE)) /* DEL */
1998  {
1999  if (Pos < Length)
2000  {
2002  &InputBuffer[Pos + 1],
2003  (Length - Pos - 1) * sizeof(WCHAR));
2005 
2006  Length--;
2007  CONSOLE_SetInputTextXY(iLeft,
2008  iTop,
2010  InputBuffer);
2011  CONSOLE_SetCursorXY(iLeft + Pos, iTop);
2012  }
2013  }
2014  else if (Ir.Event.KeyEvent.wVirtualKeyCode == VK_BACK) /* BACKSPACE */
2015  {
2016  if (Pos > 0)
2017  {
2018  if (Pos < Length)
2019  memmove(&InputBuffer[Pos - 1],
2020  &InputBuffer[Pos],
2021  (Length - Pos) * sizeof(WCHAR));
2023 
2024  Pos--;
2025  Length--;
2026  CONSOLE_SetInputTextXY(iLeft,
2027  iTop,
2029  InputBuffer);
2030  CONSOLE_SetCursorXY(iLeft + Pos, iTop);
2031  }
2032  }
2033  else if (Ir.Event.KeyEvent.uChar.AsciiChar != 0x00)
2034  {
2036  {
2037  ch = (WCHAR)Ir.Event.KeyEvent.uChar.AsciiChar;
2038 
2039  if ((ch >= L'0') && (ch <= L'9'))
2040  {
2041  if (Pos < Length)
2042  memmove(&InputBuffer[Pos + 1],
2043  &InputBuffer[Pos],
2044  (Length - Pos) * sizeof(WCHAR));
2046  InputBuffer[Pos] = ch;
2047 
2048  Pos++;
2049  Length++;
2050  CONSOLE_SetInputTextXY(iLeft,
2051  iTop,
2053  InputBuffer);
2054  CONSOLE_SetCursorXY(iLeft + Pos, iTop);
2055  }
2056  }
2057  }
2058  }
2059 }
2060 
2061 
2062 /*
2063  * Displays the CreatePrimaryPartitionPage.
2064  *
2065  * Next pages:
2066  * SelectPartitionPage
2067  * SelectFileSystemPage (default)
2068  * QuitPage
2069  *
2070  * RETURNS
2071  * Number of the next page.
2072  */
2073 static PAGE_NUMBER
2075 {
2076  PPARTENTRY PartEntry;
2077  PDISKENTRY DiskEntry;
2078  BOOLEAN Quit;
2079  BOOLEAN Cancel;
2080  ULONG MaxSize;
2081  ULONGLONG PartSize;
2083  WCHAR InputBuffer[50];
2084  CHAR LineBuffer[100];
2085 
2086  if (PartitionList == NULL || CurrentPartition == NULL)
2087  {
2088  /* FIXME: show an error dialog */
2089  return QUIT_PAGE;
2090  }
2091 
2092  PartEntry = CurrentPartition;
2093  DiskEntry = CurrentPartition->DiskEntry;
2094 
2096 
2098 
2099  DiskDescription(DiskEntry, LineBuffer, ARRAYSIZE(LineBuffer));
2101  LineBuffer);
2102 
2104 
2105 #if 0
2106  CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2107  CurrentPartition->SectorCount * DiskEntry->BytesPerSector / MB);
2108 #endif
2109 
2111 
2112  PartEntry = CurrentPartition;
2113  while (TRUE)
2114  {
2115  MaxSize = (PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector) / MB; /* in MBytes (rounded) */
2116 
2117  if (MaxSize > PARTITION_MAXSIZE)
2118  MaxSize = PARTITION_MAXSIZE;
2119 
2120  ShowPartitionSizeInputBox(12, 14, xScreen - 12, 17, /* left, top, right, bottom */
2121  MaxSize, InputBuffer, &Quit, &Cancel);
2122 
2123  if (Quit)
2124  {
2125  if (ConfirmQuit(Ir))
2126  return QUIT_PAGE;
2127 
2128  break;
2129  }
2130  else if (Cancel)
2131  {
2132  return SELECT_PARTITION_PAGE;
2133  }
2134  else
2135  {
2136  PartSize = _wcstoui64(InputBuffer, NULL, 10);
2137 
2138  if (PartSize < 1)
2139  {
2140  /* Too small */
2141  continue;
2142  }
2143 
2144  if (PartSize > MaxSize)
2145  {
2146  /* Too large */
2147  continue;
2148  }
2149 
2150  /* Convert to bytes */
2151  if (PartSize == MaxSize)
2152  {
2153  /* Use all of the unpartitioned disk space */
2154  SectorCount = PartEntry->SectorCount.QuadPart;
2155  }
2156  else
2157  {
2158  /* Calculate the sector count from the size in MB */
2159  SectorCount = PartSize * MB / DiskEntry->BytesPerSector;
2160 
2161  /* But never get larger than the unpartitioned disk space */
2162  if (SectorCount > PartEntry->SectorCount.QuadPart)
2163  SectorCount = PartEntry->SectorCount.QuadPart;
2164  }
2165 
2166  DPRINT ("Partition size: %I64u bytes\n", PartSize);
2167 
2170  SectorCount,
2171  FALSE);
2172 
2173  return SELECT_PARTITION_PAGE;
2174  }
2175  }
2176 
2178 }
2179 
2180 
2181 /*
2182  * Displays the CreateExtendedPartitionPage.
2183  *
2184  * Next pages:
2185  * SelectPartitionPage (default)
2186  * QuitPage
2187  *
2188  * RETURNS
2189  * Number of the next page.
2190  */
2191 static PAGE_NUMBER
2193 {
2194  PPARTENTRY PartEntry;
2195  PDISKENTRY DiskEntry;
2196  BOOLEAN Quit;
2197  BOOLEAN Cancel;
2198  ULONG MaxSize;
2199  ULONGLONG PartSize;
2201  WCHAR InputBuffer[50];
2202  CHAR LineBuffer[100];
2203 
2204  if (PartitionList == NULL || CurrentPartition == NULL)
2205  {
2206  /* FIXME: show an error dialog */
2207  return QUIT_PAGE;
2208  }
2209 
2210  PartEntry = CurrentPartition;
2211  DiskEntry = CurrentPartition->DiskEntry;
2212 
2214 
2216 
2217  DiskDescription(DiskEntry, LineBuffer, ARRAYSIZE(LineBuffer));
2219  LineBuffer);
2220 
2222 
2223 #if 0
2224  CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2225  CurrentPartition->SectorCount * DiskEntry->BytesPerSector / MB);
2226 #endif
2227 
2229 
2230  PartEntry = CurrentPartition;
2231  while (TRUE)
2232  {
2233  MaxSize = (PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector) / MB; /* in MBytes (rounded) */
2234 
2235  if (MaxSize > PARTITION_MAXSIZE)
2236  MaxSize = PARTITION_MAXSIZE;
2237 
2238  ShowPartitionSizeInputBox(12, 14, xScreen - 12, 17, /* left, top, right, bottom */
2239  MaxSize, InputBuffer, &Quit, &Cancel);
2240 
2241  if (Quit)
2242  {
2243  if (ConfirmQuit(Ir))
2244  return QUIT_PAGE;
2245 
2246  break;
2247  }
2248  else if (Cancel)
2249  {
2250  return SELECT_PARTITION_PAGE;
2251  }
2252  else
2253  {
2254  PartSize = _wcstoui64(InputBuffer, NULL, 10);
2255 
2256  if (PartSize < 1)
2257  {
2258  /* Too small */
2259  continue;
2260  }
2261 
2262  if (PartSize > MaxSize)
2263  {
2264  /* Too large */
2265  continue;
2266  }
2267 
2268  /* Convert to bytes */
2269  if (PartSize == MaxSize)
2270  {
2271  /* Use all of the unpartitioned disk space */
2272  SectorCount = PartEntry->SectorCount.QuadPart;
2273  }
2274  else
2275  {
2276  /* Calculate the sector count from the size in MB */
2277  SectorCount = PartSize * MB / DiskEntry->BytesPerSector;
2278 
2279  /* But never get larger than the unpartitioned disk space */
2280  if (SectorCount > PartEntry->SectorCount.QuadPart)
2281  SectorCount = PartEntry->SectorCount.QuadPart;
2282  }
2283 
2284  DPRINT ("Partition size: %I64u bytes\n", PartSize);
2285 
2288  SectorCount);
2289 
2290  return SELECT_PARTITION_PAGE;
2291  }
2292  }
2293 
2295 }
2296 
2297 
2298 /*
2299  * Displays the CreateLogicalPartitionPage.
2300  *
2301  * Next pages:
2302  * SelectFileSystemPage (default)
2303  * QuitPage
2304  *
2305  * RETURNS
2306  * Number of the next page.
2307  */
2308 static PAGE_NUMBER
2310 {
2311  PPARTENTRY PartEntry;
2312  PDISKENTRY DiskEntry;
2313  BOOLEAN Quit;
2314  BOOLEAN Cancel;
2315  ULONG MaxSize;
2316  ULONGLONG PartSize;
2318  WCHAR InputBuffer[50];
2319  CHAR LineBuffer[100];
2320 
2321  if (PartitionList == NULL || CurrentPartition == NULL)
2322  {
2323  /* FIXME: show an error dialog */
2324  return QUIT_PAGE;
2325  }
2326 
2327  PartEntry = CurrentPartition;
2328  DiskEntry = CurrentPartition->DiskEntry;
2329 
2331 
2333 
2334  DiskDescription(DiskEntry, LineBuffer, ARRAYSIZE(LineBuffer));
2336  LineBuffer);
2337 
2339 
2340 #if 0
2341  CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2342  CurrentPartition->SectorCount * DiskEntry->BytesPerSector / MB);
2343 #endif
2344 
2346 
2347  PartEntry = CurrentPartition;
2348  while (TRUE)
2349  {
2350  MaxSize = (PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector) / MB; /* in MBytes (rounded) */
2351 
2352  if (MaxSize > PARTITION_MAXSIZE)
2353  MaxSize = PARTITION_MAXSIZE;
2354 
2355  ShowPartitionSizeInputBox(12, 14, xScreen - 12, 17, /* left, top, right, bottom */
2356  MaxSize, InputBuffer, &Quit, &Cancel);
2357 
2358  if (Quit)
2359  {
2360  if (ConfirmQuit(Ir))
2361  return QUIT_PAGE;
2362 
2363  break;
2364  }
2365  else if (Cancel)
2366  {
2367  return SELECT_PARTITION_PAGE;
2368  }
2369  else
2370  {
2371  PartSize = _wcstoui64(InputBuffer, NULL, 10);
2372 
2373  if (PartSize < 1)
2374  {
2375  /* Too small */
2376  continue;
2377  }
2378 
2379  if (PartSize > MaxSize)
2380  {
2381  /* Too large */
2382  continue;
2383  }
2384 
2385  /* Convert to bytes */
2386  if (PartSize == MaxSize)
2387  {
2388  /* Use all of the unpartitioned disk space */
2389  SectorCount = PartEntry->SectorCount.QuadPart;
2390  }
2391  else
2392  {
2393  /* Calculate the sector count from the size in MB */
2394  SectorCount = PartSize * MB / DiskEntry->BytesPerSector;
2395 
2396  /* But never get larger than the unpartitioned disk space */
2397  if (SectorCount > PartEntry->SectorCount.QuadPart)
2398  SectorCount = PartEntry->SectorCount.QuadPart;
2399  }
2400 
2401  DPRINT("Partition size: %I64u bytes\n", PartSize);
2402 
2405  SectorCount,
2406  FALSE);
2407 
2408  return SELECT_PARTITION_PAGE;
2409  }
2410  }
2411 
2413 }
2414 
2415 
2416 /*
2417  * Displays the ConfirmDeleteSystemPartitionPage.
2418  *
2419  * Next pages:
2420  * DeletePartitionPage (default)
2421  * SelectPartitionPage
2422  *
2423  * RETURNS
2424  * Number of the next page.
2425  */
2426 static PAGE_NUMBER
2428 {
2430 
2431  while (TRUE)
2432  {
2433  CONSOLE_ConInKey(Ir);
2434 
2435  if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2436  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
2437  {
2438  if (ConfirmQuit(Ir))
2439  return QUIT_PAGE;
2440 
2441  break;
2442  }
2443  else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
2444  {
2445  return DELETE_PARTITION_PAGE;
2446  }
2447  else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESC */
2448  {
2449  return SELECT_PARTITION_PAGE;
2450  }
2451  }
2452 
2454 }
2455 
2456 
2457 /*
2458  * Displays the DeletePartitionPage.
2459  *
2460  * Next pages:
2461  * SelectPartitionPage (default)
2462  * QuitPage
2463  *
2464  * RETURNS
2465  * Number of the next page.
2466  */
2467 static PAGE_NUMBER
2469 {
2470  PPARTENTRY PartEntry;
2471  PDISKENTRY DiskEntry;
2472  CHAR LineBuffer[100];
2473 
2474  if (PartitionList == NULL || CurrentPartition == NULL)
2475  {
2476  /* FIXME: show an error dialog */
2477  return QUIT_PAGE;
2478  }
2479 
2480  PartEntry = CurrentPartition;
2481  DiskEntry = CurrentPartition->DiskEntry;
2482 
2484 
2485  PartitionDescription(PartEntry, LineBuffer, ARRAYSIZE(LineBuffer));
2486  CONSOLE_PrintTextXY(6, 10, " %s", LineBuffer);
2487 
2488  DiskDescription(DiskEntry, LineBuffer, ARRAYSIZE(LineBuffer));
2490  LineBuffer);
2491 
2492  while (TRUE)
2493  {
2494  CONSOLE_ConInKey(Ir);
2495 
2496  if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2497  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
2498  {
2499  if (ConfirmQuit(Ir))
2500  return QUIT_PAGE;
2501 
2502  break;
2503  }
2504  else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESC */
2505  {
2506  return SELECT_PARTITION_PAGE;
2507  }
2508  else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'L') /* L */
2509  {
2512  &CurrentPartition);
2513  return SELECT_PARTITION_PAGE;
2514  }
2515  }
2516 
2517  return DELETE_PARTITION_PAGE;
2518 }
2519 
2520 
2521 static VOID
2523 {
2524  if (!FileSystemList)
2525  return;
2526 
2528  FileSystemList = NULL;
2529 }
2530 
2531 /*
2532  * Displays the SelectFileSystemPage.
2533  *
2534  * Next pages:
2535  * CheckFileSystemPage (At once if RepairUpdate is selected)
2536  * CheckFileSystemPage (At once if Unattended and not USetupData.FormatPartition)
2537  * FormatPartitionPage (At once if Unattended and USetupData.FormatPartition)
2538  * SelectPartitionPage (If the user aborts)
2539  * FormatPartitionPage (Default)
2540  * QuitPage
2541  *
2542  * SIDEEFFECTS
2543  * Calls UpdatePartitionType()
2544  * Calls FindSupportedSystemPartition()
2545  *
2546  * RETURNS
2547  * Number of the next page.
2548  */
2549 static PAGE_NUMBER
2551 {
2552  PPARTENTRY PartEntry;
2553  PDISKENTRY DiskEntry;
2554  FORMATMACHINESTATE PreviousFormatState;
2555  PCWSTR DefaultFs;
2556  CHAR LineBuffer[100];
2557 
2558  DPRINT("SelectFileSystemPage()\n");
2559 
2560  if (PartitionList == NULL || InstallPartition == NULL)
2561  {
2562  /* FIXME: show an error dialog */
2563  return QUIT_PAGE;
2564  }
2565 
2566  /* Find or set the active system partition when starting formatting */
2567  if (FormatState == Start)
2568  {
2569  /*
2570  * If we install on a fixed disk, try to find a supported system
2571  * partition on the system. Otherwise if we install on a removable disk
2572  * use the install partition as the system partition.
2573  */
2574  if (InstallPartition->DiskEntry->MediaType == FixedMedia)
2575  {
2577  FALSE,
2580  /* Use the original system partition as the old active partition hint */
2581  PartEntry = PartitionList->SystemPartition;
2582 
2585  {
2586  DPRINT1("We are using a different system partition!!!!\n");
2587 
2589 
2590  {
2591  PPARTENTRY PartEntry; // Shadow variable
2592 
2593  PartEntry = PartitionList->SystemPartition;
2594  DiskEntry = PartEntry->DiskEntry;
2595 
2596  PartitionDescription(PartEntry, LineBuffer, ARRAYSIZE(LineBuffer));
2597  CONSOLE_SetTextXY(8, 10, LineBuffer);
2598 
2599  DiskDescription(DiskEntry, LineBuffer, ARRAYSIZE(LineBuffer));
2601  LineBuffer);
2602 
2603 
2604  PartEntry = SystemPartition;
2605  DiskEntry = PartEntry->DiskEntry;
2606 
2607  PartitionDescription(PartEntry, LineBuffer, ARRAYSIZE(LineBuffer));
2608  CONSOLE_SetTextXY(8, 23, LineBuffer);
2609  }
2610 
2611  while (TRUE)
2612  {
2613  CONSOLE_ConInKey(Ir);
2614 
2615  if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
2616  {
2617  break;
2618  }
2619  else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESC */
2620  {
2621  return SELECT_PARTITION_PAGE;
2622  }
2623  }
2624 
2626  CONSOLE_Flush();
2627  }
2628  }
2629  else // if (InstallPartition->DiskEntry->MediaType == RemovableMedia)
2630  {
2632  /* Don't specify any old active partition hint */
2633  PartEntry = NULL;
2634  }
2635 
2636  if (!SystemPartition)
2637  {
2638  /* FIXME: improve the error dialog */
2639  //
2640  // Error dialog should say that we cannot find a suitable
2641  // system partition and create one on the system. At this point,
2642  // it may be nice to ask the user whether he wants to continue,
2643  // or use an external drive as the system drive/partition
2644  // (e.g. floppy, USB drive, etc...)
2645  //
2646  PopupError("The ReactOS Setup could not find a supported system partition\n"
2647  "on your system or could not create a new one. Without such partition\n"
2648  "the Setup program cannot install ReactOS.\n"
2649  "Press ENTER to return to the partition selection list.",
2651  Ir, POPUP_WAIT_ENTER);
2652  return SELECT_PARTITION_PAGE;
2653  }
2654 
2655  /*
2656  * If the system partition can be created in some
2657  * non-partitioned space, create it now.
2658  */
2660  {
2663  0LL, // SystemPartition->SectorCount.QuadPart,
2664  TRUE);
2666  }
2667 
2668  /* Set it as such */
2670  {
2671  DPRINT1("SetActivePartition(0x%p) failed?!\n", SystemPartition);
2672  ASSERT(FALSE);
2673  }
2674 
2675  /* Commit all partition changes to all the disks */
2677  {
2678  DPRINT("WritePartitionsToDisk() failed\n");
2680  return QUIT_PAGE;
2681  }
2682 
2683  /*
2684  * In all cases, whether or not we are going to perform a formatting,
2685  * we must perform a filesystem check of both the system and the
2686  * installation partitions.
2687  */
2691 
2692  /*
2693  * In case we just repair an existing installation, or make
2694  * an unattended setup without formatting, just go to the
2695  * filesystem check step.
2696  */
2697  if (RepairUpdateFlag)
2698  return CHECK_FILE_SYSTEM_PAGE;
2699 
2700  if (IsUnattendedSetup && !USetupData.FormatPartition)
2701  return CHECK_FILE_SYSTEM_PAGE;
2702  }
2703 
2704  // ASSERT(SystemPartition->IsPartitioned);
2705 
2706  /* Reset the filesystem list for each partition that is to be formatted */
2708 
2709  PreviousFormatState = FormatState;
2710  switch (FormatState)
2711  {
2712  case Start:
2713  {
2714  /*
2715  * We start by formatting the system partition in case it is new
2716  * (it didn't exist before) and is not the same as the installation
2717  * partition. Otherwise we just require a filesystem check on it,
2718  * and start by formatting the installation partition instead.
2719  */
2720 
2722 
2723  if ((SystemPartition != InstallPartition) &&
2725  {
2728 
2729  // TODO: Should we let the user using a custom file-system,
2730  // or should we always use FAT(32) for it?
2731  // For "compatibility", FAT(32) would be best indeed.
2732 
2734  DPRINT1("FormatState: Start --> FormatSystemPartition\n");
2735  }
2736  else
2737  {
2740 
2742  {
2743  /* The system partition is separate, so it had better be formatted! */
2746 
2747  /* Require a filesystem check on the system partition too */
2749  }
2750 
2752  DPRINT1("FormatState: Start --> FormatInstallPartition\n");
2753  }
2754  break;
2755  }
2756 
2757  case FormatSystemPartition:
2758  {
2761 
2763  DPRINT1("FormatState: FormatSystemPartition --> FormatInstallPartition\n");
2764  break;
2765  }
2766 
2768  case FormatOtherPartition:
2769  {
2771  NULL,
2772  &TempPartition))
2773  {
2776 
2778  DPRINT1("FormatState: FormatInstallPartition --> FormatOtherPartition\n");
2779  else
2780  DPRINT1("FormatState: FormatOtherPartition --> FormatOtherPartition\n");
2781  }
2782  else
2783  {
2785 
2787  DPRINT1("FormatState: FormatInstallPartition --> FormatDone\n");
2788  else
2789  DPRINT1("FormatState: FormatOtherPartition --> FormatDone\n");
2790 
2791  return CHECK_FILE_SYSTEM_PAGE;
2792  }
2793  break;
2794  }
2795 
2796  case FormatDone:
2797  {
2798  DPRINT1("FormatState: FormatDone\n");
2799  return CHECK_FILE_SYSTEM_PAGE;
2800  }
2801 
2802  default:
2803  {
2804  DPRINT1("FormatState: Invalid value %ld\n", FormatState);
2805  ASSERT(FALSE);
2806  return QUIT_PAGE;
2807  }
2808  }
2809 
2810  PartEntry = TempPartition;
2811  DiskEntry = TempPartition->DiskEntry;
2812 
2813  ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0);
2814 
2816 
2817  if (PartEntry->AutoCreate)
2818  {
2820 
2821 #if 0
2822  PartitionDescription(PartEntry, LineBuffer, ARRAYSIZE(LineBuffer));
2823  CONSOLE_SetTextXY(8, 10, LineBuffer);
2824 #endif
2825 
2826  DiskDescription(DiskEntry, LineBuffer, ARRAYSIZE(LineBuffer));
2828  LineBuffer);
2829 
2831 
2832  PartEntry->AutoCreate = FALSE;
2833  }
2834  else if (PartEntry->New)
2835  {
2836  switch (FormatState)
2837  {
2838  case FormatSystemPartition:
2840  break;
2841 
2844  break;
2845 
2846  case FormatOtherPartition:
2848  break;
2849 
2850  default:
2851  ASSERT(FALSE);
2852  break;
2853  }
2854 
2855  DiskDescription(DiskEntry, LineBuffer, ARRAYSIZE(LineBuffer));
2857  LineBuffer);
2858 
2860  }
2861  else
2862  {
2864 
2865  PartitionDescription(PartEntry, LineBuffer, ARRAYSIZE(LineBuffer));
2866  CONSOLE_SetTextXY(8, 10, LineBuffer);
2867 
2868  DiskDescription(DiskEntry, LineBuffer, ARRAYSIZE(LineBuffer));
2870  LineBuffer);
2871  }
2872 
2874 
2875  if (IsUnattendedSetup)
2876  {
2877  ASSERT(USetupData.FormatPartition);
2878 
2879  switch (USetupData.FsType)
2880  {
2881  /* 1 is for BtrFS */
2882  case 1:
2883  DefaultFs = L"BTRFS";
2884  break;
2885 
2886  /* If we don't understand input, default to FAT */
2887  default:
2888  DefaultFs = L"FAT";
2889  break;
2890  }
2891  }
2892  else
2893  {
2894  /* By default select the "FAT" file system */
2895  DefaultFs = L"FAT";
2896  }
2897 
2898  /* Create the file system list */
2899  // TODO: Display only the FSes compatible with the selected partition!
2901  PartEntry->New ||
2902  PartEntry->FormatState == Unformatted,
2903  DefaultFs);
2904  if (FileSystemList == NULL)
2905  {
2906  /* FIXME: show an error dialog */
2907  return QUIT_PAGE;
2908  }
2909 
2910  if (IsUnattendedSetup)
2911  {
2912  ASSERT(USetupData.FormatPartition);
2913  return FORMAT_PARTITION_PAGE;
2914  }
2915 
2917 
2918  while (TRUE)
2919  {
2920  CONSOLE_ConInKey(Ir);
2921 
2922  if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2923  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
2924  {
2925  if (ConfirmQuit(Ir))
2926  {
2927  /* Reset the filesystem list */
2929  return QUIT_PAGE;
2930  }
2931 
2932  break;
2933  }
2934  else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESC */
2935  {
2936  /* Reset the formatter machine state */
2937  TempPartition = NULL;
2938  FormatState = Start;
2939 
2940  /* Reset the filesystem list */
2942 
2943  return SELECT_PARTITION_PAGE;
2944  }
2945  else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2946  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
2947  {
2949  }
2950  else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2951  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
2952  {
2954  }
2955  else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
2956  {
2958  {
2960 
2961  /*
2962  * Skip formatting this partition. We will also ignore
2963  * filesystem checks on it, unless it is either the system
2964  * or the installation partition.
2965  */
2966  if (TempPartition != SystemPartition &&
2968  {
2969  PartEntry->NeedsCheck = FALSE;
2970  }
2971 
2972  return SELECT_FILE_SYSTEM_PAGE;
2973  }
2974  else
2975  {
2976  /* Format this partition */
2977  return FORMAT_PARTITION_PAGE;
2978  }
2979  }
2980  }
2981 
2982  FormatState = PreviousFormatState;
2983 
2984  return SELECT_FILE_SYSTEM_PAGE;
2985 }
2986 
2987 
2988 /*
2989  * Displays the FormatPartitionPage.
2990  *
2991  * Next pages:
2992  * InstallDirectoryPage (At once if IsUnattendedSetup or InstallShortcut)
2993  * SelectPartitionPage (At once)
2994  * QuitPage
2995  *
2996  * SIDEEFFECTS
2997  * Sets InstallPartition->FormatState
2998  * Sets USetupData.DestinationRootPath
2999  *
3000  * RETURNS
3001  * Number of the next page.
3002  */
3003 static PAGE_NUMBER
3005 {
3006  NTSTATUS Status;
3007  PPARTENTRY PartEntry;
3008  PDISKENTRY DiskEntry;
3009  PFILE_SYSTEM_ITEM SelectedFileSystem;
3010  WCHAR PathBuffer[MAX_PATH];
3011  CHAR Buffer[MAX_PATH];
3012 
3013  DPRINT("FormatPartitionPage()\n");
3014 
3016 
3017  if (PartitionList == NULL || TempPartition == NULL)
3018  {
3019  /* FIXME: show an error dialog */
3020  return QUIT_PAGE;
3021  }
3022 
3023  PartEntry = TempPartition;
3024  DiskEntry = TempPartition->DiskEntry;
3025 
3026  ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0);
3027 
3028  SelectedFileSystem = FileSystemList->Selected;
3029  ASSERT(SelectedFileSystem && SelectedFileSystem->FileSystem);
3030 
3031  while (TRUE)
3032  {
3033  if (!IsUnattendedSetup)
3034  CONSOLE_ConInKey(Ir);
3035 
3036  if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3037  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
3038  {
3039  if (ConfirmQuit(Ir))
3040  {
3041  /* Reset the filesystem list */
3043  return QUIT_PAGE;
3044  }
3045 
3046  break;
3047  }
3048  else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN || IsUnattendedSetup) /* ENTER */
3049  {
3050  /*
3051  * Remove the "Press ENTER to continue" message prompt when the ENTER
3052  * key is pressed as the user wants to begin the partition formatting.
3053  */
3056 
3057  /* Format the partition */
3058  Status = DoFormat(PartEntry,
3059  SelectedFileSystem->FileSystem,
3060  SelectedFileSystem->QuickFormat);
3062  {
3064 
3065  /* Reset the filesystem list */
3067  return QUIT_PAGE;
3068  }
3069  else if (Status == STATUS_UNRECOGNIZED_VOLUME)
3070  {
3071  /* FIXME: show an error dialog */
3072  // MUIDisplayError(ERROR_FORMATTING_PARTITION, Ir, POPUP_WAIT_ANY_KEY, PathBuffer);
3073 
3074  /* Reset the filesystem list */
3076  return QUIT_PAGE;
3077  }
3078  else if (Status == STATUS_NOT_SUPPORTED)
3079  {
3081  sizeof(Buffer),
3082  "Setup is currently unable to format a partition in %S.\n"
3083  "\n"
3084  " \x07 Press ENTER to continue Setup.\n"
3085  " \x07 Press F3 to quit Setup.",
3086  SelectedFileSystem->FileSystem);
3087 
3091 
3092  while (TRUE)
3093  {
3094  CONSOLE_ConInKey(Ir);
3095 
3096  if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x00 &&
3097  Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3) /* F3 */
3098  {
3099  if (ConfirmQuit(Ir))
3100  {
3101  /* Reset the filesystem list */
3103  return QUIT_PAGE;
3104  }
3105  else
3106  {
3107  return SELECT_FILE_SYSTEM_PAGE;
3108  }
3109  }
3110  else if (Ir->Event.KeyEvent.uChar.AsciiChar == VK_RETURN) /* ENTER */
3111  {
3112  return SELECT_FILE_SYSTEM_PAGE;
3113  }
3114  }
3115  }
3116  else if (!NT_SUCCESS(Status))
3117  {
3119  RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
3120  L"\\Device\\Harddisk%lu\\Partition%lu",
3121  DiskEntry->DiskNumber,
3122  PartEntry->PartitionNumber);
3123 
3124  DPRINT1("FormatPartition() failed with status 0x%08lx\n", Status);
3126 
3127  /* Reset the filesystem list */
3129  return QUIT_PAGE;
3130  }
3131 
3132  return SELECT_FILE_SYSTEM_PAGE;
3133  }
3134  }
3135 
3136  return FORMAT_PARTITION_PAGE;
3137 }
3138 
3139 
3140 /*
3141  * Displays the CheckFileSystemPage.
3142  *
3143  * Next pages:
3144  * InstallDirectoryPage (At once)
3145  * QuitPage
3146  *
3147  * SIDEEFFECTS
3148  * Inits or reloads FileSystemList
3149  *
3150  * RETURNS
3151  * Number of the next page.
3152  */
3153 static PAGE_NUMBER
3155 {
3156  NTSTATUS Status;
3157  PPARTENTRY PartEntry;
3158  CHAR Buffer[MAX_PATH];
3159 
3161 
3162  if (PartitionList == NULL)
3163  {
3164  /* FIXME: show an error dialog */
3165  return QUIT_PAGE;
3166  }
3167 
3168  if (!GetNextUncheckedPartition(PartitionList, NULL, &PartEntry))
3169  {
3170  return INSTALL_DIRECTORY_PAGE;
3171  }
3172 
3173  ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0);
3174 
3175  DPRINT1("CheckFileSystemPage -- PartitionType: 0x%02X ; FileSystem: %S\n",
3176  PartEntry->PartitionType, (*PartEntry->FileSystem ? PartEntry->FileSystem : L"n/a"));
3177 
3178  /* Check the partition */
3179  Status = DoChkdsk(PartEntry);
3181  {
3182  /*
3183  * Partition checking is not supported with the current filesystem,
3184  * so disable FS checks on it.
3185  */
3186  PartEntry->NeedsCheck = FALSE;
3187 
3189  sizeof(Buffer),
3190  "Setup is currently unable to check a partition formatted in %S.\n"
3191  "\n"
3192  " \x07 Press ENTER to continue Setup.\n"
3193  " \x07 Press F3 to quit Setup.",
3194  PartEntry->FileSystem);
3195 
3199 
3200  while (TRUE)
3201  {
3202  CONSOLE_ConInKey(Ir);
3203 
3204  if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x00 &&
3205  Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3) /* F3 */
3206  {
3207  if (ConfirmQuit(Ir))
3208  return QUIT_PAGE;
3209  else
3210  return CHECK_FILE_SYSTEM_PAGE;
3211  }
3212  else if (Ir->Event.KeyEvent.uChar.AsciiChar == VK_RETURN) /* ENTER */
3213  {
3214  return CHECK_FILE_SYSTEM_PAGE;
3215  }
3216  }
3217  }
3218  else if (!NT_SUCCESS(Status))
3219  {
3220  DPRINT1("ChkdskPartition() failed with status 0x%08lx\n", Status);
3221 
3223  sizeof(Buffer),
3224  "ChkDsk detected some disk errors.\n(Status 0x%08lx).\n",
3225  Status);
3226 
3229  Ir, POPUP_WAIT_ENTER);
3230  }
3231 
3232  PartEntry->NeedsCheck = FALSE;
3233  return CHECK_FILE_SYSTEM_PAGE;
3234 }
3235 
3236 
3237 static BOOLEAN
3239  IN PCWSTR InstallDir)
3240 {
3241  UINT i, Length;
3242 
3243  Length = wcslen(InstallDir);
3244 
3245  // TODO: Add check for 8.3 too.
3246 
3247  /* Path must be at least 2 characters long */
3248 // if (Length < 2)
3249 // return FALSE;
3250 
3251  /* Path must start with a backslash */
3252 // if (InstallDir[0] != L'\\')
3253 // return FALSE;
3254 
3255  /* Path must not end with a backslash */
3256  if (InstallDir[Length - 1] == L'\\')
3257  return FALSE;
3258 
3259  /* Path must not contain whitespace characters */
3260  for (i = 0; i < Length; i++)
3261  {
3262  if (iswspace(InstallDir[i]))
3263  return FALSE;
3264  }
3265 
3266  /* Path component must not end with a dot */
3267  for (i = 0; i < Length; i++)
3268  {
3269  if (InstallDir[i] == L'\\' && i > 0)
3270  {
3271  if (InstallDir[i - 1] == L'.')
3272  return FALSE;
3273  }
3274  }
3275 
3276  if (InstallDir[Length - 1] == L'.')
3277  return FALSE;
3278 
3279  return TRUE;
3280 }
3281 
3282 
3283 /*
3284  * Displays the InstallDirectoryPage.
3285  *
3286  * Next pages:
3287  * PrepareCopyPage
3288  * QuitPage
3289  *
3290  * RETURNS
3291  * Number of the next page.
3292  */
3293 static PAGE_NUMBER
3295 {
3296  NTSTATUS Status;
3297  ULONG Length, Pos;
3298  WCHAR c;
3299  WCHAR InstallDir[MAX_PATH];
3300 
3301  /* We do not need the filesystem list anymore */
3303 
3304  if (PartitionList == NULL || InstallPartition == NULL)
3305  {
3306  /* FIXME: show an error dialog */
3307  return QUIT_PAGE;
3308  }
3309 
3310  // if (IsUnattendedSetup)
3311  if (RepairUpdateFlag)
3312  wcscpy(InstallDir, CurrentInstallation->PathComponent); // SystemNtPath
3313  else if (USetupData.InstallationDirectory[0])
3314  wcscpy(InstallDir, USetupData.InstallationDirectory);
3315  else
3316  wcscpy(InstallDir, L"\\ReactOS");
3317 
3318  /*
3319  * Check the validity of the predefined 'InstallDir'. If we are either
3320  * in unattended setup or in update/repair mode, and the installation path
3321  * is valid, just perform the installation. Otherwise (either in the case
3322  * of an invalid path, or we are in regular setup), display the UI and allow
3323  * the user to specify a new installation path.
3324  */
3325  if ((RepairUpdateFlag || IsUnattendedSetup) && IsValidPath(InstallDir))
3326  {
3328  if (!NT_SUCCESS(Status))
3329  {
3330  DPRINT1("InitDestinationPaths() failed. Status code: 0x%lx", Status);
3332  return QUIT_PAGE;
3333  }
3334 
3335  /*
3336  * Check whether the user attempts to install ReactOS within the
3337  * installation source directory, or in a subdirectory thereof.
3338  * If so, fail with an error.
3339  */
3340  if (RtlPrefixUnicodeString(&USetupData.SourcePath, &USetupData.DestinationPath, TRUE))
3341  {
3343  return INSTALL_DIRECTORY_PAGE;
3344  }
3345 
3346  return PREPARE_COPY_PAGE;
3347  }
3348 
3349  Length = wcslen(InstallDir);
3350  Pos = Length;
3351 
3353  CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
3354  CONSOLE_SetCursorXY(8 + Pos, 11);
3356 
3357  while (TRUE)
3358  {
3359  CONSOLE_ConInKey(Ir);
3360 
3361  if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3362  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
3363  {
3365 
3366  if (ConfirmQuit(Ir))
3367  return QUIT_PAGE;
3368 
3370  break;
3371  }
3372  else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3373  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DELETE)) /* DEL */
3374  {
3375  if (Pos < Length)
3376  {
3377  memmove(&InstallDir[Pos],
3378  &InstallDir[Pos + 1],
3379  (Length - Pos - 1) * sizeof(WCHAR));
3380  InstallDir[Length - 1] = UNICODE_NULL;
3381 
3382  Length--;
3383  CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
3384  CONSOLE_SetCursorXY(8 + Pos, 11);
3385  }
3386  }
3387  else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3388  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_HOME)) /* HOME */
3389  {
3390  Pos = 0;
3391  CONSOLE_SetCursorXY(8 + Pos, 11);
3392  }
3393  else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3394  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_END)) /* END */
3395  {
3396  Pos = Length;
3397  CONSOLE_SetCursorXY(8 + Pos, 11);
3398  }
3399  else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3400  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_LEFT)) /* LEFT */
3401  {
3402  if (Pos > 0)
3403  {
3404  Pos--;
3405  CONSOLE_SetCursorXY(8 + Pos, 11);
3406  }
3407  }
3408  else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3409  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RIGHT)) /* RIGHT */
3410  {
3411  if (Pos < Length)
3412  {
3413  Pos++;
3414  CONSOLE_SetCursorXY(8 + Pos, 11);
3415  }
3416  }
3417  else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
3418  {
3420 
3421  /*
3422  * Check for the validity of the installation directory and pop up
3423  * an error if it is not the case. Then the user can fix its input.
3424  */
3425  if (!IsValidPath(InstallDir))
3426  {
3428  return INSTALL_DIRECTORY_PAGE;
3429  }
3430 
3432  if (!NT_SUCCESS(Status))
3433  {
3434  DPRINT1("InitDestinationPaths() failed. Status code: 0x%lx", Status);
3436  return QUIT_PAGE;
3437  }
3438 
3439  /*
3440  * Check whether the user attempts to install ReactOS within the
3441  * installation source directory, or in a subdirectory thereof.
3442  * If so, fail with an error.
3443  */
3444  if (RtlPrefixUnicodeString(&USetupData.SourcePath, &USetupData.DestinationPath, TRUE))
3445  {
3447  return INSTALL_DIRECTORY_PAGE;
3448  }
3449 
3450  return PREPARE_COPY_PAGE;
3451  }
3452  else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x08) /* BACKSPACE */
3453  {
3454  if (Pos > 0)
3455  {
3456  if (Pos < Length)
3457  memmove(&InstallDir[Pos - 1],
3458  &InstallDir[Pos],
3459  (Length - Pos) * sizeof(WCHAR));
3460  InstallDir[Length - 1] = UNICODE_NULL;
3461 
3462  Pos--;
3463  Length--;
3464  CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
3465  CONSOLE_SetCursorXY(8 + Pos, 11);
3466  }
3467  }
3468  else if (isprint(Ir->Event.KeyEvent.uChar.AsciiChar))
3469  {
3470  if (Length < 50)
3471  {
3473  if (iswalpha(c) || iswdigit(c) || c == '.' || c == '\\' || c == '-' || c == '_')
3474  {
3475  if (Pos < Length)
3476  memmove(&InstallDir[Pos + 1],
3477  &InstallDir[Pos],
3478  (Length - Pos) * sizeof(WCHAR));
3479  InstallDir[Length + 1] = UNICODE_NULL;
3480  InstallDir[Pos] = c;
3481 
3482  Pos++;
3483  Length++;
3484  CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
3485  CONSOLE_SetCursorXY(8 + Pos, 11);
3486  }
3487  }
3488  }
3489  }
3490 
3491  return INSTALL_DIRECTORY_PAGE;
3492 }
3493 
3494 
3495 // PSETUP_ERROR_ROUTINE
3496 static VOID
3497 __cdecl
3499  IN PUSETUP_DATA pSetupData,
3500  ...)
3501 {
3502  INPUT_RECORD Ir;
3503  va_list arg_ptr;
3504 
3505  va_start(arg_ptr, pSetupData);
3506 
3507  if (pSetupData->LastErrorNumber >= ERROR_SUCCESS &&
3508  pSetupData->LastErrorNumber < ERROR_LAST_ERROR_CODE)
3509  {
3510  // Note: the "POPUP_WAIT_ENTER" actually depends on the LastErrorNumber...
3511  MUIDisplayErrorV(pSetupData->LastErrorNumber, &Ir, POPUP_WAIT_ENTER, arg_ptr);
3512  }
3513 
3514  va_end(arg_ptr);
3515 }
3516 
3517 /*
3518  * Displays the PrepareCopyPage.
3519  *
3520  * Next pages:
3521  * FileCopyPage(At once)
3522  * QuitPage
3523  *
3524  * SIDEEFFECTS
3525  * Calls PrepareFileCopy
3526  *
3527  * RETURNS
3528  * Number of the next page.
3529  */
3530 static PAGE_NUMBER
3532 {
3533  // ERROR_NUMBER ErrorNumber;
3534  BOOLEAN Success;
3535 
3537 
3538  /* ErrorNumber = */ Success = PrepareFileCopy(&USetupData, NULL);
3539  if (/*ErrorNumber != ERROR_SUCCESS*/ !Success)
3540  {
3541  // MUIDisplayError(ErrorNumber, Ir, POPUP_WAIT_ENTER);
3542  return QUIT_PAGE;
3543  }
3544 
3545  return FILE_COPY_PAGE;
3546 }
3547 
3548 typedef struct _COPYCONTEXT
3549 {
3555 
3556 static VOID
3558  IN BOOLEAN First)
3559 {
3561 
3562  /* Get the memory information from the system */
3564  &PerfInfo,
3565  sizeof(PerfInfo),
3566  NULL);
3567 
3568  /* Check if this is initial setup */
3569  if (First)
3570  {
3571  /* Set maximum limits to be total RAM pages */
3572  ProgressSetStepCount(CopyContext->MemoryBars[0], PerfInfo.CommitLimit);
3573  ProgressSetStepCount(CopyContext->MemoryBars[1], PerfInfo.CommitLimit);
3574  ProgressSetStepCount(CopyContext->MemoryBars[2], PerfInfo.CommitLimit);
3575  }
3576 
3577  /* Set current values */
3578  ProgressSetStep(CopyContext->MemoryBars[0], PerfInfo.PagedPoolPages + PerfInfo.NonPagedPoolPages);
3579  ProgressSetStep(CopyContext->MemoryBars[1], PerfInfo.ResidentSystemCachePage);
3580  ProgressSetStep(CopyContext->MemoryBars[2], PerfInfo.AvailablePages);
3581 }
3582 
3583 static UINT
3584 CALLBACK
3587  UINT_PTR Param1,
3588  UINT_PTR Param2)
3589 {
3590  PCOPYCONTEXT CopyContext = (PCOPYCONTEXT)Context;
3591  PFILEPATHS_W FilePathInfo;
3592  PCWSTR SrcFileName, DstFileName;
3593 
3594  switch (Notification)
3595  {
3597  {
3598  CopyContext->TotalOperations = (ULONG)Param2;
3599  CopyContext->CompletedOperations = 0;
3600  ProgressSetStepCount(CopyContext->ProgressBar,
3601  CopyContext->TotalOperations);
3602  SetupUpdateMemoryInfo(CopyContext, TRUE);
3603  break;
3604  }
3605 
3609  {
3610  FilePathInfo = (PFILEPATHS_W)Param1;
3611 
3613  {
3614  /* Display delete message */
3615  ASSERT(Param2 == FILEOP_DELETE);
3616 
3617  DstFileName = wcsrchr(FilePathInfo->Target, L'\\');
3618  if (DstFileName) ++DstFileName;
3619  else DstFileName = FilePathInfo->Target;
3620 
3622  DstFileName);
3623  }
3625  {
3626  /* Display move/rename message */
3627  ASSERT(Param2 == FILEOP_RENAME);
3628 
3629  SrcFileName = wcsrchr(FilePathInfo->Source, L'\\');
3630  if (SrcFileName) ++SrcFileName;
3631  else SrcFileName = FilePathInfo->Source;
3632 
3633  DstFileName = wcsrchr(FilePathInfo->Target, L'\\');
3634  if (DstFileName) ++DstFileName;
3635  else DstFileName = FilePathInfo->Target;
3636 
3637  if (!wcsicmp(SrcFileName, DstFileName))
3638  Param2 = STRING_MOVING;
3639  else
3640  Param2 = STRING_RENAMING;
3641 
3643  SrcFileName, DstFileName);
3644  }
3646  {
3647  /* Display copy message */
3648  ASSERT(Param2 == FILEOP_COPY);
3649 
3650  /* NOTE: When extracting from CABs the Source is the CAB name */
3651  DstFileName = wcsrchr(FilePathInfo->Target, L'\\');
3652  if (DstFileName) ++DstFileName;
3653  else DstFileName = FilePathInfo->Target;
3654 
3656  DstFileName);
3657 #ifdef __REACTOS__ /* HACK */
3658  DoWatchDestFileName(DstFileName);
3659 #endif
3660  }
3661 
3662  SetupUpdateMemoryInfo(CopyContext, FALSE);
3663  break;
3664  }
3665 
3667  {
3668  FilePathInfo = (PFILEPATHS_W)Param1;
3669 
3670  DPRINT1("An error happened while trying to copy file '%S' (error 0x%08lx), skipping it...\n",
3671  FilePathInfo->Target, FilePathInfo->Win32Error);
3672  return FILEOP_SKIP;
3673  }
3674 
3677  case SPFILENOTIFY_ENDCOPY:
3678  {
3679  CopyContext->CompletedOperations++;
3680 
3681  /* SYSREG checkpoint */
3682  if (CopyContext->TotalOperations >> 1 == CopyContext->CompletedOperations)
3683  DPRINT1("CHECKPOINT:HALF_COPIED\n");
3684 
3685  ProgressNextStep(CopyContext->ProgressBar);
3686  SetupUpdateMemoryInfo(CopyContext, FALSE);
3687  break;
3688  }
3689  }
3690 
3691  return FILEOP_DOIT;
3692 }
3693 
3694 
3695 /*
3696  * Displays the FileCopyPage.
3697  *
3698  * Next pages:
3699  * RegistryPage(At once)
3700  *
3701  * SIDEEFFECTS
3702  * Calls DoFileCopy
3703  *
3704  * RETURNS
3705  * Number of the next page.
3706  */
3707 static PAGE_NUMBER
3709 {
3710  COPYCONTEXT CopyContext;
3711  UINT MemBarWidth;
3712 
3714 
3715  /* Create context for the copy process */
3716  CopyContext.TotalOperations = 0;
3717  CopyContext.CompletedOperations = 0;
3718 
3719  /* Create the progress bar as well */
3720  CopyContext.ProgressBar = CreateProgressBar(13,
3721  26,
3722  xScreen - 13,
3723  yScreen - 20,
3724  10,
3725  24,
3726  TRUE,
3728 
3729  // fit memory bars to screen width, distribute them uniform
3730  MemBarWidth = (xScreen - 26) / 5;
3731  MemBarWidth -= MemBarWidth % 2; // make even
3732  /* ATTENTION: The following progress bars are debug stuff, which should not be translated!! */
3733  /* Create the paged pool progress bar */
3734  CopyContext.MemoryBars[0] = CreateProgressBar(13,
3735  40,
3736  13 + MemBarWidth,
3737  43,
3738  13,
3739  44,
3740  FALSE,
3741  "Kernel Pool");
3742 
3743  /* Create the non paged pool progress bar */
3744  CopyContext.MemoryBars[1] = CreateProgressBar((xScreen / 2)- (MemBarWidth / 2),
3745  40,
3746  (xScreen / 2) + (MemBarWidth / 2),
3747  43,
3748  (xScreen / 2)- (MemBarWidth / 2),
3749  44,
3750  FALSE,
3751  "Kernel Cache");
3752 
3753  /* Create the global memory progress bar */
3754  CopyContext.MemoryBars[2] = CreateProgressBar(xScreen - 13 - MemBarWidth,
3755  40,
3756  xScreen - 13,
3757  43,
3758  xScreen - 13 - MemBarWidth,
3759  44,
3760  FALSE,
3761  "Free Memory");
3762 
3763  /* Do the file copying */
3764  DoFileCopy(&USetupData, FileCopyCallback, &CopyContext);
3765 
3766  /* If we get here, we're done, so cleanup the progress bar */
3767  DestroyProgressBar(CopyContext.ProgressBar);
3768  DestroyProgressBar(CopyContext.MemoryBars[0]);
3769  DestroyProgressBar(CopyContext.MemoryBars[1]);
3770  DestroyProgressBar(CopyContext.MemoryBars[2]);
3771 
3772  /* Create the $winnt$.inf file */
3774 
3775  /* Go display the next page */
3776  return REGISTRY_PAGE;
3777 }
3778 
3779 
3780 static VOID
3781 __cdecl
3783 {
3784  /* WARNING: Please keep this lookup table in sync with the resources! */
3785  static const UINT StringIDs[] =
3786  {
3787  STRING_DONE, /* Success */
3788  STRING_REGHIVEUPDATE, /* RegHiveUpdate */
3789  STRING_IMPORTFILE, /* ImportRegHive */
3790  STRING_DISPLAYSETTINGSUPDATE, /* DisplaySettingsUpdate */
3791  STRING_LOCALESETTINGSUPDATE, /* LocaleSettingsUpdate */
3792  STRING_ADDKBLAYOUTS, /* KeybLayouts */
3793  STRING_KEYBOARDSETTINGSUPDATE, /* KeybSettingsUpdate */
3794  STRING_CODEPAGEINFOUPDATE, /* CodePageInfoUpdate */
3795  };
3796 
3797  va_list args;
3798 
3799  if (RegStatus < ARRAYSIZE(StringIDs))
3800  {
3801  va_start(args, RegStatus);
3802  CONSOLE_SetStatusTextV(MUIGetString(StringIDs[RegStatus]), args);
3803  va_end(args);
3804  }
3805  else
3806  {
3807  CONSOLE_SetStatusText("Unknown status %d", RegStatus);
3808  }
3809 }
3810 
3811 /*
3812  * Displays the RegistryPage.
3813  *
3814  * Next pages:
3815  * SuccessPage (if RepairUpdate)
3816  * BootLoaderPage (default)
3817  * QuitPage
3818  *
3819  * SIDEEFFECTS
3820  * Calls UpdateRegistry
3821  *
3822  * RETURNS
3823  * Number of the next page.
3824  */
3825 static PAGE_NUMBER
3827 {
3828  ULONG Error;
3829 
3831 
3834  PartitionList,
3838  &s_SubstSettings);
3839  if (Error != ERROR_SUCCESS)
3840  {
3842  return QUIT_PAGE;
3843  }
3844  else
3845  {
3847  return BOOT_LOADER_PAGE;
3848  }
3849 }
3850 
3851 
3852 /*
3853  * Displays the BootLoaderPage.
3854  *
3855  * Next pages:
3856  * SuccessPage (if RepairUpdate)
3857  * BootLoaderHarddiskMbrPage
3858  * BootLoaderHarddiskVbrPage
3859  * BootLoaderFloppyPage
3860  * SuccessPage
3861  * QuitPage
3862  *
3863  * SIDEEFFECTS
3864  * Calls RegInitializeRegistry
3865  * Calls ImportRegistryFile
3866  * Calls SetDefaultPagefile
3867  * Calls SetMountedDeviceValues
3868  *
3869  * RETURNS
3870  * Number of the next page.
3871  */
3872 static PAGE_NUMBER
3874 {
3875  USHORT Line = 12;
3876  WCHAR PathBuffer[MAX_PATH];
3877 
3879 
3880  /* We must have a supported system partition by now */
3882 
3883  RtlFreeUnicodeString(&USetupData.SystemRootPath);
3884  RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
3885  L"\\Device\\Harddisk%lu\\Partition%lu\\",
3886  SystemPartition->DiskEntry->DiskNumber,
3888  RtlCreateUnicodeString(&USetupData.SystemRootPath, PathBuffer);
3889  DPRINT1("SystemRootPath: %wZ\n", &USetupData.SystemRootPath);
3890 
3891  /* For unattended setup, skip MBR installation or install on floppy if needed */
3892  if (IsUnattendedSetup)
3893  {
3894  if ((USetupData.MBRInstallType == 0) ||
3895  (USetupData.MBRInstallType == 1))
3896  {
3897  goto Quit;
3898  }
3899  }
3900 
3901  /*
3902  * We may install an MBR or VBR, but before that, check whether
3903  * we need to actually install the VBR on floppy/removable media
3904  * if the system partition is not recognized.
3905  */
3906  if ((SystemPartition->DiskEntry->DiskStyle != PARTITION_STYLE_MBR) ||
3908  {
3909  USetupData.MBRInstallType = 1;
3910  goto Quit;
3911  }
3912 
3913  /* Is it an unattended install on hdd? */
3914  if (IsUnattendedSetup)
3915  {
3916  if ((USetupData.MBRInstallType == 2) ||
3917  (USetupData.MBRInstallType == 3))
3918  {
3919  goto Quit;
3920  }
3921  }
3922 
3924  CONSOLE_InvertTextXY(8, Line, 60, 1);
3925 
3926  while (TRUE)
3927  {
3928  CONSOLE_ConInKey(Ir);
3929 
3930  if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3931  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
3932  {
3933  CONSOLE_NormalTextXY(8, Line, 60, 1);
3934 
3935  Line++;
3936  if (Line < 12)
3937  Line = 15;
3938 
3939  if (Line > 15)
3940  Line = 12;
3941 
3942  CONSOLE_InvertTextXY(8, Line, 60, 1);
3943  }
3944  else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3945  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
3946  {
3947  CONSOLE_NormalTextXY(8, Line, 60, 1);
3948 
3949  Line--;
3950  if (Line < 12)
3951  Line = 15;
3952 
3953  if (Line > 15)
3954  Line = 12;
3955 
3956  CONSOLE_InvertTextXY(8, Line, 60, 1);
3957  }
3958  else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3959  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_HOME)) /* HOME */
3960  {
3961  CONSOLE_NormalTextXY(8, Line, 60, 1);
3962 
3963  Line = 12;
3964 
3965  CONSOLE_InvertTextXY(8, Line, 60, 1);
3966  }
3967  else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3968  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_END)) /* END */
3969  {
3970  CONSOLE_NormalTextXY(8, Line, 60, 1);
3971 
3972  Line = 15;
3973 
3974  CONSOLE_InvertTextXY(8, Line, 60, 1);
3975  }
3976  else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3977  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
3978  {
3979  if (ConfirmQuit(Ir))
3980  return QUIT_PAGE;
3981 
3982  break;
3983  }
3984  else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
3985  {
3986  if (Line == 12)
3987  {
3988  /* Install on both MBR and VBR */
3989  USetupData.MBRInstallType = 2;
3990  break;
3991  }
3992  else if (Line == 13)
3993  {
3994  /* Install on VBR only */
3995  USetupData.MBRInstallType = 3;
3996  break;
3997  }
3998  else if (Line == 14)
3999  {
4000  /* Install on floppy */
4001  USetupData.MBRInstallType = 1;
4002  break;
4003  }
4004  else if (Line == 15)
4005  {
4006  /* Skip MBR installation */
4007  USetupData.MBRInstallType = 0;
4008  break;
4009  }
4010 
4011  return BOOT_LOADER_PAGE;
4012  }
4013  }
4014 
4015 Quit:
4016  switch (USetupData.MBRInstallType)
4017  {
4018  /* Skip MBR installation */
4019  case 0:
4020  return SUCCESS_PAGE;
4021 
4022  /* Install on floppy */
4023  case 1:
4024  return BOOT_LOADER_FLOPPY_PAGE;
4025 
4026  /* Install on both MBR and VBR or VBR only */
4027  case 2:
4028  case 3:
4030  }
4031 
4032  return BOOT_LOADER_PAGE;
4033 }
4034 
4035 
4036 /*
4037  * Displays the BootLoaderFloppyPage.
4038  *
4039  * Next pages:
4040  * SuccessPage (At once)
4041  * QuitPage
4042  *
4043  * SIDEEFFECTS
4044  * Calls InstallFatBootcodeToFloppy()
4045  *
4046  * RETURNS
4047  * Number of the next page.
4048  */
4049 static PAGE_NUMBER
4051 {
4052  NTSTATUS Status;
4053 
4055 
4056 // CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
4057 
4058  while (TRUE)
4059  {
4060  CONSOLE_ConInKey(Ir);
4061 
4062  if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
4063  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
4064  {
4065  if (ConfirmQuit(Ir))
4066  return QUIT_PAGE;
4067 
4068  break;
4069  }
4070  else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
4071  {
4072  Status = InstallFatBootcodeToFloppy(&USetupData.SourceRootPath,
4073  &USetupData.DestinationArcPath);
4074  if (!NT_SUCCESS(Status))
4075  {
4078 
4079  /* TODO: Print error message */
4080  return BOOT_LOADER_FLOPPY_PAGE;
4081  }
4082 
4083  return SUCCESS_PAGE;
4084  }
4085  }
4086 
4087  return BOOT_LOADER_FLOPPY_PAGE;
4088 }
4089 
4090 
4091 /*
4092  * Displays the BootLoaderInstallationPage.
4093  *
4094  * Next pages:
4095  * SuccessPage (At once)
4096  * QuitPage
4097  *
4098  * SIDEEFFECTS
4099  * Calls InstallVBRToPartition() if VBR installation is chosen.
4100  * Otherwise both InstallVBRToPartition() and InstallMbrBootCodeToDisk()
4101  * are called if both MBR and VBR installation is chosen.
4102  *
4103  * RETURNS
4104  * Number of the next page.
4105  */
4106 static PAGE_NUMBER
4108 {
4109  NTSTATUS Status;
4110  WCHAR DestinationDevicePathBuffer[MAX_PATH];
4111 
4113 
4114  if (USetupData.MBRInstallType == 2)
4115  {
4116  /* Step 1: Write the VBR */
4117  Status = InstallVBRToPartition(&USetupData.SystemRootPath,
4118  &USetupData.SourceRootPath,
4119  &USetupData.DestinationArcPath,
4121  if (!NT_SUCCESS(Status))
4122  {
4125  return QUIT_PAGE;
4126  }
4127 
4128  /* Step 2: Write the MBR if the disk containing the system partition is not a super-floppy */
4130  {
4131  RtlStringCchPrintfW(DestinationDevicePathBuffer, ARRAYSIZE(DestinationDevicePathBuffer),
4132  L"\\Device\\Harddisk%d\\Partition0",
4133  SystemPartition->DiskEntry->DiskNumber);
4134  Status = InstallMbrBootCodeToDisk(&USetupData.SystemRootPath,
4135  &USetupData.SourceRootPath,
4136  DestinationDevicePathBuffer);
4137  if (!NT_SUCCESS(Status))
4138  {
4139  DPRINT1("InstallMbrBootCodeToDisk() failed (Status %lx)\n", Status);
4141  return QUIT_PAGE;
4142  }
4143  }
4144  }
4145  else
4146  {
4147  Status = InstallVBRToPartition(&USetupData.SystemRootPath,
4148  &USetupData.SourceRootPath,
4149  &USetupData.DestinationArcPath,
4151  if (!NT_SUCCESS(Status))
4152  {
4155  return QUIT_PAGE;
4156  }
4157  }
4158 
4159  return SUCCESS_PAGE;
4160 }
4161 
4162 
4185 static
4186 BOOLEAN NTAPI
4190  OUT PSTR Buffer,
4192 {
4193  ULONG OldProgress = Bar->Progress;
4194 
4195  if (Bar->StepCount == 0)
4196  {
4197  Bar->Progress = 0;
4198  }
4199  else
4200  {
4201  Bar->Progress = Bar->StepCount - Bar->CurrentStep;
4202  }
4203 
4204  /* Build the progress string if it has changed */
4205  if (Bar->ProgressFormatText &&
4206  (AlwaysUpdate || (Bar->Progress != OldProgress)))
4207  {
4209  Bar->ProgressFormatText, Bar->Progress / max(1, Bar->Width) + 1);
4210 
4211  return TRUE;
4212  }
4213 
4214  return FALSE;
4215 }
4216 
4233 static VOID
4235  IN PINPUT_RECORD Ir,
4236  IN LONG TimeOut)
4237 {
4238  NTSTATUS Status;
4239  ULONG StartTime, BarWidth, TimerDiv;
4240  LONG TimeElapsed;
4241  LONG TimerValue, OldTimerValue;
4243  PPROGRESSBAR ProgressBar;
4244  BOOLEAN RefreshProgress = TRUE;
4245 
4246  /* Bail out if the timeout is already zero */
4247  if (TimeOut <= 0)
4248  return;
4249 
4250  /* Create the timeout progress bar and set it up */
4251  ProgressBar = CreateProgressBarEx(13,
4252  26,
4253  xScreen - 13,
4254  yScreen - 20,
4255  10,
4256  24,
4257  TRUE,
4259  0,
4260  NULL,
4263 
4264  BarWidth = max(1, ProgressBar->Width);
4265  TimerValue = TimeOut * BarWidth;
4266  ProgressSetStepCount(ProgressBar, TimerValue);
4267 
4269  CONSOLE_Flush();
4270 
4271  TimerDiv = 1000 / BarWidth;
4272  TimerDiv = max(1, TimerDiv);
4273  OldTimerValue = TimerValue;
4274  while (TRUE)
4275  {
4276  /* Decrease the timer */
4277 
4278  /*
4279  * Compute how much time the previous operations took.
4280  * This allows us in particular to take account for any time
4281  * elapsed if something slowed down.
4282  */
4283  TimeElapsed = NtGetTickCount() - StartTime;
4284  if (TimeElapsed >= TimerDiv)
4285  {
4286  /* Increase StartTime by steps of 1 / ProgressBar->Width seconds */
4287  TimeElapsed /= TimerDiv;
4288  StartTime += (TimerDiv * TimeElapsed);
4289 
4290  if (TimeElapsed <= TimerValue)
4291  TimerValue -= TimeElapsed;
4292  else
4293  TimerValue = 0;
4294 
4295  RefreshProgress = TRUE;
4296  }
4297 
4298  if (RefreshProgress)
4299  {
4300  ProgressSetStep(ProgressBar, OldTimerValue - TimerValue);
4301  RefreshProgress = FALSE;
4302  }
4303 
4304  /* Stop when the timer reaches zero */
4305  if (TimerValue <= 0)
4306  break;
4307 
4308  /* Check for user key presses */
4309 
4310  /*
4311  * If the timer is used, use a passive wait of maximum 1 second
4312  * while monitoring for incoming console input events, so that
4313  * we are still able to display the timing count.
4314  */
4315 
4316  /* Wait a maximum of 1 second for input events */
4317  TimeElapsed = NtGetTickCount() - StartTime;
4318  if (TimeElapsed < TimerDiv)
4319  {
4320  /* Convert the time to NT format */
4321  Timeout.QuadPart = (TimerDiv - TimeElapsed) * -10000LL;
4323  }
4324  else
4325  {
4327  }
4328 
4329  /* Check whether the input event has been signaled, or a timeout happened */
4330  if (Status == STATUS_TIMEOUT)
4331  {
4332  continue;
4333  }
4334  if (Status != STATUS_WAIT_0)
4335  {
4336  /* An error happened, bail out */
4337  DPRINT1("NtWaitForSingleObject() failed, Status 0x%08lx\n", Status);
4338  break;
4339  }
4340 
4341  /* Check for an ENTER key press */
4342  while (CONSOLE_ConInKeyPeek(Ir))
4343  {
4344  if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
4345  {
4346  /* Found it, stop waiting */
4347  goto Exit;
4348  }
4349  }
4350  }
4351 
4352 Exit:
4353  /* Destroy the progress bar and quit */
4354  DestroyProgressBar(ProgressBar);
4355 }
4356 
4357 
4358 /*
4359  * Displays the QuitPage.
4360  *
4361  * Next pages:
4362  * FlushPage (At once)
4363  *
4364  * SIDEEFFECTS
4365  * Destroy the Lists
4366  *
4367  * RETURNS
4368  * Number of the next page.
4369  */
4370 static PAGE_NUMBER
4372 {
4374 
4375  /* Destroy the NTOS installations list */
4376  if (NtOsInstallsList != NULL)
4377  {
4380  }
4381 
4382  /* Destroy the partition list */
4383  if (PartitionList != NULL)
4384  {
4386  PartitionList = NULL;
4387  }
4388 
4389  /* Reset the formatter machine state */
4390  TempPartition = NULL;
4391  FormatState = Start;
4392 
4393  /* Destroy the filesystem list */
4395 
4397 
4398  /* Wait for maximum 15 seconds or an ENTER key before quitting */
4399  ProgressCountdown(Ir, 15);
4400  return FLUSH_PAGE;
4401 }
4402 
4403 
4404 /*
4405  * Displays the SuccessPage.
4406  *
4407  * Next pages:
4408  * FlushPage (At once)
4409  *
4410  * SIDEEFFECTS
4411  * Destroy the Lists
4412  *
4413  * RETURNS
4414  * Number of the next page.
4415  */
4416 static PAGE_NUMBER
4418 {
4420 
4421  if (IsUnattendedSetup)
4422  return FLUSH_PAGE;
4423 
4424  /* Wait for maximum 15 seconds or an ENTER key before quitting */
4425  ProgressCountdown(Ir, 15);
4426  return FLUSH_PAGE;
4427 }
4428 
4429 
4430 /*
4431  * Displays the FlushPage.
4432  *
4433  * Next pages:
4434  * RebootPage (At once)
4435  *
4436  * RETURNS
4437  * Number of the next page.
4438  */
4439 static PAGE_NUMBER
4441 {
4443  return REBOOT_PAGE;
4444 }
4445 
4446 
4447 /*
4448  * The start routine and page management
4449  */
4450 NTSTATUS
4452 {
4453  NTSTATUS Status;
4454  INPUT_RECORD Ir;
4455  PAGE_NUMBER Page;
4456  BOOLEAN Old;
4457 
4459 
4460  /* Tell the Cm this is a setup boot, and it has to behave accordingly */
4462  if (!NT_SUCCESS(Status))
4463  DPRINT1("NtInitializeRegistry() failed (Status 0x%08lx)\n", Status);
4464 
4465  /* Initialize the user-mode PnP manager */
4467  if (!NT_SUCCESS(Status))
4468  {
4469  // PrintString(??);
4470  DPRINT1("The user-mode PnP manager could not initialize (Status 0x%08lx), expect unavailable devices!\n", Status);
4471  }
4472 
4473  if (!CONSOLE_Init())
4474  {
4478 
4479  /* We failed to initialize the video, just quit the installer */
4480  return STATUS_APP_INIT_FAILURE;
4481  }
4482 
4483  /* Initialize Setup, phase 0 */
4485  USetupData.ErrorRoutine = USetupErrorRoutine;
4486 
4487  /* Hide the cursor and clear the screen and keyboard buffer */
4490  CONSOLE_Flush();
4491 
4492  /* Global Initialization page */
4493  Page = SetupStartPage(&Ir);
4494 
4495  while (Page != REBOOT_PAGE && Page != RECOVERY_PAGE)
4496  {
4498  CONSOLE_Flush();
4499 
4500  // CONSOLE_SetUnderlinedTextXY(4, 3, " ReactOS " KERNEL_VERSION_STR " Setup ");
4501 
4502  switch (Page)
4503  {
4504  /* Language page */
4505  case LANGUAGE_PAGE:
4506  Page = LanguagePage(&Ir);
4507  break;
4508 
4509  /* Welcome page */
4510  case WELCOME_PAGE:
4511  Page = WelcomePage(&Ir);
4512  break;
4513 
4514  /* License page */
4515  case LICENSE_PAGE:
4516  Page = LicensePage(&Ir);
4517  break;
4518 
4519  /* Install pages */
4520  case INSTALL_INTRO_PAGE:
4521  Page = InstallIntroPage(&Ir);
4522  break;
4523 
4524 #if 0
4525  case SCSI_CONTROLLER_PAGE:
4526  Page = ScsiControllerPage(&Ir);
4527  break;
4528 
4529  case OEM_DRIVER_PAGE:
4530  Page = OemDriverPage(&Ir);
4531  break;
4532 #endif
4533 
4534  case DEVICE_SETTINGS_PAGE:
4535  Page = DeviceSettingsPage(&Ir);
4536  break;
4537 
4539  Page = ComputerSettingsPage(&Ir);
4540  break;
4541 
4542  case DISPLAY_SETTINGS_PAGE:
4543  Page = DisplaySettingsPage(&Ir);
4544  break;
4545 
4547  Page = KeyboardSettingsPage(&Ir);
4548  break;
4549 
4550  case LAYOUT_SETTINGS_PAGE:
4551  Page = LayoutSettingsPage(&Ir);
4552  break;
4553 
4554  /* Partitioning pages */
4555  case SELECT_PARTITION_PAGE:
4556  Page = SelectPartitionPage(&Ir);
4557  break;
4558 
4561  break;
4562 
4565  break;
4566 
4569  break;
4570 
4573  break;
4574 
4575  case DELETE_PARTITION_PAGE:
4576  Page = DeletePartitionPage(&Ir);
4577  break;
4578 
4579  /* Filesystem partition operations pages */
4581  Page = SelectFileSystemPage(&Ir);
4582  break;
4583 
4584  case FORMAT_PARTITION_PAGE:
4585  Page = FormatPartitionPage(&Ir);
4586  break;
4587 
4589  Page = CheckFileSystemPage(&Ir);
4590  break;
4591 
4592  /* Installation pages */
4594  Page = InstallDirectoryPage(&Ir);
4595  break;
4596 
4597  case PREPARE_COPY_PAGE:
4598  Page = PrepareCopyPage(&Ir);
4599  break;
4600 
4601  case FILE_COPY_PAGE:
4602  Page = FileCopyPage(&Ir);
4603  break;
4604 
4605  case REGISTRY_PAGE:
4606  Page = RegistryPage(&Ir);
4607  break;
4608 
4609  /* Bootloader installation pages */
4610  case BOOT_LOADER_PAGE:
4611  Page = BootLoaderPage(&Ir);
4612  break;
4613 
4615  Page = BootLoaderFloppyPage(&Ir);
4616  break;
4617 
4620  break;
4621 
4622  /* Repair pages */
4623  case REPAIR_INTRO_PAGE:
4624  Page = RepairIntroPage(&Ir);
4625  break;
4626 
4627  case UPGRADE_REPAIR_PAGE:
4628  Page = UpgradeRepairPage(&Ir);
4629  break;
4630 
4631  case SUCCESS_PAGE:
4632  Page = SuccessPage(&Ir);
4633  break;
4634 
4635  case FLUSH_PAGE:
4636  Page = FlushPage(&Ir);
4637  break;
4638 
4639  case QUIT_PAGE:
4640  Page = QuitPage(&Ir);
4641  break;
4642 
4643  /* Virtual pages */
4644  case SETUP_INIT_PAGE:
4645  case REBOOT_PAGE:
4646  case RECOVERY_PAGE:
4647  break;
4648 
4649  default:
4650  break;
4651  }
4652  }
4653 
4654  /* Terminate the user-mode PnP manager */
4656 
4657  /* Setup has finished */
4659 
4660  if (Page == RECOVERY_PAGE)
4661  RecoveryConsole();
4662 
4663  FreeConsole();
4664 
4665  /* Reboot */
4669 
4670  return STATUS_SUCCESS;
4671 }
4672 
4673 
4674 VOID NTAPI
4676 {
4677  NTSTATUS Status;
4679 
4681 
4683 
4685 
4686  Status = RunUSetup();
4687 
4688  if (NT_SUCCESS(Status))
4689  {
4690  /*
4691  * Avoid a bugcheck if RunUSetup() finishes too quickly by implementing
4692  * a protective waiting.
4693  * This wait is needed because, since we are started as SMSS.EXE,
4694  * the NT kernel explicitly waits 5 seconds for the initial process
4695  * SMSS.EXE to initialize (as a protective measure), and otherwise
4696  * bugchecks with the code SESSION5_INITIALIZATION_FAILED.
4697  */
4698  Time.QuadPart += 50000000;
4700  }
4701  else
4702  {
4703  /* The installer failed to start: raise a hard error (crash the system/BSOD) */
4705  0, 0, NULL, 0, NULL);
4706  }
4707 
4709 }
4710 
4711 /* EOF */
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:120
#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:84
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:144
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:522
#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:3873
#define __cdecl
Definition: accygwin.h:79
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
#define STRING_CREATEPARTITION
Definition: mui.h:121
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:553
#define STRING_CHOOSE_NEW_LOGICAL_PARTITION
Definition: mui.h:119
#define STATUS_APP_INIT_FAILURE
Definition: ntstatus.h:561
#define STRING_NONFORMATTEDSYSTEMPART
Definition: mui.h:124
static VOID ResetFileSystemList(VOID)
Definition: usetup.c:2522
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:149
#define TRUE
Definition: types.h:120
static BOOL IsDiskSizeValid(PPARTENTRY PartEntry)
Definition: usetup.c:1495
#define STRING_REBOOTPROGRESSBAR
Definition: mui.h:167
static PAGE_NUMBER InstallDirectoryPage(PINPUT_RECORD Ir)
Definition: usetup.c:3294
uint16_t * PWSTR
Definition: typedefs.h:56
VOID RestoreGenericListUiState(IN PGENERIC_LIST_UI ListUi)
Definition: genlist.c:62
static PAGE_NUMBER SetupStartPage(PINPUT_RECORD Ir)
Definition: usetup.c:702
VOID InfSetHeap(PVOID Heap)
Definition: infrosgen.c:40
ULARGE_INTEGER SectorCount
Definition: partlist.h:50
#define STRING_CONSOLEFAIL3
Definition: mui.h:145
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:137
char CHAR
Definition: xmlstorage.h:175
#define iswdigit(_c)
Definition: ctype.h:667
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:870
VOID ProgressNextStep(IN PPROGRESSBAR Bar)
Definition: progress.c:361
#define CALLBACK
Definition: compat.h:35
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:2199
#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:4451
PGENERIC_LIST CreateLanguageList(IN HINF InfFile, OUT PWSTR DefaultLanguage)
Definition: settings.c:1165
#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:108
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:2202
#define VK_PRIOR
Definition: winuser.h:2195
_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:1215
PRTL_USER_PROCESS_PARAMETERS ProcessParameters
Definition: btrfs_drv.h:1959
#define swprintf
Definition: precomp.h:40
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:2189
static PFILE_SYSTEM_LIST FileSystemList
Definition: usetup.c:79
#define SPFILENOTIFY_ENDRENAME
Definition: fileqsup.h:32
#define STRING_CHOOSENEWPARTITION
Definition: mui.h:117
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:1068
#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:2176
BOOL CONSOLE_Flush(VOID)
Definition: consup.c:175
#define NtGetTickCount
Definition: rtlp.h:146
BOOL WINAPI FillConsoleOutputCharacterA(IN HANDLE hConsoleOutput, IN CHAR cCharacter, IN DWORD nLength, IN COORD dwWriteCoord, OUT LPDWORD lpNumberOfCharsWritten)
Definition: console.c:557
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:158
#define VK_NEXT
Definition: winuser.h:2196
static PAGE_NUMBER HandleGenericList(PGENERIC_LIST_UI ListUi, PAGE_NUMBER nextPage, PINPUT_RECORD Ir)
Definition: usetup.c:1336
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:4107
NTSYSAPI PRTL_USER_PROCESS_PARAMETERS NTAPI RtlNormalizeProcessParams(_In_ PRTL_USER_PROCESS_PARAMETERS ProcessParameters)
#define STRING_IMPORTFILE
Definition: mui.h:136
static PAGE_NUMBER ConfirmDeleteSystemPartitionPage(PINPUT_RECORD Ir)
Definition: usetup.c:2427
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:133
static PAGE_NUMBER KeyboardSettingsPage(PINPUT_RECORD Ir)
Definition: usetup.c:1453
static BOOLEAN IsValidPath(IN PCWSTR InstallDir)
Definition: usetup.c:3238
#define SPFILENOTIFY_STARTSUBQUEUE
Definition: fileqsup.h:24
WCHAR First[]
Definition: FormatMessage.c:11
static NTSTATUS NTAPI GetNTOSInstallationName(IN PGENERIC_LIST_ENTRY Entry, OUT PSTR Buffer, IN SIZE_T cchBufferSize)
Definition: usetup.c:502
static PAGE_NUMBER LanguagePage(PINPUT_RECORD Ir)
Definition: usetup.c:543
#define MB
Definition: setuplib.h:56
#define STRING_NEWPARTITION
Definition: mui.h:156
BOOLEAN LogicalPartition
Definition: partlist.h:63
#define STRING_REBOOTCOMPUTER2
Definition: mui.h:142
#define VK_HOME
Definition: winuser.h:2198
BOOL bFoundFontMSMINCHO
Definition: substset.h:9
static VOID UpdateKBLayout(VOID)
Definition: usetup.c:456
static VOID ShowPartitionSizeInputBox(SHORT Left, SHORT Top, SHORT Right, SHORT Bottom, ULONG MaxSize, PWSTR InputBuffer, PBOOLEAN Quit, PBOOLEAN Cancel)
Definition: usetup.c:1880
#define STATUS_WAIT_0
Definition: ntstatus.h:237
VOID CONSOLE_InvertTextXY(IN SHORT x, IN SHORT y, IN SHORT col, IN SHORT row)
Definition: consup.c:276
PCWSTR MUIDefaultKeyboardLayout(IN PCWSTR LanguageId)
Definition: