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