マネージド/ネイティブ混合DLLに敗北中
私の知り合いのプログラマさんが C# 使いなんですが、野暮用により他のプロセスへのフックが必要になったらしいのです。 C#で。
正直な所、中々無謀な面があるんじゃ…なんて思ったらやっぱり無理なようで…^^;
んじゃぁ、C++/CLI でラッパーっぽいの書いてみるかー と思い立った訳です。 …が、私自身まだ C++/CLI なんてやった事無いわ、.NET の概念なんてまだ知らんよ? という所でして、色々試行錯誤しています。(==現在進行形)
まだ出来て無いんですが^^;一応簡単ながら現状をまとめてみる。
フックする時にデリゲート渡して、そいつをコールバックしよう。
ネイディブのフックプロシージャーが呼ばれたら、デリゲートをコールバックして C# コードへ飛ぼう!…と、最初に思い立ったんですが、色々問題点に気づく。
とりあえず、フックするプロセスでデリゲート渡しても、侵入先のプロセスでつかえない時点でアウト。int とか純粋な型であれば、DLLの共有セクションを利用できますが、デリゲートとなるとそれも不可能。つか、できた所でそのデリゲートがさしてる関数を呼ぼうとしたところでアウトな気がする。
なので、C++/CLIのフック用DLLをプロセスに注入した時、そのDLL が自分で C# のクラスライブラリを gcnew させるようなコードにしようとした…のですが…
DllMain からマネージドコードを呼び出せない
Download Visual Studio 2005 Retired documentation from Official Microsoft Download Center
ぎゃふん。
つまり、プロセスに侵入した時に DllMain にて DLL_PROCESS_ATTACH / DLL_PROCESS_DETACH で分岐して、C# で書かれたクラスライブラリを gcnew, 破棄 しようかと思ったんですがそれも無理。
つかついでに、DllMain で他のDLLを読むこともやっちゃいけない事を思い出したよ…。アカンねぇ…。
グローバルに配置…?
namespace cpp_hook {; typedef gcroot<cs_hook_dll::Class1^> TCSHookClass; TCSHookClass g_pcCSHookClass = gcnew cs_hook_dll::Class1(); };
仕方ないのでこんなコードも書いてみましたが、どうも落ちる………というかですね。
マネージドコードが呼び出せない。
#pragma managed void CallWndProcManaged(int nCode, WPARAM wParam, LPARAM lParam) { // System::Media::SystemSounds::Hand->Play(); ::MessageBeep(0); } #pragma unmanaged //// hook proc LRESULT CALLBACK CallWndProc(int nCode, WPARAM wParam, LPARAM lParam) { CWPSTRUCT* pcw = (CWPSTRUCT*)lParam; if(pcw->message == WM_CREATE) { CallWndProcManaged(nCode, wParam, lParam); } return ::CallNextHookEx(NULL, nCode, wParam, lParam); }
CallWndProcManaged なんていう、自前のマネージド関数を用意してみましたが、この呼び出しですら落ちました… どうやら ぬるぽ をコールしてるような感じ。
…でまぁ、確かに思うところはあるんです。 マネージドコード / .NET Framework っていつ初期化してるの? って。 …いやまぁ、そもそも初期化が必要なのかわかりませんが、大きなラインタイムだから必要なんじゃ…ないの?^^; 勝手にやってくれるのかしら…?
C# のような最初から中間コードなアプリケーションであれば、起動時にいろいろな初期化を行なってるでしょうから、ネイディブ / CLR 混合なDLLを注入したとしても何となく動きそうですケド(ぉ*1、Win32ネイディブなプロセスに対して混合 DLL 注入した場合は……なんかヤヴァそうな感じ。
ただ、メモ帳のプロセスにアタッチしながら混合DLLを注入してみましてみた所、一応 .NET Frameworks は読み込みをしているような情報がアウトプットウィンドウに表示されましたが…… んー、どうなんだろう…
引き続き資料を漁る……
しかし今回弄ってみて、やっぱり C++/CLI は面白そうなニュアンスは受け取れました。 マネージドとネイディブ上手く両立できれば、低レベルな面でちょっとごにょごにょしつつ 高レベルで便利なフレームワーク使えることになりますからねー。