[USETUP]
[reactos.git] / reactos / base / setup / usetup / interface / usetup.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 2002, 2003, 2004 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 along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 * Hervé Poussineau (hpoussin@reactos.org)
27 */
28
29 #include <usetup.h>
30
31 #include "bootsup.h"
32 #include "chkdsk.h"
33 #include "cmdcons.h"
34 #include "format.h"
35 #include "drivesup.h"
36 #include "settings.h"
37
38 #define NDEBUG
39 #include <debug.h>
40
41
42 /* GLOBALS ******************************************************************/
43
44 HANDLE ProcessHeap;
45 UNICODE_STRING SourceRootPath;
46 UNICODE_STRING SourceRootDir;
47 UNICODE_STRING SourcePath;
48 BOOLEAN IsUnattendedSetup = FALSE;
49 LONG UnattendDestinationDiskNumber;
50 LONG UnattendDestinationPartitionNumber;
51 LONG UnattendMBRInstallType = -1;
52 LONG UnattendFormatPartition = 0;
53 LONG AutoPartition = 0;
54 WCHAR UnattendInstallationDirectory[MAX_PATH];
55 PWCHAR SelectedLanguageId;
56 WCHAR LocaleID[9];
57 WCHAR DefaultLanguage[20];
58 WCHAR DefaultKBLayout[20];
59 BOOLEAN RepairUpdateFlag = FALSE;
60 HANDLE hPnpThread = INVALID_HANDLE_VALUE;
61 PPARTLIST PartitionList = NULL;
62
63 /* LOCALS *******************************************************************/
64
65 static PFILE_SYSTEM_LIST FileSystemList = NULL;
66
67 static UNICODE_STRING InstallPath;
68
69 /* Path to the install directory */
70 static UNICODE_STRING DestinationPath;
71 static UNICODE_STRING DestinationArcPath;
72 static UNICODE_STRING DestinationRootPath;
73
74 static WCHAR DestinationDriveLetter;
75
76 /* Path to the active partition (boot manager) */
77 static UNICODE_STRING SystemRootPath;
78
79 static HINF SetupInf;
80
81 static HSPFILEQ SetupFileQueue = NULL;
82
83 static BOOLEAN WarnLinuxPartitions = TRUE;
84
85 static PGENERIC_LIST ComputerList = NULL;
86 static PGENERIC_LIST DisplayList = NULL;
87 static PGENERIC_LIST KeyboardList = NULL;
88 static PGENERIC_LIST LayoutList = NULL;
89 static PGENERIC_LIST LanguageList = NULL;
90
91 static LANGID LanguageId = 0;
92
93 static ULONG RequiredPartitionDiskSpace = ~0;
94
95 /* FUNCTIONS ****************************************************************/
96
97 static VOID
98 PrintString(char* fmt,...)
99 {
100 char buffer[512];
101 va_list ap;
102 UNICODE_STRING UnicodeString;
103 ANSI_STRING AnsiString;
104
105 va_start(ap, fmt);
106 vsprintf(buffer, fmt, ap);
107 va_end(ap);
108
109 RtlInitAnsiString(&AnsiString, buffer);
110 RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE);
111 NtDisplayString(&UnicodeString);
112 RtlFreeUnicodeString(&UnicodeString);
113 }
114
115
116 static VOID
117 DrawBox(IN SHORT xLeft,
118 IN SHORT yTop,
119 IN SHORT Width,
120 IN SHORT Height)
121 {
122 COORD coPos;
123 DWORD Written;
124
125 /* draw upper left corner */
126 coPos.X = xLeft;
127 coPos.Y = yTop;
128 FillConsoleOutputCharacterA(StdOutput,
129 0xDA, // '+',
130 1,
131 coPos,
132 &Written);
133
134 /* draw upper edge */
135 coPos.X = xLeft + 1;
136 coPos.Y = yTop;
137 FillConsoleOutputCharacterA(StdOutput,
138 0xC4, // '-',
139 Width - 2,
140 coPos,
141 &Written);
142
143 /* draw upper right corner */
144 coPos.X = xLeft + Width - 1;
145 coPos.Y = yTop;
146 FillConsoleOutputCharacterA(StdOutput,
147 0xBF, // '+',
148 1,
149 coPos,
150 &Written);
151
152 /* Draw right edge, inner space and left edge */
153 for (coPos.Y = yTop + 1; coPos.Y < yTop + Height - 1; coPos.Y++)
154 {
155 coPos.X = xLeft;
156 FillConsoleOutputCharacterA(StdOutput,
157 0xB3, // '|',
158 1,
159 coPos,
160 &Written);
161
162 coPos.X = xLeft + 1;
163 FillConsoleOutputCharacterA(StdOutput,
164 ' ',
165 Width - 2,
166 coPos,
167 &Written);
168
169 coPos.X = xLeft + Width - 1;
170 FillConsoleOutputCharacterA(StdOutput,
171 0xB3, // '|',
172 1,
173 coPos,
174 &Written);
175 }
176
177 /* draw lower left corner */
178 coPos.X = xLeft;
179 coPos.Y = yTop + Height - 1;
180 FillConsoleOutputCharacterA(StdOutput,
181 0xC0, // '+',
182 1,
183 coPos,
184 &Written);
185
186 /* draw lower edge */
187 coPos.X = xLeft + 1;
188 coPos.Y = yTop + Height - 1;
189 FillConsoleOutputCharacterA(StdOutput,
190 0xC4, // '-',
191 Width - 2,
192 coPos,
193 &Written);
194
195 /* draw lower right corner */
196 coPos.X = xLeft + Width - 1;
197 coPos.Y = yTop + Height - 1;
198 FillConsoleOutputCharacterA(StdOutput,
199 0xD9, // '+',
200 1,
201 coPos,
202 &Written);
203 }
204
205
206 VOID
207 PopupError(PCCH Text,
208 PCCH Status,
209 PINPUT_RECORD Ir,
210 ULONG WaitEvent)
211 {
212 SHORT yTop;
213 SHORT xLeft;
214 COORD coPos;
215 DWORD Written;
216 ULONG Length;
217 ULONG MaxLength;
218 ULONG Lines;
219 PCHAR p;
220 PCCH pnext;
221 BOOLEAN LastLine;
222 SHORT Width;
223 SHORT Height;
224
225 /* Count text lines and longest line */
226 MaxLength = 0;
227 Lines = 0;
228 pnext = Text;
229
230 while (TRUE)
231 {
232 p = strchr(pnext, '\n');
233
234 if (p == NULL)
235 {
236 Length = strlen(pnext);
237 LastLine = TRUE;
238 }
239 else
240 {
241 Length = (ULONG)(p - pnext);
242 LastLine = FALSE;
243 }
244
245 Lines++;
246
247 if (Length > MaxLength)
248 MaxLength = Length;
249
250 if (LastLine == TRUE)
251 break;
252
253 pnext = p + 1;
254 }
255
256 /* Check length of status line */
257 if (Status != NULL)
258 {
259 Length = strlen(Status);
260
261 if (Length > MaxLength)
262 MaxLength = Length;
263 }
264
265 Width = MaxLength + 4;
266 Height = Lines + 2;
267
268 if (Status != NULL)
269 Height += 2;
270
271 yTop = (yScreen - Height) / 2;
272 xLeft = (xScreen - Width) / 2;
273
274
275 /* Set screen attributes */
276 coPos.X = xLeft;
277 for (coPos.Y = yTop; coPos.Y < yTop + Height; coPos.Y++)
278 {
279 FillConsoleOutputAttribute(StdOutput,
280 FOREGROUND_RED | BACKGROUND_WHITE,
281 Width,
282 coPos,
283 &Written);
284 }
285
286 DrawBox(xLeft, yTop, Width, Height);
287
288 /* Print message text */
289 coPos.Y = yTop + 1;
290 pnext = Text;
291 while (TRUE)
292 {
293 p = strchr(pnext, '\n');
294
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 WriteConsoleOutputCharacterA(StdOutput,
310 pnext,
311 Length,
312 coPos,
313 &Written);
314 }
315
316 if (LastLine == TRUE)
317 break;
318
319 coPos.Y++;
320 pnext = p + 1;
321 }
322
323 /* Print separator line and status text */
324 if (Status != NULL)
325 {
326 coPos.Y = yTop + Height - 3;
327 coPos.X = xLeft;
328 FillConsoleOutputCharacterA(StdOutput,
329 0xC3, // '+',
330 1,
331 coPos,
332 &Written);
333
334 coPos.X = xLeft + 1;
335 FillConsoleOutputCharacterA(StdOutput,
336 0xC4, // '-',
337 Width - 2,
338 coPos,
339 &Written);
340
341 coPos.X = xLeft + Width - 1;
342 FillConsoleOutputCharacterA(StdOutput,
343 0xB4, // '+',
344 1,
345 coPos,
346 &Written);
347
348 coPos.Y++;
349 coPos.X = xLeft + 2;
350 WriteConsoleOutputCharacterA(StdOutput,
351 Status,
352 min(strlen(Status), (SIZE_T)Width - 4),
353 coPos,
354 &Written);
355 }
356
357 if (WaitEvent == POPUP_WAIT_NONE)
358 return;
359
360 while (TRUE)
361 {
362 CONSOLE_ConInKey(Ir);
363
364 if (WaitEvent == POPUP_WAIT_ANY_KEY ||
365 Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)
366 {
367 return;
368 }
369 }
370 }
371
372
373 /*
374 * Confirm quit setup
375 * RETURNS
376 * TRUE: Quit setup.
377 * FALSE: Don't quit setup.
378 */
379 static BOOL
380 ConfirmQuit(PINPUT_RECORD Ir)
381 {
382 BOOL Result = FALSE;
383 MUIDisplayError(ERROR_NOT_INSTALLED, NULL, POPUP_WAIT_NONE);
384
385 while (TRUE)
386 {
387 CONSOLE_ConInKey(Ir);
388
389 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
390 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
391 {
392 Result = TRUE;
393 break;
394 }
395 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
396 {
397 Result = FALSE;
398 break;
399 }
400 }
401
402 return Result;
403 }
404
405
406 VOID
407 CheckUnattendedSetup(VOID)
408 {
409 WCHAR UnattendInfPath[MAX_PATH];
410 INFCONTEXT Context;
411 HINF UnattendInf;
412 UINT ErrorLine;
413 INT IntValue;
414 PWCHAR Value;
415
416 if (DoesFileExist(SourcePath.Buffer, L"unattend.inf") == FALSE)
417 {
418 DPRINT("Does not exist: %S\\%S\n", SourcePath.Buffer, L"unattend.inf");
419 return;
420 }
421
422 wcscpy(UnattendInfPath, SourcePath.Buffer);
423 wcscat(UnattendInfPath, L"\\unattend.inf");
424
425 /* Load 'unattend.inf' from install media. */
426 UnattendInf = SetupOpenInfFileW(UnattendInfPath,
427 NULL,
428 INF_STYLE_WIN4,
429 LanguageId,
430 &ErrorLine);
431
432 if (UnattendInf == INVALID_HANDLE_VALUE)
433 {
434 DPRINT("SetupOpenInfFileW() failed\n");
435 return;
436 }
437
438 /* Open 'Unattend' section */
439 if (!SetupFindFirstLineW(UnattendInf, L"Unattend", L"Signature", &Context))
440 {
441 DPRINT("SetupFindFirstLineW() failed for section 'Unattend'\n");
442 SetupCloseInfFile(UnattendInf);
443 return;
444 }
445
446 /* Get pointer 'Signature' key */
447 if (!INF_GetData(&Context, NULL, &Value))
448 {
449 DPRINT("INF_GetData() failed for key 'Signature'\n");
450 SetupCloseInfFile(UnattendInf);
451 return;
452 }
453
454 /* Check 'Signature' string */
455 if (_wcsicmp(Value, L"$ReactOS$") != 0)
456 {
457 DPRINT("Signature not $ReactOS$\n");
458 SetupCloseInfFile(UnattendInf);
459 return;
460 }
461
462 /* Check if Unattend setup is enabled */
463 if (!SetupFindFirstLineW(UnattendInf, L"Unattend", L"UnattendSetupEnabled", &Context))
464 {
465 DPRINT("Can't find key 'UnattendSetupEnabled'\n");
466 SetupCloseInfFile(UnattendInf);
467 return;
468 }
469
470 if (!INF_GetData(&Context, NULL, &Value))
471 {
472 DPRINT("Can't read key 'UnattendSetupEnabled'\n");
473 SetupCloseInfFile(UnattendInf);
474 return;
475 }
476
477 if (_wcsicmp(Value, L"yes") != 0)
478 {
479 DPRINT("Unattend setup is disabled by 'UnattendSetupEnabled' key!\n");
480 SetupCloseInfFile(UnattendInf);
481 return;
482 }
483
484 /* Search for 'DestinationDiskNumber' in the 'Unattend' section */
485 if (!SetupFindFirstLineW(UnattendInf, L"Unattend", L"DestinationDiskNumber", &Context))
486 {
487 DPRINT("SetupFindFirstLine() failed for key 'DestinationDiskNumber'\n");
488 SetupCloseInfFile(UnattendInf);
489 return;
490 }
491
492 if (!SetupGetIntField(&Context, 1, &IntValue))
493 {
494 DPRINT("SetupGetIntField() failed for key 'DestinationDiskNumber'\n");
495 SetupCloseInfFile(UnattendInf);
496 return;
497 }
498
499 UnattendDestinationDiskNumber = (LONG)IntValue;
500
501 /* Search for 'DestinationPartitionNumber' in the 'Unattend' section */
502 if (!SetupFindFirstLineW(UnattendInf, L"Unattend", L"DestinationPartitionNumber", &Context))
503 {
504 DPRINT("SetupFindFirstLine() failed for key 'DestinationPartitionNumber'\n");
505 SetupCloseInfFile(UnattendInf);
506 return;
507 }
508
509 if (!SetupGetIntField(&Context, 1, &IntValue))
510 {
511 DPRINT("SetupGetIntField() failed for key 'DestinationPartitionNumber'\n");
512 SetupCloseInfFile(UnattendInf);
513 return;
514 }
515
516 UnattendDestinationPartitionNumber = IntValue;
517
518 /* Search for 'InstallationDirectory' in the 'Unattend' section */
519 if (!SetupFindFirstLineW(UnattendInf, L"Unattend", L"InstallationDirectory", &Context))
520 {
521 DPRINT("SetupFindFirstLine() failed for key 'InstallationDirectory'\n");
522 SetupCloseInfFile(UnattendInf);
523 return;
524 }
525
526 /* Get pointer 'InstallationDirectory' key */
527 if (!INF_GetData(&Context, NULL, &Value))
528 {
529 DPRINT("INF_GetData() failed for key 'InstallationDirectory'\n");
530 SetupCloseInfFile(UnattendInf);
531 return;
532 }
533
534 wcscpy(UnattendInstallationDirectory, Value);
535
536 IsUnattendedSetup = TRUE;
537
538 /* Search for 'MBRInstallType' in the 'Unattend' section */
539 if (SetupFindFirstLineW(UnattendInf, L"Unattend", L"MBRInstallType", &Context))
540 {
541 if (SetupGetIntField(&Context, 1, &IntValue))
542 {
543 UnattendMBRInstallType = IntValue;
544 }
545 }
546
547 /* Search for 'FormatPartition' in the 'Unattend' section */
548 if (SetupFindFirstLineW(UnattendInf, L"Unattend", L"FormatPartition", &Context))
549 {
550 if (SetupGetIntField(&Context, 1, &IntValue))
551 {
552 UnattendFormatPartition = IntValue;
553 }
554 }
555
556 if (SetupFindFirstLineW(UnattendInf, L"Unattend", L"AutoPartition", &Context))
557 {
558 if (SetupGetIntField(&Context, 1, &IntValue))
559 {
560 AutoPartition = IntValue;
561 }
562 }
563
564 /* search for LocaleID in the 'Unattend' section*/
565 if (SetupFindFirstLineW (UnattendInf, L"Unattend", L"LocaleID", &Context))
566 {
567 if (INF_GetData (&Context, NULL, &Value))
568 {
569 LONG Id = wcstol(Value, NULL, 16);
570 swprintf(LocaleID,L"%08lx", Id);
571 }
572 }
573
574 SetupCloseInfFile(UnattendInf);
575
576 DPRINT("Running unattended setup\n");
577 }
578
579
580 VOID
581 UpdateKBLayout(VOID)
582 {
583 PGENERIC_LIST_ENTRY ListEntry;
584 LPCWSTR pszNewLayout;
585
586 pszNewLayout = MUIDefaultKeyboardLayout();
587
588 if (LayoutList == NULL)
589 {
590 LayoutList = CreateKeyboardLayoutList(SetupInf, DefaultKBLayout);
591 if (LayoutList == NULL)
592 {
593 /* FIXME: Handle error! */
594 return;
595 }
596 }
597
598 ListEntry = GetFirstListEntry(LayoutList);
599
600 /* Search for default layout (if provided) */
601 if (pszNewLayout != NULL)
602 {
603 while (ListEntry != NULL)
604 {
605 if (!wcscmp(pszNewLayout, GetListEntryUserData(ListEntry)))
606 {
607 SetCurrentListEntry(LayoutList, ListEntry);
608 break;
609 }
610
611 ListEntry = GetNextListEntry(ListEntry);
612 }
613 }
614 }
615
616
617 static PAGE_NUMBER
618 LanguagePage(PINPUT_RECORD Ir)
619 {
620 PWCHAR NewLanguageId;
621 BOOL RefreshPage = FALSE;
622
623 /* Initialize the computer settings list */
624 if (LanguageList == NULL)
625 {
626 LanguageList = CreateLanguageList(SetupInf, DefaultLanguage);
627
628 if (LanguageList == NULL)
629 {
630 PopupError("Setup failed to initialize available translations", NULL, NULL, POPUP_WAIT_NONE);
631 return INTRO_PAGE;
632 }
633 }
634
635 /* Load the font */
636 SelectedLanguageId = DefaultLanguage;
637 SetConsoleCodePage();
638
639 DrawGenericList(LanguageList,
640 2,
641 18,
642 xScreen - 3,
643 yScreen - 3);
644
645 ScrollToPositionGenericList (LanguageList, GetDefaultLanguageIndex());
646
647 MUIDisplayPage(LANGUAGE_PAGE);
648
649 while (TRUE)
650 {
651 CONSOLE_ConInKey(Ir);
652
653 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
654 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
655 {
656 ScrollDownGenericList (LanguageList);
657 RefreshPage = TRUE;
658 }
659 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
660 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
661 {
662 ScrollUpGenericList(LanguageList);
663 RefreshPage = TRUE;
664 }
665 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
666 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_NEXT)) /* PAGE DOWN */
667 {
668 ScrollPageDownGenericList(LanguageList);
669 RefreshPage = TRUE;
670 }
671 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
672 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_PRIOR)) /* PAGE UP */
673 {
674 ScrollPageUpGenericList(LanguageList);
675 RefreshPage = TRUE;
676 }
677 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
678 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
679 {
680 if (ConfirmQuit(Ir) == TRUE)
681 return QUIT_PAGE;
682 else
683 RedrawGenericList(LanguageList);
684 }
685 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
686 {
687 SelectedLanguageId = (PWCHAR)GetListEntryUserData(GetCurrentListEntry(LanguageList));
688
689 LanguageId = (LANGID)(wcstol(SelectedLanguageId, NULL, 16) & 0xFFFF);
690
691 if (wcscmp(SelectedLanguageId, DefaultLanguage))
692 {
693 UpdateKBLayout();
694 }
695
696 /* Load the font */
697 SetConsoleCodePage();
698
699 return INTRO_PAGE;
700 }
701 else if ((Ir->Event.KeyEvent.uChar.AsciiChar > 0x60) && (Ir->Event.KeyEvent.uChar.AsciiChar < 0x7b))
702 {
703 /* a-z */
704 GenericListKeyPress (LanguageList, Ir->Event.KeyEvent.uChar.AsciiChar);
705 RefreshPage = TRUE;
706 }
707
708 if (RefreshPage)
709 {
710 NewLanguageId = (PWCHAR)GetListEntryUserData(GetCurrentListEntry(LanguageList));
711
712 if (SelectedLanguageId != NewLanguageId)
713 {
714 /* Clear the language page */
715 MUIClearPage(LANGUAGE_PAGE);
716
717 SelectedLanguageId = NewLanguageId;
718
719 /* Load the font */
720 SetConsoleCodePage();
721
722 /* Redraw language selection page in native language */
723 MUIDisplayPage(LANGUAGE_PAGE);
724 }
725
726 RefreshPage = FALSE;
727 }
728 }
729
730 return INTRO_PAGE;
731 }
732
733
734 /*
735 * Start page
736 * RETURNS
737 * Number of the next page.
738 */
739 static PAGE_NUMBER
740 SetupStartPage(PINPUT_RECORD Ir)
741 {
742 //SYSTEM_DEVICE_INFORMATION Sdi;
743 NTSTATUS Status;
744 WCHAR FileNameBuffer[MAX_PATH];
745 INFCONTEXT Context;
746 PWCHAR Value;
747 UINT ErrorLine;
748 //ULONG ReturnSize;
749 PGENERIC_LIST_ENTRY ListEntry;
750 INT IntValue;
751
752 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
753
754 #if 0
755 /* Check whether a harddisk is available */
756 Status = NtQuerySystemInformation(SystemDeviceInformation,
757 &Sdi,
758 sizeof(SYSTEM_DEVICE_INFORMATION),
759 &ReturnSize);
760
761 if (!NT_SUCCESS(Status))
762 {
763 CONSOLE_PrintTextXY(6, 15, "NtQuerySystemInformation() failed (Status 0x%08lx)", Status);
764 MUIDisplayError(ERROR_DRIVE_INFORMATION, Ir, POPUP_WAIT_ENTER);
765 return QUIT_PAGE;
766 }
767
768 if (Sdi.NumberOfDisks == 0)
769 {
770 MUIDisplayError(ERROR_NO_HDD, Ir, POPUP_WAIT_ENTER);
771 return QUIT_PAGE;
772 }
773 #endif
774
775 /* Get the source path and source root path */
776 Status = GetSourcePaths(&SourcePath,
777 &SourceRootPath,
778 &SourceRootDir);
779
780 if (!NT_SUCCESS(Status))
781 {
782 CONSOLE_PrintTextXY(6, 15, "GetSourcePaths() failed (Status 0x%08lx)", Status);
783 MUIDisplayError(ERROR_NO_SOURCE_DRIVE, Ir, POPUP_WAIT_ENTER);
784 return QUIT_PAGE;
785 }
786 #if 0
787 else
788 {
789 CONSOLE_PrintTextXY(6, 15, "SourcePath: '%wZ'", &SourcePath);
790 CONSOLE_PrintTextXY(6, 16, "SourceRootPath: '%wZ'", &SourceRootPath);
791 CONSOLE_PrintTextXY(6, 17, "SourceRootDir: '%wZ'", &SourceRootDir);
792 }
793 #endif
794
795 /* Load txtsetup.sif from install media. */
796 wcscpy(FileNameBuffer, SourcePath.Buffer);
797 wcscat(FileNameBuffer, L"\\txtsetup.sif");
798
799 SetupInf = SetupOpenInfFileW(FileNameBuffer,
800 NULL,
801 INF_STYLE_WIN4,
802 LanguageId,
803 &ErrorLine);
804
805 if (SetupInf == INVALID_HANDLE_VALUE)
806 {
807 MUIDisplayError(ERROR_LOAD_TXTSETUPSIF, Ir, POPUP_WAIT_ENTER);
808 return QUIT_PAGE;
809 }
810
811 /* Open 'Version' section */
812 if (!SetupFindFirstLineW(SetupInf, L"Version", L"Signature", &Context))
813 {
814 MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF, Ir, POPUP_WAIT_ENTER);
815 return QUIT_PAGE;
816 }
817
818 /* Get pointer 'Signature' key */
819 if (!INF_GetData(&Context, NULL, &Value))
820 {
821 MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF, Ir, POPUP_WAIT_ENTER);
822 return QUIT_PAGE;
823 }
824
825 /* Check 'Signature' string */
826 if (_wcsicmp(Value, L"$ReactOS$") != 0)
827 {
828 MUIDisplayError(ERROR_SIGNATURE_TXTSETUPSIF, Ir, POPUP_WAIT_ENTER);
829 return QUIT_PAGE;
830 }
831
832 /* Open 'DiskSpaceRequirements' section */
833 if (!SetupFindFirstLineW(SetupInf, L"DiskSpaceRequirements", L"FreeSysPartDiskSpace", &Context))
834 {
835 MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF, Ir, POPUP_WAIT_ENTER);
836 return QUIT_PAGE;
837 }
838
839 /* Get the 'FreeSysPartDiskSpace' value */
840 if (!SetupGetIntField(&Context, 1, &IntValue))
841 {
842 MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF, Ir, POPUP_WAIT_ENTER);
843 return QUIT_PAGE;
844 }
845
846 RequiredPartitionDiskSpace = (ULONG)IntValue;
847
848 /* Start PnP thread */
849 if (hPnpThread != INVALID_HANDLE_VALUE)
850 {
851 NtResumeThread(hPnpThread, NULL);
852 hPnpThread = INVALID_HANDLE_VALUE;
853 }
854
855 CheckUnattendedSetup();
856
857 if (IsUnattendedSetup)
858 {
859 //TODO
860 //read options from inf
861 ComputerList = CreateComputerTypeList(SetupInf);
862 DisplayList = CreateDisplayDriverList(SetupInf);
863 KeyboardList = CreateKeyboardDriverList(SetupInf);
864 LayoutList = CreateKeyboardLayoutList(SetupInf, DefaultKBLayout);
865 LanguageList = CreateLanguageList(SetupInf, DefaultLanguage);
866
867 /* new part */
868 wcscpy(SelectedLanguageId,LocaleID);
869
870 /* first we hack LanguageList */
871 ListEntry = GetFirstListEntry(LanguageList);
872
873 while (ListEntry != NULL)
874 {
875 if (!wcsicmp(LocaleID, GetListEntryUserData(ListEntry)))
876 {
877 DPRINT("found %S in LanguageList\n",GetListEntryUserData(ListEntry));
878 SetCurrentListEntry(LanguageList, ListEntry);
879 break;
880 }
881
882 ListEntry = GetNextListEntry(ListEntry);
883 }
884
885 /* now LayoutList */
886 ListEntry = GetFirstListEntry(LayoutList);
887
888 while (ListEntry != NULL)
889 {
890 if (!wcsicmp(LocaleID, GetListEntryUserData(ListEntry)))
891 {
892 DPRINT("found %S in LayoutList\n",GetListEntryUserData(ListEntry));
893 SetCurrentListEntry(LayoutList, ListEntry);
894 break;
895 }
896
897 ListEntry = GetNextListEntry(ListEntry);
898 }
899
900 SetConsoleCodePage();
901
902 return INSTALL_INTRO_PAGE;
903 }
904
905 return LANGUAGE_PAGE;
906 }
907
908
909 /*
910 * First setup page
911 * RETURNS
912 * Next page number.
913 */
914 static PAGE_NUMBER
915 IntroPage(PINPUT_RECORD Ir)
916 {
917 MUIDisplayPage(START_PAGE);
918
919 while (TRUE)
920 {
921 CONSOLE_ConInKey(Ir);
922
923 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
924 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
925 {
926 if (ConfirmQuit(Ir) == TRUE)
927 return QUIT_PAGE;
928
929 break;
930 }
931 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
932 {
933 return INSTALL_INTRO_PAGE;
934 }
935 else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'R') /* R */
936 {
937 return REPAIR_INTRO_PAGE;
938 }
939 else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'L') /* R */
940 {
941 return LICENSE_PAGE;
942 }
943 }
944
945 return INTRO_PAGE;
946 }
947
948
949 /*
950 * License Page
951 * RETURNS
952 * Back to main setup page.
953 */
954 static PAGE_NUMBER
955 LicensePage(PINPUT_RECORD Ir)
956 {
957 MUIDisplayPage(LICENSE_PAGE);
958
959 while (TRUE)
960 {
961 CONSOLE_ConInKey(Ir);
962
963 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
964 {
965 return INTRO_PAGE;
966 }
967 }
968
969 return LICENSE_PAGE;
970 }
971
972
973 static PAGE_NUMBER
974 RepairIntroPage(PINPUT_RECORD Ir)
975 {
976 MUIDisplayPage(REPAIR_INTRO_PAGE);
977
978 while(TRUE)
979 {
980 CONSOLE_ConInKey(Ir);
981
982 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
983 {
984 return REBOOT_PAGE;
985 }
986 else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'U') /* U */
987 {
988 RepairUpdateFlag = TRUE;
989 return INSTALL_INTRO_PAGE;
990 }
991 else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'R') /* R */
992 {
993 return RECOVERY_PAGE;
994 }
995 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
996 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
997 {
998 return INTRO_PAGE;
999 }
1000 }
1001
1002 return REPAIR_INTRO_PAGE;
1003 }
1004
1005
1006 static PAGE_NUMBER
1007 InstallIntroPage(PINPUT_RECORD Ir)
1008 {
1009 MUIDisplayPage(INSTALL_INTRO_PAGE);
1010
1011 if (RepairUpdateFlag)
1012 {
1013 //return SELECT_PARTITION_PAGE;
1014 return DEVICE_SETTINGS_PAGE;
1015 }
1016
1017 if (IsUnattendedSetup)
1018 {
1019 return SELECT_PARTITION_PAGE;
1020 }
1021
1022 while (TRUE)
1023 {
1024 CONSOLE_ConInKey(Ir);
1025
1026 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1027 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1028 {
1029 if (ConfirmQuit(Ir) == TRUE)
1030 return QUIT_PAGE;
1031
1032 break;
1033 }
1034 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1035 {
1036 return DEVICE_SETTINGS_PAGE;
1037 // return SCSI_CONTROLLER_PAGE;
1038 }
1039 }
1040
1041 return INSTALL_INTRO_PAGE;
1042 }
1043
1044
1045 #if 0
1046 static PAGE_NUMBER
1047 ScsiControllerPage(PINPUT_RECORD Ir)
1048 {
1049 SetTextXY(6, 8, "Setup detected the following mass storage devices:");
1050
1051 /* FIXME: print loaded mass storage driver descriptions */
1052 #if 0
1053 SetTextXY(8, 10, "TEST device");
1054 #endif
1055
1056
1057 SetStatusText(" ENTER = Continue F3 = Quit");
1058
1059 while (TRUE)
1060 {
1061 ConInKey(Ir);
1062
1063 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1064 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1065 {
1066 if (ConfirmQuit(Ir) == TRUE)
1067 return QUIT_PAGE;
1068
1069 break;
1070 }
1071 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1072 {
1073 return DEVICE_SETTINGS_PAGE;
1074 }
1075 }
1076
1077 return SCSI_CONTROLLER_PAGE;
1078 }
1079 #endif
1080
1081
1082 static PAGE_NUMBER
1083 DeviceSettingsPage(PINPUT_RECORD Ir)
1084 {
1085 static ULONG Line = 16;
1086 MUIDisplayPage(DEVICE_SETTINGS_PAGE);
1087
1088 /* Initialize the computer settings list */
1089 if (ComputerList == NULL)
1090 {
1091 ComputerList = CreateComputerTypeList(SetupInf);
1092 if (ComputerList == NULL)
1093 {
1094 MUIDisplayError(ERROR_LOAD_COMPUTER, Ir, POPUP_WAIT_ENTER);
1095 return QUIT_PAGE;
1096 }
1097 }
1098
1099 /* Initialize the display settings list */
1100 if (DisplayList == NULL)
1101 {
1102 DisplayList = CreateDisplayDriverList(SetupInf);
1103 if (DisplayList == NULL)
1104 {
1105 MUIDisplayError(ERROR_LOAD_DISPLAY, Ir, POPUP_WAIT_ENTER);
1106 return QUIT_PAGE;
1107 }
1108 }
1109
1110 /* Initialize the keyboard settings list */
1111 if (KeyboardList == NULL)
1112 {
1113 KeyboardList = CreateKeyboardDriverList(SetupInf);
1114 if (KeyboardList == NULL)
1115 {
1116 MUIDisplayError(ERROR_LOAD_KEYBOARD, Ir, POPUP_WAIT_ENTER);
1117 return QUIT_PAGE;
1118 }
1119 }
1120
1121 /* Initialize the keyboard layout list */
1122 if (LayoutList == NULL)
1123 {
1124 LayoutList = CreateKeyboardLayoutList(SetupInf, DefaultKBLayout);
1125 if (LayoutList == NULL)
1126 {
1127 /* FIXME: report error */
1128 MUIDisplayError(ERROR_LOAD_KBLAYOUT, Ir, POPUP_WAIT_ENTER);
1129 return QUIT_PAGE;
1130 }
1131 }
1132
1133 MUIDisplayPage(DEVICE_SETTINGS_PAGE);
1134
1135
1136 CONSOLE_SetTextXY(25, 11, GetListEntryText(GetCurrentListEntry((ComputerList))));
1137 CONSOLE_SetTextXY(25, 12, GetListEntryText(GetCurrentListEntry((DisplayList))));
1138 CONSOLE_SetTextXY(25, 13, GetListEntryText(GetCurrentListEntry((KeyboardList))));
1139 CONSOLE_SetTextXY(25, 14, GetListEntryText(GetCurrentListEntry((LayoutList))));
1140
1141 CONSOLE_InvertTextXY(24, Line, 48, 1);
1142
1143 if (RepairUpdateFlag)
1144 {
1145 return SELECT_PARTITION_PAGE;
1146 }
1147
1148 while (TRUE)
1149 {
1150 CONSOLE_ConInKey(Ir);
1151
1152 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1153 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1154 {
1155 CONSOLE_NormalTextXY(24, Line, 48, 1);
1156
1157 if (Line == 14)
1158 Line = 16;
1159 else if (Line == 16)
1160 Line = 11;
1161 else
1162 Line++;
1163
1164 CONSOLE_InvertTextXY(24, Line, 48, 1);
1165 }
1166 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1167 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1168 {
1169 CONSOLE_NormalTextXY(24, Line, 48, 1);
1170
1171 if (Line == 11)
1172 Line = 16;
1173 else if (Line == 16)
1174 Line = 14;
1175 else
1176 Line--;
1177
1178 CONSOLE_InvertTextXY(24, Line, 48, 1);
1179 }
1180 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1181 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1182 {
1183 if (ConfirmQuit(Ir) == TRUE)
1184 return QUIT_PAGE;
1185
1186 break;
1187 }
1188 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1189 {
1190 if (Line == 11)
1191 return COMPUTER_SETTINGS_PAGE;
1192 else if (Line == 12)
1193 return DISPLAY_SETTINGS_PAGE;
1194 else if (Line == 13)
1195 return KEYBOARD_SETTINGS_PAGE;
1196 else if (Line == 14)
1197 return LAYOUT_SETTINGS_PAGE;
1198 else if (Line == 16)
1199 return SELECT_PARTITION_PAGE;
1200 }
1201 }
1202
1203 return DEVICE_SETTINGS_PAGE;
1204 }
1205
1206
1207 static PAGE_NUMBER
1208 ComputerSettingsPage(PINPUT_RECORD Ir)
1209 {
1210 MUIDisplayPage(COMPUTER_SETTINGS_PAGE);
1211
1212 DrawGenericList(ComputerList,
1213 2,
1214 18,
1215 xScreen - 3,
1216 yScreen - 3);
1217
1218 SaveGenericListState(ComputerList);
1219
1220 while (TRUE)
1221 {
1222 CONSOLE_ConInKey(Ir);
1223
1224 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1225 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1226 {
1227 ScrollDownGenericList(ComputerList);
1228 }
1229 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1230 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1231 {
1232 ScrollUpGenericList(ComputerList);
1233 }
1234 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1235 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1236 {
1237 if (ConfirmQuit(Ir) == TRUE)
1238 return QUIT_PAGE;
1239
1240 break;
1241 }
1242 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1243 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
1244 {
1245 RestoreGenericListState(ComputerList);
1246 return DEVICE_SETTINGS_PAGE;
1247 }
1248 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1249 {
1250 return DEVICE_SETTINGS_PAGE;
1251 }
1252 }
1253
1254 return COMPUTER_SETTINGS_PAGE;
1255 }
1256
1257
1258 static PAGE_NUMBER
1259 DisplaySettingsPage(PINPUT_RECORD Ir)
1260 {
1261 MUIDisplayPage(DISPLAY_SETTINGS_PAGE);
1262
1263 DrawGenericList(DisplayList,
1264 2,
1265 18,
1266 xScreen - 3,
1267 yScreen - 3);
1268
1269 SaveGenericListState(DisplayList);
1270
1271 while (TRUE)
1272 {
1273 CONSOLE_ConInKey(Ir);
1274
1275 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1276 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1277 {
1278 ScrollDownGenericList(DisplayList);
1279 }
1280 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1281 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1282 {
1283 ScrollUpGenericList(DisplayList);
1284 }
1285 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1286 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1287 {
1288 if (ConfirmQuit(Ir) == TRUE)
1289 {
1290 return QUIT_PAGE;
1291 }
1292
1293 break;
1294 }
1295 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1296 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
1297 {
1298 RestoreGenericListState(DisplayList);
1299 return DEVICE_SETTINGS_PAGE;
1300 }
1301 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1302 {
1303 return DEVICE_SETTINGS_PAGE;
1304 }
1305 }
1306
1307 return DISPLAY_SETTINGS_PAGE;
1308 }
1309
1310
1311 static PAGE_NUMBER
1312 KeyboardSettingsPage(PINPUT_RECORD Ir)
1313 {
1314 MUIDisplayPage(KEYBOARD_SETTINGS_PAGE);
1315
1316 DrawGenericList(KeyboardList,
1317 2,
1318 18,
1319 xScreen - 3,
1320 yScreen - 3);
1321
1322 SaveGenericListState(KeyboardList);
1323
1324 while (TRUE)
1325 {
1326 CONSOLE_ConInKey(Ir);
1327
1328 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1329 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1330 {
1331 ScrollDownGenericList(KeyboardList);
1332 }
1333 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1334 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1335 {
1336 ScrollUpGenericList(KeyboardList);
1337 }
1338 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1339 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1340 {
1341 if (ConfirmQuit(Ir) == TRUE)
1342 return QUIT_PAGE;
1343
1344 break;
1345 }
1346 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1347 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
1348 {
1349 RestoreGenericListState(KeyboardList);
1350 return DEVICE_SETTINGS_PAGE;
1351 }
1352 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1353 {
1354 return DEVICE_SETTINGS_PAGE;
1355 }
1356 }
1357
1358 return KEYBOARD_SETTINGS_PAGE;
1359 }
1360
1361
1362 static PAGE_NUMBER
1363 LayoutSettingsPage(PINPUT_RECORD Ir)
1364 {
1365 MUIDisplayPage(LAYOUT_SETTINGS_PAGE);
1366
1367 DrawGenericList(LayoutList,
1368 2,
1369 18,
1370 xScreen - 3,
1371 yScreen - 3);
1372
1373 SaveGenericListState(LayoutList);
1374
1375 while (TRUE)
1376 {
1377 CONSOLE_ConInKey(Ir);
1378
1379 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1380 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1381 {
1382 ScrollDownGenericList(LayoutList);
1383 }
1384 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1385 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1386 {
1387 ScrollUpGenericList(LayoutList);
1388 }
1389 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1390 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_NEXT)) /* PAGE DOWN */
1391 {
1392 ScrollPageDownGenericList(LayoutList);
1393 }
1394 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1395 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_PRIOR)) /* PAGE UP */
1396 {
1397 ScrollPageUpGenericList(LayoutList);
1398 }
1399 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1400 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1401 {
1402 if (ConfirmQuit(Ir) == TRUE)
1403 return QUIT_PAGE;
1404
1405 break;
1406 }
1407 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1408 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
1409 {
1410 RestoreGenericListState(LayoutList);
1411 return DEVICE_SETTINGS_PAGE;
1412 }
1413 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1414 {
1415 return DEVICE_SETTINGS_PAGE;
1416 }
1417 else if ((Ir->Event.KeyEvent.uChar.AsciiChar > 0x60) && (Ir->Event.KeyEvent.uChar.AsciiChar < 0x7b))
1418 {
1419 /* a-z */
1420 GenericListKeyPress(LayoutList , Ir->Event.KeyEvent.uChar.AsciiChar);
1421 }
1422 }
1423
1424 return LAYOUT_SETTINGS_PAGE;
1425 }
1426
1427
1428 static BOOL
1429 IsDiskSizeValid(PPARTENTRY PartEntry)
1430 {
1431 ULONGLONG size;
1432
1433 size = PartEntry->SectorCount.QuadPart * PartEntry->DiskEntry->BytesPerSector;
1434 size = (size + 524288) / 1048576; /* in MBytes */
1435
1436 if (size < RequiredPartitionDiskSpace)
1437 {
1438 /* partition is too small so ask for another partion */
1439 DPRINT1("Partition is too small (size: %I64u MB), required disk space is %lu MB\n", size, RequiredPartitionDiskSpace);
1440 return FALSE;
1441 }
1442 else
1443 {
1444 return TRUE;
1445 }
1446 }
1447
1448
1449 static PAGE_NUMBER
1450 SelectPartitionPage(PINPUT_RECORD Ir)
1451 {
1452 ULONG Error;
1453
1454 MUIDisplayPage(SELECT_PARTITION_PAGE);
1455
1456 if (PartitionList == NULL)
1457 {
1458 PartitionList = CreatePartitionList(2,
1459 21,
1460 xScreen - 3,
1461 yScreen - 3);
1462 if (PartitionList == NULL)
1463 {
1464 /* FIXME: show an error dialog */
1465 return QUIT_PAGE;
1466 }
1467 else if (IsListEmpty (&PartitionList->DiskListHead))
1468 {
1469 MUIDisplayError(ERROR_NO_HDD, Ir, POPUP_WAIT_ENTER);
1470 return QUIT_PAGE;
1471 }
1472 }
1473
1474 DrawPartitionList(PartitionList);
1475
1476 /* Warn about partitions created by Linux Fdisk */
1477 if (WarnLinuxPartitions == TRUE &&
1478 CheckForLinuxFdiskPartitions(PartitionList) == TRUE)
1479 {
1480 MUIDisplayError(ERROR_WARN_PARTITION, NULL, POPUP_WAIT_NONE);
1481
1482 while (TRUE)
1483 {
1484 CONSOLE_ConInKey(Ir);
1485
1486 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1487 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1488 {
1489 return QUIT_PAGE;
1490 }
1491 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
1492 {
1493 WarnLinuxPartitions = FALSE;
1494 return SELECT_PARTITION_PAGE;
1495 }
1496 }
1497 }
1498
1499 if (IsUnattendedSetup)
1500 {
1501 if (!SelectPartition(PartitionList, UnattendDestinationDiskNumber, UnattendDestinationPartitionNumber))
1502 {
1503 if (AutoPartition)
1504 {
1505 CreatePrimaryPartition(PartitionList,
1506 PartitionList->CurrentPartition->SectorCount.QuadPart,
1507 TRUE);
1508
1509 if (!IsDiskSizeValid(PartitionList->CurrentPartition))
1510 {
1511 MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE, Ir, POPUP_WAIT_ANY_KEY,
1512 RequiredPartitionDiskSpace);
1513 return SELECT_PARTITION_PAGE; /* let the user select another partition */
1514 }
1515
1516 DestinationDriveLetter = (WCHAR)PartitionList->CurrentPartition->DriveLetter;
1517
1518 return SELECT_FILE_SYSTEM_PAGE;
1519 }
1520 }
1521 else
1522 {
1523 if (!IsDiskSizeValid(PartitionList->CurrentPartition))
1524 {
1525 MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE, Ir, POPUP_WAIT_ANY_KEY,
1526 RequiredPartitionDiskSpace);
1527 return SELECT_PARTITION_PAGE; /* let the user select another partition */
1528 }
1529
1530 DestinationDriveLetter = (WCHAR)PartitionList->CurrentPartition->DriveLetter;
1531
1532 return SELECT_FILE_SYSTEM_PAGE;
1533 }
1534 }
1535
1536 while (TRUE)
1537 {
1538 /* Update status text */
1539 if (PartitionList->CurrentPartition == NULL)
1540 {
1541 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATEPARTITION));
1542 }
1543 else if (PartitionList->CurrentPartition->LogicalPartition)
1544 {
1545 if (PartitionList->CurrentPartition->IsPartitioned)
1546 {
1547 CONSOLE_SetStatusText(MUIGetString(STRING_DELETEPARTITION));
1548 }
1549 else
1550 {
1551 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATELOGICAL));
1552 }
1553 }
1554 else
1555 {
1556 if (PartitionList->CurrentPartition->IsPartitioned)
1557 {
1558 if (IsContainerPartition(PartitionList->CurrentPartition->PartitionType))
1559 {
1560 CONSOLE_SetStatusText(MUIGetString(STRING_DELETEPARTITION));
1561 }
1562 else
1563 {
1564 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLDELETEPARTITION));
1565 }
1566 }
1567 else
1568 {
1569 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATEPARTITION));
1570 }
1571 }
1572
1573 CONSOLE_ConInKey(Ir);
1574
1575 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1576 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1577 {
1578 if (ConfirmQuit(Ir) == TRUE)
1579 {
1580 DestroyPartitionList(PartitionList);
1581 PartitionList = NULL;
1582 return QUIT_PAGE;
1583 }
1584
1585 break;
1586 }
1587 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1588 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1589 {
1590 if (ScrollDownPartitionList(PartitionList))
1591 DrawPartitionList(PartitionList);
1592 }
1593 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1594 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1595 {
1596 if (ScrollUpPartitionList(PartitionList))
1597 DrawPartitionList(PartitionList);
1598 }
1599 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
1600 {
1601 if (IsContainerPartition(PartitionList->CurrentPartition->PartitionType))
1602 continue; //return SELECT_PARTITION_PAGE;
1603
1604 if (PartitionList->CurrentPartition == NULL ||
1605 PartitionList->CurrentPartition->IsPartitioned == FALSE)
1606 {
1607 CreatePrimaryPartition(PartitionList,
1608 0ULL,
1609 TRUE);
1610 }
1611
1612 if (!IsDiskSizeValid(PartitionList->CurrentPartition))
1613 {
1614 MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE, Ir, POPUP_WAIT_ANY_KEY,
1615 RequiredPartitionDiskSpace);
1616 return SELECT_PARTITION_PAGE; /* let the user select another partition */
1617 }
1618
1619 DestinationDriveLetter = (WCHAR)PartitionList->CurrentPartition->DriveLetter;
1620
1621 return SELECT_FILE_SYSTEM_PAGE;
1622 }
1623 else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'P') /* P */
1624 {
1625 if (PartitionList->CurrentPartition->LogicalPartition == FALSE)
1626 {
1627 Error = PrimaryPartitionCreationChecks(PartitionList);
1628 if (Error != NOT_AN_ERROR)
1629 {
1630 MUIDisplayError(Error, Ir, POPUP_WAIT_ANY_KEY);
1631 return SELECT_PARTITION_PAGE;
1632 }
1633
1634 return CREATE_PRIMARY_PARTITION_PAGE;
1635 }
1636 }
1637 else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'E') /* E */
1638 {
1639 if (PartitionList->CurrentPartition->LogicalPartition == FALSE)
1640 {
1641 Error = ExtendedPartitionCreationChecks(PartitionList);
1642 if (Error != NOT_AN_ERROR)
1643 {
1644 MUIDisplayError(Error, Ir, POPUP_WAIT_ANY_KEY);
1645 return SELECT_PARTITION_PAGE;
1646 }
1647
1648 return CREATE_EXTENDED_PARTITION_PAGE;
1649 }
1650 }
1651 else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'L') /* L */
1652 {
1653 if (PartitionList->CurrentPartition->LogicalPartition == TRUE)
1654 {
1655 Error = LogicalPartitionCreationChecks(PartitionList);
1656 if (Error != NOT_AN_ERROR)
1657 {
1658 MUIDisplayError(Error, Ir, POPUP_WAIT_ANY_KEY);
1659 return SELECT_PARTITION_PAGE;
1660 }
1661
1662 return CREATE_LOGICAL_PARTITION_PAGE;
1663 }
1664 }
1665 else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'D') /* D */
1666 {
1667 if (PartitionList->CurrentPartition->IsPartitioned == FALSE)
1668 {
1669 MUIDisplayError(ERROR_DELETE_SPACE, Ir, POPUP_WAIT_ANY_KEY);
1670 return SELECT_PARTITION_PAGE;
1671 }
1672
1673 return DELETE_PARTITION_PAGE;
1674 }
1675 }
1676
1677 return SELECT_PARTITION_PAGE;
1678 }
1679
1680
1681 static VOID
1682 DrawInputField(ULONG FieldLength,
1683 SHORT Left,
1684 SHORT Top,
1685 PCHAR FieldContent)
1686 {
1687 CHAR buf[100];
1688 COORD coPos;
1689 DWORD Written;
1690
1691 coPos.X = Left;
1692 coPos.Y = Top;
1693 memset(buf, '_', sizeof(buf));
1694 buf[FieldLength - strlen(FieldContent)] = 0;
1695 strcat(buf, FieldContent);
1696
1697 WriteConsoleOutputCharacterA(StdOutput,
1698 buf,
1699 strlen(buf),
1700 coPos,
1701 &Written);
1702 }
1703
1704
1705 #define PARTITION_SIZE_INPUT_FIELD_LENGTH 6
1706 /* Restriction for MaxSize: pow(10, PARTITION_SIZE_INPUT_FIELD_LENGTH)-1 */
1707 #define PARTITION_MAXSIZE 999999
1708
1709 static VOID
1710 ShowPartitionSizeInputBox(SHORT Left,
1711 SHORT Top,
1712 SHORT Right,
1713 SHORT Bottom,
1714 ULONG MaxSize,
1715 PCHAR InputBuffer,
1716 PBOOLEAN Quit,
1717 PBOOLEAN Cancel)
1718 {
1719 INPUT_RECORD Ir;
1720 COORD coPos;
1721 DWORD Written;
1722 CHAR Buffer[100];
1723 ULONG Index;
1724 CHAR ch;
1725 SHORT iLeft;
1726 SHORT iTop;
1727
1728 if (Quit != NULL)
1729 *Quit = FALSE;
1730
1731 if (Cancel != NULL)
1732 *Cancel = FALSE;
1733
1734 DrawBox(Left, Top, Right - Left + 1, Bottom - Top + 1);
1735
1736 /* Print message */
1737 coPos.X = Left + 2;
1738 coPos.Y = Top + 2;
1739 strcpy(Buffer, MUIGetString(STRING_PARTITIONSIZE));
1740 iLeft = coPos.X + strlen(Buffer) + 1;
1741 iTop = coPos.Y;
1742
1743 WriteConsoleOutputCharacterA(StdOutput,
1744 Buffer,
1745 strlen (Buffer),
1746 coPos,
1747 &Written);
1748
1749 sprintf(Buffer, MUIGetString(STRING_MAXSIZE), MaxSize);
1750 coPos.X = iLeft + PARTITION_SIZE_INPUT_FIELD_LENGTH + 1;
1751 coPos.Y = iTop;
1752 WriteConsoleOutputCharacterA(StdOutput,
1753 Buffer,
1754 strlen (Buffer),
1755 coPos,
1756 &Written);
1757
1758 sprintf(Buffer, "%lu", MaxSize);
1759 Index = strlen(Buffer);
1760 DrawInputField(PARTITION_SIZE_INPUT_FIELD_LENGTH,
1761 iLeft,
1762 iTop,
1763 Buffer);
1764
1765 while (TRUE)
1766 {
1767 CONSOLE_ConInKey(&Ir);
1768
1769 if ((Ir.Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1770 (Ir.Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1771 {
1772 if (Quit != NULL)
1773 *Quit = TRUE;
1774
1775 Buffer[0] = 0;
1776 break;
1777 }
1778 else if (Ir.Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
1779 {
1780 break;
1781 }
1782 else if (Ir.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESCAPE */
1783 {
1784 if (Cancel != NULL)
1785 *Cancel = TRUE;
1786
1787 Buffer[0] = 0;
1788 break;
1789 }
1790 else if ((Ir.Event.KeyEvent.wVirtualKeyCode == VK_BACK) && /* BACKSPACE */
1791 (Index > 0))
1792 {
1793 Index--;
1794 Buffer[Index] = 0;
1795
1796 DrawInputField(PARTITION_SIZE_INPUT_FIELD_LENGTH,
1797 iLeft,
1798 iTop,
1799 Buffer);
1800 }
1801 else if ((Ir.Event.KeyEvent.uChar.AsciiChar != 0x00) &&
1802 (Index < PARTITION_SIZE_INPUT_FIELD_LENGTH))
1803 {
1804 ch = Ir.Event.KeyEvent.uChar.AsciiChar;
1805
1806 if ((ch >= '0') && (ch <= '9'))
1807 {
1808 Buffer[Index] = ch;
1809 Index++;
1810 Buffer[Index] = 0;
1811
1812 DrawInputField(PARTITION_SIZE_INPUT_FIELD_LENGTH,
1813 iLeft,
1814 iTop,
1815 Buffer);
1816 }
1817 }
1818 }
1819
1820 strcpy(InputBuffer, Buffer);
1821 }
1822
1823
1824 static PAGE_NUMBER
1825 CreatePrimaryPartitionPage(PINPUT_RECORD Ir)
1826 {
1827 PDISKENTRY DiskEntry;
1828 PPARTENTRY PartEntry;
1829 BOOLEAN Quit;
1830 BOOLEAN Cancel;
1831 CHAR InputBuffer[50];
1832 ULONG MaxSize;
1833 ULONGLONG PartSize;
1834 ULONGLONG DiskSize;
1835 ULONGLONG SectorCount;
1836 PCHAR Unit;
1837
1838 if (PartitionList == NULL ||
1839 PartitionList->CurrentDisk == NULL ||
1840 PartitionList->CurrentPartition == NULL)
1841 {
1842 /* FIXME: show an error dialog */
1843 return QUIT_PAGE;
1844 }
1845
1846 DiskEntry = PartitionList->CurrentDisk;
1847 PartEntry = PartitionList->CurrentPartition;
1848
1849 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
1850
1851 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSENEWPARTITION));
1852
1853 DiskSize = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
1854 #if 0
1855 if (DiskSize >= 10737418240) /* 10 GB */
1856 {
1857 DiskSize = DiskSize / 1073741824;
1858 Unit = MUIGetString(STRING_GB);
1859 }
1860 else
1861 #endif
1862 {
1863 DiskSize = DiskSize / 1048576;
1864 if (DiskSize == 0)
1865 DiskSize = 1;
1866
1867 Unit = MUIGetString(STRING_MB);
1868 }
1869
1870 if (DiskEntry->DriverName.Length > 0)
1871 {
1872 CONSOLE_PrintTextXY(6, 10,
1873 MUIGetString(STRING_HDINFOPARTCREATE),
1874 DiskSize,
1875 Unit,
1876 DiskEntry->DiskNumber,
1877 DiskEntry->Port,
1878 DiskEntry->Bus,
1879 DiskEntry->Id,
1880 &DiskEntry->DriverName);
1881 }
1882 else
1883 {
1884 CONSOLE_PrintTextXY(6, 10,
1885 MUIGetString(STRING_HDDINFOUNK1),
1886 DiskSize,
1887 Unit,
1888 DiskEntry->DiskNumber,
1889 DiskEntry->Port,
1890 DiskEntry->Bus,
1891 DiskEntry->Id);
1892 }
1893
1894 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE));
1895
1896 #if 0
1897 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
1898 PartitionList->CurrentPartition->SectorCount * DiskEntry->BytesPerSector / 1048576);
1899 #endif
1900
1901 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION));
1902
1903 PartEntry = PartitionList->CurrentPartition;
1904 while (TRUE)
1905 {
1906 MaxSize = (PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector) / 1048576; /* in MBytes (rounded) */
1907
1908 if (MaxSize > PARTITION_MAXSIZE)
1909 MaxSize = PARTITION_MAXSIZE;
1910
1911 ShowPartitionSizeInputBox(12, 14, xScreen - 12, 17, /* left, top, right, bottom */
1912 MaxSize, InputBuffer, &Quit, &Cancel);
1913
1914 if (Quit == TRUE)
1915 {
1916 if (ConfirmQuit (Ir) == TRUE)
1917 {
1918 return QUIT_PAGE;
1919 }
1920 }
1921 else if (Cancel == TRUE)
1922 {
1923 return SELECT_PARTITION_PAGE;
1924 }
1925 else
1926 {
1927 PartSize = atoi(InputBuffer);
1928
1929 if (PartSize < 1)
1930 {
1931 /* Too small */
1932 continue;
1933 }
1934
1935 if (PartSize > MaxSize)
1936 {
1937 /* Too large */
1938 continue;
1939 }
1940
1941 /* Convert to bytes */
1942 if (PartSize == MaxSize)
1943 {
1944 /* Use all of the unpartitioned disk space */
1945 SectorCount = PartEntry->SectorCount.QuadPart;
1946 }
1947 else
1948 {
1949 /* Calculate the sector count from the size in MB */
1950 SectorCount = PartSize * 1048576 / DiskEntry->BytesPerSector;
1951
1952 /* But never get larger than the unpartitioned disk space */
1953 if (SectorCount > PartEntry->SectorCount.QuadPart)
1954 SectorCount = PartEntry->SectorCount.QuadPart;
1955 }
1956
1957 DPRINT ("Partition size: %I64u bytes\n", PartSize);
1958
1959 CreatePrimaryPartition(PartitionList,
1960 SectorCount,
1961 FALSE);
1962
1963 return SELECT_PARTITION_PAGE;
1964 }
1965 }
1966
1967 return CREATE_PRIMARY_PARTITION_PAGE;
1968 }
1969
1970
1971 static PAGE_NUMBER
1972 CreateExtendedPartitionPage(PINPUT_RECORD Ir)
1973 {
1974 PDISKENTRY DiskEntry;
1975 PPARTENTRY PartEntry;
1976 BOOLEAN Quit;
1977 BOOLEAN Cancel;
1978 CHAR InputBuffer[50];
1979 ULONG MaxSize;
1980 ULONGLONG PartSize;
1981 ULONGLONG DiskSize;
1982 ULONGLONG SectorCount;
1983 PCHAR Unit;
1984
1985 if (PartitionList == NULL ||
1986 PartitionList->CurrentDisk == NULL ||
1987 PartitionList->CurrentPartition == NULL)
1988 {
1989 /* FIXME: show an error dialog */
1990 return QUIT_PAGE;
1991 }
1992
1993 DiskEntry = PartitionList->CurrentDisk;
1994 PartEntry = PartitionList->CurrentPartition;
1995
1996 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
1997
1998 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSE_NEW_EXTENDED_PARTITION));
1999
2000 DiskSize = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
2001 #if 0
2002 if (DiskSize >= 10737418240) /* 10 GB */
2003 {
2004 DiskSize = DiskSize / 1073741824;
2005 Unit = MUIGetString(STRING_GB);
2006 }
2007 else
2008 #endif
2009 {
2010 DiskSize = DiskSize / 1048576;
2011 if (DiskSize == 0)
2012 DiskSize = 1;
2013
2014 Unit = MUIGetString(STRING_MB);
2015 }
2016
2017 if (DiskEntry->DriverName.Length > 0)
2018 {
2019 CONSOLE_PrintTextXY(6, 10,
2020 MUIGetString(STRING_HDINFOPARTCREATE),
2021 DiskSize,
2022 Unit,
2023 DiskEntry->DiskNumber,
2024 DiskEntry->Port,
2025 DiskEntry->Bus,
2026 DiskEntry->Id,
2027 &DiskEntry->DriverName);
2028 }
2029 else
2030 {
2031 CONSOLE_PrintTextXY(6, 10,
2032 MUIGetString(STRING_HDDINFOUNK1),
2033 DiskSize,
2034 Unit,
2035 DiskEntry->DiskNumber,
2036 DiskEntry->Port,
2037 DiskEntry->Bus,
2038 DiskEntry->Id);
2039 }
2040
2041 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE));
2042
2043 #if 0
2044 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2045 PartitionList->CurrentPartition->SectorCount * DiskEntry->BytesPerSector / 1048576);
2046 #endif
2047
2048 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION));
2049
2050 PartEntry = PartitionList->CurrentPartition;
2051 while (TRUE)
2052 {
2053 MaxSize = (PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector) / 1048576; /* in MBytes (rounded) */
2054
2055 if (MaxSize > PARTITION_MAXSIZE)
2056 MaxSize = PARTITION_MAXSIZE;
2057
2058 ShowPartitionSizeInputBox(12, 14, xScreen - 12, 17, /* left, top, right, bottom */
2059 MaxSize, InputBuffer, &Quit, &Cancel);
2060
2061 if (Quit == TRUE)
2062 {
2063 if (ConfirmQuit (Ir) == TRUE)
2064 {
2065 return QUIT_PAGE;
2066 }
2067 }
2068 else if (Cancel == TRUE)
2069 {
2070 return SELECT_PARTITION_PAGE;
2071 }
2072 else
2073 {
2074 PartSize = atoi(InputBuffer);
2075
2076 if (PartSize < 1)
2077 {
2078 /* Too small */
2079 continue;
2080 }
2081
2082 if (PartSize > MaxSize)
2083 {
2084 /* Too large */
2085 continue;
2086 }
2087
2088 /* Convert to bytes */
2089 if (PartSize == MaxSize)
2090 {
2091 /* Use all of the unpartitioned disk space */
2092 SectorCount = PartEntry->SectorCount.QuadPart;
2093 }
2094 else
2095 {
2096 /* Calculate the sector count from the size in MB */
2097 SectorCount = PartSize * 1048576 / DiskEntry->BytesPerSector;
2098
2099 /* But never get larger than the unpartitioned disk space */
2100 if (SectorCount > PartEntry->SectorCount.QuadPart)
2101 SectorCount = PartEntry->SectorCount.QuadPart;
2102 }
2103
2104 DPRINT ("Partition size: %I64u bytes\n", PartSize);
2105
2106 CreateExtendedPartition(PartitionList,
2107 SectorCount);
2108
2109 return SELECT_PARTITION_PAGE;
2110 }
2111 }
2112
2113 return CREATE_EXTENDED_PARTITION_PAGE;
2114 }
2115
2116
2117 static PAGE_NUMBER
2118 CreateLogicalPartitionPage(PINPUT_RECORD Ir)
2119 {
2120 PDISKENTRY DiskEntry;
2121 PPARTENTRY PartEntry;
2122 BOOLEAN Quit;
2123 BOOLEAN Cancel;
2124 CHAR InputBuffer[50];
2125 ULONG MaxSize;
2126 ULONGLONG PartSize;
2127 ULONGLONG DiskSize;
2128 ULONGLONG SectorCount;
2129 PCHAR Unit;
2130
2131 if (PartitionList == NULL ||
2132 PartitionList->CurrentDisk == NULL ||
2133 PartitionList->CurrentPartition == NULL)
2134 {
2135 /* FIXME: show an error dialog */
2136 return QUIT_PAGE;
2137 }
2138
2139 DiskEntry = PartitionList->CurrentDisk;
2140 PartEntry = PartitionList->CurrentPartition;
2141
2142 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
2143
2144 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSE_NEW_LOGICAL_PARTITION));
2145
2146 DiskSize = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
2147 #if 0
2148 if (DiskSize >= 10737418240) /* 10 GB */
2149 {
2150 DiskSize = DiskSize / 1073741824;
2151 Unit = MUIGetString(STRING_GB);
2152 }
2153 else
2154 #endif
2155 {
2156 DiskSize = DiskSize / 1048576;
2157 if (DiskSize == 0)
2158 DiskSize = 1;
2159
2160 Unit = MUIGetString(STRING_MB);
2161 }
2162
2163 if (DiskEntry->DriverName.Length > 0)
2164 {
2165 CONSOLE_PrintTextXY(6, 10,
2166 MUIGetString(STRING_HDINFOPARTCREATE),
2167 DiskSize,
2168 Unit,
2169 DiskEntry->DiskNumber,
2170 DiskEntry->Port,
2171 DiskEntry->Bus,
2172 DiskEntry->Id,
2173 &DiskEntry->DriverName);
2174 }
2175 else
2176 {
2177 CONSOLE_PrintTextXY(6, 10,
2178 MUIGetString(STRING_HDDINFOUNK1),
2179 DiskSize,
2180 Unit,
2181 DiskEntry->DiskNumber,
2182 DiskEntry->Port,
2183 DiskEntry->Bus,
2184 DiskEntry->Id);
2185 }
2186
2187 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE));
2188
2189 #if 0
2190 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2191 PartitionList->CurrentPartition->SectorCount * DiskEntry->BytesPerSector / 1048576);
2192 #endif
2193
2194 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION));
2195
2196 PartEntry = PartitionList->CurrentPartition;
2197 while (TRUE)
2198 {
2199 MaxSize = (PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector) / 1048576; /* in MBytes (rounded) */
2200
2201 if (MaxSize > PARTITION_MAXSIZE)
2202 MaxSize = PARTITION_MAXSIZE;
2203
2204 ShowPartitionSizeInputBox(12, 14, xScreen - 12, 17, /* left, top, right, bottom */
2205 MaxSize, InputBuffer, &Quit, &Cancel);
2206
2207 if (Quit == TRUE)
2208 {
2209 if (ConfirmQuit (Ir) == TRUE)
2210 {
2211 return QUIT_PAGE;
2212 }
2213 }
2214 else if (Cancel == TRUE)
2215 {
2216 return SELECT_PARTITION_PAGE;
2217 }
2218 else
2219 {
2220 PartSize = atoi(InputBuffer);
2221
2222 if (PartSize < 1)
2223 {
2224 /* Too small */
2225 continue;
2226 }
2227
2228 if (PartSize > MaxSize)
2229 {
2230 /* Too large */
2231 continue;
2232 }
2233
2234 /* Convert to bytes */
2235 if (PartSize == MaxSize)
2236 {
2237 /* Use all of the unpartitioned disk space */
2238 SectorCount = PartEntry->SectorCount.QuadPart;
2239 }
2240 else
2241 {
2242 /* Calculate the sector count from the size in MB */
2243 SectorCount = PartSize * 1048576 / DiskEntry->BytesPerSector;
2244
2245 /* But never get larger than the unpartitioned disk space */
2246 if (SectorCount > PartEntry->SectorCount.QuadPart)
2247 SectorCount = PartEntry->SectorCount.QuadPart;
2248 }
2249
2250 DPRINT("Partition size: %I64u bytes\n", PartSize);
2251
2252 CreateLogicalPartition(PartitionList,
2253 SectorCount);
2254
2255 return SELECT_PARTITION_PAGE;
2256 }
2257 }
2258
2259 return CREATE_LOGICAL_PARTITION_PAGE;
2260 }
2261
2262
2263 static PAGE_NUMBER
2264 DeletePartitionPage(PINPUT_RECORD Ir)
2265 {
2266 PDISKENTRY DiskEntry;
2267 PPARTENTRY PartEntry;
2268 ULONGLONG DiskSize;
2269 ULONGLONG PartSize;
2270 PCHAR Unit;
2271 PCHAR PartType;
2272
2273 if (PartitionList == NULL ||
2274 PartitionList->CurrentDisk == NULL ||
2275 PartitionList->CurrentPartition == NULL)
2276 {
2277 /* FIXME: show an error dialog */
2278 return QUIT_PAGE;
2279 }
2280
2281 DiskEntry = PartitionList->CurrentDisk;
2282 PartEntry = PartitionList->CurrentPartition;
2283
2284 MUIDisplayPage(DELETE_PARTITION_PAGE);
2285
2286 /* Determine partition type */
2287 PartType = NULL;
2288 if (PartEntry->New == TRUE)
2289 {
2290 PartType = MUIGetString(STRING_UNFORMATTED);
2291 }
2292 else if (PartEntry->IsPartitioned == TRUE)
2293 {
2294 if ((PartEntry->PartitionType == PARTITION_FAT_12) ||
2295 (PartEntry->PartitionType == PARTITION_FAT_16) ||
2296 (PartEntry->PartitionType == PARTITION_HUGE) ||
2297 (PartEntry->PartitionType == PARTITION_XINT13))
2298 {
2299 PartType = "FAT";
2300 }
2301 else if ((PartEntry->PartitionType == PARTITION_FAT32) ||
2302 (PartEntry->PartitionType == PARTITION_FAT32_XINT13))
2303 {
2304 PartType = "FAT32";
2305 }
2306 else if (PartEntry->PartitionType == PARTITION_EXT2)
2307 {
2308 PartType = "EXT2";
2309 }
2310 else if (PartEntry->PartitionType == PARTITION_IFS)
2311 {
2312 PartType = "NTFS"; /* FIXME: Not quite correct! */
2313 }
2314 else if (IsContainerPartition(PartEntry->PartitionType))
2315 {
2316 PartType = MUIGetString(STRING_EXTENDED_PARTITION);
2317 }
2318 }
2319
2320 PartSize = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
2321 #if 0
2322 if (PartSize >= 10737418240) /* 10 GB */
2323 {
2324 PartSize = PartSize / 1073741824;
2325 Unit = MUIGetString(STRING_GB);
2326 }
2327 else
2328 #endif
2329 if (PartSize >= 10485760) /* 10 MB */
2330 {
2331 PartSize = PartSize / 1048576;
2332 Unit = MUIGetString(STRING_MB);
2333 }
2334 else
2335 {
2336 PartSize = PartSize / 1024;
2337 Unit = MUIGetString(STRING_KB);
2338 }
2339
2340 if (PartType == NULL)
2341 {
2342 CONSOLE_PrintTextXY(6, 10,
2343 MUIGetString(STRING_HDDINFOUNK2),
2344 (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
2345 (PartEntry->DriveLetter == 0) ? '-' : ':',
2346 PartEntry->PartitionType,
2347 PartSize,
2348 Unit);
2349 }
2350 else
2351 {
2352 CONSOLE_PrintTextXY(6, 10,
2353 " %c%c %s %I64u %s",
2354 (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
2355 (PartEntry->DriveLetter == 0) ? '-' : ':',
2356 PartType,
2357 PartSize,
2358 Unit);
2359 }
2360
2361 DiskSize = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
2362 #if 0
2363 if (DiskSize >= 10737418240) /* 10 GB */
2364 {
2365 DiskSize = DiskSize / 1073741824;
2366 Unit = MUIGetString(STRING_GB);
2367 }
2368 else
2369 #endif
2370 {
2371 DiskSize = DiskSize / 1048576;
2372 if (DiskSize == 0)
2373 DiskSize = 1;
2374
2375 Unit = MUIGetString(STRING_MB);
2376 }
2377
2378 if (DiskEntry->DriverName.Length > 0)
2379 {
2380 CONSOLE_PrintTextXY(6, 12,
2381 MUIGetString(STRING_HDINFOPARTDELETE),
2382 DiskSize,
2383 Unit,
2384 DiskEntry->DiskNumber,
2385 DiskEntry->Port,
2386 DiskEntry->Bus,
2387 DiskEntry->Id,
2388 &DiskEntry->DriverName);
2389 }
2390 else
2391 {
2392 CONSOLE_PrintTextXY(6, 12,
2393 MUIGetString(STRING_HDDINFOUNK3),
2394 DiskSize,
2395 Unit,
2396 DiskEntry->DiskNumber,
2397 DiskEntry->Port,
2398 DiskEntry->Bus,
2399 DiskEntry->Id);
2400 }
2401
2402 while (TRUE)
2403 {
2404 CONSOLE_ConInKey(Ir);
2405
2406 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2407 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
2408 {
2409 if (ConfirmQuit(Ir) == TRUE)
2410 {
2411 return QUIT_PAGE;
2412 }
2413
2414 break;
2415 }
2416 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESC */
2417 {
2418 return SELECT_PARTITION_PAGE;
2419 }
2420 else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'D') /* D */
2421 {
2422 DeleteCurrentPartition(PartitionList);
2423
2424 return SELECT_PARTITION_PAGE;
2425 }
2426 }
2427
2428 return DELETE_PARTITION_PAGE;
2429 }
2430
2431
2432 static PAGE_NUMBER
2433 SelectFileSystemPage(PINPUT_RECORD Ir)
2434 {
2435 PDISKENTRY DiskEntry;
2436 PPARTENTRY PartEntry;
2437 ULONGLONG DiskSize;
2438 ULONGLONG PartSize;
2439 PCHAR DiskUnit;
2440 PCHAR PartUnit;
2441 PCHAR PartType;
2442
2443 if (PartitionList == NULL ||
2444 PartitionList->CurrentDisk == NULL ||
2445 PartitionList->CurrentPartition == NULL)
2446 {
2447 /* FIXME: show an error dialog */
2448 return QUIT_PAGE;
2449 }
2450
2451 DiskEntry = PartitionList->CurrentDisk;
2452 PartEntry = PartitionList->CurrentPartition;
2453
2454 /* adjust disk size */
2455 DiskSize = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
2456 if (DiskSize >= 10737418240) /* 10 GB */
2457 {
2458 DiskSize = DiskSize / 1073741824;
2459 DiskUnit = MUIGetString(STRING_GB);
2460 }
2461 else
2462 {
2463 DiskSize = DiskSize / 1048576;
2464 DiskUnit = MUIGetString(STRING_MB);
2465 }
2466
2467 /* adjust partition size */
2468 PartSize = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
2469 if (PartSize >= 10737418240) /* 10 GB */
2470 {
2471 PartSize = PartSize / 1073741824;
2472 PartUnit = MUIGetString(STRING_GB);
2473 }
2474 else
2475 {
2476 PartSize = PartSize / 1048576;
2477 PartUnit = MUIGetString(STRING_MB);
2478 }
2479
2480 /* adjust partition type */
2481 if ((PartEntry->PartitionType == PARTITION_FAT_12) ||
2482 (PartEntry->PartitionType == PARTITION_FAT_16) ||
2483 (PartEntry->PartitionType == PARTITION_HUGE) ||
2484 (PartEntry->PartitionType == PARTITION_XINT13))
2485 {
2486 PartType = "FAT";
2487 }
2488 else if ((PartEntry->PartitionType == PARTITION_FAT32) ||
2489 (PartEntry->PartitionType == PARTITION_FAT32_XINT13))
2490 {
2491 PartType = "FAT32";
2492 }
2493 else if (PartEntry->PartitionType == PARTITION_EXT2)
2494 {
2495 PartType = "EXT2";
2496 }
2497 else if (PartEntry->PartitionType == PARTITION_IFS)
2498 {
2499 PartType = "NTFS"; /* FIXME: Not quite correct! */
2500 }
2501 else if (PartEntry->PartitionType == PARTITION_ENTRY_UNUSED)
2502 {
2503 PartType = MUIGetString(STRING_FORMATUNUSED);
2504 }
2505 else
2506 {
2507 PartType = MUIGetString(STRING_FORMATUNKNOWN);
2508 }
2509
2510 if (PartEntry->AutoCreate == TRUE)
2511 {
2512 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NEWPARTITION));
2513
2514 #if 0
2515 CONSOLE_PrintTextXY(8, 10, "Partition %lu (%I64u %s) %s of",
2516 PartEntry->PartitionNumber,
2517 PartSize,
2518 PartUnit,
2519 PartType);
2520 #endif
2521
2522 CONSOLE_PrintTextXY(8, 10, MUIGetString(STRING_HDINFOPARTZEROED),
2523 DiskEntry->DiskNumber,
2524 DiskSize,
2525 DiskUnit,
2526 DiskEntry->Port,
2527 DiskEntry->Bus,
2528 DiskEntry->Id,
2529 &DiskEntry->DriverName);
2530
2531 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_PARTFORMAT));
2532
2533
2534 PartEntry->AutoCreate = FALSE;
2535 }
2536 else if (PartEntry->New == TRUE)
2537 {
2538 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDPART));
2539 CONSOLE_SetTextXY(6, 10, MUIGetString(STRING_PARTFORMAT));
2540 }
2541 else
2542 {
2543 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_INSTALLONPART));
2544
2545 if (PartType == NULL)
2546 {
2547 CONSOLE_PrintTextXY(8, 10,
2548 MUIGetString(STRING_HDDINFOUNK4),
2549 (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
2550 (PartEntry->DriveLetter == 0) ? '-' : ':',
2551 PartEntry->PartitionType,
2552 PartSize,
2553 PartUnit);
2554 }
2555 else
2556 {
2557 CONSOLE_PrintTextXY(8, 10,
2558 "%c%c %s %I64u %s",
2559 (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
2560 (PartEntry->DriveLetter == 0) ? '-' : ':',
2561 PartType,
2562 PartSize,
2563 PartUnit);
2564 }
2565
2566 CONSOLE_PrintTextXY(6, 12, MUIGetString(STRING_HDINFOPARTEXISTS),
2567 DiskEntry->DiskNumber,
2568 DiskSize,
2569 DiskUnit,
2570 DiskEntry->Port,
2571 DiskEntry->Bus,
2572 DiskEntry->Id,
2573 &DiskEntry->DriverName);
2574 }
2575
2576 MUIDisplayPage(SELECT_FILE_SYSTEM_PAGE);
2577
2578 if (FileSystemList == NULL)
2579 {
2580 FileSystemList = CreateFileSystemList(6, 26, PartEntry->New, L"FAT");
2581 if (FileSystemList == NULL)
2582 {
2583 /* FIXME: show an error dialog */
2584 return QUIT_PAGE;
2585 }
2586
2587 /* FIXME: Add file systems to list */
2588 }
2589
2590 DrawFileSystemList(FileSystemList);
2591
2592 if (RepairUpdateFlag)
2593 {
2594 return CHECK_FILE_SYSTEM_PAGE;
2595 //return SELECT_PARTITION_PAGE;
2596 }
2597
2598 if (IsUnattendedSetup)
2599 {
2600 if (UnattendFormatPartition)
2601 {
2602 return FORMAT_PARTITION_PAGE;
2603 }
2604
2605 return CHECK_FILE_SYSTEM_PAGE;
2606 }
2607
2608 while (TRUE)
2609 {
2610 CONSOLE_ConInKey(Ir);
2611
2612 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2613 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
2614 {
2615 if (ConfirmQuit(Ir) == TRUE)
2616 {
2617 return QUIT_PAGE;
2618 }
2619
2620 break;
2621 }
2622 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2623 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
2624 {
2625 return SELECT_PARTITION_PAGE;
2626 }
2627 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2628 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
2629 {
2630 ScrollDownFileSystemList(FileSystemList);
2631 }
2632 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2633 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
2634 {
2635 ScrollUpFileSystemList(FileSystemList);
2636 }
2637 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
2638 {
2639 if (!FileSystemList->Selected->FormatFunc)
2640 {
2641 return CHECK_FILE_SYSTEM_PAGE;
2642 }
2643 else
2644 {
2645 return FORMAT_PARTITION_PAGE;
2646 }
2647 }
2648 }
2649
2650 return SELECT_FILE_SYSTEM_PAGE;
2651 }
2652
2653
2654 static ULONG
2655 FormatPartitionPage(PINPUT_RECORD Ir)
2656 {
2657 WCHAR PathBuffer[MAX_PATH];
2658 PDISKENTRY DiskEntry;
2659 PPARTENTRY PartEntry;
2660 NTSTATUS Status;
2661
2662 #ifndef NDEBUG
2663 ULONG Line;
2664 ULONG i;
2665 PLIST_ENTRY Entry;
2666 #endif
2667
2668 MUIDisplayPage(FORMAT_PARTITION_PAGE);
2669
2670 if (PartitionList == NULL ||
2671 PartitionList->CurrentDisk == NULL ||
2672 PartitionList->CurrentPartition == NULL)
2673 {
2674 /* FIXME: show an error dialog */
2675 return QUIT_PAGE;
2676 }
2677
2678 DiskEntry = PartitionList->CurrentDisk;
2679 PartEntry = PartitionList->CurrentPartition;
2680
2681 while (TRUE)
2682 {
2683 if (!IsUnattendedSetup)
2684 {
2685 CONSOLE_ConInKey(Ir);
2686 }
2687
2688 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2689 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
2690 {
2691 if (ConfirmQuit(Ir) == TRUE)
2692 {
2693 return QUIT_PAGE;
2694 }
2695
2696 break;
2697 }
2698 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN || IsUnattendedSetup) /* ENTER */
2699 {
2700 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
2701
2702 if (wcscmp(FileSystemList->Selected->FileSystem, L"FAT") == 0)
2703 {
2704 if (PartEntry->SectorCount.QuadPart < 8192)
2705 {
2706 /* FAT12 CHS partition (disk is smaller than 4.1MB) */
2707 PartEntry->PartitionType = PARTITION_FAT_12;
2708 }
2709 else if (PartEntry->StartSector.QuadPart < 1450560)
2710 {
2711 /* Partition starts below the 8.4GB boundary ==> CHS partition */
2712
2713 if (PartEntry->SectorCount.QuadPart < 65536)
2714 {
2715 /* FAT16 CHS partition (partiton size < 32MB) */
2716 PartEntry->PartitionType = PARTITION_FAT_16;
2717 }
2718 else if (PartEntry->SectorCount.QuadPart < 1048576)
2719 {
2720 /* FAT16 CHS partition (partition size < 512MB) */
2721 PartEntry->PartitionType = PARTITION_HUGE;
2722 }
2723 else
2724 {
2725 /* FAT32 CHS partition (partition size >= 512MB) */
2726 PartEntry->PartitionType = PARTITION_FAT32;
2727 }
2728 }
2729 else
2730 {
2731 /* Partition starts above the 8.4GB boundary ==> LBA partition */
2732
2733 if (PartEntry->SectorCount.QuadPart < 1048576)
2734 {
2735 /* FAT16 LBA partition (partition size < 512MB) */
2736 PartEntry->PartitionType = PARTITION_XINT13;
2737 }
2738 else
2739 {
2740 /* FAT32 LBA partition (partition size >= 512MB) */
2741 PartEntry->PartitionType = PARTITION_FAT32_XINT13;
2742 }
2743 }
2744
2745 DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].PartitionType = PartEntry->PartitionType;
2746 }
2747 #if 0
2748 else if (wcscmp(FileSystemList->Selected->FileSystem, L"EXT2") == 0)
2749 {
2750 PartEntry->PartitionType = PARTITION_EXT2;
2751 DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].PartitionType = PartEntry->PartitionType;
2752 }
2753 #endif
2754 else if (!FileSystemList->Selected->FormatFunc)
2755 return QUIT_PAGE;
2756
2757 #ifndef NDEBUG
2758 CONSOLE_PrintTextXY(6, 12,
2759 "Disk: %I64u Cylinder: %I64u Track: %I64u",
2760 DiskEntry->DiskSize,
2761 DiskEntry->CylinderSize,
2762 DiskEntry->TrackSize);
2763
2764 Line = 13;
2765 DiskEntry = PartitionList->CurrentDisk;
2766 Entry = DiskEntry->PartListHead.Flink;
2767
2768 while (Entry != &DiskEntry->PrimaryPartListHead)
2769 {
2770 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
2771
2772 if (PartEntry->IsPartitioned == TRUE)
2773 {
2774 CONSOLE_PrintTextXY(6, Line,
2775 "%2u: %2u %c %12I64u %12I64u %2u %c",
2776 i,
2777 PartEntry->PartitionNumber,
2778 PartEntry->BootIndicator ? 'A' : '-',
2779 PartEntry->StartSector.QuadPart,
2780 PartEntry->SectorCount.QuadPart,
2781 PartEntry->PartitionType,
2782 PartEntry->Dirty ? '*' : ' ');
2783 Line++;
2784 }
2785
2786 Entry = Entry->Flink;
2787 }
2788
2789 /* Restore the old entry */
2790 PartEntry = PartitionList->CurrentPartition;
2791 #endif
2792
2793 CheckActiveBootPartition(PartitionList);
2794
2795 if (WritePartitionsToDisk(PartitionList) == FALSE)
2796 {
2797 DPRINT("WritePartitionsToDisk() failed\n");
2798 MUIDisplayError(ERROR_WRITE_PTABLE, Ir, POPUP_WAIT_ENTER);
2799 return QUIT_PAGE;
2800 }
2801
2802 /* Set DestinationRootPath */
2803 RtlFreeUnicodeString(&DestinationRootPath);
2804 swprintf(PathBuffer,
2805 L"\\Device\\Harddisk%lu\\Partition%lu",
2806 PartitionList->CurrentDisk->DiskNumber,
2807 PartitionList->CurrentPartition->PartitionNumber);
2808 RtlCreateUnicodeString(&DestinationRootPath,
2809 PathBuffer);
2810 DPRINT("DestinationRootPath: %wZ\n", &DestinationRootPath);
2811
2812 if (FileSystemList->Selected->FormatFunc)
2813 {
2814 Status = FormatPartition(&DestinationRootPath,
2815 FileSystemList->Selected);
2816 if (!NT_SUCCESS(Status))
2817 {
2818 DPRINT1("FormatPartition() failed with status 0x%08lx\n", Status);
2819 /* FIXME: show an error dialog */
2820 return QUIT_PAGE;
2821 }
2822
2823 PartEntry->New = FALSE;
2824
2825 }
2826
2827 #ifndef NDEBUG
2828 CONSOLE_SetStatusText(" Done. Press any key ...");
2829 CONSOLE_ConInKey(Ir);
2830 #endif
2831
2832 DestroyFileSystemList(FileSystemList);
2833 FileSystemList = NULL;
2834 return INSTALL_DIRECTORY_PAGE;
2835 }
2836 }
2837
2838 return FORMAT_PARTITION_PAGE;
2839 }
2840
2841
2842 static ULONG
2843 CheckFileSystemPage(PINPUT_RECORD Ir)
2844 {
2845 PFILE_SYSTEM_ITEM CurrentFileSystem;
2846 WCHAR PathBuffer[MAX_PATH];
2847 CHAR Buffer[MAX_PATH];
2848 NTSTATUS Status;
2849
2850 /* FIXME: code duplicated in FormatPartitionPage */
2851 /* Set DestinationRootPath */
2852 RtlFreeUnicodeString(&DestinationRootPath);
2853 swprintf(PathBuffer,
2854 L"\\Device\\Harddisk%lu\\Partition%lu",
2855 PartitionList->CurrentDisk->DiskNumber,
2856 PartitionList->CurrentPartition->PartitionNumber);
2857 RtlCreateUnicodeString(&DestinationRootPath, PathBuffer);
2858 DPRINT("DestinationRootPath: %wZ\n", &DestinationRootPath);
2859
2860 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHECKINGPART));
2861
2862 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
2863
2864 /* WRONG: first filesystem is not necesseraly the one of the current partition! */
2865 CurrentFileSystem = CONTAINING_RECORD(FileSystemList->ListHead.Flink, FILE_SYSTEM_ITEM, ListEntry);
2866
2867 if (!CurrentFileSystem->ChkdskFunc)
2868 {
2869 sprintf(Buffer,
2870 "Setup is currently unable to check a partition formatted in %S.\n"
2871 "\n"
2872 " \x07 Press ENTER to continue Setup.\n"
2873 " \x07 Press F3 to quit Setup.",
2874 CurrentFileSystem->FileSystem);
2875
2876 PopupError(Buffer,
2877 MUIGetString(STRING_QUITCONTINUE),
2878 NULL, POPUP_WAIT_NONE);
2879
2880 while (TRUE)
2881 {
2882 CONSOLE_ConInKey(Ir);
2883
2884 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x00 &&
2885 Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3) /* F3 */
2886 {
2887 if (ConfirmQuit(Ir))
2888 return QUIT_PAGE;
2889 else
2890 return CHECK_FILE_SYSTEM_PAGE;
2891 }
2892 else if (Ir->Event.KeyEvent.uChar.AsciiChar == VK_RETURN) /* ENTER */
2893 {
2894 return INSTALL_DIRECTORY_PAGE;
2895 }
2896 }
2897 }
2898 else
2899 {
2900 Status = ChkdskPartition(&DestinationRootPath, CurrentFileSystem);
2901 if (!NT_SUCCESS(Status))
2902 {
2903 DPRINT("ChkdskPartition() failed with status 0x%08lx\n", Status);
2904 sprintf(Buffer, "Setup failed to verify the selected partition.\n"
2905 "(Status 0x%08lx).\n", Status);
2906
2907 PopupError(Buffer,
2908 MUIGetString(STRING_REBOOTCOMPUTER),
2909 Ir, POPUP_WAIT_ENTER);
2910
2911 return QUIT_PAGE;
2912 }
2913
2914 return INSTALL_DIRECTORY_PAGE;
2915 }
2916 }
2917
2918
2919 static PAGE_NUMBER
2920 InstallDirectoryPage1(PWCHAR InstallDir,
2921 PDISKENTRY DiskEntry,
2922 PPARTENTRY PartEntry)
2923 {
2924 WCHAR PathBuffer[MAX_PATH];
2925
2926 /* Create 'InstallPath' string */
2927 RtlFreeUnicodeString(&InstallPath);
2928 RtlCreateUnicodeString(&InstallPath,
2929 InstallDir);
2930
2931 /* Create 'DestinationPath' string */
2932 RtlFreeUnicodeString(&DestinationPath);
2933 wcscpy(PathBuffer, DestinationRootPath.Buffer);
2934
2935 if (InstallDir[0] != L'\\')
2936 wcscat(PathBuffer, L"\\");
2937
2938 wcscat(PathBuffer, InstallDir);
2939 RtlCreateUnicodeString(&DestinationPath, PathBuffer);
2940
2941 /* Create 'DestinationArcPath' */
2942 RtlFreeUnicodeString(&DestinationArcPath);
2943 swprintf(PathBuffer,
2944 L"multi(0)disk(0)rdisk(%lu)partition(%lu)",
2945 DiskEntry->BiosDiskNumber,
2946 PartEntry->PartitionNumber);
2947
2948 if (InstallDir[0] != L'\\')
2949 wcscat(PathBuffer, L"\\");
2950
2951 wcscat(PathBuffer, InstallDir);
2952 RtlCreateUnicodeString(&DestinationArcPath, PathBuffer);
2953
2954 return PREPARE_COPY_PAGE;
2955 }
2956
2957
2958 static PAGE_NUMBER
2959 InstallDirectoryPage(PINPUT_RECORD Ir)
2960 {
2961 PDISKENTRY DiskEntry;
2962 PPARTENTRY PartEntry;
2963 WCHAR InstallDir[51];
2964 ULONG Length;
2965
2966 if (PartitionList == NULL ||
2967 PartitionList->CurrentDisk == NULL ||
2968 PartitionList->CurrentPartition == NULL)
2969 {
2970 /* FIXME: show an error dialog */
2971 return QUIT_PAGE;
2972 }
2973
2974 DiskEntry = PartitionList->CurrentDisk;
2975 PartEntry = PartitionList->CurrentPartition;
2976
2977 if (IsUnattendedSetup)
2978 wcscpy(InstallDir, UnattendInstallationDirectory);
2979 else
2980 wcscpy(InstallDir, L"\\ReactOS");
2981
2982 Length = wcslen(InstallDir);
2983 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
2984 MUIDisplayPage(INSTALL_DIRECTORY_PAGE);
2985
2986 if (IsUnattendedSetup)
2987 {
2988 return InstallDirectoryPage1(InstallDir,
2989 DiskEntry,
2990 PartEntry);
2991 }
2992
2993 while (TRUE)
2994 {
2995 CONSOLE_ConInKey(Ir);
2996
2997 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2998 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
2999 {
3000 if (ConfirmQuit(Ir) == TRUE)
3001 return QUIT_PAGE;
3002
3003 break;
3004 }
3005 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
3006 {
3007 return InstallDirectoryPage1(InstallDir,
3008 DiskEntry,
3009 PartEntry);
3010 }
3011 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x08) /* BACKSPACE */
3012 {
3013 if (Length > 0)
3014 {
3015 Length--;
3016 InstallDir[Length] = 0;
3017 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
3018 }
3019 }
3020 else if (isprint(Ir->Event.KeyEvent.uChar.AsciiChar))
3021 {
3022 if (Length < 50)
3023 {
3024 InstallDir[Length] = (WCHAR)Ir->Event.KeyEvent.uChar.AsciiChar;
3025 Length++;
3026 InstallDir[Length] = 0;
3027 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
3028 }
3029 }
3030 }
3031
3032 return INSTALL_DIRECTORY_PAGE;
3033 }
3034
3035
3036 static BOOLEAN
3037 AddSectionToCopyQueueCab(HINF InfFile,
3038 PWCHAR SectionName,
3039 PWCHAR SourceCabinet,
3040 PCUNICODE_STRING DestinationPath,
3041 PINPUT_RECORD Ir)
3042 {
3043 INFCONTEXT FilesContext;
3044 INFCONTEXT DirContext;
3045 PWCHAR FileKeyName;
3046 PWCHAR FileKeyValue;
3047 PWCHAR DirKeyValue;
3048 PWCHAR TargetFileName;
3049
3050 /* Search for the SectionName section */
3051 if (!SetupFindFirstLineW(InfFile, SectionName, NULL, &FilesContext))
3052 {
3053 char Buffer[128];
3054 sprintf(Buffer, MUIGetString(STRING_TXTSETUPFAILED), SectionName);
3055 PopupError(Buffer, MUIGetString(STRING_REBOOTCOMPUTER), Ir, POPUP_WAIT_ENTER);
3056 return FALSE;
3057 }
3058
3059 /*
3060 * Enumerate the files in the section
3061 * and add them to the file queue.
3062 */
3063 do
3064 {
3065 /* Get source file name and target directory id */
3066 if (!INF_GetData(&FilesContext, &FileKeyName, &FileKeyValue))
3067 {
3068 /* FIXME: Handle error! */
3069 DPRINT1("INF_GetData() failed\n");
3070 break;
3071 }
3072
3073 /* Get optional target file name */
3074 if (!INF_GetDataField(&FilesContext, 2, &TargetFileName))
3075 TargetFileName = NULL;
3076
3077 DPRINT("FileKeyName: '%S' FileKeyValue: '%S'\n", FileKeyName, FileKeyValue);
3078
3079 /* Lookup target directory */
3080 if (!SetupFindFirstLineW(InfFile, L"Directories", FileKeyValue, &DirContext))
3081 {
3082 /* FIXME: Handle error! */
3083 DPRINT1("SetupFindFirstLine() failed\n");
3084 break;
3085 }
3086
3087 if (!INF_GetData(&DirContext, NULL, &DirKeyValue))
3088 {
3089 /* FIXME: Handle error! */
3090 DPRINT1("INF_GetData() failed\n");
3091 break;
3092 }
3093
3094 if (!SetupQueueCopy(SetupFileQueue,
3095 SourceCabinet,
3096 SourceRootPath.Buffer,
3097 SourceRootDir.Buffer,
3098 FileKeyName,
3099 DirKeyValue,
3100 TargetFileName))
3101 {
3102 /* FIXME: Handle error! */
3103 DPRINT1("SetupQueueCopy() failed\n");
3104 }
3105 } while (SetupFindNextLine(&FilesContext, &FilesContext));
3106
3107 return TRUE;
3108 }
3109
3110
3111 static BOOLEAN
3112 AddSectionToCopyQueue(HINF InfFile,
3113 PWCHAR SectionName,
3114 PWCHAR SourceCabinet,
3115 PCUNICODE_STRING DestinationPath,
3116 PINPUT_RECORD Ir)
3117 {
3118 INFCONTEXT FilesContext;
3119 INFCONTEXT DirContext;
3120 PWCHAR FileKeyName;
3121 PWCHAR FileKeyValue;
3122 PWCHAR DirKeyValue;
3123 PWCHAR TargetFileName;
3124 WCHAR CompleteOrigFileName[512];
3125
3126 if (SourceCabinet)
3127 return AddSectionToCopyQueueCab(InfFile, L"SourceFiles", SourceCabinet, DestinationPath, Ir);
3128
3129 /* Search for the SectionName section */
3130 if (!SetupFindFirstLineW(InfFile, SectionName, NULL, &FilesContext))
3131 {
3132 char Buffer[128];
3133 sprintf(Buffer, MUIGetString(STRING_TXTSETUPFAILED), SectionName);
3134 PopupError(Buffer, MUIGetString(STRING_REBOOTCOMPUTER), Ir, POPUP_WAIT_ENTER);
3135 return FALSE;
3136 }
3137
3138 /*
3139 * Enumerate the files in the section
3140 * and add them to the file queue.
3141 */
3142 do
3143 {
3144 /* Get source file name and target directory id */
3145 if (!INF_GetData(&FilesContext, &FileKeyName, &FileKeyValue))
3146 {
3147 /* FIXME: Handle error! */
3148 DPRINT1("INF_GetData() failed\n");
3149 break;
3150 }
3151
3152 /* Get target directory id */
3153 if (!INF_GetDataField(&FilesContext, 13, &FileKeyValue))
3154 {
3155 /* FIXME: Handle error! */
3156 DPRINT1("INF_GetData() failed\n");
3157 break;
3158 }
3159
3160 /* Get optional target file name */
3161 if (!INF_GetDataField(&FilesContext, 11, &TargetFileName))
3162 TargetFileName = NULL;
3163 else if (!*TargetFileName)
3164 TargetFileName = NULL;
3165
3166 DPRINT("FileKeyName: '%S' FileKeyValue: '%S'\n", FileKeyName, FileKeyValue);
3167
3168 /* Lookup target directory */
3169 if (!SetupFindFirstLineW(InfFile, L"Directories", FileKeyValue, &DirContext))
3170 {
3171 /* FIXME: Handle error! */
3172 DPRINT1("SetupFindFirstLine() failed\n");
3173 break;
3174 }
3175
3176 if (!INF_GetData(&DirContext, NULL, &DirKeyValue))
3177 {
3178 /* FIXME: Handle error! */
3179 DPRINT1("INF_GetData() failed\n");
3180 break;
3181 }
3182
3183 wcscpy(CompleteOrigFileName, SourceRootDir.Buffer);
3184 wcscat(CompleteOrigFileName, L"\\");
3185 wcscat(CompleteOrigFileName, DirKeyValue);
3186
3187 if (!SetupQueueCopy(SetupFileQueue,
3188 SourceCabinet,
3189 SourceRootPath.Buffer,
3190 CompleteOrigFileName,
3191 FileKeyName,
3192 DirKeyValue,
3193 TargetFileName))
3194 {
3195 /* FIXME: Handle error! */
3196 DPRINT1("SetupQueueCopy() failed\n");
3197 }
3198 } while (SetupFindNextLine(&FilesContext, &FilesContext));
3199
3200 return TRUE;
3201 }
3202
3203
3204 static BOOLEAN
3205 PrepareCopyPageInfFile(HINF InfFile,
3206 PWCHAR SourceCabinet,
3207 PINPUT_RECORD Ir)
3208 {
3209 WCHAR PathBuffer[MAX_PATH];
3210 INFCONTEXT DirContext;
3211 PWCHAR AdditionalSectionName = NULL;
3212 PWCHAR KeyValue;
3213 ULONG Length;
3214 NTSTATUS Status;
3215
3216 /* Add common files */
3217 if (!AddSectionToCopyQueue(InfFile, L"SourceDisksFiles", SourceCabinet, &DestinationPath, Ir))
3218 return FALSE;
3219
3220 /* Add specific files depending of computer type */
3221 if (SourceCabinet == NULL)
3222 {
3223 if (!ProcessComputerFiles(InfFile, ComputerList, &AdditionalSectionName))
3224 return FALSE;
3225
3226 if (AdditionalSectionName)
3227 {
3228 if (!AddSectionToCopyQueue(InfFile, AdditionalSectionName, SourceCabinet, &DestinationPath, Ir))
3229 return FALSE;
3230 }
3231 }
3232
3233 /* Create directories */
3234
3235 /*
3236 * FIXME:
3237 * Install directories like '\reactos\test' are not handled yet.
3238 */
3239
3240 /* Get destination path */
3241 wcscpy(PathBuffer, DestinationPath.Buffer);
3242
3243 /* Remove trailing backslash */
3244 Length = wcslen(PathBuffer);
3245 if ((Length > 0) && (PathBuffer[Length - 1] == '\\'))
3246 {
3247 PathBuffer[Length - 1] = 0;
3248 }
3249
3250 /* Create the install directory */
3251 Status = SetupCreateDirectory(PathBuffer);
3252 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION)
3253 {
3254 DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer, Status);
3255 MUIDisplayError(ERROR_CREATE_INSTALL_DIR, Ir, POPUP_WAIT_ENTER);
3256 return FALSE;
3257 }
3258
3259 /* Search for the 'Directories' section */
3260 if (!SetupFindFirstLineW(InfFile, L"Directories", NULL, &DirContext))
3261 {
3262 if (SourceCabinet)
3263 {
3264 MUIDisplayError(ERROR_CABINET_SECTION, Ir, POPUP_WAIT_ENTER);
3265 }
3266 else
3267 {
3268 MUIDisplayError(ERROR_TXTSETUP_SECTION, Ir, POPUP_WAIT_ENTER);
3269 }
3270
3271 return FALSE;
3272 }
3273
3274 /* Enumerate the directory values and create the subdirectories */
3275 do
3276 {
3277 if (!INF_GetData(&DirContext, NULL, &KeyValue))
3278 {
3279 DPRINT1("break\n");
3280 break;
3281 }
3282
3283 if (KeyValue[0] == L'\\' && KeyValue[1] != 0)
3284 {
3285 DPRINT("Absolute Path: '%S'\n", KeyValue);
3286
3287 wcscpy(PathBuffer, DestinationRootPath.Buffer);
3288 wcscat(PathBuffer, KeyValue);
3289
3290 DPRINT("FullPath: '%S'\n", PathBuffer);
3291 }
3292 else if (KeyValue[0] != L'\\')
3293 {
3294 DPRINT("RelativePath: '%S'\n", KeyValue);
3295 wcscpy(PathBuffer, DestinationPath.Buffer);
3296 wcscat(PathBuffer, L"\\");
3297 wcscat(PathBuffer, KeyValue);
3298
3299 DPRINT("FullPath: '%S'\n", PathBuffer);
3300
3301 Status = SetupCreateDirectory(PathBuffer);
3302 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION)
3303 {
3304 DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer, Status);
3305 MUIDisplayError(ERROR_CREATE_DIR, Ir, POPUP_WAIT_ENTER);
3306 return FALSE;
3307 }
3308 }
3309 } while (SetupFindNextLine (&DirContext, &DirContext));
3310
3311 return TRUE;
3312 }
3313
3314
3315 static PAGE_NUMBER
3316 PrepareCopyPage(PINPUT_RECORD Ir)
3317 {
3318 HINF InfHandle;
3319 WCHAR PathBuffer[MAX_PATH];
3320 INFCONTEXT CabinetsContext;
3321 ULONG InfFileSize;
3322 PWCHAR KeyValue;
3323 UINT ErrorLine;
3324 PVOID InfFileData;
3325
3326 MUIDisplayPage(PREPARE_COPY_PAGE);
3327
3328 /* Create the file queue */
3329 SetupFileQueue = SetupOpenFileQueue();
3330 if (SetupFileQueue == NULL)
3331 {
3332 MUIDisplayError(ERROR_COPY_QUEUE, Ir, POPUP_WAIT_ENTER);
3333 return(QUIT_PAGE);
3334 }
3335
3336 if (!PrepareCopyPageInfFile(SetupInf, NULL, Ir))
3337 {
3338 return QUIT_PAGE;
3339 }
3340
3341 /* Search for the 'Cabinets' section */
3342 if (!SetupFindFirstLineW(SetupInf, L"Cabinets", NULL, &CabinetsContext))
3343 {
3344 return FILE_COPY_PAGE;
3345 }
3346
3347 /*
3348 * Enumerate the directory values in the 'Cabinets'
3349 * section and parse their inf files.
3350 */
3351 do
3352 {
3353 if (!INF_GetData(&CabinetsContext, NULL, &KeyValue))
3354 break;
3355
3356 wcscpy(PathBuffer, SourcePath.Buffer);
3357 wcscat(PathBuffer, L"\\");
3358 wcscat(PathBuffer, KeyValue);
3359
3360 #ifdef __REACTOS__
3361 CabinetInitialize();
3362 CabinetSetEventHandlers(NULL, NULL, NULL);
3363 CabinetSetCabinetName(PathBuffer);
3364
3365 if (CabinetOpen() == CAB_STATUS_SUCCESS)
3366 {
3367 DPRINT("Cabinet %S\n", CabinetGetCabinetName());
3368
3369 InfFileData = CabinetGetCabinetReservedArea(&InfFileSize);
3370 if (InfFileData == NULL)
3371 {
3372 MUIDisplayError(ERROR_CABINET_SCRIPT, Ir, POPUP_WAIT_ENTER);
3373 return QUIT_PAGE;
3374 }
3375 }
3376 else
3377 {
3378 DPRINT("Cannot open cabinet: %S.\n", CabinetGetCabinetName());
3379 MUIDisplayError(ERROR_CABINET_MISSING, Ir, POPUP_WAIT_ENTER);
3380 return QUIT_PAGE;
3381 }
3382
3383 InfHandle = INF_OpenBufferedFileA((CHAR*) InfFileData,
3384 InfFileSize,
3385 (const CHAR*) NULL,
3386 INF_STYLE_WIN4,
3387 LanguageId,
3388 &ErrorLine);
3389
3390 if (InfHandle == INVALID_HANDLE_VALUE)
3391 {
3392 MUIDisplayError(ERROR_INVALID_CABINET_INF, Ir, POPUP_WAIT_ENTER);
3393 return QUIT_PAGE;
3394 }
3395
3396 CabinetCleanup();
3397
3398 if (!PrepareCopyPageInfFile(InfHandle, KeyValue, Ir))
3399 {
3400 return QUIT_PAGE;
3401 }
3402 #endif
3403 } while (SetupFindNextLine(&CabinetsContext, &CabinetsContext));
3404
3405 return FILE_COPY_PAGE;
3406 }
3407
3408
3409 VOID
3410 NTAPI
3411 SetupUpdateMemoryInfo(IN PCOPYCONTEXT CopyContext,
3412 IN BOOLEAN First)
3413 {
3414 SYSTEM_PERFORMANCE_INFORMATION PerfInfo;
3415
3416 /* Get the memory information from the system */
3417 NtQuerySystemInformation(SystemPerformanceInformation,
3418 &PerfInfo,
3419 sizeof(PerfInfo),
3420 NULL);
3421
3422 /* Check if this is initial setup */
3423 if (First)
3424 {
3425 /* Set maximum limits to be total RAM pages */
3426 ProgressSetStepCount(CopyContext->MemoryBars[0], PerfInfo.CommitLimit);
3427 ProgressSetStepCount(CopyContext->MemoryBars[1], PerfInfo.CommitLimit);
3428 ProgressSetStepCount(CopyContext->MemoryBars[2], PerfInfo.CommitLimit);
3429 }
3430
3431 /* Set current values */
3432 ProgressSetStep(CopyContext->MemoryBars[0], PerfInfo.PagedPoolPages + PerfInfo.NonPagedPoolPages);
3433 ProgressSetStep(CopyContext->MemoryBars[1], PerfInfo.ResidentSystemCachePage);
3434 ProgressSetStep(CopyContext->MemoryBars[2], PerfInfo.AvailablePages);
3435 }
3436
3437
3438 static UINT
3439 CALLBACK
3440 FileCopyCallback(PVOID Context,
3441 UINT Notification,
3442 UINT_PTR Param1,
3443 UINT_PTR Param2)
3444 {
3445 PCOPYCONTEXT CopyContext;
3446
3447 CopyContext = (PCOPYCONTEXT)Context;
3448
3449 switch (Notification)
3450 {
3451 case SPFILENOTIFY_STARTSUBQUEUE:
3452 CopyContext->TotalOperations = (ULONG)Param2;
3453 ProgressSetStepCount(CopyContext->ProgressBar,
3454 CopyContext->TotalOperations);
3455 SetupUpdateMemoryInfo(CopyContext, TRUE);
3456 break;
3457
3458 case SPFILENOTIFY_STARTCOPY:
3459 /* Display copy message */
3460 CONSOLE_SetStatusText(MUIGetString(STRING_COPYING), (PWSTR)Param1);
3461 SetupUpdateMemoryInfo(CopyContext, FALSE);
3462 break;
3463
3464 case SPFILENOTIFY_ENDCOPY:
3465 CopyContext->CompletedOperations++;
3466
3467 /* SYSREG checkpoint */
3468 if (CopyContext->TotalOperations >> 1 == CopyContext->CompletedOperations)
3469 DPRINT1("CHECKPOINT:HALF_COPIED\n");
3470
3471 ProgressNextStep(CopyContext->ProgressBar);
3472 SetupUpdateMemoryInfo(CopyContext, FALSE);
3473 break;
3474 }
3475
3476 return 0;
3477 }
3478
3479
3480 static
3481 PAGE_NUMBER
3482 FileCopyPage(PINPUT_RECORD Ir)
3483 {
3484 COPYCONTEXT CopyContext;
3485 unsigned int mem_bar_width;
3486
3487 MUIDisplayPage(FILE_COPY_PAGE);
3488
3489 /* Create context for the copy process */
3490 CopyContext.DestinationRootPath = DestinationRootPath.Buffer;
3491 CopyContext.InstallPath = InstallPath.Buffer;
3492 CopyContext.TotalOperations = 0;
3493 CopyContext.CompletedOperations = 0;
3494
3495 /* Create the progress bar as well */
3496 CopyContext.ProgressBar = CreateProgressBar(13,
3497 26,
3498 xScreen - 13,
3499 yScreen - 20,
3500 10,
3501 24,
3502 TRUE,
3503 MUIGetString(STRING_SETUPCOPYINGFILES));
3504
3505 // fit memory bars to screen width, distribute them uniform
3506 mem_bar_width = (xScreen - 26) / 5;
3507 mem_bar_width -= mem_bar_width % 2; // make even
3508 /* ATTENTION: The following progress bars are debug stuff, which should not be translated!! */
3509 /* Create the paged pool progress bar */
3510 CopyContext.MemoryBars[0] = CreateProgressBar(13,
3511 40,
3512 13 + mem_bar_width,
3513 43,
3514 13,
3515 44,
3516 FALSE,
3517 "Kernel Pool");
3518
3519 /* Create the non paged pool progress bar */
3520 CopyContext.MemoryBars[1] = CreateProgressBar((xScreen / 2)- (mem_bar_width / 2),
3521 40,
3522 (xScreen / 2) + (mem_bar_width / 2),
3523 43,
3524 (xScreen / 2)- (mem_bar_width / 2),
3525 44,
3526 FALSE,
3527 "Kernel Cache");
3528
3529 /* Create the global memory progress bar */
3530 CopyContext.MemoryBars[2] = CreateProgressBar(xScreen - 13 - mem_bar_width,
3531 40,
3532 xScreen - 13,
3533 43,
3534 xScreen - 13 - mem_bar_width,
3535 44,
3536 FALSE,
3537 "Free Memory");
3538
3539 /* Do the file copying */
3540 SetupCommitFileQueueW(NULL,
3541 SetupFileQueue,
3542 FileCopyCallback,
3543 &CopyContext);
3544
3545 /* If we get here, we're done, so cleanup the queue and progress bar */
3546 SetupCloseFileQueue(SetupFileQueue);
3547 DestroyProgressBar(CopyContext.ProgressBar);
3548 DestroyProgressBar(CopyContext.MemoryBars[0]);
3549 DestroyProgressBar(CopyContext.MemoryBars[1]);
3550 DestroyProgressBar(CopyContext.MemoryBars[2]);
3551
3552 /* Go display the next page */
3553 return REGISTRY_PAGE;
3554 }
3555
3556
3557 static PAGE_NUMBER
3558 RegistryPage(PINPUT_RECORD Ir)
3559 {
3560 INFCONTEXT InfContext;
3561 PWSTR Action;
3562 PWSTR File;
3563 PWSTR Section;
3564 BOOLEAN Delete;
3565 NTSTATUS Status;
3566
3567 MUIDisplayPage(REGISTRY_PAGE);
3568
3569 if (RepairUpdateFlag)
3570 {
3571 return SUCCESS_PAGE;
3572 }
3573
3574 if (!SetInstallPathValue(&DestinationPath))
3575 {
3576 DPRINT("SetInstallPathValue() failed\n");
3577 MUIDisplayError(ERROR_INITIALIZE_REGISTRY, Ir, POPUP_WAIT_ENTER);
3578 return QUIT_PAGE;
3579 }
3580
3581 /* Create the default hives */
3582 #ifdef __REACTOS__
3583 Status = NtInitializeRegistry(CM_BOOT_FLAG_SETUP);
3584 if (!NT_SUCCESS(Status))
3585 {
3586 DPRINT("NtInitializeRegistry() failed (Status %lx)\n", Status);
3587 MUIDisplayError(ERROR_CREATE_HIVE, Ir, POPUP_WAIT_ENTER);
3588 return QUIT_PAGE;
3589 }
3590 #else
3591 RegInitializeRegistry();
3592 #endif
3593
3594 /* Update registry */
3595 CONSOLE_SetStatusText(MUIGetString(STRING_REGHIVEUPDATE));
3596
3597 if (!SetupFindFirstLineW(SetupInf, L"HiveInfs.Install", NULL, &InfContext))
3598 {
3599 DPRINT1("SetupFindFirstLine() failed\n");
3600 MUIDisplayError(ERROR_FIND_REGISTRY, Ir, POPUP_WAIT_ENTER);
3601 return QUIT_PAGE;
3602 }
3603
3604 do
3605 {
3606 INF_GetDataField (&InfContext, 0, &Action);
3607 INF_GetDataField (&InfContext, 1, &File);
3608 INF_GetDataField (&InfContext, 2, &Section);
3609
3610 DPRINT("Action: %S File: %S Section %S\n", Action, File, Section);
3611
3612 if (Action == NULL)
3613 break; // Hackfix
3614
3615 if (!_wcsicmp (Action, L"AddReg"))
3616 {
3617 Delete = FALSE;
3618 }
3619 else if (!_wcsicmp (Action, L"DelReg"))
3620 {
3621 Delete = TRUE;
3622 }
3623 else
3624 {
3625 continue;
3626 }
3627
3628 CONSOLE_SetStatusText(MUIGetString(STRING_IMPORTFILE), File);
3629
3630 if (!ImportRegistryFile(File, Section, LanguageId, Delete))
3631 {
3632 DPRINT("Importing %S failed\n", File);
3633
3634 MUIDisplayError(ERROR_IMPORT_HIVE, Ir, POPUP_WAIT_ENTER);
3635 return QUIT_PAGE;
3636 }
3637 } while (SetupFindNextLine(&InfContext, &InfContext));
3638
3639 /* Update display registry settings */
3640 CONSOLE_SetStatusText(MUIGetString(STRING_DISPLAYETTINGSUPDATE));
3641 if (!ProcessDisplayRegistry(SetupInf, DisplayList))
3642 {
3643 MUIDisplayError(ERROR_UPDATE_DISPLAY_SETTINGS, Ir, POPUP_WAIT_ENTER);
3644 return QUIT_PAGE;
3645 }
3646
3647 /* Set the locale */
3648 CONSOLE_SetStatusText(MUIGetString(STRING_LOCALESETTINGSUPDATE));
3649 if (!ProcessLocaleRegistry(LanguageList))
3650 {
3651 MUIDisplayError(ERROR_UPDATE_LOCALESETTINGS, Ir, POPUP_WAIT_ENTER);
3652 return QUIT_PAGE;
3653 }
3654
3655 /* Add keyboard layouts */
3656 CONSOLE_SetStatusText(MUIGetString(STRING_ADDKBLAYOUTS));
3657 if (!AddKeyboardLayouts())
3658 {
3659 MUIDisplayError(ERROR_ADDING_KBLAYOUTS, Ir, POPUP_WAIT_ENTER);
3660 return QUIT_PAGE;
3661 }
3662
3663 /* Set GeoID */
3664
3665 if (!SetGeoID(MUIGetGeoID()))
3666 {
3667 MUIDisplayError(ERROR_UPDATE_GEOID, Ir, POPUP_WAIT_ENTER);
3668 return QUIT_PAGE;
3669 }
3670
3671 if (!IsUnattendedSetup)
3672 {
3673 /* Update keyboard layout settings */
3674 CONSOLE_SetStatusText(MUIGetString(STRING_KEYBOARDSETTINGSUPDATE));
3675 if (!ProcessKeyboardLayoutRegistry(LayoutList))
3676 {
3677 MUIDisplayError(ERROR_UPDATE_KBSETTINGS, Ir, POPUP_WAIT_ENTER);
3678 return QUIT_PAGE;
3679 }
3680 }
3681
3682 /* Add codepage information to registry */
3683 CONSOLE_SetStatusText(MUIGetString(STRING_CODEPAGEINFOUPDATE));
3684 if (!AddCodePage())
3685 {
3686 MUIDisplayError(ERROR_ADDING_CODEPAGE, Ir, POPUP_WAIT_ENTER);
3687 return QUIT_PAGE;
3688 }
3689
3690 /* Set the default pagefile entry */
3691 SetDefaultPagefile(DestinationDriveLetter);
3692
3693 /* Update the mounted devices list */
3694 SetMountedDeviceValues(PartitionList);
3695
3696 CONSOLE_SetStatusText(MUIGetString(STRING_DONE));
3697
3698 return BOOT_LOADER_PAGE;
3699 }
3700
3701
3702 static PAGE_NUMBER
3703 BootLoaderPage(PINPUT_RECORD Ir)
3704 {
3705 UCHAR PartitionType;
3706 BOOLEAN InstallOnFloppy;
3707 USHORT Line = 12;
3708 WCHAR PathBuffer[MAX_PATH];
3709
3710 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
3711
3712 /* Find or set the active partition */
3713 CheckActiveBootPartition(PartitionList);
3714
3715 /* Update the partition table because we may have changed the active partition */
3716 if (WritePartitionsToDisk(PartitionList) == FALSE)
3717 {
3718 DPRINT("WritePartitionsToDisk() failed\n");
3719 MUIDisplayError(ERROR_WRITE_PTABLE, Ir, POPUP_WAIT_ENTER);
3720 return QUIT_PAGE;
3721 }
3722
3723 RtlFreeUnicodeString(&SystemRootPath);
3724 swprintf(PathBuffer,
3725 L"\\Device\\Harddisk%lu\\Partition%lu",
3726 PartitionList->ActiveBootDisk->DiskNumber,
3727 PartitionList->ActiveBootPartition->PartitionNumber);
3728 RtlCreateUnicodeString(&SystemRootPath,
3729 PathBuffer);
3730 DPRINT("SystemRootPath: %wZ\n", &SystemRootPath);
3731
3732 PartitionType = PartitionList->ActiveBootPartition->PartitionType;
3733
3734 if (IsUnattendedSetup)
3735 {
3736 if (UnattendMBRInstallType == 0) /* skip MBR installation */
3737 {
3738 return SUCCESS_PAGE;
3739 }
3740 else if (UnattendMBRInstallType == 1) /* install on floppy */
3741 {
3742 return BOOT_LOADER_FLOPPY_PAGE;
3743 }
3744 }
3745
3746 if (PartitionType == PARTITION_ENTRY_UNUSED)
3747 {
3748 DPRINT("Error: active partition invalid (unused)\n");
3749 InstallOnFloppy = TRUE;
3750 }
3751 else if (PartitionType == 0x0A)
3752 {
3753 /* OS/2 boot manager partition */
3754 DPRINT("Found OS/2 boot manager partition\n");
3755 InstallOnFloppy = TRUE;
3756 }
3757 else if (PartitionType == 0x83)
3758 {
3759 /* Linux ext2 partition */
3760 DPRINT("Found Linux ext2 partition\n");
3761 InstallOnFloppy = TRUE;
3762 }
3763 else if (PartitionType == PARTITION_IFS)
3764 {
3765 /* NTFS partition */
3766 DPRINT("Found NTFS partition\n");
3767 InstallOnFloppy = TRUE;
3768 }
3769 else if ((PartitionType == PARTITION_FAT_12) ||
3770 (PartitionType == PARTITION_FAT_16) ||
3771 (PartitionType == PARTITION_HUGE) ||
3772 (PartitionType == PARTITION_XINT13) ||
3773 (PartitionType == PARTITION_FAT32) ||
3774 (PartitionType == PARTITION_FAT32_XINT13))
3775 {
3776 DPRINT("Found FAT partition\n");
3777 InstallOnFloppy = FALSE;
3778 }
3779 else
3780 {
3781 /* Unknown partition */
3782 DPRINT("Unknown partition found\n");
3783 InstallOnFloppy = TRUE;
3784 }
3785
3786 if (InstallOnFloppy == TRUE)
3787 {
3788 return BOOT_LOADER_FLOPPY_PAGE;
3789 }
3790
3791 /* Unattended install on hdd? */
3792 if (IsUnattendedSetup && UnattendMBRInstallType == 2)
3793 {
3794 return BOOT_LOADER_HARDDISK_MBR_PAGE;
3795 }
3796
3797 MUIDisplayPage(BOOT_LOADER_PAGE);
3798 CONSOLE_InvertTextXY(8, Line, 60, 1);
3799
3800 while (TRUE)
3801 {
3802 CONSOLE_ConInKey(Ir);
3803
3804 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3805 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
3806 {
3807 CONSOLE_NormalTextXY(8, Line, 60, 1);
3808
3809 Line++;
3810 if (Line<12)
3811 Line=15;
3812
3813 if (Line>15)
3814 Line=12;
3815
3816 CONSOLE_InvertTextXY(8, Line, 60, 1);
3817 }
3818 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3819 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
3820 {
3821 CONSOLE_NormalTextXY(8, Line, 60, 1);
3822
3823 Line--;
3824 if (Line<12)
3825 Line=15;
3826
3827 if (Line>15)
3828 Line=12;
3829
3830 CONSOLE_InvertTextXY(8, Line, 60, 1);
3831 }
3832 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3833 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
3834 {
3835 if (ConfirmQuit(Ir) == TRUE)
3836 return QUIT_PAGE;
3837
3838 break;
3839 }
3840 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
3841 {
3842 if (Line == 12)
3843 {
3844 return BOOT_LOADER_HARDDISK_MBR_PAGE;
3845 }
3846 else if (Line == 13)
3847 {
3848 return BOOT_LOADER_HARDDISK_VBR_PAGE;
3849 }
3850 else if (Line == 14)
3851 {
3852 return BOOT_LOADER_FLOPPY_PAGE;
3853 }
3854 else if (Line == 15)
3855 {
3856 return SUCCESS_PAGE;
3857 }
3858
3859 return BOOT_LOADER_PAGE;
3860 }
3861 }
3862
3863 return BOOT_LOADER_PAGE;
3864 }
3865
3866
3867 static PAGE_NUMBER
3868 BootLoaderFloppyPage(PINPUT_RECORD Ir)
3869 {
3870 NTSTATUS Status;
3871
3872 MUIDisplayPage(BOOT_LOADER_FLOPPY_PAGE);
3873
3874 // SetStatusText(" Please wait...");
3875
3876 while (TRUE)
3877 {
3878 CONSOLE_ConInKey(Ir);
3879
3880 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3881 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
3882 {
3883 if (ConfirmQuit(Ir) == TRUE)
3884 return QUIT_PAGE;
3885
3886 break;
3887 }
3888 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
3889 {
3890 if (DoesFileExist(L"\\Device\\Floppy0", L"\\") == FALSE)
3891 {
3892 MUIDisplayError(ERROR_NO_FLOPPY, Ir, POPUP_WAIT_ENTER);
3893 return BOOT_LOADER_FLOPPY_PAGE;
3894 }
3895
3896 Status = InstallFatBootcodeToFloppy(&SourceRootPath, &DestinationArcPath);
3897 if (!NT_SUCCESS(Status))
3898 {
3899 /* Print error message */
3900 return BOOT_LOADER_FLOPPY_PAGE;
3901 }
3902
3903 return SUCCESS_PAGE;
3904 }
3905 }
3906
3907 return BOOT_LOADER_FLOPPY_PAGE;
3908 }
3909
3910 static PAGE_NUMBER
3911 BootLoaderHarddiskVbrPage(PINPUT_RECORD Ir)
3912 {
3913 UCHAR PartitionType;
3914 NTSTATUS Status;
3915
3916 PartitionType = PartitionList->ActiveBootPartition->PartitionType;
3917
3918 Status = InstallVBRToPartition(&SystemRootPath,
3919 &SourceRootPath,
3920 &DestinationArcPath,
3921 PartitionType);
3922 if (!NT_SUCCESS(Status))
3923 {
3924 MUIDisplayError(ERROR_WRITE_BOOT, Ir, POPUP_WAIT_ENTER);
3925 return QUIT_PAGE;
3926 }
3927
3928 return SUCCESS_PAGE;
3929 }
3930
3931 static PAGE_NUMBER
3932 BootLoaderHarddiskMbrPage(PINPUT_RECORD Ir)
3933 {
3934 UCHAR PartitionType;
3935 NTSTATUS Status;
3936 WCHAR DestinationDevicePathBuffer[MAX_PATH];
3937 WCHAR SourceMbrPathBuffer[MAX_PATH];
3938
3939 /* Step 1: Write the VBR */
3940 PartitionType = PartitionList->ActiveBootPartition->PartitionType;
3941
3942 Status = InstallVBRToPartition(&SystemRootPath,
3943 &SourceRootPath,
3944 &DestinationArcPath,
3945 PartitionType);
3946 if (!NT_SUCCESS(Status))
3947 {
3948 MUIDisplayError(ERROR_WRITE_BOOT, Ir, POPUP_WAIT_ENTER);
3949 return QUIT_PAGE;
3950 }
3951
3952 /* Step 2: Write the MBR */
3953 swprintf(DestinationDevicePathBuffer,
3954 L"\\Device\\Harddisk%d\\Partition0",
3955 PartitionList->ActiveBootDisk->DiskNumber);
3956
3957 wcscpy(SourceMbrPathBuffer, SourceRootPath.Buffer);
3958 wcscat(SourceMbrPathBuffer, L"\\loader\\dosmbr.bin");
3959
3960 DPRINT("Install MBR bootcode: %S ==> %S\n",
3961 SourceMbrPathBuffer, DestinationDevicePathBuffer);
3962
3963 Status = InstallMbrBootCodeToDisk(SourceMbrPathBuffer,
3964 DestinationDevicePathBuffer);
3965 if (!NT_SUCCESS (Status))
3966 {
3967 DPRINT1("InstallMbrBootCodeToDisk() failed (Status %lx)\n",
3968 Status);
3969 MUIDisplayError(ERROR_INSTALL_BOOTCODE, Ir, POPUP_WAIT_ENTER);
3970 return QUIT_PAGE;
3971 }
3972
3973 return SUCCESS_PAGE;
3974 }
3975
3976
3977 static PAGE_NUMBER
3978 QuitPage(PINPUT_RECORD Ir)
3979 {
3980 MUIDisplayPage(QUIT_PAGE);
3981
3982 /* Destroy partition list */
3983 if (PartitionList != NULL)
3984 {
3985 DestroyPartitionList (PartitionList);
3986 PartitionList = NULL;
3987 }
3988
3989 /* Destroy filesystem list */
3990 if (FileSystemList != NULL)
3991 {
3992 DestroyFileSystemList (FileSystemList);
3993 FileSystemList = NULL;
3994 }
3995
3996 /* Destroy computer settings list */
3997 if (ComputerList != NULL)
3998 {
3999 DestroyGenericList(ComputerList, TRUE);
4000 ComputerList = NULL;
4001 }
4002
4003 /* Destroy display settings list */
4004 if (DisplayList != NULL)
4005 {
4006 DestroyGenericList(DisplayList, TRUE);
4007 DisplayList = NULL;
4008 }
4009
4010 /* Destroy keyboard settings list */
4011 if (KeyboardList != NULL)
4012 {
4013 DestroyGenericList(KeyboardList, TRUE);
4014 KeyboardList = NULL;
4015 }
4016
4017 /* Destroy keyboard layout list */
4018 if (LayoutList != NULL)
4019 {
4020 DestroyGenericList(LayoutList, TRUE);
4021 LayoutList = NULL;
4022 }
4023
4024 if (LanguageList != NULL)
4025 {
4026 DestroyGenericList(LanguageList, FALSE);
4027 LanguageList = NULL;
4028 }
4029
4030 CONSOLE_SetStatusText(MUIGetString(STRING_REBOOTCOMPUTER2));
4031
4032 while (TRUE)
4033 {
4034 CONSOLE_ConInKey(Ir);
4035
4036 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
4037 {
4038 return FLUSH_PAGE;
4039 }
4040 }
4041 }
4042
4043
4044 static PAGE_NUMBER
4045 SuccessPage(PINPUT_RECORD Ir)
4046 {
4047 MUIDisplayPage(SUCCESS_PAGE);
4048
4049 if (IsUnattendedSetup)
4050 {
4051 return FLUSH_PAGE;
4052 }
4053
4054 while (TRUE)
4055 {
4056 CONSOLE_ConInKey(Ir);
4057
4058 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
4059 {
4060 return FLUSH_PAGE;
4061 }
4062 }
4063 }
4064
4065
4066 static PAGE_NUMBER
4067 FlushPage(PINPUT_RECORD Ir)
4068 {
4069 MUIDisplayPage(FLUSH_PAGE);
4070 return REBOOT_PAGE;
4071 }
4072
4073
4074 DWORD WINAPI
4075 PnpEventThread(IN LPVOID lpParameter);
4076
4077 VOID
4078 RunUSetup(VOID)
4079 {
4080 INPUT_RECORD Ir;
4081 PAGE_NUMBER Page;
4082 LARGE_INTEGER Time;
4083 NTSTATUS Status;
4084 BOOLEAN Old;
4085
4086 NtQuerySystemTime(&Time);
4087
4088 Status = RtlCreateUserThread(NtCurrentProcess(),
4089 NULL,
4090 TRUE,
4091 0,
4092 0,
4093 0,
4094 PnpEventThread,
4095 &SetupInf,
4096 &hPnpThread,
4097 NULL);
4098 if (!NT_SUCCESS(Status))
4099 hPnpThread = INVALID_HANDLE_VALUE;
4100
4101 if (!CONSOLE_Init())
4102 {
4103 PrintString(MUIGetString(STRING_CONSOLEFAIL1));
4104 PrintString(MUIGetString(STRING_CONSOLEFAIL2));
4105 PrintString(MUIGetString(STRING_CONSOLEFAIL3));
4106
4107 /* Raise a hard error (crash the system/BSOD) */
4108 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED,
4109 0,0,0,0,0);
4110 }
4111
4112 /* Initialize global unicode strings */
4113 RtlInitUnicodeString(&SourcePath, NULL);
4114 RtlInitUnicodeString(&SourceRootPath, NULL);
4115 RtlInitUnicodeString(&SourceRootDir, NULL);
4116 RtlInitUnicodeString(&InstallPath, NULL);
4117 RtlInitUnicodeString(&DestinationPath, NULL);
4118 RtlInitUnicodeString(&DestinationArcPath, NULL);
4119 RtlInitUnicodeString(&DestinationRootPath, NULL);
4120 RtlInitUnicodeString(&SystemRootPath, NULL);
4121
4122 /* Hide the cursor */
4123 CONSOLE_SetCursorType(TRUE, FALSE);
4124
4125 Page = START_PAGE;
4126 while (Page != REBOOT_PAGE && Page != RECOVERY_PAGE)
4127 {
4128 CONSOLE_ClearScreen();
4129 CONSOLE_Flush();
4130
4131 //CONSOLE_SetUnderlinedTextXY(4, 3, " ReactOS " KERNEL_VERSION_STR " Setup ");
4132 //CONSOLE_Flush();
4133
4134 switch (Page)
4135 {
4136 /* Start page */
4137 case START_PAGE:
4138 Page = SetupStartPage(&Ir);
4139 break;
4140
4141 /* Language page */
4142 case LANGUAGE_PAGE:
4143 Page = LanguagePage(&Ir);
4144 break;
4145
4146 /* License page */
4147 case LICENSE_PAGE:
4148 Page = LicensePage(&Ir);
4149 break;
4150
4151 /* Intro page */
4152 case INTRO_PAGE:
4153 Page = IntroPage(&Ir);
4154 break;
4155
4156 /* Install pages */
4157 case INSTALL_INTRO_PAGE:
4158 Page = InstallIntroPage(&Ir);
4159 break;
4160
4161 #if 0
4162 case SCSI_CONTROLLER_PAGE:
4163 Page = ScsiControllerPage(&Ir);
4164 break;
4165 #endif
4166
4167 #if 0
4168 case OEM_DRIVER_PAGE:
4169 Page = OemDriverPage(&Ir);
4170 break;
4171 #endif
4172
4173 case DEVICE_SETTINGS_PAGE:
4174 Page = DeviceSettingsPage(&Ir);
4175 break;
4176
4177 case COMPUTER_SETTINGS_PAGE:
4178 Page = ComputerSettingsPage(&Ir);
4179 break;
4180
4181 case DISPLAY_SETTINGS_PAGE:
4182 Page = DisplaySettingsPage(&Ir);
4183 break;
4184
4185 case KEYBOARD_SETTINGS_PAGE:
4186 Page = KeyboardSettingsPage(&Ir);
4187 break;
4188
4189 case LAYOUT_SETTINGS_PAGE:
4190 Page = LayoutSettingsPage(&Ir);
4191 break;
4192
4193 case SELECT_PARTITION_PAGE:
4194 Page = SelectPartitionPage(&Ir);
4195 break;
4196
4197 case CREATE_PRIMARY_PARTITION_PAGE:
4198 Page = CreatePrimaryPartitionPage(&Ir);
4199 break;
4200
4201 case CREATE_EXTENDED_PARTITION_PAGE:
4202 Page = CreateExtendedPartitionPage(&Ir);
4203 break;
4204
4205 case CREATE_LOGICAL_PARTITION_PAGE:
4206 Page = CreateLogicalPartitionPage(&Ir);
4207 break;
4208
4209 case DELETE_PARTITION_PAGE:
4210 Page = DeletePartitionPage(&Ir);
4211 break;
4212
4213 case SELECT_FILE_SYSTEM_PAGE:
4214 Page = SelectFileSystemPage(&Ir);
4215 break;
4216
4217 case FORMAT_PARTITION_PAGE:
4218 Page = (PAGE_NUMBER) FormatPartitionPage(&Ir);
4219 break;
4220
4221 case CHECK_FILE_SYSTEM_PAGE:
4222 Page = (PAGE_NUMBER) CheckFileSystemPage(&Ir);
4223 break;
4224
4225 case INSTALL_DIRECTORY_PAGE:
4226 Page = InstallDirectoryPage(&Ir);
4227 break;
4228
4229 case PREPARE_COPY_PAGE:
4230 Page = PrepareCopyPage(&Ir);
4231 break;
4232
4233 case FILE_COPY_PAGE:
4234 Page = FileCopyPage(&Ir);
4235 break;
4236
4237 case REGISTRY_PAGE:
4238 Page = RegistryPage(&Ir);
4239 break;
4240
4241 case BOOT_LOADER_PAGE:
4242 Page = BootLoaderPage(&Ir);
4243 break;
4244
4245 case BOOT_LOADER_FLOPPY_PAGE:
4246 Page = BootLoaderFloppyPage(&Ir);
4247 break;
4248
4249 case BOOT_LOADER_HARDDISK_MBR_PAGE:
4250 Page = BootLoaderHarddiskMbrPage(&Ir);
4251 break;
4252
4253 case BOOT_LOADER_HARDDISK_VBR_PAGE:
4254 Page = BootLoaderHarddiskVbrPage(&Ir);
4255 break;
4256
4257 /* Repair pages */
4258 case REPAIR_INTRO_PAGE:
4259 Page = RepairIntroPage(&Ir);
4260 break;
4261
4262 case SUCCESS_PAGE:
4263 Page = SuccessPage(&Ir);
4264 break;
4265
4266 case FLUSH_PAGE:
4267 Page = FlushPage(&Ir);
4268 break;
4269
4270 case QUIT_PAGE:
4271 Page = QuitPage(&Ir);
4272 break;
4273
4274 case RECOVERY_PAGE:
4275 case REBOOT_PAGE:
4276 break;
4277 }
4278 }
4279
4280 if (Page == RECOVERY_PAGE)
4281 RecoveryConsole();
4282
4283 FreeConsole();
4284
4285 /* Avoid bugcheck */
4286 Time.QuadPart += 50000000;
4287 NtDelayExecution(FALSE, &Time);
4288
4289 /* Reboot */
4290 RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, TRUE, FALSE, &Old);
4291 NtShutdownSystem(ShutdownReboot);
4292 RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, Old, FALSE, &Old);
4293 NtTerminateProcess(NtCurrentProcess(), 0);
4294 }
4295
4296
4297 #ifdef __REACTOS__
4298
4299 VOID NTAPI
4300 NtProcessStartup(PPEB Peb)
4301 {
4302 RtlNormalizeProcessParams(Peb->ProcessParameters);
4303
4304 ProcessHeap = Peb->ProcessHeap;
4305 InfSetHeap(ProcessHeap);
4306 RunUSetup();
4307 }
4308 #endif /* __REACTOS__ */
4309
4310 /* EOF */