Author: dchapyshev
Date: Wed Sep 28 19:01:10 2016
New Revision: 72839
URL:
http://svn.reactos.org/svn/reactos?rev=72839&view=rev
Log:
[NTOS:FSRTL] Rework FsRtlIsDbcsInExpression for correct parsing some expressions
* Fixes 1 test for kmtest:FsRtlExpression
Modified:
trunk/reactos/ntoskrnl/fsrtl/dbcsname.c
trunk/reactos/ntoskrnl/fsrtl/name.c
Modified: trunk/reactos/ntoskrnl/fsrtl/dbcsname.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/fsrtl/dbcsname.c?…
==============================================================================
--- trunk/reactos/ntoskrnl/fsrtl/dbcsname.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/fsrtl/dbcsname.c [iso-8859-1] Wed Sep 28 19:01:10 2016
@@ -160,9 +160,14 @@
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 @@
}
}
- while (NamePosition < Name->Length && ExpressionPosition <
Expression->Length)
- {
- /* 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] == '?')
- {
- NamePosition++;
- ExpressionPosition++;
- }
- /* Test star */
- else if (Expression->Buffer[ExpressionPosition] == '*')
- {
- /* Skip contigous stars */
- while (ExpressionPosition + 1 < Expression->Length &&
Expression->Buffer[ExpressionPosition + 1] == '*')
- {
- ExpressionPosition++;
- }
-
- /* 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;
+ /* Name parsing loop */
+ for (; !EndOfName; MatchingChars = BackTrackingPosition)
+ {
+ /* Reset positions */
+ OldBackTrackingPosition = BackTrackingPosition = 0;
+
+ if (NamePosition >= Name->Length)
+ {
+ EndOfName = TRUE;
+ if (OldBackTracking[MatchingChars - 1] == Expression->Length * 2)
break;
- }
- /* Allow null matching */
- else if (Expression->Buffer[ExpressionPosition] != '?' &&
- Expression->Buffer[ExpressionPosition] !=
Name->Buffer[NamePosition])
- {
- NamePosition++;
- }
- }
- /* Check DOS_STAR */
- else if (Expression->Buffer[ExpressionPosition] == ANSI_DOS_STAR)
- {
- /* Skip contigous stars */
- while (ExpressionPosition + 1 < Expression->Length &&
Expression->Buffer[ExpressionPosition + 1] == ANSI_DOS_STAR)
- {
- ExpressionPosition++;
- }
-
- /* Look for last dot */
- MatchingChars = 0;
- LastDot = (USHORT)-1;
- while (MatchingChars < Name->Length)
- {
- if (Name->Buffer[MatchingChars] == '.')
- {
- 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)
- {
- if (!DosBackTracking) DosBackTracking = ExAllocatePoolWithTag(PagedPool |
POOL_RAISE_IF_ALLOCATION_FAILURE,
-
Expression->Length * sizeof(USHORT), 'nrSF');
- DosBackTracking[++DosStarFound] = ExpressionPosition++;
-
- /* Not the same char, start exploring */
- if (Expression->Buffer[ExpressionPosition] !=
Name->Buffer[NamePosition])
- NamePosition++;
+ }
+ else
+ {
+ /* If lead byte present */
+ if (FsRtlIsLeadDbcsCharacter(Name->Buffer[NamePosition]))
+ {
+ NameChar = Name->Buffer[NamePosition] +
+ (0x100 * Name->Buffer[NamePosition + 1]);
+ NamePosition += sizeof(USHORT);
}
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] == 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++;
- }
- 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)
- {
+ NameChar = Name->Buffer[NamePosition];
+ NamePosition += sizeof(UCHAR);
+ }
+ }
+
+ while (MatchingChars > OldBackTrackingPosition)
+ {
+ ExpressionPosition = (OldBackTracking[OldBackTrackingPosition++] + 1) / 2;
+
+ /* Expression parsing loop */
+ for (Offset = 0; ExpressionPosition < Expression->Length; )
+ {
+ 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 + 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 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);
+ }
+
+ /* 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;
+
+ 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 (BackTracking)
- {
+
+ 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)
- {
- ExFreePoolWithTag(DosBackTracking, 'nrSF');
- }
-
- return (ExpressionPosition == Expression->Length && NamePosition ==
Name->Length);
+ if (OldBackTracking != BackTrackingBuffer && OldBackTracking !=
OldBackTrackingBuffer)
+ ExFreePoolWithTag(OldBackTracking, 'nrSF');
+
+ return Result;
}
/*++
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] Wed Sep 28 19:01:10 2016
@@ -27,9 +27,9 @@
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();