Как уведомить приложение пользовательского режима из драйвера windows ndislwf?

Я взял образец образца ndislwf 6.0 и внес некоторые изменения, такие как помещение уникальных входящих ARP-пакетов в связанный список. Я могу получить все данные из пространства пользователя с помощью команды IOCTL. Это очень хорошо.

Теперь я хочу иметь работающее приложение; и как только мой драйвер получает пакет ARP, он должен отправить некоторое уведомление или сигнал клиентскому приложению. Затем клиентское приложение выдаст еще один запрос, который будет получать последние данные.

Я нашел три метода:

  1. Иметь событие и ждать его в клиентском приложении
  2. Иметь ожидающий IRP, и
  3. Используйте именованную трубу.

Я реализовал первый, скопировав дословно реализацию..winddk...\src\general\event проекта.

теперь, так как я не использую таймер, я запутался. Проблема заключается в следующем:

Событие и его ожидание, требуется команда IOCTL. Кэш ARP обновляется по мере поступления нового пакета ARP и добавления его в список. Только когда он добавлен в список, мне нужно сигнализировать. Но это основано на прерывании.

Итак, как мне объединить эти два, чтобы при прерывании от NDIS я уведомлял клиентское приложение.

Я сделал это:

в функции, где я обрабатываю входящий запрос IOCTL, который помещает текущий запрос в DPC

    registerEvent->DueTime.QuadPart = -30;
    KeInitializeDpc(&notifyRecord->Dpc, // Dpc
                    CustomTimerDPC,     // DeferredRoutine
                    notifyRecord        // DeferredContext
                   );
    KeAcquireSpinLock(&deviceExtension->QueueLock, &oldIrql);

    InsertTailList(&deviceExtension->EventQueueHead,
                   &notifyRecord->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(&notifyRecord->Timer,   // Timer
                    registerEvent->DueTime, // DueTime
                    &notifyRecord->Dpc      // Dpc
              );
    return STATUS_SUCCESS;

Теперь происходит то, что первый запрос от клиентского приложения пользовательского пространства иногда завершается успешно, но последующие запросы приводят к ошибке.

Во время отладки я обнаружил, что он указывает на мой код, который я добавил, т.е. если еще и вызов KeSetTimer(). и ошибка связана с тем, что IRQL не меньше или не равен.

Понятия не имею, как это сделать и что рушится. Код больше нигде не падает, но только в этой функции.

Благодарю.

1 ответ

Решение

Похоже, вам нужно уведомить пользовательский режим, когда новый элемент добавляется в вашу очередь данных. Это общая потребность, и общепринятое решение называется моделью "перевернутого вызова". Я думаю, что это вариант № 2 в вашем списке. Поищите в Интернете "перевернутый вызов", чтобы понять, что это такое и как его использовать.

Что касается сбоя, который вы видите - я не знаю, почему ваш код использует таймеры или DPC. Вы должны быть в состоянии сделать это без таймеров или ЦОД.

Обратите внимание, что DueTime.QuadPart измеряется в 100 наносекундных единицах, поэтому относительное время -30 означает 3 микросекунды.

Я предлагаю вам избавиться от таймера и осуществить перевернутый вызов. Если вы действительно хотите, чтобы кто-то помог вам с аварией в вашем таймере, вам следует:

  1. Включите Driver Verifier в вашем драйвере и попробуйте снова. Верификатор часто дает лучшее сообщение об ошибке.
  2. Если вы попробовали верификатор, и он все еще не имеет смысла, опубликуйте вывод "! Analyse -v" с загруженными правильными символами. Включите соответствующие части вашего кода. (Например, где находится notifyRecord выделяется? Что происходит в CustomTimerDPC?)
Другие вопросы по тегам