[NTOSKRNL]

Reimplement (yes, once more...) all the DOS wildcards in FsRtlIs*InExpression().
This time with a better understanding of MSDN (doc can be sometimes quite cryptic...).
Which means that now the functions are passing all the tests and are even simpler.

svn path=/trunk/; revision=58847
This commit is contained in:
Pierre Schweitzer 2013-04-24 20:36:33 +00:00
parent a08eef8b31
commit 2840256492
2 changed files with 112 additions and 196 deletions

View file

@ -160,10 +160,9 @@ NTAPI
FsRtlIsDbcsInExpression(IN PANSI_STRING Expression,
IN PANSI_STRING Name)
{
SHORT StarFound = -1;
PUSHORT BackTracking = NULL;
USHORT ExpressionPosition = 0, NamePosition = 0, MatchingChars;
BOOLEAN BeyondName;
SHORT StarFound = -1, DosStarFound = -1;
PUSHORT BackTracking = NULL, DosBackTracking = NULL;
USHORT ExpressionPosition = 0, NamePosition = 0, MatchingChars, LastDot;
PAGED_CODE();
ASSERT(Name->Length);
@ -222,130 +221,84 @@ FsRtlIsDbcsInExpression(IN PANSI_STRING Expression,
/* Check DOS_STAR */
else if (Expression->Buffer[ExpressionPosition] == ANSI_DOS_STAR)
{
/* We can only consume dot if that's not the last one
* Otherwise, we null match
*/
if (Name->Buffer[NamePosition] == '.')
/* Skip contigous stars */
while (ExpressionPosition + 1 < Expression->Length && Expression->Buffer[ExpressionPosition + 1] == ANSI_DOS_STAR)
{
MatchingChars = NamePosition + 1;
while (MatchingChars < Name->Length)
{
if (Name->Buffer[MatchingChars] == '.')
{
NamePosition++;
break;
}
MatchingChars++;
}
/* In case we were already at last dot, simply accept it */
if (MatchingChars == Name->Length)
{
NamePosition++;
}
ExpressionPosition++;
}
else
{
/* XXX: Eat everything till the end */
if (ExpressionPosition + 1 == Expression->Length)
{
NamePosition = Name->Length;
}
/* Try to eat till the next matching char or . */
MatchingChars = NamePosition;
while (MatchingChars < Name->Length)
{
if (ExpressionPosition + 1 < Expression->Length &&
Name->Buffer[MatchingChars] == Expression->Buffer[ExpressionPosition + 1])
{
NamePosition = MatchingChars;
break;
}
else if (Name->Buffer[MatchingChars] == '.')
{
NamePosition = MatchingChars + 1;
break;
}
MatchingChars++;
}
}
ExpressionPosition++;
}
/* Check DOS_DOT */
else if (Expression->Buffer[ExpressionPosition] == DOS_DOT)
{
/* First try to find whether we are beyond last dot (beyond name) */
BeyondName = TRUE;
MatchingChars = NamePosition + 1;
/* Look for last dot */
MatchingChars = 0;
LastDot = (USHORT)-1;
while (MatchingChars < Name->Length)
{
if (Name->Buffer[MatchingChars] == '.')
{
BeyondName = FALSE;
break;
LastDot = MatchingChars;
if (LastDot > NamePosition)
break;
}
MatchingChars++;
}
/* If we are beyond name, we null match */
if (BeyondName)
/* If we don't have dots or we didn't find last yet
* start eating everything
*/
if (MatchingChars != Name->Length || LastDot == (USHORT)-1)
{
if (Name->Buffer[NamePosition] == '.')
{
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++;
}
ExpressionPosition++;
continue;
}
/* If not, we only match a dot */
else if (Name->Buffer[NamePosition] == '.')
{
NamePosition++;
ExpressionPosition++;
continue;
}
/* Otherwise, fail */
else
{
break;
/* 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)
{
/* Check whether we are upon a dot */
MatchingChars = 0;
while (MatchingChars < NamePosition)
{
if (Name->Buffer[MatchingChars] == '.')
{
break;
}
MatchingChars++;
}
/* If not, we match a single char */
if (MatchingChars == NamePosition && Name->Buffer[NamePosition] != '.')
/* We match everything except dots */
if (Name->Buffer[NamePosition] != '.')
{
NamePosition++;
ExpressionPosition++;
}
else
{
/* If we are, we just go through QMs */
while (ExpressionPosition < Expression->Length &&
Expression->Buffer[ExpressionPosition] == ANSI_DOS_QM)
{
ExpressionPosition++;
}
}
ExpressionPosition++;
}
/* If nothing match, try to backtrack */
else if (StarFound >= 0)
{
ExpressionPosition = BackTracking[StarFound--];
}
else if (DosStarFound >= 0)
{
ExpressionPosition = DosBackTracking[DosStarFound--];
}
/* Otherwise, fail */
else
{
@ -379,6 +332,10 @@ FsRtlIsDbcsInExpression(IN PANSI_STRING Expression,
{
ExFreePoolWithTag(BackTracking, 'nrSF');
}
if (DosBackTracking)
{
ExFreePoolWithTag(DosBackTracking, 'nrSF');
}
return (ExpressionPosition == Expression->Length && NamePosition == Name->Length);
}

View file

@ -23,12 +23,11 @@ FsRtlIsNameInExpressionPrivate(IN PUNICODE_STRING Expression,
IN BOOLEAN IgnoreCase,
IN PWCHAR UpcaseTable OPTIONAL)
{
SHORT StarFound = -1;
PUSHORT BackTracking = NULL;
SHORT StarFound = -1, DosStarFound = -1;
PUSHORT BackTracking = NULL, DosBackTracking = NULL;
UNICODE_STRING IntExpression;
USHORT ExpressionPosition = 0, NamePosition = 0, MatchingChars;
USHORT ExpressionPosition = 0, NamePosition = 0, MatchingChars, LastDot;
WCHAR CompareChar;
BOOLEAN BeyondName;
PAGED_CODE();
/* Check if we were given strings at all */
@ -153,130 +152,86 @@ FsRtlIsNameInExpressionPrivate(IN PUNICODE_STRING Expression,
/* Check DOS_STAR */
else if (Expression->Buffer[ExpressionPosition] == DOS_STAR)
{
/* We can only consume dot if that's not the last one
* Otherwise, we null match
*/
if (Name->Buffer[NamePosition] == L'.')
/* Skip contigous stars */
while ((ExpressionPosition + 1 < (USHORT)(Expression->Length / sizeof(WCHAR))) &&
(Expression->Buffer[ExpressionPosition + 1] == DOS_STAR))
{
MatchingChars = NamePosition + 1;
while (MatchingChars < Name->Length / sizeof(WCHAR))
{
if (Name->Buffer[MatchingChars] == L'.')
{
NamePosition++;
break;
}
MatchingChars++;
}
/* In case we were already at last dot, simply accept it */
if (MatchingChars == Name->Length / sizeof(WCHAR))
{
NamePosition++;
}
ExpressionPosition++;
}
else
{
/* XXX: Eat everything till the end */
if (ExpressionPosition + 1 == Expression->Length / sizeof(WCHAR))
{
NamePosition = Name->Length;
}
/* Try to eat till the next matching char or . */
MatchingChars = NamePosition;
while (MatchingChars < Name->Length / sizeof(WCHAR))
{
if (ExpressionPosition + 1 < Expression->Length / sizeof(WCHAR) &&
Name->Buffer[MatchingChars] == Expression->Buffer[ExpressionPosition + 1])
{
NamePosition = MatchingChars;
break;
}
else if (Name->Buffer[MatchingChars] == L'.')
{
NamePosition = MatchingChars + 1;
break;
}
MatchingChars++;
}
}
ExpressionPosition++;
}
/* Check DOS_DOT */
else if (Expression->Buffer[ExpressionPosition] == DOS_DOT)
{
/* First try to find whether we are beyond last dot (beyond name) */
BeyondName = TRUE;
MatchingChars = NamePosition + 1;
/* Look for last dot */
MatchingChars = 0;
LastDot = (USHORT)-1;
while (MatchingChars < Name->Length / sizeof(WCHAR))
{
if (Name->Buffer[MatchingChars] == L'.')
{
BeyondName = FALSE;
break;
LastDot = MatchingChars;
if (LastDot > NamePosition)
break;
}
MatchingChars++;
}
/* If we are beyond name, we null match */
if (BeyondName)
/* If we don't have dots or we didn't find last yet
* start eating everything
*/
if (MatchingChars != Name->Length || LastDot == (USHORT)-1)
{
if (Name->Buffer[NamePosition] == L'.')
{
if (!DosBackTracking) DosBackTracking = ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE,
(Expression->Length / sizeof(WCHAR)) * sizeof(USHORT),
'nrSF');
DosBackTracking[++DosStarFound] = ExpressionPosition++;
/* Not the same char, start exploring */
if (Expression->Buffer[ExpressionPosition] != Name->Buffer[NamePosition])
NamePosition++;
}
ExpressionPosition++;
continue;
}
/* If not, we only match a dot */
else if (Name->Buffer[NamePosition] == L'.')
{
NamePosition++;
ExpressionPosition++;
continue;
}
/* Otherwise, fail */
else
{
break;
/* 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)
{
/* Check whether we are upon a dot */
MatchingChars = 0;
while (MatchingChars < NamePosition)
{
if (Name->Buffer[MatchingChars] == L'.')
{
break;
}
MatchingChars++;
}
/* If not, we match a single char */
if (MatchingChars == NamePosition && Name->Buffer[NamePosition] != L'.')
/* We match everything except dots */
if (Name->Buffer[NamePosition] != L'.')
{
NamePosition++;
ExpressionPosition++;
}
else
{
/* If we are, we just go through QMs */
while (ExpressionPosition < Expression->Length / sizeof(WCHAR) &&
Expression->Buffer[ExpressionPosition] == DOS_QM)
{
ExpressionPosition++;
}
}
ExpressionPosition++;
}
/* If nothing match, try to backtrack */
else if (StarFound >= 0)
{
ExpressionPosition = BackTracking[StarFound--];
}
else if (DosStarFound >= 0)
{
ExpressionPosition = DosBackTracking[DosStarFound--];
}
/* Otherwise, fail */
else
{
@ -311,6 +266,10 @@ FsRtlIsNameInExpressionPrivate(IN PUNICODE_STRING Expression,
{
ExFreePoolWithTag(BackTracking, 'nrSF');
}
if (DosBackTracking)
{
ExFreePoolWithTag(DosBackTracking, 'nrSF');
}
return (ExpressionPosition == Expression->Length / sizeof(WCHAR) && NamePosition == Name->Length / sizeof(WCHAR));
}