Seperated inf- and ini-file routines. The inf-file routines look like the setupapi...
[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 if (_wcsicmp(Value, L"\"$ReactOS$\"") != 0)
465 {
466 PopupError("Setup found an invalid signature in TXTSETUP.SIF.\n",
467 "ENTER = Reboot computer");
468
469 while(TRUE)
470 {
471 ConInKey(Ir);
472
473 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
474 {
475 return(QUIT_PAGE);
476 }
477 }
478 }
479
480 return(INTRO_PAGE);
481 }
482
483
484
485 static ULONG
486 RepairIntroPage(PINPUT_RECORD Ir)
487 {
488 SetTextXY(6, 8, "ReactOS Setup is in an early development phase. It does not yet");
489 SetTextXY(6, 9, "support all the functions of a fully usable setup application.");
490
491 SetTextXY(6, 12, "The repair functions are not implemented yet.");
492
493 SetTextXY(8, 15, "\xfa Press ESC to return to the main page.");
494
495 SetTextXY(8, 17, "\xfa Press ENTER to reboot your computer.");
496
497 SetStatusText(" ESC = Main page ENTER = Reboot");
498
499 while(TRUE)
500 {
501 ConInKey(Ir);
502
503 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
504 {
505 return(REBOOT_PAGE);
506 }
507 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
508 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
509 {
510 return(INTRO_PAGE);
511 }
512 }
513
514 return(REPAIR_INTRO_PAGE);
515 }
516
517
518 /*
519 * First setup page
520 * RETURNS
521 * TRUE: setup/repair completed successfully
522 * FALSE: setup/repair terminated by user
523 */
524 static ULONG
525 IntroPage(PINPUT_RECORD Ir)
526 {
527 SetHighlightedTextXY(6, 8, "Welcome to ReactOS Setup");
528
529 SetTextXY(6, 11, "This part of the setup copies the ReactOS Operating System to your");
530 SetTextXY(6, 12, "computer and prepares the second part of the setup.");
531
532 SetTextXY(8, 15, "\xfa Press ENTER to install ReactOS.");
533
534 SetTextXY(8, 17, "\xfa Press E to start the emergency repair console.");
535
536 SetTextXY(8, 19, "\xfa Press R to repair ReactOS.");
537
538 SetTextXY(8, 21, "\xfa Press F3 to quit without installing ReactOS.");
539
540
541 SetStatusText(" ENTER = Continue F3 = Quit");
542
543 while(TRUE)
544 {
545 ConInKey(Ir);
546
547 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
548 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
549 {
550 if (ConfirmQuit(Ir) == TRUE)
551 return(QUIT_PAGE);
552 break;
553 }
554 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
555 {
556 return(INSTALL_INTRO_PAGE);
557 }
558 #if 0
559 else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'E') /* E */
560 {
561 return(RepairConsole());
562 }
563 #endif
564 else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'R') /* R */
565 {
566 return(REPAIR_INTRO_PAGE);
567 }
568 }
569
570 return(INTRO_PAGE);
571 }
572
573
574 static ULONG
575 InstallIntroPage(PINPUT_RECORD Ir)
576 {
577 SetTextXY(6, 8, "ReactOS Setup is in an early development phase. It does not yet");
578 SetTextXY(6, 9, "support all the functions of a fully usable setup application.");
579
580 SetTextXY(6, 12, "The following functions are missing:");
581 SetTextXY(8, 13, "- Creating and deleting harddisk partitions.");
582 SetTextXY(8, 14, "- Formatting partitions.");
583 SetTextXY(8, 15, "- Support for non-FAT file systems.");
584 SetTextXY(8, 16, "- Checking file systems.");
585
586
587
588 SetTextXY(8, 21, "\xfa Press ENTER to install ReactOS.");
589
590 SetTextXY(8, 23, "\xfa Press F3 to quit without installing ReactOS.");
591
592
593 SetStatusText(" ENTER = Continue F3 = Quit");
594
595 while(TRUE)
596 {
597 ConInKey(Ir);
598
599 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
600 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
601 {
602 if (ConfirmQuit(Ir) == TRUE)
603 return(QUIT_PAGE);
604 break;
605 }
606 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
607 {
608 return(SELECT_PARTITION_PAGE);
609 }
610 }
611
612 return(INSTALL_INTRO_PAGE);
613 }
614
615
616 static ULONG
617 SelectPartitionPage(PINPUT_RECORD Ir)
618 {
619 WCHAR PathBuffer[MAX_PATH];
620 PPARTLIST PartList;
621 SHORT xScreen;
622 SHORT yScreen;
623
624 SetTextXY(6, 8, "The list below shows existing partitions and unused disk");
625 SetTextXY(6, 9, "space for new partitions.");
626
627 SetTextXY(8, 11, "\xfa Press UP or DOWN to select a list entry.");
628 SetTextXY(8, 13, "\xfa Press ENTER to install ReactOS onto the selected partition.");
629 SetTextXY(8, 15, "\xfa Press C to create a new partition.");
630 SetTextXY(8, 17, "\xfa Press D to delete an existing partition.");
631
632 SetStatusText(" Please wait...");
633
634 RtlFreeUnicodeString(&DestinationPath);
635 RtlFreeUnicodeString(&DestinationRootPath);
636
637 GetScreenSize(&xScreen, &yScreen);
638
639 PartList = CreatePartitionList(2, 19, xScreen - 3, yScreen - 3);
640 if (PartList == NULL)
641 {
642 /* FIXME: show an error dialog */
643 return(QUIT_PAGE);
644 }
645
646 SetStatusText(" ENTER = Continue F3 = Quit");
647
648 while(TRUE)
649 {
650 ConInKey(Ir);
651
652 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
653 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
654 {
655 if (ConfirmQuit(Ir) == TRUE)
656 {
657 DestroyPartitionList(PartList);
658 return(QUIT_PAGE);
659 }
660 break;
661 }
662 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
663 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
664 {
665 ScrollDownPartitionList(PartList);
666 }
667 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
668 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
669 {
670 ScrollUpPartitionList(PartList);
671 }
672 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
673 {
674 PartDataValid = GetSelectedPartition(PartList,
675 &PartData);
676 ActivePartitionValid = GetActiveBootPartition(PartList,
677 &ActivePartition);
678 DestroyPartitionList(PartList);
679
680 RtlFreeUnicodeString(&DestinationRootPath);
681 swprintf(PathBuffer,
682 L"\\Device\\Harddisk%lu\\Partition%lu",
683 PartData.DiskNumber,
684 PartData.PartNumber);
685 RtlCreateUnicodeString(&DestinationRootPath,
686 PathBuffer);
687
688 RtlFreeUnicodeString(&SystemRootPath);
689 swprintf(PathBuffer,
690 L"\\Device\\Harddisk%lu\\Partition%lu",
691 ActivePartition.DiskNumber,
692 ActivePartition.PartNumber);
693 RtlCreateUnicodeString(&SystemRootPath,
694 PathBuffer);
695
696 return(SELECT_FILE_SYSTEM_PAGE);
697 }
698
699 /* FIXME: Update status text */
700
701 }
702
703 DestroyPartitionList(PartList);
704
705 return(SELECT_PARTITION_PAGE);
706 }
707
708
709 static ULONG
710 SelectFileSystemPage(PINPUT_RECORD Ir)
711 {
712 ULONGLONG DiskSize;
713 ULONGLONG PartSize;
714 PCHAR DiskUnit;
715 PCHAR PartUnit;
716 PCHAR PartType;
717
718 if (PartDataValid == FALSE)
719 {
720 /* FIXME: show an error dialog */
721 return(QUIT_PAGE);
722 }
723
724 /* adjust disk size */
725 if (PartData.DiskSize >= 0x280000000ULL) /* 10 GB */
726 {
727 DiskSize = (PartData.DiskSize + (1 << 29)) >> 30;
728 DiskUnit = "GB";
729 }
730 else
731 {
732 DiskSize = (PartData.DiskSize + (1 << 19)) >> 20;
733 DiskUnit = "MB";
734 }
735
736 /* adjust partition size */
737 if (PartData.PartSize >= 0x280000000ULL) /* 10 GB */
738 {
739 PartSize = (PartData.PartSize + (1 << 29)) >> 30;
740 PartUnit = "GB";
741 }
742 else
743 {
744 PartSize = (PartData.PartSize + (1 << 19)) >> 20;
745 PartUnit = "MB";
746 }
747
748 /* adjust partition type */
749 if ((PartData.PartType == PARTITION_FAT_12) ||
750 (PartData.PartType == PARTITION_FAT_16) ||
751 (PartData.PartType == PARTITION_HUGE) ||
752 (PartData.PartType == PARTITION_XINT13))
753 {
754 PartType = "FAT";
755 }
756 else if ((PartData.PartType == PARTITION_FAT32) ||
757 (PartData.PartType == PARTITION_FAT32_XINT13))
758 {
759 PartType = "FAT32";
760 }
761 else if (PartData.PartType == PARTITION_IFS)
762 {
763 PartType = "NTFS"; /* FIXME: Not quite correct! */
764 }
765 else
766 {
767 PartType = "Unknown";
768 }
769
770 SetTextXY(6, 8, "Setup will install ReactOS on");
771
772 PrintTextXY(8, 10, "Partition %lu (%I64u %s) %s of",
773 PartData.PartNumber,
774 PartSize,
775 PartUnit,
776 PartType);
777
778 PrintTextXY(8, 12, "Harddisk %lu (%I64u %s), Port=%hu, Bus=%hu, Id=%hu (%wZ).",
779 PartData.DiskNumber,
780 DiskSize,
781 DiskUnit,
782 PartData.Port,
783 PartData.Bus,
784 PartData.Id,
785 &PartData.DriverName);
786
787
788 SetTextXY(6, 17, "Select a file system for the partition from the list below.");
789
790 SetTextXY(8, 19, "\xfa Press UP or DOWN to select a file system.");
791 SetTextXY(8, 21, "\xfa Press ENTER to format the partition.");
792 SetTextXY(8, 23, "\xfa Press ESC to select another partition.");
793
794 /* FIXME: use a real list later */
795 SetInvertedTextXY(6, 26, " Keep current file system (no changes) ");
796
797
798 SetStatusText(" ENTER = Continue ESC = Cancel F3 = Quit");
799
800 while(TRUE)
801 {
802 ConInKey(Ir);
803
804 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
805 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
806 {
807 if (ConfirmQuit(Ir) == TRUE)
808 return(QUIT_PAGE);
809 break;
810 }
811 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
812 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
813 {
814 return(SELECT_PARTITION_PAGE);
815 }
816 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
817 {
818 return(CHECK_FILE_SYSTEM_PAGE);
819 }
820 }
821
822 return(SELECT_FILE_SYSTEM_PAGE);
823 }
824
825
826 static ULONG
827 CheckFileSystemPage(PINPUT_RECORD Ir)
828 {
829 SetTextXY(6, 8, "Check file system");
830
831 SetTextXY(6, 10, "At present, ReactOS can not check file systems.");
832
833 SetStatusText(" Please wait ...");
834
835
836 SetStatusText(" ENTER = Continue F3 = Quit");
837
838 while(TRUE)
839 {
840 ConInKey(Ir);
841
842 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
843 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
844 {
845 if (ConfirmQuit(Ir) == TRUE)
846 return(QUIT_PAGE);
847 break;
848 }
849 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
850 {
851 return(INSTALL_DIRECTORY_PAGE);
852 }
853 }
854
855 return(CHECK_FILE_SYSTEM_PAGE);
856 }
857
858
859 static ULONG
860 InstallDirectoryPage(PINPUT_RECORD Ir)
861 {
862 WCHAR PathBuffer[MAX_PATH];
863 WCHAR InstallDir[51];
864 PWCHAR DefaultPath;
865 INFCONTEXT Context;
866 ULONG Length;
867 NTSTATUS Status;
868
869 /* Search for 'DefaultPath' in the 'SetupData' section */
870 if (!InfFindFirstLine (SetupInf, L"SetupData", L"DefaultPath", &Context))
871 {
872 PopupError("Setup failed to find the 'SetupData' section\n"
873 "in TXTSETUP.SIF.\n",
874 "ENTER = Reboot computer");
875
876 while(TRUE)
877 {
878 ConInKey(Ir);
879
880 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
881 {
882 return(QUIT_PAGE);
883 }
884 }
885 }
886
887 /* Read the 'DefaultPath' data */
888 if (InfGetData (&Context, NULL, &DefaultPath))
889 {
890 wcscpy(InstallDir, DefaultPath);
891 }
892 else
893 {
894 wcscpy(InstallDir, L"\\ReactOS");
895 }
896 Length = wcslen(InstallDir);
897
898 SetTextXY(6, 8, "Setup installs ReactOS files onto the selected partition. Choose a");
899 SetTextXY(6, 9, "directory where you want ReactOS to be installed:");
900
901 SetInputTextXY(8, 11, 51, InstallDir);
902
903 SetTextXY(6, 14, "To change the suggested directory, press BACKSPACE to delete");
904 SetTextXY(6, 15, "characters and then type the directory where you want ReactOS to");
905 SetTextXY(6, 16, "be installed.");
906
907 SetStatusText(" ENTER = Continue F3 = Quit");
908
909 while(TRUE)
910 {
911 ConInKey(Ir);
912
913 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
914 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
915 {
916 if (ConfirmQuit(Ir) == TRUE)
917 return(QUIT_PAGE);
918 break;
919 }
920 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
921 {
922 /* Create 'InstallPath' string */
923 RtlFreeUnicodeString(&InstallPath);
924 RtlCreateUnicodeString(&InstallPath,
925 InstallDir);
926
927 /* Create 'DestinationPath' string */
928 RtlFreeUnicodeString(&DestinationPath);
929 wcscpy(PathBuffer,
930 DestinationRootPath.Buffer);
931 if (InstallDir[0] != L'\\')
932 wcscat(PathBuffer,
933 L"\\");
934 wcscat(PathBuffer, InstallDir);
935 RtlCreateUnicodeString(&DestinationPath,
936 PathBuffer);
937
938 /* Create 'DestinationArcPath' */
939 RtlFreeUnicodeString(&DestinationArcPath);
940 swprintf(PathBuffer,
941 L"multi(0)disk(0)rdisk(%lu)partition(%lu)",
942 PartData.DiskNumber,
943 PartData.PartNumber);
944 if (InstallDir[0] != L'\\')
945 wcscat(PathBuffer,
946 L"\\");
947 wcscat(PathBuffer, InstallDir);
948 RtlCreateUnicodeString(&DestinationArcPath,
949 PathBuffer);
950
951 return(PREPARE_COPY_PAGE);
952 }
953 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x08) /* BACKSPACE */
954 {
955 if (Length > 0)
956 {
957 Length--;
958 InstallDir[Length] = 0;
959 SetInputTextXY(8, 11, 51, InstallDir);
960 }
961 }
962 else if (isprint(Ir->Event.KeyEvent.uChar.AsciiChar))
963 {
964 if (Length < 50)
965 {
966 InstallDir[Length] = (WCHAR)Ir->Event.KeyEvent.uChar.AsciiChar;
967 Length++;
968 InstallDir[Length] = 0;
969 SetInputTextXY(8, 11, 51, InstallDir);
970 }
971 }
972 }
973
974 return(INSTALL_DIRECTORY_PAGE);
975 }
976
977
978 static ULONG
979 PrepareCopyPage(PINPUT_RECORD Ir)
980 {
981 WCHAR PathBuffer[MAX_PATH];
982 INFCONTEXT FilesContext;
983 INFCONTEXT DirContext;
984 PWCHAR KeyName;
985 PWCHAR KeyValue;
986 ULONG Length;
987 NTSTATUS Status;
988
989 PWCHAR FileKeyName;
990 PWCHAR FileKeyValue;
991 PWCHAR DirKeyName;
992 PWCHAR DirKeyValue;
993
994 SetTextXY(6, 8, "Setup prepares your computer for copying the ReactOS files. ");
995
996
997 // SetTextXY(8, 12, "Build file copy list");
998
999 // SetTextXY(8, 14, "Create directories");
1000
1001 // SetStatusText(" Please wait...");
1002
1003
1004 /*
1005 * Build the file copy list
1006 */
1007 SetStatusText(" Building the file copy list...");
1008 // SetInvertedTextXY(8, 12, "Build file copy list");
1009
1010
1011
1012 /* Search for the 'SourceFiles' section */
1013 if (!InfFindFirstLine (SetupInf, L"SourceFiles", NULL, &FilesContext))
1014 {
1015 PopupError("Setup failed to find the 'SourceFiles' section\n"
1016 "in TXTSETUP.SIF.\n",
1017 "ENTER = Reboot computer");
1018
1019 while(TRUE)
1020 {
1021 ConInKey(Ir);
1022
1023 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1024 {
1025 return(QUIT_PAGE);
1026 }
1027 }
1028 }
1029
1030
1031 /* Create the file queue */
1032 SetupFileQueue = SetupOpenFileQueue();
1033 if (SetupFileQueue == NULL)
1034 {
1035 PopupError("Setup failed to open the copy file queue.\n",
1036 "ENTER = Reboot computer");
1037
1038 while(TRUE)
1039 {
1040 ConInKey(Ir);
1041
1042 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1043 {
1044 return(QUIT_PAGE);
1045 }
1046 }
1047 }
1048
1049 /*
1050 * Enumerate the files in the 'SourceFiles' section
1051 * and add them to the file queue.
1052 */
1053 do
1054 {
1055 if (!InfGetData (&FilesContext, &FileKeyName, &FileKeyValue))
1056 break;
1057
1058 DPRINT1("FileKeyName: '%S' FileKeyValue: '%S'\n", FileKeyName, FileKeyValue);
1059
1060 /* Lookup target directory */
1061 if (!InfFindFirstLine (SetupInf, L"Directories", FileKeyValue, &DirContext))
1062 {
1063 /* FIXME: Handle error! */
1064 DPRINT1("InfFindFirstLine() failed\n");
1065 break;
1066 }
1067
1068 if (!InfGetData (&DirContext, NULL, &DirKeyValue))
1069 {
1070 /* FIXME: Handle error! */
1071 DPRINT1("InfGetData() failed\n");
1072 break;
1073 }
1074
1075 if (!SetupQueueCopy(SetupFileQueue,
1076 SourceRootPath.Buffer,
1077 L"\\install",
1078 FileKeyName,
1079 DirKeyValue,
1080 NULL))
1081 {
1082 /* FIXME: Handle error! */
1083 DPRINT1("SetupQueueCopy() failed\n");
1084 }
1085 }
1086 while (InfFindNextLine(&FilesContext, &FilesContext));
1087
1088
1089 /* Create directories */
1090 SetStatusText(" Creating directories...");
1091
1092 /*
1093 * FIXME:
1094 * Install directories like '\reactos\test' are not handled yet.
1095 */
1096
1097 /* Get destination path */
1098 wcscpy(PathBuffer, DestinationPath.Buffer);
1099
1100 /* Remove trailing backslash */
1101 Length = wcslen(PathBuffer);
1102 if ((Length > 0) && (PathBuffer[Length - 1] == '\\'))
1103 {
1104 PathBuffer[Length - 1] = 0;
1105 }
1106
1107 /* Create the install directory */
1108 Status = CreateDirectory(PathBuffer);
1109 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION)
1110 {
1111 DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer, Status);
1112 PopupError("Setup could not create the install directory.",
1113 "ENTER = Reboot computer");
1114
1115 while(TRUE)
1116 {
1117 ConInKey(Ir);
1118
1119 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1120 {
1121 return(QUIT_PAGE);
1122 }
1123 }
1124 }
1125
1126
1127 /* Search for the 'Directories' section */
1128 if (!InfFindFirstLine(SetupInf, L"Directories", NULL, &DirContext))
1129 {
1130 PopupError("Setup failed to find the 'Directories' section\n"
1131 "in TXTSETUP.SIF.\n",
1132 "ENTER = Reboot computer");
1133
1134 while(TRUE)
1135 {
1136 ConInKey(Ir);
1137
1138 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1139 {
1140 return(QUIT_PAGE);
1141 }
1142 }
1143 }
1144
1145 /* Enumerate the directory values and create the subdirectories */
1146 do
1147 {
1148 if (!InfGetData (&DirContext, NULL, &KeyValue))
1149 break;
1150
1151 // if (KeyValue[0] == L'\\' && KeyValue[1] != 0)
1152 if (wcscmp (KeyValue, L"\"\\\"") == 0)
1153 {
1154 DPRINT("Absolute Path: '%S'\n", KeyValue);
1155
1156 wcscpy(PathBuffer, DestinationRootPath.Buffer);
1157 wcscat(PathBuffer, KeyValue);
1158
1159 DPRINT("FullPath: '%S'\n", PathBuffer);
1160 }
1161 else if (KeyValue[0] != L'\\')
1162 {
1163 DPRINT("RelativePath: '%S'\n", KeyValue);
1164 wcscpy(PathBuffer, DestinationPath.Buffer);
1165 wcscat(PathBuffer, L"\\");
1166 wcscat(PathBuffer, KeyValue);
1167
1168 DPRINT("FullPath: '%S'\n", PathBuffer);
1169
1170 Status = CreateDirectory(PathBuffer);
1171 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION)
1172 {
1173 DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer, Status);
1174 PopupError("Setup could not create install directories.",
1175 "ENTER = Reboot computer");
1176
1177 while (TRUE)
1178 {
1179 ConInKey(Ir);
1180
1181 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1182 {
1183 return(QUIT_PAGE);
1184 }
1185 }
1186 }
1187 }
1188 }
1189 while (InfFindNextLine (&DirContext, &DirContext));
1190
1191 return(FILE_COPY_PAGE);
1192 }
1193
1194
1195 static ULONG
1196 FileCopyCallback(PVOID Context,
1197 ULONG Notification,
1198 PVOID Param1,
1199 PVOID Param2)
1200 {
1201 PCOPYCONTEXT CopyContext;
1202
1203 CopyContext = (PCOPYCONTEXT)Context;
1204
1205 switch (Notification)
1206 {
1207 case SPFILENOTIFY_STARTSUBQUEUE:
1208 CopyContext->TotalOperations = (ULONG)Param2;
1209 ProgressSetStepCount(CopyContext->ProgressBar,
1210 CopyContext->TotalOperations);
1211 break;
1212
1213 case SPFILENOTIFY_STARTCOPY:
1214 /* Display copy message */
1215 PrintTextXYN(6, 16, 60, "Copying file: %S", (PWSTR)Param1);
1216
1217 PrintTextXYN(6, 18, 60, "File %lu of %lu",
1218 CopyContext->CompletedOperations + 1,
1219 CopyContext->TotalOperations);
1220 break;
1221
1222 case SPFILENOTIFY_ENDCOPY:
1223 CopyContext->CompletedOperations++;
1224 ProgressNextStep(CopyContext->ProgressBar);
1225 break;
1226 }
1227
1228 return(0);
1229 }
1230
1231
1232 static ULONG
1233 FileCopyPage(PINPUT_RECORD Ir)
1234 {
1235 COPYCONTEXT CopyContext;
1236 SHORT xScreen;
1237 SHORT yScreen;
1238
1239 SetStatusText(" Please wait...");
1240
1241 SetTextXY(6, 8, "Copying files");
1242
1243 GetScreenSize(&xScreen, &yScreen);
1244
1245 CopyContext.TotalOperations = 0;
1246 CopyContext.CompletedOperations = 0;
1247 CopyContext.ProgressBar = CreateProgressBar(6,
1248 yScreen - 14,
1249 xScreen - 7,
1250 yScreen - 10);
1251
1252 SetupCommitFileQueue(SetupFileQueue,
1253 DestinationRootPath.Buffer,
1254 InstallPath.Buffer,
1255 (PSP_FILE_CALLBACK)FileCopyCallback,
1256 &CopyContext);
1257
1258 SetupCloseFileQueue(SetupFileQueue);
1259
1260 DestroyProgressBar(CopyContext.ProgressBar);
1261
1262 return(REGISTRY_PAGE);
1263 }
1264
1265
1266 static ULONG
1267 RegistryPage(PINPUT_RECORD Ir)
1268 {
1269 OBJECT_ATTRIBUTES ObjectAttributes;
1270 UNICODE_STRING KeyName;
1271 UNICODE_STRING ValueName;
1272 HANDLE KeyHandle;
1273 NTSTATUS Status;
1274
1275 SetTextXY(6, 8, "Setup updated the system configuration");
1276
1277 SetStatusText(" Creating registry hives...");
1278
1279 /* Create the 'secret' InstallPath key */
1280 RtlInitUnicodeStringFromLiteral(&KeyName,
1281 L"\\Registry\\Machine\\HARDWARE");
1282 InitializeObjectAttributes(&ObjectAttributes,
1283 &KeyName,
1284 OBJ_CASE_INSENSITIVE,
1285 NULL,
1286 NULL);
1287 Status = NtOpenKey(&KeyHandle,
1288 KEY_ALL_ACCESS,
1289 &ObjectAttributes);
1290 if (!NT_SUCCESS(Status))
1291 {
1292 DPRINT1("NtOpenKey() failed (Status %lx)\n", Status);
1293 PopupError("Setup failed to open the HARDWARE registry key.",
1294 "ENTER = Reboot computer");
1295
1296 while(TRUE)
1297 {
1298 ConInKey(Ir);
1299
1300 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1301 {
1302 return(QUIT_PAGE);
1303 }
1304 }
1305 }
1306
1307 RtlInitUnicodeStringFromLiteral(&ValueName,
1308 L"InstallPath");
1309
1310 Status = NtSetValueKey(KeyHandle,
1311 &ValueName,
1312 0,
1313 REG_SZ,
1314 (PVOID)DestinationPath.Buffer,
1315 DestinationPath.Length);
1316 NtClose(KeyHandle);
1317 if (!NT_SUCCESS(Status))
1318 {
1319 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status);
1320 PopupError("Setup failed to set the \'InstallPath\' registry value.",
1321 "ENTER = Reboot computer");
1322
1323 while(TRUE)
1324 {
1325 ConInKey(Ir);
1326
1327 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1328 {
1329 return(QUIT_PAGE);
1330 }
1331 }
1332 }
1333
1334 /* Create the default hives */
1335 Status = NtInitializeRegistry(TRUE);
1336 if (!NT_SUCCESS(Status))
1337 {
1338 DPRINT1("NtInitializeRegistry() failed (Status %lx)\n", Status);
1339 PopupError("Setup failed to initialize the registry.",
1340 "ENTER = Reboot computer");
1341
1342 while(TRUE)
1343 {
1344 ConInKey(Ir);
1345
1346 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1347 {
1348 return(QUIT_PAGE);
1349 }
1350 }
1351 }
1352
1353 /* Update registry */
1354 SetStatusText(" Updating registry hives...");
1355
1356 Status = SetupUpdateRegistry();
1357 if (!NT_SUCCESS(Status))
1358 {
1359 DPRINT1("SetupUpdateRegistry() failed (Status %lx)\n", Status);
1360 PopupError("Setup failed to update the registry.",
1361 "ENTER = Reboot computer");
1362
1363 while(TRUE)
1364 {
1365 ConInKey(Ir);
1366
1367 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1368 {
1369 return(QUIT_PAGE);
1370 }
1371 }
1372 }
1373
1374 return(BOOT_LOADER_PAGE);
1375 }
1376
1377
1378 static ULONG
1379 BootLoaderPage(PINPUT_RECORD Ir)
1380 {
1381 WCHAR SrcPath[MAX_PATH];
1382 WCHAR DstPath[MAX_PATH];
1383 PINICACHE IniCache;
1384 PINICACHESECTION IniSection;
1385 NTSTATUS Status;
1386
1387 SetTextXY(6, 8, "Installing the boot loader");
1388
1389 SetStatusText(" Please wait...");
1390
1391 if (ActivePartitionValid == FALSE)
1392 {
1393 DPRINT1("Error: no active partition found\n");
1394 PopupError("Setup could not find an active partiton\n",
1395 "ENTER = Reboot computer");
1396
1397 while(TRUE)
1398 {
1399 ConInKey(Ir);
1400
1401 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1402 {
1403 return(QUIT_PAGE);
1404 }
1405 }
1406 }
1407
1408 if (ActivePartition.PartType == PARTITION_ENTRY_UNUSED)
1409 {
1410 DPRINT1("Error: active partition invalid (unused)\n");
1411 PopupError("The active partition is unused (invalid).\n",
1412 "ENTER = Reboot computer");
1413
1414 while(TRUE)
1415 {
1416 ConInKey(Ir);
1417
1418 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1419 {
1420 return(QUIT_PAGE);
1421 }
1422 }
1423 }
1424
1425 if (ActivePartition.PartType == 0x0A)
1426 {
1427 /* OS/2 boot manager partition */
1428 DPRINT1("Found OS/2 boot manager partition\n");
1429 PopupError("Setup found an OS/2 boot manager partiton.\n"
1430 "The OS/2 boot manager is not supported yet!",
1431 "ENTER = Reboot computer");
1432
1433 while(TRUE)
1434 {
1435 ConInKey(Ir);
1436
1437 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1438 {
1439 return(QUIT_PAGE);
1440 }
1441 }
1442 }
1443 else if (ActivePartition.PartType == 0x83)
1444 {
1445 /* Linux ext2 partition */
1446 DPRINT1("Found Linux ext2 partition\n");
1447 PopupError("Setup found a Linux ext2 partiton.\n"
1448 "Linux ext2 partitions are not supported yet!",
1449 "ENTER = Reboot computer");
1450
1451 while(TRUE)
1452 {
1453 ConInKey(Ir);
1454
1455 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1456 {
1457 return(QUIT_PAGE);
1458 }
1459 }
1460 }
1461 else if (ActivePartition.PartType == PARTITION_IFS)
1462 {
1463 /* NTFS partition */
1464 DPRINT1("Found NTFS partition\n");
1465 PopupError("Setup found an NTFS partiton.\n"
1466 "NTFS partitions are not supported yet!",
1467 "ENTER = Reboot computer");
1468
1469 while(TRUE)
1470 {
1471 ConInKey(Ir);
1472
1473 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1474 {
1475 return(QUIT_PAGE);
1476 }
1477 }
1478 }
1479 else if ((ActivePartition.PartType == PARTITION_FAT_12) ||
1480 (ActivePartition.PartType == PARTITION_FAT_16) ||
1481 (ActivePartition.PartType == PARTITION_HUGE) ||
1482 (ActivePartition.PartType == PARTITION_XINT13) ||
1483 (ActivePartition.PartType == PARTITION_FAT32) ||
1484 (ActivePartition.PartType == PARTITION_FAT32_XINT13))
1485 {
1486 /* FAT or FAT32 partition */
1487 DPRINT1("System path: '%wZ'\n", &SystemRootPath);
1488
1489 if (DoesFileExist(SystemRootPath.Buffer, L"ntldr") == TRUE ||
1490 DoesFileExist(SystemRootPath.Buffer, L"boot.ini") == TRUE)
1491 {
1492 /* Search root directory for 'ntldr' and 'boot.ini'. */
1493 DPRINT1("Found Microsoft Windows NT/2000/XP boot loader\n");
1494
1495 /* Copy FreeLoader to the boot partition */
1496 wcscpy(SrcPath, SourceRootPath.Buffer);
1497 wcscat(SrcPath, L"\\loader\\freeldr.sys");
1498 wcscpy(DstPath, SystemRootPath.Buffer);
1499 wcscat(DstPath, L"\\freeldr.sys");
1500
1501 DPRINT1("Copy: %S ==> %S\n", SrcPath, DstPath);
1502 Status = SetupCopyFile(SrcPath, DstPath);
1503 if (!NT_SUCCESS(Status))
1504 {
1505 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
1506 PopupError("Setup failed to copy 'freeldr.sys'.",
1507 "ENTER = Reboot computer");
1508
1509 while(TRUE)
1510 {
1511 ConInKey(Ir);
1512
1513 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1514 {
1515 return(QUIT_PAGE);
1516 }
1517 }
1518 }
1519
1520 /* Create or update freeldr.ini */
1521 if (DoesFileExist(SystemRootPath.Buffer, L"freeldr.ini") == FALSE)
1522 {
1523 /* Create new 'freeldr.ini' */
1524 DPRINT1("Create new 'freeldr.ini'\n");
1525 wcscpy(DstPath, SystemRootPath.Buffer);
1526 wcscat(DstPath, L"\\freeldr.ini");
1527
1528 Status = CreateFreeLoaderIniForReactos(DstPath,
1529 DestinationArcPath.Buffer);
1530 if (!NT_SUCCESS(Status))
1531 {
1532 DPRINT1("CreateFreeLoaderIniForReactos() failed (Status %lx)\n", Status);
1533 PopupError("Setup failed to create 'freeldr.ini'.",
1534 "ENTER = Reboot computer");
1535
1536 while(TRUE)
1537 {
1538 ConInKey(Ir);
1539
1540 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1541 {
1542 return(QUIT_PAGE);
1543 }
1544 }
1545 }
1546
1547 /* Install new bootcode */
1548 if ((ActivePartition.PartType == PARTITION_FAT32) ||
1549 (ActivePartition.PartType == PARTITION_FAT32_XINT13))
1550 {
1551 /* Install FAT32 bootcode */
1552 wcscpy(SrcPath, SourceRootPath.Buffer);
1553 wcscat(SrcPath, L"\\loader\\fat32.bin");
1554 wcscpy(DstPath, SystemRootPath.Buffer);
1555 wcscat(DstPath, L"\\bootsect.ros");
1556
1557 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, DstPath);
1558 Status = InstallFat32BootCodeToFile(SrcPath,
1559 DstPath,
1560 SystemRootPath.Buffer);
1561 if (!NT_SUCCESS(Status))
1562 {
1563 DPRINT1("InstallFat32BootCodeToFile() failed (Status %lx)\n", Status);
1564 PopupError("Setup failed to install the FAT32 bootcode.",
1565 "ENTER = Reboot computer");
1566
1567 while(TRUE)
1568 {
1569 ConInKey(Ir);
1570
1571 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1572 {
1573 return(QUIT_PAGE);
1574 }
1575 }
1576 }
1577 }
1578 else
1579 {
1580 /* Install FAT16 bootcode */
1581 wcscpy(SrcPath, SourceRootPath.Buffer);
1582 wcscat(SrcPath, L"\\loader\\fat.bin");
1583 wcscpy(DstPath, SystemRootPath.Buffer);
1584 wcscat(DstPath, L"\\bootsect.ros");
1585
1586 DPRINT1("Install FAT bootcode: %S ==> %S\n", SrcPath, DstPath);
1587 Status = InstallFat16BootCodeToFile(SrcPath,
1588 DstPath,
1589 SystemRootPath.Buffer);
1590 if (!NT_SUCCESS(Status))
1591 {
1592 DPRINT1("InstallFat16BootCodeToFile() failed (Status %lx)\n", Status);
1593 PopupError("Setup failed to install the FAT bootcode.",
1594 "ENTER = Reboot computer");
1595
1596 while(TRUE)
1597 {
1598 ConInKey(Ir);
1599
1600 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1601 {
1602 return(QUIT_PAGE);
1603 }
1604 }
1605 }
1606 }
1607
1608 /* Update 'boot.ini' */
1609 wcscpy(DstPath, SystemRootPath.Buffer);
1610 wcscat(DstPath, L"\\boot.ini");
1611
1612 DPRINT1("Update 'boot.ini': %S\n", DstPath);
1613 Status = UpdateBootIni(DstPath,
1614 L"C:\\bootsect.ros",
1615 L"\"ReactOS\"");
1616 if (!NT_SUCCESS(Status))
1617 {
1618 DPRINT1("UpdateBootIni() failed (Status %lx)\n", Status);
1619 PopupError("Setup failed to update \'boot.ini\'.",
1620 "ENTER = Reboot computer");
1621
1622 while(TRUE)
1623 {
1624 ConInKey(Ir);
1625
1626 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1627 {
1628 return(QUIT_PAGE);
1629 }
1630 }
1631 }
1632 }
1633 else
1634 {
1635 /* Update existing 'freeldr.ini' */
1636 DPRINT1("Update existing 'freeldr.ini'\n");
1637 wcscpy(DstPath, SystemRootPath.Buffer);
1638 wcscat(DstPath, L"\\freeldr.ini");
1639
1640 Status = UpdateFreeLoaderIni(DstPath,
1641 DestinationArcPath.Buffer);
1642 if (!NT_SUCCESS(Status))
1643 {
1644 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
1645 PopupError("Setup failed to update 'freeldr.ini'.",
1646 "ENTER = Reboot computer");
1647
1648 while(TRUE)
1649 {
1650 ConInKey(Ir);
1651
1652 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1653 {
1654 return(QUIT_PAGE);
1655 }
1656 }
1657 }
1658 }
1659 }
1660 else if (DoesFileExist(SystemRootPath.Buffer, L"io.sys") == TRUE ||
1661 DoesFileExist(SystemRootPath.Buffer, L"msdos.sys") == TRUE)
1662 {
1663 /* Search for root directory for 'io.sys' and 'msdos.sys'. */
1664 DPRINT1("Found Microsoft DOS or Windows 9x boot loader\n");
1665
1666 /* Copy FreeLoader to the boot partition */
1667 wcscpy(SrcPath, SourceRootPath.Buffer);
1668 wcscat(SrcPath, L"\\loader\\freeldr.sys");
1669 wcscpy(DstPath, SystemRootPath.Buffer);
1670 wcscat(DstPath, L"\\freeldr.sys");
1671
1672 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
1673 Status = SetupCopyFile(SrcPath, DstPath);
1674 if (!NT_SUCCESS(Status))
1675 {
1676 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
1677 PopupError("Setup failed to copy 'freeldr.sys'.",
1678 "ENTER = Reboot computer");
1679
1680 while(TRUE)
1681 {
1682 ConInKey(Ir);
1683
1684 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1685 {
1686 return(QUIT_PAGE);
1687 }
1688 }
1689 }
1690
1691 /* Create or update 'freeldr.ini' */
1692 if (DoesFileExist(SystemRootPath.Buffer, L"freeldr.ini") == FALSE)
1693 {
1694 /* Create new 'freeldr.ini' */
1695 DPRINT1("Create new 'freeldr.ini'\n");
1696 wcscpy(DstPath, SystemRootPath.Buffer);
1697 wcscat(DstPath, L"\\freeldr.ini");
1698
1699 Status = CreateFreeLoaderIniForDos(DstPath,
1700 DestinationArcPath.Buffer);
1701 if (!NT_SUCCESS(Status))
1702 {
1703 DPRINT1("CreateFreeLoaderIniForDos() failed (Status %lx)\n", Status);
1704 PopupError("Setup failed to create 'freeldr.ini'.",
1705 "ENTER = Reboot computer");
1706
1707 while(TRUE)
1708 {
1709 ConInKey(Ir);
1710
1711 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1712 {
1713 return(QUIT_PAGE);
1714 }
1715 }
1716 }
1717
1718 /* Save current bootsector as 'BOOTSECT.DOS' */
1719 wcscpy(SrcPath, SystemRootPath.Buffer);
1720 wcscpy(DstPath, SystemRootPath.Buffer);
1721 wcscat(DstPath, L"\\bootsect.dos");
1722
1723 DPRINT1("Save bootsector: %S ==> %S\n", SrcPath, DstPath);
1724 Status = SaveCurrentBootSector(SrcPath,
1725 DstPath);
1726 if (!NT_SUCCESS(Status))
1727 {
1728 DPRINT1("SaveCurrentBootSector() failed (Status %lx)\n", Status);
1729 PopupError("Setup failed to save the current bootsector.",
1730 "ENTER = Reboot computer");
1731
1732 while(TRUE)
1733 {
1734 ConInKey(Ir);
1735
1736 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1737 {
1738 return(QUIT_PAGE);
1739 }
1740 }
1741 }
1742
1743 /* Install new bootsector */
1744 if ((ActivePartition.PartType == PARTITION_FAT32) ||
1745 (ActivePartition.PartType == PARTITION_FAT32_XINT13))
1746 {
1747 wcscpy(SrcPath, SourceRootPath.Buffer);
1748 wcscat(SrcPath, L"\\loader\\fat32.bin");
1749
1750 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, SystemRootPath.Buffer);
1751 Status = InstallFat32BootCodeToDisk(SrcPath,
1752 SystemRootPath.Buffer);
1753 if (!NT_SUCCESS(Status))
1754 {
1755 DPRINT1("InstallFat32BootCodeToDisk() failed (Status %lx)\n", Status);
1756 PopupError("Setup failed to install the FAT32 bootcode.",
1757 "ENTER = Reboot computer");
1758
1759 while(TRUE)
1760 {
1761 ConInKey(Ir);
1762
1763 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1764 {
1765 return(QUIT_PAGE);
1766 }
1767 }
1768 }
1769 }
1770 else
1771 {
1772 wcscpy(SrcPath, SourceRootPath.Buffer);
1773 wcscat(SrcPath, L"\\loader\\fat.bin");
1774
1775 DPRINT1("Install FAT bootcode: %S ==> %S\n", SrcPath, SystemRootPath.Buffer);
1776 Status = InstallFat16BootCodeToDisk(SrcPath,
1777 SystemRootPath.Buffer);
1778 if (!NT_SUCCESS(Status))
1779 {
1780 DPRINT1("InstallFat16BootCodeToDisk() failed (Status %lx)\n", Status);
1781 PopupError("Setup failed to install the FAT bootcode.",
1782 "ENTER = Reboot computer");
1783
1784 while(TRUE)
1785 {
1786 ConInKey(Ir);
1787
1788 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1789 {
1790 return(QUIT_PAGE);
1791 }
1792 }
1793 }
1794 }
1795 }
1796 else
1797 {
1798 /* Update existing 'freeldr.ini' */
1799 wcscpy(DstPath, SystemRootPath.Buffer);
1800 wcscat(DstPath, L"\\freeldr.ini");
1801
1802 Status = UpdateFreeLoaderIni(DstPath,
1803 DestinationArcPath.Buffer);
1804 if (!NT_SUCCESS(Status))
1805 {
1806 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
1807 PopupError("Setup failed to update 'freeldr.ini'.",
1808 "ENTER = Reboot computer");
1809
1810 while(TRUE)
1811 {
1812 ConInKey(Ir);
1813
1814 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1815 {
1816 return(QUIT_PAGE);
1817 }
1818 }
1819 }
1820 }
1821 }
1822 else
1823 {
1824 /* No or unknown boot loader */
1825 DPRINT1("No or unknown boot loader found\n");
1826
1827 /* Copy FreeLoader to the boot partition */
1828 wcscpy(SrcPath, SourceRootPath.Buffer);
1829 wcscat(SrcPath, L"\\loader\\freeldr.sys");
1830 wcscpy(DstPath, SystemRootPath.Buffer);
1831 wcscat(DstPath, L"\\freeldr.sys");
1832
1833 DPRINT1("Copy: %S ==> %S\n", SrcPath, DstPath);
1834 Status = SetupCopyFile(SrcPath, DstPath);
1835 if (!NT_SUCCESS(Status))
1836 {
1837 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
1838 PopupError("Setup failed to copy 'freeldr.sys'.",
1839 "ENTER = Reboot computer");
1840
1841 while(TRUE)
1842 {
1843 ConInKey(Ir);
1844
1845 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1846 {
1847 return(QUIT_PAGE);
1848 }
1849 }
1850 }
1851
1852 /* Create or update 'freeldr.ini' */
1853 if (DoesFileExist(SystemRootPath.Buffer, L"freeldr.ini") == FALSE)
1854 {
1855 /* Create new freeldr.ini */
1856 wcscpy(DstPath, SystemRootPath.Buffer);
1857 wcscat(DstPath, L"\\freeldr.ini");
1858
1859 DPRINT1("Copy: %S ==> %S\n", SrcPath, DstPath);
1860 Status = CreateFreeLoaderIniForReactos(DstPath,
1861 DestinationArcPath.Buffer);
1862 if (!NT_SUCCESS(Status))
1863 {
1864 DPRINT1("CreateFreeLoaderIniForReactos() failed (Status %lx)\n", Status);
1865 PopupError("Setup failed to create \'freeldr.ini\'.",
1866 "ENTER = Reboot computer");
1867
1868 while(TRUE)
1869 {
1870 ConInKey(Ir);
1871
1872 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1873 {
1874 return(QUIT_PAGE);
1875 }
1876 }
1877 }
1878
1879 /* Save current bootsector as 'BOOTSECT.OLD' */
1880 wcscpy(SrcPath, SystemRootPath.Buffer);
1881 wcscpy(DstPath, SystemRootPath.Buffer);
1882 wcscat(DstPath, L"\\bootsect.old");
1883
1884 DPRINT1("Save bootsector: %S ==> %S\n", SrcPath, DstPath);
1885 Status = SaveCurrentBootSector(SrcPath,
1886 DstPath);
1887 if (!NT_SUCCESS(Status))
1888 {
1889 DPRINT1("SaveCurrentBootSector() failed (Status %lx)\n", Status);
1890 PopupError("Setup failed save the current bootsector.",
1891 "ENTER = Reboot computer");
1892
1893 while(TRUE)
1894 {
1895 ConInKey(Ir);
1896
1897 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1898 {
1899 return(QUIT_PAGE);
1900 }
1901 }
1902 }
1903
1904 /* Install new bootsector */
1905 if ((ActivePartition.PartType == PARTITION_FAT32) ||
1906 (ActivePartition.PartType == PARTITION_FAT32_XINT13))
1907 {
1908 wcscpy(SrcPath, SourceRootPath.Buffer);
1909 wcscat(SrcPath, L"\\loader\\fat32.bin");
1910
1911 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, SystemRootPath.Buffer);
1912 Status = InstallFat32BootCodeToDisk(SrcPath,
1913 SystemRootPath.Buffer);
1914 if (!NT_SUCCESS(Status))
1915 {
1916 DPRINT1("InstallFat32BootCodeToDisk() failed (Status %lx)\n", Status);
1917 PopupError("Setup failed to install the FAT32 bootcode.",
1918 "ENTER = Reboot computer");
1919
1920 while(TRUE)
1921 {
1922 ConInKey(Ir);
1923
1924 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1925 {
1926 return(QUIT_PAGE);
1927 }
1928 }
1929 }
1930 }
1931 else
1932 {
1933 wcscpy(SrcPath, SourceRootPath.Buffer);
1934 wcscat(SrcPath, L"\\loader\\fat.bin");
1935
1936 DPRINT1("Install FAT bootcode: %S ==> %S\n", SrcPath, SystemRootPath.Buffer);
1937 Status = InstallFat16BootCodeToDisk(SrcPath,
1938 SystemRootPath.Buffer);
1939 if (!NT_SUCCESS(Status))
1940 {
1941 DPRINT1("InstallFat16BootCodeToDisk() failed (Status %lx)\n", Status);
1942 PopupError("Setup failed to install the FAT bootcode.",
1943 "ENTER = Reboot computer");
1944
1945 while(TRUE)
1946 {
1947 ConInKey(Ir);
1948
1949 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1950 {
1951 return(QUIT_PAGE);
1952 }
1953 }
1954 }
1955 }
1956 }
1957 else
1958 {
1959 /* Update existing 'freeldr.ini' */
1960 wcscpy(DstPath, SystemRootPath.Buffer);
1961 wcscat(DstPath, L"\\freeldr.ini");
1962
1963 Status = UpdateFreeLoaderIni(DstPath,
1964 DestinationArcPath.Buffer);
1965 if (!NT_SUCCESS(Status))
1966 {
1967 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
1968 PopupError("Setup failed to update 'freeldr.ini'.",
1969 "ENTER = Reboot computer");
1970
1971 while(TRUE)
1972 {
1973 ConInKey(Ir);
1974
1975 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1976 {
1977 return(QUIT_PAGE);
1978 }
1979 }
1980 }
1981 }
1982 }
1983 }
1984 else
1985 {
1986 /* Unknown partition */
1987 DPRINT1("Unknown partition found\n");
1988 PopupError("Setup found an unknown partiton type.\n"
1989 "This partition type is not supported!",
1990 "ENTER = Reboot computer");
1991
1992 while(TRUE)
1993 {
1994 ConInKey(Ir);
1995
1996 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1997 {
1998 return(QUIT_PAGE);
1999 }
2000 }
2001 }
2002
2003 return(SUCCESS_PAGE);
2004 }
2005
2006
2007
2008 static ULONG
2009 QuitPage(PINPUT_RECORD Ir)
2010 {
2011 SetTextXY(10, 6, "ReactOS is not completely installed");
2012
2013 SetTextXY(10, 8, "Remove floppy disk from Drive A: and");
2014 SetTextXY(10, 9, "all CD-ROMs from CD-Drives.");
2015
2016 SetTextXY(10, 11, "Press ENTER to reboot your computer.");
2017
2018 SetStatusText(" ENTER = Reboot computer");
2019
2020 while(TRUE)
2021 {
2022 ConInKey(Ir);
2023
2024 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2025 {
2026 return(REBOOT_PAGE);
2027 }
2028 }
2029 }
2030
2031
2032 static ULONG
2033 SuccessPage(PINPUT_RECORD Ir)
2034 {
2035 SetTextXY(10, 6, "The basic components of ReactOS have been installed successfully.");
2036
2037 SetTextXY(10, 8, "Remove floppy disk from Drive A: and");
2038 SetTextXY(10, 9, "all CD-ROMs from CD-Drive.");
2039
2040 SetTextXY(10, 11, "Press ENTER to reboot your computer.");
2041
2042 SetStatusText(" ENTER = Reboot computer");
2043
2044 while(TRUE)
2045 {
2046 ConInKey(Ir);
2047
2048 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2049 {
2050 return(REBOOT_PAGE);
2051 }
2052 }
2053 }
2054
2055
2056 VOID STDCALL
2057 NtProcessStartup(PPEB Peb)
2058 {
2059 NTSTATUS Status;
2060 INPUT_RECORD Ir;
2061 ULONG Page;
2062
2063 RtlNormalizeProcessParams(Peb->ProcessParameters);
2064
2065 ProcessHeap = Peb->ProcessHeap;
2066
2067 Status = AllocConsole();
2068 if (!NT_SUCCESS(Status))
2069 {
2070 PrintString("AllocConsole() failed (Status = 0x%08lx)\n", Status);
2071
2072 /* Raise a hard error (crash the system/BSOD) */
2073 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED,
2074 0,0,0,0,0);
2075 }
2076
2077 PartDataValid = FALSE;
2078
2079 /* Initialize global unicode strings */
2080 RtlInitUnicodeString(&SourcePath, NULL);
2081 RtlInitUnicodeString(&SourceRootPath, NULL);
2082 RtlInitUnicodeString(&InstallPath, NULL);
2083 RtlInitUnicodeString(&DestinationPath, NULL);
2084 RtlInitUnicodeString(&DestinationArcPath, NULL);
2085 RtlInitUnicodeString(&DestinationRootPath, NULL);
2086 RtlInitUnicodeString(&SystemRootPath, NULL);
2087
2088
2089 Page = START_PAGE;
2090 while (Page != REBOOT_PAGE)
2091 {
2092 ClearScreen();
2093
2094 SetUnderlinedTextXY(4, 3, " ReactOS " KERNEL_VERSION_STR " Setup ");
2095
2096 switch (Page)
2097 {
2098 /* Start page */
2099 case START_PAGE:
2100 Page = StartPage(&Ir);
2101 break;
2102
2103 /* Intro page */
2104 case INTRO_PAGE:
2105 Page = IntroPage(&Ir);
2106 break;
2107
2108 /* Install pages */
2109 case INSTALL_INTRO_PAGE:
2110 Page = InstallIntroPage(&Ir);
2111 break;
2112
2113 #if 0
2114 case OEM_DRIVER_PAGE:
2115 Page = OemDriverPage(&Ir);
2116 break;
2117 #endif
2118
2119 #if 0
2120 case DEVICE_SETTINGS_PAGE:
2121 #endif
2122
2123 case SELECT_PARTITION_PAGE:
2124 Page = SelectPartitionPage(&Ir);
2125 break;
2126
2127 case SELECT_FILE_SYSTEM_PAGE:
2128 Page = SelectFileSystemPage(&Ir);
2129 break;
2130
2131 case CHECK_FILE_SYSTEM_PAGE:
2132 Page = CheckFileSystemPage(&Ir);
2133 break;
2134
2135 case INSTALL_DIRECTORY_PAGE:
2136 Page = InstallDirectoryPage(&Ir);
2137 break;
2138
2139 case PREPARE_COPY_PAGE:
2140 Page = PrepareCopyPage(&Ir);
2141 break;
2142
2143 case FILE_COPY_PAGE:
2144 Page = FileCopyPage(&Ir);
2145 break;
2146
2147 case REGISTRY_PAGE:
2148 Page = RegistryPage(&Ir);
2149 break;
2150
2151 case BOOT_LOADER_PAGE:
2152 Page = BootLoaderPage(&Ir);
2153 break;
2154
2155
2156 /* Repair pages */
2157 case REPAIR_INTRO_PAGE:
2158 Page = RepairIntroPage(&Ir);
2159 break;
2160
2161
2162 case SUCCESS_PAGE:
2163 Page = SuccessPage(&Ir);
2164 break;
2165
2166 case QUIT_PAGE:
2167 Page = QuitPage(&Ir);
2168 break;
2169 }
2170 }
2171
2172 /* Reboot */
2173 FreeConsole();
2174 NtShutdownSystem(ShutdownReboot);
2175 }
2176
2177 /* EOF */