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