小池啓仁 ヒロヒト応援ブログ By はてな

小池啓仁(コイケヒロヒト)の動画など。

小池啓仁 ヒロヒト応援ブログ By はてな

PerlでWindowsAPIをコールする(DynaLoader編)

昨日、『Perl で Win32::API プログラミング入門』リンクメモでのお約束(暇な時にソース解析)の前半部だけをソース解析してみました。

今日は後半部のソース解析をしてみます。
しかし、実力不足で10%ぐらいしか分からなかったです。

#!/usr/bin/perl
use DynaLoader;
sub GetProcAddress {
	my ($DLL, $API) = @_;
	my $path = "$ENV{SystemRoot}\\system32\\$DLL";
	my $libref = DynaLoader::dl_load_file($path);
	pack "L", DynaLoader::dl_find_symbol($libref, $API);
}
my $x86 = ""
. "h\0\0\0\0"
. "h" . pack("P", "Message")
. "h" . pack("P", "Hello, World!\n")
. "h\0\0\0\0"
. "\xb8" . GetProcAddress("user32.dll", "MessageBoxA")
. "\xff\xd0" # call eax
. "\xc3"     # ret
;
DynaLoader::dl_install_xsub("X",unpack"L",pack"P",$x86);&X;
http://d.hatena.ne.jp/TAKESAKO/20090324/1237879559

なので、以下のソース解析のコメントには大部憶測で書いています。

  • GetProcAddressサブルーチンは、引数にライブラリ名とAPI名を指定してAPIのアドレスをゲットして返します。
  • 文字列『$x86』は、アセンブライメージ(?)を展開しているようです。
  • "h\0\0\0\0"は、API(MessageBoxA)の第4引数(OKボタン等)に対応している感じです。
  • "h" . pack("P", "Message")は、API(MessageBoxA)の第3引数(キャプションタイトル)に対応している感じです。
  • "h" . pack("P", "Hello, World!\n")は、API(MessageBoxA)の第2引数(メッセージ)に対応している感じです。
  • "h\0\0\0\0"は、API(MessageBoxA)の第1引数(親ハンドル)に対応している感じです。
  • "\xb8" . GetProcAddress("user32.dll", "MessageBoxA")は、API(MessageBoxA)のアドレスを展開している感じです。
  • "\xff\xd0"は、APIを実行する命令が書かれている感じです。
  • "\xc3"は、APIのリターンになにか関係がある感じです。
  • DynaLoader::dl_install_xsub("X",unpack"L",pack"P",$x86);は、"X"で示す名前の新しいPerlの外部サブルーチンを関数へのポインタを使って生成します
  • &X;は、生成したサブルーチンの実行です。

しかし、以下の記述には悩まされました。

dl_install_xsub("X",unpack"L",pack"P",$x86);

普通、dl_install_xsubの引数は2つまたは3つなのですが、上記は4つあります。
しかし、実はよく見ると2つなのです。
第一引数は、"X"で外部サブルーチン名になります。
第二引数は、『unpack"L",pack"P",$x86』なのです。
そう、『"P",$x86』はpackの引数で、『"L",pack"P",$x86』はunpackの引数なのです。
ちなみに、処理は、文字列($x86)のポインタ指定でバイナリ構造体にして、これを符号なしlong値にしています。


えーと、分かったような説明をしていますが、私自身10%も分かっていませんのでご了承ください。