Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenname.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Kernel 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: ntoskrnl/fsrtl/name.c 00005 * PURPOSE: Provides name parsing and other support routines for FSDs 00006 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 00007 * Filip Navara (navaraf@reactos.org) 00008 * Pierre Schweitzer (pierre.schweitzer@reactos.org) 00009 * Aleksey Bragin (aleksey@reactos.org) 00010 */ 00011 00012 /* INCLUDES ******************************************************************/ 00013 00014 #include <ntoskrnl.h> 00015 #define NDEBUG 00016 #include <debug.h> 00017 00018 /* PRIVATE FUNCTIONS *********************************************************/ 00019 BOOLEAN 00020 NTAPI 00021 FsRtlIsNameInExpressionPrivate(IN PUNICODE_STRING Expression, 00022 IN PUNICODE_STRING Name, 00023 IN BOOLEAN IgnoreCase, 00024 IN PWCHAR UpcaseTable OPTIONAL) 00025 { 00026 SHORT StarFound = -1; 00027 PUSHORT BackTracking = NULL; 00028 UNICODE_STRING IntExpression; 00029 USHORT ExpressionPosition = 0, NamePosition = 0, MatchingChars; 00030 PAGED_CODE(); 00031 00032 /* Check if we were given strings at all */ 00033 if (!Name->Length || !Expression->Length) 00034 { 00035 /* Return TRUE if both strings are empty, otherwise FALSE */ 00036 if (Name->Length == 0 && Expression->Length == 0) 00037 return TRUE; 00038 else 00039 return FALSE; 00040 } 00041 00042 /* Check for a shortcut: just one wildcard */ 00043 if (Expression->Length == sizeof(WCHAR)) 00044 { 00045 if (Expression->Buffer[0] == L'*') 00046 return TRUE; 00047 } 00048 00049 ASSERT(!IgnoreCase || UpcaseTable); 00050 00051 /* Another shortcut, wildcard followed by some string */ 00052 if (Expression->Buffer[0] == L'*') 00053 { 00054 /* Copy Expression to our local variable */ 00055 IntExpression = *Expression; 00056 00057 /* Skip the first char */ 00058 IntExpression.Buffer++; 00059 IntExpression.Length -= sizeof(WCHAR); 00060 00061 /* Continue only if the rest of the expression does NOT contain 00062 any more wildcards */ 00063 if (!FsRtlDoesNameContainWildCards(&IntExpression)) 00064 { 00065 /* Check for a degenerate case */ 00066 if (Name->Length < (Expression->Length - sizeof(WCHAR))) 00067 return FALSE; 00068 00069 /* Calculate position */ 00070 NamePosition = (Name->Length - IntExpression.Length) / sizeof(WCHAR); 00071 00072 /* Compare */ 00073 if (!IgnoreCase) 00074 { 00075 /* We can just do a byte compare */ 00076 return RtlEqualMemory(IntExpression.Buffer, 00077 Name->Buffer + NamePosition, 00078 IntExpression.Length); 00079 } 00080 else 00081 { 00082 /* Not so easy, need to upcase and check char by char */ 00083 for (ExpressionPosition = 0; ExpressionPosition < (IntExpression.Length / sizeof(WCHAR)); ExpressionPosition++) 00084 { 00085 /* Assert that expression is already upcased! */ 00086 ASSERT(IntExpression.Buffer[ExpressionPosition] == UpcaseTable[IntExpression.Buffer[ExpressionPosition]]); 00087 00088 /* Now compare upcased name char with expression */ 00089 if (UpcaseTable[Name->Buffer[NamePosition + ExpressionPosition]] != 00090 IntExpression.Buffer[ExpressionPosition]) 00091 { 00092 return FALSE; 00093 } 00094 } 00095 00096 /* It matches */ 00097 return TRUE; 00098 } 00099 } 00100 } 00101 00102 while (NamePosition < Name->Length / sizeof(WCHAR) && ExpressionPosition < Expression->Length / sizeof(WCHAR)) 00103 { 00104 /* Basic check to test if chars are equal */ 00105 if ((Expression->Buffer[ExpressionPosition] == (IgnoreCase ? UpcaseTable[Name->Buffer[NamePosition]] : Name->Buffer[NamePosition]))) 00106 { 00107 NamePosition++; 00108 ExpressionPosition++; 00109 } 00110 /* Check cases that eat one char */ 00111 else if (Expression->Buffer[ExpressionPosition] == L'?' || (Expression->Buffer[ExpressionPosition] == DOS_QM) || 00112 (Expression->Buffer[ExpressionPosition] == DOS_DOT && Name->Buffer[NamePosition] == L'.')) 00113 { 00114 NamePosition++; 00115 ExpressionPosition++; 00116 } 00117 /* Test star */ 00118 else if (Expression->Buffer[ExpressionPosition] == L'*') 00119 { 00120 /* Skip contigous stars */ 00121 while (ExpressionPosition + 1 < Expression->Length / sizeof(WCHAR) && Expression->Buffer[ExpressionPosition + 1] == L'*') 00122 { 00123 ExpressionPosition++; 00124 } 00125 00126 /* Save star position */ 00127 if (!BackTracking) 00128 { 00129 BackTracking = ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE, 00130 (Expression->Length / sizeof(WCHAR)) * sizeof(USHORT), 00131 'nrSF'); 00132 } 00133 BackTracking[++StarFound] = ExpressionPosition++; 00134 00135 /* If star is at the end, then eat all rest and leave */ 00136 if (ExpressionPosition == Expression->Length / sizeof(WCHAR)) 00137 { 00138 NamePosition = Name->Length / sizeof(WCHAR); 00139 break; 00140 } 00141 else if (Expression->Buffer[ExpressionPosition] != L'?') 00142 { 00143 NamePosition++; 00144 } 00145 } 00146 /* Check DOS_STAR */ 00147 else if (Expression->Buffer[ExpressionPosition] == DOS_STAR) 00148 { 00149 MatchingChars = NamePosition; 00150 while (MatchingChars < Name->Length / sizeof(WCHAR)) 00151 { 00152 if (Name->Buffer[MatchingChars] == L'.') 00153 { 00154 NamePosition = MatchingChars; 00155 } 00156 MatchingChars++; 00157 } 00158 ExpressionPosition++; 00159 } 00160 /* If nothing match, try to backtrack */ 00161 else if (StarFound >= 0) 00162 { 00163 ExpressionPosition = BackTracking[StarFound--]; 00164 } 00165 /* Otherwise, fail */ 00166 else 00167 { 00168 break; 00169 } 00170 00171 /* Under certain circumstances, expression is over, but name isn't 00172 * and we can backtrack, then, backtrack */ 00173 if (ExpressionPosition == Expression->Length / sizeof(WCHAR) && 00174 NamePosition != Name->Length / sizeof(WCHAR) && 00175 StarFound >= 0) 00176 { 00177 ExpressionPosition = BackTracking[StarFound--]; 00178 } 00179 } 00180 if (ExpressionPosition + 1 == Expression->Length / sizeof(WCHAR) && NamePosition == Name->Length / sizeof(WCHAR) && 00181 Expression->Buffer[ExpressionPosition] == DOS_DOT) 00182 { 00183 ExpressionPosition++; 00184 } 00185 00186 if (BackTracking) 00187 { 00188 ExFreePoolWithTag(BackTracking, 'nrSF'); 00189 } 00190 00191 return (ExpressionPosition == Expression->Length / sizeof(WCHAR) && NamePosition == Name->Length / sizeof(WCHAR)); 00192 } 00193 00194 /* PUBLIC FUNCTIONS **********************************************************/ 00195 00196 /*++ 00197 * @name FsRtlAreNamesEqual 00198 * @implemented 00199 * 00200 * Compare two strings to check if they match 00201 * 00202 * @param Name1 00203 * First unicode string to compare 00204 * 00205 * @param Name2 00206 * Second unicode string to compare 00207 * 00208 * @param IgnoreCase 00209 * If TRUE, Case will be ignored when comparing strings 00210 * 00211 * @param UpcaseTable 00212 * Table for upcase letters. If NULL is given, system one will be used 00213 * 00214 * @return TRUE if the strings are equal 00215 * 00216 * @remarks From Bo Branten's ntifs.h v25. 00217 * 00218 *--*/ 00219 BOOLEAN 00220 NTAPI 00221 FsRtlAreNamesEqual(IN PCUNICODE_STRING Name1, 00222 IN PCUNICODE_STRING Name2, 00223 IN BOOLEAN IgnoreCase, 00224 IN PCWCH UpcaseTable OPTIONAL) 00225 { 00226 UNICODE_STRING UpcaseName1; 00227 UNICODE_STRING UpcaseName2; 00228 BOOLEAN StringsAreEqual, MemoryAllocated = FALSE; 00229 USHORT i; 00230 NTSTATUS Status; 00231 PAGED_CODE(); 00232 00233 /* Well, first check their size */ 00234 if (Name1->Length != Name2->Length) return FALSE; 00235 00236 /* Check if the caller didn't give an upcase table */ 00237 if ((IgnoreCase) && !(UpcaseTable)) 00238 { 00239 /* Upcase the string ourselves */ 00240 Status = RtlUpcaseUnicodeString(&UpcaseName1, Name1, TRUE); 00241 if (!NT_SUCCESS(Status)) RtlRaiseStatus(Status); 00242 00243 /* Upcase the second string too */ 00244 RtlUpcaseUnicodeString(&UpcaseName2, Name2, TRUE); 00245 Name1 = &UpcaseName1; 00246 Name2 = &UpcaseName2; 00247 00248 /* Make sure we go through the path below, but free the strings */ 00249 IgnoreCase = FALSE; 00250 MemoryAllocated = TRUE; 00251 } 00252 00253 /* Do a case-sensitive search */ 00254 if (!IgnoreCase) 00255 { 00256 /* Use a raw memory compare */ 00257 StringsAreEqual = RtlEqualMemory(Name1->Buffer, 00258 Name2->Buffer, 00259 Name1->Length); 00260 00261 /* Check if we allocated strings */ 00262 if (MemoryAllocated) 00263 { 00264 /* Free them */ 00265 RtlFreeUnicodeString(&UpcaseName1); 00266 RtlFreeUnicodeString(&UpcaseName2); 00267 } 00268 00269 /* Return the equality */ 00270 return StringsAreEqual; 00271 } 00272 else 00273 { 00274 /* Case in-sensitive search */ 00275 for (i = 0; i < Name1->Length / sizeof(WCHAR); i++) 00276 { 00277 /* Check if the character matches */ 00278 if (UpcaseTable[Name1->Buffer[i]] != UpcaseTable[Name2->Buffer[i]]) 00279 { 00280 /* Non-match found! */ 00281 return FALSE; 00282 } 00283 } 00284 00285 /* We finished the loop so we are equal */ 00286 return TRUE; 00287 } 00288 } 00289 00290 /*++ 00291 * @name FsRtlDissectName 00292 * @implemented 00293 * 00294 * Dissects a given path name into first and remaining part. 00295 * 00296 * @param Name 00297 * Unicode string to dissect. 00298 * 00299 * @param FirstPart 00300 * Pointer to user supplied UNICODE_STRING, that will later point 00301 * to the first part of the original name. 00302 * 00303 * @param RemainingPart 00304 * Pointer to user supplied UNICODE_STRING, that will later point 00305 * to the remaining part of the original name. 00306 * 00307 * @return None 00308 * 00309 * @remarks Example: 00310 * Name: \test1\test2\test3 00311 * FirstPart: test1 00312 * RemainingPart: test2\test3 00313 * 00314 *--*/ 00315 VOID 00316 NTAPI 00317 FsRtlDissectName(IN UNICODE_STRING Name, 00318 OUT PUNICODE_STRING FirstPart, 00319 OUT PUNICODE_STRING RemainingPart) 00320 { 00321 USHORT FirstPosition, i; 00322 USHORT SkipFirstSlash = 0; 00323 PAGED_CODE(); 00324 00325 /* Zero the strings before continuing */ 00326 RtlZeroMemory(FirstPart, sizeof(UNICODE_STRING)); 00327 RtlZeroMemory(RemainingPart, sizeof(UNICODE_STRING)); 00328 00329 /* Just quit if the string is empty */ 00330 if (!Name.Length) return; 00331 00332 /* Find first backslash */ 00333 FirstPosition = Name.Length / sizeof(WCHAR) ; 00334 for (i = 0; i < Name.Length / sizeof(WCHAR); i++) 00335 { 00336 /* If we found one... */ 00337 if (Name.Buffer[i] == L'\\') 00338 { 00339 /* If it begins string, just notice it and continue */ 00340 if (i == 0) 00341 { 00342 SkipFirstSlash = 1; 00343 } 00344 else 00345 { 00346 /* Else, save its position and break out of the loop */ 00347 FirstPosition = i; 00348 break; 00349 } 00350 } 00351 } 00352 00353 /* Set up the first result string */ 00354 FirstPart->Buffer = Name.Buffer + SkipFirstSlash; 00355 FirstPart->Length = (FirstPosition - SkipFirstSlash) * sizeof(WCHAR); 00356 FirstPart->MaximumLength = FirstPart->Length; 00357 00358 /* And second one, if necessary */ 00359 if (FirstPosition < (Name.Length / sizeof(WCHAR))) 00360 { 00361 RemainingPart->Buffer = Name.Buffer + FirstPosition + 1; 00362 RemainingPart->Length = Name.Length - (FirstPosition + 1) * sizeof(WCHAR); 00363 RemainingPart->MaximumLength = RemainingPart->Length; 00364 } 00365 } 00366 00367 /*++ 00368 * @name FsRtlDoesNameContainWildCards 00369 * @implemented 00370 * 00371 * Checks if the given string contains WildCards 00372 * 00373 * @param Name 00374 * Pointer to a UNICODE_STRING containing Name to examine 00375 * 00376 * @return TRUE if Name contains wildcards, FALSE otherwise 00377 * 00378 * @remarks From Bo Branten's ntifs.h v12. 00379 * 00380 *--*/ 00381 BOOLEAN 00382 NTAPI 00383 FsRtlDoesNameContainWildCards(IN PUNICODE_STRING Name) 00384 { 00385 PWCHAR Ptr; 00386 PAGED_CODE(); 00387 00388 /* Loop through every character */ 00389 if (Name->Length) 00390 { 00391 Ptr = Name->Buffer + (Name->Length / sizeof(WCHAR)) - 1; 00392 while ((Ptr >= Name->Buffer) && (*Ptr != L'\\')) 00393 { 00394 /* Check for Wildcard */ 00395 if (FsRtlIsUnicodeCharacterWild(*Ptr)) return TRUE; 00396 Ptr--; 00397 } 00398 } 00399 00400 /* Nothing Found */ 00401 return FALSE; 00402 } 00403 00404 /*++ 00405 * @name FsRtlIsNameInExpression 00406 * @implemented 00407 * 00408 * Check if the Name string is in the Expression string. 00409 * 00410 * @param Expression 00411 * The string in which we've to find Name. It can contain wildcards. 00412 * If IgnoreCase is set to TRUE, this string MUST BE uppercase. 00413 * 00414 * @param Name 00415 * The string to find. It cannot contain wildcards 00416 * 00417 * @param IgnoreCase 00418 * If set to TRUE, case will be ignore with upcasing both strings 00419 * 00420 * @param UpcaseTable 00421 * If not NULL, and if IgnoreCase is set to TRUE, it will be used to 00422 * upcase the both strings 00423 * 00424 * @return TRUE if Name is in Expression, FALSE otherwise 00425 * 00426 * @remarks From Bo Branten's ntifs.h v12. This function should be 00427 * rewritten to avoid recursion and better wildcard handling 00428 * should be implemented (see FsRtlDoesNameContainWildCards). 00429 * 00430 *--*/ 00431 BOOLEAN 00432 NTAPI 00433 FsRtlIsNameInExpression(IN PUNICODE_STRING Expression, 00434 IN PUNICODE_STRING Name, 00435 IN BOOLEAN IgnoreCase, 00436 IN PWCHAR UpcaseTable OPTIONAL) 00437 { 00438 BOOLEAN Result; 00439 NTSTATUS Status; 00440 UNICODE_STRING IntName; 00441 00442 if (IgnoreCase && !UpcaseTable) 00443 { 00444 Status = RtlUpcaseUnicodeString(&IntName, Name, TRUE); 00445 if (!NT_SUCCESS(Status)) 00446 { 00447 ExRaiseStatus(Status); 00448 } 00449 Name = &IntName; 00450 IgnoreCase = FALSE; 00451 } 00452 else 00453 { 00454 IntName.Buffer = NULL; 00455 } 00456 00457 Result = FsRtlIsNameInExpressionPrivate(Expression, Name, IgnoreCase, UpcaseTable); 00458 00459 if (IntName.Buffer != NULL) 00460 { 00461 RtlFreeUnicodeString(&IntName); 00462 } 00463 00464 return Result; 00465 } Generated on Sun May 27 2012 04:26:34 for ReactOS by
1.7.6.1
|