IN BOOLEAN IgnoreCase,
IN PWCHAR UpcaseTable OPTIONAL)
{
- SHORT StarFound = -1;
- PUSHORT BackTracking = NULL;
+ USHORT Offset, Position, BackTrackingPosition, OldBackTrackingPosition;
+ USHORT BackTrackingBuffer[16], OldBackTrackingBuffer[16] = {0};
+ PUSHORT BackTrackingSwap, BackTracking = BackTrackingBuffer, OldBackTracking = OldBackTrackingBuffer;
UNICODE_STRING IntExpression;
- USHORT ExpressionPosition = 0, NamePosition = 0, MatchingChars;
+ USHORT ExpressionPosition, NamePosition = 0, MatchingChars = 1;
+ BOOLEAN EndOfName = FALSE;
+ BOOLEAN Result;
+ BOOLEAN DontSkipDot;
WCHAR CompareChar;
PAGED_CODE();
if (!Name->Length || !Expression->Length)
{
/* Return TRUE if both strings are empty, otherwise FALSE */
- if (Name->Length == 0 && Expression->Length == 0)
+ if (!Name->Length && !Expression->Length)
return TRUE;
else
return FALSE;
}
}
- while ((NamePosition < Name->Length / sizeof(WCHAR)) &&
- (ExpressionPosition < Expression->Length / sizeof(WCHAR)))
+ /* Name parsing loop */
+ for (; !EndOfName; MatchingChars = BackTrackingPosition, NamePosition++)
{
- /* Basic check to test if chars are equal */
- CompareChar = IgnoreCase ? UpcaseTable[Name->Buffer[NamePosition]] :
- Name->Buffer[NamePosition];
- if (Expression->Buffer[ExpressionPosition] == CompareChar)
- {
- NamePosition++;
- ExpressionPosition++;
- }
- /* Check cases that eat one char */
- else if (Expression->Buffer[ExpressionPosition] == L'?' || (Expression->Buffer[ExpressionPosition] == DOS_QM) ||
- (Expression->Buffer[ExpressionPosition] == DOS_DOT && Name->Buffer[NamePosition] == L'.'))
+ /* Reset positions */
+ OldBackTrackingPosition = BackTrackingPosition = 0;
+
+ if (NamePosition >= Name->Length / sizeof(WCHAR))
{
- NamePosition++;
- ExpressionPosition++;
+ EndOfName = TRUE;
+ if (MatchingChars && (OldBackTracking[MatchingChars - 1] == Expression->Length * 2))
+ break;
}
- /* Test star */
- else if (Expression->Buffer[ExpressionPosition] == L'*')
+
+ while (MatchingChars > OldBackTrackingPosition)
{
- /* Skip contigous stars */
- while ((ExpressionPosition + 1 < (USHORT)(Expression->Length / sizeof(WCHAR))) &&
- (Expression->Buffer[ExpressionPosition + 1] == L'*'))
- {
- ExpressionPosition++;
- }
+ ExpressionPosition = (OldBackTracking[OldBackTrackingPosition++] + 1) / 2;
- /* Save star position */
- if (!BackTracking)
+ /* Expression parsing loop */
+ for (Offset = 0; ExpressionPosition < Expression->Length; Offset = sizeof(WCHAR))
{
- BackTracking = ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE,
- (Expression->Length / sizeof(WCHAR)) * sizeof(USHORT),
- 'nrSF');
- }
- BackTracking[++StarFound] = ExpressionPosition++;
+ ExpressionPosition += Offset;
- /* If star is at the end, then eat all rest and leave */
- if (ExpressionPosition == Expression->Length / sizeof(WCHAR))
- {
- NamePosition = Name->Length / sizeof(WCHAR);
+ 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 + sizeof(WCHAR)) * sizeof(USHORT),
+ '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 + sizeof(WCHAR)) * sizeof(USHORT),
+ 'nrSF');
+ /* Copy old buffer content */
+ RtlCopyMemory(OldBackTracking,
+ OldBackTrackingBuffer,
+ RTL_NUMBER_OF(OldBackTrackingBuffer) * sizeof(USHORT));
+ }
+
+ /* Basic check to test if chars are equal */
+ CompareChar = (NamePosition >= Name->Length / sizeof(WCHAR)) ? UNICODE_NULL : (IgnoreCase ? UpcaseTable[Name->Buffer[NamePosition]] :
+ Name->Buffer[NamePosition]);
+ if (Expression->Buffer[ExpressionPosition / sizeof(WCHAR)] == CompareChar && !EndOfName)
+ {
+ BackTracking[BackTrackingPosition++] = (ExpressionPosition + sizeof(WCHAR)) * 2;
+ }
+ /* Check cases that eat one char */
+ else if (Expression->Buffer[ExpressionPosition / sizeof(WCHAR)] == L'?' && !EndOfName)
+ {
+ BackTracking[BackTrackingPosition++] = (ExpressionPosition + sizeof(WCHAR)) * 2;
+ }
+ /* Test star */
+ else if (Expression->Buffer[ExpressionPosition / sizeof(WCHAR)] == L'*')
+ {
+ BackTracking[BackTrackingPosition++] = ExpressionPosition * 2;
+ BackTracking[BackTrackingPosition++] = (ExpressionPosition * 2) + 3;
+ continue;
+ }
+ /* Check DOS_STAR */
+ else if (Expression->Buffer[ExpressionPosition / sizeof(WCHAR)] == DOS_STAR)
+ {
+ /* Look for last dot */
+ DontSkipDot = TRUE;
+ if (!EndOfName && Name->Buffer[NamePosition] == '.')
+ {
+ for (Position = NamePosition - 1; Position < Name->Length; Position++)
+ {
+ if (Name->Buffer[Position] == L'.')
+ {
+ DontSkipDot = FALSE;
+ break;
+ }
+ }
+ }
+
+ if (EndOfName || Name->Buffer[NamePosition] != L'.' || !DontSkipDot)
+ BackTracking[BackTrackingPosition++] = ExpressionPosition * 2;
+
+ BackTracking[BackTrackingPosition++] = (ExpressionPosition * 2) + 3;
+ continue;
+ }
+ /* Check DOS_DOT */
+ else if (Expression->Buffer[ExpressionPosition / sizeof(WCHAR)] == DOS_DOT)
+ {
+ if (EndOfName) continue;
+
+ if (Name->Buffer[NamePosition] == L'.')
+ BackTracking[BackTrackingPosition++] = (ExpressionPosition + sizeof(WCHAR)) * 2;
+ }
+ /* Check DOS_QM */
+ else if (Expression->Buffer[ExpressionPosition / sizeof(WCHAR)] == DOS_QM)
+ {
+ if (EndOfName || Name->Buffer[NamePosition] == L'.') continue;
+
+ BackTracking[BackTrackingPosition++] = (ExpressionPosition + sizeof(WCHAR)) * 2;
+ }
+
+ /* Leave from loop */
break;
}
- else if (Expression->Buffer[ExpressionPosition] != L'?')
- {
- NamePosition++;
- }
- }
- /* Check DOS_STAR */
- else if (Expression->Buffer[ExpressionPosition] == DOS_STAR)
- {
- MatchingChars = NamePosition;
- while (MatchingChars < Name->Length / sizeof(WCHAR))
+
+ for (Position = 0; MatchingChars > OldBackTrackingPosition && Position < BackTrackingPosition; Position++)
{
- if (Name->Buffer[MatchingChars] == L'.')
+ while (MatchingChars > OldBackTrackingPosition &&
+ BackTracking[Position] > OldBackTracking[OldBackTrackingPosition])
{
- NamePosition = MatchingChars;
+ ++OldBackTrackingPosition;
}
- MatchingChars++;
}
- ExpressionPosition++;
- }
- /* If nothing match, try to backtrack */
- else if (StarFound >= 0)
- {
- ExpressionPosition = BackTracking[StarFound--];
- }
- /* Otherwise, fail */
- else
- {
- break;
}
- /* Under certain circumstances, expression is over, but name isn't
- * and we can backtrack, then, backtrack */
- if (ExpressionPosition == Expression->Length / sizeof(WCHAR) &&
- NamePosition != Name->Length / sizeof(WCHAR) &&
- StarFound >= 0)
- {
- ExpressionPosition = BackTracking[StarFound--];
- }
- }
- if (ExpressionPosition + 1 == Expression->Length / sizeof(WCHAR) && NamePosition == Name->Length / sizeof(WCHAR) &&
- Expression->Buffer[ExpressionPosition] == DOS_DOT)
- {
- ExpressionPosition++;
+ /* Swap pointers */
+ BackTrackingSwap = BackTracking;
+ BackTracking = OldBackTracking;
+ OldBackTracking = BackTrackingSwap;
}
- if (BackTracking)
- {
+ /* Store result value */
+ Result = MatchingChars > 0 && (OldBackTracking[MatchingChars - 1] == (Expression->Length * 2));
+
+ /* Frees the memory if necessary */
+ if (BackTracking != BackTrackingBuffer && BackTracking != OldBackTrackingBuffer)
ExFreePoolWithTag(BackTracking, 'nrSF');
- }
+ if (OldBackTracking != BackTrackingBuffer && OldBackTracking != OldBackTrackingBuffer)
+ ExFreePoolWithTag(OldBackTracking, 'nrSF');
- return (ExpressionPosition == Expression->Length / sizeof(WCHAR) && NamePosition == Name->Length / sizeof(WCHAR));
+ return Result;
}
/* PUBLIC FUNCTIONS **********************************************************/
if (!NT_SUCCESS(Status)) RtlRaiseStatus(Status);
/* Upcase the second string too */
- RtlUpcaseUnicodeString(&UpcaseName2, Name2, TRUE);
+ Status = RtlUpcaseUnicodeString(&UpcaseName2, Name2, TRUE);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeUnicodeString(&UpcaseName1);
+ RtlRaiseStatus(Status);
+ }
+
Name1 = &UpcaseName1;
Name2 = &UpcaseName2;