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