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