PDO non elaborato per inviare IOCTL al driver filtro superiore (kbfiltr / moufiltr) per abilitare / disabilitare il dispositivo

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

Domanda

Sono abbastanza nuovo nello sviluppo di driver e sto provando a scrivere un semplice driver di filtro che abiliterà o disabiliterà un dispositivo tastiera o mouse. Se riesco a farlo funzionare, voglio usarlo per disabilitare il touchpad sul mio laptop quando è collegato un mouse. Mi rendo conto che probabilmente esiste già un software là fuori che lo fa già, ma sono davvero interessato ai driver di dispositivo e voglio impara a farlo da solo.

Sto usando gli esempi kbfiltr e moufiltr forniti con il WDK, installato come driver di filtro superiore. L'esempio kbfiltr crea un pdo che può essere enumerato e collegato da un programma usermode. Questo mi consente di inviare IOCTL al PDO che sono gestiti da KbFilter_EvtIoDeviceControlForRawPdo . Tuttavia, quando provo a fare qualsiasi cosa relativa al driver del filtro, come chiamare in KbFilter_EvtIoInternalDeviceControl in modo da poter fare qualcosa del genere

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;
    ...
    }

Ricevo un BSOD. Non è il codice sopra, nell'esempio vanilla viene commentato il set su null, solo chiamare in Kbfilter provoca BSOD. Ho provato a impostare l'estensione del dispositivo direttamente nel PDO ma questo causa anche un BSOD, presumibilmente perché è il devExt PDO, non quello di kbfiltr?

(correlato: qual è un buon modo per ottenere la traccia dello stack da un BSOD? Sto usando Virtual PC come ambiente di test e una build non controllata di XPSP3)

Non riesco a inviare un IOCTL_INTERNAL_KEYBOARD_DISCONNECT direttamente allo stack del driver (capisco che i dispositivi di input accettano solo una connessione alla volta?), quindi la necessità del PDO non elaborato. Ho davvero solo bisogno di inviare due IOCTL (per abilitare e disabilitare) e ho pensato che avrei semplicemente usato la disconnessione e la connessione della tastiera poiché queste erano già definite.

Se sbaglio su una di queste assunzioni, per favore fatemi sapere, so di essere davvero un noob in questo, ma non ho trovato molta documentazione su questo tipo di comunicazione tramite un PDO.

È stato utile?

Soluzione

Ok, ho finalmente risolto questo problema e il mio driver funziona.

Implementazione di un driver di filtro KMDF :

Grazie a Sergius che mi ha suggerito l'approccio della porta COM perché questo mi ha aiutato a configurare WinDbg. Questo fantastico post sul blog spiega come configurarlo rapidamente, in pratica si consente a VPC di configurare una porta com come pipe denominata, abilitare la modalità di debug del kernel sul sistema operativo virtualizzato e connettersi ad esso durante l'avvio. Quindi è possibile ottenere tutti i messaggi DbgPrint durante il caricamento del driver e fare molto di più, ma solo i messaggi di traccia durante il processo di avvio sono stati di grande aiuto per me.

Penso che il mio problema principale fosse cercare di riutilizzare un IOCTL interno in KbFiltr. Questa è stata solo una cattiva idea di progettazione da parte mia perché non ho capito la differenza tra IOCTL interno e altri IOCTL - IOCTL interni come IOCTL_INTERNAL_KEYBOARD_DISCONNECT hanno condizioni di accesso limitate e dovrebbero essere inviati solo da altri driver o dal kernel. Anche questo articolo KB " Come inviare IOCTL al filtro driver " è un esempio usando lo stesso controllo struttura del dispositivo, ma è WDM.

Comunque, dopo aver combattuto con l'esempio di KbFiltr per tutto il fine settimana, alla fine ho rinunciato e ho ricominciato usando Esempio di tostapane / filtro WDF . Questo è un driver di filtro KMDF più barebone e ho dovuto riempire molti spazi vuoti usando KbFiltr e MouFiltr. L'operazione del driver del filtro Toaster è simile a KbFiltr ma crea un dispositivo di controllo anziché un PDO. Imposta anche un nome dispositivo dos per il dispositivo di controllo in modo da poter comunicare con esso dal codice utente senza dover eseguire Pinvoke per eseguire quel passaggio. Il dispositivo di controllo consente di controllare tutti i dispositivi su cui è caricato il driver del filtro semplicemente ripetendo la raccolta. Un waitlock viene utilizzato per sincronizzare l'accesso alla raccolta.

Sono stato anche in grado di modificare il file INF (per utilizzare la classe Mouse anziché la classe Toaster) e applicarlo immediatamente sulla mia macchina di prova senza alcuna modifica al codice del driver! È molto più facile iniziare con qualcosa che sta funzionando. Questa pagina fornisce un elenco completo di cose che dovresti cambiare per adattarti i campioni.

Altri suggerimenti

Prima di tutto: puoi fare quello che vuoi fare (disabilitare il touchpad sul mio laptop quando è collegato un mouse) in modalità utente. Sarà molto più semplice e sicuro. Guarda Uso delle funzioni di installazione del dispositivo e WM_DEVICECHANGE

Per eseguire il debug di problemi nel codice: ottenere un dump della memoria da BSOD o configurare una connessione debugger del kernel (utilizzando una porta COM sul PC virtuale reindirizzata a una pipe). Vedi Strumenti di debug per Windows

Buon divertimento!

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top