Delphi 中的 COM 方法偏移量

发布于 2024-09-08 01:34:13 字数 296 浏览 13 评论 0原文

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

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

,但我更喜欢使用符号名称。以下显然不起作用:

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

谢谢!

In Delphi, how do I find out the the address of a COM method?
I can hardcode the offsets

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

but I would prefer to use symbolic names. The folllowing obviously does not work:

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

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

简单爱 2024-09-15 01:34:13

您可以使用 vmtoffset 汇编器指令来获取接口方法相对于接口方法表开头的字节偏移量。看一下System.pas_IntfCast的实现,例如:

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

第一个表达式加0;第二个是 8。

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

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

You can use the vmtoffset assembler directive to get the byte offset of an interface method relative to the start of the interface's method table. Take a look at the implementation of _IntfCast in System.pas, for example:

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

The first expression adds 0; the second, 8.

You cannot parameterize those expressions, though. They're compile-time constants, so you cannot choose which method you want at run time. You need to have all possible method names represented in advance.

All you really need to hook is QueryInterface. Once you have that, you can return whatever proxy object you want that can intercept calls to all the other methods.

忘羡 2024-09-15 01:34:13

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

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

I don't think Delphi supports that. Hardcoding the offsets is probably the only thing that will work, since the compiler doesn't count interface methods as symbols whose value can be assigned to a function pointer, the way object methods or standalone functions can.

Why are you trying to do this, BTW?

梦情居士 2024-09-15 01:34:13

您的代码是错误的,因为接口引用不是指向接口方法表的指针,而是指向接口方法表的指针。这就是 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 的符号名称,您最好自己将它们声明为偏移常量

Your code is wrong because an interface reference is not a pointer to an interface method table but a pointer to pointer to an interface method table. That is how Delphi interfaces are implemented on binary level. It is hard to say more and point out to the error in your code because you have not given a code example that can be compiled. Use the following code to convert interface reference to method pointer correctly, the idea was taken from Barry Kelly's demonstration of creating a method pointer from a method reference:

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;

If you prefer symbolic names for MethNo you are better to declare them yourself as offset constants

甜心 2024-09-15 01:34:13

两个附加指令允许汇编代码访问动态和
虚拟方法:VMTOFFSET 和 DMTINDEX。

VMTOFFSET 检索虚拟方法指针的偏移量(以字节为单位)
从开头开始的虚拟方法参数的表条目
虚拟方法表(VMT)。该指令需要完整指定
以方法名作为参数的类名(例如,
TExample.VirtualMethod),或接口名称和接口方法
名称。

DMTINDEX 检索传递的动态方法表索引
动态方法。该指令还需要一个完整指定的类名
以方法名称作为参数,例如,
TExample.DynamicMethod。要调用动态方法,请调用
System.@CallDynaInst 以及包含该值的 (E)SI 寄存器
从 DMTINDEX 获取。

docwiki.embarcadero.com

这里是获取所需方法指针的代码

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

Two additional directives allow assembly code to access dynamic and
virtual methods: VMTOFFSET and DMTINDEX.

VMTOFFSET retrieves the offset in bytes of the virtual method pointer
table entry of the virtual method argument from the beginning of the
virtual method table (VMT). This directive needs a fully specified
class name with a method name as a parameter (for example,
TExample.VirtualMethod), or an interface name and an interface method
name.

DMTINDEX retrieves the dynamic method table index of the passed
dynamic method. This directive also needs a fully specified class name
with a method name as a parameter, for example,
TExample.DynamicMethod. To invoke the dynamic method, call
System.@CallDynaInst with the (E)SI register containing the value
obtained from DMTINDEX.

docwiki.embarcadero.com

Here the code to get the needed method pointer

function GetMethodPointer(const IntRef: IInterface): Pointer; assembler;
asm
  mov eax, [IntRef] 
  add eax, vmtoffset ISomeInterface.MemberMethod
  mov eax, [eax]
end;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文