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