首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何迭代COM coclass的vtable?

如何迭代COM coclass的vtable?
EN

Stack Overflow用户
提问于 2010-03-11 02:57:39
回答 2查看 833关注 0票数 5

我如何迭代/访问COM coclass的vtable,它将实现其公开接口的方法?

我需要访问vtable中存储其接口的公开方法的所有地址的部分。

例如Math是COM对象,它公开的接口是Operations,Sum是这个接口的方法,如何获取Sum的地址?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-12-07 17:46:33

我不会问你为什么要这样做,但这可能会有所帮助……每个COM对象必须至少实现IUnknown接口。因此,COM对象实例的前四个字节是指向IUnknown对象的指针。IUnknown对象(以及任何其他具有虚拟函数的对象)的前四个字节是指向vtbl的指针。

(在此示例中没有错误检查,因此请不要在该主题上进行拆分。)

我使用了一个IReferenceClock实例进行演示。

代码语言:javascript
复制
int main()
{

    CoInitialize( NULL );

    IReferenceClock* pRefClock;
    HRESULT hr = CoCreateInstance( CLSID_SystemClock, NULL, CLSCTX_INPROC_SERVER, IID_IReferenceClock, (void**)&pRefClock );

    DWORD* pIUnknownAddress = (DWORD*)pRefClock;
    DWORD* pVTBLaddress = (DWORD*)*pIUnknownAddress;

    // for example, the next interface could be accessed like this
    DWORD* pNextInterfaceAddress = ( (DWORD*)pRefClock ) + 1;
    DWORD* pNextVTBLaddress = (DWORD*)*pNextInterfaceAddress;
    // and you would access virtual functions in the same way as QueryInterface, AddRef and Release below in this example

    HRESULT (__stdcall *pQueryInterfaceFunction)(void*, REFIID, void**);
    ULONG (__stdcall *pAddRef)( void* );
    ULONG (__stdcall *pRelease)( void* );

    // IUnknown looks like this:
    // 
    // virtual HRESULT QueryInterface( REFIID riid, void** ppvObject);
    // virtual ULONG AddRef( void );
    // virtual ULONG Release( void );
    //
    // So, the first function in vtbl is QueryInterface, the second is AddRef...

    pQueryInterfaceFunction = (HRESULT (__stdcall*)(void*, REFIID, void**))*pVTBLaddress;
    pAddRef = (ULONG (__stdcall *)( void* ))*( pVTBLaddress + 1 );
    pRelease = (ULONG (__stdcall *)( void* ))*( pVTBLaddress + 2 );

    // Note: extra void* is actually this pointer.. see below that we pass pRefClock to every call

    IUnknown* pUnknown;
    UINT nRefCount;

    hr = pQueryInterfaceFunction( pRefClock, IID_IUnknown, (void**)&pUnknown );

    if( SUCCEEDED( hr ) )
    {
        nRefCount = pUnknown->Release();
        ATLTRACE( TEXT( "nRefCount = %d\n" ), nRefCount );
    }

    nRefCount = pAddRef( pRefClock );
    ATLTRACE( TEXT( "nRefCount after AddRef() call = %d\n" ), nRefCount );

    nRefCount = pRelease( pRefClock );
    ATLTRACE( TEXT( "nRefCount after Release() call = %d\n" ), nRefCount );

    nRefCount = pRefClock->Release();

    CoUninitialize();

    return 0;
}
票数 7
EN

Stack Overflow用户

发布于 2010-07-22 21:04:06

很抱歉用一个问题来回答,但我必须问“从哪里来?”

如果您的意思是,如何从COM客户端遍历vtable,我认为您不能。在客户端,您所拥有的只是一个知道如何与COM服务器通信(可能是跨单元或跨进程)的代理。您可能会探测该代理的vtable,但它永远不会告诉您COM服务器内部函数的地址。

当然,如果服务器实际上在不同的进程中运行,函数的地址对您可能用处不大。即使服务器在相同的进程中,但在不同的单元中,获取函数地址可能是危险的:您可以直接调用函数,绕过COM的拦截,并打破服务器类关于调用线程的假设,等等。

我猜迭代vtable是一种达到目的的手段...?也许发布你真正想要做的事情,我想COM可能有办法做到这一点。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2419674

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档