d8c73af3ac81a24541063e24397f7ac5fb3d497b
[reactos.git] / reactos / base / setup / usetup / interface / 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: subsys/system/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 "format.h"
34 #include "drivesup.h"
35 #include "settings.h"
36
37 #define NDEBUG
38 #include <debug.h>
39
40
41 /* GLOBALS ******************************************************************/
42
43 HANDLE ProcessHeap;
44 UNICODE_STRING SourceRootPath;
45 UNICODE_STRING SourceRootDir;
46 UNICODE_STRING SourcePath;
47 BOOLEAN IsUnattendedSetup = FALSE;
48 LONG UnattendDestinationDiskNumber;
49 LONG UnattendDestinationPartitionNumber;
50 LONG UnattendMBRInstallType = -1;
51 LONG UnattendFormatPartition = 0;
52 LONG AutoPartition = 0;
53 WCHAR UnattendInstallationDirectory[MAX_PATH];
54 PWCHAR SelectedLanguageId;
55 WCHAR LocaleID[9];
56 WCHAR DefaultLanguage[20];
57 WCHAR DefaultKBLayout[20];
58 BOOLEAN RepairUpdateFlag = FALSE;
59 HANDLE hPnpThread = INVALID_HANDLE_VALUE;
60 PPARTLIST PartitionList = NULL;
61
62 /* LOCALS *******************************************************************/
63
64 static PFILE_SYSTEM_LIST FileSystemList = NULL;
65
66 static UNICODE_STRING InstallPath;
67
68 /* Path to the install directory */
69 static UNICODE_STRING DestinationPath;
70 static UNICODE_STRING DestinationArcPath;
71 static UNICODE_STRING DestinationRootPath;
72
73 static WCHAR DestinationDriveLetter;
74
75 /* Path to the active partition (boot manager) */
76 static UNICODE_STRING SystemRootPath;
77
78 static HINF SetupInf;
79
80 static HSPFILEQ SetupFileQueue = NULL;
81
82 static BOOLEAN WarnLinuxPartitions = TRUE;
83
84 static PGENERIC_LIST ComputerList = NULL;
85 static PGENERIC_LIST DisplayList = NULL;
86 static PGENERIC_LIST KeyboardList = NULL;
87 static PGENERIC_LIST LayoutList = NULL;
88 static PGENERIC_LIST LanguageList = NULL;
89
90 static LANGID LanguageId = 0;
91
92 static ULONG RequiredPartitionDiskSpace = ~0;
93
94 /* FUNCTIONS ****************************************************************/
95
96 static VOID
97 PrintString(char* fmt,...)
98 {
99 char buffer[512];
100 va_list ap;
101 UNICODE_STRING UnicodeString;
102 ANSI_STRING AnsiString;
103
104 va_start(ap, fmt);
105 vsprintf(buffer, fmt, ap);
106 va_end(ap);
107
108 RtlInitAnsiString(&AnsiString, buffer);
109 RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE);
110 NtDisplayString(&UnicodeString);
111 RtlFreeUnicodeString(&UnicodeString);
112 }
113
114
115 static VOID
116 DrawBox(IN SHORT xLeft,
117 IN SHORT yTop,
118 IN SHORT Width,
119 IN SHORT Height)
120 {
121 COORD coPos;
122 DWORD Written;
123
124 /* draw upper left corner */
125 coPos.X = xLeft;
126 coPos.Y = yTop;
127 FillConsoleOutputCharacterA(StdOutput,
128 0xDA, // '+',
129 1,
130 coPos,
131 &Written);
132
133 /* draw upper edge */
134 coPos.X = xLeft + 1;
135 coPos.Y = yTop;
136 FillConsoleOutputCharacterA(StdOutput,
137 0xC4, // '-',
138 Width - 2,
139 coPos,
140 &Written);
141
142 /* draw upper right corner */
143 coPos.X = xLeft + Width - 1;
144 coPos.Y = yTop;
145 FillConsoleOutputCharacterA(StdOutput,
146 0xBF, // '+',
147 1,
148 coPos,
149 &Written);
150
151 /* Draw right edge, inner space and left edge */
152 for (coPos.Y = yTop + 1; coPos.Y < yTop + Height - 1; coPos.Y++)
153 {
154 coPos.X = xLeft;
155 FillConsoleOutputCharacterA(StdOutput,
156 0xB3, // '|',
157 1,
158 coPos,
159 &Written);
160
161 coPos.X = xLeft + 1;
162 FillConsoleOutputCharacterA(StdOutput,
163 ' ',
164 Width - 2,
165 coPos,
166 &Written);
167
168 coPos.X = xLeft + Width - 1;
169 FillConsoleOutputCharacterA(StdOutput,
170 0xB3, // '|',
171 1,
172 coPos,
173 &Written);
174 }
175
176 /* draw lower left corner */
177 coPos.X = xLeft;
178 coPos.Y = yTop + Height - 1;
179 FillConsoleOutputCharacterA(StdOutput,
180 0xC0, // '+',
181 1,
182 coPos,
183 &Written);
184
185 /* draw lower edge */
186 coPos.X = xLeft + 1;
187 coPos.Y = yTop + Height - 1;
188 FillConsoleOutputCharacterA(StdOutput,
189 0xC4, // '-',
190 Width - 2,
191 coPos,
192 &Written);
193
194 /* draw lower right corner */
195 coPos.X = xLeft + Width - 1;
196 coPos.Y = yTop + Height - 1;
197 FillConsoleOutputCharacterA(StdOutput,
198 0xD9, // '+',
199 1,
200 coPos,
201 &Written);
202 }
203
204
205 VOID
206 PopupError(PCCH Text,
207 PCCH Status,
208 PINPUT_RECORD Ir,
209 ULONG WaitEvent)
210 {
211 SHORT yTop;
212 SHORT xLeft;
213 COORD coPos;
214 DWORD Written;
215 ULONG Length;
216 ULONG MaxLength;
217 ULONG Lines;
218 PCHAR p;
219 PCCH pnext;
220 BOOLEAN LastLine;
221 SHORT Width;
222 SHORT Height;
223
224 /* Count text lines and longest line */
225 MaxLength = 0;
226 Lines = 0;
227 pnext = Text;
228
229 while (TRUE)
230 {
231 p = strchr(pnext, '\n');
232
233 if (p == NULL)
234 {
235 Length = strlen(pnext);
236 LastLine = TRUE;
237 }
238 else
239 {
240 Length = (ULONG)(p - pnext);
241 LastLine = FALSE;
242 }
243
244 Lines++;
245
246 if (Length > MaxLength)
247 MaxLength = Length;
248
249 if (LastLine == TRUE)
250 break;
251
252 pnext = p + 1;
253 }
254
255 /* Check length of status line */
256 if (Status != NULL)
257 {
258 Length = strlen(Status);
259
260 if (Length > MaxLength)
261 MaxLength = Length;
262 }
263
264 Width = MaxLength + 4;
265 Height = Lines + 2;
266
267 if (Status != NULL)
268 Height += 2;
269
270 yTop = (yScreen - Height) / 2;
271 xLeft = (xScreen - Width) / 2;
272
273
274 /* Set screen attributes */
275 coPos.X = xLeft;
276 for (coPos.Y = yTop; coPos.Y < yTop + Height; coPos.Y++)
277 {
278 FillConsoleOutputAttribute(StdOutput,
279 FOREGROUND_RED | BACKGROUND_WHITE,
280 Width,
281 coPos,
282 &Written);
283 }
284
285 DrawBox(xLeft, yTop, Width, Height);
286
287 /* Print message text */
288 coPos.Y = yTop + 1;
289 pnext = Text;
290 while (TRUE)
291 {
292 p = strchr(pnext, '\n');
293
294 if (p == NULL)
295 {
296 Length = strlen(pnext);
297 LastLine = TRUE;
298 }
299 else
300 {
301 Length = (ULONG)(p - pnext);
302 LastLine = FALSE;
303 }
304
305 if (Length != 0)
306 {
307 coPos.X = xLeft + 2;
308 WriteConsoleOutputCharacterA(StdOutput,
309 pnext,
310 Length,
311 coPos,
312 &Written);
313 }
314
315 if (LastLine == TRUE)
316 break;
317
318 coPos.Y++;
319 pnext = p + 1;
320 }
321
322 /* Print separator line and status text */
323 if (Status != NULL)
324 {
325 coPos.Y = yTop + Height - 3;
326 coPos.X = xLeft;
327 FillConsoleOutputCharacterA(StdOutput,
328 0xC3, // '+',
329 1,
330 coPos,
331 &Written);
332
333 coPos.X = xLeft + 1;
334 FillConsoleOutputCharacterA(StdOutput,
335 0xC4, // '-',
336 Width - 2,
337 coPos,
338 &Written);
339
340 coPos.X = xLeft + Width - 1;
341 FillConsoleOutputCharacterA(StdOutput,
342 0xB4, // '+',
343 1,
344 coPos,
345 &Written);
346
347 coPos.Y++;
348 coPos.X = xLeft + 2;
349 WriteConsoleOutputCharacterA(StdOutput,
350 Status,
351 min(strlen(Status), (SIZE_T)Width - 4),
352 coPos,
353 &Written);
354 }
355
356 if (WaitEvent == POPUP_WAIT_NONE)
357 return;
358
359 while (TRUE)
360 {
361 CONSOLE_ConInKey(Ir);
362
363 if (WaitEvent == POPUP_WAIT_ANY_KEY ||
364 Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)
365 {
366 return;
367 }
368 }
369 }
370
371
372 /*
373 * Confirm quit setup
374 * RETURNS
375 * TRUE: Quit setup.
376 * FALSE: Don't quit setup.
377 */
378 static BOOL
379 ConfirmQuit(PINPUT_RECORD Ir)
380 {
381 BOOL Result = FALSE;
382 MUIDisplayError(ERROR_NOT_INSTALLED, NULL, POPUP_WAIT_NONE);
383
384 while (TRUE)
385 {
386 CONSOLE_ConInKey(Ir);
387
388 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
389 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
390 {
391 Result = TRUE;
392 break;
393 }
394 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
395 {
396 Result = FALSE;
397 break;
398 }
399 }
400
401 return Result;
402 }
403
404
405 VOID
406 CheckUnattendedSetup(VOID)
407 {
408 WCHAR UnattendInfPath[MAX_PATH];
409 INFCONTEXT Context;
410 HINF UnattendInf;
411 UINT ErrorLine;
412 INT IntValue;
413 PWCHAR Value;
414
415 if (DoesFileExist(SourcePath.Buffer, L"unattend.inf") == FALSE)
416 {
417 DPRINT("Does not exist: %S\\%S\n", SourcePath.Buffer, L"unattend.inf");
418 return;
419 }
420
421 wcscpy(UnattendInfPath, SourcePath.Buffer);
422 wcscat(UnattendInfPath, L"\\unattend.inf");
423
424 /* Load 'unattend.inf' from install media. */
425 UnattendInf = SetupOpenInfFileW(UnattendInfPath,
426 NULL,
427 INF_STYLE_WIN4,
428 LanguageId,
429 &ErrorLine);
430
431 if (UnattendInf == INVALID_HANDLE_VALUE)
432 {
433 DPRINT("SetupOpenInfFileW() failed\n");
434 return;
435 }
436
437 /* Open 'Unattend' section */
438 if (!SetupFindFirstLineW(UnattendInf, L"Unattend", L"Signature", &Context))
439 {
440 DPRINT("SetupFindFirstLineW() failed for section 'Unattend'\n");
441 SetupCloseInfFile(UnattendInf);
442 return;
443 }
444
445 /* Get pointer 'Signature' key */
446 if (!INF_GetData(&Context, NULL, &Value))
447 {
448 DPRINT("INF_GetData() failed for key 'Signature'\n");
449 SetupCloseInfFile(UnattendInf);
450 return;
451 }
452
453 /* Check 'Signature' string */
454 if (_wcsicmp(Value, L"$ReactOS$") != 0)
455 {
456 DPRINT("Signature not $ReactOS$\n");
457 SetupCloseInfFile(UnattendInf);
458 return;
459 }
460
461 /* Check if Unattend setup is enabled */
462 if (!SetupFindFirstLineW(UnattendInf, L"Unattend", L"UnattendSetupEnabled", &Context))
463 {
464 DPRINT("Can't find key 'UnattendSetupEnabled'\n");
465 SetupCloseInfFile(UnattendInf);
466 return;
467 }
468
469 if (!INF_GetData(&Context, NULL, &Value))
470 {
471 DPRINT("Can't read key 'UnattendSetupEnabled'\n");
472 SetupCloseInfFile(UnattendInf);
473 return;
474 }
475
476 if (_wcsicmp(Value, L"yes") != 0)
477 {
478 DPRINT("Unattend setup is disabled by 'UnattendSetupEnabled' key!\n");
479 SetupCloseInfFile(UnattendInf);
480 return;
481 }
482
483 /* Search for 'DestinationDiskNumber' in the 'Unattend' section */
484 if (!SetupFindFirstLineW(UnattendInf, L"Unattend", L"DestinationDiskNumber", &Context))
485 {
486 DPRINT("SetupFindFirstLine() failed for key 'DestinationDiskNumber'\n");
487 SetupCloseInfFile(UnattendInf);
488 return;
489 }
490
491 if (!SetupGetIntField(&Context, 1, &IntValue))
492 {
493 DPRINT("SetupGetIntField() failed for key 'DestinationDiskNumber'\n");
494 SetupCloseInfFile(UnattendInf);
495 return;
496 }
497
498 UnattendDestinationDiskNumber = (LONG)IntValue;
499
500 /* Search for 'DestinationPartitionNumber' in the 'Unattend' section */
501 if (!SetupFindFirstLineW(UnattendInf, L"Unattend", L"DestinationPartitionNumber", &Context))
502 {
503 DPRINT("SetupFindFirstLine() failed for key 'DestinationPartitionNumber'\n");
504 SetupCloseInfFile(UnattendInf);
505 return;
506 }
507
508 if (!SetupGetIntField(&Context, 1, &IntValue))
509 {
510 DPRINT("SetupGetIntField() failed for key 'DestinationPartitionNumber'\n");
511 SetupCloseInfFile(UnattendInf);
512 return;
513 }
514
515 UnattendDestinationPartitionNumber = IntValue;
516
517 /* Search for 'InstallationDirectory' in the 'Unattend' section */
518 if (!SetupFindFirstLineW(UnattendInf, L"Unattend", L"InstallationDirectory", &Context))
519 {
520 DPRINT("SetupFindFirstLine() failed for key 'InstallationDirectory'\n");
521 SetupCloseInfFile(UnattendInf);
522 return;
523 }
524
525 /* Get pointer 'InstallationDirectory' key */
526 if (!INF_GetData(&Context, NULL, &Value))
527 {
528 DPRINT("INF_GetData() failed for key 'InstallationDirectory'\n");
529 SetupCloseInfFile(UnattendInf);
530 return;
531 }
532
533 wcscpy(UnattendInstallationDirectory, Value);
534
535 IsUnattendedSetup = TRUE;
536
537 /* Search for 'MBRInstallType' in the 'Unattend' section */
538 if (SetupFindFirstLineW(UnattendInf, L"Unattend", L"MBRInstallType", &Context))
539 {
540 if (SetupGetIntField(&Context, 1, &IntValue))
541 {
542 UnattendMBRInstallType = IntValue;
543 }
544 }
545
546 /* Search for 'FormatPartition' in the 'Unattend' section */
547 if (SetupFindFirstLineW(UnattendInf, L"Unattend", L"FormatPartition", &Context))
548 {
549 if (SetupGetIntField(&Context, 1, &IntValue))
550 {
551 UnattendFormatPartition = IntValue;
552 }
553 }
554
555 if (SetupFindFirstLineW(UnattendInf, L"Unattend", L"AutoPartition", &Context))
556 {
557 if (SetupGetIntField(&Context, 1, &IntValue))
558 {
559 AutoPartition = IntValue;
560 }
561 }
562
563 /* search for LocaleID in the 'Unattend' section*/
564 if (SetupFindFirstLineW (UnattendInf, L"Unattend", L"LocaleID", &Context))
565 {
566 if (INF_GetData (&Context, NULL, &Value))
567 {
568 LONG Id = wcstol(Value, NULL, 16);
569 swprintf(LocaleID,L"%08lx", Id);
570 }
571 }
572
573 SetupCloseInfFile(UnattendInf);
574
575 DPRINT("Running unattended setup\n");
576 }
577
578
579 VOID
580 UpdateKBLayout(VOID)
581 {
582 PGENERIC_LIST_ENTRY ListEntry;
583 LPCWSTR pszNewLayout;
584
585 pszNewLayout = MUIDefaultKeyboardLayout();
586
587 if (LayoutList == NULL)
588 {
589 LayoutList = CreateKeyboardLayoutList(SetupInf, DefaultKBLayout);
590 if (LayoutList == NULL)
591 {
592 /* FIXME: Handle error! */
593 return;
594 }
595 }
596
597 ListEntry = GetFirstListEntry(LayoutList);
598
599 /* Search for default layout (if provided) */
600 if (pszNewLayout != NULL)
601 {
602 while (ListEntry != NULL)
603 {
604 if (!wcscmp(pszNewLayout, GetListEntryUserData(ListEntry)))
605 {
606 SetCurrentListEntry(LayoutList, ListEntry);
607 break;
608 }
609
610 ListEntry = GetNextListEntry(ListEntry);
611 }
612 }
613 }
614
615
616 static PAGE_NUMBER
617 LanguagePage(PINPUT_RECORD Ir)
618 {
619 PWCHAR NewLanguageId;
620 BOOL RefreshPage = FALSE;
621
622 /* Initialize the computer settings list */
623 if (LanguageList == NULL)
624 {
625 LanguageList = CreateLanguageList(SetupInf, DefaultLanguage);
626
627 if (LanguageList == NULL)
628 {
629 PopupError("Setup failed to initialize available translations", NULL, NULL, POPUP_WAIT_NONE);
630 return INTRO_PAGE;
631 }
632 }
633
634 /* Load the font */
635 SelectedLanguageId = DefaultLanguage;
636 SetConsoleCodePage();
637
638 DrawGenericList(LanguageList,
639 2,
640 18,
641 xScreen - 3,
642 yScreen - 3);
643
644 ScrollToPositionGenericList (LanguageList, GetDefaultLanguageIndex());
645
646 MUIDisplayPage(LANGUAGE_PAGE);
647
648 while (TRUE)
649 {
650 CONSOLE_ConInKey(Ir);
651
652 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
653 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
654 {
655 ScrollDownGenericList (LanguageList);
656 RefreshPage = TRUE;
657 }
658 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
659 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
660 {
661 ScrollUpGenericList(LanguageList);
662 RefreshPage = TRUE;
663 }
664 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
665 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_NEXT)) /* PAGE DOWN */
666 {
667 ScrollPageDownGenericList(LanguageList);
668 RefreshPage = TRUE;
669 }
670 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
671 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_PRIOR)) /* PAGE UP */
672 {
673 ScrollPageUpGenericList(LanguageList);
674 RefreshPage = TRUE;
675 }
676 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
677 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
678 {
679 if (ConfirmQuit(Ir) == TRUE)
680 return QUIT_PAGE;
681 else
682 RedrawGenericList(LanguageList);
683 }
684 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
685 {
686 SelectedLanguageId = (PWCHAR)GetListEntryUserData(GetCurrentListEntry(LanguageList));
687
688 LanguageId = (LANGID)(wcstol(SelectedLanguageId, NULL, 16) & 0xFFFF);
689
690 if (wcscmp(SelectedLanguageId, DefaultLanguage))
691 {
692 UpdateKBLayout();
693 }
694
695 /* Load the font */
696 SetConsoleCodePage();
697
698 return INTRO_PAGE;
699 }
700 else if ((Ir->Event.KeyEvent.uChar.AsciiChar > 0x60) && (Ir->Event.KeyEvent.uChar.AsciiChar < 0x7b))
701 {
702 /* a-z */
703 GenericListKeyPress (LanguageList, Ir->Event.KeyEvent.uChar.AsciiChar);
704 RefreshPage = TRUE;
705 }
706
707 if (RefreshPage)
708 {
709 NewLanguageId = (PWCHAR)GetListEntryUserData(GetCurrentListEntry(LanguageList));
710
711 if (SelectedLanguageId != NewLanguageId)
712 {
713 /* Clear the language page */
714 MUIClearPage(LANGUAGE_PAGE);
715
716 SelectedLanguageId = NewLanguageId;
717
718 /* Load the font */
719 SetConsoleCodePage();
720
721 /* Redraw language selection page in native language */
722 MUIDisplayPage(LANGUAGE_PAGE);
723 }
724
725 RefreshPage = FALSE;
726 }
727 }
728
729 return INTRO_PAGE;
730 }
731
732
733 /*
734 * Start page
735 * RETURNS
736 * Number of the next page.
737 */
738 static PAGE_NUMBER
739 SetupStartPage(PINPUT_RECORD Ir)
740 {
741 //SYSTEM_DEVICE_INFORMATION Sdi;
742 NTSTATUS Status;
743 WCHAR FileNameBuffer[MAX_PATH];
744 INFCONTEXT Context;
745 PWCHAR Value;
746 UINT ErrorLine;
747 //ULONG ReturnSize;
748 PGENERIC_LIST_ENTRY ListEntry;
749 INT IntValue;
750
751 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
752
753 #if 0
754 /* Check whether a harddisk is available */
755 Status = NtQuerySystemInformation(SystemDeviceInformation,
756 &Sdi,
757 sizeof(SYSTEM_DEVICE_INFORMATION),
758 &ReturnSize);
759
760 if (!NT_SUCCESS(Status))
761 {
762 CONSOLE_PrintTextXY(6, 15, "NtQuerySystemInformation() failed (Status 0x%08lx)", Status);
763 MUIDisplayError(ERROR_DRIVE_INFORMATION, Ir, POPUP_WAIT_ENTER);
764 return QUIT_PAGE;
765 }
766
767 if (Sdi.NumberOfDisks == 0)
768 {
769 MUIDisplayError(ERROR_NO_HDD, Ir, POPUP_WAIT_ENTER);
770 return QUIT_PAGE;
771 }
772 #endif
773
774 /* Get the source path and source root path */
775 Status = GetSourcePaths(&SourcePath,
776 &SourceRootPath,
777 &SourceRootDir);
778
779 if (!NT_SUCCESS(Status))
780 {
781 CONSOLE_PrintTextXY(6, 15, "GetSourcePaths() failed (Status 0x%08lx)", Status);
782 MUIDisplayError(ERROR_NO_SOURCE_DRIVE, Ir, POPUP_WAIT_ENTER);
783 return QUIT_PAGE;
784 }
785 #if 0
786 else
787 {
788 CONSOLE_PrintTextXY(6, 15, "SourcePath: '%wZ'", &SourcePath);
789 CONSOLE_PrintTextXY(6, 16, "SourceRootPath: '%wZ'", &SourceRootPath);
790 CONSOLE_PrintTextXY(6, 17, "SourceRootDir: '%wZ'", &SourceRootDir);
791 }
792 #endif
793
794 /* Load txtsetup.sif from install media. */
795 wcscpy(FileNameBuffer, SourcePath.Buffer);
796 wcscat(FileNameBuffer, L"\\txtsetup.sif");
797
798 SetupInf = SetupOpenInfFileW(FileNameBuffer,
799 NULL,
800 INF_STYLE_WIN4,
801 LanguageId,
802 &ErrorLine);
803
804 if (SetupInf == INVALID_HANDLE_VALUE)
805 {
806 MUIDisplayError(ERROR_LOAD_TXTSETUPSIF, Ir, POPUP_WAIT_ENTER);
807 return QUIT_PAGE;
808 }
809
810 /* Open 'Version' section */
811 if (!SetupFindFirstLineW(SetupInf, L"Version", L"Signature", &Context))
812 {
813 MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF, Ir, POPUP_WAIT_ENTER);
814 return QUIT_PAGE;
815 }
816
817 /* Get pointer 'Signature' key */
818 if (!INF_GetData(&Context, NULL, &Value))
819 {
820 MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF, Ir, POPUP_WAIT_ENTER);
821 return QUIT_PAGE;
822 }
823
824 /* Check 'Signature' string */
825 if (_wcsicmp(Value, L"$ReactOS$") != 0)
826 {
827 MUIDisplayError(ERROR_SIGNATURE_TXTSETUPSIF, Ir, POPUP_WAIT_ENTER);
828 return QUIT_PAGE;
829 }
830
831 /* Open 'DiskSpaceRequirements' section */
832 if (!SetupFindFirstLineW(SetupInf, L"DiskSpaceRequirements", L"FreeSysPartDiskSpace", &Context))
833 {
834 MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF, Ir, POPUP_WAIT_ENTER);
835 return QUIT_PAGE;
836 }
837
838 /* Get the 'FreeSysPartDiskSpace' value */
839 if (!SetupGetIntField(&Context, 1, &IntValue))
840 {
841 MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF, Ir, POPUP_WAIT_ENTER);
842 return QUIT_PAGE;
843 }
844
845 RequiredPartitionDiskSpace = (ULONG)IntValue;
846
847 /* Start PnP thread */
848 if (hPnpThread != INVALID_HANDLE_VALUE)
849 {
850 NtResumeThread(hPnpThread, NULL);
851 hPnpThread = INVALID_HANDLE_VALUE;
852 }
853
854 CheckUnattendedSetup();
855
856 if (IsUnattendedSetup)
857 {
858 //TODO
859 //read options from inf
860 ComputerList = CreateComputerTypeList(SetupInf);
861 DisplayList = CreateDisplayDriverList(SetupInf);
862 KeyboardList = CreateKeyboardDriverList(SetupInf);
863 LayoutList = CreateKeyboardLayoutList(SetupInf, DefaultKBLayout);
864 LanguageList = CreateLanguageList(SetupInf, DefaultLanguage);
865
866 /* new part */
867 wcscpy(SelectedLanguageId,LocaleID);
868
869 /* first we hack LanguageList */
870 ListEntry = GetFirstListEntry(LanguageList);
871
872 while (ListEntry != NULL)
873 {
874 if (!wcsicmp(LocaleID, GetListEntryUserData(ListEntry)))
875 {
876 DPRINT("found %S in LanguageList\n",GetListEntryUserData(ListEntry));
877 SetCurrentListEntry(LanguageList, ListEntry);
878 break;
879 }
880
881 ListEntry = GetNextListEntry(ListEntry);
882 }
883
884 /* now LayoutList */
885 ListEntry = GetFirstListEntry(LayoutList);
886
887 while (ListEntry != NULL)
888 {
889 if (!wcsicmp(LocaleID, GetListEntryUserData(ListEntry)))
890 {
891 DPRINT("found %S in LayoutList\n",GetListEntryUserData(ListEntry));
892 SetCurrentListEntry(LayoutList, ListEntry);
893 break;
894 }
895
896 ListEntry = GetNextListEntry(ListEntry);
897 }
898
899 SetConsoleCodePage();
900
901 return INSTALL_INTRO_PAGE;
902 }
903
904 return LANGUAGE_PAGE;
905 }
906
907
908 /*
909 * First setup page
910 * RETURNS
911 * Next page number.
912 */
913 static PAGE_NUMBER
914 IntroPage(PINPUT_RECORD Ir)
915 {
916 MUIDisplayPage(START_PAGE);
917
918 while (TRUE)
919 {
920 CONSOLE_ConInKey(Ir);
921
922 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
923 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
924 {
925 if (ConfirmQuit(Ir) == TRUE)
926 return QUIT_PAGE;
927
928 break;
929 }
930 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
931 {
932 return INSTALL_INTRO_PAGE;
933 break;
934 }
935 else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'R') /* R */
936 {
937 return REPAIR_INTRO_PAGE;
938 break;
939 }
940 else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'L') /* R */
941 {
942 return LICENSE_PAGE;
943 break;
944 }
945 }
946
947 return INTRO_PAGE;
948 }
949
950
951 /*
952 * License Page
953 * RETURNS
954 * Back to main setup page.
955 */
956 static PAGE_NUMBER
957 LicensePage(PINPUT_RECORD Ir)
958 {
959 MUIDisplayPage(LICENSE_PAGE);
960
961 while (TRUE)
962 {
963 CONSOLE_ConInKey(Ir);
964
965 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
966 {
967 return INTRO_PAGE;
968 break;
969 }
970 }
971
972 return LICENSE_PAGE;
973 }
974
975
976 static PAGE_NUMBER
977 RepairIntroPage(PINPUT_RECORD Ir)
978 {
979 MUIDisplayPage(REPAIR_INTRO_PAGE);
980
981 while(TRUE)
982 {
983 CONSOLE_ConInKey(Ir);
984
985 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
986 {
987 return REBOOT_PAGE;
988 }
989 else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'U') /* U */
990 {
991 RepairUpdateFlag = TRUE;
992 return INSTALL_INTRO_PAGE;
993 }
994 else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'R') /* R */
995 {
996 return INTRO_PAGE;
997 }
998 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
999 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
1000 {
1001 return INTRO_PAGE;
1002 }
1003 }
1004
1005 return REPAIR_INTRO_PAGE;
1006 }
1007
1008
1009 static PAGE_NUMBER
1010 InstallIntroPage(PINPUT_RECORD Ir)
1011 {
1012 MUIDisplayPage(INSTALL_INTRO_PAGE);
1013
1014 if (RepairUpdateFlag)
1015 {
1016 //return SELECT_PARTITION_PAGE;
1017 return DEVICE_SETTINGS_PAGE;
1018 }
1019
1020 if (IsUnattendedSetup)
1021 {
1022 return SELECT_PARTITION_PAGE;
1023 }
1024
1025 while (TRUE)
1026 {
1027 CONSOLE_ConInKey(Ir);
1028
1029 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1030 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1031 {
1032 if (ConfirmQuit(Ir) == TRUE)
1033 return QUIT_PAGE;
1034
1035 break;
1036 }
1037 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1038 {
1039 return DEVICE_SETTINGS_PAGE;
1040 // return SCSI_CONTROLLER_PAGE;
1041 }
1042 }
1043
1044 return INSTALL_INTRO_PAGE;
1045 }
1046
1047
1048 #if 0
1049 static PAGE_NUMBER
1050 ScsiControllerPage(PINPUT_RECORD Ir)
1051 {
1052 SetTextXY(6, 8, "Setup detected the following mass storage devices:");
1053
1054 /* FIXME: print loaded mass storage driver descriptions */
1055 #if 0
1056 SetTextXY(8, 10, "TEST device");
1057 #endif
1058
1059
1060 SetStatusText(" ENTER = Continue F3 = Quit");
1061
1062 while (TRUE)
1063 {
1064 ConInKey(Ir);
1065
1066 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1067 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1068 {
1069 if (ConfirmQuit(Ir) == TRUE)
1070 return QUIT_PAGE;
1071
1072 break;
1073 }
1074 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1075 {
1076 return DEVICE_SETTINGS_PAGE;
1077 }
1078 }
1079
1080 return SCSI_CONTROLLER_PAGE;
1081 }
1082 #endif
1083
1084
1085 static PAGE_NUMBER
1086 DeviceSettingsPage(PINPUT_RECORD Ir)
1087 {
1088 static ULONG Line = 16;
1089 MUIDisplayPage(DEVICE_SETTINGS_PAGE);
1090
1091 /* Initialize the computer settings list */
1092 if (ComputerList == NULL)
1093 {
1094 ComputerList = CreateComputerTypeList(SetupInf);
1095 if (ComputerList == NULL)
1096 {
1097 MUIDisplayError(ERROR_LOAD_COMPUTER, Ir, POPUP_WAIT_ENTER);
1098 return QUIT_PAGE;
1099 }
1100 }
1101
1102 /* Initialize the display settings list */
1103 if (DisplayList == NULL)
1104 {
1105 DisplayList = CreateDisplayDriverList(SetupInf);
1106 if (DisplayList == NULL)
1107 {
1108 MUIDisplayError(ERROR_LOAD_DISPLAY, Ir, POPUP_WAIT_ENTER);
1109 return QUIT_PAGE;
1110 }
1111 }
1112
1113 /* Initialize the keyboard settings list */
1114 if (KeyboardList == NULL)
1115 {
1116 KeyboardList = CreateKeyboardDriverList(SetupInf);
1117 if (KeyboardList == NULL)
1118 {
1119 MUIDisplayError(ERROR_LOAD_KEYBOARD, Ir, POPUP_WAIT_ENTER);
1120 return QUIT_PAGE;
1121 }
1122 }
1123
1124 /* Initialize the keyboard layout list */
1125 if (LayoutList == NULL)
1126 {
1127 LayoutList = CreateKeyboardLayoutList(SetupInf, DefaultKBLayout);
1128 if (LayoutList == NULL)
1129 {
1130 /* FIXME: report error */
1131 MUIDisplayError(ERROR_LOAD_KBLAYOUT, Ir, POPUP_WAIT_ENTER);
1132 return QUIT_PAGE;
1133 }
1134 }
1135
1136 MUIDisplayPage(DEVICE_SETTINGS_PAGE);
1137
1138
1139 CONSOLE_SetTextXY(25, 11, GetListEntryText(GetCurrentListEntry((ComputerList))));
1140 CONSOLE_SetTextXY(25, 12, GetListEntryText(GetCurrentListEntry((DisplayList))));
1141 CONSOLE_SetTextXY(25, 13, GetListEntryText(GetCurrentListEntry((KeyboardList))));
1142 CONSOLE_SetTextXY(25, 14, GetListEntryText(GetCurrentListEntry((LayoutList))));
1143
1144 CONSOLE_InvertTextXY(24, Line, 48, 1);
1145
1146 if (RepairUpdateFlag)
1147 {
1148 return SELECT_PARTITION_PAGE;
1149 }
1150
1151 while (TRUE)
1152 {
1153 CONSOLE_ConInKey(Ir);
1154
1155 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1156 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1157 {
1158 CONSOLE_NormalTextXY(24, Line, 48, 1);
1159
1160 if (Line == 14)
1161 Line = 16;
1162 else if (Line == 16)
1163 Line = 11;
1164 else
1165 Line++;
1166
1167 CONSOLE_InvertTextXY(24, Line, 48, 1);
1168 }
1169 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1170 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1171 {
1172 CONSOLE_NormalTextXY(24, Line, 48, 1);
1173
1174 if (Line == 11)
1175 Line = 16;
1176 else if (Line == 16)
1177 Line = 14;
1178 else
1179 Line--;
1180
1181 CONSOLE_InvertTextXY(24, Line, 48, 1);
1182 }
1183 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1184 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1185 {
1186 if (ConfirmQuit(Ir) == TRUE)
1187 return QUIT_PAGE;
1188
1189 break;
1190 }
1191 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1192 {
1193 if (Line == 11)
1194 return COMPUTER_SETTINGS_PAGE;
1195 else if (Line == 12)
1196 return DISPLAY_SETTINGS_PAGE;
1197 else if (Line == 13)
1198 return KEYBOARD_SETTINGS_PAGE;
1199 else if (Line == 14)
1200 return LAYOUT_SETTINGS_PAGE;
1201 else if (Line == 16)
1202 return SELECT_PARTITION_PAGE;
1203 }
1204 }
1205
1206 return DEVICE_SETTINGS_PAGE;
1207 }
1208
1209
1210 static PAGE_NUMBER
1211 ComputerSettingsPage(PINPUT_RECORD Ir)
1212 {
1213 MUIDisplayPage(COMPUTER_SETTINGS_PAGE);
1214
1215 DrawGenericList(ComputerList,
1216 2,
1217 18,
1218 xScreen - 3,
1219 yScreen - 3);
1220
1221 SaveGenericListState(ComputerList);
1222
1223 while (TRUE)
1224 {
1225 CONSOLE_ConInKey(Ir);
1226
1227 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1228 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1229 {
1230 ScrollDownGenericList(ComputerList);
1231 }
1232 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1233 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1234 {
1235 ScrollUpGenericList(ComputerList);
1236 }
1237 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1238 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1239 {
1240 if (ConfirmQuit(Ir) == TRUE)
1241 return QUIT_PAGE;
1242
1243 break;
1244 }
1245 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1246 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
1247 {
1248 RestoreGenericListState(ComputerList);
1249 return DEVICE_SETTINGS_PAGE;
1250 }
1251 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1252 {
1253 return DEVICE_SETTINGS_PAGE;
1254 }
1255 }
1256
1257 return COMPUTER_SETTINGS_PAGE;
1258 }
1259
1260
1261 static PAGE_NUMBER
1262 DisplaySettingsPage(PINPUT_RECORD Ir)
1263 {
1264 MUIDisplayPage(DISPLAY_SETTINGS_PAGE);
1265
1266 DrawGenericList(DisplayList,
1267 2,
1268 18,
1269 xScreen - 3,
1270 yScreen - 3);
1271
1272 SaveGenericListState(DisplayList);
1273
1274 while (TRUE)
1275 {
1276 CONSOLE_ConInKey(Ir);
1277
1278 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1279 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1280 {
1281 ScrollDownGenericList(DisplayList);
1282 }
1283 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1284 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1285 {
1286 ScrollUpGenericList(DisplayList);
1287 }
1288 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1289 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1290 {
1291 if (ConfirmQuit(Ir) == TRUE)
1292 {
1293 return QUIT_PAGE;
1294 }
1295
1296 break;
1297 }
1298 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1299 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
1300 {
1301 RestoreGenericListState(DisplayList);
1302 return DEVICE_SETTINGS_PAGE;
1303 }
1304 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1305 {
1306 return DEVICE_SETTINGS_PAGE;
1307 }
1308 }
1309
1310 return DISPLAY_SETTINGS_PAGE;
1311 }
1312
1313
1314 static PAGE_NUMBER
1315 KeyboardSettingsPage(PINPUT_RECORD Ir)
1316 {
1317 MUIDisplayPage(KEYBOARD_SETTINGS_PAGE);
1318
1319 DrawGenericList(KeyboardList,
1320 2,
1321 18,
1322 xScreen - 3,
1323 yScreen - 3);
1324
1325 SaveGenericListState(KeyboardList);
1326
1327 while (TRUE)
1328 {
1329 CONSOLE_ConInKey(Ir);
1330
1331 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1332 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1333 {
1334 ScrollDownGenericList(KeyboardList);
1335 }
1336 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1337 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1338 {
1339 ScrollUpGenericList(KeyboardList);
1340 }
1341 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1342 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1343 {
1344 if (ConfirmQuit(Ir) == TRUE)
1345 return QUIT_PAGE;
1346
1347 break;
1348 }
1349 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1350 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
1351 {
1352 RestoreGenericListState(KeyboardList);
1353 return DEVICE_SETTINGS_PAGE;
1354 }
1355 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1356 {
1357 return DEVICE_SETTINGS_PAGE;
1358 }
1359 }
1360
1361 return KEYBOARD_SETTINGS_PAGE;
1362 }
1363
1364
1365 static PAGE_NUMBER
1366 LayoutSettingsPage(PINPUT_RECORD Ir)
1367 {
1368 MUIDisplayPage(LAYOUT_SETTINGS_PAGE);
1369
1370 DrawGenericList(LayoutList,
1371 2,
1372 18,
1373 xScreen - 3,
1374 yScreen - 3);
1375
1376 SaveGenericListState(LayoutList);
1377
1378 while (TRUE)
1379 {
1380 CONSOLE_ConInKey(Ir);
1381
1382 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1383 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1384 {
1385 ScrollDownGenericList(LayoutList);
1386 }
1387 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1388 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1389 {
1390 ScrollUpGenericList(LayoutList);
1391 }
1392 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1393 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_NEXT)) /* PAGE DOWN */
1394 {
1395 ScrollPageDownGenericList(LayoutList);
1396 }
1397 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1398 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_PRIOR)) /* PAGE UP */
1399 {
1400 ScrollPageUpGenericList(LayoutList);
1401 }
1402 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1403 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1404 {
1405 if (ConfirmQuit(Ir) == TRUE)
1406 return QUIT_PAGE;
1407
1408 break;
1409 }
1410 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1411 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
1412 {
1413 RestoreGenericListState(LayoutList);
1414 return DEVICE_SETTINGS_PAGE;
1415 }
1416 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1417 {
1418 return DEVICE_SETTINGS_PAGE;
1419 }
1420 else if ((Ir->Event.KeyEvent.uChar.AsciiChar > 0x60) && (Ir->Event.KeyEvent.uChar.AsciiChar < 0x7b))
1421 {
1422 /* a-z */
1423 GenericListKeyPress(LayoutList , Ir->Event.KeyEvent.uChar.AsciiChar);
1424 }
1425 }
1426
1427 return LAYOUT_SETTINGS_PAGE;
1428 }
1429
1430
1431 static BOOL
1432 IsDiskSizeValid(PPARTENTRY PartEntry)
1433 {
1434 ULONGLONG m1, m2;
1435
1436 /* check for unpartitioned space */
1437 m1 = PartEntry->UnpartitionedLength;
1438 m1 = (m1 + (1 << 19)) >> 20; /* in MBytes (rounded) */
1439
1440 if( m1 > RequiredPartitionDiskSpace)
1441 {
1442 return TRUE;
1443 }
1444
1445 /* check for partitioned space */
1446 m2 = PartEntry->PartInfo[0].PartitionLength.QuadPart;
1447 m2 = (m2 + (1 << 19)) >> 20; /* in MBytes (rounded) */
1448 if (m2 < RequiredPartitionDiskSpace)
1449 {
1450 /* partition is too small so ask for another partion */
1451 DPRINT1("Partition is too small(unpartitioned: %I64u MB, partitioned: %I64u MB), required disk space is %lu MB\n", m1, m2, RequiredPartitionDiskSpace);
1452 return FALSE;
1453 }
1454 else
1455 {
1456 return TRUE;
1457 }
1458 }
1459
1460
1461 static PAGE_NUMBER
1462 SelectPartitionPage(PINPUT_RECORD Ir)
1463 {
1464 MUIDisplayPage(SELECT_PARTITION_PAGE);
1465
1466 if (PartitionList == NULL)
1467 {
1468 PartitionList = CreatePartitionList(2,
1469 19,
1470 xScreen - 3,
1471 yScreen - 3);
1472 if (PartitionList == NULL)
1473 {
1474 /* FIXME: show an error dialog */
1475 return QUIT_PAGE;
1476 }
1477 else if (IsListEmpty (&PartitionList->DiskListHead))
1478 {
1479 MUIDisplayError(ERROR_NO_HDD, Ir, POPUP_WAIT_ENTER);
1480 return QUIT_PAGE;
1481 }
1482 }
1483
1484 DrawPartitionList(PartitionList);
1485
1486 /* Warn about partitions created by Linux Fdisk */
1487 if (WarnLinuxPartitions == TRUE &&
1488 CheckForLinuxFdiskPartitions(PartitionList) == TRUE)
1489 {
1490 MUIDisplayError(ERROR_WARN_PARTITION, NULL, POPUP_WAIT_NONE);
1491
1492 while (TRUE)
1493 {
1494 CONSOLE_ConInKey(Ir);
1495
1496 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1497 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1498 {
1499 return QUIT_PAGE;
1500 }
1501 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
1502 {
1503 WarnLinuxPartitions = FALSE;
1504 return SELECT_PARTITION_PAGE;
1505 }
1506 }
1507 }
1508
1509 if (IsUnattendedSetup)
1510 {
1511 if (!SelectPartition(PartitionList, UnattendDestinationDiskNumber, UnattendDestinationPartitionNumber))
1512 {
1513 if (AutoPartition)
1514 {
1515 PPARTENTRY PartEntry = PartitionList->CurrentPartition;
1516 ULONG MaxSize = (PartEntry->UnpartitionedLength + (1 << 19)) >> 20; /* in MBytes (rounded) */
1517 if(!IsDiskSizeValid(PartitionList->CurrentPartition))
1518 {
1519 MUIDisplayError(ERROR_INSUFFICIENT_DISKSPACE, Ir, POPUP_WAIT_ANY_KEY);
1520 return SELECT_PARTITION_PAGE; /* let the user select another partition */
1521 }
1522
1523 CreateNewPartition(PartitionList,
1524 MaxSize,
1525 TRUE);
1526
1527 return SELECT_FILE_SYSTEM_PAGE;
1528 }
1529 }
1530 else
1531 {
1532 if(!IsDiskSizeValid(PartitionList->CurrentPartition))
1533 {
1534 MUIDisplayError(ERROR_INSUFFICIENT_DISKSPACE, Ir, POPUP_WAIT_ANY_KEY);
1535 return SELECT_PARTITION_PAGE; /* let the user select another partition */
1536 }
1537
1538 return SELECT_FILE_SYSTEM_PAGE;
1539 }
1540 }
1541
1542 while (TRUE)
1543 {
1544 /* Update status text */
1545 if (PartitionList->CurrentPartition == NULL ||
1546 PartitionList->CurrentPartition->Unpartitioned == TRUE)
1547 {
1548 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATEPARTITION));
1549 }
1550 else
1551 {
1552 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLDELETEPARTITION));
1553 }
1554
1555 CONSOLE_ConInKey(Ir);
1556
1557 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1558 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1559 {
1560 if (ConfirmQuit(Ir) == TRUE)
1561 {
1562 DestroyPartitionList(PartitionList);
1563 PartitionList = NULL;
1564 return QUIT_PAGE;
1565 }
1566
1567 break;
1568 }
1569 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1570 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1571 {
1572 ScrollDownPartitionList(PartitionList);
1573 }
1574 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1575 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1576 {
1577 ScrollUpPartitionList(PartitionList);
1578 }
1579 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
1580 {
1581 if(!IsDiskSizeValid(PartitionList->CurrentPartition))
1582 {
1583 MUIDisplayError(ERROR_INSUFFICIENT_DISKSPACE, Ir, POPUP_WAIT_ANY_KEY);
1584 return SELECT_PARTITION_PAGE; /* let the user select another partition */
1585 }
1586 if (PartitionList->CurrentPartition == NULL ||
1587 PartitionList->CurrentPartition->Unpartitioned == TRUE)
1588 {
1589 CreateNewPartition(PartitionList,
1590 0ULL,
1591 TRUE);
1592 }
1593
1594 DestinationDriveLetter = (WCHAR)PartitionList->CurrentPartition->DriveLetter[0];
1595
1596 return SELECT_FILE_SYSTEM_PAGE;
1597 }
1598 else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'C') /* C */
1599 {
1600 if (PartitionList->CurrentPartition->Unpartitioned == FALSE)
1601 {
1602 MUIDisplayError(ERROR_NEW_PARTITION, Ir, POPUP_WAIT_ANY_KEY);
1603 return SELECT_PARTITION_PAGE;
1604 }
1605
1606 return CREATE_PARTITION_PAGE;
1607 }
1608 else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'D') /* D */
1609 {
1610 if (PartitionList->CurrentPartition->Unpartitioned == TRUE)
1611 {
1612 MUIDisplayError(ERROR_DELETE_SPACE, Ir, POPUP_WAIT_ANY_KEY);
1613 return SELECT_PARTITION_PAGE;
1614 }
1615
1616 return DELETE_PARTITION_PAGE;
1617 }
1618 }
1619
1620 return SELECT_PARTITION_PAGE;
1621 }
1622
1623
1624 static VOID
1625 DrawInputField(ULONG FieldLength,
1626 SHORT Left,
1627 SHORT Top,
1628 PCHAR FieldContent)
1629 {
1630 CHAR buf[100];
1631 COORD coPos;
1632 DWORD Written;
1633
1634 coPos.X = Left;
1635 coPos.Y = Top;
1636 memset(buf, '_', sizeof(buf));
1637 buf[FieldLength - strlen(FieldContent)] = 0;
1638 strcat(buf, FieldContent);
1639
1640 WriteConsoleOutputCharacterA(StdOutput,
1641 buf,
1642 strlen(buf),
1643 coPos,
1644 &Written);
1645 }
1646
1647
1648 #define PARTITION_SIZE_INPUT_FIELD_LENGTH 6
1649 /* Restriction for MaxSize: pow(10, PARTITION_SIZE_INPUT_FIELD_LENGTH)-1 */
1650 #define PARTITION_MAXSIZE 999999
1651
1652 static VOID
1653 ShowPartitionSizeInputBox(SHORT Left,
1654 SHORT Top,
1655 SHORT Right,
1656 SHORT Bottom,
1657 ULONG MaxSize,
1658 PCHAR InputBuffer,
1659 PBOOLEAN Quit,
1660 PBOOLEAN Cancel)
1661 {
1662 INPUT_RECORD Ir;
1663 COORD coPos;
1664 DWORD Written;
1665 CHAR Buffer[100];
1666 ULONG Index;
1667 CHAR ch;
1668 SHORT iLeft;
1669 SHORT iTop;
1670
1671 if (Quit != NULL)
1672 *Quit = FALSE;
1673
1674 if (Cancel != NULL)
1675 *Cancel = FALSE;
1676
1677 DrawBox(Left, Top, Right - Left + 1, Bottom - Top + 1);
1678
1679 /* Print message */
1680 coPos.X = Left + 2;
1681 coPos.Y = Top + 2;
1682 strcpy(Buffer, MUIGetString(STRING_PARTITIONSIZE));
1683 iLeft = coPos.X + strlen(Buffer) + 1;
1684 iTop = coPos.Y;
1685
1686 WriteConsoleOutputCharacterA(StdOutput,
1687 Buffer,
1688 strlen (Buffer),
1689 coPos,
1690 &Written);
1691
1692 sprintf(Buffer, MUIGetString(STRING_MAXSIZE), MaxSize);
1693 coPos.X = iLeft + PARTITION_SIZE_INPUT_FIELD_LENGTH + 1;
1694 coPos.Y = iTop;
1695 WriteConsoleOutputCharacterA(StdOutput,
1696 Buffer,
1697 strlen (Buffer),
1698 coPos,
1699 &Written);
1700
1701 sprintf(Buffer, "%lu", MaxSize);
1702 Index = strlen(Buffer);
1703 DrawInputField(PARTITION_SIZE_INPUT_FIELD_LENGTH,
1704 iLeft,
1705 iTop,
1706 Buffer);
1707
1708 while (TRUE)
1709 {
1710 CONSOLE_ConInKey(&Ir);
1711
1712 if ((Ir.Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1713 (Ir.Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1714 {
1715 if (Quit != NULL)
1716 *Quit = TRUE;
1717
1718 Buffer[0] = 0;
1719 break;
1720 }
1721 else if (Ir.Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
1722 {
1723 break;
1724 }
1725 else if (Ir.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESCAPE */
1726 {
1727 if (Cancel != NULL)
1728 *Cancel = TRUE;
1729
1730 Buffer[0] = 0;
1731 break;
1732 }
1733 else if ((Ir.Event.KeyEvent.wVirtualKeyCode == VK_BACK) && /* BACKSPACE */
1734 (Index > 0))
1735 {
1736 Index--;
1737 Buffer[Index] = 0;
1738
1739 DrawInputField(PARTITION_SIZE_INPUT_FIELD_LENGTH,
1740 iLeft,
1741 iTop,
1742 Buffer);
1743 }
1744 else if ((Ir.Event.KeyEvent.uChar.AsciiChar != 0x00) &&
1745 (Index < PARTITION_SIZE_INPUT_FIELD_LENGTH))
1746 {
1747 ch = Ir.Event.KeyEvent.uChar.AsciiChar;
1748
1749 if ((ch >= '0') && (ch <= '9'))
1750 {
1751 Buffer[Index] = ch;
1752 Index++;
1753 Buffer[Index] = 0;
1754
1755 DrawInputField(PARTITION_SIZE_INPUT_FIELD_LENGTH,
1756 iLeft,
1757 iTop,
1758 Buffer);
1759 }
1760 }
1761 }
1762
1763 strcpy(InputBuffer, Buffer);
1764 }
1765
1766
1767 static PAGE_NUMBER
1768 CreatePartitionPage(PINPUT_RECORD Ir)
1769 {
1770 PDISKENTRY DiskEntry;
1771 PPARTENTRY PartEntry;
1772 BOOLEAN Quit;
1773 BOOLEAN Cancel;
1774 CHAR InputBuffer[50];
1775 ULONG MaxSize;
1776 ULONGLONG PartSize;
1777 ULONGLONG DiskSize;
1778 PCHAR Unit;
1779
1780 if (PartitionList == NULL ||
1781 PartitionList->CurrentDisk == NULL ||
1782 PartitionList->CurrentPartition == NULL)
1783 {
1784 /* FIXME: show an error dialog */
1785 return QUIT_PAGE;
1786 }
1787
1788 DiskEntry = PartitionList->CurrentDisk;
1789 PartEntry = PartitionList->CurrentPartition;
1790
1791 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
1792
1793 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSENEWPARTITION));
1794
1795 #if 0
1796 if (DiskEntry->DiskSize >= 0x280000000ULL) /* 10 GB */
1797 {
1798 DiskSize = (DiskEntry->DiskSize + (1 << 29)) >> 30;
1799 Unit = MUIGetString(STRING_GB);
1800 }
1801 else
1802 #endif
1803 {
1804 DiskSize = (DiskEntry->DiskSize + (1 << 19)) >> 20;
1805
1806 if (DiskSize == 0)
1807 DiskSize = 1;
1808
1809 Unit = MUIGetString(STRING_MB);
1810 }
1811
1812 if (DiskEntry->DriverName.Length > 0)
1813 {
1814 CONSOLE_PrintTextXY(6, 10,
1815 MUIGetString(STRING_HDINFOPARTCREATE),
1816 DiskSize,
1817 Unit,
1818 DiskEntry->DiskNumber,
1819 DiskEntry->Port,
1820 DiskEntry->Bus,
1821 DiskEntry->Id,
1822 &DiskEntry->DriverName);
1823 }
1824 else
1825 {
1826 CONSOLE_PrintTextXY(6, 10,
1827 MUIGetString(STRING_HDDINFOUNK1),
1828 DiskSize,
1829 Unit,
1830 DiskEntry->DiskNumber,
1831 DiskEntry->Port,
1832 DiskEntry->Bus,
1833 DiskEntry->Id);
1834 }
1835
1836 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE));
1837
1838 #if 0
1839 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
1840 PartitionList->CurrentPartition->UnpartitionedLength / (1024*1024));
1841 #endif
1842
1843 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION));
1844
1845 PartEntry = PartitionList->CurrentPartition;
1846 while (TRUE)
1847 {
1848 MaxSize = (PartEntry->UnpartitionedLength + (1 << 19)) >> 20; /* in MBytes (rounded) */
1849
1850 if (MaxSize > PARTITION_MAXSIZE) MaxSize = PARTITION_MAXSIZE;
1851
1852 ShowPartitionSizeInputBox(12, 14, xScreen - 12, 17, /* left, top, right, bottom */
1853 MaxSize, InputBuffer, &Quit, &Cancel);
1854
1855 if (Quit == TRUE)
1856 {
1857 if (ConfirmQuit (Ir) == TRUE)
1858 {
1859 return QUIT_PAGE;
1860 }
1861 }
1862 else if (Cancel == TRUE)
1863 {
1864 return SELECT_PARTITION_PAGE;
1865 }
1866 else
1867 {
1868 PartSize = atoi(InputBuffer);
1869
1870 if (PartSize < 1)
1871 {
1872 /* Too small */
1873 continue;
1874 }
1875
1876 if (PartSize > MaxSize)
1877 {
1878 /* Too large */
1879 continue;
1880 }
1881
1882 /* Convert to bytes */
1883 if (PartSize == MaxSize)
1884 {
1885 /* Use all of the unpartitioned disk space */
1886 PartSize = PartEntry->UnpartitionedLength;
1887 }
1888 else
1889 {
1890 /* Round-up by cylinder size */
1891 PartSize = (PartSize * 1024 * 1024 + DiskEntry->CylinderSize - 1) /
1892 DiskEntry->CylinderSize * DiskEntry->CylinderSize;
1893
1894 /* But never get larger than the unpartitioned disk space */
1895 if (PartSize > PartEntry->UnpartitionedLength)
1896 PartSize = PartEntry->UnpartitionedLength;
1897 }
1898
1899 DPRINT ("Partition size: %I64u bytes\n", PartSize);
1900
1901 CreateNewPartition(PartitionList,
1902 PartSize,
1903 FALSE);
1904
1905 return SELECT_PARTITION_PAGE;
1906 }
1907 }
1908
1909 return CREATE_PARTITION_PAGE;
1910 }
1911
1912
1913 static PAGE_NUMBER
1914 DeletePartitionPage(PINPUT_RECORD Ir)
1915 {
1916 PDISKENTRY DiskEntry;
1917 PPARTENTRY PartEntry;
1918 ULONGLONG DiskSize;
1919 ULONGLONG PartSize;
1920 PCHAR Unit;
1921 PCHAR PartType;
1922 UCHAR PartNumber;
1923
1924 if (PartitionList == NULL ||
1925 PartitionList->CurrentDisk == NULL ||
1926 PartitionList->CurrentPartition == NULL)
1927 {
1928 /* FIXME: show an error dialog */
1929 return QUIT_PAGE;
1930 }
1931
1932 DiskEntry = PartitionList->CurrentDisk;
1933 PartEntry = PartitionList->CurrentPartition;
1934 PartNumber = PartitionList->CurrentPartitionNumber;
1935
1936 MUIDisplayPage(DELETE_PARTITION_PAGE);
1937
1938 /* Determine partition type */
1939 PartType = NULL;
1940 if (PartEntry->New == TRUE)
1941 {
1942 PartType = MUIGetString(STRING_UNFORMATTED);
1943 }
1944 else if (PartEntry->Unpartitioned == FALSE)
1945 {
1946 if ((PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_FAT_12) ||
1947 (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_FAT_16) ||
1948 (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_HUGE) ||
1949 (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_XINT13))
1950 {
1951 PartType = "FAT";
1952 }
1953 else if ((PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_FAT32) ||
1954 (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_FAT32_XINT13))
1955 {
1956 PartType = "FAT32";
1957 }
1958 else if (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_EXT2)
1959 {
1960 PartType = "EXT2";
1961 }
1962 else if (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_IFS)
1963 {
1964 PartType = "NTFS"; /* FIXME: Not quite correct! */
1965 }
1966 }
1967
1968 #if 0
1969 if (PartEntry->PartInfo[PartNumber].PartitionLength.QuadPart >= 0x280000000LL) /* 10 GB */
1970 {
1971 PartSize = (PartEntry->PartInfo[PartNumber].PartitionLength.QuadPart + (1 << 29)) >> 30;
1972 Unit = MUIGetString(STRING_GB);
1973 }
1974 else
1975 #endif
1976 if (PartEntry->PartInfo[PartNumber].PartitionLength.QuadPart >= 0xA00000LL) /* 10 MB */
1977 {
1978 PartSize = (PartEntry->PartInfo[PartNumber].PartitionLength.QuadPart + (1 << 19)) >> 20;
1979 Unit = MUIGetString(STRING_MB);
1980 }
1981 else
1982 {
1983 PartSize = (PartEntry->PartInfo[PartNumber].PartitionLength.QuadPart + (1 << 9)) >> 10;
1984 Unit = MUIGetString(STRING_KB);
1985 }
1986
1987 if (PartType == NULL)
1988 {
1989 CONSOLE_PrintTextXY(6, 10,
1990 MUIGetString(STRING_HDDINFOUNK2),
1991 (PartEntry->DriveLetter[PartNumber] == 0) ? '-' : PartEntry->DriveLetter[PartNumber],
1992 (PartEntry->DriveLetter[PartNumber] == 0) ? '-' : ':',
1993 PartEntry->PartInfo[PartNumber].PartitionType,
1994 PartSize,
1995 Unit);
1996 }
1997 else
1998 {
1999 CONSOLE_PrintTextXY(6, 10,
2000 " %c%c %s %I64u %s",
2001 (PartEntry->DriveLetter[PartNumber] == 0) ? '-' : PartEntry->DriveLetter[PartNumber],
2002 (PartEntry->DriveLetter[PartNumber] == 0) ? '-' : ':',
2003 PartType,
2004 PartSize,
2005 Unit);
2006 }
2007
2008 #if 0
2009 if (DiskEntry->DiskSize >= 0x280000000ULL) /* 10 GB */
2010 {
2011 DiskSize = (DiskEntry->DiskSize + (1 << 29)) >> 30;
2012 Unit = MUIGetString(STRING_GB);
2013 }
2014 else
2015 #endif
2016 {
2017 DiskSize = (DiskEntry->DiskSize + (1 << 19)) >> 20;
2018
2019 if (DiskSize == 0)
2020 DiskSize = 1;
2021
2022 Unit = MUIGetString(STRING_MB);
2023 }
2024
2025 if (DiskEntry->DriverName.Length > 0)
2026 {
2027 CONSOLE_PrintTextXY(6, 12,
2028 MUIGetString(STRING_HDINFOPARTDELETE),
2029 DiskSize,
2030 Unit,
2031 DiskEntry->DiskNumber,
2032 DiskEntry->Port,
2033 DiskEntry->Bus,
2034 DiskEntry->Id,
2035 &DiskEntry->DriverName);
2036 }
2037 else
2038 {
2039 CONSOLE_PrintTextXY(6, 12,
2040 MUIGetString(STRING_HDDINFOUNK3),
2041 DiskSize,
2042 Unit,
2043 DiskEntry->DiskNumber,
2044 DiskEntry->Port,
2045 DiskEntry->Bus,
2046 DiskEntry->Id);
2047 }
2048
2049 while (TRUE)
2050 {
2051 CONSOLE_ConInKey(Ir);
2052
2053 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2054 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
2055 {
2056 if (ConfirmQuit(Ir) == TRUE)
2057 {
2058 return QUIT_PAGE;
2059 }
2060
2061 break;
2062 }
2063 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESC */
2064 {
2065 return SELECT_PARTITION_PAGE;
2066 }
2067 else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'D') /* D */
2068 {
2069 DeleteCurrentPartition(PartitionList);
2070
2071 return SELECT_PARTITION_PAGE;
2072 }
2073 }
2074
2075 return DELETE_PARTITION_PAGE;
2076 }
2077
2078
2079 static PAGE_NUMBER
2080 SelectFileSystemPage(PINPUT_RECORD Ir)
2081 {
2082 PDISKENTRY DiskEntry;
2083 PPARTENTRY PartEntry;
2084 UCHAR PartNumber;
2085 ULONGLONG DiskSize;
2086 ULONGLONG PartSize;
2087 PCHAR DiskUnit;
2088 PCHAR PartUnit;
2089 PCHAR PartType;
2090
2091 if (PartitionList == NULL ||
2092 PartitionList->CurrentDisk == NULL ||
2093 PartitionList->CurrentPartition == NULL)
2094 {
2095 /* FIXME: show an error dialog */
2096 return QUIT_PAGE;
2097 }
2098
2099 DiskEntry = PartitionList->CurrentDisk;
2100 PartEntry = PartitionList->CurrentPartition;
2101 PartNumber = PartitionList->CurrentPartitionNumber;
2102
2103 /* adjust disk size */
2104 if (DiskEntry->DiskSize >= 0x280000000ULL) /* 10 GB */
2105 {
2106 DiskSize = (DiskEntry->DiskSize + (1 << 29)) >> 30;
2107 DiskUnit = MUIGetString(STRING_GB);
2108 }
2109 else
2110 {
2111 DiskSize = (DiskEntry->DiskSize + (1 << 19)) >> 20;
2112 DiskUnit = MUIGetString(STRING_MB);
2113 }
2114
2115 /* adjust partition size */
2116 if (PartEntry->PartInfo[PartNumber].PartitionLength.QuadPart >= 0x280000000LL) /* 10 GB */
2117 {
2118 PartSize = (PartEntry->PartInfo[PartNumber].PartitionLength.QuadPart + (1 << 29)) >> 30;
2119 PartUnit = MUIGetString(STRING_GB);
2120 }
2121 else
2122 {
2123 PartSize = (PartEntry->PartInfo[PartNumber].PartitionLength.QuadPart + (1 << 19)) >> 20;
2124 PartUnit = MUIGetString(STRING_MB);
2125 }
2126
2127 /* adjust partition type */
2128 if ((PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_FAT_12) ||
2129 (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_FAT_16) ||
2130 (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_HUGE) ||
2131 (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_XINT13))
2132 {
2133 PartType = "FAT";
2134 }
2135 else if ((PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_FAT32) ||
2136 (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_FAT32_XINT13))
2137 {
2138 PartType = "FAT32";
2139 }
2140 else if (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_EXT2)
2141 {
2142 PartType = "EXT2";
2143 }
2144 else if (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_IFS)
2145 {
2146 PartType = "NTFS"; /* FIXME: Not quite correct! */
2147 }
2148 else if (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_ENTRY_UNUSED)
2149 {
2150 PartType = MUIGetString(STRING_FORMATUNUSED);
2151 }
2152 else
2153 {
2154 PartType = MUIGetString(STRING_FORMATUNKNOWN);
2155 }
2156
2157 if (PartEntry->AutoCreate == TRUE)
2158 {
2159 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NEWPARTITION));
2160
2161 #if 0
2162 CONSOLE_PrintTextXY(8, 10, "Partition %lu (%I64u %s) %s of",
2163 PartEntry->PartInfo[PartNumber].PartitionNumber,
2164 PartSize,
2165 PartUnit,
2166 PartType);
2167 #endif
2168
2169 CONSOLE_PrintTextXY(8, 10, MUIGetString(STRING_HDINFOPARTZEROED),
2170 DiskEntry->DiskNumber,
2171 DiskSize,
2172 DiskUnit,
2173 DiskEntry->Port,
2174 DiskEntry->Bus,
2175 DiskEntry->Id,
2176 &DiskEntry->DriverName);
2177
2178 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_PARTFORMAT));
2179
2180
2181 PartEntry->AutoCreate = FALSE;
2182 }
2183 else if (PartEntry->New == TRUE)
2184 {
2185 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDPART));
2186 CONSOLE_SetTextXY(6, 10, MUIGetString(STRING_PARTFORMAT));
2187 }
2188 else
2189 {
2190 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_INSTALLONPART));
2191
2192 if (PartType == NULL)
2193 {
2194 CONSOLE_PrintTextXY(8, 10,
2195 MUIGetString(STRING_HDDINFOUNK4),
2196 (PartEntry->DriveLetter[PartNumber] == 0) ? '-' : PartEntry->DriveLetter[PartNumber],
2197 (PartEntry->DriveLetter[PartNumber] == 0) ? '-' : ':',
2198 PartEntry->PartInfo[PartNumber].PartitionType,
2199 PartSize,
2200 PartUnit);
2201 }
2202 else
2203 {
2204 CONSOLE_PrintTextXY(8, 10,
2205 "%c%c %s %I64u %s",
2206 (PartEntry->DriveLetter[PartNumber] == 0) ? '-' : PartEntry->DriveLetter[PartNumber],
2207 (PartEntry->DriveLetter[PartNumber] == 0) ? '-' : ':',
2208 PartType,
2209 PartSize,
2210 PartUnit);
2211 }
2212
2213 CONSOLE_PrintTextXY(6, 12, MUIGetString(STRING_HDINFOPARTEXISTS),
2214 DiskEntry->DiskNumber,
2215 DiskSize,
2216 DiskUnit,
2217 DiskEntry->Port,
2218 DiskEntry->Bus,
2219 DiskEntry->Id,
2220 &DiskEntry->DriverName);
2221 }
2222
2223 MUIDisplayPage(SELECT_FILE_SYSTEM_PAGE);
2224
2225 if (FileSystemList == NULL)
2226 {
2227 FileSystemList = CreateFileSystemList(6, 26, PartEntry->New, L"FAT");
2228 if (FileSystemList == NULL)
2229 {
2230 /* FIXME: show an error dialog */
2231 return QUIT_PAGE;
2232 }
2233
2234 /* FIXME: Add file systems to list */
2235 }
2236 DrawFileSystemList(FileSystemList);
2237
2238 if (RepairUpdateFlag)
2239 {
2240 return CHECK_FILE_SYSTEM_PAGE;
2241 //return SELECT_PARTITION_PAGE;
2242 }
2243
2244 if (IsUnattendedSetup)
2245 {
2246 if (UnattendFormatPartition)
2247 {
2248 return FORMAT_PARTITION_PAGE;
2249 }
2250
2251 return CHECK_FILE_SYSTEM_PAGE;
2252 }
2253
2254 while (TRUE)
2255 {
2256 CONSOLE_ConInKey(Ir);
2257
2258 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2259 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
2260 {
2261 if (ConfirmQuit(Ir) == TRUE)
2262 {
2263 return QUIT_PAGE;
2264 }
2265
2266 break;
2267 }
2268 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2269 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
2270 {
2271 return SELECT_PARTITION_PAGE;
2272 }
2273 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2274 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
2275 {
2276 ScrollDownFileSystemList(FileSystemList);
2277 }
2278 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2279 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
2280 {
2281 ScrollUpFileSystemList(FileSystemList);
2282 }
2283 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
2284 {
2285 if (!FileSystemList->Selected->FormatFunc)
2286 {
2287 return CHECK_FILE_SYSTEM_PAGE;
2288 }
2289 else
2290 {
2291 return FORMAT_PARTITION_PAGE;
2292 }
2293 }
2294 }
2295
2296 return SELECT_FILE_SYSTEM_PAGE;
2297 }
2298
2299
2300 static ULONG
2301 FormatPartitionPage(PINPUT_RECORD Ir)
2302 {
2303 WCHAR PathBuffer[MAX_PATH];
2304 PPARTENTRY PartEntry;
2305 UCHAR PartNum;
2306 NTSTATUS Status;
2307
2308 #ifndef NDEBUG
2309 PDISKENTRY DiskEntry;
2310 ULONG Line;
2311 ULONG i;
2312 PLIST_ENTRY Entry;
2313 #endif
2314
2315 MUIDisplayPage(FORMAT_PARTITION_PAGE);
2316
2317 if (PartitionList == NULL ||
2318 PartitionList->CurrentDisk == NULL ||
2319 PartitionList->CurrentPartition == NULL)
2320 {
2321 /* FIXME: show an error dialog */
2322 return QUIT_PAGE;
2323 }
2324
2325 #ifndef NDEBUG
2326 DiskEntry = PartitionList->CurrentDisk;
2327 #endif
2328 PartEntry = PartitionList->CurrentPartition;
2329 PartNum = PartitionList->CurrentPartitionNumber;
2330
2331 while (TRUE)
2332 {
2333 if (!IsUnattendedSetup)
2334 {
2335 CONSOLE_ConInKey(Ir);
2336 }
2337
2338 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2339 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
2340 {
2341 if (ConfirmQuit(Ir) == TRUE)
2342 {
2343 return QUIT_PAGE;
2344 }
2345
2346 break;
2347 }
2348 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN || IsUnattendedSetup) /* ENTER */
2349 {
2350 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
2351
2352 if (wcscmp(FileSystemList->Selected->FileSystem, L"FAT") == 0)
2353 {
2354 if (PartEntry->PartInfo[PartNum].PartitionLength.QuadPart < (4200LL * 1024LL))
2355 {
2356 /* FAT12 CHS partition (disk is smaller than 4.1MB) */
2357 PartEntry->PartInfo[PartNum].PartitionType = PARTITION_FAT_12;
2358 }
2359 else if (PartEntry->PartInfo[PartNum].StartingOffset.QuadPart < (1024LL * 255LL * 63LL * 512LL))
2360 {
2361 /* Partition starts below the 8.4GB boundary ==> CHS partition */
2362
2363 if (PartEntry->PartInfo[PartNum].PartitionLength.QuadPart < (32LL * 1024LL * 1024LL))
2364 {
2365 /* FAT16 CHS partition (partiton size < 32MB) */
2366 PartEntry->PartInfo[PartNum].PartitionType = PARTITION_FAT_16;
2367 }
2368 else if (PartEntry->PartInfo[PartNum].PartitionLength.QuadPart < (512LL * 1024LL * 1024LL))
2369 {
2370 /* FAT16 CHS partition (partition size < 512MB) */
2371 PartEntry->PartInfo[PartNum].PartitionType = PARTITION_HUGE;
2372 }
2373 else
2374 {
2375 /* FAT32 CHS partition (partition size >= 512MB) */
2376 PartEntry->PartInfo[PartNum].PartitionType = PARTITION_FAT32;
2377 }
2378 }
2379 else
2380 {
2381 /* Partition starts above the 8.4GB boundary ==> LBA partition */
2382
2383 if (PartEntry->PartInfo[PartNum].PartitionLength.QuadPart < (512LL * 1024LL * 1024LL))
2384 {
2385 /* FAT16 LBA partition (partition size < 512MB) */
2386 PartEntry->PartInfo[PartNum].PartitionType = PARTITION_XINT13;
2387 }
2388 else
2389 {
2390 /* FAT32 LBA partition (partition size >= 512MB) */
2391 PartEntry->PartInfo[PartNum].PartitionType = PARTITION_FAT32_XINT13;
2392 }
2393 }
2394 }
2395 #if 0
2396 else if (wcscmp(FileSystemList->Selected->FileSystem, L"EXT2") == 0)
2397 PartEntry->PartInfo[PartNum].PartitionType = PARTITION_EXT2;
2398 #endif
2399 else if (!FileSystemList->Selected->FormatFunc)
2400 return QUIT_PAGE;
2401
2402 #ifndef NDEBUG
2403 CONSOLE_PrintTextXY(6, 12,
2404 "Disk: %I64u Cylinder: %I64u Track: %I64u",
2405 DiskEntry->DiskSize,
2406 DiskEntry->CylinderSize,
2407 DiskEntry->TrackSize);
2408
2409 Line = 13;
2410 DiskEntry = PartitionList->CurrentDisk;
2411 Entry = DiskEntry->PartListHead.Flink;
2412
2413 while (Entry != &DiskEntry->PartListHead)
2414 {
2415 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
2416
2417 if (PartEntry->Unpartitioned == FALSE)
2418 {
2419 for (i = 0; i < 4; i++)
2420 {
2421 CONSOLE_PrintTextXY(6, Line,
2422 "%2u: %2u %c %12I64u %12I64u %2u %c",
2423 i,
2424 PartEntry->PartInfo[i].PartitionNumber,
2425 PartEntry->PartInfo[i].BootIndicator ? 'A' : '-',
2426 PartEntry->PartInfo[i].StartingOffset.QuadPart,
2427 PartEntry->PartInfo[i].PartitionLength.QuadPart,
2428 PartEntry->PartInfo[i].PartitionType,
2429 PartEntry->PartInfo[i].RewritePartition ? '*' : ' ');
2430
2431 Line++;
2432 }
2433
2434 Line++;
2435 }
2436
2437 Entry = Entry->Flink;
2438 }
2439
2440 /* Restore the old entry */
2441 PartEntry = PartitionList->CurrentPartition;
2442 #endif
2443
2444 if (WritePartitionsToDisk(PartitionList) == FALSE)
2445 {
2446 DPRINT("WritePartitionsToDisk() failed\n");
2447 MUIDisplayError(ERROR_WRITE_PTABLE, Ir, POPUP_WAIT_ENTER);
2448 return QUIT_PAGE;
2449 }
2450
2451 /* Set DestinationRootPath */
2452 RtlFreeUnicodeString(&DestinationRootPath);
2453 swprintf(PathBuffer,
2454 L"\\Device\\Harddisk%lu\\Partition%lu",
2455 PartitionList->CurrentDisk->DiskNumber,
2456 PartitionList->CurrentPartition->PartInfo[PartNum].PartitionNumber);
2457 RtlCreateUnicodeString(&DestinationRootPath,
2458 PathBuffer);
2459 DPRINT("DestinationRootPath: %wZ\n", &DestinationRootPath);
2460
2461 if (FileSystemList->Selected->FormatFunc)
2462 {
2463 Status = FormatPartition(&DestinationRootPath,
2464 FileSystemList->Selected);
2465 if (!NT_SUCCESS(Status))
2466 {
2467 DPRINT1("FormatPartition() failed with status 0x%08lx\n", Status);
2468 /* FIXME: show an error dialog */
2469 return QUIT_PAGE;
2470 }
2471
2472 PartEntry->New = FALSE;
2473
2474 CheckActiveBootPartition(PartitionList);
2475 }
2476
2477 #ifndef NDEBUG
2478 CONSOLE_SetStatusText(" Done. Press any key ...");
2479 CONSOLE_ConInKey(Ir);
2480 #endif
2481
2482 DestroyFileSystemList(FileSystemList);
2483 FileSystemList = NULL;
2484 return INSTALL_DIRECTORY_PAGE;
2485 }
2486 }
2487
2488 return FORMAT_PARTITION_PAGE;
2489 }
2490
2491
2492 static ULONG
2493 CheckFileSystemPage(PINPUT_RECORD Ir)
2494 {
2495 PFILE_SYSTEM_ITEM CurrentFileSystem;
2496 WCHAR PathBuffer[MAX_PATH];
2497 CHAR Buffer[MAX_PATH];
2498 NTSTATUS Status;
2499 UCHAR PartNum = PartitionList->CurrentPartitionNumber;
2500
2501 /* FIXME: code duplicated in FormatPartitionPage */
2502 /* Set DestinationRootPath */
2503 RtlFreeUnicodeString(&DestinationRootPath);
2504 swprintf(PathBuffer,
2505 L"\\Device\\Harddisk%lu\\Partition%lu",
2506 PartitionList->CurrentDisk->DiskNumber,
2507 PartitionList->CurrentPartition->PartInfo[PartNum].PartitionNumber);
2508 RtlCreateUnicodeString(&DestinationRootPath, PathBuffer);
2509 DPRINT("DestinationRootPath: %wZ\n", &DestinationRootPath);
2510
2511 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHECKINGPART));
2512
2513 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
2514
2515 /* WRONG: first filesystem is not necesseraly the one of the current partition! */
2516 CurrentFileSystem = CONTAINING_RECORD(FileSystemList->ListHead.Flink, FILE_SYSTEM_ITEM, ListEntry);
2517
2518 if (!CurrentFileSystem->ChkdskFunc)
2519 {
2520 sprintf(Buffer,
2521 "Setup is currently unable to check a partition formatted in %S.\n"
2522 "\n"
2523 " \x07 Press ENTER to continue Setup.\n"
2524 " \x07 Press F3 to quit Setup.",
2525 CurrentFileSystem->FileSystem);
2526
2527 PopupError(Buffer,
2528 MUIGetString(STRING_QUITCONTINUE),
2529 NULL, POPUP_WAIT_NONE);
2530
2531 while (TRUE)
2532 {
2533 CONSOLE_ConInKey(Ir);
2534
2535 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x00 &&
2536 Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3) /* F3 */
2537 {
2538 if (ConfirmQuit(Ir))
2539 return QUIT_PAGE;
2540 else
2541 return CHECK_FILE_SYSTEM_PAGE;
2542 }
2543 else if (Ir->Event.KeyEvent.uChar.AsciiChar == VK_RETURN) /* ENTER */
2544 {
2545 return INSTALL_DIRECTORY_PAGE;
2546 }
2547 }
2548 }
2549 else
2550 {
2551 Status = ChkdskPartition(&DestinationRootPath, CurrentFileSystem);
2552 if (!NT_SUCCESS(Status))
2553 {
2554 DPRINT("ChkdskPartition() failed with status 0x%08lx\n", Status);
2555 sprintf(Buffer, "Setup failed to verify the selected partition.\n"
2556 "(Status 0x%08lx).\n", Status);
2557
2558 PopupError(Buffer,
2559 MUIGetString(STRING_REBOOTCOMPUTER),
2560 Ir, POPUP_WAIT_ENTER);
2561
2562 return QUIT_PAGE;
2563 }
2564
2565 return INSTALL_DIRECTORY_PAGE;
2566 }
2567 }
2568
2569
2570 static PAGE_NUMBER
2571 InstallDirectoryPage1(PWCHAR InstallDir,
2572 PDISKENTRY DiskEntry,
2573 PPARTENTRY PartEntry,
2574 UCHAR PartNum)
2575 {
2576 WCHAR PathBuffer[MAX_PATH];
2577
2578 /* Create 'InstallPath' string */
2579 RtlFreeUnicodeString(&InstallPath);
2580 RtlCreateUnicodeString(&InstallPath,
2581 InstallDir);
2582
2583 /* Create 'DestinationPath' string */
2584 RtlFreeUnicodeString(&DestinationPath);
2585 wcscpy(PathBuffer, DestinationRootPath.Buffer);
2586
2587 if (InstallDir[0] != L'\\')
2588 wcscat(PathBuffer, L"\\");
2589
2590 wcscat(PathBuffer, InstallDir);
2591 RtlCreateUnicodeString(&DestinationPath, PathBuffer);
2592
2593 /* Create 'DestinationArcPath' */
2594 RtlFreeUnicodeString(&DestinationArcPath);
2595 swprintf(PathBuffer,
2596 L"multi(0)disk(0)rdisk(%lu)partition(%lu)",
2597 DiskEntry->BiosDiskNumber,
2598 PartEntry->PartInfo[PartNum].PartitionNumber);
2599
2600 if (InstallDir[0] != L'\\')
2601 wcscat(PathBuffer, L"\\");
2602
2603 wcscat(PathBuffer, InstallDir);
2604 RtlCreateUnicodeString(&DestinationArcPath, PathBuffer);
2605
2606 return PREPARE_COPY_PAGE;
2607 }
2608
2609
2610 static PAGE_NUMBER
2611 InstallDirectoryPage(PINPUT_RECORD Ir)
2612 {
2613 PDISKENTRY DiskEntry;
2614 PPARTENTRY PartEntry;
2615 WCHAR InstallDir[51];
2616 ULONG Length;
2617
2618 if (PartitionList == NULL ||
2619 PartitionList->CurrentDisk == NULL ||
2620 PartitionList->CurrentPartition == NULL)
2621 {
2622 /* FIXME: show an error dialog */
2623 return QUIT_PAGE;
2624 }
2625
2626 DiskEntry = PartitionList->CurrentDisk;
2627 PartEntry = PartitionList->CurrentPartition;
2628
2629 if (IsUnattendedSetup)
2630 wcscpy(InstallDir, UnattendInstallationDirectory);
2631 else
2632 wcscpy(InstallDir, L"\\ReactOS");
2633
2634 Length = wcslen(InstallDir);
2635 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
2636 MUIDisplayPage(INSTALL_DIRECTORY_PAGE);
2637
2638 if (IsUnattendedSetup)
2639 {
2640 return InstallDirectoryPage1(InstallDir,
2641 DiskEntry,
2642 PartEntry,
2643 PartitionList->CurrentPartitionNumber);
2644 }
2645
2646 while (TRUE)
2647 {
2648 CONSOLE_ConInKey(Ir);
2649
2650 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2651 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
2652 {
2653 if (ConfirmQuit(Ir) == TRUE)
2654 return QUIT_PAGE;
2655
2656 break;
2657 }
2658 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2659 {
2660 return InstallDirectoryPage1(InstallDir,
2661 DiskEntry,
2662 PartEntry,
2663 PartitionList->CurrentPartitionNumber);
2664 }
2665 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x08) /* BACKSPACE */
2666 {
2667 if (Length > 0)
2668 {
2669 Length--;
2670 InstallDir[Length] = 0;
2671 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
2672 }
2673 }
2674 else if (isprint(Ir->Event.KeyEvent.uChar.AsciiChar))
2675 {
2676 if (Length < 50)
2677 {
2678 InstallDir[Length] = (WCHAR)Ir->Event.KeyEvent.uChar.AsciiChar;
2679 Length++;
2680 InstallDir[Length] = 0;
2681 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
2682 }
2683 }
2684 }
2685
2686 return INSTALL_DIRECTORY_PAGE;
2687 }
2688
2689
2690 static BOOLEAN
2691 AddSectionToCopyQueueCab(HINF InfFile,
2692 PWCHAR SectionName,
2693 PWCHAR SourceCabinet,
2694 PCUNICODE_STRING DestinationPath,
2695 PINPUT_RECORD Ir)
2696 {
2697 INFCONTEXT FilesContext;
2698 INFCONTEXT DirContext;
2699 PWCHAR FileKeyName;
2700 PWCHAR FileKeyValue;
2701 PWCHAR DirKeyValue;
2702 PWCHAR TargetFileName;
2703
2704 /* Search for the SectionName section */
2705 if (!SetupFindFirstLineW(InfFile, SectionName, NULL, &FilesContext))
2706 {
2707 char Buffer[128];
2708 sprintf(Buffer, MUIGetString(STRING_TXTSETUPFAILED), SectionName);
2709 PopupError(Buffer, MUIGetString(STRING_REBOOTCOMPUTER), Ir, POPUP_WAIT_ENTER);
2710 return FALSE;
2711 }
2712
2713 /*
2714 * Enumerate the files in the section
2715 * and add them to the file queue.
2716 */
2717 do
2718 {
2719 /* Get source file name and target directory id */
2720 if (!INF_GetData(&FilesContext, &FileKeyName, &FileKeyValue))
2721 {
2722 /* FIXME: Handle error! */
2723 DPRINT1("INF_GetData() failed\n");
2724 break;
2725 }
2726
2727 /* Get optional target file name */
2728 if (!INF_GetDataField(&FilesContext, 2, &TargetFileName))
2729 TargetFileName = NULL;
2730
2731 DPRINT("FileKeyName: '%S' FileKeyValue: '%S'\n", FileKeyName, FileKeyValue);
2732
2733 /* Lookup target directory */
2734 if (!SetupFindFirstLineW(InfFile, L"Directories", FileKeyValue, &DirContext))
2735 {
2736 /* FIXME: Handle error! */
2737 DPRINT1("SetupFindFirstLine() failed\n");
2738 break;
2739 }
2740
2741 if (!INF_GetData(&DirContext, NULL, &DirKeyValue))
2742 {
2743 /* FIXME: Handle error! */
2744 DPRINT1("INF_GetData() failed\n");
2745 break;
2746 }
2747
2748 if (!SetupQueueCopy(SetupFileQueue,
2749 SourceCabinet,
2750 SourceRootPath.Buffer,
2751 SourceRootDir.Buffer,
2752 FileKeyName,
2753 DirKeyValue,
2754 TargetFileName))
2755 {
2756 /* FIXME: Handle error! */
2757 DPRINT1("SetupQueueCopy() failed\n");
2758 }
2759 } while (SetupFindNextLine(&FilesContext, &FilesContext));
2760
2761 return TRUE;
2762 }
2763
2764
2765 static BOOLEAN
2766 AddSectionToCopyQueue(HINF InfFile,
2767 PWCHAR SectionName,
2768 PWCHAR SourceCabinet,
2769 PCUNICODE_STRING DestinationPath,
2770 PINPUT_RECORD Ir)
2771 {
2772 INFCONTEXT FilesContext;
2773 INFCONTEXT DirContext;
2774 PWCHAR FileKeyName;
2775 PWCHAR FileKeyValue;
2776 PWCHAR DirKeyValue;
2777 PWCHAR TargetFileName;
2778 WCHAR CompleteOrigFileName[512];
2779
2780 if (SourceCabinet)
2781 return AddSectionToCopyQueueCab(InfFile, L"SourceFiles", SourceCabinet, DestinationPath, Ir);
2782
2783 /* Search for the SectionName section */
2784 if (!SetupFindFirstLineW(InfFile, SectionName, NULL, &FilesContext))
2785 {
2786 char Buffer[128];
2787 sprintf(Buffer, MUIGetString(STRING_TXTSETUPFAILED), SectionName);
2788 PopupError(Buffer, MUIGetString(STRING_REBOOTCOMPUTER), Ir, POPUP_WAIT_ENTER);
2789 return FALSE;
2790 }
2791
2792 /*
2793 * Enumerate the files in the section
2794 * and add them to the file queue.
2795 */
2796 do
2797 {
2798 /* Get source file name and target directory id */
2799 if (!INF_GetData(&FilesContext, &FileKeyName, &FileKeyValue))
2800 {
2801 /* FIXME: Handle error! */
2802 DPRINT1("INF_GetData() failed\n");
2803 break;
2804 }
2805
2806 /* Get target directory id */
2807 if (!INF_GetDataField(&FilesContext, 13, &FileKeyValue))
2808 {
2809 /* FIXME: Handle error! */
2810 DPRINT1("INF_GetData() failed\n");
2811 break;
2812 }
2813
2814 /* Get optional target file name */
2815 if (!INF_GetDataField(&FilesContext, 11, &TargetFileName))
2816 TargetFileName = NULL;
2817 else if (!*TargetFileName)
2818 TargetFileName = NULL;
2819
2820 DPRINT("FileKeyName: '%S' FileKeyValue: '%S'\n", FileKeyName, FileKeyValue);
2821
2822 /* Lookup target directory */
2823 if (!SetupFindFirstLineW(InfFile, L"Directories", FileKeyValue, &DirContext))
2824 {
2825 /* FIXME: Handle error! */
2826 DPRINT1("SetupFindFirstLine() failed\n");
2827 break;
2828 }
2829
2830 if (!INF_GetData(&DirContext, NULL, &DirKeyValue))
2831 {
2832 /* FIXME: Handle error! */
2833 DPRINT1("INF_GetData() failed\n");
2834 break;
2835 }
2836
2837 wcscpy(CompleteOrigFileName, SourceRootDir.Buffer);
2838 wcscat(CompleteOrigFileName, L"\\");
2839 wcscat(CompleteOrigFileName, DirKeyValue);
2840
2841 if (!SetupQueueCopy(SetupFileQueue,
2842 SourceCabinet,
2843 SourceRootPath.Buffer,
2844 CompleteOrigFileName,
2845 FileKeyName,
2846 DirKeyValue,
2847 TargetFileName))
2848 {
2849 /* FIXME: Handle error! */
2850 DPRINT1("SetupQueueCopy() failed\n");
2851 }
2852 } while (SetupFindNextLine(&FilesContext, &FilesContext));
2853
2854 return TRUE;
2855 }
2856
2857
2858 static BOOLEAN
2859 PrepareCopyPageInfFile(HINF InfFile,
2860 PWCHAR SourceCabinet,
2861 PINPUT_RECORD Ir)
2862 {
2863 WCHAR PathBuffer[MAX_PATH];
2864 INFCONTEXT DirContext;
2865 PWCHAR AdditionalSectionName = NULL;
2866 PWCHAR KeyValue;
2867 ULONG Length;
2868 NTSTATUS Status;
2869
2870 /* Add common files */
2871 if (!AddSectionToCopyQueue(InfFile, L"SourceDisksFiles", SourceCabinet, &DestinationPath, Ir))
2872 return FALSE;
2873
2874 /* Add specific files depending of computer type */
2875 if (SourceCabinet == NULL)
2876 {
2877 if (!ProcessComputerFiles(InfFile, ComputerList, &AdditionalSectionName))
2878 return FALSE;
2879
2880 if (AdditionalSectionName)
2881 {
2882 if (!AddSectionToCopyQueue(InfFile, AdditionalSectionName, SourceCabinet, &DestinationPath, Ir))
2883 return FALSE;
2884 }
2885 }
2886
2887 /* Create directories */
2888
2889 /*
2890 * FIXME:
2891 * Install directories like '\reactos\test' are not handled yet.
2892 */
2893
2894 /* Get destination path */
2895 wcscpy(PathBuffer, DestinationPath.Buffer);
2896
2897 /* Remove trailing backslash */
2898 Length = wcslen(PathBuffer);
2899 if ((Length > 0) && (PathBuffer[Length - 1] == '\\'))
2900 {
2901 PathBuffer[Length - 1] = 0;
2902 }
2903
2904 /* Create the install directory */
2905 Status = SetupCreateDirectory(PathBuffer);
2906 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION)
2907 {
2908 DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer, Status);
2909 MUIDisplayError(ERROR_CREATE_INSTALL_DIR, Ir, POPUP_WAIT_ENTER);
2910 return FALSE;
2911 }
2912
2913 /* Search for the 'Directories' section */
2914 if (!SetupFindFirstLineW(InfFile, L"Directories", NULL, &DirContext))
2915 {
2916 if (SourceCabinet)
2917 {
2918 MUIDisplayError(ERROR_CABINET_SECTION, Ir, POPUP_WAIT_ENTER);
2919 }
2920 else
2921 {
2922 MUIDisplayError(ERROR_TXTSETUP_SECTION, Ir, POPUP_WAIT_ENTER);
2923 }
2924
2925 return FALSE;
2926 }
2927
2928 /* Enumerate the directory values and create the subdirectories */
2929 do
2930 {
2931 if (!INF_GetData(&DirContext, NULL, &KeyValue))
2932 {
2933 DPRINT1("break\n");
2934 break;
2935 }
2936
2937 if (KeyValue[0] == L'\\' && KeyValue[1] != 0)
2938 {
2939 DPRINT("Absolute Path: '%S'\n", KeyValue);
2940
2941 wcscpy(PathBuffer, DestinationRootPath.Buffer);
2942 wcscat(PathBuffer, KeyValue);
2943
2944 DPRINT("FullPath: '%S'\n", PathBuffer);
2945 }
2946 else if (KeyValue[0] != L'\\')
2947 {
2948 DPRINT("RelativePath: '%S'\n", KeyValue);
2949 wcscpy(PathBuffer, DestinationPath.Buffer);
2950 wcscat(PathBuffer, L"\\");
2951 wcscat(PathBuffer, KeyValue);
2952
2953 DPRINT("FullPath: '%S'\n", PathBuffer);
2954
2955 Status = SetupCreateDirectory(PathBuffer);
2956 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION)
2957 {
2958 DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer, Status);
2959 MUIDisplayError(ERROR_CREATE_DIR, Ir, POPUP_WAIT_ENTER);
2960 return FALSE;
2961 }
2962 }
2963 } while (SetupFindNextLine (&DirContext, &DirContext));
2964
2965 return TRUE;
2966 }
2967
2968
2969 static PAGE_NUMBER
2970 PrepareCopyPage(PINPUT_RECORD Ir)
2971 {
2972 HINF InfHandle;
2973 WCHAR PathBuffer[MAX_PATH];
2974 INFCONTEXT CabinetsContext;
2975 ULONG InfFileSize;
2976 PWCHAR KeyValue;
2977 UINT ErrorLine;
2978 PVOID InfFileData;
2979
2980 MUIDisplayPage(PREPARE_COPY_PAGE);
2981
2982 /* Create the file queue */
2983 SetupFileQueue = SetupOpenFileQueue();
2984 if (SetupFileQueue == NULL)
2985 {
2986 MUIDisplayError(ERROR_COPY_QUEUE, Ir, POPUP_WAIT_ENTER);
2987 return(QUIT_PAGE);
2988 }
2989
2990 if (!PrepareCopyPageInfFile(SetupInf, NULL, Ir))
2991 {
2992 return QUIT_PAGE;
2993 }
2994
2995 /* Search for the 'Cabinets' section */
2996 if (!SetupFindFirstLineW(SetupInf, L"Cabinets", NULL, &CabinetsContext))
2997 {
2998 return FILE_COPY_PAGE;
2999 }
3000
3001 /*
3002 * Enumerate the directory values in the 'Cabinets'
3003 * section and parse their inf files.
3004 */
3005 do
3006 {
3007 if (!INF_GetData(&CabinetsContext, NULL, &KeyValue))
3008 break;
3009
3010 wcscpy(PathBuffer, SourcePath.Buffer);
3011 wcscat(PathBuffer, L"\\");
3012 wcscat(PathBuffer, KeyValue);
3013
3014 #ifdef __REACTOS__
3015 CabinetInitialize();
3016 CabinetSetEventHandlers(NULL, NULL, NULL);
3017 CabinetSetCabinetName(PathBuffer);
3018
3019 if (CabinetOpen() == CAB_STATUS_SUCCESS)
3020 {
3021 DPRINT("Cabinet %S\n", CabinetGetCabinetName());
3022
3023 InfFileData = CabinetGetCabinetReservedArea(&InfFileSize);
3024 if (InfFileData == NULL)
3025 {
3026 MUIDisplayError(ERROR_CABINET_SCRIPT, Ir, POPUP_WAIT_ENTER);
3027 return QUIT_PAGE;
3028 }
3029 }
3030 else
3031 {
3032 DPRINT("Cannot open cabinet: %S.\n", CabinetGetCabinetName());
3033 MUIDisplayError(ERROR_CABINET_MISSING, Ir, POPUP_WAIT_ENTER);
3034 return QUIT_PAGE;
3035 }
3036
3037 InfHandle = INF_OpenBufferedFileA((CHAR*) InfFileData,
3038 InfFileSize,
3039 (const CHAR*) NULL,
3040 INF_STYLE_WIN4,
3041 LanguageId,
3042 &ErrorLine);
3043
3044 if (InfHandle == INVALID_HANDLE_VALUE)
3045 {
3046 MUIDisplayError(ERROR_INVALID_CABINET_INF, Ir, POPUP_WAIT_ENTER);
3047 return QUIT_PAGE;
3048 }
3049
3050 CabinetCleanup();
3051
3052 if (!PrepareCopyPageInfFile(InfHandle, KeyValue, Ir))
3053 {
3054 return QUIT_PAGE;
3055 }
3056 #endif
3057 } while (SetupFindNextLine(&CabinetsContext, &CabinetsContext));
3058
3059 return FILE_COPY_PAGE;
3060 }
3061
3062
3063 VOID
3064 NTAPI
3065 SetupUpdateMemoryInfo(IN PCOPYCONTEXT CopyContext,
3066 IN BOOLEAN First)
3067 {
3068 SYSTEM_PERFORMANCE_INFORMATION PerfInfo;
3069
3070 /* Get the memory information from the system */
3071 NtQuerySystemInformation(SystemPerformanceInformation,
3072 &PerfInfo,
3073 sizeof(PerfInfo),
3074 NULL);
3075
3076 /* Check if this is initial setup */
3077 if (First)
3078 {
3079 /* Set maximum limits to be total RAM pages */
3080 ProgressSetStepCount(CopyContext->MemoryBars[0], PerfInfo.CommitLimit);
3081 ProgressSetStepCount(CopyContext->MemoryBars[1], PerfInfo.CommitLimit);
3082 ProgressSetStepCount(CopyContext->MemoryBars[2], PerfInfo.CommitLimit);
3083 }
3084
3085 /* Set current values */
3086 ProgressSetStep(CopyContext->MemoryBars[0], PerfInfo.PagedPoolPages + PerfInfo.NonPagedPoolPages);
3087 ProgressSetStep(CopyContext->MemoryBars[1], PerfInfo.ResidentSystemCachePage);
3088 ProgressSetStep(CopyContext->MemoryBars[2], PerfInfo.AvailablePages);
3089 }
3090
3091
3092 static UINT
3093 CALLBACK
3094 FileCopyCallback(PVOID Context,
3095 UINT Notification,
3096 UINT_PTR Param1,
3097 UINT_PTR Param2)
3098 {
3099 PCOPYCONTEXT CopyContext;
3100
3101 CopyContext = (PCOPYCONTEXT)Context;
3102
3103 switch (Notification)
3104 {
3105 case SPFILENOTIFY_STARTSUBQUEUE:
3106 CopyContext->TotalOperations = (ULONG)Param2;
3107 ProgressSetStepCount(CopyContext->ProgressBar,
3108 CopyContext->TotalOperations);
3109 SetupUpdateMemoryInfo(CopyContext, TRUE);
3110 break;
3111
3112 case SPFILENOTIFY_STARTCOPY:
3113 /* Display copy message */
3114 CONSOLE_SetStatusText(MUIGetString(STRING_COPYING), (PWSTR)Param1);
3115 SetupUpdateMemoryInfo(CopyContext, FALSE);
3116 break;
3117
3118 case SPFILENOTIFY_ENDCOPY:
3119 CopyContext->CompletedOperations++;
3120
3121 /* SYSREG checkpoint */
3122 if (CopyContext->TotalOperations >> 1 == CopyContext->CompletedOperations)
3123 DPRINT1("CHECKPOINT:HALF_COPIED\n");
3124
3125 ProgressNextStep(CopyContext->ProgressBar);
3126 SetupUpdateMemoryInfo(CopyContext, FALSE);
3127 break;
3128 }
3129
3130 return 0;
3131 }
3132
3133
3134 static
3135 PAGE_NUMBER
3136 FileCopyPage(PINPUT_RECORD Ir)
3137 {
3138 COPYCONTEXT CopyContext;
3139 unsigned int mem_bar_width;
3140
3141 MUIDisplayPage(FILE_COPY_PAGE);
3142
3143 /* Create context for the copy process */
3144 CopyContext.DestinationRootPath = DestinationRootPath.Buffer;
3145 CopyContext.InstallPath = InstallPath.Buffer;
3146 CopyContext.TotalOperations = 0;
3147 CopyContext.CompletedOperations = 0;
3148
3149 /* Create the progress bar as well */
3150 CopyContext.ProgressBar = CreateProgressBar(13,
3151 26,
3152 xScreen - 13,
3153 yScreen - 20,
3154 10,
3155 24,
3156 TRUE,
3157 MUIGetString(STRING_SETUPCOPYINGFILES));
3158
3159 // fit memory bars to screen width, distribute them uniform
3160 mem_bar_width = (xScreen - 26) / 5;
3161 mem_bar_width -= mem_bar_width % 2; // make even
3162 /* ATTENTION: The following progress bars are debug stuff, which should not be translated!! */
3163 /* Create the paged pool progress bar */
3164 CopyContext.MemoryBars[0] = CreateProgressBar(13,
3165 40,
3166 13 + mem_bar_width,
3167 43,
3168 13,
3169 44,
3170 FALSE,
3171 "Kernel Pool");
3172
3173 /* Create the non paged pool progress bar */
3174 CopyContext.MemoryBars[1] = CreateProgressBar((xScreen / 2)- (mem_bar_width / 2),
3175 40,
3176 (xScreen / 2) + (mem_bar_width / 2),
3177 43,
3178 (xScreen / 2)- (mem_bar_width / 2),
3179 44,
3180 FALSE,
3181 "Kernel Cache");
3182
3183 /* Create the global memory progress bar */
3184 CopyContext.MemoryBars[2] = CreateProgressBar(xScreen - 13 - mem_bar_width,
3185 40,
3186 xScreen - 13,
3187 43,
3188 xScreen - 13 - mem_bar_width,
3189 44,
3190 FALSE,
3191 "Free Memory");
3192
3193 /* Do the file copying */
3194 SetupCommitFileQueueW(NULL,
3195 SetupFileQueue,
3196 FileCopyCallback,
3197 &CopyContext);
3198
3199 /* If we get here, we're done, so cleanup the queue and progress bar */
3200 SetupCloseFileQueue(SetupFileQueue);
3201 DestroyProgressBar(CopyContext.ProgressBar);
3202 DestroyProgressBar(CopyContext.MemoryBars[0]);
3203 DestroyProgressBar(CopyContext.MemoryBars[1]);
3204 DestroyProgressBar(CopyContext.MemoryBars[2]);
3205
3206 /* Go display the next page */
3207 return REGISTRY_PAGE;
3208 }
3209
3210
3211 static PAGE_NUMBER
3212 RegistryPage(PINPUT_RECORD Ir)
3213 {
3214 INFCONTEXT InfContext;
3215 PWSTR Action;
3216 PWSTR File;
3217 PWSTR Section;
3218 BOOLEAN Delete;
3219 NTSTATUS Status;
3220
3221 MUIDisplayPage(REGISTRY_PAGE);
3222
3223 if (RepairUpdateFlag)
3224 {
3225 return SUCCESS_PAGE;
3226 }
3227
3228 if (!SetInstallPathValue(&DestinationPath))
3229 {
3230 DPRINT("SetInstallPathValue() failed\n");
3231 MUIDisplayError(ERROR_INITIALIZE_REGISTRY, Ir, POPUP_WAIT_ENTER);
3232 return QUIT_PAGE;
3233 }
3234
3235 /* Create the default hives */
3236 #ifdef __REACTOS__
3237 Status = NtInitializeRegistry(CM_BOOT_FLAG_SETUP);
3238 if (!NT_SUCCESS(Status))
3239 {
3240 DPRINT("NtInitializeRegistry() failed (Status %lx)\n", Status);
3241 MUIDisplayError(ERROR_CREATE_HIVE, Ir, POPUP_WAIT_ENTER);
3242 return QUIT_PAGE;
3243 }
3244 #else
3245 RegInitializeRegistry();
3246 #endif
3247
3248 /* Update registry */
3249 CONSOLE_SetStatusText(MUIGetString(STRING_REGHIVEUPDATE));
3250
3251 if (!SetupFindFirstLineW(SetupInf, L"HiveInfs.Install", NULL, &InfContext))
3252 {
3253 DPRINT1("SetupFindFirstLine() failed\n");
3254 MUIDisplayError(ERROR_FIND_REGISTRY, Ir, POPUP_WAIT_ENTER);
3255 return QUIT_PAGE;
3256 }
3257
3258 do
3259 {
3260 INF_GetDataField (&InfContext, 0, &Action);
3261 INF_GetDataField (&InfContext, 1, &File);
3262 INF_GetDataField (&InfContext, 2, &Section);
3263
3264 DPRINT("Action: %S File: %S Section %S\n", Action, File, Section);
3265
3266 if (Action == NULL)
3267 break; // Hackfix
3268
3269 if (!_wcsicmp (Action, L"AddReg"))
3270 {
3271 Delete = FALSE;
3272 }
3273 else if (!_wcsicmp (Action, L"DelReg"))
3274 {
3275 Delete = TRUE;
3276 }
3277 else
3278 {
3279 continue;
3280 }
3281
3282 CONSOLE_SetStatusText(MUIGetString(STRING_IMPORTFILE), File);
3283
3284 if (!ImportRegistryFile(File, Section, LanguageId, Delete))
3285 {
3286 DPRINT("Importing %S failed\n", File);
3287
3288 MUIDisplayError(ERROR_IMPORT_HIVE, Ir, POPUP_WAIT_ENTER);
3289 return QUIT_PAGE;
3290 }
3291 } while (SetupFindNextLine(&InfContext, &InfContext));
3292
3293 /* Update display registry settings */
3294 CONSOLE_SetStatusText(MUIGetString(STRING_DISPLAYETTINGSUPDATE));
3295 if (!ProcessDisplayRegistry(SetupInf, DisplayList))
3296 {
3297 MUIDisplayError(ERROR_UPDATE_DISPLAY_SETTINGS, Ir, POPUP_WAIT_ENTER);
3298 return QUIT_PAGE;
3299 }
3300
3301 /* Set the locale */
3302 CONSOLE_SetStatusText(MUIGetString(STRING_LOCALESETTINGSUPDATE));
3303 if (!ProcessLocaleRegistry(LanguageList))
3304 {
3305 MUIDisplayError(ERROR_UPDATE_LOCALESETTINGS, Ir, POPUP_WAIT_ENTER);
3306 return QUIT_PAGE;
3307 }
3308
3309 /* Add keyboard layouts */
3310 CONSOLE_SetStatusText(MUIGetString(STRING_ADDKBLAYOUTS));
3311 if (!AddKeyboardLayouts())
3312 {
3313 MUIDisplayError(ERROR_ADDING_KBLAYOUTS, Ir, POPUP_WAIT_ENTER);
3314 return QUIT_PAGE;
3315 }
3316
3317 /* Set GeoID */
3318
3319 if (!SetGeoID(MUIGetGeoID()))
3320 {
3321 MUIDisplayError(ERROR_UPDATE_GEOID, Ir, POPUP_WAIT_ENTER);
3322 return QUIT_PAGE;
3323 }
3324
3325 if (!IsUnattendedSetup)
3326 {
3327 /* Update keyboard layout settings */
3328 CONSOLE_SetStatusText(MUIGetString(STRING_KEYBOARDSETTINGSUPDATE));
3329 if (!ProcessKeyboardLayoutRegistry(LayoutList))
3330 {
3331 MUIDisplayError(ERROR_UPDATE_KBSETTINGS, Ir, POPUP_WAIT_ENTER);
3332 return QUIT_PAGE;
3333 }
3334 }
3335
3336 /* Add codepage information to registry */
3337 CONSOLE_SetStatusText(MUIGetString(STRING_CODEPAGEINFOUPDATE));
3338 if (!AddCodePage())
3339 {
3340 MUIDisplayError(ERROR_ADDING_CODEPAGE, Ir, POPUP_WAIT_ENTER);
3341 return QUIT_PAGE;
3342 }
3343
3344 /* Set the default pagefile entry */
3345 SetDefaultPagefile(DestinationDriveLetter);
3346
3347 /* Update the mounted devices list */
3348 SetMountedDeviceValues(PartitionList);
3349
3350 CONSOLE_SetStatusText(MUIGetString(STRING_DONE));
3351
3352 return BOOT_LOADER_PAGE;
3353 }
3354
3355
3356 static PAGE_NUMBER
3357 BootLoaderPage(PINPUT_RECORD Ir)
3358 {
3359 UCHAR PartitionType;
3360 BOOLEAN InstallOnFloppy;
3361 USHORT Line = 12;
3362 WCHAR PathBuffer[MAX_PATH];
3363
3364 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
3365
3366 /* Find or set the active partition */
3367 CheckActiveBootPartition(PartitionList);
3368
3369 /* Update the partition table because we may have changed the active partition */
3370 if (WritePartitionsToDisk(PartitionList) == FALSE)
3371 {
3372 DPRINT("WritePartitionsToDisk() failed\n");
3373 MUIDisplayError(ERROR_WRITE_PTABLE, Ir, POPUP_WAIT_ENTER);
3374 return QUIT_PAGE;
3375 }
3376
3377 RtlFreeUnicodeString(&SystemRootPath);
3378 swprintf(PathBuffer,
3379 L"\\Device\\Harddisk%lu\\Partition%lu",
3380 PartitionList->ActiveBootDisk->DiskNumber,
3381 PartitionList->ActiveBootPartition->
3382 PartInfo[PartitionList->ActiveBootPartitionNumber].PartitionNumber);
3383 RtlCreateUnicodeString(&SystemRootPath,
3384 PathBuffer);
3385 DPRINT("SystemRootPath: %wZ\n", &SystemRootPath);
3386
3387 PartitionType = PartitionList->ActiveBootPartition->
3388 PartInfo[PartitionList->ActiveBootPartitionNumber].PartitionType;
3389
3390 if (IsUnattendedSetup)
3391 {
3392 if (UnattendMBRInstallType == 0) /* skip MBR installation */
3393 {
3394 return SUCCESS_PAGE;
3395 }
3396 else if (UnattendMBRInstallType == 1) /* install on floppy */
3397 {
3398 return BOOT_LOADER_FLOPPY_PAGE;
3399 }
3400 }
3401
3402 if (PartitionType == PARTITION_ENTRY_UNUSED)
3403 {
3404 DPRINT("Error: active partition invalid (unused)\n");
3405 InstallOnFloppy = TRUE;
3406 }
3407 else if (PartitionType == 0x0A)
3408 {
3409 /* OS/2 boot manager partition */
3410 DPRINT("Found OS/2 boot manager partition\n");
3411 InstallOnFloppy = TRUE;
3412 }
3413 else if (PartitionType == 0x83)
3414 {
3415 /* Linux ext2 partition */
3416 DPRINT("Found Linux ext2 partition\n");
3417 InstallOnFloppy = TRUE;
3418 }
3419 else if (PartitionType == PARTITION_IFS)
3420 {
3421 /* NTFS partition */
3422 DPRINT("Found NTFS partition\n");
3423 InstallOnFloppy = TRUE;
3424 }
3425 else if ((PartitionType == PARTITION_FAT_12) ||
3426 (PartitionType == PARTITION_FAT_16) ||
3427 (PartitionType == PARTITION_HUGE) ||
3428 (PartitionType == PARTITION_XINT13) ||
3429 (PartitionType == PARTITION_FAT32) ||
3430 (PartitionType == PARTITION_FAT32_XINT13))
3431 {
3432 DPRINT("Found FAT partition\n");
3433 InstallOnFloppy = FALSE;
3434 }
3435 else
3436 {
3437 /* Unknown partition */
3438 DPRINT("Unknown partition found\n");
3439 InstallOnFloppy = TRUE;
3440 }
3441
3442 if (InstallOnFloppy == TRUE)
3443 {
3444 return BOOT_LOADER_FLOPPY_PAGE;
3445 }
3446
3447 /* Unattended install on hdd? */
3448 if (IsUnattendedSetup && UnattendMBRInstallType == 2)
3449 {
3450 return BOOT_LOADER_HARDDISK_MBR_PAGE;
3451 }
3452
3453 MUIDisplayPage(BOOT_LOADER_PAGE);
3454 CONSOLE_InvertTextXY(8, Line, 60, 1);
3455
3456 while (TRUE)
3457 {
3458 CONSOLE_ConInKey(Ir);
3459
3460 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3461 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
3462 {
3463 CONSOLE_NormalTextXY(8, Line, 60, 1);
3464
3465 Line++;
3466 if (Line<12)
3467 Line=15;
3468
3469 if (Line>15)
3470 Line=12;
3471
3472 CONSOLE_InvertTextXY(8, Line, 60, 1);
3473 }
3474 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3475 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
3476 {
3477 CONSOLE_NormalTextXY(8, Line, 60, 1);
3478
3479 Line--;
3480 if (Line<12)
3481 Line=15;
3482
3483 if (Line>15)
3484 Line=12;
3485
3486 CONSOLE_InvertTextXY(8, Line, 60, 1);
3487 }
3488 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3489 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
3490 {
3491 if (ConfirmQuit(Ir) == TRUE)
3492 return QUIT_PAGE;
3493
3494 break;
3495 }
3496 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
3497 {
3498 if (Line == 12)
3499 {
3500 return BOOT_LOADER_HARDDISK_MBR_PAGE;
3501 }
3502 else if (Line == 13)
3503 {
3504 return BOOT_LOADER_HARDDISK_VBR_PAGE;
3505 }
3506 else if (Line == 14)
3507 {
3508 return BOOT_LOADER_FLOPPY_PAGE;
3509 }
3510 else if (Line == 15)
3511 {
3512 return SUCCESS_PAGE;
3513 }
3514
3515 return BOOT_LOADER_PAGE;
3516 }
3517 }
3518
3519 return BOOT_LOADER_PAGE;
3520 }
3521
3522
3523 static PAGE_NUMBER
3524 BootLoaderFloppyPage(PINPUT_RECORD Ir)
3525 {
3526 NTSTATUS Status;
3527
3528 MUIDisplayPage(BOOT_LOADER_FLOPPY_PAGE);
3529
3530 // SetStatusText(" Please wait...");
3531
3532 while (TRUE)
3533 {
3534 CONSOLE_ConInKey(Ir);
3535
3536 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3537 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
3538 {
3539 if (ConfirmQuit(Ir) == TRUE)
3540 return QUIT_PAGE;
3541
3542 break;
3543 }
3544 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
3545 {
3546 if (DoesFileExist(L"\\Device\\Floppy0", L"\\") == FALSE)
3547 {
3548 MUIDisplayError(ERROR_NO_FLOPPY, Ir, POPUP_WAIT_ENTER);
3549 return BOOT_LOADER_FLOPPY_PAGE;
3550 }
3551
3552 Status = InstallFatBootcodeToFloppy(&SourceRootPath, &DestinationArcPath);
3553 if (!NT_SUCCESS(Status))
3554 {
3555 /* Print error message */
3556 return BOOT_LOADER_FLOPPY_PAGE;
3557 }
3558
3559 return SUCCESS_PAGE;
3560 }
3561 }
3562
3563 return BOOT_LOADER_FLOPPY_PAGE;
3564 }
3565
3566 static PAGE_NUMBER
3567 BootLoaderHarddiskVbrPage(PINPUT_RECORD Ir)
3568 {
3569 UCHAR PartitionType;
3570 NTSTATUS Status;
3571
3572 PartitionType = PartitionList->ActiveBootPartition->
3573 PartInfo[PartitionList->ActiveBootPartitionNumber].PartitionType;
3574
3575 Status = InstallVBRToPartition(&SystemRootPath,
3576 &SourceRootPath,
3577 &DestinationArcPath,
3578 PartitionType);
3579 if (!NT_SUCCESS(Status))
3580 {
3581 MUIDisplayError(ERROR_WRITE_BOOT, Ir, POPUP_WAIT_ENTER);
3582 return QUIT_PAGE;
3583 }
3584
3585 return SUCCESS_PAGE;
3586 }
3587
3588 static PAGE_NUMBER
3589 BootLoaderHarddiskMbrPage(PINPUT_RECORD Ir)
3590 {
3591 UCHAR PartitionType;
3592 NTSTATUS Status;
3593 WCHAR DestinationDevicePathBuffer[MAX_PATH];
3594 WCHAR SourceMbrPathBuffer[MAX_PATH];
3595
3596 /* Step 1: Write the VBR */
3597 PartitionType = PartitionList->ActiveBootPartition->
3598 PartInfo[PartitionList->ActiveBootPartitionNumber].PartitionType;
3599
3600 Status = InstallVBRToPartition(&SystemRootPath,
3601 &SourceRootPath,
3602 &DestinationArcPath,
3603 PartitionType);
3604 if (!NT_SUCCESS(Status))
3605 {
3606 MUIDisplayError(ERROR_WRITE_BOOT, Ir, POPUP_WAIT_ENTER);
3607 return QUIT_PAGE;
3608 }
3609
3610 /* Step 2: Write the MBR */
3611 swprintf(DestinationDevicePathBuffer,
3612 L"\\Device\\Harddisk%d\\Partition0",
3613 PartitionList->ActiveBootDisk->DiskNumber);
3614
3615 wcscpy(SourceMbrPathBuffer, SourceRootPath.Buffer);
3616 wcscat(SourceMbrPathBuffer, L"\\loader\\dosmbr.bin");
3617
3618 DPRINT("Install MBR bootcode: %S ==> %S\n",
3619 SourceMbrPathBuffer, DestinationDevicePathBuffer);
3620
3621 Status = InstallMbrBootCodeToDisk(SourceMbrPathBuffer,
3622 DestinationDevicePathBuffer);
3623 if (!NT_SUCCESS (Status))
3624 {
3625 DPRINT1("InstallMbrBootCodeToDisk() failed (Status %lx)\n",
3626 Status);
3627 MUIDisplayError(ERROR_INSTALL_BOOTCODE, Ir, POPUP_WAIT_ENTER);
3628 return QUIT_PAGE;
3629 }
3630
3631 return SUCCESS_PAGE;
3632 }
3633
3634
3635 static PAGE_NUMBER
3636 QuitPage(PINPUT_RECORD Ir)
3637 {
3638 MUIDisplayPage(QUIT_PAGE);
3639
3640 /* Destroy partition list */
3641 if (PartitionList != NULL)
3642 {
3643 DestroyPartitionList (PartitionList);
3644 PartitionList = NULL;
3645 }
3646
3647 /* Destroy filesystem list */
3648 if (FileSystemList != NULL)
3649 {
3650 DestroyFileSystemList (FileSystemList);
3651 FileSystemList = NULL;
3652 }
3653
3654 /* Destroy computer settings list */
3655 if (ComputerList != NULL)
3656 {
3657 DestroyGenericList(ComputerList, TRUE);
3658 ComputerList = NULL;
3659 }
3660
3661 /* Destroy display settings list */
3662 if (DisplayList != NULL)
3663 {
3664 DestroyGenericList