9

Delphiで、COMメソッドのアドレスを確認するにはどうすればよいですか?オフセットをハードコーディングできます

//0 is the offset of the QueryInterface method
p := TPonterArray(pointer(SomeInterface)^)[0];

しかし、私は象徴的な名前を使用したいと思います。以下は明らかに機能しません:

var M : TMethod;
...
M := TMethod(SomeInterface.QueryInterface);

ありがとう!

4

4 に答える 4

6

vmtoffsetアセンブラー ディレクティブを使用して、インターフェイスのメソッド テーブルの先頭を基準としたインターフェイス メソッドのバイト オフセットを取得できます。たとえば_IntfCastSystem.pasの実装を見てみましょう。

call dword ptr [eax] + vmtoffset IInterface.QueryInterface
...
call dword ptr [eax] + vmtoffset IInterface._Release

最初の式は 0 を加算します。2番目、8。

ただし、これらの式をパラメーター化することはできません。これらはコンパイル時の定数であるため、実行時に必要なメソッドを選択することはできません。可能なすべてのメソッド名を前もって表現しておく必要があります。

本当にフックする必要があるのQueryInterface. それができたら、他のすべてのメソッドへの呼び出しを傍受できる、必要なプロキシ オブジェクトを返すことができます。

于 2010-07-02T05:07:12.343 に答える
3

Delphi はそれをサポートしていないと思います。オブジェクト メソッドやスタンドアロン関数とは異なり、コンパイラは関数ポインターに値を割り当てることができるシンボルとしてインターフェイス メソッドをカウントしないため、おそらくオフセットをハードコーディングすることが唯一の方法です。

ところで、なぜあなたはこれをやろうとしているのですか?

于 2010-07-01T17:34:11.090 に答える
2

インターフェイス参照はインターフェイス メソッド テーブルへのポインターではなく、インターフェイス メソッド テーブルへのポインターへのポインターであるため、コードが間違っています。これが、Delphi インターフェイスがバイナリ レベルで実装される方法です。コンパイル可能なコード例を示していないため、コードのエラーを指摘することは困難です。次のコードを使用して、インターフェイス参照をメソッド ポインターに正しく変換します。アイデアは、メソッド参照からメソッド ポインターを作成する Barry Kelly のデモンストレーションから取られました。

procedure IntRefToMethPtr(const IntRef; var MethPtr; MethNo: Integer);
type
  TVtable = array[0..999] of Pointer;
  PVtable = ^TVtable;
  PPVtable = ^PVtable;
begin
  // QI=0, AddRef=1, Release=2, etc
  TMethod(MethPtr).Code := PPVtable(IntRef)^^[MethNo];
  TMethod(MethPtr).Data := Pointer(IntRef);
end;

MethNo の記号名を好む場合は、それらをオフセット定数として自分で宣言することをお勧めします。

于 2010-07-04T15:59:20.627 に答える