HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2014
0606
tds12hspでグローバルフック8解決


tds12

リンク

2014/6/6(Fri) 23:35:33|NO.62328

hspでグローバルフック(CALLWNDPROC)をするにはどうしたらよいでしょう。
検索してみたところ、特定のメッセージのみをフックするプラグインはあったのですが、
作ろうと思っているものは、すべてのメッセージをフックする必要があるので
自作しようと考えました。

自分で分かっていること・考えたことは、
・グローバルフックをするにはdllを作る必要がある。
・hspでdllを作ることはいまのところできない。
・vcでdllを作る。
・よくあるdllの場合にhsp側に処理を移すためにはSendMessageしなければならず
_メッセージフックの場合、自分のウィンドウを処理できないなど都合が悪いので
_hspのプラグインとして作り、code_getlb,code_callを使う
・フック関数内の変数は共有領域で初期化しなければならない。
・statはHSPCTX型、code_callはHSPEXINFO型、などの変数も共有領域で初期化する。
・hsp側では、mesboxへの更新をいちいちしていては間に合わないので、
_メッセージ取得時は文字列の更新のみを行い、SetTimerなどで1秒ごとに更新する。
です。

自分で作ってみた結果は、
・「〜の命令が〜のメモリを参照しましたが〜になることはありませんでした。」
_というようなメッセージが表示されてしまう。
・うまくいっても、応答なしになってしまう。
・ほかのプログラムまで終了してしまう。
です。

これは、可能なのでしょうか。
プラグイン側のみの共有領域では足りないのでしょうか。
SendMessageのほうがcode_callよりも良いのでしょうか
どのように組めばよいのでしょうか。

hspを超えたむずかしい質問かもしれませんが、どうかよろしくお願いします。

スクリプトのアップロードは必要でしょうか。必要であれば検討します。



この記事に返信する


774

リンク

2014/6/7(Sat) 00:20:44|NO.62330

プラグイン作成はさっぱりなのですが
結果からはメモリの参照先違いか領域オーバーぽいですね。
DLL内でメッセージログを作成している等でなければ単純な領域不足は考えにくそうです。

とりあえず思い付く可能性としては
・code_callがgosubジャンプの為、HSPから処理が処理が戻る前に次のメッセージが来て
 処理が追いついていない
・code_callによるメッセージ自体も捕獲してしまっている為
 HSPで言うスタックエラーに陥っている
辺りでしょうか…



tds12

リンク

2014/6/7(Sat) 18:39:14|NO.62346

774さん
>>・code_callがgosubジャンプの為、HSPから処理が処理が戻る前に次のメッセージが来て
>> 処理が追いついていない
ありがとうございます。
gosubジャンプの負荷を減らすためターゲットのウィンドウを一つに絞ることにしました。
また、プラグイン内で、おそらくすべてのグローバル変数を共有領域で初期化することにしました。
これで「〜の命令が〜のメモリを参照しましたが〜になることはありませんでした。」
というようなメッセージが表示されてしまうことはなくなり、
さらに、hspが応答なしになることもなくなりました。
しかし、今回はターゲットをhsed3.exeのメインウィンドウにしたのですが、
実行した途端に「HSPスクリプトエディタは動作を停止しました」というメッセージが表示され
終了されてしまいました。それでも今回は、いくつものプログラムが終了されるという事態は
防げるようになりました。

(まだ解決したわけではないので、よろしければどうかご回答お願いします。)



774

リンク

2014/6/7(Sat) 21:30:15|NO.62348

もしプラグインを使用するスクリプトをエディタからテスト実行してるのだとすれば
デバッグ用の監視と相互参照のようになっていたりはしないでしょうか。

1.エディタのメッセージをプラグインが捕獲しプログラムに送る
2.プログラムのメッセージをデバッグ用DLLが捕獲しエディタに送る
1へ戻る…みたいな感じで。

ウロ覚えなのですが、こういったプログラムですとPostMessageの方が良いかも知れません。
SendMessageは相手側の応答を待つ間停止するので都合が悪い、とかだった気がします。
HSP用プラグインとしてどう組み込むかは…すいません解りません。
(ひょっとしてcode_setpcがそれに当たるのでしょうか



tds12

リンク

2014/6/7(Sat) 22:17:46|NO.62350

774さん
ありがとうございます。

デバッグによる異常発生は思いつきませんでした。
しかし、実行ファイルにしてもやはり駄目でした。

code_callは、ウィンドウメッセージを使わないので、関係ないようです。
(現在はSendMessageは使っていません。)
フックは戻り値が必要なため、goto(code_setpc)では、値を返せないので
使えず、PostMessageも同じようです。



774

リンク

2014/6/8(Sun) 23:41:45|NO.62370

>しかし、実行ファイルにしてもやはり駄目でした。
ターゲットがスクリプトエディタの場合にのみ駄目なのでしょうか?
それとも全般的にフックとして機能していないという事でしょうか?
とりあえず前者寄りで考えてみます。

念の為にお伺いしますが、フックしたメッセージを流していないという事は無いですよね?
具体的には return CallNextHookEx(〜); の不備ですね。
もしこれならスクリプトエディタに不具合が出る原因としても一応辻褄は合いそうです。
他の要因としては、ターゲットを1つに絞ってすら処理が追いついていない…でしょうか。
でもメッセージが停滞してるとすれば最初のようにもっと大域に影響出てそうですし…謎です。

>フックは戻り値が必要なため
すみません、この辺りがよく解りません。
例えば何らかの書き換え・監視だとして

〜〜〜〜 if(対象がターゲットウィンドウ){ PostMessage(HSPにメッセージ内容を情報として送信); if(特定のキー入力など){メッセージ内容の書き換え;} } return CallNextHookEx(〜);
例えばHSP側でフック後の処理をするとして

/* [DLL側] */ 〜〜〜〜 if(フックするメッセージ){ PostMessage(HSPにメッセージ送信して呼び出し); return 0; //元のメッセージは握り潰す } return CallNextHookEx(〜); /* [HSP側] */ 〜〜〜〜 oncmd *フック処理, DLLからの呼び出しメッセージ 〜〜〜〜 *フック処理 //ポインタ渡しなどでメッセージ内容を貰って処理 //改めてメッセージ送信する場合、それを再捕獲しない措置が必要
(書き換え内容やフックするメッセージは事前にDLLに登録
といった感じで、HSPからの戻り値は特に必要無さそうな気がします。
ただ、上記は「HSPプラグイン」であることを全く考慮してませんので
その辺の兼ね合いだったりするのでしょうか。



MillkeyStars

リンク

2014/6/12(Thu) 12:49:49|NO.62404

CallWndProc の呼び出しプロセスは、相手方という事を理解してますか?

自身が HSPDLL.DLL だとして、システムから explorer.exe にメッセージが送信される場合において、CallWndProc が呼び出された場合、実行プロセスは、explorer.exe 内の CallWndProc となります。
なので、メモリ空間内のアドレスが違う為、ctx->stat などに値を代入した際に、メモリアクセスエラーを引き起こします。

また、code_call などのサブルーチンジャンプなども利用不可能となります。
簡単に言えば、相手方プロセス(送信先)に、自身の一部を潜り込ませている状態です。
(メモリ空間などは、相手のメモリ空間になる)

この対策として、CallWndProc が呼び出された場合、共有メモリ空間内にメッセージ情報を保存し、HSP からの命令があった場合に情報を与えればいいと思います。



tds12

リンク

2014/6/12(Thu) 21:08:26|NO.62413

返信、大変遅くなりすみませんでした。

774さん、ありがとうございました。
>>HSPからの戻り値は特に必要無さそうな気がします。
確かにそうですね。CallNextHookExは、hpi側で処理することにしました。

MillkeyStarsさん、ありがとうございます。
>>CallWndProc の呼び出しプロセスは、相手方という事を理解してますか?
>>(メモリ空間などは、相手のメモリ空間になる)
ここの確信を持てずにいました。
本当にありがとうございます。

>>code_call などのサブルーチンジャンプなども利用不可能となります。
というわけで、下のようにSendMessageを使うことにしました。

//HWND hTargetWnd = (HWND)0;//フックしたいウィンドウ //HWND hWnd = (HWND)0;//メッセージの送り先 //LPARAM msglp[4] = {(LPARAM)0,(LPARAM)0,(LPARAM)0,(LPARAM)0};//メッセージ内容 //マルチバイトでコンパイル LRESULT CALLBACK CallWndProc(int nCode,WPARAM wp,LPARAM lp) { if (nCode == HC_ACTION){ if (hTargetWnd == ((CWPSTRUCT*)lp)->hwnd){ if (hWnd != ((CWPSTRUCT*)lp)->hwnd){ msglp[0] = (LPARAM)(((CWPSTRUCT*)lp)->hwnd); msglp[1] = (LPARAM)(((CWPSTRUCT*)lp)->message); msglp[2] = (LPARAM)(((CWPSTRUCT*)lp)->wParam); msglp[3] = (LPARAM)(((CWPSTRUCT*)lp)->lParam); SendMessage(hWnd,msg,0,(LPARAM)msglp);// } } } return CallNextHookEx(hHookWnd,nCode,wp,lp); }
結果としては、
何かのプロセスが終了したり、
ほかの今までのような問題は
起こらなくなりました。
しかしまだ問題があり、
最初に2回ほどメッセージを受け取ってからは
まったくメッセージが取得できずにいます。
またメッセージの内容もおかしいので、
まだ解決には至りませんでした。

>>この対策として、CallWndProc が呼び出された場合、共有メモリ空間内にメッセージ情報を保存し、
>>HSP からの命令があった場合に情報を与えればいいと思います。
これはこれからしたいと思います。

平日は忙しく、今週の土日も忙しい可能性が高いので、
なかなか返せないかもしれません。

ありがとうございました。



tds12

リンク

2014/6/15(Sun) 21:27:57|NO.62445

ありがとうございました。
無事フックに成功しました。

おかしかったというものの一つのは、
試しにメモ帳で試したのですが
何も受け取らないということがありました。

ありとあらゆるウィンドウをフックしてみると
64ビットアプリケーションのフックができないことがわかりました。
32ビットと64ビットのアプリケーションでは仕方ないことだと思うので
この質問は解決とさせていただきますが、あきらめずに続けたいと思います。

ありがとうございました。



ONION software Copyright 1997-2023(c) All rights reserved.