Mikhail Zvyozdochkink <mzvyozd@narod.ru>
[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 SIZE_T 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 /* Create the paged pool progress bar */
3085 CopyContext.MemoryBars[0] = CreateProgressBar(13,
3086 40,
3087 18,
3088 43,
3089 10,
3090 44,
3091 FALSE,
3092 MUIGetString(STRING_PAGEDMEM));
3093
3094 /* Create the non paged pool progress bar */
3095 CopyContext.MemoryBars[1] = CreateProgressBar(28,
3096 40,
3097 33,
3098 43,
3099 24,
3100 44,
3101 FALSE,
3102 MUIGetString(STRING_NONPAGEDMEM));
3103
3104 /* Create the global memory progress bar */
3105 CopyContext.MemoryBars[2] = CreateProgressBar(43,
3106 40,
3107 48,
3108 43,
3109 40,
3110 44,
3111 FALSE,
3112 MUIGetString(STRING_FREEMEM));
3113
3114 /* Do the file copying */
3115 SetupCommitFileQueueW(NULL,
3116 SetupFileQueue,
3117 FileCopyCallback,
3118 &CopyContext);
3119
3120 /* If we get here, we're done, so cleanup the queue and progress bar */
3121 SetupCloseFileQueue(SetupFileQueue);
3122 DestroyProgressBar(CopyContext.ProgressBar);
3123 DestroyProgressBar(CopyContext.MemoryBars[0]);
3124 DestroyProgressBar(CopyContext.MemoryBars[1]);
3125 DestroyProgressBar(CopyContext.MemoryBars[2]);
3126
3127 /* Go display the next page */
3128 return REGISTRY_PAGE;
3129 }
3130
3131 static PAGE_NUMBER
3132 RegistryPage(PINPUT_RECORD Ir)
3133 {
3134 INFCONTEXT InfContext;
3135 PWSTR Action;
3136 PWSTR File;
3137 PWSTR Section;
3138 BOOLEAN Delete;
3139 NTSTATUS Status;
3140
3141 MUIDisplayPage(REGISTRY_PAGE);
3142
3143 if (RepairUpdateFlag)
3144 {
3145 return SUCCESS_PAGE;
3146 }
3147
3148 if (!SetInstallPathValue(&DestinationPath))
3149 {
3150 DPRINT("SetInstallPathValue() failed\n");
3151 MUIDisplayError(ERROR_INITIALIZE_REGISTRY, Ir, POPUP_WAIT_ENTER);
3152 return QUIT_PAGE;
3153 }
3154
3155 /* Create the default hives */
3156 #ifdef __REACTOS__
3157 Status = NtInitializeRegistry(CM_BOOT_FLAG_SETUP);
3158 if (!NT_SUCCESS(Status))
3159 {
3160 DPRINT("NtInitializeRegistry() failed (Status %lx)\n", Status);
3161 MUIDisplayError(ERROR_CREATE_HIVE, Ir, POPUP_WAIT_ENTER);
3162 return QUIT_PAGE;
3163 }
3164 #else
3165 RegInitializeRegistry();
3166 #endif
3167
3168 /* Update registry */
3169 CONSOLE_SetStatusText(MUIGetString(STRING_REGHIVEUPDATE));
3170
3171 if (!SetupFindFirstLineW(SetupInf, L"HiveInfs.Install", NULL, &InfContext))
3172 {
3173 DPRINT1("SetupFindFirstLine() failed\n");
3174 MUIDisplayError(ERROR_FIND_REGISTRY, Ir, POPUP_WAIT_ENTER);
3175 return QUIT_PAGE;
3176 }
3177
3178 do
3179 {
3180 INF_GetDataField (&InfContext, 0, &Action);
3181 INF_GetDataField (&InfContext, 1, &File);
3182 INF_GetDataField (&InfContext, 2, &Section);
3183
3184 DPRINT("Action: %S File: %S Section %S\n", Action, File, Section);
3185
3186 if (!_wcsicmp (Action, L"AddReg"))
3187 {
3188 Delete = FALSE;
3189 }
3190 else if (!_wcsicmp (Action, L"DelReg"))
3191 {
3192 Delete = TRUE;
3193 }
3194 else
3195 {
3196 continue;
3197 }
3198
3199 CONSOLE_SetStatusText(MUIGetString(STRING_IMPORTFILE), File);
3200
3201 if (!ImportRegistryFile(File, Section, Delete))
3202 {
3203 DPRINT("Importing %S failed\n", File);
3204
3205 MUIDisplayError(ERROR_IMPORT_HIVE, Ir, POPUP_WAIT_ENTER);
3206 return QUIT_PAGE;
3207 }
3208 } while (SetupFindNextLine (&InfContext, &InfContext));
3209
3210 /* Update display registry settings */
3211 CONSOLE_SetStatusText(MUIGetString(STRING_DISPLAYETTINGSUPDATE));
3212 if (!ProcessDisplayRegistry(SetupInf, DisplayList))
3213 {
3214 MUIDisplayError(ERROR_UPDATE_DISPLAY_SETTINGS, Ir, POPUP_WAIT_ENTER);
3215 return QUIT_PAGE;
3216 }
3217
3218 /* Set the locale */
3219 CONSOLE_SetStatusText(MUIGetString(STRING_LOCALESETTINGSUPDATE));
3220 if (!ProcessLocaleRegistry(LanguageList))
3221 {
3222 MUIDisplayError(ERROR_UPDATE_LOCALESETTINGS, Ir, POPUP_WAIT_ENTER);
3223 return QUIT_PAGE;
3224 }
3225
3226 /* Add keyboard layouts */
3227 CONSOLE_SetStatusText(MUIGetString(STRING_ADDKBLAYOUTS));
3228 if (!AddKeyboardLayouts())
3229 {
3230 MUIDisplayError(ERROR_ADDING_KBLAYOUTS, Ir, POPUP_WAIT_ENTER);
3231 return QUIT_PAGE;
3232 }
3233
3234 /* Update keyboard layout settings */
3235 CONSOLE_SetStatusText(MUIGetString(STRING_KEYBOARDSETTINGSUPDATE));
3236 if (!ProcessKeyboardLayoutRegistry(LayoutList))
3237 {
3238 MUIDisplayError(ERROR_UPDATE_KBSETTINGS, Ir, POPUP_WAIT_ENTER);
3239 return QUIT_PAGE;
3240 }
3241
3242 /* Add codepage information to registry */
3243 CONSOLE_SetStatusText(MUIGetString(STRING_CODEPAGEINFOUPDATE));
3244 if (!AddCodePage())
3245 {
3246 MUIDisplayError(ERROR_ADDING_CODEPAGE, Ir, POPUP_WAIT_ENTER);
3247 return QUIT_PAGE;
3248 }
3249
3250 /* Update the mounted devices list */
3251 SetMountedDeviceValues(PartitionList);
3252
3253 CONSOLE_SetStatusText(MUIGetString(STRING_DONE));
3254
3255 return BOOT_LOADER_PAGE;
3256 }
3257
3258
3259 static PAGE_NUMBER
3260 BootLoaderPage(PINPUT_RECORD Ir)
3261 {
3262 UCHAR PartitionType;
3263 BOOLEAN InstallOnFloppy;
3264 USHORT Line = 12;
3265
3266 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
3267
3268 PartitionType = PartitionList->ActiveBootPartition->PartInfo[0].PartitionType;
3269
3270 if (PartitionType == PARTITION_ENTRY_UNUSED)
3271 {
3272 DPRINT("Error: active partition invalid (unused)\n");
3273 InstallOnFloppy = TRUE;
3274 }
3275 else if (PartitionType == 0x0A)
3276 {
3277 /* OS/2 boot manager partition */
3278 DPRINT("Found OS/2 boot manager partition\n");
3279 InstallOnFloppy = TRUE;
3280 }
3281 else if (PartitionType == 0x83)
3282 {
3283 /* Linux ext2 partition */
3284 DPRINT("Found Linux ext2 partition\n");
3285 InstallOnFloppy = TRUE;
3286 }
3287 else if (PartitionType == PARTITION_IFS)
3288 {
3289 /* NTFS partition */
3290 DPRINT("Found NTFS partition\n");
3291 InstallOnFloppy = TRUE;
3292 }
3293 else if ((PartitionType == PARTITION_FAT_12) ||
3294 (PartitionType == PARTITION_FAT_16) ||
3295 (PartitionType == PARTITION_HUGE) ||
3296 (PartitionType == PARTITION_XINT13) ||
3297 (PartitionType == PARTITION_FAT32) ||
3298 (PartitionType == PARTITION_FAT32_XINT13))
3299 {
3300 DPRINT("Found FAT partition\n");
3301 InstallOnFloppy = FALSE;
3302 }
3303 else
3304 {
3305 /* Unknown partition */
3306 DPRINT("Unknown partition found\n");
3307 InstallOnFloppy = TRUE;
3308 }
3309
3310 if (InstallOnFloppy == TRUE)
3311 {
3312 return BOOT_LOADER_FLOPPY_PAGE;
3313 }
3314
3315 if (IsUnattendedSetup)
3316 {
3317 if (UnattendMBRInstallType == 0) /* skip MBR installation */
3318 {
3319 return SUCCESS_PAGE;
3320 }
3321 else if (UnattendMBRInstallType == 1) /* install on floppy */
3322 {
3323 return BOOT_LOADER_FLOPPY_PAGE;
3324 }
3325 else if (UnattendMBRInstallType == 2) /* install on hdd */
3326 {
3327 return BOOT_LOADER_HARDDISK_PAGE;
3328 }
3329 }
3330
3331 MUIDisplayPage(BOOT_LOADER_PAGE);
3332 CONSOLE_InvertTextXY(8, Line, 60, 1);
3333
3334 while(TRUE)
3335 {
3336 CONSOLE_ConInKey(Ir);
3337
3338 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3339 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
3340 {
3341 CONSOLE_NormalTextXY(8, Line, 60, 1);
3342
3343 Line++;
3344 if (Line<12) Line=14;
3345 if (Line>14) Line=12;
3346
3347 CONSOLE_InvertTextXY(8, Line, 60, 1);
3348 }
3349 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3350 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
3351 {
3352 CONSOLE_NormalTextXY(8, Line, 60, 1);
3353
3354 Line--;
3355 if (Line<12) Line=14;
3356 if (Line>14) Line=12;
3357
3358 CONSOLE_InvertTextXY(8, Line, 60, 1);
3359 }
3360 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3361 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
3362 {
3363 if (ConfirmQuit(Ir) == TRUE)
3364 return QUIT_PAGE;
3365
3366 break;
3367 }
3368 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
3369 {
3370 if (Line == 12)
3371 {
3372 return BOOT_LOADER_HARDDISK_PAGE;
3373 }
3374 else if (Line == 13)
3375 {
3376 return BOOT_LOADER_FLOPPY_PAGE;
3377 }
3378 else if (Line == 14)
3379 {
3380 return SUCCESS_PAGE;;
3381 }
3382
3383 return BOOT_LOADER_PAGE;
3384 }
3385 }
3386
3387 return BOOT_LOADER_PAGE;
3388 }
3389
3390
3391 static PAGE_NUMBER
3392 BootLoaderFloppyPage(PINPUT_RECORD Ir)
3393 {
3394 NTSTATUS Status;
3395
3396 MUIDisplayPage(BOOT_LOADER_FLOPPY_PAGE);
3397
3398 // SetStatusText(" Please wait...");
3399
3400 while(TRUE)
3401 {
3402 CONSOLE_ConInKey(Ir);
3403
3404 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
3405 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
3406 {
3407 if (ConfirmQuit(Ir) == TRUE)
3408 return QUIT_PAGE;
3409
3410 break;
3411 }
3412 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
3413 {
3414 if (DoesFileExist(L"\\Device\\Floppy0", L"\\") == FALSE)
3415 {
3416 MUIDisplayError(ERROR_NO_FLOPPY, Ir, POPUP_WAIT_ENTER);
3417 return BOOT_LOADER_FLOPPY_PAGE;
3418 }
3419
3420 Status = InstallFatBootcodeToFloppy(&SourceRootPath, &DestinationArcPath);
3421 if (!NT_SUCCESS(Status))
3422 {
3423 /* Print error message */
3424 return BOOT_LOADER_FLOPPY_PAGE;
3425 }
3426
3427 return SUCCESS_PAGE;
3428 }
3429 }
3430
3431 return BOOT_LOADER_FLOPPY_PAGE;
3432 }
3433
3434
3435 static PAGE_NUMBER
3436 BootLoaderHarddiskPage(PINPUT_RECORD Ir)
3437 {
3438 UCHAR PartitionType;
3439 NTSTATUS Status;
3440
3441 PartitionType = PartitionList->ActiveBootPartition->PartInfo[0].PartitionType;
3442 if ((PartitionType == PARTITION_FAT_12) ||
3443 (PartitionType == PARTITION_FAT_16) ||
3444 (PartitionType == PARTITION_HUGE) ||
3445 (PartitionType == PARTITION_XINT13) ||
3446 (PartitionType == PARTITION_FAT32) ||
3447 (PartitionType == PARTITION_FAT32_XINT13))
3448 {
3449 Status = InstallFatBootcodeToPartition(&SystemRootPath,
3450 &SourceRootPath,
3451 &DestinationArcPath,
3452 PartitionType);
3453 if (!NT_SUCCESS(Status))
3454 {
3455 MUIDisplayError(ERROR_INSTALL_BOOTCODE, Ir, POPUP_WAIT_ENTER);
3456 return QUIT_PAGE;
3457 }
3458
3459 return SUCCESS_PAGE;
3460 }
3461 else
3462 {
3463 MUIDisplayError(ERROR_WRITE_BOOT, Ir, POPUP_WAIT_ENTER);
3464 return QUIT_PAGE;
3465 }
3466
3467 return BOOT_LOADER_HARDDISK_PAGE;
3468 }
3469
3470
3471 static PAGE_NUMBER
3472 QuitPage(PINPUT_RECORD Ir)
3473 {
3474 MUIDisplayPage(QUIT_PAGE);
3475
3476 /* Destroy partition list */
3477 if (PartitionList != NULL)
3478 {
3479 DestroyPartitionList (PartitionList);
3480 PartitionList = NULL;
3481 }
3482
3483 /* Destroy filesystem list */
3484 if (FileSystemList != NULL)
3485 {
3486 DestroyFileSystemList (FileSystemList);
3487 FileSystemList = NULL;
3488 }
3489
3490 /* Destroy computer settings list */
3491 if (ComputerList != NULL)
3492 {
3493 DestroyGenericList(ComputerList, TRUE);
3494 ComputerList = NULL;
3495 }
3496
3497 /* Destroy display settings list */
3498 if (DisplayList != NULL)
3499 {
3500 DestroyGenericList(DisplayList, TRUE);
3501 DisplayList = NULL;
3502 }
3503
3504 /* Destroy keyboard settings list */
3505 if (KeyboardList != NULL)
3506 {
3507 DestroyGenericList(KeyboardList, TRUE);
3508 KeyboardList = NULL;
3509 }
3510
3511 /* Destroy keyboard layout list */
3512 if (LayoutList != NULL)
3513 {
3514 DestroyGenericList(LayoutList, TRUE);
3515 LayoutList = NULL;
3516 }
3517
3518 if (LanguageList != NULL)
3519 {
3520 DestroyGenericList(LanguageList, FALSE);
3521 LanguageList = NULL;
3522 }
3523
3524 CONSOLE_SetStatusText(MUIGetString(STRING_REBOOTCOMPUTER2));
3525
3526 while(TRUE)
3527 {
3528 CONSOLE_ConInKey(Ir);
3529
3530 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
3531 {
3532 return FLUSH_PAGE;
3533 }
3534 }
3535 }
3536
3537
3538 static PAGE_NUMBER
3539 SuccessPage(PINPUT_RECORD Ir)
3540 {
3541 MUIDisplayPage(SUCCESS_PAGE);
3542
3543 if (IsUnattendedSetup)
3544 {
3545 return FLUSH_PAGE;
3546 }
3547
3548 while(TRUE)
3549 {
3550 CONSOLE_ConInKey(Ir);
3551
3552 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
3553 {
3554 return FLUSH_PAGE;
3555 }
3556 }
3557 }
3558
3559
3560 static PAGE_NUMBER
3561 FlushPage(PINPUT_RECORD Ir)
3562 {
3563 MUIDisplayPage(FLUSH_PAGE);
3564 return REBOOT_PAGE;
3565 }
3566
3567
3568 DWORD WINAPI
3569 PnpEventThread(IN LPVOID lpParameter);
3570
3571 VOID
3572 RunUSetup(VOID)
3573 {
3574 INPUT_RECORD Ir;
3575 PAGE_NUMBER Page;
3576 LARGE_INTEGER Time;
3577 NTSTATUS Status;
3578
3579 NtQuerySystemTime(&Time);
3580
3581 Status = RtlCreateUserThread(NtCurrentProcess(), NULL, TRUE, 0, 0, 0, PnpEventThread, &SetupInf, &hPnpThread, NULL);
3582 if (!NT_SUCCESS(Status))
3583 hPnpThread = INVALID_HANDLE_VALUE;
3584
3585 if (!CONSOLE_Init())
3586 {
3587 PrintString(MUIGetString(STRING_CONSOLEFAIL1));
3588 PrintString(MUIGetString(STRING_CONSOLEFAIL2));
3589 PrintString(MUIGetString(STRING_CONSOLEFAIL3));
3590
3591 /* Raise a hard error (crash the system/BSOD) */
3592 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED,
3593 0,0,0,0,0);
3594 }
3595
3596 /* Initialize global unicode strings */
3597 RtlInitUnicodeString(&SourcePath, NULL);
3598 RtlInitUnicodeString(&SourceRootPath, NULL);
3599 RtlInitUnicodeString(&SourceRootDir, NULL);
3600 RtlInitUnicodeString(&InstallPath, NULL);
3601 RtlInitUnicodeString(&DestinationPath, NULL);
3602 RtlInitUnicodeString(&DestinationArcPath, NULL);
3603 RtlInitUnicodeString(&DestinationRootPath, NULL);
3604 RtlInitUnicodeString(&SystemRootPath, NULL);
3605
3606 /* Hide the cursor */
3607 CONSOLE_SetCursorType(TRUE, FALSE);
3608
3609 Page = START_PAGE;
3610 while (Page != REBOOT_PAGE)
3611 {
3612 CONSOLE_ClearScreen();
3613 CONSOLE_Flush();
3614
3615 //CONSOLE_SetUnderlinedTextXY(4, 3, " ReactOS " KERNEL_VERSION_STR " Setup ");
3616 //CONSOLE_Flush();
3617
3618 switch (Page)
3619 {
3620 /* Start page */
3621 case START_PAGE:
3622 Page = SetupStartPage(&Ir);
3623 break;
3624
3625 /* Language page */
3626 case LANGUAGE_PAGE:
3627 Page = LanguagePage(&Ir);
3628 break;
3629
3630 /* License page */
3631 case LICENSE_PAGE:
3632 Page = LicensePage(&Ir);
3633 break;
3634
3635 /* Intro page */
3636 case INTRO_PAGE:
3637 Page = IntroPage(&Ir);
3638 break;
3639
3640 /* Install pages */
3641 case INSTALL_INTRO_PAGE:
3642 Page = InstallIntroPage(&Ir);
3643 break;
3644
3645 #if 0
3646 case SCSI_CONTROLLER_PAGE:
3647 Page = ScsiControllerPage(&Ir);
3648 break;
3649 #endif
3650
3651 #if 0
3652 case OEM_DRIVER_PAGE:
3653 Page = OemDriverPage(&Ir);
3654 break;
3655 #endif
3656
3657 case DEVICE_SETTINGS_PAGE:
3658 Page = DeviceSettingsPage(&Ir);
3659 break;
3660
3661 case COMPUTER_SETTINGS_PAGE:
3662 Page = ComputerSettingsPage(&Ir);
3663 break;
3664
3665 case DISPLAY_SETTINGS_PAGE:
3666 Page = DisplaySettingsPage(&Ir);
3667 break;
3668
3669 case KEYBOARD_SETTINGS_PAGE:
3670 Page = KeyboardSettingsPage(&Ir);
3671 break;
3672
3673 case LAYOUT_SETTINGS_PAGE:
3674 Page = LayoutSettingsPage(&Ir);
3675 break;
3676
3677 case SELECT_PARTITION_PAGE:
3678 Page = SelectPartitionPage(&Ir);
3679 break;
3680
3681 case CREATE_PARTITION_PAGE:
3682 Page = CreatePartitionPage(&Ir);
3683 break;
3684
3685 case DELETE_PARTITION_PAGE:
3686 Page = DeletePartitionPage(&Ir);
3687 break;
3688
3689 case SELECT_FILE_SYSTEM_PAGE:
3690 Page = SelectFileSystemPage(&Ir);
3691 break;
3692
3693 case FORMAT_PARTITION_PAGE:
3694 Page = (PAGE_NUMBER) FormatPartitionPage(&Ir);
3695 break;
3696
3697 case CHECK_FILE_SYSTEM_PAGE:
3698 Page = (PAGE_NUMBER) CheckFileSystemPage(&Ir);
3699 break;
3700
3701 case INSTALL_DIRECTORY_PAGE:
3702 Page = InstallDirectoryPage(&Ir);
3703 break;
3704
3705 case PREPARE_COPY_PAGE:
3706 Page = PrepareCopyPage(&Ir);
3707 break;
3708
3709 case FILE_COPY_PAGE:
3710 Page = FileCopyPage(&Ir);
3711 break;
3712
3713 case REGISTRY_PAGE:
3714 Page = RegistryPage(&Ir);
3715 break;
3716
3717 case BOOT_LOADER_PAGE:
3718 Page = BootLoaderPage(&Ir);
3719 break;
3720
3721 case BOOT_LOADER_FLOPPY_PAGE:
3722 Page = BootLoaderFloppyPage(&Ir);
3723 break;
3724
3725 case BOOT_LOADER_HARDDISK_PAGE:
3726 Page = BootLoaderHarddiskPage(&Ir);
3727 break;
3728
3729 /* Repair pages */
3730 case REPAIR_INTRO_PAGE:
3731 Page = RepairIntroPage(&Ir);
3732 break;
3733
3734 case SUCCESS_PAGE:
3735 Page = SuccessPage(&Ir);
3736 break;
3737
3738 case FLUSH_PAGE:
3739 Page = FlushPage(&Ir);
3740 break;
3741
3742 case QUIT_PAGE:
3743 Page = QuitPage(&Ir);
3744 break;
3745
3746 case REBOOT_PAGE:
3747 break;
3748 }
3749 }
3750
3751 /// THE FOLLOWING DPRINT IS FOR THE SYSTEM REGRESSION TOOL
3752 /// DO NOT REMOVE!!!
3753 DPRINT1("SYSREG_CHECKPOINT:USETUP_COMPLETE\n");
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 */