Skip to content

Commit 4406c36

Browse files
HBeluscabinarymaster
authored andcommitted
[FREELDR] Parse NT kernel load options in a consistent manner.
- Introduce a set of NtLdrGet(Next)Option(Ex) helpers that allow retrieving respectively, the "next" option in an options string, and retrieving a given named option in such an options string, by correctly parsing that string. Valid syntaxes: /OPTION1 /OPTION2/OPTION3 OPTION4 /OPTION5(=...) ... Options separators are slashes, or whitespace (space, tab), mandatory if no slash is used, and otherwise optional. - Use these functions wherever NT load options are being parsed. - Simplify the parsing of /DEBUGPORT=... using these functions. - When parsing the /HAL=... or /KERNEL=... options, only the first encountered one is taken into account, any other ones are discarded. - When parsing the other load options, only their first occurrences are taken into account, any other repetitions are discarded. * The NOPAE option overrides any previous PAE option. * Any NOEXECUTE(=) option should override any previous NOEXECUTE=ALWAYSOFF (or equivalently, EXECUTE) option.
1 parent c10fe76 commit 4406c36

File tree

6 files changed

+285
-177
lines changed

6 files changed

+285
-177
lines changed

boot/freeldr/freeldr/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ list(APPEND FREELDR_BASE_SOURCE
224224
## otherwise we get linking errors with Rtl**Bitmap** APIs.
225225
## Do not happen on MSVC builds however...
226226
ntldr/inffile.c
227+
ntldr/ntldropts.c
227228
lib/rtl/libsupp.c)
228229

229230
if(ARCH STREQUAL "i386")

boot/freeldr/freeldr/disk/ramdisk.c

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
/* INCLUDES *******************************************************************/
1111

1212
#include <freeldr.h>
13+
#include "../ntldr/ntldropts.h"
1314

1415
/* GLOBALS ********************************************************************/
1516

@@ -241,30 +242,31 @@ RamDiskInitialize(
241242
/* If we don't have any load options, initialize an empty Ramdisk */
242243
if (LoadOptions)
243244
{
244-
PCHAR Option;
245+
PCSTR Option;
246+
ULONG FileNameLength;
245247

246248
/* Ramdisk image file name */
247-
Option = strstr(LoadOptions, "/RDPATH=");
248-
if (Option)
249+
Option = NtLdrGetOptionEx(LoadOptions, "RDPATH=", &FileNameLength);
250+
if (Option && (FileNameLength > 7))
249251
{
250-
/* Copy the file name - everything until the next separator */
251-
Option += 8;
252+
/* Copy the file name */
253+
Option += 7; FileNameLength -= 7;
252254
RtlStringCbCopyNA(FileName, sizeof(FileName),
253-
Option, strcspn(Option, " \t") * sizeof(CHAR));
255+
Option, FileNameLength * sizeof(CHAR));
254256
}
255257

256258
/* Ramdisk image length */
257-
Option = strstr(LoadOptions, "/RDIMAGELENGTH=");
259+
Option = NtLdrGetOption(LoadOptions, "RDIMAGELENGTH=");
258260
if (Option)
259261
{
260-
RamDiskImageLength = _atoi64(Option + 15);
262+
RamDiskImageLength = _atoi64(Option + 14);
261263
}
262264

263265
/* Ramdisk image offset */
264-
Option = strstr(LoadOptions, "/RDIMAGEOFFSET=");
266+
Option = NtLdrGetOption(LoadOptions, "RDIMAGEOFFSET=");
265267
if (Option)
266268
{
267-
RamDiskImageOffset = atol(Option + 15);
269+
RamDiskImageOffset = atol(Option + 14);
268270
}
269271
}
270272

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/*
2+
* PROJECT: FreeLoader
3+
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4+
* PURPOSE: NT Kernel Load Options Support Functions
5+
* COPYRIGHT: Copyright 2020 Hermes Belusca-Maito
6+
*/
7+
8+
/* INCLUDES ******************************************************************/
9+
10+
#include <freeldr.h>
11+
#include "ntldropts.h"
12+
13+
/* FUNCTIONS *****************************************************************/
14+
15+
PCSTR
16+
NtLdrGetNextOption(
17+
IN OUT PCSTR* Options,
18+
OUT PULONG OptionLength OPTIONAL)
19+
{
20+
PCSTR NextOption;
21+
PCSTR Option = NULL;
22+
ULONG Length = 0;
23+
24+
if (OptionLength)
25+
*OptionLength = 0;
26+
27+
if (!Options || !*Options)
28+
return NULL;
29+
30+
/* Loop over each option */
31+
NextOption = *Options;
32+
while (*NextOption)
33+
{
34+
/* Skip possible initial whitespace */
35+
NextOption += strspn(NextOption, " \t");
36+
37+
/* Stop now if we have already found an option.
38+
* NextOption points to the next following option. */
39+
if (Option)
40+
break;
41+
42+
/*
43+
* Check whether a new option starts. Options are delimited
44+
* with an option separator '/' or with whitespace.
45+
*/
46+
if (*NextOption == '/')
47+
++NextOption;
48+
49+
/* Get the actual length of the option until
50+
* the next whitespace or option separator. */
51+
Length = (ULONG)strcspn(NextOption, " \t/");
52+
53+
/* Retrieve the option if present and go to the beginning of the next one */
54+
if (Length != 0)
55+
Option = NextOption;
56+
57+
/* Restart after the end of the option */
58+
NextOption += Length;
59+
}
60+
61+
*Options = NextOption;
62+
if (Option && OptionLength)
63+
*OptionLength = Length;
64+
return Option;
65+
}
66+
67+
/*
68+
* OptionName specifies the option name, without any leading
69+
* option separator '/', to search for within the Options.
70+
* The search is made case-insensitive.
71+
*/
72+
PCSTR
73+
NtLdrGetOptionExN(
74+
IN PCSTR Options,
75+
IN PCCH OptionName,
76+
IN ULONG OptNameLength,
77+
OUT PULONG OptionLength OPTIONAL)
78+
{
79+
PCSTR NextOptions;
80+
PCSTR Option = NULL;
81+
ULONG OptLength = 0;
82+
83+
if (OptionLength)
84+
*OptionLength = 0;
85+
86+
if (!Options || !*Options)
87+
return NULL;
88+
if (!OptionName || (OptNameLength == 0) || !*OptionName)
89+
return NULL;
90+
91+
NextOptions = Options;
92+
while ((Option = NtLdrGetNextOption(&NextOptions, &OptLength)))
93+
{
94+
/*
95+
* Check whether the option to find exactly matches the current
96+
* load option, or is a prefix thereof if this is an option with
97+
* appended data.
98+
*/
99+
if ((OptLength >= OptNameLength) &&
100+
(_strnicmp(Option, OptionName, OptNameLength) == 0))
101+
{
102+
if ((OptLength == OptNameLength) ||
103+
(OptionName[OptNameLength-1] == '=') ||
104+
(OptionName[OptNameLength-1] == ':'))
105+
{
106+
break;
107+
}
108+
}
109+
}
110+
111+
if (Option && OptionLength)
112+
*OptionLength = OptLength;
113+
return Option;
114+
}
115+
116+
PCSTR
117+
NtLdrGetOptionEx(
118+
IN PCSTR Options,
119+
IN PCSTR OptionName,
120+
OUT PULONG OptionLength OPTIONAL)
121+
{
122+
return NtLdrGetOptionExN(Options, OptionName, strlen(OptionName), OptionLength);
123+
}
124+
125+
PCSTR
126+
NtLdrGetOption(
127+
IN PCSTR Options,
128+
IN PCSTR OptionName)
129+
{
130+
return NtLdrGetOptionEx(Options, OptionName, NULL);
131+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* PROJECT: FreeLoader
3+
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4+
* PURPOSE: NT Kernel Load Options Support Functions
5+
* COPYRIGHT: Copyright 2020 Hermes Belusca-Maito
6+
*/
7+
8+
#pragma once
9+
10+
PCSTR
11+
NtLdrGetNextOption(
12+
IN OUT PCSTR* Options,
13+
OUT PULONG OptionLength OPTIONAL);
14+
15+
PCSTR
16+
NtLdrGetOptionExN(
17+
IN PCSTR Options,
18+
IN PCCH OptionName,
19+
IN ULONG OptNameLength,
20+
OUT PULONG OptionLength OPTIONAL);
21+
22+
PCSTR
23+
NtLdrGetOptionEx(
24+
IN PCSTR Options,
25+
IN PCSTR OptionName,
26+
OUT PULONG OptionLength OPTIONAL);
27+
28+
PCSTR
29+
NtLdrGetOption(
30+
IN PCSTR Options,
31+
IN PCSTR OptionName);

boot/freeldr/freeldr/ntldr/setupldr.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <arc/setupblk.h>
1111
#include "winldr.h"
1212
#include "inffile.h"
13+
#include "ntldropts.h"
1314

1415
#include <debug.h>
1516
DBG_DEFAULT_CHANNEL(WINDOWS);
@@ -140,6 +141,7 @@ LoadReactOSSetup(
140141
PCSTR SystemPartition;
141142
PCSTR SystemPath;
142143
PSTR FileName;
144+
ULONG FileNameLength;
143145
BOOLEAN BootFromFloppy;
144146
BOOLEAN Success;
145147
HINF InfHandle;
@@ -236,16 +238,16 @@ LoadReactOSSetup(
236238
TRACE("BootOptions: '%s'\n", BootOptions2);
237239

238240
/* Check if a RAM disk file was given */
239-
FileName = strstr(BootOptions2, "/RDPATH=");
240-
if (FileName)
241+
FileName = (PSTR)NtLdrGetOptionEx(BootOptions2, "RDPATH=", &FileNameLength);
242+
if (FileName && (FileNameLength > 7))
241243
{
242244
/* Load the RAM disk */
243245
Status = RamDiskInitialize(FALSE, BootOptions2, SystemPartition);
244246
if (Status != ESUCCESS)
245247
{
246-
FileName += 8;
248+
FileName += 7; FileNameLength -= 7;
247249
UiMessageBox("Failed to load RAM disk file '%.*s'",
248-
strcspn(FileName, " \t"), FileName);
250+
FileNameLength, FileName);
249251
return Status;
250252
}
251253
}
@@ -263,7 +265,8 @@ LoadReactOSSetup(
263265
UiMessageBox("Failed to open txtsetup.sif");
264266
return ENOENT;
265267
}
266-
RtlStringCbCopyA(FileName, sizeof(BootPath) - (FileName - BootPath)*sizeof(CHAR), SystemPath);
268+
FileNameLength = (ULONG)(sizeof(BootPath) - (FileName - BootPath)*sizeof(CHAR));
269+
RtlStringCbCopyA(FileName, FileNameLength, SystemPath);
267270
RtlStringCbCopyA(FilePath, sizeof(FilePath), BootPath);
268271
RtlStringCbCatA(FilePath, sizeof(FilePath), "txtsetup.sif");
269272
if (InfOpenFile(&InfHandle, FilePath, &ErrorLine))

0 commit comments

Comments
 (0)