I wonβt ask why you are doing this, but maybe this can help ... Every COM object should implement at least the IUnknown interface. Therefore, the first four bytes of an instance of a COM object are a pointer to an IUnknown object. The first four bytes of the IUnknown object (and any other object with virtual functions) is a pointer to vtbl.
(There is no error checking in this example, so please do not split the hair on this topic.)
I used an instance of IReferenceClock for demonstration.
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; }
user472155
source share