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