EternalWindows
DLL / DLLの検索

LoadLibraryにロードしたいDLLを指定するとき、 そのDLLの名前をフルパスで指定した場合は原則そのDLLがロードされることになりますが、 ファイル名だけを指定した場合は、いくつかのディレクトリを検索ディレクトリとして、 指定したファイル名が探されることになります。 次に、検索される順番を示します。

1, EXEファイルが含まれているディレクトリ
2, プロセスのカレントディレクトリ(又は、SetDllDirectoryで指定したパス)
3, Windowsシステムディレクトリ
4, Windowsディレクトリ
5, 環境変数PATHで指定されたディレクトリ

なお、Windows XP以降では次のレジストリキーの値が1であるとき、 2のカレントディレクトリは3と4の後に検索されます。

HKLM\System\CurrentControlSet\Control\Session Manager\SafeDllSearchMode

SetDllDirectoryという関数は、DLLを検索するときだけに使うディレクトリを設定します。 このDLLディレクトリはデフォルトではNULLであり、 そのときはカレントディレクトリが検索されることになります。 DLLディレクトリは、GetDllDirectoryで取得することができます。 なお、SetDllDirectoryやGetDllDirectoryは、WindowsXP SP1から登場した関数です。

DLLのロードには、EXEのインポートセクションに書かれたDLLを起動時にロードするという暗黙的リンクがありますが、 この時における検索の順番もLoadLibraryと同様になります。 ただし、どちらの場合においても、KnownDLLsとして登録されているDLLに関しては、 原則system32フォルダのみが検索されることになっています。 KnownDLLsには、kernel32.dllのようなシステムの一部といえるDLLが登録されており、 次のレジストキーに列挙されています。

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs

上記キーの一部を次の表に示します。

名前 データ
advapi32 advapi32.dll
DllDirectory %SystemRoot%\system32
kernel32 kernel32.dll
user32 user32.dll

kernel32.dllを次のようにロードしたとします。

LoadLibrary(TEXT("kernel32.dll"));

このように拡張子を付けてKnownDLLsを指定した場合、 拡張子は内部で取り除かれ、その値と一致するエントリが存在するかどうか調べられます。 エントリが存在しない場合は通常の検索規則が用いられますが、 存在する場合はDllDirectoryキーで示されるディレクトリが検索ディレクトリになります。 このディレクトリでDLLが見つからなかった場合はその時点で失敗となり、 GetLastErrorはERROR_FILE_NOT_FOUNDを返します。 拡張子を付けずにKnownDLLsを指定した場合は、通常の規則で検索されます。 ちなみに、特定のDLLをKnownDLLsとして除外したい場合は、 そのDLLのエントリを削除するのではなく、 次のレジストリキーのExcludeFromKnownDllsというエントリにDLLの名前を指定するとよいでしょう。

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager

ExcludeFromKnownDllsにDLLの名前を指定して再起動すれば、 そのDLLはKnownDLLsとして扱われなくなります。

DLLのリダイレクト

DLLのリダイレクトとは、DLL本来の検索アルゴリズムより優先されるメカニズムであり、 特定のDLLをアドレス空間にマッピングさせることを意図しています。 ここでは、localファイルによるDLLのリダイレクトについて説明します。 まず、sample.exeというEXEファイルがあったとして、 そのEXEファイルと同じディレクトリにsample.exe.localというファイルを用意します。 localファイルの名前は、このようにEXEファイルの拡張子を含む名前に.localを連結したもので、 ファイルの中身自体は考慮されないので空でかまいません。

localファイルが存在する場合、アプリケーションの暗黙的リンク及び明示的リンクにおいて、 まずこのlocalファイルが存在するディレクトリが検索されるようになります。 強力なことに、LoadLibraryにフルパスのファイル名を指定した場合でも、 localファイルと同じディレクトリにそのDLLと同じファイル名のDLLがあれば、 そのロードがされることになります。 localファイルによるDLLのリダイレクトはKnownDLLsにも効果がありますが、 EXEファイルがマニフェストファイルを含む場合は例外となるように思えます。 マニフェストファイルは、もう1つのDLLのリダイレクトの方法として機能しますが、 これについては別の節で説明する予定です。 なお、localファイルを利用したリダイレクトはサイドバイサイド共有とも呼ばれ、 localファイルと同じディレクトリに配置したDLLはサイドバイサイドコンポーネント呼ばれることがあります。



戻る