人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

こんにちは教えてください。
MessageBoxをフックするプログラムについて教えてください。以下はネットから探したサンプルの抜粋です。
PROCとは何でしょうか?また、=::はどんなものなのでしょうか?

教えてください。

PROC pfnOrig;
pfnOrig = ::GetProcAddress(
GetModuleHandleA("user32.dll"), "MessageBoxA");


●質問者: mai_mai_mail
●カテゴリ:コンピュータ インターネット
○ 状態 :終了
└ 回答数 : 2/2件

▽最新の回答へ

1 ● a-kuma3
●100ポイント

PROCとは何でしょうか?

http://msdn.microsoft.com/ja-jp/library/cc429133.aspx
↑では FARPROC となっていますが、GetProcAddress は関数のポインタを返します。
PROC は、こんな感じの型になります。

int (WINAPI * PROC) ()

windows.h とかを include していれば、どんな型かを気にする必要はありません。

また、=::はどんなものなのでしょうか?

= と :: に分けて考えます。

= は普通の代入で、GetProcAddress 関数の戻り値を、変数 pfnOrig に代入しているだけです。

:: は、GetProcAddress を修飾しています。
::GetProcAddress で、「無名の名前空間に属している GetProcAddress だ」ということを表します。

ネットで探したサンプルでは、何かの名前空間に属しているようなコードになっているんじゃないでしょうか。


mai_mai_mailさんのコメント
すぐに回答頂きありがとうございます。親切な回答でよくわかりました。

2 ● cx20
●100ポイント ベストアンサー
PROC pfnOrig;

PROC は関数ポインタ型を表します。
宣言は WinDef.h にありますが「戻り値が『int』で引数が『無い』関数」の型を表します。
(Visual Studio であれば「PROC」をマウス右クリックし「宣言に移動」を選択すると表示できます。)

typedef int (WINAPI *PROC)();

関数ポインタとは、関数へのポインタを代入できる変数のことです。
以下は関数ポインタのサンプルコードです。

// File : FuncPtrTest.c
#include <stdio.h>

int func()
{
 printf( "Hello, World!\n" );
 return 0;
}

int main( int argc, char* argv[] )
{
 int (*pfunc)() = func; // 「pfunc」変数(関数ポインタ)に「func」関数を代入。
 
 pfunc(); // 「pfunc」変数(関数ポインタ)により「func」を呼び出すことが可能。
 
 return 0;
}

ただ、関数ポインタの宣言として「int (*pfunc)()」を記述するのは、分かりづらい為、typedef で以下のように型宣言することが多いです。

// File : FuncPtrTest2.c
#include <stdio.h>

int func()
{
 printf( "Hello, World!\n" );
 return 0;
}

typedef int (*FUNC)(); // 「int (*)()」の型を「FUNC」として型宣言する。

int main( int argc, char* argv[] )
{
 //int (*pfunc)() = func;
 FUNC pfunc = func; // 「pfunc」変数(FUNC 型)に「func」関数を代入。
 
 pfunc(); // 「pfunc」変数(関数ポインタ)により「func」を呼び出すことが可能。
 
 return 0;
}

PROC 型は、上記コードの「FUNC」型(戻り値が『int』で引数が『無い』関数)に相当します。
MessageBox 関数は、実際には「戻り値が『int』で『4つの引数』を持つ」関数ですので、
呼出し時に適宜、正しい型に変換してあげる必要があります。

また、「::」は、スコープ解決演算子( :: )を表します。
MFC 等のクラスライブラリ等を使用していると、Win32 API と同名のメンバ関数が存在したりする為、意図的に Win32 API 等のグローバルな API を呼び出す場合に「::」を使用することがあります。
今回のコードであれば「::」は無くても動作するかと思います。

<参考情報>
■ Windows API [ 0からのゲームプログラミング ]
http://www.plustarnet.com/aspil/Programming/api00.htm


なお、ネットで探されたサンプルは、

■ Windows API Hooking Tutorial
http://ruffnex.oc.to/kenji/text/api_hook/
http://ruffnex.oc.to/kenji/text/api_hook/ex2.cpp

のコードかと思いますが、一部、誤りがある(UNICODE ビルドに対応していない)ので、修正が必要そうです。

// フックする関数のプロトタイプを定義
typedef int (WINAPI *PFNMESSAGEBOXA)(HWND, LPCSTR, LPCSTR, UINT); // PCSTR → LPCSTR
typedef int (WINAPI *PFNMESSAGEBOXW)(HWND, LPCWSTR, LPCWSTR, UINT); // PCSTR → LPCWSTR

int WINAPI Hook_MessageBoxA(
 HWND hWnd, 
 LPCSTR pszText, /* PCSTR → LPCSTR */
 LPCSTR pszCaption, /* PCSTR → LPCSTR */
 UINT uType)
{
 // オリジナルMessageBoxAを呼び出す
 PROC pfnOrig = GetProcAddress(
 GetModuleHandleA("user32.dll"), "MessageBoxA");
 int nResult = ((PFNMESSAGEBOXA) pfnOrig)
 (hWnd, pszText, "I am Hook_MessageBoxA", uType); // _T() は不要
 return nResult;
}

int WINAPI Hook_MessageBoxW(
 HWND hWnd, 
 LPCWSTR pszText, /* PCSTR → LPCWSTR */
 LPCWSTR pszCaption, /* PCSTR → LPCWSTR */
 UINT uType)
{
 // オリジナルMessageBoxWを呼び出す
 PROC pfnOrig = GetProcAddress(
 GetModuleHandleA("user32.dll"), "MessageBoxW");
 int nResult = ((PFNMESSAGEBOXW) pfnOrig) // PFNMESSAGEBOXA → PFNMESSAGEBOXW
 (hWnd, pszText, L"I am Hook_MessageBoxW", uType); // _T("") → L"" に変更
 return nResult;
}

mai_mai_mailさんのコメント
a-kuma3さんの回答で満足していたのですが、期待を超えた回答をcx20さんからいただきました。ありがとうございます。unicodeビルドに対応していないところはどうなおしていいのかわからずマルチバイトでコンパイルしていましたが、正しくunicodeで出来るようになり他のAPIのフックも正しく動くのではないかと期待しています。本当にありがとうございました。
関連質問

●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ