[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 NTSTATUS Status;
1838
1839 if (PartitionList == NULL ||
1840 PartitionList->CurrentDisk == NULL ||
1841 PartitionList->CurrentPartition == NULL)
1842 {
1843 /* FIXME: show an error dialog */
1844 return QUIT_PAGE;
1845 }
1846
1847 DiskEntry = PartitionList->CurrentDisk;
1848 PartEntry = PartitionList->CurrentPartition;
1849
1850 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
1851
1852 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSENEWPARTITION));
1853
1854 DiskSize = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
1855 #if 0
1856 if (DiskSize >= 10737418240) /* 10 GB */
1857 {
1858 DiskSize = DiskSize / 1073741824;
1859 Unit = MUIGetString(STRING_GB);
1860 }
1861 else
1862 #endif
1863 {
1864 DiskSize = DiskSize / 1048576;
1865 if (DiskSize == 0)
1866 DiskSize = 1;
1867
1868 Unit = MUIGetString(STRING_MB);
1869 }
1870
1871 if (DiskEntry->DriverName.Length > 0)
1872 {
1873 CONSOLE_PrintTextXY(6, 10,
1874 MUIGetString(STRING_HDINFOPARTCREATE),
1875 DiskSize,
1876 Unit,
1877 DiskEntry->DiskNumber,
1878 DiskEntry->Port,
1879 DiskEntry->Bus,
1880 DiskEntry->Id,
1881 &DiskEntry->DriverName);
1882 }
1883 else
1884 {
1885 CONSOLE_PrintTextXY(6, 10,
1886 MUIGetString(STRING_HDDINFOUNK1),
1887 DiskSize,
1888 Unit,
1889 DiskEntry->DiskNumber,
1890 DiskEntry->Port,
1891 DiskEntry->Bus,
1892 DiskEntry->Id);
1893 }
1894
1895 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE));
1896
1897 #if 0
1898 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
1899 PartitionList->CurrentPartition->SectorCount * DiskEntry->BytesPerSector / 1048576);
1900 #endif
1901
1902 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION));
1903
1904 PartEntry = PartitionList->CurrentPartition;
1905 while (TRUE)
1906 {
1907 MaxSize = (PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector) / 1048576; /* in MBytes (rounded) */
1908
1909 if (MaxSize > PARTITION_MAXSIZE)
1910 MaxSize = PARTITION_MAXSIZE;
1911
1912 ShowPartitionSizeInputBox(12, 14, xScreen - 12, 17, /* left, top, right, bottom */
1913 MaxSize, InputBuffer, &Quit, &Cancel);
1914
1915 if (Quit == TRUE)
1916 {
1917 if (ConfirmQuit (Ir) == TRUE)
1918 {
1919 return QUIT_PAGE;
1920 }
1921 }
1922 else if (Cancel == TRUE)
1923 {
1924 return SELECT_PARTITION_PAGE;
1925 }
1926 else
1927 {
1928 PartSize = atoi(InputBuffer);
1929
1930 if (PartSize < 1)
1931 {
1932 /* Too small */
1933 continue;
1934 }
1935
1936 if (PartSize > MaxSize)
1937 {
1938 /* Too large */
1939 continue;
1940 }
1941
1942 /* Convert to bytes */
1943 if (PartSize == MaxSize)
1944 {
1945 /* Use all of the unpartitioned disk space */
1946 SectorCount = PartEntry->SectorCount.QuadPart;
1947 }
1948 else
1949 {
1950 /* Calculate the sector count from the size in MB */
1951 SectorCount = PartSize * 1048576 / DiskEntry->BytesPerSector;
1952
1953 /* But never get larger than the unpartitioned disk space */
1954 if (SectorCount > PartEntry->SectorCount.QuadPart)
1955 SectorCount = PartEntry->SectorCount.QuadPart;
1956 }
1957
1958 DPRINT ("Partition size: %I64u bytes\n", PartSize);
1959
1960 CreatePrimaryPartition(PartitionList,
1961 SectorCount,
1962 FALSE);
1963
1964 Status = WriteDirtyPartitions(PartitionList);
1965 if (!NT_SUCCESS(Status))
1966 {
1967 DPRINT("WriteDirtyPartitions() failed\n");
1968 MUIDisplayError(ERROR_WRITE_PTABLE, Ir, POPUP_WAIT_ENTER);
1969 return QUIT_PAGE;
1970 }
1971
1972 return SELECT_PARTITION_PAGE;
1973 }
1974 }
1975
1976 return CREATE_PRIMARY_PARTITION_PAGE;
1977 }
1978
1979
1980 static PAGE_NUMBER
1981 CreateExtendedPartitionPage(PINPUT_RECORD Ir)
1982 {
1983 PDISKENTRY DiskEntry;
1984 PPARTENTRY PartEntry;
1985 BOOLEAN Quit;
1986 BOOLEAN Cancel;
1987 CHAR InputBuffer[50];
1988 ULONG MaxSize;
1989 ULONGLONG PartSize;
1990 ULONGLONG DiskSize;
1991 ULONGLONG SectorCount;
1992 PCHAR Unit;
1993 NTSTATUS Status;
1994
1995 if (PartitionList == NULL ||
1996 PartitionList->CurrentDisk == NULL ||
1997 PartitionList->CurrentPartition == NULL)
1998 {
1999 /* FIXME: show an error dialog */
2000 return QUIT_PAGE;
2001 }
2002
2003 DiskEntry = PartitionList->CurrentDisk;
2004 PartEntry = PartitionList->CurrentPartition;
2005
2006 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
2007
2008 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSE_NEW_EXTENDED_PARTITION));
2009
2010 DiskSize = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
2011 #if 0
2012 if (DiskSize >= 10737418240) /* 10 GB */
2013 {
2014 DiskSize = DiskSize / 1073741824;
2015 Unit = MUIGetString(STRING_GB);
2016 }
2017 else
2018 #endif
2019 {
2020 DiskSize = DiskSize / 1048576;
2021 if (DiskSize == 0)
2022 DiskSize = 1;
2023
2024 Unit = MUIGetString(STRING_MB);
2025 }
2026
2027 if (DiskEntry->DriverName.Length > 0)
2028 {
2029 CONSOLE_PrintTextXY(6, 10,
2030 MUIGetString(STRING_HDINFOPARTCREATE),
2031 DiskSize,
2032 Unit,
2033 DiskEntry->DiskNumber,
2034 DiskEntry->Port,
2035 DiskEntry->Bus,
2036 DiskEntry->Id,
2037 &DiskEntry->DriverName);
2038 }
2039 else
2040 {
2041 CONSOLE_PrintTextXY(6, 10,
2042 MUIGetString(STRING_HDDINFOUNK1),
2043 DiskSize,
2044 Unit,
2045 DiskEntry->DiskNumber,
2046 DiskEntry->Port,
2047 DiskEntry->Bus,
2048 DiskEntry->Id);
2049 }
2050
2051 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE));
2052
2053 #if 0
2054 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2055 PartitionList->CurrentPartition->SectorCount * DiskEntry->BytesPerSector / 1048576);
2056 #endif
2057
2058 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION));
2059
2060 PartEntry = PartitionList->CurrentPartition;
2061 while (TRUE)
2062 {
2063 MaxSize = (PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector) / 1048576; /* in MBytes (rounded) */
2064
2065 if (MaxSize > PARTITION_MAXSIZE)
2066 MaxSize = PARTITION_MAXSIZE;
2067
2068 ShowPartitionSizeInputBox(12, 14, xScreen - 12, 17, /* left, top, right, bottom */
2069 MaxSize, InputBuffer, &Quit, &Cancel);
2070
2071 if (Quit == TRUE)
2072 {
2073 if (ConfirmQuit (Ir) == TRUE)
2074 {
2075 return QUIT_PAGE;
2076 }
2077 }
2078 else if (Cancel == TRUE)
2079 {
2080 return SELECT_PARTITION_PAGE;
2081 }
2082 else
2083 {
2084 PartSize = atoi(InputBuffer);
2085
2086 if (PartSize < 1)
2087 {
2088 /* Too small */
2089 continue;
2090 }
2091
2092 if (PartSize > MaxSize)
2093 {
2094 /* Too large */
2095 continue;
2096 }
2097
2098 /* Convert to bytes */
2099 if (PartSize == MaxSize)
2100 {
2101 /* Use all of the unpartitioned disk space */
2102 SectorCount = PartEntry->SectorCount.QuadPart;
2103 }
2104 else
2105 {
2106 /* Calculate the sector count from the size in MB */
2107 SectorCount = PartSize * 1048576 / DiskEntry->BytesPerSector;
2108
2109 /* But never get larger than the unpartitioned disk space */
2110 if (SectorCount > PartEntry->SectorCount.QuadPart)
2111 SectorCount = PartEntry->SectorCount.QuadPart;
2112 }
2113
2114 DPRINT ("Partition size: %I64u bytes\n", PartSize);
2115
2116 CreateExtendedPartition(PartitionList,
2117 SectorCount);
2118
2119 Status = WriteDirtyPartitions(PartitionList);
2120 if (!NT_SUCCESS(Status))
2121 {
2122 DPRINT("WriteDirtyPartitions() failed\n");
2123 MUIDisplayError(ERROR_WRITE_PTABLE, Ir, POPUP_WAIT_ENTER);
2124 return QUIT_PAGE;
2125 }
2126
2127 return SELECT_PARTITION_PAGE;
2128 }
2129 }
2130
2131 return CREATE_EXTENDED_PARTITION_PAGE;
2132 }
2133
2134
2135 static PAGE_NUMBER
2136 CreateLogicalPartitionPage(PINPUT_RECORD Ir)
2137 {
2138 PDISKENTRY DiskEntry;
2139 PPARTENTRY PartEntry;
2140 BOOLEAN Quit;
2141 BOOLEAN Cancel;
2142 CHAR InputBuffer[50];
2143 ULONG MaxSize;
2144 ULONGLONG PartSize;
2145 ULONGLONG DiskSize;
2146 ULONGLONG SectorCount;
2147 PCHAR Unit;
2148 NTSTATUS Status;
2149
2150 if (PartitionList == NULL ||
2151 PartitionList->CurrentDisk == NULL ||
2152 PartitionList->CurrentPartition == NULL)
2153 {
2154 /* FIXME: show an error dialog */
2155 return QUIT_PAGE;
2156 }
2157
2158 DiskEntry = PartitionList->CurrentDisk;
2159 PartEntry = PartitionList->CurrentPartition;
2160
2161 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
2162
2163 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSE_NEW_LOGICAL_PARTITION));
2164
2165 DiskSize = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
2166 #if 0
2167 if (DiskSize >= 10737418240) /* 10 GB */
2168 {
2169 DiskSize = DiskSize / 1073741824;
2170 Unit = MUIGetString(STRING_GB);
2171 }
2172 else
2173 #endif
2174 {
2175 DiskSize = DiskSize / 1048576;
2176 if (DiskSize == 0)
2177 DiskSize = 1;
2178
2179 Unit = MUIGetString(STRING_MB);
2180 }
2181
2182 if (DiskEntry->DriverName.Length > 0)
2183 {
2184 CONSOLE_PrintTextXY(6, 10,
2185 MUIGetString(STRING_HDINFOPARTCREATE),
2186 DiskSize,
2187 Unit,
2188 DiskEntry->DiskNumber,
2189 DiskEntry->Port,
2190 DiskEntry->Bus,
2191 DiskEntry->Id,
2192 &DiskEntry->DriverName);
2193 }
2194 else
2195 {
2196 CONSOLE_PrintTextXY(6, 10,
2197 MUIGetString(STRING_HDDINFOUNK1),
2198 DiskSize,
2199 Unit,
2200 DiskEntry->DiskNumber,
2201 DiskEntry->Port,
2202 DiskEntry->Bus,
2203 DiskEntry->Id);
2204 }
2205
2206 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE));
2207
2208 #if 0
2209 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2210 PartitionList->CurrentPartition->SectorCount * DiskEntry->BytesPerSector / 1048576);
2211 #endif
2212
2213 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION));
2214
2215 PartEntry = PartitionList->CurrentPartition;
2216 while (TRUE)
2217 {
2218 MaxSize = (PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector) / 1048576; /* in MBytes (rounded) */
2219
2220 if (MaxSize > PARTITION_MAXSIZE)
2221 MaxSize = PARTITION_MAXSIZE;
2222
2223 ShowPartitionSizeInputBox(12, 14, xScreen - 12, 17, /* left, top, right, bottom */
2224 MaxSize, InputBuffer, &Quit, &Cancel);
2225
2226 if (Quit == TRUE)
2227 {
2228 if (ConfirmQuit (Ir) == TRUE)
2229 {
2230 return QUIT_PAGE;
2231 }
2232 }
2233 else if (Cancel == TRUE)
2234 {
2235 return SELECT_PARTITION_PAGE;
2236 }
2237 else
2238 {
2239 PartSize = atoi(InputBuffer);
2240
2241 if (PartSize < 1)
2242 {
2243 /* Too small */
2244 continue;
2245 }
2246
2247 if (PartSize > MaxSize)
2248 {
2249 /* Too large */
2250 continue;
2251 }
2252
2253 /* Convert to bytes */
2254 if (PartSize == MaxSize)
2255 {
2256 /* Use all of the unpartitioned disk space */
2257 SectorCount = PartEntry->SectorCount.QuadPart;
2258 }
2259 else
2260 {
2261 /* Calculate the sector count from the size in MB */
2262 SectorCount = PartSize * 1048576 / DiskEntry->BytesPerSector;
2263
2264 /* But never get larger than the unpartitioned disk space */
2265 if (SectorCount > PartEntry->SectorCount.QuadPart)
2266 SectorCount = PartEntry->SectorCount.QuadPart;
2267 }
2268
2269 DPRINT("Partition size: %I64u bytes\n", PartSize);
2270
2271 CreateLogicalPartition(PartitionList,
2272 SectorCount);
2273
2274 Status = WriteDirtyPartitions(PartitionList);
2275 if (!NT_SUCCESS(Status))
2276 {
2277 DPRINT("WriteDirtyPartitions() failed\n");
2278 MUIDisplayError(ERROR_WRITE_PTABLE, Ir, POPUP_WAIT_ENTER);
2279 return QUIT_PAGE;
2280 }
2281
2282 return SELECT_PARTITION_PAGE;
2283 }
2284 }
2285
2286 return CREATE_LOGICAL_PARTITION_PAGE;
2287 }
2288
2289
2290 static PAGE_NUMBER
2291 DeletePartitionPage(PINPUT_RECORD Ir)
2292 {
2293 PDISKENTRY DiskEntry;
2294 PPARTENTRY PartEntry;
2295 ULONGLONG DiskSize;
2296 ULONGLONG PartSize;
2297 PCHAR Unit;
2298 PCHAR PartType;
2299 NTSTATUS Status;
2300
2301 if (PartitionList == NULL ||
2302 PartitionList->CurrentDisk == NULL ||
2303 PartitionList->CurrentPartition == NULL)
2304 {
2305 /* FIXME: show an error dialog */
2306 return QUIT_PAGE;
2307 }
2308
2309 DiskEntry = PartitionList->CurrentDisk;
2310 PartEntry = PartitionList->CurrentPartition;
2311
2312 MUIDisplayPage(DELETE_PARTITION_PAGE);
2313
2314 /* Determine partition type */
2315 PartType = NULL;
2316 if (PartEntry->New == TRUE)
2317 {
2318 PartType = MUIGetString(STRING_UNFORMATTED);
2319 }
2320 else if (PartEntry->IsPartitioned == TRUE)
2321 {
2322 if ((PartEntry->PartitionType == PARTITION_FAT_12) ||
2323 (PartEntry->PartitionType == PARTITION_FAT_16) ||
2324 (PartEntry->PartitionType == PARTITION_HUGE) ||
2325 (PartEntry->PartitionType == PARTITION_XINT13))
2326 {
2327 PartType = "FAT";
2328 }
2329 else if ((PartEntry->PartitionType == PARTITION_FAT32) ||
2330 (PartEntry->PartitionType == PARTITION_FAT32_XINT13))
2331 {
2332 PartType = "FAT32";
2333 }
2334 else if (PartEntry->PartitionType == PARTITION_EXT2)
2335 {
2336 PartType = "EXT2";
2337 }
2338 else if (PartEntry->PartitionType == PARTITION_IFS)
2339 {
2340 PartType = "NTFS"; /* FIXME: Not quite correct! */
2341 }
2342 else if (IsContainerPartition(PartEntry->PartitionType))
2343 {
2344 PartType = MUIGetString(STRING_EXTENDED_PARTITION);
2345 }
2346 }
2347
2348 PartSize = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
2349 #if 0
2350 if (PartSize >= 10737418240) /* 10 GB */
2351 {
2352 PartSize = PartSize / 1073741824;
2353 Unit = MUIGetString(STRING_GB);
2354 }
2355 else
2356 #endif
2357 if (PartSize >= 10485760) /* 10 MB */
2358 {
2359 PartSize = PartSize / 1048576;
2360 Unit = MUIGetString(STRING_MB);
2361 }
2362 else
2363 {
2364 PartSize = PartSize / 1024;
2365 Unit = MUIGetString(STRING_KB);
2366 }
2367
2368 if (PartType == NULL)
2369 {
2370 CONSOLE_PrintTextXY(6, 10,
2371 MUIGetString(STRING_HDDINFOUNK2),
2372 (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
2373 (PartEntry->DriveLetter == 0) ? '-' : ':',
2374 PartEntry->PartitionType,
2375 PartSize,
2376 Unit);
2377 }
2378 else
2379 {
2380 CONSOLE_PrintTextXY(6, 10,
2381 " %c%c %s %I64u %s",
2382 (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
2383 (PartEntry->DriveLetter == 0) ? '-' : ':',
2384 PartType,
2385 PartSize,
2386 Unit);
2387 }
2388
2389 DiskSize = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
2390 #if 0
2391 if (DiskSize >= 10737418240) /* 10 GB */
2392 {
2393 DiskSize = DiskSize / 1073741824;
2394 Unit = MUIGetString(STRING_GB);
2395 }
2396 else
2397 #endif
2398 {
2399 DiskSize = DiskSize / 1048576;
2400 if (DiskSize == 0)
2401 DiskSize = 1;
2402
2403 Unit = MUIGetString(STRING_MB);
2404 }
2405
2406 if (DiskEntry->DriverName.Length > 0)
2407 {
2408 CONSOLE_PrintTextXY(6, 12,
2409 MUIGetString(STRING_HDINFOPARTDELETE),
2410 DiskSize,
2411 Unit,
2412 DiskEntry->DiskNumber,
2413 DiskEntry->Port,
2414 DiskEntry->Bus,
2415 DiskEntry->Id,
2416 &DiskEntry->DriverName);
2417 }
2418 else
2419 {
2420 CONSOLE_PrintTextXY(6, 12,
2421 MUIGetString(STRING_HDDINFOUNK3),
2422 DiskSize,
2423 Unit,
2424 DiskEntry->DiskNumber,
2425 DiskEntry->Port,
2426 DiskEntry->Bus,
2427 DiskEntry->Id);
2428 }
2429
2430 while (TRUE)
2431 {
2432 CONSOLE_ConInKey(Ir);
2433
2434 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2435 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
2436 {
2437 if (ConfirmQuit(Ir) == TRUE)
2438 {
2439 return QUIT_PAGE;
2440 }
2441
2442 break;
2443 }
2444 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESC */
2445 {
2446 return SELECT_PARTITION_PAGE;
2447 }
2448 else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'D') /* D */
2449 {
2450 DeleteCurrentPartition(PartitionList);
2451
2452 Status = WriteDirtyPartitions(PartitionList);
2453 if (!NT_SUCCESS(Status))
2454 {
2455 DPRINT("WriteDirtyPartitions() failed\n");
2456 MUIDisplayError(ERROR_WRITE_PTABLE, Ir, POPUP_WAIT_ENTER);
2457 return QUIT_PAGE;
2458 }
2459
2460 return SELECT_PARTITION_PAGE;
2461 }
2462 }
2463
2464 return DELETE_PARTITION_PAGE;
2465 }
2466
2467
2468 static PAGE_NUMBER
2469 SelectFileSystemPage(PINPUT_RECORD Ir)
2470 {
2471 PDISKENTRY DiskEntry;
2472 PPARTENTRY PartEntry;
2473 ULONGLONG DiskSize;
2474 ULONGLONG PartSize;
2475 PCHAR DiskUnit;
2476 PCHAR PartUnit;
2477 PCHAR PartType;
2478
2479 if (PartitionList == NULL ||
2480 PartitionList->CurrentDisk == NULL ||
2481 PartitionList->CurrentPartition == NULL)
2482 {
2483 /* FIXME: show an error dialog */
2484 return QUIT_PAGE;
2485 }
2486
2487 DiskEntry = PartitionList->CurrentDisk;
2488 PartEntry = PartitionList->CurrentPartition;
2489
2490 /* adjust disk size */
2491 DiskSize = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
2492 if (DiskSize >= 10737418240) /* 10 GB */
2493 {
2494 DiskSize = DiskSize / 1073741824;
2495 DiskUnit = MUIGetString(STRING_GB);
2496 }
2497 else
2498 {
2499 DiskSize = DiskSize / 1048576;
2500 DiskUnit = MUIGetString(STRING_MB);
2501 }
2502
2503 /* adjust partition size */
2504 PartSize = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
2505 if (PartSize >= 10737418240) /* 10 GB */
2506 {
2507 PartSize = PartSize / 1073741824;
2508 PartUnit = MUIGetString(STRING_GB);
2509 }
2510 else
2511 {
2512 PartSize = PartSize / 1048576;
2513 PartUnit = MUIGetString(STRING_MB);
2514 }
2515
2516 /* adjust partition type */
2517 if ((PartEntry->PartitionType == PARTITION_FAT_12) ||
2518 (PartEntry->PartitionType == PARTITION_FAT_16) ||
2519 (PartEntry->PartitionType == PARTITION_HUGE) ||
2520 (PartEntry->PartitionType == PARTITION_XINT13))
2521 {
2522 PartType = "FAT";
2523 }
2524 else if ((PartEntry->PartitionType == PARTITION_FAT32) ||
2525 (PartEntry->PartitionType == PARTITION_FAT32_XINT13))
2526 {
2527 PartType = "FAT32";
2528 }
2529 else if (PartEntry->PartitionType == PARTITION_EXT2)
2530 {
2531 PartType = "EXT2";
2532 }
2533 else if (PartEntry->PartitionType == PARTITION_IFS)
2534 {
2535 PartType = "NTFS"; /* FIXME: Not quite correct! */
2536 }
2537 else if (PartEntry->PartitionType == PARTITION_ENTRY_UNUSED)
2538 {
2539 PartType = MUIGetString(STRING_FORMATUNUSED);
2540 }
2541 else
2542 {
2543 PartType = MUIGetString(STRING_FORMATUNKNOWN);
2544 }
2545
2546 if (PartEntry->AutoCreate == TRUE)
2547 {
2548 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NEWPARTITION));
2549
2550 #if 0
2551 CONSOLE_PrintTextXY(8, 10, "Partition %lu (%I64u %s) %s of",
2552 PartEntry->PartitionNumber,
2553 PartSize,
2554 PartUnit,
2555 PartType);
2556 #endif
2557
2558 CONSOLE_PrintTextXY(8, 10, MUIGetString(STRING_HDINFOPARTZEROED),
2559 DiskEntry->DiskNumber,
2560 DiskSize,
2561 DiskUnit,
2562 DiskEntry->Port,
2563 DiskEntry->Bus,
2564 DiskEntry->Id,
2565 &DiskEntry->DriverName);
2566
2567 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_PARTFORMAT));
2568
2569
2570 PartEntry->AutoCreate = FALSE;
2571 }
2572 else if (PartEntry->New == TRUE)
2573 {
2574 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDPART));
2575 CONSOLE_SetTextXY(6, 10, MUIGetString(STRING_PARTFORMAT));
2576 }
2577 else
2578 {
2579 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_INSTALLONPART));
2580
2581 if (PartType == NULL)
2582 {
2583 CONSOLE_PrintTextXY(8, 10,
2584 MUIGetString(STRING_HDDINFOUNK4),
2585 (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
2586 (PartEntry->DriveLetter == 0) ? '-' : ':',
2587 PartEntry->PartitionType,
2588 PartSize,
2589 PartUnit);
2590 }
2591 else
2592 {
2593 CONSOLE_PrintTextXY(8, 10,
2594 "%c%c %s %I64u %s",
2595 (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
2596 (PartEntry->DriveLetter == 0) ? '-' : ':',
2597 PartType,
2598 PartSize,
2599 PartUnit);
2600 }
2601
2602 CONSOLE_PrintTextXY(6, 12, MUIGetString(STRING_HDINFOPARTEXISTS),
2603 DiskEntry->DiskNumber,
2604 DiskSize,
2605 DiskUnit,
2606 DiskEntry->Port,
2607 DiskEntry->Bus,
2608 DiskEntry->Id,
2609 &DiskEntry->DriverName);
2610 }
2611
2612 MUIDisplayPage(SELECT_FILE_SYSTEM_PAGE);
2613
2614 if (FileSystemList == NULL)
2615 {
2616 FileSystemList = CreateFileSystemList(6, 26, PartEntry->New, L"FAT");
2617 if (FileSystemList == NULL)
2618 {
2619 /* FIXME: show an error dialog */
2620 return QUIT_PAGE;
2621 }
2622
2623 /* FIXME: Add file systems to list */
2624 }
2625
2626 DrawFileSystemList(FileSystemList);
2627
2628 if (RepairUpdateFlag)
2629 {
2630 return CHECK_FILE_SYSTEM_PAGE;
2631 //return SELECT_PARTITION_PAGE;
2632 }
2633
2634 if (IsUnattendedSetup)
2635 {
2636 if (UnattendFormatPartition)
2637 {
2638 return FORMAT_PARTITION_PAGE;
2639 }
2640
2641 return CHECK_FILE_SYSTEM_PAGE;
2642 }
2643
2644 while (TRUE)
2645 {
2646 CONSOLE_ConInKey(Ir);
2647
2648 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2649 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
2650 {
2651 if (ConfirmQuit(Ir) == TRUE)
2652 {
2653 return QUIT_PAGE;
2654 }
2655
2656 break;
2657 }
2658 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2659 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
2660 {
2661 return SELECT_PARTITION_PAGE;
2662 }
2663 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2664 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
2665 {
2666 ScrollDownFileSystemList(FileSystemList);
2667 }
2668 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2669 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
2670 {
2671 ScrollUpFileSystemList(FileSystemList);
2672 }
2673 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
2674 {
2675 if (!FileSystemList->Selected->FormatFunc)
2676 {
2677 return CHECK_FILE_SYSTEM_PAGE;
2678 }
2679 else
2680 {
2681 return FORMAT_PARTITION_PAGE;
2682 }
2683 }
2684 }
2685
2686 return SELECT_FILE_SYSTEM_PAGE;
2687 }
2688
2689
2690 static ULONG
2691 FormatPartitionPage(PINPUT_RECORD Ir)
2692 {
2693 WCHAR PathBuffer[MAX_PATH];
2694 PDISKENTRY DiskEntry;
2695 PPARTENTRY PartEntry;
2696 NTSTATUS Status;
2697
2698 #ifndef NDEBUG
2699 ULONG Line;
2700 ULONG i;
2701 PLIST_ENTRY Entry;
2702 #endif
2703
2704 MUIDisplayPage(FORMAT_PARTITION_PAGE);
2705
2706 if (PartitionList == NULL ||
2707 PartitionList->CurrentDisk == NULL ||
2708 PartitionList->CurrentPartition == NULL)
2709 {
2710 /* FIXME: show an error dialog */
2711 return QUIT_PAGE;
2712 }
2713
2714 DiskEntry = PartitionList->CurrentDisk;
2715 PartEntry = PartitionList->CurrentPartition;
2716
2717 while (TRUE)
2718 {
2719 if (!IsUnattendedSetup)
2720 {
2721 CONSOLE_ConInKey(Ir);
2722 }
2723
2724 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2725 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
2726 {
2727 if (ConfirmQuit(Ir) == TRUE)
2728 {
2729 return QUIT_PAGE;
2730 }
2731
2732 break;
2733 }
2734 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN || IsUnattendedSetup) /* ENTER */
2735 {
2736 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
2737
2738 if (wcscmp(FileSystemList->Selected->FileSystem, L"FAT") == 0)
2739 {
2740 if (PartEntry->SectorCount.QuadPart < 8192)
2741 {
2742 /* FAT12 CHS partition (disk is smaller than 4.1MB) */
2743 PartEntry->PartitionType = PARTITION_FAT_12;
2744 }
2745 else if (PartEntry->StartSector.QuadPart < 1450560)
2746 {
2747 /* Partition starts below the 8.4GB boundary ==> CHS partition */
2748
2749 if (PartEntry->SectorCount.QuadPart < 65536)
2750 {
2751 /* FAT16 CHS partition (partiton size < 32MB) */
2752 PartEntry->PartitionType = PARTITION_FAT_16;
2753 }
2754 else if (PartEntry->SectorCount.QuadPart < 1048576)
2755 {
2756 /* FAT16 CHS partition (partition size < 512MB) */
2757 PartEntry->PartitionType = PARTITION_HUGE;
2758 }
2759 else
2760 {
2761 /* FAT32 CHS partition (partition size >= 512MB) */
2762 PartEntry->PartitionType = PARTITION_FAT32;
2763 }
2764 }
2765 else
2766 {
2767 /* Partition starts above the 8.4GB boundary ==> LBA partition */
2768
2769 if (PartEntry->SectorCount.QuadPart < 1048576)
2770 {
2771 /* FAT16 LBA partition (partition size < 512MB) */
2772 PartEntry->PartitionType = PARTITION_XINT13;
2773 }
2774 else
2775 {
2776 /* FAT32 LBA partition (partition size >= 512MB) */
2777 PartEntry->PartitionType = PARTITION_FAT32_XINT13;
2778 }
2779 }
2780
2781 DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].PartitionType = PartEntry->PartitionType;
2782 }
2783 #if 0
2784 else if (wcscmp(FileSystemList->Selected->FileSystem, L"EXT2") == 0)
2785 {
2786 PartEntry->PartitionType = PARTITION_EXT2;
2787 DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].PartitionType = PartEntry->PartitionType;
2788 }
2789 #endif
2790 else if (!FileSystemList->Selected->FormatFunc)
2791 return QUIT_PAGE;
2792
2793 #ifndef NDEBUG
2794 CONSOLE_PrintTextXY(6, 12,
2795 "Disk: %I64u Cylinder: %I64u Track: %I64u",
2796 DiskEntry->DiskSize,
2797 DiskEntry->CylinderSize,
2798 DiskEntry->TrackSize);
2799
2800 Line = 13;
2801 DiskEntry = PartitionList->CurrentDisk;
2802 Entry = DiskEntry->PartListHead.Flink;
2803
2804 while (Entry != &DiskEntry->PrimaryPartListHead)
2805 {
2806 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
2807
2808 if (PartEntry->IsPartitioned == TRUE)
2809 {
2810 CONSOLE_PrintTextXY(6, Line,
2811 "%2u: %2u %c %12I64u %12I64u %2u %c",
2812 i,
2813 PartEntry->PartitionNumber,
2814 PartEntry->BootIndicator ? 'A' : '-',
2815 PartEntry->StartSector.QuadPart,
2816 PartEntry->SectorCount.QuadPart,
2817 PartEntry->PartitionType,
2818 PartEntry->Dirty ? '*' : ' ');
2819 Line++;
2820 }
2821
2822 Entry = Entry->Flink;
2823 }
2824
2825 /* Restore the old entry */
2826 PartEntry = PartitionList->CurrentPartition;
2827 #endif
2828
2829 CheckActiveBootPartition(PartitionList);
2830
2831 Status = WriteDirtyPartitions(PartitionList);
2832 if (!NT_SUCCESS(Status))
2833 {
2834 DPRINT("WriteDirtyPartitions() failed\n");
2835 MUIDisplayError(ERROR_WRITE_PTABLE, Ir, POPUP_WAIT_ENTER);
2836 return QUIT_PAGE;
2837 }
2838
2839 /* Set DestinationRootPath */
2840 RtlFreeUnicodeString(&DestinationRootPath);
2841 swprintf(PathBuffer,
2842 L"\\Device\\Harddisk%lu\\Partition%lu",
2843 PartitionList->CurrentDisk->DiskNumber,
2844 PartitionList->CurrentPartition->PartitionNumber);
2845 RtlCreateUnicodeString(&DestinationRootPath,
2846 PathBuffer);
2847 DPRINT("DestinationRootPath: %wZ\n", &DestinationRootPath);
2848
2849 if (FileSystemList->Selected->FormatFunc)
2850 {
2851 Status = FormatPartition(&DestinationRootPath,
2852 FileSystemList->Selected);
2853 if (!NT_SUCCESS(Status))
2854 {
2855 DPRINT1("FormatPartition() failed with status 0x%08lx\n", Status);
2856 /* FIXME: show an error dialog */
2857 return QUIT_PAGE;
2858 }
2859
2860 PartEntry->New = FALSE;
2861
2862 }
2863
2864 #ifndef NDEBUG
2865 CONSOLE_SetStatusText(" Done. Press any key ...");
2866 CONSOLE_ConInKey(Ir);
2867 #endif
2868
2869 DestroyFileSystemList(FileSystemList);
2870 FileSystemList = NULL;
2871 return INSTALL_DIRECTORY_PAGE;
2872 }
2873 }
2874
2875 return FORMAT_PARTITION_PAGE;
2876 }
2877
2878
2879 static ULONG
2880 CheckFileSystemPage(PINPUT_RECORD Ir)
2881 {
2882 PFILE_SYSTEM_ITEM CurrentFileSystem;
2883 WCHAR PathBuffer[MAX_PATH];
2884 CHAR Buffer[MAX_PATH];
2885 NTSTATUS Status;
2886
2887 /* FIXME: code duplicated in FormatPartitionPage */
2888 /* Set DestinationRootPath */
2889 RtlFreeUnicodeString(&DestinationRootPath);
2890 swprintf(PathBuffer,
2891 L"\\Device\\Harddisk%lu\\Partition%lu",
2892 PartitionList->CurrentDisk->DiskNumber,
2893 PartitionList->CurrentPartition->PartitionNumber);
2894 RtlCreateUnicodeString(&DestinationRootPath, PathBuffer);
2895 DPRINT("DestinationRootPath: %wZ\n", &DestinationRootPath);
2896
2897 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHECKINGPART));
2898
2899 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
2900
2901 /* WRONG: first filesystem is not necesseraly the one of the current partition! */
2902 CurrentFileSystem = CONTAINING_RECORD(FileSystemList->ListHead.Flink, FILE_SYSTEM_ITEM, ListEntry);
2903
2904 if (!CurrentFileSystem->ChkdskFunc)
2905 {
2906 sprintf(Buffer,
2907 "Setup is currently unable to check a partition formatted in %S.\n"
2908 "\n"
2909 " \x07 Press ENTER to continue Setup.\n"
2910 " \x07 Press F3 to quit Setup.",
2911 CurrentFileSystem->FileSystem);
2912
2913 PopupError(Buffer,
2914 MUIGetString(STRING_QUITCONTINUE),
2915 NULL, POPUP_WAIT_NONE);
2916
2917 while (TRUE)
2918 {
2919 CONSOLE_ConInKey(Ir);
2920
2921 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x00 &&
2922 Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3) /* F3 */
2923 {
2924 if (ConfirmQuit(Ir))
2925 return QUIT_PAGE;
2926 else
2927 return CHECK_FILE_SYSTEM_PAGE;
2928 }
2929 else if (Ir->Event.KeyEvent.uChar.AsciiChar == VK_RETURN) /* ENTER */
2930 {
2931 return INSTALL_DIRECTORY_PAGE;
2932 }
2933 }
2934 }
2935 else
2936 {
2937 Status = ChkdskPartition(&DestinationRootPath, CurrentFileSystem);
2938 if (!NT_SUCCESS(Status))
2939 {
2940 DPRINT("ChkdskPartition() failed with status 0x%08lx\n", Status);
2941 sprintf(Buffer, "Setup failed to verify the selected partition.\n"
2942 "(Status 0x%08lx).\n", Status);
2943
2944 PopupError(Buffer,
2945 MUIGetString(STRING_REBOOTCOMPUTER),
2946 Ir, POPUP_WAIT_ENTER);
2947
2948 return QUIT_PAGE;
2949 }
2950
2951 return INSTALL_DIRECTORY_PAGE;
2952 }
2953 }
2954
2955
2956 static PAGE_NUMBER
2957 InstallDirectoryPage1(PWCHAR InstallDir,
2958 PDISKENTRY DiskEntry,
2959 PPARTENTRY PartEntry)
2960 {
2961 WCHAR PathBuffer[MAX_PATH];
2962
2963 /* Create 'InstallPath' string */
2964 RtlFreeUnicodeString(&InstallPath);
2965 RtlCreateUnicodeString(&InstallPath,
2966 InstallDir);
2967
2968 /* Create 'DestinationPath' string */
2969 RtlFreeUnicodeString(&DestinationPath);
2970 wcscpy(PathBuffer, DestinationRootPath.Buffer);
2971
2972 if (InstallDir[0] != L'\\')
2973 wcscat(PathBuffer, L"\\");
2974
2975 wcscat(PathBuffer, InstallDir);
2976 RtlCreateUnicodeString(&DestinationPath, PathBuffer);
2977
2978 /* Create 'DestinationArcPath' */
2979 RtlFreeUnicodeString(&DestinationArcPath);
2980 swprintf(PathBuffer,
2981 L"multi(0)disk(0)rdisk(%lu)partition(%lu)",
2982 DiskEntry->BiosDiskNumber,
2983 PartEntry->PartitionNumber);
2984
2985 if (InstallDir[0] != L'\\')
2986 wcscat(PathBuffer, L"\\");
2987
2988 wcscat(PathBuffer, InstallDir);
2989 RtlCreateUnicodeString(&DestinationArcPath, PathBuffer);
2990
2991 return PREPARE_COPY_PAGE;
2992 }
2993
2994
2995 static PAGE_NUMBER
2996 InstallDirectoryPage(PINPUT_RECORD Ir)
2997 {
2998 PDISKENTRY DiskEntry;
2999 PPARTENTRY PartEntry;
3000 WCHAR InstallDir[51];
3001 ULONG Length;
3002
3003 if (PartitionList == NULL ||
3004 PartitionList->CurrentDisk == NULL ||
3005 PartitionList->CurrentPartition == NULL)
3006 {
3007 /* FIXME: show an error dialog */
3008 return QUIT_PAGE;
3009 }
3010
3011 DiskEntry = PartitionList->CurrentDisk;
3012 PartEntry = PartitionList->CurrentPartition;
3013
3014 if (IsUnattendedSetup)
3015 wcscpy(InstallDir, UnattendInstallationDirectory);
3016 else
3017 wcscpy(InstallDir, L"\\ReactOS");
3018
3019 Length = wcslen(InstallDir);
3020 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
3021 MUIDisplayPage(INSTALL_DIRECTORY_PAGE);
3022
3023 if (IsUnattendedSetup)
3024 {
3025 return InstallDirectoryPage1(InstallDir,
3026 DiskEntry,
3027 PartEntry);
3028 }
3029
3030 while (TRUE)
3031 {
3032 CONSOLE_ConInKey(Ir);
3033
3034 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3035 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
3036 {
3037 if (ConfirmQuit(Ir) == TRUE)
3038 return QUIT_PAGE;
3039
3040 break;
3041 }
3042 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
3043 {
3044 return InstallDirectoryPage1(InstallDir,
3045 DiskEntry,
3046 PartEntry);
3047 }
3048 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x08) /* BACKSPACE */
3049 {
3050 if (Length > 0)
3051 {
3052 Length--;
3053 InstallDir[Length] = 0;
3054 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
3055 }
3056 }
3057 else if (isprint(Ir->Event.KeyEvent.uChar.AsciiChar))
3058 {
3059 if (Length < 50)
3060 {
3061 InstallDir[Length] = (WCHAR)Ir->Event.KeyEvent.uChar.AsciiChar;
3062 Length++;
3063 InstallDir[Length] = 0;
3064 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
3065 }
3066 }
3067 }
3068
3069 return INSTALL_DIRECTORY_PAGE;
3070 }
3071
3072
3073 static BOOLEAN
3074 AddSectionToCopyQueueCab(HINF InfFile,
3075 PWCHAR SectionName,
3076 PWCHAR SourceCabinet,
3077 PCUNICODE_STRING DestinationPath,
3078 PINPUT_RECORD Ir)
3079 {
3080 INFCONTEXT FilesContext;
3081 INFCONTEXT DirContext;
3082 PWCHAR FileKeyName;
3083 PWCHAR FileKeyValue;
3084 PWCHAR DirKeyValue;
3085 PWCHAR TargetFileName;
3086
3087 /* Search for the SectionName section */
3088 if (!SetupFindFirstLineW(InfFile, SectionName, NULL, &FilesContext))
3089 {
3090 char Buffer[128];
3091 sprintf(Buffer, MUIGetString(STRING_TXTSETUPFAILED), SectionName);
3092 PopupError(Buffer, MUIGetString(STRING_REBOOTCOMPUTER), Ir, POPUP_WAIT_ENTER);
3093 return FALSE;
3094 }
3095
3096 /*
3097 * Enumerate the files in the section
3098 * and add them to the file queue.
3099 */
3100 do
3101 {
3102 /* Get source file name and target directory id */
3103 if (!INF_GetData(&FilesContext, &FileKeyName, &FileKeyValue))
3104 {
3105 /* FIXME: Handle error! */
3106 DPRINT1("INF_GetData() failed\n");
3107 break;
3108 }
3109
3110 /* Get optional target file name */
3111 if (!INF_GetDataField(&FilesContext, 2, &TargetFileName))
3112 TargetFileName = NULL;
3113
3114 DPRINT("FileKeyName: '%S' FileKeyValue: '%S'\n", FileKeyName, FileKeyValue);
3115
3116 /* Lookup target directory */
3117 if (!SetupFindFirstLineW(InfFile, L"Directories", FileKeyValue, &DirContext))
3118 {
3119 /* FIXME: Handle error! */
3120 DPRINT1("SetupFindFirstLine() failed\n");
3121 break;
3122 }
3123
3124 if (!INF_GetData(&DirContext, NULL, &DirKeyValue))
3125 {
3126 /* FIXME: Handle error! */
3127 DPRINT1("INF_GetData() failed\n");
3128 break;
3129 }
3130
3131 if (!SetupQueueCopy(SetupFileQueue,
3132 SourceCabinet,
3133 SourceRootPath.Buffer,
3134 SourceRootDir.Buffer,
3135 FileKeyName,
3136 DirKeyValue,
3137 TargetFileName))
3138 {
3139 /* FIXME: Handle error! */
3140 DPRINT1("SetupQueueCopy() failed\n");
3141 }
3142 } while (SetupFindNextLine(&FilesContext, &FilesContext));
3143
3144 return TRUE;
3145 }
3146
3147
3148 static BOOLEAN
3149 AddSectionToCopyQueue(HINF InfFile,
3150 PWCHAR SectionName,
3151 PWCHAR SourceCabinet,
3152 PCUNICODE_STRING DestinationPath,
3153 PINPUT_RECORD Ir)
3154 {
3155 INFCONTEXT FilesContext;
3156 INFCONTEXT DirContext;
3157 PWCHAR FileKeyName;
3158 PWCHAR FileKeyValue;
3159 PWCHAR DirKeyValue;
3160 PWCHAR TargetFileName;
3161 WCHAR CompleteOrigFileName[512];
3162
3163 if (SourceCabinet)
3164 return AddSectionToCopyQueueCab(InfFile, L"SourceFiles", SourceCabinet, DestinationPath, Ir);
3165
3166 /* Search for the SectionName section */
3167 if (!SetupFindFirstLineW(InfFile, SectionName, NULL, &FilesContext))
3168 {
3169 char Buffer[128];
3170 sprintf(Buffer, MUIGetString(STRING_TXTSETUPFAILED), SectionName);
3171 PopupError(Buffer, MUIGetString(STRING_REBOOTCOMPUTER), Ir, POPUP_WAIT_ENTER);
3172 return FALSE;
3173 }
3174
3175 /*
3176 * Enumerate the files in the section
3177 * and add them to the file queue.
3178 */
3179 do
3180 {
3181 /* Get source file name and target directory id */
3182 if (!INF_GetData(&FilesContext, &FileKeyName, &FileKeyValue))
3183 {
3184 /* FIXME: Handle error! */
3185 DPRINT1("INF_GetData() failed\n");
3186 break;
3187 }
3188
3189 /* Get target directory id */
3190 if (!INF_GetDataField(&FilesContext, 13, &FileKeyValue))
3191 {
3192 /* FIXME: Handle error! */
3193 DPRINT1("INF_GetData() failed\n");
3194 break;
3195 }
3196
3197 /* Get optional target file name */
3198 if (!INF_GetDataField(&FilesContext, 11, &TargetFileName))
3199 TargetFileName = NULL;
3200 else if (!*TargetFileName)
3201 TargetFileName = NULL;
3202
3203 DPRINT("FileKeyName: '%S' FileKeyValue: '%S'\n", FileKeyName, FileKeyValue);
3204
3205 /* Lookup target directory */
3206 if (!SetupFindFirstLineW(InfFile, L"Directories", FileKeyValue, &DirContext))
3207 {
3208 /* FIXME: Handle error! */
3209 DPRINT1("SetupFindFirstLine() failed\n");
3210 break;
3211 }
3212
3213 if (!INF_GetData(&DirContext, NULL, &DirKeyValue))
3214 {
3215 /* FIXME: Handle error! */
3216 DPRINT1("INF_GetData() failed\n");
3217 break;
3218 }
3219
3220 wcscpy(CompleteOrigFileName, SourceRootDir.Buffer);
3221 wcscat(CompleteOrigFileName, L"\\");
3222 wcscat(CompleteOrigFileName, DirKeyValue);
3223
3224 if (!SetupQueueCopy(SetupFileQueue,
3225 SourceCabinet,
3226 SourceRootPath.Buffer,
3227 CompleteOrigFileName,
3228 FileKeyName,
3229 DirKeyValue,
3230 TargetFileName))
3231 {
3232 /* FIXME: Handle error! */
3233 DPRINT1("SetupQueueCopy() failed\n");
3234 }
3235 } while (SetupFindNextLine(&FilesContext, &FilesContext));
3236
3237 return TRUE;
3238 }
3239
3240
3241 static BOOLEAN
3242 PrepareCopyPageInfFile(HINF InfFile,
3243 PWCHAR SourceCabinet,
3244 PINPUT_RECORD Ir)
3245 {
3246 WCHAR PathBuffer[MAX_PATH];
3247 INFCONTEXT DirContext;
3248 PWCHAR AdditionalSectionName = NULL;
3249 PWCHAR KeyValue;
3250 ULONG Length;
3251 NTSTATUS Status;
3252
3253 /* Add common files */
3254 if (!AddSectionToCopyQueue(InfFile, L"SourceDisksFiles", SourceCabinet, &DestinationPath, Ir))
3255 return FALSE;
3256
3257 /* Add specific files depending of computer type */
3258 if (SourceCabinet == NULL)
3259 {
3260 if (!ProcessComputerFiles(InfFile, ComputerList, &AdditionalSectionName))
3261 return FALSE;
3262
3263 if (AdditionalSectionName)
3264 {
3265 if (!AddSectionToCopyQueue(InfFile, AdditionalSectionName, SourceCabinet, &DestinationPath, Ir))
3266 return FALSE;
3267 }
3268 }
3269
3270 /* Create directories */
3271
3272 /*
3273 * FIXME:
3274 * Install directories like '\reactos\test' are not handled yet.
3275 */
3276
3277 /* Get destination path */
3278 wcscpy(PathBuffer, DestinationPath.Buffer);
3279
3280 /* Remove trailing backslash */
3281 Length = wcslen(PathBuffer);
3282 if ((Length > 0) && (PathBuffer[Length - 1] == '\\'))
3283 {
3284 PathBuffer[Length - 1] = 0;
3285 }
3286
3287 /* Create the install directory */
3288 Status = SetupCreateDirectory(PathBuffer);
3289 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION)
3290 {
3291 DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer, Status);
3292 MUIDisplayError(ERROR_CREATE_INSTALL_DIR, Ir, POPUP_WAIT_ENTER);
3293 return FALSE;
3294 }
3295
3296 /* Search for the 'Directories' section */
3297 if (!SetupFindFirstLineW(InfFile, L"Directories", NULL, &DirContext))
3298 {
3299 if (SourceCabinet)
3300 {
3301 MUIDisplayError(ERROR_CABINET_SECTION, Ir, POPUP_WAIT_ENTER);
3302 }
3303 else
3304 {
3305 MUIDisplayError(ERROR_TXTSETUP_SECTION, Ir, POPUP_WAIT_ENTER);
3306 }
3307
3308 return FALSE;
3309 }
3310
3311 /* Enumerate the directory values and create the subdirectories */
3312 do
3313 {
3314 if (!INF_GetData(&DirContext, NULL, &KeyValue))
3315 {
3316 DPRINT1("break\n");
3317 break;
3318 }
3319
3320 if (KeyValue[0] == L'\\' && KeyValue[1] != 0)
3321 {
3322 DPRINT("Absolute Path: '%S'\n", KeyValue);
3323
3324 wcscpy(PathBuffer, DestinationRootPath.Buffer);
3325 wcscat(PathBuffer, KeyValue);
3326
3327 DPRINT("FullPath: '%S'\n", PathBuffer);
3328 }
3329 else if (KeyValue[0] != L'\\')
3330 {
3331 DPRINT("RelativePath: '%S'\n", KeyValue);
3332 wcscpy(PathBuffer, DestinationPath.Buffer);
3333 wcscat(PathBuffer, L"\\");
3334 wcscat(PathBuffer, KeyValue);
3335
3336 DPRINT("FullPath: '%S'\n", PathBuffer);
3337
3338 Status = SetupCreateDirectory(PathBuffer);
3339 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION)
3340 {
3341 DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer, Status);
3342 MUIDisplayError(ERROR_CREATE_DIR, Ir, POPUP_WAIT_ENTER);
3343 return FALSE;
3344 }
3345 }
3346 } while (SetupFindNextLine (&DirContext, &DirContext));
3347
3348 return TRUE;
3349 }
3350
3351
3352 static PAGE_NUMBER
3353 PrepareCopyPage(PINPUT_RECORD Ir)
3354 {
3355 HINF InfHandle;
3356 WCHAR PathBuffer[MAX_PATH];
3357 INFCONTEXT CabinetsContext;
3358 ULONG InfFileSize;
3359 PWCHAR KeyValue;
3360 UINT ErrorLine;
3361 PVOID InfFileData;
3362
3363 MUIDisplayPage(PREPARE_COPY_PAGE);
3364
3365 /* Create the file queue */
3366 SetupFileQueue = SetupOpenFileQueue();
3367 if (SetupFileQueue == NULL)
3368 {
3369 MUIDisplayError(ERROR_COPY_QUEUE, Ir, POPUP_WAIT_ENTER);
3370 return(QUIT_PAGE);
3371 }
3372
3373 if (!PrepareCopyPageInfFile(SetupInf, NULL, Ir))
3374 {
3375 return QUIT_PAGE;
3376 }
3377
3378 /* Search for the 'Cabinets' section */
3379 if (!SetupFindFirstLineW(SetupInf, L"Cabinets", NULL, &CabinetsContext))
3380 {
3381 return FILE_COPY_PAGE;
3382 }
3383
3384 /*
3385 * Enumerate the directory values in the 'Cabinets'
3386 * section and parse their inf files.
3387 */
3388 do
3389 {
3390 if (!INF_GetData(&CabinetsContext, NULL, &KeyValue))
3391 break;
3392
3393 wcscpy(PathBuffer, SourcePath.Buffer);
3394 wcscat(PathBuffer, L"\\");
3395 wcscat(PathBuffer, KeyValue);
3396
3397 #ifdef __REACTOS__
3398 CabinetInitialize();
3399 CabinetSetEventHandlers(NULL, NULL, NULL);
3400 CabinetSetCabinetName(PathBuffer);
3401
3402 if (CabinetOpen() == CAB_STATUS_SUCCESS)
3403 {
3404 DPRINT("Cabinet %S\n", CabinetGetCabinetName());
3405
3406 InfFileData = CabinetGetCabinetReservedArea(&InfFileSize);
3407 if (InfFileData == NULL)
3408 {
3409 MUIDisplayError(ERROR_CABINET_SCRIPT, Ir, POPUP_WAIT_ENTER);
3410 return QUIT_PAGE;
3411 }
3412 }
3413 else
3414 {
3415 DPRINT("Cannot open cabinet: %S.\n", CabinetGetCabinetName());
3416 MUIDisplayError(ERROR_CABINET_MISSING, Ir, POPUP_WAIT_ENTER);
3417 return QUIT_PAGE;
3418 }
3419
3420 InfHandle = INF_OpenBufferedFileA((CHAR*) InfFileData,
3421 InfFileSize,
3422 (const CHAR*) NULL,
3423 INF_STYLE_WIN4,
3424 LanguageId,
3425 &ErrorLine);
3426
3427 if (InfHandle == INVALID_HANDLE_VALUE)
3428 {
3429 MUIDisplayError(ERROR_INVALID_CABINET_INF, Ir, POPUP_WAIT_ENTER);
3430 return QUIT_PAGE;
3431 }
3432
3433 CabinetCleanup();
3434
3435 if (!PrepareCopyPageInfFile(InfHandle, KeyValue, Ir))
3436 {
3437 return QUIT_PAGE;
3438 }
3439 #endif
3440 } while (SetupFindNextLine(&CabinetsContext, &CabinetsContext));
3441
3442 return FILE_COPY_PAGE;
3443 }
3444
3445
3446 VOID
3447 NTAPI
3448 SetupUpdateMemoryInfo(IN PCOPYCONTEXT CopyContext,
3449 IN BOOLEAN First)
3450 {
3451 SYSTEM_PERFORMANCE_INFORMATION PerfInfo;
3452
3453 /* Get the memory information from the system */
3454 NtQuerySystemInformation(SystemPerformanceInformation,
3455 &PerfInfo,
3456 sizeof(PerfInfo),
3457 NULL);
3458
3459 /* Check if this is initial setup */
3460 if (First)
3461 {
3462 /* Set maximum limits to be total RAM pages */
3463 ProgressSetStepCount(CopyContext->MemoryBars[0], PerfInfo.CommitLimit);
3464 ProgressSetStepCount(CopyContext->MemoryBars[1], PerfInfo.CommitLimit);
3465 ProgressSetStepCount(CopyContext->MemoryBars[2], PerfInfo.CommitLimit);
3466 }
3467
3468 /* Set current values */
3469 ProgressSetStep(CopyContext->MemoryBars[0], PerfInfo.PagedPoolPages + PerfInfo.NonPagedPoolPages);
3470 ProgressSetStep(CopyContext->MemoryBars[1], PerfInfo.ResidentSystemCachePage);
3471 ProgressSetStep(CopyContext->MemoryBars[2], PerfInfo.AvailablePages);
3472 }
3473
3474
3475 static UINT
3476 CALLBACK
3477 FileCopyCallback(PVOID Context,
3478 UINT Notification,
3479 UINT_PTR Param1,
3480 UINT_PTR Param2)
3481 {
3482 PCOPYCONTEXT CopyContext;
3483
3484 CopyContext = (PCOPYCONTEXT)Context;
3485
3486 switch (Notification)
3487 {
3488 case SPFILENOTIFY_STARTSUBQUEUE:
3489 CopyContext->TotalOperations = (ULONG)Param2;
3490 ProgressSetStepCount(CopyContext->ProgressBar,
3491 CopyContext->TotalOperations);
3492 SetupUpdateMemoryInfo(CopyContext, TRUE);
3493 break;
3494
3495 case SPFILENOTIFY_STARTCOPY:
3496 /* Display copy message */
3497 CONSOLE_SetStatusText(MUIGetString(STRING_COPYING), (PWSTR)Param1);
3498 SetupUpdateMemoryInfo(CopyContext, FALSE);
3499 break;
3500
3501 case SPFILENOTIFY_ENDCOPY:
3502 CopyContext->CompletedOperations++;
3503
3504 /* SYSREG checkpoint */
3505 if (CopyContext->TotalOperations >> 1 == CopyContext->CompletedOperations)
3506 DPRINT1("CHECKPOINT:HALF_COPIED\n");
3507
3508 ProgressNextStep(CopyContext->ProgressBar);
3509 SetupUpdateMemoryInfo(CopyContext, FALSE);
3510 break;
3511 }
3512
3513 return 0;
3514 }
3515
3516
3517 static
3518 PAGE_NUMBER
3519 FileCopyPage(PINPUT_RECORD Ir)
3520 {
3521 COPYCONTEXT CopyContext;
3522 unsigned int mem_bar_width;
3523
3524 MUIDisplayPage(FILE_COPY_PAGE);
3525
3526 /* Create context for the copy process */
3527 CopyContext.DestinationRootPath = DestinationRootPath.Buffer;
3528 CopyContext.InstallPath = InstallPath.Buffer;
3529 CopyContext.TotalOperations = 0;
3530 CopyContext.CompletedOperations = 0;
3531
3532 /* Create the progress bar as well */
3533 CopyContext.ProgressBar = CreateProgressBar(13,
3534 26,
3535 xScreen - 13,
3536 yScreen - 20,
3537 10,
3538 24,
3539 TRUE,
3540 MUIGetString(STRING_SETUPCOPYINGFILES));
3541
3542 // fit memory bars to screen width, distribute them uniform
3543 mem_bar_width = (xScreen - 26) / 5;
3544 mem_bar_width -= mem_bar_width % 2; // make even
3545 /* ATTENTION: The following progress bars are debug stuff, which should not be translated!! */
3546 /* Create the paged pool progress bar */
3547 CopyContext.MemoryBars[0] = CreateProgressBar(13,
3548 40,
3549 13 + mem_bar_width,
3550 43,
3551 13,
3552 44,
3553 FALSE,
3554 "Kernel Pool");
3555
3556 /* Create the non paged pool progress bar */
3557 CopyContext.MemoryBars[1] = CreateProgressBar((xScreen / 2)- (mem_bar_width / 2),
3558 40,
3559 (xScreen / 2) + (mem_bar_width / 2),
3560 43,
3561 (xScreen / 2)- (mem_bar_width / 2),
3562 44,
3563 FALSE,
3564 "Kernel Cache");
3565
3566 /* Create the global memory progress bar */
3567 CopyContext.MemoryBars[2] = CreateProgressBar(xScreen - 13 - mem_bar_width,
3568 40,
3569 xScreen - 13,
3570 43,
3571 xScreen - 13 - mem_bar_width,
3572 44,
3573 FALSE,
3574 "Free Memory");
3575
3576 /* Do the file copying */
3577 SetupCommitFileQueueW(NULL,
3578 SetupFileQueue,
3579 FileCopyCallback,
3580 &CopyContext);
3581
3582 /* If we get here, we're done, so cleanup the queue and progress bar */
3583 SetupCloseFileQueue(SetupFileQueue);
3584 DestroyProgressBar(CopyContext.ProgressBar);
3585 DestroyProgressBar(CopyContext.MemoryBars[0]);
3586 DestroyProgressBar(CopyContext.MemoryBars[1]);
3587 DestroyProgressBar(CopyContext.MemoryBars[2]);
3588
3589 /* Go display the next page */
3590 return REGISTRY_PAGE;
3591 }
3592
3593
3594 static PAGE_NUMBER
3595 RegistryPage(PINPUT_RECORD Ir)
3596 {
3597 INFCONTEXT InfContext;
3598 PWSTR Action;
3599 PWSTR File;
3600 PWSTR Section;
3601 BOOLEAN Delete;
3602 NTSTATUS Status;
3603
3604 MUIDisplayPage(REGISTRY_PAGE);
3605
3606 if (RepairUpdateFlag)
3607 {
3608 return SUCCESS_PAGE;
3609 }
3610
3611 if (!SetInstallPathValue(&DestinationPath))
3612 {
3613 DPRINT("SetInstallPathValue() failed\n");
3614 MUIDisplayError(ERROR_INITIALIZE_REGISTRY, Ir, POPUP_WAIT_ENTER);
3615 return QUIT_PAGE;
3616 }
3617
3618 /* Create the default hives */
3619 #ifdef __REACTOS__
3620 Status = NtInitializeRegistry(CM_BOOT_FLAG_SETUP);
3621 if (!NT_SUCCESS(Status))
3622 {
3623 DPRINT("NtInitializeRegistry() failed (Status %lx)\n", Status);
3624 MUIDisplayError(ERROR_CREATE_HIVE, Ir, POPUP_WAIT_ENTER);
3625 return QUIT_PAGE;
3626 }
3627 #else
3628 RegInitializeRegistry();
3629 #endif
3630
3631 /* Update registry */
3632 CONSOLE_SetStatusText(MUIGetString(STRING_REGHIVEUPDATE));
3633
3634 if (!SetupFindFirstLineW(SetupInf, L"HiveInfs.Install", NULL, &InfContext))
3635 {
3636 DPRINT1("SetupFindFirstLine() failed\n");
3637 MUIDisplayError(ERROR_FIND_REGISTRY, Ir, POPUP_WAIT_ENTER);
3638 return QUIT_PAGE;
3639 }
3640
3641 do
3642 {
3643 INF_GetDataField (&InfContext, 0, &Action);
3644 INF_GetDataField (&InfContext, 1, &File);
3645 INF_GetDataField (&InfContext, 2, &Section);
3646
3647 DPRINT("Action: %S File: %S Section %S\n", Action, File, Section);
3648
3649 if (Action == NULL)
3650 break; // Hackfix
3651
3652 if (!_wcsicmp (Action, L"AddReg"))
3653 {
3654 Delete = FALSE;
3655 }
3656 else if (!_wcsicmp (Action, L"DelReg"))
3657 {
3658 Delete = TRUE;
3659 }
3660 else
3661 {
3662 continue;
3663 }
3664
3665 CONSOLE_SetStatusText(MUIGetString(STRING_IMPORTFILE), File);
3666
3667 if (!ImportRegistryFile(File, Section, LanguageId, Delete))
3668 {
3669 DPRINT("Importing %S failed\n", File);
3670
3671 MUIDisplayError(ERROR_IMPORT_HIVE, Ir, POPUP_WAIT_ENTER);
3672 return QUIT_PAGE;
3673 }
3674 } while (SetupFindNextLine(&InfContext, &InfContext));
3675
3676 /* Update display registry settings */
3677 CONSOLE_SetStatusText(MUIGetString(STRING_DISPLAYETTINGSUPDATE));
3678 if (!ProcessDisplayRegistry(SetupInf, DisplayList))
3679 {
3680 MUIDisplayError(ERROR_UPDATE_DISPLAY_SETTINGS, Ir, POPUP_WAIT_ENTER);
3681 return QUIT_PAGE;
3682 }
3683
3684 /* Set the locale */
3685 CONSOLE_SetStatusText(MUIGetString(STRING_LOCALESETTINGSUPDATE));
3686 if (!ProcessLocaleRegistry(LanguageList))
3687 {
3688 MUIDisplayError(ERROR_UPDATE_LOCALESETTINGS, Ir, POPUP_WAIT_ENTER);
3689 return QUIT_PAGE;
3690 }
3691
3692 /* Add keyboard layouts */
3693 CONSOLE_SetStatusText(MUIGetString(STRING_ADDKBLAYOUTS));
3694 if (!AddKeyboardLayouts())
3695 {
3696 MUIDisplayError(ERROR_ADDING_KBLAYOUTS, Ir, POPUP_WAIT_ENTER);
3697 return QUIT_PAGE;
3698 }
3699
3700 /* Set GeoID */
3701
3702 if (!SetGeoID(MUIGetGeoID()))
3703 {
3704 MUIDisplayError(ERROR_UPDATE_GEOID, Ir, POPUP_WAIT_ENTER);
3705 return QUIT_PAGE;
3706 }
3707
3708 if (!IsUnattendedSetup)
3709 {
3710 /* Update keyboard layout settings */
3711 CONSOLE_SetStatusText(MUIGetString(STRING_KEYBOARDSETTINGSUPDATE));
3712 if (!ProcessKeyboardLayoutRegistry(LayoutList))
3713 {
3714 MUIDisplayError(ERROR_UPDATE_KBSETTINGS, Ir, POPUP_WAIT_ENTER);
3715 return QUIT_PAGE;
3716 }
3717 }
3718
3719 /* Add codepage information to registry */
3720 CONSOLE_SetStatusText(MUIGetString(STRING_CODEPAGEINFOUPDATE));
3721 if (!AddCodePage())
3722 {
3723 MUIDisplayError(ERROR_ADDING_CODEPAGE, Ir, POPUP_WAIT_ENTER);
3724 return QUIT_PAGE;
3725 }
3726
3727 /* Set the default pagefile entry */
3728 SetDefaultPagefile(DestinationDriveLetter);
3729
3730 /* Update the mounted devices list */
3731 SetMountedDeviceValues(PartitionList);
3732
3733 CONSOLE_SetStatusText(MUIGetString(STRING_DONE));
3734
3735 return BOOT_LOADER_PAGE;
3736 }
3737
3738
3739 static PAGE_NUMBER
3740 BootLoaderPage(PINPUT_RECORD Ir)
3741 {
3742 UCHAR PartitionType;
3743 BOOLEAN InstallOnFloppy;
3744 USHORT Line = 12;
3745 WCHAR PathBuffer[MAX_PATH];
3746 NTSTATUS Status;
3747
3748 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
3749
3750 /* Find or set the active partition */
3751 CheckActiveBootPartition(PartitionList);
3752
3753 /* Update the partition table because we may have changed the active partition */
3754 Status = WriteDirtyPartitions(PartitionList);
3755 if (!NT_SUCCESS(Status))
3756 {
3757 DPRINT("WriteDirtyPartitions() failed\n");
3758 MUIDisplayError(ERROR_WRITE_PTABLE, Ir, POPUP_WAIT_ENTER);
3759 return QUIT_PAGE;
3760 }
3761
3762 RtlFreeUnicodeString(&SystemRootPath);
3763 swprintf(PathBuffer,
3764 L"\\Device\\Harddisk%lu\\Partition%lu",
3765 PartitionList->ActiveBootDisk->DiskNumber,
3766 PartitionList->ActiveBootPartition->PartitionNumber);
3767 RtlCreateUnicodeString(&SystemRootPath,
3768 PathBuffer);
3769 DPRINT("SystemRootPath: %wZ\n", &SystemRootPath);
3770
3771 PartitionType = PartitionList->ActiveBootPartition->PartitionType;
3772
3773 if (IsUnattendedSetup)
3774 {
3775 if (UnattendMBRInstallType == 0) /* skip MBR installation */
3776 {
3777 return SUCCESS_PAGE;
3778 }
3779 else if (UnattendMBRInstallType == 1) /* install on floppy */
3780 {
3781 return BOOT_LOADER_FLOPPY_PAGE;
3782 }
3783 }
3784
3785 if (PartitionType == PARTITION_ENTRY_UNUSED)
3786 {
3787 DPRINT("Error: active partition invalid (unused)\n");
3788 InstallOnFloppy = TRUE;
3789 }
3790 else if (PartitionType == 0x0A)
3791 {
3792 /* OS/2 boot manager partition */
3793 DPRINT("Found OS/2 boot manager partition\n");
3794 InstallOnFloppy = TRUE;
3795 }
3796 else if (PartitionType == 0x83)
3797 {
3798 /* Linux ext2 partition */
3799 DPRINT("Found Linux ext2 partition\n");
3800 InstallOnFloppy = TRUE;
3801 }
3802 else if (PartitionType == PARTITION_IFS)
3803 {
3804 /* NTFS partition */
3805 DPRINT("Found NTFS partition\n");
3806 InstallOnFloppy = TRUE;
3807 }
3808 else if ((PartitionType == PARTITION_FAT_12) ||
3809 (PartitionType == PARTITION_FAT_16) ||
3810 (PartitionType == PARTITION_HUGE) ||
3811 (PartitionType == PARTITION_XINT13) ||
3812 (PartitionType == PARTITION_FAT32) ||
3813 (PartitionType == PARTITION_FAT32_XINT13))
3814 {
3815 DPRINT("Found FAT partition\n");
3816 InstallOnFloppy = FALSE;
3817 }
3818 else
3819 {
3820 /* Unknown partition */
3821 DPRINT("Unknown partition found\n");
3822 InstallOnFloppy = TRUE;
3823 }
3824
3825 if (InstallOnFloppy == TRUE)
3826 {
3827 return BOOT_LOADER_FLOPPY_PAGE;
3828 }
3829
3830 /* Unattended install on hdd? */
3831 if (IsUnattendedSetup && UnattendMBRInstallType == 2)
3832 {
3833 return BOOT_LOADER_HARDDISK_MBR_PAGE;
3834 }
3835
3836 MUIDisplayPage(BOOT_LOADER_PAGE);
3837 CONSOLE_InvertTextXY(8, Line, 60, 1);
3838
3839 while (TRUE)
3840 {
3841 CONSOLE_ConInKey(Ir);
3842
3843 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3844 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
3845 {
3846 CONSOLE_NormalTextXY(8, Line, 60, 1);
3847
3848 Line++;
3849 if (Line<12)
3850 Line=15;
3851
3852 if (Line>15)
3853 Line=12;
3854
3855 CONSOLE_InvertTextXY(8, Line, 60, 1);
3856 }
3857 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3858 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
3859 {
3860 CONSOLE_NormalTextXY(8, Line, 60, 1);
3861
3862 Line--;
3863 if (Line<12)
3864 Line=15;
3865
3866 if (Line>15)
3867 Line=12;
3868
3869 CONSOLE_InvertTextXY(8, Line, 60, 1);
3870 }
3871 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3872 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
3873 {
3874 if (ConfirmQuit(Ir) == TRUE)
3875 return QUIT_PAGE;
3876
3877 break;
3878 }
3879 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
3880 {
3881 if (Line == 12)
3882 {
3883 return BOOT_LOADER_HARDDISK_MBR_PAGE;
3884 }
3885 else if (Line == 13)
3886 {
3887 return BOOT_LOADER_HARDDISK_VBR_PAGE;
3888 }
3889 else if (Line == 14)
3890 {
3891 return BOOT_LOADER_FLOPPY_PAGE;
3892 }
3893 else if (Line == 15)
3894 {
3895 return SUCCESS_PAGE;
3896 }
3897
3898 return BOOT_LOADER_PAGE;
3899 }
3900 }
3901
3902 return BOOT_LOADER_PAGE;
3903 }
3904
3905
3906 static PAGE_NUMBER
3907 BootLoaderFloppyPage(PINPUT_RECORD Ir)
3908 {
3909 NTSTATUS Status;
3910
3911 MUIDisplayPage(BOOT_LOADER_FLOPPY_PAGE);
3912
3913 // SetStatusText(" Please wait...");
3914
3915 while (TRUE)
3916 {
3917 CONSOLE_ConInKey(Ir);
3918
3919 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3920 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
3921 {
3922 if (ConfirmQuit(Ir) == TRUE)
3923 return QUIT_PAGE;
3924
3925 break;
3926 }
3927 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
3928 {
3929 if (DoesFileExist(L"\\Device\\Floppy0", L"\\") == FALSE)
3930 {
3931 MUIDisplayError(ERROR_NO_FLOPPY, Ir, POPUP_WAIT_ENTER);
3932 return BOOT_LOADER_FLOPPY_PAGE;
3933 }
3934
3935 Status = InstallFatBootcodeToFloppy(&SourceRootPath, &DestinationArcPath);
3936 if (!NT_SUCCESS(Status))
3937 {
3938 /* Print error message */
3939 return BOOT_LOADER_FLOPPY_PAGE;
3940 }
3941
3942 return SUCCESS_PAGE;
3943 }
3944 }
3945
3946 return BOOT_LOADER_FLOPPY_PAGE;
3947 }
3948
3949 static PAGE_NUMBER
3950 BootLoaderHarddiskVbrPage(PINPUT_RECORD Ir)
3951 {
3952 UCHAR PartitionType;
3953 NTSTATUS Status;
3954
3955 PartitionType = PartitionList->ActiveBootPartition->PartitionType;
3956
3957 Status = InstallVBRToPartition(&SystemRootPath,
3958 &SourceRootPath,
3959 &DestinationArcPath,
3960 PartitionType);
3961 if (!NT_SUCCESS(Status))
3962 {
3963 MUIDisplayError(ERROR_WRITE_BOOT, Ir, POPUP_WAIT_ENTER);
3964 return QUIT_PAGE;
3965 }
3966
3967 return SUCCESS_PAGE;
3968 }
3969
3970 static PAGE_NUMBER
3971 BootLoaderHarddiskMbrPage(PINPUT_RECORD Ir)
3972 {
3973 UCHAR PartitionType;
3974 NTSTATUS Status;
3975 WCHAR DestinationDevicePathBuffer[MAX_PATH];
3976 WCHAR SourceMbrPathBuffer[MAX_PATH];
3977
3978 /* Step 1: Write the VBR */
3979 PartitionType = PartitionList->ActiveBootPartition->PartitionType;
3980
3981 Status = InstallVBRToPartition(&SystemRootPath,
3982 &SourceRootPath,
3983 &DestinationArcPath,
3984 PartitionType);
3985 if (!NT_SUCCESS(Status))
3986 {
3987 MUIDisplayError(ERROR_WRITE_BOOT, Ir, POPUP_WAIT_ENTER);
3988 return QUIT_PAGE;
3989 }
3990
3991 /* Step 2: Write the MBR */
3992 swprintf(DestinationDevicePathBuffer,
3993 L"\\Device\\Harddisk%d\\Partition0",
3994 PartitionList->ActiveBootDisk->DiskNumber);
3995
3996 wcscpy(SourceMbrPathBuffer, SourceRootPath.Buffer);
3997 wcscat(SourceMbrPathBuffer, L"\\loader\\dosmbr.bin");
3998
3999 DPRINT("Install MBR bootcode: %S ==> %S\n",
4000 SourceMbrPathBuffer, DestinationDevicePathBuffer);
4001
4002 Status = InstallMbrBootCodeToDisk(SourceMbrPathBuffer,
4003 DestinationDevicePathBuffer);
4004 if (!NT_SUCCESS (Status))
4005 {
4006 DPRINT1("InstallMbrBootCodeToDisk() failed (Status %lx)\n",
4007 Status);
4008 MUIDisplayError(ERROR_INSTALL_BOOTCODE, Ir, POPUP_WAIT_ENTER);
4009 return QUIT_PAGE;
4010 }
4011
4012 return SUCCESS_PAGE;
4013 }
4014
4015
4016 static PAGE_NUMBER
4017 QuitPage(PINPUT_RECORD Ir)
4018 {
4019 MUIDisplayPage(QUIT_PAGE);
4020
4021 /* Destroy partition list */
4022 if (PartitionList != NULL)
4023 {
4024 DestroyPartitionList (PartitionList);
4025 PartitionList = NULL;
4026 }
4027
4028 /* Destroy filesystem list */
4029 if (FileSystemList != NULL)
4030 {
4031 DestroyFileSystemList (FileSystemList);
4032 FileSystemList = NULL;
4033 }
4034
4035 /* Destroy computer settings list */
4036 if (ComputerList != NULL)
4037 {
4038 DestroyGenericList(ComputerList, TRUE);
4039 ComputerList = NULL;
4040 }
4041
4042 /* Destroy display settings list */
4043 if (DisplayList != NULL)
4044 {
4045 DestroyGenericList(DisplayList, TRUE);
4046 DisplayList = NULL;
4047 }
4048
4049 /* Destroy keyboard settings list */
4050 if (KeyboardList != NULL)
4051 {
4052 DestroyGenericList(KeyboardList, TRUE);
4053 KeyboardList = NULL;
4054 }
4055
4056 /* Destroy keyboard layout list */
4057 if (LayoutList != NULL)
4058 {
4059 DestroyGenericList(LayoutList, TRUE);
4060 LayoutList = NULL;
4061 }
4062
4063 if (LanguageList != NULL)
4064 {
4065 DestroyGenericList(LanguageList, FALSE);
4066 LanguageList = NULL;
4067 }
4068
4069 CONSOLE_SetStatusText(MUIGetString(STRING_REBOOTCOMPUTER2));
4070
4071 while (TRUE)
4072 {
4073 CONSOLE_ConInKey(Ir);
4074
4075 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
4076 {
4077 return FLUSH_PAGE;
4078 }
4079 }
4080 }
4081
4082
4083 static PAGE_NUMBER
4084 SuccessPage(PINPUT_RECORD Ir)
4085 {
4086 MUIDisplayPage(SUCCESS_PAGE);
4087
4088 if (IsUnattendedSetup)
4089 {
4090 return FLUSH_PAGE;
4091 }
4092
4093 while (TRUE)
4094 {
4095 CONSOLE_ConInKey(Ir);
4096
4097 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
4098 {
4099 return FLUSH_PAGE;
4100 }
4101 }
4102 }
4103
4104
4105 static PAGE_NUMBER
4106 FlushPage(PINPUT_RECORD Ir)
4107 {
4108 MUIDisplayPage(FLUSH_PAGE);
4109 return REBOOT_PAGE;
4110 }
4111
4112
4113 DWORD WINAPI
4114 PnpEventThread(IN LPVOID lpParameter);
4115
4116 VOID
4117 RunUSetup(VOID)
4118 {
4119 INPUT_RECORD Ir;
4120 PAGE_NUMBER Page;
4121 LARGE_INTEGER Time;
4122 NTSTATUS Status;
4123 BOOLEAN Old;
4124
4125 NtQuerySystemTime(&Time);
4126
4127 Status = RtlCreateUserThread(NtCurrentProcess(),
4128 NULL,
4129 TRUE,
4130 0,
4131 0,
4132 0,
4133 PnpEventThread,
4134 &SetupInf,
4135 &hPnpThread,
4136 NULL);
4137 if (!NT_SUCCESS(Status))
4138 hPnpThread = INVALID_HANDLE_VALUE;
4139
4140 if (!CONSOLE_Init())
4141 {
4142 PrintString(MUIGetString(STRING_CONSOLEFAIL1));
4143 PrintString(MUIGetString(STRING_CONSOLEFAIL2));
4144 PrintString(MUIGetString(STRING_CONSOLEFAIL3));
4145
4146 /* Raise a hard error (crash the system/BSOD) */
4147 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED,
4148 0,0,0,0,0);
4149 }
4150
4151 /* Initialize global unicode strings */
4152 RtlInitUnicodeString(&SourcePath, NULL);
4153 RtlInitUnicodeString(&SourceRootPath, NULL);
4154 RtlInitUnicodeString(&SourceRootDir, NULL);
4155 RtlInitUnicodeString(&InstallPath, NULL);
4156 RtlInitUnicodeString(&DestinationPath, NULL);
4157 RtlInitUnicodeString(&DestinationArcPath, NULL);
4158 RtlInitUnicodeString(&DestinationRootPath, NULL);
4159 RtlInitUnicodeString(&SystemRootPath, NULL);
4160
4161 /* Hide the cursor */
4162 CONSOLE_SetCursorType(TRUE, FALSE);
4163
4164 Page = START_PAGE;
4165 while (Page != REBOOT_PAGE && Page != RECOVERY_PAGE)
4166 {
4167 CONSOLE_ClearScreen();
4168 CONSOLE_Flush();
4169
4170 //CONSOLE_SetUnderlinedTextXY(4, 3, " ReactOS " KERNEL_VERSION_STR " Setup ");
4171 //CONSOLE_Flush();
4172
4173 switch (Page)
4174 {
4175 /* Start page */
4176 case START_PAGE:
4177 Page = SetupStartPage(&Ir);
4178 break;
4179
4180 /* Language page */
4181 case LANGUAGE_PAGE:
4182 Page = LanguagePage(&Ir);
4183 break;
4184
4185 /* License page */
4186 case LICENSE_PAGE:
4187 Page = LicensePage(&Ir);
4188 break;
4189
4190 /* Intro page */
4191 case INTRO_PAGE:
4192 Page = IntroPage(&Ir);
4193 break;
4194
4195 /* Install pages */
4196 case INSTALL_INTRO_PAGE:
4197 Page = InstallIntroPage(&Ir);
4198 break;
4199
4200 #if 0
4201 case SCSI_CONTROLLER_PAGE:
4202 Page = ScsiControllerPage(&Ir);
4203 break;
4204 #endif
4205
4206 #if 0
4207 case OEM_DRIVER_PAGE:
4208 Page = OemDriverPage(&Ir);
4209 break;
4210 #endif
4211
4212 case DEVICE_SETTINGS_PAGE:
4213 Page = DeviceSettingsPage(&Ir);
4214 break;
4215
4216 case COMPUTER_SETTINGS_PAGE:
4217 Page = ComputerSettingsPage(&Ir);
4218 break;
4219
4220 case DISPLAY_SETTINGS_PAGE:
4221 Page = DisplaySettingsPage(&Ir);
4222 break;
4223
4224 case KEYBOARD_SETTINGS_PAGE:
4225 Page = KeyboardSettingsPage(&Ir);
4226 break;
4227
4228 case LAYOUT_SETTINGS_PAGE:
4229 Page = LayoutSettingsPage(&Ir);
4230 break;
4231
4232 case SELECT_PARTITION_PAGE:
4233 Page = SelectPartitionPage(&Ir);
4234 break;
4235
4236 case CREATE_PRIMARY_PARTITION_PAGE:
4237 Page = CreatePrimaryPartitionPage(&Ir);
4238 break;
4239
4240 case CREATE_EXTENDED_PARTITION_PAGE:
4241 Page = CreateExtendedPartitionPage(&Ir);
4242 break;
4243
4244 case CREATE_LOGICAL_PARTITION_PAGE:
4245 Page = CreateLogicalPartitionPage(&Ir);
4246 break;
4247
4248 case DELETE_PARTITION_PAGE:
4249 Page = DeletePartitionPage(&Ir);
4250 break;
4251
4252 case SELECT_FILE_SYSTEM_PAGE:
4253 Page = SelectFileSystemPage(&Ir);
4254 break;
4255
4256 case FORMAT_PARTITION_PAGE:
4257 Page = (PAGE_NUMBER) FormatPartitionPage(&Ir);
4258 break;
4259
4260 case CHECK_FILE_SYSTEM_PAGE:
4261 Page = (PAGE_NUMBER) CheckFileSystemPage(&Ir);
4262 break;
4263
4264 case INSTALL_DIRECTORY_PAGE:
4265 Page = InstallDirectoryPage(&Ir);
4266 break;
4267
4268 case PREPARE_COPY_PAGE:
4269 Page = PrepareCopyPage(&Ir);
4270 break;
4271
4272 case FILE_COPY_PAGE:
4273 Page = FileCopyPage(&Ir);
4274 break;
4275
4276 case REGISTRY_PAGE:
4277 Page = RegistryPage(&Ir);
4278 break;
4279
4280 case BOOT_LOADER_PAGE:
4281 Page = BootLoaderPage(&Ir);
4282 break;
4283
4284 case BOOT_LOADER_FLOPPY_PAGE:
4285 Page = BootLoaderFloppyPage(&Ir);
4286 break;
4287
4288 case BOOT_LOADER_HARDDISK_MBR_PAGE:
4289 Page = BootLoaderHarddiskMbrPage(&Ir);
4290 break;
4291
4292 case BOOT_LOADER_HARDDISK_VBR_PAGE:
4293 Page = BootLoaderHarddiskVbrPage(&Ir);
4294 break;
4295
4296 /* Repair pages */
4297 case REPAIR_INTRO_PAGE:
4298 Page = RepairIntroPage(&Ir);
4299 break;
4300
4301 case SUCCESS_PAGE:
4302 Page = SuccessPage(&Ir);
4303 break;
4304
4305 case FLUSH_PAGE:
4306 Page = FlushPage(&Ir);
4307 break;
4308
4309 case QUIT_PAGE:
4310 Page = QuitPage(&Ir);
4311 break;
4312
4313 case RECOVERY_PAGE:
4314 case REBOOT_PAGE:
4315 break;
4316 }
4317 }
4318
4319 if (Page == RECOVERY_PAGE)
4320 RecoveryConsole();
4321
4322 FreeConsole();
4323
4324 /* Avoid bugcheck */
4325 Time.QuadPart += 50000000;
4326 NtDelayExecution(FALSE, &Time);
4327
4328 /* Reboot */
4329 RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, TRUE, FALSE, &Old);
4330 NtShutdownSystem(ShutdownReboot);
4331 RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, Old, FALSE, &Old);
4332 NtTerminateProcess(NtCurrentProcess(), 0);
4333 }
4334
4335
4336 #ifdef __REACTOS__
4337
4338 VOID NTAPI
4339 NtProcessStartup(PPEB Peb)
4340 {
4341 RtlNormalizeProcessParams(Peb->ProcessParameters);
4342
4343 ProcessHeap = Peb->ProcessHeap;
4344 InfSetHeap(ProcessHeap);
4345 RunUSetup();
4346 }
4347 #endif /* __REACTOS__ */
4348
4349 /* EOF */