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