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