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