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