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