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

お疲れ様です。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 にも記載されていますので、ご参考までにどうぞ。

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