2009-09-16 8 views
19

Я довольно новичок в разработке драйверов и пытаюсь написать простой драйвер фильтра, который включит или отключит клавиатуру или мышь. Если я смогу заставить его работать, я хочу использовать его, чтобы отключить тачпад на моем ноутбуке, когда мышь подключена. Я понимаю, что есть, вероятно, программное обеспечение, которое делает это уже, но я действительно заинтересован в драйверах устройств и хочу научитесь самому это делать.Raw PDO для отправки IOCTL в верхний драйвер фильтра (kbfiltr/moufiltr) для включения/выключения устройства

Я использую kbfiltr и moufiltr примеры, которые поставляются с WDK, установленные в верхних драйверов фильтров. Пример kbfiltr создает pdo, который можно перечислить и связать с помощью программы usermode. Это позволяет мне отправлять IOCTLs в 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. Это не приведенный выше код, в примере с ванилью закомментирован набор с нулевым значением, просто вызов в Kbfilter вызывает BSOD. Я попытался установить расширение устройства непосредственно в PDO, но это также вызывает BSOD, предположительно потому, что это PDO devExt, а не kbfiltr?

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

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

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

ответ

16

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

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

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

Я думаю, что моя основная проблема заключалась в том, чтобы повторно использовать внутренний IOCTL в KbFiltr.Это была всего лишь плохая идея дизайна с моей стороны, потому что я не понимал разницы между внутренними IOCTL и другими IOCTL. - Внутренние IOCTLS, такие как IOCTL_INTERNAL_KEYBOARD_DISCONNECT, имеют ограниченные условия доступа и могут быть отправлены только другими драйверами или ядром. Также this KB article "How to send IOCTL to filter driver" является примером, использующим одну и ту же структуру устройства управления, но это WDM.

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

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

+2

Мой первый и, возможно, последний, +1 комментарий! Сэкономил мне часы ... спасибо кучу за то, что нашли время, чтобы отформатировать ваш ответ ... отлично! –

+0

Мне интересно, можете ли вы поделиться кодом драйвера для клавиатуры. Я пытаюсь включить/отключить USB-клавиатуру (от многих, которых я подключил к компьютеру для особых целей), но мне было трудно понять, как это сделать. Попытка с развитием драйвера фильтра, но она движется медленно. Возможно, вы можете поделиться своими источниками, чтобы узнать, как вам удалось это сделать. – 2010-09-01 02:07:47

+0

Несомненно, Энди, это не проблема, я получил эту работу и использовал службу Windows с WMI, чтобы включить или отключить сенсорную панель, если внешняя мышь была подключена. Как бы вы хотели, чтобы я пришёл к вам? –

3

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

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

Удачи!

+0

Спасибо Серджиус, у вас есть дополнительная информация о функции SetupDi. Мне нужно позвонить, чтобы включить или отключить сенсорную панель (или даже просто отключить ее интерфейс от отправки сообщений)? –

+2

Посмотрите на источники devcon.exe из WINDDK (WINDDK \ 6000 \ tools \ devcon \ i386 \ devcon.exe, WINDDK \ 6000 \ src \ setup \ devcon \\). Он может включать/отключать устройства и делать многое другое с помощью SetupAPI. –