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