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)
10 /* INCLUDES ******************************************************************/
16 /* PUBLIC FUNCTIONS **********************************************************/
19 * @name FsRtlAreNamesEqual
38 * @remarks From Bo Branten's ntifs.h v25.
43 FsRtlAreNamesEqual(IN PCUNICODE_STRING Name1
,
44 IN PCUNICODE_STRING Name2
,
45 IN BOOLEAN IgnoreCase
,
46 IN PCWCH UpcaseTable OPTIONAL
)
48 UNICODE_STRING UpcaseName1
;
49 UNICODE_STRING UpcaseName2
;
50 BOOLEAN StringsAreEqual
, MemoryAllocated
= FALSE
;
54 /* Well, first check their size */
55 if (Name1
->Length
!= Name2
->Length
) return FALSE
;
57 /* Check if the caller didn't give an upcase table */
58 if ((IgnoreCase
) && !(UpcaseTable
))
60 /* Upcase the string ourselves */
61 Status
= RtlUpcaseUnicodeString(&UpcaseName1
, Name1
, TRUE
);
62 if (!NT_SUCCESS(Status
)) RtlRaiseStatus(Status
);
64 /* Upcase the second string too */
65 RtlUpcaseUnicodeString(&UpcaseName2
, Name2
, TRUE
);
69 /* Make sure we go through the path below, but free the strings */
71 MemoryAllocated
= TRUE
;
74 /* Do a case-sensitive search */
77 /* Use a raw memory compare */
78 StringsAreEqual
= RtlEqualMemory(Name1
->Buffer
,
82 /* Check if we allocated strings */
86 RtlFreeUnicodeString(&UpcaseName1
);
87 RtlFreeUnicodeString(&UpcaseName2
);
90 /* Return the equality */
91 return StringsAreEqual
;
95 /* Case in-sensitive search */
96 for (i
= 0; i
< Name1
->Length
/ sizeof(WCHAR
); i
++)
98 /* Check if the character matches */
99 if (UpcaseTable
[Name1
->Buffer
[i
]] != UpcaseTable
[Name2
->Buffer
[i
]])
101 /* Non-match found! */
106 /* We finished the loop so we are equal */
112 * @name FsRtlDissectName
115 * Dissects a given path name into first and remaining part.
118 * Unicode string to dissect.
121 * Pointer to user supplied UNICODE_STRING, that will later point
122 * to the first part of the original name.
124 * @param RemainingPart
125 * Pointer to user supplied UNICODE_STRING, that will later point
126 * to the remaining part of the original name.
131 * Name: \test1\test2\test3
133 * RemainingPart: test2\test3
138 FsRtlDissectName(IN UNICODE_STRING Name
,
139 OUT PUNICODE_STRING FirstPart
,
140 OUT PUNICODE_STRING RemainingPart
)
142 ULONG FirstPosition
, i
;
143 ULONG SkipFirstSlash
= 0;
145 /* Zero the strings before continuing */
146 RtlZeroMemory(FirstPart
, sizeof(UNICODE_STRING
));
147 RtlZeroMemory(RemainingPart
, sizeof(UNICODE_STRING
));
149 /* Just quit if the string is empty */
150 if (!Name
.Length
) return;
152 /* Find first backslash */
153 FirstPosition
= Name
.Length
/ sizeof(WCHAR
) ;
154 for (i
= 0; i
< Name
.Length
/ sizeof(WCHAR
); i
++)
156 /* If we found one... */
157 if (Name
.Buffer
[i
] == L
'\\')
159 /* If it begins string, just notice it and continue */
166 /* Else, save its position and break out of the loop */
173 /* Set up the first result string */
174 FirstPart
->Buffer
= Name
.Buffer
+ SkipFirstSlash
;
175 FirstPart
->Length
= (FirstPosition
- SkipFirstSlash
) * sizeof(WCHAR
);
176 FirstPart
->MaximumLength
= FirstPart
->Length
;
178 /* And second one, if necessary */
179 if (FirstPosition
< (Name
.Length
/ sizeof(WCHAR
)))
181 RemainingPart
->Buffer
= Name
.Buffer
+ FirstPosition
+ 1;
182 RemainingPart
->Length
= Name
.Length
- (FirstPosition
+ 1) * sizeof(WCHAR
);
183 RemainingPart
->MaximumLength
= RemainingPart
->Length
;
188 * @name FsRtlDoesNameContainWildCards
194 * Pointer to a UNICODE_STRING containing Name to examine
196 * @return TRUE if Name contains wildcards, FALSE otherwise
198 * @remarks From Bo Branten's ntifs.h v12.
203 FsRtlDoesNameContainWildCards(IN PUNICODE_STRING Name
)
207 /* Loop through every character */
210 Ptr
= Name
->Buffer
+ (Name
->Length
/ sizeof(WCHAR
)) - 1;
211 while ((Ptr
>= Name
->Buffer
) && (*Ptr
!= L
'\\'))
213 /* Check for Wildcard */
214 if (FsRtlIsUnicodeCharacterWild(*Ptr
)) return TRUE
;
224 * @name FsRtlIsNameInExpression
229 * @param DeviceObject
235 * @return TRUE if Name is in Expression, FALSE otherwise
237 * @remarks From Bo Branten's ntifs.h v12. This function should be
238 * rewritten to avoid recursion and better wildcard handling
239 * should be implemented (see FsRtlDoesNameContainWildCards).
244 FsRtlIsNameInExpression(IN PUNICODE_STRING Expression
,
245 IN PUNICODE_STRING Name
,
246 IN BOOLEAN IgnoreCase
,
247 IN PWCHAR UpcaseTable OPTIONAL
)
249 USHORT ExpressionPosition
, NamePosition
;
250 UNICODE_STRING TempExpression
, TempName
;
252 ExpressionPosition
= 0;
254 while (ExpressionPosition
< (Expression
->Length
/ sizeof(WCHAR
)) &&
255 NamePosition
< (Name
->Length
/ sizeof(WCHAR
)))
257 if (Expression
->Buffer
[ExpressionPosition
] == L
'*')
259 ExpressionPosition
++;
260 if (ExpressionPosition
== (Expression
->Length
/ sizeof(WCHAR
)))
264 while (NamePosition
< (Name
->Length
/ sizeof(WCHAR
)))
266 TempExpression
.Length
=
267 TempExpression
.MaximumLength
=
268 Expression
->Length
- (ExpressionPosition
* sizeof(WCHAR
));
269 TempExpression
.Buffer
= Expression
->Buffer
+ ExpressionPosition
;
271 TempName
.MaximumLength
=
272 Name
->Length
- (NamePosition
* sizeof(WCHAR
));
273 TempName
.Buffer
= Name
->Buffer
+ NamePosition
;
274 /* FIXME: Rewrite to get rid of recursion */
275 if (FsRtlIsNameInExpression(&TempExpression
, &TempName
,
276 IgnoreCase
, UpcaseTable
))
285 /* FIXME: Take UpcaseTable into account! */
286 if (Expression
->Buffer
[ExpressionPosition
] == L
'?' ||
288 RtlUpcaseUnicodeChar(Expression
->Buffer
[ExpressionPosition
]) ==
289 RtlUpcaseUnicodeChar(Name
->Buffer
[NamePosition
])) ||
291 Expression
->Buffer
[ExpressionPosition
] ==
292 Name
->Buffer
[NamePosition
]))
295 ExpressionPosition
++;
304 /* Handle matching of "f0_*.*" expression to "f0_000" file name. */
305 if (ExpressionPosition
< (Expression
->Length
/ sizeof(WCHAR
)) &&
306 Expression
->Buffer
[ExpressionPosition
] == L
'.')
308 while (ExpressionPosition
< (Expression
->Length
/ sizeof(WCHAR
)) &&
309 (Expression
->Buffer
[ExpressionPosition
] == L
'.' ||
310 Expression
->Buffer
[ExpressionPosition
] == L
'*' ||
311 Expression
->Buffer
[ExpressionPosition
] == L
'?'))
313 ExpressionPosition
++;
317 if (ExpressionPosition
== (Expression
->Length
/ sizeof(WCHAR
)) &&
318 NamePosition
== (Name
->Length
/ sizeof(WCHAR
)))