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