UMDF Version 2 の Toaster Sample をインストールする

今回は、ユーザーモードドライバーフレームワーク(User-mode Driver Framework, UMDF) のバージョン 2 について学びたい方向けのサンプル、Toaster Sample (UMDF Version 2) をご紹介します。   皆さん、こんにちは。WDK サポートチームの津田です。今回は、このサンプルをビルドして、ターゲット側 PC の Windows 10 (1607) x86 にインストールし、デバイスマネージャ上で表示されるところまでを確認します。サンプルをビルドする、開発側の PC は Windows 10 (1607) x64 に Visual Studio 2015 と WDK 10 がインストールされています。   1. サンプルの入手   Toaster Sample (UMDF Version 2) サンプルは、以下のサイトの右側の緑色の [Clone or Download] ボタンを押すと表示される [Download ZIP] ボタンで Windows-driver-samples-master.zipをダウンロードすると、Windows-driver-samples-master\general\toaster\umdf2 のフォルダにあります。…


WDF ソースコード公開

皆様、いかがお過ごしでしょうか。WDK サポートチームの石沢です。 今回の記事より Twitter アカウント MSDEVJP より更新をお知らせいただけることになりました!是非ご活用ください。また Twitter よりお越しの皆様、初めまして!本ブログではドライバ開発に関する記事を公開しております。今後とも何卒よろしくお願いいたします。 今回は Windows Driver Frameworks (WDF) に関するお話しです。 去年の 3 月に WDF のソースコードが GitHub 上に公開されました。  Windows Driver Frameworks これにより Windows 10 では WDF を含めたデバッグをできるようになったわけなのですが、今回はどのように設定すればソースコードデバッグできるのか具体的な手順を詳しく解説いたします。   <今回のメニュー> カーネルデバッグ開始 シンボルパスとソースパスの設定 ブレイクポイントを設定しよう Go! 上手くいかないときは   ■ 1.カーネルデバッグ開始 まずはカーネルデバッガ (Windbg) を接続しましょう。今回は Windows 10 バージョン 10586に接続しています。 バージョンは Windbg 接続時に以下のように表示されますので、把握しておくとよいでしょう。   Connected to Windows 10…


KMDF のディスパッチルーチンについて

皆さん、はじめまして。WDK サポートチームの JS と申します。I 沢さんに続いて新しくチームに加入いたしましたので、これからよろしくお願いします。 今回は、WDM と KMDF のディスパッチルーチンの登録方法の違いについてご紹介したいと思います。   WDFの概要 さて、いきなり出てきた KMDF という単語ですが、これは Kernel Mode Driver Framework の略語で、WDF (Windows Driver Foundation) というドライバモデルに分類されます。 WDF や KMDF についてもうご存知でいらっしゃる方が多いと思いますが、このブログではあまり触れられていません。なので、本題に入る前に、まずはその概要をご紹介したいと思います。   なおきお~さんの記事「日本語の資料はあるの?」でも書かれていますが、WDF には二種類のドライバーがあります: ・KMDF (Kernel Mode Driver Framework) ・UMDF (User Mode Driver Framework) WDFの前に開発されたWDM (Windows Driver Model) というモデルがありますが、後者の方はカーネルモードのドライバしか作成できません。また、ユーザーモードドライバ開発用フレームワークは、WDFの誕生と同時に提供されました。一方、カーネルモードドライバは KMDF と WDM の二種類のモデルができました。   上記のように、KMDF は WDM を基にした新しいドライバーモデルであり、デザインに大きな違いがあります。どういう違いがあるのか、挙げたらきりがありませんので、まずは代表的な変更点である「ディスパッチルーチン (Dispatch…


イベントログの出力方法

皆さん、こんにちは。A寿です。   突然ですが、皆さんは、パスポートなしで他国に入国したことはありますか?・・・このお話にご興味のある方は本文の最後の【閑話休題】までどうぞ。   さて、今回はカーネル ドライバでのシステムイベントログの出力方法をご紹介しようと思います。ドライバ内の情報をシステム イベントログに残すことで、お客様先のトラブル発生時に、イベントビューアーでそのドライバ以外のモジュールのログと併せて確認できるため、トラブル発生時の大まかな状況をつかむことができます。トラブルシューティングのための情報記録の手段として、他に DbgPrint や、 Event Tracing for Windows (ETW) という方法があります。これらは、イベントログよりも詳細な情報を記録できるメリットがあります。しかし、その一方で、常時採取するには、イベントログよりもデータ量が大きくなってしまったり、データ量を抑えようとしてサイクリックに上書きすると、肝心のエラー時の情報が上書きで消されてしまう可能性があったりというデメリットもあります。そのため、イベントログで、トラブルが発生した時点までのどこを調査すべきかを判断してから、より詳細な情報を見るために、DbgPrint や ETW を使われるのが良いかと思います。   まず、カーネル ドライバでのシステムイベントログの出力方法について、手順の概要は以下の通りです。   IO_ERROR_LOG_PACKET のポインタを宣言します。 IoAllocateErrorLogEntry() を呼び、戻り値を 1. のポインタに代入します。 第一引数にはドライバオブジェクトまたはデバイスオブジェクトのポインタを入れます。 第二引数には IO_ERROR_LOG_PACKET 構造体のサイズ、 DumpData のサイズ×個数、 %n に挿入する文字列のサイズ、の和を入れます。     3.    2. の戻り値が NULL でなければ、 IO_ERROR_LOG_PACKET のメンバ変数に値をセットし、 IoWriteErrorLogEntry() を呼びます。   続いて、 Toaster サンプルの busenum.sys の DriverEntry() に、上記手順の具体的な実装を追加して、 busenum.sys ロード時にシステム…


デバイスの追加・削除の通知をアプリケーションで受け取る方法

皆さん、こんにちは。A寿です。   突然ですが、皆さんは、かつお節を使った和食の「本物の味」を味わったことはありますか?・・・このお話にご興味のある方は本文の最後の【閑話休題】までどうぞ。   さて、今回は、デバイスの追加・削除の通知をアプリケーションで受け取る方法をご紹介しようと思います。前回の私の記事で、ToasterサンプルのNotify.exeの使い方をご紹介しました。その記事で、Notify.exeでToasterデバイスを追加・削除した場合に、Notify.exeのウィンドウに、対応するメッセージが表示されていました。今回は、Toasterデバイスが追加・削除されて、Notify.exeのウィンドウに、対応するメッセージが表示されるまでに、Notify.exe(アプリ側)とToaster.sys(ドライバ側)それぞれに必要となる実装について見ていきたいと思います。   まず、Notify.exeがToaster.sysから受け取る通知には以下の2種類があります。 (A) デバイスインターフェイスに関する通知 (B) デバイスハンドルに関する通知   それぞれについて、以下の3つの処理があります。 (1) 通知の受け取りの開始(登録) (2) 通知の受け取り (3) 通知の受け取りの終了(登録解除)   Notify.exeの操作と、(A),(B)それぞれの(1)~(3)の処理は、以下の表のような関係になります。   Notify.exe の操作 起動 (ウィンドウの作成) デバイス 追加 デバイス 削除 終了 (ウィンドウのクローズ) (A) (1) (2) (2) (3) (B) ((1)(※)) (1) (2),(3)   (※:Notify.exe起動前に、すでにToasterデバイスが追加されていた場合。)   それでは、(A)から順番に、(1)~(3)の通知についてNotify.exeとToaster.sysの処理を見ていきましょう。(以下の説明は、可能であれば、ソースコードを見たり、実機やデバッガを動かしたりしながら、お読みいただければ幸いです。)   (A) デバイスインターフェイスの場合   (1) 通知の受け取りの開始(登録)   アプリケーション側で、通知の受け取りを開始するためには、RegisterDeviceNotification()のAPIを使います。後程説明しますが、デバイスインターフェイスだけでなく、デバイスハンドルもこの関数を使います。   Notify.exeでは、ウィンドウが作成されるタイミングで、toaster.sysのデバイスインターフェイスに対して、RegisterDeviceNotification()を呼びます。…


ToasterサンプルのNotify.exeの使い方

皆さん、こんにちは。A寿です。   突然ですが、皆さんは、シーカヤックに乗っている時に転覆させられたことはありますか?・・・このお話にご興味のある方は本文の最後の【閑話休題】までどうぞ。   さて、今回はToasterサンプルのNotify.exeの使い方をご紹介しようと思います。Notify.exeは、Toasterサンプルのデバイスの追加や削除を行うことができると同時に、デバイスが追加・削除されたことを、WM_DEVICECHANGEというメッセージとして受け取ることができるウィンドウアプリケーションのサンプルです。ToasterサンプルのNotify.exeは、     \WinDDK\{バージョン番号}\src\general\toaster\exe\notify   のフォルダにあります。notify.exe自体の説明は、\WinDDK\{バージョン番号}\src\general\toaster\readme.htmのExeの項目に、だいたい以下のようなことが書いてあります。   ・Notify.exe: このGUIアプリケーションはenum.exeとtoast.exeを組み合わせた機能を持つだけでなく、ユーザーモードでPnP通知を処理する方法を示しています。PnP通知について意味のある表示を得るためには、toastco.infを使って、toasterデバイスのためのcoinstallerをインストールしなければなりません。このexeの他の特徴としては、(デフォルトのtoasterのdevice idの代わりに)他の何らかのHW IDを指定して、ファンクションドライバとして他のドライバをロードさせることができます。   今回は、まずNotify.exeの使い方として下記の手順をご紹介します。デバイスの追加・削除のメッセージのやり取りについての実装については、別の機会にご紹介できればと思います。   ■Notify.exeを使用するまでの手順: (1) notify.exeのビルド (2) busenum.sysのビルド (3) toaster.sysのビルド (4) tostrcls.dllのビルド (5) tostrco1.dllのビルド (6) busenum.sysをインストール (7) toaster.sysをインストール (8) notify.exeでtoasterデバイスを追加 (9) notify.exeでtoasterデバイスを削除   それでは、それぞれの手順についてご説明します。今回は、Windows 7 x86をテスト環境とし、WDKのバージョンは現時点で最新の7600.16385.1を使用します。     (1) notify.exeのビルド   まず、notify.exeをビルドする場合、notifyフォルダだけをどこか別のところにコピーしてビルドしようとしてもエラーします。 これは、sourcesの4行目に   INCLUDES=..\..\wdm\inc;$(DDK_INC_PATH);   という記述がある通り、src\general\toaster\wdm\incフォルダが必要なためです。今回は、簡単のためにtoasterフォルダごとC:\の直下にコピーし、ここで必要なファイルをビルドしていきたいと思います。   Win7 x86…


Device Object と Device Stack

こんにちは、K里です。今回は、以前の記事で紹介しました WDM (Windows Driver Model) ドライバのデバイス オブジェクトとデバイス スタックについて説明します。 デバイス オブジェクトWindows OS は、システムに接続される全てのデバイスをデバイスオブジェクトという情報を用いて制御します。各デバイスには、1 つ以上のデバイス オブジェクトが関連付けられていて、デバイスの操作は、このオブジェクトを対象に機能します。カーネルモードドライバは、デバイスに対して少なくとも 1 つ以上のデバイス オブジェクトを作成することになります。実際のソースコードレベルでは、デバイスオブジェクトは、DEVICE_OBJECT 構造体として wdm.h に定義されています。DEVICE_OBJECT 構造体で定義されている各メンバについては、下記サイトをご覧ください。 DEVICE_OBJECT Structurehttp://msdn.microsoft.com/en-us/library/ff543147(VS.85).aspx また、デバイスオブジェクトは、ドライバに応じて以下のように 3 種類のオブジェクトに分類されます (データ自体は、全て上記 DEVICE_OBJECT 構造体になります)。 Physical Device Object (PDO): バスドライバに対するデバイス オブジェクトFunctional Device Object (FDO): ファンクションドライバに対するデバイス オブジェクトFilter Device Object (filter DO): フィルタドライバに対するデバイス オブジェクト なお、例外として、クラスドライバやポートドライバに関連付けられるミニ(クラス/ポート)ドライバでは、デバイスオブジェクトを作成しない場合があります。また、逆に特定デバイスクラスのミニドライバ (NDIS ミニポートドライバや USB ミニポートドライバなど) では、自身がデバイス オブジェクトを作成し、クラスドライバやポートドライバが作成しない場合もあります。 デバイス スタックとドライバ…


DriverObject と DriverEntry

こんにちは、K 里です。今回は、WDM ドライバの基本部分について、WDK サンプルドライバの Toaster を用いて説明しようと思います。基本とはいえその範囲は広いので、まずは OS とドライバの関わりとオブジェクトベースとなる Driver Object、ドライバの初期化についてまとめました。今後は Tips 記事と交互に WDK のコア コンポーネントについて説明していきたいと考えています。お役にたてれば幸いです。   I/O Manager Windows 上で動作するデバイス ドライバは、I/O Manager を始めとした Kernel (ntoskrnl.exe) 内の各種コンポーネントと密接な関係を持つことになります。I/O Manager は、I/O 操作を実現するための IRP (I/O Request Packet) というパケット駆動型のモデルを実装しています。あるドライバに対して I/O 操作が必要な場合、I/O Manager はこの IRP を介してドライバの制御を行います。ドライバは、I/O Manager から受け取った IRP を基にデバイスを制御することになります。以下は、ユーザーモードのアプリケーションが CreateFile 関数を呼び出した際の I/O 要求の流れを図解しています。              …


WDMが美しい

こんにちは、Cleng です。冬の名残のまだ去りやらぬ時候、皆さんいかがお過ごしでしょうか。   突然ですが、皆さん、中国語で「奥数」という言葉の意味はご存知でしょうか。私もつい最近まで知らなかった言葉ですが、「国際数学オリンピック」の略語として使用されているようです。今の中国、特に都市部では、「奥数」の塾がたくさんできて、いい中学校に進学するためにたくさんの小学生が週末に「奥数」の塾に通っています。「奥数」の塾で難しい数学問題の解き方を覚え、地域、市または全国の数学コンテストに挑戦します。上位に入れば、確実にいい学校に入れるようになります。小学生レベルの数学だからたかが知れていると私も思っていましたが、実際いくつかの問題をやってみたら本当に難しかったです。でも、数学の問題って難しければ難しいほど解けたときに達成感を感じ、「数学は美しい」と思うことがありますね。   さて、WDKのBlogですので、数学の話をこれぐらいにして、本題のWindowsのデバイスドライバについてお話したいと思います。   ご存知のように基本的にはカーネルモードドライバは WDM モデルを使っています。このモデルは、Windows NT のドライバモデルに、PnPと電源管理のサポートが追加された形でWindows 2000 でデビューして、そのまま最新バージョンのWindowsでも使用されています。また、PnPと電源管理に関わらないドライバは、Windows NT のドライバモデルをそのまま使用します。Windows NT のドライバモデルの設計が非常に優れていたというのが私の感想です。   WDMドライバはWindowsのカーネルと直接やり取りを行いますので、WDMを理解することは、Windows のカーネルの動きもある程度把握することにもなります。WDMの参考書として、個人的にはWalter Oney著Programming the Microsoft Windows Driver Model, Second Edition をお勧めします。この本のFrist Editionの日本語訳も出版されていますが、やはり英文原著のほうがいいですね。   WDMモデルの習得に当たって以下の項目がポイントになるかなと思います。 . IRP の流れ . デバイスオブジェクトとデバイススタック . PnP . 電源管理 . IRQL   この中に、他のOS/プラットフォームでドライバ作成経験があってこれからWDMを触れる方にとっては、最初IRQLというものになかなか馴染めないかもしれません。IRQLに関する技術文書がたくさんありますので詳細を割愛させていただきますが、IRQLに纏わる落とし穴的なものは以下のようなものがあります。 A.  IRQLがDISPATCH_LEVEL以上の場合、ページフォルトを起こしてはいけないし、待ち状態に移行してはいけません。これが理由で、DISPATCH_LEVEL以上の場合呼び出してはいけない関数がたくさん存在します。WDKのヘルプに各関数のIRQLの制限が記載されていますのでご参照ください。IRQLを慎重に扱わないと、IRQL_NOT_LESS_OR_EQUALというカッコいい名前のバグチェックになってしまいます。 B.  ドライバでのIRQLの操作について、IRQLを上げて、元のレベルに戻すことのみ許されています。つまり、ドライバがIRQLを元のレベルより低く設定することが許されていません。 AとBは切っても切れない間柄です。Bの制限がなくなると、Aの制限もなくなります。実は、つい最近Aの制限を回避しようとしてIRQLを下げるドライバを見ましたので、注意点としてここに書かせていただきます。皆さん、同じミスをしないように、慎重にIRQLと付き合いましょう。   WDKにはたくさんのドライバのサンプルがあります。中には、src\general\toaster配下の Toasterというドライバ群がありまして、仮想バスと仮想デバイスを制御するドライバのサンプルです。特別なハードウェアがなくても、バスドライバ、ファンクションドライバと各階層のフィルタドライバの動きを確認できるのが、このサンプルの特徴です。本に書かれていることを実際確認してみたいという方は、ぜひToasterサンプルインストールして、いじって見てください。  …