ReactOS  0.4.15-dev-3294-ge98684e
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 
15 PCSTR
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 */
58  NextOption += Length;
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  */
72 PCSTR
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
118  IN PCSTR Options,
119  IN PCSTR OptionName,
120  OUT PULONG OptionLength OPTIONAL)
121 {
122  return NtLdrGetOptionExN(Options, OptionName,
123  (ULONG)strlen(OptionName),
124  OptionLength);
125 }
126 
127 PCSTR
129  IN PCSTR Options,
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  */
139 VOID
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  {
190  AddSeparator = TRUE;
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 }
#define IN
Definition: typedefs.h:39
static void AddSeparator(HWND hwndToolBar)
Definition: wordpad.c:169
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define TRUE
Definition: types.h:120
PCSTR NtLdrGetNextOption(IN OUT PCSTR *Options, OUT PULONG OptionLength OPTIONAL)
Definition: ntldropts.c:16
_Check_return_ _CRTIMP size_t __cdecl strcspn(_In_z_ const char *_Str, _In_z_ const char *_Control)
char * strncpy(char *DstString, const char *SrcString, ACPI_SIZE Count)
Definition: utclib.c:427
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
_Check_return_ _CRTIMP size_t __cdecl strspn(_In_z_ const char *_Str, _In_z_ const char *_Control)
static BOOL Append(LPWSTR *ppszText, DWORD *pdwTextLen, LPCWSTR pszAppendText, DWORD dwAppendLen)
Definition: text.c:26
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
#define FALSE
Definition: types.h:117
unsigned char BOOLEAN
CONST CHAR * PCCH
Definition: ntbasedef.h:392
_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 _strnicmp(_String1, _String2, _MaxCount)
Definition: compat.h:23
PCSTR NtLdrGetOption(IN PCSTR Options, IN PCSTR OptionName)
Definition: ntldropts.c:128
signed char * PSTR
Definition: retypes.h:7
unsigned int * PULONG
Definition: retypes.h:1
#define min(a, b)
Definition: monoChain.cc:55
#define NULL
Definition: types.h:112
#define OUT
Definition: typedefs.h:40
unsigned int ULONG
Definition: retypes.h:1
const char * PCSTR
Definition: typedefs.h:52
PCSTR NtLdrGetOptionEx(IN PCSTR Options, IN PCSTR OptionName, OUT PULONG OptionLength OPTIONAL)
Definition: ntldropts.c:117
_In_ WDFMEMORY _Out_opt_ size_t * BufferSize
Definition: wdfmemory.h:251
static char * NextOption(const char *const ostr)
Definition: getopt.c:31
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