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