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