Fix splitting of cells (noticed by Hartmut).
[reactos.git] / reactos / ntoskrnl / fs / name.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/fs/name.c
5 * PURPOSE: Name and DBCS Name Validation and Dissection Functions.
6 *
7 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
8 * Eric Kohl
9 * Filip Navara
10 */
11
12 /* INCLUDES ****************************************************************/
13
14 #include <ntoskrnl.h>
15 #define NDEBUG
16 #include <internal/debug.h>
17
18 /* GLOBALS *******************************************************************/
19
20 static UCHAR LegalAnsiCharacterArray[] =
21 {
22 0, /* CTRL+@, 0x00 */
23 0, /* CTRL+A, 0x01 */
24 0, /* CTRL+B, 0x02 */
25 0, /* CTRL+C, 0x03 */
26 0, /* CTRL+D, 0x04 */
27 0, /* CTRL+E, 0x05 */
28 0, /* CTRL+F, 0x06 */
29 0, /* CTRL+G, 0x07 */
30 0, /* CTRL+H, 0x08 */
31 0, /* CTRL+I, 0x09 */
32 0, /* CTRL+J, 0x0a */
33 0, /* CTRL+K, 0x0b */
34 0, /* CTRL+L, 0x0c */
35 0, /* CTRL+M, 0x0d */
36 0, /* CTRL+N, 0x0e */
37 0, /* CTRL+O, 0x0f */
38 0, /* CTRL+P, 0x10 */
39 0, /* CTRL+Q, 0x11 */
40 0, /* CTRL+R, 0x12 */
41 0, /* CTRL+S, 0x13 */
42 0, /* CTRL+T, 0x14 */
43 0, /* CTRL+U, 0x15 */
44 0, /* CTRL+V, 0x16 */
45 0, /* CTRL+W, 0x17 */
46 0, /* CTRL+X, 0x18 */
47 0, /* CTRL+Y, 0x19 */
48 0, /* CTRL+Z, 0x1a */
49 0, /* CTRL+[, 0x1b */
50 0, /* CTRL+\, 0x1c */
51 0, /* CTRL+], 0x1d */
52 0, /* CTRL+^, 0x1e */
53 0, /* CTRL+_, 0x1f */
54 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* ` ', 0x20 */
55 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `!', 0x21 */
56 FSRTL_WILD_CHARACTER, /* `"', 0x22 */
57 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `#', 0x23 */
58 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `$', 0x24 */
59 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `%', 0x25 */
60 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `&', 0x26 */
61 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `'', 0x27 */
62 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `(', 0x28 */
63 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `)', 0x29 */
64 FSRTL_WILD_CHARACTER, /* `*', 0x2a */
65 FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `+', 0x2b */
66 FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `,', 0x2c */
67 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `-', 0x2d */
68 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `.', 0x2e */
69 0, /* `/', 0x2f */
70 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `0', 0x30 */
71 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `1', 0x31 */
72 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `2', 0x32 */
73 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `3', 0x33 */
74 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `4', 0x34 */
75 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `5', 0x35 */
76 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `6', 0x36 */
77 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `7', 0x37 */
78 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `8', 0x38 */
79 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `9', 0x39 */
80 FSRTL_NTFS_LEGAL, /* `:', 0x3a */
81 FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `;', 0x3b */
82 FSRTL_WILD_CHARACTER, /* `<', 0x3c */
83 FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `=', 0x3d */
84 FSRTL_WILD_CHARACTER, /* `>', 0x3e */
85 FSRTL_WILD_CHARACTER, /* `?', 0x3f */
86 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `@', 0x40 */
87 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `A', 0x41 */
88 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `B', 0x42 */
89 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `C', 0x43 */
90 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `D', 0x44 */
91 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `E', 0x45 */
92 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `F', 0x46 */
93 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `G', 0x47 */
94 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `H', 0x48 */
95 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `I', 0x49 */
96 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `J', 0x4a */
97 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `K', 0x4b */
98 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `L', 0x4c */
99 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `M', 0x4d */
100 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `N', 0x4e */
101 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `O', 0x4f */
102 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `P', 0x50 */
103 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `Q', 0x51 */
104 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `R', 0x52 */
105 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `S', 0x53 */
106 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `T', 0x54 */
107 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `U', 0x55 */
108 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `V', 0x56 */
109 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `W', 0x57 */
110 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `X', 0x58 */
111 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `Y', 0x59 */
112 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `Z', 0x5a */
113 FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `[', 0x5b */
114 0, /* `\', 0x5c */
115 FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `]', 0x5d */
116 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `^', 0x5e */
117 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `_', 0x5f */
118 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* ``', 0x60 */
119 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `a', 0x61 */
120 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `b', 0x62 */
121 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `c', 0x63 */
122 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `d', 0x64 */
123 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `e', 0x65 */
124 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `f', 0x66 */
125 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `g', 0x67 */
126 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `h', 0x68 */
127 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `i', 0x69 */
128 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `j', 0x6a */
129 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `k', 0x6b */
130 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `l', 0x6c */
131 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `m', 0x6d */
132 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `n', 0x6e */
133 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `o', 0x6f */
134 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `p', 0x70 */
135 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `q', 0x71 */
136 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `r', 0x72 */
137 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `s', 0x73 */
138 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `t', 0x74 */
139 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `u', 0x75 */
140 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `v', 0x76 */
141 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `w', 0x77 */
142 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `x', 0x78 */
143 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `y', 0x79 */
144 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `z', 0x7a */
145 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `{', 0x7b */
146 0, /* `|', 0x7c */
147 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `}', 0x7d */
148 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `~', 0x7e */
149 FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL /* 0x7f */
150 };
151
152 PUCHAR FsRtlLegalAnsiCharacterArray = LegalAnsiCharacterArray;
153
154 /* FUNCTIONS *****************************************************************/
155
156 /*
157 * NAME EXPORTED
158 * FsRtlAreNamesEqual@16
159 *
160 * DESCRIPTION
161 *
162 * ARGUMENTS
163 *
164 * RETURN VALUE
165 *
166 * NOTE
167 * From Bo Branten's ntifs.h v25.
168 *
169 * @implemented
170 */
171 BOOLEAN
172 STDCALL
173 FsRtlAreNamesEqual(IN PUNICODE_STRING Name1,
174 IN PUNICODE_STRING Name2,
175 IN BOOLEAN IgnoreCase,
176 IN PWCHAR UpcaseTable OPTIONAL)
177 {
178 UNICODE_STRING UpcaseName1;
179 UNICODE_STRING UpcaseName2;
180 BOOLEAN StringsAreEqual;
181
182 /* Well, first check their size */
183 if (Name1->Length != Name2->Length) {
184 /* Not equal! */
185 return FALSE;
186 }
187
188 /* Turn them into Upcase if we don't have a table */
189 if (IgnoreCase && !UpcaseTable) {
190 RtlUpcaseUnicodeString(&UpcaseName1, Name1, TRUE);
191 RtlUpcaseUnicodeString(&UpcaseName2, Name2, TRUE);
192 Name1 = &UpcaseName1;
193 Name2 = &UpcaseName2;
194
195 goto ManualCase;
196 }
197
198 /* Do a case-sensitive search */
199 if (!IgnoreCase) {
200
201 ManualCase:
202 /* Use a raw memory compare */
203 StringsAreEqual = RtlEqualMemory(Name1->Buffer,
204 Name2->Buffer,
205 Name1->Length);
206
207 /* Clear the strings if we need to */
208 if (IgnoreCase) {
209 RtlFreeUnicodeString(&UpcaseName1);
210 RtlFreeUnicodeString(&UpcaseName2);
211 }
212
213 /* Return the equality */
214 return StringsAreEqual;
215
216 } else {
217
218 /* Case in-sensitive search */
219
220 LONG i;
221
222 for (i = Name1->Length / sizeof(WCHAR) - 1; i >= 0; i--) {
223
224 if (UpcaseTable[Name1->Buffer[i]] != UpcaseTable[Name2->Buffer[i]]) {
225
226 /* Non-match found! */
227 return FALSE;
228 }
229 }
230
231 /* We finished the loop so we are equal */
232 return TRUE;
233 }
234 }
235
236 /*
237 * NAME EXPORTED
238 * FsRtlDissectDbcs@16
239 *
240 * Dissects a given path name into first and remaining part.
241 *
242 * ARGUMENTS
243 * Name
244 * ANSI string to dissect.
245 *
246 * FirstPart
247 * Pointer to user supplied ANSI_STRING, that will
248 * later point to the first part of the original name.
249 *
250 * RemainingPart
251 * Pointer to user supplied ANSI_STRING, that will
252 * later point to the remaining part of the original name.
253 *
254 * RETURN VALUE
255 * None
256 *
257 * EXAMPLE
258 * Name: \test1\test2\test3
259 * FirstPart: test1
260 * RemainingPart: test2\test3
261 *
262 * @implemented
263 */
264 VOID
265 STDCALL
266 FsRtlDissectDbcs(IN ANSI_STRING Name,
267 OUT PANSI_STRING FirstPart,
268 OUT PANSI_STRING RemainingPart)
269 {
270 ULONG i;
271 ULONG FirstLoop;
272
273 /* Initialize the Outputs */
274 RtlZeroMemory(&FirstPart, sizeof(ANSI_STRING));
275 RtlZeroMemory(&RemainingPart, sizeof(ANSI_STRING));
276
277 /* Bail out if empty */
278 if (!Name.Length) return;
279
280 /* Ignore backslash */
281 if (Name.Buffer[0] == '\\') {
282 i = 1;
283 } else {
284 i = 0;
285 }
286
287 /* Loop until we find a backslash */
288 for (FirstLoop = i;i < Name.Length;i++) {
289 if (Name.Buffer[i] != '\\') break;
290 if (FsRtlIsLeadDbcsCharacter(Name.Buffer[i])) i++;
291 }
292
293 /* Now we have the First Part */
294 FirstPart->Length = (i-FirstLoop);
295 FirstPart->MaximumLength = FirstPart->Length; /* +2?? */
296 FirstPart->Buffer = &Name.Buffer[FirstLoop];
297
298 /* Make the second part if something is still left */
299 if (i<Name.Length) {
300 RemainingPart->Length = (Name.Length - (i+1));
301 RemainingPart->MaximumLength = RemainingPart->Length; /* +2?? */
302 RemainingPart->Buffer = &Name.Buffer[i+1];
303 }
304
305 return;
306 }
307
308 /*
309 * NAME EXPORTED
310 * FsRtlDissectName@16
311 *
312 * DESCRIPTION
313 * Dissects a given path name into first and remaining part.
314 *
315 * ARGUMENTS
316 * Name
317 * Unicode string to dissect.
318 *
319 * FirstPart
320 * Pointer to user supplied UNICODE_STRING, that will
321 * later point to the first part of the original name.
322 *
323 * RemainingPart
324 * Pointer to user supplied UNICODE_STRING, that will
325 * later point to the remaining part of the original name.
326 *
327 * RETURN VALUE
328 * None
329 *
330 * EXAMPLE
331 * Name: \test1\test2\test3
332 * FirstPart: test1
333 * RemainingPart: test2\test3
334 *
335 * @implemented
336 */
337 VOID
338 STDCALL
339 FsRtlDissectName(IN UNICODE_STRING Name,
340 OUT PUNICODE_STRING FirstPart,
341 OUT PUNICODE_STRING RemainingPart)
342 {
343 USHORT NameOffset = 0;
344 USHORT NameLength = 0;
345 USHORT Length;
346
347 FirstPart->Length = 0;
348 FirstPart->MaximumLength = 0;
349 FirstPart->Buffer = NULL;
350
351 RemainingPart->Length = 0;
352 RemainingPart->MaximumLength = 0;
353 RemainingPart->Buffer = NULL;
354
355 if (Name.Length == 0)
356 return;
357
358 /* Skip leading backslash */
359 if (Name.Buffer[0] == L'\\')
360 NameOffset++;
361
362 Length = Name.Length / sizeof(WCHAR);
363
364 /* Search for next backslash or end-of-string */
365 while ((NameOffset + NameLength < Length) &&
366 (Name.Buffer[NameOffset + NameLength] != L'\\'))
367 {
368 NameLength++;
369 }
370
371 FirstPart->Length =
372 FirstPart->MaximumLength = NameLength * sizeof(WCHAR);
373 FirstPart->Buffer = &Name.Buffer[NameOffset];
374
375 NameOffset += NameLength + 1;
376 if (NameOffset < Length)
377 {
378 RemainingPart->Length = (Length - NameOffset) * sizeof(WCHAR);
379 RemainingPart->MaximumLength = (Length - NameOffset) * sizeof(WCHAR);
380 RemainingPart->Buffer = &Name.Buffer[NameOffset];
381 }
382 }
383
384 /*
385 * NAME EXPORTED
386 * FsRtlDoesDbcsContainWildCards@4
387 *
388 * DESCRIPTION
389 *
390 * ARGUMENTS
391 *
392 * RETURN VALUE
393 *
394 * @implemented
395 */
396 BOOLEAN
397 STDCALL
398 FsRtlDoesDbcsContainWildCards(IN PANSI_STRING Name)
399 {
400 ULONG i;
401
402 /* Check every character */
403 for (i=0;i < Name->Length;i++) {
404
405 /* First make sure it's not the Lead DBCS */
406 if (FsRtlIsLeadDbcsCharacter(Name->Buffer[i])) {
407 i++;
408 } else if (FsRtlIsAnsiCharacterWild(Name->Buffer[i])) {
409 /* Now return if it has a Wilcard */
410 return TRUE;
411 }
412 }
413
414 /* We didn't return above...so none found */
415 return FALSE;
416 }
417
418 /*
419 * NAME EXPORTED
420 * FsRtlDoesNameContainWildCards@4
421 *
422 * DESCRIPTION
423 *
424 * ARGUMENTS
425 *
426 * RETURN VALUE
427 *
428 * NOTE
429 * From Bo Branten's ntifs.h v12.
430 *
431 * @implemented
432 */
433 BOOLEAN
434 STDCALL
435 FsRtlDoesNameContainWildCards(IN PUNICODE_STRING Name)
436 {
437 PWCHAR Ptr;
438
439 /* Loop through every character */
440 if (Name->Length) {
441 for (Ptr = Name->Buffer + (Name->Length / sizeof(WCHAR))-1;
442 Ptr >= Name->Buffer && *Ptr != L'\\';Ptr--) {
443
444 /* Check for Wildcard */
445 if (FsRtlIsUnicodeCharacterWild(*Ptr)) {
446 return TRUE;
447 }
448 }
449 }
450
451 /* Nothing Found */
452 return FALSE;
453 }
454
455 /*
456 * NAME EXPORTED
457 * FsRtlIsDbcsInExpression@8
458 *
459 * DESCRIPTION
460 *
461 * ARGUMENTS
462 *
463 * RETURN VALUE
464 *
465 * @unimplemented
466 */
467 BOOLEAN
468 STDCALL
469 FsRtlIsDbcsInExpression(IN PANSI_STRING Expression,
470 IN PANSI_STRING Name)
471 {
472 return FALSE;
473 }
474
475 /*
476 * NAME EXPORTED
477 * FsRtlIsFatDbcsLegal@20
478 *
479 * DESCRIPTION
480 *
481 * ARGUMENTS
482 *
483 * RETURN VALUE
484 *
485 * @unimplemented
486 */
487 BOOLEAN
488 STDCALL
489 FsRtlIsFatDbcsLegal(IN ANSI_STRING DbcsName,
490 IN BOOLEAN WildCardsPermissible,
491 IN BOOLEAN PathNamePermissible,
492 IN BOOLEAN LeadingBackslashPermissible)
493 {
494 return FALSE;
495 }
496
497 /*
498 * NAME EXPORTED
499 * FsRtlIsHpfsDbcsLegal@20
500 *
501 * DESCRIPTION
502 *
503 * ARGUMENTS
504 *
505 * RETURN VALUE
506 *
507 * @unimplemented
508 */
509 BOOLEAN
510 STDCALL
511 FsRtlIsHpfsDbcsLegal(IN ANSI_STRING DbcsName,
512 IN BOOLEAN WildCardsPermissible,
513 IN BOOLEAN PathNamePermissible,
514 IN BOOLEAN LeadingBackslashPermissible)
515 {
516 return FALSE;
517 }
518
519 /*
520 * NAME EXPORTED
521 * FsRtlIsNameInExpression@16
522 *
523 * DESCRIPTION
524 *
525 * ARGUMENTS
526 *
527 * RETURN VALUE
528 *
529 * NOTE
530 * From Bo Branten's ntifs.h v12. This function should be rewritten
531 * to avoid recursion and better wildcard handling should be
532 * implemented (see FsRtlDoesNameContainWildCards).
533 *
534 * @implemented
535 */
536 BOOLEAN
537 STDCALL
538 FsRtlIsNameInExpression(IN PUNICODE_STRING Expression,
539 IN PUNICODE_STRING Name,
540 IN BOOLEAN IgnoreCase,
541 IN PWCHAR UpcaseTable OPTIONAL)
542 {
543 USHORT ExpressionPosition, NamePosition;
544 UNICODE_STRING TempExpression, TempName;
545
546 ExpressionPosition = 0;
547 NamePosition = 0;
548 while (ExpressionPosition < (Expression->Length / sizeof(WCHAR)) &&
549 NamePosition < (Name->Length / sizeof(WCHAR)))
550 {
551 if (Expression->Buffer[ExpressionPosition] == L'*')
552 {
553 ExpressionPosition++;
554 if (ExpressionPosition == (Expression->Length / sizeof(WCHAR)))
555 {
556 return TRUE;
557 }
558 while (NamePosition < (Name->Length / sizeof(WCHAR)))
559 {
560 TempExpression.Length =
561 TempExpression.MaximumLength =
562 Expression->Length - (ExpressionPosition * sizeof(WCHAR));
563 TempExpression.Buffer = Expression->Buffer + ExpressionPosition;
564 TempName.Length =
565 TempName.MaximumLength =
566 Name->Length - (NamePosition * sizeof(WCHAR));
567 TempName.Buffer = Name->Buffer + NamePosition;
568 /* FIXME: Rewrite to get rid of recursion */
569 if (FsRtlIsNameInExpression(&TempExpression, &TempName,
570 IgnoreCase, UpcaseTable))
571 {
572 return TRUE;
573 }
574 NamePosition++;
575 }
576 }
577 else
578 {
579 /* FIXME: Take UpcaseTable into account! */
580 if (Expression->Buffer[ExpressionPosition] == L'?' ||
581 (IgnoreCase &&
582 RtlUpcaseUnicodeChar(Expression->Buffer[ExpressionPosition]) ==
583 RtlUpcaseUnicodeChar(Name->Buffer[NamePosition])) ||
584 (!IgnoreCase &&
585 Expression->Buffer[ExpressionPosition] ==
586 Name->Buffer[NamePosition]))
587 {
588 NamePosition++;
589 ExpressionPosition++;
590 }
591 else
592 {
593 return FALSE;
594 }
595 }
596 }
597
598 /* Handle matching of "f0_*.*" expression to "f0_000" file name. */
599 if (ExpressionPosition < (Expression->Length / sizeof(WCHAR)) &&
600 Expression->Buffer[ExpressionPosition] == L'.')
601 {
602 while (ExpressionPosition < (Expression->Length / sizeof(WCHAR)) &&
603 (Expression->Buffer[ExpressionPosition] == L'.' ||
604 Expression->Buffer[ExpressionPosition] == L'*' ||
605 Expression->Buffer[ExpressionPosition] == L'?'))
606 {
607 ExpressionPosition++;
608 }
609 }
610
611 if (ExpressionPosition == (Expression->Length / sizeof(WCHAR)) &&
612 NamePosition == (Name->Length / sizeof(WCHAR)))
613 {
614 return TRUE;
615 }
616
617 return FALSE;
618 }
619
620 /* EOF */