我该如何迭代/访问COM coclass的vtable,以实现其公开接口的方法?
我需要访问存储其接口所有公开方法地址的vtable部分。
例如,Math是COM对象,其公开接口为“操作”,而“Sum”是此接口的方法,我如何获取“Sum”的地址?
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;
}
很抱歉用问题来回答,但我必须问“从哪里开始?”
如果你的意思是如何通过COM客户端迭代vtable,我认为你不能。在客户端上,你只有一个代理,它知道如何与COM服务器通信(可能跨进程或跨应用程序)。你可以探测该代理的vtable,但它永远无法告诉你COM服务器内部函数的地址。
当然,如果服务器实际上在不同的进程中运行,函数的地址对你可能没有什么用处。即使服务器在同一进程中,但在不同的公寓中,获取函数地址可能是危险的:你可以直接调用函数,规避COM的拦截,并打破服务器类对调用线程等方面的假设。
我想迭代vtable只是达到目的的一种手段...?也许你可以发布你实际想要做什么,我认为COM可能有一种方法可以实现。