ドライバー ストアから実行する

[ドライバー ストアから実行する] を使用している INF は、インストール時に ドライバー パッケージ ファイルの場所を指定するために DIRID 13 を使用する INF を意味します。

INF によってペイロードされた "ドライバー ストアから実行する" ファイルの場合、INF 内のそのファイルに対する SourceDisksFiles エントリにリストされている subdir は、INF 内の同じファイルに対する DestinationDirs エントリにリストされている subdir と一致している 必要があります

さらに、 CopyFiles ディレクティブを使用して、ドライバーストアから実行されるファイルの名前を変更することはできません。 これらの制限は、デバイスにINFをインストールしてもドライバー ストア ディレクトリに新しいファイルが作成されないようにするために必要です。

SourceDisksFiles エントリには同じファイル名の複数のエントリを含めることはできず、CopyFilesを使用してファイル名を変更することはできないため、INF が参照するすべての「ドライバー ストアから実行」ファイルには一意のファイル名が必要です。

ドライバー パッケージは Windows 10 1709 以降、[ドライバー ストアから実行する] を全般的にサポートしています。 ただし、特定のデバイス スタックでは、そのスタックにプラグインするために提供する必要があるファイルに追加の制限が課される場合があります。 いくつかの例は、Windows 10 1803 まで「ドライバー ストアからの実行」をサポートしていなかったデバイススタックです。

特定のデバイス スタックにプラグインするバイナリを提供する場合は、プラグインしている特定のデバイス スタックのドキュメントを参照して、バイナリへの完全なファイル パスの提供をサポートしているかどうか、およびその完全なファイル パスに制限があるかどうかを確認してください。 。 バイナリへの完全ファイル パスの提供をそのパスの制限なしでサポートしている場合は、'ドライバー ストアから実行' されるファイルをサポートする必要があります。

ドライバー ストアから動的にファイルを見つけて読み込む

場合によっては、コンポーネントが「ドライバー ストアから実行」を使用するドライバー パッケージの一部であるファイルを読み込む必要があることがあります。 これらのドライバー パッケージ ファイルへのパスは、ドライバー パッケージのバージョン、OS バージョン、OS エディションなどによって異なる可能性があるため、ハードコーディングしないでください。ドライバー パッケージ ファイルを読み込む必要が生じた場合は、これらのドライバー パッケージ ファイルをハードコーディングする必要があります。以下で説明するパラダイムのいくつかを使用して、動的に検出およびロードできます。

同じドライバー パッケージ内のファイルを検索して読み込む

ドライバー パッケージ内のファイルが、同じドライバー パッケージから別のファイルを読み込む必要がある場合、そのファイルを動的に検出するためのオプションの 1 つは、このファイルが実行されているディレクトリを特定し、そのディレクトリから見て相対的に他のファイルを読み込むことです。

Windows 10 バージョン 1803 以降のドライバーストアから実行され、ドライバーパッケージから他のファイルにアクセスする必要がある WDM または KMDFドライバーは、ドライバーの読み込み元のディレクトリ パスを取得するために、ディレクトリ タイプとして DriverDirectoryImage を指定して IoGetDriverDirectory を呼び出す必要があります。 または、Windows 10 バージョン 1803 より前の OS バージョンをサポートする必要があるドライバーの場合は、 IoQueryFullDriverPath を使用してドライバーのパスを見つけ、読み込み元であるディレクトリ パスを取得して、そのパスから見て相対的な場所にあるファイルを探します。 カーネル モード ドライバーが KMDF ドライバーの場合、 WdfDriverWdmGetDriverObject を使用して、IoQueryFullDriverPath に渡す WDM ドライバー オブジェクトを取得できます。

ユーザー モード バイナリは、 GetModuleHandleExWGetModuleFileNameW を使用して 、バイナリが読み込まれた場所を特定できます。 たとえば、UMDF ドライバー バイナリは、次のような処理を実行できます。

bRet = GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
                         (PCWSTR)&DriverEntry,
                         &handleModule);
if (bRet) {
    charsWritten = GetModuleFileNameW(handleModule,
                                      path,
                                      pathLength);
    …

任意のドライバー パッケージのファイルを検索して読み込む

ドライバー パッケージには、別のドライバー パッケージのバイナリまたはユーザー モード コンポーネントによって読み込まれるファイルが含まれている場合があります。 同じドライバー パッケージからのファイルの読み込みについて前述した方法よりも優先される場合は、この方法を同じドライバー パッケージのファイルに対して使用することもできます。

次に、ドライバー パッケージからのファイルの読み込みに関連する可能性のあるシナリオの例をいくつか示します。

  • ドライバー パッケージ内のユーザー モード DLL が、ドライバー パッケージ内のドライバーと通信するためのインターフェイスを提供する。

  • 拡張ドライバー パッケージ に、ベース ドライバー パッケージ内のドライバーによって読み込まれる構成ファイルが含まれている。

このような状況では、ドライバー パッケージは、読み込まれると予期されるファイルのパスを示すデバイスまたはデバイス インターフェイスに対して、状態を設定する必要があります。

ドライバー パッケージは通常、HKR AddReg を使用してこの状態を設定できます。 この例では、 ExampleFile.dll について、ドライバー パッケージは subdir のない SourceDisksFiles エントリを持つとします。 この結果、このファイルはドライバー パッケージ ディレクトリの root に存在します。 また、 CopyFiles ディレクティブの DestinationDirsdirid 13 が指定されることを前提とする必要があります。

これをデバイス状態として設定するINFの例を次に示します。

[ExampleDDInstall.HW]
AddReg = Example_DDInstall.AddReg

[Example_DDInstall.AddReg]
HKR,,ExampleValue,,%13%\ExampleFile.dll

デバイス インターフェイスの状態としてこれを設定する INF の例は次のようになります。

[ExampleDDInstall.Interfaces]
AddInterface = {<fill in an interface class GUID for an interface exposed by the device>},,Example_Add_Interface_Section

[Example_Add_Interface_Section]
AddReg = Example_Add_Interface_Section.AddReg

[Example_Add_Interface_Section.AddReg]
HKR,,ExampleValue,,%13%\ExampleFile.dll

前の例では、空のフラグ値が使用されているため、REG_SZ レジストリ値になります。 これにより、 %13% が完全修飾ユーザー モード ファイル パスに変換されます。 多くの場合、パスは環境変数に対する相対パスであることが望ましいです。 フラグ値 0x20000 を使用すると、レジストリ値はタイプ REG_EXPAND_SZ となり、 %13% は適切な環境変数で変換され、パスの場所が抽象化されます。 このレジストリ値を取得する場合、 ExpandEnvironmentStrings を呼び出して、パスの環境変数を解決します。

カーネル モード コンポーネントによってこの値を読み取る必要がある場合、値は REG_SZ 値でなければなりません。 カーネル モード コンポーネントはこの値を読み取るときに、先頭に \??\ を付けてから、 ZwOpenFile などの API に渡す必要があります。

この設定がデバイスの状態の一部である場合にこの設定にアクセスするには、まずアプリケーションがデバイスのIDを見つける必要があります。 ユーザー モード コードでは、 CM_Get_Device_ID_List_Size および CM_Get_Device_ID_List を使用してデバイスの一覧 (必要に応じて、フィルタ適用) を取得できます。 このデバイスの一覧には複数のデバイスが含まれている場合があるため、デバイスから状態を読み取る前に、適切なデバイスを検索します。 たとえば、特定の条件に一致するデバイスを検索するときに、CM_Get_DevNode_Property を呼び出して、そのデバイスのプロパティを取得します。

適切なデバイスが見つかったら、 CM_Open_DevNode_Key を呼び出して、デバイスの状態が格納されたレジストリの場所へのハンドルを取得します。

カーネル モード コードでは、デバイスに対して PDO (物理デバイス オブジェクト) を状態とともに取得し、 IoOpenDeviceRegistryKey を呼び出す必要があります。 カーネル モード コードでデバイスの PDO を取得する方法の 1 つとして、デバイスによって公開されている有効なインターフェイスを検出し、 IoGetDeviceObjectPointer を使用してデバイス オブジェクトを取得する方法があります。

デバイスインターフェイス状態のときにこの設定にアクセスするには、ユーザーモードコードで CM_Get_Device_Interface_List_Size および CM_Get_Device_Interface_Listを呼び出すことができます。

また、デバイス インターフェイスの接続や削除の通知を受けるために、 CM_Register_Notification を使用できます。これにより、コードではインターフェイスが有効化されたときに通知を受け、状態を取得できます。 上記の API で使用されるデバイス インターフェイス クラスには、複数のデバイス インターフェイスがある可能性があります。 これらのインターフェイスを確認し、設定を読み込むために適切なインターフェイスを特定します。

適切なインターフェイスが見つかったら、 CM_Open_Device_Interface_Key を呼び出します。

カーネル モード コードでは、状態を取得するデバイス インターフェイスのシンボリック リンク名を取得できます。 そのためには、 IoRegisterPlugPlayNotification を呼び出して、適切なデバイス インターフェイス クラスでデバイス インターフェイス通知に登録します。 別の方法として、システム上の現在のデバイス インターフェイスの一覧を取得するために IoGetDeviceInterfaces を呼び出すこともできます。 上記の API で使用されるデバイス インターフェイス クラスには、複数のデバイス インターフェイスがある可能性があります。 これらのインターフェイスを確認し、設定を読み取る適切なインターフェイスを特定します。

適切なシンボリック リンク名が見つかったら、 IoOpenDeviceInterfaceRegistryKey を呼び出して、デバイス インターフェイスの状態が格納されたレジストリの場所へのハンドルを取得します。

Note

CM_GETIDLIST_FILTER_PRESENT フラグと CM_Get_Device_ID_List_Size および CM_Get_Device_ID_List を使用するか、 CM_GET_DEVICE_INTERFACE_LIST_PRESENT フラグと CM_Get_Device_Interface_List_Size および CM_Get_Device_Interface_List を使用します。 これにより、ファイル パスを含む状態に関連するハードウェアが存在し、通信の準備ができていることが確認されます。

ドライバー パッケージの削除

デフォルトでは、ドライバーパッケージがデバイスにまだインストールされている場合、そのドライバーパッケージをシステムから削除することはできません。 ただし、システムからドライバー パッケージを削除するための一部のオプションでは、"強制的" な削除を試行できます。 これにより、ドライバー パッケージがシステムの一部のデバイスにまだインストールされている場合でも、ドライバー パッケージの削除が試行されます。 「ドライバー ストアから実行」されるファイルを含むドライバーパッケージの強制削除は許可されません。 ドライバー パッケージがシステムから削除されると、そのドライバー ストアの内容は削除されます。 そのドライバー パッケージを使用してインストールされているデバイスがある場合は、そのドライバー パッケージ内の "ドライバー ストアから実行する" ファイルがすべて削除され、それらの欠落しているファイルが原因でデバイスが誤動作する可能性があります。 デバイスがそのような悪い状態に陥るのを防ぐために、「ドライバー ストアから実行」ファイルを含むドライバーパッケージは強制的に削除できません。 これらは、どのデバイスにもインストールされなくなった場合にのみ削除できます。 このようなドライバー パッケージの削除を支援するために、 DiUninstallDriver または pnputil /delete-driver <oem#.inf> /uninstall を使用できます。 これらの削除方法では、ドライバー パッケージの削除を試行する前に、削除するドライバー パッケージを使用しているデバイスを更新して、そのドライバー パッケージが今後インストールされることのないようにします。

ドライバー パッケージの開発

プライベート バイナリのテスト

ドライバーパッケージを開発するときに、システム上のドライバー パッケージを完全に再構築して置き換えるのではなく、ドライバー パッケージの特定の実行可能ファイルをプライベート バージョンに置き換える必要がある場合は、カーネル デバッガーを .kdfiles コマンドとともに使用することを勧めます。 ドライバーストア内のファイルへのフルパスはハードコーディングすべきではないため、.kdfiles マッピングでは、 OldDriver ファイル名は先行するパス情報のない単なるファイルの直接名であることが推奨されます。 これ (および他のシナリオ) を容易にするために、ドライバーパッケージ内のファイル名はできる限り一意にして、システム上の無関係なドライバーパッケージのファイル名と一致しないようにする必要があります。

ドライバー ストアからの実行を使用するように INF を移植する

ドライバーストアからの実行を使用しない INF を含む既存のドライバーパッケージがあり、それをドライバーストアからの実行を使用するように移植する場合、次の例は、INFでの一般的なファイルの使用法と、それらのファイルを実行するように更新するパターンを示しています。ドライバーストア。

宛先ディレクトリの更新に関するクイック リファレンス

次の表は、ドライバーパッケージ INFがファイルに対して指定する現在の宛先ディレクトリ DIRID に基づいて、適切なガイダンスを見つけるためのクイックリファレンスを提供します。

ディリド Subdirectory 詳細
13 ファイルはすでに「ドライバー ストアから実行」を使用しています。 これ以上の作業は必要ありません。
1 DIRID 1は使用しないでください。 ファイルへの参照を解決する必要があるときに、ソース ディレクトリが使用できるという保証はありません。 その代わりに、ドライバーパッケージ内のコンポーネントが特定のファイルに依存している場合は、それらのファイルをドライバーパッケージに含めて、ドライバー ストアから実行します。
10 ファームウェア DIRID 13をファームウェア更新ドライバー パッケージとともに使用して「ドライバー ストアから実行」を使用する方法については、 更新ドライバー パッケージの作成 を参照。
10 他のファイルを参照。
11 他のファイルを参照。
12 UMDF UMDF ドライバー バイナリを参照。
12 DIRID 12の宛先を持つほとんどのファイルは、ドライバーサービスバイナリを表します。 サービスバイナリを参照。
16422、16426、16427、16428 これらの DIRID の宛先を持つほとんどのファイルは、アプリケーションのインストールを表します。 代わりに、ユニバーサルウィンドウプラットフォーム (UWP) アプリケーションを提供し、ドライバー パッケージ INFの DDInstall.Software セクション から AddSoftware ディレクティブ を使用してインストールします。 詳細については、 ドライバーとユニバーサルウィンドウプラットフォーム (UWP) アプリの組み合わせ を参照。

サービス バイナリ

INFがサービスを追加し、バイナリがドライバー ストアから実行されていない場合、INFは次のようになります。

[DestinationDirs]
 ; Copy the file to %windir%\system32\drivers
 Example_CopyFiles = 12

[ExampleDDInstall]
CopyFiles = Example_CopyFiles

[Example_CopyFiles]
ExampleBinary.sys

[ExampleDDInstall.Services]
AddService = ExampleService,0x2,Example_Service_Inst

[Example_Service_Inst]
DisplayName   = %SvcDesc%
ServiceType   = %SERVICE_KERNEL_DRIVER%
StartType     = %SERVICE_DEMAND_START%
ErrorControl  = %SERVICE_ERROR_NORMAL%
; Point at the file in %windir%\system32\drivers
ServiceBinary = %12%\ExampleBinary.sys

このファイルをドライバー ストアから実行されるように移動するには、ファイルのコピー先の DestinationDirs エントリを更新し、このファイルの場所を参照する ServiceBinary ディレクティブを更新する必要があります。

[DestinationDirs]
; Update the destination to DIRID 13
Example_CopyFiles = 13

[ExampleDDInstall]
CopyFiles = Example_CopyFiles

[Example_CopyFiles]
ExampleBinary.sys

[ExampleDDInstall.Services]
AddService = ExampleService,0x2,Example_Service_Inst

[Example_Service_Inst]
DisplayName   = %SvcDesc%
ServiceType   = %SERVICE_KERNEL_DRIVER%
StartType     = %SERVICE_DEMAND_START%
ErrorControl  = %SERVICE_ERROR_NORMAL%
; Point at the run from Driver Store file using DIRID 13
ServiceBinary = %13%\ExampleBinary.sys

UMDF ドライバー バイナリ

INFがUMDFドライバーを追加し、バイナリがドライバー ストアから実行されていない場合、INF は次のようになります。

[DestinationDirs]
; Copy the file to %windir%\system32\drivers\UMDF
Example_CopyFiles = 12, UMDF

[ExampleDDInstall]
CopyFiles = Example_CopyFiles

[Example_CopyFiles]
ExampleUmdfDriver.dll

[ExampleDDInstall.Wdf]
UmdfService = ExampleUmdfDriver,Example_UMDF_Inst
...

[Example_UMDF_Inst]
; Point at the file in %windir%\system32\drivers\UMDF
ServiceBinary = %12%\UMDF\ExampleUmdfDriver.dll
...

このファイルをドライバー ストアから実行されるように移動するには、ファイルのコピー先の DestinationDirs エントリを更新し、このファイルの場所を参照する ServiceBinary ディレクティブを更新する必要があります。

[DestinationDirs]
; Update the destination to DIRID 13
Example_CopyFiles = 13

[ExampleDDInstall]
CopyFiles = Example_CopyFiles

[Example_CopyFiles]
ExampleUmdfDriver.dll

[ExampleDDInstall.Wdf]
UmdfService = ExampleUmdfDriver,Example_UMDF_Inst
...

[Example_UMDF_Inst]
; Point at the run from Driver Store file using DIRID 13
ServiceBinary = %13%\ExampleUmdfDriver.dll
...

他のファイル

他のコンポーネントによって読み込まれる可能性があり、ドライバー ストアから実行されないファイルを INF に追加する場合、INFは次のようになります。 この例では、ファイルの名前のみがデバイスのレジストリの状態に書き込まれます。 このレジストリ値を読み取って、読み込むファイルを決定するコンポーネントは、ファイルが %windir%\system32 にあるか、または LoadLibraryの検索順序に応じてファイルを見つけることができます。

[DestinationDirs]
; Copy the file to %windir%\system32
Example_CopyFiles = 11

[ExampleDDInstall]
CopyFiles=Example_CopyFiles
AddReg=Example_AddReg

[Example_CopyFiles]
ExampleFile.dll

[Example_AddReg]
HKR,,FileLocation,,"ExampleFile.dll"

このファイルをドライバー ストアから実行されるように移動するには、ファイルのコピー先の DestinationDirs エントリを更新し、デバイスの状態に保存されている場所を更新する必要があります。 そのためには、そのレジストリ値を読み取るコンポーネントが、 %windir%\system32への相対パスではなく、ファイルへの完全パスであるレジストリ値を処理できるようにする必要があります。

[DestinationDirs]
Example_CopyFiles = 13 ; update the destination to DIRID 13

[ExampleDDInstall]
CopyFiles=Example_CopyFiles
AddReg=Example_AddReg

[Example_CopyFiles]
ExampleFile.dll

[Example_AddReg]
; Point at the run from Driver Store file using DIRID 13
HKR,,FileLocation,,"%13%\ExampleFile.dll"