前回「タスクバーのアイコンの列挙方法は?」を質問したものです。
http://madia.world.coocan.jp/cgi-bin/Vcbbs/wwwlng.cgi?print+200711/07110886.txt
この質問のサンプルソースから素朴な疑問があります。
それはカレントのプロセス以外でツールバーなどの情報を取得するときは
なぜローカル変数(構造体)ではなく、取得しようとしている他のプロセス上に
メモリ領域を VirtualAllocEx で確保してその領域に対して SendMessage を
行わないといけないのでしょうか?
前回のタスクバーの列挙方法で調べたときに VB、C のサンプルを見つけて
VB のカテゴリ(同サイト掲示板)でローカル変数では取得できないようなことが
書かれていました。
> 前レスにも書いたようにそのままTB_GETRECTやTB_GETBUTTONを行っても
> 別プロセスで確保されたメモリにはアクセスできないようです。
http://madia.world.coocan.jp/cgi-bin/VBBBS2/wwwlng.cgi?print+200512/05120034.txt
また ReadProcessMemory、WriteProcessMemory 関数を MSDN で調べたら
「デバッグ」の関数のカテゴリにありました。
この関数は「デバッガ」を作るときに使われそうな関数な気がしますが、
普通に使っても問題ないのでしょうか?
この質問はカレントのプロセス意外はなぜ VirtualAllocEx で確保した
メモリ領域を使わなければいけないのか?
という疑問です。
Windows OS の内部に詳しい人がおりましたら教えて下さい。
(プロセス間通信とか関係ありますか?)
簡単に書くと,プロセス境界をまたぐために,アドレスだけ渡しても別のメモリを参照してしまうからです。
知っての通り,Win32環境ではプロセスごとに別のメモリ空間を持っています。
そのため,メッセージの送信側と受信側が異なるプロセスの場合,ポインタを送受信しても,正しく情報は伝わりません。
最悪,受信側がクラッシュしてしまいます。
# スタックフレームを破壊した場合など。
で,今回のように他のプロセス内の情報を得るためにポインタが必用になる場合ですが,受信側のプロセス内に情報を受け渡すための領域があればよいわけです。
そうすれば,メッセージの送信側と受信側は異なるプロセスであっても,ポインタは受信側プロセス内の領域を示すためのものですから,受信側は問題なく読み書き出来ます。
で,その受信側プロセス内にメモリ領域を確保するための手段がVirtualAllocExであり,そこへ送信側プロセスが読み書きするための手段がReadProcessMemory, WriteProcessMemoryになります。
デバッグカテゴリにあるのは,これを利用するのは通常デバッガくらいだからでしょう。
# 他のプロセスのメモリを弄るなんてのは危険な行為。
このあたりは,絵を描いてみると理解の助けになるかもしれません。
ちなみに,WM_GETTEXTなどの一部のメッセージに限り,Windowsがそのあたりをうまいこと処理してくれます。
YuOさんの分かりやすい解説を読み納得しました。
> 知っての通り,Win32環境ではプロセスごとに別のメモリ空間を持っています。
よく考えたらプロセスが異なるのでローカル変数の領域に…は無理があるね。
この質問をした後に薄っすら気づきました。
> その受信側プロセス内にメモリ領域を確保するための手段がVirtualAllocExであり…
受信側プロセス内にメモリ領域があればよいなら、受信側プロセスからカレントヒープ領域を
取得して HeapCreate、HeapAlloc でも理論上は可能ですよね。この方法もできますか?
> 送信側プロセスが読み書きするための手段がReadProcessMemory, WriteProcessMemoryになります。
なるほど。この関数はプロセス境界を越えても読み書きが出来るんですね。
> # 他のプロセスのメモリを弄るなんてのは危険な行為。
確かに危険な行為になりそうですね。
システムは破壊(低下)につながりそ〜う。怖いゃ。
> ちなみに,WM_GETTEXTなどの一部のメッセージに限り,Windowsがそのあたりをうまいこと処理してくれます。
これは特別なんですね。
スッキリ理解しました。
ありがとうございました。
> 受信側プロセス内にメモリ領域があればよいなら、受信側プロセスからカレントヒープ領域を
> 取得して HeapCreate、HeapAlloc でも理論上は可能ですよね。この方法もできますか?
MSDNで引数調べたら無理だね。
ボケてたよ。
ツイート | ![]() |