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

View file

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