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