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