branch update for HEAD-2002110401
[reactos.git] / 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 "usetup.h"
31 #include "console.h"
32 #include "partlist.h"
33
34
35
36 #define START_PAGE                      0
37 #define INTRO_PAGE                      1
38 #define INSTALL_INTRO_PAGE              2
39
40 #define SELECT_PARTITION_PAGE           4
41 #define SELECT_FILE_SYSTEM_PAGE         5
42 #define CHECK_FILE_SYSTEM_PAGE          6
43 #define PREPARE_COPY_PAGE               7
44 #define INSTALL_DIRECTORY_PAGE          8
45 #define FILE_COPY_PAGE                  9
46 #define INIT_SYSTEM_PAGE                10
47
48 #define REPAIR_INTRO_PAGE               20
49
50 #define SUCCESS_PAGE                    100
51 #define QUIT_PAGE                       101
52 #define REBOOT_PAGE                     102
53
54
55 /* GLOBALS ******************************************************************/
56
57 HANDLE ProcessHeap;
58
59 BOOL PartDataValid = FALSE;
60 PARTDATA PartData;
61
62 CHAR InstallDir[51];
63
64 UNICODE_STRING SourcePath;
65 UNICODE_STRING SourceRootPath;
66
67
68 /* FUNCTIONS ****************************************************************/
69
70 static VOID
71 PrintString(char* fmt,...)
72 {
73   char buffer[512];
74   va_list ap;
75   UNICODE_STRING UnicodeString;
76   ANSI_STRING AnsiString;
77
78   va_start(ap, fmt);
79   vsprintf(buffer, fmt, ap);
80   va_end(ap);
81
82   RtlInitAnsiString(&AnsiString, buffer);
83   RtlAnsiStringToUnicodeString(&UnicodeString,
84                                &AnsiString,
85                                TRUE);
86   NtDisplayString(&UnicodeString);
87   RtlFreeUnicodeString(&UnicodeString);
88 }
89
90
91 /*
92  * Confirm quit setup
93  * RETURNS
94  *      TRUE: Quit setup.
95  *      FALSE: Don't quit setup.
96  */
97 static BOOL
98 ConfirmQuit(PINPUT_RECORD Ir)
99 {
100   SHORT xScreen;
101   SHORT yScreen;
102   SHORT yTop;
103   SHORT xLeft;
104   BOOL Result = FALSE;
105   PUSHORT pAttributes = NULL;
106   PUCHAR pCharacters = NULL;
107   COORD Pos;
108
109   GetScreenSize(&xScreen, &yScreen);
110   yTop = (yScreen - 10) / 2;
111   xLeft = (xScreen - 52) / 2;
112
113   /* Save screen */
114 #if 0
115   Pos.X = 0;
116   Pos.Y = 0;
117   pAttributes = (PUSHORT)RtlAllocateHeap(ProcessHeap,
118                                          0,
119                                          xScreen * yScreen * sizeof(USHORT));
120 CHECKPOINT1;
121 DPRINT1("pAttributes %p\n", pAttributes);
122   ReadConsoleOutputAttributes(pAttributes,
123                               xScreen * yScreen,
124                               Pos,
125                               NULL);
126 CHECKPOINT1;
127   pCharacters = (PUCHAR)RtlAllocateHeap(ProcessHeap,
128                                         0,
129                                         xScreen * yScreen * sizeof(UCHAR));
130 CHECKPOINT1;
131   ReadConsoleOutputCharacters(pCharacters,
132                               xScreen * yScreen,
133                               Pos,
134                               NULL);
135 CHECKPOINT1;
136 #endif
137
138   /* Draw popup window */
139   SetTextXY(xLeft, yTop,
140             "+----------------------------------------------------+");
141   SetTextXY(xLeft, yTop + 1,
142             "| ReactOS 0.0.20 is not completely installed on your |");
143   SetTextXY(xLeft, yTop + 2,
144             "| computer. If you quit Setup now, you will need to  |");
145   SetTextXY(xLeft, yTop + 3,
146             "| run Setup again to install ReactOS.                |");
147   SetTextXY(xLeft, yTop + 4,
148             "|                                                    |");
149   SetTextXY(xLeft, yTop + 5,
150             "|   * Press ENTER to continue Setup.                 |");
151   SetTextXY(xLeft, yTop + 6,
152             "|   * Press F3 to quit Setup.                        |");
153   SetTextXY(xLeft, yTop + 7,
154             "+----------------------------------------------------+");
155   SetTextXY(xLeft, yTop + 8,
156             "| F3= Quit  ENTER = Continue                         |");
157   SetTextXY(xLeft, yTop + 9,
158             "+----------------------------------------------------+");
159
160   while(TRUE)
161     {
162       ConInKey(Ir);
163
164       if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
165           (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3))        /* F3 */
166         {
167           Result = TRUE;
168           break;
169         }
170       else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)      /* ENTER */
171         {
172           Result = FALSE;
173           break;
174         }
175     }
176
177   /* Restore screen */
178 #if 0
179 CHECKPOINT1;
180   WriteConsoleOutputAttributes(pAttributes,
181                                xScreen * yScreen,
182                                Pos,
183                                NULL);
184 CHECKPOINT1;
185
186   WriteConsoleOutputCharacters(pCharacters,
187                                xScreen * yScreen,
188                                Pos);
189 CHECKPOINT1;
190
191   RtlFreeHeap(ProcessHeap,
192               0,
193               pAttributes);
194   RtlFreeHeap(ProcessHeap,
195               0,
196               pCharacters);
197 #endif
198
199   return(Result);
200 }
201
202
203
204
205 /*
206  * Start page
207  * RETURNS
208  *      Number of the next page.
209  */
210 static ULONG
211 StartPage(PINPUT_RECORD Ir)
212 {
213   NTSTATUS Status;
214
215   SetStatusText("   Please wait...");
216
217   Status = GetSourcePaths(&SourcePath,
218                           &SourceRootPath);
219   if (!NT_SUCCESS(Status))
220     {
221       PrintTextXY(6, 15, "GetSourcePath() failed (Status 0x%08lx)", Status);
222     }
223   else
224     {
225       PrintTextXY(6, 15, "SourcePath: '%wZ'", &SourcePath);
226       PrintTextXY(6, 16, "SourceRootPath: '%wZ'", &SourceRootPath);
227     }
228
229   /*
230    * FIXME: Open and load txtsetup.sif here. A pointer (or handle) to the
231    * ini data should be stored in a global variable.
232    * The full path to txtsetup.sif is created by appending '\txtsetup.sif'
233    * to the unicode string SourceRootPath.
234    */
235
236   SetStatusText("   ENTER = Continue");
237
238   while(TRUE)
239     {
240       ConInKey(Ir);
241
242       if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)   /* ENTER */
243         {
244           return(INTRO_PAGE);
245         }
246     }
247
248   return(START_PAGE);
249 }
250
251
252
253 static ULONG
254 RepairIntroPage(PINPUT_RECORD Ir)
255 {
256   SetTextXY(6, 8, "ReactOS Setup is in an early development phase. It does not yet");
257   SetTextXY(6, 9, "support all the functions of a fully usable setup application.");
258
259   SetTextXY(6, 12, "The repair functions are not implemented yet.");
260
261   SetTextXY(8, 15, "\xf9  Press ESC to return to the main page.");
262
263   SetTextXY(8, 17, "\xf9  Press ENTER to reboot your computer.");
264
265   SetStatusText("   ESC = Main page  ENTER = Reboot");
266
267   while(TRUE)
268     {
269       ConInKey(Ir);
270
271       if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
272         {
273           return(REBOOT_PAGE);
274         }
275       else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
276                (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
277         {
278           return(INTRO_PAGE);
279         }
280     }
281
282   return(REPAIR_INTRO_PAGE);
283 }
284
285
286 /*
287  * First setup page
288  * RETURNS
289  *      TRUE: setup/repair completed successfully
290  *      FALSE: setup/repair terminated by user
291  */
292 static ULONG
293 IntroPage(PINPUT_RECORD Ir)
294 {
295   SetHighlightedTextXY(6, 8, "Welcome to ReactOS Setup");
296
297   SetTextXY(6, 11, "This part of the setup copies the ReactOS Operating System to your");
298   SetTextXY(6, 12, "computer and prepares the second part of the setup.");
299
300   SetTextXY(8, 15, "\xf9  Press ENTER to install ReactOS.");
301
302   SetTextXY(8, 17, "\xf9  Press E to start the emergency repair console.");
303
304   SetTextXY(8, 19, "\xf9  Press R to repair ReactOS.");
305
306   SetTextXY(8, 21, "\xf9  Press F3 to quit without installing ReactOS.");
307
308
309   SetStatusText("   ENTER = Continue   F3 = Quit");
310
311   while(TRUE)
312     {
313       ConInKey(Ir);
314
315       if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
316           (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
317         {
318           if (ConfirmQuit(Ir) == TRUE)
319             return(QUIT_PAGE);
320           break;
321         }
322       else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
323         {
324           return(INSTALL_INTRO_PAGE);
325         }
326 #if 0
327       else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'E') /* E */
328         {
329           return(RepairConsole());
330         }
331 #endif
332       else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'R') /* R */
333         {
334           return(REPAIR_INTRO_PAGE);
335         }
336     }
337
338   return(INTRO_PAGE);
339 }
340
341
342 static ULONG
343 InstallIntroPage(PINPUT_RECORD Ir)
344 {
345   SetTextXY(6, 8, "ReactOS Setup is in an early development phase. It does not yet");
346   SetTextXY(6, 9, "support all the functions of a fully usable setup application.");
347
348   SetTextXY(6, 12, "The following functions are missing:");
349   SetTextXY(8, 13, "- Creating and deleting harddisk partitions.");
350   SetTextXY(8, 14, "- Formatting partitions.");
351   SetTextXY(8, 15, "- Support for non-FAT file systems.");
352   SetTextXY(8, 16, "- Checking file systems.");
353   SetTextXY(8, 17, "- Installing the bootloader.");
354
355
356
357   SetTextXY(8, 21, "\xf9  Press ENTER to install ReactOS.");
358
359   SetTextXY(8, 23, "\xf9  Press F3 to quit without installing ReactOS.");
360
361
362   SetStatusText("   ENTER = Continue   F3 = Quit");
363
364   while(TRUE)
365     {
366       ConInKey(Ir);
367
368       if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
369           (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
370         {
371           if (ConfirmQuit(Ir) == TRUE)
372             return(QUIT_PAGE);
373           break;
374         }
375       else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
376         {
377           return(SELECT_PARTITION_PAGE);
378         }
379     }
380
381   return(INSTALL_INTRO_PAGE);
382 }
383
384
385 static ULONG
386 SelectPartitionPage(PINPUT_RECORD Ir)
387 {
388   PPARTLIST PartList;
389   SHORT xScreen;
390   SHORT yScreen;
391
392   SetTextXY(6, 8, "The list below shows existing partitions and unused disk");
393   SetTextXY(6, 9, "space for new partitions.");
394
395   SetTextXY(8, 11, "\xf9  Press UP or DOWN to select a list entry.");
396   SetTextXY(8, 13, "\xf9  Press ENTER to install ReactOS onto the selected partition.");
397   SetTextXY(8, 15, "\xf9  Press C to create a new partition.");
398   SetTextXY(8, 17, "\xf9  Press D to delete an existing partition.");
399
400   SetStatusText("   Please wait...");
401
402   GetScreenSize(&xScreen, &yScreen);
403
404   PartList = CreatePartitionList(2, 19, xScreen - 3, yScreen - 3);
405   if (PartList == NULL)
406     {
407       /* FIXME: show an error dialog */
408       return(QUIT_PAGE);
409     }
410
411   SetStatusText("   ENTER = Continue   F3 = Quit");
412
413   while(TRUE)
414     {
415       ConInKey(Ir);
416
417       if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
418           (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
419         {
420           if (ConfirmQuit(Ir) == TRUE)
421             {
422               DestroyPartitionList(PartList);
423               return(QUIT_PAGE);
424             }
425           break;
426         }
427       else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
428                (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
429         {
430           ScrollDownPartitionList(PartList);
431         }
432       else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
433                (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
434         {
435           ScrollUpPartitionList(PartList);
436         }
437       else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
438         {
439           PartDataValid = GetPartitionData(PartList, &PartData);
440           DestroyPartitionList(PartList);
441           return(SELECT_FILE_SYSTEM_PAGE);
442         }
443
444       /* FIXME: Update status text */
445
446     }
447
448   DestroyPartitionList(PartList);
449
450   return(SELECT_PARTITION_PAGE);
451 }
452
453
454 static ULONG
455 SelectFileSystemPage(PINPUT_RECORD Ir)
456 {
457   ULONGLONG DiskSize;
458   ULONGLONG PartSize;
459   PCHAR DiskUnit;
460   PCHAR PartUnit;
461   PCHAR PartType;
462
463   if (PartDataValid == FALSE)
464     {
465       /* FIXME: show an error dialog */
466       return(QUIT_PAGE);
467     }
468
469   /* adjust disk size */
470   if (PartData.DiskSize >= 0x280000000ULL) /* 10 GB */
471     {
472       DiskSize = (PartData.DiskSize + (1 << 29)) >> 30;
473       DiskUnit = "GB";
474     }
475   else
476     {
477       DiskSize = (PartData.DiskSize + (1 << 19)) >> 20;
478       DiskUnit = "MB";
479     }
480
481   /* adjust partition size */
482   if (PartData.PartSize >= 0x280000000ULL) /* 10 GB */
483     {
484       PartSize = (PartData.PartSize + (1 << 29)) >> 30;
485       PartUnit = "GB";
486     }
487   else
488     {
489       PartSize = (PartData.PartSize + (1 << 19)) >> 20;
490       PartUnit = "MB";
491     }
492
493   /* adjust partition type */
494   if ((PartData.PartType == PARTITION_FAT_12) ||
495       (PartData.PartType == PARTITION_FAT_16) ||
496       (PartData.PartType == PARTITION_HUGE) ||
497       (PartData.PartType == PARTITION_XINT13))
498     {
499       PartType = "FAT";
500     }
501   else if ((PartData.PartType == PARTITION_FAT32) ||
502            (PartData.PartType == PARTITION_FAT32_XINT13))
503     {
504       PartType = "FAT32";
505     }
506   else if (PartData.PartType == PARTITION_IFS)
507     {
508       PartType = "NTFS"; /* FIXME: Not quite correct! */
509     }
510   else
511     {
512       PartType = "Unknown";
513     }
514
515   SetTextXY(6, 8, "ReactOS will be installed");
516
517   PrintTextXY(8, 9, "on Harddisk %lu (%I64u %s), Port=%hu, Bus=%hu, Id=%hu.",
518               PartData.DiskNumber,
519               DiskSize,
520               DiskUnit,
521               PartData.Port,
522               PartData.Bus,
523               PartData.Id);
524
525   PrintTextXY(8, 10, "on Partition %lu (%I64u %s) %s",
526               PartData.PartNumber,
527               PartSize,
528               PartUnit,
529               PartType);
530
531   SetTextXY(6, 13, "Select a file system for the partition from the list below.");
532
533   SetTextXY(8, 15, "\xf9  Press UP or DOWN to select a file system.");
534   SetTextXY(8, 17, "\xf9  Press ENTER to format the partition.");
535   SetTextXY(8, 19, "\xf9  Press ESC to select another partition.");
536
537   /* FIXME: use a real list later */
538   SetInvertedTextXY(6, 22, " Keep current file system (no changes) ");
539
540
541   SetStatusText("   ENTER = Continue   ESC = Cancel   F3 = Quit");
542
543   while(TRUE)
544     {
545       ConInKey(Ir);
546
547       if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
548           (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
549         {
550           if (ConfirmQuit(Ir) == TRUE)
551             return(QUIT_PAGE);
552           break;
553         }
554       else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
555                (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
556         {
557           return(SELECT_PARTITION_PAGE);
558         }
559       else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
560         {
561           return(CHECK_FILE_SYSTEM_PAGE);
562         }
563     }
564
565   return(SELECT_FILE_SYSTEM_PAGE);
566 }
567
568
569 static ULONG
570 CheckFileSystemPage(PINPUT_RECORD Ir)
571 {
572   SetTextXY(6, 8, "Check file system");
573
574   SetTextXY(6, 10, "At present, ReactOS can not check file systems.");
575
576   SetStatusText("   Please wait ...");
577
578
579   SetStatusText("   ENTER = Continue   F3 = Quit");
580
581   while(TRUE)
582     {
583       ConInKey(Ir);
584
585       if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
586           (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
587         {
588           if (ConfirmQuit(Ir) == TRUE)
589             return(QUIT_PAGE);
590           break;
591         }
592       else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
593         {
594           return(INSTALL_DIRECTORY_PAGE);
595         }
596     }
597
598   return(CHECK_FILE_SYSTEM_PAGE);
599 }
600
601
602 static ULONG
603 InstallDirectoryPage(PINPUT_RECORD Ir)
604 {
605   ULONG Length;
606
607   SetTextXY(6, 8, "Setup installs ReactOS files onto the selected partition. Choose a");
608   SetTextXY(6, 9, "directory where you want ReactOS to be installed:");
609
610   strcpy(InstallDir, "\\reactos");
611   Length = strlen(InstallDir);
612
613   SetInputTextXY(8, 11, 51, InstallDir);
614
615   SetTextXY(6, 14, "To change the suggested directory, press BACKSPACE to delete");
616   SetTextXY(6, 15, "characters and then type the directory where you want ReactOS to");
617   SetTextXY(6, 16, "be installed.");
618
619
620   SetStatusText("   ENTER = Continue   F3 = Quit");
621
622   while(TRUE)
623     {
624       ConInKey(Ir);
625
626       if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
627           (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
628         {
629           if (ConfirmQuit(Ir) == TRUE)
630             return(QUIT_PAGE);
631           break;
632         }
633       else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
634         {
635           return(PREPARE_COPY_PAGE);
636         }
637       else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x08) /* BACKSPACE */
638         {
639           if (Length > 0)
640             {
641               Length--;
642               InstallDir[Length] = 0;
643               SetInputTextXY(8, 11, 51, InstallDir);
644             }
645         }
646       else if (isprint(Ir->Event.KeyEvent.uChar.AsciiChar))
647         {
648           if (Length < 50)
649             {
650               InstallDir[Length] = Ir->Event.KeyEvent.uChar.AsciiChar;
651               Length++;
652               InstallDir[Length] = 0;
653               SetInputTextXY(8, 11, 51, InstallDir);
654             }
655         }
656     }
657
658   return(INSTALL_DIRECTORY_PAGE);
659 }
660
661
662 static ULONG
663 PrepareCopyPage(PINPUT_RECORD Ir)
664 {
665   OBJECT_ATTRIBUTES ObjectAttributes;
666   IO_STATUS_BLOCK IoStatusBlock;
667   CHAR PathBuffer[MAX_PATH];
668   UNICODE_STRING PathName;
669   HANDLE DirectoryHandle;
670   NTSTATUS Status;
671   PCHAR End;
672   ULONG Length;
673   ULONG i;
674
675   PCHAR Dirs[]= {
676     "System32",
677     "System32\\Config",
678     "System32\\Drivers",
679     "Inf",
680     "Help",
681     "Fonts",
682     NULL};
683
684   SetTextXY(6, 8, "Setup prepares your computer for copying the ReactOS files. ");
685
686
687   SetTextXY(8, 12, "Build file copy list");
688
689   SetTextXY(8, 14, "Create directories");
690
691   SetStatusText("   Please wait...");
692
693
694   /* build the file copy list */
695
696   SetInvertedTextXY(8, 12, "Build file copy list");
697
698   /* FIXME: build that list */
699
700   SetTextXY(8, 12, "Build file copy list");
701   SetHighlightedTextXY(50, 12, "Done");
702
703
704   /* create directories */
705   SetInvertedTextXY(8, 14, "Create directories");
706
707
708   /*
709    * FIXME: Enumerate the ini section 'Directories' and create all "relative" directories
710    */
711
712
713   /* create the systemroot directory */
714   sprintf(PathBuffer,
715           "\\Device\\Harddisk%lu\\Partition%lu",
716           PartData.DiskNumber,
717           PartData.PartNumber);
718   if (InstallDir[0] != '\\')
719     strcat(PathBuffer, "\\");
720   strcat(PathBuffer, InstallDir);
721
722   /* remove trailing backslash */
723   Length = strlen(PathBuffer);
724   if ((Length > 0) && (PathBuffer[Length - 1] == '\\'))
725     PathBuffer[Length - 1] = 0;
726
727   RtlCreateUnicodeStringFromAsciiz(&PathName,
728                                    PathBuffer);
729
730   ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
731   ObjectAttributes.RootDirectory = NULL;
732   ObjectAttributes.ObjectName = &PathName;
733   ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE | OBJ_INHERIT;
734   ObjectAttributes.SecurityDescriptor = NULL;
735   ObjectAttributes.SecurityQualityOfService = NULL;
736
737   Status = NtCreateFile(&DirectoryHandle,
738                         DIRECTORY_ALL_ACCESS,
739                         &ObjectAttributes,
740                         &IoStatusBlock,
741                         NULL,
742                         FILE_ATTRIBUTE_DIRECTORY,
743                         0,
744                         FILE_CREATE,
745                         FILE_DIRECTORY_FILE,
746                         NULL,
747                         0);
748   if (!NT_SUCCESS(Status))
749     {
750       PrintTextXY(6, 25, "Creating directory failed: Status = 0x%08lx", Status);
751
752     }
753   else
754     {
755       PrintTextXY(6, 25, "Created directory.");
756       NtClose (DirectoryHandle);
757     }
758
759
760   RtlFreeUnicodeString(&PathName);
761
762
763   /* create the subdirectories */
764
765   /* append backslash and init end pointer */
766   strcat(PathBuffer, "\\");
767   Length = strlen(PathBuffer);
768   End = &PathBuffer[Length];
769
770   for (i = 0; Dirs[i] != NULL; i++)
771     {
772       strcpy(End, Dirs[i]);
773
774
775       RtlCreateUnicodeStringFromAsciiz(&PathName,
776                                        PathBuffer);
777
778
779       ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
780       ObjectAttributes.RootDirectory = NULL;
781       ObjectAttributes.ObjectName = &PathName;
782       ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE | OBJ_INHERIT;
783       ObjectAttributes.SecurityDescriptor = NULL;
784       ObjectAttributes.SecurityQualityOfService = NULL;
785
786       Status = NtCreateFile(&DirectoryHandle,
787                             DIRECTORY_ALL_ACCESS,
788                             &ObjectAttributes,
789                             &IoStatusBlock,
790                             NULL,
791                             FILE_ATTRIBUTE_DIRECTORY,
792                             0,
793                             FILE_CREATE,
794                             FILE_DIRECTORY_FILE,
795                             NULL,
796                             0);
797       if (!NT_SUCCESS(Status))
798         {
799           PrintTextXY(6, 25, "Creating directory failed: Status = 0x%08lx", Status);
800         }
801       else
802         {
803           PrintTextXY(6, 25, "Created directory.");
804           NtClose (DirectoryHandle);
805         }
806
807       RtlFreeUnicodeString(&PathName);
808     }
809
810
811   SetTextXY(8, 14, "Create directories");
812   SetHighlightedTextXY(50, 14, "Done");
813
814
815   SetStatusText("   ENTER = Continue   F3 = Quit");
816
817   while(TRUE)
818     {
819       ConInKey(Ir);
820
821       if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
822           (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
823         {
824           if (ConfirmQuit(Ir) == TRUE)
825             return(QUIT_PAGE);
826           break;
827         }
828       else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
829         {
830           return(FILE_COPY_PAGE);
831         }
832     }
833
834   return(PREPARE_COPY_PAGE);
835 }
836
837
838 static ULONG
839 FileCopyPage(PINPUT_RECORD Ir)
840 {
841
842   SetTextXY(6, 8, "Copying files");
843
844
845   SetStatusText("   ENTER = Continue   F3 = Quit");
846
847   while(TRUE)
848     {
849       ConInKey(Ir);
850
851       if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
852           (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
853         {
854           if (ConfirmQuit(Ir) == TRUE)
855             return(QUIT_PAGE);
856           break;
857         }
858       else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
859         {
860           return(INIT_SYSTEM_PAGE);
861         }
862     }
863
864   return(FILE_COPY_PAGE);
865 }
866
867
868 #if 0
869 static NTSTATUS
870 UpdateSystemRootLink(VOID)
871 {
872   OBJECT_ATTRIBUTES ObjectAttributes;
873   UNICODE_STRING LinkName;
874   UNICODE_STRING TargetName;
875   CHAR TargetBuffer[MAX_PATH];
876   HANDLE Handle;
877   NTSTATUS Status;
878
879   RtlInitUnicodeString(&LinkName,
880                        L"\\SystemRoot");
881
882   InitializeObjectAttributes(&ObjectAttributes,
883                              &LinkName,
884                              OBJ_OPENLINK,
885                              NULL,
886                              NULL);
887
888   Status = NtOpenSymbolicLinkObject(&Handle,
889                                     SYMBOLIC_LINK_ALL_ACCESS,
890                                     &ObjectAttributes);
891   if (!NT_SUCCESS(Status))
892     return(Status);
893
894   Status = NtMakeTemporaryObject(Handle);
895   NtClose(Handle);
896   if (!NT_SUCCESS(Status))
897     return(Status);
898
899   sprintf(TargetBuffer,
900           "\\Device\\Harddisk%lu\\Partition%lu",
901           PartData.DiskNumber,
902           PartData.PartNumber);
903   if (InstallDir[0] != '\\')
904     strcat(TargetBuffer, "\\");
905   strcat(TargetBuffer, InstallDir);
906
907   RtlCreateUnicodeStringFromAsciiz(&TargetName,
908                                    TargetBuffer);
909
910   Status = NtCreateSymbolicLinkObject(&Handle,
911                                       SYMBOLIC_LINK_ALL_ACCESS,
912                                       &ObjectAttributes,
913                                       &TargetName);
914
915   RtlFreeUnicodeString(&TargetName);
916
917   if (!NT_SUCCESS(Status))
918     return(Status);
919
920   NtClose(Handle);
921
922   return(STATUS_SUCCESS);
923 }
924 #endif
925
926
927 static ULONG
928 InitSystemPage(PINPUT_RECORD Ir)
929 {
930 #if 0
931   NTSTATUS Status;
932 #endif
933
934   SetTextXY(6, 8, "Initializing system settings");
935
936
937   SetTextXY(6, 12, "Create registry hives");
938
939   SetTextXY(6, 14, "Update registry hives");
940
941   SetTextXY(6, 16, "Install/update boot manager");
942
943   SetStatusText("   Please wait...");
944
945 #if 0
946   /*
947    * Initialize registry
948    */
949
950   /* Update 'SystemRoot' link */
951   Status = UpdateSystemRootLink();
952   if (!NT_SUCCESS(Status))
953     {
954
955       PrintTextXY(6, 25, "UpdateSystemRootLink() failed (Status = 0x%08lx)", Status);
956     }
957
958
959   Status = NtInitializeRegistry(TRUE);
960   if (!NT_SUCCESS(Status))
961     {
962
963       PrintTextXY(6, 26, "NtInitializeRegistry() failed (Status = 0x%08lx)", Status);
964     }
965 #endif
966
967   /*
968    * Update registry
969    */
970
971   /* FIXME: Create key '\Registry\Machine\System\Setup' */
972
973   /* FIXME: Create value 'SystemSetupInProgress' */
974
975
976
977   SetStatusText("   ENTER = Continue   F3 = Quit");
978
979   while(TRUE)
980     {
981       ConInKey(Ir);
982
983       if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
984           (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
985         {
986           if (ConfirmQuit(Ir) == TRUE)
987             return(QUIT_PAGE);
988           break;
989         }
990       else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
991         {
992           return(SUCCESS_PAGE);
993         }
994     }
995
996   return(INIT_SYSTEM_PAGE);
997 }
998
999
1000 static ULONG
1001 QuitPage(PINPUT_RECORD Ir)
1002 {
1003   SetTextXY(10, 6, "ReactOS is not completely installed");
1004
1005   SetTextXY(10, 8, "Remove floppy disk from Drive A: and");
1006   SetTextXY(10, 9, "all CD-ROMs from CD-Drive.");
1007
1008   SetTextXY(10, 11, "Press ENTER to reboot your computer.");
1009
1010   SetStatusText("   ENTER = Reboot computer");
1011
1012   while(TRUE)
1013     {
1014       ConInKey(Ir);
1015
1016       if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1017         {
1018           return(REBOOT_PAGE);
1019         }
1020     }
1021 }
1022
1023
1024 static ULONG
1025 SuccessPage(PINPUT_RECORD Ir)
1026 {
1027   SetTextXY(10, 6, "The basic components of ReactOS have been installed successfully.");
1028
1029   SetTextXY(10, 8, "Remove floppy disk from Drive A: and");
1030   SetTextXY(10, 9, "all CD-ROMs from CD-Drive.");
1031
1032   SetTextXY(10, 11, "Press ENTER to reboot your computer.");
1033
1034   SetStatusText("   ENTER = Reboot computer");
1035
1036   while(TRUE)
1037     {
1038       ConInKey(Ir);
1039
1040       if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1041         {
1042           return(REBOOT_PAGE);
1043         }
1044     }
1045 }
1046
1047
1048 VOID STDCALL
1049 NtProcessStartup(PPEB Peb)
1050 {
1051   NTSTATUS Status;
1052   INPUT_RECORD Ir;
1053   ULONG Page;
1054
1055   RtlNormalizeProcessParams(Peb->ProcessParameters);
1056
1057   ProcessHeap = Peb->ProcessHeap;
1058
1059   Status = AllocConsole();
1060   if (!NT_SUCCESS(Status))
1061     {
1062       PrintString("AllocConsole() failed (Status = 0x%08lx)\n", Status);
1063
1064       /* Raise a hard error (crash the system/BSOD) */
1065       NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED,
1066                        0,0,0,0,0);
1067     }
1068
1069   Page = START_PAGE;
1070   while (Page != REBOOT_PAGE)
1071     {
1072       ClearScreen();
1073
1074       SetUnderlinedTextXY(4, 3, " ReactOS 0.0.20 Setup ");
1075
1076       switch (Page)
1077         {
1078           /* Start page */
1079           case START_PAGE:
1080             Page = StartPage(&Ir);
1081             break;
1082
1083           /* Intro page */
1084           case INTRO_PAGE:
1085             Page = IntroPage(&Ir);
1086             break;
1087
1088           /* Install pages */
1089           case INSTALL_INTRO_PAGE:
1090             Page = InstallIntroPage(&Ir);
1091             break;
1092
1093 #if 0
1094           case OEM_DRIVER_PAGE:
1095             Page = OemDriverPage(&Ir);
1096             break;
1097 #endif
1098
1099 #if 0
1100           case DEVICE_SETTINGS_PAGE:
1101 #endif
1102
1103           case SELECT_PARTITION_PAGE:
1104             Page = SelectPartitionPage(&Ir);
1105             break;
1106
1107           case SELECT_FILE_SYSTEM_PAGE:
1108             Page = SelectFileSystemPage(&Ir);
1109             break;
1110
1111           case CHECK_FILE_SYSTEM_PAGE:
1112             Page = CheckFileSystemPage(&Ir);
1113             break;
1114
1115           case INSTALL_DIRECTORY_PAGE:
1116             Page = InstallDirectoryPage(&Ir);
1117             break;
1118
1119           case PREPARE_COPY_PAGE:
1120             Page = PrepareCopyPage(&Ir);
1121             break;
1122
1123           case FILE_COPY_PAGE:
1124             Page = FileCopyPage(&Ir);
1125             break;
1126
1127           case INIT_SYSTEM_PAGE:
1128             Page = InitSystemPage(&Ir);
1129             break;
1130
1131
1132           /* Repair pages */
1133           case REPAIR_INTRO_PAGE:
1134             Page = RepairIntroPage(&Ir);
1135             break;
1136
1137
1138           case SUCCESS_PAGE:
1139             Page = SuccessPage(&Ir);
1140             break;
1141
1142           case QUIT_PAGE:
1143             Page = QuitPage(&Ir);
1144             break;
1145         }
1146     }
1147
1148   /* Reboot */
1149   FreeConsole();
1150   NtShutdownSystem(ShutdownReboot);
1151 }
1152
1153 /* EOF */