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