Reorganize registry initialization.
[reactos.git] / reactos / subsys / system / usetup / usetup.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 2002 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 */
26
27 #include <ddk/ntddk.h>
28 #include <ntdll/rtl.h>
29
30 #include <ntos/minmax.h>
31 #include <reactos/resource.h>
32
33 #include "usetup.h"
34 #include "console.h"
35 #include "partlist.h"
36 #include "inicache.h"
37 #include "infcache.h"
38 #include "filequeue.h"
39 #include "progress.h"
40 #include "bootsup.h"
41 #include "registry.h"
42
43
44 #define START_PAGE 0
45 #define INTRO_PAGE 1
46 #define INSTALL_INTRO_PAGE 2
47
48 #define SELECT_PARTITION_PAGE 4
49 #define SELECT_FILE_SYSTEM_PAGE 5
50 #define CHECK_FILE_SYSTEM_PAGE 6
51 #define PREPARE_COPY_PAGE 7
52 #define INSTALL_DIRECTORY_PAGE 8
53 #define FILE_COPY_PAGE 9
54 #define REGISTRY_PAGE 10
55 #define BOOT_LOADER_PAGE 11
56
57 #define REPAIR_INTRO_PAGE 20
58
59 #define SUCCESS_PAGE 100
60 #define QUIT_PAGE 101
61 #define REBOOT_PAGE 102
62
63
64 typedef struct _COPYCONTEXT
65 {
66 ULONG TotalOperations;
67 ULONG CompletedOperations;
68 PPROGRESS ProgressBar;
69 } COPYCONTEXT, *PCOPYCONTEXT;
70
71
72 /* GLOBALS ******************************************************************/
73
74 HANDLE ProcessHeap;
75
76 BOOLEAN PartDataValid;
77 PARTDATA PartData;
78
79 BOOLEAN ActivePartitionValid;
80 PARTDATA ActivePartition;
81
82 UNICODE_STRING SourcePath;
83 UNICODE_STRING SourceRootPath;
84
85 UNICODE_STRING InstallPath;
86 UNICODE_STRING DestinationPath;
87 UNICODE_STRING DestinationArcPath;
88 UNICODE_STRING DestinationRootPath;
89
90 UNICODE_STRING SystemRootPath; /* Path to the active partition */
91
92 HINF SetupInf;
93
94 HSPFILEQ SetupFileQueue = NULL;
95
96
97 /* FUNCTIONS ****************************************************************/
98
99 static VOID
100 PrintString(char* fmt,...)
101 {
102 char buffer[512];
103 va_list ap;
104 UNICODE_STRING UnicodeString;
105 ANSI_STRING AnsiString;
106
107 va_start(ap, fmt);
108 vsprintf(buffer, fmt, ap);
109 va_end(ap);
110
111 RtlInitAnsiString(&AnsiString, buffer);
112 RtlAnsiStringToUnicodeString(&UnicodeString,
113 &AnsiString,
114 TRUE);
115 NtDisplayString(&UnicodeString);
116 RtlFreeUnicodeString(&UnicodeString);
117 }
118
119
120 static VOID
121 PopupError(PCHAR Text,
122 PCHAR Status)
123 {
124 SHORT xScreen;
125 SHORT yScreen;
126 SHORT yTop;
127 SHORT xLeft;
128 COORD coPos;
129 ULONG Written;
130 ULONG Length;
131 ULONG MaxLength;
132 ULONG Lines;
133 PCHAR p;
134 PCHAR pnext;
135 BOOLEAN LastLine;
136 SHORT Width;
137 SHORT Height;
138
139 /* Count text lines and longest line */
140 MaxLength = 0;
141 Lines = 0;
142 pnext = Text;
143 while (TRUE)
144 {
145 p = strchr(pnext, '\n');
146 if (p == NULL)
147 {
148 Length = strlen(pnext);
149 LastLine = TRUE;
150 }
151 else
152 {
153 Length = (ULONG)(p - pnext);
154 LastLine = FALSE;
155 }
156
157 Lines++;
158 if (Length > MaxLength)
159 MaxLength = Length;
160
161 if (LastLine == TRUE)
162 break;
163
164 pnext = p + 1;
165 }
166
167 /* Check length of status line */
168 if (Status != NULL)
169 {
170 Length = strlen(Status);
171 if (Length > MaxLength)
172 MaxLength = Length;
173 }
174
175 GetScreenSize(&xScreen, &yScreen);
176
177 Width = MaxLength + 4;
178 Height = Lines + 2;
179 if (Status != NULL)
180 Height += 2;
181
182 yTop = (yScreen - Height) / 2;
183 xLeft = (xScreen - Width) / 2;
184
185
186 /* Set screen attributes */
187 coPos.X = xLeft;
188 for (coPos.Y = yTop; coPos.Y < yTop + Height; coPos.Y++)
189 {
190 FillConsoleOutputAttribute(0x74,
191 Width,
192 coPos,
193 &Written);
194 }
195
196 /* draw upper left corner */
197 coPos.X = xLeft;
198 coPos.Y = yTop;
199 FillConsoleOutputCharacter(0xDA, // '+',
200 1,
201 coPos,
202 &Written);
203
204 /* draw upper edge */
205 coPos.X = xLeft + 1;
206 coPos.Y = yTop;
207 FillConsoleOutputCharacter(0xC4, // '-',
208 Width - 2,
209 coPos,
210 &Written);
211
212 /* draw upper right corner */
213 coPos.X = xLeft + Width - 1;
214 coPos.Y = yTop;
215 FillConsoleOutputCharacter(0xBF, // '+',
216 1,
217 coPos,
218 &Written);
219
220 /* Draw right edge, inner space and left edge */
221 for (coPos.Y = yTop + 1; coPos.Y < yTop + Height - 1; coPos.Y++)
222 {
223 coPos.X = xLeft;
224 FillConsoleOutputCharacter(0xB3, // '|',
225 1,
226 coPos,
227 &Written);
228
229 coPos.X = xLeft + 1;
230 FillConsoleOutputCharacter(' ',
231 Width - 2,
232 coPos,
233 &Written);
234
235 coPos.X = xLeft + Width - 1;
236 FillConsoleOutputCharacter(0xB3, // '|',
237 1,
238 coPos,
239 &Written);
240 }
241
242 /* draw lower left corner */
243 coPos.X = xLeft;
244 coPos.Y = yTop + Height - 1;
245 FillConsoleOutputCharacter(0xC0, // '+',
246 1,
247 coPos,
248 &Written);
249
250 /* draw lower edge */
251 coPos.X = xLeft + 1;
252 coPos.Y = yTop + Height - 1;
253 FillConsoleOutputCharacter(0xC4, // '-',
254 Width - 2,
255 coPos,
256 &Written);
257
258 /* draw lower right corner */
259 coPos.X = xLeft + Width - 1;
260 coPos.Y = yTop + Height - 1;
261 FillConsoleOutputCharacter(0xD9, // '+',
262 1,
263 coPos,
264 &Written);
265
266 /* Print message text */
267 coPos.Y = yTop + 1;
268 pnext = Text;
269 while (TRUE)
270 {
271 p = strchr(pnext, '\n');
272 if (p == NULL)
273 {
274 Length = strlen(pnext);
275 LastLine = TRUE;
276 }
277 else
278 {
279 Length = (ULONG)(p - pnext);
280 LastLine = FALSE;
281 }
282
283 if (Length != 0)
284 {
285 coPos.X = xLeft + 2;
286 WriteConsoleOutputCharacters(pnext,
287 Length,
288 coPos);
289 }
290
291 if (LastLine == TRUE)
292 break;
293
294 coPos.Y++;
295 pnext = p + 1;
296 }
297
298 /* Print separator line and status text */
299 if (Status != NULL)
300 {
301 coPos.Y = yTop + Height - 3;
302 coPos.X = xLeft;
303 FillConsoleOutputCharacter(0xC3, // '+',
304 1,
305 coPos,
306 &Written);
307
308 coPos.X = xLeft + 1;
309 FillConsoleOutputCharacter(0xC4, // '-',
310 Width - 2,
311 coPos,
312 &Written);
313
314 coPos.X = xLeft + Width - 1;
315 FillConsoleOutputCharacter(0xB4, // '+',
316 1,
317 coPos,
318 &Written);
319
320 coPos.Y++;
321 coPos.X = xLeft + 2;
322 WriteConsoleOutputCharacters(Status,
323 min(strlen(Status), Width - 4),
324 coPos);
325 }
326 }
327
328
329 /*
330 * Confirm quit setup
331 * RETURNS
332 * TRUE: Quit setup.
333 * FALSE: Don't quit setup.
334 */
335 static BOOL
336 ConfirmQuit(PINPUT_RECORD Ir)
337 {
338 BOOL Result = FALSE;
339
340 PopupError("ReactOS is not completely installed on your\n"
341 "computer. If you quit Setup now, you will need to\n"
342 "run Setup again to install ReactOS.\n"
343 "\n"
344 " * Press ENTER to continue Setup.\n"
345 " * Press F3 to quit Setup.",
346 "F3= Quit ENTER = Continue");
347
348 while(TRUE)
349 {
350 ConInKey(Ir);
351
352 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
353 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
354 {
355 Result = TRUE;
356 break;
357 }
358 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
359 {
360 Result = FALSE;
361 break;
362 }
363 }
364
365 return(Result);
366 }
367
368
369
370 /*
371 * Start page
372 * RETURNS
373 * Number of the next page.
374 */
375 static ULONG
376 StartPage(PINPUT_RECORD Ir)
377 {
378 NTSTATUS Status;
379 WCHAR FileNameBuffer[MAX_PATH];
380 UNICODE_STRING FileName;
381
382 INFCONTEXT Context;
383 PWCHAR Value;
384 ULONG ErrorLine;
385
386
387 SetStatusText(" Please wait...");
388
389 Status = GetSourcePaths(&SourcePath,
390 &SourceRootPath);
391 if (!NT_SUCCESS(Status))
392 {
393 PrintTextXY(6, 15, "GetSourcePath() failed (Status 0x%08lx)", Status);
394 }
395 else
396 {
397 PrintTextXY(6, 15, "SourcePath: '%wZ'", &SourcePath);
398 PrintTextXY(6, 16, "SourceRootPath: '%wZ'", &SourceRootPath);
399 }
400
401
402 /* Load txtsetup.sif from install media. */
403 wcscpy(FileNameBuffer, SourceRootPath.Buffer);
404 wcscat(FileNameBuffer, L"\\install\\txtsetup.sif");
405 RtlInitUnicodeString(&FileName,
406 FileNameBuffer);
407
408 Status = InfOpenFile(&SetupInf,
409 &FileName,
410 &ErrorLine);
411 if (!NT_SUCCESS(Status))
412 {
413 PopupError("Setup failed to load the file TXTSETUP.SIF.\n",
414 "ENTER = Reboot computer");
415
416 while(TRUE)
417 {
418 ConInKey(Ir);
419
420 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
421 {
422 return(QUIT_PAGE);
423 }
424 }
425 }
426
427 /* Open 'Version' section */
428 if (!InfFindFirstLine (SetupInf, L"Version", L"Signature", &Context))
429 {
430 PopupError("Setup found a corrupt TXTSETUP.SIF.\n",
431 "ENTER = Reboot computer");
432
433 while(TRUE)
434 {
435 ConInKey(Ir);
436
437 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
438 {
439 return(QUIT_PAGE);
440 }
441 }
442 }
443
444
445 /* Get pointer 'Signature' key */
446 if (!InfGetData (&Context, NULL, &Value))
447 {
448 PopupError("Setup found a corrupt TXTSETUP.SIF.\n",
449 "ENTER = Reboot computer");
450
451 while(TRUE)
452 {
453 ConInKey(Ir);
454
455 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
456 {
457 return(QUIT_PAGE);
458 }
459 }
460 }
461
462 /* Check 'Signature' string */
463 if (_wcsicmp(Value, L"$ReactOS$") != 0)
464 {
465 PopupError("Setup found an invalid signature in TXTSETUP.SIF.\n",
466 "ENTER = Reboot computer");
467
468 while(TRUE)
469 {
470 ConInKey(Ir);
471
472 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
473 {
474 return(QUIT_PAGE);
475 }
476 }
477 }
478
479 return(INTRO_PAGE);
480 }
481
482
483
484 static ULONG
485 RepairIntroPage(PINPUT_RECORD Ir)
486 {
487 SetTextXY(6, 8, "ReactOS Setup is in an early development phase. It does not yet");
488 SetTextXY(6, 9, "support all the functions of a fully usable setup application.");
489
490 SetTextXY(6, 12, "The repair functions are not implemented yet.");
491
492 SetTextXY(8, 15, "\xfa Press ESC to return to the main page.");
493
494 SetTextXY(8, 17, "\xfa Press ENTER to reboot your computer.");
495
496 SetStatusText(" ESC = Main page ENTER = Reboot");
497
498 while(TRUE)
499 {
500 ConInKey(Ir);
501
502 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
503 {
504 return(REBOOT_PAGE);
505 }
506 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
507 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
508 {
509 return(INTRO_PAGE);
510 }
511 }
512
513 return(REPAIR_INTRO_PAGE);
514 }
515
516
517 /*
518 * First setup page
519 * RETURNS
520 * TRUE: setup/repair completed successfully
521 * FALSE: setup/repair terminated by user
522 */
523 static ULONG
524 IntroPage(PINPUT_RECORD Ir)
525 {
526 SetHighlightedTextXY(6, 8, "Welcome to ReactOS Setup");
527
528 SetTextXY(6, 11, "This part of the setup copies the ReactOS Operating System to your");
529 SetTextXY(6, 12, "computer and prepares the second part of the setup.");
530
531 SetTextXY(8, 15, "\xfa Press ENTER to install ReactOS.");
532
533 SetTextXY(8, 17, "\xfa Press E to start the emergency repair console.");
534
535 SetTextXY(8, 19, "\xfa Press R to repair ReactOS.");
536
537 SetTextXY(8, 21, "\xfa Press F3 to quit without installing ReactOS.");
538
539
540 SetStatusText(" ENTER = Continue F3 = Quit");
541
542 while(TRUE)
543 {
544 ConInKey(Ir);
545
546 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
547 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
548 {
549 if (ConfirmQuit(Ir) == TRUE)
550 return(QUIT_PAGE);
551 break;
552 }
553 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
554 {
555 return(INSTALL_INTRO_PAGE);
556 }
557 #if 0
558 else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'E') /* E */
559 {
560 return(RepairConsole());
561 }
562 #endif
563 else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'R') /* R */
564 {
565 return(REPAIR_INTRO_PAGE);
566 }
567 }
568
569 return(INTRO_PAGE);
570 }
571
572
573 static ULONG
574 InstallIntroPage(PINPUT_RECORD Ir)
575 {
576 SetTextXY(6, 8, "ReactOS Setup is in an early development phase. It does not yet");
577 SetTextXY(6, 9, "support all the functions of a fully usable setup application.");
578
579 SetTextXY(6, 12, "The following functions are missing:");
580 SetTextXY(8, 13, "- Creating and deleting harddisk partitions.");
581 SetTextXY(8, 14, "- Formatting partitions.");
582 SetTextXY(8, 15, "- Support for non-FAT file systems.");
583 SetTextXY(8, 16, "- Checking file systems.");
584
585
586
587 SetTextXY(8, 21, "\xfa Press ENTER to install ReactOS.");
588
589 SetTextXY(8, 23, "\xfa Press F3 to quit without installing ReactOS.");
590
591
592 SetStatusText(" ENTER = Continue F3 = Quit");
593
594 while(TRUE)
595 {
596 ConInKey(Ir);
597
598 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
599 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
600 {
601 if (ConfirmQuit(Ir) == TRUE)
602 return(QUIT_PAGE);
603 break;
604 }
605 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
606 {
607 return(SELECT_PARTITION_PAGE);
608 }
609 }
610
611 return(INSTALL_INTRO_PAGE);
612 }
613
614
615 static ULONG
616 SelectPartitionPage(PINPUT_RECORD Ir)
617 {
618 WCHAR PathBuffer[MAX_PATH];
619 PPARTLIST PartList;
620 SHORT xScreen;
621 SHORT yScreen;
622
623 SetTextXY(6, 8, "The list below shows existing partitions and unused disk");
624 SetTextXY(6, 9, "space for new partitions.");
625
626 SetTextXY(8, 11, "\xfa Press UP or DOWN to select a list entry.");
627 SetTextXY(8, 13, "\xfa Press ENTER to install ReactOS onto the selected partition.");
628 SetTextXY(8, 15, "\xfa Press C to create a new partition.");
629 SetTextXY(8, 17, "\xfa Press D to delete an existing partition.");
630
631 SetStatusText(" Please wait...");
632
633 RtlFreeUnicodeString(&DestinationPath);
634 RtlFreeUnicodeString(&DestinationRootPath);
635
636 GetScreenSize(&xScreen, &yScreen);
637
638 PartList = CreatePartitionList(2, 19, xScreen - 3, yScreen - 3);
639 if (PartList == NULL)
640 {
641 /* FIXME: show an error dialog */
642 return(QUIT_PAGE);
643 }
644
645 SetStatusText(" ENTER = Continue F3 = Quit");
646
647 while(TRUE)
648 {
649 ConInKey(Ir);
650
651 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
652 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
653 {
654 if (ConfirmQuit(Ir) == TRUE)
655 {
656 DestroyPartitionList(PartList);
657 return(QUIT_PAGE);
658 }
659 break;
660 }
661 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
662 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
663 {
664 ScrollDownPartitionList(PartList);
665 }
666 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
667 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
668 {
669 ScrollUpPartitionList(PartList);
670 }
671 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
672 {
673 PartDataValid = GetSelectedPartition(PartList,
674 &PartData);
675 ActivePartitionValid = GetActiveBootPartition(PartList,
676 &ActivePartition);
677 DestroyPartitionList(PartList);
678
679 RtlFreeUnicodeString(&DestinationRootPath);
680 swprintf(PathBuffer,
681 L"\\Device\\Harddisk%lu\\Partition%lu",
682 PartData.DiskNumber,
683 PartData.PartNumber);
684 RtlCreateUnicodeString(&DestinationRootPath,
685 PathBuffer);
686
687 RtlFreeUnicodeString(&SystemRootPath);
688 swprintf(PathBuffer,
689 L"\\Device\\Harddisk%lu\\Partition%lu",
690 ActivePartition.DiskNumber,
691 ActivePartition.PartNumber);
692 RtlCreateUnicodeString(&SystemRootPath,
693 PathBuffer);
694
695 return(SELECT_FILE_SYSTEM_PAGE);
696 }
697
698 /* FIXME: Update status text */
699
700 }
701
702 DestroyPartitionList(PartList);
703
704 return(SELECT_PARTITION_PAGE);
705 }
706
707
708 static ULONG
709 SelectFileSystemPage(PINPUT_RECORD Ir)
710 {
711 ULONGLONG DiskSize;
712 ULONGLONG PartSize;
713 PCHAR DiskUnit;
714 PCHAR PartUnit;
715 PCHAR PartType;
716
717 if (PartDataValid == FALSE)
718 {
719 /* FIXME: show an error dialog */
720 return(QUIT_PAGE);
721 }
722
723 /* adjust disk size */
724 if (PartData.DiskSize >= 0x280000000ULL) /* 10 GB */
725 {
726 DiskSize = (PartData.DiskSize + (1 << 29)) >> 30;
727 DiskUnit = "GB";
728 }
729 else
730 {
731 DiskSize = (PartData.DiskSize + (1 << 19)) >> 20;
732 DiskUnit = "MB";
733 }
734
735 /* adjust partition size */
736 if (PartData.PartSize >= 0x280000000ULL) /* 10 GB */
737 {
738 PartSize = (PartData.PartSize + (1 << 29)) >> 30;
739 PartUnit = "GB";
740 }
741 else
742 {
743 PartSize = (PartData.PartSize + (1 << 19)) >> 20;
744 PartUnit = "MB";
745 }
746
747 /* adjust partition type */
748 if ((PartData.PartType == PARTITION_FAT_12) ||
749 (PartData.PartType == PARTITION_FAT_16) ||
750 (PartData.PartType == PARTITION_HUGE) ||
751 (PartData.PartType == PARTITION_XINT13))
752 {
753 PartType = "FAT";
754 }
755 else if ((PartData.PartType == PARTITION_FAT32) ||
756 (PartData.PartType == PARTITION_FAT32_XINT13))
757 {
758 PartType = "FAT32";
759 }
760 else if (PartData.PartType == PARTITION_IFS)
761 {
762 PartType = "NTFS"; /* FIXME: Not quite correct! */
763 }
764 else
765 {
766 PartType = "Unknown";
767 }
768
769 SetTextXY(6, 8, "Setup will install ReactOS on");
770
771 PrintTextXY(8, 10, "Partition %lu (%I64u %s) %s of",
772 PartData.PartNumber,
773 PartSize,
774 PartUnit,
775 PartType);
776
777 PrintTextXY(8, 12, "Harddisk %lu (%I64u %s), Port=%hu, Bus=%hu, Id=%hu (%wZ).",
778 PartData.DiskNumber,
779 DiskSize,
780 DiskUnit,
781 PartData.Port,
782 PartData.Bus,
783 PartData.Id,
784 &PartData.DriverName);
785
786
787 SetTextXY(6, 17, "Select a file system for the partition from the list below.");
788
789 SetTextXY(8, 19, "\xfa Press UP or DOWN to select a file system.");
790 SetTextXY(8, 21, "\xfa Press ENTER to format the partition.");
791 SetTextXY(8, 23, "\xfa Press ESC to select another partition.");
792
793 /* FIXME: use a real list later */
794 SetInvertedTextXY(6, 26, " Keep current file system (no changes) ");
795
796
797 SetStatusText(" ENTER = Continue ESC = Cancel F3 = Quit");
798
799 while(TRUE)
800 {
801 ConInKey(Ir);
802
803 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
804 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
805 {
806 if (ConfirmQuit(Ir) == TRUE)
807 return(QUIT_PAGE);
808 break;
809 }
810 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
811 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
812 {
813 return(SELECT_PARTITION_PAGE);
814 }
815 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
816 {
817 return(CHECK_FILE_SYSTEM_PAGE);
818 }
819 }
820
821 return(SELECT_FILE_SYSTEM_PAGE);
822 }
823
824
825 static ULONG
826 CheckFileSystemPage(PINPUT_RECORD Ir)
827 {
828 SetTextXY(6, 8, "Check file system");
829
830 SetTextXY(6, 10, "At present, ReactOS can not check file systems.");
831
832 SetStatusText(" Please wait ...");
833
834
835 SetStatusText(" ENTER = Continue F3 = Quit");
836
837 while(TRUE)
838 {
839 ConInKey(Ir);
840
841 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
842 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
843 {
844 if (ConfirmQuit(Ir) == TRUE)
845 return(QUIT_PAGE);
846 break;
847 }
848 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
849 {
850 return(INSTALL_DIRECTORY_PAGE);
851 }
852 }
853
854 return(CHECK_FILE_SYSTEM_PAGE);
855 }
856
857
858 static ULONG
859 InstallDirectoryPage(PINPUT_RECORD Ir)
860 {
861 WCHAR PathBuffer[MAX_PATH];
862 WCHAR InstallDir[51];
863 PWCHAR DefaultPath;
864 INFCONTEXT Context;
865 ULONG Length;
866 NTSTATUS Status;
867
868 /* Search for 'DefaultPath' in the 'SetupData' section */
869 if (!InfFindFirstLine (SetupInf, L"SetupData", L"DefaultPath", &Context))
870 {
871 PopupError("Setup failed to find the 'SetupData' section\n"
872 "in TXTSETUP.SIF.\n",
873 "ENTER = Reboot computer");
874
875 while(TRUE)
876 {
877 ConInKey(Ir);
878
879 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
880 {
881 return(QUIT_PAGE);
882 }
883 }
884 }
885
886 /* Read the 'DefaultPath' data */
887 if (InfGetData (&Context, NULL, &DefaultPath))
888 {
889 wcscpy(InstallDir, DefaultPath);
890 }
891 else
892 {
893 wcscpy(InstallDir, L"\\ReactOS");
894 }
895 Length = wcslen(InstallDir);
896
897 SetTextXY(6, 8, "Setup installs ReactOS files onto the selected partition. Choose a");
898 SetTextXY(6, 9, "directory where you want ReactOS to be installed:");
899
900 SetInputTextXY(8, 11, 51, InstallDir);
901
902 SetTextXY(6, 14, "To change the suggested directory, press BACKSPACE to delete");
903 SetTextXY(6, 15, "characters and then type the directory where you want ReactOS to");
904 SetTextXY(6, 16, "be installed.");
905
906 SetStatusText(" ENTER = Continue F3 = Quit");
907
908 while(TRUE)
909 {
910 ConInKey(Ir);
911
912 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
913 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
914 {
915 if (ConfirmQuit(Ir) == TRUE)
916 return(QUIT_PAGE);
917 break;
918 }
919 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
920 {
921 /* Create 'InstallPath' string */
922 RtlFreeUnicodeString(&InstallPath);
923 RtlCreateUnicodeString(&InstallPath,
924 InstallDir);
925
926 /* Create 'DestinationPath' string */
927 RtlFreeUnicodeString(&DestinationPath);
928 wcscpy(PathBuffer,
929 DestinationRootPath.Buffer);
930 if (InstallDir[0] != L'\\')
931 wcscat(PathBuffer,
932 L"\\");
933 wcscat(PathBuffer, InstallDir);
934 RtlCreateUnicodeString(&DestinationPath,
935 PathBuffer);
936
937 /* Create 'DestinationArcPath' */
938 RtlFreeUnicodeString(&DestinationArcPath);
939 swprintf(PathBuffer,
940 L"multi(0)disk(0)rdisk(%lu)partition(%lu)",
941 PartData.DiskNumber,
942 PartData.PartNumber);
943 if (InstallDir[0] != L'\\')
944 wcscat(PathBuffer,
945 L"\\");
946 wcscat(PathBuffer, InstallDir);
947 RtlCreateUnicodeString(&DestinationArcPath,
948 PathBuffer);
949
950 return(PREPARE_COPY_PAGE);
951 }
952 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x08) /* BACKSPACE */
953 {
954 if (Length > 0)
955 {
956 Length--;
957 InstallDir[Length] = 0;
958 SetInputTextXY(8, 11, 51, InstallDir);
959 }
960 }
961 else if (isprint(Ir->Event.KeyEvent.uChar.AsciiChar))
962 {
963 if (Length < 50)
964 {
965 InstallDir[Length] = (WCHAR)Ir->Event.KeyEvent.uChar.AsciiChar;
966 Length++;
967 InstallDir[Length] = 0;
968 SetInputTextXY(8, 11, 51, InstallDir);
969 }
970 }
971 }
972
973 return(INSTALL_DIRECTORY_PAGE);
974 }
975
976
977 static ULONG
978 PrepareCopyPage(PINPUT_RECORD Ir)
979 {
980 WCHAR PathBuffer[MAX_PATH];
981 INFCONTEXT FilesContext;
982 INFCONTEXT DirContext;
983 PWCHAR KeyName;
984 PWCHAR KeyValue;
985 ULONG Length;
986 NTSTATUS Status;
987
988 PWCHAR FileKeyName;
989 PWCHAR FileKeyValue;
990 PWCHAR DirKeyName;
991 PWCHAR DirKeyValue;
992
993 SetTextXY(6, 8, "Setup prepares your computer for copying the ReactOS files. ");
994
995
996 // SetTextXY(8, 12, "Build file copy list");
997
998 // SetTextXY(8, 14, "Create directories");
999
1000 // SetStatusText(" Please wait...");
1001
1002
1003 /*
1004 * Build the file copy list
1005 */
1006 SetStatusText(" Building the file copy list...");
1007 // SetInvertedTextXY(8, 12, "Build file copy list");
1008
1009
1010
1011 /* Search for the 'SourceFiles' section */
1012 if (!InfFindFirstLine (SetupInf, L"SourceFiles", NULL, &FilesContext))
1013 {
1014 PopupError("Setup failed to find the 'SourceFiles' section\n"
1015 "in TXTSETUP.SIF.\n",
1016 "ENTER = Reboot computer");
1017
1018 while(TRUE)
1019 {
1020 ConInKey(Ir);
1021
1022 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1023 {
1024 return(QUIT_PAGE);
1025 }
1026 }
1027 }
1028
1029
1030 /* Create the file queue */
1031 SetupFileQueue = SetupOpenFileQueue();
1032 if (SetupFileQueue == NULL)
1033 {
1034 PopupError("Setup failed to open the copy file queue.\n",
1035 "ENTER = Reboot computer");
1036
1037 while(TRUE)
1038 {
1039 ConInKey(Ir);
1040
1041 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1042 {
1043 return(QUIT_PAGE);
1044 }
1045 }
1046 }
1047
1048 /*
1049 * Enumerate the files in the 'SourceFiles' section
1050 * and add them to the file queue.
1051 */
1052 do
1053 {
1054 if (!InfGetData (&FilesContext, &FileKeyName, &FileKeyValue))
1055 break;
1056
1057 DPRINT1("FileKeyName: '%S' FileKeyValue: '%S'\n", FileKeyName, FileKeyValue);
1058
1059 /* Lookup target directory */
1060 if (!InfFindFirstLine (SetupInf, L"Directories", FileKeyValue, &DirContext))
1061 {
1062 /* FIXME: Handle error! */
1063 DPRINT1("InfFindFirstLine() failed\n");
1064 break;
1065 }
1066
1067 if (!InfGetData (&DirContext, NULL, &DirKeyValue))
1068 {
1069 /* FIXME: Handle error! */
1070 DPRINT1("InfGetData() failed\n");
1071 break;
1072 }
1073
1074 if (!SetupQueueCopy(SetupFileQueue,
1075 SourceRootPath.Buffer,
1076 L"\\install",
1077 FileKeyName,
1078 DirKeyValue,
1079 NULL))
1080 {
1081 /* FIXME: Handle error! */
1082 DPRINT1("SetupQueueCopy() failed\n");
1083 }
1084 }
1085 while (InfFindNextLine(&FilesContext, &FilesContext));
1086
1087
1088 /* Create directories */
1089 SetStatusText(" Creating directories...");
1090
1091 /*
1092 * FIXME:
1093 * Install directories like '\reactos\test' are not handled yet.
1094 */
1095
1096 /* Get destination path */
1097 wcscpy(PathBuffer, DestinationPath.Buffer);
1098
1099 /* Remove trailing backslash */
1100 Length = wcslen(PathBuffer);
1101 if ((Length > 0) && (PathBuffer[Length - 1] == '\\'))
1102 {
1103 PathBuffer[Length - 1] = 0;
1104 }
1105
1106 /* Create the install directory */
1107 Status = CreateDirectory(PathBuffer);
1108 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION)
1109 {
1110 DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer, Status);
1111 PopupError("Setup could not create the install directory.",
1112 "ENTER = Reboot computer");
1113
1114 while(TRUE)
1115 {
1116 ConInKey(Ir);
1117
1118 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1119 {
1120 return(QUIT_PAGE);
1121 }
1122 }
1123 }
1124
1125
1126 /* Search for the 'Directories' section */
1127 if (!InfFindFirstLine(SetupInf, L"Directories", NULL, &DirContext))
1128 {
1129 PopupError("Setup failed to find the 'Directories' section\n"
1130 "in TXTSETUP.SIF.\n",
1131 "ENTER = Reboot computer");
1132
1133 while(TRUE)
1134 {
1135 ConInKey(Ir);
1136
1137 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1138 {
1139 return(QUIT_PAGE);
1140 }
1141 }
1142 }
1143
1144 /* Enumerate the directory values and create the subdirectories */
1145 do
1146 {
1147 if (!InfGetData (&DirContext, NULL, &KeyValue))
1148 break;
1149
1150 if (KeyValue[0] == L'\\' && KeyValue[1] != 0)
1151 {
1152 DPRINT("Absolute Path: '%S'\n", KeyValue);
1153
1154 wcscpy(PathBuffer, DestinationRootPath.Buffer);
1155 wcscat(PathBuffer, KeyValue);
1156
1157 DPRINT("FullPath: '%S'\n", PathBuffer);
1158 }
1159 else if (KeyValue[0] != L'\\')
1160 {
1161 DPRINT("RelativePath: '%S'\n", KeyValue);
1162 wcscpy(PathBuffer, DestinationPath.Buffer);
1163 wcscat(PathBuffer, L"\\");
1164 wcscat(PathBuffer, KeyValue);
1165
1166 DPRINT("FullPath: '%S'\n", PathBuffer);
1167
1168 Status = CreateDirectory(PathBuffer);
1169 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION)
1170 {
1171 DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer, Status);
1172 PopupError("Setup could not create install directories.",
1173 "ENTER = Reboot computer");
1174
1175 while (TRUE)
1176 {
1177 ConInKey(Ir);
1178
1179 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1180 {
1181 return(QUIT_PAGE);
1182 }
1183 }
1184 }
1185 }
1186 }
1187 while (InfFindNextLine (&DirContext, &DirContext));
1188
1189 return(FILE_COPY_PAGE);
1190 }
1191
1192
1193 static ULONG
1194 FileCopyCallback(PVOID Context,
1195 ULONG Notification,
1196 PVOID Param1,
1197 PVOID Param2)
1198 {
1199 PCOPYCONTEXT CopyContext;
1200
1201 CopyContext = (PCOPYCONTEXT)Context;
1202
1203 switch (Notification)
1204 {
1205 case SPFILENOTIFY_STARTSUBQUEUE:
1206 CopyContext->TotalOperations = (ULONG)Param2;
1207 ProgressSetStepCount(CopyContext->ProgressBar,
1208 CopyContext->TotalOperations);
1209 break;
1210
1211 case SPFILENOTIFY_STARTCOPY:
1212 /* Display copy message */
1213 PrintTextXYN(6, 16, 60, "Copying file: %S", (PWSTR)Param1);
1214
1215 PrintTextXYN(6, 18, 60, "File %lu of %lu",
1216 CopyContext->CompletedOperations + 1,
1217 CopyContext->TotalOperations);
1218 break;
1219
1220 case SPFILENOTIFY_ENDCOPY:
1221 CopyContext->CompletedOperations++;
1222 ProgressNextStep(CopyContext->ProgressBar);
1223 break;
1224 }
1225
1226 return(0);
1227 }
1228
1229
1230 static ULONG
1231 FileCopyPage(PINPUT_RECORD Ir)
1232 {
1233 COPYCONTEXT CopyContext;
1234 SHORT xScreen;
1235 SHORT yScreen;
1236
1237 SetStatusText(" Please wait...");
1238
1239 SetTextXY(6, 8, "Copying files");
1240
1241 GetScreenSize(&xScreen, &yScreen);
1242
1243 CopyContext.TotalOperations = 0;
1244 CopyContext.CompletedOperations = 0;
1245 CopyContext.ProgressBar = CreateProgressBar(6,
1246 yScreen - 14,
1247 xScreen - 7,
1248 yScreen - 10);
1249
1250 SetupCommitFileQueue(SetupFileQueue,
1251 DestinationRootPath.Buffer,
1252 InstallPath.Buffer,
1253 (PSP_FILE_CALLBACK)FileCopyCallback,
1254 &CopyContext);
1255
1256 SetupCloseFileQueue(SetupFileQueue);
1257
1258 DestroyProgressBar(CopyContext.ProgressBar);
1259
1260 return(REGISTRY_PAGE);
1261 }
1262
1263
1264 static ULONG
1265 RegistryPage(PINPUT_RECORD Ir)
1266 {
1267 INFCONTEXT InfContext;
1268 NTSTATUS Status;
1269
1270 PWSTR Action;
1271 PWSTR File;
1272 PWSTR Section;
1273
1274
1275 SetTextXY(6, 8, "Setup is updating the system configuration");
1276
1277 SetStatusText(" Creating registry hives...");
1278
1279 if (!SetInstallPathValue(&DestinationPath))
1280 {
1281 PopupError("Setup failed to set the initialize the registry.",
1282 "ENTER = Reboot computer");
1283
1284 while(TRUE)
1285 {
1286 ConInKey(Ir);
1287
1288 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1289 {
1290 return(QUIT_PAGE);
1291 }
1292 }
1293 }
1294
1295 /* Create the default hives */
1296 Status = NtInitializeRegistry(TRUE);
1297 if (!NT_SUCCESS(Status))
1298 {
1299 DPRINT1("NtInitializeRegistry() failed (Status %lx)\n", Status);
1300 PopupError("Setup failed to create the registry hives.",
1301 "ENTER = Reboot computer");
1302
1303 while(TRUE)
1304 {
1305 ConInKey(Ir);
1306
1307 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1308 {
1309 return(QUIT_PAGE);
1310 }
1311 }
1312 }
1313
1314 /* Update registry */
1315 SetStatusText(" Updating registry hives...");
1316
1317 #if 0
1318 if (!InfFindFirstLine(SetupInf, L"HiveInfs.Install", NULL, &InfContext))
1319 {
1320 DPRINT1("InfFindFirstLine() failed\n");
1321 PopupError("Setup failed to find the registry hive inf-files.",
1322 "ENTER = Reboot computer");
1323
1324 while(TRUE)
1325 {
1326 ConInKey(Ir);
1327
1328 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1329 {
1330 return(QUIT_PAGE);
1331 }
1332 }
1333 }
1334
1335 do
1336 {
1337
1338 InfGetDataField (&InfContext, 0, &Action);
1339 InfGetDataField (&InfContext, 1, &File);
1340 InfGetDataField (&InfContext, 2, &Section);
1341
1342 DPRINT1("Action: %S File: %S Section %S\n", Action, File, Section);
1343
1344 }
1345 while (InfFindNextLine (&InfContext, &InfContext));
1346 #endif
1347
1348
1349 Status = SetupUpdateRegistry();
1350 if (!NT_SUCCESS(Status))
1351 {
1352 DPRINT1("SetupUpdateRegistry() failed (Status %lx)\n", Status);
1353 PopupError("Setup failed to update the registry.",
1354 "ENTER = Reboot computer");
1355
1356 while(TRUE)
1357 {
1358 ConInKey(Ir);
1359
1360 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1361 {
1362 return(QUIT_PAGE);
1363 }
1364 }
1365 }
1366
1367 return(BOOT_LOADER_PAGE);
1368 }
1369
1370
1371 static ULONG
1372 BootLoaderPage(PINPUT_RECORD Ir)
1373 {
1374 WCHAR SrcPath[MAX_PATH];
1375 WCHAR DstPath[MAX_PATH];
1376 PINICACHE IniCache;
1377 PINICACHESECTION IniSection;
1378 NTSTATUS Status;
1379
1380 SetTextXY(6, 8, "Installing the boot loader");
1381
1382 SetStatusText(" Please wait...");
1383
1384 if (ActivePartitionValid == FALSE)
1385 {
1386 DPRINT1("Error: no active partition found\n");
1387 PopupError("Setup could not find an active partiton\n",
1388 "ENTER = Reboot computer");
1389
1390 while(TRUE)
1391 {
1392 ConInKey(Ir);
1393
1394 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1395 {
1396 return(QUIT_PAGE);
1397 }
1398 }
1399 }
1400
1401 if (ActivePartition.PartType == PARTITION_ENTRY_UNUSED)
1402 {
1403 DPRINT1("Error: active partition invalid (unused)\n");
1404 PopupError("The active partition is unused (invalid).\n",
1405 "ENTER = Reboot computer");
1406
1407 while(TRUE)
1408 {
1409 ConInKey(Ir);
1410
1411 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1412 {
1413 return(QUIT_PAGE);
1414 }
1415 }
1416 }
1417
1418 if (ActivePartition.PartType == 0x0A)
1419 {
1420 /* OS/2 boot manager partition */
1421 DPRINT1("Found OS/2 boot manager partition\n");
1422 PopupError("Setup found an OS/2 boot manager partiton.\n"
1423 "The OS/2 boot manager is not supported yet!",
1424 "ENTER = Reboot computer");
1425
1426 while(TRUE)
1427 {
1428 ConInKey(Ir);
1429
1430 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1431 {
1432 return(QUIT_PAGE);
1433 }
1434 }
1435 }
1436 else if (ActivePartition.PartType == 0x83)
1437 {
1438 /* Linux ext2 partition */
1439 DPRINT1("Found Linux ext2 partition\n");
1440 PopupError("Setup found a Linux ext2 partiton.\n"
1441 "Linux ext2 partitions are not supported yet!",
1442 "ENTER = Reboot computer");
1443
1444 while(TRUE)
1445 {
1446 ConInKey(Ir);
1447
1448 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1449 {
1450 return(QUIT_PAGE);
1451 }
1452 }
1453 }
1454 else if (ActivePartition.PartType == PARTITION_IFS)
1455 {
1456 /* NTFS partition */
1457 DPRINT1("Found NTFS partition\n");
1458 PopupError("Setup found an NTFS partiton.\n"
1459 "NTFS partitions are not supported yet!",
1460 "ENTER = Reboot computer");
1461
1462 while(TRUE)
1463 {
1464 ConInKey(Ir);
1465
1466 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1467 {
1468 return(QUIT_PAGE);
1469 }
1470 }
1471 }
1472 else if ((ActivePartition.PartType == PARTITION_FAT_12) ||
1473 (ActivePartition.PartType == PARTITION_FAT_16) ||
1474 (ActivePartition.PartType == PARTITION_HUGE) ||
1475 (ActivePartition.PartType == PARTITION_XINT13) ||
1476 (ActivePartition.PartType == PARTITION_FAT32) ||
1477 (ActivePartition.PartType == PARTITION_FAT32_XINT13))
1478 {
1479 /* FAT or FAT32 partition */
1480 DPRINT1("System path: '%wZ'\n", &SystemRootPath);
1481
1482 if (DoesFileExist(SystemRootPath.Buffer, L"ntldr") == TRUE ||
1483 DoesFileExist(SystemRootPath.Buffer, L"boot.ini") == TRUE)
1484 {
1485 /* Search root directory for 'ntldr' and 'boot.ini'. */
1486 DPRINT1("Found Microsoft Windows NT/2000/XP boot loader\n");
1487
1488 /* Copy FreeLoader to the boot partition */
1489 wcscpy(SrcPath, SourceRootPath.Buffer);
1490 wcscat(SrcPath, L"\\loader\\freeldr.sys");
1491 wcscpy(DstPath, SystemRootPath.Buffer);
1492 wcscat(DstPath, L"\\freeldr.sys");
1493
1494 DPRINT1("Copy: %S ==> %S\n", SrcPath, DstPath);
1495 Status = SetupCopyFile(SrcPath, DstPath);
1496 if (!NT_SUCCESS(Status))
1497 {
1498 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
1499 PopupError("Setup failed to copy 'freeldr.sys'.",
1500 "ENTER = Reboot computer");
1501
1502 while(TRUE)
1503 {
1504 ConInKey(Ir);
1505
1506 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1507 {
1508 return(QUIT_PAGE);
1509 }
1510 }
1511 }
1512
1513 /* Create or update freeldr.ini */
1514 if (DoesFileExist(SystemRootPath.Buffer, L"freeldr.ini") == FALSE)
1515 {
1516 /* Create new 'freeldr.ini' */
1517 DPRINT1("Create new 'freeldr.ini'\n");
1518 wcscpy(DstPath, SystemRootPath.Buffer);
1519 wcscat(DstPath, L"\\freeldr.ini");
1520
1521 Status = CreateFreeLoaderIniForReactos(DstPath,
1522 DestinationArcPath.Buffer);
1523 if (!NT_SUCCESS(Status))
1524 {
1525 DPRINT1("CreateFreeLoaderIniForReactos() failed (Status %lx)\n", Status);
1526 PopupError("Setup failed to create 'freeldr.ini'.",
1527 "ENTER = Reboot computer");
1528
1529 while(TRUE)
1530 {
1531 ConInKey(Ir);
1532
1533 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1534 {
1535 return(QUIT_PAGE);
1536 }
1537 }
1538 }
1539
1540 /* Install new bootcode */
1541 if ((ActivePartition.PartType == PARTITION_FAT32) ||
1542 (ActivePartition.PartType == PARTITION_FAT32_XINT13))
1543 {
1544 /* Install FAT32 bootcode */
1545 wcscpy(SrcPath, SourceRootPath.Buffer);
1546 wcscat(SrcPath, L"\\loader\\fat32.bin");
1547 wcscpy(DstPath, SystemRootPath.Buffer);
1548 wcscat(DstPath, L"\\bootsect.ros");
1549
1550 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, DstPath);
1551 Status = InstallFat32BootCodeToFile(SrcPath,
1552 DstPath,
1553 SystemRootPath.Buffer);
1554 if (!NT_SUCCESS(Status))
1555 {
1556 DPRINT1("InstallFat32BootCodeToFile() failed (Status %lx)\n", Status);
1557 PopupError("Setup failed to install the FAT32 bootcode.",
1558 "ENTER = Reboot computer");
1559
1560 while(TRUE)
1561 {
1562 ConInKey(Ir);
1563
1564 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1565 {
1566 return(QUIT_PAGE);
1567 }
1568 }
1569 }
1570 }
1571 else
1572 {
1573 /* Install FAT16 bootcode */
1574 wcscpy(SrcPath, SourceRootPath.Buffer);
1575 wcscat(SrcPath, L"\\loader\\fat.bin");
1576 wcscpy(DstPath, SystemRootPath.Buffer);
1577 wcscat(DstPath, L"\\bootsect.ros");
1578
1579 DPRINT1("Install FAT bootcode: %S ==> %S\n", SrcPath, DstPath);
1580 Status = InstallFat16BootCodeToFile(SrcPath,
1581 DstPath,
1582 SystemRootPath.Buffer);
1583 if (!NT_SUCCESS(Status))
1584 {
1585 DPRINT1("InstallFat16BootCodeToFile() failed (Status %lx)\n", Status);
1586 PopupError("Setup failed to install the FAT bootcode.",
1587 "ENTER = Reboot computer");
1588
1589 while(TRUE)
1590 {
1591 ConInKey(Ir);
1592
1593 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1594 {
1595 return(QUIT_PAGE);
1596 }
1597 }
1598 }
1599 }
1600
1601 /* Update 'boot.ini' */
1602 wcscpy(DstPath, SystemRootPath.Buffer);
1603 wcscat(DstPath, L"\\boot.ini");
1604
1605 DPRINT1("Update 'boot.ini': %S\n", DstPath);
1606 Status = UpdateBootIni(DstPath,
1607 L"C:\\bootsect.ros",
1608 L"\"ReactOS\"");
1609 if (!NT_SUCCESS(Status))
1610 {
1611 DPRINT1("UpdateBootIni() failed (Status %lx)\n", Status);
1612 PopupError("Setup failed to update \'boot.ini\'.",
1613 "ENTER = Reboot computer");
1614
1615 while(TRUE)
1616 {
1617 ConInKey(Ir);
1618
1619 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1620 {
1621 return(QUIT_PAGE);
1622 }
1623 }
1624 }
1625 }
1626 else
1627 {
1628 /* Update existing 'freeldr.ini' */
1629 DPRINT1("Update existing 'freeldr.ini'\n");
1630 wcscpy(DstPath, SystemRootPath.Buffer);
1631 wcscat(DstPath, L"\\freeldr.ini");
1632
1633 Status = UpdateFreeLoaderIni(DstPath,
1634 DestinationArcPath.Buffer);
1635 if (!NT_SUCCESS(Status))
1636 {
1637 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
1638 PopupError("Setup failed to update 'freeldr.ini'.",
1639 "ENTER = Reboot computer");
1640
1641 while(TRUE)
1642 {
1643 ConInKey(Ir);
1644
1645 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1646 {
1647 return(QUIT_PAGE);
1648 }
1649 }
1650 }
1651 }
1652 }
1653 else if (DoesFileExist(SystemRootPath.Buffer, L"io.sys") == TRUE ||
1654 DoesFileExist(SystemRootPath.Buffer, L"msdos.sys") == TRUE)
1655 {
1656 /* Search for root directory for 'io.sys' and 'msdos.sys'. */
1657 DPRINT1("Found Microsoft DOS or Windows 9x boot loader\n");
1658
1659 /* Copy FreeLoader to the boot partition */
1660 wcscpy(SrcPath, SourceRootPath.Buffer);
1661 wcscat(SrcPath, L"\\loader\\freeldr.sys");
1662 wcscpy(DstPath, SystemRootPath.Buffer);
1663 wcscat(DstPath, L"\\freeldr.sys");
1664
1665 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
1666 Status = SetupCopyFile(SrcPath, DstPath);
1667 if (!NT_SUCCESS(Status))
1668 {
1669 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
1670 PopupError("Setup failed to copy 'freeldr.sys'.",
1671 "ENTER = Reboot computer");
1672
1673 while(TRUE)
1674 {
1675 ConInKey(Ir);
1676
1677 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1678 {
1679 return(QUIT_PAGE);
1680 }
1681 }
1682 }
1683
1684 /* Create or update 'freeldr.ini' */
1685 if (DoesFileExist(SystemRootPath.Buffer, L"freeldr.ini") == FALSE)
1686 {
1687 /* Create new 'freeldr.ini' */
1688 DPRINT1("Create new 'freeldr.ini'\n");
1689 wcscpy(DstPath, SystemRootPath.Buffer);
1690 wcscat(DstPath, L"\\freeldr.ini");
1691
1692 Status = CreateFreeLoaderIniForDos(DstPath,
1693 DestinationArcPath.Buffer);
1694 if (!NT_SUCCESS(Status))
1695 {
1696 DPRINT1("CreateFreeLoaderIniForDos() failed (Status %lx)\n", Status);
1697 PopupError("Setup failed to create 'freeldr.ini'.",
1698 "ENTER = Reboot computer");
1699
1700 while(TRUE)
1701 {
1702 ConInKey(Ir);
1703
1704 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1705 {
1706 return(QUIT_PAGE);
1707 }
1708 }
1709 }
1710
1711 /* Save current bootsector as 'BOOTSECT.DOS' */
1712 wcscpy(SrcPath, SystemRootPath.Buffer);
1713 wcscpy(DstPath, SystemRootPath.Buffer);
1714 wcscat(DstPath, L"\\bootsect.dos");
1715
1716 DPRINT1("Save bootsector: %S ==> %S\n", SrcPath, DstPath);
1717 Status = SaveCurrentBootSector(SrcPath,
1718 DstPath);
1719 if (!NT_SUCCESS(Status))
1720 {
1721 DPRINT1("SaveCurrentBootSector() failed (Status %lx)\n", Status);
1722 PopupError("Setup failed to save the current bootsector.",
1723 "ENTER = Reboot computer");
1724
1725 while(TRUE)
1726 {
1727 ConInKey(Ir);
1728
1729 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1730 {
1731 return(QUIT_PAGE);
1732 }
1733 }
1734 }
1735
1736 /* Install new bootsector */
1737 if ((ActivePartition.PartType == PARTITION_FAT32) ||
1738 (ActivePartition.PartType == PARTITION_FAT32_XINT13))
1739 {
1740 wcscpy(SrcPath, SourceRootPath.Buffer);
1741 wcscat(SrcPath, L"\\loader\\fat32.bin");
1742
1743 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, SystemRootPath.Buffer);
1744 Status = InstallFat32BootCodeToDisk(SrcPath,
1745 SystemRootPath.Buffer);
1746 if (!NT_SUCCESS(Status))
1747 {
1748 DPRINT1("InstallFat32BootCodeToDisk() failed (Status %lx)\n", Status);
1749 PopupError("Setup failed to install the FAT32 bootcode.",
1750 "ENTER = Reboot computer");
1751
1752 while(TRUE)
1753 {
1754 ConInKey(Ir);
1755
1756 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1757 {
1758 return(QUIT_PAGE);
1759 }
1760 }
1761 }
1762 }
1763 else
1764 {
1765 wcscpy(SrcPath, SourceRootPath.Buffer);
1766 wcscat(SrcPath, L"\\loader\\fat.bin");
1767
1768 DPRINT1("Install FAT bootcode: %S ==> %S\n", SrcPath, SystemRootPath.Buffer);
1769 Status = InstallFat16BootCodeToDisk(SrcPath,
1770 SystemRootPath.Buffer);
1771 if (!NT_SUCCESS(Status))
1772 {
1773 DPRINT1("InstallFat16BootCodeToDisk() failed (Status %lx)\n", Status);
1774 PopupError("Setup failed to install the FAT bootcode.",
1775 "ENTER = Reboot computer");
1776
1777 while(TRUE)
1778 {
1779 ConInKey(Ir);
1780
1781 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1782 {
1783 return(QUIT_PAGE);
1784 }
1785 }
1786 }
1787 }
1788 }
1789 else
1790 {
1791 /* Update existing 'freeldr.ini' */
1792 wcscpy(DstPath, SystemRootPath.Buffer);
1793 wcscat(DstPath, L"\\freeldr.ini");
1794
1795 Status = UpdateFreeLoaderIni(DstPath,
1796 DestinationArcPath.Buffer);
1797 if (!NT_SUCCESS(Status))
1798 {
1799 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
1800 PopupError("Setup failed to update 'freeldr.ini'.",
1801 "ENTER = Reboot computer");
1802
1803 while(TRUE)
1804 {
1805 ConInKey(Ir);
1806
1807 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1808 {
1809 return(QUIT_PAGE);
1810 }
1811 }
1812 }
1813 }
1814 }
1815 else
1816 {
1817 /* No or unknown boot loader */
1818 DPRINT1("No or unknown boot loader found\n");
1819
1820 /* Copy FreeLoader to the boot partition */
1821 wcscpy(SrcPath, SourceRootPath.Buffer);
1822 wcscat(SrcPath, L"\\loader\\freeldr.sys");
1823 wcscpy(DstPath, SystemRootPath.Buffer);
1824 wcscat(DstPath, L"\\freeldr.sys");
1825
1826 DPRINT1("Copy: %S ==> %S\n", SrcPath, DstPath);
1827 Status = SetupCopyFile(SrcPath, DstPath);
1828 if (!NT_SUCCESS(Status))
1829 {
1830 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
1831 PopupError("Setup failed to copy 'freeldr.sys'.",
1832 "ENTER = Reboot computer");
1833
1834 while(TRUE)
1835 {
1836 ConInKey(Ir);
1837
1838 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1839 {
1840 return(QUIT_PAGE);
1841 }
1842 }
1843 }
1844
1845 /* Create or update 'freeldr.ini' */
1846 if (DoesFileExist(SystemRootPath.Buffer, L"freeldr.ini") == FALSE)
1847 {
1848 /* Create new freeldr.ini */
1849 wcscpy(DstPath, SystemRootPath.Buffer);
1850 wcscat(DstPath, L"\\freeldr.ini");
1851
1852 DPRINT1("Copy: %S ==> %S\n", SrcPath, DstPath);
1853 Status = CreateFreeLoaderIniForReactos(DstPath,
1854 DestinationArcPath.Buffer);
1855 if (!NT_SUCCESS(Status))
1856 {
1857 DPRINT1("CreateFreeLoaderIniForReactos() failed (Status %lx)\n", Status);
1858 PopupError("Setup failed to create \'freeldr.ini\'.",
1859 "ENTER = Reboot computer");
1860
1861 while(TRUE)
1862 {
1863 ConInKey(Ir);
1864
1865 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1866 {
1867 return(QUIT_PAGE);
1868 }
1869 }
1870 }
1871
1872 /* Save current bootsector as 'BOOTSECT.OLD' */
1873 wcscpy(SrcPath, SystemRootPath.Buffer);
1874 wcscpy(DstPath, SystemRootPath.Buffer);
1875 wcscat(DstPath, L"\\bootsect.old");
1876
1877 DPRINT1("Save bootsector: %S ==> %S\n", SrcPath, DstPath);
1878 Status = SaveCurrentBootSector(SrcPath,
1879 DstPath);
1880 if (!NT_SUCCESS(Status))
1881 {
1882 DPRINT1("SaveCurrentBootSector() failed (Status %lx)\n", Status);
1883 PopupError("Setup failed save the current bootsector.",
1884 "ENTER = Reboot computer");
1885
1886 while(TRUE)
1887 {
1888 ConInKey(Ir);
1889
1890 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1891 {
1892 return(QUIT_PAGE);
1893 }
1894 }
1895 }
1896
1897 /* Install new bootsector */
1898 if ((ActivePartition.PartType == PARTITION_FAT32) ||
1899 (ActivePartition.PartType == PARTITION_FAT32_XINT13))
1900 {
1901 wcscpy(SrcPath, SourceRootPath.Buffer);
1902 wcscat(SrcPath, L"\\loader\\fat32.bin");
1903
1904 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, SystemRootPath.Buffer);
1905 Status = InstallFat32BootCodeToDisk(SrcPath,
1906 SystemRootPath.Buffer);
1907 if (!NT_SUCCESS(Status))
1908 {
1909 DPRINT1("InstallFat32BootCodeToDisk() failed (Status %lx)\n", Status);
1910 PopupError("Setup failed to install the FAT32 bootcode.",
1911 "ENTER = Reboot computer");
1912
1913 while(TRUE)
1914 {
1915 ConInKey(Ir);
1916
1917 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1918 {
1919 return(QUIT_PAGE);
1920 }
1921 }
1922 }
1923 }
1924 else
1925 {
1926 wcscpy(SrcPath, SourceRootPath.Buffer);
1927 wcscat(SrcPath, L"\\loader\\fat.bin");
1928
1929 DPRINT1("Install FAT bootcode: %S ==> %S\n", SrcPath, SystemRootPath.Buffer);
1930 Status = InstallFat16BootCodeToDisk(SrcPath,
1931 SystemRootPath.Buffer);
1932 if (!NT_SUCCESS(Status))
1933 {
1934 DPRINT1("InstallFat16BootCodeToDisk() failed (Status %lx)\n", Status);
1935 PopupError("Setup failed to install the FAT bootcode.",
1936 "ENTER = Reboot computer");
1937
1938 while(TRUE)
1939 {
1940 ConInKey(Ir);
1941
1942 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1943 {
1944 return(QUIT_PAGE);
1945 }
1946 }
1947 }
1948 }
1949 }
1950 else
1951 {
1952 /* Update existing 'freeldr.ini' */
1953 wcscpy(DstPath, SystemRootPath.Buffer);
1954 wcscat(DstPath, L"\\freeldr.ini");
1955
1956 Status = UpdateFreeLoaderIni(DstPath,
1957 DestinationArcPath.Buffer);
1958 if (!NT_SUCCESS(Status))
1959 {
1960 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
1961 PopupError("Setup failed to update 'freeldr.ini'.",
1962 "ENTER = Reboot computer");
1963
1964 while(TRUE)
1965 {
1966 ConInKey(Ir);
1967
1968 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1969 {
1970 return(QUIT_PAGE);
1971 }
1972 }
1973 }
1974 }
1975 }
1976 }
1977 else
1978 {
1979 /* Unknown partition */
1980 DPRINT1("Unknown partition found\n");
1981 PopupError("Setup found an unknown partiton type.\n"
1982 "This partition type is not supported!",
1983 "ENTER = Reboot computer");
1984
1985 while(TRUE)
1986 {
1987 ConInKey(Ir);
1988
1989 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1990 {
1991 return(QUIT_PAGE);
1992 }
1993 }
1994 }
1995
1996 return(SUCCESS_PAGE);
1997 }
1998
1999
2000
2001 static ULONG
2002 QuitPage(PINPUT_RECORD Ir)
2003 {
2004 SetTextXY(10, 6, "ReactOS is not completely installed");
2005
2006 SetTextXY(10, 8, "Remove floppy disk from Drive A: and");
2007 SetTextXY(10, 9, "all CD-ROMs from CD-Drives.");
2008
2009 SetTextXY(10, 11, "Press ENTER to reboot your computer.");
2010
2011 SetStatusText(" ENTER = Reboot computer");
2012
2013 while(TRUE)
2014 {
2015 ConInKey(Ir);
2016
2017 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2018 {
2019 return(REBOOT_PAGE);
2020 }
2021 }
2022 }
2023
2024
2025 static ULONG
2026 SuccessPage(PINPUT_RECORD Ir)
2027 {
2028 SetTextXY(10, 6, "The basic components of ReactOS have been installed successfully.");
2029
2030 SetTextXY(10, 8, "Remove floppy disk from Drive A: and");
2031 SetTextXY(10, 9, "all CD-ROMs from CD-Drive.");
2032
2033 SetTextXY(10, 11, "Press ENTER to reboot your computer.");
2034
2035 SetStatusText(" ENTER = Reboot computer");
2036
2037 while(TRUE)
2038 {
2039 ConInKey(Ir);
2040
2041 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2042 {
2043 return(REBOOT_PAGE);
2044 }
2045 }
2046 }
2047
2048
2049 VOID STDCALL
2050 NtProcessStartup(PPEB Peb)
2051 {
2052 NTSTATUS Status;
2053 INPUT_RECORD Ir;
2054 ULONG Page;
2055
2056 RtlNormalizeProcessParams(Peb->ProcessParameters);
2057
2058 ProcessHeap = Peb->ProcessHeap;
2059
2060 Status = AllocConsole();
2061 if (!NT_SUCCESS(Status))
2062 {
2063 PrintString("AllocConsole() failed (Status = 0x%08lx)\n", Status);
2064
2065 /* Raise a hard error (crash the system/BSOD) */
2066 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED,
2067 0,0,0,0,0);
2068 }
2069
2070 PartDataValid = FALSE;
2071
2072 /* Initialize global unicode strings */
2073 RtlInitUnicodeString(&SourcePath, NULL);
2074 RtlInitUnicodeString(&SourceRootPath, NULL);
2075 RtlInitUnicodeString(&InstallPath, NULL);
2076 RtlInitUnicodeString(&DestinationPath, NULL);
2077 RtlInitUnicodeString(&DestinationArcPath, NULL);
2078 RtlInitUnicodeString(&DestinationRootPath, NULL);
2079 RtlInitUnicodeString(&SystemRootPath, NULL);
2080
2081
2082 Page = START_PAGE;
2083 while (Page != REBOOT_PAGE)
2084 {
2085 ClearScreen();
2086
2087 SetUnderlinedTextXY(4, 3, " ReactOS " KERNEL_VERSION_STR " Setup ");
2088
2089 switch (Page)
2090 {
2091 /* Start page */
2092 case START_PAGE:
2093 Page = StartPage(&Ir);
2094 break;
2095
2096 /* Intro page */
2097 case INTRO_PAGE:
2098 Page = IntroPage(&Ir);
2099 break;
2100
2101 /* Install pages */
2102 case INSTALL_INTRO_PAGE:
2103 Page = InstallIntroPage(&Ir);
2104 break;
2105
2106 #if 0
2107 case OEM_DRIVER_PAGE:
2108 Page = OemDriverPage(&Ir);
2109 break;
2110 #endif
2111
2112 #if 0
2113 case DEVICE_SETTINGS_PAGE:
2114 #endif
2115
2116 case SELECT_PARTITION_PAGE:
2117 Page = SelectPartitionPage(&Ir);
2118 break;
2119
2120 case SELECT_FILE_SYSTEM_PAGE:
2121 Page = SelectFileSystemPage(&Ir);
2122 break;
2123
2124 case CHECK_FILE_SYSTEM_PAGE:
2125 Page = CheckFileSystemPage(&Ir);
2126 break;
2127
2128 case INSTALL_DIRECTORY_PAGE:
2129 Page = InstallDirectoryPage(&Ir);
2130 break;
2131
2132 case PREPARE_COPY_PAGE:
2133 Page = PrepareCopyPage(&Ir);
2134 break;
2135
2136 case FILE_COPY_PAGE:
2137 Page = FileCopyPage(&Ir);
2138 break;
2139
2140 case REGISTRY_PAGE:
2141 Page = RegistryPage(&Ir);
2142 break;
2143
2144 case BOOT_LOADER_PAGE:
2145 Page = BootLoaderPage(&Ir);
2146 break;
2147
2148
2149 /* Repair pages */
2150 case REPAIR_INTRO_PAGE:
2151 Page = RepairIntroPage(&Ir);
2152 break;
2153
2154
2155 case SUCCESS_PAGE:
2156 Page = SuccessPage(&Ir);
2157 break;
2158
2159 case QUIT_PAGE:
2160 Page = QuitPage(&Ir);
2161 break;
2162 }
2163 }
2164
2165 /* Reboot */
2166 FreeConsole();
2167 NtShutdownSystem(ShutdownReboot);
2168 }
2169
2170 /* EOF */