Synchronize with trunk revision 59636 (just before Alex's CreateProcess revamp).
[reactos.git] / 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 along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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
35 /* GLOBALS ******************************************************************/
36
37 HANDLE ProcessHeap;
38 UNICODE_STRING SourceRootPath;
39 UNICODE_STRING SourceRootDir;
40 UNICODE_STRING SourcePath;
41 BOOLEAN IsUnattendedSetup = FALSE;
42 LONG UnattendDestinationDiskNumber;
43 LONG UnattendDestinationPartitionNumber;
44 LONG UnattendMBRInstallType = -1;
45 LONG UnattendFormatPartition = 0;
46 LONG AutoPartition = 0;
47 WCHAR UnattendInstallationDirectory[MAX_PATH];
48 PWCHAR SelectedLanguageId;
49 WCHAR LocaleID[9];
50 WCHAR DefaultLanguage[20];
51 WCHAR DefaultKBLayout[20];
52 BOOLEAN RepairUpdateFlag = FALSE;
53 HANDLE hPnpThread = INVALID_HANDLE_VALUE;
54 PPARTLIST PartitionList = NULL;
55
56 /* LOCALS *******************************************************************/
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 static LANGID LanguageId = 0;
83
84 static ULONG RequiredPartitionDiskSpace = ~0;
85
86 /* FUNCTIONS ****************************************************************/
87
88 static VOID
89 PrintString(char* fmt,...)
90 {
91 char buffer[512];
92 va_list ap;
93 UNICODE_STRING UnicodeString;
94 ANSI_STRING AnsiString;
95
96 va_start(ap, fmt);
97 vsprintf(buffer, fmt, ap);
98 va_end(ap);
99
100 RtlInitAnsiString(&AnsiString, buffer);
101 RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE);
102 NtDisplayString(&UnicodeString);
103 RtlFreeUnicodeString(&UnicodeString);
104 }
105
106
107 static VOID
108 DrawBox(IN SHORT xLeft,
109 IN SHORT yTop,
110 IN SHORT Width,
111 IN SHORT Height)
112 {
113 COORD coPos;
114 DWORD Written;
115
116 /* draw upper left corner */
117 coPos.X = xLeft;
118 coPos.Y = yTop;
119 FillConsoleOutputCharacterA(StdOutput,
120 0xDA, // '+',
121 1,
122 coPos,
123 &Written);
124
125 /* draw upper edge */
126 coPos.X = xLeft + 1;
127 coPos.Y = yTop;
128 FillConsoleOutputCharacterA(StdOutput,
129 0xC4, // '-',
130 Width - 2,
131 coPos,
132 &Written);
133
134 /* draw upper right corner */
135 coPos.X = xLeft + Width - 1;
136 coPos.Y = yTop;
137 FillConsoleOutputCharacterA(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(StdOutput,
148 0xB3, // '|',
149 1,
150 coPos,
151 &Written);
152
153 coPos.X = xLeft + 1;
154 FillConsoleOutputCharacterA(StdOutput,
155 ' ',
156 Width - 2,
157 coPos,
158 &Written);
159
160 coPos.X = xLeft + Width - 1;
161 FillConsoleOutputCharacterA(StdOutput,
162 0xB3, // '|',
163 1,
164 coPos,
165 &Written);
166 }
167
168 /* draw lower left corner */
169 coPos.X = xLeft;
170 coPos.Y = yTop + Height - 1;
171 FillConsoleOutputCharacterA(StdOutput,
172 0xC0, // '+',
173 1,
174 coPos,
175 &Written);
176
177 /* draw lower edge */
178 coPos.X = xLeft + 1;
179 coPos.Y = yTop + Height - 1;
180 FillConsoleOutputCharacterA(StdOutput,
181 0xC4, // '-',
182 Width - 2,
183 coPos,
184 &Written);
185
186 /* draw lower right corner */
187 coPos.X = xLeft + Width - 1;
188 coPos.Y = yTop + Height - 1;
189 FillConsoleOutputCharacterA(StdOutput,
190 0xD9, // '+',
191 1,
192 coPos,
193 &Written);
194 }
195
196
197 VOID
198 PopupError(PCCH Text,
199 PCCH Status,
200 PINPUT_RECORD Ir,
201 ULONG WaitEvent)
202 {
203 SHORT yTop;
204 SHORT xLeft;
205 COORD coPos;
206 DWORD Written;
207 ULONG Length;
208 ULONG MaxLength;
209 ULONG Lines;
210 PCHAR p;
211 PCCH pnext;
212 BOOLEAN LastLine;
213 SHORT Width;
214 SHORT Height;
215
216 /* Count text lines and longest line */
217 MaxLength = 0;
218 Lines = 0;
219 pnext = Text;
220
221 while (TRUE)
222 {
223 p = strchr(pnext, '\n');
224
225 if (p == NULL)
226 {
227 Length = strlen(pnext);
228 LastLine = TRUE;
229 }
230 else
231 {
232 Length = (ULONG)(p - pnext);
233 LastLine = FALSE;
234 }
235
236 Lines++;
237
238 if (Length > MaxLength)
239 MaxLength = Length;
240
241 if (LastLine == TRUE)
242 break;
243
244 pnext = p + 1;
245 }
246
247 /* Check length of status line */
248 if (Status != NULL)
249 {
250 Length = strlen(Status);
251
252 if (Length > MaxLength)
253 MaxLength = Length;
254 }
255
256 Width = MaxLength + 4;
257 Height = Lines + 2;
258
259 if (Status != NULL)
260 Height += 2;
261
262 yTop = (yScreen - Height) / 2;
263 xLeft = (xScreen - Width) / 2;
264
265
266 /* Set screen attributes */
267 coPos.X = xLeft;
268 for (coPos.Y = yTop; coPos.Y < yTop + Height; coPos.Y++)
269 {
270 FillConsoleOutputAttribute(StdOutput,
271 FOREGROUND_RED | BACKGROUND_WHITE,
272 Width,
273 coPos,
274 &Written);
275 }
276
277 DrawBox(xLeft, yTop, Width, Height);
278
279 /* Print message text */
280 coPos.Y = yTop + 1;
281 pnext = Text;
282 while (TRUE)
283 {
284 p = strchr(pnext, '\n');
285
286 if (p == NULL)
287 {
288 Length = strlen(pnext);
289 LastLine = TRUE;
290 }
291 else
292 {
293 Length = (ULONG)(p - pnext);
294 LastLine = FALSE;
295 }
296
297 if (Length != 0)
298 {
299 coPos.X = xLeft + 2;
300 WriteConsoleOutputCharacterA(StdOutput,
301 pnext,
302 Length,
303 coPos,
304 &Written);
305 }
306
307 if (LastLine == TRUE)
308 break;
309
310 coPos.Y++;
311 pnext = p + 1;
312 }
313
314 /* Print separator line and status text */
315 if (Status != NULL)
316 {
317 coPos.Y = yTop + Height - 3;
318 coPos.X = xLeft;
319 FillConsoleOutputCharacterA(StdOutput,
320 0xC3, // '+',
321 1,
322 coPos,
323 &Written);
324
325 coPos.X = xLeft + 1;
326 FillConsoleOutputCharacterA(StdOutput,
327 0xC4, // '-',
328 Width - 2,
329 coPos,
330 &Written);
331
332 coPos.X = xLeft + Width - 1;
333 FillConsoleOutputCharacterA(StdOutput,
334 0xB4, // '+',
335 1,
336 coPos,
337 &Written);
338
339 coPos.Y++;
340 coPos.X = xLeft + 2;
341 WriteConsoleOutputCharacterA(StdOutput,
342 Status,
343 min(strlen(Status), (SIZE_T)Width - 4),
344 coPos,
345 &Written);
346 }
347
348 if (WaitEvent == POPUP_WAIT_NONE)
349 return;
350
351 while (TRUE)
352 {
353 CONSOLE_ConInKey(Ir);
354
355 if (WaitEvent == POPUP_WAIT_ANY_KEY ||
356 Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)
357 {
358 return;
359 }
360 }
361 }
362
363
364 /*
365 * Confirm quit setup
366 * RETURNS
367 * TRUE: Quit setup.
368 * FALSE: Don't quit setup.
369 */
370 static BOOL
371 ConfirmQuit(PINPUT_RECORD Ir)
372 {
373 BOOL Result = FALSE;
374 MUIDisplayError(ERROR_NOT_INSTALLED, NULL, POPUP_WAIT_NONE);
375
376 while (TRUE)
377 {
378 CONSOLE_ConInKey(Ir);
379
380 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
381 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
382 {
383 Result = TRUE;
384 break;
385 }
386 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
387 {
388 Result = FALSE;
389 break;
390 }
391 }
392
393 return Result;
394 }
395
396
397 VOID
398 CheckUnattendedSetup(VOID)
399 {
400 WCHAR UnattendInfPath[MAX_PATH];
401 INFCONTEXT Context;
402 HINF UnattendInf;
403 UINT ErrorLine;
404 INT IntValue;
405 PWCHAR Value;
406
407 if (DoesFileExist(SourcePath.Buffer, L"unattend.inf") == FALSE)
408 {
409 DPRINT("Does not exist: %S\\%S\n", SourcePath.Buffer, L"unattend.inf");
410 return;
411 }
412
413 wcscpy(UnattendInfPath, SourcePath.Buffer);
414 wcscat(UnattendInfPath, L"\\unattend.inf");
415
416 /* Load 'unattend.inf' from install media. */
417 UnattendInf = SetupOpenInfFileW(UnattendInfPath,
418 NULL,
419 INF_STYLE_WIN4,
420 LanguageId,
421 &ErrorLine);
422
423 if (UnattendInf == INVALID_HANDLE_VALUE)
424 {
425 DPRINT("SetupOpenInfFileW() failed\n");
426 return;
427 }
428
429 /* Open 'Unattend' section */
430 if (!SetupFindFirstLineW(UnattendInf, L"Unattend", L"Signature", &Context))
431 {
432 DPRINT("SetupFindFirstLineW() failed for section 'Unattend'\n");
433 SetupCloseInfFile(UnattendInf);
434 return;
435 }
436
437 /* Get pointer 'Signature' key */
438 if (!INF_GetData(&Context, NULL, &Value))
439 {
440 DPRINT("INF_GetData() failed for key 'Signature'\n");
441 SetupCloseInfFile(UnattendInf);
442 return;
443 }
444
445 /* Check 'Signature' string */
446 if (_wcsicmp(Value, L"$ReactOS$") != 0)
447 {
448 DPRINT("Signature not $ReactOS$\n");
449 SetupCloseInfFile(UnattendInf);
450 return;
451 }
452
453 /* Check if Unattend setup is enabled */
454 if (!SetupFindFirstLineW(UnattendInf, L"Unattend", L"UnattendSetupEnabled", &Context))
455 {
456 DPRINT("Can't find key 'UnattendSetupEnabled'\n");
457 SetupCloseInfFile(UnattendInf);
458 return;
459 }
460
461 if (!INF_GetData(&Context, NULL, &Value))
462 {
463 DPRINT("Can't read key 'UnattendSetupEnabled'\n");
464 SetupCloseInfFile(UnattendInf);
465 return;
466 }
467
468 if (_wcsicmp(Value, L"yes") != 0)
469 {
470 DPRINT("Unattend setup is disabled by 'UnattendSetupEnabled' key!\n");
471 SetupCloseInfFile(UnattendInf);
472 return;
473 }
474
475 /* Search for 'DestinationDiskNumber' in the 'Unattend' section */
476 if (!SetupFindFirstLineW(UnattendInf, L"Unattend", L"DestinationDiskNumber", &Context))
477 {
478 DPRINT("SetupFindFirstLine() failed for key 'DestinationDiskNumber'\n");
479 SetupCloseInfFile(UnattendInf);
480 return;
481 }
482
483 if (!SetupGetIntField(&Context, 1, &IntValue))
484 {
485 DPRINT("SetupGetIntField() failed for key 'DestinationDiskNumber'\n");
486 SetupCloseInfFile(UnattendInf);
487 return;
488 }
489
490 UnattendDestinationDiskNumber = (LONG)IntValue;
491
492 /* Search for 'DestinationPartitionNumber' in the 'Unattend' section */
493 if (!SetupFindFirstLineW(UnattendInf, L"Unattend", L"DestinationPartitionNumber", &Context))
494 {
495 DPRINT("SetupFindFirstLine() failed for key 'DestinationPartitionNumber'\n");
496 SetupCloseInfFile(UnattendInf);
497 return;
498 }
499
500 if (!SetupGetIntField(&Context, 1, &IntValue))
501 {
502 DPRINT("SetupGetIntField() failed for key 'DestinationPartitionNumber'\n");
503 SetupCloseInfFile(UnattendInf);
504 return;
505 }
506
507 UnattendDestinationPartitionNumber = IntValue;
508
509 /* Search for 'InstallationDirectory' in the 'Unattend' section */
510 if (!SetupFindFirstLineW(UnattendInf, L"Unattend", L"InstallationDirectory", &Context))
511 {
512 DPRINT("SetupFindFirstLine() failed for key 'InstallationDirectory'\n");
513 SetupCloseInfFile(UnattendInf);
514 return;
515 }
516
517 /* Get pointer 'InstallationDirectory' key */
518 if (!INF_GetData(&Context, NULL, &Value))
519 {
520 DPRINT("INF_GetData() failed for key 'InstallationDirectory'\n");
521 SetupCloseInfFile(UnattendInf);
522 return;
523 }
524
525 wcscpy(UnattendInstallationDirectory, Value);
526
527 IsUnattendedSetup = TRUE;
528
529 /* Search for 'MBRInstallType' in the 'Unattend' section */
530 if (SetupFindFirstLineW(UnattendInf, L"Unattend", L"MBRInstallType", &Context))
531 {
532 if (SetupGetIntField(&Context, 1, &IntValue))
533 {
534 UnattendMBRInstallType = IntValue;
535 }
536 }
537
538 /* Search for 'FormatPartition' in the 'Unattend' section */
539 if (SetupFindFirstLineW(UnattendInf, L"Unattend", L"FormatPartition", &Context))
540 {
541 if (SetupGetIntField(&Context, 1, &IntValue))
542 {
543 UnattendFormatPartition = IntValue;
544 }
545 }
546
547 if (SetupFindFirstLineW(UnattendInf, L"Unattend", L"AutoPartition", &Context))
548 {
549 if (SetupGetIntField(&Context, 1, &IntValue))
550 {
551 AutoPartition = IntValue;
552 }
553 }
554
555 /* search for LocaleID in the 'Unattend' section*/
556 if (SetupFindFirstLineW (UnattendInf, L"Unattend", L"LocaleID", &Context))
557 {
558 if (INF_GetData (&Context, NULL, &Value))
559 {
560 LONG Id = wcstol(Value, NULL, 16);
561 swprintf(LocaleID,L"%08lx", Id);
562 }
563 }
564
565 SetupCloseInfFile(UnattendInf);
566
567 DPRINT("Running unattended setup\n");
568 }
569
570
571 VOID
572 UpdateKBLayout(VOID)
573 {
574 PGENERIC_LIST_ENTRY ListEntry;
575 LPCWSTR pszNewLayout;
576
577 pszNewLayout = MUIDefaultKeyboardLayout();
578
579 if (LayoutList == NULL)
580 {
581 LayoutList = CreateKeyboardLayoutList(SetupInf, DefaultKBLayout);
582 if (LayoutList == NULL)
583 {
584 /* FIXME: Handle error! */
585 return;
586 }
587 }
588
589 ListEntry = GetFirstListEntry(LayoutList);
590
591 /* Search for default layout (if provided) */
592 if (pszNewLayout != NULL)
593 {
594 while (ListEntry != NULL)
595 {
596 if (!wcscmp(pszNewLayout, GetListEntryUserData(ListEntry)))
597 {
598 SetCurrentListEntry(LayoutList, ListEntry);
599 break;
600 }
601
602 ListEntry = GetNextListEntry(ListEntry);
603 }
604 }
605 }
606
607
608 static PAGE_NUMBER
609 LanguagePage(PINPUT_RECORD Ir)
610 {
611 PWCHAR NewLanguageId;
612 BOOL RefreshPage = FALSE;
613
614 /* Initialize the computer settings list */
615 if (LanguageList == NULL)
616 {
617 LanguageList = CreateLanguageList(SetupInf, DefaultLanguage);
618
619 if (LanguageList == NULL)
620 {
621 PopupError("Setup failed to initialize available translations", NULL, NULL, POPUP_WAIT_NONE);
622 return INTRO_PAGE;
623 }
624 }
625
626 /* Load the font */
627 SelectedLanguageId = DefaultLanguage;
628 SetConsoleCodePage();
629
630 DrawGenericList(LanguageList,
631 2,
632 18,
633 xScreen - 3,
634 yScreen - 3);
635
636 ScrollToPositionGenericList (LanguageList, GetDefaultLanguageIndex());
637
638 MUIDisplayPage(LANGUAGE_PAGE);
639
640 while (TRUE)
641 {
642 CONSOLE_ConInKey(Ir);
643
644 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
645 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
646 {
647 ScrollDownGenericList (LanguageList);
648 RefreshPage = TRUE;
649 }
650 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
651 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
652 {
653 ScrollUpGenericList(LanguageList);
654 RefreshPage = TRUE;
655 }
656 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
657 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_NEXT)) /* PAGE DOWN */
658 {
659 ScrollPageDownGenericList(LanguageList);
660 RefreshPage = TRUE;
661 }
662 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
663 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_PRIOR)) /* PAGE UP */
664 {
665 ScrollPageUpGenericList(LanguageList);
666 RefreshPage = TRUE;
667 }
668 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
669 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
670 {
671 if (ConfirmQuit(Ir) == TRUE)
672 return QUIT_PAGE;
673 }
674 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
675 {
676 SelectedLanguageId = (PWCHAR)GetListEntryUserData(GetCurrentListEntry(LanguageList));
677
678 LanguageId = (LANGID)(wcstol(SelectedLanguageId, NULL, 16) & 0xFFFF);
679
680 if (wcscmp(SelectedLanguageId, DefaultLanguage))
681 {
682 UpdateKBLayout();
683 }
684
685 /* Load the font */
686 SetConsoleCodePage();
687
688 return INTRO_PAGE;
689 }
690 else if ((Ir->Event.KeyEvent.uChar.AsciiChar > 0x60) && (Ir->Event.KeyEvent.uChar.AsciiChar < 0x7b))
691 {
692 /* a-z */
693 GenericListKeyPress (LanguageList, Ir->Event.KeyEvent.uChar.AsciiChar);
694 RefreshPage = TRUE;
695 }
696
697 if (RefreshPage)
698 {
699 NewLanguageId = (PWCHAR)GetListEntryUserData(GetCurrentListEntry(LanguageList));
700
701 if (SelectedLanguageId != NewLanguageId)
702 {
703 /* Clear the language page */
704 MUIClearPage(LANGUAGE_PAGE);
705
706 SelectedLanguageId = NewLanguageId;
707
708 /* Load the font */
709 SetConsoleCodePage();
710
711 /* Redraw language selection page in native language */
712 MUIDisplayPage(LANGUAGE_PAGE);
713 }
714
715 RefreshPage = FALSE;
716 }
717 }
718
719 return INTRO_PAGE;
720 }
721
722
723 /*
724 * Start page
725 * RETURNS
726 * Number of the next page.
727 */
728 static PAGE_NUMBER
729 SetupStartPage(PINPUT_RECORD Ir)
730 {
731 //SYSTEM_DEVICE_INFORMATION Sdi;
732 NTSTATUS Status;
733 WCHAR FileNameBuffer[MAX_PATH];
734 INFCONTEXT Context;
735 PWCHAR Value;
736 UINT ErrorLine;
737 //ULONG ReturnSize;
738 PGENERIC_LIST_ENTRY ListEntry;
739 INT IntValue;
740
741 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
742
743 #if 0
744 /* Check whether a harddisk is available */
745 Status = NtQuerySystemInformation(SystemDeviceInformation,
746 &Sdi,
747 sizeof(SYSTEM_DEVICE_INFORMATION),
748 &ReturnSize);
749
750 if (!NT_SUCCESS(Status))
751 {
752 CONSOLE_PrintTextXY(6, 15, "NtQuerySystemInformation() failed (Status 0x%08lx)", Status);
753 MUIDisplayError(ERROR_DRIVE_INFORMATION, Ir, POPUP_WAIT_ENTER);
754 return QUIT_PAGE;
755 }
756
757 if (Sdi.NumberOfDisks == 0)
758 {
759 MUIDisplayError(ERROR_NO_HDD, Ir, POPUP_WAIT_ENTER);
760 return QUIT_PAGE;
761 }
762 #endif
763
764 /* Get the source path and source root path */
765 Status = GetSourcePaths(&SourcePath,
766 &SourceRootPath,
767 &SourceRootDir);
768
769 if (!NT_SUCCESS(Status))
770 {
771 CONSOLE_PrintTextXY(6, 15, "GetSourcePaths() failed (Status 0x%08lx)", Status);
772 MUIDisplayError(ERROR_NO_SOURCE_DRIVE, Ir, POPUP_WAIT_ENTER);
773 return QUIT_PAGE;
774 }
775 #if 0
776 else
777 {
778 CONSOLE_PrintTextXY(6, 15, "SourcePath: '%wZ'", &SourcePath);
779 CONSOLE_PrintTextXY(6, 16, "SourceRootPath: '%wZ'", &SourceRootPath);
780 CONSOLE_PrintTextXY(6, 17, "SourceRootDir: '%wZ'", &SourceRootDir);
781 }
782 #endif
783
784 /* Load txtsetup.sif from install media. */
785 wcscpy(FileNameBuffer, SourcePath.Buffer);
786 wcscat(FileNameBuffer, L"\\txtsetup.sif");
787
788 SetupInf = SetupOpenInfFileW(FileNameBuffer,
789 NULL,
790 INF_STYLE_WIN4,
791 LanguageId,
792 &ErrorLine);
793
794 if (SetupInf == INVALID_HANDLE_VALUE)
795 {
796 MUIDisplayError(ERROR_LOAD_TXTSETUPSIF, Ir, POPUP_WAIT_ENTER);
797 return QUIT_PAGE;
798 }
799
800 /* Open 'Version' section */
801 if (!SetupFindFirstLineW(SetupInf, L"Version", L"Signature", &Context))
802 {
803 MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF, Ir, POPUP_WAIT_ENTER);
804 return QUIT_PAGE;
805 }
806
807 /* Get pointer 'Signature' key */
808 if (!INF_GetData(&Context, NULL, &Value))
809 {
810 MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF, Ir, POPUP_WAIT_ENTER);
811 return QUIT_PAGE;
812 }
813
814 /* Check 'Signature' string */
815 if (_wcsicmp(Value, L"$ReactOS$") != 0)
816 {
817 MUIDisplayError(ERROR_SIGNATURE_TXTSETUPSIF, Ir, POPUP_WAIT_ENTER);
818 return QUIT_PAGE;
819 }
820
821 /* Open 'DiskSpaceRequirements' section */
822 if (!SetupFindFirstLineW(SetupInf, L"DiskSpaceRequirements", L"FreeSysPartDiskSpace", &Context))
823 {
824 MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF, Ir, POPUP_WAIT_ENTER);
825 return QUIT_PAGE;
826 }
827
828 /* Get the 'FreeSysPartDiskSpace' value */
829 if (!SetupGetIntField(&Context, 1, &IntValue))
830 {
831 MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF, Ir, POPUP_WAIT_ENTER);
832 return QUIT_PAGE;
833 }
834
835 RequiredPartitionDiskSpace = (ULONG)IntValue;
836
837 /* Start PnP thread */
838 if (hPnpThread != INVALID_HANDLE_VALUE)
839 {
840 NtResumeThread(hPnpThread, NULL);
841 hPnpThread = INVALID_HANDLE_VALUE;
842 }
843
844 CheckUnattendedSetup();
845
846 if (IsUnattendedSetup)
847 {
848 //TODO
849 //read options from inf
850 ComputerList = CreateComputerTypeList(SetupInf);
851 DisplayList = CreateDisplayDriverList(SetupInf);
852 KeyboardList = CreateKeyboardDriverList(SetupInf);
853 LayoutList = CreateKeyboardLayoutList(SetupInf, DefaultKBLayout);
854 LanguageList = CreateLanguageList(SetupInf, DefaultLanguage);
855
856 /* new part */
857 wcscpy(SelectedLanguageId,LocaleID);
858
859 /* first we hack LanguageList */
860 ListEntry = GetFirstListEntry(LanguageList);
861
862 while (ListEntry != NULL)
863 {
864 if (!wcsicmp(LocaleID, GetListEntryUserData(ListEntry)))
865 {
866 DPRINT("found %S in LanguageList\n",GetListEntryUserData(ListEntry));
867 SetCurrentListEntry(LanguageList, ListEntry);
868 break;
869 }
870
871 ListEntry = GetNextListEntry(ListEntry);
872 }
873
874 /* now LayoutList */
875 ListEntry = GetFirstListEntry(LayoutList);
876
877 while (ListEntry != NULL)
878 {
879 if (!wcsicmp(LocaleID, GetListEntryUserData(ListEntry)))
880 {
881 DPRINT("found %S in LayoutList\n",GetListEntryUserData(ListEntry));
882 SetCurrentListEntry(LayoutList, ListEntry);
883 break;
884 }
885
886 ListEntry = GetNextListEntry(ListEntry);
887 }
888
889 SetConsoleCodePage();
890
891 return INSTALL_INTRO_PAGE;
892 }
893
894 return LANGUAGE_PAGE;
895 }
896
897
898 /*
899 * First setup page
900 * RETURNS
901 * Next page number.
902 */
903 static PAGE_NUMBER
904 IntroPage(PINPUT_RECORD Ir)
905 {
906 MUIDisplayPage(START_PAGE);
907
908 while (TRUE)
909 {
910 CONSOLE_ConInKey(Ir);
911
912 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
913 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
914 {
915 if (ConfirmQuit(Ir) == TRUE)
916 return QUIT_PAGE;
917
918 break;
919 }
920 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
921 {
922 return INSTALL_INTRO_PAGE;
923 break;
924 }
925 else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'R') /* R */
926 {
927 return REPAIR_INTRO_PAGE;
928 break;
929 }
930 else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'L') /* R */
931 {
932 return LICENSE_PAGE;
933 break;
934 }
935 }
936
937 return INTRO_PAGE;
938 }
939
940
941 /*
942 * License Page
943 * RETURNS
944 * Back to main setup page.
945 */
946 static PAGE_NUMBER
947 LicensePage(PINPUT_RECORD Ir)
948 {
949 MUIDisplayPage(LICENSE_PAGE);
950
951 while (TRUE)
952 {
953 CONSOLE_ConInKey(Ir);
954
955 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
956 {
957 return INTRO_PAGE;
958 break;
959 }
960 }
961
962 return LICENSE_PAGE;
963 }
964
965
966 static PAGE_NUMBER
967 RepairIntroPage(PINPUT_RECORD Ir)
968 {
969 MUIDisplayPage(REPAIR_INTRO_PAGE);
970
971 while(TRUE)
972 {
973 CONSOLE_ConInKey(Ir);
974
975 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
976 {
977 return REBOOT_PAGE;
978 }
979 else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'U') /* U */
980 {
981 RepairUpdateFlag = TRUE;
982 return INSTALL_INTRO_PAGE;
983 }
984 else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'R') /* R */
985 {
986 return INTRO_PAGE;
987 }
988 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
989 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
990 {
991 return INTRO_PAGE;
992 }
993 }
994
995 return REPAIR_INTRO_PAGE;
996 }
997
998
999 static PAGE_NUMBER
1000 InstallIntroPage(PINPUT_RECORD Ir)
1001 {
1002 MUIDisplayPage(INSTALL_INTRO_PAGE);
1003
1004 if (RepairUpdateFlag)
1005 {
1006 //return SELECT_PARTITION_PAGE;
1007 return DEVICE_SETTINGS_PAGE;
1008 }
1009
1010 if (IsUnattendedSetup)
1011 {
1012 return SELECT_PARTITION_PAGE;
1013 }
1014
1015 while (TRUE)
1016 {
1017 CONSOLE_ConInKey(Ir);
1018
1019 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1020 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1021 {
1022 if (ConfirmQuit(Ir) == TRUE)
1023 return QUIT_PAGE;
1024
1025 break;
1026 }
1027 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1028 {
1029 return DEVICE_SETTINGS_PAGE;
1030 // return SCSI_CONTROLLER_PAGE;
1031 }
1032 }
1033
1034 return INSTALL_INTRO_PAGE;
1035 }
1036
1037
1038 #if 0
1039 static PAGE_NUMBER
1040 ScsiControllerPage(PINPUT_RECORD Ir)
1041 {
1042 SetTextXY(6, 8, "Setup detected the following mass storage devices:");
1043
1044 /* FIXME: print loaded mass storage driver descriptions */
1045 #if 0
1046 SetTextXY(8, 10, "TEST device");
1047 #endif
1048
1049
1050 SetStatusText(" ENTER = Continue F3 = Quit");
1051
1052 while (TRUE)
1053 {
1054 ConInKey(Ir);
1055
1056 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1057 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1058 {
1059 if (ConfirmQuit(Ir) == TRUE)
1060 return QUIT_PAGE;
1061
1062 break;
1063 }
1064 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1065 {
1066 return DEVICE_SETTINGS_PAGE;
1067 }
1068 }
1069
1070 return SCSI_CONTROLLER_PAGE;
1071 }
1072 #endif
1073
1074
1075 static PAGE_NUMBER
1076 DeviceSettingsPage(PINPUT_RECORD Ir)
1077 {
1078 static ULONG Line = 16;
1079 MUIDisplayPage(DEVICE_SETTINGS_PAGE);
1080
1081 /* Initialize the computer settings list */
1082 if (ComputerList == NULL)
1083 {
1084 ComputerList = CreateComputerTypeList(SetupInf);
1085 if (ComputerList == NULL)
1086 {
1087 MUIDisplayError(ERROR_LOAD_COMPUTER, Ir, POPUP_WAIT_ENTER);
1088 return QUIT_PAGE;
1089 }
1090 }
1091
1092 /* Initialize the display settings list */
1093 if (DisplayList == NULL)
1094 {
1095 DisplayList = CreateDisplayDriverList(SetupInf);
1096 if (DisplayList == NULL)
1097 {
1098 MUIDisplayError(ERROR_LOAD_DISPLAY, Ir, POPUP_WAIT_ENTER);
1099 return QUIT_PAGE;
1100 }
1101 }
1102
1103 /* Initialize the keyboard settings list */
1104 if (KeyboardList == NULL)
1105 {
1106 KeyboardList = CreateKeyboardDriverList(SetupInf);
1107 if (KeyboardList == NULL)
1108 {
1109 MUIDisplayError(ERROR_LOAD_KEYBOARD, Ir, POPUP_WAIT_ENTER);
1110 return QUIT_PAGE;
1111 }
1112 }
1113
1114 /* Initialize the keyboard layout list */
1115 if (LayoutList == NULL)
1116 {
1117 LayoutList = CreateKeyboardLayoutList(SetupInf, DefaultKBLayout);
1118 if (LayoutList == NULL)
1119 {
1120 /* FIXME: report error */
1121 MUIDisplayError(ERROR_LOAD_KBLAYOUT, Ir, POPUP_WAIT_ENTER);
1122 return QUIT_PAGE;
1123 }
1124 }
1125
1126 MUIDisplayPage(DEVICE_SETTINGS_PAGE);
1127
1128
1129 CONSOLE_SetTextXY(25, 11, GetListEntryText(GetCurrentListEntry((ComputerList))));
1130 CONSOLE_SetTextXY(25, 12, GetListEntryText(GetCurrentListEntry((DisplayList))));
1131 CONSOLE_SetTextXY(25, 13, GetListEntryText(GetCurrentListEntry((KeyboardList))));
1132 CONSOLE_SetTextXY(25, 14, GetListEntryText(GetCurrentListEntry((LayoutList))));
1133
1134 CONSOLE_InvertTextXY(24, Line, 48, 1);
1135
1136 if (RepairUpdateFlag)
1137 {
1138 return SELECT_PARTITION_PAGE;
1139 }
1140
1141 while (TRUE)
1142 {
1143 CONSOLE_ConInKey(Ir);
1144
1145 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1146 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1147 {
1148 CONSOLE_NormalTextXY(24, Line, 48, 1);
1149
1150 if (Line == 14)
1151 Line = 16;
1152 else if (Line == 16)
1153 Line = 11;
1154 else
1155 Line++;
1156
1157 CONSOLE_InvertTextXY(24, Line, 48, 1);
1158 }
1159 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1160 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1161 {
1162 CONSOLE_NormalTextXY(24, Line, 48, 1);
1163
1164 if (Line == 11)
1165 Line = 16;
1166 else if (Line == 16)
1167 Line = 14;
1168 else
1169 Line--;
1170
1171 CONSOLE_InvertTextXY(24, Line, 48, 1);
1172 }
1173 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1174 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1175 {
1176 if (ConfirmQuit(Ir) == TRUE)
1177 return QUIT_PAGE;
1178
1179 break;
1180 }
1181 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1182 {
1183 if (Line == 11)
1184 return COMPUTER_SETTINGS_PAGE;
1185 else if (Line == 12)
1186 return DISPLAY_SETTINGS_PAGE;
1187 else if (Line == 13)
1188 return KEYBOARD_SETTINGS_PAGE;
1189 else if (Line == 14)
1190 return LAYOUT_SETTINGS_PAGE;
1191 else if (Line == 16)
1192 return SELECT_PARTITION_PAGE;
1193 }
1194 }
1195
1196 return DEVICE_SETTINGS_PAGE;
1197 }
1198
1199
1200 static PAGE_NUMBER
1201 ComputerSettingsPage(PINPUT_RECORD Ir)
1202 {
1203 MUIDisplayPage(COMPUTER_SETTINGS_PAGE);
1204
1205 DrawGenericList(ComputerList,
1206 2,
1207 18,
1208 xScreen - 3,
1209 yScreen - 3);
1210
1211 SaveGenericListState(ComputerList);
1212
1213 while (TRUE)
1214 {
1215 CONSOLE_ConInKey(Ir);
1216
1217 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1218 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1219 {
1220 ScrollDownGenericList(ComputerList);
1221 }
1222 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1223 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1224 {
1225 ScrollUpGenericList(ComputerList);
1226 }
1227 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1228 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1229 {
1230 if (ConfirmQuit(Ir) == TRUE)
1231 return QUIT_PAGE;
1232
1233 break;
1234 }
1235 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1236 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
1237 {
1238 RestoreGenericListState(ComputerList);
1239 return DEVICE_SETTINGS_PAGE;
1240 }
1241 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1242 {
1243 return DEVICE_SETTINGS_PAGE;
1244 }
1245 }
1246
1247 return COMPUTER_SETTINGS_PAGE;
1248 }
1249
1250
1251 static PAGE_NUMBER
1252 DisplaySettingsPage(PINPUT_RECORD Ir)
1253 {
1254 MUIDisplayPage(DISPLAY_SETTINGS_PAGE);
1255
1256 DrawGenericList(DisplayList,
1257 2,
1258 18,
1259 xScreen - 3,
1260 yScreen - 3);
1261
1262 SaveGenericListState(DisplayList);
1263
1264 while (TRUE)
1265 {
1266 CONSOLE_ConInKey(Ir);
1267
1268 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1269 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1270 {
1271 ScrollDownGenericList(DisplayList);
1272 }
1273 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1274 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1275 {
1276 ScrollUpGenericList(DisplayList);
1277 }
1278 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1279 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1280 {
1281 if (ConfirmQuit(Ir) == TRUE)
1282 {
1283 return QUIT_PAGE;
1284 }
1285
1286 break;
1287 }
1288 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1289 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
1290 {
1291 RestoreGenericListState(DisplayList);
1292 return DEVICE_SETTINGS_PAGE;
1293 }
1294 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1295 {
1296 return DEVICE_SETTINGS_PAGE;
1297 }
1298 }
1299
1300 return DISPLAY_SETTINGS_PAGE;
1301 }
1302
1303
1304 static PAGE_NUMBER
1305 KeyboardSettingsPage(PINPUT_RECORD Ir)
1306 {
1307 MUIDisplayPage(KEYBOARD_SETTINGS_PAGE);
1308
1309 DrawGenericList(KeyboardList,
1310 2,
1311 18,
1312 xScreen - 3,
1313 yScreen - 3);
1314
1315 SaveGenericListState(KeyboardList);
1316
1317 while (TRUE)
1318 {
1319 CONSOLE_ConInKey(Ir);
1320
1321 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1322 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1323 {
1324 ScrollDownGenericList(KeyboardList);
1325 }
1326 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1327 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1328 {
1329 ScrollUpGenericList(KeyboardList);
1330 }
1331 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1332 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1333 {
1334 if (ConfirmQuit(Ir) == TRUE)
1335 return QUIT_PAGE;
1336
1337 break;
1338 }
1339 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1340 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
1341 {
1342 RestoreGenericListState(KeyboardList);
1343 return DEVICE_SETTINGS_PAGE;
1344 }
1345 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1346 {
1347 return DEVICE_SETTINGS_PAGE;
1348 }
1349 }
1350
1351 return DISPLAY_SETTINGS_PAGE;
1352 }
1353
1354
1355 static PAGE_NUMBER
1356 LayoutSettingsPage(PINPUT_RECORD Ir)
1357 {
1358 MUIDisplayPage(LAYOUT_SETTINGS_PAGE);
1359
1360 DrawGenericList(LayoutList,
1361 2,
1362 18,
1363 xScreen - 3,
1364 yScreen - 3);
1365
1366 SaveGenericListState(LayoutList);
1367
1368 while (TRUE)
1369 {
1370 CONSOLE_ConInKey(Ir);
1371
1372 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1373 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1374 {
1375 ScrollDownGenericList(LayoutList);
1376 }
1377 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1378 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1379 {
1380 ScrollUpGenericList(LayoutList);
1381 }
1382 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1383 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_NEXT)) /* PAGE DOWN */
1384 {
1385 ScrollPageDownGenericList(LayoutList);
1386 }
1387 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1388 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_PRIOR)) /* PAGE UP */
1389 {
1390 ScrollPageUpGenericList(LayoutList);
1391 }
1392 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1393 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1394 {
1395 if (ConfirmQuit(Ir) == TRUE)
1396 return QUIT_PAGE;
1397
1398 break;
1399 }
1400 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1401 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
1402 {
1403 RestoreGenericListState(LayoutList);
1404 return DEVICE_SETTINGS_PAGE;
1405 }
1406 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1407 {
1408 return DEVICE_SETTINGS_PAGE;
1409 }
1410 else if ((Ir->Event.KeyEvent.uChar.AsciiChar > 0x60) && (Ir->Event.KeyEvent.uChar.AsciiChar < 0x7b))
1411 {
1412 /* a-z */
1413 GenericListKeyPress(LayoutList , Ir->Event.KeyEvent.uChar.AsciiChar);
1414 }
1415 }
1416
1417 return DISPLAY_SETTINGS_PAGE;
1418 }
1419
1420
1421 static BOOL
1422 IsDiskSizeValid(PPARTENTRY PartEntry)
1423 {
1424 ULONGLONG m1, m2;
1425
1426 /* check for unpartitioned space */
1427 m1 = PartEntry->UnpartitionedLength;
1428 m1 = (m1 + (1 << 19)) >> 20; /* in MBytes (rounded) */
1429
1430 if( m1 > RequiredPartitionDiskSpace)
1431 {
1432 return TRUE;
1433 }
1434
1435 /* check for partitioned space */
1436 m2 = PartEntry->PartInfo[0].PartitionLength.QuadPart;
1437 m2 = (m2 + (1 << 19)) >> 20; /* in MBytes (rounded) */
1438 if (m2 < RequiredPartitionDiskSpace)
1439 {
1440 /* partition is too small so ask for another partion */
1441 DPRINT1("Partition is too small(unpartitioned: %I64u MB, partitioned: %I64u MB), required disk space is %lu MB\n", m1, m2, RequiredPartitionDiskSpace);
1442 return FALSE;
1443 }
1444 else
1445 {
1446 return TRUE;
1447 }
1448 }
1449
1450
1451 static PAGE_NUMBER
1452 SelectPartitionPage(PINPUT_RECORD Ir)
1453 {
1454 MUIDisplayPage(SELECT_PARTITION_PAGE);
1455
1456 if (PartitionList == NULL)
1457 {
1458 PartitionList = CreatePartitionList(2,
1459 19,
1460 xScreen - 3,
1461 yScreen - 3);
1462 if (PartitionList == NULL)
1463 {
1464 /* FIXME: show an error dialog */
1465 return QUIT_PAGE;
1466 }
1467 }
1468
1469 DrawPartitionList(PartitionList);
1470
1471 /* Warn about partitions created by Linux Fdisk */
1472 if (WarnLinuxPartitions == TRUE &&
1473 CheckForLinuxFdiskPartitions(PartitionList) == TRUE)
1474 {
1475 MUIDisplayError(ERROR_WARN_PARTITION, NULL, POPUP_WAIT_NONE);
1476
1477 while (TRUE)
1478 {
1479 CONSOLE_ConInKey(Ir);
1480
1481 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1482 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1483 {
1484 return QUIT_PAGE;
1485 }
1486 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
1487 {
1488 WarnLinuxPartitions = FALSE;
1489 return SELECT_PARTITION_PAGE;
1490 }
1491 }
1492 }
1493
1494 if (IsUnattendedSetup)
1495 {
1496 if (!SelectPartition(PartitionList, UnattendDestinationDiskNumber, UnattendDestinationPartitionNumber))
1497 {
1498 if (AutoPartition)
1499 {
1500 PPARTENTRY PartEntry = PartitionList->CurrentPartition;
1501 ULONG MaxSize = (PartEntry->UnpartitionedLength + (1 << 19)) >> 20; /* in MBytes (rounded) */
1502 if(!IsDiskSizeValid(PartitionList->CurrentPartition))
1503 {
1504 MUIDisplayError(ERROR_INSUFFICIENT_DISKSPACE, Ir, POPUP_WAIT_ANY_KEY);
1505 return SELECT_PARTITION_PAGE; /* let the user select another partition */
1506 }
1507
1508 CreateNewPartition(PartitionList,
1509 MaxSize,
1510 TRUE);
1511
1512 return SELECT_FILE_SYSTEM_PAGE;
1513 }
1514 }
1515 else
1516 {
1517 if(!IsDiskSizeValid(PartitionList->CurrentPartition))
1518 {
1519 MUIDisplayError(ERROR_INSUFFICIENT_DISKSPACE, Ir, POPUP_WAIT_ANY_KEY);
1520 return SELECT_PARTITION_PAGE; /* let the user select another partition */
1521 }
1522
1523 return SELECT_FILE_SYSTEM_PAGE;
1524 }
1525 }
1526
1527 while (TRUE)
1528 {
1529 /* Update status text */
1530 if (PartitionList->CurrentPartition == NULL ||
1531 PartitionList->CurrentPartition->Unpartitioned == TRUE)
1532 {
1533 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATEPARTITION));
1534 }
1535 else
1536 {
1537 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLDELETEPARTITION));
1538 }
1539
1540 CONSOLE_ConInKey(Ir);
1541
1542 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1543 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1544 {
1545 if (ConfirmQuit(Ir) == TRUE)
1546 {
1547 DestroyPartitionList(PartitionList);
1548 PartitionList = NULL;
1549 return QUIT_PAGE;
1550 }
1551
1552 break;
1553 }
1554 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1555 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
1556 {
1557 ScrollDownPartitionList(PartitionList);
1558 }
1559 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1560 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
1561 {
1562 ScrollUpPartitionList(PartitionList);
1563 }
1564 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
1565 {
1566 if(!IsDiskSizeValid(PartitionList->CurrentPartition))
1567 {
1568 MUIDisplayError(ERROR_INSUFFICIENT_DISKSPACE, Ir, POPUP_WAIT_ANY_KEY);
1569 return SELECT_PARTITION_PAGE; /* let the user select another partition */
1570 }
1571 if (PartitionList->CurrentPartition == NULL ||
1572 PartitionList->CurrentPartition->Unpartitioned == TRUE)
1573 {
1574 CreateNewPartition(PartitionList,
1575 0ULL,
1576 TRUE);
1577 }
1578
1579 return SELECT_FILE_SYSTEM_PAGE;
1580 }
1581 else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'C') /* C */
1582 {
1583 if (PartitionList->CurrentPartition->Unpartitioned == FALSE)
1584 {
1585 MUIDisplayError(ERROR_NEW_PARTITION, Ir, POPUP_WAIT_ANY_KEY);
1586 return SELECT_PARTITION_PAGE;
1587 }
1588
1589 return CREATE_PARTITION_PAGE;
1590 }
1591 else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'D') /* D */
1592 {
1593 if (PartitionList->CurrentPartition->Unpartitioned == TRUE)
1594 {
1595 MUIDisplayError(ERROR_DELETE_SPACE, Ir, POPUP_WAIT_ANY_KEY);
1596 return SELECT_PARTITION_PAGE;
1597 }
1598
1599 return DELETE_PARTITION_PAGE;
1600 }
1601 }
1602
1603 return SELECT_PARTITION_PAGE;
1604 }
1605
1606
1607 static VOID
1608 DrawInputField(ULONG FieldLength,
1609 SHORT Left,
1610 SHORT Top,
1611 PCHAR FieldContent)
1612 {
1613 CHAR buf[100];
1614 COORD coPos;
1615 DWORD Written;
1616
1617 coPos.X = Left;
1618 coPos.Y = Top;
1619 memset(buf, '_', sizeof(buf));
1620 buf[FieldLength - strlen(FieldContent)] = 0;
1621 strcat(buf, FieldContent);
1622
1623 WriteConsoleOutputCharacterA(StdOutput,
1624 buf,
1625 strlen(buf),
1626 coPos,
1627 &Written);
1628 }
1629
1630
1631 #define PARTITION_SIZE_INPUT_FIELD_LENGTH 6
1632 /* Restriction for MaxSize: pow(10, PARTITION_SIZE_INPUT_FIELD_LENGTH)-1 */
1633 #define PARTITION_MAXSIZE 999999
1634
1635 static VOID
1636 ShowPartitionSizeInputBox(SHORT Left,
1637 SHORT Top,
1638 SHORT Right,
1639 SHORT Bottom,
1640 ULONG MaxSize,
1641 PCHAR InputBuffer,
1642 PBOOLEAN Quit,
1643 PBOOLEAN Cancel)
1644 {
1645 INPUT_RECORD Ir;
1646 COORD coPos;
1647 DWORD Written;
1648 CHAR Buffer[100];
1649 ULONG Index;
1650 CHAR ch;
1651 SHORT iLeft;
1652 SHORT iTop;
1653
1654 if (Quit != NULL)
1655 *Quit = FALSE;
1656
1657 if (Cancel != NULL)
1658 *Cancel = FALSE;
1659
1660 DrawBox(Left, Top, Right - Left + 1, Bottom - Top + 1);
1661
1662 /* Print message */
1663 coPos.X = Left + 2;
1664 coPos.Y = Top + 2;
1665 strcpy(Buffer, MUIGetString(STRING_PARTITIONSIZE));
1666 iLeft = coPos.X + strlen(Buffer) + 1;
1667 iTop = coPos.Y;
1668
1669 WriteConsoleOutputCharacterA(StdOutput,
1670 Buffer,
1671 strlen (Buffer),
1672 coPos,
1673 &Written);
1674
1675 sprintf(Buffer, MUIGetString(STRING_MAXSIZE), MaxSize);
1676 coPos.X = iLeft + PARTITION_SIZE_INPUT_FIELD_LENGTH + 1;
1677 coPos.Y = iTop;
1678 WriteConsoleOutputCharacterA(StdOutput,
1679 Buffer,
1680 strlen (Buffer),
1681 coPos,
1682 &Written);
1683
1684 sprintf(Buffer, "%lu", MaxSize);
1685 Index = strlen(Buffer);
1686 DrawInputField(PARTITION_SIZE_INPUT_FIELD_LENGTH,
1687 iLeft,
1688 iTop,
1689 Buffer);
1690
1691 while (TRUE)
1692 {
1693 CONSOLE_ConInKey(&Ir);
1694
1695 if ((Ir.Event.KeyEvent.uChar.AsciiChar == 0x00) &&
1696 (Ir.Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
1697 {
1698 if (Quit != NULL)
1699 *Quit = TRUE;
1700
1701 Buffer[0] = 0;
1702 break;
1703 }
1704 else if (Ir.Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
1705 {
1706 break;
1707 }
1708 else if (Ir.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESCAPE */
1709 {
1710 if (Cancel != NULL)
1711 *Cancel = TRUE;
1712
1713 Buffer[0] = 0;
1714 break;
1715 }
1716 else if ((Ir.Event.KeyEvent.wVirtualKeyCode == VK_BACK) && /* BACKSPACE */
1717 (Index > 0))
1718 {
1719 Index--;
1720 Buffer[Index] = 0;
1721
1722 DrawInputField(PARTITION_SIZE_INPUT_FIELD_LENGTH,
1723 iLeft,
1724 iTop,
1725 Buffer);
1726 }
1727 else if ((Ir.Event.KeyEvent.uChar.AsciiChar != 0x00) &&
1728 (Index < PARTITION_SIZE_INPUT_FIELD_LENGTH))
1729 {
1730 ch = Ir.Event.KeyEvent.uChar.AsciiChar;
1731
1732 if ((ch >= '0') && (ch <= '9'))
1733 {
1734 Buffer[Index] = ch;
1735 Index++;
1736 Buffer[Index] = 0;
1737
1738 DrawInputField(PARTITION_SIZE_INPUT_FIELD_LENGTH,
1739 iLeft,
1740 iTop,
1741 Buffer);
1742 }
1743 }
1744 }
1745
1746 strcpy(InputBuffer, Buffer);
1747 }
1748
1749
1750 static PAGE_NUMBER
1751 CreatePartitionPage(PINPUT_RECORD Ir)
1752 {
1753 PDISKENTRY DiskEntry;
1754 PPARTENTRY PartEntry;
1755 BOOLEAN Quit;
1756 BOOLEAN Cancel;
1757 CHAR InputBuffer[50];
1758 ULONG MaxSize;
1759 ULONGLONG PartSize;
1760 ULONGLONG DiskSize;
1761 PCHAR Unit;
1762
1763 if (PartitionList == NULL ||
1764 PartitionList->CurrentDisk == NULL ||
1765 PartitionList->CurrentPartition == NULL)
1766 {
1767 /* FIXME: show an error dialog */
1768 return QUIT_PAGE;
1769 }
1770
1771 DiskEntry = PartitionList->CurrentDisk;
1772 PartEntry = PartitionList->CurrentPartition;
1773
1774 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
1775
1776 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSENEWPARTITION));
1777
1778 #if 0
1779 if (DiskEntry->DiskSize >= 0x280000000ULL) /* 10 GB */
1780 {
1781 DiskSize = (DiskEntry->DiskSize + (1 << 29)) >> 30;
1782 Unit = MUIGetString(STRING_GB);
1783 }
1784 else
1785 #endif
1786 {
1787 DiskSize = (DiskEntry->DiskSize + (1 << 19)) >> 20;
1788
1789 if (DiskSize == 0)
1790 DiskSize = 1;
1791
1792 Unit = MUIGetString(STRING_MB);
1793 }
1794
1795 if (DiskEntry->DriverName.Length > 0)
1796 {
1797 CONSOLE_PrintTextXY(6, 10,
1798 MUIGetString(STRING_HDINFOPARTCREATE),
1799 DiskSize,
1800 Unit,
1801 DiskEntry->DiskNumber,
1802 DiskEntry->Port,
1803 DiskEntry->Bus,
1804 DiskEntry->Id,
1805 &DiskEntry->DriverName);
1806 }
1807 else
1808 {
1809 CONSOLE_PrintTextXY(6, 10,
1810 MUIGetString(STRING_HDDINFOUNK1),
1811 DiskSize,
1812 Unit,
1813 DiskEntry->DiskNumber,
1814 DiskEntry->Port,
1815 DiskEntry->Bus,
1816 DiskEntry->Id);
1817 }
1818
1819 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE));
1820
1821 #if 0
1822 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
1823 PartitionList->CurrentPartition->UnpartitionedLength / (1024*1024));
1824 #endif
1825
1826 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION));
1827
1828 PartEntry = PartitionList->CurrentPartition;
1829 while (TRUE)
1830 {
1831 MaxSize = (PartEntry->UnpartitionedLength + (1 << 19)) >> 20; /* in MBytes (rounded) */
1832
1833 if (MaxSize > PARTITION_MAXSIZE) MaxSize = PARTITION_MAXSIZE;
1834
1835 ShowPartitionSizeInputBox(12, 14, xScreen - 12, 17, /* left, top, right, bottom */
1836 MaxSize, InputBuffer, &Quit, &Cancel);
1837
1838 if (Quit == TRUE)
1839 {
1840 if (ConfirmQuit (Ir) == TRUE)
1841 {
1842 return QUIT_PAGE;
1843 }
1844 }
1845 else if (Cancel == TRUE)
1846 {
1847 return SELECT_PARTITION_PAGE;
1848 }
1849 else
1850 {
1851 PartSize = atoi(InputBuffer);
1852
1853 if (PartSize < 1)
1854 {
1855 /* Too small */
1856 continue;
1857 }
1858
1859 if (PartSize > MaxSize)
1860 {
1861 /* Too large */
1862 continue;
1863 }
1864
1865 /* Convert to bytes */
1866 if (PartSize == MaxSize)
1867 {
1868 /* Use all of the unpartitioned disk space */
1869 PartSize = PartEntry->UnpartitionedLength;
1870 }
1871 else
1872 {
1873 /* Round-up by cylinder size */
1874 PartSize = (PartSize * 1024 * 1024 + DiskEntry->CylinderSize - 1) /
1875 DiskEntry->CylinderSize * DiskEntry->CylinderSize;
1876
1877 /* But never get larger than the unpartitioned disk space */
1878 if (PartSize > PartEntry->UnpartitionedLength)
1879 PartSize = PartEntry->UnpartitionedLength;
1880 }
1881
1882 DPRINT ("Partition size: %I64u bytes\n", PartSize);
1883
1884 CreateNewPartition(PartitionList,
1885 PartSize,
1886 FALSE);
1887
1888 return SELECT_PARTITION_PAGE;
1889 }
1890 }
1891
1892 return CREATE_PARTITION_PAGE;
1893 }
1894
1895
1896 static PAGE_NUMBER
1897 DeletePartitionPage(PINPUT_RECORD Ir)
1898 {
1899 PDISKENTRY DiskEntry;
1900 PPARTENTRY PartEntry;
1901 ULONGLONG DiskSize;
1902 ULONGLONG PartSize;
1903 PCHAR Unit;
1904 PCHAR PartType;
1905 UCHAR PartNumber;
1906
1907 if (PartitionList == NULL ||
1908 PartitionList->CurrentDisk == NULL ||
1909 PartitionList->CurrentPartition == NULL)
1910 {
1911 /* FIXME: show an error dialog */
1912 return QUIT_PAGE;
1913 }
1914
1915 DiskEntry = PartitionList->CurrentDisk;
1916 PartEntry = PartitionList->CurrentPartition;
1917 PartNumber = PartitionList->CurrentPartitionNumber;
1918
1919 MUIDisplayPage(DELETE_PARTITION_PAGE);
1920
1921 /* Determine partition type */
1922 PartType = NULL;
1923 if (PartEntry->New == TRUE)
1924 {
1925 PartType = MUIGetString(STRING_UNFORMATTED);
1926 }
1927 else if (PartEntry->Unpartitioned == FALSE)
1928 {
1929 if ((PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_FAT_12) ||
1930 (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_FAT_16) ||
1931 (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_HUGE) ||
1932 (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_XINT13))
1933 {
1934 PartType = "FAT";
1935 }
1936 else if ((PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_FAT32) ||
1937 (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_FAT32_XINT13))
1938 {
1939 PartType = "FAT32";
1940 }
1941 else if (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_EXT2)
1942 {
1943 PartType = "EXT2";
1944 }
1945 else if (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_IFS)
1946 {
1947 PartType = "NTFS"; /* FIXME: Not quite correct! */
1948 }
1949 }
1950
1951 #if 0
1952 if (PartEntry->PartInfo[PartNumber].PartitionLength.QuadPart >= 0x280000000LL) /* 10 GB */
1953 {
1954 PartSize = (PartEntry->PartInfo[PartNumber].PartitionLength.QuadPart + (1 << 29)) >> 30;
1955 Unit = MUIGetString(STRING_GB);
1956 }
1957 else
1958 #endif
1959 if (PartEntry->PartInfo[PartNumber].PartitionLength.QuadPart >= 0xA00000LL) /* 10 MB */
1960 {
1961 PartSize = (PartEntry->PartInfo[PartNumber].PartitionLength.QuadPart + (1 << 19)) >> 20;
1962 Unit = MUIGetString(STRING_MB);
1963 }
1964 else
1965 {
1966 PartSize = (PartEntry->PartInfo[PartNumber].PartitionLength.QuadPart + (1 << 9)) >> 10;
1967 Unit = MUIGetString(STRING_KB);
1968 }
1969
1970 if (PartType == NULL)
1971 {
1972 CONSOLE_PrintTextXY(6, 10,
1973 MUIGetString(STRING_HDDINFOUNK2),
1974 (PartEntry->DriveLetter[PartNumber] == 0) ? '-' : PartEntry->DriveLetter[PartNumber],
1975 (PartEntry->DriveLetter[PartNumber] == 0) ? '-' : ':',
1976 PartEntry->PartInfo[PartNumber].PartitionType,
1977 PartSize,
1978 Unit);
1979 }
1980 else
1981 {
1982 CONSOLE_PrintTextXY(6, 10,
1983 " %c%c %s %I64u %s",
1984 (PartEntry->DriveLetter[PartNumber] == 0) ? '-' : PartEntry->DriveLetter[PartNumber],
1985 (PartEntry->DriveLetter[PartNumber] == 0) ? '-' : ':',
1986 PartType,
1987 PartSize,
1988 Unit);
1989 }
1990
1991 #if 0
1992 if (DiskEntry->DiskSize >= 0x280000000ULL) /* 10 GB */
1993 {
1994 DiskSize = (DiskEntry->DiskSize + (1 << 29)) >> 30;
1995 Unit = MUIGetString(STRING_GB);
1996 }
1997 else
1998 #endif
1999 {
2000 DiskSize = (DiskEntry->DiskSize + (1 << 19)) >> 20;
2001
2002 if (DiskSize == 0)
2003 DiskSize = 1;
2004
2005 Unit = MUIGetString(STRING_MB);
2006 }
2007
2008 if (DiskEntry->DriverName.Length > 0)
2009 {
2010 CONSOLE_PrintTextXY(6, 12,
2011 MUIGetString(STRING_HDINFOPARTDELETE),
2012 DiskSize,
2013 Unit,
2014 DiskEntry->DiskNumber,
2015 DiskEntry->Port,
2016 DiskEntry->Bus,
2017 DiskEntry->Id,
2018 &DiskEntry->DriverName);
2019 }
2020 else
2021 {
2022 CONSOLE_PrintTextXY(6, 12,
2023 MUIGetString(STRING_HDDINFOUNK3),
2024 DiskSize,
2025 Unit,
2026 DiskEntry->DiskNumber,
2027 DiskEntry->Port,
2028 DiskEntry->Bus,
2029 DiskEntry->Id);
2030 }
2031
2032 while (TRUE)
2033 {
2034 CONSOLE_ConInKey(Ir);
2035
2036 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2037 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
2038 {
2039 if (ConfirmQuit(Ir) == TRUE)
2040 {
2041 return QUIT_PAGE;
2042 }
2043
2044 break;
2045 }
2046 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESC */
2047 {
2048 return SELECT_PARTITION_PAGE;
2049 }
2050 else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'D') /* D */
2051 {
2052 DeleteCurrentPartition(PartitionList);
2053
2054 return SELECT_PARTITION_PAGE;
2055 }
2056 }
2057
2058 return DELETE_PARTITION_PAGE;
2059 }
2060
2061
2062 static PAGE_NUMBER
2063 SelectFileSystemPage(PINPUT_RECORD Ir)
2064 {
2065 PDISKENTRY DiskEntry;
2066 PPARTENTRY PartEntry;
2067 UCHAR PartNumber;
2068 ULONGLONG DiskSize;
2069 ULONGLONG PartSize;
2070 PCHAR DiskUnit;
2071 PCHAR PartUnit;
2072 PCHAR PartType;
2073
2074 if (PartitionList == NULL ||
2075 PartitionList->CurrentDisk == NULL ||
2076 PartitionList->CurrentPartition == NULL)
2077 {
2078 /* FIXME: show an error dialog */
2079 return QUIT_PAGE;
2080 }
2081
2082 DiskEntry = PartitionList->CurrentDisk;
2083 PartEntry = PartitionList->CurrentPartition;
2084 PartNumber = PartitionList->CurrentPartitionNumber;
2085
2086 /* adjust disk size */
2087 if (DiskEntry->DiskSize >= 0x280000000ULL) /* 10 GB */
2088 {
2089 DiskSize = (DiskEntry->DiskSize + (1 << 29)) >> 30;
2090 DiskUnit = MUIGetString(STRING_GB);
2091 }
2092 else
2093 {
2094 DiskSize = (DiskEntry->DiskSize + (1 << 19)) >> 20;
2095 DiskUnit = MUIGetString(STRING_MB);
2096 }
2097
2098 /* adjust partition size */
2099 if (PartEntry->PartInfo[PartNumber].PartitionLength.QuadPart >= 0x280000000LL) /* 10 GB */
2100 {
2101 PartSize = (PartEntry->PartInfo[PartNumber].PartitionLength.QuadPart + (1 << 29)) >> 30;
2102 PartUnit = MUIGetString(STRING_GB);
2103 }
2104 else
2105 {
2106 PartSize = (PartEntry->PartInfo[PartNumber].PartitionLength.QuadPart + (1 << 19)) >> 20;
2107 PartUnit = MUIGetString(STRING_MB);
2108 }
2109
2110 /* adjust partition type */
2111 if ((PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_FAT_12) ||
2112 (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_FAT_16) ||
2113 (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_HUGE) ||
2114 (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_XINT13))
2115 {
2116 PartType = "FAT";
2117 }
2118 else if ((PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_FAT32) ||
2119 (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_FAT32_XINT13))
2120 {
2121 PartType = "FAT32";
2122 }
2123 else if (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_EXT2)
2124 {
2125 PartType = "EXT2";
2126 }
2127 else if (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_IFS)
2128 {
2129 PartType = "NTFS"; /* FIXME: Not quite correct! */
2130 }
2131 else if (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_ENTRY_UNUSED)
2132 {
2133 PartType = MUIGetString(STRING_FORMATUNUSED);
2134 }
2135 else
2136 {
2137 PartType = MUIGetString(STRING_FORMATUNKNOWN);
2138 }
2139
2140 if (PartEntry->AutoCreate == TRUE)
2141 {
2142 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NEWPARTITION));
2143
2144 #if 0
2145 CONSOLE_PrintTextXY(8, 10, "Partition %lu (%I64u %s) %s of",
2146 PartEntry->PartInfo[PartNumber].PartitionNumber,
2147 PartSize,
2148 PartUnit,
2149 PartType);
2150 #endif
2151
2152 CONSOLE_PrintTextXY(8, 10, MUIGetString(STRING_HDINFOPARTZEROED),
2153 DiskEntry->DiskNumber,
2154 DiskSize,
2155 DiskUnit,
2156 DiskEntry->Port,
2157 DiskEntry->Bus,
2158 DiskEntry->Id,
2159 &DiskEntry->DriverName);
2160
2161 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_PARTFORMAT));
2162
2163
2164 PartEntry->AutoCreate = FALSE;
2165 }
2166 else if (PartEntry->New == TRUE)
2167 {
2168 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDPART));
2169 CONSOLE_SetTextXY(6, 10, MUIGetString(STRING_PARTFORMAT));
2170 }
2171 else
2172 {
2173 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_INSTALLONPART));
2174
2175 if (PartType == NULL)
2176 {
2177 CONSOLE_PrintTextXY(8, 10,
2178 MUIGetString(STRING_HDDINFOUNK4),
2179 (PartEntry->DriveLetter[PartNumber] == 0) ? '-' : PartEntry->DriveLetter[PartNumber],
2180 (PartEntry->DriveLetter[PartNumber] == 0) ? '-' : ':',
2181 PartEntry->PartInfo[PartNumber].PartitionType,
2182 PartSize,
2183 PartUnit);
2184 }
2185 else
2186 {
2187 CONSOLE_PrintTextXY(8, 10,
2188 "%c%c %s %I64u %s",
2189 (PartEntry->DriveLetter[PartNumber] == 0) ? '-' : PartEntry->DriveLetter[PartNumber],
2190 (PartEntry->DriveLetter[PartNumber] == 0) ? '-' : ':',
2191 PartType,
2192 PartSize,
2193 PartUnit);
2194 }
2195
2196 CONSOLE_PrintTextXY(6, 12, MUIGetString(STRING_HDINFOPARTEXISTS),
2197 DiskEntry->DiskNumber,
2198 DiskSize,
2199 DiskUnit,
2200 DiskEntry->Port,
2201 DiskEntry->Bus,
2202 DiskEntry->Id,
2203 &DiskEntry->DriverName);
2204 }
2205
2206 MUIDisplayPage(SELECT_FILE_SYSTEM_PAGE);
2207
2208 if (FileSystemList == NULL)
2209 {
2210 FileSystemList = CreateFileSystemList(6, 26, PartEntry->New, L"FAT");
2211 if (FileSystemList == NULL)
2212 {
2213 /* FIXME: show an error dialog */
2214 return QUIT_PAGE;
2215 }
2216
2217 /* FIXME: Add file systems to list */
2218 }
2219 DrawFileSystemList(FileSystemList);
2220
2221 if (RepairUpdateFlag)
2222 {
2223 return CHECK_FILE_SYSTEM_PAGE;
2224 //return SELECT_PARTITION_PAGE;
2225 }
2226
2227 if (IsUnattendedSetup)
2228 {
2229 if (UnattendFormatPartition)
2230 {
2231 return FORMAT_PARTITION_PAGE;
2232 }
2233
2234 return CHECK_FILE_SYSTEM_PAGE;
2235 }
2236
2237 while (TRUE)
2238 {
2239 CONSOLE_ConInKey(Ir);
2240
2241 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2242 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
2243 {
2244 if (ConfirmQuit(Ir) == TRUE)
2245 {
2246 return QUIT_PAGE;
2247 }
2248
2249 break;
2250 }
2251 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2252 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
2253 {
2254 return SELECT_PARTITION_PAGE;
2255 }
2256 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2257 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */
2258 {
2259 ScrollDownFileSystemList(FileSystemList);
2260 }
2261 else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2262 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */
2263 {
2264 ScrollUpFileSystemList(FileSystemList);
2265 }
2266 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
2267 {
2268 if (!FileSystemList->Selected->FormatFunc)
2269 {
2270 return CHECK_FILE_SYSTEM_PAGE;
2271 }
2272 else
2273 {
2274 return FORMAT_PARTITION_PAGE;
2275 }
2276 }
2277 }
2278
2279 return SELECT_FILE_SYSTEM_PAGE;
2280 }
2281
2282
2283 static ULONG
2284 FormatPartitionPage(PINPUT_RECORD Ir)
2285 {
2286 WCHAR PathBuffer[MAX_PATH];
2287 PPARTENTRY PartEntry;
2288 UCHAR PartNum;
2289 NTSTATUS Status;
2290
2291 #ifndef NDEBUG
2292 PDISKENTRY DiskEntry;
2293 ULONG Line;
2294 ULONG i;
2295 PLIST_ENTRY Entry;
2296 #endif
2297
2298 MUIDisplayPage(FORMAT_PARTITION_PAGE);
2299
2300 if (PartitionList == NULL ||
2301 PartitionList->CurrentDisk == NULL ||
2302 PartitionList->CurrentPartition == NULL)
2303 {
2304 /* FIXME: show an error dialog */
2305 return QUIT_PAGE;
2306 }
2307
2308 #ifndef NDEBUG
2309 DiskEntry = PartitionList->CurrentDisk;
2310 #endif
2311 PartEntry = PartitionList->CurrentPartition;
2312 PartNum = PartitionList->CurrentPartitionNumber;
2313
2314 while (TRUE)
2315 {
2316 if (!IsUnattendedSetup)
2317 {
2318 CONSOLE_ConInKey(Ir);
2319 }
2320
2321 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2322 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
2323 {
2324 if (ConfirmQuit(Ir) == TRUE)
2325 {
2326 return QUIT_PAGE;
2327 }
2328
2329 break;
2330 }
2331 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN || IsUnattendedSetup) /* ENTER */
2332 {
2333 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
2334
2335 if (wcscmp(FileSystemList->Selected->FileSystem, L"FAT") == 0)
2336 {
2337 if (PartEntry->PartInfo[PartNum].PartitionLength.QuadPart < (4200LL * 1024LL))
2338 {
2339 /* FAT12 CHS partition (disk is smaller than 4.1MB) */
2340 PartEntry->PartInfo[PartNum].PartitionType = PARTITION_FAT_12;
2341 }
2342 else if (PartEntry->PartInfo[PartNum].StartingOffset.QuadPart < (1024LL * 255LL * 63LL * 512LL))
2343 {
2344 /* Partition starts below the 8.4GB boundary ==> CHS partition */
2345
2346 if (PartEntry->PartInfo[PartNum].PartitionLength.QuadPart < (32LL * 1024LL * 1024LL))
2347 {
2348 /* FAT16 CHS partition (partiton size < 32MB) */
2349 PartEntry->PartInfo[PartNum].PartitionType = PARTITION_FAT_16;
2350 }
2351 else if (PartEntry->PartInfo[PartNum].PartitionLength.QuadPart < (512LL * 1024LL * 1024LL))
2352 {
2353 /* FAT16 CHS partition (partition size < 512MB) */
2354 PartEntry->PartInfo[PartNum].PartitionType = PARTITION_HUGE;
2355 }
2356 else
2357 {
2358 /* FAT32 CHS partition (partition size >= 512MB) */
2359 PartEntry->PartInfo[PartNum].PartitionType = PARTITION_FAT32;
2360 }
2361 }
2362 else
2363 {
2364 /* Partition starts above the 8.4GB boundary ==> LBA partition */
2365
2366 if (PartEntry->PartInfo[PartNum].PartitionLength.QuadPart < (512LL * 1024LL * 1024LL))
2367 {
2368 /* FAT16 LBA partition (partition size < 512MB) */
2369 PartEntry->PartInfo[PartNum].PartitionType = PARTITION_XINT13;
2370 }
2371 else
2372 {
2373 /* FAT32 LBA partition (partition size >= 512MB) */
2374 PartEntry->PartInfo[PartNum].PartitionType = PARTITION_FAT32_XINT13;
2375 }
2376 }
2377 }
2378 else if (wcscmp(FileSystemList->Selected->FileSystem, L"EXT2") == 0)
2379 PartEntry->PartInfo[PartNum].PartitionType = PARTITION_EXT2;
2380 else if (!FileSystemList->Selected->FormatFunc)
2381 return QUIT_PAGE;
2382
2383 #ifndef NDEBUG
2384 CONSOLE_PrintTextXY(6, 12,
2385 "Disk: %I64u Cylinder: %I64u Track: %I64u",
2386 DiskEntry->DiskSize,
2387 DiskEntry->CylinderSize,
2388 DiskEntry->TrackSize);
2389
2390 Line = 13;
2391 DiskEntry = PartitionList->CurrentDisk;
2392 Entry = DiskEntry->PartListHead.Flink;
2393
2394 while (Entry != &DiskEntry->PartListHead)
2395 {
2396 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
2397
2398 if (PartEntry->Unpartitioned == FALSE)
2399 {
2400 for (i = 0; i < 4; i++)
2401 {
2402 CONSOLE_PrintTextXY(6, Line,
2403 "%2u: %2u %c %12I64u %12I64u %2u %c",
2404 i,
2405 PartEntry->PartInfo[i].PartitionNumber,
2406 PartEntry->PartInfo[i].BootIndicator ? 'A' : '-',
2407 PartEntry->PartInfo[i].StartingOffset.QuadPart,
2408 PartEntry->PartInfo[i].PartitionLength.QuadPart,
2409 PartEntry->PartInfo[i].PartitionType,
2410 PartEntry->PartInfo[i].RewritePartition ? '*' : ' ');
2411
2412 Line++;
2413 }
2414
2415 Line++;
2416 }
2417
2418 Entry = Entry->Flink;
2419 }
2420
2421 /* Restore the old entry */
2422 PartEntry = PartitionList->CurrentPartition;
2423 #endif
2424
2425 if (WritePartitionsToDisk(PartitionList) == FALSE)
2426 {
2427 DPRINT("WritePartitionsToDisk() failed\n");
2428 MUIDisplayError(ERROR_WRITE_PTABLE, Ir, POPUP_WAIT_ENTER);
2429 return QUIT_PAGE;
2430 }
2431
2432 /* Set DestinationRootPath */
2433 RtlFreeUnicodeString(&DestinationRootPath);
2434 swprintf(PathBuffer,
2435 L"\\Device\\Harddisk%lu\\Partition%lu",
2436 PartitionList->CurrentDisk->DiskNumber,
2437 PartitionList->CurrentPartition->PartInfo[PartNum].PartitionNumber);
2438 RtlCreateUnicodeString(&DestinationRootPath,
2439 PathBuffer);
2440 DPRINT("DestinationRootPath: %wZ\n", &DestinationRootPath);
2441
2442 if (FileSystemList->Selected->FormatFunc)
2443 {
2444 Status = FormatPartition(&DestinationRootPath,
2445 FileSystemList->Selected);
2446 if (!NT_SUCCESS(Status))
2447 {
2448 DPRINT1("FormatPartition() failed with status 0x%08lx\n", Status);
2449 /* FIXME: show an error dialog */
2450 return QUIT_PAGE;
2451 }
2452
2453 PartEntry->New = FALSE;
2454
2455 CheckActiveBootPartition(PartitionList);
2456 }
2457
2458 #ifndef NDEBUG
2459 CONSOLE_SetStatusText(" Done. Press any key ...");
2460 CONSOLE_ConInKey(Ir);
2461 #endif
2462
2463 DestroyFileSystemList(FileSystemList);
2464 FileSystemList = NULL;
2465 return INSTALL_DIRECTORY_PAGE;
2466 }
2467 }
2468
2469 return FORMAT_PARTITION_PAGE;
2470 }
2471
2472
2473 static ULONG
2474 CheckFileSystemPage(PINPUT_RECORD Ir)
2475 {
2476 PFILE_SYSTEM_ITEM CurrentFileSystem;
2477 WCHAR PathBuffer[MAX_PATH];
2478 CHAR Buffer[MAX_PATH];
2479 NTSTATUS Status;
2480 UCHAR PartNum = PartitionList->CurrentPartitionNumber;
2481
2482 /* FIXME: code duplicated in FormatPartitionPage */
2483 /* Set DestinationRootPath */
2484 RtlFreeUnicodeString(&DestinationRootPath);
2485 swprintf(PathBuffer,
2486 L"\\Device\\Harddisk%lu\\Partition%lu",
2487 PartitionList->CurrentDisk->DiskNumber,
2488 PartitionList->CurrentPartition->PartInfo[PartNum].PartitionNumber);
2489 RtlCreateUnicodeString(&DestinationRootPath, PathBuffer);
2490 DPRINT("DestinationRootPath: %wZ\n", &DestinationRootPath);
2491
2492 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHECKINGPART));
2493
2494 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
2495
2496 /* WRONG: first filesystem is not necesseraly the one of the current partition! */
2497 CurrentFileSystem = CONTAINING_RECORD(FileSystemList->ListHead.Flink, FILE_SYSTEM_ITEM, ListEntry);
2498
2499 if (!CurrentFileSystem->ChkdskFunc)
2500 {
2501 sprintf(Buffer,
2502 "Setup is currently unable to check a partition formatted in %S.\n"
2503 "\n"
2504 " \x07 Press ENTER to continue Setup.\n"
2505 " \x07 Press F3 to quit Setup.",
2506 CurrentFileSystem->FileSystem);
2507
2508 PopupError(Buffer,
2509 MUIGetString(STRING_QUITCONTINUE),
2510 NULL, POPUP_WAIT_NONE);
2511
2512 while (TRUE)
2513 {
2514 CONSOLE_ConInKey(Ir);
2515
2516 if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x00 &&
2517 Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3) /* F3 */
2518 {
2519 if (ConfirmQuit(Ir))
2520 return QUIT_PAGE;
2521 else
2522 return CHECK_FILE_SYSTEM_PAGE;
2523 }
2524 else if (Ir->Event.KeyEvent.uChar.AsciiChar == VK_RETURN) /* ENTER */
2525 {
2526 return INSTALL_DIRECTORY_PAGE;
2527 }
2528 }
2529 }
2530 else
2531 {
2532 Status = ChkdskPartition(&DestinationRootPath, CurrentFileSystem);
2533 if (!NT_SUCCESS(Status))
2534 {
2535 DPRINT("ChkdskPartition() failed with status 0x%08lx\n", Status);
2536 sprintf(Buffer, "Setup failed to verify the selected partition.\n"
2537 "(Status 0x%08lx).\n", Status);
2538
2539 PopupError(Buffer,
2540 MUIGetString(STRING_REBOOTCOMPUTER),
2541 Ir, POPUP_WAIT_ENTER);
2542
2543 return QUIT_PAGE;
2544 }
2545
2546 return INSTALL_DIRECTORY_PAGE;
2547 }
2548 }
2549
2550
2551 static PAGE_NUMBER
2552 InstallDirectoryPage1(PWCHAR InstallDir,
2553 PDISKENTRY DiskEntry,
2554 PPARTENTRY PartEntry,
2555 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 ULONG Length;
2598
2599 if (PartitionList == NULL ||
2600 PartitionList->CurrentDisk == NULL ||
2601 PartitionList->CurrentPartition == NULL)
2602 {
2603 /* FIXME: show an error dialog */
2604 return QUIT_PAGE;
2605 }
2606
2607 DiskEntry = PartitionList->CurrentDisk;
2608 PartEntry = PartitionList->CurrentPartition;
2609
2610 if (IsUnattendedSetup)
2611 wcscpy(InstallDir, UnattendInstallationDirectory);
2612 else
2613 wcscpy(InstallDir, L"\\ReactOS");
2614
2615 Length = wcslen(InstallDir);
2616 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
2617 MUIDisplayPage(INSTALL_DIRECTORY_PAGE);
2618
2619 if (IsUnattendedSetup)
2620 {
2621 return InstallDirectoryPage1(InstallDir,
2622 DiskEntry,
2623 PartEntry,
2624 PartitionList->CurrentPartitionNumber);
2625 }
2626
2627 while (TRUE)
2628 {
2629 CONSOLE_ConInKey(Ir);
2630
2631 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
2632 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
2633 {
2634 if (ConfirmQuit(Ir) == TRUE)
2635 return QUIT_PAGE;
2636
2637 break;
2638 }
2639 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
2640 {
2641 return InstallDirectoryPage1(InstallDir,
2642 DiskEntry,
2643 PartEntry,
2644 PartitionList->CurrentPartitionNumber);
2645 }
2646 else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x08) /* BACKSPACE */
2647 {
2648 if (Length > 0)
2649 {
2650 Length--;
2651 InstallDir[Length] = 0;
2652 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
2653 }
2654 }
2655 else if (isprint(Ir->Event.KeyEvent.uChar.AsciiChar))
2656 {
2657 if (Length < 50)
2658 {
2659 InstallDir[Length] = (WCHAR)Ir->Event.KeyEvent.uChar.AsciiChar;
2660 Length++;
2661 InstallDir[Length] = 0;
2662 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
2663 }
2664 }
2665 }
2666
2667 return INSTALL_DIRECTORY_PAGE;
2668 }
2669
2670
2671 static BOOLEAN
2672 AddSectionToCopyQueueCab(HINF InfFile,
2673 PWCHAR SectionName,
2674 PWCHAR SourceCabinet,
2675 PCUNICODE_STRING DestinationPath,
2676 PINPUT_RECORD Ir)
2677 {
2678 INFCONTEXT FilesContext;
2679 INFCONTEXT DirContext;
2680 PWCHAR FileKeyName;
2681 PWCHAR FileKeyValue;
2682 PWCHAR DirKeyValue;
2683 PWCHAR TargetFileName;
2684
2685 /* Search for the SectionName section */
2686 if (!SetupFindFirstLineW(InfFile, SectionName, NULL, &FilesContext))
2687 {
2688 char Buffer[128];
2689 sprintf(Buffer, MUIGetString(STRING_TXTSETUPFAILED), SectionName);
2690 PopupError(Buffer, MUIGetString(STRING_REBOOTCOMPUTER), Ir, POPUP_WAIT_ENTER);
2691 return FALSE;
2692 }
2693
2694 /*
2695 * Enumerate the files in the section
2696 * and add them to the file queue.
2697 */
2698 do
2699 {
2700 /* Get source file name and target directory id */
2701 if (!INF_GetData(&FilesContext, &FileKeyName, &FileKeyValue))
2702 {
2703 /* FIXME: Handle error! */
2704 DPRINT1("INF_GetData() failed\n");
2705 break;
2706 }
2707
2708 /* Get optional target file name */
2709 if (!INF_GetDataField(&FilesContext, 2, &TargetFileName))
2710 TargetFileName = NULL;
2711
2712 DPRINT("FileKeyName: '%S' FileKeyValue: '%S'\n", FileKeyName, FileKeyValue);
2713
2714 /* Lookup target directory */
2715 if (!SetupFindFirstLineW(InfFile, L"Directories", FileKeyValue, &DirContext))
2716 {
2717 /* FIXME: Handle error! */
2718 DPRINT1("SetupFindFirstLine() failed\n");
2719 break;
2720 }
2721
2722 if (!INF_GetData(&DirContext, NULL, &DirKeyValue))
2723 {
2724 /* FIXME: Handle error! */
2725 DPRINT1("INF_GetData() failed\n");
2726 break;
2727 }
2728
2729 if (!SetupQueueCopy(SetupFileQueue,
2730 SourceCabinet,
2731 SourceRootPath.Buffer,
2732 SourceRootDir.Buffer,
2733 FileKeyName,
2734 DirKeyValue,
2735 TargetFileName))
2736 {
2737 /* FIXME: Handle error! */
2738 DPRINT1("SetupQueueCopy() failed\n");
2739 }
2740 } while (SetupFindNextLine(&FilesContext, &FilesContext));
2741
2742 return TRUE;
2743 }
2744
2745
2746 static BOOLEAN
2747 AddSectionToCopyQueue(HINF InfFile,
2748 PWCHAR SectionName,
2749 PWCHAR SourceCabinet,
2750 PCUNICODE_STRING DestinationPath,
2751 PINPUT_RECORD Ir)
2752 {
2753 INFCONTEXT FilesContext;
2754 INFCONTEXT DirContext;
2755 PWCHAR FileKeyName;
2756 PWCHAR FileKeyValue;
2757 PWCHAR DirKeyValue;
2758 PWCHAR TargetFileName;
2759 WCHAR CompleteOrigFileName[512];
2760
2761 if (SourceCabinet)
2762 return AddSectionToCopyQueueCab(InfFile, L"SourceFiles", SourceCabinet, DestinationPath, Ir);
2763
2764 /* Search for the SectionName section */
2765 if (!SetupFindFirstLineW(InfFile, SectionName, NULL, &FilesContext))
2766 {
2767 char Buffer[128];
2768 sprintf(Buffer, MUIGetString(STRING_TXTSETUPFAILED), SectionName);
2769 PopupError(Buffer, MUIGetString(STRING_REBOOTCOMPUTER), Ir, POPUP_WAIT_ENTER);
2770 return FALSE;
2771 }
2772
2773 /*
2774 * Enumerate the files in the section
2775 * and add them to the file queue.
2776 */
2777 do
2778 {
2779 /* Get source file name and target directory id */
2780 if (!INF_GetData(&FilesContext, &FileKeyName, &FileKeyValue))
2781 {
2782 /* FIXME: Handle error! */
2783 DPRINT1("INF_GetData() failed\n");
2784 break;
2785 }
2786
2787 /* Get target directory id */
2788 if (!INF_GetDataField(&FilesContext, 13, &FileKeyValue))
2789 {
2790 /* FIXME: Handle error! */
2791 DPRINT1("INF_GetData() failed\n");
2792 break;
2793 }
2794
2795 /* Get optional target file name */
2796 if (!INF_GetDataField(&FilesContext, 11, &TargetFileName))
2797 TargetFileName = NULL;
2798 else if (!*TargetFileName)
2799 TargetFileName = NULL;
2800
2801 DPRINT("FileKeyName: '%S' FileKeyValue: '%S'\n", FileKeyName, FileKeyValue);
2802
2803 /* Lookup target directory */
2804 if (!SetupFindFirstLineW(InfFile, L"Directories", FileKeyValue, &DirContext))
2805 {
2806 /* FIXME: Handle error! */
2807 DPRINT1("SetupFindFirstLine() failed\n");
2808 break;
2809 }
2810
2811 if (!INF_GetData(&DirContext, NULL, &DirKeyValue))
2812 {
2813 /* FIXME: Handle error! */
2814 DPRINT1("INF_GetData() failed\n");
2815 break;
2816 }
2817
2818 wcscpy(CompleteOrigFileName, SourceRootDir.Buffer);
2819 wcscat(CompleteOrigFileName, L"\\");
2820 wcscat(CompleteOrigFileName, DirKeyValue);
2821
2822 if (!SetupQueueCopy(SetupFileQueue,
2823 SourceCabinet,
2824 SourceRootPath.Buffer,
2825 CompleteOrigFileName,
2826 FileKeyName,
2827 DirKeyValue,
2828 TargetFileName))
2829 {
2830 /* FIXME: Handle error! */
2831 DPRINT1("SetupQueueCopy() failed\n");
2832 }
2833 } while (SetupFindNextLine(&FilesContext, &FilesContext));
2834
2835 return TRUE;
2836 }
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
2950 static PAGE_NUMBER
2951 PrepareCopyPage(PINPUT_RECORD Ir)
2952 {
2953 HINF InfHandle;
2954 WCHAR PathBuffer[MAX_PATH];
2955 INFCONTEXT CabinetsContext;
2956 ULONG InfFileSize;
2957 PWCHAR KeyValue;
2958 UINT ErrorLine;
2959 PVOID InfFileData;
2960
2961 MUIDisplayPage(PREPARE_COPY_PAGE);
2962
2963 /* Create the file queue */
2964 SetupFileQueue = SetupOpenFileQueue();
2965 if (SetupFileQueue == NULL)
2966 {
2967 MUIDisplayError(ERROR_COPY_QUEUE, Ir, POPUP_WAIT_ENTER);
2968 return(QUIT_PAGE);
2969 }
2970
2971 if (!PrepareCopyPageInfFile(SetupInf, NULL, Ir))
2972 {
2973 return QUIT_PAGE;
2974 }
2975
2976 /* Search for the 'Cabinets' section */
2977 if (!SetupFindFirstLineW(SetupInf, L"Cabinets", NULL, &CabinetsContext))
2978 {
2979 return FILE_COPY_PAGE;
2980 }
2981
2982 /*
2983 * Enumerate the directory values in the 'Cabinets'
2984 * section and parse their inf files.
2985 */
2986 do
2987 {
2988 if (!INF_GetData(&CabinetsContext, NULL, &KeyValue))
2989 break;
2990
2991 wcscpy(PathBuffer, SourcePath.Buffer);
2992 wcscat(PathBuffer, L"\\");
2993 wcscat(PathBuffer, KeyValue);
2994
2995 #ifdef __REACTOS__
2996 CabinetInitialize();
2997 CabinetSetEventHandlers(NULL, NULL, NULL);
2998 CabinetSetCabinetName(PathBuffer);
2999
3000 if (CabinetOpen() == CAB_STATUS_SUCCESS)
3001 {
3002 DPRINT("Cabinet %S\n", CabinetGetCabinetName());
3003
3004 InfFileData = CabinetGetCabinetReservedArea(&InfFileSize);
3005 if (InfFileData == NULL)
3006 {
3007 MUIDisplayError(ERROR_CABINET_SCRIPT, Ir, POPUP_WAIT_ENTER);
3008 return QUIT_PAGE;
3009 }
3010 }
3011 else
3012 {
3013 DPRINT("Cannot open cabinet: %S.\n", CabinetGetCabinetName());
3014 MUIDisplayError(ERROR_CABINET_MISSING, Ir, POPUP_WAIT_ENTER);
3015 return QUIT_PAGE;
3016 }
3017
3018 InfHandle = INF_OpenBufferedFileA((CHAR*) InfFileData,
3019 InfFileSize,
3020 (const CHAR*) NULL,
3021 INF_STYLE_WIN4,
3022 LanguageId,
3023 &ErrorLine);
3024
3025 if (InfHandle == INVALID_HANDLE_VALUE)
3026 {
3027 MUIDisplayError(ERROR_INVALID_CABINET_INF, Ir, POPUP_WAIT_ENTER);
3028 return QUIT_PAGE;
3029 }
3030
3031 CabinetCleanup();
3032
3033 if (!PrepareCopyPageInfFile(InfHandle, KeyValue, Ir))
3034 {
3035 return QUIT_PAGE;
3036 }
3037 #endif
3038 } while (SetupFindNextLine(&CabinetsContext, &CabinetsContext));
3039
3040 return FILE_COPY_PAGE;
3041 }
3042
3043
3044 VOID
3045 NTAPI
3046 SetupUpdateMemoryInfo(IN PCOPYCONTEXT CopyContext,
3047 IN BOOLEAN First)
3048 {
3049 SYSTEM_PERFORMANCE_INFORMATION PerfInfo;
3050
3051 /* Get the memory information from the system */
3052 NtQuerySystemInformation(SystemPerformanceInformation,
3053 &PerfInfo,
3054 sizeof(PerfInfo),
3055 NULL);
3056
3057 /* Check if this is initial setup */
3058 if (First)
3059 {
3060 /* Set maximum limits to be total RAM pages */
3061 ProgressSetStepCount(CopyContext->MemoryBars[0], PerfInfo.CommitLimit);
3062 ProgressSetStepCount(CopyContext->MemoryBars[1], PerfInfo.CommitLimit);
3063 ProgressSetStepCount(CopyContext->MemoryBars[2], PerfInfo.CommitLimit);
3064 }
3065
3066 /* Set current values */
3067 ProgressSetStep(CopyContext->MemoryBars[0], PerfInfo.PagedPoolPages + PerfInfo.NonPagedPoolPages);
3068 ProgressSetStep(CopyContext->MemoryBars[1], PerfInfo.ResidentSystemCachePage);
3069 ProgressSetStep(CopyContext->MemoryBars[2], PerfInfo.AvailablePages);
3070 }
3071
3072
3073 static UINT
3074 CALLBACK
3075 FileCopyCallback(PVOID Context,
3076 UINT Notification,
3077 UINT_PTR Param1,
3078 UINT_PTR Param2)
3079 {
3080 PCOPYCONTEXT CopyContext;
3081
3082 CopyContext = (PCOPYCONTEXT)Context;
3083
3084 switch (Notification)
3085 {
3086 case SPFILENOTIFY_STARTSUBQUEUE:
3087 CopyContext->TotalOperations = (ULONG)Param2;
3088 ProgressSetStepCount(CopyContext->ProgressBar,
3089 CopyContext->TotalOperations);
3090 SetupUpdateMemoryInfo(CopyContext, TRUE);
3091 break;
3092
3093 case SPFILENOTIFY_STARTCOPY:
3094 /* Display copy message */
3095 CONSOLE_SetStatusText(MUIGetString(STRING_COPYING), (PWSTR)Param1);
3096 SetupUpdateMemoryInfo(CopyContext, FALSE);
3097 break;
3098
3099 case SPFILENOTIFY_ENDCOPY:
3100 CopyContext->CompletedOperations++;
3101
3102 /* SYSREG checkpoint */
3103 if (CopyContext->TotalOperations >> 1 == CopyContext->CompletedOperations)
3104 DPRINT1("CHECKPOINT:HALF_COPIED\n");
3105
3106 ProgressNextStep(CopyContext->ProgressBar);
3107 SetupUpdateMemoryInfo(CopyContext, FALSE);
3108 break;
3109 }
3110
3111 return 0;
3112 }
3113
3114
3115 static
3116 PAGE_NUMBER
3117 FileCopyPage(PINPUT_RECORD Ir)
3118 {
3119 COPYCONTEXT CopyContext;
3120 unsigned int mem_bar_width;
3121
3122 MUIDisplayPage(FILE_COPY_PAGE);
3123
3124 /* Create context for the copy process */
3125 CopyContext.DestinationRootPath = DestinationRootPath.Buffer;
3126 CopyContext.InstallPath = InstallPath.Buffer;
3127 CopyContext.TotalOperations = 0;
3128 CopyContext.CompletedOperations = 0;
3129
3130 /* Create the progress bar as well */
3131 CopyContext.ProgressBar = CreateProgressBar(13,
3132 26,
3133 xScreen - 13,
3134 yScreen - 20,
3135 10,
3136 24,
3137 TRUE,
3138 MUIGetString(STRING_SETUPCOPYINGFILES));
3139
3140 // fit memory bars to screen width, distribute them uniform
3141 mem_bar_width = (xScreen - 26) / 5;
3142 mem_bar_width -= mem_bar_width % 2; // make even
3143 /* ATTENTION: The following progress bars are debug stuff, which should not be translated!! */
3144 /* Create the paged pool progress bar */
3145 CopyContext.MemoryBars[0] = CreateProgressBar(13,
3146 40,
3147 13 + mem_bar_width,
3148 43,
3149 13,
3150 44,
3151 FALSE,
3152 "Kernel Pool");
3153
3154 /* Create the non paged pool progress bar */
3155 CopyContext.MemoryBars[1] = CreateProgressBar((xScreen / 2)- (mem_bar_width / 2),
3156 40,
3157 (xScreen / 2) + (mem_bar_width / 2),
3158 43,
3159 (xScreen / 2)- (mem_bar_width / 2),
3160 44,
3161 FALSE,
3162 "Kernel Cache");
3163
3164 /* Create the global memory progress bar */
3165 CopyContext.MemoryBars[2] = CreateProgressBar(xScreen - 13 - mem_bar_width,
3166 40,
3167 xScreen - 13,
3168 43,
3169 xScreen - 13 - mem_bar_width,
3170 44,
3171 FALSE,
3172 "Free Memory");
3173
3174 /* Do the file copying */
3175 SetupCommitFileQueueW(NULL,
3176 SetupFileQueue,
3177 FileCopyCallback,
3178 &CopyContext);
3179
3180 /* If we get here, we're done, so cleanup the queue and progress bar */
3181 SetupCloseFileQueue(SetupFileQueue);
3182 DestroyProgressBar(CopyContext.ProgressBar);
3183 DestroyProgressBar(CopyContext.MemoryBars[0]);
3184 DestroyProgressBar(CopyContext.MemoryBars[1]);
3185 DestroyProgressBar(CopyContext.MemoryBars[2]);
3186
3187 /* Go display the next page */
3188 return REGISTRY_PAGE;
3189 }
3190
3191
3192 static PAGE_NUMBER
3193 RegistryPage(PINPUT_RECORD Ir)
3194 {
3195 INFCONTEXT InfContext;
3196 PWSTR Action;
3197 PWSTR File;
3198 PWSTR Section;
3199 BOOLEAN Delete;
3200 NTSTATUS Status;
3201
3202 MUIDisplayPage(REGISTRY_PAGE);
3203
3204 if (RepairUpdateFlag)
3205 {
3206 return SUCCESS_PAGE;
3207 }
3208
3209 if (!SetInstallPathValue(&DestinationPath))
3210 {
3211 DPRINT("SetInstallPathValue() failed\n");
3212 MUIDisplayError(ERROR_INITIALIZE_REGISTRY, Ir, POPUP_WAIT_ENTER);
3213 return QUIT_PAGE;
3214 }
3215
3216 /* Create the default hives */
3217 #ifdef __REACTOS__
3218 Status = NtInitializeRegistry(CM_BOOT_FLAG_SETUP);
3219 if (!NT_SUCCESS(Status))
3220 {
3221 DPRINT("NtInitializeRegistry() failed (Status %lx)\n", Status);
3222 MUIDisplayError(ERROR_CREATE_HIVE, Ir, POPUP_WAIT_ENTER);
3223 return QUIT_PAGE;
3224 }
3225 #else
3226 RegInitializeRegistry();
3227 #endif
3228
3229 /* Update registry */
3230 CONSOLE_SetStatusText(MUIGetString(STRING_REGHIVEUPDATE));
3231
3232 if (!SetupFindFirstLineW(SetupInf, L"HiveInfs.Install", NULL, &InfContext))
3233 {
3234 DPRINT1("SetupFindFirstLine() failed\n");
3235 MUIDisplayError(ERROR_FIND_REGISTRY, Ir, POPUP_WAIT_ENTER);
3236 return QUIT_PAGE;
3237 }
3238
3239 do
3240 {
3241 INF_GetDataField (&InfContext, 0, &Action);
3242 INF_GetDataField (&InfContext, 1, &File);
3243 INF_GetDataField (&InfContext, 2, &Section);
3244
3245 DPRINT("Action: %S File: %S Section %S\n", Action, File, Section);