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