IN BOOLEAN IgnoreCase,
IN PWCHAR UpcaseTable OPTIONAL)
{
- SHORT StarFound = -1;
- PUSHORT BackTracking = NULL;
+ 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);
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 */
ExpressionPosition++;
}
/* Check cases that eat one char */
- else if (Expression->Buffer[ExpressionPosition] == L'?' || (Expression->Buffer[ExpressionPosition] == DOS_QM))
+ else if (Expression->Buffer[ExpressionPosition] == L'?')
{
NamePosition++;
ExpressionPosition++;
ExpressionPosition++;
}
- /* Save star position */
- if (!BackTracking)
- {
- BackTracking = ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE,
- (Expression->Length / sizeof(WCHAR)) * sizeof(USHORT),
- 'nrSF');
- }
- 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);
break;
}
+
+ /* Save star position */
+ StarFound++;
+ if (StarFound >= BackTrackingSize)
+ {
+ 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++;
+
/* Allow null matching */
- else if (Expression->Buffer[ExpressionPosition] != L'?' &&
+ if (Expression->Buffer[ExpressionPosition] != L'?' &&
Expression->Buffer[ExpressionPosition] != Name->Buffer[NamePosition])
{
NamePosition++;
/* 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))
+ ExpressionPosition++;
+ }
+
+ /* Look for last dot */
+ MatchingChars = 0;
+ LastDot = (USHORT)-1;
+ while (MatchingChars < Name->Length / sizeof(WCHAR))
+ {
+ if (Name->Buffer[MatchingChars] == L'.')
{
- if (Name->Buffer[MatchingChars] == L'.')
- {
- NamePosition++;
+ LastDot = MatchingChars;
+ if (LastDot > NamePosition)
break;
- }
- MatchingChars++;
}
+
+ MatchingChars++;
}
- else
+
+ /* If we don't have dots or we didn't find last yet
+ * start eating everything
+ */
+ if (MatchingChars != Name->Length || LastDot == (USHORT)-1)
{
- /* XXX: Eat everything till the end */
- if (ExpressionPosition + 1 == Expression->Length / sizeof(WCHAR))
+ DosStarFound++;
+ if (DosStarFound >= DosBackTrackingSize)
{
- NamePosition = Name->Length;
+ DosBackTrackingSize = Expression->Length / sizeof(WCHAR);
+ DosBackTracking = ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE,
+ DosBackTrackingSize * sizeof(USHORT),
+ 'nrSF');
+ RtlCopyMemory(DosBackTracking, DosBackTrackingBuffer, sizeof(DosBackTrackingBuffer));
}
+ DosBackTracking[DosStarFound] = ExpressionPosition++;
- /* 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++;
- }
+ /* 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++;
}
- 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;
- 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)
+ /* We only match dots */
+ if (Name->Buffer[NamePosition] == L'.')
{
- ExpressionPosition++;
- continue;
+ NamePosition++;
}
- /* If not, we only match a dot */
- else if (Name->Buffer[NamePosition] == L'.')
+ /* 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++;
- continue;
}
- /* Otherwise, fail */
- else
+ ExpressionPosition++;
+ }
+ /* Check DOS_QM */
+ else if (Expression->Buffer[ExpressionPosition] == DOS_QM)
+ {
+ /* We match everything except dots */
+ if (Name->Buffer[NamePosition] != L'.')
{
- break;
+ 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
{
}
}
- if (BackTracking)
+ if (BackTracking != BackTrackingBuffer)
{
ExFreePoolWithTag(BackTracking, 'nrSF');
}
+ if (DosBackTracking != DosBackTrackingBuffer)
+ {
+ ExFreePoolWithTag(DosBackTracking, 'nrSF');
+ }
return (ExpressionPosition == Expression->Length / sizeof(WCHAR) && NamePosition == Name->Length / sizeof(WCHAR));
}