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