Welcome to MSDN Blogs Sign in | Join | Help

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) をご紹介します。

 

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 をグラフィカルに表示してくれるので、容易に全容を把握でき、一次次切り分けの検証工数を減らすことに役立つと思いますので、興味があったら試してみてください。

 

ではまた。

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

何故ならば、ほぼソース