Raw PDO для отправки IOCTL в драйвер верхнего фильтра (kbfiltr/moufiltr) для включения / выключения устройства

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

Я использую примеры kbfiltr и moufiltr, которые поставляются с WDK, установленным в качестве драйверов верхнего фильтра. Пример kbfiltr создает pdo, который может быть перечислен и подключен программой пользовательского режима. Это позволяет мне отправлять IOCTL в PDO, которые обрабатываются KbFilter_EvtIoDeviceControlForRawPdo. Тем не менее, когда я пытаюсь сделать что-либо вообще, связанное с драйвером фильтра, например, вызвать KbFilter_EvtIoInternalDeviceControl, чтобы я мог сделать что-то вроде

VOID
KbFilter_EvtIoInternalDeviceControl(
    IN WDFQUEUE      Queue,
    IN WDFREQUEST    Request,
    IN size_t        OutputBufferLength,
    IN size_t        InputBufferLength,
    IN ULONG         IoControlCode
    )
    ...
    hDevice = WdfIoQueueGetDevice(Queue);
    devExt = FilterGetData(hDevice);

    switch (IoControlCode) {      
    ...
      case IOCTL_INTERNAL_KEYBOARD_DISCONNECT:
       //
       // Clear the connection parameters in the device extension.
       //
       devExt->UpperConnectData.ClassService = NULL;
       break;
    ...
    }

Я получаю BSOD. Это не приведенный выше код, в ванильном примере закомментировано значение null, просто вызов Kbfilter вызывает BSOD. Я пытался установить расширение устройства непосредственно в PDO, но это также вызывает BSOD, предположительно потому, что это PDE devExt, а не kbfiltr?

(связанный: каков хороший способ получения трассировки стека от BSOD? Я использую Virtual PC в качестве тестовой среды и непроверенную сборку XPSP3)

Я не могу отправить IOCTL_INTERNAL_KEYBOARD_DISCONNECT непосредственно в стек драйверов (я так понимаю, что устройства ввода принимают только одно соединение за раз?), Следовательно, необходима необработанная PDO. Мне действительно нужно всего лишь отправить два IOCTL (для включения и выключения), и я решил, что просто использовал бы отключение клавиатуры и подключение, так как они уже были определены.

Если я ошибаюсь по поводу любого из этих предположений, пожалуйста, дайте мне знать, я знаю, что я действительно нуб, но я не нашел много документации об этом виде связи через PDO.

2 ответа

Решение

Хорошо, я наконец решил это, и мой драйвер работает.

Реализация драйвера фильтра KMDF:

Спасибо Сергию, который предложил подход с COM-портом, потому что это помогло мне настроить WinDbg. Этот замечательный пост в блоге объясняет, как быстро настроить его, в основном вы позволяете VPC настроить com-порт в качестве именованного канала, включить режим отладки ядра в виртуализированной ОС и подключаться к нему во время загрузки. Затем вы можете получить все сообщения DbgPrint во время загрузки драйвера и делать гораздо больше, но только сообщения трассировки во время запуска очень помогли мне.

Я думаю, что моей главной проблемой была попытка повторно использовать внутренний IOCTL в KbFiltr. С моей стороны это была просто плохая идея проекта, потому что я не понимал разницу между внутренним IOCTL и другими IOCTL - внутренние IOCTLS, такие как IOCTL_INTERNAL_KEYBOARD_DISCONNECT, имеют условия ограниченного доступа и должны отправляться только другими драйверами или ядром. Также эта статья базы знаний "Как отправить IOCTL в драйвер фильтра" является примером, использующим ту же структуру устройства управления, но это WDM.

Во всяком случае, после того, как все выходные боролся с примером KbFiltr, я наконец сдался и начал заново, используя пример WDF Toaster/filters. Это более простой драйвер фильтра KMDF, и мне пришлось заполнить много пробелов, используя KbFiltr и MouFiltr. Работа драйвера фильтра Toaster аналогична KbFiltr, но вместо PDO создает управляющее устройство. Он также задает имя устройства DOS для устройства управления, чтобы вы могли общаться с ним из пользовательского режима, не выполняя Pinvoke для выполнения этого шага. Управляющее устройство позволяет вам контролировать все устройства, на которых загружен драйвер фильтра, просто перебирая коллекцию. Блокировка ожидания используется для синхронизации доступа к коллекции.

Я также смог просто изменить файл INF (чтобы использовать класс Mouse вместо класса Toaster) и применить его прямо из коробки на моей тестовой машине без изменения кода драйвера! Намного легче начать с чего-то, что работает. На этой странице представлен полный список вещей, которые вы должны изменить, чтобы адаптировать образцы.

Прежде всего: вы можете делать то, что вы хотите (отключить тачпад на моем ноутбуке, когда мышь подключена) в пользовательском режиме. Это будет намного проще и безопаснее. Посмотрите на использование функций установки устройства и WM_DEVICECHANGE

Для устранения проблем в вашем коде: Получите дамп памяти из BSOD или настройте соединение с отладчиком ядра (используя COM-порт на вашем виртуальном ПК, перенаправленный на канал). См. Инструменты отладки для Windows

Повеселись!

Другие вопросы по тегам