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.
7 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
12 /* INCLUDES ****************************************************************/
16 #include <internal/debug.h>
18 /* GLOBALS *******************************************************************/
20 static UCHAR LegalAnsiCharacterArray
[] =
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 */
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 */
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 */
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 */
152 PUCHAR EXPORTED FsRtlLegalAnsiCharacterArray
= LegalAnsiCharacterArray
;
154 /* FUNCTIONS *****************************************************************/
158 * FsRtlAreNamesEqual@16
167 * From Bo Branten's ntifs.h v25.
173 FsRtlAreNamesEqual(IN PUNICODE_STRING Name1
,
174 IN PUNICODE_STRING Name2
,
175 IN BOOLEAN IgnoreCase
,
176 IN PWCHAR UpcaseTable OPTIONAL
)
178 UNICODE_STRING UpcaseName1
;
179 UNICODE_STRING UpcaseName2
;
180 BOOLEAN StringsAreEqual
;
182 /* Well, first check their size */
183 if (Name1
->Length
!= Name2
->Length
) {
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
;
198 /* Do a case-sensitive search */
202 /* Use a raw memory compare */
203 StringsAreEqual
= RtlEqualMemory(Name1
->Buffer
,
207 /* Clear the strings if we need to */
209 RtlFreeUnicodeString(&UpcaseName1
);
210 RtlFreeUnicodeString(&UpcaseName2
);
213 /* Return the equality */
214 return StringsAreEqual
;
218 /* Case in-sensitive search */
222 for (i
= Name1
->Length
/ sizeof(WCHAR
) - 1; i
>= 0; i
--) {
224 if (UpcaseTable
[Name1
->Buffer
[i
]] != UpcaseTable
[Name2
->Buffer
[i
]]) {
226 /* Non-match found! */
231 /* We finished the loop so we are equal */
238 * FsRtlDissectDbcs@16
240 * Dissects a given path name into first and remaining part.
244 * ANSI string to dissect.
247 * Pointer to user supplied ANSI_STRING, that will
248 * later point to the first part of the original name.
251 * Pointer to user supplied ANSI_STRING, that will
252 * later point to the remaining part of the original name.
258 * Name: \test1\test2\test3
260 * RemainingPart: test2\test3
266 FsRtlDissectDbcs(IN ANSI_STRING Name
,
267 OUT PANSI_STRING FirstPart
,
268 OUT PANSI_STRING RemainingPart
)
273 /* Initialize the Outputs */
274 RtlZeroMemory(&FirstPart
, sizeof(ANSI_STRING
));
275 RtlZeroMemory(&RemainingPart
, sizeof(ANSI_STRING
));
277 /* Bail out if empty */
278 if (!Name
.Length
) return;
280 /* Ignore backslash */
281 if (Name
.Buffer
[0] == '\\') {
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
++;
293 /* Now we have the First Part */
294 FirstPart
->Length
= (i
-FirstLoop
);
295 FirstPart
->MaximumLength
= FirstPart
->Length
; /* +2?? */
296 FirstPart
->Buffer
= &Name
.Buffer
[FirstLoop
];
298 /* Make the second part if something is still left */
300 RemainingPart
->Length
= (Name
.Length
- (i
+1));
301 RemainingPart
->MaximumLength
= RemainingPart
->Length
; /* +2?? */
302 RemainingPart
->Buffer
= &Name
.Buffer
[i
+1];
310 * FsRtlDissectName@16
313 * Dissects a given path name into first and remaining part.
317 * Unicode string to dissect.
320 * Pointer to user supplied UNICODE_STRING, that will
321 * later point to the first part of the original name.
324 * Pointer to user supplied UNICODE_STRING, that will
325 * later point to the remaining part of the original name.
331 * Name: \test1\test2\test3
333 * RemainingPart: test2\test3
339 FsRtlDissectName(IN UNICODE_STRING Name
,
340 OUT PUNICODE_STRING FirstPart
,
341 OUT PUNICODE_STRING RemainingPart
)
343 USHORT NameOffset
= 0;
344 USHORT NameLength
= 0;
347 FirstPart
->Length
= 0;
348 FirstPart
->MaximumLength
= 0;
349 FirstPart
->Buffer
= NULL
;
351 RemainingPart
->Length
= 0;
352 RemainingPart
->MaximumLength
= 0;
353 RemainingPart
->Buffer
= NULL
;
355 if (Name
.Length
== 0)
358 /* Skip leading backslash */
359 if (Name
.Buffer
[0] == L
'\\')
362 Length
= Name
.Length
/ sizeof(WCHAR
);
364 /* Search for next backslash or end-of-string */
365 while ((NameOffset
+ NameLength
< Length
) &&
366 (Name
.Buffer
[NameOffset
+ NameLength
] != L
'\\'))
372 FirstPart
->MaximumLength
= NameLength
* sizeof(WCHAR
);
373 FirstPart
->Buffer
= &Name
.Buffer
[NameOffset
];
375 NameOffset
+= NameLength
+ 1;
376 if (NameOffset
< Length
)
378 RemainingPart
->Length
= (Length
- NameOffset
) * sizeof(WCHAR
);
379 RemainingPart
->MaximumLength
= (Length
- NameOffset
) * sizeof(WCHAR
);
380 RemainingPart
->Buffer
= &Name
.Buffer
[NameOffset
];
386 * FsRtlDoesDbcsContainWildCards@4
398 FsRtlDoesDbcsContainWildCards(IN PANSI_STRING Name
)
402 /* Check every character */
403 for (i
=0;i
< Name
->Length
;i
++) {
405 /* First make sure it's not the Lead DBCS */
406 if (FsRtlIsLeadDbcsCharacter(Name
->Buffer
[i
])) {
408 } else if (FsRtlIsAnsiCharacterWild(Name
->Buffer
[i
])) {
409 /* Now return if it has a Wilcard */
414 /* We didn't return above...so none found */
420 * FsRtlDoesNameContainWildCards@4
429 * From Bo Branten's ntifs.h v12.
435 FsRtlDoesNameContainWildCards(IN PUNICODE_STRING Name
)
439 /* Loop through every character */
441 for (Ptr
= Name
->Buffer
+ (Name
->Length
/ sizeof(WCHAR
))-1;
442 Ptr
>= Name
->Buffer
&& *Ptr
!= L
'\\';Ptr
--) {
444 /* Check for Wildcard */
445 if (FsRtlIsUnicodeCharacterWild(*Ptr
)) {
457 * FsRtlIsDbcsInExpression@8
469 FsRtlIsDbcsInExpression(IN PANSI_STRING Expression
,
470 IN PANSI_STRING Name
)
477 * FsRtlIsFatDbcsLegal@20
489 FsRtlIsFatDbcsLegal(IN ANSI_STRING DbcsName
,
490 IN BOOLEAN WildCardsPermissible
,
491 IN BOOLEAN PathNamePermissible
,
492 IN BOOLEAN LeadingBackslashPermissible
)
499 * FsRtlIsHpfsDbcsLegal@20
511 FsRtlIsHpfsDbcsLegal(IN ANSI_STRING DbcsName
,
512 IN BOOLEAN WildCardsPermissible
,
513 IN BOOLEAN PathNamePermissible
,
514 IN BOOLEAN LeadingBackslashPermissible
)
521 * FsRtlIsNameInExpression@16
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).
538 FsRtlIsNameInExpression(IN PUNICODE_STRING Expression
,
539 IN PUNICODE_STRING Name
,
540 IN BOOLEAN IgnoreCase
,
541 IN PWCHAR UpcaseTable OPTIONAL
)
543 USHORT ExpressionPosition
, NamePosition
;
544 UNICODE_STRING TempExpression
, TempName
;
546 ExpressionPosition
= 0;
548 while (ExpressionPosition
< (Expression
->Length
/ sizeof(WCHAR
)) &&
549 NamePosition
< (Name
->Length
/ sizeof(WCHAR
)))
551 if (Expression
->Buffer
[ExpressionPosition
] == L
'*')
553 ExpressionPosition
++;
554 if (ExpressionPosition
== (Expression
->Length
/ sizeof(WCHAR
)))
558 while (NamePosition
< (Name
->Length
/ sizeof(WCHAR
)))
560 TempExpression
.Length
=
561 TempExpression
.MaximumLength
=
562 Expression
->Length
- (ExpressionPosition
* sizeof(WCHAR
));
563 TempExpression
.Buffer
= Expression
->Buffer
+ ExpressionPosition
;
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
))
579 /* FIXME: Take UpcaseTable into account! */
580 if (Expression
->Buffer
[ExpressionPosition
] == L
'?' ||
582 RtlUpcaseUnicodeChar(Expression
->Buffer
[ExpressionPosition
]) ==
583 RtlUpcaseUnicodeChar(Name
->Buffer
[NamePosition
])) ||
585 Expression
->Buffer
[ExpressionPosition
] ==
586 Name
->Buffer
[NamePosition
]))
589 ExpressionPosition
++;
598 /* Handle matching of "f0_*.*" expression to "f0_000" file name. */
599 if (ExpressionPosition
< (Expression
->Length
/ sizeof(WCHAR
)) &&
600 Expression
->Buffer
[ExpressionPosition
] == L
'.')
602 while (ExpressionPosition
< (Expression
->Length
/ sizeof(WCHAR
)) &&
603 (Expression
->Buffer
[ExpressionPosition
] == L
'.' ||
604 Expression
->Buffer
[ExpressionPosition
] == L
'*' ||
605 Expression
->Buffer
[ExpressionPosition
] == L
'?'))
607 ExpressionPosition
++;
611 if (ExpressionPosition
== (Expression
->Length
/ sizeof(WCHAR
)) &&
612 NamePosition
== (Name
->Length
/ sizeof(WCHAR
)))