none
デバイスドライバで、特定のデバイスインタフェースを使用した時のみCreate要求を完了させたい RRS feed

  • 質問

  • はじめまして。
    KMDFベースでデバイスインタフェースを持つフィルタドライバを作成しようとしております。

    ドライバのEvtDeviceFileCreateが呼ばれた際、上記デバイスインタフェースを使ったファイルオープンのときのみ、
    STATUS_SUCCESSのみで要求を完了させる(=ユーザーモードアプリのCreateFile()を成功させる)というようなことは可能なのでしょうか?これ以外のファイルオープンのときは下位ドライバに判断を任せたいのです。


    WDFの解説によると、WDFドライバーはCreate要求をすべて完了させるか、すべてForwardするかどちらかにする必要があるとの記述があったため、EvtDeviceFileCreate内でファイル名によってCompleteかForwardか処理を分けるというような単純な分岐では無理なのかもしれません。

    何か関連する情報をお持ちの方、どうぞご教示ください。
    よろしくお願いいたします。

    2012年10月9日 15:02

すべての返信

  • どのようなタイプのデバイスに対するフィルタ ドライバを、どのような目的で作成されているのか分からないので、適切なコメントでない可能性がありますが。。。


    > KMDFベースでデバイスインタフェースを持つフィルタドライバを作成しようとしております。
    ここで仰っている「デバイスインタフェースを持つ」とは、自作されてるフィルタドライバだけで処理が完結する、フィルタドライバとだけ通信を行うためのインターフェースのことでしょうか?
    もしこの推測に該当している場合、そのインターフェースはデバイス スタックにアタッチさせているフィルタ デバイス オブジェクト(KMDF なので厳密に言うと、フィルタ ドライバのフレームワーク デバイス オブジェクト)とは完全に独立した実装を行う必要があると思います。
    (以降のコメントも、上記推測に該当していることを前提としたものです。)


    > ドライバのEvtDeviceFileCreateが呼ばれた際、上記デバイスインタフェースを使ったファイルオープンのときのみ、
    >  STATUS_SUCCESSのみで要求を完了させる(=ユーザーモードアプリのCreateFile()を成功させる)というようなことは可能なのでしょうか?
    > これ以外のファイルオープンのときは下位ドライバに判断を任せたいのです。
    1つのデバイス オブジェクトでは不可能ですが、複数のデバイス オブジェクトを持てば、実現することは可能だと思います。
    説明の重複になりますが、デバイス スタックにアタッチさせたフィルタ デバイス オブジェクトとは全く別に、別途コントロール デバイス オブジェクトを作成すれば可能。。。ということです。
    フィルタ デバイス オブジェクトとコントロール デバイス オブジェクトを別々に持つので、EvtDeviceFileCreate などのコールバック ルーチンもそれぞれ別々に実装する必要があると思います。
    (↑コールバック ルーチンのエントリは1つでも構わないが、内部の処理は完全に分離させる必要がある。。。という意味)


    > WDFの解説によると、WDFドライバーはCreate要求をすべて完了させるか、すべてForwardするかどちらかにする必要があるとの記述があったため、
    > EvtDeviceFileCreate内でファイル名によってCompleteかForwardか処理を分けるというような単純な分岐では無理なのかもしれません。
    上記ご質問は、1つのデバイス オブジェクト(フィルタ デバイス オブジェクト)であることを前提とした内容であると思いますが、その場合は無理だと思います。


    > 何か関連する情報をお持ちの方、どうぞご教示ください。
    KMDF ではそのような実装を行ったサンプルは無いと思いますが、WDM や Filesystem (Filter) Driver では、そのようなサンプルが存在しています。
    Vista 時代の WDK まで添付されていた "sfilter" という Filesystem Filter Driver でも、そんなような実装がされていました。


    以上、参考になりましたら幸いに存じます。

    2012年10月11日 10:58
  • 返信ありがとうございます。

    うまくお伝えできておらず恐縮です。
    「デバイスインタフェース」と記載したものは、WdfDeviceCreateDeviceInterface()またはIoRegisterDeviceInterface()で作成するインタフェースのことです。
    これらで作成できるインタフェースはデバイススタック上にあるデバイスオブジェクトでしか作成できなかったと思います。
    そのため、ご提示いただいているコントロールデバイスオブジェクトを作成した方法(Toastサンプルのsidebandで提示されている方法ですよね)では、残念ながら使用できなかったと記憶しております。

    コントロールデバイスオブジェクトを使用した方法では、ユーザーモードアプリとのインタフェースはシンボリックリンクを使用したもの(WdfDeviceCreateSymbolicLink()を使用)になるかと思います。
    しかしユーザーモードアプリ側の事情でシンボリックリンクではなく、WdfDeviceCreateDeviceInterface()を使用して作成されるインタフェースを使用する必要があり、今回のような質問させていただきました。

    今回作成するフィルタドライバの下位にいるドライバが既製品でありソースコードを改変できないため、下位のドライバのデバイスインタフェースに対するCreateFile()要求を弾くことなくフィルタドライバ側の動作を行いたいと考えております。

    2012年10月11日 13:25
  • >「デバイスインタフェース」と記載したものは、WdfDeviceCreateDeviceInterface()またはIoRegisterDeviceInterface()で作成するインタフェースのことです。

    私の質問の仕方が悪かったせいか、質問の意図がうまく伝わらなかったみたいですね。。。
    「デバイスインタフェース」についてお伺いしたかったことは、ドライバの実装的なことではなく、自作されているドライバの要求仕様としての機能です。
    どのようなタイプのデバイスに対するフィルタ ドライバ(Bus Driver Filter, Class Driver Filter, Functional Driver Filter)を開発されていて、どのような目的で「デバイスインタフェース」が必要になったのかが知りたかったのです。
    それが明確にならないと、その目的に対して、コントロール デバイス オブジェクト (以降:CDO) を作成することで対応出来るのか、あるいは既存のフィルタ デバイス オブジェクト (以降:FiDO) を流用することで対応できるのかが、適切に判断できないと考えているからです。
    (もちろん、お仕事絡みのお話だと思いますので、開示できない部分については、それ以上穿鑿するつもりもありません。)


    > これらで作成できるインタフェースはデバイススタック上にあるデバイスオブジェクトでしか作成できなかったと思います。
    > そのため、ご提示いただいているコントロールデバイスオブジェクトを作成した方法(Toastサンプルのsidebandで提示されている方法ですよね)では、
    > 残念ながら使用できなかったと記憶しております。

    私が提案させていただいた方法は、ご推察の通り、Toaster sideband で提示されている方法です。
    (先の返信では、KMDF では CDO を示したサンプルは無いと書いてしまいましたが、ありましたね。大変申し訳ございませんでした。)
    FiDO であれ、 CDO であれ、NT カーネルから見たら "デバイス オブジェクト" であることに変わりはないはずです。
    なので、CDO だからデバイスインタフェースは作れない。。。ということは無いと思います。
    ただし CDO は、それを作成したドライバ自身がすべてを管理しないといけないはずです。
    さらに、CDO は対応する実デバイスを持ちませんので、このデバイス オブジェクトに対して PnP (IRP_MJ_PNP) リクエストは来ないはずです。
    ドライバが提供するデバイスインタフェースは、PnP リクエストと密接に関連しますが、CDO は性質上この様な制限があるため、デバイスインタフェースを割り当てるのは不向きというだけのことで、不可能ということでは無いと思います。
    Toaster sideband サンプルがシンボリックリンクを使用してユーザー モード側アプリにインターフェースを提供しているのは、この制限に対する手間を省くためだと個人的に思っています。(あるいは、そんな手間を掛けてもあんまり意味が無いと思っているのかも。。。)
    要するに CDO に対してデバイスインタフェースを割り当てる場合、ドライバ側はその CDO を管理するために必要な PnP 等のリクエストをすべて自力でハンドリングしなければならず、かつ CDO を利用するアプリ側は、SetupDiSetClassInstallParams() / SetupDiCallClassInstaller() 等の Setup API を使って、PnP リクエストをエミュレートする必要がある。。。ということだと思います。 (実現させたい機能が簡単なことであっても、そのための実装はとても手間がかかる。。。ということです。)
    もっとも CDO に対して PnP リクエストをハンドリングすること自体、あまり意味がないことだと個人的には思っているので、CDO に対する PnP リクエストは一切除外して、CDO が常にアクセス可能状態であることを前提としても、つまりシンボリックリンクで提供している部分をデバイスインタフェースに置き換えて、かつこのデバイスインタフェースを無条件で有効にする実装にしたとしても、動くかも知れません。
    ただし、このような実装は WDM で規定されているデバイスインタフェースに対するガイドラインからは逸脱することになるので、予期しない問題が発生する可能性も覚悟しないといけませんが。。。。


    > 今回作成するフィルタドライバの下位にいるドライバが既製品でありソースコードを改変できないため、
    > 下位のドライバのデバイスインタフェースに対するCreateFile()要求を弾くことなくフィルタドライバ側の動作を行いたいと考えております。

    いまいち実現されたいことがイメージできませんが。。。
    たとえば極端な例として、「ターゲット デバイスへのアクセスをダイナミックに有効/無効に切り替えられるようにしたい!」ということであれば、Upper Filter であることを前提とすれば、CDO を作らなくても、既存の FiDO に対してCustom I/O Control の処理を追加実装するだけで実現可能な気もします。
    (もっともそのような機能は、フィルタ ドライバを作るまでもなく、ユーザ モード側にサービス プロセスを用意して、そのサービスで有効/無効を切り替えた方が簡単で安全だと思うので、実現されたいことはもっと別のことだとは思いますけど。)

    以上、参考になりましたら幸いに存じます。

    • 回答の候補に設定 佐伯玲 2012年11月1日 0:53
    2012年10月12日 8:43