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

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

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

16 голосов
/ 24 сентября 2009

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

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

Спасибо Sergius, который предложил подход с 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) и применить его прямо из коробки на моей тестовой машине без изменения кода драйвера! It намного легче начать с чего-то, что работает. На этой странице приведен полный список вещей, которые вы должны изменить, чтобы адаптировать образцы.

3 голосов
/ 16 сентября 2009

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

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

Веселись!

...