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