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