Changed file system decision as per Brian Palmers suggestion.
[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].StartingOffset.QuadPart < (1024ULL * 255ULL * 63ULL * 512ULL))
1593 {
1594 /* Partition starts below the 8.4GB boundary ==> CHS partition */
1595
1596 if (PartEntry->PartInfo[0].PartitionLength.QuadPart < (32ULL * 1024ULL * 1024ULL))
1597 {
1598 /* FAT16 CHS partition (partiton size < 32MB) */
1599 PartEntry->PartInfo[0].PartitionType = PARTITION_FAT_16;
1600 }
1601 else if (PartEntry->PartInfo[0].PartitionLength.QuadPart < (512ULL * 1024ULL * 1024ULL))
1602 {
1603 /* FAT16 CHS partition (partition size < 512MB) */
1604 PartEntry->PartInfo[0].PartitionType = PARTITION_HUGE;
1605 }
1606 else
1607 {
1608 /* FAT32 CHS partition (partition size >= 512MB) */
1609 PartEntry->PartInfo[0].PartitionType = PARTITION_FAT32;
1610 }
1611 }
1612 else
1613 {
1614 /* Partition starts above the 8.4GB boundary ==> LBA partition */
1615
1616 if (PartEntry->PartInfo[0].PartitionLength.QuadPart < (512ULL * 1024ULL * 1024ULL))
1617 {
1618 /* FAT16 LBA partition (partition size < 512MB) */
1619 PartEntry->PartInfo[0].PartitionType = PARTITION_XINT13;
1620 }
1621 else
1622 {
1623 /* FAT32 LBA partition (partition size >= 512MB) */
1624 PartEntry->PartInfo[0].PartitionType = PARTITION_FAT32_XINT13;
1625 }
1626 }
1627 break;
1628
1629 case FsKeep:
1630 break;
1631
1632 default:
1633 return QUIT_PAGE;
1634 }
1635 }
1636
1637 CheckActiveBootPartition (PartitionList);
1638
1639 //#ifndef NDEBUG
1640 PrintTextXY (6, 12,
1641 "Disk: %I64u Cylinder: %I64u Track: %I64u",
1642 DiskEntry->DiskSize,
1643 DiskEntry->CylinderSize,
1644 DiskEntry->TrackSize);
1645
1646 Line = 13;
1647 DiskEntry = PartitionList->CurrentDisk;
1648 Entry = DiskEntry->PartListHead.Flink;
1649 while (Entry != &DiskEntry->PartListHead)
1650 {
1651 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
1652
1653 if (PartEntry->Unpartitioned == FALSE)
1654 {
1655
1656 for (i = 0; i < 4; i++)
1657 {
1658 PrintTextXY (6, Line,
1659 "%2u: %2u %c %12I64u %12I64u %2u %c",
1660 i,
1661 PartEntry->PartInfo[i].PartitionNumber,
1662 PartEntry->PartInfo[i].BootIndicator ? 'A' : '-',
1663 PartEntry->PartInfo[i].StartingOffset.QuadPart,
1664 PartEntry->PartInfo[i].PartitionLength.QuadPart,
1665 PartEntry->PartInfo[i].PartitionType,
1666 PartEntry->PartInfo[i].RewritePartition ? '*' : ' ');
1667
1668 Line++;
1669 }
1670
1671 Line++;
1672 }
1673
1674 Entry = Entry->Flink;
1675 }
1676
1677 /* Restore the old entry */
1678 PartEntry = PartitionList->CurrentPartition;
1679 //#endif
1680
1681 if (WritePartitionsToDisk (PartitionList) == FALSE)
1682 {
1683 DPRINT ("WritePartitionsToDisk() failed\n");
1684
1685 PopupError ("Setup failed to write partition tables.\n",
1686 "ENTER = Reboot computer");
1687
1688 while (TRUE)
1689 {
1690 ConInKey (Ir);
1691
1692 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1693 {
1694 return QUIT_PAGE;
1695 }
1696 }
1697 }
1698
1699
1700 /* Set DestinationRootPath */
1701 RtlFreeUnicodeString (&DestinationRootPath);
1702 swprintf (PathBuffer,
1703 L"\\Device\\Harddisk%lu\\Partition%lu",
1704 PartitionList->CurrentDisk->DiskNumber,
1705 PartitionList->CurrentPartition->PartInfo[0].PartitionNumber);
1706 RtlCreateUnicodeString (&DestinationRootPath,
1707 PathBuffer);
1708 DPRINT ("DestinationRootPath: %wZ\n", &DestinationRootPath);
1709
1710
1711 /* Set SystemRootPath */
1712 RtlFreeUnicodeString (&SystemRootPath);
1713 swprintf (PathBuffer,
1714 L"\\Device\\Harddisk%lu\\Partition%lu",
1715 PartitionList->ActiveBootDisk->DiskNumber,
1716 PartitionList->ActiveBootPartition->PartInfo[0].PartitionNumber);
1717 RtlCreateUnicodeString (&SystemRootPath,
1718 PathBuffer);
1719 DPRINT ("SystemRootPath: %wZ\n", &SystemRootPath);
1720
1721
1722 switch (FileSystemList->CurrentFileSystem)
1723 {
1724 case FsFat:
1725 Status = FormatPartition (&DestinationRootPath);
1726 if (!NT_SUCCESS (Status))
1727 {
1728 DPRINT1 ("FormatPartition() failed with status 0x%.08x\n", Status);
1729 /* FIXME: show an error dialog */
1730 return QUIT_PAGE;
1731 }
1732
1733 PartEntry->New = FALSE;
1734 if (FileSystemList != NULL)
1735 {
1736 DestroyFileSystemList (FileSystemList);
1737 FileSystemList = NULL;
1738 }
1739
1740 CheckActiveBootPartition (PartitionList);
1741
1742 /* FIXME: Install boot code. This is a hack! */
1743 if ((PartEntry->PartInfo[0].PartitionType == PARTITION_FAT32_XINT13) ||
1744 (PartEntry->PartInfo[0].PartitionType == PARTITION_FAT32))
1745 {
1746 wcscpy (PathBuffer, SourceRootPath.Buffer);
1747 wcscat (PathBuffer, L"\\loader\\fat32.bin");
1748
1749 DPRINT1 ("Install FAT32 bootcode: %S ==> %S\n", PathBuffer,
1750 DestinationRootPath.Buffer);
1751 Status = InstallFat32BootCodeToDisk (PathBuffer,
1752 DestinationRootPath.Buffer);
1753 if (!NT_SUCCESS (Status))
1754 {
1755 DPRINT1 ("InstallFat32BootCodeToDisk() failed with status 0x%.08x\n", Status);
1756 /* FIXME: show an error dialog */
1757 return QUIT_PAGE;
1758 }
1759 }
1760 else
1761 {
1762 wcscpy (PathBuffer, SourceRootPath.Buffer);
1763 wcscat (PathBuffer, L"\\loader\\fat.bin");
1764
1765 DPRINT1 ("Install FAT bootcode: %S ==> %S\n", PathBuffer,
1766 DestinationRootPath.Buffer);
1767 Status = InstallFat16BootCodeToDisk (PathBuffer,
1768 DestinationRootPath.Buffer);
1769 if (!NT_SUCCESS (Status))
1770 {
1771 DPRINT1 ("InstallFat16BootCodeToDisk() failed with status 0x%.08x\n", Status);
1772 /* FIXME: show an error dialog */
1773 return QUIT_PAGE;
1774 }
1775 }
1776 break;
1777
1778 case FsKeep:
1779 break;
1780
1781 default:
1782 return QUIT_PAGE;
1783 }
1784
1785 SetStatusText (" Done. Press any key ...");
1786 ConInKey(Ir);
1787
1788 return INSTALL_DIRECTORY_PAGE;
1789 }
1790 }
1791
1792 return FORMAT_PARTITION_PAGE;
1793 }
1794
1795
1796 static ULONG
1797 CheckFileSystemPage(PINPUT_RECORD Ir)
1798 {
1799 WCHAR PathBuffer[MAX_PATH];
1800
1801 SetTextXY(6, 8, "Check file system");
1802
1803 SetTextXY(6, 10, "At present, ReactOS can not check file systems.");
1804
1805 SetStatusText(" Please wait ...");
1806
1807
1808 SetStatusText(" ENTER = Continue F3 = Quit");
1809
1810
1811 /* Set DestinationRootPath */
1812 RtlFreeUnicodeString (&DestinationRootPath);
1813 swprintf (PathBuffer,
1814 L"\\Device\\Harddisk%lu\\Partition%lu",
1815 PartitionList->CurrentDisk->DiskNumber,
1816 PartitionList->CurrentPartition->PartInfo[0].PartitionNumber);
1817 RtlCreateUnicodeString (&DestinationRootPath,
1818 PathBuffer);
1819 DPRINT ("DestinationRootPath: %wZ\n", &DestinationRootPath);
1820
1821 /* Set SystemRootPath */
1822 RtlFreeUnicodeString (&SystemRootPath);
1823 swprintf (PathBuffer,
1824 L"\\Device\\Harddisk%lu\\Partition%lu",
1825 PartitionList->ActiveBootDisk->DiskNumber,
1826 PartitionList->ActiveBootPartition->PartInfo[0].PartitionNumber);
1827 RtlCreateUnicodeString (&SystemRootPath,
1828 PathBuffer);
1829 DPRINT ("SystemRootPath: %wZ\n", &SystemRootPath);
1830
1831
1832 while(TRUE)
1833 {
1834 ConInKey(Ir);
1835
1836 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1837 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1838 {
1839 if (ConfirmQuit(Ir) == TRUE)
1840 return(QUIT_PAGE);
1841 break;
1842 }
1843 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1844 {
1845 return(INSTALL_DIRECTORY_PAGE);
1846 }
1847 }
1848
1849 return(CHECK_FILE_SYSTEM_PAGE);
1850 }
1851
1852
1853 static PAGE_NUMBER
1854 InstallDirectoryPage(PINPUT_RECORD Ir)
1855 {
1856 PDISKENTRY DiskEntry;
1857 PPARTENTRY PartEntry;
1858 WCHAR PathBuffer[MAX_PATH];
1859 WCHAR InstallDir[51];
1860 PWCHAR DefaultPath;
1861 INFCONTEXT Context;
1862 ULONG Length;
1863 NTSTATUS Status;
1864
1865 if (PartitionList == NULL ||
1866 PartitionList->CurrentDisk == NULL ||
1867 PartitionList->CurrentPartition == NULL)
1868 {
1869 /* FIXME: show an error dialog */
1870 return QUIT_PAGE;
1871 }
1872
1873 DiskEntry = PartitionList->CurrentDisk;
1874 PartEntry = PartitionList->CurrentPartition;
1875
1876 /* Search for 'DefaultPath' in the 'SetupData' section */
1877 if (!InfFindFirstLine (SetupInf, L"SetupData", L"DefaultPath", &Context))
1878 {
1879 PopupError("Setup failed to find the 'SetupData' section\n"
1880 "in TXTSETUP.SIF.\n",
1881 "ENTER = Reboot computer");
1882
1883 while (TRUE)
1884 {
1885 ConInKey (Ir);
1886
1887 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1888 {
1889 return QUIT_PAGE;
1890 }
1891 }
1892 }
1893
1894 /* Read the 'DefaultPath' data */
1895 if (InfGetData (&Context, NULL, &DefaultPath))
1896 {
1897 wcscpy(InstallDir, DefaultPath);
1898 }
1899 else
1900 {
1901 wcscpy(InstallDir, L"\\ReactOS");
1902 }
1903 Length = wcslen(InstallDir);
1904
1905 SetTextXY(6, 8, "Setup installs ReactOS files onto the selected partition. Choose a");
1906 SetTextXY(6, 9, "directory where you want ReactOS to be installed:");
1907
1908 SetInputTextXY(8, 11, 51, InstallDir);
1909
1910 SetTextXY(6, 14, "To change the suggested directory, press BACKSPACE to delete");
1911 SetTextXY(6, 15, "characters and then type the directory where you want ReactOS to");
1912 SetTextXY(6, 16, "be installed.");
1913
1914 SetStatusText(" ENTER = Continue F3 = Quit");
1915
1916 while(TRUE)
1917 {
1918 ConInKey(Ir);
1919
1920 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1921 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1922 {
1923 if (ConfirmQuit(Ir) == TRUE)
1924 return(QUIT_PAGE);
1925 break;
1926 }
1927 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1928 {
1929 /* Create 'InstallPath' string */
1930 RtlFreeUnicodeString(&InstallPath);
1931 RtlCreateUnicodeString(&InstallPath,
1932 InstallDir);
1933
1934 /* Create 'DestinationPath' string */
1935 RtlFreeUnicodeString(&DestinationPath);
1936 wcscpy(PathBuffer,
1937 DestinationRootPath.Buffer);
1938 if (InstallDir[0] != L'\\')
1939 wcscat(PathBuffer,
1940 L"\\");
1941 wcscat(PathBuffer, InstallDir);
1942 RtlCreateUnicodeString(&DestinationPath,
1943 PathBuffer);
1944
1945 /* Create 'DestinationArcPath' */
1946 RtlFreeUnicodeString(&DestinationArcPath);
1947 swprintf(PathBuffer,
1948 L"multi(0)disk(0)rdisk(%lu)partition(%lu)",
1949 DiskEntry->DiskNumber,
1950 PartEntry->PartInfo[0].PartitionNumber);
1951 if (InstallDir[0] != L'\\')
1952 wcscat(PathBuffer,
1953 L"\\");
1954 wcscat(PathBuffer, InstallDir);
1955 RtlCreateUnicodeString(&DestinationArcPath,
1956 PathBuffer);
1957
1958 return(PREPARE_COPY_PAGE);
1959 }
1960 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x08) /* BACKSPACE */
1961 {
1962 if (Length > 0)
1963 {
1964 Length--;
1965 InstallDir[Length] = 0;
1966 SetInputTextXY(8, 11, 51, InstallDir);
1967 }
1968 }
1969 else if (isprint(Ir->Event.KeyEvent.uChar.AsciiChar))
1970 {
1971 if (Length < 50)
1972 {
1973 InstallDir[Length] = (WCHAR)Ir->Event.KeyEvent.uChar.AsciiChar;
1974 Length++;
1975 InstallDir[Length] = 0;
1976 SetInputTextXY(8, 11, 51, InstallDir);
1977 }
1978 }
1979 }
1980
1981 return(INSTALL_DIRECTORY_PAGE);
1982 }
1983
1984
1985 static BOOLEAN
1986 PrepareCopyPageInfFile(HINF InfFile, PWCHAR SourceCabinet, PINPUT_RECORD Ir)
1987 {
1988 WCHAR PathBuffer[MAX_PATH];
1989 INFCONTEXT FilesContext;
1990 INFCONTEXT DirContext;
1991 PWCHAR KeyName;
1992 PWCHAR KeyValue;
1993 ULONG Length;
1994 NTSTATUS Status;
1995 PWCHAR FileKeyName;
1996 PWCHAR FileKeyValue;
1997 PWCHAR DirKeyName;
1998 PWCHAR DirKeyValue;
1999
2000 /* Search for the 'SourceFiles' section */
2001 if (!InfFindFirstLine (InfFile, L"SourceFiles", NULL, &FilesContext))
2002 {
2003 PopupError("Setup failed to find the 'SourceFiles' section\n"
2004 "in TXTSETUP.SIF.\n", // FIXME
2005 "ENTER = Reboot computer");
2006
2007 while(TRUE)
2008 {
2009 ConInKey(Ir);
2010
2011 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2012 {
2013 return(FALSE);
2014 }
2015 }
2016 }
2017
2018 /*
2019 * Enumerate the files in the 'SourceFiles' section
2020 * and add them to the file queue.
2021 */
2022 do
2023 {
2024 if (!InfGetData (&FilesContext, &FileKeyName, &FileKeyValue))
2025 {
2026 DPRINT("break\n");
2027 break;
2028 }
2029
2030 DPRINT ("FileKeyName: '%S' FileKeyValue: '%S'\n", FileKeyName, FileKeyValue);
2031
2032 /* Lookup target directory */
2033 if (!InfFindFirstLine (InfFile, L"Directories", FileKeyValue, &DirContext))
2034 {
2035 /* FIXME: Handle error! */
2036 DPRINT1("InfFindFirstLine() failed\n");
2037 break;
2038 }
2039
2040 if (!InfGetData (&DirContext, NULL, &DirKeyValue))
2041 {
2042 /* FIXME: Handle error! */
2043 DPRINT1("InfGetData() failed\n");
2044 break;
2045 }
2046
2047 if (!SetupQueueCopy(SetupFileQueue,
2048 SourceCabinet,
2049 SourceRootPath.Buffer,
2050 L"\\reactos",
2051 FileKeyName,
2052 DirKeyValue,
2053 NULL))
2054 {
2055 /* FIXME: Handle error! */
2056 DPRINT1("SetupQueueCopy() failed\n");
2057 }
2058 }
2059 while (InfFindNextLine(&FilesContext, &FilesContext));
2060
2061
2062 /* Create directories */
2063
2064 /*
2065 * FIXME:
2066 * Install directories like '\reactos\test' are not handled yet.
2067 */
2068
2069 /* Get destination path */
2070 wcscpy(PathBuffer, DestinationPath.Buffer);
2071
2072 /* Remove trailing backslash */
2073 Length = wcslen(PathBuffer);
2074 if ((Length > 0) && (PathBuffer[Length - 1] == '\\'))
2075 {
2076 PathBuffer[Length - 1] = 0;
2077 }
2078
2079 /* Create the install directory */
2080 Status = CreateDirectory(PathBuffer);
2081 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION)
2082 {
2083 DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer, Status);
2084 PopupError("Setup could not create the install directory.",
2085 "ENTER = Reboot computer");
2086
2087 while(TRUE)
2088 {
2089 ConInKey(Ir);
2090
2091 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2092 {
2093 return(FALSE);
2094 }
2095 }
2096 }
2097
2098
2099 /* Search for the 'Directories' section */
2100 if (!InfFindFirstLine(InfFile, L"Directories", NULL, &DirContext))
2101 {
2102 if (SourceCabinet)
2103 {
2104 PopupError("Setup failed to find the 'Directories' section\n"
2105 "in the cabinet.\n", "ENTER = Reboot computer");
2106 }
2107 else
2108 {
2109 PopupError("Setup failed to find the 'Directories' section\n"
2110 "in TXTSETUP.SIF.\n", "ENTER = Reboot computer");
2111 }
2112
2113 while(TRUE)
2114 {
2115 ConInKey(Ir);
2116
2117 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2118 {
2119 return(FALSE);
2120 }
2121 }
2122 }
2123
2124 /* Enumerate the directory values and create the subdirectories */
2125 do
2126 {
2127 if (!InfGetData (&DirContext, NULL, &KeyValue))
2128 {
2129 DPRINT1("break\n");
2130 break;
2131 }
2132
2133 if (KeyValue[0] == L'\\' && KeyValue[1] != 0)
2134 {
2135 DPRINT("Absolute Path: '%S'\n", KeyValue);
2136
2137 wcscpy(PathBuffer, DestinationRootPath.Buffer);
2138 wcscat(PathBuffer, KeyValue);
2139
2140 DPRINT("FullPath: '%S'\n", PathBuffer);
2141 }
2142 else if (KeyValue[0] != L'\\')
2143 {
2144 DPRINT("RelativePath: '%S'\n", KeyValue);
2145 wcscpy(PathBuffer, DestinationPath.Buffer);
2146 wcscat(PathBuffer, L"\\");
2147 wcscat(PathBuffer, KeyValue);
2148
2149 DPRINT("FullPath: '%S'\n", PathBuffer);
2150
2151 Status = CreateDirectory(PathBuffer);
2152 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION)
2153 {
2154 DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer, Status);
2155 PopupError("Setup could not create install directories.",
2156 "ENTER = Reboot computer");
2157
2158 while (TRUE)
2159 {
2160 ConInKey(Ir);
2161
2162 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2163 {
2164 return(FALSE);
2165 }
2166 }
2167 }
2168 }
2169 }
2170 while (InfFindNextLine (&DirContext, &DirContext));
2171
2172 return(TRUE);
2173 }
2174
2175
2176 static PAGE_NUMBER
2177 PrepareCopyPage(PINPUT_RECORD Ir)
2178 {
2179 INT CabStatus;
2180 HINF InfHandle;
2181 WCHAR PathBuffer[MAX_PATH];
2182 INFCONTEXT CabinetsContext;
2183 ULONG InfFileSize;
2184 PWCHAR KeyValue;
2185 NTSTATUS Status;
2186 ULONG ErrorLine;
2187 PVOID InfFileData;
2188
2189 SetTextXY(6, 8, "Setup prepares your computer for copying the ReactOS files. ");
2190
2191
2192 /*
2193 * Build the file copy list
2194 */
2195 SetStatusText(" Building the file copy list...");
2196
2197 /* Create the file queue */
2198 SetupFileQueue = SetupOpenFileQueue();
2199 if (SetupFileQueue == NULL)
2200 {
2201 PopupError("Setup failed to open the copy file queue.\n",
2202 "ENTER = Reboot computer");
2203
2204 while(TRUE)
2205 {
2206 ConInKey(Ir);
2207
2208 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2209 {
2210 return(QUIT_PAGE);
2211 }
2212 }
2213 }
2214
2215
2216 if (!PrepareCopyPageInfFile(SetupInf, NULL, Ir))
2217 {
2218 return(QUIT_PAGE);
2219 }
2220
2221
2222 /* Search for the 'Cabinets' section */
2223 if (!InfFindFirstLine (SetupInf, L"Cabinets", NULL, &CabinetsContext))
2224 {
2225 PopupError("Setup failed to find the 'Cabinets' section\n"
2226 "in TXTSETUP.SIF.\n",
2227 "ENTER = Reboot computer");
2228
2229 while(TRUE)
2230 {
2231 ConInKey(Ir);
2232
2233 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2234 {
2235 return(QUIT_PAGE);
2236 }
2237 }
2238 }
2239
2240
2241 /*
2242 * Enumerate the directory values in the 'Cabinets'
2243 * section and parse their inf files.
2244 */
2245 do
2246 {
2247 if (!InfGetData (&CabinetsContext, NULL, &KeyValue))
2248 break;
2249
2250 wcscpy(PathBuffer, SourcePath.Buffer);
2251 wcscat(PathBuffer, L"\\");
2252 wcscat(PathBuffer, KeyValue);
2253
2254 CabinetInitialize();
2255 CabinetSetEventHandlers(NULL, NULL, NULL);
2256 CabinetSetCabinetName(PathBuffer);
2257
2258 if (CabinetOpen() == CAB_STATUS_SUCCESS)
2259 {
2260 DPRINT("Cabinet %S\n", CabinetGetCabinetName());
2261
2262 InfFileData = CabinetGetCabinetReservedArea(&InfFileSize);
2263 if (InfFileData == NULL)
2264 {
2265 PopupError("Cabinet has no setup script.\n",
2266 "ENTER = Reboot computer");
2267
2268 while(TRUE)
2269 {
2270 ConInKey(Ir);
2271
2272 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2273 {
2274 return(QUIT_PAGE);
2275 }
2276 }
2277 }
2278 }
2279 else
2280 {
2281 DPRINT("Cannot open cabinet: %S.\n", CabinetGetCabinetName());
2282
2283 PopupError("Cabinet not found.\n", "ENTER = Reboot computer");
2284
2285 while(TRUE)
2286 {
2287 ConInKey(Ir);
2288
2289 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2290 {
2291 return(QUIT_PAGE);
2292 }
2293 }
2294 }
2295
2296 Status = InfOpenBufferedFile(&InfHandle,
2297 InfFileData,
2298 InfFileSize,
2299 &ErrorLine);
2300 if (!NT_SUCCESS(Status))
2301 {
2302 PopupError("Cabinet has no valid inf file.\n",
2303 "ENTER = Reboot computer");
2304
2305 while(TRUE)
2306 {
2307 ConInKey(Ir);
2308
2309 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2310 {
2311 return(QUIT_PAGE);
2312 }
2313 }
2314 }
2315
2316 CabinetCleanup();
2317
2318 if (!PrepareCopyPageInfFile(InfHandle, KeyValue, Ir))
2319 {
2320 return(QUIT_PAGE);
2321 }
2322 }
2323 while (InfFindNextLine (&CabinetsContext, &CabinetsContext));
2324
2325 return(FILE_COPY_PAGE);
2326 }
2327
2328
2329 static ULONG
2330 FileCopyCallback(PVOID Context,
2331 ULONG Notification,
2332 PVOID Param1,
2333 PVOID Param2)
2334 {
2335 PCOPYCONTEXT CopyContext;
2336
2337 CopyContext = (PCOPYCONTEXT)Context;
2338
2339 switch (Notification)
2340 {
2341 case SPFILENOTIFY_STARTSUBQUEUE:
2342 CopyContext->TotalOperations = (ULONG)Param2;
2343 ProgressSetStepCount(CopyContext->ProgressBar,
2344 CopyContext->TotalOperations);
2345 break;
2346
2347 case SPFILENOTIFY_STARTCOPY:
2348 /* Display copy message */
2349 PrintTextXYN(6, 16, 60, "Copying file: %S", (PWSTR)Param1);
2350
2351 PrintTextXYN(6, 18, 60, "File %lu of %lu",
2352 CopyContext->CompletedOperations + 1,
2353 CopyContext->TotalOperations);
2354 break;
2355
2356 case SPFILENOTIFY_ENDCOPY:
2357 CopyContext->CompletedOperations++;
2358 ProgressNextStep(CopyContext->ProgressBar);
2359 break;
2360 }
2361
2362 return(0);
2363 }
2364
2365
2366 static PAGE_NUMBER
2367 FileCopyPage(PINPUT_RECORD Ir)
2368 {
2369 COPYCONTEXT CopyContext;
2370 SHORT xScreen;
2371 SHORT yScreen;
2372
2373 SetStatusText(" Please wait...");
2374
2375 SetTextXY(6, 8, "Copying files");
2376
2377 GetScreenSize(&xScreen, &yScreen);
2378
2379 CopyContext.TotalOperations = 0;
2380 CopyContext.CompletedOperations = 0;
2381 CopyContext.ProgressBar = CreateProgressBar(6,
2382 yScreen - 14,
2383 xScreen - 7,
2384 yScreen - 10);
2385
2386 SetupCommitFileQueue(SetupFileQueue,
2387 DestinationRootPath.Buffer,
2388 InstallPath.Buffer,
2389 (PSP_FILE_CALLBACK)FileCopyCallback,
2390 &CopyContext);
2391
2392 SetupCloseFileQueue(SetupFileQueue);
2393
2394 DestroyProgressBar(CopyContext.ProgressBar);
2395
2396 return(REGISTRY_PAGE);
2397 }
2398
2399
2400 static PAGE_NUMBER
2401 RegistryPage(PINPUT_RECORD Ir)
2402 {
2403 INFCONTEXT InfContext;
2404 NTSTATUS Status;
2405
2406 PWSTR Action;
2407 PWSTR File;
2408 PWSTR Section;
2409 BOOLEAN Delete;
2410
2411
2412 SetTextXY(6, 8, "Setup is updating the system configuration");
2413
2414 SetStatusText(" Creating registry hives...");
2415
2416 if (!SetInstallPathValue(&DestinationPath))
2417 {
2418 DPRINT("SetInstallPathValue() failed\n");
2419 PopupError("Setup failed to set the initialize the registry.",
2420 "ENTER = Reboot computer");
2421
2422 while(TRUE)
2423 {
2424 ConInKey(Ir);
2425
2426 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2427 {
2428 return(QUIT_PAGE);
2429 }
2430 }
2431 }
2432
2433 /* Create the default hives */
2434 Status = NtInitializeRegistry(TRUE);
2435 if (!NT_SUCCESS(Status))
2436 {
2437 DPRINT("NtInitializeRegistry() failed (Status %lx)\n", Status);
2438 PopupError("Setup failed to create the registry hives.",
2439 "ENTER = Reboot computer");
2440
2441 while(TRUE)
2442 {
2443 ConInKey(Ir);
2444
2445 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2446 {
2447 return(QUIT_PAGE);
2448 }
2449 }
2450 }
2451
2452 /* Update registry */
2453 SetStatusText(" Updating registry hives...");
2454
2455 if (!InfFindFirstLine(SetupInf, L"HiveInfs.Install", NULL, &InfContext))
2456 {
2457 DPRINT1("InfFindFirstLine() failed\n");
2458 PopupError("Setup failed to find the registry data files.",
2459 "ENTER = Reboot computer");
2460
2461 while(TRUE)
2462 {
2463 ConInKey(Ir);
2464
2465 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2466 {
2467 return(QUIT_PAGE);
2468 }
2469 }
2470 }
2471
2472 do
2473 {
2474 InfGetDataField (&InfContext, 0, &Action);
2475 InfGetDataField (&InfContext, 1, &File);
2476 InfGetDataField (&InfContext, 2, &Section);
2477
2478 DPRINT1("Action: %S File: %S Section %S\n", Action, File, Section);
2479
2480 if (!_wcsicmp (Action, L"AddReg"))
2481 {
2482 Delete = FALSE;
2483 }
2484 else if (!_wcsicmp (Action, L"DelReg"))
2485 {
2486 Delete = TRUE;
2487 }
2488 else
2489 {
2490 continue;
2491 }
2492
2493 SetStatusText(" Importing %S...", File);
2494
2495 if (!ImportRegistryFile(File, Section, Delete))
2496 {
2497 DPRINT1("Importing %S failed\n", File);
2498
2499 PopupError("Setup failed to import a hive file.",
2500 "ENTER = Reboot computer");
2501
2502 while(TRUE)
2503 {
2504 ConInKey(Ir);
2505
2506 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2507 {
2508 return(QUIT_PAGE);
2509 }
2510 }
2511 }
2512 }
2513 while (InfFindNextLine (&InfContext, &InfContext));
2514
2515 SetStatusText(" Done...");
2516
2517 return(BOOT_LOADER_PAGE);
2518 }
2519
2520
2521 static PAGE_NUMBER
2522 BootLoaderPage(PINPUT_RECORD Ir)
2523 {
2524 WCHAR SrcPath[MAX_PATH];
2525 WCHAR DstPath[MAX_PATH];
2526 PINICACHE IniCache;
2527 PINICACHESECTION IniSection;
2528 NTSTATUS Status;
2529
2530 SetTextXY(6, 8, "Installing the boot loader");
2531
2532 SetStatusText(" Please wait...");
2533
2534 if (PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_ENTRY_UNUSED)
2535 {
2536 DPRINT1("Error: active partition invalid (unused)\n");
2537 PopupError("The active partition is unused (invalid).\n",
2538 "ENTER = Reboot computer");
2539
2540 while(TRUE)
2541 {
2542 ConInKey(Ir);
2543
2544 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2545 {
2546 return(QUIT_PAGE);
2547 }
2548 }
2549 }
2550 if (PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == 0x0A)
2551 {
2552 /* OS/2 boot manager partition */
2553 DPRINT1("Found OS/2 boot manager partition\n");
2554 PopupError("Setup found an OS/2 boot manager partiton.\n"
2555 "The OS/2 boot manager is not supported yet!",
2556 "ENTER = Reboot computer");
2557
2558 while(TRUE)
2559 {
2560 ConInKey(Ir);
2561
2562 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2563 {
2564 return(QUIT_PAGE);
2565 }
2566 }
2567 }
2568 else if (PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == 0x83)
2569 {
2570 /* Linux ext2 partition */
2571 DPRINT1("Found Linux ext2 partition\n");
2572 PopupError("Setup found a Linux ext2 partiton.\n"
2573 "Linux ext2 partitions are not supported yet!",
2574 "ENTER = Reboot computer");
2575
2576 while(TRUE)
2577 {
2578 ConInKey(Ir);
2579
2580 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2581 {
2582 return(QUIT_PAGE);
2583 }
2584 }
2585 }
2586 else if (PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_IFS)
2587 {
2588 /* NTFS partition */
2589 DPRINT1("Found NTFS partition\n");
2590 PopupError("Setup found an NTFS partiton.\n"
2591 "NTFS partitions are not supported yet!",
2592 "ENTER = Reboot computer");
2593
2594 while(TRUE)
2595 {
2596 ConInKey(Ir);
2597
2598 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2599 {
2600 return(QUIT_PAGE);
2601 }
2602 }
2603 }
2604 else if ((PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_FAT_12) ||
2605 (PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_FAT_16) ||
2606 (PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_HUGE) ||
2607 (PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_XINT13) ||
2608 (PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_FAT32) ||
2609 (PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_FAT32_XINT13))
2610 {
2611 /* FAT or FAT32 partition */
2612 DPRINT1("System path: '%wZ'\n", &SystemRootPath);
2613
2614 if (DoesFileExist(SystemRootPath.Buffer, L"ntldr") == TRUE ||
2615 DoesFileExist(SystemRootPath.Buffer, L"boot.ini") == TRUE)
2616 {
2617 /* Search root directory for 'ntldr' and 'boot.ini'. */
2618 DPRINT1("Found Microsoft Windows NT/2000/XP boot loader\n");
2619
2620 /* Copy FreeLoader to the boot partition */
2621 wcscpy(SrcPath, SourceRootPath.Buffer);
2622 wcscat(SrcPath, L"\\loader\\freeldr.sys");
2623 wcscpy(DstPath, SystemRootPath.Buffer);
2624 wcscat(DstPath, L"\\freeldr.sys");
2625
2626 DPRINT1("Copy: %S ==> %S\n", SrcPath, DstPath);
2627 Status = SetupCopyFile(SrcPath, DstPath);
2628 if (!NT_SUCCESS(Status))
2629 {
2630 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
2631 PopupError("Setup failed to copy 'freeldr.sys'.",
2632 "ENTER = Reboot computer");
2633
2634 while(TRUE)
2635 {
2636 ConInKey(Ir);
2637
2638 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2639 {
2640 return(QUIT_PAGE);
2641 }
2642 }
2643 }
2644
2645 /* Create or update freeldr.ini */
2646 if (DoesFileExist(SystemRootPath.Buffer, L"freeldr.ini") == FALSE)
2647 {
2648 /* Create new 'freeldr.ini' */
2649 DPRINT1("Create new 'freeldr.ini'\n");
2650 wcscpy(DstPath, SystemRootPath.Buffer);
2651 wcscat(DstPath, L"\\freeldr.ini");
2652
2653 Status = CreateFreeLoaderIniForReactos(DstPath,
2654 DestinationArcPath.Buffer);
2655 if (!NT_SUCCESS(Status))
2656 {
2657 DPRINT1("CreateFreeLoaderIniForReactos() failed (Status %lx)\n", Status);
2658 PopupError("Setup failed to create 'freeldr.ini'.",
2659 "ENTER = Reboot computer");
2660
2661 while(TRUE)
2662 {
2663 ConInKey(Ir);
2664
2665 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2666 {
2667 return(QUIT_PAGE);
2668 }
2669 }
2670 }
2671
2672 /* Install new bootcode */
2673 if ((PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_FAT32) ||
2674 (PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_FAT32_XINT13))
2675 {
2676 /* Install FAT32 bootcode */
2677 wcscpy(SrcPath, SourceRootPath.Buffer);
2678 wcscat(SrcPath, L"\\loader\\fat32.bin");
2679 wcscpy(DstPath, SystemRootPath.Buffer);
2680 wcscat(DstPath, L"\\bootsect.ros");
2681
2682 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, DstPath);
2683 Status = InstallFat32BootCodeToFile(SrcPath,
2684 DstPath,
2685 SystemRootPath.Buffer);
2686 if (!NT_SUCCESS(Status))
2687 {
2688 DPRINT1("InstallFat32BootCodeToFile() failed (Status %lx)\n", Status);
2689 PopupError("Setup failed to install the FAT32 bootcode.",
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(QUIT_PAGE);
2699 }
2700 }
2701 }
2702 }
2703 else
2704 {
2705 /* Install FAT16 bootcode */
2706 wcscpy(SrcPath, SourceRootPath.Buffer);
2707 wcscat(SrcPath, L"\\loader\\fat.bin");
2708 wcscpy(DstPath, SystemRootPath.Buffer);
2709 wcscat(DstPath, L"\\bootsect.ros");
2710
2711 DPRINT1("Install FAT bootcode: %S ==> %S\n", SrcPath, DstPath);
2712 Status = InstallFat16BootCodeToFile(SrcPath,
2713 DstPath,
2714 SystemRootPath.Buffer);
2715 if (!NT_SUCCESS(Status))
2716 {
2717 DPRINT1("InstallFat16BootCodeToFile() failed (Status %lx)\n", Status);
2718 PopupError("Setup failed to install the FAT bootcode.",
2719 "ENTER = Reboot computer");
2720
2721 while(TRUE)
2722 {
2723 ConInKey(Ir);
2724
2725 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2726 {
2727 return(QUIT_PAGE);
2728 }
2729 }
2730 }
2731 }
2732
2733 /* Update 'boot.ini' */
2734 wcscpy(DstPath, SystemRootPath.Buffer);
2735 wcscat(DstPath, L"\\boot.ini");
2736
2737 DPRINT1("Update 'boot.ini': %S\n", DstPath);
2738 Status = UpdateBootIni(DstPath,
2739 L"C:\\bootsect.ros",
2740 L"\"ReactOS\"");
2741 if (!NT_SUCCESS(Status))
2742 {
2743 DPRINT1("UpdateBootIni() failed (Status %lx)\n", Status);
2744 PopupError("Setup failed to update \'boot.ini\'.",
2745 "ENTER = Reboot computer");
2746
2747 while(TRUE)
2748 {
2749 ConInKey(Ir);
2750
2751 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2752 {
2753 return(QUIT_PAGE);
2754 }
2755 }
2756 }
2757 }
2758 else
2759 {
2760 /* Update existing 'freeldr.ini' */
2761 DPRINT1("Update existing 'freeldr.ini'\n");
2762 wcscpy(DstPath, SystemRootPath.Buffer);
2763 wcscat(DstPath, L"\\freeldr.ini");
2764
2765 Status = UpdateFreeLoaderIni(DstPath,
2766 DestinationArcPath.Buffer);
2767 if (!NT_SUCCESS(Status))
2768 {
2769 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
2770 PopupError("Setup failed to update 'freeldr.ini'.",
2771 "ENTER = Reboot computer");
2772
2773 while(TRUE)
2774 {
2775 ConInKey(Ir);
2776
2777 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2778 {
2779 return(QUIT_PAGE);
2780 }
2781 }
2782 }
2783 }
2784 }
2785 else if (DoesFileExist(SystemRootPath.Buffer, L"io.sys") == TRUE ||
2786 DoesFileExist(SystemRootPath.Buffer, L"msdos.sys") == TRUE)
2787 {
2788 /* Search for root directory for 'io.sys' and 'msdos.sys'. */
2789 DPRINT1("Found Microsoft DOS or Windows 9x boot loader\n");
2790
2791 /* Copy FreeLoader to the boot partition */
2792 wcscpy(SrcPath, SourceRootPath.Buffer);
2793 wcscat(SrcPath, L"\\loader\\freeldr.sys");
2794 wcscpy(DstPath, SystemRootPath.Buffer);
2795 wcscat(DstPath, L"\\freeldr.sys");
2796
2797 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
2798 Status = SetupCopyFile(SrcPath, DstPath);
2799 if (!NT_SUCCESS(Status))
2800 {
2801 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
2802 PopupError("Setup failed to copy 'freeldr.sys'.",
2803 "ENTER = Reboot computer");
2804
2805 while(TRUE)
2806 {
2807 ConInKey(Ir);
2808
2809 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2810 {
2811 return(QUIT_PAGE);
2812 }
2813 }
2814 }
2815
2816 /* Create or update 'freeldr.ini' */
2817 if (DoesFileExist(SystemRootPath.Buffer, L"freeldr.ini") == FALSE)
2818 {
2819 /* Create new 'freeldr.ini' */
2820 DPRINT1("Create new 'freeldr.ini'\n");
2821 wcscpy(DstPath, SystemRootPath.Buffer);
2822 wcscat(DstPath, L"\\freeldr.ini");
2823
2824 Status = CreateFreeLoaderIniForDos(DstPath,
2825 DestinationArcPath.Buffer);
2826 if (!NT_SUCCESS(Status))
2827 {
2828 DPRINT1("CreateFreeLoaderIniForDos() failed (Status %lx)\n", Status);
2829 PopupError("Setup failed to create 'freeldr.ini'.",
2830 "ENTER = Reboot computer");
2831
2832 while(TRUE)
2833 {
2834 ConInKey(Ir);
2835
2836 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2837 {
2838 return(QUIT_PAGE);
2839 }
2840 }
2841 }
2842
2843 /* Save current bootsector as 'BOOTSECT.DOS' */
2844 wcscpy(SrcPath, SystemRootPath.Buffer);
2845 wcscpy(DstPath, SystemRootPath.Buffer);
2846 wcscat(DstPath, L"\\bootsect.dos");
2847
2848 DPRINT1("Save bootsector: %S ==> %S\n", SrcPath, DstPath);
2849 Status = SaveCurrentBootSector(SrcPath,
2850 DstPath);
2851 if (!NT_SUCCESS(Status))
2852 {
2853 DPRINT1("SaveCurrentBootSector() failed (Status %lx)\n", Status);
2854 PopupError("Setup failed to save the current bootsector.",
2855 "ENTER = Reboot computer");
2856
2857 while(TRUE)
2858 {
2859 ConInKey(Ir);
2860
2861 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2862 {
2863 return(QUIT_PAGE);
2864 }
2865 }
2866 }
2867
2868 /* Install new bootsector */
2869 if ((PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_FAT32) ||
2870 (PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_FAT32_XINT13))
2871 {
2872 wcscpy(SrcPath, SourceRootPath.Buffer);
2873 wcscat(SrcPath, L"\\loader\\fat32.bin");
2874
2875 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, SystemRootPath.Buffer);
2876 Status = InstallFat32BootCodeToDisk(SrcPath,
2877 SystemRootPath.Buffer);
2878 if (!NT_SUCCESS(Status))
2879 {
2880 DPRINT1("InstallFat32BootCodeToDisk() failed (Status %lx)\n", Status);
2881 PopupError("Setup failed to install the FAT32 bootcode.",
2882 "ENTER = Reboot computer");
2883
2884 while(TRUE)
2885 {
2886 ConInKey(Ir);
2887
2888 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2889 {
2890 return(QUIT_PAGE);
2891 }
2892 }
2893 }
2894 }
2895 else
2896 {
2897 wcscpy(SrcPath, SourceRootPath.Buffer);
2898 wcscat(SrcPath, L"\\loader\\fat.bin");
2899
2900 DPRINT1("Install FAT bootcode: %S ==> %S\n", SrcPath, SystemRootPath.Buffer);
2901 Status = InstallFat16BootCodeToDisk(SrcPath,
2902 SystemRootPath.Buffer);
2903 if (!NT_SUCCESS(Status))
2904 {
2905 DPRINT1("InstallFat16BootCodeToDisk() failed (Status %lx)\n", Status);
2906 PopupError("Setup failed to install the FAT bootcode.",
2907 "ENTER = Reboot computer");
2908
2909 while(TRUE)
2910 {
2911 ConInKey(Ir);
2912
2913 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2914 {
2915 return(QUIT_PAGE);
2916 }
2917 }
2918 }
2919 }
2920 }
2921 else
2922 {
2923 /* Update existing 'freeldr.ini' */
2924 wcscpy(DstPath, SystemRootPath.Buffer);
2925 wcscat(DstPath, L"\\freeldr.ini");
2926
2927 Status = UpdateFreeLoaderIni(DstPath,
2928 DestinationArcPath.Buffer);
2929 if (!NT_SUCCESS(Status))
2930 {
2931 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
2932 PopupError("Setup failed to update 'freeldr.ini'.",
2933 "ENTER = Reboot computer");
2934
2935 while(TRUE)
2936 {
2937 ConInKey(Ir);
2938
2939 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2940 {
2941 return(QUIT_PAGE);
2942 }
2943 }
2944 }
2945 }
2946 }
2947 else
2948 {
2949 /* No or unknown boot loader */
2950 DPRINT1("No or unknown boot loader found\n");
2951
2952 /* Copy FreeLoader to the boot partition */
2953 wcscpy(SrcPath, SourceRootPath.Buffer);
2954 wcscat(SrcPath, L"\\loader\\freeldr.sys");
2955 wcscpy(DstPath, SystemRootPath.Buffer);
2956 wcscat(DstPath, L"\\freeldr.sys");
2957
2958 DPRINT1("Copy: %S ==> %S\n", SrcPath, DstPath);
2959 Status = SetupCopyFile(SrcPath, DstPath);
2960 if (!NT_SUCCESS(Status))
2961 {
2962 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
2963 PopupError("Setup failed to copy 'freeldr.sys'.",
2964 "ENTER = Reboot computer");
2965
2966 while(TRUE)
2967 {
2968 ConInKey(Ir);
2969
2970 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2971 {
2972 return(QUIT_PAGE);
2973 }
2974 }
2975 }
2976
2977 /* Create or update 'freeldr.ini' */
2978 if (DoesFileExist(SystemRootPath.Buffer, L"freeldr.ini") == FALSE)
2979 {
2980 /* Create new freeldr.ini */
2981 wcscpy(DstPath, SystemRootPath.Buffer);
2982 wcscat(DstPath, L"\\freeldr.ini");
2983
2984 DPRINT1("Copy: %S ==> %S\n", SrcPath, DstPath);
2985 Status = CreateFreeLoaderIniForReactos(DstPath,
2986 DestinationArcPath.Buffer);
2987 if (!NT_SUCCESS(Status))
2988 {
2989 DPRINT1("CreateFreeLoaderIniForReactos() failed (Status %lx)\n", Status);
2990 PopupError("Setup failed to create \'freeldr.ini\'.",
2991 "ENTER = Reboot computer");
2992
2993 while(TRUE)
2994 {
2995 ConInKey(Ir);
2996
2997 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2998 {
2999 return(QUIT_PAGE);
3000 }
3001 }
3002 }
3003
3004 /* Save current bootsector as 'BOOTSECT.OLD' */
3005 wcscpy(SrcPath, SystemRootPath.Buffer);
3006 wcscpy(DstPath, SystemRootPath.Buffer);
3007 wcscat(DstPath, L"\\bootsect.old");
3008
3009 DPRINT1("Save bootsector: %S ==> %S\n", SrcPath, DstPath);
3010 Status = SaveCurrentBootSector(SrcPath,
3011 DstPath);
3012 if (!NT_SUCCESS(Status))
3013 {
3014 DPRINT1("SaveCurrentBootSector() failed (Status %lx)\n", Status);
3015 PopupError("Setup failed save the current bootsector.",
3016 "ENTER = Reboot computer");
3017
3018 while(TRUE)
3019 {
3020 ConInKey(Ir);
3021
3022 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
3023 {
3024 return(QUIT_PAGE);
3025 }
3026 }
3027 }
3028
3029 /* Install new bootsector */
3030 if ((PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_FAT32) ||
3031 (PartitionList->ActiveBootPartition->PartInfo[0].PartitionType == PARTITION_FAT32_XINT13))
3032 {
3033 wcscpy(SrcPath, SourceRootPath.Buffer);
3034 wcscat(SrcPath, L"\\loader\\fat32.bin");
3035
3036 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, SystemRootPath.Buffer);
3037 Status = InstallFat32BootCodeToDisk(SrcPath,
3038 SystemRootPath.Buffer);
3039 if (!NT_SUCCESS(Status))
3040 {
3041 DPRINT1("InstallFat32BootCodeToDisk() failed (Status %lx)\n", Status);
3042 PopupError("Setup failed to install the FAT32 bootcode.",
3043 "ENTER = Reboot computer");
3044
3045 while(TRUE)
3046 {
3047 ConInKey(Ir);
3048
3049 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
3050 {
3051 return(QUIT_PAGE);
3052 }
3053 }
3054 }
3055 }
3056 else
3057 {
3058 wcscpy(SrcPath, SourceRootPath.Buffer);
3059 wcscat(SrcPath, L"\\loader\\fat.bin");
3060
3061 DPRINT1("Install FAT bootcode: %S ==> %S\n", SrcPath, SystemRootPath.Buffer);
3062 Status = InstallFat16BootCodeToDisk(SrcPath,
3063 SystemRootPath.Buffer);
3064 if (!NT_SUCCESS(Status))
3065 {
3066 DPRINT1("InstallFat16BootCodeToDisk() failed (Status %lx)\n", Status);
3067 PopupError("Setup failed to install the FAT bootcode.",
3068 "ENTER = Reboot computer");
3069
3070 while(TRUE)
3071 {
3072 ConInKey(Ir);
3073
3074 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
3075 {
3076 return(QUIT_PAGE);
3077 }
3078 }
3079 }
3080 }
3081 }
3082 else
3083 {
3084 /* Update existing 'freeldr.ini' */
3085 wcscpy(DstPath, SystemRootPath.Buffer);
3086 wcscat(DstPath, L"\\freeldr.ini");
3087
3088 Status = UpdateFreeLoaderIni(DstPath,
3089 DestinationArcPath.Buffer);
3090 if (!NT_SUCCESS(Status))
3091 {
3092 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
3093 PopupError("Setup failed to update 'freeldr.ini'.",
3094 "ENTER = Reboot computer");
3095
3096 while(TRUE)
3097 {
3098 ConInKey(Ir);
3099
3100 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
3101 {
3102 return(QUIT_PAGE);
3103 }
3104 }
3105 }
3106 }
3107 }
3108 }
3109 else
3110 {
3111 /* Unknown partition */
3112 DPRINT1("Unknown partition found\n");
3113 PopupError("Setup found an unknown partiton type.\n"
3114 "This partition type is not supported!",
3115 "ENTER = Reboot computer");
3116
3117 while(TRUE)
3118 {
3119 ConInKey(Ir);
3120
3121 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
3122 {
3123 return(QUIT_PAGE);
3124 }
3125 }
3126 }
3127
3128 return(SUCCESS_PAGE);
3129 }
3130
3131
3132
3133 static PAGE_NUMBER
3134 QuitPage(PINPUT_RECORD Ir)
3135 {
3136 SetTextXY(10, 6, "ReactOS is not completely installed");
3137
3138 SetTextXY(10, 8, "Remove floppy disk from Drive A: and");
3139 SetTextXY(10, 9, "all CD-ROMs from CD-Drives.");
3140
3141 SetTextXY(10, 11, "Press ENTER to reboot your computer.");
3142
3143 SetStatusText(" Please wait ...");
3144
3145 /* Destroy partition list */
3146 if (PartitionList != NULL)
3147 {
3148 DestroyPartitionList (PartitionList);
3149 PartitionList = NULL;
3150 }
3151
3152 /* Destroy filesystem list */
3153 if (FileSystemList != NULL)
3154 {
3155 DestroyFileSystemList (FileSystemList);
3156 FileSystemList = NULL;
3157 }
3158
3159 SetStatusText(" ENTER = Reboot computer");
3160
3161 while(TRUE)
3162 {
3163 ConInKey(Ir);
3164
3165 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
3166 {
3167 return(REBOOT_PAGE);
3168 }
3169 }
3170 }
3171
3172
3173 static PAGE_NUMBER
3174 SuccessPage(PINPUT_RECORD Ir)
3175 {
3176 SetTextXY(10, 6, "The basic components of ReactOS have been installed successfully.");
3177
3178 SetTextXY(10, 8, "Remove floppy disk from Drive A: and");
3179 SetTextXY(10, 9, "all CD-ROMs from CD-Drive.");
3180
3181 SetTextXY(10, 11, "Press ENTER to reboot your computer.");
3182
3183 SetStatusText(" ENTER = Reboot computer");
3184
3185 while(TRUE)
3186 {
3187 ConInKey(Ir);
3188
3189 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
3190 {
3191 return(REBOOT_PAGE);
3192 }
3193 }
3194 }
3195
3196
3197 VOID STDCALL
3198 NtProcessStartup(PPEB Peb)
3199 {
3200 NTSTATUS Status;
3201 INPUT_RECORD Ir;
3202 PAGE_NUMBER Page;
3203
3204 RtlNormalizeProcessParams(Peb->ProcessParameters);
3205
3206 ProcessHeap = Peb->ProcessHeap;
3207
3208 Status = AllocConsole();
3209 if (!NT_SUCCESS(Status))
3210 {
3211 PrintString("AllocConsole() failed (Status = 0x%08lx)\n", Status);
3212
3213 /* Raise a hard error (crash the system/BSOD) */
3214 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED,
3215 0,0,0,0,0);
3216 }
3217
3218
3219 /* Initialize global unicode strings */
3220 RtlInitUnicodeString(&SourcePath, NULL);
3221 RtlInitUnicodeString(&SourceRootPath, NULL);
3222 RtlInitUnicodeString(&InstallPath, NULL);
3223 RtlInitUnicodeString(&DestinationPath, NULL);
3224 RtlInitUnicodeString(&DestinationArcPath, NULL);
3225 RtlInitUnicodeString(&DestinationRootPath, NULL);
3226 RtlInitUnicodeString(&SystemRootPath, NULL);
3227
3228
3229 Page = START_PAGE;
3230 while (Page != REBOOT_PAGE)
3231 {
3232 ClearScreen();
3233
3234 SetUnderlinedTextXY(4, 3, " ReactOS " KERNEL_VERSION_STR " Setup ");
3235
3236 switch (Page)
3237 {
3238 /* Start page */
3239 case START_PAGE:
3240 Page = StartPage(&Ir);
3241 break;
3242
3243 /* Intro page */
3244 case INTRO_PAGE:
3245 Page = IntroPage(&Ir);
3246 break;
3247
3248 /* Install pages */
3249 case INSTALL_INTRO_PAGE:
3250 Page = InstallIntroPage(&Ir);
3251 break;
3252
3253 #if 0
3254 case OEM_DRIVER_PAGE:
3255 Page = OemDriverPage(&Ir);
3256 break;
3257 #endif
3258
3259 #if 0
3260 case DEVICE_SETTINGS_PAGE:
3261 #endif
3262
3263 case SELECT_PARTITION_PAGE:
3264 Page = SelectPartitionPage(&Ir);
3265 break;
3266
3267 case CREATE_PARTITION_PAGE:
3268 Page = CreatePartitionPage(&Ir);
3269 break;
3270
3271 case DELETE_PARTITION_PAGE:
3272 Page = DeletePartitionPage(&Ir);
3273 break;
3274
3275 case SELECT_FILE_SYSTEM_PAGE:
3276 Page = SelectFileSystemPage(&Ir);
3277 break;
3278
3279 case FORMAT_PARTITION_PAGE:
3280 Page = FormatPartitionPage(&Ir);
3281 break;
3282
3283 case CHECK_FILE_SYSTEM_PAGE:
3284 Page = CheckFileSystemPage(&Ir);
3285 break;
3286
3287 case INSTALL_DIRECTORY_PAGE:
3288 Page = InstallDirectoryPage(&Ir);
3289 break;
3290
3291 case PREPARE_COPY_PAGE:
3292 Page = PrepareCopyPage(&Ir);
3293 break;
3294
3295 case FILE_COPY_PAGE:
3296 Page = FileCopyPage(&Ir);
3297 break;
3298
3299 case REGISTRY_PAGE:
3300 Page = RegistryPage(&Ir);
3301 break;
3302
3303 case BOOT_LOADER_PAGE:
3304 Page = BootLoaderPage(&Ir);
3305 break;
3306
3307
3308 /* Repair pages */
3309 case REPAIR_INTRO_PAGE:
3310 Page = RepairIntroPage(&Ir);
3311 break;
3312
3313
3314 /* Emergency pages */
3315 case EMERGENCY_INTRO_PAGE:
3316 Page = EmergencyIntroPage(&Ir);
3317 break;
3318
3319
3320 case SUCCESS_PAGE:
3321 Page = SuccessPage(&Ir);
3322 break;
3323
3324 case QUIT_PAGE:
3325 Page = QuitPage(&Ir);
3326 break;
3327 }
3328 }
3329
3330 /* Reboot */
3331 FreeConsole();
3332 NtShutdownSystem(ShutdownReboot);
3333 }
3334
3335 /* EOF */