ReactOS
0.4.17-dev-573-g8315b8c
name.c
Go to the documentation of this file.
1
/*
2
* PROJECT: ReactOS System Libraries
3
* LICENSE: MIT (https://spdx.org/licenses/MIT)
4
* PURPOSE: RtlIsNameInExpression implementation
5
* COPYRIGHT: Copyright 2026 Carl Bialorucki <carl.bialorucki@reactos.org>
6
*/
7
8
#include <
rtl.h
>
9
#define NDEBUG
10
#include <debug.h>
11
12
#define DOS_STAR (L'<')
13
#define DOS_QM (L'>')
14
#define DOS_DOT (L'"')
15
16
#define EXPRESSION_IS_WILDCARD(expr, len) \
17
(len == 1 && expr->Buffer[0] == L'*') \
18
|| (len == 3 && expr->Buffer[0] == L'*' && expr->Buffer[1] == L'.' && expr->Buffer[2] == L'*')
19
#define IS_LITERAL_OR_DOS_DOT(wchar) \
20
(wchar == DOS_DOT || (wchar != L'*' && wchar != DOS_STAR && wchar != L'?' && wchar != DOS_QM))
21
22
/* ****** PRIVATE FUNCTIONS ****** */
23
24
static __inline BOOLEAN
25
RtlpContainsWildcard(
26
_In_ PWCH Buffer,
27
_In_ ULONG Length)
28
{
29
for (ULONG i = 0; i < Length; i++)
30
{
31
WCHAR c = Buffer[i];
32
if (c == L'*' || c == L'?' || c == DOS_STAR || c == DOS_QM || c == DOS_DOT)
33
return TRUE;
34
}
35
return FALSE;
36
}
37
38
static __inline WCHAR
39
RtlpGetExprChar(
40
_In_ PWCH Buffer,
41
_In_ ULONG Position,
42
_In_ ULONG Length,
43
_In_ BOOLEAN IgnoreCase,
44
_In_opt_ PWCH UpcaseTable)
45
{
46
WCHAR Result = (Position < Length) ? Buffer[Position] : L'\0';
47
if (IgnoreCase)
48
Result = UpcaseTable ? UpcaseTable[Result] : RtlUpcaseUnicodeChar(Result);
49
return Result;
50
}
51
52
/* ****** PUBLIC FUNCTIONS ****** */
53
54
BOOLEAN
55
NTAPI
56
RtlIsNameInExpression(
57
_In_ PUNICODE_STRING Expression,
58
_In_ PUNICODE_STRING Name,
59
_In_ BOOLEAN IgnoreCase,
60
_In_opt_ PWCH UpcaseTable
61
)
62
{
63
ULONG NameLen = Name->Length / sizeof(WCHAR);
64
ULONG ExprLen = Expression->Length / sizeof(WCHAR);
65
ULONG NamePos = 0, ExprPos = 0;
66
ULONG StarExprPos = MAXULONG;
67
ULONG StarNamePos = 0;
68
69
/* For more information about this algorithm, see
70
* https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fsa/0b034646-4e23-4874-8488-2adac231ff23
71
*/
72
73
/* *** Optimizations *** */
74
75
/* Empty string */
76
if (ExprLen == 0 || NameLen == 0)
77
return (ExprLen == 0 && NameLen == 0);
78
79
/* Wildcard only */
80
if (EXPRESSION_IS_WILDCARD(Expression, ExprLen))
81
return TRUE;
82
83
/* Wildcard + literal with no other wildcards */
84
if (ExprLen >= 2
85
&& NameLen >= ExprLen - 1
86
&& Expression->Buffer[0] == L'*'
87
&& !RtlpContainsWildcard(&Expression->Buffer[1], ExprLen - 1))
88
{
89
ExprPos = 1;
90
NamePos = NameLen - (ExprLen - 1);
91
92
while (ExprPos < ExprLen)
93
{
94
WCHAR NameChar = RtlpGetExprChar(Name->Buffer, NamePos, NameLen, IgnoreCase, UpcaseTable);
95
WCHAR ExprChar = RtlpGetExprChar(Expression->Buffer, ExprPos, ExprLen, IgnoreCase, UpcaseTable);
96
if (ExprChar != NameChar)
97
return FALSE;
98
NamePos++;
99
ExprPos++;
100
}
101
102
return TRUE;
103
}
104
105
/* *** Main parser *** */
106
107
for (;;)
108
{
109
/* We passed everything and reached the end of both the name and expression. */
110
if (NamePos >= NameLen && ExprPos >= ExprLen)
111
return TRUE;
112
113
WCHAR NameChar = RtlpGetExprChar(Name->Buffer, NamePos, NameLen, IgnoreCase, UpcaseTable);
114
WCHAR ExprChar = RtlpGetExprChar(Expression->Buffer, ExprPos, ExprLen, IgnoreCase, UpcaseTable);
115
116
/* '?' or character literal */
117
if ((ExprChar == L'?' && NamePos < NameLen)
118
|| (IS_LITERAL_OR_DOS_DOT(ExprChar) && ExprChar == NameChar))
119
{
120
NamePos++;
121
ExprPos++;
122
continue;
123
}
124
125
/* '*' */
126
if (ExprChar == L'*')
127
{
128
StarExprPos = ExprPos;
129
StarNamePos = NamePos;
130
ExprPos++;
131
continue;
132
}
133
134
/* DOS_STAR */
135
if (ExprChar == DOS_STAR)
136
{
137
ULONG LookPos = ExprPos + 1;
138
StarExprPos = ExprPos;
139
StarNamePos = NamePos;
140
141
while (LookPos < ExprLen)
142
{
143
WCHAR LookChar = Expression->Buffer[LookPos];
144
if (IS_LITERAL_OR_DOS_DOT(LookChar))
145
break;
146
LookPos++;
147
}
148
149
ExprPos++;
150
continue;
151
}
152
153
/* DOS_QM */
154
if (ExprChar == DOS_QM)
155
{
156
if (NamePos >= NameLen || NameChar == L'.')
157
{
158
/* Dot or end-of-name: skip all consecutive DOS_QM tokens */
159
while (ExprPos < ExprLen && Expression->Buffer[ExprPos] == DOS_QM)
160
ExprPos++;
161
continue;
162
}
163
164
/* Normal DOS_QM: consume one non-dot character */
165
NamePos++;
166
ExprPos++;
167
continue;
168
}
169
170
/* DOS_DOT */
171
if (ExprChar == DOS_DOT)
172
{
173
if (NamePos >= NameLen)
174
{
175
ExprPos++;
176
continue;
177
}
178
179
if (NameChar == L'.')
180
{
181
NamePos++;
182
ExprPos++;
183
continue;
184
}
185
}
186
187
/* Backtrack from a '*' or DOS_STAR */
188
if (StarExprPos != MAXULONG)
189
{
190
/* A DOS_STAR at the end cannot consume a trailing '.' in the name */
191
if (Expression->Buffer[StarExprPos] == DOS_STAR && ExprPos >= ExprLen)
192
{
193
ULONG i;
194
for (i = StarNamePos; i < NameLen; i++)
195
{
196
if (Name->Buffer[i] == L'.')
197
return FALSE;
198
}
199
}
200
201
if (StarNamePos < NameLen)
202
{
203
StarNamePos++;
204
NamePos = StarNamePos;
205
ExprPos = StarExprPos + 1;
206
continue;
207
}
208
}
209
210
return FALSE;
211
}
212
}
rtl.h
sdk
lib
rtl
name.c
Generated on Sat Aug 1 2026 06:21:54 for ReactOS by
1.9.6