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