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