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