[USETUP]
[reactos.git] / reactos / base / setup / usetup / interface / usetup.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 2002, 2003, 2004 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 /*
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS text-mode setup
22 * FILE: subsys/system/usetup/usetup.c
23 * PURPOSE: Text-mode setup
24 * PROGRAMMER: Eric Kohl
25 * Casper S. Hornstrup (chorns@users.sourceforge.net)
26 * Hervé Poussineau (hpoussin@reactos.org)
27 */
28
29 #include <usetup.h>
30
31 #include "bootsup.h"
32 #include "chkdsk.h"
33 #include "format.h"
34 #include "drivesup.h"
35 #include "settings.h"
36
37 #define NDEBUG
38 #include <debug.h>
39
40
41 /* GLOBALS ******************************************************************/
42
43 HANDLE ProcessHeap;
44 UNICODE_STRING SourceRootPath;
45 UNICODE_STRING SourceRootDir;
46 UNICODE_STRING SourcePath;
47 BOOLEAN IsUnattendedSetup = FALSE;
48 LONG UnattendDestinationDiskNumber;
49 LONG UnattendDestinationPartitionNumber;
50 LONG UnattendMBRInstallType = -1;
51 LONG UnattendFormatPartition = 0;
52 LONG AutoPartition = 0;
53 WCHAR UnattendInstallationDirectory[MAX_PATH];
54 PWCHAR SelectedLanguageId;
55 WCHAR LocaleID[9];
56 WCHAR DefaultLanguage[20];
57 WCHAR DefaultKBLayout[20];
58 BOOLEAN RepairUpdateFlag = FALSE;
59 HANDLE hPnpThread = INVALID_HANDLE_VALUE;
60 PPARTLIST PartitionList = NULL;
61
62 /* LOCALS *******************************************************************/
63
64 static PFILE_SYSTEM_LIST FileSystemList = NULL;
65
66 static UNICODE_STRING InstallPath;
67
68 /* Path to the install directory */
69 static UNICODE_STRING DestinationPath;
70 static UNICODE_STRING DestinationArcPath;
71 static UNICODE_STRING DestinationRootPath;
72
73 static WCHAR DestinationDriveLetter;
74
75 /* Path to the active partition (boot manager) */
76 static UNICODE_STRING SystemRootPath;
77
78 static HINF SetupInf;
79
80 static HSPFILEQ SetupFileQueue = NULL;
81
82 static BOOLEAN WarnLinuxPartitions = TRUE;
83
84 static PGENERIC_LIST ComputerList = NULL;
85 static PGENERIC_LIST DisplayList = NULL;
86 static PGENERIC_LIST KeyboardList = NULL;
87 static PGENERIC_LIST LayoutList = NULL;
88 static PGENERIC_LIST LanguageList = NULL;
89
90 static LANGID LanguageId = 0;
91
92 static ULONG RequiredPartitionDiskSpace = ~0;
93
94 /* FUNCTIONS ****************************************************************/
95
96 static VOID
97 PrintString(char* fmt,...)
98 {
99 char buffer[512];
100 va_list ap;
101 UNICODE_STRING UnicodeString;
102 ANSI_STRING AnsiString;
103
104 va_start(ap, fmt);
105 vsprintf(buffer, fmt, ap);
106 va_end(ap);
107
108 RtlInitAnsiString(&AnsiString, buffer);
109 RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE);
110 NtDisplayString(&UnicodeString);
111 RtlFreeUnicodeString(&UnicodeString);
112 }
113
114
115 static VOID
116 DrawBox(IN SHORT xLeft,
117 IN SHORT yTop,
118 IN SHORT Width,
119 IN SHORT Height)
120 {
121 COORD coPos;
122 DWORD Written;
123
124 /* draw upper left corner */
125 coPos.X = xLeft;
126 coPos.Y = yTop;
127 FillConsoleOutputCharacterA(StdOutput,
128 0xDA, // '+',
129 1,
130 coPos,
131 &Written);
132
133 /* draw upper edge */
134 coPos.X = xLeft + 1;
135 coPos.Y = yTop;
136 FillConsoleOutputCharacterA(StdOutput,
137 0xC4, // '-',
138 Width - 2,
139 coPos,
140 &Written);
141
142 /* draw upper right corner */
143 coPos.X = xLeft + Width - 1;
144 coPos.Y = yTop;
145 FillConsoleOutputCharacterA(StdOutput,
146 0xBF, // '+',
147 1,
148 coPos,
149 &Written);
150
151 /* Draw right edge, inner space and left edge */
152 for (coPos.Y = yTop + 1; coPos.Y < yTop + Height - 1; coPos.Y++)
153 {
154 coPos.X = xLeft;
155 FillConsoleOutputCharacterA(StdOutput,
156 0xB3, // '|',
157 1,
158 coPos,
159 &Written);
160
161 coPos.X = xLeft + 1;
162 FillConsoleOutputCharacterA(StdOutput,
163 ' ',
164 Width - 2,
165 coPos,
166 &Written);
167
168 coPos.X = xLeft + Width - 1;
169 FillConsoleOutputCharacterA(StdOutput,
170 0xB3, // '|',
171 1,
172 coPos,
173 &Written);
174 }
175
176 /* draw lower left corner */
177 coPos.X = xLeft;
178 coPos.Y = yTop + Height - 1;
179 FillConsoleOutputCharacterA(StdOutput,
180 0xC0, // '+',
181 1,
182 coPos,
183 &Written);
184
185 /* draw lower edge */
186 coPos.X = xLeft + 1;
187 coPos.Y = yTop + Height - 1;
188 FillConsoleOutputCharacterA(StdOutput,
189 0xC4, // '-',
190 Width - 2,
191 coPos,
192 &Written);
193
194 /* draw lower right corner */
195 coPos.X = xLeft + Width - 1;
196 coPos.Y = yTop + Height - 1;
197 FillConsoleOutputCharacterA(StdOutput,
198 0xD9, // '+',
199 1,
200 coPos,
201 &Written);
202 }
203
204
205 VOID
206 PopupError(PCCH Text,
207 PCCH Status,
208 PINPUT_RECORD Ir,
209 ULONG WaitEvent)
210 {
211 SHORT yTop;
212 SHORT xLeft;
213 COORD coPos;
214 DWORD Written;
215 ULONG Length;
216 ULONG MaxLength;
217 ULONG Lines;
218 PCHAR p;
219 PCCH pnext;
220 BOOLEAN LastLine;
221 SHORT Width;
222 SHORT Height;
223
224 /* Count text lines and longest line */
225 MaxLength = 0;
226 Lines = 0;
227 pnext = Text;
228
229 while (TRUE)
230 {
231 p = strchr(pnext, '\n');
232
233 if (p == NULL)
234 {
235 Length = strlen(pnext);
236 LastLine = TRUE;
237 }
238 else
239 {
240 Length = (ULONG)(p - pnext);
241 LastLine = FALSE;
242 }
243
244 Lines++;
245
246 if (Length > MaxLength)
247 MaxLength = Length;
248
249 if (LastLine == TRUE)
250 break;
251
252 pnext = p + 1;
253 }
254
255 /* Check length of status line */
256 if (Status != NULL)
257 {
258 Length = strlen(Status);
259
260 if (Length > MaxLength)
261 MaxLength = Length;
262 }
263
264 Width = MaxLength + 4;
265 Height = Lines + 2;
266
267 if (Status != NULL)
268 Height += 2;
269
270 yTop = (yScreen - Height) / 2;
271 xLeft = (xScreen - Width) / 2;
272
273
274 /* Set screen attributes */
275 coPos.X = xLeft;
276 for (coPos.Y = yTop; coPos.Y < yTop + Height; coPos.Y++)
277 {
278 FillConsoleOutputAttribute(StdOutput,
279 FOREGROUND_RED | BACKGROUND_WHITE,
280 Width,
281 coPos,
282 &Written);
283 }
284
285 DrawBox(xLeft, yTop, Width, Height);
286
287 /* Print message text */
288 coPos.Y = yTop + 1;
289 pnext = Text;
290 while (TRUE)
291 {
292 p = strchr(pnext, '\n');
293
294 if (p == NULL)
295 {
296 Length = strlen(pnext);
297 LastLine = TRUE;
298 }
299 else
300 {
301 Length = (ULONG)(p - pnext);
302 LastLine = FALSE;
303 }
304
305 if (Length != 0)
306 {
307 coPos.X = xLeft + 2;
308 WriteConsoleOutputCharacterA(StdOutput,
309 pnext,
310 Length,
311 coPos,
312 &Written);
313 }
314
315 if (LastLine == TRUE)
316 break;
317
318 coPos.Y++;
319 pnext = p + 1;
320 }
321
322 /* Print separator line and status text */
323 if (Status != NULL)
324 {
325 coPos.Y = yTop + Height - 3;
326 coPos.X = xLeft;
327 FillConsoleOutputCharacterA(StdOutput,
328 0xC3, // '+',
329 1,
330 coPos,
331 &Written);
332
333 coPos.X = xLeft + 1;
334 FillConsoleOutputCharacterA(StdOutput,
335 0xC4, // '-',
336 Width - 2,
337 coPos,
338 &Written);
339
340 coPos.X = xLeft + Width - 1;
341 FillConsoleOutputCharacterA(StdOutput,
342 0xB4, // '+',
343 1,
344 coPos,
345 &Written);
346
347 coPos.Y++;
348 coPos.X = xLeft + 2;
349 WriteConsoleOutputCharacterA(StdOutput,
350 Status,
351 min(strlen(Status), (SIZE_T)Width - 4),
352 coPos,
353 &Written);
354 }
355
356 if (WaitEvent == POPUP_WAIT_NONE)
357 return;
358
359 while (TRUE)
360 {
361 CONSOLE_ConInKey(Ir);
362
363 if (WaitEvent == POPUP_WAIT_ANY_KEY ||
364 Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)
365 {
366 return;
367 }
368 }
369 }
370
371
372 /*
373 * Confirm quit setup
374 * RETURNS
375 * TRUE: Quit setup.
376 * FALSE: Don't quit setup.
377 */
378 static BOOL
379 ConfirmQuit(PINPUT_RECORD Ir)
380 {
381 BOOL Result = FALSE;
382 MUIDisplayError(ERROR_NOT_INSTALLED, NULL, POPUP_WAIT_NONE);
383
384 while (TRUE)
385 {
386 CONSOLE_ConInKey(Ir);
387
388 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
389 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
390 {
391 Result = TRUE;
392 break;
393 }
394 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
395 {
396 Result = FALSE;
397 break;
398 }
399 }
400
401 return Result;
402 }
403
404
405 VOID
406 CheckUnattendedSetup(VOID)
407 {
408 WCHAR UnattendInfPath[MAX_PATH];
409 INFCONTEXT Context;
410 HINF UnattendInf;
411 UINT ErrorLine;
412 INT IntValue;
413 PWCHAR Value;
414
415 if (DoesFileExist(SourcePath.Buffer, L"unattend.inf") == FALSE)
416 {
417 DPRINT("Does not exist: %S\\%S\n", SourcePath.Buffer, L"unattend.inf");
418 return;
419 }
420
421 wcscpy(UnattendInfPath, SourcePath.Buffer);
422 wcscat(UnattendInfPath, L"\\unattend.inf");
423
424 /* Load 'unattend.inf' from install media. */
425 UnattendInf = SetupOpenInfFileW(UnattendInfPath,
426 NULL,
427 INF_STYLE_WIN4,
428 LanguageId,
429 &ErrorLine);
430
431 if (UnattendInf == INVALID_HANDLE_VALUE)
432 {
433 DPRINT("SetupOpenInfFileW() failed\n");
434 return;
435 }
436
437 /* Open 'Unattend' section */
438 if (!SetupFindFirstLineW(UnattendInf, L"Unattend", L"Signature", &Context))
439 {
440 DPRINT("SetupFindFirstLineW() failed for section 'Unattend'\n");
441 SetupCloseInfFile(UnattendInf);
442 return;
443 }
444
445 /* Get pointer 'Signature' key */
446 if (!INF_GetData(&Context, NULL, &Value))
447 {
448 DPRINT("INF_GetData() failed for key 'Signature'\n");
449 SetupCloseInfFile(UnattendInf);
450 return;
451 }
452
453 /* Check 'Signature' string */
454 if (_wcsicmp(Value, L"$ReactOS$") != 0)
455 {
456 DPRINT("Signature not $ReactOS$\n");
457 SetupCloseInfFile(UnattendInf);
458 return;
459 }
460
461 /* Check if Unattend setup is enabled */
462 if (!SetupFindFirstLineW(UnattendInf, L"Unattend", L"UnattendSetupEnabled", &Context))
463 {
464 DPRINT("Can't find key 'UnattendSetupEnabled'\n");
465 SetupCloseInfFile(UnattendInf);
466 return;
467 }
468
469 if (!INF_GetData(&Context, NULL, &Value))
470 {
471 DPRINT("Can't read key 'UnattendSetupEnabled'\n");
472 SetupCloseInfFile(UnattendInf);
473 return;
474 }
475
476 if (_wcsicmp(Value, L"yes") != 0)
477 {
478 DPRINT("Unattend setup is disabled by 'UnattendSetupEnabled' key!\n");
479 SetupCloseInfFile(UnattendInf);
480 return;
481 }
482
483 /* Search for 'DestinationDiskNumber' in the 'Unattend' section */
484 if (!SetupFindFirstLineW(UnattendInf, L"Unattend", L"DestinationDiskNumber", &Context))
485 {
486 DPRINT("SetupFindFirstLine() failed for key 'DestinationDiskNumber'\n");
487 SetupCloseInfFile(UnattendInf);
488 return;
489 }
490
491 if (!SetupGetIntField(&Context, 1, &IntValue))
492 {
493 DPRINT("SetupGetIntField() failed for key 'DestinationDiskNumber'\n");
494 SetupCloseInfFile(UnattendInf);
495 return;
496 }
497
498 UnattendDestinationDiskNumber = (LONG)IntValue;
499
500 /* Search for 'DestinationPartitionNumber' in the 'Unattend' section */
501 if (!SetupFindFirstLineW(UnattendInf, L"Unattend", L"DestinationPartitionNumber", &Context))
502 {
503 DPRINT("SetupFindFirstLine() failed for key 'DestinationPartitionNumber'\n");
504 SetupCloseInfFile(UnattendInf);
505 return;
506 }
507
508 if (!SetupGetIntField(&Context, 1, &IntValue))
509 {
510 DPRINT("SetupGetIntField() failed for key 'DestinationPartitionNumber'\n");
511 SetupCloseInfFile(UnattendInf);
512 return;
513 }
514
515 UnattendDestinationPartitionNumber = IntValue;
516
517 /* Search for 'InstallationDirectory' in the 'Unattend' section */
518 if (!SetupFindFirstLineW(UnattendInf, L"Unattend", L"InstallationDirectory", &Context))
519 {
520 DPRINT("SetupFindFirstLine() failed for key 'InstallationDirectory'\n");
521 SetupCloseInfFile(UnattendInf);
522 return;
523 }
524
525 /* Get pointer 'InstallationDirectory' key */
526 if (!INF_GetData(&Context, NULL, &Value))
527 {
528 DPRINT("INF_GetData() failed for key 'InstallationDirectory'\n");
529 SetupCloseInfFile(UnattendInf);
530 return;
531 }
532
533 wcscpy(UnattendInstallationDirectory, Value);
534
535 IsUnattendedSetup = TRUE;
536
537 /* Search for 'MBRInstallType' in the 'Unattend' section */
538 if (SetupFindFirstLineW(UnattendInf, L"Unattend", L"MBRInstallType", &Context))
539 {
540 if (SetupGetIntField(&Context, 1, &IntValue))
541 {
542 UnattendMBRInstallType = IntValue;
543 }
544 }
545
546 /* Search for 'FormatPartition' in the 'Unattend' section */
547 if (SetupFindFirstLineW(UnattendInf, L"Unattend", L"FormatPartition", &Context))
548 {
549 if (SetupGetIntField(&Context, 1, &IntValue))
550 {
551 UnattendFormatPartition = IntValue;
552 }
553 }
554
555 if (SetupFindFirstLineW(UnattendInf, L"Unattend", L"AutoPartition", &Context))
556 {
557 if (SetupGetIntField(&Context, 1, &IntValue))
558 {
559 AutoPartition = IntValue;
560 }
561 }
562
563 /* search for LocaleID in the 'Unattend' section*/
564 if (SetupFindFirstLineW (UnattendInf, L"Unattend", L"LocaleID", &Context))
565 {
566 if (INF_GetData (&Context, NULL, &Value))
567 {
568 LONG Id = wcstol(Value, NULL, 16);
569 swprintf(LocaleID,L"%08lx", Id);
570 }
571 }
572
573 SetupCloseInfFile(UnattendInf);
574
575 DPRINT("Running unattended setup\n");
576 }
577
578
579 VOID
580 UpdateKBLayout(VOID)
581 {
582 PGENERIC_LIST_ENTRY ListEntry;
583 LPCWSTR pszNewLayout;
584
585 pszNewLayout = MUIDefaultKeyboardLayout();
586
587 if (LayoutList == NULL)
588 {
589 LayoutList = CreateKeyboardLayoutList(SetupInf, DefaultKBLayout);
590 if (LayoutList == NULL)
591 {
592 /* FIXME: Handle error! */
593 return;
594 }
595 }
596
597 ListEntry = GetFirstListEntry(LayoutList);
598
599 /* Search for default layout (if provided) */
600 if (pszNewLayout != NULL)
601 {
602 while (ListEntry != NULL)
603 {
604 if (!wcscmp(pszNewLayout, GetListEntryUserData(ListEntry)))
605 {
606 SetCurrentListEntry(LayoutList, ListEntry);
607 break;
608 }
609
610 ListEntry = GetNextListEntry(ListEntry);
611 }
612 }
613 }
614
615
616 static PAGE_NUMBER
617 LanguagePage(PINPUT_RECORD Ir)
618 {
619 PWCHAR NewLanguageId;
620 BOOL RefreshPage = FALSE;
621
622 /* Initialize the computer settings list */
623 if (LanguageList == NULL)
624 {
625 LanguageList = CreateLanguageList(SetupInf, DefaultLanguage);
626
627 if (LanguageList == NULL)
628 {
629 PopupError("Setup failed to initialize available translations", NULL, NULL, POPUP_WAIT_NONE);
630 return INTRO_PAGE;
631 }
632 }
633
634 /* Load the font */
635 SelectedLanguageId = DefaultLanguage;
636 SetConsoleCodePage();
637
638 DrawGenericList(LanguageList,
639 2,
640 18,
641 xScreen - 3,
642 yScreen - 3);
643
644 ScrollToPositionGenericList (LanguageList, GetDefaultLanguageIndex());
645
646 MUIDisplayPage(LANGUAGE_PAGE);
647
648 while (TRUE)
649 {
650 CONSOLE_ConInKey(Ir);
651
652 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
653 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
654 {
655 ScrollDownGenericList (LanguageList);
656 RefreshPage = TRUE;
657 }
658 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
659 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
660 {
661 ScrollUpGenericList(LanguageList);
662 RefreshPage = TRUE;
663 }
664 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
665 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_NEXT)) /* PAGE DOWN */
666 {
667 ScrollPageDownGenericList(LanguageList);
668 RefreshPage = TRUE;
669 }
670 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
671 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_PRIOR)) /* PAGE UP */
672 {
673 ScrollPageUpGenericList(LanguageList);
674 RefreshPage = TRUE;
675 }
676 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
677 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
678 {
679 if (ConfirmQuit(Ir) == TRUE)
680 return QUIT_PAGE;
681 else
682 RedrawGenericList(LanguageList);
683 }
684 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
685 {
686 SelectedLanguageId = (PWCHAR)GetListEntryUserData(GetCurrentListEntry(LanguageList));
687
688 LanguageId = (LANGID)(wcstol(SelectedLanguageId, NULL, 16) & 0xFFFF);
689
690 if (wcscmp(SelectedLanguageId, DefaultLanguage))
691 {
692 UpdateKBLayout();
693 }
694
695 /* Load the font */
696 SetConsoleCodePage();
697
698 return INTRO_PAGE;
699 }
700 else if ((Ir->Event.KeyEvent.uChar.AsciiChar > 0x60) && (Ir->Event.KeyEvent.uChar.AsciiChar < 0x7b))
701 {
702 /* a-z */
703 GenericListKeyPress (LanguageList, Ir->Event.KeyEvent.uChar.AsciiChar);
704 RefreshPage = TRUE;
705 }
706
707 if (RefreshPage)
708 {
709 NewLanguageId = (PWCHAR)GetListEntryUserData(GetCurrentListEntry(LanguageList));
710
711 if (SelectedLanguageId != NewLanguageId)
712 {
713 /* Clear the language page */
714 MUIClearPage(LANGUAGE_PAGE);
715
716 SelectedLanguageId = NewLanguageId;
717
718 /* Load the font */
719 SetConsoleCodePage();
720
721 /* Redraw language selection page in native language */
722 MUIDisplayPage(LANGUAGE_PAGE);
723 }
724
725 RefreshPage = FALSE;
726 }
727 }
728
729 return INTRO_PAGE;
730 }
731
732
733 /*
734 * Start page
735 * RETURNS
736 * Number of the next page.
737 */
738 static PAGE_NUMBER
739 SetupStartPage(PINPUT_RECORD Ir)
740 {
741 //SYSTEM_DEVICE_INFORMATION Sdi;
742 NTSTATUS Status;
743 WCHAR FileNameBuffer[MAX_PATH];
744 INFCONTEXT Context;
745 PWCHAR Value;
746 UINT ErrorLine;
747 //ULONG ReturnSize;
748 PGENERIC_LIST_ENTRY ListEntry;
749 INT IntValue;
750
751 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
752
753 #if 0
754 /* Check whether a harddisk is available */
755 Status = NtQuerySystemInformation(SystemDeviceInformation,
756 &Sdi,
757 sizeof(SYSTEM_DEVICE_INFORMATION),
758 &ReturnSize);
759
760 if (!NT_SUCCESS(Status))
761 {
762 CONSOLE_PrintTextXY(6, 15, "NtQuerySystemInformation() failed (Status 0x%08lx)", Status);
763 MUIDisplayError(ERROR_DRIVE_INFORMATION, Ir, POPUP_WAIT_ENTER);
764 return QUIT_PAGE;
765 }
766
767 if (Sdi.NumberOfDisks == 0)
768 {
769 MUIDisplayError(ERROR_NO_HDD, Ir, POPUP_WAIT_ENTER);
770 return QUIT_PAGE;
771 }
772 #endif
773
774 /* Get the source path and source root path */
775 Status = GetSourcePaths(&SourcePath,
776 &SourceRootPath,
777 &SourceRootDir);
778
779 if (!NT_SUCCESS(Status))
780 {
781 CONSOLE_PrintTextXY(6, 15, "GetSourcePaths() failed (Status 0x%08lx)", Status);
782 MUIDisplayError(ERROR_NO_SOURCE_DRIVE, Ir, POPUP_WAIT_ENTER);
783 return QUIT_PAGE;
784 }
785 #if 0
786 else
787 {
788 CONSOLE_PrintTextXY(6, 15, "SourcePath: '%wZ'", &SourcePath);
789 CONSOLE_PrintTextXY(6, 16, "SourceRootPath: '%wZ'", &SourceRootPath);
790 CONSOLE_PrintTextXY(6, 17, "SourceRootDir: '%wZ'", &SourceRootDir);
791 }
792 #endif
793
794 /* Load txtsetup.sif from install media. */
795 wcscpy(FileNameBuffer, SourcePath.Buffer);
796 wcscat(FileNameBuffer, L"\\txtsetup.sif");
797
798 SetupInf = SetupOpenInfFileW(FileNameBuffer,
799 NULL,
800 INF_STYLE_WIN4,
801 LanguageId,
802 &ErrorLine);
803
804 if (SetupInf == INVALID_HANDLE_VALUE)
805 {
806 MUIDisplayError(ERROR_LOAD_TXTSETUPSIF, Ir, POPUP_WAIT_ENTER);
807 return QUIT_PAGE;
808 }
809
810 /* Open 'Version' section */
811 if (!SetupFindFirstLineW(SetupInf, L"Version", L"Signature", &Context))
812 {
813 MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF, Ir, POPUP_WAIT_ENTER);
814 return QUIT_PAGE;
815 }
816
817 /* Get pointer 'Signature' key */
818 if (!INF_GetData(&Context, NULL, &Value))
819 {
820 MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF, Ir, POPUP_WAIT_ENTER);
821 return QUIT_PAGE;
822 }
823
824 /* Check 'Signature' string */
825 if (_wcsicmp(Value, L"$ReactOS$") != 0)
826 {
827 MUIDisplayError(ERROR_SIGNATURE_TXTSETUPSIF, Ir, POPUP_WAIT_ENTER);
828 return QUIT_PAGE;
829 }
830
831 /* Open 'DiskSpaceRequirements' section */
832 if (!SetupFindFirstLineW(SetupInf, L"DiskSpaceRequirements", L"FreeSysPartDiskSpace", &Context))
833 {
834 MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF, Ir, POPUP_WAIT_ENTER);
835 return QUIT_PAGE;
836 }
837
838 /* Get the 'FreeSysPartDiskSpace' value */
839 if (!SetupGetIntField(&Context, 1, &IntValue))
840 {
841 MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF, Ir, POPUP_WAIT_ENTER);
842 return QUIT_PAGE;
843 }
844
845 RequiredPartitionDiskSpace = (ULONG)IntValue;
846
847 /* Start PnP thread */
848 if (hPnpThread != INVALID_HANDLE_VALUE)
849 {
850 NtResumeThread(hPnpThread, NULL);
851 hPnpThread = INVALID_HANDLE_VALUE;
852 }
853
854 CheckUnattendedSetup();
855
856 if (IsUnattendedSetup)
857 {
858 //TODO
859 //read options from inf
860 ComputerList = CreateComputerTypeList(SetupInf);
861 DisplayList = CreateDisplayDriverList(SetupInf);
862 KeyboardList = CreateKeyboardDriverList(SetupInf);
863 LayoutList = CreateKeyboardLayoutList(SetupInf, DefaultKBLayout);
864 LanguageList = CreateLanguageList(SetupInf, DefaultLanguage);
865
866 /* new part */
867 wcscpy(SelectedLanguageId,LocaleID);
868
869 /* first we hack LanguageList */
870 ListEntry = GetFirstListEntry(LanguageList);
871
872 while (ListEntry != NULL)
873 {
874 if (!wcsicmp(LocaleID, GetListEntryUserData(ListEntry)))
875 {
876 DPRINT("found %S in LanguageList\n",GetListEntryUserData(ListEntry));
877 SetCurrentListEntry(LanguageList, ListEntry);
878 break;
879 }
880
881 ListEntry = GetNextListEntry(ListEntry);
882 }
883
884 /* now LayoutList */
885 ListEntry = GetFirstListEntry(LayoutList);
886
887 while (ListEntry != NULL)
888 {
889 if (!wcsicmp(LocaleID, GetListEntryUserData(ListEntry)))
890 {
891 DPRINT("found %S in LayoutList\n",GetListEntryUserData(ListEntry));
892 SetCurrentListEntry(LayoutList, ListEntry);
893 break;
894 }
895
896 ListEntry = GetNextListEntry(ListEntry);
897 }
898
899 SetConsoleCodePage();
900
901 return INSTALL_INTRO_PAGE;
902 }
903
904 return LANGUAGE_PAGE;
905 }
906
907
908 /*
909 * First setup page
910 * RETURNS
911 * Next page number.
912 */
913 static PAGE_NUMBER
914 IntroPage(PINPUT_RECORD Ir)
915 {
916 MUIDisplayPage(START_PAGE);
917
918 while (TRUE)
919 {
920 CONSOLE_ConInKey(Ir);
921
922 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
923 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
924 {
925 if (ConfirmQuit(Ir) == TRUE)
926 return QUIT_PAGE;
927
928 break;
929 }
930 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
931 {
932 return INSTALL_INTRO_PAGE;
933 break;
934 }
935 else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'R') /* R */
936 {
937 return REPAIR_INTRO_PAGE;
938 break;
939 }
940 else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'L') /* R */
941 {
942 return LICENSE_PAGE;
943 break;
944 }
945 }
946
947 return INTRO_PAGE;
948 }
949
950
951 /*
952 * License Page
953 * RETURNS
954 * Back to main setup page.
955 */
956 static PAGE_NUMBER
957 LicensePage(PINPUT_RECORD Ir)
958 {
959 MUIDisplayPage(LICENSE_PAGE);
960
961 while (TRUE)
962 {
963 CONSOLE_ConInKey(Ir);
964
965 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
966 {
967 return INTRO_PAGE;
968 break;
969 }
970 }
971
972 return LICENSE_PAGE;
973 }
974
975
976 static PAGE_NUMBER
977 RepairIntroPage(PINPUT_RECORD Ir)
978 {
979 MUIDisplayPage(REPAIR_INTRO_PAGE);
980
981 while(TRUE)
982 {
983 CONSOLE_ConInKey(Ir);
984
985 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
986 {
987 return REBOOT_PAGE;
988 }
989 else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'U') /* U */
990 {
991 RepairUpdateFlag = TRUE;
992 return INSTALL_INTRO_PAGE;
993 }
994 else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'R') /* R */
995 {
996 return INTRO_PAGE;
997 }
998 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
999 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
1000 {
1001 return INTRO_PAGE;
1002 }
1003 }
1004
1005 return REPAIR_INTRO_PAGE;
1006 }
1007
1008
1009 static PAGE_NUMBER
1010 InstallIntroPage(PINPUT_RECORD Ir)
1011 {
1012 MUIDisplayPage(INSTALL_INTRO_PAGE);
1013
1014 if (RepairUpdateFlag)
1015 {
1016 //return SELECT_PARTITION_PAGE;
1017 return DEVICE_SETTINGS_PAGE;
1018 }
1019
1020 if (IsUnattendedSetup)
1021 {
1022 return SELECT_PARTITION_PAGE;
1023 }
1024
1025 while (TRUE)
1026 {
1027 CONSOLE_ConInKey(Ir);
1028
1029 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1030 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1031 {
1032 if (ConfirmQuit(Ir) == TRUE)
1033 return QUIT_PAGE;
1034
1035 break;
1036 }
1037 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1038 {
1039 return DEVICE_SETTINGS_PAGE;
1040 // return SCSI_CONTROLLER_PAGE;
1041 }
1042 }
1043
1044 return INSTALL_INTRO_PAGE;
1045 }
1046
1047
1048 #if 0
1049 static PAGE_NUMBER
1050 ScsiControllerPage(PINPUT_RECORD Ir)
1051 {
1052 SetTextXY(6, 8, "Setup detected the following mass storage devices:");
1053
1054 /* FIXME: print loaded mass storage driver descriptions */
1055 #if 0
1056 SetTextXY(8, 10, "TEST device");
1057 #endif
1058
1059
1060 SetStatusText(" ENTER = Continue F3 = Quit");
1061
1062 while (TRUE)
1063 {
1064 ConInKey(Ir);
1065
1066 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1067 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1068 {
1069 if (ConfirmQuit(Ir) == TRUE)
1070 return QUIT_PAGE;
1071
1072 break;
1073 }
1074 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1075 {
1076 return DEVICE_SETTINGS_PAGE;
1077 }
1078 }
1079
1080 return SCSI_CONTROLLER_PAGE;
1081 }
1082 #endif
1083
1084
1085 static PAGE_NUMBER
1086 DeviceSettingsPage(PINPUT_RECORD Ir)
1087 {
1088 static ULONG Line = 16;
1089 MUIDisplayPage(DEVICE_SETTINGS_PAGE);
1090
1091 /* Initialize the computer settings list */
1092 if (ComputerList == NULL)
1093 {
1094 ComputerList = CreateComputerTypeList(SetupInf);
1095 if (ComputerList == NULL)
1096 {
1097 MUIDisplayError(ERROR_LOAD_COMPUTER, Ir, POPUP_WAIT_ENTER);
1098 return QUIT_PAGE;
1099 }
1100 }
1101
1102 /* Initialize the display settings list */
1103 if (DisplayList == NULL)
1104 {
1105 DisplayList = CreateDisplayDriverList(SetupInf);
1106 if (DisplayList == NULL)
1107 {
1108 MUIDisplayError(ERROR_LOAD_DISPLAY, Ir, POPUP_WAIT_ENTER);
1109 return QUIT_PAGE;
1110 }
1111 }
1112
1113 /* Initialize the keyboard settings list */
1114 if (KeyboardList == NULL)
1115 {
1116 KeyboardList = CreateKeyboardDriverList(SetupInf);
1117 if (KeyboardList == NULL)
1118 {
1119 MUIDisplayError(ERROR_LOAD_KEYBOARD, Ir, POPUP_WAIT_ENTER);
1120 return QUIT_PAGE;
1121 }
1122 }
1123
1124 /* Initialize the keyboard layout list */
1125 if (LayoutList == NULL)
1126 {
1127 LayoutList = CreateKeyboardLayoutList(SetupInf, DefaultKBLayout);
1128 if (LayoutList == NULL)
1129 {
1130 /* FIXME: report error */
1131 MUIDisplayError(ERROR_LOAD_KBLAYOUT, Ir, POPUP_WAIT_ENTER);
1132 return QUIT_PAGE;
1133 }
1134 }
1135
1136 MUIDisplayPage(DEVICE_SETTINGS_PAGE);
1137
1138
1139 CONSOLE_SetTextXY(25, 11, GetListEntryText(GetCurrentListEntry((ComputerList))));
1140 CONSOLE_SetTextXY(25, 12, GetListEntryText(GetCurrentListEntry((DisplayList))));
1141 CONSOLE_SetTextXY(25, 13, GetListEntryText(GetCurrentListEntry((KeyboardList))));
1142 CONSOLE_SetTextXY(25, 14, GetListEntryText(GetCurrentListEntry((LayoutList))));
1143
1144 CONSOLE_InvertTextXY(24, Line, 48, 1);
1145
1146 if (RepairUpdateFlag)
1147 {
1148 return SELECT_PARTITION_PAGE;
1149 }
1150
1151 while (TRUE)
1152 {
1153 CONSOLE_ConInKey(Ir);
1154
1155 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1156 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1157 {
1158 CONSOLE_NormalTextXY(24, Line, 48, 1);
1159
1160 if (Line == 14)
1161 Line = 16;
1162 else if (Line == 16)
1163 Line = 11;
1164 else
1165 Line++;
1166
1167 CONSOLE_InvertTextXY(24, Line, 48, 1);
1168 }
1169 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1170 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1171 {
1172 CONSOLE_NormalTextXY(24, Line, 48, 1);
1173
1174 if (Line == 11)
1175 Line = 16;
1176 else if (Line == 16)
1177 Line = 14;
1178 else
1179 Line--;
1180
1181 CONSOLE_InvertTextXY(24, Line, 48, 1);
1182 }
1183 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1184 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1185 {
1186 if (ConfirmQuit(Ir) == TRUE)
1187 return QUIT_PAGE;
1188
1189 break;
1190 }
1191 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1192 {
1193 if (Line == 11)
1194 return COMPUTER_SETTINGS_PAGE;
1195 else if (Line == 12)
1196 return DISPLAY_SETTINGS_PAGE;
1197 else if (Line == 13)
1198 return KEYBOARD_SETTINGS_PAGE;
1199 else if (Line == 14)
1200 return LAYOUT_SETTINGS_PAGE;
1201 else if (Line == 16)
1202 return SELECT_PARTITION_PAGE;
1203 }
1204 }
1205
1206 return DEVICE_SETTINGS_PAGE;
1207 }
1208
1209
1210 static PAGE_NUMBER
1211 ComputerSettingsPage(PINPUT_RECORD Ir)
1212 {
1213 MUIDisplayPage(COMPUTER_SETTINGS_PAGE);
1214
1215 DrawGenericList(ComputerList,
1216 2,
1217 18,
1218 xScreen - 3,
1219 yScreen - 3);
1220
1221 SaveGenericListState(ComputerList);
1222
1223 while (TRUE)
1224 {
1225 CONSOLE_ConInKey(Ir);
1226
1227 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1228 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1229 {
1230 ScrollDownGenericList(ComputerList);
1231 }
1232 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1233 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1234 {
1235 ScrollUpGenericList(ComputerList);
1236 }
1237 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1238 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1239 {
1240 if (ConfirmQuit(Ir) == TRUE)
1241 return QUIT_PAGE;
1242
1243 break;
1244 }
1245 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1246 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
1247 {
1248 RestoreGenericListState(ComputerList);
1249 return DEVICE_SETTINGS_PAGE;
1250 }
1251 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1252 {
1253 return DEVICE_SETTINGS_PAGE;
1254 }
1255 }
1256
1257 return COMPUTER_SETTINGS_PAGE;
1258 }
1259
1260
1261 static PAGE_NUMBER
1262 DisplaySettingsPage(PINPUT_RECORD Ir)
1263 {
1264 MUIDisplayPage(DISPLAY_SETTINGS_PAGE);
1265
1266 DrawGenericList(DisplayList,
1267 2,
1268 18,
1269 xScreen - 3,
1270 yScreen - 3);
1271
1272 SaveGenericListState(DisplayList);
1273
1274 while (TRUE)
1275 {
1276 CONSOLE_ConInKey(Ir);
1277
1278 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1279 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1280 {
1281 ScrollDownGenericList(DisplayList);
1282 }
1283 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1284 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1285 {
1286 ScrollUpGenericList(DisplayList);
1287 }
1288 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1289 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1290 {
1291 if (ConfirmQuit(Ir) == TRUE)
1292 {
1293 return QUIT_PAGE;
1294 }
1295
1296 break;
1297 }
1298 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1299 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
1300 {
1301 RestoreGenericListState(DisplayList);
1302 return DEVICE_SETTINGS_PAGE;
1303 }
1304 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1305 {
1306 return DEVICE_SETTINGS_PAGE;
1307 }
1308 }
1309
1310 return DISPLAY_SETTINGS_PAGE;
1311 }
1312
1313
1314 static PAGE_NUMBER
1315 KeyboardSettingsPage(PINPUT_RECORD Ir)
1316 {
1317 MUIDisplayPage(KEYBOARD_SETTINGS_PAGE);
1318
1319 DrawGenericList(KeyboardList,
1320 2,
1321 18,
1322 xScreen - 3,
1323 yScreen - 3);
1324
1325 SaveGenericListState(KeyboardList);
1326
1327 while (TRUE)
1328 {
1329 CONSOLE_ConInKey(Ir);
1330
1331 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1332 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1333 {
1334 ScrollDownGenericList(KeyboardList);
1335 }
1336 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1337 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1338 {
1339 ScrollUpGenericList(KeyboardList);
1340 }
1341 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1342 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1343 {
1344 if (ConfirmQuit(Ir) == TRUE)
1345 return QUIT_PAGE;
1346
1347 break;
1348 }
1349 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1350 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
1351 {
1352 RestoreGenericListState(KeyboardList);
1353 return DEVICE_SETTINGS_PAGE;
1354 }
1355 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1356 {
1357 return DEVICE_SETTINGS_PAGE;
1358 }
1359 }
1360
1361 return KEYBOARD_SETTINGS_PAGE;
1362 }
1363
1364
1365 static PAGE_NUMBER
1366 LayoutSettingsPage(PINPUT_RECORD Ir)
1367 {
1368 MUIDisplayPage(LAYOUT_SETTINGS_PAGE);
1369
1370 DrawGenericList(LayoutList,
1371 2,
1372 18,
1373 xScreen - 3,
1374 yScreen - 3);
1375
1376 SaveGenericListState(LayoutList);
1377
1378 while (TRUE)
1379 {
1380 CONSOLE_ConInKey(Ir);
1381
1382 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1383 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1384 {
1385 ScrollDownGenericList(LayoutList);
1386 }
1387 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1388 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1389 {
1390 ScrollUpGenericList(LayoutList);
1391 }
1392 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1393 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_NEXT)) /* PAGE DOWN */
1394 {
1395 ScrollPageDownGenericList(LayoutList);
1396 }
1397 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1398 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_PRIOR)) /* PAGE UP */
1399 {
1400 ScrollPageUpGenericList(LayoutList);
1401 }
1402 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1403 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1404 {
1405 if (ConfirmQuit(Ir) == TRUE)
1406 return QUIT_PAGE;
1407
1408 break;
1409 }
1410 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1411 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
1412 {
1413 RestoreGenericListState(LayoutList);
1414 return DEVICE_SETTINGS_PAGE;
1415 }
1416 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1417 {
1418 return DEVICE_SETTINGS_PAGE;
1419 }
1420 else if ((Ir->Event.KeyEvent.uChar.AsciiChar > 0x60) && (Ir->Event.KeyEvent.uChar.AsciiChar < 0x7b))
1421 {
1422 /* a-z */
1423 GenericListKeyPress(LayoutList , Ir->Event.KeyEvent.uChar.AsciiChar);
1424 }
1425 }
1426
1427 return LAYOUT_SETTINGS_PAGE;
1428 }
1429
1430
1431 #if 0
1432 static BOOL
1433 IsDiskSizeValid(PPARTENTRY PartEntry)
1434 {
1435 ULONGLONG m1, m2;
1436
1437 /* check for unpartitioned space */
1438 m1 = PartEntry->UnpartitionedLength;
1439 m1 = (m1 + (1 << 19)) >> 20; /* in MBytes (rounded) */
1440
1441 if( m1 > RequiredPartitionDiskSpace)
1442 {
1443 return TRUE;
1444 }
1445
1446 /* check for partitioned space */
1447 m2 = PartEntry->PartInfo[0].PartitionLength.QuadPart;
1448 m2 = (m2 + (1 << 19)) >> 20; /* in MBytes (rounded) */
1449 if (m2 < RequiredPartitionDiskSpace)
1450 {
1451 /* partition is too small so ask for another partion */
1452 DPRINT1("Partition is too small(unpartitioned: %I64u MB, partitioned: %I64u MB), required disk space is %lu MB\n", m1, m2, RequiredPartitionDiskSpace);
1453 return FALSE;
1454 }
1455 else
1456 {
1457 return TRUE;
1458 }
1459 }
1460 #endif
1461
1462
1463 static PAGE_NUMBER
1464 SelectPartitionPage(PINPUT_RECORD Ir)
1465 {
1466 ULONG Error;
1467
1468 MUIDisplayPage(SELECT_PARTITION_PAGE);
1469
1470 if (PartitionList == NULL)
1471 {
1472 PartitionList = CreatePartitionList(2,
1473 21,
1474 xScreen - 3,
1475 yScreen - 3);
1476 if (PartitionList == NULL)
1477 {
1478 /* FIXME: show an error dialog */
1479 return QUIT_PAGE;
1480 }
1481 else if (IsListEmpty (&PartitionList->DiskListHead))
1482 {
1483 MUIDisplayError(ERROR_NO_HDD, Ir, POPUP_WAIT_ENTER);
1484 return QUIT_PAGE;
1485 }
1486 }
1487
1488 DrawPartitionList(PartitionList);
1489
1490 /* Warn about partitions created by Linux Fdisk */
1491 if (WarnLinuxPartitions == TRUE &&
1492 CheckForLinuxFdiskPartitions(PartitionList) == TRUE)
1493 {
1494 MUIDisplayError(ERROR_WARN_PARTITION, NULL, POPUP_WAIT_NONE);
1495
1496 while (TRUE)
1497 {
1498 CONSOLE_ConInKey(Ir);
1499
1500 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1501 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1502 {
1503 return QUIT_PAGE;
1504 }
1505 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
1506 {
1507 WarnLinuxPartitions = FALSE;
1508 return SELECT_PARTITION_PAGE;
1509 }
1510 }
1511 }
1512
1513 if (IsUnattendedSetup)
1514 {
1515 if (!SelectPartition(PartitionList, UnattendDestinationDiskNumber, UnattendDestinationPartitionNumber))
1516 {
1517 if (AutoPartition)
1518 {
1519 #if 0
1520 if (!IsDiskSizeValid(PartitionList->CurrentPartition))
1521 {
1522 MUIDisplayError(ERROR_INSUFFICIENT_DISKSPACE, Ir, POPUP_WAIT_ANY_KEY);
1523 return SELECT_PARTITION_PAGE; /* let the user select another partition */
1524 }
1525 #endif
1526 CreatePrimaryPartition(PartitionList,
1527 PartitionList->CurrentPartition->SectorCount.QuadPart,
1528 TRUE);
1529
1530 DestinationDriveLetter = (WCHAR)PartitionList->CurrentPartition->DriveLetter;
1531
1532 return SELECT_FILE_SYSTEM_PAGE;
1533 }
1534 }
1535 else
1536 {
1537 #if 0
1538 if (!IsDiskSizeValid(PartitionList->CurrentPartition))
1539 {
1540 MUIDisplayError(ERROR_INSUFFICIENT_DISKSPACE, Ir, POPUP_WAIT_ANY_KEY);
1541 return SELECT_PARTITION_PAGE; /* let the user select another partition */
1542 }
1543 #endif
1544 DestinationDriveLetter = (WCHAR)PartitionList->CurrentPartition->DriveLetter;
1545
1546 return SELECT_FILE_SYSTEM_PAGE;
1547 }
1548 }
1549
1550 while (TRUE)
1551 {
1552 /* Update status text */
1553 if (PartitionList->CurrentPartition == NULL ||
1554 PartitionList->CurrentPartition->IsPartitioned == FALSE)
1555 {
1556 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATEPARTITION));
1557 }
1558 else if (IsContainerPartition(PartitionList->CurrentPartition->PartitionType))
1559 {
1560 CONSOLE_SetStatusText(MUIGetString(STRING_DELETEPARTITION));
1561 }
1562 else
1563 {
1564 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLDELETEPARTITION));
1565 }
1566
1567 CONSOLE_ConInKey(Ir);
1568
1569 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1570 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1571 {
1572 if (ConfirmQuit(Ir) == TRUE)
1573 {
1574 DestroyPartitionList(PartitionList);
1575 PartitionList = NULL;
1576 return QUIT_PAGE;
1577 }
1578
1579 break;
1580 }
1581 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1582 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1583 {
1584 if (ScrollDownPartitionList(PartitionList))
1585 DrawPartitionList(PartitionList);
1586 }
1587 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1588 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1589 {
1590 if (ScrollUpPartitionList(PartitionList))
1591 DrawPartitionList(PartitionList);
1592 }
1593 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
1594 {
1595 #if 0
1596 if (!IsDiskSizeValid(PartitionList->CurrentPartition))
1597 {
1598 MUIDisplayError(ERROR_INSUFFICIENT_DISKSPACE, Ir, POPUP_WAIT_ANY_KEY);
1599 return SELECT_PARTITION_PAGE; /* let the user select another partition */
1600 }
1601 #endif
1602 if (IsContainerPartition(PartitionList->CurrentPartition->PartitionType))
1603 continue; //return SELECT_PARTITION_PAGE;
1604
1605 if (PartitionList->CurrentPartition == NULL ||
1606 PartitionList->CurrentPartition->IsPartitioned == FALSE)
1607 {
1608 CreatePrimaryPartition(PartitionList,
1609 0ULL,
1610 TRUE);
1611 }
1612
1613 DestinationDriveLetter = (WCHAR)PartitionList->CurrentPartition->DriveLetter;
1614
1615 return SELECT_FILE_SYSTEM_PAGE;
1616 }
1617 else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'P') /* P */
1618 {
1619 Error = PrimaryPartitionCreationChecks(PartitionList);
1620 if (Error != NOT_AN_ERROR)
1621 {
1622 MUIDisplayError(Error, Ir, POPUP_WAIT_ANY_KEY);
1623 return SELECT_PARTITION_PAGE;
1624 }
1625
1626 return CREATE_PRIMARY_PARTITION_PAGE;
1627 }
1628 else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'E') /* E */
1629 {
1630 Error = ExtendedPartitionCreationChecks(PartitionList);
1631 if (Error != NOT_AN_ERROR)
1632 {
1633 MUIDisplayError(Error, Ir, POPUP_WAIT_ANY_KEY);
1634 return SELECT_PARTITION_PAGE;
1635 }
1636
1637 return CREATE_EXTENDED_PARTITION_PAGE;
1638 }
1639 else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'D') /* D */
1640 {
1641 if (PartitionList->CurrentPartition->IsPartitioned == FALSE)
1642 {
1643 MUIDisplayError(ERROR_DELETE_SPACE, Ir, POPUP_WAIT_ANY_KEY);
1644 return SELECT_PARTITION_PAGE;
1645 }
1646
1647 return DELETE_PARTITION_PAGE;
1648 }
1649 }
1650
1651 return SELECT_PARTITION_PAGE;
1652 }
1653
1654
1655 static VOID
1656 DrawInputField(ULONG FieldLength,
1657 SHORT Left,
1658 SHORT Top,
1659 PCHAR FieldContent)
1660 {
1661 CHAR buf[100];
1662 COORD coPos;
1663 DWORD Written;
1664
1665 coPos.X = Left;
1666 coPos.Y = Top;
1667 memset(buf, '_', sizeof(buf));
1668 buf[FieldLength - strlen(FieldContent)] = 0;
1669 strcat(buf, FieldContent);
1670
1671 WriteConsoleOutputCharacterA(StdOutput,
1672 buf,
1673 strlen(buf),
1674 coPos,
1675 &Written);
1676 }
1677
1678
1679 #define PARTITION_SIZE_INPUT_FIELD_LENGTH 6
1680 /* Restriction for MaxSize: pow(10, PARTITION_SIZE_INPUT_FIELD_LENGTH)-1 */
1681 #define PARTITION_MAXSIZE 999999
1682
1683 static VOID
1684 ShowPartitionSizeInputBox(SHORT Left,
1685 SHORT Top,
1686 SHORT Right,
1687 SHORT Bottom,
1688 ULONG MaxSize,
1689 PCHAR InputBuffer,
1690 PBOOLEAN Quit,
1691 PBOOLEAN Cancel)
1692 {
1693 INPUT_RECORD Ir;
1694 COORD coPos;
1695 DWORD Written;
1696 CHAR Buffer[100];
1697 ULONG Index;
1698 CHAR ch;
1699 SHORT iLeft;
1700 SHORT iTop;
1701
1702 if (Quit != NULL)
1703 *Quit = FALSE;
1704
1705 if (Cancel != NULL)
1706 *Cancel = FALSE;
1707
1708 DrawBox(Left, Top, Right - Left + 1, Bottom - Top + 1);
1709
1710 /* Print message */
1711 coPos.X = Left + 2;
1712 coPos.Y = Top + 2;
1713 strcpy(Buffer, MUIGetString(STRING_PARTITIONSIZE));
1714 iLeft = coPos.X + strlen(Buffer) + 1;
1715 iTop = coPos.Y;
1716
1717 WriteConsoleOutputCharacterA(StdOutput,
1718 Buffer,
1719 strlen (Buffer),
1720 coPos,
1721 &Written);
1722
1723 sprintf(Buffer, MUIGetString(STRING_MAXSIZE), MaxSize);
1724 coPos.X = iLeft + PARTITION_SIZE_INPUT_FIELD_LENGTH + 1;
1725 coPos.Y = iTop;
1726 WriteConsoleOutputCharacterA(StdOutput,
1727 Buffer,
1728 strlen (Buffer),
1729 coPos,
1730 &Written);
1731
1732 sprintf(Buffer, "%lu", MaxSize);
1733 Index = strlen(Buffer);
1734 DrawInputField(PARTITION_SIZE_INPUT_FIELD_LENGTH,
1735 iLeft,
1736 iTop,
1737 Buffer);
1738
1739 while (TRUE)
1740 {
1741 CONSOLE_ConInKey(&Ir);
1742
1743 if ((Ir.Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1744 (Ir.Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1745 {
1746 if (Quit != NULL)
1747 *Quit = TRUE;
1748
1749 Buffer[0] = 0;
1750 break;
1751 }
1752 else if (Ir.Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
1753 {
1754 break;
1755 }
1756 else if (Ir.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESCAPE */
1757 {
1758 if (Cancel != NULL)
1759 *Cancel = TRUE;
1760
1761 Buffer[0] = 0;
1762 break;
1763 }
1764 else if ((Ir.Event.KeyEvent.wVirtualKeyCode == VK_BACK) && /* BACKSPACE */
1765 (Index > 0))
1766 {
1767 Index--;
1768 Buffer[Index] = 0;
1769
1770 DrawInputField(PARTITION_SIZE_INPUT_FIELD_LENGTH,
1771 iLeft,
1772 iTop,
1773 Buffer);
1774 }
1775 else if ((Ir.Event.KeyEvent.uChar.AsciiChar != 0x00) &&
1776 (Index < PARTITION_SIZE_INPUT_FIELD_LENGTH))
1777 {
1778 ch = Ir.Event.KeyEvent.uChar.AsciiChar;
1779
1780 if ((ch >= '0') && (ch <= '9'))
1781 {
1782 Buffer[Index] = ch;
1783 Index++;
1784 Buffer[Index] = 0;
1785
1786 DrawInputField(PARTITION_SIZE_INPUT_FIELD_LENGTH,
1787 iLeft,
1788 iTop,
1789 Buffer);
1790 }
1791 }
1792 }
1793
1794 strcpy(InputBuffer, Buffer);
1795 }
1796
1797
1798 static PAGE_NUMBER
1799 CreatePrimaryPartitionPage(PINPUT_RECORD Ir)
1800 {
1801 PDISKENTRY DiskEntry;
1802 PPARTENTRY PartEntry;
1803 BOOLEAN Quit;
1804 BOOLEAN Cancel;
1805 CHAR InputBuffer[50];
1806 ULONG MaxSize;
1807 ULONGLONG PartSize;
1808 ULONGLONG DiskSize;
1809 ULONGLONG SectorCount;
1810 PCHAR Unit;
1811
1812 if (PartitionList == NULL ||
1813 PartitionList->CurrentDisk == NULL ||
1814 PartitionList->CurrentPartition == NULL)
1815 {
1816 /* FIXME: show an error dialog */
1817 return QUIT_PAGE;
1818 }
1819
1820 DiskEntry = PartitionList->CurrentDisk;
1821 PartEntry = PartitionList->CurrentPartition;
1822
1823 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
1824
1825 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSENEWPARTITION));
1826
1827 DiskSize = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
1828 #if 0
1829 if (DiskSize >= 10737418240) /* 10 GB */
1830 {
1831 DiskSize = DiskSize / 1073741824;
1832 Unit = MUIGetString(STRING_GB);
1833 }
1834 else
1835 #endif
1836 {
1837 DiskSize = DiskSize / 1048576;
1838 if (DiskSize == 0)
1839 DiskSize = 1;
1840
1841 Unit = MUIGetString(STRING_MB);
1842 }
1843
1844 if (DiskEntry->DriverName.Length > 0)
1845 {
1846 CONSOLE_PrintTextXY(6, 10,
1847 MUIGetString(STRING_HDINFOPARTCREATE),
1848 DiskSize,
1849 Unit,
1850 DiskEntry->DiskNumber,
1851 DiskEntry->Port,
1852 DiskEntry->Bus,
1853 DiskEntry->Id,
1854 &DiskEntry->DriverName);
1855 }
1856 else
1857 {
1858 CONSOLE_PrintTextXY(6, 10,
1859 MUIGetString(STRING_HDDINFOUNK1),
1860 DiskSize,
1861 Unit,
1862 DiskEntry->DiskNumber,
1863 DiskEntry->Port,
1864 DiskEntry->Bus,
1865 DiskEntry->Id);
1866 }
1867
1868 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE));
1869
1870 #if 0
1871 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
1872 PartitionList->CurrentPartition->SectorCount * DiskEntry->BytesPerSector / 1048576);
1873 #endif
1874
1875 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION));
1876
1877 PartEntry = PartitionList->CurrentPartition;
1878 while (TRUE)
1879 {
1880 MaxSize = (PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector) / 1048576; /* in MBytes (rounded) */
1881
1882 if (MaxSize > PARTITION_MAXSIZE)
1883 MaxSize = PARTITION_MAXSIZE;
1884
1885 ShowPartitionSizeInputBox(12, 14, xScreen - 12, 17, /* left, top, right, bottom */
1886 MaxSize, InputBuffer, &Quit, &Cancel);
1887
1888 if (Quit == TRUE)
1889 {
1890 if (ConfirmQuit (Ir) == TRUE)
1891 {
1892 return QUIT_PAGE;
1893 }
1894 }
1895 else if (Cancel == TRUE)
1896 {
1897 return SELECT_PARTITION_PAGE;
1898 }
1899 else
1900 {
1901 PartSize = atoi(InputBuffer);
1902
1903 if (PartSize < 1)
1904 {
1905 /* Too small */
1906 continue;
1907 }
1908
1909 if (PartSize > MaxSize)
1910 {
1911 /* Too large */
1912 continue;
1913 }
1914
1915 /* Convert to bytes */
1916 if (PartSize == MaxSize)
1917 {
1918 /* Use all of the unpartitioned disk space */
1919 SectorCount = PartEntry->SectorCount.QuadPart;
1920 }
1921 else
1922 {
1923 /* Calculate the sector count from the size in MB */
1924 SectorCount = PartSize * 1048576 / DiskEntry->BytesPerSector;
1925
1926 /* But never get larger than the unpartitioned disk space */
1927 if (SectorCount > PartEntry->SectorCount.QuadPart)
1928 SectorCount = PartEntry->SectorCount.QuadPart;
1929 }
1930
1931 DPRINT ("Partition size: %I64u bytes\n", PartSize);
1932
1933 CreatePrimaryPartition(PartitionList,
1934 SectorCount,
1935 FALSE);
1936
1937 return SELECT_PARTITION_PAGE;
1938 }
1939 }
1940
1941 return CREATE_PRIMARY_PARTITION_PAGE;
1942 }
1943
1944
1945 static PAGE_NUMBER
1946 CreateExtendedPartitionPage(PINPUT_RECORD Ir)
1947 {
1948 PDISKENTRY DiskEntry;
1949 PPARTENTRY PartEntry;
1950 BOOLEAN Quit;
1951 BOOLEAN Cancel;
1952 CHAR InputBuffer[50];
1953 ULONG MaxSize;
1954 ULONGLONG PartSize;
1955 ULONGLONG DiskSize;
1956 ULONGLONG SectorCount;
1957 PCHAR Unit;
1958
1959 if (PartitionList == NULL ||
1960 PartitionList->CurrentDisk == NULL ||
1961 PartitionList->CurrentPartition == NULL)
1962 {
1963 /* FIXME: show an error dialog */
1964 return QUIT_PAGE;
1965 }
1966
1967 DiskEntry = PartitionList->CurrentDisk;
1968 PartEntry = PartitionList->CurrentPartition;
1969
1970 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
1971
1972 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSE_NEW_EXTENDED_PARTITION));
1973
1974 DiskSize = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
1975 #if 0
1976 if (DiskSize >= 10737418240) /* 10 GB */
1977 {
1978 DiskSize = DiskSize / 1073741824;
1979 Unit = MUIGetString(STRING_GB);
1980 }
1981 else
1982 #endif
1983 {
1984 DiskSize = DiskSize / 1048576;
1985 if (DiskSize == 0)
1986 DiskSize = 1;
1987
1988 Unit = MUIGetString(STRING_MB);
1989 }
1990
1991 if (DiskEntry->DriverName.Length > 0)
1992 {
1993 CONSOLE_PrintTextXY(6, 10,
1994 MUIGetString(STRING_HDINFOPARTCREATE),
1995 DiskSize,
1996 Unit,
1997 DiskEntry->DiskNumber,
1998 DiskEntry->Port,
1999 DiskEntry->Bus,
2000 DiskEntry->Id,
2001 &DiskEntry->DriverName);
2002 }
2003 else
2004 {
2005 CONSOLE_PrintTextXY(6, 10,
2006 MUIGetString(STRING_HDDINFOUNK1),
2007 DiskSize,
2008 Unit,
2009 DiskEntry->DiskNumber,
2010 DiskEntry->Port,
2011 DiskEntry->Bus,
2012 DiskEntry->Id);
2013 }
2014
2015 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE));
2016
2017 #if 0
2018 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2019 PartitionList->CurrentPartition->SectorCount * DiskEntry->BytesPerSector / 1048576);
2020 #endif
2021
2022 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION));
2023
2024 PartEntry = PartitionList->CurrentPartition;
2025 while (TRUE)
2026 {
2027 MaxSize = (PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector) / 1048576; /* in MBytes (rounded) */
2028
2029 if (MaxSize > PARTITION_MAXSIZE)
2030 MaxSize = PARTITION_MAXSIZE;
2031
2032 ShowPartitionSizeInputBox(12, 14, xScreen - 12, 17, /* left, top, right, bottom */
2033 MaxSize, InputBuffer, &Quit, &Cancel);
2034
2035 if (Quit == TRUE)
2036 {
2037 if (ConfirmQuit (Ir) == TRUE)
2038 {
2039 return QUIT_PAGE;
2040 }
2041 }
2042 else if (Cancel == TRUE)
2043 {
2044 return SELECT_PARTITION_PAGE;
2045 }
2046 else
2047 {
2048 PartSize = atoi(InputBuffer);
2049
2050 if (PartSize < 1)
2051 {
2052 /* Too small */
2053 continue;
2054 }
2055
2056 if (PartSize > MaxSize)
2057 {
2058 /* Too large */
2059 continue;
2060 }
2061
2062 /* Convert to bytes */
2063 if (PartSize == MaxSize)
2064 {
2065 /* Use all of the unpartitioned disk space */
2066 SectorCount = PartEntry->SectorCount.QuadPart;
2067 }
2068 else
2069 {
2070 /* Calculate the sector count from the size in MB */
2071 SectorCount = PartSize * 1048576 / DiskEntry->BytesPerSector;
2072
2073 /* But never get larger than the unpartitioned disk space */
2074 if (SectorCount > PartEntry->SectorCount.QuadPart)
2075 SectorCount = PartEntry->SectorCount.QuadPart;
2076 }
2077
2078 DPRINT ("Partition size: %I64u bytes\n", PartSize);
2079
2080 CreateExtendedPartition(PartitionList,
2081 SectorCount);
2082
2083 return SELECT_PARTITION_PAGE;
2084 }
2085 }
2086
2087 return CREATE_EXTENDED_PARTITION_PAGE;
2088 }
2089
2090
2091 static PAGE_NUMBER
2092 DeletePartitionPage(PINPUT_RECORD Ir)
2093 {
2094 PDISKENTRY DiskEntry;
2095 PPARTENTRY PartEntry;
2096 ULONGLONG DiskSize;
2097 ULONGLONG PartSize;
2098 PCHAR Unit;
2099 PCHAR PartType;
2100
2101 if (PartitionList == NULL ||
2102 PartitionList->CurrentDisk == NULL ||
2103 PartitionList->CurrentPartition == NULL)
2104 {
2105 /* FIXME: show an error dialog */
2106 return QUIT_PAGE;
2107 }
2108
2109 DiskEntry = PartitionList->CurrentDisk;
2110 PartEntry = PartitionList->CurrentPartition;
2111
2112 MUIDisplayPage(DELETE_PARTITION_PAGE);
2113
2114 /* Determine partition type */
2115 PartType = NULL;
2116 if (PartEntry->New == TRUE)
2117 {
2118 PartType = MUIGetString(STRING_UNFORMATTED);
2119 }
2120 else if (PartEntry->IsPartitioned == TRUE)
2121 {
2122 if ((PartEntry->PartitionType == PARTITION_FAT_12) ||
2123 (PartEntry->PartitionType == PARTITION_FAT_16) ||
2124 (PartEntry->PartitionType == PARTITION_HUGE) ||
2125 (PartEntry->PartitionType == PARTITION_XINT13))
2126 {
2127 PartType = "FAT";
2128 }
2129 else if ((PartEntry->PartitionType == PARTITION_FAT32) ||
2130 (PartEntry->PartitionType == PARTITION_FAT32_XINT13))
2131 {
2132 PartType = "FAT32";
2133 }
2134 else if (PartEntry->PartitionType == PARTITION_EXT2)
2135 {
2136 PartType = "EXT2";
2137 }
2138 else if (PartEntry->PartitionType == PARTITION_IFS)
2139 {
2140 PartType = "NTFS"; /* FIXME: Not quite correct! */
2141 }
2142 else if (IsContainerPartition(PartEntry->PartitionType))
2143 {
2144 PartType = MUIGetString(STRING_EXTENDED_PARTITION);
2145 }
2146 }
2147
2148 PartSize = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
2149 #if 0
2150 if (PartSize >= 10737418240) /* 10 GB */
2151 {
2152 PartSize = PartSize / 1073741824;
2153 Unit = MUIGetString(STRING_GB);
2154 }
2155 else
2156 #endif
2157 if (PartSize >= 10485760) /* 10 MB */
2158 {
2159 PartSize = PartSize / 1048576;
2160 Unit = MUIGetString(STRING_MB);
2161 }
2162 else
2163 {
2164 PartSize = PartSize / 1024;
2165 Unit = MUIGetString(STRING_KB);
2166 }
2167
2168 if (PartType == NULL)
2169 {
2170 CONSOLE_PrintTextXY(6, 10,
2171 MUIGetString(STRING_HDDINFOUNK2),
2172 (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
2173 (PartEntry->DriveLetter == 0) ? '-' : ':',
2174 PartEntry->PartitionType,
2175 PartSize,
2176 Unit);
2177 }
2178 else
2179 {
2180 CONSOLE_PrintTextXY(6, 10,
2181 " %c%c %s %I64u %s",
2182 (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
2183 (PartEntry->DriveLetter == 0) ? '-' : ':',
2184 PartType,
2185 PartSize,
2186 Unit);
2187 }
2188
2189 DiskSize = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
2190 #if 0
2191 if (DiskSize >= 10737418240) /* 10 GB */
2192 {
2193 DiskSize = DiskSize / 1073741824;
2194 Unit = MUIGetString(STRING_GB);
2195 }
2196 else
2197 #endif
2198 {
2199 DiskSize = DiskSize / 1048576;
2200 if (DiskSize == 0)
2201 DiskSize = 1;
2202
2203 Unit = MUIGetString(STRING_MB);
2204 }
2205
2206 if (DiskEntry->DriverName.Length > 0)
2207 {
2208 CONSOLE_PrintTextXY(6, 12,
2209 MUIGetString(STRING_HDINFOPARTDELETE),
2210 DiskSize,
2211 Unit,
2212 DiskEntry->DiskNumber,
2213 DiskEntry->Port,
2214 DiskEntry->Bus,
2215 DiskEntry->Id,
2216 &DiskEntry->DriverName);
2217 }
2218 else
2219 {
2220 CONSOLE_PrintTextXY(6, 12,
2221 MUIGetString(STRING_HDDINFOUNK3),
2222 DiskSize,
2223 Unit,
2224 DiskEntry->DiskNumber,
2225 DiskEntry->Port,
2226 DiskEntry->Bus,
2227 DiskEntry->Id);
2228 }
2229
2230 while (TRUE)
2231 {
2232 CONSOLE_ConInKey(Ir);
2233
2234 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2235 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
2236 {
2237 if (ConfirmQuit(Ir) == TRUE)
2238 {
2239 return QUIT_PAGE;
2240 }
2241
2242 break;
2243 }
2244 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESC */
2245 {
2246 return SELECT_PARTITION_PAGE;
2247 }
2248 else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'D') /* D */
2249 {
2250 DeleteCurrentPartition(PartitionList);
2251
2252 return SELECT_PARTITION_PAGE;
2253 }
2254 }
2255
2256 return DELETE_PARTITION_PAGE;
2257 }
2258
2259
2260 static PAGE_NUMBER
2261 SelectFileSystemPage(PINPUT_RECORD Ir)
2262 {
2263 PDISKENTRY DiskEntry;
2264 PPARTENTRY PartEntry;
2265 ULONGLONG DiskSize;
2266 ULONGLONG PartSize;
2267 PCHAR DiskUnit;
2268 PCHAR PartUnit;
2269 PCHAR PartType;
2270
2271 if (PartitionList == NULL ||
2272 PartitionList->CurrentDisk == NULL ||
2273 PartitionList->CurrentPartition == NULL)
2274 {
2275 /* FIXME: show an error dialog */
2276 return QUIT_PAGE;
2277 }
2278
2279 DiskEntry = PartitionList->CurrentDisk;
2280 PartEntry = PartitionList->CurrentPartition;
2281
2282 /* adjust disk size */
2283 DiskSize = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
2284 if (DiskSize >= 10737418240) /* 10 GB */
2285 {
2286 DiskSize = DiskSize / 1073741824;
2287 DiskUnit = MUIGetString(STRING_GB);
2288 }
2289 else
2290 {
2291 DiskSize = DiskSize / 1048576;
2292 DiskUnit = MUIGetString(STRING_MB);
2293 }
2294
2295 /* adjust partition size */
2296 PartSize = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
2297 if (PartSize >= 10737418240) /* 10 GB */
2298 {
2299 PartSize = PartSize / 1073741824;
2300 PartUnit = MUIGetString(STRING_GB);
2301 }
2302 else
2303 {
2304 PartSize = PartSize / 1048576;
2305 PartUnit = MUIGetString(STRING_MB);
2306 }
2307
2308 /* adjust partition type */
2309 if ((PartEntry->PartitionType == PARTITION_FAT_12) ||
2310 (PartEntry->PartitionType == PARTITION_FAT_16) ||
2311 (PartEntry->PartitionType == PARTITION_HUGE) ||
2312 (PartEntry->PartitionType == PARTITION_XINT13))
2313 {
2314 PartType = "FAT";
2315 }
2316 else if ((PartEntry->PartitionType == PARTITION_FAT32) ||
2317 (PartEntry->PartitionType == PARTITION_FAT32_XINT13))
2318 {
2319 PartType = "FAT32";
2320 }
2321 else if (PartEntry->PartitionType == PARTITION_EXT2)
2322 {
2323 PartType = "EXT2";
2324 }
2325 else if (PartEntry->PartitionType == PARTITION_IFS)
2326 {
2327 PartType = "NTFS"; /* FIXME: Not quite correct! */
2328 }
2329 else if (PartEntry->PartitionType == PARTITION_ENTRY_UNUSED)
2330 {
2331 PartType = MUIGetString(STRING_FORMATUNUSED);
2332 }
2333 else
2334 {
2335 PartType = MUIGetString(STRING_FORMATUNKNOWN);
2336 }
2337
2338 if (PartEntry->AutoCreate == TRUE)
2339 {
2340 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NEWPARTITION));
2341
2342 #if 0
2343 CONSOLE_PrintTextXY(8, 10, "Partition %lu (%I64u %s) %s of",
2344 PartEntry->PartitionNumber,
2345 PartSize,
2346 PartUnit,
2347 PartType);
2348 #endif
2349
2350 CONSOLE_PrintTextXY(8, 10, MUIGetString(STRING_HDINFOPARTZEROED),
2351 DiskEntry->DiskNumber,
2352 DiskSize,
2353 DiskUnit,
2354 DiskEntry->Port,
2355 DiskEntry->Bus,
2356 DiskEntry->Id,
2357 &DiskEntry->DriverName);
2358
2359 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_PARTFORMAT));
2360
2361
2362 PartEntry->AutoCreate = FALSE;
2363 }
2364 else if (PartEntry->New == TRUE)
2365 {
2366 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDPART));
2367 CONSOLE_SetTextXY(6, 10, MUIGetString(STRING_PARTFORMAT));
2368 }
2369 else
2370 {
2371 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_INSTALLONPART));
2372
2373 if (PartType == NULL)
2374 {
2375 CONSOLE_PrintTextXY(8, 10,
2376 MUIGetString(STRING_HDDINFOUNK4),
2377 (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
2378 (PartEntry->DriveLetter == 0) ? '-' : ':',
2379 PartEntry->PartitionType,
2380 PartSize,
2381 PartUnit);
2382 }
2383 else
2384 {
2385 CONSOLE_PrintTextXY(8, 10,
2386 "%c%c %s %I64u %s",
2387 (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
2388 (PartEntry->DriveLetter == 0) ? '-' : ':',
2389 PartType,
2390 PartSize,
2391 PartUnit);
2392 }
2393
2394 CONSOLE_PrintTextXY(6, 12, MUIGetString(STRING_HDINFOPARTEXISTS),
2395 DiskEntry->DiskNumber,
2396 DiskSize,
2397 DiskUnit,
2398 DiskEntry->Port,
2399 DiskEntry->Bus,
2400 DiskEntry->Id,
2401 &DiskEntry->DriverName);
2402 }
2403
2404 MUIDisplayPage(SELECT_FILE_SYSTEM_PAGE);
2405
2406 if (FileSystemList == NULL)
2407 {
2408 FileSystemList = CreateFileSystemList(6, 26, PartEntry->New, L"FAT");
2409 if (FileSystemList == NULL)
2410 {
2411 /* FIXME: show an error dialog */
2412 return QUIT_PAGE;
2413 }
2414
2415 /* FIXME: Add file systems to list */
2416 }
2417
2418 DrawFileSystemList(FileSystemList);
2419
2420 if (RepairUpdateFlag)
2421 {
2422 return CHECK_FILE_SYSTEM_PAGE;
2423 //return SELECT_PARTITION_PAGE;
2424 }
2425
2426 if (IsUnattendedSetup)
2427 {
2428 if (UnattendFormatPartition)
2429 {
2430 return FORMAT_PARTITION_PAGE;
2431 }
2432
2433 return CHECK_FILE_SYSTEM_PAGE;
2434 }
2435
2436 while (TRUE)
2437 {
2438 CONSOLE_ConInKey(Ir);
2439
2440 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2441 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
2442 {
2443 if (ConfirmQuit(Ir) == TRUE)
2444 {
2445 return QUIT_PAGE;
2446 }
2447
2448 break;
2449 }
2450 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2451 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
2452 {
2453 return SELECT_PARTITION_PAGE;
2454 }
2455 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2456 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
2457 {
2458 ScrollDownFileSystemList(FileSystemList);
2459 }
2460 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2461 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
2462 {
2463 ScrollUpFileSystemList(FileSystemList);
2464 }
2465 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
2466 {
2467 if (!FileSystemList->Selected->FormatFunc)
2468 {
2469 return CHECK_FILE_SYSTEM_PAGE;
2470 }
2471 else
2472 {
2473 return FORMAT_PARTITION_PAGE;
2474 }
2475 }
2476 }
2477
2478 return SELECT_FILE_SYSTEM_PAGE;
2479 }
2480
2481
2482 static ULONG
2483 FormatPartitionPage(PINPUT_RECORD Ir)
2484 {
2485 WCHAR PathBuffer[MAX_PATH];
2486 PDISKENTRY DiskEntry;
2487 PPARTENTRY PartEntry;
2488 NTSTATUS Status;
2489
2490 #ifndef NDEBUG
2491 ULONG Line;
2492 ULONG i;
2493 PLIST_ENTRY Entry;
2494 #endif
2495
2496 MUIDisplayPage(FORMAT_PARTITION_PAGE);
2497
2498 if (PartitionList == NULL ||
2499 PartitionList->CurrentDisk == NULL ||
2500 PartitionList->CurrentPartition == NULL)
2501 {
2502 /* FIXME: show an error dialog */
2503 return QUIT_PAGE;
2504 }
2505
2506 DiskEntry = PartitionList->CurrentDisk;
2507 PartEntry = PartitionList->CurrentPartition;
2508
2509 while (TRUE)
2510 {
2511 if (!IsUnattendedSetup)
2512 {
2513 CONSOLE_ConInKey(Ir);
2514 }
2515
2516 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2517 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
2518 {
2519 if (ConfirmQuit(Ir) == TRUE)
2520 {
2521 return QUIT_PAGE;
2522 }
2523
2524 break;
2525 }
2526 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN || IsUnattendedSetup) /* ENTER */
2527 {
2528 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
2529
2530 if (wcscmp(FileSystemList->Selected->FileSystem, L"FAT") == 0)
2531 {
2532 if (PartEntry->SectorCount.QuadPart < 8192)
2533 {
2534 /* FAT12 CHS partition (disk is smaller than 4.1MB) */
2535 PartEntry->PartitionType = PARTITION_FAT_12;
2536 }
2537 else if (PartEntry->StartSector.QuadPart < 1450560)
2538 {
2539 /* Partition starts below the 8.4GB boundary ==> CHS partition */
2540
2541 if (PartEntry->SectorCount.QuadPart < 65536)
2542 {
2543 /* FAT16 CHS partition (partiton size < 32MB) */
2544 PartEntry->PartitionType = PARTITION_FAT_16;
2545 }
2546 else if (PartEntry->SectorCount.QuadPart < 1048576)
2547 {
2548 /* FAT16 CHS partition (partition size < 512MB) */
2549 PartEntry->PartitionType = PARTITION_HUGE;
2550 }
2551 else
2552 {
2553 /* FAT32 CHS partition (partition size >= 512MB) */
2554 PartEntry->PartitionType = PARTITION_FAT32;
2555 }
2556 }
2557 else
2558 {
2559 /* Partition starts above the 8.4GB boundary ==> LBA partition */
2560
2561 if (PartEntry->SectorCount.QuadPart < 1048576)
2562 {
2563 /* FAT16 LBA partition (partition size < 512MB) */
2564 PartEntry->PartitionType = PARTITION_XINT13;
2565 }
2566 else
2567 {
2568 /* FAT32 LBA partition (partition size >= 512MB) */
2569 PartEntry->PartitionType = PARTITION_FAT32_XINT13;
2570 }
2571 }
2572
2573 DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].PartitionType = PartEntry->PartitionType;
2574 }
2575 #if 0
2576 else if (wcscmp(FileSystemList->Selected->FileSystem, L"EXT2") == 0)
2577 {
2578 PartEntry->PartInfo[PartNum].PartitionType = PARTITION_EXT2;
2579 DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].PartitionType = PartEntry->PartitionType;
2580 }
2581 #endif
2582 else if (!FileSystemList->Selected->FormatFunc)
2583 return QUIT_PAGE;
2584
2585 #ifndef NDEBUG
2586 CONSOLE_PrintTextXY(6, 12,
2587 "Disk: %I64u Cylinder: %I64u Track: %I64u",
2588 DiskEntry->DiskSize,
2589 DiskEntry->CylinderSize,
2590 DiskEntry->TrackSize);
2591
2592 Line = 13;
2593 DiskEntry = PartitionList->CurrentDisk;
2594 Entry = DiskEntry->PartListHead.Flink;
2595
2596 while (Entry != &DiskEntry->PrimaryPartListHead)
2597 {
2598 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
2599
2600 if (PartEntry->IsPartitioned == TRUE)
2601 {
2602 CONSOLE_PrintTextXY(6, Line,
2603 "%2u: %2u %c %12I64u %12I64u %2u %c",
2604 i,
2605 PartEntry->PartitionNumber,
2606 PartEntry->BootIndicator ? 'A' : '-',
2607 PartEntry->StartSector.QuadPart,
2608 PartEntry->SectorCount.QuadPart,
2609 PartEntry->PartitionType,
2610 PartEntry->Dirty ? '*' : ' ');
2611 Line++;
2612 }
2613
2614 Entry = Entry->Flink;
2615 }
2616
2617 /* Restore the old entry */
2618 PartEntry = PartitionList->CurrentPartition;
2619 #endif
2620
2621 CheckActiveBootPartition(PartitionList);
2622
2623 if (WritePartitionsToDisk(PartitionList) == FALSE)
2624 {
2625 DPRINT("WritePartitionsToDisk() failed\n");
2626 MUIDisplayError(ERROR_WRITE_PTABLE, Ir, POPUP_WAIT_ENTER);
2627 return QUIT_PAGE;
2628 }
2629
2630 /* Set DestinationRootPath */
2631 RtlFreeUnicodeString(&DestinationRootPath);
2632 swprintf(PathBuffer,
2633 L"\\Device\\Harddisk%lu\\Partition%lu",
2634 PartitionList->CurrentDisk->DiskNumber,
2635 PartitionList->CurrentPartition->PartitionNumber);
2636 RtlCreateUnicodeString(&DestinationRootPath,
2637 PathBuffer);
2638 DPRINT("DestinationRootPath: %wZ\n", &DestinationRootPath);
2639
2640 if (FileSystemList->Selected->FormatFunc)
2641 {
2642 Status = FormatPartition(&DestinationRootPath,
2643 FileSystemList->Selected);
2644 if (!NT_SUCCESS(Status))
2645 {
2646 DPRINT1("FormatPartition() failed with status 0x%08lx\n", Status);
2647 /* FIXME: show an error dialog */
2648 return QUIT_PAGE;
2649 }
2650
2651 PartEntry->New = FALSE;
2652
2653 }
2654
2655 #ifndef NDEBUG
2656 CONSOLE_SetStatusText(" Done. Press any key ...");
2657 CONSOLE_ConInKey(Ir);
2658 #endif
2659
2660 DestroyFileSystemList(FileSystemList);
2661 FileSystemList = NULL;
2662 return INSTALL_DIRECTORY_PAGE;
2663 }
2664 }
2665
2666 return FORMAT_PARTITION_PAGE;
2667 }
2668
2669
2670 static ULONG
2671 CheckFileSystemPage(PINPUT_RECORD Ir)
2672 {
2673 PFILE_SYSTEM_ITEM CurrentFileSystem;
2674 WCHAR PathBuffer[MAX_PATH];
2675 CHAR Buffer[MAX_PATH];
2676 NTSTATUS Status;
2677
2678 /* FIXME: code duplicated in FormatPartitionPage */
2679 /* Set DestinationRootPath */
2680 RtlFreeUnicodeString(&DestinationRootPath);
2681 swprintf(PathBuffer,
2682 L"\\Device\\Harddisk%lu\\Partition%lu",
2683 PartitionList->CurrentDisk->DiskNumber,
2684 PartitionList->CurrentPartition->PartitionNumber);
2685 RtlCreateUnicodeString(&DestinationRootPath, PathBuffer);
2686 DPRINT("DestinationRootPath: %wZ\n", &DestinationRootPath);
2687
2688 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHECKINGPART));
2689
2690 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
2691
2692 /* WRONG: first filesystem is not necesseraly the one of the current partition! */
2693 CurrentFileSystem = CONTAINING_RECORD(FileSystemList->ListHead.Flink, FILE_SYSTEM_ITEM, ListEntry);
2694
2695 if (!CurrentFileSystem->ChkdskFunc)
2696 {
2697 sprintf(Buffer,
2698 "Setup is currently unable to check a partition formatted in %S.\n"
2699 "\n"
2700 " \x07 Press ENTER to continue Setup.\n"
2701 " \x07 Press F3 to quit Setup.",
2702 CurrentFileSystem->FileSystem);
2703
2704 PopupError(Buffer,
2705 MUIGetString(STRING_QUITCONTINUE),
2706 NULL, POPUP_WAIT_NONE);
2707
2708 while (TRUE)
2709 {
2710 CONSOLE_ConInKey(Ir);
2711
2712 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x00 &&
2713 Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3) /* F3 */
2714 {
2715 if (ConfirmQuit(Ir))
2716 return QUIT_PAGE;
2717 else
2718 return CHECK_FILE_SYSTEM_PAGE;
2719 }
2720 else if (Ir->Event.KeyEvent.uChar.AsciiChar == VK_RETURN) /* ENTER */
2721 {
2722 return INSTALL_DIRECTORY_PAGE;
2723 }
2724 }
2725 }
2726 else
2727 {
2728 Status = ChkdskPartition(&DestinationRootPath, CurrentFileSystem);
2729 if (!NT_SUCCESS(Status))
2730 {
2731 DPRINT("ChkdskPartition() failed with status 0x%08lx\n", Status);
2732 sprintf(Buffer, "Setup failed to verify the selected partition.\n"
2733 "(Status 0x%08lx).\n", Status);
2734
2735 PopupError(Buffer,
2736 MUIGetString(STRING_REBOOTCOMPUTER),
2737 Ir, POPUP_WAIT_ENTER);
2738
2739 return QUIT_PAGE;
2740 }
2741
2742 return INSTALL_DIRECTORY_PAGE;
2743 }
2744 }
2745
2746
2747 static PAGE_NUMBER
2748 InstallDirectoryPage1(PWCHAR InstallDir,
2749 PDISKENTRY DiskEntry,
2750 PPARTENTRY PartEntry)
2751 {
2752 WCHAR PathBuffer[MAX_PATH];
2753
2754 /* Create 'InstallPath' string */
2755 RtlFreeUnicodeString(&InstallPath);
2756 RtlCreateUnicodeString(&InstallPath,
2757 InstallDir);
2758
2759 /* Create 'DestinationPath' string */
2760 RtlFreeUnicodeString(&DestinationPath);
2761 wcscpy(PathBuffer, DestinationRootPath.Buffer);
2762
2763 if (InstallDir[0] != L'\\')
2764 wcscat(PathBuffer, L"\\");
2765
2766 wcscat(PathBuffer, InstallDir);
2767 RtlCreateUnicodeString(&DestinationPath, PathBuffer);
2768
2769 /* Create 'DestinationArcPath' */
2770 RtlFreeUnicodeString(&DestinationArcPath);
2771 swprintf(PathBuffer,
2772 L"multi(0)disk(0)rdisk(%lu)partition(%lu)",
2773 DiskEntry->BiosDiskNumber,
2774 PartEntry->PartitionNumber);
2775
2776 if (InstallDir[0] != L'\\')
2777 wcscat(PathBuffer, L"\\");
2778
2779 wcscat(PathBuffer, InstallDir);
2780 RtlCreateUnicodeString(&DestinationArcPath, PathBuffer);
2781
2782 return PREPARE_COPY_PAGE;
2783 }
2784
2785
2786 static PAGE_NUMBER
2787 InstallDirectoryPage(PINPUT_RECORD Ir)
2788 {
2789 PDISKENTRY DiskEntry;
2790 PPARTENTRY PartEntry;
2791 WCHAR InstallDir[51];
2792 ULONG Length;
2793
2794 if (PartitionList == NULL ||
2795 PartitionList->CurrentDisk == NULL ||
2796 PartitionList->CurrentPartition == NULL)
2797 {
2798 /* FIXME: show an error dialog */
2799 return QUIT_PAGE;
2800 }
2801
2802 DiskEntry = PartitionList->CurrentDisk;
2803 PartEntry = PartitionList->CurrentPartition;
2804
2805 if (IsUnattendedSetup)
2806 wcscpy(InstallDir, UnattendInstallationDirectory);
2807 else
2808 wcscpy(InstallDir, L"\\ReactOS");
2809
2810 Length = wcslen(InstallDir);
2811 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
2812 MUIDisplayPage(INSTALL_DIRECTORY_PAGE);
2813
2814 if (IsUnattendedSetup)
2815 {
2816 return InstallDirectoryPage1(InstallDir,
2817 DiskEntry,
2818 PartEntry);
2819 }
2820
2821 while (TRUE)
2822 {
2823 CONSOLE_ConInKey(Ir);
2824
2825 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2826 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
2827 {
2828 if (ConfirmQuit(Ir) == TRUE)
2829 return QUIT_PAGE;
2830
2831 break;
2832 }
2833 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2834 {
2835 return InstallDirectoryPage1(InstallDir,
2836 DiskEntry,
2837 PartEntry);
2838 }
2839 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x08) /* BACKSPACE */
2840 {
2841 if (Length > 0)
2842 {
2843 Length--;
2844 InstallDir[Length] = 0;
2845 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
2846 }
2847 }
2848 else if (isprint(Ir->Event.KeyEvent.uChar.AsciiChar))
2849 {
2850 if (Length < 50)
2851 {
2852 InstallDir[Length] = (WCHAR)Ir->Event.KeyEvent.uChar.AsciiChar;
2853 Length++;
2854 InstallDir[Length] = 0;
2855 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
2856 }
2857 }
2858 }
2859
2860 return INSTALL_DIRECTORY_PAGE;
2861 }
2862
2863
2864 static BOOLEAN
2865 AddSectionToCopyQueueCab(HINF InfFile,
2866 PWCHAR SectionName,
2867 PWCHAR SourceCabinet,
2868 PCUNICODE_STRING DestinationPath,
2869 PINPUT_RECORD Ir)
2870 {
2871 INFCONTEXT FilesContext;
2872 INFCONTEXT DirContext;
2873 PWCHAR FileKeyName;
2874 PWCHAR FileKeyValue;
2875 PWCHAR DirKeyValue;
2876 PWCHAR TargetFileName;
2877
2878 /* Search for the SectionName section */
2879 if (!SetupFindFirstLineW(InfFile, SectionName, NULL, &FilesContext))
2880 {
2881 char Buffer[128];
2882 sprintf(Buffer, MUIGetString(STRING_TXTSETUPFAILED), SectionName);
2883 PopupError(Buffer, MUIGetString(STRING_REBOOTCOMPUTER), Ir, POPUP_WAIT_ENTER);
2884 return FALSE;
2885 }
2886
2887 /*
2888 * Enumerate the files in the section
2889 * and add them to the file queue.
2890 */
2891 do
2892 {
2893 /* Get source file name and target directory id */
2894 if (!INF_GetData(&FilesContext, &FileKeyName, &FileKeyValue))
2895 {
2896 /* FIXME: Handle error! */
2897 DPRINT1("INF_GetData() failed\n");
2898 break;
2899 }
2900
2901 /* Get optional target file name */
2902 if (!INF_GetDataField(&FilesContext, 2, &TargetFileName))
2903 TargetFileName = NULL;
2904
2905 DPRINT("FileKeyName: '%S' FileKeyValue: '%S'\n", FileKeyName, FileKeyValue);
2906
2907 /* Lookup target directory */
2908 if (!SetupFindFirstLineW(InfFile, L"Directories", FileKeyValue, &DirContext))
2909 {
2910 /* FIXME: Handle error! */
2911 DPRINT1("SetupFindFirstLine() failed\n");
2912 break;
2913 }
2914
2915 if (!INF_GetData(&DirContext, NULL, &DirKeyValue))
2916 {
2917 /* FIXME: Handle error! */
2918 DPRINT1("INF_GetData() failed\n");
2919 break;
2920 }
2921
2922 if (!SetupQueueCopy(SetupFileQueue,
2923 SourceCabinet,
2924 SourceRootPath.Buffer,
2925 SourceRootDir.Buffer,
2926 FileKeyName,
2927 DirKeyValue,
2928 TargetFileName))
2929 {
2930 /* FIXME: Handle error! */
2931 DPRINT1("SetupQueueCopy() failed\n");
2932 }
2933 } while (SetupFindNextLine(&FilesContext, &FilesContext));
2934
2935 return TRUE;
2936 }
2937
2938
2939 static BOOLEAN
2940 AddSectionToCopyQueue(HINF InfFile,
2941 PWCHAR SectionName,
2942 PWCHAR SourceCabinet,
2943 PCUNICODE_STRING DestinationPath,
2944 PINPUT_RECORD Ir)
2945 {
2946 INFCONTEXT FilesContext;
2947 INFCONTEXT DirContext;
2948 PWCHAR FileKeyName;
2949 PWCHAR FileKeyValue;
2950 PWCHAR DirKeyValue;
2951 PWCHAR TargetFileName;
2952 WCHAR CompleteOrigFileName[512];
2953
2954 if (SourceCabinet)
2955 return AddSectionToCopyQueueCab(InfFile, L"SourceFiles", SourceCabinet, DestinationPath, Ir);
2956
2957 /* Search for the SectionName section */
2958 if (!SetupFindFirstLineW(InfFile, SectionName, NULL, &FilesContext))
2959 {
2960 char Buffer[128];
2961 sprintf(Buffer, MUIGetString(STRING_TXTSETUPFAILED), SectionName);
2962 PopupError(Buffer, MUIGetString(STRING_REBOOTCOMPUTER), Ir, POPUP_WAIT_ENTER);
2963 return FALSE;
2964 }
2965
2966 /*
2967 * Enumerate the files in the section
2968 * and add them to the file queue.
2969 */
2970 do
2971 {
2972 /* Get source file name and target directory id */
2973 if (!INF_GetData(&FilesContext, &FileKeyName, &FileKeyValue))
2974 {
2975 /* FIXME: Handle error! */
2976 DPRINT1("INF_GetData() failed\n");
2977 break;
2978 }
2979
2980 /* Get target directory id */
2981 if (!INF_GetDataField(&FilesContext, 13, &FileKeyValue))
2982 {
2983 /* FIXME: Handle error! */
2984 DPRINT1("INF_GetData() failed\n");
2985 break;
2986 }
2987
2988 /* Get optional target file name */
2989 if (!INF_GetDataField(&FilesContext, 11, &TargetFileName))
2990 TargetFileName = NULL;
2991 else if (!*TargetFileName)
2992 TargetFileName = NULL;
2993
2994 DPRINT("FileKeyName: '%S' FileKeyValue: '%S'\n", FileKeyName, FileKeyValue);
2995
2996 /* Lookup target directory */
2997 if (!SetupFindFirstLineW(InfFile, L"Directories", FileKeyValue, &DirContext))
2998 {
2999 /* FIXME: Handle error! */
3000 DPRINT1("SetupFindFirstLine() failed\n");
3001 break;
3002 }
3003
3004 if (!INF_GetData(&DirContext, NULL, &DirKeyValue))
3005 {
3006 /* FIXME: Handle error! */
3007 DPRINT1("INF_GetData() failed\n");
3008 break;
3009 }
3010
3011 wcscpy(CompleteOrigFileName, SourceRootDir.Buffer);
3012 wcscat(CompleteOrigFileName, L"\\");
3013 wcscat(CompleteOrigFileName, DirKeyValue);
3014
3015 if (!SetupQueueCopy(SetupFileQueue,
3016 SourceCabinet,
3017 SourceRootPath.Buffer,
3018 CompleteOrigFileName,
3019 FileKeyName,
3020 DirKeyValue,
3021 TargetFileName))
3022 {
3023 /* FIXME: Handle error! */
3024 DPRINT1("SetupQueueCopy() failed\n");
3025 }
3026 } while (SetupFindNextLine(&FilesContext, &FilesContext));
3027
3028 return TRUE;
3029 }
3030
3031
3032 static BOOLEAN
3033 PrepareCopyPageInfFile(HINF InfFile,
3034 PWCHAR SourceCabinet,
3035 PINPUT_RECORD Ir)
3036 {
3037 WCHAR PathBuffer[MAX_PATH];
3038 INFCONTEXT DirContext;
3039 PWCHAR AdditionalSectionName = NULL;
3040 PWCHAR KeyValue;
3041 ULONG Length;
3042 NTSTATUS Status;
3043
3044 /* Add common files */
3045 if (!AddSectionToCopyQueue(InfFile, L"SourceDisksFiles", SourceCabinet, &DestinationPath, Ir))
3046 return FALSE;
3047
3048 /* Add specific files depending of computer type */
3049 if (SourceCabinet == NULL)
3050 {
3051 if (!ProcessComputerFiles(InfFile, ComputerList, &AdditionalSectionName))
3052 return FALSE;
3053
3054 if (AdditionalSectionName)
3055 {
3056 if (!AddSectionToCopyQueue(InfFile, AdditionalSectionName, SourceCabinet, &DestinationPath, Ir))
3057 return FALSE;
3058 }
3059 }
3060
3061 /* Create directories */
3062
3063 /*
3064 * FIXME:
3065 * Install directories like '\reactos\test' are not handled yet.
3066 */
3067
3068 /* Get destination path */
3069 wcscpy(PathBuffer, DestinationPath.Buffer);
3070
3071 /* Remove trailing backslash */
3072 Length = wcslen(PathBuffer);
3073 if ((Length > 0) && (PathBuffer[Length - 1] == '\\'))
3074 {
3075 PathBuffer[Length - 1] = 0;
3076 }
3077
3078 /* Create the install directory */
3079 Status = SetupCreateDirectory(PathBuffer);
3080 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION)
3081 {
3082 DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer, Status);
3083 MUIDisplayError(ERROR_CREATE_INSTALL_DIR, Ir, POPUP_WAIT_ENTER);
3084 return FALSE;
3085 }
3086
3087 /* Search for the 'Directories' section */
3088 if (!SetupFindFirstLineW(InfFile, L"Directories", NULL, &DirContext))
3089 {
3090 if (SourceCabinet)
3091 {
3092 MUIDisplayError(ERROR_CABINET_SECTION, Ir, POPUP_WAIT_ENTER);
3093 }
3094 else
3095 {
3096 MUIDisplayError(ERROR_TXTSETUP_SECTION, Ir, POPUP_WAIT_ENTER);
3097 }
3098
3099 return FALSE;
3100 }
3101
3102 /* Enumerate the directory values and create the subdirectories */
3103 do
3104 {
3105 if (!INF_GetData(&DirContext, NULL, &KeyValue))
3106 {
3107 DPRINT1("break\n");
3108 break;
3109 }
3110
3111 if (KeyValue[0] == L'\\' && KeyValue[1] != 0)
3112 {
3113 DPRINT("Absolute Path: '%S'\n", KeyValue);
3114
3115 wcscpy(PathBuffer, DestinationRootPath.Buffer);
3116 wcscat(PathBuffer, KeyValue);
3117
3118 DPRINT("FullPath: '%S'\n", PathBuffer);
3119 }
3120 else if (KeyValue[0] != L'\\')
3121 {
3122 DPRINT("RelativePath: '%S'\n", KeyValue);
3123 wcscpy(PathBuffer, DestinationPath.Buffer);
3124 wcscat(PathBuffer, L"\\");
3125 wcscat(PathBuffer, KeyValue);
3126
3127 DPRINT("FullPath: '%S'\n", PathBuffer);
3128
3129 Status = SetupCreateDirectory(PathBuffer);
3130 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION)
3131 {
3132 DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer, Status);
3133 MUIDisplayError(ERROR_CREATE_DIR, Ir, POPUP_WAIT_ENTER);
3134 return FALSE;
3135 }
3136 }
3137 } while (SetupFindNextLine (&DirContext, &DirContext));
3138
3139 return TRUE;
3140 }
3141
3142
3143 static PAGE_NUMBER
3144 PrepareCopyPage(PINPUT_RECORD Ir)
3145 {
3146 HINF InfHandle;
3147 WCHAR PathBuffer[MAX_PATH];
3148 INFCONTEXT CabinetsContext;
3149 ULONG InfFileSize;
3150 PWCHAR KeyValue;
3151 UINT ErrorLine;
3152 PVOID InfFileData;
3153
3154 MUIDisplayPage(PREPARE_COPY_PAGE);
3155
3156 /* Create the file queue */
3157 SetupFileQueue = SetupOpenFileQueue();
3158 if (SetupFileQueue == NULL)
3159 {
3160 MUIDisplayError(ERROR_COPY_QUEUE, Ir, POPUP_WAIT_ENTER);
3161 return(QUIT_PAGE);
3162 }
3163
3164 if (!PrepareCopyPageInfFile(SetupInf, NULL, Ir))
3165 {
3166 return QUIT_PAGE;
3167 }
3168
3169 /* Search for the 'Cabinets' section */
3170 if (!SetupFindFirstLineW(SetupInf, L"Cabinets", NULL, &CabinetsContext))
3171 {
3172 return FILE_COPY_PAGE;
3173 }
3174
3175 /*
3176 * Enumerate the directory values in the 'Cabinets'
3177 * section and parse their inf files.
3178 */
3179 do
3180 {
3181 if (!INF_GetData(&CabinetsContext, NULL, &KeyValue))
3182 break;
3183
3184 wcscpy(PathBuffer, SourcePath.Buffer);
3185 wcscat(PathBuffer, L"\\");
3186 wcscat(PathBuffer, KeyValue);
3187
3188 #ifdef __REACTOS__
3189 CabinetInitialize();
3190 CabinetSetEventHandlers(NULL, NULL, NULL);