Implemented:
[reactos.git] / reactos / ntoskrnl / fs / name.c
1 /* $Id: name.c,v 1.13 2004/12/30 18:30:05 ion Exp $
2 *
3 * reactos/ntoskrnl/fs/name.c
4 *
5 */
6
7 #include <ntoskrnl.h>
8
9 /* FUNCTIONS ***************************************************************/
10
11 /**********************************************************************
12 * NAME EXPORTED
13 * FsRtlAreNamesEqual@16
14 *
15 * DESCRIPTION
16 *
17 * ARGUMENTS
18 *
19 * RETURN VALUE
20 *
21 * NOTE
22 * From Bo Branten's ntifs.h v25.
23 *
24 * @implemented
25 */
26 BOOLEAN STDCALL
27 FsRtlAreNamesEqual (IN PUNICODE_STRING Name1,
28 IN PUNICODE_STRING Name2,
29 IN BOOLEAN IgnoreCase,
30 IN PWCHAR UpcaseTable OPTIONAL)
31 {
32
33 UNICODE_STRING UpcaseName1;
34 UNICODE_STRING UpcaseName2;
35 BOOLEAN StringsAreEqual;
36
37 /* Well, first check their size */
38 if (Name1->Length != Name2->Length) {
39 /* Not equal! */
40 return FALSE;
41 }
42
43 /* Turn them into Upcase if we don't have a table */
44 if (IgnoreCase && !UpcaseTable) {
45 RtlUpcaseUnicodeString(&UpcaseName1, Name1, TRUE);
46 RtlUpcaseUnicodeString(&UpcaseName2, Name2, TRUE);
47 Name1 = &UpcaseName1;
48 Name2 = &UpcaseName2;
49
50 goto ManualCase;
51 }
52
53 /* Do a case-sensitive search */
54 if (!IgnoreCase) {
55
56 ManualCase:
57 /* Use a raw memory compare */
58 StringsAreEqual = RtlEqualMemory(Name1->Buffer,
59 Name2->Buffer,
60 Name1->Length);
61
62 /* Clear the strings if we need to */
63 if (IgnoreCase) {
64 RtlFreeUnicodeString(&UpcaseName1);
65 RtlFreeUnicodeString(&UpcaseName2);
66 }
67
68 /* Return the equality */
69 return StringsAreEqual;
70
71 } else {
72
73 /* Case in-sensitive search */
74
75 LONG i;
76
77 for (i = Name1->Length / sizeof(WCHAR) - 1; i >= 0; i--) {
78
79 if (UpcaseTable[Name1->Buffer[i]] != UpcaseTable[Name2->Buffer[i]]) {
80
81 /* Non-match found! */
82 return FALSE;
83 }
84 }
85
86 /* We finished the loop so we are equal */
87 return TRUE;
88 }
89 }
90
91
92 /**********************************************************************
93 * NAME EXPORTED
94 * FsRtlDissectName@16
95 *
96 * DESCRIPTION
97 * Dissects a given path name into first and remaining part.
98 *
99 * ARGUMENTS
100 * Name
101 * Unicode string to dissect.
102 *
103 * FirstPart
104 * Pointer to user supplied UNICODE_STRING, that will
105 * later point to the first part of the original name.
106 *
107 * RemainingPart
108 * Pointer to user supplied UNICODE_STRING, that will
109 * later point to the remaining part of the original name.
110 *
111 * RETURN VALUE
112 * None
113 *
114 * EXAMPLE
115 * Name: \test1\test2\test3
116 * FirstPart: test1
117 * RemainingPart: test2\test3
118 *
119 * @implemented
120 */
121 VOID STDCALL
122 FsRtlDissectName (IN UNICODE_STRING Name,
123 OUT PUNICODE_STRING FirstPart,
124 OUT PUNICODE_STRING RemainingPart)
125 {
126 USHORT NameOffset = 0;
127 USHORT NameLength = 0;
128 USHORT Length;
129
130 FirstPart->Length = 0;
131 FirstPart->MaximumLength = 0;
132 FirstPart->Buffer = NULL;
133
134 RemainingPart->Length = 0;
135 RemainingPart->MaximumLength = 0;
136 RemainingPart->Buffer = NULL;
137
138 if (Name.Length == 0)
139 return;
140
141 /* Skip leading backslash */
142 if (Name.Buffer[0] == L'\\')
143 NameOffset++;
144
145 Length = Name.Length / sizeof(WCHAR);
146
147 /* Search for next backslash or end-of-string */
148 while ((NameOffset + NameLength < Length) &&
149 (Name.Buffer[NameOffset + NameLength] != L'\\'))
150 {
151 NameLength++;
152 }
153
154 FirstPart->Length =
155 FirstPart->MaximumLength = NameLength * sizeof(WCHAR);
156 FirstPart->Buffer = &Name.Buffer[NameOffset];
157
158 NameOffset += NameLength + 1;
159 if (NameOffset < Length)
160 {
161 RemainingPart->Length = (Length - NameOffset) * sizeof(WCHAR);
162 RemainingPart->MaximumLength = (Length - NameOffset) * sizeof(WCHAR);
163 RemainingPart->Buffer = &Name.Buffer[NameOffset];
164 }
165 }
166
167
168 /**********************************************************************
169 * NAME EXPORTED
170 * FsRtlDoesNameContainWildCards@4
171 *
172 * DESCRIPTION
173 *
174 * ARGUMENTS
175 *
176 * RETURN VALUE
177 *
178 * NOTE
179 * From Bo Branten's ntifs.h v12.
180 *
181 * @implemented
182 */
183 BOOLEAN STDCALL
184 FsRtlDoesNameContainWildCards (IN PUNICODE_STRING Name)
185 {
186 PWCHAR Ptr;
187
188 /* Loop through every character */
189 if (Name->Length) {
190 for (Ptr = Name->Buffer + (Name->Length / sizeof(WCHAR))-1;
191 Ptr >= Name->Buffer && *Ptr != L'\\';Ptr--) {
192
193 /* Check for Wildcard */
194 if (FsRtlIsUnicodeCharacterWild(*Ptr)) {
195 return TRUE;
196 }
197 }
198 }
199
200 /* Nothing Found */
201 return FALSE;
202 }
203
204
205 /**********************************************************************
206 * NAME EXPORTED
207 * FsRtlIsNameInExpression@16
208 *
209 * DESCRIPTION
210 *
211 * ARGUMENTS
212 *
213 * RETURN VALUE
214 *
215 * NOTE
216 * From Bo Branten's ntifs.h v12. This function should be rewritten
217 * to avoid recursion and better wildcard handling should be
218 * implemented (see FsRtlDoesNameContainWildCards).
219 *
220 * @implemented
221 */
222 BOOLEAN STDCALL
223 FsRtlIsNameInExpression (IN PUNICODE_STRING Expression,
224 IN PUNICODE_STRING Name,
225 IN BOOLEAN IgnoreCase,
226 IN PWCHAR UpcaseTable OPTIONAL)
227 {
228 USHORT ExpressionPosition, NamePosition;
229 UNICODE_STRING TempExpression, TempName;
230
231 ExpressionPosition = 0;
232 NamePosition = 0;
233 while (ExpressionPosition < (Expression->Length / sizeof(WCHAR)) &&
234 NamePosition < (Name->Length / sizeof(WCHAR)))
235 {
236 if (Expression->Buffer[ExpressionPosition] == L'*')
237 {
238 ExpressionPosition++;
239 if (ExpressionPosition == (Expression->Length / sizeof(WCHAR)))
240 {
241 return TRUE;
242 }
243 while (NamePosition < (Name->Length / sizeof(WCHAR)))
244 {
245 TempExpression.Length =
246 TempExpression.MaximumLength =
247 Expression->Length - (ExpressionPosition * sizeof(WCHAR));
248 TempExpression.Buffer = Expression->Buffer + ExpressionPosition;
249 TempName.Length =
250 TempName.MaximumLength =
251 Name->Length - (NamePosition * sizeof(WCHAR));
252 TempName.Buffer = Name->Buffer + NamePosition;
253 /* FIXME: Rewrite to get rid of recursion */
254 if (FsRtlIsNameInExpression(&TempExpression, &TempName,
255 IgnoreCase, UpcaseTable))
256 {
257 return TRUE;
258 }
259 NamePosition++;
260 }
261 }
262 else
263 {
264 /* FIXME: Take UpcaseTable into account! */
265 if (Expression->Buffer[ExpressionPosition] == L'?' ||
266 (IgnoreCase &&
267 RtlUpcaseUnicodeChar(Expression->Buffer[ExpressionPosition]) ==
268 RtlUpcaseUnicodeChar(Name->Buffer[NamePosition])) ||
269 (!IgnoreCase &&
270 Expression->Buffer[ExpressionPosition] ==
271 Name->Buffer[NamePosition]))
272 {
273 NamePosition++;
274 ExpressionPosition++;
275 }
276 else
277 {
278 return FALSE;
279 }
280 }
281 }
282
283 /* Handle matching of "f0_*.*" expression to "f0_000" file name. */
284 if (ExpressionPosition < (Expression->Length / sizeof(WCHAR)) &&
285 Expression->Buffer[ExpressionPosition] == L'.')
286 {
287 while (ExpressionPosition < (Expression->Length / sizeof(WCHAR)) &&
288 (Expression->Buffer[ExpressionPosition] == L'.' ||
289 Expression->Buffer[ExpressionPosition] == L'*' ||
290 Expression->Buffer[ExpressionPosition] == L'?'))
291 {
292 ExpressionPosition++;
293 }
294 }
295
296 if (ExpressionPosition == (Expression->Length / sizeof(WCHAR)) &&
297 NamePosition == (Name->Length / sizeof(WCHAR)))
298 {
299 return TRUE;
300 }
301
302 return FALSE;
303 }
304
305 /* EOF */