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