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