В документации DDK написано, что все функции работы со строками UNICODE_STRING, такие как RtlCompareUnicodeString и даже DbgPrint допустимы только при IRQL=PASSIVE_LEVEL. А что делать со строками, если нужно работать на APC_LEVEL? Мне нужно сравнивать имена модулей, поступающие в callback от PsSetLoadImageNotifyRoutine. Попробовал вызывать функции работы со строками на APC_LEVEL, бсодов пока нет, с чем связано это ограничение и в каких случаях можно его нарушать?
Ограничение связанно с тем, что память, на которую указывает поле Buffer, может быть выделена в подкачиваемом пуле. Нарушать это ограничение нельзя вообще ни при каких условиях (вернее, можно только при работе со своими строками, про которые _точно_ известно, что они находятся в неподкачиваемой памяти). То что BSoD-а нет - просто везение, на других машинах (или под driver verifier-ом) он может появиться. И да, нотификатор на загрузку образов разве не на PASSIVE_LEVEL-е вызывается?
есть ещё и wide-char функции В callback PsSetLoadImageNotifyRoutine не замечал, чтобы UNICODE_STRING - функции вызывали какие-либо проблемы. P.S. Возможно из-за NonPaged памяти
Но ведь отказ страницы может привести к бсоду только если IRQL>=DISPATCH_LEVEL, а на APC_LEVEL это нормальная ситуация и подкачка должна осуществляться прозрачно для моего кода?
Я вот тоже сначала хотел использовать всякие _wcsnicmp вместо системных функций, но потом наткнулся на это сообщение:http://www.wasm.ru/forum/viewtopic.php?pid=385746#p385746
На XP SP2 он вызывается с PASSIVE_LEVEL только для экзешника и NTDLL, а для остальных библиотек уже на APC_LEVEL.
Cr4sh На пассиве. Так что, проблем работы со строками внутри колбека быть не должно. Главное проверять указатель PUNICODE_STRING FullImageName на NULL.
Нет, на пассиве он вызывается только для модуля экзешника и ntdll, а для остальных библиотек уже на APC_LEVEL, по крайней мере у меня на XP SP2 это так.
ntdrivers возможно. Хотя опять же не замечал проблем с тем же DbgPrint(). То о чем пишет ТС - имеет место быть, но не в данной ситуации.
Вот здесь обсуждался вопрос http://www.osronline.com/showthread.cfm?link=169645 Как я понял, ограничение может быть связано с тем, что таблица соответствия для сравнения без учёта регистра находится в выгружаемой памяти. Посмотрел функцию под дизасмом - она простая, без вызовов наружу, вот только идёт обращение к памяти через ds, видимо к этой таблице оно и относится.
Мне нужно именно сравнение без учета регистра, и именно с ним могут быть проблемы на APC_LEVEL, печально.. От использования _wcsnicmp тоже профита наверно не будет, она сама импортируется из NTOSKRNL.EXE.. Как обычно решается проблема работы с unicode на высоких IRQL?
ntdrivers Как вариант - напишите тогда свою процедуру сравнения (благо она не очень то и сложная если известно, что кодировка будет латиницей). И передавайте ей юникод который будет создан только в Nonpaged Pool (для этого юзайте например RtlInitUnicodeString). Либо сравнивать строки в отдельном потоке (передавая ему параметры), в контексте системы на PASSIV_LEVEL. Пока только такие две идеи.
Не факт, что латиница. В документации я заметил интересную штуку: RtlUpcaseUnicodeString допускается вызывать на IRQL<=APC_LEVEL. Варианта два: забить и оставить как есть, благо пока не падало, либо написать свой аналог на основе RtlUpcaseUnicodeString и побайтового сравнения.
TermoSINteZ Для этого ему придётся скопировать сначала из подкачиваемого пула, а тут и вся проблема. Насколько я понимаю, память под строку выделяется отнюдь не его кодом.... Сначала хотел посоветовать IsBadReadPtr, но потом почитал мсдн и отхотелось что-то.... Идея с отдельным потоком пока самая толковая.
Ну и бред понаписали... При чем подкачиваемый пул к APC_LEVEL- не ясно. А причина, на самом деле, в NLS-таблицах, которые могут подгружаться при работе с unicode-строками. Поскольку они открываются и грузятся с применением хотя бы той же ZwCreateFile, для которой существуют вот такие ограничения: Аналогичные ограничения будут накладываться и на функции, типа:
Вот это больше похоже на правду.. А почему тогда RtlUpcaseUnicodeString допускается вызывать на APC_LEVEL?
Потому, что не грузит NLS-таблицы динамически, а использует Nls844UnicodeUpcaseTable, которая инициализируется еще при загрузке системы в KiInitializeKernel. Кстати, в доках не всегда правду пишут, может это связанно с различиями реализаций Rtl* функций на разных ОС, и разрабы MS решили не заморачиваться с правкой MSDN, но часть Rtl* функций все же может работать на APC_LEVEL. Нужно полагаться больше на реверс, чтобы знать точно, что можно, а что нельзя.
Deyton Как раз лучше не полагаться. Со следущей версии работа функции может быть такой, как написано в мсдн в точности (а может и не быть, кто знает). И тогда то, что отработало - не сработает.