Bring back ext2 code from branch
[reactos.git] / reactos / ntoskrnl / fsrtl / name.c
1 /*
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 */
9
10 /* INCLUDES ******************************************************************/
11
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <debug.h>
15
16 /* PUBLIC FUNCTIONS **********************************************************/
17
18 /*++
19 * @name FsRtlAreNamesEqual
20 * @implemented
21 *
22 * FILLME
23 *
24 * @param Name1
25 * FILLME
26 *
27 * @param Name2
28 * FILLME
29 *
30 * @param IgnoreCase
31 * FILLME
32 *
33 * @param UpcaseTable
34 * FILLME
35 *
36 * @return None
37 *
38 * @remarks From Bo Branten's ntifs.h v25.
39 *
40 *--*/
41 BOOLEAN
42 NTAPI
43 FsRtlAreNamesEqual(IN PCUNICODE_STRING Name1,
44 IN PCUNICODE_STRING Name2,
45 IN BOOLEAN IgnoreCase,
46 IN PCWCH UpcaseTable OPTIONAL)
47 {
48 UNICODE_STRING UpcaseName1;
49 UNICODE_STRING UpcaseName2;
50 BOOLEAN StringsAreEqual, MemoryAllocated = FALSE;
51 ULONG i;
52 NTSTATUS Status;
53
54 /* Well, first check their size */
55 if (Name1->Length != Name2->Length) return FALSE;
56
57 /* Check if the caller didn't give an upcase table */
58 if ((IgnoreCase) && !(UpcaseTable))
59 {
60 /* Upcase the string ourselves */
61 Status = RtlUpcaseUnicodeString(&UpcaseName1, Name1, TRUE);
62 if (!NT_SUCCESS(Status)) RtlRaiseStatus(Status);
63
64 /* Upcase the second string too */
65 RtlUpcaseUnicodeString(&UpcaseName2, Name2, TRUE);
66 Name1 = &UpcaseName1;
67 Name2 = &UpcaseName2;
68
69 /* Make sure we go through the path below, but free the strings */
70 IgnoreCase = FALSE;
71 MemoryAllocated = TRUE;
72 }
73
74 /* Do a case-sensitive search */
75 if (!IgnoreCase)
76 {
77 /* Use a raw memory compare */
78 StringsAreEqual = RtlEqualMemory(Name1->Buffer,
79 Name2->Buffer,
80 Name1->Length);
81
82 /* Check if we allocated strings */
83 if (MemoryAllocated)
84 {
85 /* Free them */
86 RtlFreeUnicodeString(&UpcaseName1);
87 RtlFreeUnicodeString(&UpcaseName2);
88 }
89
90 /* Return the equality */
91 return StringsAreEqual;
92 }
93 else
94 {
95 /* Case in-sensitive search */
96 for (i = 0; i < Name1->Length / sizeof(WCHAR); i++)
97 {
98 /* Check if the character matches */
99 if (UpcaseTable[Name1->Buffer[i]] != UpcaseTable[Name2->Buffer[i]])
100 {
101 /* Non-match found! */
102 return FALSE;
103 }
104 }
105
106 /* We finished the loop so we are equal */
107 return TRUE;
108 }
109 }
110
111 /*++
112 * @name FsRtlDissectName
113 * @implemented
114 *
115 * Dissects a given path name into first and remaining part.
116 *
117 * @param Name
118 * Unicode string to dissect.
119 *
120 * @param FirstPart
121 * Pointer to user supplied UNICODE_STRING, that will later point
122 * to the first part of the original name.
123 *
124 * @param RemainingPart
125 * Pointer to user supplied UNICODE_STRING, that will later point
126 * to the remaining part of the original name.
127 *
128 * @return None
129 *
130 * @remarks Example:
131 * Name: \test1\test2\test3
132 * FirstPart: test1
133 * RemainingPart: test2\test3
134 *
135 *--*/
136 VOID
137 NTAPI
138 FsRtlDissectName(IN UNICODE_STRING Name,
139 OUT PUNICODE_STRING FirstPart,
140 OUT PUNICODE_STRING RemainingPart)
141 {
142 KEBUGCHECK(0);
143 }
144
145 /*++
146 * @name FsRtlDoesNameContainWildCards
147 * @implemented
148 *
149 * FILLME
150 *
151 * @param Name
152 * Pointer to a UNICODE_STRING containing Name to examine
153 *
154 * @return TRUE if Name contains wildcards, FALSE otherwise
155 *
156 * @remarks From Bo Branten's ntifs.h v12.
157 *
158 *--*/
159 BOOLEAN
160 NTAPI
161 FsRtlDoesNameContainWildCards(IN PUNICODE_STRING Name)
162 {
163 PWCHAR Ptr;
164
165 /* Loop through every character */
166 if (Name->Length)
167 {
168 Ptr = Name->Buffer + (Name->Length / sizeof(WCHAR)) - 1;
169 while ((Ptr >= Name->Buffer) && (*Ptr != L'\\'))
170 {
171 /* Check for Wildcard */
172 if (FsRtlIsUnicodeCharacterWild(*Ptr)) return TRUE;
173 Ptr--;
174 }
175 }
176
177 /* Nothing Found */
178 return FALSE;
179 }
180
181 /*++
182 * @name FsRtlIsNameInExpression
183 * @implemented
184 *
185 * FILLME
186 *
187 * @param DeviceObject
188 * FILLME
189 *
190 * @param Irp
191 * FILLME
192 *
193 * @return TRUE if Name is in Expression, FALSE otherwise
194 *
195 * @remarks From Bo Branten's ntifs.h v12. This function should be
196 * rewritten to avoid recursion and better wildcard handling
197 * should be implemented (see FsRtlDoesNameContainWildCards).
198 *
199 *--*/
200 BOOLEAN
201 NTAPI
202 FsRtlIsNameInExpression(IN PUNICODE_STRING Expression,
203 IN PUNICODE_STRING Name,
204 IN BOOLEAN IgnoreCase,
205 IN PWCHAR UpcaseTable OPTIONAL)
206 {
207 USHORT ExpressionPosition, NamePosition;
208 UNICODE_STRING TempExpression, TempName;
209
210 ExpressionPosition = 0;
211 NamePosition = 0;
212 while (ExpressionPosition < (Expression->Length / sizeof(WCHAR)) &&
213 NamePosition < (Name->Length / sizeof(WCHAR)))
214 {
215 if (Expression->Buffer[ExpressionPosition] == L'*')
216 {
217 ExpressionPosition++;
218 if (ExpressionPosition == (Expression->Length / sizeof(WCHAR)))
219 {
220 return TRUE;
221 }
222 while (NamePosition < (Name->Length / sizeof(WCHAR)))
223 {
224 TempExpression.Length =
225 TempExpression.MaximumLength =
226 Expression->Length - (ExpressionPosition * sizeof(WCHAR));
227 TempExpression.Buffer = Expression->Buffer + ExpressionPosition;
228 TempName.Length =
229 TempName.MaximumLength =
230 Name->Length - (NamePosition * sizeof(WCHAR));
231 TempName.Buffer = Name->Buffer + NamePosition;
232 /* FIXME: Rewrite to get rid of recursion */
233 if (FsRtlIsNameInExpression(&TempExpression, &TempName,
234 IgnoreCase, UpcaseTable))
235 {
236 return TRUE;
237 }
238 NamePosition++;
239 }
240 }
241 else
242 {
243 /* FIXME: Take UpcaseTable into account! */
244 if (Expression->Buffer[ExpressionPosition] == L'?' ||
245 (IgnoreCase &&
246 RtlUpcaseUnicodeChar(Expression->Buffer[ExpressionPosition]) ==
247 RtlUpcaseUnicodeChar(Name->Buffer[NamePosition])) ||
248 (!IgnoreCase &&
249 Expression->Buffer[ExpressionPosition] ==
250 Name->Buffer[NamePosition]))
251 {
252 NamePosition++;
253 ExpressionPosition++;
254 }
255 else
256 {
257 return FALSE;
258 }
259 }
260 }
261
262 /* Handle matching of "f0_*.*" expression to "f0_000" file name. */
263 if (ExpressionPosition < (Expression->Length / sizeof(WCHAR)) &&
264 Expression->Buffer[ExpressionPosition] == L'.')
265 {
266 while (ExpressionPosition < (Expression->Length / sizeof(WCHAR)) &&
267 (Expression->Buffer[ExpressionPosition] == L'.' ||
268 Expression->Buffer[ExpressionPosition] == L'*' ||
269 Expression->Buffer[ExpressionPosition] == L'?'))
270 {
271 ExpressionPosition++;
272 }
273 }
274
275 if (ExpressionPosition == (Expression->Length / sizeof(WCHAR)) &&
276 NamePosition == (Name->Length / sizeof(WCHAR)))
277 {
278 return TRUE;
279 }
280
281 return FALSE;
282 }
283