ReactOS 0.4.16-dev-1521-gb8f1da6
setupldr.c
Go to the documentation of this file.
1/*
2 * PROJECT: FreeLoader
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Windows-compatible NT OS Setup Loader.
5 * COPYRIGHT: Copyright 2009-2019 Aleksey Bragin <aleksey@reactos.org>
6 */
7
8#include <freeldr.h>
9#include <ndk/ldrtypes.h>
10#include <arc/setupblk.h>
11#include "winldr.h"
12#include "inffile.h"
13#include "ntldropts.h"
14
15#include <debug.h>
17
18/* Architecture name suffixes for architecture-specific INF sections */
19#if defined(_M_IX86)
20#define INF_ARCH "x86"
21#elif defined(_M_AMD64)
22#define INF_ARCH "amd64"
23#elif defined(_M_ARM)
24#define INF_ARCH "arm"
25#elif defined(_M_ARM64)
26#define INF_ARCH "arm64"
27#endif
28
29// TODO: Move to .h
30VOID
32 IN USHORT VersionToBoot,
33 OUT PLOADER_PARAMETER_BLOCK* OutLoaderBlock);
34
35static VOID
38 _In_ HINF InfHandle,
40{
42 INFCONTEXT InfContext;
43 PCSTR AnsiData;
44 UNICODE_STRING AnsiFileName = {0};
45 UNICODE_STRING OemFileName = {0};
46 UNICODE_STRING LangFileName = {0}; // CaseTable
47 UNICODE_STRING OemHalFileName = {0};
48
49 /* Get ANSI codepage file */
50 if (!InfFindFirstLine(InfHandle, "NLS", "AnsiCodepage", &InfContext) ||
51 !InfGetDataField(&InfContext, 1, &AnsiData) ||
52 !RtlCreateUnicodeStringFromAsciiz(&AnsiFileName, AnsiData))
53 {
54 ERR("Failed to find or get 'NLS/AnsiCodepage'\n");
55 return;
56 }
57
58 /* Get OEM codepage file */
59 if (!InfFindFirstLine(InfHandle, "NLS", "OemCodepage", &InfContext) ||
60 !InfGetDataField(&InfContext, 1, &AnsiData) ||
61 !RtlCreateUnicodeStringFromAsciiz(&OemFileName, AnsiData))
62 {
63 ERR("Failed to find or get 'NLS/OemCodepage'\n");
64 goto Quit;
65 }
66
67 /* Get the Unicode case table file */
68 if (!InfFindFirstLine(InfHandle, "NLS", "UnicodeCasetable", &InfContext) ||
69 !InfGetDataField(&InfContext, 1, &AnsiData) ||
70 !RtlCreateUnicodeStringFromAsciiz(&LangFileName, AnsiData))
71 {
72 ERR("Failed to find or get 'NLS/UnicodeCasetable'\n");
73 goto Quit;
74 }
75
76 /* Get OEM HAL font file */
77 if (!InfFindFirstLine(InfHandle, "NLS", "OemHalFont", &InfContext) ||
78 !InfGetData(&InfContext, NULL, &AnsiData) ||
79 !RtlCreateUnicodeStringFromAsciiz(&OemHalFileName, AnsiData))
80 {
81 WARN("Failed to find or get 'NLS/OemHalFont'\n");
82 /* Ignore, this is an optional file */
83 RtlInitEmptyUnicodeString(&OemHalFileName, NULL, 0);
84 }
85
86 TRACE("NLS data: '%wZ' '%wZ' '%wZ' '%wZ'\n",
87 &AnsiFileName, &OemFileName, &LangFileName, &OemHalFileName);
88
89 /* Load NLS data */
90 Success = WinLdrLoadNLSData(LoaderBlock,
92 &AnsiFileName,
93 &OemFileName,
94 &LangFileName,
95 &OemHalFileName);
96 TRACE("NLS data loading %s\n", Success ? "successful" : "failed");
98
99Quit:
100 RtlFreeUnicodeString(&OemHalFileName);
101 RtlFreeUnicodeString(&LangFileName);
102 RtlFreeUnicodeString(&OemFileName);
103 RtlFreeUnicodeString(&AnsiFileName);
104}
105
106static
109 IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
110 IN HINF InfHandle,
112{
113 INFCONTEXT InfContext;
116 PVOID PhysicalBase;
117 CHAR ErrataFilePath[MAX_PATH];
118
119 /* Retrieve the INF file name value */
120 if (!InfFindFirstLine(InfHandle, "BiosInfo", "InfName", &InfContext))
121 {
122 WARN("Failed to find 'BiosInfo/InfName'\n");
123 return FALSE;
124 }
125 if (!InfGetDataField(&InfContext, 1, &FileName))
126 {
127 WARN("Failed to read 'InfName' value\n");
128 return FALSE;
129 }
130
131 RtlStringCbCopyA(ErrataFilePath, sizeof(ErrataFilePath), SystemRoot);
132 RtlStringCbCatA(ErrataFilePath, sizeof(ErrataFilePath), FileName);
133
134 /* Load the INF file */
135 PhysicalBase = WinLdrLoadModule(ErrataFilePath, &FileSize, LoaderRegistryData);
136 if (!PhysicalBase)
137 {
138 WARN("Could not load '%s'\n", ErrataFilePath);
139 return FALSE;
140 }
141
142 LoaderBlock->Extension->EmInfFileImage = PaToVa(PhysicalBase);
143 LoaderBlock->Extension->EmInfFileSize = FileSize;
144
145 return TRUE;
146}
147
148static VOID
150 _Inout_ PLIST_ENTRY BootDriverListHead,
151 _In_ HINF InfHandle,
153{
154 INFCONTEXT InfContext, dirContext;
155 PCSTR Media, DriverName, dirIndex, ImagePath;
157 UINT8 Pass;
158 WCHAR ImagePathW[MAX_PATH];
159 WCHAR DriverNameW[256];
160
162
163 /* Open the INF section, first the optional platform-specific one,
164 * then the generic section */
165 for (Pass = 0; Pass <= 1; ++Pass)
166 {
167 PCSTR pFilesSection[] = {"SourceDisksFiles." INF_ARCH, "SourceDisksFiles"};
168
169 if (!InfFindFirstLine(InfHandle, pFilesSection[Pass], NULL, &InfContext))
170 continue;
171
172 /* Load all listed boot drivers */
173 do
174 {
175 if (InfGetDataField(&InfContext, 7, &Media) &&
176 InfGetDataField(&InfContext, 0, &DriverName) &&
177 InfGetDataField(&InfContext, 13, &dirIndex))
178 {
179 if ((strcmp(Media, "x") == 0) && // HACK: ReactOS-specific
180 InfFindFirstLine(InfHandle, "Directories", dirIndex, &dirContext) &&
181 InfGetDataField(&dirContext, 1, &ImagePath))
182 {
183 /* Prepare image path */
184 RtlStringCbPrintfW(ImagePathW, sizeof(ImagePathW),
185 L"%S\\%S", ImagePath, DriverName);
186
187 /* Convert name to Unicode and remove .sys extension */
188 RtlStringCbPrintfW(DriverNameW, sizeof(DriverNameW),
189 L"%S", DriverName);
190 DriverNameW[wcslen(DriverNameW) - 4] = UNICODE_NULL;
191
192 /* Add it to the list */
193 Success = WinLdrAddDriverToList(BootDriverListHead,
194 FALSE,
195 DriverNameW,
196 ImagePathW,
197 NULL,
199 -1);
200 if (!Success)
201 {
202 ERR("Could not add boot driver '%s'\n", DriverName);
203 /* Ignore and continue adding other drivers */
204 }
205 }
206 }
207 } while (InfFindNextLine(&InfContext, &InfContext));
208 } // for (Pass...)
209
210 /* Finally, add the boot filesystem driver to the list */
211 if (BootFileSystem)
212 {
213 TRACE("Adding filesystem driver %S\n", BootFileSystem);
214 Success = WinLdrAddDriverToList(BootDriverListHead,
215 FALSE,
217 NULL,
218 L"Boot File System",
220 -1);
221 if (!Success)
222 ERR("Failed to add filesystem driver %S\n", BootFileSystem);
223 }
224 else
225 {
226 TRACE("No required filesystem driver\n");
227 }
228}
229
230
231/* SETUP STARTER **************************************************************/
232
233/*
234 * Update the options in the buffer pointed by LoadOptions, of maximum size
235 * BufferSize, by first removing any specified options, and then adding any
236 * other ones.
237 *
238 * OptionsToAdd is a NULL-terminated array of string buffer pointers that
239 * specify the options to be added into LoadOptions. Whether they are
240 * prepended or appended to LoadOptions is controlled via the Append
241 * parameter. The options are added in the order specified by the array.
242 *
243 * OptionsToRemove is a NULL-terminated array of string buffer pointers that
244 * specify the options to remove from LoadOptions. Specifying also there
245 * any options to add, has the effect of removing from LoadOptions any
246 * duplicates of the options to be added, before adding them later into
247 * LoadOptions. The options are removed in the order specified by the array.
248 *
249 * The options string buffers in the OptionsToRemove array have the format:
250 * "/option1 /option2[=] ..."
251 *
252 * An option in the OptionsToRemove list with a trailing '=' or ':' designates
253 * an option in LoadOptions with user-specific data appended after the sign.
254 * When such an option is being removed from LoadOptions, all the appended
255 * data is also removed until the next option.
256 */
257VOID
259 IN OUT PSTR LoadOptions,
261 IN BOOLEAN Append,
262 IN PCSTR OptionsToAdd[] OPTIONAL,
263 IN PCSTR OptionsToRemove[] OPTIONAL)
264{
265 PCSTR NextOptions, NextOpt;
266 PSTR Options, Option;
267 ULONG NextOptLength;
268 ULONG OptionLength;
269
270 if (!LoadOptions || (BufferSize == 0))
271 return;
272 // ASSERT(strlen(LoadOptions) + 1 <= BufferSize);
273
274 /* Loop over the options to remove */
275 for (; OptionsToRemove && *OptionsToRemove; ++OptionsToRemove)
276 {
277 NextOptions = *OptionsToRemove;
278 while ((NextOpt = NtLdrGetNextOption(&NextOptions, &NextOptLength)))
279 {
280 /* Scan the load options */
281 Options = LoadOptions;
282 while ((Option = (PSTR)NtLdrGetNextOption((PCSTR*)&Options, &OptionLength)))
283 {
284 /*
285 * Check whether the option to find exactly matches the current
286 * load option, or is a prefix thereof if this is an option with
287 * appended data.
288 */
289 if ((OptionLength >= NextOptLength) &&
290 (_strnicmp(Option, NextOpt, NextOptLength) == 0))
291 {
292 if ((OptionLength == NextOptLength) ||
293 (NextOpt[NextOptLength-1] == '=') ||
294 (NextOpt[NextOptLength-1] == ':'))
295 {
296 /* Eat any skipped option or whitespace separators */
297 while ((Option > LoadOptions) &&
298 (Option[-1] == '/' ||
299 Option[-1] == ' ' ||
300 Option[-1] == '\t'))
301 {
302 --Option;
303 }
304
305 /* If the option was not preceded by a whitespace
306 * separator, insert one and advance the pointer. */
307 if ((Option > LoadOptions) &&
308 (Option[-1] != ' ') &&
309 (Option[-1] != '\t') &&
310 (*Options != '\0') /* &&
311 ** Not necessary since NtLdrGetNextOption() **
312 ** stripped any leading separators. **
313 (*Options != ' ') &&
314 (*Options != '\t') */)
315 {
316 *Option++ = ' ';
317 }
318
319 /* Move the remaining options back, erasing the current one */
320 ASSERT(Option <= Options);
321 RtlMoveMemory(Option,
322 Options,
323 (strlen(Options) + 1) * sizeof(CHAR));
324
325 /* Reset the iterator */
326 Options = Option;
327 }
328 }
329 }
330 }
331 }
332
333 /* Now loop over the options to add */
334 for (; OptionsToAdd && *OptionsToAdd; ++OptionsToAdd)
335 {
336 NtLdrAddOptions(LoadOptions,
338 Append,
339 *OptionsToAdd);
340 }
341}
342
343
344/*
345 * List of options and their corresponding higher priority ones,
346 * that are either checked before any other ones, or whose name
347 * includes another option name as a subset (e.g. NODEBUG vs. DEBUG).
348 * See also https://geoffchappell.com/notes/windows/boot/editoptions.htm
349 */
350static const struct
351{
356{
357 /* NODEBUG has a higher precedence than DEBUG */
358 {"/DEBUG/DEBUG=", NULL, "/NODEBUG"},
359
360 /* When using SCREEN debug port, we need boot video */
361 {"/DEBUGPORT=SCREEN", NULL, "/NOGUIBOOT"},
362
363 /* DETECTHAL has a higher precedence than HAL= or KERNEL= */
364 {"/HAL=/KERNEL=", NULL, "/DETECTHAL"},
365
366 /* NOPAE has a higher precedence than PAE */
367 {"/PAE", NULL, "/NOPAE"},
368
369 /* NOEXECUTE(=) has a higher precedence than EXECUTE */
370 {"/EXECUTE", "/NOEXECUTE=ALWAYSOFF", "/NOEXECUTE/NOEXECUTE="},
371 /* NOEXECUTE(=) options are self-excluding and
372 * some have higher precedence than others. */
373 {"/NOEXECUTE/NOEXECUTE=", NULL, "/NOEXECUTE/NOEXECUTE="},
374
375 /* SAFEBOOT(:) options are self-excluding */
376 {"/SAFEBOOT/SAFEBOOT:", NULL, "/SAFEBOOT/SAFEBOOT:"},
378
379#define TAG_BOOT_OPTIONS 'pOtB'
380
381VOID
385 OUT PSTR* HigherPriorityOptions)
386{
387 ULONG i;
388 PCSTR NextOptions, NextOpt;
389 ULONG NextOptLength;
390 SIZE_T ExtraOptsSize = 0;
391 SIZE_T HighPriorOptsSize = 0;
392
393 /* Masks specifying the presence (TRUE) or absence (FALSE) of the options */
395
396 /* Just return if we cannot return anything */
397 if (!ExtraOptions && !HigherPriorityOptions)
398 return;
399
400 if (ExtraOptions)
402 if (HigherPriorityOptions)
403 *HigherPriorityOptions = NULL;
404
405 /* Just return if no initial options were given */
406 if (!BootOptions || !*BootOptions)
407 return;
408
409 /* Determine the presence of the colliding options, and the
410 * maximum necessary sizes for the pointers to be allocated. */
411 RtlZeroMemory(Masks, sizeof(Masks));
412 for (i = 0; i < RTL_NUMBER_OF(HighPriorOptionsMap); ++i)
413 {
414 /* Loop over the given options to search for */
415 NextOptions = HighPriorOptionsMap[i].Options;
416 while ((NextOpt = NtLdrGetNextOption(&NextOptions, &NextOptLength)))
417 {
418 /* If any of these options are present... */
419 if (NtLdrGetOptionExN(BootOptions, NextOpt, NextOptLength, NULL))
420 {
421 /* ... set the mask, retrieve the sizes and stop looking for these options */
422 Masks[i] = TRUE;
424 {
425 ExtraOptsSize += strlen(HighPriorOptionsMap[i].ExtraOptions) * sizeof(CHAR);
426 }
427 if (HigherPriorityOptions && HighPriorOptionsMap[i].HigherPriorOptions)
428 {
429 HighPriorOptsSize += strlen(HighPriorOptionsMap[i].HigherPriorOptions) * sizeof(CHAR);
430 }
431 break;
432 }
433 }
434 }
435 /* Count the NULL-terminator */
436 if (ExtraOptions)
437 ExtraOptsSize += sizeof(ANSI_NULL);
438 if (HigherPriorityOptions)
439 HighPriorOptsSize += sizeof(ANSI_NULL);
440
441 /* Allocate the string pointers */
442 if (ExtraOptions)
443 {
445 if (!*ExtraOptions)
446 return;
447 }
448 if (HigherPriorityOptions)
449 {
450 *HigherPriorityOptions = FrLdrHeapAlloc(HighPriorOptsSize, TAG_BOOT_OPTIONS);
451 if (!*HigherPriorityOptions)
452 {
453 if (ExtraOptions)
454 {
457 }
458 return;
459 }
460 }
461
462 /* Initialize the strings */
463 if (ExtraOptions)
464 *(*ExtraOptions) = '\0';
465 if (HigherPriorityOptions)
466 *(*HigherPriorityOptions) = '\0';
467
468 /* Go through the masks that determine the options to check */
469 for (i = 0; i < RTL_NUMBER_OF(HighPriorOptionsMap); ++i)
470 {
471 if (Masks[i])
472 {
473 /* Retrieve the strings */
475 {
477 ExtraOptsSize,
479 }
480 if (HigherPriorityOptions && HighPriorOptionsMap[i].HigherPriorOptions)
481 {
482 RtlStringCbCatA(*HigherPriorityOptions,
483 HighPriorOptsSize,
485 }
486 }
487 }
488}
489
490
493 IN ULONG Argc,
494 IN PCHAR Argv[],
495 IN PCHAR Envp[])
496{
498 PCSTR ArgValue;
500 PCSTR SystemPath;
503 BOOLEAN BootFromFloppy;
505 HINF InfHandle;
506 INFCONTEXT InfContext;
507 ULONG i, ErrorLine;
508 PLOADER_PARAMETER_BLOCK LoaderBlock;
509 PSETUP_LOADER_BLOCK SetupBlock;
510 CHAR BootPath[MAX_PATH];
512 CHAR UserBootOptions[256];
514
515 static PCSTR SourcePaths[] =
516 {
517 "", /* Only for floppy boot */
518#if defined(_M_IX86)
519 "I386\\",
520#elif defined(_M_MPPC)
521 "PPC\\",
522#elif defined(_M_MRX000)
523 "MIPS\\",
524#endif
525 "reactos\\",
526 NULL
527 };
528
529 /* Retrieve the (mandatory) boot type */
530 ArgValue = GetArgumentValue(Argc, Argv, "BootType");
531 if (!ArgValue || !*ArgValue)
532 {
533 ERR("No 'BootType' value, aborting!\n");
534 return EINVAL;
535 }
536 if (_stricmp(ArgValue, "ReactOSSetup") != 0)
537 {
538 ERR("Unknown 'BootType' value '%s', aborting!\n", ArgValue);
539 return EINVAL;
540 }
541
542 /* Retrieve the (mandatory) system partition */
543 SystemPartition = GetArgumentValue(Argc, Argv, "SystemPartition");
545 {
546 ERR("No 'SystemPartition' specified, aborting!\n");
547 return EINVAL;
548 }
549
550 /* Let the user know we started loading */
552 UiDrawStatusText("Setup is loading...");
553 UiDrawProgressBarCenter("Loading ReactOS Setup...");
554
555 /* Retrieve the system path */
556 *BootPath = ANSI_NULL;
557 ArgValue = GetArgumentValue(Argc, Argv, "SystemPath");
558 if (ArgValue)
559 {
560 RtlStringCbCopyA(BootPath, sizeof(BootPath), ArgValue);
561 }
562 else
563 {
564 /*
565 * IMPROVE: I don't want to use the SystemPartition here as a
566 * default choice because I can do it after (see few lines below).
567 * Instead I reset BootPath here so that we can build the full path
568 * using the general code from below.
569 */
570 // RtlStringCbCopyA(BootPath, sizeof(BootPath), SystemPartition);
571 *BootPath = ANSI_NULL;
572 }
573
574 /*
575 * Check whether BootPath is a full path
576 * and if not, create a full boot path.
577 *
578 * See FsOpenFile for the technique used.
579 */
580 if (strrchr(BootPath, ')') == NULL)
581 {
582 /* Temporarily save the boot path */
583 RtlStringCbCopyA(FilePath, sizeof(FilePath), BootPath);
584
585 /* This is not a full path: prepend the SystemPartition */
586 RtlStringCbCopyA(BootPath, sizeof(BootPath), SystemPartition);
587
588 /* Append a path separator if needed */
589 if (*FilePath != '\\' && *FilePath != '/')
590 RtlStringCbCatA(BootPath, sizeof(BootPath), "\\");
591
592 /* Append the remaining path */
593 RtlStringCbCatA(BootPath, sizeof(BootPath), FilePath);
594 }
595
596 /* Append a path separator if needed */
597 if (!*BootPath || BootPath[strlen(BootPath) - 1] != '\\')
598 RtlStringCbCatA(BootPath, sizeof(BootPath), "\\");
599
600 TRACE("BootPath: '%s'\n", BootPath);
601
602 /*
603 * Retrieve the boot options. Any options present here will supplement or
604 * override those that will be specified in TXTSETUP.SIF's OsLoadOptions.
605 */
606 BootOptions = GetArgumentValue(Argc, Argv, "Options");
607 if (!BootOptions)
608 BootOptions = "";
609
610 TRACE("BootOptions: '%s'\n", BootOptions);
611
612 /* Check if a RAM disk file was given */
614 if (FileName && (FileNameLength > 7))
615 {
616 /* Load the RAM disk */
618 if (Status != ESUCCESS)
619 {
620 FileName += 7; FileNameLength -= 7;
621 UiMessageBox("Failed to load RAM disk file '%.*s'",
623 return Status;
624 }
625 }
626
627 /* Check if we booted from floppy */
628 BootFromFloppy = strstr(BootPath, "fdisk") != NULL;
629
630 /* Open 'txtsetup.sif' from any of the source paths */
631 FileName = BootPath + strlen(BootPath);
632 for (i = BootFromFloppy ? 0 : 1; ; i++)
633 {
634 SystemPath = SourcePaths[i];
635 if (!SystemPath)
636 {
637 UiMessageBox("Failed to open txtsetup.sif");
638 return ENOENT;
639 }
640 FileNameLength = (ULONG)(sizeof(BootPath) - (FileName - BootPath)*sizeof(CHAR));
642 RtlStringCbCopyA(FilePath, sizeof(FilePath), BootPath);
643 RtlStringCbCatA(FilePath, sizeof(FilePath), "txtsetup.sif");
644 if (InfOpenFile(&InfHandle, FilePath, &ErrorLine))
645 {
646 break;
647 }
648 }
649
650 TRACE("BootPath: '%s', SystemPath: '%s'\n", BootPath, SystemPath);
651
652 // UseLocalSif = NtLdrGetOption(BootOptions, "USELOCALSIF");
653
654 if (NtLdrGetOption(BootOptions, "SIFOPTIONSOVERRIDE"))
655 {
656 PCSTR OptionsToRemove[2] = {"SIFOPTIONSOVERRIDE", NULL};
657
658 /* Do not use any load options from TXTSETUP.SIF, but
659 * use instead those passed from the command line. */
660 RtlStringCbCopyA(UserBootOptions, sizeof(UserBootOptions), BootOptions);
661
662 /* Remove the private switch from the options */
663 NtLdrUpdateLoadOptions(UserBootOptions,
664 sizeof(UserBootOptions),
665 FALSE,
666 NULL,
667 OptionsToRemove);
668
669 BootOptions = UserBootOptions;
670 }
671 else // if (!*BootOptions || NtLdrGetOption(BootOptions, "SIFOPTIONSADD"))
672 {
673 PCSTR LoadOptions = NULL;
674 PCSTR DbgLoadOptions = NULL;
675 PSTR ExtraOptions, HigherPriorityOptions;
676 PSTR OptionsToAdd[3];
677 PSTR OptionsToRemove[4];
678
679 /* Load the options from TXTSETUP.SIF */
680 if (InfFindFirstLine(InfHandle, "SetupData", "OsLoadOptions", &InfContext))
681 {
682 if (!InfGetDataField(&InfContext, 1, &LoadOptions))
683 WARN("Failed to get load options\n");
684 }
685
686#if !DBG
687 /* Non-debug mode: get the debug load options only if /DEBUG was specified
688 * in the Argv command-line options (was e.g. added to the options when
689 * the user selected "Debugging Mode" in the advanced boot menu). */
690 if (NtLdrGetOption(BootOptions, "DEBUG") ||
691 NtLdrGetOption(BootOptions, "DEBUG="))
692 {
693#else
694 /* Debug mode: always get the debug load options */
695#endif
696 if (InfFindFirstLine(InfHandle, "SetupData", "SetupDebugOptions", &InfContext))
697 {
698 if (!InfGetDataField(&InfContext, 1, &DbgLoadOptions))
699 WARN("Failed to get debug load options\n");
700 }
701 /* If none was found, default to enabling debugging */
702 if (!DbgLoadOptions)
703 DbgLoadOptions = "/DEBUG";
704#if !DBG
705 }
706#endif
707
708 /* Initialize the load options with those from TXTSETUP.SIF */
709 *UserBootOptions = ANSI_NULL;
710 if (LoadOptions && *LoadOptions)
711 RtlStringCbCopyA(UserBootOptions, sizeof(UserBootOptions), LoadOptions);
712
713 /* Merge the debug load options if any */
714 if (DbgLoadOptions)
715 {
716 RtlZeroMemory(OptionsToAdd, sizeof(OptionsToAdd));
717 RtlZeroMemory(OptionsToRemove, sizeof(OptionsToRemove));
718
719 /*
720 * Retrieve any option patterns that we should remove from the
721 * SIF load options because they are of higher precedence than
722 * those specified in the debug load options to be added.
723 * Also always remove NODEBUG (even if the debug load options
724 * do not contain explicitly the DEBUG option), since we want
725 * to have debugging enabled if possible.
726 */
727 OptionsToRemove[0] = "/NODEBUG";
728 NtLdrGetHigherPriorityOptions(DbgLoadOptions,
730 &HigherPriorityOptions);
731 OptionsToAdd[1] = (ExtraOptions ? ExtraOptions : "");
732 OptionsToRemove[1] = (HigherPriorityOptions ? HigherPriorityOptions : "");
733
734 /*
735 * Prepend the debug load options, so that in case it contains
736 * redundant options with respect to the SIF load options, the
737 * former can take precedence over the latter.
738 */
739 OptionsToAdd[0] = (PSTR)DbgLoadOptions;
740 OptionsToRemove[2] = (PSTR)DbgLoadOptions;
741 NtLdrUpdateLoadOptions(UserBootOptions,
742 sizeof(UserBootOptions),
743 FALSE,
744 (PCSTR*)OptionsToAdd,
745 (PCSTR*)OptionsToRemove);
746
747 if (ExtraOptions)
749 if (HigherPriorityOptions)
750 FrLdrHeapFree(HigherPriorityOptions, TAG_BOOT_OPTIONS);
751 }
752
753 RtlZeroMemory(OptionsToAdd, sizeof(OptionsToAdd));
754 RtlZeroMemory(OptionsToRemove, sizeof(OptionsToRemove));
755
756 /*
757 * Retrieve any option patterns that we should remove from the
758 * SIF load options because they are of higher precedence than
759 * those specified in the options to be added.
760 */
763 &HigherPriorityOptions);
764 OptionsToAdd[1] = (ExtraOptions ? ExtraOptions : "");
765 OptionsToRemove[0] = (HigherPriorityOptions ? HigherPriorityOptions : "");
766
767 /* Finally, prepend the user-specified options that
768 * take precedence over those from TXTSETUP.SIF. */
769 OptionsToAdd[0] = (PSTR)BootOptions;
770 OptionsToRemove[1] = (PSTR)BootOptions;
771 NtLdrUpdateLoadOptions(UserBootOptions,
772 sizeof(UserBootOptions),
773 FALSE,
774 (PCSTR*)OptionsToAdd,
775 (PCSTR*)OptionsToRemove);
776
777 if (ExtraOptions)
779 if (HigherPriorityOptions)
780 FrLdrHeapFree(HigherPriorityOptions, TAG_BOOT_OPTIONS);
781
782 BootOptions = UserBootOptions;
783 }
784
785 TRACE("BootOptions: '%s'\n", BootOptions);
786
787 /* Handle the SOS option */
789 if (SosEnabled)
791
792 /* Allocate and minimally-initialize the Loader Parameter Block */
794
795 /* Allocate and initialize the setup loader block */
796 SetupBlock = &WinLdrSystemBlock->SetupBlock;
797 LoaderBlock->SetupLdrBlock = SetupBlock;
798
799 /* Set textmode setup flag */
800 SetupBlock->Flags = SETUPLDR_TEXT_MODE;
801
802 /* Load the "setupreg.hiv" setup system hive */
803 UiUpdateProgressBar(15, "Loading setup system hive...");
804 Success = WinLdrInitSystemHive(LoaderBlock, BootPath, TRUE);
805 TRACE("Setup SYSTEM hive %s\n", (Success ? "loaded" : "not loaded"));
806 /* Bail out if failure */
807 if (!Success)
808 return ENOEXEC;
809
810 /* Load NLS data, they are in the System32 directory of the installation medium */
811 RtlStringCbCopyA(FilePath, sizeof(FilePath), BootPath);
812 RtlStringCbCatA(FilePath, sizeof(FilePath), "system32\\");
813 SetupLdrLoadNlsData(LoaderBlock, InfHandle, FilePath);
814
815 /* Load the Firmware Errata file from the installation medium */
816 Success = SetupLdrInitErrataInf(LoaderBlock, InfHandle, BootPath);
817 TRACE("Firmware Errata file %s\n", (Success ? "loaded" : "not loaded"));
818 /* Not necessarily fatal if not found - carry on going */
819
820 // UiDrawStatusText("Press F6 if you need to install a 3rd-party SCSI or RAID driver...");
821
822 /* Get a list of boot drivers */
823 SetupLdrScanBootDrivers(&LoaderBlock->BootDriverListHead, InfHandle, BootPath);
824
825 /* Close the inf file */
826 InfCloseFile(InfHandle);
827
828 UiDrawStatusText("The Setup program is starting...");
829
830 /* Finish loading */
832 LoaderBlock,
834 BootPath);
835}
PCWSTR FilePath
unsigned char BOOLEAN
unsigned char UINT8
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
#define ENOENT
Definition: acclib.h:79
#define EINVAL
Definition: acclib.h:90
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
char * strstr(char *String1, char *String2)
Definition: utclib.c:653
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define VOID
Definition: acefi.h:82
PSTR GetArgumentValue(_In_ ULONG Argc, _In_ PCHAR Argv[], _In_ PCSTR ArgumentName)
Definition: arcsupp.c:42
PPARTENTRY SystemPartition
Definition: reactos.c:50
#define CHAR(Char)
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
@ BootOptions
Definition: bl.h:898
ARC_STATUS RamDiskInitialize(IN BOOLEAN InitRamDisk, IN PCSTR LoadOptions OPTIONAL, IN PCSTR DefaultPath OPTIONAL)
Definition: ramdisk.c:206
#define DBG_DEFAULT_CHANNEL(ch)
Definition: debug.h:106
VOID FrLdrHeapFree(PVOID MemoryPointer, ULONG Tag)
Definition: heap.c:539
PVOID FrLdrHeapAlloc(SIZE_T MemorySize, ULONG Tag)
Definition: heap.c:533
VOID UiDrawBackdrop(ULONG DrawHeight)
Definition: ui.c:233
VOID UiUpdateProgressBar(_In_ ULONG Percentage, _In_opt_ PCSTR ProgressText)
Definition: ui.c:454
ULONG UiGetScreenHeight(VOID)
Definition: ui.c:655
VOID UiDrawProgressBarCenter(_In_ PCSTR ProgressText)
Definition: ui.c:487
VOID UiDrawStatusText(PCSTR StatusText)
Definition: ui.c:286
VOID UiResetForSOS(VOID)
Definition: ui.c:639
VOID UiMessageBox(_In_ PCSTR Format,...)
Definition: ui.c:359
#define _stricmp
Definition: cat.c:22
FORCEINLINE PVOID PaToVa(PVOID Pa)
Definition: conversion.h:22
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
static const WCHAR SystemRoot[]
Definition: reg.c:38
#define _strnicmp(_String1, _String2, _MaxCount)
Definition: compat.h:23
#define MAX_PATH
Definition: compat.h:34
#define L(x)
Definition: resources.c:13
#define ENOEXEC
Definition: errno.h:14
@ Success
Definition: eventcreate.c:712
struct _FileName FileName
Definition: fatprocs.h:897
_Must_inspect_result_ _In_ PFILE_OBJECT _In_opt_ HANDLE _In_ ULONG FileNameLength
Definition: fltkernel.h:1129
_Must_inspect_result_ _Out_ PLARGE_INTEGER FileSize
Definition: fsrtlfuncs.h:108
Status
Definition: gdiplustypes.h:25
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
BOOLEAN InfFindFirstLine(HINF InfHandle, PCSTR Section, PCSTR Key, PINFCONTEXT Context)
Definition: inffile.c:1050
BOOLEAN InfGetData(PINFCONTEXT Context, PCSTR *Key, PCSTR *Data)
Definition: inffile.c:1491
BOOLEAN InfOpenFile(PHINF InfHandle, PCSTR FileName, PULONG ErrorLine)
Definition: inffile.c:918
static struct proto Pass[]
Definition: mkg3states.c:58
#define ASSERT(a)
Definition: mode.c:44
NTSYSAPI BOOLEAN NTAPI RtlCreateUnicodeStringFromAsciiz(_Out_ PUNICODE_STRING Destination, _In_ PCSZ Source)
#define _Inout_
Definition: no_sal2.h:162
#define _In_
Definition: no_sal2.h:158
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define UNICODE_NULL
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:329
#define ANSI_NULL
BOOLEAN WinLdrLoadNLSData(_Inout_ PLOADER_PARAMETER_BLOCK LoaderBlock, _In_ PCSTR DirectoryPath, _In_ PCUNICODE_STRING AnsiFileName, _In_ PCUNICODE_STRING OemFileName, _In_ PCUNICODE_STRING LangFileName, _In_ PCUNICODE_STRING OemHalFileName)
Definition: wlregistry.c:406
BOOLEAN WinLdrAddDriverToList(_Inout_ PLIST_ENTRY DriverListHead, _In_ BOOLEAN InsertAtHead, _In_ PCWSTR DriverName, _In_opt_ PCWSTR ImagePath, _In_opt_ PCWSTR GroupName, _In_ ULONG ErrorControl, _In_ ULONG Tag)
Inserts the specified driver entry into the driver list, or updates an existing entry with new ImageP...
Definition: wlregistry.c:645
BOOLEAN WinLdrInitSystemHive(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, IN PCSTR SystemRoot, IN BOOLEAN Setup)
Definition: wlregistry.c:125
PCSTR NtLdrGetOptionExN(IN PCSTR Options, IN PCCH OptionName, IN ULONG OptNameLength, OUT PULONG OptionLength OPTIONAL)
Definition: ntldropts.c:73
PCSTR NtLdrGetOption(IN PCSTR Options, IN PCSTR OptionName)
Definition: ntldropts.c:128
PCSTR NtLdrGetNextOption(IN OUT PCSTR *Options, OUT PULONG OptionLength OPTIONAL)
Definition: ntldropts.c:16
VOID NtLdrAddOptions(IN OUT PSTR LoadOptions, IN ULONG BufferSize, IN BOOLEAN Append, IN PCSTR NewOptions OPTIONAL)
Definition: ntldropts.c:140
PCSTR NtLdrGetOptionEx(IN PCSTR Options, IN PCSTR OptionName, OUT PULONG OptionLength OPTIONAL)
Definition: ntldropts.c:117
NTSTRSAFEAPI RtlStringCbCatA(_Inout_updates_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest, _In_ size_t cbDest, _In_ NTSTRSAFE_PCSTR pszSrc)
Definition: ntstrsafe.h:625
NTSTRSAFEVAPI RtlStringCbPrintfW(_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest, _In_ size_t cbDest, _In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,...)
Definition: ntstrsafe.h:1173
NTSTRSAFEAPI RtlStringCbCopyA(_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest, _In_ size_t cbDest, _In_ NTSTRSAFE_PCSTR pszSrc)
Definition: ntstrsafe.h:156
#define WINDOWS(string, interface)
Definition: osi.c:31
unsigned short USHORT
Definition: pedump.c:61
_CRT_RESTORE_GCC_WARNINGS _CRT_DISABLE_GCC_WARNINGS _Check_return_ _CRTIMP _CONST_RETURN char *__cdecl strrchr(_In_z_ const char *_Str, _In_ int _Ch)
@ ESUCCESS
Definition: arc.h:32
@ LoaderRegistryData
Definition: arc.h:193
ULONG ARC_STATUS
Definition: arc.h:4
#define _WIN32_WINNT_WS03
Definition: sdkddkver.h:23
#define SETUPLDR_TEXT_MODE
Definition: setupblk.h:7
VOID NtLdrUpdateLoadOptions(IN OUT PSTR LoadOptions, IN ULONG BufferSize, IN BOOLEAN Append, IN PCSTR OptionsToAdd[] OPTIONAL, IN PCSTR OptionsToRemove[] OPTIONAL)
Definition: setupldr.c:258
static const struct @223 HighPriorOptionsMap[]
static VOID SetupLdrLoadNlsData(_Inout_ PLOADER_PARAMETER_BLOCK LoaderBlock, _In_ HINF InfHandle, _In_ PCSTR SearchPath)
Definition: setupldr.c:36
ARC_STATUS LoadReactOSSetup(IN ULONG Argc, IN PCHAR Argv[], IN PCHAR Envp[])
Definition: setupldr.c:492
static VOID SetupLdrScanBootDrivers(_Inout_ PLIST_ENTRY BootDriverListHead, _In_ HINF InfHandle, _In_ PCSTR SearchPath)
Definition: setupldr.c:149
PCSTR ExtraOptions
Definition: setupldr.c:353
VOID NtLdrGetHigherPriorityOptions(IN PCSTR BootOptions, OUT PSTR *ExtraOptions, OUT PSTR *HigherPriorityOptions)
Definition: setupldr.c:382
#define TAG_BOOT_OPTIONS
Definition: setupldr.c:379
static BOOLEAN SetupLdrInitErrataInf(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, IN HINF InfHandle, IN PCSTR SystemRoot)
Definition: setupldr.c:108
PCSTR Options
Definition: setupldr.c:352
PCSTR HigherPriorOptions
Definition: setupldr.c:354
VOID AllocateAndInitLPB(IN USHORT VersionToBoot, OUT PLOADER_PARAMETER_BLOCK *OutLoaderBlock)
Definition: winldr.c:77
#define TRACE(s)
Definition: solgame.cpp:4
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
Definition: typedefs.h:120
LIST_ENTRY BootDriverListHead
Definition: arc.h:542
struct _SETUP_LOADER_BLOCK * SetupLdrBlock
Definition: arc.h:558
SETUP_LOADER_BLOCK SetupBlock
Definition: winldr.h:50
char * PSTR
Definition: typedefs.h:51
ULONG_PTR SIZE_T
Definition: typedefs.h:80
const char * PCSTR
Definition: typedefs.h:52
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define IN
Definition: typedefs.h:39
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
char * PCHAR
Definition: typedefs.h:51
BOOLEAN InfGetDataField(PINFCONTEXT Context, ULONG FieldIndex, PWCHAR *Data)
Definition: infrosget.c:127
VOID InfCloseFile(HINF InfHandle)
Definition: inffile.c:1028
BOOLEAN InfFindNextLine(PINFCONTEXT ContextIn, PINFCONTEXT ContextOut)
Definition: inffile.c:1107
_In_ PWDFDEVICE_INIT _In_ PWDF_REMOVE_LOCK_OPTIONS Options
Definition: wdfdevice.h:3534
_In_ WDFMEMORY _Out_opt_ size_t * BufferSize
Definition: wdfmemory.h:254
#define SearchPath
Definition: winbase.h:3941
ARC_STATUS LoadAndBootWindowsCommon(IN USHORT OperatingSystemVersion, IN PLOADER_PARAMETER_BLOCK LoaderBlock, IN PCSTR BootOptions, IN PCSTR BootPath)
Definition: winldr.c:1172
PVOID WinLdrLoadModule(PCSTR ModuleName, PULONG Size, TYPE_OF_MEMORY MemoryType)
Definition: winldr.c:440
PCWSTR BootFileSystem
Definition: winldr.c:28
PLOADER_SYSTEM_BLOCK WinLdrSystemBlock
Definition: winldr.c:27
BOOLEAN SosEnabled
Definition: winldr.c:31
#define SERVICE_ERROR_CRITICAL
Definition: cmtypes.h:984
#define SERVICE_ERROR_NORMAL
Definition: cmtypes.h:982
__wchar_t WCHAR
Definition: xmlstorage.h:180
char CHAR
Definition: xmlstorage.h:175