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

StackOverflow https://stackoverflow.com/questions/1430798

Вопрос

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

Я использую примеры 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.

Это было полезно?

Решение

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

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

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

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

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

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

Другие советы

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

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

Веселись!

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top