Как уведомить приложение пользовательского режима из драйвера windows ndislwf?
Я взял образец образца ndislwf 6.0 и внес некоторые изменения, такие как помещение уникальных входящих ARP-пакетов в связанный список. Я могу получить все данные из пространства пользователя с помощью команды IOCTL. Это очень хорошо.
Теперь я хочу иметь работающее приложение; и как только мой драйвер получает пакет ARP, он должен отправить некоторое уведомление или сигнал клиентскому приложению. Затем клиентское приложение выдаст еще один запрос, который будет получать последние данные.
Я нашел три метода:
- Иметь событие и ждать его в клиентском приложении
- Иметь ожидающий IRP, и
- Используйте именованную трубу.
Я реализовал первый, скопировав дословно реализацию..winddk...\src\general\event проекта.
теперь, так как я не использую таймер, я запутался. Проблема заключается в следующем:
Событие и его ожидание, требуется команда IOCTL. Кэш ARP обновляется по мере поступления нового пакета ARP и добавления его в список. Только когда он добавлен в список, мне нужно сигнализировать. Но это основано на прерывании.
Итак, как мне объединить эти два, чтобы при прерывании от NDIS я уведомлял клиентское приложение.
Я сделал это:
в функции, где я обрабатываю входящий запрос IOCTL, который помещает текущий запрос в DPC
registerEvent->DueTime.QuadPart = -30;
KeInitializeDpc(¬ifyRecord->Dpc, // Dpc
CustomTimerDPC, // DeferredRoutine
notifyRecord // DeferredContext
);
KeAcquireSpinLock(&deviceExtension->QueueLock, &oldIrql);
InsertTailList(&deviceExtension->EventQueueHead,
¬ifyRecord->ListEntry);
KeReleaseSpinLock(&deviceExtension->QueueLock, oldIrql);
// check. Arp cache changed or not since last time.
// timer: 0 = delay
if(IsARPCacheModified()){
//if ARP cache is modified, it will return true and end up here.
DbgPrint("ARP Cache modified. Signal.");
// due time is -30. is it relative 30*100ns = 3 secs?
} else{
// if ARP Cache is not modified, it will end up here.
registerEvent->DueTime.QuadPart = -1000;
}
KeSetTimer(¬ifyRecord->Timer, // Timer
registerEvent->DueTime, // DueTime
¬ifyRecord->Dpc // Dpc
);
return STATUS_SUCCESS;
Теперь происходит то, что первый запрос от клиентского приложения пользовательского пространства иногда завершается успешно, но последующие запросы приводят к ошибке.
Во время отладки я обнаружил, что он указывает на мой код, который я добавил, т.е. если еще и вызов KeSetTimer(). и ошибка связана с тем, что IRQL не меньше или не равен.
Понятия не имею, как это сделать и что рушится. Код больше нигде не падает, но только в этой функции.
Благодарю.
1 ответ
Похоже, вам нужно уведомить пользовательский режим, когда новый элемент добавляется в вашу очередь данных. Это общая потребность, и общепринятое решение называется моделью "перевернутого вызова". Я думаю, что это вариант № 2 в вашем списке. Поищите в Интернете "перевернутый вызов", чтобы понять, что это такое и как его использовать.
Что касается сбоя, который вы видите - я не знаю, почему ваш код использует таймеры или DPC. Вы должны быть в состоянии сделать это без таймеров или ЦОД.
Обратите внимание, что DueTime.QuadPart
измеряется в 100 наносекундных единицах, поэтому относительное время -30 означает 3 микросекунды.
Я предлагаю вам избавиться от таймера и осуществить перевернутый вызов. Если вы действительно хотите, чтобы кто-то помог вам с аварией в вашем таймере, вам следует:
- Включите Driver Verifier в вашем драйвере и попробуйте снова. Верификатор часто дает лучшее сообщение об ошибке.
- Если вы попробовали верификатор, и он все еще не имеет смысла, опубликуйте вывод "! Analyse -v" с загруженными правильными символами. Включите соответствующие части вашего кода. (Например, где находится
notifyRecord
выделяется? Что происходит вCustomTimerDPC
?)