Holy cow, I wrote a book!
Yesterday we learned about the layout of COM objects and I
hinted at "adjustor thunks".
If you find yourself debugging in disassembly,
you'll sometimes find strange little functions called
Let's take another look at the object we laid out last time:
class CSample : public IPersist, public IServiceProvider
// *** IUnknown ***
STDMETHODIMP QueryInterface(REFIID riid, void** ppv);
// *** IPersist ***
STDMETHODIMP GetClassID(CLSID* pClassID);
// *** IQueryService ***
STDMETHODIMP QueryService(REFGUID guidService,
REFIID riid, void** ppv);
In the diagram, p is the pointer returned when the IPersist interface
is needed, and q is the pointer for the IQueryService interface.
Now, there is only one QueryInterface method, but there are two entries,
one for each vtable. Remember that each function in a vtable receives
the corresponding interface pointer as its "this" parameter. That's
just fine for QueryInterface (1); its interface pointer is the
same as the object's interface pointer. But that's bad news for
QueryInterface (2), since its interface pointer is q, not p.
This is where the adjustor thunks come in.
The entry for QueryInterface (2) is a stub function that
changes q to p, and then lets QueryInterface (1) do the
rest of the work. This stub function is the adjustor thunk.
sub DWORD PTR [esp+4], 4 ; this -= sizeof(lpVtbl)
The adjustor thunk takes the "this" pointer and subtracts 4,
converting q into p, then it jumps to the QueryInterface (1)
function to do the real work.