Welcome to MSDN Blogs Sign in | Join | Help

Windows Touch

ご無沙汰しております。なおき~です。

年末となり、皆様、如何お過ごしでしょうか?

今年最後の投稿をさせていただきます。

 

まず、私たち、DDK/WDK サポートチームの中で、今年 最も大きなニュースは、やはりWindows 7のリリースです。

そのWindows 7のデバイス ドライバ関連でのトピックと言えば、Windows Touchがあります。

 

さて、Windows Touchに対応したデバイス ドライバというのは、どうやって開発するのかご存知でしょうか?

開発するデバイスにもよりますが、USB HID デバイスならば、Windows 7標準のデバイス ドライバが動くので、デバイス ドライバを開発/提供しなくてもいいのです。

 

Windows Touch Overview

http://msdn.microsoft.com/en-us/library/ee220483.aspx

抜粋: If your digitizer device supports HID in firmware, you are not required to provide a driver.

 

さて、デバイス ドライバは、必要ないとして、USB HID のデバイスは、どうればいいのだろう?と思われた方は、HID の仕様書をご確認ください。

HID Informationには、Multi-touch digitizersの情報があります。このMulti-touch digitizersに準拠していたら、Windows 7標準のデバイス ドライバが動きます。

 

HID Information

http://www.usb.org/developers/hidpage/

 

私たちは、DDK/WDKをご利用いただき開発をしていただきたいのですが、デバイスをご提供されている皆様の立場の場合、デバイス ドライバを開発せず、デバイスだけを開発する方が負荷が減ると思います。

 

なお、USB HID デバイスではない場合はどうするの?という場合は、デバイス ドライバを開発する必要がありますが、以下のようなHID ClassMinidriverサンプル コードを提供しています。そのためデバイス ドライバ開発する必要がある皆様も決してスクラッチ開発をしなくてもいいのでご安心ください。

 

WacomKMDF Driver

http://msdn.microsoft.com/en-us/library/ee220508.aspx

 

Elotouch Driver

http://msdn.microsoft.com/en-us/library/ee220514.aspx

 

WDKドキュメントで、皆様のシナリオに合うトピックを見つけて、サンプル コードをご利用いただければ幸いです。

 

それでは、皆さん、よいお年をお迎えください。

Posted by jpwdkblg | (Comments Off)
Filed under: , ,

Driver Coverage Tool Kit

おひさしぶりです。まさかたです。

 

以前、A寿さんの Blog の記事の中で、WDK for windows 7 で追加された新しいツールとして、OACR について紹介いたしましたが、この他にも様々なツールが追加されました。

 

New for Windows 7

http://msdn.microsoft.com/en-us/library/dd434869.aspx

 

そんな中から、今回は、WDK 7.0.0 に追加された Driver Coverage Took Kit という、ドライバーのテストを補助するツールについて、ご紹介したいと思います。

 

Driver Coverage Tool Kit とは?

 

Driver Coverage Tool Kit は、ターゲットとなるドライバーにどんな IRP が、どれだけ流れてきているかを調べることができるツールです。

原理的には、ターゲットとなる任意のドライバーに対し、フィルタードライバーをインストールし、流れる IRP を記録していくというものです。

 

このツールを使えば、例えば、ドライバーの IRP Dispatch Routine をテストしているときに、テストでどの Dispatch Routine が網羅されているのか、いないのかなど、Coverage を測ることができます。

そのため、この Tool は、ドライバーのテストそのものを実行するというよりは、テストを補助するためのツールと考えていただいた方がいいと思います。

 

以下では、Toaster ドライバーを対象に、実際に Driver Coverage Tool Kit を動かした様子を、簡単にご紹介したいと思います。

 

■ツールの場所

まず、ツールの在り処ですが、WDK の以下のパスに格納されています。

 

WINDDK\7600.16385.0\tools\drvCov

 

上記のフォルダーの中で、さらに、CPU アーキテクチャーごとにフォルダーが分かれています。

フォルダーに含まれているファイルは、以下の 4点 ですが、これらのファイルをテスト用のマシンの任意の場所にコピーして使用します。

※今回の記事では、”C:\Workspace” というフォルダーにコピーして使っています。

 

Ø  Drvcov.sys : フィルタードライバー(Driver Coverage Filter driver

Ø  Drvcov.inf : フィルタードライバーをインストールするための INF ファイル

Ø  Drvcov.cat : フィルタードライバーをインストールする際に使用するカタログファイル

Ø  Drvcov.exe : フィルタードライバーのインストールや、IRP のキャプチャを開始したりするコマンドラインツール

 

■使用手順

Driver Coverage Tool Kit を使う場合の大まかな手順は以下のようになります。

 

1.     ターゲットとなるドライバーの ID を確認

2.     ターゲットのドライバーにフィルタードライバーをインストール

3.     IRP 計測用のバッファをクリア

4.     目的のドライバーで IRP のやり取りを発生させる

5.     結果を出力、分析

6.     フィルタードライバーをアンインストール

 

今回は、ターゲットとするドライバーとして Toaster を使用して、実際に上記の手順を追っていきます。

なお、以下で実行するコマンドプロンプトは、管理者権限で起動しておく必要がありますので、ご注意ください。

 

1.    ターゲットとなるドライバ ID を確認

Driver Coverage Tool Kit の原理としては、調べる対象のドライバーの Upper または、Lower に フィルタードライバー(Driver Coverage Filter driver) をインストールして、流れてくる IRP を監視し、それぞれの数をカウントしています。

そのフィルタードライバーが、DrvCov.sys になります。

というわけで、ツールを使うためには、調べるドライバーを予め OS にインストールしておき、さらに、DrvCov.sys を目的のドライバーのフィルタードライバーとしてインストールしておかなくてはなりません。

 

そして、上記のインストールを行う時に、どのドライバーのフィルタードライバーとしてインストールするかを指定するのに、ID を使います。

ID には、Devnode # というのと、Device ID が指定可能です。

 

この ID を知るために、”/DA” オプションで、さらにパラメーターに “1  を指定することで、すべてのデバイスの Devnode # Device ID を表示させます。

 

C:\WorkSpace> drvcov.exe /DA 1

  Devnode #: 2080 Class:  Net Desc:  Microsoft 6to4 Adapter

    |Device ID :  ROOT\*6TO4MP\0000

  Devnode #: 2120 Class:  Net Desc:  Microsoft ISATAP Adapter

    |Device ID :  ROOT\*ISATAP\0000

  Devnode #: 2160 Class:  Computer Desc:  ACPI x86  PC

    |Device ID :  ROOT\ACPI_HAL\0000

    Devnode #: 2204 Class:  System Desc:  Microsoft ACPI-Compliant System

      |Device ID : ACPI_HAL\PNP0C08\0

(中略)

  Devnode #: 11572 Class:  System Desc:  Toaster Bus Enumerator

    |Device ID :  ROOT\UNKNOWN\0001

    Devnode #: 11612 FN:  ToasterDevice01 Class:  TOASTER Desc:  Microsoft Toaster With Coinstaller

      |Device ID :  {B85B7C50-6A01-11D2-B841-00C04FAD5171}\MSTOASTER\1&7F60330&0&01

 

Toaster のインスタンス 01 Devnode # は、11612 ということなので、以後のコマンド実行でデバイスを指定する必要がある場合には、この ID を使用します。

ちなみに、この Devnode # は、OS が再起動する毎に変わる可能性があるので、注意が必要です。

 

2.    Filter のインストール

Toaster Upper にフィルタードライバーをインストールする際は、以下のとおり、”/A” オプションで可能です。

 

C:\WorkSpace>drvcov.exe /A 11612

Add our upper filter to:  Devnode #: 11612 FN:  ToasterDevice01 Class:  TOASTER

Desc:  Microsoft Toaster With Coinstaller

  Process path

   Raw path          : drvcov.exe

   Relative path     :

   Absolute path     : C:\WorkSpace\Blog_20090824\DrvCov_i386

   Absolute Inf File : C:\WorkSpace\Blog_20090824\DrvCov_i386\Drvcov.INF

  Process INF File : C:\WorkSpace\Blog_20090824\DrvCov_i386\Drvcov.INF

   Add Service. ( Run INF section DRVCOV.Service)

   Copy files.  ( Run INF section DRVCOV.Files): ............

  Process Devnode 11612l

   Add filter driver

 

NOTE: You need to reboot to load the filter driver.

 

メッセージにも書かれているように、フィルタードライバーをロードするには、再起動が必要です。

再起動後に、デバイスマネージャーで確認してみると、確かに、フィルタードライバー drvCov.sys がロードされているのがわかります。

 

DeviceManager01

 

ちなみに、Lower にインストールする場合は、”/AL” オプションでインストール可能です。

 

C:\WorkSpace>drvcov.exe /AL 11612

Add our lower filter to:  Devnode #: 11612 FN:  ToasterDevice01 Class:  TOASTER Desc:  Microsoft Toaster With Coinstaller

  Process path

   Raw path          : drvcov.exe

   Relative path     : 

   Absolute path     : C:\WorkSpace\Blog_20090824\DrvCov_i386

   Absolute Inf File : C:\WorkSpace\Blog_20090824\DrvCov_i386\Drvcov.INF

  Process INF File : C:\WorkSpace\Blog_20090824\DrvCov_i386\Drvcov.INF

   Add Service. ( Run INF section DRVCOV.Service) 

   Copy files.  ( Run INF section DRVCOV.Files): ............

  Process Devnode 11612l

   Add filter driver

 

NOTE: You need to reboot to load the filter driver.

 

DeviceManager02 

 

また、drvcov.exe の ”/DF” オプションでも、フィルターがインストールされているドライバーを確認することができます。

ただし、フィルタードライバーはインストールされていても、実際にはロードされていないドライバーも表示されます。

 

C:\WorkSpace>drvcov.exe /DF

|------------------------------------------------------------------

| List of devices that are filtered by the Driver Coverage driver.

|------------------------------------------------------------------

|  Devnode #: 10600 FN:  ToasterDevice01 Class:  TOASTER Desc:  Microsoft Toaster With Coinstaller

|      - Drvcov Filter  :  Lower  Upper

| 1 device(s) found.

|------------------------------------------------------------------

 

/D” オプションを使えば、現在、ドライバーが実際にロードされていて、データの収集が可能なもののみが表示されます。

 

C:\WorkSpace>drvcov.exe /D

|------------------------------------------------------------------

| List of devices we can get coverage data from.

|------------------------------------------------------------------

|  Device # : 1

|  Devnode #: 10600 FN:  ToasterDevice01 Class:  TOASTER Desc:  Microsoft Toaster With Coinstaller

|  Device ID: "{B85B7C50-6A01-11D2-B841-00C04FAD5171}\MSTOASTER\1&1AAFB3D5&0&01"

|------------------------------------------------------------------

| 1 device(s) found.

|------------------------------------------------------------------

 

3.    バッファのクリア

さて、IRP の測定に入る前に、前回測定したバッファがあれば、それをクリアしておく必要があります。

今回は初めて測定を行うので必要ありませんが、コマンドで実行すると以下のような出力となります。(/E” オプション)

 

C:\WorkSpace> drvcov /E 11612

Clear IRP coverage data for device:

  Friendly Name : Microsoft Toaster With Coinstaller

  DeviceInstId : {B85B7C50-6A01-11D2-B841-00C04FAD5171}\MSTOASTER\1&7F60330&0&01

 

4.    IRP のやり取りを発生させる

今回は、以下の操作を実行してみました。

-       Enum.exe で、Unplug/Plug-in を繰り返す

-       Toast.exe Read を繰り返す

-       システムを Sleep -> 復帰

 

5.    結果の出力

それでは、実際に流れた IRP を見てみます。

結果の出力には、“/C” オプションを使います。

 

C:\WorkSpace>drvcov.exe /C 11612

Getting coverage data

Data source

   Source Type:  Driver

   Source Name:  \\.\DrvcovControl2

Device

   Friendly Name : Microsoft Toaster With Coinstaller

   Class Name    : TOASTER

   Device ID     : {B85B7C50-6A01-11D2-B841-00C04FAD5171}\MSTOASTER\1&1AAFB3D5&0&01

   Device #      : 1

   Devnode #     : 10600

 

|--------------------------------------------------------|

| MJ & MN Device irp coverage                            |   ß------

|--------------------------------------------------------|

| IRPS covered     24                      |  # of times |

|--------------------------------------------------------|

| CREATE                                   |          15 |

| PNP\QUERY_INTERFACE                      |           9 |

| READ                                     |          61 |

| CLEANUP                                  |           5 |

| CLOSE                                    |           5 |

| PNP\QUERY_DEVICE_RELATIONS\Target        |           6 |

| PNP\QUERY_DEVICE_RELATIONS\Removal       |           2 |

| PNP\QUERY_DEVICE_RELATIONS\Eject         |           2 |

| PNP\SURPRISE_REMOVAL                     |           2 |

| PNP\REMOVE_DEVICE                        |           2 |

| Unknown                                  |          12 |

| PNP\QUERY_RESOURCE_REQUIREMENTS          |           2 |

| PNP\FILTER_RESOURCE_REQUIREMENTS         |           2 |

| PNP\START_DEVICE                         |           6 |

| PNP\QUERY_CAPABILITIES                   |           4 |

| PNP\QUERY_PNP_DEVICE_STATE               |           2 |

| PNP\QUERY_DEVICE_TEXT                    |           2 |

| PNP\QUERY_ID                             |           2 |

| PNP\QUERY_DEVICE_RELATIONS\Bus           |           2 |

| WMI\REGINFO_EX                           |           2 |

| POWER\QUERY_POWER\SYSTEM                 |           3 |

| POWER\QUERY_POWER\DEVICE                 |           1 |

| POWER\SET_POWER\SYSTEM                   |           5 |

| POWER\SET_POWER\DEVICE                   |           3 |

|--------------------------------------------------------|

| IRPS NOT covered     28                  |             |

|--------------------------------------------------------|

| WRITE                                    |             |

| FLUSH_BUFFERS                            |             |

| DEVICE_CONTROL                           |             |

| INTERNAL_DEVICE_CONTROL                  |             |

| SHUTDOWN                                 |             |

| POWER\WAIT_WAKE                          |             |

| WMI\QUERY_ALL_DATA                       |             |

| WMI\QUERY_SINGLE_INSTANCE                |             |

| WMI\CHANGE_SINGLE_INSTANCE               |             |

| WMI\CHANGE_SINGLE_ITEM                   |             |

| WMI\ENABLE_EVENTS                        |             |

| WMI\DISABLE_EVENTS                       |             |

| WMI\ENABLE_COLLECTION                    |             |

| WMI\DISABLE_COLLECTION                   |             |

| WMI\REGINFO                              |             |

| WMI\EXECUTE_METHOD                       |             |

| PNP\QUERY_REMOVE_DEVICE                  |             |

| PNP\CANCEL_REMOVE_DEVICE                 |             |

| PNP\STOP_DEVICE                          |             |

| PNP\QUERY_STOP_DEVICE                    |             |

| PNP\CANCEL_STOP_DEVICE                   |             |

| PNP\QUERY_RESOURCES                      |             |

| PNP\READ_CONFIG                          |             |

| PNP\WRITE_CONFIG                         |             |

| PNP\EJECT                                |             |

| PNP\SET_LOCK                             |             |

| PNP\QUERY_BUS_INFORMATION                |             |

| PNP\DEVICE_USAGE_NOTIFICATION            |             |

|--------------------------------------------------------|

| Stats                                                  |

|--------------------------------------------------------|

| Total IRP count        :     52                        |

| Covered IRP count      :     24                        |

| NOT Covered IRP count  :     28                        |

| Covered IRP %          :     46.15%                    |

| NOT Covered IRP %      :     53.85%                    |

|--------------------------------------------------------|

 

|--------------------------------------------------------|

| MJ Device irp coverage                                 |   ß------

|--------------------------------------------------------|

| IRPS covered      8                      |  # of times |

|--------------------------------------------------------|

| IRP_MJ_CREATE                            |          15 |

| IRP_MJ_PNP                               |          45 |

| IRP_MJ_READ                              |          61 |

| IRP_MJ_CLEANUP                           |           5 |

| IRP_MJ_CLOSE                             |           5 |

| IRP_MJ_UNKNOWN                           |          12 |

| IRP_MJ_SYSTEM_CONTROL                    |           2 |

| IRP_MJ_POWER                             |          12 |

|--------------------------------------------------------|

| IRPS NOT covered      5                  |             |

|--------------------------------------------------------|

| IRP_MJ_WRITE                             |             |

| IRP_MJ_FLUSH_BUFFERS                     |             |

| IRP_MJ_DEVICE_CONTROL                    |             |

| IRP_MJ_INTERNAL_DEVICE_CONTROL           |             |

| IRP_MJ_SHUTDOWN                          |             |

|--------------------------------------------------------|

| Stats                                                  |

|--------------------------------------------------------|

| Total IRP count        :     13                        |

| Covered IRP count      :      8                        |

| NOT Covered IRP count  :      5                        |

| Covered IRP %          :     61.54%                    |

| NOT Covered IRP %      :     38.46%                    |

|--------------------------------------------------------|

 

 

|--------------------------------------------------------|

| MJ & MN Device IRP Concurrency pairs.                  |   ß------

|--------------------------------------------------------|

| IRP Pairs covered                      4 |  # of times |

|--------------------------------------------------------|

| CREATE                                   |             |

| PNP\QUERY_INTERFACE                      |           5 |

|--------------------------------------------------------|

| POWER\SET_POWER\SYSTEM                   |             |

| POWER\SET_POWER\DEVICE                   |           2 |

|--------------------------------------------------------|

| POWER\QUERY_POWER\SYSTEM                 |             |

| POWER\QUERY_POWER\DEVICE                 |           1 |

|--------------------------------------------------------|

| PNP\START_DEVICE                         |             |

| PNP\QUERY_CAPABILITIES                   |           2 |

|--------------------------------------------------------|

|--------------------------------------------------------|

| Stats                                                  |

|--------------------------------------------------------|

| Total IRP pairs                 :        1099          |

| Covered IRP pairs               :           4          |

| NOT Covered IRP pairs           :        1095          |

| Covered IRP pairs %             :           0.36%      |

| NOT Covered IRP pairs %         :          99.64%      |

|--------------------------------------------------------|

 

 

この出力は、3つのセクションに分かれています。

     MJ & MN Device irp coverage (IRP Major (MJ) and Minor (MN) Coverage Data)

様々な Major Function IRP と、Minor Function IRP の中で、テスト中にドライバーによって処理された IRP と、処理されていない IRP の種類と数がそれぞれ表示されます。

これによって、実施したテストの IRP Coverage がどれだけであるか、またどの IRP のテストが足りないかを知ることができます。

     MJ Device Irp coverage (IRP MJ Coverage Data)

IRP Major Function Code に限って、どれだけの IRP Code Cover されているかを測定した結果です。

これによって、ドライバーに実装されている MJ_IRP Dispatch Routine のテストの Coverage を知ることができます。

     MJ & MN Device IRP Concurrency pairs. (IRP Pairs Coverage Data)

同時に処理された IRP の組について、結果を表示しています。

これは、複数の IRP の同時処理のテストを行う場合に、どれだけの IRP の組み合わせが網羅できているのかを知ることができます。

 

以上の内容を見ると、確かに、4 の手順に関連する IRP が流れているのが分かります。ただ、網羅できたのは半分くらいですね。まだまだです。

ちなみに、データをコンマ区切りでマトリックスとして表した、csv 形式での出力もできます。("/CT” オプション)

これは、通常はファイルに結果をリダイレクトして使えばいいかと思います。

 

C:\Workspace> drvcov /CT 11612 > result.csv

 

このファイルを Excelで表示すれば、マトリックスで全体の状況を表示できるので、必要に応じて使い分けてはいかがでしょうか。

 

 ResultMatrix

 

6.    Filter のアンインストール

最後に、”/R” オプションでフィルタードライバーをアンインストールします。

 

C:\Workspace> drvcov /R 11612

Remove our filter ( both Upper & Lower ) from :  Devnode #: 11364 FN:  ToasterD

evice01 Class:  TOASTER Desc:  Microsoft Toaster With Coinstaller

  Process Devnode 11364l

   Removing filter driver.

  Process Devnode 11364l

   Removing filter driver.

 

NOTE: You need to reboot to unload the filter driver.

 

このツールの使い方については、MSDN にも詳しい説明が載っていますので、使ってみたいという方は、是非こちらもご覧いただいきたいと思います。

 

Driver Coverage Toolkit

http://msdn.microsoft.com/en-us/library/dd535798.aspx

 

それでは、また。

 

 

Posted by jpwdkblg | (Comments Off)
Filed under: ,

USB 2.0 カーネル デバッグ その後

こんにちは、K里です。今回は、以前ご紹介した USB 2.0 カーネルデバッグについての追加情報をお知らせします。USB デバッグの詳細については、まずは以下の記事をご一読いただけますと幸いです。

 

USB 2.0 カーネル デバッグ 前編

USB 2.0 カーネル デバッグ 後編

 

上記記事の前編にて、ターゲットマシンの設定 (3) に以下のコマンドがあります。

 

  bcdedit /set {identifier} loadoptions busparams=x.y.z

 

これは、カーネルデバッガ接続のために使うデバイス (USB EHCI Host Controller 1394 Host Controller) を一意に指定するために、デバイスマネージャーで確認される  busparams=<Bus>.<Device>.<Func> の入力を行いますが、この busparams の指定方法が、USB デバッグの場合、ターゲット OS によって何進数で入力するのかが異なります。以下、1394 デバッグも併せてターゲット OS 毎の指定方法を記載します。

 

Target OS

USB 2.0 Debug

1394 Debug

Windows Vista &

Windows Server 2008

16 進数で入力

10 進数で入力

Windows 7 &

Windows Server 2008 R2

10 進数で入力 new!

10 進数で入力 new!

 

上記の通り、Windows 7 & Server 2008 R2 USB デバッグ接続する場合、デバイスマネージャーの表記のまま (下図をご参照ください) busparams を入力することになります。一方で、Windows Vista & Server 2008 の場合は、以前の記事で説明したとおり、デバイスマネージャーの表記を 16 進数に変更して入力します。1394 デバッグ接続では、OS 問わず、10 進数で指定します。このため、USB デバッグの場合、busparams の指定方法が OS によって異なりますのでご注意ください。

 

ehci 

 

 

例えば、上記 “PCI バス 0 デバイス 29 機能 7” のコントローラーをデバッグ接続のデバイスとして指定する場合、以下のようにコマンドを実施します。

 

Windows Vista & Server 2008 の場合

  bcdedit /set {identifier} loadoptions busparams=0.1d.7

 

Windows 7 & Server 2008 R2 の場合

  bcdedit /set {identifier} loadoptions busparams=0.29.7

 

ではまた。

 

Appendix

BCDEdit /set - loadoptions busparams=Bus.Device.Function

http://msdn.microsoft.com/en-us/library/aa906211.aspx

 

Posted by jpwdkblg | (Comments Off)
Filed under: ,

デバイスの有効・無効をプログラムから切り替える方法

みなさまこんにちは。さなえすです。

 

デバイスマネージャから、特定のデバイスを有効にしたり、無効にすることができますね。では、このような操作を、プログラムから操作したいとしたら、どうすればよいでしょうか??

 

(デバイスを右クリックしたところ↓)

 

 DevMgr

 

そのヒントは、DevCon にあります。

 

先の「デバイスを有効・無効にする API はありますか?」という質問の答えは、Yesです。ただ、単一の API では実現できませんので、複数の SetupDi API 関数などを組み合わせれば可能です、ということになります。(Vista以降のOSですと WMI などを使用しても実現できるようです。)今日は、SetupDi  API関数を使った実現方法について DevCon サンプルを使って、” デバイスの有効・無効をプログラムから切り替える方法” としてご紹介します。DevCon SetupDi APIについての詳しい説明は、以下のまさかたさんからの投稿を再度参照ください。今回の投稿と併せて読んでいただくことで、違う角度からさらに理解を深められることと思います!

 

DevCon と SetupDi API ~ DevCon の使い方編

SetupDi API と DevCon ~ SetupDi API の使い方編

 

1DevCon サンプルをビルド

さて、それでは早速 DevCon サンプルをビルドして、動かすところから始めましょう。(とりあえず、DevCon の操作方法だけ確認したいという方は、こちらからどうぞ。)C ドライブに Windows Driver Kit をインストールした場合、以下のフォルダに DevCon サンプルアプリケーションのソースコードがあります。

 

    C:\WinDDK\7600.16385.0\src\setup\devcon

 

ビルドしたプログラムを動作させるターゲットのオペレーティングシステムに応じて、ビルド環境を選択してください。そうすると、ビルドするための環境変数を読み込んだコマンドコンソールが起動されます。

 

    [スタート]

      -> [すべてのプログラム]

        -> [Windows Driver Kits]

          -> [WDK 7600.16385.0]

            -> [Build Environment]

 

ここでは例として [Windows 7]> [x86 Free Build Environment] を使用します。Devcon サンプルのフォルダへ移動し、 build コマンドで、サンプルをビルドしましょう。

 

    コマンド例:

    C:\WinDDK\7600.16385.0\src\setup\devcon>build

 

実行形式ファイル  devcon.exe は、Free ビルドの場合、↓以下のフォルダに生成されます。

 

C:\WinDDK\7600.16385.0\src\setup\devcon\objfre_win7_x86\i386

 

2.デバイスを列挙する

ビルドされた devcon.exe を使用して、“USB 大容量記憶装置デバイス” ( [USB Mass Storage Device] ) を無効化してみましょう。特定のデバイスを無効化するという判別作業には、インスタンス ID やデバイス名を使用して行います。DevCon では、hwids コマンドで、セットアップクラスを指定すると、該当するデバイスを列挙することができます。これで、デバイスのインスタンスIDが取得できます。

 

では実際に、USBクラスを例に、コマンドラインから以下を入力して、USB デバイスの ID を列挙してみます。この時 = の後にスペースを入れずに入力してください。(※後でデバイスの有効・無効の切り替えを行う際に、管理者権限が必要となりますので、DevCon サンプルは管理者権限で動作させてください。)”USB” の他にも、”1394” や、”net” で、同様にそれぞれのクラスのデバイスが列挙できます。

 

    コマンド例:

devcon.exe hwids =usb

 

    出力例:

C:\Sample\DevCon>devcon.exe hwids =usb

PCI\VEN_8086&DEV_27C8&SUBSYS_01AD1028&REV_01\3&172E68DD&0&E8

    Name: Intel(R) 82801G (ICH7 Family) USB Universal Host Controller - 27C8

    Hardware IDs:

        PCI\VEN_8086&DEV_27C8&SUBSYS_01AD1028&REV_01

        PCI\VEN_8086&DEV_27C8&SUBSYS_01AD1028

        PCI\VEN_8086&DEV_27C8&CC_0C0300

        PCI\VEN_8086&DEV_27C8&CC_0C03

    Compatible IDs:

        PCI\VEN_8086&DEV_27C8&REV_01

        PCI\VEN_8086&DEV_27C8

        PCI\VEN_8086&CC_0C0300

        PCI\VEN_8086&CC_0C03

        PCI\VEN_8086

        PCI\CC_0C0300

        PCI\CC_0C03

PCI\VEN_8086&DEV_27C9&SUBSYS_01AD1028&REV_01\3&172E68DD&0&E9

    Name: Intel(R) 82801G (ICH7 Family) USB Universal Host Controller - 27C9

    Hardware IDs:

        PCI\VEN_8086&DEV_27C9&SUBSYS_01AD1028&REV_01

        PCI\VEN_8086&DEV_27C9&SUBSYS_01AD1028

        PCI\VEN_8086&DEV_27C9&CC_0C0300

        PCI\VEN_8086&DEV_27C9&CC_0C03

    Compatible IDs:

        PCI\VEN_8086&DEV_27C9&REV_01

        PCI\VEN_8086&DEV_27C9

        PCI\VEN_8086&CC_0C0300

        PCI\VEN_8086&CC_0C03

        PCI\VEN_8086

        PCI\CC_0C0300

        PCI\CC_0C03

PCI\VEN_8086&DEV_27CA&SUBSYS_01AD1028&REV_01\3&172E68DD&0&EA

    Name: Intel(R) 82801G (ICH7 Family) USB Universal Host Controller - 27CA

    Hardware IDs:

        PCI\VEN_8086&DEV_27CA&SUBSYS_01AD1028&REV_01

        PCI\VEN_8086&DEV_27CA&SUBSYS_01AD1028

        PCI\VEN_8086&DEV_27CA&CC_0C0300

        PCI\VEN_8086&DEV_27CA&CC_0C03

    Compatible IDs:

        PCI\VEN_8086&DEV_27CA&REV_01

        PCI\VEN_8086&DEV_27CA

        PCI\VEN_8086&CC_0C0300

        PCI\VEN_8086&CC_0C03

        PCI\VEN_8086

        PCI\CC_0C0300

        PCI\CC_0C03

USB\ROOT_HUB\4&19F1AF77&0

    Name: USB Root Hub

    Hardware IDs:

        USB\ROOT_HUB&VID8086&PID27CA&REV0001

        USB\ROOT_HUB&VID8086&PID27CA

        USB\ROOT_HUB

PCI\VEN_8086&DEV_27CB&SUBSYS_01AD1028&REV_01\3&172E68DD&0&EB

    Name: Intel(R) 82801G (ICH7 Family) USB Universal Host Controller - 27CB

    Hardware IDs:

        PCI\VEN_8086&DEV_27CB&SUBSYS_01AD1028&REV_01

        PCI\VEN_8086&DEV_27CB&SUBSYS_01AD1028

        PCI\VEN_8086&DEV_27CB&CC_0C0300

        PCI\VEN_8086&DEV_27CB&CC_0C03

    Compatible IDs:

        PCI\VEN_8086&DEV_27CB&REV_01

        PCI\VEN_8086&DEV_27CB

        PCI\VEN_8086&CC_0C0300

        PCI\VEN_8086&CC_0C03

        PCI\VEN_8086

        PCI\CC_0C0300

        PCI\CC_0C03

USB\ROOT_HUB\4&2F60F7EA&0

    Name: USB Root Hub

    Hardware IDs:

        USB\ROOT_HUB&VID8086&PID27CB&REV0001

        USB\ROOT_HUB&VID8086&PID27CB

        USB\ROOT_HUB

USB\ROOT_HUB\4&32C41A52&0

    Name: USB Root Hub

    Hardware IDs:

        USB\ROOT_HUB&VID8086&PID27C9&REV0001

        USB\ROOT_HUB&VID8086&PID27C9

        USB\ROOT_HUB

PCI\VEN_8086&DEV_27CC&SUBSYS_01AD1028&REV_01\3&172E68DD&0&EF

    Name: Intel(R) 82801G (ICH7 Family) USB2 Enhanced Host Controller - 27CC

    Hardware IDs:

        PCI\VEN_8086&DEV_27CC&SUBSYS_01AD1028&REV_01

        PCI\VEN_8086&DEV_27CC&SUBSYS_01AD1028

        PCI\VEN_8086&DEV_27CC&CC_0C0320

        PCI\VEN_8086&DEV_27CC&CC_0C03

    Compatible IDs:

        PCI\VEN_8086&DEV_27CC&REV_01

        PCI\VEN_8086&DEV_27CC

        PCI\VEN_8086&CC_0C0320

        PCI\VEN_8086&CC_0C03

        PCI\VEN_8086

        PCI\CC_0C0320

        PCI\CC_0C03

USB\ROOT_HUB\4&4FC3F26&0

    Name: USB Root Hub

    Hardware IDs:

        USB\ROOT_HUB&VID8086&PID27C8&REV0001

        USB\ROOT_HUB&VID8086&PID27C8

        USB\ROOT_HUB

USB\ROOT_HUB20\4&4F1A976&0

    Name: USB Root Hub

    Hardware IDs:

        USB\ROOT_HUB20&VID8086&PID27CC&REV0001

        USB\ROOT_HUB20&VID8086&PID27CC

        USB\ROOT_HUB20

USB\VID_054C&PID_0243\5A0903040021511インスタンスID

    Name: USB Mass Storage Device デバイス名

    Hardware IDs:

        USB\VID_054C&PID_0243&REV_0200

        USB\VID_054C&PID_0243

    Compatible IDs:

        USB\Class_08&SubClass_06&Prot_50

        USB\Class_08&SubClass_06

        USB\Class_08

11 matching device(s) found.

 

USBクラスのデバイスがずらりと表示されました。このときの表示内容は、デバイスマネージャにてデバイスの種類別に表示した時と同じ内容になります。

この時デバイスマネージャはこんなかんじ↓

 

 

 2 DevMgr

 

ハイ、どちらも USB クラスのデバイスについて同じインスタンス(11 個)が列挙されていますね。

 

ここで、日本語環境で検証中の方にちょっとだけ補足します。上記の図では、Windows 7 Build 7600 英語版環境で動作させていますので、気になりませんが、日本語表記のデバイス名は DevCon サンプルをコマンドプロンプトで動作させるとコマンドプロンプトが Unicode 文字を正しく表示できないため日本語が表示されません(残念..)。もちろん、文字列の文字コードデータ自体は正しくバッファに格納されていますので、プログラムで特定のデバイス名を比較する際の文字列操作は通常通り行うことができますその点はご心配なく!

 

3.デバイスを無効化・有効化する

次に、デバイスの無効化です。上記の手順で取得したインスタンス ID を指定して、 USB デバイスを無効化します。DevCon では、コマンドラインより devcon.exe disable <インスタンス ID> と入力して、指定した USB デバイスを無効化します。インスタンス ID を指定する場合は下記の例のように“@<インスタンス ID>” のようにダブルクウォートとアットマークを使用してインスタンス ID を指定してください。

 

    出力例:

C:\Sample\DevCon>devcon.exe disable "@USB\VID_054C&PID_0243\5A0903040021511"

USB\VID_054C&PID_0243\5A0903040021511                       : Disabled

1 device(s) disabled.

 

というわけで、無事にデバイスが無効化されました。

この時デバイスマネージャはこんなかんじ↓ デバイスが無効化されていることが、デバイスマネージャからも確認できます

 

 3 USB Disabled

 

今度は、先ほど無効化した USB デバイスを有効化してみます。上記同様、Devcon サンプルでは、有効にするデバイスのインスタンス ID を取得し、コマンドラインより devcon.exe enable <インスタンス ID> と入力して、指定したUSB デバイスを有効にします。

 

    出力例:

C:\Sample\DevCon>devcon.exe enable "@USB\VID_054C&PID_0243\5A0903040021511"

USB\VID_054C&PID_0243\5A0903040021511                       : Enabled

1 device(s) are enabled.

 

 

実際、DevConでのデバイス列挙の部分でポイントとなる流れは、以下の SetupDi API 関数です。

 

⓪ SetupDiClassGuidsFromNameEx(クラスGUIDを取得)

    SetupDiGetClassDevsEx OR SetupDiCreateDeviceInfoListExDevice Information Set の作成)

    SetupDiEnumDeviceInfo +  CM_Get_Device_ID_Ex(デバイスの列挙)

    SetupDiGetDeviceRegistryProperty(デバイス情報の取得)

 

これらは主に、EnumerateDevices() 関数で実装されていますので、詳しくはソースコードを参照ください。(まさかたさんのこちらの投稿でも “ Setup API の使い方” でポイントをまとめてくれています)以上の流れで、DevCon  (=プログラム)を使って USB デバイスの有効・無効を切り替えが可能なことを確認できました。

 

4.その他 ~ネットワークアダプタの有効・無効~

上記は、USBクラスのデバイスについてでしたが、例えば、ネットワークアダプタの有効・無効を行う場合はどうでしょうか?先ほど同様devcon.exe hwids =net で、デバイスを列挙することはできます。ただ、仮に複数のネットワークアダプタが存在している中で [ローカルエリア接続] に割り当てられているものを無効化したい、というような場合にちょっと困ってしまいます。DevCon サンプルのデバイス列挙は、デバイス単位で行われているため、どのネットワークアダプタが  [ローカルエリア接続] に割り当てられているかまでを判別する処理は DevCon には含まれていないのです

 

しかし、ここであきらめてはいけません! 逆を言えば、どのネットワークアダプタが 「ローカルエリア接続」 に割り当てられているかを判別する処理を別途組めばよいわけですから。そのアイディアを以下にご紹介します。(※なお、ここでご紹介する方法は、現行の OS におけるレジストリ構成に依存しています。そのため今後の OS の実装によっては同じロジックが使えなくなる可能性がありますので、その点にはご了承ください。)

 

試しに以下のレジストリをのぞいてみてください

 

 4 Registry

 

このような構成になっています。

 

    HKEY_LOCAL_MACHINE

     + SYSTEM

      + CurrentControlSet

        + Control

          + Network

           + {4D36E972-E325-11CE-BFC1-08002BE10318} <-- 1. ネットワーク アダプタのレジストリ

             + {6FF9F1D8-5A39-4A3F-B594-9759A9C8A7A} <-- 2. アダプタの GUID

               + Connection  <-- 3. Connection キー

 

どのネットワークアダプタが「ローカルエリア接続」 に割り当てられているかは、このレジストリを検索して値の比較をして判別することによって実現できます。

 

1. ネットワーク アダプタのレジストリ

ネットワーク アダプタのレジストリにて 「ローカルエリア接続」 に使用しているネットワーク アダプタの関連付けを行っています。

 

2. アダプタの GUID

ネットワーク アダプタのレジストリの下に、各アダプタの GUID が列挙されています。GUID {6FF9F1D8-5A39-4A3F-B594-9759A9C8A7A} は、インストール時に割り当てられた値です。

 

3. Connection キー

Connection キーの中に [Name] の値として 「ローカル エリア接続」 の文字列と、[PnpInstanceID] の値としてインスタンス ID が格納されています。このインスタンス ID を使用すれば、DevCon サンプルで取得したデバイスのインスタンス ID と同様に使用できます。

 

判別のポイントとなるのは、3. Connection キーです。つまり、ここで登録されている ネットワークアダプタのレジストリの [Name]   ローカル エリア接続の文字列を元に、 [PnpInstanceID] ID DevCon サンプルで取得したインスタンス ID と比較する処理を DevCon サンプルと組み合わせて実装すれば、特定のネットワークアダプタの有効・無効も可能になるというわけです。

 

 

いかがでしたでしょうか?

このようにプログラムからデバイスを無効・有効の切り替えを行いたい場合は、 SetupDi API をアプリケーションに組み込むことで実現できます。最後に、Devcon サンプルや、今回取り上げた SetupDi API 関数群に関してのヘルプドキュメントをまとめておしまいにしたいと思います。DevCon は、沢山の機能が実装されているので、最初はとっつきにくいかもしれませんが、様々な場面で応用が効く、素晴らしいサンプルですので、みなさんも、DevCon サンプルの実装をもとにいろいろと試してみてください 私も頑張りますJ

 

- DevCon

- SetupDiClassGuidsFromNameEx

- SetupDiGetClassDevsEx

- SetupDiCreateDeviceInfoListEx

- SetupDiEnumDeviceInfo

- CM_Get_Device_ID_Ex

- Device Management Functions

SetupDi を使用してハードウェア機器を列挙する方法

 

ではまた♪

 

 

 

 

Posted by jpwdkblg | (Comments Off)
Filed under:

Microsoft Auto Code Review(OACR)とは

皆さん、こんにちは。A寿です。

 

突然ですが、皆さんはものすごい勢いで沖の方に流されたことはありますか?・・・このお話にご興味のある方は本文の最後の【閑話休題】までどうぞ。

 

さて、皆さんは、もうWDK for Windows 7 RTM(Windows Driver Kit (WDK) Version 7.0.0RTM)をインストールされましたでしょうか?

WDK for Windows 7 RTMをインストールしてビルド環境を立ち上げると、タスクバーに緑色のアイコンが追加されて驚かれた方もいらっしゃるかと思います。そして、ドライバをビルドしたりしますと、この緑色のアイコンが時々黄色や赤に変わったりして、さらに驚かれた方もいらっしゃるかと思います。これは、 Microsoft Auto Code Review(OACR)というもので、自動的にソースコードを静的に解析するツールです。今回は、このOACRについてご紹介したいと思います。

 

OACRとは

 

OACRとは、PREfast for DriversWDKのビルド環境に統合されたものです。WDKのビルド環境でドライバやアプリケーションをビルドすると、自動的にソースコードの問題を解析してくれます。OACRはバックグラウンドで動作し、CPUを使用する優先度が低く設定されています。なので、これまでと変わらないスピードでビルドを実行することができます。また、これまでPREfastを使うには、自分でビルド環境上で実行する必要がありましたが、今後は、特に自分で意識して実行しなくても、PREfastが実行されます。PREfastについては、すでに、さなえすさんの「ドライバー検証ツール」の回で説明されておりますので、ご興味のある方はそちらも参照していただけると幸いです。

 

OACRがどのような動きをするかを具体的に説明するために、実際に動かして見てみましょう。

 

ビルド環境を起動すると、自動的にOACRが起動します。今回は、例として、Windows Win7 x86 Checked Buildを使ってみます。

初回起動時には、ビルド環境のコマンドプロンプト上に下図のようなメッセージが表示されます。

 

 

 

1行目に「Launching OACR monitor」と表示されていますが、このOACRモニターは、下図の赤丸で囲んだ、緑色のアイコンとして、タスクバーに追加されます。

 

 

 

ただ、Windows 7の場合、デフォルトの設定では、OACRモニターのアイコンがタスクバーから隠されてしまっているので、これを表示したい場合は、[隠れているインジケーターを表示します](タスクバー上の白い三角)[カスタマイズ]をクリックして、「タスクバーに表示するアイコンと通知の選択」の画面で、下図の「通知のみを表示」から「アイコンと通知を表示」に変更します。

 

 

 

また、先ほどのビルド環境のコマンドプロンプトの2行目の表示に、「Starting dirs creation ... Completed.」とありますが、これにより、下図のように、新しく%BASEDIR%(例えば、C:\WinDDK\7600.16385.0)OACRというフォルダと、その中にx86フォルダとchk_win7_x86フォルダが作成されます。このx86フォルダには、ビルド時にOACRPREfastが実行された結果のログなどが置かれます。

 

 

 

ちなみに、ビルド環境を閉じても、OACRモニターは起動したままなので、2回目以降に同じビルド環境を起動する時には、ビルド環境のコマンドプロンプトに「OACR monitor running already」と表示されます。もし、OACRモニターを自分で終了させていたら、「Launching OACR monitor」と表示され、初回と同様にOACRモニターのアイコンがタスクバーに表示されます。

 

さて、OACRモニターのアイコンを右クリックすると、下図のようにメニューがいくつかあることがわかります。

 

 

 

メニューで有効になっている各項目について、簡単にご紹介しましょう。

 

Closeを選ぶと、OACRモニターを終了させることができます。

 

About OACR...を選ぶと、下図のように、OACRのバージョン(表示ではVersion 3.0.30122.1)OACRの設定ファイルoacr.iniの場所(表示ではC:\WinDDK\7600.16385.0\bin\x86\oacr\oacr.ini)などがわかります。

 

 

 

Statusを選ぶと、下図のように、現在OACRが監視しているプロジェクト(sourcesファイルで定義されたビルドするファイルの集合、1つのドライバやアプリを作る単位とお考えください)に警告やエラーがあるか(表示ではNo projects with warning log)、ビルド時にソースコードの解析をバックグラウンドで行うために、そのジョブをキューに入れますが、そこで待機しているジョブはあるか(表示ではNo projects with pending queue)OACR Monitorの状態(表示ではMonitor: Running)などがわかります。

 

 

 

Snoozeを選ぶと、一時的に、OACRモニターを無効にできますが、一時間後に再度有効になります。

 

 

OACRによるソースコードの問題の検出

 

それでは、ビルド環境のコマンドプロンプトに戻り、WDKtoasterサンプルをビルドして、OACRがソースコードの問題をどう検出するのかを見てみましょう。toasterサンプルの場所は、これまでと同様%BASEDIR%\src\general\toasterの下にありますが、少しフォルダの構成が変わりました。WDK for Windows 7 RTMでは、これまで%BASEDIR%\srcフォルダの下でkmdfumdfのフォルダとして別れていた、Kernel Mode Driver FrameworkUser Mode Driver Frameworkで作られたサンプルが、各カテゴリに含まれるように、編成しなおされたからです。(なので、フォルダ構成に変更があったのは、toasterだけではありません。ご自身に関係のあるフォルダにどのような変更が行われたか、ご興味がありましたら、ご確認ください。)

 

今回は、toasterWDMのバスドライバを使ってみようと思います。

 

  cd C:\WinDDK\7600.16385.0\src\general\toaster\wdm\bus

 

をビルド環境のコマンドプロンプトで実行し、対象のフォルダに移動してください。

そこで、

 

  build

 

と実行します。すると、buildは先に完了(正常終了)し、OACRは次の図のように、Machinebusy状態のため、idleになるまでソースコードの解析の実行を待ちます。

 

 

 

待っている間、アイコンを右クリックしてStatusを見ると、次の図のように、DaemonQueueに入れられていることがわかります。

 

 

 

もし、解析の実行をすぐに行いたい場合は、次の図のように、OACRモニターを右クリックして、Check Nowを選んで、プロジェクト名である「WDKSample:x86chk」を選ぶと実行できます。ちなみに、この”プロジェクト名“は、デフォルトの設定として、%BASEDIR%の下でビルドすれば「WDKSamples:x86chk」になり、それ以外のフォルダでビルドすれば「root:x86chk」となります。

 

 

 

解析が行われた結果、ソースコードに問題があると判断された場合は、次の図のように、通知が行われます。

先ほど、ビルドは正常に完了していたので、ビルド時に見つからないソースコードの問題を、OACRが見つけてくれることがわかります。

 

 

 

問題の内容を見るには、次の図のように、OACRモニターを右クリックして、View Errorsを選んで、プロジェクト名を選びます。

 

 

 

すると、次の図のように、PREfastMessage List画面が表示されます。

 

 

 

リストアップされているエラーの詳細を確認したい場合は、各エラーをダブルクリックします。

まずは、Message List画面の一番上のエラーを見てみましょう。次の図のように、View Annotated Source画面が表示されます。

 

 

 

Warning 6291が出ており、ビット演算として、!|よりも高い優先度を持つため、||(!(x | y))のどちらかを使うように、と書いています。図の赤字で表示されている、busenum.c73行目でこの問題が発生しているようですが、赤字で表示されている部分には、この問題に該当しそうな記述はありません。そのため、Bus_KdPrint_Def()というマクロの中に問題があるようです。

 

そこで、Bus_KdPrint_Def()を定義している、busenum.hを見てみましょう。

Bus_KdPrint_Def()の定義は、112行目から始まっていますが、同様の処理を行っているところとして、101行目から116行目に次のようなマクロがありました。

 

101 #define Bus_KdPrint(_d_,_l_, _x_) \

102             if (!(_l_) | (_d_)->DebugLevel & (_l_)) { \

103                DbgPrint ("BusEnum.SYS: "); \

104                DbgPrint _x_; \

105             }

106

107 #define Bus_KdPrint_Cont(_d_,_l_, _x_) \

108             if (!(_l_) | (_d_)->DebugLevel & (_l_)) { \

109                DbgPrint _x_; \

110             }

111

112 #define Bus_KdPrint_Def(_l_, _x_) \

113             if (!(_l_) | BusEnumDebugLevel & (_l_)) { \

114                DbgPrint ("BusEnum.SYS: "); \

115                DbgPrint _x_; \

116             }

 

これらを見ると、確かに102,108,113行目に、「if (!(_l_) | ...」という部分があります。このコードでは「!」の有効範囲を明示していないために、コーディングしている人の設計の意図と異なるコーディングをしている可能性があることをOACR(PREfast)は指摘しています。

 

そこで、これらの行を、以下の赤字のように変更してみました。

 

101 #define Bus_KdPrint(_d_,_l_, _x_) \

102             if ((!(_l_)) | (_d_)->DebugLevel & (_l_)) { \

103                DbgPrint ("BusEnum.SYS: "); \

104                DbgPrint _x_; \

105             }

106

107 #define Bus_KdPrint_Cont(_d_,_l_, _x_) \

108             if ((!(_l_)) | (_d_)->DebugLevel & (_l_)) { \

109                DbgPrint _x_; \

110             }

111

112 #define Bus_KdPrint_Def(_l_, _x_) \

113             if ((!(_l_)) | BusEnumDebugLevel & (_l_)) { \

114                DbgPrint ("BusEnum.SYS: "); \

115                DbgPrint _x_; \

116             }

 

それでは、再度ビルドして見ましょう。

ビルド環境のコマンドプロンプトで

 

  build -cZ

 

を実行します。

ビルド完了後、しばらくすると、ソースコードの解析が実行され、次の図のように、問題がないことが表示されました。つまり、ソースコードに潜在する問題を解決できたことになります。

 

 

 

 

以上のように、OACRは、ビルド時に自動的にPREfastでソースコードの実装の問題点を見つけてくれる、すばらしいツールです。まだWDK for Windows 7 RTMを使用されていない方は、ぜひご利用いただき、ご自身のソースコードの質を向上していただければと思います。

 

また、今回は、概要だけで長くなってしまったので、OACRのカスタマイズ(有効/無効やプロジェクトごとの設定など)についてはご紹介しませんでしたが、ご興味のある方は以下のドキュメントをご参照いただければ幸いです。機会があれば、こちらもご紹介してみたいと思っています。

 

Windows Auto Code Review (OACR)

http://msdn.microsoft.com/en-us/library/dd445214.aspx

 

Configuring Microsoft Auto Code Review (OACR)

http://msdn.microsoft.com/en-us/library/dd445213.aspx

 

Customizing a Microsoft Auto Code Review (OACR) Project

http://blogs.msdn.com/wdkdocs/archive/2009/07/10/customizing-a-microsoft-auto-code-review-oacr-project.aspx

 

 

――――――――――――――――

 

【閑話休題】皆さんはものすごい勢いで沖の方に流されたことはありますか?

 

残念ながら、離岸流の話ではありません。もし離岸流を体験した話だったら、体が非常に丈夫な方ならともかく、私は生きていないと思います。

何の話かといいますと、ウィンドサーフィンの話です。私は、数年前の9月に一度だけ、ウィンドサーフィンの初心者向けの教室に参加したことがあります。初心者向けのウィンドサーフィンのサーフボードは、まるでイカダのような形で、非常に安定しており、その時の風がすごくいい感じなのもあって、しばらくは岸と並行に、行ったり来たりしていました。

先生も、9月には余り生徒がいないこともあって(実際その時の受講者は私一人でした)、海上で近くに寄ってきた時には必ず「初心者なのに、うまいねー。ぜひ続けるべきだよ」と、目的が見え見えのお世辞を言っては離れていくのを繰り返していました。

ただ、調子に乗りやすい性格なのもあり、海上を何往復もしているうちに、ついうっかり帆で風をうける方向を誤り、すごい勢いでぐんぐん沖の方に流されていきました。先生も、指の爪か米粒くらいの大きさに見え、こちらに気づいているかどうかすらわかりません。

「やばい、先生とあんなに遠く離れてしまった。これは自力で戻れなかったら、どうなるんだ?」と、怖くなり、必死に帆で風を受けて、岸になんとかたどりついたのでした。皆様も、先生の見え見えなお世辞にはお気をつけください。

 

Posted by jpwdkblg | (Comments Off)
Filed under: ,

印刷時のスプーリングについて

こんにちは、A尾です。

 

前回と前々回のブログでは、早速 K里さん、なおきお~さんから Windows 7 のお話をしていただきましたが、私からのプリンタ ネタについては、しばらくは昔の Windows からあるような基本的な内容についてお話させていただく予定です。よろしくお願いいたします。

今回は、印刷時に使用される2つのスプーリング方法についてお話させていただきます。

具体的には、NT EMF スプーリングと RAW スプーリングの2つとなりますが、これらにはどのような違いがあるのでしょうか。まずは NT EMF スプーリングから見ていきましょう。

 

NT EMF スプーリング

    ①アプリケーション印刷処理開始

       

    ②プリンタデバイス コンテキストへの描画のため、アプリケーションが GDI API を呼び出す

       

    ③呼び出された API とそのパラメータから、GDI WinSpool 経由で NT EMF スプール ファイルを作成する

       

    ④アプリケーション印刷処理終了

       

    ⑤プリントプロセッサが NT EMF スプール ファイルを再生する

       

    NT EMF レコードの内容を基に、GDI がプリンタ デバイス コンテキストへ描画を行う

       

    ⑦プリンタドライバの DDI 関数が呼ばれる

       

    ⑧プリンタドライバがプリンタ言語に基づいて RAW データを生成する

       

    ⑨ランゲージモニタが必要な処理を行う(もしあれば)

       

    ⑩ポートモニタが、プリンタ ポートの種類 (USB, TCP/IP etc) に合わせて出力処理を行う

       

    ⑪カーネルモード ドライバに RAW データが通知される

       

    ⑫プリンタに RAW データが通知される

 

NT EMF スプーリング 

 

文章だけではわかりづらいので図も入れてみましたが、以上が NT EMF スプーリング時のシーケンスとなります。それでは細かいことは置いておいて、続けて RAW スプーリングを見てみましょう。

 

RAW スプーリング

    ①アプリケーション印刷処理開始

       

    ②プリンタデバイス コンテキストへの描画のため、アプリケーションが GDI API を呼び出す

       

    GDI がプリンタ デバイス コンテキストへ描画を行う

       

    ④プリンタドライバの DDI 関数が呼ばれる

       

    ⑤プリンタドライバがプリンタ言語に基づいて RAW データを生成する

       

    ⑥アプリケーション印刷処理終了

       

    ⑦プリントプロセッサは、 RAW データをそのまま下位に渡す

       

    ⑧ランゲージモニタが必要な処理を行う(もしあれば)

       

    ⑨ポートモニタは、プリンタ ポートの種類 (USB, TCP/IP etc) に合わせて出力処理を行う

       

    ⑩カーネルモード ドライバに RAW データが通知される

       

    ⑪プリンタに RAW データが通知される

 

 RAW スプーリング

 

以上が RAW スプーリング時のシーケンスとなります。

 

■メリット・デメリット

では、どのようなメリット・デメリットがあるのでしょうか。

NT EMF の場合、GDI が行う描画処理とプリンタ ドライバが行うプリンタ言語への変換処理については、スプーラ サービスにて行われることになりますので、アプリケーションが印刷処理から解放されるまでの時間が早く済むというメリットがあります。また、アプリケーションからの描画命令を一旦 NT EMF スプール ファイルに保持しておくため、再生する際に拡大・縮小したり、ページ順序を入れ替えたり、描画オブジェクトを追加したりすることが可能となります。実際に Windows OS 標準の WinPrint プリント プロセッサでは、[シートごとのページ数] [ページの順序] 機能などを提供しています。

デメリットとしては、トータルで考えると、RAW スプーリングと比較して NT EMF スプール ファイルを処理するプロセスが余計にかかってしまう点がありますが、その差が顕著にわかることはないレベルかと思われます。

これに対し、RAW スプーリングの場合ですが、正直なところ、あまりメリットと言えるメリットは無いような気がします。デメリットとしては、NT EMF スプーリング時のメリットとして挙げました通り、アプリケーションが印刷処理から解放されるまでに時間がかかる点となります。

 

■スプーリング方法の決定

スプーリング方法については、主に3つの要素から決定されます。

1つは、プリンタ プロパティの [詳細設定] タブ上にある [詳細な印刷機能を有効にする] チェックボックスです。チェックボックスを ON にすると NT EMF スプーリングが有効となり、OFF にすると RAW スプーリングとなります。

もう1つは、プリンタ ドライバの DrvEnablePDEV 関数にて設定する DEVINFO 構造体の flGraphicsCaps フラグに GCAPS_DONTJOURNAL がセットされているか否かです。このフラグがセットされていると RAW スプーリングとなり、設定されていないと NT EMF スプーリングとなります。

最後は、印刷開始時にアプリケーションが呼び出す StartDoc API にて、DOCINFO 構造体の lpszDatatype "emf" が指定されているか否かです。

"emf" の場合には NT EMF スプーリングとなり、それ以外の文字列の場合は RAW スプーリングとなります。

なお、上記うち、いずれか1つでも RAW スプーリングの設定となっている場合には RAW スプーリングされます。つまり、全ての設定が NT EMF スプーリングとなっていないと、NT EMF スプーリングされません。

 

■スプーリング方法の見分け方

印刷時に RAW スプーリングなのか、NT EMF スプーリングなのかを見分ける方法としては、スプール フォルダに生成されるスプール ファイル内のデータを見ることで判断が出来ます。(スプールフォルダについては、プリンタ フォルダから [サーバーのプロパティ] を開き、[詳細設定] タブ上の [スプールフォルダ] にて指定されています。)

プリンタ キューを一時停止にして印刷を行い、スプール フォルダに生成されたスプール ファイル (.spl) をバイナリ エディタ等で開いてみてください。中身が RAW データであれば RAW スプーリングされたことになり、そうでなければ NT EMF スプーリングされたことになります。

 

今回お話した内容はスタンドアロン環境での動作となりますが、Point and Print によりインストールしたプリンタや、Client Side Rendering (CSR) の場合には、サーバー側も意識する必要があります。

次回はその辺についてお話しようと思います。

ではまた。

 

Posted by jpwdkblg | (Comments Off)
Filed under:

Windows Driver Kit (WDK) Version 7.0.0がリリースされました

こんにちは。なおきお~です。

 

200986(米国時間)に、 Windows Driver Kit (WDK) Version 7.0.0 RTM が、Microsoft Connect からダウンロードできるようになりました。

ダウンロードの方法は、「DDK/WDK の入手方法 - Welcome, Device driver world!!!」でご紹介した方法と同じ方法でログインをして、"会員一覧" から "Windows Driver Kit (WDK)" をクリックします。そして、ダウンロードを選択すると、"Windows Driver Kit (WDK) 7_0_0" があるので、この項目をクリックして、ダウンロードが終わるまで、ジーッと待っていてください。また、今までダウンロードできた WDK は、"WDK and DDK Archives" をクリックするとダウンロードできるようになっています。

 

また、今回 WDK は、Windows 7 が対象 OS として、新たにサポートされました。Windows 7 で新たに追加や更新されたドライバの機能は、WDK Documentation "New Information" "New for Windows 7" に概要が掲載されので、興味があれば、ご一読ください。例えば、生体認証のドライバやマルチタッチのドライバなどが新たに追加されています。

ただ、今回の WDK は、Windows 2000 が未サポートになってしまったことを気を付けてください。

Windows 2000 のドライバは、"WDK and DDK Archives" から、前のバージョンを入手して、開発をしてください。

なお、今回の WDK のそれぞれのドライバのトピックについては、各チーム メンバーからご紹介していきたいと思います。

 

それではまた。

Posted by jpwdkblg | (Comments Off)
Filed under:

デバイス メタデータ パッケージ

こんにちは、K里です。

 

Windows 7 のリリースが近づいてまいりました。WDK も現在 Windows 7 RC 用の WDK としてキットの配布がされています。その中で、一部の新要素となるデバイス メタデータについてお話したいと思います。お役にたてれば幸いです。

 

デバイス メタデータパッケージ

Windows 7 の新機能に “デバイスとプリンター” と “Device Stage” があります。デバイスとプリンター画面では、ユーザーが PC 上で使用する様々なデバイス (プリンター、スキャナー、デジタルカメラ、ポータブルオーディオプレーヤー、携帯電話などなど) を一元管理します。また、Device Stage 画面では、各デバイスに応じた固有のインターフェースを提供します。たとえば、デジタルカメラであれば、写真を取り込んだり編集したり、オーディオプレーヤーであれば、音楽を再生したり、などといったインターフェースを提供することになると思います。デバイスメーカー各社は、これらの機能を利用することで、ユーザーエクスペリエンスの向上や、自社ブランドを高めるためのビジュアル インターフェースを提供することができます。

 

 

話を戻しますと、上述のデバイスとプリンター、ならびに Device Stage を定義する情報が、デバイスメタデータ パッケージとなります。デバイス メタデータ パッケージは、複数の XML スキーマとイメージ ファイルでパッケージング化されます。なお Device Stage については、WDK とは別に Microsoft Device Experience Development Kit があります。詳細については下記 URL をご参照ください。

 

  Windows デバイス エクスペリエンス

  http://www.microsoft.com/japan/whdc/device/DeviceExperience/default.mspx

  Microsoft Device Experience Development Kit

  http://www.microsoft.com/whdc/device/DeviceExperience/Dev-Kit.mspx

  Windows 7 Portable Device Enabling Kit for MTP Version 7R2

  http://www.microsoft.com/japan/whdc/device/wpd/MTP-DEK_Win7.mspx

 

デバイス メタデータを構成するコンポーネント

では、デバイス メタデータパッケージを構成する各種コンポーネントを、WDK 7.0.0 に含まれるToaster 向けメタデータを参考に説明します。Toaster のサンプル メタデータは、%WinDDK%\7100.0.0\src\general\toaster\devicemetadatapackage\rawdata にあります。今回は、ja-jp 用のメタデータを使用しています。

 

PackageInfo: http://msdn.microsoft.com/en-us/library/dd835107.aspx

デバイス メタデータ パッケージの統括的な情報を構成するスキーマです。OS は、この情報を基に、パッケージのインストール、ならびにコンテンツの参照を行います。例えば対象デバイスの HardwareID や地域情報、パッケージの構成情報などが含まれます。ちなみに下のサンプルスキーマで、<HardwareID> 要素の Prefix に定義される DOID は、デバイスコンテナーの種別を意味します。デバイスコンテナーは、デバイスが持つ機能のグルーピング化するもので、例えばプリンター、スキャナー、FAX 機能を持つ Multi Function Device を一デバイス (見た目上は一つのデバイス) と認識するためのものです。対して、複数機能を持ち、且つ一機能で認識するデバイスをシングルファンクションデバイスコンテナー (SFDOID) と定義しています (見た目上は複数のデバイス)。現在までのところ、Windows 7 では、DOID のみをサポート対象としています。

 

<?xml version="1.0" encoding="utf-8" standalone="yes"?>

<PackageInfo xmlns="http://schemas.microsoft.com/windows/DeviceMetadata/PackageInfo/2007/11/">

  <MetadataKey>

    <HardwareIDList>

      <HardwareID>DOID:{b85b7c50-6a01-11d2-b841-00c04fad5171}\MsToaster</HardwareID>

    </HardwareIDList>

    <Locale default="false">ja-JP</Locale>

    <LastModifiedDate>2009-02-25T11:46:53.5108690Z</LastModifiedDate>

  </MetadataKey>

  <PackageStructure>

    <Metadata MetadataID="http://schemas.microsoft.com/windows/DeviceMetadata/PackageInfo/2007/11/">PackageInfo.xml</Metadata>

    <Metadata MetadataID="http://schemas.microsoft.com/windows/DeviceMetadata/DeviceInfo/2007/11/">DeviceInformation</Metadata>

    <Metadata MetadataID="http://schemas.microsoft.com/windows/DeviceMetadata/WindowsInfo/2007/11/">WindowsInformation</Metadata>

  </PackageStructure>

</PackageInfo>

 

DeviceInfo: http://msdn.microsoft.com/en-us/library/dd835138.aspx

デバイス固有の情報を定義するスキーマです。製造元名、モデル名、デバイスの説明、デバイスカテゴリ、デバイス アイコンファイルなどを定義します。

 

<?xml version="1.0" encoding="utf-8" standalone="yes"?>

<DeviceInfo xmlns="http://schemas.microsoft.com/windows/DeviceMetadata/DeviceInfo/2007/11/">

  <DeviceCategoryList>

    <DeviceCategory>Other</DeviceCategory>

  </DeviceCategoryList>

  <ModelName>トースター</ModelName>

  <DeviceDescription1>WDK トースター用 デバイスメタデータパッケージサンプル</DeviceDescription1>

  <Manufacturer>Fabrikam, Inc.</Manufacturer>

  <DeviceIconFile>Toaster.ico</DeviceIconFile>

</DeviceInfo>

 

WindowsInfo: http://msdn.microsoft.com/en-us/library/dd835104.aspx

“デバイスとプリンター“ 上で、対象デバイスの表示方法を定義するスキーマです。対象デバイスの Device Stage 画面の表示設定や、デバイス接続状態に応じた表示設定を定義します。

 

<?xml version="1.0" encoding="utf-8" standalone="yes"?>

<WindowsInfo xmlns="http://schemas.microsoft.com/windows/DeviceMetadata/WindowsInfo/2007/11/">

  <ShowDeviceInDisconnectedState>false</ShowDeviceInDisconnectedState>

  <LaunchDeviceStageOnDeviceConnect>false</LaunchDeviceStageOnDeviceConnect>

  <LaunchDeviceStageFromExplorer>false</LaunchDeviceStageFromExplorer>

</WindowsInfo>

 

Device Icon ファイル:

デバイスとプリンター画面に表示するためのアイコンファイル (.ico) を定義します。

 

パッケージのビルド

メタデータのパッケージ名は、”<GUID>.devicemetadata-ms” となります。このため、まずは Guidgen.exe ツールを使用してパッケージ用の GUID を取得します。次に、パッケージ情報を Cabarc.exe ツールを使用して全ファイルを圧縮することで、デバイス メタデータ パッケージが作成されることになります。それでは、先ほどの Toaster Raw Data を使用してパッケージを作成してみます。

 

 

1.     下記フォルダ内のデータを作業用フォルダにコピーします。ここでは、D:\Test にコピーすることにします。

%WinDDK%\7100.0.0\src\general\toaster\devicemetadatapackage\rawdata\ja-jp\6d898b55-ab8a-4762-bdaf-cb0972a304c5

2.     Guidgen.exe を起動し、Format Type 4 に設定し、GUID を取得します。

 

 

3.     コマンドプロンプト上で、Cabarc.exe より以下のように設定し、パッケージを作成します (赤字が 2 で取得した GUID となります)

D:\Test>D:\tools\Cabarc\BIN\CABARC.EXE -p -r N A3EB00A7-AF45-4b4f-9A10-133D2636C30A.devicemetadata-ms *.*

 

Microsoft (R) Cabinet Tool - Version 1.00.0601 (03/18/97)

Copyright (c) Microsoft Corp 1996-1997. All rights reserved.

 

Creating new cabinet 'A3EB00A7-AF45-4b4f-9A10-133D2636C30A.devicemetadata-ms' with compression 'MSZIP':

  -- adding PackageInfo.xml

  -- adding DeviceInformation\DeviceInfo.xml

  -- adding DeviceInformation\Toaster.ico

  -- adding WindowsInformation\WindowsInfo.xml

 

Completed successfully

4.     作業フォルダ内にデバイス メタデータ パッケージ (.devicemetadata-ms ファイル) があることを確認します。

 

上記で使用した各ツールについては以下をご参照ください。

Microsoft Exchange Server GUID Generator

http://www.microsoft.com/downloads/details.aspx?familyid=94551f58-484f-4a8c-bb39-adb270833afc&displaylang=en

Microsoft Cabinet SDK について

http://support.microsoft.com/kb/310618/ja

パッケージのインストール

メタデータのパッケージをインストールする方法は、以下の 3 通りあります。

 

Ø  WMIS (Windows Metadata and Internet Services) からインストールする

OS は新しいハードウェアを検知すると、オンラインで WMIS を利用することで、そのデバイスに対するメタデータを検索します。WMIS でインストール可能なメタデータは、Windows ロゴプログラムにて、ドライバ パッケージとともに送付し、署名されたものになります。ちなみにロゴ申請時にデバイスメタデータ パッケージが必須というわけではありません。

Ø  アプリケーションからインストールする

シェル関数 SHGetKnownFolderPath よりパッケージのフルパスを取得し、CreateFile 関数でストアフォルダに格納します。

Ø  手動でインストールする

対象パッケージを %PROGRAMDATA%\Microsoft\Windows\DeviceMetadataStore にコピーします。

※例えば Toaster 用のパッケージ (.devicemetadata-ms ファイル) を上記フォルダにコピーすると、デバイスとプリンター画面の Toaster アイコンが変わります。

 

いかがでしたでしょうか。今回は、WDK に付属するサンプルを参考にデバイス メタデータ パッケージについてお話ししました。それではまた。

Posted by jpwdkblg | (Comments Off)
Filed under:

SetupDi API と DevCon ~ SetupDi API の使い方編 ~

まさかたです。こんにちは。

 

前回、「DevCon と SetupDi API ~ DevCon の使い方編 」で、DevCon とその使い方について、簡単にご紹介させていただきました。

今回は、サンプルソースコードでどういう風に SetupDi API が使われているのかを見て、その基本的な使い方を紹介したい思います。

 

DevCon のコマンドオプションとコールバック関数

さて、DevCon コマンドに渡すオプションが、それぞれどのコードに対応するかですが、これは、Cmds.cpp 内に、各コマンドに対応してコールされる関数名が、DispatchTable として定義されておりますので、ここから、オプション毎にどの関数が呼ばれているかが簡単分かります(cmds.cpp 2308 行目より)。

(結局、オプション名の直前に “cmd” がついた関数を見ればいいわけです。)

2308    DispatchEntry DispatchTable[] = {

2309        { TEXT("classfilter"),  cmdClassFilter, MSG_CLASSFILTER_SHORT, MSG_CLASSFILTER_LONG },

2310        { TEXT("classes"),      cmdClasses,     MSG_CLASSES_SHORT,     MSG_CLASSES_LONG },

2311        { TEXT("disable"),      cmdDisable,     MSG_DISABLE_SHORT,     MSG_DISABLE_LONG },

2312        { TEXT("driverfiles"),  cmdDriverFiles, MSG_DRIVERFILES_SHORT, MSG_DRIVERFILES_LONG },

2313        { TEXT("drivernodes"),  cmdDriverNodes, MSG_DRIVERNODES_SHORT, MSG_DRIVERNODES_LONG },

2314        { TEXT("enable"),       cmdEnable,      MSG_ENABLE_SHORT,      MSG_ENABLE_LONG },

2315        { TEXT("find"),         cmdFind,        MSG_FIND_SHORT,        MSG_FIND_LONG },

2316        { TEXT("findall"),      cmdFindAll,     MSG_FINDALL_SHORT,     MSG_FINDALL_LONG },

2317        { TEXT("help"),         cmdHelp,        MSG_HELP_SHORT,        0 },

2318        { TEXT("hwids"),        cmdHwIds,       MSG_HWIDS_SHORT,       MSG_HWIDS_LONG },

2319        { TEXT("install"),      cmdInstall,     MSG_INSTALL_SHORT,     MSG_INSTALL_LONG },

2320        { TEXT("listclass"),    cmdListClass,   MSG_LISTCLASS_SHORT,   MSG_LISTCLASS_LONG },

2321        { TEXT("reboot"),       cmdReboot,      MSG_REBOOT_SHORT,      MSG_REBOOT_LONG },

2322        { TEXT("remove"),       cmdRemove,      MSG_REMOVE_SHORT,      MSG_REMOVE_LONG },

2323        { TEXT("rescan"),       cmdRescan,      MSG_RESCAN_SHORT,      MSG_RESCAN_LONG },

2324        { TEXT("resources"),    cmdResources,   MSG_RESOURCES_SHORT,   MSG_RESOURCES_LONG },

2325        { TEXT("restart"),      cmdRestart,     MSG_RESTART_SHORT,     MSG_RESTART_LONG },

2326        { TEXT("sethwid"),      cmdSetHwid,     MSG_SETHWID_SHORT,     MSG_SETHWID_LONG },

2327        { TEXT("stack"),        cmdStack,       MSG_STACK_SHORT,       MSG_STACK_LONG },

2328        { TEXT("status"),       cmdStatus,      MSG_STATUS_SHORT,      MSG_STATUS_LONG },

2329        { TEXT("update"),       cmdUpdate,      MSG_UPDATE_SHORT,      MSG_UPDATE_LONG },

2330        { TEXT("updateni"),     cmdUpdateNI,    MSG_UPDATENI_SHORT,    MSG_UPDATENI_LONG },

2331        { TEXT("dp_add"),       cmdDPAdd,       MSG_DPADD_SHORT,       MSG_DPADD_LONG },

2332        { TEXT("dp_delete"),    cmdDPDelete,    MSG_DPDELETE_SHORT,    MSG_DPDELETE_LONG },

2333        { TEXT("dp_enum"),      cmdDPEnumLegacy,MSG_DPENUM_SHORT,      MSG_DPENUM_LONG },

2334        { TEXT("?"),            cmdHelp,        0,                     0 },

2335        { NULL,NULL }

2336    };

 

試しにfind オプションの場合として、cmdFind() の中をのぞいてみると、中でさらに EnumerateDevices() という関数がコールされています。

failcode = EnumerateDevices(BaseName,Machine,DIGCF_PRESENT,argc,argv,FindCallback,&context);

この関数は、DevCon.cpp の 798 行目から定義されており、以下に示すように、その他のオプションの処理でも呼ばれている関数です。

ですので、今回は、SetupDi API を使ったデバイスの情報を採取する共通の手段として、主にこの中で行われている処理について見ていきたいと思います。

ü  HwIDs

ü  DriverFiles

ü  DriverNodes

ü  Resources

ü  Stack

ü  Status

ü  Find

ü  FindAll

ü  Enable

ü  Disable

ü  Remove

ü  Restart

ü  SetHwID

 

n  Setup API の使い方

ここでは、EnumerateDevices() のソースコードを細かく 1行 ずつ見ていくのではなく、SetupDi API を使っている箇所にポイントを絞ります。

すると、おおまかな処理の流れは以下のようになると思います。

1.    SetupDiGetClassDevsEx() で、デバイス情報セットへのハンドル(HDEVINFO)を取得

2.    SetupDiEnumDeviceInfo() で、デバイスを列挙

3.    SetupDiGetDeviceRegistryProperty() で、HwID などのデバイスの詳細情報を取得

4.    3 で取得した情報から目的のデバイスであるかを判別し、オプション毎に定義された Callback 関数を呼んで独自の処理を実行

5.    最後は、SetupDiDestroyDeviceInfoList() で、使い終わったデバイス情報セットを破棄

以下では、それぞれの API について、その定義と使われ方を見ながら、デバイスを列挙する仕組みや概念についてもご紹介したいと思います。

ただし、SetupDiDestroyDeviceInfoList() については、ハンドルを破棄するだけのものですので、詳しい説明は省略させていただきます。

 

1.     SetupDiGetClassDevsEx

2.     SetupDiEnumDeviceInfo

3.     SetupDiGetDeviceRegistryProperty

 

1. SetupDiGetClassDevsEx

この API は何をするかと言うと、デバイスを列挙する前に、列挙する元となる様々なデバイスの情報をかき集めて、ひとつの「デバイス情報セット」と呼ばれる、デバイスの情報の集合体のようなものを構築して、それにアクセスするためのハンドルを返してくれます。

この「デバイス情報セット」の詳細については、以下の 【補足】デバイス情報セットについて にて補足の説明をしていますので、併せて見ていただければと思います。

 さて、この関数を使ってデバイス情報セットを構築する時、どんな種類のデバイスの情報をかき集めるのかを、引数を使って指定することができます。

API そのものの定義は以下の通りです。

HDEVINFO
  SetupDiGetClassDevsEx(
    IN LPGUID  ClassGuid,  OPTIONAL
    IN PCTSTR  Enumerator,  OPTIONAL
    IN HWND  hwndParent,  OPTIONAL
    IN DWORD  Flags,
    IN HDEVINFO
  DeviceInfoSet,  OPTIONAL
    IN PCTSTR  MachineName,  OPTIONAL
    IN PVOID  Reserved
    );

 

以下では、SetupDiGetClassDevsEx() でポイントとなる、ClassGUIDEnumeratorFlags のパラメータについて見ていきます。

Ø  ClassGUID

ClassGUID には、情報を集めてくるデバイスの種類を、Device Setup Class または Device Interface Class という Class で指定することができます。

Class GUID は、その名の通り、上記の Class を表す GUID になります。

上記の2つの Class の詳細については、さらに以下の 【補足】Device Setup Class Device Interface Class について  でも、さらに説明をしていますので、そちらもご参照ください。

ここで指定したクラスに属するデバイスだけが、デバイス情報セットに含まれることになります。

Ø  Enumerator

この引数は、デバイス情報セットに含めるデバイスの種類をフィルタリングするために指定するものです。

このパラメータの意味合いは、以下で説明する Flags で何を指定するかによっても変わります。

Flags で、DIGCF_DEVICEINTERFACE を指定しない場合 は、Plug and Play の列挙子(Enumerator)の ID として認識され、例えば、”PCI”、”USB”、"PCMCIA"、”SCSI” 等が指定できます。

ここで、他に指定できる Enumerator としては、具体的には、以下のレジストリキー直下のキー名が指定できます。

 

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum

 

 EnumRegistryKey

 

また、DIGCF_DEVICEINTERFACE を指定した場合は、 PnP のデバイスインスタンス IDとして認識されます。

Device Instance IDs

http://msdn.microsoft.com/en-us/library/dd567984.aspx

Ø  Flags

Flags も、さらにデバイス情報セットに含めるデバイスの種類をフィルタリングするために指定するもので、指定できる Flag と、それぞれの意味は以下のようになります。

この Flag を組み合わせて、さらにデバイスの絞込みをすることができます。

Flags

対象となるデバイス

DIGCF_ALLCLASSES

Device Setup Class および Device Interface Class を含む全ての Class のデバイス

DIGCF_DEVICEINTERFACE

全ての Device Interface Class のデバイス

DIGCF_DEFAULT

システムにデフォルトで組み込まれている Device Interface Class のデバイス

(後から追加した Class は無視)

DIGCF_PRESENT

現在、システムに接続されているデバイスのみ

Non Present Device Phantom Device は無視)

DIGCF_PROFILE

現在のハードウェア プロファイルに含まれるデバイスのみ

 

以上を踏まえて、DevCon で使われているコードを見てみます。(devcon.cpp 898 行目より)

898             devs = SetupDiGetClassDevsEx(numClass ? &cls : NULL,

899                                          NULL,

900                                          NULL,

901                                          (numClass ? 0 : DIGCF_ALLCLASSES) | Flags,

902                                          NULL,

903                                          Machine,

904                                          NULL);

 

上記の numClass は、コマンドのオプションで、Class 名がいくつ指定されたかを表すものです。

これが 0 の場合は、Class が指定されていないということになりますので、第1引数の ClassGUID には、NULL が指定されます。

逆に、クラス名を指定した場合には、NULL ではなく、cls が入力引数となります。

この cls には、上記のコードの前でコールしている SetupDiClassGuidsFromNameEx() から取得した、ClassGUID が入っていて、これを第1引数に指定して Class を指定しています。

なお、該当するコードの抜粋は以下の通りです。(devcon.cpp 854 行目より)

854    if(argc>skip && argv[skip][0]==CLASS_PREFIX_CHAR && argv[skip][1]) {

855        if(!SetupDiClassGuidsFromNameEx(argv[skip]+1,&cls,1,&numClass,Machine,NULL)

SetupDiClassGuidsFromNameEx() を使えば、DevCon のコマンドオプションで指定したクラス名から ClassGUID を取得することができます。

また、API の定義は以下の通りです。

WINSETUPAPI BOOL WINAPI
  SetupDiClassGuidsFromNameEx(
    IN PCTSTR  ClassName,
    OUT LPGUID  ClassGuidList,
    IN DWORD  ClassGuidListSize,
    OUT PDWORD  RequiredSize,
    IN PCTSTR  MachineName,  OPTIONAL
    IN PVOID  Reserved
    ); 

 

さらに、DevCon 内のソースコードでは、Flags には、EnumerateDevices() に与えられたFlags 引数と、0 または DIGCF_ALLCLASSES OR を取っていますので、基本的には EnumerateDevices() に与えられた Flags が有効になります。

具体的に Flags に与えられている引数の内容を見てみると、多くの場合、DIGCF_PRESENT が指定されており、FindAll オプションの場合のみ、0 が指定されています。

このことから、FindAll 以外では、システムに接続されているデバイスのみが検索対象となり、FindAll の場合には、システムに接続されていないデバイスも検索対象となっているということが分かります。

つまり、他のオプションでも、この Flags で、DIGCF_PRESENT を指定しなければ、システムに接続されていないデバイス(例えば、過去に接続したけど、今は接続していない USB デバイスなど)も、操作の対象とすることができるわけです。

これを応用すれば、例えば、Remove オプションで、DIGCF_PRESENT Flag を外せば、システムに接続されていないデバイスを削除の対象とすることができます。 

 

【補足】デバイス情報セットについて

デバイス情報セットとは、SetupDiGetClassDevs() によって指定された Class に含まれる、複数のデバイスの情報の集合体のようなものです。

下の図は、デバイス情報セットに含まれる、デバイスの情報を、デバイス情報エレメントや、DevNodeDevice Interaface という概念で表した図でこちらの MSDN のページでも参照することができます。

デバイス情報エレメントは、個々のデバイスの情報を表すもので、その中には、1つの Devnode と、1つ以上の Device Interface が含まれています。

DevNode は、個々のデバイス インスタンスに対応するものです。

また、Device Interface については、さらに以下の 【補足】Device Setup Class Device Interface Class について  でも説明をしていますので、そちらも見ていただければと思います。

 DeviceInfoSet

 

【補足】Device Setup Class Device Interface Class について

Device Setup ClassDevice Interface Class というのは、デバイスをある基準で分類した時の種類を表すもので、それぞれに分類する時の基準が微妙に違います。

ü  Device Setup Class

Device Setup Class とは、そのデバイスをインストールする時のセットアップ方法やデバイスの設定の仕方が同じものを、Class として分類したものです。

デバイスのインストールで出てくる Class Installer Co-installer というのは、そのデバイスの Setup Class に応じて用意されるもので、Class 毎に必要になる特別なインストールの方法や設定を行うためのものということになります。

例えば、システムで定義されている Class として、Ports Class がありますが、この Class Installer は、デバイスに対して、COM port 名を割り当てる作業をしたりします。

また、この Setup Class の識別は、Class そのものの名前ではなく、実際には、それぞれに割り当てられた独自の GUID を使って行われます。

システム上に、どんな Device Setup Class が存在し、GUID として何が割り当てられているかは、以下のレジストリキーを参照することで確認することも可能です。

 

 HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Class\<ClassGUID>

 

 ただし、このレジストリキーは、デバッグ目的などで参照することのみ可能なもので、ドライバやユーザーモードアプリケーションから直接アクセスして、編集したりしてはいけないものですので、注意してください。

また、既に System で定義された GUID について詳しいことは、以下を見ていただきたいと思います。 

System-Supplied Device Setup Classes

http://msdn.microsoft.com/en-us/library/ms791134.aspx

ü  Device Interface Class

Device Setup Class に対して、Device Interface Class とは、その名の通り、そのデバイスが、他のアプリケーションやドライバに対して持つ Interfaceという側面から、Class として分類したものです。

デバイスのソフトウェア的な Interface は、そのデバイスを制御するドライバに当たりますから、Device Interface Class とは、そのデバイスを制御するドライバの種類ということになります。

ドライバは、必ず自分がどの Device Interface Class に属するものであるのかを、ドライバの AddDevice 関数の中で IoRegisterDeviceInterface API を使って登録しなくてはなりません。

この Class も、Device Setup  Class と同様に、GUID を使って表されます。

既に System で定義済みの Device Interface Class の詳細については、以下を見ていただければと思います。

 System-Defined Device Interface Classes

http://msdn.microsoft.com/en-us/library/bb663138.aspx

 

1.    2. SetupDiEnumDeviceInfo

SetupDiEnumDeviceInfo 関数では、デバイス情報セットの中に含まれる一つ一つのデバイス情報エレメントを列挙していきます。

API 自体の定義は以下の通りです。

 WINSETUPAPI BOOL WINAPI
  SetupDiEnumDeviceInfo(
    IN HDEVINFO  DeviceInfoSet,
    IN DWORD  MemberIndex,
    OUT PSP_DEVINFO_DATA  DeviceInfoData
    );

 

そして、DevCon で使われているコードは以下の通りです。(devcon.cpp 943行目)

for(devIndex=0;SetupDiEnumDeviceInfo(devs,devIndex,&devInfo);devIndex++) {

 

ここで、SetupDiGetClassDevs() で取得したデバイス情報セット devs を第1引数に渡し、2引数の devIndex をインクリメントしながら、繰り返し同 API をコールすることによって、次々にデバイスの情報を devInfo受け取っています。

列挙されたデバイス情報エレメントの情報は、SP_DEVINFO_DATA 構造体表されます。

 

3. SetupDiGetDeviceRegistryProperty

SetupDiEnumDeviceInfo() で取得した SP_DEVINFO_DATA 構造体を使って、SetupDiGetDeviceRegistryProperty() をコールし、さらにデバイスに関する詳細な情報を取得することが可能になります。

また、SP_DEVINFO_DATA 構造体を使って、デバイスの情報を取得できる SetupDi API は、SetupDiGetDeviceRegistryProperty() 以外にもさまざまあります。

さて、SetupDiGetDeviceRegistryProperty() の定義は以下の通りです。

WINSETUPAPI BOOL WINAPI
  SetupDiGetDeviceRegistryProperty(
    IN HDEVINFO  DeviceInfoSet,
    IN PSP_DEVINFO_DATA  DeviceInfoData,
    IN DWORD  Property,
    OUT PDWORD  PropertyRegDataType,  OPTIONAL
    OUT PBYTE  PropertyBuffer,
    IN DWORD  PropertyBufferSize,
    OUT PDWORD  RequiredSize  OPTIONAL
    );

 

また、DevCon で使われているコードは以下の通りです。(devcon.cpp の 517 行目より)

while(!SetupDiGetDeviceRegistryProperty(Devs,DevInfo,Prop,&dataType,(LPBYTE)buffer,size,&reqSize)) {

 

ここで、第1引数 DeviceInfoSet には、デバイス情報セットを、第2引数 DeviceInfoData には、先に取得した SP_DEVINFO_DATA 構造体を指定します。 

3引数 Property には、どのプロパティを取得してくるのかその種類を指定し、それ以降の引数では、プロパティの値を取得するためのレジストリの値のタイプ(REG_DWORD とか REG_SZなど)や、バッファのポインタとバッファサイズなどを指定します。

また、この API の名前からも察しが付くかと思いますが、これらの情報はレジストリから取得しています。

また、その情報源は、以下のレジストリキー配下に格納されている値になります。

 

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum

 

それじゃ、こんな面倒くさいことをせずに、ここに直接アクセスして情報を取ってくればいいんじゃない、などと思われるかもしれませんし、実際、こちらに直接アクセスして、手を加えているのですが…というお問い合わせをいただくこともあります。

しかし、このレジストリキーは、デバッグ目的などでレジストリエディタなので参照するだけならよいのですが、以下の技術情報にもありますように、OS でのみ管理することを前提としています。


HKLM\SYSTEM\CurrentControlSet\Enum Registry Tree

http://msdn.microsoft.com/en-us/library/dd568017.aspx

 

そのため、ドライバやアプリケーションから直接アクセスして操作すると、システム全体として不整合が発生する恐れもあるため、そのようなことはしてはいけないレジストリなのです。 

というわけで、カーネルモードドライバでは、IoGetDeviceProperty()、ユーザーモードなら SetupDiGetDeviceRegistryProperty() というように、間接的にアクセスするための API が用意されていますので、情報の取得を行う必要がある場合にはこちらの API をお使いいただく必要があります。

 

【補足】Device Interface の列挙について

先の「【補足】デバイス情報セットについて」でご紹介した図には、各デバイス情報エレメントに、さらに「Device Interface」 が含まれる形となっていますが、この「Device Interface」を列挙するには、SetupdiEnumDeviceInterfaces() を使います。

SetupdiEnumDeviceInterfaces() の定義は以下の通りです。

WINSETUPAPI BOOL WINAPI
  SetupDiEnumDeviceInterfaces(
    IN HDEVINFO  DeviceInfoSet,
    IN PSP_DEVINFO_DATA  DeviceInfoData,  OPTIONAL
    IN LPGUID  InterfaceClassGuid,
    IN DWORD  MemberIndex,
    OUT PSP_DEVICE_INTERFACE_DATA  DeviceInterfaceData
    );

 

ここで、第2引数に、 DeviceInfoData を指定することができますが、これによって、列挙する範囲を特定のデバイス情報エレメントに絞ることができるわけです。

逆に指定しなければ、SetupDiGetClassDevs() で取得したデバイス情報セット全体に含まれる Device Interface が列挙されることになります。

そして、列挙した Device Interface に対して、詳細な情報を取得するには、SetupDiEnumDeviceInterfaces() で取得した SP_DEVICE_INTERFACE_DATA 構造体を、SetupdiGetDeviceInterfaceDetail() に渡してコールすることで、SP_DEVICE_INTERFACE_DETAIL_DATA 構造体を取得します。

この構造体から、デバイスハンドルをオープンするために CreateFile() で指定する、Symbolic Link (DevicePath[])を知ることができます。 

 

typedef struct _SP_DEVICE_INTERFACE_DETAIL_DATA {
  DWORD  cbSize;
  TCHAR  DevicePath[ANYSIZE_ARRAY];
} SP_DEVICE_INTERFACE_DETAIL_DATA, *PSP_DEVICE_INTERFACE_DETAIL_DATA;

 

 

今回は、ソースコードの細かな内容はかなりスキップしてしまいましたが、基本的な SetupDi API の使い方と、それにまつわる概念について簡単にご紹介いたしました。

SetupDi API で、デバイスの検索、情報の取得、設定の変更などを行う場合でも、基本的には呼び出しの流れはほぼ同じです。

今後、様々な SetupDi API を使うときに、少しでも皆様のお役に立てれば幸いです。

 

それでは。

Posted by jpwdkblg | (Comments Off)
Filed under:

ドライバ インストール時のトラブルシューティングの第一歩

皆さん、こんにちは。A寿です。

 

突然ですが、皆さんは魚に手足をかじられたことはありますか?・・・このお話にご興味のある方は本文の最後の【閑話休題】までどうぞ。

 

 

さて、今回は、「ドライバインストール時のトラブルシューティングの第一歩」をご案内したいと思います。お客様からのお問い合わせの中に、よく「ドライバのインストールに失敗するのですが、どうすればよいのでしょうか?」とおっしゃられる方がいらっしゃいます。その場合に、お客様に最初にご確認いただく情報として、以下の2つをご案内することが多いです。

 

  (1) デバイスマネージャで、対象デバイスに警告の「!」マークが出ている場合、プロパティに表示されるエラーコード

  (2) setupapi.logを採取してエラーの内容を確認

 

それでは、(1)から順番に見ていきましょう。

 

(1) デバイスマネージャで、対象デバイスに警告の「!」マークが出ている場合、プロパティに表示されるエラーコード

 

デバイスマネージャで、対象デバイスに警告の「!」マークが出ている場合、とは、次のような状態のことを言います。

 

 

 

今回、説明のために、USBフラッシュメモリに「ハードウェアの安全な取り外し」を実行した後、物理的には抜いていない状態を作りました。このデバイスのプロパティを見ると、次のように表示されます。

 

 

 

このプロパティの全般タブの下半分の「デバイスの状態」にあるメッセージと、その後の「コード 47」というエラーコードにご着目ください。このようなエラーコードの解決方法などの説明は、

 

Device Manager Error Messages

http://msdn.microsoft.com/en-us/library/ms791364.aspx

 

を見てください。

 

今回の例であるコード47の場合は、メッセージ部分に「この問題を解決するには、デバイスを取り外してから再度取り付ける必要があります。」と解決方法が書いてあります。一方、上記ドキュメントの「Code 47 CM_PROB_HELD_FOR_EJECT」のリンクをたどると、

 

CM_PROB_HELD_FOR_EJECT

http://msdn.microsoft.com/en-us/library/ms791344.aspx

 

のドキュメントに行くことができ、そこには、「The device has been prepared for ejection. (Windows XP and later)」というようにコードの説明がされていたり、Error CodeDisplay MessageRecommended Resolutionのような項目が並んでいたりすることが確認できます。

そして、Recommended Resolutionの項目に、上記メッセージの解決方法と同様に、

 

Unplug the device and plug it in again. Alternately, selecting Restart Computer will restart the computer and make the device available.

 

という内容を読むことができます。

 

それでは、同様に、お問い合わせの中で回答することが多いコード番号である、コード10とコード31を見てみましょう。

 

まず、コード10についてです。「Device Manager Error Messages」ドキュメントの中の「Code 10 CM_PROB_FAILED_START」のリンクをたどると、

 

CM_PROB_FAILED_START

http://msdn.microsoft.com/en-us/library/ms791325.aspx

 

のドキュメントに行くことができ、そこにメッセージ(Display Message)

 

"This device cannot start. (Code 10)"

 

になることが書かれています。この問題の解決方法はプロパティの「デバイスの状態」には表示されませんが、このドキュメントを見ることで、Recommended Resolutionの中に、

 

This error code is set when one of the drivers in the device's driver stack fails IRP_MN_START_DEVICE.

 

という一文から、このエラーが、対象デバイスのドライバがIRP_MN_START_DEVICEの処理に失敗したことがわかります。そのため、この処理の周辺に

問題がないか、デバッグをしていけばよい、ということがわかります。

 

次に、コード31の対処方法を知るために、「Code 31 CM_PROB_FAILED_ADD」のリンクをたどってみましょう。

 

CM_PROB_FAILED_ADD

http://msdn.microsoft.com/en-us/library/ms791370.aspx

 

のドキュメントを見ると、Display Message

 

"This device is not working properly because Windows cannot load the drivers required for this device. (Code 31)"

 

です。このメッセージの場合も、メッセージだけからは解決方法を知ることはできません。そこで、Recommended Resolutionの項目を見ますと、

 

Beginning with Windows XP, this problem can only occur if the driver's AddDevice routine fails.

 

とあります。つまり、対象デバイスのドライバがAddDeviceルーチンで失敗したために、このエラーになったことがわかります。

 

以上のように、ドライバのインストールが失敗した際に、デバイスマネージャ上のデバイスのプロパティでエラーコードがわかった場合は、「Device Manager Error Messages」ドキュメントから、該当エラーコードのリンクをたどることで、問題解決への第一歩を踏み出すことができます。

 

 

(2) setupapi.logを採取してエラーの内容を確認

 

setupapi.logは、Vista以前の場合は、%SystemRoot%(C:\Windows)フォルダ、Vista以降では%SystemRoot%\inf(C:\Windows\inf)フォルダにあります。

ただ、Vista以降でも%SystemRoot%(C:\Windows)フォルダにsetupapi.logがありますが、こちらを開くと、

 

The location of the SetupAPI log file has been changed.

The new location is: D:\Windows\INF

 

のように書かれています。実際には、Vista以降では、setupapi.logという名前ではなく、setupapi.app.logsetupapi.dev.logという名前になっています。setupapi.app.logは、インストールアプリケーションやクラスインストーラなどのアプリケーション側のインストール時のログ、setupapi.dev.logはデバイスとドライバ側のインストールのログです。今回は両方のファイルを見ますので、2つのログの違いについての詳細は、下記ドキュメントやそのリンクに譲りたいと思います。

 

SetupAPI Text Logs

http://msdn.microsoft.com/en-us/library/aa477114.aspx

 

さて、Vista以前と以降でsetupapiログファイルのファイル名が違うと、説明がしづらいので、以後、総称して「SetupAPIログファイル」と呼ばせていただきます。このSetupAPIログファイルを見ることで、ドライバのインストールの成功/失敗、失敗時のエラーコードやメッセージを知ることができます。そして、エラーコードやメッセージを見つけたら、WHDCのサイトの

 

  SetupAPI ログ ファイルを使用した、デバイスのインストールのトラブルシューティング

  http://www.microsoft.com/japan/whdc/driver/install/setupapilog.mspx

 

のページにある、SetupAPILog.docを開いて、その中でエラーコードやメッセージを文字列検索してみてください。「7. Common Device-Installation Problems」の章に、以下のような内容についてのエラーメッセージの実例が多くありますので、そのどれかにヒットすれば、問題が解決する確率がグンと上がります。

 

Ø  The devices INF file has been modified but not re-signed

Ø  SetupAPI cannot find a driver for the device

Ø  Rebooting the system is required

Ø  A device vetoes its removal

Ø  The test certificate for a driver package is not installed

Ø  The certificate for a driver package that has a Authenticode signature is not installed

Ø  A driver file is unsigned

Ø  A service deletion is pending

Ø  A protected system file was replaced

 

例を挙げましょう。例えば、Vista以降のx64環境にドライバをインストールした際に、インストールが失敗し、setupapi.app.log

 

>>>  [SetupVerifyInfFile - C:\Windows\INF\oem1.inf]

>>>  Section start 2009/06/19 19:06:06.702

      cmd: "C:\Windows\system32\mmc.exe" "C:\Windows\system32\compmgmt.msc" /s

!    sig: Verifying file against specific (valid) catalog failed! (0x800b0109)

!    sig: Error 0x800b0109: A certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider.

!    sig: Verifying file against specific Authenticode(tm) catalog failed! (0x800b0109)

!    sig: Error 0x800b0109: A certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider.

<<<  Section end 2009/06/19 19:06:06.702

<<<  [Exit status: FAILURE(0x800b0109)]

 

のようなエラーが出たとします。この時、上記の黄色部分のメッセージからだけでも、ドライバ署名のルート証明書がtrusted providerに信頼されていないのだな、ということがわかります。この時、エラーコードである「0x800b0109」でSetupAPILog.docを文字列検索すると、「7.5 Test Certificate Not Installed」の、

 

Error 0x800b0109: A certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider.

 

というメッセージが見つかります。そこで、この節を読んでみると、

 

To fix this problem, install the test certificate and reboot.

 

という解決策が書かれています。(実際には、これだけだと漠然としているので、

  カーネル モードのコード署名の手順

  http://www.microsoft.com/japan/whdc/winlogo/drvsign/kmcs_walkthrough.mspx

を読んで、適切に署名を行ったり、certmgr.exeで証明書を正しい場所(roottrustedpublisher)にインストールをしたりといったことが必要になります。)

 

他の例としては、例えばWindows 2000

 

エラー 1072: 指定されたサービスは削除の対象としてマークされています。

 

というようなエラーが表示された場合には、「1072」でSetupAPILog.docを文字列検索すると、「7.8 Service Deletion Pending」の

 

Error 1072: The specified service has been marked for deletion.

 

というメッセージが見つかります。そこで、この節を読んでみると、

 

If an INF file deletes a service by using a DelService directive, and then it attempts to add the same service by using an AddService directive, SetupAPI will log an error.

 

という説明や、

 

Note that the only way to correct this error is to reboot.

 

という解決策が書かれています。

 

以上のように、もしSetupAPIログファイルのエラー内容が、SetupAPILog.docドキュメントに記載されていれば、早い段階で問題を解決できる可能性があります。ただ、必ずしも、このドキュメントだけでSetupAPIログファイルに書かれた全てのエラーが解決できるわけではないことを十分ご理解いただきたいと思います。その場合はぜひWindows デバイスドライバー開発フォーラムにご相談いただいたり、我々ドライバ開発サポート(有償)にお問い合わせいただき、ログの状況から原因を調査させていただければ幸いです。ただ、このドキュメントにより、少しでも皆様のお問い合わせの手間を減らすことができれば、より幸いであると思います。

 

 

以上、「ドライバ インストール時のトラブルシューティングの第一歩」をお送りしましたが、あくまでもこれは第一歩です。上記の方法により、問題の解決の糸口をつかんだあと、長期にわたるデバッグ調査が必要な場合もありますが、早く問題解決への第一歩を踏み出せるのは意味のあることだと思います。開発中のドライバをインストールして問題がおきた場合は、ぜひ上記の方法をお試しいただたいと思いますし、WDKドキュメントには以下のようなサイトもございますので、こちらも併せてご参照いただければ幸いです。

 

Troubleshooting Device Installations

http://msdn.microsoft.com/en-us/library/ms791354.aspx

 

 

――――――――――――――――

 

【閑話休題】皆さんは魚に手足をかじられたことはありますか?

 

私は、グアムでダイビング体験教室に参加した時に手を、箱根の某温泉テーマパークで足をかじられたことがあります。

 

ダイビングの時には、友人たちと一緒に海にもぐって、海中展望塔の中の小さなお子様とジャンケンして遊んだり、先生に写真を撮ってもらったりと楽しい時間を過ごしていたのですが、魚に魚肉ソーセージをあげようとしたところ、バクッと人差し指をかじられてしまいました。幸い、かじられたといっても数週間歯型が残る程度でしたし、「どうせ、初心者がダイビングするところなんて、かわいい熱帯魚しかいないから大したことないでしょ」と思われる方もいらっしゃると思います。が、残念ながら、私の指をかじったのは、でかい魚で、しかも、後で写真で確認したところ、他の友人たちの周りにはかわいい熱帯魚が囲んでいたにもかかわらず、私の周りだけ、でかい魚がうようよしていたのです。皆様もダイビング中に魚にえさをあげる際にはお気をつけください。彼らは結構テキトーです。

 

さて、足の方はといいますと、箱根の某温泉テーマパークでの話ですので、もちろんでかい魚にかじられるということはなく、ドクターフィッシュと言われる、足の悪いところ()をかじってくれる魚にかじってもらいました。「それなら全然危なくないじゃん」と思われるかもしれませんが、私は極度のくすぐったがりなので、魚のいる水槽(?)に足をつけたらすぐに小さな魚が大量に群がってきて、触れるか触れないかの絶妙な力加減で足の裏をこちょこちょこちょこちょと噛まれると、もう大変です。大騒ぎです。同席していた外国の観光旅行者の方たちが、「Oh My God!!!!」と口々に繰り返し叫んでいたことからも、私がどれだけ大変な思いをしたかがおわかりいただけると思います。その方たちのおかげで、私の大騒ぎは比較的軽い方であったのがせめてもの救いです。皆様も、魚に故意に足をかませる際には、自分がくすぐったがりでないかどうかをよくご確認ください。

 

 

Posted by jpwdkblg | (Comments Off)
Filed under:

WPA とか XPerf とか

こんにちは、K 里です。今回は WPA (Windows Performance Analyzer) をご紹介します。

 

※ 2009/12/25 に情報を追加しました。この記事の最後に追加しましたのでご確認いただけると幸いです。

 

WPA (ひょっとしたら Xperf という名前の方が有名かもしれません) は、Windows OS やその中で動作するアプリケーション、サービス、ドライバを含むシステム全体のパフォーマンスを詳細に測定するためのプログラムです。このプログラムは、システムビルダー、ハードウェアメーカー、アプリケーション&ドライバ デベロッパーの方々を対象としています。用途としては、開発時に発生する問題の一次的な切り分けやシステム全体のパフォーマンス検証などが主です。WPA は、見るべき個所が多岐にわたるパフォーマンス関連の調査ならびに検証に対して非常に優れた効果を発揮します。是非ご活用くださいませ。

 

インストールしよう

まずは下記 URL Downloads のセクションから WPA のツールキット (Windows Performance Toolkit) をダウンロードしましょう。

 

Windows Performance Analysis

http://msdn.microsoft.com/en-us/performance/

 

インストールフォルダには、以下の実行ファイルがあります。

Ø  xperf.exe: カーネルイベントを含む各種トレースデータを採取するための実行ファイル

Ø  xperfview.exe: xperf.exe で採取したトレースデータをグラフィカルに表示してくれるビューアー (CUI からだと xperf xxx.etl でも可)

Ø  xbootmgr.exe: システムの状態遷移時にトレースするための実行ファイル

 

WPA は、Windows XP SP2, Vista SP1, Server 2003 SP1, Server 2008 以降 OS 動作します。しかし、Windows XP Server 2003 では、キットのインストールができないため、一度 Vista もしくは Server 2008 にインストールし、インストールフォルダ (デフォルトだと \Program Files\Microsoft Windows Performance Toolkit) から xperf.exe perfctrl.dll XP, Server 2003 環境にコピーすることになります。また、XP, Server 2003 でトレースデータの取得は可能ですが、ビューアーからの確認は残念ながらできません。XP, Server 2003 で採取したトレースデータは、Vista もしくは Server 2008 環境で確認することになります。

 

使ってみよう

モノは試しです。まずは使ってみましょう。コマンドプロンプトを管理者権限で起動し、下記コマンドを実行します。(1) のコマンドで、トレースが開始されます。次に、システム上でファイル操作やアプリケーション操作、デバイス接続などシステムに負荷を与えるようなことを色々やってみてください。適当なタイミングで (2) のコマンドを実行します。これで、トレースが終了し、そのデータを trace.etl に保存することになります。早速 (3) のコマンドを実行してデータを見てみましょう。なお “インストールしよう” での説明通り、コマンド (1), (2) は、トレースデータを採取するためのコマンドですので Windows XP, Server 2003 でも実行できます。ただ、コマンド (3) は、ビューアーを起動するためのコマンド (xperf と入力しても実際に起動するのは xperfview.exe となります) ですので、Windows XP, Server 2003 では使用できません。

 

C:\Program Files\Microsoft Windows Performance Toolkit>xperf -on DiagEasy          ----- (1)

 

C:\Program Files\Microsoft Windows Performance Toolkit>xperf -d trace.etl          ----- (2)

Merged Etl: trace.etl

 

C:\Program Files\Microsoft Windows Performance Toolkit>xperf trace.etl             ----- (3)

 

C:\Program Files\Microsoft Windows Performance Toolkit>

 

以下のようなグラフが表示されたらバッチリです。

 

 

さて、グラフの各項目については、見て触ってなんとなくの感触をつかめると思いますので、トレース開始時に指定した “DiagEasy” について少々補足します。WPA は、ETW (Event Tracing for Windows) をベースに動作し、ETW と同様に Event Provider からイベント情報を取得することになります。Kernel のイベント情報も数多くあり、それらをキャプチャする際の最小単位を Kernel Flag と呼びます。プロセスやスレッドの情報、割込み、File I/ODisk I/O、電源管理などのイベント情報に分類されます。先に使用した DiagEasy とは、様々な用途に応じてこれら Kernel Flag をまとめたものであり、Kernel Group と呼ばれています。Kernel Flag, Kernel Group に関しては下記コマンドで確認することができます。赤字で示しているのが DiagEasy に関する Kernel Flag, Kernel Group の説明となります。

 

C:\Program Files\Microsoft Windows Performance Toolkit>xperf -providers k

Kernel Flags:

       PROC_THREAD    : Process and Thread create/delete

       LOADER         : Kernel and user mode Image Load/Unload events

       PROFILE        : CPU Sample profile

       CSWITCH        : Context Switch

       COMPACT_CSWITCH: Compact Context Switch

       DISPATCHER     : CPU Scheduler

       DPC            : DPC Events

       INTERRUPT      : Interrupt events

       SYSCALL        : System calls

       PRIORITY       : Priority change events

       ALPC           : Advanced Local Procedure Call

       PERF_COUNTER   : Process Perf Counters

       DISK_IO        : Disk I/O

       DISK_IO_INIT   : Disk I/O Initiation

       FILE_IO        : File system operation end times and results

       FILE_IO_INIT   : File system operation (create/open/close/read/write)

       HARD_FAULTS    : Hard Page Faults

       FILENAME       : FileName (e.g., FileName create/delete/rundown)

       SPLIT_IO       : Split I/O

       REGISTRY       : Registry tracing

       DRIVERS        : Driver events

       POWER          : Power management events

       NETWORKTRACE   : Network events (e.g., tcp/udp send/receive)

       VIRT_ALLOC     : Virtual allocation reserve and release

       MEMINFO        : Memory List Info

       ALL_FAULTS     : All page faults including hard, Copy on write, demand zero faults, etc.

 

Kernel Groups:

       Base           : PROC_THREAD+LOADER+DISK_IO+HARD_FAULTS+PROFILE+MEMINFO

       Diag           : PROC_THREAD+LOADER+DISK_IO+HARD_FAULTS+DPC+INTERRUPT+CSWITCH+PERF_COUNTER+COMPACT_CSWITCH

       DiagEasy       : PROC_THREAD+LOADER+DISK_IO+HARD_FAULTS+DPC+INTERRUPT+CSWITCH+PERF_COUNTER

       Latency        : PROC_THREAD+LOADER+DISK_IO+HARD_FAULTS+DPC+INTERRUPT+CSWITCH+PROFILE

       FileIO         : PROC_THREAD+LOADER+DISK_IO+HARD_FAULTS+FILE_IO+FILE_IO_INIT

       IOTrace        : PROC_THREAD+LOADER+DISK_IO+HARD_FAULTS+CSWITCH

       ResumeTrace    : PROC_THREAD+LOADER+DISK_IO+HARD_FAULTS+PROFILE+POWER

       SysProf        : PROC_THREAD+LOADER+PROFILE

       Network        : PROC_THREAD+LOADER+NETWORKTRACE

 

歩いてみよう

ETW WPA には Stack Walking (もしくは Stack Tracing) と呼ばれる機能があります。Stack Walking はトレース期間の Kernel イベントに対するコールスタック情報を網羅します。スタック情報と併せて各関数の処理にかかった時間を表示できますので、パフォーマンスの調査を行う際に、どのプロセスで、どのスレッドで、どの関数で処理に時間がかかっているのかを特定することができます。なおコールスタックを表示するためには、おなじみシンボルファイルが必要となります。

 

まずは、シンボルファイルを使用するためのシンボルパスを設定しましょう。WPA には、Windbg でいうところの .sympath コマンドはないので、環境変数でシンボルパスを設定することになります。例えば以下の通りです。

 

変数名: _NT_SYMBOL_PATH

変数値: srv*C:\SrvSymbols*http://msdl.microsoft.com/download/symbols

 

以下のコマンドを実行してデータを採取します。適当なタイミングでトレースを終了し、先ほどと同様にトレースデータをロードします。

 

C:\Program Files\Microsoft Windows Performance Toolkit>xperf -on Latency stackwalk Profile

 

C:\Program Files\Microsoft Windows Performance Toolkit>xperf -d stackwalk.etl

Merged Etl: stackwalk.etl

 

C:\Program Files\Microsoft Windows Performance Toolkit>xperf stackwalk.etl

 

C:\Program Files\Microsoft Windows Performance Toolkit>

 

 

[Trace] メニューの [Load Symbols]、または Window 内で右クリックメニューの [Load Symbols] をクリックします。Microsoft Internet Symbols Store というライセンス規約に関するダイアログ画面が表示されたら [YES] をクリックします。環境変数で設定したシンボルパスにシンボルファイルがロードされますので少々お待ちください。シンボルパスのフォルダに xxxxx.pdb というフォルダがポコポコ作成されると思います。

 

 

 

[CPU Sampling by CPU] のエリアにて、左クリックで範囲を設定し (全範囲は右クリックで [Select View] をクリック)、右クリックメニューの [Summary Table] をクリックします。

 

 

Selector tab をクリックして、Column Chooser を開きます。Process name, Process stack, Weight, %Weight にチェックします。

 

 

stack 列に表示される [Root] '+' をクリックしていくと順次コールスタックが展開されます。なお公開されているシンボルファイルは、パブリックなシンボルですので、全てのモジュール情報が含まれているわけではなく場合によっては表示されない関数もあります。

 

 

 

システム状態遷移時のトレースについて

パフォーマンスの検証では、システムの起動、シャットダウンにかかる時間やスリープ、休止状態からの復帰にかかる時間などが重要になってくると思います。Windows Vista Server 2008 環境では以下のコマンドを実行してデータを採取します。なおコマンド実行後に自動的に再起動、スリープ、休止状態に移行しますのでご注意ください。システム起動 or 復帰後、自動的にトレースデータが採取されます (Delaying for boot trace x of xダイアログ画面が表示されます。トレースデータのファイル名は、boot_xxxxx.etl などになります)

 

C:\Program Files\Microsoft Windows Performance Toolkit>xbootmgr trace boot stackwalk Profile

 

/*** 実行後に、-trace で指定されたオプション通りに状態遷移が行われます ***/

 

Trouble Shooting

どのような状況において WPA を使用すると効果的か、具体的な例を挙げて説明します。例として、外付け USB HDD を接続すると、デバイスの認識に時間がかかるという問題が発生したと仮定します (仮想的に問題を発生させたので、若干不自然な箇所があるかもしれませんがご容赦ください)。この問題に対して、デバイスを接続してからエクスプローラがデバイスを認識するまでの時間をトレースしてみました。

 

Disk I/O エリアを確認すると、どうやらデバイス接続時に Read Access が頻繁に起きているようです。

 

 

 

Read Access が頻繁に起きている期間を選択し、右クリックメニューの [Summary Table] をクリックします。Service Time から System プロセスの処理に時間を要していることがわかります。

 

 

 

次に Interrupt CPU Usage エリア上で、先ほどと同様の期間を選択し、右クリックメニューの [Summary Table] をクリックします。内容を確認すると、USB のハードウェア割り込みが多く発生しています。DPC CPU Usage についても同様の結果になっています。

 

 

 

ここから以下のような要因を推測することができます。

Ø  USB ハードウェア割り込みが発生しているので、PC USB 外付け HDD でなんか通信しているみたい

Ø  外付け USB HDD に対して Read アクセスが発生しているので、システム内の誰かが I/O Read 要求を出しているみたい

Ø  System プロセスの処理で時間がかかっているようなので、System プロセスが原因かも

 

ハードウェア割り込みや外付け USB HDD に対する Read は、デバイスの調査や USB のプロトコルアナライザーが必要になるのでここでは割愛します。残るは、システムの誰かが、I/O Read をしているか、System プロセスのパフォーマンスの問題のどちらかです。そこで、Stack Walking でどのスタックで時間が掛っているかがわかりますが、今回は仮想的に問題を発生させて不自然な状態になってしまったので、図解は割愛させてください。もし、同じような問題が発生したら試してみてください。

 

最後になりますが、アプリケーションやドライバでパフォーマンスを低下させる要因としては、同期/非同期処理の実装があります。適切に同期処理を実装しないと Race Condition につながり、適切に非同期処理を実装しないとパフォーマンス低下につながります。開発者にとっては永遠の課題です。このようなパフォーマンス問題は、切り分けとして、まずはシステム上で何が起きているのかを WPA から確認するのは如何でしょうか? WPA Kernel Event をグラフィカルに表示してくれるので、容易に全容を把握でき、一次次切り分けの検証工数を減らすことに役立つと思いますので、興味があったら試してみてください。

 

★★★★★ [2009/12/25] 追加情報 ★★★★★

MSDN サイト情報の更新に伴い補足情報を追記します。これまでの XPerf は単体でダウンロード可能でしたが、Windows 7 対応に伴い、SDK に含まれるようになりました。また、Windows XP Windows Server 2003 XPerf を使用するにあたり、上記記事でトレースデータの取得は可能と記載しましたが、カーネルの構造上 Stackwalk 機能を使用することはできませんのでご了承ください。前述を踏まえ、Windows XP での XPerf の使用例 (boot trace) を以下に追記します。参考になりましたら幸いです。

 

Windows Vista or later バージョンの OS で以下を実施します

1. 下記サイトから Microsoft Windows SDK for Windows 7 and .NET Framework 3.5 SP1 をダウンロード & インストールします

  Download Windows Performance Analysis

  http://msdn.microsoft.com/en-us/performance/cc752957.aspx

2. 下記 SDK インストールフォルダ Bin フォルダ上にある wpt_xxx.msi (xxx は各 architecture) をダブルクリックし、WPA(Windows Performance Analysis) をインストールします

  : C:\Program Files\Microsoft SDKs\Windows\v7.0\Bin

3. 下記 WPA インストールフォルダより xbootmgr.exeperfctrl.dll をコピーします

  : C:\Program Files\Microsoft Windows Performance Toolkit

 

Windows XP (Target PC) 上で以下を実施します

4. 任意の作業用フォルダを作成し、3 でコピーしたファイルを格納します

5. コマンドプロンプト上で以下のコマンドを実施します (自動的にシステムが再起動されます)

   xbootmgr.exe -trace boot

6. 再起動後、コマンドプロンプト上で以下のコマンドを実施します (etl ファイルが生成されます)

   xbootmgr.exe -remove

7. 4 の作業用フォルダに生成された etl ファイルをコピーします

 

Windows Vista or later バージョンの OS で以下を実施します

8. 7 でコピーした etl ファイルを任意の作業用フォルダに格納します

9. [スタート] -> [すべてのプログラム] -> [Microsoft Windows Performace Tool Kit] -> Performace Analyzer をクリックします

10. [File] -> [Open] をクリックし、対象 etl ファイルを選択します

 

ではまた。

 

 

Posted by jpwdkblg | (Comments Off)
Filed under: ,

プリンタ ドライバやスプーラ コンポーネントをデバッグする

お疲れ様です。A尾です。

前回は WDK に含まれるサンプルについて簡単にご案内させていただきました。今回は「とにかくまずはサンプルの動きを見てみたい!」という方のために、プリンタドライバやスプーラコンポーネントを WinDBG でデバッグする方法についてお話しようと思います。

 

■前準備

1.まずは、WDK を入手して、開発用 PC にインストールします。

2.そして、デバッグしたいサンプルをビルドし、テスト用 PC にインストールします。

      (サンプルによっては、インストールのためのプログラムが別途必要となる場合があります。)

3.あと、WinDBG についても入手し、テスト用 PC にインストールします。

 

これでとりあえずは準備完了です。それでは、実際にデバッグしていきましょう。

 

■スプーラ コンポーネント

ランゲージ モニタやポートモニタ、プリントプロセッサといったスプーラ コンポーネントについては、スプーラ サービス上でしか動作しないため、デバッグ自体は面倒ではありません。ただ、ポートモニタの UI DLL だけはエクスプローラ プロセスもしくはアプリケーション プロセスにて動作するので注意が必要です。

 

1.スプーラ サービスにデバッガをアタッチする。

1.1. WinDBG.exe [管理者として実行] で起動します。

1.2. [File] メニューから [Attach to a Process...] を選択します。

1.3. 現在起動しているプロセスの一覧が表示されるので、そこから spoolsv.exe を選択し OK ボタンを押します。

 

2.シンボル パスを設定する。

2.1. [File] メニューから [Symbol File Path...] を選択します。

2.2. ビルド時に生成されたシンボル ファイル (.pdb) のパスを指定し OK ボタンを押します。

 

3.ソース パスを設定する。

3.1. [File] メニューから [Source File Path...] を選択します。

3.2. ビルドしたサンプルのソース コードのパスを指定し、OK ボタンを押します。

 

これで基本的な設定は完了です。あとは必要に応じてブレイクポイントを設定したりして、デバッグすることが出来ます。

※ポート モニタの UI DLL については、手順 1.3 spoolsv.exe の代わりに explorer.exe もしくはそのアプリケーションプロセスを選択します。

 

■プリンタ ドライバ

プリンタ ドライバには、大きく分けてインタフェース DLL とグラフィックス DLL の二つがあります。どちらの DLLも、基本的には上記のスプーラ コンポーネントにてお話した方法でデバッグすることが可能ですが、どちらもちょっと厄介です。

インタフェース DLL についてですが、例えば DrvDevicePropertySheets については、デバイスプロパティに対しての操作が発生した際に呼び出されますが、プリンタフォルダからの操作の場合にはエクスプローラ プロセスから呼び出され、アプリケーションからの操作の場合にはそのアプリケーションプロセスから呼び出されます。また、DrvDocumentPropertySheets については、エクスプローラプロセス、アプリケーション プロセス以外にも、スプーラサービスから呼び出される場合もあります。

つまり、デバッグしたい DDI 関数にもよりますが、状況に応じて WinDBG をアタッチするプロセスを見極める必要があります。

 

グラフィックス DLL については、EMF スプーリングして印刷する場合にはスプーラ サービスから呼び出され、EMF スプーリングしないで印刷する場合にはアプリケーション プロセスから呼び出されます。EMF スプーリングする場合でもアプリケーション プロセスから呼ばれる DDI 関数もあります。(EMF スプーリングについてはまた説明します。)

このように、グラフィックス DLL についても、アタッチするプロセスを見極める必要があります。

 

なお、XPS プリンタ ドライバには XPS Filter Pipeline モジュールと呼ばれるフィルタモジュールを含めることができます。WDK サンプルとして SimplePipelineFilter XPSDrvSmpl を提供していますが、これらをデバッグするには、ちょっとコツが必要となってきます。

具体的には...XPS プリンタ ドライバにて印刷を行うと、PrintFilterPipelineSvc サービス (printfilterpipelinesvc.exe) が起動し、そこから Filter Pipeline モジュールが呼び出されることになりますが、このサービスは印刷時に起動し、印刷が完了すると一定時間経過後に終了してしまいます。そのため、スプーラサービスのように予めアタッチしておいてデバッグするのがかなり難しいのです。

ただ、このサービスは、印刷開始時に既に起動されている場合には新たに起動することはせず、既に起動しているサービスが引き続き動作します。そのため、サービス終了までの時間を長めに設定し、デバッグ開始前にダミーの印刷を行う (PrintFilterPipelineSvc サービスを起動させておく) ことで、PrintFilterPipelineSvc サービスにアタッチし、デバッグを行うことが出来るようになります。

サービス終了までの時間を変更するには、以下のレジストリキーを作成・変更します。(レジストリ操作を行う際はくれぐれも気をつけてください。)

 

キー : HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Print

: PipelineHostTimeout (REG_DWORD)

 

なお、ミリ秒単位で指定する必要がありますので、例えば 60 秒に設定したい場合には 10 進数で 60000 と入力します。

詳細については Debugging XPSDrv Printer Drivers にも記載されていますので、ご参考までにどうぞ。

それでは今回はこの辺で失礼します。

 

 

Posted by jpwdkblg | (Comments Off)
Filed under:

64ビットへのいざない

こんにちは、なおきお~です。

皆さんは、職場や自宅では、どのWindows OSを使用されていますでしょうか?

先日、知人から64ビットのWindows OSは、アプリケーションの互換性が心配だし、デバイス ドライバがあるかどうかわからないので、敷居が高いと言われました。

Windows Vistaのリリース直後に64ビットに移行してしまった私としては、既に気にならないのですが、移行するときは、アプリケーションの互換性やデバイス ドライバの有無は、少なからず心配になりましたので、知人の心配も尤だと思います。

 

デバイス ドライバを開発されている方の立場からすると、過去に開発したデバイス ドライバの互換性が気になると思いますし、最近では、Windows 7のリリースされるのが、気になるのではないかと思います。また、Windows 7だけでなく、Windows Server 2008 R2もリリースされると思います。

特に、Windows Server 2008 R2 は、32ビット版は提供されず、64ビット版のみになり、サーバーの Windows OS は、完全に64ビットになります。

対して、ノートPCもデスクトップPCも、4GB以上のメモリを搭載PCが増えてきて、クライアント側も、ひしひしと64ビット化を感じます。

 

ユーザ モードのアプリケーションは、WOW64 (Windows 32-bit on Windows 64-bit ) という機能のおかげで、32ビットでも動作します。

しかしながら、デバイス ドライバは、64ビット版のWindows OS では、ユーザ モードやカーネル モードに関わらず、64ビットである必要があります。

 

64ビット化が近づきながらも、32ビット版のWindows OS も、まだまだ現役という現状は、32ビットと64ビットのデバイス ドライバを開発する必要があると思います。

2つもデバイス ドライバを開発しなければいけないのか!と思われるかもしれませんが、開発自体は、そんなに大変ではありません。

何故ならば、ほぼソース コードレベルで互換が可能であるということです。つまり、x86x64ia64 それぞれのBuild Environmentbuildすれば、ほとんど終了してしまうのです。

 

しかし、ソース コード レベルで互換が可能ということは、過去に開発した全ての32ビットのデバイス ドライバに対して、ソース コード レベルで互換性を保証しているわけではありません。意識して、コーディングすれば、ソース コード レベルの互換が可能ということです。また、100%のソース コードの互換ではなく、若干 考慮しなければいけないところもあります。

とはいっても、ソース コードの互換が可能なぐらいの差異なので、過去に開発した32ビットのデバイス ドライバも比較的 容易に移行できるのではないかと思います。

 

まず、よく使用するデータ型は、このようになっており、ポインター型は、全て64ビット長になります。

データ型

ビット数

LONG, INT

32 ビット符号付き

ULONG,UINT,DWORD

32 ビット符号なし

LONG32, INT32

32 ビット符号付き

LONG64, INT64

64 ビット符号付き

ULONG32,UINT32,DWORD32

32 ビット符号なし

ULONG64,UINT64,DWORD64

64 ビット符号なし

 

データ型で、よくある問題として、-10xFFFFFFFFとコーディングしたり、0x80000000以上のアドレスは、カーネル アドレスと判定するなど、32ビット長に依存しているコーディングです。

こういったのは、-1にするなど、ビット長に依存しないようにコーディングするか、ヘッダ ファイルに定数を定義するなどの工夫が必要になります。

また、定数を定義する場合に、_WIN64_IA64__AMD64_ を使用すると、Build Environmentで適切に定義してくれるので便利だと思います。

 

なお、このようなコーディングは、デバイス ドライバのみならず、ユーザ アプリケーションでも必要な一般的な考慮点で、ユーザ モードのデバイス ドライバは、このような一般的な考慮点のみで、ほぼ64ビットに移行できると思います。

強いて言えば、プリンタ ドライバの場合、32ビットのユーザ アプリケーションから呼び出される場合、SPLWOW64.EXE経由で呼び出されるため、プロセス空間が、ユーザ アプリケーションではない点です。ただ、通常 プリンタ ドライバは、動作するプロセス空間を認識する必要がないので、問題にならないと思いますが、もし、何らかの事情で、プロセスを意識しているコードがあったとしたら、変更が必要かもしれません。

 

対してまして、カーネル モードのデバイス ドライバの代表的な考慮点は、32ビットのユーザ アプリケーションから、DeviceIoControl()が呼ばれる場合の実装だと思います。

DeviceIoControl()で指定するInputBufferOutputBufferの構造体は、IOCTLに依存します。IOCTLが、デバイス ドライバが管理していると同様に、InputBufferOutputBufferの構造体も管理する必要があります。そのため、32ビットのユーザ アプリケーションから、DeviceIoControl()が呼ばれたら、32ビット用の構造体に変更する必要があります。

WDKのサンプル コード(%BASEDIR%\src\ src\storage\class\classpnp\class.c)にわかりやすい例があるので、そのコードを抜粋してみます。

 

ClassDeviceControl()という関数で、IOCTL_SCSI_PASS_THROUGHIOCTL_SCSI_PASS_THROUGH_DIRECTというIOCTLのハンドリングをしています。

_WIN64 の場合のみ、32ビットのプロセスから呼ばれたかどうかをIoIs32bitProcess()という関数で確認しています。もし、32ビットのプロセスから呼ばれたのであれば、SCSI_PASS_THROUGH32という構造体でサイズチェックをしています。

---------- 抜粋 ----------

        #if defined (_WIN64)

            if (IoIs32bitProcess(Irp)) {

                if (irpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(SCSI_PASS_THROUGH32)){

                    Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;

                    ClassReleaseRemoveLock(DeviceObject, Irp);

                    ClassCompleteRequest(DeviceObject, Irp, IO_NO_INCREMENT);

                    status = STATUS_INVALID_PARAMETER;

                    goto SetStatusAndReturn;

                }

            }

            else

        #endif

            {

                if (irpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(SCSI_PASS_THROUGH)) {

                    Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;

                    ClassReleaseRemoveLock(DeviceObject, Irp);

                    ClassCompleteRequest(DeviceObject, Irp, IO_NO_INCREMENT);

                    status = STATUS_INVALID_PARAMETER;

                    goto SetStatusAndReturn;

                }

            }

---------- 抜粋 ----------

 

build するだけで、終了すると書きましたが、実際に本格的な64ビット化する場合は、ソース コードをちょっと変更してre-build するだけでなく、テストをしたり、ドライバ署名をしたりと色々と必要になるので、軽い気持ちで、64ビット化することはできないと思いますが、将来的な64ビット化に備えて、過去に開発したデバイス ドライバや現在 開発しているデバイス ドライバを64ビットのBuild Environmentre-buildしてみたり、ソース コードを調整してみたり、少しずつ準備をされるとよいと思います。

 

なお、細かなチェックリストは、WHDC のサイトに公開されているので、本格的な移行際には、このチェックリストを活用していただくのがいいと思います。

 

64 ビット Microsoft Windows ドライバー用のチェックリスト

http://www.microsoft.com/japan/whdc/driver/kernel/64bit_chklist.mspx

 

ちなみに、64ビットのDumpファイルの調査は、少々厄介かもしれません。なにせ、引数がレジスタになってしまったので、32ビットのようにお気軽に引数を確認することができません。ETWトレースなど、他のトラブルシューティングの方法を充実させなければいけないかもしれません。

トラブルシューティングについては、いずれ紹介したいと思います。

 

それでは、また~

 

Posted by jpwdkblg | (Comments Off)
Filed under:

ファイル I/O の API とフィルタドライバのふかーい関係

こんばんは。cleng です。

前回 5/13 のポストから、約一ヶ月間が経ち、この一ヶ月間の間、いくつかの出来事があって、皆さんに紹介したいと思います。また前回のポストでは、次回はミニフィルタの話をすると予告しましたが、フィルタドライバの話をする前に、ファイル I/O の API の話を少しお話したほうがいいかもしれないと、思うようになりました。ミニフィルタの話は、また今度ということで、ご勘弁ください。

まず、コンサートの話です。マイクロソフトには社員が有志で作った管弦楽団があり、毎年1回ファミリーコンサートを開催しています。開催時期は大体 5 月です。コンサートのチケットは、開催日より約 1ヶ月前から無料配布していますので、ご興味のある方は来年 4 月になったら http://msjso.org を覗いてみてください。そして、今年のコンサートでは、WDK チームのさなえすさんが合唱団の一員として華麗なるデビューを果たしました!!もちろん当日コンサート会場に駆けつけましたが、合唱団は舞台の一番後ろに立たされ、しかも皆さん同じ服装をしていたので、残念ながら、どれがさなえすさんなのかは全く分かりませんでした。でも、きっと得意の語学力を存分に生かし、「乾杯の歌」、「第九」などをイタリア語、ドイツ語で歌っていたに違いないと思います。

次に、先週ある加工機のメーカ様のところにお邪魔しました。そこで、高精度・高剛性の頂点に立つ巨大な加工機を見せてもらい、普段携わっているコンピュータソフトウェアと全く別の世界に存在する「ものづくり」の美しさに魅了されました。特に印象深いのは、加工済みサンプルの中にある一枚の鏡でした。その鏡は、なんと、このメーカ様の加工機の精密な動きにより、金属の塊から削りだしたものです。鏡であるゆえに、少しでもゆがみなどがあればすぐに「ばれて」しまいますが、その鏡は完璧なものでした。その鏡の前で感嘆しつつ、Windowsがこんなところでも役に立っていることをとても誇りに思いました。

さて、本題のファイル I/O の API に入ります。今日お話したいテーマは2つあり、メモリマップドファイル非同期処理です。

--------------------------------
メモリマップドファイル
--------------------------------
ファイルデータをリードする場合、以下の2つの方法があります。

1. ReadFile方式
CreateFile -> ReadFile/ReadFileEx -> CloseHandle

2. メモリマップドファイル方式
A. CreateFile -> CreateFileMapping -> MapViewOfFile/MapViewOfFileEx を使って、ディスク上にあるファイルを仮想メモリにマッピングする
B. MapViewOfFile/MapViewOfFileEx から返されるアドレスに対して、普通のメモリアクセスを行う
C. リードが終わったら、UnmapViewOfFile -> CloseHandle(マッピングハンドルのクローズ) -> CloseHandle (ファイルハンドルのクローズ) を行う

アプリケーションレベルではこの2つの方法のどれでも、ファイルデータのリードが簡単にできて、違いは呼出し手順だけですが、ファイルシステムフィルタドライバにとっては、この2つの方法は天と地の違いがあります。

ReadFile 方式の場合、アプリケーションがReadFileを呼び出す時点で、フィルタドライバにFastI/O か、IRP_MJ_READ のキャッシュI/O リクエストがディスパッチされますが、メモリマップドファイル方式の場合、この2種類のキャッシュI/Oリクエストのどれもがフィルタドライバにディスパッチされません。なぜなら、アプリケーションがファイルデータのマッピングされているメモリに直接アクセスしているだけです。

幸いなことに、ファイルシステムフィルタドライバにとって、この2つの方式に共通するところがあります。どの方式においても、データを得るのにディスク上にあるファイルからデータを読み込む必要があるので、このディスクからファイルを読み込むリクエストは、共通項になります。このようなリクエストは、ページングI/Oとも呼ばれています。

この2つのファイルアクセスの方式が一因となり、ファイルシステムフィルタドライバではキャッシュI/Oリクエストではなく、ページングI/O(とノンキャッシュI/O)をフィルタリングするのは一般的なつくりとなっています。

メモリマップドファイル方式をあまり馴染んでいない方もいると思いますが、Windowsのメモ帳(Notepad.exe)がこの方式を使用してファイルのリード・ライトを行っています。「自作のフィルタドライバで、普通のエディタで問題なく動きますが、メモ帳だとうまく行かない」と言う類の問題に遭遇したら、フィルタドライバのどこかがメモリマップドファイル方式にうまく対応できていない可能性が高いと思っていただければと思います。

メモリマップドファイルのユーザモードAPIについて、以下のMSDNドキュメントをご参照ください。
http://msdn.microsoft.com/en-us/library/aa366556.aspx

-----------------
非同期処理
-----------------
ここで言う非同期処理は、アプリケーションが I/O リクエストを発行し、その I/O リクエストの完了を待たずに他の処理を行うことを指します。

非同期処理について、すぐにぴんと来ない方がいるかもしれませんが、分かりやすい例で言いますと、宅配ピザのお店に電話でピザを注文し、その後、ピザが届くまでの約 30 分間、玄関の外でじっと待つのではなく、Xbox でゲームをやったり、Windows 7 の RC 版をインストールしたり、Bing.com で検索したりして、待機時間を有効に使うのは、一種の非同期処理と言えます。

ピザの注文の例と同じ理由ですが、アプリケーションレベルで非同期的 API をうまく使うことによって、アプリケーションの操作性とパフォーマンスを向上させることが可能です。例えば、三つの異なる物理ディスク上にあるファイルに対して、非同期的 ReadFile を 3 回呼び出し、WaitForMultipleObjects 関数で 3つの I/O の結果を待つほうが、ReadFile を呼び出したつど結果待ちを行うことよりは、パフォーマンスが遥かにいいはずです。

この非同期処理の仕組みの根幹にあるのは、カーネルモードドライバの STATUS_PENDING に関わる処理です。ドライバで時間のかかる IPR を処理する際に、ディスパッチルーチンでその IRP をキューイングして、STATUS_PENDING を返すようにしますと、制御が I/O 発行元のアプリケーションに戻り、非同期処理が可能になります。

しかし、もしそのドライバの上にフィルタドライバがあり、そのフィルタドライバではこの非同期処理のルールを無視して、STATUS_PENDING のステータスに対してIRP が完了されるまで待つように実装されていますと、アプリケーションのつくりがどんなに優れても、非同期処理ができなくなってしまいます。

あるハードウェアのデバイスドライバでこの問題が起きても影響範囲がそんなに広くないかもしれませんが、ファイルシステムフィルタドライバでこのような間違った実装が行われますと、ただ1つのフィルタドライバによってシステム全体のパフォーマンスが大きく低下する事態となります。

また、IRP の種類にも依存しますが、パフォーマンスの低下だけではなく、システムがハングアップしてしまうことも考えられます。例えば、 IRP_MJ_DIRECTORY_CONTROL / IRP_MN_NOTIFY_CHANGE_DIRECTORY の IRP に対して、ファイルシステムがその IRP をキューイングしてから、 STATUS_PENDINGを返します。ファイルシステムの上位にあるフィルタドライバが、もしこのSTATUS_PENDINGに対して、完了待ちを行いますと、OSのシャットダウンまでこのスレッドがフィルタドライバの中でブロックされてしまう可能性があります。理由は、IRP_MN_NOTIFY_CHANGE_DIRECTORY の IRP は、ターゲットとなるディレクトリに変化が起きないと、完了されないからです。

STATUS_PENDINGに対して完了待ちを行うのは、それなりの理由があると思います。例えば、ドライバの完了ルーチンが DISPATCH_LEVEL で呼ばれる可能性があるので、呼び出してはいけない関数が存在します。だから、ディスパッチルーチンで完了待ちを行えば、PASSIVE_LEVEL になりますので、どんな関数を呼んでも問題ない、という考え方です。しかし、フィルタドライバの処理が簡単になるからと言って、I/O の非同期処理の通り道を塞ぐのが、良いデザインとは言えません。ファイルシステムフィルタドライバは、他のドライバ以上に、システム全体のパフォーマンスに影響を与えますので、デザインを慎重に検討していただきたいと思います。

ここまで書いて、よく考えてみたら、結局言いたかったのは、いつ来るかは分からないピザを足が棒になるまで外でじっと待つことのないように、ファイルシステムフィルタドライバが STATUS_PENDING のステータスをそのまま返すべきことですね。

それでは、皆さん、楽しくファイルシステムフィルタドライバを作りましょう!

フニクリ・フニクラ♪

 

Posted by jpwdkblg | (Comments Off)
Filed under:

DevCon と SetupDi API ~ DevCon の使い方編 ~

久方ぶりです。まさかたです。

 

前回の「USBView の中身を見てみる」の記事の中で USBView のお話を書かせていただいた時に、SetupDi という API について、少しだけ触れさせていただきました。

この API は、ドライバに縁の深いものであるという風に、簡単にしかご紹介しませんでしたので、この SetupDi API について、もう少し詳しくお話したいなと思っています。

 

と、その前に、みなさんは、WDK に含まれている DevCon というツールについて、ご存知でしょうか?

このツールは、システム上のデバイスドライバの情報を取得・表示したり、さらには、新規にデバイスをインストールしたり、既にインストールされているデバイスドライバの設定を変更したり、削除することもできるという、Device Manager 並に豊富な機能を持つコマンドライン ツールです。

 

-      DevCon

http://msdn.microsoft.com/en-us/library/ms792824.aspx

 

このツール、WDK の中の以下のパスに、バイナリとして含まれているものの他に、そのサンプルコードも公開されています。

 

-      バイナリ : WINDDK\6001.18002\Tools\devcon

-      サンプルコード : WINDDK\6001.18002\src\setup\devcon

 

そして、その中身を覗いていただければお分かりになるかと思いますが、DevCon はさまざまな SetupDi API を駆使して、その豊富な機能を実現しています。

ですので、SetupDi API のことを知ろうとするなら、このサンプルはとても参考になると思います。

 

前回の記事で、SetupDi API は、システム上の USB ホスト コントローラ デバイスを列挙するために使われていると書きましたが、この API の主な用途は、その名前の通り、そういったデバイスの列挙や情報の取得するための他に、デバイスやドライバのインストールを行うために使われるものです。

具体的にどんな API があるかについては、以下の技術情報を見ていただければと思いますが、たくさんの種類があります。

 

-      Using Device Installation Functions

http://msdn.microsoft.com/en-us/library/ms791137.aspx

 

これを一つ一つ見て、覚えて使いこなすというのも手ですが、まずは DevCon を入り口として、どんなことができるのかを具体的に見ながら、その使い方を知っていくのもいいのではないかと思います。

というわけで、少々前置きが長くなりましたが、今回は DevCon そのものについて簡単にご紹介したいと思います。

 

DevCon の使い方

それでは、DevCon のサンプルの中身に入って行く前に、どんなツールなのか、その使い方を見ていきたいと思います。

(今回は、Windows Vista x86 の環境を前提としています。)

まずは、コマンドプロンプトを開いて、DevCon help オプションを打ち込んでみましょう。

c:\WINDDK\6001.18002\Tools\Devcon\i386>devcon help

Device Console Help:

devcon [-r] [-m:\\<machine>] <command> [<arg>...]

-r           Reboots the system only when a restart or reboot is required.

<machine>    Specifies a remote computer.

<command>    Specifies a Devcon command (see command list below).

<arg>...     One or more arguments that modify a command.

For help with a specific command, type: devcon help <command>

classfilter          Add, delete, and reorder class filters.

 

classes              List all device setup classes.

 

disable              Disable devices.

 

driverfiles          List installed driver files for devices.

 

drivernodes          List driver nodes of devices.

 

enable               Enable devices.

 

find                 Find devices.

 

findall              Find devices, including those that are not currently attached.

 

help                 Display Devcon help.

 

hwids                List hardware IDs of devices.

 

install              Install a device manually.

 

listclass            List all devices in a setup class.

 

reboot               Reboot the local computer.

 

remove               Remove devices.

 

rescan               Scan for new hardware.

 

resources            List hardware resources for devices.

 

restart              Restart devices.

 

sethwid              Modify Hardware ID's of listed root-enumerated devices.

 

stack                List expected driver stack for devices.

 

status               List running status of devices.

 

update               Update a device manually.

 

updateni             Manually update a device (non interactive).

 

dp_add               Adds (installs) a third-party (OEM) driver package.

 

dp_delete            Deletes a third-party (OEM) driver package.

 

dp_enum              Lists the third-party (OEM) driver packages installed on this machine.

たくさんのオプションがありますね!

とは言え、これら DevCon が持っている各オプションの機能は、大別すると主に以下の 3つになります。

 

1.    デバイスおよびドライバの情報の取得と表示

2.    デバイスおよびドライバの検索

3.    デバイスおよびドライバの設定を変更

 

それぞれのコマンドでは、ターゲットとなるデバイスの指定方法や、検索条件を指定する必要がありますが、その指定の仕方は、主に以下の 2つ の方法があります。

 

     デバイスの Hardware ID, Compatible ID, Device Instance ID そのもの、もしくはそのパターンで指定

     デバイスが属する Setup Class 名で指定

 

以下のヘルプ等をご覧いただければ、それぞれのコマンドがどんなことをするのかも分かりますが、せっかくなので、以下で、簡単な一覧にまとめてみました。

-      Commands for DevCon Operations

http://msdn.microsoft.com/en-us/library/ms792835.aspx

 

Ø  デバイスおよびドライバの情報の取得と表示

オプション

説明

ターゲットの指定方法

HwIDs

指定したデバイスの Hardware ID を列挙

or

Classes

システムに存在する Setup Class を列挙

N/A

ListClass

指定した Setup Class に属するデバイスを列挙

DriverFiles

指定したデバイスのドライバファイルを列挙

or

DriverNodes

指定したドライバパッケージの情報を列挙

or

Resources

指定したデバイスが使用しているリソースを列挙

or

Stack

指定したデバイスのスタック(Upper FilterLower Filter)を表示

or

Status

指定したデバイスの状態(動作中、停止中、無効)を表示

or

Dp_enum

システムにインストールされている OEM*.inf のドライバパッケージを列挙

N/A

 

Ø  デバイスおよびドライバの検索

オプション

説明

ターゲットの指定方法

Find

指定した条件に合致するデバイスの情報を表示

現在接続されているデバイスだけを表示

or

FindAll

一度インストールされたが、現在は接続されていないデバイスも表示する

or

 

Ø  デバイスおよびドライバの設定を変更

オプション

説明

ターゲットの指定方法

Enable

指定したデバイスを有効にする

or

Disable

指定したデバイスを無効にする

or

Update

指定した HardwareID のデバイスのドライバを、指定した INF のドライバに更新

Hardware ID

UpdateNI

Update オプションを、ユーザーインターフェースを表示しないで実行

Hardware ID

Install

指定したプラグアンドプレイデバイスをインストール

-      INF (フル)パス

-      Hardware ID

Remove

指定したデバイスをデバイスツリーから削除

ただし、ドライバは削除されない。

or

Rescan

デバイスリストの情報を再スキャンし、最新の情報に更新し、新しいデバイスを検出(管理者権限が必要)

N/A

Restart

指定したデバイスをリスタート

or

Reboot

OS を再起動

N/A

SetHwID

指定したデバイスのHardware ID のリストを変更

or

ClassFilter

指定した Setup Class のフィルタドライバの設定を変更

Dp_add

指定した Driver Package Driver Store にコピー

INF (フル)パス

Dp_delete

指定した Driver Package Driver Store から削除

INF (フル)パス

 

Toaster で実験

百聞は一見に如かずということで、例として WDK のサンプルの Toaster ドライバをインストールした環境で、DevCon をいろいろ動かしてみることにします。

-       Toaster

http://msdn.microsoft.com/en-us/library/dd163450.aspx

 

Toaster を動かすためには、Toaster のバスドライバ(BusEnum.sys)をインストールしなければなりません。

これは、当然 Device Manager からインストールすることもできますが、実は以下のように DevCon Install オプションを使って行うこともできます。

c:\WINDDK\6001.18002\Tools\Devcon\i386>devcon install C:\WINDDK\6001.18002\src\general\toaster\

inf\i386\bus.inf "root\busenum"

Device node created. Install is complete when drivers are installed...

Updating drivers for root\busenum from C:\WINDDK\6001.18002\src\general\toaster\inf\i386\bus.inf.

Drivers installed successfully.

 

その後、Toaster のインスタンスをプラグインしてインストールしておきますが、今回は、Toaster のインスタンスを 3 入れてみました。

 5 Toaster Instances

それでは、手始めにシステムに Toaster Setup Classs が組み込まれているかを、Classes オプションでチェックします。

c:\WINDDK\6001.18002\Tools\Devcon\i386>devcon classes

Listing 55 setup classes.

WCEUSBS             :

USB                 :

Media Center Extender: Media Center Extender

PnpPrinters         : IEEE 1394  SCSI

Dot4                : IEEE 1284.4

Dot4Print           : IEEE 1284.4

CDROM               : DVD/CD-ROM

Computer            :

DiskDrive           :

Display             :

fdc                 :

hdc                 : IDE ATA/ATAPI

Keyboard            :

MEDIA               :

Modem               :

Monitor             :

Mouse               :

MTD                 :

MultiFunction       :

Net                 :

NetClient           :

NetService          :

NetTrans            :

PCMCIA              : PCMCIA

Ports               :  (COM  LPT)

Printer             :

SCSIAdapter         :

System              :

Unknown             :

FloppyDisk          :

Processor           :

MultiPortSerial     :

Memory              :

SmartCardReader     :

VolumeSnapshot      :

1394                : 1394

Infrared            :

Image               :

TapeDrive           :

Volume              :

Battery             :

HIDClass            :

61883               : 61883

LegacyDriver        :

SideShow            : Windows SideShow

SDHost              : SD

TOASTER             : Toaster

Transfer Cable      :

AVC                 : AVC

MediumChanger       :

SBP2                : SBP2 IEEE 1394

XnaComposite        : Windows  Microsoft

SecurityDevices     :

Bluetooth           : Bluetooth

WPD                 :

確かに Toaster クラスが存在します。

では、この Toaster クラスに属するデバイスを、ListClass オプションで列挙してみます。

c:\WINDDK\6001.18002\Tools\Devcon\i386>devcon listclass toaster

Listing 3 devices in setup class "TOASTER" (Toaster).

{B85B7C50-6A01-11D2-B841-00C04FAD5171}\MSTOASTER\1&1AAFB3D5&0&01: ToasterDevice01

{B85B7C50-6A01-11D2-B841-00C04FAD5171}\MSTOASTER\1&1AAFB3D5&0&02: ToasterDevice02

{B85B7C50-6A01-11D2-B841-00C04FAD5171}\MSTOASTER\1&1AAFB3D5&0&03: ToasterDevice03

確かに、該当するデバイスとして、ToasterDevice01 03 が見つかりました。

 

続いて、検索機能として、Find オプションと Findall オプションという 2つ のオプションがありますので、この違いを見てみたいと思います。

ここで、結果に差をつけるために、ToasterDevice03 だけを Unplug しておきました。

c:\WINDDK\6001.18002\Tools\Devcon\i386>devcon find *toaster*

{B85B7C50-6A01-11D2-B841-00C04FAD5171}\MSTOASTER\1&1AAFB3D5&0&01: ToasterDevice01

{B85B7C50-6A01-11D2-B841-00C04FAD5171}\MSTOASTER\1&1AAFB3D5&0&02: ToasterDevice02

2 matching device(s) found.

 

c:\WINDDK\6001.18002\Tools\Devcon\i386>devcon findall *toaster*

{B85B7C50-6A01-11D2-B841-00C04FAD5171}\MSTOASTER\1&1AAFB3D5&0&01: ToasterDevice01

{B85B7C50-6A01-11D2-B841-00C04FAD5171}\MSTOASTER\1&1AAFB3D5&0&02: ToasterDevice02

{B85B7C50-6A01-11D2-B841-00C04FAD5171}\MSTOASTER\1&1AAFB3D5&0&03: ToasterDevice03

3 matching device(s) found.

すると、Find オプションでは出てこない ToasterDevice03 が、Findall オプションだとちゃんと出てきました。

 

では、次に、Update オプションを使ってドライバを更新して、クラスドライバ、ファンクションドライバにそれぞれ Upper Lower のフィルタドライバ4つも入れてみます。

-      Class upper filter : Clsupper.sys

-      Class lower filter : Clslower.sys

-      Device upper filter : Devupper.sys

-      Device lower filter : Devlower.sys

 

と、その前に、Update コマンドで必要となる Toaster Hardware ID HwIds オプションで調べておきます。

c:\WINDDK\6001.18002\Tools\Devcon\i386>devcon hwids =toaster

{B85B7C50-6A01-11D2-B841-00C04FAD5171}\MSTOASTER\1&79F5D87&0&01

    Name: ToasterDevice01

    Hardware IDs:

        {B85B7C50-6A01-11d2-B841-00C04FAD5171}\MsToaster

    Compatible IDs:

        {B85B7C50-6A01-11d2-B841-00C04FAD5171}\MsCompatibleToaster

{B85B7C50-6A01-11D2-B841-00C04FAD5171}\MSTOASTER\1&79F5D87&0&02

    Name: ToasterDevice02

    Hardware IDs:

        {B85B7C50-6A01-11d2-B841-00C04FAD5171}\MsToaster

    Compatible IDs:

        {B85B7C50-6A01-11d2-B841-00C04FAD5171}\MsCompatibleToaster

{B85B7C50-6A01-11D2-B841-00C04FAD5171}\MSTOASTER\1&79F5D87&0&03

    Name: ToasterDevice03

    Hardware IDs:

        {B85B7C50-6A01-11d2-B841-00C04FAD5171}\MsToaster

    Compatible IDs:

        {B85B7C50-6A01-11d2-B841-00C04FAD5171}\MsCompatibleToaster

3 matching device(s) found.

INF を見ても分かることではありますが、Hardwere ID は、”{B85B7C50-6A01-11d2-B841-00C04FAD5171}\MsToaster” になります。

 

それでは、Update コマンドで、toasterf.inf を使ってドライバをアップデートして、フィルタドライバをインストールします。

c:\WINDDK\6001.18002\Tools\Devcon\i386>devcon update c:\Workspace\toaster_pkg\toasterf.inf {b85b7c50-6a01-11d2-b841-

00c04fad5171}\MsToaster

Updating drivers for {b85b7c50-6a01-11d2-b841-00c04fad5171}\MsToaster from

 c:\Workspace\toaster_pkg\toasterf.inf.

Drivers installed successfully.

 

ここで Stack オプションを使えば、ファンクションドライバの Upper Lower のフィルタドライバとして、何がインストールされているかが分かります。

c:\WINDDK\6001.18002\Tools\Devcon\i386>devcon stack *toaster*

{B85B7C50-6A01-11D2-B841-00C04FAD5171}\MSTOASTER\1&79F5D87&0&01

    Name: ToasterDevice01

    Setup Class: {b85b7c50-6a01-11d2-b841-00c04fad5171} TOASTER

    Upper filters:

        devupper

    Controlling service:

        toaster

    Lower filters:

        devlower

{B85B7C50-6A01-11D2-B841-00C04FAD5171}\MSTOASTER\1&79F5D87&0&02

    Name: ToasterDevice02

    Setup Class: {b85b7c50-6a01-11d2-b841-00c04fad5171} TOASTER

    Upper filters:

        devupper

    Controlling service:

        toaster

    Lower filters:

        devlower

{B85B7C50-6A01-11D2-B841-00C04FAD5171}\MSTOASTER\1&79F5D87&0&03

    Name: ToasterDevice03

    Setup Class: {b85b7c50-6a01-11d2-b841-00c04fad5171} TOASTER

    Upper filters:

        devupper

    Controlling service:

        toaster

    Lower filters:

        devlower

3 matching device(s) found.

 

さて、次は、DriverFiles と、DriverNodes オプションで、ドライバが使っているファイルの情報を取得してみましょう。

まずは、DriverFiles オプションの場合です。

c:\WINDDK\6001.18002\Tools\Devcon\i386>devcon driverfiles =toaster

{B85B7C50-6A01-11D2-B841-00C04FAD5171}\MSTOASTER\1&1AAFB3D5&0&01

    Name: ToasterDevice01

    Driver installed from C:\Windows\INF\oem6.inf [Toaster_Device]. 5 file(s) used by driver:

        C:\Windows\system32\DRIVERS\toaster.sys

        C:\Windows\system32\DRIVERS\Devupper.sys

        C:\Windows\system32\DRIVERS\Devlower.sys

        C:\Windows\system32\DRIVERS\clsupper.sys

        C:\Windows\system32\DRIVERS\clslower.sys

(中略)

3 matching device(s) found.

長いので間の出力は省略しましたが、その間には、ToasterDevice02 03 について、同じ情報が列挙されます。

先ほどのドライバの更新により、Toaster のデバイスドライバと、クラスドライバの両方に、Upper Lower のフィルタをインストールされているので、デバイスドライバである toaster.sys の他に、ファンクションドライバに対するフィルタドライバとして、Devupper.sysDevlower.syが、クラスのフィルタドライバとして、clsupper.sysclslower.sys が使われているのが分かります。

 

次に、DriverNodes オプションの場合です。今度は、デバイスを指定するのに、Hardware ID のパターンを使ってみました。

c:\WINDDK\6001.18002\Tools\Devcon\i386>devcon drivernodes *toaster*

{B85B7C50-6A01-11D2-B841-00C04FAD5171}\MSTOASTER\1&1AAFB3D5&0&01

    Name: ToasterDevice01

Driver node #0:

    Inf file is C:\Windows\INF\oem6.inf

    Inf section is Toaster_Device

    Driver description is Microsoft Toaster with class and device filters

    Manufacturer name is (Standard system devices)

    Provider name is Microsoft

    Driver date is 2006/09/21

    Driver version is 6.0.5736.1

    Driver node rank is 2164195328

    Driver node flags are 00040040

Driver node #1:

    Inf file is C:\Windows\INF\oem7.inf

    Inf section is Toaster_Device

    Driver description is Microsoft Toaster With Coinstaller

    Manufacturer name is (Standard system devices)

    Provider name is Microsoft

    Driver date is 2006/09/21

    Driver version is 6.0.5736.1

    Driver node rank is 2164195328

    Driver node flags are 00000040

(中略)

3 matching device(s) found.

Manufacturer や、ProviderDriver Date Version など、INF に記述されている情報も取得できます。

SetupDi API を使えば、このような情報も取得することができるわけです。

 

以上のように、DevCon を使えば、通常なら Device Manager を使って行うような操作も、コマンドラインから行うことができるわけです。

さらに、DevCon をコマンドとして使った Script を組んで、Device Manager のような UI を使わずに、デバイスの設定を操作することができます。

 

ちなみに、DevCon は、WDK をインストールしなくても、以下のサポート オンラインのページから、既にビルド済みのバイナリをダウンロードすることもできます。

すぐに試してみたい方は、こちらも一緒にご覧いただければと思います。

 

-      デバイスマネージャとして機能する DevCon コマンド ライン ユーティリティ

http://support.microsoft.com/kb/311272/ja

 

というわけで、今回は、SetupDi API の説明をする前に、SetupDi API の使い方の参考となりそうな DevCon とその使い方をご紹介をさせていただきました。

また別の機会に、DevCon のサンプルコードを見ながら、DevCon では SetupDi API をどのように使って、上記のような機能を実現しているのかについてお話したいと思います。

 

それでは

Posted by jpwdkblg | (Comments Off)
Filed under: ,
More Posts Next page »
 
Page view tracker