[NTOSKRNL]
[reactos.git] / reactos / ntoskrnl / fsrtl / name.c
index 17f5f88..0712a2b 100644 (file)
@@ -5,6 +5,7 @@
  * PURPOSE:         Provides name parsing and other support routines for FSDs
  * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
  *                  Filip Navara (navaraf@reactos.org)
+ *                  Pierre Schweitzer (pierre.schweitzer@reactos.org) 
  */
 
 /* INCLUDES ******************************************************************/
 #define NDEBUG
 #include <debug.h>
 
+/* PRIVATE FUNCTIONS *********************************************************/
+BOOLEAN
+NTAPI
+FsRtlIsNameInExpressionPrivate(IN PUNICODE_STRING Expression,
+                               IN PUNICODE_STRING Name,
+                               IN BOOLEAN IgnoreCase,
+                               IN PWCHAR UpcaseTable OPTIONAL)
+{
+    USHORT ExpressionPosition = 0, NamePosition = 0, MatchingChars, StarFound = MAXUSHORT;
+    PAGED_CODE();
+
+    ASSERT(!IgnoreCase || UpcaseTable);
+
+    while (NamePosition < Name->Length / sizeof(WCHAR) && ExpressionPosition < Expression->Length / sizeof(WCHAR))
+    {
+        if ((Expression->Buffer[ExpressionPosition] == (IgnoreCase ? UpcaseTable[Name->Buffer[NamePosition]] : Name->Buffer[NamePosition])))
+        {
+            NamePosition++;
+            ExpressionPosition++;
+        }
+        else if (Expression->Buffer[ExpressionPosition] == L'?' || (Expression->Buffer[ExpressionPosition] == DOS_QM) ||
+                 (Expression->Buffer[ExpressionPosition] == DOS_DOT && Name->Buffer[NamePosition] == L'.'))
+        {
+            NamePosition++;
+            ExpressionPosition++;
+            StarFound = MAXUSHORT;
+        }
+        else if (Expression->Buffer[ExpressionPosition] == L'*')
+        {
+            StarFound = ExpressionPosition++;
+            if (StarFound < (Expression->Length / sizeof(WCHAR) - 1))
+            {
+                while ((IgnoreCase ? UpcaseTable[Name->Buffer[NamePosition]] : Name->Buffer[NamePosition]) != Expression->Buffer[ExpressionPosition] &&
+                       NamePosition < Name->Length / sizeof(WCHAR))
+                {
+                    NamePosition++;
+                }
+            }
+            else
+            {
+                NamePosition = Name->Length / sizeof(WCHAR);
+            }
+        }
+        else if (Expression->Buffer[ExpressionPosition] == DOS_STAR)
+        {
+            StarFound = MAXUSHORT;
+            MatchingChars = NamePosition;
+            while (MatchingChars < Name->Length / sizeof(WCHAR))
+            {
+                if (Name->Buffer[MatchingChars] == L'.')
+                {
+                    NamePosition = MatchingChars;
+                }
+                MatchingChars++;
+            }
+            ExpressionPosition++;
+        }
+        else if (StarFound != MAXUSHORT)
+        {
+            ExpressionPosition = StarFound + 1;
+            while ((IgnoreCase ? UpcaseTable[Name->Buffer[NamePosition]] : Name->Buffer[NamePosition]) != Expression->Buffer[ExpressionPosition] &&
+                       NamePosition < Name->Length / sizeof(WCHAR))
+            {
+                NamePosition++;
+            }
+        }
+        else
+        {
+            NamePosition = Name->Length / sizeof(WCHAR);
+        }
+    }
+    if (ExpressionPosition + 1 == Expression->Length / sizeof(WCHAR) && NamePosition == Name->Length / sizeof(WCHAR) &&
+        Expression->Buffer[ExpressionPosition] == DOS_DOT)
+    {
+        ExpressionPosition++;
+    }
+
+    return (ExpressionPosition == Expression->Length / sizeof(WCHAR) && NamePosition == Name->Length / sizeof(WCHAR));
+}
+
 /* PUBLIC FUNCTIONS **********************************************************/
 
 /*++
  * @name FsRtlAreNamesEqual
  * @implemented
  *
- * FILLME
+ * Compare two strings to check if they match
  *
  * @param Name1
- *        FILLME
+ *        First unicode string to compare
  *
  * @param Name2
- *        FILLME
+ *        Second unicode string to compare
  *
  * @param IgnoreCase
- *        FILLME
+ *        If TRUE, Case will be ignored when comparing strings
  *
  * @param UpcaseTable
- *        FILLME
+ *        Table for upcase letters. If NULL is given, system one will be used
  *
- * @return None
+ * @return TRUE if the strings are equal
  *
  * @remarks From Bo Branten's ntifs.h v25.
  *
@@ -50,6 +131,7 @@ FsRtlAreNamesEqual(IN PCUNICODE_STRING Name1,
     BOOLEAN StringsAreEqual, MemoryAllocated = FALSE;
     ULONG i;
     NTSTATUS Status;
+    PAGED_CODE();
 
     /* Well, first check their size */
     if (Name1->Length != Name2->Length) return FALSE;
@@ -141,6 +223,7 @@ FsRtlDissectName(IN UNICODE_STRING Name,
 {
     ULONG FirstPosition, i;
     ULONG SkipFirstSlash = 0;
+    PAGED_CODE();
 
     /* Zero the strings before continuing */
     RtlZeroMemory(FirstPart, sizeof(UNICODE_STRING));
@@ -188,7 +271,7 @@ FsRtlDissectName(IN UNICODE_STRING Name,
  * @name FsRtlDoesNameContainWildCards
  * @implemented
  *
- * FILLME
+ * Checks if the given string contains WildCards
  *
  * @param Name
  *        Pointer to a UNICODE_STRING containing Name to examine
@@ -203,6 +286,7 @@ NTAPI
 FsRtlDoesNameContainWildCards(IN PUNICODE_STRING Name)
 {
     PWCHAR Ptr;
+    PAGED_CODE();
 
     /* Loop through every character */
     if (Name->Length)
@@ -224,13 +308,21 @@ FsRtlDoesNameContainWildCards(IN PUNICODE_STRING Name)
  * @name FsRtlIsNameInExpression
  * @implemented
  *
- * FILLME
+ * Check if the Name string is in the Expression string.
+ *
+ * @param Expression
+ *        The string in which we've to find Name. It can contain wildcards.
+ *        If IgnoreCase is set to TRUE, this string MUST BE uppercase. 
  *
- * @param DeviceObject
- *        FILLME
+ * @param Name
+ *        The string to find. It cannot contain wildcards
  *
- * @param Irp
- *        FILLME
+ * @param IgnoreCase
+ *        If set to TRUE, case will be ignore with upcasing both strings
+ *
+ * @param UpcaseTable
+ *        If not NULL, and if IgnoreCase is set to TRUE, it will be used to
+ *        upcase the both strings 
  *
  * @return TRUE if Name is in Expression, FALSE otherwise
  *
@@ -246,80 +338,31 @@ FsRtlIsNameInExpression(IN PUNICODE_STRING Expression,
                         IN BOOLEAN IgnoreCase,
                         IN PWCHAR UpcaseTable OPTIONAL)
 {
-    USHORT ExpressionPosition, NamePosition;
-    UNICODE_STRING TempExpression, TempName;
+    BOOLEAN Result;
+    NTSTATUS Status;
+    UNICODE_STRING IntName;
 
-    ExpressionPosition = 0;
-    NamePosition = 0;
-    while (ExpressionPosition < (Expression->Length / sizeof(WCHAR)) &&
-        NamePosition < (Name->Length / sizeof(WCHAR)))
+    if (IgnoreCase && !UpcaseTable)
     {
-        if (Expression->Buffer[ExpressionPosition] == L'*')
-        {
-            ExpressionPosition++;
-            if (ExpressionPosition == (Expression->Length / sizeof(WCHAR)))
-            {
-                return TRUE;
-            }
-            while (NamePosition < (Name->Length / sizeof(WCHAR)))
-            {
-                TempExpression.Length =
-                    TempExpression.MaximumLength =
-                    Expression->Length - (ExpressionPosition * sizeof(WCHAR));
-                TempExpression.Buffer = Expression->Buffer + ExpressionPosition;
-                TempName.Length =
-                    TempName.MaximumLength =
-                    Name->Length - (NamePosition * sizeof(WCHAR));
-                TempName.Buffer = Name->Buffer + NamePosition;
-                /* FIXME: Rewrite to get rid of recursion */
-                if (FsRtlIsNameInExpression(&TempExpression, &TempName,
-                    IgnoreCase, UpcaseTable))
-                {
-                    return TRUE;
-                }
-                NamePosition++;
-            }
-        }
-        else
+        Status = RtlUpcaseUnicodeString(&IntName, Name, TRUE);
+        if (Status != STATUS_SUCCESS)
         {
-            /* FIXME: Take UpcaseTable into account! */
-            if (Expression->Buffer[ExpressionPosition] == L'?' ||
-                (IgnoreCase &&
-                RtlUpcaseUnicodeChar(Expression->Buffer[ExpressionPosition]) ==
-                RtlUpcaseUnicodeChar(Name->Buffer[NamePosition])) ||
-                (!IgnoreCase &&
-                Expression->Buffer[ExpressionPosition] ==
-                Name->Buffer[NamePosition]))
-            {
-                NamePosition++;
-                ExpressionPosition++;
-            }
-            else
-            {
-                return FALSE;
-            }
+            ExRaiseStatus(Status);
         }
+        Name = &IntName;
+        IgnoreCase = FALSE;
     }
-
-    /* Handle matching of "f0_*.*" expression to "f0_000" file name. */
-    if (ExpressionPosition < (Expression->Length / sizeof(WCHAR)) &&
-        Expression->Buffer[ExpressionPosition] == L'.')
+    else
     {
-        while (ExpressionPosition < (Expression->Length / sizeof(WCHAR)) &&
-            (Expression->Buffer[ExpressionPosition] == L'.' ||
-            Expression->Buffer[ExpressionPosition] == L'*' ||
-            Expression->Buffer[ExpressionPosition] == L'?'))
-        {
-            ExpressionPosition++;
-        }
+        IntName.Buffer = NULL;
     }
 
-    if (ExpressionPosition == (Expression->Length / sizeof(WCHAR)) &&
-        NamePosition == (Name->Length / sizeof(WCHAR)))
+    Result = FsRtlIsNameInExpressionPrivate(Expression, Name, IgnoreCase, UpcaseTable);
+
+    if (IntName.Buffer != NULL)
     {
-        return TRUE;
+        RtlFreeUnicodeString(&IntName);
     }
 
-    return FALSE;
+    return Result;
 }
-