Sync with trunk r63383 .
[reactos.git] / 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 MUIDisplayPage(SELECT_PARTITION_PAGE);
1467
1468 if (PartitionList == NULL)
1469 {
1470 PartitionList = CreatePartitionList(2,
1471 19,
1472 xScreen - 3,
1473 yScreen - 3);
1474 if (PartitionList == NULL)
1475 {
1476 /* FIXME: show an error dialog */
1477 return QUIT_PAGE;
1478 }
1479 else if (IsListEmpty (&PartitionList->DiskListHead))
1480 {
1481 MUIDisplayError(ERROR_NO_HDD, Ir, POPUP_WAIT_ENTER);
1482 return QUIT_PAGE;
1483 }
1484 }
1485
1486 DrawPartitionList(PartitionList);
1487
1488 /* Warn about partitions created by Linux Fdisk */
1489 if (WarnLinuxPartitions == TRUE &&
1490 CheckForLinuxFdiskPartitions(PartitionList) == TRUE)
1491 {
1492 MUIDisplayError(ERROR_WARN_PARTITION, NULL, POPUP_WAIT_NONE);
1493
1494 while (TRUE)
1495 {
1496 CONSOLE_ConInKey(Ir);
1497
1498 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1499 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1500 {
1501 return QUIT_PAGE;
1502 }
1503 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
1504 {
1505 WarnLinuxPartitions = FALSE;
1506 return SELECT_PARTITION_PAGE;
1507 }
1508 }
1509 }
1510
1511 if (IsUnattendedSetup)
1512 {
1513 if (!SelectPartition(PartitionList, UnattendDestinationDiskNumber, UnattendDestinationPartitionNumber))
1514 {
1515 if (AutoPartition)
1516 {
1517 #if 0
1518 if (!IsDiskSizeValid(PartitionList->CurrentPartition))
1519 {
1520 MUIDisplayError(ERROR_INSUFFICIENT_DISKSPACE, Ir, POPUP_WAIT_ANY_KEY);
1521 return SELECT_PARTITION_PAGE; /* let the user select another partition */
1522 }
1523 #endif
1524 CreateNewPartition(PartitionList,
1525 PartitionList->CurrentPartition->SectorCount.QuadPart,
1526 TRUE);
1527
1528 DestinationDriveLetter = (WCHAR)PartitionList->CurrentPartition->DriveLetter;
1529
1530 return SELECT_FILE_SYSTEM_PAGE;
1531 }
1532 }
1533 else
1534 {
1535 #if 0
1536 if (!IsDiskSizeValid(PartitionList->CurrentPartition))
1537 {
1538 MUIDisplayError(ERROR_INSUFFICIENT_DISKSPACE, Ir, POPUP_WAIT_ANY_KEY);
1539 return SELECT_PARTITION_PAGE; /* let the user select another partition */
1540 }
1541 #endif
1542 DestinationDriveLetter = (WCHAR)PartitionList->CurrentPartition->DriveLetter;
1543
1544 return SELECT_FILE_SYSTEM_PAGE;
1545 }
1546 }
1547
1548 while (TRUE)
1549 {
1550 /* Update status text */
1551 if (PartitionList->CurrentPartition == NULL ||
1552 PartitionList->CurrentPartition->IsPartitioned == FALSE)
1553 {
1554 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATEPARTITION));
1555 }
1556 else
1557 {
1558 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLDELETEPARTITION));
1559 }
1560
1561 CONSOLE_ConInKey(Ir);
1562
1563 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1564 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1565 {
1566 if (ConfirmQuit(Ir) == TRUE)
1567 {
1568 DestroyPartitionList(PartitionList);
1569 PartitionList = NULL;
1570 return QUIT_PAGE;
1571 }
1572
1573 break;
1574 }
1575 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1576 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1577 {
1578 ScrollDownPartitionList(PartitionList);
1579 }
1580 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1581 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1582 {
1583 ScrollUpPartitionList(PartitionList);
1584 }
1585 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
1586 {
1587 #if 0
1588 if (!IsDiskSizeValid(PartitionList->CurrentPartition))
1589 {
1590 MUIDisplayError(ERROR_INSUFFICIENT_DISKSPACE, Ir, POPUP_WAIT_ANY_KEY);
1591 return SELECT_PARTITION_PAGE; /* let the user select another partition */
1592 }
1593 #endif
1594 if (PartitionList->CurrentPartition == NULL ||
1595 PartitionList->CurrentPartition->IsPartitioned == FALSE)
1596 {
1597 CreateNewPartition(PartitionList,
1598 0ULL,
1599 TRUE);
1600 }
1601
1602 DestinationDriveLetter = (WCHAR)PartitionList->CurrentPartition->DriveLetter;
1603
1604 return SELECT_FILE_SYSTEM_PAGE;
1605 }
1606 else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'C') /* C */
1607 {
1608 if (PartitionList->CurrentPartition->IsPartitioned == TRUE)
1609 {
1610 MUIDisplayError(ERROR_NEW_PARTITION, Ir, POPUP_WAIT_ANY_KEY);
1611 return SELECT_PARTITION_PAGE;
1612 }
1613
1614 return CREATE_PARTITION_PAGE;
1615 }
1616 else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'D') /* D */
1617 {
1618 if (PartitionList->CurrentPartition->IsPartitioned == FALSE)
1619 {
1620 MUIDisplayError(ERROR_DELETE_SPACE, Ir, POPUP_WAIT_ANY_KEY);
1621 return SELECT_PARTITION_PAGE;
1622 }
1623
1624 return DELETE_PARTITION_PAGE;
1625 }
1626 }
1627
1628 return SELECT_PARTITION_PAGE;
1629 }
1630
1631
1632 static VOID
1633 DrawInputField(ULONG FieldLength,
1634 SHORT Left,
1635 SHORT Top,
1636 PCHAR FieldContent)
1637 {
1638 CHAR buf[100];
1639 COORD coPos;
1640 DWORD Written;
1641
1642 coPos.X = Left;
1643 coPos.Y = Top;
1644 memset(buf, '_', sizeof(buf));
1645 buf[FieldLength - strlen(FieldContent)] = 0;
1646 strcat(buf, FieldContent);
1647
1648 WriteConsoleOutputCharacterA(StdOutput,
1649 buf,
1650 strlen(buf),
1651 coPos,
1652 &Written);
1653 }
1654
1655
1656 #define PARTITION_SIZE_INPUT_FIELD_LENGTH 6
1657 /* Restriction for MaxSize: pow(10, PARTITION_SIZE_INPUT_FIELD_LENGTH)-1 */
1658 #define PARTITION_MAXSIZE 999999
1659
1660 static VOID
1661 ShowPartitionSizeInputBox(SHORT Left,
1662 SHORT Top,
1663 SHORT Right,
1664 SHORT Bottom,
1665 ULONG MaxSize,
1666 PCHAR InputBuffer,
1667 PBOOLEAN Quit,
1668 PBOOLEAN Cancel)
1669 {
1670 INPUT_RECORD Ir;
1671 COORD coPos;
1672 DWORD Written;
1673 CHAR Buffer[100];
1674 ULONG Index;
1675 CHAR ch;
1676 SHORT iLeft;
1677 SHORT iTop;
1678
1679 if (Quit != NULL)
1680 *Quit = FALSE;
1681
1682 if (Cancel != NULL)
1683 *Cancel = FALSE;
1684
1685 DrawBox(Left, Top, Right - Left + 1, Bottom - Top + 1);
1686
1687 /* Print message */
1688 coPos.X = Left + 2;
1689 coPos.Y = Top + 2;
1690 strcpy(Buffer, MUIGetString(STRING_PARTITIONSIZE));
1691 iLeft = coPos.X + strlen(Buffer) + 1;
1692 iTop = coPos.Y;
1693
1694 WriteConsoleOutputCharacterA(StdOutput,
1695 Buffer,
1696 strlen (Buffer),
1697 coPos,
1698 &Written);
1699
1700 sprintf(Buffer, MUIGetString(STRING_MAXSIZE), MaxSize);
1701 coPos.X = iLeft + PARTITION_SIZE_INPUT_FIELD_LENGTH + 1;
1702 coPos.Y = iTop;
1703 WriteConsoleOutputCharacterA(StdOutput,
1704 Buffer,
1705 strlen (Buffer),
1706 coPos,
1707 &Written);
1708
1709 sprintf(Buffer, "%lu", MaxSize);
1710 Index = strlen(Buffer);
1711 DrawInputField(PARTITION_SIZE_INPUT_FIELD_LENGTH,
1712 iLeft,
1713 iTop,
1714 Buffer);
1715
1716 while (TRUE)
1717 {
1718 CONSOLE_ConInKey(&Ir);
1719
1720 if ((Ir.Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1721 (Ir.Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1722 {
1723 if (Quit != NULL)
1724 *Quit = TRUE;
1725
1726 Buffer[0] = 0;
1727 break;
1728 }
1729 else if (Ir.Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
1730 {
1731 break;
1732 }
1733 else if (Ir.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESCAPE */
1734 {
1735 if (Cancel != NULL)
1736 *Cancel = TRUE;
1737
1738 Buffer[0] = 0;
1739 break;
1740 }
1741 else if ((Ir.Event.KeyEvent.wVirtualKeyCode == VK_BACK) && /* BACKSPACE */
1742 (Index > 0))
1743 {
1744 Index--;
1745 Buffer[Index] = 0;
1746
1747 DrawInputField(PARTITION_SIZE_INPUT_FIELD_LENGTH,
1748 iLeft,
1749 iTop,
1750 Buffer);
1751 }
1752 else if ((Ir.Event.KeyEvent.uChar.AsciiChar != 0x00) &&
1753 (Index < PARTITION_SIZE_INPUT_FIELD_LENGTH))
1754 {
1755 ch = Ir.Event.KeyEvent.uChar.AsciiChar;
1756
1757 if ((ch >= '0') && (ch <= '9'))
1758 {
1759 Buffer[Index] = ch;
1760 Index++;
1761 Buffer[Index] = 0;
1762
1763 DrawInputField(PARTITION_SIZE_INPUT_FIELD_LENGTH,
1764 iLeft,
1765 iTop,
1766 Buffer);
1767 }
1768 }
1769 }
1770
1771 strcpy(InputBuffer, Buffer);
1772 }
1773
1774
1775 static PAGE_NUMBER
1776 CreatePartitionPage(PINPUT_RECORD Ir)
1777 {
1778 PDISKENTRY DiskEntry;
1779 PPARTENTRY PartEntry;
1780 BOOLEAN Quit;
1781 BOOLEAN Cancel;
1782 CHAR InputBuffer[50];
1783 ULONG MaxSize;
1784 ULONGLONG PartSize;
1785 ULONGLONG DiskSize;
1786 ULONGLONG SectorCount;
1787 PCHAR Unit;
1788
1789 if (PartitionList == NULL ||
1790 PartitionList->CurrentDisk == NULL ||
1791 PartitionList->CurrentPartition == NULL)
1792 {
1793 /* FIXME: show an error dialog */
1794 return QUIT_PAGE;
1795 }
1796
1797 DiskEntry = PartitionList->CurrentDisk;
1798 PartEntry = PartitionList->CurrentPartition;
1799
1800 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
1801
1802 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSENEWPARTITION));
1803
1804 DiskSize = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
1805 #if 0
1806 if (DiskSize >= 10737418240) /* 10 GB */
1807 {
1808 DiskSize = DiskSize / 1073741824;
1809 Unit = MUIGetString(STRING_GB);
1810 }
1811 else
1812 #endif
1813 {
1814 DiskSize = DiskSize / 1048576;
1815 if (DiskSize == 0)
1816 DiskSize = 1;
1817
1818 Unit = MUIGetString(STRING_MB);
1819 }
1820
1821 if (DiskEntry->DriverName.Length > 0)
1822 {
1823 CONSOLE_PrintTextXY(6, 10,
1824 MUIGetString(STRING_HDINFOPARTCREATE),
1825 DiskSize,
1826 Unit,
1827 DiskEntry->DiskNumber,
1828 DiskEntry->Port,
1829 DiskEntry->Bus,
1830 DiskEntry->Id,
1831 &DiskEntry->DriverName);
1832 }
1833 else
1834 {
1835 CONSOLE_PrintTextXY(6, 10,
1836 MUIGetString(STRING_HDDINFOUNK1),
1837 DiskSize,
1838 Unit,
1839 DiskEntry->DiskNumber,
1840 DiskEntry->Port,
1841 DiskEntry->Bus,
1842 DiskEntry->Id);
1843 }
1844
1845 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE));
1846
1847 #if 0
1848 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
1849 PartitionList->CurrentPartition->SectorCount * DiskEntry->BytesPerSector / 1048576);
1850 #endif
1851
1852 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION));
1853
1854 PartEntry = PartitionList->CurrentPartition;
1855 while (TRUE)
1856 {
1857 MaxSize = (PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector) / 1048576; /* in MBytes (rounded) */
1858
1859 if (MaxSize > PARTITION_MAXSIZE)
1860 MaxSize = PARTITION_MAXSIZE;
1861
1862 ShowPartitionSizeInputBox(12, 14, xScreen - 12, 17, /* left, top, right, bottom */
1863 MaxSize, InputBuffer, &Quit, &Cancel);
1864
1865 if (Quit == TRUE)
1866 {
1867 if (ConfirmQuit (Ir) == TRUE)
1868 {
1869 return QUIT_PAGE;
1870 }
1871 }
1872 else if (Cancel == TRUE)
1873 {
1874 return SELECT_PARTITION_PAGE;
1875 }
1876 else
1877 {
1878 PartSize = atoi(InputBuffer);
1879
1880 if (PartSize < 1)
1881 {
1882 /* Too small */
1883 continue;
1884 }
1885
1886 if (PartSize > MaxSize)
1887 {
1888 /* Too large */
1889 continue;
1890 }
1891
1892 /* Convert to bytes */
1893 if (PartSize == MaxSize)
1894 {
1895 /* Use all of the unpartitioned disk space */
1896 SectorCount = PartEntry->SectorCount.QuadPart;
1897 }
1898 else
1899 {
1900 /* Calculate the sector count from the size in MB */
1901 SectorCount = PartSize * 1048576 / DiskEntry->BytesPerSector;
1902
1903 /* But never get larger than the unpartitioned disk space */
1904 if (SectorCount > PartEntry->SectorCount.QuadPart)
1905 SectorCount = PartEntry->SectorCount.QuadPart;
1906 }
1907
1908 DPRINT ("Partition size: %I64u bytes\n", PartSize);
1909
1910 CreateNewPartition(PartitionList,
1911 SectorCount,
1912 FALSE);
1913
1914 return SELECT_PARTITION_PAGE;
1915 }
1916 }
1917
1918 return CREATE_PARTITION_PAGE;
1919 }
1920
1921
1922 static PAGE_NUMBER
1923 DeletePartitionPage(PINPUT_RECORD Ir)
1924 {
1925 PDISKENTRY DiskEntry;
1926 PPARTENTRY PartEntry;
1927 ULONGLONG DiskSize;
1928 ULONGLONG PartSize;
1929 PCHAR Unit;
1930 PCHAR PartType;
1931
1932 if (PartitionList == NULL ||
1933 PartitionList->CurrentDisk == NULL ||
1934 PartitionList->CurrentPartition == NULL)
1935 {
1936 /* FIXME: show an error dialog */
1937 return QUIT_PAGE;
1938 }
1939
1940 DiskEntry = PartitionList->CurrentDisk;
1941 PartEntry = PartitionList->CurrentPartition;
1942
1943 MUIDisplayPage(DELETE_PARTITION_PAGE);
1944
1945 /* Determine partition type */
1946 PartType = NULL;
1947 if (PartEntry->New == TRUE)
1948 {
1949 PartType = MUIGetString(STRING_UNFORMATTED);
1950 }
1951 else if (PartEntry->IsPartitioned == TRUE)
1952 {
1953 if ((PartEntry->PartitionType == PARTITION_FAT_12) ||
1954 (PartEntry->PartitionType == PARTITION_FAT_16) ||
1955 (PartEntry->PartitionType == PARTITION_HUGE) ||
1956 (PartEntry->PartitionType == PARTITION_XINT13))
1957 {
1958 PartType = "FAT";
1959 }
1960 else if ((PartEntry->PartitionType == PARTITION_FAT32) ||
1961 (PartEntry->PartitionType == PARTITION_FAT32_XINT13))
1962 {
1963 PartType = "FAT32";
1964 }
1965 else if (PartEntry->PartitionType == PARTITION_EXT2)
1966 {
1967 PartType = "EXT2";
1968 }
1969 else if (PartEntry->PartitionType == PARTITION_IFS)
1970 {
1971 PartType = "NTFS"; /* FIXME: Not quite correct! */
1972 }
1973 }
1974
1975 PartSize = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
1976 #if 0
1977 if (PartSize >= 10737418240) /* 10 GB */
1978 {
1979 PartSize = PartSize / 1073741824;
1980 Unit = MUIGetString(STRING_GB);
1981 }
1982 else
1983 #endif
1984 if (PartSize >= 10485760) /* 10 MB */
1985 {
1986 PartSize = PartSize / 1048576;
1987 Unit = MUIGetString(STRING_MB);
1988 }
1989 else
1990 {
1991 PartSize = PartSize / 1024;
1992 Unit = MUIGetString(STRING_KB);
1993 }
1994
1995 if (PartType == NULL)
1996 {
1997 CONSOLE_PrintTextXY(6, 10,
1998 MUIGetString(STRING_HDDINFOUNK2),
1999 (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
2000 (PartEntry->DriveLetter == 0) ? '-' : ':',
2001 PartEntry->PartitionType,
2002 PartSize,
2003 Unit);
2004 }
2005 else
2006 {
2007 CONSOLE_PrintTextXY(6, 10,
2008 " %c%c %s %I64u %s",
2009 (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
2010 (PartEntry->DriveLetter == 0) ? '-' : ':',
2011 PartType,
2012 PartSize,
2013 Unit);
2014 }
2015
2016 DiskSize = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
2017 #if 0
2018 if (DiskSize >= 10737418240) /* 10 GB */
2019 {
2020 DiskSize = DiskSize / 1073741824;
2021 Unit = MUIGetString(STRING_GB);
2022 }
2023 else
2024 #endif
2025 {
2026 DiskSize = DiskSize / 1048576;
2027 if (DiskSize == 0)
2028 DiskSize = 1;
2029
2030 Unit = MUIGetString(STRING_MB);
2031 }
2032
2033 if (DiskEntry->DriverName.Length > 0)
2034 {
2035 CONSOLE_PrintTextXY(6, 12,
2036 MUIGetString(STRING_HDINFOPARTDELETE),
2037 DiskSize,
2038 Unit,
2039 DiskEntry->DiskNumber,
2040 DiskEntry->Port,
2041 DiskEntry->Bus,
2042 DiskEntry->Id,
2043 &DiskEntry->DriverName);
2044 }
2045 else
2046 {
2047 CONSOLE_PrintTextXY(6, 12,
2048 MUIGetString(STRING_HDDINFOUNK3),
2049 DiskSize,
2050 Unit,
2051 DiskEntry->DiskNumber,
2052 DiskEntry->Port,
2053 DiskEntry->Bus,
2054 DiskEntry->Id);
2055 }
2056
2057 while (TRUE)
2058 {
2059 CONSOLE_ConInKey(Ir);
2060
2061 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2062 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
2063 {
2064 if (ConfirmQuit(Ir) == TRUE)
2065 {
2066 return QUIT_PAGE;
2067 }
2068
2069 break;
2070 }
2071 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESC */
2072 {
2073 return SELECT_PARTITION_PAGE;
2074 }
2075 else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'D') /* D */
2076 {
2077 DeleteCurrentPartition(PartitionList);
2078
2079 return SELECT_PARTITION_PAGE;
2080 }
2081 }
2082
2083 return DELETE_PARTITION_PAGE;
2084 }
2085
2086
2087 static PAGE_NUMBER
2088 SelectFileSystemPage(PINPUT_RECORD Ir)
2089 {
2090 PDISKENTRY DiskEntry;
2091 PPARTENTRY PartEntry;
2092 ULONGLONG DiskSize;
2093 ULONGLONG PartSize;
2094 PCHAR DiskUnit;
2095 PCHAR PartUnit;
2096 PCHAR PartType;
2097
2098 if (PartitionList == NULL ||
2099 PartitionList->CurrentDisk == NULL ||
2100 PartitionList->CurrentPartition == NULL)
2101 {
2102 /* FIXME: show an error dialog */
2103 return QUIT_PAGE;
2104 }
2105
2106 DiskEntry = PartitionList->CurrentDisk;
2107 PartEntry = PartitionList->CurrentPartition;
2108
2109 /* adjust disk size */
2110 DiskSize = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
2111 if (DiskSize >= 10737418240) /* 10 GB */
2112 {
2113 DiskSize = DiskSize / 1073741824;
2114 DiskUnit = MUIGetString(STRING_GB);
2115 }
2116 else
2117 {
2118 DiskSize = DiskSize / 1048576;
2119 DiskUnit = MUIGetString(STRING_MB);
2120 }
2121
2122 /* adjust partition size */
2123 PartSize = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
2124 if (PartSize >= 10737418240) /* 10 GB */
2125 {
2126 PartSize = PartSize / 1073741824;
2127 PartUnit = MUIGetString(STRING_GB);
2128 }
2129 else
2130 {
2131 PartSize = PartSize / 1048576;
2132 PartUnit = MUIGetString(STRING_MB);
2133 }
2134
2135 /* adjust partition type */
2136 if ((PartEntry->PartitionType == PARTITION_FAT_12) ||
2137 (PartEntry->PartitionType == PARTITION_FAT_16) ||
2138 (PartEntry->PartitionType == PARTITION_HUGE) ||
2139 (PartEntry->PartitionType == PARTITION_XINT13))
2140 {
2141 PartType = "FAT";
2142 }
2143 else if ((PartEntry->PartitionType == PARTITION_FAT32) ||
2144 (PartEntry->PartitionType == PARTITION_FAT32_XINT13))
2145 {
2146 PartType = "FAT32";
2147 }
2148 else if (PartEntry->PartitionType == PARTITION_EXT2)
2149 {
2150 PartType = "EXT2";
2151 }
2152 else if (PartEntry->PartitionType == PARTITION_IFS)
2153 {
2154 PartType = "NTFS"; /* FIXME: Not quite correct! */
2155 }
2156 else if (PartEntry->PartitionType == PARTITION_ENTRY_UNUSED)
2157 {
2158 PartType = MUIGetString(STRING_FORMATUNUSED);
2159 }
2160 else
2161 {
2162 PartType = MUIGetString(STRING_FORMATUNKNOWN);
2163 }
2164
2165 if (PartEntry->AutoCreate == TRUE)
2166 {
2167 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NEWPARTITION));
2168
2169 #if 0
2170 CONSOLE_PrintTextXY(8, 10, "Partition %lu (%I64u %s) %s of",
2171 PartEntry->PartitionNumber,
2172 PartSize,
2173 PartUnit,
2174 PartType);
2175 #endif
2176
2177 CONSOLE_PrintTextXY(8, 10, MUIGetString(STRING_HDINFOPARTZEROED),
2178 DiskEntry->DiskNumber,
2179 DiskSize,
2180 DiskUnit,
2181 DiskEntry->Port,
2182 DiskEntry->Bus,
2183 DiskEntry->Id,
2184 &DiskEntry->DriverName);
2185
2186 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_PARTFORMAT));
2187
2188
2189 PartEntry->AutoCreate = FALSE;
2190 }
2191 else if (PartEntry->New == TRUE)
2192 {
2193 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDPART));
2194 CONSOLE_SetTextXY(6, 10, MUIGetString(STRING_PARTFORMAT));
2195 }
2196 else
2197 {
2198 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_INSTALLONPART));
2199
2200 if (PartType == NULL)
2201 {
2202 CONSOLE_PrintTextXY(8, 10,
2203 MUIGetString(STRING_HDDINFOUNK4),
2204 (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
2205 (PartEntry->DriveLetter == 0) ? '-' : ':',
2206 PartEntry->PartitionType,
2207 PartSize,
2208 PartUnit);
2209 }
2210 else
2211 {
2212 CONSOLE_PrintTextXY(8, 10,
2213 "%c%c %s %I64u %s",
2214 (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
2215 (PartEntry->DriveLetter == 0) ? '-' : ':',
2216 PartType,
2217 PartSize,
2218 PartUnit);
2219 }
2220
2221 CONSOLE_PrintTextXY(6, 12, MUIGetString(STRING_HDINFOPARTEXISTS),
2222 DiskEntry->DiskNumber,
2223 DiskSize,
2224 DiskUnit,
2225 DiskEntry->Port,
2226 DiskEntry->Bus,
2227 DiskEntry->Id,
2228 &DiskEntry->DriverName);
2229 }
2230
2231 MUIDisplayPage(SELECT_FILE_SYSTEM_PAGE);
2232
2233 if (FileSystemList == NULL)
2234 {
2235 FileSystemList = CreateFileSystemList(6, 26, PartEntry->New, L"FAT");
2236 if (FileSystemList == NULL)
2237 {
2238 /* FIXME: show an error dialog */
2239 return QUIT_PAGE;
2240 }
2241
2242 /* FIXME: Add file systems to list */
2243 }
2244
2245 DrawFileSystemList(FileSystemList);
2246
2247 if (RepairUpdateFlag)
2248 {
2249 return CHECK_FILE_SYSTEM_PAGE;
2250 //return SELECT_PARTITION_PAGE;
2251 }
2252
2253 if (IsUnattendedSetup)
2254 {
2255 if (UnattendFormatPartition)
2256 {
2257 return FORMAT_PARTITION_PAGE;
2258 }
2259
2260 return CHECK_FILE_SYSTEM_PAGE;
2261 }
2262
2263 while (TRUE)
2264 {
2265 CONSOLE_ConInKey(Ir);
2266
2267 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2268 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
2269 {
2270 if (ConfirmQuit(Ir) == TRUE)
2271 {
2272 return QUIT_PAGE;
2273 }
2274
2275 break;
2276 }
2277 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2278 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
2279 {
2280 return SELECT_PARTITION_PAGE;
2281 }
2282 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2283 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
2284 {
2285 ScrollDownFileSystemList(FileSystemList);
2286 }
2287 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2288 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
2289 {
2290 ScrollUpFileSystemList(FileSystemList);
2291 }
2292 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
2293 {
2294 if (!FileSystemList->Selected->FormatFunc)
2295 {
2296 return CHECK_FILE_SYSTEM_PAGE;
2297 }
2298 else
2299 {
2300 return FORMAT_PARTITION_PAGE;
2301 }
2302 }
2303 }
2304
2305 return SELECT_FILE_SYSTEM_PAGE;
2306 }
2307
2308
2309 static ULONG
2310 FormatPartitionPage(PINPUT_RECORD Ir)
2311 {
2312 WCHAR PathBuffer[MAX_PATH];
2313 PDISKENTRY DiskEntry;
2314 PPARTENTRY PartEntry;
2315 NTSTATUS Status;
2316
2317 #ifndef NDEBUG
2318 ULONG Line;
2319 ULONG i;
2320 PLIST_ENTRY Entry;
2321 #endif
2322
2323 MUIDisplayPage(FORMAT_PARTITION_PAGE);
2324
2325 if (PartitionList == NULL ||
2326 PartitionList->CurrentDisk == NULL ||
2327 PartitionList->CurrentPartition == NULL)
2328 {
2329 /* FIXME: show an error dialog */
2330 return QUIT_PAGE;
2331 }
2332
2333 DiskEntry = PartitionList->CurrentDisk;
2334 PartEntry = PartitionList->CurrentPartition;
2335
2336 while (TRUE)
2337 {
2338 if (!IsUnattendedSetup)
2339 {
2340 CONSOLE_ConInKey(Ir);
2341 }
2342
2343 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2344 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
2345 {
2346 if (ConfirmQuit(Ir) == TRUE)
2347 {
2348 return QUIT_PAGE;
2349 }
2350
2351 break;
2352 }
2353 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN || IsUnattendedSetup) /* ENTER */
2354 {
2355 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
2356
2357 if (wcscmp(FileSystemList->Selected->FileSystem, L"FAT") == 0)
2358 {
2359 if (PartEntry->SectorCount.QuadPart < 8192)
2360 {
2361 /* FAT12 CHS partition (disk is smaller than 4.1MB) */
2362 PartEntry->PartitionType = PARTITION_FAT_12;
2363 }
2364 else if (PartEntry->StartSector.QuadPart < 1450560)
2365 {
2366 /* Partition starts below the 8.4GB boundary ==> CHS partition */
2367
2368 if (PartEntry->SectorCount.QuadPart < 65536)
2369 {
2370 /* FAT16 CHS partition (partiton size < 32MB) */
2371 PartEntry->PartitionType = PARTITION_FAT_16;
2372 }
2373 else if (PartEntry->SectorCount.QuadPart < 1048576)
2374 {
2375 /* FAT16 CHS partition (partition size < 512MB) */
2376 PartEntry->PartitionType = PARTITION_HUGE;
2377 }
2378 else
2379 {
2380 /* FAT32 CHS partition (partition size >= 512MB) */
2381 PartEntry->PartitionType = PARTITION_FAT32;
2382 }
2383 }
2384 else
2385 {
2386 /* Partition starts above the 8.4GB boundary ==> LBA partition */
2387
2388 if (PartEntry->SectorCount.QuadPart < 1048576)
2389 {
2390 /* FAT16 LBA partition (partition size < 512MB) */
2391 PartEntry->PartitionType = PARTITION_XINT13;
2392 }
2393 else
2394 {
2395 /* FAT32 LBA partition (partition size >= 512MB) */
2396 PartEntry->PartitionType = PARTITION_FAT32_XINT13;
2397 }
2398 }
2399
2400 DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].PartitionType = PartEntry->PartitionType;
2401 }
2402 #if 0
2403 else if (wcscmp(FileSystemList->Selected->FileSystem, L"EXT2") == 0)
2404 {
2405 PartEntry->PartInfo[PartNum].PartitionType = PARTITION_EXT2;
2406 DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].PartitionType = PartEntry->PartitionType;
2407 }
2408 #endif
2409 else if (!FileSystemList->Selected->FormatFunc)
2410 return QUIT_PAGE;
2411
2412 #ifndef NDEBUG
2413 CONSOLE_PrintTextXY(6, 12,
2414 "Disk: %I64u Cylinder: %I64u Track: %I64u",
2415 DiskEntry->DiskSize,
2416 DiskEntry->CylinderSize,
2417 DiskEntry->TrackSize);
2418
2419 Line = 13;
2420 DiskEntry = PartitionList->CurrentDisk;
2421 Entry = DiskEntry->PartListHead.Flink;
2422
2423 while (Entry != &DiskEntry->PrimaryPartListHead)
2424 {
2425 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
2426
2427 if (PartEntry->IsPartitioned == TRUE)
2428 {
2429 CONSOLE_PrintTextXY(6, Line,
2430 "%2u: %2u %c %12I64u %12I64u %2u %c",
2431 i,
2432 PartEntry->PartitionNumber,
2433 PartEntry->BootIndicator ? 'A' : '-',
2434 PartEntry->StartSector.QuadPart,
2435 PartEntry->SectorCount.QuadPart,
2436 PartEntry->PartitionType,
2437 PartEntry->Dirty ? '*' : ' ');
2438 Line++;
2439 }
2440
2441 Entry = Entry->Flink;
2442 }
2443
2444 /* Restore the old entry */
2445 PartEntry = PartitionList->CurrentPartition;
2446 #endif
2447
2448 CheckActiveBootPartition(PartitionList);
2449
2450 if (WritePartitionsToDisk(PartitionList) == FALSE)
2451 {
2452 DPRINT("WritePartitionsToDisk() failed\n");
2453 MUIDisplayError(ERROR_WRITE_PTABLE, Ir, POPUP_WAIT_ENTER);
2454 return QUIT_PAGE;
2455 }
2456
2457 /* Set DestinationRootPath */
2458 RtlFreeUnicodeString(&DestinationRootPath);
2459 swprintf(PathBuffer,
2460 L"\\Device\\Harddisk%lu\\Partition%lu",
2461 PartitionList->CurrentDisk->DiskNumber,
2462 PartitionList->CurrentPartition->PartitionNumber);
2463 RtlCreateUnicodeString(&DestinationRootPath,
2464 PathBuffer);
2465 DPRINT("DestinationRootPath: %wZ\n", &DestinationRootPath);
2466
2467 if (FileSystemList->Selected->FormatFunc)
2468 {
2469 Status = FormatPartition(&DestinationRootPath,
2470 FileSystemList->Selected);
2471 if (!NT_SUCCESS(Status))
2472 {
2473 DPRINT1("FormatPartition() failed with status 0x%08lx\n", Status);
2474 /* FIXME: show an error dialog */
2475 return QUIT_PAGE;
2476 }
2477
2478 PartEntry->New = FALSE;
2479
2480 }
2481
2482 #ifndef NDEBUG
2483 CONSOLE_SetStatusText(" Done. Press any key ...");
2484 CONSOLE_ConInKey(Ir);
2485 #endif
2486
2487 DestroyFileSystemList(FileSystemList);
2488 FileSystemList = NULL;
2489 return INSTALL_DIRECTORY_PAGE;
2490 }
2491 }
2492
2493 return FORMAT_PARTITION_PAGE;
2494 }
2495
2496
2497 static ULONG
2498 CheckFileSystemPage(PINPUT_RECORD Ir)
2499 {
2500 PFILE_SYSTEM_ITEM CurrentFileSystem;
2501 WCHAR PathBuffer[MAX_PATH];
2502 CHAR Buffer[MAX_PATH];
2503 NTSTATUS Status;
2504
2505 /* FIXME: code duplicated in FormatPartitionPage */
2506 /* Set DestinationRootPath */
2507 RtlFreeUnicodeString(&DestinationRootPath);
2508 swprintf(PathBuffer,
2509 L"\\Device\\Harddisk%lu\\Partition%lu",
2510 PartitionList->CurrentDisk->DiskNumber,
2511 PartitionList->CurrentPartition->PartitionNumber);
2512 RtlCreateUnicodeString(&DestinationRootPath, PathBuffer);
2513 DPRINT("DestinationRootPath: %wZ\n", &DestinationRootPath);
2514
2515 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHECKINGPART));
2516
2517 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
2518
2519 /* WRONG: first filesystem is not necesseraly the one of the current partition! */
2520 CurrentFileSystem = CONTAINING_RECORD(FileSystemList->ListHead.Flink, FILE_SYSTEM_ITEM, ListEntry);
2521
2522 if (!CurrentFileSystem->ChkdskFunc)
2523 {
2524 sprintf(Buffer,
2525 "Setup is currently unable to check a partition formatted in %S.\n"
2526 "\n"
2527 " \x07 Press ENTER to continue Setup.\n"
2528 " \x07 Press F3 to quit Setup.",
2529 CurrentFileSystem->FileSystem);
2530
2531 PopupError(Buffer,
2532 MUIGetString(STRING_QUITCONTINUE),
2533 NULL, POPUP_WAIT_NONE);
2534
2535 while (TRUE)
2536 {
2537 CONSOLE_ConInKey(Ir);
2538
2539 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x00 &&
2540 Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3) /* F3 */
2541 {
2542 if (ConfirmQuit(Ir))
2543 return QUIT_PAGE;
2544 else
2545 return CHECK_FILE_SYSTEM_PAGE;
2546 }
2547 else if (Ir->Event.KeyEvent.uChar.AsciiChar == VK_RETURN) /* ENTER */
2548 {
2549 return INSTALL_DIRECTORY_PAGE;
2550 }
2551 }
2552 }
2553 else
2554 {
2555 Status = ChkdskPartition(&DestinationRootPath, CurrentFileSystem);
2556 if (!NT_SUCCESS(Status))
2557 {
2558 DPRINT("ChkdskPartition() failed with status 0x%08lx\n", Status);
2559 sprintf(Buffer, "Setup failed to verify the selected partition.\n"
2560 "(Status 0x%08lx).\n", Status);
2561
2562 PopupError(Buffer,
2563 MUIGetString(STRING_REBOOTCOMPUTER),
2564 Ir, POPUP_WAIT_ENTER);
2565
2566 return QUIT_PAGE;
2567 }
2568
2569 return INSTALL_DIRECTORY_PAGE;
2570 }
2571 }
2572
2573
2574 static PAGE_NUMBER
2575 InstallDirectoryPage1(PWCHAR InstallDir,
2576 PDISKENTRY DiskEntry,
2577 PPARTENTRY PartEntry)
2578 {
2579 WCHAR PathBuffer[MAX_PATH];
2580
2581 /* Create 'InstallPath' string */
2582 RtlFreeUnicodeString(&InstallPath);
2583 RtlCreateUnicodeString(&InstallPath,
2584 InstallDir);
2585
2586 /* Create 'DestinationPath' string */
2587 RtlFreeUnicodeString(&DestinationPath);
2588 wcscpy(PathBuffer, DestinationRootPath.Buffer);
2589
2590 if (InstallDir[0] != L'\\')
2591 wcscat(PathBuffer, L"\\");
2592
2593 wcscat(PathBuffer, InstallDir);
2594 RtlCreateUnicodeString(&DestinationPath, PathBuffer);
2595
2596 /* Create 'DestinationArcPath' */
2597 RtlFreeUnicodeString(&DestinationArcPath);
2598 swprintf(PathBuffer,
2599 L"multi(0)disk(0)rdisk(%lu)partition(%lu)",
2600 DiskEntry->BiosDiskNumber,
2601 PartEntry->PartitionNumber);
2602
2603 if (InstallDir[0] != L'\\')
2604 wcscat(PathBuffer, L"\\");
2605
2606 wcscat(PathBuffer, InstallDir);
2607 RtlCreateUnicodeString(&DestinationArcPath, PathBuffer);
2608
2609 return PREPARE_COPY_PAGE;
2610 }
2611
2612
2613 static PAGE_NUMBER
2614 InstallDirectoryPage(PINPUT_RECORD Ir)
2615 {
2616 PDISKENTRY DiskEntry;
2617 PPARTENTRY PartEntry;
2618 WCHAR InstallDir[51];
2619 ULONG Length;
2620
2621 if (PartitionList == NULL ||
2622 PartitionList->CurrentDisk == NULL ||
2623 PartitionList->CurrentPartition == NULL)
2624 {
2625 /* FIXME: show an error dialog */
2626 return QUIT_PAGE;
2627 }
2628
2629 DiskEntry = PartitionList->CurrentDisk;
2630 PartEntry = PartitionList->CurrentPartition;
2631
2632 if (IsUnattendedSetup)
2633 wcscpy(InstallDir, UnattendInstallationDirectory);
2634 else
2635 wcscpy(InstallDir, L"\\ReactOS");
2636
2637 Length = wcslen(InstallDir);
2638 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
2639 MUIDisplayPage(INSTALL_DIRECTORY_PAGE);
2640
2641 if (IsUnattendedSetup)
2642 {
2643 return InstallDirectoryPage1(InstallDir,
2644 DiskEntry,
2645 PartEntry);
2646 }
2647
2648 while (TRUE)
2649 {
2650 CONSOLE_ConInKey(Ir);
2651
2652 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2653 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
2654 {
2655 if (ConfirmQuit(Ir) == TRUE)
2656 return QUIT_PAGE;
2657
2658 break;
2659 }
2660 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2661 {
2662 return InstallDirectoryPage1(InstallDir,
2663 DiskEntry,
2664 PartEntry);
2665 }
2666 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x08) /* BACKSPACE */
2667 {
2668 if (Length > 0)
2669 {
2670 Length--;
2671 InstallDir[Length] = 0;
2672 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
2673 }
2674 }
2675 else if (isprint(Ir->Event.KeyEvent.uChar.AsciiChar))
2676 {
2677 if (Length < 50)
2678 {
2679 InstallDir[Length] = (WCHAR)Ir->Event.KeyEvent.uChar.AsciiChar;
2680 Length++;
2681 InstallDir[Length] = 0;
2682 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
2683 }
2684 }
2685 }
2686
2687 return INSTALL_DIRECTORY_PAGE;
2688 }
2689
2690
2691 static BOOLEAN
2692 AddSectionToCopyQueueCab(HINF InfFile,
2693 PWCHAR SectionName,
2694 PWCHAR SourceCabinet,
2695 PCUNICODE_STRING DestinationPath,
2696 PINPUT_RECORD Ir)
2697 {
2698 INFCONTEXT FilesContext;
2699 INFCONTEXT DirContext;
2700 PWCHAR FileKeyName;
2701 PWCHAR FileKeyValue;
2702 PWCHAR DirKeyValue;
2703 PWCHAR TargetFileName;
2704
2705 /* Search for the SectionName section */
2706 if (!SetupFindFirstLineW(InfFile, SectionName, NULL, &FilesContext))
2707 {
2708 char Buffer[128];
2709 sprintf(Buffer, MUIGetString(STRING_TXTSETUPFAILED), SectionName);
2710 PopupError(Buffer, MUIGetString(STRING_REBOOTCOMPUTER), Ir, POPUP_WAIT_ENTER);
2711 return FALSE;
2712 }
2713
2714 /*
2715 * Enumerate the files in the section
2716 * and add them to the file queue.
2717 */
2718 do
2719 {
2720 /* Get source file name and target directory id */
2721 if (!INF_GetData(&FilesContext, &FileKeyName, &FileKeyValue))
2722 {
2723 /* FIXME: Handle error! */
2724 DPRINT1("INF_GetData() failed\n");
2725 break;
2726 }
2727
2728 /* Get optional target file name */
2729 if (!INF_GetDataField(&FilesContext, 2, &TargetFileName))
2730 TargetFileName = NULL;
2731
2732 DPRINT("FileKeyName: '%S' FileKeyValue: '%S'\n", FileKeyName, FileKeyValue);
2733
2734 /* Lookup target directory */
2735 if (!SetupFindFirstLineW(InfFile, L"Directories", FileKeyValue, &DirContext))
2736 {
2737 /* FIXME: Handle error! */
2738 DPRINT1("SetupFindFirstLine() failed\n");
2739 break;
2740 }
2741
2742 if (!INF_GetData(&DirContext, NULL, &DirKeyValue))
2743 {
2744 /* FIXME: Handle error! */
2745 DPRINT1("INF_GetData() failed\n");
2746 break;
2747 }
2748
2749 if (!SetupQueueCopy(SetupFileQueue,
2750 SourceCabinet,
2751 SourceRootPath.Buffer,
2752 SourceRootDir.Buffer,
2753 FileKeyName,
2754 DirKeyValue,
2755 TargetFileName))
2756 {
2757 /* FIXME: Handle error! */
2758 DPRINT1("SetupQueueCopy() failed\n");
2759 }
2760 } while (SetupFindNextLine(&FilesContext, &FilesContext));
2761
2762 return TRUE;
2763 }
2764
2765
2766 static BOOLEAN
2767 AddSectionToCopyQueue(HINF InfFile,
2768 PWCHAR SectionName,
2769 PWCHAR SourceCabinet,
2770 PCUNICODE_STRING DestinationPath,
2771 PINPUT_RECORD Ir)
2772 {
2773 INFCONTEXT FilesContext;
2774 INFCONTEXT DirContext;
2775 PWCHAR FileKeyName;
2776 PWCHAR FileKeyValue;
2777 PWCHAR DirKeyValue;
2778 PWCHAR TargetFileName;
2779 WCHAR CompleteOrigFileName[512];
2780
2781 if (SourceCabinet)
2782 return AddSectionToCopyQueueCab(InfFile, L"SourceFiles", SourceCabinet, DestinationPath, Ir);
2783
2784 /* Search for the SectionName section */
2785 if (!SetupFindFirstLineW(InfFile, SectionName, NULL, &FilesContext))
2786 {
2787 char Buffer[128];
2788 sprintf(Buffer, MUIGetString(STRING_TXTSETUPFAILED), SectionName);
2789 PopupError(Buffer, MUIGetString(STRING_REBOOTCOMPUTER), Ir, POPUP_WAIT_ENTER);
2790 return FALSE;
2791 }
2792
2793 /*
2794 * Enumerate the files in the section
2795 * and add them to the file queue.
2796 */
2797 do
2798 {
2799 /* Get source file name and target directory id */
2800 if (!INF_GetData(&FilesContext, &FileKeyName, &FileKeyValue))
2801 {
2802 /* FIXME: Handle error! */
2803 DPRINT1("INF_GetData() failed\n");
2804 break;
2805 }
2806
2807 /* Get target directory id */
2808 if (!INF_GetDataField(&FilesContext, 13, &FileKeyValue))
2809 {
2810 /* FIXME: Handle error! */
2811 DPRINT1("INF_GetData() failed\n");
2812 break;
2813 }
2814
2815 /* Get optional target file name */
2816 if (!INF_GetDataField(&FilesContext, 11, &TargetFileName))
2817 TargetFileName = NULL;
2818 else if (!*TargetFileName)
2819 TargetFileName = NULL;
2820
2821 DPRINT("FileKeyName: '%S' FileKeyValue: '%S'\n", FileKeyName, FileKeyValue);
2822
2823 /* Lookup target directory */
2824 if (!SetupFindFirstLineW(InfFile, L"Directories", FileKeyValue, &DirContext))
2825 {
2826 /* FIXME: Handle error! */
2827 DPRINT1("SetupFindFirstLine() failed\n");
2828 break;
2829 }
2830
2831 if (!INF_GetData(&DirContext, NULL, &DirKeyValue))
2832 {
2833 /* FIXME: Handle error! */
2834 DPRINT1("INF_GetData() failed\n");
2835 break;
2836 }
2837
2838 wcscpy(CompleteOrigFileName, SourceRootDir.Buffer);
2839 wcscat(CompleteOrigFileName, L"\\");
2840 wcscat(CompleteOrigFileName, DirKeyValue);
2841
2842 if (!SetupQueueCopy(SetupFileQueue,
2843 SourceCabinet,
2844 SourceRootPath.Buffer,
2845 CompleteOrigFileName,
2846 FileKeyName,
2847 DirKeyValue,
2848 TargetFileName))
2849 {
2850 /* FIXME: Handle error! */
2851 DPRINT1("SetupQueueCopy() failed\n");
2852 }
2853 } while (SetupFindNextLine(&FilesContext, &FilesContext));
2854
2855 return TRUE;
2856 }
2857
2858
2859 static BOOLEAN
2860 PrepareCopyPageInfFile(HINF InfFile,
2861 PWCHAR SourceCabinet,
2862 PINPUT_RECORD Ir)
2863 {
2864 WCHAR PathBuffer[MAX_PATH];
2865 INFCONTEXT DirContext;
2866 PWCHAR AdditionalSectionName = NULL;
2867 PWCHAR KeyValue;
2868 ULONG Length;
2869 NTSTATUS Status;
2870
2871 /* Add common files */
2872 if (!AddSectionToCopyQueue(InfFile, L"SourceDisksFiles", SourceCabinet, &DestinationPath, Ir))
2873 return FALSE;
2874
2875 /* Add specific files depending of computer type */
2876 if (SourceCabinet == NULL)
2877 {
2878 if (!ProcessComputerFiles(InfFile, ComputerList, &AdditionalSectionName))
2879 return FALSE;
2880
2881 if (AdditionalSectionName)
2882 {
2883 if (!AddSectionToCopyQueue(InfFile, AdditionalSectionName, SourceCabinet, &DestinationPath, Ir))
2884 return FALSE;
2885 }
2886 }
2887
2888 /* Create directories */
2889
2890 /*
2891 * FIXME:
2892 * Install directories like '\reactos\test' are not handled yet.
2893 */
2894
2895 /* Get destination path */
2896 wcscpy(PathBuffer, DestinationPath.Buffer);
2897
2898 /* Remove trailing backslash */
2899 Length = wcslen(PathBuffer);
2900 if ((Length > 0) && (PathBuffer[Length - 1] == '\\'))
2901 {
2902 PathBuffer[Length - 1] = 0;
2903 }
2904
2905 /* Create the install directory */
2906 Status = SetupCreateDirectory(PathBuffer);
2907 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION)
2908 {
2909 DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer, Status);
2910 MUIDisplayError(ERROR_CREATE_INSTALL_DIR, Ir, POPUP_WAIT_ENTER);
2911 return FALSE;
2912 }
2913
2914 /* Search for the 'Directories' section */
2915 if (!SetupFindFirstLineW(InfFile, L"Directories", NULL, &DirContext))
2916 {
2917 if (SourceCabinet)
2918 {
2919 MUIDisplayError(ERROR_CABINET_SECTION, Ir, POPUP_WAIT_ENTER);
2920 }
2921 else
2922 {
2923 MUIDisplayError(ERROR_TXTSETUP_SECTION, Ir, POPUP_WAIT_ENTER);
2924 }
2925
2926 return FALSE;
2927 }
2928
2929 /* Enumerate the directory values and create the subdirectories */
2930 do
2931 {
2932 if (!INF_GetData(&DirContext, NULL, &KeyValue))
2933 {
2934 DPRINT1("break\n");
2935 break;
2936 }
2937
2938 if (KeyValue[0] == L'\\' && KeyValue[1] != 0)
2939 {
2940 DPRINT("Absolute Path: '%S'\n", KeyValue);
2941
2942 wcscpy(PathBuffer, DestinationRootPath.Buffer);
2943 wcscat(PathBuffer, KeyValue);
2944
2945 DPRINT("FullPath: '%S'\n", PathBuffer);
2946 }
2947 else if (KeyValue[0] != L'\\')
2948 {
2949 DPRINT("RelativePath: '%S'\n", KeyValue);
2950 wcscpy(PathBuffer, DestinationPath.Buffer);
2951 wcscat(PathBuffer, L"\\");
2952 wcscat(PathBuffer, KeyValue);
2953
2954 DPRINT("FullPath: '%S'\n", PathBuffer);
2955
2956 Status = SetupCreateDirectory(PathBuffer);
2957 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION)
2958 {
2959 DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer, Status);
2960 MUIDisplayError(ERROR_CREATE_DIR, Ir, POPUP_WAIT_ENTER);
2961 return FALSE;
2962 }
2963 }
2964 } while (SetupFindNextLine (&DirContext, &DirContext));
2965
2966 return TRUE;
2967 }
2968
2969
2970 static PAGE_NUMBER
2971 PrepareCopyPage(PINPUT_RECORD Ir)
2972 {
2973 HINF InfHandle;
2974 WCHAR PathBuffer[MAX_PATH];
2975 INFCONTEXT CabinetsContext;
2976 ULONG InfFileSize;
2977 PWCHAR KeyValue;
2978 UINT ErrorLine;
2979 PVOID InfFileData;
2980
2981 MUIDisplayPage(PREPARE_COPY_PAGE);
2982
2983 /* Create the file queue */
2984 SetupFileQueue = SetupOpenFileQueue();
2985 if (SetupFileQueue == NULL)
2986 {
2987 MUIDisplayError(ERROR_COPY_QUEUE, Ir, POPUP_WAIT_ENTER);
2988 return(QUIT_PAGE);
2989 }
2990
2991 if (!PrepareCopyPageInfFile(SetupInf, NULL, Ir))
2992 {
2993 return QUIT_PAGE;
2994 }
2995
2996 /* Search for the 'Cabinets' section */
2997 if (!SetupFindFirstLineW(SetupInf, L"Cabinets", NULL, &CabinetsContext))
2998 {
2999 return FILE_COPY_PAGE;
3000 }
3001
3002 /*
3003 * Enumerate the directory values in the 'Cabinets'
3004 * section and parse their inf files.
3005 */
3006 do
3007 {
3008 if (!INF_GetData(&CabinetsContext, NULL, &KeyValue))
3009 break;
3010
3011 wcscpy(PathBuffer, SourcePath.Buffer);
3012 wcscat(PathBuffer, L"\\");
3013 wcscat(PathBuffer, KeyValue);
3014
3015 #ifdef __REACTOS__
3016 CabinetInitialize();
3017 CabinetSetEventHandlers(NULL, NULL, NULL);
3018 CabinetSetCabinetName(PathBuffer);
3019
3020 if (CabinetOpen() == CAB_STATUS_SUCCESS)
3021 {
3022 DPRINT("Cabinet %S\n", CabinetGetCabinetName());
3023
3024 InfFileData = CabinetGetCabinetReservedArea(&InfFileSize);
3025 if (InfFileData == NULL)
3026 {
3027 MUIDisplayError(ERROR_CABINET_SCRIPT, Ir, POPUP_WAIT_ENTER);
3028 return QUIT_PAGE;
3029 }
3030 }
3031 else
3032 {
3033 DPRINT("Cannot open cabinet: %S.\n", CabinetGetCabinetName());
3034 MUIDisplayError(ERROR_CABINET_MISSING, Ir, POPUP_WAIT_ENTER);
3035 return QUIT_PAGE;
3036 }
3037
3038 InfHandle = INF_OpenBufferedFileA((CHAR*) InfFileData,
3039 InfFileSize,
3040 (const CHAR*) NULL,
3041 INF_STYLE_WIN4,
3042 LanguageId,
3043 &ErrorLine);
3044
3045 if (InfHandle == INVALID_HANDLE_VALUE)
3046 {
3047 MUIDisplayError(ERROR_INVALID_CABINET_INF, Ir, POPUP_WAIT_ENTER);
3048 return QUIT_PAGE;
3049 }
3050
3051 CabinetCleanup();
3052
3053 if (!PrepareCopyPageInfFile(InfHandle, KeyValue, Ir))
3054 {
3055 return QUIT_PAGE;
3056 }
3057 #endif
3058 } while (SetupFindNextLine(&CabinetsContext, &CabinetsContext));
3059
3060 return FILE_COPY_PAGE;
3061 }
3062
3063
3064 VOID
3065 NTAPI
3066 SetupUpdateMemoryInfo(IN PCOPYCONTEXT CopyContext,
3067 IN BOOLEAN First)
3068 {
3069 SYSTEM_PERFORMANCE_INFORMATION PerfInfo;
3070
3071 /* Get the memory information from the system */
3072 NtQuerySystemInformation(SystemPerformanceInformation,
3073 &PerfInfo,
3074 sizeof(PerfInfo),
3075 NULL);
3076
3077 /* Check if this is initial setup */
3078 if (First)
3079 {
3080 /* Set maximum limits to be total RAM pages */
3081 ProgressSetStepCount(CopyContext->MemoryBars[0], PerfInfo.CommitLimit);
3082 ProgressSetStepCount(CopyContext->MemoryBars[1], PerfInfo.CommitLimit);
3083 ProgressSetStepCount(CopyContext->MemoryBars[2], PerfInfo.CommitLimit);
3084 }
3085
3086 /* Set current values */
3087 ProgressSetStep(CopyContext->MemoryBars[0], PerfInfo.PagedPoolPages + PerfInfo.NonPagedPoolPages);
3088 ProgressSetStep(CopyContext->MemoryBars[1], PerfInfo.ResidentSystemCachePage);
3089 ProgressSetStep(CopyContext->MemoryBars[2], PerfInfo.AvailablePages);
3090 }
3091
3092
3093 static UINT
3094 CALLBACK
3095 FileCopyCallback(PVOID Context,
3096 UINT Notification,
3097 UINT_PTR Param1,
3098 UINT_PTR Param2)
3099 {
3100 PCOPYCONTEXT CopyContext;
3101
3102 CopyContext = (PCOPYCONTEXT)Context;
3103
3104 switch (Notification)
3105 {
3106 case SPFILENOTIFY_STARTSUBQUEUE:
3107 CopyContext->TotalOperations = (ULONG)Param2;
3108 ProgressSetStepCount(CopyContext->ProgressBar,
3109 CopyContext->TotalOperations);
3110 SetupUpdateMemoryInfo(CopyContext, TRUE);
3111 break;
3112
3113 case SPFILENOTIFY_STARTCOPY:
3114 /* Display copy message */
3115 CONSOLE_SetStatusText(MUIGetString(STRING_COPYING), (PWSTR)Param1);
3116 SetupUpdateMemoryInfo(CopyContext, FALSE);
3117 break;
3118
3119 case SPFILENOTIFY_ENDCOPY:
3120 CopyContext->CompletedOperations++;
3121
3122 /* SYSREG checkpoint */
3123 if (CopyContext->TotalOperations >> 1 == CopyContext->CompletedOperations)
3124 DPRINT1("CHECKPOINT:HALF_COPIED\n");
3125
3126 ProgressNextStep(CopyContext->ProgressBar);
3127 SetupUpdateMemoryInfo(CopyContext, FALSE);
3128 break;
3129 }
3130
3131 return 0;
3132 }
3133
3134
3135 static
3136 PAGE_NUMBER
3137 FileCopyPage(PINPUT_RECORD Ir)
3138 {
3139 COPYCONTEXT CopyContext;
3140 unsigned int mem_bar_width;
3141
3142 MUIDisplayPage(FILE_COPY_PAGE);
3143
3144 /* Create context for the copy process */
3145 CopyContext.DestinationRootPath = DestinationRootPath.Buffer;
3146 CopyContext.InstallPath = InstallPath.Buffer;
3147 CopyContext.TotalOperations = 0;
3148 CopyContext.CompletedOperations = 0;
3149
3150 /* Create the progress bar as well */
3151 CopyContext.ProgressBar = CreateProgressBar(13,
3152 26,
3153 xScreen - 13,
3154 yScreen - 20,
3155 10,
3156 24,
3157 TRUE,
3158 MUIGetString(STRING_SETUPCOPYINGFILES));
3159
3160 // fit memory bars to screen width, distribute them uniform
3161 mem_bar_width = (xScreen - 26) / 5;
3162 mem_bar_width -= mem_bar_width % 2; // make even
3163 /* ATTENTION: The following progress bars are debug stuff, which should not be translated!! */
3164 /* Create the paged pool progress bar */
3165 CopyContext.MemoryBars[0] = CreateProgressBar(13,
3166 40,
3167 13 + mem_bar_width,
3168 43,
3169 13,
3170 44,
3171 FALSE,
3172 "Kernel Pool");
3173
3174 /* Create the non paged pool progress bar */
3175 CopyContext.MemoryBars[1] = CreateProgressBar((xScreen / 2)- (mem_bar_width / 2),
3176 40,
3177 (xScreen / 2) + (mem_bar_width / 2),
3178 43,
3179 (xScreen / 2)- (mem_bar_width / 2),
3180 44,
3181 FALSE,
3182 "Kernel Cache");
3183
3184 /* Create the global memory progress bar */
3185 CopyContext.MemoryBars[2] = CreateProgressBar(xScreen - 13 - mem_bar_width,
3186 40,
3187 xScreen - 13,
3188 43,
3189 xScreen - 13 - mem_bar_width,
3190 44,
3191 FALSE,
3192 "Free Memory");
3193
3194 /* Do the file copying */
3195 SetupCommitFileQueueW(NULL,
3196 SetupFileQueue,
3197 FileCopyCallback,
3198 &CopyContext);
3199
3200 /* If we get here, we're done, so cleanup the queue and progress bar */
3201 SetupCloseFileQueue(SetupFileQueue);
3202 DestroyProgressBar(CopyContext.ProgressBar);
3203 DestroyProgressBar(CopyContext.MemoryBars[0]);
3204 DestroyProgressBar(CopyContext.MemoryBars[1]);
3205 DestroyProgressBar(CopyContext.MemoryBars[2]);
3206
3207 /* Go display the next page */
3208 return REGISTRY_PAGE;
3209 }
3210
3211
3212 static PAGE_NUMBER
3213 RegistryPage(PINPUT_RECORD Ir)
3214 {
3215 INFCONTEXT InfContext;
3216 PWSTR Action;
3217 PWSTR File;
3218 PWSTR Section;
3219 BOOLEAN Delete;
3220 NTSTATUS Status;
3221
3222 MUIDisplayPage(REGISTRY_PAGE);
3223
3224 if (RepairUpdateFlag)
3225 {
3226 return SUCCESS_PAGE;
3227 }
3228
3229 if (!SetInstallPathValue(&DestinationPath))
3230 {
3231 DPRINT("SetInstallPathValue() failed\n");
3232 MUIDisplayError(ERROR_INITIALIZE_REGISTRY, Ir, POPUP_WAIT_ENTER);
3233 return QUIT_PAGE;
3234 }
3235
3236 /* Create the default hives */
3237 #ifdef __REACTOS__
3238 Status = NtInitializeRegistry(CM_BOOT_FLAG_SETUP);
3239 if (!NT_SUCCESS(Status))
3240 {
3241 DPRINT("NtInitializeRegistry() failed (Status %lx)\n", Status);
3242 MUIDisplayError(ERROR_CREATE_HIVE, Ir, POPUP_WAIT_ENTER);
3243 return QUIT_PAGE;
3244 }
3245 #else
3246 RegInitializeRegistry();
3247 #endif
3248
3249 /* Update registry */
3250 CONSOLE_SetStatusText(MUIGetString(STRING_REGHIVEUPDATE));
3251
3252 if (!SetupFindFirstLineW(SetupInf, L"HiveInfs.Install", NULL, &InfContext))
3253 {
3254 DPRINT1("SetupFindFirstLine() failed\n");
3255 MUIDisplayError(ERROR_FIND_REGISTRY, Ir, POPUP_WAIT_ENTER);
3256 return QUIT_PAGE;
3257 }
3258
3259 do
3260 {
3261 INF_GetDataField (&InfContext, 0, &Action);
3262 INF_GetDataField (&InfContext, 1, &File);
3263 INF_GetDataField (&InfContext, 2, &Section);
3264
3265 DPRINT("Action: %S File: %S Section %S\n", Action, File, Section);
3266
3267 if (Action == NULL)
3268 break; // Hackfix
3269
3270 if (!_wcsicmp (Action, L"AddReg"))
3271 {
3272 Delete = FALSE;
3273 }
3274 else if (!_wcsicmp (Action, L"DelReg"))
3275 {
3276 Delete = TRUE;
3277 }
3278 else
3279 {
3280 continue;
3281 }
3282
3283 CONSOLE_SetStatusText(MUIGetString(STRING_IMPORTFILE), File);
3284
3285 if (!ImportRegistryFile(File, Section, LanguageId, Delete))
3286 {
3287 DPRINT("Importing %S failed\n", File);
3288
3289 MUIDisplayError(ERROR_IMPORT_HIVE, Ir, POPUP_WAIT_ENTER);
3290 return QUIT_PAGE;
3291 }
3292 } while (SetupFindNextLine(&InfContext, &InfContext));
3293
3294 /* Update display registry settings */
3295 CONSOLE_SetStatusText(MUIGetString(STRING_DISPLAYETTINGSUPDATE));
3296 if (!ProcessDisplayRegistry(SetupInf, DisplayList))
3297 {
3298 MUIDisplayError(ERROR_UPDATE_DISPLAY_SETTINGS, Ir, POPUP_WAIT_ENTER);
3299 return QUIT_PAGE;
3300 }
3301
3302 /* Set the locale */
3303 CONSOLE_SetStatusText(MUIGetString(STRING_LOCALESETTINGSUPDATE));
3304 if (!ProcessLocaleRegistry(LanguageList))
3305 {
3306 MUIDisplayError(ERROR_UPDATE_LOCALESETTINGS, Ir, POPUP_WAIT_ENTER);
3307 return QUIT_PAGE;
3308 }
3309
3310 /* Add keyboard layouts */
3311 CONSOLE_SetStatusText(MUIGetString(STRING_ADDKBLAYOUTS));
3312 if (!AddKeyboardLayouts())
3313 {
3314 MUIDisplayError(ERROR_ADDING_KBLAYOUTS, Ir, POPUP_WAIT_ENTER);
3315 return QUIT_PAGE;
3316 }
3317
3318 /* Set GeoID */
3319
3320 if (!SetGeoID(MUIGetGeoID()))
3321 {
3322 MUIDisplayError(ERROR_UPDATE_GEOID, Ir, POPUP_WAIT_ENTER);
3323 return QUIT_PAGE;
3324 }
3325
3326 if (!IsUnattendedSetup)
3327 {
3328 /* Update keyboard layout settings */
3329 CONSOLE_SetStatusText(MUIGetString(STRING_KEYBOARDSETTINGSUPDATE));
3330 if (!ProcessKeyboardLayoutRegistry(LayoutList))
3331 {
3332 MUIDisplayError(ERROR_UPDATE_KBSETTINGS, Ir, POPUP_WAIT_ENTER);
3333 return QUIT_PAGE;
3334 }
3335 }
3336
3337 /* Add codepage information to registry */
3338 CONSOLE_SetStatusText(MUIGetString(STRING_CODEPAGEINFOUPDATE));
3339 if (!AddCodePage())
3340 {
3341 MUIDisplayError(ERROR_ADDING_CODEPAGE, Ir, POPUP_WAIT_ENTER);
3342 return QUIT_PAGE;
3343 }
3344
3345 /* Set the default pagefile entry */
3346 SetDefaultPagefile(DestinationDriveLetter);
3347
3348 /* Update the mounted devices list */
3349 SetMountedDeviceValues(PartitionList);
3350
3351 CONSOLE_SetStatusText(MUIGetString(STRING_DONE));
3352
3353 return BOOT_LOADER_PAGE;
3354 }
3355
3356
3357 static PAGE_NUMBER
3358 BootLoaderPage(PINPUT_RECORD Ir)
3359 {
3360 UCHAR PartitionType;
3361 BOOLEAN InstallOnFloppy;
3362 USHORT Line = 12;
3363 WCHAR PathBuffer[MAX_PATH];
3364
3365 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
3366
3367 /* Find or set the active partition */
3368 CheckActiveBootPartition(PartitionList);
3369
3370 /* Update the partition table because we may have changed the active partition */
3371 if (WritePartitionsToDisk(PartitionList) == FALSE)
3372 {
3373 DPRINT("WritePartitionsToDisk() failed\n");
3374 MUIDisplayError(ERROR_WRITE_PTABLE, Ir, POPUP_WAIT_ENTER);
3375 return QUIT_PAGE;
3376 }
3377
3378 RtlFreeUnicodeString(&SystemRootPath);
3379 swprintf(PathBuffer,
3380 L"\\Device\\Harddisk%lu\\Partition%lu",
3381 PartitionList->ActiveBootDisk->DiskNumber,
3382 PartitionList->ActiveBootPartition->PartitionNumber);
3383 RtlCreateUnicodeString(&SystemRootPath,
3384 PathBuffer);
3385 DPRINT("SystemRootPath: %wZ\n", &SystemRootPath);
3386
3387 PartitionType = PartitionList->ActiveBootPartition->PartitionType;
3388
3389 if (IsUnattendedSetup)
3390 {
3391 if (UnattendMBRInstallType == 0) /* skip MBR installation */
3392 {
3393 return SUCCESS_PAGE;
3394 }
3395 else if (UnattendMBRInstallType == 1) /* install on floppy */
3396 {
3397 return BOOT_LOADER_FLOPPY_PAGE;
3398 }
3399 }
3400
3401 if (PartitionType == PARTITION_ENTRY_UNUSED)
3402 {
3403 DPRINT("Error: active partition invalid (unused)\n");
3404 InstallOnFloppy = TRUE;
3405 }
3406 else if (PartitionType == 0x0A)
3407 {
3408 /* OS/2 boot manager partition */
3409 DPRINT("Found OS/2 boot manager partition\n");
3410 InstallOnFloppy = TRUE;
3411 }
3412 else if (PartitionType == 0x83)
3413 {
3414 /* Linux ext2 partition */
3415 DPRINT("Found Linux ext2 partition\n");
3416 InstallOnFloppy = TRUE;
3417 }
3418 else if (PartitionType == PARTITION_IFS)
3419 {
3420 /* NTFS partition */
3421 DPRINT("Found NTFS partition\n");
3422 InstallOnFloppy = TRUE;
3423 }
3424 else if ((PartitionType == PARTITION_FAT_12) ||
3425 (PartitionType == PARTITION_FAT_16) ||
3426 (PartitionType == PARTITION_HUGE) ||
3427 (PartitionType == PARTITION_XINT13) ||
3428 (PartitionType == PARTITION_FAT32) ||
3429 (PartitionType == PARTITION_FAT32_XINT13))
3430 {
3431 DPRINT("Found FAT partition\n");
3432 InstallOnFloppy = FALSE;
3433 }
3434 else
3435 {
3436 /* Unknown partition */
3437 DPRINT("Unknown partition found\n");
3438 InstallOnFloppy = TRUE;
3439 }
3440
3441 if (InstallOnFloppy == TRUE)
3442 {
3443 return BOOT_LOADER_FLOPPY_PAGE;
3444 }
3445
3446 /* Unattended install on hdd? */
3447 if (IsUnattendedSetup && UnattendMBRInstallType == 2)
3448 {
3449 return BOOT_LOADER_HARDDISK_MBR_PAGE;
3450 }
3451
3452 MUIDisplayPage(BOOT_LOADER_PAGE);
3453 CONSOLE_InvertTextXY(8, Line, 60, 1);
3454
3455 while (TRUE)
3456 {
3457 CONSOLE_ConInKey(Ir);
3458
3459 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3460 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
3461 {
3462 CONSOLE_NormalTextXY(8, Line, 60, 1);
3463
3464 Line++;
3465 if (Line<12)
3466 Line=15;
3467
3468 if (Line>15)
3469 Line=12;
3470
3471 CONSOLE_InvertTextXY(8, Line, 60, 1);
3472 }
3473 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3474 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
3475 {
3476 CONSOLE_NormalTextXY(8, Line, 60, 1);
3477
3478 Line--;
3479 if (Line<12)
3480 Line=15;
3481
3482 if (Line>15)
3483 Line=12;
3484
3485 CONSOLE_InvertTextXY(8, Line, 60, 1);
3486 }
3487 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3488 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
3489 {
3490 if (ConfirmQuit(Ir) == TRUE)
3491 return QUIT_PAGE;
3492
3493 break;
3494 }
3495 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
3496 {
3497 if (Line == 12)
3498 {
3499 return BOOT_LOADER_HARDDISK_MBR_PAGE;
3500 }
3501 else if (Line == 13)
3502 {
3503 return BOOT_LOADER_HARDDISK_VBR_PAGE;
3504 }
3505 else if (Line == 14)
3506 {
3507 return BOOT_LOADER_FLOPPY_PAGE;
3508 }
3509 else if (Line == 15)
3510 {
3511 return SUCCESS_PAGE;
3512 }
3513
3514 return BOOT_LOADER_PAGE;
3515 }
3516 }
3517
3518 return BOOT_LOADER_PAGE;
3519 }
3520
3521
3522 static PAGE_NUMBER
3523 BootLoaderFloppyPage(PINPUT_RECORD Ir)
3524 {
3525 NTSTATUS Status;
3526
3527 MUIDisplayPage(BOOT_LOADER_FLOPPY_PAGE);
3528
3529 // SetStatusText(" Please wait...");
3530
3531 while (TRUE)
3532 {
3533 CONSOLE_ConInKey(Ir);
3534
3535 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3536 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
3537 {
3538 if (ConfirmQuit(Ir) == TRUE)
3539 return QUIT_PAGE;
3540
3541 break;
3542 }
3543 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
3544 {
3545 if (DoesFileExist(L"\\Device\\Floppy0", L"\\") == FALSE)
3546 {
3547 MUIDisplayError(ERROR_NO_FLOPPY, Ir, POPUP_WAIT_ENTER);
3548 return BOOT_LOADER_FLOPPY_PAGE;
3549 }
3550
3551 Status = InstallFatBootcodeToFloppy(&SourceRootPath, &DestinationArcPath);
3552 if (!NT_SUCCESS(Status))
3553 {
3554 /* Print error message */
3555 return BOOT_LOADER_FLOPPY_PAGE;
3556 }
3557
3558 return SUCCESS_PAGE;
3559 }
3560 }
3561
3562 return BOOT_LOADER_FLOPPY_PAGE;
3563 }
3564
3565 static PAGE_NUMBER
3566 BootLoaderHarddiskVbrPage(PINPUT_RECORD Ir)
3567 {
3568 UCHAR PartitionType;
3569 NTSTATUS Status;
3570
3571 PartitionType = PartitionList->ActiveBootPartition->PartitionType;
3572
3573 Status = InstallVBRToPartition(&SystemRootPath,
3574 &SourceRootPath,
3575 &DestinationArcPath,
3576 PartitionType);
3577 if (!NT_SUCCESS(Status))
3578 {
3579 MUIDisplayError(ERROR_WRITE_BOOT, Ir, POPUP_WAIT_ENTER);
3580 return QUIT_PAGE;
3581 }
3582
3583 return SUCCESS_PAGE;
3584 }
3585
3586 static PAGE_NUMBER
3587 BootLoaderHarddiskMbrPage(PINPUT_RECORD Ir)
3588 {
3589 UCHAR PartitionType;
3590 NTSTATUS Status;
3591 WCHAR DestinationDevicePathBuffer[MAX_PATH];
3592 WCHAR SourceMbrPathBuffer[MAX_PATH];
3593
3594 /* Step 1: Write the VBR */
3595 PartitionType = PartitionList->ActiveBootPartition->PartitionType;
3596
3597 Status = InstallVBRToPartition(&SystemRootPath,
3598 &SourceRootPath,
3599 &DestinationArcPath,
3600 PartitionType);
3601 if (!NT_SUCCESS(Status))
3602 {
3603 MUIDisplayError(ERROR_WRITE_BOOT, Ir, POPUP_WAIT_ENTER);
3604 return QUIT_PAGE;
3605 }
3606
3607 /* Step 2: Write the MBR */
3608 swprintf(DestinationDevicePathBuffer,
3609 L"\\Device\\Harddisk%d\\Partition0",
3610 PartitionList->ActiveBootDisk->DiskNumber);
3611
3612 wcscpy(SourceMbrPathBuffer, SourceRootPath.Buffer);
3613 wcscat(SourceMbrPathBuffer, L"\\loader\\dosmbr.bin");
3614
3615 DPRINT("Install MBR bootcode: %S ==> %S\n",
3616 SourceMbrPathBuffer, DestinationDevicePathBuffer);
3617
3618 Status = InstallMbrBootCodeToDisk(SourceMbrPathBuffer,
3619 DestinationDevicePathBuffer);
3620 if (!NT_SUCCESS (Status))
3621 {
3622 DPRINT1("InstallMbrBootCodeToDisk() failed (Status %lx)\n",
3623 Status);
3624 MUIDisplayError(ERROR_INSTALL_BOOTCODE, Ir, POPUP_WAIT_ENTER);
3625 return QUIT_PAGE;
3626 }
3627
3628 return SUCCESS_PAGE;
3629 }
3630
3631
3632 static PAGE_NUMBER
3633 QuitPage(PINPUT_RECORD Ir)
3634 {
3635 MUIDisplayPage(QUIT_PAGE);
3636
3637 /* Destroy partition list */
3638 if (PartitionList != NULL)
3639 {
3640 DestroyPartitionList (PartitionList);
3641 PartitionList = NULL;
3642 }
3643
3644 /* Destroy filesystem list */
3645 if (FileSystemList != NULL)
3646 {
3647 DestroyFileSystemList (FileSystemList);
3648 FileSystemList = NULL;
3649 }
3650
3651 /* Destroy computer settings list */
3652 if (ComputerList != NULL)
3653 {
3654 DestroyGenericList(ComputerList, TRUE);
3655 ComputerList = NULL;
3656 }
3657
3658 /* Destroy display settings list */
3659 if (DisplayList != NULL)
3660 {
3661 DestroyGenericList(DisplayList, TRUE);
3662 DisplayList = NULL;
3663 }
3664
3665 /* Destroy keyboard settings list */
3666 if (KeyboardList != NULL)
3667 {
3668 DestroyGenericList(KeyboardList, TRUE);
3669 KeyboardList = NULL;
3670 }
3671
3672 /* Destroy keyboard layout list */
3673 if (LayoutList != NULL)
3674 {
3675 DestroyGenericList(LayoutList, TRUE);
3676 LayoutList = NULL;
3677 }
3678
3679 if (LanguageList != NULL)
3680 {
3681 DestroyGenericList(LanguageList, FALSE);
3682 LanguageList = NULL;
3683 }
3684
3685 CONSOLE_SetStatusText(MUIGetString(STRING_REBOOTCOMPUTER2));
3686
3687 while (TRUE)
3688 {
3689 CONSOLE_ConInKey(Ir);
3690
3691 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
3692 {
3693 return FLUSH_PAGE;
3694 }
3695 }
3696 }
3697
3698
3699 static PAGE_NUMBER
3700 SuccessPage(PINPUT_RECORD Ir)
3701 {
3702 MUIDisplayPage(SUCCESS_PAGE);
3703
3704 if (IsUnattendedSetup)
3705 {
3706 return FLUSH_PAGE;
3707 }
3708
3709 while (TRUE)
3710 {
3711 CONSOLE_ConInKey(Ir);
3712
3713 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
3714 {
3715 return FLUSH_PAGE;
3716 }
3717 }
3718 }
3719
3720
3721 static PAGE_NUMBER
3722 FlushPage(PINPUT_RECORD Ir)
3723 {
3724 MUIDisplayPage(FLUSH_PAGE);
3725 return REBOOT_PAGE;
3726 }
3727
3728
3729 DWORD WINAPI
3730 PnpEventThread(IN LPVOID lpParameter);
3731
3732 VOID
3733 RunUSetup(VOID)
3734 {
3735 INPUT_RECORD Ir;
3736 PAGE_NUMBER Page;
3737 LARGE_INTEGER Time;
3738 NTSTATUS Status;
3739
3740 NtQuerySystemTime(&Time);
3741
3742 Status = RtlCreateUserThread(NtCurrentProcess(),
3743 NULL,
3744 TRUE,
3745 0,
3746 0,
3747 0,
3748 PnpEventThread,
3749 &SetupInf,
3750 &hPnpThread,
3751 NULL);
3752 if (!NT_SUCCESS(Status))
3753 hPnpThread = INVALID_HANDLE_VALUE;
3754
3755 if (!CONSOLE_Init())
3756 {
3757 PrintString(MUIGetString(STRING_CONSOLEFAIL1));
3758 PrintString(MUIGetString(STRING_CONSOLEFAIL2));
3759 PrintString(MUIGetString(STRING_CONSOLEFAIL3));
3760
3761 /* Raise a hard error (crash the system/BSOD) */
3762 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED,
3763 0,0,0,0,0);
3764 }
3765
3766 /* Initialize global unicode strings */
3767 RtlInitUnicodeString(&SourcePath, NULL);
3768 RtlInitUnicodeString(&SourceRootPath, NULL);
3769 RtlInitUnicodeString(&SourceRootDir, NULL);
3770 RtlInitUnicodeString(&InstallPath, NULL);
3771 RtlInitUnicodeString(&DestinationPath, NULL);
3772 RtlInitUnicodeString(&DestinationArcPath, NULL);
3773 RtlInitUnicodeString(&DestinationRootPath, NULL);
3774 RtlInitUnicodeString(&SystemRootPath, NULL);
3775
3776 /* Hide the cursor */
3777 CONSOLE_SetCursorType(TRUE, FALSE);
3778
3779 Page = START_PAGE;
3780 while (Page != REBOOT_PAGE)
3781 {
3782 CONSOLE_ClearScreen();
3783 CONSOLE_Flush();
3784
3785 //CONSOLE_SetUnderlinedTextXY(4, 3, " ReactOS " KERNEL_VERSION_STR " Setup ");
3786 //CONSOLE_Flush();
3787
3788 switch (Page)
3789 {
3790 /* Start page */
3791 case START_PAGE:
3792 Page = SetupStartPage(&Ir);
3793 break;
3794
3795 /* Language page */
3796 case LANGUAGE_PAGE:
3797 Page = LanguagePage(&Ir);
3798 break;
3799
3800 /* License page */
3801 case LICENSE_PAGE:
3802 Page = LicensePage(&Ir);
3803 break;
3804
3805 /* Intro page */
3806 case INTRO_PAGE:
3807 Page = IntroPage(&Ir);
3808 break;
3809
3810 /* Install pages */
3811 case INSTALL_INTRO_PAGE:
3812 Page = InstallIntroPage(&Ir);
3813 break;
3814
3815 #if 0
3816 case SCSI_CONTROLLER_PAGE:
3817 Page = ScsiControllerPage(&Ir);
3818 break;
3819 #endif
3820
3821 #if 0
3822 case OEM_DRIVER_PAGE:
3823 Page = OemDriverPage(&Ir);
3824 break;
3825 #endif
3826
3827 case DEVICE_SETTINGS_PAGE:
3828 Page = DeviceSettingsPage(&Ir);
3829 break;
3830
3831 case COMPUTER_SETTINGS_PAGE:
3832 Page = ComputerSettingsPage(&Ir);
3833 break;
3834
3835 case DISPLAY_SETTINGS_PAGE:
3836 Page = DisplaySettingsPage(&Ir);
3837 break;
3838
3839 case KEYBOARD_SETTINGS_PAGE:
3840 Page = KeyboardSettingsPage(&Ir);
3841 break;
3842
3843 case LAYOUT_SETTINGS_PAGE:
3844 Page = LayoutSettingsPage(&Ir);
3845 break;
3846
3847 case SELECT_PARTITION_PAGE:
3848 Page = SelectPartitionPage(&Ir);
3849 break;
3850
3851 case CREATE_PARTITION_PAGE:
3852 Page = CreatePartitionPage(&Ir);
3853 break;
3854
3855 case DELETE_PARTITION_PAGE:
3856 Page = DeletePartitionPage(&Ir);
3857 break;
3858
3859 case SELECT_FILE_SYSTEM_PAGE:
3860 Page = SelectFileSystemPage(&Ir);
3861 break;
3862
3863 case FORMAT_PARTITION_PAGE:
3864 Page = (PAGE_NUMBER) FormatPartitionPage(&Ir);
3865 break;
3866
3867 case CHECK_FILE_SYSTEM_PAGE:
3868 Page = (PAGE_NUMBER) CheckFileSystemPage(&Ir);
3869 break;
3870
3871 case INSTALL_DIRECTORY_PAGE:
3872 Page = InstallDirectoryPage(&Ir);
3873 break;
3874
3875 case PREPARE_COPY_PAGE:
3876 Page = PrepareCopyPage(&Ir);
3877 break;
3878
3879 case FILE_COPY_PAGE:
3880 Page = FileCopyPage(&Ir);
3881 break;
3882
3883 case REGISTRY_PAGE:
3884 Page = RegistryPage(&Ir);
3885 break;
3886
3887 case BOOT_LOADER_PAGE:
3888 Page = BootLoaderPage(&Ir);
3889 break;
3890
3891 case BOOT_LOADER_FLOPPY_PAGE:
3892 Page = BootLoaderFloppyPage(&Ir);
3893 break;
3894
3895 case BOOT_LOADER_HARDDISK_MBR_PAGE:
3896 Page = BootLoaderHarddiskMbrPage(&Ir);
3897 break;
3898
3899 case BOOT_LOADER_HARDDISK_VBR_PAGE:
3900 Page = BootLoaderHarddiskVbrPage(&Ir);
3901 break;
3902
3903 /* Repair pages */
3904 case REPAIR_INTRO_PAGE:
3905 Page = RepairIntroPage(&Ir);
3906 break;
3907
3908 case SUCCESS_PAGE:
3909 Page = SuccessPage(&Ir);
3910 break;
3911
3912 case FLUSH_PAGE:
3913 Page = FlushPage(&Ir);
3914 break;
3915
3916 case QUIT_PAGE:
3917 Page = QuitPage(&Ir);
3918 break;
3919
3920 case REBOOT_PAGE:
3921 break;
3922 }
3923 }
3924
3925 FreeConsole();
3926
3927 /* Avoid bugcheck */
3928 Time.QuadPart += 50000000;
3929 NtDelayExecution(FALSE, &Time);
3930
3931 /* Reboot */
3932 NtShutdownSystem(ShutdownReboot);
3933 NtTerminateProcess(NtCurrentProcess(), 0);
3934 }
3935
3936
3937 #ifdef __REACTOS__
3938
3939 VOID NTAPI
3940 NtProcessStartup(PPEB Peb)
3941 {
3942 RtlNormalizeProcessParams(Peb->ProcessParameters);
3943
3944 ProcessHeap = Peb->ProcessHeap;
3945 InfSetHeap(ProcessHeap);
3946 RunUSetup();
3947 }
3948 #endif /* __REACTOS__ */
3949
3950 /* EOF */