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