ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

name.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.