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