Author: dchapyshev
Date: Tue Sep 27 23:00:20 2016
New Revision: 72835

URL: http://svn.reactos.org/svn/reactos?rev=72835&view=rev
Log:
[NTOS:FSRTL] Rework FsRtlIsNameInExpressionPrivate for correct parsing some 
expressions

* Fixes 1 test for kmtest:FsRtlExpression and 15 tests for kernel32:file

Modified:
    trunk/reactos/ntoskrnl/fsrtl/name.c

Modified: trunk/reactos/ntoskrnl/fsrtl/name.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/fsrtl/name.c?rev=72835&r1=72834&r2=72835&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/fsrtl/name.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/fsrtl/name.c [iso-8859-1] Tue Sep 27 23:00:20 2016
@@ -23,13 +23,14 @@
                                IN BOOLEAN IgnoreCase,
                                IN PWCHAR UpcaseTable OPTIONAL)
 {
-    SHORT StarFound = -1, DosStarFound = -1;
-    USHORT BackTrackingBuffer[5], DosBackTrackingBuffer[5];
-    PUSHORT BackTracking = BackTrackingBuffer, DosBackTracking = 
DosBackTrackingBuffer;
-    SHORT BackTrackingSize = RTL_NUMBER_OF(BackTrackingBuffer);
-    SHORT DosBackTrackingSize = RTL_NUMBER_OF(DosBackTrackingBuffer);
+    USHORT Offset, Position, BackTrackingPosition, OldBackTrackingPosition;
+    USHORT BackTrackingBuffer[16], OldBackTrackingBuffer[16] = {0};
+    PUSHORT BackTrackingSwap, BackTracking = BackTrackingBuffer, 
OldBackTracking = OldBackTrackingBuffer;
     UNICODE_STRING IntExpression;
-    USHORT ExpressionPosition = 0, NamePosition = 0, MatchingChars, LastDot;
+    USHORT ExpressionPosition = 0, NamePosition = 0, MatchingChars = 1;
+    BOOLEAN EndOfName = FALSE;
+    BOOLEAN Result = FALSE;
+    BOOLEAN DontSkipDot;
     WCHAR CompareChar;
     PAGED_CODE();
 
@@ -37,7 +38,7 @@
     if (!Name->Length || !Expression->Length)
     {
         /* Return TRUE if both strings are empty, otherwise FALSE */
-        if (Name->Length == 0 && Expression->Length == 0)
+        if (!Name->Length && !Expression->Length)
             return TRUE;
         else
             return FALSE;
@@ -103,193 +104,144 @@
         }
     }
 
-    while ((NamePosition < Name->Length / sizeof(WCHAR)) &&
-           (ExpressionPosition < Expression->Length / sizeof(WCHAR)))
-    {
-        /* Basic check to test if chars are equal */
-        CompareChar = IgnoreCase ? UpcaseTable[Name->Buffer[NamePosition]] :
-                                   Name->Buffer[NamePosition];
-        if (Expression->Buffer[ExpressionPosition] == CompareChar)
-        {
-            NamePosition++;
-            ExpressionPosition++;
-        }
-        /* Check cases that eat one char */
-        else if (Expression->Buffer[ExpressionPosition] == L'?')
-        {
-            NamePosition++;
-            ExpressionPosition++;
-        }
-        /* Test star */
-        else if (Expression->Buffer[ExpressionPosition] == L'*')
-        {
-            /* Skip contigous stars */
-            while ((ExpressionPosition + 1 < (USHORT)(Expression->Length / 
sizeof(WCHAR))) &&
-                   (Expression->Buffer[ExpressionPosition + 1] == L'*'))
-            {
-                ExpressionPosition++;
-            }
-
-            /* Save star position */
-            StarFound++;
-            if (StarFound >= BackTrackingSize)
-            {
-                ASSERT(BackTracking == BackTrackingBuffer);
-
-                BackTrackingSize = Expression->Length / sizeof(WCHAR);
-                BackTracking = ExAllocatePoolWithTag(PagedPool | 
POOL_RAISE_IF_ALLOCATION_FAILURE,
-                                                     BackTrackingSize * 
sizeof(USHORT),
-                                                     'nrSF');
-                RtlCopyMemory(BackTracking, BackTrackingBuffer, 
sizeof(BackTrackingBuffer));
-
-            }
-            BackTracking[StarFound] = ExpressionPosition++;
-
-            /* If star is at the end, then eat all rest and leave */
-            if (ExpressionPosition == Expression->Length / sizeof(WCHAR))
-            {
-                NamePosition = Name->Length / sizeof(WCHAR);
+    /* Name parsing loop */
+    for (; !EndOfName; MatchingChars = BackTrackingPosition, NamePosition++)
+    {
+        /* Reset positions */
+        OldBackTrackingPosition = BackTrackingPosition = 0;
+
+        if (NamePosition >= Name->Length / sizeof(WCHAR))
+        {
+            EndOfName = TRUE;
+            if (OldBackTracking[MatchingChars - 1] == Expression->Length * 2)
                 break;
-            }
-
-            /* Allow null matching */
-            if (Expression->Buffer[ExpressionPosition] != L'?' &&
-                     Expression->Buffer[ExpressionPosition] != 
Name->Buffer[NamePosition])
-            {
-                NamePosition++;
-            }
-        }
-        /* Check DOS_STAR */
-        else if (Expression->Buffer[ExpressionPosition] == DOS_STAR)
-        {
-            /* Skip contigous stars */
-            while ((ExpressionPosition + 1 < (USHORT)(Expression->Length / 
sizeof(WCHAR))) &&
-                   (Expression->Buffer[ExpressionPosition + 1] == DOS_STAR))
-            {
-                ExpressionPosition++;
-            }
-
-            /* Look for last dot */
-            MatchingChars = 0;
-            LastDot = (USHORT)-1;
-            while (MatchingChars < Name->Length / sizeof(WCHAR))
-            {
-                if (Name->Buffer[MatchingChars] == L'.')
-                {
-                    LastDot = MatchingChars;
-                    if (LastDot > NamePosition)
-                        break;
-                }
-
-                MatchingChars++;
-            }
-
-            /* If we don't have dots or we didn't find last yet
-             * start eating everything
-             */
-            if (MatchingChars != Name->Length || LastDot == (USHORT)-1)
-            {
-                DosStarFound++;
-                if (DosStarFound >= DosBackTrackingSize)
-                {
-                    ASSERT(DosBackTracking == DosBackTrackingBuffer);
-
-                    DosBackTrackingSize = Expression->Length / sizeof(WCHAR);
-                    DosBackTracking = ExAllocatePoolWithTag(PagedPool | 
POOL_RAISE_IF_ALLOCATION_FAILURE,
-                                                            
DosBackTrackingSize * sizeof(USHORT),
+        }
+
+        while (MatchingChars > OldBackTrackingPosition)
+        {
+            ExpressionPosition = (OldBackTracking[OldBackTrackingPosition++] + 
1) / 2;
+
+            /* Expression parsing loop */
+            for (Offset = 0; ExpressionPosition < Expression->Length; Offset = 
sizeof(WCHAR))
+            {
+                ExpressionPosition += Offset;
+
+                if (ExpressionPosition == Expression->Length)
+                {
+                    BackTracking[BackTrackingPosition++] = Expression->Length 
* 2;
+                    break;
+                }
+
+                /* If buffer too small */
+                if (BackTrackingPosition > RTL_NUMBER_OF(BackTrackingBuffer) - 
1)
+                {
+                    /* Allocate memory for BackTracking */
+                    BackTracking = ExAllocatePoolWithTag(PagedPool | 
POOL_RAISE_IF_ALLOCATION_FAILURE,
+                                                         (Expression->Length + 
sizeof(WCHAR)) * sizeof(USHORT),
+                                                         'nrSF');
+                    /* Copy old buffer content */
+                    RtlCopyMemory(BackTracking,
+                                  BackTrackingBuffer,
+                                  RTL_NUMBER_OF(BackTrackingBuffer) * 
sizeof(USHORT));
+
+                    /* Allocate memory for OldBackTracking */
+                    OldBackTracking = ExAllocatePoolWithTag(PagedPool | 
POOL_RAISE_IF_ALLOCATION_FAILURE,
+                                                            
(Expression->Length + sizeof(WCHAR)) * sizeof(USHORT),
                                                             'nrSF');
-                    RtlCopyMemory(DosBackTracking, DosBackTrackingBuffer, 
sizeof(DosBackTrackingBuffer));
-                }
-                DosBackTracking[DosStarFound] = ExpressionPosition++;
-
-                /* Not the same char, start exploring */
-                if (Expression->Buffer[ExpressionPosition] != 
Name->Buffer[NamePosition])
-                    NamePosition++;
-            }
-            else
-            {
-                /* Else, if we are at last dot, eat it - otherwise, null match 
*/
-                if (Name->Buffer[NamePosition] == '.')
-                    NamePosition++;
-
-                 ExpressionPosition++;
-            }
-        }
-        /* Check DOS_DOT */
-        else if (Expression->Buffer[ExpressionPosition] == DOS_DOT)
-        {
-            /* We only match dots */
-            if (Name->Buffer[NamePosition] == L'.')
-            {
-                NamePosition++;
-            }
-            /* Try to explore later on for null matching */
-            else if ((ExpressionPosition + 1 < (USHORT)(Expression->Length / 
sizeof(WCHAR))) &&
-                     (Name->Buffer[NamePosition] == 
Expression->Buffer[ExpressionPosition + 1]))
-            {
-                NamePosition++;
-            }
-            ExpressionPosition++;
-        }
-        /* Check DOS_QM */
-        else if (Expression->Buffer[ExpressionPosition] == DOS_QM)
-        {
-            /* We match everything except dots */
-            if (Name->Buffer[NamePosition] != L'.')
-            {
-                NamePosition++;
-            }
-            ExpressionPosition++;
-        }
-        /* If nothing match, try to backtrack */
-        else if (StarFound >= 0)
-        {
-            ExpressionPosition = BackTracking[StarFound--];
-        }
-        else if (DosStarFound >= 0)
-        {
-            ExpressionPosition = DosBackTracking[DosStarFound--];
-        }
-        /* Otherwise, fail */
-        else
-        {
-            break;
-        }
-
-        /* Under certain circumstances, expression is over, but name isn't
-         * and we can backtrack, then, backtrack */
-        if (ExpressionPosition == Expression->Length / sizeof(WCHAR) &&
-            NamePosition != Name->Length / sizeof(WCHAR) &&
-            StarFound >= 0)
-        {
-            ExpressionPosition = BackTracking[StarFound--];
-        }
-    }
-    /* If we have nullable matching wc at the end of the string, eat them */
-    if (ExpressionPosition != Expression->Length / sizeof(WCHAR) && 
NamePosition == Name->Length / sizeof(WCHAR))
-    {
-        while (ExpressionPosition < Expression->Length / sizeof(WCHAR))
-        {
-            if (Expression->Buffer[ExpressionPosition] != DOS_DOT &&
-                Expression->Buffer[ExpressionPosition] != L'*' &&
-                Expression->Buffer[ExpressionPosition] != DOS_STAR)
-            {
+                    /* Copy old buffer content */
+                    RtlCopyMemory(OldBackTracking,
+                                  OldBackTrackingBuffer,
+                                  RTL_NUMBER_OF(OldBackTrackingBuffer) * 
sizeof(USHORT));
+                }
+
+                /* Basic check to test if chars are equal */
+                CompareChar = IgnoreCase ? 
UpcaseTable[Name->Buffer[NamePosition]] :
+                                           Name->Buffer[NamePosition];
+                if (Expression->Buffer[ExpressionPosition / sizeof(WCHAR)] == 
CompareChar && !EndOfName)
+                {
+                    BackTracking[BackTrackingPosition++] = (ExpressionPosition 
+ sizeof(WCHAR)) * 2;
+                }
+                /* Check cases that eat one char */
+                else if (Expression->Buffer[ExpressionPosition / 
sizeof(WCHAR)] == L'?' && !EndOfName)
+                {
+                    BackTracking[BackTrackingPosition++] = (ExpressionPosition 
+ sizeof(WCHAR)) * 2;
+                }
+                /* Test star */
+                else if (Expression->Buffer[ExpressionPosition / 
sizeof(WCHAR)] == L'*')
+                {
+                    BackTracking[BackTrackingPosition++] = ExpressionPosition 
* 2;
+                    BackTracking[BackTrackingPosition++] = (ExpressionPosition 
* 2) + 3;
+                    continue;
+                }
+                /* Check DOS_STAR */
+                else if (Expression->Buffer[ExpressionPosition / 
sizeof(WCHAR)] == DOS_STAR)
+                {
+                    /* Look for last dot */
+                    DontSkipDot = TRUE;
+                    if (!EndOfName && Name->Buffer[NamePosition] == '.')
+                    {
+                        for (Position = NamePosition - 1; Position < 
Name->Length; Position++)
+                        {
+                            if (Name->Buffer[Position] == L'.')
+                            {
+                                DontSkipDot = FALSE;
+                                break;
+                            }
+                        }
+                    }
+
+                    if (EndOfName || Name->Buffer[NamePosition] != L'.' || 
!DontSkipDot)
+                        BackTracking[BackTrackingPosition++] = 
ExpressionPosition * 2;
+
+                    BackTracking[BackTrackingPosition++] = (ExpressionPosition 
* 2) + 3;
+                    continue;
+                }
+                /* Check DOS_DOT */
+                else if (Expression->Buffer[ExpressionPosition / 
sizeof(WCHAR)] == DOS_DOT)
+                {
+                    if (EndOfName) continue;
+
+                    if (Name->Buffer[NamePosition] == L'.')
+                        BackTracking[BackTrackingPosition++] = 
(ExpressionPosition + sizeof(WCHAR)) * 2;
+                }
+                /* Check DOS_QM */
+                else if (Expression->Buffer[ExpressionPosition / 
sizeof(WCHAR)] == DOS_QM)
+                {
+                    if (EndOfName || Name->Buffer[NamePosition] == L'.') 
continue;
+
+                    BackTracking[BackTrackingPosition++] = (ExpressionPosition 
+ sizeof(WCHAR)) * 2;
+                }
+
+                /* Leave from loop */
                 break;
             }
-            ExpressionPosition++;
-        }
-    }
-
-    if (BackTracking != BackTrackingBuffer)
-    {
+
+            for (Position = 0; MatchingChars > OldBackTrackingPosition && 
Position < BackTrackingPosition; Position++)
+            {
+                while (MatchingChars > OldBackTrackingPosition &&
+                       BackTracking[Position] > 
OldBackTracking[OldBackTrackingPosition])
+                {
+                    ++OldBackTrackingPosition;
+                }
+            }
+        }
+
+        /* Swap pointers */
+        BackTrackingSwap = BackTracking;
+        BackTracking = OldBackTracking;
+        OldBackTracking = BackTrackingSwap;
+    }
+
+    /* Store result value */
+    Result = (OldBackTracking[MatchingChars - 1] == (Expression->Length * 2));
+
+    /* Frees the memory if necessary */
+    if (BackTracking != BackTrackingBuffer && BackTracking != 
OldBackTrackingBuffer)
         ExFreePoolWithTag(BackTracking, 'nrSF');
-    }
-    if (DosBackTracking != DosBackTrackingBuffer)
-    {
-        ExFreePoolWithTag(DosBackTracking, 'nrSF');
-    }
-
-    return (ExpressionPosition == Expression->Length / sizeof(WCHAR) && 
NamePosition == Name->Length / sizeof(WCHAR));
+    if (OldBackTracking != BackTrackingBuffer && OldBackTracking != 
OldBackTrackingBuffer)
+        ExFreePoolWithTag(OldBackTracking, 'nrSF');
+
+    return Result;
 }
 
 /* PUBLIC FUNCTIONS **********************************************************/


Reply via email to