[USETUP] Use _wcstoui64() instead of atoi() to convert the partition size in order...
[reactos.git] / base / setup / usetup / usetup.c
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 * PROGRAMMER: Eric Kohl
25 * Casper S. Hornstrup (chorns@users.sourceforge.net)
26 * Hervé Poussineau (hpoussin@reactos.org)
27 */
28
29 #include <usetup.h>
30 #include <math.h>
31
32 #include "bootsup.h"
33 #include "chkdsk.h"
34 #include "cmdcons.h"
35 #include "format.h"
36 #include "drivesup.h"
37 #include "settings.h"
38
39 #define NDEBUG
40 #include <debug.h>
41
42
43 /* GLOBALS ******************************************************************/
44
45 HANDLE ProcessHeap;
46 UNICODE_STRING SourceRootPath;
47 UNICODE_STRING SourceRootDir;
48 UNICODE_STRING SourcePath;
49 BOOLEAN IsUnattendedSetup = FALSE;
50 LONG UnattendDestinationDiskNumber;
51 LONG UnattendDestinationPartitionNumber;
52 LONG UnattendMBRInstallType = -1;
53 LONG UnattendFormatPartition = 0;
54 LONG AutoPartition = 0;
55 WCHAR UnattendInstallationDirectory[MAX_PATH];
56 PWCHAR SelectedLanguageId;
57 WCHAR LocaleID[9];
58 WCHAR DefaultLanguage[20];
59 WCHAR DefaultKBLayout[20];
60 BOOLEAN RepairUpdateFlag = FALSE;
61 HANDLE hPnpThread = INVALID_HANDLE_VALUE;
62 PPARTLIST PartitionList = NULL;
63
64 /* LOCALS *******************************************************************/
65
66 static PFILE_SYSTEM_LIST FileSystemList = NULL;
67
68 static UNICODE_STRING InstallPath;
69
70 /*
71 * Path to the system partition, where the boot manager resides.
72 * On x86 PCs, this is usually the active partition.
73 * On ARC, (u)EFI, ... platforms, this is a dedicated partition.
74 *
75 * For more information, see:
76 * https://en.wikipedia.org/wiki/System_partition_and_boot_partition
77 * http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/boot-and-system-volumes.html
78 * http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/arc-boot-process.html
79 * http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/efi-boot-process.html
80 * http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/determining-system-volume.html
81 * http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/determining-boot-volume.html
82 */
83 static UNICODE_STRING SystemRootPath;
84
85 /* Path to the install directory inside the ReactOS boot partition */
86 static UNICODE_STRING DestinationPath;
87 static UNICODE_STRING DestinationArcPath;
88 static UNICODE_STRING DestinationRootPath;
89
90 static WCHAR DestinationDriveLetter;
91
92 static HINF SetupInf;
93
94 static HSPFILEQ SetupFileQueue = NULL;
95
96 static PGENERIC_LIST ComputerList = NULL;
97 static PGENERIC_LIST DisplayList = NULL;
98 static PGENERIC_LIST KeyboardList = NULL;
99 static PGENERIC_LIST LayoutList = NULL;
100 static PGENERIC_LIST LanguageList = NULL;
101
102 static LANGID LanguageId = 0;
103
104 static ULONG RequiredPartitionDiskSpace = ~0;
105
106 /* FUNCTIONS ****************************************************************/
107
108 static VOID
109 PrintString(char* fmt,...)
110 {
111 char buffer[512];
112 va_list ap;
113 UNICODE_STRING UnicodeString;
114 ANSI_STRING AnsiString;
115
116 va_start(ap, fmt);
117 vsprintf(buffer, fmt, ap);
118 va_end(ap);
119
120 RtlInitAnsiString(&AnsiString, buffer);
121 RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE);
122 NtDisplayString(&UnicodeString);
123 RtlFreeUnicodeString(&UnicodeString);
124 }
125
126
127 static VOID
128 DrawBox(IN SHORT xLeft,
129 IN SHORT yTop,
130 IN SHORT Width,
131 IN SHORT Height)
132 {
133 COORD coPos;
134 DWORD Written;
135
136 /* draw upper left corner */
137 coPos.X = xLeft;
138 coPos.Y = yTop;
139 FillConsoleOutputCharacterA(StdOutput,
140 0xDA, // '+',
141 1,
142 coPos,
143 &Written);
144
145 /* draw upper edge */
146 coPos.X = xLeft + 1;
147 coPos.Y = yTop;
148 FillConsoleOutputCharacterA(StdOutput,
149 0xC4, // '-',
150 Width - 2,
151 coPos,
152 &Written);
153
154 /* draw upper right corner */
155 coPos.X = xLeft + Width - 1;
156 coPos.Y = yTop;
157 FillConsoleOutputCharacterA(StdOutput,
158 0xBF, // '+',
159 1,
160 coPos,
161 &Written);
162
163 /* Draw right edge, inner space and left edge */
164 for (coPos.Y = yTop + 1; coPos.Y < yTop + Height - 1; coPos.Y++)
165 {
166 coPos.X = xLeft;
167 FillConsoleOutputCharacterA(StdOutput,
168 0xB3, // '|',
169 1,
170 coPos,
171 &Written);
172
173 coPos.X = xLeft + 1;
174 FillConsoleOutputCharacterA(StdOutput,
175 ' ',
176 Width - 2,
177 coPos,
178 &Written);
179
180 coPos.X = xLeft + Width - 1;
181 FillConsoleOutputCharacterA(StdOutput,
182 0xB3, // '|',
183 1,
184 coPos,
185 &Written);
186 }
187
188 /* draw lower left corner */
189 coPos.X = xLeft;
190 coPos.Y = yTop + Height - 1;
191 FillConsoleOutputCharacterA(StdOutput,
192 0xC0, // '+',
193 1,
194 coPos,
195 &Written);
196
197 /* draw lower edge */
198 coPos.X = xLeft + 1;
199 coPos.Y = yTop + Height - 1;
200 FillConsoleOutputCharacterA(StdOutput,
201 0xC4, // '-',
202 Width - 2,
203 coPos,
204 &Written);
205
206 /* draw lower right corner */
207 coPos.X = xLeft + Width - 1;
208 coPos.Y = yTop + Height - 1;
209 FillConsoleOutputCharacterA(StdOutput,
210 0xD9, // '+',
211 1,
212 coPos,
213 &Written);
214 }
215
216
217 VOID
218 PopupError(PCCH Text,
219 PCCH Status,
220 PINPUT_RECORD Ir,
221 ULONG WaitEvent)
222 {
223 SHORT yTop;
224 SHORT xLeft;
225 COORD coPos;
226 DWORD Written;
227 ULONG Length;
228 ULONG MaxLength;
229 ULONG Lines;
230 PCHAR p;
231 PCCH pnext;
232 BOOLEAN LastLine;
233 SHORT Width;
234 SHORT Height;
235
236 /* Count text lines and longest line */
237 MaxLength = 0;
238 Lines = 0;
239 pnext = Text;
240
241 while (TRUE)
242 {
243 p = strchr(pnext, '\n');
244
245 if (p == NULL)
246 {
247 Length = strlen(pnext);
248 LastLine = TRUE;
249 }
250 else
251 {
252 Length = (ULONG)(p - pnext);
253 LastLine = FALSE;
254 }
255
256 Lines++;
257
258 if (Length > MaxLength)
259 MaxLength = Length;
260
261 if (LastLine != FALSE)
262 break;
263
264 pnext = p + 1;
265 }
266
267 /* Check length of status line */
268 if (Status != NULL)
269 {
270 Length = strlen(Status);
271
272 if (Length > MaxLength)
273 MaxLength = Length;
274 }
275
276 Width = MaxLength + 4;
277 Height = Lines + 2;
278
279 if (Status != NULL)
280 Height += 2;
281
282 yTop = (yScreen - Height) / 2;
283 xLeft = (xScreen - Width) / 2;
284
285
286 /* Set screen attributes */
287 coPos.X = xLeft;
288 for (coPos.Y = yTop; coPos.Y < yTop + Height; coPos.Y++)
289 {
290 FillConsoleOutputAttribute(StdOutput,
291 FOREGROUND_RED | BACKGROUND_WHITE,
292 Width,
293 coPos,
294 &Written);
295 }
296
297 DrawBox(xLeft, yTop, Width, Height);
298
299 /* Print message text */
300 coPos.Y = yTop + 1;
301 pnext = Text;
302 while (TRUE)
303 {
304 p = strchr(pnext, '\n');
305
306 if (p == NULL)
307 {
308 Length = strlen(pnext);
309 LastLine = TRUE;
310 }
311 else
312 {
313 Length = (ULONG)(p - pnext);
314 LastLine = FALSE;
315 }
316
317 if (Length != 0)
318 {
319 coPos.X = xLeft + 2;
320 WriteConsoleOutputCharacterA(StdOutput,
321 pnext,
322 Length,
323 coPos,
324 &Written);
325 }
326
327 if (LastLine != FALSE)
328 break;
329
330 coPos.Y++;
331 pnext = p + 1;
332 }
333
334 /* Print separator line and status text */
335 if (Status != NULL)
336 {
337 coPos.Y = yTop + Height - 3;
338 coPos.X = xLeft;
339 FillConsoleOutputCharacterA(StdOutput,
340 0xC3, // '+',
341 1,
342 coPos,
343 &Written);
344
345 coPos.X = xLeft + 1;
346 FillConsoleOutputCharacterA(StdOutput,
347 0xC4, // '-',
348 Width - 2,
349 coPos,
350 &Written);
351
352 coPos.X = xLeft + Width - 1;
353 FillConsoleOutputCharacterA(StdOutput,
354 0xB4, // '+',
355 1,
356 coPos,
357 &Written);
358
359 coPos.Y++;
360 coPos.X = xLeft + 2;
361 WriteConsoleOutputCharacterA(StdOutput,
362 Status,
363 min(strlen(Status), (SIZE_T)Width - 4),
364 coPos,
365 &Written);
366 }
367
368 if (WaitEvent == POPUP_WAIT_NONE)
369 return;
370
371 while (TRUE)
372 {
373 CONSOLE_ConInKey(Ir);
374
375 if (WaitEvent == POPUP_WAIT_ANY_KEY ||
376 Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)
377 {
378 return;
379 }
380 }
381 }
382
383
384 /*
385 * Confirm quit setup
386 * RETURNS
387 * TRUE: Quit setup.
388 * FALSE: Don't quit setup.
389 */
390 static BOOL
391 ConfirmQuit(PINPUT_RECORD Ir)
392 {
393 BOOL Result = FALSE;
394 MUIDisplayError(ERROR_NOT_INSTALLED, NULL, POPUP_WAIT_NONE);
395
396 while (TRUE)
397 {
398 CONSOLE_ConInKey(Ir);
399
400 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
401 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
402 {
403 Result = TRUE;
404 break;
405 }
406 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
407 {
408 Result = FALSE;
409 break;
410 }
411 }
412
413 return Result;
414 }
415
416
417 VOID
418 CheckUnattendedSetup(VOID)
419 {
420 WCHAR UnattendInfPath[MAX_PATH];
421 INFCONTEXT Context;
422 HINF UnattendInf;
423 UINT ErrorLine;
424 INT IntValue;
425 PWCHAR Value;
426
427 if (DoesFileExist(SourcePath.Buffer, L"unattend.inf") == FALSE)
428 {
429 DPRINT("Does not exist: %S\\%S\n", SourcePath.Buffer, L"unattend.inf");
430 return;
431 }
432
433 wcscpy(UnattendInfPath, SourcePath.Buffer);
434 wcscat(UnattendInfPath, L"\\unattend.inf");
435
436 /* Load 'unattend.inf' from install media. */
437 UnattendInf = SetupOpenInfFileW(UnattendInfPath,
438 NULL,
439 INF_STYLE_WIN4,
440 LanguageId,
441 &ErrorLine);
442
443 if (UnattendInf == INVALID_HANDLE_VALUE)
444 {
445 DPRINT("SetupOpenInfFileW() failed\n");
446 return;
447 }
448
449 /* Open 'Unattend' section */
450 if (!SetupFindFirstLineW(UnattendInf, L"Unattend", L"Signature", &Context))
451 {
452 DPRINT("SetupFindFirstLineW() failed for section 'Unattend'\n");
453 SetupCloseInfFile(UnattendInf);
454 return;
455 }
456
457 /* Get pointer 'Signature' key */
458 if (!INF_GetData(&Context, NULL, &Value))
459 {
460 DPRINT("INF_GetData() failed for key 'Signature'\n");
461 SetupCloseInfFile(UnattendInf);
462 return;
463 }
464
465 /* Check 'Signature' string */
466 if (_wcsicmp(Value, L"$ReactOS$") != 0)
467 {
468 DPRINT("Signature not $ReactOS$\n");
469 SetupCloseInfFile(UnattendInf);
470 return;
471 }
472
473 /* Check if Unattend setup is enabled */
474 if (!SetupFindFirstLineW(UnattendInf, L"Unattend", L"UnattendSetupEnabled", &Context))
475 {
476 DPRINT("Can't find key 'UnattendSetupEnabled'\n");
477 SetupCloseInfFile(UnattendInf);
478 return;
479 }
480
481 if (!INF_GetData(&Context, NULL, &Value))
482 {
483 DPRINT("Can't read key 'UnattendSetupEnabled'\n");
484 SetupCloseInfFile(UnattendInf);
485 return;
486 }
487
488 if (_wcsicmp(Value, L"yes") != 0)
489 {
490 DPRINT("Unattend setup is disabled by 'UnattendSetupEnabled' key!\n");
491 SetupCloseInfFile(UnattendInf);
492 return;
493 }
494
495 /* Search for 'DestinationDiskNumber' in the 'Unattend' section */
496 if (!SetupFindFirstLineW(UnattendInf, L"Unattend", L"DestinationDiskNumber", &Context))
497 {
498 DPRINT("SetupFindFirstLine() failed for key 'DestinationDiskNumber'\n");
499 SetupCloseInfFile(UnattendInf);
500 return;
501 }
502
503 if (!SetupGetIntField(&Context, 1, &IntValue))
504 {
505 DPRINT("SetupGetIntField() failed for key 'DestinationDiskNumber'\n");
506 SetupCloseInfFile(UnattendInf);
507 return;
508 }
509
510 UnattendDestinationDiskNumber = (LONG)IntValue;
511
512 /* Search for 'DestinationPartitionNumber' in the 'Unattend' section */
513 if (!SetupFindFirstLineW(UnattendInf, L"Unattend", L"DestinationPartitionNumber", &Context))
514 {
515 DPRINT("SetupFindFirstLine() failed for key 'DestinationPartitionNumber'\n");
516 SetupCloseInfFile(UnattendInf);
517 return;
518 }
519
520 if (!SetupGetIntField(&Context, 1, &IntValue))
521 {
522 DPRINT("SetupGetIntField() failed for key 'DestinationPartitionNumber'\n");
523 SetupCloseInfFile(UnattendInf);
524 return;
525 }
526
527 UnattendDestinationPartitionNumber = IntValue;
528
529 /* Search for 'InstallationDirectory' in the 'Unattend' section */
530 if (!SetupFindFirstLineW(UnattendInf, L"Unattend", L"InstallationDirectory", &Context))
531 {
532 DPRINT("SetupFindFirstLine() failed for key 'InstallationDirectory'\n");
533 SetupCloseInfFile(UnattendInf);
534 return;
535 }
536
537 /* Get pointer 'InstallationDirectory' key */
538 if (!INF_GetData(&Context, NULL, &Value))
539 {
540 DPRINT("INF_GetData() failed for key 'InstallationDirectory'\n");
541 SetupCloseInfFile(UnattendInf);
542 return;
543 }
544
545 wcscpy(UnattendInstallationDirectory, Value);
546
547 IsUnattendedSetup = TRUE;
548
549 /* Search for 'MBRInstallType' in the 'Unattend' section */
550 if (SetupFindFirstLineW(UnattendInf, L"Unattend", L"MBRInstallType", &Context))
551 {
552 if (SetupGetIntField(&Context, 1, &IntValue))
553 {
554 UnattendMBRInstallType = IntValue;
555 }
556 }
557
558 /* Search for 'FormatPartition' in the 'Unattend' section */
559 if (SetupFindFirstLineW(UnattendInf, L"Unattend", L"FormatPartition", &Context))
560 {
561 if (SetupGetIntField(&Context, 1, &IntValue))
562 {
563 UnattendFormatPartition = IntValue;
564 }
565 }
566
567 if (SetupFindFirstLineW(UnattendInf, L"Unattend", L"AutoPartition", &Context))
568 {
569 if (SetupGetIntField(&Context, 1, &IntValue))
570 {
571 AutoPartition = IntValue;
572 }
573 }
574
575 /* search for LocaleID in the 'Unattend' section*/
576 if (SetupFindFirstLineW(UnattendInf, L"Unattend", L"LocaleID", &Context))
577 {
578 if (INF_GetData(&Context, NULL, &Value))
579 {
580 LONG Id = wcstol(Value, NULL, 16);
581 swprintf(LocaleID,L"%08lx", Id);
582 }
583 }
584
585 SetupCloseInfFile(UnattendInf);
586
587 DPRINT("Running unattended setup\n");
588 }
589
590
591 VOID
592 UpdateKBLayout(VOID)
593 {
594 PGENERIC_LIST_ENTRY ListEntry;
595 LPCWSTR pszNewLayout;
596
597 pszNewLayout = MUIDefaultKeyboardLayout();
598
599 if (LayoutList == NULL)
600 {
601 LayoutList = CreateKeyboardLayoutList(SetupInf, DefaultKBLayout);
602 if (LayoutList == NULL)
603 {
604 /* FIXME: Handle error! */
605 return;
606 }
607 }
608
609 ListEntry = GetFirstListEntry(LayoutList);
610
611 /* Search for default layout (if provided) */
612 if (pszNewLayout != NULL)
613 {
614 while (ListEntry != NULL)
615 {
616 if (!wcscmp(pszNewLayout, GetListEntryUserData(ListEntry)))
617 {
618 SetCurrentListEntry(LayoutList, ListEntry);
619 break;
620 }
621
622 ListEntry = GetNextListEntry(ListEntry);
623 }
624 }
625 }
626
627
628 /*
629 * Displays the LanguagePage.
630 *
631 * Next pages: IntroPage, QuitPage
632 *
633 * SIDEEFFECTS
634 * Init SelectedLanguageId
635 * Init LanguageId
636 *
637 * RETURNS
638 * Number of the next page.
639 */
640 static PAGE_NUMBER
641 LanguagePage(PINPUT_RECORD Ir)
642 {
643 PWCHAR NewLanguageId;
644 BOOL RefreshPage = FALSE;
645
646 /* Initialize the computer settings list */
647 if (LanguageList == NULL)
648 {
649 LanguageList = CreateLanguageList(SetupInf, DefaultLanguage);
650
651 if (LanguageList == NULL)
652 {
653 PopupError("Setup failed to initialize available translations", NULL, NULL, POPUP_WAIT_NONE);
654 return INTRO_PAGE;
655 }
656 }
657
658 /* Load the font */
659 SelectedLanguageId = DefaultLanguage;
660 SetConsoleCodePage();
661 UpdateKBLayout();
662
663 /* If there's just a single language in the list skip
664 * the language selection process altogether! */
665 if (GenericListHasSingleEntry(LanguageList))
666 {
667 LanguageId = (LANGID)(wcstol(SelectedLanguageId, NULL, 16) & 0xFFFF);
668 return INTRO_PAGE;
669 }
670
671 DrawGenericList(LanguageList,
672 2,
673 18,
674 xScreen - 3,
675 yScreen - 3);
676
677 ScrollToPositionGenericList(LanguageList, GetDefaultLanguageIndex());
678
679 MUIDisplayPage(LANGUAGE_PAGE);
680
681 while (TRUE)
682 {
683 CONSOLE_ConInKey(Ir);
684
685 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
686 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
687 {
688 ScrollDownGenericList(LanguageList);
689 RefreshPage = TRUE;
690 }
691 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
692 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
693 {
694 ScrollUpGenericList(LanguageList);
695 RefreshPage = TRUE;
696 }
697 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
698 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_NEXT)) /* PAGE DOWN */
699 {
700 ScrollPageDownGenericList(LanguageList);
701 RefreshPage = TRUE;
702 }
703 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
704 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_PRIOR)) /* PAGE UP */
705 {
706 ScrollPageUpGenericList(LanguageList);
707 RefreshPage = TRUE;
708 }
709 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
710 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
711 {
712 if (ConfirmQuit(Ir) != FALSE)
713 return QUIT_PAGE;
714 else
715 RedrawGenericList(LanguageList);
716 }
717 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
718 {
719 SelectedLanguageId = (PWCHAR)GetListEntryUserData(GetCurrentListEntry(LanguageList));
720
721 LanguageId = (LANGID)(wcstol(SelectedLanguageId, NULL, 16) & 0xFFFF);
722
723 if (wcscmp(SelectedLanguageId, DefaultLanguage))
724 {
725 UpdateKBLayout();
726 }
727
728 /* Load the font */
729 SetConsoleCodePage();
730
731 return INTRO_PAGE;
732 }
733 else if ((Ir->Event.KeyEvent.uChar.AsciiChar > 0x60) && (Ir->Event.KeyEvent.uChar.AsciiChar < 0x7b))
734 {
735 /* a-z */
736 GenericListKeyPress(LanguageList, Ir->Event.KeyEvent.uChar.AsciiChar);
737 RefreshPage = TRUE;
738 }
739
740 if (RefreshPage)
741 {
742 NewLanguageId = (PWCHAR)GetListEntryUserData(GetCurrentListEntry(LanguageList));
743
744 if (SelectedLanguageId != NewLanguageId)
745 {
746 /* Clear the language page */
747 MUIClearPage(LANGUAGE_PAGE);
748
749 SelectedLanguageId = NewLanguageId;
750
751 /* Load the font */
752 SetConsoleCodePage();
753
754 /* Redraw language selection page in native language */
755 MUIDisplayPage(LANGUAGE_PAGE);
756 }
757
758 RefreshPage = FALSE;
759 }
760 }
761
762 return INTRO_PAGE;
763 }
764
765
766 /*
767 * Start page
768 *
769 * Next pages:
770 * LanguagePage (at once, default)
771 * InstallIntroPage (at once, if unattended)
772 * QuitPage
773 *
774 * SIDEEFFECTS
775 * Init Sdi
776 * Init SourcePath
777 * Init SourceRootPath
778 * Init SourceRootDir
779 * Init SetupInf
780 * Init RequiredPartitionDiskSpace
781 * Init IsUnattendedSetup
782 * If unattended, init *List and sets the Codepage
783 * If unattended, init SelectedLanguageId
784 * If unattended, init LanguageId
785 *
786 * RETURNS
787 * Number of the next page.
788 */
789 static PAGE_NUMBER
790 SetupStartPage(PINPUT_RECORD Ir)
791 {
792 //SYSTEM_DEVICE_INFORMATION Sdi;
793 NTSTATUS Status;
794 WCHAR FileNameBuffer[MAX_PATH];
795 INFCONTEXT Context;
796 PWCHAR Value;
797 UINT ErrorLine;
798 //ULONG ReturnSize;
799 PGENERIC_LIST_ENTRY ListEntry;
800 INT IntValue;
801
802 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
803
804 #if 0
805 /* Check whether a harddisk is available */
806 Status = NtQuerySystemInformation(SystemDeviceInformation,
807 &Sdi,
808 sizeof(SYSTEM_DEVICE_INFORMATION),
809 &ReturnSize);
810
811 if (!NT_SUCCESS(Status))
812 {
813 CONSOLE_PrintTextXY(6, 15, "NtQuerySystemInformation() failed (Status 0x%08lx)", Status);
814 MUIDisplayError(ERROR_DRIVE_INFORMATION, Ir, POPUP_WAIT_ENTER);
815 return QUIT_PAGE;
816 }
817
818 if (Sdi.NumberOfDisks == 0)
819 {
820 MUIDisplayError(ERROR_NO_HDD, Ir, POPUP_WAIT_ENTER);
821 return QUIT_PAGE;
822 }
823 #endif
824
825 /* Get the source path and source root path */
826 Status = GetSourcePaths(&SourcePath,
827 &SourceRootPath,
828 &SourceRootDir);
829
830 if (!NT_SUCCESS(Status))
831 {
832 CONSOLE_PrintTextXY(6, 15, "GetSourcePaths() failed (Status 0x%08lx)", Status);
833 MUIDisplayError(ERROR_NO_SOURCE_DRIVE, Ir, POPUP_WAIT_ENTER);
834 return QUIT_PAGE;
835 }
836 #if 0
837 else
838 {
839 CONSOLE_PrintTextXY(6, 15, "SourcePath: '%wZ'", &SourcePath);
840 CONSOLE_PrintTextXY(6, 16, "SourceRootPath: '%wZ'", &SourceRootPath);
841 CONSOLE_PrintTextXY(6, 17, "SourceRootDir: '%wZ'", &SourceRootDir);
842 }
843 #endif
844
845 /* Load txtsetup.sif from install media. */
846 wcscpy(FileNameBuffer, SourcePath.Buffer);
847 wcscat(FileNameBuffer, L"\\txtsetup.sif");
848
849 SetupInf = SetupOpenInfFileW(FileNameBuffer,
850 NULL,
851 INF_STYLE_WIN4,
852 LanguageId,
853 &ErrorLine);
854
855 if (SetupInf == INVALID_HANDLE_VALUE)
856 {
857 MUIDisplayError(ERROR_LOAD_TXTSETUPSIF, Ir, POPUP_WAIT_ENTER);
858 return QUIT_PAGE;
859 }
860
861 /* Open 'Version' section */
862 if (!SetupFindFirstLineW(SetupInf, L"Version", L"Signature", &Context))
863 {
864 MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF, Ir, POPUP_WAIT_ENTER);
865 return QUIT_PAGE;
866 }
867
868 /* Get pointer 'Signature' key */
869 if (!INF_GetData(&Context, NULL, &Value))
870 {
871 MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF, Ir, POPUP_WAIT_ENTER);
872 return QUIT_PAGE;
873 }
874
875 /* Check 'Signature' string */
876 if (_wcsicmp(Value, L"$ReactOS$") != 0)
877 {
878 MUIDisplayError(ERROR_SIGNATURE_TXTSETUPSIF, Ir, POPUP_WAIT_ENTER);
879 return QUIT_PAGE;
880 }
881
882 /* Open 'DiskSpaceRequirements' section */
883 if (!SetupFindFirstLineW(SetupInf, L"DiskSpaceRequirements", L"FreeSysPartDiskSpace", &Context))
884 {
885 MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF, Ir, POPUP_WAIT_ENTER);
886 return QUIT_PAGE;
887 }
888
889 /* Get the 'FreeSysPartDiskSpace' value */
890 if (!SetupGetIntField(&Context, 1, &IntValue))
891 {
892 MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF, Ir, POPUP_WAIT_ENTER);
893 return QUIT_PAGE;
894 }
895
896 RequiredPartitionDiskSpace = (ULONG)IntValue;
897
898 /* Start PnP thread */
899 if (hPnpThread != INVALID_HANDLE_VALUE)
900 {
901 NtResumeThread(hPnpThread, NULL);
902 hPnpThread = INVALID_HANDLE_VALUE;
903 }
904
905 CheckUnattendedSetup();
906
907 if (IsUnattendedSetup)
908 {
909 //TODO
910 //read options from inf
911 ComputerList = CreateComputerTypeList(SetupInf);
912 DisplayList = CreateDisplayDriverList(SetupInf);
913 KeyboardList = CreateKeyboardDriverList(SetupInf);
914 LayoutList = CreateKeyboardLayoutList(SetupInf, DefaultKBLayout);
915 LanguageList = CreateLanguageList(SetupInf, DefaultLanguage);
916
917 /* new part */
918 wcscpy(SelectedLanguageId,LocaleID);
919 LanguageId = (LANGID)(wcstol(SelectedLanguageId, NULL, 16) & 0xFFFF);
920
921 /* first we hack LanguageList */
922 ListEntry = GetFirstListEntry(LanguageList);
923
924 while (ListEntry != NULL)
925 {
926 if (!wcsicmp(LocaleID, GetListEntryUserData(ListEntry)))
927 {
928 DPRINT("found %S in LanguageList\n",GetListEntryUserData(ListEntry));
929 SetCurrentListEntry(LanguageList, ListEntry);
930 break;
931 }
932
933 ListEntry = GetNextListEntry(ListEntry);
934 }
935
936 /* now LayoutList */
937 ListEntry = GetFirstListEntry(LayoutList);
938
939 while (ListEntry != NULL)
940 {
941 if (!wcsicmp(LocaleID, GetListEntryUserData(ListEntry)))
942 {
943 DPRINT("found %S in LayoutList\n",GetListEntryUserData(ListEntry));
944 SetCurrentListEntry(LayoutList, ListEntry);
945 break;
946 }
947
948 ListEntry = GetNextListEntry(ListEntry);
949 }
950
951 SetConsoleCodePage();
952
953 return INSTALL_INTRO_PAGE;
954 }
955
956 return LANGUAGE_PAGE;
957 }
958
959
960 /*
961 * Displays the IntroPage.
962 *
963 * Next pages:
964 * InstallIntroPage (default)
965 * RepairIntroPage
966 * LicensePage
967 * QuitPage
968 *
969 * RETURNS
970 * Number of the next page.
971 */
972 static PAGE_NUMBER
973 IntroPage(PINPUT_RECORD Ir)
974 {
975 MUIDisplayPage(START_PAGE);
976
977 while (TRUE)
978 {
979 CONSOLE_ConInKey(Ir);
980
981 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
982 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
983 {
984 if (ConfirmQuit(Ir) != FALSE)
985 return QUIT_PAGE;
986
987 break;
988 }
989 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
990 {
991 return INSTALL_INTRO_PAGE;
992 }
993 else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'R') /* R */
994 {
995 return REPAIR_INTRO_PAGE;
996 }
997 else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'L') /* R */
998 {
999 return LICENSE_PAGE;
1000 }
1001 }
1002
1003 return INTRO_PAGE;
1004 }
1005
1006
1007 /*
1008 * Displays the License page.
1009 *
1010 * Next page:
1011 * IntroPage (default)
1012 *
1013 * RETURNS
1014 * Number of the next page.
1015 */
1016 static PAGE_NUMBER
1017 LicensePage(PINPUT_RECORD Ir)
1018 {
1019 MUIDisplayPage(LICENSE_PAGE);
1020
1021 while (TRUE)
1022 {
1023 CONSOLE_ConInKey(Ir);
1024
1025 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1026 {
1027 return INTRO_PAGE;
1028 }
1029 }
1030
1031 return LICENSE_PAGE;
1032 }
1033
1034
1035 /*
1036 * Displays the RepairIntroPage.
1037 *
1038 * Next pages:
1039 * RebootPage (default)
1040 * InstallIntroPage
1041 * RecoveryPage
1042 * IntroPage
1043 *
1044 * RETURNS
1045 * Number of the next page.
1046 */
1047 static PAGE_NUMBER
1048 RepairIntroPage(PINPUT_RECORD Ir)
1049 {
1050 MUIDisplayPage(REPAIR_INTRO_PAGE);
1051
1052 while(TRUE)
1053 {
1054 CONSOLE_ConInKey(Ir);
1055
1056 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1057 {
1058 return REBOOT_PAGE;
1059 }
1060 else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'U') /* U */
1061 {
1062 RepairUpdateFlag = TRUE;
1063 return INSTALL_INTRO_PAGE;
1064 }
1065 else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'R') /* R */
1066 {
1067 return RECOVERY_PAGE;
1068 }
1069 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1070 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
1071 {
1072 return INTRO_PAGE;
1073 }
1074 }
1075
1076 return REPAIR_INTRO_PAGE;
1077 }
1078
1079 /*
1080 * Displays the InstallIntroPage.
1081 *
1082 * Next pages:
1083 * DeviceSettingsPage (At once if repair or update is selected)
1084 * SelectPartitionPage (At once if unattended setup)
1085 * DeviceSettingsPage (default)
1086 * QuitPage
1087 *
1088 * RETURNS
1089 * Number of the next page.
1090 */
1091 static PAGE_NUMBER
1092 InstallIntroPage(PINPUT_RECORD Ir)
1093 {
1094 MUIDisplayPage(INSTALL_INTRO_PAGE);
1095
1096 if (RepairUpdateFlag)
1097 {
1098 //return SELECT_PARTITION_PAGE;
1099 return DEVICE_SETTINGS_PAGE;
1100 }
1101
1102 if (IsUnattendedSetup)
1103 {
1104 return SELECT_PARTITION_PAGE;
1105 }
1106
1107 while (TRUE)
1108 {
1109 CONSOLE_ConInKey(Ir);
1110
1111 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1112 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1113 {
1114 if (ConfirmQuit(Ir) != FALSE)
1115 return QUIT_PAGE;
1116
1117 break;
1118 }
1119 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1120 {
1121 return DEVICE_SETTINGS_PAGE;
1122 // return SCSI_CONTROLLER_PAGE;
1123 }
1124 }
1125
1126 return INSTALL_INTRO_PAGE;
1127 }
1128
1129
1130 #if 0
1131 static PAGE_NUMBER
1132 ScsiControllerPage(PINPUT_RECORD Ir)
1133 {
1134 SetTextXY(6, 8, "Setup detected the following mass storage devices:");
1135
1136 /* FIXME: print loaded mass storage driver descriptions */
1137 #if 0
1138 SetTextXY(8, 10, "TEST device");
1139 #endif
1140
1141
1142 SetStatusText(" ENTER = Continue F3 = Quit");
1143
1144 while (TRUE)
1145 {
1146 ConInKey(Ir);
1147
1148 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1149 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1150 {
1151 if (ConfirmQuit(Ir) != FALSE)
1152 return QUIT_PAGE;
1153
1154 break;
1155 }
1156 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1157 {
1158 return DEVICE_SETTINGS_PAGE;
1159 }
1160 }
1161
1162 return SCSI_CONTROLLER_PAGE;
1163 }
1164 #endif
1165
1166
1167 /*
1168 * Displays the DeviceSettingsPage.
1169 *
1170 * Next pages:
1171 * SelectPartitionPage (At once if repair or update is selected)
1172 * ComputerSettingsPage
1173 * DisplaySettingsPage
1174 * KeyboardSettingsPage
1175 * LayoutsettingsPage
1176 * SelectPartitionPage
1177 * QuitPage
1178 *
1179 * SIDEEFFECTS
1180 * Init ComputerList
1181 * Init DisplayList
1182 * Init KeyboardList
1183 * Init LayoutList
1184 *
1185 * RETURNS
1186 * Number of the next page.
1187 */
1188 static PAGE_NUMBER
1189 DeviceSettingsPage(PINPUT_RECORD Ir)
1190 {
1191 static ULONG Line = 16;
1192 MUIDisplayPage(DEVICE_SETTINGS_PAGE);
1193
1194 /* Initialize the computer settings list */
1195 if (ComputerList == NULL)
1196 {
1197 ComputerList = CreateComputerTypeList(SetupInf);
1198 if (ComputerList == NULL)
1199 {
1200 MUIDisplayError(ERROR_LOAD_COMPUTER, Ir, POPUP_WAIT_ENTER);
1201 return QUIT_PAGE;
1202 }
1203 }
1204
1205 /* Initialize the display settings list */
1206 if (DisplayList == NULL)
1207 {
1208 DisplayList = CreateDisplayDriverList(SetupInf);
1209 if (DisplayList == NULL)
1210 {
1211 MUIDisplayError(ERROR_LOAD_DISPLAY, Ir, POPUP_WAIT_ENTER);
1212 return QUIT_PAGE;
1213 }
1214 }
1215
1216 /* Initialize the keyboard settings list */
1217 if (KeyboardList == NULL)
1218 {
1219 KeyboardList = CreateKeyboardDriverList(SetupInf);
1220 if (KeyboardList == NULL)
1221 {
1222 MUIDisplayError(ERROR_LOAD_KEYBOARD, Ir, POPUP_WAIT_ENTER);
1223 return QUIT_PAGE;
1224 }
1225 }
1226
1227 /* Initialize the keyboard layout list */
1228 if (LayoutList == NULL)
1229 {
1230 LayoutList = CreateKeyboardLayoutList(SetupInf, DefaultKBLayout);
1231 if (LayoutList == NULL)
1232 {
1233 /* FIXME: report error */
1234 MUIDisplayError(ERROR_LOAD_KBLAYOUT, Ir, POPUP_WAIT_ENTER);
1235 return QUIT_PAGE;
1236 }
1237 }
1238
1239 MUIDisplayPage(DEVICE_SETTINGS_PAGE);
1240
1241
1242 CONSOLE_SetTextXY(25, 11, GetListEntryText(GetCurrentListEntry((ComputerList))));
1243 CONSOLE_SetTextXY(25, 12, GetListEntryText(GetCurrentListEntry((DisplayList))));
1244 CONSOLE_SetTextXY(25, 13, GetListEntryText(GetCurrentListEntry((KeyboardList))));
1245 CONSOLE_SetTextXY(25, 14, GetListEntryText(GetCurrentListEntry((LayoutList))));
1246
1247 CONSOLE_InvertTextXY(24, Line, 48, 1);
1248
1249 if (RepairUpdateFlag)
1250 {
1251 return SELECT_PARTITION_PAGE;
1252 }
1253
1254 while (TRUE)
1255 {
1256 CONSOLE_ConInKey(Ir);
1257
1258 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1259 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1260 {
1261 CONSOLE_NormalTextXY(24, Line, 48, 1);
1262
1263 if (Line == 14)
1264 Line = 16;
1265 else if (Line == 16)
1266 Line = 11;
1267 else
1268 Line++;
1269
1270 CONSOLE_InvertTextXY(24, Line, 48, 1);
1271 }
1272 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1273 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1274 {
1275 CONSOLE_NormalTextXY(24, Line, 48, 1);
1276
1277 if (Line == 11)
1278 Line = 16;
1279 else if (Line == 16)
1280 Line = 14;
1281 else
1282 Line--;
1283
1284 CONSOLE_InvertTextXY(24, Line, 48, 1);
1285 }
1286 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1287 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1288 {
1289 if (ConfirmQuit(Ir) != FALSE)
1290 return QUIT_PAGE;
1291
1292 break;
1293 }
1294 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1295 {
1296 if (Line == 11)
1297 return COMPUTER_SETTINGS_PAGE;
1298 else if (Line == 12)
1299 return DISPLAY_SETTINGS_PAGE;
1300 else if (Line == 13)
1301 return KEYBOARD_SETTINGS_PAGE;
1302 else if (Line == 14)
1303 return LAYOUT_SETTINGS_PAGE;
1304 else if (Line == 16)
1305 return SELECT_PARTITION_PAGE;
1306 }
1307 }
1308
1309 return DEVICE_SETTINGS_PAGE;
1310 }
1311
1312
1313 /*
1314 * Handles generic selection lists.
1315 *
1316 * PARAMS
1317 * GenericList: The list to handle.
1318 * nextPage: The page it needs to jump to after this page.
1319 * Ir: The PINPUT_RECORD
1320 */
1321 static PAGE_NUMBER
1322 HandleGenericList(PGENERIC_LIST GenericList,
1323 PAGE_NUMBER nextPage,
1324 PINPUT_RECORD Ir)
1325 {
1326 while (TRUE)
1327 {
1328 CONSOLE_ConInKey(Ir);
1329
1330 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1331 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1332 {
1333 ScrollDownGenericList(GenericList);
1334 }
1335 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1336 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1337 {
1338 ScrollUpGenericList(GenericList);
1339 }
1340 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1341 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_NEXT)) /* PAGE DOWN */
1342 {
1343 ScrollPageDownGenericList(GenericList);
1344 }
1345 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1346 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_PRIOR)) /* PAGE UP */
1347 {
1348 ScrollPageUpGenericList(GenericList);
1349 }
1350 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1351 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1352 {
1353 if (ConfirmQuit(Ir) != FALSE)
1354 return QUIT_PAGE;
1355
1356 continue;
1357 }
1358 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1359 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
1360 {
1361 RestoreGenericListState(GenericList);
1362 return nextPage;
1363 }
1364 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1365 {
1366 return nextPage;
1367 }
1368 else if ((Ir->Event.KeyEvent.uChar.AsciiChar > 0x60) && (Ir->Event.KeyEvent.uChar.AsciiChar < 0x7b))
1369 {
1370 /* a-z */
1371 GenericListKeyPress(GenericList, Ir->Event.KeyEvent.uChar.AsciiChar);
1372 }
1373 }
1374 }
1375
1376
1377 /*
1378 * Displays the ComputerSettingsPage.
1379 *
1380 * Next pages:
1381 * DeviceSettingsPage
1382 * QuitPage
1383 *
1384 * RETURNS
1385 * Number of the next page.
1386 */
1387 static PAGE_NUMBER
1388 ComputerSettingsPage(PINPUT_RECORD Ir)
1389 {
1390 MUIDisplayPage(COMPUTER_SETTINGS_PAGE);
1391
1392 DrawGenericList(ComputerList,
1393 2,
1394 18,
1395 xScreen - 3,
1396 yScreen - 3);
1397
1398 SaveGenericListState(ComputerList);
1399
1400 return HandleGenericList(ComputerList, DEVICE_SETTINGS_PAGE, Ir);
1401 }
1402
1403
1404 /*
1405 * Displays the DisplaySettingsPage.
1406 *
1407 * Next pages:
1408 * DeviceSettingsPage
1409 * QuitPage
1410 *
1411 * RETURNS
1412 * Number of the next page.
1413 */
1414 static PAGE_NUMBER
1415 DisplaySettingsPage(PINPUT_RECORD Ir)
1416 {
1417 MUIDisplayPage(DISPLAY_SETTINGS_PAGE);
1418
1419 DrawGenericList(DisplayList,
1420 2,
1421 18,
1422 xScreen - 3,
1423 yScreen - 3);
1424
1425 SaveGenericListState(DisplayList);
1426
1427 return HandleGenericList(DisplayList, DEVICE_SETTINGS_PAGE, Ir);
1428 }
1429
1430
1431 /*
1432 * Displays the KeyboardSettingsPage.
1433 *
1434 * Next pages:
1435 * DeviceSettingsPage
1436 * QuitPage
1437 *
1438 * RETURNS
1439 * Number of the next page.
1440 */
1441 static PAGE_NUMBER
1442 KeyboardSettingsPage(PINPUT_RECORD Ir)
1443 {
1444 MUIDisplayPage(KEYBOARD_SETTINGS_PAGE);
1445
1446 DrawGenericList(KeyboardList,
1447 2,
1448 18,
1449 xScreen - 3,
1450 yScreen - 3);
1451
1452 SaveGenericListState(KeyboardList);
1453
1454 return HandleGenericList(KeyboardList, DEVICE_SETTINGS_PAGE, Ir);
1455 }
1456
1457
1458 /*
1459 * Displays the LayoutSettingsPage.
1460 *
1461 * Next pages:
1462 * DeviceSettingsPage
1463 * QuitPage
1464 *
1465 * RETURNS
1466 * Number of the next page.
1467 */
1468 static PAGE_NUMBER
1469 LayoutSettingsPage(PINPUT_RECORD Ir)
1470 {
1471 MUIDisplayPage(LAYOUT_SETTINGS_PAGE);
1472
1473 DrawGenericList(LayoutList,
1474 2,
1475 18,
1476 xScreen - 3,
1477 yScreen - 3);
1478
1479 SaveGenericListState(LayoutList);
1480
1481 return HandleGenericList(LayoutList, DEVICE_SETTINGS_PAGE, Ir);
1482 }
1483
1484
1485 static BOOL
1486 IsDiskSizeValid(PPARTENTRY PartEntry)
1487 {
1488 ULONGLONG size;
1489
1490 size = PartEntry->SectorCount.QuadPart * PartEntry->DiskEntry->BytesPerSector;
1491 size = (size + 524288) / 1048576; /* in MBytes */
1492
1493 if (size < RequiredPartitionDiskSpace)
1494 {
1495 /* partition is too small so ask for another partition */
1496 DPRINT1("Partition is too small (size: %I64u MB), required disk space is %lu MB\n", size, RequiredPartitionDiskSpace);
1497 return FALSE;
1498 }
1499 else
1500 {
1501 return TRUE;
1502 }
1503 }
1504
1505
1506 /*
1507 * Displays the SelectPartitionPage.
1508 *
1509 * Next pages:
1510 * SelectFileSystemPage (At once if unattended)
1511 * SelectFileSystemPage (Default if free space is selected)
1512 * CreatePrimaryPartitionPage
1513 * CreateExtendedPartitionPage
1514 * CreateLogicalPartitionPage
1515 * ConfirmDeleteSystemPartitionPage (if the selected partition is the system partition, aka with the boot flag set)
1516 * DeletePartitionPage
1517 * QuitPage
1518 *
1519 * SIDEEFFECTS
1520 * Init DestinationDriveLetter (only if unattended or not free space is selected)
1521 * Set InstallShortcut (only if not unattended + free space is selected)
1522 *
1523 * RETURNS
1524 * Number of the next page.
1525 */
1526 static PAGE_NUMBER
1527 SelectPartitionPage(PINPUT_RECORD Ir)
1528 {
1529 ULONG Error;
1530
1531 MUIDisplayPage(SELECT_PARTITION_PAGE);
1532
1533 if (PartitionList == NULL)
1534 {
1535 PartitionList = CreatePartitionList(2,
1536 23,
1537 xScreen - 3,
1538 yScreen - 3);
1539 if (PartitionList == NULL)
1540 {
1541 /* FIXME: show an error dialog */
1542 return QUIT_PAGE;
1543 }
1544 else if (IsListEmpty(&PartitionList->DiskListHead))
1545 {
1546 MUIDisplayError(ERROR_NO_HDD, Ir, POPUP_WAIT_ENTER);
1547 return QUIT_PAGE;
1548 }
1549 }
1550
1551 DrawPartitionList(PartitionList);
1552
1553 if (IsUnattendedSetup)
1554 {
1555 if (!SelectPartition(PartitionList, UnattendDestinationDiskNumber, UnattendDestinationPartitionNumber))
1556 {
1557 if (AutoPartition)
1558 {
1559 if (PartitionList->CurrentPartition->LogicalPartition)
1560 {
1561 CreateLogicalPartition(PartitionList,
1562 PartitionList->CurrentPartition->SectorCount.QuadPart,
1563 TRUE);
1564 }
1565 else
1566 {
1567 CreatePrimaryPartition(PartitionList,
1568 PartitionList->CurrentPartition->SectorCount.QuadPart,
1569 TRUE);
1570 }
1571
1572 if (!IsDiskSizeValid(PartitionList->CurrentPartition))
1573 {
1574 MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE, Ir, POPUP_WAIT_ANY_KEY,
1575 RequiredPartitionDiskSpace);
1576 return SELECT_PARTITION_PAGE; /* let the user select another partition */
1577 }
1578
1579 DestinationDriveLetter = (WCHAR)PartitionList->CurrentPartition->DriveLetter;
1580
1581 return SELECT_FILE_SYSTEM_PAGE;
1582 }
1583 }
1584 else
1585 {
1586 if (!IsDiskSizeValid(PartitionList->CurrentPartition))
1587 {
1588 MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE, Ir, POPUP_WAIT_ANY_KEY,
1589 RequiredPartitionDiskSpace);
1590 return SELECT_PARTITION_PAGE; /* let the user select another partition */
1591 }
1592
1593 DestinationDriveLetter = (WCHAR)PartitionList->CurrentPartition->DriveLetter;
1594
1595 return SELECT_FILE_SYSTEM_PAGE;
1596 }
1597 }
1598
1599 while (TRUE)
1600 {
1601 /* Update status text */
1602 if (PartitionList->CurrentPartition == NULL)
1603 {
1604 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATEPARTITION));
1605 }
1606 else if (PartitionList->CurrentPartition->LogicalPartition)
1607 {
1608 if (PartitionList->CurrentPartition->IsPartitioned)
1609 {
1610 CONSOLE_SetStatusText(MUIGetString(STRING_DELETEPARTITION));
1611 }
1612 else
1613 {
1614 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATELOGICAL));
1615 }
1616 }
1617 else
1618 {
1619 if (PartitionList->CurrentPartition->IsPartitioned)
1620 {
1621 if (IsContainerPartition(PartitionList->CurrentPartition->PartitionType))
1622 {
1623 CONSOLE_SetStatusText(MUIGetString(STRING_DELETEPARTITION));
1624 }
1625 else
1626 {
1627 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLDELETEPARTITION));
1628 }
1629 }
1630 else
1631 {
1632 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATEPARTITION));
1633 }
1634 }
1635
1636 CONSOLE_ConInKey(Ir);
1637
1638 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1639 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1640 {
1641 if (ConfirmQuit(Ir) != FALSE)
1642 {
1643 DestroyPartitionList(PartitionList);
1644 PartitionList = NULL;
1645 return QUIT_PAGE;
1646 }
1647
1648 break;
1649 }
1650 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1651 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1652 {
1653 if (ScrollDownPartitionList(PartitionList))
1654 DrawPartitionList(PartitionList);
1655 }
1656 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1657 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1658 {
1659 if (ScrollUpPartitionList(PartitionList))
1660 DrawPartitionList(PartitionList);
1661 }
1662 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
1663 {
1664 if (IsContainerPartition(PartitionList->CurrentPartition->PartitionType))
1665 continue; //return SELECT_PARTITION_PAGE;
1666
1667 if (PartitionList->CurrentPartition == NULL ||
1668 PartitionList->CurrentPartition->IsPartitioned == FALSE)
1669 {
1670 if (PartitionList->CurrentPartition->LogicalPartition)
1671 {
1672 CreateLogicalPartition(PartitionList,
1673 0ULL,
1674 TRUE);
1675 }
1676 else
1677 {
1678 CreatePrimaryPartition(PartitionList,
1679 0ULL,
1680 TRUE);
1681 }
1682 }
1683
1684 if (!IsDiskSizeValid(PartitionList->CurrentPartition))
1685 {
1686 MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE, Ir, POPUP_WAIT_ANY_KEY,
1687 RequiredPartitionDiskSpace);
1688 return SELECT_PARTITION_PAGE; /* let the user select another partition */
1689 }
1690
1691 DestinationDriveLetter = (WCHAR)PartitionList->CurrentPartition->DriveLetter;
1692
1693 return SELECT_FILE_SYSTEM_PAGE;
1694 }
1695 else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'P') /* P */
1696 {
1697 if (PartitionList->CurrentPartition->LogicalPartition == FALSE)
1698 {
1699 Error = PrimaryPartitionCreationChecks(PartitionList);
1700 if (Error != NOT_AN_ERROR)
1701 {
1702 MUIDisplayError(Error, Ir, POPUP_WAIT_ANY_KEY);
1703 return SELECT_PARTITION_PAGE;
1704 }
1705
1706 return CREATE_PRIMARY_PARTITION_PAGE;
1707 }
1708 }
1709 else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'E') /* E */
1710 {
1711 if (PartitionList->CurrentPartition->LogicalPartition == FALSE)
1712 {
1713 Error = ExtendedPartitionCreationChecks(PartitionList);
1714 if (Error != NOT_AN_ERROR)
1715 {
1716 MUIDisplayError(Error, Ir, POPUP_WAIT_ANY_KEY);
1717 return SELECT_PARTITION_PAGE;
1718 }
1719
1720 return CREATE_EXTENDED_PARTITION_PAGE;
1721 }
1722 }
1723 else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'L') /* L */
1724 {
1725 if (PartitionList->CurrentPartition->LogicalPartition != FALSE)
1726 {
1727 Error = LogicalPartitionCreationChecks(PartitionList);
1728 if (Error != NOT_AN_ERROR)
1729 {
1730 MUIDisplayError(Error, Ir, POPUP_WAIT_ANY_KEY);
1731 return SELECT_PARTITION_PAGE;
1732 }
1733
1734 return CREATE_LOGICAL_PARTITION_PAGE;
1735 }
1736 }
1737 else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'D') /* D */
1738 {
1739 if (PartitionList->CurrentPartition->IsPartitioned == FALSE)
1740 {
1741 MUIDisplayError(ERROR_DELETE_SPACE, Ir, POPUP_WAIT_ANY_KEY);
1742 return SELECT_PARTITION_PAGE;
1743 }
1744
1745 if (PartitionList->CurrentPartition->BootIndicator ||
1746 PartitionList->CurrentPartition == PartitionList->SystemPartition)
1747 {
1748 return CONFIRM_DELETE_SYSTEM_PARTITION_PAGE;
1749 }
1750
1751 return DELETE_PARTITION_PAGE;
1752 }
1753 }
1754
1755 return SELECT_PARTITION_PAGE;
1756 }
1757
1758
1759 #define PARTITION_SIZE_INPUT_FIELD_LENGTH 9
1760 /* Restriction for MaxSize: pow(10, (PARTITION_SIZE_INPUT_FIELD_LENGTH - 1)) - 1 */
1761 #define PARTITION_MAXSIZE (pow(10, (PARTITION_SIZE_INPUT_FIELD_LENGTH - 1)) - 1)
1762
1763 static VOID
1764 ShowPartitionSizeInputBox(SHORT Left,
1765 SHORT Top,
1766 SHORT Right,
1767 SHORT Bottom,
1768 ULONG MaxSize,
1769 PWSTR InputBuffer,
1770 PBOOLEAN Quit,
1771 PBOOLEAN Cancel)
1772 {
1773 INPUT_RECORD Ir;
1774 COORD coPos;
1775 DWORD Written;
1776 CHAR Buffer[128];
1777 INT Length, Pos;
1778 WCHAR ch;
1779 SHORT iLeft;
1780 SHORT iTop;
1781
1782 if (Quit != NULL)
1783 *Quit = FALSE;
1784
1785 if (Cancel != NULL)
1786 *Cancel = FALSE;
1787
1788 DrawBox(Left, Top, Right - Left + 1, Bottom - Top + 1);
1789
1790 /* Print message */
1791 coPos.X = Left + 2;
1792 coPos.Y = Top + 2;
1793 strcpy(Buffer, MUIGetString(STRING_PARTITIONSIZE));
1794 iLeft = coPos.X + strlen(Buffer) + 1;
1795 iTop = coPos.Y;
1796
1797 WriteConsoleOutputCharacterA(StdOutput,
1798 Buffer,
1799 strlen(Buffer),
1800 coPos,
1801 &Written);
1802
1803 sprintf(Buffer, MUIGetString(STRING_MAXSIZE), MaxSize);
1804 coPos.X = iLeft + PARTITION_SIZE_INPUT_FIELD_LENGTH + 1;
1805 coPos.Y = iTop;
1806 WriteConsoleOutputCharacterA(StdOutput,
1807 Buffer,
1808 strlen(Buffer),
1809 coPos,
1810 &Written);
1811
1812 swprintf(InputBuffer, L"%lu", MaxSize);
1813 Length = wcslen(InputBuffer);
1814 Pos = Length;
1815 CONSOLE_SetInputTextXY(iLeft,
1816 iTop,
1817 PARTITION_SIZE_INPUT_FIELD_LENGTH,
1818 InputBuffer);
1819 CONSOLE_SetCursorXY(iLeft + Length, iTop);
1820 CONSOLE_SetCursorType(TRUE, TRUE);
1821
1822 while (TRUE)
1823 {
1824 CONSOLE_ConInKey(&Ir);
1825
1826 if ((Ir.Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1827 (Ir.Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1828 {
1829 if (Quit != NULL)
1830 *Quit = TRUE;
1831
1832 InputBuffer[0] = UNICODE_NULL;
1833 CONSOLE_SetCursorType(TRUE, FALSE);
1834 break;
1835 }
1836 else if (Ir.Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
1837 {
1838 CONSOLE_SetCursorType(TRUE, FALSE);
1839 break;
1840 }
1841 else if (Ir.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESCAPE */
1842 {
1843 if (Cancel != NULL)
1844 *Cancel = TRUE;
1845
1846 InputBuffer[0] = UNICODE_NULL;
1847 CONSOLE_SetCursorType(TRUE, FALSE);
1848 break;
1849 }
1850 else if ((Ir.Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1851 (Ir.Event.KeyEvent.wVirtualKeyCode == VK_HOME)) /* HOME */
1852 {
1853 Pos = 0;
1854 CONSOLE_SetCursorXY(iLeft + Pos, iTop);
1855 }
1856 else if ((Ir.Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1857 (Ir.Event.KeyEvent.wVirtualKeyCode == VK_END)) /* END */
1858 {
1859 Pos = Length;
1860 CONSOLE_SetCursorXY(iLeft + Pos, iTop);
1861 }
1862 else if ((Ir.Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1863 (Ir.Event.KeyEvent.wVirtualKeyCode == VK_LEFT)) /* LEFT */
1864 {
1865 if (Pos > 0)
1866 {
1867 Pos--;
1868 CONSOLE_SetCursorXY(iLeft + Pos, iTop);
1869 }
1870 }
1871 else if ((Ir.Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1872 (Ir.Event.KeyEvent.wVirtualKeyCode == VK_RIGHT)) /* RIGHT */
1873 {
1874 if (Pos < Length)
1875 {
1876 Pos++;
1877 CONSOLE_SetCursorXY(iLeft + Pos, iTop);
1878 }
1879 }
1880 else if ((Ir.Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1881 (Ir.Event.KeyEvent.wVirtualKeyCode == VK_DELETE)) /* DEL */
1882 {
1883 if (Pos < Length)
1884 {
1885 memmove(&InputBuffer[Pos],
1886 &InputBuffer[Pos + 1],
1887 (Length - Pos - 1) * sizeof(WCHAR));
1888 InputBuffer[Length - 1] = UNICODE_NULL;
1889
1890 Length--;
1891 CONSOLE_SetInputTextXY(iLeft,
1892 iTop,
1893 PARTITION_SIZE_INPUT_FIELD_LENGTH,
1894 InputBuffer);
1895 CONSOLE_SetCursorXY(iLeft + Pos, iTop);
1896 }
1897 }
1898 else if (Ir.Event.KeyEvent.wVirtualKeyCode == VK_BACK) /* BACKSPACE */
1899 {
1900 if (Pos > 0)
1901 {
1902 if (Pos < Length)
1903 memmove(&InputBuffer[Pos - 1],
1904 &InputBuffer[Pos],
1905 (Length - Pos) * sizeof(WCHAR));
1906 InputBuffer[Length - 1] = UNICODE_NULL;
1907
1908 Pos--;
1909 Length--;
1910 CONSOLE_SetInputTextXY(iLeft,
1911 iTop,
1912 PARTITION_SIZE_INPUT_FIELD_LENGTH,
1913 InputBuffer);
1914 CONSOLE_SetCursorXY(iLeft + Pos, iTop);
1915 }
1916 }
1917 else if (Ir.Event.KeyEvent.uChar.AsciiChar != 0x00)
1918 {
1919 if (Length < PARTITION_SIZE_INPUT_FIELD_LENGTH - 1)
1920 {
1921 ch = (WCHAR)Ir.Event.KeyEvent.uChar.AsciiChar;
1922
1923 if ((ch >= L'0') && (ch <= L'9'))
1924 {
1925 if (Pos < Length)
1926 memmove(&InputBuffer[Pos + 1],
1927 &InputBuffer[Pos],
1928 (Length - Pos) * sizeof(WCHAR));
1929 InputBuffer[Length + 1] = UNICODE_NULL;
1930 InputBuffer[Pos] = ch;
1931
1932 Pos++;
1933 Length++;
1934 CONSOLE_SetInputTextXY(iLeft,
1935 iTop,
1936 PARTITION_SIZE_INPUT_FIELD_LENGTH,
1937 InputBuffer);
1938 CONSOLE_SetCursorXY(iLeft + Pos, iTop);
1939 }
1940 }
1941 }
1942 }
1943 }
1944
1945
1946 /*
1947 * Displays the CreatePrimaryPartitionPage.
1948 *
1949 * Next pages:
1950 * SelectPartitionPage
1951 * SelectFileSystemPage (default)
1952 * QuitPage
1953 *
1954 * RETURNS
1955 * Number of the next page.
1956 */
1957 static PAGE_NUMBER
1958 CreatePrimaryPartitionPage(PINPUT_RECORD Ir)
1959 {
1960 PDISKENTRY DiskEntry;
1961 PPARTENTRY PartEntry;
1962 BOOLEAN Quit;
1963 BOOLEAN Cancel;
1964 WCHAR InputBuffer[50];
1965 ULONG MaxSize;
1966 ULONGLONG PartSize;
1967 ULONGLONG DiskSize;
1968 ULONGLONG SectorCount;
1969 PCHAR Unit;
1970
1971 if (PartitionList == NULL ||
1972 PartitionList->CurrentDisk == NULL ||
1973 PartitionList->CurrentPartition == NULL)
1974 {
1975 /* FIXME: show an error dialog */
1976 return QUIT_PAGE;
1977 }
1978
1979 DiskEntry = PartitionList->CurrentDisk;
1980 PartEntry = PartitionList->CurrentPartition;
1981
1982 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
1983
1984 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSENEWPARTITION));
1985
1986 DiskSize = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
1987 #if 0
1988 if (DiskSize >= 10737418240) /* 10 GB */
1989 {
1990 DiskSize = DiskSize / 1073741824;
1991 Unit = MUIGetString(STRING_GB);
1992 }
1993 else
1994 #endif
1995 {
1996 DiskSize = DiskSize / 1048576;
1997 if (DiskSize == 0)
1998 DiskSize = 1;
1999
2000 Unit = MUIGetString(STRING_MB);
2001 }
2002
2003 if (DiskEntry->DriverName.Length > 0)
2004 {
2005 CONSOLE_PrintTextXY(6, 10,
2006 MUIGetString(STRING_HDINFOPARTCREATE),
2007 DiskSize,
2008 Unit,
2009 DiskEntry->DiskNumber,
2010 DiskEntry->Port,
2011 DiskEntry->Bus,
2012 DiskEntry->Id,
2013 &DiskEntry->DriverName);
2014 }
2015 else
2016 {
2017 CONSOLE_PrintTextXY(6, 10,
2018 MUIGetString(STRING_HDDINFOUNK1),
2019 DiskSize,
2020 Unit,
2021 DiskEntry->DiskNumber,
2022 DiskEntry->Port,
2023 DiskEntry->Bus,
2024 DiskEntry->Id);
2025 }
2026
2027 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE));
2028
2029 #if 0
2030 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2031 PartitionList->CurrentPartition->SectorCount * DiskEntry->BytesPerSector / 1048576);
2032 #endif
2033
2034 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION));
2035
2036 PartEntry = PartitionList->CurrentPartition;
2037 while (TRUE)
2038 {
2039 MaxSize = (PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector) / 1048576; /* in MBytes (rounded) */
2040
2041 if (MaxSize > PARTITION_MAXSIZE)
2042 MaxSize = PARTITION_MAXSIZE;
2043
2044 ShowPartitionSizeInputBox(12, 14, xScreen - 12, 17, /* left, top, right, bottom */
2045 MaxSize, InputBuffer, &Quit, &Cancel);
2046
2047 if (Quit != FALSE)
2048 {
2049 if (ConfirmQuit(Ir) != FALSE)
2050 return QUIT_PAGE;
2051
2052 break;
2053 }
2054 else if (Cancel != FALSE)
2055 {
2056 return SELECT_PARTITION_PAGE;
2057 }
2058 else
2059 {
2060 PartSize = _wcstoui64(InputBuffer, NULL, 10);
2061
2062 if (PartSize < 1)
2063 {
2064 /* Too small */
2065 continue;
2066 }
2067
2068 if (PartSize > MaxSize)
2069 {
2070 /* Too large */
2071 continue;
2072 }
2073
2074 /* Convert to bytes */
2075 if (PartSize == MaxSize)
2076 {
2077 /* Use all of the unpartitioned disk space */
2078 SectorCount = PartEntry->SectorCount.QuadPart;
2079 }
2080 else
2081 {
2082 /* Calculate the sector count from the size in MB */
2083 SectorCount = PartSize * 1048576 / DiskEntry->BytesPerSector;
2084
2085 /* But never get larger than the unpartitioned disk space */
2086 if (SectorCount > PartEntry->SectorCount.QuadPart)
2087 SectorCount = PartEntry->SectorCount.QuadPart;
2088 }
2089
2090 DPRINT ("Partition size: %I64u bytes\n", PartSize);
2091
2092 CreatePrimaryPartition(PartitionList,
2093 SectorCount,
2094 FALSE);
2095
2096 return SELECT_PARTITION_PAGE;
2097 }
2098 }
2099
2100 return CREATE_PRIMARY_PARTITION_PAGE;
2101 }
2102
2103
2104 /*
2105 * Displays the CreateExtendedPartitionPage.
2106 *
2107 * Next pages:
2108 * SelectPartitionPage (default)
2109 * QuitPage
2110 *
2111 * RETURNS
2112 * Number of the next page.
2113 */
2114 static PAGE_NUMBER
2115 CreateExtendedPartitionPage(PINPUT_RECORD Ir)
2116 {
2117 PDISKENTRY DiskEntry;
2118 PPARTENTRY PartEntry;
2119 BOOLEAN Quit;
2120 BOOLEAN Cancel;
2121 WCHAR InputBuffer[50];
2122 ULONG MaxSize;
2123 ULONGLONG PartSize;
2124 ULONGLONG DiskSize;
2125 ULONGLONG SectorCount;
2126 PCHAR Unit;
2127
2128 if (PartitionList == NULL ||
2129 PartitionList->CurrentDisk == NULL ||
2130 PartitionList->CurrentPartition == NULL)
2131 {
2132 /* FIXME: show an error dialog */
2133 return QUIT_PAGE;
2134 }
2135
2136 DiskEntry = PartitionList->CurrentDisk;
2137 PartEntry = PartitionList->CurrentPartition;
2138
2139 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
2140
2141 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSE_NEW_EXTENDED_PARTITION));
2142
2143 DiskSize = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
2144 #if 0
2145 if (DiskSize >= 10737418240) /* 10 GB */
2146 {
2147 DiskSize = DiskSize / 1073741824;
2148 Unit = MUIGetString(STRING_GB);
2149 }
2150 else
2151 #endif
2152 {
2153 DiskSize = DiskSize / 1048576;
2154 if (DiskSize == 0)
2155 DiskSize = 1;
2156
2157 Unit = MUIGetString(STRING_MB);
2158 }
2159
2160 if (DiskEntry->DriverName.Length > 0)
2161 {
2162 CONSOLE_PrintTextXY(6, 10,
2163 MUIGetString(STRING_HDINFOPARTCREATE),
2164 DiskSize,
2165 Unit,
2166 DiskEntry->DiskNumber,
2167 DiskEntry->Port,
2168 DiskEntry->Bus,
2169 DiskEntry->Id,
2170 &DiskEntry->DriverName);
2171 }
2172 else
2173 {
2174 CONSOLE_PrintTextXY(6, 10,
2175 MUIGetString(STRING_HDDINFOUNK1),
2176 DiskSize,
2177 Unit,
2178 DiskEntry->DiskNumber,
2179 DiskEntry->Port,
2180 DiskEntry->Bus,
2181 DiskEntry->Id);
2182 }
2183
2184 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE));
2185
2186 #if 0
2187 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2188 PartitionList->CurrentPartition->SectorCount * DiskEntry->BytesPerSector / 1048576);
2189 #endif
2190
2191 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION));
2192
2193 PartEntry = PartitionList->CurrentPartition;
2194 while (TRUE)
2195 {
2196 MaxSize = (PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector) / 1048576; /* in MBytes (rounded) */
2197
2198 if (MaxSize > PARTITION_MAXSIZE)
2199 MaxSize = PARTITION_MAXSIZE;
2200
2201 ShowPartitionSizeInputBox(12, 14, xScreen - 12, 17, /* left, top, right, bottom */
2202 MaxSize, InputBuffer, &Quit, &Cancel);
2203
2204 if (Quit != FALSE)
2205 {
2206 if (ConfirmQuit(Ir) != FALSE)
2207 return QUIT_PAGE;
2208
2209 break;
2210 }
2211 else if (Cancel != FALSE)
2212 {
2213 return SELECT_PARTITION_PAGE;
2214 }
2215 else
2216 {
2217 PartSize = _wcstoui64(InputBuffer, NULL, 10);
2218
2219 if (PartSize < 1)
2220 {
2221 /* Too small */
2222 continue;
2223 }
2224
2225 if (PartSize > MaxSize)
2226 {
2227 /* Too large */
2228 continue;
2229 }
2230
2231 /* Convert to bytes */
2232 if (PartSize == MaxSize)
2233 {
2234 /* Use all of the unpartitioned disk space */
2235 SectorCount = PartEntry->SectorCount.QuadPart;
2236 }
2237 else
2238 {
2239 /* Calculate the sector count from the size in MB */
2240 SectorCount = PartSize * 1048576 / DiskEntry->BytesPerSector;
2241
2242 /* But never get larger than the unpartitioned disk space */
2243 if (SectorCount > PartEntry->SectorCount.QuadPart)
2244 SectorCount = PartEntry->SectorCount.QuadPart;
2245 }
2246
2247 DPRINT ("Partition size: %I64u bytes\n", PartSize);
2248
2249 CreateExtendedPartition(PartitionList,
2250 SectorCount);
2251
2252 return SELECT_PARTITION_PAGE;
2253 }
2254 }
2255
2256 return CREATE_EXTENDED_PARTITION_PAGE;
2257 }
2258
2259
2260 /*
2261 * Displays the CreateLogicalPartitionPage.
2262 *
2263 * Next pages:
2264 * SelectFileSystemPage (default)
2265 * QuitPage
2266 *
2267 * RETURNS
2268 * Number of the next page.
2269 */
2270 static PAGE_NUMBER
2271 CreateLogicalPartitionPage(PINPUT_RECORD Ir)
2272 {
2273 PDISKENTRY DiskEntry;
2274 PPARTENTRY PartEntry;
2275 BOOLEAN Quit;
2276 BOOLEAN Cancel;
2277 WCHAR InputBuffer[50];
2278 ULONG MaxSize;
2279 ULONGLONG PartSize;
2280 ULONGLONG DiskSize;
2281 ULONGLONG SectorCount;
2282 PCHAR Unit;
2283
2284 if (PartitionList == NULL ||
2285 PartitionList->CurrentDisk == NULL ||
2286 PartitionList->CurrentPartition == NULL)
2287 {
2288 /* FIXME: show an error dialog */
2289 return QUIT_PAGE;
2290 }
2291
2292 DiskEntry = PartitionList->CurrentDisk;
2293 PartEntry = PartitionList->CurrentPartition;
2294
2295 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
2296
2297 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSE_NEW_LOGICAL_PARTITION));
2298
2299 DiskSize = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
2300 #if 0
2301 if (DiskSize >= 10737418240) /* 10 GB */
2302 {
2303 DiskSize = DiskSize / 1073741824;
2304 Unit = MUIGetString(STRING_GB);
2305 }
2306 else
2307 #endif
2308 {
2309 DiskSize = DiskSize / 1048576;
2310 if (DiskSize == 0)
2311 DiskSize = 1;
2312
2313 Unit = MUIGetString(STRING_MB);
2314 }
2315
2316 if (DiskEntry->DriverName.Length > 0)
2317 {
2318 CONSOLE_PrintTextXY(6, 10,
2319 MUIGetString(STRING_HDINFOPARTCREATE),
2320 DiskSize,
2321 Unit,
2322 DiskEntry->DiskNumber,
2323 DiskEntry->Port,
2324 DiskEntry->Bus,
2325 DiskEntry->Id,
2326 &DiskEntry->DriverName);
2327 }
2328 else
2329 {
2330 CONSOLE_PrintTextXY(6, 10,
2331 MUIGetString(STRING_HDDINFOUNK1),
2332 DiskSize,
2333 Unit,
2334 DiskEntry->DiskNumber,
2335 DiskEntry->Port,
2336 DiskEntry->Bus,
2337 DiskEntry->Id);
2338 }
2339
2340 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE));
2341
2342 #if 0
2343 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2344 PartitionList->CurrentPartition->SectorCount * DiskEntry->BytesPerSector / 1048576);
2345 #endif
2346
2347 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION));
2348
2349 PartEntry = PartitionList->CurrentPartition;
2350 while (TRUE)
2351 {
2352 MaxSize = (PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector) / 1048576; /* in MBytes (rounded) */
2353
2354 if (MaxSize > PARTITION_MAXSIZE)
2355 MaxSize = PARTITION_MAXSIZE;
2356
2357 ShowPartitionSizeInputBox(12, 14, xScreen - 12, 17, /* left, top, right, bottom */
2358 MaxSize, InputBuffer, &Quit, &Cancel);
2359
2360 if (Quit != FALSE)
2361 {
2362 if (ConfirmQuit(Ir) != FALSE)
2363 return QUIT_PAGE;
2364
2365 break;
2366 }
2367 else if (Cancel != FALSE)
2368 {
2369 return SELECT_PARTITION_PAGE;
2370 }
2371 else
2372 {
2373 PartSize = _wcstoui64(InputBuffer, NULL, 10);
2374
2375 if (PartSize < 1)
2376 {
2377 /* Too small */
2378 continue;
2379 }
2380
2381 if (PartSize > MaxSize)
2382 {
2383 /* Too large */
2384 continue;
2385 }
2386
2387 /* Convert to bytes */
2388 if (PartSize == MaxSize)
2389 {
2390 /* Use all of the unpartitioned disk space */
2391 SectorCount = PartEntry->SectorCount.QuadPart;
2392 }
2393 else
2394 {
2395 /* Calculate the sector count from the size in MB */
2396 SectorCount = PartSize * 1048576 / DiskEntry->BytesPerSector;
2397
2398 /* But never get larger than the unpartitioned disk space */
2399 if (SectorCount > PartEntry->SectorCount.QuadPart)
2400 SectorCount = PartEntry->SectorCount.QuadPart;
2401 }
2402
2403 DPRINT("Partition size: %I64u bytes\n", PartSize);
2404
2405 CreateLogicalPartition(PartitionList,
2406 SectorCount,
2407 FALSE);
2408
2409 return SELECT_PARTITION_PAGE;
2410 }
2411 }
2412
2413 return CREATE_LOGICAL_PARTITION_PAGE;
2414 }
2415
2416
2417 /*
2418 * Displays the ConfirmDeleteSystemPartitionPage.
2419 *
2420 * Next pages:
2421 * DeletePartitionPage (default)
2422 * SelectPartitionPage
2423 *
2424 * RETURNS
2425 * Number of the next page.
2426 */
2427 static PAGE_NUMBER
2428 ConfirmDeleteSystemPartitionPage(PINPUT_RECORD Ir)
2429 {
2430 MUIDisplayPage(CONFIRM_DELETE_SYSTEM_PARTITION_PAGE);
2431
2432 while (TRUE)
2433 {
2434 CONSOLE_ConInKey(Ir);
2435
2436 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2437 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
2438 {
2439 if (ConfirmQuit(Ir) == TRUE)
2440 return QUIT_PAGE;
2441
2442 break;
2443 }
2444 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
2445 {
2446 return DELETE_PARTITION_PAGE;
2447 }
2448 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESC */
2449 {
2450 return SELECT_PARTITION_PAGE;
2451 }
2452 }
2453
2454 return CONFIRM_DELETE_SYSTEM_PARTITION_PAGE;
2455 }
2456
2457
2458 /*
2459 * Displays the DeletePartitionPage.
2460 *
2461 * Next pages:
2462 * SelectPartitionPage (default)
2463 * QuitPage
2464 *
2465 * RETURNS
2466 * Number of the next page.
2467 */
2468 static PAGE_NUMBER
2469 DeletePartitionPage(PINPUT_RECORD Ir)
2470 {
2471 PDISKENTRY DiskEntry;
2472 PPARTENTRY PartEntry;
2473 ULONGLONG DiskSize;
2474 ULONGLONG PartSize;
2475 PCHAR Unit;
2476 CHAR PartTypeString[32];
2477
2478 if (PartitionList == NULL ||
2479 PartitionList->CurrentDisk == NULL ||
2480 PartitionList->CurrentPartition == NULL)
2481 {
2482 /* FIXME: show an error dialog */
2483 return QUIT_PAGE;
2484 }
2485
2486 DiskEntry = PartitionList->CurrentDisk;
2487 PartEntry = PartitionList->CurrentPartition;
2488
2489 MUIDisplayPage(DELETE_PARTITION_PAGE);
2490
2491 GetPartTypeStringFromPartitionType(PartEntry->PartitionType,
2492 PartTypeString,
2493 ARRAYSIZE(PartTypeString));
2494
2495 PartSize = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
2496 #if 0
2497 if (PartSize >= 10737418240) /* 10 GB */
2498 {
2499 PartSize = PartSize / 1073741824;
2500 Unit = MUIGetString(STRING_GB);
2501 }
2502 else
2503 #endif
2504 if (PartSize >= 10485760) /* 10 MB */
2505 {
2506 PartSize = PartSize / 1048576;
2507 Unit = MUIGetString(STRING_MB);
2508 }
2509 else
2510 {
2511 PartSize = PartSize / 1024;
2512 Unit = MUIGetString(STRING_KB);
2513 }
2514
2515 if (*PartTypeString == '\0') // STRING_FORMATUNKNOWN ??
2516 {
2517 CONSOLE_PrintTextXY(6, 10,
2518 MUIGetString(STRING_HDDINFOUNK2),
2519 (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
2520 (PartEntry->DriveLetter == 0) ? '-' : ':',
2521 PartEntry->PartitionType,
2522 PartSize,
2523 Unit);
2524 }
2525 else
2526 {
2527 CONSOLE_PrintTextXY(6, 10,
2528 " %c%c %s %I64u %s",
2529 (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
2530 (PartEntry->DriveLetter == 0) ? '-' : ':',
2531 PartTypeString,
2532 PartSize,
2533 Unit);
2534 }
2535
2536 DiskSize = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
2537 #if 0
2538 if (DiskSize >= 10737418240) /* 10 GB */
2539 {
2540 DiskSize = DiskSize / 1073741824;
2541 Unit = MUIGetString(STRING_GB);
2542 }
2543 else
2544 #endif
2545 {
2546 DiskSize = DiskSize / 1048576;
2547 if (DiskSize == 0)
2548 DiskSize = 1;
2549
2550 Unit = MUIGetString(STRING_MB);
2551 }
2552
2553 if (DiskEntry->DriverName.Length > 0)
2554 {
2555 CONSOLE_PrintTextXY(6, 12,
2556 MUIGetString(STRING_HDINFOPARTDELETE),
2557 DiskSize,
2558 Unit,
2559 DiskEntry->DiskNumber,
2560 DiskEntry->Port,
2561 DiskEntry->Bus,
2562 DiskEntry->Id,
2563 &DiskEntry->DriverName);
2564 }
2565 else
2566 {
2567 CONSOLE_PrintTextXY(6, 12,
2568 MUIGetString(STRING_HDDINFOUNK3),
2569 DiskSize,
2570 Unit,
2571 DiskEntry->DiskNumber,
2572 DiskEntry->Port,
2573 DiskEntry->Bus,
2574 DiskEntry->Id);
2575 }
2576
2577 while (TRUE)
2578 {
2579 CONSOLE_ConInKey(Ir);
2580
2581 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2582 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
2583 {
2584 if (ConfirmQuit(Ir) != FALSE)
2585 return QUIT_PAGE;
2586
2587 break;
2588 }
2589 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESC */
2590 {
2591 return SELECT_PARTITION_PAGE;
2592 }
2593 else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'D') /* D */
2594 {
2595 DeleteCurrentPartition(PartitionList);
2596
2597 return SELECT_PARTITION_PAGE;
2598 }
2599 }
2600
2601 return DELETE_PARTITION_PAGE;
2602 }
2603
2604
2605 /*
2606 * Displays the SelectFileSystemPage.
2607 *
2608 * Next pages:
2609 * CheckFileSystemPage (At once if RepairUpdate is selected)
2610 * CheckFileSystemPage (At once if Unattended and not UnattendFormatPartition)
2611 * FormatPartitionPage (At once if Unattended and UnattendFormatPartition)
2612 * SelectPartitionPage (If the user aborts)
2613 * FormatPartitionPage (Default)
2614 * QuitPage
2615 *
2616 * SIDEEFFECTS
2617 * Sets PartEntry->DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].PartitionType (via UpdatePartitionType)
2618 * Calls CheckActiveSystemPartition()
2619 *
2620 * RETURNS
2621 * Number of the next page.
2622 */
2623 static PAGE_NUMBER
2624 SelectFileSystemPage(PINPUT_RECORD Ir)
2625 {
2626 PDISKENTRY DiskEntry;
2627 PPARTENTRY PartEntry;
2628 ULONGLONG DiskSize;
2629 ULONGLONG PartSize;
2630 PCHAR DiskUnit;
2631 PCHAR PartUnit;
2632 CHAR PartTypeString[32];
2633 FORMATMACHINESTATE PreviousFormatState;
2634
2635 DPRINT("SelectFileSystemPage()\n");
2636
2637 if (PartitionList == NULL ||
2638 PartitionList->CurrentDisk == NULL ||
2639 PartitionList->CurrentPartition == NULL)
2640 {
2641 /* FIXME: show an error dialog */
2642 return QUIT_PAGE;
2643 }
2644
2645 /*** HACK! ***/
2646 if (FileSystemList == NULL)
2647 {
2648 FileSystemList = CreateFileSystemList(6, 26, PartitionList->CurrentPartition->New, L"FAT");
2649 if (FileSystemList == NULL)
2650 {
2651 /* FIXME: show an error dialog */
2652 return QUIT_PAGE;
2653 }
2654
2655 /* FIXME: Add file systems to list */
2656 }
2657
2658 /* Find or set the active system partition */
2659 CheckActiveSystemPartition(PartitionList, FileSystemList);
2660
2661 if (PartitionList->SystemDisk == NULL ||
2662 PartitionList->SystemPartition == NULL)
2663 {
2664 /* FIXME: show an error dialog */
2665 return QUIT_PAGE;
2666 }
2667
2668 PreviousFormatState = PartitionList->FormatState;
2669 switch (PartitionList->FormatState)
2670 {
2671 case Start:
2672 if (PartitionList->CurrentPartition != PartitionList->SystemPartition)
2673 {
2674 PartitionList->TempDisk = PartitionList->SystemDisk;
2675 PartitionList->TempPartition = PartitionList->SystemPartition;
2676 PartitionList->TempPartition->NeedsCheck = TRUE;
2677
2678 PartitionList->FormatState = FormatSystemPartition;
2679 DPRINT1("FormatState: Start --> FormatSystemPartition\n");
2680 }
2681 else
2682 {
2683 PartitionList->TempDisk = PartitionList->CurrentDisk;
2684 PartitionList->TempPartition = PartitionList->CurrentPartition;
2685 PartitionList->TempPartition->NeedsCheck = TRUE;
2686
2687 PartitionList->FormatState = FormatInstallPartition;
2688 DPRINT1("FormatState: Start --> FormatInstallPartition\n");
2689 }
2690 break;
2691
2692 case FormatSystemPartition:
2693 PartitionList->TempDisk = PartitionList->CurrentDisk;
2694 PartitionList->TempPartition = PartitionList->CurrentPartition;
2695 PartitionList->TempPartition->NeedsCheck = TRUE;
2696
2697 PartitionList->FormatState = FormatInstallPartition;
2698 DPRINT1("FormatState: FormatSystemPartition --> FormatInstallPartition\n");
2699 break;
2700
2701 case FormatInstallPartition:
2702 if (GetNextUnformattedPartition(PartitionList,
2703 &PartitionList->TempDisk,
2704 &PartitionList->TempPartition))
2705 {
2706 PartitionList->FormatState = FormatOtherPartition;
2707 PartitionList->TempPartition->NeedsCheck = TRUE;
2708 DPRINT1("FormatState: FormatInstallPartition --> FormatOtherPartition\n");
2709 }
2710 else
2711 {
2712 PartitionList->FormatState = FormatDone;
2713 DPRINT1("FormatState: FormatInstallPartition --> FormatDone\n");
2714 return CHECK_FILE_SYSTEM_PAGE;
2715 }
2716 break;
2717
2718 case FormatOtherPartition:
2719 if (GetNextUnformattedPartition(PartitionList,
2720 &PartitionList->TempDisk,
2721 &PartitionList->TempPartition))
2722 {
2723 PartitionList->FormatState = FormatOtherPartition;
2724 PartitionList->TempPartition->NeedsCheck = TRUE;
2725 DPRINT1("FormatState: FormatOtherPartition --> FormatOtherPartition\n");
2726 }
2727 else
2728 {
2729 PartitionList->FormatState = FormatDone;
2730 DPRINT1("FormatState: FormatOtherPartition --> FormatDone\n");
2731 return CHECK_FILE_SYSTEM_PAGE;
2732 }
2733 break;
2734
2735 default:
2736 DPRINT1("FormatState: Invalid value %ld\n", PartitionList->FormatState);
2737 /* FIXME: show an error dialog */
2738 return QUIT_PAGE;
2739 }
2740
2741 DiskEntry = PartitionList->TempDisk;
2742 PartEntry = PartitionList->TempPartition;
2743
2744 /* adjust disk size */
2745 DiskSize = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
2746 if (DiskSize >= 10737418240) /* 10 GB */
2747 {
2748 DiskSize = DiskSize / 1073741824;
2749 DiskUnit = MUIGetString(STRING_GB);
2750 }
2751 else
2752 {
2753 DiskSize = DiskSize / 1048576;
2754 DiskUnit = MUIGetString(STRING_MB);
2755 }
2756
2757 /* adjust partition size */
2758 PartSize = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
2759 if (PartSize >= 10737418240) /* 10 GB */
2760 {
2761 PartSize = PartSize / 1073741824;
2762 PartUnit = MUIGetString(STRING_GB);
2763 }
2764 else
2765 {
2766 PartSize = PartSize / 1048576;
2767 PartUnit = MUIGetString(STRING_MB);
2768 }
2769
2770 /* adjust partition type */
2771 GetPartTypeStringFromPartitionType(PartEntry->PartitionType,
2772 PartTypeString,
2773 ARRAYSIZE(PartTypeString));
2774
2775 if (PartEntry->AutoCreate != FALSE)
2776 {
2777 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NEWPARTITION));
2778
2779 #if 0
2780 CONSOLE_PrintTextXY(8, 10, "Partition %lu (%I64u %s) %s of",
2781 PartEntry->PartitionNumber,
2782 PartSize,
2783 PartUnit,
2784 PartTypeString);
2785 #endif
2786
2787 CONSOLE_PrintTextXY(8, 10, MUIGetString(STRING_HDINFOPARTZEROED),
2788 DiskEntry->DiskNumber,
2789 DiskSize,
2790 DiskUnit,
2791 DiskEntry->Port,
2792 DiskEntry->Bus,
2793 DiskEntry->Id,
2794 &DiskEntry->DriverName);
2795
2796 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_PARTFORMAT));
2797
2798
2799 PartEntry->AutoCreate = FALSE;
2800 }
2801 else if (PartEntry->New != FALSE)
2802 {
2803 switch (PartitionList->FormatState)
2804 {
2805 case FormatSystemPartition:
2806 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDSYSTEMPART));
2807 break;
2808
2809 case FormatInstallPartition:
2810 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDPART));
2811 break;
2812
2813 case FormatOtherPartition:
2814 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDOTHERPART));
2815 break;
2816
2817 default:
2818 break;
2819 }
2820
2821 CONSOLE_SetTextXY(6, 10, MUIGetString(STRING_PARTFORMAT));
2822 }
2823 else
2824 {
2825 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_INSTALLONPART));
2826
2827 if (*PartTypeString == '\0') // STRING_FORMATUNKNOWN ??
2828 {
2829 CONSOLE_PrintTextXY(8, 10,
2830 MUIGetString(STRING_HDDINFOUNK4),
2831 (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
2832 (PartEntry->DriveLetter == 0) ? '-' : ':',
2833 PartEntry->PartitionType,
2834 PartSize,
2835 PartUnit);
2836 }
2837 else
2838 {
2839 CONSOLE_PrintTextXY(8, 10,
2840 "%c%c %s %I64u %s",
2841 (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
2842 (PartEntry->DriveLetter == 0) ? '-' : ':',
2843 PartTypeString,
2844 PartSize,
2845 PartUnit);
2846 }
2847
2848 CONSOLE_PrintTextXY(6, 12, MUIGetString(STRING_HDINFOPARTEXISTS),
2849 DiskEntry->DiskNumber,
2850 DiskSize,
2851 DiskUnit,
2852 DiskEntry->Port,
2853 DiskEntry->Bus,
2854 DiskEntry->Id,
2855 &DiskEntry->DriverName);
2856 }
2857
2858 MUIDisplayPage(SELECT_FILE_SYSTEM_PAGE);
2859
2860 if (FileSystemList == NULL)
2861 {
2862 FileSystemList = CreateFileSystemList(6, 26, PartEntry->New, L"FAT");
2863 if (FileSystemList == NULL)
2864 {
2865 /* FIXME: show an error dialog */
2866 return QUIT_PAGE;
2867 }
2868
2869 /* FIXME: Add file systems to list */
2870 }
2871
2872 DrawFileSystemList(FileSystemList);
2873
2874 if (RepairUpdateFlag)
2875 {
2876 return CHECK_FILE_SYSTEM_PAGE;
2877 //return SELECT_PARTITION_PAGE;
2878 }
2879
2880 if (IsUnattendedSetup)
2881 {
2882 if (UnattendFormatPartition)
2883 {
2884 PartEntry->FileSystem = GetFileSystemByName(FileSystemList, L"FAT");
2885 return FORMAT_PARTITION_PAGE;
2886 }
2887
2888 return CHECK_FILE_SYSTEM_PAGE;
2889 }
2890
2891 while (TRUE)
2892 {
2893 CONSOLE_ConInKey(Ir);
2894
2895 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2896 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
2897 {
2898 if (ConfirmQuit(Ir) != FALSE)
2899 return QUIT_PAGE;
2900
2901 break;
2902 }
2903 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2904 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
2905 {
2906 PartitionList->FormatState = Start;
2907 return SELECT_PARTITION_PAGE;
2908 }
2909 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2910 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
2911 {
2912 ScrollDownFileSystemList(FileSystemList);
2913 }
2914 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2915 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
2916 {
2917 ScrollUpFileSystemList(FileSystemList);
2918 }
2919 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
2920 {
2921 if (!FileSystemList->Selected->FormatFunc)
2922 {
2923 return SELECT_FILE_SYSTEM_PAGE;
2924 }
2925 else
2926 {
2927 PartEntry->FileSystem = FileSystemList->Selected;
2928 return FORMAT_PARTITION_PAGE;
2929 }
2930 }
2931 }
2932
2933 PartitionList->FormatState = PreviousFormatState;
2934
2935 return SELECT_FILE_SYSTEM_PAGE;
2936 }
2937
2938
2939 /*
2940 * Displays the FormatPartitionPage.
2941 *
2942 * Next pages:
2943 * InstallDirectoryPage (At once if IsUnattendedSetup or InstallShortcut)
2944 * SelectPartitionPage (At once)
2945 * QuitPage
2946 *
2947 * SIDEEFFECTS
2948 * Sets PartitionList->CurrentPartition->FormatState
2949 * Sets DestinationRootPath
2950 *
2951 * RETURNS
2952 * Number of the next page.
2953 */
2954 static ULONG
2955 FormatPartitionPage(PINPUT_RECORD Ir)
2956 {
2957 UNICODE_STRING PartitionRootPath;
2958 WCHAR PathBuffer[MAX_PATH];
2959 PDISKENTRY DiskEntry;
2960 PPARTENTRY PartEntry;
2961 NTSTATUS Status;
2962
2963 #ifndef NDEBUG
2964 ULONG Line;
2965 ULONG i;
2966 PPARTITION_INFORMATION PartitionInfo;
2967 #endif
2968
2969 DPRINT("FormatPartitionPage()\n");
2970
2971 MUIDisplayPage(FORMAT_PARTITION_PAGE);
2972
2973 if (PartitionList == NULL ||
2974 PartitionList->TempDisk == NULL ||
2975 PartitionList->TempPartition == NULL)
2976 {
2977 /* FIXME: show an error dialog */
2978 return QUIT_PAGE;
2979 }
2980
2981 DiskEntry = PartitionList->TempDisk;
2982 PartEntry = PartitionList->TempPartition;
2983
2984 while (TRUE)
2985 {
2986 if (!IsUnattendedSetup)
2987 {
2988 CONSOLE_ConInKey(Ir);
2989 }
2990
2991 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2992 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
2993 {
2994 if (ConfirmQuit(Ir) != FALSE)
2995 return QUIT_PAGE;
2996
2997 break;
2998 }
2999 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN || IsUnattendedSetup) /* ENTER */
3000 {
3001 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
3002
3003 if (wcscmp(PartEntry->FileSystem->FileSystemName, L"FAT") == 0)
3004 {
3005 if (PartEntry->SectorCount.QuadPart < 8192)
3006 {
3007 /* FAT12 CHS partition (disk is smaller than 4.1MB) */
3008 PartEntry->PartitionType = PARTITION_FAT_12;
3009 }
3010 else if (PartEntry->StartSector.QuadPart < 1450560)
3011 {
3012 /* Partition starts below the 8.4GB boundary ==> CHS partition */
3013
3014 if (PartEntry->SectorCount.QuadPart < 65536)
3015 {
3016 /* FAT16 CHS partition (partition size < 32MB) */
3017 PartEntry->PartitionType = PARTITION_FAT_16;
3018 }
3019 else if (PartEntry->SectorCount.QuadPart < 1048576)
3020 {
3021 /* FAT16 CHS partition (partition size < 512MB) */
3022 PartEntry->PartitionType = PARTITION_HUGE;
3023 }
3024 else
3025 {
3026 /* FAT32 CHS partition (partition size >= 512MB) */
3027 PartEntry->PartitionType = PARTITION_FAT32;
3028 }
3029 }
3030 else
3031 {
3032 /* Partition starts above the 8.4GB boundary ==> LBA partition */
3033
3034 if (PartEntry->SectorCount.QuadPart < 1048576)
3035 {
3036 /* FAT16 LBA partition (partition size < 512MB) */
3037 PartEntry->PartitionType = PARTITION_XINT13;
3038 }
3039 else
3040 {
3041 /* FAT32 LBA partition (partition size >= 512MB) */
3042 PartEntry->PartitionType = PARTITION_FAT32_XINT13;
3043 }
3044 }
3045
3046 DiskEntry->Dirty = TRUE;
3047 DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].PartitionType = PartEntry->PartitionType;
3048 DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].RewritePartition = TRUE;
3049 }
3050 #if 0
3051 else if (wcscmp(PartEntry->FileSystem->FileSystemName, L"EXT2") == 0)
3052 {
3053 PartEntry->PartitionType = PARTITION_EXT2;
3054
3055 DiskEntry->Dirty = TRUE;
3056 DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].PartitionType = PartEntry->PartitionType;
3057 DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].RewritePartition = TRUE;
3058 }
3059 else if (wcscmp(PartEntry->FileSystem->FileSystemName, L"NTFS") == 0)
3060 {
3061 PartEntry->PartitionType = PARTITION_IFS;
3062
3063 DiskEntry->Dirty = TRUE;
3064 DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].PartitionType = PartEntry->PartitionType;
3065 DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].RewritePartition = TRUE;
3066 }
3067 #endif
3068 else if (!PartEntry->FileSystem->FormatFunc)
3069 {
3070 /* FIXME: show an error dialog */
3071 return QUIT_PAGE;
3072 }
3073
3074 #ifndef NDEBUG
3075 CONSOLE_PrintTextXY(6, 12,
3076 "Cylinders: %I64u Tracks/Cyl: %lu Sectors/Trk: %lu Bytes/Sec: %lu %c",
3077 DiskEntry->Cylinders,
3078 DiskEntry->TracksPerCylinder,
3079 DiskEntry->SectorsPerTrack,
3080 DiskEntry->BytesPerSector,
3081 DiskEntry->Dirty ? '*' : ' ');
3082
3083 Line = 13;
3084
3085 for (i = 0; i < DiskEntry->LayoutBuffer->PartitionCount; i++)
3086 {
3087 PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[i];
3088
3089 CONSOLE_PrintTextXY(6, Line,
3090 "%2u: %2lu %c %12I64u %12I64u %02x",
3091 i,
3092 PartitionInfo->PartitionNumber,
3093 PartitionInfo->BootIndicator ? 'A' : '-',
3094 PartitionInfo->StartingOffset.QuadPart / DiskEntry->BytesPerSector,
3095 PartitionInfo->PartitionLength.QuadPart / DiskEntry->BytesPerSector,
3096 PartitionInfo->PartitionType);
3097 Line++;
3098 }
3099 #endif
3100
3101 if (WritePartitionsToDisk(PartitionList) == FALSE)
3102 {
3103 DPRINT("WritePartitionsToDisk() failed\n");
3104 MUIDisplayError(ERROR_WRITE_PTABLE, Ir, POPUP_WAIT_ENTER);
3105 return QUIT_PAGE;
3106 }
3107
3108 /* Set PartitionRootPath */
3109 swprintf(PathBuffer,
3110 L"\\Device\\Harddisk%lu\\Partition%lu",
3111 DiskEntry->DiskNumber,
3112 PartEntry->PartitionNumber);
3113 RtlInitUnicodeString(&PartitionRootPath,
3114 PathBuffer);
3115 DPRINT("PartitionRootPath: %wZ\n", &PartitionRootPath);
3116
3117 if (PartEntry->FileSystem->FormatFunc)
3118 {
3119 Status = FormatPartition(&PartitionRootPath,
3120 PartEntry->FileSystem);
3121 if (!NT_SUCCESS(Status))
3122 {
3123 DPRINT1("FormatPartition() failed with status 0x%08lx\n", Status);
3124 MUIDisplayError(ERROR_FORMATTING_PARTITION, Ir, POPUP_WAIT_ANY_KEY, PathBuffer);
3125 return QUIT_PAGE;
3126 }
3127
3128 PartEntry->New = FALSE;
3129 }
3130
3131 #ifndef NDEBUG
3132 CONSOLE_SetStatusText(" Done. Press any key ...");
3133 CONSOLE_ConInKey(Ir);
3134 #endif
3135
3136 return SELECT_FILE_SYSTEM_PAGE;
3137 }
3138 }
3139
3140 return FORMAT_PARTITION_PAGE;
3141 }
3142
3143
3144 /*
3145 * Displays the CheckFileSystemPage.
3146 *
3147 * Next pages:
3148 * InstallDirectoryPage (At once)
3149 * QuitPage
3150 *
3151 * SIDEEFFECTS
3152 * Inits or reloads FileSystemList
3153 *
3154 * RETURNS
3155 * Number of the next page.
3156 */
3157 static ULONG
3158 CheckFileSystemPage(PINPUT_RECORD Ir)
3159 {
3160 PFILE_SYSTEM_ITEM CurrentFileSystem;
3161 UNICODE_STRING PartitionRootPath;
3162 WCHAR PathBuffer[MAX_PATH];
3163 CHAR Buffer[MAX_PATH];
3164 PDISKENTRY DiskEntry;
3165 PPARTENTRY PartEntry;
3166 NTSTATUS Status;
3167
3168 if (PartitionList == NULL)
3169 {
3170 /* FIXME: show an error dialog */
3171 return QUIT_PAGE;
3172 }
3173
3174 if (!GetNextUncheckedPartition(PartitionList, &DiskEntry, &PartEntry))
3175 {
3176 return INSTALL_DIRECTORY_PAGE;
3177 }
3178
3179 /* Set PartitionRootPath */
3180 swprintf(PathBuffer,
3181 L"\\Device\\Harddisk%lu\\Partition%lu",
3182 DiskEntry->DiskNumber,
3183 PartEntry->PartitionNumber);
3184 RtlInitUnicodeString(&PartitionRootPath, PathBuffer);
3185 DPRINT("PartitionRootPath: %wZ\n", &PartitionRootPath);
3186
3187 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHECKINGPART));
3188
3189 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
3190
3191 CurrentFileSystem = GetFileSystem(FileSystemList, PartEntry);
3192 DPRINT1("CheckFileSystemPage -- PartitionType: 0x%02X ; FileSystemName: %S\n",
3193 PartEntry->PartitionType, (CurrentFileSystem ? CurrentFileSystem->FileSystemName : L"n/a"));
3194
3195 /* HACK: Do not try to check a partition with an unknown filesystem */
3196 if (CurrentFileSystem == NULL)
3197 {
3198 PartEntry->NeedsCheck = FALSE;
3199 return CHECK_FILE_SYSTEM_PAGE;
3200 }
3201
3202 if (CurrentFileSystem->ChkdskFunc == NULL)
3203 {
3204 sprintf(Buffer,
3205 "Setup is currently unable to check a partition formatted in %S.\n"
3206 "\n"
3207 " \x07 Press ENTER to continue Setup.\n"
3208 " \x07 Press F3 to quit Setup.",
3209 CurrentFileSystem->FileSystemName);
3210
3211 PopupError(Buffer,
3212 MUIGetString(STRING_QUITCONTINUE),
3213 NULL, POPUP_WAIT_NONE);
3214
3215 while (TRUE)
3216 {
3217 CONSOLE_ConInKey(Ir);
3218
3219 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x00 &&
3220 Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3) /* F3 */
3221 {
3222 if (ConfirmQuit(Ir))
3223 return QUIT_PAGE;
3224 else
3225 return CHECK_FILE_SYSTEM_PAGE;
3226 }
3227 else if (Ir->Event.KeyEvent.uChar.AsciiChar == VK_RETURN) /* ENTER */
3228 {
3229 PartEntry->NeedsCheck = FALSE;
3230 return CHECK_FILE_SYSTEM_PAGE;
3231 }
3232 }
3233 }
3234 else
3235 {
3236 Status = ChkdskPartition(&PartitionRootPath, CurrentFileSystem);
3237 if (!NT_SUCCESS(Status))
3238 {
3239 DPRINT("ChkdskPartition() failed with status 0x%08lx\n", Status);
3240 // sprintf(Buffer, "Setup failed to verify the selected partition.\n"
3241 sprintf(Buffer, "ChkDsk detected some disk errors.\n"
3242 "(Status 0x%08lx).\n", Status);
3243 PopupError(Buffer,
3244 // MUIGetString(STRING_REBOOTCOMPUTER),
3245 MUIGetString(STRING_CONTINUE),
3246 Ir, POPUP_WAIT_ENTER);
3247
3248 // return QUIT_PAGE;
3249 }
3250
3251 PartEntry->NeedsCheck = FALSE;
3252 return CHECK_FILE_SYSTEM_PAGE;
3253 }
3254 }
3255
3256
3257 static
3258 VOID
3259 BuildInstallPaths(PWCHAR InstallDir,
3260 PDISKENTRY DiskEntry,
3261 PPARTENTRY PartEntry)
3262 {
3263 WCHAR PathBuffer[MAX_PATH];
3264
3265 /* Create 'InstallPath' string */
3266 RtlFreeUnicodeString(&InstallPath);
3267 RtlCreateUnicodeString(&InstallPath, InstallDir);
3268
3269 /* Create 'DestinationRootPath' string */
3270 RtlFreeUnicodeString(&DestinationRootPath);
3271 swprintf(PathBuffer,
3272 L"\\Device\\Harddisk%lu\\Partition%lu",
3273 DiskEntry->DiskNumber,
3274 PartEntry->PartitionNumber);
3275 RtlCreateUnicodeString(&DestinationRootPath, PathBuffer);
3276 DPRINT("DestinationRootPath: %wZ\n", &DestinationRootPath);
3277
3278 /* Create 'DestinationPath' string */
3279 RtlFreeUnicodeString(&DestinationPath);
3280 wcscpy(PathBuffer, DestinationRootPath.Buffer);
3281
3282 if (InstallDir[0] != L'\\')
3283 wcscat(PathBuffer, L"\\");
3284
3285 wcscat(PathBuffer, InstallDir);
3286 RtlCreateUnicodeString(&DestinationPath, PathBuffer);
3287
3288 /* Create 'DestinationArcPath' */
3289 RtlFreeUnicodeString(&DestinationArcPath);
3290 swprintf(PathBuffer,
3291 L"multi(0)disk(0)rdisk(%lu)partition(%lu)",
3292 DiskEntry->BiosDiskNumber,
3293 PartEntry->PartitionNumber);
3294
3295 if (InstallDir[0] != L'\\')
3296 wcscat(PathBuffer, L"\\");
3297
3298 wcscat(PathBuffer, InstallDir);
3299 RtlCreateUnicodeString(&DestinationArcPath, PathBuffer);
3300 }
3301
3302
3303 /*
3304 * Displays the InstallDirectoryPage.
3305 *
3306 * Next pages:
3307 * PrepareCopyPage (As the direct result of InstallDirectoryPage1)
3308 * QuitPage
3309 *
3310 * RETURNS
3311 * Number of the next page.
3312 */
3313 static PAGE_NUMBER
3314 InstallDirectoryPage(PINPUT_RECORD Ir)
3315 {
3316 PDISKENTRY DiskEntry;
3317 PPARTENTRY PartEntry;
3318 WCHAR InstallDir[51];
3319 WCHAR c;
3320 ULONG Length, Pos;
3321
3322 /* We do not need the filesystem list any more */
3323 if (FileSystemList != NULL)
3324 {
3325 DestroyFileSystemList(FileSystemList);
3326 FileSystemList = NULL;
3327 }
3328
3329 if (PartitionList == NULL ||
3330 PartitionList->CurrentDisk == NULL ||
3331 PartitionList->CurrentPartition == NULL)
3332 {
3333 /* FIXME: show an error dialog */
3334 return QUIT_PAGE;
3335 }
3336
3337 DiskEntry = PartitionList->CurrentDisk;
3338 PartEntry = PartitionList->CurrentPartition;
3339
3340 if (IsUnattendedSetup)
3341 {
3342 if (!IsValidPath(UnattendInstallationDirectory))
3343 {
3344 /* FIXME: Log the error? */
3345 return QUIT_PAGE;
3346 }
3347
3348 BuildInstallPaths(UnattendInstallationDirectory,
3349 DiskEntry,
3350 PartEntry);
3351
3352 return PREPARE_COPY_PAGE;
3353 }
3354
3355 wcscpy(InstallDir, L"\\ReactOS");
3356
3357 Length = wcslen(InstallDir);
3358 Pos = Length;
3359 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
3360 CONSOLE_SetCursorXY(8 + Pos, 11);
3361 CONSOLE_SetCursorType(TRUE, TRUE);
3362 MUIDisplayPage(INSTALL_DIRECTORY_PAGE);
3363
3364 while (TRUE)
3365 {
3366 CONSOLE_ConInKey(Ir);
3367
3368 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3369 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
3370 {
3371 CONSOLE_SetCursorType(TRUE, FALSE);
3372
3373 if (ConfirmQuit(Ir) != FALSE)
3374 return QUIT_PAGE;
3375
3376 CONSOLE_SetCursorType(TRUE, TRUE);
3377 break;
3378 }
3379 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3380 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DELETE)) /* DEL */
3381 {
3382 if (Pos < Length)
3383 {
3384 memmove(&InstallDir[Pos],
3385 &InstallDir[Pos + 1],
3386 (Length - Pos - 1) * sizeof(WCHAR));
3387 InstallDir[Length - 1] = UNICODE_NULL;
3388
3389 Length--;
3390 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
3391 CONSOLE_SetCursorXY(8 + Pos, 11);
3392 }
3393 }
3394 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3395 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_HOME)) /* HOME */
3396 {
3397 Pos = 0;
3398 CONSOLE_SetCursorXY(8 + Pos, 11);
3399 }
3400 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3401 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_END)) /* END */
3402 {
3403 Pos = Length;
3404 CONSOLE_SetCursorXY(8 + Pos, 11);
3405 }
3406 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3407 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_LEFT)) /* LEFT */
3408 {
3409 if (Pos > 0)
3410 {
3411 Pos--;
3412 CONSOLE_SetCursorXY(8 + Pos, 11);
3413 }
3414 }
3415 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3416 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RIGHT)) /* RIGHT */
3417 {
3418 if (Pos < Length)
3419 {
3420 Pos++;
3421 CONSOLE_SetCursorXY(8 + Pos, 11);
3422 }
3423 }
3424 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
3425 {
3426 CONSOLE_SetCursorType(TRUE, FALSE);
3427
3428 /*
3429 * Check for the validity of the installation directory and pop up
3430 * an error if it is not the case. Then the user can fix its input.
3431 */
3432 if (!IsValidPath(InstallDir))
3433 {
3434 MUIDisplayError(ERROR_DIRECTORY_NAME, Ir, POPUP_WAIT_ENTER);
3435 return INSTALL_DIRECTORY_PAGE;
3436 }
3437
3438 BuildInstallPaths(InstallDir,
3439 DiskEntry,
3440 PartEntry);
3441
3442 return PREPARE_COPY_PAGE;
3443 }
3444 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x08) /* BACKSPACE */
3445 {
3446 if (Pos > 0)
3447 {
3448 if (Pos < Length)
3449 memmove(&InstallDir[Pos - 1],
3450 &InstallDir[Pos],
3451 (Length - Pos) * sizeof(WCHAR));
3452 InstallDir[Length - 1] = UNICODE_NULL;
3453
3454 Pos--;
3455 Length--;
3456 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
3457 CONSOLE_SetCursorXY(8 + Pos, 11);
3458 }
3459 }
3460 else if (isprint(Ir->Event.KeyEvent.uChar.AsciiChar))
3461 {
3462 if (Length < 50)
3463 {
3464 c = (WCHAR)Ir->Event.KeyEvent.uChar.AsciiChar;
3465 if (iswalpha(c) || iswdigit(c) || c == '.' || c == '\\' || c == '-' || c == '_')
3466 {
3467 if (Pos < Length)
3468 memmove(&InstallDir[Pos + 1],
3469 &InstallDir[Pos],
3470 (Length - Pos) * sizeof(WCHAR));
3471 InstallDir[Length + 1] = UNICODE_NULL;
3472 InstallDir[Pos] = c;
3473
3474 Pos++;
3475 Length++;
3476 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
3477 CONSOLE_SetCursorXY(8 + Pos, 11);
3478 }
3479 }
3480 }
3481 }
3482
3483 return INSTALL_DIRECTORY_PAGE;
3484 }
3485
3486
3487 static BOOLEAN
3488 AddSectionToCopyQueueCab(HINF InfFile,
3489 PWCHAR SectionName,
3490 PWCHAR SourceCabinet,
3491 PCUNICODE_STRING DestinationPath,
3492 PINPUT_RECORD Ir)
3493 {
3494 INFCONTEXT FilesContext;
3495 INFCONTEXT DirContext;
3496 PWCHAR FileKeyName;
3497 PWCHAR FileKeyValue;
3498 PWCHAR DirKeyValue;
3499 PWCHAR TargetFileName;
3500
3501 /* Search for the SectionName section */
3502 if (!SetupFindFirstLineW(InfFile, SectionName, NULL, &FilesContext))
3503 {
3504 char Buffer[128];
3505 sprintf(Buffer, MUIGetString(STRING_TXTSETUPFAILED), SectionName);
3506 PopupError(Buffer, MUIGetString(STRING_REBOOTCOMPUTER), Ir, POPUP_WAIT_ENTER);
3507 return FALSE;
3508 }
3509
3510 /*
3511 * Enumerate the files in the section
3512 * and add them to the file queue.
3513 */
3514 do
3515 {
3516 /* Get source file name and target directory id */
3517 if (!INF_GetData(&FilesContext, &FileKeyName, &FileKeyValue))
3518 {
3519 /* FIXME: Handle error! */
3520 DPRINT1("INF_GetData() failed\n");
3521 break;
3522 }
3523
3524 /* Get optional target file name */
3525 if (!INF_GetDataField(&FilesContext, 2, &TargetFileName))
3526 TargetFileName = NULL;
3527
3528 DPRINT("FileKeyName: '%S' FileKeyValue: '%S'\n", FileKeyName, FileKeyValue);
3529
3530 /* Lookup target directory */
3531 if (!SetupFindFirstLineW(InfFile, L"Directories", FileKeyValue, &DirContext))
3532 {
3533 /* FIXME: Handle error! */
3534 DPRINT1("SetupFindFirstLine() failed\n");
3535 break;
3536 }
3537
3538 if (!INF_GetData(&DirContext, NULL, &DirKeyValue))
3539 {
3540 /* FIXME: Handle error! */
3541 DPRINT1("INF_GetData() failed\n");
3542 break;
3543 }
3544
3545 if (!SetupQueueCopy(SetupFileQueue,
3546 SourceCabinet,
3547 SourceRootPath.Buffer,
3548 SourceRootDir.Buffer,
3549 FileKeyName,
3550 DirKeyValue,
3551 TargetFileName))
3552 {
3553 /* FIXME: Handle error! */
3554 DPRINT1("SetupQueueCopy() failed\n");
3555 }
3556 } while (SetupFindNextLine(&FilesContext, &FilesContext));
3557
3558 return TRUE;
3559 }
3560
3561
3562 static BOOLEAN
3563 AddSectionToCopyQueue(HINF InfFile,
3564 PWCHAR SectionName,
3565 PWCHAR SourceCabinet,
3566 PCUNICODE_STRING DestinationPath,
3567 PINPUT_RECORD Ir)
3568 {
3569 INFCONTEXT FilesContext;
3570 INFCONTEXT DirContext;
3571 PWCHAR FileKeyName;
3572 PWCHAR FileKeyValue;
3573 PWCHAR DirKeyValue;
3574 PWCHAR TargetFileName;
3575 ULONG Length;
3576 WCHAR CompleteOrigDirName[512];
3577
3578 if (SourceCabinet)
3579 return AddSectionToCopyQueueCab(InfFile, L"SourceFiles", SourceCabinet, DestinationPath, Ir);
3580
3581 /* Search for the SectionName section */
3582 if (!SetupFindFirstLineW(InfFile, SectionName, NULL, &FilesContext))
3583 {
3584 char Buffer[128];
3585 sprintf(Buffer, MUIGetString(STRING_TXTSETUPFAILED), SectionName);
3586 PopupError(Buffer, MUIGetString(STRING_REBOOTCOMPUTER), Ir, POPUP_WAIT_ENTER);
3587 return FALSE;
3588 }
3589
3590 /*
3591 * Enumerate the files in the section
3592 * and add them to the file queue.
3593 */
3594 do
3595 {
3596 /* Get source file name and target directory id */
3597 if (!INF_GetData(&FilesContext, &FileKeyName, &FileKeyValue))
3598 {
3599 /* FIXME: Handle error! */
3600 DPRINT1("INF_GetData() failed\n");
3601 break;
3602 }
3603
3604 /* Get target directory id */
3605 if (!INF_GetDataField(&FilesContext, 13, &FileKeyValue))
3606 {
3607 /* FIXME: Handle error! */
3608 DPRINT1("INF_GetData() failed\n");
3609 break;
3610 }
3611
3612 /* Get optional target file name */
3613 if (!INF_GetDataField(&FilesContext, 11, &TargetFileName))
3614 TargetFileName = NULL;
3615 else if (!*TargetFileName)
3616 TargetFileName = NULL;
3617
3618 DPRINT("FileKeyName: '%S' FileKeyValue: '%S'\n", FileKeyName, FileKeyValue);
3619
3620 /* Lookup target directory */
3621 if (!SetupFindFirstLineW(InfFile, L"Directories", FileKeyValue, &DirContext))
3622 {
3623 /* FIXME: Handle error! */
3624 DPRINT1("SetupFindFirstLine() failed\n");
3625 break;
3626 }
3627
3628 if (!INF_GetData(&DirContext, NULL, &DirKeyValue))
3629 {
3630 /* FIXME: Handle error! */
3631 DPRINT1("INF_GetData() failed\n");
3632 break;
3633 }
3634
3635 if ((DirKeyValue[0] == 0) || (DirKeyValue[0] == L'\\' && DirKeyValue[1] == 0))
3636 {
3637 /* Installation path */
3638 wcscpy(CompleteOrigDirName, SourceRootDir.Buffer);
3639 }
3640 else if (DirKeyValue[0] == L'\\')
3641 {
3642 /* Absolute path */
3643 wcscpy(CompleteOrigDirName, DirKeyValue);
3644 }
3645 else // if (DirKeyValue[0] != L'\\')
3646 {
3647 /* Path relative to the installation path */
3648 wcscpy(CompleteOrigDirName, SourceRootDir.Buffer);
3649 wcscat(CompleteOrigDirName, L"\\");
3650 wcscat(CompleteOrigDirName, DirKeyValue);
3651 }
3652
3653 /* Remove trailing backslash */
3654 Length = wcslen(CompleteOrigDirName);
3655 if ((Length > 0) && (CompleteOrigDirName[Length - 1] == L'\\'))
3656 {
3657 CompleteOrigDirName[Length - 1] = 0;
3658 }
3659
3660 if (!SetupQueueCopy(SetupFileQueue,
3661 SourceCabinet,
3662 SourceRootPath.Buffer,
3663 CompleteOrigDirName,
3664 FileKeyName,
3665 DirKeyValue,
3666 TargetFileName))
3667 {
3668 /* FIXME: Handle error! */
3669 DPRINT1("SetupQueueCopy() failed\n");
3670 }
3671 } while (SetupFindNextLine(&FilesContext, &FilesContext));
3672
3673 return TRUE;
3674 }
3675
3676
3677 static BOOLEAN
3678 PrepareCopyPageInfFile(HINF InfFile,
3679 PWCHAR SourceCabinet,
3680 PINPUT_RECORD Ir)
3681 {
3682 WCHAR PathBuffer[MAX_PATH];
3683 INFCONTEXT DirContext;
3684 PWCHAR AdditionalSectionName = NULL;
3685 PWCHAR DirKeyValue;
3686 ULONG Length;
3687 NTSTATUS Status;
3688
3689 /* Add common files */
3690 if (!AddSectionToCopyQueue(InfFile, L"SourceDisksFiles", SourceCabinet, &DestinationPath, Ir))
3691 return FALSE;
3692
3693 /* Add specific files depending of computer type */
3694 if (SourceCabinet == NULL)
3695 {
3696 if (!ProcessComputerFiles(InfFile, ComputerList, &AdditionalSectionName))
3697 return FALSE;
3698
3699 if (AdditionalSectionName)
3700 {
3701 if (!AddSectionToCopyQueue(InfFile, AdditionalSectionName, SourceCabinet, &DestinationPath, Ir))
3702 return FALSE;
3703 }
3704 }
3705
3706 /* Create directories */
3707
3708 /*
3709 * FIXME:
3710 * - Install directories like '\reactos\test' are not handled yet.
3711 * - Copying files to DestinationRootPath should be done from within
3712 * the SystemPartitionFiles section.
3713 * At the moment we check whether we specify paths like '\foo' or '\\' for that.
3714 * For installing to DestinationPath specify just '\' .
3715 */
3716
3717 /* Get destination path */
3718 wcscpy(PathBuffer, DestinationPath.Buffer);
3719
3720 /* Remove trailing backslash */
3721 Length = wcslen(PathBuffer);
3722 if ((Length > 0) && (PathBuffer[Length - 1] == L'\\'))
3723 {
3724 PathBuffer[Length - 1] = 0;
3725 }
3726
3727 /* Create the install directory */
3728 Status = SetupCreateDirectory(PathBuffer);
3729 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION)
3730 {
3731 DPRINT1("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer, Status);
3732 MUIDisplayError(ERROR_CREATE_INSTALL_DIR, Ir, POPUP_WAIT_ENTER);
3733 return FALSE;
3734 }
3735
3736 /* Search for the 'Directories' section */
3737 if (!SetupFindFirstLineW(InfFile, L"Directories", NULL, &DirContext))
3738 {
3739 if (SourceCabinet)
3740 {
3741 MUIDisplayError(ERROR_CABINET_SECTION, Ir, POPUP_WAIT_ENTER);
3742 }
3743 else
3744 {
3745 MUIDisplayError(ERROR_TXTSETUP_SECTION, Ir, POPUP_WAIT_ENTER);
3746 }
3747
3748 return FALSE;
3749 }
3750
3751 /* Enumerate the directory values and create the subdirectories */
3752 do
3753 {
3754 if (!INF_GetData(&DirContext, NULL, &DirKeyValue))
3755 {
3756 DPRINT1("break\n");
3757 break;
3758 }
3759
3760 if ((DirKeyValue[0] == 0) || (DirKeyValue[0] == L'\\' && DirKeyValue[1] == 0))
3761 {
3762 /* Installation path */
3763 DPRINT("InstallationPath: '%S'\n", DirKeyValue);
3764
3765 wcscpy(PathBuffer, DestinationPath.Buffer);
3766
3767 DPRINT("FullPath: '%S'\n", PathBuffer);
3768 }
3769 else if (DirKeyValue[0] == L'\\')
3770 {
3771 /* Absolute path */
3772 DPRINT("Absolute Path: '%S'\n", DirKeyValue);
3773
3774 wcscpy(PathBuffer, DestinationRootPath.Buffer);
3775 wcscat(PathBuffer, DirKeyValue);
3776
3777 /* Remove trailing backslash */
3778 Length = wcslen(PathBuffer);
3779 if ((Length > 0) && (PathBuffer[Length - 1] == L'\\'))
3780 {
3781 PathBuffer[Length - 1] = 0;
3782 }
3783
3784 DPRINT("FullPath: '%S'\n", PathBuffer);
3785
3786 Status = SetupCreateDirectory(PathBuffer);
3787 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION)
3788 {
3789 DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer, Status);
3790 MUIDisplayError(ERROR_CREATE_DIR, Ir, POPUP_WAIT_ENTER);
3791 return FALSE;
3792 }
3793 }
3794 else // if (DirKeyValue[0] != L'\\')
3795 {
3796 /* Path relative to the installation path */
3797 DPRINT("RelativePath: '%S'\n", DirKeyValue);
3798
3799 wcscpy(PathBuffer, DestinationPath.Buffer);
3800 wcscat(PathBuffer, L"\\");
3801 wcscat(PathBuffer, DirKeyValue);
3802
3803 /* Remove trailing backslash */
3804 Length = wcslen(PathBuffer);
3805 if ((Length > 0) && (PathBuffer[Length - 1] == L'\\'))
3806 {
3807 PathBuffer[Length - 1] = 0;
3808 }
3809
3810 DPRINT("FullPath: '%S'\n", PathBuffer);
3811
3812 Status = SetupCreateDirectory(PathBuffer);
3813 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION)
3814 {
3815 DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer, Status);
3816 MUIDisplayError(ERROR_CREATE_DIR, Ir, POPUP_WAIT_ENTER);
3817 return FALSE;
3818 }
3819 }
3820 } while (SetupFindNextLine(&DirContext, &DirContext));
3821
3822 return TRUE;
3823 }
3824
3825
3826 /*
3827 * Displays the PrepareCopyPage.
3828 *
3829 * Next pages:
3830 * FileCopyPage(At once)
3831 * QuitPage
3832 *
3833 * SIDEEFFECTS
3834 * Inits SetupFileQueue
3835 * Calls PrepareCopyPageInfFile
3836 *
3837 * RETURNS
3838 * Number of the next page.
3839 */
3840 static PAGE_NUMBER
3841 PrepareCopyPage(PINPUT_RECORD Ir)
3842 {
3843 HINF InfHandle;
3844 WCHAR PathBuffer[MAX_PATH];
3845 INFCONTEXT CabinetsContext;
3846 ULONG InfFileSize;
3847 PWCHAR KeyValue;
3848 UINT ErrorLine;
3849 PVOID InfFileData;
3850
3851 MUIDisplayPage(PREPARE_COPY_PAGE);
3852
3853 /* Create the file queue */
3854 SetupFileQueue = SetupOpenFileQueue();
3855 if (SetupFileQueue == NULL)
3856 {
3857 MUIDisplayError(ERROR_COPY_QUEUE, Ir, POPUP_WAIT_ENTER);
3858 return QUIT_PAGE;
3859 }
3860
3861 if (!PrepareCopyPageInfFile(SetupInf, NULL, Ir))
3862 {
3863 /* FIXME: show an error dialog */
3864 return QUIT_PAGE;
3865 }
3866
3867 /* Search for the 'Cabinets' section */
3868 if (!SetupFindFirstLineW(SetupInf, L"Cabinets", NULL, &CabinetsContext))
3869 {
3870 return FILE_COPY_PAGE;
3871 }
3872
3873 /*
3874 * Enumerate the directory values in the 'Cabinets'
3875 * section and parse their inf files.
3876 */
3877 do
3878 {
3879 if (!INF_GetData(&CabinetsContext, NULL, &KeyValue))
3880 break;
3881
3882 wcscpy(PathBuffer, SourcePath.Buffer);
3883 wcscat(PathBuffer, L"\\");
3884 wcscat(PathBuffer, KeyValue);
3885
3886 CabinetInitialize();
3887 CabinetSetEventHandlers(NULL, NULL, NULL);
3888 CabinetSetCabinetName(PathBuffer);
3889
3890 if (CabinetOpen() == CAB_STATUS_SUCCESS)
3891 {
3892 DPRINT("Cabinet %S\n", CabinetGetCabinetName());
3893
3894 InfFileData = CabinetGetCabinetReservedArea(&InfFileSize);
3895 if (InfFileData == NULL)
3896 {
3897 MUIDisplayError(ERROR_CABINET_SCRIPT, Ir, POPUP_WAIT_ENTER);
3898 return QUIT_PAGE;
3899 }
3900 }
3901 else
3902 {
3903 DPRINT("Cannot open cabinet: %S.\n", CabinetGetCabinetName());
3904 MUIDisplayError(ERROR_CABINET_MISSING, Ir, POPUP_WAIT_ENTER);
3905 return QUIT_PAGE;
3906 }
3907
3908 InfHandle = INF_OpenBufferedFileA((CHAR*) InfFileData,
3909 InfFileSize,
3910 (const CHAR*) NULL,
3911 INF_STYLE_WIN4,
3912 LanguageId,
3913 &ErrorLine);
3914
3915 if (InfHandle == INVALID_HANDLE_VALUE)
3916 {
3917 MUIDisplayError(ERROR_INVALID_CABINET_INF, Ir, POPUP_WAIT_ENTER);
3918 return QUIT_PAGE;
3919 }
3920
3921 CabinetCleanup();
3922
3923 if (!PrepareCopyPageInfFile(InfHandle, KeyValue, Ir))
3924 {
3925 /* FIXME: show an error dialog */
3926 return QUIT_PAGE;
3927 }
3928 } while (SetupFindNextLine(&CabinetsContext, &CabinetsContext));
3929
3930 return FILE_COPY_PAGE;
3931 }
3932
3933
3934 VOID
3935 NTAPI
3936 SetupUpdateMemoryInfo(IN PCOPYCONTEXT CopyContext,
3937 IN BOOLEAN First)
3938 {
3939 SYSTEM_PERFORMANCE_INFORMATION PerfInfo;
3940
3941 /* Get the memory information from the system */
3942 NtQuerySystemInformation(SystemPerformanceInformation,
3943 &PerfInfo,
3944 sizeof(PerfInfo),
3945 NULL);
3946
3947 /* Check if this is initial setup */
3948 if (First)
3949 {
3950 /* Set maximum limits to be total RAM pages */
3951 ProgressSetStepCount(CopyContext->MemoryBars[0], PerfInfo.CommitLimit);
3952 ProgressSetStepCount(CopyContext->MemoryBars[1], PerfInfo.CommitLimit);
3953 ProgressSetStepCount(CopyContext->MemoryBars[2], PerfInfo.CommitLimit);
3954 }
3955
3956 /* Set current values */
3957 ProgressSetStep(CopyContext->MemoryBars[0], PerfInfo.PagedPoolPages + PerfInfo.NonPagedPoolPages);
3958 ProgressSetStep(CopyContext->MemoryBars[1], PerfInfo.ResidentSystemCachePage);
3959 ProgressSetStep(CopyContext->MemoryBars[2], PerfInfo.AvailablePages);
3960 }
3961
3962
3963 static UINT
3964 CALLBACK
3965 FileCopyCallback(PVOID Context,
3966 UINT Notification,
3967 UINT_PTR Param1,
3968 UINT_PTR Param2)
3969 {
3970 PCOPYCONTEXT CopyContext;
3971
3972 CopyContext = (PCOPYCONTEXT)Context;
3973
3974 switch (Notification)
3975 {
3976 case SPFILENOTIFY_STARTSUBQUEUE:
3977 CopyContext->TotalOperations = (ULONG)Param2;
3978 ProgressSetStepCount(CopyContext->ProgressBar,
3979 CopyContext->TotalOperations);
3980 SetupUpdateMemoryInfo(CopyContext, TRUE);
3981 break;
3982
3983 case SPFILENOTIFY_STARTCOPY:
3984 /* Display copy message */
3985 CONSOLE_SetStatusText(MUIGetString(STRING_COPYING), (PWSTR)Param1);
3986 SetupUpdateMemoryInfo(CopyContext, FALSE);
3987 break;
3988
3989 case SPFILENOTIFY_ENDCOPY:
3990 CopyContext->CompletedOperations++;
3991
3992 /* SYSREG checkpoint */
3993 if (CopyContext->TotalOperations >> 1 == CopyContext->CompletedOperations)
3994 DPRINT1("CHECKPOINT:HALF_COPIED\n");
3995
3996 ProgressNextStep(CopyContext->ProgressBar);
3997 SetupUpdateMemoryInfo(CopyContext, FALSE);
3998 break;
3999 }
4000
4001 return 0;
4002 }
4003
4004
4005 /*
4006 * Displays the FileCopyPage.
4007 *
4008 * Next pages:
4009 * RegistryPage(At once)
4010 *
4011 * SIDEEFFECTS
4012 * Calls SetupCommitFileQueueW
4013 * Calls SetupCloseFileQueue
4014 *
4015 * RETURNS
4016 * Number of the next page.
4017 */
4018 static
4019 PAGE_NUMBER
4020 FileCopyPage(PINPUT_RECORD Ir)
4021 {
4022 COPYCONTEXT CopyContext;
4023 unsigned int mem_bar_width;
4024
4025 MUIDisplayPage(FILE_COPY_PAGE);
4026
4027 /* Create context for the copy process */
4028 CopyContext.DestinationRootPath = DestinationRootPath.Buffer;
4029 CopyContext.InstallPath = InstallPath.Buffer;
4030 CopyContext.TotalOperations = 0;
4031 CopyContext.CompletedOperations = 0;
4032
4033 /* Create the progress bar as well */
4034 CopyContext.ProgressBar = CreateProgressBar(13,
4035 26,
4036 xScreen - 13,
4037 yScreen - 20,
4038 10,
4039 24,
4040 TRUE,
4041 MUIGetString(STRING_SETUPCOPYINGFILES));
4042
4043 // fit memory bars to screen width, distribute them uniform
4044 mem_bar_width = (xScreen - 26) / 5;
4045 mem_bar_width -= mem_bar_width % 2; // make even
4046 /* ATTENTION: The following progress bars are debug stuff, which should not be translated!! */
4047 /* Create the paged pool progress bar */
4048 CopyContext.MemoryBars[0] = CreateProgressBar(13,
4049 40,
4050 13 + mem_bar_width,
4051 43,
4052 13,
4053 44,
4054 FALSE,
4055 "Kernel Pool");
4056
4057 /* Create the non paged pool progress bar */
4058 CopyContext.MemoryBars[1] = CreateProgressBar((xScreen / 2)- (mem_bar_width / 2),
4059 40,
4060 (xScreen / 2) + (mem_bar_width / 2),
4061 43,
4062 (xScreen / 2)- (mem_bar_width / 2),
4063 44,
4064 FALSE,
4065 "Kernel Cache");
4066
4067 /* Create the global memory progress bar */
4068 CopyContext.MemoryBars[2] = CreateProgressBar(xScreen - 13 - mem_bar_width,
4069 40,
4070 xScreen - 13,
4071 43,
4072 xScreen - 13 - mem_bar_width,
4073 44,
4074 FALSE,
4075 "Free Memory");
4076
4077 /* Do the file copying */
4078 SetupCommitFileQueueW(NULL,
4079 SetupFileQueue,
4080 FileCopyCallback,
4081 &CopyContext);
4082
4083 /* If we get here, we're done, so cleanup the queue and progress bar */
4084 SetupCloseFileQueue(SetupFileQueue);
4085 DestroyProgressBar(CopyContext.ProgressBar);
4086 DestroyProgressBar(CopyContext.MemoryBars[0]);
4087 DestroyProgressBar(CopyContext.MemoryBars[1]);
4088 DestroyProgressBar(CopyContext.MemoryBars[2]);
4089
4090 /* Go display the next page */
4091 return REGISTRY_PAGE;
4092 }
4093
4094
4095 /*
4096 * Displays the RegistryPage.
4097 *
4098 * Next pages:
4099 * SuccessPage (if RepairUpdate)
4100 * BootLoaderPage (default)
4101 * QuitPage
4102 *
4103 * SIDEEFFECTS
4104 * Calls SetInstallPathValue
4105 * Calls NtInitializeRegistry
4106 * Calls ImportRegistryFile
4107 * Calls SetDefaultPagefile
4108 * Calls SetMountedDeviceValues
4109 *
4110 * RETURNS
4111 * Number of the next page.
4112 */
4113 static PAGE_NUMBER
4114 RegistryPage(PINPUT_RECORD Ir)
4115 {
4116 INFCONTEXT InfContext;
4117 PWSTR Action;
4118 PWSTR File;
4119 PWSTR Section;
4120 BOOLEAN Delete;
4121 NTSTATUS Status;
4122
4123 MUIDisplayPage(REGISTRY_PAGE);
4124
4125 if (RepairUpdateFlag)
4126 {
4127 return SUCCESS_PAGE;
4128 }
4129
4130 if (!SetInstallPathValue(&DestinationPath))
4131 {
4132 DPRINT1("SetInstallPathValue() failed\n");
4133 MUIDisplayError(ERROR_INITIALIZE_REGISTRY, Ir, POPUP_WAIT_ENTER);
4134 return QUIT_PAGE;
4135 }
4136
4137 /* Create the default hives */
4138 Status = NtInitializeRegistry(CM_BOOT_FLAG_SETUP);
4139 if (!NT_SUCCESS(Status))
4140 {
4141 DPRINT1("NtInitializeRegistry() failed (Status %lx)\n", Status);
4142 MUIDisplayError(ERROR_CREATE_HIVE, Ir, POPUP_WAIT_ENTER);
4143 return QUIT_PAGE;
4144 }
4145
4146 /* Update registry */
4147 CONSOLE_SetStatusText(MUIGetString(STRING_REGHIVEUPDATE));
4148
4149 if (!SetupFindFirstLineW(SetupInf, L"HiveInfs.Install", NULL, &InfContext))
4150 {
4151 DPRINT1("SetupFindFirstLine() failed\n");
4152 MUIDisplayError(ERROR_FIND_REGISTRY, Ir, POPUP_WAIT_ENTER);
4153 return QUIT_PAGE;
4154 }
4155
4156 do
4157 {
4158 INF_GetDataField(&InfContext, 0, &Action);
4159 INF_GetDataField(&InfContext, 1, &File);
4160 INF_GetDataField(&InfContext, 2, &Section);
4161
4162 DPRINT("Action: %S File: %S Section %S\n", Action, File, Section);
4163
4164 if (Action == NULL)
4165 break; // Hackfix
4166
4167 if (!_wcsicmp(Action, L"AddReg"))
4168 {
4169 Delete = FALSE;
4170 }
4171 else if (!_wcsicmp(Action, L"DelReg"))
4172 {
4173 Delete = TRUE;
4174 }
4175 else
4176 {
4177 continue;
4178 }
4179
4180 CONSOLE_SetStatusText(MUIGetString(STRING_IMPORTFILE), File);
4181
4182 if (!ImportRegistryFile(File, Section, LanguageId, Delete))
4183 {
4184 DPRINT1("Importing %S failed\n", File);
4185
4186 MUIDisplayError(ERROR_IMPORT_HIVE, Ir, POPUP_WAIT_ENTER);
4187 return QUIT_PAGE;
4188 }
4189 } while (SetupFindNextLine(&InfContext, &InfContext));
4190
4191 /* Update display registry settings */
4192 CONSOLE_SetStatusText(MUIGetString(STRING_DISPLAYETTINGSUPDATE));
4193 if (!ProcessDisplayRegistry(SetupInf, DisplayList))
4194 {
4195 MUIDisplayError(ERROR_UPDATE_DISPLAY_SETTINGS, Ir, POPUP_WAIT_ENTER);
4196 return QUIT_PAGE;
4197 }
4198
4199 /* Set the locale */
4200 CONSOLE_SetStatusText(MUIGetString(STRING_LOCALESETTINGSUPDATE));
4201 if (!ProcessLocaleRegistry(LanguageList))
4202 {
4203 MUIDisplayError(ERROR_UPDATE_LOCALESETTINGS, Ir, POPUP_WAIT_ENTER);
4204 return QUIT_PAGE;
4205 }
4206
4207 /* Add keyboard layouts */
4208 CONSOLE_SetStatusText(MUIGetString(STRING_ADDKBLAYOUTS));
4209 if (!AddKeyboardLayouts())
4210 {
4211 MUIDisplayError(ERROR_ADDING_KBLAYOUTS, Ir, POPUP_WAIT_ENTER);
4212 return QUIT_PAGE;
4213 }
4214
4215 /* Set GeoID */
4216
4217 if (!SetGeoID(MUIGetGeoID()))
4218 {
4219 MUIDisplayError(ERROR_UPDATE_GEOID, Ir, POPUP_WAIT_ENTER);
4220 return QUIT_PAGE;
4221 }
4222
4223 if (!IsUnattendedSetup)
4224 {
4225 /* Update keyboard layout settings */
4226 CONSOLE_SetStatusText(MUIGetString(STRING_KEYBOARDSETTINGSUPDATE));
4227 if (!ProcessKeyboardLayoutRegistry(LayoutList))
4228 {
4229 MUIDisplayError(ERROR_UPDATE_KBSETTINGS, Ir, POPUP_WAIT_ENTER);
4230 return QUIT_PAGE;
4231 }
4232 }
4233
4234 /* Add codepage information to registry */
4235 CONSOLE_SetStatusText(MUIGetString(STRING_CODEPAGEINFOUPDATE));
4236 if (!AddCodePage())
4237 {
4238 MUIDisplayError(ERROR_ADDING_CODEPAGE, Ir, POPUP_WAIT_ENTER);
4239 return QUIT_PAGE;
4240 }
4241
4242 /* Set the default pagefile entry */
4243 SetDefaultPagefile(DestinationDriveLetter);
4244
4245 /* Update the mounted devices list */
4246 SetMountedDeviceValues(PartitionList);
4247
4248 CONSOLE_SetStatusText(MUIGetString(STRING_DONE));
4249
4250 return BOOT_LOADER_PAGE;
4251 }
4252
4253
4254 /*
4255 * Displays the BootLoaderPage.
4256 *
4257 * Next pages:
4258 * SuccessPage (if RepairUpdate)
4259 * BootLoaderHarddiskMbrPage
4260 * BootLoaderHarddiskVbrPage
4261 * BootLoaderFloppyPage
4262 * SuccessPage
4263 * QuitPage
4264 *
4265 * SIDEEFFECTS
4266 * Calls SetInstallPathValue
4267 * Calls NtInitializeRegistry
4268 * Calls ImportRegistryFile
4269 * Calls SetDefaultPagefile
4270 * Calls SetMountedDeviceValues
4271 *
4272 * RETURNS
4273 * Number of the next page.
4274 */
4275 static PAGE_NUMBER
4276 BootLoaderPage(PINPUT_RECORD Ir)
4277 {
4278 UCHAR PartitionType;
4279 BOOLEAN InstallOnFloppy;
4280 USHORT Line = 12;
4281 WCHAR PathBuffer[MAX_PATH];
4282
4283 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
4284
4285 RtlFreeUnicodeString(&SystemRootPath);
4286 swprintf(PathBuffer,
4287 L"\\Device\\Harddisk%lu\\Partition%lu",
4288 PartitionList->SystemDisk->DiskNumber,
4289 PartitionList->SystemPartition->PartitionNumber);
4290 RtlCreateUnicodeString(&SystemRootPath, PathBuffer);
4291 DPRINT1("SystemRootPath: %wZ\n", &SystemRootPath);
4292
4293 PartitionType = PartitionList->SystemPartition->PartitionType;
4294
4295 if (IsUnattendedSetup)
4296 {
4297 if (UnattendMBRInstallType == 0) /* skip MBR installation */
4298 {
4299 return SUCCESS_PAGE;
4300 }
4301 else if (UnattendMBRInstallType == 1) /* install on floppy */
4302 {
4303 return BOOT_LOADER_FLOPPY_PAGE;
4304 }
4305 }
4306
4307 if (PartitionType == PARTITION_ENTRY_UNUSED)
4308 {
4309 DPRINT("Error: system partition invalid (unused)\n");
4310 InstallOnFloppy = TRUE;
4311 }
4312 else if (PartitionType == PARTITION_OS2BOOTMGR)
4313 {
4314 /* OS/2 boot manager partition */
4315 DPRINT("Found OS/2 boot manager partition\n");
4316 InstallOnFloppy = TRUE;
4317 }
4318 else if (PartitionType == PARTITION_EXT2)
4319 {
4320 /* Linux EXT2 partition */
4321 DPRINT("Found Linux EXT2 partition\n");
4322 InstallOnFloppy = FALSE;
4323 }
4324 else if (PartitionType == PARTITION_IFS)
4325 {
4326 /* NTFS partition */
4327 DPRINT("Found NTFS partition\n");
4328
4329 // FIXME: Make it FALSE when we'll support NTFS installation!
4330 InstallOnFloppy = TRUE;
4331 }
4332 else if ((PartitionType == PARTITION_FAT_12) ||
4333 (PartitionType == PARTITION_FAT_16) ||
4334 (PartitionType == PARTITION_HUGE) ||
4335 (PartitionType == PARTITION_XINT13) ||
4336 (PartitionType == PARTITION_FAT32) ||
4337 (PartitionType == PARTITION_FAT32_XINT13))
4338 {
4339 DPRINT("Found FAT partition\n");
4340 InstallOnFloppy = FALSE;
4341 }
4342 else
4343 {
4344 /* Unknown partition */
4345 DPRINT("Unknown partition found\n");
4346 InstallOnFloppy = TRUE;
4347 }
4348
4349 if (InstallOnFloppy != FALSE)
4350 {
4351 return BOOT_LOADER_FLOPPY_PAGE;
4352 }
4353
4354 /* Unattended install on hdd? */
4355 if (IsUnattendedSetup && UnattendMBRInstallType == 2)
4356 {
4357 return BOOT_LOADER_HARDDISK_MBR_PAGE;
4358 }
4359
4360 MUIDisplayPage(BOOT_LOADER_PAGE);
4361 CONSOLE_InvertTextXY(8, Line, 60, 1);
4362
4363 while (TRUE)
4364 {
4365 CONSOLE_ConInKey(Ir);
4366
4367 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
4368 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
4369 {
4370 CONSOLE_NormalTextXY(8, Line, 60, 1);
4371
4372 Line++;
4373 if (Line<12)
4374 Line=15;
4375
4376 if (Line>15)
4377 Line=12;
4378
4379 CONSOLE_InvertTextXY(8, Line, 60, 1);
4380 }
4381 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
4382 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
4383 {
4384 CONSOLE_NormalTextXY(8, Line, 60, 1);
4385
4386 Line--;
4387 if (Line<12)
4388 Line=15;
4389
4390 if (Line>15)
4391 Line=12;
4392
4393 CONSOLE_InvertTextXY(8, Line, 60, 1);
4394 }
4395 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
4396 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
4397 {
4398 if (ConfirmQuit(Ir) != FALSE)
4399 return QUIT_PAGE;
4400
4401 break;
4402 }
4403 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
4404 {
4405 if (Line == 12)
4406 {
4407 return BOOT_LOADER_HARDDISK_MBR_PAGE;
4408 }
4409 else if (Line == 13)
4410 {
4411 return BOOT_LOADER_HARDDISK_VBR_PAGE;
4412 }
4413 else if (Line == 14)
4414 {
4415 return BOOT_LOADER_FLOPPY_PAGE;
4416 }
4417 else if (Line == 15)
4418 {
4419 return SUCCESS_PAGE;
4420 }
4421
4422 return BOOT_LOADER_PAGE;
4423 }
4424 }
4425
4426 return BOOT_LOADER_PAGE;
4427 }
4428
4429
4430 /*
4431 * Displays the BootLoaderFloppyPage.
4432 *
4433 * Next pages:
4434 * SuccessPage (At once)
4435 * QuitPage
4436 *
4437 * SIDEEFFECTS
4438 * Calls InstallFatBootcodeToFloppy()
4439 *
4440 * RETURNS
4441 * Number of the next page.
4442 */
4443 static PAGE_NUMBER
4444 BootLoaderFloppyPage(PINPUT_RECORD Ir)
4445 {
4446 NTSTATUS Status;
4447
4448 MUIDisplayPage(BOOT_LOADER_FLOPPY_PAGE);
4449
4450 // SetStatusText(" Please wait...");
4451
4452 while (TRUE)
4453 {
4454 CONSOLE_ConInKey(Ir);
4455
4456 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
4457 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
4458 {
4459 if (ConfirmQuit(Ir) != FALSE)
4460 return QUIT_PAGE;
4461
4462 break;
4463 }
4464 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
4465 {
4466 if (DoesFileExist(L"\\Device\\Floppy0", L"\\") == FALSE)
4467 {
4468 MUIDisplayError(ERROR_NO_FLOPPY, Ir, POPUP_WAIT_ENTER);
4469 return BOOT_LOADER_FLOPPY_PAGE;
4470 }
4471
4472 Status = InstallFatBootcodeToFloppy(&SourceRootPath, &DestinationArcPath);
4473 if (!NT_SUCCESS(Status))
4474 {
4475 /* Print error message */
4476 return BOOT_LOADER_FLOPPY_PAGE;
4477 }
4478
4479 return SUCCESS_PAGE;
4480 }
4481 }
4482
4483 return BOOT_LOADER_FLOPPY_PAGE;
4484 }
4485
4486
4487 /*
4488 * Displays the BootLoaderHarddiskVbrPage.
4489 *
4490 * Next pages:
4491 * SuccessPage (At once)
4492 * QuitPage
4493 *
4494 * SIDEEFFECTS
4495 * Calls InstallVBRToPartition()
4496 *
4497 * RETURNS
4498 * Number of the next page.
4499 */
4500 static PAGE_NUMBER
4501 BootLoaderHarddiskVbrPage(PINPUT_RECORD Ir)
4502 {
4503 UCHAR PartitionType;
4504 NTSTATUS Status;
4505
4506 PartitionType = PartitionList->SystemPartition->PartitionType;
4507
4508 Status = InstallVBRToPartition(&SystemRootPath,
4509 &SourceRootPath,
4510 &DestinationArcPath,
4511 PartitionType);
4512 if (!NT_SUCCESS(Status))
4513 {
4514 MUIDisplayError(ERROR_WRITE_BOOT, Ir, POPUP_WAIT_ENTER);
4515 return QUIT_PAGE;
4516 }
4517
4518 return SUCCESS_PAGE;
4519 }
4520
4521
4522 /*
4523 * Displays the BootLoaderHarddiskMbrPage.
4524 *
4525 * Next pages:
4526 * SuccessPage (At once)
4527 * QuitPage
4528 *
4529 * SIDEEFFECTS
4530 * Calls InstallVBRToPartition()
4531 * CallsInstallMbrBootCodeToDisk()
4532 *
4533 * RETURNS
4534 * Number of the next page.
4535 */
4536 static PAGE_NUMBER
4537 BootLoaderHarddiskMbrPage(PINPUT_RECORD Ir)
4538 {
4539 UCHAR PartitionType;
4540 NTSTATUS Status;
4541 WCHAR DestinationDevicePathBuffer[MAX_PATH];
4542 WCHAR SourceMbrPathBuffer[MAX_PATH];
4543 WCHAR DstPath[MAX_PATH];
4544
4545 /* Step 1: Write the VBR */
4546 PartitionType = PartitionList->SystemPartition->PartitionType;
4547
4548 Status = InstallVBRToPartition(&SystemRootPath,
4549 &SourceRootPath,
4550 &DestinationArcPath,
4551 PartitionType);
4552 if (!NT_SUCCESS(Status))
4553 {
4554 MUIDisplayError(ERROR_WRITE_BOOT, Ir, POPUP_WAIT_ENTER);
4555 return QUIT_PAGE;
4556 }
4557
4558 /* Step 2: Write the MBR */
4559 swprintf(DestinationDevicePathBuffer,
4560 L"\\Device\\Harddisk%d\\Partition0",
4561 PartitionList->SystemDisk->DiskNumber);
4562
4563 wcscpy(SourceMbrPathBuffer, SourceRootPath.Buffer);
4564 wcscat(SourceMbrPathBuffer, L"\\loader\\dosmbr.bin");
4565
4566 if (IsThereAValidBootSector(DestinationDevicePathBuffer))
4567 {
4568 /* Save current MBR */
4569 wcscpy(DstPath, SystemRootPath.Buffer);
4570 wcscat(DstPath, L"\\mbr.old");
4571
4572 DPRINT1("Save MBR: %S ==> %S\n", DestinationDevicePathBuffer, DstPath);
4573 Status = SaveBootSector(DestinationDevicePathBuffer, DstPath, sizeof(PARTITION_SECTOR));
4574 if (!NT_SUCCESS(Status))
4575 {
4576 DPRINT1("SaveBootSector() failed (Status %lx)\n", Status);
4577 // Don't care if we succeeded or not saving the old MBR, just go ahead.
4578 }
4579 }
4580
4581 DPRINT1("Install MBR bootcode: %S ==> %S\n",
4582 SourceMbrPathBuffer, DestinationDevicePathBuffer);
4583 Status = InstallMbrBootCodeToDisk(SourceMbrPathBuffer,
4584 DestinationDevicePathBuffer);
4585 if (!NT_SUCCESS(Status))
4586 {
4587 DPRINT1("InstallMbrBootCodeToDisk() failed (Status %lx)\n",
4588 Status);
4589 MUIDisplayError(ERROR_INSTALL_BOOTCODE, Ir, POPUP_WAIT_ENTER);
4590 return QUIT_PAGE;
4591 }
4592
4593 return SUCCESS_PAGE;
4594 }
4595
4596
4597 /*
4598 * Displays the QuitPage.
4599 *
4600 * Next pages:
4601 * FlushPage (At once)
4602 *
4603 * SIDEEFFECTS
4604 * Destroy the Lists
4605 *
4606 * RETURNS
4607 * Number of the next page.
4608 */
4609 static PAGE_NUMBER
4610 QuitPage(PINPUT_RECORD Ir)
4611 {
4612 MUIDisplayPage(QUIT_PAGE);
4613
4614 /* Destroy partition list */
4615 if (PartitionList != NULL)
4616 {
4617 DestroyPartitionList(PartitionList);
4618 PartitionList = NULL;
4619 }
4620
4621 /* Destroy filesystem list */
4622 if (FileSystemList != NULL)
4623 {
4624 DestroyFileSystemList(FileSystemList);
4625 FileSystemList = NULL;
4626 }
4627
4628 /* Destroy computer settings list */
4629 if (ComputerList != NULL)
4630 {
4631 DestroyGenericList(ComputerList, TRUE);
4632 ComputerList = NULL;
4633 }
4634
4635 /* Destroy display settings list */
4636 if (DisplayList != NULL)
4637 {
4638 DestroyGenericList(DisplayList, TRUE);
4639 DisplayList = NULL;
4640 }
4641
4642 /* Destroy keyboard settings list */
4643 if (KeyboardList != NULL)
4644 {
4645 DestroyGenericList(KeyboardList, TRUE);
4646 KeyboardList = NULL;
4647 }
4648
4649 /* Destroy keyboard layout list */
4650 if (LayoutList != NULL)
4651 {
4652 DestroyGenericList(LayoutList, TRUE);
4653 LayoutList = NULL;
4654 }
4655
4656 if (LanguageList != NULL)
4657 {
4658 DestroyGenericList(LanguageList, FALSE);
4659 LanguageList = NULL;
4660 }
4661
4662 CONSOLE_SetStatusText(MUIGetString(STRING_REBOOTCOMPUTER2));
4663
4664 while (TRUE)
4665 {
4666 CONSOLE_ConInKey(Ir);
4667
4668 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
4669 {
4670 return FLUSH_PAGE;
4671 }
4672 }
4673 }
4674
4675
4676 /*
4677 * Displays the SuccessPage.
4678 *
4679 * Next pages:
4680 * FlushPage (At once)
4681 *
4682 * SIDEEFFECTS
4683 * Destroy the Lists
4684 *
4685 * RETURNS
4686 * Number of the next page.
4687 */
4688 static PAGE_NUMBER
4689 SuccessPage(PINPUT_RECORD Ir)
4690 {
4691 MUIDisplayPage(SUCCESS_PAGE);
4692
4693 if (IsUnattendedSetup)
4694 {
4695 return FLUSH_PAGE;
4696 }
4697
4698 while (TRUE)
4699 {
4700 CONSOLE_ConInKey(Ir);
4701
4702 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
4703 {
4704 return FLUSH_PAGE;
4705 }
4706 }
4707 }
4708
4709
4710 /*
4711 * Displays the FlushPage.
4712 *
4713 * Next pages:
4714 * RebootPage (At once)
4715 *
4716 * RETURNS
4717 * Number of the next page.
4718 */
4719 static PAGE_NUMBER
4720 FlushPage(PINPUT_RECORD Ir)
4721 {
4722 MUIDisplayPage(FLUSH_PAGE);
4723 return REBOOT_PAGE;
4724 }
4725
4726
4727 DWORD WINAPI
4728 PnpEventThread(IN LPVOID lpParameter);
4729
4730
4731 /*
4732 * The start routine and page management
4733 */
4734 VOID
4735 RunUSetup(VOID)
4736 {
4737 INPUT_RECORD Ir;
4738 PAGE_NUMBER Page;
4739 LARGE_INTEGER Time;
4740 NTSTATUS Status;
4741 BOOLEAN Old;
4742
4743 NtQuerySystemTime(&Time);
4744
4745 Status = RtlCreateUserThread(NtCurrentProcess(),
4746 NULL,
4747 TRUE,
4748 0,
4749 0,
4750 0,
4751 PnpEventThread,
4752 &SetupInf,
4753 &hPnpThread,
4754 NULL);
4755 if (!NT_SUCCESS(Status))
4756 hPnpThread = INVALID_HANDLE_VALUE;
4757
4758 if (!CONSOLE_Init())
4759 {
4760 PrintString(MUIGetString(STRING_CONSOLEFAIL1));
4761 PrintString(MUIGetString(STRING_CONSOLEFAIL2));
4762 PrintString(MUIGetString(STRING_CONSOLEFAIL3));
4763
4764 /* Raise a hard error (crash the system/BSOD) */
4765 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED,
4766 0,0,0,0,0);
4767 }
4768
4769 /* Initialize global unicode strings */
4770 RtlInitUnicodeString(&SourcePath, NULL);
4771 RtlInitUnicodeString(&SourceRootPath, NULL);
4772 RtlInitUnicodeString(&SourceRootDir, NULL);
4773 RtlInitUnicodeString(&InstallPath, NULL);
4774 RtlInitUnicodeString(&DestinationPath, NULL);
4775 RtlInitUnicodeString(&DestinationArcPath, NULL);
4776 RtlInitUnicodeString(&DestinationRootPath, NULL);
4777 RtlInitUnicodeString(&SystemRootPath, NULL);
4778
4779 /* Hide the cursor */
4780 CONSOLE_SetCursorType(TRUE, FALSE);
4781
4782 Page = START_PAGE;
4783 while (Page != REBOOT_PAGE && Page != RECOVERY_PAGE)
4784 {
4785 CONSOLE_ClearScreen();
4786 CONSOLE_Flush();
4787
4788 //CONSOLE_SetUnderlinedTextXY(4, 3, " ReactOS " KERNEL_VERSION_STR " Setup ");
4789 //CONSOLE_Flush();
4790
4791 switch (Page)
4792 {
4793 /* Start page */
4794 case START_PAGE:
4795 Page = SetupStartPage(&Ir);
4796 break;
4797
4798 /* Language page */
4799 case LANGUAGE_PAGE:
4800 Page = LanguagePage(&Ir);
4801 break;
4802
4803 /* License page */
4804 case LICENSE_PAGE:
4805 Page = LicensePage(&Ir);
4806 break;
4807
4808 /* Intro page */
4809 case INTRO_PAGE:
4810 Page = IntroPage(&Ir);
4811 break;
4812
4813 /* Install pages */
4814 case INSTALL_INTRO_PAGE:
4815 Page = InstallIntroPage(&Ir);
4816 break;
4817
4818 #if 0
4819 case SCSI_CONTROLLER_PAGE:
4820 Page = ScsiControllerPage(&Ir);
4821 break;
4822 #endif
4823
4824 #if 0
4825 case OEM_DRIVER_PAGE:
4826 Page = OemDriverPage(&Ir);
4827 break;
4828 #endif
4829
4830 case DEVICE_SETTINGS_PAGE:
4831 Page = DeviceSettingsPage(&Ir);
4832 break;
4833
4834 case COMPUTER_SETTINGS_PAGE:
4835 Page = ComputerSettingsPage(&Ir);
4836 break;
4837
4838 case DISPLAY_SETTINGS_PAGE:
4839 Page = DisplaySettingsPage(&Ir);
4840 break;
4841
4842 case KEYBOARD_SETTINGS_PAGE:
4843 Page = KeyboardSettingsPage(&Ir);
4844 break;
4845
4846 case LAYOUT_SETTINGS_PAGE:
4847 Page = LayoutSettingsPage(&Ir);
4848 break;
4849
4850 case SELECT_PARTITION_PAGE:
4851 Page = SelectPartitionPage(&Ir);
4852 break;
4853
4854 case CREATE_PRIMARY_PARTITION_PAGE:
4855 Page = CreatePrimaryPartitionPage(&Ir);
4856 break;
4857
4858 case CREATE_EXTENDED_PARTITION_PAGE:
4859 Page = CreateExtendedPartitionPage(&Ir);
4860 break;
4861
4862 case CREATE_LOGICAL_PARTITION_PAGE:
4863 Page = CreateLogicalPartitionPage(&Ir);
4864 break;
4865
4866 case CONFIRM_DELETE_SYSTEM_PARTITION_PAGE:
4867 Page = ConfirmDeleteSystemPartitionPage(&Ir);
4868 break;
4869
4870 case DELETE_PARTITION_PAGE:
4871 Page = DeletePartitionPage(&Ir);
4872 break;
4873
4874 case SELECT_FILE_SYSTEM_PAGE:
4875 Page = SelectFileSystemPage(&Ir);
4876 break;
4877
4878 case FORMAT_PARTITION_PAGE:
4879 Page = (PAGE_NUMBER) FormatPartitionPage(&Ir);
4880 break;
4881
4882 case CHECK_FILE_SYSTEM_PAGE:
4883 Page = (PAGE_NUMBER) CheckFileSystemPage(&Ir);
4884 break;
4885
4886 case INSTALL_DIRECTORY_PAGE:
4887 Page = InstallDirectoryPage(&Ir);
4888 break;
4889
4890 case PREPARE_COPY_PAGE:
4891 Page = PrepareCopyPage(&Ir);
4892 break;
4893
4894 case FILE_COPY_PAGE:
4895 Page = FileCopyPage(&Ir);
4896 break;
4897
4898 case REGISTRY_PAGE:
4899 Page = RegistryPage(&Ir);
4900 break;
4901
4902 case BOOT_LOADER_PAGE:
4903 Page = BootLoaderPage(&Ir);
4904 break;
4905
4906 case BOOT_LOADER_FLOPPY_PAGE:
4907 Page = BootLoaderFloppyPage(&Ir);
4908 break;
4909
4910 case BOOT_LOADER_HARDDISK_MBR_PAGE:
4911 Page = BootLoaderHarddiskMbrPage(&Ir);
4912 break;
4913
4914 case BOOT_LOADER_HARDDISK_VBR_PAGE:
4915 Page = BootLoaderHarddiskVbrPage(&Ir);
4916 break;
4917
4918 /* Repair pages */
4919 case REPAIR_INTRO_PAGE:
4920 Page = RepairIntroPage(&Ir);
4921 break;
4922
4923 case SUCCESS_PAGE:
4924 Page = SuccessPage(&Ir);
4925 break;
4926
4927 case FLUSH_PAGE:
4928 Page = FlushPage(&Ir);
4929 break;
4930
4931 case QUIT_PAGE:
4932 Page = QuitPage(&Ir);
4933 break;
4934
4935 case RECOVERY_PAGE:
4936 case REBOOT_PAGE:
4937 break;
4938 }
4939 }
4940
4941 if (Page == RECOVERY_PAGE)
4942 RecoveryConsole();
4943
4944 FreeConsole();
4945
4946 /* Avoid bugcheck */
4947 Time.QuadPart += 50000000;
4948 NtDelayExecution(FALSE, &Time);
4949
4950 /* Reboot */
4951 RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, TRUE, FALSE, &Old);
4952 NtShutdownSystem(ShutdownReboot);
4953 RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, Old, FALSE, &Old);
4954 NtTerminateProcess(NtCurrentProcess(), 0);
4955 }
4956
4957
4958 VOID NTAPI
4959 NtProcessStartup(PPEB Peb)
4960 {
4961 RtlNormalizeProcessParams(Peb->ProcessParameters);
4962
4963 ProcessHeap = Peb->ProcessHeap;
4964 InfSetHeap(ProcessHeap);
4965 RunUSetup();
4966 }
4967
4968 /* EOF */