ReactOS  0.4.15-dev-4853-g3a72a52
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>
16 DBG_DEFAULT_CHANNEL(WINDOWS);
17 
18 // TODO: Move to .h
19 VOID
21  IN USHORT VersionToBoot,
22  OUT PLOADER_PARAMETER_BLOCK* OutLoaderBlock);
23 
24 static VOID
26  _Inout_ PLOADER_PARAMETER_BLOCK LoaderBlock,
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,
80  SearchPath,
81  &AnsiFileName,
82  &OemFileName,
83  &LangFileName,
84  &OemHalFileName);
85  TRACE("NLS data loading %s\n", Success ? "successful" : "failed");
86  (VOID)Success;
87 
88 Quit:
89  RtlFreeUnicodeString(&OemHalFileName);
90  RtlFreeUnicodeString(&LangFileName);
91  RtlFreeUnicodeString(&OemFileName);
92  RtlFreeUnicodeString(&AnsiFileName);
93 }
94 
95 static
96 BOOLEAN
98  IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
99  IN HINF InfHandle,
101 {
102  INFCONTEXT InfContext;
103  PCSTR FileName;
104  ULONG FileSize;
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 
137 static 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 
192 Quit:
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  */
240 VOID
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,
320  BufferSize,
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  */
333 static 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:"},
360 };
361 
362 #define TAG_BOOT_OPTIONS 'pOtB'
363 
364 VOID
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)
384  *ExtraOptions = NULL;
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  {
427  *ExtraOptions = FrLdrHeapAlloc(ExtraOptsSize, TAG_BOOT_OPTIONS);
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  {
439  *ExtraOptions = NULL;
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;
484  PSTR FileName;
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 */
534  UiDrawBackdrop();
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,
712  &ExtraOptions,
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  */
745  &ExtraOptions,
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)
773  UiResetForSOS();
774 
775  /* Allocate and minimally-initialize the Loader Parameter Block */
776  AllocateAndInitLPB(_WIN32_WINNT_WS03, &LoaderBlock);
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,
816  BootOptions,
817  BootPath);
818 }
VOID UiUpdateProgressBar(_In_ ULONG Percentage, _In_opt_ PCSTR ProgressText)
Definition: ui.c:462
signed char * PCHAR
Definition: retypes.h:7
#define IN
Definition: typedefs.h:39
ARC_STATUS RamDiskInitialize(IN BOOLEAN InitRamDisk, IN PCSTR LoadOptions OPTIONAL, IN PCSTR DefaultPath OPTIONAL)
Definition: ramdisk.c:206
#define SERVICE_ERROR_NORMAL
Definition: cmtypes.h:982
FORCEINLINE VOID FrLdrHeapFree(PVOID MemoryPointer, ULONG Tag)
Definition: mm.h:181
#define _Inout_
Definition: ms_sal.h:378
BOOLEAN SosEnabled
Definition: winldr.c:33
#define _WIN32_WINNT_WS03
Definition: sdkddkver.h:23
BOOLEAN InfFindNextLine(PINFCONTEXT ContextIn, PINFCONTEXT ContextOut)
Definition: inffile.c:1107
Definition: arc.h:32
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define TRUE
Definition: types.h:120
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
PCSTR NtLdrGetNextOption(IN OUT PCSTR *Options, OUT PULONG OptionLength OPTIONAL)
Definition: ntldropts.c:16
char * strstr(char *String1, char *String2)
Definition: utclib.c:653
PCSTR ExtraOptions
Definition: setupldr.c:336
Definition: arc.h:39
VOID NtLdrAddOptions(IN OUT PSTR LoadOptions, IN ULONG BufferSize, IN BOOLEAN Append, IN PCSTR NewOptions OPTIONAL)
Definition: ntldropts.c:140
char CHAR
Definition: xmlstorage.h:175
#define WARN(fmt,...)
Definition: debug.h:112
ULONG ARC_STATUS
Definition: arc.h:4
static BOOL Append(LPWSTR *ppszText, DWORD *pdwTextLen, LPCWSTR pszAppendText, DWORD dwAppendLen)
Definition: text.c:26
static const struct @175 HighPriorOptionsMap[]
VOID NtLdrUpdateLoadOptions(IN OUT PSTR LoadOptions, IN ULONG BufferSize, IN BOOLEAN Append, IN PCSTR OptionsToAdd[] OPTIONAL, IN PCSTR OptionsToRemove[] OPTIONAL)
Definition: setupldr.c:241
_Check_return_ _CRTIMP _CONST_RETURN char *__cdecl strrchr(_In_z_ const char *_Str, _In_ int _Ch)
DBG_DEFAULT_CHANNEL(WINDOWS)
static VOID SetupLdrScanBootDrivers(_Inout_ PLIST_ENTRY BootDriverListHead, _In_ HINF InfHandle, _In_ PCSTR SearchPath)
Definition: setupldr.c:138
#define _stricmp
Definition: cat.c:22
BOOLEAN InfGetDataField(PINFCONTEXT Context, ULONG FieldIndex, PWCHAR *Data)
Definition: infrosget.c:127
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
PCWSTR FilePath
#define SearchPath
Definition: winbase.h:3761
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
struct _SETUP_LOADER_BLOCK * SetupLdrBlock
Definition: arc.h:511
#define FALSE
Definition: types.h:117
#define UNICODE_NULL
#define ANSI_NULL
VOID UiMessageBox(PCSTR Format,...)
Definition: ui.c:363
PCSTR HigherPriorOptions
Definition: setupldr.c:337
unsigned char BOOLEAN
VOID UiDrawProgressBarCenter(_In_ PCSTR ProgressText)
Definition: ui.c:503
ARC_STATUS LoadAndBootWindowsCommon(IN USHORT OperatingSystemVersion, IN PLOADER_PARAMETER_BLOCK LoaderBlock, IN PCSTR BootOptions, IN PCSTR BootPath)
Definition: winldr.c:1150
#define _In_
Definition: ms_sal.h:308
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:575
NTSYSAPI BOOLEAN NTAPI RtlCreateUnicodeStringFromAsciiz(_Out_ PUNICODE_STRING Destination, _In_ PCSZ Source)
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:336
PCWSTR BootFileSystem
Definition: winldr.c:30
Status
Definition: gdiplustypes.h:24
FORCEINLINE PVOID FrLdrHeapAlloc(SIZE_T MemorySize, ULONG Tag)
Definition: mm.h:174
#define TRACE(s)
Definition: solgame.cpp:4
_In_ PWDFDEVICE_INIT _In_ PWDF_REMOVE_LOCK_OPTIONS Options
Definition: wdfdevice.h:3531
PCSTR NtLdrGetOptionExN(IN PCSTR Options, IN PCCH OptionName, IN ULONG OptNameLength, OUT PULONG OptionLength OPTIONAL)
Definition: ntldropts.c:73
#define ASSERT(a)
Definition: mode.c:44
static const WCHAR SystemRoot[]
Definition: reg.c:38
__wchar_t WCHAR
Definition: xmlstorage.h:180
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
#define MAX_PATH
Definition: compat.h:34
static VOID SetupLdrLoadNlsData(_Inout_ PLOADER_PARAMETER_BLOCK LoaderBlock, _In_ HINF InfHandle, _In_ PCSTR SearchPath)
Definition: setupldr.c:25
LIST_ENTRY BootDriverListHead
Definition: arc.h:495
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define _strnicmp(_String1, _String2, _MaxCount)
Definition: compat.h:23
static PPARTENTRY SystemPartition
Definition: usetup.c:61
VOID UiDrawStatusText(PCSTR StatusText)
Definition: ui.c:292
VOID InfCloseFile(HINF InfHandle)
Definition: inffile.c:1028
#define VOID
Definition: acefi.h:82
_Must_inspect_result_ _Out_ PLARGE_INTEGER FileSize
Definition: fsrtlfuncs.h:108
PCSTR Options
Definition: setupldr.c:335
Definition: typedefs.h:119
VOID UiDrawBackdrop(VOID)
Definition: ui.c:239
_Must_inspect_result_ _In_ PFILE_OBJECT _In_opt_ HANDLE _In_ ULONG FileNameLength
Definition: fltkernel.h:1129
SETUP_LOADER_BLOCK SetupBlock
Definition: winldr.h:50
BOOLEAN InfGetData(PINFCONTEXT Context, PCSTR *Key, PCSTR *Data)
Definition: inffile.c:1491
#define ERR(fmt,...)
Definition: debug.h:110
ULONG_PTR SIZE_T
Definition: typedefs.h:80
struct _FileName FileName
Definition: fatprocs.h:893
#define TAG_BOOT_OPTIONS
Definition: setupldr.c:362
PCSTR NtLdrGetOption(IN PCSTR Options, IN PCSTR OptionName)
Definition: ntldropts.c:128
#define SETUPLDR_TEXT_MODE
Definition: setupblk.h:7
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
unsigned short USHORT
Definition: pedump.c:61
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
PVOID WinLdrLoadModule(PCSTR ModuleName, PULONG Size, TYPE_OF_MEMORY MemoryType)
Definition: winldr.c:425
signed char * PSTR
Definition: retypes.h:7
Definition: arc.h:46
#define NULL
Definition: types.h:112
ARC_STATUS LoadReactOSSetup(IN ULONG Argc, IN PCHAR Argv[], IN PCHAR Envp[])
Definition: setupldr.c:475
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
FORCEINLINE VOID UiResetForSOS(VOID)
Definition: winldr.h:83
static BOOLEAN SetupLdrInitErrataInf(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, IN HINF InfHandle, IN PCSTR SystemRoot)
Definition: setupldr.c:97
#define OUT
Definition: typedefs.h:40
FORCEINLINE PVOID PaToVa(PVOID Pa)
Definition: conversion.h:22
VOID AllocateAndInitLPB(IN USHORT VersionToBoot, OUT PLOADER_PARAMETER_BLOCK *OutLoaderBlock)
Definition: winldr.c:79
BOOLEAN InfFindFirstLine(HINF InfHandle, PCSTR Section, PCSTR Key, PINFCONTEXT Context)
Definition: inffile.c:1050
unsigned int ULONG
Definition: retypes.h:1
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
Definition: arc.h:47
#define SERVICE_ERROR_CRITICAL
Definition: cmtypes.h:984
const char * PCSTR
Definition: typedefs.h:52
PCHAR GetArgumentValue(IN ULONG Argc, IN PCHAR Argv[], IN PCHAR ArgumentName)
Definition: arcsupp.c:41
BOOLEAN WinLdrInitSystemHive(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, IN PCSTR SystemRoot, IN BOOLEAN Setup)
Definition: wlregistry.c:110
VOID NtLdrGetHigherPriorityOptions(IN PCSTR BootOptions, OUT PSTR *ExtraOptions, OUT PSTR *HigherPriorityOptions)
Definition: setupldr.c:365
#define CHAR(Char)
PCSTR NtLdrGetOptionEx(IN PCSTR Options, IN PCSTR OptionName, OUT PULONG OptionLength OPTIONAL)
Definition: ntldropts.c:117
BOOLEAN InfOpenFile(PHINF InfHandle, PCSTR FileName, PULONG ErrorLine)
Definition: inffile.c:918
_In_ WDFMEMORY _Out_opt_ size_t * BufferSize
Definition: wdfmemory.h:251
PLOADER_SYSTEM_BLOCK WinLdrSystemBlock
Definition: winldr.c:29
NTSTRSAFEAPI RtlStringCbCatA(_Inout_updates_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest, _In_ size_t cbDest, _In_ NTSTRSAFE_PCSTR pszSrc)
Definition: ntstrsafe.h:625
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68