EreTIk's Box » Cтатьи, исходники » Нюансы использования FsRtlIsNameInExpression


Разработчикам драйверов режима ядра доступна функция FsRtlIsNameInExpression. Эта функция позволяет сравнивать строковое имя с шаблоном, содержащим wildcard'ы.


Сразу настораживает, что такая не простая функция не возвращает статус NTSTATUS, если происходит ошибка ее исполнения. Взглянем на эту функцию в Windows 8 (build 9200) под дизассемблером (можно параллельно смотреть в код WRK, там ситуация аналогична, Windows 8 выбрана как более актуальная сборка ядра). Сразу бросается в глаза, что если задан параметр IgnoreCase и не задан UpcaseTable, то функция делает локальную копию строки Name в верхнем регистре вызовом RtlUpcaseUnicodeString. Куда же попадает статус ошибки, если перевод в верхний регистр не успешен? В вызов RtlRaiseStatus! То есть генерируется исключение, к которому должен быть готов вызывающий код. Но об этом нет ни слова на странице описания функции. Конечно, именно этот случай легко обойти: в вызывающем коде переводить строку в верхний регистр и указывать сравнение с учетом регистра. Но стоит посмотреть немного глубже. Далее управление передается в неэкспортируемую функцию RtlpIsNameInExpressionPrivate. По одной из веток исполнения этой функции происходит вызов ExAllocatePoolWithTag. Если выделение памяти не удастся, то вызовется RtlRaiseStatus(STATUS_NO_MEMORY).


Вывод из всего вышесказанного простой: вызывать функцию FsRtlIsNameInExpression нужно всегда внутри блоки обработки исключений.


P.S. Функция FsRtlIsDbcsInExpression обладает тем же подводным камнем: может бросить исключение.


Если посмотреть на описание соседних функций FsRtlXxx то, для некоторых явно указано, что они бросают исключение, например:


ΞρεΤΙκ