IOCTLを上位フィルタードライバー(kbfiltr / moufiltr)に送信してデバイスを有効/無効にする未加工のPDO
-
07-07-2019 - |
質問
私は、ドライバー開発を始めたばかりで、キーボードまたはマウスデバイスを有効または無効にする簡単なフィルタードライバーを作成しようとしています。私はそれを動作させることができれば、マウスが接続されているときにラップトップのタッチパッドを無効にするためにそれを使用したいと思います。自分でこれを行う方法を学びます。
WDKに付属し、上位フィルタードライバーとしてインストールされている kbfiltr および moufiltr の例を使用しています。 kbfiltrの例は、ユーザーモードプログラムによって列挙および接続できるpdoを作成します。これにより、 KbFilter_EvtIoDeviceControlForRawPdo によって処理されるIOCTLをPDOに送信できます。ただし、 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を引き起こします。これは、おそらくkbfiltrではなくPDO devExtであるためでしょうか。
(関連:BSODからスタックトレースを取得する良い方法は何ですか?テスト環境としてVirtual PCを使用し、XPSP3の未チェックビルドを使用しています)
IOCTL_INTERNAL_KEYBOARD_DISCONNECTをドライバースタックに直接送信できない(入力デバイスが一度に1つの接続のみを受け入れることを理解していますか?)ため、生のPDOが必要です。実際には2つのIOCTLを送信するだけで(有効化および無効化)、キーボードの切断と接続は既に定義されているので使用するだけでした。
これらの仮定のいずれかが間違っている場合はお知らせください、私は本当にこれに慣れていることを知っていますが、PDOを介したこの種の通信に関する多くのドキュメントを見つけていません。
解決
さて、私はついにこれを解決し、私のドライバーは動作しています。
KMDFフィルタードライバーの実装:
WinDbgのセットアップに役立ったため、COMポートアプローチを提案してくれたSergiusに感謝します。 この素晴らしいブログ投稿すぐにセットアップする方法を説明します。基本的には、VPCに名前付きパイプとしてcomポートをセットアップさせ、仮想化OSでカーネルデバッグモードを有効にし、起動中に接続します。そうすれば、ドライバーのロード中にすべてのDbgPrintメッセージを取得でき、さらに多くの操作を実行できますが、起動プロセス中のトレースメッセージだけが非常に役立ちました。
私の主な問題は、KbFiltrで内部IOCTLを再利用しようとしたことだと思います。内部IOCTLと他のIOCTLの違いを理解していなかったため、これは私の悪い設計アイデアでした-IOCTL_INTERNAL_KEYBOARD_DISCONNECTなどの内部IOCTLSはアクセス条件が制限されており、他のドライバーまたはカーネルによってのみ送信されるべきです。また、このKB記事" IOCTLをフィルタードライバーに送信する方法" は、同じコントロールを使用した例です。デバイス構造ですが、WDMです。
とにかく、週末ずっとKbFiltrの例と戦った後、私はついにあきらめて WDF Toaster / filtrの例。これはより基本的なKMDFフィルタードライバーであり、KbFiltrとMouFiltrを使用して多くの空白を埋める必要がありました。 Toasterフィルタードライバーの操作はKbFiltrに似ていますが、PDOの代わりに制御デバイスを作成します。また、制御デバイスのdosデバイス名を設定するため、そのステップを実行するためにPinvokeする必要なく、ユーザーモードから制御デバイスと通信できます。制御デバイスを使用すると、コレクションを反復処理するだけで、フィルタードライバーが読み込まれているすべてのデバイスを制御できます。ウェイトロックは、コレクションへのアクセスを同期するために使用されます。
(Toasterクラスの代わりにMouseクラスを使用するために)INFファイルを変更し、ドライバーコードを変更せずにテストマシンでそのまま使用することもできました!動作しているものから始めるのはとても簡単です。 このページは、適応するために変更する必要があるものの包括的なリストを提供しますサンプル。
他のヒント
まず第一に:ユーザーモードで、あなたがやりたいことをすることができます(マウスが接続されている場合、ラップトップのタッチパッドを無効にします)。それははるかに簡単で安全です。 デバイスインストール機能の使用および WM_DEVICECHANGE
コードの問題をデバッグするには:BSODからメモリダンプを取得するか、カーネルデバッガー接続をセットアップします(パイプにリダイレクトされた仮想PCのCOMポートを使用)。 Windows用デバッグツール
を参照してください。楽しんでください!