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