Don't forget to apply the changes (not reviewed, sorry, no time) to
FsRtlIsDbcsInExpression.
Le 28/09/2016 à 01:00, dchapyshev(a)svn.reactos.org a écrit :
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=…
==============================================================================
--- 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 **********************************************************/
--
Pierre Schweitzer <pierre at reactos.org>
System & Network Administrator
Senior Kernel Developer
ReactOS Deutschland e.V.