2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/fsrtl/name.c
5 * PURPOSE: Provides name parsing and other support routines for FSDs
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 * Filip Navara (navaraf@reactos.org)
8 * Pierre Schweitzer (pierre.schweitzer@reactos.org)
11 /* INCLUDES ******************************************************************/
17 /* PRIVATE FUNCTIONS *********************************************************/
20 FsRtlIsNameInExpressionPrivate(IN PUNICODE_STRING Expression
,
21 IN PUNICODE_STRING Name
,
22 IN BOOLEAN IgnoreCase
,
23 IN PWCHAR UpcaseTable OPTIONAL
)
25 ULONG i
= 0, j
, k
= 0;
27 ASSERT(!FsRtlDoesNameContainWildCards(Name
));
29 while (i
< Name
->Length
/ sizeof(WCHAR
) && k
< Expression
->Length
/ sizeof(WCHAR
))
31 if ((Expression
->Buffer
[k
] == (IgnoreCase
? UpcaseTable
[Name
->Buffer
[i
]] : Name
->Buffer
[i
])) ||
32 (Expression
->Buffer
[k
] == L
'?') || (Expression
->Buffer
[k
] == DOS_QM
) ||
33 (Expression
->Buffer
[k
] == DOS_DOT
&& (Name
->Buffer
[i
] == L
'.' || Name
->Buffer
[i
] == L
'0')))
38 else if (Expression
->Buffer
[k
] == L
'*')
40 if (k
< (Expression
->Length
/ sizeof(WCHAR
) - 1))
42 if (Expression
->Buffer
[k
+1] != L
'*' && Expression
->Buffer
[k
+1] != L
'?' &&
43 Expression
->Buffer
[k
+1] != DOS_DOT
&& Expression
->Buffer
[k
+1] != DOS_QM
&&
44 Expression
->Buffer
[k
+1] != DOS_STAR
)
46 while ((IgnoreCase
? UpcaseTable
[Name
->Buffer
[i
]] : Name
->Buffer
[i
]) != Expression
->Buffer
[k
+1] &&
47 i
< Name
->Length
/ sizeof(WCHAR
)) i
++;
51 if (!(Expression
->Buffer
[k
+1] != DOS_DOT
&& (Name
->Buffer
[i
] == L
'.' || Name
->Buffer
[i
] == L
'0')))
59 i
= Name
->Length
/ sizeof(WCHAR
);
63 else if (Expression
->Buffer
[k
] == DOS_STAR
)
66 while (j
< Name
->Length
/ sizeof(WCHAR
))
68 if (Name
->Buffer
[j
] == L
'.')
78 i
= Name
->Length
/ sizeof(WCHAR
);
82 return (k
== Expression
->Length
/ sizeof(WCHAR
) && i
== Name
->Length
/ sizeof(WCHAR
));
85 /* PUBLIC FUNCTIONS **********************************************************/
88 * @name FsRtlAreNamesEqual
91 * Compare two strings to check if they match
94 * First unicode string to compare
97 * Second unicode string to compare
100 * If TRUE, Case will be ignored when comparing strings
103 * Table for upcase letters. If NULL is given, system one will be used
105 * @return TRUE if the strings are equal
107 * @remarks From Bo Branten's ntifs.h v25.
112 FsRtlAreNamesEqual(IN PCUNICODE_STRING Name1
,
113 IN PCUNICODE_STRING Name2
,
114 IN BOOLEAN IgnoreCase
,
115 IN PCWCH UpcaseTable OPTIONAL
)
117 UNICODE_STRING UpcaseName1
;
118 UNICODE_STRING UpcaseName2
;
119 BOOLEAN StringsAreEqual
, MemoryAllocated
= FALSE
;
123 /* Well, first check their size */
124 if (Name1
->Length
!= Name2
->Length
) return FALSE
;
126 /* Check if the caller didn't give an upcase table */
127 if ((IgnoreCase
) && !(UpcaseTable
))
129 /* Upcase the string ourselves */
130 Status
= RtlUpcaseUnicodeString(&UpcaseName1
, Name1
, TRUE
);
131 if (!NT_SUCCESS(Status
)) RtlRaiseStatus(Status
);
133 /* Upcase the second string too */
134 RtlUpcaseUnicodeString(&UpcaseName2
, Name2
, TRUE
);
135 Name1
= &UpcaseName1
;
136 Name2
= &UpcaseName2
;
138 /* Make sure we go through the path below, but free the strings */
140 MemoryAllocated
= TRUE
;
143 /* Do a case-sensitive search */
146 /* Use a raw memory compare */
147 StringsAreEqual
= RtlEqualMemory(Name1
->Buffer
,
151 /* Check if we allocated strings */
155 RtlFreeUnicodeString(&UpcaseName1
);
156 RtlFreeUnicodeString(&UpcaseName2
);
159 /* Return the equality */
160 return StringsAreEqual
;
164 /* Case in-sensitive search */
165 for (i
= 0; i
< Name1
->Length
/ sizeof(WCHAR
); i
++)
167 /* Check if the character matches */
168 if (UpcaseTable
[Name1
->Buffer
[i
]] != UpcaseTable
[Name2
->Buffer
[i
]])
170 /* Non-match found! */
175 /* We finished the loop so we are equal */
181 * @name FsRtlDissectName
184 * Dissects a given path name into first and remaining part.
187 * Unicode string to dissect.
190 * Pointer to user supplied UNICODE_STRING, that will later point
191 * to the first part of the original name.
193 * @param RemainingPart
194 * Pointer to user supplied UNICODE_STRING, that will later point
195 * to the remaining part of the original name.
200 * Name: \test1\test2\test3
202 * RemainingPart: test2\test3
207 FsRtlDissectName(IN UNICODE_STRING Name
,
208 OUT PUNICODE_STRING FirstPart
,
209 OUT PUNICODE_STRING RemainingPart
)
211 ULONG FirstPosition
, i
;
212 ULONG SkipFirstSlash
= 0;
214 /* Zero the strings before continuing */
215 RtlZeroMemory(FirstPart
, sizeof(UNICODE_STRING
));
216 RtlZeroMemory(RemainingPart
, sizeof(UNICODE_STRING
));
218 /* Just quit if the string is empty */
219 if (!Name
.Length
) return;
221 /* Find first backslash */
222 FirstPosition
= Name
.Length
/ sizeof(WCHAR
) ;
223 for (i
= 0; i
< Name
.Length
/ sizeof(WCHAR
); i
++)
225 /* If we found one... */
226 if (Name
.Buffer
[i
] == L
'\\')
228 /* If it begins string, just notice it and continue */
235 /* Else, save its position and break out of the loop */
242 /* Set up the first result string */
243 FirstPart
->Buffer
= Name
.Buffer
+ SkipFirstSlash
;
244 FirstPart
->Length
= (FirstPosition
- SkipFirstSlash
) * sizeof(WCHAR
);
245 FirstPart
->MaximumLength
= FirstPart
->Length
;
247 /* And second one, if necessary */
248 if (FirstPosition
< (Name
.Length
/ sizeof(WCHAR
)))
250 RemainingPart
->Buffer
= Name
.Buffer
+ FirstPosition
+ 1;
251 RemainingPart
->Length
= Name
.Length
- (FirstPosition
+ 1) * sizeof(WCHAR
);
252 RemainingPart
->MaximumLength
= RemainingPart
->Length
;
257 * @name FsRtlDoesNameContainWildCards
260 * Checks if the given string contains WildCards
263 * Pointer to a UNICODE_STRING containing Name to examine
265 * @return TRUE if Name contains wildcards, FALSE otherwise
267 * @remarks From Bo Branten's ntifs.h v12.
272 FsRtlDoesNameContainWildCards(IN PUNICODE_STRING Name
)
276 /* Loop through every character */
279 Ptr
= Name
->Buffer
+ (Name
->Length
/ sizeof(WCHAR
)) - 1;
280 while ((Ptr
>= Name
->Buffer
) && (*Ptr
!= L
'\\'))
282 /* Check for Wildcard */
283 if (FsRtlIsUnicodeCharacterWild(*Ptr
)) return TRUE
;
293 * @name FsRtlIsNameInExpression
296 * Check if the Name string is in the Expression string.
299 * The string in which we've to find Name. It can contain wildcards.
300 * If IgnoreCase is set to TRUE, this string MUST BE uppercase.
303 * The string to find. It cannot contain wildcards
306 * If set to TRUE, case will be ignore with upcasing both strings
309 * If not NULL, and if IgnoreCase is set to TRUE, it will be used to
310 * upcase the both strings
312 * @return TRUE if Name is in Expression, FALSE otherwise
314 * @remarks From Bo Branten's ntifs.h v12. This function should be
315 * rewritten to avoid recursion and better wildcard handling
316 * should be implemented (see FsRtlDoesNameContainWildCards).
321 FsRtlIsNameInExpression(IN PUNICODE_STRING Expression
,
322 IN PUNICODE_STRING Name
,
323 IN BOOLEAN IgnoreCase
,
324 IN PWCHAR UpcaseTable OPTIONAL
)
328 UNICODE_STRING IntName
;
330 if (IgnoreCase
&& !UpcaseTable
)
332 Status
= RtlUpcaseUnicodeString(&IntName
, Name
, TRUE
);
333 if (Status
!= STATUS_SUCCESS
)
335 ExRaiseStatus(Status
);
342 IntName
.Buffer
= NULL
;
345 Result
= FsRtlIsNameInExpressionPrivate(Expression
, Name
, IgnoreCase
, UpcaseTable
);
347 if (IntName
.Buffer
!= NULL
)
349 RtlFreeUnicodeString(&IntName
);