[STORPORT] Fix x64 build
[reactos.git] / ntoskrnl / fsrtl / name.c
index 5b3b4f9..6700f73 100644 (file)
@@ -23,10 +23,14 @@ FsRtlIsNameInExpressionPrivate(IN PUNICODE_STRING Expression,
                                IN BOOLEAN IgnoreCase,
                                IN PWCHAR UpcaseTable OPTIONAL)
 {
-    SHORT StarFound = -1;
-    PUSHORT BackTracking = NULL;
+    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;
+    USHORT ExpressionPosition, NamePosition = 0, MatchingChars = 1;
+    BOOLEAN EndOfName = FALSE;
+    BOOLEAN Result;
+    BOOLEAN DontSkipDot;
     WCHAR CompareChar;
     PAGED_CODE();
 
@@ -34,7 +38,7 @@ FsRtlIsNameInExpressionPrivate(IN PUNICODE_STRING Expression,
     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;
@@ -100,100 +104,144 @@ FsRtlIsNameInExpressionPrivate(IN PUNICODE_STRING Expression,
         }
     }
 
-    while ((NamePosition < Name->Length / sizeof(WCHAR)) &&
-           (ExpressionPosition < Expression->Length / sizeof(WCHAR)))
+    /* Name parsing loop */
+    for (; !EndOfName; MatchingChars = BackTrackingPosition, NamePosition++)
     {
-        /* 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'?' || (Expression->Buffer[ExpressionPosition] == DOS_QM) ||
-                 (Expression->Buffer[ExpressionPosition] == DOS_DOT && Name->Buffer[NamePosition] == L'.'))
+        /* Reset positions */
+        OldBackTrackingPosition = BackTrackingPosition = 0;
+
+        if (NamePosition >= Name->Length / sizeof(WCHAR))
         {
-            NamePosition++;
-            ExpressionPosition++;
+            EndOfName = TRUE;
+            if (MatchingChars && (OldBackTracking[MatchingChars - 1] == Expression->Length * 2))
+                break;
         }
-        /* Test star */
-        else if (Expression->Buffer[ExpressionPosition] == L'*')
+
+        while (MatchingChars > OldBackTrackingPosition)
         {
-            /* Skip contigous stars */
-            while ((ExpressionPosition + 1 < (USHORT)(Expression->Length / sizeof(WCHAR))) &&
-                   (Expression->Buffer[ExpressionPosition + 1] == L'*'))
-            {
-                ExpressionPosition++;
-            }
+            ExpressionPosition = (OldBackTracking[OldBackTrackingPosition++] + 1) / 2;
 
-            /* Save star position */
-            if (!BackTracking)
+            /* Expression parsing loop */
+            for (Offset = 0; ExpressionPosition < Expression->Length; Offset = sizeof(WCHAR))
             {
-                BackTracking = ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE,
-                                                     (Expression->Length / sizeof(WCHAR)) * sizeof(USHORT),
-                                                     'nrSF');
-            }
-            BackTracking[++StarFound] = ExpressionPosition++;
+                ExpressionPosition += Offset;
 
-            /* If star is at the end, then eat all rest and leave */
-            if (ExpressionPosition == Expression->Length / sizeof(WCHAR))
-            {
-                NamePosition = Name->Length / sizeof(WCHAR);
+                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');
+                    /* Copy old buffer content */
+                    RtlCopyMemory(OldBackTracking,
+                                  OldBackTrackingBuffer,
+                                  RTL_NUMBER_OF(OldBackTrackingBuffer) * sizeof(USHORT));
+                }
+
+                /* Basic check to test if chars are equal */
+                CompareChar = (NamePosition >= Name->Length / sizeof(WCHAR)) ? UNICODE_NULL : (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;
             }
-            else if (Expression->Buffer[ExpressionPosition] != L'?')
-            {
-                NamePosition++;
-            }
-        }
-        /* Check DOS_STAR */
-        else if (Expression->Buffer[ExpressionPosition] == DOS_STAR)
-        {
-            MatchingChars = NamePosition;
-            while (MatchingChars < Name->Length / sizeof(WCHAR))
+
+            for (Position = 0; MatchingChars > OldBackTrackingPosition && Position < BackTrackingPosition; Position++)
             {
-                if (Name->Buffer[MatchingChars] == L'.')
+                while (MatchingChars > OldBackTrackingPosition &&
+                       BackTracking[Position] > OldBackTracking[OldBackTrackingPosition])
                 {
-                    NamePosition = MatchingChars + 1;
+                    ++OldBackTrackingPosition;
                 }
-                MatchingChars++;
             }
-            ExpressionPosition++;
-        }
-        /* If nothing match, try to backtrack */
-        else if (StarFound >= 0)
-        {
-            ExpressionPosition = BackTracking[StarFound--];
-        }
-        /* 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 (ExpressionPosition + 1 == Expression->Length / sizeof(WCHAR) && NamePosition == Name->Length / sizeof(WCHAR) &&
-        Expression->Buffer[ExpressionPosition] == DOS_DOT)
-    {
-        ExpressionPosition++;
+        /* Swap pointers */
+        BackTrackingSwap = BackTracking;
+        BackTracking = OldBackTracking;
+        OldBackTracking = BackTrackingSwap;
     }
 
-    if (BackTracking)
-    {
+    /* Store result value */
+    Result = MatchingChars > 0 && (OldBackTracking[MatchingChars - 1] == (Expression->Length * 2));
+
+    /* Frees the memory if necessary */
+    if (BackTracking != BackTrackingBuffer && BackTracking != OldBackTrackingBuffer)
         ExFreePoolWithTag(BackTracking, 'nrSF');
-    }
+    if (OldBackTracking != BackTrackingBuffer && OldBackTracking != OldBackTrackingBuffer)
+        ExFreePoolWithTag(OldBackTracking, 'nrSF');
 
-    return (ExpressionPosition == Expression->Length / sizeof(WCHAR) && NamePosition == Name->Length / sizeof(WCHAR));
+    return Result;
 }
 
 /* PUBLIC FUNCTIONS **********************************************************/
@@ -246,7 +294,13 @@ FsRtlAreNamesEqual(IN PCUNICODE_STRING Name1,
         if (!NT_SUCCESS(Status)) RtlRaiseStatus(Status);
 
         /* Upcase the second string too */
-        RtlUpcaseUnicodeString(&UpcaseName2, Name2, TRUE);
+        Status = RtlUpcaseUnicodeString(&UpcaseName2, Name2, TRUE);
+        if (!NT_SUCCESS(Status))
+        {
+            RtlFreeUnicodeString(&UpcaseName1);
+            RtlRaiseStatus(Status);
+        }
+
         Name1 = &UpcaseName1;
         Name2 = &UpcaseName2;