DLL 検索順序 (1)

単純な真理として,絶対パスで指定した場合はその DLL がロードされます.Side-by-Side の介入の余地もありません(追記2006-07-16: .local による DLL/COM リダイレクションを使用すると,絶対パス指定の LoadLibrary に介入できることに注意).例えば Office 2003 の話ですが,exe ファイルと同一ディレクトリに GDIPlus.dll が存在して,こいつはバージョン 6 系です.通常の SxS 版の GDIPlus.dll はバージョン 5 系なので,Office 2003 は単純に絶対パスを指定して GDIPlus.dll をロードしているのではないか,というのが私の予想です.
一方,以前軽く触れたことが(id:NyaRuRu:20040614#p3)ありますが,パスを完全に指定せずに DLL を指定したときの検索順序は非常に複雑です.実際,以前紹介した URL に書かれている内容は古いもので,最新の正しい情報を知るためには別の箇所を見る必要がありました.ただ嫌らしいことに MSDN の日本語ヘルプは内容が最新ではありません.というわけで英語版を見てみましょう.
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/loadlibrary.asp?frame=true
特に Remarks 以下にご注目下さい.まずは簡単のため非 SxS DLL を考えることにしましょう.32bit DLL の検索順序ですが,実は Windows XP Service Pack 1 または,Windows 2000 Service Pack 3 以降 (追記:Windows 2000 SP3 の方はデフォルト設定では無いかもしれません) では,DLL の検索順序が変更されています.以前の Windows ではカレントディレクトリは 2 番目の検索順序だったのが,最近では以下のように 5 番目に後退しています.

  1. アプリケーションの exe ファイルが存在するディレクトリ
  2. システムディレクトリ
  3. 16-bit システムディレクトリ
  4. Windows ディレクトリ
  5. カレントディレクトリ
  6. 環境変数 PATH に設定されてたディレクトリ

この変更の背景については Windows Server 2003 について書かれた以下の文章でも触れられています.

DLL Search Order Has Changed

No longer is the current directory searched first when loading DLLs! This change was also made in Windows XP SP1. The default behavior now is to look in all the system locations first, then the current directory, and finally any user-defined paths. This will have an impact on your code if you install a DLL in the application's directory because Windows Server 2003 no longer loads the 'local' DLL if a DLL of the same name is in the system directory. A common example is if an application won't run with a specific version of a DLL, an older version is installed that does work in the application directory. This scenario will fail in Windows Server 2003.

The reason this change was made was to mitigate some kinds of trojaning attacks. An attacker may be able to sneak a bad DLL into your application directory or a directory that has files associated with your application. The DLL search order change removes this attack vector.

The SetDllDirectory function, also available in Windows XP SP1, modifies the search path used to locate DLLs for the application and affects all subsequent calls to the LoadLibrary and LoadLibraryEx functions by the application.

後方互換性を失うことを覚悟した変更ですが,実際この変更によって Outlook が誤ったバージョンの GAPI32.DLL をロードしてしまうという事例も発生しています.
http://support.microsoft.com/default.aspx?scid=kb;ja;833274
以前の検索順序及び以前の順序に変更する方法や,SetDllDirectory による DLL 検索パスへの追加については Dynamic-Link Library Search Order を参照してください.