- Allow LANGUAGE_PAGE localization
[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
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, 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 /* GLOBALS ******************************************************************/
35
36 HANDLE ProcessHeap;
37 UNICODE_STRING SourceRootPath;
38 UNICODE_STRING SourceRootDir;
39 UNICODE_STRING SourcePath;
40 BOOLEAN IsUnattendedSetup = FALSE;
41 LONG UnattendDestinationDiskNumber;
42 LONG UnattendDestinationPartitionNumber;
43 LONG UnattendMBRInstallType = -1;
44 LONG UnattendFormatPartition = 0;
45 LONG AutoPartition = 0;
46 WCHAR UnattendInstallationDirectory[MAX_PATH];
47 PWCHAR SelectedLanguageId;
48 BOOLEAN RepairUpdateFlag = FALSE;
49 HANDLE hPnpThread = INVALID_HANDLE_VALUE;
50
51 /* LOCALS *******************************************************************/
52
53 static PPARTLIST PartitionList = NULL;
54
55 static PFILE_SYSTEM_LIST FileSystemList = NULL;
56
57 static UNICODE_STRING InstallPath;
58
59 /* Path to the install directory */
60 static UNICODE_STRING DestinationPath;
61 static UNICODE_STRING DestinationArcPath;
62 static UNICODE_STRING DestinationRootPath;
63
64 /* Path to the active partition (boot manager) */
65 static UNICODE_STRING SystemRootPath;
66
67 static HINF SetupInf;
68
69 static HSPFILEQ SetupFileQueue = NULL;
70
71 static BOOLEAN WarnLinuxPartitions = TRUE;
72
73 static PGENERIC_LIST ComputerList = NULL;
74 static PGENERIC_LIST DisplayList = NULL;
75 static PGENERIC_LIST KeyboardList = NULL;
76 static PGENERIC_LIST LayoutList = NULL;
77 static PGENERIC_LIST LanguageList = NULL;
78
79 /* FUNCTIONS ****************************************************************/
80
81 static VOID
82 PrintString(char* fmt,...)
83 {
84 char buffer[512];
85 va_list ap;
86 UNICODE_STRING UnicodeString;
87 ANSI_STRING AnsiString;
88
89 va_start(ap, fmt);
90 vsprintf(buffer, fmt, ap);
91 va_end(ap);
92
93 RtlInitAnsiString(&AnsiString, buffer);
94 RtlAnsiStringToUnicodeString(&UnicodeString,
95 &AnsiString,
96 TRUE);
97 NtDisplayString(&UnicodeString);
98 RtlFreeUnicodeString(&UnicodeString);
99 }
100
101
102 static VOID
103 DrawBox(
104 IN SHORT xLeft,
105 IN SHORT yTop,
106 IN SHORT Width,
107 IN SHORT Height)
108 {
109 COORD coPos;
110 DWORD Written;
111
112 /* draw upper left corner */
113 coPos.X = xLeft;
114 coPos.Y = yTop;
115 FillConsoleOutputCharacterA(
116 StdOutput,
117 0xDA, // '+',
118 1,
119 coPos,
120 &Written);
121
122 /* draw upper edge */
123 coPos.X = xLeft + 1;
124 coPos.Y = yTop;
125 FillConsoleOutputCharacterA(
126 StdOutput,
127 0xC4, // '-',
128 Width - 2,
129 coPos,
130 &Written);
131
132 /* draw upper right corner */
133 coPos.X = xLeft + Width - 1;
134 coPos.Y = yTop;
135 FillConsoleOutputCharacterA(
136 StdOutput,
137 0xBF, // '+',
138 1,
139 coPos,
140 &Written);
141
142 /* Draw right edge, inner space and left edge */
143 for (coPos.Y = yTop + 1; coPos.Y < yTop + Height - 1; coPos.Y++)
144 {
145 coPos.X = xLeft;
146 FillConsoleOutputCharacterA(
147 StdOutput,
148 0xB3, // '|',
149 1,
150 coPos,
151 &Written);
152
153 coPos.X = xLeft + 1;
154 FillConsoleOutputCharacterA(
155 StdOutput,
156 ' ',
157 Width - 2,
158 coPos,
159 &Written);
160
161 coPos.X = xLeft + Width - 1;
162 FillConsoleOutputCharacterA(
163 StdOutput,
164 0xB3, // '|',
165 1,
166 coPos,
167 &Written);
168 }
169
170 /* draw lower left corner */
171 coPos.X = xLeft;
172 coPos.Y = yTop + Height - 1;
173 FillConsoleOutputCharacterA(
174 StdOutput,
175 0xC0, // '+',
176 1,
177 coPos,
178 &Written);
179
180 /* draw lower edge */
181 coPos.X = xLeft + 1;
182 coPos.Y = yTop + Height - 1;
183 FillConsoleOutputCharacterA(
184 StdOutput,
185 0xC4, // '-',
186 Width - 2,
187 coPos,
188 &Written);
189
190 /* draw lower right corner */
191 coPos.X = xLeft + Width - 1;
192 coPos.Y = yTop + Height - 1;
193 FillConsoleOutputCharacterA(
194 StdOutput,
195 0xD9, // '+',
196 1,
197 coPos,
198 &Written);
199 }
200
201 VOID
202 PopupError(PCHAR Text,
203 PCHAR Status,
204 PINPUT_RECORD Ir,
205 ULONG WaitEvent)
206 {
207 SHORT yTop;
208 SHORT xLeft;
209 COORD coPos;
210 DWORD Written;
211 ULONG Length;
212 ULONG MaxLength;
213 ULONG Lines;
214 PCHAR p;
215 PCHAR pnext;
216 BOOLEAN LastLine;
217 SHORT Width;
218 SHORT Height;
219
220 /* Count text lines and longest line */
221 MaxLength = 0;
222 Lines = 0;
223 pnext = Text;
224 while (TRUE)
225 {
226 p = strchr(pnext, '\n');
227 if (p == NULL)
228 {
229 Length = strlen(pnext);
230 LastLine = TRUE;
231 }
232 else
233 {
234 Length = (ULONG)(p - pnext);
235 LastLine = FALSE;
236 }
237
238 Lines++;
239 if (Length > MaxLength)
240 MaxLength = Length;
241
242 if (LastLine == TRUE)
243 break;
244
245 pnext = p + 1;
246 }
247
248 /* Check length of status line */
249 if (Status != NULL)
250 {
251 Length = strlen(Status);
252 if (Length > MaxLength)
253 MaxLength = Length;
254 }
255
256 Width = MaxLength + 4;
257 Height = Lines + 2;
258 if (Status != NULL)
259 Height += 2;
260
261 yTop = (yScreen - Height) / 2;
262 xLeft = (xScreen - Width) / 2;
263
264
265 /* Set screen attributes */
266 coPos.X = xLeft;
267 for (coPos.Y = yTop; coPos.Y < yTop + Height; coPos.Y++)
268 {
269 FillConsoleOutputAttribute(StdOutput,
270 FOREGROUND_RED | BACKGROUND_WHITE,
271 Width,
272 coPos,
273 &Written);
274 }
275
276 DrawBox(xLeft, yTop, Width, Height);
277
278 /* Print message text */
279 coPos.Y = yTop + 1;
280 pnext = Text;
281 while (TRUE)
282 {
283 p = strchr(pnext, '\n');
284 if (p == NULL)
285 {
286 Length = strlen(pnext);
287 LastLine = TRUE;
288 }
289 else
290 {
291 Length = (ULONG)(p - pnext);
292 LastLine = FALSE;
293 }
294
295 if (Length != 0)
296 {
297 coPos.X = xLeft + 2;
298 WriteConsoleOutputCharacterA(StdOutput,
299 pnext,
300 Length,
301 coPos,
302 &Written);
303 }
304
305 if (LastLine == TRUE)
306 break;
307
308 coPos.Y++;
309 pnext = p + 1;
310 }
311
312 /* Print separator line and status text */
313 if (Status != NULL)
314 {
315 coPos.Y = yTop + Height - 3;
316 coPos.X = xLeft;
317 FillConsoleOutputCharacterA(StdOutput,
318 0xC3, // '+',
319 1,
320 coPos,
321 &Written);
322
323 coPos.X = xLeft + 1;
324 FillConsoleOutputCharacterA(StdOutput,
325 0xC4, // '-',
326 Width - 2,
327 coPos,
328 &Written);
329
330 coPos.X = xLeft + Width - 1;
331 FillConsoleOutputCharacterA(StdOutput,
332 0xB4, // '+',
333 1,
334 coPos,
335 &Written);
336
337 coPos.Y++;
338 coPos.X = xLeft + 2;
339 WriteConsoleOutputCharacterA(StdOutput,
340 Status,
341 min(strlen(Status), (SIZE_T)Width - 4),
342 coPos,
343 &Written);
344 }
345
346 if (WaitEvent == POPUP_WAIT_NONE)
347 return;
348
349 while (TRUE)
350 {
351 CONSOLE_ConInKey(Ir);
352
353 if (WaitEvent == POPUP_WAIT_ANY_KEY
354 || Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)
355 {
356 return;
357 }
358 }
359 }
360
361
362 /*
363 * Confirm quit setup
364 * RETURNS
365 * TRUE: Quit setup.
366 * FALSE: Don't quit setup.
367 */
368 static BOOL
369 ConfirmQuit(PINPUT_RECORD Ir)
370 {
371 BOOL Result = FALSE;
372 MUIDisplayError(ERROR_NOT_INSTALLED, NULL, POPUP_WAIT_NONE);
373
374 while(TRUE)
375 {
376 CONSOLE_ConInKey(Ir);
377
378 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
379 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
380 {
381 Result = TRUE;
382 break;
383 }
384 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
385 {
386 Result = FALSE;
387 break;
388 }
389 }
390
391 return Result;
392 }
393
394
395 VOID
396 CheckUnattendedSetup(VOID)
397 {
398 WCHAR UnattendInfPath[MAX_PATH];
399 INFCONTEXT Context;
400 HINF UnattendInf;
401 UINT ErrorLine;
402 INT IntValue;
403 PWCHAR Value;
404
405 if (DoesFileExist(SourcePath.Buffer, L"unattend.inf") == FALSE)
406 {
407 DPRINT("Does not exist: %S\\%S\n", SourcePath.Buffer, L"unattend.inf");
408 return;
409 }
410
411 wcscpy(UnattendInfPath, SourcePath.Buffer);
412 wcscat(UnattendInfPath, L"\\unattend.inf");
413
414 /* Load 'unattend.inf' from install media. */
415 UnattendInf = SetupOpenInfFileW(UnattendInfPath,
416 NULL,
417 INF_STYLE_WIN4,
418 &ErrorLine);
419 if (UnattendInf == INVALID_HANDLE_VALUE)
420 {
421 DPRINT("SetupOpenInfFileW() failed\n");
422 return;
423 }
424
425 /* Open 'Unattend' section */
426 if (!SetupFindFirstLineW(UnattendInf, L"Unattend", L"Signature", &Context))
427 {
428 DPRINT("SetupFindFirstLineW() failed for section 'Unattend'\n");
429 SetupCloseInfFile(UnattendInf);
430 return;
431 }
432
433 /* Get pointer 'Signature' key */
434 if (!INF_GetData(&Context, NULL, &Value))
435 {
436 DPRINT("INF_GetData() failed for key 'Signature'\n");
437 SetupCloseInfFile(UnattendInf);
438 return;
439 }
440
441 /* Check 'Signature' string */
442 if (_wcsicmp(Value, L"$ReactOS$") != 0)
443 {
444 DPRINT("Signature not $ReactOS$\n");
445 SetupCloseInfFile(UnattendInf);
446 return;
447 }
448
449 /* Check if Unattend setup is enabled */
450 if (!SetupFindFirstLineW(UnattendInf, L"Unattend", L"UnattendSetupEnabled", &Context))
451 {
452 DPRINT("Can't find key 'UnattendSetupEnabled'\n");
453 SetupCloseInfFile(UnattendInf);
454 return;
455 }
456 if (!INF_GetData(&Context, NULL, &Value))
457 {
458 DPRINT("Can't read key 'UnattendSetupEnabled'\n");
459 SetupCloseInfFile(UnattendInf);
460 return;
461 }
462 if (_wcsicmp(Value, L"yes") != 0)
463 {
464 DPRINT("Unattend setup is disabled by 'UnattendSetupEnabled' key!\n");
465 SetupCloseInfFile(UnattendInf);
466 return;
467 }
468
469 /* Search for 'DestinationDiskNumber' in the 'Unattend' section */
470 if (!SetupFindFirstLineW(UnattendInf, L"Unattend", L"DestinationDiskNumber", &Context))
471 {
472 DPRINT("SetupFindFirstLine() failed for key 'DestinationDiskNumber'\n");
473 SetupCloseInfFile(UnattendInf);
474 return;
475 }
476 if (!SetupGetIntField(&Context, 1, &IntValue))
477 {
478 DPRINT("SetupGetIntField() failed for key 'DestinationDiskNumber'\n");
479 SetupCloseInfFile(UnattendInf);
480 return;
481 }
482 UnattendDestinationDiskNumber = (LONG)IntValue;
483
484 /* Search for 'DestinationPartitionNumber' in the 'Unattend' section */
485 if (!SetupFindFirstLineW(UnattendInf, L"Unattend", L"DestinationPartitionNumber", &Context))
486 {
487 DPRINT("SetupFindFirstLine() failed for key 'DestinationPartitionNumber'\n");
488 SetupCloseInfFile(UnattendInf);
489 return;
490 }
491 if (!SetupGetIntField(&Context, 1, &IntValue))
492 {
493 DPRINT("SetupGetIntField() failed for key 'DestinationPartitionNumber'\n");
494 SetupCloseInfFile(UnattendInf);
495 return;
496 }
497 UnattendDestinationPartitionNumber = IntValue;
498
499 /* Search for 'DestinationPartitionNumber' in the 'Unattend' section */
500 if (!SetupFindFirstLineW(UnattendInf, L"Unattend", L"DestinationPartitionNumber", &Context))
501 {
502 DPRINT("SetupFindFirstLine() failed for key 'DestinationPartitionNumber'\n");
503 SetupCloseInfFile(UnattendInf);
504 return;
505 }
506
507 /* Get pointer 'InstallationDirectory' key */
508 if (!INF_GetData(&Context, NULL, &Value))
509 {
510 DPRINT("INF_GetData() failed for key 'InstallationDirectory'\n");
511 SetupCloseInfFile(UnattendInf);
512 return;
513 }
514 wcscpy(UnattendInstallationDirectory, Value);
515
516 IsUnattendedSetup = TRUE;
517
518 /* Search for 'MBRInstallType' in the 'Unattend' section */
519 if (SetupFindFirstLineW(UnattendInf, L"Unattend", L"MBRInstallType", &Context))
520 {
521 if (SetupGetIntField(&Context, 1, &IntValue))
522 {
523 UnattendMBRInstallType = IntValue;
524 }
525 }
526 /* Search for 'FormatPartition' in the 'Unattend' section */
527 if (SetupFindFirstLineW(UnattendInf, L"Unattend", L"FormatPartition", &Context))
528 {
529 if (SetupGetIntField(&Context, 1, &IntValue))
530 {
531 UnattendFormatPartition = IntValue;
532 }
533 }
534 if (SetupFindFirstLineW(UnattendInf, L"Unattend", L"AutoPartition", &Context))
535 {
536 if (SetupGetIntField(&Context, 1, &IntValue))
537 {
538 AutoPartition = IntValue;
539 }
540 }
541 SetupCloseInfFile(UnattendInf);
542
543 DPRINT("Running unattended setup\n");
544 }
545
546 static PAGE_NUMBER
547 LanguagePage(PINPUT_RECORD Ir)
548 {
549 /* Initialize the computer settings list */
550 if (LanguageList == NULL)
551 {
552 LanguageList = CreateLanguageList(SetupInf);
553 if (LanguageList == NULL)
554 {
555 PopupError("Setup failed to initialize available translations", NULL, NULL, POPUP_WAIT_NONE);
556 return INTRO_PAGE;
557 }
558 }
559
560 DrawGenericList(LanguageList,
561 2,
562 18,
563 xScreen - 3,
564 yScreen - 3);
565
566 MUIDisplayPage(LANGUAGE_PAGE);
567
568 while(TRUE)
569 {
570 CONSOLE_ConInKey(Ir);
571
572 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
573 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
574 {
575 #if 0 //Dinamically update user interface
576 SelectedLanguageId = (PWCHAR)LanguageList->CurrentEntry->UserData;
577 MUIDisplayPage(LANGUAGE_PAGE);
578 #endif
579 ScrollDownGenericList (LanguageList);
580 }
581 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
582 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
583 {
584 #if 0
585 SelectedLanguageId = (PWCHAR)LanguageList->CurrentEntry->UserData;
586 MUIDisplayPage(LANGUAGE_PAGE);
587 #endif
588 ScrollUpGenericList (LanguageList);
589 }
590 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
591 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
592 {
593 if (ConfirmQuit(Ir) == TRUE)
594 return QUIT_PAGE;
595 }
596 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
597 {
598 SelectedLanguageId = (PWCHAR)LanguageList->CurrentEntry->UserData;
599 return INTRO_PAGE;
600 }
601 }
602
603 return INTRO_PAGE;
604 }
605
606
607 /*
608 * Start page
609 * RETURNS
610 * Number of the next page.
611 */
612 static PAGE_NUMBER
613 SetupStartPage(PINPUT_RECORD Ir)
614 {
615 SYSTEM_DEVICE_INFORMATION Sdi;
616 NTSTATUS Status;
617 WCHAR FileNameBuffer[MAX_PATH];
618 INFCONTEXT Context;
619 PWCHAR Value;
620 UINT ErrorLine;
621 SIZE_T ReturnSize;
622
623 CONSOLE_SetStatusText(" Please wait...");
624
625
626 /* Check whether a harddisk is available */
627 Status = NtQuerySystemInformation (SystemDeviceInformation,
628 &Sdi,
629 sizeof(SYSTEM_DEVICE_INFORMATION),
630 &ReturnSize);
631 if (!NT_SUCCESS (Status))
632 {
633 CONSOLE_PrintTextXY(6, 15, "NtQuerySystemInformation() failed (Status 0x%08lx)", Status);
634 MUIDisplayError(ERROR_DRIVE_INFORMATION, Ir, POPUP_WAIT_ENTER);
635 return QUIT_PAGE;
636 }
637
638 if (Sdi.NumberOfDisks == 0)
639 {
640 MUIDisplayError(ERROR_NO_HDD, Ir, POPUP_WAIT_ENTER);
641 return QUIT_PAGE;
642 }
643
644 /* Get the source path and source root path */
645 Status = GetSourcePaths(&SourcePath,
646 &SourceRootPath,
647 &SourceRootDir);
648 if (!NT_SUCCESS(Status))
649 {
650 CONSOLE_PrintTextXY(6, 15, "GetSourcePaths() failed (Status 0x%08lx)", Status);
651 MUIDisplayError(ERROR_NO_SOURCE_DRIVE, Ir, POPUP_WAIT_ENTER);
652 return QUIT_PAGE;
653 }
654 #if 0
655 else
656 {
657 CONSOLE_PrintTextXY(6, 15, "SourcePath: '%wZ'", &SourcePath);
658 CONSOLE_PrintTextXY(6, 16, "SourceRootPath: '%wZ'", &SourceRootPath);
659 CONSOLE_PrintTextXY(6, 17, "SourceRootDir: '%wZ'", &SourceRootDir);
660 }
661 #endif
662
663 /* Load txtsetup.sif from install media. */
664 wcscpy(FileNameBuffer, SourcePath.Buffer);
665 wcscat(FileNameBuffer, L"\\txtsetup.sif");
666
667 SetupInf = SetupOpenInfFileW(FileNameBuffer,
668 NULL,
669 INF_STYLE_WIN4,
670 &ErrorLine);
671 if (SetupInf == INVALID_HANDLE_VALUE)
672 {
673 MUIDisplayError(ERROR_LOAD_TXTSETUPSIF, Ir, POPUP_WAIT_ENTER);
674 return QUIT_PAGE;
675 }
676
677 /* Open 'Version' section */
678 if (!SetupFindFirstLineW (SetupInf, L"Version", L"Signature", &Context))
679 {
680 MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF, Ir, POPUP_WAIT_ENTER);
681 return QUIT_PAGE;
682 }
683
684
685 /* Get pointer 'Signature' key */
686 if (!INF_GetData (&Context, NULL, &Value))
687 {
688 MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF, Ir, POPUP_WAIT_ENTER);
689 return QUIT_PAGE;
690 }
691
692 /* Check 'Signature' string */
693 if (_wcsicmp(Value, L"$ReactOS$") != 0)
694 {
695 MUIDisplayError(ERROR_SIGNATURE_TXTSETUPSIF, Ir, POPUP_WAIT_ENTER);
696 return QUIT_PAGE;
697 }
698
699 /* Start PnP thread */
700 if (hPnpThread != INVALID_HANDLE_VALUE)
701 {
702 //HACK: Commented out till the problem with CM is solved
703 //NtResumeThread(hPnpThread, NULL);
704 hPnpThread = INVALID_HANDLE_VALUE;
705 }
706
707 CheckUnattendedSetup();
708
709 if (IsUnattendedSetup)
710 {
711 //TODO
712 //read options from inf
713 ComputerList = CreateComputerTypeList(SetupInf);
714 DisplayList = CreateDisplayDriverList(SetupInf);
715 KeyboardList = CreateKeyboardDriverList(SetupInf);
716 LayoutList = CreateKeyboardLayoutList(SetupInf);
717 LanguageList = CreateLanguageList(SetupInf);
718
719 return INSTALL_INTRO_PAGE;
720 }
721
722 return LANGUAGE_PAGE;
723 }
724
725
726 /*
727 * First setup page
728 * RETURNS
729 * Next page number.
730 */
731 static PAGE_NUMBER
732 IntroPage(PINPUT_RECORD Ir)
733 {
734 MUIDisplayPage(START_PAGE);
735
736 while (TRUE)
737 {
738 CONSOLE_ConInKey(Ir);
739
740 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
741 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
742 {
743 if (ConfirmQuit(Ir) == TRUE)
744 return QUIT_PAGE;
745 break;
746 }
747 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
748 {
749 return INSTALL_INTRO_PAGE;
750 break;
751 }
752 else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'R') /* R */
753 {
754 return REPAIR_INTRO_PAGE;
755 break;
756 }
757 else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'L') /* R */
758 {
759 return LICENSE_PAGE;
760 break;
761 }
762 }
763
764 return INTRO_PAGE;
765 }
766
767 /*
768 * License Page
769 * RETURNS
770 * Back to main setup page.
771 */
772 static PAGE_NUMBER
773 LicensePage(PINPUT_RECORD Ir)
774 {
775 MUIDisplayPage(LICENSE_PAGE);
776
777 while (TRUE)
778 {
779 CONSOLE_ConInKey(Ir);
780
781 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
782 {
783 return INTRO_PAGE;
784 break;
785 }
786 }
787
788 return LICENSE_PAGE;
789 }
790
791 static PAGE_NUMBER
792 RepairIntroPage(PINPUT_RECORD Ir)
793 {
794 MUIDisplayPage(REPAIR_INTRO_PAGE);
795
796 while(TRUE)
797 {
798 CONSOLE_ConInKey(Ir);
799
800 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
801 {
802 return REBOOT_PAGE;
803 }
804 else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'U') /* U */
805 {
806 RepairUpdateFlag = TRUE;
807 return INSTALL_INTRO_PAGE;
808 }
809 else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'R') /* R */
810 {
811 return INTRO_PAGE;
812 }
813 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
814 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
815 {
816 return INTRO_PAGE;
817 }
818 }
819
820 return REPAIR_INTRO_PAGE;
821 }
822
823
824 static PAGE_NUMBER
825 InstallIntroPage(PINPUT_RECORD Ir)
826 {
827 MUIDisplayPage(INSTALL_INTRO_PAGE);
828
829 if (RepairUpdateFlag)
830 {
831 //return SELECT_PARTITION_PAGE;
832 return DEVICE_SETTINGS_PAGE;
833 }
834
835 if (IsUnattendedSetup)
836 {
837 return SELECT_PARTITION_PAGE;
838 }
839
840 while(TRUE)
841 {
842 CONSOLE_ConInKey(Ir);
843
844 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
845 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
846 {
847 if (ConfirmQuit(Ir) == TRUE)
848 return QUIT_PAGE;
849 break;
850 }
851 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
852 {
853 return DEVICE_SETTINGS_PAGE;
854 // return SCSI_CONTROLLER_PAGE;
855 }
856 }
857
858 return INSTALL_INTRO_PAGE;
859 }
860
861
862 #if 0
863 static PAGE_NUMBER
864 ScsiControllerPage(PINPUT_RECORD Ir)
865 {
866 SetTextXY(6, 8, "Setup detected the following mass storage devices:");
867
868 /* FIXME: print loaded mass storage driver descriptions */
869 #if 0
870 SetTextXY(8, 10, "TEST device");
871 #endif
872
873
874 SetStatusText(" ENTER = Continue F3 = Quit");
875
876 while(TRUE)
877 {
878 ConInKey(Ir);
879
880 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
881 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
882 {
883 if (ConfirmQuit(Ir) == TRUE)
884 return QUIT_PAGE;
885 break;
886 }
887 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
888 {
889 return DEVICE_SETTINGS_PAGE;
890 }
891 }
892
893 return SCSI_CONTROLLER_PAGE;
894 }
895 #endif
896
897
898 static PAGE_NUMBER
899 DeviceSettingsPage(PINPUT_RECORD Ir)
900 {
901 static ULONG Line = 16;
902 MUIDisplayPage(DEVICE_SETTINGS_PAGE);
903
904 /* Initialize the computer settings list */
905 if (ComputerList == NULL)
906 {
907 ComputerList = CreateComputerTypeList(SetupInf);
908 if (ComputerList == NULL)
909 {
910 MUIDisplayError(ERROR_LOAD_COMPUTER, Ir, POPUP_WAIT_ENTER);
911 return QUIT_PAGE;
912 }
913 }
914
915 /* Initialize the display settings list */
916 if (DisplayList == NULL)
917 {
918 DisplayList = CreateDisplayDriverList(SetupInf);
919 if (DisplayList == NULL)
920 {
921 MUIDisplayError(ERROR_LOAD_DISPLAY, Ir, POPUP_WAIT_ENTER);
922 return QUIT_PAGE;
923 }
924 }
925
926 /* Initialize the keyboard settings list */
927 if (KeyboardList == NULL)
928 {
929 KeyboardList = CreateKeyboardDriverList(SetupInf);
930 if (KeyboardList == NULL)
931 {
932 MUIDisplayError(ERROR_LOAD_KEYBOARD, Ir, POPUP_WAIT_ENTER);
933 return QUIT_PAGE;
934 }
935 }
936
937 /* Initialize the keyboard layout list */
938 if (LayoutList == NULL)
939 {
940 LayoutList = CreateKeyboardLayoutList(SetupInf);
941 if (LayoutList == NULL)
942 {
943 /* FIXME: report error */
944 MUIDisplayError(ERROR_LOAD_KBLAYOUT, Ir, POPUP_WAIT_ENTER);
945 return QUIT_PAGE;
946 }
947 }
948
949 MUIDisplayPage(DEVICE_SETTINGS_PAGE);
950
951
952 CONSOLE_SetTextXY(25, 11, GetGenericListEntry(ComputerList)->Text);
953 CONSOLE_SetTextXY(25, 12, GetGenericListEntry(DisplayList)->Text);
954 CONSOLE_SetTextXY(25, 13, GetGenericListEntry(KeyboardList)->Text);
955 CONSOLE_SetTextXY(25, 14, GetGenericListEntry(LayoutList)->Text);
956
957 CONSOLE_InvertTextXY (24, Line, 48, 1);
958
959 if (RepairUpdateFlag)
960 {
961 return SELECT_PARTITION_PAGE;
962 }
963
964 while(TRUE)
965 {
966 CONSOLE_ConInKey(Ir);
967
968 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
969 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
970 {
971 CONSOLE_NormalTextXY (24, Line, 48, 1);
972 if (Line == 14)
973 Line = 16;
974 else if (Line == 16)
975 Line = 11;
976 else
977 Line++;
978 CONSOLE_InvertTextXY (24, Line, 48, 1);
979 }
980 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
981 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
982 {
983 CONSOLE_NormalTextXY (24, Line, 48, 1);
984 if (Line == 11)
985 Line = 16;
986 else if (Line == 16)
987 Line = 14;
988 else
989 Line--;
990 CONSOLE_InvertTextXY (24, Line, 48, 1);
991 }
992 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
993 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
994 {
995 if (ConfirmQuit(Ir) == TRUE)
996 return QUIT_PAGE;
997 break;
998 }
999 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1000 {
1001 if (Line == 11)
1002 return COMPUTER_SETTINGS_PAGE;
1003 else if (Line == 12)
1004 return DISPLAY_SETTINGS_PAGE;
1005 else if (Line == 13)
1006 return KEYBOARD_SETTINGS_PAGE;
1007 else if (Line == 14)
1008 return LAYOUT_SETTINGS_PAGE;
1009 else if (Line == 16)
1010 return SELECT_PARTITION_PAGE;
1011 }
1012 }
1013
1014 return DEVICE_SETTINGS_PAGE;
1015 }
1016
1017
1018 static PAGE_NUMBER
1019 ComputerSettingsPage(PINPUT_RECORD Ir)
1020 {
1021 MUIDisplayPage(COMPUTER_SETTINGS_PAGE);
1022
1023 DrawGenericList(ComputerList,
1024 2,
1025 18,
1026 xScreen - 3,
1027 yScreen - 3);
1028
1029 SaveGenericListState(ComputerList);
1030
1031 while(TRUE)
1032 {
1033 CONSOLE_ConInKey(Ir);
1034
1035 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1036 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1037 {
1038 ScrollDownGenericList (ComputerList);
1039 }
1040 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1041 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1042 {
1043 ScrollUpGenericList (ComputerList);
1044 }
1045 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1046 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1047 {
1048 if (ConfirmQuit(Ir) == TRUE)
1049 return QUIT_PAGE;
1050 break;
1051 }
1052 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1053 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
1054 {
1055 RestoreGenericListState(ComputerList);
1056 return DEVICE_SETTINGS_PAGE;
1057 }
1058 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1059 {
1060 return DEVICE_SETTINGS_PAGE;
1061 }
1062 }
1063
1064 return COMPUTER_SETTINGS_PAGE;
1065 }
1066
1067
1068 static PAGE_NUMBER
1069 DisplaySettingsPage(PINPUT_RECORD Ir)
1070 {
1071 MUIDisplayPage(DISPLAY_SETTINGS_PAGE);
1072
1073 DrawGenericList(DisplayList,
1074 2,
1075 18,
1076 xScreen - 3,
1077 yScreen - 3);
1078
1079 SaveGenericListState(DisplayList);
1080
1081 while(TRUE)
1082 {
1083 CONSOLE_ConInKey(Ir);
1084
1085 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1086 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1087 {
1088 ScrollDownGenericList (DisplayList);
1089 }
1090 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1091 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1092 {
1093 ScrollUpGenericList (DisplayList);
1094 }
1095 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1096 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1097 {
1098 if (ConfirmQuit(Ir) == TRUE)
1099 {
1100 return QUIT_PAGE;
1101 }
1102 break;
1103 }
1104 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1105 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
1106 {
1107 RestoreGenericListState(DisplayList);
1108 return DEVICE_SETTINGS_PAGE;
1109 }
1110 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1111 {
1112 return DEVICE_SETTINGS_PAGE;
1113 }
1114 }
1115
1116 return DISPLAY_SETTINGS_PAGE;
1117 }
1118
1119
1120 static PAGE_NUMBER
1121 KeyboardSettingsPage(PINPUT_RECORD Ir)
1122 {
1123 MUIDisplayPage(KEYBOARD_SETTINGS_PAGE);
1124
1125 DrawGenericList(KeyboardList,
1126 2,
1127 18,
1128 xScreen - 3,
1129 yScreen - 3);
1130
1131
1132
1133 SaveGenericListState(KeyboardList);
1134
1135 while(TRUE)
1136 {
1137 CONSOLE_ConInKey(Ir);
1138
1139 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1140 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1141 {
1142 ScrollDownGenericList (KeyboardList);
1143 }
1144 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1145 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1146 {
1147 ScrollUpGenericList (KeyboardList);
1148 }
1149 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1150 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1151 {
1152 if (ConfirmQuit(Ir) == TRUE)
1153 return QUIT_PAGE;
1154 break;
1155 }
1156 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1157 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
1158 {
1159 RestoreGenericListState(KeyboardList);
1160 return DEVICE_SETTINGS_PAGE;
1161 }
1162 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1163 {
1164 return DEVICE_SETTINGS_PAGE;
1165 }
1166 }
1167
1168 return DISPLAY_SETTINGS_PAGE;
1169 }
1170
1171
1172 static PAGE_NUMBER
1173 LayoutSettingsPage(PINPUT_RECORD Ir)
1174 {
1175 MUIDisplayPage(LAYOUT_SETTINGS_PAGE);
1176
1177 DrawGenericList(LayoutList,
1178 2,
1179 15,
1180 xScreen - 3,
1181 yScreen - 3);
1182
1183 SaveGenericListState(LayoutList);
1184
1185 while(TRUE)
1186 {
1187 CONSOLE_ConInKey(Ir);
1188
1189 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1190 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1191 {
1192 ScrollDownGenericList (LayoutList);
1193 }
1194 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1195 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1196 {
1197 ScrollUpGenericList (LayoutList);
1198 }
1199 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1200 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1201 {
1202 if (ConfirmQuit(Ir) == TRUE)
1203 return QUIT_PAGE;
1204 break;
1205 }
1206 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1207 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
1208 {
1209 RestoreGenericListState(LayoutList);
1210 return DEVICE_SETTINGS_PAGE;
1211 }
1212 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1213 {
1214 return DEVICE_SETTINGS_PAGE;
1215 }
1216 }
1217
1218 return DISPLAY_SETTINGS_PAGE;
1219 }
1220
1221
1222 static PAGE_NUMBER
1223 SelectPartitionPage(PINPUT_RECORD Ir)
1224 {
1225 MUIDisplayPage(SELECT_PARTITION_PAGE);
1226
1227 if (PartitionList == NULL)
1228 {
1229 PartitionList = CreatePartitionList (2,
1230 19,
1231 xScreen - 3,
1232 yScreen - 3);
1233 if (PartitionList == NULL)
1234 {
1235 /* FIXME: show an error dialog */
1236 return QUIT_PAGE;
1237 }
1238 }
1239
1240 CheckActiveBootPartition (PartitionList);
1241
1242 DrawPartitionList (PartitionList);
1243
1244 /* Warn about partitions created by Linux Fdisk */
1245 if (WarnLinuxPartitions == TRUE &&
1246 CheckForLinuxFdiskPartitions (PartitionList) == TRUE)
1247 {
1248 MUIDisplayError(ERROR_WARN_PARTITION, NULL, POPUP_WAIT_NONE);
1249 while (TRUE)
1250 {
1251 CONSOLE_ConInKey (Ir);
1252
1253 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1254 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1255 {
1256 return QUIT_PAGE;
1257 }
1258 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
1259 {
1260 WarnLinuxPartitions = FALSE;
1261 return SELECT_PARTITION_PAGE;
1262 }
1263 }
1264 }
1265
1266 if (IsUnattendedSetup)
1267 {
1268 if (!SelectPartition(PartitionList, UnattendDestinationDiskNumber, UnattendDestinationPartitionNumber))
1269 {
1270 if (AutoPartition)
1271 {
1272 PPARTENTRY PartEntry = PartEntry = PartitionList->CurrentPartition;
1273 ULONG MaxSize = (PartEntry->UnpartitionedLength + (1 << 19)) >> 20; /* in MBytes (rounded) */
1274 CreateNewPartition (PartitionList,
1275 MaxSize,
1276 TRUE);
1277 return (SELECT_FILE_SYSTEM_PAGE);
1278 }
1279 }
1280 else
1281 {
1282 return(SELECT_FILE_SYSTEM_PAGE);
1283 }
1284 }
1285
1286 while(TRUE)
1287 {
1288 /* Update status text */
1289 if (PartitionList->CurrentPartition == NULL ||
1290 PartitionList->CurrentPartition->Unpartitioned == TRUE)
1291 {
1292 CONSOLE_SetStatusText (" ENTER = Install C = Create Partition F3 = Quit");
1293 }
1294 else
1295 {
1296 CONSOLE_SetStatusText (" ENTER = Install D = Delete Partition F3 = Quit");
1297 }
1298
1299 CONSOLE_ConInKey(Ir);
1300
1301 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1302 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1303 {
1304 if (ConfirmQuit(Ir) == TRUE)
1305 {
1306 DestroyPartitionList (PartitionList);
1307 PartitionList = NULL;
1308 return QUIT_PAGE;
1309 }
1310 break;
1311 }
1312 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1313 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1314 {
1315 ScrollDownPartitionList (PartitionList);
1316 }
1317 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1318 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1319 {
1320 ScrollUpPartitionList (PartitionList);
1321 }
1322 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
1323 {
1324 if (PartitionList->CurrentPartition == NULL ||
1325 PartitionList->CurrentPartition->Unpartitioned == TRUE)
1326 {
1327 CreateNewPartition (PartitionList,
1328 0ULL,
1329 TRUE);
1330 }
1331
1332 return SELECT_FILE_SYSTEM_PAGE;
1333 }
1334 else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'C') /* C */
1335 {
1336 if (PartitionList->CurrentPartition->Unpartitioned == FALSE)
1337 {
1338 MUIDisplayError(ERROR_NEW_PARTITION, Ir, POPUP_WAIT_ANY_KEY);
1339 return SELECT_PARTITION_PAGE;
1340 }
1341
1342 return CREATE_PARTITION_PAGE;
1343 }
1344 else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'D') /* D */
1345 {
1346 if (PartitionList->CurrentPartition->Unpartitioned == TRUE)
1347 {
1348 MUIDisplayError(ERROR_DELETE_SPACE, Ir, POPUP_WAIT_ANY_KEY);
1349 return SELECT_PARTITION_PAGE;
1350 }
1351
1352 return DELETE_PARTITION_PAGE;
1353 }
1354 }
1355
1356 return SELECT_PARTITION_PAGE;
1357 }
1358
1359
1360 static VOID
1361 DrawInputField(ULONG FieldLength,
1362 SHORT Left,
1363 SHORT Top,
1364 PCHAR FieldContent)
1365 {
1366 CHAR buf[100];
1367 COORD coPos;
1368 DWORD Written;
1369
1370 coPos.X = Left;
1371 coPos.Y = Top;
1372 memset(buf, '_', sizeof(buf));
1373 buf[FieldLength - strlen(FieldContent)] = 0;
1374 strcat(buf, FieldContent);
1375
1376 WriteConsoleOutputCharacterA (StdOutput,
1377 buf,
1378 strlen (buf),
1379 coPos,
1380 &Written);
1381 }
1382
1383
1384 #define PARTITION_SIZE_INPUT_FIELD_LENGTH 6
1385
1386 static VOID
1387 ShowPartitionSizeInputBox(SHORT Left,
1388 SHORT Top,
1389 SHORT Right,
1390 SHORT Bottom,
1391 ULONG MaxSize,
1392 PCHAR InputBuffer,
1393 PBOOLEAN Quit,
1394 PBOOLEAN Cancel)
1395 {
1396 INPUT_RECORD Ir;
1397 COORD coPos;
1398 DWORD Written;
1399 CHAR Buffer[100];
1400 ULONG Index;
1401 CHAR ch;
1402 SHORT iLeft;
1403 SHORT iTop;
1404
1405 if (Quit != NULL)
1406 *Quit = FALSE;
1407
1408 if (Cancel != NULL)
1409 *Cancel = FALSE;
1410
1411 DrawBox(Left, Top, Right - Left + 1, Bottom - Top + 1);
1412
1413 /* Print message */
1414 coPos.X = Left + 2;
1415 coPos.Y = Top + 2;
1416 strcpy (Buffer, "Size of new partition:");
1417 iLeft = coPos.X + strlen (Buffer) + 1;
1418 iTop = coPos.Y;
1419 WriteConsoleOutputCharacterA (StdOutput,
1420 Buffer,
1421 strlen (Buffer),
1422 coPos,
1423 &Written);
1424
1425 sprintf (Buffer, "MB (max. %lu MB)", MaxSize);
1426 coPos.X = iLeft + PARTITION_SIZE_INPUT_FIELD_LENGTH + 1;
1427 coPos.Y = iTop;
1428 WriteConsoleOutputCharacterA (StdOutput,
1429 Buffer,
1430 strlen (Buffer),
1431 coPos,
1432 &Written);
1433
1434 sprintf(Buffer, "%lu", MaxSize);
1435 Index = strlen(Buffer);
1436 DrawInputField (PARTITION_SIZE_INPUT_FIELD_LENGTH,
1437 iLeft,
1438 iTop,
1439 Buffer);
1440
1441 while (TRUE)
1442 {
1443 CONSOLE_ConInKey (&Ir);
1444
1445 if ((Ir.Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1446 (Ir.Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1447 {
1448 if (Quit != NULL)
1449 *Quit = TRUE;
1450 Buffer[0] = 0;
1451 break;
1452 }
1453 else if (Ir.Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
1454 {
1455 break;
1456 }
1457 else if (Ir.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESCAPE */
1458 {
1459 if (Cancel != NULL)
1460 *Cancel = TRUE;
1461 Buffer[0] = 0;
1462 break;
1463 }
1464 else if ((Ir.Event.KeyEvent.wVirtualKeyCode == VK_BACK) && /* BACKSPACE */
1465 (Index > 0))
1466 {
1467 Index--;
1468 Buffer[Index] = 0;
1469 DrawInputField (PARTITION_SIZE_INPUT_FIELD_LENGTH,
1470 iLeft,
1471 iTop,
1472 Buffer);
1473 }
1474 else if ((Ir.Event.KeyEvent.uChar.AsciiChar != 0x00) &&
1475 (Index < PARTITION_SIZE_INPUT_FIELD_LENGTH))
1476 {
1477 ch = Ir.Event.KeyEvent.uChar.AsciiChar;
1478 if ((ch >= '0') && (ch <= '9'))
1479 {
1480 Buffer[Index] = ch;
1481 Index++;
1482 Buffer[Index] = 0;
1483 DrawInputField (PARTITION_SIZE_INPUT_FIELD_LENGTH,
1484 iLeft,
1485 iTop,
1486 Buffer);
1487 }
1488 }
1489 }
1490
1491 strcpy (InputBuffer,
1492 Buffer);
1493 }
1494
1495
1496 static PAGE_NUMBER
1497 CreatePartitionPage (PINPUT_RECORD Ir)
1498 {
1499 PDISKENTRY DiskEntry;
1500 PPARTENTRY PartEntry;
1501 BOOLEAN Quit;
1502 BOOLEAN Cancel;
1503 CHAR InputBuffer[50];
1504 ULONG MaxSize;
1505 ULONGLONG PartSize;
1506 ULONGLONG DiskSize;
1507 PCHAR Unit;
1508
1509 if (PartitionList == NULL ||
1510 PartitionList->CurrentDisk == NULL ||
1511 PartitionList->CurrentPartition == NULL)
1512 {
1513 /* FIXME: show an error dialog */
1514 return QUIT_PAGE;
1515 }
1516
1517 DiskEntry = PartitionList->CurrentDisk;
1518 PartEntry = PartitionList->CurrentPartition;
1519
1520 CONSOLE_SetStatusText (" Please wait...");
1521
1522 CONSOLE_SetTextXY (6, 8, "You have chosen to create a new partition on");
1523
1524 #if 0
1525 if (DiskEntry->DiskSize >= 0x280000000ULL) /* 10 GB */
1526 {
1527 DiskSize = (DiskEntry->DiskSize + (1 << 29)) >> 30;
1528 Unit = "GB";
1529 }
1530 else
1531 #endif
1532 {
1533 DiskSize = (DiskEntry->DiskSize + (1 << 19)) >> 20;
1534 if (DiskSize == 0)
1535 DiskSize = 1;
1536 Unit = "MB";
1537 }
1538
1539 if (DiskEntry->DriverName.Length > 0)
1540 {
1541 CONSOLE_PrintTextXY (6, 10,
1542 "%I64u %s Harddisk %lu (Port=%hu, Bus=%hu, Id=%hu) on %wZ.",
1543 DiskSize,
1544 Unit,
1545 DiskEntry->DiskNumber,
1546 DiskEntry->Port,
1547 DiskEntry->Bus,
1548 DiskEntry->Id,
1549 &DiskEntry->DriverName);
1550 }
1551 else
1552 {
1553 CONSOLE_PrintTextXY (6, 10,
1554 "%I64u %s Harddisk %lu (Port=%hu, Bus=%hu, Id=%hu).",
1555 DiskSize,
1556 Unit,
1557 DiskEntry->DiskNumber,
1558 DiskEntry->Port,
1559 DiskEntry->Bus,
1560 DiskEntry->Id);
1561 }
1562
1563
1564 CONSOLE_SetTextXY (6, 12, "Please enter the size of the new partition in megabytes.");
1565
1566 #if 0
1567 CONSOLE_PrintTextXY (8, 10, "Maximum size of the new partition is %I64u MB",
1568 PartitionList->CurrentPartition->UnpartitionedLength / (1024*1024));
1569 #endif
1570
1571 CONSOLE_SetStatusText (" ENTER = Create Partition ESC = Cancel F3 = Quit");
1572
1573 PartEntry = PartitionList->CurrentPartition;
1574 while (TRUE)
1575 {
1576 MaxSize = (PartEntry->UnpartitionedLength + (1 << 19)) >> 20; /* in MBytes (rounded) */
1577 ShowPartitionSizeInputBox (12, 14, xScreen - 12, 17, /* left, top, right, bottom */
1578 MaxSize, InputBuffer, &Quit, &Cancel);
1579 if (Quit == TRUE)
1580 {
1581 if (ConfirmQuit (Ir) == TRUE)
1582 {
1583 return QUIT_PAGE;
1584 }
1585 }
1586 else if (Cancel == TRUE)
1587 {
1588 return SELECT_PARTITION_PAGE;
1589 }
1590 else
1591 {
1592 PartSize = atoi (InputBuffer);
1593 if (PartSize < 1)
1594 {
1595 /* Too small */
1596 continue;
1597 }
1598
1599 if (PartSize > MaxSize)
1600 {
1601 /* Too large */
1602 continue;
1603 }
1604
1605 /* Convert to bytes */
1606 if (PartSize == MaxSize)
1607 {
1608 /* Use all of the unpartitioned disk space */
1609 PartSize = PartEntry->UnpartitionedLength;
1610 }
1611 else
1612 {
1613 /* Round-up by cylinder size */
1614 PartSize = ROUND_UP (PartSize * 1024 * 1024,
1615 DiskEntry->CylinderSize);
1616
1617 /* But never get larger than the unpartitioned disk space */
1618 if (PartSize > PartEntry->UnpartitionedLength)
1619 PartSize = PartEntry->UnpartitionedLength;
1620 }
1621
1622 DPRINT ("Partition size: %I64u bytes\n", PartSize);
1623
1624 CreateNewPartition (PartitionList,
1625 PartSize,
1626 FALSE);
1627
1628 return SELECT_PARTITION_PAGE;
1629 }
1630 }
1631
1632 return CREATE_PARTITION_PAGE;
1633 }
1634
1635
1636 static PAGE_NUMBER
1637 DeletePartitionPage (PINPUT_RECORD Ir)
1638 {
1639 PDISKENTRY DiskEntry;
1640 PPARTENTRY PartEntry;
1641 ULONGLONG DiskSize;
1642 ULONGLONG PartSize;
1643 PCHAR Unit;
1644 PCHAR PartType;
1645
1646 if (PartitionList == NULL ||
1647 PartitionList->CurrentDisk == NULL ||
1648 PartitionList->CurrentPartition == NULL)
1649 {
1650 /* FIXME: show an error dialog */
1651 return QUIT_PAGE;
1652 }
1653
1654 DiskEntry = PartitionList->CurrentDisk;
1655 PartEntry = PartitionList->CurrentPartition;
1656
1657 MUIDisplayPage(DELETE_PARTITION_PAGE);
1658
1659 /* Determine partition type */
1660 PartType = NULL;
1661 if (PartEntry->New == TRUE)
1662 {
1663 PartType = "New (Unformatted)";
1664 }
1665 else if (PartEntry->Unpartitioned == FALSE)
1666 {
1667 if ((PartEntry->PartInfo[0].PartitionType == PARTITION_FAT_12) ||
1668 (PartEntry->PartInfo[0].PartitionType == PARTITION_FAT_16) ||
1669 (PartEntry->PartInfo[0].PartitionType == PARTITION_HUGE) ||
1670 (PartEntry->PartInfo[0].PartitionType == PARTITION_XINT13))
1671 {
1672 PartType = "FAT";
1673 }
1674 else if ((PartEntry->PartInfo[0].PartitionType == PARTITION_FAT32) ||
1675 (PartEntry->PartInfo[0].PartitionType == PARTITION_FAT32_XINT13))
1676 {
1677 PartType = "FAT32";
1678 }
1679 else if (PartEntry->PartInfo[0].PartitionType == PARTITION_IFS)
1680 {
1681 PartType = "NTFS"; /* FIXME: Not quite correct! */
1682 }
1683 }
1684
1685 #if 0
1686 if (PartEntry->PartInfo[0].PartitionLength.QuadPart >= 0x280000000LL) /* 10 GB */
1687 {
1688 PartSize = (PartEntry->PartInfo[0].PartitionLength.QuadPart + (1 << 29)) >> 30;
1689 Unit = "GB";
1690 }
1691 else
1692 #endif
1693 if (PartEntry->PartInfo[0].PartitionLength.QuadPart >= 0xA00000LL) /* 10 MB */
1694 {
1695 PartSize = (PartEntry->PartInfo[0].PartitionLength.QuadPart + (1 << 19)) >> 20;
1696 Unit = "MB";
1697 }
1698 else
1699 {
1700 PartSize = (PartEntry->PartInfo[0].PartitionLength.QuadPart + (1 << 9)) >> 10;
1701 Unit = "KB";
1702 }
1703
1704 if (PartType == NULL)
1705 {
1706 CONSOLE_PrintTextXY (6, 10,
1707 " %c%c Type %lu %I64u %s",
1708 (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
1709 (PartEntry->DriveLetter == 0) ? '-' : ':',
1710 PartEntry->PartInfo[0].PartitionType,
1711 PartSize,
1712 Unit);
1713 }
1714 else
1715 {
1716 CONSOLE_PrintTextXY (6, 10,
1717 " %c%c %s %I64u %s",
1718 (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
1719 (PartEntry->DriveLetter == 0) ? '-' : ':',
1720 PartType,
1721 PartSize,
1722 Unit);
1723 }
1724
1725 #if 0
1726 if (DiskEntry->DiskSize >= 0x280000000ULL) /* 10 GB */
1727 {
1728 DiskSize = (DiskEntry->DiskSize + (1 << 29)) >> 30;
1729 Unit = "GB";
1730 }
1731 else
1732 #endif
1733 {
1734 DiskSize = (DiskEntry->DiskSize + (1 << 19)) >> 20;
1735 if (DiskSize == 0)
1736 DiskSize = 1;
1737 Unit = "MB";
1738 }
1739
1740 if (DiskEntry->DriverName.Length > 0)
1741 {
1742 CONSOLE_PrintTextXY (6, 12,
1743 "on %I64u %s Harddisk %lu (Port=%hu, Bus=%hu, Id=%hu) on %wZ.",
1744 DiskSize,
1745 Unit,
1746 DiskEntry->DiskNumber,
1747 DiskEntry->Port,
1748 DiskEntry->Bus,
1749 DiskEntry->Id,
1750 &DiskEntry->DriverName);
1751 }
1752 else
1753 {
1754 CONSOLE_PrintTextXY (6, 12,
1755 "on %I64u %s Harddisk %lu (Port=%hu, Bus=%hu, Id=%hu).",
1756 DiskSize,
1757 Unit,
1758 DiskEntry->DiskNumber,
1759 DiskEntry->Port,
1760 DiskEntry->Bus,
1761 DiskEntry->Id);
1762 }
1763
1764 while (TRUE)
1765 {
1766 CONSOLE_ConInKey (Ir);
1767
1768 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1769 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1770 {
1771 if (ConfirmQuit (Ir) == TRUE)
1772 {
1773 return QUIT_PAGE;
1774 }
1775 break;
1776 }
1777 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESC */
1778 {
1779 return SELECT_PARTITION_PAGE;
1780 }
1781 else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'D') /* D */
1782 {
1783 DeleteCurrentPartition (PartitionList);
1784
1785 return SELECT_PARTITION_PAGE;
1786 }
1787 }
1788
1789 return DELETE_PARTITION_PAGE;
1790 }
1791
1792
1793 static PAGE_NUMBER
1794 SelectFileSystemPage (PINPUT_RECORD Ir)
1795 {
1796 PDISKENTRY DiskEntry;
1797 PPARTENTRY PartEntry;
1798 ULONGLONG DiskSize;
1799 ULONGLONG PartSize;
1800 PCHAR DiskUnit;
1801 PCHAR PartUnit;
1802 PCHAR PartType;
1803
1804 if (PartitionList == NULL ||
1805 PartitionList->CurrentDisk == NULL ||
1806 PartitionList->CurrentPartition == NULL)
1807 {
1808 /* FIXME: show an error dialog */
1809 return QUIT_PAGE;
1810 }
1811
1812 DiskEntry = PartitionList->CurrentDisk;
1813 PartEntry = PartitionList->CurrentPartition;
1814
1815 /* adjust disk size */
1816 if (DiskEntry->DiskSize >= 0x280000000ULL) /* 10 GB */
1817 {
1818 DiskSize = (DiskEntry->DiskSize + (1 << 29)) >> 30;
1819 DiskUnit = "GB";
1820 }
1821 else
1822 {
1823 DiskSize = (DiskEntry->DiskSize + (1 << 19)) >> 20;
1824 DiskUnit = "MB";
1825 }
1826
1827 /* adjust partition size */
1828 if (PartEntry->PartInfo[0].PartitionLength.QuadPart >= 0x280000000LL) /* 10 GB */
1829 {
1830 PartSize = (PartEntry->PartInfo[0].PartitionLength.QuadPart + (1 << 29)) >> 30;
1831 PartUnit = "GB";
1832 }
1833 else
1834 {
1835 PartSize = (PartEntry->PartInfo[0].PartitionLength.QuadPart + (1 << 19)) >> 20;
1836 PartUnit = "MB";
1837 }
1838
1839 /* adjust partition type */
1840 if ((PartEntry->PartInfo[0].PartitionType == PARTITION_FAT_12) ||
1841 (PartEntry->PartInfo[0].PartitionType == PARTITION_FAT_16) ||
1842 (PartEntry->PartInfo[0].PartitionType == PARTITION_HUGE) ||
1843 (PartEntry->PartInfo[0].PartitionType == PARTITION_XINT13))
1844 {
1845 PartType = "FAT";
1846 }
1847 else if ((PartEntry->PartInfo[0].PartitionType == PARTITION_FAT32) ||
1848 (PartEntry->PartInfo[0].PartitionType == PARTITION_FAT32_XINT13))
1849 {
1850 PartType = "FAT32";
1851 }
1852 else if (PartEntry->PartInfo[0].PartitionType == PARTITION_IFS)
1853 {
1854 PartType = "NTFS"; /* FIXME: Not quite correct! */
1855 }
1856 else if (PartEntry->PartInfo[0].PartitionType == PARTITION_ENTRY_UNUSED)
1857 {
1858 PartType = "Unused";
1859 }
1860 else
1861 {
1862 PartType = "Unknown";
1863 }
1864
1865 if (PartEntry->AutoCreate == TRUE)
1866 {
1867 CONSOLE_SetTextXY(6, 8, "Setup created a new partition on");
1868
1869 #if 0
1870 CONSOLE_PrintTextXY(8, 10, "Partition %lu (%I64u %s) %s of",
1871 PartEntry->PartInfo[0].PartitionNumber,
1872 PartSize,
1873 PartUnit,
1874 PartType);
1875 #endif
1876
1877 CONSOLE_PrintTextXY(8, 10, "Harddisk %lu (%I64u %s), Port=%hu, Bus=%hu, Id=%hu (%wZ).",
1878 DiskEntry->DiskNumber,
1879 DiskSize,
1880 DiskUnit,
1881 DiskEntry->Port,
1882 DiskEntry->Bus,
1883 DiskEntry->Id,
1884 &DiskEntry->DriverName);
1885
1886 CONSOLE_SetTextXY(6, 12, "This Partition will be formatted next.");
1887
1888
1889 PartEntry->AutoCreate = FALSE;
1890 }
1891 else if (PartEntry->New == TRUE)
1892 {
1893 CONSOLE_SetTextXY(6, 8, "You chose to install ReactOS on a new or unformatted Partition.");
1894 CONSOLE_SetTextXY(6, 10, "This Partition will be formatted next.");
1895 }
1896 else
1897 {
1898 CONSOLE_SetTextXY(6, 8, "Setup install ReactOS onto Partition");
1899
1900 if (PartType == NULL)
1901 {
1902 CONSOLE_PrintTextXY (8, 10,
1903 "%c%c Type %lu %I64u %s",
1904 (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
1905 (PartEntry->DriveLetter == 0) ? '-' : ':',
1906 PartEntry->PartInfo[0].PartitionType,
1907 PartSize,
1908 PartUnit);
1909 }
1910 else
1911 {
1912 CONSOLE_PrintTextXY (8, 10,
1913 "%c%c %s %I64u %s",
1914 (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
1915 (PartEntry->DriveLetter == 0) ? '-' : ':',
1916 PartType,
1917 PartSize,
1918 PartUnit);
1919 }
1920
1921 CONSOLE_PrintTextXY(6, 12, "on Harddisk %lu (%I64u %s), Port=%hu, Bus=%hu, Id=%hu (%wZ).",
1922 DiskEntry->DiskNumber,
1923 DiskSize,
1924 DiskUnit,
1925 DiskEntry->Port,
1926 DiskEntry->Bus,
1927 DiskEntry->Id,
1928 &DiskEntry->DriverName);
1929 }
1930
1931 MUIDisplayPage(SELECT_FILE_SYSTEM_PAGE);
1932
1933 if (FileSystemList == NULL)
1934 {
1935 FileSystemList = CreateFileSystemList (6, 26, PartEntry->New, L"FAT");
1936 if (FileSystemList == NULL)
1937 {
1938 /* FIXME: show an error dialog */
1939 return QUIT_PAGE;
1940 }
1941
1942 /* FIXME: Add file systems to list */
1943 }
1944 DrawFileSystemList (FileSystemList);
1945
1946 if (RepairUpdateFlag)
1947 {
1948 return (CHECK_FILE_SYSTEM_PAGE);
1949 //return SELECT_PARTITION_PAGE;
1950 }
1951
1952 if (IsUnattendedSetup)
1953 {
1954 if (UnattendFormatPartition)
1955 {
1956 return FORMAT_PARTITION_PAGE;
1957 }
1958 return(CHECK_FILE_SYSTEM_PAGE);
1959 }
1960
1961 while (TRUE)
1962 {
1963 CONSOLE_ConInKey (Ir);
1964
1965 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1966 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1967 {
1968 if (ConfirmQuit (Ir) == TRUE)
1969 {
1970 return QUIT_PAGE;
1971 }
1972 break;
1973 }
1974 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1975 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
1976 {
1977 return SELECT_PARTITION_PAGE;
1978 }
1979 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1980 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1981 {
1982 ScrollDownFileSystemList (FileSystemList);
1983 }
1984 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1985 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1986 {
1987 ScrollUpFileSystemList (FileSystemList);
1988 }
1989 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
1990 {
1991 if (!FileSystemList->Selected->FormatFunc)
1992 {
1993 return CHECK_FILE_SYSTEM_PAGE;
1994 }
1995 else
1996 {
1997 return FORMAT_PARTITION_PAGE;
1998 }
1999 }
2000 }
2001
2002 return SELECT_FILE_SYSTEM_PAGE;
2003 }
2004
2005
2006 static ULONG
2007 FormatPartitionPage (PINPUT_RECORD Ir)
2008 {
2009 WCHAR PathBuffer[MAX_PATH];
2010 PDISKENTRY DiskEntry;
2011 PPARTENTRY PartEntry;
2012 NTSTATUS Status;
2013
2014 #ifndef NDEBUG
2015 ULONG Line;
2016 ULONG i;
2017 PLIST_ENTRY Entry;
2018 #endif
2019
2020 MUIDisplayPage(FORMAT_PARTITION_PAGE);
2021
2022 if (PartitionList == NULL ||
2023 PartitionList->CurrentDisk == NULL ||
2024 PartitionList->CurrentPartition == NULL)
2025 {
2026 /* FIXME: show an error dialog */
2027 return QUIT_PAGE;
2028 }
2029
2030 DiskEntry = PartitionList->CurrentDisk;
2031 PartEntry = PartitionList->CurrentPartition;
2032
2033 while(TRUE)
2034 {
2035 if (!IsUnattendedSetup)
2036 {
2037 CONSOLE_ConInKey(Ir);
2038 }
2039
2040 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2041 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
2042 {
2043 if (ConfirmQuit (Ir) == TRUE)
2044 {
2045 return QUIT_PAGE;
2046 }
2047 break;
2048 }
2049 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN || IsUnattendedSetup) /* ENTER */
2050 {
2051 CONSOLE_SetStatusText (" Please wait ...");
2052
2053 if (PartEntry->PartInfo[0].PartitionType == PARTITION_ENTRY_UNUSED)
2054 {
2055 if (wcscmp(FileSystemList->Selected->FileSystem, L"FAT") == 0)
2056 {
2057 if (PartEntry->PartInfo[0].PartitionLength.QuadPart < (4200LL * 1024LL))
2058 {
2059 /* FAT12 CHS partition (disk is smaller than 4.1MB) */
2060 PartEntry->PartInfo[0].PartitionType = PARTITION_FAT_12;
2061 }
2062 else if (PartEntry->PartInfo[0].StartingOffset.QuadPart < (1024LL * 255LL * 63LL * 512LL))
2063 {
2064 /* Partition starts below the 8.4GB boundary ==> CHS partition */
2065
2066 if (PartEntry->PartInfo[0].PartitionLength.QuadPart < (32LL * 1024LL * 1024LL))
2067 {
2068 /* FAT16 CHS partition (partiton size < 32MB) */
2069 PartEntry->PartInfo[0].PartitionType = PARTITION_FAT_16;
2070 }
2071 else if (PartEntry->PartInfo[0].PartitionLength.QuadPart < (512LL * 1024LL * 1024LL))
2072 {
2073 /* FAT16 CHS partition (partition size < 512MB) */
2074 PartEntry->PartInfo[0].PartitionType = PARTITION_HUGE;
2075 }
2076 else
2077 {
2078 /* FAT32 CHS partition (partition size >= 512MB) */
2079 PartEntry->PartInfo[0].PartitionType = PARTITION_FAT32;
2080 }
2081 }
2082 else
2083 {
2084 /* Partition starts above the 8.4GB boundary ==> LBA partition */
2085
2086 if (PartEntry->PartInfo[0].PartitionLength.QuadPart < (512LL * 1024LL * 1024LL))
2087 {
2088 /* FAT16 LBA partition (partition size < 512MB) */
2089 PartEntry->PartInfo[0].PartitionType = PARTITION_XINT13;
2090 }
2091 else
2092 {
2093 /* FAT32 LBA partition (partition size >= 512MB) */
2094 PartEntry->PartInfo[0].PartitionType = PARTITION_FAT32_XINT13;
2095 }
2096 }
2097 }
2098 else if (!FileSystemList->Selected->FormatFunc)
2099 return QUIT_PAGE;
2100 }
2101
2102 CheckActiveBootPartition (PartitionList);
2103
2104 #ifndef NDEBUG
2105 CONSOLE_PrintTextXY (6, 12,
2106 "Disk: %I64u Cylinder: %I64u Track: %I64u",
2107 DiskEntry->DiskSize,
2108 DiskEntry->CylinderSize,
2109 DiskEntry->TrackSize);
2110
2111 Line = 13;
2112 DiskEntry = PartitionList->CurrentDisk;
2113 Entry = DiskEntry->PartListHead.Flink;
2114 while (Entry != &DiskEntry->PartListHead)
2115 {
2116 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
2117
2118 if (PartEntry->Unpartitioned == FALSE)
2119 {
2120
2121 for (i = 0; i < 4; i++)
2122 {
2123 CONSOLE_PrintTextXY (6, Line,
2124 "%2u: %2u %c %12I64u %12I64u %2u %c",
2125 i,
2126 PartEntry->PartInfo[i].PartitionNumber,
2127 PartEntry->PartInfo[i].BootIndicator ? 'A' : '-',
2128 PartEntry->PartInfo[i].StartingOffset.QuadPart,
2129 PartEntry->PartInfo[i].PartitionLength.QuadPart,
2130 PartEntry->PartInfo[i].PartitionType,
2131 PartEntry->PartInfo[i].RewritePartition ? '*' : ' ');
2132
2133 Line++;
2134 }
2135
2136 Line++;
2137 }
2138
2139 Entry = Entry->Flink;
2140 }
2141
2142 /* Restore the old entry */
2143 PartEntry = PartitionList->CurrentPartition;
2144 #endif
2145
2146 if (WritePartitionsToDisk (PartitionList) == FALSE)
2147 {
2148 DPRINT ("WritePartitionsToDisk() failed\n");
2149 MUIDisplayError(ERROR_WRITE_PTABLE, Ir, POPUP_WAIT_ENTER);
2150 return QUIT_PAGE;
2151 }
2152
2153 /* Set DestinationRootPath */
2154 RtlFreeUnicodeString (&DestinationRootPath);
2155 swprintf (PathBuffer,
2156 L"\\Device\\Harddisk%lu\\Partition%lu",
2157 PartitionList->CurrentDisk->DiskNumber,
2158 PartitionList->CurrentPartition->PartInfo[0].PartitionNumber);
2159 RtlCreateUnicodeString (&DestinationRootPath,
2160 PathBuffer);
2161 DPRINT ("DestinationRootPath: %wZ\n", &DestinationRootPath);
2162
2163
2164 /* Set SystemRootPath */
2165 RtlFreeUnicodeString (&SystemRootPath);
2166 swprintf (PathBuffer,
2167 L"\\Device\\Harddisk%lu\\Partition%lu",
2168 PartitionList->ActiveBootDisk->DiskNumber,
2169 PartitionList->ActiveBootPartition->PartInfo[0].PartitionNumber);
2170 RtlCreateUnicodeString (&SystemRootPath,
2171 PathBuffer);
2172 DPRINT ("SystemRootPath: %wZ\n", &SystemRootPath);
2173
2174
2175 if (FileSystemList->Selected->FormatFunc)
2176 {
2177 Status = FormatPartition(&DestinationRootPath, FileSystemList->Selected);
2178 if (!NT_SUCCESS(Status))
2179 {
2180 DPRINT1("FormatPartition() failed with status 0x%08lx\n", Status);
2181 /* FIXME: show an error dialog */
2182 return QUIT_PAGE;
2183 }
2184
2185 PartEntry->New = FALSE;
2186
2187 CheckActiveBootPartition(PartitionList);
2188 }
2189
2190 if (wcscmp(FileSystemList->Selected->FileSystem, L"FAT") == 0)
2191 {
2192 /* FIXME: Install boot code. This is a hack! */
2193 if ((PartEntry->PartInfo[0].PartitionType == PARTITION_FAT32_XINT13)
2194 || (PartEntry->PartInfo[0].PartitionType == PARTITION_FAT32))
2195 {
2196 wcscpy(PathBuffer, SourceRootPath.Buffer);
2197 wcscat(PathBuffer, L"\\loader\\fat32.bin");
2198
2199 DPRINT("Install FAT32 bootcode: %S ==> %S\n", PathBuffer,
2200 DestinationRootPath.Buffer);
2201 Status = InstallFat32BootCodeToDisk(PathBuffer,
2202 DestinationRootPath.Buffer);
2203 if (!NT_SUCCESS(Status))
2204 {
2205 DPRINT1("InstallFat32BootCodeToDisk() failed with status 0x%08lx\n", Status);
2206 /* FIXME: show an error dialog */
2207 DestroyFileSystemList(FileSystemList);
2208 FileSystemList = NULL;
2209 return QUIT_PAGE;
2210 }
2211 }
2212 else
2213 {
2214 wcscpy(PathBuffer, SourceRootPath.Buffer);
2215 wcscat(PathBuffer, L"\\loader\\fat.bin");
2216
2217 DPRINT("Install FAT bootcode: %S ==> %S\n", PathBuffer,
2218 DestinationRootPath.Buffer);
2219 Status = InstallFat16BootCodeToDisk(PathBuffer,
2220 DestinationRootPath.Buffer);
2221 if (!NT_SUCCESS(Status))
2222 {
2223 DPRINT1("InstallFat16BootCodeToDisk() failed with status 0x%.08x\n", Status);
2224 /* FIXME: show an error dialog */
2225 DestroyFileSystemList(FileSystemList);
2226 FileSystemList = NULL;
2227 return QUIT_PAGE;
2228 }
2229 }
2230 }
2231 else if (FileSystemList->Selected->FormatFunc)
2232 {
2233 DestroyFileSystemList(FileSystemList);
2234 FileSystemList = NULL;
2235 return QUIT_PAGE;
2236 }
2237
2238 #ifndef NDEBUG
2239 CONSOLE_SetStatusText (" Done. Press any key ...");
2240 CONSOLE_ConInKey(Ir);
2241 #endif
2242
2243 DestroyFileSystemList(FileSystemList);
2244 FileSystemList = NULL;
2245 return INSTALL_DIRECTORY_PAGE;
2246 }
2247 }
2248
2249 return FORMAT_PARTITION_PAGE;
2250 }
2251
2252
2253 static ULONG
2254 CheckFileSystemPage(PINPUT_RECORD Ir)
2255 {
2256 PFILE_SYSTEM_ITEM CurrentFileSystem;
2257 WCHAR PathBuffer[MAX_PATH];
2258 CHAR Buffer[MAX_PATH];
2259 NTSTATUS Status;
2260
2261 /* FIXME: code duplicated in FormatPartitionPage */
2262 /* Set DestinationRootPath */
2263 RtlFreeUnicodeString(&DestinationRootPath);
2264 swprintf(PathBuffer,
2265 L"\\Device\\Harddisk%lu\\Partition%lu",
2266 PartitionList->CurrentDisk->DiskNumber,
2267 PartitionList->CurrentPartition->PartInfo[0].PartitionNumber);
2268 RtlCreateUnicodeString(&DestinationRootPath, PathBuffer);
2269 DPRINT("DestinationRootPath: %wZ\n", &DestinationRootPath);
2270
2271 /* Set SystemRootPath */
2272 RtlFreeUnicodeString(&SystemRootPath);
2273 swprintf(PathBuffer,
2274 L"\\Device\\Harddisk%lu\\Partition%lu",
2275 PartitionList->ActiveBootDisk->DiskNumber,
2276 PartitionList->ActiveBootPartition->PartInfo[0].PartitionNumber);
2277 RtlCreateUnicodeString(&SystemRootPath, PathBuffer);
2278 DPRINT("SystemRootPath: %wZ\n", &SystemRootPath);
2279
2280 CONSOLE_SetTextXY(6, 8, "Setup is now checking the selected partition.");
2281
2282 CONSOLE_SetStatusText(" Please wait...");
2283
2284 /* WRONG: first filesystem is not necesseraly the one of the current partition! */
2285 CurrentFileSystem = CONTAINING_RECORD(FileSystemList->ListHead.Flink, FILE_SYSTEM_ITEM, ListEntry);
2286
2287 if (!CurrentFileSystem->ChkdskFunc)
2288 {
2289 sprintf(Buffer,
2290 "Setup is currently unable to check a partition formatted in %S.\n"
2291 "\n"
2292 " \x07 Press ENTER to continue Setup.\n"
2293 " \x07 Press F3 to quit Setup.",
2294 CurrentFileSystem->FileSystem);
2295 PopupError(
2296 Buffer,
2297 "F3= Quit ENTER = Continue",
2298 NULL, POPUP_WAIT_NONE);
2299
2300 while(TRUE)
2301 {
2302 CONSOLE_ConInKey(Ir);
2303
2304 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x00
2305 && Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3) /* F3 */
2306 {
2307 if (ConfirmQuit(Ir))
2308 return QUIT_PAGE;
2309 else
2310 return CHECK_FILE_SYSTEM_PAGE;
2311 }
2312 else if (Ir->Event.KeyEvent.uChar.AsciiChar == VK_RETURN) /* ENTER */
2313 {
2314 return INSTALL_DIRECTORY_PAGE;
2315 }
2316 }
2317 }
2318 else
2319 {
2320 Status = ChkdskPartition(&DestinationRootPath, CurrentFileSystem);
2321 if (!NT_SUCCESS(Status))
2322 {
2323 DPRINT("ChkdskPartition() failed with status 0x%08lx\n", Status);
2324 sprintf(Buffer, "Setup failed to verify the selected partition.\n"
2325 "(Status 0x%08lx).\n", Status);
2326 PopupError(Buffer,
2327 "ENTER = Reboot computer",
2328 Ir, POPUP_WAIT_ENTER);
2329 return QUIT_PAGE;
2330 }
2331
2332 return INSTALL_DIRECTORY_PAGE;
2333 }
2334 }
2335
2336
2337 static PAGE_NUMBER
2338 InstallDirectoryPage1(PWCHAR InstallDir, PDISKENTRY DiskEntry, PPARTENTRY PartEntry)
2339 {
2340 WCHAR PathBuffer[MAX_PATH];
2341
2342 /* Create 'InstallPath' string */
2343 RtlFreeUnicodeString(&InstallPath);
2344 RtlCreateUnicodeString(&InstallPath,
2345 InstallDir);
2346
2347 /* Create 'DestinationPath' string */
2348 RtlFreeUnicodeString(&DestinationPath);
2349 wcscpy(PathBuffer,
2350 DestinationRootPath.Buffer);
2351 if (InstallDir[0] != L'\\')
2352 wcscat(PathBuffer,
2353 L"\\");
2354 wcscat(PathBuffer, InstallDir);
2355 RtlCreateUnicodeString(&DestinationPath,
2356 PathBuffer);
2357
2358 /* Create 'DestinationArcPath' */
2359 RtlFreeUnicodeString(&DestinationArcPath);
2360 swprintf(PathBuffer,
2361 L"multi(0)disk(0)rdisk(%lu)partition(%lu)",
2362 DiskEntry->BiosDiskNumber,
2363 PartEntry->PartInfo[0].PartitionNumber);
2364 if (InstallDir[0] != L'\\')
2365 wcscat(PathBuffer,
2366 L"\\");
2367 wcscat(PathBuffer, InstallDir);
2368 RtlCreateUnicodeString(&DestinationArcPath,
2369 PathBuffer);
2370
2371 return(PREPARE_COPY_PAGE);
2372 }
2373
2374
2375 static PAGE_NUMBER
2376 InstallDirectoryPage(PINPUT_RECORD Ir)
2377 {
2378 PDISKENTRY DiskEntry;
2379 PPARTENTRY PartEntry;
2380 WCHAR InstallDir[51];
2381 PWCHAR DefaultPath;
2382 INFCONTEXT Context;
2383 ULONG Length;
2384
2385 if (PartitionList == NULL ||
2386 PartitionList->CurrentDisk == NULL ||
2387 PartitionList->CurrentPartition == NULL)
2388 {
2389 /* FIXME: show an error dialog */
2390 return QUIT_PAGE;
2391 }
2392
2393 DiskEntry = PartitionList->CurrentDisk;
2394 PartEntry = PartitionList->CurrentPartition;
2395
2396 /* Search for 'DefaultPath' in the 'SetupData' section */
2397 if (!SetupFindFirstLineW (SetupInf, L"SetupData", L"DefaultPath", &Context))
2398 {
2399 MUIDisplayError(ERROR_FIND_SETUPDATA, Ir, POPUP_WAIT_ENTER);
2400 return QUIT_PAGE;
2401 }
2402
2403 /* Read the 'DefaultPath' data */
2404 if (INF_GetData (&Context, NULL, &DefaultPath))
2405 {
2406 wcscpy(InstallDir, DefaultPath);
2407 }
2408 else
2409 {
2410 wcscpy(InstallDir, L"\\ReactOS");
2411 }
2412 Length = wcslen(InstallDir);
2413 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
2414 MUIDisplayPage(INSTALL_DIRECTORY_PAGE);
2415
2416 if (IsUnattendedSetup)
2417 {
2418 return(InstallDirectoryPage1 (InstallDir, DiskEntry, PartEntry));
2419 }
2420
2421 while(TRUE)
2422 {
2423 CONSOLE_ConInKey(Ir);
2424
2425 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2426 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
2427 {
2428 if (ConfirmQuit(Ir) == TRUE)
2429 return(QUIT_PAGE);
2430 break;
2431 }
2432 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2433 {
2434 return (InstallDirectoryPage1 (InstallDir, DiskEntry, PartEntry));
2435 }
2436 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x08) /* BACKSPACE */
2437 {
2438 if (Length > 0)
2439 {
2440 Length--;
2441 InstallDir[Length] = 0;
2442 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
2443 }
2444 }
2445 else if (isprint(Ir->Event.KeyEvent.uChar.AsciiChar))
2446 {
2447 if (Length < 50)
2448 {
2449 InstallDir[Length] = (WCHAR)Ir->Event.KeyEvent.uChar.AsciiChar;
2450 Length++;
2451 InstallDir[Length] = 0;
2452 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
2453 }
2454 }
2455 }
2456
2457 return(INSTALL_DIRECTORY_PAGE);
2458 }
2459
2460 static BOOLEAN
2461 AddSectionToCopyQueueCab(HINF InfFile,
2462 PWCHAR SectionName,
2463 PWCHAR SourceCabinet,
2464 PCUNICODE_STRING DestinationPath,
2465 PINPUT_RECORD Ir)
2466 {
2467 INFCONTEXT FilesContext;
2468 INFCONTEXT DirContext;
2469 PWCHAR FileKeyName;
2470 PWCHAR FileKeyValue;
2471 PWCHAR DirKeyValue;
2472 PWCHAR TargetFileName;
2473
2474 /* Search for the SectionName section */
2475 if (!SetupFindFirstLineW (InfFile, SectionName, NULL, &FilesContext))
2476 {
2477 char Buffer[128];
2478 sprintf(Buffer, "Setup failed to find the '%S' section\nin TXTSETUP.SIF.\n", SectionName);
2479 PopupError(Buffer, "ENTER = Reboot computer", Ir, POPUP_WAIT_ENTER);
2480 return(FALSE);
2481 }
2482
2483 /*
2484 * Enumerate the files in the section
2485 * and add them to the file queue.
2486 */
2487 do
2488 {
2489 /* Get source file name and target directory id */
2490 if (!INF_GetData (&FilesContext, &FileKeyName, &FileKeyValue))
2491 {
2492 /* FIXME: Handle error! */
2493 DPRINT1("INF_GetData() failed\n");
2494 break;
2495 }
2496
2497 /* Get optional target file name */
2498 if (!INF_GetDataField (&FilesContext, 2, &TargetFileName))
2499 TargetFileName = NULL;
2500
2501 DPRINT ("FileKeyName: '%S' FileKeyValue: '%S'\n", FileKeyName, FileKeyValue);
2502
2503 /* Lookup target directory */
2504 if (!SetupFindFirstLineW (InfFile, L"Directories", FileKeyValue, &DirContext))
2505 {
2506 /* FIXME: Handle error! */
2507 DPRINT1("SetupFindFirstLine() failed\n");
2508 break;
2509 }
2510
2511 if (!INF_GetData (&DirContext, NULL, &DirKeyValue))
2512 {
2513 /* FIXME: Handle error! */
2514 DPRINT1("INF_GetData() failed\n");
2515 break;
2516 }
2517
2518 if (!SetupQueueCopy(SetupFileQueue,
2519 SourceCabinet,
2520 SourceRootPath.Buffer,
2521 SourceRootDir.Buffer,
2522 FileKeyName,
2523 DirKeyValue,
2524 TargetFileName))
2525 {
2526 /* FIXME: Handle error! */
2527 DPRINT1("SetupQueueCopy() failed\n");
2528 }
2529 }
2530 while (SetupFindNextLine(&FilesContext, &FilesContext));
2531
2532 return TRUE;
2533 }
2534
2535 static BOOLEAN
2536 AddSectionToCopyQueue(HINF InfFile,
2537 PWCHAR SectionName,
2538 PWCHAR SourceCabinet,
2539 PCUNICODE_STRING DestinationPath,
2540 PINPUT_RECORD Ir)
2541 {
2542 INFCONTEXT FilesContext;
2543 INFCONTEXT DirContext;
2544 PWCHAR FileKeyName;
2545 PWCHAR FileKeyValue;
2546 PWCHAR DirKeyValue;
2547 PWCHAR TargetFileName;
2548
2549 if (SourceCabinet)
2550 return AddSectionToCopyQueueCab(InfFile, L"SourceFiles", SourceCabinet, DestinationPath, Ir);
2551
2552 /* Search for the SectionName section */
2553 if (!SetupFindFirstLineW (InfFile, SectionName, NULL, &FilesContext))
2554 {
2555 char Buffer[128];
2556 sprintf(Buffer, "Setup failed to find the '%S' section\nin TXTSETUP.SIF.\n", SectionName);
2557 PopupError(Buffer, "ENTER = Reboot computer", Ir, POPUP_WAIT_ENTER);
2558 return(FALSE);
2559 }
2560
2561 /*
2562 * Enumerate the files in the section
2563 * and add them to the file queue.
2564 */
2565 do
2566 {
2567 /* Get source file name and target directory id */
2568 if (!INF_GetData (&FilesContext, &FileKeyName, &FileKeyValue))
2569 {
2570 /* FIXME: Handle error! */
2571 DPRINT1("INF_GetData() failed\n");
2572 break;
2573 }
2574
2575 /* Get target directory id */
2576 if (!INF_GetDataField (&FilesContext, 13, &FileKeyValue))
2577 {
2578 /* FIXME: Handle error! */
2579 DPRINT1("INF_GetData() failed\n");
2580 break;
2581 }
2582
2583 /* Get optional target file name */
2584 if (!INF_GetDataField (&FilesContext, 11, &TargetFileName))
2585 TargetFileName = NULL;
2586 else if (!*TargetFileName)
2587 TargetFileName = NULL;
2588
2589 DPRINT ("FileKeyName: '%S' FileKeyValue: '%S'\n", FileKeyName, FileKeyValue);
2590
2591 /* Lookup target directory */
2592 if (!SetupFindFirstLineW (InfFile, L"Directories", FileKeyValue, &DirContext))
2593 {
2594 /* FIXME: Handle error! */
2595 DPRINT1("SetupFindFirstLine() failed\n");
2596 break;
2597 }
2598
2599 if (!INF_GetData (&DirContext, NULL, &DirKeyValue))
2600 {
2601 /* FIXME: Handle error! */
2602 DPRINT1("INF_GetData() failed\n");
2603 break;
2604 }
2605
2606 if (!SetupQueueCopy(SetupFileQueue,
2607 SourceCabinet,
2608 SourceRootPath.Buffer,
2609 SourceRootDir.Buffer,
2610 FileKeyName,
2611 DirKeyValue,
2612 TargetFileName))
2613 {
2614 /* FIXME: Handle error! */
2615 DPRINT1("SetupQueueCopy() failed\n");
2616 }
2617 }
2618 while (SetupFindNextLine(&FilesContext, &FilesContext));
2619
2620 return TRUE;
2621 }
2622
2623 static BOOLEAN
2624 PrepareCopyPageInfFile(HINF InfFile,
2625 PWCHAR SourceCabinet,
2626 PINPUT_RECORD Ir)
2627 {
2628 WCHAR PathBuffer[MAX_PATH];
2629 INFCONTEXT DirContext;
2630 PWCHAR AdditionalSectionName = NULL;
2631 PWCHAR KeyValue;
2632 ULONG Length;
2633 NTSTATUS Status;
2634
2635 /* Add common files */
2636 if (!AddSectionToCopyQueue(InfFile, L"SourceDisksFiles", SourceCabinet, &DestinationPath, Ir))
2637 return FALSE;
2638
2639 /* Add specific files depending of computer type */
2640 if (SourceCabinet == NULL)
2641 {
2642 if (!ProcessComputerFiles(InfFile, ComputerList, &AdditionalSectionName))
2643 return FALSE;
2644 if (AdditionalSectionName)
2645 {
2646 if (!AddSectionToCopyQueue(InfFile, AdditionalSectionName, SourceCabinet, &DestinationPath, Ir))
2647 return FALSE;
2648 }
2649 }
2650
2651 /* Create directories */
2652
2653 /*
2654 * FIXME:
2655 * Install directories like '\reactos\test' are not handled yet.
2656 */
2657
2658 /* Get destination path */
2659 wcscpy(PathBuffer, DestinationPath.Buffer);
2660
2661 /* Remove trailing backslash */
2662 Length = wcslen(PathBuffer);
2663 if ((Length > 0) && (PathBuffer[Length - 1] == '\\'))
2664 {
2665 PathBuffer[Length - 1] = 0;
2666 }
2667
2668 /* Create the install directory */
2669 Status = SetupCreateDirectory(PathBuffer);
2670 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION)
2671 {
2672 DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer, Status);
2673 MUIDisplayError(ERROR_CREATE_INSTALL_DIR, Ir, POPUP_WAIT_ENTER);
2674 return(FALSE);
2675 }
2676
2677
2678 /* Search for the 'Directories' section */
2679 if (!SetupFindFirstLineW(InfFile, L"Directories", NULL, &DirContext))
2680 {
2681 if (SourceCabinet)
2682 {
2683 MUIDisplayError(ERROR_CABINET_SECTION, Ir, POPUP_WAIT_ENTER);
2684 }
2685 else
2686 {
2687 MUIDisplayError(ERROR_TXTSETUP_SECTION, Ir, POPUP_WAIT_ENTER);
2688 }
2689 return(FALSE);
2690 }
2691
2692 /* Enumerate the directory values and create the subdirectories */
2693 do
2694 {
2695 if (!INF_GetData (&DirContext, NULL, &KeyValue))
2696 {
2697 DPRINT1("break\n");
2698 break;
2699 }
2700
2701 if (KeyValue[0] == L'\\' && KeyValue[1] != 0)
2702 {
2703 DPRINT("Absolute Path: '%S'\n", KeyValue);
2704
2705 wcscpy(PathBuffer, DestinationRootPath.Buffer);
2706 wcscat(PathBuffer, KeyValue);
2707
2708 DPRINT("FullPath: '%S'\n", PathBuffer);
2709 }
2710 else if (KeyValue[0] != L'\\')
2711 {
2712 DPRINT("RelativePath: '%S'\n", KeyValue);
2713 wcscpy(PathBuffer, DestinationPath.Buffer);
2714 wcscat(PathBuffer, L"\\");
2715 wcscat(PathBuffer, KeyValue);
2716
2717 DPRINT("FullPath: '%S'\n", PathBuffer);
2718
2719 Status = SetupCreateDirectory(PathBuffer);
2720 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION)
2721 {
2722 DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer, Status);
2723 MUIDisplayError(ERROR_CREATE_DIR, Ir, POPUP_WAIT_ENTER);
2724 return(FALSE);
2725 }
2726 }
2727 }
2728 while (SetupFindNextLine (&DirContext, &DirContext));
2729
2730 return(TRUE);
2731 }
2732
2733 static PAGE_NUMBER
2734 PrepareCopyPage(PINPUT_RECORD Ir)
2735 {
2736 HINF InfHandle;
2737 WCHAR PathBuffer[MAX_PATH];
2738 INFCONTEXT CabinetsContext;
2739 ULONG InfFileSize;
2740 PWCHAR KeyValue;
2741 UINT ErrorLine;
2742 PVOID InfFileData;
2743
2744 MUIDisplayPage(PREPARE_COPY_PAGE);
2745
2746 /* Create the file queue */
2747 SetupFileQueue = SetupOpenFileQueue();
2748 if (SetupFileQueue == NULL)
2749 {
2750 MUIDisplayError(ERROR_COPY_QUEUE, Ir, POPUP_WAIT_ENTER);
2751 return(QUIT_PAGE);
2752 }
2753
2754 if (!PrepareCopyPageInfFile(SetupInf, NULL, Ir))
2755 {
2756 return QUIT_PAGE;
2757 }
2758
2759 /* Search for the 'Cabinets' section */
2760 if (!SetupFindFirstLineW (SetupInf, L"Cabinets", NULL, &CabinetsContext))
2761 {
2762 return FILE_COPY_PAGE;
2763 }
2764
2765 /*
2766 * Enumerate the directory values in the 'Cabinets'
2767 * section and parse their inf files.
2768 */
2769 do
2770 {
2771 if (!INF_GetData (&CabinetsContext, NULL, &KeyValue))
2772 break;
2773
2774 wcscpy(PathBuffer, SourcePath.Buffer);
2775 wcscat(PathBuffer, L"\\");
2776 wcscat(PathBuffer, KeyValue);
2777
2778 #ifdef __REACTOS__
2779 CabinetInitialize();
2780 CabinetSetEventHandlers(NULL, NULL, NULL);
2781 CabinetSetCabinetName(PathBuffer);
2782
2783 if (CabinetOpen() == CAB_STATUS_SUCCESS)
2784 {
2785 DPRINT("Cabinet %S\n", CabinetGetCabinetName());
2786
2787 InfFileData = CabinetGetCabinetReservedArea(&InfFileSize);
2788 if (InfFileData == NULL)
2789 {
2790 MUIDisplayError(ERROR_CABINET_SCRIPT, Ir, POPUP_WAIT_ENTER);
2791 return QUIT_PAGE;
2792 }
2793 }
2794 else
2795 {
2796 DPRINT("Cannot open cabinet: %S.\n", CabinetGetCabinetName());
2797 MUIDisplayError(ERROR_CABINET_MISSING, Ir, POPUP_WAIT_ENTER);
2798 return QUIT_PAGE;
2799 }
2800
2801 InfHandle = INF_OpenBufferedFileA((CHAR*) InfFileData,
2802 InfFileSize,
2803 (const CHAR*) NULL,
2804 INF_STYLE_WIN4,
2805 &ErrorLine);
2806 if (InfHandle == INVALID_HANDLE_VALUE)
2807 {
2808 MUIDisplayError(ERROR_INVALID_CABINET_INF, Ir, POPUP_WAIT_ENTER);
2809 return QUIT_PAGE;
2810 }
2811
2812 CabinetCleanup();
2813
2814 if (!PrepareCopyPageInfFile(InfHandle, KeyValue, Ir))
2815 {
2816 return QUIT_PAGE;
2817 }
2818 #endif
2819 }
2820 while (SetupFindNextLine (&CabinetsContext, &CabinetsContext));
2821
2822 return FILE_COPY_PAGE;
2823 }
2824
2825 VOID
2826 NTAPI
2827 SetupUpdateMemoryInfo(IN PCOPYCONTEXT CopyContext,
2828 IN BOOLEAN First)
2829 {
2830 SYSTEM_PERFORMANCE_INFORMATION PerfInfo;
2831
2832 /* Get the memory information from the system */
2833 NtQuerySystemInformation(SystemPerformanceInformation,
2834 &PerfInfo,
2835 sizeof(PerfInfo),
2836 NULL);
2837
2838 /* Check if this is initial setup */
2839 if (First)
2840 {
2841 /* Set maximum limits to be total RAM pages */
2842 ProgressSetStepCount(CopyContext->MemoryBars[0], PerfInfo.CommitLimit);
2843 ProgressSetStepCount(CopyContext->MemoryBars[1], PerfInfo.CommitLimit);
2844 ProgressSetStepCount(CopyContext->MemoryBars[2], PerfInfo.CommitLimit);
2845 }
2846
2847 /* Set current values */
2848 ProgressSetStep(CopyContext->MemoryBars[0], PerfInfo.PagedPoolPages);
2849 ProgressSetStep(CopyContext->MemoryBars[1], PerfInfo.NonPagedPoolPages);
2850 ProgressSetStep(CopyContext->MemoryBars[2], PerfInfo.AvailablePages);
2851
2852 /* Check if memory dropped below 40%! */
2853 if (CopyContext->MemoryBars[2]->Percent <= 40)
2854 {
2855 /* Wait a while until Mm does its thing */
2856 LARGE_INTEGER Interval;
2857 Interval.QuadPart = -1 * 15 * 1000 * 100;
2858 NtDelayExecution(FALSE, &Interval);
2859 }
2860 }
2861
2862 static UINT CALLBACK
2863 FileCopyCallback(PVOID Context,
2864 UINT Notification,
2865 UINT_PTR Param1,
2866 UINT_PTR Param2)
2867 {
2868 PCOPYCONTEXT CopyContext;
2869
2870 CopyContext = (PCOPYCONTEXT)Context;
2871
2872 switch (Notification)
2873 {
2874 case SPFILENOTIFY_STARTSUBQUEUE:
2875 CopyContext->TotalOperations = (ULONG)Param2;
2876 ProgressSetStepCount(CopyContext->ProgressBar,
2877 CopyContext->TotalOperations);
2878 SetupUpdateMemoryInfo(CopyContext, TRUE);
2879 break;
2880
2881 case SPFILENOTIFY_STARTCOPY:
2882 /* Display copy message */
2883 CONSOLE_SetStatusText(" \xB3 Copying file: %S", (PWSTR)Param1);
2884 SetupUpdateMemoryInfo(CopyContext, FALSE);
2885 break;
2886
2887 case SPFILENOTIFY_ENDCOPY:
2888 CopyContext->CompletedOperations++;
2889 ProgressNextStep(CopyContext->ProgressBar);
2890 SetupUpdateMemoryInfo(CopyContext, FALSE);
2891 break;
2892 }
2893
2894 return 0;
2895 }
2896
2897 static
2898 PAGE_NUMBER
2899 FileCopyPage(PINPUT_RECORD Ir)
2900 {
2901 COPYCONTEXT CopyContext;
2902
2903 MUIDisplayPage(FILE_COPY_PAGE);
2904
2905 /* Create context for the copy process */
2906 CopyContext.DestinationRootPath = DestinationRootPath.Buffer;
2907 CopyContext.InstallPath = InstallPath.Buffer;
2908 CopyContext.TotalOperations = 0;
2909 CopyContext.CompletedOperations = 0;
2910
2911 /* Create the progress bar as well */
2912 CopyContext.ProgressBar = CreateProgressBar(13,
2913 26,
2914 xScreen - 13,
2915 yScreen - 20,
2916 10,
2917 24,
2918 TRUE,
2919 "Setup is copying files...");
2920
2921 /* Create the paged pool progress bar */
2922 CopyContext.MemoryBars[0] = CreateProgressBar(13,
2923 40,
2924 18,
2925 43,
2926 10,
2927 44,
2928 FALSE,
2929 "Paged Memory");
2930
2931 /* Create the non paged pool progress bar */
2932 CopyContext.MemoryBars[1] = CreateProgressBar(28,
2933 40,
2934 33,
2935 43,
2936 24,
2937 44,
2938 FALSE,
2939 "Nonpaged Memory");
2940
2941 /* Create the global memory progress bar */
2942 CopyContext.MemoryBars[2] = CreateProgressBar(43,
2943 40,
2944 48,
2945 43,
2946 40,
2947 44,
2948 FALSE,
2949 "Free Memory");
2950
2951 /* Do the file copying */
2952 SetupCommitFileQueueW(NULL,
2953 SetupFileQueue,
2954 FileCopyCallback,
2955 &CopyContext);
2956
2957 /* If we get here, we're done, so cleanup the queue and progress bar */
2958 SetupCloseFileQueue(SetupFileQueue);
2959 DestroyProgressBar(CopyContext.ProgressBar);
2960 DestroyProgressBar(CopyContext.MemoryBars[0]);
2961 DestroyProgressBar(CopyContext.MemoryBars[1]);
2962 DestroyProgressBar(CopyContext.MemoryBars[2]);
2963
2964 /* Go display the next page */
2965 return REGISTRY_PAGE;
2966 }
2967
2968 static PAGE_NUMBER
2969 RegistryPage(PINPUT_RECORD Ir)
2970 {
2971 INFCONTEXT InfContext;
2972 PWSTR Action;
2973 PWSTR File;
2974 PWSTR Section;
2975 BOOLEAN Delete;
2976 NTSTATUS Status;
2977
2978 CONSOLE_SetTextXY(6, 8, "Setup is updating the system configuration");
2979
2980 CONSOLE_SetStatusText(" Creating registry hives...");
2981
2982 if (RepairUpdateFlag)
2983 {
2984 return SUCCESS_PAGE;
2985 }
2986
2987 if (!SetInstallPathValue(&DestinationPath))
2988 {
2989 DPRINT("SetInstallPathValue() failed\n");
2990 MUIDisplayError(ERROR_INITIALIZE_REGISTRY, Ir, POPUP_WAIT_ENTER);
2991 return QUIT_PAGE;
2992 }
2993
2994 /* Create the default hives */
2995 #ifdef __REACTOS__
2996 Status = NtInitializeRegistry(CM_BOOT_FLAG_SETUP);
2997 if (!NT_SUCCESS(Status))
2998 {
2999 DPRINT("NtInitializeRegistry() failed (Status %lx)\n", Status);
3000 MUIDisplayError(ERROR_CREATE_HIVE, Ir, POPUP_WAIT_ENTER);
3001 return QUIT_PAGE;
3002 }
3003 #else
3004 RegInitializeRegistry();
3005 #endif
3006
3007 /* Update registry */
3008 CONSOLE_SetStatusText(" Updating registry hives...");
3009
3010 if (!SetupFindFirstLineW(SetupInf, L"HiveInfs.Install", NULL, &InfContext))
3011 {
3012 DPRINT1("SetupFindFirstLine() failed\n");
3013 MUIDisplayError(ERROR_FIND_REGISTRY, Ir, POPUP_WAIT_ENTER);
3014 return QUIT_PAGE;
3015 }
3016
3017 do
3018 {
3019 INF_GetDataField (&InfContext, 0, &Action);
3020 INF_GetDataField (&InfContext, 1, &File);
3021 INF_GetDataField (&InfContext, 2, &Section);
3022
3023 DPRINT("Action: %S File: %S Section %S\n", Action, File, Section);
3024
3025 if (!_wcsicmp (Action, L"AddReg"))
3026 {
3027 Delete = FALSE;
3028 }
3029 else if (!_wcsicmp (Action, L"DelReg"))
3030 {
3031 Delete = TRUE;
3032 }
3033 else
3034 {
3035 continue;
3036 }
3037
3038 CONSOLE_SetStatusText(" Importing %S...", File);
3039
3040 if (!ImportRegistryFile(File, Section, Delete))
3041 {
3042 DPRINT("Importing %S failed\n", File);
3043
3044 MUIDisplayError(ERROR_IMPORT_HIVE, Ir, POPUP_WAIT_ENTER);
3045 return QUIT_PAGE;
3046 }
3047 }
3048 while (SetupFindNextLine (&InfContext, &InfContext));
3049
3050 /* Update display registry settings */
3051 CONSOLE_SetStatusText(" Updating display registry settings...");
3052 if (!ProcessDisplayRegistry(SetupInf, DisplayList))
3053 {
3054 MUIDisplayError(ERROR_UPDATE_DISPLAY_SETTINGS, Ir, POPUP_WAIT_ENTER);
3055 return QUIT_PAGE;
3056 }
3057
3058 /* Update keyboard layout settings */
3059 CONSOLE_SetStatusText(" Updating keyboard layout settings...");
3060 if (!ProcessKeyboardLayoutRegistry(LanguageList))
3061 {
3062 MUIDisplayError(ERROR_UPDATE_KBSETTINGS, Ir, POPUP_WAIT_ENTER);
3063 return QUIT_PAGE;
3064 }
3065
3066 /* Update the mounted devices list */
3067 SetMountedDeviceValues(PartitionList);
3068
3069 CONSOLE_SetStatusText(" Done...");
3070
3071 return BOOT_LOADER_PAGE;
3072 }
3073
3074
3075 static PAGE_NUMBER
3076 BootLoaderPage(PINPUT_RECORD Ir)
3077 {
3078 UCHAR PartitionType;
3079 BOOLEAN InstallOnFloppy;
3080 USHORT Line = 12;
3081
3082 CONSOLE_SetStatusText(" Please wait...");
3083
3084 PartitionType = PartitionList->ActiveBootPartition->PartInfo[0].PartitionType;
3085
3086 if (PartitionType == PARTITION_ENTRY_UNUSED)
3087 {
3088 DPRINT("Error: active partition invalid (unused)\n");
3089 InstallOnFloppy = TRUE;
3090 }
3091 else if (PartitionType == 0x0A)
3092 {
3093 /* OS/2 boot manager partition */
3094 DPRINT("Found OS/2 boot manager partition\n");
3095 InstallOnFloppy = TRUE;
3096 }
3097 else if (PartitionType == 0x83)
3098 {
3099 /* Linux ext2 partition */
3100 DPRINT("Found Linux ext2 partition\n");
3101 InstallOnFloppy = TRUE;
3102 }
3103 else if (PartitionType == PARTITION_IFS)
3104 {
3105 /* NTFS partition */
3106 DPRINT("Found NTFS partition\n");
3107 InstallOnFloppy = TRUE;
3108 }
3109 else if ((PartitionType == PARTITION_FAT_12) ||
3110 (PartitionType == PARTITION_FAT_16) ||
3111 (PartitionType == PARTITION_HUGE) ||
3112 (PartitionType == PARTITION_XINT13) ||
3113 (PartitionType == PARTITION_FAT32) ||
3114 (PartitionType == PARTITION_FAT32_XINT13))
3115 {
3116 DPRINT("Found FAT partition\n");
3117 InstallOnFloppy = FALSE;
3118 }
3119 else
3120 {
3121 /* Unknown partition */
3122 DPRINT("Unknown partition found\n");
3123 InstallOnFloppy = TRUE;
3124 }
3125
3126 if (InstallOnFloppy == TRUE)
3127 {
3128 return BOOT_LOADER_FLOPPY_PAGE;
3129 }
3130
3131 if (IsUnattendedSetup)
3132 {
3133 if (UnattendMBRInstallType == 0) /* skip MBR installation */
3134 {
3135 return SUCCESS_PAGE;
3136 }
3137 else if (UnattendMBRInstallType == 1) /* install on floppy */
3138 {
3139 return BOOT_LOADER_FLOPPY_PAGE;
3140 }
3141 else if (UnattendMBRInstallType == 2) /* install on hdd */
3142 {
3143 return BOOT_LOADER_HARDDISK_PAGE;
3144 }
3145 }
3146
3147 MUIDisplayPage(BOOT_LOADER_PAGE);
3148 CONSOLE_InvertTextXY (8, Line, 60, 1);
3149
3150 while(TRUE)
3151 {
3152 CONSOLE_ConInKey(Ir);
3153
3154 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3155 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
3156 {
3157 CONSOLE_NormalTextXY (8, Line, 60, 1);
3158
3159 Line++;
3160 if (Line<12) Line=14;
3161 if (Line>14) Line=12;
3162
3163
3164
3165 CONSOLE