[NTOS:FSRTL] Rework FsRtlIsDbcsInExpression for correct parsing some expressions
authorDmitry Chapyshev <dmitry@reactos.org>
Wed, 28 Sep 2016 19:01:10 +0000 (19:01 +0000)
committerDmitry Chapyshev <dmitry@reactos.org>
Wed, 28 Sep 2016 19:01:10 +0000 (19:01 +0000)
* Fixes 1 test for kmtest:FsRtlExpression

svn path=/trunk/; revision=72839

reactos/ntoskrnl/fsrtl/dbcsname.c
reactos/ntoskrnl/fsrtl/name.c

index 8ecd3b4..ccaaa9b 100644 (file)
@@ -160,9 +160,14 @@ NTAPI
 FsRtlIsDbcsInExpression(IN PANSI_STRING Expression,
                         IN PANSI_STRING Name)
 {
-    SHORT StarFound = -1, DosStarFound = -1;
-    PUSHORT BackTracking = NULL, DosBackTracking = NULL;
-    USHORT ExpressionPosition = 0, NamePosition = 0, MatchingChars, LastDot;
+    USHORT Offset, Position, BackTrackingPosition, OldBackTrackingPosition;
+    USHORT BackTrackingBuffer[16], OldBackTrackingBuffer[16] = {0};
+    PUSHORT BackTrackingSwap, BackTracking = BackTrackingBuffer, OldBackTracking = OldBackTrackingBuffer;
+    USHORT ExpressionPosition, NamePosition = 0, MatchingChars = 1;
+    USHORT NameChar = 0, ExpressionChar;
+    BOOLEAN EndOfName = FALSE;
+    BOOLEAN Result;
+    BOOLEAN DontSkipDot;
     PAGED_CODE();
 
     ASSERT(Name->Length);
@@ -232,170 +237,180 @@ FsRtlIsDbcsInExpression(IN PANSI_STRING Expression,
         }
     }
 
-    while (NamePosition < Name->Length && ExpressionPosition < Expression->Length)
+    /* Name parsing loop */
+    for (; !EndOfName; MatchingChars = BackTrackingPosition)
     {
-        /* Basic check to test if chars are equal */
-        if ((Expression->Buffer[ExpressionPosition] == Name->Buffer[NamePosition]))
-        {
-            NamePosition++;
-            ExpressionPosition++;
-        }
-        /* Check cases that eat one char */
-        else if (Expression->Buffer[ExpressionPosition] == '?')
+        /* Reset positions */
+        OldBackTrackingPosition = BackTrackingPosition = 0;
+
+        if (NamePosition >= Name->Length)
         {
-            NamePosition++;
-            ExpressionPosition++;
+            EndOfName = TRUE;
+            if (OldBackTracking[MatchingChars - 1] == Expression->Length * 2)
+                break;
         }
-        /* Test star */
-        else if (Expression->Buffer[ExpressionPosition] == '*')
+        else
         {
-            /* Skip contigous stars */
-            while (ExpressionPosition + 1 < Expression->Length && Expression->Buffer[ExpressionPosition + 1] == '*')
+            /* If lead byte present */
+            if (FsRtlIsLeadDbcsCharacter(Name->Buffer[NamePosition]))
             {
-                ExpressionPosition++;
+                NameChar = Name->Buffer[NamePosition] +
+                           (0x100 * Name->Buffer[NamePosition + 1]);
+                NamePosition += sizeof(USHORT);
             }
-
-            /* Save star position */
-            if (!BackTracking)
-            {
-                BackTracking = ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE,
-                                                     Expression->Length * sizeof(USHORT), 'nrSF');
-            }
-            BackTracking[++StarFound] = ExpressionPosition++;
-
-            /* If star is at the end, then eat all rest and leave */
-            if (ExpressionPosition == Expression->Length)
-            {
-                NamePosition = Name->Length;
-                break;
-            }
-            /* Allow null matching */
-            else if (Expression->Buffer[ExpressionPosition] != '?' &&
-                     Expression->Buffer[ExpressionPosition] != Name->Buffer[NamePosition])
+            else
             {
-                NamePosition++;
+                NameChar = Name->Buffer[NamePosition];
+                NamePosition += sizeof(UCHAR);
             }
         }
-        /* Check DOS_STAR */
-        else if (Expression->Buffer[ExpressionPosition] == ANSI_DOS_STAR)
+
+        while (MatchingChars > OldBackTrackingPosition)
         {
-            /* Skip contigous stars */
-            while (ExpressionPosition + 1 < Expression->Length && Expression->Buffer[ExpressionPosition + 1] == ANSI_DOS_STAR)
-            {
-                ExpressionPosition++;
-            }
+            ExpressionPosition = (OldBackTracking[OldBackTrackingPosition++] + 1) / 2;
 
-            /* Look for last dot */
-            MatchingChars = 0;
-            LastDot = (USHORT)-1;
-            while (MatchingChars < Name->Length)
+            /* Expression parsing loop */
+            for (Offset = 0; ExpressionPosition < Expression->Length; )
             {
-                if (Name->Buffer[MatchingChars] == '.')
+                ExpressionPosition += Offset;
+
+                if (ExpressionPosition == Expression->Length)
                 {
-                    LastDot = MatchingChars;
-                    if (LastDot > NamePosition)
-                        break;
+                    BackTracking[BackTrackingPosition++] = Expression->Length * 2;
+                    break;
                 }
 
-                MatchingChars++;
-            }
+                /* 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 + 1) * sizeof(USHORT) * 2,
+                                                         '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 + 1) * sizeof(USHORT) * 2,
+                                                            'nrSF');
+                    /* Copy old buffer content */
+                    RtlCopyMemory(OldBackTracking,
+                                  OldBackTrackingBuffer,
+                                  RTL_NUMBER_OF(OldBackTrackingBuffer) * sizeof(USHORT));
+                }
 
-            /* If we don't have dots or we didn't find last yet
-             * start eating everything
-             */
-            if (MatchingChars != Name->Length || LastDot == (USHORT)-1)
-            {
-                if (!DosBackTracking) DosBackTracking = ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE,
-                                                                              Expression->Length * sizeof(USHORT), 'nrSF');
-                DosBackTracking[++DosStarFound] = ExpressionPosition++;
+                /* If lead byte present */
+                if (FsRtlIsLeadDbcsCharacter(Expression->Buffer[ExpressionPosition]))
+                {
+                    ExpressionChar = Expression->Buffer[ExpressionPosition] +
+                                     (0x100 * Expression->Buffer[ExpressionPosition + 1]);
+                    Offset = sizeof(USHORT);
+                }
+                else
+                {
+                    ExpressionChar = Expression->Buffer[ExpressionPosition];
+                    Offset = sizeof(UCHAR);
+                }
 
-                /* 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++;
+                /* Basic check to test if chars are equal */
+                if (ExpressionChar == NameChar && !EndOfName)
+                {
+                    BackTracking[BackTrackingPosition++] = (ExpressionPosition + Offset) * 2;
+                }
+                /* Check cases that eat one char */
+                else if (ExpressionChar == '?' && !EndOfName)
+                {
+                    BackTracking[BackTrackingPosition++] = (ExpressionPosition + Offset) * 2;
+                }
+                /* Test star */
+                else if (ExpressionChar == '*')
+                {
+                    BackTracking[BackTrackingPosition++] = ExpressionPosition * 2;
+                    BackTracking[BackTrackingPosition++] = (ExpressionPosition * 2) + 1;
+                    continue;
+                }
+                /* Check DOS_STAR */
+                else if (ExpressionChar == ANSI_DOS_STAR)
+                {
+                    /* Look for last dot */
+                    DontSkipDot = TRUE;
+                    if (!EndOfName && NameChar == '.')
+                    {
+                        for (Position = NamePosition; Position < Name->Length; )
+                        {
+                            /* If lead byte not present */
+                            if (!FsRtlIsLeadDbcsCharacter(Name->Buffer[Position]))
+                            {
+                                if (Name->Buffer[Position] == '.')
+                                {
+                                    DontSkipDot = FALSE;
+                                    break;
+                                }
+
+                                Position += sizeof(UCHAR);
+                            }
+                            else
+                            {
+                                Position += sizeof(USHORT);
+                            }
+                        }
+                    }
+
+                    if (EndOfName || NameChar != '.' || !DontSkipDot)
+                        BackTracking[BackTrackingPosition++] = ExpressionPosition * 2;
+
+                    BackTracking[BackTrackingPosition++] = (ExpressionPosition * 2) + 1;
+                    continue;
+                }
+                /* Check DOS_DOT */
+                else if (ExpressionChar == DOS_DOT)
+                {
+                    if (EndOfName) continue;
 
-                 ExpressionPosition++;
-            }
-        }
-        /* Check DOS_DOT */
-        else if (Expression->Buffer[ExpressionPosition] == ANSI_DOS_DOT)
-        {
-            /* We only match dots */
-            if (Name->Buffer[NamePosition] == '.')
-            {
-                NamePosition++;
-            }
-            /* Try to explore later on for null matching */
-            else if (ExpressionPosition + 1 < Expression->Length &&
-                     Name->Buffer[NamePosition] == Expression->Buffer[ExpressionPosition + 1])
-            {
-                NamePosition++;
-            }
-            ExpressionPosition++;
-        }
-        /* Check DOS_QM */
-        else if (Expression->Buffer[ExpressionPosition] == ANSI_DOS_QM)
-        {
-            /* We match everything except dots */
-            if (Name->Buffer[NamePosition] != '.')
-            {
-                NamePosition++;
+                    if (NameChar == '.')
+                        BackTracking[BackTrackingPosition++] = (ExpressionPosition + Offset) * 2;
+                }
+                /* Check DOS_QM */
+                else if (ExpressionChar == ANSI_DOS_QM)
+                {
+                    if (EndOfName || NameChar == '.') continue;
+
+                    BackTracking[BackTrackingPosition++] = (ExpressionPosition + Offset) * 2;
+                }
+
+                /* Leave from loop */
+                break;
             }
-            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 &&
-            NamePosition != Name->Length && StarFound >= 0)
-        {
-            ExpressionPosition = BackTracking[StarFound--];
-        }
-    }
-    /* If we have nullable matching wc at the end of the string, eat them */
-    if (ExpressionPosition != Expression->Length && NamePosition == Name->Length)
-    {
-        while (ExpressionPosition < Expression->Length)
-        {
-            if (Expression->Buffer[ExpressionPosition] != ANSI_DOS_DOT &&
-                Expression->Buffer[ExpressionPosition] != '*' &&
-                Expression->Buffer[ExpressionPosition] != ANSI_DOS_STAR)
+            for (Position = 0; MatchingChars > OldBackTrackingPosition && Position < BackTrackingPosition; Position++)
             {
-                break;
+                while (MatchingChars > OldBackTrackingPosition &&
+                       BackTracking[Position] > OldBackTracking[OldBackTrackingPosition])
+                {
+                    ++OldBackTrackingPosition;
+                }
             }
-            ExpressionPosition++;
         }
+
+        /* Swap pointers */
+        BackTrackingSwap = BackTracking;
+        BackTracking = OldBackTracking;
+        OldBackTracking = BackTrackingSwap;
     }
 
-    if (BackTracking)
-    {
+    /* 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)
-    {
-        ExFreePoolWithTag(DosBackTracking, 'nrSF');
-    }
+    if (OldBackTracking != BackTrackingBuffer && OldBackTracking != OldBackTrackingBuffer)
+        ExFreePoolWithTag(OldBackTracking, 'nrSF');
 
-    return (ExpressionPosition == Expression->Length && NamePosition == Name->Length);
+    return Result;
 }
 
 /*++
index 3830454..f470cc0 100644 (file)
@@ -27,9 +27,9 @@ FsRtlIsNameInExpressionPrivate(IN PUNICODE_STRING Expression,
     USHORT BackTrackingBuffer[16], OldBackTrackingBuffer[16] = {0};
     PUSHORT BackTrackingSwap, BackTracking = BackTrackingBuffer, OldBackTracking = OldBackTrackingBuffer;
     UNICODE_STRING IntExpression;
-    USHORT ExpressionPosition = 0, NamePosition = 0, MatchingChars = 1;
+    USHORT ExpressionPosition, NamePosition = 0, MatchingChars = 1;
     BOOLEAN EndOfName = FALSE;
-    BOOLEAN Result = FALSE;
+    BOOLEAN Result;
     BOOLEAN DontSkipDot;
     WCHAR CompareChar;
     PAGED_CODE();