::Hikaru's blog

調べたこと, 考えたことをメモ.
<< October 2017 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 >>

スポンサーサイト

一定期間更新がないため広告を表示しています

- | permalink | - | -
<< Visual Studio .NET 正規表現を使った置換 | main | 数値をカンマ区切りの文字列に変換する >>

DLLの遅延読み込みをフックする

GetProcAddressは面倒だ、かといってスタティックリンクは自由度が低い上、例外のハンドリングが難しい・・・と頭を抱えるあなたに遅延読み込みのフックをお勧めします。
遅延読み込みとフックを利用すればGetProcAddressを使わなくて良い上に、自由度が高く、また、ヘルパ関数を使えば例外のハンドリングも簡単に行うことができます。
フックするためにはフックプロシージャを定義し、登録します。
登録するには2つのグローバル変数にフックプロシージャのアドレスを設定するだけです。
PfnDliHook __pfnDliNotifyHook2 = MyDliHook;
PfnDliHook __pfnDliFailureHook2 = MyDliHook;
NotifyとFailureにそれぞれフック関数を設定できますが、通常は同一のプロシージャで処理します。

MyDliHookを見てみましょう。
// 遅延読み込み用のヘルパ関数からコールバックされる。 FARPROC WINAPI MyDliHook( unsigned int dliNotify, PDelayLoadInfo pdli) { FARPROC pRet = NULL; switch (dliNotify) { case dliStartProcessing: // ヘルパ関数が起動した時。 break; case dliNotePreLoadLibrary: // ヘルパ関数がLoadLibraryを呼び出す直前。 break; case dliNotePreGetProcAddress: // ヘルパ関数がGetProcAddressを呼び出す直前。 break; case dliFailLoadLib: // ヘルパ関数がLoadLibraryの呼び出しに失敗した時。 break; case dliFailGetProc: // ヘルパ関数がGetProcAddressの呼び出しに失敗した時。 break; case dliNoteEndProcessing: // ヘルパ関数の処理が終了した時。 break; default: return NULL; } return pRet; }
遅延呼び出しヘルパ関数から上記のタイミングでコールバックされます。
フックプロシージャで有効なHMODULEまたはFARPROCを返してやると遅延呼び出し処理の振る舞いを変えることができます。
例えば…
case dliNotePreLoadLibrary: if (::SHGetSpecialFolderPathA(NULL, szPath, CSIDL_PROGRAM_FILES_COMMON, FALSE)) { ::PathAddBackslashA(szPath); lstrcatA(szPath, pdli->szDll); pRet = (FARPROC) ::LoadLibraryA(szPath); } break;
これで自分の好きな場所(CSIDL_PROGRAM_FILES_COMMON)からDLLをロードさせることができます。


以上でDLLの遅延読み込みをフックすることができました。
DLLの遅延読み込みをより便利に使うためのヘルパ関数を紹介します。
__HrLoadAllImportsForDll(LPCSTR szDll);
DLLからすべてのインポートを読み込みます。
例えば、プログラムの開始時に__HrLoadAllImportsForDllを呼び出すと、その他の実際の呼び出し時に例外処理をする必要がなくなります。
szDllは'/DELAYLOAD'で指定したDLLのファイル名と、大文字と小文字の区別も含めて完全に一致しなければなりません。
__FUnloadDelayLoadedDLL2(LPCSTR szDll);
遅延読み込みを行ったDLLをアンロードします。
リンカに'/DELAY:UNLOAD'の指定が必要です。
szDllは'/DELAYLOAD'で指定したDLLのファイル名と、大文字と小文字の区別も含めて完全に一致しなければなりません。

サンプルコード: delayhk.cpp

MSDN: リンカによるDLLの遅延読み込み
Visual C++ | permalink | comments(4) | trackbacks(0)

スポンサーサイト

- | permalink | - | -

この記事に対するコメント

DLLの関数をたくさんimportしないといけない場合には便利そうやなー。
でも自分でDLLを作るときは関数にせずにCOMにするかな。
akihiro | 2006/04/07 1:00 PM
COMは便利やね。

サンプルコードを作りました。
hikaru | 2006/04/07 4:00 PM
あれ、たまにページのレイアウトが崩れる?
F5でリロードすると直るみたい。なぞ。
hikaru | 2006/04/07 4:06 PM
サンプルのリンク切れてますよ
通りがかり | 2009/09/27 3:12 PM
コメントする









この記事のトラックバックURL
http://hikarukaru.jugem.cc/trackback/83
この記事に対するトラックバック