サンプル コードから実稼働ドライバーへ - サンプルでの必要な変更

このトピックでは、サンプル コードに基づいたデバイス ドライバーをリリースする前に、WDK サンプル ドライバーに加える必要がある重要な変更について説明します。

ここで説明する変更に加えて、すべてのドライバーで、「信頼性の高いカーネルモード ドライバーの作成」と「Surface Team ドライバー開発ベスト プラクティス」で説明されているベスト プラクティスを利用する必要があります。 また、すべてのドライバーが、「ドライバーのセキュリティ ガイダンス」に示されているガイドラインを遵守する必要があります。

WDK ドライバーのサンプル - 一意識別子

Windows Driver Kit (WDK) には、ドライバー開発に役立つ手法を示すさまざまなサンプル ドライバーが含まれています。 これらのサンプルは独自のドライバーの基礎として使用できますが、ドライバーをリリースする前に、独自のデバイスとドライバーに一意に適用するために (明らかなオペコード以外)、サンプルの特定のデバイス固有の側面を変更する必要があります。 ドライバーの作成者は、これらの詳細を見落とす場合があります。

変更する必要がある正確な項目は、サンプルごとに異なりますが、一般に、特定のデバイス、インターフェイス、またはドライバーは識別されます。 たとえば、サンプル ドライバーに次の項目が含まれる場合は、ドライバーとデバイスに適用するには変更する必要があります。

  • グローバル一意識別子 (GUID)

  • シンボリック リンク名

  • デバイス オブジェクト名

  • プール タグ

  • I/O 制御コード (IOCTL) の定義

  • システム フォルダーにコピーされるファイルの名前

  • プラグ アンド プレイ デバイス ID、ハードウェア ID、および互換性 ID

  • ドライバー サービス名

  • デバイスの説明

  • リソース ファイル

これらの変更をし忘れると、インストールが失敗したり、システム上の他のデバイスやドライバーとの競合が発生したり、デバッグが困難になったりなどのエラーが発生する可能性があります。

たとえば、...\toastDrv\kmdf\toastmon\wdftoastmon.inx(18-18): error 1284: Class "Sample" is reserved for use by Microsoft. のようなエラーが発生した場合、これは "サンプル" 名をサンプル ドライバーの一意の名前に変更する必要があることを示しています。

GUID

ドライバーは GUID を使用して、デバイス セットアップ クラス、デバイス インターフェイス クラス、カスタム PnP イベント、カスタム Windows Management Instrumentation (WMI) イベント、および Windows PreProcessor (WPP) トレース プロバイダーを識別します。 Microsoft によって定義される GUID もあれば、デバイスやドライバーのベンダーによって定義される GUID もあります。

一般的なデバイスと WMI データのデバイス セットアップ クラス GUID、デバイス インターフェイス クラス GUID、および WMI GUID は、WDK 内、または任意のドライバーによって使用されるパブリック ヘッダー ファイル内で定義されます。 これらの GUID は変更することはできません。

たとえば、マウスを実装する場合、デバイス インターフェイス クラスとして、WDK Ntddmou.h ヘッダー ファイルで定義されている GUID_DEVINTERFACE_MOUSE を引き続き使用します。ただし、新しいデバイス セットアップ クラスを定義する場合は、新しいデバイス セットアップ クラス GUID、セットアップ クラス名、および場合によっては新しいデバイス インターフェイス クラス GUID も生成する必要があります。 セットアップ クラス GUID とデバイス インターフェイス クラス GUID は一意の値である必要があります。1 つの GUID を共有することはできません。

ほとんどのサンプルベースのドライバーでは、サンプルのローカル ヘッダーまたはソース ファイルで定義されており、そのためサンプルに固有の GUID のみを変更する必要があります。 そのような GUID には、以下のようなものがあります。

  • カスタム PnP イベント

  • カスタム WMI イベント

  • 新しいデバイスまたはカスタム デバイスのデバイス インターフェイス クラス

  • WPP トレース プロバイダー

別のドライバーに対して定義されている GUID を使用すると、両方のドライバーが同じシステムで読み込まれると、競合が発生する可能性があります。 たとえば、2 つの異なるドライバーが同じ GUID を使用してデバイス インターフェイスを登録している場合、クライアントがデバイス インターフェイスを開こうとするとき、間違ったデバイスを開く可能性があります。

次の抜粋は、すべてのトースター ドライバー サンプルに含まれている Driver.h ファイルからのものです。 これにより、トースター デバイスのデバイス インターフェイス GUID が定義されます。

DEFINE_GUID(GUID_TOASTER_INTERFACE_STANDARD, \
            0xe0b27630, 0x5434, 0x11d3, 0xb8, 0x90, 0x0, 0xc0, \
            0x4f, 0xad, 0x51, 0x71);
// {E0B27630-5434-11d3-B890-00C04FAD5171}

このファイルを独自のドライバーで使用する場合は、サンプル GUID (上の太字のテキストで示された) を、自身のデバイスのインターフェイス GUID に置き換えてください。 GUID を作成するには、Microsoft Visual Studio または Guidgen.exe で GUID の作成ツールを使用します。どちらも Microsoft Windows Software Development Kit (SDK) に含まれています。 次に、例に示すように、GUID をドライバー ヘッダー ファイル内のシンボリック定数に関連付けできます。

ドライバーの WMI イベントの新しい GUID を作成する必要がある場合もあります。 トースター ドライバーのサンプルでは、トースター デバイスの到着を通知する次の GUID を定義しています。


DEFINE_GUID (TOASTER_NOTIFY_DEVICE_ARRIVAL_EVENT, \
             0x1cdaff1, 0xc901, 0x45b4, 0xb3, 0x59, 0xb5, 0x54, \
             0x27, 0x25, 0xe2, 0x9c);
// {01CDAFF1-C901-45b4-B359-B5542725E29C}

ドライバーの WMI イベントごとに新しい GUID を作成する必要があります。

サンプル ドライバーで WPP ソフトウェア トレースが使用される場合は、サンプルをベースにしているすべてのドライバーの新しいトレース プロバイダー GUID を生成します。 たとえば、%WinDDK%\Src\Kmdf\Osrusbfx2\Final の Osrusbfx2 サンプルの Trace.h ヘッダー ファイルは、コントロール GUID を次のように定義します。

#define WPP_CONTROL_GUIDS \
    WPP_DEFINE_CONTROL_GUID( \
           OsrUsbFxTraceGuid,(d23a0c5a,d307,4f0e,ae8e,E2A355AD5DAB), \
        WPP_DEFINE_BIT(DBG_INIT)          /* bit  0 = 0x00000001 */ \
        WPP_DEFINE_BIT(DBG_PNP)           /* bit  1 = 0x00000002 */ \
        WPP_DEFINE_BIT(DBG_POWER)         /* bit  2 = 0x00000004 */ \
        WPP_DEFINE_BIT(DBG_WMI)           /* bit  3 = 0x00000008 */ \
        WPP_DEFINE_BIT(DBG_CREATE_CLOSE)  /* bit  4 = 0x00000010 */ \
        WPP_DEFINE_BIT(DBG_IOCTL)         /* bit  5 = 0x00000020 */ \
        WPP_DEFINE_BIT(DBG_WRITE)         /* bit  6 = 0x00000040 */ \
        WPP_DEFINE_BIT(DBG_READ)          /* bit  7 = 0x00000080 */ \
       )

独自のドライバーでは、太字のテキストを、作成したドライバー固有の名前と GUID に置き換えます。

サンプルでシンボリック リンク名が定義されている場合は、サンプル内の名前を、独自のドライバーに適用される名前に置き換えます。 ただし、\DosDevices\COM1 などの既知のリンク名は変更しないでください。 一般に、リンク名がサンプル名 (\DosDevices\CancelSamp など) に非常に似ている場合は、変更する必要があります。

デバイス インターフェイスは基本的にシンボリック リンクなので、別のドライバーと同じシンボリック リンクを使用すると、間違ったデバイス インターフェイス GUID を使用した場合と同じ影響が出ます。

%WinDDK\Src\Kmdf\Toaster\Filter の KMDF トースター フィルター ドライバーは、Filter.h ヘッダー ファイルで次のように定義された文字列を使用するシンボリック リンク名を作成します。

#define SYMBOLIC_NAME_STRING     L"\\DosDevices\\ToasterFilter"

太字の文字列を変更して、独自のドライバーをより正確に記述します。

デバイス オブジェクト名

サンプルでデバイス オブジェクトの名前を作成する場合は、サンプル コードを調整するときに名前を変更する必要があります。

KMDF トースター フィルター ドライバーは、Filter.h ヘッダー ファイルでデバイス オブジェクトに次のように名前を付けます。

#define NTDEVICE_NAME_STRING      L\\Device\\ToasterFilter

シンボリック リンク名と同様に、ドライバーを記述するために文字列を変更する必要があります。

名前付きデバイス オブジェクトはセキュリティ リスクを表す可能性があることを覚えておいてください。 物理デバイス オブジェクト (PDP) には名前が必要です。このような名前のほとんどは、ドライバーによって明示的に割り当てられるのではなく、システムによって生成されます。 その他のデバイス オブジェクトには、アプリケーションとドライバー間のサイドバンド通信に使用されるコントロール デバイス オブジェクトを表す場合にのみ、名前を付ける必要があります。 カーネルモード ドライバー フレームワーク (KMDF) と Windows Driver Model (WDM) の両方で、Windows により名前を生成できます。 この方法を使用すると、デバイス オブジェクトの名前は一意になり、特権のないユーザーはアクセスできなくなります。 詳細については、「デバイスの名前空間アクセスの制御」と「KMDF ドライバーでのデバイス アクセスの制御」を参照してください。

プール タグ

プール タグは、特定のメモリ割り当てを識別し、デバッグに役立つ 1 から 4 文字のリテラルです。

サンプル ドライバーの多くは、Toaster.h からの次の行のように、ドライバー ヘッダー ファイルにプール タグを定義します。

#define TOASTER_POOL_TAG (ULONG) 'saoT'

ドライバーはタグを後ろから定義します。これは、デバッガーにより逆順にそれが表示されるためです。 したがって、このタグはデバッガー出力に Toas として表示されます。 サンプルで定義されるタグを使用する代わりに、独自のコードを一意に識別するために文字列を変更します。

この Pooltag.txt ファイルには、Windows に付属する、カーネルモード のコンポーネントとドライバーで使用されるプール タグが一覧表示されます。 Pooltag.txt は %winddk%\Tools\Other<i>platform\Poolmon の WDK によってインストールされます。ここで、プラットフォームは amd64、i386、または ia64 です。 この一覧に表示されるタグは使用しないでください。

IOCTL 定義

サンプル定義の I/O 制御コードを、デバイスとドライバーに適した名前、デバイスの種類、関数コード、転送の種類、およびアクセスの種類を使用するように変更します。

たとえば、Osrusbfx2 サンプルには、IOCTL_OSRUSBFX2_READ_SWITCHES の次の定義が含まれます。

#define IOCTL_OSRUSBFX2_READ_SWITCHES   
                    CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
                             IOCTL_INDEX + 6, \
                             METHOD_BUFFERED, \
                             FILE_READ_ACCESS)

別のデバイスのサンプルベースのドライバーでは、この定義を変更する必要があります。

ファイル名

INF または INX で、ドライバーの名前、ベンダーが提供する共同インストーラー、およびインストール手順でシステム フォルダーにコピーされるその他のファイルがあれば変更します。 これらのファイル名は、通常、INF の [SourceDisksFiles] セクションと [ClassInstall32] セクションや CopyFiles エントリに表示されます。

次の例は、KMDF おすすめトースター サンプルの INX ファイルからのものです (%WinDDK%\src\kmdf\Toaster\Func\Featured で入手可能)。 変更する必要があるファイル名は、太字で示されています。

[ClassInstall32]
Addreg=ToasterClassReg
CopyFiles=ToasterClassInstallerCopyFileshighlight

[ToasterClassReg]
...
HKR,,Installer32,,"tostrcls.dll,ToasterClassInstaller"
...

[ToasterClassInstallerCopyFiles]
tostrcls.dll									    
...

ファイルのこの部分を別のドライバーに対応させるには、"tostrcls.dll" をクラス インストーラーのファイル名に変更し、"ToasterClassInstaller" 文字列を独自のインストーラーを説明するように変更します。 これらの変更により、インストール手順で正しい共同インストーラー ファイルがコピーされ、レジストリ キーに正しいファイル名が記録されます。

WDK または Windows に付属の共同インストーラー (KMDF、UMDF、WinUSB 共同インストーラーなど) の名前を変更しないでください。

この例に示すように、追加の変更が、後でファイルのデバイス インストールのセクションで必要になります。

[Toaster_Device.NT]
CopyFiles=Toaster_Device.NT.Copy

[Toaster_Device.NT.Copy]
wdffeatured.sys

この例では、太字のファイル名を、生成されたドライバー ファイルの名前に変更します。

セットアップによって INF ファイルとドライバー カタログ ファイルがコピーされるときに、それらは変更されます。そのため、ドライバー パッケージ内の名前を変更する必要は厳密にはありません。 ただし、一般的に、INF ファイル名とカタログ ファイル名をドライバー ファイル名と同様のものにすることをお勧めします。

PnP デバイス ID、ハードウェア ID、および互換性 ID

セットアップでは、ハードウェア ID や互換性 ID と共にデバイス ID を使用して、デバイスのインストールに使用する INF が選択されます。

デバイス ID は、特定のデバイスを一意に識別するベンダー定義の文字列です。 すべてのデバイスには、正確に 1 つのデバイス ID があります。 バス ドライバーは列挙中にデバイス ID を報告し、セットアップはそれを使用してデバイスを正しい INF ファイルと一致させます。 デバイス ID は、INF の [製造元] セクションで定義されています。

次の例は、Osrusbfx2.inx ファイルで指定されている、OSR USB Fx2 デバイスのデバイス ID を示しています。

[Manufacturer]
%MfgName%=Microsoft,NT$ARCH$

; For Win2K
[Microsoft]
%USB\VID_045E&PID_930A.DeviceDesc%=osrusbfx2.Dev, 
        USB\VID_0547&PID_1002
...

; For XP and later
[Microsoft.NT$ARCH$]
%USB\VID_045E&PID_930A.DeviceDesc%=osrusbfx2.Dev, 
        USB\VID_0547&PID_1002

独自のドライバー用にこの INF ディレクティブを調整するには、太字で示されているデバイス ID を、自分のデバイスのデバイス ID に置き換えます。 製造元の名前を自社の名前に変更する必要もあります。

ハードウェア ID と互換性 ID は、デバイス ID を INF に一致させることができない場合、セットアップによって使用される特定性の低い ID になります。 INF が他のデバイスをサポートできる場合は、デバイス ID に加えて、これらの値も変更する必要があります。 KMDF のおすすめのトースター ドライバーの次の例は、ハードウェア ID を示しています。


[Manufacturer]
%StdMfg%=Standard,NT$ARCH$

; For Win2K
[Standard]
; DisplayName                   Section           DeviceId
; -----------                   -------           --------
%ToasterDevice.DeviceDesc%=Toaster_Device, 
         {b85b7c50-6a01-11d2-b841-00c04fad5171}\MsToaster

; For XP and later
[Standard.NT$ARCH$]
%ToasterDevice.DeviceDesc%=Toaster_Device, 
         {b85b7c50-6a01-11d2-b841-00c04fad5171}\MsToaster

独自のドライバー用にこの INF ディレクティブを調整するには、ハードウェア ID をドライバーのデバイス ID に置き換え、"MsToaster" をよりわかりやすい文字列に変更します。

ドライバー サービス名

INF で Addservice ディレクティブのサービス名を、ドライバーに適した値に更新します。 ドライバー サービス名がシステム上の別のドライバーの名前と競合する場合、ドライバーはインストールまたはロードされません。

KMDF のおすすめのトースター ドライバーは、次のようにサービスに名前を付けます。


[Toaster_Device.NT.Services]
AddService = wdffeatured, %SPSVCINST_ASSOCSERVICE%,
     wdffeatured_Service_Inst
      

サービス名は、Addservice ディレクティブの最初のエントリです。 おすすめのトースターの INF を調整するには、太字の文字列を、ドライバーにより適した文字列に変更します。 この例では、wdffeatured_Service_Inst エントリは単に INF 定義のセクションを参照しているので、変更することは重要ではありません。

デバイスの説明

デバイスの説明は、INF の [Strings] セクションで通常定義され、INF 全体のさまざまな場所で使用されるいくつかの文字列で構成されます。 たとえば、KMDF のおすすめトースター サンプルでは、WdfFeatured.inx ファイル内で次の文字列が定義されます。

[Strings]
SPSVCINST_ASSOCSERVICE   = 0x00000002
MSFT                     = "Microsoft"
StdMfg                   = "(Standard system devices)"
ClassName                = "Toaster"
DiskId1                  = "Toaster Device Installation Disk #1"
ToasterDevice.DeviceDesc = "Microsoft WDF Featured Toaster"
Toaster.SVCDESC          = "Microsoft WDF Toaster Featured Device Driver"

このファイルを変更して独自のドライバーをインストールするには、会社、デバイス、およびドライバーに関する情報を反映するように太字の文字列を変更する必要があります。

会社名が INF の [Manufacturer] セクションにも表示される場合は、その名前も変更する必要があります。

リソース ファイル

ドライバーや、サンプル固有の共同インストーラーなどのコンポーネントには、リソース (.rc) ファイルも含まれています。これは、製品名、ファイルのバージョン、会社名など、ドライバー固有の文字列を定義します。 これらの文字列を、ドライバー パッケージの適切な値に変更します。

概要 - 必要な変更

WDK サンプルに基づくドライバーをリリースする前に、ソース ファイル、INF、および独自のドライバーの作成に使用したその他のリソースの、サンプル固有の情報を置き換えてください。 必要な変更はサンプルによって異なりますが、通常は、サンプル ドライバーまたはそのデバイスを一意に識別する情報を含みます。 一般に、次のような変更が必要になります。

  • 必要に応じて、お使いのドライバー固有の GUID を生成して使用します。

  • シンボリック リンク名を更新します。

  • デバイス オブジェクトの名前を更新するか、自動生成された名前を使用します。

  • ドライバーを識別し、既知のタグと競合しないプール タグを使用します。

  • ドライバーとデバイスに適した IOCTL コードを定義します。

  • システム フォルダーにコピーされるファイルの名前を更新します。

  • 正しいプラグ アンド プレイ デバイス ID、ハードウェア ID、互換性 ID を INF に挿入します。

  • INF でドライバーのサービス名を更新します。

  • デバイスの説明を変更します。

  • リソース ファイル内のドライバー固有の文字列を変更します。

  • セキュリティと信頼性に関するベスト プラクティスに従います。

追加情報

書籍

Windows Driver Foundation でのドライバーの開発』、著者: Penny Orwick および Guy Smith

WDK に関するトピック

新しい GUID の定義とエクスポート

KMDF ドライバーでのデバイス アクセスの制御

ドライバーの開発、テスト、および展開

信頼性の高いカーネルモード ドライバーの作成

Surface Team ドライバー開発ベスト プラクティス

ドライバーのセキュリティ ガイダンス

初めてのドライバーの作成