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