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