* Added ini file suport (Thanks to Royce Mitchell!)
[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
38
39
40 #define START_PAGE 0
41 #define INTRO_PAGE 1
42 #define INSTALL_INTRO_PAGE 2
43
44 #define SELECT_PARTITION_PAGE 4
45 #define SELECT_FILE_SYSTEM_PAGE 5
46 #define CHECK_FILE_SYSTEM_PAGE 6
47 #define PREPARE_COPY_PAGE 7
48 #define INSTALL_DIRECTORY_PAGE 8
49 #define FILE_COPY_PAGE 9
50 #define INIT_SYSTEM_PAGE 10
51
52 #define REPAIR_INTRO_PAGE 20
53
54 #define SUCCESS_PAGE 100
55 #define QUIT_PAGE 101
56 #define REBOOT_PAGE 102
57
58
59 /* GLOBALS ******************************************************************/
60
61 HANDLE ProcessHeap;
62
63 BOOLEAN PartDataValid;
64 PARTDATA PartData;
65
66 WCHAR InstallDir[51];
67
68 UNICODE_STRING SourcePath;
69 UNICODE_STRING SourceRootPath;
70
71 PINICACHE IniCache;
72
73
74 /* FUNCTIONS ****************************************************************/
75
76 static VOID
77 PrintString(char* fmt,...)
78 {
79 char buffer[512];
80 va_list ap;
81 UNICODE_STRING UnicodeString;
82 ANSI_STRING AnsiString;
83
84 va_start(ap, fmt);
85 vsprintf(buffer, fmt, ap);
86 va_end(ap);
87
88 RtlInitAnsiString(&AnsiString, buffer);
89 RtlAnsiStringToUnicodeString(&UnicodeString,
90 &AnsiString,
91 TRUE);
92 NtDisplayString(&UnicodeString);
93 RtlFreeUnicodeString(&UnicodeString);
94 }
95
96
97 static VOID
98 PopupError(PCHAR Text,
99 PCHAR Status)
100 {
101 SHORT xScreen;
102 SHORT yScreen;
103 SHORT yTop;
104 SHORT xLeft;
105 COORD coPos;
106 ULONG Written;
107 ULONG Length;
108 ULONG MaxLength;
109 ULONG Lines;
110 PCHAR p;
111 PCHAR pnext;
112 BOOLEAN LastLine;
113 SHORT Width;
114 SHORT Height;
115
116
117 /* Count text lines and longest line */
118 MaxLength = 0;
119 Lines = 0;
120 pnext = Text;
121 while (TRUE)
122 {
123 p = strchr(pnext, '\n');
124 if (p == NULL)
125 {
126 Length = strlen(pnext);
127 LastLine = TRUE;
128 }
129 else
130 {
131 Length = (ULONG)(p - pnext);
132 LastLine = FALSE;
133 }
134
135 Lines++;
136 if (Length > MaxLength)
137 MaxLength = Length;
138
139 if (LastLine == TRUE)
140 break;
141
142 pnext = p + 1;
143 }
144
145 /* Check length of status line */
146 if (Status != NULL)
147 {
148 Length = strlen(Status);
149 if (Length > MaxLength)
150 MaxLength = Length;
151 }
152
153 GetScreenSize(&xScreen, &yScreen);
154
155 Width = MaxLength + 4;
156 Height = Lines + 2;
157 if (Status != NULL)
158 Height += 2;
159
160 yTop = (yScreen - Height) / 2;
161 xLeft = (xScreen - Width) / 2;
162
163
164 /* Set screen attributes */
165 coPos.X = xLeft;
166 for (coPos.Y = yTop; coPos.Y < yTop + Height; coPos.Y++)
167 {
168 FillConsoleOutputAttribute(0x74,
169 Width,
170 coPos,
171 &Written);
172 }
173
174 /* draw upper left corner */
175 coPos.X = xLeft;
176 coPos.Y = yTop;
177 FillConsoleOutputCharacter(0xDA, // '+',
178 1,
179 coPos,
180 &Written);
181
182 /* draw upper edge */
183 coPos.X = xLeft + 1;
184 coPos.Y = yTop;
185 FillConsoleOutputCharacter(0xC4, // '-',
186 Width - 2,
187 coPos,
188 &Written);
189
190 /* draw upper right corner */
191 coPos.X = xLeft + Width - 1;
192 coPos.Y = yTop;
193 FillConsoleOutputCharacter(0xBF, // '+',
194 1,
195 coPos,
196 &Written);
197
198 /* Draw right edge, inner space and left edge */
199 for (coPos.Y = yTop + 1; coPos.Y < yTop + Height - 1; coPos.Y++)
200 {
201 coPos.X = xLeft;
202 FillConsoleOutputCharacter(0xB3, // '|',
203 1,
204 coPos,
205 &Written);
206
207 coPos.X = xLeft + 1;
208 FillConsoleOutputCharacter(' ',
209 Width - 2,
210 coPos,
211 &Written);
212
213 coPos.X = xLeft + Width - 1;
214 FillConsoleOutputCharacter(0xB3, // '|',
215 1,
216 coPos,
217 &Written);
218 }
219
220 /* draw lower left corner */
221 coPos.X = xLeft;
222 coPos.Y = yTop + Height - 1;
223 FillConsoleOutputCharacter(0xC0, // '+',
224 1,
225 coPos,
226 &Written);
227
228 /* draw lower edge */
229 coPos.X = xLeft + 1;
230 coPos.Y = yTop + Height - 1;
231 FillConsoleOutputCharacter(0xC4, // '-',
232 Width - 2,
233 coPos,
234 &Written);
235
236 /* draw lower right corner */
237 coPos.X = xLeft + Width - 1;
238 coPos.Y = yTop + Height - 1;
239 FillConsoleOutputCharacter(0xD9, // '+',
240 1,
241 coPos,
242 &Written);
243
244 /* Print message text */
245 coPos.Y = yTop + 1;
246 pnext = Text;
247 while (TRUE)
248 {
249 p = strchr(pnext, '\n');
250 if (p == NULL)
251 {
252 Length = strlen(pnext);
253 LastLine = TRUE;
254 }
255 else
256 {
257 Length = (ULONG)(p - pnext);
258 LastLine = FALSE;
259 }
260
261 if (Length != 0)
262 {
263 coPos.X = xLeft + 2;
264 WriteConsoleOutputCharacters(pnext,
265 Length,
266 coPos);
267 }
268
269 if (LastLine == TRUE)
270 break;
271
272 coPos.Y++;
273 pnext = p + 1;
274 }
275
276 /* Print separator line and status text */
277 if (Status != NULL)
278 {
279 coPos.Y = yTop + Height - 3;
280 coPos.X = xLeft;
281 FillConsoleOutputCharacter(0xC3, // '+',
282 1,
283 coPos,
284 &Written);
285
286 coPos.X = xLeft + 1;
287 FillConsoleOutputCharacter(0xC4, // '-',
288 Width - 2,
289 coPos,
290 &Written);
291
292 coPos.X = xLeft + Width - 1;
293 FillConsoleOutputCharacter(0xB4, // '+',
294 1,
295 coPos,
296 &Written);
297
298 coPos.Y++;
299 coPos.X = xLeft + 2;
300 WriteConsoleOutputCharacters(Status,
301 min(strlen(Status), Width - 4),
302 coPos);
303 }
304 }
305
306
307 /*
308 * Confirm quit setup
309 * RETURNS
310 * TRUE: Quit setup.
311 * FALSE: Don't quit setup.
312 */
313 static BOOL
314 ConfirmQuit(PINPUT_RECORD Ir)
315 {
316 BOOL Result = FALSE;
317
318 PopupError("ReactOS is not completely installed on your\n"
319 "computer. If you quit Setup now, you will need to\n"
320 "run Setup again to install ReactOS.\n"
321 "\n"
322 " * Press ENTER to continue Setup.\n"
323 " * Press F3 to quit Setup.",
324 "F3= Quit ENTER = Continue");
325
326 while(TRUE)
327 {
328 ConInKey(Ir);
329
330 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
331 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
332 {
333 Result = TRUE;
334 break;
335 }
336 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
337 {
338 Result = FALSE;
339 break;
340 }
341 }
342
343 return(Result);
344 }
345
346
347
348 /*
349 * Start page
350 * RETURNS
351 * Number of the next page.
352 */
353 static ULONG
354 StartPage(PINPUT_RECORD Ir)
355 {
356 NTSTATUS Status;
357 WCHAR FileNameBuffer[MAX_PATH];
358 UNICODE_STRING FileName;
359
360 PINICACHESECTION Section;
361 PWCHAR Value;
362
363
364 SetStatusText(" Please wait...");
365
366 Status = GetSourcePaths(&SourcePath,
367 &SourceRootPath);
368 if (!NT_SUCCESS(Status))
369 {
370 PrintTextXY(6, 15, "GetSourcePath() failed (Status 0x%08lx)", Status);
371 }
372 else
373 {
374 PrintTextXY(6, 15, "SourcePath: '%wZ'", &SourcePath);
375 PrintTextXY(6, 16, "SourceRootPath: '%wZ'", &SourceRootPath);
376 }
377
378
379 /* Load txtsetup.sif from install media. */
380 wcscpy(FileNameBuffer, SourceRootPath.Buffer);
381 wcscat(FileNameBuffer, L"\\install\\txtsetup.sif");
382 RtlInitUnicodeString(&FileName,
383 FileNameBuffer);
384
385 IniCache = NULL;
386 Status = IniCacheLoad(&IniCache,
387 &FileName);
388 if (!NT_SUCCESS(Status))
389 {
390 PopupError("Setup failed to load the file TXTSETUP.SIF.\n",
391 "ENTER = Reboot computer");
392
393 while(TRUE)
394 {
395 ConInKey(Ir);
396
397 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
398 {
399 return(QUIT_PAGE);
400 }
401 }
402 }
403
404 /* Open 'Version' section */
405 Section = IniCacheGetSection(IniCache,
406 L"Version");
407 if (Section == NULL)
408 {
409 PopupError("Setup found a corrupt TXTSETUP.SIF.\n",
410 "ENTER = Reboot computer");
411
412 while(TRUE)
413 {
414 ConInKey(Ir);
415
416 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
417 {
418 return(QUIT_PAGE);
419 }
420 }
421 }
422
423
424 /* Get pointer 'Signature' key */
425 Status = IniCacheGetKey(Section,
426 L"Signature",
427 &Value);
428 if (!NT_SUCCESS(Status))
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 /* Check 'Signature' string */
445 if (_wcsicmp(Value, L"$ReactOS$") != 0)
446 {
447 PopupError("Setup found an invalid signature in TXTSETUP.SIF.\n",
448 "ENTER = Reboot computer");
449
450 while(TRUE)
451 {
452 ConInKey(Ir);
453
454 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
455 {
456 return(QUIT_PAGE);
457 }
458 }
459 }
460
461 #if 0
462 PopupError("This is a test error.", "ENTER = Reboot computer");
463
464 SetStatusText(" ENTER = Continue");
465
466 while(TRUE)
467 {
468 ConInKey(Ir);
469
470 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
471 {
472 return(INTRO_PAGE);
473 }
474 }
475
476 return(START_PAGE);
477 #endif
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, "\xf9 Press ESC to return to the main page.");
493
494 SetTextXY(8, 17, "\xf9 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, "\xf9 Press ENTER to install ReactOS.");
532
533 SetTextXY(8, 17, "\xf9 Press E to start the emergency repair console.");
534
535 SetTextXY(8, 19, "\xf9 Press R to repair ReactOS.");
536
537 SetTextXY(8, 21, "\xf9 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 SetTextXY(8, 17, "- Installing the bootloader.");
585
586
587
588 SetTextXY(8, 21, "\xf9 Press ENTER to install ReactOS.");
589
590 SetTextXY(8, 23, "\xf9 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 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, "\xf9 Press UP or DOWN to select a list entry.");
627 SetTextXY(8, 13, "\xf9 Press ENTER to install ReactOS onto the selected partition.");
628 SetTextXY(8, 15, "\xf9 Press C to create a new partition.");
629 SetTextXY(8, 17, "\xf9 Press D to delete an existing partition.");
630
631 SetStatusText(" Please wait...");
632
633 GetScreenSize(&xScreen, &yScreen);
634
635 PartList = CreatePartitionList(2, 19, xScreen - 3, yScreen - 3);
636 if (PartList == NULL)
637 {
638 /* FIXME: show an error dialog */
639 return(QUIT_PAGE);
640 }
641
642 SetStatusText(" ENTER = Continue F3 = Quit");
643
644 while(TRUE)
645 {
646 ConInKey(Ir);
647
648 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
649 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
650 {
651 if (ConfirmQuit(Ir) == TRUE)
652 {
653 DestroyPartitionList(PartList);
654 return(QUIT_PAGE);
655 }
656 break;
657 }
658 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
659 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
660 {
661 ScrollDownPartitionList(PartList);
662 }
663 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
664 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
665 {
666 ScrollUpPartitionList(PartList);
667 }
668 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
669 {
670 PartDataValid = GetPartitionData(PartList, &PartData);
671 DestroyPartitionList(PartList);
672 return(SELECT_FILE_SYSTEM_PAGE);
673 }
674
675 /* FIXME: Update status text */
676
677 }
678
679 DestroyPartitionList(PartList);
680
681 return(SELECT_PARTITION_PAGE);
682 }
683
684
685 static ULONG
686 SelectFileSystemPage(PINPUT_RECORD Ir)
687 {
688 ULONGLONG DiskSize;
689 ULONGLONG PartSize;
690 PCHAR DiskUnit;
691 PCHAR PartUnit;
692 PCHAR PartType;
693
694 if (PartDataValid == FALSE)
695 {
696 /* FIXME: show an error dialog */
697 return(QUIT_PAGE);
698 }
699
700 /* adjust disk size */
701 if (PartData.DiskSize >= 0x280000000ULL) /* 10 GB */
702 {
703 DiskSize = (PartData.DiskSize + (1 << 29)) >> 30;
704 DiskUnit = "GB";
705 }
706 else
707 {
708 DiskSize = (PartData.DiskSize + (1 << 19)) >> 20;
709 DiskUnit = "MB";
710 }
711
712 /* adjust partition size */
713 if (PartData.PartSize >= 0x280000000ULL) /* 10 GB */
714 {
715 PartSize = (PartData.PartSize + (1 << 29)) >> 30;
716 PartUnit = "GB";
717 }
718 else
719 {
720 PartSize = (PartData.PartSize + (1 << 19)) >> 20;
721 PartUnit = "MB";
722 }
723
724 /* adjust partition type */
725 if ((PartData.PartType == PARTITION_FAT_12) ||
726 (PartData.PartType == PARTITION_FAT_16) ||
727 (PartData.PartType == PARTITION_HUGE) ||
728 (PartData.PartType == PARTITION_XINT13))
729 {
730 PartType = "FAT";
731 }
732 else if ((PartData.PartType == PARTITION_FAT32) ||
733 (PartData.PartType == PARTITION_FAT32_XINT13))
734 {
735 PartType = "FAT32";
736 }
737 else if (PartData.PartType == PARTITION_IFS)
738 {
739 PartType = "NTFS"; /* FIXME: Not quite correct! */
740 }
741 else
742 {
743 PartType = "Unknown";
744 }
745
746 SetTextXY(6, 8, "ReactOS will be installed");
747
748 PrintTextXY(8, 9, "on Harddisk %lu (%I64u %s), Port=%hu, Bus=%hu, Id=%hu.",
749 PartData.DiskNumber,
750 DiskSize,
751 DiskUnit,
752 PartData.Port,
753 PartData.Bus,
754 PartData.Id);
755
756 PrintTextXY(8, 10, "on Partition %lu (%I64u %s) %s",
757 PartData.PartNumber,
758 PartSize,
759 PartUnit,
760 PartType);
761
762 SetTextXY(6, 13, "Select a file system for the partition from the list below.");
763
764 SetTextXY(8, 15, "\xf9 Press UP or DOWN to select a file system.");
765 SetTextXY(8, 17, "\xf9 Press ENTER to format the partition.");
766 SetTextXY(8, 19, "\xf9 Press ESC to select another partition.");
767
768 /* FIXME: use a real list later */
769 SetInvertedTextXY(6, 22, " Keep current file system (no changes) ");
770
771
772 SetStatusText(" ENTER = Continue ESC = Cancel F3 = Quit");
773
774 while(TRUE)
775 {
776 ConInKey(Ir);
777
778 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
779 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
780 {
781 if (ConfirmQuit(Ir) == TRUE)
782 return(QUIT_PAGE);
783 break;
784 }
785 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
786 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
787 {
788 return(SELECT_PARTITION_PAGE);
789 }
790 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
791 {
792 return(CHECK_FILE_SYSTEM_PAGE);
793 }
794 }
795
796 return(SELECT_FILE_SYSTEM_PAGE);
797 }
798
799
800 static ULONG
801 CheckFileSystemPage(PINPUT_RECORD Ir)
802 {
803 SetTextXY(6, 8, "Check file system");
804
805 SetTextXY(6, 10, "At present, ReactOS can not check file systems.");
806
807 SetStatusText(" Please wait ...");
808
809
810 SetStatusText(" ENTER = Continue F3 = Quit");
811
812 while(TRUE)
813 {
814 ConInKey(Ir);
815
816 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
817 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
818 {
819 if (ConfirmQuit(Ir) == TRUE)
820 return(QUIT_PAGE);
821 break;
822 }
823 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
824 {
825 return(INSTALL_DIRECTORY_PAGE);
826 }
827 }
828
829 return(CHECK_FILE_SYSTEM_PAGE);
830 }
831
832
833 static ULONG
834 InstallDirectoryPage(PINPUT_RECORD Ir)
835 {
836 ULONG Length;
837
838 SetTextXY(6, 8, "Setup installs ReactOS files onto the selected partition. Choose a");
839 SetTextXY(6, 9, "directory where you want ReactOS to be installed:");
840
841 wcscpy(InstallDir, L"\\reactos");
842 Length = wcslen(InstallDir);
843
844 SetInputTextXY(8, 11, 51, InstallDir);
845
846 SetTextXY(6, 14, "To change the suggested directory, press BACKSPACE to delete");
847 SetTextXY(6, 15, "characters and then type the directory where you want ReactOS to");
848 SetTextXY(6, 16, "be installed.");
849
850
851 SetStatusText(" ENTER = Continue F3 = Quit");
852
853 while(TRUE)
854 {
855 ConInKey(Ir);
856
857 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
858 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
859 {
860 if (ConfirmQuit(Ir) == TRUE)
861 return(QUIT_PAGE);
862 break;
863 }
864 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
865 {
866
867 return(PREPARE_COPY_PAGE);
868 }
869 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x08) /* BACKSPACE */
870 {
871 if (Length > 0)
872 {
873 Length--;
874 InstallDir[Length] = 0;
875 SetInputTextXY(8, 11, 51, InstallDir);
876 }
877 }
878 else if (isprint(Ir->Event.KeyEvent.uChar.AsciiChar))
879 {
880 if (Length < 50)
881 {
882 InstallDir[Length] = (WCHAR)Ir->Event.KeyEvent.uChar.AsciiChar;
883 Length++;
884 InstallDir[Length] = 0;
885 SetInputTextXY(8, 11, 51, InstallDir);
886 }
887 }
888 }
889
890 return(INSTALL_DIRECTORY_PAGE);
891 }
892
893
894 static ULONG
895 PrepareCopyPage(PINPUT_RECORD Ir)
896 {
897 WCHAR PathBuffer[MAX_PATH];
898 PINICACHESECTION Section;
899 PINICACHEITERATOR Iterator;
900 PWCHAR KeyName;
901 PWCHAR KeyValue;
902 ULONG Length;
903 NTSTATUS Status;
904
905
906 SetTextXY(6, 8, "Setup prepares your computer for copying the ReactOS files. ");
907
908
909 SetTextXY(8, 12, "Build file copy list");
910
911 SetTextXY(8, 14, "Create directories");
912
913 SetStatusText(" Please wait...");
914
915
916 /* build the file copy list */
917
918 SetInvertedTextXY(8, 12, "Build file copy list");
919
920 /* FIXME: build that list */
921
922 SetTextXY(8, 12, "Build file copy list");
923 SetHighlightedTextXY(50, 12, "Done");
924
925
926
927
928 /* create directories */
929 SetInvertedTextXY(8, 14, "Create directories");
930
931
932 /* Open 'Directories' section */
933 Section = IniCacheGetSection(IniCache,
934 L"Directories");
935 if (Section == NULL)
936 {
937 PopupError("Setup failed to find the 'Directories' section\n"
938 "in TXTSETUP.SIF.\n",
939 "ENTER = Reboot computer");
940
941 while(TRUE)
942 {
943 ConInKey(Ir);
944
945 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
946 {
947 return(QUIT_PAGE);
948 }
949 }
950 }
951
952 /*
953 * FIXME:
954 * Install directories like '\reactos\test' are not handled yet.
955 */
956
957 /* Build full install directory name */
958 swprintf(PathBuffer,
959 L"\\Device\\Harddisk%lu\\Partition%lu",
960 PartData.DiskNumber,
961 PartData.PartNumber);
962 if (InstallDir[0] != L'\\')
963 wcscat(PathBuffer, L"\\");
964 wcscat(PathBuffer, InstallDir);
965
966 /* Remove trailing backslash */
967 Length = wcslen(PathBuffer);
968 if ((Length > 0) && (PathBuffer[Length - 1] == '\\'))
969 PathBuffer[Length - 1] = 0;
970
971 /* Create the install directory */
972 Status = CreateDirectory(PathBuffer);
973 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION)
974 {
975 DPRINT1("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer, Status);
976
977 PopupError("Setup could not create the install directory.",
978 "ENTER = Reboot computer");
979
980 while(TRUE)
981 {
982 ConInKey(Ir);
983
984 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
985 {
986 return(QUIT_PAGE);
987 }
988 }
989 }
990
991
992 /* Enumerate the directory values and create the subdirectories */
993 Iterator = IniCacheFindFirstValue(Section,
994 &KeyName,
995 &KeyValue);
996 if (Iterator != NULL)
997 {
998 do
999 {
1000 if (KeyValue[0] == L'\\' && KeyValue[1] != 0)
1001 {
1002 DPRINT("Absolute Path: '%S'\n", KeyValue);
1003
1004 swprintf(PathBuffer,
1005 L"\\Device\\Harddisk%lu\\Partition%lu",
1006 PartData.DiskNumber,
1007 PartData.PartNumber);
1008 wcscat(PathBuffer, KeyValue);
1009
1010 DPRINT("FullPath: '%S'\n", PathBuffer);
1011 }
1012 else if (KeyValue[0] != L'\\')
1013 {
1014 DPRINT("RelativePath: '%S'\n", KeyValue);
1015 swprintf(PathBuffer,
1016 L"\\Device\\Harddisk%lu\\Partition%lu",
1017 PartData.DiskNumber,
1018 PartData.PartNumber);
1019
1020 if (InstallDir[0] != L'\\')
1021 wcscat(PathBuffer, L"\\");
1022 wcscat(PathBuffer, InstallDir);
1023 wcscat(PathBuffer, L"\\");
1024 wcscat(PathBuffer, KeyValue);
1025
1026 DPRINT("FullPath: '%S'\n", PathBuffer);
1027
1028 Status = CreateDirectory(PathBuffer);
1029 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION)
1030 {
1031 DPRINT1("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer, Status);
1032
1033 PopupError("Setup could not create install directories.",
1034 "ENTER = Reboot computer");
1035
1036 while(TRUE)
1037 {
1038 ConInKey(Ir);
1039
1040 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1041 {
1042 IniCacheFindClose(Iterator);
1043 return(QUIT_PAGE);
1044 }
1045 }
1046 }
1047 }
1048 }
1049 while (IniCacheFindNextValue(Iterator, &KeyName, &KeyValue));
1050
1051 IniCacheFindClose(Iterator);
1052 }
1053
1054
1055 SetTextXY(8, 14, "Create directories");
1056 SetHighlightedTextXY(50, 14, "Done");
1057
1058
1059 SetStatusText(" ENTER = Continue F3 = Quit");
1060
1061 while(TRUE)
1062 {
1063 ConInKey(Ir);
1064
1065 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1066 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1067 {
1068 if (ConfirmQuit(Ir) == TRUE)
1069 return(QUIT_PAGE);
1070 break;
1071 }
1072 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1073 {
1074 return(FILE_COPY_PAGE);
1075 }
1076 }
1077
1078 return(PREPARE_COPY_PAGE);
1079 }
1080
1081
1082 static ULONG
1083 FileCopyPage(PINPUT_RECORD Ir)
1084 {
1085
1086 SetTextXY(6, 8, "Copying files");
1087
1088
1089 SetStatusText(" ENTER = Continue F3 = Quit");
1090
1091 while(TRUE)
1092 {
1093 ConInKey(Ir);
1094
1095 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1096 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1097 {
1098 if (ConfirmQuit(Ir) == TRUE)
1099 return(QUIT_PAGE);
1100 break;
1101 }
1102 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1103 {
1104 return(INIT_SYSTEM_PAGE);
1105 }
1106 }
1107
1108 return(FILE_COPY_PAGE);
1109 }
1110
1111
1112 #if 0
1113 static NTSTATUS
1114 UpdateSystemRootLink(VOID)
1115 {
1116 OBJECT_ATTRIBUTES ObjectAttributes;
1117 UNICODE_STRING LinkName;
1118 UNICODE_STRING TargetName;
1119 CHAR TargetBuffer[MAX_PATH];
1120 HANDLE Handle;
1121 NTSTATUS Status;
1122
1123 RtlInitUnicodeString(&LinkName,
1124 L"\\SystemRoot");
1125
1126 InitializeObjectAttributes(&ObjectAttributes,
1127 &LinkName,
1128 OBJ_OPENLINK,
1129 NULL,
1130 NULL);
1131
1132 Status = NtOpenSymbolicLinkObject(&Handle,
1133 SYMBOLIC_LINK_ALL_ACCESS,
1134 &ObjectAttributes);
1135 if (!NT_SUCCESS(Status))
1136 return(Status);
1137
1138 Status = NtMakeTemporaryObject(Handle);
1139 NtClose(Handle);
1140 if (!NT_SUCCESS(Status))
1141 return(Status);
1142
1143 sprintf(TargetBuffer,
1144 "\\Device\\Harddisk%lu\\Partition%lu",
1145 PartData.DiskNumber,
1146 PartData.PartNumber);
1147 if (InstallDir[0] != '\\')
1148 strcat(TargetBuffer, "\\");
1149 strcat(TargetBuffer, InstallDir);
1150
1151 RtlCreateUnicodeStringFromAsciiz(&TargetName,
1152 TargetBuffer);
1153
1154 Status = NtCreateSymbolicLinkObject(&Handle,
1155 SYMBOLIC_LINK_ALL_ACCESS,
1156 &ObjectAttributes,
1157 &TargetName);
1158
1159 RtlFreeUnicodeString(&TargetName);
1160
1161 if (!NT_SUCCESS(Status))
1162 return(Status);
1163
1164 NtClose(Handle);
1165
1166 return(STATUS_SUCCESS);
1167 }
1168 #endif
1169
1170
1171 static ULONG
1172 InitSystemPage(PINPUT_RECORD Ir)
1173 {
1174 #if 0
1175 NTSTATUS Status;
1176 #endif
1177
1178 SetTextXY(6, 8, "Initializing system settings");
1179
1180
1181 SetTextXY(6, 12, "Create registry hives");
1182
1183 SetTextXY(6, 14, "Update registry hives");
1184
1185 SetTextXY(6, 16, "Install/update boot manager");
1186
1187 SetStatusText(" Please wait...");
1188
1189 #if 0
1190 /*
1191 * Initialize registry
1192 */
1193
1194 /* Update 'SystemRoot' link */
1195 Status = UpdateSystemRootLink();
1196 if (!NT_SUCCESS(Status))
1197 {
1198
1199 PrintTextXY(6, 25, "UpdateSystemRootLink() failed (Status = 0x%08lx)", Status);
1200 }
1201
1202
1203 Status = NtInitializeRegistry(TRUE);
1204 if (!NT_SUCCESS(Status))
1205 {
1206
1207 PrintTextXY(6, 26, "NtInitializeRegistry() failed (Status = 0x%08lx)", Status);
1208 }
1209 #endif
1210
1211 /*
1212 * Update registry
1213 */
1214
1215 /* FIXME: Create key '\Registry\Machine\System\Setup' */
1216
1217 /* FIXME: Create value 'SystemSetupInProgress' */
1218
1219
1220
1221 SetStatusText(" ENTER = Continue F3 = Quit");
1222
1223 while(TRUE)
1224 {
1225 ConInKey(Ir);
1226
1227 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1228 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1229 {
1230 if (ConfirmQuit(Ir) == TRUE)
1231 return(QUIT_PAGE);
1232 break;
1233 }
1234 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1235 {
1236 return(SUCCESS_PAGE);
1237 }
1238 }
1239
1240 return(INIT_SYSTEM_PAGE);
1241 }
1242
1243
1244 static ULONG
1245 QuitPage(PINPUT_RECORD Ir)
1246 {
1247 SetTextXY(10, 6, "ReactOS is not completely installed");
1248
1249 SetTextXY(10, 8, "Remove floppy disk from Drive A: and");
1250 SetTextXY(10, 9, "all CD-ROMs from CD-Drive.");
1251
1252 SetTextXY(10, 11, "Press ENTER to reboot your computer.");
1253
1254 SetStatusText(" ENTER = Reboot computer");
1255
1256 while(TRUE)
1257 {
1258 ConInKey(Ir);
1259
1260 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1261 {
1262 return(REBOOT_PAGE);
1263 }
1264 }
1265 }
1266
1267
1268 static ULONG
1269 SuccessPage(PINPUT_RECORD Ir)
1270 {
1271 SetTextXY(10, 6, "The basic components of ReactOS have been installed successfully.");
1272
1273 SetTextXY(10, 8, "Remove floppy disk from Drive A: and");
1274 SetTextXY(10, 9, "all CD-ROMs from CD-Drive.");
1275
1276 SetTextXY(10, 11, "Press ENTER to reboot your computer.");
1277
1278 SetStatusText(" ENTER = Reboot computer");
1279
1280 while(TRUE)
1281 {
1282 ConInKey(Ir);
1283
1284 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1285 {
1286 return(REBOOT_PAGE);
1287 }
1288 }
1289 }
1290
1291
1292 VOID STDCALL
1293 NtProcessStartup(PPEB Peb)
1294 {
1295 NTSTATUS Status;
1296 INPUT_RECORD Ir;
1297 ULONG Page;
1298
1299 RtlNormalizeProcessParams(Peb->ProcessParameters);
1300
1301 ProcessHeap = Peb->ProcessHeap;
1302
1303 Status = AllocConsole();
1304 if (!NT_SUCCESS(Status))
1305 {
1306 PrintString("AllocConsole() failed (Status = 0x%08lx)\n", Status);
1307
1308 /* Raise a hard error (crash the system/BSOD) */
1309 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED,
1310 0,0,0,0,0);
1311 }
1312
1313 PartDataValid = FALSE;
1314
1315 Page = START_PAGE;
1316 while (Page != REBOOT_PAGE)
1317 {
1318 ClearScreen();
1319
1320 SetUnderlinedTextXY(4, 3, " ReactOS " KERNEL_VERSION_STR " Setup ");
1321
1322 switch (Page)
1323 {
1324 /* Start page */
1325 case START_PAGE:
1326 Page = StartPage(&Ir);
1327 break;
1328
1329 /* Intro page */
1330 case INTRO_PAGE:
1331 Page = IntroPage(&Ir);
1332 break;
1333
1334 /* Install pages */
1335 case INSTALL_INTRO_PAGE:
1336 Page = InstallIntroPage(&Ir);
1337 break;
1338
1339 #if 0
1340 case OEM_DRIVER_PAGE:
1341 Page = OemDriverPage(&Ir);
1342 break;
1343 #endif
1344
1345 #if 0
1346 case DEVICE_SETTINGS_PAGE:
1347 #endif
1348
1349 case SELECT_PARTITION_PAGE:
1350 Page = SelectPartitionPage(&Ir);
1351 break;
1352
1353 case SELECT_FILE_SYSTEM_PAGE:
1354 Page = SelectFileSystemPage(&Ir);
1355 break;
1356
1357 case CHECK_FILE_SYSTEM_PAGE:
1358 Page = CheckFileSystemPage(&Ir);
1359 break;
1360
1361 case INSTALL_DIRECTORY_PAGE:
1362 Page = InstallDirectoryPage(&Ir);
1363 break;
1364
1365 case PREPARE_COPY_PAGE:
1366 Page = PrepareCopyPage(&Ir);
1367 break;
1368
1369 case FILE_COPY_PAGE:
1370 Page = FileCopyPage(&Ir);
1371 break;
1372
1373 case INIT_SYSTEM_PAGE:
1374 Page = InitSystemPage(&Ir);
1375 break;
1376
1377
1378 /* Repair pages */
1379 case REPAIR_INTRO_PAGE:
1380 Page = RepairIntroPage(&Ir);
1381 break;
1382
1383
1384 case SUCCESS_PAGE:
1385 Page = SuccessPage(&Ir);
1386 break;
1387
1388 case QUIT_PAGE:
1389 Page = QuitPage(&Ir);
1390 break;
1391 }
1392 }
1393
1394 /* Reboot */
1395 FreeConsole();
1396 NtShutdownSystem(ShutdownReboot);
1397 }
1398
1399 /* EOF */