ReactOS 0.4.15-dev-8058-ga7cbb60
ntldropts.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: 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
18 OUT PULONG OptionLength OPTIONAL)
19{
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 */
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 */
59 }
60
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 */
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
116PCSTR
119 IN PCSTR OptionName,
120 OUT PULONG OptionLength OPTIONAL)
121{
122 return NtLdrGetOptionExN(Options, OptionName,
123 (ULONG)strlen(OptionName),
124 OptionLength);
125}
126
127PCSTR
130 IN PCSTR OptionName)
131{
132 return NtLdrGetOptionEx(Options, OptionName, NULL);
133}
134
135/*
136 * Appends or prepends new options to the ones originally contained
137 * in the buffer pointed by LoadOptions, of maximum size BufferSize.
138 */
139VOID
141 IN OUT PSTR LoadOptions,
143 IN BOOLEAN Append,
144 IN PCSTR NewOptions OPTIONAL)
145{
146 ULONG OptionsLength;
147 ULONG NewOptsLength;
149
150 if (!LoadOptions || (BufferSize == 0))
151 return;
152 // ASSERT(strlen(LoadOptions) + 1 <= BufferSize);
153
154 if (!NewOptions || !*NewOptions)
155 return;
156
157 if (Append)
158 {
159 OptionsLength = (ULONG)strlen(LoadOptions);
160 OptionsLength = min(OptionsLength, BufferSize-1);
161
162 /* Add a whitespace separator if needed */
163 if (OptionsLength != 0 &&
164 (LoadOptions[OptionsLength-1] != ' ') &&
165 (LoadOptions[OptionsLength-1] != '\t') &&
166 (*NewOptions != '\0') &&
167 (*NewOptions != ' ') &&
168 (*NewOptions != '\t'))
169 {
170 RtlStringCbCatA(LoadOptions, BufferSize * sizeof(CHAR), " ");
171 }
172
173 /* Append the options */
174 RtlStringCbCatA(LoadOptions, BufferSize * sizeof(CHAR), NewOptions);
175 }
176 else
177 {
178 NewOptsLength = (ULONG)strlen(NewOptions);
179 NewOptsLength = min(NewOptsLength, BufferSize-1);
180
181 /* Add a whitespace separator if needed */
183 if (NewOptsLength != 0 &&
184 (NewOptions[NewOptsLength-1] != ' ') &&
185 (NewOptions[NewOptsLength-1] != '\t') &&
186 (*LoadOptions != '\0') &&
187 (*LoadOptions != ' ') &&
188 (*LoadOptions != '\t'))
189 {
191 ++NewOptsLength;
192 }
193
194 /*
195 * Move the original load options forward (possibly truncating them
196 * at the end if the buffer is not large enough) to make place for
197 * the options to prepend.
198 */
199 OptionsLength = (ULONG)strlen(LoadOptions) + 1;
200 OptionsLength = min(OptionsLength, BufferSize - NewOptsLength);
201 RtlMoveMemory(LoadOptions + NewOptsLength,
202 LoadOptions,
203 OptionsLength * sizeof(CHAR));
204 /* NULL-terminate */
205 (LoadOptions + NewOptsLength)[OptionsLength-1] = '\0';
206
207 /* Restore the new options length back to its original value */
208 if (AddSeparator) --NewOptsLength;
209 /* Prepend the options and add the whitespace separator if needed */
210 strncpy(LoadOptions, NewOptions, NewOptsLength);
211 if (AddSeparator) LoadOptions[NewOptsLength] = ' ';
212 }
213}
unsigned char BOOLEAN
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
char * strncpy(char *DstString, const char *SrcString, ACPI_SIZE Count)
Definition: utclib.c:427
static void AddSeparator(HWND hwndToolBar)
Definition: wordpad.c:169
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define _strnicmp(_String1, _String2, _MaxCount)
Definition: compat.h:23
static char * NextOption(const char *const ostr)
Definition: getopt.c:31
#define min(a, b)
Definition: monoChain.cc:55
CONST CHAR * PCCH
Definition: ntbasedef.h:392
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
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
_Check_return_ _CRTIMP size_t __cdecl strspn(_In_z_ const char *_Str, _In_z_ const char *_Control)
_Check_return_ _CRTIMP size_t __cdecl strcspn(_In_z_ const char *_Str, _In_z_ const char *_Control)
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
uint32_t * PULONG
Definition: typedefs.h:59
char * PSTR
Definition: typedefs.h:51
const char * PCSTR
Definition: typedefs.h:52
#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
_In_ PWDFDEVICE_INIT _In_ PWDF_REMOVE_LOCK_OPTIONS Options
Definition: wdfdevice.h:3534
_In_ WDFMEMORY _Out_opt_ size_t * BufferSize
Definition: wdfmemory.h:254
char CHAR
Definition: xmlstorage.h:175