5

I'm reversing an old DirectDraw game that uses DirectX 7.

I have a LPDIRECTDRAWSURFACE7 g_lpDDSBack and g_lpDDSBack->BltFast is being called but this is how it is decompiled in HexRays:

(*(int (__stdcall **)(struct IDirectDrawSurface7Vtbl *, int, int, LPDIRECTDRAWSURFACE7, RECT *, MACRO_DDBLTFAST))((int (__stdcall **)(_DWORD, _DWORD, _DWORD, _DWORD, _DWORD, _DWORD))g_lpDDSBack->QueryInterface + 7))(
                                      g_lpDDSBack,
                                      x,
                                      y,
                                      pgf2->lpDDSrcSurface,
                                      &pgf2->rect,
                                      DDBLTFAST_SRCCOLORKEY);

For reference, here is the interface:

DECLARE_INTERFACE_( IDirectDrawSurface7, IUnknown )
{
    /*** IUnknown methods ***/
    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE; // 0
    STDMETHOD_(ULONG,AddRef) (THIS)  PURE; // 1
    STDMETHOD_(ULONG,Release) (THIS) PURE; // 2
    /*** IDirectDrawSurface methods ***/
    STDMETHOD(AddAttachedSurface)(THIS_ LPDIRECTDRAWSURFACE7) PURE; // 3
    STDMETHOD(AddOverlayDirtyRect)(THIS_ LPRECT) PURE; // 4
    STDMETHOD(Blt)(THIS_ LPRECT,LPDIRECTDRAWSURFACE7, LPRECT,DWORD, LPDDBLTFX) PURE; // 5
    STDMETHOD(BltBatch)(THIS_ LPDDBLTBATCH, DWORD, DWORD ) PURE; // 6
    STDMETHOD(BltFast)(THIS_ DWORD,DWORD,LPDIRECTDRAWSURFACE7, LPRECT,DWORD) PURE; // 7
    // etc ...

So from the HexRays code g_lpDDSBack->QueryInterface + 7, we can see it's calling g_lpDDSBack->BltFast. But why doesn't HexRays directly call BltFast?

user16729
  • 51
  • 2

2 Answers2

2

HexRays doesn't call it because it doesn't know what is the value of g_lpDDSBack->QueryInterface in the common case.

Generally speaking you can define a structure as a QueryInterface type, where members of this structure are named according to the related function names and than you'll see the call as g_lpDDSBack->QueryInterface->BltFast .

w s
  • 8,458
  • 1
  • 24
  • 40
0

It turned out to be a bug in IDA pro. I can't seem to edit my original question so first, I want to point out an error I made in the original question.


When g_lpDDSBack is defined as struct IDirectDrawSurface7Vtbl *g_lpDDSBack;, then this was the output HexRays was showing:

(*(int (__stdcall **)(struct IDirectDrawSurface7Vtbl *, int, int, LPDIRECTDRAWSURFACE7, RECT *, MACRO_DDBLTFAST))((int (__stdcall **)(_DWORD, _DWORD, _DWORD, _DWORD, _DWORD, _DWORD))g_lpDDSBack->QueryInterface + 7))(
                                      g_lpDDSBack,
                                      x,
                                      y,
                                      pgf2->lpDDSrcSurface,
                                      &pgf2->rect,
                                      DDBLTFAST_SRCCOLORKEY);

When g_lpDDSBack is defined as LPDIRECTDRAWSURFACE7 g_lpDDSBack;, then this was the output HexRays was showing:

(*((int (__stdcall **)(int, int, int, _DWORD, int, signed int))g_lpDDSBack->lpVtbl + 7))(
                       g_lpDDSBack,
                       x,
                       y,
                       pgf2->lpDDSrcSurface,
                       &pgf2->rect,
                       DDBLTFAST_SRCCOLORKEY);

Alright, now here are the instructions to fixing the bug (g_lpDDSBack is defined as LPDIRECTDRAWSURFACE7 g_lpDDSBack;):

  1. Select lpVtbl in g_lpDDSBack->lpVtbl, press y and then copy the contents of the textbox to a notepad. In this case, the contents were struct IDirectDrawSurface7::IDirectDrawSurface7Vtbl *lpVtbl.
  2. Change the type to int lpVtbl and press OK
  3. Press y again on lpVtbl and change the type back to its original type stored in notepad. In this case, it is struct IDirectDrawSurface7::IDirectDrawSurface7Vtbl *lpVtbl.

After doing this, this is how it looks like in HexRays (you might have to press F5 first):

g_lpDDSBack->lpVtbl->BltFast(g_lpDDSBack,
                                      x,
                                      y,
                                      pgf2->lpDDSrcSurface,
                                      &pgf2->rect,
                                      DDBLTFAST_SRCCOLORKEY);