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