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