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