Есть драйвер — некое подобие filemon.
Проблема заключается в его "выгрузке". Драйвер якобы корректно выгружается, но IRP'ы продолжают приходить. В итоге слетает стек и BSOD.
Очевидно, что допустил ошибку в реализации detach'а дисков, на IRP'ы которых подписался
Невозможно выгрузить legacy FS Filter корректно. Подумайте о фильтрах сверху, например. Пишите минифильтр, если выгружаться все же хочется. Кстати это не единственная причина в пользу мимнифильтров
Доброго!
А>Есть драйвер — некое подобие filemon. А>Проблема заключается в его "выгрузке". Драйвер якобы корректно выгружается, но IRP'ы продолжают приходить. В итоге слетает стек и BSOD.
А>Очевидно, что допустил ошибку в реализации detach'а дисков, на IRP'ы которых подписался
Да, кое-чего не хватает. Идея такая:
1) Detach. После этого новые IRP приходят уже мимо фильтра.
2) (этого-то и не хватает) ждем пока вернутся ушедшие вниз IRP. Точнее, пока вернется управление, ждать Complete'а не нужно, если нет собственных CompletionRoutines. Для этого в цикле проверяем счетчик в DeviceExtension'е. Как только обнулится — значит ни в одном потоке наших адресов уже нет на стеке возврата, можно переходть к 3
3) IoDeleteDevice
А>Вот так пытаюсь "отцепиться" от дисков
device = m_arrDriveHookDevices[drive];
hookExt = (LPHOOK_EXTENSION)device->DeviceExtension;
IoDetachDevice( hookExt->FileSystem );
Delay.QuadPart = -1*1000*1000; // 0.1 secwhile(hookExt->EnterCount) {
KeDelayExecutionThread(KernelMode, FALSE, &Delay); // чтобы другие потоки могли работать
}
/*
а это на всякий случай. Если система сильно нагружена,
мы счетчик можем уже обнулить, а до RET не успеть дойти.
*/
Delay.QuadPart = -50*1000*1000; // 5 sec
KeDelayExecutionThread(KernelMode, FALSE, &Delay);
IoDeleteDevice( device );
Правила форума нарушены.
— оверквотинг
Правила можно найти в разделе FAQ данного форума и\или ресурса.
Нарушение правил может повлечь за собой санкции, описанные там же — модератор
Спасибо. Можно кое-что уточнить?
У меня есть собственные CompletionRoutines. В этом случае сценарий подсчета ссылок будет таким:
1) Когда приходит IRP, счетчик EnterCount увеличивается.
2) И в completionroutine он уменьшается.
Здравствуйте, Alter_, Вы писали:
A_>/* A_>а это на всякий случай. Если система сильно нагружена, A_>мы счетчик можем уже обнулить, а до RET не успеть дойти. A_>*/ A_>Delay.QuadPart = -50*1000*1000; // 5 sec A_>KeDelayExecutionThread(KernelMode, FALSE, &Delay);
я бы не стал использовать такой код в production драйвере — более правильный путь (как уже советовали) перейти на минифильтр, это не только решиит проблему выгрузки, но и значительно упростит логику драйвера.
In WindowsXP the IO Manager will not call a filters DriverUnload routine
until all of its DeviceObjects are at the top of their respective stacks
and there are no more references to them. The problem is that the IO
Manager does not keep track of what IRPs might be pending inside a given
file system stack.
The SFilter and FileSpy examples handle this in their DriverUnload
routines by pausing for 5 seconds after detaching all of their device
objects but before deleting them. This is a reasonable solution for a
filter under development when you want to quickly unload and reload a
new version of the driver. This works most of the time but if a test
machine crashes once in a while, so what; at least you don't have to
reboot every time you want to load a new version of your filter. This
is a totally unreasonable solution for a production filter.
Везде. Невозможно 100% надежно удалить такой фильтр.
Filemon 100% надежным не является. Потому вопросы типа "код, основанный на filemon, иногда валится" не имеют ответа.
Единственный способ написать надежно удаляемый фильтр — это разбить его на 2 части, одна будет неотгружаемый простейший код, который отрабатывает присоединение и удаление, а вторая — уже "смысловая" часть фильтра, которая регистрирует и дерегистрирует себя в неотгружаемой части.
В качестве неотгружаемой части можно использовать готовый микрософтный fltmgr.sys, написав таким образом минифильтр. Вот они отгружаемы.