[USETUP]
[reactos.git] / reactos / base / setup / usetup / interface / usetup.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 2002, 2003, 2004 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 /*
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS text-mode setup
22 * FILE: subsys/system/usetup/usetup.c
23 * PURPOSE: Text-mode setup
24 * PROGRAMMER: Eric Kohl
25 * Casper S. Hornstrup (chorns@users.sourceforge.net)
26 * Hervé Poussineau (hpoussin@reactos.org)
27 */
28
29 #include "usetup.h"
30
31 #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 (wcscmp(FileSystemList->Selected->FileSystem, L"FAT") == 0)
2314 {
2315 if (PartEntry->PartInfo[PartNum].PartitionLength.QuadPart < (4200LL * 1024LL))
2316 {
2317 /* FAT12 CHS partition (disk is smaller than 4.1MB) */
2318 PartEntry->PartInfo[PartNum].PartitionType = PARTITION_FAT_12;
2319 }
2320 else if (PartEntry->PartInfo[PartNum].StartingOffset.QuadPart < (1024LL * 255LL * 63LL * 512LL))
2321 {
2322 /* Partition starts below the 8.4GB boundary ==> CHS partition */
2323
2324 if (PartEntry->PartInfo[PartNum].PartitionLength.QuadPart < (32LL * 1024LL * 1024LL))
2325 {
2326 /* FAT16 CHS partition (partiton size < 32MB) */
2327 PartEntry->PartInfo[PartNum].PartitionType = PARTITION_FAT_16;
2328 }
2329 else if (PartEntry->PartInfo[PartNum].PartitionLength.QuadPart < (512LL * 1024LL * 1024LL))
2330 {
2331 /* FAT16 CHS partition (partition size < 512MB) */
2332 PartEntry->PartInfo[PartNum].PartitionType = PARTITION_HUGE;
2333 }
2334 else
2335 {
2336 /* FAT32 CHS partition (partition size >= 512MB) */
2337 PartEntry->PartInfo[PartNum].PartitionType = PARTITION_FAT32;
2338 }
2339 }
2340 else
2341 {
2342 /* Partition starts above the 8.4GB boundary ==> LBA partition */
2343
2344 if (PartEntry->PartInfo[PartNum].PartitionLength.QuadPart < (512LL * 1024LL * 1024LL))
2345 {
2346 /* FAT16 LBA partition (partition size < 512MB) */
2347 PartEntry->PartInfo[PartNum].PartitionType = PARTITION_XINT13;
2348 }
2349 else
2350 {
2351 /* FAT32 LBA partition (partition size >= 512MB) */
2352 PartEntry->PartInfo[PartNum].PartitionType = PARTITION_FAT32_XINT13;
2353 }
2354 }
2355 }
2356 else if (wcscmp(FileSystemList->Selected->FileSystem, L"EXT2") == 0)
2357 PartEntry->PartInfo[PartNum].PartitionType = PARTITION_EXT2;
2358 else if (!FileSystemList->Selected->FormatFunc)
2359 return QUIT_PAGE;
2360
2361 CheckActiveBootPartition (PartitionList);
2362
2363 #ifndef NDEBUG
2364 CONSOLE_PrintTextXY(6, 12,
2365 "Disk: %I64u Cylinder: %I64u Track: %I64u",
2366 DiskEntry->DiskSize,
2367 DiskEntry->CylinderSize,
2368 DiskEntry->TrackSize);
2369
2370 Line = 13;
2371 DiskEntry = PartitionList->CurrentDisk;
2372 Entry = DiskEntry->PartListHead.Flink;
2373
2374 while (Entry != &DiskEntry->PartListHead)
2375 {
2376 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
2377
2378 if (PartEntry->Unpartitioned == FALSE)
2379 {
2380 for (i = 0; i < 4; i++)
2381 {
2382 CONSOLE_PrintTextXY(6, Line,
2383 "%2u: %2u %c %12I64u %12I64u %2u %c",
2384 i,
2385 PartEntry->PartInfo[i].PartitionNumber,
2386 PartEntry->PartInfo[i].BootIndicator ? 'A' : '-',
2387 PartEntry->PartInfo[i].StartingOffset.QuadPart,
2388 PartEntry->PartInfo[i].PartitionLength.QuadPart,
2389 PartEntry->PartInfo[i].PartitionType,
2390 PartEntry->PartInfo[i].RewritePartition ? '*' : ' ');
2391
2392 Line++;
2393 }
2394
2395 Line++;
2396 }
2397
2398 Entry = Entry->Flink;
2399 }
2400
2401 /* Restore the old entry */
2402 PartEntry = PartitionList->CurrentPartition;
2403 #endif
2404
2405 if (WritePartitionsToDisk (PartitionList) == FALSE)
2406 {
2407 DPRINT ("WritePartitionsToDisk() failed\n");
2408 MUIDisplayError(ERROR_WRITE_PTABLE, Ir, POPUP_WAIT_ENTER);
2409 return QUIT_PAGE;
2410 }
2411
2412 /* Set DestinationRootPath */
2413 RtlFreeUnicodeString (&DestinationRootPath);
2414 swprintf (PathBuffer,
2415 L"\\Device\\Harddisk%lu\\Partition%lu",
2416 PartitionList->CurrentDisk->DiskNumber,
2417 PartitionList->CurrentPartition->PartInfo[PartNum].PartitionNumber);
2418 RtlCreateUnicodeString (&DestinationRootPath,
2419 PathBuffer);
2420 DPRINT ("DestinationRootPath: %wZ\n", &DestinationRootPath);
2421
2422
2423 /* Set SystemRootPath */
2424 RtlFreeUnicodeString (&SystemRootPath);
2425 swprintf (PathBuffer,
2426 L"\\Device\\Harddisk%lu\\Partition%lu",
2427 PartitionList->ActiveBootDisk->DiskNumber,
2428 PartitionList->ActiveBootPartition->
2429 PartInfo[PartitionList->ActiveBootPartitionNumber].PartitionNumber);
2430 RtlCreateUnicodeString (&SystemRootPath,
2431 PathBuffer);
2432 DPRINT ("SystemRootPath: %wZ\n", &SystemRootPath);
2433
2434
2435 if (FileSystemList->Selected->FormatFunc)
2436 {
2437 Status = FormatPartition(&DestinationRootPath, FileSystemList->Selected);
2438 if (!NT_SUCCESS(Status))
2439 {
2440 DPRINT1("FormatPartition() failed with status 0x%08lx\n", Status);
2441 /* FIXME: show an error dialog */
2442 return QUIT_PAGE;
2443 }
2444
2445 PartEntry->New = FALSE;
2446
2447 CheckActiveBootPartition(PartitionList);
2448 }
2449
2450 /* Install MBR if necessary */
2451 if (DiskEntry->NoMbr &&
2452 DiskEntry->BiosDiskNumber == 0)
2453 {
2454 wcscpy(PathBuffer, SourceRootPath.Buffer);
2455 wcscat(PathBuffer, L"\\loader\\dosmbr.bin");
2456
2457 DPRINT("Install MBR bootcode: %S ==> %S\n",
2458 PathBuffer, DestinationRootPath.Buffer);
2459
2460 /* Install MBR bootcode */
2461 Status = InstallMbrBootCodeToDisk(PathBuffer, DestinationRootPath.Buffer);
2462 if (!NT_SUCCESS (Status))
2463 {
2464 DPRINT1("InstallMbrBootCodeToDisk() failed (Status %lx)\n",
2465 Status);
2466 return FALSE;
2467 }
2468
2469 DiskEntry->NoMbr = FALSE;
2470 }
2471
2472 if (wcscmp(FileSystemList->Selected->FileSystem, L"FAT") == 0)
2473 {
2474 /* FIXME: Install boot code. This is a hack! */
2475 if ((PartEntry->PartInfo[PartNum].PartitionType == PARTITION_FAT32_XINT13) ||
2476 (PartEntry->PartInfo[PartNum].PartitionType == PARTITION_FAT32))
2477 {
2478 wcscpy(PathBuffer, SourceRootPath.Buffer);
2479 wcscat(PathBuffer, L"\\loader\\fat32.bin");
2480
2481 DPRINT("Install FAT32 bootcode: %S ==> %S\n", PathBuffer,
2482 DestinationRootPath.Buffer);
2483 Status = InstallFat32BootCodeToDisk(PathBuffer,
2484 DestinationRootPath.Buffer);
2485
2486 if (!NT_SUCCESS(Status))
2487 {
2488 DPRINT1("InstallFat32BootCodeToDisk() failed with status 0x%08lx\n", Status);
2489 /* FIXME: show an error dialog */
2490 DestroyFileSystemList(FileSystemList);
2491 FileSystemList = NULL;
2492 return QUIT_PAGE;
2493 }
2494 }
2495 else
2496 {
2497 wcscpy(PathBuffer, SourceRootPath.Buffer);
2498 wcscat(PathBuffer, L"\\loader\\fat.bin");
2499
2500 DPRINT("Install FAT bootcode: %S ==> %S\n", PathBuffer,
2501 DestinationRootPath.Buffer);
2502 Status = InstallFat16BootCodeToDisk(PathBuffer,
2503 DestinationRootPath.Buffer);
2504
2505 if (!NT_SUCCESS(Status))
2506 {
2507 DPRINT1("InstallFat16BootCodeToDisk() failed with status 0x%.08x\n", Status);
2508 /* FIXME: show an error dialog */
2509 DestroyFileSystemList(FileSystemList);
2510 FileSystemList = NULL;
2511 return QUIT_PAGE;
2512 }
2513 }
2514 }
2515 else if (wcscmp(FileSystemList->Selected->FileSystem, L"EXT2") == 0)
2516 {
2517 wcscpy(PathBuffer, SourceRootPath.Buffer);
2518 wcscat(PathBuffer, L"\\loader\\ext2.bin");
2519
2520 DPRINT("Install EXT2 bootcode: %S ==> %S\n", PathBuffer,
2521 DestinationRootPath.Buffer);
2522 Status = InstallFat32BootCodeToDisk(PathBuffer,
2523 DestinationRootPath.Buffer);
2524
2525 if (!NT_SUCCESS(Status))
2526 {
2527 DPRINT1("InstallFat32BootCodeToDisk() failed with status 0x%08lx\n", Status);
2528 /* FIXME: show an error dialog */
2529 DestroyFileSystemList(FileSystemList);
2530 FileSystemList = NULL;
2531 return QUIT_PAGE;
2532 }
2533 }
2534 else if (FileSystemList->Selected->FormatFunc)
2535 {
2536 DestroyFileSystemList(FileSystemList);
2537 FileSystemList = NULL;
2538 return QUIT_PAGE;
2539 }
2540
2541 #ifndef NDEBUG
2542 CONSOLE_SetStatusText(" Done. Press any key ...");
2543 CONSOLE_ConInKey(Ir);
2544 #endif
2545
2546 DestroyFileSystemList(FileSystemList);
2547 FileSystemList = NULL;
2548 return INSTALL_DIRECTORY_PAGE;
2549 }
2550 }
2551
2552 return FORMAT_PARTITION_PAGE;
2553 }
2554
2555
2556 static ULONG
2557 CheckFileSystemPage(PINPUT_RECORD Ir)
2558 {
2559 PFILE_SYSTEM_ITEM CurrentFileSystem;
2560 WCHAR PathBuffer[MAX_PATH];
2561 CHAR Buffer[MAX_PATH];
2562 NTSTATUS Status;
2563 UCHAR PartNum = PartitionList->CurrentPartitionNumber;
2564
2565 /* FIXME: code duplicated in FormatPartitionPage */
2566 /* Set DestinationRootPath */
2567 RtlFreeUnicodeString(&DestinationRootPath);
2568 swprintf(PathBuffer,
2569 L"\\Device\\Harddisk%lu\\Partition%lu",
2570 PartitionList->CurrentDisk->DiskNumber,
2571 PartitionList->CurrentPartition->PartInfo[PartNum].PartitionNumber);
2572 RtlCreateUnicodeString(&DestinationRootPath, PathBuffer);
2573 DPRINT("DestinationRootPath: %wZ\n", &DestinationRootPath);
2574
2575 /* Set SystemRootPath */
2576 RtlFreeUnicodeString(&SystemRootPath);
2577 swprintf(PathBuffer,
2578 L"\\Device\\Harddisk%lu\\Partition%lu",
2579 PartitionList->ActiveBootDisk->DiskNumber,
2580 PartitionList->ActiveBootPartition->PartInfo[PartNum].PartitionNumber);
2581 RtlCreateUnicodeString(&SystemRootPath, PathBuffer);
2582 DPRINT("SystemRootPath: %wZ\n", &SystemRootPath);
2583
2584 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHECKINGPART));
2585
2586 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
2587
2588 /* WRONG: first filesystem is not necesseraly the one of the current partition! */
2589 CurrentFileSystem = CONTAINING_RECORD(FileSystemList->ListHead.Flink, FILE_SYSTEM_ITEM, ListEntry);
2590
2591 if (!CurrentFileSystem->ChkdskFunc)
2592 {
2593 sprintf(Buffer,
2594 "Setup is currently unable to check a partition formatted in %S.\n"
2595 "\n"
2596 " \x07 Press ENTER to continue Setup.\n"
2597 " \x07 Press F3 to quit Setup.",
2598 CurrentFileSystem->FileSystem);
2599
2600 PopupError(Buffer,
2601 MUIGetString(STRING_QUITCONTINUE),
2602 NULL, POPUP_WAIT_NONE);
2603
2604 while(TRUE)
2605 {
2606 CONSOLE_ConInKey(Ir);
2607
2608 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x00 &&
2609 Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3) /* F3 */
2610 {
2611 if (ConfirmQuit(Ir))
2612 return QUIT_PAGE;
2613 else
2614 return CHECK_FILE_SYSTEM_PAGE;
2615 }
2616 else if (Ir->Event.KeyEvent.uChar.AsciiChar == VK_RETURN) /* ENTER */
2617 {
2618 return INSTALL_DIRECTORY_PAGE;
2619 }
2620 }
2621 }
2622 else
2623 {
2624 Status = ChkdskPartition(&DestinationRootPath, CurrentFileSystem);
2625 if (!NT_SUCCESS(Status))
2626 {
2627 DPRINT("ChkdskPartition() failed with status 0x%08lx\n", Status);
2628 sprintf(Buffer, "Setup failed to verify the selected partition.\n"
2629 "(Status 0x%08lx).\n", Status);
2630
2631 PopupError(Buffer,
2632 MUIGetString(STRING_REBOOTCOMPUTER),
2633 Ir, POPUP_WAIT_ENTER);
2634
2635 return QUIT_PAGE;
2636 }
2637
2638 return INSTALL_DIRECTORY_PAGE;
2639 }
2640 }
2641
2642
2643 static PAGE_NUMBER
2644 InstallDirectoryPage1(PWCHAR InstallDir, PDISKENTRY DiskEntry, PPARTENTRY PartEntry, UCHAR PartNum)
2645 {
2646 WCHAR PathBuffer[MAX_PATH];
2647
2648 /* Create 'InstallPath' string */
2649 RtlFreeUnicodeString(&InstallPath);
2650 RtlCreateUnicodeString(&InstallPath,
2651 InstallDir);
2652
2653 /* Create 'DestinationPath' string */
2654 RtlFreeUnicodeString(&DestinationPath);
2655 wcscpy(PathBuffer, DestinationRootPath.Buffer);
2656
2657 if (InstallDir[0] != L'\\')
2658 wcscat(PathBuffer, L"\\");
2659
2660 wcscat(PathBuffer, InstallDir);
2661 RtlCreateUnicodeString(&DestinationPath, PathBuffer);
2662
2663 /* Create 'DestinationArcPath' */
2664 RtlFreeUnicodeString(&DestinationArcPath);
2665 swprintf(PathBuffer,
2666 L"multi(0)disk(0)rdisk(%lu)partition(%lu)",
2667 DiskEntry->BiosDiskNumber,
2668 PartEntry->PartInfo[PartNum].PartitionNumber);
2669
2670 if (InstallDir[0] != L'\\')
2671 wcscat(PathBuffer, L"\\");
2672
2673 wcscat(PathBuffer, InstallDir);
2674 RtlCreateUnicodeString(&DestinationArcPath, PathBuffer);
2675
2676 return(PREPARE_COPY_PAGE);
2677 }
2678
2679
2680 static PAGE_NUMBER
2681 InstallDirectoryPage(PINPUT_RECORD Ir)
2682 {
2683 PDISKENTRY DiskEntry;
2684 PPARTENTRY PartEntry;
2685 WCHAR InstallDir[51];
2686 PWCHAR DefaultPath;
2687 INFCONTEXT Context;
2688 ULONG Length;
2689
2690 if (PartitionList == NULL ||
2691 PartitionList->CurrentDisk == NULL ||
2692 PartitionList->CurrentPartition == NULL)
2693 {
2694 /* FIXME: show an error dialog */
2695 return QUIT_PAGE;
2696 }
2697
2698 DiskEntry = PartitionList->CurrentDisk;
2699 PartEntry = PartitionList->CurrentPartition;
2700
2701 /* Search for 'DefaultPath' in the 'SetupData' section */
2702 if (!SetupFindFirstLineW (SetupInf, L"SetupData", L"DefaultPath", &Context))
2703 {
2704 MUIDisplayError(ERROR_FIND_SETUPDATA, Ir, POPUP_WAIT_ENTER);
2705 return QUIT_PAGE;
2706 }
2707
2708 /* Read the 'DefaultPath' data */
2709 if (INF_GetData (&Context, NULL, &DefaultPath))
2710 {
2711 wcscpy(InstallDir, DefaultPath);
2712 }
2713 else
2714 {
2715 wcscpy(InstallDir, L"\\ReactOS");
2716 }
2717
2718 Length = wcslen(InstallDir);
2719 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
2720 MUIDisplayPage(INSTALL_DIRECTORY_PAGE);
2721
2722 if (IsUnattendedSetup)
2723 {
2724 return(InstallDirectoryPage1 (InstallDir, DiskEntry, PartEntry, PartitionList->CurrentPartitionNumber));
2725 }
2726
2727 while(TRUE)
2728 {
2729 CONSOLE_ConInKey(Ir);
2730
2731 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2732 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
2733 {
2734 if (ConfirmQuit(Ir) == TRUE)
2735 return(QUIT_PAGE);
2736
2737 break;
2738 }
2739 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2740 {
2741 return (InstallDirectoryPage1 (InstallDir, DiskEntry, PartEntry, PartitionList->CurrentPartitionNumber));
2742 }
2743 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x08) /* BACKSPACE */
2744 {
2745 if (Length > 0)
2746 {
2747 Length--;
2748 InstallDir[Length] = 0;
2749 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
2750 }
2751 }
2752 else if (isprint(Ir->Event.KeyEvent.uChar.AsciiChar))
2753 {
2754 if (Length < 50)
2755 {
2756 InstallDir[Length] = (WCHAR)Ir->Event.KeyEvent.uChar.AsciiChar;
2757 Length++;
2758 InstallDir[Length] = 0;
2759 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
2760 }
2761 }
2762 }
2763
2764 return(INSTALL_DIRECTORY_PAGE);
2765 }
2766
2767 static BOOLEAN
2768 AddSectionToCopyQueueCab(HINF InfFile,
2769 PWCHAR SectionName,
2770 PWCHAR SourceCabinet,
2771 PCUNICODE_STRING DestinationPath,
2772 PINPUT_RECORD Ir)
2773 {
2774 INFCONTEXT FilesContext;
2775 INFCONTEXT DirContext;
2776 PWCHAR FileKeyName;
2777 PWCHAR FileKeyValue;
2778 PWCHAR DirKeyValue;
2779 PWCHAR TargetFileName;
2780
2781 /* Search for the SectionName section */
2782 if (!SetupFindFirstLineW (InfFile, SectionName, NULL, &FilesContext))
2783 {
2784 char Buffer[128];
2785 sprintf(Buffer, MUIGetString(STRING_TXTSETUPFAILED), SectionName);
2786 PopupError(Buffer, MUIGetString(STRING_REBOOTCOMPUTER), Ir, POPUP_WAIT_ENTER);
2787 return(FALSE);
2788 }
2789
2790 /*
2791 * Enumerate the files in the section
2792 * and add them to the file queue.
2793 */
2794 do
2795 {
2796 /* Get source file name and target directory id */
2797 if (!INF_GetData (&FilesContext, &FileKeyName, &FileKeyValue))
2798 {
2799 /* FIXME: Handle error! */
2800 DPRINT1("INF_GetData() failed\n");
2801 break;
2802 }
2803
2804 /* Get optional target file name */
2805 if (!INF_GetDataField (&FilesContext, 2, &TargetFileName))
2806 TargetFileName = NULL;
2807
2808 DPRINT ("FileKeyName: '%S' FileKeyValue: '%S'\n", FileKeyName, FileKeyValue);
2809
2810 /* Lookup target directory */
2811 if (!SetupFindFirstLineW (InfFile, L"Directories", FileKeyValue, &DirContext))
2812 {
2813 /* FIXME: Handle error! */
2814 DPRINT1("SetupFindFirstLine() failed\n");
2815 break;
2816 }
2817
2818 if (!INF_GetData (&DirContext, NULL, &DirKeyValue))
2819 {
2820 /* FIXME: Handle error! */
2821 DPRINT1("INF_GetData() failed\n");
2822 break;
2823 }
2824
2825 if (!SetupQueueCopy(SetupFileQueue,
2826 SourceCabinet,
2827 SourceRootPath.Buffer,
2828 SourceRootDir.Buffer,
2829 FileKeyName,
2830 DirKeyValue,
2831 TargetFileName))
2832 {
2833 /* FIXME: Handle error! */
2834 DPRINT1("SetupQueueCopy() failed\n");
2835 }
2836 } while (SetupFindNextLine(&FilesContext, &FilesContext));
2837
2838 return TRUE;
2839 }
2840
2841 static BOOLEAN
2842 AddSectionToCopyQueue(HINF InfFile,
2843 PWCHAR SectionName,
2844 PWCHAR SourceCabinet,
2845 PCUNICODE_STRING DestinationPath,
2846 PINPUT_RECORD Ir)
2847 {
2848 INFCONTEXT FilesContext;
2849 INFCONTEXT DirContext;
2850 PWCHAR FileKeyName;
2851 PWCHAR FileKeyValue;
2852 PWCHAR DirKeyValue;
2853 PWCHAR TargetFileName;
2854
2855 if (SourceCabinet)
2856 return AddSectionToCopyQueueCab(InfFile, L"SourceFiles", SourceCabinet, DestinationPath, Ir);
2857
2858 /* Search for the SectionName section */
2859 if (!SetupFindFirstLineW (InfFile, SectionName, NULL, &FilesContext))
2860 {
2861 char Buffer[128];
2862 sprintf(Buffer, MUIGetString(STRING_TXTSETUPFAILED), SectionName);
2863 PopupError(Buffer, MUIGetString(STRING_REBOOTCOMPUTER), Ir, POPUP_WAIT_ENTER);
2864 return FALSE;
2865 }
2866
2867 /*
2868 * Enumerate the files in the section
2869 * and add them to the file queue.
2870 */
2871 do
2872 {
2873 /* Get source file name and target directory id */
2874 if (!INF_GetData (&FilesContext, &FileKeyName, &FileKeyValue))
2875 {
2876 /* FIXME: Handle error! */
2877 DPRINT1("INF_GetData() failed\n");
2878 break;
2879 }
2880
2881 /* Get target directory id */
2882 if (!INF_GetDataField (&FilesContext, 13, &FileKeyValue))
2883 {
2884 /* FIXME: Handle error! */
2885 DPRINT1("INF_GetData() failed\n");
2886 break;
2887 }
2888
2889 /* Get optional target file name */
2890 if (!INF_GetDataField (&FilesContext, 11, &TargetFileName))
2891 TargetFileName = NULL;
2892 else if (!*TargetFileName)
2893 TargetFileName = NULL;
2894
2895 DPRINT ("FileKeyName: '%S' FileKeyValue: '%S'\n", FileKeyName, FileKeyValue);
2896
2897 /* Lookup target directory */
2898 if (!SetupFindFirstLineW (InfFile, L"Directories", FileKeyValue, &DirContext))
2899 {
2900 /* FIXME: Handle error! */
2901 DPRINT1("SetupFindFirstLine() failed\n");
2902 break;
2903 }
2904
2905 if (!INF_GetData (&DirContext, NULL, &DirKeyValue))
2906 {
2907 /* FIXME: Handle error! */
2908 DPRINT1("INF_GetData() failed\n");
2909 break;
2910 }
2911
2912 if (!SetupQueueCopy(SetupFileQueue,
2913 SourceCabinet,
2914 SourceRootPath.Buffer,
2915 SourceRootDir.Buffer,
2916 FileKeyName,
2917 DirKeyValue,
2918 TargetFileName))
2919 {
2920 /* FIXME: Handle error! */
2921 DPRINT1("SetupQueueCopy() failed\n");
2922 }
2923 } while (SetupFindNextLine(&FilesContext, &FilesContext));
2924
2925 return TRUE;
2926 }
2927
2928 static BOOLEAN
2929 PrepareCopyPageInfFile(HINF InfFile,
2930 PWCHAR SourceCabinet,
2931 PINPUT_RECORD Ir)
2932 {
2933 WCHAR PathBuffer[MAX_PATH];
2934 INFCONTEXT DirContext;
2935 PWCHAR AdditionalSectionName = NULL;
2936 PWCHAR KeyValue;
2937 ULONG Length;
2938 NTSTATUS Status;
2939
2940 /* Add common files */
2941 if (!AddSectionToCopyQueue(InfFile, L"SourceDisksFiles", SourceCabinet, &DestinationPath, Ir))
2942 return FALSE;
2943
2944 /* Add specific files depending of computer type */
2945 if (SourceCabinet == NULL)
2946 {
2947 if (!ProcessComputerFiles(InfFile, ComputerList, &AdditionalSectionName))
2948 return FALSE;
2949
2950 if (AdditionalSectionName)
2951 {
2952 if (!AddSectionToCopyQueue(InfFile, AdditionalSectionName, SourceCabinet, &DestinationPath, Ir))
2953 return FALSE;
2954 }
2955 }
2956
2957 /* Create directories */
2958
2959 /*
2960 * FIXME:
2961 * Install directories like '\reactos\test' are not handled yet.
2962 */
2963
2964 /* Get destination path */
2965 wcscpy(PathBuffer, DestinationPath.Buffer);
2966
2967 /* Remove trailing backslash */
2968 Length = wcslen(PathBuffer);
2969 if ((Length > 0) && (PathBuffer[Length - 1] == '\\'))
2970 {
2971 PathBuffer[Length - 1] = 0;
2972 }
2973
2974 /* Create the install directory */
2975 Status = SetupCreateDirectory(PathBuffer);
2976 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION)
2977 {
2978 DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer, Status);
2979 MUIDisplayError(ERROR_CREATE_INSTALL_DIR, Ir, POPUP_WAIT_ENTER);
2980 return FALSE;
2981 }
2982
2983 /* Search for the 'Directories' section */
2984 if (!SetupFindFirstLineW(InfFile, L"Directories", NULL, &DirContext))
2985 {
2986 if (SourceCabinet)
2987 {
2988 MUIDisplayError(ERROR_CABINET_SECTION, Ir, POPUP_WAIT_ENTER);
2989 }
2990 else
2991 {
2992 MUIDisplayError(ERROR_TXTSETUP_SECTION, Ir, POPUP_WAIT_ENTER);
2993 }
2994
2995 return FALSE;
2996 }
2997
2998 /* Enumerate the directory values and create the subdirectories */
2999 do
3000 {
3001 if (!INF_GetData (&DirContext, NULL, &KeyValue))
3002 {
3003 DPRINT1("break\n");
3004 break;
3005 }
3006
3007 if (KeyValue[0] == L'\\' && KeyValue[1] != 0)
3008 {
3009 DPRINT("Absolute Path: '%S'\n", KeyValue);
3010
3011 wcscpy(PathBuffer, DestinationRootPath.Buffer);
3012 wcscat(PathBuffer, KeyValue);
3013
3014 DPRINT("FullPath: '%S'\n", PathBuffer);
3015 }
3016 else if (KeyValue[0] != L'\\')
3017 {
3018 DPRINT("RelativePath: '%S'\n", KeyValue);
3019 wcscpy(PathBuffer, DestinationPath.Buffer);
3020 wcscat(PathBuffer, L"\\");
3021 wcscat(PathBuffer, KeyValue);
3022
3023 DPRINT("FullPath: '%S'\n", PathBuffer);
3024
3025 Status = SetupCreateDirectory(PathBuffer);
3026 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION)
3027 {
3028 DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer, Status);
3029 MUIDisplayError(ERROR_CREATE_DIR, Ir, POPUP_WAIT_ENTER);
3030 return FALSE;
3031 }
3032 }
3033 } while (SetupFindNextLine (&DirContext, &DirContext));
3034
3035 return TRUE;
3036 }
3037
3038 static PAGE_NUMBER
3039 PrepareCopyPage(PINPUT_RECORD Ir)
3040 {
3041 HINF InfHandle;
3042 WCHAR PathBuffer[MAX_PATH];
3043 INFCONTEXT CabinetsContext;
3044 ULONG InfFileSize;
3045 PWCHAR KeyValue;
3046 UINT ErrorLine;
3047 PVOID InfFileData;
3048
3049 MUIDisplayPage(PREPARE_COPY_PAGE);
3050
3051 /* Create the file queue */
3052 SetupFileQueue = SetupOpenFileQueue();
3053 if (SetupFileQueue == NULL)
3054 {
3055 MUIDisplayError(ERROR_COPY_QUEUE, Ir, POPUP_WAIT_ENTER);
3056 return(QUIT_PAGE);
3057 }
3058
3059 if (!PrepareCopyPageInfFile(SetupInf, NULL, Ir))
3060 {
3061 return QUIT_PAGE;
3062 }
3063
3064 /* Search for the 'Cabinets' section */
3065 if (!SetupFindFirstLineW (SetupInf, L"Cabinets", NULL, &CabinetsContext))
3066 {
3067 return FILE_COPY_PAGE;
3068 }
3069
3070 /*
3071 * Enumerate the directory values in the 'Cabinets'
3072 * section and parse their inf files.
3073 */
3074 do
3075 {
3076 if (!INF_GetData (&CabinetsContext, NULL, &KeyValue))
3077 break;
3078
3079 wcscpy(PathBuffer, SourcePath.Buffer);
3080 wcscat(PathBuffer, L"\\");
3081 wcscat(PathBuffer, KeyValue);
3082
3083 #ifdef __REACTOS__
3084 CabinetInitialize();
3085 CabinetSetEventHandlers(NULL, NULL, NULL);
3086 CabinetSetCabinetName(PathBuffer);
3087
3088 if (CabinetOpen() == CAB_STATUS_SUCCESS)
3089 {
3090 DPRINT("Cabinet %S\n", CabinetGetCabinetName());
3091
3092 InfFileData = CabinetGetCabinetReservedArea(&InfFileSize);
3093 if (InfFileData == NULL)
3094 {
3095 MUIDisplayError(ERROR_CABINET_SCRIPT, Ir, POPUP_WAIT_ENTER);
3096 return QUIT_PAGE;
3097 }
3098 }
3099 else
3100 {
3101 DPRINT("Cannot open cabinet: %S.\n", CabinetGetCabinetName());
3102 MUIDisplayError(ERROR_CABINET_MISSING, Ir, POPUP_WAIT_ENTER);
3103 return QUIT_PAGE;
3104 }
3105
3106 InfHandle = INF_OpenBufferedFileA((CHAR*) InfFileData,
3107 InfFileSize,
3108 (const CHAR*) NULL,
3109 INF_STYLE_WIN4,
3110 LanguageId,
3111 &ErrorLine);
3112
3113 if (InfHandle == INVALID_HANDLE_VALUE)
3114 {
3115 MUIDisplayError(ERROR_INVALID_CABINET_INF, Ir, POPUP_WAIT_ENTER);
3116 return QUIT_PAGE;
3117 }
3118
3119 CabinetCleanup();
3120
3121 if (!PrepareCopyPageInfFile(InfHandle, KeyValue, Ir))
3122 {
3123 return QUIT_PAGE;
3124 }
3125 #endif
3126 } while (SetupFindNextLine (&CabinetsContext, &CabinetsContext));
3127
3128 return FILE_COPY_PAGE;
3129 }
3130
3131 VOID
3132 NTAPI
3133 SetupUpdateMemoryInfo(IN PCOPYCONTEXT CopyContext,
3134 IN BOOLEAN First)
3135 {
3136 SYSTEM_PERFORMANCE_INFORMATION PerfInfo;
3137
3138 /* Get the memory information from the system */
3139 NtQuerySystemInformation(SystemPerformanceInformation,
3140 &PerfInfo,
3141 sizeof(PerfInfo),
3142 NULL);
3143
3144 /* Check if this is initial setup */
3145 if (First)
3146 {
3147 /* Set maximum limits to be total RAM pages */
3148 ProgressSetStepCount(CopyContext->MemoryBars[0], PerfInfo.CommitLimit);
3149 ProgressSetStepCount(CopyContext->MemoryBars[1], PerfInfo.CommitLimit);
3150 ProgressSetStepCount(CopyContext->MemoryBars[2], PerfInfo.CommitLimit);
3151 }
3152
3153 /* Set current values */
3154 ProgressSetStep(CopyContext->MemoryBars[0], PerfInfo.PagedPoolPages + PerfInfo.NonPagedPoolPages);
3155 ProgressSetStep(CopyContext->MemoryBars[1], PerfInfo.ResidentSystemCachePage);
3156 ProgressSetStep(CopyContext->MemoryBars[2], PerfInfo.AvailablePages);
3157 }
3158
3159 static UINT CALLBACK
3160 FileCopyCallback(PVOID Context,
3161 UINT Notification,
3162 UINT_PTR Param1,
3163 UINT_PTR Param2)
3164 {
3165 PCOPYCONTEXT CopyContext;
3166
3167 CopyContext = (PCOPYCONTEXT)Context;
3168
3169 switch (Notification)
3170 {
3171 case SPFILENOTIFY_STARTSUBQUEUE:
3172 CopyContext->TotalOperations = (ULONG)Param2;
3173 ProgressSetStepCount(CopyContext->ProgressBar,
3174 CopyContext->TotalOperations);
3175 SetupUpdateMemoryInfo(CopyContext, TRUE);
3176 break;
3177
3178 case SPFILENOTIFY_STARTCOPY:
3179 /* Display copy message */
3180 CONSOLE_SetStatusText(MUIGetString(STRING_COPYING), (PWSTR)Param1);
3181 SetupUpdateMemoryInfo(CopyContext, FALSE);
3182 break;
3183
3184 case SPFILENOTIFY_ENDCOPY:
3185 CopyContext->CompletedOperations++;
3186 ProgressNextStep(CopyContext->ProgressBar);
3187 SetupUpdateMemoryInfo(CopyContext, FALSE);
3188 break;
3189 }
3190
3191 return 0;
3192 }
3193
3194 static
3195 PAGE_NUMBER
3196 FileCopyPage(PINPUT_RECORD Ir)
3197 {
3198 COPYCONTEXT CopyContext;
3199 unsigned int mem_bar_width;
3200
3201 MUIDisplayPage(FILE_COPY_PAGE);
3202
3203 /* Create context for the copy process */
3204 CopyContext.DestinationRootPath = DestinationRootPath.Buffer;
3205 CopyContext.InstallPath = InstallPath.Buffer;
3206 CopyContext.TotalOperations = 0;
3207 CopyContext.CompletedOperations = 0;
3208
3209 /* Create the progress bar as well */
3210 CopyContext.ProgressBar = CreateProgressBar(13,
3211 26,
3212 xScreen - 13,
3213 yScreen - 20,
3214 10,
3215 24,
3216 TRUE,
3217 MUIGetString(STRING_SETUPCOPYINGFILES));
3218
3219 // fit memory bars to screen width, distribute them uniform
3220 mem_bar_width = (xScreen - 26) / 5;
3221 mem_bar_width -= mem_bar_width % 2; // make even
3222 /* ATTENTION: The following progress bars are debug stuff, which should not be translated!! */
3223 /* Create the paged pool progress bar */
3224 CopyContext.MemoryBars[0] = CreateProgressBar(13,
3225 40,
3226 13 + mem_bar_width,
3227 43,
3228 13,
3229 44,
3230 FALSE,
3231 "Kernel Pool");
3232
3233 /* Create the non paged pool progress bar */
3234 CopyContext.MemoryBars[1] = CreateProgressBar((xScreen / 2)- (mem_bar_width / 2),
3235 40,
3236 (xScreen / 2) + (mem_bar_width / 2),
3237 43,
3238 (xScreen / 2)- (mem_bar_width / 2),
3239 44,
3240 FALSE,
3241 "Kernel Cache");
3242
3243 /* Create the global memory progress bar */
3244 CopyContext.MemoryBars[2] = CreateProgressBar(xScreen - 13 - mem_bar_width,
3245 40,
3246 xScreen - 13,
3247 43,
3248 xScreen - 13 - mem_bar_width,
3249 44,
3250 FALSE,
3251 "Free Memory");
3252
3253 /* Do the file copying */
3254 SetupCommitFileQueueW(NULL,
3255 SetupFileQueue,
3256 FileCopyCallback,
3257 &CopyContext);
3258
3259 /* If we get here, we're done, so cleanup the queue and progress bar */
3260 SetupCloseFileQueue(SetupFileQueue);
3261 DestroyProgressBar(CopyContext.ProgressBar);
3262 DestroyProgressBar(CopyContext.MemoryBars[0]);
3263 DestroyProgressBar(CopyContext.MemoryBars[1]);
3264 DestroyProgressBar(CopyContext.MemoryBars[2]);
3265
3266 /* Go display the next page */
3267 return REGISTRY_PAGE;
3268 }
3269
3270 static PAGE_NUMBER
3271 RegistryPage(PINPUT_RECORD Ir)
3272 {
3273 INFCONTEXT InfContext;
3274 PWSTR Action;
3275 PWSTR File;
3276 PWSTR Section;
3277 BOOLEAN Delete;
3278 NTSTATUS Status;
3279
3280 MUIDisplayPage(REGISTRY_PAGE);
3281
3282 if (RepairUpdateFlag)
3283 {
3284 return SUCCESS_PAGE;
3285 }
3286
3287 if (!SetInstallPathValue(&DestinationPath))
3288 {
3289 DPRINT("SetInstallPathValue() failed\n");
3290 MUIDisplayError(ERROR_INITIALIZE_REGISTRY, Ir, POPUP_WAIT_ENTER);
3291 return QUIT_PAGE;
3292 }
3293
3294 /* Create the default hives */
3295 #ifdef __REACTOS__
3296 Status = NtInitializeRegistry(CM_BOOT_FLAG_SETUP);
3297 if (!NT_SUCCESS(Status))
3298 {
3299 DPRINT("NtInitializeRegistry() failed (Status %lx)\n", Status);
3300 MUIDisplayError(ERROR_CREATE_HIVE, Ir, POPUP_WAIT_ENTER);
3301 return QUIT_PAGE;
3302 }
3303 #else
3304 RegInitializeRegistry();
3305 #endif
3306
3307 /* Update registry */
3308 CONSOLE_SetStatusText(MUIGetString(STRING_REGHIVEUPDATE));
3309
3310 if (!SetupFindFirstLineW(SetupInf, L"HiveInfs.Install", NULL, &InfContext))
3311 {
3312 DPRINT1("SetupFindFirstLine() failed\n");
3313 MUIDisplayError(ERROR_FIND_REGISTRY, Ir, POPUP_WAIT_ENTER);
3314 return QUIT_PAGE;
3315 }
3316
3317 do
3318 {
3319 INF_GetDataField (&InfContext, 0, &Action);
3320 INF_GetDataField (&InfContext, 1, &File);
3321 INF_GetDataField (&InfContext, 2, &Section);
3322
3323 DPRINT("Action: %S File: %S Section %S\n", Action, File, Section);
3324
3325 if (Action == NULL) break; // Hackfix
3326
3327 if (!_wcsicmp (Action, L"AddReg"))
3328 {
3329 Delete = FALSE;
3330 }
3331 else if (!_wcsicmp (Action, L"DelReg"))
3332 {
3333 Delete = TRUE;
3334 }
3335 else
3336 {
3337 continue;
3338 }
3339
3340 CONSOLE_SetStatusText(MUIGetString(STRING_IMPORTFILE), File);
3341
3342 if (!ImportRegistryFile(File, Section, LanguageId, Delete))
3343 {
3344 DPRINT("Importing %S failed\n", File);
3345
3346 MUIDisplayError(ERROR_IMPORT_HIVE, Ir, POPUP_WAIT_ENTER);
3347 return QUIT_PAGE;
3348 }
3349 } while (SetupFindNextLine (&InfContext, &InfContext));
3350
3351 /* Update display registry settings */
3352 CONSOLE_SetStatusText(MUIGetString(STRING_DISPLAYETTINGSUPDATE));
3353 if (!ProcessDisplayRegistry(SetupInf, DisplayList))
3354 {
3355 MUIDisplayError(ERROR_UPDATE_DISPLAY_SETTINGS, Ir, POPUP_WAIT_ENTER);
3356 return QUIT_PAGE;
3357 }
3358
3359 /* Set the locale */
3360 CONSOLE_SetStatusText(MUIGetString(STRING_LOCALESETTINGSUPDATE));
3361 if (!ProcessLocaleRegistry(LanguageList))
3362 {
3363 MUIDisplayError(ERROR_UPDATE_LOCALESETTINGS, Ir, POPUP_WAIT_ENTER);
3364 return QUIT_PAGE;
3365 }
3366
3367 /* Add keyboard layouts */
3368 CONSOLE_SetStatusText(MUIGetString(STRING_ADDKBLAYOUTS));
3369 if (!AddKeyboardLayouts())
3370 {
3371 MUIDisplayError(ERROR_ADDING_KBLAYOUTS, Ir, POPUP_WAIT_ENTER);
3372 return QUIT_PAGE;
3373 }
3374
3375 /* Set GeoID */
3376
3377 if (!SetGeoID(MUIGetGeoID()))
3378 {
3379 MUIDisplayError(ERROR_UPDATE_GEOID, Ir, POPUP_WAIT_ENTER);
3380 return QUIT_PAGE;
3381 }
3382
3383 if (!IsUnattendedSetup){
3384
3385 /* Update keyboard layout settings */
3386 CONSOLE_SetStatusText(MUIGetString(STRING_KEYBOARDSETTINGSUPDATE));
3387 if (!ProcessKeyboardLayoutRegistry(LayoutList))
3388 {
3389 MUIDisplayError(ERROR_UPDATE_KBSETTINGS, Ir, POPUP_WAIT_ENTER);
3390 return QUIT_PAGE;
3391 }
3392 }
3393 /* Add codepage information to registry */
3394 CONSOLE_SetStatusText(MUIGetString(STRING_CODEPAGEINFOUPDATE));
3395 if (!AddCodePage())
3396 {
3397 MUIDisplayError(ERROR_ADDING_CODEPAGE, Ir, POPUP_WAIT_ENTER);
3398 return QUIT_PAGE;
3399 }
3400
3401 /* Update the mounted devices list */
3402 SetMountedDeviceValues(PartitionList);
3403
3404 CONSOLE_SetStatusText(MUIGetString(STRING_DONE));
3405
3406 return BOOT_LOADER_PAGE;
3407 }
3408
3409
3410 static PAGE_NUMBER
3411 BootLoaderPage(PINPUT_RECORD Ir)
3412 {
3413 UCHAR PartitionType;
3414 BOOLEAN InstallOnFloppy;
3415 USHORT Line = 12;
3416
3417 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
3418
3419 PartitionType = PartitionList->ActiveBootPartition->
3420 PartInfo[PartitionList->ActiveBootPartitionNumber].PartitionType;
3421
3422 if (IsUnattendedSetup)
3423 {
3424 if (UnattendMBRInstallType == 0) /* skip MBR installation */
3425 {
3426 return SUCCESS_PAGE;
3427 }
3428 else if (UnattendMBRInstallType == 1) /* install on floppy */
3429 {
3430 return BOOT_LOADER_FLOPPY_PAGE;
3431 }
3432 }
3433
3434 if (PartitionType == PARTITION_ENTRY_UNUSED)
3435 {
3436 DPRINT("Error: active partition invalid (unused)\n");
3437 InstallOnFloppy = TRUE;
3438 }
3439 else if (PartitionType == 0x0A)
3440 {
3441 /* OS/2 boot manager partition */
3442 DPRINT("Found OS/2 boot manager partition\n");
3443 InstallOnFloppy = TRUE;
3444 }
3445 else if (PartitionType == 0x83)
3446 {
3447 /* Linux ext2 partition */
3448 DPRINT("Found Linux ext2 partition\n");
3449 InstallOnFloppy = TRUE;
3450 }
3451 else if (PartitionType == PARTITION_IFS)
3452 {
3453 /* NTFS partition */
3454 DPRINT("Found NTFS partition\n");
3455 InstallOnFloppy = TRUE;
3456 }
3457 else if ((PartitionType == PARTITION_FAT_12) ||
3458 (PartitionType == PARTITION_FAT_16) ||
3459 (PartitionType == PARTITION_HUGE) ||
3460 (PartitionType == PARTITION_XINT13) ||
3461 (PartitionType == PARTITION_FAT32) ||
3462 (PartitionType == PARTITION_FAT32_XINT13))
3463 {
3464 DPRINT("Found FAT partition\n");
3465 InstallOnFloppy = FALSE;
3466 }
3467 else
3468 {
3469 /* Unknown partition */
3470 DPRINT("Unknown partition found\n");
3471 InstallOnFloppy = TRUE;
3472 }
3473
3474 if (InstallOnFloppy == TRUE)
3475 {
3476 return BOOT_LOADER_FLOPPY_PAGE;
3477 }
3478
3479 /* Unattended install on hdd? */
3480 if (IsUnattendedSetup && UnattendMBRInstallType == 2)
3481 {
3482 return BOOT_LOADER_HARDDISK_PAGE;
3483 }
3484
3485 MUIDisplayPage(BOOT_LOADER_PAGE);
3486 CONSOLE_InvertTextXY(8, Line, 60, 1);
3487
3488 while(TRUE)
3489 {
3490 CONSOLE_ConInKey(Ir);
3491
3492 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3493 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
3494 {
3495 CONSOLE_NormalTextXY(8, Line, 60, 1);
3496
3497 Line++;
3498 if (Line<12) Line=14;
3499 if (Line>14) Line=12;
3500
3501 CONSOLE_InvertTextXY(8, Line, 60, 1);
3502 }
3503 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3504 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
3505 {
3506 CONSOLE_NormalTextXY(8, Line, 60, 1);
3507
3508 Line--;
3509 if (Line<12) Line=14;
3510 if (Line>14) Line=12;
3511
3512 CONSOLE_InvertTextXY(8, Line, 60, 1);
3513 }
3514 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3515 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
3516 {
3517 if (ConfirmQuit(Ir) == TRUE)
3518 return QUIT_PAGE;
3519
3520 break;
3521 }
3522 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
3523 {
3524 if (Line == 12)
3525 {
3526 return BOOT_LOADER_HARDDISK_PAGE;
3527 }
3528 else if (Line == 13)
3529 {
3530 return BOOT_LOADER_FLOPPY_PAGE;
3531 }
3532 else if (Line == 14)
3533 {
3534 return SUCCESS_PAGE;
3535 }
3536
3537 return BOOT_LOADER_PAGE;
3538 }
3539 }
3540
3541 return BOOT_LOADER_PAGE;
3542 }
3543
3544
3545 static PAGE_NUMBER
3546 BootLoaderFloppyPage(PINPUT_RECORD Ir)
3547 {
3548 NTSTATUS Status;
3549
3550 MUIDisplayPage(BOOT_LOADER_FLOPPY_PAGE);
3551
3552 // SetStatusText(" Please wait...");
3553
3554 while(TRUE)
3555 {
3556 CONSOLE_ConInKey(Ir);
3557
3558 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3559 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
3560 {
3561 if (ConfirmQuit(Ir) == TRUE)
3562 return QUIT_PAGE;
3563
3564 break;
3565 }
3566 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
3567 {
3568 if (DoesFileExist(L"\\Device\\Floppy0", L"\\") == FALSE)
3569 {
3570 MUIDisplayError(ERROR_NO_FLOPPY, Ir, POPUP_WAIT_ENTER);
3571 return BOOT_LOADER_FLOPPY_PAGE;
3572 }
3573
3574 Status = InstallFatBootcodeToFloppy(&SourceRootPath, &DestinationArcPath);
3575 if (!NT_SUCCESS(Status))
3576 {
3577 /* Print error message */
3578 return BOOT_LOADER_FLOPPY_PAGE;
3579 }
3580
3581 return SUCCESS_PAGE;
3582 }
3583 }
3584
3585 return BOOT_LOADER_FLOPPY_PAGE;
3586 }
3587
3588
3589 static PAGE_NUMBER
3590 BootLoaderHarddiskPage(PINPUT_RECORD Ir)
3591 {
3592 UCHAR PartitionType;
3593 NTSTATUS Status;
3594
3595 PartitionType = PartitionList->ActiveBootPartition->
3596 PartInfo[PartitionList->ActiveBootPartitionNumber].PartitionType;
3597 if ((PartitionType == PARTITION_FAT_12) ||
3598 (PartitionType == PARTITION_FAT_16) ||
3599 (PartitionType == PARTITION_HUGE) ||
3600 (PartitionType == PARTITION_XINT13) ||
3601 (PartitionType == PARTITION_FAT32) ||
3602 (PartitionType == PARTITION_FAT32_XINT13))
3603 {
3604 Status = InstallFatBootcodeToPartition(&SystemRootPath,
3605 &SourceRootPath,
3606 &DestinationArcPath,
3607 PartitionType);
3608 if (!NT_SUCCESS(Status))
3609 {
3610 MUIDisplayError(ERROR_INSTALL_BOOTCODE, Ir, POPUP_WAIT_ENTER);
3611 return QUIT_PAGE;
3612 }
3613
3614 return SUCCESS_PAGE;
3615 }
3616 else
3617 {
3618 MUIDisplayError(ERROR_WRITE_BOOT, Ir, POPUP_WAIT_ENTER);
3619 return QUIT_PAGE;
3620 }
3621
3622 return BOOT_LOADER_HARDDISK_PAGE;
3623 }
3624
3625
3626 static PAGE_NUMBER
3627 QuitPage(PINPUT_RECORD Ir)
3628 {
3629 MUIDisplayPage(QUIT_PAGE);
3630
3631 /* Destroy partition list */
3632 if (PartitionList != NULL)
3633 {
3634 DestroyPartitionList (PartitionList);
3635 PartitionList = NULL;
3636 }
3637
3638 /* Destroy filesystem list */
3639 if (FileSystemList != NULL)
3640 {
3641 DestroyFileSystemList (FileSystemList);
3642 FileSystemList = NULL;
3643 }
3644
3645 /* Destroy computer settings list */
3646 if (ComputerList != NULL)
3647 {
3648 DestroyGenericList(ComputerList, TRUE);
3649 ComputerList = NULL;
3650 }
3651
3652 /* Destroy display settings list */
3653 if (DisplayList != NULL)
3654 {
3655 DestroyGenericList(DisplayList, TRUE);
3656 DisplayList = NULL;
3657 }
3658
3659 /* Destroy keyboard settings list */
3660 if (KeyboardList != NULL)
3661 {
3662 DestroyGenericList(KeyboardList, TRUE);
3663 KeyboardList = NULL;
3664 }
3665
3666 /* Destroy keyboard layout list */
3667 if (LayoutList != NULL)
3668 {
3669 DestroyGenericList(LayoutList, TRUE);
3670 LayoutList = NULL;
3671 }
3672
3673 if (LanguageList != NULL)
3674 {
3675 DestroyGenericList(LanguageList, FALSE);
3676 LanguageList = NULL;
3677 }
3678
3679 CONSOLE_SetStatusText(MUIGetString(STRING_REBOOTCOMPUTER2));
3680
3681 while(TRUE)
3682 {
3683 CONSOLE_ConInKey(Ir);
3684
3685 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
3686 {
3687 return FLUSH_PAGE;
3688 }
3689 }
3690 }
3691
3692
3693 static PAGE_NUMBER
3694 SuccessPage(PINPUT_RECORD Ir)
3695 {
3696 MUIDisplayPage(SUCCESS_PAGE);
3697
3698 if (IsUnattendedSetup)
3699 {
3700 return FLUSH_PAGE;
3701 }
3702
3703 while(TRUE)
3704 {
3705 CONSOLE_ConInKey(Ir);
3706
3707 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
3708 {
3709 return FLUSH_PAGE;
3710 }
3711 }
3712 }
3713
3714
3715 static PAGE_NUMBER
3716 FlushPage(PINPUT_RECORD Ir)
3717 {
3718 MUIDisplayPage(FLUSH_PAGE);
3719 return REBOOT_PAGE;
3720 }
3721
3722
3723 DWORD WINAPI
3724 PnpEventThread(IN LPVOID lpParameter);
3725
3726 VOID
3727 RunUSetup(VOID)
3728 {
3729 INPUT_RECORD Ir;
3730 PAGE_NUMBER Page;
3731 LARGE_INTEGER Time;
3732 NTSTATUS Status;
3733
3734 NtQuerySystemTime(&Time);
3735
3736 Status = RtlCreateUserThread(NtCurrentProcess(), NULL, TRUE, 0, 0, 0, PnpEventThread, &SetupInf, &hPnpThread, NULL);
3737 if (!NT_SUCCESS(Status))
3738 hPnpThread = INVALID_HANDLE_VALUE;
3739
3740 if (!CONSOLE_Init())
3741 {
3742 PrintString(MUIGetString(STRING_CONSOLEFAIL1));
3743 PrintString(MUIGetString(STRING_CONSOLEFAIL2));
3744 PrintString(MUIGetString(STRING_CONSOLEFAIL3));
3745
3746 /* Raise a hard error (crash the system/BSOD) */
3747 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED,
3748 0,0,0,0,0);
3749 }
3750
3751 /* Initialize global unicode strings */
3752 RtlInitUnicodeString(&SourcePath, NULL);
3753 RtlInitUnicodeString(&SourceRootPath, NULL);
3754 RtlInitUnicodeString(&SourceRootDir, NULL);
3755 RtlInitUnicodeString(&InstallPath, NULL);
3756 RtlInitUnicodeString(&DestinationPath, NULL);
3757 RtlInitUnicodeString(&DestinationArcPath, NULL);
3758 RtlInitUnicodeString(&DestinationRootPath, NULL);
3759 RtlInitUnicodeString(&SystemRootPath, NULL);
3760
3761 /* Hide the cursor */
3762 CONSOLE_SetCursorType(TRUE, FALSE);
3763
3764 Page = START_PAGE;
3765 while (Page != REBOOT_PAGE)
3766 {
3767 CONSOLE_ClearScreen();
3768 CONSOLE_Flush();
3769
3770 //CONSOLE_SetUnderlinedTextXY(4, 3, " ReactOS " KERNEL_VERSION_STR " Setup ");
3771 //CONSOLE_Flush();
3772
3773 switch (Page)
3774 {
3775 /* Start page */
3776 case START_PAGE:
3777 Page = SetupStartPage(&Ir);
3778 break;
3779
3780 /* Language page */
3781 case LANGUAGE_PAGE:
3782 Page = LanguagePage(&Ir);
3783 break;
3784
3785 /* License page */
3786 case LICENSE_PAGE:
3787 Page = LicensePage(&Ir);
3788 break;
3789
3790 /* Intro page */
3791 case INTRO_PAGE:
3792 Page = IntroPage(&Ir);
3793 break;
3794
3795 /* Install pages */
3796 case INSTALL_INTRO_PAGE:
3797 Page = InstallIntroPage(&Ir);
3798 break;
3799
3800 #if 0
3801 case SCSI_CONTROLLER_PAGE:
3802 Page = ScsiControllerPage(&Ir);
3803 break;
3804 #endif
3805
3806 #if 0
3807 case OEM_DRIVER_PAGE:
3808 Page = OemDriverPage(&Ir);
3809 break;
3810 #endif
3811
3812 case DEVICE_SETTINGS_PAGE:
3813 Page = DeviceSettingsPage(&Ir);
3814 break;
3815
3816 case COMPUTER_SETTINGS_PAGE:
3817 Page = ComputerSettingsPage(&Ir);
3818 break;
3819
3820 case DISPLAY_SETTINGS_PAGE:
3821 Page = DisplaySettingsPage(&Ir);
3822 break;
3823
3824 case KEYBOARD_SETTINGS_PAGE:
3825 Page = KeyboardSettingsPage(&Ir);
3826 break;
3827
3828 case LAYOUT_SETTINGS_PAGE:
3829 Page = LayoutSettingsPage(&Ir);
3830 break;
3831
3832 case SELECT_PARTITION_PAGE:
3833 Page = SelectPartitionPage(&Ir);
3834 break;
3835
3836 case CREATE_PARTITION_PAGE:
3837 Page = CreatePartitionPage(&Ir);
3838 break;
3839
3840 case DELETE_PARTITION_PAGE:
3841 Page = DeletePartitionPage(&Ir);
3842 break;
3843
3844 case SELECT_FILE_SYSTEM_PAGE:
3845 Page = SelectFileSystemPage(&Ir);
3846 break;
3847
3848 case FORMAT_PARTITION_PAGE:
3849 Page = (PAGE_NUMBER) FormatPartitionPage(&Ir);
3850 break;
3851
3852 case CHECK_FILE_SYSTEM_PAGE:
3853 Page = (PAGE_NUMBER) CheckFileSystemPage(&Ir);
3854 break;
3855
3856 case INSTALL_DIRECTORY_PAGE:
3857 Page = InstallDirectoryPage(&Ir);
3858 break;
3859
3860 case PREPARE_COPY_PAGE:
3861 Page = PrepareCopyPage(&Ir);
3862 break;
3863
3864 case FILE_COPY_PAGE:
3865 Page = FileCopyPage(&Ir);
3866 break;
3867
3868 case REGISTRY_PAGE:
3869 Page = RegistryPage(&Ir);
3870 break;
3871
3872 case BOOT_LOADER_PAGE:
3873 Page = BootLoaderPage(&Ir);
3874 break;
3875
3876 case BOOT_LOADER_FLOPPY_PAGE:
3877 Page = BootLoaderFloppyPage(&Ir);
3878 break;
3879
3880 case BOOT_LOADER_HARDDISK_PAGE:
3881 Page = BootLoaderHarddiskPage(&Ir);
3882 break;
3883
3884 /* Repair pages */
3885 case REPAIR_INTRO_PAGE:
3886 Page = RepairIntroPage(&Ir);
3887 break;
3888
3889 case SUCCESS_PAGE:
3890 Page = SuccessPage(&Ir);
3891 break;
3892
3893 case FLUSH_PAGE:
3894 Page = FlushPage(&Ir);
3895 break;
3896
3897 case QUIT_PAGE:
3898 Page = QuitPage(&Ir);
3899 break;
3900
3901 case REBOOT_PAGE:
3902 break;
3903 }
3904 }
3905
3906 FreeConsole();
3907
3908 /* Avoid bugcheck */
3909 Time.QuadPart += 50000000;
3910 NtDelayExecution(FALSE, &Time);
3911
3912 /* Reboot */
3913 NtShutdownSystem(ShutdownReboot);
3914 NtTerminateProcess(NtCurrentProcess(), 0);
3915 }
3916
3917
3918 #ifdef __REACTOS__
3919
3920 VOID NTAPI
3921 NtProcessStartup(PPEB Peb)
3922 {
3923 RtlNormalizeProcessParams(Peb->ProcessParameters);
3924
3925 ProcessHeap = Peb->ProcessHeap;
3926 INF_SetHeap(ProcessHeap);
3927 RunUSetup();
3928 }
3929 #endif /* __REACTOS__ */
3930
3931 /* EOF */