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