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=7... ============================================================================== --- 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 **********************************************************/