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