mirror of
https://github.com/reactos/reactos.git
synced 2025-07-31 13:21:39 +00:00
[NTOS:FSRTL] Rework FsRtlIsDbcsInExpression for correct parsing some expressions
* Fixes 1 test for kmtest:FsRtlExpression svn path=/trunk/; revision=72839
This commit is contained in:
parent
7d865c5974
commit
d507b7555e
2 changed files with 163 additions and 148 deletions
|
@ -160,9 +160,14 @@ NTAPI
|
||||||
FsRtlIsDbcsInExpression(IN PANSI_STRING Expression,
|
FsRtlIsDbcsInExpression(IN PANSI_STRING Expression,
|
||||||
IN PANSI_STRING Name)
|
IN PANSI_STRING Name)
|
||||||
{
|
{
|
||||||
SHORT StarFound = -1, DosStarFound = -1;
|
USHORT Offset, Position, BackTrackingPosition, OldBackTrackingPosition;
|
||||||
PUSHORT BackTracking = NULL, DosBackTracking = NULL;
|
USHORT BackTrackingBuffer[16], OldBackTrackingBuffer[16] = {0};
|
||||||
USHORT ExpressionPosition = 0, NamePosition = 0, MatchingChars, LastDot;
|
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();
|
PAGED_CODE();
|
||||||
|
|
||||||
ASSERT(Name->Length);
|
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 */
|
/* Reset positions */
|
||||||
if ((Expression->Buffer[ExpressionPosition] == Name->Buffer[NamePosition]))
|
OldBackTrackingPosition = BackTrackingPosition = 0;
|
||||||
{
|
|
||||||
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 (NamePosition >= Name->Length)
|
||||||
if (!BackTracking)
|
{
|
||||||
{
|
EndOfName = TRUE;
|
||||||
BackTracking = ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE,
|
if (OldBackTracking[MatchingChars - 1] == Expression->Length * 2)
|
||||||
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;
|
break;
|
||||||
}
|
|
||||||
/* Allow null matching */
|
|
||||||
else if (Expression->Buffer[ExpressionPosition] != '?' &&
|
|
||||||
Expression->Buffer[ExpressionPosition] != Name->Buffer[NamePosition])
|
|
||||||
{
|
|
||||||
NamePosition++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/* Check DOS_STAR */
|
else
|
||||||
else if (Expression->Buffer[ExpressionPosition] == ANSI_DOS_STAR)
|
|
||||||
{
|
{
|
||||||
/* Skip contigous stars */
|
/* If lead byte present */
|
||||||
while (ExpressionPosition + 1 < Expression->Length && Expression->Buffer[ExpressionPosition + 1] == ANSI_DOS_STAR)
|
if (FsRtlIsLeadDbcsCharacter(Name->Buffer[NamePosition]))
|
||||||
{
|
{
|
||||||
ExpressionPosition++;
|
NameChar = Name->Buffer[NamePosition] +
|
||||||
}
|
(0x100 * Name->Buffer[NamePosition + 1]);
|
||||||
|
NamePosition += sizeof(USHORT);
|
||||||
/* 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
|
else
|
||||||
{
|
{
|
||||||
/* Else, if we are at last dot, eat it - otherwise, null match */
|
NameChar = Name->Buffer[NamePosition];
|
||||||
if (Name->Buffer[NamePosition] == '.')
|
NamePosition += sizeof(UCHAR);
|
||||||
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
|
while (MatchingChars > OldBackTrackingPosition)
|
||||||
* and we can backtrack, then, backtrack */
|
|
||||||
if (ExpressionPosition == Expression->Length &&
|
|
||||||
NamePosition != Name->Length && StarFound >= 0)
|
|
||||||
{
|
{
|
||||||
ExpressionPosition = BackTracking[StarFound--];
|
ExpressionPosition = (OldBackTracking[OldBackTrackingPosition++] + 1) / 2;
|
||||||
}
|
|
||||||
}
|
/* Expression parsing loop */
|
||||||
/* If we have nullable matching wc at the end of the string, eat them */
|
for (Offset = 0; ExpressionPosition < Expression->Length; )
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
|
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;
|
break;
|
||||||
}
|
}
|
||||||
ExpressionPosition++;
|
|
||||||
|
for (Position = 0; MatchingChars > OldBackTrackingPosition && Position < BackTrackingPosition; Position++)
|
||||||
|
{
|
||||||
|
while (MatchingChars > OldBackTrackingPosition &&
|
||||||
|
BackTracking[Position] > OldBackTracking[OldBackTrackingPosition])
|
||||||
|
{
|
||||||
|
++OldBackTrackingPosition;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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');
|
ExFreePoolWithTag(BackTracking, 'nrSF');
|
||||||
}
|
if (OldBackTracking != BackTrackingBuffer && OldBackTracking != OldBackTrackingBuffer)
|
||||||
if (DosBackTracking)
|
ExFreePoolWithTag(OldBackTracking, 'nrSF');
|
||||||
{
|
|
||||||
ExFreePoolWithTag(DosBackTracking, 'nrSF');
|
|
||||||
}
|
|
||||||
|
|
||||||
return (ExpressionPosition == Expression->Length && NamePosition == Name->Length);
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*++
|
/*++
|
||||||
|
|
|
@ -27,9 +27,9 @@ FsRtlIsNameInExpressionPrivate(IN PUNICODE_STRING Expression,
|
||||||
USHORT BackTrackingBuffer[16], OldBackTrackingBuffer[16] = {0};
|
USHORT BackTrackingBuffer[16], OldBackTrackingBuffer[16] = {0};
|
||||||
PUSHORT BackTrackingSwap, BackTracking = BackTrackingBuffer, OldBackTracking = OldBackTrackingBuffer;
|
PUSHORT BackTrackingSwap, BackTracking = BackTrackingBuffer, OldBackTracking = OldBackTrackingBuffer;
|
||||||
UNICODE_STRING IntExpression;
|
UNICODE_STRING IntExpression;
|
||||||
USHORT ExpressionPosition = 0, NamePosition = 0, MatchingChars = 1;
|
USHORT ExpressionPosition, NamePosition = 0, MatchingChars = 1;
|
||||||
BOOLEAN EndOfName = FALSE;
|
BOOLEAN EndOfName = FALSE;
|
||||||
BOOLEAN Result = FALSE;
|
BOOLEAN Result;
|
||||||
BOOLEAN DontSkipDot;
|
BOOLEAN DontSkipDot;
|
||||||
WCHAR CompareChar;
|
WCHAR CompareChar;
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue