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