Delphi中的COM方法

Delphi中的COM方法,delphi,com,vtable,Delphi,Com,Vtable,在Delphi中,如何查找COM方法的地址? 我可以硬编码偏移量 //0 is the offset of the QueryInterface method p := TPonterArray(pointer(SomeInterface)^)[0]; 但我更喜欢用象征性的名字。以下显然不起作用: var M : TMethod; ... M := TMethod(SomeInterface.QueryInterface); 谢谢 我认为德尔福不支持这一点。硬编码偏移量可能是唯一可行的方法,

在Delphi中,如何查找COM方法的地址? 我可以硬编码偏移量

//0 is the offset of the QueryInterface method
p := TPonterArray(pointer(SomeInterface)^)[0];
但我更喜欢用象征性的名字。以下显然不起作用:

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

谢谢

我认为德尔福不支持这一点。硬编码偏移量可能是唯一可行的方法,因为编译器不会像对象方法或独立函数那样,将接口方法计算为其值可以分配给函数指针的符号


顺便说一句,为什么要这样做?

您可以使用
vmtoffset
汇编指令获取接口方法相对于接口方法表开头的字节偏移量。查看System.pas中
\u IntfCast
的实现,例如:

call dword ptr [eax] + vmtoffset IInterface.QueryInterface
...
call dword ptr [eax] + vmtoffset IInterface._Release
第一个表达式加0;第二,8

但是,您不能参数化这些表达式。它们是编译时常量,因此您无法在运行时选择所需的方法。您需要提前表示所有可能的方法名称


真正需要钩住的是
QueryInterface
。一旦你有了它,你就可以返回你想要的任何代理对象来拦截对所有其他方法的调用。

你的代码是错误的,因为接口引用不是指向接口方法表的指针,而是指向接口方法表的指针。这就是如何在二进制级别实现Delphi接口。很难说得更多,也很难指出代码中的错误,因为您没有给出可以编译的代码示例。使用以下代码将接口引用正确转换为方法指针,其思想来源于:

如果您更喜欢MethNo的符号名,最好自己将它们声明为偏移量常量

另外两条指令允许汇编代码访问动态和 虚拟方法:VMTOFFSET和DMTINDEX

VMTOFFSET检索虚拟方法指针的偏移量(以字节为单位) 虚拟方法参数的表项(从 虚拟方法表(VMT)。此指令需要一个完全指定的 以方法名作为参数的类名(例如, 或接口名称和接口方法 名字

DMTINDEX检索所传递数据的动态方法表索引 动态方法。此指令还需要完全指定的类名 例如,使用方法名称作为参数, TExample.DynamicMethod。要调用动态方法,请调用 系统。@calldyninst,带有包含该值的(E)SI寄存器 从DMTINDEX获得

下面是获取所需方法指针的代码

function GetMethodPointer(const IntRef: IInterface): Pointer; assembler;
asm
  mov eax, [IntRef] 
  add eax, vmtoffset ISomeInterface.MemberMethod
  mov eax, [eax]
end;

Delphi删除了很多血淋淋的COM细节,我认为你自己想做的太多了。你想达到什么目标?创建自己的COM服务器还是使用现有的COM服务器?是否希望接口中方法的数值偏移量(例如,IUnknown.QueryInterface为0),实现该接口方法的类中方法的地址(例如,@TInterfacedObject.QueryInterface),或者生成的存根代码的地址,用于将接口调用链接到相应的对象方法?后者存储在类的接口表中。@The_-Fox:note:我正在使用Win32Hook.pas拦截对外部COM对象的调用@Rob Kennedy:没有TInterfacedObject类-我只有一个由外部dll实现的接口。我正在使用Win32Hook.pas拦截对外部COM对象的调用-只是我的OutlookSpy()的一个日志功能。顺便说一句,Delphi编译器显然知道方法偏移,我只是想找到一种方法来做同样的事情,而不是使用硬编码的偏移量。是的,编译器知道这一点,但据我所知,没有办法直接得到它。这看起来很有希望。。。今天晚些时候我会试试,然后公布结果。谢谢不,Delphi中的接口变量是指向v表的指针。不,Dmitry,Serg是正确的。接口变量不能只是指向vtable的指针。与非接口类一样,该类的所有实例共享一个vtable。考虑C++,在接口和普通类之间没有区别。对象指针不仅仅是vtable指针,所以接口指针也不是。@Rob Kennedy:谢谢,这个问题迫使我写了一篇关于Delphi接口的博客文章:
function GetMethodPointer(const IntRef: IInterface): Pointer; assembler;
asm
  mov eax, [IntRef] 
  add eax, vmtoffset ISomeInterface.MemberMethod
  mov eax, [eax]
end;