DLLをロードできない理由


おかP  2023-07-28 05:19:16  No: 151047  IP: [192.*.*.*]

回答しにくいとは思いますが。
環境 Delphi 2007 、公開済みのパッチは、だいたい適用済みのはず

症状 特定のDLLで、初回のみロードでき、2回目はロードできない。

7-zip32.dll を利用して、zip書庫内のファイルを確認・展開し、読み込みするプログラムがあります。
1)ファイル選択ダイアログで、zip書庫を選択すると、内容チェックのため一回中身を展開(※1)します。
  DLLは、一度アンロードします(FreeLibrary実行)
2)実際に取り込み時点で、再度展開(※2)し、取り込みを行います。

※1でのLoadLibraryは成功し、中身は展開できる。
※2の時点で、LoadLibraryが0を返します。
 GetLastError→126:指定されたモジュールが見つかりません

ただし、本家(http://akky.xrea.jp/)のDLLでは問題なく、改造版(http://frostmoon.sakura.ne.jp/)のDLLでのみ発生。

動作的には、使い方の問題ではなくDLLに問題ありそうですが、原因を特定するため、なにか調査すべき点とかありますか?
新規プロジェクトで、指定DLLをロード・アンロードするだけのようなテストプログラムまでは作っていません。

ただ・・・そこにあるのに見つかりませんって、どうなんでしょうね( ´-`)
時間があまりとれないので、のんびり対応になります。

編集 削除
take  2023-07-28 06:21:33  No: 151048  IP: [192.*.*.*]

LoadLibraryとFreeLibraryの部分だけでもどう記述しているのかわからないと回答が出来ません

あと解放してわざわざロードし直すのはなにか理由があるのでしょうか?

7-zip32.dll でしたら
圧縮展開をクラスとしてカプセル化して
CreateでLoadLibrary
DestroyでFreeLibrary
とするかと思うので生成と破棄を繰り返すのがよくわかりません

もし本当にLoadLibraryとFreeLibraryを繰り返してエラーが出るなら
それぐらいはデバッグプログラムを書くのが手っ取り早いと思います

編集 削除
AAAAA  2023-07-28 07:22:16  No: 151049  IP: [192.*.*.*]

DLL を PAHT 付きで指定したらどうなる?

編集 削除
HFUKUSHI  2023-07-28 12:31:43  No: 151050  IP: [192.*.*.*]

FreeLibraryは成功しているのでしょうか?

編集 削除
おかP  2023-07-31 00:44:03  No: 151051  IP: [192.*.*.*]

回答感謝です

takeさん
> 7-zip32.dll でしたら
> (略)
> とするかと思うので生成と破棄を繰り返すのがよくわかりません
前任者が作ったのか、ネットで拾ってきたものかはわかりませんが、
そのようになっています。ただ、圧縮展開のアーカイバではないので、
必要なタイミングで生成・破棄するだけのことです。
今回は、1回で済むことを2回やっているのが問題だと仰るのかもしれませんが
そのように変更したとしても、時間をおいて、2回目にzipを展開するタイミングで
再度インスタンスを生成すれば同じようにエラーになります。
それとも、初回ロードしたら「インスタンスを保持し続けるべき」なのでしょうか?

AAAAA さん
強制的に、DLLのフルパスを指定すると、問題なく動作しました。

HFUKUSHIさん
FreeLibraryのリターンは見ていませんでしたが、確認できるようにしたところ
True で返ってきていました。

takeさんの仰るとおり、一応ソースを抜粋しますが、どこかに介入する要素があるのでしょうか?
-----
const
  s7zip32dllName = '7-zip32.dll';
-----
var
  h7zip32dll: THandle;
  s7zip32dllPath: String;
-----
  //ロード:DLLをフルパス指定できるようにはなっていました
  if s7zip32dllPath = '' then begin
    //フルパス指定なしであればdll名だけでロード
    h7zip32dll := Windows.LoadLibrary(s7zip32dllName);
  end
  else begin
    //フルパス指定あるので、そのパスを使ってロード
    h7zip32dll := Windows.LoadLibrary(PChar(s7zip32dllPath));
  end;
  // if h7zip32dll = 0 then begin
  //  GetLastError→126:指定されたモジュールが見つかりません
-----
  //アンロード:Resultはノーチェックでしたが、修正
  if not Windows.FreeLibrary(h7zip32dll) then begin
    //ここは通りませんので、失敗はしていない様子
-----

DLLロードの検索順序は、アプリケーションが読み込まれたディレクトリが
最優先だと思っていましたし、そのように記載があるのですが。
例えばココ
https://support.microsoft.com/ja-jp/topic/dll-%E3%83%97%E3%83%AA%E3%83%AD%E3%83%BC%E3%83%89%E6%94%BB%E6%92%83%E3%82%92%E9%98%B2%E3%81%90%E3%81%9F%E3%82%81%E3%81%AB%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA%E3%81%AE%E8%AA%AD%E3%81%BF%E8%BE%BC%E3%81%BF%E3%82%92%E3%82%BB%E3%82%AD%E3%83%A5%E3%83%AA%E3%83%86%E3%82%A3%E3%81%A7%E4%BF%9D%E8%AD%B7%E3%81%99%E3%82%8B-d41303ec-0748-9211-f317-2edc819682e1

DLL hijacking攻撃の対策の何かなのか?
ただ、理屈・仕様がわからないのであれば、AAAAAさんの仰るとおり、
フルパス指定で回避が解決策でしょうか。

編集 削除
take  2023-07-31 01:46:12  No: 151052  IP: [192.*.*.*]

短いサンプルを提示して頂きましたが
1.そのサンプルでLoadLibrary、FreeLibrary、LoadLibraryと処理をすると現象は再現出来ますか?

> DLLロードの検索順序は、アプリケーションが読み込まれたディレクトリが最優先だと思っていましたし

7z.dll文字化け対策版を見るとDLLはシステムディレクトリに入るようですね
で、それを文字化け対策版のDLLで上書きする感じなのかな?

2.必要と思われるDLLを全て実行時のEXEがあるフォルダにコピーしてから実行した場合はどうなりますか?

>フルパス指定で回避が解決策でしょうか

一時的に自身の環境でのみ実行でよければ大丈夫でしょうけど
他のPCに移行すると動かなくなる可能性が高いですね

編集 削除
AAAAA  2023-07-31 03:23:38  No: 151053  IP: [192.*.*.*]

>強制的に、DLLのフルパスを指定すると、問題なく動作しました
なので DLL 内で CD を変えてると思います。

DLL ロード前の CD を保存しておいて 解放後に元に戻せは良いと思います

編集 削除
AAAAA  2023-07-31 03:26:03  No: 151054  IP: [192.*.*.*]

DLL を SYSTEM32 にとかに入れておいても動作すると思う。

編集 削除
おかp  2023-07-31 05:35:58  No: 151055  IP: [192.*.*.*]

全部検証できていないところ恐縮ですが、下記の順序が正しいとすると

1)アプリケーションが読み込まれたディレクトリ
2)システム ディレクトリ
3)16 ビット システム ディレクトリ
4)Windows ディレクトリ
5)現在の作業ディレクトリ (CWD)
6)PATH 環境変数に設定されているディレクトリ

お二方のレスを読んで、最初の質問読み直しましたが、1)の場所に置いてあるって書いてない(大失態)
結果的に後出しになってすいません。実行ファイルと7-zip32.dll は、同じディレクトリ内に置いてあります。
それでも、上記のようにロードできなくなります。

現状確認したこと
○ 2)の場所 C:\Windows\SysWOW64 に置いたところ、フルパスでなくても動作する (AAAAA  さん  No: 151054)
○ 実行ファイルと7-zip32.dll は、同じディレクトリ内に配置し、
 単純にLoadLibrary、FreeLibrary、LoadLibrary... では、発生しません。(take  さん  No: 151052)

混乱してわからなくなりました
I) DLLの検索順序 1)は、いわゆるカレントディレクトリ?
   ずっと 5) のことをカレントディレクトリ と思っていましたが、そもそもそれが間違い・・・なんですかね?
II) なんらかの書庫操作を行うと発生するが、どれか調査できていない。


しばらく検証から離れるため、回答遅くなります。

編集 削除
AAAAA  2023-07-31 10:35:49  No: 151056  IP: [192.*.*.*]

ちょっと試したけど CD は関係ないみたいです

編集 削除