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