ダイナミック リンク ライブラリの検索順序
システムには、同じダイナミック リンク ライブラリ (DLL) の複数のバージョンを含めることができます。 アプリケーションは、完全なパスを指定するか、マニフェストなどの別のメカニズムを使用して、DLL の読み込み元の場所を制御できます。 これらのメソッドを使用しない場合、システムはこのトピックで説明するように読み込み時に DLL を検索します。
検索に影響を与える要因
次の要因は、システムが DLL を検索するかどうかに影響します。
- 同じモジュール名を持つ DLL が既にメモリに読み込まれている場合、システムはリダイレクトとマニフェストのみをチェックしてから、読み込まれた DLL に解決します。どのディレクトリにあってもかまいません。 システムは DLL を検索しません。
- アプリケーションが実行されているWindowsのバージョンの既知の DLL の一覧に DLL がある場合、システムは DLL を検索する代わりに、既知の DLL (および既知の DLL の依存 DLL がある場合) のコピーを使用します。 現在のシステム上の既知の DLL の一覧については、次のレジストリ キーを参照してください: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs。
- DLL に依存関係がある場合、システムは依存 DLL を、モジュール名だけで読み込まれたかのように検索します。 これは、完全パスを指定して最初の DLL が読み込まれた場合でも当てはまります。
UWP アプリの検索順序
Windows 10用の UWP アプリ (または Windows 8.x 用のMicrosoft Store アプリ) が LoadPackagedLibrary 関数を呼び出してパッケージ化されたモジュールを読み込む場合、DLL はプロセスのパッケージ依存関係グラフに含まれている必要があります。 詳細については、「 LoadPackagedLibrary」を参照してください。 UWP アプリが他の方法でモジュールを読み込み、完全なパスを指定しない場合、システムはこのセクションで説明するように、読み込み時に DLL とその依存関係を検索します。
システムが DLL を検索する前に、次のチェックが行われます。
- 同じモジュール名の DLL が既にメモリに読み込まれている場合、システムは読み込まれた DLL をどのディレクトリにあっても使用します。 システムは DLL を検索しません。
- アプリケーションが実行されているWindowsのバージョンの既知の DLL の一覧に DLL がある場合、システムは既知の DLL (および既知の DLL の依存 DLL がある場合) のコピーを使用します。 システムは DLL を検索しません。 現在のシステム上の既知の DLL の一覧については、次のレジストリ キーを参照してください: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs。
システムがモジュールまたはその依存関係を検索する必要がある場合、依存関係が UWP アプリ コードでない場合でも、常に UWP アプリの検索順序が使用されます。
UWP アプリの標準検索順序
モジュールがまだ読み込まれていない場合、または既知の DLL の一覧に含まれている場合、システムは次の順序でこれらの場所を検索します。
- プロセスのパッケージ依存関係グラフ。 これは、アプリケーションのパッケージ と、アプリケーションのパッケージ マニフェストのセクションで
<PackageDependency><Dependencies>指定された依存関係です。 依存関係は、マニフェストに表示される順序で検索されます。 - 呼び出し元のプロセスが読み込まれたディレクトリ。
- システム ディレクトリ (%SystemRoot%\system32)。
DLL に依存関係がある場合、システムは依存 DLL を、モジュール名だけで読み込まれたかのように検索します。 これは、完全パスを指定して最初の DLL が読み込まれた場合でも当てはまります。
UWP アプリの代替検索順序
LOAD_WITH_ALTERED_SEARCH_PATHを使用して LoadLibraryEx 関数を呼び出してモジュールが標準の検索順序を変更した場合、システムは呼び出し元プロセスのディレクトリではなく、指定したモジュールが読み込まれたディレクトリを検索します。 システムは、次の場所を次の順序で検索します。
- プロセスのパッケージ依存関係グラフ。 これは、アプリケーションのパッケージ と、アプリケーションのパッケージ マニフェストのセクションで
<PackageDependency><Dependencies>指定された依存関係です。 依存関係は、マニフェストに表示される順序で検索されます。 - 指定したモジュールが読み込まれたディレクトリ。
- システム ディレクトリ (%SystemRoot%\system32)。
デスクトップ アプリケーションの検索順序
デスクトップ アプリケーションは、完全なパスを指定するか、DLL リダイレクトを使用するか、マニフェストを使用して、 DLL の読み込み元の場所を制御 できます。 これらのメソッドのいずれも使用しない場合は、このセクションで説明するように、読み込み時に DLL が検索されます。
システムが DLL を検索する前に、次のチェックが行われます。
- 同じモジュール名の DLL が既にメモリに読み込まれている場合、システムは読み込まれた DLL をどのディレクトリにあっても使用します。 システムは DLL を検索しません。
- アプリケーションが実行されているWindowsのバージョンの既知の DLL の一覧に DLL がある場合、システムは既知の DLL (および既知の DLL の依存 DLL がある場合) のコピーを使用します。 システムは DLL を検索しません。 現在のシステム上の既知の DLL の一覧については、次のレジストリ キーを参照してください: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs。
DLL に依存関係がある場合、システムは依存 DLL を、モジュール名だけで読み込まれたかのように検索します。 これは、完全パスを指定して最初の DLL が読み込まれた場合でも当てはまります。
重要
攻撃者が検索されるディレクトリの 1 つを制御すると、そのディレクトリに DLL の悪意のあるコピーが配置される可能性があります。 このような攻撃を防ぐ方法については、 ダイナミック リンク ライブラリのセキュリティに関するページを参照してください。
デスクトップ アプリケーションの標準検索順序
システムで使用される標準 DLL 検索順序は、安全な DLL 検索モードが有効か無効かによって異なります。 セーフ DLL 検索モードでは、後でユーザーの現在のディレクトリが検索順序に配置されます。
セーフ DLL 検索モードは既定で有効になっています。 この機能を無効にするには、 HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\SafeDllSearchMode レジストリ値を作成し、0 に設定します。 SetDllDirectory 関数を呼び出すと、指定したディレクトリが検索パスにある間に SafeDllSearchMode が実質的に無効になり、このトピックの説明に従って検索順序が変更されます。
SafeDllSearchMode が有効になっている場合、検索順序は次のようになります。
- アプリケーションの読み込み元のディレクトリ。
- システム ディレクトリです。 GetSystemDirectory 関数を使用して、このディレクトリのパスを取得します。
- 16 ビット システム ディレクトリ。 このディレクトリのパスを取得する関数はありませんが、検索されます。
- Windows ディレクトリ。 GetWindowsDirectory 関数を使用して、このディレクトリのパスを取得します。
- 現在のフォルダー。
- PATH 環境変数に一覧表示されているディレクトリ。 これには、 App Paths レジストリ キーで指定されたアプリケーションごとのパスは含まれないことに注意してください。 DLL 検索パスを計算するときに 、アプリ パス キーは使用されません。
SafeDllSearchMode が無効になっている場合、検索順序は次のようになります。
- アプリケーションの読み込み元のディレクトリ。
- 現在のフォルダー。
- システム ディレクトリです。 GetSystemDirectory 関数を使用して、このディレクトリのパスを取得します。
- 16 ビット システム ディレクトリ。 このディレクトリのパスを取得する関数はありませんが、検索されます。
- Windows ディレクトリ。 GetWindowsDirectory 関数を使用して、このディレクトリのパスを取得します。
- PATH 環境変数に一覧表示されているディレクトリ。 これには、 App Paths レジストリ キーで指定されたアプリケーションごとのパスは含まれないことに注意してください。 DLL 検索パスを計算するときに 、アプリ パス キーは使用されません。
デスクトップ アプリケーションの代替検索順序
システムで使用される標準の検索順序は、LOAD_WITH_ALTERED_SEARCH_PATHを使用して LoadLibraryEx 関数を呼び出すことによって変更できます。 標準の検索順序は、 SetDllDirectory 関数を呼び出すことによっても変更できます。
Note
プロセスの標準的な検索順序も、現在のプロセスを開始する前に親プロセスで SetDllDirectory 関数を呼び出すことによって影響を受けます。
代替検索戦略を指定した場合、関連付けられているすべての実行可能モジュールが見つかるまで、その動作は続行されます。 システムが DLL 初期化ルーチンの処理を開始すると、システムは標準の検索戦略に戻ります。
LoadLibraryEx 関数は、呼び出しでLOAD_WITH_ALTERED_SEARCH_PATHを指定し、lpFileName パラメーターで絶対パスを指定する場合に、代替検索順序をサポートします。
LoadLibraryEx で指定された標準的な検索戦略と、LOAD_WITH_ALTERED_SEARCH_PATHで指定された代替検索戦略は、1 つの方法で異なります。標準検索は呼び出し元のアプリケーションのディレクトリから始まり、代替検索は LoadLibraryEx が読み込んでいる実行可能モジュールのディレクトリから開始されます。
SafeDllSearchMode が有効になっている場合、代替検索順序は次のようになります。
- lpFileName で指定されたディレクトリ。
- システム ディレクトリです。 GetSystemDirectory 関数を使用して、このディレクトリのパスを取得します。
- 16 ビット システム ディレクトリ。 このディレクトリのパスを取得する関数はありませんが、検索されます。
- Windows ディレクトリ。 GetWindowsDirectory 関数を使用して、このディレクトリのパスを取得します。
- 現在のフォルダー。
- PATH 環境変数に一覧表示されているディレクトリ。 これには、 App Paths レジストリ キーで指定されたアプリケーションごとのパスは含まれないことに注意してください。 DLL 検索パスを計算する場合、 アプリ パス キーは使用されません。
SafeDllSearchMode が無効になっている場合、代替検索順序は次のようになります。
- lpFileName で指定されたディレクトリ。
- 現在のフォルダー。
- システム ディレクトリです。 GetSystemDirectory 関数を使用して、このディレクトリのパスを取得します。
- 16 ビット システム ディレクトリ。 このディレクトリのパスを取得する関数はありませんが、検索されます。
- Windows ディレクトリ。 GetWindowsDirectory 関数を使用して、このディレクトリのパスを取得します。
- PATH 環境変数に一覧表示されているディレクトリ。 これには、 App Paths レジストリ キーで指定されたアプリケーションごとのパスは含まれないことに注意してください。 DLL 検索パスを計算する場合、 アプリ パス キーは使用されません。
lpPathName パラメーターでパスが指定されている場合、SetDllDirectory 関数は代替検索順序をサポートします。 代替検索順序は次のとおりです。
- アプリケーションの読み込み元のディレクトリ。
- SetDllDirectory の lpPathName パラメーターで指定されたディレクトリ。
- システム ディレクトリです。 GetSystemDirectory 関数を使用して、このディレクトリのパスを取得します。 このディレクトリの名前は System32 です。
- 16 ビット システム ディレクトリ。 このディレクトリのパスを取得する関数はありませんが、検索されます。 このディレクトリの名前は System です。
- Windows ディレクトリ。 GetWindowsDirectory 関数を使用して、このディレクトリのパスを取得します。
- PATH 環境変数に一覧表示されているディレクトリ。 これには、 App Paths レジストリ キーで指定されたアプリケーションごとのパスは含まれないことに注意してください。 DLL 検索パスを計算する場合、 アプリ パス キーは使用されません。
lpPathName パラメーターが空の文字列の場合、呼び出しは現在のディレクトリを検索順序から削除します。
SetDllDirectory は 、指定されたディレクトリが検索パスにある間、安全な DLL 検索モードを効果的に無効にします。 SafeDllSearchMode レジストリ値に基づいて安全な DLL 検索モードを復元し、現在のディレクトリを検索順序に復元するには、lpPathName を NULL として使用して SetDllDirectory を呼び出します。
LOAD_LIBRARY_SEARCH フラグを使用した検索順序
アプリケーションでは、LoadLibraryEx 関数で 1 つ以上のLOAD_LIBRARY_SEARCH フラグを使用して、検索順序を指定できます。 アプリケーションでは、SetDefaultDllDirectories 関数で LOAD_LIBRARY_SEARCH フラグを使用して、プロセスの DLL 検索順序を確立することもできます。 アプリケーションでは、 AddDllDirectory 関数または SetDllDirectory 関数を使用して、プロセス DLL 検索順序の追加ディレクトリを指定できます。
検索されるディレクトリは、 SetDefaultDllDirectories または LoadLibraryEx で指定されたフラグによって異なります。 複数のフラグを使用する場合、対応するディレクトリは次の順序で検索されます。
- DLL (LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR) を含むディレクトリ。 このディレクトリは、読み込まれる DLL の依存関係のみを検索します。
- アプリケーション ディレクトリ (LOAD_LIBRARY_SEARCH_APPLICATION_DIR)。
- AddDllDirectory 関数 (LOAD_LIBRARY_SEARCH_USER_DIRS) または SetDllDirectory 関数を使用して明示的に追加されたパス。 複数のパスが追加されている場合、パスの検索順序は指定されません。
- システム ディレクトリ (LOAD_LIBRARY_SEARCH_SYSTEM32)。
アプリケーションが LOAD_LIBRARY_SEARCH フラグを指定して LoadLibraryEx を呼び出したり、プロセスの DLL 検索順序を確立したりしない場合、システムは標準の検索順序または代替検索順序を使用して DLL を検索します。
関連トピック